From 648948279e992b7bd6328413f362d5fe1017a983 Mon Sep 17 00:00:00 2001 From: Auto Commit Date: Thu, 31 Aug 2023 16:26:53 -0400 Subject: [PATCH] Addition of 26.452-g30, 16.3 --- Makefile | 92 + Workspace_msvc/Workspace_msvc.sln | 39 + Workspace_msvc/common.vcxproj | 250 + Workspace_msvc/evs_dec.vcxproj | 294 + Workspace_msvc/evs_enc.vcxproj | 321 + Workspace_msvc/lib_fx.vcxproj | 126 + basic_math/log2.c | 211 + basic_math/log2.h | 40 + basic_math/math_32.h | 10 + basic_math/math_op.c | 359 + basic_math/math_op.h | 48 + basic_math/oper_32b.c | 381 + basic_math/oper_32b.h | 18 + basic_math/rom_basic_math.c | 91 + basic_math/rom_basic_math.h | 26 + basic_op/README.md | 101 + basic_op/basop.rme | 120 + basic_op/basop32.c | 2429 ++ basic_op/basop32.h | 130 + basic_op/complex_basop.c | 457 + basic_op/complex_basop.h | 77 + basic_op/control.c | 250 + basic_op/control.h | 332 + basic_op/count.c | 772 + basic_op/count.h | 542 + basic_op/enh1632.c | 664 + basic_op/enh1632.h | 545 + basic_op/enh32.c | 215 + basic_op/enh32.h | 38 + basic_op/enh40.c | 1045 + basic_op/enh40.h | 839 + basic_op/enh64.c | 1665 ++ basic_op/enh64.h | 73 + basic_op/enhUL32.c | 409 + basic_op/enhUL32.h | 76 + basic_op/move.h | 95 + basic_op/patch.h | 51 + basic_op/stl.h | 69 + basic_op/typedef.h | 102 + basic_op/typedefs.h | 218 + lib_com/ACcontextMapping.c | 81 + lib_com/ari.c | 57 + lib_com/ari_hm.c | 292 + lib_com/arith_coder.c | 471 + lib_com/basop_mpy.h | 10 + lib_com/basop_util.c | 2284 ++ lib_com/basop_util.h | 816 + lib_com/bitalloc_fx.c | 1029 + lib_com/bitallocsum_fx.c | 63 + lib_com/bits_alloc.c | 384 + lib_com/bitstream_fx.c | 2589 ++ lib_com/cb_shape_fx.c | 134 + lib_com/cldfb.c | 1661 ++ lib_com/cng_exc_fx.c | 890 + lib_com/cnst_fx.h | 2373 ++ lib_com/codec_tcx_common.c | 288 + lib_com/core_com_config_fx.c | 471 + lib_com/deemph_fx.c | 136 + lib_com/delay_comp.c | 43 + lib_com/disclaimer.c | 19 + lib_com/disclaimer.h | 15 + lib_com/dlpc_bfi.c | 55 + lib_com/edct_fx.c | 424 + lib_com/enhancer_fx.c | 679 + lib_com/enr_1_az_fx.c | 78 + lib_com/env_adj_fx.c | 158 + lib_com/env_stab_fx.c | 188 + lib_com/env_stab_trans_fx.c | 161 + lib_com/est_tilt_fx.c | 269 + lib_com/fd_cng_com.c | 1826 ++ lib_com/fft.c | 2475 ++ lib_com/fft_fx.c | 2832 +++ lib_com/fft_rel_fx.c | 433 + lib_com/fft_rel_sas_fx.c | 456 + lib_com/fill_spectrum_fx.c | 278 + lib_com/findpulse_fx.c | 117 + lib_com/fine_gain_bits_fx.c | 107 + lib_com/frame_ener_fx.c | 196 + lib_com/g192.c | 254 + lib_com/g192.h | 64 + lib_com/gain_inov.c | 54 + lib_com/get_gain.c | 97 + lib_com/gs_bitallocation_fx.c | 481 + lib_com/gs_gains_fx.c | 673 + lib_com/gs_inact_switching_fx.c | 153 + lib_com/gs_noisefill_fx.c | 922 + lib_com/gs_preech_fx.c | 139 + lib_com/guided_plc_util.c | 324 + lib_com/hp50.c | 250 + lib_com/hq2_bit_alloc_fx.c | 914 + lib_com/hq2_core_com_fx.c | 770 + lib_com/hq2_noise_inject_fx.c | 618 + lib_com/hq_bit_allocation_fx.c | 217 + lib_com/hq_conf_fx.c | 279 + lib_com/hq_tools_fx.c | 2342 ++ lib_com/hvq_pvq_bitalloc_fx.c | 191 + lib_com/igf_base.c | 936 + lib_com/index_pvq_opt_fx.c | 1187 + lib_com/int_lsp_fx.c | 173 + lib_com/interleave_spectrum_fx.c | 189 + lib_com/interpol_fx.c | 77 + lib_com/isf_dec_amr_wb_fx.c | 329 + lib_com/lag_wind.c | 130 + lib_com/lerp.c | 179 + lib_com/limit_t0_fx.c | 259 + lib_com/logqnorm_fx.c | 195 + lib_com/longarith.c | 47 + lib_com/low_rate_band_att_fx.c | 219 + lib_com/lpc_tools_fx.c | 1009 + lib_com/lsf_dec_bfi_fx.c | 301 + lib_com/lsf_msvq_ma.c | 159 + lib_com/lsf_tools_fx.c | 3426 +++ lib_com/lsp_conv_poly_fx.c | 858 + lib_com/mime.h | 423 + lib_com/modif_fs_fx.c | 1297 + lib_com/mslvq_com_fx.c | 850 + lib_com/nelp_fx.c | 218 + lib_com/options.h | 27 + lib_com/parameter_bitmaping.c | 276 + lib_com/phase_dispersion.c | 177 + lib_com/ppp_fx.c | 115 + lib_com/pred_lt4_fx.c | 166 + lib_com/preemph_fx.c | 136 + lib_com/prot_fx.h | 11084 +++++++++ lib_com/pvq_com_fx.c | 753 + lib_com/range_com_fx.c | 62 + lib_com/re8_ppv_fx.c | 193 + lib_com/re8_util_fx.c | 387 + lib_com/recovernorm_fx.c | 62 + lib_com/reordvct_fx.c | 58 + lib_com/residu_fx.c | 210 + lib_com/rom_basop_util.c | 991 + lib_com/rom_basop_util.h | 81 + lib_com/rom_com_fx.c | 21195 +++++++++++++++++ lib_com/rom_com_fx.h | 1240 + lib_com/scale_mem_fx.c | 346 + lib_com/stab_est_fx.c | 245 + lib_com/stat_com.h | 676 + lib_com/stat_noise_uv_mod_fx.c | 420 + lib_com/swb_bwe_com_fx.c | 2803 +++ lib_com/swb_bwe_com_hr_fx.c | 262 + lib_com/swb_bwe_com_lr_fx.c | 3352 +++ lib_com/swb_tbe_com_fx.c | 3612 +++ lib_com/syn_12k8_fx.c | 62 + lib_com/syn_filt_fx.c | 275 + lib_com/tcq_position_arith_fx.c | 2566 ++ lib_com/tcx_ltp.c | 732 + lib_com/tcx_mdct.c | 219 + lib_com/tcx_mdct_window.c | 208 + lib_com/tcx_utils.c | 1593 ++ lib_com/tec_com.c | 1511 ++ lib_com/tns_base.c | 980 + lib_com/tools_fx.c | 2630 ++ lib_com/trans_direct_fx.c | 204 + lib_com/trans_inv_fx.c | 1134 + lib_com/vlpc_2st_com.c | 61 + lib_com/weight_a_fx.c | 208 + lib_com/weight_fx.c | 362 + lib_com/wi_fx.c | 5354 +++++ lib_com/window.c | 68 + lib_com/window_ola_fx.c | 778 + lib_com/wtda_fx.c | 441 + lib_dec/ACcontextMapping_dec.c | 326 + lib_dec/EvsRXlib.c | 569 + lib_dec/EvsRXlib.h | 85 + lib_dec/FEC_HQ_core_fx.c | 1590 ++ lib_dec/FEC_HQ_phase_ecu_fx.c | 2800 +++ lib_dec/FEC_adapt_codebook_fx.c | 536 + lib_dec/FEC_clas_estim_fx.c | 937 + lib_dec/FEC_fx.c | 803 + lib_dec/FEC_lsf_estim_fx.c | 59 + lib_dec/FEC_pitch_estim_fx.c | 104 + lib_dec/FEC_scale_syn_fx.c | 616 + lib_dec/LD_music_post_filter_fx.c | 914 + lib_dec/TonalComponentDetection.c | 1013 + lib_dec/acelp_core_dec_fx.c | 1247 + lib_dec/acelp_core_switch_dec_fx.c | 677 + lib_dec/amr_wb_dec_fx.c | 1135 + lib_dec/ari_dec.c | 533 + lib_dec/ari_hm_dec.c | 152 + lib_dec/arith_coder_dec.c | 232 + lib_dec/avq_dec_fx.c | 241 + lib_dec/basop_util_jbm.c | 38 + lib_dec/basop_util_jbm.h | 18 + lib_dec/bass_psfilter_fx.c | 868 + lib_dec/cng_dec_fx.c | 982 + lib_dec/core_dec_init.c | 786 + lib_dec/core_dec_reconf.c | 169 + lib_dec/core_dec_switch.c | 227 + lib_dec/core_switching_dec_fx.c | 1181 + lib_dec/d_gain2p.c | 406 + lib_dec/dec2t32_fx.c | 125 + lib_dec/dec4t64_fx.c | 800 + lib_dec/dec_LPD.c | 1020 + lib_dec/dec_ace.c | 772 + lib_dec/dec_acelp.c | 372 + lib_dec/dec_acelp_tcx_main.c | 536 + lib_dec/dec_amr_wb_fx.c | 139 + lib_dec/dec_gen_voic_fx.c | 443 + lib_dec/dec_higher_acelp_fx.c | 266 + lib_dec/dec_nelp_fx.c | 92 + lib_dec/dec_pit_exc_fx.c | 260 + lib_dec/dec_post.c | 1540 ++ lib_dec/dec_ppp_fx.c | 106 + lib_dec/dec_prm.c | 1199 + lib_dec/dec_tcx.c | 2404 ++ lib_dec/dec_tran_fx.c | 230 + lib_dec/dec_uv.c | 89 + lib_dec/decision_matrix_dec_fx.c | 709 + lib_dec/decoder.c | 258 + lib_dec/dlpc_avq.c | 274 + lib_dec/dlpc_stoch.c | 121 + lib_dec/er_dec_acelp.c | 1126 + lib_dec/er_dec_tcx.c | 904 + lib_dec/er_scale_syn.c | 129 + lib_dec/er_sync_exc.c | 542 + lib_dec/er_util.c | 474 + lib_dec/evs_dec_fx.c | 1508 ++ lib_dec/evs_rtp_payload.c | 238 + lib_dec/evs_rtp_payload.h | 173 + lib_dec/fd_cng_dec.c | 2181 ++ lib_dec/gain_dec_fx.c | 1238 + lib_dec/gaus_dec_fx.c | 284 + lib_dec/gs_dec_amr_wb_fx.c | 454 + lib_dec/gs_dec_fx.c | 606 + lib_dec/hdecnrm_fx.c | 405 + lib_dec/hf_synth_fx.c | 1776 ++ lib_dec/hq_classifier_dec_fx.c | 70 + lib_dec/hq_conf_fec_fx.c | 39 + lib_dec/hq_core_dec_fx.c | 460 + lib_dec/hq_env_dec_fx.c | 216 + lib_dec/hq_hr_dec_fx.c | 313 + lib_dec/hq_lr_dec_fx.c | 1332 ++ lib_dec/igf_dec.c | 1735 ++ lib_dec/igf_scf_dec.c | 352 + lib_dec/init_dec_fx.c | 967 + lib_dec/inov_dec_fx.c | 135 + lib_dec/io_dec_fx.c | 497 + lib_dec/jbm_jb4_circularbuffer.c | 422 + lib_dec/jbm_jb4_circularbuffer.h | 52 + lib_dec/jbm_jb4_inputbuffer.c | 355 + lib_dec/jbm_jb4_inputbuffer.h | 50 + lib_dec/jbm_jb4_jmf.c | 274 + lib_dec/jbm_jb4_jmf.h | 42 + lib_dec/jbm_jb4sb.c | 1495 ++ lib_dec/jbm_jb4sb.h | 70 + lib_dec/jbm_pcmdsp_apa.c | 1472 ++ lib_dec/jbm_pcmdsp_apa.h | 93 + lib_dec/jbm_pcmdsp_fifo.c | 213 + lib_dec/jbm_pcmdsp_fifo.h | 44 + lib_dec/jbm_pcmdsp_similarityestimation.c | 202 + lib_dec/jbm_pcmdsp_similarityestimation.h | 114 + lib_dec/jbm_pcmdsp_window.c | 41 + lib_dec/jbm_pcmdsp_window.h | 36 + lib_dec/lead_deindexing_fx.c | 279 + lib_dec/lp_exc_d_fx.c | 104 + lib_dec/lsf_dec_fx.c | 864 + lib_dec/lsf_msvq_ma_dec.c | 294 + lib_dec/nelp_dec_fx.c | 401 + lib_dec/peak_vq_dec_fx.c | 609 + lib_dec/pit_dec.c | 948 + lib_dec/pitch_extr.c | 328 + lib_dec/post_dec.c | 619 + lib_dec/ppp_dec_fx.c | 162 + lib_dec/pvq_core_dec_fx.c | 556 + lib_dec/pvq_decode_fx.c | 104 + lib_dec/range_dec_fx.c | 215 + lib_dec/re8_dec_fx.c | 72 + lib_dec/rom_dec_fx.c | 456 + lib_dec/rom_dec_fx.h | 86 + lib_dec/rst_dec_fx.c | 85 + lib_dec/rtpdump.c | 351 + lib_dec/rtpdump.h | 74 + lib_dec/stat_dec_fx.h | 1114 + lib_dec/stat_noise_uv_dec_fx.c | 84 + lib_dec/swb_bwe_dec_fx.c | 968 + lib_dec/swb_bwe_dec_hr_fx.c | 1488 ++ lib_dec/swb_bwe_dec_lr_fx.c | 357 + lib_dec/swb_tbe_dec_fx.c | 3624 +++ lib_dec/syn_outp_fx.c | 116 + lib_dec/tcq_core_dec_fx.c | 475 + lib_dec/tcx_utils_dec.c | 343 + lib_dec/tns_base_dec.c | 94 + lib_dec/tonalMDCTconcealment.c | 1246 + lib_dec/transition_dec_fx.c | 925 + lib_dec/updt_dec_fx.c | 739 + lib_dec/vlpc_1st_dec.c | 30 + lib_dec/vlpc_2st_dec.c | 59 + lib_dec/voiced_dec_fx.c | 363 + lib_dec/voip_client.c | 372 + lib_dec/waveadjust_fec_dec.c | 1602 ++ lib_enc/ACcontextMapping_enc.c | 713 + lib_enc/FEC_enc_fx.c | 294 + lib_enc/SNR_calc.c | 525 + lib_enc/acelp_core_enc_fx.c | 654 + lib_enc/acelp_core_switch_enc_fx.c | 535 + lib_enc/acelp_enc_util.c | 280 + lib_enc/amr_wb_enc_fx.c | 625 + lib_enc/analy_lp_fx.c | 173 + lib_enc/analy_sp.c | 387 + lib_enc/ari_enc.c | 321 + lib_enc/ari_hm_enc.c | 799 + lib_enc/arith_coder_enc.c | 814 + lib_enc/avq_cod_fx.c | 460 + lib_enc/bass_psfilter_enc.c | 389 + lib_enc/bw_detect_fx.c | 915 + lib_enc/cng_enc_fx.c | 1377 ++ lib_enc/cod2t32_fx.c | 383 + lib_enc/cod4t64_fx.c | 1167 + lib_enc/cod_ace.c | 606 + lib_enc/cod_tcx.c | 2328 ++ lib_enc/cod_uv.c | 88 + lib_enc/comvad_decision.c | 886 + lib_enc/cor_shif_fx.c | 50 + lib_enc/core_enc_2div.c | 342 + lib_enc/core_enc_init.c | 861 + lib_enc/core_enc_ol.c | 1612 ++ lib_enc/core_enc_reconf.c | 277 + lib_enc/core_enc_switch.c | 230 + lib_enc/core_enc_updt.c | 257 + lib_enc/core_switching_enc_fx.c | 512 + lib_enc/corr_xh_fx.c | 65 + lib_enc/decision_matrix_enc_fx.c | 751 + lib_enc/detect_transient_fx.c | 352 + lib_enc/diffcod_fx.c | 142 + lib_enc/dtx_fx.c | 923 + lib_enc/enc_acelp.c | 2049 ++ lib_enc/enc_acelp_tcx_main.c | 114 + lib_enc/enc_acelpx.c | 541 + lib_enc/enc_amr_wb_fx.c | 232 + lib_enc/enc_gain.c | 395 + lib_enc/enc_gen_voic_fx.c | 382 + lib_enc/enc_gen_voic_rf_fx.c | 624 + lib_enc/enc_higher_acelp_fx.c | 456 + lib_enc/enc_nelp_fx.c | 172 + lib_enc/enc_pit_exc_fx.c | 361 + lib_enc/enc_ppp_fx.c | 227 + lib_enc/enc_prm.c | 915 + lib_enc/enc_tran_fx.c | 416 + lib_enc/enc_uv_fx.c | 119 + lib_enc/encoder.c | 282 + lib_enc/energy.c | 457 + lib_enc/eval_pit_contr_fx.c | 413 + lib_enc/evs_enc_fx.c | 804 + lib_enc/ext_sig_ana.c | 485 + lib_enc/fd_cng_enc.c | 1500 ++ lib_enc/find_tar_fx.c | 155 + lib_enc/find_tilt_fx.c | 229 + lib_enc/find_uv.c | 551 + lib_enc/find_wsp_fx.c | 86 + lib_enc/frame_spec_dif_cor_rate.c | 112 + lib_enc/gain_enc_fx.c | 1901 ++ lib_enc/gaus_enc_fx.c | 666 + lib_enc/gp_clip_fx.c | 396 + lib_enc/gs_enc_fx.c | 570 + lib_enc/guided_plc_enc.c | 445 + lib_enc/hf_cod_amrwb_fx.c | 224 + lib_enc/hq_classifier_enc_fx.c | 671 + lib_enc/hq_core_enc_fx.c | 202 + lib_enc/hq_env_enc_fx.c | 597 + lib_enc/hq_hr_enc_fx.c | 235 + lib_enc/hq_lr_enc_fx.c | 1928 ++ lib_enc/hvq_enc_fx.c | 232 + lib_enc/igf_enc.c | 1316 + lib_enc/igf_scf_enc.c | 430 + lib_enc/init_enc_fx.c | 1008 + lib_enc/inov_enc_fx.c | 332 + lib_enc/io_enc_fx.c | 1051 + lib_enc/isf_enc_amr_wb_fx.c | 544 + lib_enc/lead_indexing_fx.c | 196 + lib_enc/long_enr.c | 78 + lib_enc/lp_exc_e_fx.c | 417 + lib_enc/lsf_enc_fx.c | 2350 ++ lib_enc/lsf_msvq_ma_enc.c | 718 + lib_enc/ltd_stable.c | 468 + lib_enc/mdct_classifier_fx.c | 470 + lib_enc/mdct_selector.c | 355 + lib_enc/mslvq_enc_fx.c | 898 + lib_enc/multi_harm_fx.c | 355 + lib_enc/nelp_enc_fx.c | 975 + lib_enc/nois_est_fx.c | 1721 ++ lib_enc/noise_adjust_fx.c | 69 + lib_enc/normalizecoefs_fx.c | 61 + lib_enc/peak_vq_enc_fx.c | 782 + lib_enc/pit_enc_fx.c | 1505 ++ lib_enc/pitch_ol.c | 1551 ++ lib_enc/pitch_ol2_fx.c | 392 + lib_enc/plc_enc_ext.c | 136 + lib_enc/ppp_enc_fx.c | 342 + lib_enc/pre_proc_fx.c | 1281 + lib_enc/pvq_core_enc_fx.c | 633 + lib_enc/pvq_encode_fx.c | 370 + lib_enc/q_gain2p.c | 653 + lib_enc/qlpc_avq.c | 332 + lib_enc/qlpc_stoch.c | 437 + lib_enc/range_enc_fx.c | 297 + lib_enc/re8_cod_fx.c | 53 + lib_enc/reordernorm_fx.c | 57 + lib_enc/rom_enc_fx.c | 696 + lib_enc/rom_enc_fx.h | 120 + lib_enc/rst_enc_fx.c | 69 + lib_enc/scale_enc_fx.c | 273 + lib_enc/set_impulse_fx.c | 348 + lib_enc/setmodeindex.c | 50 + lib_enc/sig_clas.c | 378 + lib_enc/spec_center.c | 311 + lib_enc/spec_flatness.c | 314 + lib_enc/speech_music_classif_fx.c | 2889 +++ lib_enc/stat_enc_fx.h | 1325 ++ lib_enc/stat_noise_uv_enc_fx.c | 103 + lib_enc/subband_fft.c | 323 + lib_enc/swb_bwe_enc_fx.c | 2833 +++ lib_enc/swb_bwe_enc_hr_fx.c | 787 + lib_enc/swb_bwe_enc_lr_fx.c | 1067 + lib_enc/swb_pre_proc_fx.c | 435 + lib_enc/swb_tbe_enc_fx.c | 3678 +++ lib_enc/tcq_core_enc_fx.c | 474 + lib_enc/tcx_ltp_enc.c | 614 + lib_enc/tcx_utils_enc.c | 1930 ++ lib_enc/tfa_enc.c | 104 + lib_enc/tns_base_enc.c | 446 + lib_enc/transient_detection.c | 729 + lib_enc/transition_enc_fx.c | 1200 + lib_enc/update_decision.c | 465 + lib_enc/updt_enc_fx.c | 271 + lib_enc/updt_tar_fx.c | 60 + lib_enc/vad_basop.c | 145 + lib_enc/vad_basop.h | 80 + lib_enc/vad_fx.c | 1553 ++ lib_enc/vad_param_updt_fx.c | 177 + lib_enc/vad_proc.c | 455 + lib_enc/vbr_average_rate_fx.c | 244 + lib_enc/vlpc_1st_cod.c | 137 + lib_enc/vlpc_2st_cod.c | 147 + lib_enc/voiced_enc_fx.c | 1205 + lib_enc/waveadjust_fec_cod.c | 76 + scripts/switchPaths/sw_13k2_512k.bin | 3 + scripts/switchPaths/sw_13k2_to_128k_10fr.bin | 3 + scripts/switchPaths/sw_amrwb.bin | 3 + scripts/switchPaths/sw_amrwb_evs.bin | 3 + scripts/switchPaths/sw_amrwb_evs2.bin | 3 + scripts/switchPaths/sw_highest.bin | 3 + scripts/switchPaths/sw_nb1.bin | 3 + scripts/switchPaths/sw_nb5.bin | 3 + scripts/switchPaths/sw_swb1.bin | 3 + scripts/switchPaths/sw_wb1.bin | 3 + scripts/switchPaths/sw_wb5.bin | 3 + scripts/switchPaths/swb_high1.bin | 3 + scripts/switchPaths/swb_low1.bin | 3 + scripts/switchPaths/wb_high1.bin | 3 + scripts/switchPaths/wb_low1.bin | 3 + 451 files changed, 293136 insertions(+) create mode 100644 Makefile create mode 100644 Workspace_msvc/Workspace_msvc.sln create mode 100644 Workspace_msvc/common.vcxproj create mode 100644 Workspace_msvc/evs_dec.vcxproj create mode 100644 Workspace_msvc/evs_enc.vcxproj create mode 100644 Workspace_msvc/lib_fx.vcxproj create mode 100644 basic_math/log2.c create mode 100644 basic_math/log2.h create mode 100644 basic_math/math_32.h create mode 100644 basic_math/math_op.c create mode 100644 basic_math/math_op.h create mode 100644 basic_math/oper_32b.c create mode 100644 basic_math/oper_32b.h create mode 100644 basic_math/rom_basic_math.c create mode 100644 basic_math/rom_basic_math.h create mode 100644 basic_op/README.md create mode 100644 basic_op/basop.rme create mode 100644 basic_op/basop32.c create mode 100644 basic_op/basop32.h create mode 100644 basic_op/complex_basop.c create mode 100644 basic_op/complex_basop.h create mode 100644 basic_op/control.c create mode 100644 basic_op/control.h create mode 100644 basic_op/count.c create mode 100644 basic_op/count.h create mode 100644 basic_op/enh1632.c create mode 100644 basic_op/enh1632.h create mode 100644 basic_op/enh32.c create mode 100644 basic_op/enh32.h create mode 100644 basic_op/enh40.c create mode 100644 basic_op/enh40.h create mode 100644 basic_op/enh64.c create mode 100644 basic_op/enh64.h create mode 100644 basic_op/enhUL32.c create mode 100644 basic_op/enhUL32.h create mode 100644 basic_op/move.h create mode 100644 basic_op/patch.h create mode 100644 basic_op/stl.h create mode 100644 basic_op/typedef.h create mode 100644 basic_op/typedefs.h create mode 100644 lib_com/ACcontextMapping.c create mode 100644 lib_com/ari.c create mode 100644 lib_com/ari_hm.c create mode 100644 lib_com/arith_coder.c create mode 100644 lib_com/basop_mpy.h create mode 100644 lib_com/basop_util.c create mode 100644 lib_com/basop_util.h create mode 100644 lib_com/bitalloc_fx.c create mode 100644 lib_com/bitallocsum_fx.c create mode 100644 lib_com/bits_alloc.c create mode 100644 lib_com/bitstream_fx.c create mode 100644 lib_com/cb_shape_fx.c create mode 100644 lib_com/cldfb.c create mode 100644 lib_com/cng_exc_fx.c create mode 100644 lib_com/cnst_fx.h create mode 100644 lib_com/codec_tcx_common.c create mode 100644 lib_com/core_com_config_fx.c create mode 100644 lib_com/deemph_fx.c create mode 100644 lib_com/delay_comp.c create mode 100644 lib_com/disclaimer.c create mode 100644 lib_com/disclaimer.h create mode 100644 lib_com/dlpc_bfi.c create mode 100644 lib_com/edct_fx.c create mode 100644 lib_com/enhancer_fx.c create mode 100644 lib_com/enr_1_az_fx.c create mode 100644 lib_com/env_adj_fx.c create mode 100644 lib_com/env_stab_fx.c create mode 100644 lib_com/env_stab_trans_fx.c create mode 100644 lib_com/est_tilt_fx.c create mode 100644 lib_com/fd_cng_com.c create mode 100644 lib_com/fft.c create mode 100644 lib_com/fft_fx.c create mode 100644 lib_com/fft_rel_fx.c create mode 100644 lib_com/fft_rel_sas_fx.c create mode 100644 lib_com/fill_spectrum_fx.c create mode 100644 lib_com/findpulse_fx.c create mode 100644 lib_com/fine_gain_bits_fx.c create mode 100644 lib_com/frame_ener_fx.c create mode 100644 lib_com/g192.c create mode 100644 lib_com/g192.h create mode 100644 lib_com/gain_inov.c create mode 100644 lib_com/get_gain.c create mode 100644 lib_com/gs_bitallocation_fx.c create mode 100644 lib_com/gs_gains_fx.c create mode 100644 lib_com/gs_inact_switching_fx.c create mode 100644 lib_com/gs_noisefill_fx.c create mode 100644 lib_com/gs_preech_fx.c create mode 100644 lib_com/guided_plc_util.c create mode 100644 lib_com/hp50.c create mode 100644 lib_com/hq2_bit_alloc_fx.c create mode 100644 lib_com/hq2_core_com_fx.c create mode 100644 lib_com/hq2_noise_inject_fx.c create mode 100644 lib_com/hq_bit_allocation_fx.c create mode 100644 lib_com/hq_conf_fx.c create mode 100644 lib_com/hq_tools_fx.c create mode 100644 lib_com/hvq_pvq_bitalloc_fx.c create mode 100644 lib_com/igf_base.c create mode 100644 lib_com/index_pvq_opt_fx.c create mode 100644 lib_com/int_lsp_fx.c create mode 100644 lib_com/interleave_spectrum_fx.c create mode 100644 lib_com/interpol_fx.c create mode 100644 lib_com/isf_dec_amr_wb_fx.c create mode 100644 lib_com/lag_wind.c create mode 100644 lib_com/lerp.c create mode 100644 lib_com/limit_t0_fx.c create mode 100644 lib_com/logqnorm_fx.c create mode 100644 lib_com/longarith.c create mode 100644 lib_com/low_rate_band_att_fx.c create mode 100644 lib_com/lpc_tools_fx.c create mode 100644 lib_com/lsf_dec_bfi_fx.c create mode 100644 lib_com/lsf_msvq_ma.c create mode 100644 lib_com/lsf_tools_fx.c create mode 100644 lib_com/lsp_conv_poly_fx.c create mode 100644 lib_com/mime.h create mode 100644 lib_com/modif_fs_fx.c create mode 100644 lib_com/mslvq_com_fx.c create mode 100644 lib_com/nelp_fx.c create mode 100644 lib_com/options.h create mode 100644 lib_com/parameter_bitmaping.c create mode 100644 lib_com/phase_dispersion.c create mode 100644 lib_com/ppp_fx.c create mode 100644 lib_com/pred_lt4_fx.c create mode 100644 lib_com/preemph_fx.c create mode 100644 lib_com/prot_fx.h create mode 100644 lib_com/pvq_com_fx.c create mode 100644 lib_com/range_com_fx.c create mode 100644 lib_com/re8_ppv_fx.c create mode 100644 lib_com/re8_util_fx.c create mode 100644 lib_com/recovernorm_fx.c create mode 100644 lib_com/reordvct_fx.c create mode 100644 lib_com/residu_fx.c create mode 100644 lib_com/rom_basop_util.c create mode 100644 lib_com/rom_basop_util.h create mode 100644 lib_com/rom_com_fx.c create mode 100644 lib_com/rom_com_fx.h create mode 100644 lib_com/scale_mem_fx.c create mode 100644 lib_com/stab_est_fx.c create mode 100644 lib_com/stat_com.h create mode 100644 lib_com/stat_noise_uv_mod_fx.c create mode 100644 lib_com/swb_bwe_com_fx.c create mode 100644 lib_com/swb_bwe_com_hr_fx.c create mode 100644 lib_com/swb_bwe_com_lr_fx.c create mode 100644 lib_com/swb_tbe_com_fx.c create mode 100644 lib_com/syn_12k8_fx.c create mode 100644 lib_com/syn_filt_fx.c create mode 100644 lib_com/tcq_position_arith_fx.c create mode 100644 lib_com/tcx_ltp.c create mode 100644 lib_com/tcx_mdct.c create mode 100644 lib_com/tcx_mdct_window.c create mode 100644 lib_com/tcx_utils.c create mode 100644 lib_com/tec_com.c create mode 100644 lib_com/tns_base.c create mode 100644 lib_com/tools_fx.c create mode 100644 lib_com/trans_direct_fx.c create mode 100644 lib_com/trans_inv_fx.c create mode 100644 lib_com/vlpc_2st_com.c create mode 100644 lib_com/weight_a_fx.c create mode 100644 lib_com/weight_fx.c create mode 100644 lib_com/wi_fx.c create mode 100644 lib_com/window.c create mode 100644 lib_com/window_ola_fx.c create mode 100644 lib_com/wtda_fx.c create mode 100644 lib_dec/ACcontextMapping_dec.c create mode 100644 lib_dec/EvsRXlib.c create mode 100644 lib_dec/EvsRXlib.h create mode 100644 lib_dec/FEC_HQ_core_fx.c create mode 100644 lib_dec/FEC_HQ_phase_ecu_fx.c create mode 100644 lib_dec/FEC_adapt_codebook_fx.c create mode 100644 lib_dec/FEC_clas_estim_fx.c create mode 100644 lib_dec/FEC_fx.c create mode 100644 lib_dec/FEC_lsf_estim_fx.c create mode 100644 lib_dec/FEC_pitch_estim_fx.c create mode 100644 lib_dec/FEC_scale_syn_fx.c create mode 100644 lib_dec/LD_music_post_filter_fx.c create mode 100644 lib_dec/TonalComponentDetection.c create mode 100644 lib_dec/acelp_core_dec_fx.c create mode 100644 lib_dec/acelp_core_switch_dec_fx.c create mode 100644 lib_dec/amr_wb_dec_fx.c create mode 100644 lib_dec/ari_dec.c create mode 100644 lib_dec/ari_hm_dec.c create mode 100644 lib_dec/arith_coder_dec.c create mode 100644 lib_dec/avq_dec_fx.c create mode 100644 lib_dec/basop_util_jbm.c create mode 100644 lib_dec/basop_util_jbm.h create mode 100644 lib_dec/bass_psfilter_fx.c create mode 100644 lib_dec/cng_dec_fx.c create mode 100644 lib_dec/core_dec_init.c create mode 100644 lib_dec/core_dec_reconf.c create mode 100644 lib_dec/core_dec_switch.c create mode 100644 lib_dec/core_switching_dec_fx.c create mode 100644 lib_dec/d_gain2p.c create mode 100644 lib_dec/dec2t32_fx.c create mode 100644 lib_dec/dec4t64_fx.c create mode 100644 lib_dec/dec_LPD.c create mode 100644 lib_dec/dec_ace.c create mode 100644 lib_dec/dec_acelp.c create mode 100644 lib_dec/dec_acelp_tcx_main.c create mode 100644 lib_dec/dec_amr_wb_fx.c create mode 100644 lib_dec/dec_gen_voic_fx.c create mode 100644 lib_dec/dec_higher_acelp_fx.c create mode 100644 lib_dec/dec_nelp_fx.c create mode 100644 lib_dec/dec_pit_exc_fx.c create mode 100644 lib_dec/dec_post.c create mode 100644 lib_dec/dec_ppp_fx.c create mode 100644 lib_dec/dec_prm.c create mode 100644 lib_dec/dec_tcx.c create mode 100644 lib_dec/dec_tran_fx.c create mode 100644 lib_dec/dec_uv.c create mode 100644 lib_dec/decision_matrix_dec_fx.c create mode 100644 lib_dec/decoder.c create mode 100644 lib_dec/dlpc_avq.c create mode 100644 lib_dec/dlpc_stoch.c create mode 100644 lib_dec/er_dec_acelp.c create mode 100644 lib_dec/er_dec_tcx.c create mode 100644 lib_dec/er_scale_syn.c create mode 100644 lib_dec/er_sync_exc.c create mode 100644 lib_dec/er_util.c create mode 100644 lib_dec/evs_dec_fx.c create mode 100644 lib_dec/evs_rtp_payload.c create mode 100644 lib_dec/evs_rtp_payload.h create mode 100644 lib_dec/fd_cng_dec.c create mode 100644 lib_dec/gain_dec_fx.c create mode 100644 lib_dec/gaus_dec_fx.c create mode 100644 lib_dec/gs_dec_amr_wb_fx.c create mode 100644 lib_dec/gs_dec_fx.c create mode 100644 lib_dec/hdecnrm_fx.c create mode 100644 lib_dec/hf_synth_fx.c create mode 100644 lib_dec/hq_classifier_dec_fx.c create mode 100644 lib_dec/hq_conf_fec_fx.c create mode 100644 lib_dec/hq_core_dec_fx.c create mode 100644 lib_dec/hq_env_dec_fx.c create mode 100644 lib_dec/hq_hr_dec_fx.c create mode 100644 lib_dec/hq_lr_dec_fx.c create mode 100644 lib_dec/igf_dec.c create mode 100644 lib_dec/igf_scf_dec.c create mode 100644 lib_dec/init_dec_fx.c create mode 100644 lib_dec/inov_dec_fx.c create mode 100644 lib_dec/io_dec_fx.c create mode 100644 lib_dec/jbm_jb4_circularbuffer.c create mode 100644 lib_dec/jbm_jb4_circularbuffer.h create mode 100644 lib_dec/jbm_jb4_inputbuffer.c create mode 100644 lib_dec/jbm_jb4_inputbuffer.h create mode 100644 lib_dec/jbm_jb4_jmf.c create mode 100644 lib_dec/jbm_jb4_jmf.h create mode 100644 lib_dec/jbm_jb4sb.c create mode 100644 lib_dec/jbm_jb4sb.h create mode 100644 lib_dec/jbm_pcmdsp_apa.c create mode 100644 lib_dec/jbm_pcmdsp_apa.h create mode 100644 lib_dec/jbm_pcmdsp_fifo.c create mode 100644 lib_dec/jbm_pcmdsp_fifo.h create mode 100644 lib_dec/jbm_pcmdsp_similarityestimation.c create mode 100644 lib_dec/jbm_pcmdsp_similarityestimation.h create mode 100644 lib_dec/jbm_pcmdsp_window.c create mode 100644 lib_dec/jbm_pcmdsp_window.h create mode 100644 lib_dec/lead_deindexing_fx.c create mode 100644 lib_dec/lp_exc_d_fx.c create mode 100644 lib_dec/lsf_dec_fx.c create mode 100644 lib_dec/lsf_msvq_ma_dec.c create mode 100644 lib_dec/nelp_dec_fx.c create mode 100644 lib_dec/peak_vq_dec_fx.c create mode 100644 lib_dec/pit_dec.c create mode 100644 lib_dec/pitch_extr.c create mode 100644 lib_dec/post_dec.c create mode 100644 lib_dec/ppp_dec_fx.c create mode 100644 lib_dec/pvq_core_dec_fx.c create mode 100644 lib_dec/pvq_decode_fx.c create mode 100644 lib_dec/range_dec_fx.c create mode 100644 lib_dec/re8_dec_fx.c create mode 100644 lib_dec/rom_dec_fx.c create mode 100644 lib_dec/rom_dec_fx.h create mode 100644 lib_dec/rst_dec_fx.c create mode 100644 lib_dec/rtpdump.c create mode 100644 lib_dec/rtpdump.h create mode 100644 lib_dec/stat_dec_fx.h create mode 100644 lib_dec/stat_noise_uv_dec_fx.c create mode 100644 lib_dec/swb_bwe_dec_fx.c create mode 100644 lib_dec/swb_bwe_dec_hr_fx.c create mode 100644 lib_dec/swb_bwe_dec_lr_fx.c create mode 100644 lib_dec/swb_tbe_dec_fx.c create mode 100644 lib_dec/syn_outp_fx.c create mode 100644 lib_dec/tcq_core_dec_fx.c create mode 100644 lib_dec/tcx_utils_dec.c create mode 100644 lib_dec/tns_base_dec.c create mode 100644 lib_dec/tonalMDCTconcealment.c create mode 100644 lib_dec/transition_dec_fx.c create mode 100644 lib_dec/updt_dec_fx.c create mode 100644 lib_dec/vlpc_1st_dec.c create mode 100644 lib_dec/vlpc_2st_dec.c create mode 100644 lib_dec/voiced_dec_fx.c create mode 100644 lib_dec/voip_client.c create mode 100644 lib_dec/waveadjust_fec_dec.c create mode 100644 lib_enc/ACcontextMapping_enc.c create mode 100644 lib_enc/FEC_enc_fx.c create mode 100644 lib_enc/SNR_calc.c create mode 100644 lib_enc/acelp_core_enc_fx.c create mode 100644 lib_enc/acelp_core_switch_enc_fx.c create mode 100644 lib_enc/acelp_enc_util.c create mode 100644 lib_enc/amr_wb_enc_fx.c create mode 100644 lib_enc/analy_lp_fx.c create mode 100644 lib_enc/analy_sp.c create mode 100644 lib_enc/ari_enc.c create mode 100644 lib_enc/ari_hm_enc.c create mode 100644 lib_enc/arith_coder_enc.c create mode 100644 lib_enc/avq_cod_fx.c create mode 100644 lib_enc/bass_psfilter_enc.c create mode 100644 lib_enc/bw_detect_fx.c create mode 100644 lib_enc/cng_enc_fx.c create mode 100644 lib_enc/cod2t32_fx.c create mode 100644 lib_enc/cod4t64_fx.c create mode 100644 lib_enc/cod_ace.c create mode 100644 lib_enc/cod_tcx.c create mode 100644 lib_enc/cod_uv.c create mode 100644 lib_enc/comvad_decision.c create mode 100644 lib_enc/cor_shif_fx.c create mode 100644 lib_enc/core_enc_2div.c create mode 100644 lib_enc/core_enc_init.c create mode 100644 lib_enc/core_enc_ol.c create mode 100644 lib_enc/core_enc_reconf.c create mode 100644 lib_enc/core_enc_switch.c create mode 100644 lib_enc/core_enc_updt.c create mode 100644 lib_enc/core_switching_enc_fx.c create mode 100644 lib_enc/corr_xh_fx.c create mode 100644 lib_enc/decision_matrix_enc_fx.c create mode 100644 lib_enc/detect_transient_fx.c create mode 100644 lib_enc/diffcod_fx.c create mode 100644 lib_enc/dtx_fx.c create mode 100644 lib_enc/enc_acelp.c create mode 100644 lib_enc/enc_acelp_tcx_main.c create mode 100644 lib_enc/enc_acelpx.c create mode 100644 lib_enc/enc_amr_wb_fx.c create mode 100644 lib_enc/enc_gain.c create mode 100644 lib_enc/enc_gen_voic_fx.c create mode 100644 lib_enc/enc_gen_voic_rf_fx.c create mode 100644 lib_enc/enc_higher_acelp_fx.c create mode 100644 lib_enc/enc_nelp_fx.c create mode 100644 lib_enc/enc_pit_exc_fx.c create mode 100644 lib_enc/enc_ppp_fx.c create mode 100644 lib_enc/enc_prm.c create mode 100644 lib_enc/enc_tran_fx.c create mode 100644 lib_enc/enc_uv_fx.c create mode 100644 lib_enc/encoder.c create mode 100644 lib_enc/energy.c create mode 100644 lib_enc/eval_pit_contr_fx.c create mode 100644 lib_enc/evs_enc_fx.c create mode 100644 lib_enc/ext_sig_ana.c create mode 100644 lib_enc/fd_cng_enc.c create mode 100644 lib_enc/find_tar_fx.c create mode 100644 lib_enc/find_tilt_fx.c create mode 100644 lib_enc/find_uv.c create mode 100644 lib_enc/find_wsp_fx.c create mode 100644 lib_enc/frame_spec_dif_cor_rate.c create mode 100644 lib_enc/gain_enc_fx.c create mode 100644 lib_enc/gaus_enc_fx.c create mode 100644 lib_enc/gp_clip_fx.c create mode 100644 lib_enc/gs_enc_fx.c create mode 100644 lib_enc/guided_plc_enc.c create mode 100644 lib_enc/hf_cod_amrwb_fx.c create mode 100644 lib_enc/hq_classifier_enc_fx.c create mode 100644 lib_enc/hq_core_enc_fx.c create mode 100644 lib_enc/hq_env_enc_fx.c create mode 100644 lib_enc/hq_hr_enc_fx.c create mode 100644 lib_enc/hq_lr_enc_fx.c create mode 100644 lib_enc/hvq_enc_fx.c create mode 100644 lib_enc/igf_enc.c create mode 100644 lib_enc/igf_scf_enc.c create mode 100644 lib_enc/init_enc_fx.c create mode 100644 lib_enc/inov_enc_fx.c create mode 100644 lib_enc/io_enc_fx.c create mode 100644 lib_enc/isf_enc_amr_wb_fx.c create mode 100644 lib_enc/lead_indexing_fx.c create mode 100644 lib_enc/long_enr.c create mode 100644 lib_enc/lp_exc_e_fx.c create mode 100644 lib_enc/lsf_enc_fx.c create mode 100644 lib_enc/lsf_msvq_ma_enc.c create mode 100644 lib_enc/ltd_stable.c create mode 100644 lib_enc/mdct_classifier_fx.c create mode 100644 lib_enc/mdct_selector.c create mode 100644 lib_enc/mslvq_enc_fx.c create mode 100644 lib_enc/multi_harm_fx.c create mode 100644 lib_enc/nelp_enc_fx.c create mode 100644 lib_enc/nois_est_fx.c create mode 100644 lib_enc/noise_adjust_fx.c create mode 100644 lib_enc/normalizecoefs_fx.c create mode 100644 lib_enc/peak_vq_enc_fx.c create mode 100644 lib_enc/pit_enc_fx.c create mode 100644 lib_enc/pitch_ol.c create mode 100644 lib_enc/pitch_ol2_fx.c create mode 100644 lib_enc/plc_enc_ext.c create mode 100644 lib_enc/ppp_enc_fx.c create mode 100644 lib_enc/pre_proc_fx.c create mode 100644 lib_enc/pvq_core_enc_fx.c create mode 100644 lib_enc/pvq_encode_fx.c create mode 100644 lib_enc/q_gain2p.c create mode 100644 lib_enc/qlpc_avq.c create mode 100644 lib_enc/qlpc_stoch.c create mode 100644 lib_enc/range_enc_fx.c create mode 100644 lib_enc/re8_cod_fx.c create mode 100644 lib_enc/reordernorm_fx.c create mode 100644 lib_enc/rom_enc_fx.c create mode 100644 lib_enc/rom_enc_fx.h create mode 100644 lib_enc/rst_enc_fx.c create mode 100644 lib_enc/scale_enc_fx.c create mode 100644 lib_enc/set_impulse_fx.c create mode 100644 lib_enc/setmodeindex.c create mode 100644 lib_enc/sig_clas.c create mode 100644 lib_enc/spec_center.c create mode 100644 lib_enc/spec_flatness.c create mode 100644 lib_enc/speech_music_classif_fx.c create mode 100644 lib_enc/stat_enc_fx.h create mode 100644 lib_enc/stat_noise_uv_enc_fx.c create mode 100644 lib_enc/subband_fft.c create mode 100644 lib_enc/swb_bwe_enc_fx.c create mode 100644 lib_enc/swb_bwe_enc_hr_fx.c create mode 100644 lib_enc/swb_bwe_enc_lr_fx.c create mode 100644 lib_enc/swb_pre_proc_fx.c create mode 100644 lib_enc/swb_tbe_enc_fx.c create mode 100644 lib_enc/tcq_core_enc_fx.c create mode 100644 lib_enc/tcx_ltp_enc.c create mode 100644 lib_enc/tcx_utils_enc.c create mode 100644 lib_enc/tfa_enc.c create mode 100644 lib_enc/tns_base_enc.c create mode 100644 lib_enc/transient_detection.c create mode 100644 lib_enc/transition_enc_fx.c create mode 100644 lib_enc/update_decision.c create mode 100644 lib_enc/updt_enc_fx.c create mode 100644 lib_enc/updt_tar_fx.c create mode 100644 lib_enc/vad_basop.c create mode 100644 lib_enc/vad_basop.h create mode 100644 lib_enc/vad_fx.c create mode 100644 lib_enc/vad_param_updt_fx.c create mode 100644 lib_enc/vad_proc.c create mode 100644 lib_enc/vbr_average_rate_fx.c create mode 100644 lib_enc/vlpc_1st_cod.c create mode 100644 lib_enc/vlpc_2st_cod.c create mode 100644 lib_enc/voiced_enc_fx.c create mode 100644 lib_enc/waveadjust_fec_cod.c create mode 100644 scripts/switchPaths/sw_13k2_512k.bin create mode 100644 scripts/switchPaths/sw_13k2_to_128k_10fr.bin create mode 100644 scripts/switchPaths/sw_amrwb.bin create mode 100644 scripts/switchPaths/sw_amrwb_evs.bin create mode 100644 scripts/switchPaths/sw_amrwb_evs2.bin create mode 100644 scripts/switchPaths/sw_highest.bin create mode 100644 scripts/switchPaths/sw_nb1.bin create mode 100644 scripts/switchPaths/sw_nb5.bin create mode 100644 scripts/switchPaths/sw_swb1.bin create mode 100644 scripts/switchPaths/sw_wb1.bin create mode 100644 scripts/switchPaths/sw_wb5.bin create mode 100644 scripts/switchPaths/swb_high1.bin create mode 100644 scripts/switchPaths/swb_low1.bin create mode 100644 scripts/switchPaths/wb_high1.bin create mode 100644 scripts/switchPaths/wb_low1.bin diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e348552 --- /dev/null +++ b/Makefile @@ -0,0 +1,92 @@ +# GNU Makefile + +# Paths +SRC_ENC = lib_enc lib_com basic_op basic_math lib_debug +SRC_DEC = lib_dec lib_com basic_op basic_math lib_debug +BUILD = build + +SRC_DIRS = $(sort -u $(SRC_ENC) $(SRC_DEC)) + +# Name of CLI binaries +CLI_ENC = EVS_cod +CLI_DEC = EVS_dec + +# Default tool settings +CC = gcc +RM = rm -f + +ifndef VERBOSE +QUIET_CC = @echo ' ' Compiling $<; +QUIET_LINK= @echo ' ' Linking $@; +QUIET = @ +endif + +# C compiler flags +CFLAGS += -pedantic -Wcast-qual -Wall -W -Wextra -Wno-long-long \ + -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes \ + -Werror-implicit-function-declaration + +ifeq "$(RELEASE)" "1" +CFLAGS += -DRELEASE +DELIVERY = 1 +OPTIM ?= 2 +endif + +ifneq "$(DEBUG)" "0" +CFLAGS += -g3 +LDFLAGS += -g3 +endif + +ifeq "$(WMOPS)" "1" +CFLAGS += -DWMOPS=1 +endif + +OPTIM ?= 0 +CFLAGS += -O$(OPTIM) + +CFLAGS += $(foreach DIR,$(SRC_DIRS),-I$(DIR)) + +# Source file search paths +VPATH = $(SRC_DIRS) + +############################################################################### + +SRCS_ENC = $(foreach DIR,$(SRC_ENC),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c))) +SRCS_DEC = $(foreach DIR,$(SRC_DEC),$(patsubst $(DIR)/%,%,$(wildcard $(DIR)/*.c))) + +OBJS_ENC = $(addprefix $(BUILD)/,$(SRCS_ENC:.c=.o)) +OBJS_DEC = $(addprefix $(BUILD)/,$(SRCS_DEC:.c=.o)) + +DEPS = $(addprefix $(BUILD)/,$(SRCS_ENC:.c=.P) $(SRCS_DEC:.c=.P)) + +############################################################################### + +.PHONY: all clean clean_all + +all: $(CLI_ENC) $(CLI_DEC) + +$(BUILD): + $(QUIET)mkdir -p $(BUILD) + +$(CLI_ENC): $(OBJS_ENC) + $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_ENC) -lm -o $(CLI_ENC) + +$(CLI_DEC): $(OBJS_DEC) + $(QUIET_LINK)$(CC) $(LDFLAGS) $(OBJS_DEC) -lm -o $(CLI_DEC) + +clean: + $(QUIET)$(RM) $(OBJS_ENC) $(OBJS_DEC) $(DEPS) + $(QUIET)$(RM) $(DEPS:.P=.d) + $(QUIET)test ! -d $(BUILD) || rm -rf $(BUILD) + +clean_all: clean + $(QUIET)$(RM) $(CLI_ENC) $(CLI_DEC) + +$(BUILD)/%.o : %.c | $(BUILD) + $(QUIET_CC)$(CC) $(CFLAGS) -c -MD -o $@ $< + @cp $(BUILD)/$*.d $(BUILD)/$*.P; \ + sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' < $(BUILD)/$*.d >> $(BUILD)/$*.P; \ + $(RM) $(BUILD)/$*.d + +-include $(DEPS) diff --git a/Workspace_msvc/Workspace_msvc.sln b/Workspace_msvc/Workspace_msvc.sln new file mode 100644 index 0000000..adee191 --- /dev/null +++ b/Workspace_msvc/Workspace_msvc.sln @@ -0,0 +1,39 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "common.vcxproj", "{39EC200D-7795-4FF8-B214-B24EDA5526AE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "evs_dec", "evs_dec.vcxproj", "{E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "evs_enc", "evs_enc.vcxproj", "{824DA4CF-06F0-45C9-929A-8792F0E19C3E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib_fx", "lib_fx.vcxproj", "{52EF5F7B-DF20-4BA8-96E0-DCB4A9B3D200}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Debug|Win32.ActiveCfg = Debug|Win32 + {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Debug|Win32.Build.0 = Debug|Win32 + {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Release|Win32.ActiveCfg = Release|Win32 + {39EC200D-7795-4FF8-B214-B24EDA5526AE}.Release|Win32.Build.0 = Release|Win32 + {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Debug|Win32.ActiveCfg = Debug|Win32 + {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Debug|Win32.Build.0 = Debug|Win32 + {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Release|Win32.ActiveCfg = Release|Win32 + {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3}.Release|Win32.Build.0 = Release|Win32 + {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Debug|Win32.ActiveCfg = Debug|Win32 + {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Debug|Win32.Build.0 = Debug|Win32 + {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Release|Win32.ActiveCfg = Release|Win32 + {824DA4CF-06F0-45C9-929A-8792F0E19C3E}.Release|Win32.Build.0 = Release|Win32 + {52EF5F7B-DF20-4BA8-96E0-DCB4A9B3D200}.Debug|Win32.ActiveCfg = Debug|Win32 + {52EF5F7B-DF20-4BA8-96E0-DCB4A9B3D200}.Debug|Win32.Build.0 = Debug|Win32 + {52EF5F7B-DF20-4BA8-96E0-DCB4A9B3D200}.Release|Win32.ActiveCfg = Release|Win32 + {52EF5F7B-DF20-4BA8-96E0-DCB4A9B3D200}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Workspace_msvc/common.vcxproj b/Workspace_msvc/common.vcxproj new file mode 100644 index 0000000..946a2e0 --- /dev/null +++ b/Workspace_msvc/common.vcxproj @@ -0,0 +1,250 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {39EC200D-7795-4FF8-B214-B24EDA5526AE} + common + 10.0 + + + + StaticLibrary + v142 + false + MultiByte + + + StaticLibrary + v142 + false + MultiByte + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.26228.10 + + + .\Debug_Common\ + .\Debug_Common\ + + + .\Release_Common\ + .\Release_Common\ + + + + /MP %(AdditionalOptions) + Disabled + ..\lib_enc;..\lib_dec;..\lib_com;..\lib_debug;..\basic_op;..\basic_math;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + EnableFastChecks + MultiThreadedDebug + + + $(IntDir)commonlib.pdb + Level4 + true + OldStyle + Default + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + WS2_32.lib;%(AdditionalDependencies) + $(OutDir)$(TargetName)$(TargetExt) + true + + + + + MaxSpeed + OnlyExplicitInline + false + Speed + false + false + ..\lib_enc;..\lib_dec;..\lib_com;..\basic_op;..\basic_math;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;RELEASE;%(PreprocessorDefinitions) + true + + Default + MultiThreaded + true + + + $(IntDir)commonlib.pdb + Level4 + true + + Default + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + WS2_32.lib;%(AdditionalDependencies) + $(OutDir)$(TargetName)$(TargetExt) + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {52ef5f7b-df20-4ba8-96e0-dcb4a9b3d200} + false + + + + + + \ No newline at end of file diff --git a/Workspace_msvc/evs_dec.vcxproj b/Workspace_msvc/evs_dec.vcxproj new file mode 100644 index 0000000..410ecd8 --- /dev/null +++ b/Workspace_msvc/evs_dec.vcxproj @@ -0,0 +1,294 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {E822DDAF-0F5F-4CD0-A694-38AE69DE74D3} + evs_dec + 10.0 + + + + Application + v142 + false + MultiByte + + + Application + v142 + false + MultiByte + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.26228.10 + + + ..\ + .\Debug_Dec\ + false + false + EVS_dec + + + ..\ + .\Release_Dec\ + false + false + EVS_dec + + + + + + + .\Debug/vbr_dec.tlb + + + + /MP %(AdditionalOptions) + Disabled + ..\lib_enc;..\lib_dec;..\lib_com;..\lib_debug;..\basic_op;..\basic_math;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + EnableFastChecks + MultiThreadedDebug + false + + + $(IntDir)evs_dec.pdb + Level4 + true + OldStyle + Default + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + + ..\EVS_dec.exe + true + + true + .\Debug/evs_dec.pdb + Console + false + + MachineX86 + + + + + .\Release/vbr_dec.tlb + + + + MaxSpeed + OnlyExplicitInline + false + Speed + false + false + ..\lib_enc;..\lib_dec;..\lib_com;..\basic_op;..\basic_math;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;RELEASE;%(PreprocessorDefinitions) + true + + Default + MultiThreaded + true + false + + + + $(IntDir) + $(IntDir)evs_dec.pdb + Level4 + true + + Default + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + Ws2_32.lib;%(AdditionalDependencies) + ..\EVS_dec.exe + true + + false + .\Release/vbr_dec.pdb + Console + false + + MachineX86 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {39ec200d-7795-4ff8-b214-b24eda5526ae} + false + + + {52ef5f7b-df20-4ba8-96e0-dcb4a9b3d200} + false + + + + + + \ No newline at end of file diff --git a/Workspace_msvc/evs_enc.vcxproj b/Workspace_msvc/evs_enc.vcxproj new file mode 100644 index 0000000..7da2473 --- /dev/null +++ b/Workspace_msvc/evs_enc.vcxproj @@ -0,0 +1,321 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {824DA4CF-06F0-45C9-929A-8792F0E19C3E} + evs_enc + 10.0 + + + + Application + v142 + false + MultiByte + + + Application + v142 + false + MultiByte + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.26228.10 + + + ..\ + .\Release_Enc\ + false + false + EVS_cod + + + ..\ + .\Debug_Enc\ + false + false + EVS_cod + + + + + + + .\Release/vbr_enc.tlb + + + + MaxSpeed + OnlyExplicitInline + false + Speed + false + false + ..\lib_enc;..\lib_dec;..\lib_com;..\basic_op;..\basic_math;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;RELEASE;%(PreprocessorDefinitions) + true + + Default + MultiThreaded + true + Precise + false + + + + $(IntDir) + $(IntDir)evs_enc.pdb + Level4 + true + + Default + + + NDEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + Ws2_32.lib;%(AdditionalDependencies) + ..\EVS_cod.exe + true + + false + .\Release/vbr_enc.pdb + Console + false + + MachineX86 + + + + + + + + .\Debug/vbr_enc.tlb + + + + /MP %(AdditionalOptions) + Disabled + ..\lib_enc;..\lib_dec;..\lib_com;..\lib_debug;..\basic_op;..\basic_math;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + EnableFastChecks + MultiThreadedDebug + false + + + $(IntDir)evs_enc.pdb + true + Level4 + true + OldStyle + Default + + + _DEBUG;%(PreprocessorDefinitions) + 0x0c0c + + + + ..\EVS_cod.exe + true + + false + true + .\Debug/evs_enc.pdb + Console + + false + + MachineX86 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {39ec200d-7795-4ff8-b214-b24eda5526ae} + false + + + {52ef5f7b-df20-4ba8-96e0-dcb4a9b3d200} + false + + + + + + \ No newline at end of file diff --git a/Workspace_msvc/lib_fx.vcxproj b/Workspace_msvc/lib_fx.vcxproj new file mode 100644 index 0000000..c05eb8e --- /dev/null +++ b/Workspace_msvc/lib_fx.vcxproj @@ -0,0 +1,126 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {52EF5F7B-DF20-4BA8-96E0-DCB4A9B3D200} + lib_fx + 10.0 + + + + StaticLibrary + v142 + MultiByte + true + + + StaticLibrary + v142 + MultiByte + + + + + + + + + + + + + <_ProjectFileVersion>15.0.26228.10 + + + .\Debug_Fx\ + .\Debug_Fx\ + + + .\Release_Fx\ + .\Release_Fx\ + + + + /MP %(AdditionalOptions) + Disabled + ..\lib_enc;..\lib_dec;..\lib_com;..\lib_debug;..\basic_op;..\basic_math;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + $(IntDir)lib_fixlib.pdb + Level3 + OldStyle + Default + + + + + MaxSpeed + false + false + ..\lib_enc;..\lib_dec;..\lib_com;..\basic_op;..\basic_math;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_WARNINGS;RELEASE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + true + $(IntDir)lib_fixlib.pdb + Level3 + ProgramDatabase + Default + Speed + + + + + + \ No newline at end of file diff --git a/basic_math/log2.c b/basic_math/log2.c new file mode 100644 index 0000000..57abb33 --- /dev/null +++ b/basic_math/log2.c @@ -0,0 +1,211 @@ +/******************************************************************************** +* +* File : log2.c +* Purpose : Computes log2(L_x) +* +******************************************************************************** +*/ + +/* +******************************************************************************** +* INCLUDE FILES +******************************************************************************** +*/ +#include "stl.h" +#include "math_op.h" +#include +#include "rom_basic_math.h" +#include "options.h" + +#define LW_SIGN (Word32)0x80000000 /* sign bit */ +#define LW_MIN (Word32)0x80000000 +#define LW_MAX (Word32)0x7fffffff + +#define SW_SIGN (Word16)0x8000 /* sign bit for Word16 type */ +#define SW_MIN (Word16)0x8000 /* smallest Ram */ +#define SW_MAX (Word16)0x7fff /* largest Ram */ + + +/* +******************************************************************************** +* PUBLIC PROGRAM CODE +******************************************************************************** +*/ + +/************************************************************************* + * + * FUNCTION: Log2_norm_lc() + * + * PURPOSE: Computes log2(L_x, exp), where L_x is positive and + * normalized, and exp is the normalisation exponent + * If L_x is negative or zero, the result is 0. + * + * DESCRIPTION: + * The function Log2(L_x) is approximated by a table and linear + * interpolation. The following steps are used to compute Log2(L_x) + * + * 1- exponent = 30-norm_exponent + * 2- i = bit25-b31 of L_x; 32<=i<=63 (because of normalization). + * 3- a = bit10-b24 + * 4- i -=32 + * 5- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2 + * + *************************************************************************/ +Word16 Log2_norm_lc ( /* (o) : Fractional part of Log2. (range: 0<=val<1) */ + Word32 L_x /* (i) : input value (normalized) */ +) +{ + Word16 i, a; + Word16 y; + + if (L_x <= 0) + L_x = L_deposit_h(0x4000); + + L_x = L_shr (L_x, 9); + a = extract_l (L_x); /* Extract b10-b24 of fraction */ + a = lshr(a, 1); + + i = mac_r(L_x, -32*2-1, 16384); /* Extract b25-b31 minus 32 */ + + y = mac_r(L_table_Log2_norm_lc[i], table_diff_Log2_norm_lc[i], a); /* table[i] << 16 - diff*a*2 */ + + return y; +} + +Word32 log10_fx(Word32 Linput) +{ + Word16 n1, frac, p1, p2, q1; + Word32 Ltemp1, Ltemp2; + Word32 L_tmp; + + if (Linput<=0) return(LW_MIN); + n1=norm_l(Linput); + Ltemp1=(Word32)L_shl(Linput,n1); + + Ltemp2=L_mult(extract_h(Ltemp1),0x40); + frac=extract_l(Ltemp2); + + p1=log2_tab[sub(extract_h(Ltemp2),0x20)]; + p2=log2_tab[sub(extract_h(Ltemp2),0x1F)]; + Ltemp2=L_mult(n1,0x200); + n1=extract_l(Ltemp2); + + Ltemp1=L_add(L_deposit_h(p1),0x8000); /* Add rounding bit */ + + IF(frac >= 0) + { + Ltemp1=L_sub(Ltemp1,(Word32)L_mult0(p1,frac)); + Ltemp1=L_add(Ltemp1,(Word32)L_mult0(p2,frac)); + } + ELSE + { + L_tmp = L_add(65536,frac); + L_tmp = L_tmp*p1; + Ltemp1=L_sub(Ltemp1,L_tmp); + + L_tmp = L_add(65536,frac); + L_tmp = L_tmp*p2; + Ltemp1=L_add(Ltemp1,L_tmp); + } + q1=extract_h(Ltemp1); + Ltemp1=L_mult(q1,0x6054); + Ltemp1=L_msu(Ltemp1,0x6054,n1); + return(L_shr(Ltemp1,1)); + +} + +Word32 pow_10(Word32 x , Word16 *Q) +{ + Word16 xl,xh, t1, t2, n; + Word32 Ltemp1; + Word32 Lacc; + Word32 L_tmp; + Word16 n1,i; + Word16 count = 0; + + move16();; + + xl=extract_l(x); + xh=extract_h(x); + + IF(xl < 0) + { + L_tmp = L_add(65536,xl); + Ltemp1=(Word32) (0x6a4d*L_tmp ); + } + ELSE + { + Ltemp1=L_mult0(0x6a4d,xl); + } + Ltemp1=L_add(L_shr(Ltemp1,16),L_shr(L_mult(xh,0x6a4d),1)); + + + Lacc=L_sub(-1L, Ltemp1); /* Lacc=~Lacc, 1's complement */ + t1=extract_l(L_shr(Lacc,7)); + + Ltemp1=L_shr(Ltemp1,7); + n1 = extract_h(Ltemp1); + n=sub(n1,14); + *Q = 14; move16(); + IF(t1<0) + { + L_tmp = L_add(65536,t1); + t2=extract_h(L_tmp*L_tmp); + } + ELSE + { + t2=extract_h(L_mult0(t1,t1)); + } + + Lacc = L_deposit_h(0x1FEF); + IF(t2 < 0) + { + L_tmp = L_add(65536,t2); + Lacc = L_add(Lacc,(Word32)(L_tmp*0x057C)); + } + ELSE + { + Lacc = L_add(Lacc,(Word32)L_mult0(t2,0x057C)); + } + + IF(t1 < 0) + { + L_tmp = L_add(65536,t1); + Lacc = L_sub(Lacc,(Word32)(L_tmp*0x155C)); + } + ELSE + { + Lacc = L_sub(Lacc,(Word32)L_mult0(t1,0x155C)); + } + + L_tmp = Lacc; + FOR(i =1 ;i <= n ;i++) + { + Overflow = 0; move16(); + L_tmp = L_shl(L_tmp,i); + IF(Overflow) + { + count = add(count,1); + } + } + *Q = sub(*Q,count); move16(); + + return(L_shl(Lacc,sub(n,count))); + +} + +Word16 Log2_lc( /* (o) : Fractional part of Log2. (range: 0<=val<1) */ + Word32 L_x, /* (i) : input value */ + Word16 *exponent /* (o) : Integer part of Log2. (range: 0<=val<=30) */ +) +{ + Word16 exp; + + if (L_x <= 0) + L_x = L_deposit_l(0x1); + + exp = norm_l (L_x); + *exponent = sub(30, exp); move16(); + + return Log2_norm_lc(L_shl(L_x, exp)); +} diff --git a/basic_math/log2.h b/basic_math/log2.h new file mode 100644 index 0000000..a8ff32e --- /dev/null +++ b/basic_math/log2.h @@ -0,0 +1,40 @@ +/******************************************************************************** +* +* File : log2.h +* Purpose : Computes log2(L_x) +* +******************************************************************************** +*/ +#ifndef log2_h +#define log2_h "$Id $" + +/* +******************************************************************************** +* INCLUDE FILES +******************************************************************************** +*/ +#include "typedef.h" +#include "log2.h" + +/* +******************************************************************************** +* DEFINITION OF DATA TYPES +******************************************************************************** +*/ + +/* +******************************************************************************** +* DECLARATION OF PROTOTYPES +******************************************************************************** +*/ +Word16 Log2_norm_lc ( /* (o) : Fractional part of Log2. (range: 0<=val<1) */ + Word32 L_x /* (i) : input value (normalized) */ +); + +Word32 log10_fx(Word32 Linput); +Word32 pow_10(Word32 x, Word16 *Q); +Word16 Log2_lc( /* (o) : Fractional part of Log2. (range: 0<=val<1) */ + Word32 L_x, /* (i) : input value */ + Word16 *exponent /* (o) : Integer part of Log2. (range: 0<=val<=30) */ +); +#endif diff --git a/basic_math/math_32.h b/basic_math/math_32.h new file mode 100644 index 0000000..539284d --- /dev/null +++ b/basic_math/math_32.h @@ -0,0 +1,10 @@ +#ifndef _MATH_32_H_ +#define _MATH_32_H_ + +#include "typedef.h" +#include "basop32.h" +#include "enh32.h" + +#define Mult_32_16(A,B) Mpy_32_16_1(A,B) +#define Mult_32_32(A,B) Mpy_32_32(A,B) +#endif /* #ifndef _MATH_32_H_ */ diff --git a/basic_math/math_op.c b/basic_math/math_op.c new file mode 100644 index 0000000..a5256a2 --- /dev/null +++ b/basic_math/math_op.c @@ -0,0 +1,359 @@ +/*___________________________________________________________________________ + | | + | This file contains mathematic operations in fixed point. | + | | + | Isqrt() : inverse square root (16 bits precision). | + | Pow2() : 2^x (16 bits precision). | + | Log2() : log2 (16 bits precision). | + | Dot_product() : scalar product of | + | | + | In this file, the values use theses representations: | + | | + | Word32 L_32 : standard signed 32 bits format | + | Word16 hi, lo : L_32 = hi<<16 + lo<<1 (DPF - Double Precision Format) | + | Word32 frac, Word16 exp : L_32 = frac << exp-31 (normalised format) | + | Word16 int, frac : L_32 = int.frac (fractional format) | + |___________________________________________________________________________| +*/ + +#include "stl.h" +#include "math_op.h" +#include "rom_basic_math.h" + +#include +#include + +/*___________________________________________________________________________ + | | + | Function Name : Isqrt | + | | + | Compute 1/sqrt(L_x). | + | if L_x is negative or zero, result is 1 (7fffffff). | + |---------------------------------------------------------------------------| + | Algorithm: | + | | + | 1- Normalization of L_x. | + | 2- call Isqrt_lc(L_x, exponant) | + | 3- L_y = L_x << exponant | + |___________________________________________________________________________| +*/ +Word32 Isqrt( /* (o) Q31 : output value (range: 0<=val<1) */ + Word32 L_x /* (i) Q0 : input value (range: 0<=val<=7fffffff) */ +) +{ + Word16 exp; + Word32 L_y; + + exp = norm_l(L_x); + L_x = L_shl(L_x, exp); /* L_x is normalized */ + exp = sub(31, exp); + + L_x = Isqrt_lc(L_x, &exp); + + L_y = L_shl(L_x, exp); /* denormalization */ + + return (L_y); +} + +/*___________________________________________________________________________ + | | + | Function Name : Isqrt_lc | + | | + | Compute 1/sqrt(value). | + | if value is negative or zero, result is 1 (frac=7fffffff, exp=0). | + |---------------------------------------------------------------------------| + | Algorithm: | + | | + | The function 1/sqrt(value) is approximated by a table and linear | + | interpolation. | + | | + | 1- If exponant is odd then shift fraction right once. | + | 2- exponant = -((exponant-1)>>1) | + | 3- i = bit25-b30 of fraction, 16 <= i <= 63 ->because of normalization. | + | 4- a = bit10-b24 | + | 5- i -=16 | + | 6- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2 | + |___________________________________________________________________________| +*/ +Word32 Isqrt_lc( + Word32 frac, /* (i) Q31: normalized value (1.0 < frac <= 0.5) */ + Word16 * exp /* (i/o) : exponent (value = frac x 2^exponent) */ +) +{ + Word16 i, a; + Word32 L_tmp; + + IF (frac <= (Word32) 0) + { + *exp = 0; move16(); + return 0x7fffffff; /*0x7fffffff*/ + } + + /* If exponant odd -> shift right by 10 (otherwise 9) */ + L_tmp = L_shr(frac, shift_Isqrt_lc[s_and(*exp, 1)]); + + /* 1) -16384 to shift left and change sign */ + /* 2) 32768 to Add 1 to Exponent like it was divided by 2 */ + /* 3) We let the mac_r add another 0.5 because it imitates */ + /* the behavior of shr on negative number that should */ + /* not be rounded towards negative infinity. */ + /* It replaces: */ + /* *exp = negate(shr(sub(*exp, 1), 1)); move16(); */ + *exp = mac_r(32768, *exp, -16384); move16(); + + a = extract_l(L_tmp); /* Extract b10-b24 */ + a = lshr(a, 1); + + i = mac_r(L_tmp, -16*2-1, 16384); /* Extract b25-b31 minus 16 */ + + L_tmp = L_msu(L_table_isqrt[i], table_isqrt_diff[i], a);/* table[i] << 16 - diff*a*2 */ + + return L_tmp; +} + +/*___________________________________________________________________________ + | | + | Function Name : Pow2() | + | | + | L_x = pow(2.0, exponant.fraction) (exponant = interger part) | + | = pow(2.0, 0.fraction) << exponant | + |---------------------------------------------------------------------------| + | Algorithm: | + | | + | The function Pow2(L_x) is approximated by a table and linear | + | interpolation. | + | | + | 1- i = bit10-b15 of fraction, 0 <= i <= 31 | + | 2- a = bit0-b9 of fraction | + | 3- L_x = table[i]<<16 - (table[i] - table[i+1]) * a * 2 | + | 4- L_x = L_x >> (30-exponant) (with rounding) | + |___________________________________________________________________________| +*/ + +Word32 Pow2( /* (o) Q0 : result (range: 0<=val<=0x7fffffff) */ + Word16 exponant, /* (i) Q0 : Integer part. (range: 0<=val<=30) */ + Word16 fraction /* (i) Q15 : Fractionnal part. (range: 0.0<=val<1.0) */ +) +{ + Word16 exp, i, a; + Word32 L_x; + + + + i = mac_r(-32768, fraction, 32); /* Extract b10-b16 of fraction */ + a = s_and(fraction, 0x3ff); /* Extract b0-b9 of fraction */ + + L_x = L_deposit_h(table_pow2[i]); /* table[i] << 16 */ + L_x = L_mac(L_x, table_pow2_diff_x32[i], a);/* L_x -= diff*a*2 */ + + exp = sub(30, exponant); + + L_x = L_shr_r(L_x, exp); + + + return L_x; +} + +/*___________________________________________________________________________ + | | + | Function Name : Dot_product12() | + | | + | Compute scalar product of using accumulator. | + | | + | The result is normalized (in Q31) with exponent (0..30). | + |---------------------------------------------------------------------------| + | Algorithm: | + | | + | dot_product = sum(x[i]*y[i]) i=0..N-1 | + |___________________________________________________________________________| +*/ + +Word32 Dot_product12( /* (o) Q31: normalized result (1 < val <= -1) */ + const Word16 x[], /* (i) 12bits: x vector */ + const Word16 y[], /* (i) 12bits: y vector */ + const Word16 lg, /* (i) : vector length */ + Word16 * exp /* (o) : exponent of result (0..+30) */ +) +{ + Word16 i, sft; + Word32 L_sum; + + L_sum = L_mac(1, x[0], y[0]); + FOR (i = 1; i < lg; i++) + L_sum = L_mac(L_sum, x[i], y[i]); + + /* Normalize acc in Q31 */ + + sft = norm_l(L_sum); + L_sum = L_shl(L_sum, sft); + + *exp = sub(30, sft); move16(); /* exponent = 0..30 */ + + return L_sum; +} + +/*___________________________________________________________________________ + | | + | Function Name : Energy_scale() | + | | + | Compute energy of signal (scaling the input if specified) | + | | + | The result is normalized (in Q31) with exponent (0..30). | + |___________________________________________________________________________| +*/ + +Word32 Energy_scale( /* (o) : Q31: normalized result (1 < val <= -1) */ + const Word16 x[], /* (i) : input vector x */ + const Word16 lg, /* (i) : vector length */ + Word16 expi, /* (i) : exponent of input */ + Word16 *exp /* (o) : exponent of result (0..+30) */ +) +{ + Word16 i, sft, tmp; + Word32 L_sum; + + + L_sum = 0; /* just to avoid superflous compiler warning about uninitialized use of L_sum */ + + IF (expi == 0) + { + L_sum = L_mac(1, x[0], x[0]); + FOR (i = 1; i < lg; i++) + { + L_sum = L_mac(L_sum, x[i], x[i]); + } + } + IF (expi < 0) + { + sft = lshl(-32768 /* 0x8000 */, expi); + tmp = mult_r(x[0], sft); + L_sum = L_mac(1, tmp, tmp); + FOR (i = 1; i < lg; i++) + { + tmp = mult_r(x[i], sft); + L_sum = L_mac(L_sum, tmp, tmp); + } + } + IF (expi > 0) + { + tmp = shl(x[0], expi); + L_sum = L_mac(1, tmp, tmp); + FOR (i = 1; i < lg; i++) + { + tmp = shl(x[i], expi); + L_sum = L_mac(L_sum, tmp, tmp); + } + } + + /* Normalize acc in Q31 */ + + sft = norm_l(L_sum); + L_sum = L_shl(L_sum, sft); + + *exp = sub(30, sft); move16(); /* exponent = 0..30 */ + + + return L_sum; +} + +Word32 Sqrt_l( /* o : output value, Q31 */ + Word32 L_x, /* i : input value, Q31 */ + Word16 *exp /* o : right shift to be applied to result, Q1 */ +) +{ + /* + y = sqrt(x) + + x = f * 2^-e, 0.5 <= f < 1 (normalization) + + y = sqrt(f) * 2^(-e/2) + + a) e = 2k --> y = sqrt(f) * 2^-k (k = e div 2, + 0.707 <= sqrt(f) < 1) + b) e = 2k+1 --> y = sqrt(f/2) * 2^-k (k = e div 2, + 0.5 <= sqrt(f/2) < 0.707) + */ + + Word16 e, i, a, tmp; + Word32 L_y; + + if (L_x <= 0) + { + *exp = 0; move16 (); + return L_deposit_l(0); + } + + e = s_and(norm_l(L_x), 0x7FFE); /* get next lower EVEN norm. exp */ + L_x = L_shl(L_x, e); /* L_x is normalized to [0.25..1) */ + *exp = e; move16 (); /* return 2*exponent (or Q1) */ + + L_x = L_shr(L_x, 9); + a = extract_l(L_x); /* Extract b10-b24 */ + a = lshr(a, 1); + + i = mac_r(L_x, -16*2-1, 16384); /* Extract b25-b31 minus 16 */ + + L_y = L_deposit_h(sqrt_table[i]); /* table[i] << 16 */ + tmp = sub(sqrt_table[i], sqrt_table[i + 1]); /* table[i] - table[i+1]) */ + L_y = L_msu(L_y, tmp, a); /* L_y -= tmp*a*2 */ + + /* L_y = L_shr (L_y, *exp); */ /* denormalization done by caller */ + + return (L_y); +} + +/*---------------------------------------------------------------------------* + * L_Frac_sqrtQ31 + * + * Calculate square root from fractional values (Q31 -> Q31) + * Uses 32 bit internal representation for precision + *---------------------------------------------------------------------------*/ +Word32 L_Frac_sqrtQ31( /* o : Square root if input */ + const Word32 x /* i : Input */ +) +{ + Word32 log2_work; + Word16 log2_int, log2_frac; + + test(); + if (x > 0) + { + log2_int = norm_l(x); + log2_frac = Log2_norm_lc(L_shl(x, log2_int)); + + log2_work = L_msu((31+30)*65536L/2, 16384, log2_int); + log2_work = L_mac0(log2_work, log2_frac, 1); + + log2_frac = L_Extract_lc(log2_work, &log2_int); + + return Pow2(log2_int, log2_frac); + } + return 0; +} + +/*----------------------------------------------------------------------------------* + * Frac_sqrt + * + * Calculate square root from fractional values (Q15 -> Q15) + *----------------------------------------------------------------------------------*/ +Word16 Frac_sqrt( /* o : Square root if input */ + const Word16 x /* i : Input */ +) +{ + return round_fx(L_Frac_sqrtQ31(L_deposit_h(x))); +} + + +/*----------------------------------------------------------------------------------* + * i_mult2 + * + * Faster Integer Multiplication + *----------------------------------------------------------------------------------*/ + +Word16 i_mult2 (Word16 a, Word16 b) +{ + return extract_l(L_mult0(a, b)); +} + + + diff --git a/basic_math/math_op.h b/basic_math/math_op.h new file mode 100644 index 0000000..9a17485 --- /dev/null +++ b/basic_math/math_op.h @@ -0,0 +1,48 @@ +/*--------------------------------------------------------------------------* + * MATH_OP.H * + *--------------------------------------------------------------------------* + * Mathematical operations * + *--------------------------------------------------------------------------*/ +#include "oper_32b.h" +#include "log2.h" + +Word32 Isqrt( /* (o) Q31 : output value (range: 0<=val<1) */ + Word32 L_x /* (i) Q0 : input value (range: 0<=val<=7fffffff) */ +); +Word32 Isqrt_lc( + Word32 frac, /* (i/o) Q31: normalized value (1.0 < frac <= 0.5) */ + Word16 * exp /* (i/o) : exponent (value = frac x 2^exponent) */ +); + +Word32 Pow2( /* (o) Q0 : result (range: 0<=val<=0x7fffffff) */ + Word16 exponant, /* (i) Q0 : Integer part. (range: 0<=val<=30) */ + Word16 fraction /* (i) Q15 : Fractionnal part. (range: 0.0<=val<1.0) */ +); +Word32 Dot_product12( /* (o) Q31: normalized result (1 < val <= -1) */ + const Word16 x[], /* (i) 12bits: x vector */ + const Word16 y[], /* (i) 12bits: y vector */ + const Word16 lg, /* (i) : vector length */ + Word16 * exp /* (o) : exponent of result (0..+30) */ +); + +Word32 Energy_scale( /* (o) Q31: normalized result (1 < val <= -1) */ + const Word16 x[], /* (i) 12bits: x vector */ + const Word16 lg, /* (i) : vector length */ + Word16 expi, /* (i) : exponent of input */ + Word16 *exp /* (o) : exponent of result (0..+30) */ +); + +Word32 Sqrt_l(Word32 L_x, Word16 *exp); + +Word32 L_Frac_sqrtQ31( /* o : Square root if input */ + const Word32 x /* i : Input */ +); + +Word16 Frac_sqrt( /* o : Square root if input */ + const Word16 x /* i : Input */ +); + +Word16 i_mult2 (Word16 a, Word16 b); + +#include "math_32.h" + diff --git a/basic_math/oper_32b.c b/basic_math/oper_32b.c new file mode 100644 index 0000000..1904cdd --- /dev/null +++ b/basic_math/oper_32b.c @@ -0,0 +1,381 @@ +/***************************************************************************** + * $Id: oper_32b.c 1094 2014-02-10 17:12:11Z jdr $ + * + * This file contains operations in double precision. * + * These operations are not standard double precision operations. * + * They are used where single precision is not enough but the full 32 bits * + * precision is not necessary. For example, the function Div_32() has a * + * 24 bits precision which is enough for our purposes. * + * * + * The double precision numbers use a special representation: * + * * + * L_32 = hi<<16 + lo<<1 * + * * + * L_32 is a 32 bit integer. * + * hi and lo are 16 bit signed integers. * + * As the low part also contains the sign, this allows fast multiplication. * + * * + * 0x8000 0000 <= L_32 <= 0x7fff fffe. * + * * + * We will use DPF (Double Precision Format) in this file to specify * + * this special format. * + ***************************************************************************** +*/ + +#include "stl.h" +#include "math_op.h" + +/***************************************************************************** + * * + * Function L_Extract() * + * * + * Extract from a 32 bit integer two 16 bit DPF. * + * * + * Arguments: * + * * + * L_32 : 32 bit integer. * + * 0x8000 0000 <= L_32 <= 0x7fff ffff. * + * hi : b16 to b31 of L_32 * + * lo : (L_32 - hi<<16)>>1 * + ***************************************************************************** +*/ + +void L_Extract (Word32 L_32, Word16 *hi, Word16 *lo) +{ + *hi = extract_h (L_32); + *lo = extract_l (L_msu (L_shr (L_32, 1), *hi, 16384)); + return; +} + +/***************************************************************************** + * * + * Function L_Extract_lc() * + * * + * Extract from a 32 bit integer two 16 bit DPF. * + * (lo is returned, store to memory is not accounted for) * + * * + * Arguments: * + * * + * L_32 : 32 bit integer. * + * 0x8000 0000 <= L_32 <= 0x7fff ffff. * + * hi : b16 to b31 of L_32 * + * lo : (L_32 - hi<<16)>>1 * + ***************************************************************************** +*/ + +Word16 L_Extract_lc (Word32 L_32, Word16 *hi) +{ + *hi = extract_h (L_32); + + return lshr(extract_l(L_32), 1); +} + +/***************************************************************************** + * * + * Function L_Comp() * + * * + * Compose from two 16 bit DPF a 32 bit integer. * + * * + * L_32 = hi<<16 + lo<<1 * + * * + * Arguments: * + * * + * hi msb * + * lo lsf (with sign) * + * * + * Return Value : * + * * + * 32 bit long signed integer (Word32) whose value falls in the * + * range : 0x8000 0000 <= L_32 <= 0x7fff fff0. * + * * + ***************************************************************************** +*/ + +Word32 L_Comp (Word16 hi, Word16 lo) +{ + Word32 L_32; + + L_32 = L_deposit_h (hi); + return (L_mac (L_32, lo, 1)); /* = hi<<16 + lo<<1 */ +} + +/***************************************************************************** + * Function Mpy_32() * + * * + * Multiply two 32 bit integers (DPF). The result is divided by 2**31 * + * * + * L_32 = (hi1*hi2)<<1 + ( (hi1*lo2)>>15 + (lo1*hi2)>>15 )<<1 * + * * + * This operation can also be viewed as the multiplication of two Q31 * + * number and the result is also in Q31. * + * * + * Arguments: * + * * + * hi1 hi part of first number * + * lo1 lo part of first number * + * hi2 hi part of second number * + * lo2 lo part of second number * + * * + ***************************************************************************** +*/ + +Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2) +{ + Word32 L_32; + + L_32 = L_mult (hi1, hi2); + L_32 = L_mac (L_32, mult (hi1, lo2), 1); + L_32 = L_mac (L_32, mult (lo1, hi2), 1); + + return (L_32); +} + +/***************************************************************************** + * Function Mac_32() * + * * + * Multiply two 32 bit integers (DPF). The result is divided by 2**31 * + * Adds a 32 bit integer (non DFP) * + * * + * L_32 = L_num + (hi1*hi2)<<1 + ( (hi1*lo2)>>15 + (lo1*hi2)>>15 )<<1 * + * * + * This operation can also be viewed as the multiplication of two Q31 * + * number and the result is also in Q31. * + * * + * Arguments: * + * * + * hi1 hi part of first number * + * lo1 lo part of first number * + * hi2 hi part of second number * + * lo2 lo part of second number * + * * + ***************************************************************************** +*/ + +Word32 Mac_32 (Word32 L_num, Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2) +{ + Word32 L_32; + + L_32 = L_mac (L_num, hi1, hi2); + L_32 = L_mac (L_32, mult (hi1, lo2), 1); + L_32 = L_mac (L_32, mult (lo1, hi2), 1); + + return (L_32); +} + +/***************************************************************************** + * Function Sqr_32() * + * * + * Square one 32 bit integer (DPF). The result is divided by 2**31 * + * * + * L_32 = (hi*hi)<<1 + ( (hi*lo)>>15 *2)<<1 * + * * + * This operation can also be viewed as the square of one Q31 * + * number and the result is also in Q31. * + * * + * Arguments: * + * * + * hi1 hi part of first number * + * lo1 lo part of first number * + * hi2 hi part of second number * + * lo2 lo part of second number * + * * + ***************************************************************************** +*/ + +Word32 Sqr_32 (Word16 hi, Word16 lo) +{ + Word32 L_32; + + L_32 = L_mult (hi, hi); + L_32 = L_mac (L_32, mult (hi, lo), 2); + + return (L_32); +} + +/***************************************************************************** + * Function Sad_32() * + * * + * Square one 32 bit integer (DPF). The result is divided by 2**31 * + * Adds a 32 bit integer (non DFP) * + * * + * L_32 = L_num + (hi*hi)<<1 + ( (hi*lo)>>15 *2)<<1 * + * * + * This operation can also be viewed as the square of one Q31 * + * number and the result is also in Q31. * + * * + * Arguments: * + * * + * hi1 hi part of first number * + * lo1 lo part of first number * + * hi2 hi part of second number * + * lo2 lo part of second number * + * * + ***************************************************************************** +*/ + +Word32 Sad_32 (Word32 L_num, Word16 hi, Word16 lo) +{ + Word32 L_32; + + L_32 = L_mac (L_num, hi, hi); + L_32 = L_mac (L_32, mult (hi, lo), 2); + + return (L_32); +} + +/***************************************************************************** + * Function Mpy_32_16() * + * * + * Multiply a 16 bit integer by a 32 bit (DPF). The result is divided * + * by 2**15 * + * * + * * + * L_32 = (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1 * + * * + * Arguments: * + * * + * hi hi part of 32 bit number. * + * lo lo part of 32 bit number. * + * n 16 bit number. * + * * + ***************************************************************************** +*/ + +Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n) +{ + Word32 L_32; + + L_32 = L_mult (hi, n); + L_32 = L_mac (L_32, mult (lo, n), 1); + + return (L_32); +} + +/***************************************************************************** + * Function Mac_32_16() * + * * + * Multiply a 16 bit integer by a 32 bit (DPF). The result is divided * + * by 2**15 * + * Adds a 32 bit integer (non DFP) * + * * + * * + * L_32 = L_num + (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1 * + * * + * Arguments: * + * * + * L_num 32 bit long signed integer (Word32) * + * hi hi part of 32 bit number. * + * lo lo part of 32 bit number. * + * n 16 bit number. * + * * + ***************************************************************************** +*/ + +Word32 Mac_32_16 (Word32 L_num, Word16 hi, Word16 lo, Word16 n) +{ + Word32 L_32; + + L_32 = L_mac (L_num, hi, n); + L_32 = L_mac (L_32, mult (lo, n), 1); + + return (L_32); +} + +/***************************************************************************** + * Function Msu_32_16() * + * * + * Substract a 32 bit integer (non DFP) * + * Multiply a 16 bit integer by a 32 bit (DPF). The result is divided * + * by 2**15 * + * * + * * + * L_32 = L_num - (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1 * + * * + * Arguments: * + * * + * L_num 32 bit long signed integer (Word32) * + * hi hi part of 32 bit number. * + * lo lo part of 32 bit number. * + * n 16 bit number. * + * * + ***************************************************************************** +*/ + +Word32 Msu_32_16 (Word32 L_num, Word16 hi, Word16 lo, Word16 n) +{ + Word32 L_32; + + L_32 = L_msu (L_num, hi, n); + L_32 = L_msu (L_32, mult (lo, n), 1); + + return (L_32); +} + +/***************************************************************************** + * * + * Function Name : Div_32 * + * * + * Purpose : * + * Fractional integer division of two 32 bit numbers. * + * L_num / L_denom. * + * L_num and L_denom must be positive and L_num < L_denom. * + * L_denom = denom_hi<<16 + denom_lo<<1 * + * denom_hi is a normalize number. * + * * + * Inputs : * + * * + * L_num * + * 32 bit long signed integer (Word32) whose value falls in the * + * range : 0x0000 0000 < L_num < L_denom * + * * + * L_denom = denom_hi<<16 + denom_lo<<1 (DPF) * + * * + * denom_hi * + * 16 bit positive normalized integer whose value falls in the * + * range : 0x4000 < hi < 0x7fff * + * denom_lo * + * 16 bit positive integer whose value falls in the * + * range : 0 < lo < 0x7fff * + * * + * Return Value : * + * * + * L_div * + * 32 bit long signed integer (Word32) whose value falls in the * + * range : 0x0000 0000 <= L_div <= 0x7fff ffff. * + * * + * Algorithm: * + * * + * - find = 1/L_denom. * + * First approximation: approx = 1 / denom_hi * + * 1/L_denom = approx * (2.0 - L_denom * approx ) * + * * + * - result = L_num * (1/L_denom) * + ***************************************************************************** +*/ + +Word32 Div_32 (Word32 L_num, Word16 denom_hi, Word16 denom_lo) +{ + Word16 approx, hi, lo, n_hi, n_lo; + Word32 L_32; + + /* First approximation: 1 / L_denom = 1/denom_hi */ + + approx = div_s ((Word16) 0x3fff, denom_hi); + + /* 1/L_denom = approx * (2.0 - L_denom * approx) */ + + L_32 = Msu_32_16 ((Word32) 0x7fffffffL, denom_hi, denom_lo, approx); + + lo = L_Extract_lc (L_32, &hi); + L_32 = Mpy_32_16 (hi, lo, approx); + + /* L_num * (1/L_denom) */ + + lo = L_Extract_lc (L_32, &hi); + n_lo = L_Extract_lc (L_num, &n_hi); + L_32 = Mpy_32 (n_hi, n_lo, hi, lo); + L_32 = L_shl (L_32, 2); + + return (L_32); +} + diff --git a/basic_math/oper_32b.h b/basic_math/oper_32b.h new file mode 100644 index 0000000..70d1c59 --- /dev/null +++ b/basic_math/oper_32b.h @@ -0,0 +1,18 @@ +/* Double precision operations */ +/* $Id: oper_32b.h 1094 2014-02-10 17:12:11Z jdr $ */ +#ifndef _OPER_32b_H +#define _OPER_32b_H + +void L_Extract (Word32 L_32, Word16 *hi, Word16 *lo); +Word16 L_Extract_lc (Word32 L_32, Word16 *hi); +Word32 L_Comp (Word16 hi, Word16 lo); +Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2); +Word32 Mac_32 (Word32 L_num, Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2); +Word32 Sqr_32 (Word16 hi, Word16 lo); +Word32 Sad_32 (Word32 L_num, Word16 hi, Word16 lo); +Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n); +Word32 Mac_32_16 (Word32 L_num, Word16 hi, Word16 lo, Word16 n); +Word32 Msu_32_16 (Word32 L_num, Word16 hi, Word16 lo, Word16 n); +Word32 Div_32 (Word32 L_num, Word16 denom_hi, Word16 denom_lo); + +#endif diff --git a/basic_math/rom_basic_math.c b/basic_math/rom_basic_math.c new file mode 100644 index 0000000..8c81378 --- /dev/null +++ b/basic_math/rom_basic_math.c @@ -0,0 +1,91 @@ +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Decoder static structure */ +#include "stl.h" + +/* math_op.c */ +const Word32 L_table_isqrt[48] = +{ + 2147418112L, 2083389440L, 2024669184L, 1970667520L, + 1920794624L, 1874460672L, 1831403520L, 1791098880L, + 1753415680L, 1717960704L, 1684602880L, 1653145600L, + 1623326720L, 1595080704L, 1568276480L, 1542782976L, + 1518469120L, 1495334912L, 1473183744L, 1451950080L, + 1431633920L, 1412169728L, 1393491968L, 1375469568L, + 1358168064L, 1341521920L, 1325465600L, 1309933568L, + 1294991360L, 1280507904L, 1266548736L, 1252982784L, + 1239875584L, 1227161600L, 1214775296L, 1202847744L, + 1191182336L, 1179910144L, 1168965632L, 1158283264L, + 1147863040L, 1137770496L, 1127940096L, 1118306304L, + 1108934656L, 1099825152L, 1090912256L, 1082261504L +}; + +/* table of table_isqrt[i] - table_isqrt[i+1] */ +const Word16 table_isqrt_diff[48] = +{ + 977, 896, 824, 761, 707, 657, 615, 575, + 541, 509, 480, 455, 431, 409, 389, 371, + 353, 338, 324, 310, 297, 285, 275, 264, + 254, 245, 237, 228, 221, 213, 207, 200, + 194, 189, 182, 178, 172, 167, 163, 159, + 154, 150, 147, 143, 139, 136, 132, 130 +}; + +const Word16 shift_Isqrt_lc[] = {9,10}; + +const Word16 table_pow2[32] = +{ + 16384, 16743, 17109, 17484, 17867, 18258, 18658, 19066, 19484, 19911, + 20347, 20792, 21247, 21713, 22188, 22674, 23170, 23678, 24196, 24726, + 25268, 25821, 26386, 26964, 27554, 28158, 28774, 29405, 30048, 30706, + 31379, 32066 +}; + +/* table of table_pow2[i+1] - table_pow2[i] */ +const Word16 table_pow2_diff_x32[32] = +{ + 11488, 11712, 12000, 12256, 12512, 12800, 13056, 13376, 13664, 13952, + 14240, 14560, 14912, 15200, 15552, 15872, 16256, 16576, 16960, 17344, + 17696, 18080, 18496, 18880, 19328, 19712, 20192, 20576, 21056, 21536, + 21984, 22432 +}; + +const Word16 sqrt_table[49] = +{ + 16384, 16888, 17378, 17854, 18318, 18770, 19212, + 19644, 20066, 20480, 20886, 21283, 21674, 22058, + 22435, 22806, 23170, 23530, 23884, 24232, 24576, + 24915, 25249, 25580, 25905, 26227, 26545, 26859, + 27170, 27477, 27780, 28081, 28378, 28672, 28963, + 29251, 29537, 29819, 30099, 30377, 30652, 30924, + 31194, 31462, 31727, 31991, 32252, 32511, 32767 +}; + +/* log2.c */ +const Word32 L_table_Log2_norm_lc[32] = +{ + -32768L, 95322112L, 187793408L, 277577728L, + 364871680L, 449740800L, 532381696L, 612859904L, + 691306496L, 767787008L, 842432512L, 915308544L, + 986546176L, 1056210944L, 1124302848L, 1190887424L, + 1256095744L, 1319993344L, 1382580224L, 1443921920L, + 1504083968L, 1563131904L, 1621000192L, 1677885440L, + 1733722112L, 1788510208L, 1842380800L, 1895399424L, + 1947435008L, 1998618624L, 2049015808L, 2098626560L +}; + +const Word16 table_diff_Log2_norm_lc[32] = +{ + 1455, 1411, 1370, 1332, 1295, 1261, 1228, 1197, + 1167, 1139, 1112, 1087, 1063, 1039, 1016, 995, + 975, 955, 936, 918, 901, 883, 868, 852, + 836, 822, 809, 794, 781, 769, 757, 744 +}; + +const Word16 log2_tab[33]={ + 0x7800, 0x782D, 0x785A, 0x7884, 0x78AE, 0x78D6, 0x78FE, 0x7924, + 0x794A, 0x796E, 0x7992, 0x79B4, 0x79D6, 0x79F8, 0x7A18, 0x7A38, + 0x7A57, 0x7A75, 0x7A93, 0x7AB1, 0x7ACD, 0x7AE9, 0x7B05, 0x7B20, + 0x7B3B, 0x7B55, 0x7B6F, 0x7B88, 0x7BA1, 0x7BB9, 0x7BD1, 0x7BE9, + 0x7C00 +}; + diff --git a/basic_math/rom_basic_math.h b/basic_math/rom_basic_math.h new file mode 100644 index 0000000..f39ea84 --- /dev/null +++ b/basic_math/rom_basic_math.h @@ -0,0 +1,26 @@ +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Decoder static structure */ +#include "stl.h" + + +/* math_op.c */ +extern const Word32 L_table_isqrt[48]; + +/* table of table_isqrt[i] - table_isqrt[i+1] */ +extern const Word16 table_isqrt_diff[48]; + +extern const Word16 shift_Isqrt_lc[]; + +extern const Word16 table_pow2[32]; + +/* table of table_pow2[i+1] - table_pow2[i] */ +extern const Word16 table_pow2_diff_x32[32]; + +extern const Word16 sqrt_table[49]; + +/* log2.c */ +extern const Word32 L_table_Log2_norm_lc[32]; + +extern const Word16 table_diff_Log2_norm_lc[32]; + +extern const Word16 log2_tab[33]; diff --git a/basic_op/README.md b/basic_op/README.md new file mode 100644 index 0000000..47ff87c --- /dev/null +++ b/basic_op/README.md @@ -0,0 +1,101 @@ + + Read-me for ITU-T/UGST Basic Operator Module V.2.3 + (30.Nov.2009) + + ============================================================= + COPYRIGHT NOTE: This source code, and all of its derivations, + is subject to the "ITU-T General Public License". Please have + it read in the distribution disk, or in the ITU-T + Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO + CODING STANDARDS". + ============================================================= + +# Changes v.2.2 --> v.2.3 + +Modifications in `basop32.c` and `basop32.h` +- Function `round()` is now named `round_fx()`, to avoid clashes with +standard C library. +- Function `saturate()` is made unreferencable from outside application. + +Added new functionalities: +- Basic operator counter utility: `basop_cnt.c` +- Complexity evaluation tool for floating-point: `flc.h`, `flc.c` + +# Changes v.2.1 --> v.2.2 + +New functions in `count.c`: +- `void setFrameRate(int samplingFreq, int frameLength);` + + This function can overwrite the value of the frameRate variable + that is initialized by the `FRAME_RATE` constant. + +- `void WMOPS_output_avg (Word16 dtx_mode, Word32 *tot_wm, Word16 *num_frames);` + + Same as `WMOPS_output` + returns the total wmops counter and the number of frames + to support the computation of advanced complexity results as the global average. + +An example of the use of `WMOPS_output_avg` is given below: + +In a decoder, the `spe1Id` was used for valid frames while the `spe2Id` counter was used for erased frames. +Using the `WMOPS_output_avg` the global average complexity can be also displayed : + + short spe1Id = getCounterId("Valid frames"); + short spe2Id = getCounterId("Bad frames"); + long tot_wm1; + short num_frames1; + long tot_wm2; + short num_frames2; + + ... + + setCounter(spe1Id); + fwc(); + WMOPS_output_avg(0, &tot_wm1, &num_frames1); + setCounter(spe2Id); + fwc(); + WMOPS_output_avg(0, &tot_wm2, &num_frames2); + printf("Global average %f WMOPS\n", (tot_wm1 + tot_wm2)/(float)(num_frames1 + num_frames2)); + + Modifications in count.c: + - L_mls() is weighted 5. + - div_l() is weighted 32. + - i_mult() is weighted 3. + +# Changes v.2.0 --> v.2.1 + +Improved portability: +- in header files `__inline` was changed to `static __inline` +- `//` style comments were changed to `/* */` +- Cygwin added in the supported compiler list (`typedef.h`) +- Word40 definition was added for Sun and Unix (`typedef.h`) + +Corrections: +- missing incrementations were added for `s_and`, `s_or` and `s_xor` (`enh1632.h`) + +# Original version: v.2.0 + +The ITU-T/UGST Basic Operator module contains the following files: + +## C code: (`model` directory) + + basop32.c: ....... 16/32 bit basic operators + basop32.h: ....... Prototypes for basop32.c + count.c: ......... Functions for WMOPS computation + count.h: ......... Prototypes for count.c + typedef.h: ....... Data type definitions + typedefs.h: ...... New data type definitions + move.h: .......... Move & miscellaneous legacy operators + control.c: ....... Control operator internal variable decl. + control.h: ....... Control operators + enh1632.c: ....... Enhanced 16/32 bit basic operators + enh1632.h: ....... Prototypes for enh1632.c + enh40.c: ......... 40 bit basic operators + enh40.h: ......... Prototypes for enh40.c + patch.h: ......... Backward compatibility for operator names + stl.h: ........... Main header file + +## Demos: + +Demo programs are not available for this module. + +-- diff --git a/basic_op/basop.rme b/basic_op/basop.rme new file mode 100644 index 0000000..361ebc4 --- /dev/null +++ b/basic_op/basop.rme @@ -0,0 +1,120 @@ + + Read-me for ITU-T/UGST Basic Operator Module V.2.3 + (30.Nov.2009) + + ============================================================= + COPYRIGHT NOTE: This source code, and all of its derivations, + is subject to the "ITU-T General Public License". Please have + it read in the distribution disk, or in the ITU-T + Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO + CODING STANDARDS". + ============================================================= + +Changes v.2.2 --> v.2.3 +*********************** + +Modifications in basop32.c and basop32.h + - Function round() is now named round_fx(), to avoid clashes with + standard C library. + - Function saturate() is made unreferencable from outside application. + +Added new functionalities: + - Basic operator counter utility: basop_cnt.c + - Complexity evaluation tool for floating-point: flc.h, flc.c + +Changes v.2.1 --> v.2.2 +*********************** + +New functions in count.c: + - void setFrameRate(int samplingFreq, int frameLength); + This function can overwrite the value of the frameRate variable + that is initialized by the FRAME_RATE constant. + - void WMOPS_output_avg (Word16 dtx_mode, Word32 *tot_wm, Word16 *num_frames); + same as WMOPS_output + returns the total wmops counter and the number of frames + to support the computation of advanced complexity results as the global average. + +An example of the use of WMOPS_output_avg is given below: + +In a decoder, the spe1Id was used for valid frames while the spe2Id counter was used for erased frames. +Using the WMOPS_output_avg the global average complexity can be also displayed : + +short spe1Id = getCounterId("Valid frames"); +short spe2Id = getCounterId("Bad frames"); +long tot_wm1; +short num_frames1; +long tot_wm2; +short num_frames2; + +... + +setCounter(spe1Id); +fwc(); +WMOPS_output_avg(0, &tot_wm1, &num_frames1); +setCounter(spe2Id); +fwc(); +WMOPS_output_avg(0, &tot_wm2, &num_frames2); +printf("Global average %f WMOPS\n", (tot_wm1 + tot_wm2)/(float)(num_frames1 + num_frames2)); + +Modifications in count.c: + - L_mls() is weighted 5. + - div_l() is weighted 32. + - i_mult() is weighted 3. + +Changes v.2.0 --> v.2.1 +*********************** + +Improved portability: + - in header files "__inline" was changed to "static __inline" + - // style comments were changed to /* */ + - Cygwin added in the supported compiler list (typedef.h) + - Word40 definition was added for Sun and Unix (typedef.h) +Corrections: + - missing incrementations were added for s_and, s_or and s_xor (enh1632.h) + + + +Original version: v.2.0 +*********************** + +The ITU-T/UGST Basic Operator module contails the following files: + +General: +~~~~~~~~ + basop.rme: ....... Read-me file for Basic Operator module (this file) + +C code: ('model' directory) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + basop32.c: ....... 16/32 bit basic operators + basop32.h: ....... Prototypes for basop32.c + count.c: ......... Functions for WMOPS computation + count.h: ......... Prototypes for count.c + typedef.h: ....... Data type definitions + typedefs.h: ...... New data type definitions + move.h: .......... Move & miscellaneous legacy operators + control.c: ....... Control operator internal variable decl. + control.h: ....... Control operators + enh1632.c: ....... Enhanced 16/32 bit basic operators + enh1632.h: ....... Prototypes for enh1632.c + enh40.c: ......... 40 bit basic operators + enh40.h: ......... Prototypes for enh40.c + patch.h: ......... Backward compatibility for operator names + stl.h: ........... Main header file + enh64.c: ......... 64 bit basic operators + enh64.h: ......... Prototypes for enh64.c + enh32.c: ......... Extension to enhanced 32 bit operators + enh32.h: ......... Prototypes for enh32.c + complex_basop.c: ... 32/16 complex basic operators + complex_basop.h: ... Prototypes for complex_basop.c + +Demos: +~~~~~~ +Demo programs are not available for this module. + + +Makefiles +~~~~~~~~~ +Make files are not available for this module. + + +-- + diff --git a/basic_op/basop32.c b/basic_op/basop32.c new file mode 100644 index 0000000..b83cd21 --- /dev/null +++ b/basic_op/basop32.c @@ -0,0 +1,2429 @@ +/* v.2.3 - 30.Nov.2009 + ============================================================================= + + U U GGG SSSS TTTTT + U U G S T + U U G GG SSSS T + U U G G S T + UUU GG SSS T + + ======================================== + ITU-T - USER'S GROUP ON SOFTWARE TOOLS + ======================================== + + ============================================================= + COPYRIGHT NOTE: This source code, and all of its derivations, + is subject to the "ITU-T General Public License". Please have + it read in the distribution disk, or in the ITU-T + Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO + CODING STANDARDS". + ============================================================= + +MODULE: BASOP32, BASIC OPERATORS + +ORIGINAL BY: + Incorporated from anonymous contributions for + ETSI Standards as well as G.723.1, G.729, and G.722.1 + +DESCRIPTION: + This file contains the definition of 16- and 32-bit basic + operators to be used in the implementation of signal + processing algorithms. The basic operators try to resemble + assembly language instructions that are commonly found in + digital signal processor (DSP) CPUs, thus allowing algorithm + C-code implementations more directly mapeable to DSP assembly + code. + + ********************************************************* + NOTE: so far, this module does not have a demo program! + ********************************************************* + +FUNCTIONS: + Defined in basop32.h. Self-documentation within each function. + +HISTORY: + 26.Jan.00 v1.0 Incorporated to the STL from updated G.723.1/G.729 + basic operator library (based on basicop2.c) and + G.723.1's basop.c [L_mls(), div_l(), i_mult()] + + 05.Jul.00 v1.1 Added 32-bit shiftless accumulation basic + operators (L_msu0, L_mac0, L_mult0). Improved + documentation for i_mult(). + + 03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control + operators for the ITU-T Standard Tool Library as + described in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + TD 11 document and subsequent discussions on the + wp3audio@yahoogroups.com email reflector. + norm_s() weight reduced from 15 to 1. + norm_l() weight reduced from 30 to 1. + L_abs() weight reduced from 2 to 1. + L_add() weight reduced from 2 to 1. + L_negate() weight reduced from 2 to 1. + L_shl() weight reduced from 2 to 1. + L_shr() weight reduced from 2 to 1. + L_sub() weight reduced from 2 to 1. + mac_r() weight reduced from 2 to 1. + msu_r() weight reduced from 2 to 1. + mult_r() weight reduced from 2 to 1. + L_deposit_h() weight reduced from 2 to 1. + L_deposit_l() weight reduced from 2 to 1. + L_mls() weight of 5. + div_l() weight of 32. + i_mult() weight of 3. + + 30 Nov 09 v2.3 round() function is now round_fx(). + saturate() is not referencable from outside application + ============================================================================= +*/ + + +/*___________________________________________________________________________ + | | + | Basic arithmetic operators. | + | | + | $Id $ | + | | + | saturate() | + | add() | + | sub() | + | abs_s() | + | divide_s() | + | extract_h() | + | extract_l() | + | L_abs() | + | L_add() | + | L_deposit_h() | + | L_deposit_l() | + | L_mac() | + | L_msu() | + | L_mult() | + | L_negate() | + | L_shl() | + | L_shr() | + | L_sub() | + | mac_r() | + | msu_r() | + | mult() | + | mult_r() | + | negate() | + | norm_l() | + | norm_s() | + | round_fx() | + | shl() | + | shr() | + |___________________________________________________________________________| +*/ + + +/*___________________________________________________________________________ + | | + | Include-Files | + |___________________________________________________________________________| +*/ +#include +#include +#include "stl.h" + + +#if (WMOPS) +extern BASIC_OP multiCounter[MAXCOUNTERS]; +extern int currCounter; +#endif + + +/*___________________________________________________________________________ + | | + | Local Functions | + |___________________________________________________________________________| +*/ +static Word16 saturate (Word32 L_var1); + + +/*___________________________________________________________________________ + | | + | Constants and Globals | + |___________________________________________________________________________| +*/ +Flag Overflow = 0; +Flag Carry = 0; + + +/*___________________________________________________________________________ + | | + | Functions | + |___________________________________________________________________________| +*/ + +/*___________________________________________________________________________ + | | + | Function Name : saturate | + | | + | Purpose : | + | | + | Limit the 32 bit input to the range of a 16 bit word. Must NOT be | + | referenced from outside applications. | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +static Word16 saturate (Word32 L_var1) { + Word16 var_out; + + if (L_var1 > 0X00007fffL) { + Overflow = 1; + var_out = MAX_16; + } else if (L_var1 < (Word32) 0xffff8000L) { + Overflow = 1; + var_out = MIN_16; + } else { + var_out = extract_l (L_var1); +#if (WMOPS) + multiCounter[currCounter].extract_l--; +#endif + } + + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : add | + | | + | Purpose : | + | | + | Performs the addition (var1+var2) with overflow control and saturation;| + | the 16 bit result is set at +32767 when overflow occurs or at -32768 | + | when underflow occurs. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +Word16 add (Word16 var1, Word16 var2) { + Word16 var_out; + Word32 L_sum; + + L_sum = (Word32) var1 + var2; + var_out = saturate (L_sum); + +#if (WMOPS) + multiCounter[currCounter].add++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : sub | + | | + | Purpose : | + | | + | Performs the subtraction (var1+var2) with overflow control and satu- | + | ration; the 16 bit result is set at +32767 when overflow occurs or at | + | -32768 when underflow occurs. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +Word16 sub (Word16 var1, Word16 var2) { + Word16 var_out; + Word32 L_diff; + + L_diff = (Word32) var1 - var2; + var_out = saturate (L_diff); + +#if (WMOPS) + multiCounter[currCounter].sub++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : abs_s | + | | + | Purpose : | + | | + | Absolute value of var1; abs_s(-32768) = 32767. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +Word16 abs_s (Word16 var1) { + Word16 var_out; + + if (var1 == (Word16) MIN_16) { + var_out = MAX_16; + } else { + if (var1 < 0) { + var_out = -var1; + } else { + var_out = var1; + } + } + +#if (WMOPS) + multiCounter[currCounter].abs_s++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : shl | + | | + | Purpose : | + | | + | Arithmetically shift the 16 bit input var1 left var2 positions.Zero fill| + | the var2 LSB of the result. If var2 is negative, arithmetically shift | + | var1 right by -var2 with sign extension. Saturate the result in case of | + | underflows or overflows. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +Word16 shl (Word16 var1, Word16 var2) { + Word16 var_out; + Word32 result; + + if (var2 < 0) { + if (var2 < -16) + var2 = -16; + var2 = -var2; + var_out = shr (var1, var2); + +#if (WMOPS) + multiCounter[currCounter].shr--; +#endif + } else { + result = (Word32) var1 *((Word32) 1 << var2); + + if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result))) { + Overflow = 1; + var_out = (var1 > 0) ? MAX_16 : MIN_16; + } else { + var_out = extract_l (result); + +#if (WMOPS) + multiCounter[currCounter].extract_l--; +#endif + } + } + +#if (WMOPS) + multiCounter[currCounter].shl++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : shr | + | | + | Purpose : | + | | + | Arithmetically shift the 16 bit input var1 right var2 positions with | + | sign extension. If var2 is negative, arithmetically shift var1 left by | + | -var2 with sign extension. Saturate the result in case of underflows or | + | overflows. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +Word16 shr (Word16 var1, Word16 var2) { + Word16 var_out; + + if (var2 < 0) { + if (var2 < -16) + var2 = -16; + var2 = -var2; + var_out = shl (var1, var2); + +#if (WMOPS) + multiCounter[currCounter].shl--; +#endif + } else { + if (var2 >= 15) { + var_out = (var1 < 0) ? -1 : 0; + } else { + if (var1 < 0) { + var_out = ~((~var1) >> var2); + } else { + var_out = var1 >> var2; + } + } + } + +#if (WMOPS) + multiCounter[currCounter].shr++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : mult | + | | + | Purpose : | + | | + | Performs the multiplication of var1 by var2 and gives a 16 bit result | + | which is scaled i.e.: | + | mult(var1,var2) = extract_l(L_shr((var1 times var2),15)) and | + | mult(-32768,-32768) = 32767. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +Word16 mult (Word16 var1, Word16 var2) { + Word16 var_out; + Word32 L_product; + + L_product = (Word32) var1 *(Word32) var2; + + L_product = (L_product & (Word32) 0xffff8000L) >> 15; + + if (L_product & (Word32) 0x00010000L) + L_product = L_product | (Word32) 0xffff0000L; + + var_out = saturate (L_product); + +#if (WMOPS) + multiCounter[currCounter].mult++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_mult | + | | + | Purpose : | + | | + | L_mult is the 32 bit result of the multiplication of var1 times var2 | + | with one shift left i.e.: | + | L_mult(var1,var2) = L_shl((var1 times var2),1) and | + | L_mult(-32768,-32768) = 2147483647. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +Word32 L_mult (Word16 var1, Word16 var2) { + Word32 L_var_out; + + L_var_out = (Word32) var1 *(Word32) var2; + + if (L_var_out != (Word32) 0x40000000L) { + L_var_out *= 2; + } else { + Overflow = 1; + L_var_out = MAX_32; + } + +#if (WMOPS) + multiCounter[currCounter].L_mult++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : negate | + | | + | Purpose : | + | | + | Negate var1 with saturation, saturate in the case where input is -32768:| + | negate(var1) = sub(0,var1). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +Word16 negate (Word16 var1) { + Word16 var_out; + + var_out = (var1 == MIN_16) ? MAX_16 : -var1; + +#if (WMOPS) + multiCounter[currCounter].negate++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : extract_h | + | | + | Purpose : | + | | + | Return the 16 MSB of L_var1. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32 ) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +Word16 extract_h (Word32 L_var1) { + Word16 var_out; + + var_out = (Word16) (L_var1 >> 16); + +#if (WMOPS) + multiCounter[currCounter].extract_h++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : extract_l | + | | + | Purpose : | + | | + | Return the 16 LSB of L_var1. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32 ) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +Word16 extract_l (Word32 L_var1) { + Word16 var_out; + + var_out = (Word16) L_var1; + +#if (WMOPS) + multiCounter[currCounter].extract_l++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : round_fx | + | | + | Purpose : | + | | + | Round the lower 16 bits of the 32 bit input number into the MS 16 bits | + | with saturation. Shift the resulting bits right by 16 and return the 16 | + | bit number: | + | round_fx(L_var1) = extract_h(L_add(L_var1,32768)) | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32 ) whose value falls in the | + | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +Word16 round_fx (Word32 L_var1) { + Word16 var_out; + Word32 L_rounded; + + L_rounded = L_add (L_var1, (Word32) 0x00008000L); + var_out = extract_h (L_rounded); + +#if (WMOPS) + multiCounter[currCounter].L_add--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].round++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_mac | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit | + | result to L_var3 with saturation, return a 32 bit result: | + | L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2) { + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult (var1, var2); + L_var_out = L_add (L_var3, L_product); + +#if (WMOPS) + multiCounter[currCounter].L_mult--; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].L_mac++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_msu | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 | + | bit result from L_var3 with saturation, return a 32 bit result: | + | L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2) { + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult (var1, var2); + L_var_out = L_sub (L_var3, L_product); + +#if (WMOPS) + multiCounter[currCounter].L_mult--; + multiCounter[currCounter].L_sub--; + multiCounter[currCounter].L_msu++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_macNs | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit | + | result to L_var3 without saturation, return a 32 bit result. Generate | + | carry and overflow values : | + | L_macNs(L_var3,var1,var2) = L_add_c(L_var3,L_mult(var1,var2)). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + | | + | Caution : | + | | + | In some cases the Carry flag has to be cleared or set before using | + | operators which take into account its value. | + |___________________________________________________________________________| +*/ +Word32 L_macNs (Word32 L_var3, Word16 var1, Word16 var2) { + Word32 L_var_out; + + L_var_out = L_mult (var1, var2); + L_var_out = L_add_c (L_var3, L_var_out); + +#if (WMOPS) + multiCounter[currCounter].L_mult--; + multiCounter[currCounter].L_add_c--; + multiCounter[currCounter].L_macNs++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_msuNs | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 | + | bit result from L_var3 without saturation, return a 32 bit result. Ge- | + | nerate carry and overflow values : | + | L_msuNs(L_var3,var1,var2) = L_sub_c(L_var3,L_mult(var1,var2)). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + | | + | Caution : | + | | + | In some cases the Carry flag has to be cleared or set before using | + | operators which take into account its value. | + |___________________________________________________________________________| +*/ +Word32 L_msuNs (Word32 L_var3, Word16 var1, Word16 var2) { + Word32 L_var_out; + + L_var_out = L_mult (var1, var2); + L_var_out = L_sub_c (L_var3, L_var_out); + +#if (WMOPS) + multiCounter[currCounter].L_mult--; + multiCounter[currCounter].L_sub_c--; + multiCounter[currCounter].L_msuNs++; + +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_add | + | | + | Purpose : | + | | + | 32 bits addition of the two 32 bits variables (L_var1+L_var2) with | + | overflow control and saturation; the result is set at +2147483647 when | + | overflow occurs or at -2147483648 when underflow occurs. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | L_var2 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +Word32 L_add (Word32 L_var1, Word32 L_var2) { + Word32 L_var_out; + + L_var_out = L_var1 + L_var2; + + if (((L_var1 ^ L_var2) & MIN_32) == 0) { + if ((L_var_out ^ L_var1) & MIN_32) { + L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32; + Overflow = 1; + } + } +#if (WMOPS) + multiCounter[currCounter].L_add++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_sub | + | | + | Purpose : | + | | + | 32 bits subtraction of the two 32 bits variables (L_var1-L_var2) with | + | overflow control and saturation; the result is set at +2147483647 when | + | overflow occurs or at -2147483648 when underflow occurs. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | L_var2 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +Word32 L_sub (Word32 L_var1, Word32 L_var2) { + Word32 L_var_out; + + L_var_out = L_var1 - L_var2; + + if (((L_var1 ^ L_var2) & MIN_32) != 0) { + if ((L_var_out ^ L_var1) & MIN_32) { + L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32; + Overflow = 1; + } + } +#if (WMOPS) + multiCounter[currCounter].L_sub++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_add_c | + | | + | Purpose : | + | | + | Performs 32 bits addition of the two 32 bits variables (L_var1+L_var2+C)| + | with carry. No saturation. Generate carry and Overflow values. The car- | + | ry and overflow values are binary variables which can be tested and as- | + | signed values. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | L_var2 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + | | + | Caution : | + | | + | In some cases the Carry flag has to be cleared or set before using | + | operators which take into account its value. | + |___________________________________________________________________________| +*/ +Word32 L_add_c (Word32 L_var1, Word32 L_var2) { + Word32 L_var_out; + Word32 L_test; + Flag carry_int = 0; + + L_var_out = L_var1 + L_var2 + Carry; + + L_test = L_var1 + L_var2; + + if ((L_var1 > 0) && (L_var2 > 0) && (L_test < 0)) { + Overflow = 1; + carry_int = 0; + } else { + if ((L_var1 < 0) && (L_var2 < 0)) { + if (L_test >= 0) { + Overflow = 1; + carry_int = 1; + } else { + Overflow = 0; + carry_int = 1; + } + } else { + if (((L_var1 ^ L_var2) < 0) && (L_test >= 0)) { + Overflow = 0; + carry_int = 1; + } else { + Overflow = 0; + carry_int = 0; + } + } + } + + if (Carry) { + if (L_test == MAX_32) { + Overflow = 1; + Carry = carry_int; + } else { + if (L_test == (Word32) 0xFFFFFFFFL) { + Carry = 1; + } else { + Carry = carry_int; + } + } + } else { + Carry = carry_int; + } + +#if (WMOPS) + multiCounter[currCounter].L_add_c++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_sub_c | + | | + | Purpose : | + | | + | Performs 32 bits subtraction of the two 32 bits variables with carry | + | (borrow) : L_var1-L_var2-C. No saturation. Generate carry and Overflow | + | values. The carry and overflow values are binary variables which can | + | be tested and assigned values. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | L_var2 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + | | + | Caution : | + | | + | In some cases the Carry flag has to be cleared or set before using | + | operators which take into account its value. | + |___________________________________________________________________________| +*/ +Word32 L_sub_c (Word32 L_var1, Word32 L_var2) { + Word32 L_var_out; + Word32 L_test; + Flag carry_int = 0; + + if (Carry) { + Carry = 0; + if (L_var2 != MIN_32) { + L_var_out = L_add_c (L_var1, -L_var2); +#if (WMOPS) + multiCounter[currCounter].L_add_c--; +#endif + } else { + L_var_out = L_var1 - L_var2; + if (L_var1 > 0L) { + Overflow = 1; + Carry = 0; + } + } + } else { + L_var_out = L_var1 - L_var2 - (Word32) 0X00000001L; + L_test = L_var1 - L_var2; + + if ((L_test < 0) && (L_var1 > 0) && (L_var2 < 0)) { + Overflow = 1; + carry_int = 0; + } else if ((L_test > 0) && (L_var1 < 0) && (L_var2 > 0)) { + Overflow = 1; + carry_int = 1; + } else if ((L_test > 0) && ((L_var1 ^ L_var2) > 0)) { + Overflow = 0; + carry_int = 1; + } + if (L_test == MIN_32) { + Overflow = 1; + Carry = carry_int; + } else { + Carry = carry_int; + } + } + +#if (WMOPS) + multiCounter[currCounter].L_sub_c++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_negate | + | | + | Purpose : | + | | + | Negate the 32 bit variable L_var1 with saturation; saturate in the case | + | where input is -2147483648 (0x8000 0000). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +Word32 L_negate (Word32 L_var1) { + Word32 L_var_out; + + L_var_out = (L_var1 == MIN_32) ? MAX_32 : -L_var1; + +#if (WMOPS) + multiCounter[currCounter].L_negate++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : mult_r | + | | + | Purpose : | + | | + | Same as mult with rounding, i.e.: | + | mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and | + | mult_r(-32768,-32768) = 32767. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x8000 <= var_out <= 0x7fff. | + |___________________________________________________________________________| +*/ +Word16 mult_r (Word16 var1, Word16 var2) { + Word16 var_out; + Word32 L_product_arr; + + L_product_arr = (Word32) var1 *(Word32) var2; /* product */ + L_product_arr += (Word32) 0x00004000L; /* round */ + L_product_arr &= (Word32) 0xffff8000L; + L_product_arr >>= 15; /* shift */ + + if (L_product_arr & (Word32) 0x00010000L) { /* sign extend when necessary */ + L_product_arr |= (Word32) 0xffff0000L; + } + var_out = saturate (L_product_arr); + +#if (WMOPS) + multiCounter[currCounter].mult_r++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_shl | + | | + | Purpose : | + | | + | Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero | + | fill the var2 LSB of the result. If var2 is negative, arithmetically | + | shift L_var1 right by -var2 with sign extension. Saturate the result in | + | case of underflows or overflows. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +Word32 L_shl (Word32 L_var1, Word16 var2) { + + Word32 L_var_out = 0L; + + if (var2 <= 0) { + if (var2 < -32) + var2 = -32; + var2 = -var2; + L_var_out = L_shr (L_var1, var2); +#if (WMOPS) + multiCounter[currCounter].L_shr--; +#endif + } else { + for (; var2 > 0; var2--) { + if (L_var1 > (Word32) 0X3fffffffL) { + Overflow = 1; + L_var_out = MAX_32; + break; + } else { + if (L_var1 < (Word32) 0xc0000000L) { + Overflow = 1; + L_var_out = MIN_32; + break; + } + } + L_var1 *= 2; + L_var_out = L_var1; + } + } +#if (WMOPS) + multiCounter[currCounter].L_shl++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_shr | + | | + | Purpose : | + | | + | Arithmetically shift the 32 bit input L_var1 right var2 positions with | + | sign extension. If var2 is negative, arithmetically shift L_var1 left | + | by -var2 and zero fill the -var2 LSB of the result. Saturate the result | + | in case of underflows or overflows. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +Word32 L_shr (Word32 L_var1, Word16 var2) { + Word32 L_var_out; + + if (var2 < 0) { + if (var2 < -32) + var2 = -32; + var2 = -var2; + L_var_out = L_shl (L_var1, var2); +#if (WMOPS) + multiCounter[currCounter].L_shl--; +#endif + } else { + if (var2 >= 31) { + L_var_out = (L_var1 < 0L) ? -1 : 0; + } else { + if (L_var1 < 0) { + L_var_out = ~((~L_var1) >> var2); + } else { + L_var_out = L_var1 >> var2; + } + } + } +#if (WMOPS) + multiCounter[currCounter].L_shr++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : shr_r | + | | + | Purpose : | + | | + | Same as shr(var1,var2) but with rounding. Saturate the result in case of| + | underflows or overflows : | + | - If var2 is greater than zero : | + | if (sub(shl(shr(var1,var2),1),shr(var1,sub(var2,1)))) | + | is equal to zero | + | then | + | shr_r(var1,var2) = shr(var1,var2) | + | else | + | shr_r(var1,var2) = add(shr(var1,var2),1) | + | - If var2 is less than or equal to zero : | + | shr_r(var1,var2) = shr(var1,var2). | + | | + | Complexity weight : 3 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +Word16 shr_r (Word16 var1, Word16 var2) { + Word16 var_out; + + if (var2 > 15) { + var_out = 0; + } else { + var_out = shr (var1, var2); + +#if (WMOPS) + multiCounter[currCounter].shr--; +#endif + + if (var2 > 0) { + if ((var1 & ((Word16) 1 << (var2 - 1))) != 0) { + var_out++; + } + } + } + +#if (WMOPS) + multiCounter[currCounter].shr_r++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : mac_r | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit | + | result to L_var3 with saturation. Round the LS 16 bits of the result | + | into the MS 16 bits with saturation and shift the result right by 16. | + | Return a 16 bit result. | + | mac_r(L_var3,var1,var2) = round_fx(L_mac(L_var3,var1,var2)) | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2) { + Word16 var_out; + + L_var3 = L_mac (L_var3, var1, var2); + L_var3 = L_add (L_var3, (Word32) 0x00008000L); + var_out = extract_h (L_var3); + +#if (WMOPS) + multiCounter[currCounter].L_mac--; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].mac_r++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : msu_r | + | | + | Purpose : | + | | + | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 | + | bit result from L_var3 with saturation. Round the LS 16 bits of the res-| + | ult into the MS 16 bits with saturation and shift the result right by | + | 16. Return a 16 bit result. | + | msu_r(L_var3,var1,var2) = round_fx(L_msu(L_var3,var1,var2)) | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var3 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2) { + Word16 var_out; + + L_var3 = L_msu (L_var3, var1, var2); + L_var3 = L_add (L_var3, (Word32) 0x00008000L); + var_out = extract_h (L_var3); + +#if (WMOPS) + multiCounter[currCounter].L_msu--; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].msu_r++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_deposit_h | + | | + | Purpose : | + | | + | Deposit the 16 bit var1 into the 16 MS bits of the 32 bit output. The | + | 16 LS bits of the output are zeroed. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var_out <= 0x7fff 0000. | + |___________________________________________________________________________| +*/ +Word32 L_deposit_h (Word16 var1) { + Word32 L_var_out; + + L_var_out = (Word32) var1 << 16; + +#if (WMOPS) + multiCounter[currCounter].L_deposit_h++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_deposit_l | + | | + | Purpose : | + | | + | Deposit the 16 bit var1 into the 16 LS bits of the 32 bit output. The | + | 16 MS bits of the output are sign extended. | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0xFFFF 8000 <= var_out <= 0x0000 7fff. | + |___________________________________________________________________________| +*/ +Word32 L_deposit_l (Word16 var1) { + Word32 L_var_out; + + L_var_out = (Word32) var1; + +#if (WMOPS) + multiCounter[currCounter].L_deposit_l++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_shr_r | + | | + | Purpose : | + | | + | Same as L_shr(L_var1,var2) but with rounding. Saturate the result in | + | case of underflows or overflows : | + | - If var2 is greater than zero : | + | if (L_sub(L_shl(L_shr(L_var1,var2),1),L_shr(L_var1,sub(var2,1))))| + | is equal to zero | + | then | + | L_shr_r(L_var1,var2) = L_shr(L_var1,var2) | + | else | + | L_shr_r(L_var1,var2) = L_add(L_shr(L_var1,var2),1) | + | - If var2 is less than or equal to zero : | + | L_shr_r(L_var1,var2) = L_shr(L_var1,var2). | + | | + | Complexity weight : 3 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +Word32 L_shr_r (Word32 L_var1, Word16 var2) { + Word32 L_var_out; + + if (var2 > 31) { + L_var_out = 0; + } else { + L_var_out = L_shr (L_var1, var2); + +#if (WMOPS) + multiCounter[currCounter].L_shr--; +#endif + if (var2 > 0) { + if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0) { + L_var_out++; + } + } + } + +#if (WMOPS) + multiCounter[currCounter].L_shr_r++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_abs | + | | + | Purpose : | + | | + | Absolute value of L_var1; Saturate in case where the input is | + | -214783648 | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +Word32 L_abs (Word32 L_var1) { + Word32 L_var_out; + + if (L_var1 == MIN_32) { + L_var_out = MAX_32; + } else { + if (L_var1 < 0) { + L_var_out = -L_var1; + } else { + L_var_out = L_var1; + } + } + +#if (WMOPS) + multiCounter[currCounter].L_abs++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : L_sat | + | | + | Purpose : | + | | + | 32 bit L_var1 is set to 2147483647 if an overflow occured or to | + | -2147483648 if an underflow occured on the most recent L_add_c, | + | L_sub_c, L_macNs or L_msuNs operations. The carry and overflow values | + | are binary values which can be tested and assigned values. | + | | + | Complexity weight : 4 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L_var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var_out <= 0x7fff ffff. | + |___________________________________________________________________________| +*/ +Word32 L_sat (Word32 L_var1) { + Word32 L_var_out; + + L_var_out = L_var1; + + if (Overflow) { + + if (Carry) { + L_var_out = MIN_32; + } else { + L_var_out = MAX_32; + } + + Carry = 0; + Overflow = 0; + } +#if (WMOPS) + multiCounter[currCounter].L_sat++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : norm_s | + | | + | Purpose : | + | | + | Produces the number of left shift needed to normalize the 16 bit varia- | + | ble var1 for positive values on the interval with minimum of 16384 and | + | maximum of 32767, and for negative values on the interval with minimum | + | of -32768 and maximum of -16384; in order to normalize the result, the | + | following operation must be done : | + | norm_var1 = shl(var1,norm_s(var1)). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 000f. | + |___________________________________________________________________________| +*/ +Word16 norm_s (Word16 var1) { + Word16 var_out; + + if (var1 == 0) { + var_out = 0; + } else { + if (var1 == (Word16) 0xffff) { + var_out = 15; + } else { + if (var1 < 0) { + var1 = ~var1; + } + for (var_out = 0; var1 < 0x4000; var_out++) { + var1 <<= 1; + } + } + } + +#if (WMOPS) + multiCounter[currCounter].norm_s++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : div_s | + | | + | Purpose : | + | | + | Produces a result which is the fractional integer division of var1 by | + | var2; var1 and var2 must be positive and var2 must be greater or equal | + | to var1; the result is positive (leading bit equal to 0) and truncated | + | to 16 bits. | + | If var1 = var2 then div(var1,var2) = 32767. | + | | + | Complexity weight : 18 | + | | + | Inputs : | + | | + | var1 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var1 <= var2 and var2 != 0. | + | | + | var2 | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : var1 <= var2 <= 0x0000 7fff and var2 != 0. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 7fff. | + | It's a Q15 value (point between b15 and b14). | + |___________________________________________________________________________| +*/ +Word16 div_s (Word16 var1, Word16 var2) { + Word16 var_out = 0; + Word16 iteration; + Word32 L_num; + Word32 L_denom; + + if ((var1 > var2) || (var1 < 0) || (var2 < 0)) { + printf ("Division Error var1=%d var2=%d\n", var1, var2); + abort (); /* exit (0); */ + } + if (var2 == 0) { + printf ("Division by 0, Fatal error \n"); + abort (); /* exit (0); */ + } + if (var1 == 0) { + var_out = 0; + } else { + if (var1 == var2) { + var_out = MAX_16; + } else { + L_num = L_deposit_l (var1); + L_denom = L_deposit_l (var2); + +#if (WMOPS) + multiCounter[currCounter].L_deposit_l--; + multiCounter[currCounter].L_deposit_l--; +#endif + + for (iteration = 0; iteration < 15; iteration++) { + var_out <<= 1; + L_num <<= 1; + + if (L_num >= L_denom) { + L_num = L_sub (L_num, L_denom); + var_out = add (var_out, 1); +#if (WMOPS) + multiCounter[currCounter].L_sub--; + multiCounter[currCounter].add--; +#endif + } + } + } + } + +#if (WMOPS) + multiCounter[currCounter].div_s++; +#endif + return (var_out); +} + + +/*___________________________________________________________________________ + | | + | Function Name : norm_l | + | | + | Purpose : | + | | + | Produces the number of left shifts needed to normalize the 32 bit varia-| + | ble L_var1 for positive values on the interval with minimum of | + | 1073741824 and maximum of 2147483647, and for negative values on the in-| + | terval with minimum of -2147483648 and maximum of -1073741824; in order | + | to normalize the result, the following operation must be done : | + | norm_L_var1 = L_shl(L_var1,norm_l(L_var1)). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L_var1 | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 001f. | + |___________________________________________________________________________| +*/ +Word16 norm_l (Word32 L_var1) { + Word16 var_out; + + if (L_var1 == 0) { + var_out = 0; + } else { + if (L_var1 == (Word32) 0xffffffffL) { + var_out = 31; + } else { + if (L_var1 < 0) { + L_var1 = ~L_var1; + } + for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++) { + L_var1 <<= 1; + } + } + } + +#if (WMOPS) + multiCounter[currCounter].norm_l++; +#endif + return (var_out); +} + +/* + ****************************************************************************** + * Additional operators extracted from the G.723.1 Library + * Adapted for WMOPS calculations + ****************************************************************************** +*/ + +/*___________________________________________________________________________ + | | + | Function Name : L_mls | + | | + | Purpose : | + | | + | Multiplies a 16 bit word v by a 32 bit word Lv and returns a 32 bit | + | word (multiplying 16 by 32 bit words gives 48 bit word; the function | + | extracts the 32 MSB and shift the result to the left by 1). | + | | + | A 32 bit word can be written as | + | Lv = a + b * 2^16 | + | where a= unsigned 16 LSBs and b= signed 16 MSBs. | + | The function returns v * Lv / 2^15 which is equivalent to | + | a*v / 2^15 + b*v*2 | + | | + | Complexity weight : 5 | + | | + | Inputs : | + | | + | Lv | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var1 <= 0x7fff ffff. | + | v | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x8000 <= var1 <= 0x7fff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 32 bit long signed integer (Word32) whose value falls in the | + | range : 0x8000 0000 <= var_out <= 0x7fff ffff. | + | | + |___________________________________________________________________________| +*/ +Word32 L_mls (Word32 Lv, Word16 v) { + Word32 Temp; + + Temp = Lv & (Word32) 0x0000ffff; + Temp = Temp * (Word32) v; + Temp = L_shr (Temp, (Word16) 15); + Temp = L_mac (Temp, v, extract_h (Lv)); + +#if (WMOPS) + multiCounter[currCounter].L_shr--; + multiCounter[currCounter].L_mac--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].L_mls++; +#endif + + return Temp; +} + + +/*__________________________________________________________________________ +| | +| Function Name : div_l | +| | +| Purpose : | +| | +| Produces a result which is the fractional integer division of L_var1 by | +| var2; L_var1 and var2 must be positive and var2 << 16 must be greater or| +| equal to L_var1; the result is positive (leading bit equal to 0) and | +| truncated to 16 bits. | +| If L_var1 == var2 << 16 then div_l(L_var1,var2) = 32767. | +| | +| Complexity weight : 32 | +| | +| Inputs : | +| | +| L_var1 | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x0000 0000 <= var1 <= (var2 << 16) and var2 != 0. | +| L_var1 must be considered as a Q.31 value | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : var1 <= (var2<< 16) <= 0x7fff0000 and var2 != 0. | +| var2 must be considered as a Q.15 value | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| var_out | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0x0000 0000 <= var_out <= 0x0000 7fff. | +| It's a Q15 value (point between b15 and b14). | +|___________________________________________________________________________| +*/ +Word16 div_l (Word32 L_num, Word16 den) { + Word16 var_out = (Word16) 0; + Word32 L_den; + Word16 iteration; + +#if (WMOPS) + multiCounter[currCounter].div_l++; +#endif + + if (den == (Word16) 0) { + printf ("Division by 0 in div_l, Fatal error \n"); + exit (0); + } + + if ((L_num < (Word32) 0) || (den < (Word16) 0)) { + printf ("Division Error in div_l, Fatal error \n"); + exit (0); + } + + L_den = L_deposit_h (den); +#if (WMOPS) + multiCounter[currCounter].L_deposit_h--; +#endif + + if (L_num >= L_den) { + return MAX_16; + } else { + L_num = L_shr (L_num, (Word16) 1); + L_den = L_shr (L_den, (Word16) 1); +#if (WMOPS) + multiCounter[currCounter].L_shr -= 2; +#endif + for (iteration = (Word16) 0; iteration < (Word16) 15; iteration++) { + var_out = shl (var_out, (Word16) 1); + L_num = L_shl (L_num, (Word16) 1); +#if (WMOPS) + multiCounter[currCounter].shl--; + multiCounter[currCounter].L_shl--; +#endif + if (L_num >= L_den) { + L_num = L_sub (L_num, L_den); + var_out = add (var_out, (Word16) 1); +#if (WMOPS) + multiCounter[currCounter].L_sub--; + multiCounter[currCounter].add--; +#endif + } + } + + return var_out; + } +} + + +/*__________________________________________________________________________ +| | +| Function Name : i_mult | +| | +| Purpose : | +| | +| Integer 16-bit multiplication with overflow control. | +| No overflow protection is performed if ORIGINAL_G7231 is defined. | +| | +| Complexity weight : 3 (it is performing something equivalent to | +| extract_h( L_shl( L_mult0( v1, v2), 16)) | +| | +| Inputs : | +| | +| a | +| 16 bit short signed integer (Word16). | +| | +| b | +| 16 bit short signed integer (Word16). | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| 16 bit short signed integer (Word16). No overflow checks | +| are performed if ORIGINAL_G7231 is defined. | +|___________________________________________________________________________| +*/ +Word16 i_mult (Word16 a, Word16 b) { +#ifdef ORIGINAL_G7231 + return a * b; +#else + Word32 /*register*/ c = a * b; +#if (WMOPS) + multiCounter[currCounter].i_mult++; +#endif + return saturate (c); +#endif +} + + +/* + ****************************************************************************** + * The following three operators are not part of the original + * G.729/G.723.1 set of basic operators and implement shiftless + * accumulation operation. + ****************************************************************************** +*/ + +/*___________________________________________________________________________ + | + | Function Name : L_mult0 + | + | Purpose : + | + | L_mult0 is the 32 bit result of the multiplication of var1 times var2 + | without one left shift. + | + | Complexity weight : 1 + | + | Inputs : + | + | var1 16 bit short signed integer (Word16) whose value falls in the + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. + | + | var2 16 bit short signed integer (Word16) whose value falls in the + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. + | + | Return Value : + | + | L_var_out + | 32 bit long signed integer (Word32) whose value falls in the + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. + |___________________________________________________________________________ +*/ +Word32 L_mult0 (Word16 var1, Word16 var2) { + Word32 L_var_out; + + L_var_out = (Word32) var1 *(Word32) var2; + +#if (WMOPS) + multiCounter[currCounter].L_mult0++; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | + | Function Name : L_mac0 + | + | Purpose : + | + | Multiply var1 by var2 (without left shift) and add the 32 bit result to + | L_var3 with saturation, return a 32 bit result: + | L_mac0(L_var3,var1,var2) = L_add(L_var3,(L_mult0(var1,var2)). + | + | Complexity weight : 1 + | + | Inputs : + | + | L_var3 32 bit long signed integer (Word32) whose value falls in the + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. + | + | var1 16 bit short signed integer (Word16) whose value falls in the + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. + | + | var2 16 bit short signed integer (Word16) whose value falls in the + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. + | + | Return Value : + | + | L_var_out + | 32 bit long signed integer (Word32) whose value falls in the + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. + |___________________________________________________________________________ +*/ +Word32 L_mac0 (Word32 L_var3, Word16 var1, Word16 var2) { + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult0 (var1, var2); + L_var_out = L_add (L_var3, L_product); + +#if (WMOPS) + multiCounter[currCounter].L_mac0++; + multiCounter[currCounter].L_mult0--; + multiCounter[currCounter].L_add--; +#endif + return (L_var_out); +} + + +/*___________________________________________________________________________ + | + | Function Name : L_msu0 + | + | Purpose : + | + | Multiply var1 by var2 (without left shift) and subtract the 32 bit + | result to L_var3 with saturation, return a 32 bit result: + | L_msu0(L_var3,var1,var2) = L_sub(L_var3,(L_mult0(var1,var2)). + | + | Complexity weight : 1 + | + | Inputs : + | + | L_var3 32 bit long signed integer (Word32) whose value falls in the + | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. + | + | var1 16 bit short signed integer (Word16) whose value falls in the + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. + | + | var2 16 bit short signed integer (Word16) whose value falls in the + | range : 0xffff 8000 <= var1 <= 0x0000 7fff. + | + | Return Value : + | + | L_var_out + | 32 bit long signed integer (Word32) whose value falls in the + | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. + |___________________________________________________________________________ +*/ +Word32 L_msu0 (Word32 L_var3, Word16 var1, Word16 var2) { + Word32 L_var_out; + Word32 L_product; + + L_product = L_mult0 (var1, var2); + L_var_out = L_sub (L_var3, L_product); + +#if (WMOPS) + multiCounter[currCounter].L_msu0++; + multiCounter[currCounter].L_mult0--; + multiCounter[currCounter].L_sub--; +#endif + return (L_var_out); +} + + +/* end of file */ diff --git a/basic_op/basop32.h b/basic_op/basop32.h new file mode 100644 index 0000000..a9d6377 --- /dev/null +++ b/basic_op/basop32.h @@ -0,0 +1,130 @@ +/* + =========================================================================== + File: BASOP32.H v.2.3 - 30.Nov.2009 + =========================================================================== + + ITU-T STL BASIC OPERATORS + + GLOBAL FUNCTION PROTOTYPES + + History: + 26.Jan.00 v1.0 Incorporated to the STL from updated G.723.1/G.729 + basic operator library (based on basic_op.h) and + G.723.1's basop.h. + 05.Jul.00 v1.1 Added 32-bit shiftless mult/mac/msub operators + + 03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control + operators for the ITU-T Standard Tool Library as + described in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + TD 11 document and subsequent discussions on the + wp3audio@yahoogroups.com email reflector. + norm_s() weight reduced from 15 to 1. + norm_l() weight reduced from 30 to 1. + L_abs() weight reduced from 2 to 1. + L_add() weight reduced from 2 to 1. + L_negate() weight reduced from 2 to 1. + L_shl() weight reduced from 2 to 1. + L_shr() weight reduced from 2 to 1. + L_sub() weight reduced from 2 to 1. + mac_r() weight reduced from 2 to 1. + msu_r() weight reduced from 2 to 1. + mult_r() weight reduced from 2 to 1. + L_deposit_h() weight reduced from 2 to 1. + L_deposit_l() weight reduced from 2 to 1. + L_mls() weight of 5. + div_l() weight of 32. + i_mult() weight of 3. + + 30 Nov 09 v2.3 round() function is now round_fx(). + saturate() is not referencable from outside application + ============================================================================ +*/ + + +#ifndef _BASIC_OP_H +#define _BASIC_OP_H + + +/*___________________________________________________________________________ + | | + | Constants and Globals | + | $Id $ + |___________________________________________________________________________| +*/ +extern Flag Overflow; +extern Flag Carry; + +#define BASOP_SATURATE_WARNING_ON +#define BASOP_SATURATE_WARNING_OFF +#define BASOP_SATURATE_ERROR_ON +#define BASOP_SATURATE_ERROR_OFF +#define BASOP_CHECK() + +#define MAX_32 (Word32)0x7fffffffL +#define MIN_32 (Word32)0x80000000L + +#define MAX_16 (Word16)0x7fff +#define MIN_16 (Word16)0x8000 + +/*___________________________________________________________________________ + | | + | Prototypes for basic arithmetic operators | + |___________________________________________________________________________| +*/ + +Word16 add (Word16 var1, Word16 var2); /* Short add, 1 */ +Word16 sub (Word16 var1, Word16 var2); /* Short sub, 1 */ +Word16 abs_s (Word16 var1); /* Short abs, 1 */ +Word16 shl (Word16 var1, Word16 var2); /* Short shift left, 1 */ +Word16 shr (Word16 var1, Word16 var2); /* Short shift right, 1 */ +Word16 mult (Word16 var1, Word16 var2); /* Short mult, 1 */ +Word32 L_mult (Word16 var1, Word16 var2); /* Long mult, 1 */ +Word16 negate (Word16 var1); /* Short negate, 1 */ +Word16 extract_h (Word32 L_var1); /* Extract high, 1 */ +Word16 extract_l (Word32 L_var1); /* Extract low, 1 */ +Word16 round_fx (Word32 L_var1); /* Round, 1 */ +Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2); /* Mac, 1 */ +Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2); /* Msu, 1 */ +Word32 L_macNs (Word32 L_var3, Word16 var1, Word16 var2); /* Mac without sat, 1 */ +Word32 L_msuNs (Word32 L_var3, Word16 var1, Word16 var2); /* Msu without sat, 1 */ +Word32 L_add (Word32 L_var1, Word32 L_var2); /* Long add, 1 */ +Word32 L_sub (Word32 L_var1, Word32 L_var2); /* Long sub, 1 */ +Word32 L_add_c (Word32 L_var1, Word32 L_var2); /* Long add with c, 2 */ +Word32 L_sub_c (Word32 L_var1, Word32 L_var2); /* Long sub with c, 2 */ +Word32 L_negate (Word32 L_var1); /* Long negate, 1 */ +Word16 mult_r (Word16 var1, Word16 var2); /* Mult with round, 1 */ +Word32 L_shl (Word32 L_var1, Word16 var2); /* Long shift left, 1 */ +Word32 L_shr (Word32 L_var1, Word16 var2); /* Long shift right, 1 */ +Word16 shr_r (Word16 var1, Word16 var2); /* Shift right with round, 2 */ +Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2); /* Mac with rounding, 1 */ +Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2); /* Msu with rounding, 1 */ +Word32 L_deposit_h (Word16 var1); /* 16 bit var1 -> MSB, 1 */ +Word32 L_deposit_l (Word16 var1); /* 16 bit var1 -> LSB, 1 */ + +Word32 L_shr_r (Word32 L_var1, Word16 var2); /* Long shift right with round, 3 */ +Word32 L_abs (Word32 L_var1); /* Long abs, 1 */ +Word32 L_sat (Word32 L_var1); /* Long saturation, 4 */ +Word16 norm_s (Word16 var1); /* Short norm, 1 */ +Word16 div_s (Word16 var1, Word16 var2); /* Short division, 18 */ +Word16 norm_l (Word32 L_var1); /* Long norm, 1 */ + + +/* + * Additional G.723.1 operators +*/ +Word32 L_mls (Word32, Word16); /* Weight FFS; currently assigned 5 */ +Word16 div_l (Word32, Word16); /* Weight FFS; currently assigned 32 */ +Word16 i_mult (Word16 a, Word16 b); /* Weight FFS; currently assigned 3 */ + +/* + * New shiftless operators, not used in G.729/G.723.1 +*/ +Word32 L_mult0 (Word16 v1, Word16 v2); /* 32-bit Multiply w/o shift e 1 */ +Word32 L_mac0 (Word32 L_v3, Word16 v1, Word16 v2); /* 32-bit Mac w/o shift 1 */ +Word32 L_msu0 (Word32 L_v3, Word16 v1, Word16 v2); /* 32-bit Msu w/o shift 1 */ + + +#endif /* ifndef _BASIC_OP_H */ + + +/* end of file */ diff --git a/basic_op/complex_basop.c b/basic_op/complex_basop.c new file mode 100644 index 0000000..3a65d65 --- /dev/null +++ b/basic_op/complex_basop.c @@ -0,0 +1,457 @@ +/***************************************************************************** + +* + +* Complex arithmetic operators + +* + +*****************************************************************************/ + + +#include "typedef.h" +#include "basop32.h" + +#include "complex_basop.h" + +#include "stl.h" + + + +#if (WMOPS) + +extern BASIC_OP multiCounter[MAXCOUNTERS]; + +extern int currCounter; + +#endif /* if WMOPS */ + + + +#ifdef COMPLEX_OPERATOR + +/* ================================ New Complex Basops ========================= */ + +cmplx CL_shr (cmplx inp, Word32 shift_val) { + cmplx out; + out.re = L_shr (inp.re, shift_val); + out.im = L_shr (inp.im, shift_val); +#if (WMOPS) + multiCounter[currCounter].CL_shr++; + multiCounter[currCounter].L_shr--; + multiCounter[currCounter].L_shr--; +#endif + return out; +} + +cmplx CL_shl (cmplx inp, Word32 shift_val) { + cmplx out; + out.re = L_shl (inp.re, shift_val); + out.im = L_shl (inp.im, shift_val); +#if (WMOPS) + multiCounter[currCounter].CL_shl++; + multiCounter[currCounter].L_shl--; + multiCounter[currCounter].L_shl--; +#endif + return out; +} + +cmplx CL_add (cmplx inp1, cmplx inp2) { + cmplx out; + out.re = L_add (inp1.re, inp2.re); + out.im = L_add (inp1.im, inp2.im); +#if (WMOPS) + multiCounter[currCounter].CL_add++; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].L_add--; +#endif + return out; +} + +cmplx CL_sub (cmplx inp1, cmplx inp2) { + cmplx out; + out.re = L_sub (inp1.re, inp2.re); + out.im = L_sub (inp1.im, inp2.im); +#if (WMOPS) + multiCounter[currCounter].CL_sub++; + multiCounter[currCounter].L_sub--; + multiCounter[currCounter].L_sub--; +#endif + return out; +} + +cmplx CL_scale(cmplx x, Word16 y) { + cmplx result; + result.re = Mpy_32_16_r (x.re, y); + result.im = Mpy_32_16_r (x.im, y); +#if (WMOPS) + multiCounter[currCounter].Mpy_32_16_r--; + multiCounter[currCounter].Mpy_32_16_r--; + multiCounter[currCounter].CL_scale++; +#endif/* #if (WMOPS) */ + return (result); +} + +cmplx CL_dscale (cmplx x, Word16 y1, Word16 y2) { + cmplx result; + result.re = Mpy_32_16_r (x.re, y1); + result.im = Mpy_32_16_r (x.im, y2); +#if (WMOPS) + multiCounter[currCounter].Mpy_32_16_r--; + multiCounter[currCounter].Mpy_32_16_r--; + multiCounter[currCounter].CL_dscale++; +#endif/* #if (WMOPS) */ + return (result); +} + +cmplx CL_msu_j (cmplx x, cmplx y) { + cmplx result; + result.re = L_add (x.re, y.im); + result.im = L_sub (x.im, y.re); +#if (WMOPS) + multiCounter[currCounter].CL_msu_j++; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].L_sub--; +#endif + return result; +} + +cmplx CL_mac_j (cmplx x, cmplx y) { + cmplx result; + result.re = L_sub (x.re, y.im ); + result.im = L_add (x.im, y.re ); +#if (WMOPS) + multiCounter[currCounter].CL_mac_j++; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].L_sub--; +#endif + return result; +} + +cmplx CL_move (cmplx x) { +#if (WMOPS) + multiCounter[currCounter].CL_move++; +#endif + return x; +} + +Word32 CL_Extract_real (cmplx x) { +#if (WMOPS) + multiCounter[currCounter].CL_Extract_real++; +#endif + return x.re; +} + +Word32 CL_Extract_imag (cmplx x) { +#if (WMOPS) + multiCounter[currCounter].CL_Extract_imag++; +#endif + return x.im; +} + +cmplx CL_form (Word32 re, Word32 im) { + cmplx result; + result.re = re; + result.im = im; +#if (WMOPS) + multiCounter[currCounter].CL_form++; +#endif + return result; +} + +cmplx CL_multr_32x16 (cmplx input, cmplx_s coeff) { + cmplx result; + result.re = W_round48_L (W_sub_nosat (W_mult_32_16 (input.re, coeff.re), W_mult_32_16 (input.im, coeff.im) ) ); + result.im = W_round48_L (W_add_nosat (W_mult_32_16 (input.re, coeff.im), W_mult_32_16 (input.im, coeff.re) ) ); +#if (WMOPS) + multiCounter[currCounter].CL_multr_32x16++; + multiCounter[currCounter].W_mult_32_16--; + multiCounter[currCounter].W_mult_32_16--; + multiCounter[currCounter].W_mult_32_16--; + multiCounter[currCounter].W_mult_32_16--; + multiCounter[currCounter].W_sub_nosat--; + multiCounter[currCounter].W_add_nosat--; + multiCounter[currCounter].W_round48_L--; + multiCounter[currCounter].W_round48_L--; +#endif + return result; +} + +cmplx CL_negate(cmplx x) { + cmplx result; + result.re = L_negate (x.re); + result.im = L_negate (x.im); +#if (WMOPS) + multiCounter[currCounter].CL_negate++; + multiCounter[currCounter].L_negate--; + multiCounter[currCounter].L_negate--; +#endif + return result; +} + +cmplx CL_conjugate (cmplx x) { + cmplx result; + result.re = x.re; + result.im = L_negate (x.im); +#if (WMOPS) + multiCounter[currCounter].CL_conjugate++; + multiCounter[currCounter].L_negate--; +#endif + return result; +} + + +cmplx CL_mul_j (cmplx input) { + cmplx temp, result; + temp = CL_negate (input); + result.re = temp.im; + result.im = input.re; +#if (WMOPS) + multiCounter[currCounter].CL_mul_j++; + multiCounter[currCounter].CL_negate--; +#endif + return result; +} + +cmplx CL_swap_real_imag (cmplx input) { + cmplx result; + result.re = input.im; + result.im = input.re; +#if (WMOPS) + multiCounter[currCounter].CL_swap_real_imag++; +#endif + return result; +} + +cmplx_s C_add (cmplx_s inp1, cmplx_s inp2) { + cmplx_s out; + out.re = add (inp1.re, inp2.re); + out.im = add (inp1.im, inp2.im); + +#if (WMOPS) + multiCounter[currCounter].C_add++; + multiCounter[currCounter].add--; + multiCounter[currCounter].add--; +#endif + return out; +} + +cmplx_s C_sub (cmplx_s inp1, cmplx_s inp2) { + cmplx_s out; + out.re = sub (inp1.re, inp2.re); + out.im = sub (inp1.im, inp2.im); + +#if (WMOPS) + multiCounter[currCounter].C_sub++; + multiCounter[currCounter].sub--; + multiCounter[currCounter].sub--; +#endif + return out; +} + +cmplx_s C_mul_j (cmplx_s input) { + cmplx_s result; + Word16 temp; + temp = negate(input.im); + result.re = temp; + result.im = input.re; + +#if (WMOPS) + multiCounter[currCounter].C_mul_j++; + multiCounter[currCounter].negate--; +#endif + return result; +} + +cmplx_s C_multr (cmplx_s x, cmplx_s c) { + cmplx_s result; + result.re = round_fx (W_sat_l (W_sub_nosat (W_mult_16_16 (x.re, c.re), W_mult_16_16 (x.im, c.im) ) ) ); + result.im = round_fx (W_sat_l (W_add_nosat (W_mult_16_16 (x.im, c.re), W_mult_16_16 (x.re, c.im) ) ) ); + +#if (WMOPS) + multiCounter[currCounter].C_multr++; + multiCounter[currCounter].W_mult_16_16--; + multiCounter[currCounter].W_mult_16_16--; + multiCounter[currCounter].W_mult_16_16--; + multiCounter[currCounter].W_mult_16_16--; + multiCounter[currCounter].W_sub_nosat--; + multiCounter[currCounter].W_add_nosat--; + multiCounter[currCounter].W_sat_l--; + multiCounter[currCounter].W_sat_l--; + multiCounter[currCounter].round--; + multiCounter[currCounter].round--; +#endif + return result; +} + +cmplx_s C_form ( Word16 re, Word16 im) { + cmplx_s result; + result.re = re; + result.im = im; +#if (WMOPS) + multiCounter[currCounter].C_form++; +#endif + return result; +} + +cmplx C_scale(cmplx_s x, Word16 y) { + cmplx result; + result.re = L_mult(x.re, y); + result.im = L_mult(x.im, y); +#if (WMOPS) + multiCounter[currCounter].L_mult--; + multiCounter[currCounter].L_mult--; + multiCounter[currCounter].C_scale++; +#endif/* #if (WMOPS) */ + return (result); +} + +cmplx_s CL_round32_16 (cmplx x) { + cmplx_s result; + result.re = round_fx (x.re); + result.im = round_fx (x.im); + +#if (WMOPS) + multiCounter[currCounter].CL_round32_16++; + multiCounter[currCounter].round--; + multiCounter[currCounter].round--; +#endif + return result; +} + +cmplx CL_scale_32 (cmplx x, Word32 y) { + cmplx result; + result.re = Mpy_32_32_r (x.re, y); + result.im = Mpy_32_32_r (x.im, y); +#if (WMOPS) + multiCounter[currCounter].Mpy_32_32_r--; + multiCounter[currCounter].Mpy_32_32_r--; + multiCounter[currCounter].CL_scale_32++; +#endif/* #if (WMOPS) */ + return (result); +} + +cmplx CL_dscale_32 (cmplx x, Word32 y1, Word32 y2) { + cmplx result; + result.re = Mpy_32_32_r (x.re, y1); + result.im = Mpy_32_32_r (x.im, y2); +#if (WMOPS) + multiCounter[currCounter].Mpy_32_32_r--; + multiCounter[currCounter].Mpy_32_32_r--; + multiCounter[currCounter].CL_dscale_32++; +#endif/* #if (WMOPS) */ + return (result); +} + +cmplx CL_multr_32x32 (cmplx x, cmplx y) { + cmplx result; + result.re = W_round64_L (W_sub (W_mult_32_32 (x.re, y.re), W_mult_32_32(x.im, y.im) ) ) ; + result.im = W_round64_L (W_add (W_mult_32_32 (x.im, y.re), W_mult_32_32(x.re, y.im) ) ) ; + +#if (WMOPS) + multiCounter[currCounter].CL_multr_32x32++; + multiCounter[currCounter].W_mult_32_32--; + multiCounter[currCounter].W_mult_32_32--; + multiCounter[currCounter].W_mult_32_32--; + multiCounter[currCounter].W_mult_32_32--; + multiCounter[currCounter].W_round64_L--; + multiCounter[currCounter].W_round64_L--; + multiCounter[currCounter].W_sub--; + multiCounter[currCounter].W_add--; +#endif + return result; +} + +cmplx_s C_mac_r (cmplx x, cmplx_s y, Word16 c) { + cmplx_s result; + cmplx temp = CL_add (x, C_scale (y, c) ); + result = CL_round32_16 (temp); + +#if (WMOPS) + multiCounter[currCounter].C_mac_r++; + multiCounter[currCounter].CL_add--; + multiCounter[currCounter].C_scale--; + multiCounter[currCounter].CL_round32_16--; +#endif + return result; +} + +cmplx_s C_msu_r (cmplx x, cmplx_s y, Word16 c) { + cmplx_s result; + cmplx temp = CL_sub (x, C_scale (y, c) ); + result = CL_round32_16 (temp); + +#if (WMOPS) + multiCounter[currCounter].C_msu_r++; + multiCounter[currCounter].CL_sub--; + multiCounter[currCounter].C_scale--; + multiCounter[currCounter].CL_round32_16--; +#endif + return result; +} + +Word16 C_Extract_real (cmplx_s x) { +#if (WMOPS) + multiCounter[currCounter].C_Extract_real++; +#endif + return x.re; +} + +Word16 C_Extract_imag (cmplx_s x) { +#if (WMOPS) + multiCounter[currCounter].C_Extract_imag++; +#endif + return x.im; +} + +cmplx_s C_negate (cmplx_s x) { + cmplx_s result; + result.re = negate (x.re); + result.im = negate (x.im); +#if (WMOPS) + multiCounter[currCounter].C_negate++; + multiCounter[currCounter].negate--; + multiCounter[currCounter].negate--; +#endif + return result; +} + +cmplx_s C_conjugate (cmplx_s x) { + cmplx_s result; + result.re = x.re; + result.im = negate (x.im); +#if (WMOPS) + multiCounter[currCounter].C_conjugate++; + multiCounter[currCounter].negate--; +#endif + return result; +} + +cmplx_s C_shr (cmplx_s inp, Word16 shift_val) { + cmplx_s out; + out.re = shr (inp.re, shift_val); + out.im = shr (inp.im, shift_val); +#if (WMOPS) + multiCounter[currCounter].C_shr++; + multiCounter[currCounter].shr--; + multiCounter[currCounter].shr--; +#endif + return out; +} + +cmplx_s C_shl (cmplx_s inp, Word16 shift_val) { + cmplx_s out; + out.re = shl (inp.re, shift_val); + out.im = shl (inp.im, shift_val); +#if (WMOPS) + multiCounter[currCounter].C_shl++; + multiCounter[currCounter].shl--; + multiCounter[currCounter].shl--; +#endif + return out; +} + +#endif /* #ifdef COMPLEX_OPERATOR */ + +/* end of file */ + diff --git a/basic_op/complex_basop.h b/basic_op/complex_basop.h new file mode 100644 index 0000000..c3deb14 --- /dev/null +++ b/basic_op/complex_basop.h @@ -0,0 +1,77 @@ + /***************************************************************************** + + * + + * Complex arithmetic operators + + * + + *****************************************************************************/ +#ifndef _COMPLEX_BASIC_OP_H +#define _COMPLEX_BASIC_OP_H + +#include "typedef.h" +#include "basop32.h" +#include "stl.h" + +#ifdef COMPLEX_OPERATOR + +typedef struct +{ + Word32 re; + Word32 im; +}cmplx; + +typedef struct +{ + Word16 re; + Word16 im; +}cmplx_s; + +/*___________________________________________________________________________ + | | + | Prototypes for complex arithmetic operators | + |___________________________________________________________________________| +*/ + +cmplx CL_shr (cmplx inp, Word32 shift_val); +cmplx CL_shl (cmplx inp, Word32 shift_val); +cmplx CL_add (cmplx inp1, cmplx inp2); +cmplx CL_sub (cmplx inp1, cmplx inp2); +cmplx CL_scale (cmplx x, Word16 y); +cmplx CL_dscale (cmplx x, Word16 y1, Word16 y2); +cmplx CL_msu_j (cmplx x, cmplx y); +cmplx CL_mac_j (cmplx x, cmplx y); +cmplx CL_move (cmplx x); +Word32 CL_Extract_real (cmplx x); +Word32 CL_Extract_imag (cmplx x); +cmplx CL_form (Word32 re, Word32 im); +cmplx CL_multr_32x16 (cmplx input, cmplx_s coeff); +cmplx CL_negate (cmplx x); +cmplx CL_conjugate (cmplx x); +cmplx CL_mul_j (cmplx input); +cmplx CL_swap_real_imag (cmplx input); +cmplx_s C_add (cmplx_s inp1, cmplx_s inp2); +cmplx_s C_sub (cmplx_s inp1, cmplx_s inp2); +cmplx_s C_mul_j (cmplx_s input); +cmplx_s C_multr (cmplx_s x, cmplx_s c); +cmplx_s C_form (Word16 re, Word16 im ); + +cmplx C_scale (cmplx_s x, Word16 y); +cmplx_s CL_round32_16 (cmplx x); +cmplx CL_scale_32 (cmplx x, Word32 y); +cmplx CL_dscale_32 (cmplx x, Word32 y1, Word32 y2); +cmplx CL_multr_32x32 (cmplx x, cmplx y); +cmplx_s C_mac_r (cmplx x, cmplx_s y, Word16 c); +cmplx_s C_msu_r (cmplx x, cmplx_s y, Word16 c); +Word16 C_Extract_real (cmplx_s x ); +Word16 C_Extract_imag (cmplx_s x ); +cmplx_s C_negate (cmplx_s x); +cmplx_s C_conjugate (cmplx_s x); +cmplx_s C_shr (cmplx_s inp, Word16 shift_val); +cmplx_s C_shl (cmplx_s inp, Word16 shift_val); + +#endif /* #ifdef COMPLEX_OPERATOR */ + +#endif /* ifndef _COMPLEX_BASIC_OP_H */ + diff --git a/basic_op/control.c b/basic_op/control.c new file mode 100644 index 0000000..2d0a46c --- /dev/null +++ b/basic_op/control.c @@ -0,0 +1,250 @@ +/* + =========================================================================== + File: CONTROL.C v.2.3 - 30.Nov.2009 + =========================================================================== + + ITU-T STL BASIC OPERATORS + + CONTROL FLOW OPERATOR INTERNAL VARIABLE DECLARATIONS + + History: + 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control + operators for the ITU-T Standard Tool Library as + described in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + TD 11 document and subsequent discussions on the + wp3audio@yahoogroups.com email reflector. + March 06 v2.1 Changed to improve portability. + + ============================================================================ +*/ + +#include "stl.h" + +#ifdef WMOPS +int funcId_where_last_call_to_else_occurred; +long funcid_total_wmops_at_last_call_to_else; +int call_occurred = 1; +#endif + +#ifdef CONTROL_CODE_OPS + +Flag LT_16 (Word16 var1, Word16 var2) { + Flag F_ret = 0; + + if( var1 < var2 ) + { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].LT_16++; +#endif + return F_ret; +} + +Flag GT_16 (Word16 var1, Word16 var2) { + Flag F_ret = 0; + + if( var1 > var2 ) + { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].GT_16++; +#endif + return F_ret; +} + +Flag LE_16 (Word16 var1, Word16 var2) { + Flag F_ret = 0; + + if (var1 <= var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].LE_16++; +#endif + return F_ret; +} + +Flag GE_16 (Word16 var1, Word16 var2) { + Flag F_ret = 0; + + if (var1 >= var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].GE_16++; +#endif + return F_ret; +} + +Flag EQ_16 (Word16 var1, Word16 var2) { + Flag F_ret = 0; + + if (var1 == var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].EQ_16++; +#endif + return F_ret; +} + +Flag NE_16 (Word16 var1, Word16 var2) { + Flag F_ret = 0; + + if (var1 != var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].NE_16++; +#endif + return F_ret; +} + +Flag LT_32 (Word32 L_var1, Word32 L_var2) { + Flag F_ret = 0; + + if (L_var1 < L_var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].LT_32++; +#endif + return F_ret; +} + +Flag GT_32 (Word32 L_var1, Word32 L_var2) { + Flag F_ret = 0; + + if (L_var1 > L_var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].GT_32++; +#endif + return F_ret; +} + +Flag LE_32 (Word32 L_var1, Word32 L_var2) { + Flag F_ret = 0; + + if (L_var1 <= L_var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].LE_32++; +#endif + return F_ret; +} + +Flag GE_32 (Word32 L_var1, Word32 L_var2) { + Flag F_ret = 0; + + if (L_var1 >= L_var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].GE_32++; +#endif + return F_ret; +} + +Flag EQ_32 (Word32 L_var1, Word32 L_var2) { + Flag F_ret = 0; + + if (L_var1 == L_var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].EQ_32++; +#endif + return F_ret; +} + +Flag NE_32 (Word32 L_var1, Word32 L_var2) { + Flag F_ret = 0; + + if (L_var1 != L_var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].NE_32++; +#endif + return F_ret; +} + +Flag LT_64 (Word64 L64_var1, Word64 L64_var2) { + Flag F_ret = 0; + + if (L64_var1 < L64_var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].LT_64++; +#endif + return F_ret; +} + +Flag GT_64 (Word64 L64_var1, Word64 L64_var2) { + Flag F_ret = 0; + + if (L64_var1 > L64_var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].GT_64++; +#endif + return F_ret; +} + +Flag LE_64 (Word64 L64_var1, Word64 L64_var2) { + Flag F_ret = 0; + + if (L64_var1 <= L64_var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].LE_64++; +#endif + return F_ret; +} +Flag GE_64 (Word64 L64_var1, Word64 L64_var2) { + Flag F_ret = 0; + + if (L64_var1 >= L64_var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].GE_64++; +#endif + return F_ret; +} + +Flag EQ_64 (Word64 L64_var1, Word64 L64_var2) { + Flag F_ret = 0; + + if (L64_var1 == L64_var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].EQ_64++; +#endif + return F_ret; +} +Flag NE_64 (Word64 L64_var1, Word64 L64_var2) { + Flag F_ret = 0; + + if (L64_var1 != L64_var2) { + F_ret = 1; + } +#if (WMOPS) + multiCounter[currCounter].NE_64++; +#endif + return F_ret; +} + +#endif /* #ifdef CONTROL_CODE_OPS */ + + +/* end of file */ diff --git a/basic_op/control.h b/basic_op/control.h new file mode 100644 index 0000000..4f406e2 --- /dev/null +++ b/basic_op/control.h @@ -0,0 +1,332 @@ +/* + =========================================================================== + File: CONTROL.H v.2.3 - 30.Nov.2009 + =========================================================================== + + ITU-T STL BASIC OPERATORS + + CONTROL FLOW OPERATORS + + History: + 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control + operators for the ITU-T Standard Tool Library as + described in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + TD 11 document and subsequent discussions on the + wp3audio@yahoogroups.com email reflector. + March 06 v2.1 Changed to improve portability. + + ============================================================================ +*/ + +#ifndef _CONTROL_H +#define _CONTROL_H + +#include "stl.h" + + +/***************************************************************************** + * + * Constants and Globals + * + *****************************************************************************/ +#if (WMOPS) +extern BASIC_OP multiCounter[MAXCOUNTERS]; +extern int currCounter; + + /* Technical note : + * The following 3 variables are only used for correct complexity + * evaluation of the following structure : + * IF{ + * ... + * } ELSE IF { + * ... + * } ELSE IF { + * ... + * } + * ... + * } ELSE { + * ... + * } + */ +extern int funcId_where_last_call_to_else_occurred; +extern long funcid_total_wmops_at_last_call_to_else; +extern int call_occurred; +#endif /* ifdef WMOPS */ + + +/***************************************************************************** + * + * Function Macros + * + *****************************************************************************/ + +/***************************************************************************** + * + * Function Name : FOR + * + * Purpose : + * + * The macro FOR should be used instead of the 'for' C statement. + * The complexity is independent of the number of loop iterations that are + * performed. + * + * Complexity weight : 3 (regardless of number of iterations). + * + *****************************************************************************/ +#ifndef WMOPS +#define FOR( a) for( a) + +#else /* ifndef WMOPS */ +#define FOR( a) if( incrFor(), 0); else for( a) + +static __inline void incrFor (void) { + multiCounter[currCounter].For++; +} +#endif /* ifndef WMOPS */ + + +/***************************************************************************** + * + * Function Name : WHILE + * + * Purpose : + * + * The macro WHILE should be used instead of the 'while' C statement. + * The complexity is proportional to the number of loop iterations that + * are performed. + * + * Complexity weight : 4 x 'number of loop iterations'. + * + *****************************************************************************/ +#ifndef WMOPS +#define WHILE(a) while (a) + +#else /* ifndef WMOPS */ +#define WHILE(a) while (incrWhile(), a) + +static __inline void incrWhile (void) { + multiCounter[currCounter].While++; +} +#endif /* ifndef WMOPS */ + + +/***************************************************************************** + * + * Function Name : DO + * + * Purpose : + * + * The macro DO should be used instead of the 'do' C statement. + * + * Complexity weight : 0 (complexity counted by WHILE macro). + * + *****************************************************************************/ +#ifndef WMOPS +#define DO do + +#else /* ifndef WMOPS */ +#define DO do + +#endif /* ifndef WMOPS */ + + +/***************************************************************************** + * + * Function Name : IF + * + * Purpose : + * + * The macro IF should : + * + * - not be used when : + * - the 'if' structure does not have any 'else if' nor 'else' statement + * - and it conditions only one DSP basic operations. + * + * - be used instead of the 'if' C statement in every other case : + * - when there is an 'else' or 'else if' statement, + * - or when the 'if' conditions several DSP basic operations, + * - or when the 'if' conditions a function call. + * + * Complexity weight : 4 + * + *****************************************************************************/ +#ifndef WMOPS +#define IF(a) if (a) + +#else /* ifndef WMOPS */ +#define IF(a) if (incrIf (), a) + +static __inline void incrIf (void) { + /* Technical note : + * If the "IF" operator comes just after an "ELSE", its counter + * must not be incremented. + */ + if ((currCounter != funcId_where_last_call_to_else_occurred) + || (TotalWeightedOperation () != funcid_total_wmops_at_last_call_to_else) + || (call_occurred == 1)) + multiCounter[currCounter].If++; + + call_occurred = 0; + funcId_where_last_call_to_else_occurred = MAXCOUNTERS; +} +#endif /* ifndef WMOPS */ + + +/***************************************************************************** + * + * Function Name : ELSE + * + * Purpose : + * + * The macro ELSE should be used instead of the 'else' C statement. + * + * Complexity weight : 4 + * + *****************************************************************************/ +#ifndef WMOPS +#define ELSE else + +#else /* ifndef WMOPS */ +#define ELSE else if (incrElse (), 0) ; else + +static __inline void incrElse (void) { + multiCounter[currCounter].If++; + + /* We keep track of the funcId of the last function which used ELSE {...} structure. */ + funcId_where_last_call_to_else_occurred = currCounter; + + /* We keep track of the number of WMOPS of this funcId when the ELSE macro was called. */ + funcid_total_wmops_at_last_call_to_else = TotalWeightedOperation (); + + /* call_occurred is set to 0, in order to count the next IF (if necessary) */ + call_occurred = 0; +} +#endif /* ifndef WMOPS */ + + +/***************************************************************************** + * + * Function Name : SWITCH + * + * Purpose : + * + * The macro SWITCH should be used instead of the 'switch' C statement. + * + * Complexity weight : 8 + * + *****************************************************************************/ +#ifndef WMOPS +#define SWITCH(a) switch (a) + +#else /* ifndef WMOPS */ +#define SWITCH(a) switch (incrSwitch (), a) + +static __inline void incrSwitch (void) { + multiCounter[currCounter].Switch++; +} +#endif /* ifndef WMOPS */ + + +/***************************************************************************** + * + * Function Name : CONTINUE + * + * Purpose : + * + * The macro CONTINUE should be used instead of the 'continue' C statement. + * + * Complexity weight : 4 + * + *****************************************************************************/ +#ifndef WMOPS +#define CONTINUE continue + +#else /* ifndef WMOPS */ +#define CONTINUE if (incrContinue (), 0); else continue + +static __inline void incrContinue (void) { + multiCounter[currCounter].Continue++; +} +#endif /* ifndef WMOPS */ + + +/***************************************************************************** + * + * Function Name : BREAK + * + * Purpose : + * + * The macro BREAK should be used instead of the 'break' C statement. + * + * Complexity weight : 4 + * + *****************************************************************************/ +#ifndef WMOPS +#define BREAK break + +#else /* ifndef WMOPS */ +#define BREAK if (incrBreak (), 0); else break + +static __inline void incrBreak (void) { + multiCounter[currCounter].Break++; +} +#endif /* ifndef WMOPS */ + + +/***************************************************************************** + * + * Function Name : GOTO + * + * Purpose : + * + * The macro GOTO should be used instead of the 'goto' C statement. + * + * Complexity weight : 4 + * + *****************************************************************************/ +#ifndef WMOPS +#define GOTO goto + +#else /* ifndef WMOPS */ +#define GOTO if (incrGoto (), 0); else goto + +static __inline void incrGoto (void) { + multiCounter[currCounter].Goto++; +} +#endif /* ifndef WMOPS */ + + + +/* + * New control code basops +*/ +#ifdef CONTROL_CODE_OPS + +Flag LT_16 (Word16 var1, Word16 var2); +Flag GT_16 (Word16 var1, Word16 var2); +Flag LE_16 (Word16 var1, Word16 var2); +Flag GE_16 (Word16 var1, Word16 var2); +Flag EQ_16 (Word16 var1, Word16 var2); +Flag NE_16 (Word16 var1, Word16 var2); + +Flag LT_32 (Word32 L_var1, Word32 L_var2); +Flag GT_32 (Word32 L_var1, Word32 L_var2); +Flag LE_32 (Word32 L_var1, Word32 L_var2); +Flag GE_32 (Word32 L_var1, Word32 L_var2); +Flag EQ_32 (Word32 L_var1, Word32 L_var2); +Flag NE_32 (Word32 L_var1, Word32 L_var2); + +Flag LT_64 (Word64 L64_var1, Word64 L64_var2); +Flag GT_64 (Word64 L64_var1, Word64 L64_var2); +Flag LE_64 (Word64 L64_var1, Word64 L64_var2); +Flag GE_64 (Word64 L64_var1, Word64 L64_var2); +Flag EQ_64 (Word64 L64_var1, Word64 L64_var2); +Flag NE_64 (Word64 L64_var1, Word64 L64_var2); + + +#endif /* #ifdef CONTROL_CODE_OPS */ + +#endif /* _CONTROL_H */ + + +/* end of file */ diff --git a/basic_op/count.c b/basic_op/count.c new file mode 100644 index 0000000..1fc839b --- /dev/null +++ b/basic_op/count.c @@ -0,0 +1,772 @@ +/* + =========================================================================== + File: COUNT.C v.2.3 - 30.Nov.2009 + =========================================================================== + + ITU-T STL BASIC OPERATORS + + COMPLEXITY EVALUATION FUNCTIONS + + History: + 03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control + operators for the ITU-T Standard Tool Library as + described in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + TD 11 document and subsequent discussions on the + wp3audio@yahoogroups.com email reflector. + norm_s() weight reduced from 15 to 1. + norm_l() weight reduced from 30 to 1. + L_abs() weight reduced from 2 to 1. + L_add() weight reduced from 2 to 1. + L_negate() weight reduced from 2 to 1. + L_shl() weight reduced from 2 to 1. + L_shr() weight reduced from 2 to 1. + L_sub() weight reduced from 2 to 1. + mac_r() weight reduced from 2 to 1. + msu_r() weight reduced from 2 to 1. + mult_r() weight reduced from 2 to 1. + L_deposit_h() weight reduced from 2 to 1. + L_deposit_l() weight reduced from 2 to 1. + March 06 v2.1 Changed to improve portability. + Dec 06 v2.2 Changed to specify frame rate using setFrameRate() + Adding WMOPS_output_avg() for global average computation + L_mls() weight of 5. + div_l() weight of 32. + i_mult() weight of 3. + ============================================================================ +*/ + + +/***************************************************************************** + * + * This file contains functions for the automatic complexity calculation + * + *****************************************************************************/ + + +#include +#include +#include +#include "stl.h" + +#ifdef WMOPS +static double frameRate = FRAME_RATE; /* default value : 10 ms */ +#endif /* ifdef WMOPS */ + +#ifdef WMOPS +/* Global counter variable for calculation of complexity weight */ +BASIC_OP multiCounter[MAXCOUNTERS]; +int currCounter = 0; /* Zero equals global counter */ +#endif /* ifdef WMOPS */ + +#ifdef WMOPS +void setFrameRate (int samplingFreq, int frameLength) { + if (frameLength > 0) { + frameRate = samplingFreq / 1000000.0 / frameLength; + } + return; +} + +#endif /* ifdef WMOPS */ + +#ifdef WMOPS +/* + * Below list is used for displaying the code profiling information in + * the file which name is defined by CODE_PROFILE_FILENAME. + * For further details see generic_WMOPS_output() function. + * Attention, the ordering in this table must be kept in synchronisation + * with the structure definition BASIC_OP. + */ +char *BasicOperationList[] = { + "add", "sub", "abs_s", "shl", "shr", + "extract_h", "extract_l", "mult", "L_mult", "negate", + "round", "L_mac", "L_msu", "L_macNs", "L_msuNs", + "L_add", "L_sub", "L_add_c", "L_sub_c", "L_negate", + "L_shl", "L_shr", "mult_r", "shr_r", "mac_r", + + "msu_r", "L_deposit_h", "L_deposit_l", "L_shr_r", "L_abs", + "L_sat", "norm_s", "div_s", "norm_l", "move16", + "move32", "Logic16", "Logic32", "Test", "s_max", + "s_min", "L_max", "L_min", "L40_max", "L40_min", + "shl_r", "L_shl_r", "L40_shr_r", "L40_shl_r", "norm_L40", + + "L40_shl", "L40_shr", "L40_negate", "L40_add", "L40_sub", + "L40_abs", "L40_mult", "L40_mac", "mac_r40", + "L40_msu", "msu_r40", "Mpy_32_16_ss", "Mpy_32_32_ss", "L_mult0", + "L_mac0", "L_msu0", "lshl", "lshr", "L_lshl", + "L_lshr", "L40_lshl", "L40_lshr", "s_and", "s_or", + + "s_xor", "L_and", "L_or", "L_xor", "rotl", + "rotr", "L_rotl", "L_rotr", "L40_set", "L40_deposit_h", + "L40_deposit_l", "L40_deposit32", "Extract40_H", "Extract40_L", "L_Extract40", + "L40_round", "L_saturate40", "round40", "IF", "GOTO", + "BREAK", "SWITCH", "FOR", "WHILE", "CONTINUE", + + "L_mls", "div_l", "i_mult" + + /* New complex basops */ + #ifdef COMPLEX_OPERATOR + , "CL_shr", "CL_shl", "CL_add" + , "CL_sub", "CL_scale", "CL_dscale" + , "CL_msu_j", "CL_mac_j", "CL_move" + , "CL_Extract_real", "CL_Extract_imag", "CL_form" + , "CL_multr_32x16", "CL_negate", "CL_conjugate" + , "CL_mul_j" + , "CL_swap_real_imag" + , "C_add" + , "C_sub" + , "C_mul_j" + , "C_multr" + , "C_form" + + , "C_scale" + , "CL_round32_16", "CL_scale_32", "CL_dscale_32", "CL_multr_32x32" + , "C_mac_r", "C_msu_r", "C_Extract_real", "C_Extract_imag" + , "C_negate", "C_conjugate" + , "C_shr", "C_shl" + +#endif /* #ifdef COMPLEX_OPERATOR */ + + /* New 64 bit basops */ +#ifdef ENH_64_BIT_OPERATOR + , "move64" , "W_add_nosat" ,"W_sub_nosat" + , "W_shl" , "W_shr" + , "W_shl_nosat" , "W_shr_nosat" + , "W_mac_32_16" , "W_msu_32_16" , "W_mult_32_16" + , "W_mult0_16_16" , "W_mac0_16_16" , "W_msu0_16_16" + , "W_mult_16_16" , "W_mac_16_16" , "W_msu_16_16" + , "W_shl_sat_l" , "W_sat_l" + , "W_sat_m" , "W_deposit32_l" ,"W_deposit32_h" + , "W_extract_l" , "W_extract_h" + , "W_round48_L" , "W_round32_s" + , "W_norm" + , "W_add" , "W_sub" ,"W_neg" ,"W_abs" + , "W_mult_32_32" , "W_mult0_32_32" + , "W_lshl" , "W_lshr" ,"W_round64_L" + +#endif /* #ifdef ENH_64_BIT_OPERATOR */ + +#ifdef ENH_32_BIT_OPERATOR + , "Mpy_32_16_1" + , "Mpy_32_16_r" + , "Mpy_32_32" + , "Mpy_32_32_r" + , "Madd_32_16" + , "Madd_32_16_r" + , "Msub_32_16" + , "Msub_32_16_r" + , "Madd_32_32" + , "Madd_32_32_r" + , "Msub_32_32" + , "Msub_32_32_r" +#endif /* #ifdef ENH_32_BIT_OPERATOR */ + +#ifdef ENH_U_32_BIT_OPERATOR + , "UL_addNs" + , "UL_subNs" + , "UL_Mpy_32_32" + , "Mpy_32_32_uu" + , "Mpy_32_16_uu" + , "norm_ul" + , "UL_deposit_l" +#endif /* #ifdef ENH_U_32_BIT_OPERATOR */ + +#ifdef CONTROL_CODE_OPS + , "LT_16" + , "GT_16" + , "LE_16" + , "GE_16" + , "EQ_16" + , "NE_16" + , "LT_32" + , "GT_32" + , "LE_32" + , "GE_32" + , "EQ_32" + , "NE_32" + , "LT_64" + , "GT_64" + , "LE_64" + , "GE_64" + , "EQ_64" + , "NE_64" +#endif /* #ifdef CONTROL_CODE_OPS */ + +}; +#endif /* ifdef WMOPS */ + + +#ifdef WMOPS +const BASIC_OP op_weight = { + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 2, 2, 1, + 1, 1, 1, 2, 1, + + 1, 1, 1, 2, 1, + 1, 1, 18, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 2, 2, 2, 2, 1, + + 1, 1, 1, 1, 1, + 1, 1, 1, 2, + 1, 2, 2, 2, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 3, + 3, 3, 3, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 3, 2, + 2, 6, 3, 3, 2, + + 1, 32, 1 + +/* New complex basops */ + #ifdef COMPLEX_OPERATOR + , 1, 1, 1 + , 1, 1, 1 + , 1, 1, 1 + , 1, 1, 1 + , 2, 1, 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 2 + , 1 + + , 1 + , 1, 1, 1, 2 + , 2, 2, 1, 1 + , 1, 1 + , 1, 1 + +#endif /* #ifdef COMPLEX_OPERATOR */ + +#ifdef ENH_64_BIT_OPERATOR + /* Weights of new 64 bit basops */ + , 1 , 1 ,1 + , 1 , 1 + , 1 , 1 + , 1 , 1 , 1 + , 1 , 1 , 1 + , 1 , 1 , 1 + , 1 , 1 + , 1 , 1 , 1 + , 1 , 1 + , 1 , 1 + , 1 + , 1 , 1 , 1 , 1 + , 1 , 1 + , 1 , 1 , 1 +#endif /* #ifdef ENH_64_BIT_OPERATOR */ + +#ifdef ENH_32_BIT_OPERATOR + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 +#endif /* #ifdef ENH_32_BIT_OPERATOR */ + +#ifdef ENH_U_32_BIT_OPERATOR + , 1 + , 1 + , 1 + , 2 + , 2 + , 1 + , 1 +#endif /* #ifdef ENH_U_32_BIT_OPERATOR */ + +#ifdef CONTROL_CODE_OPS + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 + , 1 +#endif /* #ifdef CONTROL_CODE_OPS */ +}; +#endif /* ifdef WMOPS */ + + +Word32 TotalWeightedOperation (void); +Word32 DeltaWeightedOperation (void); + + +#ifdef WMOPS +/* Counters for separating counting for different objects */ + + +static int maxCounter = 0; +static char *objectName[MAXCOUNTERS + 1]; + +static Word16 fwc_corr[MAXCOUNTERS + 1]; +static long int nbTimeObjectIsCalled[MAXCOUNTERS + 1]; + +#define NbFuncMax 1024 + +static Word16 funcid[MAXCOUNTERS], nbframe[MAXCOUNTERS]; +static Word32 glob_wc[MAXCOUNTERS], wc[MAXCOUNTERS][NbFuncMax]; +static float total_wmops[MAXCOUNTERS]; + +static Word32 LastWOper[MAXCOUNTERS]; +#endif /* ifdef WMOPS */ + + +#ifdef WMOPS +static char *my_strdup (const char *s) { + /* + * duplicates UNIX function strdup() which is not ANSI standard: + * -- malloc() memory area big enough to hold the string s + * -- copy string into new area + * -- return pointer to new area + * + * returns NULL if either s==NULL or malloc() fails + */ + char *dup; + + if (s == NULL) + return NULL; + + /* allocate memory for copy of ID string (including string terminator) */ + /* NOTE: the ID strings will never be deallocated because there is no way to "destroy" a counter that is not longer needed */ + if ((dup = (char *) malloc (strlen (s) + 1)) == NULL) + return NULL; + + return strcpy (dup, s); +} +#endif /* ifdef WMOPS */ + + +int getCounterId (char *objectNameArg) { +#if WMOPS + if (maxCounter >= MAXCOUNTERS - 1) + return 0; + objectName[++maxCounter] = my_strdup (objectNameArg); + return maxCounter; + +#else /* ifdef WMOPS */ + (void)objectNameArg; + return 0; /* Dummy */ + +#endif /* ifdef WMOPS */ +} + + +#if WMOPS +int readCounterId () { + return currCounter; +} +#endif /* ifdef WMOPS */ + + +#ifdef WMOPS +char *readCounterIdName () { + return objectName[currCounter]; +} +#endif /* ifdef WMOPS */ + +void setCounter (int counterId) { +#if WMOPS + if ((counterId > maxCounter) + || (counterId < 0)) { + currCounter = 0; + return; + } + currCounter = counterId; + call_occurred = 1; +#else + (void)counterId; +#endif /* ifdef WMOPS */ +} + + +void incrementNbTimeObjectIsCalled (int counterId) { +#if WMOPS + if ((counterId > maxCounter) + || (counterId < 0)) { + nbTimeObjectIsCalled[0]++; + return; + } + nbTimeObjectIsCalled[counterId]++; +#else + (void)counterId; +#endif /* ifdef WMOPS */ +} + + +#if WMOPS +static Word32 WMOPS_frameStat (void) { +/* calculate the WMOPS seen so far and update the global + per-frame maximum (glob_wc) + */ + Word32 tot; + + tot = TotalWeightedOperation (); + if (tot > glob_wc[currCounter]) + glob_wc[currCounter] = tot; + + /* check if fwc() was forgotten at end of last frame */ + if (tot > LastWOper[currCounter]) { + if (!fwc_corr[currCounter]) { + fprintf (stderr, + "count: operations counted after last fwc() for '%s'; " "-> fwc() called\n", + objectName[currCounter] ? objectName[currCounter] : ""); + } + fwc (); + } + + return tot; +} +#endif /* ifdef WMOPS */ + + +#ifdef WMOPS +static void WMOPS_clearMultiCounter (void) { + Word16 i; + + Word32 *ptr = (Word32 *) & multiCounter[currCounter]; + for (i = 0; i < (Word16)(sizeof (multiCounter[currCounter]) / sizeof (Word32)); i++) { + *ptr++ = 0; + } +} +#endif /* ifdef WMOPS */ + + +void ClearNbTimeObjectsAreCalled () { +#if WMOPS + Word16 i; + + for (i = 0; i < (Word16)(sizeof (multiCounter[currCounter]) / sizeof (Word32)); i++) { + nbTimeObjectIsCalled[i] = 0; + } +#endif /* ifdef WMOPS */ +} + +Word32 TotalWeightedOperation () { +#if WMOPS + Word16 i; + Word32 tot, *ptr, *ptr2; + + tot = 0; + ptr = (Word32 *) & multiCounter[currCounter]; + ptr2 = (Word32 *) & op_weight; + for (i = 0; i < (Word16)(sizeof (multiCounter[currCounter]) / sizeof (Word32)); i++) { + tot += ((*ptr++) * (*ptr2++)); + } + + return ((Word32) tot); + +#else /* ifdef WMOPS */ + return 0; /* Dummy */ + +#endif /* ifdef WMOPS */ + +} + +Word32 DeltaWeightedOperation () { +#if WMOPS + Word32 NewWOper, delta; + + NewWOper = TotalWeightedOperation (); + delta = NewWOper - LastWOper[currCounter]; + LastWOper[currCounter] = NewWOper; + return (delta); + +#else /* ifdef WMOPS */ + return 0; /* Dummy */ + +#endif /* ifdef WMOPS */ +} + + +void Init_WMOPS_counter (void) { +#if WMOPS + Word16 i; + + /* reset function weight operation counter variable */ + + for (i = 0; i < NbFuncMax; i++) + wc[currCounter][i] = (Word32) 0; + glob_wc[currCounter] = 0; + nbframe[currCounter] = 0; + total_wmops[currCounter] = 0.0; + + /* initially clear all counters */ + WMOPS_clearMultiCounter (); + LastWOper[currCounter] = 0; + funcid[currCounter] = 0; + + /* Following line is useful for incrIf(), see control.h */ + call_occurred = 1; + funcId_where_last_call_to_else_occurred = MAXCOUNTERS; +#endif /* ifdef WMOPS */ +} + + +void Reset_WMOPS_counter (void) { +#if WMOPS + Word32 tot = WMOPS_frameStat (); + + /* increase the frame counter --> a frame is counted WHEN IT BEGINS */ + nbframe[currCounter]++; + + /* add wmops used in last frame to count, then reset counter (in first frame, this is a no-op */ + total_wmops[currCounter] += (float) (tot * frameRate); + + /* clear counter before new frame starts */ + WMOPS_clearMultiCounter (); + LastWOper[currCounter] = 0; + funcid[currCounter] = 0; /* new frame, set function id to zero */ +#endif /* ifdef WMOPS */ +} + + +Word32 fwc (void) { +/* function worst case */ +#if WMOPS + Word32 tot; + + tot = DeltaWeightedOperation (); + if (tot > wc[currCounter][funcid[currCounter]]) + wc[currCounter][funcid[currCounter]] = tot; + + funcid[currCounter]++; + return (tot); + +#else /* ifdef WMOPS */ + return 0; /* Dummy */ + +#endif /* ifdef WMOPS */ +} + +void WMOPS_output (Word16 dtx_mode) { +#if WMOPS + Word16 i; + Word32 tot, tot_wm, tot_wc; + + /* get operations since last reset (or init), but do not update the counters (except the glob_wc[] maximum) + so output CAN be called in each frame without problems. The frame counter is NOT updated! */ + tot = WMOPS_frameStat (); + tot_wm = (Word32) (total_wmops[currCounter] + ((float) tot) * frameRate); + + fprintf (stdout, + "%10s:WMOPS=%.3f", objectName[currCounter] ? objectName[currCounter] : "", + ((float) tot) * frameRate); + + if (nbframe[currCounter] != 0) { + fprintf (stdout, " Average=%.3f", tot_wm / (float) nbframe[currCounter]); + } + fprintf (stdout, " WorstCase=%.3f", ((float) glob_wc[currCounter]) * frameRate); + + /* Worst worst case printed only when not in DTX mode */ + if (dtx_mode == 0) { + tot_wc = 0L; + for (i = 0; i < funcid[currCounter]; i++) + tot_wc += wc[currCounter][i]; + fprintf (stdout, " WorstWC=%.3f", ((float) tot_wc) * frameRate); + } + fprintf (stdout, " (%d frames)\n", nbframe[currCounter]); +#else + (void)dtx_mode; +#endif /* ifdef WMOPS */ +} + + +void WMOPS_output_avg (Word16 dtx_mode, Word32 * tot_wm, Word16 * num_frames) { +#if WMOPS + Word16 i; + Word32 tot, tot_wc; + + /* get operations since last reset (or init), but do not update the counters (except the glob_wc[] maximum) + so output CAN be called in each frame without problems. The frame counter is NOT updated! */ + tot = WMOPS_frameStat (); + *tot_wm = (Word32) (total_wmops[currCounter] + ((float) tot) * frameRate); + *num_frames = nbframe[currCounter]; + + fprintf (stdout, "%10s:WMOPS=%.3f", objectName[currCounter] ? objectName[currCounter] : "", ((float) tot) * frameRate); + + if (nbframe[currCounter] != 0) { + fprintf (stdout, " Average=%.3f", *tot_wm / (float) nbframe[currCounter]); + } + fprintf (stdout, " WorstCase=%.3f", ((float) glob_wc[currCounter]) * frameRate); + + /* Worst worst case printed only when not in DTX mode */ + if (dtx_mode == 0) { + tot_wc = 0L; + for (i = 0; i < funcid[currCounter]; i++) + tot_wc += wc[currCounter][i]; + fprintf (stdout, " WorstWC=%.3f", ((float) tot_wc) * frameRate); + } + fprintf (stdout, " (%d frames)\n", nbframe[currCounter]); +#else + (void)dtx_mode; + (void)tot_wm; + (void)num_frames; +#endif /* ifdef WMOPS */ +} + +void generic_WMOPS_output (Word16 dtx_mode, char *test_file_name) { +#if WMOPS + int saved_value; + Word16 i; + Word32 tot, tot_wm, tot_wc, *ptr, *ptr2; + Word40 grand_total; + FILE *WMOPS_file; + + saved_value = currCounter; + + /* Count the grand_total WMOPS so that % ratio per function group can be displayed. */ + grand_total = 0; + for (currCounter = 0; currCounter <= maxCounter; currCounter++) { + tot = WMOPS_frameStat (); + grand_total += tot; + } + + + if ((WMOPS_file = fopen (WMOPS_DATA_FILENAME, "a")) != NULL) { + + printf ("opened file %s in order to print WMOPS for each function group.\n", WMOPS_DATA_FILENAME); + + /* Print the file header line. */ + fprintf (WMOPS_file, "Test file name\tFunction Name \tFrame\tNb Times Called\tWMOPS\t%% versus grand total"); + + if (nbframe[saved_value] != 0) + fprintf (WMOPS_file, "\tAverage"); + + fprintf (WMOPS_file, "\tWorstCase"); + + /* Worst worst case printed only when not in DTX mode */ + if (dtx_mode == 0) + fprintf (WMOPS_file, "\tWorstWC"); + + fprintf (WMOPS_file, "\n"); + + /* Print the WMOPS for each Function Group by scanning all the function groups with currCounter index. */ + for (currCounter = 0; currCounter <= maxCounter; currCounter++) { + + fprintf (WMOPS_file, "%s", test_file_name); + fprintf (WMOPS_file, "\t%s", objectName[currCounter] ? objectName[currCounter] : ""); + fprintf (WMOPS_file, "\t%d", nbframe[currCounter]); + + tot = WMOPS_frameStat (); + tot_wm = (Word32) (total_wmops[currCounter] + ((float) tot) * frameRate); + + fprintf (WMOPS_file, "\t\t%ld", nbTimeObjectIsCalled[currCounter]); + fprintf (WMOPS_file, "\t%.6f", ((float) tot) * frameRate); + fprintf (WMOPS_file, "\t%.3f", ((float) tot) / grand_total * 100); + + if (nbframe[currCounter] != 0) + fprintf (WMOPS_file, "\t%.3f", tot_wm / (float) nbframe[currCounter]); + + fprintf (WMOPS_file, "\t%.3f", ((float) glob_wc[currCounter]) * frameRate); + + /* Worst worst case printed only when not in DTX mode */ + if (dtx_mode == 0) { + tot_wc = 0L; + for (i = 0; i < funcid[currCounter]; i++) + tot_wc += wc[currCounter][i]; + fprintf (WMOPS_file, "\t%.3f", ((float) tot_wc) * frameRate); + } + fprintf (WMOPS_file, "\n"); + + } + + /* Print the file Grand Total line */ + fprintf (WMOPS_file, "%s", test_file_name); + fprintf (WMOPS_file, "\tGrand Total"); + fprintf (WMOPS_file, "\t%d", nbframe[saved_value]); + fprintf (WMOPS_file, "\t\t%.6f", ((float) grand_total) * frameRate); + fprintf (WMOPS_file, "\t100.000"); + fprintf (WMOPS_file, "\n"); + fclose (WMOPS_file); + + } else + printf ("Can not open file %s for WMOPS editing\n", WMOPS_DATA_FILENAME); + + + if ((WMOPS_file = fopen (WMOPS_TOTAL_FILENAME, "a")) != NULL) { + printf ("opened file %s in order to print application's total WMOPS.\n", WMOPS_TOTAL_FILENAME); + fprintf (WMOPS_file, "%s", test_file_name); + fprintf (WMOPS_file, "\tframe=%d", nbframe[currCounter]); + fprintf (WMOPS_file, "\tWMOPS=%.6f", ((float) grand_total) * frameRate); + fprintf (WMOPS_file, "\n"); + fclose (WMOPS_file); + + } else + printf ("Can not open file %s for WMOPS editing.\n", WMOPS_TOTAL_FILENAME); + + + if ((WMOPS_file = fopen (CODE_PROFILE_FILENAME, "a")) != NULL) { + + printf ("opened file %s in order to print basic operation distribution statistics.\n", CODE_PROFILE_FILENAME); + + /* Print the file header line. */ + fprintf (WMOPS_file, "Test file name\tBasic Operation Name\tframe\tWMOPS\t\t%% versus grand total\n"); + + /* Print the WMOPS for each Basic Operation across all the defined */ + /* Function Groups. */ + for (i = 0; i < (Word16)(sizeof (op_weight) / sizeof (Word32)); i++) { + fprintf (WMOPS_file, "%-16s", test_file_name); + fprintf (WMOPS_file, "\t%s", BasicOperationList[i]); + fprintf (WMOPS_file, "\t%d", nbframe[0]); + + tot = 0; + ptr = (Word32 *) & multiCounter[0] + i; + ptr2 = (Word32 *) & op_weight + i; + for (currCounter = 0; currCounter <= maxCounter; currCounter++) { + tot += ((*ptr) * (*ptr2)); + ptr += (sizeof (op_weight) / sizeof (Word32)); + } + + fprintf (WMOPS_file, "\t%.6f", ((float) tot) * frameRate); + fprintf (WMOPS_file, "\t%.3f", ((float) tot) / grand_total * 100); + fprintf (WMOPS_file, "\n"); + } + + /* Print the file Grand Total line */ + fprintf (WMOPS_file, "%s", test_file_name); + fprintf (WMOPS_file, "\tGrand Total"); + fprintf (WMOPS_file, "\t%d", nbframe[saved_value]); + fprintf (WMOPS_file, "\t%.6f", ((float) grand_total) * frameRate); + fprintf (WMOPS_file, "\t100.000"); + fprintf (WMOPS_file, "\n"); + fclose (WMOPS_file); + + } else + printf ("Can not open file %s for basic operations distribution statistic editing\n", CODE_PROFILE_FILENAME); + + currCounter = saved_value; + +#else + (void)dtx_mode; + (void)test_file_name; +#endif /* ifdef WMOPS */ +} + + +/* end of file */ diff --git a/basic_op/count.h b/basic_op/count.h new file mode 100644 index 0000000..e173de6 --- /dev/null +++ b/basic_op/count.h @@ -0,0 +1,542 @@ +/* + =========================================================================== + File: COUNT.H v.2.3 - 30.Nov.2009 + =========================================================================== + + ITU-T STL BASIC OPERATORS + + PROTOTYPES & DEFINITION FOR COUNTING OPERATIONS + + History + 09.Aug.1999 V1.0.0 Input to UGST from ETSI AMR (count.h); + + 26.Jan.2000 V1.1.0 Added counter entries for G.723.1's + L_mls(), div_l(), i_mult() [from basop32.c] + + 05.Jul.2000 V1.2.0 Added counter entries for 32bit shiftless + operators L_mult0(), L_mac0(), L_msu0() + + 03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control + operators for the ITU-T Standard Tool Library as + described in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + TD 11 document and subsequent discussions on the + wp3audio@yahoogroups.com email reflector. + March 06 v2.1 Changed to improve portability. + Dec 06 v2.2 Changed to specify frame rate using setFrameRate() + Adding WMOPS_output_avg() for global average computation + L_mls() weight of 5. + div_l() weight of 32. + i_mult() weight of 3. + ============================================================================ +*/ + + +/****************************************************************************** + * Functions for counting operations. + * + * These functions make it possible to measure the wMOPS of a codec. + * + * All functions in this file, and in other *.h files, update a structure so + * that it will be possible to track how many calls to add(), sub(), L_mult() + * ... was made by the code and to estimate the wMOPS (and MIPS) for a certain + * part of the code. + * + * It is also possible to measure the wMOPS separatly for different parts + * of the codec. + * + * This is done by creating a counter group (getCounterId) for each part of + * the code that one wants a seperate measure for. Before a part of the code + * is executed a call to the "setCounter" function is needed to identify + * which counter group to use. + * + * Currently there is a limit of 255 different counter groups. + * + * In the end of this file, there is a piece of code illustrating how the + * functions can be used. + * +******************************************************************************/ + + +#ifndef _COUNT_H +#define _COUNT_H "$Id$" +#if 0 +#define WMOPS 1 /* enable WMOPS profiling features */ +#undef WMOPS /* disable WMOPS profiling features */ +#endif +#define MAXCOUNTERS (256) + + +#define BASOP_sub_start(label) +#define BASOP_sub_end() +#define SUB_WMOPS_INIT(label) BASOP_sub_start(label) +#define END_SUB_WMOPS BASOP_sub_end() +#define BASOP_push_wmops(label) +#define BASOP_pop_wmops() +#define BASOP_end_noprint +#define BASOP_end +#define BASOP_init + +int getCounterId (char *objectName); +/* + * Create a counter group, the "objectname" will be used when printing + * statistics for this counter group. + * + * Returns 0 if no more counter groups are available. + */ + + +int readCounterId (void); +/* + * Returns the current CounterId. + */ + + +void setCounter (int counterId); +/* + * Defines which counter group to use, default is zero. + */ + + +char *readCounterIdName (void); +/* + * Returns the current CounterId name. + */ + + +void incrementNbTimeObjectIsCalled (int counterId); +/* + * This function enables to increment by 1 a counter + * tracking the number of times the application enters a groups of functions. + * If the counterId is not refering to a defined function counter group, then it is + * the default function group (0) which is impacted. + * + */ + + +void ClearNbTimeObjectsAreCalled (void); +/* + * This function enables to clear to 0 all the counters enabling to + * track the number of times the application enters any groups of functions. + */ + + +void Init_WMOPS_counter (void); +/* + * Initiates the current counter group. + */ + + +void Reset_WMOPS_counter (void); +/* + * Resets the current counter group. + */ + + +void WMOPS_output (Word16 notPrintWorstWorstCase); +/* + * Prints the statistics to the screen, if the argument is non zero + * the statistics for worst worst case will not be printed. This is typically + * done for dtx frames. + * + */ + +void WMOPS_output_avg (Word16 dtx_mode, Word32 * tot_wm, Word16 * num_frames); +/* + * same as WMOPS_output + returns the total wmops counter and the number of frames + * to support the computation of global average. + * + */ + + +Word32 fwc (void); +/* + * worst worst case counter. + * + * This function calculates the worst possible case that can be reached. + * + * This is done by calling this function for each subpart of the calculations + * for a frame. This function then stores the maximum wMOPS for each part. + * + * The WMOPS_output function add together all parts and presents the sum. + */ + +void setFrameRate (int samplingFreq, int frameLength); +/* + * This function can overwrite the value of the frameRate variable that is + * initialized by the FRAME_RATE constant. + */ + + +#define WMOPS_DATA_FILENAME "wmops_data.txt" +/* + * WMOPS_DATA_FILENAME is the macro defining the name of the file + * where the Weighted Million of Operations per Second (wMOPS) + * are appended, function group by function group. +*/ + + +#define CODE_PROFILE_FILENAME "code_profile.txt" +/* + * CODE_PROFILE_FILENAME is the macro defining the name of the file + * where the Weighted Million of Operations per Second (WMOPS) + * are appended, basic operation by basic operation. +*/ + + +#define WMOPS_TOTAL_FILENAME "wmops_total.txt" +/* + * WMOPS_TOTAL_FILENAME is the macro defining the name of the file + * where the Weighted Million of Operations per Second (WMOPS) + * are printed, globally for the application. +*/ + + +#define FRAME_RATE (0.0001F) /* in this version frame_rate can be overwriten online by the new setFrameRate function */ +/* FRAME_RATE of 0.000025 is corresponding to 40ms frame.*/ +/* FRAME_RATE of 0.00005 is corresponding to 20ms frame.*/ +/* FRAME_RATE of 0.0001 is corresponding to 10ms frame.*/ +/* + * FRAME_RATE is the macro defining the calling rate of the + * application to benchmark. +*/ + + +/* Global counter variable for calculation of complexity weight */ +typedef struct { + UWord32 add; /* Complexity Weight of 1 */ + UWord32 sub; /* Complexity Weight of 1 */ + UWord32 abs_s; /* Complexity Weight of 1 */ + UWord32 shl; /* Complexity Weight of 1 */ + UWord32 shr; /* Complexity Weight of 1 */ + + UWord32 extract_h; /* Complexity Weight of 1 */ + UWord32 extract_l; /* Complexity Weight of 1 */ + UWord32 mult; /* Complexity Weight of 1 */ + UWord32 L_mult; /* Complexity Weight of 1 */ + UWord32 negate; /* Complexity Weight of 1 */ + + UWord32 round; /* Complexity Weight of 1 */ + UWord32 L_mac; /* Complexity Weight of 1 */ + UWord32 L_msu; /* Complexity Weight of 1 */ + UWord32 L_macNs; /* Complexity Weight of 1 */ + UWord32 L_msuNs; /* Complexity Weight of 1 */ + + UWord32 L_add; /* Complexity Weight of 1 */ + UWord32 L_sub; /* Complexity Weight of 1 */ + UWord32 L_add_c; /* Complexity Weight of 2 */ + UWord32 L_sub_c; /* Complexity Weight of 2 */ + UWord32 L_negate; /* Complexity Weight of 1 */ + + UWord32 L_shl; /* Complexity Weight of 1 */ + UWord32 L_shr; /* Complexity Weight of 1 */ + UWord32 mult_r; /* Complexity Weight of 1 */ + UWord32 shr_r; /* Complexity Weight of 3 */ + UWord32 mac_r; /* Complexity Weight of 1 */ + + UWord32 msu_r; /* Complexity Weight of 1 */ + UWord32 L_deposit_h; /* Complexity Weight of 1 */ + UWord32 L_deposit_l; /* Complexity Weight of 1 */ + UWord32 L_shr_r; /* Complexity Weight of 3 */ + UWord32 L_abs; /* Complexity Weight of 1 */ + + UWord32 L_sat; /* Complexity Weight of 4 */ + UWord32 norm_s; /* Complexity Weight of 1 */ + UWord32 div_s; /* Complexity Weight of 18 */ + UWord32 norm_l; /* Complexity Weight of 1 */ + UWord32 move16; /* Complexity Weight of 1 */ + + UWord32 move32; /* Complexity Weight of 2 */ + UWord32 Logic16; /* Complexity Weight of 1 */ + UWord32 Logic32; /* Complexity Weight of 2 */ + UWord32 Test; /* Complexity Weight of 2 */ + UWord32 s_max; /* Complexity Weight of 1 */ + + UWord32 s_min; /* Complexity Weight of 1 */ + UWord32 L_max; /* Complexity Weight of 1 */ + UWord32 L_min; /* Complexity Weight of 1 */ + UWord32 L40_max; /* Complexity Weight of 1 */ + UWord32 L40_min; /* Complexity Weight of 1 */ + + UWord32 shl_r; /* Complexity Weight of 2 */ + UWord32 L_shl_r; /* Complexity Weight of 2 */ + UWord32 L40_shr_r; /* Complexity Weight of 2 */ + UWord32 L40_shl_r; /* Complexity Weight of 2 */ + UWord32 norm_L40; /* Complexity Weight of 1 */ + + UWord32 L40_shl; /* Complexity Weight of 1 */ + UWord32 L40_shr; /* Complexity Weight of 1 */ + UWord32 L40_negate; /* Complexity Weight of 1 */ + UWord32 L40_add; /* Complexity Weight of 1 */ + UWord32 L40_sub; /* Complexity Weight of 1 */ + + UWord32 L40_abs; /* Complexity Weight of 1 */ + UWord32 L40_mult; /* Complexity Weight of 1 */ + UWord32 L40_mac; /* Complexity Weight of 1 */ + UWord32 mac_r40; /* Complexity Weight of 2 */ + + UWord32 L40_msu; /* Complexity Weight of 1 */ + UWord32 msu_r40; /* Complexity Weight of 2 */ + UWord32 Mpy_32_16_ss; /* Complexity Weight of 2 */ + UWord32 Mpy_32_32_ss; /* Complexity Weight of 2 */ + UWord32 L_mult0; /* Complexity Weight of 1 */ + + UWord32 L_mac0; /* Complexity Weight of 1 */ + UWord32 L_msu0; /* Complexity Weight of 1 */ + UWord32 lshl; /* Complexity Weight of 1 */ + UWord32 lshr; /* Complexity Weight of 1 */ + UWord32 L_lshl; /* Complexity Weight of 1 */ + + UWord32 L_lshr; /* Complexity Weight of 1 */ + UWord32 L40_lshl; /* Complexity Weight of 1 */ + UWord32 L40_lshr; /* Complexity Weight of 1 */ + UWord32 s_and; /* Complexity Weight of 1 */ + UWord32 s_or; /* Complexity Weight of 1 */ + + UWord32 s_xor; /* Complexity Weight of 1 */ + UWord32 L_and; /* Complexity Weight of 1 */ + UWord32 L_or; /* Complexity Weight of 1 */ + UWord32 L_xor; /* Complexity Weight of 1 */ + UWord32 rotl; /* Complexity Weight of 3 */ + + UWord32 rotr; /* Complexity Weight of 3 */ + UWord32 L_rotl; /* Complexity Weight of 3 */ + UWord32 L_rotr; /* Complexity Weight of 3 */ + UWord32 L40_set; /* Complexity Weight of 1 */ + UWord32 L40_deposit_h; /* Complexity Weight of 1 */ + + UWord32 L40_deposit_l; /* Complexity Weight of 1 */ + UWord32 L40_deposit32; /* Complexity Weight of 1 */ + UWord32 Extract40_H; /* Complexity Weight of 1 */ + UWord32 Extract40_L; /* Complexity Weight of 1 */ + UWord32 L_Extract40; /* Complexity Weight of 1 */ + + UWord32 L40_round; /* Complexity Weight of 1 */ + UWord32 L_saturate40; /* Complexity Weight of 1 */ + UWord32 round40; /* Complexity Weight of 1 */ + UWord32 If; /* Complexity Weight of 3 */ + UWord32 Goto; /* Complexity Weight of 2 */ + + UWord32 Break; /* Complexity Weight of 2 */ + UWord32 Switch; /* Complexity Weight of 6 */ + UWord32 For; /* Complexity Weight of 3 */ + UWord32 While; /* Complexity Weight of 3 */ + UWord32 Continue; /* Complexity Weight of 2 */ + + UWord32 L_mls; /* Complexity Weight of 1 */ + UWord32 div_l; /* Complexity Weight of 32 */ + UWord32 i_mult; /* Complexity Weight of 1 */ + +/* New complex basic operators */ +#ifdef COMPLEX_OPERATOR + UWord32 CL_shr; /* Complexity Weight of 1 */ + UWord32 CL_shl; /* Complexity Weight of 1 */ + UWord32 CL_add; /* Complexity Weight of 1 */ + UWord32 CL_sub; /* Complexity Weight of 1 */ + UWord32 CL_scale; /* Complexity Weight of 1 */ + UWord32 CL_dscale; /* Complexity Weight of 1 */ + UWord32 CL_msu_j; /* Complexity Weight of 1 */ + UWord32 CL_mac_j; /* Complexity Weight of 1 */ + UWord32 CL_move; /* Complexity Weight of 1 */ + UWord32 CL_Extract_real; /* Complexity Weight of 1 */ + UWord32 CL_Extract_imag; /* Complexity Weight of 1 */ + UWord32 CL_form; /* Complexity Weight of 1 */ + UWord32 CL_multr_32x16; /* Complexity Weight of 2 */ + UWord32 CL_negate; /* Complexity Weight of 1 */ + UWord32 CL_conjugate; /* Complexity Weight of 1 */ + UWord32 CL_mul_j; /* Complexity Weight of 1 */ + UWord32 CL_swap_real_imag; /* Complexity Weight of 1 */ + UWord32 C_add; /* Complexity Weight of 1 */ + UWord32 C_sub; /* Complexity Weight of 1 */ + UWord32 C_mul_j; /* Complexity Weight of 1 */ + UWord32 C_multr; /* Complexity Weight of 2 */ + UWord32 C_form; /* Complexity Weight of 1 */ + + UWord32 C_scale; /* Complexity Weight of 1 */ + UWord32 CL_round32_16; /* Complexity Weight of 1 */ + UWord32 CL_scale_32; /* Complexity Weight of 1 */ + UWord32 CL_dscale_32; /* Complexity Weight of 1 */ + UWord32 CL_multr_32x32; /* Complexity Weight of 2 */ + UWord32 C_mac_r; /* Complexity Weight of 2 */ + UWord32 C_msu_r; /* Complexity Weight of 2 */ + UWord32 C_Extract_real; /* Complexity Weight of 1 */ + UWord32 C_Extract_imag; /* Complexity Weight of 1 */ + UWord32 C_negate; /* Complexity Weight of 1 */ + UWord32 C_conjugate; /* Complexity Weight of 1 */ + UWord32 C_shr; /* Complexity Weight of 1 */ + UWord32 C_shl; /* Complexity Weight of 1 */ + +#endif /* #ifdef COMPLEX_OPERATOR */ + +/* New 64 bit basops */ +#ifdef ENH_64_BIT_OPERATOR + UWord32 move64; /* Complexity Weight of 1 */ + UWord32 W_add_nosat; /* Complexity Weight of 1 */ + UWord32 W_sub_nosat; /* Complexity Weight of 1 */ + UWord32 W_shl; /* Complexity Weight of 1 */ + UWord32 W_shr; /* Complexity Weight of 1 */ + UWord32 W_shl_nosat; /* Complexity Weight of 1 */ + UWord32 W_shr_nosat; /* Complexity Weight of 1 */ + UWord32 W_mac_32_16; /* Complexity Weight of 1 */ + UWord32 W_msu_32_16; /* Complexity Weight of 1 */ + UWord32 W_mult_32_16; /* Complexity Weight of 1 */ + UWord32 W_mult0_16_16; /* Complexity Weight of 1 */ + UWord32 W_mac0_16_16; /* Complexity Weight of 1 */ + UWord32 W_msu0_16_16; /* Complexity Weight of 1 */ + UWord32 W_mult_16_16; /* Complexity Weight of 1 */ + UWord32 W_mac_16_16; /* Complexity Weight of 1 */ + UWord32 W_msu_16_16; /* Complexity Weight of 1 */ + UWord32 W_shl_sat_l; /* Complexity Weight of 1 */ + UWord32 W_sat_l; /* Complexity Weight of 1 */ + UWord32 W_sat_m; /* Complexity Weight of 1 */ + UWord32 W_deposit32_l; /* Complexity Weight of 1 */ + UWord32 W_deposit32_h; /* Complexity Weight of 1 */ + UWord32 W_extract_l; /* Complexity Weight of 1 */ + UWord32 W_extract_h; /* Complexity Weight of 1 */ + UWord32 W_round48_L; /* Complexity Weight of 1 */ + UWord32 W_round32_s; /* Complexity Weight of 1 */ + UWord32 W_norm; /* Complexity Weight of 1 */ + + UWord32 W_add; /* Complexity Weight of 1 */ + UWord32 W_sub; /* Complexity Weight of 1 */ + UWord32 W_neg; /* Complexity Weight of 1 */ + UWord32 W_abs; /* Complexity Weight of 1 */ + UWord32 W_mult_32_32; /* Complexity Weight of 1 */ + UWord32 W_mult0_32_32; /* Complexity Weight of 1 */ + UWord32 W_lshl; /* Complexity Weight of 1 */ + UWord32 W_lshr; /* Complexity Weight of 1 */ + UWord32 W_round64_L; /* Complexity Weight of 1 */ + +#endif /* #ifdef ENH_64_BIT_OPERATOR */ + +#ifdef ENH_32_BIT_OPERATOR + UWord32 Mpy_32_16_1; /* Complexity Weight of 1 */ + UWord32 Mpy_32_16_r; /* Complexity Weight of 1 */ + UWord32 Mpy_32_32; /* Complexity Weight of 1 */ + UWord32 Mpy_32_32_r; /* Complexity Weight of 1 */ + UWord32 Madd_32_16; /* Complexity Weight of 1 */ + UWord32 Madd_32_16_r; /* Complexity Weight of 1 */ + UWord32 Msub_32_16; /* Complexity Weight of 1 */ + UWord32 Msub_32_16_r; /* Complexity Weight of 1 */ + UWord32 Madd_32_32; /* Complexity Weight of 1 */ + UWord32 Madd_32_32_r; /* Complexity Weight of 1 */ + UWord32 Msub_32_32; /* Complexity Weight of 1 */ + UWord32 Msub_32_32_r; /* Complexity Weight of 1 */ +#endif /* #ifdef ENH_32_BIT_OPERATOR */ + +#ifdef ENH_U_32_BIT_OPERATOR + UWord32 UL_addNs; /* Complexity Weight of 1 */ + UWord32 UL_subNs; /* Complexity Weight of 1 */ + UWord32 UL_Mpy_32_32; /* Complexity Weight of 1 */ + UWord32 Mpy_32_32_uu; /* Complexity Weight of 2 */ + UWord32 Mpy_32_16_uu; /* Complexity Weight of 2 */ + UWord32 norm_ul; /* Complexity Weight of 1 */ + UWord32 UL_deposit_l; /* Complexity Weight of 1 */ +#endif /* #ifdef ENH_U_32_BIT_OPERATOR */ + +#ifdef CONTROL_CODE_OPS + UWord32 LT_16; /* Complexity Weight of 1 */ + UWord32 GT_16; /* Complexity Weight of 1 */ + UWord32 LE_16; /* Complexity Weight of 1 */ + UWord32 GE_16; /* Complexity Weight of 1 */ + UWord32 EQ_16; /* Complexity Weight of 1 */ + UWord32 NE_16; /* Complexity Weight of 1 */ + UWord32 LT_32; /* Complexity Weight of 1 */ + UWord32 GT_32; /* Complexity Weight of 1 */ + UWord32 LE_32; /* Complexity Weight of 1 */ + UWord32 GE_32; /* Complexity Weight of 1 */ + UWord32 EQ_32; /* Complexity Weight of 1 */ + UWord32 NE_32; /* Complexity Weight of 1 */ + UWord32 LT_64; /* Complexity Weight of 1 */ + UWord32 GT_64; /* Complexity Weight of 1 */ + UWord32 LE_64; /* Complexity Weight of 1 */ + UWord32 GE_64; /* Complexity Weight of 1 */ + UWord32 EQ_64; /* Complexity Weight of 1 */ + UWord32 NE_64; /* Complexity Weight of 1 */ + +#endif /* #ifdef CONTROL_CODE_OPS */ +} BASIC_OP; + + +Word32 TotalWeightedOperation (void); +Word32 DeltaWeightedOperation (void); + + +void generic_WMOPS_output (Word16 notPrintWorstWorstCase, char *test_file_name); +/* + * This function enable to append : + * - to WMOPS_DATA_FILENAME file, the WMOPS information related + * to the execution of the application, function group by function + * group. + * - to CODE_PROFILE_FILENAME file, the WMOPS information related + * to the execution of the application, basic operation by basic + * operation. + * - to WMOPS_TOTAL_FILENAME file, the total WMOPS information related + * to the execution of the application. + * + * Note that : + * if the files exists, the data will be written at the end of file. + * + * test_file_name : Is a character string referencing each calls to + * generic_WMOPS_output(). Usually, it is the name of a test + * sequence file. + * + * notPrintWorstWorstCase : Same usage as in WMOPS_output(). + */ + + +#if 0 +/* + * Example of how count.h could be used. + * + * In the example below it is assumed that the init_OBJECT functions + * does not use any calls to counter.h or basic_op.h. If this is the case + * a call to the function Reset_WMOPS_counter() must be done after each call + * to init_OBJECT if these operations is not to be included in the statistics. + */ + +int main () { + int spe1Id, spe2Id, cheId; + + /* initiate counters and objects */ + spe1Id = getCounterId ("Spe 5k8"); + setCounter (spe1Id); + Init_WMOPS_counter (); + init_spe1 ( ...); + + spe2Id = getCounterId ("Spe 12k2"); + setCounter (spe2Id); + Init_WMOPS_counter (); + init_spe2 ( ...); + + cheId = getCounterId ("Channel encoder"); + setCounter (cheId); + Init_WMOPS_counter (); + init_che ( ...); + ... while (data) { + test (); /* Note this call to test(); */ + if (useSpe1) + setCounter (spe1Id); + else + setCounter (spe2Id); + Reset_WMOPS_counter (); + speEncode ( ...); + WMOPS_output (0); /* Normal routine for displaying WMOPS info */ + + setCounter (cheId); + Reset_WMOPS_counter (); + preChannelInter ( ...); + fwc (); /* Note the call to fwc() for each part */ + convolve ( ...); + fwc (); /* of the channel encoder. */ + interleave ( ...); + fwc (); + WMOPS_output (0); /* Normal routine for displaying WMOPS info */ + } +} +#endif /* #if 0 */ + + +#endif /* _COUNT_H */ + + +/* end of file */ diff --git a/basic_op/enh1632.c b/basic_op/enh1632.c new file mode 100644 index 0000000..aa3d16b --- /dev/null +++ b/basic_op/enh1632.c @@ -0,0 +1,664 @@ +/* + =========================================================================== + File: ENH1632.C v.2.3 - 30.Nov.2009 + =========================================================================== + + ITU-T STL BASIC OPERATORS + + ENHANCED 16-BIT & 32-BIT ARITHMETIC OPERATORS + + History: + 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control + operators for the ITU-T Standard Tool Library as + described in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + TD 11 document and subsequent discussions on the + wp3audio@yahoogroups.com email reflector. + + ============================================================================ +*/ + + + /***************************************************************************** + * + * Enhanced 16/32 bit operators : + * s_max() + * s_min() + * L_max() + * L_min() + * shl_r() + * L_shl_r() + * L_mac0() + * L_mult0() + * L_msu0() + * s_and() + * s_or() + * s_xor() + * L_and() + * L_or() + * lshl() + * lshr() + * L_lshl() + * L_lshr() + * rotr() + * rotl() + * L_rotr() + * L_rotl() + * + *****************************************************************************/ + + +/***************************************************************************** + * + * Include-Files + * + *****************************************************************************/ +#include +#include +#include "stl.h" + +#if (WMOPS) +extern BASIC_OP multiCounter[MAXCOUNTERS]; +extern int currCounter; +#endif /* ifdef WMOPS */ + + + +/***************************************************************************** + * + * Constants and Globals + * + *****************************************************************************/ + + +/***************************************************************************** + * + * Functions + * + *****************************************************************************/ + + +/***************************************************************************** + * + * Function Name : lshl + * + * Purpose : + * + * Logically shifts left var1 by var2 positions. + * - If var2 is negative, var1 is shifted to the LSBits by (-var2) + * positions with insertion of 0 at the MSBit. + * - If var2 is positive, var1 is shifted to the MSBits by (var2) + * positions. + * + * Complexity weight : 1 + * + * Inputs : + * + * var1 16 bit short signed integer (Word16) whose value falls in + * the range 0xffff 8000 <= var1 <= 0x0000 7fff. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range 0xffff 8000 <= var2 <= 0x0000 7fff. + * + * Outputs : + * + * none + * + * Return Value: + * + * var_out 16 bit short signed integer (Word16) whose value falls in + * the range 0xffff 8000 <= var_out <= 0x0000 7fff. + * + *****************************************************************************/ +Word16 lshl (Word16 var1, Word16 var2) { + Word16 var_out = 0; + + if (var2 < 0) { + var2 = -var2; + var_out = lshr (var1, var2); + +#if (WMOPS) + multiCounter[currCounter].lshr--; +#endif /* ifdef WMOPS */ + + } else { + if (var2 == 0 || var1 == 0) { + var_out = var1; + } else if (var2 >= 16) { + var_out = 0; + } else { + var_out = var1 << var2; + } + } +#if (WMOPS) + multiCounter[currCounter].lshl++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + +/***************************************************************************** + * + * Function Name : lshr + * + * Purpose : + * + * Logically shifts right var1 by var2 positions. + * - If var2 is positive, var1 is shifted to the LSBits by (var2) + * positions with insertion of 0 at the MSBit. + * - If var2 is negative, var1 is shifted to the MSBits by (-var2) + * positions. + * + * Complexity weight : 1 + * + * Inputs : + * + * var1 16 bit short signed integer (Word16) whose value falls in + * the range 0xffff 8000 <= var1 <= 0x0000 7fff. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range 0xffff 8000 <= var2 <= 0x0000 7fff. + * + * Outputs : + * + * none + * + * Return Value: + * + * var_out 16 bit short signed integer (Word16) whose value falls in + * the range 0xffff 8000 <= var_out <= 0x0000 7fff. + * + *****************************************************************************/ +Word16 lshr (Word16 var1, Word16 var2) { + Word16 var_out; + + if (var2 < 0) { + var2 = -var2; + var_out = lshl (var1, var2); + +#if (WMOPS) + multiCounter[currCounter].lshl--; +#endif /* ifdef WMOPS */ + + } else { + if (var2 == 0 || var1 == 0) { + var_out = var1; + } else if (var2 >= 16) { + var_out = 0; + } else { + var_out = var1 >> 1; + var_out = var_out & 0x7fff; + var_out = var_out >> (var2 - 1); + } + } +#if (WMOPS) + multiCounter[currCounter].lshr++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + +/***************************************************************************** + * + * Function Name : L_lshl + * + * Purpose : + * + * Logically shifts left L_var1 by var2 positions. + * - If var2 is negative, L_var1 is shifted to the LSBits by (-var2) + * positions with insertion of 0 at the MSBit. + * - If var2 is positive, L_var1 is shifted to the MSBits by (var2) + * positions. + * + * Complexity weight : 1 + * + * Inputs : + * + * L_var1 32 bit long signed integer (Word32) whose value falls in + * the range 0x8000 0000 <= L_var1 <= 0x7fff ffff. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range 0xffff 8000 <= var2 <= 0x0000 7fff. + * + * Outputs : + * + * none + * + * Return Value: + * + * L_var_out 32 bit long signed integer (Word32) whose value falls in + * the range 0x8000 0000 <= L_var_out <= 0x7fff ffff. + * + *****************************************************************************/ +Word32 L_lshl (Word32 L_var1, Word16 var2) { + Word32 L_var_out = 0; + + if (var2 < 0) { + var2 = -var2; + L_var_out = L_lshr (L_var1, var2); + +#if (WMOPS) + multiCounter[currCounter].L_lshr--; +#endif /* ifdef WMOPS */ + + } else { + if (var2 == 0 || L_var1 == 0) { + L_var_out = L_var1; + } else if (var2 >= 32) { + L_var_out = 0; + } else { + L_var_out = L_var1 << var2; + } + } +#if (WMOPS) + multiCounter[currCounter].L_lshl++; +#endif /* ifdef WMOPS */ + + return (L_var_out); +} + + +/***************************************************************************** + * + * Function Name : L_lshr + * + * Purpose : + * + * Logically shifts right L_var1 by var2 positions. + * - If var2 is positive, L_var1 is shifted to the LSBits by (var2) + * positions with insertion of 0 at the MSBit. + * - If var2 is negative, L_var1 is shifted to the MSBits by (-var2) + * positions. + * + * Complexity weight : 1 + * + * Inputs : + * + * L_var1 32 bit long signed integer (Word32) whose value falls in + * the range 0x8000 0000 <= L_var1 <= 0x7fff ffff. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range 0xffff 8000 <= var2 <= 0x0000 7fff. + * + * Outputs : + * + * none + * + * Return Value: + * + * L_var_out 32 bit long signed integer (Word32) whose value falls in + * the range 0x8000 0000 <= L_var_out <= 0x7fff ffff. + * + *****************************************************************************/ +Word32 L_lshr (Word32 L_var1, Word16 var2) { + Word32 L_var_out; + + if (var2 < 0) { + var2 = -var2; + L_var_out = L_lshl (L_var1, var2); + +#if (WMOPS) + multiCounter[currCounter].L_lshl--; +#endif /* ifdef WMOPS */ + + } else { + if (var2 == 0 || L_var1 == 0) { + L_var_out = L_var1; + } else if (var2 >= 32) { + L_var_out = 0; + } else { + L_var_out = L_var1 >> 1; + L_var_out = L_var_out & 0x7fffffff; + L_var_out = L_var_out >> (var2 - 1); + } + } +#if (WMOPS) + multiCounter[currCounter].L_lshr++; +#endif /* ifdef WMOPS */ + + return (L_var_out); +} + + +/***************************************************************************** + * + * Function Name : shl_r + * + * Purpose : + * + * Identical to shl( var1, var2) but with rounding. Saturates the result + * in case of underflows or overflows. + * + * Complexity weight : 3 + * + * Inputs : + * + * var1 16 bit short signed integer (Word16) whose value falls in + * the range : 0xffff 8000 <= var1 <= 0x0000 7fff. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : 0xffff 8000 <= var2 <= 0x0000 7fff. + * + * Outputs : + * + * none + * + * Return Value : + * + * var_out 16 bit short signed integer (Word16) whose value falls in + * the range : 0xffff 8000 <= var_out <= 0x0000 7fff. + * + *****************************************************************************/ +Word16 shl_r (Word16 var1, Word16 var2) { + Word16 var_out; + + if (var2 >= 0) { + var_out = shl (var1, var2); + +#if (WMOPS) + multiCounter[currCounter].shl--; +#endif /* ifdef WMOPS */ + + } else { + var2 = -var2; + var_out = shr_r (var1, var2); + +#if (WMOPS) + multiCounter[currCounter].shr_r--; +#endif /* ifdef WMOPS */ + } + +#if (WMOPS) + multiCounter[currCounter].shl_r++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + +/***************************************************************************** + * + * Function Name : L_shl_r + * + * Purpose : + * + * Same as L_shl( var1, var2) but with rounding. Saturates the result in + * case of underflows or overflows. + * + * Complexity weight : 3 + * + * Inputs : + * + * L_var1 32 bit long signed integer (Word32) whose value falls in + * the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : 0xffff 8000 <= var2 <= 0x0000 7fff. + * + * Outputs : + * + * none + * + * Return Value : + * + * L_var_out 32 bit long signed integer (Word32) whose value falls in + * the range : 0x8000 0000 <= var_out <= 0x7fff ffff. + * + *****************************************************************************/ +Word32 L_shl_r (Word32 L_var1, Word16 var2) { + Word32 var_out; + + if (var2 >= 0) { + var_out = L_shl (L_var1, var2); + +#if (WMOPS) + multiCounter[currCounter].L_shl--; +#endif /* ifdef WMOPS */ + + } else { + var2 = -var2; + var_out = L_shr_r (L_var1, var2); + +#if (WMOPS) + multiCounter[currCounter].L_shr_r--; +#endif /* ifdef WMOPS */ + } + +#if (WMOPS) + multiCounter[currCounter].L_shl_r++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + +/***************************************************************************** + * + * Function Name : rotr + * + * Purpose : + * + * Performs a 16-bit logical rotation of var1 by 1 bit to the LSBits. The + * MSBit is set to var2 bit 0. The LSBit of var1 is kept in *var3 bit 0. + * + * Complexity weight : 3 + * + * Inputs : + * + * var1 16 bit short signed integer (Word16) whose value falls in + * the range : 0xffff 8000 <= var1 <= 0x0000 7fff. + * + * var2 16 bit short signed integer (Word16) whose value must be 0 + * or 1. + * + * Outputs : + * + * *var3 Points on a 16 bit short signed integer (Word16) whose + * value will be 0 or 1. + * + * Return Value : + * + * var_out 16 bit short signed integer (Word16) whose value falls in + * the range : 0xffff 8000 <= var_out <= 0x0000 7fff. + * + *****************************************************************************/ +Word16 rotr (Word16 var1, Word16 var2, Word16 * var3) { + Word16 var_out; + + *var3 = s_and (var1, 0x1); + var_out = s_or (lshr (var1, 1), lshl (var2, 15)); + +#if (WMOPS) + multiCounter[currCounter].s_and--; + multiCounter[currCounter].lshl--; + multiCounter[currCounter].lshr--; + multiCounter[currCounter].s_or--; + multiCounter[currCounter].rotr++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + +/***************************************************************************** + * + * Function Name : rotl + * + * Purpose : + * + * Performs a 16-bit logical rotation of var1 by 1 bit to the MSBits. The + * LSBit is set to var2 bit 0. The MSBit of var1 is kept in *var3 bit 0. + * + * Complexity weight : 3 + * + * Inputs : + * + * var1 16 bit short signed integer (Word16) whose value falls in + * the range : 0xffff 8000 <= var1 <= 0x0000 7fff. + * + * var2 16 bit short signed integer (Word16) whose value must be 0 + * or 1. + * + * Outputs : + * + * *var3 Points on a 16 bit short signed integer (Word16) whose + * value will be 0 or 1. + * + * Return Value : + * + * var_out 16 bit short signed integer (Word16) whose value falls in + * the range : 0xffff 8000 <= var_out <= 0x0000 7fff. + * + *****************************************************************************/ +Word16 rotl (Word16 var1, Word16 var2, Word16 * var3) { + Word16 var_out; + + *var3 = lshr (var1, 15); + + var_out = s_or (lshl (var1, 1), s_and (var2, 0x1)); + +#if (WMOPS) + multiCounter[currCounter].lshr--; + multiCounter[currCounter].s_and--; + multiCounter[currCounter].lshl--; + multiCounter[currCounter].s_or--; + multiCounter[currCounter].rotl++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + +/***************************************************************************** + * + * Function Name : L_rotr + * + * Purpose : + * + * Performs a 32-bit logical rotation of L_var1 by 1 bit to the LSBits. The + * MSBit is set to var2 bit 0. The LSBit of L_var1 is kept in *var3 bit 0. + * + * Complexity weight : 3 + * + * Inputs : + * + * L_var1 32 bit long signed integer (Word32) whose value falls in + * the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. + * + * var2 16 bit short signed integer (Word16) whose value must be 0 + * or 1. + * + * Outputs : + * + * *var3 Points on a 16 bit short signed integer (Word16) whose + * value will be 0 or 1. + * + * Return Value : + * + * L_var_out 32 bit long signed integer (Word32) whose value falls in + * the range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. + * + *****************************************************************************/ +Word32 L_rotr (Word32 L_var1, Word16 var2, Word16 * var3) { + Word32 L_var_out; + + *var3 = s_and (extract_l (L_var1), 0x1); + + L_var_out = L_or (L_lshr (L_var1, 1), L_lshl (L_deposit_l (var2), 31)); + +#if (WMOPS) + multiCounter[currCounter].extract_l--; + multiCounter[currCounter].s_and--; + multiCounter[currCounter].L_deposit_l--; + multiCounter[currCounter].L_lshl--; + multiCounter[currCounter].L_lshr--; + multiCounter[currCounter].L_or--; + multiCounter[currCounter].L_rotr++; +#endif /* ifdef WMOPS */ + + return (L_var_out); +} + + +/***************************************************************************** + * + * Function Name : L_rotl + * + * Purpose : + * + * Performs a 32-bit logical rotation of L_var1 by 1 bit to the MSBits. The + * LSBit is set to var2 bit 0. The MSBit of L_var1 is kept in *var3 bit 0. + * + * Complexity weight : 3 + * + * Inputs : + * + * L_var1 32 bit long signed integer (Word32) whose value falls in + * the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. + * + * var2 16 bit short signed integer (Word16) whose value must be 0 + * or 1. + * + * Outputs : + * + * *var3 Points on a 16 bit short signed integer (Word16) whose + * value will be 0 or 1. + * + * Return Value : + * + * L_var_out 32 bit long signed integer (Word32) whose value falls in + * the range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. + * + *****************************************************************************/ +Word32 L_rotl (Word32 L_var1, Word16 var2, Word16 * var3) { + Word32 L_var_out; + + *var3 = extract_l (L_lshr (L_var1, 31)); + + L_var_out = L_or (L_lshl (L_var1, 1), L_deposit_l (s_and (var2, 0x1))); + +#if (WMOPS) + multiCounter[currCounter].L_lshr--; + multiCounter[currCounter].extract_l--; + multiCounter[currCounter].s_and--; + multiCounter[currCounter].L_deposit_l--; + multiCounter[currCounter].L_lshl--; + multiCounter[currCounter].L_or--; + multiCounter[currCounter].L_rotl++; +#endif /* ifdef WMOPS */ + + return (L_var_out); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/* end of file */ diff --git a/basic_op/enh1632.h b/basic_op/enh1632.h new file mode 100644 index 0000000..1aee12b --- /dev/null +++ b/basic_op/enh1632.h @@ -0,0 +1,545 @@ +/* + =========================================================================== + File: ENH1632.H v.2.3 - 30.Nov.2009 + =========================================================================== + + ITU-T STL BASIC OPERATORS + + ENHANCED 16-BIT & 32-BIT ARITHMETIC OPERATORS + + History: + 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control + operators for the ITU-T Standard Tool Library as + described in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + TD 11 document and subsequent discussions on the + wp3audio@yahoogroups.com email reflector. + March 06 v2.1 Changed to improve portability. + Some counters incrementations were missing (s_and, + s_or, s_xor). + 30 Nov 09 v2.3 saturate() removed + + ============================================================================ +*/ + + +#ifndef _ENH1632_H +#define _ENH1632_H + + +/***************************************************************************** + * + * Constants and Globals + * + *****************************************************************************/ + + +#include "stl.h" + + +#if (WMOPS) +#include "count.h" +extern BASIC_OP multiCounter[MAXCOUNTERS]; +extern int currCounter; +#endif /* ifdef WMOPS */ + + +/***************************************************************************** + * + * Prototypes for enhanced 16/32 bit arithmetic operators + * + *****************************************************************************/ +Word16 shl_r (Word16 var1, Word16 var2); +Word32 L_shl_r (Word32 L_var1, Word16 var2); + + +Word16 lshl (Word16 var1, Word16 var2); +Word16 lshr (Word16 var1, Word16 var2); +Word32 L_lshl (Word32 L_var1, Word16 var2); +Word32 L_lshr (Word32 L_var1, Word16 var2); + +Word16 rotr (Word16 var1, Word16 var2, Word16 * var3); +Word16 rotl (Word16 var1, Word16 var2, Word16 * var3); +Word32 L_rotr (Word32 var1, Word16 var2, Word16 * var3); +Word32 L_rotl (Word32 var1, Word16 var2, Word16 * var3); + + + +/***************************************************************************** + * + * Functions + * + *****************************************************************************/ + +/***************************************************************************** + * + * Function Name : s_max + * + * Purpose : + * + * Compares var1 and var2 and returns the maximum value. + * + * Complexity weight : 1 + * + * Inputs : + * + * var1 16 bit short signed integer (Word16) whose value falls in + * the range : 0x8000 <= var1 <= 0x7fff. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : 0x8000 <= var2 <= 0x7fff. + * + * Outputs : + * + * none + * + * Return Value : + * + * var_out 16 bit short signed integer (Word16) whose value falls in + * the range : 0x8000 <= L_var_out <= 0x7fff. + * + *****************************************************************************/ +static __inline Word16 s_max (Word16 var1, Word16 var2) { + Word16 var_out; + + if (var1 >= var2) + var_out = var1; + else + var_out = var2; + +#if (WMOPS) + multiCounter[currCounter].s_max++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + +/***************************************************************************** + * + * Function Name : s_min + * + * Purpose : + * + * Compares var1 and var2 and returns the minimum value. + * + * Complexity weight : 1 + * + * Inputs : + * + * var1 16 bit short signed integer (Word16) whose value falls in + * the range : 0x8000 <= var1 <= 0x7fff. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : 0x8000 <= var2 <= 0x7fff. + * + * Outputs : + * + * none + * + * Return Value : + * + * var_out 16 bit short signed integer (Word16) whose value falls in + * the range : 0x8000 <= var_out <= 0x7fff. + * + *****************************************************************************/ +static __inline Word16 s_min (Word16 var1, Word16 var2) { + Word16 var_out; + + if (var1 <= var2) + var_out = var1; + else + var_out = var2; + +#if (WMOPS) + multiCounter[currCounter].s_min++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + +/***************************************************************************** + * + * Function Name : L_max + * + * Purpose : + * + * Compares L_var1 and L_var2 and returns the maximum value. + * + * Complexity weight : 1 + * + * Inputs : + * + * L_var1 32 bit long signed integer (Word32) whose value falls in the + * range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. + * + * L_var2 32 bit long signed integer (Word32) whose value falls in the + * range : 0x8000 0000 <= L_var2 <= 0x7fff ffff. + * + * Outputs : + * + * none + * + * Return Value : + * + * L_var_out 32 bit long signed integer (Word32) whose value falls in the + * range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. + * + *****************************************************************************/ +static __inline Word32 L_max (Word32 L_var1, Word32 L_var2) { + Word32 L_var_out; + + if (L_var1 >= L_var2) + L_var_out = L_var1; + else + L_var_out = L_var2; + +#if (WMOPS) + multiCounter[currCounter].L_max++; +#endif /* ifdef WMOPS */ + + return (L_var_out); +} + + +/***************************************************************************** + * + * Function Name : L_min + * + * Purpose : + * + * Compares L_var1 and L_var2 and returns the minimum value. + * + * Complexity weight : 1 + * + * Inputs : + * + * L_var1 32 bit long signed integer (Word32) whose value falls in the + * range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. + * + * L_var2 32 bit long signed integer (Word32) whose value falls in the + * range : 0x8000 0000 <= L_var2 <= 0x7fff ffff. + * + * Outputs : + * + * none + * + * Return Value : + * + * L_var_out 32 bit long signed integer (Word32) whose value falls in the + * range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. + * + *****************************************************************************/ +static __inline Word32 L_min (Word32 L_var1, Word32 L_var2) { + Word32 L_var_out; + + if (L_var1 <= L_var2) + L_var_out = L_var1; + else + L_var_out = L_var2; + +#if (WMOPS) + multiCounter[currCounter].L_min++; +#endif /* ifdef WMOPS */ + + return (L_var_out); +} + + + + + + + + + + +/***************************************************************************** + * + * Function Name : s_and + * + * Purpose : + * + * Performs logical AND of the two 16 bit input variables. + * var_out = var1 & var2 + * + * Complexity weight : 1 + * + * Inputs : + * + * var1 16 bit short signed integer (Word16) whose value + * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. + * + * var2 16 bit short signed integer (Word16) whose value + * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. + * + * Outputs : + * + * none + * + * Return Value : + * + * var_out 16 bit short signed integer (Word16) whose value + * falls in the range 0xffff 8000 <= var_out <= 0x0000 7fff. + * + *****************************************************************************/ +static __inline Word16 s_and (Word16 var1, Word16 var2) { + Word16 var_out; + + var_out = var1 & var2; + +#if (WMOPS) + multiCounter[currCounter].s_and++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + +/***************************************************************************** + * + * Function Name : L_and + * + * Purpose : + * + * Performs logical AND of the two 32 bit input variables. + * L_var_out = L_var1 & L_var2 + * + * Complexity weight : 1 + * + * Inputs : + * + * L_var1 32 bit long signed integer (Word32) whose value + * falls in the range 0x8000 0000 <= L_var1 <= 0x7fff ffff. + * + * L_var2 32 bit long signed integer (Word32) whose value + * falls in the range 0x8000 0000 <= L_var2 <= 0x7fff ffff. + * + * Outputs : + * + * none + * + * Return Value : + * + * L_var_out 32 bit long signed integer (Word32) whose value + * falls in the range 0x8000 0000 <= L_var_out <= 0x7fff ffff. + * + *****************************************************************************/ +static __inline Word32 L_and (Word32 L_var1, Word32 L_var2) { + Word32 L_var_out; + + L_var_out = L_var1 & L_var2; + +#if (WMOPS) + multiCounter[currCounter].L_and++; +#endif /* ifdef WMOPS */ + + return (L_var_out); +} + + +/***************************************************************************** + * + * Function Name : s_or + * + * Purpose : + * + * Performs logical OR of the two 16 bit input variables. + * var_out = var1 | var2 + * + * Complexity weight : 1 + * + * Inputs : + * + * var1 16 bit short signed integer (Word16) whose value + * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. + * + * var2 16 bit short signed integer (Word16) whose value + * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. + * + * Outputs : + * + * none + * + * Return Value : + * + * var_out 16 bit short signed integer (Word16) whose value + * falls in the range 0xffff 8000 <= var_out <= 0x0000 7fff. + * + *****************************************************************************/ +static __inline Word16 s_or (Word16 var1, Word16 var2) { + Word16 var_out; + + var_out = var1 | var2; + +#if (WMOPS) + multiCounter[currCounter].s_or++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + +/***************************************************************************** + * + * Function Name : L_or + * + * Purpose : + * + * Performs logical OR of the two 32 bit input variables. + * L_var_out = L_var1 | L_var2 + * + * Complexity weight : 1 + * + * Inputs : + * + * L_var1 32 bit long signed integer (Word32) whose value + * falls in the range 0x8000 0000 <= L_var1 <= 0x7fff ffff. + * + * L_var2 32 bit long signed integer (Word32) whose value + * falls in the range 0x8000 0000 <= L_var2 <= 0x7fff ffff. + * + * Outputs : + * + * none + * + * Return Value : + * + * L_var_out 32 bit long signed integer (Word32) whose value + * falls in the range 0x8000 0000 <= L_var_out <= 0x7fff ffff. + * + *****************************************************************************/ +static __inline Word32 L_or (Word32 L_var1, Word32 L_var2) { + + Word32 L_var_out; + + L_var_out = L_var1 | L_var2; + +#if (WMOPS) + multiCounter[currCounter].L_or++; +#endif /* ifdef WMOPS */ + + return (L_var_out); +} + + +/***************************************************************************** + * + * Function Name : s_xor + * + * Purpose : + * + * Performs logical XOR of the two 16 bit input variables. + * var_out = var1 ^ var2 + * + * Complexity weight : 1 + * + * Inputs : + * + * var1 16 bit short signed integer (Word16) whose value + * falls in the range 0xffff 8000 <= var1 <= 0x0000 7fff. + * + * var2 16 bit short signed integer (Word16) whose value + * falls in the range 0xffff 8000 <= var2 <= 0x0000 7fff. + * + * Outputs : + * + * none + * + * Return Value : + * + * var_out 16 bit short signed integer (Word16) whose value + * falls in the range 0xffff 8000 <= var_out <= 0x0000 7fff. + * + *****************************************************************************/ +static __inline Word16 s_xor (Word16 var1, Word16 var2) { + Word16 var_out; + + var_out = var1 ^ var2; + +#if (WMOPS) + multiCounter[currCounter].s_xor++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + +/***************************************************************************** + * + * Function Name : L_xor + * + * Purpose : + * + * Performs logical OR of the two 32 bit input variables. + * L_var_out = L_var1 ^ L_var2 + * + * Complexity weight : 1 + * + * Inputs : + * + * L_var1 32 bit long signed integer (Word32) whose value + * falls in the range 0x8000 0000 <= L_var1 <= 0x7fff ffff. + * + * L_var2 32 bit long signed integer (Word32) whose value + * falls in the range 0x8000 0000 <= L_var2 <= 0x7fff ffff. + * + * Outputs : + * + * none + * + * Return Value : + * + * L_var_out 32 bit long signed integer (Word32) whose value + * falls in the range 0x8000 0000 <= L_var_out <= 0x7fff ffff. + * + *****************************************************************************/ +static __inline Word32 L_xor (Word32 L_var1, Word32 L_var2) { + Word32 L_var_out; + + L_var_out = L_var1 ^ L_var2; + +#if (WMOPS) + multiCounter[currCounter].L_xor++; +#endif /* ifdef WMOPS */ + + return (L_var_out); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#endif /*_ENH1632_H*/ + +/* end of file */ diff --git a/basic_op/enh32.c b/basic_op/enh32.c new file mode 100644 index 0000000..1f8a6f8 --- /dev/null +++ b/basic_op/enh32.c @@ -0,0 +1,215 @@ +/***************************************************************************** + * + * Enhanced 32 bit operators : + * + * Mpy_32_16_1() + * Mpy_32_16_r() + * Mpy_32_32() + * Mpy_32_32_r() + * Madd_32_16() + * Msub_32_16() + * Madd_32_32() + * Msub_32_32() + * + *****************************************************************************/ + + +/***************************************************************************** + * + * Include-Files + * + *****************************************************************************/ +#include +#include +#include "enh32.h" + +#if (WMOPS) +extern BASIC_OP multiCounter[MAXCOUNTERS]; +extern int currCounter; +#endif /* if WMOPS */ + +#ifdef ENH_32_BIT_OPERATOR +/***************************************************************************** + * + * Local Functions + * + *****************************************************************************/ + +/***************************************************************************** + * + * Constants and Globals + * + *****************************************************************************/ + + +/***************************************************************************** + * + * Functions + * + *****************************************************************************/ + +Word32 Mpy_32_16_1 (Word32 L_var1, Word16 var2) { + Word32 L_var_out = W_sat_m (W_mult_32_16 (L_var1, var2) ); +#if (WMOPS) + multiCounter[currCounter].Mpy_32_16_1++; + multiCounter[currCounter].W_mult_32_16--; + multiCounter[currCounter].W_sat_m--; +#endif /* if WMOPS */ + return L_var_out; +} + +Word32 Mpy_32_16_r (Word32 L_var1, Word16 var2) { + Word32 L_var_out = W_round48_L (W_mult_32_16 (L_var1, var2 ) ); +#if (WMOPS) + multiCounter[currCounter].Mpy_32_16_r++; + multiCounter[currCounter].W_mult_32_16--; + multiCounter[currCounter].W_round48_L--; +#endif /* if WMOPS */ + return L_var_out; +} + +Word32 Mpy_32_32 (Word32 L_var1, Word32 L_var2) { + Word32 L_var_out; + Word64 L64_var1; + + L64_var1 = ((Word64)L_var1 * L_var2); + L64_var1 = W_shl (L64_var1, 1); + L_var_out = W_extract_h (L64_var1 ); +#if (WMOPS) + multiCounter[currCounter].Mpy_32_32++; + multiCounter[currCounter].W_shl--; + multiCounter[currCounter].W_extract_h--; +#endif /* if WMOPS */ + return L_var_out; +} + +Word32 Mpy_32_32_r (Word32 L_var1, Word32 L_var2) { + Word32 L_var_out; + Word64 L64_var1; + + L64_var1 = ((Word64) L_var1 * L_var2); + L64_var1 = W_shr (L64_var1, 15); + L_var_out = W_round48_L (L64_var1 ); +#if (WMOPS) + multiCounter[currCounter].Mpy_32_32_r++; + multiCounter[currCounter].W_shr--; + multiCounter[currCounter].W_round48_L--; +#endif /* if WMOPS */ + return L_var_out; +} + +Word32 Madd_32_16 (Word32 L_var3, Word32 L_var1, Word16 var2) { + Word32 L_var_out; + + L_var_out = Mpy_32_16_1 (L_var1, var2); + L_var_out = L_add (L_var3, L_var_out); + +#if (WMOPS) + multiCounter[currCounter].Mpy_32_16_1--; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].Madd_32_16++; +#endif /* if WMOPS */ + return L_var_out; +} + +Word32 Madd_32_16_r (Word32 L_var3, Word32 L_var1, Word16 var2) { + Word32 L_var_out; + + L_var_out = Mpy_32_16_r (L_var1, var2); + L_var_out = L_add (L_var3, L_var_out); + +#if (WMOPS) + multiCounter[currCounter].Mpy_32_16_r--; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].Madd_32_16_r++; +#endif /* if WMOPS */ + return L_var_out; +} + +Word32 Msub_32_16 (Word32 L_var3, Word32 L_var1, Word16 var2) { + Word32 L_var_out; + + L_var_out = Mpy_32_16_1 (L_var1, var2); + L_var_out = L_sub(L_var3, L_var_out); + +#if (WMOPS) + multiCounter[currCounter].Mpy_32_16_1--; + multiCounter[currCounter].L_sub--; + multiCounter[currCounter].Msub_32_16++; +#endif /* if WMOPS */ + return L_var_out; +} + +Word32 Msub_32_16_r (Word32 L_var3, Word32 L_var1, Word16 var2) { + Word32 L_var_out; + + L_var_out = Mpy_32_16_r (L_var1, var2); + L_var_out = L_sub (L_var3, L_var_out); + +#if (WMOPS) + multiCounter[currCounter].Mpy_32_16_r--; + multiCounter[currCounter].L_sub--; + multiCounter[currCounter].Msub_32_16_r++; +#endif /* if WMOPS */ + return L_var_out; +} + +Word32 Madd_32_32 (Word32 L_var3, Word32 L_var1, Word32 L_var2) { + Word32 L_var_out; + + L_var_out = Mpy_32_32 (L_var1, L_var2); + L_var_out = L_add (L_var3, L_var_out); + +#if (WMOPS) + multiCounter[currCounter].Mpy_32_32--; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].Madd_32_32++; +#endif /* if WMOPS */ + return L_var_out; +} + +Word32 Madd_32_32_r (Word32 L_var3, Word32 L_var1, Word32 L_var2) { + Word32 L_var_out; + + L_var_out = Mpy_32_32_r (L_var1, L_var2); + L_var_out = L_add (L_var3, L_var_out); + +#if (WMOPS) + multiCounter[currCounter].Mpy_32_32_r--; + multiCounter[currCounter].L_add--; + multiCounter[currCounter].Madd_32_32_r++; +#endif /* if WMOPS */ + return L_var_out; +} + +Word32 Msub_32_32 (Word32 L_var3, Word32 L_var1, Word32 L_var2) { + Word32 L_var_out; + + L_var_out = Mpy_32_32 (L_var1, L_var2); + L_var_out = L_sub (L_var3, L_var_out); + +#if (WMOPS) + multiCounter[currCounter].Mpy_32_32--; + multiCounter[currCounter].L_sub--; + multiCounter[currCounter].Msub_32_32++; +#endif /* if WMOPS */ + return L_var_out; +} + +Word32 Msub_32_32_r (Word32 L_var3, Word32 L_var1, Word32 L_var2) { + Word32 L_var_out; + + L_var_out = Mpy_32_32_r (L_var1, L_var2); + L_var_out = L_sub (L_var3, L_var_out); + +#if (WMOPS) + multiCounter[currCounter].Mpy_32_32_r--; + multiCounter[currCounter].L_sub--; + multiCounter[currCounter].Msub_32_32_r++; +#endif /* if WMOPS */ + return L_var_out; +} + +#endif /* #ifdef ENH_32_BIT_OPERATOR */ + +/* end of file */ diff --git a/basic_op/enh32.h b/basic_op/enh32.h new file mode 100644 index 0000000..a6e220c --- /dev/null +++ b/basic_op/enh32.h @@ -0,0 +1,38 @@ + +#ifndef _ENH32_H +#define _ENH32_H + +#include "stl.h" + +#ifndef Word64 +#define Word64 long long int +#endif + + /***************************************************************************** + * + * Prototypes for enhanced 32 bit arithmetic operators + * + *****************************************************************************/ +#ifdef ENH_32_BIT_OPERATOR + +Word32 Mpy_32_16_1 (Word32 L_var1, Word16 var2); +Word32 Mpy_32_16_r (Word32 L_var1, Word16 var2); +Word32 Mpy_32_32 (Word32 L_var1, Word32 L_var2); +Word32 Mpy_32_32_r (Word32 L_var1, Word32 L_var2); +Word32 Madd_32_16 (Word32 L_var3, Word32 L_var1, Word16 var2); +Word32 Madd_32_16_r (Word32 L_var3, Word32 L_var1, Word16 var2); +Word32 Msub_32_16 (Word32 L_var3, Word32 L_var1, Word16 var2); +Word32 Msub_32_16_r (Word32 L_var3, Word32 L_var1, Word16 var2); +Word32 Madd_32_32 (Word32 L_var3, Word32 L_var1, Word32 L_var2); +Word32 Madd_32_32_r (Word32 L_var3, Word32 L_var1, Word32 L_var2); +Word32 Msub_32_32 (Word32 L_var3, Word32 L_var1, Word32 L_var2); +Word32 Msub_32_32_r (Word32 L_var3, Word32 L_var1, Word32 L_var2); + +#endif /* #ifdef ENH_32_BIT_OPERATOR */ + +#endif /*_ENH32_H*/ + + +/* end of file */ + + diff --git a/basic_op/enh40.c b/basic_op/enh40.c new file mode 100644 index 0000000..a72a243 --- /dev/null +++ b/basic_op/enh40.c @@ -0,0 +1,1045 @@ +/* + =========================================================================== + File: ENH40.C v.2.3 - 30.Nov.2009 + =========================================================================== + + ITU-T STL BASIC OPERATORS + + 40-BIT ARITHMETIC OPERATORS + + History: + 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control + operators for the ITU-T Standard Tool Library as + described in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + TD 11 document and subsequent discussions on the + wp3audio@yahoogroups.com email reflector. + + ============================================================================ +*/ + + +/***************************************************************************** + * + * Enhanced 40 bit operators : + * + * L40_add() + * L40_sub() + * L40_abs() + * L40_negate() + * L40_max() + * L40_min() + * L40_shr() + * L40_shr_r() + * L40_shl() + * L40_shl_r() + * norm_L40() + * L40_mult() + * L40_mac() + * L40_msu() + * mac_r40() + * msu_r40() + * Mpy_32_16_ss() + * Mpy_32_32_ss() + * L40_lshl() + * L40_lshr() + * L40_round() + * L_saturate40() + * L40_set() + * Extract40_H() + * Extract40_L() + * L_Extract40() + * L40_deposit_h() + * L40_deposit_l() + * L40_deposit32() + * + *****************************************************************************/ + + +/***************************************************************************** + * + * Include-Files + * + *****************************************************************************/ +#include +#include +#include "stl.h" + +#if (WMOPS) +extern BASIC_OP multiCounter[MAXCOUNTERS]; +extern int currCounter; +#endif /* ifdef WMOPS */ + + +/***************************************************************************** + * + * Local Functions + * + *****************************************************************************/ + + +/***************************************************************************** + * + * Constants and Globals + * + *****************************************************************************/ + + +/***************************************************************************** + * + * Functions + * + *****************************************************************************/ + +/***************************************************************************** + * + * Function Name : L40_shl + * + * Purpose : + * + * Arithmetically shifts left L40_var1 by var2 positions. + * - If var2 is negative, L40_var1 is shifted to the LSBits by (-var2) + * positions with extension of the sign bit. + * - If var2 is positive, L40_var1 is shifted to the MSBits by (var2) + * positions. + * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit. + * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit. + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var2 <= MAX_16. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +Word40 L40_shl (Word40 L40_var1, Word16 var2) { + + Word40 L40_var_out; + Word40 L40_constant = L40_set (0xc000000000); + + if (var2 < 0) { + var2 = -var2; + L40_var_out = L40_shr (L40_var1, var2); + +#if (WMOPS) + multiCounter[currCounter].L40_shr--; +#endif /* ifdef WMOPS */ + } + + else { + L40_var_out = L40_var1; + + for (; var2 > 0; var2--) { + if (L40_var_out > 0x003fffffffff) { + L40_var_out = L40_OVERFLOW_OCCURED (L40_var_out); + break; + } + + else if (L40_var_out < L40_constant) { + L40_var_out = L40_UNDERFLOW_OCCURED (L40_var_out); + break; + } + + else { + L40_var_out = L40_var_out << 1; + } + } + } + +#if (WMOPS) + multiCounter[currCounter].L40_set--; + multiCounter[currCounter].L40_shl++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + +/***************************************************************************** + * + * Function Name : L40_shr + * + * Purpose : + * + * Arithmetically shifts right L40_var1 by var2 positions. + * - If var2 is positive, L40_var1 is shifted to the LSBits by (var2) + * positions with extension of the sign bit. + * - If var2 is negative, L40_var1 is shifted to the MSBits by (-var2) + * positions. + * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit. + * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit. + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var2 <= MAX_16. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +Word40 L40_shr (Word40 L40_var1, Word16 var2) { + Word40 L40_var_out; + + if (var2 < 0) { + var2 = -var2; + L40_var_out = L40_shl (L40_var1, var2); + +#if (WMOPS) + multiCounter[currCounter].L40_shl--; +#endif /* ifdef WMOPS */ + + } else { + L40_var_out = L40_var1 >> var2; + } + +#if (WMOPS) + multiCounter[currCounter].L40_shr++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + +/***************************************************************************** + * + * Function Name : L40_negate + * + * Purpose : + * + * Negates L40_var1. + * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit. + * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit. + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +Word40 L40_negate (Word40 L40_var1) { + Word40 L40_var_out; + + L40_var_out = L40_add (~L40_var1, 0x01); + +#if (WMOPS) + multiCounter[currCounter].L40_add--; + multiCounter[currCounter].L40_negate++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + +/***************************************************************************** + * + * Function Name : L40_add + * + * Purpose : + * + * Adds L40_var1 and L40_var2 and returns the 40-bit result. + * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit. + * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit. + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * L40_var2 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var2 <= MAX_40. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +Word40 L40_add (Word40 L40_var1, Word40 L40_var2) { + Word40 L40_var_out; + + L40_var_out = L40_var1 + L40_var2; + + if ((((L40_var1 & 0x8000000000) >> 39) != 0) + && (((L40_var2 & 0x8000000000) >> 39) != 0) + && (((L40_var_out & 0x8000000000) >> 39) == 0)) { + L40_var_out = L40_UNDERFLOW_OCCURED (L40_var_out); + + } else if ((((L40_var1 & 0x8000000000) >> 39) == 0) + && (((L40_var2 & 0x8000000000) >> 39) == 0) + && (((L40_var_out & 0x8000000000) >> 39) != 0)) { + L40_var_out = L40_OVERFLOW_OCCURED (L40_var_out); + } +#if (WMOPS) + multiCounter[currCounter].L40_add++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + +/***************************************************************************** + * + * Function Name : L40_sub + * + * Purpose : + * + * Subtracts L40_var2 from L40_var1. + * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit. + * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit. + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * L40_var2 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var2 <= MAX_40. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +Word40 L40_sub (Word40 L40_var1, Word40 L40_var2) { + Word40 L40_var_out; + + L40_var_out = L40_var1 - L40_var2; + + if ((((L40_var1 & 0x8000000000) >> 39) != 0) + && (((L40_var2 & 0x8000000000) >> 39) == 0) + && (((L40_var_out & 0x8000000000) >> 39) == 0)) { + L40_var_out = L40_UNDERFLOW_OCCURED (L40_var_out); + + } else if ((((L40_var1 & 0x8000000000) >> 39) == 0) + && (((L40_var2 & 0x8000000000) >> 39) != 0) + && (((L40_var_out & 0x8000000000) >> 39) != 0)) { + L40_var_out = L40_OVERFLOW_OCCURED (L40_var_out); + } +#if (WMOPS) + multiCounter[currCounter].L40_sub++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + +/***************************************************************************** + * + * Function Name : L40_abs + * + * Purpose : + * + * Returns the absolute value of L40_var1. + * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit. + * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit. + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : 0x00 0000 0000 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +Word40 L40_abs (Word40 L40_var1) { + Word40 L40_var_out; + + if (L40_var1 < 0) { + L40_var_out = L40_negate (L40_var1); + +#if (WMOPS) + multiCounter[currCounter].L40_negate--; +#endif /* ifdef WMOPS */ + + } else { + L40_var_out = L40_var1; + } + +#if (WMOPS) + multiCounter[currCounter].L40_abs++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + +/***************************************************************************** + * + * Function Name : L40_max + * + * Purpose : + * + * Compares L40_var1 and L40_var2 and returns the maximum value. + * + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * L40_var2 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var2 <= MAX_40. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +Word40 L40_max (Word40 L40_var1, Word40 L40_var2) { + Word40 L40_var_out; + + if (L40_var1 < L40_var2) + L40_var_out = L40_var2; + else + L40_var_out = L40_var1; + +#if (WMOPS) + multiCounter[currCounter].L40_max++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + +/***************************************************************************** + * + * Function Name : L40_min + * + * Purpose : + * + * Compares L40_var1 and L40_var2 and returns the minimum value. + * + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * L40_var2 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var2 <= MAX_40. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +Word40 L40_min (Word40 L40_var1, Word40 L40_var2) { + Word40 L40_var_out; + + if (L40_var1 < L40_var2) + L40_var_out = L40_var1; + else + L40_var_out = L40_var2; + +#if (WMOPS) + multiCounter[currCounter].L40_min++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + +/***************************************************************************** + * + * Function Name : L_saturate40 + * + * Purpose : + * + * If L40_var1 is greater than MAX_32, returns MAX_32. + * If L40_var1 is lower than MIN_32, returns MIN_32. + * If not, returns L_Extract40( L40_var1). + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * Outputs : + * + * none + * + * Return Value : + * + * L_var_out 32 bit long signed integer (Word32) whose value falls in + * the range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. + * + *****************************************************************************/ +Word32 L_saturate40 (Word40 L40_var1) { + Word32 L_var_out; + + Word40 UNDER_L40_var2 = (Word40) ~ ((((Word40) 1) << 31) - (Word40) 1); + Word40 OVER_L40_var2 = (Word40) ((((Word40) 1) << 31) - (Word40) 1); + + if (L40_var1 < UNDER_L40_var2) { + L40_var1 = UNDER_L40_var2; + Overflow = 1; + } + + if (L40_var1 > OVER_L40_var2) { + L40_var1 = OVER_L40_var2; + Overflow = 1; + } + + L_var_out = L_Extract40 (L40_var1); + +#if (WMOPS) + multiCounter[currCounter].L_Extract40--; + multiCounter[currCounter].L_saturate40++; +#endif /* ifdef WMOPS */ + + return (L_var_out); +} + + +/***************************************************************************** + * + * Function Name : Mpy_32_16_ss + * + * Purpose : + * + * Multiplies the 2 signed values L_var1 and var2 with saturation control + * on 48-bit. The operation is performed in fractional mode : + * - L_var1 is supposed to be in 1Q31 format. + * - var2 is supposed to be in 1Q15 format. + * - The result is produced in 1Q47 format : L_varout_h points to the + * 32 MSBits while varout_l points to the 16 LSBits. + * + * Complexity weight : 2 + * + * Inputs : + * + * L_var1 32 bit long signed integer (Word32) whose value falls in + * the range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : 0xffff 8000 <= var2 <= 0x0000 7fff. + * + * Outputs : + * + * *L_varout_h 32 bit long signed integer (Word32) whose value falls in + * the range : 0x8000 0000 <= L_varout_h <= 0x7fff ffff. + * + * *varout_l 16 bit short unsigned integer (UWord16) whose value falls in + * the range : 0x0000 0000 <= varout_l <= 0x0000 ffff. + * + * Return Value : + * + * none + * + *****************************************************************************/ +void Mpy_32_16_ss (Word32 L_var1, Word16 var2, Word32 * L_varout_h, UWord16 * varout_l) { + Word16 var1_h; + UWord16 uvar1_l; + Word40 L40_var1; + + if ((L_var1 == (Word32) 0x80000000) + && (var2 == (Word16) 0x8000)) { + *L_varout_h = 0x7fffffff; + *varout_l = (UWord16) 0xffff; + + } else { + uvar1_l = extract_l (L_var1); + var1_h = extract_h (L_var1); + + /* Below line can not overflow, so we can use << instead of L40_shl. */ + L40_var1 = ((Word40) ((Word32) var2 * (Word32) uvar1_l)) << 1; + + *varout_l = Extract40_L (L40_var1); + + L40_var1 = L40_shr (L40_var1, 16); + L40_var1 = L40_mac (L40_var1, var2, var1_h); + + *L_varout_h = L_Extract40 (L40_var1); + +#if(WMOPS) + multiCounter[currCounter].extract_l--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].Extract40_L--; + multiCounter[currCounter].L40_shr--; + multiCounter[currCounter].L40_mac--; + multiCounter[currCounter].L_Extract40--; +#endif /* ifdef WMOPS */ + } + +#if (WMOPS) + multiCounter[currCounter].Mpy_32_16_ss++; +#endif /* ifdef WMOPS */ + + return; +} + + +/***************************************************************************** + * + * Function Name : Mpy_32_32_ss + * + * Purpose : + * + * Multiplies the 2 signed values L_var1 and L_var2 with saturation control + * on 64-bit. The operation is performed in fractional mode : + * - L_var1 and L_var2 are supposed to be in 1Q31 format. + * - The result is produced in 1Q63 format : L_varout_h points to the + * 32 MSBits while L_varout_l points to the 32 LSBits. + * + * Complexity weight : 4 + * + * Inputs : + * + * L_var1 32 bit long signed integer (Word32) whose value falls in the + * range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. + * + * L_var2 32 bit long signed integer (Word32) whose value falls in the + * range : 0x8000 0000 <= L_var2 <= 0x7fff ffff. + * + * Outputs : + * + * *L_varout_h 32 bit long signed integer (Word32) whose value falls in + * the range : 0x8000 0000 <= L_varout_h <= 0x7fff ffff. + * + * *L_varout_l 32 bit short unsigned integer (UWord32) whose value falls in + * the range : 0x0000 0000 <= L_varout_l <= 0xffff ffff. + * + * + * Return Value : + * + * none + * + *****************************************************************************/ +void Mpy_32_32_ss (Word32 L_var1, Word32 L_var2, Word32 * L_varout_h, UWord32 * L_varout_l) { + UWord16 uvar1_l, uvar2_l; + Word16 var1_h, var2_h; + Word40 L40_var1; + + if ((L_var1 == (Word32) 0x80000000) + && (L_var2 == (Word32) 0x80000000)) { + *L_varout_h = 0x7fffffff; + *L_varout_l = (UWord32) 0xffffffff; + + } else { + + uvar1_l = extract_l (L_var1); + var1_h = extract_h (L_var1); + uvar2_l = extract_l (L_var2); + var2_h = extract_h (L_var2); + + /* Below line can not overflow, so we can use << instead of L40_shl. */ + L40_var1 = ((Word40) ((UWord32) uvar2_l * (UWord32) uvar1_l)) << 1; + + *L_varout_l = 0x0000ffff & L_Extract40 (L40_var1); + + L40_var1 = L40_shr (L40_var1, 16); + L40_var1 = L40_add (L40_var1, ((Word40) ((Word32) var2_h * (Word32) uvar1_l)) << 1); + L40_var1 = L40_add (L40_var1, ((Word40) ((Word32) var1_h * (Word32) uvar2_l)) << 1); + *L_varout_l |= (L_Extract40 (L40_var1)) << 16; + + L40_var1 = L40_shr (L40_var1, 16); + L40_var1 = L40_mac (L40_var1, var1_h, var2_h); + + *L_varout_h = L_Extract40 (L40_var1); + +#if (WMOPS) + multiCounter[currCounter].extract_l -= 2; + multiCounter[currCounter].extract_h -= 2; + multiCounter[currCounter].L_Extract40 -= 3; + multiCounter[currCounter].L40_shr -= 2; + multiCounter[currCounter].L40_add -= 2; + multiCounter[currCounter].L40_mac--; +#endif /* ifdef WMOPS */ + } + +#if (WMOPS) + multiCounter[currCounter].Mpy_32_32_ss++; +#endif /* ifdef WMOPS */ + + return; +} + + +/***************************************************************************** + * + * Function Name : L40_lshl + * + * Purpose : + * + * Logically shifts left L40_var1 by var2 positions. + * - If var2 is negative, L40_var1 is shifted to the LSBits by (-var2) + * positions with insertion of 0 at the MSBit. + * - If var2 is positive, L40_var1 is shifted to the MSBits by (var2) + * positions. + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var2 <= MAX_16. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +Word40 L40_lshl (Word40 L40_var1, Word16 var2) { + Word40 L40_var_out; + + if (var2 <= 0) { + var2 = -var2; + L40_var_out = L40_lshr (L40_var1, var2); + +#if (WMOPS) + multiCounter[currCounter].L40_lshr--; +#endif /* ifdef WMOPS */ + + } else { + if (var2 >= 40) + L40_var_out = 0x0000000000; + else + L40_var_out = L40_var1 << var2; + + L40_var_out = L40_set (L40_var_out); + +#if (WMOPS) + multiCounter[currCounter].L40_set--; +#endif /* ifdef WMOPS */ + } + +#if (WMOPS) + multiCounter[currCounter].L40_lshl++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + +/***************************************************************************** + * + * Function Name : L40_lshr + * + * Purpose : + * + * Logically shifts right L40_var1 by var2 positions. + * - If var2 is positive, L40_var1 is shifted to the LSBits by (var2) + * positions with insertion of 0 at the MSBit. + * - If var2 is negative, L40_var1 is shifted to the MSBits by (-var2) + * positions. + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var2 <= MAX_16. +* + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +Word40 L40_lshr (Word40 L40_var1, Word16 var2) { + Word40 L40_var_out; + + if (var2 < 0) { + var2 = -var2; + L40_var_out = L40_lshl (L40_var1, var2); + +#if (WMOPS) + multiCounter[currCounter].L40_lshl--; +#endif /* ifdef WMOPS */ + } else { + if (var2 >= 40) + L40_var_out = 0x0000000000; + else + L40_var_out = (L40_var1 & 0xffffffffff) >> var2; + } + +#if (WMOPS) + multiCounter[currCounter].L40_lshr++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + +/***************************************************************************** + * + * Function Name : norm_L40 + * + * Purpose : + * + * Produces the number of left shifts needed to normalize in 32 bit format + * the 40 bit variable L40_var1. This returned value can be used to scale + * L_40_var1 into the following intervals : + * - [(MAX_32+1)/2 .. MAX_32 ] for positive values. + * - [ MIN_32 .. (MIN_32/2)+1 ] for negative values. + * - [ 0 .. 0 ] for null values. + * In order to normalize the result, the following operation must be done : + * normelized_L40_var1 = L40_shl( L40_var1, norm_L40( L40_var1)) + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * Outputs : + * + * none + * + * Return Value : + * + * var_out 16 bit short signed integer (Word16) whose value falls in + * the range : -8 <= var_out <= 31. + * + *****************************************************************************/ +Word16 norm_L40 (Word40 L40_var1) { + Word16 var_out; + + var_out = 0; + + if (L40_var1 != 0) { + while ((L40_var1 > (Word32) 0x80000000L) + && (L40_var1 < (Word32) 0x7fffffffL)) { + + L40_var1 = L40_shl (L40_var1, 1); + var_out++; + +#ifdef WMOPS + multiCounter[currCounter].L40_shl--; +#endif /* ifdef WMOPS */ + } + + while ((L40_var1 < (Word32) 0x80000000L) + || (L40_var1 > (Word32) 0x7fffffffL)) { + + L40_var1 = L40_shl (L40_var1, -1); + var_out--; + +#ifdef WMOPS + multiCounter[currCounter].L40_shl--; +#endif /* ifdef WMOPS */ + } + } +#ifdef WMOPS + multiCounter[currCounter].norm_L40++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + + + + + +/***************************************************************************** + * + * Function Name : L40_shr_r + * + * Purpose : + * + * Arithmetically shifts right L40_var1 by var2 positions and rounds the + * result. It is equivalent to L40_shr( L40_var1, var2) except that if the + * last bit shifted out to the LSBit is 1, then the shifted result is + * incremented by 1. + * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit. + * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit. + * + * Complexity weight : 3 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : 0xffff 8000 <= var2 <= 0x0000 7fff. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +Word40 L40_shr_r (Word40 L40_var1, Word16 var2) { + Word40 L40_var_out; + + if (var2 > 39) { + L40_var_out = 0; + + } else { + L40_var_out = L40_shr (L40_var1, var2); + +#if (WMOPS) + multiCounter[currCounter].L40_shr--; +#endif /* ifdef WMOPS */ + + if (var2 > 0) { + if ((L40_var1 & ((Word40) 1 << (var2 - 1))) != 0) { + /* below line can not generate overflows on 40-bit */ + L40_var_out++; + } + } + } + +#if (WMOPS) + multiCounter[currCounter].L40_shr_r++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + +/***************************************************************************** + * + * Function Name : L40_shl_r + * + * Purpose : + * + * Arithmetically shifts left L40_var1 by var2 positions and rounds the + * result. It is equivalent to L40_shl( L40_var1, var2) except if var2 is + * negative. In that case, it does the same as + * L40_shr_r( L40_var1, (-var2)). + * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit. + * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit. + * + * Complexity weight : 3 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : 0xffff 8000 <= var2 <= 0x0000 7fff. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +Word40 L40_shl_r (Word40 L40_var1, Word16 var2) { + Word40 L40_var_out; + + if (var2 >= 0) { + L40_var_out = L40_shl (L40_var1, var2); + +#if (WMOPS) + multiCounter[currCounter].L40_shl--; +#endif /* ifdef WMOPS */ + + } else { + var2 = -var2; + L40_var_out = L40_shr_r (L40_var1, var2); + +#if (WMOPS) + multiCounter[currCounter].L40_shr_r--; +#endif /* ifdef WMOPS */ + } +#if (WMOPS) + multiCounter[currCounter].L40_shl_r++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + +/* end of file */ diff --git a/basic_op/enh40.h b/basic_op/enh40.h new file mode 100644 index 0000000..69ab7fc --- /dev/null +++ b/basic_op/enh40.h @@ -0,0 +1,839 @@ +/* + =========================================================================== + File: ENH40.H v.2.3 - 30.Nov.2009 + =========================================================================== + + ITU-T STL BASIC OPERATORS + + 40-BIT ARITHMETIC OPERATORS + + History: + 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control + operators for the ITU-T Standard Tool Library as + described in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + TD 11 document and subsequent discussions on the + wp3audio@yahoogroups.com email reflector. + March 06 v2.1 Changed to improve portability. + + ============================================================================ +*/ + + +#ifndef _ENH40_H +#define _ENH40_H + + +#include "stl.h" + + +#ifdef WMOPS +extern BASIC_OP multiCounter[MAXCOUNTERS]; +extern int currCounter; +#endif /* ifdef WMOPS */ + + +/***************************************************************************** + * + * Constants and Globals + * + *****************************************************************************/ +#ifdef _MSC_VER +#define MAX_40 (0x0000007fffffffff) +#define MIN_40 (0xffffff8000000000) +#endif /* ifdef _MSC_VER */ + + + +/***************************************************************************** + * + * Macros for 40 bit arithmetic overflow management : + * Upon 40-bit overflow beyond MAX_40 or underflow beyond MIN_40, + * the application will exit. + * + *****************************************************************************/ +#define L40_OVERFLOW_OCCURED( L40_var1) (Overflow = 1, exit(1), L40_var1) +#define L40_UNDERFLOW_OCCURED( L40_var1) (Overflow = 1, exit(2), L40_var1) + + + + /***************************************************************************** + * + * Prototypes for enhanced 40 bit arithmetic operators + * + *****************************************************************************/ +Word40 L40_shr (Word40 L40_var1, Word16 var2); +Word40 L40_shr_r (Word40 L40_var1, Word16 var2); +Word40 L40_shl (Word40 L40_var1, Word16 var2); +Word40 L40_shl_r (Word40 L40_var1, Word16 var2); + +static __inline Word40 L40_mult (Word16 var1, Word16 var2); + +static __inline Word40 L40_mac (Word40 L40_var1, Word16 var1, Word16 var2); +static __inline Word16 mac_r40 (Word40 L40_var1, Word16 var1, Word16 var2); + +static __inline Word40 L40_msu (Word40 L40_var1, Word16 var1, Word16 var2); +static __inline Word16 msu_r40 (Word40 L40_var1, Word16 var1, Word16 var2); + + +void Mpy_32_16_ss (Word32 L_var1, Word16 var2, Word32 * L_varout_h, UWord16 * varout_l); +void Mpy_32_32_ss (Word32 L_var1, Word32 L_var2, Word32 * L_varout_h, UWord32 * L_varout_l); + + +Word40 L40_lshl (Word40 L40_var1, Word16 var2); +Word40 L40_lshr (Word40 L40_var1, Word16 var2); + +static __inline Word40 L40_set (Word40 L40_var1); +static __inline UWord16 Extract40_H (Word40 L40_var1); +static __inline UWord16 Extract40_L (Word40 L40_var1); +static __inline UWord32 L_Extract40 (Word40 L40_var1); + +static __inline Word40 L40_deposit_h (Word16 var1); +static __inline Word40 L40_deposit_l (Word16 var1); +static __inline Word40 L40_deposit32 (Word32 L_var1); + +static __inline Word40 L40_round (Word40 L40_var1); +static __inline Word16 round40 (Word40 L40_var1); + + +Word40 L40_add (Word40 L40_var1, Word40 L40_var2); +Word40 L40_sub (Word40 L40_var1, Word40 L40_var2); +Word40 L40_abs (Word40 L40_var1); +Word40 L40_negate (Word40 L40_var1); +Word40 L40_max (Word40 L40_var1, Word40 L40_var2); +Word40 L40_min (Word40 L40_var1, Word40 L40_var2); +Word32 L_saturate40 (Word40 L40_var1); +Word16 norm_L40 (Word40 L40_var1); + + +/***************************************************************************** + * + * Functions + * + *****************************************************************************/ + +/***************************************************************************** + * + * Function Name : L40_set + * + * Purpose : + * + * Assigns a 40 constant to a Word40 with adequate initialization depending + * on underlying architecture constraints (for example to keep consistency + * of sign bits). Current implementation only validated on MSVC++6.0. + * + * Complexity weight : 3 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +/*#ifdef _MSC_VER*/ +static __inline Word40 L40_set (Word40 L40_var1) { + Word40 L40_var_out; + + L40_var_out = L40_var1 & 0x000000ffffffffff; + + if (L40_var1 & 0x8000000000) + L40_var_out = L40_var_out | 0xffffff0000000000; + +#ifdef WMOPS + multiCounter[currCounter].L40_set++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + +/* #endif */ /* ifdef _MSC_VER */ + + +/***************************************************************************** + * + * Function Name : Extract40_H + * + * Purpose : + * + * Returns the bits [31-16] of L40_var1. + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * Outputs : + * + * none + * + * Return Value : + * + * var_out 16 bit short unsigned integer (UWord16) whose value falls in + * the range : MIN_U_16 <= var_out <= MAX_U_16. + * + *****************************************************************************/ +static __inline UWord16 Extract40_H (Word40 L40_var1) { + UWord16 var_out; + + var_out = (UWord16) (L40_var1 >> 16); + +#if (WMOPS) + multiCounter[currCounter].Extract40_H++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + +/***************************************************************************** + * + * Function Name : Extract40_L + * + * Purpose : + * + * Returns the bits [15-0] of L40_var1. + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * Outputs : + * + * none + * + * Return Value : + * + * var_out 16 bit short unsigned integer (UWord16) whose value falls in + * the range : MIN_U_16 <= var_out <= MAX_U_16. + * + *****************************************************************************/ +static __inline UWord16 Extract40_L (Word40 L40_var1) { + UWord16 var_out; + + var_out = (UWord16) (L40_var1); + +#if (WMOPS) + multiCounter[currCounter].Extract40_L++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + +/***************************************************************************** + * + * Function Name : L_Extract40 + * + * Purpose : + * + * Returns the bits [31-0] of L40_var1. + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * Outputs : + * + * none + * + * Return Value : + * + * L_var_out 32 bit long unsigned integer (UWord32) whose value falls in + * range : MIN_U_32 <= L_var_out <= MAX_U_32. + * + *****************************************************************************/ +static __inline UWord32 L_Extract40 (Word40 L40_var1) { + UWord32 L_var_out; + + L_var_out = (UWord32) L40_var1; + +#if (WMOPS) + multiCounter[currCounter].L_Extract40++; +#endif /* ifdef WMOPS */ + + return (L_var_out); +} + + +/***************************************************************************** + * + * Function Name : L40_deposit_h + * + * Purpose : + * + * Deposits var1 in the bits [31-16] in a 40-bit number. The 16 LSBits of + * the output are zeroed and the 8 MSBits sign extend var1 sign bit. + * + * Complexity weight : 1 + * + * Inputs : + * + * var1 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var1 <= MAX_16. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +static __inline Word40 L40_deposit_h (Word16 var1) { + Word40 L40_var_out; + + L40_var_out = ((Word40) var1) << 16; + + if (var1 & 0x8000) { + L40_var_out = L40_set (L40_var_out | 0xff00000000); + +#if (WMOPS) + multiCounter[currCounter].L40_set--; +#endif /* ifdef WMOPS */ + } +#if (WMOPS) + multiCounter[currCounter].L40_deposit_h++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + +/***************************************************************************** + * + * Function Name : L40_deposit_l + * + * Purpose : + * + * Deposits var1 in the bits [15-0] in a 40-bit number. The 24 MSBits sign + * extend var1 sign bit. + * + * Complexity weight : 1 + * + * Inputs : + * + * var1 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var1 <= MAX_16. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +static __inline Word40 L40_deposit_l (Word16 var1) { + Word40 L40_var_out; + + L40_var_out = var1; + + if (var1 & 0x8000) { + L40_var_out = L40_set (L40_var_out | 0xffffff0000); + +#if (WMOPS) + multiCounter[currCounter].L40_set--; +#endif /* ifdef WMOPS */ + } +#if (WMOPS) + multiCounter[currCounter].L40_deposit_l++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + +/***************************************************************************** + * + * Function Name : L40_deposit32 + * + * Purpose : + * + * Deposits L_var1 in the bits [31-0] in a 40-bit number. The 8 MSBits sign + * extend L_var1 sign bit. + * + * Complexity weight : 1 + * + * Inputs : + * + * L_var1 32 bit long signed integer (Word32) whose value falls in the + * range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +static __inline Word40 L40_deposit32 (Word32 L_var1) { + Word40 L40_var_out; + + L40_var_out = (Word40) L_var1; + + if (L_var1 & 0x80000000) { + L40_var_out = L40_set (L40_var_out | 0xff00000000); + +#if (WMOPS) + multiCounter[currCounter].L40_set--; +#endif /* ifdef WMOPS */ + } +#if (WMOPS) + multiCounter[currCounter].L40_deposit32++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + + + + + + + +/***************************************************************************** + * + * Function Name : L40_round + * + * Purpose : + * + * Rounds the lower 16 bits of the 40 bit input number. Returns the 40 bit + * result with bits 15-0 cleared. + * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit. + * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit. + * + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +static __inline Word40 L40_round (Word40 L40_var1) { + Word40 L40_var_out; + Word40 L40_constant = L40_set (0xffffff0000); + + L40_var_out = L40_add (0x8000, L40_var1); + L40_var_out = L40_var_out & L40_constant; + +#if (WMOPS) + multiCounter[currCounter].L40_set--; + multiCounter[currCounter].L40_add--; + multiCounter[currCounter].L40_round++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + +/***************************************************************************** + * + * Function Name : round40 + * + * Purpose : + * + * Rounds the lower 16 bits of the 40 bit input number. Saturates the 40 + * bit result to 32-bit and returns the resulting higher 16-bit. + * round40( L40_var1) = extract_h( L_saturate40( L40_round( L40_var1))) + * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit. + * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit. + * + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * + * Outputs : + * + * none + * + * Return Value : + * + * var_out 16 bit short signed integer (Word16) whose value falls in + * the range 0xffff 8000 <= var_out <= 0x0000 7fff. + * + *****************************************************************************/ +static __inline Word16 round40 (Word40 L40_var1) { + Word16 var_out; + + var_out = extract_h (L_saturate40 (L40_round (L40_var1))); + +#if (WMOPS) + multiCounter[currCounter].L40_round--; + multiCounter[currCounter].L_saturate40--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].round40++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + +/***************************************************************************** + * + * Function Name : L40_mult + * + * Purpose : + * + * Multiplies var1 by var2 and shifts the result left by 1. Returns the + * full precision result on 40-bit. + * L40_mult( var1, var2) = shiftleft(( var1 times var2), 1) + * + * Complexity weight : 1 + * + * Inputs : + * + * var1 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var1 <= MAX_16. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var2 <= MAX_16. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +static __inline Word40 L40_mult (Word16 var1, Word16 var2) { + Word32 L_var_out; + Word40 L40_var_out; + + L_var_out = (Word32) var1 *(Word32) var2; + L40_var_out = (Word40) L_var_out; + + /* Below line can not overflow, so we can use << instead of L40_shl. */ + L40_var_out = L40_var_out << 1; + +#if (WMOPS) + multiCounter[currCounter].L40_mult++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + + + + + + + + + + + +/***************************************************************************** + * + * Function Name : L40_mac + * + * Purpose : + * + * Multiplies var2 by var3. Shifts left the 40-bit result by 1 and adds + * the result to L40_var1. Returns a 40 bit result. + * L40_mac( L40_var1, var2, var3) + * = L40_add( L40_var1, L40_mult( var2, var3)) + * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit. + * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit. + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var2 <= MAX_16. + * + * var3 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var3 <= MAX_16. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +static __inline Word40 L40_mac (Word40 L40_var1, Word16 var2, Word16 var3) { + Word40 L40_var_out; + + L40_var_out = L40_mult (var2, var3); + L40_var_out = L40_add (L40_var1, L40_var_out); + +#if (WMOPS) + multiCounter[currCounter].L40_mult--; + multiCounter[currCounter].L40_add--; + multiCounter[currCounter].L40_mac++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + + + + + +/***************************************************************************** + * + * Function Name : mac_r40 + * + * Purpose : + * + * Multiplies var2 by var3. Shifts left the 40-bit result by 1 and adds + * the result to L40_var1. Rounds the lower 16 bits of the 40 bit result. + * Saturates the 40 bit result to 32-bit and returns the resulting higher + * 16-bit. + * mac_r40( L40_var1, var2, var3) + * = round40( L40_mac( L40_var1, var2, var3)) + * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit. + * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit. + * + * Complexity weight : 2 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var2 <= MAX_16. + * + * var3 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var3 <= MAX_16. + * + * Outputs : + * + * none + * + * Return Value : + * + * var_out 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var_out <= MAX_16. + * + *****************************************************************************/ +static __inline Word16 mac_r40 (Word40 L40_var1, Word16 var2, Word16 var3) { + Word40 L40_var_out; + Word16 var_out; + + L40_var_out = L40_mac (L40_var1, var2, var3); + var_out = round40 (L40_var_out); + +#if (WMOPS) + multiCounter[currCounter].L40_mac--; + multiCounter[currCounter].round40--; + multiCounter[currCounter].mac_r40++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + + + + + +/***************************************************************************** + * + * Function Name : L40_msu + * + * Purpose : + * + * Multiplies var2 by var3. Shifts left the 40-bit result by 1 and + * subtracts the result from L40_var1. Returns a 40 bit result. + * L40_msu( L40_var1, var2, var3) + * = L40_sub( L40_var1, L40_mult( var2, var3)) + * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit. + * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit. + * + * Complexity weight : 1 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var2 <= MAX_16. + * + * var3 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var3 <= MAX_16. + * + * Outputs : + * + * none + * + * Return Value : + * + * L40_var_out 40 bit long signed integer (Word40) whose value falls in + * the range : MIN_40 <= L40_var_out <= MAX_40. + * + *****************************************************************************/ +static __inline Word40 L40_msu (Word40 L40_var1, Word16 var2, Word16 var3) { + Word40 L40_var_out; + + L40_var_out = L40_mult (var2, var3); + L40_var_out = L40_sub (L40_var1, L40_var_out); + +#if (WMOPS) + multiCounter[currCounter].L40_mult--; + multiCounter[currCounter].L40_sub--; + multiCounter[currCounter].L40_msu++; +#endif /* ifdef WMOPS */ + + return (L40_var_out); +} + + + + + + +/***************************************************************************** + * + * Function Name : msu_r40 + * + * Purpose : + * + * Multiplies var2 by var3. Shifts left the 40-bit result by 1 and + * subtracts the result from L40_var1. Rounds the lower 16 bits of the + * 40 bit result. Saturates the 40 bit result to 32-bit and returns the + * resulting higher 16-bit. + * msu_r40( L40_var1, var2, var3) + * = round40( L40_msu( L40_var1, var2, var3)) + * Calls the macro L40_UNDERFLOW_OCCURED() in case of underflow on 40-bit. + * Calls the macro L40_OVERFLOW_OCCURED() in case of overflow on 40-bit. + * + * Complexity weight : 2 + * + * Inputs : + * + * L40_var1 40 bit long signed integer (Word40) whose value falls in the + * range : MIN_40 <= L40_var1 <= MAX_40. + * + * var2 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var2 <= MAX_16. + * + * var3 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var3 <= MAX_16. + * + * Outputs : + * + * none + * + * Return Value : + * + * var_out 16 bit short signed integer (Word16) whose value falls in + * the range : MIN_16 <= var_out <= MAX_16. + * + *****************************************************************************/ +static __inline Word16 msu_r40 (Word40 L40_var1, Word16 var2, Word16 var3) { + Word40 L40_var_out; + Word16 var_out; + + L40_var_out = L40_msu (L40_var1, var2, var3); + var_out = round40 (L40_var_out); + +#if (WMOPS) + multiCounter[currCounter].L40_msu--; + multiCounter[currCounter].round40--; + multiCounter[currCounter].msu_r40++; +#endif /* ifdef WMOPS */ + + return (var_out); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#endif /*_ENH40_H*/ + + +/* end of file */ diff --git a/basic_op/enh64.c b/basic_op/enh64.c new file mode 100644 index 0000000..4a365ee --- /dev/null +++ b/basic_op/enh64.c @@ -0,0 +1,1665 @@ +/***************************************************************************** +* +* Enhanced 64 bit operators : +* +* W_mac_32_16() +* W_mac0_16_16() +* W_msu0_16_16() +* +*****************************************************************************/ + + +/***************************************************************************** +* +* Include-Files +* +*****************************************************************************/ +#include +#include +#include "enh64.h" + +#if (WMOPS) +extern BASIC_OP multiCounter[MAXCOUNTERS]; +extern int currCounter; +#endif /* if WMOPS */ + + +/***************************************************************************** +* +* Local Functions +* +*****************************************************************************/ + +/***************************************************************************** +* +* Constants and Globals +* +*****************************************************************************/ + + +/***************************************************************************** +* +* Functions +* +*****************************************************************************/ + +#ifdef ENH_64_BIT_OPERATOR + + +/*___________________________________________________________________________ +| | +| Function Name : W_add_nosat | +| | +| Purpose : | +| | +| 64 bits addition of the two 64 bits variables (L64_var1+L64_var2) | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| L64_var2 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +|___________________________________________________________________________| +*/ +Word64 W_add_nosat (Word64 L64_var1, Word64 L64_var2) { + Word64 L64_var_out; + + L64_var_out = L64_var1 + L64_var2; + +#if (WMOPS) + multiCounter[currCounter].W_add_nosat++; +#endif + + return L64_var_out; +} + + +/*___________________________________________________________________________ +| | +| Function Name : W_sub_nosat | +| | +| Purpose : | +| | +| 64 bits subtraction of the two 64 bits variables (L64_var1-L64_var2) | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| L64_var2 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +|___________________________________________________________________________| +*/ +Word64 W_sub_nosat (Word64 L64_var1, Word64 L64_var2) { + Word64 L64_var_out; + + L64_var_out = L64_var1 - L64_var2; + +#if (WMOPS) + multiCounter[currCounter].W_sub_nosat++; +#endif + + return L64_var_out; +} + + +/*___________________________________________________________________________ +| | +| Function Name : W_shl | +| | +| Purpose : | +| | +| Arithmetically shift the 64 bit input L64_var1 left var2 positions. Zero| +| fill the var2 LSB of the result. If var2 is negative, arithmetically | +| shift L64_var1 right by -var2 with sign extension. Saturate the result | +| in case of underflows or overflows. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 64 bit long signed integer (Word64) whose value falls in the| +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +|___________________________________________________________________________| +*/ +Word64 W_shl (Word64 L64_var1, Word16 var2) { + + Word64 L64_var_out = 0LL; + + if (var2 <= 0) { + if (var2 < -64) + var2 = -64; + var2 = -var2; + L64_var_out = L64_var1 >> var2; + } + else { + for (; var2 > 0; var2--) { + if (L64_var1 > (Word64) 0X3fffffffffffffffLL) { + Overflow = 1; + L64_var_out = (Word64) 0X7fffffffffffffffLL; + break; + } + else { + if (L64_var1 < (Word64) 0xc000000000000000LL) { + Overflow = 1; + L64_var_out = (Word64)0x8000000000000000LL; + break; + } + } + L64_var1 *= 2; + L64_var_out = L64_var1; + } + } +#if (WMOPS) + multiCounter[currCounter].W_shl++; +#endif + +/* BASOP_CHECK();*/ + + return (L64_var_out); +} + + +/*___________________________________________________________________________ +| | +| Function Name : W_shr | +| | +| Purpose : | +| | +| Arithmetically shift the 64 bit input L64_var1 right var2 positions. | +| Zero fill the var2 LSB of the result. If var2 is negative, | +| arithmetically shift L64_var1 left by -var2 with sign extension. | +| Saturate the result in case of underflows or overflows. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 64 bit long signed integer (Word64) whose value falls in the| +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +|___________________________________________________________________________| +*/ +Word64 W_shr (Word64 L64_var1, Word16 var2) { + Word64 L64_var_out; + + if (var2 < 0) { + var2 = -var2; + L64_var_out = W_shl (L64_var1, var2); + +#if (WMOPS) + multiCounter[currCounter].W_shl--; +#endif /* if WMOPS */ + + } else { + L64_var_out = L64_var1 >> var2; + } + +#if (WMOPS) + multiCounter[currCounter].W_shr++; +#endif /* if WMOPS */ + + return (L64_var_out); +} + + +/*___________________________________________________________________________ +| | +| Function Name : W_shl_nosat | +| | +| Purpose : | +| | +| Arithmetically shifts left the 64-bit variable W_var1 by var2 positions. | +| if var2 is negative, W_var1 is shifted to the least significant bits by | +| (�var2) positions with extension of the sign bit . | +| if var2 is positive, W_var1 is shifted to the most significant bits by | +| (var2) positions without saturation control on 64 bits. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 64 bit long signed integer (Word64) whose value falls in the| +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +|___________________________________________________________________________| +*/ +Word64 W_shl_nosat (Word64 L64_var1, Word16 var2) { + + Word64 L64_var_out = 0LL; + + if (var2 <= 0) { + var2 = -var2; + L64_var_out = L64_var1 >> var2; + } + else { + L64_var_out = L64_var1 << var2; + } +#if (WMOPS) + multiCounter[currCounter].W_shl_nosat++; +#endif + +/* BASOP_CHECK();*/ + + return (L64_var_out); +} + + +/*___________________________________________________________________________ +| | +| Function Name : W_shr_nosat | +| | +| Purpose : | +| | +| Arithmetically shifts right the 64-bit variable W_var1 by var2 positions. | +| if var2 is negative, W_var1 is shifted to the most significant bits by | +| (�var2) positions without saturation control on 64 bits. | +| if var2 is positive, W_var1 is shifted to the least significant bits by | +| (var2) positions with extension of the sign bit . | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 64 bit long signed integer (Word64) whose value falls in the| +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +|___________________________________________________________________________| +*/ +Word64 W_shr_nosat (Word64 L64_var1, Word16 var2) { + Word64 L64_var_out; + + if (var2 < 0) { + var2 = -var2; + L64_var_out = L64_var1 << var2; + + } else { + L64_var_out = L64_var1 >> var2; + } + +#if (WMOPS) + multiCounter[currCounter].W_shr_nosat++; +#endif /* if WMOPS */ + + return (L64_var_out); +} + + +/*_________________________________________________________________________________________________ +| | +| Function Name : W_mac_32_16 | +| | +| Purpose : | +| | +| Multiply L_var2 by var3 and shift the result left by 1. Add the 64 bit | +| result to L64_var1, return a 64 bit result. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| L_var2 | +| 32 bit signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var2 <= 0x7fff ffff | +| | +| var3 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var3 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var_out <= 0x7fffffff ffffffffLL. | +|_________________________________________________________________________________________________| +*/ +Word64 W_mac_32_16 (Word64 L64_var1, Word32 L_var2, Word16 var3) { + Word64 L64_var_out = ((Word64) L_var2*var3) << 1; + L64_var_out += L64_var1; +#if (WMOPS) + multiCounter[currCounter].W_mac_32_16++; +#endif /* if WMOPS */ + return L64_var_out; +} + + +/*_________________________________________________________________________________________________ +| | +| Function Name : W_msu_32_16 | +| | +| Purpose : | +| | +| Multiply L_var2 by var3 and shift the result left by 1. Subtract the 64 bit | +| result from L64_var1, return a 64 bit result. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| L_var2 | +| 32 bit signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var2 <= 0x7fff ffff | +| | +| var3 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var3 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var_out <= 0x7fffffff ffffffffLL. | +|_________________________________________________________________________________________________| +*/ +Word64 W_msu_32_16(Word64 L64_var1, Word32 L_var2, Word16 var3) { + Word64 L64_var_out = ((Word64 )L_var2*var3) << 1; + L64_var_out = L64_var1 - L64_var_out; +#if (WMOPS) + multiCounter[currCounter].W_msu_32_16++; +#endif /* if WMOPS */ + return L64_var_out; +} + + +/*_________________________________________________________________________________________________ +| | +| Function Name : W_mult_32_16 | +| | +| Purpose : | +| | +| Multiply L_var1 by var2 and shift the result left by 1. Return a 64 bit result. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L_var1 | +| 32 bit signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var1 <= 0x7fff ffff | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var2 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var_out <= 0x7fffffff ffffffffLL. | +|_________________________________________________________________________________________________| +*/ +Word64 W_mult_32_16(Word32 L_var1, Word16 var2) { + Word64 L64_var_out = ((Word64 )L_var1*var2) << 1; +#if (WMOPS) + multiCounter[currCounter].W_mult_32_16++; +#endif /* if WMOPS */ + return L64_var_out; +} + +/*________________________________________________________________________________________________ +| | +| Function Name : W_mult0_16_16 | +| | +| Purpose : | +| | +| Multiply var1 by var2 and return a 64 bit result. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| var1 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0x8000 0000 <= L_var1 <= 0x7fff ffff | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_acc <= 0x7fffffff ffffffffLL. | +|_________________________________________________________________________________________________| +*/ +Word64 W_mult0_16_16(Word16 var1, Word16 var2) { + Word64 L64_var_out = (Word64 )var1*var2; +#if (WMOPS) + multiCounter[currCounter].W_mult0_16_16++; +#endif /* if WMOPS */ + return L64_var_out; +} + +/*________________________________________________________________________________________________ +| | +| Function Name : W_mac0_16_16 | +| | +| Purpose : | +| | +| Multiply var2 by var3 and add the 64 bit result to L64_var1, return a 64 bit result. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var2 <= 0x0000 7fff. | +| | +| var3 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var3 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var_out <= 0x7fffffff ffffffffLL. | +|_________________________________________________________________________________________________| +*/ +Word64 W_mac0_16_16(Word64 L64_var1, Word16 var2, Word16 var3) { + Word64 L64_var_out = (Word64 )var2*var3; + L64_var_out += L64_var1; +#if (WMOPS) + multiCounter[currCounter].W_mac0_16_16++; +#endif /* if WMOPS */ + return L64_var_out; +} + + +/*________________________________________________________________________________________________ +| | +| Function Name : W_msu0_16_16 | +| | +| Purpose : | +| | +| Multiply var2 by var3 and subtract the 64 bit result from L64_var1, return a 64 bit result. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var2 <= 0x0000 7fff. | +| | +| var3 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var3 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var_out <= 0x7fffffff ffffffffLL. | +|_________________________________________________________________________________________________| +*/ +Word64 W_msu0_16_16 (Word64 L64_var1, Word16 var2, Word16 var3) { + Word64 L64_var_out = (Word64) var2*var3; + L64_var_out = L64_var1 - L64_var_out; +#if (WMOPS) + multiCounter[currCounter].W_msu0_16_16++; +#endif /* if WMOPS */ + return L64_var_out; +} + + + +/*_____________________________________________________________________________________ +| | +| Function Name : W_sat_l | +| | +| Purpose : | +| | +| Saturate the lower 32 bits of the 64 bit input number L64_var into 32 bits. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var <= 0x7fffffff ffffffffLL. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L_var_out | +| 32 bit signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var_out <= 0x7fff 0000. | +|_____________________________________________________________________________________| +*/ +Word32 W_sat_l (Word64 L64_var) { + Word32 L_var_out; + + if (L64_var > 0x7FFFFFFF) { + L_var_out = 0x7FFFFFFF; + } + else if (L64_var < (int)0x80000000) { + L_var_out = 0x80000000; + } + else { + L_var_out = (Word32)L64_var; + } + +#if (WMOPS) + multiCounter[currCounter].W_sat_l++; +#endif /* if WMOPS */ + + return L_var_out; +} + + + +/*___________________________________________________________________________________ +| | +| Function Name : W_sat_m | +| | +| Purpose : | +| | +| Truncates the lower 16 bits of the 64 bit input L64_var | +| and saturates the number into 32 bits. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var <= 0x7fffffff ffffffffLL. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L_var_out | +| 32 bit signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var_out <= 0x7fff 0000. | +|_____________________________________________________________________________________| +*/ +Word32 W_sat_m (Word64 L64_var) { + Word32 L_var_out; + + L64_var = L64_var >> 16; + L_var_out = W_sat_l (L64_var); + +#if (WMOPS) + multiCounter[currCounter].W_sat_l--; + multiCounter[currCounter].W_sat_m++; +#endif /* if WMOPS */ + + return L_var_out; +} + + +/*__________________________________________________________________________________ +| | +| Function Name : W_deposit32_l | +| | +| Purpose : | +| | +| Deposit the 32 bit L_var1 into the 32 LS bits of the 64 bit output. The | +| 32 MS bits of the output are sign extended. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L_var1 | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= var_out <= 0x7fff 0000. | | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long long signed integer (Word64) whose value falls in | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +|__________________________________________________________________________________| +*/ +Word64 W_deposit32_l (Word32 L_var1) { + Word64 L64_var_out; + + L64_var_out = (Word64) L_var1; + +#if (WMOPS) + multiCounter[currCounter].W_deposit32_l++; +#endif + + return (L64_var_out); +} + + +/*__________________________________________________________________________________ +| | +| Function Name : W_deposit32_h | +| | +| Purpose : | +| | +| Deposit the 32 bit L_var1 into the 32 MS bits of the 64 bit output. The | +| 32 LS bits of the output are zeroed. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L_var1 | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= var_out <= 0x7fff 0000. | | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long long signed integer (Word64) whose value falls in | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +|__________________________________________________________________________________| +*/ +Word64 W_deposit32_h (Word32 L_var1) { + Word64 L64_var_out; + + L64_var_out = (Word64) L_var1 << 32; + +#if (WMOPS) + multiCounter[currCounter].W_deposit32_h++; +#endif + + return (L64_var_out); +} + + +/*__________________________________________________________________________________ +| | +| Function Name : W_extract_l | +| | +| Purpose : | +| | +| Return the 32 LSB of L64_var1. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 | +| 64 bit long long signed integer (Word64) whose value falls in | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L_var_out | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var_out <= 0x7fff 0000. | +|__________________________________________________________________________________| +*/ +Word32 W_extract_l (Word64 L64_var1) { + Word32 L_var_out; + + L_var_out = (Word32) L64_var1; + +#if (WMOPS) + multiCounter[currCounter].W_extract_l++; +#endif /* if WMOPS */ + + return (L_var_out); +} + + + +/*__________________________________________________________________________________ +| | +| Function Name : W_extract_h | +| | +| Purpose : | +| | +| Return the 32 MSB of L64_var1. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 | +| 64 bit long long signed integer (Word64) whose value falls in | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L_var_out | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var_out <= 0x7fff 0000. | +|__________________________________________________________________________________| +*/ +Word32 W_extract_h (Word64 L64_var1) { + Word32 L_var_out; + + L_var_out = (Word32) (L64_var1 >> 32); + +#if (WMOPS) + multiCounter[currCounter].W_extract_h++; +#endif /* if WMOPS */ + + return (L_var_out); +} + + + +/*________________________________________________________________________________________________ +| | +| Function Name : W_mult_16_16 | +| | +| Purpose : | +| | +| Multiply var1 by var2 and shift the result left by 1. Return a 64 bit result. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| var1 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0x8000 0000 <= L_var1 <= 0x7fff ffff | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_acc <= 0x7fffffff ffffffffLL. | +|_________________________________________________________________________________________________| +*/ +Word64 W_mult_16_16 (Word16 var1, Word16 var2) { + Word64 L64_var_out = ((Word64) var1*var2) << 1; +#if (WMOPS) + multiCounter[currCounter].W_mult_16_16++; +#endif /* if WMOPS */ + return L64_var_out; +} +/*________________________________________________________________________________________________ +| | +| Function Name : W_mac_16_16 | +| | +| Purpose : | +| | +| Multiply var1 by var2 and shift the result left by 1 and add the 64 bit result to L64_acc, | +| return a 64 bit result. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_acc | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_acc <= 0x7fffffff ffffffffLL. | +| | +| var1 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var2 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var_out <= 0x7fffffff ffffffffLL. | +|_________________________________________________________________________________________________| +*/ +Word64 W_mac_16_16 (Word64 L64_acc, Word16 var1, Word16 var2) { + Word64 L64_var_out = ((Word64) var1*var2) << 1; + L64_acc = L64_acc + L64_var_out; + +#if (WMOPS) + multiCounter[currCounter].W_mac_16_16++; +#endif /* if WMOPS */ + return L64_acc; +} + + + +/*________________________________________________________________________________________________ +| | +| Function Name : W_msu_16_16 | +| | +| Purpose : | +| | +| Multiply var2 by var3 and shift the result left by1 and subtract the 64 bit result | +| from L64_var1, return a 64 bit result. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var2 <= 0x0000 7fff. | +| | +| var3 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var3 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var_out <= 0x7fffffff ffffffffLL. | +|_________________________________________________________________________________________________| +*/ +Word64 W_msu_16_16 (Word64 L64_var1, Word16 var2, Word16 var3) { + Word64 L64_var_out = ((Word64)var2*var3) << 1; + L64_var_out = L64_var1 - L64_var_out; +#if (WMOPS) + multiCounter[currCounter].W_msu_16_16++; +#endif /* if WMOPS */ + return L64_var_out; +} + + +/*___________________________________________________________________________ +| | +| Function Name : W_shl_sat_l | +| | +| Purpose : | +| | +| Arithmetically shift the 64 bit input L64_var left by n positions with | +| lower 32 bit saturation and return the 32 LSB of 64 bit result | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var | +| 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var <= 0x7fffffff ffffffffLL. | +| | +| n | +| 32 bit signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= n <= 0x7fff 0000. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L_result | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_result <= 0x7fff 0000. | +|___________________________________________________________________________| +*/ +Word32 W_shl_sat_l (Word64 L64_var, Word32 n) { + Word32 L_result; + Word64 d_var_64; + + d_var_64 = W_shl (L64_var, n); + L_result = W_sat_l (d_var_64); + +#if (WMOPS) + multiCounter[currCounter].W_shl_sat_l++; + multiCounter[currCounter].W_shl--; + multiCounter[currCounter].W_sat_l--; +#endif /* if WMOPS */ + + return L_result; +} + + +/*__________________________________________________________________________________ +| | +| Function Name : W_round48_L | +| | +| Purpose : | +| | +| Round asymmetrically lower 16 bits, and | +| saturate the 17.47-bit values to 1.31-bit values | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 | +| 64 bit long long signed integer (Word64) whose value falls in | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L_var_out | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | +|__________________________________________________________________________________| +*/ +Word32 W_round48_L (Word64 L64_var1) { + Word64 L64_var_out; + Word32 L_result; + + Word64 L64_var2 = 0x80000000; + Word64 L64_MIN = 0x8000000000000000LL; + Word64 L64_MAX = 0x7FFFFFFFFFFFFFFFLL; + + L64_var1 = W_shl (L64_var1, 16); + + L64_var_out = L64_var1 + L64_var2; + + if ( ( (L64_var1 ^ L64_var2) & L64_MIN) == 0) { + if ( (L64_var_out ^ L64_var1) & L64_MIN) { + L64_var_out = (L64_var1 < 0) ? L64_MIN : L64_MAX; + Overflow = 1; + } + } + L_result = W_extract_h (L64_var_out); +#if (WMOPS) + multiCounter[currCounter].W_round48_L++; + multiCounter[currCounter].W_extract_h--; + multiCounter[currCounter].W_shl--; +#endif /* if WMOPS */ + + return (L_result); +} + +/*__________________________________________________________________________________ +| | +| Function Name : W_round32_s | +| | +| Purpose : | +| | +| Round asymmetrically lower 32 bits, and | +| saturate the 17.47-bit values to 1.15-bit values | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 | +| 64 bit long long signed integer (Word64) whose value falls in | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| var_out | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var_out <= 0x0000 7fff. | +|__________________________________________________________________________________| +*/ +Word16 W_round32_s (Word64 L64_var1) { + Word64 L64_var_out; + Word32 L_var; + Word16 var_out; + + + Word64 L64_var2 = 0x800000000000LL; + Word64 L64_MIN = 0x8000000000000000LL; + Word64 L64_MAX = 0x7FFFFFFFFFFFFFFFLL; + + L64_var1 = W_shl (L64_var1, 16); + L64_var_out = L64_var1 + L64_var2; + + if (((L64_var1 ^ L64_var2) & L64_MIN) == 0) { + if ((L64_var_out ^ L64_var1) & L64_MIN) { + L64_var_out = (L64_var1 < 0) ? L64_MIN : L64_MAX; + Overflow = 1; + } + } + L_var = W_extract_h (L64_var_out); + var_out = extract_h (L_var); +#if (WMOPS) + multiCounter[currCounter].W_round32_s ++; + multiCounter[currCounter].W_extract_h--; + multiCounter[currCounter].extract_h--; + multiCounter[currCounter].W_shl--; +#endif /* if WMOPS */ + + return (var_out); +} +/*___________________________________________________________________________ +| | +| Function Name : W_norm | +| | +| Purpose : | +| | +| Produces the number of left shifts needed to normalize the 64 bit varia-| +| ble L64_var1. +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 | +| 64 bit long long signed integer (Word64) whose value falls in | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| var_out | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0x0000 0000 <= var_out <= 0x0000 003f. | +|___________________________________________________________________________| +*/ +Word16 W_norm (Word64 L64_var1) { + Word16 var_out; + if (L64_var1 == 0) { + var_out = 0; + } + else { + if (L64_var1 == (Word64) 0xffffffffffffffffLL) { + var_out = 63; + } + else { + if (L64_var1 < 0) { + L64_var1 = ~L64_var1; + } + for (var_out = 0; L64_var1 < (Word64) 0x4000000000000000LL; var_out++) { + L64_var1 <<= 1; + } + } + } +#if (WMOPS) + multiCounter[currCounter].W_norm ++; +#endif /* if WMOPS */ + return (var_out); +} + + + +/*______________________________________________________________________________ +| | +| Function Name : W_add | +| | +| Purpose : | +| | +| 64 bits addition of the two 64 bits variables (L64_var1+L64_var2) with | +| overflow control and saturation; the result is set at 0x7fffffffffffffffLL | +| when overflow occurs or at 0x8000000000000000LL when underflow occurs. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| L64_var2 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +|_______________________________________________________________________________| +*/ +Word64 W_add (Word64 L64_var1, Word64 L64_var2) { + Word64 L64_var_out; + + L64_var_out = L64_var1 + L64_var2; + + if (((L64_var1 ^ L64_var2) & MIN_64) == 0) { + if ((L64_var_out ^ L64_var1) & MIN_64) { + L64_var_out = (L64_var1 < 0) ? MIN_64 : MAX_64; + Overflow = 1; + } + } + +#if (WMOPS) + multiCounter[currCounter].W_add++; +#endif + return L64_var_out; +} + +/*______________________________________________________________________________ +| | +| Function Name : W_sub | +| | +| Purpose : | +| | +| 64 bits subtraction of the two 64 bits variables (L64_var1-L64_var2) with | +| overflow control and saturation; the result is set at 0x7fffffffffffffffLL | +| when overflow occurs or at 0x8000000000000000LL when underflow occurs. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| L64_var2 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +|_______________________________________________________________________________| +*/ +Word64 W_sub (Word64 L64_var1, Word64 L64_var2) { + Word64 L64_var_out; + + L64_var_out = L64_var1 - L64_var2; + + if (((L64_var1 ^ L64_var2) & MIN_64) != 0) { + if ((L64_var_out ^ L64_var1) & MIN_64) { + L64_var_out = (L64_var1 < 0) ? MIN_64 : MAX_64; + Overflow = 1; + } + } + +#if (WMOPS) + multiCounter[currCounter].W_add++; +#endif + return L64_var_out; +} + + +/*______________________________________________________________________________ +| | +| Function Name : W_neg | +| | +| Purpose : | +| | +| Negate the 64 bit variable L64_var1 with overflow control and saturation; | +| Saturate and set overflow in the case where input is 0x8000000000000000LL. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +|_______________________________________________________________________________| +*/ +Word64 W_neg (Word64 L64_var1) { + Word64 L64_var_out; + + if (L64_var1 == MIN_64) { + L64_var_out = MAX_64; + Overflow = 1; + } + else { + L64_var_out = -L64_var1; + } + +#if (WMOPS) + multiCounter[currCounter].W_neg++; +#endif + + return (L64_var_out); + +} + + +/*___________________________________________________________________________ + | | + | Function Name : W_abs | + | | + | Purpose : | + | | + | Absolute value of L64_var1; Saturate in case where the input is | + | 0x8000000000000000LL | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | L64_var1 64 bit long signed integer (Word64) whose value falls in the | + | range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | L64_var_out | + | 64 bit long signed integer (Word64) whose value falls in the | + | range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | + |___________________________________________________________________________| +*/ +Word64 W_abs (Word64 L64_var1) { + Word64 L64_var_out; + + if (L64_var1 == MIN_64) { + L64_var_out = MAX_64; + Overflow = 1; + } + else { + if (L64_var1 < 0) { + L64_var_out = -L64_var1; + } + else { + L64_var_out = L64_var1; + } + } + +#if (WMOPS) + multiCounter[currCounter].W_abs++; +#endif + + return (L64_var_out); +} + +/*_________________________________________________________________________________________________ +| | +| Function Name : W_mult_32_32 | +| | +| Purpose : | +| | +| Multiply L_var1 by L_var2 and shift the result left by 1.Saturate and set overflow in case | +| where both inputs are 0x80000000 . Return a 64 bit result. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L_var1 | +| 32 bit signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var1 <= 0x7fff ffff | +| | +| L_var2 | +| 32 bit signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var1 <= 0x7fff ffff | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var_out <= 0x7fffffff ffffffffLL. | +|_________________________________________________________________________________________________| +*/ +Word64 W_mult_32_32(Word32 L_var1, Word32 L_var2) { + Word64 L64_var_out; + + if ((L_var1 == MIN_32) && (L_var2 == MIN_32)) { + L64_var_out = MAX_64; + Overflow = 1; + } + else { + L64_var_out = ((Word64 )L_var1*L_var2) << 1; + } + +#if (WMOPS) + multiCounter[currCounter].W_mult_32_32++; +#endif /* if WMOPS */ + return L64_var_out; +} + +/*_________________________________________________________________________________________________ +| | +| Function Name : W_mult0_32_32 | +| | +| Purpose : | +| | +| Multiply L_var1 by L_var2. Return a 64 bit result. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L_var1 | +| 32 bit signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var1 <= 0x7fff ffff | +| | +| L_var2 | +| 32 bit signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var1 <= 0x7fff ffff | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long long signed integer (Word64) whose value falls in the | +| range : 0x80000000 00000000LL <= L64_var_out <= 0x7fffffff ffffffffLL. | +|_________________________________________________________________________________________________| +*/ +Word64 W_mult0_32_32 (Word32 L_var1, Word32 L_var2) { + Word64 L64_var_out; + + L64_var_out = (Word64) L_var1*L_var2; + + +#if (WMOPS) + multiCounter[currCounter].W_mult0_32_32++; +#endif /* if WMOPS */ + return L64_var_out; +} + + +/*_____________________________________________________________________________ +| | +| Function Name : W_lshl | +| | +| Purpose : | +| | +| Logically shift the 64 bit unsigned input L64_var1 left by var2 positions. | +| Zero fill the var2 LSB of the result. If var2 is negative, logically shift | +| L64_var1 right by -var2 with zero fill in the MSB. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 64 bit long unsigned signed integer (UWord64) whose value falls | +| in the range : 0LL <= L64_var1 <= 0xffffffff ffffffffLL. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long unsigned signed integer (UWord64) whose value falls | +| in the range : 0LL <= L64_var1 <= 0xffffffff ffffffffLL. | +|______________________________________________________________________________| +*/ +UWord64 W_lshl (UWord64 L64_var1, Word16 var2) { + + UWord64 L64_var_out = 0LL; + + if (var2 < 0) { + L64_var_out = L64_var1 >> (-var2); + } + else { + L64_var_out = L64_var1 << var2 ; + } +#if (WMOPS) + multiCounter[currCounter].W_lshl++; +#endif + + return (L64_var_out); +} + +/*_____________________________________________________________________________ +| | +| Function Name : W_lshr | +| | +| Purpose : | +| | +| Logically shift the 64 bit unsigned input L64_var1 right by var2 positions.| +| Zero fill the var2 MSB of the result. If var2 is negative, logically shift | +| L64_var1 left by -var2 with zero fill in the LSB. | +| | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 64 bit long unsigned signed integer (UWord64) whose value falls | +| in the range : 0LL <= L64_var1 <= 0xffffffff ffffffffLL. | +| | +| var2 | +| 16 bit short signed integer (Word16) whose value falls in the | +| range : 0xffff 8000 <= var1 <= 0x0000 7fff. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L64_var_out | +| 64 bit long unsigned signed integer (UWord64) whose value falls | +| in the range : 0LL <= L64_var1 <= 0xffffffff ffffffffLL. | +|______________________________________________________________________________| +*/ +UWord64 W_lshr (UWord64 L64_var1, Word16 var2) { + + UWord64 L64_var_out = 0LL; + + if (var2 < 0) { + L64_var_out = L64_var1 << (-var2); + } + else { + L64_var_out = L64_var1 >> var2 ; + } +#if (WMOPS) + multiCounter[currCounter].W_lshr++; +#endif + + return (L64_var_out); +} + + +/*__________________________________________________________________________________ +| | +| Function Name : W_round64_L | +| | +| Purpose : | +| | +| Round asymmetrically lower 32 bits, and | +| saturate the 1.63-bit values to 1.31-bit values | +| Complexity weight : 1 | +| | +| Inputs : | +| | +| L64_var1 | +| 64 bit long long signed integer (Word64) whose value falls in | +| range : 0x80000000 00000000LL <= L64_var1 <= 0x7fffffff ffffffffLL. | +| | +| Outputs : | +| | +| none | +| | +| Return Value : | +| | +| L_var_out | +| 32 bit long signed integer (Word32) whose value falls in the | +| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. | +|__________________________________________________________________________________| +*/ +Word32 W_round64_L (Word64 L64_var1) { + Word64 L64_var_out; + Word32 L_result; + + + Word64 L64_tmp = 0x80000000; + L64_var_out = W_add (L64_var1, L64_tmp); + L_result = W_extract_h (L64_var_out); + +#if (WMOPS) + multiCounter[currCounter].W_round64_L++; + multiCounter[currCounter].W_extract_h--; + multiCounter[currCounter].W_add--; +#endif /* if WMOPS */ + + return (L_result); +} + +#endif /* #ifdef ENH_64_BIT_OPERATOR */ + +/* end of file */ diff --git a/basic_op/enh64.h b/basic_op/enh64.h new file mode 100644 index 0000000..ac15ffd --- /dev/null +++ b/basic_op/enh64.h @@ -0,0 +1,73 @@ + +#ifndef _ENH64_H +#define _ENH64_H + +#include "stl.h" + +#ifndef Word64 +#define Word64 long long int +#endif + +#ifndef UWord64 +#define UWord64 unsigned long long int +#endif + +#define MAX_64 (Word64)0x7fffffffffffffffLL +#define MIN_64 (Word64)0x8000000000000000LL + + /***************************************************************************** + * + * Prototypes for enhanced 64 bit arithmetic operators + * + *****************************************************************************/ +#ifdef ENH_64_BIT_OPERATOR +Word64 W_add_nosat (Word64 L64_var1, Word64 L64_var2); +Word64 W_sub_nosat (Word64 L64_var1, Word64 L64_var2); +Word64 W_shl (Word64 L64_var1, Word16 var2); +Word64 W_shr (Word64 L64_var1, Word16 var2); +Word64 W_shl_nosat (Word64 L64_var1, Word16 var2); +Word64 W_shr_nosat (Word64 L64_var1, Word16 var2); +Word64 W_mult_32_16 (Word32 L_var1, Word16 var2); +Word64 W_mac_32_16 (Word64 L64_acc, Word32 L_var1, Word16 var2); +Word64 W_msu_32_16 (Word64 L64_acc, Word32 L_var1, Word16 var2); +Word64 W_mult0_16_16 (Word16 var1, Word16 var2); +Word64 W_mac0_16_16 (Word64 L64_acc, Word16 var1, Word16 var2); +Word64 W_msu0_16_16 (Word64 L64_acc, Word16 var1, Word16 var2); +Word64 W_mult_16_16 (Word16 var1, Word16 var2); +Word64 W_mac_16_16 (Word64 L64_acc, Word16 var1, Word16 var2); +Word64 W_msu_16_16 (Word64 L64_acc, Word16 var1, Word16 var2); + +Word64 W_deposit32_l (Word32 L_var1); +Word64 W_deposit32_h (Word32 L_var1); + +Word32 W_sat_l (Word64 L64_var); +Word32 W_sat_m (Word64 L64_var); +Word32 W_shl_sat_l (Word64 L64_var, Word32 n); + +Word32 W_extract_l (Word64 L64_var1); +Word32 W_extract_h (Word64 L64_var1); + +Word32 W_round48_L (Word64 L64_var1); +Word16 W_round32_s (Word64 L64_var1); + +Word16 W_norm (Word64 L_var1); + + +Word64 W_add (Word64 L64_var1, Word64 L64_var2); +Word64 W_sub (Word64 L64_var1, Word64 L64_var2); +Word64 W_neg (Word64 L64_var1); +Word64 W_abs (Word64 L64_var1); +Word64 W_mult_32_32 (Word32 L_var1, Word32 L_var2); +Word64 W_mult0_32_32 (Word32 L_var1, Word32 L_var2); +UWord64 W_lshl (UWord64 L64_var1, Word16 var2); +UWord64 W_lshr (UWord64 L64_var1, Word16 var2); +Word32 W_round64_L (Word64 L64_var1) ; + +#endif /* #ifdef ENH_64_BIT_OPERATOR */ + +#endif /*_ENH64_H*/ + + +/* end of file */ + + diff --git a/basic_op/enhUL32.c b/basic_op/enhUL32.c new file mode 100644 index 0000000..9f82d04 --- /dev/null +++ b/basic_op/enhUL32.c @@ -0,0 +1,409 @@ +/* + ============================================================================ + File: ENHUL32.C v.1.0 - 01.July.2018 + ============================================================================ + + ENHANCED UNSIGNED 32-BIT ARITHMETIC OPERATORS + History: + v.0.5 - 21.March.2014 + + ============================================================================ +*/ + + /***************************************************************************** + * + * Enhanced Unsigned 32 bit operators : + * see complete list in .h file + * + *****************************************************************************/ + +/***************************************************************************** + * + * Include-Files + * + *****************************************************************************/ +#include +#include +#include "stl.h" +#include "enhUL32.h" + +#if (WMOPS) +extern BASIC_OP multiCounter[MAXCOUNTERS]; +extern int currCounter; +#endif /* if WMOPS */ + + +/***************************************************************************** + * + * Constants and Globals + * + *****************************************************************************/ + + +/***************************************************************************** + * + * Functions + * + *****************************************************************************/ +#ifdef ENH_U_32_BIT_OPERATOR + +/*___________________________________________________________________________ + | | + | Function Name : UL_deposit_l | + | | + | Purpose : | + | | + | Deposit the 16 bit var1 into the 16 LS bits of the 32 bit output. The | + | 16 MS bits of the output are not sign extended. | + |___________________________________________________________________________| +*/ + +UWord32 UL_deposit_l (UWord16 uvar) { + UWord32 UL_result; + UL_result = (UWord32) uvar; /* no sign extension*/ +#if (WMOPS) + multiCounter[currCounter].UL_deposit_l++; +#endif + return (UL_result); +} + +/*_____________________________________________________________________________ + | | + | Function Name : norm_ul | + | | + | Purpose : | + | | + | Produces the number of left shifts needed to normalize the 32 bit varia- | + | ble UL_var1 for positive values on the interval with minimum of | + | 0 and maximum of 0xffffffff, ; in order to normalize the | + | result, the following operation must be done : | + | | + | norm_UL_var1 = UL_lshl(UL_var1, norm_ul(UL_var1)). | + | | + | Complexity weight : 1 | + | | + | Inputs : | + | | + | UL_var1 | + | 32 bit long unsigned integer (UWord32) whose value falls in the | + | range : 0x0000 0000 <= var1 <= 0xffff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | | + | var_out | + | 16 bit short signed integer (Word16) whose value falls in the | + | range : 0x0000 0000 <= var_out <= 0x0000 001f. (0..31d) | + |_____________________________________________________________________________| +*/ +Word16 norm_ul (UWord32 UL_var1) { + Word16 var_out; + + if (UL_var1 == 0) { + var_out = 0; + } + else { + /* simply test shift up until highest bit is set */ + for (var_out = 0; UL_var1 < (UWord32) 0x80000000U; var_out++) { + UL_var1 <<= 1; + } + } + +#if (WMOPS) + multiCounter[currCounter].norm_ul++; +#endif + + return (var_out); +} + +/*___________________________________________________________________________ + | | + | Function Name : UL_addNs | + | | + | Purpose : | + | | + | 32 bits addition of the two unsigned 32 bits variables | + | (L_var1+L_var2) with overflow control, but without saturation | + | | + | Outputs : | + | | + | *wrap = 1 if wrap occured, otherwize 0 | + | | + | Return Value : | + | | + | UL_var3 = modulo(UL_var1+UL_var2,32) | + |___________________________________________________________________________| +*/ + +UWord32 UL_addNs (UWord32 UL_var1, UWord32 UL_var2, UWord16 * wrap) { + UWord32 UL_var3; + + /* STL Overflow flag is not updated */ + UL_var3 = UL_var1 + UL_var2; /* 32-bit wrap may occur, like in C */ + + if (((UWord64) UL_var1 + (UWord64) UL_var2) > 0xFFFFFFFFU) { + *wrap = 1; /* wrapped output */ + } + else { + *wrap = 0; + } + +#if WMOPS + multiCounter[currCounter].UL_addNs++; +#endif + + return UL_var3; +} + +/*___________________________________________________________________________ + | | + | Function Name : UL_subNs | + | | + | Purpose : | + | | + | 32 bits subtraction of the two unsigned 32 bits variables | + | (L_var1-L_var2) with overflow control, but without saturation | + | | + | Outputs : | + | | + | *sgn = 1 if wrap (to "negative" occured, otherwise 0) | + | | + | Return Value : | + | | + | UL_var3 = modulo(UL_var1-UL_var2,32) | + |___________________________________________________________________________| +*/ + +UWord32 UL_subNs (UWord32 UL_var1, UWord32 UL_var2, UWord16 * sgn) { + UWord32 UL_var3; + + UL_var3 = UL_var1 - UL_var2; /*wrap may occur, like in C */ + if (UL_var1 >= UL_var2) { + *sgn = 0; + } + else { + *sgn = 1; /* "negative", wrapped output */ + } + +#if WMOPS + multiCounter[currCounter].UL_subNs++; +#endif + return UL_var3; +} + +/*________________________________________________________________________________ + | | + | Function Name : Mpy_32_16_uu | + | | + | Purpose : | + | | + | Multiplies the 2 unsigned values UL_var1 and uvar2. | + | The operation is performed in fractional mode : | + | - UL_var1 is supposed to be in Q32 format. | + | - var2 is supposed to be in Q16 format. | + | - The result is produced in Q48 format : UL_varout_h points to the | + | 32 MSBits while varout_l points to the 16 LSBits. | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | UL_var1 32 bit long unsigned integer (UWord32) whose value falls in | + | the range : 0x0000 0000 <= L_var1 <= 0xffff ffff. | + | | + | var2 16 bit short unsigned integer (UWord16) whose value falls in | + | the range : 0x0000 <= var2 <= 0x0000 ffff. | + | | + | Outputs : | + | | + | *UL_varout_h 32 bit long unsigned integer (UWord32) whose value falls in | + | the range : 0x0000 0000 <= UL_varout_h <= 0xffff ffff. | + | | + | *varout_l 16 bit short unsigned integer (UWord16) whose value falls in | + | the range : 0x0000 0000 <= varout_l <= 0x0000 ffff. | + | | + | Return Value : | + | | + | none | + |________________________________________________________________________________| +*/ +void Mpy_32_16_uu (UWord32 UL_var1, UWord16 uvar2, UWord32 *UL_varout_h, UWord16 *varout_l) { + UWord64 UL64_var1; + + /* 4294967295 * 65535 < 281474976710655 */ + /* (uint64(2)^16-1 )*(uint64(2)^32-1) < (uint64(2)^(16+32)-1) */ + UL64_var1 = ((UWord64) UL_var1)*((UWord64) uvar2); + *varout_l = (UWord16) UL64_var1; + *UL_varout_h = (UWord32) (UL64_var1>>16); + +#if (WMOPS) + multiCounter[currCounter].Mpy_32_16_uu++; +#endif /* if WMOPS */ + + return; +} + +/*__________________________________________________________________________________ + | | + | Function Name : Mpy_32_32_uu | + | | + | Purpose : | + | | + | Multiplies the 2 unsigned values UL_var1 and UL_var2. | + | The operation is performed in fractional mode : | + | - UL_var1 and UL_var2 are supposed to be in Q32 format. | + | - The result is produced in Q64 format : UL_varout_h points to the | + | 32 MSBits while UL_varout_l points to the 32 LSBits. | + | | + | Complexity weight : 4 | + | | + | Inputs : | + | | + | UL_var1 32 bit long unsigned integer (UWord32) whose value falls in the | + | range : 0x0000 0000 <= L_var1 <= 0xffff ffff. | + | | + | UL_var2 32 bit long unsigned integer (UWord32) whose value falls in the | + | range : 0x0000 0000 <= L_var2 <= 0xffff ffff. | + | | + | Outputs : | + | | + | *UL_varout_h 32 bit long signed integer (Word32) whose value falls in | + | the range : 0x0000 0000 <= UL_varout_h <= 0xffff ffff. | + | | + | *UL_varout_l 32 bit short unsigned integer (UWord32) whose value falls in | + | the range : 0x0000 0000 <= UL_varout_l <= 0xffff ffff. | + | | + | Return Value : | + | | + | none | + |__________________________________________________________________________________| + */ +void Mpy_32_32_uu (UWord32 UL_var1, UWord32 UL_var2, UWord32 *UL_varout_h, UWord32 *UL_varout_l) { + UWord64 UL64_var1; + /* (uint64(2)^32-1 )*(uint64(2)^32-1) < (uint64(2)^(32+32)-1) */ + UL64_var1 = ((UWord64) UL_var1)*((UWord64) UL_var2); + *UL_varout_h = (UWord32)(UL64_var1>>32); + *UL_varout_l = (UWord32)(UL64_var1); + +#if (WMOPS) + multiCounter[currCounter].Mpy_32_32_uu++; +#endif /* if WMOPS */ + + return; +} + +/*_____________________________________________________________________________________ + | | + | Function Name : UL_Mpy_32_32 | + | | + | Purpose : | + | | + | Multiplies the 2 unsigned values UL_var1 and UL_var2 | + | and returns the lower 32 bits, without saturation control. | + | | + | - UL_var1 and UL_var2 are supposed to be in Q32 format. | + | - The result is produced in Q64 format, the 32 LSBits. | + | | + | operates like a regular 32-by-32 bit unsigned int multiplication in ANSI-C. | + | UWord32) = (unsigned int)*(unsigned int); | + | | + | | + | Complexity weight : 2 | + | | + | Inputs : | + | | + | UL_var1 32 bit long unsigned integer (UWord32) whose value falls in the | + | range : 0x0000 0000 <= UL_var1 <= 0xffff ffff. | + | | + | UL_var2 32 bit long unsigned integer (UWord32) whose value falls in the | + | range : 0x0000 0000 <= UL_var2 <= 0xffff ffff. | + | | + | Outputs : | + | | + | none | + | | + | Return Value : | + | *UL_varout_l 32 bit short unsigned integer (UWord32) whose value falls in | + | the range : 0x0000 0000 <= UL_varout_l <= 0xffff ffff. | + | | + |_____________________________________________________________________________________| +*/ +UWord32 UL_Mpy_32_32 (UWord32 UL_var1, UWord32 UL_var2) { + UWord32 UL_varout_l; + +#define MASK32 0xFFFFFFFFU + /* MASK32 may be needed in case Hardware is using larger than 32 bits for UWord32 type */ + UL_varout_l = (UL_var1&MASK32)*(UL_var2&MASK32); + UL_varout_l = UL_varout_l&MASK32; +#undef MASK32 + +#if (WMOPS) + multiCounter[currCounter].UL_Mpy_32_32++; +#endif /* if WMOPS */ + + return UL_varout_l; +} + + +#ifdef STL_TYPECASTS +/* (Reuse of existing signed STL "L" operators) with + typecasting to make the resulting "UL" code a lot cleaner and more readable. */ + +UWord32 UL_lshl( UWord32 UL_var1, Word16 var2) { + return( (UWord32)L_lshl( (Word32) UL_var1, var2)); +} + +UWord32 UL_lshr( UWord32 UL_var1, Word16 var2) { + return( (UWord32)L_lshr( (Word32) UL_var1, var2) ); +} + +UWord32 UL_and(UWord32 UL_var1, UWord32 UL_var2 ) +{ + return (UWord32) L_and((Word32)UL_var1,(Word32) UL_var2); +} + +UWord32 UL_or(UWord32 UL_var1, UWord32 UL_var2 ) +{ + return (UWord32) L_or((Word32)UL_var1,(Word32) UL_var2); +} + +UWord32 UL_xor(UWord32 UL_var1, UWord32 UL_var2 ) +{ + return (UWord32) L_xor((Word32)UL_var1,(Word32) UL_var2); +} + +UWord32 UL_deposit_h(UWord16 uvar1) +{ + return (UWord32) L_deposit_h((Word32)uvar1); +} + +UWord16 u_extract_h(UWord32 UL_var1) +{ + return (UWord16) extract_h((Word32)UL_var1); +} + +UWord16 u_extract_l(UWord32 UL_var1) +{ + return (UWord32)extract_l((Word32)UL_var1); +} + +/* enable convenient reuse of Non-saturating UL_subNs , UL_addNs while "D"iscarding the sgn/wrap output flags */ +UWord32 UL_subNsD(UWord32 UL_var1, UWord32 UL_var2 ) +{ + UWord16 dummy_sign; + return UL_subNs(UL_var1,UL_var2,&dummy_sign ); +} + +UWord32 UL_addNsD(UWord32 UL_var1, UWord32 UL_var2 ) +{ + UWord16 dummy_wrap; + return UL_addNs(UL_var1,UL_var2,&dummy_wrap ); +} +#endif + +#endif /* ENH_U_32_BIT_OPERATOR */ + +/* end of file */ diff --git a/basic_op/enhUL32.h b/basic_op/enhUL32.h new file mode 100644 index 0000000..a89b248 --- /dev/null +++ b/basic_op/enhUL32.h @@ -0,0 +1,76 @@ +/* + ============================================================================ + File: ENHUL32.H v.1.0 - 01.July.2018 + ============================================================================ + + + ============================================================================ +*/ + +#ifndef _ENHUL32_H +#define _ENHUL32_H + +/***************************************************************************** + * + * Constants and Globals + * + *****************************************************************************/ +#define STL_TYPECASTS /* logical shift and bitwise manipulation functions */ + /* algorithmically exact to existing signed L_lshr and L_lshr */ + +#include "stl.h" + +#ifndef UWord64 +#define UWord64 unsigned long long /* for local use inside UL_Mpy_32_* */ +#endif + +#if (WMOPS) +#include "count.h" +extern BASIC_OP multiCounter[MAXCOUNTERS]; /* existing signed counters are reused for unsigedn operators */ +extern int currCounter; +#endif /* if WMOPS */ + +/***************************************************************************** + * + * Prototypes for enhanced unsigned 32 bit arithmetic operators + * + *****************************************************************************/ +#ifdef ENH_U_32_BIT_OPERATOR +UWord32 UL_addNs (UWord32 a, UWord32 b, UWord16* wrap); +UWord32 UL_subNs (UWord32 a, UWord32 b, UWord16* sgn); + +UWord32 UL_Mpy_32_32 (UWord32 a, UWord32 b); +void Mpy_32_32_uu (UWord32 a, UWord32 b, UWord32 *c_h, UWord32 *c_l); /* does not saturate */ +void Mpy_32_16_uu (UWord32 a, UWord16 b, UWord32 *c_h, UWord16 *c_l); /* does not saturate */ + +Word16 norm_ul (UWord32 UL_var1); +UWord32 UL_deposit_l (UWord16); /* deposit low without sign extension */ +#endif /* ENH_U_32_BIT_OPERATOR */ + +/***************************************************************************** + * + * Inline Functions + * + *****************************************************************************/ + +#ifdef STL_TYPECASTS +/* (Reuse of existing signed STL "L" operators) with + typecasting to make the resulting "UL" code a lot cleaner and more readable. */ +UWord32 UL_lshl( UWord32 UL_var1, Word16 var2); +UWord32 UL_lshr( UWord32 UL_var1, Word16 var2); +UWord32 UL_and(UWord32 UL_var1, UWord32 UL_var2 ); +UWord32 UL_or(UWord32 UL_var1, UWord32 UL_var2 ); +UWord32 UL_xor(UWord32 UL_var1, UWord32 UL_var2 ); +UWord32 UL_deposit_h(UWord16 uvar1); +UWord16 u_extract_h(UWord32 UL_var1); +UWord16 u_extract_l(UWord32 UL_var1); + +/* enable convenient reuse of Non-saturating UL_subNs , UL_addNs + while "D"iscarding the sgn/wrap output flags */ +UWord32 UL_subNsD(UWord32 UL_var1, UWord32 UL_var2 ); +UWord32 UL_addNsD(UWord32 UL_var1, UWord32 UL_var2 ); +#endif + +#endif /*_ENHUL32_H*/ + +/* end of file */ diff --git a/basic_op/move.h b/basic_op/move.h new file mode 100644 index 0000000..8a02bd9 --- /dev/null +++ b/basic_op/move.h @@ -0,0 +1,95 @@ +/* + =========================================================================== + File: MOVE.H v.2.3 - 30.Nov.2009 + =========================================================================== + + ITU-T STL BASIC OPERATORS + + MOVE & MISC LEGACY OPERATORS + + History: + 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control + operators for the ITU-T Standard Tool Library as + described in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + TD 11 document and subsequent discussions on the + wp3audio@yahoogroups.com email reflector. + March 06 v2.1 Changed to improve portability. + + ============================================================================ +*/ + + +#ifndef _MOVE_H +#define _MOVE_H + + +#include "stl.h" + +#if (WMOPS) +extern BASIC_OP multiCounter[MAXCOUNTERS]; +extern int currCounter; +#endif /* ifdef WMOPS */ + + +static __inline void move16 (void) { +#if WMOPS + multiCounter[currCounter].move16++; +#endif /* ifdef WMOPS */ +} + + + + + + +static __inline void move32 (void) { +#if WMOPS + multiCounter[currCounter].move32++; +#endif /* ifdef WMOPS */ +} + + +#ifdef ENH_64_BIT_OPERATOR +static __inline void move64 (void) { +#if WMOPS + multiCounter[currCounter].move64++; +#endif /* if WMOPS */ +} +#endif /* #ifdef ENH_64_BIT_OPERATOR */ + + + + +static __inline void test (void) { +#if WMOPS + multiCounter[currCounter].Test++; +#endif /* ifdef WMOPS */ +} + + +static __inline void logic16 (void) { +#if WMOPS + multiCounter[currCounter].Logic16++; +#endif /* ifdef WMOPS */ +} + + +static __inline void logic32 (void) { +#if WMOPS + multiCounter[currCounter].Logic32++; +#endif /* ifdef WMOPS */ +} + + +/*-------- legacy ----------*/ +#define data_move () move16 () +#define L_data_move () move32 () +#define data_move_external () move16 () +#define compare_zero () test () +/*-------- end legacy ----------*/ + + +#endif /* _MOVE_H */ + + +/* end of file */ diff --git a/basic_op/patch.h b/basic_op/patch.h new file mode 100644 index 0000000..c843cb7 --- /dev/null +++ b/basic_op/patch.h @@ -0,0 +1,51 @@ +/* + =========================================================================== + File: PATCH.H v.2.3 - 30.Nov.2009 + =========================================================================== + + ITU-T STL BASIC OPERATORS + + OPERATOR NAME PATCHING + + History: + 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control + operators for the ITU-T Standard Tool Library as + described in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + TD 11 document and subsequent discussions on the + wp3audio@yahoogroups.com email reflector. + + ============================================================================ +*/ + + +#ifndef _PATCH_H +#define _PATCH_H + + +#if 1 +/***************************************************************************** + * start of Patch1 : + * It is enabled. + * + * This patch enables to keep compatibility with old ITU DSP operator names + * following naming conventions as proposed to ITU-T Standard Tool Library + * definition group in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + * TD 11 document. + * + *****************************************************************************/ +#define shift_r( var1, var2) shl_r( var1, var2) +#define L_shift_r( L_var1, var2) L_shl_r( L_var1, var2) + + +#endif /* end of Patch1 */ + + + + + + + + + + +#endif /* end of _PATCH_H */ diff --git a/basic_op/stl.h b/basic_op/stl.h new file mode 100644 index 0000000..0ba4c3f --- /dev/null +++ b/basic_op/stl.h @@ -0,0 +1,69 @@ +/* + =========================================================================== + File: STL.H v.2.3 - 30.Nov.2009 + =========================================================================== + + ITU-T STL BASIC OPERATORS + + MAIN HEADER FILE + + History: + 07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control + operators for the ITU-T Standard Tool Library as + described in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + TD 11 document and subsequent discussions on the + wp3audio@yahoogroups.com email reflector. + March 06 v2.1 Changed to improve portability. + + ============================================================================ +*/ + + +#ifndef _STL_H +#define _STL_H + + +#include /* for size_t */ + +#define ENH_U_32_BIT_OPERATOR +#define COMPLEX_OPERATOR +#define CONTROL_CODE_OPS +#define ENH_32_BIT_OPERATOR + +#include "patch.h" +/* both ALLOW_40bits and ALLOW_ENH_UL32 shall be enabled for the EVS codec. */ +#define ALLOW_40bits /* allow 32x16 and 32x32 multiplications */ +#define ALLOW_ENH_UL32 /* allow enhanced unsigned 32bit operators */ +#include "typedef.h" +#include "basop32.h" +#include "count.h" +#include "move.h" +#include "control.h" +#include "enh1632.h" +#include "oper_32b.h" +#include "math_op.h" +#include "log2.h" + +#include "enh40.h" + + +#ifdef ENH_64_BIT_OPERATOR +#include "enh64.h" +#endif + +#ifdef ENH_32_BIT_OPERATOR +#include "enh32.h" +#endif + +#ifdef COMPLEX_OPERATOR +#include "complex_basop.h" +#endif + +#ifdef ENH_U_32_BIT_OPERATOR +#include "enhUL32.h" +#endif + +#endif /* ifndef _STL_H */ + + +/* end of file */ diff --git a/basic_op/typedef.h b/basic_op/typedef.h new file mode 100644 index 0000000..cd031a3 --- /dev/null +++ b/basic_op/typedef.h @@ -0,0 +1,102 @@ +/* + =========================================================================== + File: TYPEDEF.H v.2.3 - 30.Nov.2009 + =========================================================================== + + ITU-T STL BASIC OPERATORS + + TYPE DEFINITION PROTOTYPES + + History: + 26.Jan.00 v1.0 Incorporated to the STL from updated G.723.1/G.729 + basic operator library (based on basic_op.h) + + 03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control + operators for the ITU-T Standard Tool Library as + described in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + TD 11 document and subsequent discussions on the + wp3audio@yahoogroups.com email reflector. + March 06 v2.1 Changed to improve portability. + + ============================================================================ +*/ + + +/*_____________________ + | | + | Basic types. | + |_____________________| +*/ + + +#ifndef _TYPEDEF_H +#define _TYPEDEF_H "$Id $" + +#define ORIGINAL_TYPEDEF_H /* Define to get "original" version of typedef.h (this file). */ +#undef ORIGINAL_TYPEDEF_H /* Undefine to get the "new" version of typedef.h (see typedefs.h). */ + + +#ifdef ORIGINAL_TYPEDEF_H +/* + * This is the original code from the file typedef.h + */ + +#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__ZTC__) +typedef signed char Word8; +typedef short Word16; +typedef long Word32; +typedef __int64 Word40; +typedef unsigned short UWord16; +typedef unsigned long UWord32; +typedef int Flag; + +#elif defined(__CYGWIN__) +typedef signed char Word8; +typedef short Word16; +typedef long Word32; +typedef long long Word40; +typedef unsigned short UWord16; +typedef unsigned long UWord32; +typedef int Flag; + +#elif defined(__sun) +typedef signed char Word8; +typedef short Word16; +typedef long Word32; +/*#error "The 40-bit operations have not been tested on __sun : need to define Word40"*/ +typedef long long Word40; +typedef unsigned short UWord16; +typedef unsigned long UWord32; +typedef int Flag; + +#elif defined(__unix__) || defined(__unix) || defined(__APPLE__) +typedef signed char Word8; +typedef short Word16; +typedef int Word32; +/*#error "The 40-bit operations have not been tested on unix : need to define Word40"*/ +typedef long long Word40; +typedef unsigned short UWord16; +typedef unsigned int UWord32; +typedef int Flag; +#endif + + +#else /* ifdef ORIGINAL_TYPEDEF_H */ /* not original typedef.h */ + + + + +/* + * Use (improved) type definition file typdefs.h and add a "Flag" type. + */ +#include "typedefs.h" +typedef int Flag; + + +#endif /* ifdef ORIGINAL_TYPEDEF_H */ + + +#endif /* ifndef _TYPEDEF_H */ + + +/* end of file */ diff --git a/basic_op/typedefs.h b/basic_op/typedefs.h new file mode 100644 index 0000000..c0e7645 --- /dev/null +++ b/basic_op/typedefs.h @@ -0,0 +1,218 @@ +/* + =========================================================================== + File: TYPEDEFS.H v.2.3 - 30.Nov.2009 + =========================================================================== + + ITU-T STL BASIC OPERATORS + + NEW TYPE DEFINITION PROTOTYPES + + History: + 03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control + operators for the ITU-T Standard Tool Library as + described in Geneva, 20-30 January 2004 WP 3/16 Q10/16 + TD 11 document and subsequent discussions on the + wp3audio@yahoogroups.com email reflector. + + Editor comment : + This file is not yet used or validated since + ORIGINAL_TYPEDEF_H compilation flag is defined in + typedef.h. This file is incorporated for future + reference / usage. + + ============================================================================ +*/ + + +/****************************************************************************** + * + * File : typedefs.h + * Description : Definition of platform independent data + * types and constants + * + * + * The following platform independent data types and corresponding + * preprocessor (#define) constants are defined: + * + * defined type meaning corresponding constants + * ---------------------------------------------------------- + * Char character (none) + * Bool boolean true, false + * Word8 8-bit signed minWord8, maxWord8 + * UWord8 8-bit unsigned minUWord8, maxUWord8 + * Word16 16-bit signed minWord16, maxWord16 + * UWord16 16-bit unsigned minUWord16, maxUWord16 + * Word32 32-bit signed minWord32, maxWord32 + * UWord32 32-bit unsigned minUWord32, maxUWord32 + * Float floating point minFloat, maxFloat + * + * + * The following compile switches are #defined: + * + * PLATFORM string indicating platform progam is compiled on + * possible values: "OSF", "PC", "SUN" + * + * OSF only defined if the current platform is an Alpha + * PC only defined if the current platform is a PC + * SUN only defined if the current platform is a Sun + * + * LSBFIRST is defined if the byte order on this platform is + * "least significant byte first" -> defined on DEC Alpha + * and PC, undefined on Sun + * + *****************************************************************************/ + + +#ifndef _TYPEDEFS_H +#define _TYPEDEFS_H "$Id $" + +/***************************************************************************** + * INCLUDE FILES + *****************************************************************************/ +#include +#include + +#define ENH_64_BIT_OPERATOR + +/***************************************************************************** + * DEFINITION OF CONSTANTS + *****************************************************************************/ +/* + ********* define char type + */ +typedef char Char; + +typedef unsigned short int UNS_Word16; /* 16 bit "register" (sw*) */ +#ifdef UNS_Word16 +#pragma message ("UNS_Word16 is defined but not officially part of STL2009@") +#endif + +/* + ********* define 8 bit signed/unsigned types & constants + */ +#if SCHAR_MAX == 127 +typedef signed char Word8; +#define minWord8 SCHAR_MIN +#define maxWord8 SCHAR_MAX + +typedef unsigned char UWord8; +#define minUWord8 0 +#define maxUWord8 UCHAR_MAX +#else +#error cannot find 8-bit type +#endif + + +/* + ********* define 16 bit signed/unsigned types & constants + */ +#if INT_MAX == 32767 +typedef int Word16; +#define minWord16 INT_MIN +#define maxWord16 INT_MAX +typedef unsigned int UWord16; +#define minUWord16 0 +#define maxUWord16 UINT_MAX +#elif SHRT_MAX == 32767 +typedef short Word16; +#define minWord16 SHRT_MIN +#define maxWord16 SHRT_MAX +typedef unsigned short UWord16; +#define minUWord16 0 +#define maxUWord16 USHRT_MAX +#else +#error cannot find 16-bit type +#endif + +/* Definition of Word64 */ +#ifdef ENH_64_BIT_OPERATOR +#define Word64 long long int +#endif /* #ifdef ENH_64_BIT_OPERATOR */ + +/* Definition of Word40 was missing 10/06/2013 */ +#define Word40 long long + +/* + ********* define 32 bit signed/unsigned types & constants + */ +#if INT_MAX == 2147483647 +typedef int Word32; +#define minWord32 INT_MIN +#define maxWord32 INT_MAX +typedef unsigned int UWord32; +#define minUWord32 0 +#define maxUWord32 UINT_MAX +#elif LONG_MAX == 2147483647 +typedef long Word32; +#define minWord32 LONG_MIN +#define maxWord32 LONG_MAX +typedef unsigned long UWord32; +#define minUWord32 0 +#define maxUWord32 ULONG_MAX +#else +#error cannot find 32-bit type +#endif + +/* + ********* define floating point type & constants + */ +/* use "if 0" below if Float should be double; + use "if 1" below if Float should be float + */ +#if 0 +typedef float Float; +#define maxFloat FLT_MAX +#define minFloat FLT_MIN +#else +typedef double Float; +#define maxFloat DBL_MAX +#define minFloat DBL_MIN +#endif + +/* + ********* define complex type + */ +typedef struct { + Float r; /* real part */ + Float i; /* imaginary part */ +} CPX; + +/* + ********* define boolean type + */ +typedef int Bool; +#define false 0 +#define true 1 + +/* + ********* Check current platform + */ +#if defined (__MSDOS__) +#define PC +#define PLATFORM "PC" +#define LSBFIRST +#elif defined (__osf__) +#define OSF +#define PLATFORM "OSF" +#define LSBFIRST +#elif defined (__sun__) || defined (__sun) +#define SUN +#define PLATFORM "SUN" +#undef LSBFIRST +#elif defined (linux) && defined (i386) +#define PC +#define PLATFORM "PC" +#define LSBFIRST +#else +/*#error "can't determine architecture; adapt typedefs.h to your platform"*/ +/* for MSVC 2008 10/06/2013 */ +#define PC +#define PLATFORM "PC" +#define LSBFIRST +#endif + + +#endif /* ifndef _TYPEDEFS_H */ + + +/* end of file */ diff --git a/lib_com/ACcontextMapping.c b/lib_com/ACcontextMapping.c new file mode 100644 index 0000000..154618f --- /dev/null +++ b/lib_com/ACcontextMapping.c @@ -0,0 +1,81 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include +#include "options.h" +#include "basop_util.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "stl.h" + +/* Returns: index of next coefficient */ +Word16 get_next_coeff_mapped( + Word16 ii[2], /* i/o: coefficient indexes */ + Word16 *pp, /* o : peak(1)/hole(0) indicator */ + Word16 *idx, /* o : index in unmapped domain */ + CONTEXT_HM_CONFIG *hm_cfg /* i : HM configuration */ +) +{ + Word16 p; + + p = s_and(sub(ii[1], hm_cfg->numPeakIndices), sub(hm_cfg->indexBuffer[ii[1]], hm_cfg->indexBuffer[ii[0]])); + if (p > 0) + { + p = 0; + move16(); + } + if (p < 0) + { + p = 1; + move16(); + } + *pp = p; + move16(); + *idx = ii[p]; + move16(); + ii[p] = add(ii[p], 1); + move16(); + return hm_cfg->indexBuffer[*idx]; +} + +/* Returns: index of next coefficient */ +Word16 get_next_coeff_unmapped( + Word16 ii[2], /* i/o: coefficient indexes */ + Word16 *pp, /* o : peak(1)/hole(0) indicator */ + Word16 *idx, /* o : index in unmapped domain */ + CONTEXT_HM_CONFIG *hm_cfg /* i : HM configuration */ +) +{ + (void)pp; + (void)hm_cfg; + + *idx = ii[0]; + move16(); + ii[0] = add(ii[0], 1); + move16(); + return *idx; +} + +Word16 update_mixed_context(Word16 ctx, Word16 a) +{ + Word32 t32; + Word16 t=0; /* initialize just to avoid compiler warning */ + + t32 = L_mac0(1-13, s_and(a, ~1), add(shr(a, 2), 1)); + if (t32 <= 0) + { + t = extract_l(t32); + } + a = shr(a, 3); + if (t32 > 0) + { + t = s_min(a, 2); + } + return add(shl(s_and(ctx, 0xf), 4), add(t, 13)); +} + diff --git a/lib_com/ari.c b/lib_com/ari.c new file mode 100644 index 0000000..edf6e47 --- /dev/null +++ b/lib_com/ari.c @@ -0,0 +1,57 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "assert.h" +#include "prot_fx.h" +#include "basop_mpy.h" +#include "cnst_fx.h" +#include "stl.h" + +/** + * \brief 31x16 Bit multiply (x*y) + * + * \param[i] xh high part, bit [30..15] + * \param[i] xl low part, 15 LSBits + * \param[i] y + * + * \return x*y + */ +Word32 L_multi31x16_X2(Word16 xh, Word16 xl, Word16 y) +{ + Word32 z; + + z = L_shl(L_mult0(xh,y),15); + z = L_mac0(z,xl,y); + + return z; +} + +/*--------------------------------------------------------------- + Ari 14 bits common routines + -------------------------------------------------------------*/ + +/** + * \brief Integer Multiply + * + * \param[i] r + * \param[i] c + * + * \return r*c + */ +Word32 mul_sbc_14bits(Word32 r, Word16 c) +{ + Word32 ret; + + + /* + temp = (((int32) r)*((int32) c))>>stat_bitsnew; + */ + assert(stat_bitsnew == 14); + ret = Mpy_32_16_1(L_shl(r,15-stat_bitsnew), c); + + /*assert( (((int) r)*((int) c))>>stat_bitsnew == ret);*/ + + return (ret); +} diff --git a/lib_com/ari_hm.c b/lib_com/ari_hm.c new file mode 100644 index 0000000..80f2d70 --- /dev/null +++ b/lib_com/ari_hm.c @@ -0,0 +1,292 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include +#include +#include "stl.h" +#include "cnst_fx.h" +#include "basop_util.h" +#include "rom_com_fx.h" +#include "prot_fx.h" + +void UnmapIndex( + Word16 PeriodicityIndex, + Word16 Bandwidth, + Word16 LtpPitchLag, + Word8 SmallerLags, + Word16 *FractionalResolution, + Word32 *Lag) +{ + Word16 LtpPitchIndex, Multiplier; + Word16 Lag16; + + test(); + IF ((LtpPitchLag > 0) && (s_and(PeriodicityIndex, kLtpHmFlag) != 0)) + { + LtpPitchIndex = shr(PeriodicityIndex, 9); + Multiplier = s_and(PeriodicityIndex, 0xff); + + assert(0 <= LtpPitchIndex && LtpPitchIndex <= 16); + assert(1 <= Multiplier && Multiplier <= (1 << NumRatioBits[Bandwidth][LtpPitchIndex])); + + *FractionalResolution = kLtpHmFractionalResolution; + move16(); + *Lag = L_shr(L_mult0(LtpPitchLag, Ratios[Bandwidth][LtpPitchIndex][Multiplier-1]), 8); + move32(); + } + ELSE + { + IF (LT_16(PeriodicityIndex, 16)) + { + *FractionalResolution = 3; + move16(); + Lag16 = add(PeriodicityIndex, GET_ADJ2(0, 6, 3)); + } + ELSE IF (LT_16(PeriodicityIndex, 80)) + { + *FractionalResolution = 4; + move16(); + Lag16 = add(PeriodicityIndex, GET_ADJ2(16, 8, 4)); + } + ELSE IF (LT_16(PeriodicityIndex, 208)) + { + *FractionalResolution = 3; + move16(); + Lag16 = add(PeriodicityIndex, GET_ADJ2(80, 12, 3)); + } + ELSE { + test(); + IF (LT_16(PeriodicityIndex, 224)||SmallerLags!=0) + { + *FractionalResolution = 1; + move16(); + Lag16 = add(PeriodicityIndex, GET_ADJ2(208, 28, 1)); + } + ELSE { + *FractionalResolution = 0; + move16(); + Lag16 = add(PeriodicityIndex, GET_ADJ2(224, 188, 0)); + } + } + *Lag = L_deposit_l(Lag16); + } +} + + +void ConfigureContextHm( + Word16 NumCoeffs, /* (I) Number of coefficients */ + Word16 TargetBits, /* (I) Target bit budget (excl. Done flag) */ + Word16 PeriodicityIndex, /* (I) Pitch related index */ + Word16 LtpPitchLag, /* (I) TCX-LTP pitch in F.D. */ + CONTEXT_HM_CONFIG *hm_cfg /* (O) Context-based harmonic model configuration */ +) +{ + Word8 Bandwidth, SmallerLags; + Word32 i, Limit, Lag; + Word16 j, Index, FractionalResolution; + Word16 *tmp; + + + Bandwidth = 0; + move16(); + if (GE_16(NumCoeffs, 256)) + { + Bandwidth = 1; + move16(); + } + + SmallerLags = 0; + move16(); + test(); + if ((LE_16(TargetBits, kSmallerLagsTargetBitsThreshold))||(Bandwidth==0)) + { + SmallerLags = 1; + move16(); + } + + UnmapIndex(PeriodicityIndex, + Bandwidth, + LtpPitchLag, + SmallerLags, + &FractionalResolution, &Lag); + + /* Set up and fill peakIndices */ + hm_cfg->peakIndices = hm_cfg->indexBuffer; + tmp = hm_cfg->peakIndices; + Limit = L_shl(L_deposit_l(sub(NumCoeffs, 1)), FractionalResolution); + IF (LT_32(Lag, Limit)) + { + FOR (i=Lag; inumPeakIndices = (Word16)(tmp - hm_cfg->indexBuffer); + + /* Set up and fill holeIndices */ + hm_cfg->holeIndices = hm_cfg->indexBuffer + hm_cfg->numPeakIndices; + tmp = hm_cfg->holeIndices; + Index = 0; + move16(); + IF (hm_cfg->numPeakIndices > 0) + { + FOR (j=0; jnumPeakIndices; j+=3) + { + FOR (; IndexpeakIndices[j]; ++Index) + { + *tmp++ = Index; + move16(); + } + Index = add(Index, 3); /* Skip the peak */ + } + } + IF (LT_16(Index, NumCoeffs)) + { + FOR (; IndexnumHoleIndices = (Word16)(tmp - hm_cfg->holeIndices); + *tmp++ = NumCoeffs; + move16(); /* Add extremal element signaling the end of the buffer */ + +} + +Word16 CountIndexBits( + Word16 Bandwidth, + Word16 PeriodicityIndex) +{ + Word16 result; + Word16 PeriodicityIndexS; + + result = 8; + move16(); + PeriodicityIndexS = shr(PeriodicityIndex, 9); + + if (s_and(PeriodicityIndex, kLtpHmFlag) != 0) + { + result = NumRatioBits[Bandwidth][PeriodicityIndexS]; + move16(); + } + + return result; +} + + + +int tcx_hm_render( + Word32 lag, /* i: pitch lag Q0 */ + Word16 fract_res, /* i: fractional resolution of the lag Q0 */ + Word16 p[] /* o: harmonic model Q13 */ +) +{ + Word16 k, tmp, height; + Word16 PeakDeviation; + Word32 f0, tmp32; + + /* Set up overall shape */ + f0 = L_shl(lag, sub(15, fract_res)); /* Q31 */ + + tmp32 = Mpy_32_16_1(f0, -26474); + tmp32 = L_shr_r(BASOP_Util_InvLog2(L_shl(tmp32, 7)), 2); + tmp32 = L_sub(603979776L, tmp32); + tmp32 = L_add(L_add(tmp32, tmp32), Mpy_32_16_1(tmp32, 26214)); + height = round_fx(tmp32); /* Q13 */ + + tmp32 = Mpy_32_16_1(f0, -18910); + tmp32 = L_shr_r(BASOP_Util_InvLog2(L_shl(tmp32, 7)), 2); + tmp32 = L_sub(1395864371L, tmp32); + PeakDeviation = round_fx(tmp32); /* Q14 */ + + IF( GT_16(13915,PeakDeviation)) + { + /* A bit error was encountered */ + return 1; + } + ELSE + { + tmp = div_s(13915, PeakDeviation); + tmp = mult_r(tmp, tmp); /* Q15 */ + } + + tmp = div_s(13915, PeakDeviation); + tmp = mult_r(tmp, tmp); /* Q15 */ + + /* Render the prototype peak */ + p[kTcxHmParabolaHalfWidth] = height; + move16(); + + FOR (k=1; k<=kTcxHmParabolaHalfWidth; ++k) + { + p[kTcxHmParabolaHalfWidth+k] = round_fx(Mpy_32_16_1(BASOP_Util_InvLog2(L_shl(L_mult0(i_mult2(negate(k),k), tmp),10)), height)); + } + /* Mirror */ + FOR (k=-kTcxHmParabolaHalfWidth; k<0; ++k) + { + p[kTcxHmParabolaHalfWidth+k] = p[kTcxHmParabolaHalfWidth-k]; + move16(); + } + + return 0; +} + +void tcx_hm_modify_envelope( + Word16 gain, /* i: HM gain Q11 */ + Word32 lag, /* i: pitch lag Q0 */ + Word16 fract_res, /* i: fractional resolution of the lag Q0 */ + Word16 p[], /* i: harmonic model Q13 */ + Word32 env[], /* i/o: envelope Q16 */ + Word16 L_frame /* i: number of spectral lines Q0 */ +) +{ + Word16 k, h, x, l1,l2, L_frame_m1, L_frame_for_loop; + Word16 inv_shape[2*kTcxHmParabolaHalfWidth+1]; + + IF ( gain == 0 ) + { + return; + } + + FOR (k=0; k<2*kTcxHmParabolaHalfWidth+1; ++k) + { + /* Q24 = Q11 * Q13; 512 = 1.0 in Q24 format */ + inv_shape[k] = div_s(512, add(512, mult_r(gain, p[k]))); + move16(); + } + + h = 1; + move16(); + k = extract_l(L_shr(lag,fract_res)); + + L_frame_m1 = sub(L_frame,1); + L_frame_for_loop = add(L_frame,kTcxHmParabolaHalfWidth - 1); + + WHILE ( LE_16(k,L_frame_for_loop)) + { + l1 = s_max(0, sub(k,kTcxHmParabolaHalfWidth)); + l2 = s_min(add(k,kTcxHmParabolaHalfWidth), L_frame_m1); + FOR (x=l1; x<=l2; ++x) + { + env[x] = Mpy_32_16_1(env[x], inv_shape[x-k+kTcxHmParabolaHalfWidth]); + move32(); + } + + h = add(h,1); + k = extract_l(L_shr(imult3216(lag,h),fract_res)); + } + +} + + diff --git a/lib_com/arith_coder.c b/lib_com/arith_coder.c new file mode 100644 index 0000000..6c4739d --- /dev/null +++ b/lib_com/arith_coder.c @@ -0,0 +1,471 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include + +#include "prot_fx.h" +#include "basop_util.h" +#include "options.h" +#include "cnst_fx.h" +#include "stl.h" + +/* Fixed point implementation of exp(negate()) */ +Word32 expfp( /* o: Q31 */ + Word16 x, /* i: mantissa Q-e */ + Word16 x_e) /* i: exponent Q0 */ +{ + Word16 xi, xf, tmp; + Word16 b0, b1, b2, b3; + Word32 y, L_tmp; + + + assert(x > 0); + + L_tmp = L_shl(L_deposit_h(x), x_e); + + /* split into integer and fractional parts */ + xi = round_fx(L_tmp); + xf = extract_l(L_tmp); + + BASOP_SATURATE_WARNING_OFF; + xf = negate(xf); + BASOP_SATURATE_WARNING_ON; + + /* Fractional part */ + /* y = 65536 + + xf + + ((xf*xf) / (2*65536)) + + ((((((xf*xf) / (2*65536))*xf) / 65536)*65536/3) / 65536) + + ((((((((xf*xf) / (2*65536))*xf) / 65536)*65536/3) / 65536)*xf) / (4*65536)); */ + y = L_mac0(65536, xf, 1); + tmp = shr(mult(xf, xf), 2); + y = L_mac0(y, tmp, 1); + tmp = shr(mult(shr(mult(tmp, xf), 1), 65536/3), 1); + y = L_mac0(y, tmp, 1); + tmp = shr(mult(tmp, xf), 3); + y = L_mac0(y, tmp, 1); + + /* Integer part */ + b0 = s_and(xi, 1); + b1 = s_and(xi, 2); + b2 = s_and(xi, 4); + b3 = s_and(xi, 8); + + if (b0 != 0) y = Mpy_32_16_1(y, 24109); /* exp(-1) in -1Q16 */ + if (b1 != 0) y = Mpy_32_16_1(y, 17739); /* exp(-2) in -2Q17 */ + if (b2 != 0) y = Mpy_32_16_1(y, 19205); /* exp(-4) in -5Q20 */ + if (b3 != 0) y = Mpy_32_16_1(y, 22513); /* exp(-8) in -11Q26 */ + + /* scaling: -1*b0 - 2*b1 -5*b2 -11*b3 */ + y = L_shr(y, add(add(xi, shr(xi, 2)), shr(b3, 3))); + + /* zero for xi >= 16 */ + if (shr(xi, 4) > 0) + { + y = L_deposit_l(0); + } + + + return L_shl(y, 15); +} + +/* Fixed point implementation of pow(), where base is fixed point (16/16) and exponent a small *odd* integer + * + * Returns: *pout1 = ( (base/65536)^(2*exp - 1) ) * 65536 + * *pout2 = ( (base/65536)^(2*exp + 1) ) * 65536 + * + * NOTE: This function must be in sync with ari_decode_14bits_pow() */ +void powfp_odd2(Word16 base, /* Q15 */ + Word16 exp, /* Q0 */ + Word16 *pout1, /* Q15 */ + Word16 *pout2) /* Q15 */ +{ + /* this version is in sync with ari_enc_14bits_pow() + * that is, we have to start multiplication from the largest power-of-two, in order to + * get the rounding errors to appear at the same places */ + Word16 pows[12]; /* powers of two exponents*/ + Word16 exp2; + Word16 out, out2; + Word16 k, h, maxk; + + assert(exp >= 0); + + out = base; + move16(); + out2 = 0x7FFF; + move16(); + IF (exp != 0) + { + exp2 = sub(exp, 1); + maxk = sub(15, norm_s(exp)); + assert(maxk < 12); + + pows[0] = base; + move16(); + FOR (k = 0; k < maxk; k++) + { + pows[k+1] = mult_r(pows[k], pows[k]); + move16(); + } + k = sub(k, 1); + h = shl(1, k); /* highest bit of exp2 */ + out2 = base; + move16(); + out = mult_r(out, pows[k+1]); /* we already know that "exp" has the highest bit set to one since we calculated .. */ + /* .. the effective length of "exp" earlier on, thus we omit the branch for out2 */ + if (s_and(exp2, h) != 0) + { + out2 = mult_r(out2, pows[k+1]); + } + + h = shr(h, 1); + FOR (k = sub(k, 1); k >= 0; k--) + { + if (s_and(exp, h) != 0) + { + out = mult_r(out, pows[k+1]); + } + + if (s_and(exp2, h) != 0) + { + out2 = mult_r(out2, pows[k+1]); + } + + h = shr(h, 1); + } + } + + *pout1 = out2; + move16(); + *pout2 = out; + move16(); + +} + +/*------------------------------------------------------------------------ + * Function: tcx_arith_scale_envelope + * + * For optimal performance of the arithmetic coder, the envelope shape must + * be scaled such that the expected bit-consumption of a signal that + * follows the scaled shape coincides with the target bitrate. + * This function calculates a first-guess scaling and then uses the bi-section + * search to find the optimal scaling. + * + * We assume that lines follow the Laplacian distribution, whereby the expected + * bit-consumption would be log2(2*e*s[k]), where s[k] is the envelope value + * for the line in question. However, this theoretical formula assumes that + * all lines are encoded with magnitude+sign. Since the sign is unnecessary + * for 0-values, that estimate of bit-consumption is biased when s[k] is small. + * Analytical solution of the expectation for small s[k] is difficult, whereby + * we use the approximation log2(2*e*s[k] + 0.15 + 0.035 / s[k]) which is accurate + * on the range 0.08 to 1.0. + * + * NOTE: This function must be bit-exact on all platforms such that encoder + * and decoder remain synchronized. + *-------------------------------------------------------------------------*/ +void tcx_arith_scale_envelope( + Word16 L_spec_core, /* i: number of lines to scale Q0 */ + Word16 L_frame, /* i: number of lines Q0 */ + Word32 env[], /* i: unscaled envelope Q16 */ + Word16 target_bits, /* i: number of available bits Q0 */ + Word16 low_complexity, /* i: low-complexity flag Q0 */ + Word16 s_env[], /* o: scaled envelope Q15-e */ + Word16 *s_env_e /* o: scaled envelope exponent Q0 */ +) +{ + Word32 ienv[N_MAX_ARI]; + Word16 scale, iscale, iscale_e, a_e, b, b_e; + Word16 lob, hib, adjust; + Word16 k, iter, max_iter, lob_bits, hib_bits; + Word16 statesi, bits; + Word32 mean, a, s, L_tmp; + Word16 mean_e, tmp, tmp2; + + + + lob_bits = 0; + move16(); + hib_bits = 0; + move16(); + + /* Boosting to account for expected spectrum truncation (kMax) */ + /* target_bits = (int)(target_bits * (1.2f - 0.00045f * target_bits + 0.00000025f * target_bits * target_bits)); */ + L_tmp = L_shr(Mpy_32_16_1(L_mult0(target_bits, target_bits), 17180), 6); /* Q15; 17180 -> 0.00000025f (Q36) */ + L_tmp = L_sub(L_tmp, L_shr(L_mult0(target_bits, 30199), 11)); /* Q15; 30199 -> 0.00045f (Q26) */ + L_tmp = L_add(L_tmp, 39322); /* Q15; 39322 -> 1.2f (Q15) */ + L_tmp = Mpy_32_16_1(L_tmp, target_bits); /* Q0 */ + assert(L_tmp < 32768); + target_bits = extract_l(L_tmp); + + /* Calculate inverse envelope and find initial scale guess based on mean */ + mean = L_deposit_l(0); + FOR (k = 0; k < L_frame; k++) + { + /* ienv[k] = 1.0f / env[k]; + mean += ienv[k]; */ + + tmp = norm_l(env[k]); + tmp2 = sub(15, tmp); + tmp = Inv16(round_fx(L_shl(env[k], tmp)), &tmp2); + ienv[k] = L_shl(L_deposit_h(tmp), sub(tmp2, 15)); /* Q16 */ move32(); + mean = L_add(mean, ienv[k]); + } + tmp = norm_s(L_frame); + tmp = shl(div_s(8192, shl(L_frame, tmp)), sub(tmp, 7)); + mean = L_shr(Mpy_32_16_1(mean, tmp), 6); /* Q16 */ + + /* Rate dependent compensation to get closer to the target on average */ + /* mean = (float)pow(mean, (float)L_frame / (float)target_bits * 0.357f); */ + tmp = BASOP_Util_Divide1616_Scale(L_frame, target_bits, &tmp2); + tmp = mult_r(tmp, 11698/*0.357f Q15*/); + mean = BASOP_Util_fPow(mean, 15, L_deposit_h(tmp), tmp2, &mean_e); + + /* Find first-guess scaling coefficient "scale" such that if "mean" is the + * mean of the envelope, then the mean bit-consumption is approximately + * + * log2(2*e*mean*scale + 0.15 + 0.035/(mean*scale)) * L_frame = target_bits + */ + /* a = 2*2.71828183f*mean*mean; */ + tmp = round_fx(mean); + a = L_mult(mult_r(tmp, 22268/*2.71828183f Q13*/), tmp); + a_e = add(shl(mean_e, 1), 3); + + /* b = (0.15f - (float)pow(2.0f, target_bits/(float)L_frame)) * mean; */ + tmp = BASOP_Util_Divide1616_Scale(target_bits, L_frame, &tmp2); + tmp = round_fx(BASOP_util_Pow2(L_deposit_h(tmp), tmp2, &tmp2)); + b_e = BASOP_Util_Add_MantExp(4915/*0.15f Q15*/, 0, negate(tmp), tmp2, &b); + b = mult_r(b, round_fx(mean)); + b_e = add(b_e, mean_e); + + /* scale = (-b + (float)sqrt(b*b - 4.0f*a*0.035f)) / (2.0f * a); */ + tmp = round_fx(BASOP_Util_Add_Mant32Exp(L_mult(b, b), shl(b_e, 1), Mpy_32_16_1(a, -4588/*-4.0f*0.035f Q15*/), a_e, &tmp2)); + + IF( tmp <= 0 ) + { + tmp = 0; + set16_fx(s_env, 0, L_frame); + } + ELSE + { + tmp = Sqrt16(tmp, &tmp2); + } + + tmp2 = BASOP_Util_Add_MantExp(negate(b), b_e, tmp, tmp2, &scale); + scale = BASOP_Util_Divide1616_Scale(scale, round_fx(a), &tmp); + scale = shl(scale, sub(sub(add(tmp, tmp2), a_e), 1)); /* Q15 */ + + /* iscale = 1.0f / scale; */ + iscale_e = 0; + move16(); + iscale = Inv16(s_max(1, scale), &iscale_e); + + lob = 0; + move16(); + hib = 0; + move16(); + + max_iter = 2; + move16(); + if(low_complexity) + { + max_iter = 1; + move16(); + } + + FOR (iter = 0; iter < max_iter; iter++) + { + statesi = 0x7FFF; + move16(); + bits = 0; + move16(); + + FOR (k = 0; k < L_frame; k++) + { + s = Mpy_32_16_1(ienv[k], scale); /* Q16 */ + + IF (LE_32(s, 5243l/*0.08f Q16*/)) + { + /* If s = 0.08, the expected bit-consumption is log2(1.0224). Below 0.08, the bit-consumption + estimate function becomes inaccurate, so use log2(1.0224) for all values below 0.08. */ + /* round(state * 1.0224 * 32768) */ + statesi = mult_r(statesi, 16751/*1.0224 Q14*/); + tmp = norm_s(statesi); + statesi = shl(statesi, tmp); + bits = add(bits, sub(1, tmp)); + } + ELSE IF (LE_32(s, 16711680l/*255.0 Q16*/)) + { + /* a = 5.436564f * s + 0.15f + 0.035f * env[k] * iscale; */ + L_tmp = L_shl(Mpy_32_16_1(s, 22268/*5.436564f Q12*/), 3); + L_tmp = L_add(L_tmp, 9830l/*0.15f Q16*/); + L_tmp = L_add(L_tmp, L_shl(Mpy_32_16_1(env[k], mult_r(1147/*0.035f Q15*/, iscale)), iscale_e)); + + tmp = norm_l(L_tmp); + statesi = mult_r(statesi, round_fx(L_shl(L_tmp, tmp))); + bits = add(bits, sub(15, tmp)); + + tmp = norm_s(statesi); + statesi = shl(statesi, tmp); + bits = sub(bits, tmp); + } + ELSE + { + /* for large envelope values, s > 255, bit consumption is approx log2(2*e*s) + * further, we use round(log2(x)) = floor(log2(x)+0.5) = floor(log2(x*sqrt(2))) */ + /* a = 5.436564f * s; */ + L_tmp = Mpy_32_16_1(s, 31492/*5.436564f * 1.4142f Q12*/); /* Q13 */ + bits = add(bits, sub(17, norm_l(L_tmp))); + } + } + + IF (LE_16(bits, target_bits)) /* Bits leftover => scale is too small */ + { + lob = scale; + move16(); + lob_bits = bits; + move16(); + + IF (hib > 0) /* Bisection search */ + { + adjust = div_s(sub(hib_bits, target_bits), sub(hib_bits, lob_bits)); + scale = add(mult_r(sub(lob, hib), adjust), hib); + } + ELSE /* Initial scale adaptation */ + { + /* adjust = 1.05f * target_bits / (float)bits; + scale *= adjust; */ + adjust = mult_r(17203/*1.05f Q14*/, target_bits); + adjust = BASOP_Util_Divide1616_Scale(adjust, bits, &tmp); + scale = shl(mult_r(scale, adjust), add(1, tmp)); + } + } + ELSE /* Ran out of bits => scale is too large */ + { + hib = scale; + move16(); + hib_bits = bits; + move16(); + + IF (lob > 0) /* Bisection search */ + { + adjust = div_s(sub(hib_bits, target_bits), sub(hib_bits, lob_bits)); + scale = add(mult_r(sub(lob, hib), adjust), hib); + } + ELSE { /* Initial scale adaptation */ + test(); + IF( target_bits <= 0 || bits <= 0 ) /* safety check in case of bit errors */ + { + adjust = 0; + move16(); + set16_fx( s_env, 0, L_frame ); + } + ELSE + { + adjust = div_s(mult_r(31130/*0.95f Q15*/, target_bits), bits); + } + scale = mult_r(scale, adjust); + } + } + iscale_e = 0; + move16(); + + IF( scale == 0 ) /* safety check in case of bit errors */ + { + iscale = 0; + move16(); + set16_fx( s_env, 0, L_frame ); + } + ELSE + { + iscale = Inv16(scale, &iscale_e); + } + } + L_frame = L_spec_core; + move16(); + + tmp = getScaleFactor32(env, L_frame); + *s_env_e = sub(add(15, iscale_e), tmp); + move16(); + BASOP_SATURATE_WARNING_OFF; + a = L_shl(1265000, sub(15, *s_env_e)); + BASOP_SATURATE_WARNING_ON; + + FOR (k = 0; k < L_frame; k++) + { + L_tmp = Mpy_32_16_1(L_shl(env[k], tmp), iscale); + L_tmp = L_min(L_tmp, a); + s_env[k] = round_fx(L_tmp); + } + +} + +/*------------------------------------------------------------------------ + * Function: tcx_arith_render_envelope + * + * Calculate the envelope of the spectrum based on the LPC shape. The + * envelope is used in a perceptual domain, whereby the LPC shape has to + * be multiplied by the perceptual model. + * Operations that are performed on the spectrum, which change the magnitude + * expectation of lines, such as low-frequency emphasis, are included in the + * envelope shape. + * NOTE: This function must be bit-exact on all platforms such that encoder + * and decoder remain synchronized. + *-------------------------------------------------------------------------*/ +void tcx_arith_render_envelope( + const Word16 A_ind[], /* i: LPC coefficients of signal envelope */ + Word16 L_frame, /* i: number of spectral lines */ + Word16 L_spec, + Word16 preemph_fac, /* i: pre-emphasis factor */ + Word16 gamma_w, /* i: A_ind -> weighted envelope factor */ + Word16 gamma_uw, /* i: A_ind -> non-weighted envelope factor */ + Word32 env[] /* o: shaped signal envelope */ +) +{ + Word16 k; + Word16 tmpA[M+2]; + Word16 signal_env[FDNS_NPTS], signal_env_e[FDNS_NPTS]; + Word16 gainlpc[FDNS_NPTS], gainlpc_e[FDNS_NPTS]; + + + + /* Compute perceptual LPC envelope, transform it into freq.-domain gains */ + weight_a_fx( A_ind, tmpA, gamma_w, M ); + lpc2mdct( tmpA, M, NULL, NULL, gainlpc, gainlpc_e ); + + /* Add pre-emphasis tilt to LPC envelope, transform LPC into MDCT gains */ + E_LPC_a_weight_inv(A_ind, signal_env, gamma_uw, M); + E_LPC_a_add_tilt(signal_env, tmpA, preemph_fac, M); + lpc2mdct(tmpA, M+1, signal_env, signal_env_e, NULL, NULL); + + /* Compute weighted signal envelope in perceptual domain */ + FOR (k = 0; k < FDNS_NPTS; k++) + { + signal_env[k] = mult_r(signal_env[k], gainlpc[k]); + move16(); + signal_env_e[k] = add(signal_env_e[k], gainlpc_e[k]); + move16(); + } + + /* Adaptive low frequency emphasis */ + set32_fx(env, 0x10000, L_frame); + + AdaptLowFreqDeemph(env, 15, + 1, + gainlpc, gainlpc_e, + L_frame, NULL); + + /* Scale from FDNS_NPTS to L_frame and multiply LFE gains */ + mdct_noiseShaping_interp(env, L_frame, signal_env, signal_env_e); + + FOR (k=L_frame; k +#include + +#include "stl.h" + +#define DOT12_SUBDIV_LD 2 /* log2(number of dot product sub divisions) */ + +#define HP20_COEF_SCALE 2 +#define INV_BANDS10 3277 /* 1/10 in Q15 */ +#define INV_BANDS9 3641 /* 1/9 in Q15 */ + +extern const Word32 SqrtTable[32]; +extern const Word16 SqrtDiffTable[32]; + +extern const Word32 ISqrtTable[32]; +extern const Word16 ISqrtDiffTable[32]; + +extern const Word32 InvTable[32]; +extern const Word16 InvDiffTable[32]; + + +Word32 BASOP_Util_Log2(Word32 x) +{ + Word32 exp; + Word16 exp_e; + Word16 nIn; + Word16 accuSqr; + Word32 accuRes; + + + + assert(x >= 0); + + if (x == 0) + { + + return ((Word32)MIN_32); + } + + /* normalize input, calculate integer part */ + exp_e = norm_l(x); + x = L_shl(x,exp_e); + exp = L_deposit_l(exp_e); + + /* calculate (1-normalized_input) */ + nIn = extract_h(L_sub(MAX_32,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[0]); /* nIn^i * coeff[0] */ + accuSqr = mult(nIn,nIn); /* nIn^2, nIn^3 .... */ + + /* iteration 2 */ + 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[2]); /* nIn^i * coeff[2] */ + accuSqr = mult(accuSqr,nIn); /* nIn^2, nIn^3 .... */ + + /* iteration 4 */ + 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[4]); /* nIn^i * coeff[4] */ + accuSqr = mult(accuSqr,nIn); /* nIn^2, nIn^3 .... */ + + /* iteration 6 */ + 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[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); + + accuRes = L_shr(accuRes,LD_DATA_SCALE-1); /* fractional part/LD_DATA_SCALE */ + exp = L_shl(exp,(31-LD_DATA_SCALE)); /* integer part/LD_DATA_SCALE */ + accuRes = L_sub(accuRes,exp); /* result = integer part + fractional part */ + + + return (accuRes); +} + +Word32 BASOP_Util_InvLog2(Word32 x) +{ + Word16 frac; + Word16 exp; + Word32 retVal; + UWord32 index3; + UWord32 index2; + UWord32 index1; + UWord32 lookup3f; + UWord32 lookup12; + UWord32 lookup; + + + + if ( x < -1040187392l/*-31.0/64.0 Q31*/ ) + { + + return 0; + } + test(); + if ( (GE_32(x,1040187392l/*31.0/64.0 Q31*/))||(x==0)) + { + + return 0x7FFFFFFF; + } + + frac = extract_l(L_and(x,0x3FF)); + + index3 = L_and(L_shr(x,10),0x1F); + index2 = L_and(L_shr(x,15),0x1F); + index1 = L_and(L_shr(x,20),0x1F); + + exp = extract_l(L_shr(x,25)); + if ( x > 0 ) + { + exp = sub(31,exp); + } + if ( x < 0 ) + { + exp = negate(exp); + } + + lookup3f = L_add(exp2x_tab_long[index3],L_shr(Mpy_32_16_1(0x0016302F,frac),1)); + lookup12 = Mpy_32_32(exp2_tab_long[index1],exp2w_tab_long[index2]); + lookup = Mpy_32_32(lookup12, lookup3f); + + retVal = L_shr(lookup,sub(exp,3)); + + + return retVal; +} + + +Word16 BASOP_Util_Add_MantExp /*!< Exponent of result */ +(Word16 a_m, /*!< Mantissa of 1st operand a */ + Word16 a_e, /*!< Exponent of 1st operand a */ + Word16 b_m, /*!< Mantissa of 2nd operand b */ + Word16 b_e, /*!< Exponent of 2nd operand b */ + Word16 *ptrSum_m) /*!< Mantissa of result */ +{ + Word32 L_lm, L_hm; + Word16 shift; + + + + /* Compare exponents: the difference is limited to +/- 15 + The Word16 mantissa of the operand with higher exponent is moved into the low + part of a Word32 and shifted left by the exponent difference. Then, the + unshifted mantissa of the operand with the lower exponent is added to the lower + 16 bits. The addition result is normalized and the upper Word16 of the result represents + the mantissa to return. The returned exponent takes into account all shift operations + including the final 16-bit extraction. + Note: The resulting mantissa may be inaccurate in the case, where the mantissa of the operand + with higher exponent is not really left-aligned, while the mantissa of the operand with + lower exponent is so. If in such a case, the difference in exponents is more than 15, + an inaccuracy is introduced. + Example: + A: a_e = 20, a_m = 0x0001 + B: b_e = 0, b_m = 0x4000 + correct: A+B=1*2^20+1*2^14=0x0010.0000+0x0000.4000=0x0010.4000=0x4100*2^6 + previously: A+B=1*2^20+1*2^14=0x0001+0x0000=0x0001*2^20 + this version: A+B=1*2^20+1*2^14=0x0000.8000+0x0000.4000=0x6000*2^6 + */ + + shift = sub(a_e, b_e); + if (shift >= 0) + shift = s_min( 15,shift); + + if (shift < 0) + shift = s_max(-15,shift); + a_e = s_max(a_e,b_e); + L_hm = L_deposit_l(a_m); /* mantissa belonging to higher exponent */ + L_lm = L_deposit_l(a_m); /* mantissa belonging to lower exponent */ + if (shift >= 0) + L_lm = L_deposit_l(b_m); + if (shift < 0) + L_hm = L_deposit_l(b_m); + + if (shift > 0) + shift = negate(shift); + + L_hm = L_shr(L_hm,shift); /* shift left due to negative shift parameter */ + a_e = add(a_e, shift); + L_hm = L_add(L_hm, L_lm); + shift = norm_l(L_hm); + L_hm = L_shl(L_hm,shift); + *ptrSum_m = extract_h(L_hm); + move16(); + + a_e = sub(a_e,shift); + if (L_hm) + a_e = add(a_e,16); + return (a_e); +} + + +void BASOP_Util_Divide_MantExp (Word16 a_m, /*!< Mantissa of dividend a */ + Word16 a_e, /*!< Exponent of dividend a */ + Word16 b_m, /*!< Mantissa of divisor b */ + Word16 b_e, /*!< Exponent of divisor b */ + Word16 *ptrResult_m, /*!< Mantissa of quotient a/b */ + Word16 *ptrResult_e /*!< Exponent of quotient a/b */ + ) +{ + Word16 index, frac; + Word16 preShift, postShift; + Word16 m; + Word32 m32; + + + + assert(b_m != 0); + + /* normalize b */ + preShift = norm_s(b_m); + m = shl(b_m, preShift); + + /* make b positive */ + BASOP_SATURATE_WARNING_OFF; + if (m < 0) m = negate(m); + BASOP_SATURATE_WARNING_ON; + + /* get table index (upper 6 bits minus 16) */ + /* index = (m >> 9) - 32; */ + index = mac_r(-32768 - (32 << 16), m, 1 << 6); + + /* get fractional part for interpolation (lower 9 bits) */ + frac = shl(s_and(m, 0x1FF), 1); /* Q10 */ + + /* interpolate 1/b */ + m = msu_r(InvTable[index], InvDiffTable[index], frac); + + /* restore sign */ + if (b_m < 0) m = negate(m); + + /* multiply with a */ + m32 = L_mult(a_m, m); + + /* normalize result */ + postShift = norm_l(m32); + m = round_fx(L_shl(m32, postShift)); + + /* exponent */ + *ptrResult_e = sub(add(add(a_e, sub(1, b_e)), preShift), postShift); + move16(); + + *ptrResult_m = m; + move16(); + +} + + +/* local function for Sqrt16 and Sqrt16norm */ +static Word16 Sqrt16_common(Word16 m, + Word16 e) +{ + Word16 index, frac; + + assert((m >= 0x4000) || (m == 0)); + + /* get table index (upper 6 bits minus 32) */ + /* index = (m >> 9) - 32; */ + index = mac_r(-32768 - (32 << 16), m, 1 << 6); + + /* get fractional part for interpolation (lower 9 bits) */ + frac = s_and(m, 0x1FF); /* Q9 */ + + /* interpolate */ + if (m != 0) + { + BASOP_SATURATE_WARNING_OFF; + m = mac_r(SqrtTable[index], SqrtDiffTable[index], frac); + BASOP_SATURATE_WARNING_ON; + } + + /* handle odd exponents */ + if (s_and(e, 1) != 0) m = mult_r(m, 0x5a82); + + return m; +} + +/* local function for Sqrt32 and Sqrt32norm */ +static Word32 Sqrt32_common(Word32 m, + Word16 e) +{ + Word16 m16, index, frac; + + assert((m >= 0x40000000) || (m == 0)); + + m16 = round_fx(m); + + /* get table index (upper 6 bits minus 32) */ + /* index = (m16 >> 9) - 32; */ + index = mac_r(-32768 - (32 << 16), m16, 1 << 6); + + /* get fractional part for interpolation (lower 9 bits) */ + frac = s_and(m16, 0x1FF); /* Q9 */ + + /* interpolate */ + if (m != 0) + { + BASOP_SATURATE_WARNING_OFF; + m = L_mac(SqrtTable[index], SqrtDiffTable[index], frac); + BASOP_SATURATE_WARNING_ON; + } + + /* handle odd exponents */ + if (s_and(e, 1) != 0) m = Mpy_32_16_1(m, 0x5a82); + + return m; +} + +/* local function for ISqrt16 and ISqrt16norm */ +static Word16 ISqrt16_common(Word16 m, + Word16 e) +{ + Word16 index, frac; + + assert(m >= 0x4000); + + /* get table index (upper 6 bits minus 32) */ + /* index = (m >> 9) - 32; */ + index = mac_r(-32768 - (32 << 16), m, 1 << 6); + + /* get fractional part for interpolation (lower 9 bits) */ + frac = s_and(m, 0x1FF); /* Q9 */ + + /* interpolate */ + m = msu_r(ISqrtTable[index], ISqrtDiffTable[index], frac); + + /* handle even exponents */ + if (s_and(e, 1) == 0) m = mult_r(m, 0x5a82); + + return m; +} + +/* local function for ISqrt32 and ISqrt32norm */ +static Word32 ISqrt32_common(Word32 m, + Word16 e) +{ + Word16 m16, index, frac; + + assert(m >= 0x40000000); + + m16 = round_fx(m); + + /* get table index (upper 6 bits minus 32) */ + /* index = (m16 >> 25) - 32; */ + index = mac_r(-32768 - (32 << 16), m16, 1 << 6); + + /* get fractional part for interpolation (lower 9 bits) */ + frac = s_and(m16, 0x1FF); /* Q9 */ + + /* interpolate */ + m = L_msu(ISqrtTable[index], ISqrtDiffTable[index], frac); + + /* handle even exponents */ + if (s_and(e, 1) == 0) m = Mpy_32_16_1(m, 0x5a82); + + return m; +} + + +Word16 Sqrt16( /*!< output mantissa */ + Word16 mantissa, /*!< input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +) +{ + Word16 preShift, e; + + assert(mantissa >= 0); + + /* normalize */ + preShift = norm_s(mantissa); + + e = sub(*exponent, preShift); + mantissa = shl(mantissa, preShift); + + /* calc mantissa */ + mantissa = Sqrt16_common(mantissa, e); + + /* e = (e + 1) >> 1 */ + *exponent = mult_r(e, 1 << 14); + move16(); + + return mantissa; +} + +Word16 Sqrt16norm( /*!< output mantissa */ + Word16 mantissa, /*!< normalized input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +) +{ + + assert((mantissa >= 0x4000) || (mantissa == 0)); + + /* calc mantissa */ + mantissa = Sqrt16_common(mantissa, *exponent); + + /* e = (e + 1) >> 1 */ + *exponent = mult_r(*exponent, 1 << 14); + move16(); + + return mantissa; +} + + +Word16 ISqrt16( /*!< output mantissa */ + Word16 mantissa, /*!< input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +) +{ + Word16 preShift, e; + + assert(mantissa > 0); + + /* normalize */ + preShift = norm_s(mantissa); + + e = sub(*exponent, preShift); + mantissa = shl(mantissa, preShift); + + /* calc mantissa */ + mantissa = ISqrt16_common(mantissa, e); + + /* e = (2 - e) >> 1 */ + *exponent = msu_r(1L << 15, e, 1 << 14); + move16(); + + return mantissa; +} + + +Word32 Sqrt32( /*!< output mantissa */ + Word32 mantissa, /*!< input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +) +{ + Word16 preShift, e; + + assert(mantissa >= 0); + + /* normalize */ + preShift = norm_l(mantissa); + + e = sub(*exponent, preShift); + mantissa = L_shl(mantissa, preShift); + + /* calc mantissa */ + mantissa = Sqrt32_common(mantissa, e); + + /* e = (e + 1) >> 1 */ + *exponent = mult_r(e, 1 << 14); + move16(); + + return mantissa; +} + + +Word32 ISqrt32( /*!< output mantissa */ + Word32 mantissa, /*!< input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +) +{ + Word16 preShift, e; + + assert(mantissa > 0); + + /* normalize */ + preShift = norm_l(mantissa); + + e = sub(*exponent, preShift); + mantissa = L_shl(mantissa, preShift); + + /* calc mantissa */ + mantissa = ISqrt32_common(mantissa, e); + + /* e = (2 - e) >> 1 */ + *exponent = msu_r(1L << 15, e, 1 << 14); + move16(); + + return mantissa; +} + +Word32 ISqrt32norm( /*!< output mantissa */ + Word32 mantissa, /*!< normalized input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +) +{ + + assert(mantissa >= 0x40000000); + + /* calc mantissa */ + mantissa = ISqrt32_common(mantissa, *exponent); + + /* e = (2 - e) >> 1 */ + *exponent = msu_r(1L << 15, *exponent, 1 << 14); + move16(); + + return mantissa; +} + + +Word16 Inv16( /*!< output mantissa */ + Word16 mantissa, /*!< input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +) +{ + Word16 index, frac; + Word16 preShift; + Word16 m, e; + + + + assert(mantissa != 0); + + /* absolute */ + BASOP_SATURATE_WARNING_OFF; + m = abs_s(mantissa); + BASOP_SATURATE_WARNING_ON; + + /* normalize */ + preShift = norm_s(m); + + e = sub(*exponent, preShift); + m = shl(m, preShift); + + /* get table index (upper 6 bits minus 32) */ + /* index = (m >> 9) - 32; */ + index = mac_r(-32768 - (32 << 16), m, 1 << 6); + + /* get fractional part for interpolation (lower 9 bits) */ + frac = shl(s_and(m, 0x1FF), 1); /* Q10 */ + + /* interpolate */ + m = msu_r(InvTable[index], InvDiffTable[index], frac); + + /* restore sign */ + if (mantissa < 0) m = negate(m); + + /* e = 1 - e */ + *exponent = sub(1, e); + move16(); + + return m; +} + + +void BASOP_Util_Sqrt_InvSqrt_MantExp (Word16 mantissa, /*!< mantissa */ + Word16 exponent, /*!< expoinent */ + Word16 *sqrt_mant, /*!< Pointer to sqrt mantissa */ + Word16 *sqrt_exp, /*!< Pointer to sqrt exponent */ + Word16 *isqrt_mant, /*!< Pointer to 1/sqrt mantissa */ + Word16 *isqrt_exp /*!< Pointer to 1/sqrt exponent */ + ) +{ + Word16 index, frac; + Word16 preShift; + Word16 m, mi, e_odd; + + + + assert(mantissa > 0); + + /* normalize */ + preShift = norm_s(mantissa); + + exponent = sub(exponent, preShift); + mantissa = shl(mantissa, preShift); + + /* get table index (upper 6 bits minus 32) */ + /* index = (m >> 9) - 32; */ + index = mac_r(-32768 - (32 << 16), mantissa, 1 << 6); + + /* get fractional part for interpolation (lower 9 bits) */ + frac = s_and(mantissa, 0x1FF); /* Q9 */ + + /* interpolate */ + BASOP_SATURATE_WARNING_OFF; + m = mac_r(SqrtTable[index], SqrtDiffTable[index], frac); + mi = msu_r(ISqrtTable[index], ISqrtDiffTable[index], frac); + BASOP_SATURATE_WARNING_ON; + + /* handle even/odd exponents */ + e_odd = s_and(exponent, 1); + if (e_odd != 0) m = mult_r(m, 0x5a82); + if (e_odd == 0) mi = mult_r(mi, 0x5a82); + + /* e = (e + 1) >> 1 */ + *sqrt_exp = mult_r(exponent, 1 << 14); + move16(); + + /* e = (2 - e) >> 1 */ + *isqrt_exp = msu_r(1L << 15, exponent, 1 << 14); + move16(); + + /* Write result */ + *sqrt_mant = m; + move16(); + *isqrt_mant = mi; + move16(); + +} + +/********************************************************************/ +/*! + \brief Calculates the scalefactor needed to normalize input array + + The scalefactor needed to normalize the Word16 input array is returned
+ If the input array contains only '0', a scalefactor 0 is returned
+ Scaling factor is determined wrt a normalized target x: 16384 <= x <= 32767 for positive x
+ and -32768 <= x <= -16384 for negative x +*/ + +Word16 getScaleFactor16( /* o: measured headroom in range [0..15], 0 if all x[i] == 0 */ + const Word16 *x, /* i: array containing 16-bit data */ + const Word16 len_x) /* i: length of the array to scan */ +{ + Word16 i, i_min, i_max; + Word16 x_min, x_max; + + + + x_max = 0; + move16(); + x_min = 0; + move16(); + FOR (i = 0; i < len_x; i++) + { + if (x[i] >= 0) + x_max = s_max(x_max,x[i]); + if (x[i] < 0) + x_min = s_min(x_min,x[i]); + } + + i_max = 0x10; + move16(); + i_min = 0x10; + move16(); + + if (x_max != 0) + i_max = norm_s(x_max); + + if (x_min != 0) + i_min = norm_s(x_min); + + i = s_and(s_min(i_max, i_min),0xF); + + + return i; +} + + +/********************************************************************/ +/*! + \brief Calculates the scalefactor needed to normalize input array + + The scalefactor needed to normalize the Word32 input array is returned
+ If the input array contains only '0', a scalefactor 0 is returned
+ Scaling factor is determined wrt a normalized target x: 1073741824 <= x <= 2147483647 for positive x
+ and -2147483648 <= x <= -1073741824 for negative x +*/ + +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 */ +{ + Word16 i, i_min, i_max; + Word32 x_min, x_max; + + + + x_max = 0; move32(); + x_min = 0; move32(); + FOR (i = 0; i < len_x; i++) + { + if (x[i] >= 0) + x_max = L_max(x_max,x[i]); + if (x[i] < 0) + x_min = L_min(x_min,x[i]); + } + + i_max = 0x20; + move16(); + i_min = 0x20; + move16(); + + if (x_max != 0) + i_max = norm_l(x_max); + + if (x_min != 0) + i_min = norm_l(x_min); + + i = s_and(s_min(i_max, i_min),0x1F); + + + return i; +} + +Word16 normalize16(Word16 mantissa, Word16 *pexponent) +{ + Word16 tmp; + + tmp = norm_s(mantissa); + mantissa = shl(mantissa, tmp); + move16(); + *pexponent = sub(*pexponent, tmp); + + + return mantissa; +} +Word16 divide3216(Word32 x, Word16 y) +{ + Word16 z; + + + z = 0; + move16(); + if (0 == y) + { + return 0x7fff; + } + + IF (x != 0) + { + Word16 den, sign; + Word32 num; + num = L_abs(x); + den = abs_s(y); + + sign = s_and(s_xor(extract_h(x),y),-32768 /* 0x8000 */); + + z = div_l(num,den); + if (0 != sign) + { + z = negate(z); + } + } + + + return z; +} + +Word16 divide1616(Word16 x, Word16 y) +{ + Word16 z, num, den, sign; + + + num = abs_s(x); + den = abs_s(y); + + sign = s_and(s_xor(x,y),-32768 /* 0x8000 */); + + move16(); + z = 0x7fff; + if ( LT_16(num, den)) + z = div_s(num,den); + + if (0 != sign) + { + z = negate(z); + } + + + return z; +} + +Word16 divide3232(Word32 L_num, Word32 L_denom) +{ + Word16 z; + Word32 sign; + + + sign = L_and(L_xor(L_num,L_denom),0x80000000); + + L_num = L_abs(L_num); + L_denom = L_abs(L_denom); + + /* limit the range of denominator to Word16 */ + z = s_min(norm_l(L_num),norm_l(L_denom)); + L_num = L_shl(L_num,z); + L_denom = L_shl(L_denom,z); + + /* round_fx instead of extract_h improves spectral distortion in E_UTIL_lev_dur (schur version). */ + z = div_l(L_num,round_fx(L_denom)); + if (0 != sign) + { + z = negate(z); + } + + + return z; +} + +Word16 BASOP_Util_Divide3232_uu_1616_Scale(Word32 x, Word32 y, Word16 *s) +{ + Word16 z; + Word16 sx; + Word16 sy; + Word16 x16; + Word16 y16; + + + + assert(x >= 0); + assert(y > 0); + + if ( x == 0 ) + { + *s = 0; + move16(); + + + return (0); + } + + sx = norm_l(x); + sy = norm_l(y); + + x16 = extract_h(L_shl(x,sx)); + y16 = extract_h(L_shl(y,sy)); + + if(GT_16(x16,y16)) + { + sx = sub(sx,1); + } + + if(LT_16(y16,x16)) + { + x16 = mult_r(x16,0x4000); + } + + + z = div_s(x16,y16); + move16(); + *s = sub(sy,sx); + + + return (z); +} + +Word16 BASOP_Util_Divide3232_Scale(Word32 x, Word32 y, Word16 *s) +{ + Word16 z; + Word16 sy; + + + + sy = norm_l(y); + if (sy > 0) + { + sy = sub(sy,1); + } + y = L_shl(y,sy); + + z = BASOP_Util_Divide3216_Scale(x, extract_h(y), s); + move16(); + *s = add(*s,sy); + + + return (z); +} + +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 */ +{ + Word16 z; + Word16 sx; + Word16 sy; + Word16 sign; + + + + /*assert (x > (Word32)0); + assert (y >= (Word16)0);*/ + + /* check, if numerator equals zero, return zero then */ + IF ( x == (Word32)0 ) + { + move16(); + *s = 0; + + + return ((Word16)0); + } + + sign = s_xor(extract_h(x),y); /* just to exor the sign bits */ + BASOP_SATURATE_WARNING_OFF + x = L_abs(x); + y = abs_s(y); + BASOP_SATURATE_WARNING_ON + sx = sub(norm_l(x),1); + x = L_shl(x,sx); + sy = norm_s(y); + y = shl(y,sy); + *s = sub(sy,sx); + move16(); + + z = div_s(round_fx(x),y); + + if ( sign < 0 ) /* if sign bits differ, negate the result */ + { + z = negate(z); + } + + + return z; +} + +Word16 BASOP_Util_Divide1616_Scale(Word16 x, Word16 y, Word16 *s) +{ + Word16 z; + Word16 sx; + Word16 sy; + Word16 sign; + + + + /* assert (x >= (Word16)0); */ + assert (y != (Word16)0); + + sign = 0; + move16(); + + IF ( x < 0 ) + { + x = negate(x); + sign = s_xor(sign,1); + } + + IF ( y < 0 ) + { + y = negate(y); + sign= s_xor(sign,1); + } + + IF ( x == (Word16)0 ) + { + move16(); + *s = 0; + + + return ((Word16)0); + } + + sx = norm_s(x); + x = shl(x,sx); + x = shr(x,1); + move16(); + *s = sub(1,sx); + + sy = norm_s(y); + y = shl(y,sy); + move16(); + *s = add(*s,sy); + + z = div_s(x,y); + + if ( sign != 0 ) + { + z = negate(z); + } + + + return z; +} + +void copyWord8(const Word8 *src, Word8 *dst, const Word32 n) +{ + Word32 i; + + + FOR (i=0; i= 0) + { + /* Yes */ + temp = temp2; + move16(); + } + return temp; +} +Word16 findIndexOfMinWord32(Word32 *x, const Word16 len) +{ + Word16 i, indx; + + + indx = 0; + move16(); + FOR (i = 1; i < len; i++) + { + if (LT_32(x[i],x[indx])) + { + indx = i; + move16(); + } + } + + + return indx; +} + + +Word16 imult1616(Word16 x, Word16 y) +{ + assert((int)x * (int)y < 32768 && (int)x * (int)y >= -32768); + return extract_l(L_mult0(x, y)); +} + +Word32 imult3216(Word32 x, Word16 y) +{ + Word32 mh; + UWord16 ml; + + Mpy_32_16_ss(x, y, &mh, &ml); + + mh = L_shl(mh, 15); + ml = lshr(ml, 1); + + return L_or(mh, L_deposit_l(ml)); +} + + +Word16 idiv1616U(Word16 x, Word16 y) +{ + Word16 sx, sy; + + /* make y > x to meet the requirements for div_s parameters */ + sx = norm_s(x); + sy = norm_s(y); + x = shl(x, sx); + y = shl(y, sy); + + if (x >= y) + { + x = shr(x,1); + sx = sub(sx,1); + } + + /* divide and shift */ + y = shr(div_s(x, y), sub(15, sub(sy,sx))); + + return y; +} + + +Word16 idiv1616(Word16 x, Word16 y) +{ + Word16 s, num, den, sign; + + + num = abs_s(x); + den = abs_s(y); + + sign = s_and(s_xor(x,y),-32768 /* 0x8000 */); + + /* make num > den */ + s = add(sub(norm_s(den), norm_s(num)), 1); + s = s_max(s, 0); + + den = shl(den, s); + + /* divide and shift */ + y = shr(div_s(num, den), sub(15, s)); + + if (0 != sign) + { + y = negate(y); + } + + + return y; +} + +Word32 norm_llQ31( /* o : normalized result Q31 */ + Word32 L_c, /* i : upper bits of accu Q-1 */ + Word32 L_sum, /* i : lower bits of accu, unsigned Q31 */ + Word16 * exp /* o : exponent of result in [-32,31] Q0 */ +) +{ + Word16 i; + Word32 L_tmp; + + /* Move MSBit of L_sum into L_c */ + Carry = 0; + L_tmp = L_add_c(L_sum, L_sum); /* L_tmp = L_sum << 1 */ + L_c = L_add_c(L_c,L_c); + L_add(0,0); + test(); + IF ((L_c != (Word32) 0L) && (L_c != (Word32) 0xFFFFFFFFL)) + { + i = norm_l(L_c); + L_c = L_shl(L_c,i); + i = sub(31,i); /* positive exponent */ + L_sum = L_lshr(L_tmp, 1); /* L_sum with MSBit=0 */ + L_sum = L_lshr(L_sum, i); + L_sum = L_add(L_c,L_sum); + } + ELSE + { + i = -32; + move16(); /* default exponent, if total sum=0 */ + IF (L_sum) + { + i = norm_l(L_sum); + L_sum = L_shl(L_sum,i); + i = negate(i); /* negative or zero exponent */ + } + } + *exp = i; + move16(); + return L_sum; +} + +Word32 w_norm_llQ31( Word64 L_sum, Word16 * exp ); +Word32 w_norm_llQ31( /* o : normalized result Q31 */ + Word64 L_sum, /* i : upper and lower bits of accu, unsigned Q31 */ + Word16 * exp /* o : exponent of result in [-32,31] Q0 */ +) +{ + Word32 L_tmp; + Word16 exp_val; + Word64 L64_inp64 = L_sum; move64(); + + L64_inp64 = W_shl( L64_inp64, 1); + exp_val = W_norm( L64_inp64 ); + L64_inp64 = W_shl( L64_inp64, exp_val ); + exp_val = sub( 31, exp_val ); + if(EQ_64(L_sum , 0)) + { + exp_val = -32; move16(); + } + *exp = exp_val; move16(); + + L_tmp = W_extract_h( L64_inp64 ); + return L_tmp; +} + +Word32 Dot_product16HQ( /* o : normalized result Q31 */ + const Word32 L_off, /* i : initial sum value Qn */ + const Word16 x[], /* i : x vector Qn */ + const Word16 y[], /* i : y vector Qn */ + const Word16 lg, /* i : vector length, range [0..7FFF] Q0 */ + Word16 * exp /* o : exponent of result in [-32,31] Q0 */ +) +{ + Word16 i; + Word32 L_sum; + Word64 L_sum64; + + L_sum64 = W_deposit32_l( L_off ); + + FOR (i=0; i < lg; i++) + { + L_sum64 = W_mac_16_16(L_sum64,x[i], y[i]); + } + + L_sum = w_norm_llQ31(L_sum64,exp); + return L_sum; +} + +Word32 Norm32Norm(const Word32 *x, const Word16 headroom, const Word16 length, Word16 *result_e) +{ + Word32 L_tmp, L_tmp2; + Word16 i, shift, tmp; + + move16(); + shift = headroom; + + L_tmp = L_deposit_l(0); + + FOR (i=0; i= 0) shift = sub(shift,1); + if (L_tmp2 >= 0) L_tmp = L_shr(L_tmp, 2); + + tmp = round_fx(L_shl(x[i], shift)); + L_tmp = L_mac0(L_tmp, tmp, tmp); /* exponent = (1-shift*2) , Q(30+shift*2) */ + } + + move16(); + *result_e = sub(1, shl(shift,1)); + + return L_tmp; +} + +Word32 Dot_productSq16HQ( /* o : normalized result Q31 */ + const Word32 L_off, /* i : initial sum value Qn */ + const Word16 x[], /* i : x vector Qn */ + const Word16 lg, /* i : vector length, range [0..7FFF] Q0 */ + Word16 * exp /* o : exponent of result in [-32,31] Q0 */ +) +{ + Word16 i; + Word32 L_sum; + Word64 L_sum64; + + L_sum64 = W_deposit32_l( L_off ); + + FOR (i=0; i < lg; i++) + { + L_sum64 = W_mac_16_16(L_sum64, x[i], x[i]); + } + L_sum = w_norm_llQ31(L_sum64,exp); + + return L_sum; +} + +Word32 dotp_s_fx(const Word16 *x, const Word16 *y, const Word16 n, Word16 s) +{ + Word16 i; + Word16 n2; + Word32 L_tmp; + Word32 L_sum; + + + L_sum = 0; + move32(); + + n2 = shr(n,1); + + s = sub(s,1); + + FOR (i=0; i < n2; i++) + { + L_tmp = L_mult0(x[2*i], y[2*i]); + L_tmp = L_mac0(L_tmp, x[2*i+1], y[2*i+1]); + L_sum = L_add(L_sum, L_shr(L_tmp, s)); + } + + IF ( s_and(n,1) ) + { + L_tmp = L_mult0(x[n-1], y[n-1]); + L_sum = L_add(L_sum, L_shr(L_tmp, s)); + } + + + return L_sum; +} + +Word32 BASOP_util_Pow2( + const Word32 exp_m, const Word16 exp_e, + Word16 *result_e +) +{ + static const Word16 pow2Coeff[8] = + { + 22713/*0.693147180559945309417232121458177 Q15*/, /* ln(2)^1 /1! */ + 7872/*0.240226506959100712333551263163332 Q15*/, /* ln(2)^2 /2! */ + 1819/*0.0555041086648215799531422637686218 Q15*/, /* ln(2)^3 /3! */ + 315/*0.00961812910762847716197907157365887 Q15*/, /* ln(2)^4 /4! */ + 44/*0.00133335581464284434234122219879962 Q15*/, /* ln(2)^5 /5! */ + 5/*1.54035303933816099544370973327423e-4 Q15*/, /* ln(2)^6 /6! */ + 0/*1.52527338040598402800254390120096e-5 Q15*/, /* ln(2)^7 /7! */ + 0/*1.32154867901443094884037582282884e-6 Q15*/ /* ln(2)^8 /8! */ + }; + + Word32 frac_part, tmp_frac, result_m; + Word16 int_part; + + int_part = 0; /* to avoid compilation warnings */ + frac_part = 0; /* to avoid compilation warnings */ + + IF (exp_e > 0) + { + /* "+ 1" compensates L_shr(,1) of the polynomial evaluation at the loop end. */ + + int_part = add(1,extract_l(L_shr(exp_m, sub(31, exp_e)))); + frac_part = L_lshl(exp_m, exp_e); + frac_part = L_and(0x7FFFFFFF, frac_part); + } + if (exp_e <= 0) + frac_part = L_shl(exp_m, exp_e); + if (exp_e <= 0) + { + int_part = 1; + move16(); + } + + /* Best accuracy is around 0, so try to get there with the fractional part. */ + IF( (tmp_frac = L_sub(frac_part,1073741824l/*0.5 Q31*/)) >= 0) + { + int_part = add(int_part, 1); + frac_part = L_sub(tmp_frac,1073741824l/*0.5 Q31*/); + } + ELSE IF( (tmp_frac = L_add(frac_part,1073741824l/*0.5 Q31*/)) < 0) + { + int_part = sub(int_part, 1); + frac_part = L_add(tmp_frac,1073741824l/*0.5 Q31*/); + } + + /* Evaluate taylor polynomial which approximates 2^x */ + { + Word32 p; + Word16 i; + + + /* First taylor series coefficient a_0 = 1.0, scaled by 0.5 due to L_shr(,1). */ + result_m = L_add(1073741824l/*1.0/2.0 Q31*/,L_shr(Mpy_32_16_1(frac_part, pow2Coeff[0]), 1)); + p = Mpy_32_32(frac_part, frac_part); + FOR (i = 1; i < 7; i++) + { + /* next taylor series term: a_i * x^i, x=0 */ + result_m = L_add(result_m, L_shr(Mpy_32_16_1(p, pow2Coeff[i]), 1)); + p = Mpy_32_32(p, frac_part); + } + result_m = L_add(result_m, L_shr(Mpy_32_16_1(p, pow2Coeff[i]), 1)); + } + *result_e = int_part; + move16(); + return result_m; +} +Word16 findIndexOfMaxWord32(Word32 *x, const Word16 len) +{ + Word16 i, indx; + + + indx = 0; + move16(); + FOR (i = 1; i < len; i++) + { + if (GT_32(x[i],x[indx])) + { + indx = i; + move16(); + } + } + + + return indx; +} + + +Word16 getNormReciprocalWord16(Word16 x) +{ + + assert(x < (Word16)(sizeof(BASOP_util_normReciprocal)/sizeof(BASOP_util_normReciprocal[0]))); + + return extract_h(BASOP_util_normReciprocal[x]); +} +Word16 getNormReciprocalWord16Scale(Word16 x, Word16 s) +{ + + assert(x < (Word16)(sizeof(BASOP_util_normReciprocal)/sizeof(BASOP_util_normReciprocal[0]))); + + return round_fx(L_shl(BASOP_util_normReciprocal[x],s)); +} + +Word32 BASOP_Util_fPow( + Word32 base_m, Word16 base_e, + Word32 exp_m, Word16 exp_e, + Word16 *result_e +) +{ + + Word16 ans_lg2_e, base_lg2_e; + Word32 base_lg2_m, ans_lg2_m, result_m; + Word16 shift; + + + test(); + IF ((base_m == 0) && (exp_m != 0)) + { + *result_e = 0; + move16(); + return 0; + } + /* Calc log2 of base */ + shift = norm_l(base_m); + base_m = L_shl(base_m, shift); + base_e = sub(base_e, shift); + base_lg2_m = BASOP_Util_Log2(base_m); + + /* shift: max left shift such that neither base_e or base_lg2_m saturate. */ + shift = sub(s_min(norm_s(base_e), WORD16_BITS-1-LD_DATA_SCALE), 1); + /* Compensate shift into exponent of result. */ + base_lg2_e = sub(WORD16_BITS-1, shift); + base_lg2_m = L_add(L_shr(base_lg2_m, sub(WORD16_BITS-1-LD_DATA_SCALE, shift)), L_deposit_h(shl(base_e, shift))); + + /* Prepare exp */ + shift = norm_l(exp_m); + exp_m = L_shl(exp_m, shift); + exp_e = sub(exp_e, shift); + + /* Calc base pow exp */ + ans_lg2_m = Mpy_32_32(base_lg2_m, exp_m); + ans_lg2_e = add(exp_e, base_lg2_e); + + /* Calc antilog */ + result_m = BASOP_util_Pow2(ans_lg2_m, ans_lg2_e, result_e); + + return result_m; +} + + +/*___________________________________________________________________________ + | | + | Function Name : Dot_product12_offs() | + | | + | Compute scalar product of using accumulator. | + | The parameter 'L_off' is added to the accumulation result. | + | The result is normalized (in Q31) with exponent (0..30). | + | Notes: | + | o data in x[],y[] must provide enough headroom for accumulation | + | o L_off must correspond in format with product of x,y | + | Example: 0.01f for Q9 x Q9: 0x0000147B in Q19 | + | means: L_off = FL2WORD32_SCALE(0.01,31-19) | + |---------------------------------------------------------------------------| + | Algorithm: | + | | + | dot_product = L_off + sum(x[i]*y[i]) i=0..N-1 | + |___________________________________________________________________________| +*/ +Word32 Dot_product12_offs( /* (o) Q31: normalized result (1 < val <= -1) */ + const Word16 x[], /* (i) 12bits: x vector */ + const Word16 y[], /* (i) 12bits: y vector */ + const Word16 lg, /* (i) : vector length in range [1..256] */ + Word16 * exp, /* (o) : exponent of result (0..+30) */ + Word32 L_off /* (i) initial summation offset / 2 */ +) +{ + Word16 i, sft; + Word32 L_sum; + + Word64 L_sum64; + + L_sum64 = W_deposit32_l( L_off ); + FOR (i = 0; i < lg; i++) + { + L_sum64 = W_mac0_16_16(L_sum64, x[i], y[i]); + } + L_sum = W_sat_l( L_sum64 ); + + /* Normalize acc in Q31 */ + + sft = norm_l(L_sum); + if (exp != NULL) + { + L_sum = L_shl(L_sum, sft); + } + + /* exponent = 0..30, when L_sum != 0 */ + if (L_sum != 0) + { + sft = sub(31,sft); + } + + if (exp != NULL) + { + *exp = sft; + move16(); + } + + return L_sum; +} + +Word32 Dot_product15_offs( /* (o) Q31: normalized result (1 < val <= -1) */ + const Word16 x[], /* (i) 15bits: x vector */ + const Word16 y[], /* (i) 15bits: y vector */ + const Word16 lg, /* (i) : vector length in range [1..256] */ + Word16 *exp, /* (o) : exponent of result (0..+30) */ + Word32 L_off /* (i) initial summation offset */ +) +{ + Word16 i, sft, fac, ld; + Word32 L_sum; + + ld = sub(14,norm_s(lg)); + fac = shr(-32768,ld); + L_sum = L_shr(L_off,ld); + + FOR (i = 0; i < lg; i++) + { + L_sum = L_add(L_sum, Mpy_32_16_1(L_msu(0, y[i],fac),x[i])); + } + + /* Avoid returning 0 */ + if (L_sum == 0) + { + L_sum = L_add(L_sum, 1); + } + + /* Normalize acc in Q31 */ + sft = norm_l(L_sum); + L_sum = L_shl(L_sum, sft); + + /* exponent = 0..30, when L_sum != 0 */ + if (L_sum != 0) + { + sft = add(ld, sub(30,sft)); + } + + *exp = sft; + move16(); + + return L_sum; +} + + +/* + + precondition: headroom in Y is sufficient for n accumulations +*/ +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 */ + Word16 b_e, /*!< i: Exponent of 2nd operand b */ + Word16 *ptr_e) /*!< o: exponent of result */ +{ + Word32 L_tmp; + Word16 shift; + + + + /* Compare exponents: the difference is limited to +/- 30 + The Word32 mantissa of the operand with lower exponent is shifted right by the exponent difference. + Then, the unshifted mantissa of the operand with the higher exponent is added. The addition result + is normalized and the result represents the mantissa to return. The returned exponent takes into + account all shift operations. + */ + + if (!a_m) + { + a_e = b_e; + move16(); + } + + if (!b_m) + { + b_e = a_e; + move16(); + } + + shift = sub(a_e, b_e); + shift = s_max(-31,shift); + shift = s_min(31, shift); + if (shift < 0) + { + /* exponent of b is greater than exponent of a, shr a_m */ + a_m = L_shl(a_m,shift); + } + if (shift > 0) + { + /* exponent of a is greater than exponent of b */ + b_m = L_shr(b_m,shift); + } + a_e = add(s_max(a_e,b_e),1); + L_tmp = L_add(L_shr(a_m,1),L_shr(b_m,1)); + shift = norm_l(L_tmp); + if (shift) + L_tmp = L_shl(L_tmp,shift); + if (L_tmp == 0) + { + a_e = 0; + move16(); + } + if (L_tmp != 0) + a_e = sub(a_e,shift); + *ptr_e = a_e; + + return (L_tmp); +} + + +Word16 BASOP_Util_Cmp_Mant32Exp /*!< o: flag: result of comparison */ +/* 0, if a == b */ +/* 1, if a > b */ +/* -1, if a < b */ +(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 */ + Word16 b_e) /*!< i: Exponent of 2nd operand b */ + +{ + Word32 diff_m; + Word16 diff_e, shift, result; + + + + /* + This function compares two input parameters, both represented by a 32-bit mantissa and a 16-bit exponent. + If both values are identical, 0 is returned. + If a is greater b, 1 is returned. + If a is less than b, -1 is returned. + */ + + /* Check, if both mantissa and exponents are identical, when normalized: return 0 */ + shift = norm_l(a_m); + if (shift) + a_m = L_shl(a_m, shift); + if (shift) + a_e = sub(a_e, shift); + + shift = norm_l(b_m); + if (shift) + b_m = L_shl(b_m, shift); + if (shift) + b_e = sub(b_e, shift); + + /* align exponent, if any mantissa is zero */ + if (!a_m) + { + a_e = b_e; + move16(); + } + if (!b_m) + { + b_e = a_e; + move16(); + } + + BASOP_SATURATE_WARNING_OFF + diff_m = L_sub(a_m,b_m); + BASOP_SATURATE_WARNING_ON + diff_e = sub(a_e,b_e); + + test(); + IF(diff_m == 0 && diff_e == 0) + { + return 0; + } + + /* Check sign, exponent and mantissa to identify, whether a is greater b or not */ + result = sub(0,1); + + IF (a_m >= 0) + { + /* a is positive */ + if (b_m < 0) + { + result = 1; + move16(); + } + + test(); + test(); + test(); + if ((b_m >= 0) && ((diff_e > 0) || (diff_e == 0 && diff_m > 0))) + { + result = 1; + move16(); + } + } + ELSE + { + /* a is negative */ + test(); + test(); + test(); + if ((b_m < 0) && ((diff_e < 0) || (diff_e == 0 && diff_m > 0))) + { + result = 1; + move16(); + } + } + return result; +} + +/* + + headroom is introduced into acc +*/ + + + +void bufferCopyFx( + Word16* src, /*old_exc, exc_buf, st->old_exc_len);*/ + tmp_16 = sub(sub(Qf_src,Qf_dest),sub(Q_src,Q_dest)); + IF (tmp_16>0) /*if value will be shifted right, do a multiplication with rounding ->preserves more accuracy*/ + { + tmp_16 = shl(1,sub(15,tmp_16)); + FOR (i = 0 ; i < length ; i++) + { + *(dest+i) = mult_r(*(src+i),tmp_16); + move16(); + } + } + ELSE IF (tmp_16 <0)/*leftshift - no accuracy preservation needed*/ + { + FOR (i = 0 ; i < length ; i++) + { + *(dest+i) = shr(*(src+i),tmp_16); + move16(); + } + } + ELSE /*no shift, simply copy*/ + { + FOR (i = 0 ; i < length ; i++) + { + *(dest+i) = *(src+i); + move16(); + } + } +} + +Word32 dotWord32_16_Mant32Exp(const Word32 *bufX32,/* i: 32-bit buffer with unknown headroom */ + Word16 bufX32_exp, /* i: exponent of buffer bufX32 */ + const Word16 *bufY16,/* i: 16-bit buffer quite right-aligned */ + Word16 bufY16_exp, /* i: exponent of buffer bufY16 */ + Word16 len, /* i: buffer len to process */ + Word16 *exp) /* o: result exponent */ +{ + Word32 L_sum; + Word16 shift, shift1, i; + + + + shift = getScaleFactor32(bufX32, len); /* current available headroom */ + shift = sub(shift, sub(14,norm_s(len))); /* reduced required headroom */ + L_sum = 0; /* Clear accu */ + move32(); + FOR(i=0; i < len; i++) + { + L_sum = L_mac0(L_sum, round_fx(L_shl(bufX32[i], shift)), bufY16[i]); + } + shift1 = norm_l(L_sum); + L_sum = L_shl(L_sum, shift1); /* return value */ + + shift = sub(add(bufX32_exp, bufY16_exp), add(shift, shift1)); + shift = add(shift, 1); /* compensate for factor of 2 introduced by L_mac0 */ + /* In case of NULL result, we want to have a 0 exponent too */ + if (L_sum == 0) + shift = 0; + *exp = shift; + move16(); + + + return L_sum; + +} + +Word16 BASOP_Util_lin2dB(Word32 x, Word16 x_e, Word16 fEnergy) +{ + assert(x >= 0); + + /* log2 */ + x = L_shr(BASOP_Util_Log2(x), 25-16); /* Q16 */ + + /* add exponent */ + x = L_msu(x, x_e, -32768 /* 0x8000 */); + + /* convert log2 to 20*log10 */ + x = Mpy_32_16_1(x, 24660/*6.0206f Q12*/); /* Q13 */ + + /* if energy divide by 2 (->10*log10) */ + if (fEnergy != 0) x = L_shr(x, 1); + + /* return dB as 7Q8 */ + return round_fx(L_shl(x, 8-13+16)); /* Q8 */ +} + +/* --- fixp_atan() ---- */ +#define Q_ATANINP (25) /* Input in q25, Output in q14 */ +#define Q_ATANOUT (14) +#define ATI_SF ((32-1)-Q_ATANINP) /* 6 */ +#define ATO_SF ((16-1)-Q_ATANOUT) /* 1 ] -pi/2 .. pi/2 [ */ +/* --- fixp_atan2() --- */ +#define Q_ATAN2OUT (13) +#define AT2O_SF ((16-1)-Q_ATAN2OUT) /* 2 ] -pi .. pi ] */ + + +Word16 BASOP_util_atan2( /* o: atan2(y,x) [-pi,pi] Q13 */ + Word32 y, /* i: */ + Word32 x, /* i: */ + Word16 e /* i: exponent difference (exp_y - exp_x) */ +) +{ + Word16 q; + Word32 at; + Word16 ret = -32768/*-1.0f Q15*/; + Word16 sf,sfo,stf; + Word32 L_sign; + + if(L_or(y,x) == 0) + { + return 0; + } + + IF(x == 0) + { + ret = 12868/*+EVS_PI/2 Q13*/; + move16(); + if ( y < 0 ) + { + ret = negate(ret); + } + + return ret; + } + + /* --- division */ + L_sign = L_and(L_xor(x,y), 0x80000000 ); + + q = 32767/*1.0f Q15*/; /* y/x = neg/zero = -Inf */ + sf = 0; + BASOP_SATURATE_WARNING_OFF + q = BASOP_Util_Divide3232_uu_1616_Scale(L_abs(y),L_abs(x), &sf); + BASOP_SATURATE_WARNING_ON + + BASOP_SATURATE_WARNING_OFF + if(L_sign < 0) + q = negate(q); + BASOP_SATURATE_WARNING_ON + + sfo = add(sf,e); + + /* --- atan() */ + IF ( GT_16(sfo,ATI_SF)) + { + /* --- could not calc fixp_atan() here bec of input data out of range + ==> therefore give back boundary values */ + + sfo = s_min(sfo, MAXSFTAB); + + /*q = FL2WORD16( 0.0f ); move16();*/ + + if( q > 0 ) + { + move16(); + q = +f_atan_expand_range[sfo-ATI_SF-1]; + } + if( q < 0 ) + { + move16(); + q = -f_atan_expand_range[sfo-ATI_SF-1]; + } + } + ELSE + { + /* --- calc of fixp_atan() is possible; input data within range + ==> set q on fixed scale level as desired from fixp_atan() */ + stf = sub(sfo, ATI_SF); + + at = L_deposit_h(q); + if (stf < 0) at = L_shl(at,stf); + + q = BASOP_util_atan(at); /* ATO_SF*/ + } + + + /* --- atan2() */ + + ret = shr(q,(AT2O_SF - ATO_SF)); /* now AT2O_SF for atan2 */ + IF ( x < 0 ) + { + if ( y >= 0 ) + { + ret = add(ret, 25736/*EVS_PI Q13*/); + } + if(y < 0) + { + ret = sub(ret, 25736/* EVS_PI Q13*/); + } + } + + return ret; +} + +/* SNR of fixp_atan() = 56 dB*/ +#define ONEBY3P56 0x26800000 /* 1.0/3.56 in q31*/ +#define P281 0x00026000 /* 0.281 in q19*/ +#define ONEP571 0x6487 /* 1.571 in q14*/ + +Word16 BASOP_util_atan( /* o: atan(x) [-pi/2;pi/2] 1Q14 */ + Word32 x /* i: input data (-64;64) 6Q25 */ +) +{ + Word16 sign, result, exp; + Word16 res_e; + Word16 tmp, xx; + + + + sign = 0; + move16(); + if (x < 0) + { + sign = 1; + move16(); + } + x = L_abs(x); + + /* calc of arctan */ + IF(LT_32(x, 1509950l/*0.045f/64.0f Q31*/)) + { + result = round_fx(L_shl(x,5)); /*Q14*/ + /*BASOP_util_atan_16(0.0444059968): max error 0.0000567511, mean 0.000017, abs mean 0.000017*/ + } + ELSE + IF(LT_32(x,( L_shl(1,Q_ATANINP)-8482560l/*0.00395 Q31*/))) + { + xx =round_fx(L_shl(x,6)); + tmp = mult_r(xx, xx); /* q15 * q15 - (16-1) = q15*/ + tmp = mult_r(tmp, 0x1340); /* 15 * (ONEBY3P56) q14 - (16-1) = q14*/ + tmp = add(tmp, 0x4000); /*L_shl(1,14) = 524288*/ /* q14 + q14 = q14 */ + res_e=Q_ATANOUT-15+14-16+1; + move16(); + if(GT_16(xx,tmp)) + { + res_e = add(res_e,1); + } + if(GT_16(xx,tmp)) + { + xx = shr(xx,1); + } + result = div_s(xx, tmp); + result = msu_r(0, result, shl(-32768,res_e)); + /*BASOP_util_atan_16(0.7471138239): max error 0.0020029545, mean 0.000715, abs mean 0.000715*/ + } + ELSE IF( LT_32(x,42949673l/*1.28/64.0 Q31*/)) + { + Word16 delta_fix; + Word32 PI_BY_4 = 1686629684l/*3.1415926/4.0 Q31*//2; /* pi/4 in q30 */ + + delta_fix = round_fx(L_shl(L_sub(x,33554432l/*1.0/64.0 Q31*/), 5)); /* q30 */ + result = round_fx(L_sub(L_add(PI_BY_4, L_msu(0,delta_fix,-16384)),(L_mult0(delta_fix, delta_fix)))); + /* BASOP_Util_fPow(0.7472000122): max error 0.0020237688, mean 0.000026, abs mean 0.000520 */ + } + ELSE + { + exp = sub(norm_l(x),1); + xx = round_fx(L_shl(x,exp)); + /* q25+exp * q25+exp - (16-1) = q19+2*exp*/ + tmp = mac_r(L_shl(P281,shl(exp,1)),xx, xx); /* q19+2*exp + q19+2*exp = q19+2*exp*/ + res_e = norm_s(tmp); + result = div_s(xx, shl(tmp,res_e)); + result = shl(result, add(add(Q_ATANOUT-Q_ATANINP/*-exp*/+19/*+2*exp*/-16+1, res_e ),exp)); + result = sub(ONEP571,result); /* q14 + q14 = q14*/ + /*BASOP_Util_fPow(1.2799999714): max error 0.0020168927, mean 0.000066, abs mean 0.000072*/ + } + + if (sign) + { + result = negate(result); + } + + return(result); +} + +/* compare two positive normalized 16 bit mantissa/exponent values */ +/* return value: positive if first value greater, negative if second value greater, zero if equal */ +Word16 compMantExp16Unorm(Word16 m1, Word16 e1, Word16 m2, Word16 e2) +{ + Word16 tmp; + + assert((m1 >= 0x4000) && (m2 >= 0x4000)); /* comparisons below work only for normalized mantissas */ + + tmp = sub(e1, e2); + if (tmp == 0) tmp = sub(m1, m2); + + return tmp; +} + +cmplx CL_scale_t(cmplx x, Word16 y) +{ + cmplx result; + result.re = Mpy_32_16_1(x.re, y); + result.im = Mpy_32_16_1(x.im, y); +#if (WMOPS) + multiCounter[currCounter].Mpy_32_16_1--; + multiCounter[currCounter].Mpy_32_16_1--; + multiCounter[currCounter].CL_scale++; +#endif + return (result); +} + +cmplx CL_dscale_t(cmplx x, Word16 y1, Word16 y2) +{ + cmplx result; + result.re = Mpy_32_16_1(x.re, y1); + result.im = Mpy_32_16_1(x.im, y2); +#if (WMOPS) + multiCounter[currCounter].Mpy_32_16_1--; + multiCounter[currCounter].Mpy_32_16_1--; + multiCounter[currCounter].CL_dscale++; +#endif/* #if (WMOPS) */ + return (result); +} + +cmplx CL_mult_32x16(cmplx input, cmplx_s coeff) +{ + cmplx result; + result.re = L_sub(Mpy_32_16_1(input.re,coeff.re), Mpy_32_16_1(input.im, coeff.im)); + result.im = L_add(Mpy_32_16_1(input.re,coeff.im), Mpy_32_16_1(input.im, coeff.re)); +#if (WMOPS) + multiCounter[currCounter].CL_multr_32x16++; + multiCounter[currCounter].Mpy_32_16_1--; + multiCounter[currCounter].Mpy_32_16_1--; + multiCounter[currCounter].Mpy_32_16_1--; + multiCounter[currCounter].Mpy_32_16_1--; + multiCounter[currCounter].L_sub--; + multiCounter[currCounter].L_add--; +#endif + return result; +} diff --git a/lib_com/basop_util.h b/lib_com/basop_util.h new file mode 100644 index 0000000..b52e70c --- /dev/null +++ b/lib_com/basop_util.h @@ -0,0 +1,816 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#ifndef __BASOP_UTIL_H__ +#define __BASOP_UTIL_H__ + +#include "stl.h" +#include "typedef.h" +#include "basop32.h" +#include "basop_mpy.h" + + +#define _LONG long +#define _SHORT short +#ifdef _WIN32 +#define _INT64 __int64 +#else +#define _INT64 long long +#endif + +#define WORD32_BITS 32 +#define MAXVAL_WORD32 ((signed)0x7FFFFFFF) +#define MINVAL_WORD32 ((signed)0x80000000) +#define WORD32_FIX_SCALE ((_INT64)(1)<<(WORD32_BITS-1)) + +#define WORD16_BITS 16 +#define MAXVAL_WORD16 (((signed)0x7FFFFFFF)>>16) +#define MINVAL_WORD16 (((signed)0x80000000)>>16) +#define WORD16_FIX_SCALE ((_INT64)(1)<<(WORD16_BITS-1)) + +/*! + \def Macro converts a Word32 fixed point to Word16 fixed point <1 with saturation +*/ +#define WORD322WORD16(val) \ + ( ( ((((val) >> (WORD32_BITS-WORD16_BITS-1)) + 1) > (((_LONG)1< 0) ) ? \ + (Word16)(_SHORT)(((_LONG)1<<(WORD16_BITS-1))-1):(Word16)(_SHORT)((((val) >> (WORD32_BITS-WORD16_BITS-1)) + 1) >> 1) ) + + +/* Word16 Packed Type */ +typedef struct +{ + struct + { + Word16 re; + Word16 im; + } v; +} PWord16; + +#define cast16 move16 + + +#define LD_DATA_SCALE (6) +#define LD_DATA_SHIFT_I5 (7) + +#define modDiv2(x) sub(x,shl(shr(x,1),1)) +#define modDiv8(x) L_sub(x,L_shl(L_shr(x,3),3)) + +static __inline Word16 limitScale16( Word16 s) +{ + /* It is assumed, that s is calculated just before, therefore we can switch upon sign */ + if (s >= 0) + s = s_min(s,WORD16_BITS-1); + if (s < 0) + s = s_max(s,1-WORD16_BITS); + return (s); +} + +static __inline Word16 limitScale32( Word16 s) +{ + /* It is assumed, that s is calculated just before, therefore we can switch upon sign */ + if (s >= 0) + s = s_min(s, WORD32_BITS-1); + if (s < 0) + s = s_max(s, 1-WORD32_BITS); + return (s); +} + +/*!********************************************************************** + \brief Add two values given by mantissa and exponent. + + Mantissas are in 16-bit-fractional format with values between 0 and 1.
+ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ +************************************************************************/ +Word16 BASOP_Util_Add_MantExp /*!< Exponent of result */ +(Word16 a_m, /*!< Mantissa of 1st operand a */ + Word16 a_e, /*!< Exponent of 1st operand a */ + Word16 b_m, /*!< Mantissa of 2nd operand b */ + Word16 b_e, /*!< Exponent of 2nd operand b */ + Word16 *ptrSum_m); /*!< Mantissa of result */ + +/************************************************************************/ +/*! + \brief Divide two values given by mantissa and exponent. + + Mantissas are in 16-bit-fractional format with values between 0 and 1.
+ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ + For performance reasons, the division is based on a table lookup + which limits accuracy. +*/ +void BASOP_Util_Divide_MantExp (Word16 a_m, /*!< Mantissa of dividend a */ + Word16 a_e, /*!< Exponent of dividend a */ + Word16 b_m, /*!< Mantissa of divisor b */ + Word16 b_e, /*!< Exponent of divisor b */ + Word16 *ptrResult_m, /*!< Mantissa of quotient a/b */ + Word16 *ptrResult_e /*!< Exponent of quotient a/b */ + ); + +/************************************************************************/ +/*! + \brief Calculate the squareroot of a number given by mantissa and exponent + + Mantissa is in 16/32-bit-fractional format with values between 0 and 1.
+ For *norm versions mantissa has to be between 0.5 and 1.
+ The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ The exponent is addressed via pointers and will be overwritten with the result. +*/ +Word16 Sqrt16( /*!< output mantissa */ + Word16 mantissa, /*!< input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +); + +Word16 Sqrt16norm( /*!< output mantissa */ + Word16 mantissa, /*!< normalized input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +); + +Word32 Sqrt32( /*!< output mantissa */ + Word32 mantissa, /*!< input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +); + + +/* deprecated, use Sqrt16! */ +void BASOP_Util_Sqrt_MantExp (Word16 *mantissa, /*!< Pointer to mantissa */ + Word16 *exponent /*!< Pointer to exponent */ + ); + +/* deprecated, use Sqrt16norm! */ +void BASOP_Util_Sqrt_MantExpNorm (Word16 *mantissa, /*!< Pointer to normalized mantissa */ + Word16 *exponent /*!< Pointer to exponent */ + ); + +/****************************************************************************/ +/*! + \brief Calculate the inverse of the squareroot of a number given by mantissa and exponent + + Mantissa is in 16/32-bit-fractional format with values between 0 and 1.
+ For *norm versions mantissa has to be between 0.5 and 1.
+ The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ The exponent is addressed via pointers and will be overwritten with the result. +*/ +Word16 ISqrt16( /*!< output mantissa */ + Word16 mantissa, /*!< input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +); + +Word32 ISqrt32( /*!< output mantissa */ + Word32 mantissa, /*!< input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +); + +Word32 ISqrt32norm( /*!< output mantissa */ + Word32 mantissa, /*!< normalized input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +); + +/* deprecated, use ISqrt16! */ +void BASOP_Util_InvSqrt_MantExp (Word16 *mantissa, /*!< Pointer to mantissa */ + Word16 *exponent /*!< Pointer to exponent */ + ); + +/*****************************************************************************/ +/*! + \brief Calculate the inverse of a number given by mantissa and exponent + + Mantissa is in 16-bit-fractional format with values between 0 and 1.
+ The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ The operand is addressed via pointers and will be overwritten with the result. + + The function uses a table lookup and a newton iteration. +*/ +Word16 Inv16( /*!< output mantissa */ + Word16 mantissa, /*!< input mantissa */ + Word16 *exponent /*!< pointer to exponent */ +); +/******************************************************************************/ +/*! + \brief Calculate the squareroot and inverse of squareroot of a number given by mantissa and exponent + + Mantissa is in 16-bit-fractional format with values between 0 and 1.
+ The base for the exponent is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+*/ +void BASOP_Util_Sqrt_InvSqrt_MantExp (Word16 mantissa, /*!< mantissa */ + Word16 exponent, /*!< expoinent */ + Word16 *sqrt_mant, /*!< Pointer to sqrt mantissa */ + Word16 *sqrt_exp, /*!< Pointer to sqrt exponent */ + Word16 *isqrt_mant, /*!< Pointer to 1/sqrt mantissa */ + Word16 *isqrt_exp /*!< Pointer to 1/sqrt exponent */ + ); + +/********************************************************************/ +/*! + \brief Calculates the scalefactor needed to normalize input array + + The scalefactor needed to normalize the Word16 input array is returned
+ If the input array contains only '0', a scalefactor 0 is returned
+ Scaling factor is determined wrt a normalized target x: 16384 <= x <= 32767 for positive x
+ and -32768 <= x <= -16384 for negative x +*/ + +Word16 getScaleFactor16( /* o: measured headroom in range [0..15], 0 if all x[i] == 0 */ + const Word16 *x, /* i: array containing 16-bit data */ + const Word16 len_x); /* i: length of the array to scan */ + +/********************************************************************/ +/*! + \brief Calculates the scalefactor needed to normalize input array + + The scalefactor needed to normalize the Word32 input array is returned
+ If the input array contains only '0', a scalefactor 0 is returned
+ Scaling factor is determined wrt a normalized target x: 1073741824 <= x <= 2147483647 for positive x
+ and -2147483648 <= x <= -1073741824 for negative x +*/ + +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 */ + +/** + * \brief normalize mantissa and update the exponent accordingly. + * \param mantissa the mantissa to be normalized + * \param pexponent pointer to the exponent. + * \return the normalized mantissa. + */ +Word16 normalize16(Word16 mantissa, Word16 *pexponent); +/****************************************************************************/ +/*! + \brief Does fractional integer division of Word32 arg1 by Word16 arg2 + + both input arguments may be positive or negative
+ the result is truncated to Word16 + + \return fractional integer Word16 result of arg1/arg2 +*/ +Word16 divide3216( Word32 x, /*!< Numerator*/ + Word16 y); /*!< Denominator*/ + + +/****************************************************************************/ +/*! + \brief Does fractional integer division of Word16 arg1 by Word16 arg2 + + both input arguments may be positive or negative
+ the result is truncated to Word16 + + \return fractional integer Word16 result of arg1/arg2 +*/ +Word16 divide1616( Word16 x, /*!< Numerator*/ + Word16 y); /*!< Denominator*/ + + +/****************************************************************************/ +/*! + \brief Does fractional integer division of Word32 arg1 by Word32 arg2 + + this function makes both the numerator and the denominator positive integers, + and scales up both values to avoid losing the accuracy of the outcome + too much + + WARNING: it should be arg1 < arg2 because of the maximum degree of scaling for the mantissa! + + \return fractional Word16 integer z = arg1(32bits)/arg2(32bits) +*/ +Word16 divide3232( Word32 x, /*!< Numerator*/ + Word32 y); /*!< Denominator*/ + + +/****************************************************************************/ +/*! + \brief Does fractional integer division of UWord32 arg1 by UWord32 arg2 + + This function ensures both the numerator and the denominator are positive integers, + and scales up both values to avoid losing the accuracy of the outcome + too much.
+ + CAUTION: Arg 3 is a Word16 pointer which will point to the scalefactor difference + s_diff = sub(s2,s1), where s1 and s2 are the scalefactors of the arguments, which + were shifted in order to e.g. preserve accuracy. + I.e. the result has to be scaled due to shifting it + s_diff to the right to obtain the real result of the division. + + \return fractional Word16 integer z = arg1(32bits)/arg2(32bits) +*/ +Word16 BASOP_Util_Divide3232_uu_1616_Scale( Word32 x, /*!< i : Numerator*/ + Word32 y, /*!< i : Denominator*/ + Word16 *s); /*!< o : Additional scalefactor difference*/ + + +/****************************************************************************/ +/*! + \brief Does fractional integer division of Word32 arg1 by Word32 arg2 + + This function scales up both values to avoid losing the accuracy of the outcome + too much.
+ + CAUTION: Arg 3 is a Word16 pointer which will point to the scalefactor difference + s_diff = sub(s2,s1), where s1 and s2 are the scalefactors of the arguments, which + were shifted in order to e.g. preserve accuracy. + I.e. the result has to be scaled due to shifting it + s_diff to the right to obtain the real result of the division. + + \return fractional Word16 integer z = arg1(32bits)/arg2(32bits) +*/ +Word16 BASOP_Util_Divide3232_Scale( Word32 x, /*!< i : Numerator*/ + Word32 y, /*!< i : Denominator*/ + Word16 *s); /*!< o : Additional scalefactor difference*/ + + +/****************************************************************************/ +/*! + \brief Does fractional integer division of Word32 arg1 by Word16 arg2 + + + \return fractional Word16 integer z = arg1(32bits)/arg2(16bits) , z not normalized +*/ +Word16 BASOP_Util_Divide3216_Scale( Word32 x, /*!< i : Numerator */ + Word16 y, /*!< i : Denominator*/ + Word16 *s); /*!< o : Additional scalefactor difference*/ + + +/****************************************************************************/ +/*! + \brief Does fractional division of Word16 arg1 by Word16 arg2 + + + \return fractional Q15 Word16 z = arg1(Q15)/arg2(Q15) with scaling s +*/ +Word16 BASOP_Util_Divide1616_Scale( Word16 x, /*!< i : Numerator*/ + Word16 y, /*!< i : Denominator*/ + Word16 *s); /*!< o : Additional scalefactor difference*/ + +/************************************************************************/ +/*! + \brief Binary logarithm with 7 iterations + + \param x + + \return log2(x)/64 + */ +/************************************************************************/ +Word32 BASOP_Util_Log2(Word32 x); + + +/************************************************************************/ +/*! + \brief Binary power + + Date: 06-JULY-2012 Arthur Tritthart, IIS Fraunhofer Erlangen + + Version with 3 table lookup and 1 linear interpolations + + Algorithm: compute power of 2, argument x is in Q7.25 format + result = 2^(x/64) + We split exponent (x/64) into 5 components: + integer part: represented by b31..b25 (exp) + fractional part 1: represented by b24..b20 (lookup1) + fractional part 2: represented by b19..b15 (lookup2) + fractional part 3: represented by b14..b10 (lookup3) + fractional part 4: represented by b09..b00 (frac) + => result = (lookup1*lookup2*(lookup3+C1*frac)<<3)>>exp + + 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 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. + + Limitations: + + For x <= 0, the result is fractional positive + For x > 0, the result is integer in range 1...7FFF.FFFF + For x < -31/64, we have to clear the result + For x = 0, the result is ~1.0 (0x7FFF.FFFF) + For x >= 31/64, the result is 0x7FFF.FFFF + + \param x + + \return pow(2,(x/64)) + */ +/************************************************************************/ +Word32 BASOP_Util_InvLog2(Word32 x); + +Word16 BASOP_util_norm_s_bands2shift (Word16 x); + +/***********************************************************************/ +/*! + \brief Calculate the headroom of the complex data in a 2 dimensional array + + \return number of headroom bits + */ +Word16 BASOP_util_norm_l_dim2_cplx (const Word32 * const *re, /*!< Real part of 32 Bit input */ + const Word32 * const *im, /*!< Imag part if 32 Bit input */ + Word16 startBand, /*!< start band of cplx data */ + Word16 stopBand, /*!< stop band of cplx data */ + Word16 startSlot, /*!< start slot of cplx data */ + Word16 stopSlot /*!< stop slot of cplx data */ + ); +/****************************************************************************/ +/*! + \brief Does a data copy of Word8 *arg1 to Word8 *arg2 with Word16 arg3 number of moves +*/ +void copyWord8( const Word8 *src, /*!< i : Source address */ + Word8 *dst, /*!< i : Destination address */ + const Word32 n); /*!< i : Number of elements to copy */ + + +/****************************************************************************/ +/*! + \brief Sets Word8 array arg1[] to zero for a length of Word16 arg2 elements +*/ +void set_zero_Word8( Word8 X[], /*!< i : Address of array */ + Word32 n); /*!< i : Number of elements to set to zero */ + +/****************************************************************************/ +/*! + \brief Does a multiplication of Word32 * Word16 input values + + \return z32 = x32 * y16 +*/ +Word32 L_mult0_3216( Word32 x, /*!< : Multiplier */ + Word16 y); /*!< : Multiplicand */ + +/* Calculate sin/cos. Angle in 2Q13 format, result has exponent = 1 */ +Word16 getCosWord16(Word16 theta); +Word32 getCosWord32(Word32 theta); +/** + * \brief calculate cosine of angle. Tuned for ISF domain. + * \param theta Angle normalized to radix 2, theta = (angle in radians)*2.0/pi + * \return result with exponent 0. + */ +Word16 getCosWord16R2(Word16 theta); + +/****************************************************************************/ +/*! + \brief square root abacus algorithm + + \return integer sqrt(x) + */ +Word16 getSqrtWord32(Word32 x); + +/****************************************************************************/ +/*! + \brief finds index of min Word16 in array + + \return index of min Word16 + */ +Word16 findIndexOfMinWord16(Word16 *x, const Word16 len); + +/****************************************************************************/ +/*! + \brief finds index of min Word32 in array + + \return index of min Word32 + */ +Word16 findIndexOfMinWord32(Word32 *x, const Word16 len); + +/****************************************************************************/ +/*! + \brief finds index of max Word16 in array + + \return index of max Word16 + */ +Word16 findIndexOfMaxWord16(Word16 *x, const Word16 len); + +/****************************************************************************/ +/*! + \brief finds index of max Word32 in array + + \return index of max Word32 + */ +Word16 findIndexOfMaxWord32(Word32 *x, const Word16 len); + +/****************************************************************************/ +/*! + \brief 16x16->16 integer multiplication without overflow control + + \return 16x16->16 integer + */ +Word16 imult1616(Word16 x, Word16 y); + +/****************************************************************************/ +/*! + \brief 32x16->32 integer multiplication with overflow control + + \return 32x16->32 integer + */ +Word32 imult3216(Word32 x, Word16 y); + +/****************************************************************************/ +/*! + \brief 16/16->16 unsigned integer division + + x and y have to be positive, x has to be < 16384 + + \return 16/16->16 integer + */ + +Word16 idiv1616U(Word16 x, Word16 y); + +/****************************************************************************/ +/*! + \brief 16/16->16 signed integer division + + x and y have to be positive, x has to be < 16384 + + \return 16/16->16 integer + */ + +Word16 idiv1616(Word16 x, Word16 y); + +/*------------------------------------------------------------------* + * Dot_product16HQ: + * + * \brief Compute scalar product of using 64-bit accumulator. + * + * Performs normalization of the result, returns the exponent + * Note: In contrast to dotWord32, no headroom is required for data + * in x[] and y[], means, they may have any format Qn + *------------------------------------------------------------------*/ +Word32 Dot_product16HQ( /* using 64-bit accumulator. + * + * Performs normalization of the result, returns the exponent + * Note: In contrast to dotWord32, no headroom is required for data + * in x[], means, they may have any format Qn + *------------------------------------------------------------------*/ +Word32 Dot_productSq16HQ( /* using 64-bit accumulator. + * + * Performs no normalization of the result + *------------------------------------------------------------------*/ +Word32 dotp_s_fx( /* using accumulator. | + | The parameter 'L_off' is added to the accumulation result. | + | The result is normalized (in Q31) with exponent (0..30). | + | Notes: | + | o data in x[],y[] must provide enough headroom for accumulation | + | o L_off must correspond in format with product of x,y | + | Example: 0.01f for Q9 x Q9: 0x0000147B in Q19 | + | means: L_off = FL2WORD32_SCALE(0.01f,31-19) | + |---------------------------------------------------------------------------| + | Algorithm: | + | | + | dot_product = L_off + sum(x[i]*y[i]) i=0..N-1 | + |___________________________________________________________________________| +*/ + +Word32 Dot_product12_offs( /* (o) Q31: normalized result (1 < val <= -1) */ + const Word16 x[], /* (i) 12bits: x vector */ + const Word16 y[], /* (i) 12bits: y vector */ + const Word16 lg, /* (i) : vector length in range [1..256] */ + Word16 * exp, /* (o) : exponent of result (0..+30) */ + Word32 L_off /* (i) initial summation offset /2 */ +); + +Word32 Dot_product15_offs( /* (o) Q31: normalized result (1 < val <= -1) */ + const Word16 x[], /* (i) 15bits: x vector */ + const Word16 y[], /* (i) 15bits: y vector */ + const Word16 lg, /* (i) : vector length in range [1..256] */ + Word16 *exp, /* (o) : exponent of result (0..+30) */ + Word32 L_off /* (i) initial summation offset */ +); + +/*!********************************************************************** + \brief Add two values given by mantissa and exponent. + + Mantissas are in 32-bit-fractional format with values between 0 and 1.
+ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ +************************************************************************/ +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 */ + Word16 b_e, /*!< i: Exponent of 2nd operand b */ + Word16 *ptr_e); /*!< o: exponent of result */ +/*!********************************************************************** + \brief Returns the comparison result of two normalized values given by mantissa and exponent. + return value: -1: a < b, 0: a == b, 1; a > b + + Mantissas are in 32-bit-fractional format with values between 0 and 1.
+ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ +************************************************************************/ +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 */ + Word16 b_e); /*!< i: Exponent of 2nd operand b */ + +/******************************************************************** + * bufferCopyFx + * + * \brief copies buffer while preserving Format of destination buffer +********************************************************************* +*/ +void bufferCopyFx( + Word16* src, /* + The base for exponent x_e is 2.
+ +************************************************************************/ +Word16 BASOP_Util_lin2dB( /*!< o: dB value (7Q8) */ + Word32 x, /*!< i: mantissa */ + Word16 x_e, /*!< i: exponent */ + Word16 fEnergy); /*!< i: flag indicating if x is energy */ + +/*!********************************************************************** + \brief Calculates atan(x). +************************************************************************/ +Word16 BASOP_util_atan( /*!< o: atan(x) [-pi/2;pi/2] 1Q14 */ + Word32 x /*!< i: input data (-64;64) 6Q25 */ +); + +/*!********************************************************************** + \brief Calculates atan2(y,x). +************************************************************************/ +Word16 BASOP_util_atan2( /*!< o: atan2(y,x) [-pi,pi] Q13 */ + Word32 y, /*!< i: */ + Word32 x, /*!< i: */ + Word16 e /*!< i: exponent difference (exp_y - exp_x) */ +); +/*!********************************************************************** + \brief norm_llQ31 returns Word32 with scalingfactor, with 2 32bit accus as input + +************************************************************************/ +Word32 norm_llQ31( /* o : normalized result Q31 */ + Word32 L_c, /* i : upper bits of accu Q-1 */ + Word32 L_sum, /* i : lower bits of accu, unsigned Q31 */ + Word16 * exp /* o : exponent of result in [-32,31] Q0 */ +); + +/* compare two positive normalized 16 bit mantissa/exponent values */ +/* return value: positive if first value greater, negative if second value greater, zero if equal */ +Word16 compMantExp16Unorm(Word16 m1, Word16 e1, Word16 m2, Word16 e2); + + +cmplx CL_scale_t(cmplx x, Word16 y); +cmplx CL_dscale_t(cmplx x, Word16 y1, Word16 y2); +cmplx CL_mult_32x16(cmplx input, cmplx_s coeff); + +#endif /* __BASOP_UTIL_H__ */ diff --git a/lib_com/bitalloc_fx.c b/lib_com/bitalloc_fx.c new file mode 100644 index 0000000..e875265 --- /dev/null +++ b/lib_com/bitalloc_fx.c @@ -0,0 +1,1029 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required for wmc_tool */ + +void bitalloc_fx ( + Word16 *y, /* i : reordered norm of sub-vectors Q0 */ + Word16 *idx, /* i : reordered sub-vector indices Q0 */ + Word16 sum, /* i : number of available bits Q0 */ + Word16 N, /* i : number of norms Q0 */ + Word16 K, /* i : maximum number of bits per dimension Q0 */ + Word16 *r, /* o : bit-allacation vector Q0 */ + const Word16 *sfmsize, /* i : band length Q0 */ + const Word16 hqswb_clas /* i : signal classification flag Q0 */ +) +{ + Word16 i, j, k, n, m, v, im; + Word16 diff, temp; + Word16 fac; + Word16 ii; + Word16 SFM_thr = SFM_G1G2; + move16(); + + N = sub(N, 1); + + if ( EQ_16(hqswb_clas, HQ_HARMONIC)) + { + SFM_thr = 22; + move16(); + } + + fac = 3; + move16(); + K = sub(K,2); + im = 1; + move16(); + diff = sum; + move16(); + n = shr(sum,3); + FOR ( i=0; i 0) + { + n = add(n,Nb[i]); + Rsubband_w32_fx[i] = Mult_32_16(Rsubband_w32_fx[i], tmp); + move32();/*exp1 - 15*/ + Rsubband_w32_fx[i] = L_shl(Rsubband_w32_fx[i], sub(30, exp1));/*Q15*/ + + t_fx = L_add(t_fx, Rsubband_w32_fx[i]);/*Q0*/ + } + ELSE + { + Rsubband_w32_fx[i] = L_deposit_l(0); + } + } + } + ELSE + { + /* Initial bits distribution */ + L_tmp1 = 0; + move16(); + m_fx = 0; + move16(); + FOR ( i = 0; i < N ; i++) + { + L_tmp1 = L_mac0(L_tmp1, Nb[i], y[i]); + } + L_tmp1 = L_msu0(L_tmp1, fac, B); + + + t_fx = L_deposit_l(0); + n = 0; + move16(); + tmp = add(band_end_HQ[N-1], shl(band_end_HQ[N-1], 1)); + exp1 = norm_s(tmp); + tmp = div_s(16384, shl(tmp, exp1));/*15 + 14 - exp1*/ + exp2 = norm_s(tmp); + tmp = shl(tmp, exp2); + exp1 = add(29, sub(exp2, exp1)); + FOR ( i = 0; i < N; i++) + { + L_tmp2 = L_sub(L_mult0(y[i], band_end_HQ[N-1]), L_tmp1); + Rsubband_w32_fx[i] = L_mult0(extract_l(L_tmp2), Nb[i]); + move32();/*Q0*/ + IF (Rsubband_w32_fx[i] > 0) + { + n = add(n,Nb[i]); + L_tmp3 = Mult_32_16(Rsubband_w32_fx[i], tmp); /*exp1 - 15*/ + Rsubband_w32_fx[i] = L_shl(L_tmp3, sub(30, exp1)); /*Q15*/ move32(); + + t_fx = L_add(t_fx, Rsubband_w32_fx[i]);/*Q0*/ + } + ELSE + { + Rsubband_w32_fx[i] = L_deposit_l(0); + } + } + } + + /* Distribute the remaining bits to subbands with non-zero bits */ + B_fx = L_shl(B, 15); + WHILE (NE_32(L_shr(L_add(t_fx, 16384), 15) , B)) + { + L_tmp1 = L_sub(t_fx, B_fx); + exp1 = sub(norm_l(L_tmp1), 1); + exp2 = norm_s(n); + tmp = div_s(extract_h(L_shl(L_tmp1, exp1)), shl(n, exp2));/*15 + 15 + exp1 - 16 - exp2*/ + m_fx = shl(tmp, sub(exp2, exp1));/*Q14*/ + + t_fx = L_deposit_l(0); + n = 0; + move16(); + FOR ( i = 0; i < N; i++) + { + IF (Rsubband_w32_fx[i] > 0) + { + Rsubband_w32_fx[i] = L_msu(Rsubband_w32_fx[i], m_fx, Nb[i]); + move32(); + + IF (Rsubband_w32_fx[i] > 0) + { + n = add(n,Nb[i]); + + t_fx = L_add(t_fx, Rsubband_w32_fx[i]); + } + ELSE + { + Rsubband_w32_fx[i] = L_deposit_l(0); + } + } + } + } + Bits = B; + move16(); + + /* Impose bit-constraints to subbands with less than minimum bits*/ + t_fx = L_deposit_l(0); + n = 0; + move16(); + FOR ( i = 0; i < N; i++) + { + IF (Rsubband_w32_fx[i] > 0) + { + test(); + IF ((LT_32(Rsubband_w32_fx[i] , L_shl(add(bs, LNb[i]), 15)))&&(EQ_16(low_rate,1))) + { + Rsubband_w32_fx[i] = L_deposit_l(0); + } + ELSE IF ( LE_32(Rsubband_w32_fx[i] , L_shl(Nb[i], 15))) + { + B = sub(B,Nb[i]); + Rsubband_w32_fx[i] = L_shl(Nb[i], 15); + move32(); + } + ELSE + { + n = add(n,Nb[i]); + t_fx = L_add(t_fx, Rsubband_w32_fx[i]); + } + } + } + + /* Distribute the remaining bits to subbands with more than 1-bit per sample */ + WHILE (NE_32(L_shr(L_add(t_fx, 16384), 15) ,B)) + { + L_tmp1 = L_sub(t_fx, L_shl(B, 15)); + L_tmp2 = L_abs(L_tmp1); + + if (n>0) + { + exp1 = sub(norm_l(L_tmp2), 1); + exp2 = norm_s(n); + tmp = div_s(extract_h(L_shl(L_tmp2, exp1)), shl(n, exp2));/*15 + 15 + exp1 - 16 - exp2*/ + m_fx = shl(tmp, sub(exp2, exp1));/*Q14*/ + if (L_tmp1 < 0) + { + m_fx = negate(m_fx); + } + + t_fx = L_deposit_l(0); + n = 0; + move16(); + FOR( i = 0; i < N; i++) + { + IF (GT_32(Rsubband_w32_fx[i] , L_shl(Nb[i], 15))) + { + Rsubband_w32_fx[i] = L_msu(Rsubband_w32_fx[i], m_fx, Nb[i]); + move32(); + IF (GT_32(Rsubband_w32_fx[i] ,L_shl(Nb[i], 15))) + { + n = add(n,Nb[i]); + + t_fx = L_add(t_fx, Rsubband_w32_fx[i]); + } + ELSE + { + B = sub(B,Nb[i]); + + Rsubband_w32_fx[i] = L_shl(Nb[i], 15); + move32(); + } + } + } + } + /*In case no subband has enough bits more than 1-bit per sample, take bits off the higher subbands */ + IF (t_fx == 0) + { + FOR ( i = N-1; i >= 0; i--) + { + IF (Rsubband_w32_fx[i] > 0) + { + B = add( B, Nb[i] ); + Rsubband_w32_fx[i] = L_deposit_l(0); + IF ( B >= 0) + { + BREAK; + } + } + } + BREAK; + } + } + + /* fine redistribution of over-allocated or under-allocated bits */ + tmp = 0; + move16(); + FOR ( i = 0; i < N; i++) + { + Rsubband_fx[i] = extract_l(L_shr(Rsubband_w32_fx[i], 12)); + tmp = add(tmp, Rsubband_fx[i]); + } + + B = Bits; + B_w16_fx = shl(B, 3); + IF (GT_16(tmp ,B_w16_fx)) + { + tmp = sub(tmp, B_w16_fx); + FOR ( i = 0; i < N; i++) + { + IF (GE_16(Rsubband_fx[i], add(shl(Nb[i], 3), tmp))) + { + Rsubband_fx[i] = sub(Rsubband_fx[i], tmp); + move16(); + BREAK; + } + } + } + ELSE + { + tmp = sub(tmp, B_w16_fx); + FOR ( i = 0; i < N; i++) + { + IF (Rsubband_fx[i] > 0) + { + Rsubband_fx[i] = sub(Rsubband_fx[i], tmp); + move16(); + BREAK; + } + } + } + + /* Calcuate total used bits and initialize R to be used for Noise Filling */ + tmp = 0; + move16(); + FOR ( i = 0; i < N; i++) + { + tmp = add(tmp, Rsubband_fx[i]); + R[i] = shr(Rsubband_fx[i], 3); + move16(); + } + return shr(tmp, 3); +} +/*-------------------------------------------------------------------* + * Bit_group() + * + * bit allocation in group + *-------------------------------------------------------------------*/ +static +void Bit_group_fx ( + Word16 *y, /* i : norm of sub-band Q0*/ + Word16 start_band, /* i : start band indices Q0*/ + Word16 end_band, /* i : end band indices Q0*/ + Word16 Bits, /* i : number of allocation bits in group Q0*/ + Word16 thr, /* i : smallest bit number for allocation in group Q0*/ + Word32 *Rsubband_fx, /* o : bit allocation of sub-band Q21*/ + Word16 *fac_fx /* i : weight factor for norm of sub-band Q13*/ +) +{ + Word16 i, j, k, m, y_index[16], index[16], bit_band, band_num, norm_sum; + Word16 tmp,exp; + Word16 factor_fx; + Word32 R_temp_fx[16], R_sum_fx = 0, R_sum_org_fx = 0, Bits_avg_fx = 0; + Word32 L_tmp; + + /* initialization for bit allocation in one group*/ + tmp = 6554; + move16(); /*Q15 1/5 */ + if(EQ_16(thr,5)) + { + tmp = 6554; + move16(); /*Q15 1/5 */ + } + if(EQ_16(thr,6)) + { + tmp = 5462; + move16();/*Q15 1/6 */ + } + if(EQ_16(thr,7)) + { + tmp = 4682; + move16();/*Q15 1/7 */ + } + bit_band = mult(tmp, Bits); /*0+15-15=0, Q0 */ + band_num = sub(end_band,start_band); + + FOR( i = 0; i < band_num; i++ ) + { + y_index[i] = y[add(i,start_band)]; + move16(); + index[i] = i; + move16(); + } + + /* Rearrange norm vector in decreasing order */ + reordvct_fx(y_index, band_num, index); + /* norm vector modification */ + + factor_fx = div_s(1, band_num);/*Q15 */ + IF ( GT_16(thr,5)) + { + FOR ( i = 0; i < band_num; i++ ) + { + L_tmp = L_mult(i,factor_fx);/*Q16 */ + tmp = extract_h(L_shl(L_tmp, 13)); /*Q13 */ + tmp = sub(fac_fx[1],tmp);/*Q13 */ + L_tmp = L_mult(y_index[i],tmp);/*Q14 */ + y_index[i] = extract_h(L_shl(L_tmp, 2));/*Q0 */ + } + } + ELSE + { + FOR ( i = 0; i < band_num; i++ ) + { + L_tmp = L_mult(i,factor_fx);/*Q16 */ + tmp = extract_h(L_shl(L_tmp, 13)); /*Q13 */ + tmp = sub(fac_fx[0],tmp);/*Q13 */ + L_tmp = L_mult(y_index[i],tmp);/*Q14 */ + y_index[i] = extract_h(L_shl(L_tmp, 2));/*Q0 */ + } + } + + /* bit allocation based on modified norm */ + L_tmp = L_mult(band_num,24576);/*Q16 */ + tmp = extract_h(L_shl(L_tmp,7));/*Q7 */ + IF ( GE_16(shl(bit_band,7),tmp)) + { + FOR ( j = 0; j < band_num; j++) + { + if ( y_index[j] < 0 ) + { + y_index[j] = 0; + move16(); + } + R_temp_fx[j] = 2097152; + move16();/*Q21 = 1 move16(); */ + } + + i = sub(band_num,1); + norm_sum = 0;/*Q0 */ + FOR (k = 0; k <= i; k++) + { + norm_sum = add(norm_sum,y_index[k]); + } + + FOR (j = 0; j < band_num; j++) + { + IF(norm_sum == 0) + { + FOR (k = 0; k <= i; k++) + { + R_temp_fx[k] = L_deposit_h(0);/*Q21 */ + } + } + ELSE + { + exp = norm_s(norm_sum); + tmp = shl(norm_sum, exp);/*Q(exp) */ + tmp = div_s(16384,tmp); /*Q(15+14-exp) */ + Bits_avg_fx = L_mult(tmp, Bits);/*Q(30-exp) */ + + FOR (k = 0; k <= i; k++) + { + L_tmp = L_shl(L_deposit_l(y_index[k]),24); + L_tmp = Mult_32_32(Bits_avg_fx,L_tmp);/*Q(23-exp) */ + + R_temp_fx[k] = L_shl(L_tmp,sub(exp,2)); + move32();/*Q21 */ + } + } + + L_tmp = L_shl(L_deposit_l(thr),21);/*Q21 */ + IF ( LT_32(R_temp_fx[i],L_tmp)) + { + R_temp_fx[i] = L_deposit_h(0); + norm_sum = sub(norm_sum,y_index[i]); + i--; + } + ELSE + { + BREAK; + } + } + } + ELSE + { + FOR ( j = 0; j < bit_band; j++ ) + { + if ( y_index[j] < 0 ) + { + y_index[j] = 0; + move16(); + } + R_temp_fx[j] = 2097152; + move32();/*Q21 = 1 */ + } + + FOR ( j = bit_band; j < band_num; j++ ) + { + R_temp_fx[j] = L_deposit_l(0); + } + + norm_sum = 0; + FOR (k = 0; k < bit_band; k++) + { + norm_sum = add(norm_sum,y_index[k]); + } + + i = bit_band; + FOR (j = 0; j < bit_band; j++) + { + IF(norm_sum == 0) + { + FOR (k = 0; k < i; k++) + { + R_temp_fx[k] = L_deposit_l(0); /*Q21 */ + } + } + ELSE + { + exp = norm_s(norm_sum); + tmp = shl(norm_sum, exp);/*Q(exp) */ + tmp = div_s(16384,tmp); /*Q(15+14-exp) */ + Bits_avg_fx = L_mult(tmp, Bits);/*Q(30-exp) */ + FOR (k = 0; k < i; k++) + { + L_tmp = L_shl(L_deposit_l(y_index[k]),24); + L_tmp = Mult_32_32(Bits_avg_fx,L_tmp);/*Q(23-exp) */ + + R_temp_fx[k] = L_shl(L_tmp,sub(exp,2)); + move32();/*Q21 */ + } + } + R_sum_fx = 0; + L_tmp = L_shl(L_deposit_l(thr),21);/*Q21 */ + FOR (k = 0; k < i; k++) + { + IF (LT_32(R_temp_fx[k],L_tmp)) + { + FOR(m = k; m < i; m++) + { + norm_sum = sub(norm_sum,y_index[m]); + R_temp_fx[m] = L_deposit_l(0); /*Q21 */ + } + i = k; + BREAK; + } + ELSE + { + R_sum_fx = L_add(R_sum_fx,R_temp_fx[k]); + } + } + IF (EQ_32(R_sum_fx,R_sum_org_fx)) + { + BREAK; + } + + R_sum_org_fx = R_sum_fx; + } + } + + /* index comeback */ + FOR ( k = 0 ; k < band_num; k++ ) + { + j = index[k]; + move16(); + Rsubband_fx[add(j,start_band)] = R_temp_fx[k]; + move32(); + } + + return; + +} + +/*-------------------------------------------------------------------* + * BitAllocWB() + * + * WB bit allocation + *-------------------------------------------------------------------*/ + +Word16 BitAllocWB_fx( /* o : t Q0*/ + Word16 *y, /* i : norm of sub-vectors Q0*/ + Word16 B, /* i : number of available bits Q0*/ + Word16 N, /* i : number of sub-vectors Q0*/ + Word16 *R, /* o : bit-allocation indicator Q0*/ + Word16 *Rsubband_fx /* o : sub-band bit-allocation vector Q3*/ +) +{ + Word16 t_fx; + Word16 i, j, k, B1, B2, B3, B_saved; + Word16 Rsum_fx, Rsum_sub_fx[3]; + Word32 Ravg_sub_32_fx[3], R_diff_32_fx[2]; + Word16 factor_fx[2];/*Q13 */ + Word16 BANDS; + Word16 tmp,exp; + Word16 Rsum_sub_fx_tmp=0; /* initialize just to avoid compiler warning */ + Word32 L_tmp,L_tmp1; + Word32 Rsubband_buf[NB_SFM]; + + BANDS = N; + move16(); + if( GT_16(BANDS,SFM_N)) + { + BANDS = SFM_N; + move16(); + } + /* Init Rsubband to non-zero values for bands to be allocated bits */ + FOR (k = 0; k < BANDS; k++) + { + Rsubband_buf[k] = 2097152; + move32();/*Q21 */ + } + /* Calculate the norm sum and average of sub-band */ + Rsum_sub_fx[0] = 0; + move16(); + FOR ( j = 0; j < SFM_G1; j++ ) + { + if ( y[j] > 0 ) + { + Rsum_sub_fx_tmp = add(Rsum_sub_fx[0],y[j]); /*Q0 */ + } + if (y[j] > 0) + { + Rsum_sub_fx[0] = Rsum_sub_fx_tmp; + move16(); /*Q0 */ + } + } + Ravg_sub_32_fx[0] = L_mult(Rsum_sub_fx[0], 2048); + move32();/*Q16 0+15+1 //q15 1/16 =2048 */ + + Rsum_sub_fx[1] = 0; + move16(); + FOR ( j = SFM_G1; j < SFM_G1G2; j++ ) + { + if ( y[j] > 0 ) + { + Rsum_sub_fx_tmp = add(Rsum_sub_fx[1],y[j]); /*Q0 */ + } + if ( y[j] > 0 ) + { + Rsum_sub_fx[1] = Rsum_sub_fx_tmp; + move16();/*Q0 */ + } + } + Ravg_sub_32_fx[1] = L_mult(Rsum_sub_fx[1], 4096); /*16 0+15+1 //q15 1/8 =4096 */ + + Rsum_sub_fx[2] = 0; + move16(); + FOR ( j = SFM_G1G2; j < BANDS; j++ ) + { + if ( y[j] > 0 ) + { + Rsum_sub_fx_tmp = add(Rsum_sub_fx[2],y[j]); /*Q0 */ + } + if ( y[j] > 0 ) + { + Rsum_sub_fx[2] = Rsum_sub_fx_tmp; + move16();/*Q0 */ + } + } + tmp = div_s(1, BANDS-SFM_G1G2); /*Q15 */ + Ravg_sub_32_fx[2] = L_mult(Rsum_sub_fx[2], tmp); + move32();/*Q16 */ + + /* Bit allocation for every group */ + tmp = add(Rsum_sub_fx[0],Rsum_sub_fx[1]); + Rsum_fx = add(tmp,Rsum_sub_fx[2]);/*Q0 */ + + factor_fx[0] = 16384;/*Q13 move16(); */ + factor_fx[1] = 24576;/*Q13 move16(); */ + { + R_diff_32_fx[0] = L_sub(Ravg_sub_32_fx[0], Ravg_sub_32_fx[1]); + move32();/*Q16 */ + R_diff_32_fx[1] = L_sub(Ravg_sub_32_fx[1], Ravg_sub_32_fx[2]); + move32();/*Q16 */ + + test(); + IF ( LT_32(R_diff_32_fx[0],393216)&<_32(R_diff_32_fx[1],245760)) + { + IF(Rsum_fx == 0) + { + B1 = 0; + move16(); + B2 = 0; + move16(); + B3 = 0; + move16(); + } + ELSE + { + exp = norm_s(Rsum_fx); + tmp = shl(Rsum_fx,exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp) */ + L_tmp1 = L_mult(B,Rsum_sub_fx[0]);/*Q1 */ + L_tmp = Mult_32_16(L_tmp1,tmp);/*Q(15-exp) */ + B1 = extract_h(L_shl(L_tmp,add(exp,1)));/*Q0 */ + test(); + if(GT_32(L_tmp1,L_mult(B1,Rsum_fx))&&GE_32(L_tmp1,L_mult(add(B1,1),Rsum_fx))) + { + B1 = add(B1,1); + } + L_tmp1 = L_mult(B,Rsum_sub_fx[1]);/*Q1 */ + L_tmp = Mult_32_16(L_tmp1,tmp);/*Q(15-exp) */ + B2 = extract_h(L_shl(L_tmp,add(exp,1)));/*Q0 */ + test(); + if(GT_32(L_tmp1,L_mult(B2,Rsum_fx))&&GE_32(L_tmp1,L_mult(add(B2,1),Rsum_fx))) + { + B2 = add(B2,1); + } + L_tmp1 = L_mult(B,Rsum_sub_fx[2]);/*Q1 */ + L_tmp = Mult_32_16(L_tmp1,tmp);/*Q(15-exp) */ + B3 = extract_h(L_shl(L_tmp,add(exp,1)));/*Q0 */ + test(); + if(GT_32(L_tmp1,L_mult(B3,Rsum_fx))&&GE_32(L_tmp1,L_mult(add(B3,1),Rsum_fx))) + { + B3 = add(B3,1); + } + } + IF ( GT_32(Ravg_sub_32_fx[2],786432)) + { + B_saved = 0; + move16(); + IF ( GT_16(B1,288)) + { + B_saved = sub(B1,288); + B1 = 288; + move16(); + } + + IF ( GT_16(B2,256)) + { + tmp = sub(B2,256); + B_saved = add(B_saved,tmp); + B2 = 256; + move16(); + } + + IF ( GT_16(B3,96)) + { + tmp = sub(B3,96); + B_saved = add(B_saved,tmp); + B3 = 96; + move16(); + } + + IF ( B_saved > 0 ) + { + IF ( EQ_16(B1,288)) + { + tmp = shr(B_saved,1); + B2 = add(B2,tmp); + tmp = sub(B,B1); + B3 = sub(tmp,B2); + } + ELSE + { + tmp = shr(B_saved,1); + B1 = add(B1,tmp); + IF ( EQ_16(B2,256)) + { + tmp = sub(B,B1); + B3 = sub(tmp,B2); + } + ELSE + { + tmp = sub(B,B1); + B2 = sub(tmp,B3); + } + } + } + } + + factor_fx[0] = 16384; + move16();/*Q13 */ + factor_fx[1] = 12288; + move16();/*Q13 */ + } + ELSE + { + IF(Rsum_fx == 0) + { + B1 = 0; + move16(); + B2 = 0; + move16(); + B3 = B; + move16(); + } + ELSE + { + exp = norm_s(Rsum_fx); + tmp = shl(Rsum_fx,exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp) */ + L_tmp1 = L_mult(B,Rsum_sub_fx[0]);/*Q1 */ + L_tmp = Mult_32_16(L_tmp1,tmp);/*Q(15-exp) */ + B1 = extract_h(L_shl(L_tmp,add(exp,1)));/*Q0 */ + test(); + if(GT_32(L_tmp1,L_mult(B1,Rsum_fx))&&GE_32(L_tmp1,L_mult(add(B1,1),Rsum_fx))) + { + B1 = add(B1,1); + } + L_tmp1 = Mult_32_16(1975684956,shl(B,5));/*Q(31+5-15=21) */ + L_tmp1 = Mult_32_16(L_tmp1,shl(Rsum_sub_fx[1],7));/*Q(21+7-15=13) */ + L_tmp = Mult_32_16(L_tmp1,tmp);/*Q(27-exp) */ + B2 = extract_h(L_shl(L_tmp,sub(exp,11)));/*Q0 */ + test(); + if(GT_32(L_tmp1,L_shl(L_mult(B2,Rsum_fx),12))&&GE_32(L_add(L_tmp1,2),L_shl(L_mult(add(B2,1),Rsum_fx),12))) + { + B2 = add(B2,1); + } + tmp = sub(B,B1); + B3 = sub(tmp,B2); + } + } + } + + IF ( LT_16(Rsum_sub_fx[2],3)) + { + B2 = add(B2,B3); + B3 = 0; + move16(); + } + + /* Bit allocation in group */ + Bit_group_fx( y, 0, SFM_G1, B1, 5, Rsubband_buf, factor_fx); + Bit_group_fx( y, SFM_G1, SFM_G1G2, B2, 6, Rsubband_buf, factor_fx); + Bit_group_fx( y, SFM_G1G2, BANDS, B3, 7, Rsubband_buf, factor_fx); + FOR (i = 0; i < BANDS; i++) + { + Rsubband_fx[i] = extract_l(L_shr(Rsubband_buf[i], 18)); + } + + /* Calcuate total used bits and initialize R to be used for Noise Filling */ + L_tmp = L_deposit_l(0); + FOR( i = 0; i < N; i++) + { + L_tmp = L_add(L_tmp,Rsubband_buf[i]);/*Q21 */ + R[i] = extract_h(L_shr(Rsubband_buf[i],5));/*Q0 */ + } + t_fx = extract_h(L_shr(L_tmp, 5)); /*Q0 */ + + return (Word16)t_fx; + +} diff --git a/lib_com/bitallocsum_fx.c b/lib_com/bitallocsum_fx.c new file mode 100644 index 0000000..cb8cf09 --- /dev/null +++ b/lib_com/bitallocsum_fx.c @@ -0,0 +1,63 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* Common constants */ + +/*-------------------------------------------------------------------------- + * bitallocsum_fx() + * + * Calculate the total number of bits allocated over frame + *--------------------------------------------------------------------------*/ +void bitallocsum_fx( + Word16 *R, /* i : bit-allocation vector Q0 */ + const Word16 nb_sfm, /* i : number of sub-vectors Q0 */ + Word16 *sum, /* o : total number of bits allocated Q0 */ + Word16 *Rsubband, /* o : rate per subband Q3 */ + const Word16 v, /* i : bit rate Q0 */ + const Word16 length, /* i : length of spectrum (32 or 48 kHz samplerate) Q0 */ + const Word16 *sfmsize /* i : band length Q0 */ +) +{ + Word16 i; + Word16 total, tmp; + Word16 diff; + + total = (Word16)0; + move16(); + FOR (i = 0; i < nb_sfm; i++) + { + tmp = extract_l(L_mult0(R[i], sfmsize[i])); + Rsubband[i] = shl(tmp, 3); + move16(); + total = add(total, tmp); + } + *sum = total; + + IF ( LE_16(length, L_FRAME32k)) + { + diff = sub(v, *sum); + i = (Word16)0; + move16(); + WHILE ( diff > 0 ) + { + IF ( R[i] > 0 ) + { + Rsubband[i] = add(Rsubband[i], 8); + move16(); + diff = sub(diff, 1); + *sum = add(*sum, 1); + } + i = add(i, 1); + if ( GE_16(i, nb_sfm)) + { + i = (Word16)0; + move16(); + } + } + } + return; +} diff --git a/lib_com/bits_alloc.c b/lib_com/bits_alloc.c new file mode 100644 index 0000000..69b71c6 --- /dev/null +++ b/lib_com/bits_alloc.c @@ -0,0 +1,384 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "stl.h" +#include "options.h" +#include "rom_com_fx.h" + + +/* + * function BITS_ALLOC_init_config_acelp() + * + * description: initial configuration for ACELP + * + * return: void + */ +void BITS_ALLOC_init_config_acelp( + const Word32 bit_rate, + const Word8 narrowBand, + const Word16 nb_subfr, + ACELP_config *pConfigAcelp /*o: configuration structure of ACELP*/ +) +{ + Word8 rate_mode_index; + + + move16(); + move16(); + move16(); + rate_mode_index=(bit_rate > ACELP_9k60); + + pConfigAcelp->mode_index=rate_mode_index; + + + /*LPC: midLpc should be swithced off?*/ + pConfigAcelp->midLpc_enable = 1; + move16(); + + /*ACELP ICB config*/ + test(); + IF( (rate_mode_index==0) || narrowBand != 0 ) + { + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + pConfigAcelp->pre_emphasis = 1; + pConfigAcelp->formant_enh = 1; + pConfigAcelp->formant_enh_num = FORMANT_SHARPENING_G1; + pConfigAcelp->formant_enh_den = FORMANT_SHARPENING_G2; + pConfigAcelp->formant_tilt = 0; + pConfigAcelp->voice_tilt = 0; + } + ELSE + { + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + pConfigAcelp->pre_emphasis = 0; + pConfigAcelp->formant_enh = 1; + pConfigAcelp->formant_enh_num = FORMANT_SHARPENING_G1; + pConfigAcelp->formant_enh_den = FORMANT_SHARPENING_G2; + pConfigAcelp->formant_tilt = 1; + pConfigAcelp->voice_tilt = 1; + } + + /*Wide band @ 16kHz*/ + IF ( EQ_16(nb_subfr,NB_SUBFR16k)) + { + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + pConfigAcelp->pre_emphasis = 1; + pConfigAcelp->formant_enh = 1; + pConfigAcelp->formant_enh_num = FORMANT_SHARPENING_G1_16k; + pConfigAcelp->formant_enh_den = FORMANT_SHARPENING_G2_16k; + pConfigAcelp->formant_tilt = 0; + pConfigAcelp->voice_tilt = 2; + } + +} + + +/* + * function BITS_ALLOC_config_acelp() + * + * description: configure all acelp modes and allocate the bits + * + * return: bit demand + */ +Word16 BITS_ALLOC_config_acelp( + const Word16 bits_frame, /*i: remaining bit budget for the frame*/ + const Word16 coder_type, /*i: acelp coder type*/ + ACELP_config *pConfigAcelp, /*i/o: configuration structure of ACELP*/ + const Word16 narrowBand, + const Word16 nb_subfr +) +{ + Word16 mode_index; + Word16 band_index; + Word16 i; + Word16 remaining_bits, bits; + + + + move16(); + move16(); + move16(); + mode_index = pConfigAcelp->mode_index; + band_index = (narrowBand==0); + bits=0; + + IF ( band_index==0 ) + { + move16(); + pConfigAcelp->formant_enh = 1; + if(EQ_16(coder_type,INACTIVE)) + { + move16(); + pConfigAcelp->formant_enh = 0; + } + } + + IF ( s_and((Word16)EQ_16(band_index,1),(Word16)EQ_16(nb_subfr,4))) + { + IF(EQ_16(coder_type,INACTIVE)) + { + pConfigAcelp->pre_emphasis = 0; + move16(); + pConfigAcelp->formant_enh = 0; + move16(); + pConfigAcelp->formant_enh_num = FORMANT_SHARPENING_G1_16k; + move16(); + pConfigAcelp->voice_tilt = 1; + move16(); + pConfigAcelp->formant_tilt = 1; + move16(); + } + ELSE + { + pConfigAcelp->pre_emphasis = 1; + move16(); + pConfigAcelp->formant_enh = 1; + move16(); + pConfigAcelp->formant_enh_num = FORMANT_SHARPENING_G1; + move16(); + pConfigAcelp->voice_tilt = 0; + move16(); + pConfigAcelp->formant_tilt = 0; + move16(); + } + } + IF (EQ_16(coder_type,UNVOICED)) + { + IF(EQ_16(ACELP_GAINS_MODE[mode_index][band_index][coder_type], 6)) + { + pConfigAcelp->pitch_sharpening = 0; + move16(); + pConfigAcelp->phase_scrambling = 1; + move16(); + } + ELSE + { + pConfigAcelp->pitch_sharpening = 0; + move16(); + pConfigAcelp->phase_scrambling = 0; + move16(); + } + } + ELSE + { + pConfigAcelp->pitch_sharpening = 1; + move16(); + pConfigAcelp->phase_scrambling = 0; + move16(); + } + + IF(GT_16(coder_type,ACELP_MODE_MAX)) /* keep pitch sharpening for RF_ALLPRED mode */ + { + pConfigAcelp->pitch_sharpening = 0; + pConfigAcelp->phase_scrambling = 0; + } + + /*Allocate bits and different modes*/ + move16(); + pConfigAcelp->bpf_mode=ACELP_BPF_MODE[mode_index][band_index][coder_type]; + bits = add(bits, ACELP_BPF_BITS[pConfigAcelp->bpf_mode]); + + move16(); + move16(); + pConfigAcelp->nrg_mode=ACELP_NRG_MODE[mode_index][band_index][coder_type]; + pConfigAcelp->nrg_bits=ACELP_NRG_BITS[pConfigAcelp->nrg_mode]; + bits = add(bits, pConfigAcelp->nrg_bits); + + move16(); + pConfigAcelp->ltp_mode=ACELP_LTP_MODE[mode_index][band_index][coder_type]; + + move16(); + pConfigAcelp->ltp_bits=0; + + move16(); + pConfigAcelp->ltf_mode=ACELP_LTF_MODE[mode_index][band_index][coder_type]; + + move16(); + pConfigAcelp->ltf_bits=ACELP_LTF_BITS[pConfigAcelp->ltf_mode]; + if ( s_and((Word16)EQ_16(nb_subfr,5),(Word16)EQ_16(pConfigAcelp->ltf_bits,4))) + { + pConfigAcelp->ltf_bits = add(pConfigAcelp->ltf_bits,1); + } + bits = add(bits,pConfigAcelp->ltf_bits); + + + FOR ( i=0; igains_mode[i] = ACELP_GAINS_MODE[mode_index][band_index][coder_type]; + move16(); + + /* skip subframe 1, 3 gain encoding, and use from subframe 0, and 3, respectively */ + test(); + test(); + IF(GE_16(coder_type,ACELP_MODE_MAX)&&(EQ_16(i,1)||EQ_16(i,3))) + { + pConfigAcelp->gains_mode[i] = 0; + } + + bits = add(bits, ACELP_GAINS_BITS[pConfigAcelp->gains_mode[i]]); + + move16(); + bits = add(bits, ACELP_LTP_BITS_SFR[pConfigAcelp->ltp_mode][i]); + pConfigAcelp->ltp_bits= add( pConfigAcelp->ltp_bits,ACELP_LTP_BITS_SFR[pConfigAcelp->ltp_mode][i]); + } + + /*Innovation*/ + + if ( LT_16(bits_frame,bits)) + { + printf("Warning: bits per frame too low\n"); + return -1; + } + + IF( EQ_16(coder_type,RF_ALLPRED)) + { + set16_fx(pConfigAcelp->fixed_cdk_index, -1, nb_subfr); + } + ELSE IF ( EQ_16(coder_type,RF_GENPRED)) + { + pConfigAcelp->fixed_cdk_index[0] = 0; /* 7 bits */ + pConfigAcelp->fixed_cdk_index[1] = -1; + pConfigAcelp->fixed_cdk_index[2] = 0; /* 7 bits */ + pConfigAcelp->fixed_cdk_index[3] = -1; + pConfigAcelp->fixed_cdk_index[4] = -1; + bits = add(bits,14); + } + ELSE IF( EQ_16(coder_type,RF_NOPRED)) + { + set16_fx(pConfigAcelp->fixed_cdk_index, 0, nb_subfr); + bits = add(bits,28); + } + ELSE + { + bits = add(bits, BITS_ALLOC_adjust_acelp_fixed_cdk(sub(bits_frame,bits), pConfigAcelp->fixed_cdk_index, nb_subfr )); + } + + remaining_bits = sub(bits_frame, bits); + + /*Sanity check*/ + if (remaining_bits<0) + { + move16(); + bits = -1; + } + + + return(bits); +} + + +static +Word16 BITS_ALLOC_adjust_generic( + const Word16 bits_frame, /*i: bit budget*/ + Word16 *fixed_cdk_index, + const Word16 nb_subfr, + const Word16 *pulseconfigbits, + const Word16 pulseconfig_size +) +{ + Word16 bits_subframe2, inb_subfr; + Word16 sfr, k, bitsused, bits_currsubframe; + + bits_subframe2 = bits_frame; + move16(); + inb_subfr = 8192/*1.0f/NB_SUBFR Q15*/; + move16(); + if ( EQ_16(nb_subfr,NB_SUBFR16k)) + { + inb_subfr = 6554/*1.0f/NB_SUBFR16k Q15*/; + move16(); + } + + IF ( LT_16(bits_subframe2, i_mult2(pulseconfigbits[0], nb_subfr))) /* not in final code - not instrumented */ + { + return add(bits_frame,1); /* Not enough bits for lowest mode. -> trigger alarm*/ + } + + /* search cdk-index for first subframe */ + FOR (k=0; k bits_subframe2) + { + k = sub(k,1); /* previous mode did not exceed bit-budget */ + BREAK; + } + } + + if (i_mult2(pulseconfigbits[k], nb_subfr) > bits_subframe2) + { + k = sub(k,1); /* previous mode did not exceed bit-budget */ + } + + move16(); + fixed_cdk_index[0] = k; + bitsused = i_mult2(pulseconfigbits[k], nb_subfr); + + FOR (sfr=1; sfr < nb_subfr; sfr++) + { + /*bits_currsubframe = (int)(((float)sfr+1.0f)*bits_subframe) - bitsused;*/ + bits_currsubframe = sub(add(i_mult2(sfr, bits_subframe2), bits_subframe2), bitsused); + + /* try increasing mode while below threshold */ + WHILE ( (LT_16(k, pulseconfig_size-1))&&(LE_16(i_mult2(pulseconfigbits[add(k,1)],nb_subfr),bits_currsubframe))) + { + test(); + k = add(k,1); + } + + /* try decreasing mode until below threshold */ + WHILE (i_mult2(pulseconfigbits[k], nb_subfr) > bits_currsubframe) + { + k = sub(k,1); + + IF (k == 0) + { + BREAK; + } + } + + /* store mode */ + move16(); + fixed_cdk_index[sfr] = k; + bitsused = add(bitsused, i_mult2(pulseconfigbits[k], nb_subfr)); + } + + return mult_r(bitsused, inb_subfr); +} + +Word16 BITS_ALLOC_adjust_acelp_fixed_cdk( + const Word16 bits_frame, /*i: bit budget*/ + Word16 *fixed_cdk_index, + const Word16 nb_subfr +) +{ + Word16 bitsused; + + + bitsused = BITS_ALLOC_adjust_generic(bits_frame, fixed_cdk_index, nb_subfr, ACELP_CDK_BITS, ACELP_FIXED_CDK_NB); + + + return bitsused; +} + diff --git a/lib_com/bitstream_fx.c b/lib_com/bitstream_fx.c new file mode 100644 index 0000000..c734eb4 --- /dev/null +++ b/lib_com/bitstream_fx.c @@ -0,0 +1,2589 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "stl.h" +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "options.h" +#include "basop_util.h" +#include "rom_com_fx.h" +#include "mime.h" +#ifdef DEBUGGING + /*-------------------------------------------------------------------* + * Global variables + *--------------------------------------------------------------------*/ + +int16_t FEC_seed = 12558; /* Seed for random FEC generator */ +float FEC_random = 0; /* FEC rate in percent (for simulation of FEC) */ +FILE* FEC_pattern = NULL; /* FEC pattern file (for simulation of FEC) */ +/*-------------------------------------------------------------------* + * file_read_FECpattern() + * + * Simulate packet losses by reading FEC pattern from external file + *-------------------------------------------------------------------*/ + +static int16_t file_read_FECpattern(void) +{ + int16_t bfi = 0; + + /* FEC pattern file provided */ + if (FEC_pattern != NULL) + { + int16_t tmp = 0; + if (fread(&tmp, sizeof(int16_t), 1, FEC_pattern) != 1) + { + if (feof(FEC_pattern) != 0) + { + tmp = 0; + fseek(FEC_pattern, 0L, SEEK_SET); + } + else + { + fprintf(stderr, "\nError reading the FEC pattern file !"); + exit(-1); + } + } + + if (tmp == 2609 || tmp == 1 || tmp == SYNC_BAD_FRAME) + { + bfi = 1; + } + else + { + bfi = 0; + } + } + + /* random FEC simulation requested */ + else if (FEC_random > 0) + { + float ftmp = (float)/*own_random*/Random(&FEC_seed) + 32768.0f; + if (ftmp <= FEC_random / 100.0f * 65535.0f) + { + bfi = 1; + } + else + { + bfi = 0; + } + } + + return bfi; +} +#endif +/*-------------------------------------------------------------------* +* pack_bit() +* +* insert a bit into packed octet +*-------------------------------------------------------------------*/ +static void pack_bit( + const Word16 bit, /* i: bit to be packed */ + UWord8 **pt, /* i/o: pointer to octet array into which bit will be placed */ + UWord8 *omask /* i/o: output mask to indicate where in the octet the bit is to be written */ +) +{ + if (*omask == 0x80) + { + **pt = 0; + } + if (bit != 0) + { + **pt = **pt | *omask; + } + *omask >>= 1; + if (*omask == 0) + { + *omask = 0x80; + (*pt)++; + } + + return; +} + +/*-------------------------------------------------------------------* +* unpack_bit() +* +* unpack a bit from packed octet +*-------------------------------------------------------------------*/ +static Word16 unpack_bit( + UWord8 **pt, /* i/o: pointer to octet array from which bit will be read */ + UWord8 *mask /* i/o: mask to indicate the bit in the octet */ +) +{ + Word16 bit; + + bit = (**pt & *mask) != 0; + *mask >>= 1; + if (*mask == 0) + { + *mask = 0x80; + (*pt)++; + } + return bit; +} + +/*-------------------------------------------------------------------* +* rate2AMRWB_IOmode() +* +* lookup AMRWB IO mode +*-------------------------------------------------------------------*/ +static Word16 rate2AMRWB_IOmode( + Word32 rate /* i: bit rate */ +) +{ + switch ( rate ) + { + /* EVS AMR-WB IO modes */ + case SID_1k75 : + return AMRWB_IO_SID; + case ACELP_6k60 : + return AMRWB_IO_6600; + case ACELP_8k85 : + return AMRWB_IO_8850; + case ACELP_12k65 : + return AMRWB_IO_1265; + case ACELP_14k25 : + return AMRWB_IO_1425; + case ACELP_15k85 : + return AMRWB_IO_1585; + case ACELP_18k25 : + return AMRWB_IO_1825; + case ACELP_19k85 : + return AMRWB_IO_1985; + case ACELP_23k05 : + return AMRWB_IO_2305; + case ACELP_23k85 : + return AMRWB_IO_2385; + default: + return -1; + } +} + +/*-------------------------------------------------------------------* +* rate2EVSmode() +* +* lookup EVS mode +*-------------------------------------------------------------------*/ +static Word16 rate2EVSmode( + Word32 rate /* i: bit rate */ +) +{ + switch ( rate ) + { + /* EVS Primary modes */ + case FRAME_NO_DATA : + return NO_DATA_TYPE; + case SID_2k40 : + return PRIMARY_SID; + case PPP_NELP_2k80 : + return PRIMARY_2800; + case ACELP_7k20 : + return PRIMARY_7200; + case ACELP_8k00 : + return PRIMARY_8000; + case ACELP_9k60 : + return PRIMARY_9600; + case ACELP_13k20 : + return PRIMARY_13200; + case ACELP_16k40 : + return PRIMARY_16400; + case ACELP_24k40 : + return PRIMARY_24400; + case ACELP_32k : + return PRIMARY_32000; + case ACELP_48k : + return PRIMARY_48000; + case ACELP_64k : + return PRIMARY_64000; + case HQ_96k : + return PRIMARY_96000; + case HQ_128k : + return PRIMARY_128000; + default : + return rate2AMRWB_IOmode(rate); + } +} + +/*-------------------------------------------------------------------* + * push_indice_fx( ) + * + * Push a new indice into the buffer + *-------------------------------------------------------------------*/ + +void push_indice_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 id, /* i : ID of the indice */ + UWord16 value, /* i : value of the quantized indice */ + Word16 nb_bits /* i : number of bits used to quantize the indice */ +) +{ + Word16 i; + + + IF ( EQ_16(st_fx->last_ind_fx, id)) + { + /* indice with the same name as the previous one */ + i = st_fx->next_ind_fx; + } + ELSE + { + /* new indice - find an empty slot in the list */ + i = id; + move16(); + WHILE (NE_16(st_fx->ind_list_fx[i].nb_bits, -1)) + { + i = add(i, 1); + } + } + + /* store the values in the list */ + st_fx->ind_list_fx[i].value = value; + move16(); + st_fx->ind_list_fx[i].nb_bits = nb_bits; + move16(); + + /* updates */ + st_fx->next_ind_fx = add(i, 1); + st_fx->last_ind_fx = id; + move16(); + st_fx->nb_bits_tot_fx = add(st_fx->nb_bits_tot_fx, nb_bits); + + return; +} + +/*-------------------------------------------------------------------* + * push_next_indice_fx() * + * Push a new indice into the buffer at the next position + *-------------------------------------------------------------------*/ + +void push_next_indice_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + UWord16 value, /* i : value of the quantized indice */ + Word16 nb_bits /* i : number of bits used to quantize the indice */ +) +{ + + /* store the values in the list */ + st_fx->ind_list_fx[st_fx->next_ind_fx].value = value; + move16(); + st_fx->ind_list_fx[st_fx->next_ind_fx].nb_bits = nb_bits; + move16(); + st_fx->next_ind_fx = add(st_fx->next_ind_fx, 1); + + + /* update the total number of bits already written */ + st_fx->nb_bits_tot_fx = add(st_fx->nb_bits_tot_fx, nb_bits); + + return; +} + + +/*-------------------------------------------------------------------* + * push_next_bits_fx() + * Push a bit buffer into the buffer at the next position + *-------------------------------------------------------------------*/ + +void push_next_bits_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 bits[], /* i : bit buffer to pack, sequence of single bits */ + Word16 nb_bits /* i : number of bits to pack */ +) +{ + UWord16 code; + Word16 i, nb_bits_m15; + Indice_fx *ptr; + + ptr = &st_fx->ind_list_fx[st_fx->next_ind_fx]; + nb_bits_m15 = sub(nb_bits, 15); + i = 0; + move16(); + IF (nb_bits_m15 > 0) + { + FOR (; ivalue = code; + move16(); + ptr->nb_bits = 16; + move16(); + ++ptr; + } + } + IF (LT_16(i, nb_bits)) + { + FOR (; ivalue = bits[i]; + move16(); + ptr->nb_bits = 1; + move16(); + ++ptr; + } + } + st_fx->next_ind_fx = (Word16)(ptr - st_fx->ind_list_fx); + st_fx->nb_bits_tot_fx = add(st_fx->nb_bits_tot_fx, nb_bits); +} + +/*-------------------------------------------------------------------* + * get_next_indice_fx( ) + * + * Get the next indice from the buffer + *-------------------------------------------------------------------*/ + +UWord16 get_next_indice_fx( /* o : value of the indice */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 nb_bits /* i : number of bits that were used to quantize the indice */ +) +{ + UWord16 value; + Word16 i; + + assert(nb_bits <= 16); + value = 0; + move16(); + + /* detect corrupted bitstream */ + IF( GT_16(add(st_fx->next_bit_pos_fx,nb_bits),st_fx->total_num_bits)) + { + st_fx->BER_detect = 1; + move16(); + return(0); + } + + FOR (i = 0; i < nb_bits; i++) + { + value = lshl(value, 1); + value = add(value, st_fx->bit_stream_fx[st_fx->next_bit_pos_fx+i]); + } + + /* update the position in the bitstream */ + st_fx->next_bit_pos_fx = add(st_fx->next_bit_pos_fx, nb_bits); + return value; +} + +/*-------------------------------------------------------------------* + * get_next_indice_1_fx( ) + * + * Get the next 1-bit indice from the buffer + *-------------------------------------------------------------------*/ + +UWord16 get_next_indice_1_fx( /* o : value of the indice */ + Decoder_State_fx *st_fx /* i/o: decoder state structure */ +) +{ + /* detect corrupted bitstream */ + test(); + test(); + test(); + IF( ( GT_16(add(st_fx->next_bit_pos_fx,1),st_fx->total_num_bits)&&EQ_16(st_fx->codec_mode,MODE1))|| + ( GT_16(add(st_fx->next_bit_pos_fx,1),add(st_fx->total_num_bits,2*8)) && EQ_16(st_fx->codec_mode,MODE2)) /* add two zero bytes for arithmetic coder flush */ + ) + { + st_fx->BER_detect = 1; + move16(); + return(0); + } + + return st_fx->bit_stream_fx[st_fx->next_bit_pos_fx++]; +} + +/*-------------------------------------------------------------------* + * get_next_indice_tmp() + * + * update the total number of bits and the position in the bitstream + *-------------------------------------------------------------------*/ + +void get_next_indice_tmp_fx( + Decoder_State_fx *st_fx, /* o : decoder state structure */ + Word16 nb_bits /* i : number of bits that were used to quantize the indice */ +) +{ + /* update the position in the bitstream */ + st_fx->next_bit_pos_fx = add(st_fx->next_bit_pos_fx, nb_bits); +} + +/*-------------------------------------------------------------------* + * get_indice_fx( ) + * + * Get indice at specific position in the buffer + *-------------------------------------------------------------------*/ + +UWord16 get_indice_fx( /* o : value of the indice */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 pos, /* i : absolute position in the bitstream (update after the read) */ + Word16 nb_bits /* i : number of bits that were used to quantize the indice */ +) +{ + UWord16 value; + Word16 i; + + assert(nb_bits <= 16); + + /* detect corrupted bitstream */ + IF( GT_16(add(pos,nb_bits),st_fx->total_num_bits)) + { + st_fx->BER_detect = 1; + move16(); + return(0); + } + + value = 0; + move16(); + FOR (i = 0; i < nb_bits; i++) + { + value = lshl(value, 1); + value = add(value, st_fx->bit_stream_fx[pos+i]); + } + + return value; +} + +/*-------------------------------------------------------------------* + * get_indice_1_fx( ) + * + * Get a 1-bit indice at specific position in the buffer + *-------------------------------------------------------------------*/ + +UWord16 get_indice_1_fx( /* o : value of the indice */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 pos /* i : absolute position in the bitstream (update after the read) */ +) +{ + /* detect corrupted bitstream */ + IF( GT_16(add(pos,1),st_fx->total_num_bits)) + { + st_fx->BER_detect = 1; + move16(); + return(0); + } + + return st_fx->bit_stream_fx[pos]; +} + +/*-------------------------------------------------------------------* + * reset_indices_enc_fx() + * + * Reset the buffer of indices + *-------------------------------------------------------------------*/ + +void reset_indices_enc_fx( + Encoder_State_fx *st_fx +) +{ + Word16 i; + + st_fx->nb_bits_tot_fx = 0; + move16(); + st_fx->next_ind_fx = 0; + move16(); + st_fx->last_ind_fx = -1; + move16(); + + FOR (i=0; iind_list_fx[i].nb_bits = -1; + move16(); + } + + return; +} + +/*-------------------------------------------------------------------* + * reset_indices_dec_fx() + * + * Reset the buffer of decoder indices + *-------------------------------------------------------------------*/ + +void reset_indices_dec_fx( + Decoder_State_fx *st_fx +) +{ + st_fx->next_bit_pos_fx = 0; + move16(); + + return; +} + + +/*-------------------------------------------------------------------* + * write_indices_fx() + * + * Write the buffer of indices to a file + *-------------------------------------------------------------------*/ + +void write_indices_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + FILE *file /* i : output bitstream file */ + , UWord8 *pFrame, /* i: byte array with bit packet and byte aligned coded speech data */ + Word16 pFrame_size /* i: size of the binary encoded access unit [bits] */ +) +{ + Word16 i, k; + Word16 stream[2+MAX_BITS_PER_FRAME], *pt_stream; + Word32 mask; + UWord8 header; + + if( st_fx->bitstreamformat == G192 ) + { + /*-----------------------------------------------------------------* + * Encode Sync Header and Frame Length + *-----------------------------------------------------------------*/ + pt_stream = stream; + for (i=0; i<(2 + MAX_BITS_PER_FRAME); ++i) + { + stream[i] = 0; + } + *pt_stream++ = (Word16)SYNC_GOOD_FRAME; + *pt_stream++ = st_fx->nb_bits_tot_fx; + + /*----------------------------------------------------------------* + * Bitstream packing (conversion of individual indices into a serial stream) + * Writing the serial stream into file + *----------------------------------------------------------------*/ + + for (i=0; iind_list_fx[i].nb_bits != -1) + { + /* mask from MSB to LSB */ + mask = 1 << (st_fx->ind_list_fx[i].nb_bits - 1); + + /* write bit by bit */ + for (k=0; k < st_fx->ind_list_fx[i].nb_bits; k++) + { + if ( st_fx->ind_list_fx[i].value & mask ) + { + *pt_stream++ = G192_BIN1; + } + else + { + *pt_stream++ = G192_BIN0; + } + + mask >>= 1; + } + } + } + + } + else + { + /* Create and write ToC header */ + /* qbit always set to 1 on encoder side for AMRWBIO , no qbit in use for EVS, but set to 0(bad) */ + header = (UWord8)(st_fx->Opt_AMR_WB_fx << 5 | st_fx->Opt_AMR_WB_fx << 4 | rate2EVSmode(st_fx->nb_bits_tot_fx * 50)); + fwrite( &header, sizeof(UWord8), 1, file ); + /* Write speech bits */ + fwrite( pFrame, sizeof(UWord8), (pFrame_size + 7)>>3, file ); + } + + /* Clearing of indices */ + FOR (i=0; iind_list_fx[i].nb_bits = -1; + move16(); + } + + + if( st_fx->bitstreamformat == G192 ) + { + /* write the serial stream into file */ + fwrite( stream, sizeof(unsigned short), 2+stream[1], file ); + } + /* reset index pointers */ + st_fx->nb_bits_tot_fx = 0; + st_fx->next_ind_fx = 0; + st_fx->last_ind_fx = -1; + + return; +} + +/*-------------------------------------------------------------------* + * indices_to_serial() + * + * pack indices into serialized payload format + *-------------------------------------------------------------------*/ + +void indices_to_serial( + const Encoder_State_fx *st_fx, /* i: encoder state structure */ + UWord8 *pFrame, /* o: byte array with bit packet and byte aligned coded speech data */ + Word16 *pFrame_size /* o: size of the binary encoded access unit [bits] */ +) +{ + Word16 i, k, j; + Word16 cmi = 0, core_mode=0; + Word32 mask; + Word16 amrwb_bits[(ACELP_23k85 / 50)]; + UWord8 omask= 0x80; + UWord8 *pt_pFrame=pFrame; + + if ( st_fx->Opt_AMR_WB_fx ) + { + cmi = rate2EVSmode(st_fx->total_brate_fx); + core_mode = rate2EVSmode(st_fx->nb_bits_tot_fx * 50); + + j=0; + for (i=0; iind_list_fx[i].nb_bits != -1) + { + /* mask from MSB to LSB */ + mask = 1 << (st_fx->ind_list_fx[i].nb_bits - 1); + + /* temporarily save bit */ + for (k=0; k < st_fx->ind_list_fx[i].nb_bits; k++) + { + amrwb_bits[j++] = (st_fx->ind_list_fx[i].value & mask) > 0; + mask >>= 1; + } + } + } + } + + *pFrame_size = st_fx->nb_bits_tot_fx; + + /*----------------------------------------------------------------* + * Bitstream packing (conversion of individual indices into a serial stream) + *----------------------------------------------------------------*/ + j=0; + for (i=0; iind_list_fx[i].nb_bits != -1) + { + /* mask from MSB to LSB */ + mask = 1 << (st_fx->ind_list_fx[i].nb_bits - 1); + + /* write bit by bit */ + for (k=0; k < st_fx->ind_list_fx[i].nb_bits; k++) + { + if (st_fx->Opt_AMR_WB_fx ) + { + pack_bit(amrwb_bits[sort_ptr[core_mode][j++]], &pt_pFrame, &omask); + } + else + { + pack_bit(st_fx->ind_list_fx[i].value & mask, &pt_pFrame, &omask); + j++; + } + mask >>= 1; + } + } + } + + if ( st_fx->Opt_AMR_WB_fx && core_mode == AMRWB_IO_SID) /* SID UPD frame always written now .... */ + { + /* insert STI bit and CMI */ + pack_bit(1, &pt_pFrame, &omask); + for (mask=0x08; mask>0; mask >>= 1) + { + pack_bit(cmi & mask, &pt_pFrame, &omask); + } + } +} + + +/*-------------------------------------------------------------------* + * indices_to_serial_generic() + * + * pack indices into serialized payload format + *-------------------------------------------------------------------*/ + +void indices_to_serial_generic( + const Indice_fx *ind_list, /* i: indices list */ + const Word16 num_indices, /* i: number of indices to write */ + UWord8 *pFrame, /* o: byte array with bit packet and byte aligned coded speech data */ + Word16 *pFrame_size /* i/o: number of bits in the binary encoded access unit [bits] */ +) +{ + Word16 i, k, j; + Word32 mask; + UWord8 omask; + UWord8 *pt_pFrame = pFrame; + Word16 nb_bits_tot; + + nb_bits_tot = 0; + move16(); + omask = (0x80 >> (*pFrame_size & 0x7)); + pt_pFrame += shr(*pFrame_size, 3); + + /*----------------------------------------------------------------* + * Bitstream packing (conversion of individual indices into a serial stream) + *----------------------------------------------------------------*/ + j=0; + move16(); + for (i=0; i>= 1; + } + nb_bits_tot = add(nb_bits_tot, ind_list[i].nb_bits); + } + } + + *pFrame_size = add(*pFrame_size, nb_bits_tot); + + return; +} + + +static void decoder_selectCodec( + Decoder_State_fx *st, /* i/o: decoder state structure */ + const Word32 total_brate, /* i : total bitrate */ + const Word16 bit0 +) +{ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + /* check if we are in AMR-WB IO mode */ + IF( EQ_32(total_brate, SID_1k75)|| + EQ_32(total_brate, ACELP_6k60) || EQ_32(total_brate, ACELP_8k85) || EQ_32(total_brate, ACELP_12k65) || + EQ_32(total_brate, ACELP_14k25) || EQ_32(total_brate, ACELP_15k85) || EQ_32(total_brate, ACELP_18k25) || + EQ_32(total_brate, ACELP_19k85) || EQ_32(total_brate, ACELP_23k05) || EQ_32(total_brate, ACELP_23k85) ) + { + st->Opt_AMR_WB_fx = 1; + move16(); + } + ELSE IF ( NE_32(total_brate, FRAME_NO_DATA)) + { + st->Opt_AMR_WB_fx = 0; + move16(); + } + + /* select MODE1 or MODE2 */ + IF (st->Opt_AMR_WB_fx) + { + st->codec_mode = MODE1; + move16();/**/ + } + ELSE + { + SWITCH ( total_brate ) + { + case 0: + st->codec_mode = st->last_codec_mode; + move16(); + BREAK; + case 2400: + st->codec_mode = st->last_codec_mode; + move16(); + BREAK; + case 2800: + st->codec_mode = MODE1; + move16(); + BREAK; + case 7200: + st->codec_mode = MODE1; + move16(); + BREAK; + case 8000: + st->codec_mode = MODE1; + move16(); + BREAK; + case 9600: + st->codec_mode = MODE2; + move16(); + BREAK; + case 13200: + st->codec_mode = MODE1; + move16(); + BREAK; + case 16400: + st->codec_mode = MODE2; + move16(); + BREAK; + case 24400: + st->codec_mode = MODE2; + move16(); + BREAK; + case 32000: + st->codec_mode = MODE1; + move16(); + BREAK; + case 48000: + st->codec_mode = MODE2; + move16(); + BREAK; + case 64000: + st->codec_mode = MODE1; + move16(); + BREAK; + case 96000: + st->codec_mode = MODE2; + move16(); + BREAK; + case 128000: + st->codec_mode = MODE2; + move16(); + BREAK; + default : + /* validate that total_brate (derived from RTP packet or a file header) is one of the defined bit rates */ + st->codec_mode = st->last_codec_mode; + st->bfi_fx = 1; + move16(); + move16(); + BREAK; + } + } + + IF ( st->ini_frame_fx == 0 ) + { + IF(EQ_16(st->codec_mode,-1)) + { + st->codec_mode = MODE1; + move16(); + } + st->last_codec_mode = st->codec_mode; + move16(); + } + + /* set SID/CNG type */ + IF ( EQ_32(total_brate,SID_2k40)) + { + IF ( bit0 == G192_BIN0 ) + { + st->cng_type_fx = LP_CNG; + move16(); + + /* force MODE1 when selecting LP_CNG */ + st->codec_mode = MODE1; + move16(); + } + ELSE + { + st->cng_type_fx = FD_CNG; + test(); + if ( EQ_16(st->last_codec_mode, MODE2)&&EQ_32(st->last_total_brate_fx,13200)) + { + st->codec_mode = MODE1; + move16(); + } + } + st->last_cng_type_fx = st->cng_type_fx; /* CNG type switching at the first correctly received SID frame */ + } + + + return; +} + + + + +void dec_prm_core(Decoder_State_fx *st) +{ + Word16 n, frame_size_index, num_bits; + UWord16 lsb; + Word32 L_tmp; + + frame_size_index = -1; + move16(); + st->core_fx = -1; + move16(); + + IF (EQ_32(st->total_brate_fx, FRAME_NO_DATA)) + { + st->m_frame_type = ZERO_FRAME; + move16(); + } + ELSE IF (EQ_32(st->total_brate_fx, SID_2k40)) + { + st->m_frame_type = SID_FRAME; + move16(); + } + ELSE + { + st->m_frame_type = ACTIVE_FRAME; + move16(); + Mpy_32_16_ss(st->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + num_bits = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + assert(num_bits == st->total_brate_fx/50); + FOR (n=0; nbwidth_fx = get_next_indice_fx(st, FrameSizeConfig[frame_size_index].bandwidth_bits); + + st->bwidth_fx = add(st->bwidth_fx, FrameSizeConfig[frame_size_index].bandwidth_min); + + if (GT_16(st->bwidth_fx, FB)) + { + st->bwidth_fx = FB; + move16(); + st->BER_detect = 1; + move16(); + } + + if (GT_16(st->bwidth_fx, SWB)&<_32(st->total_brate_fx,ACELP_16k40)) + { + st->bwidth_fx = SWB; + move16(); + st->BER_detect = 1; + move16(); + } + + /* Skip reserved bit */ + get_next_indice_tmp_fx(st, FrameSizeConfig[frame_size_index].reserved_bits); + + IF (get_next_indice_1_fx(st) != 0) /* TCX */ + { + st->core_fx = TCX_20_CORE; + move16(); + if (get_next_indice_1_fx(st) != 0) + { + st->core_fx = HQ_CORE; + move16(); + } + } + ELSE /* ACELP */ + { + st->core_fx = ACELP_CORE; + move16(); + } + } +} + +/*-----------------------------------------------------------------* + * decision_matrix_core_dec() + * + * Read core mode signalling bits from the bitstream + * Set st->core, and st->bwidth if signalled together with the core. + *-----------------------------------------------------------------*/ + +void decision_matrix_core_dec( + Decoder_State_fx *st /* i/o: decoder state structure */ +) +{ + Word16 start_idx; + Word32 ind; + Word16 nBits; + + assert(st->bfi_fx != 1); + + st->core_fx = -1; + move16(); + st->bwidth_fx = -1; + move16(); + + test(); + IF ( EQ_32(st->total_brate_fx, FRAME_NO_DATA)||EQ_32(st->total_brate_fx,SID_2k40)) + { + st->core_fx = ACELP_CORE; + move16(); + } + /* SC-VBR */ + ELSE IF ( st->total_brate_fx == PPP_NELP_2k80 ) + { + st->core_fx = ACELP_CORE; + move16(); + return; + } + + /*---------------------------------------------------------------------* + * ACELP/HQ core selection + *---------------------------------------------------------------------*/ + + test(); + IF ( LT_32(st->total_brate_fx, ACELP_24k40)) + { + st->core_fx = ACELP_CORE; + move16(); + } + ELSE IF ( GE_32(st->total_brate_fx, ACELP_24k40)&&LE_32(st->total_brate_fx,ACELP_64k)) + { + /* read the ACELP/HQ core selection bit */ + st->core_fx = imult1616(get_next_indice_fx( st, 1 ), HQ_CORE); + } + ELSE + { + st->core_fx = HQ_CORE; + move16(); + } + + /*-----------------------------------------------------------------* + * Read ACELP signalling bits from the bitstream + *-----------------------------------------------------------------*/ + + IF ( EQ_16(st->core_fx, ACELP_CORE)) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + start_idx = 0; + move16(); + WHILE ( NE_32(acelp_sig_tbl[start_idx], st->total_brate_fx)) + { + start_idx = add(start_idx, 1); + } + + /* skip the bitrate */ + start_idx = add(start_idx, 1); + + /* retrieve the number of bits */ + nBits = extract_l(acelp_sig_tbl[start_idx]); + start_idx = add(start_idx, 1); + + /* retrieve the signalling indice */ + ind = acelp_sig_tbl[add(start_idx, get_next_indice_fx( st, nBits ))]; + st->bwidth_fx = extract_l(L_and(L_shr(ind, 3), 0x7)); + + /* convert signalling indice into signalling information */ + if ( EQ_32(L_and(ind, 0x7), LR_MDCT)) + { + st->core_fx = HQ_CORE; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Read HQ signalling bits from the bitstream + * Set HQ core type + *-----------------------------------------------------------------*/ + + IF ( EQ_16(st->core_fx, HQ_CORE)) + { + /* read the HQ/TCX core switching flag */ + if ( get_next_indice_fx( st, 1 ) != 0 ) + { + st->core_fx = TCX_20_CORE; + move16(); + } + + /* For TCX: read/set band-width (needed for different I/O sampling rate support) */ + test(); + IF( EQ_16(st->core_fx, TCX_20_CORE)&>_32(st->total_brate_fx,ACELP_16k40)) + { + ind = get_next_indice_fx( st, 2 ); + + IF( ind == 0 ) + { + st->bwidth_fx = NB; + move16(); + } + ELSE IF( EQ_32(ind, 1)) + { + st->bwidth_fx = WB; + move16(); + } + ELSE IF( EQ_32(ind, 2)) + { + st->bwidth_fx = SWB; + move16(); + } + ELSE + { + st->bwidth_fx = FB; + move16(); + } + } + } + + return; +} + +/*-------------------------------------------------------------------* + * mdct_switching_dec() + * + * Set up MDCT core switching if indicated in the bit stream + *-------------------------------------------------------------------*/ + +static void mdct_switching_dec( + Decoder_State_fx *st /* i/o: decoder state structure */ +) +{ + IF (st->Opt_AMR_WB_fx != 0) + { + return; + } + + test(); + test(); + IF (EQ_32(st->total_brate_fx, ACELP_13k20)||EQ_32(st->total_brate_fx,ACELP_32k)) + { + st->mdct_sw_enable = MODE1; + move16(); + } + ELSE IF (LE_32(ACELP_16k40, st->total_brate_fx)&&LE_32(st->total_brate_fx,ACELP_24k40)) + { + st->mdct_sw_enable = MODE2; + move16(); + } + + test(); + test(); + IF ( EQ_16(st->codec_mode, MODE1)&&EQ_16(st->mdct_sw_enable,MODE1)) + { + /* Read ahead core mode signaling */ + Word16 next_bit_pos_save; + Word16 core_save; + Word16 bwidth_save; + + next_bit_pos_save = st->next_bit_pos_fx; + move16(); + core_save = st->core_fx; + move16(); + bwidth_save = st->bwidth_fx; + move16(); + + decision_matrix_core_dec(st); /* sets st->core */ + + IF (EQ_16(st->core_fx, TCX_20_CORE)) + { + /* Trigger TCX */ + st->codec_mode = MODE2; + move16(); + st->mdct_sw = MODE1; + move16(); + } + ELSE + { + /* Rewind bitstream */ + st->next_bit_pos_fx = next_bit_pos_save; + move16(); + IF (st->bfi_fx != 0) + { + st->core_fx = core_save; + move16(); + st->bwidth_fx = bwidth_save; + move16(); + } + } + } + ELSE IF (EQ_16(st->codec_mode, MODE2)&&EQ_16(st->mdct_sw_enable,MODE2)) + { + /* Read ahead core mode signaling */ + Word16 next_bit_pos_save; + Word16 core_save; + Word16 bwidth_save; + + next_bit_pos_save = st->next_bit_pos_fx; + move16(); + core_save = st->core_fx; + move16(); + bwidth_save = st->bwidth_fx; + move16(); + + dec_prm_core(st); /* sets st->core */ + + IF (EQ_16(st->core_fx, HQ_CORE)) + { + /* Trigger HQ_CORE */ + st->codec_mode = MODE1; + move16(); + st->mdct_sw = MODE2; + move16(); + } + ELSE + { + /* Rewind bitstream */ + st->next_bit_pos_fx = next_bit_pos_save; + move16(); + IF (st->bfi_fx != 0) + { + st->core_fx = core_save; + move16(); + } + /* always reset bwidth, to not interfere with BER logic */ + st->bwidth_fx = bwidth_save; + move16(); + } + } +} + +/*-------------------------------------------------------------------* + * BRATE2IDX_fx() + * + * Convert Bitrate to Index Value + *-------------------------------------------------------------------*/ + +Word16 BRATE2IDX_fx(Word32 brate) +{ + Word32 L_temp; + Word32 L_idx; +#define START 9 + extern const Word16 bit_rates_div50[]; + + /* This is a Fast Bit Rate Value to Index Value Binary Search */ + L_temp = L_msu0(brate, bit_rates_div50[START], 50); + L_temp = L_min(6, L_max(-6, L_temp)); + L_idx = L_add(L_temp, START); + L_temp = L_msu0(brate, bit_rates_div50[L_idx], 50); + L_temp = L_min(3, L_max(-3, L_temp)); + L_idx = L_add(L_temp, L_idx); + L_temp = L_msu0(brate, bit_rates_div50[L_idx], 50); + L_temp = L_min(1, L_max(-2, L_temp)); + L_idx = L_add(L_temp, L_idx); + L_temp = L_msu0(brate, bit_rates_div50[L_idx], 50); + if (L_temp != 0) L_idx = L_add(L_idx, 1); + return (Word16)L_idx; +} + + +/*-------------------------------------------------------------------* + * BRATE2IDX16k_fx() + * + * Convert Bitrate to Index Value + *-------------------------------------------------------------------*/ + +Word16 BRATE2IDX16k_fx(Word32 brate) +{ + Word32 L_temp, L_idx; +#define START_16K 5 + extern const Word16 bit_rates_16k_div50[]; + + if(EQ_32(brate,ACELP_16k40)) + { + brate=ACELP_14k80; + } + + /* This is a Fast Bit Rate Value to Index Value Binary Search */ + L_temp = L_msu0(brate, bit_rates_16k_div50[START_16K], 50); + L_temp = L_min(3, L_max(-3, L_temp)); + L_idx = L_add(L_temp, START_16K); + L_temp = L_msu0(brate, bit_rates_16k_div50[L_idx], 50); + L_temp = L_min(2, L_max(-2, L_temp)); + L_idx = L_add(L_temp, L_idx); + L_temp = L_msu0(brate, bit_rates_16k_div50[L_idx], 50); + L_temp = L_min(1, L_max(-1, L_temp)); + L_idx = L_add(L_temp, L_idx); + + return (Word16)L_idx; +} + +/*-------------------------------------------------------------------* + * BIT_ALLOC_IDX_fx() + *-------------------------------------------------------------------*/ + +Word32 BIT_ALLOC_IDX_fx(Word32 brate, Word16 ctype, Word16 sfrm, Word16 tc) +{ + Word32 L_temp; + Word16 temp; + if (ctype == INACTIVE) /* no sub(ctype, INACTIVE) because it is '0' */ + ctype = GENERIC; + move16(); + L_temp = L_mac0(-1l*256, 1*256, ctype); + + temp = BRATE2IDX_fx(brate); + L_temp = L_mac0(L_temp, 4*256, temp); + if (tc >= 0) + L_temp = L_mac0(L_temp, (10-4)*256, temp); + /* So either 'temp' x 4 when 'tc < 0', 'temp' x 10 otherwise */ + + L_temp = L_mac0(L_temp, 1*256, s_max(0, tc)); + + L_temp = L_mac0(L_temp, s_max(0, sfrm), 1); + if (sfrm < 0) + L_temp = L_shr(L_temp, 2); + L_temp = L_shr(L_temp, 6); + + return L_temp; +} + +/*-------------------------------------------------------------------* + * BIT_ALLOC_IDX_16KHZ_fx() + *-------------------------------------------------------------------*/ + +Word32 BIT_ALLOC_IDX_16KHZ_fx(Word32 brate, Word16 ctype, Word16 sfrm, Word16 tc) +{ + Word32 L_temp; + Word16 temp; + /* 'ctype' = + TRANSITION => 2 + GENERIC => 1 + ALL Other => 0 + */ + L_temp = L_and(shr(0x0240l, shl(ctype, 1)), 3); + + temp = BRATE2IDX16k_fx(brate); + L_temp = L_mac0(L_temp, 3, temp); + if (tc >= 0) + L_temp = L_mac0(L_temp, (7-3), temp); + /* So either 'temp' x 3 when 'tc < 0', 'temp' x 7 otherwise */ + + L_temp = L_mac0(L_temp, 1, s_max(0, tc)); + + IF (sfrm >= 0) + { + /* Mult by 5 */ + L_temp = L_add(L_temp, L_shl(L_temp, 2)); + L_temp = L_mac0(L_temp, shr(sfrm, 6), 1); + } + + return L_temp; +} + + +/*-------------------------------------------------------------------* + * read_indices_fx() + * + * Read indices from an ITU-T G.192 bitstream to the buffer + * Simulate packet losses by inserting frame erasures + *-------------------------------------------------------------------*/ + +Word16 read_indices_fx( /* o : 1 = reading OK, 0 = problem */ + Decoder_State_fx *st, /* i/o: decoder state structure */ + FILE *file, /* i : bitstream file */ + Word16 rew_flag /* i : rewind flag (rewind file after reading)*/ +) +{ + Word16 k; + UWord16 utmp, stream[2+MAX_BITS_PER_FRAME], *pt_stream, *bit_stream_ptr; + Word16 num_bits; + Word32 total_brate; + Word32 L_tmp; + Word16 curr_ft_good_sp, curr_ft_bad_sp; + Word16 g192_sid_first,sid_upd_bad, sid_update; + Word16 speech_bad, speech_lost; + Word16 num_bits_read; + + st->bfi_fx = 0; + st->BER_detect = 0; + st->mdct_sw_enable = 0; + st->mdct_sw = 0; + reset_indices_dec_fx( st ); + + /* read the Sync Header field from the bitstream */ + /* in case rew_flag is set, read until first good frame is encountered */ + do + { + /* read the Sync header */ + if ( fread( &utmp, sizeof(unsigned short), 1, file ) != 1 ) + { + if( ferror( file ) ) + { + /* error during reading */ + fprintf(stderr, "\nError reading the bitstream !"); + exit(-1); + } + else + { + /* end of file reached */ + return 0; + } + } + + /* set the BFI indicator according the value of Sync Header */ + if ( EQ_16(utmp, SYNC_BAD_FRAME)) + { + st->bfi_fx = 1; + } + + + else + { + st->bfi_fx = 0; + } + + /* read the Frame Length field from the bitstream */ + if ( fread( &num_bits, sizeof(unsigned short), 1, file ) != 1 ) + { + if( ferror( file ) ) + { + /* error during reading */ + fprintf(stderr, "\nError reading the bitstream !"); + exit(-1); + } + else + { + /* end of file reached */ + return 0; + } + } + /* convert the frame length to total bitrate */ + total_brate = (long)(num_bits* 50); + + /* read ITU-T G.192 serial stream of indices from file to the local buffer */ + /* Validate that the G.192 length is within the defined bit rate range + to not allow writing past the end of the "stream" buffer */ + if( num_bits > MAX_BITS_PER_FRAME ) + { + fprintf(stderr, "\nError, too large G.192 frame (size(%d))! Exiting ! \n", num_bits); + exit(-1); + } + + /* verify that a valid num bits value is present in the G.192 file */ + /* only AMRWB or EVS bit rates or 0(NO DATA) are allowed in G.192 file frame reading */ + if( rate2EVSmode(total_brate) < 0 ) /* negative value means that a valid rate was not found */ + { + fprintf(stderr, "\nError, illegal bit rate (%d) in the G.192 frame ! Exiting ! \n", total_brate); + exit(-1); + } + pt_stream = stream; + + num_bits_read = (Word16) fread( pt_stream, sizeof(unsigned short), num_bits, file ); + + if( num_bits_read != num_bits ) + { + fprintf(stderr, "\nError, invalid number of bits read ! Exiting ! \n"); + exit(-1); + } + + } + while ( rew_flag && (st->bfi_fx || LT_32(total_brate,2800))); + + /* G.192 RX DTX handler*/ + if( !rew_flag ) + { + /* handle SID_FIRST, SID_BAD, SPEECH_LOST, NO_DATA as properly as possible for the ITU-T G.192 format */ + + /* (total_brate, bfi , st_CNG) = rx_handler(received frame type, [previous frame type], past CNG state, past core) */ + curr_ft_good_sp = 0; + curr_ft_bad_sp = 0; + + if( total_brate > SID_2k40 ) + { + if( st->bfi_fx == 0 ) + { + curr_ft_good_sp = 1; + } + else + { + curr_ft_bad_sp = 1; + } + } + sid_update = 0; + sid_upd_bad = 0; + + if( total_brate == SID_1k75 || total_brate == SID_2k40 ) + { + if( st->bfi_fx == 0 ) + { + sid_update = 1; + } + else + { + sid_upd_bad = 1; /* may happen in CS , corrupt but detected sid frame */ + } + } + + /* all zero indeces/bits iSP AMRWB SID_update results in a valid LP filter with extremely high LP-filter-gain */ + /* all zero indeces/bits may be a result of CS bit errors and/or erroneously injected by gateways or by a bad dejitter handlers */ + if (total_brate == SID_1k75 && sid_update == 1) + { + /* valid sid_update received, check for very risky but formally valid content */ + Word16 sum = 0; + for (k = 0; k < num_bits; ++k) + { + sum += (pt_stream[k] == G192_BIN1);/* check of 35 zeroes, 35 ones */ + } + if( sum == 0 ) + { /* all zeros */ + sid_upd_bad = 1; /* initial signal as corrupt (BER likley) */ + } + } + + /* AMRWB 26.173 G.192 file reader (read_serial) does not declare/use SID_BAD ft, + it declares every bad synch marked frame initially as a lost_speech frame, + and then the RXDTX handler CNG state decides the decoding mode CNG/SPEECH. + While In the AMRWB ETSI/3GPP format eid a CRC error in a detected SID_UPDATE frame triggers SID_UPD_BAD. + + Here we inhibit use of the SID-length info, even though it is available in the G.192 file format after STL/EID-XOR . + */ + if ( sid_upd_bad ) + { + sid_upd_bad = 0; + total_brate = FRAME_NO_DATA ; /* treat SID_BAD as a stolen signaling frame --> SPEECH LOST */ + + } + + g192_sid_first = 0; + if( st->core_fx == AMR_WB_CORE && st->prev_ft_speech_fx && total_brate == FRAME_NO_DATA && st->bfi_fx == 0 ) + { + g192_sid_first = 1; /* SID_FIRST detected for previous AMRWB/AMRWBIO active frames only */ + /* + It is not possible to perfectly simulate rate switching conditions EVS->AMRWBIO where: + the very first SID_FIRST detection is based on a past EVS active frame + and a good length 0 "SID_FIRST"(NO_DATA) frame is sent in AMRWBIO, + , due to the one frame state memory in the AMRWB legacy G.192 SID_FIRST encoding + */ + } + + speech_bad = 0; + if( total_brate > SID_2k40 && st->bfi_fx != 0 ) /* CS-type of CRC failure frame */ + { + speech_bad = 1; /* initial assumption, CNG_state decides what to do */ + } + + speech_lost = 0; + if( total_brate == 0 && st->bfi_fx != 0 ) /* unsent NO_DATA or stolen NO_DATA/signaling frame */ + { + speech_lost = 1; /* initial assumption, CNG_state decides what to do */ + } + + /* Do not allow decoder to enter CNG-synthesis for any instantly received GOOD+LENGTH==0 frame + as this frame was never transmitted, one can not know it is good and has a a length of zero ) */ + + if( st->CNG_fx != 0 ) + { + /* We were in CNG synthesis */ + if( curr_ft_good_sp != 0 ) + { + /* only a good speech frame makes you leave CNG synthesis */ + st->CNG_fx = 0; + } + } + else + { + /* We were in SPEECH synthesis */ + /* only a received SID frame can make the decoder enter into CNG synthsis */ + if( g192_sid_first || sid_update || sid_upd_bad ) + { + st->CNG_fx = 1; + } + } + + /* handle the g.192 _simulated_ untransmitted frame, setting for decoder SPEECH synthesis */ + if ( (st->CNG_fx==0) && (total_brate==0 && st->bfi_fx == 0 ) ) + { + st->bfi_fx = 1; + move16(); /* SPEECH PLC code will now become active as in a real system */ + /* total_brate= 0 */ + } + + /* handle bad speech frame(and bad sid frame) in the decoders CNG synthesis settings pair (total_brate, bfi) */ + if( ((st->CNG_fx != 0) && ( (speech_bad != 0) || (speech_lost != 0) )) || /* SP_BAD or SPEECH_LOST) --> stay in CNG */ + ( sid_upd_bad != 0 )) /* SID_UPD_BAD --> start CNG */ + { + st->bfi_fx = 0; + total_brate = 0; + } + /* update for next frame's G.192 file format's SID_FIRST detection (primarily for AMRWBIO) */ + st->prev_ft_speech_fx = ((curr_ft_good_sp != 0) || (curr_ft_bad_sp != 0)); + + /* st->total brate= total_brate ; updated in a good frame below */ + } /* rew_flag */ +#ifdef DEBUGGING + st->bfi_fx |= file_read_FECpattern(); +#endif + /* get total bit-rate */ + if ( st->bfi_fx == 0 && !rew_flag ) + { + /* select MODE1 or MODE2 */ + decoder_selectCodec( st, total_brate, *pt_stream ); + } + + Mpy_32_16_ss(total_brate, 5243, &L_tmp, &utmp); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + st->total_num_bits = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + + /* in case rew_flag is set, rewind the file and return */ + /* (used in io_enc() to print out info about technologies and to initialize the codec) */ + if ( rew_flag ) + { + rewind( file ); + st->total_brate_fx = total_brate; + move16(); + return 1; + } + + /* GOOD frame */ + if ( st->bfi_fx == 0 ) + { + /* GOOD frame - convert ITU-T G.192 words to short values */ + bit_stream_ptr = st->bit_stream_fx; + + for( k = 0; k< num_bits; ++k) + { + *bit_stream_ptr++ = (*pt_stream++ == G192_BIN1 ); + } + + /*add two zero bytes for arithmetic coder flush*/ + for(k=0; k< 2*8; ++k) + { + *bit_stream_ptr++ = 0; + } + /*a change of the total bitrate should not be + known to the decoder, if the received frame was lost*/ + st->total_brate_fx = total_brate ; + + mdct_switching_dec(st); + } + + return 1; +} + + +/*-------------------------------------------------------------------* + * read_indices_mime_handle_dtx() + * + * Handle DTX for MIME and RTP_DUMP decoding. + * Returns the actual total_brate. + *-------------------------------------------------------------------*/ + +static Word32 read_indices_mime_handle_dtx( + Decoder_State_fx *st, + Word16 isAMRWB_IOmode, + Word16 core_mode, + Word32 total_brate, + Word16 sti, + Word16 speech_lost, + Word16 no_data +) +{ + Word16 curr_ft_good_sp = 0; + Word16 speech_bad = 0; + Word16 sid_upd_bad = 0, sid_update = 0; + Word16 amrwb_sid_first = 0; /* derived from sti SID_FIRST indicator in AMRWB payload */ + + /* keep st->CNG , st_bfi and total_brate updated for proper synthesis in DTX and FER */ + if( GT_32(total_brate, SID_2k40) ) + { + if( st->bfi_fx != 1 ) /* so far derived from q bit in AMRWB/AMRWBIO cases */ + { + curr_ft_good_sp = 1; + } + } + + /* handle q_bit and lost_sp clash , assume worst case */ + if( speech_lost != 0 ) /* overrides a good q_bit */ + { + curr_ft_good_sp = 0; + st->bfi_fx = 1; /* override qbit */ + } + + /* now_bfi_fx has been set based on q_bit and ToC fields */ + + + /* SID_UPDATE check */ + if( total_brate == SID_1k75 || total_brate == SID_2k40 ) + { + if( st->bfi_fx == 0 ) + { + /* typically from q bit */ + sid_update = 1; + } + else + { + sid_upd_bad = 1; /* may happen in saving from e.g. a CS-connection */ + } + } + + if( isAMRWB_IOmode && total_brate == 0 && sti == 0 ) + { + if( st->bfi_fx ) + { + sid_upd_bad = 1; /* corrupt sid_first, signaled as bad sid */ + } + else + { + amrwb_sid_first = 1; /* 1-sti */ + } + } + + if ( sid_upd_bad != 0 && ( + (isAMRWB_IOmode != 0 && st->Opt_AMR_WB_fx==0 ) || /* switch to AMRWBIO */ + (isAMRWB_IOmode != 1 && st->Opt_AMR_WB_fx==1) /* switch from AMRWBIO */ + ) ) + { + /* do not allow a normal start of CNG synthesis if this SID(with BER or FER) is a switch to/from AMRWBIO */ + sid_upd_bad = 0; /* revert this detection due to AMRWBIO/EVS mode switch */ + total_brate = 0; + no_data = 1; + assert( st->bfi_fx==1); /* bfi stays 1 */ + } + + if( GT_32(total_brate, SID_2k40) && st->bfi_fx == 1 ) /* typically from q bit */ + { + speech_bad = 1; /* initial assumption, CNG synt state decides what to actually do */ + } + /* all frame types decoded */ + + /* update CNG synthesis state */ + /* Decoder can only enter CNG-synthesis for CNG frame types (sid_upd, sid_bad, sid_first) */ + if( st->CNG_fx != 0 ) + { + /* We were in CNG synthesis */ + if( curr_ft_good_sp != 0 ) + { + /* only a good speech frame makes decoder leave CNG synthesis */ + st->CNG_fx = 0; + } + } + else + { + /* We were in SPEECH synthesis */ + /* only a received SID frame can make the decoder enter into CNG synthesis */ + if( amrwb_sid_first || sid_update || sid_upd_bad ) + { + st->CNG_fx = 1; + } + } + + /* Now modify bfi flag for the decoder's SPEECH/CNG synthesis logic */ + /* in SPEECH synthesis, make sure to activate speech plc for a received no_data frame, + no_data frames may be injected by the network or by the dejitter buffer */ + /* modify bfi_flag to stay/move into the correct decoder PLC section */ + if ( (st->CNG_fx == 0) && ( no_data != 0 ) ) + { + /* treat no_data received in speech synthesis as SP_LOST frames, SPEECH PLC code will now become active */ + st->bfi_fx = 1; + /* total_brate= 0; always zero for no_data */ + } + + /* in CNG */ + /* handle bad speech frame(and bad sid frame) in the decoders CNG synthesis settings pair (total_brate, bfi) */ + if( ( st->CNG_fx != 0 && ( speech_bad || speech_lost || no_data )) || /* SP_BAD or SPEECH_LOST) --> stay in CNG */ + sid_upd_bad ) /* SID_UPD_BAD --> start/stay CNG */ + { + st->bfi_fx = 0; /* mark as good to not start speech PLC */ + total_brate = 0; /* this zeroing needed for speech_bad, sid_bad frames */ + } + + + /* now bfi, total_brate are set by RX-DTX handler:: + bfi==0, total_brate!=0 cng or speech pending bitrate + bfi==0, total_brate==0 cng will continue or start(sid_first, sid_bad) + bfi==1, total_brate!=0 speech plc + bfi==1, total_brate==0 , speech plc + */ + + + /* handle available AMRWB/AMRWBIO MIME header ToC rate-info at startup */ + if( ( st->bfi_fx == 1 && st->ini_frame_fx == 0) && + ( (st->amrwb_rfc4867_flag != 0) || (st->amrwb_rfc4867_flag == 0 && isAMRWB_IOmode != 0 )) ) /*AMRWB ToC */ + { + Word32 init_rate; + + init_rate = total_brate; /* default , may have been modified from original ToC value */ + if (speech_lost !=0 || no_data != 0 ) + { + init_rate = ACELP_12k65; /* make sure the decoder starts up in a selected AMRWB mode */ + } + else if( speech_bad !=0 ) + { + init_rate = AMRWB_IOmode2rate[core_mode]; /* read from from ToC */ + } + st->total_brate_fx = init_rate; /* not updated on bfi as decoderSelectCodec is not called below */ + st->core_brate_fx = init_rate; + } + + return total_brate; +} + + +/*-------------------------------------------------------------------* + * read_indices_mime_handle_sti_and_all_zero_bits() + * + * Handle STI and frames with all zero bits for MIME and RTP_DUMP decoding. + *-------------------------------------------------------------------*/ + +static void read_indices_mime_handle_sti_and_all_zero_bits( + Decoder_State_fx *st, + Word32 *total_brate, + Word16 sti +) +{ + Word16 k; + + if( sti == 0 ) + { + *total_brate = 0; /* signal received SID_FIRST as a good frame with no bits */ + for(k=0; k<35; k++) + { + st->bfi_fx |= st->bit_stream_fx[k] ; /* partity check of 35 zeroes, any single 1 gives BFI */ + } + } + /* all zero bit SID_update results in a valid LP filter with extremely high LP-filter-gain */ + /* all zero bits signal may be a result of CS bit errors or erronesouly injected by gateways or bad dejitter handlers */ + if (sti == 1) + { /*sid_update received */ + Word16 sum = 0; + for (k = 0; k < 35; k++) + { + sum += st->bit_stream_fx[k]; /* check of 35 zeroes */ + } + + if ( sum == 0 ) + { + st->bfi_fx = 1; /* eventually becomes SID_UPD_BAD */ + } + } +} + + +/*------------------------------------------------------------------------------------------* +* read_indices_mime() +* +* Read indices from MIME formatted bitstream to the buffer +* The magic word and number of channnels should be consumed before calling this function +*-------------------------------------------------------------------------------------------*/ + +Word16 read_indices_mime( /* o : 1 = reading OK, 0 = problem */ + Decoder_State_fx *st, /* i/o: decoder state structure */ + FILE *file, /* i : bitstream file */ + Word16 rew_flag /* i : rewind flag (rewind file after reading) */ +) +{ + Word16 k, isAMRWB_IOmode, cmi, core_mode = -1, qbit,sti; + UWord8 header; + UWord8 pFrame[(MAX_BITS_PER_FRAME + 7) >> 3]; + UWord8 mask= 0x80, *pt_pFrame=pFrame; + UWord16 *bit_stream_ptr; + Word16 num_bits; + Word32 total_brate; + UWord16 utmp; + Word32 L_tmp; + Word16 speech_lost = 0, no_data = 0; + Word16 num_bytes_read; + + st->BER_detect = 0; + st->bfi_fx = 0; + st->mdct_sw_enable = 0; + st->mdct_sw = 0; + reset_indices_dec_fx( st ); + + /* read the FT Header field from the bitstream */ + if ( fread( &header, sizeof(UWord8), 1, file ) != 1 ) + { + if( ferror( file ) ) + { + /* error during reading */ + fprintf(stderr, "\nError reading the bitstream !"); + exit(-1); + } + else + { + /* end of file reached */ + return 0; + } + } + + /* init local RXDTX flags */ + sti = -1; + + if( st->amrwb_rfc4867_flag != 0 ) + { + /* RFC 4867 + 5.3 .... + Each stored speech frame starts with a one-octet frame header with + the following format: + 0 1 2 3 4 5 6 7 + +-+-+-+-+-+-+-+-+ + |P| FT |Q|P|P| + +-+-+-+-+-+-+-+-+ + The FT field and the Q bit are defined in the same way as in + Section 4.3.2. The P bits are padding and MUST be set to 0, and MUST be ignored. */ + + isAMRWB_IOmode = 1; + qbit = (header>>2)&0x01 ; /* b2 bit (b7 is the F bit ) */ + st->bfi_fx = !qbit; + core_mode = ((header>>3) & 0x0F); /* b6..b3 */ + total_brate = AMRWB_IOmode2rate[core_mode]; /* get the frame length from the header */ + } + else + { + /*0 1 2 3 4 5 6 7 MS-bit ---> LS-bit + +-+-+-+-+-+-+-+-+ + |H|F|E|x| brate | + +-+-+-+-+-+-+-+-+ + where : + "E|x| brate " is the 6 bit "FT" -field + x is unused if E=0, (should be 0 ) + x is the q-bit if E=1, q==1(good), Q==0(bad, maybe bit errors in payload ) + H,F always 0 in RTP format. + */ + isAMRWB_IOmode = (header & 0x20) > 0; /* get EVS mode-from header */ /* b2 */ + core_mode = (header & 0x0F); /* b4,b5,b6,b7 */ + + if( isAMRWB_IOmode ) + { + qbit = (header & 0x10) > 0; /* get Q bit, valid for IO rates */ /* b3 */ + total_brate = AMRWB_IOmode2rate[core_mode]; + } + else + { + qbit = 1; /* assume good q_bit for the unused EVS-mode bit, complete ToC validity checked later */ + total_brate = PRIMARYmode2rate[ core_mode ]; + } + st->bfi_fx = !qbit; + } + + + + + /* set up RX-DTX-handler input */ + if( core_mode == 14 ) + { + /* SP_LOST */ + speech_lost=1; + } + if ( core_mode == 15) + { + /* NO_DATA unsent CNG frame OR any frame marked or injected as no_data by e.g a signaling layer or dejitter buffer */ + no_data=1; + } + + Mpy_32_16_ss(total_brate, 5243, &L_tmp, &utmp); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + num_bits = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + st->total_num_bits = num_bits; + + if( total_brate < 0 ) + { + /* validate that total_brate (derived from RTP packet or a file header) is one of the defined bit rates */ + fprintf(stderr, "\n Error. Illegal total bit rate (= %d) in MIME ToC header \n", total_brate ); + /* num_bits = -1; not needed as BASOP multiplication preserves sign */ + } + + /* Check correctness of ToC headers */ + if( st->amrwb_rfc4867_flag == 0 ) + { + /* EVS ToC header (FT field(b2-b7), H bit (b0), F bit (b1) , (EVS-modebit(b2)=0 unused(Qbit)(b3)==0) */ + if ( (isAMRWB_IOmode == 0) && ((num_bits < 0) || ((header & 0x80) > 0) || ((header & 0x40) > 0) || (header & 0x30) != 0x00 ) ) + { + /* incorrect FT header */ + fprintf(stderr, "\nError in EVS FT ToC header(%02x) ! ",header); + exit(-1); + } + else if( (isAMRWB_IOmode != 0) && ( (num_bits < 0) || ((header & 0x80) > 0) || ((header & 0x40) > 0) ) ) /* AMRWBIO */ + { + /* incorrect IO FT header */ + fprintf(stderr, "\nError in EVS(AMRWBIO) FT ToC header(%02x) ! ",header); + exit(-1); + } + } + else + { + /* legacy AMRWB ToC, is only using Padding bits which MUST be ignored */ + if ( num_bits < 0 ) + { + /* incorrect FT header */ + fprintf(stderr, "\nError in AMRWB RFC4867 Toc(FT) header(%02x) !", header); + exit(-1); + } + } + + /* read serial stream of indices from file to the local buffer */ + num_bytes_read = (Word16) fread( pFrame, sizeof(UWord8), (num_bits + 7)>>3, file ); + if( num_bytes_read != (num_bits + 7)>>3 ) + { + fprintf(stderr, "\nError, invalid number of bytes read ! Exiting ! \n"); + exit(-1); + } + + /* in case rew_flag is set, rewind the file and return */ + /* (used in io_dec() to attempt print out info about technologies and to initialize the codec ) */ + if ( rew_flag ) + { + st->total_brate_fx = total_brate; /* used for the codec banner output */ + if( st->bfi_fx == 0 && speech_lost == 0 && no_data == 0 ) + { + decoder_selectCodec( st, total_brate, unpack_bit(&pt_pFrame,&mask) ? G192_BIN1 : G192_BIN0); + } + return 1; + } + + + + /* unpack speech data */ + bit_stream_ptr = st->bit_stream_fx; + for (k=0; kbit_stream_fx[sort_ptr[core_mode][k]] = unpack_bit(&pt_pFrame,&mask); + bit_stream_ptr++; + } + else + { + *bit_stream_ptr++ = unpack_bit(&pt_pFrame,&mask); + } + } + + /* unpack auxiliary bits */ + /* Note: the cmi bits are unpacked for demo purposes; */ + if (isAMRWB_IOmode && total_brate == SID_1k75) + { + sti = unpack_bit(&pt_pFrame,&mask); + cmi = unpack_bit(&pt_pFrame,&mask) << 3; + cmi |= unpack_bit(&pt_pFrame,&mask) << 2; + cmi |= unpack_bit(&pt_pFrame,&mask) << 1; + cmi |= unpack_bit(&pt_pFrame,&mask); + + read_indices_mime_handle_sti_and_all_zero_bits( st, &total_brate, sti ); + } + + /*add two zero bytes for arithmetic coder flush*/ + for(k=0; k< 2*8; ++k) + { + *bit_stream_ptr++ = 0; + } + + /* MIME RX_DTX handler */ + if( !rew_flag ) + { + total_brate = read_indices_mime_handle_dtx( st, isAMRWB_IOmode, core_mode, total_brate, sti, speech_lost, no_data ); + } + + if( st->bfi_fx == 0 ) + { + /* select MODE1 or MODE2 in MIME */ + decoder_selectCodec( st, total_brate, *st->bit_stream_fx ? G192_BIN1 : G192_BIN0); + + /* a change of the total bitrate should not be known to the decoder, if the received frame was truly lost */ + st->total_brate_fx = total_brate; + mdct_switching_dec(st); + } + /* else{ bfi stay in past synthesis mode(SP,CNG) } */ + + return 1; +} + +/*-------------------------------------------------------------------* +* berCheck() +* +* Check for bit errors in channel aware signalling. +*-------------------------------------------------------------------*/ + +static void berCheck( + Decoder_State_fx *st, /* i/o: decoder state structure */ + Word16 *coder_type /* i/o: coder type */ +) +{ + /* In case of RF flag = 1, and valid RF packet with primary and partial copy */ + if ( ( EQ_16( st->bwidth_fx, NB)||EQ_16(st->bwidth_fx,FB)) + || (GE_16(*coder_type,TRANSITION) ) + ) + { + if( EQ_16( st->use_partial_copy, 1 )) + { + st->use_partial_copy = 0; + move16(); + } + + st->bfi_fx = 1; + move16(); + st->bwidth_fx = st->last_bwidth_fx; + move16(); + st->BER_detect = 1; + move16(); + *coder_type = GENERIC; + move16(); + } + + return; +} + +/*-------------------------------------------------------------------* +* getPartialCopyInfo() +* +* Check if the frame includes a partial copy for channel aware processing. +*-------------------------------------------------------------------*/ + +void getPartialCopyInfo( + Decoder_State_fx *st, /* i/o: decoder state structure */ + Word16 *coder_type, + Word16 *sharpFlag +) +{ + Word16 nBits; + Word16 ind; + /* check the rf flag in the packet */ + get_rfFlag( st, &(st->rf_flag), &nBits , &ind); + + /* get rf frame type info */ + get_rfFrameType( st, &(st->rf_frame_type) ); + + /* Get the FEC offset info */ + get_rf_fec_offset( st, &(st->rf_fec_offset) ); + + /* reset number of target bits in case of rate switching */ + st->rf_target_bits = 0; + + /* Get the number of bits used for RF*/ + IF( EQ_16(st->rf_flag,1)) + { + *coder_type = s_and(ind,0x7); + st->bwidth_fx = s_and(shr(ind,3), 0x7); + *sharpFlag = s_and(shr(ind,6), 0x1); + st->codec_mode = MODE2; + move16(); + get_rfTargetBits( st->rf_frame_type, &(st->rf_target_bits) ); + + IF( EQ_16(st->bfi_fx,FRAMEMODE_FUTURE)) + { + st->use_partial_copy = 1; + /* now set the frame mode to normal mode */ + test(); + IF(GE_16(st->rf_frame_type,RF_TCXFD)&&LE_16(st->rf_frame_type,RF_TCXTD2)) + { + st->bfi_fx = 1; + st->core_fx = 1; + } + ELSE + { + st->bfi_fx = FRAMEMODE_NORMAL; + st->core_fx = 0; + } + } + + /* check for bit errors */ + berCheck( st, coder_type ); + + get_next_indice_tmp_fx(st, nBits); + + } +} + +/*-------------------------------------------------------------------* +* get_rfFlag() +* +* Check if rf flag is present in the bitstream +*-------------------------------------------------------------------*/ + +void get_rfFlag( + Decoder_State_fx *st, /* i: decoder state structure */ + Word16 *rf_flag, /* o : check for the RF flag */ + Word16 *nBits, + Word16 *ind +) +{ + Word16 start_idx, nBits_tmp; + Word16 ind_tmp; + + /* Init */ + *rf_flag = 0; + + /* check for rf_flag in the packet and extract the rf_frame_type and rf_fec_offset */ + test(); + test(); + IF( EQ_32(st->total_brate_fx,ACELP_13k20)&&(EQ_16(st->bfi_fx,FRAMEMODE_NORMAL)||EQ_16(st->bfi_fx,FRAMEMODE_FUTURE))) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + start_idx = 0; + WHILE ( NE_32(acelp_sig_tbl[start_idx], st->total_brate_fx)) + { + start_idx++; + assert((start_idx < MAX_ACELP_SIG) && "ERROR: start_idx larger than acelp_sig_tbl[].\n"); + } + + /* skip the bitrate */ + start_idx = add(start_idx,1); + + /* retrieve the number of bits */ + nBits_tmp = (Word16) acelp_sig_tbl[start_idx++]; + + /* retrieve the signalling indice */ + ind_tmp = (Word16) acelp_sig_tbl[start_idx + get_indice_fx( st, 0, nBits_tmp )]; + + /* convert signalling indice into RF flag. */ + *rf_flag = s_and(shr(ind_tmp, 7), 0x1); + + if( ind ) + { + *ind = ind_tmp; + } + + if( nBits ) + { + *nBits = nBits_tmp; + } + } +} + +/*-------------------------------------------------------------------* +* get_rfFrameType() +* +* Extract the rf frame type +*-------------------------------------------------------------------*/ + +void get_rfFrameType( + Decoder_State_fx *st, /* i : decoder state structure */ + Word16 *rf_frame_type /* o : RF frame type */ +) +{ + Word16 num_bits = 0; + + IF( EQ_16(st->rf_flag, 1)) + { + /*num_bits = st->total_brate_fx/50;*/ + if( EQ_32(st->total_brate_fx, ACELP_13k20)) + { + num_bits = 264; + move16(); /* @13.2kbps */ + } + else + { + UWord16 lsb; + Word32 L_tmp; + Mpy_32_16_ss(st->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + num_bits = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + } + + /* the last three bits in a packet is the RF frame type */ + *rf_frame_type = get_indice_fx( st, num_bits - 3, 3 ); + } + ELSE + { + *rf_frame_type = 0; + } +} + +/*-------------------------------------------------------------------* +* get_rf_fec_offset() +* +* Extract the FEC offset +*-------------------------------------------------------------------*/ + +void get_rf_fec_offset( + Decoder_State_fx *st, /* i : decoder state structure */ + Word16 *rf_fec_offset /* o : RF fec offset */ +) +{ + Word16 num_bits, tmp; + + IF( EQ_16(st->rf_flag,1)) + { + /*num_bits = st->total_brate_fx/50;*/ + if( EQ_32(st->total_brate_fx, ACELP_13k20)) + { + num_bits = 264; + move16(); /* @13.2kbps */ + } + else + { + UWord16 lsb; + Word32 L_tmp; + Mpy_32_16_ss(st->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + num_bits = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + } + + /* the two bits before the rf frame type contain the fec offset */ + tmp = get_indice_fx( st, num_bits - 5, 2 ); + + if( tmp == 0 ) + { + *rf_fec_offset = 2; + move16(); + } + else + { + *rf_fec_offset = add(shl(tmp, 1), 1); + } + } + ELSE + { + *rf_fec_offset = 0; + move16(); + } +} + +/*-------------------------------------------------------------------* +* get_rfTargetBits() +* +* Return the number of RF target bits +*-------------------------------------------------------------------*/ + +void get_rfTargetBits( + Word16 rf_frame_type, /* i : RF frame type */ + Word16 *rf_target_bits /* o : Number of RF target bits */ +) +{ + + /* Number of RF bits for different RF coder types */ + + SWITCH (rf_frame_type) + { + case RF_NO_DATA: + *rf_target_bits = 5; + BREAK; + case RF_TCXFD: + *rf_target_bits = 27; + BREAK; + case RF_TCXTD1: + *rf_target_bits = 16; + BREAK; + case RF_TCXTD2: + *rf_target_bits = 16; + BREAK; + case RF_ALLPRED: + /* Es_pred bits 3 bits, LTF: 1, pitch: 8,5,5,5, FCB: 0, gain: 7,0,7,0, Diff GFr: 4*/ + *rf_target_bits = 63; + BREAK; + case RF_NOPRED: + /* Es_pred bits 3 bits, LTF: 0, pitch: 0, FCB: 7,7,7,7, gain: 6,0,6,0, Diff GFr: 2*/ + *rf_target_bits = 66; + BREAK; + case RF_GENPRED: + /* Es_pred bits 3 bits, LTF: 1, pitch: 8,0,8,0, FCB: 6,7,5,5, gain: 5,0,5,0, Diff GFr: 0*/ + *rf_target_bits = 70; + BREAK; + case RF_NELP: + /* gain: 19, Diff GFr: 5 */ + *rf_target_bits = 45; + BREAK; + } +} + + +/*-------------------------------------------------------------------* + * get_NextCoderType_fx() + * + * Extract the coder type of next frame + *-------------------------------------------------------------------*/ + +void get_NextCoderType_fx( + UWord8 *bitsteam, /* i : bitstream */ + Word16 *next_coder_type /* o : next coder type */ +) +{ + Word16 k; + Word16 start_idx; + Word16 nBits_tmp; + Word8 bit_stream[ACELP_13k20/50]; + UWord16 tmp; + + + FOR( k = 0; k < ACELP_13k20/50; k++ ) + { + bit_stream[k] = (bitsteam[k / 8] >> (7 - (k % 8))) & 0x1; + } + start_idx = 0; + WHILE ( NE_32(acelp_sig_tbl[start_idx], ACELP_13k20)) + { + start_idx = add(start_idx,1); + assert((start_idx < MAX_ACELP_SIG) && "ERROR: start_idx larger than acelp_sig_tbl[].\n"); + } + + /* skip the bitrate */ + start_idx = add(start_idx,1); + + tmp = 0; + move16(); + nBits_tmp = (Word16) acelp_sig_tbl[start_idx++]; + FOR (k = 0; k < nBits_tmp; k++) + { + tmp = lshl(tmp, 1); + tmp = add(tmp, bit_stream[k]); + } + /* retrieve the signalling indice */ + *next_coder_type = s_and((Word16)acelp_sig_tbl[start_idx + tmp],0x7); +} + +/*-------------------------------------------------------------------* + * read_indices_from_djb_fx() + * + * Read indices from the de-jitter buffer payload (works also for AMR-WB IO mode) + *-------------------------------------------------------------------*/ + +void read_indices_from_djb_fx( + Decoder_State_fx *st, /* i/o: decoder state structure */ + UWord8 *pt_stream, /* i : bitstream file */ + Word16 num_bits, /* i : input frame length in bits */ + Word16 isAMRWB_IOmode, + Word16 core_mode, + Word16 qbit, + Word16 partialframe, /* i : partial frame information */ + Word16 next_coder_type /* i : next coder type information */ +) +{ + Word16 k; + UWord8 mask = 0x80; + Word16 no_data = 0; + Word16 sti = -1; + UWord16 *bit_stream_ptr; + Word32 total_brate; + Word16 speech_lost = 0; + + st->bfi_fx = 0; + st->BER_detect = 0; + st->mdct_sw_enable = 0; + st->mdct_sw = 0; + reset_indices_dec_fx(st); + + st->bfi_fx = !qbit; + total_brate = (Word32)(num_bits) * 50; + st->total_num_bits = num_bits; + + if( num_bits == 0 ) /* guess type of missing frame for SP_LOST and NO_DATA */ + { + speech_lost = st->CNG_fx == 0; + no_data = st->CNG_fx != 0; + } + + if( partialframe || st->prev_use_partial_copy) + { + st->next_coder_type = next_coder_type; + } + else + { + st->next_coder_type = INACTIVE; + } + + if (partialframe == 1) + { + st->bfi_fx = 2; + } + + /* unpack speech data */ + bit_stream_ptr = st->bit_stream_fx; + /* convert bitstream from compact bytes to short values and store it in decoder state */ + for( k = 0; k < num_bits; k++ ) + { + if( st->bitstreamformat == VOIP_RTPDUMP && isAMRWB_IOmode ) + { + st->bit_stream_fx[sort_ptr[core_mode][k]] = unpack_bit(&pt_stream, &mask); + bit_stream_ptr++; + } + else + { + *bit_stream_ptr++ = unpack_bit(&pt_stream, &mask); + } + } + + /* unpack auxiliary bits */ + if( isAMRWB_IOmode && total_brate == SID_1k75 ) + { + if( st->bitstreamformat == VOIP_RTPDUMP ) + { + /* A.2.2.1.3: AMR-WB SID_1k75 frame is followed by STI bit and CMI bits */ + sti = unpack_bit(&pt_stream, &mask); + } + else + { + /* VOIP_G192_RTP does not contain STI and CMI */ + sti = 1; + } + read_indices_mime_handle_sti_and_all_zero_bits(st, &total_brate, sti); + + } + + /* add two zero bytes for arithmetic coder flush */ + for( k=0; k < 8*2; ++k ) + { + *bit_stream_ptr++ = 0; + } + + total_brate = read_indices_mime_handle_dtx(st, isAMRWB_IOmode, core_mode, total_brate, sti, speech_lost, no_data); + /* st->CNG_fx set inside */ + + if ( st->bfi_fx != 1 ) + { + /* select Mode 1 or Mode 2 */ + decoder_selectCodec( st, total_brate, *st->bit_stream_fx ? G192_BIN1 : G192_BIN0); + + /* a change of the total bitrate should not be known to the decoder, if the received frame was truly lost */ + st->total_brate_fx = total_brate; + + mdct_switching_dec(st); + } +} + + + +/*-------------------------------------------------------------------* + * get_indice_preview() + * + * Indices preview to parse for the presence of partial copy + *-------------------------------------------------------------------*/ +static UWord16 get_indice_preview( + UWord8 *bitstream, + Word16 bitstreamSize, + Word16 pos, + Word16 nb_bits +) +{ + UWord16 value; + Word16 i; + UWord16 bitstreamShort[MAX_BITS_PER_FRAME+16]; + UWord16 *bitstreamShortPtr; + + /* convert bitstream from compact bytes to short values */ + bitstreamShortPtr = bitstreamShort; + FOR( i = 0; i < bitstreamSize; i++ ) + { + *bitstreamShortPtr++ = (bitstream[i / 8] >> (7 - (i % 8))) & 0x1; + } + + assert(nb_bits <= 16); + value = 0; + FOR (i = 0; i < nb_bits; i++) + { + value = shl(value,1); + value = add(value,bitstreamShort[pos+i]); + } + return value; +} + +/*-------------------------------------------------------------------* + * evs_dec_previewFrame() + * + * Signalling index preview + *-------------------------------------------------------------------*/ +void evs_dec_previewFrame( + UWord8 *bitstream, + Word16 bitstreamSize, + Word16 *partialCopyFrameType, + Word16 *partialCopyOffset +) +{ + Word32 total_brate; + Word16 start_idx, nBits; + Word32 ind; + Word16 rf_flag; + + rf_flag = 0; + *partialCopyFrameType = 0; + *partialCopyOffset = 0; + total_brate = bitstreamSize * 50; + + IF( EQ_32(total_brate,ACELP_13k20)) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + start_idx = 0; + WHILE ( NE_32(acelp_sig_tbl[start_idx], total_brate)) + { + start_idx = add(start_idx,1); + assert((start_idx < MAX_ACELP_SIG) && "ERROR: start_idx larger than acelp_sig_tbl[].\n"); + } + + /* skip the bitrate */ + start_idx = add(start_idx,1); + /* retrieve the number of bits */ + nBits = (Word16) acelp_sig_tbl[start_idx++]; + + /* retrieve the signalling indice */ + ind = acelp_sig_tbl[start_idx + get_indice_preview( bitstream, bitstreamSize, 0, nBits )]; + + /* convert signalling indice into RF flag. */ + rf_flag = s_and(extract_l(L_shr(ind, 7)), 0x1); + assert(rf_flag == ((ind >> 7) & 0x1)); + IF(rf_flag != 0) + { + /* read the fec offset at which the partial copy is received */ + ind = get_indice_preview( bitstream, bitstreamSize, (bitstreamSize-5), 2 ); + IF(ind== 0) *partialCopyOffset = 2; + ELSE IF(EQ_32(ind,1))*partialCopyOffset=3; + ELSE IF(EQ_32(ind,2))*partialCopyOffset=5; + ELSE IF(EQ_32(ind,3))*partialCopyOffset=7; + + /* the last three bits in a packet is the RF frame type */ + *partialCopyFrameType = get_indice_preview( bitstream, bitstreamSize, bitstreamSize - 3, 3 ); + } + } +} + + diff --git a/lib_com/cb_shape_fx.c b/lib_com/cb_shape_fx.c new file mode 100644 index 0000000..b475136 --- /dev/null +++ b/lib_com/cb_shape_fx.c @@ -0,0 +1,134 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* */ + +#include "stl.h" + +/* + * E_GAIN_f_pitch_sharpening + * + * Parameters: + * x I/O: impulse response (or algebraic code) + * pit_lag I: pitch lag + * + * Function: + * Performs Pitch sharpening routine for one subframe. + * pitch sharpening factor is 0.85 + * + * Returns: + * void + */ +static void E_GAIN_f_pitch_sharpening(Word16 *x, Word16 pit_lag, Word16 L_subfr) +{ + Word16 i, tmp; + + FOR (i = pit_lag; i < L_subfr; i++) + { + /*x[i] += x[i - pit_lag] * F_PIT_SHARP;*/ + tmp = mult_r(x[i - pit_lag], 27853/*F_PIT_SHARP Q15*/); + x[i] = add(x[i],tmp); + move16(); + } + return; +} + +/*-------------------------------------------------------------------* + * cb_shape() + * + * pre-emphasis, pitch sharpening and formant sharpening of the algebraic codebook + *-------------------------------------------------------------------*/ + +void cb_shape_fx( + const Word16 preemphFlag, /* i : flag for pre-emphasis */ + const Word16 pitchFlag, /* i : flag for pitch sharpening */ + const Word16 scramblingFlag, /* i : flag for phase scrambling */ + const Word16 sharpFlag, /* i : flag for formant sharpening */ + const Word16 formantTiltFlag, /* i : flag for formant tilt */ + const Word16 g1, /* i : formant sharpening numerator weighting */ + const Word16 g2, /* i : formant sharpening denominator weighting */ + const Word16 *p_Aq, /* i : LP filter coefficients */ + Word16 *code, /* i/o: signal to shape */ + const Word16 tilt_code, /* i : tilt of code */ + const Word16 pt_pitch, /* i : pointer to current subframe fractional pitch */ + const Word16 shift +) +{ + Word16 tmp, buff[L_SUBFR+M], A_num[M+1], A_den[M+1]; + Word16 i; + Word32 L_tmp; + Word16 tilt, mu; + tmp = 0; + move16(); + + /* Pre-emphasis */ + IF( preemphFlag ) + { + preemph_copy_fx(code, code, tilt_code, L_SUBFR, &tmp); + } + + /* pitch sharpening */ + IF( pitchFlag ) + { + E_GAIN_f_pitch_sharpening( code, pt_pitch, L_SUBFR ); + } + + /* phase scrambling filter */ + IF( scramblingFlag ) + { + buff[0] = code[0]; + move16(); + FOR (i = 1; i < L_SUBFR; i++) + { + buff[i]=code[i]; + move16(); + /*code[i] = 0.7f*buff[i] + buff[i-1] - 0.7f*code[i-1]; */ + L_tmp = L_mult(22938, buff[i]); + tmp = mac_r(L_tmp,-22938, code[i-1]); + code[i] = add(tmp,buff[i-1]); + move16(); + } + } + + test(); + IF ( sharpFlag || formantTiltFlag ) + { + weight_a_fx( p_Aq, A_num, g1, M ); + weight_a_fx( p_Aq, A_den, g2, M ); + set16_fx(buff, 0, M+L_SUBFR); + IF( formantTiltFlag ) + { + Copy(A_num, buff+M, M+1); + + E_UTIL_synthesis(1, A_den, buff+M, buff+M, L_SUBFR, buff, 0, M); + + /*Compute tilt of formant enhancement*/ + tilt = extract_l(L_shr(get_gain(buff+M+1, buff+M, L_SUBFR-1),1)); + + /*Combine tilt of code and fe*/ + tmp = 0; + move16(); + /*mu = 0.5f*tilt_code-0.25f*tilt;*/ + mu = sub(shr(tilt_code,1),shr(tilt,2)); + preemph_copy_fx(code, code, mu, L_SUBFR, &tmp); + } + ELSE + { + Copy( code, buff, L_SUBFR ); + + Overflow = 0; + move16(); + Residu3_lc_fx(A_num, M, buff, code, L_SUBFR, shift); + { + syn_filt_s_lc_fx(shift, A_den, code, code, L_SUBFR); + } + } + } + + return; +} + diff --git a/lib_com/cldfb.c b/lib_com/cldfb.c new file mode 100644 index 0000000..a05236e --- /dev/null +++ b/lib_com/cldfb.c @@ -0,0 +1,1661 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ +/*! + \file + \brief Complex cldfb analysis/synthesis, $Revision: 1214 $ + This module contains the cldfb filterbank for analysis [ cplxAnalysisCldfbFiltering() ] and + synthesis [ cplxSynthesisCldfbFiltering() ]. It is a polyphase implementation of a complex + exponential modulated filter bank. The analysis part usually runs at half the sample rate + than the synthesis part. (So called "dual-rate" mode.) + + \anchor PolyphaseFiltering

About polyphase filtering

+ The polyphase implementation of a filterbank requires filtering at the input and output. + This is implemented as part of cplxAnalysisCldfbFiltering() and cplxSynthesisCldfbFiltering(). + +*/ + +#include "stl.h" +#include "cnst_fx.h" +#include "stat_com.h" +#include "rom_com_fx.h" +#include "basop_util.h" +#include "prot_fx.h" +#include + +#define STATE_BUFFER_SIZE ( 9+16 ) + +#define CLDFB_NO_POLY ( 5 ) +#define SYN_FILTER_HEADROOM ( 1 ) + +#define CLDFB_LDCLDFB_PFT_SCALE ( 0 ) +#define CLDFB_CLDFB80_O24_PFT_SCALE ( 1 ) +#define CLDFB_CLDFB80_O5_PFT_SCALE ( 1 ) +#define CLDFB_CLDFB80_PFT_SCALE ( 1 ) + + + +#define SYN_FILTER_HEADROOM_1MS ( 2 ) +#define SYN_FILTER_HEADROOM_2MS ( 2 ) +#define SYN_FILTER_HEADROOM_2_5MS ( 2 ) +#define SYN_FILTER_HEADROOM_8MS ( 1 ) + +#define N8 ( 4 ) +#define N10 ( 5 ) +#define N16 ( 8 ) +#define N20 ( 10 ) +#define N30 ( 15 ) +#define N32 ( 16 ) +#define N40 ( 20 ) +#define N60 ( 30 ) + +static void +cldfb_init_proto_and_twiddles(HANDLE_CLDFB_FILTER_BANK hs); + +#define cplxMpyS(yr,yi,xr,xi,cr,ci,syr,syi,sxr,sxi,CL_x,CL_z,C_c) CL_x = CL_form( *xr, *xi ); \ + C_c = C_form( *cr, *ci ); \ + CL_z = CL_mult_32x16( CL_x, C_c ); \ + *yr = CL_Extract_real( CL_z ); \ + *yi = CL_Extract_imag( CL_z ); \ + yr+=syr, yi+=syi, xr+=sxr, xi+=sxi, cr++, ci++ + +#define cplxMpy(ryr,ryi,iyr,iyi,rxr,rxi,ixr,ixi,cr,ci,g,sx,sr,CL_x,CL_ry,CL_iy,C_c) CL_x = CL_form( *rxr, *rxi ); \ + C_c = C_form( *cr, *ci ); \ + CL_ry = CL_mult_32x16( CL_x, C_c ); \ + CL_x = CL_form( *ixr, *ixi ); \ + CL_iy = CL_mult_32x16( CL_x, C_c ); \ + CL_ry = CL_scale_t( CL_ry, g ); \ + CL_iy = CL_scale_t( CL_iy, g ); \ + ryr = CL_Extract_real( CL_ry ); \ + ryi = CL_Extract_imag( CL_ry ); \ + iyr = CL_Extract_real( CL_iy ); \ + iyi = CL_Extract_imag( CL_iy ); \ + rxr+=sx, rxi+=sx, ixr+=sx, ixi+=sx, cr+=sr, ci+=sr + +#define add1(y1,y2,y3,y4,rr12,ri12,ir12,ii12,s) *y1 = round_fx(L_shl(L_negate(L_add(rr12,ii12)),s)); \ + *y2 = round_fx(L_shl(L_negate(L_add(ri12,ir12)),s)); \ + *y3 = round_fx(L_shl(L_sub(rr12,ii12),s)); \ + *y4 = round_fx(L_shl(L_sub(ir12,ri12),s)); \ + y1+=2, y2-=2, y3-=2, y4+=2 + + +#define add2(y1,y2,y3,y4,rr12,ri12,ir12,ii12,s) *y1 = round_fx(L_shl(L_add(ri12,ir12),s)); \ + *y2 = round_fx(L_shl(L_add(rr12,ii12),s)); \ + *y3 = round_fx(L_shl(L_sub(ir12,ri12),s)); \ + *y4 = round_fx(L_shl(L_sub(rr12,ii12),s)); \ + y1+=2, y2-=2, y3-=2, y4+=2 + +#define ptrUpdate16(y11,y12,y13,y14,r11,x11,x12,x13,x14,r12,y21,y22,y23,y24,r21,x21,x22,x23,x24,r22) \ + y11 += 2*N8, y12 -= 2*N8, y13 -= 2*N8, y14 += 2*N8, r11 -= 1*N8; \ + x11 -= 2*N8, x12 -= 2*N8, x13 -= 2*N8, x14 -= 2*N8, r12 -= 1*N8; \ + y21 += 2*N8, y22 -= 2*N8, y23 -= 2*N8, y24 += 2*N8, r21 += 1*N8; \ + x21 += 2*N8, x22 += 2*N8, x23 += 2*N8, x24 += 2*N8, r22 += 1*N8 + +#define ptrUpdate20(y11,y12,y13,y14,r11,x11,x12,x13,x14,r12,y21,y22,y23,y24,r21,x21,x22,x23,x24,r22) \ + y11 += 2*N10, y12 -= 2*N10, y13 -= 2*N10, y14 += 2*N10, r11 -= 1*N10; \ + x11 -= 2*N10, x12 -= 2*N10, x13 -= 2*N10, x14 -= 2*N10, r12 -= 1*N10; \ + y21 += 2*N10, y22 -= 2*N10, y23 -= 2*N10, y24 += 2*N10, r21 += 1*N10; \ + x21 += 2*N10, x22 += 2*N10, x23 += 2*N10, x24 += 2*N10, r22 += 1*N10 + + + + +static void cplxMultAdd10_1(Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4, + Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI, + const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s, + Word16 sx, Word16 sr) +{ + Word32 rr12, ri12, ir12, ii12; + cmplx CL_x,CL_ry, CL_iy; + cmplx_s C_c; + + cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr,CL_x,CL_ry, CL_iy,C_c); + add1(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s); + cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr,CL_x,CL_ry, CL_iy,C_c); + add1(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s); + +} + +static void cplxMultAdd10_2(Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4, + Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI, + const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s, + Word16 sx, Word16 sr) +{ + Word32 rr12, ri12, ir12, ii12; + cmplx CL_x,CL_ry, CL_iy; + cmplx_s C_c; + + cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c); + add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s); + cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c); + add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s); + cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c); + add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s); + +} + + +static void cplxMultAdd20_1(Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4, + Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI, + const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s, + Word16 sx, Word16 sr) +{ + Word32 rr12, ri12, ir12, ii12; + cmplx CL_x,CL_ry, CL_iy; + cmplx_s C_c; + + cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c); + add1(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s); + cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c); + add1(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s); + cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c); + add1(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s); + cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c); + add1(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s); + cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c); + add1(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s); + + +} + +static void cplxMultAdd20_2(Word16 *rY1, Word16 *rY2, Word16 *rY3, Word16 *rY4, + Word32 *rXR, Word32 *rXI, Word32 *iXR, Word32 *iXI, + const Word16 *cr, const Word16 *ci, Word16 gv, Word16 s, + Word16 sx, Word16 sr) +{ + Word32 rr12, ri12, ir12, ii12; + cmplx CL_x,CL_ry, CL_iy; + cmplx_s C_c; + + cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c); + add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s); + cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c); + add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s); + cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c); + add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s); + cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c); + add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s); + cplxMpy(rr12, ri12, ir12, ii12, rXR, rXI, iXR, iXI, cr, ci, gv, sx, sr, CL_x, CL_ry, CL_iy, C_c); + add2(rY1, rY2, rY3, rY4, rr12, ri12, ir12, ii12, s); + +} + +/* calcModulation + + Parameters: + *rYR O: pointer to real output samples (DST) + *rYI O: pointer to imaginary output samples (DST) + *rXR I: pointer to real input samples (DST) + *rXI I: pointer to imaginary input samples (DST) + srYR I: offset for update of pointer to real output samples (DST) + srYI I: offset for update of pointer to imaginary output samples (DST) + srXR I: offset for update of pointer to real input samples (DST) + srXI I: offset for update of pointer to imaginary input samples (DST) + *iYR O: pointer to real output samples (DCT) + *iYI O: pointer to imaginary output samples (DCT) + *iXR I: pointer to real input samples (DCT) + *iXI I: pointer to imaginary input samples (DCT) + siYR I: offset for update of pointer to real output samples (DCT) + siYI I: offset for update of pointer to imaginary output samples (DCT) + siXR I: offset for update of pointer to real input samples (DCT) + siXI I: offset for update of pointer to imaginary input samples (DCT) + m I: processed cldfb bands + + Function: + The function applies for each cldfb length a unrolled complex modulation + + Returns: + void +*/ +static void calcModulation( Word32 *rYR, + Word32 *rYI, + Word32 *rXR, + Word32 *rXI, + Word16 srYR, + Word16 srYI, + Word16 srXR, + Word16 srXI, + Word32 *iYR, + Word32 *iYI, + Word32 *iXR, + Word32 *iXI, + Word16 siYR, + Word16 siYI, + Word16 siXR, + Word16 siXI, + const Word16 *rRotVctr, + const Word16 *iRotVctr, + Word16 m + ) +{ + cmplx CL_x,CL_z; + cmplx_s C_c; + int i; + int lc = m >> 1; + + const Word16 *cr = rRotVctr; + const Word16 *ci = iRotVctr; + + for(i=0;ino_channels; + move16(); + L2 = shl(m,1); + m2 = shr(m,1); + M4 = shr(m,2); + M4 = sub(m2,M4); + + L3 = sub(L2,m2); + L4 = add(L2,m2); + + M0M2 = sub(0,m2); + M2M1 = sub(m2,1); + L3M1 = sub(L3,1); + L4M1 = sub(L4,1); + + rBuffer = &pWorkBuffer[0]; + iBuffer = &pWorkBuffer[m]; + + rRotVctr = cldfbBank->rRotVctr; + iRotVctr = cldfbBank->iRotVctr; + + pStates = cldfbBank->FilterStates; + pStates1 = &pStates[L3M1]; + pStates2 = &pStates[L3]; + pStates3 = &pStates[m2]; + pStates4 = &pStates[M2M1]; + pStates5 = &pStates[L4M1]; + pStates6 = &pStates[M0M2]; + + p_stride = CLDFB_NO_POLY; + pFilter = &cldfbBank->p_filter[p_stride - CLDFB_NO_POLY]; + pFilter1 = &pFilter[p_stride*L3M1]; + pFilter2 = &pFilter[p_stride*L3]; + pFilter3 = &pFilter[p_stride*m2]; + pFilter4 = &pFilter[p_stride*M2M1]; + pFilter5 = &pFilter[p_stride*L4M1]; + pFilter6 = &pFilter[p_stride*M0M2]; + + nSamples = i_mult(nTimeSlots, cldfbBank->no_channels); + nSamplesUpd = i_mult(cldfbBank->no_col, cldfbBank->no_channels); + offset = sub(sub(cldfbBank->p_filter_length, cldfbBank->no_channels),cldfbBank->zeros); + + /* Determine states scale */ + scale = -15; + move16(); + k = 0; + move16(); + FOR (i=0; ino_channels) + { + cldfbBank->FilterStates_e[k] = cldfbBank->FilterStates_e[k+cldfbBank->no_col]; + move16(); + assert((size_t)k < sizeof(cldfbBank->FilterStates_e)/sizeof(cldfbBank->FilterStates_e[0])); + scale = s_max(scale, cldfbBank->FilterStates_e[k]); + k = add(k,1); + } + FOR (i=0; ino_channels) + { + cldfbBank->FilterStates_e[k] = timeIn_e; + move16(); + assert((size_t)k < sizeof(cldfbBank->FilterStates_e)/sizeof(cldfbBank->FilterStates_e[0])); + scale = s_max(scale, cldfbBank->FilterStates_e[k]); + k = add(k,1); + } + i = s_max(scale, timeIn_e); + scale = sub(cldfbBank->FilterStates_eg, i); + cldfbBank->FilterStates_eg = i; + move16(); + + /* if nTimeSlots==0, make sure we have a value. */ + scaleFactor->lb_scale = add(cldfbBank->anaScalefactor, add(cldfbBank->FilterStates_eg, 5)); + move16(); + + /* move and scale filter states */ + FOR (i=0; iFilterStates_eg); + FOR (i=0; ilb_scale = add(cldfbBank->anaScalefactor, add(cldfbBank->FilterStates_eg, scale)); + move16(); + + /* FFT of DCT IV */ + BASOP_cfft((cmplx *)iBuffer, m2, &scale, workBuffer); + + /* post modulation of DST IV and DCT IV */ + calcModulation(&rAnalysis[k][m-1], &rAnalysis[k][0], &rBuffer[0], &rBuffer[1],-2, 2, 2, 2, + &iAnalysis[k][0], &iAnalysis[k][m-1], &iBuffer[0], &iBuffer[1], 2,-2, 2, 2, + rRotVctr, iRotVctr, m); + + + /* update states pointer */ + pStates1 = &pStates1[cldfbBank->no_channels]; + pStates2 = &pStates2[cldfbBank->no_channels]; + pStates3 = &pStates3[cldfbBank->no_channels]; + pStates5 = &pStates5[cldfbBank->no_channels]; + pStates4 = &pStates4[cldfbBank->no_channels]; + pStates6 = &pStates6[cldfbBank->no_channels]; + } + +} + + +/* cldfbSynthesisFiltering + + Parameters: + cldfbBank I/O: handle to analysis CLDFB filter struct + **rAnalysis I: matrix holding the real part of the subband samples + **iAnalysis I: matrix holding the imaginary part of the subband samples + *scaleFactor I: pointer to cldfb scalefactor struct + ov_len I: determines overlapping area in time slots (obsolete) + *timeOut O: pointer to time domain data + stride I: stride for time domain data + *pWorkBuffer I: pointer to scratch buffer, needed for buffer of size 2*cldfbbands*Word32 + 2*cldfbbands*Word16 + + Function: + Performs inverse complex-valued subband filtering of the subband samples in rAnalysis and iAnalysis + and stores the time domain data in timeOut + + Returns: + void +*/ +void +cldfbSynthesisFiltering( HANDLE_CLDFB_FILTER_BANK cldfbBank, + Word32 **rAnalysis, + Word32 **iAnalysis, + const CLDFB_SCALE_FACTOR *scaleFactor, + Word16 *timeOut, + const Word16 timeOut_e, + const Word16 nTimeSlots, + Word32 *pWorkBuffer + ) +{ + Word16 i; + Word16 k; + Word16 L2; + Word16 m; + Word16 m2; + Word16 Lz; + Word16 Mz; + Word32 acc; + Word16 offset1; + Word16 offset2; + Word16 channels0; + Word16 channels1; + Word16 channels2; + Word16 channels3; + Word16 channels4; + Word16 statesSizeM1; + Word16 statesSizeM2; + Word16 stride; + + Word16 scale, scaleMod; + Word16 outScale; + Word16 scaleLB; + Word16 scaleHB; + + Word32 *rAnalysisS; + Word32 *iAnalysisS; + + Word32 *rBuffer; + Word32 *iBuffer; + Word16 *nBuffer; + + Word16 *pStates; + Word16 *pStatesI; + Word16 *pStatesR; + + const Word16 *pFilterS; + const Word16 *pFilterM; + + const Word16 *rRotVctr; + const Word16 *iRotVctr; + Word32 workBuffer[2*BASOP_CFFT_MAX_LENGTH]; + + m = cldfbBank->no_channels; + move16(); + L2 = shl(m,1); + m2 = shr(m,1); + Lz = s_min(cldfbBank->lsb, sub(m,cldfbBank->bandsToZero)); + Mz = s_min(cldfbBank->usb, sub(m,cldfbBank->bandsToZero)); + stride = 1; /* constant */ + + channels0 = sub(m,cldfbBank->zeros); + channels1 = sub(m,1); + channels2 = shl(m,1); + channels3 = add(m,channels2); + channels4 = shl(channels2,1); + + statesSizeM1 = sub(shl(cldfbBank->p_filter_length,1),m); + statesSizeM2 = sub(statesSizeM1,m); + + offset1 = sub(channels1,cldfbBank->zeros); + offset2 = add(offset1,cldfbBank->no_channels); + + rBuffer = &pWorkBuffer[0]; + iBuffer = &pWorkBuffer[m]; + nBuffer = (Word16*)(&pWorkBuffer[L2]); + + rAnalysisS = &pWorkBuffer[3*m]; + iAnalysisS = &pWorkBuffer[4*m]; + + rRotVctr = cldfbBank->rRotVctr; + iRotVctr = cldfbBank->iRotVctr; + + scale = scaleFactor->lb_scale; + move16(); + if ( NE_16(Lz, Mz)) + { + scale = s_max(scale, scaleFactor->hb_scale); + } + scaleLB = limitScale32(sub(scale, scaleFactor->lb_scale)); + scaleHB = limitScale32(sub(scale, scaleFactor->hb_scale)); + + outScale = cldfbBank->synFilterHeadroom; + move16(); + + scaleMod = sub(add(scale, cldfbBank->outScalefactor), outScale); + + /* Increase CLDFB synthesis states for low level signals */ + IF ( LT_16(scale, 8)) + { + scaleMod = add(scaleMod, 2); + outScale = sub(outScale, 2); + } + scaleMod = sub(scaleMod, timeOut_e); + scale = add(outScale, timeOut_e); + IF ( NE_16(scale, cldfbBank->FilterStates_eg)) + { + Scale_sig(cldfbBank->FilterStates, statesSizeM2, sub(cldfbBank->FilterStates_eg, scale)); + cldfbBank->FilterStates_eg = scale; + move16(); + } + + FOR (k=0; k < nTimeSlots; k++) + { + { + FOR (i=0; i < Lz; i+=2) + { + rAnalysisS[i] = L_shr(rAnalysis[k][i],scaleLB); + move32(); + iAnalysisS[i] = L_negate(L_shr(iAnalysis[k][i],scaleLB)); + move32(); + } + + IF ( LT_16(i,Mz)) + { + FOR ( ; i < Mz; i+=2) + { + rAnalysisS[i] = L_shr(rAnalysis[k][i],scaleHB); + move32(); + iAnalysisS[i] = L_negate(L_shr(iAnalysis[k][i],scaleHB)); + move32(); + } + } + + IF ( LT_16(i,m)) + { + FOR ( ; i < m; i+=2) + { + rAnalysisS[i] = L_deposit_l(0); + iAnalysisS[i] = L_deposit_l(0); + } + } + + FOR (i=1; i < Lz; i+=2) + { + rAnalysisS[i] = L_shr(rAnalysis[k][i],scaleLB); + move32(); + iAnalysisS[i] = L_shr(iAnalysis[k][i],scaleLB); + move32(); + } + + IF ( LT_16(i,Mz)) + { + FOR ( ; i < Mz; i+=2) + { + rAnalysisS[i] = L_shr(rAnalysis[k][i],scaleHB); + move32(); + iAnalysisS[i] = L_shr(iAnalysis[k][i],scaleHB); + move32(); + } + } + + IF ( LT_16(i,m)) + { + FOR ( ; i < m; i+=2) + { + rAnalysisS[i] = L_deposit_l(0); + iAnalysisS[i] = L_deposit_l(0); + } + } + } + + /* pre modulation */ + calcModulation(&rBuffer[0], &rBuffer[1], &rAnalysisS[0], &rAnalysisS[m-1], 2, 2, 2,-2, + &iBuffer[0], &iBuffer[1], &iAnalysisS[0], &iAnalysisS[m-1], 2, 2, 2,-2, + rRotVctr, iRotVctr, m); + + + /* FFT of DST IV */ + scale = 0; + move16(); + BASOP_cfft((cmplx *)rBuffer, m2, &scale, workBuffer); + + /* FFT of DCT IV */ + scale = scaleMod; + move16(); + BASOP_cfft((cmplx *)iBuffer, m2, &scale, workBuffer); + + /* post modulation and folding */ + calcModulationAndFolding(nBuffer, rBuffer, iBuffer, rRotVctr, iRotVctr, cldfbBank->synGain, scale, m, m2); + + /* prototype filter */ + pStates = &cldfbBank->FilterStates[k*L2]; + pFilterS = &cldfbBank->p_filter[0]; + pFilterM = &cldfbBank->p_filter[shr(cldfbBank->p_filter_length,1)]; + + FOR (i=0; i < channels0; i++) + { + pStatesI = &pStates[i]; + pStatesR = &pStates[i+channels3]; + + acc = L_mult( *pStatesI, *pFilterS++); + acc = L_mac(acc, *pStatesR, *pFilterM++); + pStatesR += channels4; + pStatesI += channels4; + + acc = L_mac(acc, *pStatesI, *pFilterS++); + acc = L_mac(acc, *pStatesR, *pFilterM++); + pStatesR += channels4; + pStatesI += channels4; + + acc = L_mac(acc, *pStatesI, *pFilterS++); + acc = L_mac(acc, *pStatesR, *pFilterM++); + pStatesR += channels4; + pStatesI += channels4; + + acc = L_mac(acc, *pStatesI, *pFilterS++); + acc = L_mac(acc, *pStatesR, *pFilterM++); + pStatesI += channels4; + + acc = L_mac(acc, *pStatesI, *pFilterS++); + acc = L_mac(acc, nBuffer[channels1-i], *pFilterM++); + + BASOP_SATURATE_WARNING_OFF + timeOut[(offset1-i)*stride] = round_fx(L_shl(acc,outScale)); + BASOP_SATURATE_WARNING_ON + } + + FOR ( ; ino_channels; i++) + { + pStatesI = &pStates[i+channels2]; + pStatesR = &pStates[i+channels2+channels3]; + + acc = L_mult( *pStatesI, *pFilterS++); + acc = L_mac(acc, *pStatesR, *pFilterM++); + pStatesR += channels4; + pStatesI += channels4; + + acc = L_mac(acc, *pStatesI, *pFilterS++); + acc = L_mac(acc, *pStatesR, *pFilterM++); + pStatesR += channels4; + pStatesI += channels4; + + acc = L_mac(acc, *pStatesI, *pFilterS++); + acc = L_mac(acc, *pStatesR, *pFilterM++); + pStatesR += channels4; + pStatesI += channels4; + + acc = L_mac(acc, *pStatesI, *pFilterS++); + acc = L_mac(acc, *pStatesR, *pFilterM++); + + acc = L_mac(acc, nBuffer[channels1+m-i], *pFilterS++); + pFilterM++; + + BASOP_SATURATE_WARNING_OFF + timeOut[(offset2-i)*stride] = round_fx(L_shl(acc,outScale)); + BASOP_SATURATE_WARNING_ON + } + + FOR (i=0; ino_channels; i++) + { + pStates[statesSizeM1+i] = nBuffer[channels1-i]; + move16(); + pStates[statesSizeM2+i] = nBuffer[channels1+m-i]; + move16(); + } + + timeOut = &timeOut[m*stride]; + } + + /* move filter states */ + Copy(&cldfbBank->FilterStates[i_mult(nTimeSlots,L2)], cldfbBank->FilterStates, statesSizeM2); + set16_fx(&cldfbBank->FilterStates[statesSizeM2],0,L2); + +} + + +/*-------------------------------------------------------------------* + * configureClfdb() + * + * configures a CLDFB handle + *--------------------------------------------------------------------*/ + +void configureCldfb ( HANDLE_CLDFB_FILTER_BANK h_cldfb, /*!< Returns handle */ + const Word16 no_channels, /*!< Number of channels (bands) */ + const Word16 frameSize /*!< FrameSize */ + ) +{ + + h_cldfb->no_channels = no_channels; + move16(); + assert(h_cldfb->no_channels >= 10); + h_cldfb->no_col = div_l(frameSize,shr(h_cldfb->no_channels,1)); + + /* was cldfbInitFilterBank()*/ + h_cldfb->anaScalefactor = 0; + move16(); + h_cldfb->synScalefactor = 0; + move16(); + h_cldfb->bandsToZero = 0; + move16(); + h_cldfb->filtermode = 0; + move16(); + h_cldfb->memory = 0; + move16(); + h_cldfb->memory_length = 0; + move16(); + + h_cldfb->p_filter_length = i_mult(10,h_cldfb->no_channels); + move16(); + + h_cldfb->flags = s_or(h_cldfb->flags,CLDFB_FLAG_2_5MS_SETUP); + h_cldfb->filterScale = CLDFB_CLDFB80_PFT_SCALE; + move16(); + + h_cldfb->zeros = 0; + move16(); + h_cldfb->synFilterHeadroom = SYN_FILTER_HEADROOM_2_5MS; + move16(); + + cldfb_init_proto_and_twiddles (h_cldfb); + + h_cldfb->lsb = no_channels; + move16(); + h_cldfb->usb = s_min(no_channels, h_cldfb->no_channels); /* Does this make any sense? in the previous implemenatation lsb, usb and no_channels are all maxCldfbBands */ move16(); + + h_cldfb->FilterStates = (void*)h_cldfb->FilterStates; + h_cldfb->outScalefactor = h_cldfb->synScalefactor; + move16(); + + return; +} + +/*-------------------------------------------------------------------* + * openClfdb() + * + * open and configures a CLDFB handle + *--------------------------------------------------------------------*/ +void openCldfb ( HANDLE_CLDFB_FILTER_BANK *h_cldfb, /*!< Returns handle */ + const Word16 type, /*!< analysis or synthesis */ + const Word16 maxCldfbBands, /*!< number of cldfb bands */ + const Word16 frameSize /*!< FrameSize */ + ) +{ + HANDLE_CLDFB_FILTER_BANK hs; + + hs = (HANDLE_CLDFB_FILTER_BANK) calloc(1, sizeof (struct CLDFB_FILTER_BANK)); + + + hs->type = type; + move16(); + + IF (type == CLDFB_ANALYSIS) + { + hs->FilterStates = (Word16 *) calloc(STATE_BUFFER_SIZE*maxCldfbBands, sizeof (Word16)); + } + ELSE + { + hs->FilterStates = (Word16 *) calloc( 2 * STATE_BUFFER_SIZE * maxCldfbBands, sizeof (Word16)); + } + hs->flags &= ~CLDFB_FLAG_KEEP_STATES; + + configureCldfb (hs, maxCldfbBands, frameSize ); + + hs->memory = NULL; + hs->memory_length = 0; + move16(); + + IF( hs->type == CLDFB_ANALYSIS) + { + test(); + IF ( (s_and(hs->flags,CLDFB_FLAG_KEEP_STATES) == 0) && (hs->FilterStates != 0) ) + { + set16_fx(hs->FilterStates, 0, i_mult(STATE_BUFFER_SIZE,hs->no_channels)); + set16_fx(hs->FilterStates_e, 0, sizeof(hs->FilterStates_e)/sizeof(hs->FilterStates_e[0])); + + hs->FilterStates_eg = 0; + move16(); + } + } + ELSE IF (hs->type == CLDFB_SYNTHESIS ) + { + IF ( hs->FilterStates != 0 ) + { + IF ( s_and(hs->flags,CLDFB_FLAG_KEEP_STATES) == 0 ) + { + set16_fx(hs->FilterStates, 0, i_mult( shl(STATE_BUFFER_SIZE,1), hs->no_channels)); + } + } + hs->FilterStates_eg = 0; + move16(); + } + + if (h_cldfb != NULL) + { + *h_cldfb = hs; + } + + return; +} + + +/*-------------------------------------------------------------------* +* resampleCldfb() +* +* Change sample rate of filter bank +*--------------------------------------------------------------------*/ +void resampleCldfb (HANDLE_CLDFB_FILTER_BANK hs, + const Word16 newCldfbBands, + const Word16 frameSize, + const Word8 firstFrame + ) + +{ + Word16 timeOffset; + Word16 timeOffsetOld; + Word16 noChannelsOld; + + noChannelsOld = hs->no_channels; + move16(); + timeOffsetOld = sub(sub(hs->p_filter_length,hs->no_channels),hs->zeros); + + /* change all CLDFB bank parameters that depend on the no of channels */ + hs->flags = s_or(hs->flags,CLDFB_FLAG_KEEP_STATES); + move16(); + + /* new settings */ + configureCldfb (hs, newCldfbBands, frameSize); + + /* resample cldfb state buffer */ + timeOffset = sub(sub(hs->p_filter_length,hs->no_channels),hs->zeros); + + IF( firstFrame == 0 ) + { + /*low complexity-resampling only stored previous samples that are needed for next frame modulation */ + lerp(hs->FilterStates+(noChannelsOld*hs->no_col), hs->FilterStates+(noChannelsOld*hs->no_col), timeOffset, timeOffsetOld); + Copy(hs->FilterStates+(noChannelsOld*hs->no_col), hs->FilterStates+frameSize, timeOffset); + } + + return; +} + +/* + AnalysisPostSpectrumScaling_Fx + + Parameters: + cldfbBank I: CLDFB handle + **rSubband32 I: matrix holding real part of the CLDFB subsamples + **iSubband32 I: matrix holding imaginary part of the CLDFB subsamples + **rSubband16 O: matrix holding real part of the CLDFB subsamples + **iSubband16 O: matrix holding imaginary part of the CLDFB subsamples + *cldfbScale O: cldfb lowband scalefactor + + Function: + performs dynamic spectrum scaling for all subband + + Returns: + headroom +*/ +Word16 +AnalysisPostSpectrumScaling_Fx (HANDLE_CLDFB_FILTER_BANK cldfbBank, /*!< Handle of cldfbBank */ + Word32 **rSubband32, /*!< Real bands */ + Word32 **iSubband32, /*!< Imaginary bands */ + Word16 **rSubband16, /*!< Real bands */ + Word16 **iSubband16, /*!< Imaginary bands */ + Word16 *cldfbScale /*!< CLDFB lowband scalefactor */ + ) +{ + Word16 i; + Word16 j; + Word16 headRoom; + + + + headRoom = BASOP_util_norm_l_dim2_cplx ( + (const Word32 * const*) rSubband32, + (const Word32 * const*) iSubband32, + 0, + cldfbBank->no_channels, + 0, + cldfbBank->no_col + ); + + FOR (i=0; i < cldfbBank->no_col; i++) + { + FOR (j=0; j < cldfbBank->no_channels; j++) + { + rSubband16[i][j] = round_fx(L_shl(rSubband32[i][j], headRoom)); + iSubband16[i][j] = round_fx(L_shl(iSubband32[i][j], headRoom)); + } + } + + *cldfbScale = add(*cldfbScale,headRoom); + move16(); + + + return headRoom; +} + + +/*-------------------------------------------------------------------* +* analysisCLDFBEncoder() +* +* Encoder CLDFB analysis + energy stage +*--------------------------------------------------------------------*/ + +void analysisCldfbEncoder_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *timeIn, + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 realBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 imagBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 enerBuffSum[CLDFB_NO_CHANNELS_MAX], + Word16 *enerBuffSum_exp, + CLDFB_SCALE_FACTOR * scale +) +{ + Word16 i; + CLDFB_SCALE_FACTOR enerScale; + Word32 *ppBuf_Real[CLDFB_NO_COL_MAX]; + Word32 *ppBuf_Imag[CLDFB_NO_COL_MAX]; + Word16 *ppBuf_Real16[CLDFB_NO_COL_MAX]; + Word16 *ppBuf_Imag16[CLDFB_NO_COL_MAX]; + Word32 workBuffer[256]; + Word16 num_slots = 1; + + FOR (i=0; icldfbAna_Fx, + ppBuf_Real, + ppBuf_Imag, + scale, + timeIn, + 0, + CLDFB_NO_COL_MAX, + workBuffer + ); + + enerScale.lb_scale = negate(scale->lb_scale); + enerScale.lb_scale16 = negate(scale->lb_scale); + + /* get 16bit respresentation */ + AnalysisPostSpectrumScaling_Fx ( + st_fx->cldfbAna_Fx, + ppBuf_Real, + ppBuf_Imag, + ppBuf_Real16, + ppBuf_Imag16, + &enerScale.lb_scale16 + ); + + /* get the energy */ + GetEnergyCldfb( &st_fx->energyCoreLookahead_Fx, + &st_fx->sf_energyCoreLookahead_Fx, + num_slots, + ppBuf_Real16, + ppBuf_Imag16, + enerScale.lb_scale16, + st_fx->cldfbAna_Fx->no_channels, + st_fx->cldfbAna_Fx->no_col, + &st_fx->currEnergyHF_fx, + &st_fx->currEnergyHF_e_fx, + enerBuffSum, + enerBuffSum_exp, + &st_fx->tecEnc + ); + + return; +} + +void +GetEnergyCldfb( Word32 *energyLookahead, /*!< o: Q(*sf_energyLookahead) | pointer to the result in the core look-ahead slot */ + Word16 *sf_energyLookahead, /*!< o: pointer to the scalefactor of the result in the core look-ahead slot */ + const Word16 numLookahead, /*!< i: Q0 the number of look-ahead time-slots */ + Word16 **realValues, /*!< i: Q(sf_Values) | the real part of the CLDFB subsamples */ + Word16 **imagValues, /*!< i: Q(sf_Values) | the imaginary part of the CLDFB subsamples */ + Word16 sf_Values, /*!< i: scalefactor of the CLDFB subcamples - apply as a negated Exponent */ + Word16 numberBands, /*!< i: Q0 | number of CLDFB bands */ + Word16 numberCols, /*!< i: Q0 | number of CLDFB subsamples */ + Word32 *energyHF, /*!< o: Q31 | pointer to HF energy */ + Word16 *energyHF_Exp, /*!< o: pointer to exponent of HF energy */ + Word32 *energyValuesSum, /*!< o: Q(2*sf_Values-4) | pointer to sum array of energy values, not initialized*/ + Word16 *energyValuesSum_Exp,/*!< o: pointer to exponents of energyValuesSum, not initialized */ + HANDLE_TEC_ENC_FX hTecEnc + ) +{ + Word16 j; + Word16 k; + Word16 s; + Word16 sm; + Word32 nrg; + Word16 numberColsL; + Word16 numberBandsM; + Word16 numberBandsM20; + Word32 energyValues[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word16 energyValuesSumE[CLDFB_NO_CHANNELS_MAX]; + Word16 freqTable[2] = {20, 40}; + + + FOR (k=0; kloBuffer, + hTecEnc->hiTempEnv, + ScaleX2 + ); + } + + FOR (j=0; j< numberBands; j++) + { + energyValuesSum[j] = L_deposit_l(0); + energyValuesSumE[j] = 31; + move16(); + FOR (k=0; k value 0x40000000, scale 44 */ + *energyLookahead = L_add(L_shr(nrg, sub(s, sm)), + L_shr(0x40000000, s_max(-31, s_min(31, sub(44, sm))))); + move32(); + BASOP_SATURATE_WARNING_ON + *sf_energyLookahead = sm; + move16(); + + return; + } + + + + *energyHF = 0x40000000; + move32(); + *energyHF_Exp = 17; + move16(); + + +} + + +Word16 +CLDFB_getNumChannels(Word32 sampleRate) +{ + + Word16 nChannels = 0; + + + SWITCH (sampleRate) + { + case 48000: + move16(); + nChannels = 60; + BREAK; + case 32000: + move16(); + nChannels = 40; + BREAK; + case 25600: + move16(); + nChannels = 32; + BREAK; + case 16000: + move16(); + nChannels = 20; + BREAK; + case 12800: + move16(); + nChannels = 16; + BREAK; + case 8000: + move16(); + nChannels = 10; + BREAK; + } + + return (nChannels); +} + +/*-------------------------------------------------------------------* +* cldfb_get_memory_length() +* +* Return length of filter state for recovery +*--------------------------------------------------------------------*/ +static Word16 +cldfb_get_memory_length (HANDLE_CLDFB_FILTER_BANK hs) +{ + IF (EQ_16(hs->type,CLDFB_ANALYSIS)) + { + return (i_mult(hs->no_channels,STATE_BUFFER_SIZE)); + } + ELSE + { + return (i_mult(hs->no_channels,(9*2)) ); + } +} + +/*-------------------------------------------------------------------* +* GetEnergyCldfb() +* +* Remove handle +*--------------------------------------------------------------------*/ +void +deleteCldfb (HANDLE_CLDFB_FILTER_BANK * h_cldfb) /* i: cldfb handle */ +{ + IF ( *h_cldfb != NULL ) + { + IF ( (*h_cldfb)->FilterStates != NULL ) + { + free((*h_cldfb)->FilterStates); + } + free(*h_cldfb); + } + *h_cldfb = NULL; +} + + +/*-------------------------------------------------------------------* +* cldfb_init_proto_and_twiddles() +* +* Initializes rom pointer +*--------------------------------------------------------------------*/ +static void +cldfb_init_proto_and_twiddles(HANDLE_CLDFB_FILTER_BANK hs) /* i: cldfb handle */ +{ + + /*find appropriate set of rotVecs*/ + SWITCH(hs->no_channels) + { + case 10: + + hs->rRotVctr = rRotVectr_10; + hs->iRotVctr = iRotVectr_10; + hs->synGain = cldfb_synGain[0]; + move16(); + hs->p_filter = cldfb_protoFilter_2_5ms[0]; + hs->scale = cldfb_scale_2_5ms[0]; + move16(); + IF (hs->type == CLDFB_SYNTHESIS ) + { + hs->synScalefactor = add(cldfb_synScale[0],hs->filterScale); + move16(); + } + ELSE + { + hs->anaScalefactor = add(cldfb_anaScale[0],hs->filterScale); + move16(); + } + break; + + case 16: + hs->rRotVctr = rRotVectr_16; + hs->iRotVctr = iRotVectr_16; + hs->synGain = cldfb_synGain[1]; + move16(); + hs->p_filter = cldfb_protoFilter_2_5ms[1]; + hs->scale = cldfb_scale_2_5ms[1]; + move16(); + { + hs->anaScalefactor = add(cldfb_anaScale[1],hs->filterScale); + move16(); + } + break; + + case 20: + hs->rRotVctr = rRotVectr_20; + hs->iRotVctr = iRotVectr_20; + hs->synGain = cldfb_synGain[2]; + move16(); + hs->p_filter = cldfb_protoFilter_2_5ms[2]; + hs->scale = cldfb_scale_2_5ms[2]; + move16(); + IF (hs->type == CLDFB_SYNTHESIS ) + { + hs->synScalefactor = add(cldfb_synScale[2],hs->filterScale); + move16(); + } + ELSE + { + hs->anaScalefactor = add(cldfb_anaScale[2],hs->filterScale); + move16(); + } + break; + + case 32: + hs->rRotVctr = rRotVectr_32; + hs->iRotVctr = iRotVectr_32; + hs->synGain = cldfb_synGain[3]; + move16(); + hs->p_filter = cldfb_protoFilter_2_5ms[3]; + hs->scale = cldfb_scale_2_5ms[3]; + move16(); + { + hs->anaScalefactor = add(cldfb_anaScale[3],hs->filterScale); + move16(); + } + break; + + case 40: + hs->rRotVctr = rRotVectr_40; + hs->iRotVctr = iRotVectr_40; + hs->synGain = cldfb_synGain[4]; + move16(); + hs->p_filter = cldfb_protoFilter_2_5ms[4]; + hs->scale = cldfb_scale_2_5ms[4]; + move16(); + IF (hs->type == CLDFB_SYNTHESIS ) + { + hs->synScalefactor = add(cldfb_synScale[4],hs->filterScale); + move16(); + } + ELSE + { + hs->anaScalefactor = add(cldfb_anaScale[4],hs->filterScale); + move16(); + } + break; + + case 60: + hs->rRotVctr = rRotVectr_60; + hs->iRotVctr = iRotVectr_60; + hs->synGain = cldfb_synGain[5]; + move16(); + hs->p_filter = cldfb_protoFilter_2_5ms[5]; + hs->scale = cldfb_scale_2_5ms[5]; + move16(); + IF (hs->type == CLDFB_SYNTHESIS ) + { + hs->synScalefactor = add(cldfb_synScale[5],hs->filterScale); + move16(); + } + ELSE + { + hs->anaScalefactor = add(cldfb_anaScale[5],hs->filterScale); + move16(); + } + break; + + } +} + + +#define CLDFB_MEM_EXPONENTS (CLDFB_NO_COL_MAX+9) + +/*-------------------------------------------------------------------* +* cldfb_save_memory() +* +* Save the memory of filter; to be restored with cldfb_restore_memory() +*--------------------------------------------------------------------*/ +void +cldfb_save_memory (HANDLE_CLDFB_FILTER_BANK hs) /* i: cldfb handle */ +{ + + hs->memory_length = cldfb_get_memory_length(hs); + hs->memory = (Word16 *) calloc( hs->memory_length + CLDFB_MEM_EXPONENTS + 1, sizeof (Word16)); + + + /* save the memory */ + Copy (hs->FilterStates, hs->memory, hs->memory_length); + Copy (hs->FilterStates_e, hs->memory+hs->memory_length, CLDFB_MEM_EXPONENTS); + hs->memory[hs->memory_length+CLDFB_MEM_EXPONENTS] = hs->FilterStates_eg; + move16(); + + return; +} + + +/*-------------------------------------------------------------------* +* cldfb_restore_memory() +* +* Restores the memory of filter; memory to be save by cldfb_save_memory() +*--------------------------------------------------------------------*/ +void +cldfb_restore_memory (HANDLE_CLDFB_FILTER_BANK hs) /* i/o: cldfb handle */ + +{ + Word16 size; + + + size = cldfb_get_memory_length(hs); + + /* read the memory */ + Copy (hs->memory, hs->FilterStates, hs->memory_length); + Copy (hs->memory+hs->memory_length, hs->FilterStates_e, CLDFB_MEM_EXPONENTS); + hs->FilterStates_eg = hs->memory[hs->memory_length+CLDFB_MEM_EXPONENTS]; + move16(); + + /* adjust sample rate if it was changed in the meanwhile */ + IF (NE_16 (hs->memory_length,size)) + { + lerp(hs->FilterStates, hs->FilterStates, size, hs->memory_length); + } + + hs->memory_length = 0; + free(hs->memory); + hs->memory = NULL; + + return; +} + +/*-------------------------------------------------------------------* +* cldfb_reset_memory() +* +* Resets the memory of filter. +*--------------------------------------------------------------------*/ +void +cldfb_reset_memory (HANDLE_CLDFB_FILTER_BANK hs) /* i/o: cldfb handle */ +{ + Word16 length; + + length = cldfb_get_memory_length(hs); + /* erase the memory */ + set16_fx (hs->FilterStates, 0, length); + set16_fx (hs->FilterStates_e, 0, sizeof(hs->FilterStates_e)/sizeof(hs->FilterStates_e[0])); + hs->FilterStates_eg = 0; + move16(); +} + diff --git a/lib_com/cng_exc_fx.c b/lib_com/cng_exc_fx.c new file mode 100644 index 0000000..b0249f6 --- /dev/null +++ b/lib_com/cng_exc_fx.c @@ -0,0 +1,890 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "rom_com_fx.h" + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ +#define A2 6554 +#define OmA2 (32768-A2) +#define GAIN_VAR 11811 /* in Q31 divided by 2 (Q30) */ + +/*-------------------------------------------------------* + * CNG_exc() + * + * Comfort noise generation routine + *-------------------------------------------------------*/ + +void CNG_exc_fx( + const Word32 core_brate, /* i : core bitrate */ + const Word16 L_frame, /* i : length of the frame */ + Word32 *Enew, /* i/o: decoded SID energy Q6 */ + Word16 *seed, /* i/o: random generator seed */ + Word16 exc[], /* o : current non-enhanced excitation Q_new */ + Word16 exc2[], /* o : current enhanced excitation Q_new */ + Word32 *lp_ener, /* i/o: LP filtered E */ + const Word32 last_core_brate, /* i : previous frame core bitrate */ + Word16 *first_CNG, /* i/o: first CNG frame flag for energy init. */ + Word16 *cng_ener_seed, /* i/o: random generator seed for CNG energy */ + Word16 bwe_exc[], /* o : excitation for SWB TBE */ + const Word16 allow_cn_step, /* i : allow CN step */ + Word16 *last_allow_cn_step, /* i/o: last allow step */ + const Word16 OldQ_exc, /* i : Old excitation scaling */ + const Word16 Q_exc /* i : excitation scaling */ + , const Word16 num_ho /* i : number of selected hangover frames */ + ,Word32 q_env[] + ,Word32 *lp_env + ,Word32 *old_env + ,Word16 *exc_mem + ,Word16 *exc_mem1 + ,Word16 *sid_bw + ,Word16 *cng_ener_seed1 + ,Word16 exc3[] + ,Word16 Opt_AMR_WB +) +{ + Word16 i, tmp, tmp2, exp, exp2, Q_ener; + Word32 L_tmp_ener, L_tmp; + Word16 i_subfr; + Word16 pit_max; + Word16 ftmp,j; + Word16 *ptR,*ptI; + Word16 fft_io[L_FRAME16k]; + Word32 itmp[129]; + Word32 env[NUM_ENV_CNG]; + Word32 enr1; + Word32 denv[NUM_ENV_CNG]; + Word16 fra; + Word16 temp_lo_fx, temp_hi_fx; + Word16 exp_pow; + Word32 L_tmp2; + Word16 *pt_fft_io; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + pit_max = PIT16k_MAX; + move16(); + if( EQ_16(L_frame,L_FRAME)) + { + pit_max = PIT_MAX; + move16(); + } + + /*---------------------------------------------------------------------* + * Initialization of CNG energy for the first CNG frame + *---------------------------------------------------------------------*/ + + IF(*first_CNG == 0 ) + { + IF(EQ_32(core_brate,FRAME_NO_DATA)) + { + /* needed only in decoder when the very first SID frame was erased and this frame is FRAME_NO_DATA frame */ + /*fenew = dotp( fexc, fexc, pit_max )/pit_max;*/ + L_tmp_ener = Calc_Energy_Autoscaled(exc-pit_max, OldQ_exc, pit_max, &Q_ener); + L_tmp_ener = Mult_32_16(L_tmp_ener, 9079); /* divide by PIT_MAX (in Q15 + Q6 to get output in Q6)*/ + L_tmp_ener = L_shr(L_tmp_ener, Q_ener); /* -> If we want ener in Q6 */ + + if(EQ_16(L_frame, L_FRAME16k)) + { + L_tmp_ener = Mult_32_16(L_tmp_ener, 26214); /* Compensate for 16kHz */ + } + *Enew = L_tmp_ener; + move32(); + } + + *lp_ener = *Enew; + move32(); + } + + /*---------------------------------------------------------------------* + * Update CNG energy + *---------------------------------------------------------------------*/ + test(); + test(); + IF( NE_32(last_core_brate,SID_1k75)&&NE_32(last_core_brate,FRAME_NO_DATA)&&NE_32(last_core_brate,SID_2k40)) + { + /* Partially reset CNG energy after active speech period */ + test(); + IF ( allow_cn_step == 0 && *last_allow_cn_step == 0 ) + { + test(); + IF( LT_16(num_ho,3)||LT_32(Mult_32_16(*Enew,21845/*1/1.5f, Q15*/),*lp_ener)) + { + /**lp_ener = 0.8f * *lp_ener + 0.2f * *Enew;*/ + L_tmp_ener = Mult_32_16(*lp_ener, 26214); + L_tmp_ener = Madd_32_16(L_tmp_ener, *Enew, 6554); + + } + ELSE + { + /**lp_ener = 0.95f * *lp_ener + 0.05f * *Enew;*/ + L_tmp_ener = Mult_32_16(*lp_ener, 31130); + L_tmp_ener = Madd_32_16(L_tmp_ener, *Enew, 1638); + } + } + ELSE + { + L_tmp_ener = *Enew; + move32(); + *last_allow_cn_step = 0; + move16(); + } + } + ELSE + { + /* normal CNG update */ + IF ( *last_allow_cn_step == 0 ) + { + /**lp_ener = (float)(A2 * *Enew + (1-A2) * *lp_ener);*/ + L_tmp_ener = Mult_32_16(*Enew, A2); + L_tmp_ener = Madd_32_16(L_tmp_ener, *lp_ener, OmA2); + } + ELSE + { + test(); + if ( EQ_32(core_brate,SID_1k75)||EQ_32(core_brate,SID_2k40)) + { + *last_allow_cn_step = 0; + move16(); + } + + L_tmp_ener = *Enew; + move32(); + + } + } + *lp_ener = L_max(L_tmp_ener,1); + move32(); /*To avoid / per 0*/ + + if ( EQ_16(allow_cn_step,1)) + { + *last_allow_cn_step = 1; + move16(); + } + + /*---------------------------------------------------------------------* + * Generate white noise vector + *---------------------------------------------------------------------*/ + + /*for ( i=0; i Q_exc +16 */ + exc2[i_subfr+i] = round_fx(L_shl(L_tmp, exp)); + } + } + IF ( NE_16(Opt_AMR_WB,1)) + { + Copy( exc2, exc3, L_FRAME16k); + + /* enr1 = (float)log10( *Enew*L_frame + 0.1f ) / (float)log10( 2.0f ); */ + exp = norm_l(*Enew); + L_tmp = L_shl(*Enew,exp); /* Q(exp+6) */ + L_tmp = Mult_32_16(L_tmp,shl(L_frame,5)); /* Q(exp+6+5-15=exp-4) */ + L_tmp = L_shr(L_tmp,sub(exp,10)); /* Q6 */ + + exp = norm_l(L_tmp); + fra = Log2_norm_lc(L_shl(L_tmp,exp)); + exp = sub(sub(30,exp),6); + L_tmp = L_Comp(exp,fra); + /* enr1 = round_fx(L_shl(L_tmp,8)); */ /*Q8 */ + enr1 = L_shr(L_tmp,10);/* Q6 */ + + + IF ( EQ_32(core_brate,SID_2k40)) + { + IF ( *sid_bw == 0 ) + { + FOR ( i=0; iHQ switching gap in ms */ +#define HQ_DELAY_COMP NS2SA(8000, DELAY_CLDFB_NS) +#define HQ_DELTA_MAX 6 /* maximum multiplication factor (==48kHz/8kHz) for core switching modules */ + +#define N_ZERO_MDCT_NS 5625000L /* Number of zeros in ms for MDCT */ +#define NL_BUFF_OFFSET 12 + +#define N_WS2N_FRAMES 40 /* number of frames for attenuation during the band-width switching */ +#define N_NS2W_FRAMES 20 /* number of frames for attenuation during the band-width switching */ + +/*----------------------------------------------------------------------------------* + * Coder types (only for ACELP core when not running in AMR-WB IO mode) + *----------------------------------------------------------------------------------*/ + +#define INACTIVE 0 /* inactive */ +#define UNVOICED 1 /* unvoiced */ +#define VOICED 2 /* purely voiced */ +#define GENERIC 3 /* generic */ +#define TRANSITION 4 /* transition */ +#define AUDIO 5 /* audio (GSC) */ +#define LR_MDCT 6 /* low-rate MDCT core */ + + +/*--------------------------------------------------* + * Partial copy frame types (only for ACELP core ) + *--------------------------------------------------*/ + +/* TCX partial copy frame types */ +#define RF_NO_DATA 0 +#define RF_TCXFD 1 +#define RF_TCXTD1 2 +#define RF_TCXTD2 3 +/* ACELP partial copy frame types */ +#define RF_ALLPRED ACELP_MODE_MAX +#define RF_NOPRED ACELP_MODE_MAX + 1 +#define RF_GENPRED ACELP_MODE_MAX + 2 +#define RF_NELP ACELP_MODE_MAX + 3 + + +/*--------------------------------------------------------------* + * MODE2 Frame length constants + *---------------------------------------------------------------*/ + +#define L_FRAME_MAX 960 /* Max 20ms frame size @48kHz */ +#define L_FRAME_PLUS 1200 /* Max frame size (long TCX frame) */ +#define L_MDCT_OVLP_MAX NS2SA(48000,ACELP_LOOK_NS) /* = Max mdct overlap */ +#define N_TCX10_MAX 480 /* Max size of TCX10 MDCT size */ +#define BITS_TEC 1 /* number of bits for TEC */ +#define BITS_TFA 1 /* number of bits for TTF */ +#define N_TEC_TFA_SUBFR 16 /* number of subframes of TEC/TFA */ +#define L_TEC_TFA_SUBFR16k (L_FRAME16k/N_TEC_TFA_SUBFR) /* TEC/TFA subframe size @ 16kHz*/ +#define MAX_TEC_SMOOTHING_DEG 6 /* max degree of smoothing for TEC */ +#define N_MAX 1200 /* Max size of MDCT spectrum = 25ms @ 48kHz */ +#define N_MAX_TCX 1000 /* Max size of MDCT spectrum = 25ms @ 48kHz */ +#define IGF_START_MN 164 /* MDCT lines not used by IGF*/ +#define IGF_START_MX 800 /* max. MDCT lines used by IGF*/ + +#define L_FRAME_12k8 256 /* Frame size at 12k8Hz: 20ms = 256 samples */ +#define L_FRAME_16k 320 /* Frame size at 16kHz: 20ms = 320 samples */ +#define L_NEXT_MAX_12k8 112 /* maximum encoder lookahead at 12k8Hz */ +#define L_PAST_MAX_12k8 144 /* maximum encoder past samples at 12k8Hz */ +#define L_DIV 256 /* 20ms frame size (ACELP or short TCX frame) */ +#define L_DIV_MAX 320 +#define NB_DIV 2 /* number of division (frame) per 20ms frame */ +#define NB_SUBFR 4 /* number of 5ms subframe per 20ms frame */ + +#define L_NEXT_MAX_16k 140 /* maximum encoder lookahead at 16kHz */ +#define L_NEXT_MAX_32k 280 /* maximum encoder lookahead at 32kHz */ +#define L_PAST_MAX_32k 360 /* maximum encoder past samples at 32kHz */ + +#define MIDLSF_NBITS 5 +#define ENDLSF_NBITS 31 + +/*----------------------------------------------------------------------------------* + * ACELP core constants + *----------------------------------------------------------------------------------*/ + +#define SAFETY_NET 0 +#define MOVING_AVERAGE 1 +#define AUTO_REGRESSIVE 2 + +#define ACELP_MODE_MAX 4 + +#define RF_MODE_MAX 4 + +#define M 16 /* order of the LP filter @ 12.8kHz */ +#define L_FRAME 256 /* frame size at 12.8kHz */ +#define NB_SUBFR 4 /* number of subframes per frame */ +#define L_SUBFR (L_FRAME/NB_SUBFR) /* subframe size */ +#define L_SUBFR_Q6 ((L_FRAME/NB_SUBFR)*64) /* subframe size */ +#define L_SUBFR_Q16 ((L_FRAME/NB_SUBFR)*65536) /* subframe size */ + +#define L_INP_MEM (L_LOOK_16k + ((L_LP_16k - (NS2SA(INT_FS_16k, ACELP_LOOK_NS) + L_SUBFR16k/2)) - 3*L_SUBFR16k/2)) /* length of memory of input signal, given by the Look-Ahead + the past memory (max needed for the LP window at 16 kHz) */ +#define L_INP_12k8 (L_INP_MEM + L_FRAME) /* length of input signal buffer @12.8kHz */ +#define L_INP (L_INP_MEM + L_FRAME32k) /* length of input signal buffer */ + +#define L_EXC_MEM L_FRAME16k /*(PIT16k_MAX + L_INTERPOL)*/ /* length of memory of excitation signal */ +#define L_EXC_MEM_12k8 (PIT_MAX + L_INTERPOL) /* length of memory of excitation signal @12.8kHz */ +#define L_EXC_MEM_DEC (3*L_FRAME16k/2) /*Half-frame needed for MODE2 PLC in case of TCX->ACELP*/ +#define L_EXC (L_EXC_MEM + L_FRAME16k + 1) /* length of excitation signal buffer */ +#define L_EXC_DEC (L_EXC_MEM_DEC + L_FRAME16k + 1 + L_SUBFR) /* length of decoder excitation signal buffer @16kHz*/ +#define L_SYN_MEM NS2SA(48000,DELAY_CLDFB_NS) /* synthesis memory length, 1.25ms @ 48kHz */ +#define L_SYN (L_SYN_MEM + L_FRAME16k) /* length of synthesis signal buffer */ +#define L_WSP_MEM (PIT_MAX + L_INTERPOL) /* length of memory for weighted input signal */ +#define L_WSP (L_WSP_MEM + L_FRAME + L_LOOK_12k8) /* length of weighted input signal buffer */ + +#define OLD_SYNTH_SIZE_DEC (2*L_FRAME_MAX) /* decoder past synthesis; needed for LTP, PLC and rate switching*/ +#define OLD_SYNTH_INTERNAL_DEC (2*L_FRAME32k) /* decoder past synthesis @ internal sampling rate; needed for LTP, PLC and rate switching*/ +#define OLD_SYNTH_SIZE_ENC L_FRAME32k+L_FRAME32k/4 /* Frame size in samples at 25.6 kHz */ +#define OLD_EXC_SIZE_DEC (3*L_FRAME_MAX/2+2*L_FIR_FER2) /*old excitation needed for decoder for PLC*/ + +#define TILT_CODE 9830 /* ACELP code preemphasis factor ~=0.3f (0Q15) (=0.299987792968750) */ + +#define L_SUBFR16k (L_FRAME16k/NB_SUBFR) /* subframe size at 16kHz */ +#define L_HALFR16k (2*L_SUBFR16k) /* half-frame size at 16kHz */ + +#define L_INTERPOL2 16 /* Length of filter for interpolation */ +#define L_INTERPOL (L_INTERPOL2+1) /* Length of filter for interpolation */ +#define TILT_FAC_FX 22282 /* tilt factor (denominator) fixed-point*/ +#define M16k 20 /* order of the LP filter @ 16kHz */ +#define PIT_SHARP_fx 27853 /* pitch sharpening factor */ +#define F_PIT_SHARP 0.85F /* pitch sharpening factor */ +#define PIT_UP_SAMP 4 +#define UP_SAMP 4 /* upsampling factor for 1/4 interpolation filter */ +#define PIT_L_INTERPOL2 16 +#define PIT_FIR_SIZE2 (PIT_UP_SAMP*PIT_L_INTERPOL2+1) +#define PIT_UP_SAMP6 6 +#define PIT_L_INTERPOL6_2 17 +#define PIT_FIR_SIZE6_2 (PIT_UP_SAMP6*PIT_L_INTERPOL6_2+1) +#define E_MIN_FX 1 /* QSCALE (Q7)*/ +#define STEP_DELTA_FX 11 +#define FORMANT_SHARPENING_NOISE_THRESHOLD_FX 5376 /* 21 (!8)lp_noise level above which formant sharpening is deactivated - at this level most of 20 dB SNR office noisy speech still uses sharpening */ +#define LP_NOISE_THRESH 167772160l/*20.f Q23*/ +#define LFAC 160 /* FAC maximum frame length */ + +#define L_FILT_UP8k 24 /* Resampling - delay of filter for 8 kHz output signals (at 12.8 kHz sampling rate) */ +#define LEN_WIN_SSS 120 +#define L_FILT 12 /* Delay of the low-pass filter in the BPF */ +#define L_FILT8k 16 /* Resampling - delay of filter for 8 kHz input signals (at 8kHz sampling rate) */ +#define L_FILT16k 15 /* Resampling - delay of filter for 16 kHz input signals (at 16kHz sampling rate) */ +#define L_FILT32k 30 /* Resampling - delay of filter for 32 kHz input signals (at 32kHz sampling rate) */ +#define L_FILT48k 45 /* Resampling - delay of filter for 48 kHz input signals (at 48kHz sampling rate) */ +#define L_FILT_UP16k 12 /* Resampling - delay of filter for 16 kHz output signals (at 12.8 kHz sampling rate) */ +#define L_FILT_UP32k 12 /* Resampling - delay of filter for 32 kHz output signals (at 12.8 kHz sampling rate) */ +#define L_FILT_UP48k 12 /* Resampling - delay of filter for 48 kHz output signals (at 12.8 kHz sampling rate) */ +#define L_FILT_MAX L_FILT48k /* Resampling - maximum length of all filters - for memories */ +#define RS_INV_FAC 0x8000 /* Resampling - flag needed in rom_com and modif_fs to allow pre-scaled and non pre-scaled filters */ + +#define CLDFB_NO_CHANNELS_MAX 60 /* CLDFB resampling - max number of CLDFB channels */ +#define CLDFB_NO_COL_MAX 16 /* CLDFB resampling - max number of CLDFB col. */ +#define CLDFB_NO_COL_MAX_SWITCH 6 /* CLDFB resampling - max number of CLDFB col. for switching */ +#define CLDFB_NO_COL_MAX_SWITCH_BFI 8 /* CLDFB resampling - max number of CLDFB col. for switching */ + +#define CLDFB_ANALYSIS 0 +#define CLDFB_SYNTHESIS 1 + +#define L_FFT 256 /* Spectral analysis - length of the FFT */ +#define LOG2_L_FFT 8 /* Spectral analysis - log2 of L_FFT */ + + +#define BIN (INT_FS_FX/L_FFT)/* Spectral analysis - Width of one frequency bin in Hz */ +#define NB_BANDS 20 /* Spectral analysis - number of frequency bands */ +#define VOIC_BINS 74 /* Spectral analysis - max number of frequency bins considered as voiced (related to VOIC_BAND and L_FFT) */ +#define VOIC_BAND 17 /* Spectral analysis - number of critical bands considered as voiced (related to VOIC_BINS) */ +#define VOIC_BINS_8k 115 /* Spectral analysis - max number of frequency bins considered as voiced in NB (related to VOIC_BAND_8k and L_FFT) */ +#define VOIC_BAND_8k 17 /* Spectral analysis - number of critical bands considered as voiced in NB (related to VOIC_BINS_8k) */ +#define N_SPEC (L_FFT/2) /* number of spectral bins */ + +#define M_GAMMA_FX 32440 /* Q15 - forgetting factor of active speech decision predictor */ +#define M_ALPHA_FX 29491 /* Q15 - forgetting factor of LT correlation map */ +#define ONE_MINUS_M_ALPHA 3277 /* Q15 - one minus forgetting factor of LT correlation map */ +#define THR_CORR_INIT_FX (56<<9 ) /* Q9 - starting threshold of multi-harm. correlation */ +#define THR_NCHAR_WB_FX 2048 /* Q11 threshold for noise character (WB) */ +#define THR_NCHAR_NB_FX 2048 /* Q11 threshold for noise character (NB) */ + +#define L_LP 320 /* LP analysis - LP window size */ +#define L_LP_16k 400 /* LP analysis @16kHz - LP window size for 16kHz */ +#define L_LP_AMR_WB 384 /* LP analysis - windows size (only for AMR-WB IO mode) */ +#define GRID100_POINTS 100 /* LP analysis - number of points to evaluate Chebyshev polynomials */ +#define GRID80_POINTS 80 /* LP analysis - number of points to evaluate Chebyshev polynomials used in the LP coefs. conversion */ + +#define GRID50_POINTS 51 /* LP analysis - half-number of points to evaluate Chebyshev polynomials used in the LP coefs. conversion */ +#define GRID40_POINTS 41 /* LP analysis - half-number of points to evaluate Chebyshev polynomials used in the LP coefs. conversion */ + +#define PIT_MIN 34 /* OL pitch analysis - Minimum pitch lag */ +#define PIT_MAX 231 /* OL pitch analysis - Maximum pitch lag */ +#define PIT_MIN_EXTEND 20 /* OL pitch analysis - Minimum pitch lag of extended range */ +#define PIT_MIN_DOUBLEEXTEND 17 /* OL pitch analysis - Minimum pitch lag of double-extended range */ +#define OPL_DECIM 2 /* OL pitch analysis - decimation factor */ +#define L_INTERPOL1 4 /* OL pitch analysis - interval to compute normalized correlation */ +#define FIR_SIZE1 (UP_SAMP*L_INTERPOL1+1) /* OL pitch analysis - total length of the 1/4 interpolation filter */ + +#define PIT_MIN_SHORTER 29 /* OL pitch analysis - minimum for wider pitch, MODE2 specific constant */ + +#define PIT_MIN_12k8 29 /* Minimum pitch lag with resolution 1/4 */ +#define PIT_FR2_12k8 121 /* Minimum pitch lag with resolution 1/2 */ +#define PIT_FR1_12k8 154 /* Minimum pitch lag with resolution 1 */ +#define PIT_MAX_12k8 231 /* Maximum pitch lag */ +#define PIT_FR1_8b_12k8 82 /* Minimum pitch lag with resolution 1 for low bit-rate pitch delay codings*/ +#define PIT_MIN_16k 36 +#define PIT_FR2_16k 36 +#define PIT_FR1_16k 165 +#define PIT_FR1_8b_16k 165 +#define PIT_MIN_25k6 58 +#define PIT_FR2_25k6 58 +#define PIT_FR1_25k6 164 +#define PIT_MAX_25k6 463 +#define PIT_FR1_8b_25k6 164 +#define PIT_MIN_32k 72 +#define PIT_FR2_32k 72 +#define PIT_FR1_32k 75 +#define PIT_MAX_32k 577 +#define PIT_FR1_8b_32k 75 +#define PIT_MAX_MAX PIT_MAX_32k +#define PIT_MAX_16k 289 + +#define PIT_FR1_8b 92 /* Pitch encoding - Minimum pitch lag with resolution 1 */ +#define PIT_FR2_9b 128 /* Pitch encoding - Minimum pitch lag with resolution 1/2 */ +#define PIT_FR1_9b 160 /* Pitch encoding - Minimum pitch lag with resolution 1 */ +#define PIT_FR1_EXTEND_8b 64 /* Pitch encoding - Minimum pitch lag with resolution 1 of extended range */ +#define PIT_FR2_EXTEND_9b 116 /* Pitch encoding - Minimum pitch lag with resolution 1/2 of extended range */ +#define PIT_FR1_EXTEND_9b 128 /* Pitch encoding - Minimum pitch lag with resolution 1 of extended range */ +#define PIT_FR1_DOUBLEEXTEND_8b 58 /* Pitch encoding - Minimum pitch lag with resolution 1 of double-extended range */ +#define PIT_FR2_DOUBLEEXTEND_9b 112 /* Pitch encoding - Minimum pitch lag with resolution 1/2 of double-extended range */ +#define PIT_FR1_DOUBLEEXTEND_9b 124 /* Pitch encoding - Minimum pitch lag with resolution 1 of double-extended range */ + +#define LOW_PASS 0 /* LP filtering - flag for low-pass filtering of the excitation */ +#define FULL_BAND 1 /* LP filtering - flag for no low-pass filtering of the excitation */ +#define NORMAL_OPERATION 2 /* LP filtering - flag for selecting the best of the two above */ + +#define NB_TRACK_FCB_2T 2 /* Algebraic codebook - number of tracks in algebraic fixed codebook search with 2 tracks */ +#define NB_POS_FCB_2T 32 /* Algebraic codebook - number of positions in algebraic fixed codebook search with 2 tracks */ +#define NB_TRACK_FCB_4T 4 /* Algebraic codebook - number of tracks in algebraic fixed codebook search with 4 tracks */ +#define NB_POS_FCB_4T 16 /* Algebraic codebook - number of positions in algebraic fixed codebook search with 4 tracks */ +#define NB_PULSE_MAX 36 +#define NPMAXPT ((NB_PULSE_MAX+NB_TRACK_FCB_4T-1)/NB_TRACK_FCB_4T) + +#define GAIN_PRED_ORDER 4 /* Gain quantization - prediction order for gain quantizer (only for AMR-WB IO mode) */ +#define MEAN_ENER 30 /* Gain quantization - average innovation energy */ + +#define DTX_HIST_SIZE 8 /* CNG & DTX - number of last signal frames used for CNG averaging */ +#define CNG_ISF_FACT_FX 29491 /* Q15(0.9), CNG & DTX - CNG spectral envelope smoothing factor*/ +#define STEP_AMR_WB_SID_FX 10752 /* Q12 */ +#define HO_HIST_SIZE 8 /* CNG & DTX - maximal number of hangover frames used for averaging */ + +#define NUM_ENV_CNG 20 +#define BUF_L_NRG_FX 22938 /* Q15(0.7), CNG & DTX - lower threshold offset for hangover updates */ +#define ONE_OVER_BUF_H_NRG_FX 31814 /* Q15(1/1.03), CNG & DTX - inverse of higher threshold offset for hangover updates */ +#define HO_ATT_FAC_FX 3277 /* Q15(0.1), CNG & DTX - Hangover frame attenuation rate factor */ + +#define BUF_DEC_RATE 25 /* CNG & DTX - buffer size decrease rate for active frames */ +#define STEP_SID_FX 21504 /* Q12 */ +#define ISTEP_SID_FX 6242 /* Inverse of CNG & DTX - CNG energy quantization step in Q15(1/5.25 in Q15)*/ +#define ISTEP_AMR_WB_SID_FX 12483 /* Q15(1/2.625) Inverse of CNG & DTX - CNG energy quantization step */ + +#define MIN_ACT_CNG_UPD 20 /* DTX - Minimum number of consecutive active frames for CNG mode update */ +#define FIXED_SID_RATE 8 /* DTX SID rate */ + +#define TOTALNOISE_HIST_SIZE 4 + +/************************************************************************/ + +/************************************************************************/ +#define SUBFFT_QIN 10 +#define DATAFFT_Q 5 +#define SUBFFT_QOUT SUBFFT_QIN-DATAFFT_Q +#define SPECAMP_Q SUBFFT_QIN + +#define CLDFBVAD_NB_ID 1 +#define CLDFBVAD_WB_ID 2 +#define CLDFBVAD_SWB_ID 3 +#define CLDFBVAD_FB_ID 4 +#define SP_CENTER_NUM 4 +#define TONA_NUM 3 +#define PRE_SNR_NUM 32 +#define PRE_FLAG_NUM 64 +#define POWER_NUM 56 +#define PRE_SPEC_DIF_NUM 56 +#define CLDFBVAD_VAD_ON 1 +#define COM_VAD_ON 2 + +#define MAX_SUBBAND_NUM 12 /* max number of sub-band divided non-uniformly*/ +#define BG_ENG_NUM MAX_SUBBAND_NUM /* number of energy of sub-band divided non-uniformly*/ +#define MIN_AMP_ID 5 +#define MAX_AMP_ID 64 +#define SPEC_AMP_NUM (MAX_AMP_ID-MIN_AMP_ID+1) +#define STABLE_NUM 4 /* number of time-domain stable rate*/ +#define SFM_NUM 3 /* number of spectral flatness */ + + + +#define MAX_CORR_SHIFT_FX 16384 /* corrshift limit, 0.5 in Q15 */ + + +#define START_NG 5 /* Stationary noise UV modification */ +#define FULL_NG 10 /* Stationary noise UV modification */ +#define ISP_SMOOTHING_QUANT_A1_FX 29491 /* 0.9f in Q15 */ /* Stationary noise UV modification */ + +#define KP559016994_FX 18318 /* EDCT & EMDCT constants */ +#define KP951056516_FX 31164 /* EDCT & EMDCT constants */ +#define KP587785252_FX 19261 /* EDCT & EMDCT constants */ +#define KP866025403_FX 28378 /* EDCT & EMDCT constants */ +#define KP250000000_FX 8192 /* EDCT & EMDCT constants */ + +#define FEC_BITS_CLS 2 /* FEC - number of bits for clas information */ +#define FEC_BITS_ENR 5 /* FEC - number of bits for energy information */ +#define FEC_ENR_STEP (96.0f/(1< 1! For dividing spectrum into multiple ranges, define NOISE_FILL_RANGES > 1. For each region one noise filling level will be transmited */ +#define NBITS_NOISE_FILL_LEVEL 3 /* Number of bits used for coding noise filling level for each range */ +#define MIN_NOISE_FILLING_HOLE 8 +#define HOLE_SIZE_FROM_LTP(gain) (add(4, extract_h(L_shr(L_mult0(gain, 0x6666), 10)))) /* 0x6666 -> 2.0*(4.0/0.625) (4Q11) */ +#define FDNS_NPTS 64 +#define AVG_TCX20_LSF_BITS 40 +#define AVG_TCX10_LSF_BITS 59 +#define LTPSIZE 3 +#define TCXLTP_DELAY_NS 250000 +#define TCXLTP_MAX_DELAY NS2SA(48000,TCXLTP_DELAY_NS) +#define TCXLTP_LTP_ORDER 24 +#define TCX_RES_Q_BITS_GAIN 3 + +#define LPC_SHAPED_ARI_MAX_RATE ACELP_9k60 + +#define N_MAX_ARI 800 + +#define SPEC_EXP_DEC 20 /* initial decoder spectrum exponent */ + +/*----------------------------------------------------------------------------------* + * TNS constants + *----------------------------------------------------------------------------------*/ + +#define R1_48 690 +#define R2_48 420 +#define R1_16 230 +#define R2_16 140 +#define R1_25 368 +#define R2_25 224 + +#define TNS_MAX_NUM_OF_FILTERS 2 /* TNS maximum number of filters */ +#define TNS_MAX_FILTER_ORDER 8 /* TNS maximum filter order */ +#define ITF_MAX_FILTER_ORDER 16 /* ITF maximum filter order */ +#define NPRM_TNS (2+TNS_MAX_NUM_OF_FILTERS*(3+TNS_MAX_FILTER_ORDER)) /* TNS total number of quantized parameters */ +#define NPRM_RESQ 100 /* Maximum number of parameter for residual Q in TCX */ +#define NPRM_CTX_HM 3 /* Number of Parameters for Context HM : flag+index */ +#define NPRM_DIV (2+NPRM_TNS+N_MAX/2+NPRM_RESQ+NPRM_CTX_HM) /* Total number of quantized parameter in 1 division */ +#define DEC_NPRM_DIV NPRM_DIV /* Total number of quantized parameter in 1 division (decoder side) */ +#define NPRM_LPC_NEW 2*(4+2*NB_SPHERE) /* LPC total number of quantized parameters */ + +#define BITBUFSIZE (128000/50) + +#define TNS_COEF_RES 4 /* Bit resolution of the coefficients. */ +#define INDEX_SHIFT (1 << (TNS_COEF_RES-1)) /* For shifting the index so that index 0 points to 0. */ + +/*----------------------------------------------------------------------------------* + * LSF quantization constants + *----------------------------------------------------------------------------------*/ + +#define GENERIC_MA_LIMIT 9600 + +#define SPC_FX 770 /* q15 */ +#define SPC_PLUS_FX 771 + +#define LSF_GAP_FX 128 /*50.0f x 2.56*/ +#define MODE1_LSF_GAP_FX 179 /* MODE1_LSF_GAP*2.56 */ /* Minimum LSF separation for end-frame ISFs */ +#define FREQ_MAX 16384 /*6400Hz in 14Q1*1.28 */ +#define FREQ_DIV 800 /*400.0f in 14Q1 */ + +#define LSF_BITS_CNG 29 + +#define ISF_GAP_FX 128 /* Minimum ISF separation for end-frame ISFs (only in AMR-WB IO mode) */ +#define LSF_GAP_MID_FX 205 /* 80.0 * 2.56 */ /* Minimum LSF separation for mid-frame LSFs */ +#define PREFERSFNET_FX 1638 /* 0.05 in Q16*/ +#define SFNETLOWLIMIT_WB 3670016 /* 2.56x2.56*Q4 LSF quantizer - new sampling rate dependent thresholds used in LSF codebook decision logic, WB case */ +#define SFNETLOWLIMIT_NB 3984589 /* 2.56x2.56*Q4 LSF quantizer - new sampling rate dependent thresholds used in LSF codebook decision logic, NB case */ +#define LSFMBEST 2 /* number of survivors from one stage to another */ +#define STREAKLEN 3 /* Allow this many predictive frames, before starting limiting, For voiced +3 frames allowed */ +#define STREAKMULT_FX 26214 /* Exponential limiting multiplier */ + +#define LSFMBEST_MAX 16 + +#define TCXLPC_NUMSTAGES 3 +#define TCXLPC_NUMBITS 13 +#define TCXLPC_IND_NUMSTAGES 1 +#define TCXLPC_IND_NUMBITS 2 +#define TCXLPC_LSF_GAP 204 /* 80 in 14Q1*1.28 */ +#define kMaxC 8 + +#define MAX_VQ_STAGES 4 /* Maximum number of LSF VQ (3 trained and 1 LVQ) stages allowed */ +#define MAX_VQ_STAGES_USED 9 /*this is the maximum number of stages currently used and changing this will affect the memory allocated MAX_VQ_STAGES is also used as offset for addressing some arrays, so this should NOT be changed*/ + +#define LEN_INDICE 15 +#define LATTICE_DIM 8 +#define NO_LEADERS 49 +#define MAX_NO_BR_LVQ 28 +#define MAX_NO_SCALES 3 +#define MAX_NO_VALS 4 +#define CNG_LVQ_MODES 16 +#define MAX_NO_MODES 128 +#define START_CNG 112 +#define MAX_NO_MODES_p 145 +#define NO_CODING_MODES 6 +#define LVQ_COD_MODES 18 +/* BC-TCQ */ +#define N_STAGE_VQ 8 +#define N_DIM 2 +#define NUM_SUBSET 8 +#define OP_LOOP_THR_HVO 1550146 /* 80% : Open-loop Threshold 2.56*2.56/16 */ +#define NUM_STATE 16 /* BC-TCQ - Number of state of the Trellis */ +#define N_STAGE 16 /* BC-TCQ - Smaple number in a frame */ + +#define SIZE_BK1 256 +#define SIZE_BK2 256 +#define SIZE_BK21 64 +#define SIZE_BK22 128 +#define SIZE_BK23 128 +#define SIZE_BK24 32 +#define SIZE_BK25 32 +#define SIZE_BK21_36b 128 +#define SIZE_BK22_36b 128 +#define SIZE_BK23_36b 64 + +#define NB_QUA_GAIN5B 32 /* Number of quantization level */ +#define NB_QUA_GAIN6B 64 /* Number of quantization level */ +#define NB_QUA_GAIN7B 128 /* Number of quantization level */ + +/*----------------------------------------------------------------------------------* + * Transient detection + *----------------------------------------------------------------------------------*/ + +#define NSUBBLOCKS 8 /* Number of subblocks per frame, one transient per a sub-block can be found */ +#define MAX_TD_DELAY 2*NSUBBLOCKS /* Maximum allowed delay (in number of subblocks) of the transient detection, affects required memory */ + +#define NO_TCX 0 +#define TCX_20 1 +#define TCX_10 2 +#define TCX_5 3 + +#define TRANSITION_OVERLAP (-2) +#define RECTANGULAR_OVERLAP (-1) +#define FULL_OVERLAP 0 +#define NOT_SUPPORTED 1 +#define MIN_OVERLAP 2 +#define HALF_OVERLAP 3 + +/*----------------------------------------------------------------------------------* + * FEC constants + *----------------------------------------------------------------------------------*/ + +#define UNVOICED_CLAS 0 /* Unvoiced, silence, noise, voiced offset */ +#define UNVOICED_TRANSITION 1 /* Transition from unvoiced to voiced components - possible onset, but too small */ +#define VOICED_TRANSITION 2 /* Transition from voiced - still voiced, but with very weak voiced characteristics */ +#define VOICED_CLAS 3 /* Voiced frame, previous frame was also voiced or ONSET */ +#define ONSET 4 /* Voiced onset sufficiently well built to follow with a voiced concealment */ +#define SIN_ONSET 5 /* Artificial harmonic+noise onset (used only in decoder) */ +#define INACTIVE_CLAS 6 /* Inactive frame (used only in decoder) */ +#define AUDIO_CLAS 7 /* Audio frame (used only in AMR-WB IO mode) */ + +#define BETA_FEC_FX 24576 /* FEC - weighting factor for LSF estimation in FER */ +#define STAB_FAC_LIMIT_FX 8192 /* FEC - limit at which safety net is forced for next frame */ + +#define MODE1_L_FIR_FER 5 /* FEC - impulse response length for low- and high-pass filters in FEC */ +#define L_FIR_FER 3 /* FEC - impulse response length for low- & high-pass filters in FER concealment*/ +#define L_FIR_FER2 11 /* FEC - new filter tuning: 11*/ +#define MAX_UPD_CNT 5 /* FEC - maximum number of frames since last pitch update */ + +/* attenuation strategy in case of FER */ +#define _ALPHA_S_FX 19661 +#define _ALPHA_V_FX 32767 +#define _ALPHA_VT_FX 13107 +#define _ALPHA_UT_FX 26214 +#define _ALPHA_U_FX 13107 +#define _ALPHA_U_FX_X_2 26214 +#define _ALPHA_UU_FX 32767 + +#define PLC_MIN_CNG_LEV 328/*0.01f Q15*/ +#define PLC_MIN_STAT_BUFF_SIZE 50 /* buffer size for minimum statistics */ +#define G_LPC_RECOVERY_BITS 1 + +/*----------------------------------------------------------------------------------* + * Transition mode (TC) constants + *----------------------------------------------------------------------------------*/ +/* Conversion of tc_subfr to index */ +#define TC_SUBFR2IDX_16KHZ_fx(x) mac_r(1024L, (x), 512) /* -1 => 0, 0 => 0, 64 => 1, 128 => 2, 192 => 3, 256 => 4 */ + +#define TC_SUBFR2IDX_fx(x) add(s_min(3, s_max(0, sub((x), 1))), TC_SUBFR2IDX_16KHZ_fx(x)) + +#define L_IMPULSE 17 /* TC - length of one prototype impulse */ +#define L_IMPULSE2 8 /* TC - half-length of one prototype impulse == floor(L_IMPULSE/2) */ +#define NUM_IMPULSE 8 /* TC - number of prototype impulses */ +#define N_GAIN_CODE_TC 8 /* TC - number of levels for gain_code quantization for subrames without glot. impulse(s) - */ +#define N_GAIN_TC 8 /* TC - number of levels for gain_trans quantization */ +/* TC - attention: DO NOT CHANGE the following constants - needed for correct bit-allocations */ +#define TC_0_0 1 /* TC - subframe ID for TC: first glottal impulse in the 1st subframe, second in the 1st subframe */ +#define TC_0_64 2 /* TC - subframe ID for TC: first glottal impulse in the 1st subframe, second in the 2nd subframe */ +#define TC_0_128 3 /* TC - subframe ID for TC: first glottal impulse in the 1st subframe, second in the 3rd subframe */ +#define TC_0_192 4 /* TC - subframe ID for TC: first glottal impulse in the 1st subframe, second in the 4th subframe */ + +/*----------------------------------------------------------------------------------* + * AVQ constants + *----------------------------------------------------------------------------------*/ + +#define NB_LDQ3 9 /* RE8 constants */ +#define NB_LDQ4 27 +#define NB_SPHERE 32 +#define NB_LEADER 36 + +#define NSV_MAX 34 /* maximal number of sub-vectors used by the AVQ */ + +/*----------------------------------------------------------------------------------* + * Arithmetic coder + *----------------------------------------------------------------------------------*/ +#define A_THRES_SHIFT 2 +#define A_THRES (1<0 */ +#define GAMMA3_MINUS_FX 29491 /* NB post-filter - tilt weighting factor when k1<0 */ +#define GAMMA3_PLUS_WB_FX 21299 /* WB post-filter */ +#define GAMMA3_MINUS_WB_FX 27853 /* WB post-filter */ +#define AGC_FAC_WB_FX 27853 /* WB post-filter - gain adjustment factor */ +#define AGC_FAC1_WB_FX (Word16)(32768L-AGC_FAC_WB_FX) /* WB post-filter - gain adjustment factor complement */ + +/* SWB TBE, FX only constants */ +#define NOISE_QFAC 6 +#define NOISE_QADJ (15-NOISE_QFAC) + +/*----------------------------------------------------------------------------------* + * SWB BWE constants + *----------------------------------------------------------------------------------*/ + +#define INV_L_SUBFR16k_FX 410 /*Q15 */ +#define SWB_L_SUBFR 160 +#define FB_L_SUBFR 240 +#define SWB_FENV 14 +#define WB_FENV 2 +#define FB_GAIN_QLOW_FX 0 +#define FB_GAIN_QDELTA_FX 512 /*Q14 */ + +#define NUM_BITS_FB_FRAMEGAIN 4 /* Number of bits for framegain for FB */ +#define FB_BAND_BEGIN 620 +#define FB_BAND_END 800 +#define FB_BAND_WIDTH 180 +#define N_CAND 2 +#define N_CB11 32 /* 5bits */ +#define N_CB1ST 128 /* 7bits */ +#define N_CB2ND 64 /* 6bits */ +#define N_CB3RD 32 /* 5bits */ +#define N_CB4TH 64 /* 6bits */ +#define DIM1ST 3 +#define DIM2ND 4 +#define DIM3RD 3 +#define DIM4TH 4 +#define DIM11 (DIM1ST+DIM2ND) +#define DIM12 (DIM3RD+DIM4TH) +#define N_CAND_TR 3 +#define N_CB_TR1 128 +#define N_CB_TR2 64 +#define DIM_TR1 2 +#define DIM_TR2 2 +#define SWB_FENV_TRANS 4 +#define SWB_TENV 4 +#define NUM_SHARP 9 +#define SHARP_WIDTH 32 + +#define HARMONIC 3 +#define NORMAL 2 +#define TRANSIENT 1 +#define NOISE 0 + +/*----------------------------------------------------------------------------------* + * HR SWB BWE constants + *----------------------------------------------------------------------------------*/ + +#define NSV_OVERLAP 2 /* number of sub-bands overlaping with lower-band (0-8kHz) */ /* note that NSV_MAX >= END_FREQ_BWE_FULL/(8*50) + NSV_OVERLAP ! */ +#define N_BANDS_BWE_HR 4 /* number of frequency bands in non-transient frame */ +#define N_BANDS_TRANS_BWE_HR 2 /* number of frequency bands in transient frame */ +#define END_FREQ_BWE 14400 /* maximum frequency coded by AVQ */ +#define END_FREQ_BWE_FULL 16000 /* maximum frequency coded by HR SWB BWE */ +#define END_FREQ_BWE_FULL_FB 20000 /* maximum frequency coded by HR FB BWE */ + +#define NBITS_GLOB_GAIN_BWE_HR 5 /* number of bits of the global gain quantizer */ +#define MIN_GLOB_GAIN_BWE_HR 3 /* minimum value of the global gain quantizer */ +#define MAX_GLOB_GAIN_BWE_HR 500 /* maximum value of the global gain quantizer */ + +#define NBITS_ENVELOPE_BWE_HR1 6 /* number of bits for envelope VQ - first two subbands in non-transient frame */ +#define NBITS_ENVELOPE_BWE_HR2 5 /* number of bits for envelope VQ - second two subbands in non-transient frame */ +#define NBITS_ENVELOPE_BWE_HR_TR 4 /* number of bits for envelope VQ - two subbands in transient frame */ +#define NUM_ENVLOPE_CODE_HR1 64 /* dimension of envelope VQ - first two subbands in non-transient frame */ +#define NUM_ENVLOPE_CODE_HR2 32 /* dimension of envelope VQ - second two subbands in non-transient frame */ +#define NUM_ENVLOPE_CODE_HR_TR 16 /* dimension of envelope VQ - two subbands in transient frame */ +#define NUM_ENVLOPE_CODE_HR_TR2 8 /* dimension of envelope VQ - two subbands in transient frame */ + +#define NUM_NONTRANS_START_FREQ_COEF (L_FRAME32k/2 - NSV_OVERLAP*WIDTH_BAND) /* start frequency coefficient (==7.6kHz) in non-transient frame */ +#define NUM_NONTRANS_END_FREQ_COEF (L_FRAME32k*END_FREQ_BWE/END_FREQ_BWE_FULL) /* end frequency coefficient (==14.4kHz) in non-transient frame */ +#define NUM_TRANS_START_FREQ_COEF (NUM_NONTRANS_START_FREQ_COEF/NUM_TIME_SWITCHING_BLOCKS) /* start frequency coefficient (==7.6kHz) in transient frame */ +#define NUM_TRANS_END_FREQ_COEF (NUM_NONTRANS_END_FREQ_COEF/NUM_TIME_SWITCHING_BLOCKS) /* end frequency coefficient (==14.4kHz) in transient frame */ +#define NUM_TRANS_END_FREQ_COEF_EFF 140 +#define WIDTH_NONTRANS_FREQ_COEF ((NUM_NONTRANS_END_FREQ_COEF - NUM_NONTRANS_START_FREQ_COEF)/N_BANDS_BWE_HR) /* number of coefficients per band in non-transient frame */ +#define WIDTH_TRANS_FREQ_COEF ((NUM_TRANS_END_FREQ_COEF - NUM_TRANS_START_FREQ_COEF)/N_BANDS_TRANS_BWE_HR) /* number of coefficients per band in transient frame */ + +#define NBITS_THRESH_BWE_HR 400 /* BWE HR number of bits threshold */ + +#define NBITS_HF_GAIN_BWE_HR 2 /* number of bits for HF (noncoded) energy estimation */ +#define BWE_HR_TRANS_EN_LIMIT1_FX_Q16 6554 +#define BWE_HR_TRANS_EN_LIMIT2_FX_Q16 19661 +#define BWE_HR_TRANS_EN_LIMIT3_FX_Q16 32767 +#define BWE_HR_NONTRANS_EN_LIMIT1_FX_Q15 16384 /* 0.5 */ +#define BWE_HR_NONTRANS_EN_LIMIT2_FX_Q14 19661 /* 1.2 */ +#define BWE_HR_NONTRANS_EN_LIMIT2_FX_Q15 16384 +#define BWE_HR_NONTRANS_EN_LIMIT3_FX_Q15 26214 /* 0.8 */ + +/*----------------------------------------------------------------------------------* + * FD CNG + *----------------------------------------------------------------------------------*/ +#define DELTA 1e-20f +#define DELTA_MANTISSA_W16 0x5e73 +#define DELTA_MANTISSA_W32 0x5e728433 +#define DELTA_EXPONENT (-66) + +#define CLDFB_SCALING 24576/*1.5 Q14*/ /* Q 2.14 */ + +#define FFTLEN 640 +#define FFTLEN2 (FFTLEN/2) +#define CORECLDFBLEN 20 +#define TOTCLDFBLEN 40 +#define FFTCLDFBLEN (FFTLEN2+TOTCLDFBLEN-CORECLDFBLEN) +#define PERIODOGLEN (FFTLEN2-2) +#define NPART 24 +#define NPARTCLDFB 10 +#define NPART_SHAPING 62 + +#define MSSUBFRLEN 12 +#define MSNUMSUBFR 6 +#define MSBUFLEN 5 + +#define NOISE_HEADROOM 5 /* headroom of noise in generate_masking_noise */ + +#define MSALPHACORALPHA 22938/*0.7f Q15*/ +#define MSALPHACORALPHA2 9830/*0.3f Q15*/ +#define MSALPHACORMAX 9830/*0.3f Q15*/ +#define MSALPHAMAX 31457/*0.96f Q15*/ +#define MSALPHAHATMIN 107374184l/*0.05f Q31*/ +#define MSQEQINVMAX 6554/*1.f/5.f Q15*/ +#define MSAV 17367/*2.12f Q13*/ +#define MSAV_EXP 2 +#define MSBETAMAX 1717986944l/*0.8f Q31*/ +#define MSBETAMAX_SQRT 1920767767l/*0.894427191 Q31*/ /* sqrt(MSBETAMAX) */ +#define MSSNREXP -10240/*-0.02f/0.064f Q15*/ + +#define NB_LAST_BAND_SCALE 26214/*0.8f Q15*/ +#define SWB_13k2_LAST_BAND_SCALE 26214/*0.8f Q15*/ + +#define M_MAX 32 +#define NSTAGES_MAX 9 +#define MBEST_MAX 8 +#define N_GAIN_MIN 4 +#define N_GAIN_MAX 17 + +#define numSlots_inv_EXP (-3) +#define PREEMPH_COMPENSATION_EXP 4 + +#define CLDFBscalingFactor_EXP (-15) +#define CLDFBinvScalingFactor_EXP ( 16) + +#define CNG_NORM_RECIPROCAL_RANGE_SHIFT 2 +#define CNG_RAND_GAUSS_SHIFT 2 + +#define CNA_MAX_BRATE 13200 + +/*----------------------------------------------------------------------------------* + * Bass post-filter constants + *----------------------------------------------------------------------------------*/ + +#define NBPSF_PIT_MAX (PIT16k_MAX+1) /* maximum pitch value for bass post-filter */ +#define L_TRACK_HIST 10 + +/*----------------------------------------------------------------------------------* + * NB post-filter constants + *----------------------------------------------------------------------------------*/ + +#define LONG_H_ST 20 /* NB post-filter - impulse response length */ +#define GAMMA1_PST12K_FX 24576 /* denominator weighting factor 12K (0.75 in Q15) */ +#define GAMMA2_PST12K_FX 22938 /* numerator weighting factor 12K (0.7 in Q15) */ +#define POST_G1_FX GAMMA1_PST12K_FX /* 12 kbps default */ +#define POST_G2_FX GAMMA2_PST12K_FX /* 12 kbps default */ +#define GAMMA1_PST12K_MIN_FX 21299 /* 0.65 in Q15 */ +#define GAMMA2_PST12K_MIN_FX 18022 /* 0.55 in Q15 */ +#define GAMMA1_PST12K_NOIS_FX 4915 /* 0.15 in Q15 */ +#define GAMMA2_PST12K_NOIS_FX 3277 /* 0.10 in Q15 */ +#define F_UP_PST 8 /* NB post-filter - resolution for fractionnal delay */ +#define LH2_S 4 /* NB post-filter - length of INT16 interp. subfilters */ +#define LH2_L 16 /* NB post-filter - length of long interp. subfilters */ +#define LH_UP_S (LH2_S/2) +#define LH_UP_L (LH2_L/2) +#define LH2_L_P1 (LH2_L + 1) +#define DECMEM_RES2 (PIT16k_MAX + 2 + LH_UP_L) +#define SIZ_RES2 (DECMEM_RES2 + L_SUBFR) +#define SIZ_Y_UP ((F_UP_PST-1) * (L_SUBFR+1)) +#define SIZ_TAB_HUP_L ((F_UP_PST-1) * LH2_L) +#define SIZ_TAB_HUP_S ((F_UP_PST-1) * LH2_S) +#define BG1_FX -328 /* -0.01 in Q15 */ +#define BG2_FX -1638 /* -0.05 in Q15 */ +#define CG1_FX 29491 /* 0.9 in Q15 */ +#define CG2_FX 47514L /* 1.45 in Q15 */ +#define C_LP_NOISE_FX 819 /* 0.1/4.0 in Q15 */ +#define CK_LP_NOISE_FX 6291456L /* 15.0 * 0.1/4 in Q8 * 65536 */ +#define LP_NOISE_THR_FX 6400 /* 25.0 in Q8 */ + +/*----------------------------------------------------------------------------------* + * Stability estimation + *----------------------------------------------------------------------------------*/ + +#define NB_BFI_THR 2 /* threshold for counter of last bad frames */ +#define MAX_LT 40 + +#define TH_0_MIN_FX 5120 /* 2.5f in Q11 */ +#define TH_1_MIN_FX 3840 /* 1.875f in Q11 */ +#define TH_2_MIN_FX 3200 /* 1.5625f in Q11 */ +#define TH_3_MIN_FX 2688 /* 1.3125f in Q11 */ + +/*----------------------------------------------------------------------------------* + * Speech/music classifier constants + *----------------------------------------------------------------------------------*/ + +#define N_FEATURES 12 /* number of features */ +#define N_MIXTURES 6 /* number of mixtures */ +#define M_LSP_SPMUS 6 /* number of LSPs used in speech/music classifier */ +#define NB_BANDS_SPMUS 15 +#define START_BAND_SPMUS 2 +#define N_OLD_BIN_E 42 + +#define LOWEST_FBIN 3 /* lowest frequency bin for feature vector preparation */ +#define HIGHEST_FBIN 70 /* highest frequency bin for feature vector preparation */ +#define HANG_LEN_INIT 8 /* number of frames for hang-over (causes delay of decision) */ +#define HANG_LEN 8 +#define BUF_LEN 60 +#define L_OVR 8 + +#define N_FEATURES_2 3 /* number of features */ + +/*----------------------------------------------------------------------------------* + * LD music post-filter constants + *----------------------------------------------------------------------------------*/ + +#define TH_0_MIN2_FX 3840 /* Q11 -> 1.875 */ +#define TH_1_MIN2_FX 2560 /* Q11 -> 1.25 */ +#define TH_2_MIN2_FX 1920 /* Q11 -> 0.9375 */ +#define TH_3_MIN2_FX 1280 /* Q11 -> 0.625 */ + +#define DCT_L_POST 640 +#define OFFSET2 192 + +#define VOIC_BINS_HR 640 +#define BIN_16kdct (6400/DCT_L_POST) +#define NB_LIMIT_BAND 16 +#define MBANDS_GN_LD 20 /* number of bands for gain coding in the postfilter */ + +/*----------------------------------------------------------------------------------* + * AC mode (GSC) constants + *----------------------------------------------------------------------------------*/ + +#define NOISE_LEVEL_SP0 8 +#define NOISE_LEVEL_SP1a 9 +#define NOISE_LEVEL_SP1 10 +#define NOISE_LEVEL_SP2 12 +#define NOISE_LEVEL_SP3 14 + +#define MAX_DYNAMIC 82 +#define MIN_DYNAMIC 50 +#define DYNAMIC_RANGE (MAX_DYNAMIC-MIN_DYNAMIC) +#define MAX_GSC_NF_BITS 3 +#define GSC_NF_STEPS (1 << MAX_GSC_NF_BITS) + +#define CRIT_NOIS_BAND 23 + +#define SSF 32 /* Sub-subframe length for energy estimation in UC decision */ +#define NB_SSF (L_FRAME / SSF) /* number of sub-subframes per frame */ + + +#define MBANDS_GN 16 /* Number of band for gain coding in GSC */ +#define BAND1k2 3 + +#define MBANDS_LOC (MBANDS_GN-1) +#define SWNB_SUBFR 1 + +#define VAR_COR_LEN 10 + +#define CFREQ_BITRATE ACELP_11k60 + +#define LT_UV_THR 100 +#define LT_UV_THRMID 70 + +#define PIT_EXC_L_SUBFR L_FRAME +#define LOCAL_CT VOICED + +#define Q_PVQ_OUT 10 + +/*----------------------------------------------------------------------------------* + * Core Switching constants + *----------------------------------------------------------------------------------*/ + +#define SWITCH_MAX_GAP 360 /* 6.25 + 1.25 of filter mem max */ + +/*----------------------------------------------------------------------------------* + * HQ core constants + *----------------------------------------------------------------------------------*/ + +#define HQ_NORMAL 0 +#define HQ_TRANSIENT 1 +#define HQ_HARMONIC 2 +#define HQ_HVQ 3 +#define HQ_GEN_SWB 4 +#define HQ_GEN_FB 5 + +#define PREECHO_SMOOTH_LEN 20 + +#define MAX16B 32767 +#define MIN16B (-32768) + +#define ALDO_WINDOW 4 +#define WINDECAY48 1230 +#define WINDECAY48_256 656 +#define WINDECAY16 410 +#define N16_CORE_SW 90 +#define N_ZERO_8 45 + +#define SWITCH_OVERLAP_8k 15 +#define SWITCH_GAP_LENGTH_8k 50 + +#define MAX_SEGMENT_LENGTH 480 +#define NUM_TIME_SWITCHING_BLOCKS 4 +#define NUM_MAP_BANDS 20 +#define NUM_MAP_BANDS_HQ_24k4 17 +#define NUM_MAP_BANDS_HQ_32k 18 +#define FREQ_LENGTH 800 + +#define STOP_BAND 800 + +#define SFM_G1 16 +#define SFM_G1G2 24 +#define SFM_N_NB 18 +#define SFM_N_WB 26 +#define SFM_N_STA_8k 27 +#define SFM_N_STA_10k 30 +#define SFM_N_ENV_STAB SFM_N_STA_8k /* Number of bands for env_stab stability measure */ +#define SFM_N_ENV_STAB_WB SFM_N_WB /* Number of bands for env_stab stability measure used in HQPLC decision for WB signals */ +#define SFM_N_HARMONIC 39 +#define SFM_N 36 + +#define L_HQ_WB_BWE 20 /* == band_end_wb[SFM_N_WB-1] - (band_start_wb[SFM_N_WB-1]+12) */ +#define N_INTL_GRP_16 2 /* Number of interleaving band groups at 16kHz samplerate */ +#define N_INTL_GRP_32 2 /* Number of interleaving band groups at 32kHz samplerate */ +#define N_INTL_GRP_48 3 /* Number of interleaving band groups at 48kHz samplerate */ +#define SFM_N_SWB 39 +#define SFM_N_HARM 31 +#define SFM_N_HARM_FB 33 +#define NB_SFM 44 +#define NB_SFM_MAX 58 +#define WID_G1 8 +#define WID_G2 16 +#define WID_G3 24 +#define WID_GX 32 +#define NUMC_N 544 +#define HQ_MAX_BAND_LEN 96 /* Largest bandwidth in HQ mode (band_len_harm[32]) */ +#define HVQ_PVQ_BUF_LEN (HVQ_PVQ_COEFS*(MAX_PVQ_BANDS-1) + HQ_MAX_BAND_LEN) /* 24*7+96 = 216 */ + +#define QBIT_MAX2 9 + +#define FLAGN_BITS 1 +#define GAIN0_BITS 5 +#define GAINI_BITS 5 + +#define FLAGS_BITS 2 +#define FLAGS_BITS_FB 3 +#define NORM0_BITS 5 +#define NORMI_BITS 5 +#define NUMNRMIBITS_SWB_STA_8k 5*(SFM_N_STA_8k-1) +#define NUMNRMIBITS_SWB_STA_10k 5*(SFM_N_STA_10k-1) +#define NUMNRMIBITS_SWB_HARMONIC 185 +#define NUMNRMIBITS_SWB 190 +#define NUMNRMIBITS 215 +#define NUMNRMIBITS_WB 125 + +#define NOHUFCODE 0 +#define HUFCODE 1 +#define HUFF_THR 10 +#define NOSUPERPOSITION 40 + +#define MAXVALUEOFFIRSTGAIN_FX 20480 /*2.5f in Q13 */ +#define MINVALUEOFFIRSTGAIN_FX -20480 +#define NOOFGAINBITS1 6 + +#define AUDIODELAYBITS 6 +#define DELTAOFFIRSTGAIN_FX 2601 /*Q15 */ + +#define MAX_D1M_16k ((L_FRAME16k>>1) - NS2SA(16000,SWITCH_GAP_LENGTH_NS) - 16) +#define MAX_D1M_12k8 ((L_FRAME16k>>1) - NS2SA(16000,SWITCH_GAP_LENGTH_NS) - 20) + +#define MAX_P_ATT 40 /* Maximum number of pulses for gain attenuation factor */ +#define NB_G 4 /* Number of band groups */ +#define MAX_GAIN_BITS 5 /* Maximum number of gain bits */ + +#define ENV_ADJ_START 6 /* Number of consecutive bands for which the attenuation is maximum */ +#define ENV_ADJ_INCL 5 /* Inclination for mapping between attenuation region width and attenuation limit */ + +#define L_STAB_TBL 10 /* Number of elements in stability transition table */ +#define LUMPED_ENV_SMOOTH_FAC_FX ((Word16)10089) /* Q19 (no typo error), 0.1/sqrt(27) */ +#define CMPLMNT_ENV_SMOOTH_FAC_FX ((Word16)29491) /* Q15 0.9 */ +#define M_STAB_TBL_FX ((Word16)21068) /* Q13, 2.571756 */ +#define HALF_D_STAB_TBL_FX ((Word16) 422) /* Q13 0.1013138/2.0 */ +#define D_STAB_TBL_FX ((Word16) 845) /* Q13 0.1013138 */ +#define NUM_ENV_STAB_PLC_STATES 2 /* Number of states of markov model */ +#define INV_NUM_ENV_STAB_PLC_STATES 16384 /* Q15 */ +#define INV_STAB_TRANS_FX 16497 /* Q14. Equal to 1.0f/(1-2*stab_trans_fx[L_STAB_TBL-1]) */ + +#define ATT_LIM_HANGOVER 150 /* Number of hangover frames for disabling stability dependent attenuation */ + +#define START_EXC 60 +#define L_HARMONIC_EXC 202 + +#define HQ_GENERIC_OFFSET 2 +#define HQ_GENERIC_END_FREQ 560 + +#define HQ_GENERIC_FOFFSET_24K4 80 +#define HQ_GENERIC_FOFFSET_32K 144 +#define HQ_GENERIC_SWB_NBITS 31 +#define HQ_GENERIC_SWB_NBITS2 30 +#define HQ_GENERIC_FB_NBITS 5 + +#define HQ_GENERIC_ST_FREQ 224 +#define HQ_GENERIC_LOW0 80 +#define HQ_GENERIC_HIGH0 240 +#define HQ_GENERIC_HIGH1 368 +#define HQ_GENERIC_HIGH2 496 +#define HQ_GENERIC_LEN0 128 +#define HQ_GENERIC_NVQIDX 6 + +#define HQ_GENERIC_EXC0 0 +#define HQ_GENERIC_EXC1 1 +#define HQ_GENERIC_SP_EXC 2 + + +#define DIM_FB 3 +#define HQ_FB_FENV SWB_FENV + DIM_FB +#define N_CB_FB 32 + +#define HVQ_THRES_BIN_24k 224 +#define HVQ_THRES_SFM_24k 22 +#define HVQ_THRES_BIN_32k 320 +#define HVQ_THRES_SFM_32k 25 +#define HVQ_MIN_PEAKS 2 +#define HVQ_MAX_PEAKS_32k 23 +#define HVQ_MAX_PEAKS_24k 17 +#define HVQ_MAX_PEAKS_24k_CLAS 20 /* Limit for HVQ mode */ +#define HVQ_MAX_PEAKS HVQ_MAX_PEAKS_32k + 1 +#define HVQ_NUM_SFM_24k (SFM_N_HARMONIC - 1 - HVQ_THRES_SFM_24k) +#define HVQ_NUM_SFM_32k (SFM_N_HARMONIC - 1 - HVQ_THRES_SFM_32k) + +#define HVQ_MAX_RATE 32000 + + + +#define NUMNRMIBITS_SWB_HVQ_24k 35 +#define NUMNRMIBITS_SWB_HVQ_32k 25 + +#define MAX_PVQ_BANDS 8 +#define HVQ_MAX_PVQ_WORDS ((HVQ_MAX_RATE/50)/16 + MAX_PVQ_BANDS) +#define HVQ_MAX_POS_WORDS 40 +#define HVQ_PVQ_COEFS 24 +#define HVQ_BAND_MIN_PULSES 2 +#define HVQ_BAND_MAX_BITS_24k 80 +#define HVQ_BAND_MAX_BITS_32k 95 +#define HVQ_NEW_BAND_BIT_THR 30 + +#define HVQ_NF_GROUPS 2 +#define HVQ_NF_WEIGHT1_FX 31385 /* Q15 0.9578 - HVQ Classifier - Noise floor estimate weight 1 */ +#define HVQ_NF_WEIGHT1B 1383 /* Q15, 1 - HVQ_NF_WEIGHT1_FX */ +#define HVQ_NF_WEIGHT2_FX 21207 /* Q15 0.6472 - HVQ Classifier - Noise floor estimate weight 2 */ +#define HVQ_NF_WEIGHT2B 11561 /* Q15 1 - HVQ_NF_WEIGHT2_FX */ +#define HVQ_PE_WEIGHT1_FX 13840 /* Q15 0.42237 - HVQ Classifier - Peak envelope estimate weight 1 */ +#define HVQ_PE_WEIGHT1B 18928 /* Q15, 1 - HVQ_PE_WEIGHT1_FX */ +#define HVQ_PE_WEIGHT2_FX 26308 /* Q15 0.80285 - HVQ Classifier - Peak envelope estimate weight 2 */ +#define HVQ_PE_WEIGHT2B 6460 /* Q15, 1 - HVQ_PE_WEIGHT2_FX */ +#define HVQ_SHARP_THRES_FX 576 /*9 in Q6 */ + +#define HVQ_PA_FAC_FX 23170 /* Q15 0.7071 - HVQ Classifier peak allocation factor */ +#define HVQ_PA_PEAKS_SHARP1 9 /* HVQ Classifier - Maximum number of peaks for band with high sharpness */ +#define HVQ_PA_PEAKS_SHARP2 3 /* HVQ Classifier - Maximum number of peaks for band with medium sharpness */ +#define HVQ_PA_PEAKS_SHARP3 2 /* HVQ Classifier - Maximum number of peaks for band with low sharpness */ +#define HVQ_PA_SHARP_THRES2_FX 1024 /* Q6 16.0 - HVQ Classifier - Sharpness threshold for band with medium sharpness */ +#define HVQ_PA_SHARP_THRES3_FX 768 /* Q6 12.0 - HVQ Classifier - Sharpness threshold for band with low sharpness */ + +#define HVQ_BW 32 /* HVQ Classifier subband bandwidth */ +#define HVQ_NSUB_32k 10 +#define HVQ_NSUB_24k 7 /* HVQ Classifier number of subbands */ + +#define HVQ_BWE_NOISE_BANDS 2 /* Number of BWE noise bands */ +#define HVQ_BWE_WEIGHT1_FX ((Word16)31130) /* 0.95 in Q15 */ +#define HVQ_BWE_WEIGHT2_FX ((Word16)6554) /* 0.2 in Q15 */ +#define HVQ_NFPE_FACTOR_CUBE_FX ((Word16)16777) /* 6.4^3 in Q6 */ +#define HVQ_LB_NFPE_FACTOR_CUBE_FX ((Word16)16777) /* 3.2^3 in Q9 */ + +#define HVQ_VQ_DIM 5 /* HVQ peak VQ dimension */ +#define HVQ_PVQ_GAIN_BITS 5 /* Number of bits to encode PVQ gains in HVQ */ +#define HVQ_NUM_CLASS 4 /* Number of codebook classes */ +#define HVQ_CB_SIZE 256 + +#define NUM_PG_HUFFLEN 9 /* Number of Huffman codewords for peak gains */ +#define MAX_PG_HUFFLEN 12 /* Length of the longest codeword for peak gain Huffman coding */ + +#define HVQ_CP_HUFF_OFFSET 3 /* HVQ Code Pos - Delta offset */ +#define HVQ_CP_HUFF_MAX 51 /* HVQ Code Pos - Maximum delta for huffman coding */ +#define HVQ_CP_HUFF_MAX_CODE 13 /* HVQ Code Pos - Size of largest code word */ +#define HVQ_CP_HUFF_NUM_LEN 11 /* HVQ Code Pos - Number of different huffman lengths */ +#define HVQ_CP_L2_MAX 64 /* HVQ Code Pos - Layer 2 maximum size */ +#define HVQ_CP_L1_LEN 5 /* HVQ Code Pos - Layer 1 block size */ +#define HVQ_CP_MAP_LEN 8 /* HVQ Code Pos - Mapping table size */ +#define HVQ_CP_MAP_IDX_LEN 3 /* HVQ Code Pos - Mapping index size */ +#define HVQ_CP_DELTA 0 /* HVQ Code Pos - Use Delta coding */ +#define HVQ_CP_SPARSE 1 /* HVQ Code Pos - Use Sparse coding */ + +#define MAX_SPLITS 10 /* Maximum number of PVQ band splits */ + +#define QUANTAQ3OFFSET 1 +enum QuantaMode { NEAREST = 0, CONS }; +#define PYR_OFFSET 1 +#define RCF_INIT_SHIFT 14 + +#define THR_ADD_SPLIT 7 /* Threshold for using additional split */ +#define PVQ_MAX_BAND_SIZE 64 /* Maxiumum supported band size for PVQ search */ +#define MIN_BAND_SIZE 1 /* Minimum supported band size for PVQ search */ +#define RC_BITS_RESERVED 1 +#define MAX_PVQ_BITS_PER_COEFFICIENT 80 /* Maximum bits per coefficient allocated per PVQ band. Q3. */ + +/* index_pvq constants */ +#define KMAX_FX 512 + +#define KMAX_NON_DIRECT_FX 96 /* max K for non-direct indexing recursion rows is 1+KMAX_NON_DIRECT +1 */ +#define ODD_DIV_SIZE_FX 48 /* ind0=1/1 ind1 =1/3 ... ind47=1/95 */ + + +/* TCQ */ +#define TCQ_MAX_BAND_SIZE 120 /* Maxiumum supported band size for TCQ+USQ search */ +#define STATES 8 +#define MAX_AR_FREQ 16383 +#define AR_BITS 16 +#define STATES_LSB 4 +#define TCQ_LSB_SIZE 24 +#define TCQ_AMP 10 + +#define AR_TOP ( ( 1 << AR_BITS ) - 1 ) +#define AR_FIRST ( AR_TOP / 4 + 1 ) +#define AR_HALF ( 2 * AR_FIRST ) +#define AR_THIRD ( 3 * AR_FIRST ) + +#define MAX_SIZEBUF_PBITSTREAM 1024 + +/*----------------------------------------------------------------------------------* + * SWB BWE for LR MDCT core + *----------------------------------------------------------------------------------*/ +/* Q value */ +#define SWB_BWE_LR_Qs 12 /* Q value of spectra (Word32) */ +#define SWB_BWE_LR_Qbe 14 /* Q value of band_energy (Word32) */ +#define SWB_BWE_LR_QRk 16 /* Q value of Rk, Rcalc (Word32) */ +#define SWB_BWE_LR_QsEn 4 /* Q value of smoothed sqrt band energy */ + +#define G1_RANGE 4 +#define G1G2_RANGE 15 +#define GRP_SB 4 /*Maximum subband groups*/ +#define THR1 4 /* Bit allocation threshold value */ +#define THR2 5 /* Bit allocation threshold value */ +#define THR3 6 /* Bit allocation threshold value */ + +#define NB_SWB_SUBBANDS 4 /* maximum number of subbands in normal2 subband coding */ + +#define SWB_SB_LEN0_12KBPS 55/* length of subband number X in lowest bit rate operation */ +#define SWB_SB_LEN1_12KBPS 68 +#define SWB_SB_LEN2_12KBPS 84 +#define SWB_SB_LEN3_12KBPS 105 + +#define SWB_HIGHBAND_12KBPS (SWB_SB_LEN0_12KBPS+SWB_SB_LEN1_12KBPS+SWB_SB_LEN2_12KBPS+SWB_SB_LEN3_12KBPS) +#define SWB_LOWBAND_12KBPS (HQ_GENERIC_END_FREQ - SWB_HIGHBAND_12KBPS) +#define SWB_HIGHBAND_MAX SWB_HIGHBAND_12KBPS +#define SWB_LOWBAND_MAX SWB_LOWBAND_12KBPS + +#define SWB_SB_OFF0_12KBPS 0 /* subband offsets are based on the subband lengths */ +#define SWB_SB_OFF1_12KBPS (SWB_SB_OFF0_12KBPS + SWB_SB_LEN0_12KBPS) +#define SWB_SB_OFF2_12KBPS (SWB_SB_OFF1_12KBPS + SWB_SB_LEN1_12KBPS) +#define SWB_SB_OFF3_12KBPS (SWB_SB_OFF2_12KBPS + SWB_SB_LEN2_12KBPS) +#define SWB_SB_OFF4_12KBPS (SWB_SB_OFF3_12KBPS + SWB_SB_LEN3_12KBPS) + +/* 16.4 kbps */ +#define SWB_SB_LEN0_16KBPS 59/* length of subband number X in lowest bit rate operation */ +#define SWB_SB_LEN1_16KBPS 74 +#define SWB_SB_LEN2_16KBPS 92 +#define SWB_SB_LEN3_16KBPS 115 + +#define SWB_HIGHBAND_16KBPS (SWB_SB_LEN0_16KBPS+SWB_SB_LEN1_16KBPS+SWB_SB_LEN2_16KBPS+SWB_SB_LEN3_16KBPS) +#define SWB_LOWBAND_16KBPS (HQ_GENERIC_END_FREQ - SWB_HIGHBAND_16KBPS) + +#define SWB_SB_OFF0_16KBPS 0 /* subband offsets are based on the subband lengths */ +#define SWB_SB_OFF1_16KBPS (SWB_SB_OFF0_16KBPS + SWB_SB_LEN0_16KBPS) +#define SWB_SB_OFF2_16KBPS (SWB_SB_OFF1_16KBPS + SWB_SB_LEN1_16KBPS) +#define SWB_SB_OFF3_16KBPS (SWB_SB_OFF2_16KBPS + SWB_SB_LEN2_16KBPS) +#define SWB_SB_OFF4_16KBPS (SWB_SB_OFF3_16KBPS + SWB_SB_LEN3_16KBPS) + +/* SpectrumSmoothing */ +#define L_SB 12 /* subband length for SpectrumSmoothing */ + +/* SpectrumSmoothing for NSS */ +#define L_SB_NSS 8 +#define L_SB_NSS_HALF (L_SB_NSS/2) +#define NUM_SUBBAND_SMOOTH_MAX (L_FRAME32k/L_SB_NSS+1) +#define MA_LEN 7 + +/* Harmonic mode */ +#define NB_SWB_SUBBANDS_HAR_SEARCH_SB 2 /* search number of subbands in harmonic subband coding */ +#define NB_SWB_SUBBANDS_HAR 4 /* maximum number of subbands in harmonic subband coding */ + + +#define N_NBIGGEST_PULSEARCH 18 +#define N_NBIGGEST_SEARCH_LRG_B 32 + + +/* 13.2 kbps */ +#define SWB_SB_BW_LEN0_12KBPS_HAR 56 /* Group 1 length for BWE */ +#define SWB_SB_BW_LEN1_12KBPS_HAR 100 /* Group 2 Length for BWE */ +#define SWB_SB_BW_LEN2_12KBPS_HAR SWB_SB_BW_LEN1_12KBPS_HAR +#define SWB_SB_BW_LEN3_12KBPS_HAR SWB_SB_BW_LEN0_12KBPS_HAR + +/* 16.4 kbps */ +#define SWB_SB_BW_LEN0_16KBPS_HAR 60 /* Group 1 length for BWE */ +#define SWB_SB_BW_LEN1_16KBPS_HAR 110 /* Group 2 Length for BWE */ +#define SWB_SB_BW_LEN2_16KBPS_HAR SWB_SB_BW_LEN1_16KBPS_HAR +#define SWB_SB_BW_LEN3_16KBPS_HAR SWB_SB_BW_LEN0_16KBPS_HAR + +#define SWB_SB_OFF0_SUB5_12KBPS_HAR 0 /* subband offsets are based on the subband lengths */ +#define SWB_SB_OFF1_SUB5_12KBPS_HAR (SWB_SB_OFF0_SUB5_12KBPS_HAR + SWB_SB_BW_LEN0_12KBPS_HAR) +#define SWB_SB_OFF2_SUB5_12KBPS_HAR (SWB_SB_OFF1_SUB5_12KBPS_HAR + SWB_SB_BW_LEN1_12KBPS_HAR) +#define SWB_SB_OFF3_SUB5_12KBPS_HAR (SWB_SB_OFF2_SUB5_12KBPS_HAR + SWB_SB_BW_LEN2_12KBPS_HAR) + +#define SWB_SB_OFF0_SUB5_16KBPS_HAR 0 /* subband offsets are based on the subband lengths */ +#define SWB_SB_OFF1_SUB5_16KBPS_HAR (SWB_SB_OFF0_SUB5_16KBPS_HAR + SWB_SB_BW_LEN0_16KBPS_HAR) +#define SWB_SB_OFF2_SUB5_16KBPS_HAR (SWB_SB_OFF1_SUB5_16KBPS_HAR + SWB_SB_BW_LEN1_16KBPS_HAR) +#define SWB_SB_OFF3_SUB5_16KBPS_HAR (SWB_SB_OFF2_SUB5_16KBPS_HAR + SWB_SB_BW_LEN2_16KBPS_HAR) + +#define LR_BLK_LEN 16 +#define LR_HLF_PK_BLK_LEN 8 +#define LR_LOWBAND_DIF_PK_LEN 10 +#define SWB_HAR_RAN1 80 +#define SWB_HAR_RAN2 140 +#define SWB_HAR_RAN3 200 +#define SPT_SHORTEN_SBNUM 4 + +/*----------------------------------------------------------------------------------* + * FEC for HQ core + *----------------------------------------------------------------------------------*/ + +#define MAX_PGF 7 +#define MAX_ROW 2 + +#define MINIMUM_RATE_TO_ENCODE_VOICING_FLAG 45000 +#define FRAMECTTOSTART_MDCT 3 + +/*----------------------------------------------------------------------------------* + * Channel-aware mode (FEC) + *----------------------------------------------------------------------------------*/ + +#define FEC_OFFSET 3 +#define MAX_RF_FEC_OFFSET 9 + +/*----------------------------------------------------------------------------------* + * HQ FEC + *----------------------------------------------------------------------------------*/ + +#define MAXDELAY_FEC 224 + +#define PH_ECU_ALDO_OLP2_NS (ACELP_LOOK_NS/2) /* half the aldo window overlap */ +#define PH_ECU_LOOKAHEAD_NS (11*ACELP_LOOK_NS/(7*2)) /* Number of nanoseconds look-ahead ahead from the end of the past synthesized frame */ +#define PH_ECU_MEM_NS ((Lprot48k/48 - 20)*1000000-PH_ECU_LOOKAHEAD_NS) /* Number of nanoseconds memory for Phase ECU before the old_synthFB_fx pointer */ +#define POST_HQ_DELAY_NS DELAY_BWE_TOTAL_NS /* delay of post processing after core HQ coding */ +#define MAX_PLOCS Lprot48k/4+1 /* maximum number of spectral peaks to be searched */ +#define Lprot32k 1024 /* HQ phase ECU prototype frame length */ +#define Lprot32k_2 Lprot32k/2 +#define Quot_Lpr_Ltr 4 +#define Lgw_max 9 /* maximum number frequency group widths */ +#define BETA_MUTE_FAC_INI 16384 /* Q15, initial noise attenuation factor */ +#define Ltrana32k (Lprot32k/Quot_Lpr_Ltr) /* transient analysis frame length */ +#define Ltrana16k Ltrana32k/2 +#define pfind_sens 0.9f /* peakfinder sensitivity - tuning parameter */ +#define Lprot_hamm_len2_48k NS2SA(48000,6000000L) +#define Lprot_hamm_len2_32k NS2SA(32000,6000000L) +#define Lprot_hamm_len2_16k NS2SA(16000,6000000L) +#define Lprot48k Lprot32k * 3/2 /* HQ phase ECU prototype frame length */ +#define Lprot48k_2 Lprot48k/2 +#define Ltrana48k (Lprot48k/Quot_Lpr_Ltr) /* transient analysis frame length */ +#define PH_ECU_SPEC_SIZE Lprot48k +#define T_SIN_PI_2 PH_ECU_SPEC_SIZE/4 +#define RANDOM_START 1 +#define HQ_FEC_SIGN_SFM 16 +#define HQ_FEC_SIGN_THRES 6 +#define HQ_FEC_SIGN_THRES_TRANS 3 +#define HQ_FEC_BAND_SIZE 4 + +/*--------------------------------------------------------------* + * Tonal MDCT PLC constants + *---------------------------------------------------------------*/ +#define SPEC_EXP_DEC 20 + +#define MAX_NUMBER_OF_IDX 30 +#define GROUP_LENGTH 7 +#define MAX_PEAKS_FROM_PITCH 10 +#define LAST_HARMONIC_POS_TO_CHECK 128 /* 128 because we check harmonics only up to 3.2 kHz */ +#define FILTLEN 15 +#define ALLOWED_SIDE_LOBE_FLUCTUATION 24576/*3.0f Q13*/ /* 4.8 dB */ +#define ALLOWED_SIDE_LOBE_FLUCTUATION_EXP 2 +#define LEVEL_ABOVE_ENVELOPE 7.59f /* 8.8 dB */ +#define UNREACHABLE_THRESHOLD 16384/*16.0f Q10*/ /* 12 dB Increase of LEVEL_ABOVE_ENVELOPE so that the threshold is not reached */ +#define SMALL_THRESHOLD 1126/*1.10f Q10*/ /* 0.41 dB Increase of LEVEL_ABOVE_ENVELOPE for the peak detection at a definitive peak in the estimated spectrum */ +#define BIG_THRESHOLD 1536/*1.5f Q10*/ /* 1.76 dB Increase of LEVEL_ABOVE_ENVELOPE for the peak detection at a probable peak in the estimated spectrum */ + +#define kSmallerLagsTargetBitsThreshold 150 + +#define kLtpHmGainThr 0x3AE1 /* 0.46f */ +#define kCtxHmOlRSThr 0x5333 /* 2.6f (2Q13) */ + +#define kTcxHmSnrOffsetGc 8/*0.03125f Q8*/ +#define kTcxHmSnrOffsetVc 0 + +#define kTcxHmNumGainBits 2 /* Number of bits for the gain index */ +#define kTcxHmParabolaHalfWidth 4 /* Parabola half width */ +#define kLtpHmGainThr 0x3AE1 /* 0.46f */ /* Use the LTP pitch lag in the harmonic model? */ + +#define kSmallerLagsTargetBitsThreshold 150 + +#define TCX_LPC_OFFSET_SNR + +#define kTcxSnrOffsetGc 0x08 /* 0.03125f (7Q8) */ +#define kTcxSnrOffsetVc 0x20 /* 0.125f (7Q8) */ + +#define LOWRATE_TCXLPC_MAX_BR ACELP_9k60 + +/*--------------------------------------------------------------* + * Waveform-adjustment MDCT PLC + *---------------------------------------------------------------*/ + +#define DEC_STATE_LEN 10 +#define MAX_POST_LEN 3 +#define TCX_TONALITY_INIT_CNT 7 + +#define TCX_NONTONAL 0 +#define TCX_TONAL 1 + +/*---------------------------------------------------------------* + * IGF * + *---------------------------------------------------------------*/ +#define IGF_MAX_TILES 5 +#define IGF_MAX_GRANULE_LEN 1200 +#define IGF_TRANS_FAK 2 +#define IGF_MAX_SFB 23 +#define IGF_NOF_GRIDS 3 +#define IGF_MAX_SUBFRAMES 2 + +#define IGF_MODE_WB 1 +#define IGF_MODE_SWB 2 +#define IGF_MODE_FB 3 + + +#define IGF_BITRATE_WB_9600 0 +#define IGF_BITRATE_RF_WB_13200 1 +#define IGF_BITRATE_SWB_9600 2 +#define IGF_BITRATE_SWB_13200 3 +#define IGF_BITRATE_RF_SWB_13200 4 +#define IGF_BITRATE_SWB_16400 5 +#define IGF_BITRATE_SWB_24400 6 +#define IGF_BITRATE_SWB_32000 7 +#define IGF_BITRATE_SWB_48000 8 +#define IGF_BITRATE_FB_16400 9 +#define IGF_BITRATE_FB_24400 10 +#define IGF_BITRATE_FB_32000 11 +#define IGF_BITRATE_FB_48000 12 +#define IGF_BITRATE_FB_96000 13 +#define IGF_BITRATE_FB_128000 14 +#define IGF_BITRATE_UNKNOWN 15 + + +#define IGF_WHITENING_OFF 0 +#define IGF_WHITENING_MID 1 +#define IGF_WHITENING_STRONG 2 + +#define IGF_GRID_LB_NORM 0 +#define IGF_GRID_LB_TRAN 1 +#define IGF_GRID_LB_SHORT 2 + +/* constants for IGFSCFDecoder and IGFSCFEncoder */ +#define IGF_CTX_OFFSET 3 /* offset added to make the context values nonnegative, for array indexing */ +#define IGF_CTX_COUNT (2 * IGF_CTX_OFFSET + 1) /* number of contexts for the AC statistical model */ +#define IGF_MIN_ENC_SEPARATE -12 /* minimum residual value coded separately, without escape coding */ +#define IGF_MAX_ENC_SEPARATE +12 /* maximum residual value coded separately, without escape coding */ +#define IGF_SYMBOLS_IN_TABLE (1 + (IGF_MAX_ENC_SEPARATE - IGF_MIN_ENC_SEPARATE + 1) + 1) /* alphabet size */ + +/*----------------------------------------------------------------------------------* + * SC-VBR + *----------------------------------------------------------------------------------*/ + +#define UVG1_CBSIZE 32 /* NELP unvoiced gain-1 codebook size */ +#define UVG2_CBSIZE 64 /* NELP unvoiced gain-2 codebook size */ + +/* PPP constants */ + +#define NUM_ERB_WB 24 /* Number of ERB bands in wideband */ +#define NUM_ERB_NB 22 /* Number of ERB bands in narrowband */ + +#define MAXLAG 180 + +#define PPP_LAG_THRLD_Q6 180*64 +#define PPP_LAG_THRLD 180 +#define SNR_THLD_FX_Q8 17152 /* Threshold is upscaled to Q8 to compared with st->vadsnr*/ + +#define MAXLAG_WI (PPP_LAG_THRLD/2 + 12) /* Maximum lag used in waveform interpolation */ +#define MAX_LAG_PIT (PPP_LAG_THRLD + 21) + +#define WI_FX_phase_fx 512 + +#define VBR_ADR_MAX_TARGET_x10_Q1 123 /* VBR_ADR_MAX_TARGET(6.15f)*10 in Q1 */ + +#define Q_SCALE 7 + +#define CONST_1_16_Q14 19005 /* 1.16*16384 */ +#define CONST_1_37_Q14 22446 /* 1.37*16384 */ +#define SCALE_DOWN_ERAS_Q15 26214 /* 0.8*32768 */ +#define SHAPE1_COEF_QF 15 /* shape1 num and den coeffcient Q format */ +#define SHAPE2_COEF_QF 15 /* shape2 num and den coeffcient Q format */ +#define SHAPE3_COEF_QF 15 /* shape3 num and den coeffcient Q format */ +#define BP1_COEF_WB_QF 14 /* wb num and den coeffcient Q format */ +#define BP1_COEF_NB_QF_ORDER7 13 /* nb num and den coeffcient Q format */ + +/*----------------------------------------------------------------------------------* + * JBM + *----------------------------------------------------------------------------------*/ + +#define MAX_JBM_SLOTS 100 /* every primary copy and partial copy stored in JBM needs one slot */ +#define MAX_AU_SIZE (128000/50/8) /* max frame size in bytes */ + +#define ACTIVE 4 +#define BACKGROUND 1 +#define LOST 14 +#define SIZE_UNDERFLOW_ARRAY 10000 +#define TIME_WARP_SPACING 4 +#define FLAG_DECREASING_BUFFER_DEPTH 1 +#define TIME_WARP_SPACING_EXPAND 1 +#define PREALLOCATE_OUTPUT_SIZE 1000 + +#define TSM_LOST 1 +#define TSM_AUDIO 2 +#define TSM_ONSET 3 +#define TSM_UNVOICED 4 +#define TSM_VOICED 5 +#define TSM_TRANSITION 6 +#define TSM_GENERIC 7 +#define TSM_BACKGROUND 8 + +/*------------------------------------------------------------------------------------* +FEC_clas_estim constants +*-------------------------------------------------------------------------------------*/ +#define Q_MAX 12 +#define LG10 24660 /* 10*log10(2) in Q13 */ +#define L_Q_MEM 5 + +#define GE_SHIFT 6 +#define LSF_1_OVER_256SQ 5000 +#define LSF_1_OVER_256SQSQ 763 + +#define G_CODE_MIN_TC_Q15 655 /*0.02 Q15*/ +#define G_CODE_MAX_TC_Q0 5 + +#define G_PITCH_MIN_Q14 0 /* SQ of gains: pitch gain lower limit (0.0 in Q13) */ +#define G_PITCH_MAX_MINUS_MIN_Q13 9994 /* SQ of gains: pitch gain upper limit (1.22-0 in Q13) */ + +/* higher ACELP constants */ +#define G_AVQ_MIN_32kbps_Q15 2621 /* lower limit for gain Q in higher-rate ACELP contribtuion @32kbps (0.08 in Q15) */ +#define G_AVQ_MIN_Q15 26214 /* lower limit for gain Q in higher-rate ACELP contribtuion (0.8 in Q15) */ +#define G_AVQ_MAX_Q0 96 /* upper limit for gain Q in higher-rate ACELP contribtuion */ + +#define LG10_G_AVQ_MIN_32kbps_Q14 (-17972) /* log10(0.08) lower limit for gain Q in higher-rate ACELP contribtuion @32kbps (0.08 in Q15) */ +#define LG10_G_AVQ_MIN_Q14 (-1588) /* log10(0.8) lower limit for gain Q in higher-rate ACELP contribtuion (0.8 in Q15) */ +#define LG10_G_AVQ_MAX_Q13 16239 /* log10(96) upper limit for gain Q in higher-rate ACELP contribtuion */ +#define LG10_G_CODE_MIN_TC192_Q14 (-3635) /* log10(0.6) */ +#define LG10_G_CODE_MAX_TC192_Q13 13212 /* log10(41) */ +#define LG10_G_CODE_MAX_Q13 5726 /* log10(5) SQ of gains: code gain upper limit */ +#define LG10_G_CODE_MIN_Q14 (-27836) /* log10(0.02) SQ of gains: code gain lower limit */ +#define LG10_G_CODE_MIN_TC_Q14 LG10_G_CODE_MIN_Q14 /* log10(0.02) Q15*/ +#define LG10_G_CODE_MAX_TC_Q13 LG10_G_CODE_MAX_Q13 + + +/* AVQ (RE8) related consatnts */ +#define QR 32768 +#define Q_AVQ_OUT 6 /* AVQ_output scaling currently Q9, but may change */ +#define Q_AVQ_OUT_DEC 10 + + +#define PIT_DECODE_2XL_SUBFR (2*L_SUBFR) +#define PIT_FR1_8b_MINUS_PIT_MIN_X2 ((PIT_FR1_8b-PIT_MIN)*2) +#define PIT_FR1_8b_MINUS_PIT_FR1_8b_MINUS_PIT_MIN_X2 (PIT_FR1_8b-PIT_FR1_8b_MINUS_PIT_MIN_X2) +#define PIT_FR2_9b_MINUS_PIT_MIN_X4 ((PIT_FR2_9b-PIT_MIN)*4) +#define PIT_FR1_EXT8b_MINUS_PIT_MIN_EXT_X2 ((PIT_FR1_EXTEND_8b-PIT_MIN_EXTEND)*2) +#define PIT_FR2_EXT9b_MINUS_PIT_MIN_EXT_X4 ((PIT_FR2_EXTEND_9b-PIT_MIN_EXTEND)*4) +#define PIT_FR1_EXT9b_MINUS_PIT_FR2_EXT9b_X2 ((PIT_FR1_EXTEND_9b-PIT_FR2_EXTEND_9b)*2) +#define PIT_FR1_DEXT8b_MINUS_PIT_MIN_DEXT_X2 ((PIT_FR1_DOUBLEEXTEND_8b-PIT_MIN_DOUBLEEXTEND)*2 ) +#define PIT_FR2_DEXT9b_MINUS_PIT_MIN_DEXT_X4 ((PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4 ) + +#define PIT_DECODE_1 ((PIT_FR2_9b-PIT_MIN)*4 + (PIT_FR1_9b-PIT_FR2_9b)*2) +#define PIT_DECODE_2 ((PIT_FR2_9b-PIT_MIN)*4) +#define PIT_DECODE_3 (PIT_FR1_9b - ((PIT_FR2_9b-PIT_MIN)*4) - ((PIT_FR1_9b-PIT_FR2_9b)*2)) +#define PIT_DECODE_7 (PIT_FR1_EXTEND_9b - (PIT_FR2_EXT9b_MINUS_PIT_MIN_EXT_X4) - (PIT_FR1_EXT9b_MINUS_PIT_FR2_EXT9b_X2)) +#define PIT_DECODE_8 (PIT_FR1_DOUBLEEXTEND_8b - ((PIT_FR1_DOUBLEEXTEND_8b-PIT_MIN_DOUBLEEXTEND)*2)) +#define PIT_DECODE_9 (( (PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4 + (PIT_FR1_DOUBLEEXTEND_9b-PIT_FR2_DOUBLEEXTEND_9b)*2)) +#define PIT_DECODE_10 (PIT_FR1_DOUBLEEXTEND_9b - ((PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4) - ((PIT_FR1_DOUBLEEXTEND_9b-PIT_FR2_DOUBLEEXTEND_9b)*2)) + +#define BIN4_FX 800 +#define TH_COR_FX 19661 /* Q15 Minimum correlation for per bin processing */ +#define TH_D_FX 800 /* 50 (Q4) Difference limit between nearest harmonic and a frequency bin */ +#define TH_PIT_FX 128 /* (Fs / (2.0f * TH_D)) Maximum pitch for per bin processing */ + +#define GUESS_TBL_SZ 256 +#define INT_FS_FX 12800 /* internal sampling frequency */ +#define INT_FS_16k_FX 16000 /* CELP core internal sampling frequency @16kHz */ + +#define WB_LIMIT_LSF_FX 16256 +#define Fs_2 16384 /* lsf max value (Use in reorder_fx.c) */ +#define Fs_2_16k 20480 /* lsf max value (Use in reorder_fx.c) */ + +#define LG10 24660 /* 10*log10(2) in Q13 */ +#define LG10_s3_0 16440 /* 10*log10(2)/1.55 = 1.00343331 in Q14 */ + +#define MU_MA_FX 10923 /* original prediction factor for the AMR WB tables (Q15) */ + +#define E_MIN_FXQ15 115 /* Q15*/ + +#define MAX_DYNAMIC_FX (82*128) +#define MIN_DYNAMIC_FX (50*128) +#define DYNAMIC_RANGE_FX (MAX_DYNAMIC_FX-MIN_DYNAMIC_FX) +#define MAX_GSC_NF_BITS 3 +#define GSC_NF_STEPS (1 << MAX_GSC_NF_BITS) +#define GSF_NF_DELTA_FX (DYNAMIC_RANGE_FX/GSC_NF_STEPS) + +/*----------------------------------------------------------------------------------* + * DTC/iDCT constants + *----------------------------------------------------------------------------------*/ + +/* DCT related */ +#define KP559016994_16FX 1200479845 /* EDCT & EMDCT constants */ +#define KP951056516_16FX 2042378325 /* EDCT & EMDCT constants */ +#define KP587785252_16FX 1262259213 /* EDCT & EMDCT constants */ + +/*----------------------------------------------------------------------------------* + * AVQ constants + *----------------------------------------------------------------------------------*/ + +#define MIN_GLOB_GAIN_BWE_HR_FX 24576 /* Q13 */ +#define MAX_GLOB_GAIN_BWE_HR_FX 32000 /* Q6 */ + +#define LG10_MIN_GLOB_GAIN_BWE_HR_Q14 7817 +#define LG10_MAX_GLOB_GAIN_BWE_HR_Q13 22110 + + +/*----------------------------------------------------------------------------------* + * LD music post-filter constants + *----------------------------------------------------------------------------------*/ + +#define BIN_16kdct_fx (6400/DCT_L_POST) +#define E_MIN_Q15 14680 /* 0.0035 -> Q22 */ + +#define QSCALE 7 +#define MODE2_E_MIN 4/*0.03f Q0*/ /* 0.03f in QSCALE */ +#define MODE2_E_MIN_Q15 983/*0.03f Q15*/ /* 0.03f in Q15*/ + +/* long term pst parameters : */ +#define L2_LH2_L 4 /* log2(LH2_L) */ +#define MIN_GPLT_FX 21845 /* LT gain minimum 1/1.5 (Q15) */ + +#define AGC_FAC_FX 32358 /* gain adjustment factor 0.9875 (Q15) */ +#define AGC_FAC1_FX (Word16)(32768L - AGC_FAC_FX) + +#define DOWNMIX_12k8_FX 1850 + +/*----------------------------------------------------------------------------------* + * HQ Constants + *----------------------------------------------------------------------------------*/ + +#define INV2POWHALF 23170 /* Q15, sqrt(2)/2 */ +#define EPSILLON_FX (Word16) 1 +#define MAX_SFM_LEN_FX 96 +#define MAX_P_ATT_FX (Word16) 40 /* Maximum number of pulses for gain attenuation factor */ +#define MAX_PHG_FX (Word16) 10 /* Q0, Maximum number of pulses for which to apply pulse height dependent gain */ +#define PHG_START_FX (Word16) 3277 /* Q15, 0.1f */ +#define PHG_DELTA_FX (Word16) 2621 /* Q15, ((PHG_END-PHG_START)/MAX_PHG) */ +#define ENV_ADJ_START_FX (Word16) 6 /* Q0, Number of consecutive bands for which the attenuation is maximum */ +#define ENV_ADJ_INV_INCL_FX (Word16) 6554 /* Q15, 1/5.0f, Inverse inclination for mapping between attenuation region width and attenuation limit */ + +#define INV_HVQ_THRES_BIN_24k 9362 /* 1/224 in Q21 */ +#define INV_HVQ_THRES_BIN_32k 6554 /* 1/320 in Q21 */ +#define INV_BANDS_PER_SUBFRAMES 14564 /* 1/9 in Q17 */ +#define NUM_SUBFRAMES 4 +#define BANDS_PER_SUBFRAMES 9 +#define ENERGY_TH_NUM_SUBFRAMES 1638400L /* 400 in Q12 */ +#define INV_SFM_N_ENV_STAB 19418 /* 1/27 in Q19 */ +#define ENERGY_TH_FX 819200L /* 100 in Q13 */ +#define ENERGY_LT_BETA_FX 30474 /* 0.93 in Q15 - Smoothing factor for long-term energy measure */ +#define ENERGY_LT_BETA_1_FX 2294 /* 0.07 i Q15 - (1 - ENERGY_LT_BETA_FX) */ +#define INV_DELTA_TH 13107 /* 1/5 in Q16 - Inverse Delta energy threshold for transient detection for envelope stability */ + +#define ONE_OVER_HVQ_BAND_MAX_BITS_24k_FX ((Word16) 410) /* Q15, 1/80 = 0.0125 */ +#define ONE_OVER_HVQ_BAND_MAX_BITS_32k_FX ((Word16) 345) /* Q15, 1/95 = 0.010526315 */ + +#define INV_PREECHO_SMOOTH_LENP1_FX 1560 /*(32768 / (PREECHO_SMOOTH_LEN + 1.0));*/ + +#define INV_HVQ_BW 1024 /* Q15 1/32 */ + +#define ACELP_48k_BITS 960 /* Q0 - ACELP_48k / 50 */ + + +/*-------------------------------------- + * FEC_HQ_phase_ecu + *-------------------------------------*/ + +#define OFF_FRAMES_LIMIT 30 /* Hard limit the variable "time_offs" to 30 */ + +/*----------------------------------------------------------------------------------* + * FEC for HQ core + *----------------------------------------------------------------------------------*/ + + +#define MAX_SB_NB 3 + + +#define NELP_LP_ORDER 8 +#define NUM_NELP_GAINS 10 + +#define N_LEAD_NB 70 /* (N_LEAD_MDCT*(L_FRAME8k/20)) */ +#define N_ZERO_NB 45 /* (N_ZERO_MDCT*(L_FRAME8k/20)) */ +#define N_LEAD_O_NB 90 /* (20.f-N_LEAD_MDCT)*(L_FRAME8k/20) */ +#define N_ZERO_O_NB 35 /* (10.f-N_ZERO_MDCT)*(L_FRAME8k/20) */ +#define N_Z_L_NB 115 /* (N_Z_L_MDCT*(float)(L/20)) = N_ZERO_NB + N_LEAD_NB*/ +#define N_Z_L_O_NB 205 /* (N_Z_L_O_MDCT*(float)(L/20)) = N_ZERO_NB + N_LEAD_NB + N_LEAD_O_NB */ + +#define ED_THRES_12P_fx 66 +#define ED_THRES_50P_fx 326 +#define ED_THRES_90P_fx 1091 + +/*----------------------------------------------------------------------------------* + * ISF quantizer constants + *----------------------------------------------------------------------------------*/ + +/*qlpc_avq, lsf_msvq_ma*/ +#define W_MODE0 0x1333 /*60.0f/FREQ_DIV in 0Q15*/ +#define W_MODE1 0x14CD /*65.0f/FREQ_DIV in 0Q15*/ +#define W_MODE2 0x147B /*64.0f/FREQ_DIV in 0Q15*/ +#define W_MODE_ELSE 0x1429 /*60.0f/FREQ_DIV in 0Q15*/ + + +enum TRACKPOS +{ + TRACKPOS_FIXED_FIRST =0, /* Fill tracks from left */ + TRACKPOS_FIXED_EVEN =1, /* Even tracks */ + TRACKPOS_FIXED_FIRST_TWO =2, /* One track of 32 */ + TRACKPOS_FIXED_TWO =3, /* Two tracks of 32 instead of four of 16 */ + TRACKPOS_FREE_ONE =4, /* One freely moving track with extra pulse */ + TRACKPOS_FREE_THREE =5 /* Three freely moving tracks with single extra pulses */ +}; + +#define ALP_E 2 + +/* Lag window strengths */ +enum +{ + LAGW_WEAK, /* weak lag window */ + LAGW_MEDIUM, /* medium strength lag window */ + LAGW_STRONG, /* strong lag window */ + + NUM_LAGW_STRENGTHS +}; + +/* qmc_cng_common.h */ +/* codec side */ +#define SCALE_TABLE_SHIFT_FACTOR (31-23) + +/* parameter_bitmapping.h */ +#define NPARAMS_MAX 10 + +/*tns_tables.h*/ + +#define TRUE 1 +#define FALSE 0 + +#define PRED_GAIN_E 8 + +/* Flags for CLDFB intialization */ +/* Flag indicating that the states should be kept. */ +#define CLDFB_FLAG_KEEP_STATES 8 +/* Flag indicating 2.5 ms setup */ +#define CLDFB_FLAG_2_5MS_SETUP 128 + + +/* bits_alloc.h */ +#define RATE_MODE_MAX 2 /*Number of rate mode*/ +#define BANDWIDTH_MODE_MAX 2 /*Number of different bandwidth modes (NB/WB-FB)*/ + + +typedef enum SIGNAL_CLASSIFER_MODE +{ + CLASSIFIER_ACELP, + CLASSIFIER_TCX +} SIGNAL_CLASSIFIER_MODE; + + +#define NRG_CHANGE_E 8 +#define AVG_FLAT_E 8 + +#define FRAME_SIZE_NB 13 + +/* RTP Payload Header Info */ +#define ACTIVE_FRAME 0xFF +#define SID_FRAME 0xFA +#define ZERO_FRAME 0xF0 + + +/************************************************************************/ + +/************************************************************************/ +#define UNKNOWN_NOISE 0 +#define SILENCE 1 + +#define CNT0P1 1717986918 /* 0.1*2^34 */ +#define CNT0P001 1099511627 /* 0.001*2^40 */ +#define CNT0P0001 1759218604 /* 0.0001*2^44 */ + +#define CNT0P05 1717986918 /* 0.05*2^35 */ + +#define CNT1DIV28 1227133513 /* (1/28)*2^35 */ +#define CNT1DIV14 1227133513 /* (1/14)*2^34 */ +#define CNT1DIV8 1073741824 /* (1/8)*2^33 */ + +#define SP_CENTER_Q 10 +#define ITD_STABLE_RATE_Q 15 +#define SPEC_AMP_Q 14 +#define SFM_Q 15 +#define TONA_Q 14 +#define lt_bg_highf_eng_Q 16 + +/************************************************************************/ +/* TEC/TFA */ +/************************************************************************/ +#define DELAY_TEMP_ENV_BUFF_TEC 9 +#define EXT_DELAY_HI_TEMP_ENV 2 + + +/************************************************************************/ +/* CLDFB */ +/************************************************************************/ + +#define SCALE_MODULATION ( 1 ) + +#define SCALE_GAIN_ANA_10 ( 4 ) +#define SCALE_GAIN_ANA_16 ( 3 ) +#define SCALE_GAIN_ANA_20 ( 3 ) +#define SCALE_GAIN_ANA_32 ( 2 ) +#define SCALE_GAIN_ANA_40 ( 2 ) +#define SCALE_GAIN_ANA_60 ( 1 ) + +#define SCALE_GAIN_SYN (-6 ) + +#define SCALE_CLDFB_ANA_10 ( SCALE_MODULATION + SCALE_GAIN_ANA_10 ) +#define SCALE_CLDFB_ANA_16 ( SCALE_MODULATION + SCALE_GAIN_ANA_16 ) +#define SCALE_CLDFB_ANA_20 ( SCALE_MODULATION + SCALE_GAIN_ANA_20 ) +#define SCALE_CLDFB_ANA_32 ( SCALE_MODULATION + SCALE_GAIN_ANA_32 ) +#define SCALE_CLDFB_ANA_40 ( SCALE_MODULATION + SCALE_GAIN_ANA_40 ) +#define SCALE_CLDFB_ANA_60 ( SCALE_MODULATION + SCALE_GAIN_ANA_60 ) + +#define SCALE_CLDFB_SYN_10 ( SCALE_MODULATION + SCALE_GAIN_SYN ) +#define SCALE_CLDFB_SYN_16 ( SCALE_MODULATION + SCALE_GAIN_SYN ) +#define SCALE_CLDFB_SYN_20 ( SCALE_MODULATION + SCALE_GAIN_SYN ) +#define SCALE_CLDFB_SYN_32 ( SCALE_MODULATION + SCALE_GAIN_SYN ) +#define SCALE_CLDFB_SYN_40 ( SCALE_MODULATION + SCALE_GAIN_SYN ) +#define SCALE_CLDFB_SYN_60 ( SCALE_MODULATION + SCALE_GAIN_SYN ) + +/************************************************************************/ +/* FFT */ +/************************************************************************/ + +#define SCALEFACTORN2 ( 3) +#define SCALEFACTOR2 ( 2) +#define SCALEFACTOR3 ( 3) +#define SCALEFACTOR4 ( 3) +#define SCALEFACTOR5 ( 4) +#define SCALEFACTOR8 ( 4) +#define SCALEFACTOR10 ( 5) +#define SCALEFACTOR12 ( 5) +#define SCALEFACTOR15 ( 5) +#define SCALEFACTOR16 ( 5) +#define SCALEFACTOR20 ( 5) +#define SCALEFACTOR24 ( 6) +#define SCALEFACTOR30 ( 6) +#define SCALEFACTOR30_1 ( 5) +#define SCALEFACTOR30_2 ( 1) +#define SCALEFACTOR32 ( 6) +#define SCALEFACTOR32_1 ( 5) +#define SCALEFACTOR32_2 ( 1) +#define SCALEFACTOR40 ( 7) +#define SCALEFACTOR60 ( 7) +#define SCALEFACTOR64 ( 7) +#define SCALEFACTOR80 ( 8) +#define SCALEFACTOR100 (10) +#define SCALEFACTOR120 ( 8) +#define SCALEFACTOR128 ( 8) +#define SCALEFACTOR160 ( 8) +#define SCALEFACTOR192 (10) +#define SCALEFACTOR200 (10) +#define SCALEFACTOR240 ( 9) +#define SCALEFACTOR256 ( 9) +#define SCALEFACTOR320 (10) +#define SCALEFACTOR400 (10) +#define SCALEFACTOR480 (11) +#define SCALEFACTOR600 (10) + +#define BASOP_CFFT_MAX_LENGTH 600 + +enum +{ + PRIMARY_2800, + PRIMARY_7200, + PRIMARY_8000, + PRIMARY_9600, + PRIMARY_13200, + PRIMARY_16400, + PRIMARY_24400, + PRIMARY_32000, + PRIMARY_48000, + PRIMARY_64000, + PRIMARY_96000, + PRIMARY_128000, + PRIMARY_SID, + PRIMARY_FUT1, + SPEECH_LOST, + NO_DATA_TYPE +}; + +enum +{ + AMRWB_IO_6600, + AMRWB_IO_8850, + AMRWB_IO_1265, + AMRWB_IO_1425, + AMRWB_IO_1585, + AMRWB_IO_1825, + AMRWB_IO_1985, + AMRWB_IO_2305, + AMRWB_IO_2385, + AMRWB_IO_SID + /*, AMRWB_IO_FUT1, + AMRWB_IO_FUT2, + AMRWB_IO_FUT3, + AMRWB_IO_FUT4, + SPEECH_LOST, + NO_DATA_TYPE */ +}; + +enum +{ + G192, + MIME + , VOIP_G192_RTP + , VOIP_RTPDUMP +}; + +#endif /* CNST_FX_H */ diff --git a/lib_com/codec_tcx_common.c b/lib_com/codec_tcx_common.c new file mode 100644 index 0000000..5f5f1db --- /dev/null +++ b/lib_com/codec_tcx_common.c @@ -0,0 +1,288 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "prot_fx.h" +#include "options.h" + +#include "stl.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "rom_basop_util.h" +#define inv_int InvIntTable + + + +Word16 tcxGetNoiseFillingTilt(Word16 A[], Word16 lpcorder, Word16 L_frame, Word16 mode, Word16 *noiseTiltFactor) +{ + Word16 firstLine; + Word32 tmp; + Word16 As[M+1]; + + + IF (mode != 0) + { + firstLine = idiv1616U(L_frame, 6); + *noiseTiltFactor = 18432/*0.5625f Q15*/; + move16(); + } + ELSE + { + firstLine = shr(L_frame, 3); + + Copy_Scale_sig( A, As, lpcorder+1, sub(norm_s(A[0]),2) ); + tmp = get_gain(As+1, As, lpcorder); + BASOP_SATURATE_WARNING_OFF; + *noiseTiltFactor = add(round_fx(L_shl(tmp, 15)), 3072/*0.09375f Q15*/); + move16(); + BASOP_SATURATE_WARNING_ON; + } + + + return firstLine; +} + + +void tcxFormantEnhancement( + Word16 xn_buf[], + Word16 gainlpc[], Word16 gainlpc_e[], + Word32 spectrum[], Word16 *spectrum_e, + Word16 L_frame, + Word16 L_frameTCX +) +{ + Word16 i, j, k, l, n; + Word16 fac, fac0, fac1, fac_e, d, tmp; + Word16 xn_buf_e, xn_one, m, e; + + + k = shr(L_frame, 6); /* FDNS_NPTS = 64 */ + l = 0; + move16(); + + /* get exponent */ + xn_buf_e = 0; + move16(); + FOR (i = 0; i < FDNS_NPTS; i++) + { + xn_buf_e = s_max(xn_buf_e, gainlpc_e[i]); + } + xn_buf_e = shr(add(xn_buf_e, 1), 1); /* max exponent after sqrt */ + xn_one = shr(0x4000, sub(xn_buf_e, 1)); /* 1.0 scaled to xn_buf_e */ + + /* Formant enhancement via square root of the LPC gains */ + e = gainlpc_e[0]; + move16(); + m = Sqrt16(gainlpc[0], &e); + xn_buf[0] = shl(m, sub(e, xn_buf_e)); + move16(); + + e = gainlpc_e[1]; + move16(); + m = Sqrt16(gainlpc[1], &e); + xn_buf[1] = shl(m, sub(e, xn_buf_e)); + move16(); + + fac0 = s_min(xn_buf[0], xn_buf[1]); + fac_e = xn_buf_e; + move16(); + fac0 = Inv16(fac0, &fac_e); + + FOR (i = 1; i < FDNS_NPTS-1; i++) + { + e = gainlpc_e[i+1]; + move16(); + m = Sqrt16(gainlpc[i+1], &e); + xn_buf[i+1] = shl(m, sub(e, xn_buf_e)); + move16(); + + test(); + IF ((LE_16(xn_buf[i-1], xn_buf[i]))&&(LE_16(xn_buf[i+1],xn_buf[i]))) + { + m = s_max(xn_buf[i-1], xn_buf[i+1]); + e = xn_buf_e; + move16(); + m = Inv16(m, &e); + + fac1 = m; + move16(); + tmp = sub(e, fac_e); + + if (tmp > 0) fac0 = shr(fac0, tmp); + if (tmp < 0) fac1 = shl(fac1, tmp); + + if (tmp > 0) + { + fac_e = e; + move16(); + } + + d = sub(fac1, fac0); + n = sub(i, l); + assert(n <= 64); + + xn_buf[l] = xn_one; + move16(); + FOR (j = 1; j < n; j++) + { + fac = add(fac0, mult(d, extract_l(L_mult0(j, inv_int[n])))); + BASOP_SATURATE_WARNING_OFF; + xn_buf[l+j] = s_min(xn_one, shl(mult(xn_buf[l+j], fac), fac_e)); + move16(); + BASOP_SATURATE_WARNING_ON; + } + + l = i; + move16(); + + fac0 = m; + move16(); + fac_e = e; + move16(); + } + } + /* i = FDNS_NPTS - 1; Completing changes to gains */ + m = s_min(xn_buf[i-1], xn_buf[i]); + e = xn_buf_e; + move16(); + m = Inv16(m, &e); + + fac1 = m; + move16(); + tmp = sub(e, fac_e); + + if (tmp > 0) fac0 = shr(fac0, tmp); + if (tmp < 0) fac1 = shl(fac1, tmp); + + if (tmp > 0) + { + fac_e = e; + move16(); + } + + d = sub(fac1, fac0); + n = sub(i, l); + assert(n <= 64); + + xn_buf[l] = xn_one; + move16(); + FOR (j = 1; j < n; j++) + { + fac = add(fac0, mult(d, extract_l(L_mult0(j, inv_int[n])))); + BASOP_SATURATE_WARNING_OFF; + xn_buf[l+j] = s_min(xn_one, shl(mult(xn_buf[l+j], fac), fac_e)); + move16(); + BASOP_SATURATE_WARNING_ON; + } + + xn_buf[i] = xn_one; + move16(); + + /* Application of changed gains onto decoded MDCT lines */ + FOR (i = 0; i < L_frame; i += k) + { + FOR (l = 0; l < k; l++) + { + *spectrum = Mpy_32_16_1(*spectrum, *xn_buf); + move32(); + spectrum++; + } + xn_buf++; + } + + tmp = sub(L_frameTCX, L_frame); + FOR (i = 0; i < tmp; i++) + { + spectrum[i] = L_shr(spectrum[i], xn_buf_e); + move32(); + } + *spectrum_e = add(*spectrum_e, xn_buf_e); + move16(); + +} + +void tcxInvertWindowGrouping(TCX_config *tcx_cfg, + Word32 xn_buf[], + Word32 spectrum[], + Word16 L_frame, + Word8 fUseTns, + Word16 last_core, + Word16 index, + Word16 frame_cnt, + Word16 bfi) +{ + Word16 i, L_win, L_spec; + Word32 *p; + + + L_win = shr(L_frame, 1); + L_spec = tcx_cfg->tnsConfig[0][0].iFilterBorders[0]; + move16(); + + test(); + test(); + if ((frame_cnt != 0) && (bfi == 0) && (last_core != ACELP_CORE)) /* fix sub-window overlap */ + { + tcx_cfg->tcx_last_overlap_mode = tcx_cfg->tcx_curr_overlap_mode; + move16(); + } + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF (((bfi==0) &&((tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) || + ((tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP) && (frame_cnt == 0) && (index == 0)))) + || + ((bfi!=0) &&((tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) && + !(tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP)))) + { + /* ungroup sub-windows: deinterleave MDCT bins into separate windows */ + p = xn_buf; + FOR (i = 1; i < L_win; i += 2) + { + *p++ = spectrum[i]; + move32(); + } + + p = spectrum; + FOR (i = 0; i < L_frame; i += 2) + { + *p++ = spectrum[i]; + move32(); + } + + p = spectrum + L_frame - 1; + FOR (i = sub(L_frame, 1); i > L_win; i -= 2) + { + *p-- = spectrum[i]; + move32(); + } + Copy32(xn_buf, spectrum + L_win, shr(L_win, 1)); + + test(); + test(); + IF ((tcx_cfg->fIsTNSAllowed != 0) && (bfi == 0) && (fUseTns != 0)) + { + /* rearrange LF sub-window lines prior to TNS synthesis filtering */ + IF (LT_16(L_spec, L_frame)) + { + Copy32(spectrum+8, spectrum+16, sub(shr(L_spec,1),8)); + Copy32(spectrum+L_frame/2, spectrum+8, 8); + Copy32(spectrum+L_frame/2+8, spectrum+L_spec/2+8, sub(shr(L_spec,1),8)); + } + ELSE + { + Copy32(spectrum+L_win, xn_buf, 8); + Copy32(spectrum+8, spectrum+16, sub(L_win, 8)); + Copy32(xn_buf, spectrum+8, 8); + } + } + } + +} + + diff --git a/lib_com/core_com_config_fx.c b/lib_com/core_com_config_fx.c new file mode 100644 index 0000000..a287157 --- /dev/null +++ b/lib_com/core_com_config_fx.c @@ -0,0 +1,471 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include + +#include "options.h" +#include "stl.h" +#include "basop_util.h" +#include "prot_fx.h" +#include "rom_com_fx.h" + + +Word8 getTcxonly(const Word32 bitrate) +{ + + Word8 tcxonly; + + tcxonly = 0; + move16(); + if( GT_32(bitrate,32000)) + { + tcxonly = 1; + move16(); + } + + return tcxonly; +} + +Word8 getCtxHm(const Word32 bitrate, const Word16 rf_flag) +{ + + Word8 ctx_hm; + + ctx_hm = 0; + move16(); + test(); + if( (bitrate > LPC_SHAPED_ARI_MAX_RATE) && (bitrate <= 64000) && !rf_flag) + { + + ctx_hm = 1; + move16(); + } + + + return ctx_hm; +} + + +Word8 getResq(const Word32 bitrate) +{ + + Word8 resq; + + resq = 0; + move16(); + if (LE_32(bitrate,64000)) + { + resq = 1; + move16(); + } + + return resq; +} + + +Word8 getTnsAllowed(const Word32 bitrate + ,const Word16 igf + ) +{ + Word8 tnsAllowed; + + tnsAllowed = 0; + move16(); + IF ( igf != 0 ) + { + if( GT_32(bitrate, HQ_16k40)) + { + tnsAllowed = 1; + move16(); + } + } + ELSE + { + if( GT_32(bitrate, HQ_32k)) + { + tnsAllowed = 1; + move16(); + } + } + + return tnsAllowed; +} + + +Word8 getRestrictedMode(const Word32 bitrate, const Word16 Opt_AMR_WB) +{ + + Word8 restrictedMode; + + restrictedMode = 3; + move16(); + + test(); + IF ( (Opt_AMR_WB == 0) && (GT_32(bitrate,32000))) + { + restrictedMode = 6; + move16(); + } + ELSE IF( Opt_AMR_WB ) + { + restrictedMode = 1; + move16(); + } + + return restrictedMode; +} + + +Word16 sr2fscale(const Word32 sr) +{ + Word16 fscale; + + SWITCH(sr) + { + case 8000: + fscale = (FSCALE_DENOM*8000)/12800; + move16(); + BREAK; + + case 12800: + fscale = FSCALE_DENOM; + move16(); + BREAK; + + case 16000: + fscale = (FSCALE_DENOM*16000)/12800; + move16(); + BREAK; + + case 25600: + fscale = (FSCALE_DENOM*25600)/12800; + move16(); + BREAK; + + case 32000: + fscale = (FSCALE_DENOM*32000)/12800; + move16(); + BREAK; + + case 48000: + fscale = (FSCALE_DENOM*48000)/12800; + move16(); + BREAK; + + default: + assert(0); + fscale = 0; /* just to avoid compiler warning */ + BREAK; + } + return fscale; +} + +Word32 getCoreSamplerateMode2(const Word32 bitrate, const Word16 bandwidth, const Word16 rf_mode) +{ + + Word32 sr_core; + sr_core = -1; /* to suppress MSVC warning */ move32(); + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + + IF( EQ_32( bandwidth,NB)) + { + sr_core = 12800; + move32(); + } + + ELSE IF ( L_and(EQ_32(bandwidth,WB),LT_32(bitrate,13200))|| + L_and(EQ_32(bandwidth,SWB), LE_32(bitrate,13200)) || EQ_16(rf_mode,1) ) + + { + sr_core = 12800; + move32(); + } + ELSE IF (EQ_32(bandwidth,WB)||((LE_32(bitrate,32000))&&((EQ_32(bandwidth,SWB))||(EQ_32(bandwidth,FB))))) + { + sr_core = 16000; + move32(); + } + ELSE IF ( ((EQ_32(bandwidth,SWB))||(EQ_32(bandwidth,FB)))&&(LE_32(bitrate,64000))) + { + sr_core = 25600; + move32(); + } + ELSE IF (EQ_32(bandwidth,SWB)||EQ_32(bandwidth,FB)) + { + sr_core = 32000; + move32(); + } + ELSE + { + assert(0); + } + + return sr_core; +} + +Word16 getTcxBandwidth(const Word16 bandwidth) +{ + + Word16 tcxBandwidth; + + tcxBandwidth = 16384/*0.5f Q15*/; + move16(); + if(EQ_16(bandwidth, NB)) + { + tcxBandwidth = 10240/*0.3125f Q15*/; + move16(); + + } + + return tcxBandwidth; +} + + +Word8 getIgfPresent( + const Word32 bitrate, + const Word16 bandwidth + ,const Word16 rf_mode +) +{ + Word8 igfPresent; + + igfPresent = 0; + move16(); + + test(); + test(); + if( (EQ_16(bandwidth, SWB))&&(GE_32(bitrate,ACELP_9k60))&&(LT_32(bitrate,HQ_64k))) + { + igfPresent = 1; + move16(); + } + + test(); + if( EQ_16(bandwidth, FB)&&(GE_32(bitrate,ACELP_16k40))) + { + igfPresent = 1; + move16(); + } + + test(); + if( (EQ_16(bandwidth, WB))&&(EQ_32(bitrate,ACELP_9k60))) + { + igfPresent = 1; + move16(); + } + + test(); + test(); + test(); + if( ((EQ_16(bandwidth, WB))||(EQ_16(bandwidth,SWB)))&&(EQ_16(rf_mode,1))&&(EQ_32(bitrate,ACELP_13k20))) + { + igfPresent = 1; + move16(); + } + + return igfPresent; +} + + +Word8 getCnaPresent( + const Word32 bitrate, + const Word16 bandwidth +) +{ + Word8 flag_cna = 0; + + flag_cna = 0; + move16(); + test(); + if( EQ_16(bandwidth, NB)&&(LE_32(bitrate,ACELP_13k20))) + { + flag_cna = 1; + move16(); + } + + test(); + if( (EQ_16(bandwidth, WB))&&(LE_32(bitrate,ACELP_13k20))) + { + flag_cna = 1; + move16(); + } + + test(); + if( (EQ_16(bandwidth, SWB))&&(LE_32(bitrate,ACELP_13k20))) + { + flag_cna = 1; + move16(); + } + + return flag_cna; +} + +Word8 getTcxLtp(const Word32 sr_core) +{ + + Word8 tcxltp = 0; + + tcxltp = 0; + move16(); + test(); + if ( (LE_32(sr_core, 25600))) + { + tcxltp = 1; + move16(); + } + + return tcxltp; +} + + +Word16 initPitchLagParameters( + const Word32 sr_core, + Word16 *pit_min, + Word16 *pit_fr1, + Word16 *pit_fr1b, + Word16 *pit_fr2, + Word16 *pit_max +) +{ + + Word16 pit_res_max; + + IF (EQ_32(sr_core, 12800)) + { + + *pit_min = PIT_MIN_12k8; + move16(); + *pit_max = PIT_MAX_12k8; + move16(); + *pit_fr2 = PIT_FR2_12k8; + move16(); + *pit_fr1 = PIT_FR1_12k8; + move16(); + *pit_fr1b = PIT_FR1_8b_12k8; + move16(); + pit_res_max = 4; + move16(); + + } + ELSE IF (EQ_32(sr_core, 16000)) + { + + *pit_min = PIT_MIN_16k; + move16(); + *pit_max = PIT_MAX_16k; + move16(); + *pit_fr2 = PIT_FR2_16k; + move16(); + *pit_fr1 = PIT_FR1_16k; + move16(); + *pit_fr1b = PIT_FR1_8b_16k; + move16(); + pit_res_max = 6; + move16(); + + } + ELSE IF (EQ_32(sr_core, 25600)) + { + + *pit_min = PIT_MIN_25k6; + move16(); + *pit_max = PIT_MAX_25k6; + move16(); + *pit_fr2 = PIT_FR2_25k6; + move16(); + *pit_fr1 = PIT_FR1_25k6; + move16(); + *pit_fr1b = PIT_FR1_8b_25k6; + move16(); + pit_res_max = 4; + move16(); + } + ELSE /* sr_core==32000 */ + { + + *pit_min = PIT_MIN_32k; + move16(); + *pit_max = PIT_MAX_32k; + move16(); + *pit_fr2 = PIT_FR2_32k; + move16(); + *pit_fr1 = PIT_FR1_32k; + move16(); + *pit_fr1b = PIT_FR1_8b_32k; + move16(); + pit_res_max = 6; + move16(); + + } + + return pit_res_max; +} + +Word16 getNumTcxCodedLines(const Word16 bwidth) +{ + + Word16 tcx_coded_lines; + + tcx_coded_lines = 0; + move16(); + + if(EQ_16(bwidth, NB)) + { + tcx_coded_lines = 160; + move16(); + } + + if(EQ_16(bwidth, WB)) + { + tcx_coded_lines = 320; + move16(); + } + + if(EQ_16(bwidth, SWB)) + { + tcx_coded_lines = 640; + move16(); + } + + if(EQ_16(bwidth, FB)) + { + tcx_coded_lines = 960; + move16(); + } + + return tcx_coded_lines; +} + +Word16 getTcxLpcShapedAri( + const Word32 total_brate, + const Word16 bwidth + ,const Word16 rf_mode +) +{ + Word16 tcx_lpc_shaped_ari = 0; + move16(); + + (void) bwidth; + + test(); + if( (LE_32(total_brate, LPC_SHAPED_ARI_MAX_RATE))||rf_mode) + { + tcx_lpc_shaped_ari = 1; + move16(); + } + + + return tcx_lpc_shaped_ari; +} diff --git a/lib_com/deemph_fx.c b/lib_com/deemph_fx.c new file mode 100644 index 0000000..56e32fc --- /dev/null +++ b/lib_com/deemph_fx.c @@ -0,0 +1,136 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "basop_util.h" + +/*========================================================================*/ +/* FUNCTION : deemph_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : Deemphasis: filtering through 1/(1-mu z^-1) */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) mu : deemphasis factor Q15 */ +/* _ (Word16) L : vector size */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16*) signal : signal Q_syn2-1 */ +/* _ (Word16*) mem : memory (y[-1]) Q_syn2-1 */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ +void deemph_fx( + Word16 *signal, /* i/o: signal Qx */ + const Word16 mu, /* i : deemphasis factor Q15 */ + const Word16 L, /* i : vector size Q0 */ + Word16 *mem /* i/o: memory (y[-1]) Qx */ +) +{ + Word16 i; + Word32 L_tmp; + + L_tmp = L_deposit_h(signal[0]); + L_tmp = L_mac(L_tmp, *mem, mu); + signal[0] = round_fx(L_tmp); + + FOR (i = 1; i < L; i++) + { + L_tmp = L_deposit_h(signal[i]); + L_tmp = L_mac(L_tmp, signal[i - 1], mu); + signal[i] = round_fx(L_tmp); + } + + *mem = signal[L - 1]; + move16(); +} + +/*-------------------------------------------------------------------* + * Deeemph2 : + * + * Deemphasis: filtering through 1/(1-mu z^-1) + * Output divided by 2 + *-------------------------------------------------------------------*/ +void Deemph2( + Word16 x[], /* i/o: input signal overwritten by the output Qx/Qx-1 */ + const Word16 mu, /* i : deemphasis factor Q15 */ + const Word16 L, /* i : vector size Q0 */ + Word16 *mem /* i/o: memory (y[-1]) Qx-1 */ +) +{ + Word16 i; + Word32 L_tmp; + + /* saturation can occur in L_mac() */ + + L_tmp = L_mult(x[0], 16384); + x[0] = mac_r(L_tmp, *mem, mu); + move16(); + + FOR (i = 1; i < L; i++) + { + L_tmp = L_mult(x[i], 16384); + x[i] = mac_r(L_tmp, x[i - 1], mu); + move16(); + } + + *mem = x[L - 1]; + move16(); +} + + +/* + * E_UTIL_deemph2 + * + * Parameters: + * shift I: scale output + * x I/O: signal Qx/Qx-shift + * mu I: deemphasis factor Qx + * L I: vector size + * mem I/O: memory (signal[-1]) Qx + * + * Function: + * Filtering through 1/(1-mu z^-1) + * Signal is divided by 2. + * + * Returns: + * void + */ +void E_UTIL_deemph2(Word16 shift, Word16 *x, const Word16 mu, const Word16 L, Word16 *mem) +{ + Word16 i; + Word32 L_tmp; + + /* signal[0] = signal[0] + mu * (*mem); */ + L_tmp = L_deposit_h(*mem); + IF(shift >= 0) + { + shift = shr(-32768, shift); + FOR (i = 0; i < L; i++) + { + L_tmp = L_msu(Mpy_32_16_1(L_tmp, mu), x[i],shift); + x[i] = round_fx(L_tmp); + } + + } + ELSE + { + FOR (i = 0; i < L; i++) + { + L_tmp = L_msu(Mpy_32_16_1(L_tmp, mu), shr(x[i],shift),-32768); + x[i] = round_fx(L_tmp); + } + } + + *mem = x[L - 1]; + move16(); + + return; +} diff --git a/lib_com/delay_comp.c b/lib_com/delay_comp.c new file mode 100644 index 0000000..f67b752 --- /dev/null +++ b/lib_com/delay_comp.c @@ -0,0 +1,43 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "stl.h" +#include "prot_fx.h" + + +/*-------------------------------------------------------------------------- +* get_delay_fx() +* +* Function returns various types of delays in the codec in ms. +*--------------------------------------------------------------------------*/ + +Word32 get_delay_fx( /* o : delay value in ms */ + const Word16 what_delay, /* i : what delay? (ENC or DEC) */ + const Word32 io_fs /* i : input/output sampling frequency */ +) +{ + Word32 delay = 0; + + IF( EQ_16(what_delay,ENC)) + { + delay = (DELAY_FIR_RESAMPL_NS + ACELP_LOOK_NS); + move32(); + } + ELSE + { + IF( EQ_32(io_fs,8000)) + { + delay = DELAY_CLDFB_NS; + move32(); + } + ELSE + { + delay = DELAY_BWE_TOTAL_NS; + move32(); + } + } + + return delay; +} diff --git a/lib_com/disclaimer.c b/lib_com/disclaimer.c new file mode 100644 index 0000000..52f2fc2 --- /dev/null +++ b/lib_com/disclaimer.c @@ -0,0 +1,19 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "disclaimer.h" +#include "options.h" +#include "stl.h" + +/* WMC_TOOL_SKIP_FILE */ + +int print_disclaimer(FILE *fPtr) +{ + + fprintf(fPtr, "\n===========================================================================\n"); + fprintf(fPtr, " EVS Codec 3GPP TS26.452 August 12, 2021. \n"); + fprintf(fPtr, " Version 16.3.0\n"); + fprintf(fPtr, "===========================================================================\n\n\n"); + return 0; +} diff --git a/lib_com/disclaimer.h b/lib_com/disclaimer.h new file mode 100644 index 0000000..cb41b93 --- /dev/null +++ b/lib_com/disclaimer.h @@ -0,0 +1,15 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#ifndef __INCLUDED_DISCLAIMER_H +#define __INCLUDED_DISCLAIMER_H + +#include + +int print_disclaimer(FILE *fPtr); + + + + +#endif /* __INCLUDED_DISCLAIMER_H */ diff --git a/lib_com/dlpc_bfi.c b/lib_com/dlpc_bfi.c new file mode 100644 index 0000000..4271e1c --- /dev/null +++ b/lib_com/dlpc_bfi.c @@ -0,0 +1,55 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +/* Header files */ +#include +#include +#include +#include "prot_fx.h" +#include "stl.h" +#include "prot_fx.h" + +void dlpc_bfi( + const Word16 L_frame, + Word16 *lsf_q, /* o : quantized LSFs */ + const Word16 *lsfold, /* i : past quantized LSF */ + const Word16 last_good, /* i : last good received frame */ + const Word16 nbLostCmpt, /* i : counter of consecutive bad frames */ + Word16 mem_MA[], /* i/o: quantizer memory for MA model */ + Word16 mem_AR[], /* i/o: quantizer memory for AR model */ + Word16 *stab_fac, /* i : LSF stability factor */ + Word16 *lsf_adaptive_mean,/* i : LSF adaptive mean, updated when BFI==0 */ + Word16 numlpc, /* i : Number of division per superframe */ + Word16 lsf_cng[], + Word8 plcBackgroundNoiseUpdated, + Word16 *lsf_q_cng, /* o : quantized LSFs */ + Word16 *old_lsf_q_cng, /* o : old quantized LSFs for background noise */ + const Word16* lsfBase, /* i : base for differential LSF coding */ + Word8 tcxonly +) +{ + + lsf_dec_bfi( + MODE2, + &lsf_q[0], lsfold, lsf_adaptive_mean, lsfBase, mem_MA, mem_AR, *stab_fac, + 0, L_frame, last_good, nbLostCmpt, + plcBackgroundNoiseUpdated, lsf_q_cng, lsf_cng, old_lsf_q_cng, 0, 0, tcxonly + ,0 + + ); + IF ( EQ_16(numlpc,2)) + { + /* Decode the second LPC */ + lsf_dec_bfi( + MODE2, + &lsf_q[M], &lsf_q[0], lsf_adaptive_mean, lsfBase, mem_MA, mem_AR, *stab_fac, + 0, L_frame, last_good, nbLostCmpt+1, + plcBackgroundNoiseUpdated, lsf_q_cng, lsf_cng, old_lsf_q_cng, 0, 0, tcxonly + ,0 + ); + } + /**/ /*No local variabvles defined*/ +} + diff --git a/lib_com/edct_fx.c b/lib_com/edct_fx.c new file mode 100644 index 0000000..f45a54f --- /dev/null +++ b/lib_com/edct_fx.c @@ -0,0 +1,424 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + + +#include "math_32.h" + +static Word16 const * get_edct_table(Word16 length, Word16 *q) +{ + Word16 const * edct_table = NULL; + SWITCH (length) + { + case 1200: + edct_table = edct_table_600_fx; + move16(); + *q = add(*q, 2); + BREAK; + case 960 : + edct_table = edct_table_480_fx; + move16(); + BREAK; + case 640 : + edct_table = edct_table_320_fx; + move16(); + BREAK; + case 320 : + edct_table = edct_table_160_fx; + move16(); + BREAK; + case 256 : + edct_table = edct_table_128_fx; + move16(); + BREAK; + case 240 : + edct_table = edct_table_120_fx; + move16(); + BREAK; + case 200 : + edct_table = edct_table_100_fx; + move16(); + BREAK; + case 160 : + edct_table = edct_table_80_fx ; + move16(); + BREAK; + case 40 : + edct_table = edct_table_20_fx ; + move16(); + BREAK; + case 800 : + edct_table = edct_table_400_fx; + move16(); + *q = add(*q, 2); + BREAK; + case 512 : + edct_table = edct_table_256_fx; + move16(); + BREAK; + case 480 : + edct_table = edct_table_240_fx; + move16(); + BREAK; + case 400 : + edct_table = edct_table_200_fx; + move16(); + BREAK; + case 128 : + edct_table = edct_table_64_fx ; + move16(); + BREAK; + case 80 : + edct_table = edct_table_40_fx ; + move16(); + BREAK; + default: + BREAK; + } + return edct_table; +} + +/*-------------------------------------------------------------------------* + * FUNCTION : edct_fx() + * + * PURPOSE : DCT transform + * + * INPUT ARGUMENTS : + * _ (Word16) length : length + * _ (Word16*) x : input signal Qx + * _ (Word16*) edct_table_128_fx : edct table Q16 + * + * OUTPUT ARGUMENTS : + * _ (Word16[]) y : output transform Qx + *-------------------------------------------------------------------------*/ +void edct_fx( + const Word32 *x, /* i : input signal Qq */ + Word32 *y, /* o : output transform Qq */ + Word16 length, /* i : length */ + Word16 *q /* i : Q value of input signal */ +) +{ + Word16 i; + Word32 re; + Word32 im; + const Word16 *edct_table = 0; /*Q16 */ + Word32 complex_buf[2*(L_FRAME48k/2+240)]; + Word32 L_tmp; + Word16 tmp; + Word16 len1; + + edct_table = get_edct_table(length, q); + len1 = shr(length, 1); + /* Twiddling and Pre-rotate */ + FOR (i = 0; i < len1; i++) + { + L_tmp = Mult_32_16(x[2*i], edct_table[i]); /*Q(q+1) */ + complex_buf[2*i] = Madd_32_16(L_tmp, x[length-1-2*i], edct_table[len1-1-i]); /*Q(q+1) */ move32(); + + L_tmp = Mult_32_16(x[length-1-2*i], edct_table[i]); /*Q(q+1) */ + + complex_buf[2*i+1] = Msub_32_16(L_tmp, x[2*i], edct_table[len1-1-i]); /*Q(q+1) */ move32(); + } + + *q = sub(15, *q); + BASOP_cfft((cmplx *)complex_buf, len1, q, y); + + tmp = div_s(1, length); /*Q15 */ + tmp = round_fx(L_shl(L_mult(tmp, 19302), 2)); /*Q15 */ + FOR (i = 0; i < len1; i++) + { + re = Msub_32_16(complex_buf[2*i], complex_buf[2*i+1], tmp); + im = Madd_32_16(complex_buf[2*i+1], complex_buf[2*i], tmp); + y[2 * i] = L_add(Mult_32_16(re, edct_table[i]), Mult_32_16(im, edct_table[len1 - 1 - i])); + move32(); + y[length - 1 - 2 * i] = L_sub(Mult_32_16(re, edct_table[len1 - 1 - i]), Mult_32_16(im, edct_table[i])); + move32(); + } /*Q(q-2) */ + + *q = sub(15+2, *q); + return; +} + +/*-------------------------------------------------------------------------* + * FUNCTION : edst_fx() + * + * PURPOSE : DST_IV transform + * + * INPUT ARGUMENTS : + * _ (Word16) length : length + * _ (Word16*) x : input signal Qx + * _ (Word16*) edct_table_128_fx : edct table Q16 + * + * OUTPUT ARGUMENTS : + * _ (Word16[]) y : output transform Qx + *-------------------------------------------------------------------------*/ +void edst_fx( + const Word32 *x, /* i : input signal Qq */ + Word32 *y, /* o : output transform Qq */ + Word16 length, /* i : length */ + Word16 *q /* i : Q value of input signal */ +) +{ + Word16 i; + Word32 re; + Word32 im; + const Word16 *edct_table = 0; /*Q16 */ + Word32 complex_buf[2*(L_FRAME48k/2+240)]; + Word32 L_tmp; + Word16 tmp; + Word16 len1; + + edct_table = get_edct_table(length, q); + len1 = shr(length, 1); + /* Twiddling and Pre-rotate */ + FOR (i = 0; i < len1; i++) + { + L_tmp = Mult_32_16(x[length-1-2*i], edct_table[i]); + complex_buf[2*i] = Madd_32_16(L_tmp, x[2*i], edct_table[len1-1-i]); + move32(); + + L_tmp = Mult_32_16(x[2*i], edct_table[i]); + complex_buf[2*i+1] = Msub_32_16(L_tmp, x[length-1-2*i], edct_table[len1-1-i]); + move32(); + } + + *q = sub(15, *q); + BASOP_cfft((cmplx *)complex_buf, len1, q, y); + + tmp = div_s(1, length); /*Q15 */ + tmp = round_fx(L_shl(L_mult(tmp, 19302), 2)); /*Q15 */ + FOR (i = 0; i < len1; i++) + { + re = Msub_32_16(complex_buf[2*i], complex_buf[2*i+1], tmp); + im = Madd_32_16(complex_buf[2*i+1], complex_buf[2*i], tmp); + y[2 * i] = L_add(Mult_32_16(re, edct_table[i]), Mult_32_16(im, edct_table[len1 - 1 - i])); + move32(); + y[length - 1 - 2 * i] = L_sub(Mult_32_16(im, edct_table[i]), Mult_32_16(re, edct_table[len1 - 1 - i])); + move32(); + } /*Q(q) */ + + *q = sub(15+2, *q); + + return; +} + +/*========================================================================*/ +/* FUNCTION : edct_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : DCT transform */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) length : length */ +/* _ (Word16*) x : input signal Qx */ +/* _ (Word16*) edct_table_128_fx : edct table Q15 */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) y : output transform Qx */ +/*------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ +void edct_16fx( + const Word16 *x, /* i : input signal Qx */ + Word16 *y, /* o : output transform Qx */ + Word16 length, /* i : length */ + Word16 bh /* bit-headroom */ +) +{ + Word16 i; + Word16 re[L_FRAME48k/2]; + Word16 im[L_FRAME48k/2]; + const Word16 *edct_table = 0; + Word16 re2[L_FRAME48k/2]; + Word16 im2[L_FRAME48k/2]; + + Word32 L_tmp, Lacc, Lmax; + Word16 tmp, fact; + Word16 Q_edct; + Word16 Len2, i2; + const Word16 *px, *pt; + Word16 *py; + + /*COMPLETE: some eDCT sub function are missing */ + + IF (EQ_16(length,L_FRAME32k)) + { + edct_table = &edct_table_320_16fx[0]; + move16(); + } + ELSE IF (EQ_16(length,L_FRAME)) + { + edct_table = &edct_table_128_16fx[0]; + move16(); + } + ELSE IF (EQ_16(length,L_FRAME16k)) + { + edct_table = &edct_table_160_16fx[0]; + move16(); + } + ELSE + { + } + + /* Twiddling and Pre-rotate */ + Lmax = L_deposit_l(0); + Len2 = shr(length,1); + px = x + length - 1; + pt = edct_table + Len2 - 1; + FOR (i = 0; i < Len2; i++) + { + i2 = shl(i,1); + L_tmp = L_mult(x[i2],edct_table[i]);/*Q(Qx+16) */ + + Lacc = L_mac(L_tmp,*px,*pt);/*Q(Qx+16) */ + + Lmax = L_max(Lmax, Lacc); + + L_tmp = L_mult(*px,edct_table[i]);/*Q(Qx+16) */ + Lacc = L_msu(L_tmp,x[i2],*pt);/*Q(Qx+16) */ + Lmax = L_max(Lmax, Lacc); + + px -= 2; + pt--; + } + + tmp = 31; + if( Lmax != 0 ) + { + tmp = norm_l(Lmax); + } + Q_edct = sub(tmp,bh); /*creating a bit-headroom */ + + px = x + length - 1; + pt = edct_table + Len2 - 1; + FOR (i = 0; i < Len2; i++) + { + i2 = shl(i,1); + + L_tmp = L_mult(x[i2],edct_table[i]);/*Q(Qx+16) */ + Lacc = L_mac(L_tmp,*px,*pt);/*Q(Qx+16) */ + re2[i] = round_fx(L_shl(Lacc, Q_edct)); /* Q(Qx+Q_edct) */ + + L_tmp = L_mult(*px,edct_table[i]);/*Q(Qx+16) */ + Lacc = L_msu(L_tmp,x[i2],*pt);/*Q(Qx+16) */ + im2[i] = round_fx(L_shl(Lacc, Q_edct)); /* Q(Qx+Q_edct) */ + + px -= 2; + pt--; + } + IF (EQ_16(length,L_FRAME32k)) + { + DoRTFT320_16fx(re2, im2); + } + ELSE IF (EQ_16(length,L_FRAME )) + { + DoRTFT128_16fx(re2, im2); + } + ELSE IF (EQ_16(length,L_FRAME16k)) + { + DoRTFT160_16fx(re2, im2); + } + ELSE + { + } + tmp = div_s(1,length); /*Q15 */ + L_tmp = L_mult(tmp,19302); /*Q29, (3*PI/4) in Q13 */ + fact = round_fx(L_shl(L_tmp,2)); /*Q15 */ + FOR (i = 0; i < length/2; i++) + { + tmp = mult_r(im2[i],fact); /*Q(Qx+Q_edct) */ + re[i] = sub(re2[i],tmp); /*Q(Qx+Q_edct) */ move16(); + + tmp = mult_r(re2[i],fact); /*Q(Qx+Q_edct) */ + im[i] = add(im2[i],tmp); /*Q(Qx+Q_edct) */ move16(); + } + + /* Post-rotate and obtain the output data */ + py = y + length - 1; + pt = edct_table + Len2 - 1; + FOR (i = 0; i < Len2; i++) + { + i2 = shl(i,1); + + L_tmp = L_mult(re[i],edct_table[i]);/*Q(Qx+Q_edct+16) */ + Lacc = L_mac(L_tmp,im[i],*pt);/*Q(Qx+Q_edct+16) */ + y[i2] = round_fx(L_shr(Lacc,Q_edct)); /* Q(Qx) */ + + L_tmp = L_mult(re[i],edct_table[length/2-1-i]);/*Q(Qx+Q_edct+16) */ + Lacc = L_msu(L_tmp,im[i],edct_table[i]);/*Q(Qx+Q_edct+16) */ + *py = round_fx(L_shr(Lacc,Q_edct)); /* Q(Qx) */ + + py -= 2; + pt--; + } + return; +} + + +/*-----------------------------------------------------------------* + * iedct_short_fx() + * + * Inverse EDCT for short frames + *-----------------------------------------------------------------*/ + +void iedct_short_fx( + const Word32 *in, /* i : input vector */ + Word16 *Q, /* i/o: Q value of input */ + Word32 *out, /* o : output vector */ + const Word16 segment_length /* i : length */ +) +{ + Word32 alias[MAX_SEGMENT_LENGTH]; + Word16 seg_len_div2, seg_len_div4, seg_len_3mul_div4; + Word16 i; + Word16 qtmp, tmp; + + qtmp = *Q; + move16(); + tmp = 0; + move16(); + seg_len_div2 = shr(segment_length, 1); + seg_len_div4 = shr(segment_length, 2); + seg_len_3mul_div4 = add(seg_len_div2, seg_len_div4); + + edct_fx(in, alias, seg_len_div2, Q); + FOR (i = 0; i < seg_len_div2; i++) + { + IF (alias[i] != 0) + { + tmp = 1; + move16(); + BREAK; + } + } + if (tmp == 0) + { + *Q = qtmp; + move16(); + } + FOR (i = 0; i < seg_len_div4; i++) + { + out[i] = alias[seg_len_div4 + i]; + move32(); + out[seg_len_div4 + i] = L_negate(alias[seg_len_div2 - 1 - i]); + move32(); + out[seg_len_div2 + i] = L_negate(alias[seg_len_div4 - 1 - i]); + move32(); + out[seg_len_3mul_div4 + i] = L_negate(alias[i]); + move32(); + } + + return; +} diff --git a/lib_com/enhancer_fx.c b/lib_com/enhancer_fx.c new file mode 100644 index 0000000..81b8097 --- /dev/null +++ b/lib_com/enhancer_fx.c @@ -0,0 +1,679 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" +#include "basop_util.h" + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ +#define pitch_0_9 14746 /* 0.9 in Q14 */ +#define pitch_0_6 9830 /* 0.6 in Q14 */ +#define SIZE 64 +#define SIZE2 32 +#define NUM_STAGES 5 + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ +static void phase_dispersion_fx(Word32 gain_code,Word16 gain_pit,Word16 code[],Word16 mode,struct dispMem_fx *dm_fx); +static void agc2_fx(const Word16 *sig_in,Word16 *sig_out,const Word16 l_trm); + +/*======================================================================================*/ +/* FUNCTION : enhancer_fx() */ +/*--------------------------------------------------------------------------------------*/ +/* PURPOSE : Enhancement of the excitation signal before synthesis */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word32) core_brate : decoder bitrate */ +/* _ (Word16) Opt_AMR_WB : flag indicating AMR-WB IO mode */ +/* _ (Word16) coder_type : coder type */ +/* _ (Word16) i_subfr : subframe number */ +/* _ (Word16) voice_fac : subframe voicing estimation (Q15) */ +/* _ (Word16) stab_fac : LP filter stablility measure (Q15) */ +/* _ (Word32) norm_gain_code : normalised innovative cb. gain (Q16) */ +/* _ (Word16) gain_inov : gain of the unscaled innovation (Q12) */ +/* _ (Word16) gain_pit_fx : Pitch gain (Q14) */ +/* _ (Word16) Q_exc : Q of the excitation */ +/* _ (Word16) Enc : Encoder = 1; decoder = 0 */ +/*--------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) voice_factors_fx : TBE voicing factor (Q15) */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word32*) gc_threshold : gain code threshold (Q16) */ +/* _ (Word16*[]) code : innovation (Q12) */ +/* _ (Word16*[]) exc2 : adapt. excitation/total exc (Q0) */ +/* _ (struct dispMem_fx*) dm_fx : phase dispersion algorithm memory */ +/* (a[0]->Q0,a[1]->Q16,a[2-7]->Q14) */ +/*--------------------------------------------------------------------------------------*/ + +/* _ None */ +/*--------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*======================================================================================*/ +void enhancer_fx( + const Word32 core_brate, /* i : decoder bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 coder_type, /* i : coder type */ + const Word16 i_subfr, /* i : subframe number */ + const Word16 L_frame, /* i : frame size */ + const Word16 voice_fac, /* i : subframe voicing estimation Q15 */ + const Word16 stab_fac, /* i : LP filter stablility measure Q15 */ + Word32 norm_gain_code, /* i : normalised innovative cb. gain Q16 */ + const Word16 gain_inov, /* i : gain of the unscaled innovation Q12 */ + Word32 *gc_threshold,/* i/o: gain code threshold Q16 */ + Word16 *code, /* i/o: innovation Q12 */ + Word16 *exc2, /* i/o: adapt. excitation/total exc. Q_exc*/ + const Word16 gain_pit, /* i : quantized pitch gain Q14 */ + struct dispMem_fx *dm_fx, /* i/o: phase dispersion algorithm memory */ + const Word16 Q_exc /* i : Q of the excitation */ +) +{ + Word16 tmp, fac, *pt_exc2; + Word16 i; + Word32 L_tmp; + Word16 gain_code_hi; + Word16 pit_sharp, tmp16; + Word16 excp[L_SUBFR], sc; + + pit_sharp = gain_pit; + move16(); /* to remove gcc warning */ + pt_exc2 = exc2 + i_subfr; + move16(); + + /*------------------------------------------------------------* + * Phase dispersion to enhance noise at low bit rate + *------------------------------------------------------------*/ + + i = 2; + move16(); /* no dispersion */ + IF (Opt_AMR_WB) + { + IF ( LE_32(core_brate,ACELP_6k60)) + { + i = 0; + move16(); /* high dispersion */ + } + ELSE if ( LE_32(core_brate,ACELP_8k85)) + { + i = 1; + move16(); /* low dispersion */ + } + } + ELSE IF( NE_16(coder_type,UNVOICED)) + + { + test(); + test(); + test(); + test(); + IF ( LE_32(core_brate,ACELP_7k20)) + { + i = 0; + move16(); /* high dispersion */ + } + ELSE if ( ( EQ_16(coder_type,GENERIC)||EQ_16(coder_type,TRANSITION)||EQ_16(coder_type,AUDIO)||EQ_16(coder_type,INACTIVE))&&LE_32(core_brate,ACELP_9k60)) + { + i = 1; + move16(); /* low dispersion */ + } + } + phase_dispersion_fx(norm_gain_code, gain_pit, code, i, dm_fx); + + /*------------------------------------------------------------ + * noise enhancer + * + * - Enhance excitation on noise. (modify gain of code) + * If signal is noisy and LPC filter is stable, move gain + * of code 1.5 dB toward gain of code threshold. + * This decreases by 3 dB noise energy variation. + *-----------------------------------------------------------*/ + + /* tmp = 0.5f * (1.0f - voice_fac) */ + tmp = msu_r(0x40000000, voice_fac, 16384); /*Q15 */ /* 1=unvoiced, 0=voiced */ + /* fac = stab_fac * tmp */ + fac = mult(stab_fac, tmp); /*Q15*/ + + IF (LT_32(norm_gain_code, *gc_threshold)) + { + L_tmp = Madd_32_16(norm_gain_code, norm_gain_code, 6226);/*Q16 */ + L_tmp = L_min(L_tmp, *gc_threshold);/*Q16 */ + } + ELSE + { + L_tmp = Mult_32_16(norm_gain_code, 27536);/*Q16 */ + L_tmp = L_max(L_tmp, *gc_threshold); /*Q16 */ + } + *gc_threshold = L_tmp; + move32(); /*Q16 */ + + /* gain_code = (fac * tmp) + (1.0 - fac) * gain_code ==> fac * (tmp - gain_code) + gain_code */ + L_tmp = L_sub(L_tmp, norm_gain_code); /*Q16 */ + norm_gain_code = Madd_32_16(norm_gain_code, L_tmp, fac);/*Q16 */ + + /* gain_code *= gain_inov - Inverse the normalization */ + L_tmp = Mult_32_16(norm_gain_code, gain_inov); /*Q13*/ /* gain_inov in Q12 */ + + sc = 6; + move16(); + + gain_code_hi = round_fx(L_shl(L_tmp, add(Q_exc, 3))); /* in Q_exc */ + + /*------------------------------------------------------------* + * pitch enhancer + * + * - Enhance excitation on voiced. (HP filtering of code) + * On voiced signal, filtering of code by a smooth fir HP + * filter to decrease energy of code at low frequency. + *------------------------------------------------------------*/ + test(); + IF( !Opt_AMR_WB && EQ_16(coder_type,UNVOICED)) + { + /* Copy(code, exc2, L_SUBFR) */ + FOR (i = 0; i < L_SUBFR; i++) + { + pt_exc2[i] = round_fx(L_shl(L_mult(gain_code_hi, code[i]), sc)); /*Q0 */ /* code in Q12 (Q9 for encoder) */ + } + } + ELSE + { + test(); + test(); + IF ( Opt_AMR_WB && ( EQ_32(core_brate,ACELP_8k85)||EQ_32(core_brate,ACELP_6k60))) + { + pit_sharp = shl(gain_pit, 1); /* saturation can occur here Q14 -> Q15 */ + + /* saturation takes care of "if (pit_sharp > 1.0) { pit_sharp=1.0; }" */ + IF (GT_16(pit_sharp, 16384)) + { + tmp16 = mult(pit_sharp, 8192); + FOR (i = 0; i < L_SUBFR; i++) + { + /* excp[i] = pt_exc2[i] * pit_sharp * 0.25 */ + excp[i] = mult_r(pt_exc2[i], tmp16); + move16(); + } + } + } + + IF ( EQ_16(L_frame, L_FRAME16k)) + { + /* tmp = 0.150 * (1.0 + voice_fac) */ + /* 0.30=voiced, 0=unvoiced */ + tmp = mac_r(0x10000000L, voice_fac, 4915);/*Q15 */ + } + ELSE + { + /* tmp = 0.125 * (1.0 + voice_fac) */ + /* 0.25=voiced, 0=unvoiced */ + tmp = mac_r(0x10000000L, voice_fac, 4096);/*Q15 */ + } + + /*----------------------------------------------------------------- + * Do a simple noncasual "sharpening": effectively an FIR + * filter with coefs [-tmp 1.0 -tmp] where tmp=0...0.25. + * This is applied to code and add_fxed to exc2 + *-----------------------------------------------------------------*/ + /* pt_exc2[0] += code[0] - tmp * code[1] */ + L_tmp = L_deposit_h(code[0]); /* if Enc :Q9 * Q15 -> Q25 */ + L_tmp = L_msu(L_tmp, code[1], tmp); /* Q12 * Q15 -> Q28 */ + L_tmp = L_shl(L_mult(gain_code_hi, extract_h(L_tmp)), sc); + pt_exc2[0] = msu_r(L_tmp, -32768, pt_exc2[0]); + move16();/* in Q_exc */ + + FOR (i = 1; i < L_SUBFR-1; i++) + { + /* pt_exc2[i] += code[i] - tmp * code[i-1] - tmp * code[i+1] */ + L_tmp = L_msu(-32768, code[i], -32768); + L_tmp = L_msu(L_tmp, code[i + 1], tmp); + tmp16 = msu_r(L_tmp, code[i - 1], tmp); + L_tmp = L_shl(L_mult(gain_code_hi, tmp16), sc); + pt_exc2[i] = msu_r(L_tmp, -32768, pt_exc2[i]); + move16(); /* in Q_exc */ + } + + /* pt_exc2[L_SUBFR-1] += code[L_SUBFR-1] - tmp * code[L_SUBFR-2] */ + L_tmp = L_deposit_h(code[L_SUBFR - 1]);/*Q28 */ + L_tmp = L_msu(L_tmp, code[L_SUBFR - 2], tmp);/*Q28 */ + L_tmp = L_shl(L_mult(gain_code_hi, extract_h(L_tmp)), sc); + pt_exc2[L_SUBFR - 1] = msu_r(L_tmp, -32768, pt_exc2[L_SUBFR - 1]); + move16();/* in Q_exc */ + test(); + test(); + IF ( Opt_AMR_WB && ( EQ_32(core_brate,ACELP_8k85)||EQ_32(core_brate,ACELP_6k60))) + { + IF (GT_16(pit_sharp, 16384)) + { + FOR (i = 0; i < L_SUBFR; i++) + { + /* excp[i] += pt_exc2[i] */ + excp[i] = add(excp[i], pt_exc2[i]); + move16(); + } + agc2_fx(pt_exc2, excp, L_SUBFR); + Copy(excp, pt_exc2, L_SUBFR); + } + } + } +} + +/*---------------------------------------------------------* + * Enhancement of the excitation signal before synthesis + *---------------------------------------------------------*/ + +Word16 E_UTIL_enhancer( + Word16 voice_fac, /* i : subframe voicing estimation Q15 */ + Word16 stab_fac, /* i : LP filter stability measure Q15 */ + Word32 gain_code, /* i : innovative cb. gain 15Q16 */ + Word16 gain_inov, /* i : gain of the unscaled innovation Q11 */ + Word32 *gc_threshold, /* i/o: gain code threshold 15Q16 */ + Word16 *code, /* i/o: innovation(in: Q9) code_exp */ + Word16 *exc2, /* i/o: adapt. excitation/total exc. */ + Word16 gain_pit, /* i : Quantized pitch gain 1Q14 */ + Word32 *prev_gain_code, /* i/o: previous codebook gain 15Q16 */ + Word16 prev_gain_pit[], /* i/o: previous pitch gain, size=6 1Q14 */ + Word16 *prev_state, /* i/o: Phase dispersion algorithm memory Q0 */ + Word16 coder_type, /* i : coder type */ + Word16 cdk_index, /* i : */ + Word16 L_subfr, /* i : length of subframe */ + Word16 L_frame, /* i : frame size */ + Word16 Q_new +) +{ + Word16 disp_mode, i; + Word16 tmp, fac, gain; + Word32 L_tmp; + Word16 code_exp, exc2_exp; + Word16 max_cdk_index_uv; + + move16(); + code_exp = 15-9; + exc2_exp = 15-Q_new; + gain_inov = shr(gain_inov,1); + /*-----------------------------------------------------------------* + * Phase dispersion to enhance noise at low bit rates + *-----------------------------------------------------------------*/ + + max_cdk_index_uv = 10; + move16(); + if ( EQ_16(L_frame, L_FRAME16k)) + { + max_cdk_index_uv = 14; + move16(); + } + disp_mode = 2; /* any=off */ move16(); + test(); + test(); + test(); + test(); + IF ( ( (NE_16(coder_type, VOICED))&&(LE_16(cdk_index,2)))||((EQ_16(coder_type,UNVOICED))&&(LE_16(cdk_index,max_cdk_index_uv)))) + { + disp_mode = 0; /* high */ move16(); + } + ELSE IF ( (NE_16(coder_type, VOICED))&&(LE_16(cdk_index,7))) + { + disp_mode = 1; /* low */ move16(); + } + + phase_dispersion(gain_code, gain_pit,code, &code_exp, disp_mode, prev_gain_code, prev_gain_pit, prev_state, L_subfr); + + /*------------------------------------------------------------* + * noise enhancer * + * ~~~~~~~~~~~~~~ * + * - Enhance excitation on noise. (modify gain of code) * + * If signal is noisy and LPC filter is stable, move gain * + * of code 1.5 dB toward gain of code threshold. * + * This decrease by 3 dB noise energy variation. * + *------------------------------------------------------------*/ + fac = 0; + move16(); + + /* if gain_code is computed function of energy, noise enhancer is by-passed.*/ + BASOP_SATURATE_WARNING_OFF + tmp = msu_r(1073741824l/*0.5f Q31*/, 16384/*0.5f Q15*/, voice_fac); /* 1=unvoiced, 0=voiced */ + BASOP_SATURATE_WARNING_ON + fac = mult_r(stab_fac, tmp); /* fac in Q15 */ + + L_tmp = gain_code; /* L_tmp in 15Q16 */ + move32(); + + IF (LT_32(L_tmp,*gc_threshold)) + { + L_tmp = L_shl(Mpy_32_32(L_tmp, 1277752832l/*1.19f/2.0f Q31*/),1); + L_tmp = L_min(L_tmp, *gc_threshold); + } + ELSE + { + L_tmp = Mpy_32_32(L_tmp, 1804608000l/*1.0f/1.19f Q31*/); + L_tmp = L_max(L_tmp, *gc_threshold); + } + move32(); + *gc_threshold = L_tmp; /* in 15Q16 */ + + /* gain = ( (fac * L_tmp) + (gain_code - fac*gain_code) ) * gain_inov */ + /* exponent of L_tmp: 31-16 + 15-11 */ + L_tmp = Mpy_32_16_1(L_add(Mpy_32_16_1(L_tmp, fac), L_sub(gain_code, Mpy_32_16_1(gain_code, fac))), gain_inov); + + /* exponent gain: 31-16 + 15-11 - tmp */ + tmp = norm_l(L_tmp); + + /* exponent of code: 31-16 + 15-11 - tmp + code_exp */ + move16(); + code_exp = sub(add(31-16 + 15-11, code_exp), tmp); + + L_tmp = L_shl(L_tmp, tmp); + gain = round_fx(L_tmp); + + FOR (i=0; iQ0,a[1]->Q16,a[2-7]->Q14) */ +/*--------------------------------------------------------------------------------------*/ + +/* _ None */ +/*--------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*======================================================================================*/ +static void phase_dispersion_fx( + Word32 gain_code, /* i : gain of code Q16 */ + Word16 gain_pit, /* i : gain of pitch Q14 */ + Word16 code[], /* i/o: code vector */ + Word16 mode, /* i : level, 0=hi, 1=lo, 2=off */ + struct dispMem_fx *dm_fx /* i/o: static memory (size = 8) */ +) +{ + Word16 i, j, state; + Word16 *prev_gain_pit, *prev_state; + Word32 *prev_gain_code; + Word16 *code2_real, *code2_imag; + Word16 *code_real, *code_imag; + const Word16 *h_real, *h_imag; + + Word16 code2[2 * L_SUBFR]; + + prev_state = &(dm_fx->prev_state); + prev_gain_code = &(dm_fx->prev_gain_code); + prev_gain_pit = dm_fx->prev_gain_pit; + + state = 2; + move16(); + if (LT_16(gain_pit, pitch_0_9)) + { + state = 1; + move16(); + } + + if (LT_16(gain_pit, pitch_0_6)) + { + state = 0; + move16(); + } + + FOR (i = 5; i > 0; i--) + { + prev_gain_pit[i] = prev_gain_pit[i - 1]; + move16(); + } + prev_gain_pit[0] = gain_pit; + move16(); + + IF (GT_32(L_sub(gain_code, *prev_gain_code), L_shl(*prev_gain_code, 1))) + { + state = s_min(add(state, 1), 2); + } + ELSE + { + j = 0; + move16(); + + FOR (i = 0; i < 6; i++) + { + j = sub(j, shr(sub(prev_gain_pit[i], pitch_0_6), 15)); + } + + if (GT_16(j, 2)) + { + state = 0; + move16(); + } + + if (GT_16(sub(state, *prev_state), 1)) + { + state = sub(state, 1); + } + } + + *prev_gain_code = gain_code; + move32(); + *prev_state = state; + move16(); + + /*-----------------------------------------------------------------* + * circular convolution + *-----------------------------------------------------------------*/ + + state = add(state, mode); /* level of dispersion */ + + IF (LT_16(state, 2)) + { + r_fft_fx_lc(phs_tbl_dec, SIZE, SIZE2, NUM_STAGES, code, code2, 1); + + h_real = Mid_H_phasedisp; + move16(); + if (state == 0) + { + h_real = Low_H_phasedisp; + move16(); + } + + /* FFT Coefs are in code2 */ + code2_real = code2; + move16(); + code2_imag = code2 + L_SUBFR - 1; + move16(); + + code_real = code; + move16(); + code_imag = code + L_SUBFR - 1; + move16(); + + h_imag = h_real + L_SUBFR - 1; + move16(); + + *code_real++ = mult(*code2_real++, *h_real++); + move16(); /* DC */ + + FOR (i=1; i 0 && pulses[i-1] != 0 && pulses[i+1] != 0 ) + { + adj[i] = 11796; /* Q15, 0.36f */ move16(); + } + ELSE IF ( i > 0 && ( pulses[i-1] == 0 || pulses[i+1] == 0) ) + { + adj[i] = 17695; /* Q15, 0.54f */ move16(); + } + ELSE + { + adj[i] = 23593; /* Q15, 0.72f */ move16(); + } + } + ELSE IF ( LT_16(i,last_sfm)) + { + test(); + IF ( pulses[i-1] != 0 && pulses[i+1] != 0 ) + { + adj[i] = 17695; /* Q15, 0.54f */ move16(); + } + ELSE + { + adj[i] = 23593; /* Q15, 0.72f */ move16(); + } + } + ELSE + { + adj[i] = 23593; /* Q15, 0.72f */ move16(); + } + + if( att_state == 0 ) + { + start = i; + move16(); + } + + len = add(len,1); + move16(); + att_state = 1; + move16(); + } + ELSE + { + adj[i] = MAX_16; /* Q15, 1.0f (saturated) */ + IF( EQ_16(att_state, 1)) /* End of attenuation region found */ + { + /* tmp = min(1, max(0, len-ENV_ADJ_START)*(1.0f/ENV_ADJ_INCL)); */ + tmp = round_fx(L_shl(L_mult0(s_max( 0, sub(len, ENV_ADJ_START_FX)), ENV_ADJ_INV_INCL_FX),16)); /* Q15 (15+16-16) */ + tmp_diff = sub(MAX_16, tmp); /* Q15 */ move16(); + FOR( j = start; j < i ; j++ ) + { + /* adj[j] = max(tmp + (1-tmp)*adj[j],env_stab); */ + adj[j] = s_max(add(tmp, mult(tmp_diff, adj[j])), env_stab); /* Q15 (15+15-15) */ move16(); + } + len = 0; + move16(); + att_state = 0; + move16(); + } + } + } + /* length == L_FRAME16k */ + ELSE + { + + /* Calculate low accuracy band attenuation */ + gain_adj = 32767; /* Q15, 1.0f (saturated) */ move16(); + + test(); + IF( npul > 0 && LT_16(npul, MAX_P_ATT)) + { + /*idx = (short)(npul * att_step[group] + 0.5f) - 1; */ + idx = sub(mult_r(shl(npul,2),att_step_fx[group]), 1); /* Q0 (2+13+1-16) */ + if( LT_16(idx, MAX_P_ATT)) + { + gain_adj = gain_att_fx[idx]; /* Q15 */ move16(); + } + } + adj[i] = gain_adj; + move16(); + } + } + + /* Check if the sequence ended with an attenuation region */ + IF( EQ_16(att_state, 1)) + { + /* tmp = min(1, max(0, len-ENV_ADJ_START)*(1.0f/ENV_ADJ_INCL)); */ + tmp = round_fx(L_shl(L_mult0(s_max( 0, sub(len, ENV_ADJ_START_FX)), ENV_ADJ_INV_INCL_FX),16)); /* Q15 (15+16-16) */ + tmp_diff = sub(MAX_16, tmp); /* Q15 */ move16(); + FOR( j = start; j < i ; j++ ) + { + + /* adj[j] = max(tmp + (1-tmp)*adj[j],env_stab); */ + adj[j] = s_max(add(tmp, mult(tmp_diff, adj[j])), env_stab); /* Q15 (15+15-15) */ move16(); + } + } + + return; +} diff --git a/lib_com/env_stab_fx.c b/lib_com/env_stab_fx.c new file mode 100644 index 0000000..e3e8c63 --- /dev/null +++ b/lib_com/env_stab_fx.c @@ -0,0 +1,188 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" /* required by wmc_tool */ + +/*--------------------------------------------------------------------------* + * Local constants + *--------------------------------------------------------------------------*/ +#define ENV_STAB_SMO_HO 10 /* number of hangover frames when switching from music to speech state */ + +/*--------------------------------------------------------------------------*/ +/* Function env_stability_fx */ +/* ~~~~~~~~~~~~~~~~~~~~~ */ +/* */ +/* Envelope stability measure */ +/*--------------------------------------------------------------------------*/ + +Word16 env_stability_fx( /* in Q15 */ + const Word16 *ynrm, /*i: Norm vector for current frame */ + const Word16 nb_sfm, /*i: Number of sub-bands */ + Word16 *mem_norm, /*i/o: Norm vector memory from past frame */ + Word16 *mem_env_delta /*i/o: Envelope stability memory for smoothing in Q12 */ +) +{ + Word16 env_delta; + Word16 env_stab; + Word16 tmp, tmp_stab; + Word16 i; + + Word16 exp, exp2; + Word32 L_tmp, L_env_delta; + Word16 inv_nb_sfm; + + /* Calculate envelope stability parameter */ + L_env_delta = L_deposit_l(0); + FOR (i = 0; i < nb_sfm; i++) + { + tmp = sub(mem_norm[i],ynrm[i]); + L_env_delta = L_mac0(L_env_delta, tmp, tmp); + mem_norm[i] = ynrm[i]; + move16(); + } + + inv_nb_sfm = 19418; /* Q19 */ move16(); + if (nb_sfm == 26) + { + inv_nb_sfm = 20165; /* Q19 */ move16(); + } + exp = norm_l(L_env_delta); + L_env_delta = Mult_32_16(L_shl(L_env_delta, exp), inv_nb_sfm); /* 0+exp+19-15 */ + + L_tmp = Sqrt_l(L_env_delta, &exp2); /* exp+4+31+exp2 */ + + exp = add(35, add(exp, exp2)); + if ( EQ_16(s_and(exp, 1), 1)) + { + L_tmp = Mult_32_16(L_tmp, 23170); /* 1/sqrt(2) in Q15 */ + } + exp = shr(exp, 1); + + env_delta = round_fx(L_shl(L_tmp, sub(26, exp))); /* Q10 */ + + L_tmp = L_mult0(26214, env_delta); /* 26214 is 0.1 in Q18. Q28 */ + L_tmp = L_mac(L_tmp, 29491, *mem_env_delta); /* 29491 is 0.9 in Q15. Q28 */ + + *mem_env_delta = round_fx(L_tmp); /* Q12 */ + Overflow = 0; + move16(); + env_delta = round_fx(L_shl(L_tmp, 1)); /* Q13 */ + + IF (Overflow != 0) /* Saturated due to the above up-shifting operation. */ + { + return stab_trans_fx[L_STAB_TBL-1]; /* The highest quantized index. */ + } + + /* If tmp_stab > (D_STAB_TBL*L_STAB_TBL + M_STAB_TBL), i.e., 0.103138*10+2.51757=3.603137, + * the quantized index is equal to 9. Hence, we only need to worry about any tmpStab < 4. + * In this case, Q13 is good enough. + */ + tmp_stab = sub(env_delta, M_STAB_TBL_FX); /* in Q13 */ + tmp_stab = abs_s(tmp_stab); + + /* Table lookup for smooth transitions + * First, find the quantization level, i, of tmpStab. */ +#if L_STAB_TBL > 10 +#error env_stability_fx: Use more efficient usquant() +#endif + tmp_stab = sub(tmp_stab, HALF_D_STAB_TBL_FX); /* in Q13 */ + FOR (i = 0; i < L_STAB_TBL-1; i++) + { + IF (tmp_stab < 0) + { + BREAK; + } + ELSE + { + tmp_stab = sub(tmp_stab, D_STAB_TBL_FX); /* in Q13 */ + } + } + + env_stab = stab_trans_fx[i]; + move16(); + if(LT_16(env_delta, M_STAB_TBL_FX)) + { + env_stab = sub(0x7FFF,stab_trans_fx[i]); + } + + return env_stab; +} + +/*--------------------------------------------------------------------------* + * env_stab_smo_fx() + * + * + *--------------------------------------------------------------------------*/ +Word16 env_stab_smo_fx( /* Q0 */ + Word16 env_stab, /*i : env_stab value Q15 */ + Word16 *env_stab_state_p, /*i/o: env_stab state probabilities Q15 */ + Word16 *ho_cnt /*i/o: hangover counter for speech state */ +) +{ + Word16 state, prev_state; + Word16 maxval, pp[NUM_ENV_STAB_PLC_STATES], pa[NUM_ENV_STAB_PLC_STATES]; + Word16 i; + Word16 tmp, sum, exp; + + /* get previous state */ + prev_state = maximum_fx(env_stab_state_p, NUM_ENV_STAB_PLC_STATES, &maxval); + + /* assume two states: speech(0), music(1) */ + /* set a posteriori likelihoods for the two states according to env_stab */ + /* re-scale. Unclear if needed */ + /* env_stab = (env_stab - stab_trans_fx[L_STAB_TBL-1])/(1-2*stab_trans_fx[L_STAB_TBL-1]); */ + tmp = sub(env_stab, stab_trans_fx[L_STAB_TBL-1]); + tmp = round_fx(L_shl(L_mult(tmp, INV_STAB_TRANS_FX), 1)); /* Q15 */ + + pp[0] = sub(32767, tmp); + move16(); /* 1 in Q15 */ + pp[1] = tmp; + move16(); + + /* calculate a priori likelihoods */ + pa[0] = round_fx(Dot_product(env_stab_tp_fx[0], env_stab_state_p, NUM_ENV_STAB_PLC_STATES)); /* Q15*/ + pa[1] = round_fx(Dot_product(env_stab_tp_fx[1], env_stab_state_p, NUM_ENV_STAB_PLC_STATES)); + + /* multiply elementwise with a posteriori likelihoods */ + sum = 0; + move16(); + FOR (i = 0; i < NUM_ENV_STAB_PLC_STATES; i++) + { + env_stab_state_p[i] = mult_r(pa[i], pp[i]); + move16(); /* Q15 */ + sum = add(sum, env_stab_state_p[i]); + } + + /* renormalize state probabilities */ + exp = norm_s(sum); + tmp = div_s(16384, shl(sum, exp)); /* Q(14-exp) */ + /*tmp = shl(tmp, add(exp, 1));*/ /* Q15 */ + FOR (i = 0; i < NUM_ENV_STAB_PLC_STATES; i++) + { + env_stab_state_p[i] = round_fx(L_shl(L_mult(env_stab_state_p[i], tmp), add(exp, 1))); /* Q15 */ + } + + /* find maximum index as return value */ + state = maximum_fx(env_stab_state_p, NUM_ENV_STAB_PLC_STATES, &maxval); + + /* apply some hangover for speech */ + test(); + if (state == 0 && EQ_16(prev_state, 1)) + { + *ho_cnt = ENV_STAB_SMO_HO; + move16(); + } + + IF (*ho_cnt > 0) + { + *ho_cnt = sub(*ho_cnt, 1); + move16(); + } + + return state; +} diff --git a/lib_com/env_stab_trans_fx.c b/lib_com/env_stab_trans_fx.c new file mode 100644 index 0000000..6e86bca --- /dev/null +++ b/lib_com/env_stab_trans_fx.c @@ -0,0 +1,161 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "math_op.h" /* WMOPS macros */ +#include "stl.h" /* required by wmc_tool */ + +/*--------------------------------------------------------------------------* + * env_stab_transient_detect() + * + * Transient detector for envelope stability measure + *--------------------------------------------------------------------------*/ + +void env_stab_transient_detect_fx( + const Word16 is_transient, /* i: Transient flag */ + const Word16 length, /* i : Length of spectrum (32 or 48 kHz) */ + const Word16 norm[], /* i : quantization indices for norms */ + Word16 *no_att_hangover, /* i/o: Frame counter for attenuation hangover (Q0) */ + Word32 *L_energy_lt, /* i/o: Long-term energy measure for transient detection (Q13) */ + const Word16 HQ_mode, /* i : HQ coding mode */ + const Word16 bin_th, /* i : HVQ cross-over frequency bin */ + const Word32 *L_coeff, /* i : Coded spectral coefficients */ + const Word16 Qcoeff /* i : Q of coded spectral coefficients */ +) +{ + Word16 i, blk, norm_ind, sqrt_exp, bin_th_1, temp, sh; + Word32 L_e_frame, L_temp, L_d_max; + Word32 L_energy_lt_local; + Word32 L_E_sub[4]; + Word32 L_delta_e_sub; + + L_energy_lt_local = *L_energy_lt; + move32(); + + L_d_max = L_deposit_l(0); + L_e_frame = L_deposit_l(0); + temp = 32; + move16(); + + IF( EQ_16(HQ_mode,HQ_HVQ)) + { + FOR (i = 0; i < bin_th; i++) /* find adaptive shift */ + { + temp = s_min(temp,norm_l(L_coeff[i])); + } + sh = sub(temp,2); /* scale such that 2 msbs are not used, the resulting adaptive Qcoeff will be: Qcoeff+sh-16 */ + FOR (i = 0; i < bin_th; i++) /* Maximum number of loop runs 320 */ + { + temp = extract_h(L_shl(L_coeff[i],sh)); + L_e_frame = L_mac(L_e_frame,temp,temp); /* Q(2*(Qcoeff+sh-16)+1)=Q(2*(Qcoeff+sh)-31 */ + } + + bin_th_1 = INV_HVQ_THRES_BIN_24k; + move16(); + if (EQ_16(bin_th, HVQ_THRES_BIN_32k)) + { + bin_th_1 = INV_HVQ_THRES_BIN_32k; + move16(); + } + L_temp = Mult_32_16(L_e_frame,bin_th_1); /* Q(2*(Qcoeff-16+sh)+1+21-15) -> Q(2*(Qcoeff+sh)-25) */ + L_e_frame = Sqrt_l(L_temp,&sqrt_exp); + L_e_frame = L_shr(L_e_frame, add(sub(add(sh,Qcoeff),10),shr(sqrt_exp,1))); /* Adjust by (Qcoeff+sh-10) to fixed Q13: Qcoeff+sh+(-25+31)/2 - (Qcoeff+sh-10) -> Q13 */ + + IF ( GT_32(L_e_frame, ENERGY_TH_FX)) + { + L_energy_lt_local = Mult_32_16(*L_energy_lt, ENERGY_LT_BETA_FX); + L_temp = Mult_32_16(L_e_frame, ENERGY_LT_BETA_1_FX); + *L_energy_lt = L_add(L_energy_lt_local,L_temp); + move32(); + } + + IF (*no_att_hangover > 0) + { + (*no_att_hangover) = sub((*no_att_hangover), 1); + move16(); + } + } + ELSE + { + L_e_frame = L_deposit_l(0); + + test(); + IF (is_transient && EQ_16(length,L_FRAME32k)) + { + /* Measure subframe energies */ + FOR (blk = 0; blk < NUM_SUBFRAMES; blk++) + { + L_E_sub[blk] = L_deposit_l(0); /* Q9 */ + + FOR (i=0; i < 2^4 */ + { + norm_ind = subf_norm_groups_fx[blk][i]; + move16(); + L_E_sub[blk] = L_add(L_E_sub[blk],L_shr(dicn_fx[norm[norm_ind]],4)); + move32(); ; /* Q10 */ + } + + L_E_sub[blk] = Mult_32_16(L_E_sub[blk], INV_BANDS_PER_SUBFRAMES); + move32(); /* Q(10+17-15) -> Q12 */ + + L_e_frame = L_add(L_e_frame,L_E_sub[blk]); /* Q12 */ + } + + /* Test for transient */ + /* if (e_frame > ENERGY_TH * NUM_SUBFRAMES) */ + IF (GT_32(L_e_frame, ENERGY_TH_NUM_SUBFRAMES)) + { + FOR (blk = 0; blk < NUM_SUBFRAMES-1; blk++) + { + L_delta_e_sub = L_sub(L_E_sub[blk+1],L_E_sub[blk]); /* Q12 */ + if (GT_32(L_delta_e_sub,L_d_max)) + { + L_d_max = L_delta_e_sub; /* L_d_max is NOT normalized with *energy_lt */ + move32(); + } + } + } + } + ELSE + { + /* Update long-term energy measure */ + L_e_frame = L_deposit_l(0); /* Q9 */ + FOR (i = 0; i < SFM_N_ENV_STAB; i++) /* 27 times -> < 2^5 */ + { + L_e_frame = L_add(L_e_frame,L_shr(dicn_fx[norm[i]],5)); + /* Q9 */ + } + + L_e_frame = Mult_32_16(L_e_frame, INV_SFM_N_ENV_STAB); /* Q(9+19-15) -> Q13 */ + + IF ( GT_32(L_e_frame, ENERGY_TH_FX)) + { + L_energy_lt_local = Mult_32_16(*L_energy_lt, ENERGY_LT_BETA_FX); + L_temp = Mult_32_16(L_e_frame, ENERGY_LT_BETA_1_FX); + *L_energy_lt = L_add(L_energy_lt_local,L_temp); + move32(); + } + } + + /* Add hang-over for conservative application of stability dependent attenuation */ + /* -> Note: L_d_max not normalized with *energy_lt */ + /* Hence, we compare L_d_max/DELTA_TH with *energy_lt */ + IF (GT_32(Mult_32_16(L_d_max, INV_DELTA_TH),L_energy_lt_local)) /* Q13 = Q(12 + 16 -15) */ + { + *no_att_hangover = ATT_LIM_HANGOVER; + move16(); + } + ELSE if (*no_att_hangover > 0) + { + *no_att_hangover = sub(*no_att_hangover,1); + move16(); + } + } + + return; +} + diff --git a/lib_com/est_tilt_fx.c b/lib_com/est_tilt_fx.c new file mode 100644 index 0000000..07a7ac0 --- /dev/null +++ b/lib_com/est_tilt_fx.c @@ -0,0 +1,269 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "basop_mpy.h" +#include "basop_util.h" + + +/*======================================================================*/ +/* FUNCTION : est_tilt_fx() */ +/*-----------------------------------------------------------------------*/ +/* PURPOSE : Estimate spectral tilt based on the relative E of adaptive */ +/* and innovative excitations */ +/* */ +/*-----------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16 *) exc : adaptive excitation vector Q0 */ +/* _ (Word16) gain_pit : adaptive gain Q14 */ +/* _ (Word16 *) code : algebraic exctitation vector Q12 */ +/* _ (Word32) gain_code : algebraic code gain Q16 */ +/* _ (Word16) Q_exc : Scaling factor of excitation Q0 */ +/*-----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 *) voice_fac : voicing factor Q15 */ +/*-----------------------------------------------------------------------*/ +/* INPUT OUTPUT ARGUMENTS */ +/*-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word16) tolt_code : tilt of the code Q15 */ +/*=======================================================================*/ +Word16 est_tilt_fx( /* o : tilt of the code Q15 */ + const Word16 *exc, /* i : adaptive excitation vector Qx */ + const Word16 gain_pit, /* i : adaptive gain Q14 */ + const Word16 *code, /* i : algebraic exctitation vector Q9 */ + const Word32 gain_code, /* i : algebraic code gain Q16 */ + Word16 *voice_fac, /* o : voicing factor Q15 */ + const Word16 Q_exc /* i : Scaling factor of excitation Q0 */ +) +{ + Word16 i, tmp, exp, ener1, exp1, ener2, exp2; + Word32 L_tmp; + Word16 tilt_code; + + ener1 = extract_h(Dot_product12(exc, exc, L_SUBFR, &exp1)); + exp1 = sub(exp1, add(Q_exc, Q_exc)); + L_tmp = L_mult(gain_pit, gain_pit); /* energy of pitch excitation */ + exp = norm_l(L_tmp); + tmp = extract_h(L_shl(L_tmp, exp)); + ener1 = mult(ener1, tmp); + exp1 = sub(sub(exp1, exp), 10); /* 10 -> gain_pit Q14 to Q9 */ + + ener2 = extract_h(Dot_product12(code, code, L_SUBFR, &exp2)); + + exp = norm_l(gain_code); + tmp = extract_h(L_shl(gain_code, exp)); + tmp = mult(tmp, tmp); /* energy of innovative code excitation */ + ener2 = mult(ener2, tmp); + exp2 = sub(exp2, add(exp, exp)); + + i = sub(exp1, exp2); + BASOP_SATURATE_WARNING_OFF + ener1 = shr(ener1, sub(1, s_min(i, 0))); + ener2 = shr(ener2, add(s_max(0, i), 1)); + BASOP_SATURATE_WARNING_ON + tmp = sub(ener1, ener2); + ener1 = add(add(ener1, ener2), 1); + + /* find voice factor (1=voiced, -1=unvoiced) */ + exp = div_s(abs_s(tmp), ener1); + if (tmp < 0) + { + exp = negate(exp); + } + *voice_fac = exp; + move16(); + + /* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */ + + /* tilt_code = (float)(0.25*(1.0 + *voice_fac)) */ + tilt_code = mac_r(8192L*65536-0x8000, *voice_fac, 8192); /*Q15 */ + + return tilt_code; +} +/*-------------------------------------------------------------------* + * Est_tilt2: + * + * Estimate spectral tilt based on the relative E of adaptive + * and innovative excitations + *-------------------------------------------------------------------*/ +Word16 Est_tilt2( /* o : tilt of the code */ + const Word16 *exc, /* i : adaptive excitation vector Qx */ + const Word16 gain_pit, /* i : adaptive gain Q14 */ + const Word16 *code, /* i : algebraic exctitation vector Q9 */ + const Word32 gain_code, /* i : algebraic code gain Q16 */ + Word16 *voice_fac, /* o : voicing factor Q15 */ + const Word16 Q_exc /* i : Scaling factor of excitation Q0 */ +) +{ + Word16 i, tmp, exp, ener1, exp1, ener2, exp2; + Word32 L_tmp; + Word16 tilt_code; + + /* Scale exc to avoid overflow */ + ener1 = extract_h(Energy_scale(exc, L_SUBFR, Q_exc, &exp1)); + + exp1 = sub(exp1, add(Q_exc, Q_exc)); + L_tmp = L_mult(gain_pit, gain_pit); /* energy of pitch excitation */ + exp = norm_l(L_tmp); + tmp = extract_h(L_shl(L_tmp, exp)); + ener1 = mult(ener1, tmp); + exp1 = sub(sub(exp1, exp), 10); /* 10 -> gain_pit Q14 to Q9 */ + + ener2 = extract_h(Dot_product12(code, code, L_SUBFR, &exp2)); + + exp = norm_l(gain_code); + tmp = extract_h(L_shl(gain_code, exp)); + tmp = mult(tmp, tmp); /* energy of innovative code excitation */ + ener2 = mult(ener2, tmp); + exp2 = sub(exp2, add(exp, exp)); + + i = sub(exp1, exp2); + ener1 = shr(ener1, sub(1, s_min(i, 0))); + ener2 = shr(ener2, add(s_max(0, i), 1)); + + tmp = sub(ener1, ener2); + ener1 = add(add(ener1, ener2), 1); + + /* find voice factor (1=voiced, -1=unvoiced) */ + exp = div_s(abs_s(tmp), ener1); + if (tmp < 0) + { + exp = negate(exp); + } + *voice_fac = exp; + move16(); + + /* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */ + + /* tilt_code = (float)(0.25*(1.0 + *voice_fac)) */ + tilt_code = mac_r(8192L*65536-0x8000, *voice_fac, 8192); + + return tilt_code; +} + +/*---------------------------------------------------------* + * Find voice factor and tilt code * + *---------------------------------------------------------*/ +void E_UTIL_voice_factor( Word16 *exc, /* i : pointer to the excitation frame Q_new */ + Word16 i_subfr, /* i : subframe index */ + Word16 *code, /* i : innovative codebook Q9 */ + Word16 gain_pit, /* i : adaptive codebook gain 1Q14 */ + Word32 gain_code, /* i : innovative cb. gain 15Q16 */ + Word16 *voice_fac, /* o : subframe voicing estimation Q15 */ + Word16 *tilt_code, /* o : tilt factor Q15 */ + Word16 L_subfr, /* i : subframe length */ + Word16 flag_tilt, /* i : Flag for triggering new voice factor tilt*/ + Word16 Q_new, /* i : excitation buffer format */ + Word16 shift /* i : scaling to get 12bit */ + ) +{ + Word16 i, e, e2, stmp, exp_ener, fac; + Word32 ener, tmp, num; + Word64 ener_64; + + BASOP_SATURATE_ERROR_ON; + + + IF(shift != 0) + { + fac = shl(0x4000,add(1,shift)); + /* energy of pitch excitation */ + stmp = mult_r(exc[0+i_subfr], fac); /* remove fac bits */ + ener_64 = W_mult0_16_16(stmp, stmp); + FOR (i=1; i exponent = (15-Q_new)*2+1 */ + } + } + ener = W_sat_l( ener_64 ); + + + /* exponent of ener: (2*(15-Q_new+shift)+1+2-exp_ener-2*e2) */ + exp_ener = norm_l(ener); + if(ener == 0) + { + exp_ener = 31; + move16(); + } + ener = L_shl(ener,exp_ener); + e2 = norm_s(gain_pit); + gain_pit = shl(gain_pit,e2); + ener = Mpy_32_16_1(ener, mult_r(gain_pit, gain_pit)); + + + /* energy of innovative code excitation */ + tmp = L_deposit_l(1); + + FOR (i=0; i 13Q18 */ + } + /* exponent of tmp: 2*(15-9)+1+2*(15-e)) */ + e = norm_l(gain_code); + gain_code = L_shl(gain_code, e); + tmp = Mpy_32_32(tmp, Mpy_32_32(gain_code,gain_code)); + + /* find voice factor (1=voiced, -1=unvoiced) */ + /*i = (2*(15-Q_new+shift)+1+2-exp_ener-2*e2) - (2*(15-9)+1 + 2*(15-e));*/ + i = sub(sub(sub(sub(sub(33,add(shift,shift)),add(Q_new,Q_new)),exp_ener),add(e2,e2)),sub(43,add(e,e))); + IF(i >= 0) + { + ener = L_shr(ener,1); + tmp = L_shr(tmp, add(1,i)); + } + ELSE + { + tmp = L_shr(tmp,1); + BASOP_SATURATE_WARNING_OFF + ener = L_shr(ener, sub(1,i)); + BASOP_SATURATE_WARNING_ON + } + + *voice_fac = 0; + move16(); + num = L_sub(ener, tmp); + IF(num != 0) + { + BASOP_SATURATE_WARNING_OFF /* Allow saturating the voice factor because if has a limited range by definition. */ + *voice_fac = divide3232(num, L_add(ener, tmp)); + move16(); + BASOP_SATURATE_WARNING_ON + } + + /* find tilt of code for next subframe */ + IF (flag_tilt==0) + { + /*Between 0 (=unvoiced) and 0.5 (=voiced)*/ + move16(); + *tilt_code = add(8192/*0.25f Q15*/, mult_r(8192/*0.25f Q15*/, *voice_fac)); + } + ELSE IF (flag_tilt==1) + { + /*Between 0.25 (=unvoiced) and 0.5 (=voiced)*/ + move16(); + *tilt_code = add(mult_r(4096/*0.125f Q15*/, *voice_fac), 12288/*0.125f+0.25f Q15*/); + } + ELSE + { + /*Between 0.28 (=unvoiced) and 0.56 (=voiced)*/ + move16(); + *tilt_code = add(mult_r(4588/*0.14f Q15*/, *voice_fac), 13763/*0.14f+0.28f Q15*/); + } + BASOP_SATURATE_ERROR_OFF; +} diff --git a/lib_com/fd_cng_com.c b/lib_com/fd_cng_com.c new file mode 100644 index 0000000..400a41d --- /dev/null +++ b/lib_com/fd_cng_com.c @@ -0,0 +1,1826 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "stl.h" +#include "basop_util.h" +#include "options.h" +#include "stl.h" +#include "rom_basop_util.h" +#include "rom_com_fx.h" +#include "prot_fx.h" + +#define DELTA_SHIFT 2 +#define DELTA_SHIFT_LD64 67108864l/*DELTA_SHIFT/64.0 Q31*/ + + + +/***************************************** +* Create an instance of type FD_CNG_COM * +*****************************************/ +void createFdCngCom(HANDLE_FD_CNG_COM * hFdCngCom) +{ + HANDLE_FD_CNG_COM hs; + + /* Allocate memory */ + hs = (HANDLE_FD_CNG_COM) calloc(1, sizeof (FD_CNG_COM)); + move16(); + + + *hFdCngCom = hs; + move16(); + return; +} + +void initFdCngCom(HANDLE_FD_CNG_COM hs, Word16 scale) +{ + /* Calculate CLDFB scaling factor */ + /* shl(i_mult2(scale, scale), 3) does not fit in 16 bit */ + /*hs->scalingFactor = div_s(1, shl(i_mult2(scale, scale), 3));*/ + assert(2048/*1.0/(1<<4) Q15*/ < mult(scale, scale)); + /* Exponent invScalingFactor: -16 = -(2*7 (scale) + 2 (8.0) */ + hs->invScalingFactor = shl(mult(scale,scale),1); + /* Exponent scalingFactor: -15 = -(2*7 (scale) + 2 (8.0) - 1 (1.0)) */ + hs->scalingFactor = div_s(0x4000,hs->invScalingFactor); + + /* Initialize the overlap-add */ + set16_fx( hs->timeDomainBuffer, 0, L_FRAME16k ); + hs->olapBufferAna = NULL; + move16(); + set16_fx( hs->olapBufferSynth, 0, FFTLEN ); + hs->olapBufferSynth2 = NULL; + move16(); + + /* Initialize the comfort noise generation */ + set32_fx( hs->fftBuffer, 0, FFTLEN ); + set32_fx( hs->cngNoiseLevel, 0, FFTCLDFBLEN ); + + /* Initialize quantizer */ + set32_fx( hs->sidNoiseEst, 0, NPART ); + set16_fx( hs->A_cng, 0, M+1 ); + hs->A_cng[0] = 4096/*1.f Q12*/; /* 3Q12 */ move16(); + + /* Set some counters and flags */ + hs->inactive_frame_counter = 0; /* Either SID or zero frames */ move16(); + hs->active_frame_counter = 0; + move16(); + hs->frame_type_previous = ACTIVE_FRAME; + move16(); + hs->flag_noisy_speech = 0; + move16(); + hs->likelihood_noisy_speech = 0; + move16(); + hs->numCoreBands = 0; + move16(); + hs->stopBand = 0; + move16(); + hs->startBand = 0; + move16(); + hs->stopFFTbin = 0; + move16(); + hs->frameSize = 0; + move16(); + hs->fftlen = 0; + move16(); + + /* Initialize noise estimation algorithm */ + set32_fx( hs->periodog, 0, PERIODOGLEN ); + mhvals(MSNUMSUBFR*MSSUBFRLEN, &(hs->msM_win)); + mhvals(MSSUBFRLEN, &(hs->msM_subwin)); + set32_fx( hs->msPeriodogSum, 0, 2 ); + hs->msPeriodogSum_exp[0] = 0; + move16(); + hs->msPeriodogSum_exp[1] = 0; + move16(); + set32_fx( hs->msPsdSum, 0, 2 ); + set16_fx( hs->msSlope, 0, 2 ); + set32_fx( hs->msQeqInvAv, 0, 2 ); + hs->msQeqInvAv_exp[0] = 0; + move16(); + hs->msQeqInvAv_exp[1] = 0; + move16(); + hs->msFrCnt_init_counter = 0; + move16(); + hs->msFrCnt_init_thresh = 1; + move16(); + hs->init_old = 0; + move16(); + hs->offsetflag = 0; + move16(); + hs->msFrCnt = MSSUBFRLEN; + move16(); + hs->msMinBufferPtr = 0; + move16(); + hs->msAlphaCor[0] = 644245120l/*0.3f Q31*/; + move16(); + hs->msAlphaCor[1] = 644245120l/*0.3f Q31*/; + move16(); + + /* Initialize exponents */ + hs->exp_cldfb_periodog = 0; + move16(); + + return; +} + +/***************************************** +* Delete an instance of type FD_CNG_COM * +*****************************************/ +void deleteFdCngCom(HANDLE_FD_CNG_COM * hFdCngCom) /* i/o: Contains the variables related to the CLDFB-based CNG process */ +{ + HANDLE_FD_CNG_COM hsCom; + hsCom = *hFdCngCom; + move16(); + IF (hsCom != NULL) + { + free(hsCom); + *hFdCngCom = NULL; + move16(); + } +} + +/*************************************** +* Initialize the spectral partitioning * +****************************************/ +void initPartitions( const Word16* part_in, + Word16 npart_in, + Word16 startBand, + Word16 stopBand, + Word16* part_out, + Word16* npart_out, + Word16* midband, + Word16* psize, + Word16* psize_norm, + Word16* psize_norm_exp, + Word16* psize_inv, + Word16 stopBandFR + ) +{ + Word16 i, j, len_out, tmp16; + + + IF (part_in != NULL) + { + len_out = 0; + move16(); + IF (GT_16(stopBandFR, startBand)) + { + len_out = sub(stopBandFR, startBand); + FOR(i = 0 ; i < len_out; i++) + { + part_out[i] = i; + move16(); + } + } + FOR(j=0 ; j < npart_in; j++) + { + IF (GE_16(part_in[j], stopBand)) + { + BREAK; + } + tmp16 = sub(part_in[j],startBand); + test(); + if (GE_16(part_in[j],stopBandFR)&&tmp16>=0) + { + part_out[len_out++] = tmp16; + move16(); + } + } + } + ELSE + { + len_out = sub(stopBand, startBand); + FOR (i = 0 ; i < len_out; i++) + { + part_out[i] = i; + move16(); + } + } + + *npart_out = len_out; + move16(); + getmidbands(part_out, len_out, midband, psize, psize_norm, psize_norm_exp, psize_inv); + +} + +#define CNG_HS 4 /* 4 bit headroom for dot product */ +#define CNG_S 6 /* 1 sign bit, 6 bit integer part, 9 bit frational part for input and output data */ + + + + +/******************************************************** +* Apply some dynamic range compression based on the log * +********************************************************/ +void compress_range( + Word32 *in, + Word16 in_exp, + Word16 *out, + Word16 len +) +{ + Word16 i; + Word32 in_s; + Word32 one_s; + Word32 in_exp32; + Word32 L_tmp; + + + /* out = log2( 1 + in ) */ + IF ( in_exp >= 0 ) + { + one_s = L_shr(1073741824l/*0.5 Q31*/,in_exp); + in_exp32 = L_shl(L_deposit_l(add(in_exp,1)),WORD32_BITS-1-LD_DATA_SCALE); + FOR (i=0; i < len; i++) + { + in_s = L_add(L_shr(in[i],1),one_s); + L_tmp = L_add(BASOP_Util_Log2(in_s),in_exp32); + if (in_s == 0) + { + out[i] = 0; + move16(); + } + if (in_s != 0) + { + out[i] = extract_h(L_tmp); + } + if(out[i] == 0) + { + out[i] = 1; + } + } + } + ELSE + { + in_exp = sub(in_exp,1); + in_exp32 = L_shl(L_deposit_l(1),WORD32_BITS-1-LD_DATA_SCALE); + FOR (i=0; i < len; i++) + { + L_tmp = L_add(BASOP_Util_Log2(L_add(L_shl(in[i],in_exp),1073741824l/*0.5 Q31*/)),in_exp32); + if (in[i] == 0) + { + out[i] = 0; + move16(); + } + if (in[i] != 0) + { + out[i] = extract_h(L_tmp); + } + if (out[i] == 0) + { + out[i] = 1; + } + } + } + +} + +/************************************************************* +* Apply some dynamic range expansion to undo the compression * +*************************************************************/ +void expand_range( + Word16 *in, + Word32 *out, + Word16 *out_exp, + Word16 len +) +{ + Word16 i; + Word16 s; + Word16 tmp; + Word32 one_s, tmp32; + Word16 maxVal; + Word16 maxVal2; + + + maxVal = 0; + move16(); + FOR (i=0; i < len; i++) + { + maxVal = s_max(maxVal,in[i]); + } + + maxVal2 = maxVal; + move16(); + s = 0; + move16(); + WHILE ( maxVal >= 0 ) + { + maxVal = sub(maxVal,512/*0.015625 Q15*/); + s = add(s,1); + } + tmp = sub(maxVal2,maxVal); + + one_s = L_shr(1073741824l/*0.5 Q31*/,sub(s,1)); + tmp32 = L_shr(726941l/*0.0003385080526823181 Q31*/,s); + /* out = (2^(in) - 1) */ + FOR (i=0; i < len; i++) + { + out[i] = L_sub(BASOP_Util_InvLog2(L_deposit_h(sub(in[i],tmp))),one_s); + move32(); + if ( out[i] == 0 ) + { + out[i] = tmp32; + move32(); + } + } + *out_exp = s; + move16(); + +} + +/************************************************* +* Noise estimation using Minimum Statistics (MS) * +*************************************************/ +void minimum_statistics ( + Word16 len, /* i : Total number of partitions (CLDFB or FFT) */ + Word16 lenFFT, /* i : Number of FFT partitions */ + Word16 *psize, /* i : Partition sizes, fractional */ + Word16 *msPeriodog, /* i : Periodogram (energies) */ + Word16 *msNoiseFloor, /* i/o: Noise floors (energies) */ + Word16 *msNoiseEst, /* i/o: Noise estimates (energies) */ + Word32 *msAlpha, /* i/o: Forgetting factors */ + Word16 *msPsd, /* i/o: Power Spectral Density (smoothed periodogram => energies) */ + Word16 *msPsdFirstMoment, /* i/o: PSD statistics of 1st order (energy means) */ + Word32 *msPsdSecondMoment, /* i/o: PSD statistics of 2nd order (energy variances) */ + Word32 *msMinBuf, /* i/o: Buffer of minima (energies) */ + Word32 *msBminWin, /* o : Bias correction factors */ + Word32 *msBminSubWin, /* o : Bias correction factors */ + Word32 *msCurrentMin, /* i/o: Local minima (energies) */ + Word32 *msCurrentMinOut, /* i/o: Local minima (energies) */ + Word32 *msCurrentMinSubWindow, /* i/o: Local minima (energies) */ + Word16 *msLocalMinFlag, /* i : Binary flag */ + Word16 *msNewMinFlag, /* i : Binary flag */ + Word16 *msPeriodogBuf, /* i/o: Buffer of periodograms (energies) */ + Word16 *msPeriodogBufPtr, /* i/o: Counter */ + HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing buffers and variables */ +) +{ + Word16 i,j,k,s,s1,s2,s3; + Word16 len2; + Word16 current_len; + Word16 start, stop, cnt; + Word16 totsize; + Word16 inv_totsize; + + Word32 tmp, tmp0, tmp1; + Word32 scalar, scalar2, scalar3; + Word32 snr; + Word32 msAlphaHatMin2; + Word32 BminCorr; + Word32 QeqInvAv; + Word32 *ptr; + Word32 *msPsdSum; + Word32 *msPeriodogSum; + + Word16 tmp16, tmp16_1; + Word16 beta; + Word16 slope; + Word16 QeqInv; + Word16 scalar16; + Word16 scalar216; + Word16 scalar316; + Word16 msM_win; + Word16 msM_subwin; + Word16 msAlphaCorAlpha; + Word16 msAlphaCorAlpha2; + Word16 msPeriodogSum16; + Word16 msNoiseFloor16; + + + len2 = i_mult(MSNUMSUBFR,len); + + msM_win = st->msM_win; + move16(); + msM_subwin = st->msM_subwin; + move16(); + + msAlphaCorAlpha = MSALPHACORALPHA; + move16(); + msAlphaCorAlpha2 = MSALPHACORALPHA2; + move16(); + + msPsdSum = st->msPsdSum; + msPeriodogSum = st->msPeriodogSum; + + /* No minimum statistics at initialization */ + IF ( LT_16(st->msFrCnt_init_counter,st->msFrCnt_init_thresh)) + { + Copy(msPeriodog, msPsd, len); /* 6Q9 */ + Copy(msPeriodog, msNoiseFloor, len); /* 6Q9 */ + Copy(msPeriodog, msNoiseEst, len); /* 6Q9 */ + Copy(msPeriodog, msPsdFirstMoment, len); /* 6Q9 */ + + set32_fx(msPsdSecondMoment, 0l/*0.0 Q31*/, len); + msPeriodogSum[0] = dotp_s_fx(msPeriodog, psize, lenFFT, CNG_HS); + move32(); + msPsdSum[0] = msPeriodogSum[0]; /* 16Q15 */ move32(); + + IF ( LT_16(lenFFT,len)) + { + msPeriodogSum[1] = dotp_s_fx(msPeriodog+lenFFT, psize+lenFFT, sub(len,lenFFT), CNG_HS); + move32(); + msPsdSum[1] = msPeriodogSum[1]; /* 16Q15 */ move32(); + } + + /* Increment frame counter at initialization */ + /* Some frames are sometimes zero at initialization => ignore them */ + IF ( LT_16(msPeriodog[0],st->init_old)) + { + set32_fx(msCurrentMinOut, 2147483647l/*1.0 Q31*/, len); /* 16Q15 */ + set32_fx(msCurrentMin, 2147483647l/*1.0 Q31*/, len); /* 16Q15 */ + set32_fx(msMinBuf, 2147483647l/*1.0 Q31*/, len2); /* 16Q15 */ + set32_fx(msCurrentMinSubWindow, 2147483647l/*1.0 Q31*/, len); /* 16Q15 */ + + st->msFrCnt_init_counter = add(st->msFrCnt_init_counter,1); + move16(); + } + st->init_old = msPeriodog[0]; /* 6Q9 */ move16(); + } + ELSE + { + /* Consider the FFT and CLDFB bands separately + - first iteration for FFT bins, + - second one for CLDFB bands in SWB mode */ + cnt = 0; + move16(); + start = 0; + move16(); + stop = lenFFT; + move16(); + totsize = sub(st->stopFFTbin,st->startBand); + WHILE ( GT_16(stop,start)) + { + current_len = sub(stop,start); + + /* Compute smoothed correction factor for PSD smoothing */ + + /* msPeriodogSum[cnt] with format 16Q15 */ + msPeriodogSum[cnt] = dotp_s_fx(msPeriodog+start, psize+start, current_len, CNG_HS); + move32(); + + IF ( msPeriodogSum[cnt] == 0 ) + { + st->msAlphaCor[cnt] = Mpy_32_16_1(st->msAlphaCor[cnt], msAlphaCorAlpha); + move32(); + } + ELSE + { + /* calculate scalar with normalized msPeriodogSum[cnt], exponent -2*s1 */ + s1 = norm_l(msPeriodogSum[cnt]); + msPeriodogSum16 = round_fx(L_shl(msPeriodogSum[cnt],s1)); + scalar = L_mult(msPeriodogSum16, msPeriodogSum16); + + /* calculate difference, both elements in 16Q15 format, use absolute value + to avoid -1.0 x -1.0 multiplications later */ + scalar2 = L_abs(L_sub(msPsdSum[cnt], msPeriodogSum[cnt])); + + s2 = WORD32_BITS-1; + move16(); + if ( scalar2 != 0 ) + { + /* use absolute value to avoid -1.0 x -1.0 multiplications */ + s2 = norm_l(scalar2); + } + scalar216 = round_fx(L_shl(scalar2,s2)); + scalar2 = L_mult(scalar216, scalar216); + + /* find common exponent */ + tmp16_1 = sub(s1,s2); + tmp16 = s_min(shl(abs_s(tmp16_1),1),WORD32_BITS-1); + if ( tmp16_1 < 0 ) + { + scalar2 = L_shr(scalar2,tmp16); + } + if(tmp16_1 > 0) + { + scalar = L_shr(scalar,tmp16); + } + + + /* add scalar and scalar2, avoid overflows */ + scalar = L_shr(scalar,1); + scalar2 = L_shr(scalar2,1); + scalar3 = L_add(scalar,scalar2); + + /* calculate division */ + scalar16 = BASOP_Util_Divide3232_uu_1616_Scale(scalar, scalar3, &s3); + s3 = s_max(s3,-(WORD16_BITS-1)); + scalar16 = shl(scalar16,s3); + scalar16 = s_max(scalar16, MSALPHACORMAX); + + st->msAlphaCor[cnt] = L_add(Mpy_32_16_1(st->msAlphaCor[cnt], msAlphaCorAlpha), + L_mult(scalar16, msAlphaCorAlpha2)); + move32(); + } + + /* Compute SNR */ + + /* msPeriodogSum[cnt] with format 16Q15 */ + snr = dotp_s_fx(msNoiseFloor+start, psize+start, current_len, CNG_HS); + + IF ( GT_32(L_shr(Mpy_32_16_1(msPsdSum[cnt],18431/*0.56246299817 Q15*/),13),snr)) + { + tmp0 = BASOP_Util_Log2(msPsdSum[cnt]); + tmp1 = BASOP_Util_Log2(snr); + tmp1 = L_sub(tmp0, tmp1); + tmp1 = Mpy_32_16_1(tmp1, MSSNREXP); + msAlphaHatMin2 = BASOP_Util_InvLog2(tmp1); + } + ELSE + { + msAlphaHatMin2 = MSALPHAHATMIN; + move32(); + } + scalar = Mpy_32_16_1(st->msAlphaCor[cnt], MSALPHAMAX); + + FOR (j=start; j 0) + { + scalar2 = L_shr(scalar2,tmp16); + } + + /* add scalar2 and scalar3, avoid overflows */ + scalar2 = L_shr(scalar2,1); + scalar3 = L_shr(scalar3,1); + scalar3 = L_add(scalar2,scalar3); + + /* calculate division */ + tmp16 = BASOP_Util_Divide3232_uu_1616_Scale(scalar2, scalar3, &s3); + scalar2 = Mpy_32_16_1(scalar, tmp16); + s3 = s_max(s3,-(WORD32_BITS-1)); + scalar2 = L_shl(scalar2,s3); + msAlpha[j] = L_max(scalar2, msAlphaHatMin2); + move32(); + } + + /* Compute the PSD (smoothed periodogram) in each band */ + msPsd[j] = round_fx(L_add(Mpy_32_16_1(msAlpha[j], msPsd[j]), + Mpy_32_16_1(L_sub(2147483647l/*1.0 Q31*/,msAlpha[j]), msPeriodog[j]))); + } + msPsdSum[cnt] = dotp_s_fx(msPsd+start, psize+start, current_len, CNG_HS); + move32(); + + QeqInvAv = 0l/*0.0 Q31*/; + move32(); + + /* scalar: 7Q24 format */ + tmp = 1191182336l/*(float)(MSNUMSUBFR*MSSUBFRLEN)-1.0 Q24*/; + move32(); + scalar = L_sub(tmp, L_mult(round_fx(tmp), msM_win)); + + /* scalar2: 4Q27 format */ + tmp = 1476395008l/*(float)MSSUBFRLEN-1.0 Q27*/; + move32(); + scalar2 = L_sub(tmp, L_mult(round_fx(tmp), msM_subwin)); + + FOR (j=start; jmsQeqInvAv[cnt] = QeqInvAv; + move32(); + + /* New minimum? */ + + /* exponent QeqInvAv: CNG_S, exponent MSAV: (4>>1) */ + s = CNG_S+2*MSAV_EXP; + move16(); + BminCorr = Mpy_32_16_1(Sqrt32(QeqInvAv, &s), MSAV); + BminCorr = L_shl(BminCorr,sub(s,1)); + + /* exponent BminCorr: 1 */ + BminCorr = L_add(BminCorr, 1073741824l/*0.5 Q31*/); + + FOR (j=start; jmsFrCnt,MSSUBFRLEN)) + { + FOR ( i = 0; i < 3; i++ ) + { + IF ( LT_32(st->msQeqInvAv[cnt],L_shr(L_deposit_h(msQeqInvAv_thresh[i]),CNG_S))/*0.0 Q31*/) + { + BREAK; + } + } + /* format 1Q30 */ + st->msSlope[cnt] = msNoiseSlopeMax[i]; + move32(); + } + + /* Consider the FFT and CLDFB bands separately */ + start = stop; + move16(); + stop = len; + move16(); + totsize = sub(st->stopBand,st->stopFFTbin); + cnt = add(cnt,1); + } /*while (stop > start)*/ + + /* Update minimum between sub windows */ + test(); + IF ( GT_16(st->msFrCnt,1)&<_16(st->msFrCnt,MSSUBFRLEN)) + { + FOR (j=0; j 0 ) + { + msLocalMinFlag[j] = 1; + move16(); + } + if ( LT_32(msCurrentMinSubWindow[j],msCurrentMinOut[j])/*0.0 Q31*/) + { + /* msCurrentMinOut[j] scaled with CNG_S */ + msCurrentMinOut[j] = msCurrentMinSubWindow[j]; + move32(); + } + } + /* Get the current noise floor */ + Copy_Scale_sig_32_16(msCurrentMinOut, msNoiseFloor, len, -16); + } + ELSE /* sub window complete */ + { + IF ( GE_16(st->msFrCnt,MSSUBFRLEN)) + { + /* Collect buffers */ + Copy32(msCurrentMinSubWindow, msMinBuf+len*st->msMinBufferPtr, len); + + /* Compute minimum among all buffers */ + Copy32(msMinBuf, msCurrentMinOut, len); + ptr = msMinBuf + len; + FOR (i=1; imsSlope[0]; + move16(); + FOR (j=0; jmsSlope[1]; + move16(); + } + test(); + test(); + test(); + IF ( ( msLocalMinFlag[j] != 0 ) + && ( msNewMinFlag[j] == 0 ) + && ( LT_32(L_shr(msCurrentMinSubWindow[j],1),Mpy_32_16_1(msCurrentMinOut[j],slope)) /*0.0 Q31*/ ) + && ( GT_32(msCurrentMinSubWindow[j],msCurrentMinOut[j]) /*0.0 Q31*/ ) + ) + { + msCurrentMinOut[j] = msCurrentMinSubWindow[j]; + move32(); + i = j; + move16(); + FOR (k=0; koffsetflag > 0 ) + { + Copy(msPeriodog, msPsd, len); + FOR (j=0; j < len; j++) + { + msCurrentMinOut[j] = L_deposit_h(msPeriodog[j]); + } + set32_fx(st->msAlphaCor, 2147483647l/*1.0 Q31*/, cnt); + set32_fx(msAlpha, 0l/*0.0 Q31*/, len); + Copy(msPeriodog, msPsdFirstMoment, len); + set32_fx(msPsdSecondMoment, 0l/*0.0 Q31*/, len); + + msPsdSum[0] = dotp_s_fx(msPeriodog, psize, lenFFT, CNG_HS); + move32(); + IF ( LT_16(lenFFT,len)) + { + msPsdSum[1] = dotp_s_fx(msPeriodog+lenFFT, psize+lenFFT, sub(len,lenFFT), CNG_HS); + move32(); + } + } + st->offsetflag = 1; + move16(); + } + ELSE + { + st->offsetflag = 0; + move16(); + } + + + /* Increment frame counter */ + IF ( EQ_16(st->msFrCnt,MSSUBFRLEN)) + { + st->msFrCnt = 1; + move16(); + st->msMinBufferPtr = add(st->msMinBufferPtr,1); + move16(); + if ( EQ_16(st->msMinBufferPtr,MSNUMSUBFR)) + { + st->msMinBufferPtr = 0; + move16(); + } + } + ELSE + { + st->msFrCnt = add(st->msFrCnt,1); + } + + /* Smooth noise estimate during CNG phases */ + FOR (j=0; j= 0/*0.0 Q15*/); + } + +} + + +/*********************************** +* Apply bitrate-dependant scale * +***********************************/ +void apply_scale(Word32 *scale, Word16 bwmode, Word32 bitrate) +{ + Word16 i; + Word16 scaleTableSize = sizeof (scaleTable) / sizeof (scaleTable[0]); + + + + FOR (i=0; i < scaleTableSize; i++) + { + cast16(); + IF ( s_and( (Word16)EQ_16(bwmode, (Word16)scaleTable[i].bwmode), + s_and( L_sub(bitrate,scaleTable[i].bitrateFrom) >= 0, + L_sub(bitrate,scaleTable[i].bitrateTo) < 0)) + ) + { + BREAK; + } + } + + { + *scale = L_add(*scale, L_deposit_h(scaleTable[i].scale)); + } + +} + + +/*************************************** +* Compute the power for each partition * +***************************************/ +void bandcombinepow(Word32* bandpow, /* i : Power for each band */ + Word16 exp_bandpow, /* i : exponent of bandpow */ + Word16 nband, /* i : Number of bands */ + Word16* part, /* i : Partition upper boundaries (band indices starting from 0) */ + Word16 npart, /* i : Number of partitions */ + Word16* psize_inv, /* i : Inverse partition sizes */ + Word32* partpow, /* o : Power for each partition */ + Word16* exp_partpow) +{ + + Word16 i, p; + Word32 temp; + Word16 smin, len, prev_part; + Word16 facTabExp[NPART_SHAPING]; + + + + IF (EQ_16(nband, npart)) + { + Copy32(bandpow, partpow, nband); + smin = 0; + move16(); + } + ELSE + { + /* Compute the power in each partition */ + prev_part = -1; + move16(); + FOR (p=0; p < npart; p++) + { + len = sub(part[p],prev_part); + facTabExp[p] = getScaleFactor32 (&bandpow[prev_part+1], len); + move16(); + prev_part = part[p]; + move16(); + } + + smin = WORD32_BITS-1; + move16(); + FOR (p=0; p < npart; p++) + { + smin = s_min(smin,facTabExp[p]); + } + + i = 0; + move16(); + FOR (p = 0; p < npart; p++) + { + /* Arithmetic averaging of power for all bins in partition */ + temp = 0; + move32(); + FOR ( ; i <= part[p]; i++) + { + temp = L_add(temp, Mpy_32_16_1(L_shl(bandpow[i],facTabExp[p]),psize_inv[p])); + } + partpow[p] = L_shr(temp,sub(facTabExp[p],smin)); + move32(); + } + + } + + *exp_partpow = sub(exp_bandpow,smin); + move16(); +} + + +/************************************ +* Scale partitions (with smoothing) * +************************************/ +void scalebands (Word32 *partpow, /* i : Power for each partition */ + Word16 *part, /* i : Partition upper boundaries (band indices starting from 0) */ + Word16 npart, /* i : Number of partitions */ + Word16 *midband, /* i : Central band of each partition */ + Word16 nFFTpart, /* i : Number of FFT partitions */ + Word16 nband, /* i : Number of bands */ + Word32 *bandpow, /* o : Power for each band */ + Word16 flag_fft_en + ) +{ + Word16 i, j, s, s1, nint, delta, delta_cmp, delta_s; + Word16 startBand, startPart, stopPart, stopPartM1; + Word32 tmp, val, partpowLD64, partpowLD64M1; + + + + j = 0; + move16(); + delta = 0; + move16(); + partpowLD64M1 = 0L; /* to avoid compilation warnings */ + + /* Interpolate the bin/band-wise levels from the partition levels */ + IF ( EQ_16(nband, npart)) + { + Copy32(partpow, bandpow, npart); + } + ELSE + { + startBand = 0; + move16(); + startPart = 0; + move16(); + stopPart = nFFTpart; + move16(); + + WHILE ( LT_16(startBand,nband)) + { + stopPartM1 = sub(stopPart, 1); + test(); + IF ( (flag_fft_en != 0) || (GE_16(startPart,nFFTpart))) + { + /* first half partition */ + j = startPart; + move16(); + + FOR (i=startBand; i <= midband[j]; i++) + { + bandpow[i] = partpow[j]; + move32(); + } + j = add(j, 1); + + /* inner partitions */ + IF (j < stopPart) + { + partpowLD64M1 = BASOP_Util_Log2(partpow[j-1]); + } + + /* Debug values to check this variable is set. */ + delta = 0x4000; + move16(); + delta_cmp = 0x4000; + move16(); + s1 = 1; + move16(); + s = 1; + move16(); + + FOR ( ; j < stopPart; j++) + { + nint = sub(midband[j], midband[j-1]); + + /* log-linear interpolation */ + partpowLD64 = BASOP_Util_Log2(partpow[j]); + tmp = L_sub(partpowLD64, partpowLD64M1); + tmp = Mpy_32_16_1(tmp, getNormReciprocalWord16(nint)); + + /* scale logarithmic value */ + tmp = L_sub(tmp, DELTA_SHIFT_LD64); + delta_s = DELTA_SHIFT; + move16(); + + WHILE (tmp > 0) + { + tmp = L_sub(tmp,33554432l/*0.015625 Q31*/); + delta_s = add(delta_s,1); + } + delta_cmp = shl(1, s_max(-15, sub(WORD16_BITS-1,delta_s))); + + tmp = BASOP_Util_InvLog2(tmp); + s = norm_l(tmp); + s1 = sub(delta_s, s); + + delta = round_fx(L_shl(tmp, s)); + + /* Choose scale such that the interpolation start and end point both are representable and add 1 additional bit hr. */ + delta_s = sub(s_min(norm_l(partpow[j-1]), norm_l(partpow[j])), 1); + val = L_shl(partpow[j-1], delta_s); + FOR ( ; i < midband[j]; i++) + { + val = L_shl(Mpy_32_16_1(val, delta), s1); + bandpow[i] = L_shr(val, delta_s); + move32(); + } + bandpow[i++] = partpow[j]; + move32(); + partpowLD64M1 = partpowLD64; + move32(); + } + + IF ( GT_16(shr(delta, s), delta_cmp)) + { + delta = 0x4000; + move16(); + s1 = 1; + move16(); + } + + /* last half partition */ + val = partpow[stopPartM1]; + move32(); + FOR ( ; i <= part[stopPartM1]; i++) + { + val = L_shl(Mpy_32_16_1(val,delta), s1); + bandpow[i] = val; + move32(); + } + + } + startBand = add(part[stopPartM1], 1); + startPart = stopPart; + move16(); + stopPart = npart; + move16(); + } + } + +} + + +/************************************** +* Get central band for each partition * +**************************************/ +void getmidbands(Word16* part, /* i : Partition upper boundaries (band indices starting from 0) */ + Word16 npart, /* i : Number of partitions */ + Word16* midband, /* o : Central band of each partition */ + Word16* psize, /* o : Partition sizes */ + Word16* psize_norm, /* o : Partition sizes, fractional values */ + Word16* psize_norm_exp, /* o : Exponent for fractional partition sizes */ + Word16* psize_inv) /* o : Inverse of partition sizes */ +{ + Word16 j, max_psize, shift; + + + max_psize = psize[0]; + move16(); + /* first half partition */ move16(); + midband[0] = part[0]; + psize[0] = add(part[0], 1); + move16(); + psize_inv[0] = getNormReciprocalWord16(psize[0]); + move16(); + /* inner partitions */ + FOR (j = 1; j < npart; j++) + { + midband[j] = shr(add(add(part[j-1], 1), part[j]), 1); + move16(); + psize[j] = sub(part[j], part[j-1]); + move16(); + psize_inv[j] = getNormReciprocalWord16(psize[j]); + move16(); + if(GT_16(psize[j], max_psize)) + { + max_psize = psize[j]; + move16(); + } + } + + shift = 9; + move16(); + *psize_norm_exp = sub(15, shift); + move16(); + FOR(j=0; j < npart; j++) + { + psize_norm[j] = shl(psize[j], shift); + move16(); + } + /* minimum_statistics needs fixed exponent of 6 */ + assert(norm_s(-max_psize) >= 9 ); +} + + +/* + AnalysisSTFT + + Parameters: + + timeDomainInput, i : pointer to time signal + fftBuffer, o : FFT bins + fftBufferExp, i : exponent of FFT bins + st i/o: FD_CNG structure containing all buffers and variables + + Function: + STFT analysis filterbank + + Returns: + void +*/ +void AnalysisSTFT (const Word16 *timeDomainInput, /* i : pointer to time signal */ + Word16 Q, + Word32 *fftBuffer, /* o : FFT bins */ + Word16 *fftBuffer_exp, /* i : exponent of FFT bins */ + HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing all buffers and variables */ + ) +{ + Word16 i, len; + Word16 len2; + const PWord16 *olapWin; + Word16 *olapBuffer; + + + + assert( (st->fftlen>>1) == st->frameSize); + + /* pointer inititialization */ + assert(st->olapBufferAna != NULL); + olapBuffer = st->olapBufferAna; + olapWin = st->olapWinAna; + + /* olapWin factor is scaled with one bit */ + *fftBuffer_exp = 1; + move16(); + len = sub(st->fftlen,st->frameSize); + assert(len <= 320); /* see size of olapBuffer */ + + /* Window the signal */ + len2 = shr(len,1); + FOR (i=0; i < len2; i++) + { + move32(); + move32(); + fftBuffer[i] = L_mult(olapBuffer[i], mult_r(olapWin[i].v.im, 23170/*1.4142135623730950488016887242097 Q14*/)); + fftBuffer[i+len2] = L_mult(olapBuffer[i+len2], mult_r(olapWin[len2-1-i].v.re, 23170/*1.4142135623730950488016887242097 Q14*/)); + } + len2 = shr(st->frameSize,1); + FOR (i=0; i fftlen, fftBuffer_exp, -1); + + FOR (i=0; i frameSize,len)+i], Q ); + move16(); + } + +} + + +/* + SynthesisSTFT + + Parameters: + + fftBuffer i : pointer to FFT bins + fftBufferExp i : exponent of FFT bins + timeDomainOutput o : pointer to time domain signal + timeDomainOutputExp o : pointer to exponent of time domain output + olapBuffer i/o : pointer to overlap buffer + olapWin i : pointer to overlap window + st i/o : pointer to FD_CNG structure containing all buffers and variables + + Function: + STFT synthesis filterbank + + Returns: + void +*/ +void +SynthesisSTFT (Word32 *fftBuffer, /* i : pointer to FFT bins */ + Word16 fftBufferExp, /* i : exponent of FFT bins */ + Word16 *timeDomainOutput, /* o : pointer to time domain signal */ + Word16 *olapBuffer, /* i/o : pointer to overlap buffer */ + const PWord16 *olapWin, /* i : pointer to overlap window */ + Word16 tcx_transition, + HANDLE_FD_CNG_COM st, /* i/o : pointer to FD_CNG structure containing all buffers and variables */ + Word16 gen_exc, + Word16 *Q_new + ) +{ + Word16 i, len, scale, tmp; + Word16 len2, len3, len4; + Word16 buf[M+1+L_FRAME16k]; + + + /* Perform IFFT */ + scale = 0; + BASOP_rfft(fftBuffer, st->fftlen, &scale, 1); + fftBufferExp = add(fftBufferExp, scale); + fftBufferExp = add(fftBufferExp, st->fftlenShift); + + /* Perform overlap-add */ + Copy(olapBuffer+st->frameSize, olapBuffer, st->frameSize); + set16_fx(olapBuffer+st->frameSize, 0, st->frameSize); + + len2 = shr(st->fftlen,2); + len4 = shr(st->fftlen,3); + len3 = add(len2,len4); + len = add(st->frameSize,len4); + IF ( tcx_transition ) + { + FOR (i=0; i < len; i++) + { + olapBuffer[i] = round_fx(L_shl(fftBuffer[i],fftBufferExp-15)); + } + } + ELSE + { + FOR (i=0; i < len4; i++) + { + olapBuffer[i+1*len4] = add(olapBuffer[i+1*len4], mult_r(round_fx(L_shl(fftBuffer[i+1*len4],fftBufferExp-15)),olapWin[i].v.im)); + move16(); + olapBuffer[i+2*len4] = add(olapBuffer[i+2*len4], mult_r(round_fx(L_shl(fftBuffer[i+2*len4],fftBufferExp-15)),olapWin[len4-1-i].v.re)); + move16(); + } + FOR (i=len3; i < len; i++) + { + olapBuffer[i] = round_fx(L_shl(fftBuffer[i],fftBufferExp-15)); + } + } + + FOR (i=0; i < len4; i++) + { + olapBuffer[i+5*len4] = mult_r(round_fx(L_shl(fftBuffer[i+5*len4],fftBufferExp-15)),olapWin[i].v.re); + move16(); + olapBuffer[i+6*len4] = mult_r(round_fx(L_shl(fftBuffer[i+6*len4],fftBufferExp-15)),olapWin[len4-1-i].v.im); + move16(); + } + + len = add( len, len2 ); + FOR (i=len; i < st->fftlen ; i++) + { + olapBuffer[i] = 0; + move16(); + } + + /* Get time-domain signal */ + FOR (i=0; i < st->frameSize; i++) + { + timeDomainOutput[i] = mult_r( olapBuffer[i+len4], st->fftlenFac ); + move16(); + } + + /* Generate excitation */ + IF ( EQ_16( gen_exc, 1 )) + { + FOR (i=0; i < M+1+st->frameSize; i++) + { + buf[i] = mult_r( olapBuffer[i+len4-M-1], st->fftlenFac ); + move16(); + } + tmp = buf[0]; + E_UTIL_f_preemph2( *Q_new-1, buf+1, PREEMPH_FAC, M+st->frameSize, &tmp ); + Residu3_fx( st->A_cng, buf+1+M, st->exc_cng, st->frameSize, 1 ); + } + IF ( EQ_16( gen_exc, 2 )) + { + FOR (i=0; i < M+1+st->frameSize; i++) + { + buf[i] = mult_r( olapBuffer[i+len4-M-1], st->fftlenFac ); + move16(); + } + tmp = buf[0]; + *Q_new = E_UTIL_f_preemph3( buf+1, PREEMPH_FAC, M+st->frameSize, &tmp, 1 ); + Residu3_fx( st->A_cng, buf+1+M, st->exc_cng, st->frameSize, 1 ); + } + +} + + +/************************************************************************************** +* Compute some values used in the bias correction of the minimum statistics algorithm * +**************************************************************************************/ +void mhvals(Word16 d, + Word16 * m /*, float * h*/ + ) +{ + Word16 i, j; + Word16 len = sizeof(d_array)/sizeof(Word16); + + + assert( d==72 || d==12); /* function only tested for d==72 and d==12) */ + i = 0; + move16(); + FOR (i=0 ; i < len ; i++) + { + IF (LE_16(d,d_array[i])) + { + BREAK; + } + } + IF (EQ_16(i, len)) + { + i = sub(len, 1); + j = i; + move16(); + } + ELSE + { + j = sub(i, 1); + } + IF (EQ_16(d, d_array[i])) + { + *m = m_array[i]; + move16(); + } + ELSE + { + Word32 qi_m, qj_m, q_m, tmp1_m, tmp2_m; + Word16 qi_e, qj_e, q_e, tmp1_e, tmp2_e, tmp1_w16_m, tmp1_w16_e, shift; + + + /* d_array has exponent 15 */ + qj_e = 15; + move16(); + qj_m = L_deposit_h(d_array[i-1]); + + qi_e = 15; + move16(); + qi_m = L_deposit_h(d_array[i]); + + q_e = 15; + move16(); + q_m = L_deposit_h(d); + + qj_m = Sqrt32(qj_m, &qj_e); + qi_m = Sqrt32(qi_m, &qi_e); + q_m = Sqrt32(q_m, &q_e); + + tmp1_m = Mpy_32_32(qi_m, qj_m); + tmp1_e = add(qi_e, qj_e); + tmp1_m = L_deposit_h(BASOP_Util_Divide3232_Scale(tmp1_m, q_m, &shift)); + tmp1_e = sub(tmp1_e, q_e); + tmp1_e = add(tmp1_e, shift); + tmp1_m = BASOP_Util_Add_Mant32Exp(tmp1_m, tmp1_e, L_negate(qj_m), qj_e, &tmp1_e); + + tmp2_m = BASOP_Util_Add_Mant32Exp (qi_m, qi_e, L_negate(qj_m), qj_e, &tmp2_e); + tmp1_w16_m = round_fx(tmp2_m); + tmp1_w16_e = tmp2_e; + move16(); + BASOP_Util_Divide_MantExp(sub(m_array[j], m_array[i]), 0, tmp1_w16_m, tmp1_w16_e, &tmp1_w16_m, &tmp1_w16_e); + + tmp2_m = Mpy_32_16_1(tmp1_m, tmp1_w16_m); + tmp2_e = add(tmp1_e, tmp1_w16_e); + + tmp2_m = BASOP_Util_Add_Mant32Exp (tmp2_m, tmp2_e, L_deposit_h(m_array[i]), 0, &tmp2_e); + assert(tmp2_e == 0); + *m = extract_h(tmp2_m); + } +} + + +/* + rand_gauss + + Parameters: + + seed i/o : pointer to seed + + Function: + Random generator with Gaussian distribution with mean 0 and std 1 + + Returns: + random signal format Q3.29 +*/ +Word32 rand_gauss (Word16 *seed) +{ + Word32 temp; + Word16 loc_seed; + + + + /* This unrolled version reduces the cycles from 17 to 10 */ + loc_seed = extract_l(L_mac0(13849, *seed, 31821)); + temp = L_deposit_l(loc_seed); + + loc_seed = extract_l(L_mac0(13849, loc_seed, 31821)); + temp = L_msu0(temp,loc_seed,-1); + + loc_seed = extract_l(L_mac0(13849, loc_seed, 31821)); + temp = L_msu0(temp,loc_seed,-1); + + *seed = loc_seed; + move16(); + return L_shl(temp,WORD16_BITS-CNG_RAND_GAUSS_SHIFT); +} + + +/* + lpc_from_spectrum + + Parameters: + + powspec i : pointer to noise levels format Q5.27 + start i : start band + stop i : stop band + fftlen i : size of fft + A o : lpc coefficients format Q3.12 + s i : lpc order + preemph_fac i : preemphase factor format Q1.15 + + + Function: + calculate lpc coefficients from the spectrum + + Returns: + void +*/ +void lpc_from_spectrum (Word32 *powspec, + Word16 powspec_exp, + Word16 start, + Word16 stop, + Word16 fftlen, + Word16 *A, + Word16 lpcorder, + Word16 preemph_fac + ) +{ + Word16 i, s1, s2, s3, fftlen2, scale, fftlen4, fftlen8, len, step, preemph_fac2; + Word32 maxVal, r[32], fftBuffer[FFTLEN], *ptr, *pti, nf; + Word16 tmp, r_h[32], r_l[32]; + const PWord16 *table; + + + + scale = 0; + move16(); + fftlen2 = shr(fftlen,1); + fftlen4 = shr(fftlen,2); + fftlen8 = shr(fftlen,3); + + /* Power Spectrum */ + maxVal = 0; + move32(); + len = sub(stop, start); + FOR (i=0; i < len; i++) + { + maxVal = L_max(maxVal, L_abs(powspec[i])); + } + s1 = norm_l(maxVal); + nf = L_shr_r(1099511680l/*1e-3f Q40*/,add(sub(powspec_exp,s1),9)); + + ptr = fftBuffer; + pti = fftBuffer+1; + + FOR (i=0; i < start; i++) + { + *ptr = nf; + move32(); + *pti = L_deposit_l(0); + ptr += 2; + pti += 2; + } + + FOR ( ; i < stop; i++ ) + { + *ptr = L_max( nf, L_shl(powspec[i-start], s1) ); + move32(); + *pti = L_deposit_l(0); + ptr += 2; + pti += 2; + } + + FOR ( ; i < fftlen2; i++ ) + { + *ptr = nf; + move32(); + *pti = L_deposit_l(0); + ptr += 2; + pti += 2; + } + + fftBuffer[1] = nf; + move32(); + + /* Pre-emphasis */ + + BASOP_getTables(&table, NULL, &step, fftlen4); + tmp = round_fx(L_shr(L_add(0x40000000, L_mult0(preemph_fac, preemph_fac)),1)); + preemph_fac2 = shr(preemph_fac,1); + ptr = fftBuffer; + *ptr = Mpy_32_16_1( *ptr, sub( tmp, preemph_fac2 ) ); + move32(); + ptr += 2; + FOR ( i = 1; i < fftlen8; i++ ) + { + move32(); + *ptr = Mpy_32_16_1( *ptr, sub( tmp, mult_r(preemph_fac2,add(shr(table[i-1].v.re,1),shr(table[i].v.re,1)) ) ) ); + ptr += 2; + } + move32(); + *ptr = Mpy_32_16_1( *ptr, sub( tmp, mult_r(preemph_fac2,add(shr(table[fftlen8-1].v.re,1),shr(table[fftlen8-1].v.im,1)) ) ) ); + ptr += 2; + FOR ( i = 1; i < fftlen8; i++ ) + { + move32(); + *ptr = Mpy_32_16_1( *ptr, sub( tmp, mult_r(preemph_fac2,add(shr(table[fftlen8-i-1].v.im,1),shr(table[fftlen8-i].v.im,1)) ) ) ); + ptr += 2; + } + move32(); + *ptr = Mpy_32_16_1( *ptr, tmp ); + ptr += 2; + FOR ( i = 1; i < fftlen8; i++ ) + { + move32(); + *ptr = Mpy_32_16_1( *ptr, add( tmp, mult_r(preemph_fac2,add(shr(table[i-1].v.im,1),shr(table[i].v.im,1)) ) ) ); + ptr += 2; + } + move32(); + *ptr = Mpy_32_16_1( *ptr, add( tmp, mult_r(preemph_fac2,add(shr(table[fftlen8-1].v.re,1),shr(table[fftlen8-1].v.im,1)) ) ) ); + ptr += 2; + FOR ( i = 1; i < fftlen8; i++ ) + { + move32(); + *ptr = Mpy_32_16_1( *ptr, add( tmp, mult_r(preemph_fac2,add(shr(table[fftlen8-i-1].v.re,1),shr(table[fftlen8-i].v.re,1)) ) ) ); + ptr += 2; + } + move32(); + fftBuffer[1] = Mpy_32_16_1( fftBuffer[1], add( tmp, preemph_fac2 ) ); + maxVal = 0; + move32(); + FOR (i=0; i < fftlen; i++) + { + maxVal = L_max(maxVal, L_abs(fftBuffer[i])); + } + s2 = norm_l(maxVal); + FOR (i=0; i < fftlen; i++) + { + fftBuffer[i] = L_shl( fftBuffer[i], s2 ); + move32(); + } + + /* Autocorrelation */ + + BASOP_rfft(fftBuffer, fftlen, &scale, 1); + + s3 = getScaleFactor32(fftBuffer, add(lpcorder,1)); + + FOR (i=0; i <= lpcorder; i++ ) + { + r[i] = L_shl(fftBuffer[i], s3); + move32(); + } + + r[0] = Mpy_32_32( r[0], 1074278656l/*1.0005f Q30*/ ); + move32(); + FOR (i=1; i <= lpcorder; i++ ) + { + r[i] = Mpy_32_32( r[i], 1073741824l/*1.f Q30*/ ); + move32(); + } + s3 = getScaleFactor32(r, add(lpcorder,1)); + + FOR (i=0; i <= lpcorder; i++ ) + { + r[i] = L_shl(r[i], s3); + move32(); + } + + FOR (i=0; i <= lpcorder; i++ ) + { + L_Extract(r[i], &r_h[i], &r_l[i]); + } + + /* LPC */ + + E_LPC_lev_dur(r_h, r_l, A, NULL, lpcorder, NULL); + +} + +/* + msvq_decoder + + Parameters: + + cb i : Codebook (indexed cb[stages][levels][p]) format Q9.7 + stages i : Number of stages + N i : Vector dimension + maxN i : Codebook vector dimension + Idx o : Indices + uq[] i : Quantized vector format Q9.7 + + + Function: + multi stage vector dequantisation + + Returns: + void +*/ +void msvq_decoder (const Word16 *const cb[], /* i : Codebook (indexed cb[*stages][levels][p]) */ + Word16 stages, /* i : Number of stages */ + Word16 N, /* i : Vector dimension */ + Word16 maxN, /* i : Codebook vector dimension */ + Word16 Idx[], /* i : Indices */ + Word16 *uq /* o : quantized vector */ + ) +{ + Word16 s, i, offset; + + + + offset = i_mult(Idx[0], maxN); + FOR (i=0; iA_cng, Aq+i*(M+1), M+1 ); + } + + E_LPC_a_lsp_conversion( Aq, lsp_new, lsp_old, M ); + + IF( first_CNG == 0 ) + { + Copy( lsp_old, lspCNG, M ); + } + FOR( i=0; iexc_cng, exc, L_frame ); + Copy( hs->exc_cng, exc2, L_frame ); + + IF( EQ_16(L_frame,L_FRAME)) + { + interp_code_5over2_fx( exc2, bwe_exc, L_frame ); + } + ELSE + { + interp_code_4over2_fx( exc2, bwe_exc, L_frame ); + } +} + diff --git a/lib_com/fft.c b/lib_com/fft.c new file mode 100644 index 0000000..9869909 --- /dev/null +++ b/lib_com/fft.c @@ -0,0 +1,2475 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "prot_fx.h" +#include "basop_util.h" +#include "rom_basop_util.h" +#include "options.h" +#include "stl.h" + +void fft16_with_cmplx_data( cmplx *pInp, Word16 bsacle); + +/** + * \brief Profiling / Precision results + * + * Profiling / Precision of complex valued FFTs: BASOP_cfft() + * + * WOPS BASOP Precision BASOP + * FFT5 87 16.96 + * FFT8 108 17.04 + * FFT10 194 16.70 + * FFT15 354 16.97 + * FFT16 288 16.62 + * FFT20 368 16.06 + * FFT30 828 16.80 + * FFT32 752 15.45 (cplx mult mit 3 mult und 3 add) + * FFT32 824 16.07 (cplx mult mit 4 mult und 2 add) + * FFT64 ( 8x 8) 3.129 15.16 + * FFT80 (10x 8) 4.385 15.55 + * FFT100 (20x 5) 6.518 15.65 + * FFT120 (15x 8) 7.029 15.38 + * FFT128 (16x 8) 6.777 15.28 + * FFT160 (20x 8) 9.033 14.95 + * FFT240 (30x 8) 14.961 15.49 + * FFT256 (32x 8) 14.905 14.61 (cplx mult mit 3 mult und 3 add) + * FFT256 (32x 8) 15.265 15.04 (cplx mult mit 4 mult und 2 add) + * FFT320 (20x16) 21.517 15.21 + * + * + * Profiling / Precision of real valued FFTs / iFFTs: BASOP_rfft() + * + * WOPS BASOP Precision BASOP + * rFFT40 955 15.68 + * rFFT64 1635 16.17 + * + * irFFT40 1116 15.36 + * irFFT64 1759 15.18 + * + */ + + +#define Mpy_32_xx Mpy_32_16_1 + +#define FFTC(x) WORD322WORD16((Word32)x) + +#define C31 (FFTC(0x91261468)) /* FL2WORD32( -0.86602540) -sqrt(3)/2 */ + +#define C51 (FFTC(0x79bc3854)) /* FL2WORD32( 0.95105652) */ +#define C52 (FFTC(0x9d839db0)) /* FL2WORD32(-1.53884180/2) */ +#define C53 (FFTC(0xd18053ce)) /* FL2WORD32(-0.36327126) */ +#define C54 (FFTC(0x478dde64)) /* FL2WORD32( 0.55901699) */ +#define C55 (FFTC(0xb0000001)) /* FL2WORD32(-1.25/2) */ + +#define C81 (FFTC(0x5a82799a)) /* FL2WORD32( 7.071067811865475e-1) */ +#define C82 (FFTC(0xa57d8666)) /* FL2WORD32(-7.071067811865475e-1) */ + +#define C161 (FFTC(0x5a82799a)) /* FL2WORD32( 7.071067811865475e-1) INV_SQRT2 */ +#define C162 (FFTC(0xa57d8666)) /* FL2WORD32(-7.071067811865475e-1) -INV_SQRT2 */ + +#define C163 (FFTC(0x7641af3d)) /* FL2WORD32( 9.238795325112867e-1) COS_PI_DIV8 */ +#define C164 (FFTC(0x89be50c3)) /* FL2WORD32(-9.238795325112867e-1) -COS_PI_DIV8 */ + +#define C165 (FFTC(0x30fbc54d)) /* FL2WORD32( 3.826834323650898e-1) COS_3PI_DIV8 */ +#define C166 (FFTC(0xcf043ab3)) /* FL2WORD32(-3.826834323650898e-1) -COS_3PI_DIV8 */ + + +#define cplxMpy4_8_0(re,im,a,b,c,d) re = L_shr(L_sub(Mpy_32_xx(a,c),Mpy_32_xx(b,d)),1); \ + im = L_shr(L_add(Mpy_32_xx(a,d),Mpy_32_xx(b,c)),1); + +#define cplxMpy4_8_1(re,im,a,b) re = L_shr(a,1); \ + im = L_shr(b,1); + + + + +/** + * \brief Function performs a complex 5-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR5 bits. + * + * WOPS with 32x16 bit multiplications: 88 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ +static void fft5_with_cmplx_data(cmplx *inp) +{ + cmplx x0,x1,x2,x3,x4; + cmplx y1,y2,y3,y4; + cmplx t; + + x0 = CL_shr(inp[0],SCALEFACTOR5); + x1 = CL_shr(inp[1],SCALEFACTOR5); + x2 = CL_shr(inp[2],SCALEFACTOR5); + x3 = CL_shr(inp[3],SCALEFACTOR5); + x4 = CL_shr(inp[4],SCALEFACTOR5); + + y1 = CL_add(x1,x4); + y4 = CL_sub(x1,x4); + y3 = CL_add(x2,x3); + y2 = CL_sub(x2,x3); + t = CL_scale_t(CL_sub(y1,y3),C54); + y1 = CL_add(y1,y3); + inp[0] = CL_add(x0,y1); + + /* Bit shift left because of the constant C55 which was scaled with the factor 0.5 because of the representation of + the values as fracts */ + y1 = CL_add(inp[0],(CL_shl(CL_scale_t(y1,C55),1))); + y3 = CL_sub(y1,t); + y1 = CL_add(y1,t); + + t = CL_scale_t(CL_add(y4,y2),C51); + /* Bit shift left because of the constant C55 which was scaled with the factor 0.5 because of the representation of + the values as fracts */ + y4 = CL_add(t,CL_shl(CL_scale_t(y4, C52),1)); + y2 = CL_add(t,CL_scale_t(y2,C53)); + + + /* combination */ + inp[1] = CL_msu_j(y1,y2); + inp[4] = CL_mac_j(y1,y2); + + inp[2] = CL_mac_j(y3,y4); + inp[3] = CL_msu_j(y3,y4); + +#if (WMOPS) + multiCounter[currCounter].CL_move += 5; +#endif + +} + +/** + * \brief Function performs a complex 8-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR8 bits. + * + * WOPS with 32x16 bit multiplications: 108 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ +static void fft8_with_cmplx_data(cmplx *inp) +{ + cmplx x0, x1, x2, x3, x4, x5, x6, x7; + cmplx s0, s1, s2, s3, s4, s5, s6, s7; + cmplx t0, t1, t2, t3, t4, t5, t6, t7; + + /* Pre-additions */ + x0 = CL_shr(inp[0], SCALEFACTOR8); + x1 = CL_shr(inp[1], SCALEFACTOR8); + x2 = CL_shr(inp[2], SCALEFACTOR8); + x3 = CL_shr(inp[3], SCALEFACTOR8); + x4 = CL_shr(inp[4], SCALEFACTOR8); + x5 = CL_shr(inp[5], SCALEFACTOR8); + x6 = CL_shr(inp[6], SCALEFACTOR8); + x7 = CL_shr(inp[7], SCALEFACTOR8); + + /* loops are unrolled */ + { + t0 = CL_add(x0,x4); + t1 = CL_sub(x0,x4); + + t2 = CL_add(x1,x5); + t3 = CL_sub(x1,x5); + + t4 = CL_add(x2,x6); + t5 = CL_sub(x2,x6); + + t6 = CL_add(x3,x7); + t7 = CL_sub(x3,x7); + } + + /* Pre-additions and core multiplications */ + + s0 = CL_add(t0, t4); + s2 = CL_sub(t0, t4); + + s4 = CL_mac_j(t1, t5); + s5 = CL_msu_j(t1, t5); + + s1 = CL_add(t2, t6); + s3 = CL_sub(t2, t6); + s3 = CL_mul_j(s3); + + t0 = CL_add(t3, t7); + t1 = CL_sub(t3, t7); + + s6 = CL_scale_t(CL_msu_j(t1, t0), C81); + s7 = CL_dscale_t(CL_swap_real_imag(CL_msu_j(t0, t1)), C81, C82); + + /* Post-additions */ + + inp[0] = CL_add(s0, s1); + inp[4] = CL_sub(s0, s1); + + inp[2] = CL_sub(s2, s3); + inp[6] = CL_add(s2, s3); + + inp[3] = CL_add(s4, s7); + inp[7] = CL_sub(s4, s7); + + inp[1] = CL_add(s5, s6); + inp[5] = CL_sub(s5, s6); +#if (WMOPS) + multiCounter[currCounter].CL_move += 8; +#endif + + +} + + +/** + * \brief Function performs a complex 10-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR10 bits. + * + * WOPS with 32x16 bit multiplications: 196 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ + +static void fft10_with_cmplx_data(cmplx *inp_data) +{ + cmplx r1,r2,r3,r4; + cmplx x0,x1,x2,x3,x4,t; + cmplx y[10]; + + /* FOR i=0 */ + { + x0 = CL_shr(inp_data[0],SCALEFACTOR10); + x1 = CL_shr(inp_data[2],SCALEFACTOR10); + x2 = CL_shr(inp_data[4],SCALEFACTOR10); + x3 = CL_shr(inp_data[6],SCALEFACTOR10); + x4 = CL_shr(inp_data[8],SCALEFACTOR10); + + r1 = CL_add(x3,x2); + r4 = CL_sub(x3,x2); + r3 = CL_add(x1,x4); + r2 = CL_sub(x1,x4); + t = CL_scale_t(CL_sub(r1,r3),C54); + r1 = CL_add(r1,r3); + y[0] = CL_add(x0,r1); + r1 = CL_add(y[0],(CL_shl(CL_scale_t(r1,C55),1))); + r3 = CL_sub(r1,t); + r1 = CL_add(r1,t); + t = CL_scale_t((CL_add(r4,r2)),C51); + r4 = CL_add(t,CL_shl(CL_scale_t(r4, C52),1)); + r2 = CL_add(t,CL_scale_t(r2,C53)); + + + y[2] = CL_msu_j(r1,r2); + y[8] = CL_mac_j(r1,r2); + y[4] = CL_mac_j(r3,r4); + y[6] = CL_msu_j(r3,r4); + } + /* FOR i=1 */ + { + x0 = CL_shr(inp_data[5],SCALEFACTOR10); + x1 = CL_shr(inp_data[1],SCALEFACTOR10); + x2 = CL_shr(inp_data[3],SCALEFACTOR10); + x3 = CL_shr(inp_data[7],SCALEFACTOR10); + x4 = CL_shr(inp_data[9],SCALEFACTOR10); + + r1 = CL_add(x1,x4); + r4 = CL_sub(x1,x4); + r3 = CL_add(x3,x2); + r2 = CL_sub(x3,x2); + t = CL_scale_t(CL_sub(r1,r3),C54); + r1 = CL_add(r1,r3); + y[1] = CL_add(x0,r1); + r1 = CL_add(y[1],(CL_shl(CL_scale_t(r1,C55),1))); + r3 = CL_sub(r1,t); + r1 = CL_add(r1,t); + t = CL_scale_t((CL_add(r4,r2)),C51); + r4 = CL_add(t,CL_shl(CL_scale_t(r4, C52),1)); + r2 = CL_add(t,CL_scale_t(r2,C53)); + + + y[3] = CL_msu_j(r1,r2); + y[9] = CL_mac_j(r1,r2); + y[5] = CL_mac_j(r3,r4); + y[7] = CL_msu_j(r3,r4); + } + + /* FOR i=0 */ + { + inp_data[0] = CL_add(y[0],y[1]); + inp_data[5] = CL_sub(y[0],y[1]); + } + /* FOR i=2 */ + { + inp_data[2] = CL_add(y[2],y[3]); + inp_data[7] = CL_sub(y[2],y[3]); + } + /* FOR i=4 */ + { + inp_data[4] = CL_add(y[4],y[5]); + inp_data[9] = CL_sub(y[4],y[5]); + } + /* FOR i=6 */ + { + inp_data[6] = CL_add(y[6],y[7]); + inp_data[1] = CL_sub(y[6],y[7]); + } + /* FOR i=8 */ + { + inp_data[8] = CL_add(y[8],y[9]); + inp_data[3] = CL_sub(y[8],y[9]); + } + +#if (WMOPS) + multiCounter[currCounter].CL_move += 10; +#endif + +} + + +/** + * \brief Function performs a complex 15-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR15 bits. + * + * WOPS with 32x16 bit multiplications: 354 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ + +static void fft15_with_cmplx_data(cmplx *inp_data) +{ + cmplx c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14; + cmplx c_z0,c_z1, c_z2, c_z3, c_z4, c_z5, c_z6, c_z7, c_z8, c_z9, c_z10, c_z11, c_z12, c_z13, c_z14; + cmplx c_y1,c_y2,c_y3,c_y4; + cmplx c_t; + + c0 = CL_shr(inp_data[ 0],SCALEFACTOR15); + c1 = CL_shr(inp_data[ 3],SCALEFACTOR15); + c2 = CL_shr(inp_data[ 6],SCALEFACTOR15); + c3 = CL_shr(inp_data[ 9],SCALEFACTOR15); + c4 = CL_shr(inp_data[12],SCALEFACTOR15); + c5 = CL_shr(inp_data[ 5],SCALEFACTOR15); + c6 = CL_shr(inp_data[ 8],SCALEFACTOR15); + c7 = CL_shr(inp_data[11],SCALEFACTOR15); + c8 = CL_shr(inp_data[14],SCALEFACTOR15); + c9 = CL_shr(inp_data[ 2],SCALEFACTOR15); + c10 = CL_shr(inp_data[10],SCALEFACTOR15); + c11 = CL_shr(inp_data[13],SCALEFACTOR15); + c12 = CL_shr(inp_data[ 1],SCALEFACTOR15); + c13 = CL_shr(inp_data[ 4],SCALEFACTOR15); + c14 = CL_shr(inp_data[ 7],SCALEFACTOR15); + + /* 1. FFT5 stage */ + c_y1 = CL_add(c1,c4); + c_y4 = CL_sub(c1,c4); + c_y3 = CL_add(c2,c3); + c_y2 = CL_sub(c2,c3); + c_t = CL_scale_t(CL_sub(c_y1,c_y3),C54); + c_y1 = CL_add(c_y1,c_y3); + c_z0 = CL_add(c0,c_y1); + c_y1 = CL_add(c_z0,(CL_shl(CL_scale_t(c_y1,C55),1))); + c_y3 = CL_sub(c_y1,c_t); + c_y1 = CL_add(c_y1,c_t); + c_t = CL_scale_t(CL_add(c_y4,c_y2),C51); + c_y4 = CL_add(c_t,CL_shl(CL_scale_t(c_y4,C52),1)); + c_y2 = CL_add(c_t,CL_scale_t(c_y2,C53)); + + /* combination */ + c_z1 = CL_msu_j(c_y1,c_y2); + c_z2 = CL_mac_j(c_y3,c_y4); + c_z3 = CL_msu_j(c_y3,c_y4); + c_z4 = CL_mac_j(c_y1,c_y2); + + + /* 2. FFT5 stage */ + c_y1 = CL_add(c6,c9); + c_y4 = CL_sub(c6,c9); + c_y3 = CL_add(c7,c8); + c_y2 = CL_sub(c7,c8); + c_t = CL_scale_t(CL_sub(c_y1,c_y3),C54); + c_y1 = CL_add(c_y1,c_y3); + c_z5 = CL_add(c5,c_y1); + c_y1 = CL_add(c_z5,(CL_shl(CL_scale_t(c_y1,C55),1))); + c_y3 = CL_sub(c_y1,c_t); + c_y1 = CL_add(c_y1,c_t); + c_t = CL_scale_t(CL_add(c_y4,c_y2),C51); + c_y4 = CL_add(c_t,CL_shl(CL_scale_t(c_y4,C52),1)); + c_y2 = CL_add(c_t,CL_scale_t(c_y2,C53)); + /* combination */ + c_z6 = CL_msu_j(c_y1,c_y2); + c_z7 = CL_mac_j(c_y3,c_y4); + c_z8 = CL_msu_j(c_y3,c_y4); + c_z9 = CL_mac_j(c_y1,c_y2); + + + /* 3. FFT5 stage */ + + c_y1 = CL_add(c11,c14); + c_y4 = CL_sub(c11,c14); + c_y3 = CL_add(c12,c13); + c_y2 = CL_sub(c12,c13); + c_t = CL_scale_t(CL_sub(c_y1,c_y3),C54); + c_y1 = CL_add(c_y1,c_y3); + c_z10 = CL_add(c10,c_y1); + c_y1 = CL_add(c_z10,(CL_shl(CL_scale_t(c_y1,C55),1))); + c_y3 = CL_sub(c_y1,c_t); + c_y1 = CL_add(c_y1,c_t); + c_t = CL_scale_t(CL_add(c_y4,c_y2),C51); + c_y4 = CL_add(c_t,CL_shl(CL_scale_t(c_y4,C52),1)); + c_y2 = CL_add(c_t,CL_scale_t(c_y2,C53)); + /* combination */ + c_z11 = CL_msu_j(c_y1,c_y2); + c_z12 = CL_mac_j(c_y3,c_y4); + c_z13 = CL_msu_j(c_y3,c_y4); + c_z14 = CL_mac_j(c_y1,c_y2); + + + + /* 1. FFT3 stage */ + + c_y1 = CL_add(c_z5,c_z10); + c_y2 = CL_scale_t(CL_sub(c_z5,c_z10),C31); + inp_data[0] = CL_add(c_z0,c_y1); + c_y1 = CL_sub(c_z0,CL_shr(c_y1,1)); + inp_data[10] = CL_mac_j(c_y1,c_y2); + inp_data[5] = CL_msu_j(c_y1,c_y2); + + /* 2. FFT3 stage */ + c_y1 = CL_add(c_z6,c_z11); + c_y2 = CL_scale_t(CL_sub(c_z6,c_z11),C31); + inp_data[6] = CL_add(c_z1,c_y1); + c_y1 = CL_sub(c_z1,CL_shr(c_y1,1)); + inp_data[1] = CL_mac_j(c_y1,c_y2); + inp_data[11] = CL_msu_j(c_y1,c_y2); + + /* 3. FFT3 stage */ + c_y1 = CL_add(c_z7,c_z12); + c_y2 = CL_scale_t(CL_sub(c_z7,c_z12),C31); + inp_data[12] = CL_add(c_z2,c_y1); + c_y1 = CL_sub(c_z2,CL_shr(c_y1,1)); + inp_data[7] = CL_mac_j(c_y1,c_y2); + inp_data[2] = CL_msu_j(c_y1,c_y2); + + + /* 4. FFT3 stage */ + c_y1 = CL_add(c_z8,c_z13); + c_y2 = CL_scale_t(CL_sub(c_z8,c_z13),C31); + inp_data[3] = CL_add(c_z3,c_y1); + c_y1 = CL_sub(c_z3,CL_shr(c_y1,1)); + inp_data[13] = CL_mac_j(c_y1,c_y2); + inp_data[8] = CL_msu_j(c_y1,c_y2); + + + /* 5. FFT3 stage */ + c_y1 = CL_add(c_z9,c_z14); + c_y2 = CL_scale_t(CL_sub(c_z9,c_z14),C31); + inp_data[9] = CL_add(c_z4,c_y1); + c_y1 = CL_sub(c_z4,CL_shr(c_y1,1)); + inp_data[4] = CL_mac_j(c_y1,c_y2); + inp_data[14] = CL_msu_j(c_y1,c_y2); + +#if (WMOPS) + multiCounter[currCounter].CL_move += 15; +#endif + +} + + +/** + * \brief Function performs a complex 16-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR16 bits. + * + * WOPS with 32x16 bit multiplications (scale on ): 288 cycles + * WOPS with 32x16 bit multiplications (scale off): 256 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ +void fft16(Word32 *re, Word32 *im, Word16 s, Word16 bScale) +{ + int i; + if ( s == 2 ) + { + fft16_with_cmplx_data( (cmplx *) re, bScale ); + } + else + { + cmplx inp_data[16]; + FOR(i=0; i<16; i++) + { + inp_data[i] = CL_form(re[s*i], im[s*i]); + } + fft16_with_cmplx_data(inp_data, bScale ); + FOR(i=0; i<16; i++) + { + re[s*i] = CL_Extract_real(inp_data[i]); + im[s*i] = CL_Extract_imag(inp_data[i]); + } + } +} + +void fft16_with_cmplx_data(cmplx *input, Word16 bScale ) +{ + cmplx x0, x1, x2, x3, temp; + cmplx t0,t2,t4,t6,t7; + cmplx y[16]; + + IF (bScale) + { + { + x0 = CL_shr(input[0],SCALEFACTOR16); + x1 = CL_shr(input[4],SCALEFACTOR16); + x2 = CL_shr(input[8],SCALEFACTOR16); + x3 = CL_shr(input[12],SCALEFACTOR16); + t0 = CL_add(x0,x2); + t2 = CL_sub(x0,x2); + t4 = CL_add(x1,x3); + t6 = CL_sub(x1,x3); + t6 = CL_mul_j(t6); + y[0] = CL_add(t0,t4); + y[1] = CL_sub(t2,t6); + y[2] = CL_sub(t0,t4); + y[3] = CL_add(t2,t6); + + + x0 = CL_shr(input[1],SCALEFACTOR16); + x1 = CL_shr(input[5],SCALEFACTOR16); + x2 = CL_shr(input[9],SCALEFACTOR16); + x3 = CL_shr(input[13],SCALEFACTOR16); + t0 = CL_add(x0,x2); + t2 = CL_sub(x0,x2); + t4 = CL_add(x1,x3); + t6 = CL_sub(x1,x3); + t6 = CL_mul_j(t6); + y[4] = CL_add(t0,t4); + y[5] = CL_sub(t2,t6); + y[6] = CL_sub(t0,t4); + y[7] = CL_add(t2,t6); + + + x0 = CL_shr(input[2],SCALEFACTOR16); + x1 = CL_shr(input[6],SCALEFACTOR16); + x2 = CL_shr(input[10],SCALEFACTOR16); + x3 = CL_shr(input[14],SCALEFACTOR16); + t0 = CL_add(x0,x2); + t2 = CL_sub(x0,x2); + t4 = CL_add(x1,x3); + t6 = CL_sub(x1,x3); + t6 = CL_mul_j(t6); + y[8] = CL_add(t0,t4); + y[9] = CL_sub(t2,t6); + y[10] = CL_sub(t4,t0); + y[10] = CL_mul_j(y[10]); + y[11] = CL_add(t2,t6); + + + x0 = CL_shr(input[3],SCALEFACTOR16); + x1 = CL_shr(input[7],SCALEFACTOR16); + x2 = CL_shr(input[11],SCALEFACTOR16); + x3 = CL_shr(input[15],SCALEFACTOR16); + t0 = CL_add(x0,x2); + t2 = CL_sub(x0,x2); + t4 = CL_add(x1,x3); + t6 = CL_sub(x1,x3); + t6 = CL_mul_j(t6); + y[12] = CL_add(t0,t4); + y[13] = CL_sub(t2,t6); + y[14] = CL_sub(t0,t4); + y[15] = CL_add(t2,t6); + } + } + else + { + { + t0 = CL_add(input[ 0],input[ 8]); + t2 = CL_sub(input[ 0],input[ 8]); + t4 = CL_add(input[ 4],input[12]); + t7 = CL_sub(input[ 4],input[12]); + + y[0] = CL_add(t0,t4); + y[1] = CL_msu_j(t2,t7); + y[2] = CL_sub(t0,t4); + y[3] = CL_mac_j(t2,t7); + } + /* i=1 */ + { + t0 = CL_add(input[ 1],input[ 9]); + t2 = CL_sub(input[ 1],input[ 9]); + t4 = CL_add(input[ 5],input[13]); + t7 = CL_sub(input[ 5],input[13]); + + y[4] = CL_add(t0,t4); + y[5] = CL_msu_j(t2,t7); + y[6] = CL_sub(t0,t4); + y[7] = CL_mac_j(t2,t7); + } + /* i=2 */ + { + t0 = CL_add(input[ 2],input[ 10]); + t2 = CL_sub(input[ 2],input[ 10]); + t4 = CL_add(input[ 6],input[14]); + t7 = CL_sub(input[ 6],input[14]); + + y[8] = CL_add(t0,t4); + y[9] = CL_msu_j(t2,t7); + temp = CL_sub(t0,t4); + y[10] = CL_negate(CL_mul_j(temp)); + y[11] = CL_mac_j(t2,t7); + } + /* i=3 */ + { + t0 = CL_add(input[ 3],input[ 11]); + t2 = CL_sub(input[ 3],input[ 11]); + t4 = CL_add(input[ 7],input[15]); + t7 = CL_sub(input[ 7],input[15]); + + y[12] = CL_add(t0,t4); + y[13] = CL_msu_j(t2,t7); + y[14] = CL_sub(t0,t4); + y[15] = CL_mac_j(t2,t7); + } + + } + + x0 = CL_scale_t(y[11],C162); + y[11] = CL_mac_j(x0,x0); + + x0 = CL_scale_t(y[14],C162); + y[14] = CL_mac_j(x0,x0); + + x0 = CL_scale_t(y[6],C161); + y[6] = CL_msu_j(x0,x0); + + x0 = CL_scale_t(y[9],C161); + y[9] = CL_msu_j(x0,x0); + + y[5] = CL_mac_j(CL_scale_t(y[5], C163), CL_scale_t(y[5], C166)); + y[7] = CL_mac_j(CL_scale_t(y[7], C165), CL_scale_t(y[7], C164)); + y[13] = CL_mac_j(CL_scale_t(y[13], C165), CL_scale_t(y[13], C164)); + y[15] = CL_mac_j(CL_scale_t(y[15], C164), CL_scale_t(y[15], C165)); + + + /* i=0 */ + { + t0 = CL_add(y[ 0],y[ 8]); + t2 = CL_sub(y[ 0],y[ 8]); + t4 = CL_add(y[ 4],y[12]); + t7 = CL_sub(y[ 4],y[12]); + + input[0] = CL_add(t0,t4); + input[4] = CL_msu_j(t2,t7); + input[8] = CL_sub(t0,t4); + input[12] = CL_mac_j(t2,t7); + } + /* i=1 */ + { + t0 = CL_add(y[ 1],y[ 9]); + t2 = CL_sub(y[ 1],y[ 9]); + t4 = CL_add(y[ 5],y[13]); + t7 = CL_sub(y[ 5],y[13]); + + input[1] = CL_add(t0,t4); + input[5] = CL_msu_j(t2,t7); + input[9] = CL_sub(t0,t4); + input[13] = CL_mac_j(t2,t7); + } + /* i=2 */ + { + t0 = CL_add(y[ 2],y[ 10]); + t2 = CL_sub(y[ 2],y[ 10]); + t4 = CL_add(y[ 6],y[14]); + t7 = CL_sub(y[ 6],y[14]); + + input[2] = CL_add(t0,t4); + input[6] = CL_msu_j(t2,t7); + input[10] = CL_sub(t0,t4); + input[14] = CL_mac_j(t2,t7); + } + /* i=3 */ + { + t0 = CL_add(y[ 3],y[ 11]); + t2 = CL_sub(y[ 3],y[ 11]); + t4 = CL_add(y[ 7],y[15]); + t7 = CL_sub(y[ 7],y[15]); + + input[3] = CL_add(t0,t4); + input[7] = CL_msu_j(t2,t7); + input[11] = CL_sub(t0,t4); + input[15] = CL_mac_j(t2,t7); + } +#if (WMOPS) + multiCounter[currCounter].CL_move += 16; +#endif + +} + + +/** + * \brief Function performs a complex 20-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR20 bits. + * + * WOPS with 32x16 bit multiplications: 432 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ +static void fft20_with_cmplx_data(cmplx *inp_data) +{ + cmplx r1,r2,r3,r4; + cmplx x0,x1,x2,x3,x4; + cmplx t,t0,t1,t2,t3; + cmplx y[20]; + cmplx *y0, *y1,*y2,*y3,*y4; + + y0 = y; + y1 = &y[4]; + y2 = &y[16]; + y3 = &y[8]; + y4 = &y[12]; + + { + x0 = CL_shr(inp_data[0],SCALEFACTOR20); + x1 = CL_shr(inp_data[16],SCALEFACTOR20); + x2 = CL_shr(inp_data[12],SCALEFACTOR20); + x3 = CL_shr(inp_data[8],SCALEFACTOR20); + x4 = CL_shr(inp_data[4],SCALEFACTOR20); + + r4 = CL_sub(x1,x4); + r2 = CL_sub(x2,x3); + r1 = CL_add(x1,x4); + r3 = CL_add(x2,x3); + t = CL_scale_t(CL_sub(r1,r3),C54); + r1 = CL_add(r1,r3); + y0[0] = CL_add(x0,r1); + r1 = CL_add(y0[0],(CL_shl(CL_scale_t(r1,C55),1))); + r3 = CL_sub(r1,t); + r1 = CL_add(r1,t); + t = CL_scale_t((CL_add(r4,r2)),C51); + r4 = CL_add(t,CL_shl(CL_scale_t(r4, C52),1)); + r2 = CL_add(t,CL_scale_t(r2,C53)); + + + y1[0] = CL_msu_j(r1,r2); + y2[0] = CL_mac_j(r1,r2); + y3[0] = CL_mac_j(r3,r4); + y4[0] = CL_msu_j(r3,r4); + } + { + x0 = CL_shr(inp_data[5],SCALEFACTOR20); + x1 = CL_shr(inp_data[1],SCALEFACTOR20); + x2 = CL_shr(inp_data[17],SCALEFACTOR20); + x3 = CL_shr(inp_data[13],SCALEFACTOR20); + x4 = CL_shr(inp_data[9],SCALEFACTOR20); + + r4 = CL_sub(x1,x4); + r2 = CL_sub(x2,x3); + r1 = CL_add(x1,x4); + r3 = CL_add(x2,x3); + t = CL_scale_t(CL_sub(r1,r3),C54); + r1 = CL_add(r1,r3); + y0[1] = CL_add(x0,r1); + r1 = CL_add(y0[1],(CL_shl(CL_scale_t(r1,C55),1))); + r3 = CL_sub(r1,t); + r1 = CL_add(r1,t); + t = CL_scale_t((CL_add(r4,r2)),C51); + r4 = CL_add(t,CL_shl(CL_scale_t(r4, C52),1)); + r2 = CL_add(t,CL_scale_t(r2,C53)); + + + y1[1] = CL_msu_j(r1,r2); + y2[1] = CL_mac_j(r1,r2); + y3[1] = CL_mac_j(r3,r4); + y4[1] = CL_msu_j(r3,r4); + } + { + x0 = CL_shr(inp_data[10],SCALEFACTOR20); + x1 = CL_shr(inp_data[6],SCALEFACTOR20); + x2 = CL_shr(inp_data[2],SCALEFACTOR20); + x3 = CL_shr(inp_data[18],SCALEFACTOR20); + x4 = CL_shr(inp_data[14],SCALEFACTOR20); + + r4 = CL_sub(x1,x4); + r2 = CL_sub(x2,x3); + r1 = CL_add(x1,x4); + r3 = CL_add(x2,x3); + t = CL_scale_t(CL_sub(r1,r3),C54); + r1 = CL_add(r1,r3); + y0[2] = CL_add(x0,r1); + r1 = CL_add(y0[2],(CL_shl(CL_scale_t(r1,C55),1))); + r3 = CL_sub(r1,t); + r1 = CL_add(r1,t); + t = CL_scale_t((CL_add(r4,r2)),C51); + r4 = CL_add(t,CL_shl(CL_scale_t(r4, C52),1)); + r2 = CL_add(t,CL_scale_t(r2,C53)); + + + y1[2] = CL_msu_j(r1,r2); + y2[2] = CL_mac_j(r1,r2); + y3[2] = CL_mac_j(r3,r4); + y4[2] = CL_msu_j(r3,r4); + } + { + x0 = CL_shr(inp_data[15],SCALEFACTOR20); + x1 = CL_shr(inp_data[11],SCALEFACTOR20); + x2 = CL_shr(inp_data[7],SCALEFACTOR20); + x3 = CL_shr(inp_data[3],SCALEFACTOR20); + x4 = CL_shr(inp_data[19],SCALEFACTOR20); + + r4 = CL_sub(x1,x4); + r2 = CL_sub(x2,x3); + r1 = CL_add(x1,x4); + r3 = CL_add(x2,x3); + t = CL_scale_t(CL_sub(r1,r3),C54); + r1 = CL_add(r1,r3); + y0[3] = CL_add(x0,r1); + r1 = CL_add(y0[3],(CL_shl(CL_scale_t(r1,C55),1))); + r3 = CL_sub(r1,t); + r1 = CL_add(r1,t); + t = CL_scale_t((CL_add(r4,r2)),C51); + r4 = CL_add(t,CL_shl(CL_scale_t(r4, C52),1)); + r2 = CL_add(t,CL_scale_t(r2,C53)); + + + y1[3] = CL_msu_j(r1,r2); + y2[3] = CL_mac_j(r1,r2); + y3[3] = CL_mac_j(r3,r4); + y4[3] = CL_msu_j(r3,r4); + } + + { + cmplx * ptr_y = y; + { + cmplx Cy0, Cy1, Cy2, Cy3; + + Cy0 = *ptr_y++; + Cy1 = *ptr_y++; + Cy2 = *ptr_y++; + Cy3 = *ptr_y++; + + /* Pre-additions */ + t0 = CL_add(Cy0,Cy2); + t1 = CL_sub(Cy0,Cy2); + t2 = CL_add(Cy1,Cy3); + t3 = CL_sub(Cy1,Cy3); + + + inp_data[0] = CL_add(t0,t2); + inp_data[5] = CL_msu_j(t1,t3); + inp_data[10] = CL_sub(t0,t2); + inp_data[15] = CL_mac_j(t1,t3); + } + + { + cmplx Cy0, Cy1, Cy2, Cy3; + + Cy0 = *ptr_y++; + Cy1 = *ptr_y++; + Cy2 = *ptr_y++; + Cy3 = *ptr_y++; + + /* Pre-additions */ + t0 = CL_add(Cy0,Cy2); + t1 = CL_sub(Cy0,Cy2); + t2 = CL_add(Cy1,Cy3); + t3 = CL_sub(Cy1,Cy3); + + + inp_data[4] = CL_add(t0,t2); + inp_data[9] = CL_msu_j(t1,t3); + inp_data[14] = CL_sub(t0,t2); + inp_data[19] = CL_mac_j(t1,t3); + } + + { + cmplx Cy0, Cy1, Cy2, Cy3; + + Cy0 = *ptr_y++; + Cy1 = *ptr_y++; + Cy2 = *ptr_y++; + Cy3 = *ptr_y++; + + /* Pre-additions */ + t0 = CL_add(Cy0,Cy2); + t1 = CL_sub(Cy0,Cy2); + t2 = CL_add(Cy1,Cy3); + t3 = CL_sub(Cy1,Cy3); + + + inp_data[8] = CL_add(t0,t2); + inp_data[13] = CL_msu_j(t1,t3); + inp_data[18] = CL_sub(t0,t2); + inp_data[3] = CL_mac_j(t1,t3); + } + + { + cmplx Cy0, Cy1, Cy2, Cy3; + + Cy0 = *ptr_y++; + Cy1 = *ptr_y++; + Cy2 = *ptr_y++; + Cy3 = *ptr_y++; + + /* Pre-additions */ + t0 = CL_add(Cy0,Cy2); + t1 = CL_sub(Cy0,Cy2); + t2 = CL_add(Cy1,Cy3); + t3 = CL_sub(Cy1,Cy3); + + inp_data[12] = CL_add(t0,t2); + inp_data[17] = CL_msu_j(t1,t3); + inp_data[2] = CL_sub(t0,t2); + inp_data[7] = CL_mac_j(t1,t3); + } + + { + cmplx Cy0, Cy1, Cy2, Cy3; + + Cy0 = *ptr_y++; + Cy1 = *ptr_y++; + Cy2 = *ptr_y++; + Cy3 = *ptr_y++; + + /* Pre-additions */ + t0 = CL_add(Cy0,Cy2); + t1 = CL_sub(Cy0,Cy2); + t2 = CL_add(Cy1,Cy3); + t3 = CL_sub(Cy1,Cy3); + + + inp_data[16] = CL_add(t0,t2); + inp_data[1] = CL_msu_j(t1,t3); + inp_data[6] = CL_sub(t0,t2); + inp_data[11] = CL_mac_j(t1,t3); + } + } +#if (WMOPS) + multiCounter[currCounter].CL_move += 20; +#endif + +} + + +/** + * \brief Function performs a complex 30-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR30 bits. + * + * WOPS with 32x16 bit multiplications: 828 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ + +static void fft30_with_cmplx_data(cmplx * inp) +{ + cmplx *l = &inp[0]; + cmplx *h = &inp[15]; + + cmplx z[30], y[15], x[15], rs1, rs2, rs3, rs4, t; + + /* 1. FFT15 stage */ + + x[0] = CL_shr(inp[0],SCALEFACTOR30_1); + x[1] = CL_shr(inp[18],SCALEFACTOR30_1); + x[2] = CL_shr(inp[6],SCALEFACTOR30_1); + x[3] = CL_shr(inp[24],SCALEFACTOR30_1); + x[4] = CL_shr(inp[12],SCALEFACTOR30_1); + + x[5] = CL_shr(inp[20],SCALEFACTOR30_1); + x[6] = CL_shr(inp[8],SCALEFACTOR30_1); + x[7] = CL_shr(inp[26],SCALEFACTOR30_1); + x[8] = CL_shr(inp[14],SCALEFACTOR30_1); + x[9] = CL_shr(inp[2],SCALEFACTOR30_1); + + x[10] = CL_shr(inp[10],SCALEFACTOR30_1); + x[11] = CL_shr(inp[28],SCALEFACTOR30_1); + x[12] = CL_shr(inp[16],SCALEFACTOR30_1); + x[13] = CL_shr(inp[4],SCALEFACTOR30_1); + x[14] = CL_shr(inp[22],SCALEFACTOR30_1); + + + /* 1. FFT5 stage */ + rs1 = CL_add(x[1],x[4]); + rs4 = CL_sub(x[1],x[4]); + rs3 = CL_add(x[2],x[3]); + rs2 = CL_sub(x[2],x[3]); + t = CL_scale_t(CL_sub(rs1,rs3),C54); + rs1 = CL_add(rs1,rs3); + y[0] = CL_add(x[0],rs1); + rs1 = CL_add(y[0],(CL_shl(CL_scale_t(rs1,C55),1))); + rs3 = CL_sub(rs1,t); + rs1 = CL_add(rs1,t); + t = CL_scale_t(CL_add(rs4,rs2),C51); + rs4 = CL_add(t,CL_shl(CL_scale_t(rs4, C52),1)); + rs2 = CL_add(t,CL_scale_t(rs2,C53)); + + /* combination */ + y[1] = CL_msu_j(rs1,rs2); + y[4] = CL_mac_j(rs1,rs2); + y[2] = CL_mac_j(rs3,rs4); + y[3] = CL_msu_j(rs3,rs4); + + + /* 2. FFT5 stage */ + rs1 = CL_add(x[6],x[9]); + rs4 = CL_sub(x[6],x[9]); + rs3 = CL_add(x[7],x[8]); + rs2 = CL_sub(x[7],x[8]); + t = CL_scale_t(CL_sub(rs1,rs3),C54); + rs1 = CL_add(rs1,rs3); + y[5] = CL_add(x[5],rs1); + rs1 = CL_add(y[5],(CL_shl(CL_scale_t(rs1,C55),1))); + rs3 = CL_sub(rs1,t); + rs1 = CL_add(rs1,t); + t = CL_scale_t(CL_add(rs4,rs2),C51); + rs4 = CL_add(t,CL_shl(CL_scale_t(rs4, C52),1)); + rs2 = CL_add(t,CL_scale_t(rs2,C53)); + + /* combination */ + y[6] = CL_msu_j(rs1,rs2); + y[9] = CL_mac_j(rs1,rs2); + y[7] = CL_mac_j(rs3,rs4); + y[8] = CL_msu_j(rs3,rs4); + + + /* 3. FFT5 stage */ + rs1 = CL_add(x[11],x[14]); + rs4 = CL_sub(x[11],x[14]); + rs3 = CL_add(x[12],x[13]); + rs2 = CL_sub(x[12],x[13]); + t = CL_scale_t(CL_sub(rs1,rs3),C54); + rs1 = CL_add(rs1,rs3); + y[10] = CL_add(x[10],rs1); + rs1 = CL_add(y[10],(CL_shl(CL_scale_t(rs1,C55),1))); + rs3 = CL_sub(rs1,t); + rs1 = CL_add(rs1,t); + t = CL_scale_t(CL_add(rs4,rs2),C51); + rs4 = CL_add(t,CL_shl(CL_scale_t(rs4, C52),1)); + rs2 = CL_add(t,CL_scale_t(rs2,C53)); + + /* combination */ + y[11] = CL_msu_j(rs1,rs2); + y[14] = CL_mac_j(rs1,rs2); + y[12] = CL_mac_j(rs3,rs4); + y[13] = CL_msu_j(rs3,rs4); + /*for (i=10; i<15; i++) + { + printf("%d,\t %d,\t",y[i].re, y[i].im); + } + printf("\n\n");*/ + + + /* 1. FFT3 stage */ + /* real part */ + rs1 = CL_add(y[5],y[10]); + rs2 = CL_scale_t(CL_sub(y[5],y[10]),C31); + z[0] = CL_add(y[0],rs1); + rs1 = CL_sub(y[0],CL_shr(rs1,1)); + + z[10] = CL_mac_j(rs1,rs2); + z[5] = CL_msu_j(rs1,rs2); + + /* 2. FFT3 stage */ + rs1 = CL_add(y[6],y[11]); + rs2 = CL_scale_t(CL_sub(y[6],y[11]),C31); + z[6] = CL_add(y[1],rs1); + rs1 = CL_sub(y[1],CL_shr(rs1,1)); + + z[1] = CL_mac_j(rs1,rs2); + z[11] = CL_msu_j(rs1,rs2); + + + /* 3. FFT3 stage */ + rs1 = CL_add(y[7],y[12]); + rs2 = CL_scale_t(CL_sub(y[7],y[12]),C31); + z[12] = CL_add(y[2],rs1); + rs1 = CL_sub(y[2],CL_shr(rs1,1)); + + z[7] = CL_mac_j(rs1,rs2); + z[2] = CL_msu_j(rs1,rs2); + + + /* 4. FFT3 stage */ + rs1 = CL_add(y[8],y[13]); + rs2 = CL_scale_t(CL_sub(y[8],y[13]),C31); + z[3] = CL_add(y[3],rs1); + rs1 = CL_sub(y[3],CL_shr(rs1,1)); + + z[13] = CL_mac_j(rs1,rs2); + z[8] = CL_msu_j(rs1,rs2); + + + /* 5. FFT3 stage */ + rs1 = CL_add(y[9],y[14]); + rs2 = CL_scale_t(CL_sub(y[9],y[14]),C31); + z[9] = CL_add(y[4],rs1); + rs1 = CL_sub(y[4],CL_shr(rs1,1)); + + z[4] = CL_mac_j(rs1,rs2); + z[14] = CL_msu_j(rs1,rs2); + + /*for (i=0; i<15; i++) + printf("%d,\t %d,\t",z[i].re, z[i].im); + printf("\n\n");*/ + + + /* 2. FFT15 stage */ + + x[0] = CL_shr(inp[15],SCALEFACTOR30_1); + x[1] = CL_shr(inp[3],SCALEFACTOR30_1); + x[2] = CL_shr(inp[21],SCALEFACTOR30_1); + x[3] = CL_shr(inp[9],SCALEFACTOR30_1); + x[4] = CL_shr(inp[27],SCALEFACTOR30_1); + + x[5] = CL_shr(inp[5],SCALEFACTOR30_1); + x[6] = CL_shr(inp[23],SCALEFACTOR30_1); + x[7] = CL_shr(inp[11],SCALEFACTOR30_1); + x[8] = CL_shr(inp[29],SCALEFACTOR30_1); + x[9] = CL_shr(inp[17],SCALEFACTOR30_1); + + x[10] = CL_shr(inp[25],SCALEFACTOR30_1); + x[11] = CL_shr(inp[13],SCALEFACTOR30_1); + x[12] = CL_shr(inp[1],SCALEFACTOR30_1); + x[13] = CL_shr(inp[19],SCALEFACTOR30_1); + x[14] = CL_shr(inp[7],SCALEFACTOR30_1); + + /* 1. FFT5 stage */ + rs1 = CL_add(x[1],x[4]); + rs4 = CL_sub(x[1],x[4]); + rs3 = CL_add(x[2],x[3]); + rs2 = CL_sub(x[2],x[3]); + t = CL_scale_t(CL_sub(rs1,rs3),C54); + rs1 = CL_add(rs1,rs3); + y[0] = CL_add(x[0],rs1); + rs1 = CL_add(y[0],(CL_shl(CL_scale_t(rs1,C55),1))); + rs3 = CL_sub(rs1,t); + rs1 = CL_add(rs1,t); + t = CL_scale_t(CL_add(rs4,rs2),C51); + rs4 = CL_add(t,CL_shl(CL_scale_t(rs4, C52),1)); + rs2 = CL_add(t,CL_scale_t(rs2,C53)); + + /* combination */ + y[1] = CL_msu_j(rs1,rs2); + y[4] = CL_mac_j(rs1,rs2); + y[2] = CL_mac_j(rs3,rs4); + y[3] = CL_msu_j(rs3,rs4); + + + /* 2. FFT5 stage */ + rs1 = CL_add(x[6],x[9]); + rs4 = CL_sub(x[6],x[9]); + rs3 = CL_add(x[7],x[8]); + rs2 = CL_sub(x[7],x[8]); + t = CL_scale_t(CL_sub(rs1,rs3),C54); + rs1 = CL_add(rs1,rs3); + y[5] = CL_add(x[5],rs1); + rs1 = CL_add(y[5],(CL_shl(CL_scale_t(rs1,C55),1))); + rs3 = CL_sub(rs1,t); + rs1 = CL_add(rs1,t); + t = CL_scale_t(CL_add(rs4,rs2),C51); + rs4 = CL_add(t,CL_shl(CL_scale_t(rs4, C52),1)); + rs2 = CL_add(t,CL_scale_t(rs2,C53)); + + /* combination */ + y[6] = CL_msu_j(rs1,rs2); + y[9] = CL_mac_j(rs1,rs2); + y[7] = CL_mac_j(rs3,rs4); + y[8] = CL_msu_j(rs3,rs4); + + + /* 3. FFT5 stage */ + rs1 = CL_add(x[11],x[14]); + rs4 = CL_sub(x[11],x[14]); + rs3 = CL_add(x[12],x[13]); + rs2 = CL_sub(x[12],x[13]); + t = CL_scale_t(CL_sub(rs1,rs3),C54); + rs1 = CL_add(rs1,rs3); + y[10] = CL_add(x[10],rs1); + rs1 = CL_add(y[10],(CL_shl(CL_scale_t(rs1,C55),1))); + rs3 = CL_sub(rs1,t); + rs1 = CL_add(rs1,t); + t = CL_scale_t(CL_add(rs4,rs2),C51); + rs4 = CL_add(t,CL_shl(CL_scale_t(rs4, C52),1)); + rs2 = CL_add(t,CL_scale_t(rs2,C53)); + + /* combination */ + y[11] = CL_msu_j(rs1,rs2); + y[14] = CL_mac_j(rs1,rs2); + y[12] = CL_mac_j(rs3,rs4); + y[13] = CL_msu_j(rs3,rs4); + /*for (i=10; i<15; i++) + { + printf("%d,\t %d,\t",y[i].re, y[i].im); + } + printf("\n\n");*/ + + + /* 1. FFT3 stage */ + /* real part */ + rs1 = CL_add(y[5],y[10]); + rs2 = CL_scale_t(CL_sub(y[5],y[10]),C31); + z[15] = CL_add(y[0],rs1); + rs1 = CL_sub(y[0],CL_shr(rs1,1)); + + z[25] = CL_mac_j(rs1,rs2); + z[20] = CL_msu_j(rs1,rs2); + + /* 2. FFT3 stage */ + rs1 = CL_add(y[6],y[11]); + rs2 = CL_scale_t(CL_sub(y[6],y[11]),C31); + z[21] = CL_add(y[1],rs1); + rs1 = CL_sub(y[1],CL_shr(rs1,1)); + + z[16] = CL_mac_j(rs1,rs2); + z[26] = CL_msu_j(rs1,rs2); + + + /* 3. FFT3 stage */ + rs1 = CL_add(y[7],y[12]); + rs2 = CL_scale_t(CL_sub(y[7],y[12]),C31); + z[27] = CL_add(y[2],rs1); + rs1 = CL_sub(y[2],CL_shr(rs1,1)); + + z[22] = CL_mac_j(rs1,rs2); + z[17] = CL_msu_j(rs1,rs2); + + + /* 4. FFT3 stage */ + rs1 = CL_add(y[8],y[13]); + rs2 = CL_scale_t(CL_sub(y[8],y[13]),C31); + z[18] = CL_add(y[3],rs1); + rs1 = CL_sub(y[3],CL_shr(rs1,1)); + + z[28] = CL_mac_j(rs1,rs2); + z[23] = CL_msu_j(rs1,rs2); + + + /* 5. FFT3 stage */ + rs1 = CL_add(y[9],y[14]); + rs2 = CL_scale_t(CL_sub(y[9],y[14]),C31); + z[24] = CL_add(y[4],rs1); + rs1 = CL_sub(y[4],CL_shr(rs1,1)); + + z[19] = CL_mac_j(rs1,rs2); + z[29] = CL_msu_j(rs1,rs2); + + /*for (i=0; i<30; i++) + printf("%d,\t %d,\t",z[i].re, z[i].im); + printf("\n\n");*/ + + + /* 1. FFT2 stage */ + rs1 = CL_shr(z[0], SCALEFACTOR30_2); + rs2 = CL_shr(z[15],SCALEFACTOR30_2); + *l = CL_add(rs1,rs2); + *h = CL_sub(rs1,rs2); + l+=1; h+=1; + + /* 2. FFT2 stage */ + rs1 = CL_shr(z[8], SCALEFACTOR30_2); + rs2 = CL_shr(z[23],SCALEFACTOR30_2); + *h = CL_add(rs1,rs2); + *l = CL_sub(rs1,rs2); + l+=1; h+=1; + + + /* 3. FFT2 stage */ + rs1 = CL_shr(z[1], SCALEFACTOR30_2); + rs2 = CL_shr(z[16],SCALEFACTOR30_2); + *l = CL_add(rs1,rs2); + *h = CL_sub(rs1,rs2); + l+=1; h+=1; + + + /* 4. FFT2 stage */ + rs1 = CL_shr(z[9], SCALEFACTOR30_2); + rs2 = CL_shr(z[24],SCALEFACTOR30_2); + *h = CL_add(rs1,rs2); + *l = CL_sub(rs1,rs2); + l+=1; h+=1; + + /* 5. FFT2 stage */ + rs1 = CL_shr(z[2], SCALEFACTOR30_2); + rs2 = CL_shr(z[17],SCALEFACTOR30_2); + *l = CL_add(rs1,rs2); + *h = CL_sub(rs1,rs2); + l+=1; h+=1; + + /* 6. FFT2 stage */ + rs1 = CL_shr(z[10], SCALEFACTOR30_2); + rs2 = CL_shr(z[25],SCALEFACTOR30_2); + *h = CL_add(rs1,rs2); + *l = CL_sub(rs1,rs2); + l+=1; h+=1; + + /* 7. FFT2 stage */ + rs1 = CL_shr(z[3], SCALEFACTOR30_2); + rs2 = CL_shr(z[18],SCALEFACTOR30_2); + *l = CL_add(rs1,rs2); + *h = CL_sub(rs1,rs2); + l+=1; h+=1; + + /* 8. FFT2 stage */ + rs1 = CL_shr(z[11], SCALEFACTOR30_2); + rs2 = CL_shr(z[26],SCALEFACTOR30_2); + *h = CL_add(rs1,rs2); + *l = CL_sub(rs1,rs2); + l+=1; h+=1; + + /* 9. FFT2 stage */ + rs1 = CL_shr(z[4], SCALEFACTOR30_2); + rs2 = CL_shr(z[19],SCALEFACTOR30_2); + *l = CL_add(rs1,rs2); + *h = CL_sub(rs1,rs2); + l+=1; h+=1; + + /* 10. FFT2 stage */ + rs1 = CL_shr(z[12], SCALEFACTOR30_2); + rs2 = CL_shr(z[27],SCALEFACTOR30_2); + *h = CL_add(rs1,rs2); + *l = CL_sub(rs1,rs2); + l+=1; h+=1; + + /* 11. FFT2 stage */ + rs1 = CL_shr(z[5], SCALEFACTOR30_2); + rs2 = CL_shr(z[20],SCALEFACTOR30_2); + *l = CL_add(rs1,rs2); + *h = CL_sub(rs1,rs2); + l+=1; h+=1; + + /* 12. FFT2 stage */ + rs1 = CL_shr(z[13], SCALEFACTOR30_2); + rs2 = CL_shr(z[28],SCALEFACTOR30_2); + *h = CL_add(rs1,rs2); + *l = CL_sub(rs1,rs2); + l+=1; h+=1; + + /* 13. FFT2 stage */ + rs1 = CL_shr(z[6], SCALEFACTOR30_2); + rs2 = CL_shr(z[21],SCALEFACTOR30_2); + *l = CL_add(rs1,rs2); + *h = CL_sub(rs1,rs2); + l+=1; h+=1; + + /* 14. FFT2 stage */ + rs1 = CL_shr(z[14], SCALEFACTOR30_2); + rs2 = CL_shr(z[29],SCALEFACTOR30_2); + *h = CL_add(rs1,rs2); + *l = CL_sub(rs1,rs2); + l+=1; h+=1; + + /* 15. FFT2 stage */ + rs1 = CL_shr(z[7], SCALEFACTOR30_2); + rs2 = CL_shr(z[22],SCALEFACTOR30_2); + *l = CL_add(rs1,rs2); + *h = CL_sub(rs1,rs2); + l+=1; h+=1; + +#if (WMOPS) + multiCounter[currCounter].CL_move += 30; +#endif + +} + +/** + * \brief Function performs a complex 32-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR32 bits. + * + * WOPS with 32x16 bit multiplications: 752 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ + + +static void fft32_with_cmplx_data(cmplx * inp) +{ + cmplx x[32], y[32], t[32], s[32], temp, temp1; + const cmplx_s *pRotVector_32 = ( const cmplx_s *)RotVector_32; + + /* 1. FFT8 stage */ + + x[0] = CL_shr(inp[0], SCALEFACTOR32_1); + x[1] = CL_shr(inp[4], SCALEFACTOR32_1); + x[2] = CL_shr(inp[8], SCALEFACTOR32_1); + x[3] = CL_shr(inp[12], SCALEFACTOR32_1); + x[4] = CL_shr(inp[16], SCALEFACTOR32_1); + x[5] = CL_shr(inp[20], SCALEFACTOR32_1); + x[6] = CL_shr(inp[24], SCALEFACTOR32_1); + x[7] = CL_shr(inp[28], SCALEFACTOR32_1); + + + t[0] = CL_add(x[0],x[4]); + t[1] = CL_sub(x[0],x[4]); + t[2] = CL_add(x[1],x[5]); + t[3] = CL_sub(x[1],x[5]); + t[4] = CL_add(x[2],x[6]); + t[5] = CL_sub(x[2],x[6]); + t[6] = CL_add(x[3],x[7]); + t[7] = CL_sub(x[3],x[7]); + + /* Pre-additions and core multiplications */ + + s[0] = CL_add(t[0], t[4]); + s[2] = CL_sub(t[0], t[4]); + s[4] = CL_mac_j(t[1], t[5]); + s[5] = CL_msu_j(t[1], t[5]); + s[1] = CL_add(t[2], t[6]); + s[3] = CL_sub(t[2], t[6]); + s[3] = CL_mul_j(s[3]); + + temp = CL_add(t[3], t[7]); + temp1 = CL_sub(t[3], t[7]); + s[6] = CL_scale_t(CL_msu_j(temp1, temp), C81); + s[7] = CL_dscale_t(CL_swap_real_imag( CL_msu_j(temp, temp1)), C81, C82); + + + y[0] = CL_add(s[0],s[1]); + y[4] = CL_sub(s[0],s[1]); + y[2] = CL_sub(s[2],s[3]); + y[6] = CL_add(s[2],s[3]); + y[3] = CL_add(s[4],s[7]); + y[7] = CL_sub(s[4],s[7]); + y[1] = CL_add(s[5],s[6]); + y[5] = CL_sub(s[5],s[6]); + + /* 2. FFT8 stage */ + + x[0] = CL_shr(inp[1], SCALEFACTOR32_1); + x[1] = CL_shr(inp[5], SCALEFACTOR32_1); + x[2] = CL_shr(inp[9], SCALEFACTOR32_1); + x[3] = CL_shr(inp[13], SCALEFACTOR32_1); + x[4] = CL_shr(inp[17], SCALEFACTOR32_1); + x[5] = CL_shr(inp[21], SCALEFACTOR32_1); + x[6] = CL_shr(inp[25], SCALEFACTOR32_1); + x[7] = CL_shr(inp[29], SCALEFACTOR32_1); + + + t[0] = CL_add(x[0],x[4]); + t[1] = CL_sub(x[0],x[4]); + t[2] = CL_add(x[1],x[5]); + t[3] = CL_sub(x[1],x[5]); + t[4] = CL_add(x[2],x[6]); + t[5] = CL_sub(x[2],x[6]); + t[6] = CL_add(x[3],x[7]); + t[7] = CL_sub(x[3],x[7]); + + /* Pre-additions and core multiplications */ + + s[0] = CL_add(t[0], t[4]); + s[2] = CL_sub(t[0], t[4]); + s[4] = CL_mac_j(t[1], t[5]); + s[5] = CL_msu_j(t[1], t[5]); + s[1] = CL_add(t[2], t[6]); + s[3] = CL_sub(t[2], t[6]); + s[3] = CL_mul_j(s[3]); + + temp = CL_add(t[3], t[7]); + temp1 = CL_sub(t[3], t[7]); + s[6] = CL_scale_t(CL_msu_j(temp1, temp), C81); + s[7] = CL_dscale_t(CL_swap_real_imag( CL_msu_j(temp, temp1)), C81, C82); + + /* Post-additions */ + + y[8] = CL_add(s[0],s[1]); + y[12] = CL_sub(s[0],s[1]); + y[10] = CL_sub(s[2],s[3]); + y[14] = CL_add(s[2],s[3]); + y[11] = CL_add(s[4],s[7]); + y[15] = CL_sub(s[4],s[7]); + y[9] = CL_add(s[5],s[6]); + y[13] = CL_sub(s[5],s[6]); + + /* 3. FFT8 stage */ + + x[0] = CL_shr(inp[2], SCALEFACTOR32_1); + x[1] = CL_shr(inp[6], SCALEFACTOR32_1); + x[2] = CL_shr(inp[10], SCALEFACTOR32_1); + x[3] = CL_shr(inp[14], SCALEFACTOR32_1); + x[4] = CL_shr(inp[18], SCALEFACTOR32_1); + x[5] = CL_shr(inp[22], SCALEFACTOR32_1); + x[6] = CL_shr(inp[26], SCALEFACTOR32_1); + x[7] = CL_shr(inp[30], SCALEFACTOR32_1); + + + t[0] = CL_add(x[0],x[4]); + t[1] = CL_sub(x[0],x[4]); + t[2] = CL_add(x[1],x[5]); + t[3] = CL_sub(x[1],x[5]); + t[4] = CL_add(x[2],x[6]); + t[5] = CL_sub(x[2],x[6]); + t[6] = CL_add(x[3],x[7]); + t[7] = CL_sub(x[3],x[7]); + + /* Pre-additions and core multiplications */ + + s[0] = CL_add(t[0], t[4]); + s[2] = CL_sub(t[0], t[4]); + s[4] = CL_mac_j(t[1], t[5]); + s[5] = CL_msu_j(t[1], t[5]); + s[1] = CL_add(t[2], t[6]); + s[3] = CL_sub(t[2], t[6]); + s[3] = CL_mul_j(s[3]); + + temp = CL_add(t[3], t[7]); + temp1 = CL_sub(t[3], t[7]); + s[6] = CL_scale_t(CL_msu_j(temp1, temp), C81); + s[7] = CL_dscale_t(CL_swap_real_imag( CL_msu_j(temp, temp1)), C81, C82); + + /* Post-additions */ + + y[16] = CL_add(s[0],s[1]); + y[20] = CL_sub(s[0],s[1]); + y[18] = CL_sub(s[2],s[3]); + y[22] = CL_add(s[2],s[3]); + y[19] = CL_add(s[4],s[7]); + y[23] = CL_sub(s[4],s[7]); + y[17] = CL_add(s[5],s[6]); + y[21] = CL_sub(s[5],s[6]); + + /* 4. FFT8 stage */ + + x[0] = CL_shr(inp[3], SCALEFACTOR32_1); + x[1] = CL_shr(inp[7], SCALEFACTOR32_1); + x[2] = CL_shr(inp[11], SCALEFACTOR32_1); + x[3] = CL_shr(inp[15], SCALEFACTOR32_1); + x[4] = CL_shr(inp[19], SCALEFACTOR32_1); + x[5] = CL_shr(inp[23], SCALEFACTOR32_1); + x[6] = CL_shr(inp[27], SCALEFACTOR32_1); + x[7] = CL_shr(inp[31], SCALEFACTOR32_1); + + + t[0] = CL_add(x[0],x[4]); + t[1] = CL_sub(x[0],x[4]); + t[2] = CL_add(x[1],x[5]); + t[3] = CL_sub(x[1],x[5]); + t[4] = CL_add(x[2],x[6]); + t[5] = CL_sub(x[2],x[6]); + t[6] = CL_add(x[3],x[7]); + t[7] = CL_sub(x[3],x[7]); + + + /* Pre-additions and core multiplications */ + + s[0] = CL_add(t[0], t[4]); + s[2] = CL_sub(t[0], t[4]); + s[4] = CL_mac_j(t[1], t[5]); + s[5] = CL_msu_j(t[1], t[5]); + s[1] = CL_add(t[2], t[6]); + s[3] = CL_sub(t[2], t[6]); + s[3] = CL_mul_j(s[3]); + + temp = CL_add(t[3], t[7]); + temp1 = CL_sub(t[3], t[7]); + s[6] = CL_scale_t(CL_msu_j(temp1, temp), C81); + s[7] = CL_dscale_t(CL_swap_real_imag( CL_msu_j(temp, temp1)), C81, C82); + + /* Post-additions */ + + y[24] = CL_add(s[0],s[1]); + y[28] = CL_sub(s[0],s[1]); + y[26] = CL_sub(s[2],s[3]); + y[30] = CL_add(s[2],s[3]); + y[27] = CL_add(s[4],s[7]); + y[31] = CL_sub(s[4],s[7]); + y[25] = CL_add(s[5],s[6]); + y[29] = CL_sub(s[5],s[6]); + + + /* apply twiddle factors */ + y[0] = CL_shr(y[0],SCALEFACTOR32_2); + y[1] = CL_shr(y[1],SCALEFACTOR32_2); + y[2] = CL_shr(y[2],SCALEFACTOR32_2); + y[3] = CL_shr(y[3],SCALEFACTOR32_2); + y[4] = CL_shr(y[4],SCALEFACTOR32_2); + y[5] = CL_shr(y[5],SCALEFACTOR32_2); + y[6] = CL_shr(y[6],SCALEFACTOR32_2); + y[7] = CL_shr(y[7],SCALEFACTOR32_2); + y[8] = CL_shr(y[8],SCALEFACTOR32_2); + y[16] = CL_shr(y[16],SCALEFACTOR32_2); + y[24] = CL_shr(y[24],SCALEFACTOR32_2); + y[20] = CL_shr(y[20],SCALEFACTOR32_2); + + + y[9] = CL_mult_32x16((CL_shr(y[9],1)), pRotVector_32[ 0 ]); + y[10] = CL_mult_32x16((CL_shr(y[10],1)), pRotVector_32[ 1 ]); + y[11] = CL_mult_32x16((CL_shr(y[11],1)), pRotVector_32[ 2 ]); + y[12] = CL_mult_32x16((CL_shr(y[12],1)), pRotVector_32[ 3 ]); + y[13] = CL_mult_32x16((CL_shr(y[13],1)), pRotVector_32[ 4 ]); + y[14] = CL_mult_32x16((CL_shr(y[14],1)), pRotVector_32[ 5 ]); + y[15] = CL_mult_32x16((CL_shr(y[15],1)), pRotVector_32[ 6 ]); + y[17] = CL_mult_32x16((CL_shr(y[17],1)), pRotVector_32[ 7 ]); + y[18] = CL_mult_32x16((CL_shr(y[18],1)), pRotVector_32[ 8 ]); + y[19] = CL_mult_32x16((CL_shr(y[19],1)), pRotVector_32[ 9 ]); + y[21] = CL_mult_32x16((CL_shr(y[21],1)), pRotVector_32[ 10 ]); + y[22] = CL_mult_32x16((CL_shr(y[22],1)), pRotVector_32[ 11 ]); + y[23] = CL_mult_32x16((CL_shr(y[23],1)), pRotVector_32[ 12 ]); + y[25] = CL_mult_32x16((CL_shr(y[25],1)), pRotVector_32[ 13 ]); + y[26] = CL_mult_32x16((CL_shr(y[26],1)), pRotVector_32[ 14 ]); + y[27] = CL_mult_32x16((CL_shr(y[27],1)), pRotVector_32[ 15 ]); + y[28] = CL_mult_32x16((CL_shr(y[28],1)), pRotVector_32[ 16 ]); + y[29] = CL_mult_32x16((CL_shr(y[29],1)), pRotVector_32[ 17 ]); + y[30] = CL_mult_32x16((CL_shr(y[30],1)), pRotVector_32[ 18 ]); + y[31] = CL_mult_32x16((CL_shr(y[31],1)), pRotVector_32[ 19 ]); + + /* 1. FFT4 stage */ + + /* Pre-additions */ + t[0] = CL_add(y[0],y[16]); + t[1] = CL_sub(y[0],y[16]); + t[2] = CL_add(y[8],y[24]); + t[3] = CL_mul_j(CL_sub(y[8],y[24])); + + /* Post-additions */ + inp[0] = CL_add(t[0], t[2]); + inp[8] = CL_sub(t[1], t[3]); + inp[16] = CL_sub(t[0], t[2]); + inp[24] = CL_add(t[1], t[3]); + + /* 2. FFT4 stage */ + + /* Pre-additions */ + t[0] = CL_add(y[1],y[17]); + t[1] = CL_sub(y[1],y[17]); + t[2] = CL_add(y[9],y[25]); + t[3] = CL_mul_j(CL_sub(y[9],y[25])); + + /* Post-additions */ + inp[1] = CL_add(t[0], t[2]); + inp[9] = CL_sub(t[1], t[3]); + inp[17] = CL_sub(t[0], t[2]); + inp[25] = CL_add(t[1], t[3]); + + + /* 3. FFT4 stage */ + + /* Pre-additions */ + t[0] = CL_add(y[2],y[18]); + t[1] = CL_sub(y[2],y[18]); + t[2] = CL_add(y[10],y[26]); + t[3] = CL_mul_j(CL_sub(y[10],y[26])); + + /* Post-additions */ + inp[2] = CL_add(t[0], t[2]); + inp[10] = CL_sub(t[1], t[3]); + inp[18] = CL_sub(t[0], t[2]); + inp[26] = CL_add(t[1], t[3]); + + + /* 4. FFT4 stage */ + + /* Pre-additions */ + t[0] = CL_add(y[3],y[19]); + t[1] = CL_sub(y[3],y[19]); + t[2] = CL_add(y[11],y[27]); + t[3] = CL_mul_j(CL_sub(y[11],y[27])); + + + /* Post-additions */ + inp[3] = CL_add(t[0], t[2]); + inp[11] = CL_sub(t[1], t[3]); + inp[19] = CL_sub(t[0], t[2]); + inp[27] = CL_add(t[1], t[3]); + + + /* 5. FFT4 stage */ + + /* Pre-additions */ + t[0] = CL_msu_j(y[4],y[20]); + t[1] = CL_mac_j(y[4],y[20]); + t[2] = CL_add(y[12],y[28]); + t[3] = CL_mul_j(CL_sub(y[12],y[28])); + + + /* Post-additions */ + inp[4] = CL_add(t[0], t[2]); + inp[12] = CL_sub(t[1], t[3]); + inp[20] = CL_sub(t[0], t[2]); + inp[28] = CL_add(t[1], t[3]); + + + /* 6. FFT4 stage */ + + /* Pre-additions */ + t[0] = CL_add(y[5],y[21]); + t[1] = CL_sub(y[5],y[21]); + t[2] = CL_add(y[13],y[29]); + t[3] = CL_mul_j(CL_sub(y[13],y[29])); + + + /* Post-additions */ + inp[5] = CL_add(t[0], t[2]); + inp[13] = CL_sub(t[1], t[3]); + inp[21] = CL_sub(t[0], t[2]); + inp[29] = CL_add(t[1], t[3]); + + + /* 7. FFT4 stage */ + + /* Pre-additions */ + t[0] = CL_add(y[6],y[22]); + t[1] = CL_sub(y[6],y[22]); + t[2] = CL_add(y[14],y[30]); + t[3] = CL_mul_j(CL_sub(y[14],y[30])); + + + /* Post-additions */ + inp[6] = CL_add(t[0], t[2]); + inp[14] = CL_sub(t[1], t[3]); + inp[22] = CL_sub(t[0], t[2]); + inp[30] = CL_add(t[1], t[3]); + + + /* 8. FFT4 stage */ + + /* Pre-additions */ + t[0] = CL_add(y[7],y[23]); + t[1] = CL_sub(y[7],y[23]); + t[2] = CL_add(y[15],y[31]); + t[3] = CL_mul_j(CL_sub(y[15],y[31])); + + + /* Post-additions */ + inp[7] = CL_add(t[0], t[2]); + inp[15] = CL_sub(t[1], t[3]); + inp[23] = CL_sub(t[0], t[2]); + inp[31] = CL_add(t[1], t[3]); + +#if (WMOPS) + multiCounter[currCounter].CL_move += 32; +#endif + + +} + + +/** + * \brief Combined FFT + * + * \param [i/o] re real part + * \param [i/o] im imag part + * \param [i ] W rotation factor + * \param [i ] len length of fft + * \param [i ] dim1 length of fft1 + * \param [i ] dim2 length of fft2 + * \param [i ] sx stride real and imag part + * \param [i ] sc stride phase rotation coefficients + * \param [tmp] x 32-bit workbuffer of length=2*len + * \param [i ] Woff offset for addressing the rotation vector table + * + * \return void + */ + +static void fftN2( + cmplx *__restrict pComplexBuf, + const Word16 *__restrict W, + Word16 len, + Word16 dim1, + Word16 dim2, + Word16 sc, + Word32 *x, + Word16 Woff +) +{ + Word16 i, j; + cmplx *x_cmplx = (cmplx *)x; + + assert(len == (dim1*dim2)); + assert((dim1 == 3) || (dim1 == 5) || (dim1 == 8) || (dim1 == 10) || (dim1 == 15) || (dim1 == 16) || (dim1 == 20) || (dim1 == 30) || (dim1 == 32)); + assert((dim2 == 4) || (dim2 == 8) || (dim2 == 10) || (dim2 == 12) || (dim2 == 16) || (dim2 == 20)); + + FOR(i = 0; i + +/*-----------------------------------------------------------------* +* Local functions +*-----------------------------------------------------------------*/ + +#define FFT3_ONE_THIRD 21845 /* 1/3 in Q16 */ + +static void fft5_shift4_16fx( Word16 n1, Word16 *zRe, Word16 *zIm, const Word16 *Idx ); +static void fft64_16fx( Word16 *x, Word16 *y, const Word16 *Idx ); +static void fft32_5_16fx( Word16 *x, Word16 *y, const Word16 *Idx ); +static void cftmdl_16fx(Word16 n, Word16 l, Word16 *a, const Word32 *w); +static void cftfsub_16fx( Word16 n, Word16 *a, const Word32 *w ); +static void cft1st_16fx(Word16 n, Word16 *a, const Word32 *w); +static void cftmdl_16fx(Word16 n, Word16 l, Word16 *a, const Word32 *w); +static void fft5_shift4_16fx( Word16 n1, Word16 *zRe, Word16 *zIm, const Word16 *Idx ); +static void bitrv2_SR_16fx( Word16 n, const Word16 *ip, Word16 *a ); +static void fft64_16fx( Word16 *x, Word16 *y, const Word16 *Idx ); +static void fft5_32_16fx( Word16 *zRe, Word16 *zIm, const Word16 *Idx ); +static void cdftForw_16fx( Word16 n, Word16 *a, const Word16 *ip, const Word32 *w ); + +#include "math_32.h" + +/*-----------------------------------------------------------------* +* Local functions +*-----------------------------------------------------------------*/ +static void cdftForw_fx( Word16 n, Word32 *a, const Word16 *ip, const Word16 *w ); +static void bitrv2_SR_fx( Word16 n, const Word16 *ip, Word32 *a ); +static void cftfsub_fx( Word16 n, Word32 *a, const Word16 *w ); +static void cft1st_fx( Word16 n, Word32 *a, const Word16 *w ); +static void cftmdl_fx( Word16 n, Word16 l, Word32 *a, const Word16 *w ); + + +void DoRTFTn_fx( + Word32 *x, /* i/o : real part of input and output data */ + Word32 *y, /* i/o : imaginary part of input and output data */ + const Word16 n /* i : size of the FFT up to 1024 */ +) +{ + + Word16 i; + Word32 z[2048], *pt; + + pt = z; + FOR ( i=0; i=1 ; i--) + { + x[i]=*pt++; + move16(); + y[i]=*pt++; + move16(); + } + + return; +} + +/*-----------------------------------------------------------------* + * cdftForw_fx() + * Main fuction of Complex Discrete Fourier Transform + *-----------------------------------------------------------------*/ +static void cdftForw_fx( + Word16 n, /* i : data length of real and imag */ + Word32 *a, /* i/o : input/output data Q(q)*/ + const Word16 *ip, /* i : work area for bit reversal */ + const Word16 *w /* i : cos/sin table Q14*/ +) +{ + /* bit reversal */ + bitrv2_SR_fx(n, ip + 2, a); + + /* Do FFT */ + cftfsub_fx(n, a, w); +} + +/*-----------------------------------------------------------------* + * bitrv2_SR_fx() + * Bit reversal + *-----------------------------------------------------------------*/ +static void bitrv2_SR_fx( + Word16 n, /* i : data length of real and imag */ + const Word16 *ip, /* i/o : work area for bit reversal */ + Word32 *a /* i/o : input/output data Q(q)*/ +) +{ + Word16 j, j1, k, k1, m, m2; + Word16 l; + Word32 xr, xi, yr, yi; + + l = n; + move16(); + m = 1; + move16(); + + WHILE (shl(m, 3) < l) + { + l = shr(l, 1); + m = shl(m, 1); + } + + m2 = shl(m, 1); + IF (shl(m, 3) == l) + { + FOR (k = 0; k < m; k++) + { + FOR (j = 0; j < k; j++) + { + j1 = add(shl(j, 1), ip[k]); + k1 = add(shl(k, 1), ip[j]); + xr = a[j1]; move32(); + xi = a[j1 + 1]; move32(); + yr = a[k1]; move32(); + yi = a[k1 + 1]; move32(); + a[j1] = yr; + move32(); + a[j1 + 1] = yi; + move32(); + a[k1] = xr; + move32(); + a[k1 + 1] = xi; + move32(); + j1 = add(j1, m2); + k1 = add(k1, shl(m2, 1)); + xr = a[j1]; move32(); + xi = a[j1 + 1]; move32(); + yr = a[k1]; move32(); + yi = a[k1 + 1]; move32(); + a[j1] = yr; + move32(); + a[j1 + 1] = yi; + move32(); + a[k1] = xr; + move32(); + a[k1 + 1] = xi; + move32(); + j1 = add(j1, m2); + k1 = sub(k1, m2); + xr = a[j1]; move32(); + xi = a[j1 + 1]; move32(); + xi = a[j1 + 1]; move32(); + yr = a[k1]; move32(); + yi = a[k1 + 1]; move32(); + a[j1] = yr; + move32(); + a[j1 + 1] = yi; + move32(); + a[k1] = xr; + move32(); + a[k1 + 1] = xi; + move32(); + j1 = add(j1, m2); + k1 = add(k1, shl(m2, 1)); + xr = a[j1]; move32(); + xi = a[j1 + 1]; move32(); + yr = a[k1]; move32(); + yi = a[k1 + 1]; move32(); + a[j1] = yr; + move32(); + a[j1 + 1] = yi; + move32(); + a[k1] = xr; + move32(); + a[k1 + 1] = xi; + move32(); + } + + j1 = add(add(shl(k, 1), m2), ip[k]); + k1 = add(j1, m2); + xr = a[j1]; move32(); + xi = a[j1 + 1]; move32(); + yr = a[k1]; move32(); + yi = a[k1 + 1]; move32(); + a[j1] = yr; + move32(); + a[j1 + 1] = yi; + move32(); + a[k1] = xr; + move32(); + a[k1 + 1] = xi; + move32(); + } + } + ELSE + { + FOR (k = 1; k < m; k++) + { + FOR (j = 0; j < k; j++) + { + j1 = add(shl(j, 1), ip[k]); + k1 = add(shl(k, 1), ip[j]); + xr = a[j1]; move32(); + xi = a[j1 + 1]; move32(); + yr = a[k1]; move32(); + yi = a[k1 + 1]; move32(); + a[j1] = yr; + move32(); + a[j1 + 1] = yi; + move32(); + a[k1] = xr; + move32(); + a[k1 + 1] = xi; + move32(); + j1 = add(j1, m2); + k1 = add(k1, m2); + xr = a[j1]; move32(); + xi = a[j1 + 1]; move32(); + yr = a[k1]; move32(); + yi = a[k1 + 1]; move32(); + a[j1] = yr; + move32(); + a[j1 + 1] = yi; + move32(); + a[k1] = xr; + move32(); + a[k1 + 1] = xi; + move32(); + } + } + } + + return; +} + +/*-----------------------------------------------------------------* + * cftfsub_fx() + * Complex Discrete Fourier Transform + *-----------------------------------------------------------------*/ +static void cftfsub_fx( + Word16 n, /* i : data length of real and imag */ + Word32 *a, /* i/o : input/output data Q(q)*/ + const Word16 *w /* i : cos/sin table Q14*/ +) +{ + Word16 j, j1, j2, j3, l; + Word32 x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + l = 2; + move16(); + + IF (n > 8) + { + cft1st_fx(n, a, w); + l = 8; + move16(); + WHILE ((shl(l, 2) < n)) + { + cftmdl_fx(n, l, a, w); + l = shl(l, 2); + } + } + IF (shl(l, 2) == n) + { + FOR (j = 0; j < l; j += 2) + { + j1 = add(j, l); + j2 = add(j1, l); + j3 = add(j2, l); + x0r = L_add(a[j], a[j1]); + x0i = L_add(a[j + 1], a[j1 + 1]); + x1r = L_sub(a[j], a[j1]); + x1i = L_sub(a[j + 1], a[j1 + 1]); + x2r = L_add(a[j2], a[j3]); + x2i = L_add(a[j2 + 1], a[j3 + 1]); + x3r = L_sub(a[j2], a[j3]); + x3i = L_sub(a[j2 + 1], a[j3 + 1]); + a[j] = L_add(x0r, x2r); + move32(); + a[j2] = L_sub(x0r, x2r); + move32(); + a[j + 1] = L_add(x0i, x2i); + move32(); + a[j2 + 1] = L_sub(x0i, x2i); + move32(); + a[j1] = L_sub(x1r, x3i); + move32(); + a[j1 + 1] = L_add(x1i, x3r); + move32(); + a[j3] = L_add(x1r, x3i); + move32(); + a[j3 + 1] = L_sub(x1i, x3r); + move32(); + } + } + ELSE + { + FOR (j = 0; j < l; j += 2) + { + j1 = add(j, l); + x0r = L_sub(a[j], a[j1]); + x0i = L_sub(a[j + 1], a[j1 + 1]); + a[j] = L_add(a[j], a[j1]); + move32(); + a[j + 1] = L_add(a[j + 1], a[j1 + 1]); + move32(); + a[j1] = x0r; + move32(); + move32(); + a[j1 + 1] = x0i; + move32(); + move32(); + } + } + + return; +} + +/*-----------------------------------------------------------------* + * cft1st_fx() + * Subfunction of Complex Discrete Fourier Transform + *-----------------------------------------------------------------*/ +static void cft1st_fx( + Word16 n, /* i : data length of real and imag */ + Word32 *a, /* i/o : input/output data Q(q)*/ + const Word16 *w /* i : cos/sin table Q14*/ +) +{ + Word16 j, k1, k2; + Word16 wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; + Word32 x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + x0r = L_add(a[0], a[2]); + x0i = L_add(a[1], a[3]); + x1r = L_sub(a[0], a[2]); + x1i = L_sub(a[1], a[3]); + x2r = L_add(a[4], a[6]); + x2i = L_add(a[5], a[7]); + x3r = L_sub(a[4], a[6]); + x3i = L_sub(a[5], a[7]); + a[0] = L_add(x0r, x2r); + move32(); + a[1] = L_add(x0i, x2i); + move32(); + a[4] = L_sub(x0r, x2r); + move32(); + a[5] = L_sub(x0i, x2i); + move32(); + a[2] = L_sub(x1r, x3i); + move32(); + a[3] = L_add(x1i, x3r); + move32(); + a[6] = L_add(x1r, x3i); + move32(); + a[7] = L_sub(x1i, x3r); + move32(); + + wk1r = w[2]; + move16(); + x0r = L_add(a[8], a[10]); + x0i = L_add(a[9], a[11]); + x1r = L_sub(a[8], a[10]); + x1i = L_sub(a[9], a[11]); + x2r = L_add(a[12], a[14]); + x2i = L_add(a[13], a[15]); + x3r = L_sub(a[12], a[14]); + x3i = L_sub(a[13], a[15]); + a[8] = L_add(x0r, x2r); + move32(); + a[9] = L_add(x0i, x2i); + move32(); + a[12] = L_sub(x2i, x0i); + move32(); + a[13] = L_sub(x0r, x2r); + move32(); + + x0r = L_sub(x1r, x3i); + x0i = L_add(x1i ,x3r); + a[10] = Mult_32_16(L_shl(L_sub(x0r, x0i), 1), wk1r); + move32(); + a[11] = Mult_32_16(L_shl(L_add(x0r, x0i), 1), wk1r); + move32(); + x0r = L_add(x3i, x1r); + x0i = L_sub(x3r,x1i); + a[14] = Mult_32_16(L_shl(L_sub(x0i, x0r), 1), wk1r); + move32(); + a[15] = Mult_32_16(L_shl(L_add(x0i, x0r), 1), wk1r); + move32(); + + k1 = 0; + move16(); + FOR (j = 16; j < n; j += 16) + { + k1 = add(k1, 2); + k2 = shl(k1, 1); + wk2r = w[k1]; + move16(); + wk2i = w[k1 + 1]; + move16(); + wk1r = w[k2]; + move16(); + wk1i = w[k2 + 1]; + move16(); + wk3r = extract_l(L_sub(L_deposit_l(wk1r), L_shr(L_mult(wk2i, wk1i), 14))); + wk3i = extract_l(L_msu0(L_shr(L_mult(wk2i, wk1r), 14), wk1i, 1)); + x0r = L_add(a[j], a[j + 2]); + x0i = L_add(a[j + 1], a[j + 3]); + x1r = L_sub(a[j], a[j + 2]); + x1i = L_sub(a[j + 1], a[j + 3]); + x2r = L_add(a[j + 4], a[j + 6]); + x2i = L_add(a[j + 5], a[j + 7]); + x3r = L_sub(a[j + 4], a[j + 6]); + x3i = L_sub(a[j + 5], a[j + 7]); + a[j] = L_add(x0r, x2r); + move32(); + a[j + 1] = L_add(x0i, x2i); + move32(); + x0r = L_sub(x0r, x2r); + x0i = L_sub(x0i, x2i); + a[j + 4] = L_sub(Mult_32_16(L_shl(x0r, 1), wk2r), Mult_32_16(L_shl(x0i, 1), wk2i)); + move32(); + a[j + 5] = L_add(Mult_32_16(L_shl(x0i, 1), wk2r), Mult_32_16(L_shl(x0r, 1), wk2i)); + move32(); + x0r = L_sub(x1r, x3i); + x0i = L_add(x1i, x3r); + a[j + 2] = L_sub(Mult_32_16(L_shl(x0r, 1), wk1r), Mult_32_16(L_shl(x0i, 1), wk1i)); + move32(); + a[j + 3] = L_add(Mult_32_16(L_shl(x0i, 1), wk1r), Mult_32_16(L_shl(x0r, 1), wk1i)); + move32(); + x0r = L_add(x1r, x3i); + x0i = L_sub(x1i, x3r); + a[j + 6] = L_sub(Mult_32_16(L_shl(x0r, 1), wk3r), Mult_32_16(L_shl(x0i, 1), wk3i)); + move32(); + a[j + 7] = L_add(Mult_32_16(L_shl(x0i, 1), wk3r), Mult_32_16(L_shl(x0r, 1), wk3i)); + move32(); + + wk1r = w[k2 + 2]; + move16(); + wk1i = w[k2 + 3]; + move16(); + wk3r = extract_l(L_sub(L_deposit_l(wk1r), L_shr(L_mult(wk2r, wk1i), 14))); + wk3i = extract_l(L_msu0(L_shr(L_mult(wk2r, wk1r), 14), wk1i, 1)); + x0r = L_add(a[j + 8], a[j + 10]); + x0i = L_add(a[j + 9], a[j + 11]); + x1r = L_sub(a[j + 8], a[j + 10]); + x1i = L_sub(a[j + 9], a[j + 11]); + x2r = L_add(a[j + 12], a[j + 14]); + x2i = L_add(a[j + 13], a[j + 15]); + x3r = L_sub(a[j + 12], a[j + 14]); + x3i = L_sub(a[j + 13], a[j + 15]); + a[j + 8] = L_add(x0r, x2r); + move32(); + a[j + 9] = L_add(x0i, x2i); + move32(); + x0r = L_sub(x0r, x2r); + x0i = L_sub(x0i, x2i); + a[j + 12] = L_negate(L_add(Mult_32_16(L_shl(x0r, 1), wk2i), Mult_32_16(L_shl(x0i, 1), wk2r))); + move32(); + a[j + 13] = L_sub(Mult_32_16(L_shl(x0r, 1), wk2r), Mult_32_16(L_shl(x0i, 1), wk2i)); + move32(); + x0r = L_sub(x1r, x3i); + x0i = L_add(x1i, x3r); + a[j + 10] = L_sub(Mult_32_16(L_shl(x0r, 1), wk1r), Mult_32_16(L_shl(x0i, 1), wk1i)); + move32(); + a[j + 11] = L_add(Mult_32_16(L_shl(x0i, 1), wk1r), Mult_32_16(L_shl(x0r, 1), wk1i)); + move32(); + x0r =L_add(x1r, x3i); + x0i =L_sub(x1i, x3r); + a[j + 14] = L_sub(Mult_32_16(L_shl(x0r, 1), wk3r), Mult_32_16(L_shl(x0i, 1), wk3i)); + move32(); + a[j + 15] = L_add(Mult_32_16(L_shl(x0i, 1), wk3r), Mult_32_16(L_shl(x0r, 1), wk3i)); + move32(); + } + + return; +} + +/*-----------------------------------------------------------------* + * cftmdl_fx() + * Subfunction of Complex Discrete Fourier Transform + *-----------------------------------------------------------------*/ +static void cftmdl_fx( + Word16 n, /* i : data length of real and imag */ + Word16 l, /* i : initial shift for processing */ + Word32 *a, /* i/o : input/output data Q(Qx+Q_edct)*/ + const Word16 *w /* i : cos/sin table Q30*/ +) +{ + Word16 j, j1, j2, j3, k, k1, k2, m, m2; + Word16 wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; + Word32 x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + Word16 tmp; + + m = shl(l, 2); + FOR (j = 0; j < l; j += 2) + { + j1 = add(j, l); + j2 = add(j1, l); + j3 = add(j2, l); + x0r = L_add(a[j], a[j1]); + x0i = L_add(a[j + 1], a[j1 + 1]); + x1r = L_sub(a[j], a[j1]); + x1i = L_sub(a[j + 1], a[j1 + 1]); + x2r = L_add(a[j2], a[j3]); + x2i = L_add(a[j2 + 1], a[j3 + 1]); + x3r = L_sub(a[j2], a[j3]); + x3i = L_sub(a[j2 + 1], a[j3 + 1]); + a[j] = L_add(x0r, x2r); + move32(); + a[j + 1] = L_add(x0i, x2i); + move32(); + a[j2] = L_sub(x0r, x2r); + move32(); + a[j2 + 1] =L_sub(x0i, x2i); + move32(); + a[j1] = L_sub(x1r, x3i); + move32(); + a[j1 + 1] = L_add(x1i, x3r); + move32(); + a[j3] = L_add(x1r, x3i); + move32(); + a[j3 + 1] = L_sub(x1i, x3r); + move32(); + } + + wk1r = w[2]; + move16(); + tmp = add(l, m); + FOR (j = m; j < tmp; j += 2) + { + j1 = add(j, l); + j2 = add(j1, l); + j3 = add(j2, l); + x0r = L_add(a[j], a[j1]); + x0i = L_add(a[j + 1], a[j1 + 1]); + x1r = L_sub(a[j], a[j1]); + x1i = L_sub(a[j + 1], a[j1 + 1]); + x2r = L_add(a[j2], a[j3]); + x2i = L_add(a[j2 + 1], a[j3 + 1]); + x3r = L_sub(a[j2], a[j3]); + x3i = L_sub(a[j2 + 1], a[j3 + 1]); + a[j] = L_add(x0r, x2r); + move32(); + a[j + 1] = L_add(x0i, x2i); + move32(); + a[j2] = L_sub(x2i, x0i); + move32(); + a[j2 + 1] = L_sub(x0r, x2r); + move32(); + x0r = L_sub(x1r, x3i); + x0i = L_add(x1i, x3r); + a[j1] = Mult_32_16(L_shl(L_sub(x0r, x0i), 1), wk1r); + move32(); + a[j1 + 1] = Mult_32_16(L_shl(L_add(x0r, x0i), 1), wk1r); + move32(); + x0r = L_add(x3i, x1r); + x0i = L_sub(x3r, x1i); + a[j3] = Mult_32_16(L_shl(L_sub(x0i, x0r), 1), wk1r); + move32(); + a[j3 + 1] = Mult_32_16(L_shl(L_add(x0r, x0i), 1), wk1r); + move32(); + } + + k1 = 0; + move16(); + m2 = shl(m, 1); + FOR (k = m2; k < n; k += m2) + { + k1 = add(k1, 2); + k2 = shl(k1, 1); + wk2r = w[k1]; + move16(); + wk2i = w[k1 + 1]; + move16(); + wk1r = w[k2]; + move16(); + wk1i = w[k2 + 1]; + move16(); + wk3r = extract_l(L_sub(L_deposit_l(wk1r), L_shr(L_mult(wk2i, wk1i), 14))); + wk3i = extract_l(L_msu0(L_shr(L_mult(wk2i, wk1r), 14), wk1i, 1)); + + tmp = add(l, k) ; + FOR (j = k; j < tmp; j += 2) + { + j1 = add(j, l); + j2 = add(j1, l); + j3 = add(j2, l); + x0r = L_add(a[j], a[j1]); + x0i = L_add(a[j + 1], a[j1 + 1]); + x1r = L_sub(a[j], a[j1]); + x1i = L_sub(a[j + 1], a[j1 + 1]); + x2r = L_add(a[j2], a[j3]); + x2i = L_add(a[j2 + 1], a[j3 + 1]); + x3r = L_sub(a[j2], a[j3]); + x3i = L_sub(a[j2 + 1], a[j3 + 1]); + a[j] = L_add(x0r, x2r); + move32(); + a[j + 1] = L_add(x0i, x2i); + move32(); + x0r = L_sub(x0r, x2r); + x0i = L_sub(x0i, x2i); + a[j2] = L_sub(Mult_32_16(L_shl(x0r, 1), wk2r), Mult_32_16(L_shl(x0i, 1), wk2i)); + move32(); + a[j2 + 1] = L_add(Mult_32_16(L_shl(x0i, 1), wk2r), Mult_32_16(L_shl(x0r, 1), wk2i)); + move32(); + x0r = L_sub(x1r, x3i); + x0i = L_add(x1i, x3r); + a[j1] = L_sub(Mult_32_16(L_shl(x0r, 1), wk1r), Mult_32_16(L_shl(x0i, 1), wk1i)); + move32(); + a[j1 + 1] = L_add(Mult_32_16(L_shl(x0i, 1), wk1r), Mult_32_16(L_shl(x0r, 1), wk1i)); + move32(); + x0r = L_add(x1r, x3i); + x0i = L_sub(x1i, x3r); + a[j3] = L_sub(Mult_32_16(L_shl(x0r, 1), wk3r), Mult_32_16(L_shl(x0i, 1), wk3i)); + move32(); + a[j3 + 1] = L_add(Mult_32_16(L_shl(x0i, 1), wk3r), Mult_32_16(L_shl(x0r, 1), wk3i)); + move32(); + } + + wk1r = w[k2 + 2]; + move16(); + wk1i = w[k2 + 3]; + move16(); + wk3r = extract_l(L_sub(L_deposit_l(wk1r), L_shr(L_mult(wk2r, wk1i), 14))); + wk3i = extract_l(L_msu0(L_shr(L_mult(wk2r, wk1r), 14), wk1i, 1)); + + tmp = add(l, add(k, m)); + FOR (j = add(k, m); j < tmp; j += 2) + { + j1 = add(j, l); + j2 = add(j1, l); + j3 = add(j2, l); + x0r = L_add(a[j], a[j1]); + x0i = L_add(a[j + 1], a[j1 + 1]); + x1r = L_sub(a[j], a[j1]); + x1i = L_sub(a[j + 1], a[j1 + 1]); + x2r = L_add(a[j2], a[j3]); + x2i = L_add(a[j2 + 1], a[j3 + 1]); + x3r = L_sub(a[j2], a[j3]); + x3i = L_sub(a[j2 + 1], a[j3 + 1]); + a[j] = L_add(x0r, x2r); + move32(); + a[j + 1] = L_add(x0i, x2i); + move32(); + x0r= L_sub(x0r, x2r); + x0i=L_sub(x0i, x2i); + a[j2] = L_negate(L_add(Mult_32_16(L_shl(x0r, 1), wk2i), Mult_32_16(L_shl(x0i, 1), wk2r))); + move32(); + a[j2 + 1] = L_sub(Mult_32_16(L_shl(x0r, 1), wk2r), Mult_32_16(L_shl(x0i, 1), wk2i)); + move32(); + x0r = L_sub(x1r, x3i); + x0i = L_add(x1i, x3r); + a[j1] = L_sub(Mult_32_16(L_shl(x0r, 1), wk1r), Mult_32_16(L_shl(x0i, 1), wk1i)); + move32(); + a[j1 + 1] = L_add(Mult_32_16(L_shl(x0i, 1), wk1r), Mult_32_16(L_shl(x0r, 1), wk1i)); + move32(); + x0r = L_add(x1r, x3i); + x0i = L_sub(x1i, x3r); + a[j3] = L_sub(Mult_32_16(L_shl(x0r, 1), wk3r), Mult_32_16(L_shl(x0i, 1), wk3i)); + move32(); + a[j3 + 1] = L_add(Mult_32_16(L_shl(x0i, 1), wk3r), Mult_32_16(L_shl(x0r, 1), wk3i)); + move32(); + } + } + + return; +} + + +static void cftbsub_fx( + Word16 n, + Word32 *a, + const Word16 *w /* i : cos/sin table */ +) +{ + Word16 j, j1, j2, j3, l; + Word32 x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + l = 2; + move16(); + IF (n > 8) + { + cft1st_fx(n, a, w); + l = 8; + move16(); + + WHILE (LT_16(shl(l, 2), n)) + { + cftmdl_fx(n, l, a, w); + l = shl(l, 2); + } + } + + IF (EQ_16(shl(l, 2), n)) + { + FOR (j = 0; j < l; j += 2) + { + j1 = add(j, l); + j2 = add(j1, l); + j3 = add(j2, l); + x0r = L_add(a[j], a[j1]); + x0i = L_negate(L_add(a[j + 1], a[j1 + 1])); + x1r = L_sub(a[j], a[j1]); + x1i = L_sub(a[j1 + 1], a[j + 1]); + x2r = L_add(a[j2], a[j3]); + x2i = L_add(a[j2 + 1], a[j3 + 1]); + x3r = L_sub(a[j2], a[j3]); + x3i = L_sub(a[j2 + 1], a[j3 + 1]); + a[j] = L_add(x0r, x2r); + move32(); + a[j + 1] = L_sub(x0i, x2i); + move32(); + a[j2] = L_sub(x0r, x2r); + move32(); + a[j2 + 1] = L_add(x0i, x2i); + move32(); + a[j1] = L_sub(x1r, x3i); + move32(); + a[j1 + 1] = L_sub(x1i, x3r); + move32(); + a[j3] = L_add(x1r, x3i); + move32(); + a[j3 + 1] = L_add(x1i, x3r); + move32(); + } + } + ELSE + { + FOR (j = 0; j < l; j += 2) + { + j1 = add(j, l); + x0r = L_sub(a[j], a[j1]); + x0i = L_sub(a[j1 + 1], a[j + 1]); + a[j] = L_add(a[j], a[j1]); + move32(); + a[j + 1] = L_negate(L_add(a[j + 1], a[j1 + 1])); + move32(); + a[j1] = x0r; + move32(); + move32(); + a[j1 + 1] = x0i; + move32(); + move32(); + } + } +} + +static void rftfsub_fx( + Word16 n, + Word32 *a, + Word16 nc, + const Word16 *c +) +{ + Word16 j, k, kk, ks, m, tmp; + Word32 xr, xi, yr, yi; + Word16 wkr, wki; + + m = shr(n, 1); + /*ks = 2 * nc / m; */ + tmp = shl(nc, 1); + ks = 0; + move16(); + WHILE (GE_16(tmp, m)) + { + ks = add(ks, 1); + tmp = sub(tmp, m); + } + kk = 0; + move16(); + FOR (j = 2; j < m; j += 2) + { + k = sub(n, j); + kk = add(kk, ks); + wkr = sub(8192, c[nc - kk]); + wki = c[kk]; + move16(); + xr = L_sub(a[j], a[k]); + xi = L_add(a[j + 1], a[k + 1]); + yr = L_sub(Mult_32_16(L_shl(xr, 1), wkr), Mult_32_16(L_shl(xi, 1), wki)); + yi = L_add(Mult_32_16(L_shl(xi, 1), wkr), Mult_32_16(L_shl(xr, 1), wki)); + a[j] = L_sub(a[j], yr); + move32(); + a[j + 1] = L_sub(a[j + 1], yi); + move32(); + a[k] = L_add(a[k], yr); + move32(); + a[k + 1] = L_sub(a[k + 1], yi); + move32(); + } +} + + +static void rftbsub_fx( + Word16 n, + Word32 *a, + Word16 nc, + const Word16 *c +) +{ + Word16 j, k, kk, ks, m, tmp; + Word32 xr, xi, yr, yi; + Word16 wkr, wki; + + a[1] = L_negate(a[1]); + m = shr(n, 1); + /*ks = 2 * nc / m; */ + tmp = shl(nc, 1); + ks = 0; + move16(); + WHILE (GE_16(tmp, m)) + { + ks = add(ks, 1); + tmp = sub(tmp, m); + } + kk = 0; + move16(); + FOR (j = 2; j < m; j += 2) + { + k = sub(n, j); + kk = add(kk, ks); + wkr = sub(8192, c[nc - kk]); + wki = c[kk]; + move16(); + xr = L_sub(a[j], a[k]); + xi = L_add(a[j + 1], a[k + 1]); + yr = L_add(Mult_32_16(L_shl(xr, 1), wkr), Mult_32_16(L_shl(xi, 1), wki)); + yi = L_sub(Mult_32_16(L_shl(xi, 1), wkr), Mult_32_16(L_shl(xr, 1), wki)); + a[j] = L_sub(a[j], yr); + move32(); + a[j + 1] = L_sub(yi, a[j + 1]); + move32(); + a[k] = L_add(a[k], yr); + move32(); + a[k + 1] = L_sub(yi, a[k + 1]); + move32(); + } + a[m + 1] = L_negate(a[m + 1]); + move32(); +} + + +static void dctsub_fx( + Word16 n, + Word32 *a, + Word16 nc, + const Word16 *c +) +{ + Word16 j, k, kk, ks, m, tmp; + Word16 wkr, wki; + Word32 xr; + + m = shr(n, 1); + /*ks = nc / n; */ + tmp = nc; + move16(); + ks = 0; + move16(); + WHILE (GE_16(tmp, n)) + { + ks = add(ks, 1); + tmp = sub(tmp, n); + } + kk = 0; + move16(); + FOR (j = 1; j < m; j++) + { + k = sub(n, j); + kk = add(kk, ks); + wkr = sub(c[kk], c[nc - kk]); + wki = add(c[kk], c[nc - kk]); + xr = L_sub(Mult_32_16(L_shl(a[j], 1), wki), Mult_32_16(L_shl(a[k], 1), wkr)); + a[j] = L_add(Mult_32_16(L_shl(a[j], 1), wkr), Mult_32_16(L_shl(a[k], 1), wki)); + move32(); + a[k] = xr; + move32(); + } + a[m] = Mult_32_16(L_shl(a[m], 1), c[0]); +} + +/*-----------------------------------------------------------------* + * edct2_fx() + * + * Transformation of the signal to DCT domain + * OR Inverse EDCT-II for short frames + *-----------------------------------------------------------------*/ + +void edct2_fx( + Word16 n, + Word16 isgn, + Word16 *in, + Word32 *a, + Word16 *q, + const Word16 *ip, + const Word16 *w +) +{ + Word16 j, nw, nc; + Word32 xr; + + *q = Exp16Array(n, in); + *q = add(*q, 6); + FOR (j = 0; j < n; j++) + { + a[j] = L_shl((Word32) in[j], *q); + move32(); + } + + nw = ip[0]; + move16(); + if (GT_16(n, shl(nw, 2))) + { + nw = shr(n, 2); + } + + nc = ip[1]; + move16(); + if (n > nc) + { + nc = n; + move16(); + } + + IF (isgn < 0) + { + xr = a[n - 1]; + move32(); + FOR (j = n - 2; j >= 2; j -= 2) + { + a[j + 1] = L_sub(a[j], a[j - 1]); + move32(); + a[j] = L_add(a[j], a[j - 1]); + move32(); + } + a[1] = L_sub(a[0], xr); + move32(); + a[0] = L_add(a[0], xr); + move32(); + + IF (n > 4) + { + rftbsub_fx(n, a, nc, w + nw); + bitrv2_SR_fx(n, ip + 2, a); + cftbsub_fx(n, a, w); + } + ELSE IF (n == 4) + { + cftfsub_fx(n, a, w); + } + } + + IF (isgn >= 0) + { + a[0] = L_shr(a[0], 1); + move32(); + } + + dctsub_fx(n, a, nc, w + nw); + + IF (isgn >= 0) + { + IF (n > 4) + { + bitrv2_SR_fx(n, ip + 2, a); + cftfsub_fx(n, a, w); + rftfsub_fx(n, a, nc, w + nw); + } + ELSE IF (n == 4) + { + cftfsub_fx(n, a, w); + } + xr = L_sub(a[0], a[1]); + a[0] = L_add(a[0], a[1]); + move32(); + FOR (j = 2; j < n; j += 2) + { + a[j - 1] = L_sub(a[j], a[j + 1]); + move32(); + a[j] = L_add(a[j], a[j + 1]); + move32(); + } + a[n - 1] = xr; + move32(); + + FOR (j = 0; j < n; j ++) + { + a[j] = L_shr(a[j], 5); + move32(); + } + } +} + + +/*-----------------------------------------------------------------* +* fft5_shift4() +* 5-point FFT with 4-point circular shift +*-----------------------------------------------------------------*/ + +static void fft5_shift4_16fx( + Word16 n1, /* i : length of data */ + Word16 *zRe, /* i/o : real part of input and output data */ + Word16 *zIm, /* i/o : imaginary part of input and output data */ + const Word16 *Idx /* i : pointer of the address table */ +) +{ + Word16 T1, To, T8, Tt, T9, Ts, Te, Tp, Th, Tn,T2, T3, T4, T5, T6, T7; + Word16 i0,i1,i2,i3,i4; + Word32 L_tmp; + + i0 = Idx[0]; + move16(); + i1 = Idx[n1]; + move16(); + i2 = Idx[n1*2]; + move16(); + i3 = Idx[n1*3]; + move16(); + i4 = Idx[n1*4]; + move16(); + + T1 = zRe[i0]; + move16(); + To = zIm[i0]; + move16(); + + T2 = zRe[i1]; + move16(); + T3 = zRe[i4]; + move16(); + T4 = add(T2,T3); + T5 = zRe[i2]; + move16(); + T6 = zRe[i3]; + move16(); + T7 = add(T5,T6); + T8 = add(T4,T7); + Tt = sub(T5,T6); + /* T9 = KP559016994 * (T4 - T7); */ + L_tmp = Mult_32_16(KP559016994_16FX,sub(T4,T7)); + T9 = round_fx(L_tmp); + Ts = sub(T2,T3); + + T2 = zIm[i1]; + move16(); + T3 = zIm[i4]; + move16(); + T4 = add(T2,T3); + T5 = zIm[i2]; + move16(); + T6 = zIm[i3]; + move16(); + T7 = add(T5,T6); + Te = sub(T2,T3); + Tp = add(T4,T7); + Th = sub(T5,T6); + /* Tn = KP559016994 * (T4 - T7); */ + L_tmp = Mult_32_16(KP559016994_16FX,sub(T4,T7)); + Tn = round_fx(L_tmp); + + zRe[i0] = add(T1,T8); + move16(); + zIm[i0] = add(To,Tp); + move16(); + + /* T2 = KP951056516*Te + KP587785252*Th; */ + L_tmp = Mult_32_16(KP951056516_16FX,Te); + L_tmp = Madd_32_16(L_tmp,KP587785252_16FX,Th); + T2 = round_fx(L_tmp); + + /*T3 = KP951056516*Th - KP587785252*Te; */ + L_tmp = Mult_32_16(KP951056516_16FX,Th); + L_tmp = Msub_32_16(L_tmp,KP587785252_16FX,Te); + T3 = round_fx(L_tmp); + + T6 = sub(T1,shr(T8,2)); + T4 = add(T9,T6); + T5 = sub(T6,T9); + zRe[i1] = sub(T4,T2); + move16(); + zRe[i2] = add(T5,T3); + move16(); + zRe[i4] = add(T4,T2); + move16(); + zRe[i3] = sub(T5,T3); + move16(); + + /* T2 = KP951056516 * Ts + KP587785252 * Tt; */ + L_tmp = Mult_32_16(KP951056516_16FX,Ts); + L_tmp = Madd_32_16(L_tmp,KP587785252_16FX,Tt); + T2 = round_fx(L_tmp); + + /* T3 = KP951056516 * Tt - KP587785252 * Ts; */ + L_tmp = Mult_32_16(KP951056516_16FX,Tt); + L_tmp = Msub_32_16(L_tmp,KP587785252_16FX,Ts); + T3 = round_fx(L_tmp); + + T6 = sub(To,shr(Tp,2)); + T4 = add(Tn,T6); + T5 = sub(T6,Tn); + zIm[i4] = sub(T4,T2); + move16(); + zIm[i2] = sub(T5,T3); + move16(); + zIm[i1] = add(T2,T4); + move16(); + zIm[i3] = add(T3,T5); + move16(); + + return; +} + +/*-----------------------------------------------------------------* +* fft5_32() +* 5-point FFT called for 32 times +*-----------------------------------------------------------------*/ +static void fft5_32_16fx( + Word16 *zRe, /* i/o : real part of input and output data */ + Word16 *zIm, /* i/o : imaginary part of input and output data */ + const Word16 *Idx /* i : pointer of the address table */ +) +{ + Word16 T1, To, T8, Tt, T9, Ts, Te, Tp, Th, Tn,T2, T3, T4, T5, T6, T7; + Word16 i0,i1,i2,i3,i4; + Word32 L_tmp; + + i0 = Idx[0]; + move16(); + i1 = Idx[32]; + move16(); + i2 = Idx[64]; + move16(); + i3 = Idx[96]; + move16(); + i4 = Idx[128]; + move16(); + + T1 = zRe[i0]; + move16(); + To = zIm[i0]; + move16(); + + T2 = zRe[i1]; + move16(); + T3 = zRe[i4]; + move16(); + T4 = add(T2, T3); + T5 = zRe[i2]; + move16(); + T6 = zRe[i3]; + move16(); + T7 = add(T5,T6); + T8 = add(T4,T7); + Tt = sub(T5,T6); + /* T9 = KP559016994 * (T4 - T7); */ + L_tmp = Mult_32_16(KP559016994_16FX,sub(T4,T7)); + T9 = round_fx(L_tmp); + Ts = sub(T2,T3); + + T2 = zIm[i1]; + move16(); + T3 = zIm[i4]; + move16(); + T4 = add(T2,T3); + T5 = zIm[i2]; + move16(); + T6 = zIm[i3]; + move16(); + T7 = add(T5,T6); + Te = sub(T2,T3); + Tp = add(T4,T7); + Th = sub(T5,T6); + L_tmp = Mult_32_16(KP559016994_16FX,sub(T4,T7)); + Tn = round_fx(L_tmp); + + + + zRe[i0] = add(T1,T8); + move16(); + zIm[i0] = add(To,Tp); + move32(); + + + + /*T2 = KP951056516*Te + KP587785252*Th; */ + L_tmp = Mult_32_16(KP951056516_16FX,Te); + L_tmp = Madd_32_16(L_tmp,KP587785252_16FX,Th); + T2 = round_fx(L_tmp); + + /*T3 = KP951056516*Th - KP587785252*Te; */ + L_tmp = Mult_32_16(KP951056516_16FX,Th); + L_tmp = Msub_32_16(L_tmp,KP587785252_16FX,Te); + T3 = round_fx(L_tmp); + + + + T6 = sub(T1,shr(T8,2)); + T4 = add(T9,T6); + T5 = sub(T6,T9); + zRe[i3] = sub(T4,T2); + move32(); + zRe[i1] = add(T5,T3); + move32(); + zRe[i2] = add(T4,T2); + move32(); + zRe[i4] = sub(T5,T3); + move32(); + + /* T2 = KP951056516 * Ts + KP587785252 * Tt; */ + L_tmp = Mult_32_16(KP951056516_16FX,Ts); + L_tmp = Madd_32_16(L_tmp,KP587785252_16FX,Tt); + T2 = round_fx(L_tmp); + + /* T3 = KP951056516 * Tt - KP587785252 * Ts; */ + L_tmp = Mult_32_16(KP951056516_16FX,Tt); + L_tmp = Msub_32_16(L_tmp,KP587785252_16FX,Ts); + T3 = round_fx(L_tmp); + + T6 = sub(To,shr(Tp,2)); + T4 = add(Tn,T6); + T5 = sub(T6,Tn); + zIm[i2] = sub(T4,T2); + move16(); + zIm[i1] = sub(T5,T3); + move16(); + zIm[i3] = add(T2,T4); + move16(); + zIm[i4] = add(T3,T5); + move16(); + + + return; +} + +/*-----------------------------------------------------------------* +* fft64() +* 64-point FFT +*-----------------------------------------------------------------*/ +static void fft64_16fx( + Word16 *x, /* i/o : real part of input and output data */ + Word16 *y, /* i/o : imaginary part of input and output data */ + const Word16 *Idx /* i : pointer of the address table */ +) +{ + Word16 i,id,jd; + Word16 z[128]; + move16();/*penalty for 1 ptr init */ + FOR ( i=0; i<64; i++ ) + { + id = Idx[i]; + move16(); + z[2*i] = x[id]; + move16(); + z[2*i+1] = y[id]; + move16(); + } + + cdftForw_16fx(128, z, Ip_fft64_16fx, w_fft128_16fx); + + move16();/*penalty for 1 ptr init */ + FOR( i=0; i<64 ; i++) + { + jd = Odx_fft64_16fx[i]; + move16(); + id = Idx[jd]; + move16(); + x[id]=z[2*i]; + move16(); + y[id]=z[2*i+1]; + move16(); + } + + return; +} + + +/*-----------------------------------------------------------------* +* fft32_5() +* 32-point FFT called for 5 times +*-----------------------------------------------------------------*/ +static void fft32_5_16fx( + Word16 *x, /* i/o : real part of input and output data */ + Word16 *y, /* i/o : imaginary part of input and output data */ + const Word16 *Idx /* i : pointer of the address table */ +) +{ + Word16 i,id,jd; + Word16 z[64]; + + move16();/*penalty for 1 ptr init */ + FOR( i=0; i<32; i++ ) + { + id = Idx[i]; + move16(); + z[2*i] = x[id]; + move16(); + z[2*i+1] = y[id]; + move16(); + } + + cdftForw_16fx(64,z,Ip_fft32_16fx,w_fft32_16fx); + + move16();/*penalty for 1 ptr init */ + FOR( i=0; i<32; i++ ) + { + jd = Odx_fft32_5[i]; + move16(); + id = Idx[jd]; + move16(); + x[id]=z[2*i]; + move16(); + y[id]=z[2*i+1]; + move16(); + } + + return; +} + + + +/*-----------------------------------------------------------------* +* DoRTFT160() +* a low complexity 2-dimensional DFT of 160 points +*-----------------------------------------------------------------*/ +void DoRTFT160_16fx( + Word16 x[], /* i/o : real part of input and output data */ + Word16 y[] /* i/o : imaginary part of input and output data */ +) +{ + Word16 j; + + /* Applying 32-point FFT for 5 times based on the address table Idx_dortft160 */ + FOR(j=0; j<5; j++) + { + fft32_5_16fx(x,y,Idx_dortft160+shl(j,5)/*32*j*/); + } + + /* Applying 5-point FFT for 32 times based on the address table Idx_dortft160 */ + FOR(j=0; j<32; j++) + { + fft5_32_16fx(x,y,Idx_dortft160+j); + } + + return; +} + +/*-----------------------------------------------------------------* +* DoRTFT320() +* a low complexity 2-dimensional DFT of 320 points +*-----------------------------------------------------------------*/ +void DoRTFT320_16fx( + Word16 *x, /* i/o : real part of input and output data */ + Word16 *y /* i/o : imaginary part of input and output data */ +) +{ + Word16 j; + + /* Applying 64-point FFT for 5 times based on the address table Idx_dortft160 */ + FOR(j=0; j<5; j++) + { + fft64_16fx(x,y,Idx_dortft320_16fx+shl(j,6)/*64*j*/); + } + + /* Applying 5-point FFT for 64 times based on the address table Idx_dortft160 */ + FOR(j=0; j<64; j++) + { + fft5_shift4_16fx(64,x,y,Idx_dortft320_16fx+j); + } + + return; +} + +/*-----------------------------------------------------------------* +* DoRTFT128() +* FFT with 128 points +*-----------------------------------------------------------------*/ +void DoRTFT128_16fx( + Word16 *x, /* i/o : real part of input and output data Q(Qx+Q_edct)*/ + Word16 *y /* i/o : imaginary part of input and output data Q(Qx+Q_edct)*/ +) +{ + + Word16 i; + Word16 z[256]; + + move16();/*penalty for 1 ptr init */ + FOR ( i=0; i<128; i++ ) + { + z[2*i] = x[i]; + move16(); + z[2*i+1] = y[i]; + move16(); + } + + cdftForw_16fx(256,z,Ip_fft128_16fx,w_fft128_16fx); + + x[0]=z[0]; + move16(); + y[0]=z[1]; + move16(); + move16();/*penalty for 1 ptr init */ + move16();/*penalty for 1 ptr init */ + FOR( i=1; i<128 ; i++) + { + x[128-i]=z[2*i]; + move16(); + y[128-i]=z[2*i+1]; + move16(); + } + + return; +} +/*-----------------------------------------------------------------* +* cdftForw() +* Main fuction of Complex Discrete Fourier Transform +*-----------------------------------------------------------------*/ +static void cdftForw_16fx( + Word16 n, /* i : data length of real and imag */ + Word16 *a, /* i/o : input/output data Q(Qx+Q_edct)*/ + const Word16 *ip, /* i : work area for bit reversal */ + const Word32 *w /* i : cos/sin table Q30*/ +) +{ + /* bit reversal */ + bitrv2_SR_16fx(n, ip + 2, a); + + /* Do FFT */ + cftfsub_16fx(n, a, w); +} + +/*-----------------------------------------------------------------* +* bitrv2_SR() +* Bit reversal +*-----------------------------------------------------------------*/ +static void bitrv2_SR_16fx( + Word16 n, /* i : data length of real and imag */ + const Word16 *ip, /* i/o : work area for bit reversal */ + Word16 *a /* i/o : input/output data Q(Qx+Q_edct)*/ +) +{ + Word16 j, j1, k, k1, m, m2; + Word16 l; + Word16 xr, xi, yr, yi; + + l = n; + move16(); + m = 1; + move16(); + + WHILE (LT_16(shl(m,3),l)) + { + l = shr(l,1); + m = shl(m,1); + } + + m2 = shl(m,1); + IF (EQ_16(shl(m, 3),l)) + { + FOR (k = 0; k < m; k++) + { + FOR (j = 0; j < k; j++) + { + j1 = add(shl(j,1),ip[k]); + k1 = add(shl(k,1),ip[j]); + xr = a[j1]; + move16(); + xi = a[j1 + 1]; + move16(); + yr = a[k1]; + move16(); + yi = a[k1 + 1]; + move16(); + a[j1] = yr; + move16(); + a[j1 + 1] = yi; + move16(); + a[k1] = xr; + move16(); + a[k1 + 1] = xi; + move16(); + j1 = add(j1,m2); + k1 = add(k1,shl(m2,1)); + xr = a[j1]; + move16(); + xi = a[j1 + 1]; + move16(); + yr = a[k1]; + move16(); + yi = a[k1 + 1]; + move16(); + a[j1] = yr; + move16(); + a[j1 + 1] = yi; + move16(); + a[k1] = xr; + move16(); + a[k1 + 1] = xi; + move16(); + j1 = add(j1,m2); + k1 = sub(k1,m2); + xr = a[j1]; + move16(); + xi = a[j1 + 1]; + move16(); + xi = a[j1 + 1]; + move16(); + yr = a[k1]; + move16(); + yi = a[k1 + 1]; + move16(); + a[j1] = yr; + move16(); + a[j1 + 1] = yi; + move16(); + a[k1] = xr; + move16(); + a[k1 + 1] = xi; + move16(); + j1 = add(j1,m2); + k1 = add(k1,shl(m2,1)); + xr = a[j1]; + move16(); + xi = a[j1 + 1]; + move16(); + yr = a[k1]; + move16(); + yi = a[k1 + 1]; + move16(); + a[j1] = yr; + move16(); + a[j1 + 1] = yi; + move16(); + a[k1] = xr; + move16(); + a[k1 + 1] = xi; + move16(); + } + + j1 = add(add(shl(k,1),m2),ip[k]); + k1 = add(j1,m2); + xr = a[j1]; + move16(); + xi = a[j1 + 1]; + move16(); + yr = a[k1]; + move16(); + yi = a[k1 + 1]; + move16(); + a[j1] = yr; + move16(); + a[j1 + 1] = yi; + move16(); + a[k1] = xr; + move16(); + a[k1 + 1] = xi; + move16(); + } + } + ELSE + { + FOR (k = 1; k < m; k++) + { + FOR (j = 0; j < k; j++) + { + j1 = add(shl(j,1),ip[k]); + k1 = add(shl(k,1),ip[j]); + xr = a[j1]; + move16(); + xi = a[j1 + 1]; + move16(); + yr = a[k1]; + move16(); + yi = a[k1 + 1]; + move16(); + a[j1] = yr; + move16(); + a[j1 + 1] = yi; + move16(); + a[k1] = xr; + move16(); + a[k1 + 1] = xi; + move16(); + j1 = add(j1,m2); + k1 = add(k1,m2); + xr = a[j1]; + move16(); + xi = a[j1 + 1]; + move16(); + yr = a[k1]; + move16(); + yi = a[k1 + 1]; + move16(); + a[j1] = yr; + move16(); + a[j1 + 1] = yi; + move16(); + a[k1] = xr; + move16(); + a[k1 + 1] = xi; + move16(); + } + } + } + + return; +} + +/*-----------------------------------------------------------------* +* cftfsub() +* Complex Discrete Fourier Transform +*-----------------------------------------------------------------*/ +static void cftfsub_16fx( + Word16 n, /* i : data length of real and imag */ + Word16 *a, /* i/o : input/output data Q(Qx+Q_edct)*/ + const Word32 *w /* i : cos/sin table Q30*/ +) +{ + Word16 j, j1, j2, j3, l; + Word16 x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + + l = 2; + move16(); + IF (GT_16(n,8)) + { + cft1st_16fx(n, a, w); + l = 8; + move16(); + WHILE (LT_16(shl(l, 2),n)) + { + cftmdl_16fx(n, l, a, w); + l = shl(l,2); + } + } + + IF (EQ_16(shl(l,2),n)) + { + FOR (j = 0; j < l; j += 2) + { + j1 = add(j,l); + j2 = add(j1,l); + j3 = add(j2,l); + x0r = add(a[j],a[j1]); + x0i = add(a[j + 1],a[j1 + 1]); + x1r = sub(a[j],a[j1]); + x1i = sub(a[j + 1],a[j1 + 1]); + x2r = add(a[j2],a[j3]); + x2i = add(a[j2 + 1],a[j3 + 1]); + x3r = sub(a[j2],a[j3]); + x3i = sub(a[j2 + 1],a[j3 + 1]); + a[j] = add(x0r,x2r); + move16(); + a[j + 1] = add(x0i,x2i); + move16(); + a[j2] = sub(x0r,x2r); + move16(); + a[j2 + 1] = sub(x0i,x2i); + move16(); + a[j1] = sub(x1r,x3i); + move16(); + a[j1 + 1] = add(x1i,x3r); + move16(); + a[j3] = add(x1r,x3i); + move16(); + a[j3 + 1] = sub(x1i,x3r); + move16(); + } + } + ELSE + { + FOR (j = 0; j < l; j += 2) + { + j1 = add(j,l); + x0r = sub(a[j],a[j1]); + x0i = sub(a[j + 1],a[j1 + 1]); + a[j] = add(a[j],a[j1]); + move16(); + a[j + 1] = add(a[j + 1],a[j1 + 1]); + move16(); + a[j1] = x0r; + move16(); + a[j1 + 1] = x0i; + move16(); + } + } + return; +} + +/*-----------------------------------------------------------------* +* cft1st() +* Subfunction of Complex Discrete Fourier Transform +*-----------------------------------------------------------------*/ +static void cft1st_16fx( + Word16 n, /* i : data length of real and imag */ + Word16 *a, /* i/o : input/output data Q(Qx+Q_edct)*/ + const Word32 *w /* i : cos/sin table Q30*/ +) +{ + Word16 j, k1, k2; + Word32 wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; + Word16 x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + Word16 tmp; + Word32 L_tmp; + + x0r = add(a[0],a[2]); + x0i = add(a[1],a[3]); + x1r = sub(a[0],a[2]); + x1i = sub(a[1],a[3]); + x2r = add(a[4],a[6]); + x2i = add(a[5],a[7]); + x3r = sub(a[4],a[6]); + x3i = sub(a[5],a[7]); + a[0] = add(x0r,x2r); + move16(); + a[1] = add(x0i,x2i); + move16(); + a[4] = sub(x0r,x2r); + move16(); + a[5] = sub(x0i,x2i); + move16(); + a[2] = sub(x1r,x3i); + move16(); + a[3] = add(x1i,x3r); + move16(); + a[6] = add(x1r,x3i); + move16(); + a[7] = sub(x1i,x3r); + move16(); + + wk1r = w[2]; + move32(); + + x0r = add(a[8],a[10]); + x0i = add(a[9],a[11]); + x1r = sub(a[8],a[10]); + x1i = sub(a[9],a[11]); + x2r = add(a[12],a[14]); + x2i = add(a[13],a[15]); + x3r = sub(a[12],a[14]); + x3i = sub(a[13],a[15]); + a[8] = add(x0r,x2r); + move16(); + a[9] = add(x0i,x2i); + move16(); + a[12] = sub(x2i,x0i); + move16(); + a[13] = sub(x0r,x2r); + move16(); + + x0r = sub(x1r,x3i); + x0i = add(x1i,x3r); + tmp = sub(x0r,x0i); + L_tmp = Mult_32_16(wk1r,tmp); /*Q(15+Qx+Q_edct) */ + + a[10] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + tmp = add(x0r,x0i); + L_tmp = Mult_32_16(wk1r,tmp); /*Q(15+Qx+Q_edct) */ + a[11] = round_fx(L_shl(L_tmp,1)); /* Q(Qx+Q_edct) */ + + x0r = add(x3i,x1r); + x0i = sub(x3r,x1i); + tmp = sub(x0i,x0r); + L_tmp = Mult_32_16(wk1r,tmp); /*Q(15+Qx+Q_edct) */ + a[14] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + tmp = add(x0i,x0r); + L_tmp = Mult_32_16(wk1r,tmp); /*Q(15+Qx+Q_edct) */ + a[15] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + k1 = 0; + move16(); + + FOR (j = 16; j < n; j += 16) + { + k1 = add(k1,2); + k2 = shl(k1,1); + + wk2r = w[k1]; move32(); + wk2i = w[k1 + 1]; move32(); + wk1r = w[k2]; move32(); + wk1i = w[k2 + 1]; move32(); + + L_tmp = L_shl(Mult_32_32(wk2i,wk1i),1);/*Q29 */ + wk3r = L_sub(wk1r,L_shl(L_tmp,1));/*Q30 */ + + L_tmp = L_shl(Mult_32_32(wk2i,wk1r),1);/*Q29 */ + wk3i = L_sub(L_shl(L_tmp,1),wk1i);/*Q30 */ + + x0r = add(a[j],a[j + 2]); + x0i = add(a[j + 1],a[j + 3]); + x1r = sub(a[j],a[j + 2]); + x1i = sub(a[j + 1],a[j + 3]); + x2r = add(a[j + 4],a[j + 6]); + x2i = add(a[j + 5],a[j + 7]); + x3r = sub(a[j + 4],a[j + 6]); + x3i = sub(a[j + 5],a[j + 7]); + a[j] = add(x0r,x2r); + move16(); + a[j + 1] = add(x0i,x2i); + move16(); + + x0r = sub(x0r,x2r); + x0i = sub(x0i,x2i); + L_tmp = Mult_32_16(wk2r,x0r);/*Q(15+Qx+Q_edct) */ + L_tmp = Msub_32_16(L_tmp,wk2i,x0i); /*Q(15+Qx+Q_edct) */ + a[j + 4] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + L_tmp = Mult_32_16(wk2r,x0i);/*Q(15+Qx+Q_edct) */ + L_tmp = Madd_32_16(L_tmp,wk2i,x0r); /*Q(15+Qx+Q_edct) */ + a[j + 5] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + x0r = sub(x1r,x3i); + x0i = add(x1i,x3r); + L_tmp = Mult_32_16(wk1r,x0r);/*Q(15+Qx+Q_edct) */ + L_tmp = Msub_32_16(L_tmp,wk1i,x0i); /*Q(15+Qx+Q_edct) */ + a[j + 2] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + L_tmp = Mult_32_16(wk1r,x0i);/*Q(15+Qx+Q_edct) */ + L_tmp = Madd_32_16(L_tmp,wk1i,x0r); /*Q(15+Qx+Q_edct) */ + a[j + 3] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + x0r = add(x1r,x3i); + x0i = sub(x1i,x3r); + L_tmp = Mult_32_16(wk3r,x0r); /*Q(15+Qx+Q_edct) */ + L_tmp = Msub_32_16(L_tmp,wk3i,x0i); /*Q(15+Qx+Q_edct) */ + a[j + 6] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + L_tmp = Mult_32_16(wk3r,x0i); /*Q(15+Qx+Q_edct) */ + L_tmp = Madd_32_16(L_tmp,wk3i,x0r); /*Q(15+Qx+Q_edct) */ + a[j + 7] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + wk1r = w[k2 + 2]; move32(); + wk1i = w[k2 + 3]; move32(); + L_tmp = L_shl(Mult_32_32(wk2r,wk1i),1);/*Q29 */ + wk3r = L_sub(wk1r,L_shl(L_tmp,1)); /*Q30 */ + + L_tmp = L_shl(Mult_32_32(wk2r,wk1r),1);/*Q29 */ + wk3i = L_sub(L_shl(L_tmp,1),wk1i); /*Q30 */ + + x0r = add(a[j + 8],a[j + 10]); + x0i = add(a[j + 9],a[j + 11]); + x1r = sub(a[j + 8],a[j + 10]); + x1i = sub(a[j + 9],a[j + 11]); + x2r = add(a[j + 12],a[j + 14]); + x2i = add(a[j + 13],a[j + 15]); + x3r = sub(a[j + 12],a[j + 14]); + x3i = sub(a[j + 13],a[j + 15]); + a[j + 8] = add(x0r,x2r); + move16(); + a[j + 9] = add(x0i,x2i); + move16(); + + x0r = sub(x0r,x2r); + x0i = sub(x0i,x2i); + tmp = negate(x0r); + L_tmp = Mult_32_16(wk2i,tmp);/*Q(15+Qx+Q_edct) */ + L_tmp = Msub_32_16(L_tmp,wk2r,x0i); /*Q(15+Qx+Q_edct) */ + a[j + 12] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + tmp = negate(x0i); + L_tmp = Mult_32_16(wk2i,tmp);/*Q(15+Qx+Q_edct) */ + L_tmp = Madd_32_16(L_tmp,wk2r,x0r); /*Q(15+Qx+Q_edct) */ + a[j + 13] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + x0r = sub(x1r,x3i); + x0i = add(x1i,x3r); + L_tmp = Mult_32_16(wk1r,x0r);/*Q(15+Qx+Q_edct) */ + L_tmp = Msub_32_16(L_tmp,wk1i,x0i); /*Q(15+Qx+Q_edct) */ + a[j + 10] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + L_tmp = Mult_32_16(wk1r,x0i);/*Q(15+Qx+Q_edct) */ + L_tmp = Madd_32_16(L_tmp,wk1i,x0r); /*Q(15+Qx+Q_edct) */ + a[j + 11] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + x0r = add(x1r,x3i); + x0i = sub(x1i,x3r); + + L_tmp = Mult_32_16(wk3r,x0r); /*Q(15+Qx+Q_edct) */ + L_tmp = Msub_32_16(L_tmp,wk3i,x0i); /*Q(15+Qx+Q_edct) */ + a[j + 14] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + L_tmp = Mult_32_16(wk3r,x0i); /*Q(15+Qx+Q_edct) */ + L_tmp = Madd_32_16(L_tmp,wk3i,x0r); /*Q(15+Qx+Q_edct) */ + a[j + 15] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + } + + return; +} + +/*-----------------------------------------------------------------* +* cftmdl() +* Subfunction of Complex Discrete Fourier Transform +*-----------------------------------------------------------------*/ +static void cftmdl_16fx( + Word16 n, /* i : data length of real and imag */ + Word16 l, /* i : initial shift for processing */ + Word16 *a, /* i/o : input/output data Q(Qx+Q_edct)*/ + const Word32 *w /* i : cos/sin table Q30*/ +) +{ + Word16 j, j1, j2, j3, k, k1, k2, m, m2; + Word32 wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; + Word16 x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; + Word16 tmp, tmp2; + Word32 L_tmp; + Word32 L_x0r, L_x0i; + + m = shl(l, 2); + move16(); + FOR (j = 0; j < l; j += 2) + { + j1 = add(j,l); + j2 = add(j1,l); + j3 = add(j2,l); + x0r = add(a[j],a[j1]); + x0i = add(a[j + 1],a[j1 + 1]); + x1r = sub(a[j],a[j1]); + x1i = sub(a[j + 1],a[j1 + 1]); + x2r = add(a[j2],a[j3]); + x2i = add(a[j2 + 1],a[j3 + 1]); + x3r = sub(a[j2],a[j3]); + x3i = sub(a[j2 + 1],a[j3 + 1]); + a[j] = add(x0r,x2r); + move16(); + a[j + 1] = add(x0i,x2i); + move16(); + a[j2] = sub(x0r,x2r); + move16(); + a[j2 + 1] = sub(x0i,x2i); + move16(); + a[j1] = sub(x1r,x3i); + move16(); + a[j1 + 1] = add(x1i,x3r); + move16(); + a[j3] = add(x1r,x3i); + move16(); + a[j3 + 1] = sub(x1i,x3r); + move16(); + } + + wk1r = w[2]; + move32(); + tmp2 = add(l,m); + FOR (j = m; j < tmp2; j += 2) + { + j1 = add(j,l); + j2 = add(j1,l); + j3 = add(j2,l); + x0r = add(a[j],a[j1]); + x0i = add(a[j + 1],a[j1 + 1]); + x1r = sub(a[j],a[j1]); + x1i = sub(a[j + 1],a[j1 + 1]); + x2r = add(a[j2],a[j3]); + x2i = add(a[j2 + 1],a[j3 + 1]); + x3r = sub(a[j2],a[j3]); + x3i = sub(a[j2 + 1],a[j3 + 1]); + a[j] = add(x0r,x2r); + move16(); + a[j + 1] = add(x0i,x2i); + move16(); + a[j2] = sub(x2i,x0i); + move16(); + a[j2 + 1] = sub(x0r,x2r); + move16(); + + x0r = sub(x1r,x3i); + x0i = add(x1i,x3r); + tmp = sub(x0r,x0i); + L_tmp = Mult_32_16(wk1r,tmp);/*Q(15+Qx+Q_edct) */ + a[j1] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + tmp = add(x0r,x0i); + L_tmp = Mult_32_16(wk1r,tmp); /*Q(15+Qx+Q_edct) */ + a[j1 + 1] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + x0r = add(x3i,x1r); + x0i = sub(x3r,x1i); + tmp = sub(x0i,x0r); + L_tmp = Mult_32_16(wk1r,tmp);/*Q(15+Qx+Q_edct) */ + a[j3] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + tmp = add(x0i,x0r); + L_tmp = Mult_32_16(wk1r,tmp); /*Q(15+Qx+Q_edct) */ + a[j3 + 1] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + } + + k1 = 0; + move16(); + m2 = shl(m,1); + FOR (k = m2; k < n; k += m2) + { + k1 = add(k1,2); + k2 = shl(k1,1); + wk2r = w[k1]; move32(); + wk2i = w[k1 + 1]; move32(); + wk1r = w[k2]; move32(); + wk1i = w[k2 + 1]; move32(); + L_tmp = L_shl(Mult_32_32(wk2i,wk1i),1);/*Q29 */ + wk3r = L_sub(wk1r,L_shl(L_tmp,1));/*Q30 */ + + L_tmp = L_shl(Mult_32_32(wk2i,wk1r),1);/*Q29 */ + wk3i = L_sub(L_shl(L_tmp,1),wk1i);/*Q30 */ + + tmp2 = add(l,k); + FOR (j = k; j < tmp2; j += 2) + { + j1 = add(j,l); + j2 = add(j1,l); + j3 = add(j2,l); + x0r = add(a[j],a[j1]); + x0i = add(a[j + 1],a[j1 + 1]); + x1r = sub(a[j],a[j1]); + x1i = sub(a[j + 1],a[j1 + 1]); + x2r = add(a[j2],a[j3]); + x2i = add(a[j2 + 1],a[j3 + 1]); + x3r = sub(a[j2],a[j3]); + x3i = sub(a[j2 + 1],a[j3 + 1]); + a[j] = add(x0r,x2r); + move16(); + a[j + 1] = add(x0i,x2i); + move16(); + + x0r = sub(x0r,x2r); + x0i = sub(x0i,x2i); + + L_tmp = Mult_32_16(wk2r,x0r); /*Q(15+Qx+Q_edct) */ + L_tmp = Msub_32_16(L_tmp,wk2i,x0i); /*Q(15+Qx+Q_edct) */ + a[j2] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + L_tmp = Mult_32_16(wk2r,x0i); /*Q(15+Qx+Q_edct) */ + L_tmp = Madd_32_16(L_tmp,wk2i,x0r); /*Q(15+Qx+Q_edct) */ + a[j2 + 1] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + x0r = sub(x1r,x3i); + x0i = add(x1i,x3r); + + L_tmp = Mult_32_16(wk1r,x0r); /*Q(15+Qx+Q_edct) */ + L_tmp = Msub_32_16(L_tmp,wk1i,x0i); /*Q(15+Qx+Q_edct) */ + a[j1] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + L_tmp = Mult_32_16(wk1r,x0i); /*Q(15+Qx+Q_edct) */ + L_tmp = Madd_32_16(L_tmp,wk1i,x0r); /*Q(15+Qx+Q_edct) */ + a[j1 + 1] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + L_x0r = L_add((Word32) x1r, (Word32) x3i); + L_x0i = L_sub((Word32) x1i, (Word32) x3r); + x0r = extract_l(L_x0r); + x0i = extract_l(L_x0i); + L_tmp = Mult_32_16(wk3r,x0r); /*Q(15+Qx+Q_edct) */ + L_tmp = Msub_32_16(L_tmp,wk3i,x0i); /*Q(15+Qx+Q_edct) */ + a[j3] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + L_tmp = Mult_32_16(wk3r,x0i); /*Q(15+Qx+Q_edct) */ + L_tmp = Madd_32_16(L_tmp,wk3i,x0r); /*Q(15+Qx+Q_edct) */ + a[j3 + 1] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + } + + wk1r = w[k2 + 2]; + move32(); + wk1i = w[k2 + 3]; + move32(); + L_tmp = L_shl(Mult_32_32(wk2r,wk1i),1);/*Q29 */ + wk3r = L_sub(wk1r,L_shl(L_tmp,1)); /*Q30 */ + + L_tmp = L_shl(Mult_32_32(wk2r,wk1r),1);/*Q29 */ + wk3i = L_sub(L_shl(L_tmp,1),wk1i); /*Q30 */ + + tmp2 = add(l,add(k,m)); + FOR (j = add(k,m); j < tmp2; j += 2) + { + j1 = add(j,l); + j2 = add(j1,l); + j3 = add(j2,l); + x0r = add(a[j],a[j1]); + x0i = add(a[j + 1],a[j1 + 1]); + x1r = sub(a[j],a[j1]); + x1i = sub(a[j + 1],a[j1 + 1]); + x2r = add(a[j2],a[j3]); + x2i = add(a[j2 + 1],a[j3 + 1]); + x3r = sub(a[j2],a[j3]); + x3i = sub(a[j2 + 1],a[j3 + 1]); + a[j] = add(x0r,x2r); + move16(); + a[j + 1] = add(x0i,x2i); + move16(); + + x0r = sub(x0r,x2r); + x0i = sub(x0i,x2i); + + tmp = negate(x0r); + L_tmp = Mult_32_16(wk2i,tmp);/*Q(15+Qx+Q_edct) */ + L_tmp = Msub_32_16(L_tmp,wk2r,x0i); /*Q(15+Qx+Q_edct) */ + a[j2] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + tmp = negate(x0i); + L_tmp = Mult_32_16(wk2i,tmp);/*Q(15+Qx+Q_edct) */ + L_tmp = Madd_32_16(L_tmp,wk2r,x0r); /*Q(15+Qx+Q_edct) */ + a[j2 + 1] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + x0r = sub(x1r,x3i); + x0i = add(x1i,x3r); + + L_tmp = Mult_32_16(wk1r,x0r);/*Q(15+Qx+Q_edct) */ + L_tmp = Msub_32_16(L_tmp,wk1i,x0i); /*Q(15+Qx+Q_edct) */ + a[j1] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + L_tmp = Mult_32_16(wk1r,x0i);/*Q(15+Qx+Q_edct) */ + L_tmp = Madd_32_16(L_tmp,wk1i,x0r); /*Q(15+Qx+Q_edct) */ + a[j1 + 1] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + x0r = add(x1r,x3i); + x0i = sub(x1i,x3r); + + L_tmp = Mult_32_16(wk3r,x0r); /*Q(15+Qx+Q_edct) */ + L_tmp = Msub_32_16(L_tmp,wk3i,x0i); /*Q(15+Qx+Q_edct) */ + a[j3] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + + L_tmp = Mult_32_16(wk3r,x0i); /*Q(15+Qx+Q_edct) */ + L_tmp = Madd_32_16(L_tmp,wk3i,x0r); /*Q(15+Qx+Q_edct) */ + a[j3 + 1] = round_fx(L_shl(L_tmp,1)); /*Q(Qx+Q_edct) */ + } + } + + return; +} + +void fft3_fx(const Word16 X[], Word16 Y[], const Word16 n) +{ + Word16 Z[PH_ECU_SPEC_SIZE]; + Word16 *Z0, *Z1, *Z2; + Word16 *z0, *z1, *z2; + const Word16 *x; + const Word16 *t_sin = sincos_t_rad3_fx; + Word16 m, mMinus1, step; + Word16 i, l; + Word16 c1_ind, s1_ind, c2_ind, s2_ind; + Word16 c1_step, s1_step, c2_step, s2_step; + Word16 *RY, *IY, *RZ0, *IZ0, *RZ1, *IZ1, *RZ2, *IZ2; + Word32 acc; + Word16 mBy2, orderMinus1; + const Word16 *pPhaseTbl; + + /* Determine the order of the transform, the length of decimated */ + /* transforms m, and the step for the sine and cosine tables. */ + SWITCH(n) + { + case 1536: + orderMinus1 = 9-1; + move16(); + m = 512; + move16(); + step = 1; + move16(); + pPhaseTbl = FFT_W256; + BREAK; + case 384: + orderMinus1 = 7-1; + move16(); + m = 128; + move16(); + step = 4; + move16(); + pPhaseTbl = FFT_W64; + BREAK; + default: + orderMinus1 = 7-1; + move16(); + m = 128; + move16(); + step = 4; + move16(); + pPhaseTbl = FFT_W64; + BREAK; + } + + /* Compose decimated sequences X[3i], X[3i+1],X[3i+2] */ + /* compute their FFT of length m. */ + Z0 = &Z[0]; + z0 = &Z0[0]; + Z1 = &Z0[m]; + z1 = &Z1[0]; /* Z1 = &Z[ m]; */ + Z2 = &Z1[m]; + z2 = &Z2[0]; /* Z2 = &Z[2m]; */ + x = &X[0]; + FOR (i = 0; i < m; i++) + { + *z0++ = *x++; /* Z0[i] = X[3i]; */ move16(); + *z1++ = *x++; /* Z1[i] = X[3i+1]; */ move16(); + *z2++ = *x++; /* Z2[i] = X[3i+2]; */ move16(); + } + mBy2 = shr(m,1); + r_fft_fx_lc(pPhaseTbl, m, mBy2, orderMinus1, Z0, Z0, 1); + r_fft_fx_lc(pPhaseTbl, m, mBy2, orderMinus1, Z1, Z1, 1); + r_fft_fx_lc(pPhaseTbl, m, mBy2, orderMinus1, Z2, Z2, 1); + + /* Butterflies of order 3. */ + /* pointer initialization */ + mMinus1 = sub(m,1); + RY = &Y[0]; + IY = &Y[n]; + IY--; /* Decrement the address counter.*/ + RZ0 = &Z0[0]; + IZ0 = &Z0[mMinus1]; + RZ1 = &Z1[0]; + IZ1 = &Z1[mMinus1]; + RZ2 = &Z2[0]; + IZ2 = &Z2[mMinus1]; + + c1_step = negate(step); + s1_step = step; + move16(); + c2_step = shl(c1_step,1); + s2_step = shl(s1_step,1); + c1_ind = add(T_SIN_PI_2, c1_step); + s1_ind = s1_step; + move16(); + c2_ind = add(T_SIN_PI_2, c2_step); + s2_ind = s2_step; + move16(); + + /* special case: i = 0 */ + acc = L_mult(*RZ0++, 0x4000); + acc = L_mac(acc, *RZ1++, 0x4000); + *RY++ = mac_r(acc, *RZ2++, 0x4000); + move16(); + + /* first 3/12-- from 1 to (3*m/8)-1 */ + l = sub(shr(n, 3),1); /* (3*m/8) - 1 = (n/8) - 1 */ + FOR (i = 0; i < l; i++) + { + acc = L_shl(*RZ0++, 15); /* Align with the following non-fractional mode so as to gain 1 more bit headroom. */ + acc = L_mac0(acc, *RZ1, t_sin[c1_ind]); /* Non-fractional mode gains 1 more bit headroom. */ + acc = L_mac0(acc, *IZ1, t_sin[s1_ind]); + acc = L_mac0(acc, *RZ2, t_sin[c2_ind]); + acc = L_mac0(acc, *IZ2, t_sin[s2_ind]); + *RY++ = round_fx(acc); /* bit growth = 1 (compensated by non-fractional mode MAC). */ + + acc = L_shl(*IZ0--, 15); + acc = L_msu0(acc, *RZ1++, t_sin[s1_ind]); + acc = L_mac0(acc, *IZ1--, t_sin[c1_ind]); + acc = L_msu0(acc, *RZ2++, t_sin[s2_ind]); + acc = L_mac0(acc, *IZ2--, t_sin[c2_ind]); + *IY-- = round_fx(acc); + + c1_ind = add(c1_ind, c1_step); + s1_ind = add(s1_ind, s1_step); + c2_ind = add(c2_ind, c2_step); + s2_ind = add(s2_ind, s2_step); + } + + /* next 1/12-- from (3*m/8) to (4*m/8)-1 */ + l = shr(m,3); /* (4*m/8) - (3*m/8) = m/8 */ + FOR (i = 0; i < l; i++) + { + acc = L_shl(*RZ0++, 15); + acc = L_mac0(acc, *RZ1, t_sin[c1_ind]); /* Non-fractional mode gains 1 more bit headroom. */ + acc = L_mac0(acc, *IZ1, t_sin[s1_ind]); + acc = L_msu0(acc, *RZ2, t_sin[c2_ind]); + acc = L_mac0(acc, *IZ2, t_sin[s2_ind]); + *RY++ = round_fx(acc); + + acc = L_shl(*IZ0--, 15); + acc = L_msu0(acc, *RZ1++, t_sin[s1_ind]); + acc = L_mac0(acc, *IZ1--, t_sin[c1_ind]); + acc = L_msu0(acc, *RZ2++, t_sin[s2_ind]); + acc = L_msu0(acc, *IZ2--, t_sin[c2_ind]); + *IY-- = round_fx(acc); + + c1_ind = add(c1_ind, c1_step); + s1_ind = add(s1_ind, s1_step); + c2_ind = sub(c2_ind, c2_step); + s2_ind = sub(s2_ind, s2_step); + } + + /* special case: i = m/2 i.e. 1/3 */ + acc = L_shl(*RZ0--, 15); + acc = L_mac0(acc, *RZ1, t_sin[c1_ind]); + acc = L_msu0(acc, *RZ2, t_sin[c2_ind]); + *RY++ = round_fx(acc); + + acc = 0; + acc = L_msu0(acc, *RZ1--, t_sin[s1_ind]); + acc = L_msu0(acc, *RZ2--, t_sin[s2_ind]); + *IY-- = round_fx(acc); + IZ0++; + IZ1++; + IZ2++; + + c1_ind = add(c1_ind, c1_step); + s1_ind = add(s1_ind, s1_step); + c2_ind = sub(c2_ind, c2_step); + s2_ind = sub(s2_ind, s2_step); + + /* next 2/12-- from ((m/2)+1) to (6*m/8)-1 */ + l = sub(shr(m,2), 1); /* (6*m/8) - ((m/2)+1) = m/4 - 1 */ + FOR (i = 0; i < l; i++) + { + acc = L_shl(*RZ0--, 15); + acc = L_mac0(acc, *RZ1, t_sin[c1_ind]); /* Non-fractional mode gains 1 more bit headroom. */ + acc = L_msu0(acc, *IZ1, t_sin[s1_ind]); + acc = L_msu0(acc, *RZ2, t_sin[c2_ind]); + acc = L_msu0(acc, *IZ2, t_sin[s2_ind]); + *RY++ = round_fx(acc); + + acc = L_mult0(*IZ0++, -32768); + acc = L_msu0(acc, *RZ1--, t_sin[s1_ind]); + acc = L_msu0(acc, *IZ1++, t_sin[c1_ind]); + acc = L_msu0(acc, *RZ2--, t_sin[s2_ind]); + acc = L_mac0(acc, *IZ2++, t_sin[c2_ind]); + *IY-- = round_fx(acc); + + c1_ind = add(c1_ind, c1_step); + s1_ind = add(s1_ind, s1_step); + c2_ind = sub(c2_ind, c2_step); + s2_ind = sub(s2_ind, s2_step); + } + + /*--------------------------half--------------------------// */ + /* next 2/12-- from (6*m/8) to (8*m/8) - 1 */ + l = shr(m,2); + FOR (i = 0; i < l; i++) + { + acc = L_shl(*RZ0--, 15); + acc = L_msu0(acc, *RZ1, t_sin[c1_ind]); /* Non-fractional mode gains 1 more bit headroom. */ + acc = L_msu0(acc, *IZ1, t_sin[s1_ind]); + acc = L_msu0(acc, *RZ2, t_sin[c2_ind]); + acc = L_mac0(acc, *IZ2, t_sin[s2_ind]); + *RY++ = round_fx(acc); + + acc = L_mult0(*IZ0++, -32768); + acc = L_msu0(acc, *RZ1--, t_sin[s1_ind]); + acc = L_mac0(acc, *IZ1++, t_sin[c1_ind]); + acc = L_mac0(acc, *RZ2--, t_sin[s2_ind]); + acc = L_mac0(acc, *IZ2++, t_sin[c2_ind]); + *IY-- = round_fx(acc); + + c1_ind = sub(c1_ind, c1_step); + s1_ind = sub(s1_ind, s1_step); + c2_ind = add(c2_ind, c2_step); + s2_ind = add(s2_ind, s2_step); + } + + /* special case: i = m, i.e 2/3 */ + acc = L_shl(*RZ0++, 15); + acc = L_msu0(acc, *RZ1, t_sin[c1_ind]); + acc = L_msu0(acc, *RZ2, t_sin[c2_ind]); + *RY++ = round_fx(acc); + + acc = L_deposit_l(0); + acc = L_msu0(acc, *RZ1++, t_sin[s1_ind]); + acc = L_mac0(acc, *RZ2++, t_sin[s2_ind]); + *IY-- = round_fx(acc); + IZ0--; /* Just decrement the address counter */ + IZ1--; + IZ2--; + + c1_ind = sub(c1_ind, c1_step); + s1_ind = sub(s1_ind, s1_step); + c2_ind = add(c2_ind, c2_step); + s2_ind = add(s2_ind, s2_step); + + /* next 1/12-- from (m + 1) to (9*m/8) - 1 */ + l = sub(shr(m, 3), 1); /* (9*m/8) - (m +1) = m/8 - 1 */ + FOR (i = 0; i < l; i++) + { + acc = L_shl(*RZ0++, 15); + acc = L_msu0(acc, *RZ1, t_sin[c1_ind]); /* Non-fractional mode gains 1 more bit headroom. */ + acc = L_mac0(acc, *IZ1, t_sin[s1_ind]); + acc = L_msu0(acc, *RZ2, t_sin[c2_ind]); + acc = L_msu0(acc, *IZ2, t_sin[s2_ind]); + *RY++ = round_fx(acc); + + acc = L_shl(*IZ0--, 15); + acc = L_msu0(acc, *RZ1++, t_sin[s1_ind]); + acc = L_msu0(acc, *IZ1--, t_sin[c1_ind]); + acc = L_mac0(acc, *RZ2++, t_sin[s2_ind]); + acc = L_msu0(acc, *IZ2--, t_sin[c2_ind]); + *IY-- = round_fx(acc); + + c1_ind = sub(c1_ind, c1_step); + s1_ind = sub(s1_ind, s1_step); + c2_ind = add(c2_ind, c2_step); + s2_ind = add(s2_ind, s2_step); + } + + /* last 3/12-- from (9*m/8) to (12*m/8) - 1 */ + l = shr(n,3); /* (12*m/8) - (9*m/8) = 3*m/8 = n/8 */ + FOR (i = 0; i < l; i++) + { + acc = L_shl(*RZ0++, 15); + acc = L_msu0(acc, *RZ1, t_sin[c1_ind]); /* Non-fractional mode gains 1 more bit headroom. */ + acc = L_mac0(acc, *IZ1, t_sin[s1_ind]); + acc = L_mac0(acc, *RZ2, t_sin[c2_ind]); + acc = L_msu0(acc, *IZ2, t_sin[s2_ind]); + *RY++ = round_fx(acc); + + acc = L_shl(*IZ0--, 15); + acc = L_msu0(acc, *RZ1++, t_sin[s1_ind]); + acc = L_msu0(acc, *IZ1--, t_sin[c1_ind]); + acc = L_mac0(acc, *RZ2++, t_sin[s2_ind]); + acc = L_mac0(acc, *IZ2--, t_sin[c2_ind]); + *IY-- = round_fx(acc); + + c1_ind = sub(c1_ind, c1_step); + s1_ind = sub(s1_ind, s1_step); + c2_ind = sub(c2_ind, c2_step); + s2_ind = sub(s2_ind, s2_step); + } + + /* special case: i = 3*m/2 */ + acc = L_shl(*RZ0, 15); + acc = L_msu0(acc, *RZ1, t_sin[c1_ind]); + acc = L_mac0(acc, *RZ2, t_sin[c2_ind]); + *RY = round_fx(acc); + + return; +} + + +void ifft3_fx(const Word16 Z[], Word16 X[], const Word16 n) +{ + Word16 Y[PH_ECU_SPEC_SIZE]; + const Word16 *t_sin = sincos_t_rad3_fx; + Word16 m, mMinus1, step, step2; + Word16 i, l; + Word16 c0_ind, s0_ind, c1_ind, s1_ind, c2_ind, s2_ind; + const Word16 *RZ0, *IZ0, *RZ1, *IZ1, *RZ2, *IZ2; + const Word16 *RZ00, *IZ00, *RZ10, *IZ10, *RZ20, *IZ20; + Word16 *RY0, *IY0, *RY1, *IY1, *RY2, *IY2, *y0, *y1, *y2, *pX; + Word32 acc; + Word16 mBy2, orderMinus1, nMinusMBy2; + const Word16 *pPhaseTbl; + + /* Determine the order of the transform, the length of decimated */ + /* transforms m, and the step for the sine and cosine tables. */ + SWITCH(n) + { + case 1536: + orderMinus1 = 9-1; + move16(); + m = 512; + move16(); + step = 1; + move16(); + pPhaseTbl = FFT_W256; + BREAK; + case 384: + orderMinus1 = 7-1; + move16(); + m = 128; + move16(); + step = 4; + move16(); + pPhaseTbl = FFT_W64; + BREAK; + default: + orderMinus1 = 7-1; + move16(); + m = 128; + move16(); + step = 4; + move16(); + pPhaseTbl = FFT_W64; + BREAK; + } + + nMinusMBy2 = shr(sub(n, m),1); + mMinus1 = sub(m,1); + /* pointer initialization */ + RY0 = &Y[0]; + IY0 = &Y[m]; + RY1 = &RY0[m]; + IY1 = &RY1[mMinus1]; + RY2 = &RY1[m]; + IY2 = &RY2[mMinus1]; + + RZ00 = &Z[0]; /* The zero positions of the pointers */ + RZ10 = &RZ00[m]; + RZ20 = &RZ00[nMinusMBy2]; + IZ00 = &Z[n]; + IZ10 = &IZ00[-m]; + IZ20 = &IZ00[-nMinusMBy2]; + + RZ0 = RZ00; /* Reset the pointers to zero positions. */ + RZ1 = RZ10; + RZ2 = RZ20; + IZ0 = IZ00; + IZ1 = IZ10; + IZ2 = IZ20; + + /* Inverse butterflies of order 3. */ + + /* Construction of Y0 */ + acc = L_mult(*RZ0++, 0x4000); + acc = L_mac(acc, *RZ1++, 0x4000); + *RY0++ = mac_r(acc, *RZ2--, 0x4000); + move16(); + IZ0--; + IZ1--; + IZ2++; + IY0--; + + l = sub(shr(m, 1), 1); + FOR (i = 0; i < l; i++) + { + acc = L_mult(*RZ0++, 0x4000); + acc = L_mac(acc, *RZ1++, 0x4000); + *RY0++ = mac_r(acc, *RZ2--, 0x4000); + move16(); + + acc = L_mult(*IZ0--, 0x4000); + acc = L_mac(acc, *IZ1--, 0x4000); + *IY0-- = msu_r(acc, *IZ2++, 0x4000); + move16(); + } + + /* m/2 */ + acc = L_mult(*RZ0, 0x4000); + acc = L_mac(acc, *RZ1, 0x4000); + *RY0++ = mac_r(acc, *RZ2, 0x4000); + move16(); + + + /* Construction of Y1 */ + c0_ind=T_SIN_PI_2; + s0_ind=0; + c1_ind=T_SIN_PI_2*1/3; + s1_ind=T_SIN_PI_2*2/3; + c2_ind=T_SIN_PI_2*1/3; + s2_ind=T_SIN_PI_2*2/3; + + RZ0 = RZ00; /* Reset pointers to zero positions. */ + RZ1 = RZ10; + RZ2 = RZ20; + IZ0 = IZ00; + IZ1 = IZ10; + IZ2 = IZ20; + acc = L_mult0(*RZ0++, t_sin[c0_ind]); + acc = L_msu0(acc, *RZ1++, t_sin[c1_ind]); + acc = L_msu0(acc, *RZ2--, t_sin[c2_ind]); + IZ0--; + acc = L_msu0(acc, *IZ1--, t_sin[s1_ind]); + acc = L_msu0(acc, *IZ2++, t_sin[s2_ind]); + *RY1++ = round_fx(acc); + + c0_ind=sub(c0_ind,step); + s0_ind=add(s0_ind,step); + c1_ind=add(c1_ind,step); + s1_ind=sub(s1_ind,step); + c2_ind=sub(c2_ind,step); + s2_ind=add(s2_ind,step); + + /* From 1 to (m/4) - 1. */ + l = sub(shr(m,2),1); + FOR (i = 0; i < l; i++) + { + acc = L_mult0(*RZ0, t_sin[c0_ind]); + acc = L_msu0(acc, *RZ1, t_sin[c1_ind]); + acc = L_msu0(acc, *RZ2, t_sin[c2_ind]); + acc = L_msu0(acc, *IZ0, t_sin[s0_ind]); + acc = L_msu0(acc, *IZ1, t_sin[s1_ind]); + acc = L_msu0(acc, *IZ2, t_sin[s2_ind]); + *RY1++ = round_fx(acc); + + acc = L_mult0(*IZ0--, t_sin[c0_ind]); + acc = L_msu0(acc, *IZ1--, t_sin[c1_ind]); + acc = L_mac0(acc, *IZ2++, t_sin[c2_ind]); + acc = L_mac0(acc, *RZ0++, t_sin[s0_ind]); + acc = L_mac0(acc, *RZ1++, t_sin[s1_ind]); + acc = L_msu0(acc, *RZ2--, t_sin[s2_ind]); + *IY1-- = round_fx(acc); + + c0_ind=sub(c0_ind,step); + s0_ind=add(s0_ind,step); + c1_ind=add(c1_ind,step); + s1_ind=sub(s1_ind,step); + c2_ind=sub(c2_ind,step); + s2_ind=add(s2_ind,step); + } + + /* From m/4 to m/2 -1. */ + l = shr(m, 2); /* m/2 - m/4 = m/4 */ + FOR (i = 0; i < l; i++) + { + acc = L_mult0(*RZ0, t_sin[c0_ind]); + acc = L_msu0(acc, *RZ1, t_sin[c1_ind]); + acc = L_mac0(acc, *RZ2, t_sin[c2_ind]); + acc = L_msu0(acc, *IZ0, t_sin[s0_ind]); + acc = L_msu0(acc, *IZ1, t_sin[s1_ind]); + acc = L_msu0(acc, *IZ2, t_sin[s2_ind]); + *RY1++ = round_fx(acc); + + acc = L_mult0(*IZ0--, t_sin[c0_ind]); + acc = L_msu0(acc, *IZ1--, t_sin[c1_ind]); + acc = L_msu0(acc, *IZ2++, t_sin[c2_ind]); + acc = L_mac0(acc, *RZ0++, t_sin[s0_ind]); + acc = L_mac0(acc, *RZ1++, t_sin[s1_ind]); + acc = L_msu0(acc, *RZ2--, t_sin[s2_ind]); + *IY1-- = round_fx(acc); + + c0_ind=sub(c0_ind,step); + s0_ind=add(s0_ind,step); + c1_ind=add(c1_ind,step); + s1_ind=sub(s1_ind,step); + c2_ind=add(c2_ind,step); + s2_ind=sub(s2_ind,step); + } + + /* m/2 */ + acc = L_mult0(*RZ0, t_sin[c0_ind]); + acc = L_msu0(acc, *RZ1, t_sin[c1_ind]); + acc = L_mac0(acc, *RZ2, t_sin[c2_ind]); + acc = L_msu0(acc, *IZ0, t_sin[s0_ind]); + acc = L_msu0(acc, *IZ1, t_sin[s1_ind]); + acc = L_msu0(acc, *IZ2, t_sin[s2_ind]); + *RY1++ = round_fx(acc); + + /* Construction of Y2 */ + c0_ind=T_SIN_PI_2; + s0_ind=0; + c1_ind=T_SIN_PI_2*1/3; + s1_ind=T_SIN_PI_2*2/3; + c2_ind=T_SIN_PI_2*1/3; + s2_ind=T_SIN_PI_2*2/3; + step2 = shl(step,1); + + RZ0 = RZ00; /* Reset pointers to zero positions. */ + RZ1 = RZ10; + RZ2 = RZ20; + IZ0 = IZ00; + IZ1 = IZ10; + IZ2 = IZ20; + acc = L_mult0(*RZ0++, t_sin[c0_ind]); + acc = L_msu0(acc, *RZ1++, t_sin[c1_ind]); + acc = L_msu0(acc, *RZ2--, t_sin[c2_ind]); + IZ0--; + acc = L_mac0(acc, *IZ1--, t_sin[s1_ind]); + acc = L_mac0(acc, *IZ2++, t_sin[s2_ind]); + *RY2++ = round_fx(acc); + + c0_ind=sub(c0_ind,step2); + s0_ind=add(s0_ind,step2); + c1_ind=sub(c1_ind,step2); + s1_ind=add(s1_ind,step2); + c2_ind=add(c2_ind,step2); + s2_ind=sub(s2_ind,step2); + + /* From 1 to (m/8) - 1. */ + l = sub(shr(m, 3),1); /* m/8 - 1. */ + FOR (i = 0; i < l; i++) + { + acc = L_mult0(*RZ0, t_sin[c0_ind]); + acc = L_msu0(acc, *RZ1, t_sin[c1_ind]); + acc = L_msu0(acc, *RZ2, t_sin[c2_ind]); + acc = L_msu0(acc, *IZ0, t_sin[s0_ind]); + acc = L_mac0(acc, *IZ1, t_sin[s1_ind]); + acc = L_mac0(acc, *IZ2, t_sin[s2_ind]); + *RY2++ = round_fx(acc); + + acc = L_mult0(*IZ0--, t_sin[c0_ind]); + acc = L_msu0(acc, *IZ1--, t_sin[c1_ind]); + acc = L_mac0(acc, *IZ2++, t_sin[c2_ind]); + acc = L_mac0(acc, *RZ0++, t_sin[s0_ind]); + acc = L_msu0(acc, *RZ1++, t_sin[s1_ind]); + acc = L_mac0(acc, *RZ2--, t_sin[s2_ind]); + *IY2-- = round_fx(acc); + + c0_ind=sub(c0_ind,step2); + s0_ind=add(s0_ind,step2); + c1_ind=sub(c1_ind,step2); + s1_ind=add(s1_ind,step2); + c2_ind=add(c2_ind,step2); + s2_ind=sub(s2_ind,step2); + } + + /* From (m/8) to (m/4) - 1. */ + l = shr(m, 3); /* m/4 - m/8 = m/8 */ + FOR (i = 0; i < l; i++) + { + acc = L_mult0(*RZ0, t_sin[c0_ind]); + acc = L_mac0(acc, *RZ1, t_sin[c1_ind]); + acc = L_msu0(acc, *RZ2, t_sin[c2_ind]); + acc = L_msu0(acc, *IZ0, t_sin[s0_ind]); + acc = L_mac0(acc, *IZ1, t_sin[s1_ind]); + acc = L_mac0(acc, *IZ2, t_sin[s2_ind]); + *RY2++ = round_fx(acc); + + acc = L_mult0(*IZ0--, t_sin[c0_ind]); + acc = L_mac0(acc, *IZ1--, t_sin[c1_ind]); + acc = L_mac0(acc, *IZ2++, t_sin[c2_ind]); + acc = L_mac0(acc, *RZ0++, t_sin[s0_ind]); + acc = L_msu0(acc, *RZ1++, t_sin[s1_ind]); + acc = L_mac0(acc, *RZ2--, t_sin[s2_ind]); + *IY2-- = round_fx(acc); + + c0_ind=sub(c0_ind,step2); + s0_ind=add(s0_ind,step2); + c1_ind=add(c1_ind,step2); + s1_ind=sub(s1_ind,step2); + c2_ind=add(c2_ind,step2); + s2_ind=sub(s2_ind,step2); + } + + /* From m/4 to 3*m/8 - 1. */ + l = shr(m, 3); /* 3*m/8 - m/4 = m/8 */ + FOR (i = 0; i < l; i++) + { + acc = L_mult0(*RZ0, t_sin[c0_ind]); + acc = L_mac0(acc, *RZ1, t_sin[c1_ind]); + acc = L_msu0(acc, *RZ2, t_sin[c2_ind]); + acc = L_msu0(acc, *IZ0, t_sin[s0_ind]); + acc = L_mac0(acc, *IZ1, t_sin[s1_ind]); + acc = L_msu0(acc, *IZ2, t_sin[s2_ind]); + *RY2++ = round_fx(acc); + + acc = L_mult0(*IZ0--, t_sin[c0_ind]); + acc = L_mac0(acc, *IZ1--, t_sin[c1_ind]); + acc = L_mac0(acc, *IZ2++, t_sin[c2_ind]); + acc = L_mac0(acc, *RZ0++, t_sin[s0_ind]); + acc = L_msu0(acc, *RZ1++, t_sin[s1_ind]); + acc = L_msu0(acc, *RZ2--, t_sin[s2_ind]); + *IY2-- = round_fx(acc); + + c0_ind=sub(c0_ind,step2); + s0_ind=add(s0_ind,step2); + c1_ind=add(c1_ind,step2); + s1_ind=sub(s1_ind,step2); + c2_ind=sub(c2_ind,step2); + s2_ind=add(s2_ind,step2); + } + + /* From 3*m/8 to m/2 - 1*/ + l = shr(m, 3); /* m/2 - 3*m/8 = m/8 */ + FOR (i = 0; i < l; i++) + { + acc = L_mult0(*RZ1, t_sin[c1_ind]); + acc = L_msu0(acc, *RZ0, t_sin[c0_ind]); + acc = L_msu0(acc, *RZ2, t_sin[c2_ind]); + acc = L_msu0(acc, *IZ0, t_sin[s0_ind]); + acc = L_mac0(acc, *IZ1, t_sin[s1_ind]); + acc = L_msu0(acc, *IZ2, t_sin[s2_ind]); + *RY2++ = round_fx(acc); + + acc = L_mult0(*IZ1--, t_sin[c1_ind]); + acc = L_msu0(acc, *IZ0--, t_sin[c0_ind]); + acc = L_mac0(acc, *IZ2++, t_sin[c2_ind]); + acc = L_mac0(acc, *RZ0++, t_sin[s0_ind]); + acc = L_msu0(acc, *RZ1++, t_sin[s1_ind]); + acc = L_msu0(acc, *RZ2--, t_sin[s2_ind]); + *IY2-- = round_fx(acc); + + c0_ind=add(c0_ind,step2); + s0_ind=sub(s0_ind,step2); + c1_ind=add(c1_ind,step2); + s1_ind=sub(s1_ind,step2); + c2_ind=sub(c2_ind,step2); + s2_ind=add(s2_ind,step2); + } + + /* m/2 */ + acc = L_mult0(*RZ1, t_sin[c1_ind]); + acc = L_msu0(acc, *RZ0, t_sin[c0_ind]); + acc = L_msu0(acc, *RZ2, t_sin[c2_ind]); + acc = L_msu0(acc, *IZ0, t_sin[s0_ind]); + acc = L_mac0(acc, *IZ1, t_sin[s1_ind]); + acc = L_msu0(acc, *IZ2, t_sin[s2_ind]); + *RY2++ = round_fx(acc); + + /* Compute the inverse FFT for all 3 blocks. */ + RY0 = &Y[0]; /* Rewind the pointers. */ + RY1 = &Y[m]; + RY2 = &RY1[m]; + mBy2 = shr(m,1); + r_fft_fx_lc(pPhaseTbl, m, mBy2, orderMinus1, RY0, RY0, 0); /* inverse FFT */ + r_fft_fx_lc(pPhaseTbl, m, mBy2, orderMinus1, RY1, RY1, 0); /* inverse FFT */ + r_fft_fx_lc(pPhaseTbl, m, mBy2, orderMinus1, RY2, RY2, 0); /* inverse FFT */ + + y0 = RY0; + y1 = RY1; + y2 = RY2; + + /* Interlacing and scaling, scale = 1/3 */ + pX = X; + FOR (i = 0; i < m; i++) + { + *pX++ = shl(mult_r(*y0++, FFT3_ONE_THIRD), 1); + move16(); + *pX++ = shl(mult_r(*y1++, FFT3_ONE_THIRD), 1); + move16(); + *pX++ = shl(mult_r(*y2++, FFT3_ONE_THIRD), 1); + move16(); + } + + return; +} diff --git a/lib_com/fft_rel_fx.c b/lib_com/fft_rel_fx.c new file mode 100644 index 0000000..51aa3e6 --- /dev/null +++ b/lib_com/fft_rel_fx.c @@ -0,0 +1,433 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" + +#include "stdint.h" +/*------------------------------------------------------------------ + * + * This is an implementation of decimation-in-time FFT algorithm for + * real sequences. The techniques used here can be found in several + * books, e.g., i) Proakis and Manolakis, "Digital Signal Processing", + * 2nd Edition, Chapter 9, and ii) W.H. Press et. al., "Numerical + * Recipes in C", 2nd Edition, Chapter 12. + * + * Input - There are two inputs to this function: + * + * 1) An integer pointer to the input data array + * 2) An integer value which should be set as +1 for FFT + * and some other value, e.g., -1 for ifFT + * + * Output - There is no return value. + * The input data are replaced with transformed data. if the + * input is a real time domain sequence, it is replaced with + * the complex FFT for positive frequencies. The FFT value + * for DC and the foldover frequency are combined to form the + * first complex number in the array. The remaining complex + * numbers correspond to increasing frequencies. if the input + * is a complex frequency domain sequence arranged as above, + * it is replaced with the corresponding time domain sequence. + * + * Notes: + * + * 1) This function is designed to be a part of a noise supp- + * ression algorithm that requires 128-point FFT of real + * sequences. This is achieved here through a 64-point + * complex FFT. Consequently, the FFT size information is + * not transmitted explicitly. However, some flexibility + * is provided in the function to change the size of the + * FFT by specifying the size information through "define" + * statements. + * + * 2) The values of the complex sinusoids used in the FFT + * algorithm are computed once (i.e., the first time the + * r_fft function is called) and stored in a table. To + * further speed up the algorithm, these values can be + * precomputed and stored in a ROM table in actual DSP + * based implementations. + * + * 3) In the c_fft function, the FFT values are divided by + * 2 after each stage of computation thus dividing the + * final FFT values by 64. No multiplying factor is used + * for the ifFT. This is somewhat different from the usual + * definition of FFT where the factor 1/N, i.e., 1/64, is + * used for the ifFT and not the FFT. No factor is used in + * the r_fft function. + * + * 4) Much of the code for the FFT and ifFT parts in r_fft + * and c_fft functions are similar and can be combined. + * They are, however, kept separate here to speed up the + * execution. + *------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------* + * c_fft_fx: + * + * Computes the complex part of the split-radix FFT + *------------------------------------------------------------------------*/ + +static void c_fft_fx( + const Word16 *phs_tbl, /* i : Table of phases */ + Word16 SIZE, /* i : Size of the FFT */ + Word16 NUM_STAGE, /* i : Number of stages */ + const Word16 *in_ptr, /* i : coefficients in the order re[0], re[n/2], re[1], im[1], ..., re[n/2-1], im[n/2-1] */ + Word16 *out_ptr, /* o : coefficients in the order re[0], re[n/2], re[1], im[1], ..., re[n/2-1], im[n/2-1] */ + /* in_ptr & out_ptr must not overlap! */ + const Word16 isign) /* i : 1=fft, otherwise it is ifft*/ +{ + Word16 i, j, k, ii, jj, kk, ji, kj; + Word32 L_tmp1, L_tmp2; + Word16 tmp1,tmp2,tmp3,tmp4; + const Word16 *table_ptr; + const Word16 *input_ptr1,*input_ptr2,*input_ptr3,*input_ptr4; + Word16 shift=0; + /* Setup Reorder Variables */ + table_ptr = NULL; + table_ptr = FFT_REORDER_1024; + SWITCH(SIZE) + { + case 1024: + shift = 0; + BREAK; + case 512: + shift = 1; + BREAK; + case 256: + shift = 2; + BREAK; + case 128: + shift = 3; + BREAK; + case 64: + shift = 4; + BREAK; + } + /* The FFT part */ + IF (isign != 0) + { + /* Unrolled 1st/2nd Stage + * 1) to take advantage of Table Values (0 & +/- 16384) + * 2) to perform reordering of Input Values + */ + FOR (k = 0; k < SIZE; k += 8) + { + /* + * This loop use: + * 4 Word16 (tmp1...tmp4) + * 2 Word32 (L_tmp1 & L_tmp2) + * 4 Pointers (table_ptr, input_ptr1, input_ptr2, input_ptr3) + * + * The addition of 'in_ptr' + and index value from 'reorder_ptr' + * is counted as a move16() + */ + + input_ptr1 = in_ptr + (const Word16 ) ((uintptr_t)(*table_ptr++)>>(uintptr_t)shift); + + L_tmp1 = L_mult(*input_ptr1++, 16384); + L_tmp2 = L_mult(*input_ptr1, 16384); + + input_ptr1 = in_ptr + (const Word16)((uintptr_t)(*table_ptr++) >> (uintptr_t)shift); + + tmp1 = msu_r(L_tmp1, *input_ptr1, 16384); + tmp3 = mac_r(L_tmp1, *input_ptr1++, 16384); + + input_ptr2 = in_ptr + (const Word16)((uintptr_t)(*table_ptr++) >> (uintptr_t)shift); + input_ptr3 = in_ptr + (const Word16)((uintptr_t)(*table_ptr++) >> (uintptr_t)shift); + + L_tmp1 = L_mult(*input_ptr2++, 16384); + tmp2 = mac_r(L_tmp1, *input_ptr3, 16384); + tmp4 = msu_r(L_tmp1, *input_ptr3++, 16384); + + L_tmp1 = L_mult(tmp3, 16384); + out_ptr[k] = mac_r(L_tmp1, tmp2, 16384); + move16(); + out_ptr[k+4] = msu_r(L_tmp1, tmp2, 16384); + move16(); + + tmp2 = mac_r(L_tmp2, *input_ptr1, 16384); + tmp3 = msu_r(L_tmp2, *input_ptr1, 16384); + + L_tmp2 = L_mult(*input_ptr2, 16384); + + L_tmp1 = L_mult(tmp1, 16384); + tmp1 = msu_r(L_tmp2, *input_ptr3, 16384); + out_ptr[k+2] = mac_r(L_tmp1, tmp1, 16384); + move16(); + out_ptr[k+6] = msu_r(L_tmp1, tmp1, 16384); + move16(); + + L_tmp1 = L_mult(tmp2, 16384); + tmp2 = mac_r(L_tmp2, *input_ptr3, 16384); + out_ptr[k+1] = mac_r(L_tmp1, tmp2, 16384); + move16(); + out_ptr[k+5] = msu_r(L_tmp1, tmp2, 16384); + move16(); + + L_tmp1 = L_mult(tmp3, 16384); + out_ptr[k+3] = msu_r(L_tmp1, tmp4, 16384); + move16(); + out_ptr[k+7] = mac_r(L_tmp1, tmp4, 16384); + move16(); + } + + /* Remaining Stages */ + FOR (i = 2; i < NUM_STAGE; i++) + { + /* i is stage counter */ + jj = shl(2, i); /* FFT size */ + kk = shl(jj, 1); /* 2 * FFT size */ + ii = shr(SIZE, i); + ji = 0; + move16(); /* ji is phase table index */ + + FOR (j = 0; j < jj; j += 2) + { + /* j is sample counter */ + FOR (k = j; k < SIZE; k += kk) + { + /* k is butterfly top */ + kj = add(k, jj); /* kj is butterfly bottom */ + + /* Butterfly computations */ + L_tmp1 = L_msu(L_mult(*(out_ptr + kj), phs_tbl[ji]), + *(out_ptr + kj + 1), phs_tbl[ji + 1]); + L_tmp2 = L_mac(L_mult(*(out_ptr + kj + 1), phs_tbl[ji]), + *(out_ptr + kj), phs_tbl[ji + 1]); + + out_ptr[kj] = mac_r(L_negate(L_tmp1), out_ptr[k], 16384); + move16(); + out_ptr[kj+1] = mac_r(L_negate(L_tmp2), out_ptr[k+1], 16384); + move16(); + out_ptr[k] = mac_r(L_tmp1, out_ptr[k], 16384); + move16(); + out_ptr[k+1] = mac_r(L_tmp2, out_ptr[k+1], 16384); + move16(); + } + ji = add(ji, ii); + } + } + } + ELSE /* The ifFT part */ + { + /* Unrolled 1st/2nd Stage + * 1) to take advantage of Table Values (0 & +/- 16384) + * 2) to perform reordering of Input Values + */ + FOR (k = 0; k < SIZE; k += 8) + { + /* + * This loop use: + * 4 Word16 (tmp1...tmp4) + * 2 Word32 (L_tmp1 & L_tmp2) + * 5 Pointers (reorder_ptr, input_ptr1...input_ptr4) + * + * The addition of 'in_ptr' + and index value from 'reorder_ptr' + * is counted as a move16() + */ + input_ptr1= in_ptr + (const Word16)((uintptr_t)(*table_ptr++) >> (uintptr_t)shift); + input_ptr2 = in_ptr + (const Word16)((uintptr_t)(*table_ptr++) >> (uintptr_t)shift); + + input_ptr3 = in_ptr + (const Word16)((uintptr_t)(*table_ptr++) >> (uintptr_t)shift); + input_ptr4 = in_ptr + (const Word16)((uintptr_t)(*table_ptr++) >> (uintptr_t)shift); + + + tmp3 = sub(*input_ptr1, *input_ptr2); + tmp4 = add(*input_ptr1++, *input_ptr2++); + + tmp2 = sub(input_ptr3[0], input_ptr4[0]); + tmp1 = sub(input_ptr3[1], input_ptr4[1]); + + out_ptr[k+2] = sub(tmp3, tmp1); + move16(); + out_ptr[k+6] = add(tmp3, tmp1); + move16(); + + tmp1 = sub(*input_ptr1, *input_ptr2); + out_ptr[k+3] = add(tmp1, tmp2); + move16(); + out_ptr[k+7] = sub(tmp1, tmp2); + move16(); + + tmp1 = add(input_ptr3[0], input_ptr4[0]); + tmp3 = add(input_ptr3[1], input_ptr4[1]); + + out_ptr[k] = add(tmp4, tmp1); + move16(); + out_ptr[k+4] = sub(tmp4, tmp1); + move16(); + + tmp4 = add(*input_ptr1, *input_ptr2); + out_ptr[k+1] = add(tmp4, tmp3); + move16(); + out_ptr[k+5] = sub(tmp4, tmp3); + move16(); + } + + table_ptr = phs_tbl + SIZE; /* access part of table that is scaled by 2 */ + + /* Remaining Stages */ + FOR (i = 2; i < NUM_STAGE; i++) + { + /* i is stage counter */ + jj = shl(2, i); /* FFT size */ + kk = shl(jj, 1); /* 2 * FFT size */ + ii = shr(SIZE, i); + ji = 0; + move16(); /* ji is phase table index */ + + FOR (j = 0; j < jj; j += 2) + { + /* j is sample counter */ + /* This can be computed by successive add_fxitions of ii to ji, starting from 0 + hence line-count it as a one-line add (still need to increment op count!!) */ + + FOR (k = j; k < SIZE; k += kk) + { + /* k is butterfly top */ + kj = add(k, jj); /* kj is butterfly bottom */ + + /* Butterfly computations */ + tmp1 = mac_r(L_mult(out_ptr[kj], table_ptr[ji]), + out_ptr[kj+1], table_ptr[ji + 1]); + + tmp2 = msu_r(L_mult(out_ptr[kj+1], table_ptr[ji]), + out_ptr[kj], table_ptr[ji+1]); + + out_ptr[kj] = sub(out_ptr[k], tmp1); + move16(); + out_ptr[kj+1] = sub(out_ptr[k+1], tmp2); + move16(); + out_ptr[k] = add(out_ptr[k], tmp1); + move16(); + out_ptr[k+1] = add(out_ptr[k+1], tmp2); + move16(); + } + ji = add(ji, ii); + } + } + } +} + +/*--------------------------------------------------------------------------------* + * r_fft_fx: + * + * Perform FFT fixed-point for real-valued sequences of length 32, 64 or 128 + *--------------------------------------------------------------------------------*/ +void r_fft_fx_lc( + const Word16 *phs_tbl, /* i : Table of phase */ + const Word16 SIZE, /* i : Size of the FFT */ + const Word16 SIZE2, /* i : Size / 2 */ + const Word16 NUM_STAGE, /* i : Number of stage */ + const Word16 *in_ptr, /* i : coefficients in the order re[0], re[1], ... re[n/2], im[n/2-1], im[n/2-2], ..., im[1] */ + Word16 *out_ptr, /* o : coefficients in the order re[0], re[1], ... re[n/2], im[n/2-1], im[n/2-2], ..., im[1] */ + const Word16 isign /* i : 1=fft, otherwize it's ifft */ +) +{ + Word16 tmp2_real, tmp2_imag; + Word32 Ltmp1_real, Ltmp1_imag; + Word16 i; + Word32 Ltmp1; + const Word16 *phstbl_ptrDn; + Word16 *ptrDn; + Word16 temp[1024]; /* Accommodates real input FFT size up to 1024. */ + + /* Setup Pointers */ + phstbl_ptrDn = &phs_tbl[SIZE-1]; + + /* The FFT part */ + IF (isign != 0) + { + Word16 *ptRealUp, *ptRealDn, *ptImaUp, *ptImaDn; + + /* Perform the complex FFT */ + c_fft_fx(phs_tbl, SIZE, NUM_STAGE, in_ptr, temp, isign); + + /* First, handle the DC and foldover frequencies */ + out_ptr[SIZE2] = sub(temp[0], temp[1]); + move16(); + out_ptr[0] = sub(add(temp[0], temp[1]), shr(NUM_STAGE, 1)); + move16();/* DC have a small offset */ + + ptrDn = &temp[SIZE-1]; + + ptImaDn = &out_ptr[SIZE-1]; + ptRealUp = &out_ptr[1]; + ptImaUp = &out_ptr[SIZE2+1]; + ptRealDn = &out_ptr[SIZE2-1]; + + /* Now, handle the remaining positive frequencies */ + FOR (i = 2; i <= SIZE2; i += 2) + { + Ltmp1_imag = L_mult(temp[i+1], 16384); + Ltmp1_imag = L_msu(Ltmp1_imag, *ptrDn, 16384); + tmp2_real = add(temp[i+1], *ptrDn--); + + Ltmp1_real = L_mult(temp[i], 16384); + Ltmp1_real = L_mac(Ltmp1_real, *ptrDn, 16384); + tmp2_imag = sub(*ptrDn--, temp[i]); + + + *ptRealUp++ = msu_r(L_mac(Ltmp1_real, tmp2_real, phs_tbl[i]), tmp2_imag, phs_tbl[i+1]); + move16(); + *ptImaDn-- = mac_r(L_mac(Ltmp1_imag, tmp2_imag, phs_tbl[i]), tmp2_real, phs_tbl[i+1]); + move16(); + Ltmp1 = L_mac(L_negate(Ltmp1_imag), tmp2_real, *phstbl_ptrDn); + Ltmp1_real = L_mac(Ltmp1_real, tmp2_imag, *phstbl_ptrDn--); + *ptImaUp++ = msu_r(Ltmp1, tmp2_imag, *phstbl_ptrDn); + move16(); + *ptRealDn-- = mac_r(Ltmp1_real, tmp2_real, *phstbl_ptrDn--); + move16(); + } + } + ELSE /* The ifFT part */ + { + const Word16 *ptRealUp, *ptRealDn, *ptImaUp, *ptImaDn; + + /* First, handle the DC and foldover frequencies */ + Ltmp1 = L_mult(in_ptr[0], 16384); + temp[0] = mac_r(Ltmp1, in_ptr[SIZE2], 16384); + move16(); + temp[1] = msu_r(Ltmp1, in_ptr[SIZE2], 16384); + move16(); + + ptrDn = &temp[SIZE-1]; + + /* Here we cast to Word16 * from a const Word16 *. */ + /* This is ok because we use these pointers for */ + /* reading only. This is just to avoid declaring a */ + /* bunch of 4 other pointer with const Word16 *. */ + ptImaDn = &in_ptr[SIZE-1]; + ptRealUp = &in_ptr[1]; + ptImaUp = &in_ptr[SIZE2+1]; + ptRealDn = &in_ptr[SIZE2-1]; + + /* Now, handle the remaining positive frequencies */ + FOR (i = 2; i <= SIZE2; i += 2) + { + Ltmp1_imag = L_mult(*ptImaDn, 16384); + Ltmp1_imag = L_msu(Ltmp1_imag, *ptImaUp, 16384); + tmp2_real = add(*ptImaDn--, *ptImaUp++); + Ltmp1_real = L_mult(*ptRealUp, 16384); + Ltmp1_real = L_mac(Ltmp1_real, *ptRealDn, 16384); + tmp2_imag = sub(*ptRealUp++, *ptRealDn--); + + + temp[i] = mac_r(L_msu(Ltmp1_real, tmp2_real, phs_tbl[i]), tmp2_imag, phs_tbl[i+1]); + move16(); + temp[i+1] = mac_r(L_mac(Ltmp1_imag, tmp2_imag, phs_tbl[i]), tmp2_real, phs_tbl[i+1]); + move16(); + Ltmp1 = L_mac(L_negate(Ltmp1_imag), tmp2_real, *phstbl_ptrDn); + Ltmp1_real = L_msu(Ltmp1_real, tmp2_imag, *phstbl_ptrDn--); + *ptrDn-- = msu_r(Ltmp1, tmp2_imag, *phstbl_ptrDn); + move16(); + *ptrDn-- = msu_r(Ltmp1_real, tmp2_real, *phstbl_ptrDn--); + move16(); + } + + /* Perform the complex ifFT */ + c_fft_fx(phs_tbl, SIZE, NUM_STAGE, temp, out_ptr, isign); + } +} diff --git a/lib_com/fft_rel_sas_fx.c b/lib_com/fft_rel_sas_fx.c new file mode 100644 index 0000000..06a7c0f --- /dev/null +++ b/lib_com/fft_rel_sas_fx.c @@ -0,0 +1,456 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define INV_SQR2_FX 23170 +#define N_MAX_SAS 256 + +/*---------------------------------------------------------------------* + * fft_rel_fx() + * + * Computes the split-radix FFT in place for the real-valued + * signal x of length n. The algorithm has been ported from + * the fortran code of [1]. + * + * The function needs sine and cosine tables t_sin and t_cos, + * and the constant N_MAX_SAS. The table entries are defined as + * sin(2*pi*i) and cos(2*pi*i) for i = 0, 1, ..., N_MAX_SAS-1. The + * implementation assumes that any entry will not be needed + * outside the tables. Therefore, N_MAX_SAS and n must be properly + * set. The function has been tested with the values n = 16, + * 32, 64, 128, 256, and N_MAX_SAS = 1280. + * + * References + * [1] H.V. Sorensen, D.L. Jones, M.T. Heideman, C.S. Burrus, + * "Real-valued fast Fourier transform algorithm," IEEE + * Trans. on Signal Processing, Vol.35, No.6, pp 849-863, + * 1987. + * + * OUTPUT + * x[0:n-1] Transform coeffients in the order re[0], re[1], + * ..., re[n/2], im[n/2-1], ..., im[1]. + *---------------------------------------------------------------------*/ +/*MERGE fft_rel_fx and fft_rel_fx_lc */ +void fft_rel_fx( + Word16 x[], /* i/o: input/output vector */ + const Word16 n, /* i : vector length */ + const Word16 m /* i : log2 of vector length */ +) +{ + Word16 i, j, k, n1, n2, n4; + Word16 step; + Word16 xt, t1, t2; + Word16 *x0, *x1, *x2; + const Word16 *s, *c; + Word16 *xi2, *xi3, *xi4, *xi1; + + + /*-----------------------------------------------------------------* + * Digit reverse counter + *-----------------------------------------------------------------*/ + + j = 0; + move16(); + x0 = &x[0]; + move16(); + FOR (i = 0; i < n-1; i++) + { + IF (LT_16(i,j)) + { + xt = x[j]; + move16(); + x[j] = *x0; + move16(); + *x0 = xt; + move16(); + } + x0++; + k = shr(n,1); + WHILE (LE_16(k,j)) + { + j = sub(j,k); + k = shr(k,1); + } + j = add(j,k); + } + + /*-----------------------------------------------------------------* + * Length two butterflies + *-----------------------------------------------------------------*/ + + x0 = &x[0]; + move16(); + x1 = &x[1]; + move16(); + FOR (i = 0; i < n/2; i++) + { + xt = *x0; + move16(); + *x0 = add(xt,*x1); + move16(); + *x1 = sub(xt,*x1); + move16(); + x0++; + x0++; + x1++; + x1++; + } + + /*-----------------------------------------------------------------* + * Other butterflies + * + * The implementation described in [1] has been changed by using + * table lookup for evaluating sine and cosine functions. The + * variable ind and its increment step are needed to access table + * entries. Note that this implementation assumes n4 to be so + * small that ind will never exceed the table. Thus the input + * argument n and the constant N_MAX_SAS must be set properly. + *-----------------------------------------------------------------*/ + + n2 = 1; + move16(); + /* step = N_MAX_SAS/4; */ + FOR (k = 2; k <= m; k++) + { + n4 = n2; + move16(); + n2 = shl(n4,1); + n1 = shl(n2,1); + + step = N_MAX_SAS/n1; + + x0 = x; + x1 = x + n2; + x2 = x + add(n2, n4); + FOR (i = 0; i < n; i += n1) + { + xt = *x0; + move16(); /* xt = x[i]; */ + *x0 = add(xt,*x1); + move16(); /* x[i] = xt + x[i+n2]; */ + *x1 = sub(xt,*x1); + move16(); /* x[i+n2] = xt - x[i+n2]; */ + *x2 = negate(*x2); + move16(); /* x[i+n2+n4] = -x[i+n2+n4]; */ + + + s = sincos_t_fx + step; + c = s + 64; + xi1 = x + add(i, 1); + xi3 = xi1 + n2; + xi2 = xi3 - 2; + xi4 = xi1 + sub(n1, 2); + + FOR (j = 1; j < n4; j++) + { + t1 = add(mult_r(*xi3,*c),mult_r(*xi4,*s)); /* t1 = *xi3**(pt_c+ind) + *xi4**(pt_s+ind); */ + t2 = sub(mult_r(*xi3,*s),mult_r(*xi4,*c)); /* t2 = *xi3**(pt_s+ind) - *xi4**(pt_c+ind); */ + *xi4 = sub(*xi2,t2); + move16(); + *xi3 = negate(add(*xi2,t2)); + move16(); + *xi2 = sub(*xi1,t1); + move16(); + *xi1 = add(*xi1,t1); + move16(); + + xi4--; + xi2--; + xi3++; + xi1++; + c += step; + s += step; /* autoincrement by ar0 */ + } + + x0 += n1; + x1 += n1; + x2 += n1; + } + /* step = shr(step, 1); */ + } + + return; +} + +void ifft_rel_fx( + Word16 io[], /* i/o: input/output vector */ + const Word16 n, /* i : vector length */ + const Word16 m /* i : log2 of vector length */ +) +{ + Word16 i, j, k; + Word16 step; + Word16 n2, n4, n8, i0; + Word16 is, id; + Word16 *x,*xi0, *xi1, *xi2, *xi3, *xi4, *xup1, *xdn6, *xup3, *xdn8; + Word16 xt; + Word16 r1; + Word16 t1, t2, t3, t4, t5; + const Word16 *s, *c, *s3, *c3; + + Word16 cc1, cc3, ss1, ss3; + Word16 tmp; + + + /*-----------------------------------------------------------------* + * ifft + *-----------------------------------------------------------------*/ + + x = &io[-1]; + move16(); + n2 = shl(n,1); + FOR (k=1; k +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required for wmc_tool */ + +/*--------------------------------------------------------------------------* + * fill_spectrum() + * + * Apply spectral filling by + * - filling zero-bit bands below BWE region + * - applying BWE above transition frequency + *--------------------------------------------------------------------------*/ + +void fill_spectrum_fx( + Word16 *coeff, /* i/o: normalized MLT spectrum / nf spectrum Q12 */ + Word32 *L_coeff_out, /* i/o: Noisefilled MLT spectrum Q12 */ + const Word16 *R, /* i : number of pulses per band Q0 */ + const Word16 is_transient, /* i : transient flag Q0 */ + Word16 norm[], /* i : quantization indices for norms Q0 */ + const Word16 *hq_generic_fenv, /* i : HQ GENERIC envelope Q1 */ + const Word16 hq_generic_offset, /* i : HQ GENERIC offset Q0 */ + const Word16 nf_idx, /* i : noise fill index Q0 */ + const Word16 length, /* i : Length of spectrum (32 or 48 kHz) Q0 */ + const Word16 env_stab, /* i : Envelope stability measure [0..1] Q15 */ + Word16 *no_att_hangover, /* i/o: Frame counter for attenuation hangover Q0 */ + Word32 *L_energy_lt, /* i/o: Long-term energy measure for transient detection Q13 */ + Word16 *bwe_seed, /* i/o: random seed for generating BWE input Q0 */ + const Word16 hq_generic_exc_clas, /* i : BWE excitation class Q0 */ + const Word16 core_sfm, /* i : index of the end band for core Q0 */ + const Word16 HQ_mode, /* i : HQ mode Q0 */ + Word16 noise_level[], /* i : noise levels for harmonic modes Q15 */ + const Word32 L_core_brate, /* i : target bit-rate Q0 */ + Word16 prev_noise_level[], /* i/o: noise factor in previous frame Q15 */ + Word16 *prev_R, /* i/o: bit allocation info. in previous frame Q0 */ + Word32 *prev_coeff_out, /* i/o: decoded spectrum in previous frame Q12 */ + const Word16 *peak_idx, /* i : peak indices for hvq Q0 */ + const Word16 Npeaks, /* i : number of peaks in hvq Q0 */ + const Word16 *npulses, /* i : number of pulses per band Q0 */ + const Word16 prev_is_transient, /* i : previous transient flag Q0 */ + Word32 *prev_normq, /* i/o: previous norms Q14 */ + Word32 *prev_env, /* i/o: previous noise envelopes Q(prev_env_Q) */ + const Word16 prev_bfi, /* i : previous bad frame indicator Q0 */ + const Word16 *sfmsize, /* i : Length of bands Q0 */ + const Word16 *sfm_start, /* i : Start of bands Q0 */ + const Word16 *sfm_end, /* i : End of bands Q0 */ + Word16 *prev_L_swb_norm, /* i/o: HVQ/Harmonic mode normalization length Q0 */ + const Word16 prev_hq_mode, /* i : Previous HQ mode Q0 */ + const Word16 num_sfm /* i : Total number of bands Q0 */ + ,Word16 *prev_env_Q + ,const Word16 num_env_bands /* i : Number sub bands to be encoded for HQ_GEN Q0 */ +) +{ + Word16 CodeBook[FREQ_LENGTH]; /* Q12 */ + Word16 cb_size; + Word16 last_sfm; + Word16 CodeBook_mod[FREQ_LENGTH]; /*Q12 */ + Word16 norm_adj[NB_SFM]; /*Q15 */ + Word16 high_sfm; + Word16 flag_32K_env_hangover; + Word16 bin_th; + Word16 peak_pos[L_HARMONIC_EXC]; + Word16 bwe_peaks[L_FRAME48k]; + Word32 L_normq_v[NB_SFM]; /*Q14 */ + Word16 coeff_fine[L_FRAME48k]; /*Q15 */ + Word32 L_coeff_out1[L_FRAME48k]; /*Q12 */ + + set16_fx( peak_pos, 0, L_HARMONIC_EXC ); + set16_fx( bwe_peaks, 0, L_FRAME48k ); + set16_fx(norm_adj, 32767, num_sfm); /* 1.0, Q15 */ + cb_size = 0; + move16(); + bin_th = 0; + move16(); + high_sfm = 23; + move16(); + + test(); + IF ( EQ_16(HQ_mode, HQ_TRANSIENT)) + { + last_sfm = sub(num_sfm, 1); + } + ELSE IF ( EQ_16(HQ_mode,HQ_GEN_SWB)||EQ_16(HQ_mode,HQ_GEN_FB)) + { + last_sfm = s_max(core_sfm,sub(num_env_bands,1)); + } + ELSE + { + last_sfm = core_sfm; + move16(); + } + + IF ( EQ_16(HQ_mode, HQ_HARMONIC)) + { + /*high_sfm = (core_brate == HQ_24k40) ? HVQ_THRES_SFM_24k-1 : HVQ_THRES_SFM_32k-3; */ + high_sfm = sub(HVQ_THRES_SFM_32k, 1); + if (EQ_32(L_core_brate, HQ_24k40)) + { + high_sfm = sub(HVQ_THRES_SFM_24k, 1); + } + + if( LT_16(last_sfm, high_sfm)) + { + last_sfm = high_sfm; + move16(); + } + } + ELSE if ( EQ_16(HQ_mode, HQ_HVQ)) + { + bin_th = sfm_end[last_sfm]; + move16(); + } + + /* Transient analysis for envelope stability measure */ + IF ( EQ_16(length, L_FRAME32k)) + { + env_stab_transient_detect_fx( is_transient, length, norm, no_att_hangover, L_energy_lt, HQ_mode, bin_th, L_coeff_out, 12 ); + } + + test(); + test(); + test(); + test(); + IF ( EQ_16(length, L_FRAME16k)|| + ((EQ_16(length, L_FRAME32k) && NE_16(HQ_mode, HQ_HARMONIC) && NE_16(HQ_mode, HQ_HVQ) ) && *no_att_hangover == 0) ) + { + /* Norm adjustment function */ + env_adj_fx( npulses, length, last_sfm, norm_adj, env_stab, sfmsize ); + } + + /*flag_32K_env_hangover = ( length == L_FRAME32k && ( (env_stab < 0.5f && *no_att_hangover == 0) || HQ_mode == HQ_HVQ ) ); */ + flag_32K_env_hangover = 0; + move16(); + test(); + test(); + test(); + if ( EQ_16(length, L_FRAME32k)&&((LT_16(env_stab,16384)&&*no_att_hangover==0)||EQ_16(HQ_mode,HQ_HVQ))) + { + flag_32K_env_hangover = 1; + move16(); + } + + + /*----------------------------------------------------------------* + * Build noise-fill codebook + *----------------------------------------------------------------*/ + + IF ( NE_16(HQ_mode, HQ_HVQ)) + { + cb_size = build_nf_codebook_fx(flag_32K_env_hangover, coeff, sfm_start, sfmsize, sfm_end, last_sfm, R, CodeBook, CodeBook_mod); + } + /*----------------------------------------------------------------* + * Prepare fine structure for Harmonic and HVQ + *----------------------------------------------------------------*/ + + IF ( EQ_16(HQ_mode, HQ_HARMONIC)) + { + harm_bwe_fine_fx( R, last_sfm, high_sfm, num_sfm, norm, sfm_start, sfm_end, prev_L_swb_norm, coeff, L_coeff_out, coeff_fine ); + } + ELSE IF ( EQ_16(HQ_mode, HQ_HVQ)) + { + hvq_bwe_fine_fx( last_sfm, num_sfm, sfm_end, peak_idx, Npeaks, peak_pos, prev_L_swb_norm, L_coeff_out, bwe_peaks, coeff_fine ); + } + + /*----------------------------------------------------------------* + * Apply noise-fill + *----------------------------------------------------------------*/ + + test(); + IF ( NE_16(HQ_mode, HQ_HVQ)&&cb_size>0) + { + apply_noisefill_HQ_fx( R, length, flag_32K_env_hangover, L_core_brate, last_sfm, CodeBook, + CodeBook_mod, cb_size, sfm_start, sfm_end, sfmsize, coeff ); + } + + /*----------------------------------------------------------------* + * Normal mode BWE + *----------------------------------------------------------------*/ + + IF ( HQ_mode == HQ_NORMAL ) + { + hq_fold_bwe_fx(last_sfm, sfm_end, num_sfm, coeff); + } + + /*----------------------------------------------------------------* + * Apply noise-fill adjustment + *----------------------------------------------------------------*/ + + test(); + test(); + test(); + IF( (GE_16(length, L_FRAME32k)||GT_32(L_core_brate,HQ_32k)||LT_32(L_core_brate,HQ_24k40)) + && NE_16(HQ_mode, HQ_HVQ) ) + { + apply_nf_gain_fx(nf_idx, last_sfm, R, sfm_start, sfm_end, coeff); + } + + /*----------------------------------------------------------------* + * Prepare fine strucutre for HQ GENERIC + *----------------------------------------------------------------*/ + test(); + IF ( EQ_16(HQ_mode, HQ_GEN_SWB)||EQ_16(HQ_mode,HQ_GEN_FB)) + { + hq_generic_fine_fx( coeff, last_sfm, sfm_start, sfm_end, bwe_seed, coeff_fine ); + } + + /*----------------------------------------------------------------* + * Apply envelope + *----------------------------------------------------------------*/ + + test(); + IF ( NE_16(HQ_mode, HQ_HARMONIC)&&NE_16(HQ_mode,HQ_HVQ)) + { + apply_envelope_fx( coeff, norm, norm_adj, num_sfm, last_sfm, HQ_mode, length, sfm_start, sfm_end, + L_normq_v, L_coeff_out, coeff_fine, L_coeff_out1 ); + } + + /*----------------------------------------------------------------* + * Harmonic BWE, HVQ BWE and HQ SWB BWE + *----------------------------------------------------------------*/ + test(); + IF ( EQ_16(HQ_mode, HQ_HARMONIC)) + { + harm_bwe_fx( coeff_fine, coeff, num_sfm, sfm_start, sfm_end, last_sfm, R, prev_hq_mode, norm, noise_level, prev_noise_level, bwe_seed, L_coeff_out ); + } + ELSE IF ( EQ_16(HQ_mode, HQ_HVQ)) + { + hvq_bwe_fx( L_coeff_out, coeff_fine, sfm_start, sfm_end, sfmsize, last_sfm, + prev_hq_mode, bwe_peaks, bin_th, num_sfm, L_core_brate, R, norm, + noise_level, prev_noise_level, bwe_seed, L_coeff_out, 15, 12 ); + } + ELSE IF ( EQ_16(HQ_mode, HQ_GEN_SWB)||EQ_16(HQ_mode,HQ_GEN_FB)) + { + hq_bwe_fx( HQ_mode, L_coeff_out1, hq_generic_fenv, L_coeff_out, hq_generic_offset, prev_L_swb_norm, hq_generic_exc_clas, sfm_end, num_sfm, num_env_bands, R ); + } + + /*----------------------------------------------------------------* + * HQ WB BWE refinements + *----------------------------------------------------------------*/ + test(); + IF ( EQ_16(length, L_FRAME16k)&&EQ_32(L_core_brate,HQ_32k)) + { + hq_wb_nf_bwe_fx( coeff, is_transient, prev_bfi, L_normq_v, num_sfm, sfm_start, sfm_end, sfmsize, last_sfm, R, + prev_is_transient, prev_normq, prev_env, bwe_seed, prev_coeff_out, prev_R, L_coeff_out, prev_env_Q ); + } + + /*----------------------------------------------------------------* + * Update memories + *----------------------------------------------------------------*/ + + test(); + IF ( NE_16(HQ_mode, HQ_HARMONIC)&&NE_16(HQ_mode,HQ_HVQ)) + { + prev_noise_level[0] = 3277; + move16();/* 0.1 in Q15 */ + prev_noise_level[1] = 3277; + move16();/* 0.1 in Q15 */ + } + test(); + IF ( !(EQ_16(length, L_FRAME16k)&&EQ_32(L_core_brate,HQ_32k))) + { + set32_fx( prev_env, 0, SFM_N_WB ); + set32_fx( prev_normq, 0, SFM_N_WB ); + } + + test(); + IF ( EQ_16(length, L_FRAME32k)&&LE_32(L_core_brate,HQ_32k)) + { + *prev_R = R[SFM_N_WB-1]; + Copy32( L_coeff_out + L_FRAME16k - L_HQ_WB_BWE, prev_coeff_out, L_HQ_WB_BWE ); + } + + return; +} diff --git a/lib_com/findpulse_fx.c b/lib_com/findpulse_fx.c new file mode 100644 index 0000000..f292b65 --- /dev/null +++ b/lib_com/findpulse_fx.c @@ -0,0 +1,117 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*----------------------------------------------------------------------------------* + * findpulse() + * + * Find first pitch pulse in a frame + *----------------------------------------------------------------------------------*/ +Word16 findpulse_fx( /* o : pulse position */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 res[], /* i : Residual signal <12 bits */ + const Word16 T0, /* i : Pitch estimation Q0 */ + const Word16 enc, /* i : enc = 1 -> encoder side; enc = 0 -> decoder side */ + Word16 *sign /* i/o: sign of the maximum */ +) +{ + const Word16 *ptr; + Word16 maxval; + Word16 i, maxi; + Word32 Ltmp; + Word16 resf[L_FRAME16k]; /* Low pass filtered residual */ + + IF (enc != DEC) + { + /*------------------------------------------------------------------------* + * 1. Very simple LP filter + *------------------------------------------------------------------------*/ + + /* resf[0] = 0.50f * res[0] + 0.25f * res[1] */ + Ltmp = L_mult(res[0], 16384); + resf[0] = mac_r(Ltmp, res[1], 8192); + move16(); + FOR (i=1; i= 0) + { + *sign = 0; move16(); + }*/ + *sign = negate(shr(ptr[-maxi], 15)); + move16(); + } + ELSE + { + /*-----------------------------------------------------------------* + * 2. Find "biggest" pulse in the last pitch section according to the sign + *-----------------------------------------------------------------*/ + + maxval = 0; + move16(); + maxi = 0; + move16(); + + IF (*sign == 0) + { + FOR (i = 0; i < T0; i++) + { + if (GE_16(res[i], maxval)) + { + maxi = add(i, 1); + } + maxval = s_max(res[i], maxval); + } + } + ELSE + { + FOR (i = 0; i < T0; i++) + { + if (LE_16(res[i], maxval)) + { + maxi = add(i, 1); + } + maxval = s_min(res[i], maxval); + } + } + } + + return maxi; +} diff --git a/lib_com/fine_gain_bits_fx.c b/lib_com/fine_gain_bits_fx.c new file mode 100644 index 0000000..d6db726 --- /dev/null +++ b/lib_com/fine_gain_bits_fx.c @@ -0,0 +1,107 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required for wmc_tool */ + + +/*-------------------------------------------------------------------------- + * subband_gain_bits() + * + * HQ core encoder + *--------------------------------------------------------------------------*/ + +void subband_gain_bits_fx( + const Word16 *Rk, /* i : bit allocation per band Q3 */ + const Word16 N, /* i : number of bands */ + Word16 *bits, /* o : gain bits per band */ + const Word16 *sfmsize /* i : Size of bands */ +) +{ + Word16 i,b,tot; + Word16 bps; + + tot = 0; + move16(); + + FOR ( i = 0; i < N; i++ ) + { + /*bps = (short)(Rk[i]*((word16)min(32767, ceil(32767.0f/sfmsize[i]); inexact C-integer division approx. */ + bps = extract_l(L_shr(L_mult0(Rk[i], inv_tbl_fx[sfmsize[i]]), 18)); /* 3+15 */ + if (EQ_32(L_shl(L_mult0(sfmsize[i], add(bps, 1)), 3), Rk[i])) + { + bps = add(bps, 1); + } + + bps = s_min(7, bps); + b = fine_gain_bits[bps]; + move16(); + bits[i] = b; + move16(); + tot = add(tot, b); + } + + if ( tot == 0) + { + /* If no gain bits were assigned, use one bit anyway for potential PVQ overage */ + bits[0] = 1; + move16(); + } + + return; +} + +/*--------------------------------------------------------------------------* + * assign_gain_bits() + * + * Assign gain adjustment bits and update bit budget + *--------------------------------------------------------------------------*/ + +Word16 assign_gain_bits_fx( /* o : Number of assigned gain bits */ + const Word16 core, /* i : HQ core */ + const Word16 BANDS, /* i : Number of bands */ + const Word16 *band_width, /* i : Sub band bandwidth */ + Word16 *Rk, /* i/o: Bit allocation/Adjusted bit alloc. Q3 */ + Word16 *gain_bits_array, /* o : Assigned gain bits */ + Word16 *Rcalc /* o : Bit budget for shape quantizer Q3 */ +) +{ + Word16 subband_cnt; + Word16 gain_bits_tot; + Word16 i; + + /* Allocate gain bits for every subband used, based on bit rate and bandwidth */ + IF( EQ_16(core, HQ_CORE)) + { + subband_gain_bits_fx(Rk, BANDS, gain_bits_array, band_width); + } + ELSE + { + set16_fx( gain_bits_array, 0, BANDS ); + } + + /* Re-adjust bit budget for gain quantization */ + subband_cnt = 0; + move16(); + gain_bits_tot = 0; + move16(); + *Rcalc = 0; + move16(); + FOR (i = 0; i < BANDS; i++) + { + IF (Rk[i] > 0) + { + subband_cnt = add(subband_cnt, 1); + Rk[i] = sub(Rk[i], shl(gain_bits_array[i], 3)); + move16(); + gain_bits_tot = add(gain_bits_tot, gain_bits_array[i]); + *Rcalc = add(*Rcalc, Rk[i]); + move16(); + } + } + + return gain_bits_tot; +} diff --git a/lib_com/frame_ener_fx.c b/lib_com/frame_ener_fx.c new file mode 100644 index 0000000..a70235e --- /dev/null +++ b/lib_com/frame_ener_fx.c @@ -0,0 +1,196 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*----------------------------------------------------------------------------------* + * frame_ener() + * + * Estimation of pitch-synchronous (voiced) or mean half-frame (unvoiced) energy + *----------------------------------------------------------------------------------*/ +Word16 frame_ener_fx( + const Word16 L_frame, /* i : length of the frame */ + const Word16 clas, /* i : frame classification */ + const Word16 *synth, /* i : synthesized speech at Fs = 12k8 Hz Q_new */ + const Word16 pitch, /* i : pitch period Q0 */ + Word32 *enr_q, /* o : pitch-synchronous or half_frame energy Q0 */ + const Word16 offset, /* i : speech pointer offset (0 or L_FRAME) */ + const Word16 Q_new, /* i : Scaling factor */ + Word16 shift, /* i : Shift need to obtain 12 bits vectors */ + const Word16 enc /* i : Encoder/decoder */ +) +{ + Word16 len, exp_enrq, exp_tmp, pos; + Word16 i; + const Word16 *pt_synth; + Word32 Ltmp; + + exp_enrq = 0; + move16(); + test(); + test(); + IF( (EQ_16(clas, VOICED_CLAS))||(EQ_16(clas,ONSET))||(EQ_16(clas,SIN_ONSET))) /* current frame is voiced */ + { + /* current frame is voiced */ + len = pitch; + move16(); /* pitch value at the end of frame */ + pt_synth = synth; + move16(); + if (offset != 0) + { + pt_synth = synth + sub(L_frame, len); + } + emaximum_fx(Q_new, pt_synth, len, enr_q); + move16();/* pitch synchronous E */ + IF (enc != 0) + { + exp_enrq = norm_l(*enr_q); + *enr_q = L_shl(*enr_q, exp_enrq); + move32(); + exp_enrq = sub(exp_enrq, 2); + } + } + ELSE + { + /* current frame is unvoiced */ + Word16 L_frame2, exp2, enr_q_tmp; + + L_frame2 = shr(L_frame,1); + pos = 0; + move16(); + + if (offset != 0) + { + pos = sub(L_frame, L_frame2); + } + Ltmp = L_mult(synth[pos], synth[pos]); + FOR (i = 1; i < L_frame2; i++) + { + Ltmp = L_mac(Ltmp, synth[pos+i], synth[pos+i]); + } + test(); + IF (EQ_32(Ltmp, MAX_32)||enc!=0) + { + /* scale down when overflow occurs */ + *enr_q = Energy_scale(synth+pos, L_frame2, shift, &exp_enrq); + move32(); + } + ELSE + { + shift = 0; + move16(); + /* Normalize acc in Q31 (energy already calculated) */ + pos = norm_l(Ltmp); + Ltmp = L_shl(Ltmp, pos); + exp_enrq = sub(30, pos); /* exponent = 0..30 */ + *enr_q = Ltmp; + move32(); + } + + /* enr2 = 1.0f/L_FRAME2 * dot_product(synth, synth, L_FRAME2) */ + exp_enrq = sub(exp_enrq, shl(shift, 1)); + + IF (enc != 0) + { + assert(L_frame == 256 || L_frame == 320); + + exp_tmp = add(shl(Q_new, 1), -2+7); /* L_subfr == L_SUBFR */ + exp_enrq = sub(exp_enrq, exp_tmp); + exp_enrq = sub(31, exp_enrq); + + IF(EQ_16(L_frame, 320)) + { + *enr_q = Mult_32_16(*enr_q, 26214); /*x 0.8 to get /160*/ + i = norm_l(*enr_q); + *enr_q = L_shl(*enr_q, i); + exp_enrq = add(i, exp_enrq); + } + } + ELSE + { + exp_enrq = sub(exp_enrq, add(Q_new, Q_new)); + enr_q_tmp /*Q30 exp2+exp_enrq*/ = BASOP_Util_Divide3216_Scale(*enr_q /*Q31*/, L_frame2 /*Q0*/, &exp2); + *enr_q = L_shr(L_deposit_l(enr_q_tmp),sub(30,add(exp2,exp_enrq))); /*Q0*/ + *enr_q = L_add(*enr_q, 1); + move32(); + exp_enrq = 0; + move16(); + } + + + + + + + } + + return exp_enrq; +} + +/*------------------------------------------------------------------------* + * frame_energy() + * + * Compute pitch-synchronous energy at the frame end + *------------------------------------------------------------------------*/ +Word16 frame_energy_fx( /* o : Frame energy in Q8 */ + Word16 L_frame, + const Word16 *pitch, /* i : pitch values for each subframe Q6 */ + const Word16 *speech, /* i : pointer to speech signal for E computation Q_syn*/ + const Word16 lp_speech, /* i : long term active speech energy average Q8 */ + Word16 *frame_ener, /* o : pitch-synchronous energy at frame end Q8 */ + const Word16 Q_syn /* i : Synthesis scaling */ +) +{ + Word32 Ltmp; + const Word16 *pt1; + Word16 tmp16, exp1, exp2, tmp1, tmp2; + Word16 len, enern; + + /* len = (0.5f * (pitch[2]/64.0 + pitch[3]/64.0) + 0.5f) */ + len = mult_r(add(pitch[2], pitch[3]), 256); + + if(LT_16(len,L_SUBFR)) + { + len = shl(len, 1); + } + pt1 = speech + sub(L_frame,len); + + /* *frame_ener = 10.0f * log10(dot_product(pt1, pt1, len) / (float)len) */ + + tmp1 = norm_s(len); + tmp2 = shl(len, tmp1); + tmp1 = sub(15, tmp1); + + Ltmp = Dot_productSq16HQ( 0, pt1, len, &exp1); + exp1 = sub(exp1, shl(Q_syn, 1)); + exp1 = sub(exp1, 1); /* compensation of leftshift caused by mac operation in dot_productSq16HQ */ + tmp16 = BASOP_Util_Divide3216_Scale( Ltmp, len, &exp2); + + exp1 = add(exp1, exp2); + exp1 = add(exp1, 1); /* compensate result of division Q-1 */ + + + tmp2 = norm_s(tmp16); + Ltmp = L_shl(L_deposit_h(tmp16),tmp2); /*Q16, (exp1-tmp2) = Q31, exp1-tmp2+15*/ + + Ltmp = BASOP_Util_Log2(Ltmp);/*Q(31-6) = Q25*/ + exp1 = sub(15+exp1,tmp2); + + /*add ld(2^exp1)=exp1 but check format, first*/ + tmp16=sub(sub(15,norm_s(exp1)),5); /*factor to shift Ltmp and exp1 with (shr) to avoid overflows when adding*/ + Ltmp= L_shr(Ltmp,tmp16); /*Q25, tmp16*/ + exp2 = shr(exp1,tmp16); /*Q0 , tmp16*/ + Ltmp = L_add(Ltmp,L_shl(L_deposit_l(exp2),25)); /*Q25, tmp16, normalized*/ + + /*make 10*log10 out of log2*/ + Ltmp = Mpy_32_16_1(Ltmp,LG10); /*Q25,tmp16 * Q13 = Q23, tmp16*/ + *frame_ener = extract_h(L_shl(Ltmp,add(tmp16,1)));/*Q8*/ move16(); + enern = sub( *frame_ener ,lp_speech); /*Q8*/ + + return enern; +} diff --git a/lib_com/g192.c b/lib_com/g192.c new file mode 100644 index 0000000..05ad613 --- /dev/null +++ b/lib_com/g192.c @@ -0,0 +1,254 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.442 May 28, 2020. Version 12.13.0 / 13.8.0 / 14.4.0 / 15.2.0 / 16.0.0 + ====================================================================================*/ + +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#include +#else +#include +typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned int uint32_t; +typedef signed int int32_t; +typedef unsigned __int64 uint64_t; +typedef signed __int64 int64_t; +#endif +#include "options.h" +#include "stl.h" +#include "g192.h" + + +#ifdef _MSC_VER +#pragma warning( disable : 4996 ) +#endif + +#define G192_SYNC_GOOD_FRAME (Word16)0x6B21 +#define G192_SYNC_BAD_FRAME (Word16)0x6B20 +#define G192_BIT0 (Word16)0x007F +#define G192_BIT1 (Word16)0x0081 +#define MAX_BITS_PER_FRAME 2560 +#define RTP_HEADER_PART1 (Word16)22 /* magic number by network simulator */ + +/* + * Structures + */ + +/* main handle */ +struct __G192 +{ + FILE * file; +}; + +/* + * Functions + */ + +G192_ERROR +G192_Reader_Open(G192_HANDLE* phG192, FILE * filename) +{ + /* create handle */ + *phG192 = (G192_HANDLE) calloc(1, sizeof(struct __G192) ); + if ( *phG192 == NULL ) + { + return G192_MEMORY_ERROR; + } + + memset(*phG192, 0, sizeof(struct __G192)); + + /* associate file stream */ + (*phG192)->file = filename; + if( (*phG192)->file == NULL ) + { + G192_Reader_Close(phG192); + return G192_FILE_NOT_FOUND; + } + + return G192_NO_ERROR; +} + +G192_ERROR +G192_ReadVoipFrame_compact(G192_HANDLE const hG192, + unsigned char * const serial, + Word16 * const num_bits, + Word16 *rtpSequenceNumber, + Word32 *rtpTimeStamp, + Word32 *rcvTime_ms) +{ + Word16 short_serial [MAX_BITS_PER_FRAME]; + G192_ERROR err; + Word16 i; + + err = G192_ReadVoipFrame_short(hG192, short_serial, num_bits, rtpSequenceNumber, rtpTimeStamp, rcvTime_ms); + if(err != G192_NO_ERROR) + { + return err; + } + + for(i=0; i<*num_bits; i++) + { + unsigned char bit = (short_serial[i] == G192_BIT1) ? 1 : 0; + unsigned char bitinbyte = bit << (7- (i&0x7)); + if(!(i&0x7)) + serial[i>>3] = 0; + serial[i>>3] |= bitinbyte; + } + + return G192_NO_ERROR; +} + +G192_ERROR +G192_ReadVoipFrame_short(G192_HANDLE const hG192, + Word16 * const serial, + Word16 *num_bits, + Word16 *rtpSequenceNumber, + Word32 *rtpTimeStamp, + Word32 *rcvTime_ms) +{ + Word32 rtpPacketSize; + Word16 rtpPacketHeaderPart1; + Word32 ssrc; + Word16 rtpPayloadG192[2]; + Word16 rtpPayloadSize; + + /* RTP packet size */ + if(fread(&rtpPacketSize, sizeof(rtpPacketSize), 1, hG192->file) != 1) + { + if(feof( hG192->file) != 0) + { + return G192_EOF; + } + fprintf(stderr, "RTP Packet Size could't be read\n"); + return G192_READ_ERROR; + } + + if(rtpPacketSize <= 12) + { + fprintf(stderr, "RTP Packet size too small: %d\n", rtpPacketSize); + return G192_INVALID_DATA; + } + + /* RTP packet arrival time */ + if(fread(rcvTime_ms, sizeof(*rcvTime_ms), 1, hG192->file) != 1) + { + if(feof( hG192->file) != 0) + { + return G192_EOF; + } + fprintf(stderr, "Reception Time in ms could't be read\n"); + return G192_READ_ERROR; + } + + /* RTP packet header (part without sequence number) */ + if(fread(&rtpPacketHeaderPart1, sizeof(rtpPacketHeaderPart1), 1, hG192->file) != 1) + { + if(feof( hG192->file) != 0) + { + return G192_EOF; + } + fprintf(stderr, "RTP Header couldn't be read\n"); + return G192_READ_ERROR; + } + + if(rtpPacketHeaderPart1 != RTP_HEADER_PART1) + { + fprintf(stderr, "Unexpected RTP Packet header\n"); + return G192_INVALID_DATA; + } + + /* RTP sequence number */ + if(fread(rtpSequenceNumber, sizeof(*rtpSequenceNumber), 1, hG192->file) != 1) + { + if(feof( hG192->file) != 0) + { + return G192_EOF; + } + fprintf(stderr, "RTP Sequence Number be read\n"); + return G192_READ_ERROR; + } + + *rtpSequenceNumber = ntohs(*rtpSequenceNumber); + /* RTP timestamp */ + if(fread(rtpTimeStamp, sizeof(*rtpTimeStamp), 1, hG192->file) != 1) + { + if(feof( hG192->file) != 0) + { + return G192_EOF; + } + fprintf(stderr, "RTP Timestamp could't be read\n"); + return G192_READ_ERROR; + } + + *rtpTimeStamp = ntohl(*rtpTimeStamp); + /* RTP ssrc */ + if(fread(&ssrc, sizeof(ssrc), 1, hG192->file) != 1) + { + if(feof( hG192->file) != 0) + { + return G192_EOF; + } + fprintf(stderr, "RTP SSRC could't be read\n"); + return G192_READ_ERROR; + } + + /* RTP payload size */ + rtpPayloadSize = (Word16)(rtpPacketSize - 12); + if(rtpPayloadSize <= 2) + { + fprintf(stderr, "RTP payload size too small: %d\n", rtpPayloadSize); + return G192_INVALID_DATA; + } + /* RTP payload */ + if(fread(rtpPayloadG192, sizeof(Word16), 2, hG192->file) != 2) + { + if(feof( hG192->file) != 0) + { + return G192_EOF; + } + fprintf(stderr, "Premature end of file, cannot read G.192 header\n"); + return G192_READ_ERROR; + } + if(rtpPayloadG192[0] != G192_SYNC_GOOD_FRAME) + { + fprintf(stderr, "G192_SYNC_WORD missing from RTP payload!"); + return G192_INVALID_DATA; + } + *num_bits = rtpPayloadG192[1]; + if(*num_bits == 0 || *num_bits + 2 != rtpPayloadSize || *num_bits > MAX_BITS_PER_FRAME) + { + fprintf(stderr, "error in parsing RTP payload: rtpPayloadSize=%u nBits=%d", + rtpPayloadSize, *num_bits); + return G192_INVALID_DATA; + } + if( (Word16)fread(serial, sizeof(Word16), *num_bits, hG192->file) != *num_bits) + { + if(feof( hG192->file) != 0) + { + return G192_EOF; + } + fprintf(stderr, "Premature end of file, cannot read G.192 payload\n"); + return G192_READ_ERROR; + } + + return G192_NO_ERROR; +} + +G192_ERROR +G192_Reader_Close(G192_HANDLE* phG192) +{ + if(phG192 == NULL || *phG192 == NULL) + { + return G192_NO_ERROR; + } + + free( *phG192 ); + *phG192 = NULL; + phG192 = NULL; + + return G192_NO_ERROR; +} diff --git a/lib_com/g192.h b/lib_com/g192.h new file mode 100644 index 0000000..12981f6 --- /dev/null +++ b/lib_com/g192.h @@ -0,0 +1,64 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.442 May 28, 2020. Version 12.13.0 / 13.8.0 / 14.4.0 / 15.2.0 / 16.0.0 + ====================================================================================*/ + +#ifndef G192_H +#define G192_H G192_H + +/* + * ENUMS + */ + +/* error enums */ + +typedef enum _G192_ERROR +{ + G192_NO_ERROR = 0x0000, + G192_MEMORY_ERROR = 0x0001, + G192_WRONG_PARAMS = 0x0002, + G192_INIT_ERROR = 0x0003, + G192_WRITE_ERROR = 0x0004, + G192_READ_ERROR = 0x0005, + G192_FILE_NOT_FOUND = 0x0006, + G192_INVALID_DATA = 0x0007, /* error returned when read data is invalid */ + G192_NOT_IMPLEMENTED = 0x0010, + G192_NOT_INITIALIZED = 0x0100, + G192_UNKNOWN_ERROR = 0x1000, + G192_EOF = 0xffff /* EOF during reading */ +} G192_ERROR; + +/* + * Structures + */ + +/* main handle */ +struct __G192; +typedef struct __G192 * G192_HANDLE; + +/* + * Functions + */ + +G192_ERROR +G192_Reader_Open(G192_HANDLE* phG192, FILE * filename); + +G192_ERROR +G192_ReadVoipFrame_compact(G192_HANDLE const hG192, + unsigned char * const serial, + Word16 * const num_bits, + Word16 *rtpSequenceNumber, + Word32 *rtpTimeStamp, + Word32 *rcvTime_ms); + +G192_ERROR +G192_ReadVoipFrame_short(G192_HANDLE const hG192, + Word16 * const serial, + Word16 *num_bits, + Word16 *rtpSequenceNumber, + Word32 *rtpTimeStamp, + Word32 *rcvTime_ms); + +G192_ERROR +G192_Reader_Close(G192_HANDLE* phG192); + +#endif /* G192_H */ diff --git a/lib_com/gain_inov.c b/lib_com/gain_inov.c new file mode 100644 index 0000000..703054c --- /dev/null +++ b/lib_com/gain_inov.c @@ -0,0 +1,54 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "prot_fx.h" +#include "stl.h" +#include "basop_util.h" +#include "rom_com_fx.h" + + +Word32 calc_gain_inov( /* returns innovation gain Q16 */ + const Word16 *code, /* i : algebraic excitation Q9 */ + Word16 lcode, /* i : Subframe size Q0 */ + Word32 *dotp, /* o : intermediate result Q31-e */ + Word16 *dotp_e /* o : intermediate result exponent Q0 */ +) +{ + Word32 L_tmp; + Word16 exp_L_tmp, i; + + /* L_tmp = dot_product(code, code, lcode) + 0.01 */ + L_tmp = Dot_product12_offs(code, code, lcode, &exp_L_tmp, 2621l/*0.01f/2.0f Q19*/); + exp_L_tmp = sub(exp_L_tmp, 18); + + /* gain_inov = 1.0f / sqrt((dot_product(code, code, lcode) + 0.01) / lcode) */ + /* Note: lcode is in range: 32,40,64,80 */ + assert((lcode == 32) || (lcode == 40) || (lcode == 64) || (lcode == 80)); + if (s_and(lcode, sub(lcode, 1)) != 0) + { + L_tmp = Mpy_32_32(L_tmp, 1717986918l/*64.0/80.0 Q31*/); + } + exp_L_tmp = sub(exp_L_tmp, sub(14, norm_s(lcode))); + + i = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, i); + exp_L_tmp = sub(exp_L_tmp, i); + + if (dotp != NULL) + { + *dotp = L_tmp; + move32(); + } + if (dotp_e != NULL) + { + *dotp_e = exp_L_tmp; + move16(); + } + + L_tmp = ISqrt32norm(L_tmp, &exp_L_tmp); + + return L_shl(L_tmp, sub(exp_L_tmp, 15)); /* 15Q16 */ +} + diff --git a/lib_com/get_gain.c b/lib_com/get_gain.c new file mode 100644 index 0000000..9db8199 --- /dev/null +++ b/lib_com/get_gain.c @@ -0,0 +1,97 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "prot_fx.h" +#include "stl.h" +#include "basop_util.h" + +Word32 get_gain( /* output: codebook gain (adaptive or fixed) Q16 */ + Word16 x[], /* input : target signal */ + Word16 y[], /* input : filtered codebook excitation */ + Word16 n /* input : segment length */ +) +{ + Word32 tcorr, tener, Lgain; + Word16 exp_c, exp_e, exp, tmp; + + + tcorr = L_deposit_l(0); + tener = L_deposit_l(0); + + + + /*----------------------------------------------------------------* + * Find gain based on inter-correlation product + *----------------------------------------------------------------*/ + + tcorr = Dot_product16HQ( 0, x, y, n, &exp_c ); + tener = Dot_productSq16HQ( 0, y, n, &exp_e ); + + BASOP_Util_Divide_MantExp(round_fx(tcorr), exp_c, s_max(round_fx(tener),1), exp_e, &tmp,&exp); + Lgain = L_shl(L_deposit_l(tmp)/*Q15*/,add(1,exp))/*Q16*/; + + return Lgain; +} + +Word32 get_gain2( /* output: codebook gain (adaptive or fixed) Q16 */ + Word16 x[], /* input : target signal */ + Word16 y[], /* input : filtered codebook excitation */ + Word16 n /* input : segment length */ +) +{ + Word32 tcorr, tener, Lgain; + Word16 m_corr, m_ener, negative, Q_corr, Q_ener; + + negative = 0; + move16(); + + /*----------------------------------------------------------------* + * Find gain based on inter-correlation product + *----------------------------------------------------------------*/ + tcorr = Dot_product16HQ(0, x, y, n, &Q_corr); + tener = Dot_productSq16HQ(0, y, n, &Q_ener); + + tener = L_max(tener, 1); + + if (tcorr <= 0) + { + negative = 1; + move16(); + } + BASOP_SATURATE_WARNING_OFF /*tcorr max be negative maxvall - not critical*/ + tcorr = L_abs(tcorr); + BASOP_SATURATE_WARNING_ON + + m_corr = extract_h(tcorr); + + m_ener = extract_h(tener); + + IF (GT_16(m_corr, m_ener)) + { + m_corr = shr(m_corr, 1); + Q_corr = add(Q_corr,1); + } + if (m_ener==0) + { + move16(); + m_corr = 0x7FFF; + } + if (m_ener != 0) + { + m_corr = div_s(m_corr, m_ener); + } + + Q_corr = sub(Q_corr,Q_ener); + + Lgain = L_shl(L_deposit_l(m_corr), add(Q_corr, 1)); /* Lgain in Q16 */ + + if (negative != 0) + { + Lgain = L_negate(Lgain); /* Lgain in Q16 */ + } + + + return Lgain; +} diff --git a/lib_com/gs_bitallocation_fx.c b/lib_com/gs_bitallocation_fx.c new file mode 100644 index 0000000..f82fb3f --- /dev/null +++ b/lib_com/gs_bitallocation_fx.c @@ -0,0 +1,481 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "assert.h" /* Debug prototypes */ +#include "stl.h" + +/*==================================================================================*/ +/* FUNCTION : void bands_and_bit_alloc_fx(); */ +/*----------------------------------------------------------------------------------*/ +/* PURPOSE : AC mode (GSC) bands and bits allocation */ +/*----------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) cor_strong_limit : HF correlation */ +/* _ (Word16) noise_lev : dwn scaling factor Q0 */ +/* _ (Word32) core_brate : core codec used Q0 */ +/* _ (Word16) Diff_len : Lenght of the difference signal Q0 */ +/* _ (Word16) bits_used : Number of bit used before frequency Q0 */ +/* _ (Word16) idx : Energy band 14 Q0 */ +/* _ (Word16*) exc_diff : Difference signal to quantize (Encoder only) */ +/* _ (Word16) coder_type : coding type Q0 */ +/* _ (Word16) bwidth : input signal bandwidth Q0 */ +/*----------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) max_ener_band : Sorted order */ +/* _ (Word16*) nb_subbands : Number of subband allowed Q0 */ +/* _ (Word16*) concat_in : Concatened PVQ's input vector (Encoder Only) */ +/* _ (Word16*) pvq_len : Number of bin covered with the PVQ Q0 */ +/*----------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16*) bit :Number of bit allowed for frequency quantization */ +/* _ (Word16*) Ener_per_bd_iQ : Quantized energy vector Q13 */ +/* _ (Word32*) bits_per_bands : Number of bit allowed per allowed subband Q18 */ +/*----------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*==================================================================================*/ +void bands_and_bit_alloc_fx( + const Word16 cor_strong_limit, /* i : HF correlation */ + const Word16 noise_lev, /* i : dwn scaling factor */ + const Word32 core_brate, /* i : core bit rate */ + const Word16 Diff_len, /* i : Lenght of the difference signal (before pure spectral)*/ + const Word16 bits_used, /* i : Number of bit used before frequency Q */ + Word16 *bit, /* i/o: Number of bit allowed for frequency quantization */ + const Word16 *Ener_per_bd_iQ, /* i/o: Quantized energy vector */ + Word16 *max_ener_band, /* o : Sorted order */ + Word16 *out_bits_per_bands, /* i/o: Number of bit allowed per allowed subband Q3 */ + Word16 *nb_subbands, /* o : Number of subband allowed */ + const Word16 *exc_diff, /* i : Difference signal to quantize (encoder side only) */ + Word16 *concat_in, /* o : Concatened PVQ's input vector (encoder side only) */ + Word16 *pvq_len, /* o : Number of bin covered with the PVQ */ + const Word16 coder_type, /* i : coding type */ + const Word16 bwidth, /* i : input signal bandwidth */ + const Word16 GSC_noisy_speech +) +{ + + Word16 bandoffset, i, j, nb_bands_max, bit_new_bands, bit_tmp, st_band, nb_bands; + Word16 ener_vec[MBANDS_GN]; /*Q12 */ + Word16 nb_tot_bands = 16; + Word16 bit_index, bit_index_mem, imax; + Word32 L_tmp; + Word32 sum_bit, bit_fracf; + Word16 etmp; + Word16 tmp; + Word16 Ener_per_bd_iQ_tmp[MBANDS_GN]; + Word16 pos, band; + Word16 SWB_bit_budget; + Word32 bits_per_bands[MBANDS_GN]; + Word16 w_sum_bit; + + Copy( Ener_per_bd_iQ, Ener_per_bd_iQ_tmp, MBANDS_GN ); + + set32_fx( bits_per_bands, 0, MBANDS_GN ); + set16_fx( out_bits_per_bands, 0, MBANDS_GN ); + + /* To adapt current energy band to PVQ freq band for sorting*/ + ener_vec[0] = add(Ener_per_bd_iQ[0],Ener_per_bd_iQ[1]); /*Q12 */ + Copy( Ener_per_bd_iQ_tmp+1, ener_vec, 15 ); /*Q12 */ + ener_vec[15] = ener_vec[14]; + move16(); + + /*------------------------------------------------------------------------ + * Determination of the number of bits available to the frequency domain + * Allocation of a maximum number of band to be encoded + *-----------------------------------------------------------------------*/ + + nb_bands_max = nb_tot_bands; + move16(); + bit_new_bands = 5; + move16(); + + bit_index = i_mult2(BRATE2IDX_fx(core_brate),17); + bit_index_mem = bit_index; + move16(); + + test(); + test(); + IF( (EQ_16(coder_type,AUDIO)||EQ_16(coder_type,INACTIVE))&&EQ_16(bwidth,NB)) + { + IF(GE_32(core_brate,ACELP_9k60)) + { + /* *bit = (short)(core_brate*(1.0f/50) + 0.5f) - bits_used - 25; */ + L_tmp = Mult_32_16(core_brate,20971); + tmp = extract_l(L_shr_r(L_tmp,5)); + *bit = sub(sub(tmp,bits_used), 25); + move16(); + } + ELSE + { + L_tmp = Mult_32_16(core_brate,20971); + tmp = extract_l(L_shr_r(L_tmp,5)); + *bit = sub(sub(tmp,bits_used), 21); + move16(); + } + nb_tot_bands = 10; + move16(); + } + ELSE + { + /* *bit = (short)(core_brate*(1.0f/50) + 0.5f) - bits_used - GSC_freq_bits[bit_index]; */ + + L_tmp = Mult_32_16(core_brate,20971); + tmp = extract_l(L_shr_r(L_tmp,5)); + *bit = sub(sub(tmp,bits_used),GSC_freq_bits[bit_index]); + move16(); + } + + IF( EQ_16(GSC_noisy_speech,1)) + { + SWB_bit_budget = *bit; + move16(); + nb_bands = 5; + move16(); + st_band = nb_bands; + move16(); + + set32_fx( bits_per_bands, 0, MBANDS_GN ); + /*bit_fracf = (1.0f/nb_bands)*(SWB_bit_budget); */ + bit_fracf = L_mult(div_s(1,nb_bands),shl(SWB_bit_budget,2)); /* Q18 */ + + nb_tot_bands = sub(nb_bands_max,6); + nb_tot_bands = s_min(nb_tot_bands, 16); + + FOR(j = 0; j < 2; j++) + { + i = j; + move16(); + max_ener_band[j] = i; + move16(); + ener_vec[i] = 0; + move16(); + } + + FOR(; j < nb_bands; j++) + { + i = maximum_fx(ener_vec, nb_tot_bands, &etmp); + max_ener_band[j] = i; + move16(); + ener_vec[i] = 0; + move16(); + } + + set32_fx(bits_per_bands, bit_fracf, nb_bands); + } + ELSE + { + bit_index++; + bit_tmp = sub(*bit,GSC_freq_bits[bit_index]); + bit_index++; + nb_bands_max = add(nb_bands_max,GSC_freq_bits[bit_index]); + bit_index++; + + *pvq_len = 112; + move16(); + st_band = 7; + move16(); + + IF( LE_32(core_brate,ACELP_9k60)) + { + *pvq_len = 80; + move16(); + st_band = 5; + move16(); + + IF( Diff_len == 0 ) + { + nb_bands_max = add(nb_bands_max,2); + bit_tmp = sub(bit_tmp,13); + } + } + + ELSE IF( Diff_len == 0 ) + { + nb_bands_max = add(nb_bands_max,2); + bit_tmp = sub(bit_tmp,17); + } + + nb_bands = shr(*pvq_len,4); + + /*------------------------------------------------------------------------ + * Ajustement of the maximum number of bands in function of the + * dynamics of the spectrum (more or less speech like) + *-----------------------------------------------------------------------*/ + test(); + test(); + test(); + test(); + IF( EQ_16(coder_type,INACTIVE)||GE_16(noise_lev,NOISE_LEVEL_SP3)) + { + /* Probably classification error -> concentrate bits on LF */ + nb_bands_max = nb_bands; + move16(); + if( GE_32(core_brate,ACELP_8k00)) + { + nb_bands_max = add(nb_bands,1); + } + } + ELSE IF( GE_16(noise_lev,NOISE_LEVEL_SP2)|| + (LE_32(core_brate,ACELP_13k20) && GE_32(core_brate,ACELP_9k60) && cor_strong_limit == 0) ) /* Very low dynamic, tend to speech, do not try to code HF at all */ + { + nb_bands_max = sub(nb_bands_max,2); + } + ELSE if( GE_16(noise_lev,NOISE_LEVEL_SP1)) /* Very low dynamic, tend to speech, code less HF */ + { + nb_bands_max = sub(nb_bands_max,1); + } + + test(); + if( EQ_16(bwidth,NB)&>_16(nb_bands_max,10)) + { + nb_bands_max = 10; + move16(); + } + + /*------------------------------------------------------------------------ + * Find extra number of band to code according to bit rate availables + *-----------------------------------------------------------------------*/ + WHILE ( GE_16(bit_tmp,bit_new_bands)&&LE_16(nb_bands,sub(nb_bands_max,1))) + { + bit_tmp = sub(bit_tmp,bit_new_bands); + nb_bands = add(nb_bands,1); + } + + /*------------------------------------------------------------------------ + * Fractional bits to distribute on the first x bands + *-----------------------------------------------------------------------*/ + + bit_fracf = L_mult(div_s(1,st_band),shl(bit_tmp,2)); /* Q18 */ + + /*------------------------------------------------------------------------ + * Complete the bit allocation per frequency band + *-----------------------------------------------------------------------*/ + imax = 5; + move16(); + + if( GT_32(core_brate,ACELP_9k60)) + { + imax = 7; + move16(); + } + FOR(i = 0; i < imax; i++) + { + bits_per_bands[i] = L_add(GSC_freq_bits_fx[bit_index],bit_fracf); + move32();/* Q18 */ + bit_index = add(bit_index,1); + } + + IF( Diff_len == 0 ) + { + bit_index = add(bit_index_mem,10); + FOR( i = 0; i < 7; i++ ) + { + bits_per_bands[i] = L_add(bits_per_bands[i],GSC_freq_bits_fx[bit_index]); + move32();/*chk Q18 */ + bit_index = add(bit_index,1); + } + } + + /*-------------------------------------------------------------------------- + * Complete the bit allocation per frequency band for 16kHz high brate mode + *--------------------------------------------------------------------------*/ + + FOR( j = st_band; j < nb_bands; j++ ) + { + bits_per_bands[j] = L_shl(bit_new_bands,18); + move32(); /*chk Q18 */ + } + + /*-------------------------------------------------------------------------- + * Compute a maximum band (band offset) for the search on maximal energy + * This is function of the spectral dynamic and the bitrate + *--------------------------------------------------------------------------*/ + + bandoffset = sub(nb_tot_bands,add(nb_bands,2)); + + test(); + test(); + test(); + test(); + test(); + IF( LE_16(noise_lev,NOISE_LEVEL_SP1a)) + { + bandoffset = sub(bandoffset,1); + } + ELSE if ( (LE_32(core_brate,ACELP_13k20)&&(EQ_16(coder_type,INACTIVE)||GE_16(noise_lev,NOISE_LEVEL_SP3)))|| + (LE_32(core_brate,ACELP_13k20) && GE_32(core_brate,ACELP_9k60) && cor_strong_limit == 0) ) + { + bandoffset = add(bandoffset,1); + } + + bandoffset = s_max(bandoffset ,0); + + /*-------------------------------------------------------------------------- + * Initiazed sorted vector + * For the first x bands to be included in th final sorted vector + * Sort the remaining bands in decrease energy order + *--------------------------------------------------------------------------*/ + FOR(j = 0; j < nb_tot_bands; j++) + { + max_ener_band[j] = -10; + move16(); + } + FOR(j = 0; j < st_band; j++) + { + max_ener_band[j] = j; + move16(); + ener_vec[j] = -10; + move16(); + } + pos = st_band; + move16(); + FOR(; j < nb_bands; j++) + { + i = maximum_fx(ener_vec, sub(nb_tot_bands,bandoffset), &etmp); + pos = s_max(pos,i); + max_ener_band[j] = i; + move16(); + ener_vec[i] = -10; + move16(); + } + + /* re-allocate bits to the frames such that the highest band with allocated bits is higher than the threshold */ + test(); + test(); + test(); + IF( GT_16(sub(nb_tot_bands, bandoffset),nb_bands)&&(GT_16(pos,7)&&EQ_32(core_brate,ACELP_8k00))&&EQ_16(bwidth,WB)) + { + band = sub(nb_tot_bands, add(bandoffset,nb_bands)); + FOR(j=0; j 0; bit_tmp--) + { + bits_per_bands[j] = L_sub(bits_per_bands[j],262144); /*Q18 */ + j = add(j,1); + if ( EQ_16(j,sub(st_band, i))) + { + j = 0; + move16(); + } + test(); + if( j == 0 && LT_16(i,sub(st_band, 1))) + { + i = add(i,1); + } + } + } + } + /*-------------------------------------------------------------------------- + * Bit sum verification for GSC inactive at very high rate + * The maximum number of bits per band of length 16 is 112 + * Redistribute the overage bits if needed + *--------------------------------------------------------------------------*/ + sum_bit = 0; + move16(); + j = 0; + move16(); + FOR( i = 0; i < nb_bands; i++ ) + { + L_tmp = Mult_32_16(sum_bit,10923); + + IF( GT_32(bits_per_bands[i],29360128)) /* 112 in Q18 */ + { + sum_bit = L_add(sum_bit,L_sub(bits_per_bands[i],29360128)); /* Q18 */ + bits_per_bands[i] = 29360128; + move32(); + j = add(i,1); + } + ELSE if( GT_32(L_add(bits_per_bands[i],L_tmp),29360128 )) /* Q18 */ + { + j = add(i,1); + } + } + + IF( sum_bit != 0 ) + { + tmp = sub(nb_bands,j); + sum_bit = Mult_32_16(sum_bit,div_s(1,tmp)); /* Q18 */ + FOR( i = j; i < nb_bands; i++ ) + { + bits_per_bands[i] = L_add(bits_per_bands[i],sum_bit); + move32();/* Q18 */ + } + } + /*-------------------------------------------------------------------------- + * second step of bit sum verification, normally sum_bit == *bit + *--------------------------------------------------------------------------*/ + w_sum_bit = 0; + move16(); + FOR( i = 0; i < nb_bands; i++ ) + { + out_bits_per_bands[i] = shl(extract_l(L_shr(bits_per_bands[i],18)),3); + move16(); + w_sum_bit = add(w_sum_bit,out_bits_per_bands[i]); /* Q3 */ + } + tmp = shl(*bit,3); + + IF( GT_16(tmp,w_sum_bit)) + { + i = sub(nb_bands,1); + move16(); + FOR( ; tmp > w_sum_bit; w_sum_bit += (1<<3) ) + { + out_bits_per_bands[i] = add(out_bits_per_bands[i],1<<3); + move16(); + i = sub(i, 1); + if(i==0) + { + i = sub(nb_bands,1); + } + } + } + /*-------------------------------------------------------------------------- + * Recompute the real number/length of frequency bands to encode + *--------------------------------------------------------------------------*/ + *nb_subbands = nb_bands; + move16(); + *pvq_len = shl(*nb_subbands,4); + + /*-------------------------------------------------------------------------- + * Concatenate bands (encoder only) + *--------------------------------------------------------------------------*/ + IF( exc_diff != NULL ) + { + FOR( j = 0; j < nb_bands; j++ ) + { + Copy( exc_diff + shl(max_ener_band[j],4), concat_in+shl(j,4), 16 ); + } + } + + return; +} diff --git a/lib_com/gs_gains_fx.c b/lib_com/gs_gains_fx.c new file mode 100644 index 0000000..438c750 --- /dev/null +++ b/lib_com/gs_gains_fx.c @@ -0,0 +1,673 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +static Word16 VDQ_vec_fx( Word16 *Qvec_out_fx, const Word16 *mean_dic_fx, const Word16 *dic_fx, + const Word16 index_fx, const Word16 vec_en_fx ); + +/*========================================================================*/ +/* FUNCTION : void Comp_and_apply_gain_enc_fx */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : Compute and apply the quantized per band gain */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16[]) Ener_per_bd_iQ : Target ener per band Q12 */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc_diffQ : Quantized excitation Qexc */ +/* _ (Word16[]) Ener_per_bd_yQ : Ener per band for norm vectori->Q12/o->Q2*/ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ +void Comp_and_apply_gain_fx( + Word16 exc_diffQ[], /* i/o: Quantized excitation */ + Word16 Ener_per_bd_iQ[], /* i : Target ener per band Q13 */ + Word16 Ener_per_bd_yQ[], /* i/o : Ener per band for norm vector i->Q13/o->Q13 */ + Word16 Mbands_gn, /* i : number of bands */ + const Word16 ReUseGain, /* i : Reuse the gain in Ener_per_bd_yQ */ + Word16 Qexc_diff, + Word16 Q_exc +) +{ + Word16 i, i_band; + Word16 StartBin, NB_Qbins; + Word16 y_gain; + Word16 L16, frac, exp1, tmp_exp; + Word32 L32; + + /* Recreate excitation for local synthesis and decoder */ + StartBin = 0; + move16(); + NB_Qbins = 0; + move16(); + + tmp_exp = add(14,sub(Q_exc,Qexc_diff)); /* In case of reuse, it can be computed outside the loop*/ + FOR( i_band = 0; i_band < Mbands_gn; i_band++ ) + { + StartBin = add(StartBin, NB_Qbins); + NB_Qbins = mfreq_bindiv_loc[i_band]; + move16(); + IF( EQ_16(ReUseGain,1)) + { + y_gain = Ener_per_bd_yQ[i_band]; + move16(); + + FOR(i = StartBin ; i < NB_Qbins + StartBin ; i++) + { + L32 = L_shl(L_mult(exc_diffQ[i], y_gain),tmp_exp); /*Q_exc+16 */ + exc_diffQ[i] = round_fx(L32);/*Q_exc */ + } + } + ELSE + { + /*-----------------------------------------------------------------* + * y_gain = pow(10.0, (Ener_per_bd_iQ[i_band]-Ener_per_bd_yQ[i_band])) + * = pow(2, 3.321928*(Ener_per_bd_iQ[i_band]-Ener_per_bd_yQ[i_band])) + *-----------------------------------------------------------------*/ + L16 = sub(Ener_per_bd_iQ[i_band], Ener_per_bd_yQ[i_band]);/*Q12 */ + L32 = L_mult(L16, 27213); /* 3.321928 in Q13 -> Q26 */ + L32 = L_shr(L32, 10); /* From Q26 to Q16 */ + frac = L_Extract_lc(L32, &exp1); /* Extract exponent of gcode0 */ + y_gain = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + Ener_per_bd_yQ[i_band] = shl(y_gain, sub(exp1, 13)); + move16();/*Q1 */ + tmp_exp = add(add(exp1,1),sub(Q_exc,Qexc_diff)); + + FOR(i = StartBin ; i < NB_Qbins + StartBin ; i++) + { + L32 = L_mult(exc_diffQ[i], y_gain); /*Qexc_diff+15 */ + exc_diffQ[i] = round_fx(L_shl(L32,tmp_exp)); /*Q_exc */ + } + } + } + + return; +} + + +/*========================================================================*/ +/* FUNCTION : Ener_per_band_comp_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : Compute the energy per band in log domain for quantization */ +/* purposes. */ +/* Loops are decomposed to accomodate the PVQ quantization */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16*) edct_table_128_fx : edct table Q15 */ +/* _ (Word16*) Q_exc_diff : input format of exc_diff */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) y_gain4 : Energy per band to quantize Q12 */ +/* _ (Word32*) etmp14 : Energy band 14 Q_exc_diff*2+1 */ +/* _ (Word32*) etmp15 : Energy band 15 Q_exc_diff*2+1 */ +/*------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ +static Word16 Comp_band_log_ener( /* o : Band gain Q12 */ + const Word16 *pt_fx, /* i : Dct input Q_sc */ + const Word16 Len, /* i : Lenght en energy accumulation */ + const Word16 Q_sc, /* i : scaling of input */ + const Word16 E_sc /* i : Additional scaling factor for energy */ +) +{ + Word32 L_tmp; + Word16 e_tmp, f_tmp, tmp16, ener_exp; + + /*for(i = 0; i < 8; i++){etmp += (*pt * *pt);pt++;}*/ + L_tmp = Calc_Energy_Autoscaled(pt_fx, Q_sc, Len, &ener_exp); + + /*y_gain4[j] = (float)log10(sqrt(etmp< Q12 */ + } + ELSE IF (LE_32(core_brate,ACELP_8k00)) + { + Gain_off = 27034; + move16(); /* 6.6f -> Q12 */ + } + ELSE IF (LE_32(core_brate,ACELP_9k60)) + { + Gain_off = 19661; + move16(); /*4.8f-> Q12 */ + } + ELSE IF (LE_32(core_brate,ACELP_11k60)) + { + Gain_off = 14336; + move16(); /* 3.5f -> Q12 */ + } + ELSE IF (LE_32(core_brate,ACELP_13k20)) + { + Gain_off = 12288; + move16(); /* 3.0f -> Q12 dB */ + } + + /*mimic ACELP decay of energy for low rates*/ + FOR( i = 0; i < MBANDS_GN; i++ ) + { + old_y_gain[i] = y_gain_tmp[i]; + move16(); + /*y_gainQ[i] = y_gain_tmp[i]+mean_4g[0]-(i*(Gain_off/20.f)/((float) Mbands_gn));*/ + y_gainQ[i] = add(y_gain_tmp[i], sub(mean_g, i_mult2(i, mult_r(Gain_off, 102)))); + move16(); + } + } + + return; +} +/*==========================================================================*/ +/* FUNCTION : Word16 gsc_gaindec_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Generic signal frequency band decoding and application */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) pvq_bits_fx : core used Q0 */ +/* _ (Word16) coder_type_fx : coding type Q0 */ +/* _ (Word16) core_fx : core used Q0 */ +/* _ (Word16) bwidth_fx : input signal bandwidth Q0 */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) y_gainQ_fx : quantized gain per band */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16[]) old_y_gain_fx : AR gain quantizer for low rate */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word16) : average frequency gain */ +/*==========================================================================*/ + +Word16 gsc_gaindec_fx( /* o : average frequency gain */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 y_gainQ_fx[], /* o : quantized gain per band */ + const Word32 core_brate_fx, /* i : core used */ + Word16 old_y_gain_fx[], /* i/o: AR gain quantizer for low rate */ + const Word16 coder_type_fx, /* i : coding type */ + const Word16 bwidth_fx /* i : input signal bandwidth */ +) +{ + Word16 idx_g_fx, i; + Word16 mean_4g_fx; + Word16 y_gain_tmp3_fx[MBANDS_GN]; + + test(); + test(); + IF( (EQ_16(coder_type_fx,AUDIO)||EQ_16(coder_type_fx,INACTIVE))&&EQ_16(bwidth_fx,NB)) + { + idx_g_fx = (Word16) get_next_indice_fx( st_fx, 6 ); + VDQ_vec_fx(&mean_4g_fx, Gain_meanNB_fx, Gain_mean_dicNB_fx, idx_g_fx, 1 ); + + idx_g_fx = (Word16) get_next_indice_fx( st_fx, 6 ); + move16(); + VDQ_vec_fx(y_gainQ_fx, Mean_dic_NB_fx, Gain_dic1_NB_fx, idx_g_fx, 3 ); + + IF(LT_32(core_brate_fx,ACELP_9k60)) + { + idx_g_fx = (Word16) get_next_indice_fx( st_fx, 5 ); + VDQ_vec_fx(y_gainQ_fx+3, Mean_dic_NB_fx+3, Gain_dic2_NB_fx, idx_g_fx, 3 ); + + idx_g_fx = (Word16) get_next_indice_fx( st_fx, 4 ); + VDQ_vec_fx(y_gainQ_fx+6, Mean_dic_NB_fx+6, Gain_dic3_NB_fx, idx_g_fx, 4 ); + } + ELSE + { + idx_g_fx = (Word16) get_next_indice_fx( st_fx, 6 ); + VDQ_vec_fx(y_gainQ_fx+3, Mean_dic_NB_fx+3, Gain_dic2_NBHR_fx, idx_g_fx, 3 ); + + idx_g_fx = (Word16) get_next_indice_fx( st_fx, 7 ); + VDQ_vec_fx(y_gainQ_fx+6, Mean_dic_NB_fx+6, Gain_dic3_NBHR_fx, idx_g_fx, 4 ); + } + test(); + IF( LE_32(core_brate_fx,ACELP_9k60)&&EQ_16(coder_type_fx,INACTIVE)) + { + /* Some energy is needed in high band for stat_noise_uv_enc + to be functional in inactive speech */ + y_gainQ_fx[10] = mean_fx(y_gainQ_fx+6, 3); + move16(); + y_gainQ_fx[11] = mean_fx(y_gainQ_fx+7, 3); + move16(); + y_gainQ_fx[12] = mean_fx(y_gainQ_fx+8, 3); + move16(); + y_gainQ_fx[13] = mean_fx(y_gainQ_fx+9, 3); + move16(); + y_gainQ_fx[14] = mean_fx(y_gainQ_fx+10, 3); + move16(); + y_gainQ_fx[15] = mean_fx(y_gainQ_fx+11, 3); + move16(); + } + ELSE + { + set16_fx( y_gainQ_fx + 10, 0, MBANDS_GN - 10 ); + } + } + ELSE + { + idx_g_fx = (Word16) get_next_indice_fx( st_fx, 6 ); + + VDQ_vec_fx(&mean_4g_fx, mean_m_fx, mean_gain_dic_fx, idx_g_fx, 1 ); + + IF(LE_32(core_brate_fx,ACELP_9k60)) + { + /*--------------------------------------------------------------------------------------* + * UQ of the first 8 bands and half of the last 8 bands + *--------------------------------------------------------------------------------------*/ + idx_g_fx = (Word16) get_next_indice_fx( st_fx, 5 ); + VDQ_vec_fx(y_gainQ_fx, YGain_mean_LR_fx, YGain_dic1_LR_fx, idx_g_fx, 3 ); + + idx_g_fx = (Word16) get_next_indice_fx( st_fx, 5 ); + VDQ_vec_fx(y_gainQ_fx+3, YGain_mean_LR_fx+3, YGain_dic2_LR_fx, idx_g_fx, 4 ); + + /*----------------------------------------------------------------------* + * Interpolation of the last 4 Q bands to create bands 8-16 + * And scaling + *----------------------------------------------------------------------*/ + + idx_g_fx = (Word16) get_next_indice_fx( st_fx, 5 ); + + VDQ_vec_fx(y_gainQ_fx+7, YGain_mean_LR_fx+7, YGain_dic3_LR_fx, idx_g_fx, 5 ); + + Copy(y_gainQ_fx+8, y_gain_tmp3_fx, 4); + set16_fx(y_gainQ_fx+12, 0, 4); + + fft_rel_fx(y_gainQ_fx+8, 4, 2); + + y_gainQ_fx[15] = y_gainQ_fx[11]; + move16(); + y_gainQ_fx[11] = 0; + move16(); + ifft_rel_fx(y_gainQ_fx+8, 8, 3); + FOR(i = 8; i < 16; i++) + { + /*y_gainQ_fx[i] *= 1.41f;*/ + y_gainQ_fx[i] = round_fx(L_shl(L_mult(y_gainQ_fx[i] , 23101),1));/*Q12 */ + } + /*----------------------------------------------------------------------* + * Copy the true Q values in the specific bands + *----------------------------------------------------------------------*/ + y_gainQ_fx[8] = y_gain_tmp3_fx[0]; + move16(); + y_gainQ_fx[10]= y_gain_tmp3_fx[1]; + move16(); + y_gainQ_fx[12]= y_gain_tmp3_fx[2]; + move16(); + y_gainQ_fx[14]= y_gain_tmp3_fx[3]; + move16(); + } + ELSE + { + idx_g_fx = (Word16) get_next_indice_fx( st_fx, 6 ); + VDQ_vec_fx(y_gainQ_fx, YG_mean16_fx, YG_dicMR_1_fx, idx_g_fx, 4 ); + + idx_g_fx = (Word16) get_next_indice_fx( st_fx, 5 ); + VDQ_vec_fx(y_gainQ_fx+4, YG_mean16_fx+4, YG_dicMR_2_fx, idx_g_fx, 4 ); + + idx_g_fx = (Word16) get_next_indice_fx( st_fx, 5 ); + VDQ_vec_fx(y_gainQ_fx+8, YG_mean16_fx+8, YG_dicMR_3_fx, idx_g_fx, 4 ); + + idx_g_fx = (Word16) get_next_indice_fx( st_fx, 4 ); + VDQ_vec_fx(y_gainQ_fx+12, YG_mean16_fx+12, YG_dicMR_4_fx, idx_g_fx, 4 ); + } + } + + /* Gain adjustment to fit ACELP generic inactive coding gain at low rate */ + GSC_gain_adj(coder_type_fx, core_brate_fx, mean_4g_fx, old_y_gain_fx, y_gainQ_fx, y_gainQ_fx); + + return mean_4g_fx; + +} + +/*-------------------------------------------------------------------* + * gsc_gainQ() + * + * Quantization of the energy per band + *-------------------------------------------------------------------*/ +Word16 gsc_gainQ_fx( /*Q12*/ + Encoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 y_gain4[], /* i : Energy per band Q12 */ + Word16 y_gainQ[], /* o : quantized energy per band Q12 */ + const Word32 core_brate, /* i : Core rate */ + const Word16 coder_type, /* i : coding type */ + const Word16 bwidth /* i : input signal bandwidth */ +) +{ + Word16 y_gain_tmp[MBANDS_GN], y_gain_tmp2[MBANDS_GN]; + Word16 i, idx_g = 0; + Word16 mean_4g[1] = {0}, tmp16,tmp1, tmp2; + Word16 Mbands_gn = MBANDS_GN; + Word16 y_gain_tmp3[MBANDS_GN]; + Word16 cnt; + Word32 L_tmp; + + mean_4g[0] = 0; + + test(); + test(); + IF( (EQ_16(coder_type,AUDIO)||EQ_16(coder_type,INACTIVE))&&EQ_16(bwidth,NB)) + { + + /*ftmp1 = mean(y_gain4, 10)-0.6f;*/ + L_tmp = L_deposit_l(0); + FOR(cnt = 0 ; cnt < 10 ; cnt++) + { + L_tmp = L_mac(L_tmp,y_gain4[cnt], 3277); + } + tmp16 = sub(round_fx(L_tmp), 4915); + + FOR(i = 0; i < Mbands_gn; i++) + { + y_gain_tmp2[i] = y_gain4[i]; + move16(); + /*if(y_gain4[i] < ftmp1-0.6f)*/ + y_gain_tmp2[i] = s_max(y_gain_tmp2[i], tmp16); + move16(); + } + + L_tmp = L_deposit_l(0); + FOR(i = 0; i < 10; i++) + { + L_tmp = L_mac(L_tmp,y_gain_tmp2[i], 3277); + } + + /* Quantized mean gain without clipping */ + mean_4g[0] = round_fx(L_tmp); + idx_g = vquant_fx(mean_4g, Gain_meanNB_fx, mean_4g, Gain_mean_dicNB_fx, 1, 64); + push_indice_fx( st_fx, IND_MEAN_GAIN2, idx_g, 6 ); + + FOR(i = 0; i < Mbands_gn; i++) + { + y_gain_tmp[i] = sub(y_gain_tmp2[i],mean_4g[0]); + move16(); + } + /*if(y_gain_tmp[9] < -0.3f){y_gain_tmp[9] = -0.3f;}*/ + y_gain_tmp[9] = s_max(y_gain_tmp[9], -1229); + move16(); + set16_fx(y_gain_tmp+10, 0, MBANDS_GN-10); + idx_g = vquant_fx(y_gain_tmp, Mean_dic_NB_fx, y_gain_tmp, Gain_dic1_NB_fx, 3, 64); + push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 6 ); + + IF(LT_32(core_brate,ACELP_9k60)) + { + idx_g = vquant_fx(y_gain_tmp+3, Mean_dic_NB_fx+3, y_gain_tmp+3, Gain_dic2_NB_fx, 3, 32); + push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 5 ); + idx_g = vquant_fx(y_gain_tmp+6, Mean_dic_NB_fx+6, y_gain_tmp+6, Gain_dic3_NB_fx, 4, 16); + push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 4 ); + } + ELSE + { + idx_g = vquant_fx(y_gain_tmp+3, Mean_dic_NB_fx+3, y_gain_tmp+3, Gain_dic2_NBHR_fx, 3, 64); + push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 6 ); + idx_g = vquant_fx(y_gain_tmp+6, Mean_dic_NB_fx+6, y_gain_tmp+6, Gain_dic3_NBHR_fx, 4, 128); + push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 7 ); + }/*add end */ + + test(); + IF( LE_32(core_brate,ACELP_9k60)&&EQ_16(coder_type,INACTIVE)) + { + /* Some energy is needed in high band for stat_noise_uv_enc + to be functional in inactive speech */ + y_gain_tmp[10] = round_fx(L_mac(L_mac(L_mult(y_gain_tmp[6],8192),y_gain_tmp[7],8192),y_gain_tmp[8],8192)); + y_gain_tmp[11] = round_fx(L_mac(L_mac(L_mult(y_gain_tmp[7],8192),y_gain_tmp[8],8192),y_gain_tmp[9],8192)); + + y_gain_tmp[12] = round_fx(L_mac(L_mac(L_mult(y_gain_tmp[8],8192),y_gain_tmp[9],8192),y_gain_tmp[10],8192)); + y_gain_tmp[13] = round_fx(L_mac(L_mac(L_mult(y_gain_tmp[9],8192),y_gain_tmp[10],8192),y_gain_tmp[11],8192)); + y_gain_tmp[14] = round_fx(L_mac(L_mac(L_mult(y_gain_tmp[10],8192),y_gain_tmp[11],8192),y_gain_tmp[12],8192)); + y_gain_tmp[15] = round_fx(L_mac(L_mac(L_mult(y_gain_tmp[11],8192),y_gain_tmp[12],8192),y_gain_tmp[13],8192)); + } + ELSE + { + set16_fx( y_gain_tmp + 10, 0, MBANDS_GN - 10 ); + } + } + ELSE + { + /*ftmp1 = mean(y_gain4, 16);*/ + + L_tmp =0; + FOR(cnt = 0 ; cnt < 16 ; cnt++) + { + L_tmp = L_mac(L_tmp,y_gain4[cnt], 2048); + } + tmp16 = round_fx(L_tmp); + + tmp1 = sub(tmp16,4915); + tmp2 = add(tmp16,4915); + L_tmp =0; + FOR(i = 0; i < 16; i++) + { + y_gain_tmp2[i] = y_gain4[i]; + move16(); + /*if(y_gain4[i] < ftmp1-0.6f)*/ + y_gain_tmp2[i] = s_max(y_gain_tmp2[i], tmp1); + move16(); + /*else if(y_gain4[i] > ftmp1+0.6f)*/ + y_gain_tmp2[i] = s_min(y_gain_tmp2[i], tmp2); + move16(); + L_tmp = L_mac(L_tmp,y_gain_tmp2[i], 2048); + } + FOR(; i < Mbands_gn; i++) + { + y_gain_tmp2[i] = y_gain4[i]; + /*if(y_gain4[i] < ftmp1-0.6f)*/ + y_gain_tmp2[i] = s_max(y_gain_tmp2[i], tmp1); /* Just the last move is needed, because s_max and s_min could be done in 1 line*/ + /*else if(y_gain4[i] > ftmp1+0.6f)*/ + y_gain_tmp2[i] = s_min(y_gain_tmp2[i], tmp2); + move16(); + } + + /* Quantized mean gain without clipping */ + mean_4g[0] = round_fx(L_tmp); + + + /*idx_g = (short)vquant(mean_4g, mean_m, mean_4g, mean_gain_dic, 1, 64);*/ + idx_g = vquant_fx(mean_4g, mean_m_fx, mean_4g, mean_gain_dic_fx, 1, 64); + push_indice_fx( st_fx, IND_MEAN_GAIN2, idx_g, 6 ); + + FOR(i = 0; i < Mbands_gn; i++) + { + y_gain_tmp[i] = sub(y_gain_tmp2[i],mean_4g[0]); + move16(); + } + + IF( LT_32(core_brate,ACELP_9k60)) + { + /*mvr2r(y_gain_tmp, y_gain_tmp2, 8); */ + Copy(y_gain_tmp, y_gain_tmp2, 8); + + y_gain_tmp2[8] = y_gain_tmp[8]; + move16(); + y_gain_tmp2[9] = y_gain_tmp[10]; + move16(); + y_gain_tmp2[10] =y_gain_tmp[12]; + move16(); + y_gain_tmp2[11] =y_gain_tmp[14]; + move16(); + + idx_g = 0; + + /*idx_g = (short)vquant(y_gain_tmp2, YGain_mean_LR, y_gain_tmp2, YGain_dic1_LR, 3, 32);*/ + idx_g = vquant_fx(y_gain_tmp2, YGain_mean_LR_fx, y_gain_tmp2, YGain_dic1_LR_fx, 3, 32 ); + push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 5 ); + /*idx_g = (short)vquant(y_gain_tmp2+3, YGain_mean_LR+3, y_gain_tmp2+3, YGain_dic2_LR, 4, 32);*/ + idx_g = vquant_fx(y_gain_tmp2+3, YGain_mean_LR_fx+3, y_gain_tmp2+3, YGain_dic2_LR_fx, 4, 32 ); + push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 5 ); + /*idx_g = (short)vquant(y_gain_tmp2+7, YGain_mean_LR+7, y_gain_tmp2+7, YGain_dic3_LR, 5, 32);*/ + idx_g = vquant_fx(y_gain_tmp2+7, YGain_mean_LR_fx+7, y_gain_tmp2+7, YGain_dic3_LR_fx, 5, 32); + push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 5 ); + /*set_f(y_gain_tmp2+12, 0, MBANDS_GN-12);*/ + set16_fx(y_gain_tmp2+12, 0, MBANDS_GN-12); + + /* Update to quantized vector */ + Copy(y_gain_tmp2, y_gain_tmp, 8); + + Copy(y_gain_tmp2+8, y_gain_tmp3, 4); + set16_fx(y_gain_tmp+8, 0,8); + fft_rel_fx(y_gain_tmp2+8, 4, 2); + + Copy(y_gain_tmp2+8, y_gain_tmp+8, 3); + y_gain_tmp[15] = y_gain_tmp2[11]; + ifft_rel_fx(y_gain_tmp+8, 8, 3); + + FOR(i = 8; i < 16; i++) + { + /*y_gain_tmp[i] *= 1.41f;*/ + y_gain_tmp[i] = shl( mult_r(y_gain_tmp[i] , 23101),1) ; + move16(); + } + + y_gain_tmp[8] = y_gain_tmp3[0]; + move16(); + y_gain_tmp[10]= y_gain_tmp3[1]; + move16(); + y_gain_tmp[12]= y_gain_tmp3[2]; + move16(); + y_gain_tmp[14]= y_gain_tmp3[3]; + move16(); + } + ELSE + { + idx_g = vquant_fx(y_gain_tmp, YG_mean16_fx, y_gain_tmp, YG_dicMR_1_fx, 4, 64); + push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 6 ); + idx_g = vquant_fx(y_gain_tmp+4, YG_mean16_fx+4, y_gain_tmp+4, YG_dicMR_2_fx, 4, 32); + push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 5 ); + idx_g = vquant_fx(y_gain_tmp+8, YG_mean16_fx+8, y_gain_tmp+8, YG_dicMR_3_fx, 4, 32); + push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 5 ); + idx_g = vquant_fx(y_gain_tmp+12, YG_mean16_fx+12, y_gain_tmp+12, YG_dicMR_4_fx, 4, 16); + push_indice_fx( st_fx, IND_Y_GAIN_TMP, idx_g, 4 ); + } + } + + /* Gain adjustment to fit ACELP generic inactive coding gain at low rate */ + GSC_gain_adj(coder_type, core_brate, mean_4g[0], y_gain_tmp2 /* dummy buffer */, y_gain_tmp, y_gainQ); + + return mean_4g[0]; /*Q12*/ +} +/*-------------------------------------------------------------------* + * VDQ_vec() + * + * Return the dequantized vector of index + *-------------------------------------------------------------------*/ +static Word16 VDQ_vec_fx( + Word16 *Qvec_out_fx, /* o: Quanitzed vector */ + const Word16 *mean_dic_fx, /* i: average codebook */ + const Word16 *dic_fx, /* i: codebook */ + const Word16 index_fx, /* i: index of codebook*/ + const Word16 vec_en_fx /* i: vector length */ +) +{ + Word16 i, j; + + /*j = shr_r(extract_l(L_mult(index_fx,vec_en_fx)),1);*/ + j = i_mult2(index_fx,vec_en_fx); + FOR ( i = 0; i < vec_en_fx; i++) + { + Qvec_out_fx[i] = dic_fx[j++]; + move16(); + } + + FOR(i = 0; i < vec_en_fx; i++) + { + Qvec_out_fx[i] = add(Qvec_out_fx[i],mean_dic_fx[i]); + move16(); + } + + return index_fx; +} diff --git a/lib_com/gs_inact_switching_fx.c b/lib_com/gs_inact_switching_fx.c new file mode 100644 index 0000000..a92a719 --- /dev/null +++ b/lib_com/gs_inact_switching_fx.c @@ -0,0 +1,153 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define ALPHA0_FX 13107 +#define BETA0_FX (32768-ALPHA0_FX) + +/*========================================================================*/ +/* FUNCTION : Inac_swtch_ematch_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : Apply energy matching when swithcing to INACTIVE frame coded */ +/* by the GSC technology */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) coder_type : Coding mode */ +/* _ (Word16) L_frame : Frame lenght */ +/* _ (Word32) core_brate : core bitrate */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc2 : CELP/GSC excitation buffer Q_exc */ +/* _ (Word16[]) lt_ener_per_band : Long term energy per band Q12 */ +/* _ (Word16*) Q_exc : input and output format of exc2 */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ +void Inac_swtch_ematch_fx( + Word16 exc2[], /* i/o: CELP/GSC excitation buffer Q_exc*/ + Word16 dct_exc_tmp[], /* i : GSC excitation in DCT domain */ + Word16 lt_ener_per_band[], /* i/o: Long term energy per band Q12 */ + const Word16 coder_type, /* i : Coding mode */ + const Word16 L_frame, /* i : Frame lenght */ + const Word32 core_brate, /* i : Core bit rate */ + const Word16 Q_exc /* i : input and output format of exc2 */ + ,const Word16 bfi /* i : frame lost indicator */ + ,const Word16 last_core, /* i : Last core used */ + const Word16 last_codec_mode /* i : Last codec mode */ +) +{ + Word16 Ener_per_bd[MBANDS_GN]; + Word16 ftmp; + Word16 *pt_exc; + Word16 j, i; + + Word16 exp,frac; + Word32 L_tmp; + + /*-------------------------------------------------------------------------- + * average energy per band + *--------------------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + test(); + test(); + IF(EQ_16(coder_type,AUDIO)&&bfi==0) + { + Ener_per_band_comp_fx( dct_exc_tmp, Ener_per_bd, Q_exc, MBANDS_GN, 1); + + /* reset long-term energy per band */ + FOR(i = 0; i < MBANDS_GN; i++) + { + lt_ener_per_band[i] = Ener_per_bd[i]; + move16(); + } + + } + ELSE IF( EQ_16(coder_type,VOICED)||EQ_16(coder_type,GENERIC)||EQ_16(coder_type,TRANSITION)||NE_16(last_core,ACELP_CORE)||NE_16(last_codec_mode,MODE1)) + { + /* Find spectrum and energy per band for GC and VC frames */ + edct_16fx( exc2, dct_exc_tmp, L_frame, 5 ); + + Ener_per_band_comp_fx( dct_exc_tmp, Ener_per_bd, Q_exc, MBANDS_GN, 1); + + /* reset long-term energy per band */ + FOR(i = 0; i < MBANDS_GN; i++) + { + lt_ener_per_band[i] = Ener_per_bd[i]; + move16(); + } + } + ELSE IF( EQ_16(coder_type,INACTIVE)&&LE_32(core_brate,ACELP_24k40)) + { + /* Find spectrum and energy per band for inactive frames */ + edct_16fx( exc2, dct_exc_tmp, L_frame, 5 ); + Ener_per_band_comp_fx( dct_exc_tmp, Ener_per_bd, Q_exc, MBANDS_GN, 1 ); + + /* More agressive smoothing in the first 50 frames */ + pt_exc = dct_exc_tmp; + move16(); + FOR(i = 0; i < MBANDS_GN; i++) + { + /* Compute smoothing gain to apply with gain limitation */ + L_tmp = L_mult(ALPHA0_FX,lt_ener_per_band[i]); /*Q(15+12+1)=Q(28) */ + L_tmp = L_mac(L_tmp,BETA0_FX,Ener_per_bd[i]); /*Q28 */ + lt_ener_per_band[i] = round_fx(L_tmp); /*Q12 */ + + ftmp = sub(lt_ener_per_band[i],Ener_per_bd[i]); /*Q12 */ + + /* ftmp = (float)pow(10, ftmp);= pow(2,3.321928*ftmp);*/ + + L_tmp = L_mult(27213,ftmp); /*Q(13+12+1)=Q26 ; 27213=3.321928 in Q13 */ + L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of ftmp */ + ftmp = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + + exp = sub(exp,14); + IF( LT_16(i,2)) + { + FOR (j = 0; j < 8; j ++) + { + L_tmp = L_mult(*pt_exc,ftmp); /* Q_exc*Q0 -> Q(Q_exc+1) */ + L_tmp = L_shl(L_tmp, add(exp,15)); /* Q(Q_exc+1) -> Q(16+Q_exc)*/ + *pt_exc = round_fx(L_tmp); + pt_exc++; + } + } + ELSE + { + FOR (j = 0; j < 16; j ++) + { + L_tmp = L_mult(*pt_exc,ftmp); /* Q_exc*Q0 -> Q(Q_exc+1) */ + L_tmp = L_shl(L_tmp, add(exp,15)); /* Q(Q_exc+1) -> Q(16+Q_exc)*/ + *pt_exc = round_fx(L_tmp); /*Q_exc*/ + pt_exc++; + } + } + } + + /* Going back to time */ + edct_16fx( dct_exc_tmp, exc2, L_frame, 5 ); + } + + return; +} diff --git a/lib_com/gs_noisefill_fx.c b/lib_com/gs_noisefill_fx.c new file mode 100644 index 0000000..4c83b66 --- /dev/null +++ b/lib_com/gs_noisefill_fx.c @@ -0,0 +1,922 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "rom_com_fx.h" +#include "prot_fx.h" +#include "stl.h" + +/*-------------------------------------------------------------------* + * gs_noisf() + * + * Noise fill-in function + *-------------------------------------------------------------------*/ + +static void gs_noisf_fx( + const Word16 Start_BIN, /* i : First bin for noise fill */ + const Word16 NB_Qbins, /* i : Number of bin per band */ + const Word16 Noise_fac, /* i : Noise level Q15 */ + const Word16 *y_norm, /* i : Quantized pulses Qn */ + Word16 *exc_diffQ, /* o : Quantized pulses with noise added Qn */ + Word16 *seed_tcx, /* i : Random generator seed */ + const Word16 coder_type, /* i : coder type */ + Word16 qNoise_fac +) +{ + Word32 ftmp; + Word16 i, k; + Word16 NB_zer; + Word32 const_1=1; + Word16 tmp; + + NB_zer = shr(NB_Qbins,1); + + const_1 = L_shl(const_1, add(qNoise_fac, qNoise_fac)); + if( EQ_16(coder_type,INACTIVE)) + { + NB_zer = 2; + move16(); + } + + /*----------------------------------------------* + * noise fill-in on unquantized subvector * + * injected only from 1066Hz to 6400Hz. * + *----------------------------------------------*/ + + FOR( k=Start_BIN; k ACELP_24k40 ) + { + noise_offset = 6554; + move16(); /*.2f * 32768 */ + } + ELSE IF ( bitrate >= ACELP_22k60 ) + { + noise_offset = 9830; + move16();/*.3f * 32768 */ + } + ELSE IF ( bitrate >= ACELP_9k60 ) + { + noise_offset = 11469; + move16(); /*0.35f * 32768 */ + } + ELSE + { + noise_offset = 13107; + move16(); /*.4f * 32768 */ + } + + set16_fx( noisepb + i_band, noise_offset, sub(Mbands_gn, i_band) ); + + FOR( i = i_band; i < 5; i++ ) + { + noisepb[i] = s_min(noisepb[i], 6554); + move16(); + } + + return; +} +/*==========================================================================*/ +/* FUNCTION : void EstimateNoiseLevel_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word32) bitrate : Bitrate of the codec Q0 */ +/* _ (Word16) Diff_len : number of bin before cut-off frequency */ +/* _ (Word16) Mbands_gn : number of bands Q0 */ +/* _ (Word16) coder_type : coder type Q0 */ +/* _ (Word16) noise_lev : pulses dynamic Q0 */ +/* _ (Word16) pit_band_idx : bin position of the cut-off frequency */ +/* _ (Word16*) freq_nsbin_per_band : bin per bands tables Q0 */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) noisepb : Noise per band Q15 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* None */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*==========================================================================*/ +static void EstimateNoiseLevel_fx( + Word16 *noisepb, /* o : Noise per band */ + const Word32 bitrate, /* i : Bitrate of the codec */ + const Word16 Diff_len, /* i : number of bin before cut-off frequency */ + const Word16 Mbands_gn, /* i : number of bands */ + const Word16 coder_type, /* i : coder type */ + const Word16 noise_lev, /* i : pulses dynamic */ + const Word16 pit_band_idx, /* i : bin position of the cut-off frequency */ + Word16 last_bin, /* i : the last bin of bit allocation */ + Word16 bwidth +) +{ + Word16 i_band; + + i_band = 0; + move16(); + + IF( LT_16(Diff_len,L_FRAME)) + { + EstimateNoiseLevel_inner_fx(noisepb, bitrate, i_band, MBANDS_GN); + IF( coder_type != INACTIVE ) + { + test(); + test(); + IF( (EQ_32(bitrate,ACELP_8k00)&>_16(last_bin,8))&&NE_16(bwidth,NB)) + { + FOR( ; Mbands_gn > i_band; i_band++) + { + noisepb[i_band] = add(noisepb[i_band],noisepb[i_band]); + move16(); + } + } + ELSE + { + FOR( ; pit_band_idx > i_band; i_band++ ) + { + noisepb[i_band] = mult_r(noisepb[i_band], 16384); + move16();/* 1/2=0.5 in Q15 */ + } + } + } + } + test(); + IF ( (EQ_16(coder_type,INACTIVE)||GE_16(noise_lev,NOISE_LEVEL_SP3))) + { + FOR( i_band = 9; i_band < Mbands_gn; i_band++ ) + { + noisepb[i_band] = add(noisepb[i_band], mult_r(noisepb[i_band], 4915)); + move16();/*noisepb[i_band]*1.15=noisepb[i_band] *(1 + 0.15) */ + } + } + + return; +} + +/*============================================================================*/ +/* FUNCTION : void Appy_NoiseFill_fx() */ +/*----------------------------------------------------------------------------*/ +/* PURPOSE : */ +/*----------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16*) seed_tcx : Seed for noise Q0 */ +/* _ (Word16*) noisepb : Noise per band Q15 */ +/* _ (Word16) Diff_len : number of bin before cut-off frequency Q0 */ +/* _ (Word16) Mbands_gn : number of bands Q0 */ +/* _ (Word16) coder_type : pulses dynamic Q0 */ +/* _ (Word16*) freq_nsbin_per_band: bin per bands tables Q0 */ +/* _ (Word16) qexc_diffQ : Q format of exc_diffQ */ +/*----------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) exc_diffQ : Noise per band qexc_diffQ */ +/*----------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* None */ +/*----------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*============================================================================*/ +static void Apply_NoiseFill_fx( + Word16 *exc_diffQ, /* i/o: Noise per band qexc_diffQ */ + Word16 *seed_tcx, /* i : Seed for noise */ + const Word16 *noisepb, /* i : Noise per band Q15 */ + const Word16 Diff_len, /* i : number of bin before cut-off frequency */ + const Word16 Mbands_gn, /* i : number of bands */ + const Word16 coder_type, /* i : coder type */ + const Word16 *freq_nsbin_per_band, /* i : bin per bands tables */ + Word16 qexc_diffQ +) +{ + Word16 StartBin, NB_Qbins, i_band; + StartBin = 0; + move16(); + NB_Qbins = 0; + move16(); + + FOR( i_band = 0; i_band < Mbands_gn; i_band++ ) + { + StartBin += NB_Qbins; + move16(); + NB_Qbins = freq_nsbin_per_band[i_band]; + move16(); + + IF( LT_16(Diff_len,L_FRAME)) + { + gs_noisf_fx( StartBin , NB_Qbins, noisepb[i_band], exc_diffQ, exc_diffQ, seed_tcx, coder_type, qexc_diffQ); + } + } + + return; +} +/*==========================================================================*/ +/* FUNCTION :void freq_dnw_scaling_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) cor_strong_limit : HF correlation Q0 */ +/* _ (Word16) coder_type : coder type Q0 */ +/* _ (Word16) noise_lev : Noise level Q0 */ +/* _ (Word32) core_brate : Core bitrate Q0 */ +/* _ (Word16) Qx : Q format of fy_norm */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16[]) fy_norm : Frequency quantized parameter Qx */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _None */ +/*==========================================================================*/ +void freq_dnw_scaling_fx( + const Word16 cor_strong_limit, /* i : HF correlation */ + const Word16 coder_type, /* i : coder type */ + const Word16 noise_lev, /* i : Noise level */ + const Word32 core_brate, /* i : Core bitrate */ + Word16 fy_norm[], /* i/o: Frequency quantized parameter */ + Word16 Qx /* Q format of fy_norm*/ +) +{ + Word16 sc_dyn; + Word16 start_sc, i; + + sc_dyn = 32767; + move16(); /*Q15 */ + start_sc = L_FRAME; + move16(); + test(); + IF( LE_32(core_brate,ACELP_8k00)&&EQ_16(coder_type,INACTIVE)) + { + sc_dyn = mult_r(sc_dyn,4915); /*Q15 (0.15 in Q15) */ + start_sc = 64; + move16(); + } + ELSE IF ( EQ_16(coder_type,INACTIVE)) + { + sc_dyn = mult_r(sc_dyn,8192); /*Q15 (0.25 in Q15) */ + start_sc = 80; + move16(); + } + ELSE + { + /*sc_dyn = (float)(NOISE_LEVEL_SP3 - noise_lev)/10.0f + 0.4f;*/ + sc_dyn = extract_l(L_mac(13107, sub(NOISE_LEVEL_SP3, noise_lev), 1638)); /*Q0*Q14x2+Q15 =Q15*/ + start_sc = add(112, shl(sub(NOISE_LEVEL_SP3, noise_lev), 4)); + if( EQ_16(noise_lev,NOISE_LEVEL_SP0)) + { + start_sc = L_FRAME; + move16(); + } + } + + FOR(i = start_sc; i < L_FRAME; i++) + { + fy_norm[i] = mult_r(fy_norm[i],sc_dyn); + move16();/*Qx */ + } + + test(); + test(); + IF( (LT_32(core_brate,ACELP_13k20)&&cor_strong_limit==0)||LT_32(core_brate,ACELP_9k60)) + { + FOR(i = 160; i < L_FRAME; i++) + { + fy_norm[i] = s_min(fy_norm[i],shl(1,Qx)); + move16(); + fy_norm[i] = s_max(fy_norm[i],shl(-1,Qx)); + move16(); + } + } + ELSE IF ( LT_32(core_brate,ACELP_22k60)) + { + FOR(i = 160; i < L_FRAME; i++) + { + fy_norm[i] = s_min(fy_norm[i],shr_r(1536,sub(10,Qx))); + move16(); + fy_norm[i] = s_max(fy_norm[i],shr_r(-1536,sub(10,Qx))); + move16(); + } + } + + return; + +} + +static void Decreas_freqPeak_fx( + Word16 *lsf_new, /* i : ISFs at the end of the frame */ + Word16 *exc_diffQ, /* i/o: frequency coefficients of per band */ + Word16 rat /* i : threshold of ratio between consecutive lsf_new_diff */ +) +{ + Word16 i, j, k; + Word16 last_bin = 0; + Word16 pos = 0; + Word16 *src, max,avrg; + Word32 L_avrg,L_tmp; + Word16 lsf_new_diff[M]; + Word16 tmp,tmp1,exp; + Word16 tmp2; + + move16(); /*ptr init*/ + lsf_new_diff[0] = 0; /* prevent unitialized value */ + FOR(j=1; j<(M-1); j++) + { + lsf_new_diff[j] =sub( lsf_new[j] , lsf_new[j-1]);/*Qx2.56 */ + } + + avrg = 0; + move16(); + L_avrg = L_deposit_l(0); + max = 1; + move16(); + FOR(i=160; iQ_exc + 6 */ + avrg = round_fx(L_shl(L_avrg,10));/*Q_exc */ + last_bin = M-1; + move16(); /* When the search is false, should equate the end of the vector, not the beginning */ + FOR(i=0; i<(M-1); i++) + { + if(GT_16(lsf_new[i],10240)) + { + last_bin = i; + move16(); + BREAK; + } + } + + FOR(i=last_bin; i<14; i++) + { + tmp = mult_r(rat,lsf_new_diff[i-1] );/*Qx2.56 */ + IF(GT_16(tmp , lsf_new_diff[i])) + { + src = &exc_diffQ[shl(sub(i,1),4)]; + move16(); + FOR(j=0; j<2; j++) + { + FOR(k=0; k<16; k++) + { + tmp = mult_r(16384,abs_s(*src)); + IF(GT_16(tmp,avrg)) + { + tmp = abs_s(*src) ; + exp = norm_s(max); + tmp1 = div_s(shl(1,sub(14,exp)),max);/*Q(29 - exp - Q_exc) */ + L_tmp = L_mult(tmp,tmp1);/*Q(30 - exp) */ + tmp = round_fx(L_shl(L_tmp,exp));/*Q14 */ + tmp = sub(32767,tmp);/*Q14 */ + L_tmp = L_mult(avrg,tmp);/*Q_exc +15 */ + + tmp = round_fx(L_shl(L_tmp,1)); + tmp1 = negate(tmp); + + tmp2 = *src; + *(src) = tmp1; + move16(); + if( tmp2 > 0 ) + { + *(src) = tmp; + move16(); + } + + } + src++; + } + } + } + } + + tmp = mult_r(8192,max);/*Q_exc */ + test(); + IF(EQ_16(abs_s(exc_diffQ[pos]),max)&>_16(tmp,avrg)) + { + FOR(i=pos-1; iQ(2*Q_exc-7) */ + + exp1 = norm_l(Ener_fx); + Ener_fx = L_shl(Ener_fx, exp1); + exp1 = 31-exp1-sub(shl(Q_exc,1),7); + move16(); + Ener_fx = Isqrt_lc(Ener_fx, &exp1); /*Q(31-exp1) */ + + weight_fx = 16384; /*Q15 */ + src_fx = &exc_diffQ_fx[start_band]; /*Q_exc */ + FOR(i=last_bin; i Q16 */ + + frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */ + tmp = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp = sub(exp, 14); + Ener1_fx = mult_r(13107, shl(tmp, exp)); /*Q0 */ + + FOR(j=0; j<16; j++) + { + /**src = Ener1*(weight*(*src)*Ener + (1.0f-weight)*own_random(seed_tcx)/32768.0f); */ + L_tmp = Mult_32_16(Ener_fx, *src_fx); /*Q(31-exp+Q_exc-15) -> Q(16-exp+Q_exc) */ + tmp = extract_l(L_shr(L_tmp, add(4, sub(Q_exc, exp1)))); /*Q12 */ + tmp = mult_r(weight_fx, tmp); /*Q12 */ + + L_tmp = L_mult0(sub(32767, weight_fx), Random(seed_tcx)); /*Q30 */ + tmp1 = round_fx(L_shr(L_tmp, 2)); + + L_exc_diffQ_fx[16*i+j] = L_mult0(Ener1_fx, add(tmp, tmp1)); /*Q12 */ move32(); + src_fx++; + } + } + + /*Ener1 = (float)(0.4f*pow(10, Ener_per_bd_iQ[15])); */ + L_tmp = L_shr(L_mult0(Ener_per_bd_iQ_fx[15], 27213), 9); /* 3.321928 in Q13 -> Q16 */ + + frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */ + tmp = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp = sub(exp, 14); + Ener1_fx = mult_r(13107, shl(tmp, exp)); /*Q0 */ + + src_fx = &exc_diffQ_fx[224]; + FOR(j=0; j<32; j++) + { + /**src = Ener1*(weight*(*src)*Ener + (1.0f-weight)*own_random(seed_tcx)/32768.0f); */ + L_tmp = Mult_32_16(Ener_fx, *src_fx); /*Q(31-exp+Q_exc-15) -> Q(16-exp+Q_exc) */ + tmp = extract_l(L_shr(L_tmp, add(4, sub(Q_exc, exp1)))); /*Q12 */ + tmp = mult_r(weight_fx, tmp); /*Q12 */ + + L_tmp = L_mult0(sub(32767, weight_fx), Random(seed_tcx)); /*Q30 */ + tmp1 = round_fx(L_shr(L_tmp, 2)); /*Q12 */ + + L_exc_diffQ_fx[16*i+j] = L_mult0(Ener1_fx, add(tmp, tmp1)); /*Q12 */ move32(); + src_fx++; + } + + exc_diffQ_max = 0; + move16(); + FOR(i=start_band; i Q27 */ + L_tmp = L_shr(L_tmp, 10); /* From Q27 to Q16 */ + + frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */ + tmp = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp = sub(exp, 14); + tmp1 = shl(tmp,exp); + move16(); + ener = add (tmp1,ener);/*Q0 */ + } + + test(); + IF( EQ_32(core_brate,ACELP_8k00)&&NE_16(bwidth,NB)) + { + if(NE_16(last_coder_type,AUDIO)) + { + *last_ener = ener; + move16(); + } + test(); + test(); + IF((GT_16(last_bin,8)||Diff_len!=0)&&EQ_16(last_coder_type,AUDIO)) + { + MAX_Bin = 10; + move16(); + bwe_flag = 1; + move16(); + } + ELSE + { + MAX_Bin = 15; + move16(); + } + + last_bin_tmp = last_bin; + move16(); + last_bin = s_max(last_bin , MAX_Bin); + last_bin = add(last_bin, 1); + } + ELSE + { + last_bin = MBANDS_GN; + move16(); + last_bin_tmp = last_bin; + move16(); + } + IF( bfi ) + { + set16_fx( noisepb, 13107, MBANDS_GN ); /*0.4 in Q15 */ + } + ELSE + { + EstimateNoiseLevel_fx( noisepb, core_brate, Diff_len, last_bin, coder_type, noise_lev, pit_band_idx, + last_bin_tmp, bwidth ); + } + + IF( exc_wo_nf != NULL ) + { + Copy( exc_diffQ, exc_wo_nf, L_FRAME ); + } + + test(); + IF( GSC_noisy_speech && !bfi ) + { + set16_fx( noisepb, 3277, MBANDS_GN ); + } + Apply_NoiseFill_fx( exc_diffQ, seed_tcx, noisepb, Diff_len, last_bin, coder_type, mfreq_bindiv, Qexc_diffQ ); + + /*--------------------------------------------------------------------------------------* + * Quantize average gain + * Substract Q averaged gain + * VQ of remaining gain per band + *--------------------------------------------------------------------------------------*/ + test(); + IF( EQ_32(core_brate,ACELP_8k00)&&NE_16(bwidth,NB)) + { + Ener_per_band_comp_fx(exc_diffQ, Ener_per_bd_yQ, Qexc_diffQ, add(last_bin,1), 0); + } + ELSE + { + Ener_per_band_comp_fx(exc_diffQ, Ener_per_bd_yQ, Qexc_diffQ, MBANDS_GN, 1 ); + + IF( LT_16(nb_subfr, 4)) + { + FOR(i = L_FRAME-16; i < L_FRAME; i++) + { + /*exc_diffQ[i] *= 0.067f * i - 15.0f; = -15 - (-0.067f * i) */ + tmp = msu_r(-7680*65536, -17564, shl(i,6));/*-15 in Q9; -0.067 in Q18 and i in Q6= Q9 */ + L_tmp = L_mult(exc_diffQ[i],tmp); /*Q(Qexc_diffQ+10) */ + exc_diffQ[i] = round_fx(L_shl(L_tmp,16-10));/*Qexc_diffQ */ + } + } + } + /*--------------------------------------------------------------------------------------* + * Check potential energy excitation overshoot + *--------------------------------------------------------------------------------------*/ + IF( bfi ) + { + test(); + IF (GSC_noisy_speech == 0 && GT_16(coder_type,UNVOICED)) /* Here coder_type == last_coder_type because of the bfi */ + { + FOR( i=0; i end) + { + *src-- = *dst--; + move16(); + } + test(); + test(); + if( (bitallocation_exc[0] != 0 || bitallocation_exc[1] != 0) && EQ_32(core_brate, ACELP_8k00)) + { + exc_diffQ[160] = 0; + move16(); + } + + Q_hb_exc = 0; + move16(); + envelop_modify_fx( exc_diffQ, seed_tcx, last_bin, Ener_per_bd_iQ, Q_exc, &Q_hb_exc); + Copy_Scale_sig( &exc_diffQ[tmp1], &exc_dct_in[tmp1], sub(L_FRAME,tmp1), sub(Q_exc, Q_hb_exc)); /* from Q_hb_exc -> Q_exc as expected */ + } + + IF( LT_16(nb_subfr,4)) + { + FOR( i = sub(L_FRAME,16); i < L_FRAME; i++ ) + { + /*exc_dct_in[i] *= (0.067f*i-15.f); */ + tmp = mult_r(17564,shl(i,6)); /*0.067 in Q18 and i in Q6= Q9 */ + tmp = sub(tmp,7680); /*15 in Q9 = Q9 */ + L_tmp = L_mult(exc_dct_in[i],tmp);/*Q(Q_exc+10) */ + exc_dct_in[i] = round_fx(L_shl(L_tmp,6));/*Q_exc */ + } + } + + tmp1 = mult_r(ener,16384); + tmp1 = sub(*last_ener,tmp1); + tmp = mult_r(*last_ener,16384); + tmp = sub(ener,tmp); + test(); + IF( tmp>0 && tmp1>0 ) + { + length_bin = 6; + move16(); + IF(last_coder_type != AUDIO) + { + set16_fx( last_bitallocation_band, 0, 6 ); + Copy( &exc_dct_in[(4+length_bin)*16], &last_exc_dct_in[(4+length_bin)*16], length_bin*16 ); + } + + FOR(i=4; i<(4+length_bin); i++) + { + test(); + IF( !(bitallocation_band[i] == 0 && last_bitallocation_band[i-4] == 0)) + { + k = shl(add(i,length_bin),4); + src = &exc_dct_in[k]; /*(i+length_bin)*16*/ + dst = &last_exc_dct_in[k]; + FOR(j=0; j<16; j++) + { + tmp= mult_r(10923,abs_s(*src)); + tmp1 =mult_r(10923,abs_s(*dst)); + + IF(GT_16(tmp,abs_s(*dst))) + { + tmp2 = *src; + *src = mult_r(16384,sub(*src , abs_s(*dst))); /*Q_exc */ move16(); + tmp = mult_r(16384,add(tmp2 , abs_s(*dst))); /*Q_exc */ + if( tmp2 > 0 ) + { + *src = tmp; + move16(); + } + } + ELSE IF (GT_16(tmp1,abs_s(*src))) + { + tmp = mult_r(*src,22938); + tmp1 = mult_r(9830,abs_s(*dst)); + tmp2 = *src; + *src = sub(tmp,tmp1); /*Q_exc */ move16(); + if( tmp2 > 0 ) + { + *src = add(tmp,tmp1); /*Q_exc */ move16(); + } + } + src++; + dst++; + } + } + } + } + IF(EQ_16(bwe_flag,1)) + { + Decreas_freqPeak_fx( lsf_new, exc_dct_in, 9830 ); + } + ELSE + { + Decreas_freqPeak_fx( lsf_new, exc_dct_in, 16384 ); + } + } + + Copy( &exc_dct_in[64], &last_exc_dct_in[64], L_FRAME-64 ); + Copy(&bitallocation_band[4], last_bitallocation_band, 6); + *last_ener = ener; + move16(); + + return; +} diff --git a/lib_com/gs_preech_fx.c b/lib_com/gs_preech_fx.c new file mode 100644 index 0000000..75928b7 --- /dev/null +++ b/lib_com/gs_preech_fx.c @@ -0,0 +1,139 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define ATT_LENGHT 64 +#define ATT_SEG_LEN (L_FRAME/ATT_LENGHT) +#define INV_ATT_SEG_LEN (1.0f/ATT_SEG_LEN) +#define INV_L_FRAME (1.0f/L_FRAME) + +/*==========================================================================*/ +/* FUNCTION : void pre_echo_att_fx(); */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Attenuation of the pre-echo when encoder specifies an attack */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) L_frame_fx : length of the frame Q0 */ +/* _ (Word16) gsc_attack_flag_fx : LP filter coefficient Q0 */ +/* _ (Word16) core_fx : core codec used Q0 */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16*) exc_fx : adapt. excitation exc Q_exc */ +/* _ (Word32*) Last_frame_ener_fx : Energy of the last frame Q1 */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*==========================================================================*/ +void pre_echo_att_fx( + Word32 *Last_frame_ener_fx, /* i/o: Energy of the last frame 2*Q_new+1*/ + Word16 *exc_fx, /* i/o: Excitation of the current frame Q_new*/ + const Word16 gsc_attack_flag_fx /* i : flag signalling attack encoded by AC mode (GSC) */ + ,const Word16 Q_new + ,const Word16 last_coder_type_fx /* i : Last coding mode */ +) +{ + Word32 etmp_fx; + Word32 finc_fx[ATT_LENGHT] = {0}; + Word16 ratio_fx; + Word16 attack_pos_fx, i; + Word32 L_tmp, L_tmp1; + Word16 tmp, n1, n2, exp, frac1, frac2; + Word32 etmp1_fx; + test(); + IF ( EQ_16(gsc_attack_flag_fx,1)&&EQ_16(last_coder_type_fx,AUDIO)) /*gsc_attack_flag_fx does not get set for all the test cases */ + { + /*-------------------------------------------------------------------------* + * Find where the onset (attack) occurs by computing the energy per section + * The inverse weighting aims to favor the first maxima in case of + * gradual onset + *-------------------------------------------------------------------------*/ + FOR(i = 0; i < ATT_LENGHT; i++) + { + L_tmp = sum2_fx(&exc_fx[shl(i,2)], ATT_SEG_LEN ); /*2*Q_new+1, //ATT_SEG_LEN=(L_FRAME/ATT_LENGHT)=4(=shl(x,2))*/ + tmp = div_s(sub(ATT_LENGHT,i),ATT_LENGHT); /*Q15 */ + L_tmp = Mult_32_16(L_tmp, tmp); /*2*Q_new+1 */ + finc_fx[i] = L_tmp; + move32(); /*2*Q_new+1 */ + } + + attack_pos_fx = maximum_32_fx(finc_fx, ATT_LENGHT, &etmp_fx); + + /* Scaled the maximum energy and allowed 6 dB increase*/ + etmp_fx = L_shr(etmp_fx,add(2+1-4, shl(Q_new,1)));/*2*Q_new+1 //INV_ATT_SEG_LEN=1/4(=shr(x,2)) -> Q4 */ + etmp1_fx = etmp_fx; + move32(); + *Last_frame_ener_fx = L_shl(*Last_frame_ener_fx,2); + move32(); /*2*Q_new+1 */ + + /* If the maximum normalized energy > last frame energy + 6dB */ + test(); + IF( GT_32(etmp_fx,*Last_frame_ener_fx)&&attack_pos_fx>0) + { + /* Find the average energy before the attack */ + L_tmp = sum32_fx( finc_fx, attack_pos_fx); /*Q1 */ + L_tmp1 = L_shr(L_mult(attack_pos_fx,attack_pos_fx),1); /*Q0 */ + tmp = round_fx(Isqrt(L_tmp1)); /*Q15 */ + L_tmp = L_shr(L_tmp,2); /*Q1 ; ATT_SEG_LEN=4 */ + etmp_fx = Mult_32_16(L_tmp,tmp); /*Q1 */ + + etmp_fx = L_shr(etmp_fx,add(1-4, shl(Q_new,1))); /* makes etmp i nQ4 as *Last_frame_ener_fx */ + /* Find the correction factor and apply it before the attack */ + /* ratio = (float)sqrt(*Last_frame_ener/etmp);*/ + /* = isqrt(etmp/(*Last_frame_ener)) */ + etmp_fx = L_max(etmp_fx,1); + *Last_frame_ener_fx = L_max(*Last_frame_ener_fx,1); + n1 = norm_l(etmp_fx); + n2 = norm_l(*Last_frame_ener_fx); + + n1 = sub(n1,1); + exp = sub(n1,n2); + + frac1 = round_fx(L_shl(etmp_fx,n1)); + frac2 = round_fx(L_shl(*Last_frame_ener_fx,n2)); + + L_tmp = L_mult0(128, div_s(frac1, frac2)); /* s = gain_out / gain_in */ + L_tmp = L_shr(L_tmp, exp); /* add exponent */ + + L_tmp = Isqrt(L_tmp); + ratio_fx = round_fx(L_shl(L_tmp, 9)); + + /* Pre-echo atttenuation should never increase the energy */ + ratio_fx = s_min(ratio_fx, 8192); + FOR(i = 0; i < attack_pos_fx*ATT_SEG_LEN; i++) + { + /*exc_fx[i] *= ratio_fx;*/ + exc_fx[i] = round_fx(L_shl(L_mac(-8192, exc_fx[i], ratio_fx), 2)); + } + } + *Last_frame_ener_fx = etmp1_fx; + move32(); + } + ELSE + { + /*-------------------------------------------------------* + * In normal cases, just compute the energy of the frame + *-------------------------------------------------------*/ + + etmp_fx = sum2_fx( exc_fx, L_FRAME ); /*2*Q_new+1 */ + + etmp_fx = L_shr(etmp_fx,add(8+1-4, shl(Q_new,1))); /*2*Q_new+1 //INV_L_FRAME = 1/256 -> Q4*/ + *Last_frame_ener_fx = etmp_fx; + move32(); /*2*Q_new+1*/ + } + + return; +} diff --git a/lib_com/guided_plc_util.c b/lib_com/guided_plc_util.c new file mode 100644 index 0000000..5c1fa7d --- /dev/null +++ b/lib_com/guided_plc_util.c @@ -0,0 +1,324 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "prot_fx.h" +#include "stl.h" +#include "rom_com_fx.h" + +#include "basop_util.h" +#include "rom_basop_util.h" + +void getLookAheadResSig( Word16 *speechLookAhead, Word16 *A_3Q12, Word16 *res, Word16 L_frame, Word16 numSubFrame ) +{ + Word16 *p_A; + Word16 i_subfr; + Word16 subfr_len[2] = { L_SUBFR, L_SUBFR }; + + if( GT_16( L_FRAME16k, L_frame )) + { + subfr_len[1] = 48; + move16(); /* 0.75 * L_SUBFR(64) */ + } + + p_A = A_3Q12; + FOR(i_subfr=0; i_subfrlsfoldbfi1_14Q1[i] ); + L_tmp = L_mac( L_tmp, divide_by_3_Q15, decState->lsfoldbfi0_14Q1[i] ); + decState->lsf_adaptive_mean_14Q1[i] = mac_r( L_tmp, divide_by_3_Q15, lsf_14Q1[i] ); + decState->lsfoldbfi1_14Q1[i] = decState->lsfoldbfi0_14Q1[i]; + move16(); + decState->lsfoldbfi0_14Q1[i] = lsf_14Q1[i]; + move16(); + } + + return; +} + +void getConcealedLP( HANDLE_PLC_ENC_EVS memDecState, Word16 *AqCon, const Word16 lsfBase[], Word16 last_good, Word16 L_frame) +{ + Word16 *lsf; + Word16 lsp[(NB_DIV+1)*M]; + Word32 int_fs; + + move16(); + lsf = memDecState->lsf_con; + + + dlpc_bfi( L_frame, &lsf[0], memDecState->lsfold_14Q1, last_good, + 1, memDecState->mem_MA_14Q1, memDecState->mem_AR, &(memDecState->stab_fac_Q15), memDecState->lsf_adaptive_mean_14Q1, + 1, + NULL, + 0, + NULL, + NULL, + lsfBase, + 0 + ); + Copy( memDecState->lspold_Q15, lsp, M ); + + int_fs = INT_FS_FX; + move32(); + if( EQ_16(L_frame,L_FRAME_16k)) + { + int_fs = INT_FS_16k_FX; + move32(); + } + lsf2lsp_fx( lsf, &lsp[M], M, int_fs ); + + int_lsp_fx( L_frame, &lsp[0], &lsp[M], AqCon, M, interpol_frac_fx, 0 ); + + return; +} + +void getConcealedLSF( HANDLE_PLC_ENC_EVS memDecState, const Word16 lsfBase[], Word16 last_good, Word16 L_frame) +{ + Word16 *lsf = memDecState->lsf_con; + + + dlpc_bfi( L_frame, &lsf[0], memDecState->lsfold_14Q1, last_good, + 1, memDecState->mem_MA_14Q1, memDecState->mem_AR, &(memDecState->stab_fac_Q15), memDecState->lsf_adaptive_mean_14Q1, + 1, + NULL, + 0, + NULL, + NULL, + lsfBase, + 0 + ); + + return; +} + +static void reorder_lsfs(Word16 *lsf, const Word16 min_dist, const Word16 n, const Word32 sr_core); + +void RecLpcSpecPowDiffuseLc( Word16 *lspq, Word16 *lsp_old, Word16 *lsfq, Decoder_State_fx *st, Word16 reset_q ) +{ + const Word16 *means; + Word16 lsf_old[M]; + Word16 i; + + means = PlcGetLsfBase ( st->lpcQuantization, + st->narrowBand, + st->sr_core ); + + Copy( st->lsf_old_fx, lsf_old, M ); + + modify_lsf( lsf_old, M, st->sr_core, reset_q ); + + lsf2lsp_fx( lsf_old, lsp_old, M, st->sr_core ); + + IF( reset_q ) + { + FOR ( i=0; imem_MA_fx[i], means[i]); + move16(); + } + sort_fx( lsfq, 0, sub(M, 1) ); + + reorder_lsfs( lsfq, LSF_GAP_FX, M, st->sr_core ); + lsf2lsp_fx( lsfq, lspq, M, st->sr_core ); + } + ELSE + { + modify_lsf( lsfq, M, st->sr_core, reset_q ); + lsf2lsp_fx(lsfq, lspq, M, st->sr_core); + } + + return; +} + +void modify_lsf( + Word16 *lsf, + const Word16 n, + const Word32 sr_core + , Word16 reset_q +) +{ + Word16 i, k, th_x1p28_Q14; + Word16 gap, gap_sum; + + + th_x1p28_Q14 = 4864/*1900.0f*1.28f Q1*/; + move16(); + if( EQ_32( sr_core, 16000 )) + { + th_x1p28_Q14 = 6080/*2375.0f*1.28f Q1*/; + move16(); + } + + IF( reset_q == 0 ) + { + th_x1p28_Q14 = 2048; /* 800.0f*1.28f Q1*/ move16(); + if( EQ_32( sr_core, 16000 )) + { + th_x1p28_Q14 = 2560; /*1000.0f*1.28f Q1*/ move16(); + } + } + + FOR ( i=1; i= 0; i--) /* Reverify the minimum ISF gap in the reverse direction */ + { + IF (LE_16(lsf[i], th2)) + { + curr_min_dist = min_dist_fac2; + move16(); + } + ELSE + { + if (LE_16(lsf[i], th1)) + { + curr_min_dist = min_dist_fac3; + move16(); + } + } + + if (GT_16(lsf[i], lsf_max)) + { + lsf[i] = lsf_max; + move16(); + } + lsf_max = sub(lsf[i], curr_min_dist); + } + } + + return; +} + diff --git a/lib_com/hp50.c b/lib_com/hp50.c new file mode 100644 index 0000000..93b5219 --- /dev/null +++ b/lib_com/hp50.c @@ -0,0 +1,250 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include "stl.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "options.h" + + +#define HP20_COEFF_SCALE (2) + +/* + * hp20 + * + * Function: + * 2nd order high pass filter with nominal cut off frequency at 20 Hz. + * + * Returns: + * void + */ + +static Word32 HP50_Mode2_Mpy_32_16_fix(Word32 a, Word16 b) +{ + Word32 result = Mpy_32_16_1(a,b); + /* perform rounding towards lower value for negative results */ + if (result < 0) result = L_add(result,1); + return result; +} + +static Word32 HP50_Mpy_32_32_fix(Word32 a, Word32 b) +{ + Word32 result = Mpy_32_32(a,b); + /* perform rounding towards lower value for negative results */ + if (result < 0) result = L_add(result,1); + return result; +} + + +static void filter_2nd_order( + Word16 signal[], + const Word16 stride, + const Word16 prescale, + const Word16 lg, + Word32 mem[4], + Word32 a1, + Word32 a2, + Word32 b1, + Word32 b2 +) +{ + + Word16 i; + Word16 x2, x1; + Word32 L_sum, L_y1, L_y2; + + + /* + * Saturation: The states of the filter, namely L_y1 and L_y2 shall + * never saturate, because that causes error in the filter feedback. + * The final output written into signal[] might saturate because of + * unavoidable filter overshoot. + */ + + /* Execute first 2 iterations with 32-bit x anx y memory values */ + BASOP_SATURATE_ERROR_ON + L_sum = HP50_Mpy_32_32_fix(b2,mem[2]); /* b2*x2 */ + L_sum = L_add(L_sum,HP50_Mpy_32_32_fix(b1,mem[3])); /* b1*x1 */ + x2 = shr(signal[0*stride], prescale); + L_sum = L_add(L_sum,HP50_Mode2_Mpy_32_16_fix(b2,x2)); /* b2*x0 */ + L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(mem[0],a2)); /* y2*a2 */ + L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(mem[1],a1)); /* y1*a1 */ + + L_y2 = L_shl(L_sum, HP20_COEFF_SCALE); + BASOP_SATURATE_ERROR_OFF + BASOP_SATURATE_WARNING_OFF + signal[0*stride] = round_fx(L_shl(L_y2, prescale)); + BASOP_SATURATE_WARNING_ON + + BASOP_SATURATE_ERROR_ON + L_sum = HP50_Mpy_32_32_fix(b2,mem[3]); /* b2*x2 */ + L_sum = L_add(L_sum,HP50_Mode2_Mpy_32_16_fix(b1,x2)); /* b1*x1 */ + x1 = shr(signal[1*stride], prescale); + L_sum = L_add(L_sum,HP50_Mode2_Mpy_32_16_fix(b2,x1)); /* b2*x0 */ + L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(mem[1],a2)); /* y2*a2 */ + L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(L_y2, a1)); /* y1*a1 */ + + L_y1 = L_shl(L_sum, HP20_COEFF_SCALE); + BASOP_SATURATE_ERROR_OFF + BASOP_SATURATE_WARNING_OFF + signal[1*stride] = round_fx(L_shl(L_y1, prescale)); + BASOP_SATURATE_WARNING_ON + + /* New we use a trick and toggle x1/x2 and L_y1/L_y2 to save a few cycles unrolling the loop by 2 */ + FOR (i = 2; i < lg; i+=2) + { + /* y[i+0] = b2*x[i-2] + b1*x[i-1] + b2*x[i-0] + a2*y[i-2] + a1*y[i-1]; */ + BASOP_SATURATE_ERROR_ON + L_sum = HP50_Mode2_Mpy_32_16_fix(b2,x2); + L_sum = L_add(L_sum,HP50_Mode2_Mpy_32_16_fix(b1,x1)); + x2 = shr(signal[i*stride], prescale); + L_sum = L_add(L_sum,HP50_Mode2_Mpy_32_16_fix(b2,x2)); + L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(L_y2,a2)); + L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(L_y1,a1)); + + L_y2 = L_shl(L_sum, HP20_COEFF_SCALE); + BASOP_SATURATE_ERROR_OFF + BASOP_SATURATE_WARNING_OFF + signal[i*stride] = round_fx(L_shl(L_y2, prescale)); + BASOP_SATURATE_WARNING_ON + /* y[i+1] = b2*x[i-1] + b1*x[i-0] + b2*x[i+1] + a2*y[i-1] + a1*y[i+0]; */ + BASOP_SATURATE_ERROR_ON + L_sum = HP50_Mode2_Mpy_32_16_fix(b2,x1); + L_sum = L_add(L_sum,HP50_Mode2_Mpy_32_16_fix(b1,x2)); + x1 = shr(signal[(i+1)*stride], prescale); + L_sum = L_add(L_sum,HP50_Mode2_Mpy_32_16_fix(b2,x1)); + L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(L_y1,a2)); + L_sum = L_add(L_sum, HP50_Mpy_32_32_fix(L_y2,a1)); + + L_y1 = L_shl(L_sum, HP20_COEFF_SCALE); + BASOP_SATURATE_ERROR_OFF + BASOP_SATURATE_WARNING_OFF + signal[(i+1)*stride] = round_fx(L_shl(L_y1, prescale)); + BASOP_SATURATE_WARNING_ON + } + /* update static filter memory from variables */ + mem[0] = L_y2; + move32(); + mem[1] = L_y1; + move32(); + mem[2] = L_deposit_h(x2); + mem[3] = L_deposit_h(x1); + + + return; +} + + +void hp20(Word16 signal[], /* i/o: signal to filter any */ + const Word16 stride, /* i : stride to be applied accessing signal */ + const Word16 lg, /* i : length of signal (integer) Q0 */ + Word32 mem[5], /* i/o: static filter memory with this layout: */ + /* mem[0]: y[-2] (32-bit) */ + /* mem[1]; y[-1] (32-bit) */ + /* mem[2]: x[-2] << 16 */ + /* mem[3]: x[-1] << 16 */ + /* Note: mem[0..3] need to be scaled per frame */ + /* mem[4]: states scale */ + const Word32 sFreq) /* i : input sampling rate Q0 */ +{ + Word32 a1, b1, a2, b2; + Word16 prescale, prescaleOld, diff; + + + + prescale = getScaleFactor16(signal, lg); + prescaleOld = extract_l(mem[4]); + diff = norm_l(L_shl(mem[2], prescaleOld)); + if (mem[2] != 0) + { + prescale = s_min(prescale, diff); + } + diff = norm_l(L_shl(mem[3], prescaleOld)); + if (mem[3] != 0) + { + prescale = s_min(prescale, diff); + } + /* Take into account the left shift performed into the loop + 1 bit headroom*/ + prescale = s_max(-12, sub(1+HP20_COEFF_SCALE, prescale)); + IF (prescale != prescaleOld) + { + diff = sub(prescale, prescaleOld); + mem[0] = L_shr(mem[0], diff); + move32(); + mem[1] = L_shr(mem[1], diff); + move32(); + mem[2] = L_shr(mem[2], diff); + move32(); + mem[3] = L_shr(mem[3], diff); + move32(); + mem[4] = L_deposit_l(prescale); + } + + IF ( EQ_32(sFreq,8000)) + { + /* hp filter 20Hz at 3dB for 8000 Hz input sampling rate + [b,a] = butter(2, 20.0/4000.0, 'high'); + b = [0.988954248067140 -1.977908496134280 0.988954248067140] + a = [1.000000000000000 -1.977786483776764 0.978030508491796]*/ + a1 = 1061816033l/* 1.977786483776764 Q29*/; move32(); + a2 = -525076131l/*-0.978030508491796 Q29*/; move32(); + b1 = -1061881538l/*-1.977908496134280 Q29*/; move32(); + b2 = 530940769l/* 0.988954248067140 Q29*/; move32(); + + } + ELSE IF ( EQ_32(sFreq,16000)) + { + /* hp filter 20Hz at 3dB for 16000KHz sampling rate + [b,a] = butter(2, 20.0/8000.0, 'high'); + b = [0.994461788958195 -1.988923577916390 0.994461788958195] + a = [1.000000000000000 -1.988892905899653 0.988954249933127] */ + a1 = 1067778748l/* 1.988892905899653 Q29*/; move32(); + a2 = -530940770l/*-0.988954249933127 Q29*/; move32(); + b1 = -1067795215l/*-1.988923577916390 Q29*/; move32(); + b2 = 533897608l/* 0.994461788958195 Q29*/; move32(); + + } + ELSE IF ( EQ_32(sFreq,32000)) + { + /* hp filter 20Hz at 3dB for 32000KHz sampling rate + [b,a] = butter(2, 20.0/16000.0, 'high'); + b = [0.997227049904470 -1.994454099808940 0.997227049904470] + a = [1.000000000000000 -1.994446410541927 0.994461789075954]*/ + a1 = 1070760263l/* 1.994446410541927 Q29*/; move32(); + a2 = -533897608l/*-0.994461789075954 Q29*/; move32(); + b1 = -1070764392l/*-1.994454099808940 Q29*/; move32(); + b2 = 535382196l/* 0.997227049904470 Q29*/; move32(); + } + ELSE + { + assert (sFreq == 48000); + /* hp filter 20Hz at 3dB for 48000KHz sampling rate + [b,a] = butter(2, 20.0/24000.0, 'high'); + b =[0.998150511190452 -1.996301022380904 0.998150511190452] + a =[1.000000000000000 -1.996297601769122 0.996304442992686]*/ + a1 = 1071754114l/* 1.996297601769122 Q29*/; move32(); + a2 = -534886875l/*-0.996304442992686 Q29*/; move32(); + b1 = -1071755951l/*-1.996301022380904 Q29*/; move32(); + b2 = 535877975l/* 0.998150511190452 Q29*/; move32(); + } + + + filter_2nd_order(signal, + stride, + prescale, + lg, + mem, + a1, + a2, + b1, + b2); + + return; +} + + + + diff --git a/lib_com/hq2_bit_alloc_fx.c b/lib_com/hq2_bit_alloc_fx.c new file mode 100644 index 0000000..802ffc0 --- /dev/null +++ b/lib_com/hq2_bit_alloc_fx.c @@ -0,0 +1,914 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "prot_fx.h" +#include "stl.h" /* required for wmc_tool */ + +#define MIN_BITS_FIX 0 /* QRk=18 */ +#define HQ_16k40_BIT (HQ_16k40/50) /* 16400/50=328 */ +#define Qbf 14 /* Q value for bits_fact */ +#define C1_QRk (1< 0 ) + { + be_sum_fx = add(be_sum_fx, y_index_fx[k]); + } + } + QBavg = 0; + move16(); + + /*Ravg = (float) be_sum/be_cnt;*/ + Ravg_fx = 0; + move16(); + QRavg = 0; + move16(); + IF( be_cnt_fx != 0x0 ) + { + exp_normn = norm_s(be_sum_fx); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_s(be_cnt_fx); + Ravg_fx = div_s(shl(be_sum_fx, exp_normn), shl(be_cnt_fx, exp_normd)); + + Ravg_fx = shr(Ravg_fx, 2); /* safe shift */ + QRavg = add(sub(exp_normn, exp_normd), 15-2); + } + + enr_diffcnt_fx = 0; + move16(); + th_5_fx = shl(5, QRavg); + FOR (j = 0; j < be_cnt_fx; j++) + { + if( GT_16(abs_s(sub(Ravg_fx, shl(y_index_fx[j], QRavg))), th_5_fx)) + { + enr_diffcnt_fx = add(enr_diffcnt_fx, 1); + } + } + + scale_fact_fx = 19661; + move16(); /* 0.60f 19660.8(Q15) */ + if( enr_diffcnt_fx > 0 ) + { + scale_fact_fx = 11468; + move16(); /* 0.35f 11468.8(Q15) */ + } + + /* Bits allocation to individual SB's in a group based on Band Energies */ + FOR (j = 0; j < be_cnt_fx; j++) + { + Rcnt_fx = add(i, 1); + + /* Ravg = (float) be_sum/Rcnt; */ + exp_normn = norm_s(be_sum_fx); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_s(Rcnt_fx); + Ravg_fx = div_s(shl(be_sum_fx, exp_normn), shl(Rcnt_fx, exp_normd)); + Ravg_fx = shr(Ravg_fx, 2); /* safe shift */ + QRavg = add(sub(exp_normn, exp_normd), 15-2); + + if(be_sum_fx <= 0) + { + be_sum_fx = 1; + move16(); + } + + /* Bits_avg = (float) Bits/(be_sum+EPSILON); */ + Bits_avg_fx = 0; + move16(); + QBavg = 0; + move16(); + IF ( Bits != 0 ) + { + exp_normn = norm_s(Bits); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_s(be_sum_fx); + Bits_avg_fx = div_s(shl(Bits, exp_normn), shl(be_sum_fx, exp_normd)); + Bits_avg_fx = shr(Bits_avg_fx, 2); /* safe_shift */ + QBavg = add(sub(exp_normn, exp_normd), 15-2); + } + FOR (k = 0; k <=i; k++) + { + IF(L_R_temp[k] > 0) /* Rtemp -> SWB_BWE_LR_QRk */ + { + /* Allocate more bits to SB, if SB bandenergy is higher than average energy */ + /* R_temp[k] = (float)( Bits_avg * y_index[k]+( scale_fact * (y_index[k] - Ravg))); */ + L_temp1 = L_mult(Bits_avg_fx, y_index_fx[k]); /* QBavg+1 */ + L_temp2 = L_mult(scale_fact_fx, sub(shl(y_index_fx[k], QRavg), Ravg_fx)); /* 15+QRavg+1 */ + L_R_temp[k] = L_add(L_shr(L_temp1, sub(add(QBavg, 1), SWB_BWE_LR_QRk)), L_shr(L_temp2, sub(add(QRavg, 16), SWB_BWE_LR_QRk))); /* SWB_BWE_LR_QRk */ + } + } + IF ( LT_32(L_R_temp[i], L_Bits_needed)) + { + L_R_temp[i] = L_deposit_l(0); + + p2aflags_fx_ptr[index_fx[i]] = 0; + move16(); + + /* be_sum -= y_index[i]; */ + be_sum_fx = sub(be_sum_fx, y_index_fx[i]); + + i = sub(i, 1); + } + ELSE + { + BREAK; + } + } + + /* Rearrange the bit allocation to align with original */ + FOR ( k = 0 ; k < band_num_fx; k++ ) + { + j = index_fx[k]; + move16(); + L_R_ptr[j] = L_R_temp[k]; + move32(); + } + + return; +} + +/*-------------------------------------------------------------------* + * hq2_bit_alloc_har() + * + * Bit allocation mechanism for HQ_HARMONIC mode + *-------------------------------------------------------------------*/ + +void hq2_bit_alloc_har_fx ( + const Word32 *L_y, /* i : Qbe band energy of sub-vectors */ + Word16 B_fx, /* i : Q0 number of available bits */ + const Word16 N_fx, /* i : Q0 number of sub-vectors */ + Word32 *L_Rsubband, /* o : QRk sub-band bit-allocation vector */ + Word16 p2a_bands_fx, /* i : highfreq bands */ + const Word32 L_core_brate, /* i : Q0 core bit rate */ + Word16 p2a_flags_fx[], /* i/o: Q0 p2a_flags */ + const Word16 band_width_fx[] /* i : Q0 table of band_width */ +) +{ + Word16 i, j, k; + + Word32 L_norm_sum; /* Qbe */ + Word32 L_Ravg_sub[GRP_SB]; /* Qbe */ + Word32 L_temp_band_energy[BANDS_MAX]; /* Qbe */ + + Word16 j_fx, k_fx, Bits_grp_fx[GRP_SB]; + + Word32 L_temp_band_energydiff[BANDS_MAX]; + Word16 G1_BE_DIFF_POS_fx; /* Q0 */ + Word32 L_G1_BE_DIFF_VAL; /* Qbe Word32 */ + Word16 final_gr_fact_pos_fx, gmax_range_fx[2], temp_fx; + Word16 bits_fact_fx, bits_fact1_fx; /* Q? */ + Word16 grp_rngmax_fx[2] = {0}; + Word16 index_fx[NB_SWB_SUBBANDS_HAR], y_index_fx[NB_SWB_SUBBANDS_HAR], esthf_bits_fx, grp_bit_avg_fx, harmonic_band_fx; + Word32 L_norm_sum_avg; + Word32 L_norm_diff; /* Qbe */ + Word16 bits_allocweigh_fx; /* Q15 */ + Word16 grp_bound_fx[5]; + Word32 L_grp_thr[GRP_SB]; /* not require Word32 precission */ + Word16 lf_hf_ge_r_fx; /* Q15 */ + Word32 L_avg_enhf_en_diff; /* Qbe */ + + Word16 B_norm_fx; + + Word32 L_temp, L_temp2; + Word16 exp, frac; + + Word32 L_THR1, L_THR2, L_THR3; + + Word16 exp_norm; + Word16 norm_sum_fx; + Word16 Qns; /* Q value for norm_sum_fx */ + Word16 Inv_norm_sum_fx; /* 1/norm_sum */ + Word16 QIns; /* Q value for Inv_norm_sum_fx */ + + Word16 exp_normn, exp_normd; + Word16 div_fx; + + Word16 Inv_p2a_bands_fx; + Word16 QIpb; + + Word16 exp_shift; + + L_THR1 = L_shl(L_deposit_l(THR1), SWB_BWE_LR_QRk); + L_THR2 = L_shl(L_deposit_l(THR2), SWB_BWE_LR_QRk); + L_THR3 = L_shl(L_deposit_l(THR3), SWB_BWE_LR_QRk); + + set16_fx(Bits_grp_fx, 0, GRP_SB); + + /* Initialize subbands bits allocation vector based on harmonic bands */ + harmonic_band_fx = add(sub(N_fx, p2a_bands_fx), 1); + /*printf("harmonic_band= %d %d\n", harmonic_band, harmonic_band_fx);*/ + FOR (k = 0; k < N_fx; k++) + { + L_Rsubband[k] = (Word32)(C1_QRk); + move32(); /* Constant Value */ + L_temp_band_energy[k] = L_y[k]; + move32(); /* SWB_BWE_LR_Qbe */ + } + final_gr_fact_pos_fx = 2; + move16(); + bits_fact_fx = C1_Qbf; + move16(); + bits_fact1_fx = C1_Qbf; + move16(); + + gmax_range_fx[0]= G1_RANGE; + move16(); + gmax_range_fx[1]= G1G2_RANGE; + move16(); + + IF( EQ_32(L_core_brate, HQ_16k40)) + { + gmax_range_fx[1] = add(gmax_range_fx[1], 2); + move16(); + } + + /* decide each group range, for grouping spectral coefficients */ + grp_rngmax_fx[1] = 16; + move16(); + grp_rngmax_fx[0] = 7; + move16(); + temp_fx = 0; + move16(); + FOR( i=0; i<2; i++ ) + { + j_fx = gmax_range_fx[i]; + move16(); + k_fx = 0; + move16(); + WHILE(GE_32(L_temp_band_energy[gmax_range_fx[i] - 1], L_temp_band_energy[j_fx]) && LT_16(j_fx, grp_rngmax_fx[i]) ) + { + test(); + k_fx = add(k_fx, 1); + j_fx = add(j_fx, 1); + } + + temp_fx = k_fx; + move16(); + IF( GT_16(temp_fx, 1)) + { + FOR( temp_fx = 2; temp_fx <= k_fx ; ) + { + IF( LT_32(L_temp_band_energy[gmax_range_fx[i]+temp_fx-1], L_temp_band_energy[gmax_range_fx[i]+temp_fx])) + { + BREAK; + } + ELSE IF( GE_32(L_temp_band_energy[gmax_range_fx[i]+temp_fx-1], L_temp_band_energy[gmax_range_fx[i]+temp_fx])) + { + temp_fx = add(temp_fx, 1);; + IF( GT_16(temp_fx, k_fx)) + { + temp_fx = sub(temp_fx, 1); + BREAK; + } + } + } + + gmax_range_fx[i] = add(gmax_range_fx[i], temp_fx); + move16(); + } + ELSE + { + gmax_range_fx[i] = add(gmax_range_fx[i], temp_fx); + move16(); + } + } + + grp_bound_fx[0] = 0; + move16(); + FOR(i=1; i 0x0L ) + { + L_Ravg_sub[i] = L_add(L_Ravg_sub[i], L_temp_band_energy[j]); + move32(); + } + } + } + + L_temp_band_energydiff[0] = L_temp_band_energy[0]; + move32(); + FOR ( j = 1; j < harmonic_band_fx; j++ ) + { + L_temp_band_energydiff[j]= L_abs(L_sub(L_temp_band_energy[j], L_temp_band_energy[j-1])); + move32(); + } + + G1_BE_DIFF_POS_fx = 0; + move16(); + L_G1_BE_DIFF_VAL = L_deposit_l(0); + + FOR(j=1; j< harmonic_band_fx; j++) + { + IF( GT_32(L_temp_band_energydiff[j], L_G1_BE_DIFF_VAL)) + { + G1_BE_DIFF_POS_fx = j; + move16(); + L_G1_BE_DIFF_VAL = L_temp_band_energydiff[j]; + } + } + + test(); + test(); + IF( LT_16(G1_BE_DIFF_POS_fx, gmax_range_fx[0] )&&G1_BE_DIFF_POS_fx>0) + { + final_gr_fact_pos_fx = 0; + move16(); + } + ELSE IF ( GE_16(G1_BE_DIFF_POS_fx, gmax_range_fx[0])&<_16(G1_BE_DIFF_POS_fx,gmax_range_fx[1])) + { + final_gr_fact_pos_fx = 1; + move16(); + } + ELSE + { + final_gr_fact_pos_fx = 2; + move16(); + } + + test(); + IF( final_gr_fact_pos_fx == 0 || EQ_16(final_gr_fact_pos_fx, 1)) + { + IF( EQ_32(L_core_brate, HQ_16k40 )) + { + bits_fact_fx = BITS_FACT_1p10; + move16(); /* 1.10f; */ /* G1 */ + bits_fact1_fx = BITS_FACT_0p92; + move16(); /* 0.92f; */ /* G3 */ + } + ELSE + { + bits_fact_fx = BITS_FACT_1p05; + move16(); /* 1.05f; */ /* G1 */ + bits_fact1_fx = BITS_FACT_0p97; + move16(); /* 0.97f; */ /* G3 */ + } + } + ELSE + { + IF( EQ_32(L_core_brate, HQ_16k40)) + { + bits_fact_fx = BITS_FACT_0p97; + move16(); /* 0.97f; */ /* G1 */ + bits_fact1_fx = BITS_FACT_1p00; + move16(); /* 1.00f; */ /* G3 */ + } + ELSE + { + bits_fact_fx = BITS_FACT_0p92; + move16(); /* 0.92f; */ /* G1 */ + bits_fact1_fx = BITS_FACT_1p00; + move16(); /* 1.00f; */ /* G3 */ + } + } + + j = sub(N_fx, harmonic_band_fx); + FOR ( i = 0; i < j; i++ ) + { + y_index_fx[i] = extract_h(L_shl(L_temp_band_energy[harmonic_band_fx+i], sub(16, SWB_BWE_LR_Qbe))); + index_fx[i] = add(harmonic_band_fx, i); + move16(); + } + + reordvct_fx(y_index_fx, sub(N_fx, harmonic_band_fx), index_fx); + + /* Log2 */ + L_temp = L_deposit_l(band_width_fx[index_fx[0]]); + exp = norm_l(L_temp); + frac = Log2_norm_lc(L_shl(L_temp, exp)); + exp = sub(30, exp); + L_temp = L_Comp(exp, frac); + /* ceil */ + if( L_and(0x0000ffff, L_temp) > 0 ) + { + L_temp = L_add(L_temp, 0x00010000); + } + esthf_bits_fx = extract_h(L_temp); + + L_grp_thr[0] = L_THR1; + move32(); + L_grp_thr[1] = L_THR2; + move32(); + L_grp_thr[2] = L_THR3; + move32(); + L_grp_thr[3] = L_shl(L_deposit_l(esthf_bits_fx), SWB_BWE_LR_QRk); + move16(); + + L_norm_sum = L_deposit_l(1); + FOR(i=0; i<3; i++) + { + L_norm_sum = L_add( L_norm_sum, L_Ravg_sub[i]); + } + + /*reserve bits for HF coding */ + L_temp = L_add(L_norm_sum, L_Ravg_sub[GRP_SB-1]); + exp_normn = norm_l(L_temp); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_s(N_fx); + + div_fx = div_l(L_shl(L_temp, exp_normn), shl(N_fx, exp_normd)); /* (Qbe+exp_normn)-(0+exp_normd)-1) */ + L_norm_sum_avg = L_shr(L_deposit_h(div_fx), add(sub(exp_normn, exp_normd), 15)); /* -> Qbe */ + + exp_norm = norm_l(L_norm_sum); + norm_sum_fx = extract_h( L_shl(L_norm_sum, exp_norm) ); /* SWB_BWE_LR_Qbe+exp_norm-16 */ + Qns = sub(add(SWB_BWE_LR_Qbe, exp_norm), 16); + + Inv_norm_sum_fx = div_s( 0x4000 /* Q15 */ , norm_sum_fx ); + QIns = sub(31, exp_norm); /* 14 - (14+exp_norm-16) + 15 */ + + grp_bit_avg_fx = div_s_ss(B_fx, GRP_SB); /* Q0 */ + + exp_normd = norm_s(p2a_bands_fx); + Inv_p2a_bands_fx = div_s(0x3fff, shl(p2a_bands_fx, exp_normd)); /* 14-exp_normd+15 */ + QIpb = sub(29, exp_normd); + + L_temp = L_shl(Mult_32_16(L_Ravg_sub[GRP_SB-1], Inv_p2a_bands_fx), sub(SWB_BWE_LR_Qbe, sub(QIpb,1))); + L_norm_diff = L_sub(L_temp, L_norm_sum_avg); /* Qbe */ + + L_temp = Mult_32_16(L_Ravg_sub[GRP_SB-1], sub(GRP_SB, 1)); /* Qbe+0+1 */ + L_temp = Mult_32_16(L_temp, Inv_norm_sum_fx); /* Qbe+1+QIpb+1 */ + lf_hf_ge_r_fx = round_fx(L_shl(L_temp, sub(15+16, sub(add(SWB_BWE_LR_Qbe, QIns),30)))); + + exp_normn = norm_s(norm_sum_fx); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_s(harmonic_band_fx); + + div_fx = div_s(shl(norm_sum_fx, exp_normn), shl(harmonic_band_fx, exp_normd)); + L_avg_enhf_en_diff = L_sub(L_temp_band_energy[index_fx[0]], L_shl(L_deposit_h(div_fx), sub(sub(SWB_BWE_LR_Qbe, (add(Qns,sub(exp_normn,exp_normd)))),31))); /* Qbe - (Qns+exp_normn-(exp_normd)+15) -16 */ + + test(); + IF(GT_16(lf_hf_ge_r_fx, 26214) && GT_32(L_avg_enhf_en_diff, (Word32)(8 << SWB_BWE_LR_Qbe))) /* 0.8=26214.4(Q15) 8.0f=131072(Qbe) */ + { + bits_allocweigh_fx = 6554; + move16(); /* 0.2 6553.6(Q15) */ + if(L_norm_diff < 0x0L) + { + bits_allocweigh_fx = 13107; + move16(); /* 0.4 13107.2(Q15) */ + } + + /*allocate bits*/ + /*Bits_grp[GRP_SB-1] = (short)min((grp_bit_avg/p2a_bands + bits_allocweigh*norm_diff),10);*/ + L_temp = L_mult(grp_bit_avg_fx, Inv_p2a_bands_fx); /* Q0+QIpb+1 */ + L_temp2 = Mult_32_16(L_norm_diff, bits_allocweigh_fx); /* Qbe+Q15-15 */ + + L_temp = L_shr(L_temp, add(QIpb, 1)); + L_temp = L_add(L_shl(L_temp,SWB_BWE_LR_Qbe), L_temp2); + + Bits_grp_fx[GRP_SB-1] = extract_h(L_shl(L_temp, sub(16, SWB_BWE_LR_Qbe))); + Bits_grp_fx[GRP_SB-1] = s_min(Bits_grp_fx[GRP_SB-1], 10); + move16(); + + if( LT_16(Bits_grp_fx[GRP_SB-1], esthf_bits_fx)) + { + Bits_grp_fx[GRP_SB-1] = 0; + move16(); + } + B_fx = sub(B_fx, Bits_grp_fx[GRP_SB-1]); + } + + exp_shift = sub(add(SWB_BWE_LR_Qbe, QIns), 47); /* (SWB_BWE_LR_Qbe+14+1+QIns-15-16) */ + exp_norm = norm_s(B_fx); + B_norm_fx = shl(B_fx, exp_norm); + exp_shift = add(exp_shift, exp_norm); + + IF( EQ_16(final_gr_fact_pos_fx, 1)) + { + L_temp = Mult_32_16(L_Ravg_sub[1], extract_h(L_mult(bits_fact_fx, B_norm_fx))); + L_temp = Mult_32_16(L_temp, Inv_norm_sum_fx); + Bits_grp_fx[1] = extract_h(L_shr(L_temp, exp_shift)); + + L_temp = Mult_32_16(L_Ravg_sub[2], extract_h(L_mult(bits_fact1_fx, B_norm_fx))); + L_temp = Mult_32_16(L_temp, Inv_norm_sum_fx); + Bits_grp_fx[2] = extract_h(L_shr(L_temp, exp_shift)); + + Bits_grp_fx[0] = sub(sub(B_fx, Bits_grp_fx[1]), Bits_grp_fx[2]); + move16(); + } + ELSE + { + L_temp = Mult_32_16(L_Ravg_sub[0], extract_h(L_mult(bits_fact_fx, B_norm_fx))); + L_temp = Mult_32_16(L_temp, Inv_norm_sum_fx); + Bits_grp_fx[0] = extract_h(L_shr(L_temp, exp_shift)); + + L_temp = Mult_32_16(L_Ravg_sub[2], extract_h(L_mult(bits_fact1_fx, B_norm_fx))); + L_temp = Mult_32_16(L_temp, Inv_norm_sum_fx); + Bits_grp_fx[2] = extract_h(L_shr(L_temp, exp_shift)); + + Bits_grp_fx[1] = sub(sub(B_fx, Bits_grp_fx[0]), Bits_grp_fx[2]); + move16(); + } + + IF( LT_16(Bits_grp_fx[2], THR2 )) + { + Bits_grp_fx[1] = add(Bits_grp_fx[1], Bits_grp_fx[2]); + move16(); + Bits_grp_fx[2] = 0; + move16(); + } + + FOR(i=0; i 0) + { + Bits2indvsb_fx( L_temp_band_energy, grp_bound_fx[i], grp_bound_fx[i+1] , Bits_grp_fx[i], L_grp_thr[i], L_Rsubband, p2a_flags_fx); + } + ELSE + { + set32_fx(L_Rsubband+grp_bound_fx[i], 0x0L, sub(grp_bound_fx[i+1], grp_bound_fx[i])); + IF( EQ_16(i, GRP_SB-1)) + { + set16_fx(p2a_flags_fx+grp_bound_fx[i], 0, sub(grp_bound_fx[i+1], grp_bound_fx[i])); + } + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * hq2_bit_alloc() + * + * HQ2 bit-allocation + *--------------------------------------------------------------------------*/ + +Word32 hq2_bit_alloc_fx ( + const Word32 L_band_energy[], /* i : band energy of each subband */ + const Word16 bands, /* i : total number of subbands in a frame */ + Word32 L_Rk[], /* i/o: Bit allocation/Adjusted bit alloc. */ + Word16 *bit_budget_fx, /* i/o: bit bugdet */ + Word16 *p2a_flags, /* i : HF tonal indicator */ + const Word16 weight_fx, /* i : weight */ + const Word16 band_width[], /* i : Sub band bandwidth */ + const Word16 num_bits, /* i : available bits */ + const Word16 hqswb_clas, /* i : HQ2 class information */ + const Word16 bwidth, /* i : input bandwidth */ + const Word16 is_transient /* i : indicator HQ_TRANSIENT or not */ +) +{ + Word16 j, k; + Word16 tmp; + Word16 bit_budget_norm_fx; + + Word32 L_Rcalc, L_Ravg, L_Rcalc1; + + Word16 exp_normn, exp_normd; + + Word16 Rcnt_fx; + + Word16 div_fx; + Word16 Qdiv; + + Word32 L_tmp; + Word16 tmp_fx; + + Word32 L_maxxy; + Word16 maxdex_fx; + Word32 L_dummy; + + Word16 bit_budget_temp_fx; + + Word16 negflag; + + Word32 L_THR1, L_THR2, L_THR3; + + L_THR1 = L_shl(L_deposit_l(THR1), SWB_BWE_LR_QRk); + L_THR2 = L_shl(L_deposit_l(THR2), SWB_BWE_LR_QRk); + L_THR3 = L_shl(L_deposit_l(THR3), SWB_BWE_LR_QRk); + + /* Init Rk to non-zero values for bands to be allocated bits */ + IF( LE_16(num_bits, HQ_16k40_BIT)) + { + set32_fx( L_Rk, (Word32)(C1_QRk), bands); /* 1< 0 ) + { + L_Ravg = L_add(L_Ravg, L_shl(L_band_energy[k], sub(SWB_BWE_LR_QRk, SWB_BWE_LR_Qbe))); /* SWB_BWE_LR_QRk-SWB_BWE_LR_Qbe */ + Rcnt_fx = add(Rcnt_fx, 1); + } + } + /* Ravg Qband_energy */ + + /*L_Ravg /= Rcnt; */ + exp_normd = norm_l(L_Ravg); + exp_normd = sub(exp_normd, 1); + exp_normn = norm_s(Rcnt_fx); + + tmp = shl(Rcnt_fx, exp_normn); + tmp = s_max(tmp,1); + IF ( L_Ravg > 0 ) + { + div_fx = div_l(L_shl(L_Ravg, exp_normd), tmp); /* Qdiv = 14+exp_normd-(exp_normn)-1 */ + } + ELSE + { + div_fx = div_l(L_shl(L_abs(L_Ravg), exp_normd), tmp); /* Qdiv = 14+exp_normd-(exp_normn)-1 */ + div_fx = negate(div_fx); + } + + Qdiv = sub(sub(add(SWB_BWE_LR_QRk, exp_normd), exp_normn), 1); + + L_Ravg = L_shr(L_deposit_l(div_fx), sub(Qdiv, SWB_BWE_LR_QRk)); + + exp_normd = norm_s(*bit_budget_fx); + exp_normd = sub(exp_normd, 1); + bit_budget_norm_fx = shl(*bit_budget_fx, exp_normd); + div_fx = 0; + move16(); + + test(); + IF( bit_budget_norm_fx > 0 && LT_16(bit_budget_norm_fx, tmp)) + { + div_fx = div_s(bit_budget_norm_fx, tmp); + } + Qdiv = add(sub(exp_normd, exp_normn), 15); + FOR (k = 0; k < bands; k++) + { + IF ( L_Rk[k] > 0) + { + /*Rk[k] = ((float) *bit_budget / Rcnt + weight * (band_energy[k] - Ravg)); */ + + L_tmp = Mult_32_16(L_sub(L_shl(L_band_energy[k], sub(SWB_BWE_LR_QRk, SWB_BWE_LR_Qbe)), L_Ravg), weight_fx); /* SWB_BWE_LR_QRk + Q13 - 15 */ + L_tmp = L_shl(L_tmp, 2); /* -> SWB_BWE_LR_QRk */ + + L_Rk[k] = L_add(L_shr(L_deposit_l(div_fx), sub(Qdiv, SWB_BWE_LR_QRk)) , L_tmp); + move32(); + } + } + + negflag = 0; + move16(); + L_Rcalc = L_deposit_l(0); + FOR (k = 0; k < bands; k++) + { + IF ( LT_32(L_Rk[k], MIN_BITS_FIX)) + { + L_Rk[k] = L_deposit_l(0); + negflag = 1; + move16(); + } + L_Rcalc = L_add( L_Rcalc , L_Rk[k]); /*SWB_BWE_LR_QRk */ + } + + /* prune noiselike bands with low allocation */ + test(); + IF ( LE_16(num_bits, HQ_16k40_BIT)&&negflag==0) + { + L_maxxy = L_deposit_l(0); + maxdex_fx = -1; + move16(); + L_Rcalc = L_deposit_l(0); + + /* find worst under-allocation */ + FOR (k = sub(bands, 1); k >= 0; k--) + { + tmp_fx = s_min( band_width[k], s_max(12, shr( band_width[k], 2))); + L_dummy = L_sub(L_shl(L_deposit_l(tmp_fx), SWB_BWE_LR_QRk), L_Rk[k]) ; /*SWB_BWE_LR_QRk */ + test(); + test(); + IF ( p2a_flags[k] == 0 && GT_32(L_dummy, L_maxxy)&&L_Rk[k]>0) + { + maxdex_fx = k; + move16(); + L_maxxy = L_dummy; /*SWB_BWE_LR_QRk */ + move32(); + } + } + + /* prune worst allocation and recalculate total allocation */ + if ( GT_16(maxdex_fx, -1)) + { + L_Rk[maxdex_fx] = L_deposit_l(0); + } + FOR (k = 0; k < bands; k++) + { + L_Rcalc = L_add(L_Rcalc, L_Rk[k]); /*SWB_BWE_LR_QRk */ + } + } + test(); + test(); + IF ( EQ_32(L_Rcalc, L_Rcalc1)&&EQ_16(bwidth,SWB)) + { + /* Reallocate bits to individual subbands for HQ_NORMAL mode */ + /* if bits allocated to subbands areless than predefined threshold */ + test(); + IF( EQ_16(hqswb_clas, HQ_NORMAL)&<_16(num_bits,HQ_16k40_BIT)) + { + L_dummy = L_deposit_l(0); + FOR( k = 0; k < bands; k++ ) + { + test(); + test(); + test(); + test(); + test(); + IF( LT_16(k, 11)&<_32(L_Rk[k],L_THR1)) + { + L_Rk[k] = L_deposit_l(0); + } + ELSE IF( GE_16(k, 11)&<_16(k,16)&<_32(L_Rk[k],L_THR2)) + { + L_Rk[k] = L_deposit_l(0); + } + ELSE if( GE_16(k, 16)&<_16(k,bands)&<_32(L_Rk[k],L_THR3)) + { + L_Rk[k] = L_deposit_l(0); + } + + L_dummy = L_add(L_dummy, L_Rk[k]); + } + + IF( EQ_32(L_dummy, L_Rcalc )) + { + test(); + IF( EQ_16(hqswb_clas, HQ_NORMAL)&<_16(num_bits,HQ_16k40_BIT)) + { + bit_budget_temp_fx = *bit_budget_fx; + move16(); + FOR( k=0; kBER_detect */ + } + ELSE IF( EQ_16(bit_budget_temp_fx, *bit_budget_fx )) + { + BREAK; + } + } + ELSE + { + BREAK; + } + } + } + ELSE + { + BREAK; + } + } + ELSE IF ( EQ_32(L_Rcalc, L_Rcalc1 )&&NE_16(bwidth,SWB)) + { + BREAK; + } + + L_Rcalc1 = L_Rcalc; + move32(); + + } + + return L_Rcalc; +} + diff --git a/lib_com/hq2_core_com_fx.c b/lib_com/hq2_core_com_fx.c new file mode 100644 index 0000000..8fd73d1 --- /dev/null +++ b/lib_com/hq2_core_com_fx.c @@ -0,0 +1,770 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "cnst_fx.h" /* Audio core constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" +#include "stl.h" +#include "basop_mpy.h" + +/*--------------------------------------------------------------------------* + * mdct_spectrum_denorm() + * + * + *--------------------------------------------------------------------------*/ + +void mdct_spectrum_denorm_fx( + const Word16 inp_vector[], /* i : Q0 : */ + Word32 L_y2[], /* i/o : Qs : decoded spectrum */ + const Word16 band_start[], /* i : Q0 : table of start freq for every subband */ + const Word16 band_end[], /* i : Q0 : table of end freq for every subband */ + const Word16 band_width[], /* i : Q0 : table of bandwidth for every subband */ + const Word32 L_band_energy[], /* i : Qbe : band energy */ + const Word16 npulses[], /* i : Q0 : number of coded spectrum */ + const Word16 bands, /* i : Q0 : number of subbands */ + const Word16 ld_slope_fx, /* i : Q15 : */ + const Word16 pd_thresh_fx /* i : Q15 : */ +) +{ + Word16 i, k; + Word32 L_Eyy; + Word32 L_tmp, L_temp; + Word16 temp_fx, temp_lo_fx, temp_hi_fx; + Word32 L_inp_tmp[L_FRAME48k]; + Word16 exp_norm; + Word16 exp_safe; + Word16 exp_normn, exp_normd; + + Word16 pd_fx; + Word16 Qpd; + + Word16 div_pd_fx; + Word16 Qdivpd; + Word32 L_div_pd; + + Word16 frac, exp; + + Word16 gain_tweak_fx; + Word16 Qtweak; + + Word16 exp_shift; + + Word16 QEyy; + Word16 pow_fx; + Word16 Qpow; + Word16 Qdiv; + Word16 Qgamma; + Word16 gamma_fx; + + Word16 cond_fx; + + exp_safe = 4; /* safe bit for overflow */ + + FOR (k = 0; k < bands; k++) + { + L_tmp = L_deposit_l(0); + FOR (i = band_start[k]; i <= band_end[k]; i++) + { + L_inp_tmp[i] = L_mult(inp_vector[i], inp_vector[i]); + move32(); /* Q0+Q0+1 */ + L_tmp = L_or(L_tmp, L_inp_tmp[i]); + } + exp_norm = norm_l(L_tmp); + exp_norm = sub(exp_norm, exp_safe); + + L_Eyy = L_deposit_l(0); + FOR (i = band_start[k]; i <= band_end[k]; i++) + { + /*Eyy += (float) inp_vector[i] * inp_vector[i]; */ + L_Eyy = L_add(L_Eyy, L_shl(L_inp_tmp[i], exp_norm)); /* Q1+exp_norm */ + } + QEyy = add(1, exp_norm); + + IF ( L_Eyy > 0x0L ) + { + /* Set gamma to be pulse gain which results in perfect quantized subband energy */ + /*gamma = (float) sqrt (pow (2.0f, band_energy[k]) / Eyy); */ + + /* Pow part (pow(2.0f, band_energy) ) */ + L_temp = L_shr(L_band_energy[k], sub(SWB_BWE_LR_Qbe, 16)); + temp_lo_fx = L_Extract_lc(L_temp, &temp_hi_fx); + Qpow = sub(14, temp_hi_fx); + pow_fx = extract_l(Pow2(14, temp_lo_fx)); /* Qpow */ + + /* Div part ( pow (2.0f, band_energy[i])/Eyy ) */ + exp_normn = norm_s(pow_fx); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_l(L_Eyy); + temp_fx = div_s( shl( pow_fx, exp_normn), extract_h(L_shl(L_Eyy, exp_normd))); + Qdiv = add(sub(add(Qpow, exp_normn) , add(QEyy, exp_normd)), 31); + + exp_norm = norm_s(temp_fx); + temp_fx = shl(temp_fx, exp_norm); + Qdiv = add(Qdiv, exp_norm); + + /* Sqrt part sqrt(pow (2.0f, band_energy[i])/Eyy) */ + Qgamma = add(Qdiv, 16); + IF ( s_and(Qdiv, 1) == 0 ) /* Qdiv % 2 == 0 */ + { + L_temp = Sqrt_l(L_shr(L_deposit_h(temp_fx),1), &exp_norm); + L_temp = L_shr(L_temp, exp_norm); + Qgamma = sub(shr(Qgamma, 1), 1); + gamma_fx = round_fx(L_temp); + } + ELSE + { + L_temp = Sqrt_l(L_deposit_h(temp_fx), &exp_norm); + L_temp = L_shr(L_temp, exp_norm); + Qgamma = shr(Qgamma, 1); + gamma_fx = round_fx(L_temp); + } + + /* Adjust gamma based on pulse density (0 bit MSE gain estimator) */ + /*pd = (float) npulses[k] / band_width[k]; */ + exp_normn = norm_s(npulses[k]); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_s(band_width[k]); + pd_fx = div_s(shl(npulses[k],exp_normn), shl(band_width[k], exp_normd)); + Qpd = add(sub(exp_normn, exp_normd), 15); + + cond_fx = sub(shl(pd_fx, sub(15, Qpd)), pd_thresh_fx/*Q15*/); + Overflow = 0; + move16(); /* allow overflow happen. */ + IF ( cond_fx < 0 ) + { + /*gain_tweak = (float) pow (2.0f, (ld_slope * log2_f (pd / pd_thresh))); */ + /* Div part */ + exp_normn = norm_s(pd_fx); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_s(pd_thresh_fx); + div_pd_fx = div_s(shl(pd_fx, exp_normn), shl(pd_thresh_fx, exp_normd)); /* Qpd+exp_normn - (15 + exp_normd) + 15 */ + Qdivpd = add(sub(add(Qpd, exp_normn), add(15, exp_normd)), 15); + + /* Log2 part */ + exp_norm = norm_s(div_pd_fx); + L_div_pd = L_deposit_h(shl(div_pd_fx, exp_norm)); + Qdivpd = add(add(Qdivpd, exp_norm), 16); + + frac = Log2_norm_lc(L_div_pd); + exp = sub(30, Qdivpd); + L_tmp = L_Comp(exp, frac); /* Q16 */ + + /* Mult part */ + L_tmp = Mpy_32_16_1(L_tmp, ld_slope_fx); + + /* Pow part */ + temp_lo_fx = L_Extract_lc(L_tmp, &temp_hi_fx); + Qtweak = sub(14, temp_hi_fx); + gain_tweak_fx = extract_l(Pow2(14, temp_lo_fx)); + + /*gamma *= gain_tweak; */ + L_tmp = L_mult(gamma_fx, gain_tweak_fx); /* Qgamma+Qtweak+1 */ + exp_norm = norm_l(L_tmp); + gamma_fx = round_fx(L_shl(L_tmp, exp_norm)); + Qgamma = sub(add(add(Qgamma, Qtweak), exp_norm), 15);/*Qgamma+Qtweak+1+exp_norm-16; */ + } + + exp_shift = sub(SWB_BWE_LR_Qs-1, Qgamma); + FOR (i = band_start[k]; i <= band_end[k]; i++) + { + /*y2[i] = gamma * inp_vector[i]; */ + L_tmp = L_mult(gamma_fx, (Word16)inp_vector[i]); /* Qgamma+0+1=Qgamma+1 */ + L_y2[i] = L_shl(L_tmp, exp_shift); + move32(); + } + } + } + + return; +} +/*==========================================================================*/ +/* FUNCTION : void hq2_core_configure_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* Word16 *qint o: Q13 */ +/* Word16 *eref o: Q10 */ +/* Word16 *bit_alloc_weight o: Q13 */ +/* Word16 *p2a_th o: Q11 */ +/* Word16 *pd_thresh o: Q15 */ +/* Word16 *ld_slope o: Q15 */ +/* Word16 *ni_coef o: Q14 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*==========================================================================*/ + +void hq2_core_configure_fx ( + const Word16 frame_length, + const Word16 num_bits, + const Word16 is_transient, + Word16 *bands, + Word16 *length, + Word16 band_width[], + Word16 band_start[], + Word16 band_end[], + Word32 *L_qint, + Word16 *eref, + Word16 *bit_alloc_weight, + Word16 *gqlevs, + Word16 *Ngq, + Word16 *p2a_bands, + Word16 *p2a_th, + Word16 *pd_thresh, + Word16 *ld_slope, + Word16 *ni_coef, + Word32 L_bwe_br +) +{ + const Xcore_Config_fx *xcore_config_fx; + + Word16 i, k; + Word16 bands_sh; + + xcore_config_fx = &xcore_config_32kHz_013200bps_long_fx; /* default set for VC Warning */ + + IF ( EQ_16(frame_length, L_FRAME8k)) + { + IF( is_transient ) + { + IF ( LE_16(num_bits, ACELP_7k20 / 50)) + { + xcore_config_fx = &xcore_config_8kHz_007200bps_short_fx; + } + ELSE IF ( LE_16(num_bits, ACELP_8k00 / 50)) + { + xcore_config_fx = &xcore_config_8kHz_008000bps_short_fx; + } + ELSE IF ( LE_16(num_bits, ACELP_13k20 / 50)) + { + xcore_config_fx = &xcore_config_8kHz_013200bps_short_fx; + } + ELSE + { + xcore_config_fx = &xcore_config_8kHz_016400bps_short_fx; + } + } + ELSE + { + IF ( LE_16(num_bits, ACELP_7k20 / 50)) + { + xcore_config_fx = &xcore_config_8kHz_007200bps_long_fx; + } + ELSE IF ( LE_16(num_bits, ACELP_8k00 / 50)) + { + xcore_config_fx = &xcore_config_8kHz_008000bps_long_fx; + } + ELSE IF ( LE_16(num_bits, ACELP_13k20 / 50)) + { + xcore_config_fx = &xcore_config_8kHz_013200bps_long_fx; + } + ELSE + { + xcore_config_fx = &xcore_config_8kHz_016400bps_long_fx; + } + } + } + ELSE IF ( EQ_16(frame_length, L_FRAME16k)) + { + IF (is_transient) + { + IF ( LE_16(num_bits, ACELP_13k20 / 50)) + { + xcore_config_fx = &xcore_config_16kHz_013200bps_short_fx; + move16(); + } + ELSE if ( LE_16(num_bits, ACELP_16k40 / 50)) + { + xcore_config_fx = &xcore_config_16kHz_016400bps_short_fx; + move16(); + } + } + ELSE + { + IF ( LE_16(num_bits, ACELP_13k20 / 50)) + { + xcore_config_fx = &xcore_config_16kHz_013200bps_long_fx; + move16(); + } + ELSE if ( LE_16(num_bits, ACELP_16k40 / 50)) + { + xcore_config_fx = &xcore_config_16kHz_016400bps_long_fx; + move16(); + } + } + } + ELSE /* (frame_length == SWB) */ + { + IF (is_transient) + { + IF ( LE_32(L_bwe_br, ACELP_13k20)) + { + xcore_config_fx = &xcore_config_32kHz_013200bps_short_fx; + move16(); + } + ELSE if ( LE_32(L_bwe_br, ACELP_16k40)) + { + xcore_config_fx = &xcore_config_32kHz_016400bps_short_fx; + move16(); + } + } + ELSE + { + IF ( LE_32(L_bwe_br, ACELP_13k20)) + { + xcore_config_fx = &xcore_config_32kHz_013200bps_long_fx; + move16(); + } + ELSE if ( LE_32(L_bwe_br, ACELP_16k40)) + { + xcore_config_fx = &xcore_config_32kHz_016400bps_long_fx; + move16(); + } + } + } + + *bands = xcore_config_fx->bands; + move16(); + *length = xcore_config_fx->bw; + move16(); + *L_qint = xcore_config_fx->L_qint; + move32(); + + *eref = xcore_config_fx->eref; + move16(); + *bit_alloc_weight = xcore_config_fx->bit_alloc_weight; + move16(); + *gqlevs = xcore_config_fx->gqlevs; + move16(); + *Ngq = xcore_config_fx->Ngq; + move16(); + + *p2a_bands = xcore_config_fx->p2a_bands; + move16(); + *p2a_th = xcore_config_fx->p2a_th; + move16(); + + *pd_thresh = xcore_config_fx->pd_thresh; + move16(); + *ld_slope = xcore_config_fx->ld_slope; + move16(); + *ni_coef = xcore_config_fx->ni_coef; + move16(); + + /*mvs2s_fx (xcore_config_fx->band_width, band_width, *bands); */ + Copy(xcore_config_fx->band_width, band_width, *bands); + + /* Expand band_width[] table for short windows */ + IF (is_transient) + { + bands_sh = *bands; + move16(); + *bands = shl(bands_sh,2); + *length = shl(*length, 2); + + FOR (i = 1; i <= 3; i++) + { + FOR (k = 0; k < bands_sh; k++) + { + band_width[i * bands_sh + k] = band_width[k]; + move16(); + } + } + } + + /* Formulate band_start and band_end tables from band_width table */ + band_start[0] = 0; + move16(); + band_end[0] = sub(band_width[0], 1); + move16(); + FOR (k = 1; k < *bands; k++) + { + band_start[k] = add( band_start[k - 1] , band_width[k - 1]); + move16(); + band_end[k] = sub(add( band_start[k] , band_width[k]) , 1); + move16(); + } + + + return; +} + +/*--------------------------------------------------------------------------* + * reverse_transient_frame_energies() + * + * + *--------------------------------------------------------------------------*/ + +void reverse_transient_frame_energies_fx( + Word32 L_band_energy[], /* o : Q14 : band energies */ + const Word16 bands /* i : Q0 : number of bands */ +) +{ + Word16 k, k1, k2; + Word32 L_be; + Word16 bands_2, bands_4, bands_8; + Word32 *p_be1, *p_be2; + + bands_2 = shr(bands, 1); + bands_4 = shr(bands, 2); + bands_8 = shr(bands, 3); + + k1 = bands_4; + k2 = sub(bands_2, 1); + p_be1 = &L_band_energy[k1]; + p_be2 = &L_band_energy[k2]; + FOR( k = 0; k < bands_8; k++ ) + { + L_be = *p_be1; + move32(); + *p_be1 = *p_be2; + move32(); + *p_be2 = L_be; + move32(); + p_be1++; + p_be2--; + } + + k1 = sub(bands, bands_4); /* 3*bands/4 */ + k2 = sub(bands, 1); + p_be1 = &L_band_energy[k1]; + p_be2 = &L_band_energy[k2]; + FOR( k = 0; k < bands_8; k++ ) + { + L_be = *p_be1; + move32(); + *p_be1 = *p_be2; + move32(); + *p_be2 = L_be; + move32(); + p_be1++; + p_be2--; + } + + return; +} + + +/*--------------------------------------------------------------------------* + * spt_shorten_domain_pre() + * + * Compute shorten subband if previous frame has spectral peak. + *--------------------------------------------------------------------------*/ + +void spt_shorten_domain_pre_fx( + const Word16 band_start[], /* i: Starting position of sub band */ + const Word16 band_end[], /* i: End position of sub band */ + const Word16 prev_SWB_peak_pos[], /* i: Spectral peak */ + const Word16 BANDS, /* i: total number of bands */ + const Word32 L_bwe_br, /* i: bitrate information */ + Word16 new_band_start[], /* o: Starting position of new shorten sub band */ + Word16 new_band_end[], /* o: End position of new shorten sub band */ + Word16 new_band_width[] /* o: new sub band bandwidth */ +) +{ + Word16 j; + Word16 k; + Word16 kpos; + + Word16 new_band_width_half; + const Word16 *p_bw_SPT_tbl; /* pointer of bw_SPT_tbl */ + + p_bw_SPT_tbl = bw_SPT_tbl[0]; + if( EQ_32(L_bwe_br, HQ_16k40)) + { + p_bw_SPT_tbl = bw_SPT_tbl[1]; + } + + kpos = 0; + j = 0; + move16(); + FOR(k=sub(BANDS,SPT_SHORTEN_SBNUM); k0) + { + exp = norm_s(band_width[k_sort[k]]); + tmp = shl(band_width[k_sort[k]],exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp = 29-exp) */ + L_tmp = Mult_32_16(Rk_sort[k],tmp);/* Q(16+29-exp-15 = 30-exp) */ + tmp = sub(18,exp); + ever_sort[k] = extract_l(L_shr(L_tmp,tmp));/*Q12 */ + IF(LT_16(ever_sort[k],ever_temp)) + { + ever_temp = ever_sort[k]; + move16(); + k2 = k; + move16(); + } + } + } + } + + k_num[0] = k2; + IF(EQ_16(k_sort[k2],sub(BANDS,1))) + { + FOR (k = 0; k < BANDS; k++) + { + if(EQ_16(k_sort[k],sub(k_sort[k2],1))) + { + k_num[1] = k; + move16(); + } + } + } + ELSE IF(k_sort[k2] == 0) + { + FOR (k = 0; k < BANDS; k++) + { + if(EQ_16(k_sort[k],add(k_sort[k2],1))) + { + k_num[1] = k; + move16(); + } + } + } + ELSE + { + IF ( LT_32( Rk[sub(k_sort[k2],1)],Rk[add(k_sort[k2],1)] )) + { + FOR (k = 0; k < BANDS; k++) + { + if(EQ_16(k_sort[k],sub(k_sort[k2],1))) + { + k_num[1] = k; + move16(); + } + } + } + ELSE + { + FOR (k = 0; k < BANDS; k++) + { + if(EQ_16(k_sort[k],add(k_sort[k2],1))) + { + k_num[1] = k; + move16(); + } + } + } + } +} diff --git a/lib_com/hq2_noise_inject_fx.c b/lib_com/hq2_noise_inject_fx.c new file mode 100644 index 0000000..b6de410 --- /dev/null +++ b/lib_com/hq2_noise_inject_fx.c @@ -0,0 +1,618 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "stl.h" +#include "prot_fx.h" +#include "math_op.h" +#include "math_32.h" +#include "oper_32b.h" +#include "move.h" +#include "count.h" + +/*--------------------------------------------------------------------------* + * hq2_noise_inject() + * + * HQ2 noise injection for WB signals + *--------------------------------------------------------------------------*/ +void hq2_noise_inject_fx( + Word32 L_y2[], + const Word16 band_start[], + const Word16 band_end[], + const Word16 band_width[], + Word32 Ep_fx[], + Word32 Rk_fx[], + const Word16 npulses[], + Word16 ni_seed, + const Word16 bands, + const Word16 ni_start_band, + const Word16 bw_low, + const Word16 bw_high, + const Word32 enerL_fx, + const Word32 enerH_fx, + Word32 last_ni_gain_fx[], + Word16 last_env_fx[], + Word16 *last_max_pos_pulse, + Word16 *p2a_flags, + Word16 p2a_bands, + const Word16 hqswb_clas, + const Word16 bwidth, + const Word32 bwe_br +) +{ + Word32 L_tmp,L_tmp2,L_tmp2x,L_tmp3,L_tmp1; + Word16 exp,exp2,Q_speech; + Word16 pd_fx[BANDS_MAX], rand_fx, peak_fx[BANDS_MAX], fac_fx; + + Word16 tmp,tmpx,tmp1,tmp2,tmp3,tmp4,Q_env_fx[BANDS_MAX],Q_Ep_fx[BANDS_MAX]; + + Word16 Qs=SWB_BWE_LR_Qs; + Word32 env_fx[BANDS_MAX]; + Word16 env_fx2[BANDS_MAX]; + Word32 ni_gain_fx[BANDS_MAX]; + Word16 y2hat_fx[L_FRAME48k]; + + Word16 i, j, k, ni_end_band, satur, count[BANDS_MAX], max_pos_pulse, pos; + Word16 sb = bands; + + satur = 0; + move16(); + + FOR(i = 0 ; i < bands; i++) + { + Ep_fx[i] = L_shl(Ep_fx[i], 6);/* Q-6 -> Q0 */ move32(); + } + + tmp = add(band_end[bands-1], 1); + FOR (k = 0; k < tmp; k++) + { + y2hat_fx[k] = (Word16)L_min(L_max(L_shr(L_y2[k],Qs),-32768),32767); + move16(); /* Extract_l or something else is missing here */ + } + + test(); + test(); + test(); + test(); + IF( (EQ_16(hqswb_clas,HQ_HARMONIC)||EQ_16(hqswb_clas,HQ_NORMAL))&&(EQ_32(bwe_br,HQ_16k40)||EQ_32(bwe_br,HQ_13k20))&&EQ_16(bwidth,SWB)) + { + sb = 17; + move16(); + if( EQ_32(bwe_br,HQ_16k40)) + { + sb = 19; + move16(); + } + } + + /* calculate the envelopes/ the decoded peak coeff./number of the decoded coeff./ the last subbands of the bit-allocated/saturation of bit-allocation */ + ni_end_band = bands; + max_pos_pulse = bands; + FOR (k = ni_start_band; k < ni_end_band; k++) + { + tmp = div_s(1, band_width[k]); /*Q15 */ + L_tmp = Mult_32_16(Rk_fx[k],tmp);/*Q(16+15-15=16) */ + pd_fx[k] = extract_h(L_shl(L_tmp,10)); /*16+10-16 =Q10 */ + + L_tmp2 = Ep_fx[k];/*Q0 */ + move32(); + L_tmp = L_max(1, L_tmp2); + exp = norm_l(L_tmp); + tmp = extract_h(L_shl(L_tmp, exp)); + + L_tmp3 = (Word32)band_width[k]; + move32(); + exp2 = norm_l(L_tmp3); + tmp2 = extract_h(L_shl(L_tmp3, exp2)); + + exp2 = sub(exp, exp2); /* Denormalize and substract */ + + tmp3 = sub(tmp2, tmp); + if (tmp3 > 0) + { + tmp2 = shr(tmp2, 1); + } + if (tmp3 > 0) + { + exp2 = add(exp2, 1); + } + tmp = div_s(tmp2, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp2); + env_fx[k] = L_tmp; + move32();/*Q(31-exp2) move32(); */ + Q_env_fx[k] = sub(31,exp2); + move16(); + tmp = sub(17,Q_env_fx[k]); + env_fx2[k] = extract_h(L_shl(env_fx[k],tmp));/*Q1 */ + peak_fx[k] = 0; + move16(); + count[k] = 0; + move16(); + + IF(npulses[k] != 0) + { + FOR (i = band_start[k]; i <= band_end[k]; i++) + { + L_tmp =L_mult0(y2hat_fx[i],y2hat_fx[i]); /*0 */ + Ep_fx[k] =L_sub(Ep_fx[k],L_tmp); + move32();/*0 */ + IF(GT_16(abs_s(y2hat_fx[i]),peak_fx[k])) + { + peak_fx[k] = abs_s(y2hat_fx[i]); + move16();/*0 */ + } + + IF(y2hat_fx[i] != 0) + { + count[k] = add(count[k],1); + move16(); + } + } + + max_pos_pulse = k; + L_tmp2 = Ep_fx[k]; + move32(); + L_tmp = L_max(1, L_tmp2); + exp = norm_l(L_tmp); + tmp = extract_h(L_shl(L_tmp, exp)); + + L_tmp3 = (Word32)band_width[k]; + exp2 = norm_l(L_tmp3); + tmp2 = extract_h(L_shl(L_tmp3, exp2)); + + exp2 = sub(exp, exp2); /* Denormalize and substract */ + + tmp3 = sub(tmp2, tmp); + if (tmp3 > 0) + { + tmp2 = shr(tmp2, 1); + } + if (tmp3 > 0) + { + exp2 = add(exp2, 1); + } + tmp = div_s(tmp2, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp2); + Ep_fx[k] = L_tmp; + move32();/*Q(31-exp2) */ + Q_Ep_fx[k] = sub(31,exp2); + move16(); + } + ELSE + { + Ep_fx[k] = env_fx[k]; + move32();/*Q(Q_env_fx[k]) */ + Q_Ep_fx[k] = Q_env_fx[k]; + move16();/*31-exp2 */ + } + } + + FOR(k = ni_start_band; k < ni_end_band; k++) + { + /* calculate the noise gain */ + satur =0; + move16(); + if(GE_16(pd_fx[k],819)) + { + satur =1; + move16(); + } + + test(); + IF (satur == 0 && Ep_fx[k] > 0) + { + IF(npulses[k] != 0) + { + IF( EQ_16(bwidth,SWB)) + { + IF(NE_16(hqswb_clas,HQ_TRANSIENT)) + { + IF(peak_fx[k]!=0) + { + Q_speech = norm_s(peak_fx[k]); + tmp = shl(peak_fx[k],Q_speech);/*Q(Q_speech) */ + tmp = div_s(16384,tmp);/*Q(15+14-Q_speech) */ + } + ELSE + { + tmp = 0x7fff; + move16(); + Q_speech = 0; + move16(); + } + L_tmp2x = Mult_32_16(Ep_fx[k],tmp);/* Q(Q_Ep_fx[k]+29-Q_speech-15 = Q_Ep_fx[k]-Q_speech+14) */ + tmp = sub(Q_Ep_fx[k],Q_speech); + tmpx = add(tmp,1); + tmp2 = extract_l(L_shr(L_tmp2x,s_min(tmpx, 31)));/*Q13 Ep[k]/peak[k] */ + + IF(EQ_16(hqswb_clas, HQ_HARMONIC)) + { + tmp = sub(1536,pd_fx[k]); /*Q10 */ + tmp3 = shl(tmp,4); /*Q14 */ + L_tmp = Mult_32_16(env_fx[k],tmp3);/*Q(Q_env_fx[k]+14-15 = Q_env_fx[k]-1) */ + L_tmp = Mult_32_16(L_tmp,6144);/*Q(Q_env_fx[k]-1+10-15 = Q_env_fx[k]-6) */ + + IF(peak_fx[k]!=0) + { + Q_speech = norm_s(peak_fx[k]); + tmp = shl(peak_fx[k],Q_speech);/*Q(Q_speech) */ + tmp = div_s(16384,tmp);/*Q(15+14-Q_speech) */ + } + ELSE + { + tmp = 0x7fff; + move16(); + Q_speech = 0; + move16(); + } + + L_tmp2 = Mult_32_16(Ep_fx[k],tmp);/* Q(Q_Ep_fx[k]+29-Q_speech-15=Q_Ep_fx[k]-Q_speech+14) */ + L_tmp3 = Mult_32_16(L_tmp,tmp);/* Q(Q_env_fx[k]-6+29-Q_speech-15=Q_env_fx[k]-Q_speech+8) */ + L_tmp = Mult_32_32(L_tmp2,L_tmp3); /*Q(Q_Ep_fx[k]-Q_speech+14+Q_env_fx[k]-Q_speech+8-31=Q_Ep_fx[k]+Q_env_fx[k]-2*Q_speech-9) */ + + tmp = add(Q_Ep_fx[k],Q_env_fx[k]); + tmp = sub(tmp,Q_speech); + tmp = sub(tmp,Q_speech); + tmp = sub(37,tmp); + tmp1= extract_h(L_shl(L_tmp,tmp));/*Q12 //6.0f*(1.5f - pd[k])*env[k]*Ep[k]/(peak[k]*peak[k]) */ + + fac_fx = tmp1; + move16();/*Q12 */ + if(GT_16(k,sb)) + { + fac_fx =mult(24576,tmp2);/*//Q(14+13-15=12) */ + } + } + ELSE + { + IF(LE_16(k,sb)) + { + tmp = sub(1536,pd_fx[k]); /*Q10 */ + tmp3 = shl(tmp,4); /*Q14 */ + L_tmp = Mult_32_16(L_tmp2x,tmp3);/*Q(Q_Ep_fx[k]-Q_speech+14+14-15 = Q_Ep_fx[k]-Q_speech+13) */ + L_tmp = Mult_32_16(L_tmp,20480);/*Q(Q_Ep_fx[k]-Q_speech+13+12-15 = Q_Ep_fx[k]-Q_speech+10) */ + fac_fx= extract_h(L_shl(L_tmp,sub(add(18,Q_speech),Q_Ep_fx[k])));/*Q_Ep_fx[k]-Q_speech+10 +18+Q_speech-Q_Ep_fx[k] -16 =12 */ + } + ELSE + { + fac_fx =shl(mult(32767,tmp2),1);/*//Q(13+13-15+1=12) */ + } + } + } + ELSE + { + fac_fx = 4505; + move16();/*Q12 */ + } + } + ELSE + { + tmp = sub(1536,pd_fx[k]); /*Q10 */ + tmp2 = s_min(1024,tmp); /*q10 */ + tmp2 = shl(tmp2,4); /*Q14 */ + L_tmp = Mult_32_16(env_fx[k],tmp2);/*Q(Q_env_fx[k]+14-15 = Q_env_fx[k]-1) */ + L_tmp = Mult_32_16(L_tmp,20480);/*Q(Q_env_fx[k]-1+10-15 = Q_env_fx[k]-6) */ + + IF(peak_fx[k]!=0) + { + Q_speech = norm_s(peak_fx[k]); + tmp = shl(peak_fx[k],Q_speech);/*Q(Q_speech) */ + tmp = div_s(16384,tmp);/*Q(15+14-Q_speech) */ + } + ELSE + { + tmp = 0x7fff; + move16(); + Q_speech = 0; + move16(); + } + + L_tmp2 = Mult_32_16(Ep_fx[k],tmp);/* Q(Q_Ep_fx[k]+29-Q_speech-15=Q_Ep_fx[k]-Q_speech+14) */ + L_tmp3 = Mult_32_16(L_tmp,tmp);/* Q(Q_env_fx[k]-6+29-Q_speech-15=Q_env_fx[k]-Q_speech+8) */ + L_tmp = Mult_32_32(L_tmp2,L_tmp3); /*Q(Q_Ep_fx[k]-Q_speech+14+Q_env_fx[k]-Q_speech+8-31=Q_Ep_fx[k]+Q_env_fx[k]-2*Q_speech-9) */ + + tmp = add(Q_Ep_fx[k],Q_env_fx[k]); + tmp = sub(tmp,Q_speech); + tmp = sub(tmp,Q_speech); + tmp = sub(37,tmp); + + fac_fx = extract_h(L_shl(L_tmp,tmp));/*Q12 */ + + test(); + IF(GT_16(k,1)&<_16(k,sub(ni_end_band,1))) + { + IF(env_fx2[k]!=0) + { + Q_speech = norm_s(env_fx2[k]); + tmp = shl(env_fx2[k],Q_speech);/*Q(Q_speech+1) */ + tmp = div_s(16384,tmp);/*Q(15+14-Q_speech-1=28-Q_speech) */ + Q_speech = sub(28,Q_speech); + } + ELSE + { + tmp =0x7fff; + move16(); + Q_speech = 0; + move16(); + } + tmp1 = mult(env_fx2[add(k,1)],16384);/*Q(1+15-15=1) Q1 */ + tmp2 = sub(env_fx2[k],tmp1); + tmp1 = mult(env_fx2[k],16384);/*Q(1+15-15=1) Q1 */ + tmp3 = sub(tmp1,env_fx2[sub(k,1)]); + tmp1 = mult(peak_fx[k],16384);/*Q(0+15-15=0) Q0 */ + tmp4 = sub(tmp1,shr(env_fx2[k],1)); + test(); + test(); + test(); + IF(count[add(k,1)] == 0 && tmp2 > 0 && tmp3 < 0) + { + L_tmp = L_mult(env_fx2[add(k,1)],tmp);/* Q(1+Q_speech+1 = Q_speech+2) */ + L_tmp = Mult_32_16(L_tmp,24576); /*Q(Q_speech+2+14-15=Q_speech+1) */ + fac_fx = extract_h(L_shl(L_tmp,sub(27,Q_speech)));/*Q12 */ + } + ELSE IF(count[sub(k,1)] == 0 && tmp4 > 0) + { + L_tmp = L_mult(env_fx2[sub(k,1)],tmp); /* Q(1+Q_speech+1 = Q_speech+2) */ + fac_fx = extract_h(L_shl(L_tmp,sub(26,Q_speech)));/*Q12 */ + } + } + + test(); + IF(GE_16(k,sub(ni_end_band,p2a_bands))&&EQ_16(bwidth,WB)) + { + L_tmp = Mult_32_16(enerH_fx, bw_low); + L_tmp2= Mult_32_16(enerL_fx, bw_high); + L_tmp = L_sub(L_tmp,L_tmp2); + tmp1 = mult(peak_fx[k],16384);/*Q(0+15-15=0) Q0 */ + tmp4 = sub(tmp1,shr(env_fx2[k],1)); + test(); + IF(L_tmp > 0 && tmp4 < 0) + { + IF(peak_fx[k]!=0) + { + Q_speech = norm_s(peak_fx[k]); + tmp = shl(peak_fx[k],Q_speech);/*Q(Q_speech) */ + tmp = div_s(16384,tmp);/*Q(15+14-Q_speech) */ + } + ELSE + { + tmp = 0x7fff; + move16(); + Q_speech = 0; + move16(); + } + L_tmp2 = Mult_32_16(Ep_fx[k],tmp);/* Q(Q_Ep_fx[k]+29-Q_speech-15 = Q_Ep_fx[k]-Q_speech+14) */ + tmp = sub(Q_Ep_fx[k],Q_speech); + tmp = add(tmp,1); + tmp = extract_l(L_shr(L_tmp2,tmp));/*Q13 */ + tmp = sub(16384,tmp);/*Q13 */ + fac_fx = extract_h(L_shl(L_mult(fac_fx,tmp),2));/*Q12*/ + } + + IF(p2a_flags[k] == 0) + { + L_tmp2 = Mult_32_16(Ep_fx[k],fac_fx);/*Q(Q_Ep_fx[k]+12-15 = Q_Ep_fx[k]-3) */ + Q_speech = norm_l(L_tmp2); + tmp = extract_h(L_shl(L_tmp2,Q_speech));/*Q(Q_Ep_fx[k]-3+Q_speech-16 = Q_Ep_fx[k]+Q_speech-19) */ + IF(tmp != 0) + { + tmp = div_s(16384,tmp);/*Q(15+14-Q_Ep_fx[k]-Q_speech+19 = 48-Q_Ep_fx[k]-Q_speech) */ + L_tmp2 = Mult_32_16(env_fx[k],tmp);/*Q(Q_env_fx[k]+48-Q_Ep_fx[k]-Q_speech-15 = Q_env_fx[k]-Q_Ep_fx[k]-Q_speech+33) */ + L_tmp2 = Mult_32_16(L_tmp2,20480);/*Q(Q_env_fx[k]-Q_Ep_fx[k]-Q_speech+33+14-15 = Q_env_fx[k]-Q_Ep_fx[k]-Q_speech+32) */ + tmp = sub(Q_env_fx[k],Q_Ep_fx[k]); + tmp = sub(tmp,Q_speech); + tmp = add(tmp,25); + L_tmp = L_shr(L_tmp2,tmp);/*Q7 */ + tmp = extract_l(L_min(L_tmp,192));/* */ + fac_fx = extract_h(L_shl(L_mult(fac_fx,tmp),8));/*Q12 */ + } + ELSE + { + tmp = 0x7fff;/*Q0 */ + L_tmp2 = Mult_32_16(env_fx[k],tmp);/*Q(Q_env_fx[k]+0-15 = Q_env_fx[k]-15) */ + L_tmp2 = Mult_32_16(L_tmp2,20480);/*Q(Q_env_fx[k]-15+14-15 = Q_env_fx[k]-16) */ + tmp = sub(Q_env_fx[k],23); + L_tmp = L_shr(L_tmp2,tmp);/*Q7 */ + tmp = extract_l((L_min(L_tmp,192)));/* */ + fac_fx = extract_h(L_shl(L_mult(fac_fx,tmp),8));/*Q12 */ + } + } + } + } + } + ELSE + { + fac_fx = 4505; + move16(); + test(); + if( EQ_16(hqswb_clas,HQ_HARMONIC)&&EQ_16(bwidth,SWB)) + { + fac_fx = 3277; + move16(); + } + } + + L_tmp = Mult_32_16(Ep_fx[k],fac_fx);/*Q(Q_Ep_fx[k]+12-15 = Q_Ep_fx[k]-3) */ + ni_gain_fx[k] = L_shr(L_tmp,sub(Q_Ep_fx[k],20)); + move32();/*Q17 */ + } + ELSE + { + ni_gain_fx[k] = L_deposit_l(0); + } + + /* smooth the noise gain between the current frame and the previous frame */ + pos = s_max(max_pos_pulse, *last_max_pos_pulse); + move16(); + if( EQ_16(bwidth,SWB)) + { + pos = sub(ni_end_band,1); + move16(); + } + + IF(LE_16(k,pos)) + { + test(); + IF(k > 0 && LT_16(sub(k,ni_end_band),-1)) + { + tmp1 = mult(last_env_fx[k],16384);/*Q(1+15-15=1) Q1 */ + tmp2 = sub(env_fx2[k],tmp1);/*>0 */ + tmp1 = mult(env_fx2[k],16384);/*Q(1+15-15=1) Q1 */ + tmp3 = sub(tmp1,last_env_fx[k]);/*<0 */ + L_tmp = L_add((Word32)env_fx2[k],(Word32)env_fx2[sub(k,1)]); + L_tmp = L_add(L_tmp,(Word32)env_fx2[add(k,1)]);/*Q1 */ + L_tmp1 = L_add((Word32)last_env_fx[k],(Word32)last_env_fx[sub(k,1)]); + L_tmp1 = L_add(L_tmp1,(Word32)last_env_fx[add(k,1)]);/*Q1 */ + L_tmp2 = Mult_32_16(L_tmp1,16384);/*Q(1+15-15) Q1 */ + L_tmp2 = L_sub(L_tmp,L_tmp2);/*>0 */ + L_tmp3 = Mult_32_16(L_tmp,16384);/*Q(1+15-15) Q1 */ + L_tmp3 = L_sub(L_tmp3,L_tmp1);/*<0 */ + test(); + test(); + test(); + IF( (tmp2 > 0 && tmp3 < 0) ||(L_tmp2 > 0 && L_tmp3 < 0)) + { + IF( GT_32(ni_gain_fx[k],last_ni_gain_fx[k])) + { + L_tmp = Mult_32_16(ni_gain_fx[k],6554);/*Q(17+15-15 = 17) */ + L_tmp1 = Mult_32_16(last_ni_gain_fx[k],26214);/*Q17 */ + ni_gain_fx[k] = L_add(L_tmp,L_tmp1); + move32(); + } + ELSE + { + L_tmp = Mult_32_16(ni_gain_fx[k],19661);/*Q(17+15-15 = 17) */ + L_tmp1 = Mult_32_16(last_ni_gain_fx[k],13107);/*Q17 */ + ni_gain_fx[k] = L_add(L_tmp,L_tmp1); + move32(); + } + } + } + ELSE IF (add(sub(k,ni_end_band),1) == 0) + { + tmp1 = mult(last_env_fx[k],16384);/*Q(1+15-15=1) Q1 */ + tmp2 = sub(env_fx2[k],tmp1);/*>0 */ + tmp1 = mult(env_fx2[k],16384);/*Q(1+15-15=1) Q1 */ + tmp3 = sub(tmp1,last_env_fx[k]);/*<0 */ + L_tmp = L_add((Word32)env_fx2[k],(Word32)env_fx2[sub(k,1)]);/*Q1 */ + L_tmp1 = L_add((Word32)last_env_fx[k],(Word32)last_env_fx[sub(k,1)]);/*Q1 */ + L_tmp2 = Mult_32_16(L_tmp1,16384);/*Q(1+15-15) Q1 */ + L_tmp2 = L_sub(L_tmp,L_tmp2);/*>0 */ + L_tmp3 = Mult_32_16(L_tmp,16384);/*Q(1+15-15) Q1 */ + L_tmp3 = L_sub(L_tmp3,L_tmp1);/*<0 */ + + test(); + test(); + test(); + IF( (tmp2 > 0 && tmp3 < 0) ||(L_tmp2 > 0 && L_tmp3 < 0)) + { + IF( GT_32(ni_gain_fx[k],last_ni_gain_fx[k])) + { + L_tmp = Mult_32_16(ni_gain_fx[k],6554);/*Q(17+15-15 = 17) */ + L_tmp1 = Mult_32_16(last_ni_gain_fx[k],26214);/*Q17 */ + ni_gain_fx[k] = L_add(L_tmp,L_tmp1); + move32(); + } + ELSE + { + L_tmp = Mult_32_16(ni_gain_fx[k],19661);/*Q(17+15-15 = 17) */ + L_tmp1 = Mult_32_16(last_ni_gain_fx[k],13107);/*Q17 */ + ni_gain_fx[k] = L_add(L_tmp,L_tmp1); + move32(); + } + } + } + } + + /* inject noise into the non-decoded coeffs */ + test(); + test(); + IF(add(sub(k,ni_end_band),p2a_bands) >=0 && p2a_flags[k] == 0 && NE_16(bwidth,SWB) ) + { + FOR (i = band_start[k]; i <= band_end[k]; i++) + { + IF (L_y2[i] != 0) + { + L_y2[i] = Mult_32_16(L_y2[i],26215); + move32();/*Q(12+15-15=12) */ + } + } + } + + test(); + test(); + test(); + IF(EQ_16(k,max_pos_pulse)&&add(sub(k,bands),p2a_bands)<0&&NE_16(satur,1)&&NE_16(bwidth,SWB)) + { + j = 0; + Q_speech = norm_l(ni_gain_fx[k]); + tmp = extract_h(L_shl(ni_gain_fx[k],Q_speech));/*Q(Q_speech+1) */ + IF(tmp != 0) + { + tmp = div_s(16384,tmp);/*Q(15+14-Q_speech-1 = 28-Q_speech) */ + L_tmp = Mult_32_16(Ep_fx[k],tmp); /*Q(Q_Ep_fx[k]+28-Q_speech-15 = Q_Ep_fx[k]+13-Q_speech) */ + tmp = sub(Q_Ep_fx[k],Q_speech); + tmp = sub(15,tmp); + tmp = extract_h(L_shl(L_tmp,tmp));/*Q12 */ + } + ELSE + { + tmp = 0x7fff;/*Q0 */ + L_tmp = Mult_32_16(Ep_fx[k],tmp); /*Q(Q_Ep_fx[k]+0-15 = Q_Ep_fx[k]-15) */ + tmp = sub(43,Q_Ep_fx[k]); + tmp = extract_h(L_shl(L_tmp,tmp));/*Q12 */ + } + fac_fx = s_max(tmp,4096);/*Q12 */ + + FOR (i = band_start[k]; i <= band_end[k]; i++) + { + IF (L_y2[i] == 0) + { + rand_fx = Random(&ni_seed); /*Q15 */ + IF(band_width[k] != 0) + { + Q_speech = norm_s(band_width[k]); + tmp = shl(band_width[k],Q_speech);/*Q(Q_speech) */ + tmp = div_s(16384,tmp);/*Q(15+14-Q_speech) */ + } + ELSE + { + tmp = 0x7fff; + Q_speech = 0; + } + tmp1 = sub(fac_fx,4096);/*Q12 */ + L_tmp = L_mult(tmp1,j);/*Q13 */ + L_tmp = Mult_32_16(L_tmp,tmp);/*Q(13+29-Q_speech-15 = 27-Q_speech) */ + tmp = extract_h(L_shl(L_tmp,add(1,Q_speech)));/*Q12 */ + tmp = sub(fac_fx,tmp);/*Q12 */ + L_tmp = Mult_32_16(ni_gain_fx[k],tmp);/*Q(17+12-15=14) */ + L_y2[i] = L_add(L_y2[i],L_shr(Mult_32_16(L_tmp,rand_fx),2)); + move32();/*Q12 */ + } + j=add(j,1); + } + } + ELSE + { + FOR (i = band_start[k]; i <= band_end[k]; i++) + { + IF (L_y2[i] == 0) + { + rand_fx = Random(&ni_seed); /*Q15 */ + L_tmp = Mult_32_16(ni_gain_fx[k],rand_fx);/*Q(17+15-15=17) */ + L_y2[i] = L_add(L_y2[i],L_shr(L_tmp,5)); + move32();/*Q12 */ + } + } + } + } + + Copy(env_fx2,last_env_fx,ni_end_band); + Copy32(ni_gain_fx,last_ni_gain_fx,ni_end_band); + *last_max_pos_pulse = max_pos_pulse; + move16(); + return; +} diff --git a/lib_com/hq_bit_allocation_fx.c b/lib_com/hq_bit_allocation_fx.c new file mode 100644 index 0000000..7053a49 --- /dev/null +++ b/lib_com/hq_bit_allocation_fx.c @@ -0,0 +1,217 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "stl.h" /* required for wmc_tool */ +#include "prot_fx.h" /* Function prototypes */ +#include "cnst_fx.h" /* Common constants */ + +/*--------------------------------------------------------------------------* + * hq_bit_allocation_fx() + * + * Assign bits for HQ fine structure coding with PVQ + *--------------------------------------------------------------------------*/ + +void hq_bit_allocation_fx( + const Word32 core_brate, /* i : Core bit-rate Q0 */ + const Word16 length, /* i : Frame length Q0 */ + const Word16 hqswb_clas, /* i : HQ class Q0 */ + Word16 *num_bits, /* i/o: Remaining bit budget Q0 */ + const Word16 *normqlg2, /* i : Quantized norms Q0 */ + const Word16 nb_sfm, /* i : Number sub bands to be encoded Q0 */ + const Word16 *sfmsize, /* i : Sub band bandwidths Q0 */ + Word16 *noise_level, /* o : HVQ noise level */ + Word16 *R, /* o : Bit allocation per sub band Q0 */ + Word16 *Rsubband, /* o : Fractional bit allocation Q3 */ + Word16 *sum, /* o : Sum of allocated shape bits Q0 */ + Word16 *core_sfm, /* o : Last coded band in core Q0 */ + const Word16 num_env_bands /* i : Number sub bands to be encoded for HQ_GEN Q0 */ +) +{ + Word16 i; + Word16 idx[NB_SFM]; + Word16 wnorm[NB_SFM]; + Word16 avrg_wnorm; + Word16 tmp, tmp2; + Word16 E_low; + Word16 E_hb_mean; + Word16 E_max; + Word16 i_max; + /* Temp */ + + Word16 sfm_limit = nb_sfm; + move16(); + + set16_fx( R, 0, NB_SFM); + FOR( i = 0; i < nb_sfm; i++ ) + { + idx[i] = i; + move16(); + } + test(); + test(); + test(); + if( NE_16(hqswb_clas, HQ_TRANSIENT)&&NE_16(hqswb_clas,HQ_HVQ)&&!(EQ_16(length,L_FRAME16k)&&EQ_32(core_brate,HQ_32k))) + { + /* 'nf_idx' 2-bits index written later */ + *num_bits = sub(*num_bits, 2); + } + + test(); + IF ( EQ_16(hqswb_clas, HQ_GEN_SWB)||EQ_16(hqswb_clas,HQ_GEN_FB)) + { + IF ( EQ_32(core_brate, HQ_32k)) + { + *num_bits = sub(*num_bits, HQ_GENERIC_SWB_NBITS2 ); + } + ELSE + { + *num_bits = sub(*num_bits, HQ_GENERIC_SWB_NBITS ); + } + + if ( EQ_16(hqswb_clas, HQ_GEN_FB)) + { + *num_bits = sub(*num_bits, HQ_GENERIC_FB_NBITS ); + } + } + + IF( ( EQ_16(length, L_FRAME48k))&&(NE_16(hqswb_clas,HQ_HARMONIC))&&(NE_16(hqswb_clas,HQ_HVQ))) + { + tmp = 0; + move16(); + if( EQ_16(hqswb_clas,HQ_TRANSIENT)) + { + tmp = 1; + move16(); + } + map_quant_weight_fx( normqlg2, wnorm, tmp ); + } + ELSE + { + Copy( normqlg2, wnorm, nb_sfm ); + } + + IF( EQ_16(hqswb_clas, HQ_HARMONIC)) + { + /* classification and limit bandwidth for bit allocation */ + sfm_limit = sub(sfm_limit, 2); + limit_band_noise_level_calc_fx( wnorm, &sfm_limit, core_brate, noise_level ); + + /* Detect important band in high frequency region */ + E_low = sum16_fx(wnorm, SFM_G1); + i_max = 0; + move16(); + E_max = MIN16B; + move16(); + E_hb_mean = 0; + move16(); + FOR( i = SFM_G1; i < nb_sfm; i++) + { + E_hb_mean = add(E_hb_mean, wnorm[i]); + IF( GT_16(wnorm[i], E_max)) + { + E_max = wnorm[i]; + move16(); + i_max = i; + move16(); + } + } + E_hb_mean = shr(E_hb_mean, 4); /* Truncated division by SFM_G1 */ + set16_fx( wnorm + sfm_limit, -20, sub(nb_sfm, sfm_limit) ); + IF (L_msu0(L_deposit_l(E_low), E_max, 15) <= 0) + { + IF (L_msu(L_deposit_h(E_hb_mean), E_max, 21955) <= 0) /* 21955 = 0.67 (Q15) */ + { + if (GE_16(i_max, sfm_limit)) + { + wnorm[i_max] = E_max; + move16(); + } + } + } + } + test(); + test(); + test(); + test(); + IF( EQ_16(hqswb_clas, HQ_HVQ)) + { + *sum = 0; + move16(); + } + ELSE IF ( EQ_16(hqswb_clas, HQ_GEN_SWB)||(EQ_16(hqswb_clas,HQ_TRANSIENT)&&EQ_16(length,L_FRAME32k)&&LE_32(core_brate,HQ_32k))) + { + *sum = BitAllocF_fx( wnorm, core_brate, *num_bits, nb_sfm, R, Rsubband, hqswb_clas, num_env_bands ); + } + ELSE IF( EQ_16(length, L_FRAME16k)&&EQ_32(core_brate,HQ_32k)) + { + IF( NE_16(hqswb_clas, HQ_TRANSIENT)) + { + avrg_wnorm = wnorm[10]; + move16(); + FOR( i=11; i<18; i++ ) + { + avrg_wnorm = add(avrg_wnorm, wnorm[i]); + } + + avrg_wnorm = shr(avrg_wnorm, 3); + FOR( i=0; i<4; i++ ) + { + if( LT_16(wnorm[i], avrg_wnorm)) + { + wnorm[i] = avrg_wnorm; + move16(); + } + } + + /* Estimate number of bits per band */ + *sum = BitAllocWB_fx( wnorm, *num_bits, nb_sfm, R, Rsubband ); + } + ELSE + { + reordvct_fx(wnorm, nb_sfm, idx); + bitalloc_fx( wnorm, idx, *num_bits, nb_sfm, QBIT_MAX2, R, sfmsize, hqswb_clas ); + bitallocsum_fx( R, nb_sfm, sum, Rsubband, *num_bits, length, sfmsize ); + } + } + ELSE + { + reordvct_fx(wnorm, nb_sfm, idx); + + /* enlarge the wnorm value so that more bits can be allocated to (sfm_limit/2 ~ sfm_limit) range */ + IF( EQ_16(hqswb_clas, HQ_HARMONIC)) + { + tmp = shr(sfm_limit,1); + tmp2 = sub(tmp,1); + FOR( i=tmp; i +#include "options.h" +#include "cnst_fx.h" /* Audio core constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required for wmc_tool */ + +/*--------------------------------------------------------------------------* + * hq_configure() + * + * Configuration routine for HQ mode + *--------------------------------------------------------------------------*/ + +void hq_configure_fx( + const Word16 length, /* i : Frame length Q0 */ + const Word16 hqswb_clas, /* i : HQ SWB class Q0 */ + const Word32 core_brate, /* i : Codec bitrate Q0 */ + Word16 *num_sfm, /* o : Total number of subbands Q0 */ + Word16 *nb_sfm, /* o : Total number of coded bands Q0 */ + Word16 *start_norm, /* o : First norm to be SDE encoded Q0 */ + Word16 *num_env_bands, /* o : Number coded envelope bands Q0 */ + Word16 *numnrmibits, /* o : Number of bits in fall-back norm encoding Q0 */ + Word16 *hq_generic_offset, /* o : Freq offset for HQ GENERIC Q0 */ + Word16 const **sfmsize, /* o : Subband bandwidths Q0 */ + Word16 const **sfm_start, /* o : Subband start coefficients Q0 */ + Word16 const **sfm_end /* o : Subband end coefficients Q0 */ +) +{ + *start_norm = 0; + move16(); + + IF ( EQ_16(length, L_FRAME48k)) + { + IF ( EQ_16(hqswb_clas, HQ_GEN_FB)) + { + *num_sfm = NB_SFM; + move16(); + *sfmsize = band_len_HQ; + move16(); + *sfm_start = band_start_HQ; + move16(); + *sfm_end = band_end_HQ; + move16(); + + test(); + IF ( EQ_32(core_brate, HQ_32k)) + { + *hq_generic_offset = HQ_GENERIC_FOFFSET_32K; + move16(); + } + ELSE IF ( EQ_32(core_brate, HQ_16k40)||EQ_32(core_brate,HQ_24k40)) + { + *hq_generic_offset = HQ_GENERIC_FOFFSET_24K4; + move16(); + } + + /* setting start frequency of FD BWE */ + test(); + IF ( EQ_32(core_brate, HQ_32k)) + { + *num_env_bands = SFM_N_STA_10k; + move16(); + } + ELSE IF ( EQ_32(core_brate, HQ_16k40)||EQ_32(core_brate,HQ_24k40)) + { + *num_env_bands = SFM_N_STA_8k; + move16(); + } + *nb_sfm = *num_sfm; + move16(); + } + ELSE + { + IF(EQ_16(hqswb_clas, HQ_HARMONIC)) + { + *num_sfm = SFM_N_HARM_FB; + move16(); + *nb_sfm = SFM_N_HARM_FB; + move16(); + *num_env_bands = SFM_N_HARM_FB; + move16(); + + *sfmsize = band_len_harm; + move16(); + *sfm_start = band_start_harm; + move16(); + *sfm_end = band_end_harm; + move16(); + } + ELSE IF ( EQ_16(hqswb_clas, HQ_HVQ)) + { + IF ( EQ_32(core_brate, HQ_24k40)) + { + *num_sfm = SFM_N_HARM_FB; + move16(); + *nb_sfm = HVQ_THRES_SFM_24k; + move16(); + *num_env_bands = sub(*num_sfm, *nb_sfm); + + *sfmsize = band_len_harm; + move16(); + *sfm_start = band_start_harm; + move16(); + *sfm_end = band_end_harm; + move16(); + *start_norm = HVQ_THRES_SFM_24k; + move16(); + } + ELSE + { + *num_sfm = SFM_N_HARM_FB; + move16(); + *nb_sfm = HVQ_THRES_SFM_32k; + move16(); + *num_env_bands = sub(*num_sfm, *nb_sfm); + + *sfmsize = band_len_harm; + move16(); + *sfm_start = band_start_harm; + move16(); + *start_norm = HVQ_THRES_SFM_32k; + move16(); + *sfm_end = band_end_harm; + move16(); + } + } + ELSE + { + *num_sfm = NB_SFM; + move16(); + *nb_sfm = *num_sfm; + move16(); + *num_env_bands = NB_SFM; + move16(); + + *sfmsize = band_len_HQ; + move16(); + *sfm_start = band_start_HQ; + move16(); + *sfm_end = band_end_HQ; + move16(); + } + } + } + ELSE IF( EQ_16(length, L_FRAME32k)) + { + IF ( EQ_16(hqswb_clas, HQ_HARMONIC)) + { + *num_sfm = SFM_N_HARM; + move16(); + *nb_sfm = SFM_N_HARM; + move16(); + *num_env_bands = SFM_N_HARM; + move16(); + + *sfmsize = band_len_harm; + move16(); + *sfm_start = band_start_harm; + move16(); + *sfm_end = band_end_harm; + move16(); + } + ELSE IF ( EQ_16(hqswb_clas, HQ_HVQ)) + { + IF ( EQ_32(core_brate, HQ_24k40)) + { + *num_sfm = SFM_N_HARM; + move16(); + *nb_sfm = HVQ_THRES_SFM_24k; + move16(); + *num_env_bands = sub(*num_sfm, *nb_sfm); + + *sfmsize = band_len_harm; + move16(); + *sfm_start = band_start_harm; + move16(); + *sfm_end = band_end_harm; + move16(); + *start_norm = HVQ_THRES_SFM_24k; + move16(); + } + ELSE + { + *num_sfm = SFM_N_HARM; + move16(); + *nb_sfm = HVQ_THRES_SFM_32k; + move16(); + *num_env_bands = sub(*num_sfm, *nb_sfm); + + *sfmsize = band_len_harm; + move16(); + *sfm_start = band_start_harm; + move16(); + *start_norm = HVQ_THRES_SFM_32k; + move16(); + *sfm_end = band_end_harm; + move16(); + } + } + ELSE IF ( EQ_16(hqswb_clas, HQ_GEN_SWB)) + { + *num_sfm = SFM_N_SWB; + move16(); + *sfmsize = band_len_HQ; + move16(); + *sfm_start = band_start_HQ; + move16(); + *sfm_end = band_end_HQ; + move16(); + + IF ( EQ_32(core_brate, HQ_32k)) + { + *hq_generic_offset = HQ_GENERIC_FOFFSET_32K; + move16(); + } + ELSE if ( EQ_32(core_brate, HQ_24k40)) + { + *hq_generic_offset = HQ_GENERIC_FOFFSET_24K4; + move16(); + } + + /* setting start frequency of HQ Generic */ + IF ( EQ_32(core_brate, HQ_32k)) + { + *num_env_bands = SFM_N_STA_10k; + move16(); + } + ELSE if( EQ_32(core_brate, HQ_24k40)) + { + *num_env_bands = SFM_N_STA_8k; + move16(); + } + + *nb_sfm = *num_sfm; + move16(); + } + ELSE + { + /* HQ_NORMAL and HQ_TRANSIENT */ + *num_sfm = SFM_N_SWB; + move16(); + *nb_sfm = *num_sfm; + move16(); + *num_env_bands = SFM_N_SWB; + move16(); + + *sfmsize = band_len_HQ; + move16(); + *sfm_start = band_start_HQ; + move16(); + *sfm_end = band_end_HQ; + move16(); + } + } + ELSE + { + *num_sfm = SFM_N_WB; + move16(); + *nb_sfm = *num_sfm; + move16(); + *num_env_bands = SFM_N_WB; + move16(); + + *sfmsize = band_len_wb; + move16(); + *sfm_start = band_start_wb; + move16(); + *sfm_end = band_end_wb; + move16(); + } + + *numnrmibits = extract_l(L_mult0(sub(*num_env_bands, 1), NORMI_BITS)); + + return; +} diff --git a/lib_com/hq_tools_fx.c b/lib_com/hq_tools_fx.c new file mode 100644 index 0000000..f20cca9 --- /dev/null +++ b/lib_com/hq_tools_fx.c @@ -0,0 +1,2342 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "rom_com_fx.h" /* Static table prototypes FIP version */ +#include "stl.h" /* required for wmc_tool */ +#include "prot_fx.h" + +/*--------------------------------------------------------------------------* + * Local functions + *--------------------------------------------------------------------------*/ + +static void overlap_hq_bwe_fx( const Word32 *hq_swb_overlap_buf, Word32 *coeff_out, const Word16 n_swb_overlap_offset, + const Word16 n_swb_overlap, const Word16 *R, const Word16 num_env_bands, const Word16 num_sfm, const Word16 *sfm_end); + +/*--------------------------------------------------------------------------* +* hq_swb_harmonic_calc_norm_envelop() +* +* Calculate normalization envelop +*--------------------------------------------------------------------------*/ + +void hq_swb_harmonic_calc_norm_envelop_fx( + Word32 *L_SWB_signal, /* i : input signal Q=12*/ + Word32 *L_envelope, /* o : output envelope Q=12*/ + Word16 L_swb_norm, /* i : length of normaliztion */ + Word16 SWB_flength /* i : length of input signal */ +) +{ + + Word16 lookback; + Word16 env_index; + Word16 n_freq; + Word16 n_lag_now; + Word16 n_lag; + Word16 i; + Word32 L_tmp; + + lookback = shr(L_swb_norm,1); + env_index = 0; + move16(); + FOR (n_freq = 0; n_freq < lookback; n_freq++) + { + n_lag_now = add(lookback,n_freq); + + /* Apply MA filter */ + L_envelope[env_index] = EPSILLON_FX; + move16(); + + FOR (n_lag=0; n_lag 0) + { + CodeBook_mod[cb_size] = 1<<12; + move16(); /* set to 1, Q value 12 */ + E_cb_vec = add(E_cb_vec,1); + } + ELSE IF (coeff[j] < 0) + { + CodeBook_mod[cb_size] = -1 * (1<<12); + move16(); /* set to -1, Q value 12 */ + E_cb_vec = add(E_cb_vec,1); + } + ELSE + { + CodeBook_mod[cb_size] = 0; + move16(); + } + cb_size = add(cb_size,1); + } + + if (E_cb_vec < 2) + { + cb_size = sub(cb_size,8); + } + } + } + ELSE + { + FOR (j = sfm_start[sfm]; j < sfm_end[sfm]; j++) + { + CodeBook[cb_size] = coeff[j]; + move16(); + cb_size = add(cb_size,1); + } + } + } + } + + IF (flag_32K_env_ho) + { + FOR (j = 0; j < cb_size; j++) + { + IF (CodeBook_mod[j] != 0) + { + /* Densify codebook */ + CodeBook[j] = -4096; + move16(); /* -1 in Q12 */ + if (CodeBook_mod[j] > 0) + { + CodeBook[j] = 4096; + move16(); /* 1 in Q12 */ + } + + IF (CodeBook_mod[cb_size-j-1] != 0) + { + CodeBook[j] = shl(CodeBook[j], 1); + move16(); /* Mult by 2 */ + } + } + ELSE + { + CodeBook[j] = CodeBook_mod[cb_size-j-1]; + move16(); + } + } + } + + return cb_size; +} + + +/*--------------------------------------------------------------------------* +* find_last_band() +* +* Find the last band which has bits allocated +*--------------------------------------------------------------------------*/ + +Word16 find_last_band_fx( /* o : index of last band */ + const Word16 *bitalloc, /* i : bit allocation */ + const Word16 nb_sfm /* i : number of possibly coded bands */ +) +{ + Word16 sfm, core_sfm; + + core_sfm = sub(nb_sfm,1); + + FOR (sfm = nb_sfm-1; sfm >= 0; sfm--) + { + IF ( bitalloc[sfm] != 0 ) + { + core_sfm = sfm; + move16(); + BREAK; + } + } + + return core_sfm; +} + +/*--------------------------------------------------------------------------* + * apply_noisefill_HQ() + * + * Inject noise in non-coded bands + *--------------------------------------------------------------------------*/ + +void apply_noisefill_HQ_fx( + const Word16 *R, /* i : bit allocation Q0 */ + const Word16 length, /* i : input frame length Q0 */ + const Word16 flag_32K_env_ho,/* i : envelope stability hangover flag Q0 */ + const Word32 L_core_brate, /* i : core bit rate Q0 */ + const Word16 last_sfm, /* i : last coded subband Q0 */ + const Word16 *CodeBook, /* i : Noise-fill codebook Q12 */ + const Word16 *CodeBook_mod, /* i : Densified noise-fill codebook Q12 */ + const Word16 cb_size, /* i : Codebook length Q0 */ + const Word16 *sfm_start, /* i : Subband start coefficient Q0 */ + const Word16 *sfm_end, /* i : Subband end coefficient Q0 */ + const Word16 *sfmsize, /* i : Subband band width Q0 */ + Word16 *coeff /* i/o: coded/noisefilled spectrum Q12 */ +) +{ + Word16 sfm; + Word16 cb_pos; + Word16 E_corr; + Word16 cb_buff[PVQ_MAX_BAND_SIZE]; + Word16 i, j; + Word16 istart; + UWord16 lsb; + Word32 L_E_cb_vec; + Word32 L_E_corr; + + test(); + test(); + IF ( (GE_16(length, L_FRAME32k))||(GT_32(L_core_brate,HQ_32k))||(LT_32(L_core_brate,HQ_24k40))) + { + /* Read from codebook */ + cb_pos = 0; + move16(); + + FOR (sfm = 0; sfm <= last_sfm; sfm++) + { + IF (R[sfm] == 0) + { + IF (EQ_16(flag_32K_env_ho, 1)) + { + L_E_cb_vec = L_deposit_l(0); + IF (LT_16(sfm, 20)) + { + FOR (i = 0; i < sfmsize[sfm]; i++) + { + cb_buff[i] = CodeBook_mod[cb_pos++]; + move16(); + L_E_cb_vec = L_mac0(L_E_cb_vec, cb_buff[i], cb_buff[i]); /*Q24 (12+12) */ + + if (GE_16(cb_pos, cb_size)) + { + cb_pos = 0; + move16(); + } + } + } + ELSE + { + FOR (i = 0; i < sfmsize[sfm]; i++) + { + cb_buff[i] = CodeBook[cb_pos++]; + move16(); + L_E_cb_vec = L_mac0(L_E_cb_vec, cb_buff[i], cb_buff[i]); /*Q24 (12+12) */ + + if (GE_16(cb_pos, cb_size)) + { + cb_pos = 0; + move16(); + } + } + } + + /*E_corr = E_cb_vec / ((float) sfmsize[sfm]); */ + Mpy_32_16_ss(L_E_cb_vec, inv_tbl_fx[sfmsize[sfm]], &L_E_corr, &lsb); /*Q24 (24+15+1-16) */ + move16(); + + /*E_corr = 1.0f / (float)sqrt(E_corr); */ + L_E_corr = Isqrt(L_E_corr); /*Q19 (31-24/2) */ + E_corr = extract_h(L_shl(L_E_corr, 10)); /*Q13 (13-(19-16)) */ + + istart = sfm_start[sfm]; + move16(); + FOR(j = istart; j < sfm_end[sfm]; j++) + { + /*coeff[j] = cb_buff[j - istart] * E_corr; */ + coeff[j] = extract_h(L_shl(L_mult(cb_buff[j - istart], E_corr), 2)); /*Q12 (12+13+1+2-16) */ + } + } + ELSE + { + FOR (j = sfm_start[sfm]; j < sfm_end[sfm]; j++) + { + coeff[j] = CodeBook[cb_pos++]; + move16(); + if (GE_16(cb_pos, cb_size)) + { + cb_pos = 0; + move16(); + } + } + } + } + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * harm_bwe_fine_fx() + * + * Prepare harmonic BWE fine structure + *--------------------------------------------------------------------------*/ + +void harm_bwe_fine_fx( + const Word16 *R, /* i : bit allocation */ + const Word16 last_sfm, /* i : last coded subband */ + const Word16 high_sfm, /* i : higher transition band to BWE */ + const Word16 num_sfm, /* i : total number of bands */ + const Word16 *norm, /* i : quantization indices for norms */ + const Word16 *sfm_start, /* i : Subband start coefficient */ + const Word16 *sfm_end, /* i : Subband end coefficient */ + Word16 *prev_L_swb_norm, /* i/o: last normalize length */ + Word16 *coeff, /* i/o: coded/noisefilled normalized spectrum */ + Word32 *coeff_out /* o : coded/noisefilled spectrum */ + , Word16 *coeff_fine /* o : BWE fine structure */ +) +{ + Word16 sfm; + Word16 i; + Word32 normq; + Word16 SWB_signal[L_HARMONIC_EXC]; + Word32 envelope[L_HARMONIC_EXC], L_signal[L_HARMONIC_EXC]; + Word16 enve_lo[L_HARMONIC_EXC], enve_hi[L_HARMONIC_EXC]; + Word16 *src, *dst, *end; + Word16 norm_signal; + + Word16 norm_width = 64; + move16(); + + /* shape the spectrum */ + FOR (sfm = 0; sfm <= last_sfm; sfm++) + { + IF( R[sfm] != 0 ) + { + normq = dicn_fx[norm[sfm]]; + move32(); + + FOR (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + coeff_out[i] = L_shl(Mult_32_16(normq, coeff[i]),1); /*12 14+12+1+1-16 */ + move32(); + } + } + ELSE + { + FOR (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + coeff_out[i] = L_deposit_l(0); + } + } + } + + /* excitation replication */ + Copy32(coeff_out, L_signal, L_HARMONIC_EXC); + calc_normal_length_fx_32( HQ_CORE, coeff_out, HQ_HARMONIC, -1, &norm_width, prev_L_swb_norm ); + hq_swb_harmonic_calc_norm_envelop_fx( L_signal, envelope, norm_width, L_HARMONIC_EXC ); + + /* Normalize with envelope */ + FOR (i = 0; i < L_HARMONIC_EXC; i++) + { + IF (L_signal[i] > 0) + { + norm_signal = norm_l(envelope[i]); + enve_lo[i] = L_Extract_lc(L_shl(envelope[i], norm_signal), &enve_hi[i]); + L_signal[i] = Div_32(L_signal[i], enve_hi[i], enve_lo[i]); + SWB_signal[i] = round_fx(L_shl(L_signal[i], norm_signal)); + move16(); + move16(); + move32(); + + } + ELSE + { + norm_signal = norm_l(envelope[i]); + enve_lo[i] = L_Extract_lc(L_shl(envelope[i], norm_signal), &enve_hi[i]); + L_signal[i] = L_negate(Div_32(L_negate(L_signal[i]), enve_hi[i], enve_lo[i])); + SWB_signal[i] = round_fx(L_shl(L_signal[i], norm_signal)); + move16(); + move16(); + move32(); + + } + } + + dst = coeff_fine + sfm_end[last_sfm]; + end = coeff_fine + sfm_end[num_sfm-1]; + + IF (LE_16(sub(sfm_end[last_sfm], sfm_end[high_sfm]),(L_HARMONIC_EXC - START_EXC) )) + { + src = SWB_signal + START_EXC + sub(sfm_end[last_sfm], sfm_end[high_sfm]); + } + ELSE + { + src = SWB_signal + L_HARMONIC_EXC - 1; + } + + WHILE (dst < end) + { + logic32(); + WHILE (dst < end && src < &SWB_signal[L_HARMONIC_EXC]) + { + *dst++ = *src++; + move16(); + } + src --; + + logic32(); + WHILE (dst < end && src >= &SWB_signal[START_EXC]) + { + *dst++ = *src--; + move16(); + } + src++; + } + + return; +} + +/*--------------------------------------------------------------------------* + * hvq_bwe_fine() + * + * Prepare HVQ BWE fine structure + *--------------------------------------------------------------------------*/ + +void hvq_bwe_fine_fx( + const Word16 last_sfm, /* i : last coded subband Q0 */ + const Word16 num_sfm, /* i : total number of bands Q0 */ + const Word16 *sfm_end, /* i : Subband end coefficient Q0 */ + const Word16 *peak_idx, /* i : Peak index Q0 */ + const Word16 Npeaks, /* i : Number of peaks Q0 */ + Word16 *peak_pos, /* o : Peak positions Q0 */ + Word16 *prev_L_swb_norm, /* i/o: last normalize length Q0 */ + Word32 *L_coeff, /* i : coded/noisefilled normalized spectrum Q12 */ + Word16 *bwe_peaks, /* o : Positions of peaks in BWE Q0 */ + Word16 *coeff_fine /* o : HVQ BWE fine structure Q15 */ +) +{ + Word16 i, j; + Word16 SWB_signal[L_HARMONIC_EXC]; + Word32 L_envelope[L_HARMONIC_EXC]; + Word16 *src, *dst, *end; + Word16 *peak_dst, *peak_src; + Word16 norm_width = 64; + Word16 tmp; + Word16 shift, shift2; + Word32 L_tmp; + UWord16 lsb; + + calc_normal_length_fx_32( HQ_CORE, L_coeff, HQ_HVQ, -1, &norm_width, prev_L_swb_norm ); + + hq_swb_harmonic_calc_norm_envelop_fx(L_coeff, L_envelope, norm_width, L_HARMONIC_EXC); + + /* Normalize with envelope */ + FOR (i = 0; i < L_HARMONIC_EXC; i++) + { + /*SWB_signal[i] = SWB_signal[i] / envelope[i]; */ + + shift = norm_l(L_envelope[i]); + tmp = round_fx(L_shl(L_envelope[i], shift)); /* 12+s-16=Q(-4+s) */ + + /* Avoid division by zero */ + if (tmp == 0) + { + tmp = 1<<14; + move16(); + } + + tmp = div_s(1<<14, tmp); /* 15+14-(-4+s)=Q(33-s) */ + Mpy_32_16_ss(L_coeff[i], tmp, &L_tmp, &lsb); /* 12+33-s+1-16=Q(30-s) */ + shift2 = add(shift, 1); + tmp = round_fx(L_shl(L_tmp, shift2)); /* 30-s+s+1-16=Q(15) */ + SWB_signal[i] = add(tmp, lshr(lsb, sub(32, shift2))); + move16(); /* Q15 */ + /*SWB_signal[i] = round_fx(L_shl(L_tmp, add(shift, 1))); // 30-s+s+1-16=Q(15) */ + + } + + dst = coeff_fine; + end = coeff_fine + sfm_end[num_sfm-1] - sfm_end[last_sfm]; + + src = SWB_signal + START_EXC; + peak_src = peak_pos + START_EXC; + + FOR (i = 0; i < Npeaks; i++) + { + if ( LT_16(peak_idx[i], L_HARMONIC_EXC)) + { + peak_pos[peak_idx[i]] = 1; + move16(); + } + } + + i = sub(L_HARMONIC_EXC, 1); + WHILE ( i-- > 0 ) + { + IF ( EQ_16(peak_pos[i], 1)) + { + BREAK; + } + } + + if ( LT_16(i, 180)) + { + i = 180; + move16(); + } + + FOR ( j = L_HARMONIC_EXC-1; j > i+1; j-- ) + { + SWB_signal[j] = 0; + move16(); + } + + peak_dst = bwe_peaks + sfm_end[last_sfm]; + WHILE ( dst < end ) + { + test(); + WHILE ( dst < end && src < &SWB_signal[L_HARMONIC_EXC] ) + { + *dst++ = *src++; + move16(); + *peak_dst++ = *peak_src++; + move16(); + } + peak_src--; + src --; + + test(); + WHILE ( dst < end && src >= &SWB_signal[START_EXC] ) + { + *dst++ = *src--; + move16(); + *peak_dst++ = *peak_src--; + move16(); + } + peak_src++; + src++; + } + + return; +} + +/*--------------------------------------------------------------------------* + * hq_fold_bwe_fx() + * + * HQ mode folding BWE + *--------------------------------------------------------------------------*/ + +void hq_fold_bwe_fx( + const Word16 last_sfm, /* i : last coded subband Q0 */ + const Word16 *sfm_end, /* i : Subband end coefficient Q0 */ + const Word16 num_sfm, /* i : Number of subbands Q0 */ + Word16 *coeff /* i/o: coded/noisefilled normalized spectrum Q12 */ +) +{ + Word16 low_coeff; + Word16 first_coeff; + Word16 *src, *dst, *end; + + low_coeff = shr(sfm_end[last_sfm], 1); + src = coeff + sfm_end[last_sfm] - 1; + + first_coeff = sfm_end[last_sfm]; + dst = coeff + sfm_end[last_sfm]; + end = coeff + sfm_end[num_sfm-1]; + + WHILE(dst < end) + { + WHILE(dst < end && src >= &coeff[low_coeff]) + { + *dst++ = *src--; + move16(); + } + + src++; + + WHILE(dst < end && src < &coeff[first_coeff]) + { + *dst++ = *src++; + move16(); + } + } + return; +} + +/*--------------------------------------------------------------------------* + * apply_nf_gain() + * + * Apply noise fill gain + *--------------------------------------------------------------------------*/ + +void apply_nf_gain_fx( + const Word16 nf_idx, /* i : noise fill gain index Q0 */ + const Word16 last_sfm, /* i : last coded subband Q0 */ + const Word16 *R, /* i : bit allocation Q0 */ + const Word16 *sfm_start, /* i : Subband start coefficient Q0 */ + const Word16 *sfm_end, /* i : Subband end coefficient Q0 */ + Word16 *coeff /* i/o: coded/noisefilled normalized spectrum Q12 */ +) +{ + Word16 sfm; + Word16 j; + + FOR (sfm = 0; sfm <= last_sfm; sfm++) + { + IF (R[sfm] == 0) + { + FOR (j = sfm_start[sfm]; j < sfm_end[sfm]; j++) + { + /* Scale NoiseFill */ + coeff[j] = shr(coeff[j], nf_idx); + move16(); + } + } + } + + return; +} + + +/*--------------------------------------------------------------------------* + * harm_bwe_fx() + * + * HQ Harmonic BWE + *--------------------------------------------------------------------------*/ + +void harm_bwe_fx( + const Word16 *coeff_fine, /* i : fine structure for BWE */ + const Word16 *coeff, /* i : coded/noisefilled normalized spectrum */ + const Word16 num_sfm, /* i : Number of subbands */ + const Word16 *sfm_start, /* i : Subband start coefficient */ + const Word16 *sfm_end, /* i : Subband end coefficient */ + const Word16 last_sfm, /* i : last coded subband */ + const Word16 *R, /* i : bit allocation */ + const Word16 prev_hq_mode, /* i : previous hq mode */ + Word16 *norm, /* i/o: quantization indices for norms */ + Word16 *noise_level, /* i/o: noise levels for harmonic modes */ + Word16 *prev_noise_level, /* i/o: noise factor in previous frame */ + Word16 *bwe_seed, /* i/o: random seed for generating BWE input */ + Word32 *coeff_out /* o : coded/noisefilled spectrum */ +) +{ + Word16 i, j; + Word16 sfm, band_width; + Word32 normq, L_tmp,L_tmp2; + Word32 E_L; + Word16 alfa = 16384; + Word16 tmp, tmp1, exp1; + Word16 beta; + Word32 *src, *dst; + + move16(); /* alfa */ + + FOR (sfm = 0; sfm <= last_sfm; sfm++) + { + IF (R[sfm] == 0) + { + normq = dicn_fx[norm[sfm]]; /*Q14 */ move16(); + + FOR (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + coeff_out[i] = L_shl(Mult_32_16(normq, coeff[i]),1); + move32(); /*12 Q(14 +12+1-16 +1) */ + + } + } + } + noise_level[1] = noise_level[0]; + move16(); + + /* shaping the BWE spectrum further by envelopes and noise factors */ + L_tmp = L_mult(29491, prev_noise_level[0]); /* 15 +1 +15 */ + noise_level[0] = round_fx(L_mac(L_tmp, 3277, noise_level[0])); /*15 */ + + L_tmp = L_mult(29491, prev_noise_level[1]); + noise_level[1] = round_fx(L_mac(L_tmp, 3277, noise_level[1])); + + test(); + IF (prev_hq_mode == HQ_NORMAL || EQ_16(prev_hq_mode, HQ_GEN_SWB)) + { + IF (LT_16(noise_level[0], 8192)) + { + noise_level[0] = shl(noise_level[0], 2); + move16(); + } + + IF (LT_16(noise_level[1], 8192)) + { + noise_level[1] = shl(noise_level[1], 2); + move16(); + } + } + + FOR (i = add(last_sfm, 1); i < num_sfm; i++) + { + E_L = 1; + move32(); + FOR (j = sfm_start[i]; j < sfm_end[i]; j++) + { + L_tmp =L_mult0(coeff_fine[j], coeff_fine[j]);/*Q30 */ + E_L =L_add(E_L,L_shr(L_tmp,6));/*Q24 */ + } + + normq = dicn_fx[norm[i]]; + move32(); + + alfa = noise_level[0]; + move16(); + if (GT_16(i, 27)) + { + alfa = noise_level[1]; + move16(); + } + + band_width = sub(sfm_end[i], sfm_start[i]); /* */ + exp1 =norm_l(E_L); + IF(exp1 ==0) + { + E_L = Mult_32_16(E_L, inv_tbl_fx[band_width]); /* Q24 (24+15+1-16) *//*24+15+1-16 */ + tmp = div_l(E_L,sub(32767,alfa)); /*Q24-15-1 =8 */ + tmp = s_max(1,tmp); + L_tmp =L_deposit_h(tmp); /*24 */ + E_L = Isqrt(L_tmp); /* Q19 (31-24/2) */ + } + ELSE + { + exp1 =sub(exp1,1); + E_L = Mult_32_16(L_shl(E_L,exp1), inv_tbl_fx[band_width]); /* Q24+exp1 (24+exp1+15+1-16) */ + tmp = div_l(E_L,sub(32767,alfa)); /*Q24+exp1-15-1 =8+exp1 */ + tmp = s_max(1,tmp); + L_tmp =L_shl(L_deposit_l(tmp),sub(16,exp1)); /*24 8+exp1+16-exp1 */ + E_L = Isqrt(L_tmp); /* Q19 (31-24/2) */ + } + + exp1 = norm_s(alfa); + tmp1 = shl(alfa, exp1); + exp1 = add(1, exp1); + tmp1 = s_max(tmp1, 16384); + tmp1 = div_s(16384, tmp1); + L_tmp2 = L_deposit_h(tmp1); + L_tmp2 = Isqrt_lc(L_tmp2, &exp1); + beta = round_fx(L_shl(L_tmp2, exp1)); + beta =shr(beta,1); /*Q15 */ + + + FOR(sfm = sfm_start[i]; sfm < sfm_end[i]; sfm++) + { + L_tmp = Mult_32_16(E_L,coeff_fine[sfm]); /*Q19 19 + 15 +1-16 */ + L_tmp = L_shl(L_tmp,9);/*Q28 */ + tmp = Random(bwe_seed); /*Q15 */ + L_tmp2 =L_shr(L_mult(beta,tmp),3);/* Q28 31-3 15+15 +1-3 */ + L_tmp =L_add(L_tmp,L_tmp2);/*Q28 */ + coeff_out[sfm] = L_shl(Mult_32_32(L_tmp, normq),1);/*Q12 28 +14 +1 -31 */ move32(); + } + } + + prev_noise_level[0] = noise_level[0]; + move16(); + prev_noise_level[1] = noise_level[1]; + move16(); + + src = &coeff_out[add(sfm_end[last_sfm], L_HARMONIC_EXC - START_EXC)]; /*Q12 */ + + dst = src-1; + FOR( i = 0; i < 16; i++ ) + { + *src = Mult_32_16(*src, hvq_bwe_fac_fx[i]); /* Q12 (12+15+1-16) */ move32(); + src++; + *dst = Mult_32_16(*dst, hvq_bwe_fac_fx[i]); /* Q12 (12+15+1-16) */ move32(); + dst--; + } + IF(EQ_16(num_sfm, 33)) + { + set32_fx(&coeff_out[800], 0, 160); + } + return; +} + +/*--------------------------------------------------------------------------* + * HVQ_bwe_fx() + * + * HQ HVQ BWE + *--------------------------------------------------------------------------*/ + +void hvq_bwe_fx( + const Word32 *L_coeff, /* i : coded/noisefilled normalized spectrum Q12 */ + const Word16 *coeff_fine, /* i : coded/noisefilled normalized spectrum Qin */ + const Word16 *sfm_start, /* i : Subband start coefficient Q0 */ + const Word16 *sfm_end, /* i : Subband end coefficient Q0 */ + const Word16 *sfm_len, /* i : Subband length Q0 */ + const Word16 last_sfm, /* i : last coded subband Q0 */ + const Word16 prev_hq_mode, /* i : previous hq mode Q0 */ + const Word16 *bwe_peaks, /* i : HVQ bwe peaks Q0 */ + const Word16 bin_th, /* i : HVQ transition bin Q0 */ + const Word16 num_sfm, /* i : Number of bands Q0 */ + const Word32 core_brate, /* i : Core bit-rate Q0 */ + const Word16 *R, /* i : Bit allocation */ + Word16 *norm, /* i/o: quantization indices for norms Q0 */ + Word16 *noise_level, /* i/o: noise levels for harmonic modes Q15 */ + Word16 *prev_noise_level, /* i/o: noise factor in previous frame Q15 */ + Word16 *bwe_seed, /* i/o: random seed for generating BWE input Q0 */ + Word32 *L_coeff_out, /* o : coded/noisefilled spectrum Qout*/ + const Word16 qin, + const Word16 qout +) +{ + Word16 i, j; + Word16 N; + Word32 L_normq; + Word32 L_E; + Word32 L_tmp_norm = 0; + Word16 bwe_noise_th = 0; + Word16 peak_band, low, high, sel_norm; + Word16 norm_ind; + Word32 *L_src, *L_dst; + Word16 istart, iend; + Word16 offset = sfm_end[last_sfm]; + + /* Fx specific variables */ + Word32 L_tmp0, L_tmp1; + Word16 tmp, tmp2, band_size; + Word16 last_norm_ind; + Word16 shift, power_shift; + Word16 coeff_s[L_FRAME48k]; + Word16 j_N; + Word16 n_c; + UWord16 lsb; + + move32(); /* L_tmp_norm */ + move16(); /* bwe_noise_th */ + + bwe_noise_th = add(bin_th, shr(sub(sfm_end[sub(num_sfm,1)], bin_th),1)); + logqnorm_fx(&L_coeff_out[sfm_start[last_sfm]], qout, &norm[last_sfm], 40, sfm_len[last_sfm], 0); + move16(); + + /* shaping the BWE spectrum further by envelopes and noise factors */ + noise_level[0] = round_fx(L_mac(L_mult(29491,prev_noise_level[0]),3277,noise_level[0])); /* Q15 (15+15+1-16) */ + noise_level[1] = round_fx(L_mac(L_mult(29491,prev_noise_level[1]),3277,noise_level[1])); /* Q15 (15+15+1-16) */ + + test(); + IF (prev_hq_mode == HQ_NORMAL || EQ_16(prev_hq_mode, HQ_GEN_SWB)) + { + IF( LT_16(noise_level[0], 8192 /* 0.25f */)) + { + noise_level[0] = shl(noise_level[0], 2); + move16(); + } + + IF( LT_16(noise_level[1], 8192 /* 0.25f */)) + { + noise_level[1] = shl(noise_level[1], 2); + move16(); + } + } + + norm_ind = add(last_sfm, 1); + IF ( EQ_32(core_brate, HQ_24k40)) + { + peak_band = 0; + move16(); + + tmp = 1; + move16(); + FOR (i = sfm_start[norm_ind]; i < sfm_end[norm_ind+1]; i++) + { + tmp2 = abs_s(coeff_fine[i-offset]); + tmp = s_max(tmp, tmp2); + } + band_size = sub(sfm_end[norm_ind+1], sfm_start[norm_ind]); + + /* Headroom for square and accumulate */ + shift = sub(norm_s(tmp), sqac_headroom_fx[band_size]); + L_E = L_deposit_l(1); + FOR (i = sfm_start[norm_ind]; i < sfm_end[norm_ind+1]; i++) + { + if (bwe_peaks[i]) + { + peak_band = 1; + move16(); + } + /* E_L += coeff_fine[i-offset] * coeff_fine[i-offset]; */ + coeff_s[i] = shl(coeff_fine[i-offset], shift); + move16();/* Q15 + shift */ + L_E = L_mac0(L_E, coeff_s[i], coeff_s[i]); /* Q2*(qin + shift) */ + } + power_shift = shl(shift, 1); + + L_E = L_shr(L_E,sub(power_shift,28-2*qin)); /* Q28 */ + + /* E_L = (float)sqrt((sfm_end[norm_ind+1] - sfm_start[norm_ind])/E_L); */ + L_E = Mult_32_16(L_E, inv_tbl_fx[band_size]); /* Q28 (28+15+1-16) */ + /* To avoid overflow in Isqrt() */ + if( L_E == 0 ) + { + L_E = L_deposit_l(1); + } + L_E = Isqrt(L_E); /* Q17 (31-28/2) */ + + /* normq = 0.1f*dicn[norm[norm_ind-1]] + 0.8f*dicn[norm[norm_ind]] + 0.1f*dicn[norm[norm_ind+1]]; */ + /* tmp_norm = 0.1f*dicn[norm[norm_ind]] + 0.8f*dicn[norm[norm_ind+1]] + 0.1f*dicn[norm[norm_ind+2]]; */ + L_tmp0 = L_add(dicn_fx[norm[norm_ind]], 0); + L_tmp1 = L_add(dicn_fx[norm[norm_ind+1]], 0); + L_normq = Madd_32_16(Madd_32_16(Mult_32_16(L_tmp0, 26214 /* Q15, 0.8f */), dicn_fx[norm[norm_ind-1]], 3277 /* Q15, 0.1f */), L_tmp1, 3277 /* Q15, 0.1f */); /* Q14 (14+15+1-16) */ move16(); + L_tmp_norm = Madd_32_16(Madd_32_16(Mult_32_16(L_tmp1, 26214 /* Q15, 0.8f */), dicn_fx[norm[norm_ind+2]], 3277 /* Q15, 0.1f */), L_tmp0, 3277 /* Q15, 0.1f */); /* Q14 (14+15+1-16) */ move16(); + + istart = sfm_start[norm_ind]; + move16(); + /* iend = istart + sfm_len[norm_ind]/2; */ + iend = 240; + move16(); + + noise_mix_fx( &coeff_fine[-offset], L_E, L_normq, bwe_seed, istart, iend, noise_level[0], L_coeff_out, qin, qout); + + j = 0; + move16(); + /* N = sfm_len[norm_ind]/2+sfm_len[norm_ind+1]/2-1; */ + N = 31; + move16(); + j_N = N; + move16(); + + istart = iend; + move16(); + /* iend = sfm_start[norm_ind+1] + sfm_len[norm_ind+1]/2; */ + iend = 272; + move16(); + + /* special case that is not handled by noise_mix_fx() */ + n_c = sub(MAX_16,noise_level[0]); /* Q15 */ + FOR (i = istart; i < iend; i++) + { + /* coeff_out[i] = ((float)(N-j)/N*normq + (float)j/N*tmp_norm)*((1.0f - noise_level[i/bwe_noise_th])*coeff_fine[i-offset]*E_L + noise_level[i/bwe_noise_th]*own_random(bwe_seed)/32768.0f); */ + L_tmp1 = Madd_32_16(Mult_32_16(L_normq, inv_N_fx[j_N] ), L_tmp_norm, inv_N_fx[j]); /* Q14 (14+15+1-16) */ + j = add(j,1); + j_N = sub(j_N,1); + + Mpy_32_16_ss(L_E, coeff_fine[i-offset], &L_tmp0, &lsb); /* Qin+2 (17+qin+1-16) */ + Mpy_32_16_ss(L_tmp0, n_c, &L_tmp0, &lsb); /* Qin+2-15 (qin+2+15+1-16) */ + + IF(L_tmp0 != 0) + { + /* Normalize with 1 bit headroom for addition */ + tmp = 30-(qin+2); /* Assuming fixed Q values */ + tmp = s_min(norm_l(L_tmp0), tmp); + tmp = sub(tmp,1); + + L_tmp0 = L_add(L_shl(L_tmp0,tmp), L_deposit_l(lshr(lsb, sub(16,tmp)))); /* Qin+2+tmp */ + + L_tmp0 = L_add(L_tmp0, L_shr(L_mult0(noise_level[0], Random(bwe_seed)), sub(30-(qin+2), tmp))); /* Qin+2+tmp */ + tmp = round_fx(L_shl(L_tmp0,27-(qin+2)-tmp)); /* Q11 (Qin+2+tmp+27-qin-2-tmp-16) */ + + Mpy_32_16_ss(L_tmp1, tmp, &L_tmp0, &lsb); /* Q10 (14+11+1-16) */ + L_coeff_out[i] = L_add(L_shl(L_tmp0,qout-10), L_deposit_l(lshr(lsb, 10+16-qout))); + move32(); /* Qout (10+qout-10) */ + } + ELSE + { + L_tmp0 = L_mult0(noise_level[0], Random(bwe_seed)); /* Q30 (15+15) */ + tmp = round_fx(L_tmp0); /* Q14 (30-16) */ + Mpy_32_16_ss(L_tmp1, tmp, &L_tmp0, &lsb); /* Q13 (14+14+1-16) */ + L_coeff_out[i] = L_shr(L_tmp0,13-qout); + move32();/* Qout (13-(13-qout)) */ + } + } + + istart = iend; + move16(); + iend = sfm_end[norm_ind+1]; + move16(); + + noise_mix_fx( &coeff_fine[-offset], L_E, L_tmp_norm, bwe_seed, istart, iend, noise_level[0], L_coeff_out, qin, qout); + + norm_ind = add(norm_ind, 2); + } + + FOR ( ; norm_ind < num_sfm; norm_ind++) + { + IF ( R[norm_ind] == 0 ) + { + peak_band = 0; + move16(); + + FOR (i = sfm_start[norm_ind]; i < sfm_end[norm_ind]; i++) + { + if (bwe_peaks[i]) + { + peak_band = 1; + move16(); + } + } + + istart = sfm_start[norm_ind]; + move16(); + iend = sfm_end[norm_ind]; + move16(); + + last_norm_ind = sub(num_sfm, 1); + test(); + test(); + IF ( EQ_16(peak_band, 1)&>_16(norm_ind,add(last_sfm,1))&<_16(norm_ind,last_norm_ind)) + { + istart = sub(istart, shr(sfm_len[norm_ind-1],1)); + iend = add(iend, shr(sfm_len[norm_ind+1],1)); + } + + tmp = 1; + move16(); + FOR (i = istart; i < iend; i++) + { + tmp2 = abs_s(coeff_fine[i-offset]); + tmp = s_max(tmp, tmp2); + } + band_size = sub(iend, istart); + /* Headroom for square and accumulate */ + shift = sub(norm_s(tmp), sqac_headroom_fx[band_size]); + + L_E = 1L; + move32(); + FOR (i = istart; i < iend; i++) + { + /* E_L += coeff_fine[i-offset] * coeff_fine[i-offset]; */ + coeff_s[i] = shl(coeff_fine[i-offset], shift); + move16();/* Q15 + shift */ + L_E = L_mac0(L_E, coeff_s[i], coeff_s[i]); /* Q2*(15 + shift) */ + } + power_shift = shl(shift, 1); + + L_E = L_shr(L_E,sub(power_shift,28-2*qin)); /* Q28 */ + + /* E_L = (float)sqrt((iend - istart)/E_L); */ + L_E = Mult_32_16(L_E, inv_tbl_fx[band_size]); /* Q28 (28+15+1-16) */ + /* To avoid overflow in Isqrt() */ + if( L_E == 0 ) + { + L_E = 1L; + move32(); + } + L_E = Isqrt(L_E); /* Q17 (31-28/2) */ + + IF ( peak_band ) + { + IF ( GT_16(add(norm_ind,2), num_sfm)) + { + /* normq = 0.15f*dicn[norm[norm_ind-1]] + 0.85f*dicn[norm[norm_ind]]; */ + L_normq = Madd_32_16(Mult_32_16(dicn_fx[norm[norm_ind]], 27853 /* Q15, 0.85f */), dicn_fx[norm[norm_ind-1]], 4915 /* Q15, 0.1f */); /* Q14 (14+15+1-16) */ move16(); + move16(); + } + ELSE + { + /* normq = 0.1f*dicn[norm[norm_ind-1]] + 0.8f*dicn[norm[norm_ind]] + 0.1f*dicn[norm[norm_ind+1]]; */ + L_normq = Madd_32_16(Madd_32_16(Mult_32_16(dicn_fx[norm[norm_ind]], 26214 /* Q15, 0.8f */), dicn_fx[norm[norm_ind+1]], 3277 /* Q15, 0.1f */), dicn_fx[norm[norm_ind-1]], 3277 /* Q15, 0.1f */); /* Q14 (14+15+1-16) */ move16(); + move16(); + move16(); + } + } + ELSE + { + low = norm_ind; + move16(); + high = s_min(add(norm_ind,1), last_norm_ind); + move16(); + sel_norm = norm[norm_ind-1]; + move16(); + FOR (j = low; j <= high; j++) + { + if ( GT_16(norm[j], sel_norm)) + { + sel_norm = norm[j]; + move16(); + } + } + L_normq = dicn_fx[sel_norm]; + move16(); + } + + iend = s_min(sfm_end[norm_ind], bwe_noise_th); + move16(); + IF( GT_16(iend, sfm_start[norm_ind])) + { + noise_mix_fx( &coeff_fine[-offset], L_E, L_normq, bwe_seed, sfm_start[norm_ind], iend, noise_level[0], L_coeff_out, qin, qout); + } + ELSE + { + iend = sfm_end[norm_ind]; + move16(); + noise_mix_fx( &coeff_fine[-offset], L_E, L_normq, bwe_seed, sfm_start[norm_ind], iend, noise_level[1], L_coeff_out, qin, qout); + } + /* Noisemix up to threshold done */ + IF( EQ_16(iend, bwe_noise_th)) + { + noise_mix_fx( &coeff_fine[-offset], L_E, L_normq, bwe_seed, iend, sfm_end[norm_ind], noise_level[1], L_coeff_out, qin, qout); + } + + } + ELSE /* R[norm_ind] > 0 */ + { + FOR (i = sfm_start[norm_ind]; i < sfm_end[norm_ind]; i++) + { + L_coeff_out[i] = L_coeff[i]; /* Scaling already applied */ move32(); + } + } + } + + prev_noise_level[0] = noise_level[0]; + move16(); + prev_noise_level[1] = noise_level[1]; + move16(); + L_src = &L_coeff_out[add(sfm_end[last_sfm], L_HARMONIC_EXC - START_EXC)]; /* Address initialization */ + L_dst = L_src - 1 ; /* Address computation */ + + FOR( i = 0; i < 16; i++ ) + { + *L_src = Mult_32_16(*L_src, hvq_bwe_fac_fx[i]); + L_src++; /* Qout (Qout+15+1-16) */ move32(); + *L_dst = Mult_32_16(*L_dst, hvq_bwe_fac_fx[i]); + L_dst--; /* Qout (Qout+15+1-16) */ move32(); + } + + return; +} + +/*-------------------------------------------------------------------* +* hvq_concat_bands_fx() +* +* Compute the band limits for concatenated bands for PVQ target signal in HVQ +*--------------------------------------------------------------------------*/ +void hvq_concat_bands_fx +( + const Word16 pvq_bands, /* i : Number of bands in concatenated PVQ target */ + const Word16 *sel_bnds, /* i : Array of selected high bands */ + const Word16 n_sel_bnds, /* i : Number of selected high bands */ + Word16 *hvq_band_start, /* i : Band start indices */ + Word16 *hvq_band_width, /* i : Band widths */ + Word16 *hvq_band_end /* i : Band end indices */ +) +{ + Word16 k, k_1; + const Word16 *pSelBnds; + + pSelBnds = sel_bnds; + FOR (k = 0; k < pvq_bands; k++) + { + + IF( GE_16(k, sub(pvq_bands, n_sel_bnds))) + { + k_1 = sub(k, 1); + hvq_band_start[k] = hvq_band_end[k_1]; + move16(); + hvq_band_width[k] = band_len_harm[*pSelBnds++]; + move16(); + move16(); + hvq_band_end[k] = add(hvq_band_end[k_1], hvq_band_width[k]); + move16(); + } + ELSE + { + hvq_band_start[k] = extract_l(L_mult0(k, HVQ_PVQ_COEFS)); + hvq_band_width[k] = HVQ_PVQ_COEFS; + move16(); + hvq_band_end[k] = add(hvq_band_start[k], HVQ_PVQ_COEFS); + move16(); + } + } + + return; +} +/*--------------------------------------------------------------------------* + * noise_mix_fx() + *--------------------------------------------------------------------------*/ + +void noise_mix_fx( + const Word16 *coeff_fine, /* i : normalized fine structure spectrum Qin */ + const Word32 L_E, /* i : normalization factor Q17 */ + const Word32 L_normq, /* i : quantized norm Q14 */ + Word16 *seed, /* i/o: random seed Q0 */ + const Word16 istart, /* i : start coefficient Q0 */ + const Word16 iend, /* i : end coefficient Q0 */ + const Word16 noise_level, /* i : noise_level Q0 */ + Word32 *L_coeff_out, /* o : noise mixed spectrum Qout */ + const Word16 qin, + const Word16 qout +) +{ + Word16 i, tmp, n_c; + Word32 L_tmp0; + UWord16 lsb; + + n_c = sub(MAX_16,noise_level); /* Q15 */ + FOR (i = istart; i < iend; i++) + { + /* L_coeff_out[i] = ((1.0f - noise_level)*coeff_fine[i]*L_E + noise_level*own_random(seed)/32768.0f)*normq; */ + Mpy_32_16_ss(L_E, coeff_fine[i], &L_tmp0, &lsb); /* Qin+qL_E-15 (qL_E+qin+1-16) */ + Mpy_32_16_ss(L_tmp0, n_c, &L_tmp0, &lsb); /* Qin+qL_E-15 (qin+qL_E-15+15+1-16) */ + + IF(L_tmp0 != 0) + { + /* Normalize with 1 bit headroom for addition */ + tmp = 30-(qin+2); /* Assuming fixed Q values */ + tmp = s_min(norm_l(L_tmp0), tmp); + tmp = sub(tmp,1); + + L_tmp0 = L_add(L_shl(L_tmp0,tmp), L_deposit_l(lshr(lsb, sub(16,tmp)))); /* Qin+2+tmp */ + L_tmp0 = L_add(L_tmp0, L_shr(L_mult0(noise_level, Random(seed)), sub(30-(qin+2), tmp))); /* Qin+2+tmp */ + + tmp = round_fx(L_shl(L_tmp0,27-(qin+2)-tmp)); /* Q11 (Qin+2+tmp+27-qin-2-tmp-16) */ + Mpy_32_16_ss(L_normq, tmp, &L_tmp0, &lsb); /* Q10 (14+11+1-16) */ + L_coeff_out[i] = L_add(L_shl(L_tmp0,qout-10), L_deposit_l(lshr(lsb, 10+16-qout))); + move32();/* Qout (10+qout-10) */ + } + ELSE + { + L_tmp0 = L_mult0(noise_level, Random(seed)); /* Q30 (15+15) */ + tmp = round_fx(L_tmp0); /* Q14 (30-16) */ + Mpy_32_16_ss(L_normq, tmp, &L_tmp0, &lsb); /* Q13 (14+14+1-16) */ + L_coeff_out[i] = L_shr(L_tmp0,13-qout); + move32();/* Qout (13-(13-qout)) */ + } + } +} + + +/*--------------------------------------------------------------------------* + * hq_generic_fine_fx() + * + * Prepare HQ GENERIC HF fine structure + *--------------------------------------------------------------------------*/ +void hq_generic_fine_fx( + Word16 *coeff, /* i : coded/noisefilled normalized spectrum */ + const Word16 last_sfm, /* i : Last coded band */ + const Word16 *sfm_start, /* i : Subband start coefficient */ + const Word16 *sfm_end, /* i : Subband end coefficient */ + Word16 *bwe_seed, /* i/o: random seed for generating BWE input */ + Word16 *coeff_out1 /* o : HQ GENERIC input */ +) +{ + Word16 sfm; + Word16 i; + + FOR (sfm = 0; sfm <= last_sfm; sfm++) + { + FOR (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + IF (coeff[i]==0) + { + coeff_out1[i] = -2048; + move16(); + if (Random(bwe_seed) > 0) + { + coeff_out1[i] = 2048; + move16(); + } + } + ELSE + { + coeff_out1[i] = coeff[i]; + move16(); + } + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * overlap_hq_bwe_fx() + * + * Overlapping at the boundary between HQ core and BWE + *--------------------------------------------------------------------------*/ +static void overlap_hq_bwe_fx( + const Word32 *hq_swb_overlap_buf, /* i : spectrum from HQ core */ + Word32 *coeff_out, /* i/o: spectrum from BWE, overlapped output */ + const Word16 n_swb_overlap_offset, /* i : starting offset of overlapping */ + const Word16 n_swb_overlap, /* i : length of overlapping */ + const Word16 *R, + const Word16 num_env_bands, + const Word16 num_sfm, + const Word16 *sfm_end +) +{ + Word16 i; + Word16 weighting; + Word16 step; + Word16 exp, tmp, n_band; + + IF ( R[sub(num_env_bands,1)] != 0) + { + Copy32( hq_swb_overlap_buf, &coeff_out[n_swb_overlap_offset], n_swb_overlap ); + } + ELSE + { + exp = norm_s(n_swb_overlap); + tmp = div_s(16384, shl(n_swb_overlap, exp));/*15 + 14 - exp */ + tmp = shr(tmp, sub(14, exp));/*15 */ + step = mult_r(tmp, 32767);/*15 */ + weighting = 32767; + move16(); + FOR (i = 0; i < n_swb_overlap; i++) + { + coeff_out[add(n_swb_overlap_offset,i)] = L_add(coeff_out[add(n_swb_overlap_offset,i)], + Mult_32_16(L_sub(hq_swb_overlap_buf[i], coeff_out[add(n_swb_overlap_offset,i)]), weighting)); + move32(); + weighting = sub(weighting, step); + } + } + + FOR (n_band = num_env_bands; n_band < num_sfm; n_band++) + { + IF (R[n_band] !=0 ) + { + FOR(i=sfm_end[sub(n_band,1)]; i0) + { + i=sub(nb_sfm,1); + WHILE(b_add_bits_denv>0 && i>=0) + { + IF ( GT_16(Rsubband[i], 24)) + { + Rsubband[i] = sub(Rsubband[i] , 8); + move16(); + b_add_bits_denv = sub(b_add_bits_denv,1); + } + i = sub(i,1); + } + } + + return; +} + +Word16 get_nor_delta_hf_fx( + Decoder_State_fx *st, + Word16 *ynrm, + Word16 *Rsubband, /* Q3 */ + const Word16 num_env_bands, + const Word16 nb_sfm, + const Word16 core_sfm +) +{ + Word16 i; + Word16 delta,bitsforDelta,add_bits_denv; + + add_bits_denv = 0; + move16(); + IF (GE_16(core_sfm ,num_env_bands)) + { + bitsforDelta = (Word16)get_next_indice_fx(st,2); + bitsforDelta = add(bitsforDelta, 2); + add_bits_denv = add(add_bits_denv,2); + + FOR(i=num_env_bands; iBER_detect = 1; + move16(); + } + /*ynrm[i] += delta - (1<<(bitsforDelta-1));*/ + add_bits_denv = add(add_bits_denv,bitsforDelta); + } + } + update_rsubband_fx(nb_sfm, Rsubband,add_bits_denv); + } + return add_bits_denv; +} + +Word16 calc_nor_delta_hf_fx( + Encoder_State_fx *st, + const Word32 *t_audio, + Word16 *ynrm, + Word16 *Rsubband, + const Word16 num_env_bands, + const Word16 nb_sfm, + const Word16 *sfmsize, + const Word16 *sfm_start, + const Word16 core_sfm +) +{ + Word16 i; + Word16 ynrm_t[44],normqlg2_t[44]; + Word16 delta,max_delta,min_delta,bitsforDelta,add_bits_denv; + Word16 temp_num; + + temp_num=0; + move16(); + + max_delta=-100; + move16(); + calc_norm_fx( t_audio, 12, ynrm_t, normqlg2_t, 0, nb_sfm, sfmsize, sfm_start ); + add_bits_denv = 0; + move16(); + FOR(i=num_env_bands; i 0) + { + delta = add(delta,1); + } + ELSE + { + delta = negate(delta); + } + if (GT_16(delta,max_delta)) + { + max_delta = delta; + move16(); + } + } + } + IF (GE_16(core_sfm ,num_env_bands)) + { + IF (LT_16(max_delta, 16)) + { + bitsforDelta = 2; + move16(); + FOR( ; max_delta >= 2; max_delta >>= 1 ) + { + bitsforDelta = add(bitsforDelta,1); + } + } + ELSE + { + bitsforDelta = 5; + move16(); + } + max_delta = sub( shl(1, sub(bitsforDelta,1)), 1); + min_delta = negate(add(max_delta,1)); + + /* updating norm & storing delta norm */ + add_bits_denv = 2; + move16(); + push_indice_fx( st, IND_DELTA_ENV_HQ, sub(bitsforDelta,2) , 2 ); + FOR(i=num_env_bands; i0) + { + exp = norm_s(total_bit); + tmp = shl(total_bit,exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp) */ + L_tmp = L_mult(tmp, bitalloc_var_fx); /*Q(29-exp+1) */ + bitalloc_var_fx = round_fx(L_shl(L_tmp,exp));/*Q14 */ + } + ELSE + { + bitalloc_var_fx = 0; /*Q14 */ + } + /* calculate the peak-average ratio of saturable subbands */ + num = 0; + sharp_fx = 0; + FOR(sfm = last_sfm; sfm >= 8; sfm--) + { + tmp = shl(sfmsize[sfm], 9);/*Q9 */ + tmp = mult( rat_fx[sfm],tmp );/*Q(14+9-15=8) */ + IF(GE_16(shl(R[sfm],8),tmp)) + { + peak_fx = 0; + move16(); + mean_fx = 0; + move16(); + FOR( i = sfm_start[sfm]; i < sfm_end[sfm]; i++ ) + { + fabs_coeff_out_fx = L_abs(L_coeff_out[i]); + mean_fx = L_add(mean_fx, fabs_coeff_out_fx);/*Q12 */ + if(GT_32(fabs_coeff_out_fx, peak_fx)) + { + peak_fx = fabs_coeff_out_fx;/*Q12 */ + move32(); + } + } + + IF(mean_fx != 0) + { + exp = norm_l(mean_fx); + mean_fx = L_shl(mean_fx, exp);/*Q(exp+12) */ + tmp = round_fx(mean_fx);/*Q(exp-4) */ + tmp = div_s(16384,tmp); /*Q(15+14-exp+4 = 33-exp) */ + L_tmp = Mult_32_16(peak_fx, tmp);/*Q(12+33-exp-15 = 30-exp) */ + tmp = shl(sfmsize[sfm], 9);/*Q9 */ + L_tmp = Mult_32_16(L_tmp, tmp);/*Q(30-exp+9-15 = 24-exp) */ + tmp = round_fx(L_shl(L_tmp,exp));/*Q8 */ + sharp_fx = add(sharp_fx,tmp); + } + num = add(num,1); + } + } + test(); + IF(num != 0 && sharp_fx != 0) + { + num = add(num,num); + exp = norm_s(sharp_fx); + sharp_fx = shl(sharp_fx,exp);/*Q(8+exp) */ + tmp = div_s(16384,sharp_fx);/*Q(21-exp) */ + L_tmp = L_mult(num,tmp);/*Q(22-exp) */ + sharp_fx = round_fx(L_shl(L_tmp,add(8,exp)));/*Q14 */ + } + ELSE + { + sharp_fx = 16384; + move16();/*Q14 = 1 */ + } + harm_para_fx = sharp_fx; + move16();/*Q14 */ + + IF(last_sfm == 0) + { + tmp = 0; + move16(); + } + ELSE + { + tmp = div_s(1,last_sfm);/*Q15 */ + } + + L_tmp = L_mult(5,sharp_fx);/*Q15 */ + L_tmp = Mult_32_16(L_tmp,tmp);/*Q15 */ + step_fx = round_fx(L_shl(L_tmp,16));/*Q15 */ + alfa_fx = 20480; + move16();/*Q13 = 2.5 */ + /* fill noise for the insaturable subbands */ + FOR( sfm = 0; sfm < num_sfm; sfm++ ) + { + env_fx = L_deposit_l(0); + L_tmp2 =L_deposit_l(0); + exp = 0; + move16(); + test(); + IF(R[sfm] != 0 && LT_16(R[sfm], shl(mult(24756,sfmsize[sfm]),1))) + { + /* calculate the energy of the undecoded coefficients */ + env_fx =L_deposit_l(0); + exp1=norm_l(L_normq_v[sfm]); + L_tmp4 = L_shl(L_normq_v[sfm],exp1); /*14+exp1 */ + L_tmp1 = Mult_32_32(L_tmp4,L_tmp4); /*2*exp1-3 14+exp1+14+exp1 -31 */ + L_tmp2 =L_deposit_l(0); + peak_fx = L_deposit_l(0); + min_coef_fx = 0x7fffffff; + move32(); + + FOR (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + fabs_coeff_out_fx = L_abs(L_coeff_out[i]); + test(); + if(LT_32(fabs_coeff_out_fx, min_coef_fx)&&L_coeff_out[i]!=0) + { + min_coef_fx = fabs_coeff_out_fx; + move32(); + } + if(GT_32(fabs_coeff_out_fx,peak_fx)) + { + peak_fx = fabs_coeff_out_fx; + move32(); + } + } + + exp2 =norm_l(peak_fx); + FOR (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + L_tmp4 = L_shl(L_coeff_out[i],exp2); /*12+exp2 */ + L_tmp3 = L_shr(Mult_32_32(L_tmp4,L_tmp4),4);/*2*exp2-7-4 12+exp2+12+exp2-31-4 */ + L_tmp2 = L_add(L_tmp2 ,L_tmp3); /*2*exp2-11 */ + } + + tmp1 =div_s(1,sfmsize[sfm]); /*15 */ + L_tmp4 = Mult_32_16(L_tmp2,tmp1);/*2*exp2-11 2*exp2-7+15+1-16 */ + + exp =norm_l(L_tmp1); + L_tmp1 = L_shl(L_tmp1,exp);/*exp + 2*exp1 - 3 */ + exp1 =sub(add(exp,shl(exp1,1)),3); + + exp =norm_l(L_tmp4); + L_tmp4 = L_shl(L_tmp4,exp);/*exp + 2*exp1 - 3 */ + exp2 =sub(add(exp,shl(exp2,1)),11); + exp = s_min(exp1,exp2); + + L_tmp1 = L_shl(L_tmp1,sub(exp,exp1)); + L_tmp4 = L_shl(L_tmp4,sub(exp,exp2)); + env_fx= L_sub(L_tmp1,L_tmp4); /*exp */ + exp1 = norm_l(env_fx); + env_fx = L_shl(env_fx,exp1);/*exp + exp1 */ + exp =add(exp,exp1); + + IF (env_fx > 0 ) + { + IF(sfm == 0) + { + avrg_norm_fx = L_add(L_shr(L_normq_v[0],1),L_shr(L_normq_v[1],1));/*13 */ + avrg_norm_fx = L_add(avrg_norm_fx,L_shr(L_normq_v[2],1));/*13 */ + prev_avrg_norm_fx = L_add(L_shr(prev_normq_fx[0],1),L_shr(prev_normq_fx[1],1));/*13 */ + prev_avrg_norm_fx = L_add(prev_avrg_norm_fx,L_shr(prev_normq_fx[2],1));/*13 */ + } + ELSE IF (EQ_16(sfm,25)) + { + avrg_norm_fx = L_add(L_shr(L_normq_v[23],1),L_shr(L_normq_v[24],1));/*13 */ + avrg_norm_fx = L_add(avrg_norm_fx,L_shr(L_normq_v[25],1));/*13 */ + prev_avrg_norm_fx = L_add(L_shr(prev_normq_fx[23],1),L_shr(prev_normq_fx[24],1));/*13 */ + prev_avrg_norm_fx = L_add(prev_avrg_norm_fx,L_shr(prev_normq_fx[25],1));/*13 */ + } + ELSE + { + avrg_norm_fx = L_add(L_shr(L_normq_v[sub(sfm,1)],1),L_shr(L_normq_v[sfm],1));/*13 */ + avrg_norm_fx = L_add(avrg_norm_fx,L_shr(L_normq_v[sfm+1],1));/*13 */ + prev_avrg_norm_fx = L_add(L_shr(prev_normq_fx[sub(sfm,1)],1),L_shr(prev_normq_fx[sfm],1));/*13 */ + prev_avrg_norm_fx = L_add(prev_avrg_norm_fx,L_shr(prev_normq_fx[add(sfm,1)],1));/*13 */ + } + + test(); + test(); + IF((GT_16(bitalloc_var_fx,4915)||LT_32(L_normq_v[sfm],peak_fx))&&peak_fx!=0) + { + Word16 exp_p; + exp_p =norm_l(peak_fx); + exp =sub(31,exp); + env_fx = Isqrt_lc(env_fx, &exp); + L_tmp1 = Mult_32_32(env_fx, L_shl(peak_fx, exp_p));/*12+exp2-exp 31-exp+12+exp1-31 */ + L_tmp2 = Mult_32_16(avrg_norm_fx,harm_para_fx);/*12 13 + 14 + 1 -16 */ + exp1 = norm_l(L_tmp1); + L_tmp1 = L_shl(L_tmp1,exp1);/* 12+exp2-exp+exp1 */ + exp = add(sub(12,exp), add(exp1, exp_p)); + L_tmp2 = Div_32(L_tmp2, extract_h(L_tmp1), extract_l(L_tmp1)); + exp=sub(43,exp); + } + ELSE + { + L_tmp1 = Mult_32_16(L_normq_v[sfm],alfa_fx);/*12 13 + 14 + 1 -16 */ + IF(LT_32(L_tmp1,peak_fx)) + { + exp=sub(31,exp); + env_fx = Isqrt_lc(env_fx,&exp); + exp1 = norm_l(env_fx); + env_fx = L_shl(env_fx,exp1);/* 31-exp+exp1 */ + exp = add(sub(31,exp),exp1); + L_tmp1 = (Word32)sharp_fx; + L_tmp2 = Div_32(L_tmp1, extract_h(env_fx), extract_l(env_fx)); /* 45-exp 14 - exp + 31 //39-exp 8 - exp + 31 */ + exp = sub(45,exp); + exp1 = norm_l(peak_fx); + L_tmp1 = L_shl(peak_fx,exp1); /*12 + exp1 */ + L_tmp1 = Div_32(L_tmp2,extract_h(L_tmp1), extract_l(L_tmp1)); /* exp - (12 + exp1) +31 */ + L_tmp2 = Mult_32_32(L_tmp2,L_tmp1);/*2*exp+exp1-12 exp +exp - (12 + exp1) +31 - 31 */ + exp = sub(add(shl(exp,1),exp1),12); + } + ELSE + { + exp = sub(31,exp); + env_fx = Isqrt_lc(env_fx,&exp); + exp1 = norm_l(env_fx); + env_fx =L_shl(env_fx,exp1);/* 31-exp+exp1 */ + exp = add(sub(31,exp),exp1); + L_tmp1=(Word32)(sharp_fx); + L_tmp2 = Div_32(L_tmp1, extract_h(env_fx), extract_l(env_fx)); /* 45-exp 14 - exp + 31 //39-exp 8 - exp + 31 */ + exp =sub(45,exp); + } + + sharp_fx = add(sharp_fx,shr(step_fx,1)); + } + + IF(GT_32(L_tmp2,L_shl(min_coef_fx,sub(exp,13))))/*exp */ + { + L_tmp2 = L_shr(min_coef_fx,1); + exp = 12; + move16(); + } + + IF(EQ_16(prev_bfi,1)) + { + prev_env_Q[sfm] = exp; + move16(); + prev_env_fx[sfm] = L_tmp2; + move32(); + } + /* smooth the noise magnitudes between inter-frame */ + test(); + test(); + IF(GT_32(prev_avrg_norm_fx,L_shr(avrg_norm_fx,1))&<_32(prev_avrg_norm_fx,L_shl(avrg_norm_fx,1))&&prev_is_transient==0) + { + exp1 =norm_l(prev_env_fx[sfm]); + L_tmp1 = L_shl(prev_env_fx[sfm],exp1);/* prev_env_Q[sfm] +exp1 */ + + exp2= norm_l(L_tmp2); + L_tmp3 = L_shl(L_tmp2,exp2);/* exp +exp2 */ + exp3 = s_min(add(prev_env_Q[sfm],exp1),add(exp,exp2)); + + L_tmp1 = L_shl(L_tmp1,sub(sub(exp3,prev_env_Q[sfm]),exp1)); /*exp3 */ + L_tmp3 = L_shl(L_tmp3,sub(sub(exp3,exp),exp2)); /*exp3 */ + L_tmp2 = L_add(L_shr(L_tmp1,1),L_shr(L_tmp3,1));/*exp3 */ + exp = exp3; + move16(); + } + FOR (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + IF (coeff_fx[i] == 0) + { + tmp1 = Random(bwe_seed);/*Q15 */ + L_tmp1= Mult_32_16(L_tmp2,tmp1);/*exp exp+15+1 -16 */ + L_tmp1 = L_shl(L_tmp1,sub(12,exp)); + L_coeff_out[i] = L_tmp1; + move32(); + } + } + } + ELSE + { + exp =0; + move16(); + L_tmp2 =L_deposit_l(0); + } + } + ELSE IF(R[sfm] == 0) + { + /* fill random noise for 0 bit subbands */ + FOR (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + IF(coeff_fx[i] == 0) + { + tmp1 =Random(bwe_seed);/*Q15 */ + L_tmp1= Mult_32_16(L_normq_v[sfm],tmp1);/*14 14+15+1 -16 */ + L_tmp1 = L_shr(L_tmp1,2);/* */ + L_coeff_out[i] = L_tmp1; + move32(); + } + } + L_tmp2 = L_normq_v[sfm]; + move32(); + exp = 14; + move16(); + } + + test(); + test(); + test(); + test(); + IF(EQ_16(sfm,sub(SFM_N_WB,1))&&prev_is_transient==0&>_32(prev_normq_fx[sfm],L_shr(L_normq_v[sfm],1)) + && LT_32(prev_normq_fx[sfm],L_shl(L_normq_v[sfm],1)) && LE_16(bitalloc_var_fx,4915)) + { + Word32 *p_prev_coeff_out = prev_coeff_out_fx; + FOR (i = add(sfm_start[sfm],12); i < sfm_end[sfm]; i++) + { + test(); + test(); + test(); + test(); + IF(GT_32(L_abs(L_coeff_out[i]),L_shl(L_abs(*p_prev_coeff_out),2)) + || LT_32(L_abs(L_coeff_out[i]),L_shr(L_abs(*p_prev_coeff_out),2)) + || ((R[sfm] == 0 || *prev_R == 0) && add(R[sfm], *prev_R) != 0)) + { + L_tmp = L_add(L_shr(L_abs(L_coeff_out[i]),1),L_shr(L_abs(*p_prev_coeff_out),1)); + + if(L_coeff_out[i] <= 0 ) + { + L_tmp = L_negate(L_tmp); + } + L_coeff_out[i] = L_tmp; + move32(); + } + p_prev_coeff_out++; + } + } + prev_env_Q[sfm] = exp; + move16(); + prev_env_fx[sfm] = L_tmp2; + move32(); + } + } + ELSE + { + /* fill random noise for 0 bit subbands of transient frame */ + FOR(sfm = 0; sfm < num_sfm; sfm++) + { + IF( R[sfm] == 0 ) + { + FOR (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + tmp1 =Random(bwe_seed);/*Q15 */ + L_tmp1= Mult_32_16(L_normq_v[sfm],tmp1);/*14 14+15+1 -16 */ + L_tmp1 =L_shr(L_tmp1,2);/* */ + L_coeff_out[i] = L_tmp1; + move32(); + } + } + } + set16_fx( prev_env_Q, 0, SFM_N_WB ); + set32_fx( prev_env_fx, 0, SFM_N_WB ); + } + + Copy32(L_normq_v,prev_normq_fx,SFM_N_WB); + Copy32( L_coeff_out + L_FRAME16k - L_HQ_WB_BWE, prev_coeff_out_fx, L_HQ_WB_BWE ); + *prev_R = R[SFM_N_WB-1]; + + return; +} + +/*--------------------------------------------------------------------------* + * enforce_zero_for_min_envelope_fx() + * + * Detect minimum level of envelope and set corresponding bands to zero + *--------------------------------------------------------------------------*/ + +void enforce_zero_for_min_envelope_fx( + const Word16 hqswb_clas, /* i : HQ coding mode Q0 */ + const Word16 *ynrm, /* i : Envelope indices Q0 */ + Word32 *L_coefsq, /* i/o: Quantized spectrum/zeroed spectrum Q12 */ + const Word16 nb_sfm, /* i : Number of coded sub bands Q0 */ + const Word16 *sfm_start, /* i : Sub band start indices Q0 */ + const Word16 *sfm_end /* i : Sub band end indices Q0 */ +) +{ + Word16 i, j; + + /* prevent non-zero output for all-zero input */ + IF( NE_16(hqswb_clas,HQ_HVQ)) + { + IF( EQ_16(ynrm[0], 31)) + { + FOR( j = sfm_start[0]; j < sfm_end[0]; j++ ) + { + L_coefsq[j] = L_deposit_l(0); + } + } + + FOR( i = 1; i < nb_sfm; i++ ) + { + IF( EQ_16(ynrm[i], 39)) + { + FOR( j = sfm_start[i]; j < sfm_end[i]; j++ ) + { + L_coefsq[j] = L_deposit_l(0); + } + } + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * apply_envelope() + * + * Apply spectral envelope with envelope adjustments + *--------------------------------------------------------------------------*/ + +void apply_envelope_fx( + const Word16 *coeff, /* i/o: Coded/noisefilled normalized spectrum Q12 */ + const Word16 *norm, /* i : Envelope Q0 */ + const Word16 *norm_adj, /* i : Envelope adjustment Q15 */ + const Word16 num_sfm, /* i : Total number of bands Q0 */ + const Word16 last_sfm, /* i : Last coded band Q0 */ + const Word16 HQ_mode, /* i : HQ mode Q0 */ + const Word16 length, /* i : Frame length Q0 */ + const Word16 *sfm_start, /* i : Sub band start indices Q0 */ + const Word16 *sfm_end, /* i : Sub band end indices Q0 */ + Word32 *normq_v, /* o : Envelope with adjustment Q14 */ + Word32 *coeff_out, /* o : coded/noisefilled spectrum Q12 */ + const Word16 *coeff1, /* i : coded/noisefilled spectrum Q12 */ + Word32 *coeff_out1 /* o : coded/noisefilled spectrum Q12 */ +) +{ + Word16 i; + Word16 sfm; + UWord16 lsb; + Word32 normq; + Word32 L_tmp; + Word16 len; + + len = num_sfm; + move16(); + test(); + if( EQ_16(HQ_mode, HQ_GEN_SWB)||EQ_16(HQ_mode,HQ_GEN_FB)) + { + len = add(last_sfm, 1); + } + + IF( EQ_16(length, L_FRAME16k)) + { + FOR (sfm = 0; sfm < num_sfm; sfm++) + { + normq_v[sfm] = dicn_fx[norm[sfm]]; + move16(); + move32(); + /*normq = normq_v[sfm] * norm_adj[sfm]; */ + Mpy_32_16_ss(normq_v[sfm], norm_adj[sfm], &normq, &lsb); /* Q14 (14+15+1-16) */ + + FOR (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + /*coeff_out[i] = coeff[i]*normq; */ + Mpy_32_16_ss(normq, coeff[i], &L_tmp, &lsb); + coeff_out[i] = L_add(L_shl(L_tmp, 1), lshr(lsb, 15)); + move32(); /* Q12 (14+12+1-16)+1 */ + } + } + } + ELSE + { + FOR (sfm = 0; sfm < len; sfm++) + { + normq_v[sfm] = dicn_fx[norm[sfm]]; + move16(); + move32(); + /*normq_v[sfm] *= norm_adj[sfm]; */ + Mpy_32_16_ss(normq_v[sfm], norm_adj[sfm], &normq_v[sfm], &lsb); + move32(); /* Q14 (14+15+1-16) */ + + normq = normq_v[sfm]; + move32(); + FOR (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + /*coeff_out[i] = coeff[i]*normq; */ + Mpy_32_16_ss(normq, coeff[i], &L_tmp, &lsb); + coeff_out[i] = L_add(L_shl(L_tmp, 1), lshr(lsb, 15)); + move32(); /* Q12 (14+12+1-16)+1 */ + } + } + + test(); + IF ( EQ_16(HQ_mode, HQ_GEN_SWB)||EQ_16(HQ_mode,HQ_GEN_FB)) + { + FOR (sfm = 0; sfm <= last_sfm; sfm++) + { + normq = normq_v[sfm]; + move32(); + FOR (i = sfm_start[sfm]; i < sfm_end[sfm]; i++) + { + /*coeff_out1[i] = coeff_out1[i]*normq; */ + Mpy_32_16_ss(normq, coeff1[i], &L_tmp, &lsb); + coeff_out1[i] = L_add(L_shl(L_tmp, 1), lshr(lsb, 15)); + move32(); /* Q12 (14+12+1-16)+1 */ + } + } + } + } + + + return; +} + + diff --git a/lib_com/hvq_pvq_bitalloc_fx.c b/lib_com/hvq_pvq_bitalloc_fx.c new file mode 100644 index 0000000..6d21a77 --- /dev/null +++ b/lib_com/hvq_pvq_bitalloc_fx.c @@ -0,0 +1,191 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "stl.h" /* required by wmc_tool */ + +#include "rom_com_fx.h" + +#include "prot_fx.h" /* Function prototypes */ +#include "cnst_fx.h" /* Common constants */ + +/*--------------------------------------------------------------------------*/ +/* Function hvq_pvq_bitalloc */ +/* ~~~~~~~~~~~~~~~~~~~~~~~~ */ +/* */ +/* Calculate the number of PVQ bands to code and allocate bits based on */ +/* the number of available bits. */ +/*--------------------------------------------------------------------------*/ + +Word16 hvq_pvq_bitalloc_fx( + Word16 num_bits, /* i/o: Number of available bits (including gain bits) */ + const Word32 brate, /* i : bitrate */ + const Word16 bwidth_fx, /* i : Encoded bandwidth */ + const Word16 *ynrm, /* i : Envelope coefficients */ + const Word32 manE_peak, /* i : Peak energy mantissa */ + const Word16 expE_peak, /* i : Peak energy exponent */ + Word16 *Rk, /* o : bit allocation for concatenated vector */ + Word16 *R, /* i/o: Global bit allocation */ + Word16 *sel_bands, /* o : Selected bands for encoding */ + Word16 *n_sel_bands /* o : No. of selected bands for encoding */ +) +{ + Word16 num_bands, band_max_bits; + Word16 one_over_band_max_bits; + Word16 k; + Word16 reciprocal, envSum, expo, align, m, n, indx; + Word16 k_max; + Word16 k_start; + Word32 E_max, E_max5; + Word32 tmp, acc; + Word32 env_mean; + UWord16 lsb; + Word16 num_sfm; + + IF (EQ_16(bwidth_fx, FB)) + { + num_sfm = SFM_N_HARM_FB; + } + ELSE + { + num_sfm = SFM_N_HARM; + } + + IF ( EQ_32(brate, HQ_24k40)) + { + band_max_bits = HVQ_BAND_MAX_BITS_24k; + move16(); + one_over_band_max_bits = ONE_OVER_HVQ_BAND_MAX_BITS_24k_FX; + move16(); + k_start = HVQ_THRES_SFM_24k; + move16(); + IF (EQ_16(bwidth_fx, FB)) + { + reciprocal = 2731; /* Q15, 1/(SFM_N_HARM_FB + 1 - k_start) */ move16(); + } + ELSE + { + reciprocal = 3277; /* Q15, 1/(SFM_N_HARM + 1 - k_start) */ move16(); + } + } + ELSE + { + band_max_bits = HVQ_BAND_MAX_BITS_32k; + move16(); + one_over_band_max_bits = ONE_OVER_HVQ_BAND_MAX_BITS_32k_FX; + move16(); + k_start = HVQ_THRES_SFM_32k; + move16(); + IF (EQ_16(bwidth_fx, FB)) + { + reciprocal = 3641; /* Q15, 1/(SFM_N_HARM_FB + 1 - k_start) */ move16(); + } + ELSE + { + reciprocal = 4681; /* Q15, 1/(SFM_N_HARM + 1 - k_start) */ move16(); + } + } + + num_bands = mult( num_bits, one_over_band_max_bits ); /* Q0 */ + num_bits = sub( num_bits, i_mult(num_bands, band_max_bits) ); /* Q0 */ + + IF ( GE_16(num_bits, HVQ_NEW_BAND_BIT_THR)) + { + num_bands = add(num_bands, 1); + } + ELSE + { + num_bits = add(num_bits, band_max_bits); + } + + /* safety check in case of bit errors */ + if (LT_16(num_bands, 1)) + { + return 0; + } + + *n_sel_bands = 0; + move16(); + envSum = 0; + move16(); + E_max = L_deposit_l(0); + k_max = k_start; + move16(); + FOR ( k = k_start; k < num_sfm; k++ ) + { + indx = ynrm[k]; + move16(); + tmp = dicn_fx[indx]; /* Q14 */ + move32(); + envSum = add(envSum, indx); /* Since the size of dicn_fx = 40, ynrm[k] must be less than 41. 16 bits are enough for envSum.*/ + IF (GT_32(tmp, E_max)) + { + E_max = tmp; + move32(); + k_max = k; + move16(); + } + } + env_mean = L_mult(envSum, reciprocal); /* env_mean in Q16 */ + IF (GT_32(L_sub(env_mean, L_deposit_h(ynrm[k_max])), 0x30000L)) /* condition: env_mean - ynrm[k_max] > 3 */ + { + expo = norm_l(E_max); + E_max = L_shl(E_max, expo); + Mpy_32_16_ss(E_max, 0x7a12, &E_max5, &lsb); /* NB: 5.0e5 = 0x7a12(Q15) x 2^19. */ + /* True floating point value of E_max*5e5 = E_max5 x 2^(19 - expo - 14). + * In this context, the 32-bit E_max5 is in Q0, and + * -14 is due to Emax in Q14. + * True floating point value of E_peak = manE_peak x 2^(31 - expE_peak - 2*12). See peak_vq_enc_fx(). + */ + + /* Align the Q-points of the floating point Emax*5e5 and E_peak. */ + align = sub(expo, expE_peak); + align = add(align, (19 - 14) - (31 - 2*12)); + IF (align < 0) + { + acc = L_sub(E_max5, L_shl(manE_peak, align)); + } + ELSE + { + acc = L_sub(L_shr(E_max5, align), manE_peak); + } + + IF (acc > 0) /* condition: E_max*5.e5 > E_peak */ + { + IF ( EQ_16(band_len_harm[k_max], 96)) + { + n = 61; + } + ELSE + { + QuantaPerDsDirac_fx(band_len_harm[k_max], 1, hBitsN, &n); + } + m = shl(sub(num_bits, HVQ_PVQ_GAIN_BITS), 3); + IF (GE_16(m, n)) + { + IF (GT_16(num_bands, 1)) /* condition: num_bands > 1 */ + { + sel_bands[*n_sel_bands] = k_max; + move16(); + *n_sel_bands = add(*n_sel_bands, 1); + R[k_max] = 1; /* Mark that the band has been encoded for fill_spectrum */ move16(); + } + } + } + } + + /* Allocate bits */ + tmp = sub(num_bands,1); + FOR (k = 0; k < tmp; k++) + { + Rk[k] = shl(sub(band_max_bits, HVQ_PVQ_GAIN_BITS), 3); + move16(); + } + /* NB: When it exits the above loop, k = num_bands - 1. */ + Rk[k] = shl(sub(num_bits, HVQ_PVQ_GAIN_BITS), 3); + move16(); + + return num_bands; +} + diff --git a/lib_com/igf_base.c b/lib_com/igf_base.c new file mode 100644 index 0000000..3c799c5 --- /dev/null +++ b/lib_com/igf_base.c @@ -0,0 +1,936 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include +#include "options.h" +#include "stl.h" +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "basop_util.h" + +/**********************************************************************/ /* +returns an int val, multiplied with transFac +**************************************************************************/ +static Word16 IGF_ApplyTransFac( /**< out: Q0 | multiplication factor */ + const Word16 val, /**< in: Q15 | input value for multiplication, Q15 */ + const Word16 transFac /**< in: Q14 | multiplicator for variable val, Q14: 1.25f=0x5000, 1.0f=0x4000, 0.5f=0x2000 */ +) +{ + Word16 ret; + + if(EQ_16(transFac, 0x4000)) + { + return val; + } + + ret = shl(val, 1); + ret = mac_r(0x00000000, ret, transFac); + ret = add(ret, s_and(ret, 1)); + + + return ret; +} + +/**********************************************************************/ /* +maps a given bitrate to the IGF_BITRATE index +**************************************************************************/ +static Word16 IGF_MapBitRateToIndex( /**< out: Q0 | return bit rate index */ + Word32 bitRate, /**< in: | bitrate */ + Word16 mode /**< in: | bandwidth mode */ + , Word16 rf_mode /**< in: | flag to signal the RF mode */ +) +{ + Word16 bitRateIndex; + + + bitRateIndex = IGF_BITRATE_UNKNOWN; + move16(); + + switch (mode) + { + case IGF_MODE_WB: + switch (bitRate) + { + case 13200: + if (EQ_16(rf_mode,1)) + { + bitRateIndex = IGF_BITRATE_RF_WB_13200; + } + break; + case 9600: + bitRateIndex = IGF_BITRATE_WB_9600; + break; + default: + assert(0); + } + break; + case IGF_MODE_SWB: + switch (bitRate) + { + case 9600: + bitRateIndex = IGF_BITRATE_SWB_9600; + break; + case 13200: + bitRateIndex = IGF_BITRATE_SWB_13200; + if (EQ_16(rf_mode,1)) + { + bitRateIndex = IGF_BITRATE_RF_SWB_13200; + } + break; + case 16400: + bitRateIndex = IGF_BITRATE_SWB_16400; + break; + case 24400: + bitRateIndex = IGF_BITRATE_SWB_24400; + break; + case 32000: + bitRateIndex = IGF_BITRATE_SWB_32000; + break; + case 48000: + bitRateIndex = IGF_BITRATE_SWB_48000; + break; + default: + assert(0); + } + break; + case IGF_MODE_FB: + switch (bitRate) + { + case 16400: + bitRateIndex = IGF_BITRATE_FB_16400; + break; + case 24400: + bitRateIndex = IGF_BITRATE_FB_24400; + break; + case 32000: + bitRateIndex = IGF_BITRATE_FB_32000; + break; + case 48000: + bitRateIndex = IGF_BITRATE_FB_48000; + break; + case 96000: + bitRateIndex = IGF_BITRATE_FB_96000; + break; + case 128000: + bitRateIndex = IGF_BITRATE_FB_128000; + break; + default: + assert(0); + } + break; + default: + assert(0); + } + + return bitRateIndex; +} + +/**********************************************************************/ /* +IGF grid setup +**************************************************************************/ +static void IGF_gridSetUp(H_IGF_GRID hGrid, /**< out: | IGF grid handle */ + Word16 bitRateIndex, /**< in: Q0 | IGF bitrate index */ + Word32 sampleRate, /**< in: | sample rate */ + Word16 frameLength, /**< in: | frame length */ + Word16 transFac, /**< in: | transFac */ + Word16 igfMinFq /**< in: | IGF minimum frequency indicating lower start frequency for copy up */ + ) +{ + Word16 t; + Word16 sfb; + const Word16 *swb_offset; + Word16 swb_offset_len; + Word16 bandwidth; + Word16 wrp_sfb; + Word16 tmp1; + Word16 tmp2; + Word32 L_tmp1; + Word32 L_tmp2; + + swb_offset = NULL; + move16(); + swb_offset_len = 0; + move16(); + + SWITCH (bitRateIndex) + { + case IGF_BITRATE_WB_9600: + case IGF_BITRATE_SWB_9600: + case IGF_BITRATE_RF_WB_13200: + case IGF_BITRATE_RF_SWB_13200: + case IGF_BITRATE_SWB_13200: + case IGF_BITRATE_SWB_16400: + case IGF_BITRATE_SWB_24400: + case IGF_BITRATE_SWB_32000: + case IGF_BITRATE_SWB_48000: + swb_offset = &swb_offset_LB_new[bitRateIndex][1]; + swb_offset_len = swb_offset_LB_new[bitRateIndex][0]; + move16(); + Copy(&igf_whitening_TH[bitRateIndex][0][0], &hGrid->whiteningThreshold[0][0], IGF_MAX_TILES * 2); + BREAK; + case IGF_BITRATE_FB_16400: + case IGF_BITRATE_FB_24400: + case IGF_BITRATE_FB_32000: + swb_offset = &swb_offset_LB_new[bitRateIndex][1]; + swb_offset_len = swb_offset_LB_new[bitRateIndex][0]; + move16(); + Copy(&igf_whitening_TH[bitRateIndex][0][0], &hGrid->whiteningThreshold[0][0], IGF_MAX_TILES * 2); + BREAK; + case IGF_BITRATE_FB_48000: + case IGF_BITRATE_FB_96000: + case IGF_BITRATE_FB_128000: + swb_offset = &swb_offset_LB_new[bitRateIndex][1]; + swb_offset_len = swb_offset_LB_new[bitRateIndex][0]; + move16(); + Copy(&igf_whitening_TH[bitRateIndex][0][0], &hGrid->whiteningThreshold[0][0], IGF_MAX_TILES * 2); + BREAK; + case IGF_BITRATE_UNKNOWN: + default: + assert(0); + } + + FOR(sfb = 0; sfb < swb_offset_len; sfb++) + { + hGrid->swb_offset[sfb] = IGF_ApplyTransFac(swb_offset[sfb], transFac); + move16(); + } + + hGrid->infoIsRefined = 0; + move16(); + frameLength = IGF_ApplyTransFac(frameLength, transFac); + tmp2 = norm_s(frameLength); + bandwidth = shl(frameLength,tmp2); + hGrid->swb_offset_len = extract_l(L_shr(sampleRate, 2)); + tmp1 = sub(norm_s(hGrid->swb_offset_len), 1); + hGrid->swb_offset_len = shl(hGrid->swb_offset_len, tmp1); + bandwidth = div_s(hGrid->swb_offset_len, bandwidth); + tmp2 = sub(add(tmp2, 1), tmp1); + bandwidth = shr(bandwidth, sub(15, tmp2)); + + + hGrid->swb_offset_len = swb_offset_len; + move16(); + hGrid->startSfb = 0; + move16(); + hGrid->stopSfb = sub(hGrid->swb_offset_len, 1); + hGrid->startLine = hGrid->swb_offset[ hGrid->startSfb ]; + move16(); + hGrid->stopLine = hGrid->swb_offset[ hGrid->stopSfb ]; + move16(); + hGrid->startFrequency = imult1616(bandwidth, hGrid->startLine); + hGrid->stopFrequency = imult1616(bandwidth, hGrid->stopLine); + + L_tmp1 = L_mult0(igfMinFq, frameLength); + tmp1 = sub(norm_l(L_tmp1), 1); + L_tmp1 = L_shl(L_tmp1, tmp1); + + tmp2 = norm_l(sampleRate); + L_tmp2 = L_shl(sampleRate, tmp2); + tmp1 = add(WORD16_BITS-1, sub(tmp1, add(tmp2, 1))); /* takes into account sampleRate >> 1 */ + + hGrid->minSrcSubband = div_s(extract_h(L_tmp1), extract_h(L_tmp2)); + hGrid->minSrcSubband = shr(hGrid->minSrcSubband, tmp1); + + + hGrid->minSrcSubband = add(hGrid->minSrcSubband, s_and(hGrid->minSrcSubband, 1)); + hGrid->minSrcFrequency = imult1616(bandwidth, hGrid->minSrcSubband); + hGrid->infoGranuleLen = frameLength; + move16(); + hGrid->infoTransFac = transFac; + move16(); + + hGrid->sfbWrap[0] = 0; + move16(); + hGrid->tile[0] = hGrid->startLine; + move16(); + + + /*************************************************************************/ + SWITCH (bitRateIndex) + { + /* SWB 13200 */ + case IGF_BITRATE_WB_9600: + hGrid->nTiles = 2; + move16(); + wrp_sfb = 2; + move16(); + + /*1st*/ + hGrid->sfbWrap[0+1] = wrp_sfb; + move16(); + hGrid->sbWrap[0] = hGrid->minSrcSubband; + move16(); + hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb]; + move16(); + + /*2nd*/ + hGrid->sfbWrap[1+1] = hGrid->stopSfb; + move16(); + hGrid->sbWrap[1] = hGrid->minSrcSubband; + move16(); + hGrid->tile[1+1] = hGrid->swb_offset[hGrid->stopSfb]; + move16(); + BREAK; + + case IGF_BITRATE_RF_WB_13200: + hGrid->nTiles = 2; + wrp_sfb = 2; + + /*1st*/ + hGrid->sfbWrap[0+1] = wrp_sfb; + hGrid->sbWrap[0] = hGrid->minSrcSubband; + hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb]; + + /*2nd*/ + hGrid->sfbWrap[1+1] = hGrid->stopSfb; + hGrid->sbWrap[1] = hGrid->minSrcSubband; + hGrid->tile[1+1] = hGrid->swb_offset[hGrid->stopSfb]; + + BREAK; + case IGF_BITRATE_SWB_9600: + hGrid->nTiles = 3; + wrp_sfb = 1; + + /*1st*/ + hGrid->sfbWrap[0+1] = wrp_sfb; + hGrid->sbWrap[0] = hGrid->minSrcSubband; + hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb]; + + /*2nd*/ + wrp_sfb = 2; + hGrid->sfbWrap[1+1] = wrp_sfb; + hGrid->sbWrap[1] = hGrid->minSrcSubband + IGF_ApplyTransFac(32, transFac); + hGrid->tile[1+1] = hGrid->swb_offset[wrp_sfb]; + + /*3rd*/ + hGrid->sfbWrap[2+1] = hGrid->stopSfb; + hGrid->sbWrap[2] = hGrid->minSrcSubband + IGF_ApplyTransFac(46, transFac); + hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb]; + + BREAK; + case IGF_BITRATE_RF_SWB_13200: + hGrid->nTiles = 3; + wrp_sfb = 1; + + /*1st*/ + hGrid->sfbWrap[0+1] = wrp_sfb; + hGrid->sbWrap[0] = hGrid->minSrcSubband; + hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb]; + + /*2nd*/ + wrp_sfb = 2; + hGrid->sfbWrap[1+1] = wrp_sfb; + hGrid->sbWrap[1] = hGrid->minSrcSubband + IGF_ApplyTransFac(32, transFac); + hGrid->tile[1+1] = hGrid->swb_offset[wrp_sfb]; + + /*3rd*/ + hGrid->sfbWrap[2+1] = hGrid->stopSfb; + hGrid->sbWrap[2] = hGrid->minSrcSubband + IGF_ApplyTransFac(46, transFac); + hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb]; + + BREAK; + + case IGF_BITRATE_SWB_13200: + hGrid->nTiles = 2; + move16(); + wrp_sfb = 4; + move16(); + + /*1st*/ + hGrid->sfbWrap[0+1] = wrp_sfb; + move16(); + hGrid->sbWrap[0] = hGrid->minSrcSubband; + move16(); + hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb]; + move16(); + + /*2nd*/ + hGrid->sfbWrap[1+1] = hGrid->stopSfb; + move16(); + hGrid->sbWrap[1] = add(hGrid->minSrcSubband, IGF_ApplyTransFac(32, transFac)); + move16(); + hGrid->tile[1+1] = hGrid->swb_offset[hGrid->stopSfb]; + move16(); + BREAK; + + case IGF_BITRATE_SWB_16400: + hGrid->nTiles = 3; + move16(); + wrp_sfb = 4; + move16(); + + /*1st*/ + hGrid->sfbWrap[0+1] = wrp_sfb; + move16(); + hGrid->sbWrap[0] = hGrid->minSrcSubband; + move16(); + hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb]; + move16(); + + /*2nd*/ + hGrid->sfbWrap[1+1] = 6; + move16(); + hGrid->sbWrap[1] = add(hGrid->minSrcSubband, IGF_ApplyTransFac(48, transFac)); + move16(); + hGrid->tile[1+1] = hGrid->swb_offset[6]; + move16(); + + /*3nd*/ + hGrid->sfbWrap[2+1] = hGrid->stopSfb; + move16(); + hGrid->sbWrap[2] = add(hGrid->minSrcSubband, IGF_ApplyTransFac(64, transFac)); + move16(); + hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb]; + move16(); + BREAK; + + case IGF_BITRATE_SWB_24400: + case IGF_BITRATE_SWB_32000: + hGrid->nTiles = 3; + move16(); + wrp_sfb = 4; + move16(); + + /*1st*/ + hGrid->sfbWrap[0+1] = wrp_sfb; + move16(); + hGrid->sbWrap[0] = hGrid->minSrcSubband; + move16(); + hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb]; + move16(); + + /*2nd*/ + hGrid->sfbWrap[1+1] = 7; + move16(); + hGrid->sbWrap[1] = add(hGrid->minSrcSubband, IGF_ApplyTransFac(32, transFac)); + move16(); + hGrid->tile[1+1] = hGrid->swb_offset[7]; + move16(); + + /*3nd*/ + hGrid->sfbWrap[2+1] = hGrid->stopSfb; + move16(); + hGrid->sbWrap[2] = add(hGrid->minSrcSubband, IGF_ApplyTransFac(64, transFac)); + move16(); + hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb]; + move16(); + BREAK; + case IGF_BITRATE_SWB_48000: + hGrid->nTiles = 1; + move16(); + wrp_sfb = hGrid->stopSfb; + move16(); + + /*1st*/ + hGrid->sfbWrap[0+1] = hGrid->stopSfb; + move16(); + hGrid->sbWrap[0] = sub(shl(hGrid->startLine, 1), hGrid->stopLine); + move16(); + hGrid->tile[0+1] = hGrid->swb_offset[hGrid->stopSfb]; + move16(); + + BREAK; + case IGF_BITRATE_FB_16400: + hGrid->nTiles = 3; + move16(); + wrp_sfb = 4; + move16(); + + /*1st*/ + hGrid->sfbWrap[0+1] = wrp_sfb; + move16(); + hGrid->sbWrap[0] = hGrid->minSrcSubband; + move16(); + hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb]; + move16(); + wrp_sfb = 7; + move16(); + + /*2nd*/ + hGrid->sfbWrap[1+1] = wrp_sfb; + move16(); + hGrid->sbWrap[1] = hGrid->minSrcSubband; + move16(); + hGrid->tile[1+1] = hGrid->swb_offset[wrp_sfb]; + move16(); + + /*3nd*/ + hGrid->sfbWrap[2+1] = hGrid->stopSfb; + move16(); + hGrid->sbWrap[2] = hGrid->minSrcSubband; + move16(); + hGrid->tile[2+1] = hGrid->swb_offset[hGrid->stopSfb]; + move16(); + + BREAK; + + case IGF_BITRATE_FB_24400: + case IGF_BITRATE_FB_32000: + hGrid->nTiles = 4; + move16(); + wrp_sfb = 4; + move16(); + + /*1st*/ + hGrid->sfbWrap[0+1] = wrp_sfb; + move16(); + hGrid->sbWrap[0] = hGrid->minSrcSubband; + move16(); + hGrid->tile[0+1] = hGrid->swb_offset[wrp_sfb]; + move16(); + wrp_sfb = 6; + move16(); + + /*2nd*/ + hGrid->sfbWrap[1+1] = wrp_sfb; + move16(); + hGrid->sbWrap[1] = add(hGrid->minSrcSubband, IGF_ApplyTransFac(32, transFac)); + move16(); + hGrid->tile[1+1] = hGrid->swb_offset[wrp_sfb]; + move16(); + wrp_sfb = 9; + move16(); + + /*3nd*/ + hGrid->sfbWrap[2+1] = wrp_sfb; + move16(); + hGrid->sbWrap[2] = hGrid->minSrcSubband; + move16(); + hGrid->tile[2+1] = hGrid->swb_offset[wrp_sfb]; + move16(); + + /*4nd*/ + hGrid->sfbWrap[3+1] = hGrid->stopSfb; + move16(); + hGrid->sbWrap[3] = add(hGrid->minSrcSubband, sub(hGrid->swb_offset[9], hGrid->swb_offset[8])); + move16(); + hGrid->tile[3+1] = hGrid->swb_offset[hGrid->stopSfb]; + move16(); + BREAK; + case IGF_BITRATE_FB_48000: + case IGF_BITRATE_FB_96000: + case IGF_BITRATE_FB_128000: + hGrid->nTiles = 1; + move16(); + + /*1st*/ + hGrid->sfbWrap[0+1] = hGrid->stopSfb; + move16(); + hGrid->sbWrap[0] = sub(shl(hGrid->startLine, 1), hGrid->stopLine); + move16(); + hGrid->tile[0+1] = hGrid->swb_offset[hGrid->stopSfb]; + move16(); + + BREAK; + default: + assert(0); + }/*switch*/ + + /*************************************************************************/ + /*************************************************************************/ + + + /* adapt level envelope: */ + SWITCH (bitRateIndex) + { + case IGF_BITRATE_RF_WB_13200: + case IGF_BITRATE_WB_9600: + hGrid->gFactor = 13107/*0.80f Q14*/; + move16(); + hGrid->fFactor = 11469/*0.70f Q14*/; + move16(); + hGrid->lFactor = 9830/*0.60f Q14*/; + move16(); + BREAK; + case IGF_BITRATE_SWB_13200: + case IGF_BITRATE_FB_16400: + case IGF_BITRATE_SWB_16400: + hGrid->gFactor = 15237/*0.93f Q14*/; + move16(); + hGrid->fFactor = 3277/*0.20f Q14*/; + move16(); + hGrid->lFactor = 13926/*0.85f Q14*/; + move16(); + BREAK; + case IGF_BITRATE_FB_24400: + case IGF_BITRATE_SWB_24400: + case IGF_BITRATE_FB_32000: + case IGF_BITRATE_SWB_32000: + hGrid->gFactor = 15811/*0.965f Q14*/; + move16(); + hGrid->fFactor = 3277/*0.20f Q14*/; + move16(); + hGrid->lFactor = 13926/*0.85f Q14*/; + move16(); + BREAK; + case IGF_BITRATE_FB_48000: + case IGF_BITRATE_SWB_48000: + hGrid->gFactor = 16384/*1.00f Q14*/; + move16(); + hGrid->fFactor = 3277/*0.20f Q14*/; + move16(); + hGrid->lFactor = 16384/*1.00f Q14*/; + move16(); + BREAK; + case IGF_BITRATE_SWB_9600: + case IGF_BITRATE_RF_SWB_13200: + default: + hGrid->gFactor = 16384/*1.00f Q14*/; + move16(); + hGrid->fFactor = 0/*0.00f Q14*/; + move16(); + hGrid->lFactor = 16384/*1.00f Q14*/; + move16(); + } + + FOR (t = add(hGrid->nTiles, 1); t < IGF_MAX_TILES; t++) + { + hGrid->tile[t] = 0; + move16(); + hGrid->sbWrap[t - 1] = 0; + move16(); + hGrid->sfbWrap[t] = 0; + move16(); + } + +} + +/**********************************************************************/ /* +calculates energy per sfb via power spectrum +**************************************************************************/ +void IGFCommonFuncsCalcSfbEnergyPowerSpec(const Word16 startSfb, /**< in: Q0 | start sfb index */ + const Word16 stopSfb, /**< in: Q0 | stop sfb index */ + const Word16 *swb_offset, /**< in: Q0 | IGF swb offset table */ + Word32 *pPowerSpectrum, /**< in: Q31 | power spectrum */ + Word16 *pPowerSpectrum_exp, /**< in: | Exponent of PowerSpectrum */ + Word32 *sfbEnergy, /**< out:Q31 | SFB energies , will be initialized inside this function */ + Word16 *sfbEnergy_exp /**< out: | Exponent of PowerSpectrum */ + ) +{ + Word16/*Q0*/ sfb; + Word16/*Q0*/ line; + Word32 L_c; + + + FOR (sfb = startSfb; sfb < stopSfb; sfb++) + { + sfbEnergy[sfb] = L_deposit_l(0); + } + IF (NULL == pPowerSpectrum) + { + return; + } + + FOR (sfb = startSfb; sfb < stopSfb; sfb++) + { + L_c = L_deposit_l(0); + FOR (line = swb_offset[sfb]; line < swb_offset[sfb+1]; line++) + { + Carry = 0; + sfbEnergy[sfb] = L_add_c(sfbEnergy[sfb], pPowerSpectrum[line]); + move32(); + Overflow = 0; + L_c = L_macNs(L_c,0,0); + } + sfbEnergy[sfb] = norm_llQ31(L_c,sfbEnergy[sfb],&(sfbEnergy_exp[sfb])); + move32(); + sfbEnergy_exp[sfb] = add(sfbEnergy_exp[sfb],*pPowerSpectrum_exp); + move16(); + } +} + +/**********************************************************************/ /* +calculate the MDCT square spectrum in the IGF range +**************************************************************************/ +void IGFCommonFuncsMDCTSquareSpec(const Word16 sqrtBgn, /**< in: Q0 | start MDCT subband index */ + const Word16 sqrtEnd, /**< in: Q0 | stop MDCT subband index */ + const Word32 *mdctSpec, /**< in: Q31 | MDCT spectrum to square */ + const Word16 mdctSpec_e, /**< in: | exponent of mdctSpectrum */ + Word32 *mdctSquareSpec, /**< out:Q31 | MDCT square spectrum */ + Word16 *mdctSquareSpec_e, /**< out: | exponent of mdctSquareSpec */ + Word16 indexOffset /**< in: Q0 | index offset */ + ) +{ + Word16 i; + Word16 j; + Word16 s1; + Word16 tmp; + + + /* get headroom, only in IGF range */ + s1 = getScaleFactor32(mdctSpec + sqrtBgn, sub(sqrtEnd, sqrtBgn)); + + /* set new exponent */ + *mdctSquareSpec_e = add(shl(sub(mdctSpec_e, s1), 1), 1); + move16(); + + /* MDCT square spectrum: MDCT^2 */ + j = add(sqrtBgn, indexOffset); /* handle indexOffset with care, otherwise memory overruns may occur! */ + + + FOR (i = sqrtBgn; i < sqrtEnd; i++) + { + tmp = round_fx(L_shl(mdctSpec[i], s1)); + mdctSquareSpec[j++] = L_mult0(tmp, tmp); + move32(); + } + + +} + +/**********************************************************************/ /* +write bits to stream +**************************************************************************/ +void IGFCommonFuncsWriteSerialBit(void *st, /**< in: | encoder/decoder state structure */ + Word16 *pBitOffset, /**< out: Q0 | bit offset */ + Word16 bit /**< in: Q0 | value of bit */ + ) +{ + + IF (st) + { + push_next_indice_fx(st, bit, 1); + } + *pBitOffset = add(*pBitOffset, 1); + move16(); + + return; +} + +/**********************************************************************/ /* +changes the IGF configuration +**************************************************************************/ +Word16 IGFCommonFuncsIGFConfiguration( /**< out: | error value: 0 -> error, 1 -> ok */ + Word32 bitRate, /**< in: Q0 | bitrate in bs e.g. 9600 for 9.6kbs */ + Word16 mode, /**< in: Q0 | bandwidth mode */ + H_IGF_INFO hIGFInfo /**< out: | IGF info handle */ + ,Word16 rf_mode /**< in: flag to signal the RF mode */ +) +{ + H_IGF_GRID hGrid; + Word16 retValue; + Word32 sampleRate; + Word16 frameLength; + Word16 igfMinFq; + Word16 maxHopsize; + + retValue = 0; /* bitrate index is unknown -> error! */ move16(); + + /* interface call for reading in settings */ + hIGFInfo->bitRateIndex = IGF_MapBitRateToIndex(bitRate, mode + ,rf_mode + ); + + IF (NE_16(hIGFInfo->bitRateIndex, IGF_BITRATE_UNKNOWN)) + { + retValue = 1; /* no error */ move16(); + + /* mapping to local values */ + sampleRate = igfMode[hIGFInfo->bitRateIndex].sampleRate; + move32(); + frameLength = igfMode[hIGFInfo->bitRateIndex].frameLength; + move16(); + igfMinFq = igfMode[hIGFInfo->bitRateIndex].igfMinFq; + move16(); + maxHopsize = igfMode[hIGFInfo->bitRateIndex].maxHopsize; + move16(); + + /* basic information */ + hIGFInfo->sampleRate = sampleRate; + move32(); + hIGFInfo->frameLength = frameLength; + move16(); + hIGFInfo->maxHopsize = maxHopsize; + move16(); + hIGFInfo->nfSeed = 0; + move16(); + + /* set up regular IGF grid for TCX 20 (transfac = 1.f) */ + hGrid = &hIGFInfo->grid[IGF_GRID_LB_NORM]; + IGF_gridSetUp(hGrid, + hIGFInfo->bitRateIndex, + sampleRate, + frameLength, + 16384/*1 Q14*/, + igfMinFq); + + /* set up IGF grid for CELP->TCX 20 transitions (transfac = 1.25) */ + hGrid = &hIGFInfo->grid[IGF_GRID_LB_TRAN]; + IGF_gridSetUp(hGrid, + hIGFInfo->bitRateIndex, + sampleRate, + frameLength, + 20480/*1.25 Q14*/, + igfMinFq); + /* set up IGF grid for TCX 10 (transfac = 0.5) */ + hGrid = &hIGFInfo->grid[IGF_GRID_LB_SHORT]; + IGF_gridSetUp(hGrid, + hIGFInfo->bitRateIndex, + sampleRate, + frameLength, + 8192/*0.50f Q14*/, + igfMinFq); + } + + return retValue; +} + +/**********************************************************************/ /* +selects cumulative frequency tables and offsets for the IGF SCF arithmetic coder +**************************************************************************/ +Word16 IGFCommonFuncsIGFGetCFTables( /**< out: | error value: 0 -> error, 1 -> ok */ + Word32 bitRate, /**< in: Q0 | bitrate in bs e.g. 9600 for 9.6kbs */ + Word16 mode, /**< in: Q0 | bandwidth mode */ + Word16 rf_mode, /**< in: | flag to signal the RF mode */ + const Word16 **cf_se00, /**< out: | CF table for t == 0 and f == 0 */ + const Word16 **cf_se01, /**< out: | CF table for t == 0 and f == 1 */ + Word16 *cf_off_se01, /**< out: | offset for CF table above */ + const Word16 **cf_se02, /**< out: | CF tables for t == 0 and f >= 2 */ + const Word16 **cf_off_se02, /**< out: | offsets for CF tables above */ + const Word16 **cf_se10, /**< out: | CF table for t == 1 and f == 0 */ + Word16 *cf_off_se10, /**< out: | offset for CF table above */ + const Word16 **cf_se11, /**< out: | CF tables for t == 1 and f >= 1 */ + const Word16 **cf_off_se11 /**< out: | offsets for CF tables above */ +) +{ + Word16 retValue; + Word16 bitRateIndex; + +Word16 temp_var; + + retValue = 0; /* bitrate index is unknown -> error! */ move16(); + bitRateIndex = IGF_MapBitRateToIndex(bitRate, mode + ,rf_mode + ); + + + IF (NE_16(bitRateIndex, IGF_BITRATE_UNKNOWN)) + { + retValue = 1; /* no error */ move16(); + SWITCH(bitRateIndex) + { + case IGF_BITRATE_WB_9600: + case IGF_BITRATE_RF_WB_13200: + case IGF_BITRATE_SWB_9600: + case IGF_BITRATE_SWB_13200: + case IGF_BITRATE_RF_SWB_13200: + case IGF_BITRATE_SWB_16400: + case IGF_BITRATE_SWB_24400: + case IGF_BITRATE_SWB_32000: + case IGF_BITRATE_SWB_48000: + *cf_se00 = cf_se00_tab; + *cf_se01 = cf_se01_tab[bitRateIndex]; + *cf_off_se01 = cf_off_se01_tab[bitRateIndex]; + temp_var = bitRateIndex; + if ((bitRateIndex == 0) || (bitRateIndex == 1)) + { + bitRateIndex = 0; + } + else if ((bitRateIndex == 2) || (bitRateIndex == 3) || (bitRateIndex == 4) || (bitRateIndex == 5)) + { + bitRateIndex = 1; + } + else if ((bitRateIndex == 6) || (bitRateIndex == 7)) + { + bitRateIndex = 2; + } + else if (bitRateIndex == 8) + { + bitRateIndex = 3; + } + *cf_se02 = &cf_se02_tab[bitRateIndex][0][0]; + move16(); + bitRateIndex = temp_var; + *cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0]; + move16(); + *cf_se10 = &cf_se10_tab[0]; + move16(); + *cf_off_se10 = cf_off_se10_tab; + *cf_se11 = &cf_se11_tab[0][0][0]; + move16(); + *cf_off_se11 = &cf_off_se11_tab[0][0]; + move16(); + BREAK; + case IGF_BITRATE_FB_16400: + case IGF_BITRATE_FB_24400: + case IGF_BITRATE_FB_32000: + bitRateIndex = add(sub(bitRateIndex, IGF_BITRATE_FB_16400), IGF_BITRATE_SWB_16400); + *cf_se00 = cf_se00_tab; + *cf_se01 = cf_se01_tab[bitRateIndex]; + *cf_off_se01 = cf_off_se01_tab[bitRateIndex]; + temp_var = bitRateIndex; + if (bitRateIndex == 5) + { + bitRateIndex = 1; + } + else if (bitRateIndex == 6 || bitRateIndex == 7) + { + bitRateIndex = 2; + } + *cf_se02 = &cf_se02_tab[bitRateIndex][0][0]; + move16(); + bitRateIndex = temp_var; + *cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0]; + move16(); + *cf_se10 = &cf_se10_tab[0]; + move16(); + *cf_off_se10 = cf_off_se10_tab; + *cf_se11 = &cf_se11_tab[0][0][0]; + move16(); + *cf_off_se11 = &cf_off_se11_tab[0][0]; + move16(); + BREAK; + case IGF_BITRATE_FB_48000: + bitRateIndex = add(sub(bitRateIndex, IGF_BITRATE_FB_48000), IGF_BITRATE_SWB_48000); + *cf_se00 = cf_se00_tab; + *cf_se01 = cf_se01_tab[bitRateIndex]; + *cf_off_se01 = cf_off_se01_tab[bitRateIndex]; + temp_var = bitRateIndex; + bitRateIndex = 3; + *cf_se02 = &cf_se02_tab[bitRateIndex][0][0]; + move16(); + bitRateIndex = temp_var; + *cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0]; + move16(); + *cf_se10 = &cf_se10_tab[0]; + move16(); + *cf_off_se10 = cf_off_se10_tab; + *cf_se11 = &cf_se11_tab[0][0][0]; + move16(); + *cf_off_se11 = &cf_off_se11_tab[0][0]; + move16(); + BREAK; + case IGF_BITRATE_FB_96000: + case IGF_BITRATE_FB_128000: + bitRateIndex = IGF_BITRATE_SWB_48000; + move16(); + *cf_se00 = cf_se00_tab; + *cf_se01 = cf_se01_tab[bitRateIndex]; + *cf_off_se01 = cf_off_se01_tab[bitRateIndex]; + temp_var = bitRateIndex; + bitRateIndex = 3; + *cf_se02 = &cf_se02_tab[bitRateIndex][0][0]; + move16(); + bitRateIndex = temp_var; + *cf_off_se02 = &cf_off_se02_tab[bitRateIndex][0]; + move16(); + *cf_se10 = &cf_se10_tab[0]; + move16(); + *cf_off_se10 = cf_off_se10_tab; + *cf_se11 = &cf_se11_tab[0][0][0]; + move16(); + *cf_off_se11 = &cf_off_se11_tab[0][0]; + move16(); + BREAK; + case IGF_BITRATE_UNKNOWN: + default: + assert(0); + } + } + return retValue; +} + diff --git a/lib_com/index_pvq_opt_fx.c b/lib_com/index_pvq_opt_fx.c new file mode 100644 index 0000000..68297f4 --- /dev/null +++ b/lib_com/index_pvq_opt_fx.c @@ -0,0 +1,1187 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required for wmc_tool */ +#include "basop_util.h" +#include + +#define N_OPT_FX 5 /* complexity setting, direct functional calculation limit & low dim recursion limit */ +#define TABLE_LIM_OPT_FX 96 /* odd divisor table , N-row_recursion limit setting, due to dim */ + + +/* local typedefs for optimized pvq indexing, used locally c-file to vectorize common function calls */ +typedef void (*VEC2INDFUNCM) (const Word16* , Word16* , UWord32*, UWord32*); +typedef UWord32 (*NFUNCM) (Word16); +typedef UWord32 (*H_FUNCM) ( UWord32 ); +typedef void (*IND2VECFUNCM) ( Word16, Word16, UWord32, Word16* ) ; +typedef void (*NDIM_FUNCM) ( Word16, Word16, UWord32, Word16* ); + +/* local constants for indexing functions */ +#define SIGNBIT_FX 0x80000000u +#define SIGNBIT_SHRT_FX 0x8000 +#define UDIVBY3_FX 2863311531U + +/*-------------------------------------------------------------------* + * f_odd_exact_div_opt_fx() + * + * find 1/(den1*2+1) * ( num1p*num2p - num3) , + * if the result is known a priori to be exactly a 32bit UWord32 + *-------------------------------------------------------------------*/ +static +UWord32 f_odd_exact_div_opt_fx( /* o : see Eq. */ + UWord32 num1p, /* i : see Eq. */ /* (2n-1) or n , i.e can be short also */ + UWord32 num2p, /* i : see Eq. */ + UWord32 num3, /* i : see Eq. */ + Word16 den1 /* i : see Eq. */ /*range [0..127] can be made to short */ +) +{ + UWord32 UL_tmp; + UL_tmp = UL_Mpy_32_32(exactdivodd_fx[den1],UL_subNsD(UL_Mpy_32_32(num1p,num2p),num3)); + + return (UL_tmp); +} + +/*---------------------------------------------------------------------------* + * f_even_exact_div_opt_fx() + * + * returns (num1p*num2p - num3 )/ den1 + * if the result is known a priori to be exactly a 32bit unsigned integer + *--------------------------------------------------------------------------*/ +static +UWord32 f_even_exact_div_opt_fx( /* o : see Eq. */ + UWord32 UL_num1p, /* i : see Eq. 2n-1 or n can be short input */ + UWord32 UL_num2p, /* i : see Eq. range should be larger than num1p */ + UWord32 UL_num3, /* i : see Eq. */ + Word16 den1 /* i : see Eq. */ +) +{ + UWord32 UL_tmp, UL_oddfactor; + Word16 den1_m1, even_sh; + UWord32 UL_tmp_h; + UWord16 sgn; + + den1_m1 = sub(den1,1); /* remove top bit */ + even_sh = sub(15, norm_s(s_xor(den1_m1, den1))); /* STL signed ops ok as den1 <= 127 */ + + UL_oddfactor = exactdivodd_fx[lshr(den1_m1,even_sh)]; + move32(); + even_sh = sub(even_sh,1); + + + Mpy_32_32_uu(UL_num1p, UL_num2p, &UL_tmp_h, &UL_tmp); /* cost ~4 */ + UL_tmp = UL_subNs(UL_tmp,UL_num3,&sgn); /* may wrap for underflow */ + if(sgn) /* underflow */ + { + UL_tmp_h = UL_subNsD(UL_tmp_h,1U); /* single basicop -> if */ + } + UL_tmp = UL_or(UL_lshl(UL_tmp_h,sub(32,even_sh)), UL_lshr(UL_tmp,even_sh)); + /* total cost 9-11 , old solution had 15-16*/ + + /* now use tabled modular multiplicative inverse for the odd part division */ + return UL_Mpy_32_32(UL_tmp, UL_oddfactor); +} + +/* direct calculation functions for smaller dimensions to speed up indexing + +N_MPVQ(1,k) = 1; +N_MPVQ(2,k) = k*2; +N_MPVQ(3,k) = 1+2*(k^2); +N_MPVQ(4,k) = k/3 * 4*(k^2+2); +N_MPVQ(5,k) = 1 + 2*(k*k*(5+k*k))/3; +N_MPVQ(*,k) = iterations = 1 + A(n,k) + A(n+1,k); + +N_PVQ(n,k) = 2*N_MPVQ(n,k); + + +A(1,k) = 1; +A(2,k) = -1 + 2k; +A(3,k) = 1+2(k-1)k; +A(4,k) = 1/3*(((4k-6)k+8)*k-3), +A(5,k) = 1/3*(3+ k(10+2(k-2)k)k-8); +A(*,k) = recursive iterations; + + +U(n,k) = (A(n,k)-1)/2; +U(1,k) = 0; +U(2,k) = k-1; +U(3,k) = k*(k-1) +U(4,k) = (1/3)*((k - 1)*(2*k^2 - k + 3)) +U(5,k) = (1/3)*(k*(k - 1)*(k^2 - k + 4)) +U(*,k) = recursive iterations; + +U(n,k) = U(k,n); +U(n,k) = func(n, U(n,k-1), U(n,k-2) , 1/(k-1) ); +U(n,k) = 1 + U(n-1,k-1) + U(n-1,k) + U(n,k-1); +U(n,k) = 1 + A(n-1,k-1)>>1 + A(n-1,k)>>1 + A(n,k-1)>>1; A(n,k) is always odd if k>0 +*/ + +/*-------------------------------------------------------------------* + * a_three_fx() + *-------------------------------------------------------------------*/ +static +UWord32 a_three_fx( /* o: offset for dim 3 */ + UWord32 k_val /* i: nb unit pulses */ +) /* k_val may be higher than 16 bit signed */ +{ + IF( k_val ) + { + /* return (ONE_U + k_val*((k_val - ONE_U) << ONE)); */ + return UL_addNsD(1U,UL_Mpy_32_32(k_val,UL_lshl(UL_subNsD(k_val,1U),1))); + } + ELSE + { + return 0; + } +} + +/*-------------------------------------------------------------------* + * a_four_fx() + *-------------------------------------------------------------------*/ +static +UWord32 a_four_fx( /* o: offset for dim 4 */ + UWord32 k_val /* i: nb unit pulses */ +) +{ + UWord32 UL_2k; + IF(k_val) + { + /* return UDIVBY3*((k_val<0,k=0) */ + h_mem[1] = UL_deposit_l(1); /* A(*,k=1) */ + + UL_k_val_in = UL_deposit_l(k_val_in); + IF(EQ_16(dim_in,2)) + { + FOR( k_val = 2 ; k_val <= UL_k_val_in ; k_val++ ) + { + h_mem[k_val] = UL_subNsD(UL_lshl(k_val,1),1U); + move32(); /* A(2, 2 .. k ) */ + } + h_mem[k_val] = UL_k_val_in; + move32(); /* U(2,k+1) */ + } + ELSE + { + k_val_prev = UL_deposit_l(1U); + FOR(k_val_curr = 2; k_val_curr<=UL_k_val_in; k_val_curr++) + { + h_mem[k_val_curr] = UL_addNsD(1U , UL_Mpy_32_32(k_val_curr, UL_lshl(k_val_prev,1))); + move32(); + k_val_prev = UL_addNsD(k_val_curr, 0U); /* 1 op*/ + } + h_mem[k_val_curr] = UL_Mpy_32_32(k_val_curr,k_val_prev); + move32(); /* % U(3,k_val_in+1) u_three(k+1) */ + } + + return; +} + +/*-------------------------------------------------------------------* + * a_fwd_fx() + * + * create offsets for A(n,k) from lower A(n-1,k) + *-------------------------------------------------------------------*/ +static +void a_fwd_fx( + UWord32 *a_in, /* i/o: offsets */ + Word16 n_items /* i : items, k's */ +) +{ + UWord32 a_1, a_in0 ; + Word16 i ; + UWord32* a_in_prev_ptr; + + a_in0 = UL_deposit_l(1); + + a_in_prev_ptr=&(a_in[-1]); /* single loop ptr setup not counted; */ + FOR(i=1; i<=n_items; i++) /* basic A fwd row recursion */ + { + a_1 = UL_addNsD(a_in0, UL_addNsD(a_in_prev_ptr[i], a_in[i])) ; + a_in_prev_ptr[i] = a_in0; + move32(); + a_in0 = UL_addNsD(a_1, 0U); + } + a_in_prev_ptr[i] = a_in0; + move32(); + return; +} + +/*-------------------------------------------------------------------* + * a_bwd_fx() + * + * create offsets for A(n,k) from higher A(n+1,k) + *-------------------------------------------------------------------*/ +static +void a_bwd_fx( + UWord32 *a_in, /* i/o: offsets */ + Word16 n_items /* i: n_items */ +) +{ + UWord32 a_1, a_in0; + Word16 i; + UWord32* a_in_prev_ptr; + + a_in0 = UL_deposit_l(0); + a_in_prev_ptr = &(a_in[-1]); + + FOR(i = 1; i<=n_items; i++) /*basic A reverse row recursion */ + { + /* 2x[i] ptr memory access below are treated as ptr access */ + a_1 = UL_subNsD(UL_subNsD(a_in[i], a_in0), a_in_prev_ptr[i]); + a_in_prev_ptr[i] = a_in0; + move32(); + a_in0 = UL_addNsD(a_1, 0U); + + } + a_in_prev_ptr[i] = a_in0; + move32(); + return; +} + +static +UWord32 direct_row_A2U_rec_calc_fx(Word16 dim_in , Word16 k_val_in, UWord32 a_km2, UWord32 a_km1) +{ + /* U(n,k) = (A(n,k-2)-1)/2 + ((2*n-1)*A(n,k-1) - A(n,k-2) )/2*(k-1) */ + /* U(n,k) = floor(A(n,k-2)/2) + (n*A(n,k-1) - floor(A(n,k-1)/2) - floor(A(n,k-2)/2) +1 )/(k-1) */ + /* U(n,k) = floor(A(n,k-2)/2) + (n*A(n,k-1) - (floor(A(n,k-1)/2) + floor(A(n,k-2)/2) +1) )/(k-1) */ + + UWord32 km2_size, UL_um2, UL_dim ; + Word16 divisor; + + divisor = sub(k_val_in,1); + UL_um2 = UL_lshr(a_km2,1U); + UL_dim = UL_deposit_l(dim_in); + km2_size = UL_addNsD(UL_addNsD(UL_lshr(a_km1,1), UL_um2), 1U); + IF(s_and(divisor,0x1) != 0) + { + /* odd */ + return UL_addNsD(UL_um2, f_odd_exact_div_opt_fx( UL_dim, a_km1, km2_size, shr(divisor,1))); + } + ELSE + { + /* even divisor, */ + return UL_addNsD(UL_um2, f_even_exact_div_opt_fx(UL_dim, a_km1, km2_size, divisor)); + } +} + +static +void a_u_fwd_fx(UWord32 *a_u_in, + Word16 k_val_in, + Word16 mem_size_m1) +{ + UWord32 u_kp1_prev, u_kp1; + UWord32 u_k_prev ; + + u_kp1_prev = a_u_in[mem_size_m1]; + move32(); /* previous n U (n,k+1) value*/ + u_k_prev = UL_lshr(a_u_in[k_val_in],1); /* previous n A(n,k) value*/ + + a_fwd_fx(&a_u_in[1], k_val_in); /* a_u_in[k==ZERO] = zero if n>0 */ + + /* low dynamic last offset entry mixed recursion */ + /* used for size calculation */ + /* U(n,k+1) = 1 + U(n-1,k+1) + U(n-1,k) + U(n,k) */ + /* U(n,k+1) = 1 + U(n-1,k+1) + (A(n-1,k)-1)/2 + (A(n,k)-1)/2 */ + /* Note, A(n,k) always odd for k>0 , subtracted one always shifted out */ + + u_kp1 = UL_lshr(a_u_in[k_val_in],1); + a_u_in[mem_size_m1] = UL_addNsD(1U, UL_addNsD(u_kp1_prev, UL_addNsD(u_k_prev,u_kp1))); + return; +} + +/*-------------------------------------------------------------------* + * nm_h_prep_opt_fx() + * + * find and return N_MPVQ(n,k) and also offsets A(n, 0 to k ) and U(n,k+1). + *-------------------------------------------------------------------*/ +static +UWord32 nm_h_prep_opt_fx( /* o: msize for dim */ + Word16 dim_in, /* i: dimension */ + Word16 k_val_in, /* i: nb unit pulses */ + UWord32 *h /* o: A/U offsets array */ +) +{ + Word16 mem_size_m1, k_val,tmp ; + Word16 dim_tmp, d_start; + UWord32 h_saveA, h_saveB, u_kp1,a_k; /* registers for alternating A(n,k-1), A(n,k-2)*/ + UWord32 numDsub1; + Word16 end_loop, add_last_odd ; + + h[0] = UL_deposit_l(0); /* % A(=>0,k=0) */ + h[1] = UL_deposit_l(1); /* % A(*,k=1) */ + + mem_size_m1 = add(k_val_in,1); + + assert(dim_in > N_OPT_FX); /* code now optimized with direct functions for dim <= N_OPT_FX ) */ + IF( (GT_16(k_val_in, TABLE_LIM_OPT_FX))) + { + d_start = 2; + move16(); + if( GE_16(dim_in,3)) + { + /* start from A(3), U(3) */ + d_start = 3; + move16(); /* single op */ + } + initOffsets_fx(d_start, h, k_val_in); + FOR(dim_tmp = d_start; dim_tmp < dim_in; dim_tmp++) + { + a_u_fwd_fx(h, k_val_in, mem_size_m1); + } + a_k = h[k_val_in]; + move32(); + u_kp1 = h[mem_size_m1]; + move32(); + } + ELSE + { + numDsub1 = UL_deposit_l(sub(shl(dim_in,1),1)); + h[2] = numDsub1; + move32(); + + /* interleaved " odd, even [odd]" divisor calls */ + h_saveA = numDsub1; + move32(); + h_saveB = UL_deposit_l(1); + + /* OPT: makes sure that the STL FOR loop is not broken */ + tmp = sub(k_val_in,3); + add_last_odd = 0; + move16() ; /*k_val_in=0 1 2*/ + if(tmp == 0) + { + add_last_odd = 1; + move16(); /*k_val_in =3 */ + } + k_val = 3; + move16(); + IF( tmp > 0 ) + { + /* k_val_in = 3,4, 5,6, 7 ... */ + end_loop = mem_size_m1; + move16(); + add_last_odd = s_and(k_val_in,0x1) ; + move16(); /* odd -> 0x00100*/ + /* even loop limits, and odd tail exists , and */ + if(NE_16(add_last_odd,0)) + { + end_loop = sub(end_loop,1); /* make initial loop to even number of (odd-even )pairs *//* one basicop */ + } + FOR(k_val = 3; k_val < end_loop ; k_val++ ) + { + /* the optimized non broken loop k=(3,4)(5,6)...(odd,even)*/ + /* A(n,k) = A(n,k-2) + ((2*n-1)*A(n,k-1)-A(n,k-2)) /(k-1) */ + /* first odd k, even divisor */ + h_saveB = UL_addNsD(h_saveB, f_even_exact_div_opt_fx(numDsub1, h_saveA, h_saveB, sub(k_val,1))); + h[k_val] = h_saveB; + move32(); + + /* next even k, odd divisor */ + /*k_val++; */ + h_saveA = UL_addNsD(h_saveA, f_odd_exact_div_opt_fx(numDsub1, h_saveB, h_saveA,shr(k_val,1))); + k_val++; /* ptr incr */ + h[k_val] = h_saveA; + move32(); + } + } + + if(NE_16(add_last_odd,0)) + { + /* add a last odd call as needed , not to be called if k_val_in is [0,1,2] */ + h_saveB = UL_addNsD(h_saveB,f_even_exact_div_opt_fx(numDsub1, h_saveA, h_saveB, sub(k_val,1))); + h[k_val_in] = h_saveB; + move32(); + } + + /* always do the last (k+1) recursion based on U(n,k+1) = func( A(n-2,k+1), A(n-1,k+1) ) */ + a_k = h[k_val_in] ; + move32(); + u_kp1 = direct_row_A2U_rec_calc_fx(dim_in, mem_size_m1 , h[sub(mem_size_m1,2)], a_k ); + h[mem_size_m1] = u_kp1; + move32(); + } + + /* N_MPVQ(n,k) = 1 + U(n,k+1) + U(n,k) = 1 + U(n,k+1) + floor(A(n,k))/2) ; */ /* as A(n,k) always odd */ + return ( UL_addNsD(1U, UL_addNsD(u_kp1, UL_lshr(a_k,1)))); +} + +/* + find_amp_split_offset_func_mem_fx() + find first offset in range 0..k_val_in that is less than ind_in + using a tree search with direct function calls [ or memory iteration] +*/ +static +Word16 find_amp_split_offset_func_mem_fx( /* o: found k_value */ + UWord32 ind_in, + Word16 high, /* i: k_val_in (high bound) */ + H_FUNCM h_func_ptr, /* i: offset function pointer */ + UWord32 *UL_tmp_offset) /* o: offset found */ +{ + Word16 not_ready, low, k_test=0; + UWord16 sgn ; + UWord32 UL_tmp; + /* split over A(n,k) = h_mem(k), or use direct A function evaluation */ + + low = 0; + move16(); + move32(); /* account for adaptive function ptr setup */ + not_ready = 1 ; + move16(); + + WHILE( not_ready != 0) + { + k_test = shr(add(low,high),1); /*% split range in half */ + *UL_tmp_offset = (*h_func_ptr)(UL_deposit_l(k_test)); /* call direct A offset-function */ + + UL_tmp = UL_subNs(*UL_tmp_offset, ind_in, &sgn ); + IF ( sgn ) + { + /* (*tmp_offset < ind_in) */ + low = add(1, k_test) ; + if( GE_16(k_test ,high)) + { + not_ready = 0; + move16(); /* single basicop */ + } + } + ELSE + { + /* (ind_in <= *tmp_offset ) */ + high = sub(k_test,1); + if( UL_tmp == 0) + { + /* (*tmp_offset == ind_in) */ + not_ready = 0; + move16(); /* single basicop */ + } + } + } + return k_test; +} + +/* + get_lead_sign_fx() + updated index and return leading sign +*/ +static +Word16 get_lead_sign_fx(UWord32 *ind) +{ + Word16 leading_sign; + + leading_sign = 1; + move16(); + if( UL_and(*ind,1) != 0 ) + { + /* leading sign stored in LSB */ + leading_sign = -1; + move16(); + } + (*ind) = UL_lshr(*ind,1); + + return leading_sign; +} + +/*-------------------------------------------------------------------* + * mind2vec_one_fx() + *-------------------------------------------------------------------*/ +static +void mind2vec_one_fx( + Word16 k_val_in, /* i: nb unit pulses */ + Word16 leading_sign, /* i: leading sign -1, 0, 1*/ + UWord32 ind, /* i: index */ /* parameter needed as it is used in a function array */ + Word16* vec_out /* o: pulse train */ +) +{ + /* NB input k_val_in can be zero */ + /* *vec_out = leading_sign*k_val_in; */ + *vec_out = (Word16)ind; /* dummy assignment to avoid gcc "unused parameter" warning for ind, i.e no move16() needed */ + + /* *vec_out = extract_l(L_mult0(leading_sign,k_val_in)); move16(); // 3 ops */ + if( leading_sign < 0 ) + { + k_val_in = negate(k_val_in); /* single basicop --> if */ + } + *vec_out = k_val_in; + move16(); /* 1 op */ +} + +static +void mind2vec_two_fx( + Word16 k_val_in, /* i: nb unit pulses */ + Word16 leading_sign, /* i: leading sign -1,0, 1 */ + UWord32 ind_in, /* i: index */ + Word16 *vec_out /* o: pulse train */ +) +{ + UWord32 UL_ind_tmp; + Word16 val1; + + IF (ind_in == 0) + { + /* ind_in == 0 */ + mind2vec_one_fx( k_val_in,leading_sign,ind_in,vec_out); + } + ELSE IF ( EQ_16((Word16)u_extract_l(ind_in), sub(shl(k_val_in,1),1))) + { + /* signed ops fine as 2*KMAX << 32767) */ + /* (ind_in == ( (unsigned int)(k_val_in<dim; i++) + { + vec_out[i]=0; + move16(); /* set all of short vector to zero , required for fast/early exit logic */ + } + + leading_sign = 1; + move16(); + if(entry->lead_sign_ind != 0) + { + leading_sign = -1; + move16(); + } + + IF(entry->k_val != 0) + { + IF(GT_16(entry->dim,N_OPT_FX)) /* N_OPT_FX */ + { + /* generic */ + mind2vec_fx(entry->dim, entry->k_val, leading_sign, entry->index, vec_out, h_mem); + } + ELSE + { + /* specialized functions, with direct offset calculations */ + (mind2vec_f_fx[entry->dim])(entry->k_val, leading_sign, entry->index, vec_out); + } + } + + return; +} + +/*-------------------------------------------------------------------* +* vec2mind_one_fx() +*-------------------------------------------------------------------*/ +static +void vec2mind_one_fx( + const Word16* vec_in, /* i : PVQ pulse train */ + Word16 *k_val_out_ptr , /* o : number of unit pulses */ /* parameter needed as it is used in a function array */ + UWord32 *next_sign_ind, /* i/o: next sign ind */ + UWord32* ind /* o: MPVQ index */ +) +{ + *ind = (Word32)(*k_val_out_ptr) ; /* dummy assignment to avoid gcc "unused parameter" warning for *k_val_out_ptr, i.e no move32 needed() */ + *ind = UL_deposit_l(0); + + *next_sign_ind = UL_deposit_l(0); + if( *vec_in < 0 ) + { + *next_sign_ind = UL_deposit_l(1); /*single basicop */ + } + return ; +} + +/*-------------------------------------------------------------------* +* vec2mind_two_fx() +*-------------------------------------------------------------------*/ +static +void vec2mind_two_fx( + const Word16* vec_in, /* i : PVQ pulse train */ + Word16 *k_val_out_ptr , /* o : number of unit pulses */ + UWord32 *next_sign_ind, /* i/o: next sign ind */ + UWord32* ind /* o: MPVQ index */ +) +{ + UWord32 lead_sign_ind_add; + Word16 abs0,abs1,abs01,sptr; + + abs0 = abs_s(vec_in[0]); + abs1 = abs_s(vec_in[1]); + abs01 = add(abs0, abs1); + *k_val_out_ptr = abs01; + move16(); /* can be zero */ + *ind = UL_deposit_l(0); /* [KMAX 0 ] , and dual zeros */ + + *next_sign_ind = UL_deposit_h(SIGNBIT_SHRT_FX); /* "unset" sign flag set */ /* dual zeroes can happen in a recursive encoding call */ + + + IF( abs01 != 0 ) + { + sptr = 0; + move16(); /*used as ptr to vec0 or vec1 value */ + *next_sign_ind = UL_deposit_l(sptr); + + test(); + IF(abs0 != 0 && abs1 != 0 ) + { + /* likely most frequent/common case */ + /* [ KMAX-1 1],[ KMAX-1 -1] ... [ 1 +(KMAX-1) ],[ 1 -(KMAX-1)] */ + /* sign always shifted to first pos */ + lead_sign_ind_add = UL_deposit_l(1) ; + if( vec_in[1] < 0) + { + lead_sign_ind_add = UL_deposit_l(2); /* single op */ + } + *ind = UL_addNsD(UL_deposit_l((UWord16)lshl(sub(abs1,1),1)),lead_sign_ind_add); + } + ELSE + { + /* one value is a zero */ + IF( abs0 == 0 ) + { + /* [ 0 KMAX]*/ + *ind = UL_deposit_l((UWord16) sub(lshl(abs1,1),1)); + sptr = 1; + move16(); + } + } + + /* *next_sign_ind= (unsigned int)(vec_in[*next_sign_ind]<0); */ + if( vec_in[sptr] < 0 ) + { + *next_sign_ind = UL_deposit_l(1); /*single instruction */ + } + } + return; +} + +static +void enc_push_sign(Word16 val, UWord32* next_sign_ind, UWord32 *index) +{ + /* + % Check if the leading sign 'bit' is to be added + % here the leading sign bit is put in LSB as it saves about 3 cycles in sign-decoding + % (one can also put it in the MSB , but then one needs to access h_mem twice and shift the sign bit into position ) + */ + test(); + IF( (UL_and(*next_sign_ind,SIGNBIT_FX) == 0) && (val != 0)) + { + *index = UL_addNsD(UL_lshl(*index,1),*next_sign_ind); + } + + /* push sign to next non_zero position */ + /* *next_sign_ind = *next_sign_ind ;*/ /* default is to keep stored sign index */ + if( val < 0 ) + { + *next_sign_ind = UL_deposit_l(1); /* single basicop */ + } + if( val > 0) + { + *next_sign_ind = UL_deposit_l(0); /* single basicop */ + } +} + +/*-------------------------------------------------------------------* + * vec2mind_gen345_fx( vec_in kval, next_dim_func , offset_func,....) + * generic call saves PROM , + *-------------------------------------------------------------------*/ + +static +void vec2mind_gen345_fx( + const Word16* vec_in, /* i : PVQ abs pulse train */ + Word16 *k_val_out_ptr, /* o : number of unit pulses */ + UWord32 *next_sign_ind , /* i/o: next sign ind */ + UWord32* index , /* o: MPVQ index */ + VEC2INDFUNCM vec2indfunc_ptr, /* i: */ + H_FUNCM a_func_ptr /*i: offset function */ +) +{ + Word16 tmp_val; + + tmp_val = vec_in[0]; + move16(); + move32(); /* adaptive function call setup */ + (*vec2indfunc_ptr)(&vec_in[1], k_val_out_ptr, next_sign_ind, index); + + enc_push_sign(tmp_val, next_sign_ind, index); + + move32(); /* adaptive function call setup */ + *index = UL_addNsD(*index,(*a_func_ptr)(UL_deposit_l(*k_val_out_ptr))); + + *k_val_out_ptr = add(*k_val_out_ptr, abs_s(tmp_val)); + + return ; +} + +/*-------------------------------------------------------------------* + * vec2mind_three_fx() + *-------------------------------------------------------------------*/ +static +void vec2mind_three_fx( + const Word16* vec_in, /* i : PVQ pulse train */ + Word16* k_val_out_ptr, /* o : number of unit pulses */ + UWord32 *next_sign_ind, /* i/o: next sign ind */ + UWord32 *index /* o: MPVQ index */ +) +{ + vec2mind_gen345_fx(vec_in,k_val_out_ptr, next_sign_ind, index, vec2mind_two_fx, a_three_fx); + return ; +} + + +/*-------------------------------------------------------------------* + * vec2mind_four_fx() + *-------------------------------------------------------------------*/ +static +void vec2mind_four_fx( + const Word16* vec_in, /* i : PVQ pulse train */ + Word16* k_val_out_ptr, /* o : number of unit pulses */ + UWord32* next_sign_ind , /* i/o: next sign ind */ + UWord32* index /* o: MPVQ index */ +) +{ + vec2mind_gen345_fx(vec_in, k_val_out_ptr, next_sign_ind, index, vec2mind_three_fx, a_four_fx); + return ; +} + +/*-------------------------------------------------------------------* + * vec2mind_five_fx() + *-------------------------------------------------------------------*/ +static +void vec2mind_five_fx( + const Word16* vec_in, /* i : PVQ abs pulse train */ + Word16 *k_val_out_ptr, /* o : number of unit pulses */ + UWord32 *next_sign_ind , /* i/o: next sign ind */ + UWord32* index /* o: MPVQ index */ +) +{ + vec2mind_gen345_fx(vec_in,k_val_out_ptr, next_sign_ind, index, vec2mind_four_fx, a_five_fx); + return ; +} + +/*-------------------------------------------------------------------* +* vec2mind_fx() +*-------------------------------------------------------------------*/ +static +void vec2mind_fx(Word16 dim_in, /* i : dim */ + Word16 k_val_in, /* i : number of unit pulses */ + const Word16* vec_in, /* i : PVQ pulse train */ + UWord32 *next_sign_ind, /* o : pushed leading sign */ + UWord32 *index , /* o : MPVQ index */ + UWord32 *N_MPVQ_ptr, /* o : size(N_MPVQ(dim,K_val_in))*/ + UWord32* h_mem) /* o : offsets */ +{ + Word16 pos, mem_size_m1, k_val_acc, tmp_val; + UWord32 tmp_h; + + /* + %% main steps + % quick encode two rightmost pos + % for every position from dim-3 to 0 (right to left) + % check if an sign is to be encoded , + % add its offset + % check(and add) amplitude offset(for accumulated pulse sum) up to this point + % update total pulse sum + % update offset vector recursively (except for pos==0 ) + % end + % calculate size + */ + + mem_size_m1 = add(k_val_in,1); + *next_sign_ind = UL_deposit_h(SIGNBIT_SHRT_FX); /* highest bit set signals no sign found yet, should always be 0 or 1 out, */ + + pos = sub(dim_in,2); /* adress 2nd last sample */ + vec2mind_two_fx(&vec_in[pos],&k_val_acc,next_sign_ind ,index); + initOffsets_fx( 3, h_mem, k_val_in) ; /* start recursions at 3rd sample */ + + tmp_h = h_mem[k_val_acc]; + move32(); + FOR (pos--; pos>=0; pos--) + { + tmp_val = vec_in[pos]; + move16(); + enc_push_sign(tmp_val, next_sign_ind, index); + + /* now add indexing offset up to this reverse (r_l) accumulated amplitude point */ + *index = UL_addNsD(*index, tmp_h); /* k_val_acc==0 ==>0 */ + + /* k_val_acc = k_val_acc + vec_abs[pos];*/ /* now increase acc k value for next N */ + k_val_acc = add(k_val_acc, abs_s(tmp_val)); + + IF( pos != 0 ) + { + a_u_fwd_fx(h_mem, k_val_in ,mem_size_m1); + /* update A(n,k=1:k_val_in) and U(n,k_val_in+1) */ + /* NB here (k_val_in + 2 elements always has to be updated */ + } + tmp_h = UL_addNsD(h_mem[k_val_acc], 0U); + } + + /* size is needed for the subseqent arithmetic encoding/transmission of the index. + use relation N_MPVQ(n,K) = 1 + (A(n, K)-1)/2 + U(n, 1 + K) + = N_MPVQ(n,K) = 1 + (A(n, K)>>1) + U(n, 1 + K) , as A(n,K) is odd) */ + *N_MPVQ_ptr = UL_addNsD(1U,UL_addNsD(UL_lshr(tmp_h,1),h_mem[ mem_size_m1])); + move32();/* calc total size */ + + return; +} + +/*--------------------------------------------------------------------------* + * mpvq_encode_vec_fx() + * + * returns struct with lead sign index, MPVQ-index, dim and N_MPVQ size + *-------------------------------------------------------------------------*/ + +PvqEntry_fx mpvq_encode_vec_fx( /* o : leading_sign_index, index, size, k_val */ + const Word16* vec_in, /* i : signed pulse train */ + Word16 dim_in, /* i : dimension */ + Word16 k_val_local /* i : nb unit pulses */ +) +{ + PvqEntry_fx result; + UWord32 h_mem[ 1 + KMAX_NON_DIRECT_FX + 1 ] ; /* now always assign max offset buffer for dim 6 , + actually only 1+k_val_in+1 needed ) */ + UWord32 lead_sign_ind; + + VEC2INDFUNCM vec2mind_f[1+N_OPT_FX] = { (VEC2INDFUNCM)NULL, vec2mind_one_fx, vec2mind_two_fx, vec2mind_three_fx, vec2mind_four_fx, vec2mind_five_fx }; + + result.k_val = k_val_local; + move16(); + result.dim = dim_in; + move16(); + /* NB , k_val_local may be changed in some sub encoding routines */ + IF( GT_16(dim_in, N_OPT_FX)) + { + /* use the generic dimension function */ + vec2mind_fx(dim_in, k_val_local, vec_in, &lead_sign_ind, &result.index, &result.size, h_mem); + } + ELSE /* if (dim_in<=N_OPT), h_mem not used */ + { + move32(); /* adaptive function ptr setup */ + (vec2mind_f[dim_in])(vec_in, &k_val_local, &lead_sign_ind, &result.index); + result.size = direct_msize_fx(dim_in, k_val_local); + } + result.lead_sign_ind = u_extract_l(lead_sign_ind); + + return result; +} + + diff --git a/lib_com/int_lsp_fx.c b/lib_com/int_lsp_fx.c new file mode 100644 index 0000000..f431ae3 --- /dev/null +++ b/lib_com/int_lsp_fx.c @@ -0,0 +1,173 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" + +/*========================================================================*/ +/* FUNCTION : int_lsp4_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : Interpolate LSPs find the A[z] parameters for all subframes */ +/* by interpolating between old end-frame LSPs, current */ +/* mid-frame LSPs and current end-frame LSPs */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) L_frame : length of the frame */ +/* _ (Word16) m : order of LP filter */ +/* _ (Word16) clas : signal frame class */ +/* _ (Word16[]) lsp_old : LSPs from past frame Q15 */ +/* _ (Word16[]) lsp_mid : LSPs from mid-frame Q15 */ +/* _ (Word16[]) lsp_new : LSPs from present frame Q15 */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) Aq : LP coefficients in both subframes Q12 */ +/*------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ +void int_lsp4_fx( + const Word16 L_frame, /* i : length of the frame */ + const Word16 lsp_old[], /* i : LSPs from past frame Q15*/ + const Word16 lsp_mid[], /* i : LSPs from mid-frame Q15*/ + const Word16 lsp_new[], /* i : LSPs from present frame Q15*/ + Word16 *Aq, /* o : LP coefficients in both subframes Q12*/ + const Word16 m, /* i : order of LP filter */ + Word16 relax_prev_lsf_interp /* i : relax prev frame lsf interp after erasure */ +) +{ + Word16 lsp[M16k]; + Word16 i,j, k; + Word32 L_tmp; + const Word16 *pt_int_coeffs; + + IF( EQ_16(L_frame,L_FRAME)) + { + IF ( EQ_16(relax_prev_lsf_interp,1)) + { + pt_int_coeffs = interpol_frac_mid_relaxprev_12k8_fx; + } + ELSE IF ( EQ_16(relax_prev_lsf_interp,2)) + { + pt_int_coeffs = interpol_frac_mid_FEC_fx; + } + ELSE IF ( EQ_16(relax_prev_lsf_interp,-1)) + { + pt_int_coeffs = interpol_frac_mid_relaxprev_pred_12k8_fx; + } + ELSE + { + pt_int_coeffs = interpol_frac_mid_fx; + } + } + ELSE /* L_frame == L_FRAME16k */ + { + IF ( EQ_16(relax_prev_lsf_interp,1)) + { + pt_int_coeffs = interpol_frac_mid_relaxprev_16k_fx; + } + ELSE IF ( EQ_16(relax_prev_lsf_interp,2)) + { + pt_int_coeffs = interpol_frac_mid_16k_FEC_fx; + } + ELSE IF ( EQ_16(relax_prev_lsf_interp,-1)) + { + pt_int_coeffs = interpol_frac_mid_relaxprev_pred_16k_fx; + } + ELSE + { + pt_int_coeffs = interpol_frac_mid_16k_fx; + } + } + k = sub(shr(L_frame,6),1); + FOR( j=0; jcore_brate_fx,SID_1k75)) + { + + indice[0] = (Word16)get_next_indice_fx( st, 6 ); + move16(); + indice[1] = (Word16)get_next_indice_fx( st, 6 ); + move16(); + indice[2] = (Word16)get_next_indice_fx( st, 6 ); + move16(); + indice[3] = (Word16)get_next_indice_fx( st, 5 ); + move16(); + indice[4] = (Word16)get_next_indice_fx( st, 5 ); + move16(); + + disf_ns_28b_fx( indice, isf_new ); + + reorder_isf_fx( isf_new, ISF_GAP_FX, M, Fs_2); + + E_LPC_isf_isp_conversion( isf_new, isp_new, M); + /* return if SID frame (conversion to A(z) done in the calling function) */ + return; + } + + /*-----------------------------------------------------------------* + * ISF de-quantization of all other frames + *-----------------------------------------------------------------*/ + + IF( EQ_32(st->core_brate_fx,ACELP_6k60)) + { + indice[0] = (Word16)get_next_indice_fx( st, 8 ); + move16(); + indice[1] = (Word16)get_next_indice_fx( st, 8 ); + move16(); + indice[2] = (Word16)get_next_indice_fx( st, 7 ); + move16(); + indice[3] = (Word16)get_next_indice_fx( st, 7 ); + move16(); + indice[4] = (Word16)get_next_indice_fx( st, 6 ); + move16(); + + disf_2s_36b_fx( indice, isf_new, st->mem_AR_fx, st->mem_MA_fx, 1 ); + } + ELSE + { + indice[0] = (Word16)get_next_indice_fx( st, 8 ); + move16(); + indice[1] = (Word16)get_next_indice_fx( st, 8 ); + move16(); + indice[2] = (Word16)get_next_indice_fx( st, 6 ); + move16(); + indice[3] = (Word16)get_next_indice_fx( st, 7 ); + move16(); + indice[4] = (Word16)get_next_indice_fx( st, 7 ); + move16(); + indice[5] = (Word16)get_next_indice_fx( st, 5 ); + move16(); + indice[6] = (Word16)get_next_indice_fx( st, 5 ); + move16(); + + disf_2s_46b_fx( indice, isf_new, st->mem_AR_fx, st->mem_MA_fx,1 ); + } + reorder_isf_fx( isf_new, ISF_GAP_FX, M, Fs_2 ); + /* convert quantized ISFs to ISPs */ + E_LPC_isf_isp_conversion( isf_new, isp_new, M); + + /*-------------------------------------------------------------------------------------* + * FEC - update adaptive mean ISF vector + *-------------------------------------------------------------------------------------*/ + + FOR ( i=0; ilsf_adaptive_mean[i] = (st->lsfoldbfi1[i] + st->lsfoldbfi0[i] + isf_new[i]) / 3;*/ + L_tmp = L_mult(st->lsfoldbfi1_fx[i], 10923); + L_tmp = L_mac(L_tmp, st->lsfoldbfi0_fx[i], 10923); + st->lsf_adaptive_mean_fx[i] = round_fx(L_mac(L_tmp, isf_new[i], 10923)); + } + + /*-------------------------------------------------------------------------------------* + * ISP interpolation + * A(z) calculation + *-------------------------------------------------------------------------------------*/ + + if(st->rate_switching_reset) + { + /*extrapolation instead of interpolation*/ + Copy(isp_new, st->lsp_old_fx, M); + Copy(isf_new, st->lsf_old_fx, M); + } + + /* ISP interpolation and A(z) calculation */ + int_lsp_fx( L_FRAME, st->lsp_old_fx, isp_new, Aq, M, interpol_isp_amr_wb_fx, 1 ); + + /*------------------------------------------------------------------* + * Check ISF stability : distance between old ISF and current ISF + *------------------------------------------------------------------*/ + + st->stab_fac_fx = lsf_stab_fx( isf_new, st->lsf_old_fx, 1, st->L_frame_fx ); + + return; +} + +/*-------------------------------------------------------------------* + * disf_ns_28b() + * + * ISF de-quantizer for SID_1k75 frames (only for AMR-WB IO mode) + *-------------------------------------------------------------------*/ + +void disf_ns_28b_fx( + Word16 *indice, /* i : quantized indices (use indice[0] = -1 in the decoder) */ + Word16 *isf_q /* o : ISF in the frequency domain (0..6400) */ +) +{ + Word16 i; + + FOR (i = 0; i < 2; i++) + { + isf_q[i] = dico1_ns_28b_fx[indice[0]*2+i]; + move16(); + } + + FOR (i = 0; i < 3; i++) + { + isf_q[i+2] = dico2_ns_28b_fx[indice[1]*3+i]; + move16(); + isf_q[i+5] = dico3_ns_28b_fx[indice[2]*3+i]; + move16(); + } + + FOR (i = 0; i < 4; i++) + { + isf_q[i+8] = dico4_ns_28b_fx[indice[3]*4+i]; + move16(); + isf_q[i+12] = dico5_ns_28b_fx[indice[4]*4+i]; + move16(); + } + + FOR (i=0; i +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "basop_util.h" +#include "stl.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define kLagWinThGain1 19661 /* 0.6f in Q15 */ +#define kLagWinThGain2 9830 /* 0.3f in Q15 */ + +/*-------------------------------------------------------------* + * procedure lag_wind: * + * ~~~~~~~~~ * + * lag windowing of the autocorrelations * + *-------------------------------------------------------------*/ + +void lag_wind( + Word16 r_h[], /* in/out: autocorrelations */ + Word16 r_l[], /* in/out: autocorrelations */ + Word16 m, /* input : order of LP filter */ + Word32 sr, /* input : sampling rate */ + Word16 strength /* input : LAGW_WEAK, LAGW_MEDIUM, or LAGW_STRONG */ +) +{ + Word16 i; + Word32 tmp; + const Word16 *wnd_h, *wnd_l; + + + assert(0 <= strength && strength <= NUM_LAGW_STRENGTHS); + SWITCH (sr) + { + case 8000: + assert(m <= 16); + assert(strength == LAGW_STRONG); + wnd_h = lag_window_8k[0]; + wnd_l = lag_window_8k[1]; + BREAK; + case 12800: + assert(m <= 16); + wnd_h = lag_window_12k8[strength][0]; + wnd_l = lag_window_12k8[strength][1]; + BREAK; + case 16000: + assert(m <= 16); + wnd_h = lag_window_16k[strength][0]; + wnd_l = lag_window_16k[strength][1]; + BREAK; + case 24000: + case 25600: + assert(m <= 16); + wnd_h = lag_window_25k6[strength][0]; + wnd_l = lag_window_25k6[strength][1]; + BREAK; + case 32000: + assert(m <= 16); + wnd_h = lag_window_32k[strength][0]; + wnd_l = lag_window_32k[strength][1]; + BREAK; + case 48000: + assert(m <= 16); + assert(strength == LAGW_STRONG); + wnd_h = lag_window_48k[0]; + wnd_l = lag_window_48k[1]; + BREAK; + default: + assert(!"Lag window not implemented for this sampling rate"); + return; + } + + FOR (i = 1; i <= m; i++) + { + tmp = Mpy_32(r_h[i], r_l[i], wnd_h[i-1], wnd_l[i-1]); + L_Extract(tmp, &r_h[i], &r_l[i]); + } + +} + +void adapt_lag_wind( + Word16 r_h[], /* in/out: autocorrelations */ + Word16 r_l[], /* in/out: autocorrelations */ + Word16 m, /* input : order of LP filter */ + const Word16 Top, /* input : open loop pitch lag */ + const Word16 Tnc, /* input : open loop pitch gain */ + Word32 sr /* input : sampling rate */ +) +{ + Word16 strength, pitch_lag; + Word16 pitch_gain; + + pitch_lag = Top; + move16(); + pitch_gain = Tnc; + move16(); + + IF (LT_16(pitch_lag, 80)) + { + strength = LAGW_STRONG; + move16(); + if (LE_16(pitch_gain, kLagWinThGain1)) + { + strength = LAGW_MEDIUM; + move16(); + } + } + ELSE IF (LT_16(pitch_lag, 160)) + { + strength = LAGW_MEDIUM; + move16(); + if (LE_16(pitch_gain, kLagWinThGain2)) + { + strength = LAGW_WEAK; + move16(); + } + } + ELSE + { + strength = LAGW_WEAK; + move16(); + } + + lag_wind(r_h, r_l, m, sr, strength); +} diff --git a/lib_com/lerp.c b/lib_com/lerp.c new file mode 100644 index 0000000..e866e23 --- /dev/null +++ b/lib_com/lerp.c @@ -0,0 +1,179 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "basop_util.h" +#include "prot_fx.h" +#include +#include "stl.h" + + + +#define shift_e (16-1) +#define pos_e (16-1) + +static void lerp_proc(Word16 *f, Word16 *f_out, Word16 bufferNewSize, Word16 bufferOldSize); + + +void lerp(Word16 *f, Word16 *f_out, Word16 bufferNewSize, Word16 bufferOldSize) +{ + Word16 tmp1, tmp2, tmpexp; + BASOP_Util_Divide_MantExp(bufferNewSize, 0, bufferOldSize, 0, &tmp1, &tmpexp); + tmp1 = shr(tmp1,3); /*Q12*/ + tmp1 = shl(tmp1,tmpexp); + + BASOP_Util_Divide_MantExp(bufferOldSize, 0, bufferNewSize, 0, &tmp2, &tmpexp); + tmp2 = shr(tmp2,3); /*Q12*/ + tmp2 = shl(tmp2,tmpexp); + test(); + test(); + IF(GT_16(tmp1,16224 /*3,9609375 in Q12*/)) + { + Word16 tmpNewSize = shl(bufferOldSize,1); + WHILE(GT_16(bufferNewSize, bufferOldSize)) + { + BASOP_Util_Divide_MantExp(bufferNewSize, 0, bufferOldSize, 0, &tmp1, &tmpexp); + tmp1 = shr(tmp1,3); /*Q12*/ + tmp1 = shl(tmp1,tmpexp); + test(); + IF(LE_16(tmp1,16224 /*3,9609375 in Q12*/)) + { + tmpNewSize = bufferNewSize; + } + + lerp_proc(f, f_out, tmpNewSize, bufferOldSize); + + f = f_out; + bufferOldSize = tmpNewSize; + tmpNewSize = shl(tmpNewSize,1); + } + } + ELSE IF(GT_16(tmp2,16224 /*3,9609375 in Q12*/)) + { + Word16 tmpNewSize = shr(bufferOldSize,1); + WHILE(LT_16(bufferNewSize, bufferOldSize)) + { + BASOP_Util_Divide_MantExp(bufferOldSize, 0, bufferNewSize, 0, &tmp2, &tmpexp); + tmp2 = shr(tmp2,3); /*Q12*/ + tmp2 = shl(tmp2,tmpexp); + test(); + IF(LE_16(tmp2,16224 /*3,9609375 in Q12*/)) + { + tmpNewSize = bufferNewSize; + } + + lerp_proc(f, f_out, tmpNewSize, bufferOldSize); + + f = f_out; + bufferOldSize = tmpNewSize; + tmpNewSize = shr(tmpNewSize,1); + } + } + else + { + lerp_proc(f, f_out, bufferNewSize, bufferOldSize); + } +} + +void lerp_proc(Word16 *f, Word16 *f_out, Word16 bufferNewSize, Word16 bufferOldSize) +{ + + Word16 i, idx, n; + Word16 diff; + Word32 pos, shift; + Word16 buf[2*L_FRAME_MAX]; + Word16 *ptr; + + + ptr = f_out; + test(); + test(); + test(); + if ( ((f <= f_out) && (f + bufferOldSize >= f_out)) || ((f_out <= f) && (f_out + bufferNewSize >= f)) ) + { + ptr = buf; + move16(); + } + + IF( EQ_16(bufferNewSize, bufferOldSize)) + { + Copy(f, f_out, bufferNewSize); + return; + } + + shift = L_shl(L_deposit_l(div_s( bufferOldSize, shl(bufferNewSize, 4))), 4-shift_e+16); + + pos = L_sub(L_shr(shift, 1), 32768l/*1.0f Q15*/); + + /* Adjust interpolation shift to avoid accessing beyond end of input buffer. */ + if ( LT_32(shift, 19661l/*0.3f Q16*/)) + { + pos = L_sub(pos, 8520l/*0.13f Q16*/); + } + + assert(pos_e == shift_e); + + /* first point of interpolation */ + IF (pos<0) + { + + diff = shr(extract_l(pos), 1); + /*buf[0]=f[0]+pos*(f[1]-f[0]);*/ + move16(); + *ptr++ = add(f[0], msu_r(L_mult(diff, f[1]),diff, f[0])); + } + ELSE + { + + idx=extract_h(pos); + + diff = lshr(extract_l(pos), 1); + + move16(); + *ptr++ = add(f[idx], msu_r(L_mult(diff, f[idx+1]), diff, f[idx])); + } + + pos = L_add(pos, shift); + idx = s_max(0, extract_h(pos)); + + n = sub(bufferNewSize, 1); + FOR ( i=1; i= f_out)) || ((f_out <= f) && (f_out + bufferNewSize >= f)) ) + { + Copy( buf, f_out, bufferNewSize ); + } + +} diff --git a/lib_com/limit_t0_fx.c b/lib_com/limit_t0_fx.c new file mode 100644 index 0000000..d5b31b1 --- /dev/null +++ b/lib_com/limit_t0_fx.c @@ -0,0 +1,259 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "rom_basop_util.h" + + +/*-------------------------------------------------* + * Local constants + *-------------------------------------------------*/ + +#define LIMIT_PIT_REL_LOWER 2 /* delta interval to extend pitch coding in relative Q */ +#define LIMIT_PIT_REL_UPPER 0 + +/*-------------------------------------------------* + * limit_T0() + * + * Close-loop pitch lag search limitation + *-------------------------------------------------*/ + + +void limit_T0_fx( + const Word16 L_frame, /* i : length of the frame */ + const Word16 delta, /* i : Half the close-loop searched interval */ + const Word16 pit_flag, /* i : selecting absolute(0) or delta(1) pitch quantization */ + const Word16 limit_flag, /* i : flag for Q limits (0=restrained, 1=extended) */ + const Word16 T0, /* i : rough pitch estimate around which the search is done */ + const Word16 T0_frac, /* i : pitch estimate fractional part */ + Word16 *T0_min, /* o : lower pitch limit */ + Word16 *T0_max /* o : higher pitch limit */ +) +{ + + Word16 delta2,T1; + Word16 pit_min, pit_max; + + IF( limit_flag == 0 ) /* restrained Q limits */ + { + /* set limits */ + IF( EQ_16(L_frame,L_FRAME)) + { + pit_max = PIT_MAX; + move16(); + pit_min = PIT_MIN; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + pit_max = PIT16k_MAX; + move16(); + pit_min = PIT16k_MIN; + move16(); + } + + delta2 = sub(shl(delta,1),1); + T1 = T0; + move16(); + + if( GE_16(T0_frac,2)) + { + T1 = add(T1,1); + } + + *T0_min = sub(T1,delta); + move16(); + + *T0_min = s_max(*T0_min,pit_min); + + *T0_max = add(*T0_min,delta2); + move16(); + + IF( GT_16(*T0_max,pit_max)) + { + *T0_max = pit_max; + move16(); + *T0_min = sub(*T0_max,delta2); + move16(); + } + } + ELSE /* extended Q limits */ + { + /* set limits */ + IF( EQ_16(L_frame, L_FRAME)) + { + pit_max = PIT_MAX; + move16(); + pit_min = PIT_MIN_EXTEND; + move16(); + if( EQ_16(limit_flag, 2)) + { + pit_min = PIT_MIN_DOUBLEEXTEND; + move16(); + } + } + ELSE /* L_frame == L_FRAME16k */ + { + pit_max = PIT16k_MAX; + move16(); + pit_min = PIT16k_MIN_EXTEND; + move16(); + } + + delta2 = sub(shl(delta,1),1) ; + move16(); + T1 = T0; + move16(); + if( GE_16(T0_frac,2)) + { + T1 = add(T1,1); + } + *T0_min = sub(T1, delta); + move16(); + IF( pit_flag == 0 ) + { + /* subframes with absolute search: keep Q range */ + *T0_min = s_max(*T0_min,pit_min); + + *T0_max = add(*T0_min, delta2); + move16(); + IF( GT_16(*T0_max,pit_max)) + { + *T0_max = pit_max; + move16(); + *T0_min = sub(*T0_max, delta2); + move16(); + } + } + ELSE + { + /* subframes with relative search: extend Q range */ + *T0_min = s_max(*T0_min,sub(pit_min, LIMIT_PIT_REL_LOWER)); + move16(); + + *T0_min = s_max(*T0_min,L_INTERPOL); + *T0_max = *T0_min + delta2; + move16(); + + IF( GT_16(*T0_max, add(pit_max, LIMIT_PIT_REL_UPPER))) + { + *T0_max = add(pit_max, LIMIT_PIT_REL_UPPER); + move16(); + *T0_min = sub(*T0_max, delta2); + move16(); + } + } + } + return; +} + + +#define inv_T0_res InvIntTable + +/*-------------------------------------------------* +* Routine limit_T0_voiced() +* +* Close-loop pitch lag search limitation +*-------------------------------------------------*/ +void limit_T0_voiced( + const Word16 nbits, + const Word16 res, + const Word16 T0, /* i : rough pitch estimate around which the search is done */ + const Word16 T0_frac, /* i : pitch estimate fractional part */ + const Word16 T0_res, /* i : pitch resolution */ + Word16 *T0_min, /* o : lower pitch limit */ + Word16 *T0_min_frac, /* o : lower pitch limit */ + Word16 *T0_max, /* o : higher pitch limit */ + Word16 *T0_max_frac, /* o : higher pitch limit */ + const Word16 pit_min, /* i : Minimum pitch lag */ + const Word16 pit_max /* i : Maximum pitch lag */ +) +{ + Word16 T1, temp1, temp2, res2; + + + assert(res > 1 && res<=6); + + res2 = res; + move16(); + if(EQ_16(res,6)) + { + res2 = shr(res2,1); + } + + /* Mid-point */ + T1 = T0; + test(); + if( GT_16(T0_res,1)&&GE_16(T0_frac,(shr(T0_res,1)))) + { + T1 = add(T1,1); + } + + /* Lower-bound */ + temp1 = sub(i_mult(T1,res),shl(1,sub(nbits,1))); + + temp2 = mult(temp1,inv_T0_res[res2]); + if(EQ_16(res,6)) + { + temp2 = shr(temp2,1); + } + + *T0_min = temp2; + move16(); + + *T0_min_frac = sub(temp1,i_mult(temp2,res)); + move16(); + + IF ( LT_16(*T0_min,pit_min)) + { + *T0_min = pit_min; + move16(); + *T0_min_frac = 0; + move16(); + } + + /* Higher-bound */ + temp1 = add(i_mult(*T0_min,res),add(*T0_min_frac,sub(shl(1,nbits),1))); + + temp2 = mult(temp1,inv_T0_res[res2]); + if(EQ_16(res,6)) + { + temp2 = shr(temp2,1); + } + + *T0_max = temp2; + move16(); + + *T0_max_frac = sub(temp1,i_mult(temp2,res)); + move16(); + + IF ( GT_16(*T0_max,pit_max)) + { + *T0_max = pit_max; + move16(); + + *T0_max_frac = sub(res,1); + move16(); + + temp1 = add(i_mult(*T0_max,res),sub(*T0_max_frac,sub(shl(1,nbits),1))); + + temp2 = mult(temp1,inv_T0_res[res2]); + if(EQ_16(res,6)) + { + temp2 = shr(temp2,1); + } + move16(); + *T0_min = temp2; + + *T0_min_frac = sub(temp1, i_mult(temp2,res)); + move16(); + } + + + return; +} diff --git a/lib_com/logqnorm_fx.c b/lib_com/logqnorm_fx.c new file mode 100644 index 0000000..957fcdf --- /dev/null +++ b/lib_com/logqnorm_fx.c @@ -0,0 +1,195 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required for wmc_tool */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "cnst_fx.h" /* Common constants */ + +/* Local constants */ +#define THREN2POW 1518500250L + +/*--------------------------------------------------------------------------* + * logqnorm_fx + * + * Log quantization for norms of sub-vectors + *--------------------------------------------------------------------------*/ + +void logqnorm_fx( + const Word32 *L_x, /* i : coefficient vector Qx */ + const Word16 qx, /* i : Q value of input */ + Word16 *k, /* o : index Q0 */ + const Word16 L, /* i : codebook length Q0 */ + const Word16 N, /* i : sub-vector size Q0 */ + const Word16 hvq_flag /* i : HVQ flag Q0 */ +) +{ + Word16 i, m; + Word16 coefs_shift, power_shift, temp_shift; + Word32 L_temp, L_temp1, L_temp2; + Word16 coefs16[MAX_SFM_LEN_FX]; + UWord16 lsb; + + Word16 offset = add(3,shl(qx,1)); /* 3 + 2*qx */ + + lsb = 0U; /* to avoid compilation warnings */ + + L_temp1 = L_deposit_l(1); + FOR (i=0; i +#include +#include "prot_fx.h" +#include "stl.h" + + +/** + * \brief inplace long shift right: a[] = a[] >> bits + * Logical shift right of UWord32 vector a[] by 'bits' positions. + * BASOP cycles: FLC cycles + * len = 1: 8 lena = 2: 24 + * len = 2: 13 lena = 4: 34 + * len = 3: 18 lena = 6: 44 + * len = 4: 23 lena = 8: 54 + * \param UWord32 a[] + * Input: vector of the length len + * \param Word16 bits + * Input: number of bit positions to shift right in range 1..31 + * Note: 'bits' must not be 0, this would cause a shift-overflow + * \param Word16 len + * Input: length of vector a[] in units of 'UWord32' + * + * \return void + */ + +void longshr(UWord32 a[], Word16 bits, Word16 len) +{ + Word16 fracb_u, k; + + assert ((bits > 0) && (bits < 32)); + + fracb_u = sub(32,bits); + len = sub(len,1); + FOR (k=0; k < len; k++) + { + a[k] = L_or(L_lshr(a[k],bits),L_lshl(a[k+1],fracb_u)); + move32(); + } + a[k] = L_lshr(a[k],bits); + move32(); + + return; +} diff --git a/lib_com/low_rate_band_att_fx.c b/lib_com/low_rate_band_att_fx.c new file mode 100644 index 0000000..680b95e --- /dev/null +++ b/lib_com/low_rate_band_att_fx.c @@ -0,0 +1,219 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" +#include "stl.h" /* required for wmc_tool */ + + +/*--------------------------------------------------------------------------* + * fine_gain_pred() + * + * Fine gain prediction + *--------------------------------------------------------------------------*/ + +void fine_gain_pred_fx( + const Word16 *sfm_start, /* i : Sub band start indices */ + const Word16 *sfm_end, /* i : Sub band end indices */ + const Word16 *sfm_size, /* i : Sub band bandwidths */ + const Word16 *i_sort, /* i : Energy sorting indices */ + const Word16 *K, /* i : Number of pulses per band */ + const Word16 *maxpulse, /* i : Maximum pulse per band */ + const Word16 *R, /* i : Bits per sub band Q3 */ + const Word16 num_sfm, /* i : Number of sub bands */ + Word16 *xq, /* i/o: Quantized vector /quantized vector with finegain adj Q15*/ + Word16 *y, /* i/o: Quantized vector (int) */ + Word16 *fg_pred, /* o : Predicted fine gains Q12 */ + const Word16 core /* i : Core */ +) +{ + Word16 i, band; + Word16 gp; + Word32 xx; + Word16 accuracy; + Word16 k, bw; + + Word16 shift, bw_idx; + Word16 tmp, exp, exp2; + Word32 L_tmp; + UWord16 lsb; + + FOR( band = 0; band < num_sfm; band++) + { + k = K[i_sort[band]]; + move16(); + + IF( k > 0) + { + /* bw, bw_idx only used if k>0 */ + bw = sfm_size[i_sort[band]]; + move16(); /* allowed. 8, 16, 24,32,48,64,80,96 */ + bw_idx = band_len_idx[ shr(bw,3) ]; + move16(); /* bw_idx= 0: 7 */ + xx = L_deposit_l(0); + shift = band_len_ener_shift[bw_idx]; + FOR(i = sfm_start[i_sort[band]]; i < sfm_end[i_sort[band]]; i++) + { + /*xx += xq[i] * xq[i]; */ + tmp = shr(xq[i], shift); /*15-shift */ + xx = L_mac0(xx, tmp, tmp); /*30-2*shift */ + } + + IF ( xx > 0) + { + /* Normalize synthesis to RMS=1.0 */ + /*gp = (float) sqrt(bw / xx); */ + exp = norm_l(xx); + L_tmp = L_shl(xx, exp); /*2*(15-shift)+exp */ + exp = sub(31, add(exp, sub(30, shl(shift,1)))); + L_tmp = Isqrt_lc(L_tmp, &exp); /*31 - exp */ + Mpy_32_16_ss(L_tmp, fine_gain_pred_sqrt_bw[bw_idx], &L_tmp, &lsb); /*31-exp+11-15=27-exp */ + gp = round_fx(L_shl(L_tmp, add(1, exp))); /*27-exp+1+exp-16=12 */ + + test(); + test(); + IF (EQ_16(core, HQ_CORE)&&R!=NULL&&LE_16(R[i_sort[band]],256)) /* 256 is 32 in Q3 */ + { + /*accuracy = ((float)k/(float)bw)*maxpulse[i_sort[band]]; */ + L_tmp = L_mult(k, inv_tbl_fx[bw]); /*0+15+1 */ + exp2 = norm_l(L_tmp); + tmp = round_fx(L_shl(L_tmp, exp2)); /*16+exp2-16 */ + L_tmp = L_mult0(maxpulse[i_sort[band]], tmp); /*0+exp2 */ + exp = norm_l(L_tmp); + accuracy = round_fx(L_shl(L_tmp, exp)); /*exp2+exp-16=exp-16 */ + exp = add(exp, exp2); + + /*gp *= 1.0f - 0.05f / accuracy; */ + tmp = div_s(13107, accuracy); /* 0.05 in Q18 */ + tmp = shr(tmp, sub(34, exp)); /*15+18-exp+16-15=34-exp */ + tmp = sub(32767, tmp); + tmp = s_max(27554, tmp); /* Limit attenuation to norm quantizer error, 2^-0.25 in Q15 */ + gp = mult_r(tmp, gp); /*15+12+1-16=12 */ + } + + fg_pred[band] = gp; + move16(); + } + ELSE + { + fg_pred[band] = 0; + move16(); + } + } + ELSE + { + fg_pred[band] = 0; + move16(); + FOR(i = sfm_start[i_sort[band]]; i < sfm_end[i_sort[band]]; i++) + { + y[i] = 0; + move16(); + xq[i] = 0; + move16(); + } + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * get_max_pulses() + * + * Find the maximum pulse height (in unit pulses) in each band + *--------------------------------------------------------------------------*/ + +void get_max_pulses_fx( + const Word16 *band_start, /* i : Sub band start indices */ + const Word16 *band_end, /* i : Sub band end indices */ + const Word16 *k_sort, /* i : Indices for sorting by energy */ + const Word16 *npulses, /* i : Pulses per sub band */ + const Word16 BANDS, /* i : Number of bands */ + Word16 *inp_vector, /* i/o: Encoded shape vectors (int)*/ + Word16 *maxpulse /* o : Maximum pulse height per band */ +) +{ + Word16 i, k; + Word16 npul; + Word16 maxp; + Word16 tmp; + + FOR (k = 0; k < BANDS; k++) + { + npul = npulses[k_sort[k]]; + move16(); + maxp = 0; + move16(); + IF (npul > 0) + { + FOR (i = band_start[k_sort[k]]; i < band_end[k_sort[k]]; i++) + { + tmp = abs_s(inp_vector[i]); + if (GT_16(tmp, maxp)) + { + maxp = tmp; + move16(); + } + } + } + maxpulse[k_sort[k]] = maxp; + move16(); + } + + return; +} + +/*--------------------------------------------------------------------------* + * fine_gain_dec() + * + * Fine gain decoder. Decodes fine gain adjustments and applies correction to + * predicted fine gains + *--------------------------------------------------------------------------*/ + +void fine_gain_dec_fx +( + Decoder_State_fx *st, + const Word16 *ord, /* i : Indices for energy order */ + const Word16 num_sfm, /* i : Number of bands */ + const Word16 *gain_bits, /* i : Gain adjustment bits per sub band */ + Word16 *fg_pred /* i/o: Predicted gains / Corrected gains */ +) +{ + Word16 band; + Word16 gbits; + Word16 idx, tmp1, exp1; + Word16 gain_dbq; + Word32 L_tmp; + + + FOR ( band = 0; band < num_sfm; band++) + { + gbits = gain_bits[ord[band]]; + IF (gbits > 0) + { + IF (fg_pred[band] != 0) + { + idx = get_next_indice_fx( st, gbits ); + gain_dbq = finegain_fx[gbits-1][idx]; + + /* Update predicted gain with quantized correction */ + L_tmp = L_mult0(gain_dbq, 21771); /* 21771=0.05*log2(10) */ /* 14+17=31 */ + L_tmp = L_shr(L_tmp, 15); + tmp1 = L_Extract_lc(L_tmp, &exp1); + tmp1 = abs_s(tmp1); + tmp1 = extract_l(Pow2(14, tmp1)); + exp1 = sub(14, exp1); + + L_tmp = L_mult0(fg_pred[band], tmp1); /*12+exp1 */ + fg_pred[band] = round_fx(L_shl(L_tmp, sub(16, exp1))); /*12+exp1+16-exp1-16=12 */ + } + } + } + + return; +} + + diff --git a/lib_com/lpc_tools_fx.c b/lib_com/lpc_tools_fx.c new file mode 100644 index 0000000..d690482 --- /dev/null +++ b/lib_com/lpc_tools_fx.c @@ -0,0 +1,1009 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" +#include "stl.h" +#include "basop_mpy.h" +#include "basop_util.h" + + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +#define MAX_LEN_LP 960 /* maximum length in samples of the LP analysis window */ + +/*---------------------------------------------------------------------* + * autocorr() + * + * Compute autocorrelations of input signal + *---------------------------------------------------------------------*/ +void autocorr_fx( + const Word16 x[], /* i : Input signal */ + const Word16 m, /* i : LPC order Q0 */ + Word16 r_h[], /* o : Autocorrelations (msb) Q15 */ + Word16 r_l[], /* o : Autocorrelations (lsb) */ + Word16 *Q_r, /* o : normalisation shift of r Q0 */ + const Word16 len, /* i : Frame lenght */ + const Word16* wind, /* i : Window used */ + Word16 rev_flag, + const Word16 sym_flag /* i : symmetric window flag */ +) +{ + Word16 i, j, norm, shift, y[MAX_LEN_LP]; + Word16 fact; + Word32 L_sum, L_tmp; + + IF(EQ_16(rev_flag,1)) + { + /* Windowing of signal */ + FOR (i = 0; i < len; i++) + { + y[i] = mult_r(x[i], wind[len-i-1]); + move16(); + } + } + ELSE IF( EQ_16(sym_flag,1)) + { + /* symmetric window of even length */ + FOR( i=0; i 0) + { + fact = lshr(-32768, shift); + FOR (i = 0; i < len; i++) + { + y[i] = mult_r(y[i], fact); + move16(); + } + } + ELSE + { + shift = 0; + move16(); + } + + /* Compute and normalize r[0] */ + L_sum = L_mac(1, y[0], y[0]); + FOR (i = 1; i < len; i++) + { + L_sum = L_mac(L_sum, y[i], y[i]); + } + norm = norm_l(L_sum); + L_sum = L_shl(L_sum, norm); + L_Extract(L_sum, &r_h[0], &r_l[0]); /* Put in DPF format (see oper_32b) */ + + /* Compute r[1] to r[m] */ + FOR (i = 1; i <= m; i++) + { + L_sum = L_mult(y[0],y[i]); + FOR (j = 1; j < len - i; j++) + { + L_sum = L_mac(L_sum, y[j], y[j + i]); + } + + L_sum = L_shl(L_sum, norm); + L_Extract(L_sum, &r_h[i], &r_l[i]); /* Put in DPF format (see oper_32b) */ + } + + *Q_r = sub(norm, shl(shift, 1)); + move16(); +} + +/***************************************************************************** + * * + * Function Name : Div_32_opt * + * * + * Purpose : * + * Fractional integer division of two 32 bit numbers. * + * L_num / L_denom. * + * L_num and L_denom must be positive and L_num < L_denom. * + * L_denom = denom_hi<<16 + denom_lo<<1 * + * denom_hi is a normalize number. * + * * + * Inputs : * + * * + * L_num * + * 32 bit long signed integer (Word32) whose value falls in the * + * range : 0x0000 0000 < L_num < L_denom * + * * + * L_denom = denom_hi<<16 + denom_lo<<1 (DPF) * + * * + * denom_hi * + * 16 bit positive normalized integer whose value falls in the * + * range : 0x4000 < hi < 0x7fff * + * denom_lo * + * 16 bit positive integer whose value falls in the * + * range : 0 < lo < 0x7fff * + * * + * Return Value : * + * * + * L_div * + * 32 bit long signed integer (Word32) whose value falls in the * + * range : 0x0000 0000 <= L_div <= 0x7fff ffff. * + * * + * Algorithm: * + * * + * - find = 1/L_denom. * + * First approximation: approx = 1 / denom_hi * + * 1/L_denom = approx * (2.0 - L_denom * approx ) * + * * + * - result = L_num * (1/L_denom) * + ***************************************************************************** +*/ +static +Word32 Div_32_opt (Word32 L_num, Word16 denom_hi, Word16 denom_lo) +{ + Word16 approx /*, hi, lo, n_hi , n_lo*/; + Word32 L_32; + + /* First approximation: 1 / L_denom = 1/denom_hi */ + + approx = div_s ((Word16) 0x3fff, denom_hi); + + /* 1/L_denom = approx * (2.0 - L_denom * approx) */ + + L_32 = Msu_32_16 ((Word32) 0x7fffffffL, denom_hi, denom_lo, approx); + + L_32 = Mpy_32_16_1(L_32, approx); + + /* L_num * (1/L_denom) */ + + L_32 = Mpy_32_32(L_num, L_32); + + L_32 = L_shl (L_32, 2); + + return (L_32); +} + +/* + * E_LPC_lev_dur + * + * Parameters: + * Rh I: Rh[m+1] Vector of autocorrelations (msb) + * Rl I: Rl[m+1] Vector of autocorrelations (lsb) + * A O: A[m] LPC coefficients (m = 16) Qx (A[0] is always 1, so the format can be deduced in the caller with norm_s(A[0])) + * epsP O: error vector, msb + * order I: LPC order Q0 + * + * Function: + * Levinson-Durbin algorithm to compute + * the LPC parameters from the autocorrelations of speech. + * + * Returns: + * void + */ +Word16 E_LPC_lev_dur(const Word16 Rh[], const Word16 Rl[], Word16 A[], + Word32 epsP[], const Word16 order + ,Word16 *mem + ) +{ + return(E_LPC_lev_dur_stab(Rh, Rl, A, epsP, order, mem, 32750)); /* 0.99945 in Q15 */ +} + +Word16 E_LPC_lev_dur_stab(const Word16 Rh[], const Word16 Rl[], Word16 A[], + Word32 epsP[], const Word16 order, + Word16 *mem, Word16 k_max + ) +{ + Word16 i, j, k; + Word16 hi, lo; + Word16 Kh, Kl; /* reflection coefficient; hi and lo */ + Word16 alp_h, alp_l, alp_exp; /* Prediction gain; hi lo and exponent */ + Word32 t0, t1, t2; /* temporary variables */ + Word16 flag; + Word16 Ah[TCXLTP_LTP_ORDER + 1], Al[TCXLTP_LTP_ORDER + 1]; /* LPC coef. in double prec. */ + + + BASOP_SATURATE_WARNING_OFF + if(epsP!=NULL) + { + epsP[0] = L_Comp(Rh[0], Rl[0]); + move32(); + } + + flag=0; + move16(); + + /* K = A[1] = -R[1] / R[0] */ + t1 = L_Comp(Rh[1], Rl[1]); /* R[1] in Q31 */ + t2 = L_abs(t1); /* abs R[1] */ + t0 = L_deposit_l(0); + IF (Rh[0] != 0) + { + t0 = Div_32_opt(t2, Rh[0], Rl[0]); /* R[1]/R[0] in Q31 */ + /* Cause a difference in MODE1 due to different implementation of div32*/ + } + if (t1 > 0) + { + t0 = L_negate(t0); /* -R[1]/R[0] */ + } + Kl = L_Extract_lc(t0, &Kh); /* K in DPF */ + t0 = L_shr(t0, 4); /* A[1] in Q27 */ + L_Extract(t0, &Ah[1], &Al[1]); /* A[1] in DPF */ + + /* Alpha = R[0] * (1-K**2) */ + t0 = Sqr_32(Kh, Kl); /* K*K in Q31 */ + t0 = L_abs(t0); /* Some case <0 !! */ + t0 = L_sub((Word32) 0x7fffffffL, t0); /* 1 - K*K in Q31 */ + lo = L_Extract_lc(t0, &hi); /* DPF format */ + t0 = Mpy_32(Rh[0], Rl[0], hi, lo); /* Alpha in Q31 */ + if(epsP!=NULL) + { + epsP[1] = t0; + move32(); + } + + /* Normalize Alpha */ + alp_exp = norm_l(t0); + t0 = L_shl(t0, alp_exp); + alp_l = L_Extract_lc(t0, &alp_h); + /* DPF format */ + + /*--------------------------------------* + * ITERATIONS I=2 to m + *--------------------------------------*/ + + FOR (i = 2; i <= order; i++) + { + /* t0 = SUM(R[j]*A[i-j], j=1, i-1) + R[i] */ + t0 = L_deposit_l(0); + FOR (j = 1; j < i; j++) + { + t0 = Mac_32(t0, Rh[j], Rl[j], Ah[i - j], Al[i - j]); + } + + t0 = L_shl(t0, 4); /* result in Q27 -> convert to Q31 */ + /* No overflow possible */ + + /* Compose and add R[i] in Q3 */ + t0 = L_mac(t0, Rl[i], 1); + t0 = L_msu(t0, Rh[i], -32768); + + /* K = -t0 / Alpha */ + t1 = L_abs(t0); + t2 = L_deposit_l(0); + IF (alp_h != 0) + { + t2 = Div_32_opt(t1, alp_h, alp_l); /* abs(t0)/Alpha */ + /* Cause a difference in MODE1 due to different implementation of div32*/ + } + + if (t0 > 0) + { + t2 = L_negate(t2); /* K =-t0/Alpha */ + } + t2 = L_shl(t2, alp_exp); /* denormalize; compare to Alpha */ + test(); + if ((mem!=NULL) && ((GT_16(abs_s(extract_h(t2)), k_max)))) + { + flag=1; + move16();/* Test for unstable filter. If unstable keep old A(z) */ + } + if ((mem!=NULL) && ((LT_32(L_abs(t2), 5)))) + { + flag=1; + move16(); /*R matrix not reliable (R saturated for many coeff), keep old A(z) */ + } + Kl = L_Extract_lc(t2, &Kh); /* K in DPF */ + + /*------------------------------------------* + * Compute new LPC coeff. -> An[i] + * An[j]= A[j] + K*A[i-j] , j=1 to i-1 + * An[i]= K + *------------------------------------------*/ + + k = mult_r(i, 16384); + FOR (j = 1; j < k; j++) + { + /* Do two Iterations Together to Allow Direct Update of Ah & Al */ + t0 = Mac_32(L_Comp(Ah[j], Al[j]), Kh, Kl, Ah[i-j], Al[i-j]); + t1 = Mac_32(L_Comp(Ah[i-j], Al[i-j]), Kh, Kl, Ah[j], Al[j]); + L_Extract(t0, &Ah[j], &Al[j]); + L_Extract(t1, &Ah[i-j], &Al[i-j]); + } + IF (s_and(i, 1) == 0) + { + t0 = Mac_32(L_Comp(Ah[j], Al[j]), Kh, Kl, Ah[i-j], Al[i-j]); + L_Extract(t0, &Ah[j], &Al[j]); + } + t2 = L_shr(t2, 4); /* t2 = K in Q31 ->convert to Q27 */ + L_Extract(t2, &Ah[i], &Al[i]); /* An[i] in Q27 */ + + /* Alpha = Alpha * (1-K**2) */ + t1 = L_mult(Kh, Kh); /* K*K in Q31 */ + t0 = L_mac(t1, mult(Kh, Kl), 2); + t0 = L_abs(t0); /* Some case <0 !! */ + t0 = L_sub((Word32) 0x7fffffffL, t0); /* 1 - K*K in Q31 */ + lo = L_Extract_lc(t0, &hi); /* DPF format */ + t0 = Mpy_32(alp_h, alp_l, hi, lo); /* Alpha in Q31 */ + + + /* store denormalized alpha in epsP */ + t1 = L_shr(t0, alp_exp); + if(epsP!=NULL) + { + epsP[i] = t1; + move32(); + } + + /* Normalize Alpha */ + j = norm_l(t0); + t0 = L_shl(t0, j); + alp_l = L_Extract_lc(t0, &alp_h);/* DPF format */ + alp_exp = add(alp_exp, j); /* Add normalization to alp_exp */ + } + + /* Adaptive scaling */ + t1 = L_deposit_l(0); + FOR (i = 1; i <= order; i++) + { + t0 = L_Comp(Ah[i], Al[i]); + t1 = L_max( t1, L_abs(t0) ); + } + k = s_min( norm_l( t1 ), 3 ); + A[0] = shl( 2048, k ); + move16(); + FOR (i = 1; i <= order; i++) + { + t0 = L_Comp(Ah[i], Al[i]); + A[i] = round_fx(L_shl(t0, k)); + } + + BASOP_SATURATE_WARNING_ON + IF (mem != NULL) + { + /* Enforce stable LPC filter - parcorr[0] and parcorr[1] are not LPC coeffiecients */ + IF(flag) + { + Copy(mem, A, order + 1); + } + ELSE /* If stable LPC filter, store into memories */ + { + Copy(A, mem, order + 1); + } + } + + + return(flag); +} + +/* + * E_LPC_a_add_tilt + * + * Parameters: + * a I: LP filter coefficients (m+1 coeffs) + * ap O: modified LP filter coefficients (m+2 coeffs) + * gamma I: tilt factor + * m I: order of LP filter + * + * Function: + * Modified LP filter by adding 1st order pre-premphasis, Ap(z)=A(z).(1-gamma.z^(-1)) + * + * Returns: + * void + */ +void E_LPC_a_add_tilt(const Word16 *a, Word16 *ap, Word16 gamma, Word16 m) +{ + Word16 i; + Word32 Amax, Atmp[M+2]; + Word16 shift; + + + + + Amax = L_mult( 16384, a[0] ); + FOR (i = 1; i <= m; i++) + { + Atmp[i] = L_sub( L_mult(16384, a[i]), L_mult0(gamma, a[i-1]) ); + move32(); + Amax = L_max( Amax, L_abs( Atmp[i] ) ); + } + Atmp[m+1] = L_negate( L_mult0(gamma, a[m]) ); + move32(); + Amax = L_max( Amax, L_abs( Atmp[m+1] ) ); + shift = norm_l( Amax ); + ap[0] = shl( a[0], sub(shift,1) ); + move16(); + FOR (i = 1; i <= m; i++) + { + ap[i] = round_fx( L_shl( Atmp[i], shift ) ); + } + ap[m+1] = round_fx( L_shl( Atmp[m+1], shift ) ); + +} + +void E_LPC_int_lpc_tcx(const Word16 lsp_old[], /* input : LSPs from past frame Q15 */ + const Word16 lsp_new[], /* input : LSPs from present frame Q15 */ + Word16 a[] /* output: interpolated LP coefficients Q12 */ + ) +{ + Word16 i, lsp[M]; + + + + FOR (i = 0; i < M; i++) + { + /*lsp[i] = lsp_old[i]*0.125f + lsp_new[i]*0.875f;*/ + lsp[i] = round_fx(L_mac(L_mult(lsp_old[i],4096),lsp_new[i],28672)); + } + E_LPC_f_lsp_a_conversion(lsp, a, M); + + + return; +} + +static void lsp_reorder( + Word16 *lsp, /* (I/O): LSP vector (acos() domain) Q13*1.2732 */ + Word16 min_dist, /* (I): minimum required distance Q13*1.2732 */ + Word16 lpcorder /* (I): LPC order Q0 */ +) +{ + Word16 i; + Word16 lsp_min, lsp_max; + + + /* Verify the LSF ordering and minimum GAP */ + lsp_min = min_dist; + move16(); + FOR (i=0; i=0; --i) + { + lsp[i] = s_min(lsp[i], lsp_max); + move16(); + lsp_max = sub(lsp[i], min_dist); + } + } + +} + +/* Approximate unweighting */ +Word16 E_LPC_lsp_unweight( + /* const */ Word16 lsp_w[], /* (I): weighted xSP Q15 */ + Word16 lsp_uw[], /* (O): unweighted xSP Q15 */ + Word16 lsf_uw[], /* (O): unweighted LSF Q1*1.28 */ + Word16 inv_gamma, /* (I): inverse weighting factor Q14 */ + Word16 lpcorder /* (I): prediction order Q0 */ +) +{ + Word16 lsp_w_orig[M], lsp_w_diff[M], mean, step; /* Q13*1.2732 */ + const lsp_unw_triplet *unw_coeffs = NULL; + Word16 i; + + step = 0; /* to avoid compilation warnings */ + + + assert(lpcorder == 16); + + /* Table selection */ + IF (EQ_16(inv_gamma, GAMMA16k_INV)) + { + unw_coeffs = p16_gamma0_94to1; + move16(); + } + ELSE IF (EQ_16(inv_gamma, GAMMA1_INV)) + { + unw_coeffs = p16_gamma0_92to1; + move16(); + } + ELSE + { + assert(0); + } + + /* step = M_PI/(float)(lpcorder+1); */ + step = 1927; + move16(); + mean = 0; + move16(); + + /* Apply acos() and get mean removed version */ + FOR (i=0; i 0.01f*2^27/2^30 */ + Word32 tmp_epsP; + + + + mM1 = sub(m,1); + + s = getScaleFactor32(r,add(m,1)); + IF (s!=0) + { + scale_sig32(r,add(m,1),s); /* scale in-place */ + } + + g1 = r; + Copy32(r+1,g0,m); + + /* compute g0[0]/g1[0], where g0[0] < g1[0] */ + temp16 = negate(divide3232(g0[0], g1[0])); + reflCoeff[0] = temp16; + move16(); + move32(); + epsP[0] = r[0]; + + + FOR (i=0; i= 0; specix++);*/ + WHILE (mult(s,spec_r[specix]) >= 0) specix = add(specix, 1); + + tmp = divide1616(spec_r[specix-1], sub(spec_r[specix-1],spec_r[specix] ) ); + move16(); + /*lsf[lsfix] = L_add(L_deposit_h(sub(specix,1)) , L_shl(L_deposit_l(tmp),1));*/ /*Q16*/ + lsf[lsfix] = add(shl(sub(specix,1),7) , shr((tmp),8)); /*7Q8*/ + + lsfix++; + + /*check for the next zero crossing*/ + /*for (; s*spec_i[specix] >= 0; specix++);*/ + + WHILE (mult(s,spec_i[specix]) >= 0) specix = add(specix, 1); + + tmp = divide1616(spec_i[specix-1], sub(spec_i[specix-1],spec_i[specix]) ); + move16(); + /*lsf[lsfix] = L_add(L_deposit_h(sub(specix,1)) , L_shl(L_deposit_l(tmp),1));*/ /*Q16*/ + lsf[lsfix] = add(shl(sub(specix,1),7) , shr((tmp),8)); /*7Q8*/ + + lsfix++; + + spec_r[speclen] = s; + move16(); + spec_i[speclen] = s; + move16(); + + s = negate(s); + } + + IF (LT_16(lsfix,16)) + { + FOR(i=0; i<16; i++) + { + lsf[i] = old_lsf[i]; + move16(); + } + } + + return; +} + +void E_LPC_a_lsf_isf_conversion(Word16 *lpcCoeffs, Word16 *lsf, const Word16 *old_lsf, Word16 lpcOrder, Word8 lpcRep) +{ + Word32 RealFFT[128]; + Word32 ImagFFT[128]; + Word16 RealOut[130]; + Word16 ImagOut[130]; + Word32 *ptrReal; + Word32 *ptrImag; + Word16 n, i, j, step, scale; + const PWord16 *ptwiddle, *pwn17, *pwn17i; + PWord16 *pwn15, *pwn15i, tmpw15; + Word16 N = 256; + Word16 s[4]; + Word32 L_tmp, L_tmp1, L_tmp3; + Word16 lpc[19]; + + + /* half length FFT */ + scale = add(norm_s(lpcCoeffs[0]),1)+5; + move16(); + + /*s = [sum(a) ((-1).^(1:length(a)))*a];*/ + L_tmp = L_deposit_h(0); + FOR(j=0; j<=lpcOrder; j++) + { + L_tmp = L_mac(L_tmp, lpcCoeffs[j], 0x800); + } + /*s[1] = round_fx(L_tmp); move16();*/ + + L_tmp1 = L_deposit_h(0); + FOR(j=0; jv.re), lpc[2*j+1],ptwiddle->v.im),scale); + move32(); + ptrImag[j*8] = L_shl(L_mac(L_mult(lpc[2*j+1],ptwiddle->v.re), lpc[2*j],ptwiddle->v.im),scale); + move32(); + ptwiddle++; + } + + ptrReal[j*8] = L_shl(L_mac(0,lpc[2*j],ptwiddle->v.re),scale); + move32(); + ptrImag[j*8] = L_shl(L_mac(0, lpc[2*j],ptwiddle->v.im),scale); + move32(); + ptwiddle++; + j++; + FOR(; j<16; j++) + { + ptrReal[j*8] = L_deposit_h(0); + ptrImag[j*8] = L_deposit_h(0); + ptwiddle++; + } + + fft16(ptrReal, ptrImag, 8, 0); + + ptrReal++; + ptrImag++; + + } + + /* pre-twiddle */ + BASOP_getTables(NULL, &ptwiddle, &step, 128); + IF (lpcRep != 0) + { + pwn17i = &w19N[126]; + pwn17 = w19N; + } + ELSE + { + pwn17i = &w18N[126]; + pwn17 = w18N; + } + + pwn15 = &tmpw15; + pwn15i = &tmpw15; + + RealOut[0] = round_fx(2*L_add(RealFFT[0], ImagFFT[0])); + ImagOut[0] = 0; + move16(); + + RealOut[128] = 0; + move16(); + ImagOut[128] = round_fx(L_sub(L_add(RealFFT[0],RealFFT[0]), L_add(ImagFFT[0], ImagFFT[0]))); + + ptwiddle += 8; + FOR(i=1; i<=N/2/4; i++) + { + Word16 ReAr = extract_h(L_add(RealFFT[i],RealFFT[N/2-i])); + Word16 ReBr = extract_h(L_sub(RealFFT[N/2-i], RealFFT[i])); + Word16 ImAr = extract_h(L_sub(ImagFFT[i], ImagFFT[N/2-i])); + Word16 ImBr = extract_h(L_add(ImagFFT[i], ImagFFT[N/2-i])); + BASOP_SATURATE_WARNING_OFF + tmpw15.v.re = mac_r(L_mult(ptwiddle->v.re, pwn17->v.re), ptwiddle->v.im, pwn17->v.im); + tmpw15.v.im = msu_r(L_mult(ptwiddle->v.re, pwn17->v.im), ptwiddle->v.im, pwn17->v.re); + BASOP_SATURATE_WARNING_ON + RealOut[i] = mac_r(L_msu(L_msu(L_mult(ReAr, pwn17->v.re),ImAr, pwn17->v.im), ReBr, pwn15->v.im), ImBr, pwn15->v.re); + move16(); + ImagOut[i] = mac_r(L_mac(L_mac(L_mult(ReAr, pwn17->v.im), ImAr, pwn17->v.re), ReBr, pwn15->v.re), ImBr, pwn15->v.im); + move16(); + BASOP_SATURATE_WARNING_OFF + tmpw15.v.re = msu_r(L_mult(ptwiddle->v.im, pwn17i->v.im), ptwiddle->v.re, pwn17i->v.re); + tmpw15.v.im = mac_r(L_mult(ptwiddle->v.re, pwn17i->v.im), ptwiddle->v.im, pwn17i->v.re); + BASOP_SATURATE_WARNING_ON + RealOut[N/2-i] = msu_r(L_mac(L_mac(L_mult(ReAr, pwn17i->v.re), ImAr, pwn17i->v.im), ImBr, pwn15i->v.re), ReBr, pwn15i->v.im); + move16(); + ImagOut[N/2-i] = msu_r(L_msu(L_msu(L_mult(ReAr, pwn17i->v.im), ImAr, pwn17i->v.re), ReBr, pwn15i->v.re), ImBr, pwn15i->v.im); + move16(); + + ptwiddle += 8; + pwn17++; + pwn17i--; + } + + ptwiddle -= 16; + /*change real with imaginary for ptwiddle*/ + FOR(; iv.im, pwn17->v.re), ptwiddle->v.re, pwn17->v.im); + tmpw15.v.im = msu_r(L_mult(ptwiddle->v.im, pwn17->v.im), ptwiddle->v.re, pwn17->v.re); + BASOP_SATURATE_WARNING_ON + RealOut[i] = mac_r(L_msu(L_msu(L_mult(ReAr, pwn17->v.re),ImAr, pwn17->v.im), ReBr, pwn15->v.im), ImBr, pwn15->v.re); + move16(); + ImagOut[i] = mac_r(L_mac(L_mac(L_mult(ReAr, pwn17->v.im), ImAr, pwn17->v.re), ReBr, pwn15->v.re), ImBr, pwn15->v.im); + move16(); + BASOP_SATURATE_WARNING_OFF + tmpw15.v.re = msu_r(L_mult(ptwiddle->v.re, pwn17i->v.im), ptwiddle->v.im, pwn17i->v.re); + tmpw15.v.im = mac_r(L_mult(ptwiddle->v.im, pwn17i->v.im), ptwiddle->v.re, pwn17i->v.re); + BASOP_SATURATE_WARNING_ON + RealOut[N/2-i] = msu_r(L_mac(L_mac(L_mult(ReAr, pwn17i->v.re), ImAr, pwn17i->v.im), ImBr, pwn15i->v.re), ReBr, pwn15i->v.im); + move16(); + ImagOut[N/2-i] = msu_r(L_msu(L_msu(L_mult(ReAr, pwn17i->v.im), ImAr, pwn17i->v.re), ReBr, pwn15i->v.re), ImBr, pwn15i->v.im); + move16(); + + ptwiddle -= 8; + pwn17++; + pwn17i--; + } + ptwiddle += 0; + { + Word16 ReAr = extract_h(L_add(RealFFT[i],RealFFT[N/2-i])); + Word16 ReBr = extract_h(L_sub(RealFFT[N/2-i], RealFFT[i])); + Word16 ImAr = extract_h(L_sub(ImagFFT[i], ImagFFT[N/2-i])); + Word16 ImBr = extract_h((L_negate(L_add(ImagFFT[i], ImagFFT[N/2-i])))); + BASOP_SATURATE_WARNING_OFF + tmpw15.v.re = mac_r(L_mult(ptwiddle->v.im, pwn17->v.re), ptwiddle->v.re, pwn17->v.im); + tmpw15.v.im = msu_r(L_mult(ptwiddle->v.im, pwn17->v.im), ptwiddle->v.re, pwn17->v.re); + BASOP_SATURATE_WARNING_ON + RealOut[i] = msu_r(L_msu(L_msu(L_mult(ReAr, pwn17->v.re), ImAr, pwn17->v.im), ReBr, pwn15->v.im), ImBr, pwn15->v.re); + move16(); + ImagOut[i] = msu_r(L_mac(L_mac(L_mult(ReAr, pwn17->v.im), ImAr, pwn17->v.re), ReBr, pwn15->v.re), ImBr, pwn15->v.im); + move16(); + } + + spec2isf(RealOut, ImagOut, 128, lsf, old_lsf); + IF (lpcRep == 0) + { + lsf[lpcOrder - 1] = shl(lpcCoeffs[lpcOrder], add(norm_s(lpcCoeffs[0]),1)); + move16(); /* From Qx to Q15 with saturation */ + lsf[lpcOrder - 1] = xsp_to_xsf(lsf[lpcOrder - 1]); + move16(); + lsf[lpcOrder - 1] = shr(lsf[lpcOrder - 1], 1); + move16(); + } + +} + diff --git a/lib_com/lsf_dec_bfi_fx.c b/lib_com/lsf_dec_bfi_fx.c new file mode 100644 index 0000000..5c47967 --- /dev/null +++ b/lib_com/lsf_dec_bfi_fx.c @@ -0,0 +1,301 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include +#include "stl.h" +#include "basop_util.h" +#include "rom_com_fx.h" +#include "cnst_fx.h" +#include "prot_fx.h" + + +/*---------------------------------------------------------------------* +* routine: lsf_dec_bfi() +* +* Estimate the LSFs in case of FER +* Bad frame, all active speech coders +*---------------------------------------------------------------------*/ +void lsf_dec_bfi( + const Word16 codec_mode, /* i: : codec mode: MODE1 | MODE2 */ + Word16*lsf, /*!< o : 14Q1*1.28 quantized ISFs */ + const Word16*lsfold, /*!< i : 14Q1*1.28 past quantized ISF */ + Word16*lsf_adaptive_mean, /*!< i : 14Q1*1.28 ISF adaptive mean, updated when BFI==0 */ + const Word16 lsfBase[], /* i : base for differential lsf coding */ + Word16*mem_MA, /*!< i/o: 14Q1*1.28 quantizer memory for MA model */ + Word16*mem_AR, /*!< i/o: 14Q1*1.28 quantizer memory for MA model */ + Word16 stab_fac, /*!< i : ISF stability factor (shifted right by 1) */ + const Word16 last_coder_type, /*!< i : coding type in last good received fr. */ + Word16 L_frame, + const Word16 last_good, /*!< i : last good received frame */ + const Word16 nbLostCmpt, /*!< i : counter of consecutive bad frames */ + Word8 plcBackgroundNoiseUpdated, + Word16 *lsf_q_cng, /* o : quantized ISFs for background noise (14Q1*1.28) */ + Word16 *lsf_cng, + Word16 *old_lsf_q_cng, /* o : old quantized ISFs for background noise */ + const Word16 Last_GSC_pit_band_idx, + const Word16 Opt_AMR_WB /* i : IO flag */ + , const Word8 tcxonly + ,const short MODE1_bwidth /* i: coded bandwidth */ +) +{ + Word16 i; + Word16 alpha; + Word32 tmp; + Word16 lsf_mean[M]; + const Word16* pt_meansForFading; + const Word16* pt_meansForMemUpdate; + Word16 beta; + Word16 gap; + + IF (EQ_16(codec_mode,MODE1)) + { + pt_meansForMemUpdate = lsf_mean; + /* Update inital guess to something stable, with proper sampling frequency and format (ISF/LSF)*/ + IF ( Opt_AMR_WB) + { + pt_meansForFading = Mean_isf_wb; + } + ELSE + { + /* 12.8kHz ACELP sampling */ + IF( EQ_16(L_frame,L_FRAME)) + { + pt_meansForFading = GEWB_Ave_fx; + + if (EQ_16(MODE1_bwidth,NB)) + { + pt_meansForFading = GENB_Ave_fx; + } + } + /* 16kHz ACELP sampling */ + ELSE + { + pt_meansForFading = GEWB2_Ave_fx; + } + } + } + ELSE + { + pt_meansForFading = pt_meansForMemUpdate = lsfBase; + test(); + if (lsf_cng != NULL && plcBackgroundNoiseUpdated) + { + pt_meansForFading = lsf_cng; + } + } + IF( LE_16(nbLostCmpt, 3)) + { + test(); + test(); + IF( (EQ_16(last_coder_type, UNVOICED))) /* Clear unvoiced last good frame */ + { + move16(); + alpha = _ALPHA_UU_FX; + } + ELSE IF( EQ_16(last_coder_type,AUDIO)||EQ_16(last_good,INACTIVE_CLAS)) + { + alpha = 32604/*0.995f Q15*/; + move16(); + test(); + if( Last_GSC_pit_band_idx > 0 && GT_16(nbLostCmpt, 1)) + { + alpha = 26214/*0.8f Q15*/; + move16(); + } + } + ELSE IF( EQ_16(last_good,UNVOICED_CLAS)) + { + IF( LE_16(nbLostCmpt,1)) + { + /* If stable, do not flatten the spectrum in the 1st erased frame */ + alpha = add(mult(stab_fac, 32768 - _ALPHA_U_FX_X_2), _ALPHA_U_FX_X_2); + } + ELSE IF(EQ_16(nbLostCmpt,2)) + { + alpha = sub(_ALPHA_U_FX_X_2,shr(_ALPHA_U_FX,1)); /* 0.6 */ + } + ELSE + { + alpha = _ALPHA_U_FX; + move16(); /* go rapidly to CNG spectrum */ + } + } + ELSE IF( EQ_16(last_good ,UNVOICED_TRANSITION)) + { + alpha = _ALPHA_UT_FX; + move16(); + } + ELSE IF( (EQ_16(last_good,VOICED_CLAS))||(EQ_16(last_good,ONSET))) + { + /* clearly voiced - mild convergence to the CNG spectrum for the first 3 erased frames */ + move16(); + alpha = _ALPHA_V_FX; + } + ELSE IF( EQ_16(last_good ,SIN_ONSET)) + { + alpha = _ALPHA_S_FX; + move16(); + } + ELSE + { + alpha = _ALPHA_VT_FX; /* rapid convergence to the CNG spectrum (long erasure, ONSETS) */ + } + } + ELSE + { + Word16 exp = 15; + alpha = Inv16(nbLostCmpt, &exp); /*1.f/bfi_cnt;*/ + alpha = shl(alpha,exp); + } + IF(EQ_16(codec_mode,MODE1)) + { + beta = BETA_FEC_FX; + move16(); + } + ELSE + { + beta = 8192/*0.25f Q15*/; + move16(); + if (plcBackgroundNoiseUpdated) + { + beta = 0/*0.f Q15*/; + move16(); + } + } + FOR (i=0; i +#include +#include "cnst_fx.h" +#include "rom_com_fx.h" +#include "prot_fx.h" +#include "stl.h" +#include "basop_util.h" +#include "prot_fx.h" +#include "options.h" + +#define swap(x,y,type) {type u__p; u__p=x; x=y; y=u__p;} + +extern const Word16 tbl_mid_gen_wb_5b_fx[]; +extern const Word16 tbl_mid_unv_wb_5b_fx[]; + + + + +void midlsf_dec( + const Word16 qlsf0[], /* i: quantized lsf coefficients (3Q12) */ + const Word16 qlsf1[], /* i: quantized lsf coefficients (3Q12) */ + Word16 idx, /* i: codebook index */ + Word16 qlsf[], /* o: decoded lsf coefficients (3Q12) */ + Word16 coder_type, + Word16 *mid_lsf_int, + Word16 prev_bfi, + Word16 safety_net) +{ + const Word16 *ratio=NULL; + Word16 j; + Word32 L_tmp; + Word16 bad_spacing = 0; + + move16(); + /* Select codebook */ + IF ( EQ_16(coder_type, UNVOICED)) + { + ratio = tbl_mid_unv_wb_5b_fx; + } + ELSE + { + ratio = tbl_mid_gen_wb_5b_fx; + } + FOR (j=0; jQ(x2.56+14)*/ + L_tmp = L_mac(L_tmp, ratio[idx*M+j], qlsf1[j]); /*Q(x2.56+14)*/ + qlsf[j] = round_fx(L_shl(L_tmp,2)); /*Q(x2.56)*/ + } + + + IF(mid_lsf_int != NULL) /*at the decoder*/ + { + /* check for incorrect LSF ordering */ + IF ( EQ_16(*mid_lsf_int, 1)) + { + FOR (j=1; j 0 && LT_16(j, M)&<_16(qlsf[j],add(qlsf[j-1],LSF_GAP_MID_FX))) + { + qlsf[j] = add(qlsf[j-1], LSF_GAP_MID_FX); + move16(); + } + + } + } + ELSE + { + /* otherwise, use regular LSF spacing and ordering as in the encoder */ + FOR (j=0; j 0 && LT_16(j, M)&<_16(qlsf[j],add(qlsf[j-1],LSF_GAP_MID_FX))) + { + qlsf[j] = add(qlsf[j-1], LSF_GAP_MID_FX); + move16(); + } + } + } + if ( prev_bfi ) + { + /* continue redoing mid-LSF interpolation with 0.4 in order not to propagate the error */ + *mid_lsf_int = 1; + move16(); + } + if ( safety_net ) + { + /* safety-net encountered -> stop redoing mid-LSF interpolation with 0.4 */ + *mid_lsf_int = 0; + move16(); + } + } + ELSE + { + /* use regular LSF spacing */ + FOR (j=0; j 0 && LT_16(j, M)&<_16(qlsf[j],add(qlsf[j-1],LSF_GAP_MID_FX))) + { + qlsf[j] = add(qlsf[j-1], LSF_GAP_MID_FX); + move16(); + } + } + } + + return; +} +Word16 lsf_ind_is_active( + const Word16 lsf_q_ind[], + const Word16 means[], + Word16 narrowband, + Word16 cdk +) +{ + Word16 lsf[2], min_distance; + + lsf[0] = add(lsf_q_ind[0], means[0]); + move16(); + lsf[1] = add(lsf_q_ind[1], means[1]); + move16(); + + min_distance = lsf[0]; + move16(); + min_distance = s_min(min_distance, sub(lsf[1], lsf[0])); + + assert(narrowband == 0 || narrowband == 1); + assert(cdk == 0 || cdk == 1); + + return sub(min_distance, min_distance_thr[narrowband][cdk]) < 0; +} + diff --git a/lib_com/lsf_tools_fx.c b/lib_com/lsf_tools_fx.c new file mode 100644 index 0000000..f5d593f --- /dev/null +++ b/lib_com/lsf_tools_fx.c @@ -0,0 +1,3426 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "options.h" /* Compilation switches */ +#include "stl.h" +#include "basop_util.h" +#include "rom_com_fx.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include "rom_com_fx.h" /* Static table prototypes */ + + + +#define NC_MAX 8 +#define GUESS_TBL_SZ 256 + +#define depack_4_values(cbp, val0, val1, val2, val3) \ + val0 = shr((cbp)[0], 4); \ + val1 = shr((cbp)[1], 4); \ + val2 = shr((cbp)[2], 4); \ + val3 = add(add(shr(lshl((cbp)[2],12),4),lshr(lshl((cbp)[1],12),8)),s_and((cbp)[0],0xF)); + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define NC ( M/2) +#define NC16k ( M16k/2) + +#define SPC 0.0234952f +#define SPC_plus SPC * 1.001f +#define ALPHA_SQ ( ( 0.5f / PI2) * ( 0.5f / PI2)) + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ +Word16 root_search_fx( Word16 low, Word16 high, Word32 *v_low, Word32 *coef,Word16 order); +Word32 calc_weight( Word16 delta1,Word16 delta2,Word16 *n1 ); +Word32 polynomial_eval_fx( Word16 f, Word32 *coef,Word16 order); +void E_LPC_isf_isp_conversion(const Word16 isf[], Word16 isp[], const Word16 m); +void E_LPC_lsp_lsf_conversion(const Word16 lsp[],Word16 lsf[],const Word16 m); +Word16 E_LPC_f_lsp_pol_get(const Word16 lsp[], Word32 f[], const Word16 n, const Word16 past_Ovf, const Word16 isMODE1); + +static Word16 chebyshev(Word16 x, Word32 *f, Word16 n, Word16 shift) +{ + + Word16 cheb; + Word32 t0, b1, b2; + + cheb = norm_s(x); + if (cheb) + { + x = shl(x,1); + } + t0 = Mpy_32_16_1(*f++, x); /* t0 = x*b2 */ + if (!cheb) + t0 = L_shl(t0, 1); /* t0 = 2*x*b2 */ + b1 = L_add(t0, *f++); /* b1 = 2*x*b2 + f[1] */ + + /* i = 2 */ + t0 = Mpy_32_16_1(b1, x); /* t0 = x*b1 */ + if (!cheb) + t0 = L_shl(t0, 1); /* t0 = 2*x*b1 */ + b2 = L_add(t0, *f++); /* b0 = 2*x*b1 - b2 + f[i] */ + + /* i = 3 */ + t0 = Mpy_32_16_1(b2, x); /* t0 = x*b1 */ + if (!cheb) + t0 = L_shl(t0, 1); /* t0 = 2*x*b1 */ + t0 = L_sub(t0, b1); /* t0 = 2*x*b1 - b2 */ + b1 = L_add(t0, *f++); /* b0 = 2*x*b1 - b2 + f[i] */ + + /* i = 4 */ + t0 = Mpy_32_16_1(b1, x); /* t0 = x*b1 */ + if (!cheb) + t0 = L_shl(t0, 1); /* t0 = 2*x*b1 */ + t0 = L_sub(t0, b2); /* t0 = 2*x*b1 - b2 */ + + /* If the LP order is greater than 10 */ + IF(GT_16(n, 5)) + { + b2 = L_add(t0, *f++); /* b0 = 2*x*b1 - b2 + f[i] */ + /* i = 5 */ + t0 = Mpy_32_16_1(b2, x); /* t0 = x*b1 */ + if (!cheb) + t0 = L_shl(t0, 1); /* t0 = 2*x*b1 */ + t0 = L_sub(t0, b1); /* t0 = 2*x*b1 - b2 */ + b1 = L_add(t0, *f++); /* b0 = 2*x*b1 - b2 + f[i] */ + + /* i = 6 */ + t0 = Mpy_32_16_1(b1, x); /* t0 = x*b1 */ + if (!cheb) + t0 = L_shl(t0, 1); /* t0 = 2*x*b1 */ + t0 = L_sub(t0, b2); /* t0 = 2*x*b1 - b2 */ + } + /* IF (sub(n,8) == 0) */ + IF (n == 8) + { + b2 = L_add(t0, *f++); /* b0 = 2*x*b1 - b2 + f[i] */ + /* i = 7 */ + t0 = Mpy_32_16_1(b2, x); /* t0 = x*b1 */ + if (!cheb) + t0 = L_shl(t0, 1); /* t0 = 2*x*b1 */ + t0 = L_sub(t0, b1); /* t0 = 2*x*b1 - b2 */ + /*b1 = L_add(b2,0);*/ + } + ELSE + { + b2 = b1; + move32(); + } + + t0/*b2*/ = L_add(t0, *f++); /* b0 = 2*x*b1 - b2 + f[i] */ + + t0 = Mpy_32_16_1(t0/*b2*/, x);/* t0 = x*b1 */ + if (cheb) + t0 = L_shr(t0,1); + t0 = L_sub(t0, /*b1*/b2); /* t0 = x*b1 - b2 */ + t0 = L_add(t0, *f++); /* t0 = x*b1 - b2 + 0.5*f[n] */ + + + BASOP_SATURATE_WARNING_OFF + t0 = L_shl(t0, shift); /* Qx to Q30 with saturation */ + cheb = round_fx(t0); /* Result in Q14 */ + cheb = s_max(-32767,cheb); /* to avoid saturation */ + BASOP_SATURATE_WARNING_ON + return (cheb); +} + +void E_LPC_a_isp_conversion(const Word16 a[], Word16 isp[], const Word16 old_isp[], const Word16 m) +{ + Word16 i, nf, ip, order, nc; + Word16 xlow, ylow, xhigh, yhigh; + Word16 x, y, tmp, exp; + Word32 f[2][NC_MAX+1]; + Word32 t0, t1; + Word16 scale=1024; + + + /*-------------------------------------------------------------* + * find the sum and diff polynomials F1(z) and F2(z) + * F1(z) = [A(z) + z^M A(z^-1)] + * F2(z) = [A(z) - z^M A(z^-1)]/(1-z^-2) + * + * for (i=0; i 1; i--) + { + /* f2[i] -= f2[i-2]; */ + f2[i] = L_sub(f2[i], f2[i - 2]); + move32(); + } + + /*----------------------------------------------------------* + * Scale F1(z) by (1+isp[m-1]) and F2(z) by (1-isp[m-1]) * + *----------------------------------------------------------*/ + + FOR (i = 0; i < nc; i++) + { + /* f1[i] *= (1.0 + isp[m-1]); */ + f1[i] = Madd_32_16(f1[i], f1[i], isp[m - 1]); + move32(); + + /* f2[i] *= (1.0 - isp[m-1]); */ + f2[i] = Msub_32_16(f2[i], f2[i], isp[m - 1]); + move32(); + } + + /*-----------------------------------------------------* + * A(z) = (F1(z)+F2(z))/2 * + * F1(z) is symmetric and F2(z) is antisymmetric * + *-----------------------------------------------------*/ + + /* Maximum LPC */ + tmax = L_deposit_l(1); + FOR (i = 1; i < nc; i++) + { + t0 = L_add(f1[i], f2[i]); + tmax = L_max( tmax, L_abs(t0) ); + t0 = L_sub(f1[i], f2[i]); + tmax = L_max( tmax, L_abs(t0) ); + } + q = s_min( norm_l(tmax), 6 ); + + DO + { + + /* a[0] = 1.0 */ + a[0] = shl(256,q); + move16(); + j = sub(m, 1); + FOR (i = 1; i < nc; i++) + { + /* a[i] = 0.5*(f1[i] + f2[i]) */ + t0 = L_add(f1[i], f2[i]); /* f1[i] + f2[i] */ + t0 = L_shl(t0, q); + a[i] = round_fx(t0); /* from Q23 to Q12 and * 0.5 */ + + /* a[j] = 0.5*(f1[i] - f2[i]) */ + t0 = L_sub(f1[i], f2[i]); /* f1[i] - f2[i] */ + t0 = L_shl(t0, q); + a[j] = round_fx(t0); /* from Q23 to Q12 and * 0.5 */ + + j = sub(j,1); + } + + /* a[NC] = 0.5*f1[NC]*(1.0 + isp[m-1]) */ + t0 = Madd_32_16(f1[nc], f1[nc], isp[m - 1]); + + BASOP_SATURATE_WARNING_OFF /*overflow handling in loop expression*/ + t0 = L_shl(t0, q); + t0n = L_sub(t0 , 0x7FFFFFFF); /*check for positive overflow*/ + t0p = L_sub(t0, 0x80000000); /*check for negative overflow*/ + BASOP_SATURATE_WARNING_ON + + q = sub(q,1); /*decrease q in case of overflow*/ + } WHILE(t0n == 0 || t0p == 0); /*in case of overflow, recalculate coefficients*/ + + a[nc] = round_fx(t0); /* from Q23 to Q12 and * 0.5 */ + + /* a[m] = isp[m-1] */ + t0 = L_mult(a[0], isp[m - 1]); /* from Q15 to Q12 */ + a[m] = round_fx(t0); + + + return; +} + +/*===================================================================*/ +/* FUNCTION : lpc2lsp_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Convert LPC coefficients to LSP coefficients */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* */ +/* _ (Word32 []) a : LPC coefficients, Q27 */ +/* _ (Word16 []) old_freq: Previous frame LSP coefficients, Q15 */ +/* _ (Word16 []) order: LPC order */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 []) freq: LSP coefficients, Q15 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word16) flag: 1 means all 10 LSPs are found, 0 otherwise */ +/*===================================================================*/ +Word16 lpc2lsp_fx( + Word32* a, + Word16* freq, + Word16* old_freq, + Word16 order +) +{ + Word16 i; + Word16 rt, low, high, prev_rt, rc; + Word32 p[11], q[11]; /* Q26 */ + Word32 Ltemp, v_low; + Word32 Lacc; + Word16 tfreq[21]; + + /* First construct the P,Q polynomial */ + /* p[0] = q[0] = 1 */ + /* p[i] = -lpcCoeff[i] - lpcCoeff[11-i] - p[i-1] ( 1<=i<=5)*/ + /* q[i] = -lpcCoeff[i] + lpcCoeff[11-i] + q[i-1] ( 1<=i<=5)*/ + Ltemp = L_deposit_h( 0x400 ); /* Ltemp is 1.0 in Q26 */ + + p[0] = Ltemp; + move32(); + q[0] = Ltemp; + move32(); + + FOR ( i = 1; i < ( order / 2 ) + 1; i++ ) + { + Lacc = a[order - i]; + move32();/* Q27 */ + Lacc = L_sub( Lacc, a[i - 1] ); /* Lacc=-lpcCoeff[i-1] + lpcCoeff[order-i]//Q27 */ + q[i] = L_add( L_shr( Lacc, 1 ), q[i - 1] ); + move32();/* Q26 */ + + Lacc = L_add( Lacc, L_shl( a[i - 1], 1 ) );/* Lacc=lpcCoeff[i-1] + lpcCoeff[order-i]//Q27 */ + + p[i] = L_sub( L_negate( L_shr( Lacc, 1 ) ), p[i - 1] ); + move32();/* Q26 */ + } + + /* Search roots of the P and Q polynomials */ + + v_low = polynomial_eval_fx( 0, p, order ); /* Q25 */ + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + low = 0; + high = 8; + prev_rt = 0; + rc = 0; /* root counter */ + FOR ( i = 0; i < 32; i++ ) + { + rt = root_search_fx( low, high, &v_low, p, order ); + low = high; + move16(); + high = add( high, 8 ); + + IF( GE_16( rt, prev_rt )) + { + tfreq[rc] = rt; + move16(); + rc = add( rc, 2 ); + } + prev_rt = add( rt, 6 ); + } /* End for P roots */ + + tfreq[rc] = 0x3f80; + move16(); /* Set a high enough value as fake root for Q search */ + + IF ( LT_16( rc, order )) + { + /* lost P root */ + /* copy from previous LSP and return */ + FOR ( i = 0; i < order; i++ ) + { + move16(); + freq[i] = old_freq[i]; + } + return ( 0 ); + } + ELSE + { + /* Search for Q roots between P roots */ + v_low = L_deposit_h( 0x800 ); /* Init a positive value for v_low */ + rc = 1; + move16(); + FOR ( i = 0; i < order / 2; i++ ) + { + low = shr( tfreq[rc - 1], 6 ); + high = add( shr( tfreq[rc + 1], 6 ), 1 ); + rt = root_search_fx( low, high, &v_low, q, order ); + + IF ( rt < 0 ) + { + /* No Q root in this interval */ + /* copy from previous LSP and return */ + FOR ( i = 0; i < order; i++ ) + { + move16(); + freq[i] = old_freq[i]; + } + return ( 0 ); + } + ELSE + { + move16(); + tfreq[rc] = rt; + rc = add( rc, 2 ); + } /* end else, find Q root */ + } /* end for */ + } /* end else */ + + FOR ( i = 0; i < order; i++ ) + { + freq[i] = tfreq[i]; + move16(); + } + + return ( 1 ); +} + +/*===================================================================*/ +/* FUNCTION : lsp2lpc_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Convert LSP coefficients to LPC coefficients */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) freq: LSP coefficients, Q15 */ +/* _ (Word16 []) prev_a : previous frame LPC coefficients, Q12 */ +/* _ (Word16 []) order : LPC order */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 []) a : LPC coefficients, Q12 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*===================================================================*/ +void lsp2lpc_fx( + Word16 *a, + Word16 *freq, + Word16 *prev_a, + Word16 order +) +{ + Word16 i; + Word32 pq[ LPC_SHB_ORDER ] ; + Word32 p[ LPC_SHB_ORDER ], q[ LPC_SHB_ORDER ]; + Word32 Ltemp; + Word32 Lacc; + Word16 tmp_pci[M+1]; + Word16 giOverflow; + + + FOR ( i = 0; i < order; i++ ) + { + tmp_pci[i]=prev_a[i]; + move16(); + } + + compute_poly_product_fx( freq, pq, order ); + /*This change is to get funtionality if L_sub_sat*/ + giOverflow = 0 ; + move16(); /* clear overflow flag */ + Overflow = 0; + move16(); + FOR ( i=0; i < order/2; i++ ) + { + Ltemp = L_add( pq[ i ], pq[ i + 1 ] ); + giOverflow = ( Word16 )Overflow; + move16(); + IF ( EQ_16(giOverflow,1)) + { + BREAK; + } + + p[ i ] = Ltemp ; + move32(); + } + + IF ( EQ_16(giOverflow,1)) + { + FOR (i=0; i < order; i++ ) + { + a[i] = mult_r( prev_a[i], pwAlpha[i] ); + move16(); + } + return; + } + + compute_poly_product_fx( freq+1, pq, order ); + + + giOverflow = 0; + move16(); + Overflow = 0; + move16(); + + FOR ( i=0; i < order/2; i++ ) + { + Ltemp = L_sub( pq[ i+1 ], pq[i] ); + giOverflow = ( Word16 ) Overflow; + move16(); + IF ( EQ_16(giOverflow,1)) + { + BREAK; + } + + q[i] = Ltemp; + move32(); + } + + IF ( EQ_16(giOverflow,1)) + { + FOR (i = 0; i < order; i++ ) + { + a[i] = mult_r( prev_a[i], pwAlpha[i] ); + move16(); + } + } + ELSE + { + FOR (i = 0; i < order/2; i++ ) + { + Overflow = 0; + move16(); + Lacc = L_add( p[i], q[i] ); /* p[i], q[i] in Q24 */ + if ( Overflow ) + { + giOverflow = 1; + move16(); + } + + Lacc = L_negate( Lacc ); /* Lacc=-(p[i]-q[i])/2 in Q25 */ + Overflow = 0; + move16(); + Lacc = L_add( L_shl( Lacc, 3 ), 0x08000 ); /* rounding */ + if ( Overflow ) + { + giOverflow = 1; + move16(); + } + + a[i] = extract_h( Lacc ); /* a[i] in Q12 */ + + IF ( EQ_16(giOverflow,1)) + { + BREAK; + } + + } + FOR ( i=0; i < order/2; i++ ) + { + Overflow = 0; + move16(); + Lacc = L_sub( q[i], p[i] ); /* p[i], q[i] in Q24 */ + if( Overflow ) + { + giOverflow = 1; + move16(); + } + Overflow = 0; + move16(); + Lacc = L_add( L_shl( Lacc, 3 ), 0x08000); /* rounding */ + if ( Overflow ) + { + giOverflow = 1; + move16(); + } + + a[ order-1-i ] = extract_h( Lacc ); + + + IF ( EQ_16(giOverflow,1)) + { + BREAK; + } + + } + } + + + IF ( EQ_16(giOverflow,1)) + { + FOR ( i = 0; i < order; i++ ) + { + a[i] = mult_r( tmp_pci[i], pwAlpha[i] ); + move16(); + } + } + +} + +/* + * E_LPC_f_lsp_pol_get + * + * Parameters: + * lsp/isp I: Line spectral pairs (cosine domaine) Q15 + * f O: the coefficients of F1 or F2 Q23 + * n I: no of coefficients (m/2) + * == NC for F1(z); == NC-1 for F2(z) + * fact I: scaling factor + * + *-----------------------------------------------------------* + * procedure E_LPC_f_lsp_pol_get: * + * ~~~~~~~~~~~ * + * Find the polynomial F1(z) or F2(z) from the LSPs. * + * This is performed by expanding the product polynomials: * + * * + * F1(z) = product ( 1 - 2 LSF_i z^-1 + z^-2 ) * + * i=0,2,4,6,8 * + * F2(z) = product ( 1 - 2 LSF_i z^-1 + z^-2 ) * + * i=1,3,5,7,9 * + * * + * where LSP_i are the LSPs in the cosine domain. * + * * + *-----------------------------------------------------------* + * R.A.Salami October 1990 * + *-----------------------------------------------------------* + */ +Word16 E_LPC_f_lsp_pol_get(const Word16 lsp[], Word32 f[], const Word16 n, const Word16 past_Ovf, const Word16 isMODE1) +{ + /* All computation in Q23 */ + const Word16 *plsp; + Word16 i, j; + Word16 b; + Word32 b32; + Word16 Ovf = 0; + Word16 Q_out; + Word16 m2; + + + Q_out = 31-23; + move16(); + Ovf = past_Ovf; + move16(); + + test(); + if(past_Ovf && isMODE1) /* Currently this feature is implemented only in MODE1 */ + { + /* In some NB cases, overflow where detectected + in f1 or f2 polynomial computation when it + happen we reduce the precision of the computing + to limit the risk of saturation*/ + Q_out = add(Q_out, past_Ovf); + } + Overflow = 0; + move16(); + plsp = lsp; + f[0] = L_shl(1, sub(31, Q_out)); + move32(); + /*b = -2.0f * *plsp;*/ + b = *plsp; + move16(); + m2 = shl(-2, sub(15, Q_out)); + f[1] = L_mult(b, m2); + move32(); + + FOR (i = 2; i <= n; i++) + { + plsp += 2; + /*b = 2.0f * *plsp;*/ + move16(); + b = *plsp; + b32 = L_mult(b, m2); + + /*f[i] = -b*f[i-1] + 2.0f*f[i-2];*/ + move32(); + f[i] = L_shl(L_sub(f[i-2], Mpy_32_16_1(f[i-1], b)),1); + + FOR (j = i-1; j > 1; j--) + { + /*f[j] += b*f[j-1] + f[j-2];*/ + move32(); + f[j] = L_add(f[j], L_sub(f[j-2], L_shl(Mpy_32_16_1(f[j-1], b),1))); + } + move32(); + f[1] = L_add(f[1], b32); + } + + + test(); + IF (Overflow>0 && isMODE1) + { + /* If an overflow is detected, redo the computation with 1 bit less */ + Ovf = add(Ovf,1); + Ovf = E_LPC_f_lsp_pol_get(lsp, f, n ,Ovf, isMODE1); + } + return Ovf; +} + +void E_LPC_a_lsp_conversion( + const Word16 *a, /* input : LP filter coefficients (Qx) */ + Word16 *lsp, /* output: Line spectral pairs (in the cosine domain)(0Q15) */ + const Word16 *old_lsp, /* input : LSP vector from past frame (0Q15) */ + const Word16 m /* input : length of the LP filter coefficients */ +) +{ + Word16 i, nf, ip, nc; + Word16 xlow, ylow, xhigh, yhigh; + Word16 x, y, tmp, exp; + Word32 f[2][NC_MAX+1]; + Word32 t0, t1; + Word32 sum, diff; + Word16 scale; + + + + nc = shr(m, 1); + + scale = shl( 128, norm_s(a[0]) ); + + /*-------------------------------------------------------------* + * find the sum and diff polynomials F1(z) and F2(z) * + * F1(z) = [A(z) + z^11 A(z^-1)]/(1+z^-1) * + * F2(z) = [A(z) - z^11 A(z^-1)]/(1-z^-1) * + *-------------------------------------------------------------*/ + + f[0][0] = L_mult(a[0],scale); /*1.0f in Q23*/ move32(); + f[1][0] = L_mult(a[0],scale); /*1.0f in Q23*/ move32(); + FOR (i = 1; i < nc; i++) + { + t0 = L_mult(a[i],scale); /*Q23*/ + sum = L_mac(t0, a[m+1-i],scale); + diff = L_msu(t0, a[m+1-i],scale); + f[0][i] = L_sub(sum,f[0][i-1]); + move32(); /*Q23*/ + f[1][i] = L_add(diff,f[1][i-1]); + move32(); /*Q23*/ + } + t1 = L_mult0(a[i],scale); /*Q23-1*/ + sum = L_mac0(t1, a[m+1-i],scale); + diff = L_msu0(t1, a[m+1-i],scale); + f[0][nc] = L_sub(sum, L_shr(f[0][i-1],1)); + move32(); /*Q23-1*/ + f[1][nc] = L_add(diff,L_shr(f[1][i-1],1)); + move32(); /*Q23-1*/ + + /* Precalculate difference to index 0 for index 2 */ + f[0][2] = L_sub(f[0][2], f[0][0]); + move32(); + f[1][2] = L_sub(f[1][2], f[1][0]); + move32(); + + /*---------------------------------------------------------------------* + * Find the LSPs (roots of F1(z) and F2(z) ) using the * + * Chebyshev polynomial evaluation. * + * The roots of F1(z) and F2(z) are alternatively searched. * + * We start by finding the first root of F1(z) then we switch * + * to F2(z) then back to F1(z) and so on until all roots are found. * + * * + * - Evaluate Chebyshev pol. at grid points and check for sign change.* + * - If sign change track the root by subdividing the interval * + * 4 times and ckecking sign change. * + *---------------------------------------------------------------------*/ + nf = 0; + move16(); /* number of found frequencies */ + ip = 0; + move16(); /* indicator for f1 or f2 */ + + xlow = Grid[0]; + move16(); + ylow = chebyshev(xlow, f[ip], nc, 8); + + FOR (i = 1; i <= GRID100_POINTS; i++) + { + xhigh = xlow; + move16(); + yhigh = ylow; + move16(); + xlow = Grid[i]; + move16(); + ylow = chebyshev(xlow, f[ip], nc, 8); + + IF (L_mult(ylow, yhigh) <= 0) + { + t0 = L_mult(xhigh, 0x4000); + /* divide 2 times the interval */ + x = mac_r(t0, xlow, 0x4000); /* xmid = (xlow + xhigh)/2 */ + y = chebyshev(x, f[ip], nc, 8); + + IF (L_mult(ylow, y) <= 0) + { + yhigh = y; + move16(); + xhigh = x; + move16(); + y = ylow; + move16(); + x = xlow; + move16(); + /* 'xhigh' has changed, update 't0' */ + t0 = L_mult(xhigh, 0x4000); + } + xlow = mac_r(t0, x, 0x4000); /* xmid = (xlow + xhigh)/2 */ + ylow = chebyshev(xlow, f[ip], nc, 8); + + IF (L_mult(y, ylow) <= 0) + { + yhigh = ylow; + move16(); + xhigh = xlow; + move16(); + ylow = y; + move16(); + xlow = x; + move16(); + } + + /*--------------------------------------------------------* + * Linear interpolation + * xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow) + *--------------------------------------------------------*/ + y = msu_r(L_mult(yhigh,0x4000), ylow,0x4000); + + IF (y != 0) + { + x = sub(xhigh, xlow); + BASOP_SATURATE_WARNING_OFF + tmp = abs_s(y); + BASOP_SATURATE_WARNING_ON + exp = norm_s(tmp); + if (exp) + tmp = shl(tmp, exp); + tmp = div_s((Word16) 16383/2, tmp); + t0 = L_mult(x, tmp); + t0 = L_shr(t0, sub(20, exp)); + tmp = extract_l(t0); /* y = (xhigh-xlow)/(yhigh-ylow) in Q11 */ + + /* Restore Sign */ + if (y < 0) + tmp = negate(tmp); + + t0 = L_mult(ylow, tmp); /* result in Q26 */ + t0 = L_shr(t0, 11); /* result in Q15 */ + xlow = sub(xlow, extract_l(t0));/* xint = xlow - ylow*y */ + } + lsp[nf++] = xlow; + move16(); + + IF (GE_16(nf,m)) + { + BREAK; + } + + ip = s_xor(ip, 1); + ylow = chebyshev(xlow, f[ip], nc, 8); + } + } + + /* Check if m roots found */ + /* if not use the LSPs from previous frame */ + + IF (LT_16(nf,m)) + { + FOR(i=0; i= 0; i--) /* Reverify the minimum LSF gap in the reverse direction */ + { + if (GT_16(lsf[i], lsf_max)) + { + lsf[i] = lsf_max; + move16(); + } + lsf_max = sub(lsf[i], min_dist); + } + } +} + +void space_lsfs_fx ( + Word16* lsfs, /* i/o: Line spectral frequencies */ + const Word16 order /* i : order of LP analysis */ +) +{ + Word16 delta; /* Q1.15 */ + Word16 i, flag=1; + + WHILE ( flag == 1 ) + { + flag = 0; + move16(); + FOR ( i = 0; i <= order; i++ ) + { + IF( i == 0 ) + { + delta = lsfs[0]; + move16(); + } + ELSE + { + IF( EQ_16(i,order)) + { + delta = sub( HALF_POINT_FX, lsfs[i-1] ); + move16(); + } + ELSE + { + delta = sub( lsfs[i], lsfs[i-1] ); + move16(); + } + } + IF ( LT_16( delta, SPC_FX )) + { + flag = 1; + move16(); + delta = sub( delta, SPC_PLUS_FX ); + + IF ( i == order ) + { + lsfs[i - 1] = add( lsfs[i - 1], delta ); + move16(); + } + ELSE + { + IF ( i == 0 ) + { + lsfs[i] = sub( lsfs[i], delta ); + move16(); + } + ELSE + { + delta = mult_r( delta, HALF_POINT_FX ); + lsfs[i - 1] = add( lsfs[i - 1], delta ); + move16(); + lsfs[i] = sub( lsfs[i], delta ); + move16(); + } + } + } + } + } + + return; +} + +/*=================================================================== */ +/* FUNCTION : lsp_weights_fx () */ +/*------------------------------------------------------------------- */ +/* PURPOSE : This function computes the weights for the */ +/* given unquantized lsp vector */ +/*------------------------------------------------------------------- */ +/* INPUT ARGUMENTS : +_ (Word16 []) lsp_nq_fx: input unquantized lsp vector */ +/* _(Word16 Order) FilterOrder */ +/*------------------------------------------------------------------- */ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 []) w: weight vector Q(9-n_max) */ + +/*------------------------------------------------------------------- */ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None. */ +/*------------------------------------------------------------------- */ +/* RETURN ARGUMENTS : */ +/* _ None. */ +/*=================================================================== */ + +void lsp_weights_fx( + Word16 lsp_nq_fx[], + Word16 w[], + Word16 Order, + Word16* Qout +) +{ + Word16 lpcOrder =Order; + + Word16 i, n1, tmp_loop; + Word16 norm[20]; + Word32 Lsum1[20]; + Word16 delta1, delta2, temp; + Word16 n_max =-32768; + move16(); + + temp = 0; + move16(); + + tmp_loop = sub( lpcOrder, 1 ); + FOR ( i = 0; i < tmp_loop; i++ ) + { + delta1 = sub( lsp_nq_fx[i], temp ); + delta2 = sub( lsp_nq_fx[i + 1], lsp_nq_fx[i] ); + Lsum1[i] = calc_weight( delta1, delta2, &n1 ); + move32();/* Q( 26-n1) */ + norm[i] = n1; + move16(); + + if (GT_16(norm[i],n_max)) + { + n_max = norm[i]; + move16(); + } + temp = lsp_nq_fx[i]; + move16(); + } + delta1 = sub( lsp_nq_fx[i], temp ); + delta2 = sub( 16384, lsp_nq_fx[i] ); + + Lsum1[i] = calc_weight( delta1, delta2, &n1 ); + move32(); /* Q( 26-n1) */ + norm[i] = n1; + move16(); + + if ( GT_16(norm[i], n_max)) + { + n_max = norm[i]; + move16(); + } + FOR ( i = 0; i < lpcOrder; i++ ) + { + w[i] = round_fx( L_shl( Lsum1[i], sub( norm[i], n_max + 1 ) ) ); /* Q( 9-n_max) */ + } + + IF ( lpcOrder != LPC_SHB_ORDER_WB ) + { + w[3] = round_fx( L_shl( L_mult( w[3], 18022 ), 1 ) ); /* Q( 9-n_max) */ + w[4] = round_fx( L_shl( L_mult( w[4], 18022 ), 1 ) ); /* Q( 9-n_max) */ + } + + *Qout = 9 - n_max; + move16(); +} + +/* + * E_LPC_isf_isp_conversion + * + * Parameters: + * isf I: isf[m] normalized (range: 0 <= val <= 0.5) 14Q1*1.28 + * isp O: isp[m] (range: -1 <= val < 1) Q15 + * m I: LPC order + * + * Function: + * Transformation isf to isp + * + * ISF are immitance spectral pair in frequency domain (0 to 6400). + * ISP are immitance spectral pair in cosine domain (-1 to 1). + * + * Returns: + * void + */ +void E_LPC_isf_isp_conversion(const Word16 isf[], Word16 isp[], const Word16 m) +{ + Word16 i; + + assert( m==16 || m==10 ); + + + FOR (i = 1; i < m; i++) + { + *isp++ = xsf_to_xsp(*isf++); + move16(); + } + *isp = xsf_to_xsp(shl(*isf, 1)); + move16(); + + + return; +} + +/* + * E_LPC_isp_isf_conversion + * + * Parameters: + * isp I: isp[m] (range: -1 <= val < 1) Q15 + * isf O: isf[m] normalized (range: 0 <= val <= 6400) x1.28 + * m I: LPC order + * + * Function: + * Transformation isp to isf + * + * ISP are immitance spectral pair in cosine domain (-1 to 1). + * ISF are immitance spectral pair in frequency domain (0 to 6400). + * + * Returns: + * energy of prediction error + */ +void E_LPC_isp_isf_conversion(const Word16 isp[], Word16 isf[], const Word16 m) +{ + Word16 i; + + assert( m==16 || m==10 ); + + + + FOR (i = 0; i < m; i++) + { + isf[i] = xsp_to_xsf(isp[i]); + move16(); + } + + isf[m - 1] = shr(isf[m - 1], 1); + move16(); + + + return; +} + + +Word16 xsf_to_xsp(Word16 lsf) +{ + /* lsp = cos(lsf * 3.1415/6400); */ + return getCosWord16R2(lsf); +} + +Word16 xsp_to_xsf(Word16 lsp) +{ + Word16 ind, tmp; + Word32 L_tmp; + + + /*------------------------------------------------------* + * find value in table that is just greater than lsp + *------------------------------------------------------*/ + + /* Retrieve Index Guess */ + /* Based on lsp */ + ind = mac_r(GUESS_TBL_SZ/2*65536-0x8000, lsp, GUESS_TBL_SZ/2); + ind = Ind_Guess[ind]; + move16(); + + /* Correct Index so that */ + /* cos_table_129[ind] > isp[i] */ + tmp = sub(lsp, cos_table_129[ind]); + /* + 69%: (Final Index - Index Guess) is <= 1 + 28%: (Final Index - Index Guess) is 2 + 2%: (Final Index - Index Guess) is >= 3 + <1%: ... + */ + IF (tmp > 0) /* possible range 0 to -5 (-1-2-2) */ + { + ind = sub(ind, 1); + tmp = sub(lsp, cos_table_129[ind]); + + IF (tmp > 0) + { + ind = sub(ind, 2); + tmp = sub(lsp, cos_table_129[ind]); + if (tmp > 0) + { + ind = sub(ind, 2); + } + tmp = sub(lsp, cos_table_129[ind+1]); + if (tmp <= 0) + { + ind = add(ind, 1); + } + tmp = sub(lsp, cos_table_129[ind]); + } + } + + /* acos(lsp)= ind*128 + (lsp-cos_table_129[ind]) * acos_slope[ind] / 2048 */ + L_tmp = L_mac(1L<<11, tmp, acos_slope[ind]); + L_tmp = L_shr(L_tmp, 12); /* (lsp-cos_table_129[ind]) * acos_slope[ind]) >> 11 */ + L_tmp = L_mac0(L_tmp, ind, 128); + + + return extract_l(L_tmp); +} + +/*-------------------------------------------------------------------* + * a2rc() + * + * Convert from LPC to reflection coeff + *-------------------------------------------------------------------*/ + +void a2rc_fx( const Word16* a, /* i: can be any Q */ + Word16* refl, /* o: Q15 */ + Word16 lpcorder + ) + +{ + Word16 f_fx[M]; + Word16 km_fx; + Word32 L_tmp1, L_tmp2; + Word16 tmp; + Word16 denom_mant, exp; + Word32 new_mant; + Word16 temp; + Word16 m, j, n; + Word16 q, q_a, q_a2, One_Qx; + Word32 One_Qx2; + q = add( norm_s(a[-1]), 1 ); + q_a = sub(15, q); + q_a2 = add(shl(q_a,1),1); + /* copy into internal vars so they can be changed */ + + FOR ( m = 0; m < lpcorder; m++ ) + { + /* f_fx[m] = p_fx[m]; */ + f_fx[m] = negate(a[m]); + move16(); + } + One_Qx = shl(1,q_a); + One_Qx2 = L_shl(1, q_a2); + FOR ( m = lpcorder - 1; m >= 0; m-- ) + { + km_fx = f_fx[m]; + move16(); + + test(); + IF ( LE_16( km_fx, negate(One_Qx))||GE_16(km_fx,One_Qx)) + { + FOR ( j = 0; j < lpcorder; j++ ) + { + refl[j] = 0; + move16(); + } + + return; + } + + refl[m] = negate( km_fx ); + move16(); + L_tmp1 = One_Qx2; /* 1 in 2xq_a+1 */ + move32(); + L_tmp1 = L_msu( L_tmp1, km_fx, km_fx ); /* 1-km*km in Q25 */ + + /* new_mant = invert_dp(L_tmp1,4, &tmp_denom_exp,1); sum in Q61-Q25-n=Q36-n */ + exp = norm_l( L_tmp1 ); + tmp = extract_h( L_shl( L_tmp1, exp ) ); + exp = sub( sub( 30, exp ), q_a2 ); + IF ( tmp ) + { + tmp = div_s( 16384, tmp ); /* 15+exp */ + } + ELSE + { + tmp = 0; + } + new_mant = L_deposit_h( tmp ); + temp = round_fx( L_shl( new_mant, 0 ) ); /* in Q14 */ + denom_mant = temp; + move16(); + L_tmp1 = L_mult( km_fx, denom_mant ); /* km*denom. Q12*Q14 = Q27 */ + L_tmp1 = L_shl( L_tmp1, q ); /* change to Q31. simulation showed no overflow */ + tmp = round_fx( L_tmp1 ); /* extract in Q15 */ + + FOR ( j = 0; j < m / 2; j++ ) + { + n = sub( sub( m, ( Word16 )1 ), j ); + L_tmp1 = L_mult( denom_mant, f_fx[j] ); /* denom*f[j]. Q15*Q12 = Q28 (floating with exp) */ + L_tmp1 = L_mac( L_tmp1, tmp, f_fx[n] ); /* denom*f[j]+km*denom*f[n] in Q28 (floating with exp) */ + L_tmp2 = L_mult( denom_mant,f_fx[n] ); /* denom*f[n]. Q15*Q12 = Q28 (floating with exp) */ + L_tmp2 = L_mac( L_tmp2, tmp,f_fx[j] ); /* denom*f[n]+km*denom*f[j] in Q28 (floating with exp) */ + L_tmp1 = L_shr( L_tmp1, exp ); /* bringing to true Q28 */ + L_tmp2 = L_shr( L_tmp2, exp ); /* bringing to true Q28 */ + f_fx[j] = round_fx( L_tmp1 ); /* extracting in q_a */ + f_fx[n] = round_fx( L_tmp2 ); /* extracting in q_a */ + } + + IF ( m & 1 ) + { + L_tmp1 = L_mult( denom_mant, f_fx[ j] ); /* denom*f[j]. Q15*Q12 = Q28 (floating with exp) */ + L_tmp1 = L_mac( L_tmp1, tmp,f_fx[j] ); /* denom*f[j]+km*denom*f[j] in Q28 (floating with exp) */ + L_tmp1 = L_shr( L_tmp1, exp ); /* bringing to true Q28 */ + f_fx[j] = round_fx( L_tmp1 ); /* extracting in q_a */ + } + } + + FOR ( j = 0; j < lpcorder; j++ ) + { + refl[j] = shl( refl[j], q ); + move16(); + } + + + return; +} +Word16 vq_dec_lvq_fx ( + Word16 sf_flag, /* i : safety net flag */ + Word16 x[], /* o : Decoded vector Q(x2.56)*/ + Word16 indices[], /* i : Indices */ + Word16 stages, /* i : Number of stages */ + Word16 N, /* i : Vector dimension */ + Word16 mode, /* (i): mode_lvq, or mode_lvq_p */ + Word16 no_bits, /* (i): no. bits for lattice */ + Word32 *p_offset_scale1, + Word32 *p_offset_scale2, + Word32 *p_offset_scale1_p, + Word32 *p_offset_scale2_p, + Word16 *p_no_scales, + Word16 *p_no_scales_p +) +{ + Word16 x_lvq[M]; + Word16 i, stagesm1; + Word16 pt_fx; + Word16 ber_flag; + + /* clear vector */ + set16_fx(x, 0, N); + + /*-----------------------------------------------* + * add contribution of each stage + *-----------------------------------------------*/ + stagesm1 = sub(stages,1); + IF (EQ_16(sf_flag,1)) + { + FOR(i=0; i0) + { + n_stages = 2; + move16(); + levels0[0] = CBsizes_fx[nbits0]; + move16(); + bits0[0] = nbits0; + move16(); + bits0[1] = sub(cumleft,nbits0); + + IF ( bits0[1] == 0 ) + { + n_stages = sub(n_stages,1); + } + ELSE + { + levels0[1] = CBsizes_fx[sub(cumleft,nbits0)]; + move16(); + } + } + ELSE /* no bits for VQ stage */ + { + n_stages = 0; + move16(); + } + + *stages0 = n_stages; + move16(); + IF (bits_lvq > 0) + { + bits0[n_stages] = bits_lvq; + move16(); + levels0[n_stages] = bits_lvq; + move16();/* this is number of bits, not levels */ + *stages0 = add(n_stages,1); + move16(); + } + } + ELSE + { + *stages0 = 0; + move16(); + } + + /*---------------------------------------------------* + * Calculate bit allocation for predictive quantizer + *---------------------------------------------------*/ + IF ( GT_16(framemode_p, -1)) + { + cumleft = BitsVQ_p_fx[framemode_p]; + move16(); + bits_lvq = sub(nBits, cumleft); + nbits0 = CBbits_p_fx[framemode_p]; + move16(); + + IF (GT_16(nbits0,-1)) + { + IF ( nbits0 > 0 ) + { + IF ( EQ_16(framemode_p, 7)) + { + /* for UNVOICED_WB only */ + n_stages = 3; + move16(); + FOR( i=0; i0) + { + levels1[1] = CBsizes_fx[nbits0]; + move16(); + bits1[1] = nbits0; + move16(); + n_stages = 2; + move16(); + } + + levels1[n_stages] = bits_lvq; + move16();/* this is number of bits, not levels */ + bits1[n_stages] = bits_lvq; + move16(); + *stages1 = add(n_stages ,1); + } + } + ELSE + { + *stages1 = 1; + move16(); + bits1[0] = bits_lvq; + move16(); + levels1[0] = bits_lvq; + move16(); + } + } + ELSE + { + } + } + + return; +} + +Word16 find_pred_mode( + const Word16 coder_type, /* i: coding type */ + const Word16 bwidth, /* i: bandwidth index */ + const Word32 int_fs, /* i: sampling frequency */ + Word16 * p_mode_lvq, /* o: index of LSF codebooks in safety net mode */ + Word16 * p_mode_lvq_p, /* o: index of LSF codebooks in predictive mode (AR or MA) */ + Word32 core_brate) /* i: core bit rate */ +{ + Word16 idx, predmode; + + /* bwidth = 0(NB), 1 (WB), 2(WB2); line index in predmode_tab[][] */ + idx = bwidth; + move16(); + if (GT_16(idx, 1)) + { + idx = 1; + } + IF (EQ_32(int_fs, INT_FS_16k)) + { + /* WB2 is actually used if sampling frequency is 16kHz */ + idx = 2; + move16(); + } + ELSE + { + test(); + test(); + if ((GE_32(core_brate, GENERIC_MA_LIMIT))&&(EQ_16(coder_type,GENERIC))&&(EQ_16(idx,1))) + { + idx = 3; + move16(); + } + } + predmode = predmode_tab[idx][coder_type]; + move16(); + IF (LE_16(idx, 2)) + { + *p_mode_lvq = add(i_mult2(NO_CODING_MODES, idx), coder_type); + IF (predmode>0) + { + *p_mode_lvq_p = *p_mode_lvq; + move16(); + } + ELSE + { + *p_mode_lvq_p = -1; + move16(); + } + } + ELSE /* WB 12.8 with MA pred in GENERIC*/ + { + *p_mode_lvq = add(NO_CODING_MODES, coder_type); + IF (EQ_16(coder_type, GENERIC)) + { + *p_mode_lvq_p = 18; + move16(); + } + ELSE + { + IF (predmode>0) + { + *p_mode_lvq_p = *p_mode_lvq; + } + ELSE + { + *p_mode_lvq_p = -1; + } + } + } + + + + return predmode; +} + +/*---------------------------------------------------------------------------* + * reorder_isf + * + * To make sure that the isfs are properly ordered and to keep a certain + * minimum distance between consecutive isfs. + *--------------------------------------------------------------------------*/ +void reorder_isf_fx( + Word16 *isf, /* i/o: ISFs in the frequency domain (0..0.5) */ + const Word16 min_dist, /* i : minimum required distance */ + const Word16 n, /* i : LPC order */ + const Word16 fs /* i : sampling frequency */ +) +{ + Word16 i, isf_min; + Word16 isf_max; + + isf_min = min_dist; + move16(); + + /*-----------------------------------------------------------------------* + * Verify the ISF ordering and minimum GAP + *-----------------------------------------------------------------------*/ + + FOR (i = 0; i < n - 1; i++) + { + if (LT_16(isf[i], isf_min)) + { + isf[i] = isf_min; + move16(); + } + isf_min = add(isf[i], min_dist); + } + + /*-----------------------------------------------------------------------* + * Reverify the ISF ordering and minimum GAP in the reverse order (security) + *-----------------------------------------------------------------------*/ + + /*isf_max = sub(shr(fs,1), min_dist);*/ + isf_max = sub(fs, min_dist); /* Fs already divide per 2 */ + + IF (GT_16(isf[n-2], isf_max)) /* If danger of unstable filter in case of resonance in HF */ + { + FOR (i = sub(n, 2); i >= 0; i--) /* Reverify the minimum ISF gap in the reverse direction */ + { + if (GT_16(isf[i], isf_max)) + { + isf[i] = isf_max; + move16(); + } + isf_max = sub(isf[i], min_dist); + } + } +} + +/*========================================================================*/ +/* FUNCTION : lsf_stab_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : Check LSF stability (distance between old LSFs and */ +/* current LSFs) */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) Opt_AMR_WB : flag indicating AMR-WB IO mode */ +/* _ (Word16*) lsf : LSPs from past frame Q(x2.56) */ +/* _ (Word16*) lsfold : LSPs from past frame Q(x2.56) */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word16) stab_fac_fx : LP filter stability Q15 */ +/*========================================================================*/ +Word16 lsf_stab_fx( /* o : LP filter stability Q15*/ + const Word16 *lsf, /* i : LSF vector Q(x2.56)*/ + const Word16 *lsfold, /* i : old LSF vector Q(x2.56)*/ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame /* i : frame length */ +) +{ + Word16 i, m; + Word32 L_tmp; + Word16 tmp, e; + + /*-------------------------------------------------------------------* + * Check stability on lsf: distance between old lsf and current lsf + *-------------------------------------------------------------------*/ + IF ( Opt_AMR_WB ) + { + m = M-1; + move16(); + tmp = sub(lsf[0], lsfold[0]); + L_tmp = L_mult(tmp, tmp); /* Q1 */ + FOR (i = 1; i < m; i++) + { + tmp = sub(lsf[i], lsfold[i]); + L_tmp = L_mac(L_tmp, tmp, tmp); /* Q1 */ + } + } + ELSE + { + m = M; + move16(); + L_tmp = 0; + move32(); + FOR (i = 0; i < m; i++) + { + tmp = sub(lsf[i], lsfold[i]); + L_tmp = L_mac(L_tmp, tmp, tmp); /* Q1 */ + } + } + + e = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, e); /*Q(1+e)*/ + + IF( L_frame == L_FRAME16k) + { + /*stab_fac = (float)(1.25f - (tmp/625000.0f));*/ + L_tmp = Mpy_32_16_1(L_tmp, 16777); /* 30-eQ(1+e)*-21Q36 = 30-21-eQ31-9+e */ + } + ELSE + { + /* stab_fac = (float)(1.25f - (tmp1/400000.0f*2.56=1024000)) */ + L_tmp = Mpy_32_16_1(L_tmp, 26214); /* 30-eQ(1+e)*-21Q36 = 30-21-eQ31-9+e */ + } + + e = sub(30-21-1,e); + tmp = round_fx(L_shl(L_tmp, e)); /*Q14*/ + + tmp = sub(20480, tmp); /* 1.25 - tmp in Q14 */ + tmp = shl(tmp, 1); /* Q14 -> Q15 with saturation */ + + tmp = s_max(tmp, 0); + + return tmp; +} +/*-------------------------------------------------------------------* + * lsp2isp() + * + * Convert LSPs to ISPs via predictor coefficients A[] + *-------------------------------------------------------------------*/ + +void lsp2isp_fx( + const Word16 *lsp, /* i : LSP vector */ + Word16 *isp, /* o : ISP filter coefficients */ + Word16 *stable_isp, /* i/o: ISP filter coefficients */ + const Word16 m /* i : order of LP analysis */ +) +{ + Word16 a[M+1]; + + /* LSP --> A */ + /*lsp2a_stab( lsp, a, m );*/ + E_LPC_f_lsp_a_conversion(lsp, a, m ); + + /* A --> ISP */ + /*a2isp( a, isp, stable_isp, grid );*/ + E_LPC_a_isp_conversion( a, isp, stable_isp, m); + + /* Update to latest stable ISP */ + Copy( isp, stable_isp, M ); +} +/*-------------------------------------------------------------------* + * isp2lsp() + * + * Convert ISPs to LSPs via predictor coefficients A[] + *-------------------------------------------------------------------*/ + +void isp2lsp_fx( + const Word16 *isp, /* i : LSP vector */ + Word16 *lsp, /* o : ISP filter coefficients */ + Word16 *stable_lsp, /* i/o: stable LSP filter coefficients */ + const Word16 m /* i : order of LP analysis */ +) +{ + Word16 a[M+1]; + + /* ISP --> A */ + /*isp2a( isp, a, m );*/ + E_LPC_f_isp_a_conversion(isp, a, m ); + /* A --> LSP */ + /*a2lsp_stab( a, lsp, stable_lsp, grid );*/ + E_LPC_a_lsp_conversion(a, lsp, stable_lsp, m ); + /* Update to latest stable LSP */ + Copy( lsp, stable_lsp, M ); +} + +/*-------------------------------------------------------------------* + * lsf2isf() + * + * Convert LSPs to ISPs + *-------------------------------------------------------------------*/ + +void lsf2isf_fx( + const Word16 *lsf, /* i : LSF vector */ + Word16 *isf, /* o : ISF vector */ + Word16 *stable_isp, /* i/o: stable ISP filter coefficients */ + const Word16 m /* i : order of LP analysis */ +) +{ + Word16 tmp_lsp[M]; + Word16 tmp_isp[M]; + + /* LSF --> LSP */ + /*lsf2lsp( lsf, tmp_lsp, m, int_fs );*/ + E_LPC_lsf_lsp_conversion(lsf, tmp_lsp, m); + + /* LSP --> ISP */ + lsp2isp_fx( tmp_lsp, tmp_isp, stable_isp, m ); + + /* ISP --> ISF */ + /*isp2isf( tmp_isp, isf, m, int_fs );*/ + E_LPC_isp_isf_conversion(tmp_isp, isf, m); + + return; +} +/*-------------------------------------------------------------------* + * isf2lsf() + * + * Convert ISFs to LSFs + *-------------------------------------------------------------------*/ + +void isf2lsf_fx( + const Word16 *isf, /* i : ISF vector */ + Word16 *lsf, /* o : LSF vector */ + Word16 *stable_lsp /* i/o: stable LSP filter coefficients */ +) +{ + Word16 tmp_isp[M]; + Word16 tmp_lsp[M]; + + /* ISF --> ISP */ + /*isf2isp( isf, tmp_isp, m, int_fs );*/ + E_LPC_isf_isp_conversion(isf, tmp_isp, M); + /* ISP --> LSP */ + isp2lsp_fx( tmp_isp, tmp_lsp, stable_lsp, M); + + /* LSP --> LSF */ + /*lsp2lsf( tmp_lsp, lsf, m, int_fs );*/ + E_LPC_lsp_lsf_conversion(tmp_lsp, lsf, M); + return; +} +/*==========================================================================*/ +/* FUNCTION : void lsp2lsf_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : */ +/* * Transformation of LSPs to LSFs */ +/* * LSP are line spectral pair in cosine domain (-1 to 1). */ +/* * LSF are line spectral frequencies (0 to fs/2). */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 lsp[] i : lsp[m] (range: -1<=val<1) Q15 */ +/* Word16 m i : LPC order Q0 */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* Word16 lsf[] o : lsf[m] normalized (range: 0.0<=val<=0.5) Q(x2.56)*/ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*==========================================================================*/ +void lsp2lsf_fx( + const Word16 lsp[], /* i : lsp[m] (range: -1<=val<1) Q15*/ + Word16 lsf[], /* o : lsf[m] normalized (range: 0.0<=val<=0.5) Q(x2.56)*/ + const Word16 m /* i : LPC order Q0*/ + ,Word32 int_fs +) +{ + Word16 i; + Word32 L_tmp; + + FOR (i = 0; i < m; i++) + { + /*------------------------------------------------------* + * find value in table that is just greater than lsp[i] + *------------------------------------------------------*/ + + /* Retrieve Index Guess */ + /* Based on lsp[i] */ + L_tmp = sub_lsp2lsf_fx(lsp[i]); + IF(EQ_32(int_fs, INT_FS_16k_FX)) + { + L_tmp = L_shr(L_mult0(extract_l(L_tmp),5),2); + } + lsf[i] = extract_l(L_tmp); + } +} +/*===========================================================================*/ +/* FUNCTION : lsf2lsp_fx() */ +/*---------------------------------------------------------------------------*/ +/* PURPOSE : Transformation of LSFs to LSPs */ +/* LSP are line spectral pairs in cosine domain (-1 to 1). */ +/* LSF are line spectral frequencies (0 to fs/2). */ +/*---------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16[]) lsf : lsf[m] normalized (range: 0.0<=val<=0.5) Q(x2.56) */ +/* _ (Word16) m : LPC order */ +/*---------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) lsp : lsp[m] (range: -1<=val<1) Q15 */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*===========================================================================*/ +void lsf2lsp_fx( + const Word16 lsf[], /* i : lsf[m] normalized (range: 0.0<=val<=0.5) x2.56 */ + Word16 lsp[], /* o : lsp[m] (range: -1<=val<1) Q15 */ + const Word16 m /* i : LPC order Q0 */ + , Word32 int_fs +) +{ + Word16 i, ind, offset; + Word32 L_tmp; + Word16 c, ind2; + Word16 const add_prec = 4; + Word16 lsf_tmp; + + + /* 0.75 = (1<clip_var_fx[0]; + move16(); + + FOR(i=0; imem_AR_fx[i]; + move16(); + mem_MA[i] = st_fx->mem_MA_fx[i]; + move16(); + lsp_new_bck[i] = lsp_new[i]; + move16(); + lsf_new_bck[i] = lsf_new[i]; + move16(); + lsp_mid_bck[i] = lsp_mid[i]; + move16(); + } + + *mCb1 = st_fx->mCb1_fx; + move16(); + *streaklimit = st_fx->streaklimit_fx; + move16(); + *pstreaklen = st_fx->pstreaklen_fx; + move16(); + + FOR(i=0; iBin_E_fx[i]; + move32(); + } + + FOR(i=0; i<(L_FFT/2); i++) + { + Bin_E_old[i]=st_fx->Bin_E_old_fx[i]; + move32(); + } + + /* back-up memories */ + FOR(i=0; iLPDmem.mem_syn[i]; + move16(); + } + + *mem_w0_bck = st_fx->LPDmem.mem_w0; + move16(); + + + *btilt_code_fx = LPDmem->tilt_code; + *gc_threshold_fx = LPDmem->gc_threshold; + Copy( st_fx->clip_var_fx, clip_var_bck_fx, 6 ); + *next_force_sf_bck_fx = st_fx->next_force_safety_net_fx; + + + return; +} + +void lsf_update_memory( + Word16 narrowband, /* i : narrowband flag */ + const Word16 qlsf[], /* i : quantized lsf coefficients */ + Word16 old_mem_MA[], /* i : MA memory */ + Word16 mem_MA[], /* o : updated MA memory */ + Word16 lpcorder /* i : LPC order */ +) +{ + Word16 i; + + FOR (i=0; iclip_var_fx[0] = clip_var; + move16(); + + FOR(i=0; imem_AR_fx[i] = mem_AR[i]; + move16(); + st_fx->mem_MA_fx[i] = mem_MA[i]; + move16(); + lsp_new[i] = lsp_new_bck[i]; + move16(); + lsf_new[i] = lsf_new_bck[i]; + move16(); + lsp_mid[i] = lsp_mid_bck[i]; + move16(); + } + + st_fx->mCb1_fx = mCb1; + move16(); + st_fx->streaklimit_fx = streaklimit; + move16(); + st_fx->pstreaklen_fx = pstreaklen; + move16(); + + FOR(i=0; iBin_E_fx[i] = Bin_E[i]; + move16(); + } + + FOR(i=0; i<(L_FFT/2); i++) + { + st_fx->Bin_E_old_fx[i]=Bin_E_old[i]; + move32(); + } + + /* restoring memories */ + st_fx->LPDmem.mem_w0 = mem_w0_bck; + move16(); + + FOR(i=0; iLPDmem.mem_syn[i] = mem_syn_bck[i]; + move16(); + } + + move16(); + move32(); + move16(); + LPDmem->tilt_code = btilt_code_fx; + LPDmem->gc_threshold = gc_threshold_fx; + Copy( clip_var_bck_fx, st_fx->clip_var_fx, 6 ); + st_fx->next_force_safety_net_fx = next_force_sf_bck_fx; + + return; +} + +/* Returns: codebook index */ +Word16 tcxlpc_get_cdk( + Word16 acelp_ext_mode /* (I) GC/VC indicator */ +) +{ + Word16 cdk; + + move16(); + cdk = 0; + if ( EQ_16(acelp_ext_mode, VOICED)) + { + cdk = 1; + move16(); + } + + return cdk; +} + +void msvq_dec +( + const Word16 *const*cb, /* i : Codebook (indexed cb[*stages][levels][p]) (14Q1*1.28)*/ + const Word16 dims[], /* i : Dimension of each codebook stage (NULL: full dim.) */ + const Word16 offs[], /* i : Starting dimension of each codebook stage (NULL: 0) */ + const Word16 stages,/* i : Number of stages */ + const Word16 N, /* i : Vector dimension */ + const Word16 maxN, /* i : Codebook dimension */ + const Word16 Idx[], /* i : Indices */ + Word16 *uq /* o : quantized vector (14Q1*1.28)*/ +) +{ + Word16 i,j,offset; + Word16 N34; + Word16 n, maxn, start; + + + + set16_fx(uq, 0, N); + + FOR ( i=0; i lsp[i] */ + tmp = sub(lsp_i, cos_table_129[ind]); + /* + 69%: (Final Index - Index Guess) is <= 1 + 28%: (Final Index - Index Guess) is 2 + 2%: (Final Index - Index Guess) is >= 3 + <1%: ... + */ + IF (tmp > 0) /* possible range 0 to -5 (-1-2-2) */ + { + ind = sub(ind, 1); + tmp = sub(lsp_i, cos_table_129[ind]); + IF (tmp > 0) + { + ind = sub(ind, 2); + tmp = sub(lsp_i, cos_table_129[ind]); + if (tmp > 0) + { + ind = sub(ind, 2); + } + tmp = sub(lsp_i, cos_table_129[ind+1]); + if (tmp <= 0) + { + ind = add(ind, 1); + } + tmp = sub(lsp_i, cos_table_129[ind]); + } + } + + /* acos(lsp[i])= ind*128 + (lsp[i]-table[ind]) * acos_slope[ind] / 2048 */ + L_tmp = L_mac(1L<<11, tmp, acos_slope[ind]); + L_tmp = L_shr(L_tmp, 12); /* (lsp[i]-table[ind]) * acos_slope[ind]) >> 11 */ + L_tmp = L_mac0(L_tmp, ind, 128); + + return L_tmp; +} + +/*===================================================================*/ +/* FUNCTION : compute_poly_product_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Compute polynomial product for P(z) for LSP */ +/* to LPC conversion */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16[]) coef : LSP coefficients, Q15 */ +/* _ (Word16 []) order: LPC order */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word32[]) p : output sequence, Q24 */ +/* 1st entry is always 1.0, Q24 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*===================================================================*/ +/* NOTE: */ +/* P(z)=(1+z^-1)*PI(j=1to(order/2)) (1 - 2*z^-1*cos(2*pi*w(2j-1)) + z^-2) */ +/* Q(z)=(1-z^-1)*PI(j=1to(order/2)) (1 - 2*z^-1*cos(2*pi*w(2j)) + z^-2) */ +/*===================================================================*/ +void compute_poly_product_fx( + Word16* coef, /* i : LSP coefficients, Q15 */ + Word32* p, /* o : output sequence, Q24 */ + Word16 order /* i : order */ +) +{ + Word16 i, len; + Word32 lspcos[LPC_SHB_ORDER]; + Word32 p2[LPC_SHB_ORDER]; /* intermediate product, Q24*/ + Word32* p_in, *p_out, *p_temp; + + FOR ( i = 0; i < order / 2; i++ ) + { + lspcos[i] = poscos_fx( coef[i * 2] ); + move32(); /* lspcos =-cos(lsp) in Q30*/ + } + + /* Set up first polynomial for convolution (1 -2cos(w5) 1) */ + /* First element of output is 1, all in Q24 */ + p[0] = L_deposit_h( 0x100 ); /* 1.0 in Q24 */ + p[2] = L_deposit_h( 0x100 ); /* 1.0 in Q24 */ + p[1] = L_shr( lspcos[order / 2 - 1], 5 ); /* p2[1]=-2cos(w5), Q24 */ + p2[0] = L_deposit_h( 0x100 ); /* 1.0 in Q24 */ + + len = 1; + move16(); + + len = 1; + p_in = p + 1; /* 2nd entry of input sequence */ + p_out = p2 + 1; /* 2nd entry of output sequence */ + FOR ( i = 0; i < ( order / 2 - 1 ); i++ ) + { + lsp_convolve_fx( L_shr( lspcos[i], 5 ), p_in, p_out, len ); + + p_temp = p_in; + p_in = p_out; + p_out = p_temp; /* swap input/output buffer */ + len = add( len, 1 ); + } + + /* if((order/2 - 1)%2 != 0) */ + IF ( s_and( ( order / 2 - 1 ), 1 ) != 0 ) + { + FOR ( i = 1; i <= order / 2; i++ ) + { + p[i] = p_in[i - 1]; + move32(); + } + } + +} + +/*===================================================================*/ +/* FUNCTION : lsp_convolve_fx ( ) */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Convolution of LSP polynomial for LSP to LPC */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ ( Word32[]) p1 : 2nd entry of input sequence, Q24 */ +/* 1st entry is 1.0, Q24 */ +/* _ ( Word32) x : -2cos( w) in Q24 */ +/* _ ( Word16) len: length of output-2 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ ( Word32[]) p2 : 2nd entry of output sequence, Q24 */ +/* 1st entry is 1.0, Q24 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*===================================================================*/ +/* NOTE: Convolves ( 1 S 1) where S is the -2cos( w) value) with the */ +/* long sequence where the input long sequence on consecutive calls */ +/* is ( 1 X1 1), ( 1 X1 X2 X1), ( 1 X1 X2 X3 X2), ( 1 X1 X2 X3 X4 X3). */ +/* ( Since the sequence is symmetric, we only need to output one */ +/* entry beyond the center point for the next iteration). */ +/* The 1st entry of the convolution is 1, the 2nd is X1+S1, and */ +/* the rest have the form X( i-1) + X( i)*S + X( i+1). */ +/* Final output sequence is ( 1 X1 X2 X3 X4 X5 X4) */ +/*===================================================================*/ +void lsp_convolve_fx( + Word32 x, + Word32* p1, + Word32* p2, + Word16 len +) +{ + Word16 i, d1h, d1l, d2h, d2l; + Word32 Ltemp; + Word32 Lacc; + + d1h = extract_h( x ); /* d1h in Q8 */ + d1l = extract_l( x ); /* d1l in Q24 */ + + Ltemp = L_add( x, p1[0] ); /* first output is p1[0]+x, Q24 */ + + p2[0] = Ltemp; + move32(); + Ltemp = L_deposit_h( 0x100 ); /* Ltemp=1.0, Q24 */ + FOR ( i = 0; i < len; i++ ) + { + Ltemp = L_add( Ltemp, p1[i + 1] ); /* Ltemp2=p1[i-1]+p1[i+1], Q24 */ + d2h = extract_h( p1[i] ); + d2l = extract_l( p1[i] ); + + /* Lacc=L_mult_su( d1h,d2l); */ + Lacc = L_mult0( d1h, ( UWord16 )d2l ); + Lacc = L_mac0( Lacc, d2h, d1l ); + Lacc = L_add( L_shr( Lacc, 16 ), L_shr( L_mult( d1h, d2h ), 1 ) ); + /* Lacc=p1[i]* x, Q16 */ + Lacc = L_add( L_shl( Lacc, 8 ), Ltemp ); /* Lacc=p1[i-1]+p1[i+1]+p1[i]*x, Q24 */ + + p2[i + 1] = Lacc; + move32(); + + Ltemp = p1[i]; + move32(); + } /* end for */ + + p2[i + 1] = p2[i - 1]; + move32(); +} + + + +/*===================================================================*/ +/* FUNCTION : poscos_fx ( ) */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Compute cosine by approximation */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* */ +/* _ ( Word16) w: angle in radians/pi, Q14 ( 0<=w<=16384) */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ ( Word32) : -cos( w) in Q30 */ +/*===================================================================*/ +/* NOTE: This function uses 4 coefficients in the approx formula */ +/* Approx Formula: cos( w) = z + c1*z^3 + c2*z^5 + c3*z^7 + c4*z^9 */ +/* where z = pi/2 - w, c1=-.1666665668, c2=.8333025139E-2, */ +/* c3=-.198074182E-3, and c4=.2601903036E-5 */ +/*===================================================================*/ + + +Word32 poscos_fx( Word16 w ) +{ + Word16 a, z, z2, z3, z5, z7, z9; + Word32 Ltemp; + Word32 Lacc; + + IF ( w == 0 ) + { + return ( 0xc0000004 ); /* -1.0 in Q30 */ + } + ELSE + { + z = 0x2000; + move16(); /* z=0.5 in Q14 */ + z = shl( sub( z, w ), 2 ); /* z = 0.5-w in Q16 */ + + a = 0x6488; + move16(); /* a=pi in Q13 */ + z = mult_r( z, a ); /* z=pi*( 0.5-w), Q14 */ + z2 = mult_r( z, z ); /* z2=z^2, Q13 */ + z3 = round_fx( L_shl( L_mult0( z, z2 ), 0 ) ); /* z3=z^3, Q11 */ + z5 = mult_r( z2, z3 ); /* z5=z^5, Q9 */ + z7 = round_fx( L_shl( L_mult0( z2, z5 ), 0 ) ); /* z7=z^7, Q6 */ + z9 = round_fx( L_shl( L_mult0( z2, z7 ), 0 ) ); /* z9=z^9, Q3 */ + + Lacc = L_mult( z9, cos_coef_new[0] ); /* Lacc=c4*z^9, Q31, c4 in Q28 */ + Lacc = L_mac0( Lacc, z7, cos_coef_new[1] ); /* c3 in Q25 */ + Ltemp = L_shl( L_mult( z3, cos_coef_new[3] ), 1 ); /* Ltemp=c1*z^3, Q31, c1 in Q17 */ + Lacc = L_add( L_shr( Lacc, 1 ), Ltemp ); /* Lacc=c1*z^3+c3*z^7+c4*^z9, Q30 */ + Lacc = L_add( Lacc, L_deposit_h( z ) ); + Ltemp = L_mult( z5, cos_coef_new[2] ); /* Ltemp=-c2*z^5, Q29, cos_coef[2]=-c2 in Q19 */ + Lacc = L_sub( Lacc, L_shl( Ltemp, 1 ) ); /* Lacc=cos( w) in Q30 */ + + return L_negate( Lacc ); /* return -cos( w), Q30 */ + } /* end else */ +} +/*===================================================================*/ +/* FUNCTION : root_search_fx ( ) */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Search root of the P or Q polynomial in a given */ +/* interval using binary search */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ ( Word16) low : Low index of the interval, Q9 ( 0-511) */ +/* _ ( Word16) high : High index of the interval, Q9 ( 0-511) */ +/* _ ( Word32 []) coef: polynomial coefficients, Q26 */ +/* _ ( Word16) order : LPC order */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ ( Word32) v_low: Polynomial value at low index, Q25 */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ ( Word16) root in Q15, or 0xffff if no root is found */ +/*===================================================================*/ + +Word16 root_search_fx( Word16 low, + Word16 high, + Word32* v_low, + Word32* coef, + Word16 order + ) +{ + Word16 f; + Word32 v_high, vh; + Word32 Ltemp, L_tmp1, L_tmp, Ltmp; + Word16 exp1, tmp; + + v_high = polynomial_eval_fx( high, coef, order ); /* v_high has the value at high index */ + + IF ( v_high != 0 ) + { + /* No exact root found */ + test(); + IF ( ( v_high ^ ( *v_low ) ) >= 0 ) + { + /* No root in this interval ( low high] */ + *v_low = v_high; + move32(); + return ( -1 ); + } + ELSE + { + /* there is a root in this interval */ + /* Do binary search for root */ + vh = v_high; + move16(); + + WHILE ( GE_16( sub( high, low ), 2 )) + { + /* high-low>=2 */ + f = shr( add( high, low ), 1 ); /* f=( high+low)/2 */ + Ltemp = polynomial_eval_fx( f, coef, order ); + IF ( Ltemp == 0 ) + { + *v_low = v_high; + move32();/* Set low value for next root search call */ + return ( shl( f, 6 ) ); + } + ELSE + { + test(); + IF ( ( Ltemp ^ ( *v_low ) ) < 0 ) + { + /* root between f & low */ + high = f; + move16(); + vh = Ltemp; + move32(); + } + ELSE + { + *v_low = Ltemp; + move32(); + low = f; + move16(); + } + } + } /* end while */ + + /* do interpolation for root in between high and low */ + /* Lacc=divide_dp( *v_low, L_sub( *v_low,vh),2,1); // Lacc in Q31 */ + L_tmp = L_sub( *v_low, vh ); + + if ( LT_32( *v_low, vh )) + { + L_tmp = L_negate( L_tmp ); + } + + exp1 = norm_l( L_tmp ); + L_tmp1 = L_shl( L_tmp, exp1 ); + tmp = extract_h( L_tmp1 ); + exp1 = sub(30 - 25, exp1); + tmp = div_s( 16384, tmp ); /* 15+exp1 */ + Ltmp = Mult_32_16( *v_low, tmp ); /* 15+exp1+25-15 */ + Ltemp = L_shl( Ltmp, ( 6 - exp1 ) ); /* Q31 */ + if ( LT_32( *v_low, vh )) + { + Ltemp = L_negate( Ltemp ); + } + Ltemp = L_shr( Ltemp, 9 ); /* Ltemp =quotient*1.0 in Q31 */ + + *v_low = v_high; + move16(); + return ( add( round_fx( Ltemp ), shl( low, 6 ) ) ); + } /* end else ( root in interval) */ + } /* end else ( exact root at high) */ + + /* find the exact root */ + *v_low = v_high; + move32(); /* Set low value for next root search call */ + return ( shl( high, 6 ) ); /* return exact root at high in Q15 */ +} + +/*===================================================================*/ +/* FUNCTION : calc_weight( ) */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : This function computes the weight given delta1 +and delta2 */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) delta1: (Q15) */ +/* _ (Word16) delta2: (Q15) */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 *) n1: o/p weight is Q(31-n1) */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None. */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word32) Lsum1: computed weight Q(31-n1) */ +/* (alpha/(sqrt(delta1*delta2)) */ +/*===================================================================*/ + +Word32 calc_weight( + Word16 delta1, + Word16 delta2, + Word16* n1 +) +{ + Word16 n; + Word32 L_tmp; + Word16 alpha=0x4F94; + move16(); /* ( 0.5*250/( 2*pi)) in Q10*/ + + L_tmp = L_mult0( delta1, delta2 ); /* Q30 */ + n = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, n ); + n = sub(1, n); + L_tmp = Isqrt_lc( L_tmp, &n ); /* Q( 31-n)*/ + + L_tmp = Mult_32_16( L_tmp, alpha ); /* Q( 26-n) */ + + *n1 = n; + move16(); + + return L_tmp; +} + +/*===================================================================*/ +/* FUNCTION : polynomial_eval_fx ( ) */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Evaluate P or Q polynomial at given frequency */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) f : frequency used as index for cosine table lookup */ +/* Q9 */ +/* _ (Word32 []) coef: polynomial coefficients, Q26 */ +/* _ (Word16 []) order: LPC order */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word32) polynomial value at given frequency f, Q25 */ +/*===================================================================*/ +/* Note: This function uses 512 entry cosine table cos_table[], Q15 */ +/*===================================================================*/ +/* if (K = order/2) */ +/* P(w)=cos(Kw)+p[1]*cos((K-1)w)+p[2]*cos((K-2)w)+...+p[(K-1)]*cos(w)+p[K]/2 */ +/* Q(w)=cos(Kw)+q[1]*cos((K-1)w)+q[2]*cos((K-2)w)+...+q[(K-1)]*cos(w)+q[K]/2 */ +/*===================================================================*/ + +/* 40-32 bit conversion */ +Word32 polynomial_eval_fx( Word16 f, + Word32* coef, + Word16 order + ) +{ + Word16 i, idx; + Word16 dh, dl, coslut; + Word32 Ltemp, L_tmp1, L_tmp; + Word32 Lacc; + idx = f; + move16(); + dh = extract_h( coef[order / 2] ); /* Q10 */ + dl = extract_l( coef[order / 2] ); /* Q16 */ + + coslut = 0x4000; + move16(); /* coslut=0.5 in Q15 */ + Ltemp = L_mult0( coslut, dh ); /* Ltemp=MSW, coef[5]/2 in Q25 */ + + Lacc = L_mult0( coslut, dl ); /* Lacc=LSW, coef[5]/2 in Q41 //Q31 */ + Lacc = L_shr( Lacc, 1 ); /* Q30 */ + FOR ( i = ( order / 2 ) - 1; i > 0; i-- ) + { + coslut = cos_table[idx]; + move16(); /* coslut=cos( ( ( order/2)-i)f), Q15 */ + dh = extract_h( coef[i] );/* Q10 */ + dl = extract_l( coef[i] );/* Q16 */ + + Ltemp = L_add( Ltemp, L_mult0( dh, coslut ) ); /* Q25 */ + IF ( dl < 0 ) + { + L_tmp1 = L_shl( L_add( 65536, dl ), 14 ); + L_tmp = Mult_32_16( L_tmp1, coslut ); + Lacc = L_add( Lacc, L_tmp ); + } + ELSE + { + Lacc = L_add( Lacc, L_shr( L_mult0( coslut, dl ), 1 ) );/* Q30 */ + } + + idx += f; + if ( GE_16(idx, 512)) idx=sub(idx, 512); /* modulo of 512 */ + } + + coslut = cos_table[idx]; + move16(); /* coslut=cos( 5f), Q15 */ + Ltemp = L_add( Ltemp, L_mult0( 0x400, coslut ) ); /* coef[0]=1.0, Q25 */ + + return ( L_add( Ltemp, L_shr( Lacc, 15 ) ) ); /* Q25 */ +} + +/*----------------------------------------------------------------------------------* +* v_sort: +* +* This is very fast with almost ordered vectors. The first 15 ISF values +* are almost always sorted. +*----------------------------------------------------------------------------------*/ +void v_sort( + Word16 *r, /* i/o: Vector to be sorted in place */ + const Word16 lo, /* i : Low limit of sorting range */ + const Word16 up /* I : High limit of sorting range */ +) +{ + Word16 i, j; + Word16 tempr; + + + FOR (i=sub(up, 1); i>=lo; i--) + { + tempr = r[i]; + move16(); + FOR (j=i; j cos(pi/2) = 0. + *---------------------------------------------------------------------*/ + + FOR (i = 1; i <= iuni; i++) + { + Mpy_32_16_ss(R[0], x[i-1], &mh, &ml); + r0 = L_add(R[1], mh); + + Mpy_32_16_ss(S[0], x[i-1], &mh, &ml); + s0 = L_add(S[1], mh); + + + FOR (j = 2; j <= NC; j++) + { + Mpy_32_16_ss(r0, x[i-1], &mh, &ml); + r0 = L_add(R[j], mh); + + Mpy_32_16_ss(s0, x[i-1], &mh, &ml); + s0 = L_add(S[j], mh); + } + + G[i] = inv_pow(r0, s0, x[i-1]); + move32(); + } + + /*---------------------------------------------------------------------* + * Power spectrum at points other than x = -1, 0, and 1 and unique + * points is computed using the anti-symmetry of the grid relative + * to the midpoint x = 0 in order to reduce looping. + *---------------------------------------------------------------------*/ + + FOR ( ; i < imid; i++) + { + x2 = mult_r(x[i-1], x[i-1]); + + Mpy_32_16_ss(R[0], x2, &mh, &ml); + re = L_add(R[2], mh); + Mpy_32_16_ss(R[1], x2, &mh, &ml); + ro = L_add(R[3], mh); + + Mpy_32_16_ss(S[0], x2, &mh, &ml); + se = L_add(S[2], mh); + Mpy_32_16_ss(S[1], x2, &mh, &ml); + so = L_add(S[3], mh); + + FOR (j = 4; j < NC; j+=2) + { + Mpy_32_16_ss(re, x2, &mh, &ml); + re = L_add(R[j], mh); + Mpy_32_16_ss(ro, x2, &mh, &ml); + ro = L_add(R[j+1], mh); + Mpy_32_16_ss(se, x2, &mh, &ml); + se = L_add(S[j], mh); + Mpy_32_16_ss(so, x2, &mh, &ml); + so = L_add(S[j+1], mh); + } + + Mpy_32_16_ss(re, x2, &mh, &ml); + L_tmp = L_add(R[j], mh); + Mpy_32_16_ss(ro, x[i-1], &mh, &ml); + re = L_add(L_tmp, mh); + ro = L_sub(L_tmp, mh); + + Mpy_32_16_ss(se, x2, &mh, &ml); + L_tmp = L_add(S[j], mh); + Mpy_32_16_ss(so, x[i-1], &mh, &ml); + se = L_add(L_tmp, mh); + so = L_sub(L_tmp, mh); + + G[i] = inv_pow(re, se, x[i-1]); + move32(); + G[N-i-1] = inv_pow(so, ro, x[i-1]); + move32(); + } + + return; +} + +static Word32 b_inv_sq( + const Word32 in32, /* i : Input not normalized to inverse */ + const Word16 exp_in /* i : input current exponent */ +) +{ + Word16 m_den, exp_den; + Word16 div_out; + Word32 Ltmp; + + exp_den = norm_l(in32); + m_den = extract_h(L_shl(in32, exp_den)); + exp_den = add(sub(30,exp_den),sub(16,exp_in)); + + m_den = mult_r(m_den, m_den); + exp_den = shl(exp_den,1); + + div_out = div_s(8192,m_den); + Ltmp = L_shl(div_out, add(sub(30-13, exp_den),15)); /*Q15*/ + + return Ltmp; +} + +static Word32 inv_pow( + const Word32 re, + const Word32 se, + const Word16 x +) +{ + Word16 exp1, exp2; + Word16 tmp; + Word32 L_tmp; + Word32 mh; + UWord16 ml; + Word32 r0, s0; + + IF(re==0) + { + exp1 = 30; + move16(); + r0 = L_deposit_l(0); + } + ELSE + { + exp1 = norm_l(re); + tmp = extract_h(L_shl(re, exp1)); + L_tmp = L_shr(L_mult(tmp, tmp), 1); + Mpy_32_16_ss(L_tmp, x, &mh, &ml); + r0 = L_add(L_tmp, mh); + } + + IF(se==0) + { + exp2 = 30; + move16(); + s0 = L_deposit_l(0); + } + ELSE + { + exp2 = norm_l(se); + tmp = extract_h(L_shl(se, exp2)); + L_tmp = L_shr(L_mult(tmp, tmp), 1); + Mpy_32_16_ss(L_tmp, x, &mh, &ml); + s0 = L_sub(L_tmp, mh); + } + + IF(exp1 > exp2) + { + exp1 = shl(sub(exp1, exp2), 1); + r0 = L_shr(r0, exp1); + + exp2 = add(add(exp2, exp2), 8); + } + ELSE + { + exp2 = shl(sub(exp2, exp1), 1); + s0 = L_shr(s0, exp2); + + exp2 = add(add(exp1, exp1), 8); + } + + r0 = L_add(r0, s0); + exp1 = norm_l(r0); + L_tmp = L_shl(r0, exp1); + tmp = extract_h(L_tmp); + IF(tmp==0) + { + return MAX_32; + } + tmp = div_s((Word16)((1<<14)-1), tmp); + exp1 = add(exp1, exp2); + L_tmp = L_shr(tmp, sub(31, exp1)); /* result in Q15 */ + + return(L_tmp); +} + + +/*---------------------------------------------------------------------* + * spectautocorr() + * + * Computes the autocorrelation r[j] for j = 0, 1, ..., M from + * the power spectrum P(w) by using rectangle rule to approximate + * the integral + * + * 1 pi + * r[j] = --- I P(w) cos(j*w) dw. + * 2*pi -pi + * + * It is sufficient to evaluate the integrand only from w = 0 to + * w = pi due to the symmetry P(-w) = P(w). We can further + * employ the relation + * + * cos(j*(pi - w)) = (-1)^j cos(j*w) + * + * to use symmetries relative to w = pi/2. + * + * When applying the rectangle rule, it is useful to separate w = 0, + * w = pi/2, and w = pi. By using a frequency grid of N points, we + * can express the rectangle rule as + * + * r[j] = G[0] + 2*a*G[(N-1)/2] + b*G[N-1] + * + * M + * + 2 sum (G[i] - G[N-i-1]) cos(j*x[i]) + * i=1 + * + * where G[i] is the power spectrum at the grid point cos(i*pi/N) + * and M = (N-1)/2 - 1 is the number of the grid points in the + * interval(0, pi/2). + * + * The coefficients + * + * b = (-1)^j + * a = (1 + (-1)^(j+1))(-1)^floor(j/2) + * + * follow from the properties of cosine. The computation further + * uses the recursion + * + * cos(j*w) = 2*cos(w)*cos((j-1)*w) - cos((j-2)*w) + * + * Note that the autocorrelation can be scaled for convenience, + * because this scaling has no impact on the LP coefficients to be + * calculated from the autocorrelation. The expression of r[j] thus + * omits the division by N. + * + * See the powerspect function on the definition of the grid. + * + * References + * J. Makhoul, "Spectral linear prediction: properties and + * applications," IEEE Trans. on Acoustics, Speech and Signal + * Processing, Vol. 23, No. 3, pp.283-296, June 1975 + *---------------------------------------------------------------------*/ + +static void spectautocorr_fx( + const Word16 x[], /* i: Grid points x[0:m-1] */ + const Word16 N, /* i: Number of grid points */ + const Word32 G[], /* i: Power spectrum G[0:N-1] */ + Word16 rh[], /* o: Autocorrelation r[0:M] */ + Word16 rl[] /* o: Autocorrelation r[0:M] */ +) +{ + Word16 c[M+1]; /* c[j] = cos(j*w) */ + Word32 gp, gn; + Word16 i, j; + Word16 imid; + Word32 mh; + UWord16 ml; + Word32 r[M+1]; + Word16 exp0; + + /*---------------------------------------------------------------------* + * The mid point of the cosine table x of m entries assuming an odd m. + * Only the entries x[0] = cos(pi/m), x[1] = cos(2*pi/m), ..., + * x[imid-1] = cos((imid-1)*pi/m) need to be stored due to trivial + * cos(0), cos(pi/2), cos(pi), and symmetry relative to pi/2. + * Here m = 51. + *---------------------------------------------------------------------*/ + + imid = (N - 1)/2; + move16(); + + /*---------------------------------------------------------------------* + * Autocorrelation r[j] at zero lag j = 0 for the upper half of the + * unit circle, but excluding the points x = cos(0) and x = cos(pi). + *---------------------------------------------------------------------*/ + + r[0] = G[1]; + move32(); + FOR (i = 2; i < N-1; i++) + { + r[0] = L_add(r[0], G[i]); + move32(); + } + + /*---------------------------------------------------------------------* + * Initialize the autocorrelation r[j] at lags greater than zero + * by adding the midpoint x = cos(pi/2) = 0. + *---------------------------------------------------------------------*/ + + r[1] = L_deposit_l(0); + r[2] = -G[imid]; + move32(); + + FOR (i = 3; i < M; i+=2) + { + r[i] = L_deposit_l(0); + r[i+1] = -r[i-1]; + move32(); + } + + /*---------------------------------------------------------------------* + * Autocorrelation r[j] at lags j = 1, 2, ..., M. The computation + * employes the relation cos(j*(pi - w)) = (-1)^j cos(j*w) and + * cos(j*w) = 2*cos(w)*cos((j-1)*w) - cos((j-2)*w) for obtaining + * the cosine c[j] = cos(j*w). + *---------------------------------------------------------------------*/ + + c[0] = (Word16)32767; + move16(); /* 1.0 in Q15 */ + FOR (i = 1; i < imid; i++) + { + gp = L_add(G[i], G[N-i-1]); + gn = L_sub(G[i], G[N-i-1]); + + /*r[1] = L_mac(r[1], x[i-1], gn);*/ + Mpy_32_16_ss(gn, x[i-1], &mh, &ml); + r[1] = L_add(r[1], mh); + move32(); + c[1] = x[i-1]; + move16(); + + FOR (j = 2; j < M; j+=2) + { + c[j] = mult_r(c[j-1], x[i-1]); + move16(); + c[j] = add(c[j], sub(c[j], c[j-2])); + move16(); + + /*r[j] = L_mac(r[j], c[j], gp);*/ + Mpy_32_16_ss(gp, c[j], &mh, &ml); + r[j] = L_add(r[j], mh); + move32(); + + c[j+1] = mult_r(c[j], x[i-1]); + move16(); + c[j+1] = add(c[j+1], sub(c[j+1], c[j-1])); + move16(); + + /*r[j+1] = L_mac(r[j+1], c[j+1], gn);*/ + Mpy_32_16_ss(gn, c[j+1], &mh, &ml); + r[j+1] = L_add(r[j+1], mh); + move32(); + } + c[j] = mult_r(c[j-1], x[i-1]); + move16(); + c[j] = add(c[j], sub(c[j], c[j-2])); + move16(); + + Mpy_32_16_ss(gp, c[j], &mh, &ml); + r[j] = L_add(r[j], mh); + move32(); + } + + /*---------------------------------------------------------------------* + * Add the endpoints x = cos(0) = 1 and x = cos(pi) = -1 as + * well as the lower half of the unit circle. + *---------------------------------------------------------------------*/ + gp = L_shr(L_add(G[0], G[N-1]), 1); + gn = L_shr(L_sub(G[0], G[N-1]), 1); + + r[0]= L_add(r[0], gp); + move32(); + exp0 = norm_l(r[0]); + L_Extract(L_shl(r[0], exp0), &rh[0], &rl[0]); + + FOR (j = 1; j < M; j+=2) + { + L_Extract(L_shl(L_add(r[j], gn), exp0), &rh[j], &rl[j]); + L_Extract(L_shl(L_add(r[j+1], gp), exp0), &rh[j+1], &rl[j+1]); + } + + return; +} + +/*---------------------------------------------------------------------* + * zeros2poly() + * + * Computes the coefficients of the polynomials + * + * R(x) = prod (x - x[i]), + * i = 0,2,4,... + * + * S(x) = prod (x - x[i]), + * i = 1,3,5,... + * + * when their zeros x[i] are given for i = 0, 1, ..., n-1. The + * routine assumes n = 1 or even n greater than or equal to 4. + * + * The polynomial coefficients are returned in R[0:n/2-1] and + * S[0:n/2-1]. The leading coefficients are in R[0] and S[0]. + *---------------------------------------------------------------------*/ +static void zeros2poly_fx( + Word16 x[], /* i: Q15 Zeros of R(x) and S(x) */ + Word32 R[], /* o: Q22 Coefficients of R(x) */ + Word32 S[] /* o: Q22 Coefficients of S(x) */ +) +{ + Word16 xr, xs; + Word16 i, j; + Word32 mh; + UWord16 ml; + + R[0] = (1<<27)-1; + move32(); + S[0] = (1<<27)-1; + move32(); + R[1] = L_msu(0, x[0], 1<<11); + move32(); + S[1] = L_msu(0, x[1], 1<<11); + move32(); + + FOR (i = 2; i <= NC; i++) + { + xr = negate(x[2*i-2]); + xs = negate(x[2*i-1]); + + Mpy_32_16_ss(R[i-1], xr, &R[i], &ml); + Mpy_32_16_ss(S[i-1], xs, &S[i], &ml); + + FOR (j = i-1; j > 0; j--) + { + Mpy_32_16_ss(R[j-1], xr, &mh, &ml); + R[j] = L_add(R[j], mh); + Mpy_32_16_ss(S[j-1], xs, &mh, &ml); + S[j] = L_add(S[j], mh); + } + } + + return; +} + +/*---------------------------------------------------------------------* + * polydecomp() + * + * Computes the coefficients of the symmetric and antisymmetric + * polynomials P(z) and Q(z) that define the line spectrum pair + * decomposition of a given polynomial A(z) of order n. For even n, + * + * P(z) = [A(z) + z^(n+1) A(1/z)]/(1/z + 1), + * Q(z) = [A(z) - z^(n+1) A(1/z)]/(1/z - 1), + * + * These polynomials are then expressed in their direct form, + * respectively, R(x) and S(x), on the real axis x = cos w using + * explicit Chebyshev polynomials of the first kind. + * + * The coefficients of the polynomials R(x) and S(x) are returned + * in R[0:n/2] and S[0:n/2] for the given linear prediction + * coefficients A[0:n/2]. Note that R(x) and S(x) are formed in + * place such that P(z) is stored in the same array than R(x), + * and Q(z) is stored in the same array than S(x). + * + * The routines assumes n = 16. + *---------------------------------------------------------------------*/ + +static void polydecomp_fx( + Word16 A[], /* i: Q12 linear prediction coefficients */ + Word32 R[], /* o: Q20 coefficients of R(x) */ + Word32 S[] /* o: Q20 coefficients of S(x) */ +) +{ + Word16 scale; + Word16 i; + Word32 Ltmp1, Ltmp2; + + scale = shl((1<<5), norm_s(A[0])); + + R[0] = (1<<20)-1; + move32(); /* Q20 */ + S[0] = (1<<20)-1; + move32(); + + FOR(i=0; i AMRWB_1825 */ + 0x06, /* AMRWB_2305 -> AMRWB_1825 */ + 0x04, /* AMRWB_2385 */ + 0x07, /* invalid request -> none */ + 0x07, /* invalid request -> none */ + 0x07, /* invalid request -> none */ + 0x07, /* invalid request -> none */ + 0x07, /* invalid request -> none */ + 0x07, /* invalid request -> none */ + 0x07 /* invalid request -> none */ +}; + +/* 3 bit to 4 bit AMR-WB CMR remapping table */ +static const Word16 amrwb_4bit_cmr[8] = +{ + 0x00, /* AMRWB_660 */ + 0x01, /* AMRWB_885 */ + 0x02, /* AMRWB_1265 */ + 0x04, /* AMRWB_1585 */ + 0x08, /* AMRWB_2385 */ + 0x03, /* AMRWB_1425 */ + 0x05, /* AMRWB_1825 */ + 0x0f /* invalid */ +}; diff --git a/lib_com/modif_fs_fx.c b/lib_com/modif_fs_fx.c new file mode 100644 index 0000000..e092957 --- /dev/null +++ b/lib_com/modif_fs_fx.c @@ -0,0 +1,1297 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include +#include "rom_enc_fx.h" /* prototypes */ +#include "stl.h" + +#include "basop_util.h" + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + + + +/*==============================================================================*/ +/* FUNCTION : modify_Fs_fx ( ) */ +/*------------------------------------------------------------------------------*/ +/* PURPOSE : Modify sampling freq by interpolation */ +/*------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* const Word16 sigIn_fx[] signal to decimate Q_syn2-1 */ +/* const Word16 lg length of input */ +/* const Word16 fin frequency of input Q0 */ +/* const Word16 fout frequency of output Q0 */ +/*------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* Word16 sigOut_fx[] decimated signal Q_syn2-1 */ +/*------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Word16 mem_fx[] filter memory Q_syn2-1 */ +/*------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None. */ +/*------------------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*==============================================================================*/ +Word16 modify_Fs_fx( /* o : length of output Q0 */ + const Word16 sigIn_fx[], /* i : signal to decimate Q0 */ + Word16 lg, /* i : length of input Q0 */ + const Word32 fin, /* i : frequency of input Q0 */ + Word16 sigOut_fx[], /* o : decimated signal Q0 */ + const Word32 fout, /* i : frequency of output Q0 */ + Word16 mem_fx[] /* i/o: filter memory Q0 */ + ,const Word16 nblp /* i : flag indicating if NB low-pass is applied */ +) +{ + Word16 i; + + Word16 lg_out, fac_num, fac_den, filt_len, frac, temp_n, mem_len; + Word16 num_den; + Word16 datastep, fracstep; + Word16 *sigIn_ptr, *sigPtr; + Word16 signal_tab_fx[3*L_FILT_MAX + L_FRAME48k], *signal_fx, *signal_ana_fx; /* 3* as 2* for memory and 1* for future prediction */ + Word16 A_fx[M+1], r_fx_h[M+1], r_fx_l[M+1]; + Word16 mem_len_ana; + Word16 plus_sample_in; + Word16 j; + Word16 mu_preemph_fx; + Word16 mem_preemph_fx; + Word16 Q_r; + Word16 mem_lev_fx[18]; + Word32 t0, t1, t2, L_tmp; /* temporary variables */ + Word32 LepsP[M+1]; + Word16 flag_low_order = 0; + Word16 filt_len_tmp; + + const Resampling_cfg_fx *cfg_ptr_fx; + + /*-------------------------------------------------------------------* + * Find the resampling configuration + *-------------------------------------------------------------------*/ + + /* check if fin and fout are the same */ + IF (EQ_32(fin,fout)) + { + /* just copy the signal_fx and quit */ + Copy(sigIn_fx, sigOut_fx, lg); + + return lg; + } + ELSE + { + /* find the resampling configuration in the lookup table */ + cfg_ptr_fx = &resampling_cfg_tbl_fx[0]; + WHILE ( (cfg_ptr_fx->fin_fx != 0) && !(EQ_32(cfg_ptr_fx->fin_fx,fin)&&EQ_32(cfg_ptr_fx->fout_fx,fout))) + { + test(); + test(); + cfg_ptr_fx++; + } + + + /* find config with NB 4kHz low-pass */ + test(); + test(); + IF ( nblp && (GT_32(fin, 8000))&&(EQ_32(fout,12800))) + { + flag_low_order = 1; + move16(); + cfg_ptr_fx++; + WHILE ( (cfg_ptr_fx->fin_fx != 0) && !( (EQ_32(cfg_ptr_fx->fin_fx, fin))&&(EQ_32(cfg_ptr_fx->fout_fx,fout)))) + { + test(); + test(); + cfg_ptr_fx++; + } + } + + /*-------------------------------------------------------------------* + * Retrieve and/or calculate the resampling parameters + *-------------------------------------------------------------------*/ + fac_num = cfg_ptr_fx->fac_num_fx; + move16();/*Q0*/ + fac_den = cfg_ptr_fx->fac_den_fx; + move16(); + + IF(GE_16(lg,L_FRAME)) + { + lg_out = cfg_ptr_fx->lg_out ; + move16(); + } + ELSE + { + lg_out = idiv1616(i_mult2(lg, fac_num), fac_den); + } + filt_len = cfg_ptr_fx->filt_len_fx; + move16(); + plus_sample_in = 0; + move16();/*default, regular delay*/ + frac = 0; + move16(); + + test(); + IF ( (EQ_32(fin, 8000))&&(EQ_32(fout,12800))) + { + plus_sample_in = 7; + move16(); + frac = 4; + move16(); + } + + mem_len = shl(filt_len,1); + signal_fx = signal_tab_fx+2*L_FILT_MAX + sub(L_FRAME48k, add(mem_len, lg)); + signal_ana_fx = signal_fx; + mem_len_ana = mem_len; + move16(); + } + + + /*-------------------------------------------------------------------* + * Resample + *-------------------------------------------------------------------*/ + /* append filter memory */ + Copy(mem_fx, signal_fx, mem_len); + + sigPtr = signal_fx + mem_len; + Copy(sigIn_fx, sigPtr, lg); + + IF(plus_sample_in > 0) + { + autocorr_fx( signal_ana_fx+mem_len_ana+lg-LEN_WIN_SSS, 1, r_fx_h, r_fx_l, &Q_r, LEN_WIN_SSS, wind_sss_fx, 0, 0 ); + + + t1 = L_Comp(r_fx_h[1], r_fx_l[1]); /* R[1] in Q31 */ + t2 = L_abs(t1); /* abs R[1] */ + t0 = L_deposit_l(0); + IF (r_fx_h[0] != 0) + { + t0 = Div_32(t2, r_fx_h[0], r_fx_l[0]); /* R[1]/R[0] in Q31 */ + } + if (t1 < 0) + { + t0 = L_negate(t0); /* R[1]/R[0] */ + } + + + + mu_preemph_fx = extract_h(t0); /*r_fx[1] / r_fx[0]; */ + mem_preemph_fx = signal_ana_fx[mem_len_ana+lg-LEN_WIN_SSS - 1]; + move16(); + preemph_fx(signal_ana_fx+mem_len_ana+lg-LEN_WIN_SSS, mu_preemph_fx, LEN_WIN_SSS, &mem_preemph_fx); + + + /* Autocorrelations */ + autocorr_fx( signal_ana_fx+mem_len_ana+lg-LEN_WIN_SSS, M, r_fx_h, r_fx_l, &Q_r, + LEN_WIN_SSS, wind_sss_fx, 0, 0 ); + + /* Lag windowing */ + lag_wind( r_fx_h, r_fx_l, M, fin, LAGW_STRONG ); + + /* Levinson-Durbin */ + set16_fx(mem_lev_fx, 0, 18 ); + E_LPC_lev_dur(r_fx_h, r_fx_l, A_fx, LepsP, M, NULL); + + Copy_Scale_sig( A_fx, A_fx, M+1, sub(norm_s(A_fx[0]),2) ); + + FOR (i=0; ifilter_fx, frac, fac_num, filt_len_tmp )); + + frac = add(frac,fracstep); + + j = sub(fac_num, frac); + if (j < 0) + { + frac = sub(frac,fac_num); + } + sigIn_ptr += add(lshr(j, 15), datastep); + } + /* rescaling */ + test(); + IF ((GT_16(fac_num,fac_den))==((cfg_ptr_fx->flags_fx&RS_INV_FAC)!=0)) + { + IF(LT_16(fac_num, fac_den)) + { + num_den = div_s(fac_num,fac_den);/*Q15*/ + test(); + IF( GT_32(fin, 16000)&&EQ_16(lg_out,512)) + { + + FOR( i=0; iflags_fx&RS_INV_FAC)!=0)) + { + FOR( i=0; i Q(-QSR) */ + } + + /* length of the interpolated signal */ + /*lg_out = (short)(lg * fout / fin); */ + + /* cc[x][3]*s*s*s + cc[x][2]*s*s + cc[x][1]*s + cc[x][0]; indexes relatives of s : -1 0 1 2 */ + /* d : cc[x][0] = s[0] */ + /* b : cc[x][2] =(s[-1]+s[1])/2-s[0] */ + /* a : cc[x][3] = (s[-1]+s[2]-s[0]-s[1]-4*cc[x][2]) / 6 */ + /* c : cc[x][1] = s[1]-s[0]-cc[x][3]-cc[x][2] */ + + /* coef inits using memory (indexes < 0) */ + /* cc[2][] : indexes -2 -1 0 1 */ + cptr = &(cc[2][0]); + cptr[0] = mult_r(sigin_sr[-1], 10923); + move16(); /* sigIn[-1]/3 */ + cptr[2] = sub(shr(add(sigin_sr[-2], sigin_sr[0]), 1), sigin_sr[-1]); + move16(); /* (sigIn[-2]+sigIn[0])/2-sigIn[-1]; */ + cptr[3] = sub(mult_r(sub(add(sigin_sr[-2], sigin_sr[1]), add(sigin_sr[-1], sigin_sr[0])), 5461), mult_r(cptr[2],21845)); + move16(); /*(sigIn[-2]+sigIn[1]-sigIn[-1]-sigIn[0]) / 6 - 4/6*cc[2][2]);*/ + cptr[1] = sub(sub(sigin_sr[0], sigin_sr[-1]), add(cptr[3], cptr[2])); + move16(); + + /* cc[3][] : indexes -1 0 1 2 */ + cptr = &(cc[3][0]); + cptr[0] = mult_r(sigin_sr[0], 10923); + move16();/* sigIn[-1]/3 */ + cptr[2] = sub(shr(add(sigin_sr[-1], sigin_sr[1]), 1), sigin_sr[0]); + move16(); /* (sigIn[-1]+sigIn[1])/2-sigIn[0]; */ + cptr[3] = sub(mult_r(sub(add(sigin_sr[-1], sigin_sr[2]), add(sigin_sr[0], sigin_sr[1])), 5461), mult_r(cptr[2],21845)); + move16(); /*(sigIn[-2]+sigIn[1]-sigIn[-1]-sigIn[0]) / 6 - 4/6*cc[2][2]);*/ + cptr[1] = sub(sub(sigin_sr[1], sigin_sr[0]), add(cptr[3], cptr[2])); + move16(); + + sigOutptr = sigOut; + cind = -1; + move16(); + move16(); /* for the move */ + IF( EQ_32(fin, 12800)) + { + if( EQ_32(fout, 8000)) + { + cind = 0; + move16(); + } + if( EQ_32(fout, 16000)) + { + cind = 1; + move16(); + } + if( EQ_32(fout, 32000)) + { + cind = 2; + move16(); + } + if( EQ_32(fout, 48000)) + { + cind = 3; + move16(); + } + } + IF( EQ_32(fin, 16000)) + { + if( EQ_32(fout, 12800)) + { + cind = 4; + move16(); + } + if( EQ_32(fout, 32000)) + { + cind = 5; + move16(); + } + if( EQ_32(fout, 48000)) + { + cind = 6; + move16(); + } + + } + ctptr = &(ct2_fx[cind][0]); + lg_out = mult_r(shl(lg,2),ctptr[13]); + *delayout = ctptr[9]; + move16(); + + if( EQ_16(ctptr[12], 15)) + { + cu = cu15_fx; + move16();/*pointer*/ + } + + if( EQ_16(ctptr[12],4)) + { + cu = cu4_fx; + move16();/*pointer*/ + } + + k2d = sub(ctptr[12], 1); /* shift of index in cu with respect to the next sample (ex 1.25 -> 0.25 ) */ + fk1 = shl(k2d, 1); + k3d = sub(fk1, 1); /* to compurte index in cu with respect to the last sample with - sign (ex 1.25 -> -0.75 ) */ + + kk = 0; + move16(); + i = 0; + move16(); + + lim = sub(lg, ctptr[11]); + lim2 = sub(lg, 3); + lim3 = ctptr[10]; + move16(); + WHILE(LT_16(i, lim2)) + { + if(GE_16(i, lim)) + { + lim3 = sub(ctptr[11], 3); /* last, incomplete period*/ + } + *sigOutptr++ = sigIn[i]; + move16(); + FOR(k = 0; k < lim3; k++) + { + cptr = &(cc[kk][0]); + cptr[0] = mult_r(sigin_sr[i+1], 10923); + move16();/* sigIn[-1]/3 */ + cptr[2] = sub(shr(add(sigin_sr[i], sigin_sr[i+2]), 1), sigin_sr[i+1]); + move16(); /* (sigIn[-1]+sigIn[1])/2-sigIn[0]; */ + cptr[3] = sub(mult_r(sub(add(sigin_sr[i], sigin_sr[i+3]), add(sigin_sr[i+1], sigin_sr[i+2])), 5461), mult_r(cptr[2],21845)); + move16(); /*(sigIn[-1]+sigIn[1]-sigIn[0]-sigIn[1]) / 6 - 4/6*cc[3][2]);*/ + cptr[1] = sub(sub(sigin_sr[i+2], sigin_sr[i+1]), add(cptr[3], cptr[2])); + move16(); + i = add(i,1); + + i2 = sub(kk, 2); + i1 = sub(kk, 1); + if( i1 < 0 ) + { + i1 = add(i1, 4); + } + + if( i2 < 0 ) + { + i2 = add(i2, 4); + } + inc = ctptr[8]; + move16(); + FOR(k1 = ctptr[k]; k1 < fk1; k1 += inc) + { + k2 = sub(k1, k2d); + k3 = sub(k3d, k1); + cptr = &(cc[i2][0]); + uptr = &(cu[k1][0]); + vv32 = L_mult( 8192, *cptr++); + vv32 = L_mac(vv32, *uptr++, *cptr++); + vv32 = L_mac(vv32, *uptr++, *cptr++); + vv32 = L_mac(vv32, *uptr++, *cptr++); /* Q13*Q(-QSR) -> Q(13-QSR+1) 32 bits*/ + cptr = &(cc[i1][0]); + uptr = &(cu[k2][0]); + vv32 = L_mac(vv32, 8192, *cptr++); + vv32 = L_mac(vv32, *uptr++, *cptr++); + vv32 = L_mac(vv32, *uptr++, *cptr++); + vv32 = L_mac(vv32, *uptr++, *cptr++); + cptr = &(cc[kk][0]); + uptr = &(cu[k3][0]); + vv32 = L_mac(vv32, 8192, *cptr++); + vv32 = L_msu(vv32, *uptr++, *cptr++); + vv32 = L_mac(vv32, *uptr++, *cptr++); + vv32 = L_msu(vv32, *uptr++, *cptr++); + vv32 = L_shl(vv32, (QSR+2)); /* Q(13-QSR+1) -> Q16 */ + *sigOutptr++ = round_fx(vv32); /* Q16 -> Q0*/ + } + + kk = add(kk, 1); + if( EQ_16(kk, 4)) + { + kk = 0; + move16(); + } + } + } + + + kk = sub(kk, 1); + if( kk < 0 ) + { + kk = 3; + move16(); + } + + if( EQ_16(ctptr[10], 1)) + { + *sigOutptr++ = sigIn[i]; + move16(); + } + + FOR(k1 = ctptr[k]; k1 < fk1; k1 += inc) + { + k2 = sub(k1, k2d); + + cptr = &(cc[kk][0]); + uptr = &(cu[k2][0]); + vv32 = L_mult( 8192, *cptr++); + vv32 = L_mac(vv32, *uptr++, *cptr++); + vv32 = L_mac(vv32, *uptr++, *cptr++); + vv32 = L_mac(vv32, *uptr++, *cptr++); /* Q13*Q(-QSR) -> Q(13-QSR+1) 32 bits*/ + vv32 = L_shl(vv32, (QSR+2)); /* Q(13-QSR+1) -> Q16 */ + *sigOutptr++ = i_mult(round_fx(vv32), 3); + move16();/* Q16 -> Q0*/ + } + + if( LT_16(ctptr[10], 3)) + { + *sigOutptr++ = sigIn[add(i, 1)]; + move16(); + } + + FOR( k1 = ctptr[add(k, 1)]; k1 < fk1; k1 += inc ) + { + cptr = &(cc[kk][0]); + uptr = &(cu[k1][0]); + vv32 = L_mult( 8192, *cptr++); + vv32 = L_mac(vv32, *uptr++, *cptr++); + vv32 = L_mac(vv32, *uptr++, *cptr++); + vv32 = L_mac(vv32, *uptr++, *cptr++); /* Q13*Q(-QSR) -> Q(13-QSR+1) 32 bits*/ + vv32 = L_shl(vv32, (QSR+2)); /* Q(13-QSR+1) -> Q16 */ + *sigOutptr++ = i_mult(round_fx(vv32), 3); + move16();/* Q16 -> Q0*/ + } + + if( EQ_16(ctptr[10], 1)) + { + *sigOutptr = sigIn[add(i, 2)]; + move16(); + } + } + + free(sigin_sr_tab); + + return lg_out; +} + +/*====================================================================*/ +/* FUNCTION : Decimate_allpass_steep_fx1 () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : decimation by a factor 2 */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (const Word16 *) in_fx : input speech, Q0 */ +/* _ (Word16 []) state_fx: Stateinfo, Q0 */ +/* Size: 2*ALLPASSSECTIONS_STEEP+1 */ +/* _ (Word16) N: Number of Input samples */ +/* _ (Word16 []) out_fx :Output arry of size N/2 Q0 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 []) out_fx : output-signal, Q0 */ +/* _ (Word16 []) state_fx:gets updated, Q0 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*===================================================================*/ + + +void Decimate_allpass_steep_fx( const Word16 *in_fx, + Word16 state_fx[], /* array of size: 2*ALLPASSSECTIONS_STEEP+1 */ + Word16 N, /* number of input samples */ + Word16 out_fx[]) /* array of size N/2 */ +{ + + Word16 k; + Word16 temp[ ALLPASSSECTIONS_STEEP ]; + Word32 Lacc, Lacc1; + Word16 temp1, temp2; + Word16 sum = 0; + move16(); + + /*upper allpass filter chain */ + + + FOR ( k = 0; k < N/2; k++ ) + { + + Lacc = L_deposit_h( state_fx[0] ); /* Q(16+x) */ + Lacc = L_mac( Lacc, AP1_STEEP_FX[0], in_fx[2*k] ); /* Q(16+x) */ + Lacc1 = L_deposit_h( in_fx[2*k] ); /* Q16+Qx */ + temp1 = extract_h( Lacc ); /* Qx */ + Lacc1 = L_msu( Lacc1, AP1_STEEP_FX[0], temp1 ); /* Q16+Qx */ + + state_fx[0] = extract_h( Lacc1 ); /* Qx */ + temp[0] = temp1; + move16(); + + Lacc1 = L_deposit_h( state_fx[1] ); /* Q16+Qx */ + Lacc1 = ( L_mac( Lacc1, AP1_STEEP_FX[1], temp1 )); /* Q16+Qx */ + + temp2 = extract_h( Lacc1 ); /* Qx */ + Lacc = L_msu( Lacc, AP1_STEEP_FX[1], temp2 ); /* Q16+Qx */ + state_fx[1] = extract_h(Lacc); /* Qx */ + temp[1] = temp2; + move16(); + + + Lacc = L_deposit_h( state_fx[ ALLPASSSECTIONS_STEEP-1 ] ); /* Q(16+x) */ + out_fx[ k ] = extract_h( L_mac( Lacc, AP1_STEEP_FX[ ALLPASSSECTIONS_STEEP-1 ], temp2 )); /* Qx format */ + state_fx[ ALLPASSSECTIONS_STEEP-1 ] = extract_h( L_msu ( Lacc1, AP1_STEEP_FX[ ALLPASSSECTIONS_STEEP-1 ], out_fx[k] )); /* Qx */ + + } + + /* lower allpass filter chain */ + + Lacc = L_deposit_h( state_fx[ ALLPASSSECTIONS_STEEP ] ); /* Q(16+x) */ + Lacc = L_mac( Lacc, AP2_STEEP_FX[0], state_fx[2*ALLPASSSECTIONS_STEEP] ); /*Q(16+x) */ + Lacc1 = L_deposit_h( state_fx[2*ALLPASSSECTIONS_STEEP] ); /* Q(16+x) */ + temp1 = extract_h( Lacc ); /* Qx */ + Lacc1 = L_msu( Lacc1, AP2_STEEP_FX[0], temp1 ); /* Q(16+x) */ + + state_fx[ ALLPASSSECTIONS_STEEP ] = extract_h( Lacc1 ); + temp[0] = temp1; + move16(); + + Lacc1 = L_deposit_h( state_fx[ ALLPASSSECTIONS_STEEP+1 ] ); /* Q(16+x) */ + Lacc1 = L_mac( Lacc1, AP2_STEEP_FX[1], temp1 ); /* Q(16+x) */ + temp2 = extract_h( Lacc1 ); /* Qx */ + temp[1] = temp2; + move16(); + Lacc = L_msu( Lacc, AP2_STEEP_FX[1], temp2 ); /* Q(16+x) */ + state_fx[ALLPASSSECTIONS_STEEP+1] = extract_h( Lacc ); /* Qx */ + + + Lacc = L_deposit_h( state_fx[2*ALLPASSSECTIONS_STEEP-1] ); /* Q(16+x) */ + Lacc = L_mac( Lacc, AP2_STEEP_FX[ALLPASSSECTIONS_STEEP-1], temp2 ); /* Q(16+x) temp[ALLPASSSECTIONS_STEEP-1] */ + temp[2] = extract_h( Lacc ); /* temp[2] in Qx */ + Lacc1 = L_msu( Lacc1, AP2_STEEP_FX[ALLPASSSECTIONS_STEEP-1], temp[2] ); /* Q(16+x) */ + state_fx[ 2*ALLPASSSECTIONS_STEEP-1 ] = extract_h( Lacc1 ); /* Qx */ + + sum = mult_r( out_fx[0], 16384 ); /* Qx */ + out_fx[0] = add( sum, mult_r(temp[ALLPASSSECTIONS_STEEP-1], 16384 )); /* Qx */ move16(); + + + FOR ( k = 1; k < N/2; k++) + { + + + Lacc = L_deposit_h( state_fx[ ALLPASSSECTIONS_STEEP ] ); /* Q(16+x) */ + Lacc = L_mac(Lacc, AP2_STEEP_FX[0], in_fx[2*k-1] ); /* Q(16+x):temp[0] */ + Lacc1 = L_deposit_h( in_fx[ 2*k-1 ] ); /* Q(16+x) */ + temp1 = extract_h( Lacc ); /* Qx */ + Lacc1 = L_msu( Lacc1, AP2_STEEP_FX[0], temp1 ); /* Q(16+x) */ + + state_fx[ALLPASSSECTIONS_STEEP] = extract_h( Lacc1 ); /* Qx */ + temp[0] = temp1; + move16(); + + + Lacc1 = L_deposit_h( state_fx[ ALLPASSSECTIONS_STEEP+1 ] ); /* Q(16+x) */ + Lacc1 = L_mac(Lacc1,AP2_STEEP_FX[1],temp1); /* Q(16+x) */ + temp2 = extract_h( Lacc1 ); /* Qx */ + temp[1] = temp2; + move16(); + Lacc = L_msu(Lacc,AP2_STEEP_FX[1],temp2); /* Q(16+x) */ + state_fx[ALLPASSSECTIONS_STEEP+1]= extract_h(Lacc); /* Qx */ + + + Lacc = L_deposit_h( state_fx[2*ALLPASSSECTIONS_STEEP-1] ); /* Q(16+x) */ + Lacc = L_mac( Lacc, AP2_STEEP_FX[ALLPASSSECTIONS_STEEP-1], temp[1] ); /* Q(16+x) temp[ALLPASSSECTIONS_STEEP-1] */ + temp[2] = extract_h( Lacc ); /*temp[2] in Qx */ + Lacc1 = L_msu( Lacc1, AP2_STEEP_FX[ALLPASSSECTIONS_STEEP-1], temp[2] ); /* Q(16+x) */ + state_fx[2*ALLPASSSECTIONS_STEEP-1] = extract_h( Lacc1 ); /* Qx */ + + + + sum = mult_r( out_fx[k], 16384 ); /* Qx */ + out_fx[k] = add( sum, mult_r( temp[ALLPASSSECTIONS_STEEP-1], 16384 ) ); + move16(); /* Qx */ + + } + + /* z^(-1) */ + + state_fx[ 2*ALLPASSSECTIONS_STEEP ] = in_fx[ N-1 ]; + move16(); /* Qx */ + +} + + + +void Interpolate_allpass_steep_fx(const Word16 *in_fx, + Word16 state_fx[], /* array of size: 2*ALLPASSSECTIONS_STEEP+1 */ + Word16 N, /* number of input samples */ + Word16 out_fx[]) /* array of size 2*N */ + + +{ + + Word16 k; + Word32 Lacc=0, Lacc1=0; + Word16 temp1, temp2; + + /*** State in Q0,in_fx Q0, AP1_STEEP in Q15 AP2_STEEP in Q15 OP in Q0 ************/ + /*upper allpass filter chain */ + + FOR (k=0; k 0); + + mem_fx_11 = mem_fx[11]; + move16(); + mem_fx_7 = mem_fx[7]; + move16(); + mem_fx_3 = mem_fx[3]; + move16(); + FOR (i = 0; i < loop_len; i++ ) + { + /* Lower branch */ + /*Vl0 = mem[8] + filt_coeff[6] * (*in - mem[9]); + Vl1 = mem[9] + filt_coeff[7] * (Vl0 - mem[10]); + mem[11] = mem[10] + filt_coeff[8] * (Vl1 - mem[11]); */ + tmp = mult_r(filt_coeff_fx[6], sub(*in++, mem_fx[9])); + if (i == 0) + { + Vl0 = add(mem_fx[8] , tmp); + } + if (i != 0) + { + Vl0 = add(*(in-4) , tmp); + } + Vl1 = add(mem_fx[9] , mult_r(filt_coeff_fx[7], sub(Vl0, mem_fx[10]))); + mem_fx_11 = add(mem_fx[10], mult_r(filt_coeff_fx[8], sub(Vl1, mem_fx_11))); + + /* mem[8] = *in++; + mem[9] = Vl0; + mem[10] = Vl1; + *out1 = mem[11]; */ + + mem_fx[9] = Vl0; + move16(); + mem_fx[10] = Vl1; + move16(); + + /* Middle branch */ + /* Vm0 = mem[4] + filt_coeff[3] * (*in - mem[5]); + Vm1 = mem[5] + filt_coeff[4] * (Vm0-mem[6]); + mem[7] = mem[6] + filt_coeff[5] * (Vm1-mem[7]); */ + tmp = mult_r(filt_coeff_fx[3], sub(*in++, mem_fx[5])); + if (i == 0) + { + Vm0 = add(mem_fx[4] , tmp); + } + if (i != 0) + { + Vm0 = add(*(in-4), tmp); + } + Vm1 = add(mem_fx[5] , mult_r(filt_coeff_fx[4], sub(Vm0, mem_fx[6]))); + mem_fx_7 = add(mem_fx[6], mult_r(filt_coeff_fx[5], sub(Vm1, mem_fx_7))); + + mem_fx[5] = Vm0; + move16(); + mem_fx[6] = Vm1; + move16(); + out = add(mem_fx_11, mem_fx_7); + + /* Upper branch */ + /* Vu0 = mem[0] + filt_coeff[0] * ( *in - mem[1] ); + Vu1 = mem[1] + filt_coeff[1] * ( Vu0 - mem[2] ); + mem[3] = mem[2] + filt_coeff[2] * ( Vu1 - mem[3] ); */ + tmp = mult_r(filt_coeff_fx[0], sub(*in++, mem_fx[1])); + if (i == 0) + { + Vu0 = add(mem_fx[0] , tmp); + } + if (i != 0) + { + Vu0 = add(*(in-4), tmp); + } + Vu1 = add(mem_fx[1] , mult_r(filt_coeff_fx[1], sub(Vu0, mem_fx[2]))); + mem_fx_3 = add(mem_fx[2] , mult_r(filt_coeff_fx[2], sub(Vu1, mem_fx_3))); + + mem_fx[1] = Vu0; + move16(); + mem_fx[2] = Vu1; + move16(); + *out1++ = add(out, mem_fx_3); + move16(); + } + mem_fx[8] = *(in-3); + move16(); + mem_fx[4] = *(in-2); + move16(); + mem_fx[0] = *(in-1); + move16(); + mem_fx[11] = mem_fx_11; + move16(); + mem_fx[7] = mem_fx_7; + move16(); + mem_fx[3] = mem_fx_3; + move16(); + + Scale_sig(mem_fx, 12, negate(sc)); + Scale_sig(out_fx, loop_len, negate(sc)); + Scale_sig(lp_mem_fx, 6, negate(sc)); + return; +} + + +/*-------------------------------------------------------------------* + * retro_interp4_5_fx() + * + * + *-------------------------------------------------------------------*/ + +void retro_interp4_5_fx( + const Word16 *syn_fx, + Word16 *pst_old_syn_fx +) +{ + Word16 *pf5, *pf4; + Word16 c; + + /* resample st->pst_old_syn in a reverse way to preserve time-alignment */ + pf4 = (Word16*) &pst_old_syn_fx[58]; + pf5 = (Word16*) pst_old_syn_fx; + FOR (c=0; c<57; c++) + { + *pf5++ = pf4[0]; + move16(); + /* *pf5++ = 0.2f * pf4[0] + 0.8f * pf4[1]; */ + *pf5++ = mac_r(L_mult(6554, pf4[0]), 26214, pf4[1]); + move16(); + /* *pf5++ = 0.4f * pf4[1] + 0.6f * pf4[2]; */ + *pf5++ = mac_r(L_mult(13107, pf4[1]), 19661, pf4[2]); + move16(); + /* *pf5++ = 0.6f * pf4[2] + 0.4f * pf4[3]; */ + *pf5++ = mac_r(L_mult(19661, pf4[2]), 13107, pf4[3]); + move16(); + /* *pf5++ = 0.8f * pf4[3] + 0.2f * pf4[4]; */ + *pf5++ = mac_r(L_mult(26214, pf4[3]), 6554, pf4[4]); + move16(); + pf4+=4; + } + *pf5++ = pf4[0]; + move16(); + /* *pf5++ = 0.2f * pf4[0] + 0.8f * pf4[1]; */ + *pf5++ = mac_r(L_mult(6554, pf4[0]), 26214, pf4[1]); + move16(); + /* *pf5++ = 0.4f * pf4[1] + 0.6f * pf4[2]; */ + *pf5++ = mac_r(L_mult(13107, pf4[1]), 19661, pf4[2]); + move16(); + /* *pf5++ = 0.6f * pf4[2] + 0.4f * pf4[3]; */ + *pf5++ = mac_r(L_mult(19661, pf4[2]), 13107, pf4[3]); + move16(); + /* *pf5++ = 0.8f * pf4[3] + 0.2f * syn[0]; */ + *pf5++ = mac_r(L_mult(26214, pf4[3]), 6554, syn_fx[0]); + move16(); + /* all samples processed: NBPSF_PIT_MAX = 290 = (58*5) */ + + return; +} + + +/*-------------------------------------------------------------------* + * retro_interp5_4_fx() + * + * + *-------------------------------------------------------------------*/ + +void retro_interp5_4_fx( Word16 *pst_old_syn_fx ) +{ + Word16 *pf5, *pf4; + Word16 c; + + /* resample st->pst_old_syn in a reverse way to preserve time-alignment */ + pf4 = (Word16*) &pst_old_syn_fx[NBPSF_PIT_MAX-1]; + pf5 = pf4; + FOR (c=0; c<58; c++) + { + /* *pf4-- = 0.75f * pf5[0] + 0.25f * pf5[-1]; */ + *pf4-- = mac_r(L_mult(24576, pf5[0]), 8192, pf5[-1]); + move16(); + /* *pf4-- = 0.50f * pf5[-1] + 0.50f * pf5[-2]; */ + *pf4-- = mac_r(L_mult(16384, pf5[-1]), 16384, pf5[-2]); + move16(); + /* *pf4-- = 0.25f * pf5[-2] + 0.75f * pf5[-3]; */ + *pf4-- = mac_r(L_mult(8192, pf5[-2]), 24576, pf5[-3]); + move16(); + *pf4-- = pf5[-4]; + move16(); + pf5-=5; + } + /* all samples processed: NBPSF_PIT_MAX = 290 = (58*5) */ + + return; +} + diff --git a/lib_com/mslvq_com_fx.c b/lib_com/mslvq_com_fx.c new file mode 100644 index 0000000..473d67a --- /dev/null +++ b/lib_com/mslvq_com_fx.c @@ -0,0 +1,850 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "cnst_fx.h" +#include "stl.h" + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + +static void make_offset_scale_fx( Word16 j, const Word32 tab_no_cv[], const Word16 no_ld[], + Word16 no_scl, Word32 offset_scale[][MAX_NO_SCALES+1]); +static void init_offset_fx( Word32 offset_scale1[][MAX_NO_SCALES+1], Word32 offset_scale2[][MAX_NO_SCALES+1], + Word32 offset_scale1_p[][MAX_NO_SCALES+1], Word32 offset_scale2_p[][MAX_NO_SCALES+1], + Word16 no_scales[][2], Word16 no_scales_p[][2]); +static void decode_comb_fx(Word32 index,Word16 *cv,Word16 idx_lead); +static void decode_sign_pc1_fx( Word16 *c, Word16 idx_sign, Word16 parity ); +static void put_value_fx(Word16 *cv, Word16 *p, Word16 val, Word16 dim, Word16 no_new_val); +static void decode_leaders_fx(Word16 index, Word16 idx_lead, Word16 *cv ); +static void idx2c_fx(Word16 n, Word16 *p, Word16 k, Word16 val ); +static void divide_64_32_fx(Word16 *xs,Word32 y, Word32 *result, Word32 *rem); +static Word16 +decode_indexes_fx(Word16 * index,Word16 no_bits,const Word16 * p_scales, Word16 * p_no_scales, + Word32 * p_offset_scale1, Word32 * p_offset_scale2,Word16 * x_lvq,Word16 mode_glb, Word16 *scales); +static Word32 divide_32_32_fx(Word32 y, Word32 x, Word32 * rem); +static Word16 divide_16_16_fx(Word16 y, Word16 x, Word16 *rem); + +/* used in CNG-LP coding */ +void permute_fx( + Word16 *pTmp1, /* i/o: vector whose components are to be permuted */ + const Word16 *perm /* i : permutation info (indexes that should be interchanged), max two perms */ +) +{ + Word16 p1, p2; + Word16 tmp; + + p1 = perm[0]; + move16(); + p2 = perm[1]; + move16(); + tmp = pTmp1[p1]; + move16(); + pTmp1[p1] = pTmp1[p2]; + move16(); + move16(); + pTmp1[p2] = tmp; + move16(); + p1 = perm[2]; + move16(); + + IF ( GT_16(p1, -1) ) + { + p2 = perm[3]; + move16(); + tmp = pTmp1[p1]; + move16(); + pTmp1[p1] = pTmp1[p2]; + move16(); + move16(); + pTmp1[p2] = tmp; + move16(); + } + + return; +} + + +void init_lvq_fx( + Word32 offset_scale1[][MAX_NO_SCALES+1], /* o: lattice truncation index offset for the first LSF subvector - safety net structures*/ + Word32 offset_scale2[][MAX_NO_SCALES+1], /* o: lattice truncation index offset for the second LSF subvector - safety net structures*/ + Word32 offset_scale1_p[][MAX_NO_SCALES+1], /* o: lattice truncation index offset for the first LSF subvector - predictive structures*/ + Word32 offset_scale2_p[][MAX_NO_SCALES+1], /* o: lattice truncation index offset for the second LSF subvector - predictive structures*/ + Word16 no_scales[][2], /* o: number of truncations for each LSF subvector at each MSLVQ structure - safety net */ + Word16 no_scales_p[][2] /* o: number of truncations for each LSF subvector at each MSLVQ structure - predictive */ +) +{ + Word16 i, j; + /* safety-net mode */ + FOR(i=0; i0)) + { + j++; + } + no_scales[i][0] = j; + move16(); + j = MAX_NO_SCALES; + move16(); + test(); + WHILE ((LT_16(j,shl(MAX_NO_SCALES,1)))&&(no_lead_fx[i][j]>0)) + { + j++; + } + no_scales[i][1] = sub(j, MAX_NO_SCALES); + move16(); + } + /* predictive mode */ + FOR(i=0; i0)) + { + j++; + } + no_scales_p[i][0] = j; + move16(); + j = MAX_NO_SCALES; + move16(); + WHILE ((LT_16(j, shl(MAX_NO_SCALES,1)))&&(no_lead_p_fx[i][j]>0)) + { + j++; + } + no_scales_p[i][1] = sub(j,MAX_NO_SCALES); + move16(); + } + /* index offsets for each truncation */ + init_offset_fx( offset_scale1, offset_scale2, offset_scale1_p, offset_scale2_p, no_scales, no_scales_p ); +} + +/* make_offset_scale_fx() - calculates scale offset values for a particular MSLVQ structure */ +static +void make_offset_scale_fx( + Word16 j, /* i: MSLVQ structure index */ + const Word32 tab_no_cv[], /* i: cummulated number of codevectors in each leader class */ + const Word16 no_ld[], /* i: number of leaders in each truncation for the MSLVQ structure j*/ + Word16 no_scl, /* i: number of truncations in the MSLVQ structure j */ + Word32 offset_scale[][MAX_NO_SCALES+1]/* o: offset values */ +) +{ + Word16 i; + + offset_scale[j][0] = L_deposit_l(1); + FOR( i=1; i<=no_scl; i++ ) + { + offset_scale[j][i] = L_add(offset_scale[j][sub(i,1)], tab_no_cv[no_ld[sub(i,1)]]); + move32(); + } + + return; +} + +void init_offset_fx( + Word32 offset_scale1[][MAX_NO_SCALES+1], /* o: lattice truncation index offset for the first LSF subvector - safety net structures*/ + Word32 offset_scale2[][MAX_NO_SCALES+1], /* o: lattice truncation index offset for the second LSF subvector - safety net structures*/ + Word32 offset_scale1_p[][MAX_NO_SCALES+1],/* o: lattice truncation index offset for the first LSF subvector - predictive structures*/ + Word32 offset_scale2_p[][MAX_NO_SCALES+1],/* o: lattice truncation index offset for the second LSF subvector - predictive structures*/ + Word16 no_scales[][2], /* i: number of truncations for each LSF subvector at each MSLVQ structure - safety net */ + Word16 no_scales_p[][2] /* i: number of truncations for each LSF subvector at each MSLVQ structure - predictive */ +) +{ + Word16 j; + /* safety-net */ + FOR( j=0; j 0 ) + { + divide_64_32_fx( index, p_offset_scale2[tmp+ p_no_scales[add(shl(mode_glb,1),1)]], &index1, &index2 ); + } + ELSE + { + index1 = L_deposit_l(index[0]); /* this is for very low bitrates, so there is no loss in truncation */ + index2 = L_deposit_l(0); + } + IF ( index1 == 0 ) + { + FOR( i=0; i 0) + { + /*if (idx_sign % 2) */ + IF(s_and(idx_sign,1)) + { + c[i] = negate(c[i]); + move16(); + cnt_neg = negate(cnt_neg); + move16(); + } + idx_sign = shr(idx_sign,1); /* >>= 1; */ + } + } + + IF ( LT_16(len, LATTICE_DIM)) + { + IF (NE_16(cnt_neg, parity)) + { + c[len] = negate(c[len]); + move16(); + } + } + + return; +} + + +static void decode_leaders_fx( + Word16 index, /* i : index to be decoded */ + Word16 idx_lead, /* i : leader class index */ + Word16 *cv /* o : decoded codevector Q1*/ +) +{ + Word16 i, no_vals_loc, no_vals_last, p[LATTICE_DIM], dim_loc, n_crt; + Word16 index1; + Word16 val_crt; + + no_vals_loc = no_vals_fx[idx_lead]; + move16(); + val_crt = vals_fx[idx_lead][no_vals_loc-1]; + move16(); /*Q1 */ + no_vals_last = no_vals_ind_fx[idx_lead][no_vals_loc-1]; + move16(); + + FOR( i=0; i= 0) + { + result = L_add(result,1); + t = L_add(L_tmp, 0); + } + } + *rem = t; + move32(); + } + return result; +} + +/* divide_32_32_fx() :Division reminder for Word16 - rem is the reminder of the division between y and x. */ +static Word16 divide_16_16_fx(Word16 y, /* i */ + Word16 x, /* i */ + Word16 *rem /* o */ + ) +{ + Word16 result, t, tmp; + Word16 i, ny, nx, nyx; + + + IF (LT_32(y, x)) + { + result = 0; + move16(); + *rem = y; + move16(); + } + ELSE + { + + result = 0; + move16(); + IF (y==0) + { + ny = 0; + move16(); + } + ELSE + { + ny = sub(15, norm_s(y)); + } + IF (x==0) + { + nx = 0; + move16(); + } + ELSE + { + nx = sub(15, norm_s(x)); + } + + nyx = sub(ny,nx); + + t = s_and(shr(y, add(nyx,1)),sub(shl(1,sub(nx,1)),1)); + FOR(i=0; i<=nyx; i++) + { + t = add(shl(t,1), s_and(shr(y,sub(nyx,i)),1)); /* L_and(y,L_shl(1, sub(nyx,i)))); */ + result = shl(result,1); + tmp = sub(t,x); + IF(tmp >= 0) + { + result = add(result,1); + t = tmp; + move16(); + } + } + *rem = t; + move16(); + } + return result; +} + +static void divide_64_32_fx( + Word16 *xs, /* i : denominator as array of two int32 */ + Word32 y, /* i : nominator on 32 bits */ + Word32 *result, /* o : integer division result on 32 bits */ + Word32 *rem /* o : integer division reminder on 32 bits */ +) +{ + Word16 nb_x1; + Word32 r, x_tmp, x[2], q, q1; + + x[0] = L_add(L_add(L_shl(L_deposit_l(s_and(xs[2],1)),2*LEN_INDICE),L_shl(L_deposit_l(xs[1]), LEN_INDICE)),L_deposit_l(xs[0])); + move32(); + x[1] = L_shr(L_deposit_l(xs[2]),1); + move32(); + + /*x[0] = (((xs[2])&(1)<<(LEN_INDICE*2)) + (xs[1]<>1; */ + + IF (x[1] ==0) + { + nb_x1 = 0; + move16(); + } + ELSE + { + nb_x1 = sub(31, norm_l(x[1])); /*get_no_bits_fx(x[1]); */ + } + /* take the first 31 bits */ + IF ( nb_x1 > 0 ) + { + x_tmp = L_add(L_shl(x[1],sub(31,nb_x1)),L_shr(x[0], nb_x1)); + /* x_tmp = (x[1]<<(32-nb_x1)) + (x[0]>>nb_x1); */ + + q = divide_32_32_fx(x_tmp,y, &r); /* q = x_tmp/y, reminder r */ + r = L_add(L_shl(r, nb_x1), L_and(x[0],L_deposit_l(sub(shl(1,nb_x1),1)))); /* this is the first reminder */ + /* r = (r<Q27 */ + L_tmp = L_shr_r(L_tmp,11); /* Q16 */ + frac = L_Extract_lc(L_tmp,&exp); + frac = extract_l(Pow2(14,frac)); + G[i*5+k] = round_fx(L_shl(L_mult(frac,UVG2CB1[iG2[i]][k]),exp-sc)); /* Q0 */ + } + ELSE IF (EQ_16(i,1)) + { + L_tmp = L_mult(UVG1CB[iG1][i],27213); /* Q(13+13+1)->Q27 */ + L_tmp = L_shr_r(L_tmp,11); /* Q16 */ + frac = L_Extract_lc(L_tmp,&exp); + frac = extract_l(Pow2(14,frac)); + G[i*5+k] = round_fx(L_shl(L_mult(frac,UVG2CB2[iG2[i]][k]),exp-sc)); /* Q0 */ + } + } + } + return Q_gain; +} + +/*===================================================================*/ +/* FUNCTION : generate_nelp_excitation_fx */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : This function computes the random + excitation scaled by gain */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ + +/* _ (Word16*) Gains : Gain vector (Q_exc) */ +/* _ (Word16) gain_fac : gain factor (Q14) */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) seed : Random seed (Q0) */ +/* _ (Word16*) output : excitation output (Q_exc) */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None. */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None. */ +/*===================================================================*/ +void generate_nelp_excitation_fx( + Word16 *seed, /* i/o: random number seed */ + Word16 *Gains, /* i : excitation gains Q_exc*/ + Word16 *output, /* o : excitation output */ + Word16 gain_fac /* i : gain factor */ +) +{ + Word16 i, len, j; + Word16 tmp[31], tmp1[31], tmpf, L16; + Word16 k1, k2, I[31], tmpi; + Word32 L32; + Word16 cnt; + + FOR (i=0; i<10; i++) + { + IF (EQ_16(i,9)) + { + len=31; + move16(); + cnt=8; + move16(); + } + ELSE + { + len=25; + move16(); + cnt=6; + move16(); + } + + FOR (j=0; j +#include "prot_fx.h" + +/********************************/ +/* Helper functions */ +/********************************/ + +/** Put nBits long encoded value from *pStream into bitstream. Using the function EncodeValue for encoding. */ +static Word16 PutIntoBitstream(Word16 const ** pStream, TEncodeValue EncodeValue, Word16 index, Encoder_State_fx *st_fx, Word16 nBits) +{ + Word16 value; + Word16 codedValue; + + move16(); + value = *(*pStream)++; + codedValue = EncodeValue(value, index); + + push_next_indice_fx(st_fx, codedValue, nBits); + + return value; +} + + +/** Get nBits long value from bitstream into *pStream. */ +static Word16 GetFromBitstream(Decoder_State_fx *st, TDecodeValue DecodeValue, Word16 index, Word16 nFixedBits, Word16 ** pStream) +{ + Word16 value; + + move16(); + move16(); + value = 0; + + IF (DecodeValue != NULL) + { + DecodeValue(st, index, &value); + } + ELSE + { + value = get_next_indice_fx(st, nFixedBits); + } + move16(); + *(*pStream)++ = value; + + return value; +} + +static Word16 FixedWidthEncoding(Word16 value, Word16 index) +{ + (void)index; + return value; +} + +/********************************/ +/* Interface functions */ +/********************************/ + +void GetParameters(ParamsBitMap const * paramsBitMap, Word16 nArrayLength, void const * pParameter, Word16 ** pStream, Word16 * pnSize, Word16 * pnBits) +{ + Word16 index; + Word16 iParam, nParams; + Word16 value; + void const * pSubStruct; + + + assert((paramsBitMap != NULL) && (nArrayLength > 0) && (pParameter != NULL) && (pStream != NULL) && (pnSize != NULL) && (pnBits != NULL)); + + move16(); + nParams = paramsBitMap->nParams; + + FOR (index = 0; index < nArrayLength; index++) + { + + FOR (iParam = 0; iParam < nParams; iParam++) + { + ParamBitMap const * param; + + move16(); + param = & paramsBitMap->params[iParam]; + + pSubStruct = param->GetParamValue(pParameter, index, &value); + /* If a function for encoding/decoding value is defined than it should take care of 0 */ + IF ( s_or(param->fZeroAllowed != 0, param->EncodeValue != NULL) ) + { + move16(); + *(*pStream)++ = value; + } + ELSE + { + move16(); + *(*pStream)++ = sub(value, 1); + } + + move16(); + *pnSize = add(*pnSize, 1); + + IF (param->nBits != 0) + { + move16(); + *pnBits = add(*pnBits, param->nBits); + } + ELSE + { + move16(); + *pnBits = add(*pnBits, param->GetNumberOfBits(value, index)); + } + + IF ( s_and(param->pSubParamBitMap != NULL, value > 0) ) + { + const void *pointer; + + move16(); + pointer = pParameter; + if (pSubStruct != NULL) + { + move16(); + pointer = pSubStruct; + } + GetParameters(param->pSubParamBitMap, value, pointer, pStream, pnSize, pnBits); + } + } + } + +} + +void SetParameters(ParamsBitMap const * paramsBitMap, Word16 nArrayLength, void * pParameter, Word16 const ** pStream, Word16 * pnSize) +{ + Word16 index; + Word16 iParam, nParams; + Word16 value; + void * pSubStruct; + void * pTmp; + assert((paramsBitMap != NULL) && (nArrayLength > 0) && (pParameter != NULL) && (pStream != NULL) && (pnSize != NULL)); + nParams = paramsBitMap->nParams; + + FOR (index = 0; index < nArrayLength; index++) + { + FOR (iParam = 0; iParam < nParams; iParam++) + { + ParamBitMap const *param; + /* If a function for encoding/decoding value is defined than it should take care of 0 */ + + move16(); + param = ¶msBitMap->params[iParam]; + + move16(); + value = 1; + if ( s_or(param->fZeroAllowed!=0, param->EncodeValue != NULL) ) + { + move16(); + value = 0; + } + value = add(value, *(*pStream)++); + + pSubStruct = param->SetParamValue(pParameter, index, value); + move16(); + *pnSize = add(*pnSize, 1); + + IF ( s_and(param->pSubParamBitMap != NULL, value > 0) ) + { + pTmp = pParameter; + if(pSubStruct != NULL) pTmp = pSubStruct; + SetParameters(param->pSubParamBitMap, value, pTmp, pStream, pnSize); + } + } + } + +} + +void WriteToBitstream(ParamsBitMap const * paramsBitMap, Word16 nArrayLength, Word16 const ** pStream, Word16 * pnSize, Encoder_State_fx *st, Word16 * pnBits) +{ + Word16 index; + Word16 iParam, nParams; + assert((paramsBitMap != NULL) && (nArrayLength > 0) && (pStream != NULL) && (pnSize != NULL) && (st != NULL) && (pnBits != NULL)); + nParams = paramsBitMap->nParams; + + FOR (index = 0; index < nArrayLength; index++) + { + + FOR (iParam = 0; iParam < nParams; iParam++) + { + ParamBitMap const *param; + Word16 nBits; + /* If a function for encoding/decoding value is defined than it should take care of 0 */ + Word16 fShiftValue; + TEncodeValue EncodeValue; + Word16 value; + + move16(); + param = ¶msBitMap->params[iParam]; + + move16(); + nBits = param->nBits; + IF (param->nBits == 0) + { + nBits = param->GetNumberOfBits(**pStream, index); + } + + test(); + test(); + fShiftValue = s_and(param->fZeroAllowed==0, param->EncodeValue == NULL); + move16(); + EncodeValue = param->EncodeValue; + if (param->EncodeValue == NULL) + { + move16(); + EncodeValue = &FixedWidthEncoding; + } + value = PutIntoBitstream(pStream, EncodeValue, index, st, nBits); + if (fShiftValue) + { + value = add(value, 1); + } + + move16(); + *pnSize = add(*pnSize, 1); + move16(); + *pnBits = add(*pnBits, nBits); + + IF ((param->pSubParamBitMap != NULL) && (value > 0)) + { + WriteToBitstream(param->pSubParamBitMap, value, pStream, pnSize, st, pnBits); + } + + } + } +} + +void ReadFromBitstream(ParamsBitMap const * paramsBitMap, Word16 nArrayLength, Decoder_State_fx *st, Word16 ** pStream, Word16 * pnSize) +{ + Word16 index; + Word16 iParam, nParams; + Word16 fShiftValue; + Word16 value; + assert((paramsBitMap != NULL) && (nArrayLength > 0) && (pStream != NULL) && (pnSize != NULL) && (st != NULL)); + move16(); + nParams = paramsBitMap->nParams; + + FOR (index = 0; index < nArrayLength; index++) + { + + FOR (iParam = 0; iParam < nParams; iParam++) + { + ParamBitMap const * param; + + + /* If a function for encoding/decoding value is defined than it should take care of 0 */ + move16(); + param = & paramsBitMap->params[iParam]; + + test(); + test(); + fShiftValue = s_and(param->fZeroAllowed==0, param->EncodeValue == NULL); + value = GetFromBitstream(st, param->DecodeValue, index, param->nBits, pStream); + if (fShiftValue) + { + move16(); + value = add(value, 1); + } + + IF ((param->pSubParamBitMap != NULL) && (value > 0)) + { + + ReadFromBitstream(param->pSubParamBitMap, value, st, pStream, pnSize); + } + } + } + move16(); + *pnSize = add(*pnSize, i_mult(nParams, nArrayLength)); + +} diff --git a/lib_com/phase_dispersion.c b/lib_com/phase_dispersion.c new file mode 100644 index 0000000..f2a5f67 --- /dev/null +++ b/lib_com/phase_dispersion.c @@ -0,0 +1,177 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include "options.h" /* EV-VBR compilation switches */ +#include "prot_fx.h" +#include "basop_util.h" +#include "stl.h" /* Weighted mops computation related code */ + +/*-----------------------------------------------------------------------* + * phase_dispersion: + * + * post-processing to enhance noise at low bit rate. + *-----------------------------------------------------------------------*/ + +void phase_dispersion( + const Word32 gain_code, /* i : gain of code 15Q16 */ + const Word16 gain_pit, /* i : gain of pitch Q14 */ + Word16 code[], /* i/o: code vector */ + Word16 *code_exp, /* i/o: exponent of code */ + const Word16 mode, /* i : level, 0=hi, 1=lo, 2=off */ + Word32 *prev_gain_code, /* i/o: static memory 15Q16 */ + Word16 prev_gain_pit[], /* i/o: static memory Q14, size=6 */ + Word16 *prev_state, /* i/o: static memory Q0 */ + Word16 L_subfr /* i : subframe length [40,64,80]*/ +) +{ + Word16 i, j, state, scale2; + Word32 x32[2*L_SUBFR]; + Word16 *code_real, *code_imag; + const Word16 *h_real, *h_imag; + + + + move16(); + state = 2; + + if ( LT_16(gain_pit,14746/*0.9f Q14*/)) + { + move16(); + state = 1; + } + if ( LT_16(gain_pit, 9830/*0.6f Q14*/)) + { + move16(); + state = 0; + } + + FOR (i=5; i>0; i--) + { + move16(); + prev_gain_pit[i] = prev_gain_pit[i-1]; + } + move16(); + prev_gain_pit[0] = gain_pit; + + + IF ( GT_32(gain_code, L_add(*prev_gain_code, L_shl(*prev_gain_code,1)))) + { + if (LT_16(state,2)) + { + state = add(state, 1); + } + } + ELSE + { + j=0; + FOR (i=0; i<6; i++) + { + + if ( LT_32(prev_gain_pit[i], 9830/*0.6f Q14*/)) + { + j = add(j,1); + } + } + + if (GT_16(j,2)) + { + move16(); + state = 0; + } + + if ( GT_16(sub(state, *prev_state),1)) + { + state = sub(state,1); + } + } + + move32(); + move16(); + *prev_gain_code = gain_code; + *prev_state = state; + + /*-----------------------------------------------------------------* + * circular convolution + *-----------------------------------------------------------------*/ + + state = add(state, mode); /* level of dispersion */ + j = *code_exp; + move16(); + IF( LT_16(state,2)) + { + FOR(i=0; i 0) + { + frac = sub(frac,UP_SAMP); + x0--; + } + + l = add(UP_SAMP-1, frac); + FOR (j = T0; j < L_SUBFR+1; j++) + { + k = l; + move16(); + L_sum = L_mult(x0[0], win[k]); + FOR (i = 1; i < 2 * L_INTERPOL2; i++) + { + /* + * Here, additions with UP_SAMP are not counted + ki* because, the window could easily be modified + * so that the values needed are contiguous. + */ + k += UP_SAMP; + L_sum = L_mac(L_sum, x0[i], win[k]); /*Q1 */ + } + L_sum = L_shl(L_sum, 1); /*Q0h */ + + excO[j] = round_fx(L_sum); + + x0++; + } + FOR (i = T0; i < L_SUBFR; i++) + { + exc[i+i_subfr] = add(exc[i+i_subfr], mult_r(PIT_SHARP_fx, excO[i])); + move16(); + } + } + + return; + +} diff --git a/lib_com/preemph_fx.c b/lib_com/preemph_fx.c new file mode 100644 index 0000000..b667eec --- /dev/null +++ b/lib_com/preemph_fx.c @@ -0,0 +1,136 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------* + * preemph_copy_fx() + * + * Preemphasis: filtering through 1 - mu z^-1 + *-------------------------------------------------------------*/ +void preemph_copy_fx( + const Word16 x[], /* i : input signal Qx */ + Word16 y[], /* o : output signal Qx */ + const Word16 mu, /* i : preemphasis coefficient Q15 */ + const Word16 lg, /* i : vector size Q0 */ + Word16 *mem /* i/o: memory (x[-1]) Qx */ +) +{ + Word16 i, temp; + + temp = x[lg - 1]; + move16(); + FOR (i = sub(lg, 1); i > 0; i--) + { + y[i] = msu_r(L_deposit_h(x[i]), x[i - 1], mu); + move16(); + } + y[0] = msu_r(L_deposit_h(x[0]), *mem, mu); + move16(); + + *mem = temp; + move16(); +} + +/* + * E_UTIL_f_preemph2 + * + * Parameters: + * shift I: scale output + * signal I/O: signal Qx/Qx+shift + * mu I: preemphasis factor Q15 + * L I: vector size + * mem I/O: memory (x[-1]) + * + * Function: + * Filtering through 1 - mu z^-1 + * + * Returns: + * void + */ +void E_UTIL_f_preemph2(Word16 shift, Word16 *signal, const Word16 mu, const Word16 lg, Word16 *mem) +{ + Word16 i, temp; + Word32 L_tmp; + + temp = signal[lg - 1]; + move16(); + + FOR (i = sub(lg, 1); i > 0; i--) + { + L_tmp = L_mult(signal[i], 16384); + L_tmp = L_msu0(L_tmp, signal[i - 1], mu); + L_tmp = L_shl(L_tmp, add(shift,1)); + signal[i] = round_fx(L_tmp); + } + + L_tmp = L_mult(signal[0], 16384); + L_tmp = L_msu0(L_tmp, *mem, mu); + L_tmp = L_shl(L_tmp, add(shift,1)); + signal[0] = round_fx(L_tmp); + + *mem = temp; + move16(); + + return; +} + + +Word16 E_UTIL_f_preemph3(Word16 *signal, const Word16 mu, const Word16 lg, Word16 *mem, Word16 bits) +{ + Word16 i, QVal, mus, tmp_fixed, Q_new; + Word32 L_tmp, L_maxloc; + + + + QVal = shl(1, sub(15,bits)); + mus = shr(mu, bits); + + L_tmp = L_mult(signal[0], QVal); + L_tmp = L_msu(L_tmp, *mem, mus); + L_maxloc = L_abs(L_tmp); + + FOR (i = 1; i < lg; i++) + { + L_tmp = L_mult(signal[i], QVal); + L_tmp = L_msu(L_tmp, signal[i - 1], mus); + L_tmp = L_abs(L_tmp); + L_maxloc = L_max(L_tmp, L_maxloc); + } + + tmp_fixed = extract_h(L_maxloc); + + Q_new = Q_MAX; + move16(); + IF (tmp_fixed != 0) + { + Q_new = sub(norm_s(tmp_fixed), bits); + Q_new = s_max(Q_new, 0); + Q_new = s_min(Q_new, Q_MAX); + } + + tmp_fixed = signal[lg - 1]; + move16(); + + FOR (i = sub(lg,1); i > 0; i--) + { + L_tmp = L_mult(signal[i], QVal); + L_tmp = L_msu(L_tmp, signal[i - 1], mus); + L_tmp = L_shl(L_tmp, Q_new); + signal[i] = round_fx(L_tmp); + } + + L_tmp = L_mult(signal[0], QVal); + L_tmp = L_msu(L_tmp, *mem, mus); + L_tmp = L_shl(L_tmp, Q_new); + signal[0] = round_fx(L_tmp); + + *mem = tmp_fixed; + move16(); + + return Q_new; +} + diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h new file mode 100644 index 0000000..ef98679 --- /dev/null +++ b/lib_com/prot_fx.h @@ -0,0 +1,11084 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#ifndef PROT_COM_FX_H +#define PROT_COM_FX_H +#include +#include "options.h" /* Compilation switches */ +#include "rom_com_fx.h" /* Compilation switches */ +#include "typedefs.h" +#include "stat_dec_fx.h" +#include "stat_enc_fx.h" +#include "stat_com.h" +#include "cnst_fx.h" +#include "basop_util.h" +#include "complex_basop.h" +/*----------------------------------------------------------------------------------* + * Prototypes of global macros + *----------------------------------------------------------------------------------*/ + +void reset_preecho_dec_fx ( + Decoder_State_fx *st_fx /* i/o: decoder state structure */ +); + +void preecho_sb_fx( + const Word32 brate, /* i Q0 : core bit-rate */ + Word32 *wtda_audio_fx, /* i q_sig32 : imdct signal */ + Word16 q_sig32, /* i Q value for wtda_audio_fx */ + Word16 *rec_sig_fx, /* i q_sig16 : reconstructed signal, output of the imdct transform */ + Word16 q_sig16, /* i Q value for rec_sig_fx and imdct_mem_fx */ + const Word16 framelength, /* i Q0 : frame length */ + Word16 *memfilt_lb_fx, /* i/o Q0 : memory */ + Word32 *mean_prev_hb_fx, /* i/o Q0 : memory */ + Word16 *smoothmem_fx, /* i/o Q15 : memory */ + Word32 *mean_prev_fx, /* i/o Q0 : memory */ + Word32 *mean_prev_nc_fx, /* i/o Q0 : memory */ + Word16 *wmold_hb_fx, /* i/o Q15 : memory */ + Word16 *prevflag, /* i/o Q0 : flag */ + Word16 *pastpre, /* i/o Q0 : flag */ + const Word16 bwidth /* i Q0 : bandwidth */ +); + +void calc_normal_length_fx_32( + const Word16 core, /* i : core : Q0 */ + const Word32 *sp, /* i : input signal : Q12 */ + const Word16 mode, /* i : input mode : Q0 */ + const Word16 extl, /* i : extension layer : Q0 */ + Word16 *L_swb_norm, /* o : normalize length : Q0 */ + Word16 *prev_L_swb_norm /*i/o : last normalize length : Q0 */ +); + +void calc_norm_envelop_fx_32( + const Word32 SWB_signal_fx[], /* i : SWB spectrum : Q12 */ + Word32 *envelope_fx, /* o : normalized envelope : Q16 */ + const Word16 L_swb_norm, /* i : length of envelope : Q0 */ + const Word16 SWB_flength, /* i : Length of input/output : Q0 */ + const Word16 st_offset /* i : offset : Q0 */ +); + +void push_indice_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 id, /* i : ID of the indice */ + UWord16 value, /* i : value of the quantized indice */ + Word16 nb_bits /* i : number of bits used to quantize the indice */ +); + +void push_next_indice_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + UWord16 value, /* i : value of the quantized indice */ + Word16 nb_bits /* i : number of bits used to quantize the indice */ +); + +void push_next_bits_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 bits[], /* i : bit buffer to pack, sequence of single bits */ + Word16 nb_bits /* i : number of bits to pack */ +); +void get_NextCoderType_fx( + UWord8 *bitsteam, /* i : bitstream */ + Word16 *next_coder_type /* o : next coder type */ +); +void evs_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 input_sp[], /* i : input signal */ + const Word16 n_samples /* i : number of input samples */ +); + +void io_ini_enc_fx( + const int argc, /* i : command line arguments number */ + char *argv[], /* i : command line arguments */ + FILE **f_input, /* o : input signal file */ + FILE **f_stream, /* o : output bitstream file */ + FILE **f_rate, /* o : bitrate switching profile (0 if N/A) */ + FILE **f_bwidth, /* o : bandwidth switching profile (0 if N/A) */ + FILE **f_rf, /* o : channel aware config profile (0 if N/A) */ + Word16 *quietMode, /* o : limit printouts */ + Word16 *noDelayCmp, /* o : turn off delay compensation */ + Encoder_State_fx *st /* o : state structure */ +); + +void read_next_rfparam_fx( + Word16* rf_fec_offset, /* o: rf offset */ + Word16* rf_fec_indicator, /* o: rf FEC indicator */ + FILE* f_rf /* i: file pointer to read parameters */ +); + +void read_next_brate_fx( + Word32 *total_brate, /* i/o: total bitrate */ + const Word32 last_total_brate, /* i : last total bitrate */ + FILE *f_rate, /* i : bitrate switching profile (0 if N/A) */ + Word32 input_Fs, /* i : input sampling frequency */ + Word16 *Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + Word16 *Opt_SC_VBR, /* i/o: SC-VBR flag */ + Word16 *codec_mode /* i/o: MODE1 or MODE2 */ +); + + +void read_next_bwidth_fx( + Word16 *max_bwidth, /* i/o: maximum encoded bandwidth */ + FILE *f_bwidth, /* i : bandwidth switching profile (0 if N/A) */ + Word32 *bwidth_profile_cnt, /* i/o: counter of frames for bandwidth switching profile file */ + Word32 input_Fs /* i : input sampling frequency */ +); + +UWord16 get_next_indice_fx( /* o : value of the indice */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 nb_bits /* i : number of bits that were used to quantize the indice */ +); + +UWord16 get_next_indice_1_fx( /* o : value of the indice */ + Decoder_State_fx *st_fx /* i/o: decoder state structure */ +); + +void get_next_indice_tmp_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 nb_bits /* i : number of bits that were used to quantize the indice */ +); + + +UWord16 get_indice_fx( /* o : value of the indice */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 pos, /* i : absolute position in the bitstream */ + Word16 nb_bits /* i : number of bits that were used to quantize the indice */ +); + +UWord16 get_indice_1_fx( /* o : value of the indice */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 pos /* i : absolute position in the bitstream */ +); + +void reset_indices_enc_fx( + Encoder_State_fx *st_fx /* i/o: encoder state structure */ +); + + +void reset_indices_dec_fx( + Decoder_State_fx *st_fx /* i/o: decoder state structure */ +); + +void write_indices_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + FILE *file /* i : output bitstream file */ + , UWord8 *pFrame, /* i: byte array with bit packet and byte aligned coded speech data */ + Word16 pFrame_size /* i: size of the binary encoded access unit [bits] */ +); + +Word16 read_indices_fx( /* o : 1 = OK, 0 = something wrong */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + FILE *file, /* i : bitstream file */ + Word16 rew_flag /* i : rewind flag (rewind file after reading) */ +); + +Word16 read_indices_mime( /* o : 1 = reading OK, 0 = problem */ + Decoder_State_fx *st, /* i/o: decoder state structure */ + FILE *file, /* i : bitstream file */ + Word16 rew_flag /* i : rewind flag (rewind file after reading)*/ +); + +void indices_to_serial( + const Encoder_State_fx *st_fx, /* i: encoder state structure */ + UWord8 *pFrame, /* o: byte array with bit packet and byte aligned coded speech data */ + Word16 *pFrame_size /* i: size of the binary encoded access unit [bits] */ +); + +void indices_to_serial_generic( + const Indice_fx *ind_list, /* i: indices list */ + const Word16 num_indices, /* i: number of indices to write */ + UWord8 *pFrame, /* o: byte array with bit packet and byte aligned coded speech data */ + Word16 *pFrame_size /* i/o: number of bits in the binary encoded access unit [bits] */ +); + +void evs_dec_previewFrame( + UWord8 *bitstream, /* i : bitstream pointer */ + Word16 bitstreamSize, /* i : bitstream size */ + Word16 *partialCopyFrameType, /* o : frame type of the partial copy */ + Word16 *partialCopyOffset /* o : offset of the partial copy relative to the primary copy */ +); + +void read_indices_from_djb_fx( + Decoder_State_fx *st, /* i/o: decoder state structure */ + UWord8 *pt_stream, /* i : bitstream file */ + Word16 nbits /* i : number of bits */ + , Word16 isAMRWB_IOmode + , Word16 core_mode + , Word16 qbit + ,Word16 partialframe /* i : partial frame information */ + ,Word16 next_coder_type /* i : next coder type information */ +); + +void reset_rf_indices( + Encoder_State_fx *st /* i: state structure - contains partial RF indices */ +); + +void getPartialCopyInfo( + Decoder_State_fx *st, /* i : decoder state structure */ + Word16 *coder_type, + Word16 *sharpFlag +); + +void get_rfFlag( + Decoder_State_fx *st, /* i : decoder state structure */ + Word16 *rf_flag, /* o : check for the RF flag */ + Word16 *nBits, + Word16 *ind +); + +void get_rfFrameType( + Decoder_State_fx *st, /* i : decoder state structure */ + Word16 *rf_frame_type /* o : RF frame type */ +); + +void get_rf_fec_offset( + Decoder_State_fx *st, /* i : decoder state structure */ + Word16 *rf_fec_offset /* o : RF fec offset */ +); + +void get_rfTargetBits( + Word16 rf_frame_type, /* i : RF frame type */ + Word16 *rf_target_bits /* o : Number of RF target bits */ +); + + +Word16 BRATE2IDX_fx(Word32 brate); +Word16 BRATE2IDX16k_fx(Word32 brate); + +Word32 BIT_ALLOC_IDX_fx(Word32 brate, Word16 ctype, Word16 sfrm, Word16 tc); +Word32 BIT_ALLOC_IDX_16KHZ_fx(Word32 brate, Word16 ctype, Word16 sfrm, Word16 tc); + +void save_old_syn_fx( + const Word16 L_frame, /* i : frame length */ + const Word16 syn[], /* i : ACELP synthesis */ + Word16 old_syn[], /* o : old synthesis buffer */ + Word16 old_syn_mem[], /* i/o: old synthesis buffer memory */ + const Word16 preemph_fac, /* i : preemphasis factor */ + Word16 *mem_deemph /* i/o: deemphasis filter memory */ +); + +void evs_dec_fx( + Decoder_State_fx *st_fx, /* i/o : Decoder state structure */ + Word16 output_sp[], /* o : output synthesis signal */ + frameMode_fx frameMode /* i : Decoder frame mode */ +); + +Word16 decodeVoip( + Decoder_State_fx *st_fx, + FILE *f_stream, + FILE *f_synth, +#ifdef SUPPORT_JBM_TRACEFILE + const char *jbmTraceFileName, +#endif + const char *jbmFECoffsetFileName, /* : Output file for Optimum FEC offset */ + const Word16 quietMode +); + + +void io_ini_dec_fx( + const int argc, /* i : command line arguments number */ + char *argv[], /* i : command line arguments */ + FILE **f_stream, /* o : input bitstream file */ + FILE **f_synth, /* o : output synthesis file */ + Word16 *quietMode, /* o : limited printouts */ + Word16 *noDelayCmp, /* o : turn off delay compensation */ + Decoder_State_fx *st_fx, /* o : Decoder static variables structure */ +#ifdef SUPPORT_JBM_TRACEFILE + char **jbmTraceFileName, /* o : VOIP tracefilename */ +#endif + char **jbmFECoffsetFileName /* o : Output file for Optimum FEC offset */ +); +Word16 deindex_lvq_cng_fx( + Word16 *index, /* i : index to be decoded, as an array of 3 short */ + Word16 *x_lvq, /* o : decoded codevector Q9*/ + Word16 idx_cv, /* i : relative mode_lvq, wrt START_CNG */ + Word16 no_bits, /* i : number of bits for lattice */ + Word32 * p_offset_scale1, + Word32 * p_offset_scale2, + Word16 * p_no_scales +); + +void CNG_dec_fx( + Decoder_State_fx *st_fx, /* i/o: State structure */ + const Word16 L_frame, /* i : length of the frame Q0 */ + Word16 Aq[], /* o : LP coefficients Q12 */ + const Word32 core_brate, /* i : core bitrate Q0 */ + Word16 *lsp_new, /* i/o: current frame LSPs Q15 */ + Word16 *lsf_new, /* i/o: current frame LSFs Qlog2(2.56) */ + Word16 *allow_cn_step /* o : allow CN step Q0 */ + ,Word16 *sid_bw /* o : 0-NB/WB, 1-SWB SID */ + ,Word32 *q_env +); + +void swb_CNG_dec_fx( + Decoder_State_fx *st_fx, /* i/o: State structure */ + const Word16 *synth_fx, /* i : ACELP core synthesis at 32kHz */ + Word16 *shb_synth_fx, /* o : high-band CNG synthesis */ + const Word16 sid_bw, /* i : 0-NB/WB, 1-SWB SID */ + const Word16 Qsyn /* i : Q value of ACELP core synthesis */ +); + +void CNG_reset_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + LPD_state *mem, /* i/o: acelp memories */ + Word16 *pitch_buf, /* o : floating pitch for each subframe */ + Word16 *voice_factors /* o : voicing factors */ + ,Word16 VBR_cng_reset_flag +); + +void CNG_reset_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *pitch_buf, /* o : floating pitch for each subframe */ + Word16 *voice_factors /* o : voicing factors */ +); + +void CNG_exc_fx( + const Word32 core_brate, /* i : core bitrate */ + const Word16 L_frame, /* i : length of the frame */ + Word32 *Enew, /* i/o: decoded SID energy Q6 */ + Word16 *seed, /* i/o: random generator seed */ + Word16 exc[], /* o : current non-enhanced excitation Q_new */ + Word16 exc2[], /* o : current enhanced excitation Q_new */ + Word32 *lp_ener, /* i/o: LP filtered E */ + const Word32 last_core_brate, /* i : previous frame core bitrate */ + Word16 *first_CNG, /* i/o: first CNG frame flag for energy init. */ + Word16 *cng_ener_seed, /* i/o: random generator seed for CNG energy */ + Word16 bwe_exc[], /* o : excitation for SWB TBE */ + const Word16 allow_cn_step, /* i : allow CN step */ + Word16 *last_allow_cn_step, /* i/o: last allow step */ + const Word16 OldQ_exc, /* i : Old excitation scaling */ + const Word16 Q_exc, /* i : excitation scaling */ + const Word16 num_ho /* i : number of selected hangover frames */ + ,Word32 q_env[] + ,Word32 *lp_env + ,Word32 *old_env + ,Word16 *exc_mem + ,Word16 *exc_mem1 + ,Word16 *sid_bw + ,Word16 *cng_ener_seed1 + ,Word16 exc3[] + ,Word16 Opt_AMR_WB +); + +void CNG_enc_fx( + Encoder_State_fx *st_fx, /* i/o: State structure */ + const Word16 L_frame, /* i : length of the frame Q0 */ + Word16 Aq[], /* o : LP coefficients Q12 */ + const Word16 *speech, /* i : pointer to current frame input speech buffer Q_new */ + Word32 L_enr, /* i : residual energy from Levinson-Durbin Q6 */ + Word16 *lsp_new, /* i/o: current frame ISPs Q15 */ + Word16 *lsf_new, /* i/o: current frame ISFs Qlog2(2.56) */ + Word16 *allow_cn_step, /* o : allow CN step Q0 */ + Word16 burst_ho_cnt, /* i : hangover frames at end of speech burst Q0 */ + Word16 Q_new /* i : Q value of speech */ + ,Word32 *q_env + ,Word16 *sid_bw + ,Word16 *exc_mem2 +); + +void swb_CNG_enc_fx( + Encoder_State_fx *st_fx, /* i/o: State structure */ + const Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz */ + const Word16 *syn_12k8_16k_fx /* i : ACELP core synthesis at 12.8kHz or 16kHz */ +); + +void cng_params_upd_fx( + const Word16 lsp_new[], /* i : LSP parameters Q15 */ + const Word16 exc2[], /* i : current enhanced excitation Q_exc */ + const Word16 L_frame, /* i : frame length Q0 */ + Word16 *ho_circ_ptr, /* i/o: pointer for CNG averaging buffers Q0 */ + Word32 ho_ener_circ[], /* o : energy buffer for CNG averaging Q6 */ + Word16 *ho_circ_size, /* i/o: size of DTX hangover history buffer for averaging Q0 */ + Word16 ho_lsp_circ[], /* o : old LSP buffer for CNG averaging Q15 */ + const Word16 Q_exc, /* i : Q value of excitation */ + const Word16 enc_dec_flag, /* i : Flag indicating encoder or decoder (ENC,DEC) */ + Word32 ho_env_circ[], /* i/o: Envelope buffer */ + Word16 *cng_buf_cnt, /* i/o: Counter of postponed FFT-processing instances */ + Word16 cng_exc2_buf[], /* i/o: Excitation buffer Q_exc */ + Word16 cng_Qexc_buf[], /* i/o: Q_exc buffer Q0 */ + Word32 cng_brate_buf[], /* i/o: last_active_brate buffer Q0 */ + const Word32 last_active_brate /* i : Last active bit rate Q0 */ +); + +void cng_params_postupd_fx( + const Word16 ho_circ_ptr, /* i : pointer for CNG averaging buffers Q0 */ + Word16 *cng_buf_cnt, /* i/o: counter for CNG store buffers Q0 */ + const Word16 *const cng_exc2_buf, /* i : Excitation buffer Q_exc */ + const Word16 *const cng_Qexc_buf, /* i : Q_exc buffer Q0 */ + const Word32 *const cng_brate_buf, /* i : bit rate buffer Q0 */ + Word32 ho_env_circ[] /* i/o: Envelope buffer */ +); +Word32 get_delay_fx( /* o : delay value in ms */ + const Word16 what_delay, /* i : what delay? (ENC or DEC) */ + const Word32 io_fs /* i : input/output sampling frequency */ +); + + +void signalling_enc_fx( + Encoder_State_fx *st_fx, /* i : encoder state structure */ + const Word16 coder_type, /* i : coder type */ + const Word16 sharpFlag /* i : formant sharpening flag */ +); + +Word16 signalling_mode1_tcx20_enc( + Encoder_State_fx *st, /* i : encoder state structure */ + Word16 push +); + +void signalling_enc_rf( + Encoder_State_fx *st /* i : encoder state structure */ +); + +void decision_matrix_core_dec( + Decoder_State_fx *st /* i/o: decoder state structure */ +); + +void decision_matrix_enc_fx( + Encoder_State_fx *st_fx, /* i : encoder state structure */ + const Word16 sp_aud_decision1, /* i : 1st stage speech/music classification */ + const Word16 sp_aud_decision2, /* i : 2nd stage speech/music classification */ + const Word16 coder_type, /* i : coder type */ + const Word16 vad_flag, + Word16 *hq_core_type /* o : HQ core_fx type */ +); + +void decision_matrix_dec_fx( + Decoder_State_fx *st, /* i/o: decoder state structure */ + Word16 *coder_type, /* o : coder type */ + Word16 *sharpFlag, /* o : formant sharpening flag */ + Word16 *hq_core_type, /* o : HQ core type */ + Word16 *core_switching_flag /* o : ACELP->HQ switching frame flag */ +); + +void init_gp_clip_fx( + Word16 mem[] /* o : memory of gain of pitch clipping algorithm */ +); + +void gp_clip_test_isf_fx( + const Word32 core_brate, /* i : core bitrate */ + const Word16 isf[], /* i : isf values (in frequency domain) */ + Word16 mem[], /* i/o: memory of gain of pitch clipping algorithm */ + const Word16 Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */ +); + +void pitch_ol_init_fx( + Word16 *old_thres, /* o : threshold for reinforcement of past pitch influence */ + Word16 *old_pitch, /* o : pitch of the 2nd half-frame of previous frame */ + Word16 *delta_pit, /* o : pitch evolution extrapolation */ + Word16 *old_corr /* o : correlation */ +); + +void noise_est_down_fx( + const Word32 fr_bands[], /* i : per band input energy (contains 2 vectors) */ + Word32 bckr[], /* i/o: per band background noise energy estimate */ + Word32 tmpN[], /* o : temporary noise update */ + Word32 enr[], /* o : averaged energy over both subframes */ + const Word16 min_band, /* i : minimum critical band */ + const Word16 max_band, /* i : maximum critical band */ + Word16 *totalNoise, /* o : noise estimate over all critical bands */ + Word16 Etot, /* i : Energy of current frame */ + Word16 *Etot_last, /* i/o: Energy of last frame Q8 */ + Word16 *Etot_v_h2, /* i/o: Energy variations of noise frames Q8 */ + Word16 Q_new, + const Word32 e_min /* i : minimum energy scaled Q_new + QSCALE */ +); + +void wb_vad_init_fx( + Word16 *nb_active_frames, /* o : nb of consecutive active speech frames */ + Word16 *hangover_cnt, + Word16 *lp_speech, /* o : long-term active speech level */ + Word16 *nb_active_frames_he, /* o : nb of consecutive active speech frames */ + Word16 *hangover_cnt_he, + Word16 *bcg_flux, /* o : background noise fluctuation */ + Word16 *soft_hangover, /* o : soft hangover counter */ + Word16 *voiced_burst, /* o : consecutive voiced speech counter */ + Word16 *bcg_flux_init, /* o : initialization period for noise fluctuation estimation */ + Word16 *nb_active_frames_he1, /* o : nb of consecutive active speech frames 1 */ + Word16 *hangover_cnt_he1, + Word32 *L_vad_flag_reg_H, + Word32 *L_vad_flag_reg_L, + Word32 *L_vad_prim_reg, + Word16 *vad_flag_cnt_50, + Word16 *vad_prim_cnt_16, + Word16 *hangover_cnt_dtx, + Word16 *hangover_cnt_music +); + +Word16 wb_vad_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 fr_bands[], /* i : per band input energy (contains 2 vectors) Q_new+QSCALE*/ + Word16 *localVAD, + Word16 *noisy_speech_HO, /* o : SC-VBR noisy speech HO flag */ + Word16 *clean_speech_HO, /* o : SC-VBR clean speech HO flag */ + Word16 *NB_speech_HO, /* o : SC-VBR NB speech HO flag */ + Word16 *snr_sum_he, /* o : Output snr_sum as weighted spectral measure */ + Word16 *localVAD_HE_SAD, /* o : HE_SAD decision without hangovers */ + Word8 *flag_noisy_speech_snr, /* o : */ + const Word16 Q_new /* i : scaling factor Q0 */ +); + + +void dtx_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 vad, /* i : vad flag */ + const Word16 speech[], /* i : Pointer to the speech frame */ + Word16 Q_speech /* i : Q factor for speech */ + +); + +void dtx_hangover_control_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 lsp_new_fx[M] /* i : current frame LSPs */ +); + +Word16 dtx_hangover_addition_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 localVAD, /* i Q0 */ + const Word16 vad_flag, /* i Q0 */ + const Word16 lp_snr, /* i Q8 */ + const Word16 cldfb_subtraction, /* i Q0 */ + Word16 *vad_hover_flag_ptr +); + +void noise_est_init_fx( + Word16 *totalNoise, /* o : noise estimate over all critical bands */ + Word16 *first_noise_updt, /* o : noise update initialization flag */ + Word32 bckr[], /* o : per band background noise energy estimate */ + Word32 enrO[], /* o : per band old input energy */ + Word32 ave_enr[], /* o : per band long-term average energies */ + Word16 *pitO, /* o : open-loop pitch values from preceed. frame */ + Word16 *aEn, /* o : noise adaptation hangover counter */ + Word16 *st_harm_cor_cnt, /* i/o: 1st harm correlation timer */ + Word16 *bg_cnt, /* i/o: pause burst length counter */ + Word16 *lt_tn_track, /* Q15 */ + Word16 *lt_tn_dist, /* Q8 */ + Word16 *lt_Ellp_dist, /* Etot low lp same domain as *Etot_l_lp, Q8 */ + Word16 *lt_haco_ev, /* Q15 */ + Word16 *low_tn_track_cnt /* Q0 */ + ,Word16 *Etot_st_est, /* Q8: Short term Etot Estimate for variance calc */ + Word16 *Etot_sq_st_est /* Q2 : Short term Etot^2 Estimate for variance calc */ + +); + + +void noise_est_pre_fx( + const Word16 Etot, /* i : Energy of current frame */ + const Word16 ini_frame_fx, /* i : Frame number (init) */ + Word16 *Etot_l, /* i/o: Track energy from below */ /*Q8 */ + Word16 *Etot_h, /* i/o: Track energy from above */ /*Q8 */ + Word16 *Etot_l_lp, /* i/o: Smoothed low energy */ /*Q8 */ + Word16 *Etot_last, /* i/o: Energy of last frame */ /*Q8 */ + Word16 *Etot_v_h2, /* i/o: Energy variations */ /*Q8*/ + Word16 *sign_dyn_lp, /* i/o: Smoother signal dynamics */ /*Q8*/ + Word16 harm_cor_cnt, /* i : correlation counter */ + Word16 *Etot_lp /* i/o: Smoothed energy */ +); + +void Preemph_scaled( + Word16 new_speech[], /* i : Speech to scale already on 14 bits*/ + Word16 *Q_new, /* o : Scaling factor */ + Word16 *mem_preemph, /* i/o: Preemph memory */ + Word16 *Q_max, /* i/o: Q_new limitation */ + const Word16 Preemph_factor, /* i : Preemphasis factor Q15 */ + const Word16 bits, /* i : Bit to remove from the output to (15-bits)*/ + const Word16 bit1, /* i : Limit the output scaling to ((15-bits)-bit1) bits */ + const Word16 L_Q_mem, /* i : Number of old scaling to take into account */ + const Word16 Lframe, /* i : Frame length */ + const Word16 last_coder_type, /* i : coder_type */ + const Word16 Search_scaling /* i : enable the search of a proper scaling factor*/ +); +Word32 Scale_mem_pre_proc( /* o : Min energy scaled */ + Word16 ini_frame_fx, /* i : Frame number */ + Word16 Q_exp, /* i : Diff scaling factor */ + Word16 *Q_new, /* i/o: Absolute scaling factor */ + Word16 *old_speech, /* i/o: Speech memory */ + Word16 *mem_wsp, /* i/o: wsp vector memory */ + Word32 *enrO, /* i/o: Enr mem */ + Word32 *bckr, /* i/o: Back ground_fx ener mem */ + Word32 *ave_enr, /* i/o: Ave_enr mem */ + Word32 *ave_enr2, /* i/o: Ave_enr2 mem */ + Word32 *st_fr_bands1, /* i/o: spectrum per critical bands of the previous frame */ + Word32 *st_fr_bands2, /* i/o: spectrum per critical bands 2 frames ago */ + Word32 *st_Bin_E_old +); +void Scale_mem_enc( + Word16 Q_exp, /* i : Diff scaling factor */ + Word16 *old_speech16k, /* i/o: Speech memory */ + Word16 *old_exc, /* i/o: excitation memory */ + Word16 *old_bwe_exc, /* i/o: BWE excitation memory */ + Word16 *mem_w0, /* i/o: target vector memory */ + Word16 *mem_syn, /* i/o: synthesis memory */ + Word16 *mem_syn2, /* i/o: synthesis memory */ + Word16 *mem_deemp_preQ_fx, /*i/o: deemphasis memory for the high rate celp codec */ + Word16 *last_exc_dct_in, + Word16 *old_input_lp +); + +void SetModeIndex( + Encoder_State_fx *st, + Word32 total_brate, + Word16 bwidth, + const Word16 shift +); + +void init_encoder_fx( + Encoder_State_fx *st_fx /* i/o: Encoder static variables structure */ +); + +void destroy_encoder_fx( Encoder_State_fx *st_fx ); + +void analysisCldfbEncoder_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *timeIn, + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 realBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word16 imagBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], + Word32 enerBuffSum[CLDFB_NO_CHANNELS_MAX], + Word16 *enerBuffSum_exp, + CLDFB_SCALE_FACTOR * scale +); + +void cldfb_save_memory (HANDLE_CLDFB_FILTER_BANK hs); /* i/o: cldfb handle */ +void cldfb_restore_memory (HANDLE_CLDFB_FILTER_BANK hs); /* i/o: cldfb handle */ +void cldfb_reset_memory (HANDLE_CLDFB_FILTER_BANK hs); /* i/o: cldfb handle */ + +Word16 gp_clip_fx( + const Word32 core_brate, /* i : core bitrate */ + const Word16 *voicing, /* i : normalized correlations (from OL pitch) */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 coder_type, /* i : type of coder */ + const Word16 xn[], /* i : target vector */ + Word16 mem[], /* i/o: memory of gain of pitch clipping algorithm */ + const Word16 Q_new /* i : scaling factor */ +); + +void init_decoder_fx( + Decoder_State_fx *st_fx /* o: Decoder static variables structure */ +); + +void destroy_decoder( + Decoder_State_fx *st_fx /* o: Decoder static variables structure */ +); +Word16 Enr_1_Az_fx( /* o : impulse response energy Q3 */ + const Word16 Aq[], /* i : LP filter coefs Qx based on the fact that Aq[0] == 1.0 */ + const Word16 len /* i : impulse response length Q0 */ +); +void FEC_scale_syn_fx( + const Word16 L_frame, /* i : length of the frame */ + Word16 *update_flg, /* o: flag indicating re-synthesis after scaling*/ + Word16 clas, /* i/o: frame classification */ + const Word16 last_good, /* i: last good frame classification */ + Word16 *synth, /* i/o: synthesized speech at Fs = 12k8 Hz */ + const Word16 *pitch, /* i: pitch values for each subframe */ + Word32 L_enr_old, /* i: energy at the end of previous frame */ + Word32 L_enr_q, /* i: transmitted energy for current frame */ + const Word16 coder_type, /* i: coder type */ + const Word16 LSF_Q_prediction, /* i : LSF prediction mode */ + Word16 *scaling_flag, /* i/o: flag to indicate energy control of syn */ + Word32 *lp_ener_FEC_av, /* i/o: averaged voiced signal energy */ + Word32 *lp_ener_FEC_max, /* i/o: averaged voiced signal energy */ + const Word16 bfi, /* i: current frame BFI */ + const Word32 total_brate, /* i: total bitrate */ + const Word16 prev_bfi, /* i: previous frame BFI */ + const Word32 last_core_brate, /* i: previous frame core bitrate */ + Word16 *exc, /* i/o: excitation signal without enhancement */ + Word16 *exc2, /* i/o: excitation signal with enhancement */ + Word16 Aq[], /* i/o: LP filter coefs (can be modified if BR) */ + Word16 *old_enr_LP, /* i/o: LP filter E of last good voiced frame */ + const Word16 *mem_tmp, /* i: temp. initial synthesis filter states */ + Word16 *mem_syn, /* o: initial synthesis filter states */ + Word16 Q_exc, + Word16 Q_syn + , Word16 avoid_lpc_burst_on_recovery /* i : if true the excitation energy is limited if LP has big gain */ + , Word16 force_scaling /* i: force scaling */ +); + +void improv_amr_wb_gs_fx( + const Word16 clas, /* i : signal frame class */ + const Word16 coder_type, /* i : coder type */ + const Word32 core_brate, /* i : bitrate allocated to the core */ + Word16 *seed_tcx, /* i/o: Seed used for noise generation */ + Word16 *old_Aq_fx, /* i/o: old LPC filter coefficient */ + Word16 *mem_syn2_fx, /* i/o: synthesis memory */ + const Word16 lt_voice_fac_fx, /* i/o: long term voice factor Q15 */ + const Word16 locattack, /* i : Flag for a detected attack */ + Word16 *Aq_fx, /* i/o: Decoded LP filter coefficient */ + Word16 *exc2_fx, /* i/o: Decoded complete excitation */ + const Word16 Q_exc2, /* i : Exponent of Exc2 */ + Word16 *mem_tmp_fx, /* i/o: synthesis temporary memory */ + Word16 *syn_fx, /* o: Decoded synthesis to be updated */ + const Word16 Q_syn, /* i : Synthesis scaling Q0 */ + const Word16 *pitch_buf_fx, /* i : Decoded pitch buffer */ + const Word16 Last_ener_fx, /* i : Last energy (Q8) */ + const Word16 rate_switching_reset, /* i : rate switching reset flag */ + const Word16 last_coder_type_fx /* i : Last coder_type */ +); + +void FEC_pitch_estim_fx( + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 last_core, /* i : last core */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 clas, /* i : current frame classification */ + const Word16 last_good, /* i : last good clas information */ + const Word16 pitch_buf[], /* i : Floating pitch for each subframe */ + const Word32 old_pitch_buf[], /* i : buffer of old subframe pitch values 15Q16 */ + Word16 *bfi_pitch, /* i/o: update of the estimated pitch for FEC */ + Word16 *bfi_pitch_frame, /* o : frame length when pitch was updated */ + Word16 *upd_cnt, /* i/o: update counter */ + const Word16 coder_type /* i : coder_type */ +); + +Word16 div_s_ss( /* o: result of division (Word16 Q0) */ + const Word16 n, /* i: numerator (Word16 Q0 */ + const Word16 d /* i: denominator (Word16 Q0) */ +); + +Word16 detect_transient_fx( + const Word16 *in_fx, /*Q_new */ + /*Encoder_State *st, */ + const Word16 L, + const Word16 coder_type, /* i : coder type */ + Word16 Q_new, + Encoder_State_fx *st_fx +); + +Word16 detect_transient_fx32( /* o : transient flag */ + const Word32* in_fx, /* i : input signal */ + Encoder_State_fx *st_fx, /* i/o: Encoder state structure */ + const Word16 L, /* i : length (32 or 48kHz) */ + const Word16 coder_type /* i : coder type */ +); + +void ar_encoder_start_fx( PARCODEC_FX arInst, PBITSTREAM_FX bsInst, Word32 max_bits ); +void ar_encoder_done_fx( PARCODEC_FX arInst ); +void ar_decoder_start_fx( PARCODEC_FX arInst, PBITSTREAM_FX bsInst ); +void ar_decoder_done_fx( PARCODEC_FX arInst ); + +void srt_vec_ind_fx (const Word32 *linear, Word32 *srt, Word16 *I, Word16 length); +Word32 ar_div(Word32 num, Word32 denum); + +Word16 GetScale_fx( Word16 blen, Word32 bits_fx, Word32 *surplus_fx); +Word32 encode_position_ari_fx(PARCODEC_FX parenc, Word16* quants, Word16 size, Word32* est_bits_frame_fx); +Word32 encode_magnitude_usq_fx(ARCODEC_FX* parenc, Word16* magn, Word16 size, Word16 npulses, Word16 nzpos, Word32* est_frame_bits_fx); +Word32 encode_magnitude_tcq_fx(ARCODEC_FX* parenc, Word16* magn, Word16 size, Word16 npulses, Word16 nzpos, Word32* savedstates, Word32* est_frame_bits_fx); +Word32 GetISCScale_fx( Word32 *quants_fx, Word16 size, Word32 bits_fx, Word16 *magn_fx, Word32 *qscale_fx, Word32 *surplus_fx, Word16 *pulses, Word32* savedstates, Word32 noTCQ, Word16 *nzpout + , Word16 *bcount, Word32 *abuffer, Word16 *mbuffer, Word32 *sbuffer ); +Word32 encode_signs_fx(ARCODEC_FX* parenc, Word16* magn, Word16 size, Word16 npos, Word32* est_frame_bits_fx); + +void decode_position_ari_fx(PARCODEC_FX pardec, Word16 size, Word16 npulses, Word16* nz, Word16* position); +void decode_magnitude_usq_fx(ARCODEC_FX* pardec, Word16 size, Word16 npulses, Word16 nzpos, Word16* positions, Word16* out); +void decode_mangitude_tcq_fx(ARCODEC_FX* pardec, Word16 size, Word16 npulses, Word16 nzpos, Word16* positions, Word16* out, Word32* surplus_fx); +void decode_signs_fx(ARCODEC_FX* pardec, Word16 size, Word16* out); + +void tcq_core_LR_enc_fx( + Encoder_State_fx* st_fx, + Word16 inp_vector_fx[], + const Word32 coefs_norm_fx[], + Word32 coefs_quant_fx[], + const Word16 bit_budget, /* number of bits */ + const Word16 nb_sfm, + const Word16 *sfm_start, + const Word16 *sfm_end, + const Word16 *sfmsize, + Word32 *R_fx, + Word16 *npulses, + Word16 *k_sort, + const Word16 *p2a_flags, + const Word16 p2a_bands, + const Word16 *last_bitalloc, + const Word16 input_frame, + const Word16 adjustFlag, + const Word16 is_transient +); + +void tcq_core_LR_dec_fx( + Decoder_State_fx *st_fx, + Word16 *inp_vector_fx, + const Word16 bit_budget, + const Word16 bands, + const Word16 *band_start, + const Word16 *band_width, + Word32 *Rk_fx, + Word16 *npulses, + Word16 *k_sort, + const Word16 *p2a_flags, + const Word16 p2a_bands, + const Word16 *last_bitalloc, + const Word16 input_frame, + const Word16 adjustFlag, + const Word16 *is_transient +); + +void TCQLSB_fx( + Word16 bcount, + Word32 *abuffer_fx, + Word16 *mbuffer_fx, + Word32 *sbuffer_fx, + Word16 *dpath +); + +void TCQLSBdec_fx( + Word16 *dpath, + Word16 *mbuffer, + Word16 bcount +); + +void RestoreTCQ_fx( + Word16 * magn, + Word16 size, + Word16 *bcount, + Word16 *mbuffer +); + +void RestoreTCQdec_fx( + Word16 * magn, + Word16 size, + Word16 *bcount, + Word16 *mbuffer +); + +void InitLSBTCQ_fx( + Word16 *bcount +); + +void SaveTCQdata_fx( + PARCODEC_FX arInst, + Word16 *dpath, + Word16 bcount +); + +void LoadTCQdata_fx( + PARCODEC_FX arInst, + Word16 *dpath, + Word16 bcount +); + +void bit_allocation_second_fx( + Word32 *Rk, + Word32 *Rk_sort, + Word16 BANDS, + const Word16 *band_width, + Word16 *k_sort, + Word16 *k_num, + const Word16 *p2a_flags, + const Word16 p2a_bands, + const Word16 *last_bitalloc, + const Word16 input_frame +); + +void window_ola_fx( + Word32 *ImdctOut, + Word16 *auOut, + Word16 *Q_sig, + Word16 *OldauOut, + Word16 *Q_old, + const Word16 L, + const Word16 right_mode, + const Word16 left_mode, + const Word16 old_bfi, + const Word16 oldHqVoicing, + Word16 *oldgapsynth +); + +void tcx_get_windows_mode1( + Word16 left_mode, /* i: overlap mode of left window half */ + Word16 right_mode, /* i: overlap mode of right window half */ + Word16 *left_win, /* o: left overlap window */ + Word16 *right_win, /* o: right overlap window */ + Word16 *left_win_int, /* o: left overlap window */ + Word16 *right_win_int, /* o: right overlap window */ + Word16 const L +); + +void sinq_fx( + const Word16 tmp, /* i : sinus factor cos(tmp*i+phi) Q15*/ + const Word16 phi, /* i : sinus phase cos(tmp*i+phi) Q15*/ + const Word16 N, /* i : size of output */ + Word16 x[] /* o : output vector Q15*/ +); + +Word16 FEC_phase_matching_fx( + Decoder_State_fx *st_fx, /* i : Decoder State */ + Word32 *ImdctOut_fx, /* i : input */ + Word16 *auOut_fx, /* o : output audio */ + Word16 *OldauOut_fx, + Word16 OldauOut_pha_fx[2][N_LEAD_NB] +); + +void FEC_phase_matching_nextgood_fx( + const Word32 *ImdctOut_fx, /* i : input */ + Word16 *auOut_fx, /* o : output audio */ + Word16 *OldauOut_fx, /* i/o: audio from previous frame */ + Word16 OldauOut_pha_fx[2][N_LEAD_NB], + Word16 mean_en_high_fx /* Q5 */ +); + +void FEC_phase_matching_burst_fx( + const Word32 *ImdctOut_fx, /* i : input */ + Word16 *auOut_fx, /* o : output audio */ + Word16 *OldauOut_fx, /* i/o: audio from previous frame */ + Word16 OldauOut_pha_fx[2][N_LEAD_NB], + Word16 *prev_oldauOut_fx /* i : OldauOut from previous frame */ +); + +void Repetition_smoothing_nextgood_fx( + const Word32 *ImdctOut_fx, /* i : input */ + Word16 *auOut_fx, /* o : output audio */ + Word32 *OldImdctOut_fx, /* i : input */ + Word16 *OldauOut_fx, /* i/o: audio from previous frame */ + Word16 cur_data_use_flag, /* i : current imdct data use flag */ + Word16 overlap_time +); + +Word16 Repetition_smoothing_fx( + const Word32 *ImdctOut_fx, /* i : input */ + Word16 *auOut_fx, /* o : output audio */ + Word32 *OldImdctOut_fx, /* i/o: audio from previous frame */ + Word16 *OldauOut_fx, /* i/o: audio from previous frame */ + const Word16 L, /* i : length */ + Word16 *prev_oldauOut_fx, /* i/o: IMDCT output from previous old frame */ + Word16 overlap_time /* i : overlapping time */ +); + +void time_domain_FEC_HQ_fx( + Decoder_State_fx *st_fx, /* i : Decoder State */ + Word32 *wtda_audio_fx, /* i : input */ + Word16 *out_fx, /* o : output audio */ + Word16 mean_en_high_fx, /* i : transient flag */ + const Word16 output_frame, + Word16 *Q_synth +); + +void common_overlapping_fx( + Word16 *auOut_fx, /* i : Input */ + Word16 *ImdctOutWin_fx, /* o : Output */ + Word16 *OldauOut_fx, /* i : Window */ + Word16 end1, /* i : Decay */ + Word16 offset1, + Word16 start2, + Word16 end2, + Word16 offset_i2, + Word16 offset2 +); + +void Smoothing_vector_scaledown_NB_fx( + const Word16 OldauOutnoWin_fx[], /* i : Input vector 1 */ + const Word16 ImdctOutWin_fx[], /* i : Input vector 2 */ + const Word16 SmoothingWin_fx[], /* i : Smoothing window */ + Word16 auOut_fx[], /* o : Output vector that contains vector 1 .* vector 2*/ + const Word16 ol_size /* i : Overlap size */ +); + +void Scaledown_fx( + Word16 x[], /* i : Input vector */ + Word16 y[], /* o : Output vector that contains vector 1 .* vector 2*/ + Word16 scale_v, + const Word16 N /* i : Overlap size */ +); + +void Smoothing_vector_NB_fx( + const Word16 OldauOutnoWin_fx[], /* i : Input vector 1 */ + const Word16 ImdctOutWin_fx[], /* i : Input vector 2 */ + const Word16 SmoothingWin_fx[], /* i : Smoothing window */ + Word16 auOut_fx[], /* o : Output vector that contains vector 1 .* vector 2 */ + const Word16 ol_size /* i : Overlap size */ +); + +void Windowing_1st_NB_fx( + Word16 *ImdctOutWin_fx, /* o : Output */ + const Word32 *ImdctOut_fx, /* i : Input */ + const Word16 *win_fx, /* i : Window */ + const Word16 *smoothingWin_fx, /* i : Smoothing Window */ + Word16 smoothing_flag /* i : 1=Smoothing window, 0=Original window */ +); + +void Windowing_2nd_NB_fx( + Word16 *ImdctOutWin_fx, /* o : Output */ + const Word32 *ImdctOut_fx, /* i : Input */ + const Word16 *win_fx /* i : Window */ +); + +void Next_good_after_burst_erasures_fx( + const Word32 *ImdctOut_fx, + Word16 *auOut_fx, + Word16 *OldauOut_fx, + const Word16 ol_size +); + +void subband_gain_bits_fx( + const Word16 *Rk, /* i : bit allocation per band Q3 */ + const Word16 N, /* i : number of bands */ + Word16 *bits, /* o : gain bits per band */ + const Word16 *sfmsize /* i : Size of bands */ +); + +Word16 assign_gain_bits_fx( /* o : Number of assigned gain bits */ + const Word16 core, /* i : HQ core */ + const Word16 BANDS, /* i : Number of bands */ + const Word16 *band_width, /* i : Sub band bandwidth */ + Word16 *Rk, /* i/o: Bit allocation/Adjusted bit alloc. Q3 */ + Word16 *gain_bits_array, /* o : Assigned gain bits */ + Word16 *Rcalc /* o : Bit budget for shape quantizer Q3 */ +); + +void apply_gain_fx( + const Word16 *ord, /* i : Indices for energy order */ + const Word16 *band_start, /* i : Sub band start indices */ + const Word16 *band_end, /* i : Sub band end indices */ + const Word16 num_sfm, /* i : Number of bands */ + const Word16 *gains, /* i : Band gain vector Q12 */ + Word16 *xq /* i/o: Float synthesis / Gain adjusted synth Q15/Q12 */ +); + +void fine_gain_pred_fx( + const Word16 *sfm_start, /* i : Sub band start indices */ + const Word16 *sfm_end, /* i : Sub band end indices */ + const Word16 *sfm_size, /* i : Sub band bandwidths */ + const Word16 *i_sort, /* i : Energy sorting indices */ + const Word16 *K, /* i : Number of pulses per band */ + const Word16 *maxpulse, /* i : Maximum pulse per band */ + const Word16 *R, /* i : Bits per sub band Q3 */ + const Word16 num_sfm, /* i : Number of sub bands */ + Word16 *xq, /* i/o: Quantized vector /quantized vector with finegain adj Q15*/ + Word16 *y, /* i/o: Quantized vector (int) */ + Word16 *fg_pred, /* o : Predicted fine gains Q12 */ + const Word16 core /* i : Core */ +); + +void fine_gain_quant_fx( + Encoder_State_fx *st_fx, + const Word16 *ord, /* i : Indices for energy order */ + const Word16 num_sfm, /* i : Number of bands */ + const Word16 *gain_bits, /* i : Gain adjustment bits per sub band */ + Word16 *fg_pred, /* i/o: Predicted gains / Corrected gains Q12 */ + const Word16 *gopt /* i : Optimal gains Q12 */ +); + +void fine_gain_dec_fx +( + Decoder_State_fx *st, + const Word16 *ord, /* i : Indices for energy order */ + const Word16 num_sfm, /* i : Number of bands */ + const Word16 *gain_bits, /* i : Gain adjustment bits per sub band */ + Word16 *fg_pred /* i/o: Predicted gains / Corrected gains */ +); + +void get_max_pulses_fx( + const Word16 *band_start, /* i : Sub band start indices */ + const Word16 *band_end, /* i : Sub band end indices */ + const Word16 *k_sort, /* i : Indices for sorting by energy */ + const Word16 *npulses, /* i : Pulses per sub band */ + const Word16 BANDS, /* i : Number of bands */ + Word16 *inp_vector, /* i/o: Encoded shape vectors (int)*/ + Word16 *maxpulse /* o : Maximum pulse height per band */ +); + +Word16 pvq_core_enc_fx( + Encoder_State_fx *st_fx, + Word16 coefs_norm[], + Word16 coefs_quant[], + Word16 *Q_coefs, + Word16 bits_tot, /* total number of bits */ + Word16 nb_sfm, + const Word16 *sfm_start, + const Word16 *sfm_end, + const Word16 *sfmsize, + Word16 *R, /* Q3 */ + Word16 *Rs, + Word16 *npulses, + Word16 *maxpulse, + const Word16 core +); + +void pvq_encode_frame_fx( + Encoder_State_fx *st_fx, + const Word16 *coefs_norm, /* i : normalized coefficients to encode */ + Word16 Q_coefs, + Word16 *coefs_quant, /* o : quantized coefficients */ + Word16 *gopt, /* o : optimal shape gains */ + Word16 *npulses, /* o : number of pulses per band */ + Word16 *pulse_vector, /* o : non-normalized pulse shapes */ + const Word16 *sfm_start, /* i : indices of first coefficients in the bands */ + const Word16 *sfm_end, /* i : indices of last coefficients in the bands */ + const Word16 *sfmsize, /* i : band sizes */ + const Word16 nb_sfm, /* i : total number of bands */ + const Word16 *R, /* i : bitallocation per band */ + const Word16 pvq_bits, /* i : number of bits avaiable */ + const Word16 core /* i : core */ +); + + +void encode_energies_fx( + Encoder_State_fx *st_fx, + const Word16 *coefs, + const Word16 Q_coefs, + Word16 Np, + Word16 *dim_part, + Word32 *E_part, /* 32-bit Q15 */ + Word16 *bits_part, + Word16 *g_part, /* Q15 */ + Word16 qband, + Word16 *bits_left, + Word32 enr, /* 32-bit Q15 */ + Word16 dim, + const Word16 strict_bits +); + +Word16 pvq_core_dec_fx( + Decoder_State_fx *st_fx, + const Word16 *sfm_start, + const Word16 *sfm_end, + const Word16 *sfmsize, + Word16 coefs_quant[], /* o : output MDCT */ + Word16 *Q_coefs, + Word16 bits_tot, + Word16 nb_sfm, + Word16 *R, + Word16 *Rs, + Word16 *npulses, + Word16 *maxpulse, + const Word16 core +); + +void pvq_decode_frame_fx( + Decoder_State_fx *st_fx, + Word16 *coefs_quant, /* o : quantized coefficients */ + Word16 *npulses, /* o : number of pulses per band */ + Word16 *pulse_vector, /* o : non-normalized pulse shapes */ + const Word16 *sfm_start, /* i : indices of first coefficients in the bands */ + const Word16 *sfm_end, /* i : indices of last coefficients in the bands */ + const Word16 *sfmsize, /* i : band sizes */ + const Word16 nb_sfm, /* i : total number of bands */ + const Word16 *R, /* i : bitallocation per band */ + const Word16 pvq_bits, /* i : number of bits avaiable */ + const Word16 core /* i : core */ +); + +void decode_energies_fx( + Decoder_State_fx *st_fx, + Word16 Np, + Word16 *dim_part, + Word16 *bits_part, + Word16 *g_part, /* Q15 */ + Word16 qband, + Word16 *bits_left, + Word16 dim, + const Word16 strict_bits +); + +Word16 atan2_fx( + const Word32, + const Word32 +); + +void srt_vec_ind16_fx ( + const Word16 *linear, /* linear input */ + Word16 *srt, /* sorted output*/ + Word16 *I, /* index for sorted output */ + Word16 length +); + + +PvqEntry_fx mpvq_encode_vec_fx( /* o : leading_sign_index, index, size, k_val */ + const Word16* vec_in, /* i : signed pulse train */ + Word16 dim_in, /* i : dimension */ + Word16 k_val_local /* i : nb unit pulses */ +); + +PvqEntry_fx get_size_mpvq_calc_offset_fx( /* o : size, dim, k_val */ + Word16 dim_in, /* i : dimension */ + Word16 k_val_in, /* i : nb unit pulses */ + UWord32* h_mem /* o : offsets */ +); + +void mpvq_decode_vec_fx( /* o : void */ + const PvqEntry_fx* entry, /* i : sign_ind, index, dim, k_val */ + UWord32* h_mem, /* i : A/U offsets */ + Word16* vec_out /* o : pulse train */ +); + +void rc_enc_init_fx( + Encoder_State_fx *st_fx, /* i/o: Encoder state */ + Word16 tot_bits /* i : Total bit budget */ +); + +void rc_encode_fx( + Encoder_State_fx *st_fx, /* i/o: Encoder state */ + UWord32 cum_freq, /* i : Cumulative frequency up to symbol */ + UWord32 sym_freq, /* i : Symbol probability */ + UWord32 tot /* i : Total cumulative frequency */ +); + +void rc_enc_uniform_fx( + Encoder_State_fx *st_fx, /* i/o: Encoder state */ + UWord32 value, /* i : Value to encode */ + UWord32 tot /* i : Maximum value */ +); + +void rc_enc_bits_fx( + Encoder_State_fx *st_fx, /* i/o: Encoder state */ + UWord32 value, /* i : Value to encode */ + Word16 bits /* i : Number of bits used */ +); + +void rc_enc_finish_fx( + Encoder_State_fx *st_fx /* i/o: Encoder state */ +); + +Word16 rc_get_bits2_fx( /* o: Number of bits needed */ + const Word16 N, /* i: Number of bits currently used */ + const UWord32 range /* i: Range of range coder */ +); + + +void rangeCoderFinalizationFBits_fx( + Word16 Brc, + UWord32 INTrc, + Word16 *FBits +); + +void conservativeL1Norm_fx( + Word16 L, + Word16 Qvec, + Word16 Fcons, + Word16 Qavail, + Word16 Qreserv, + Word16 Dspec, + Word16 *Dvec, + Word16 *Qspare, + Word16 *Qreservplus, + Word16 *Dspecplus +); + +void bandBitsAdjustment_fx( + Word16 Brc, + UWord32 INTrc, + Word16 Bavail, + Word16 Nbands, + Word16 D, + Word16 L, + Word16 Bband, + Word16 Breserv, + Word16 *Bband_adj, + Word16 *Brem, + Word16 *Breservplus +); + + +UWord32 rc_decode_fx( /* o : Decoded cumulative frequency */ + Decoder_State_fx *st_fx, /* i/o: Decoder State */ + UWord32 tot /* i : Total cumulative frequency */ +); + +void rc_dec_update_fx( + Decoder_State_fx *st_fx, /* i/o: Decoder State */ + UWord32 cum_freq, /* i : Cumulative frequency */ + UWord32 sym_freq /* i : Symbol frequency */ +); + +UWord32 rc_dec_uniform_fx( /* i : Decoded value */ + Decoder_State_fx *st_fx, /* i/o: Decoder State */ + UWord32 tot /* i : Maximum value */ +); + +void rc_dec_init_fx( + Decoder_State_fx *st_fx, /* i/o: Decoder State */ + Word16 tot_bits /* i : Total bit budget */ +); + +Word32 rc_dec_bits_fx( /* i : Decoded value */ + Decoder_State_fx *st_fx, /* i/o: Decoder State */ + Word16 bits /* i : Number of bits */ +); + +void rc_dec_finish_fx( + Decoder_State_fx *st_fx +); + +UWord32 UL_inverse( + const UWord32 UL_val, + Word16 *exp +); + +UWord32 UL_div( + const UWord32 UL_num, + const UWord32 UL_den +); + +void hq_core_enc_fx( + Encoder_State_fx *st_fx, + const Word16 *audio, /* i : input audio signal Q0 */ + const Word16 input_frame_orig,/* i : frame length */ + const Word16 hq_core_type, /* i : HQ core type */ + const Word16 Voicing_flag +); + +void normalizecoefs_fx( + Word32 *coefs, /* i : Input vector (Q12) */ + const Word16 *ynrm, /* i : quantization indices for norms */ + const Word16 num_bands, /* i : Number of bands */ + const Word16 *band_start, /* i : Start of bands */ + const Word16 *band_end, /* i : End of bands */ + Word16 *coefs_norm /* o : Normalized output vector (Q12) */ +); + +void calc_norm_fx( + const Word32 *L_x, /* i : Input vector. Qx */ + const Word16 qx, /* i : Q value of input */ + Word16 *norm, /* o : Quantization indices for norms Q0 */ + Word16 *normlg, /* o : Quantized norms in log2 Q0 */ + const Word16 start_band, /* i : Indice of band to start coding Q0 */ + const Word16 num_bands, /* i : Number of bands Q0 */ + const Word16 *band_len, /* i : Length of bands Q0 */ + const Word16 *band_start /* i : Start of bands Q0 */ +); + +void diff_envelope_coding_fx( + const Word16 is_transient, /* i : transient indicator Q0 */ + const Word16 num_env_bands, /* i : number of envelope bands to code Q0 */ + const Word16 start_norm, /* i : start of envelope coding Q0 */ + Word16 *ynrm, /* i/o: quantization indices for norms Q0 */ + Word16 *normqlg2, /* i/o: quantized norms Q0 */ + Word16 *difidx /* o : differential code Q0 */ +); + +void reordernorm_fx( + const Word16 *ynrm, /* i : quantization indices for norms Q0 */ + const Word16 *normqlg2, /* i : quantized norms Q0 */ + Word16 *idxbuf, /* o : reordered quantization indices Q0 */ + Word16 *normbuf, /* o : reordered quantized norms Q0 */ + const Word16 nb_sfm /* i : number of bands Q0 */ +); + +void hq_hr_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure fx */ + Word32 *t_audio, /* i/o: transform-domain coefficients Q12? */ + const Word16 length, /* i : length of spectrum Q0 */ + Word16 *num_bits, /* i : number of available bits Q0 */ + const Word16 is_transient /* i : transient flag Q0 */ +); + +Word16 hq_classifier_enc_fx( /* o : Consumed bits Q0 */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 length, /* i : Frame length Q0 */ + const Word32 *coefs, /* i : Spectral coefficients Q12 */ + const Word16 is_transient, /* i : Transient flag Q0 */ + Word16 *Npeaks, /* o : Number of identified peaks Q0 */ + Word16 *peaks, /* o : Peak indices Q0 */ + Word32 *pe_gains, /* o : Peak gains Q12 */ + Word32 *nf_gains, /* o : Noise-fill gains Q12 */ + Word16 *hqswb_clas /* o : HQ class Q0 */ +); + +void hvq_classifier_fx( + const Word32 *input, /* i : input signal Q12 */ + Word16 *prev_Npeaks, /* i/o: Peak number memory Q0 */ + Word16 *prev_peaks, /* i/o: Peak indices memory Q0 */ + Word16 *hqswb_clas, /* i/o: HQ class Q0 */ + Word16 *Npeaks, /* o : Number of peaks Q0 */ + Word16 *peaks, /* o : Peak indices Q0 */ + const Word32 L_core_brate, /* i : Core bit-rate Q0 */ + const Word16 last_core, /* i : Last core used Q0 */ + Word32 *L_nf_gains, /* o : Noisefloor gains Q12 */ + Word16 *hvq_hangover, /* i/o: Mode-switch hangover Q0 */ + Word32 *L_pe_gains /* o : peak gains Q12 */ +); + +void limit_band_noise_level_calc_fx( + const Word16 *wnorm, /* i : reordered norm of sub-vectors */ + Word16 *limit, /* o : highest band of bit allocation */ + const Word32 core_brate, /* i : bit rate */ + Word16 *noise_level /* o : noise level Q15 */ +); + +Word16 BitAllocWB_fx( /* o : t Q0*/ + Word16 *y, /* i : norm of sub-vectors Q0*/ + Word16 B, /* i : number of available bits Q0*/ + Word16 N, /* i : number of sub-vectors Q0*/ + Word16 *R, /* o : bit-allocation indicator Q0*/ + Word16 *Rsubband_fx /* o : sub-band bit-allocation vector Q3*/ +); + +void hq_wb_nf_bwe_fx( + const Word16 *coeff_fx, /* i : coded/noisefilled normalized spectrum */ + const Word16 is_transient, + const Word16 prev_bfi, /* i : previous bad frame indicator */ + const Word32 *L_normq_v, + const Word16 num_sfm, /* i : Number of subbands */ + const Word16 *sfm_start, /* i : Subband start coefficient */ + const Word16 *sfm_end, /* i : Subband end coefficient */ + const Word16 *sfmsize, /* i : Subband band width */ + const Word16 last_sfm, /* i : last coded subband */ + const Word16 *R, /* i : bit allocation */ + const Word16 prev_is_transient, /* i : previous transient flag */ + Word32 *prev_normq_fx, /* i/o: previous norms */ + Word32 *prev_env_fx, /* i/o: previous noise envelopes */ + Word16 *bwe_seed, /* i/o: random seed for generating BWE input */ + Word32 *prev_coeff_out_fx, /* i/o: decoded spectrum in previous frame */ + Word16 *prev_R, /* i/o: bit allocation info. in previous frame */ + Word32 *L_coeff_out, /* o : coded/noisefilled spectrum */ + Word16 *prev_env_Q +); + +void harm_bwe_fine_fx( + const Word16 *R, /* i : bit allocation */ + const Word16 last_sfm, /* i : last coded subband */ + const Word16 high_sfm, /* i : higher transition band to BWE */ + const Word16 num_sfm, /* i : total number of bands */ + const Word16 *norm, /* i : quantization indices for norms */ + const Word16 *sfm_start, /* i : Subband start coefficient */ + const Word16 *sfm_end, /* i : Subband end coefficient */ + Word16 *prev_L_swb_norm, /* i/o: last normalize length */ + Word16 *coeff, /* i/o: coded/noisefilled normalized spectrum */ + Word32 *coeff_out, /* o : coded/noisefilled spectrum */ + Word16 *coeff_fine /* o : BWE fine structure */ +); + +void harm_bwe_fx( + const Word16 *coeff_fine, /* i : fine structure for BWE */ + const Word16 *coeff, /* i : coded/noisefilled normalized spectrum */ + const Word16 num_sfm, /* i : Number of subbands */ + const Word16 *sfm_start, /* i : Subband start coefficient */ + const Word16 *sfm_end, /* i : Subband end coefficient */ + const Word16 last_sfm, /* i : last coded subband */ + const Word16 *R, /* i : bit allocation */ + const Word16 prev_hq_mode, /* i : previous hq mode */ + Word16 *norm, /* i/o: quantization indices for norms */ + Word16 *noise_level, /* i/o: noise levels for harmonic modes */ + Word16 *prev_noise_level, /* i/o: noise factor in previous frame */ + Word16 *bwe_seed, /* i/o: random seed for generating BWE input */ + Word32 *coeff_out /* o : coded/noisefilled spectrum */ +); + +void hq_generic_encoding_fx( + const Word32 *coefs_fx, /* i : MDCT coefficients of weighted original */ + Word16 *hq_generic_fenv_fx, /* i/o: energy of SWB envelope */ + const Word16 hq_generic_offset, /* i : frequency offset for extracting energy */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *hq_generic_exc_clas /* o : bwe excitation class */ +); + +void hq_generic_fine_fx( + Word16 *coeff, /* i : coded/noisefilled normalized spectrum */ + const Word16 last_sfm, /* i : Last coded band */ + const Word16 *sfm_start, /* i : Subband start coefficient */ + const Word16 *sfm_end, /* i : Subband end coefficient */ + Word16 *bwe_seed, /* i/o: random seed for generating BWE input */ + Word16 *coeff_out1 /* o : HQ Generic input */ +); + +void hq_bwe_fx( + const Word16 HQ_mode, /* i : HQ mode */ + Word32 *coeff_out1, /* i/o: BWE input & temporary buffer */ + const Word16 *hq_generic_fenv, /* i : SWB frequency envelopes */ + Word32 *coeff_out, /* o : SWB signal in MDCT domain */ + const Word16 hq_generic_offset, /* i : frequency offset for representing hq generic bwe*/ + Word16 *prev_L_swb_norm, /*i/o : last normalize length */ + const Word16 hq_generic_exc_clas,/* i : bwe excitation class */ + const Word16 *sfm_end, /* i : End of bands */ + const Word16 num_sfm, + const Word16 num_env_bands, + const Word16 *R +); + +void hq_generic_decoding_fx( + const Word16 HQ_mode, /* i : HQ mode */ + Word32 *coeff_out1_fx, /* i/o: BWE input & temporary buffer */ + const Word16 *hq_generic_fenv_fx, /* i : SWB frequency envelopes */ + Word32 *coeff_out_fx, /* o : SWB signal in MDCT domain */ + const Word16 hq_generic_offset, /* i : frequency offset for representing hq generic*/ + Word16 *prev_L_swb_norm, /* i/o: last normalize length */ + const Word16 hq_generic_exc_clas, /* i : bwe excitation class */ + const Word16 *R +); + + +void map_hq_generic_fenv_norm_fx( + const Word16 hqswb_clas, + const Word16 *hq_generic_fenv, /* Q1, frequency-domain BWE envelope */ + Word16 *ynrm, + Word16 *normqlg2, + const Word16 num_env_bands, + const Word16 nb_sfm, + const Word16 hq_generic_offset +); + +Word16 get_nor_delta_hf_fx( + Decoder_State_fx *st, + Word16 *ynrm, + Word16 *Rsubband, /* Q3 */ + const Word16 num_env_bands, + const Word16 nb_sfm, + const Word16 core_sfm +); + +Word16 calc_nor_delta_hf_fx( + Encoder_State_fx *st, + const Word32 *t_audio, + Word16 *ynrm, + Word16 *Rsubband, + const Word16 num_env_bands, + const Word16 nb_sfm, + const Word16 *sfmsize, + const Word16 *sfm_start, + const Word16 core_sfm +); + +void HQ_FEC_processing_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word32 *t_audio_q_fx, /* o : MDCT coeffs. (for synthesis) Q12 */ + Word16 is_transient, /* i : Old flag for transient */ + Word32 ynrm_values_fx[][MAX_PGF], /* i : Old average Norm values for each group of bands Q12 */ + Word32 r_p_values_fx[][MAX_ROW], /* i : Computed y-intercept and slope by Regression Q5 */ + Word16 num_Sb, /* i : Number of sub-band group */ + Word16 nb_sfm, /* i : Number of sub-band */ + Word16 *Num_bands_p, /* i : Number of coeffs. for each sub-band */ + Word16 output_frame, /* i : Frame size */ + const Word16 *sfm_start, /* i : Start of bands */ + const Word16 *sfm_end /* i : End of bands */ +); + +void HQ_FEC_Mem_update_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word32 *t_audio_q_fx, /*Q12*/ + Word32 *normq_fx, /*Q14*/ + Word16 *ynrm, + Word16 *Num_bands_p, + Word16 is_transient, + Word16 hqswb_clas, + Word16 c_switching_flag, + Word16 nb_sfm, + Word16 num_Sb, + Word16 *mean_en_high_fx, /*Q5*/ + Word16 hq_core_type, /* i : normal or low-rate MDCT(HQ) core */ + Word16 output_frame +); + +Word16 BitAllocF_fx ( + Word16 *y, /* i : norm of sub-vectors :Q0 */ + Word32 bit_rate, /* i : bitrate :Q0 */ + Word16 B, /* i : number of available bits :Q0 */ + Word16 N, /* i : number of sub-vectors :Q0 */ + Word16 *R, /* o : bit-allocation indicator :Q0 */ + Word16 *Rsubband_fx, /* o : sub-band bit-allocation vector :Q3 */ + const Word16 hqswb_clas, /* i : hq swb class */ + const Word16 num_env_bands /* i : Number sub bands to be encoded for HQ_SWB_BWE */ +); + +void hq_bit_allocation_fx( + const Word32 core_brate, /* i : Core bit-rate */ + const Word16 length, /* i : Frame length */ + const Word16 hqswb_clas, /* i : HQ class */ + Word16 *num_bits, /* i/o: Remaining bit budget */ + const Word16 *normqlg2, /* i : Quantized norms */ + const Word16 nb_sfm, /* i : Number sub bands to be encoded */ + const Word16 *sfmsize, /* i : Sub band bandwidths */ + Word16 *noise_level, /* o : HVQ noise level */ + Word16 *R, /* o : Bit allocation per sub band */ + Word16 *Rsubband, /* o : Fractional bit allocation */ + Word16 *sum, /* o : Sum of allocated shape bits */ + Word16 *core_sfm, /* o : Last coded band in core */ + const Word16 num_env_bands /* i : Number sub bands to be encoded for HQ_SWB_BWE */ +); + +void hvq_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 num_bits, /* i : Number of available bits */ + const Word32 core_brate, /* i : Core bit-rate */ + const Word16 *ynrm, /* i : Envelope coefficients */ + Word16 *R, /* i/o: Bit allocation/updated bit allocation */ + Word16 *noise_level, /* o : Noise level in Q15 */ + Word16 *peak_idx, /* o : Peak position vector */ + Word16 *Npeaks, /* o : Total number of peaks */ + Word32 *coefsq_norm, /* o : Output vector in Q12 */ + const Word16 core +); + +void peak_vq_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word32 *coefs_out, /* o : Output coefficient vector Q12 */ + const Word16 brate, /* i : Core bitrate */ + const Word16 num_bits, /* i : Number of bits for HVQ */ + const Word16 *ynrm, /* i : Envelope coefficients */ + Word16 *R, /* i/o: Bit allocation/updated bit allocation */ + Word16 *vq_peak_idx, /* o : Peak position vector */ + Word16 *Npeaks, /* o : Number of peaks */ + const Word16 core +); + +void hq_pred_hb_bws_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 *ynrm, /* i : norm quantization index vector */ + const Word16 length, /* i : frame length */ + const Word16 hqswb_clas, /* i : HQ SWB class */ + const Word16 *SWB_fenv /* i : SWB frequency envelopes Q1 */ +); +void hq_core_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure fx */ + Word16 synth[], /* o : output synthesis */ + Word16 *Q_synth, /* o : Q value of synth */ + const Word16 output_frame, /* i : output frame length */ + const Word16 hq_core_type, /* i : HQ core type */ + const Word16 core_switching_flag /* i : ACELP->HQ switching frame flag */ +); + +void hq_hr_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure fx */ + Word32 *L_coefsq, /* o : transform-domain coefficients Q12 */ + const Word16 length, /* i : frame length Q0 */ + Word16 num_bits, /* i : number of available bits Q0 */ + Word16 *ynrm, /* o : norm quantization index vector Q0 */ + Word16 *is_transient, /* o : transient flag Q0 */ + Word16 *hqswb_clas, /* o : HQ SWB class Q0 */ + Word16 *SWB_fenv /* o : SWB frequency envelopes Q1 */ +); + +void dequantize_norms_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 start_norm, /* i : First SDE encoded norm */ + const Word16 num_sfm, /* i : Number of norms */ + const Word16 is_transient, /* i : Transient flag */ + Word16 *ynrm, /* o : Decoded norm indices */ + Word16 *normqlg2 /* o : Log2 of decoded norms */ +); + +void huff_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 N, /* i : Number of codewords to decode */ + const Word16 buffer_len, /* i : Number of bits to read */ + const Word16 num_lengths, /* i : Number of different huffman codeword lengths */ + const Word16 *thres, /* i : Threshold of first codeword of each length */ + const Word16 *offset, /* i : Offset for first codeword */ + const Word16 *huff_tab, /* i : Huffman table order by codeword lengths */ + Word16 *index /* o : Decoded index */ +); + +Word16 hq_classifier_dec_fx( /* o : Consumed bits Q0 */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : Core bit rate Q0 */ + const Word16 length, /* i : Frame length Q0 */ + Word16 *is_transient, /* o : Transient flag Q0 */ + Word16 *hqswb_clas /* o : HQ class Q0 */ +); + +void hq_configure_bfi_fx( + Word16 *nb_sfm, /* o : Number of sub bands Q0 */ + Word16 *num_Sb, /* o : Number of FEC sub bands ? Q0 */ + Word16 *num_bands_p, /* o : FEC sub bands Q0 */ + Word16 const **sfmsize, /* o : Subband bandwidths */ + Word16 const **sfm_start, /* o : Subband start coefficients */ + Word16 const **sfm_end /* o : Subband end coefficients */ +); + +void hq_swb_harmonic_calc_norm_envelop_fx( + Word32 *L_SWB_signal, /* i : input signal Q=12*/ + Word32 *L_envelope, /* o : output envelope Q=12*/ + Word16 L_swb_norm, /* i : length of normaliztion */ + Word16 SWB_flength /* i : length of input signal */ +); + +Word16 build_nf_codebook_fx( /* o : Number of coefficients in nf codebook */ + const Word16 flag_32K_env_ho, /* i : Envelope attenuation hangover flag */ + const Word16 *coeff, /* i : Coded spectral coefficients */ + const Word16 *sfm_start, /* i : Subband start indices */ + const Word16 *sfmsize, /* i : Subband widths */ + const Word16 *sfm_end, /* i : Subband end indices */ + const Word16 last_sfm, /* i : Last coded band */ + const Word16 *R, /* i : Per-band bit allocation */ + Word16 *CodeBook, /* o : Noise-fill codebook */ + Word16 *CodeBook_mod /* o : Densified noise-fill codebook */ +); + +Word16 find_last_band_fx( /* o : index of last band */ + const Word16 *bitalloc, /* i : bit allocation */ + const Word16 nb_sfm /* i : number of possibly coded bands */ +); + +void apply_noisefill_HQ_fx( + const Word16 *R, /* i : bit allocation */ + const Word16 length, /* i : input frame length */ + const Word16 flag_32K_env_ho,/* i : envelope stability hangover flag*/ + const Word32 L_core_brate, /* i : core bit rate */ + const Word16 last_sfm, /* i : last coded subband */ + const Word16 *CodeBook, /* i : Noise-fill codebook */ + const Word16 *CodeBook_mod, /* i : Densified noise-fill codebook */ + const Word16 cb_size, /* i : Codebook length */ + const Word16 *sfm_start, /* i : Subband start coefficient */ + const Word16 *sfm_end, /* i : Subband end coefficient */ + const Word16 *sfmsize, /* i : Subband band width */ + Word16 *coeff /* i/o: coded/noisefilled spectrum */ +); + +void hvq_bwe_fine_fx( + const Word16 last_sfm, /* i : last coded subband */ + const Word16 num_sfm, /* i : total number of bands */ + const Word16 *sfm_end, /* i : Subband end coefficient */ + const Word16 *peak_idx, /* i : Peak index */ + const Word16 Npeaks, /* i : Number of peaks */ + Word16 *peak_pos, /* o : Peak positions */ + Word16 *prev_L_swb_norm, /* i/o: last normalize length */ + Word32 *L_coeff, /* i/o: coded/noisefilled normalized spectrum */ + Word16 *bwe_peaks, /* o : Positions of peaks in BWE */ + Word16 *coeff_fine /* o : HVQ BWE fine structure */ +); + +void hq_fold_bwe_fx( + const Word16 last_sfm, /* i : last coded subband Q0 */ + const Word16 *sfm_end, /* i : Subband end coefficient Q0 */ + const Word16 num_sfm, /* i : Number of subbands Q0 */ + Word16 *coeff /* i/o: coded/noisefilled normalized spectrum Q12 */ +); + +void apply_nf_gain_fx( + const Word16 nf_idx, /* i : noise fill gain index Q0 */ + const Word16 last_sfm, /* i : last coded subband Q0 */ + const Word16 *R, /* i : bit allocation Q0 */ + const Word16 *sfm_start, /* i : Subband start coefficient Q0 */ + const Word16 *sfm_end, /* i : Subband end coefficient Q0 */ + Word16 *coeff /* i/o: coded/noisefilled normalized spectrum Q12 */ +); + +void logqnorm_fx( + const Word32 *x, /* i : coefficient vector Qx */ + const Word16 qx, /* i : Q value of input */ + Word16 *k, /* o : index Q0 */ + const Word16 L, /* i : codebook length Q0 */ + const Word16 N, /* i : sub-vector size Q0 */ + const Word16 hvq_flag /* i : HVQ flag Q0 */ +); + +void logqnorm_2_fx( + const Word32 *env_fl, /* o : index */ + const Word16 L, /* i : codebook length */ + const Word16 n_env_band, /* i : sub-vector size */ + const Word16 nb_sfm, /* i : sub-vector size */ + Word16 *ynrm, + Word16 *normqlg2, + const Word32 *thren /* i : quantization thresholds */ +); + +void hvq_bwe_fx( + const Word32 *coeff, + const Word16 *coeff_fine, /* i : coded/noisefilled normalized spectrum Qin */ + const Word16 *sfm_start, /* i : Subband start coefficient Q0 */ + const Word16 *sfm_end, /* i : Subband end coefficient Q0 */ + const Word16 *sfm_len, /* i : Subband length Q0 */ + const Word16 last_sfm, /* i : last coded subband Q0 */ + const Word16 prev_hq_mode, /* i : previous hq mode Q0 */ + const Word16 *bwe_peaks, /* i : HVQ bwe peaks Q0 */ + const Word16 bin_th, /* i : HVQ transition bin Q0 */ + const Word16 num_sfm, /* i : Number of bands Q0 */ + const Word32 core_brate, /* i : Core bit-rate Q0 */ + const Word16 *R, /* i : Bit allocation */ + Word16 *norm, /* i/o: quantization indices for norms Q0 */ + Word16 *noise_level, /* i/o: noise levels for harmonic modes Q15 */ + Word16 *prev_noise_level, /* i/o: noise factor in previous frame Q15 */ + Word16 *bwe_seed, /* i/o: random seed for generating BWE input Q0 */ + Word32 *L_coeff_out, /* o : coded/noisefilled spectrum Qout*/ + const Word16 qin, + const Word16 qout +); + +void hvq_concat_bands_fx +( + const Word16 pvq_bands, /* i : Number of bands in concatenated PVQ target */ + const Word16 *sel_bnds, /* i : Array of selected high bands */ + const Word16 n_sel_bnds, /* i : Number of selected high bands */ + Word16 *hvq_band_start, /* i : Band start indices */ + Word16 *hvq_band_width, /* i : Band widths */ + Word16 *hvq_band_end /* i : Band end indices */ +); + +void noise_mix_fx( + const Word16 *coeff_fine, /* i : normalized fine structure spectrum Qin */ + const Word32 L_E, /* i : normalization factor Q17 */ + const Word32 L_normq, /* i : quantized norm Q14 */ + Word16 *seed, /* i/o: random seed Q0 */ + const Word16 istart, /* i : start coefficient Q0 */ + const Word16 iend, /* i : end coefficient Q0 */ + const Word16 noise_level, /* i : noise_level Q0 */ + Word32 *L_coeff_out, /* o : noisemixed spectrum Qout */ + const Word16 qin, + const Word16 qout +); + +Word16 noise_adjust_fx( /* o : index of noise attenuation Q0 */ + const Word16 *coeffs_norm, /* i : normalized coefficients Qx */ + const Word16 qx, /* i : Q value of coeffs_norm */ + const Word16 *bitalloc, /* i : bit allocation Q0 */ + const Word16 *sfm_start, /* i : band start Q0 */ + const Word16 *sfm_end, /* i : band end Q0 */ + const Word16 core_sfm /* i : index of the end band for core Q0 */ +); + +Word16 peak_vq_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 *coefs, /* i : Input coefficient vector Q14 */ + Word32 *coefs_out, /* o : Quantized output vector Q14 */ + const Word32 brate, /* i : Core bitrate */ + const Word16 num_bits, /* i : Number of bits for HVQ */ + const Word16 vq_peaks, /* i : Number of identified peaks */ + const Word16 *ynrm, /* i : Envelope coefficients */ + Word16 *R, /* i/o: Bit allocation/updated bit allocation */ + Word16 *vq_peak_idx, /* i : Peak index vector */ + Word32 *nf_gains /* i : Estimated noise floor gains Q14 */ +); + +Word16 hvq_enc_fx( /* o : Consumed bits */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 brate, /* i : Total bit rate */ + const Word16 hvq_bits, /* i : HVQ bit budget */ + const Word16 Npeaks, /* i : Number of peaks */ + const Word16 *ynrm, /* i : Envelope coefficients */ + Word16 *R, /* i/o: Bit allocation/updated bit allocation */ + Word16 *peaks, /* i : Peak pos. / Encoded peak pos. */ + Word32 *nf_gains, /* i/o: Noise fill gains / Quant. nf gains */ + Word16 *noise_level, /* o : Quantized noise level */ + const Word32 *pe_gains, /* i : Peak gains */ + const Word32 *coefs, /* i : spectrum coefficients in Q14 */ + Word32 *coefs_out /* o : encoded spectrum coefficients in Q14 */ +); + +void enforce_zero_for_min_envelope_fx( + const Word16 hqswb_clas, /* i : HQ coding mode Q0 */ + const Word16 *ynrm, /* i : Envelope indices Q0 */ + Word32 *L_coefsq, /* i/o: Quantized spectrum/zeroed spectrum Q12 */ + const Word16 nb_sfm, /* i : Number of coded sub bands Q0 */ + const Word16 *sfm_start, /* i : Sub band start indices Q0 */ + const Word16 *sfm_end /* i : Sub band end indices Q0 */ +); + +void apply_envelope_fx( + const Word16 *coeff, /* i : Coded/noisefilled normalized spectrum Q12 */ + const Word16 *norm, /* i : Envelope */ + const Word16 *norm_adj, /* i : Envelope adjustment Q15 */ + const Word16 num_sfm, /* i : Total number of bands */ + const Word16 last_sfm, /* i : Last coded band */ + const Word16 HQ_mode, /* i : HQ mode */ + const Word16 length, /* i : Frame length */ + const Word16 *sfm_start, /* i : Sub band start indices */ + const Word16 *sfm_end, /* i : Sub band end indices */ + Word32 *normq_v, /* o : Envelope with adjustment Q14 */ + Word32 *coeff_out, /* o : coded/noisefilled spectrum */ + const Word16 *coeff1, /* i : coded/noisefilled spectrum Q12 */ + Word32 *coeff_out1 /* o : coded/noisefilled spectrum Q12 */ +); + +void bitalloc_fx ( + Word16 *y, /* i : reordered norm of sub-vectors Q0 */ + Word16 *idx, /* i : reordered sub-vector indices Q0 */ + Word16 sum, /* i : number of available bits Q0 */ + Word16 N, /* i : number of norms Q0 */ + Word16 K, /* i : maximum number of bits per dimension Q0 */ + Word16 *r, /* o : bit-allacation vector Q0 */ + const Word16 *sfmsize, /* i : band length Q0 */ + const Word16 hqswb_clas /* i : signal classification flag Q0 */ +); + +void bitallocsum_fx( + Word16 *R, /* i : bit-allocation vector Q0 */ + const Word16 nb_sfm, /* i : number of sub-vectors Q0 */ + Word16 *sum, /* o : total number of bits allocated Q0 */ + Word16 *Rsubband, /* o : rate per subband Q3 */ + const Word16 v, /* i : bit rate Q0 */ + const Word16 length, /* i : length of spectrum (32 or 48 kHz samplerate) Q0 */ + const Word16 *sfmsize /* i : band length Q0 */ +); + +void env_adj_fx +( + const Word16 *pulses, /* i : number of pulses per band Q0 */ + const Word16 length, /* i : length of spectrum Q0 */ + const Word16 last_sfm, /* i : index of the last band Q0 */ + Word16 *adj, /* o : adjustment factors for the envelope Q15 */ + const Word16 env_stab, /* i : envelope stability Q15 */ + const Word16 *sfmsize /* i : subband sizes Q0 */ +); + +Word16 env_stability_fx( /* in Q15 */ + const Word16 *ynrm, /*i: Norm vector for current frame */ + const Word16 nb_sfm, /*i: Number of sub-bands */ + Word16 *mem_norm, /*i/o: Norm vector memory from past frame */ + Word16 *mem_env_delta /*i/o: Envelope stability memory for smoothing in Q11 */ +); + +Word16 env_stab_smo_fx( /* Q0 */ + Word16 env_stab, /*i : env_stab value Q15 */ + Word16 *env_stab_state_p, /*i/o: env_stab state probabilities Q15 */ + Word16 *ho_cnt /*i/o: hangover counter for speech state */ +); + +void env_stab_transient_detect_fx( + const Word16 is_transient, /* i: Transient flag */ + const Word16 length, /* i : Length of spectrum (32 or 48 kHz) */ + const Word16 norm[], /* i : quantization indices for norms */ + Word16 *no_att_hangover, /* i/o: Frame counter for attenuation hangover (Q0) */ + Word32 *L_energy_lt, /* i/o: Long-term energy measure for transient detection (Q13) */ + const Word16 HQ_mode, /* i : HQ coding mode */ + const Word16 bin_th, /* i : HVQ cross-over frequency bin */ + const Word32 *L_coeff, /* i : Coded spectral coefficients */ + const Word16 Qcoeff /* i : Q of coded spectral coefficients */ +); + +void hq_configure_fx( + const Word16 length, /* i : Frame length Q0 */ + const Word16 hqswb_clas, /* i : HQ SWB class Q0 */ + const Word32 core_brate, /* i : Codec bitrate Q0 */ + Word16 *num_sfm, /* o : Total number of subbands Q0 */ + Word16 *nb_sfm, /* o : Total number of coded bands Q0 */ + Word16 *start_norm, /* o : First norm to be SDE encoded Q0 */ + Word16 *num_env_bands, /* o : Number coded envelope bands Q0 */ + Word16 *numnrmibits, /* o : Number of bits in fall-back norm encoding Q0 */ + Word16 *hq_generic_offset, /* o : Freq offset for HQ GENERIC Q0 */ + Word16 const **sfmsize, /* o : Subband bandwidths Q0 */ + Word16 const **sfm_start, /* o : Subband start coefficients Q0 */ + Word16 const **sfm_end /* o : Subband end coefficients Q0 */ +); + +Word16 hvq_pvq_bitalloc_fx( + Word16 num_bits, /* i/o: Number of available bits (including gain bits) */ + const Word32 brate, /* i : bitrate */ + const Word16 bwidth_fx, /* i : Encoded bandwidth */ + const Word16 *ynrm, /* i : Envelope coefficients */ + const Word32 manE_peak, /* i : Peak energy mantissa */ + const Word16 expE_peak, /* i : Peak energy exponent */ + Word16 *Rk, /* o : bit allocation for concatenated vector */ + Word16 *R, /* i/o: Global bit allocation */ + Word16 *sel_bands, /* o : Selected bands for encoding */ + Word16 *n_sel_bands /* o : No. of selected bands for encoding */ +); + +void disf_ns_28b_fx( + Word16 *indice, + Word16 *isf_q +); + +void isf_enc_amr_wb_fx( + Encoder_State_fx *st, /* i/o: state structure */ + Word16 *isf_new, /* o : quantized ISF vector */ + Word16 *isp_new, /* i/o: ISP vector to quantize/quantized */ + Word16 *Aq, /* o : quantized A(z) for 4 subframes */ + Word16 *stab_fac /* o : ISF stability factor */ +); + +void pvq_encode_fx( + Encoder_State_fx *st_fx, + const Word16 *x, /* i: vector to quantize Q15-3=>Q12 */ + Word16 *y, /* o: raw pulses (non-scaled short) Q0 */ + Word16 *xq, /* o: quantized vector Q15 */ + Word32 *L_xq, /* o: quantized vector Q31 */ + const Word16 pulses, /* i: number of allocated pulses */ + const Word16 dim, /* i: Length of vector */ + const Word16 neg_gain /* i: - Gain use - negative gain in Q15 0 ..1 */ +); + +void pvq_decode_fx( + Decoder_State_fx *st_fx, + Word16 *xq, /* o: decoded vector (Q15) */ + Word16 *y, /* o: decoded vector (non-scaled int) */ + const Word16 k_val, /* i: number of allocated pulses */ + const Word16 dim, /* i: Length of vector */ + const Word16 neg_gain /* i: Gain (negated to fit 1.0 in Q15 as -1.0) */ +); + +UWord32 intLimCDivPos_fx( + UWord32 NUM, + Word16 DEN +); + +Word32 intLimCDivSigned_fx( + Word32 NUM, + Word16 DEN +); + +Word16 shrtCDivSignedApprox( + const Word16 num, + const Word16 den +); +void de_interleave_spectrum_fx( + Word32 *coefs, /* i/o: input and output coefficients Q? */ + const Word16 length /* i : length of spectrum Q0 */ +); + +void interleave_spectrum_fx( + Word32 *coefs, /* i/o: input and output coefficients Q? */ + const Word16 length /* i : length of spectrum Q0 */ +); + +void recovernorm_fx( + Word16 *idxbuf, /* i : reordered quantization indices */ + Word16 *ynrm, /* o : recovered quantization indices */ + Word16 *normqlg2, /* o : recovered quantized norms */ + Word16 nb_sfm /* i : number of SFMs */ +); + +void map_quant_weight_fx( + const Word16 normqlg2[], /* i : quantized norms */ + Word16 wnorm[], /* o : weighted norm */ + const Word16 is_transient /* i : transient flag */ +); + +void fill_spectrum_fx( + Word16 *coeff, /* i/o: normalized MLT spectrum / nf spectrum Q12 */ + Word32 *L_coeff_out, /* i/o: Noisefilled MLT spectrum Q12 */ + const Word16 *R, /* i : number of pulses per band Q0 */ + const Word16 is_transient, /* i : transient flag Q0 */ + Word16 norm[], /* i : quantization indices for norms Q0 */ + const Word16 *hq_generic_fenv, /* i : HQ GENERIC envelope Q1 */ + const Word16 hq_generic_offset, /* i : HQ GENERIC offset Q0 */ + const Word16 nf_idx, /* i : noise fill index Q0 */ + const Word16 length, /* i : Length of spectrum (32 or 48 kHz) Q0 */ + const Word16 env_stab, /* i : Envelope stability measure [0..1] Q15 */ + Word16 *no_att_hangover, /* i/o: Frame counter for attenuation hangover Q0 */ + Word32 *L_energy_lt, /* i/o: Long-term energy measure for transient detection Q13 */ + Word16 *bwe_seed, /* i/o: random seed for generating BWE input Q0 */ + const Word16 hq_generic_exc_clas, /* i : BWE excitation class Q0 */ + const Word16 core_sfm, /* i : index of the end band for core Q0 */ + const Word16 HQ_mode, /* i : HQ mode Q0 */ + Word16 noise_level[], /* i : noise levels for harmonic modes Q15 */ + const Word32 L_core_brate, /* i : target bit-rate Q0 */ + Word16 prev_noise_level[], /* i/o: noise factor in previous frame Q15 */ + Word16 *prev_R, /* i/o: bit allocation info. in previous frame Q0 */ + Word32 *prev_coeff_out, /* i/o: decoded spectrum in previous frame Q12 */ + const Word16 *peak_idx, /* i : peak indices for hvq Q0 */ + const Word16 Npeaks, /* i : number of peaks in hvq Q0 */ + const Word16 *npulses, /* i : number of pulses per band Q0 */ + const Word16 prev_is_transient, /* i : previous transient flag Q0 */ + Word32 *prev_normq, /* i/o: previous norms Q14 */ + Word32 *prev_env, /* i/o: previous noise envelopes Q(prev_env_Q) */ + const Word16 prev_bfi, /* i : previous bad frame indicator Q0 */ + const Word16 *sfmsize, /* i : Length of bands Q0 */ + const Word16 *sfm_start, /* i : Start of bands Q0 */ + const Word16 *sfm_end, /* i : End of bands Q0 */ + Word16 *prev_L_swb_norm, /* i/o: HVQ/Harmonic mode normalization length Q0 */ + const Word16 prev_hq_mode, /* i : Previous HQ mode Q0 */ + const Word16 num_sfm, /* i : Total number of bands Q0 */ + Word16 *prev_env_Q, + const Word16 num_env_bands +); + +Word16 FEC_pos_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 coder_type, /* i : coder type */ + const Word16 last_good, /* i : last good classfication */ + Word16 *last_pulse_pos, /* o : last glotal pulse position in the lost ACB */ + Word16 *clas, /* o : decoded classification */ + Word32 *enr_q, /* o : decoded energy in Q0 */ + const Word32 core_brate /* i : decoded bitrate */ +); + +void pit16k_Q_dec_fx( + const Word16 pitch_index, /* i : pitch index */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) limits */ + Word16 *T0, /* o : integer pitch lag */ + Word16 *T0_frac, /* o : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* i/o: delta search max */ + ,Word16 *BER_detect /* o : BER detect flag */ +); + +Word16 frame_ener_fx( + const Word16 L_frame, /* i : length of the frame */ + const Word16 clas, /* i : frame classification */ + const Word16 *synth, /* i : synthesized speech at Fs = 12k8 Hz Q_new */ + const Word16 pitch, /* i : pitch period Q0 */ + Word32 *enr_q, /* o : pitch-synchronous or half_frame energy Q0 */ + const Word16 offset, /* i : speech pointer offset (0 or L_FRAME) */ + const Word16 Q_new, /* i : Scaling factor */ + Word16 shift, /* i : Shift need to obtain 12 bits vectors */ + const Word16 enc /* i : Encoder/decoder */ +); + +Word16 frame_energy_fx( /* o : Frame erergy in Q8 */ + Word16 L_frame, + const Word16 *pitch, /* i : pitch values for each subframe Q6 */ + const Word16 *speech, /* i : pointer to speech signal for E computation Q_syn*/ + const Word16 lp_speech, /* i : long term active speech energy average Q8 */ + Word16 *frame_ener, /* o : pitch-synchronous energy at frame end Q8 */ + const Word16 Q_syn /* i : Synthesis scaling */ +); + +void int_lsp_fx( + const Word16 L_frame, /* i : length of the frame */ + const Word16 lsp_old[], /* i : LSPs from past frame */ + const Word16 lsp_new[], /* i : LSPs from present frame */ + Word16 *Aq, /* o : LP coefficients in both subframes */ + const Word16 m, /* i : order of LP filter */ + const Word16 *int_coeffs, /* i : interpolation coefficients */ + const Word16 Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */ +); + +void reorder_isf_fx( + Word16 *isf, /* i/o: ISFs in the frequency domain (0..0.5) */ + const Word16 min_dist, /* i : minimum required distance */ + const Word16 n, /* i : LPC order */ + const Word16 fs /* i : sampling frequency */ +); + +void reorder_lsf_fx( + Word16 *lsf, /* i/o: LSFs in the frequency domain (0..0.5) Q(x2.56)*/ + const Word16 min_dist, /* i : minimum required distance x2.56*/ + const Word16 n, /* i : LPC order */ + const Word32 fs /* i : sampling frequency */ +); + +Word16 FEC_synchro_exc_fx( /* o : do_WI flag */ + const Word16 L_frame, /* i : length of the frame */ + Word16 *exc, /* i/o: exc vector to modify */ + const Word16 desire_puls_pos, /* i : Pulse position send by the encoder */ + const Word16 true_puls_pos, /* i : Present pulse location */ + const Word16 Old_pitch /* i : Pitch use to create temporary adaptive codebook */ +); + +Word16 findpulse_fx( /* o : pulse position */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 res[], /* i : Residual signal <12 bits */ + const Word16 T0, /* i : Pitch estimation Q0 */ + const Word16 enc, /* i : enc = 1 -> encoder side; enc = 0 -> decoder side */ + Word16 *sign /* i/o: sign of the maximum */ +); + +void FEC_exc_estim_fx( + Decoder_State_fx *st_fx, /* i/o: Decoder static memory */ + const Word16 L_frame, /* i : length of the frame */ + Word16 *exc, /* o : pointer to excitation buffer (with past) */ + Word16 *exc2, /* o : total excitation (for synthesis) */ + Word16 dct_exc_tmp[], /* o : GSC excitation in DCT domain */ + Word16 *pitch_buf, /* o : Floating pitch for each subframe */ + Word16 *voice_factors, /* o : voicing factors */ + Word16 *tmp_tc, /* o : FEC pitch Q6 */ + Word16 *bwe_exc, /* o : excitation for SWB TBE */ + Word16 *lsf_new, /* i : ISFs at the end of the frame */ + Word16 *Q_exc, + Word16 *tmp_noise /* o : long-term noise energy Q0 */ +); + +void FEC_lsf2lsp_interp( + Decoder_State_fx *st, /* i/o: Decoder static memory */ + const Word16 L_frame, /* i : length of the frame */ + Word16 *Aq, /* o : calculated A(z) for 4 subframes */ + Word16 *lsf, /* o : estimated LSF vector */ + Word16 *lsp /* o : estimated LSP vector */ +); +void FEC_lsf_estim_enc_fx( + Encoder_State_fx *st_fx, /* i : Encoder static memory */ + const Word16 L_frame, /* i : length of the frame */ + Word16 *lsf /* o : estimated LSF vector */ +); + +void FEC_clas_estim_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state handle */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ /*A*/ + const Word16 L_frame, /* i : length of the frame */ + Word16 *clas, /* i/o: frame classification */ + const Word16 coder_type, /* i : coder type */ + const Word16 *pitch, /* i : pitch values for each subframe (Q6) */ + Word16 *syn, /* i : synthesis buffer */ + Word16 *lp_speech, /* i/o: long term active speech energy average Q8 */ + Word16 *decision_hyst, /* i/o: hysteresis of the music/speech decision */ /*A*/ + Word16 *UV_cnt, /* i/o: number of consecutives frames classified as UV */ /*A*/ + Word16 *LT_UV_cnt, /* i/o: long term consecutives frames classified as UV */ /*A*/ + Word16 *Last_ener, /* i/o: last_energy frame */ /*A*/ + Word16 *locattack, /* i/o: detection of attack (mainly to localized speech burst) */ /*A*/ + Word16 *lt_diff_etot, /* i/o: long-term total energy variation */ /*A*/ + Word16 *amr_io_class, /* i/o: classification for AMR-WB IO mode */ /*A*/ + const Word32 bitrate, /* i : Decoded bitrate */ /*A*/ + Word16 Q_syn, /* i : Synthesis scaling */ + Word16 *class_para, /* o : classification para. fmerit1 */ /*A*/ + Word16 *mem_syn_clas_estim, /* i/o: memory of the synthesis signal for frame class estimation */ + Word16 *Q_mem_syn, /*i/o : exponent for memory of synthesis signal for frame class estimation */ /*B*/ + Word16 LTP_Gain, /* i : LTP gain is 0..0.6 or negative Q15*/ /*B*/ + Word16 mode, /* i : signal classifier mode *//*B*/ + Word16 bfi, /* i : bad frame indicator *//*B*/ + Word32 last_core_brate /* i : bitrate of previous frame */ +); + +void non_linearity_fx( + const Word16 input[], /* i : input signal Q_inp */ + Word32 output[], /* o : output signal 2*Q_inp */ + const Word16 length, /* i : input length */ + Word32 *prev_scale, /* i/o: memory Q30 */ + Word16 Q_inp, + Word16 coder_type, /* i : Coder Type */ + Word16 *voice_factors, /* i : Voice Factors */ + const Word16 L_frame /* i : ACELP frame length */ +); + +void stat_noise_uv_dec_fx( + Decoder_State_fx *st_fx, /* i/o: Decoder static memory */ + const Word16 coder_type, /* i : coding type */ + Word16 *lsp_new, /* i : end-frame LSP vector */ + Word16 *lsp_mid, /* i : mid-frame LSP vector */ + Word16 *Aq, /* o : A(z) quantized for the 4 subframes */ + Word16 *exc2 /* i/o: excitation buffer */ +); + +void stat_noise_uv_mod_fx( + const Word16 coder_type, /* i : Coder type */ + Word16 noisiness, /* i : noisiness parameter */ + const Word16 *lsp_old, /* i : old LSP vector at 4th sfr */ + const Word16 *lsp_new, /* i : LSP vector at 4th sfr */ + const Word16 *lsp_mid, /* i : LSP vector at 2nd sfr */ + Word16 *Aq, /* o : A(z) quantized for the 4 subframes */ + Word16 *exc2, /* i/o: excitation buffer */ + Word16 Q_exc, /* i : Q of exc2 excitation buffer [11..-1] expected */ + const Word16 bfi , /* i : Bad frame indicator */ + Word32 *ge_sm, /* i/o: smoothed excitation gain */ + Word16 *uv_count, /* i/o: unvoiced counter */ + Word16 *act_count, /* i/o: activation counter */ + Word16 lspold_s[], /* i/o: old LSP */ + Word16 *noimix_seed, /* i/o: mixture seed */ + Word16 *st_min_alpha, /* i/o: minimum alpha */ + Word16 *exc_pe, /* i/o: scale Q_stat_noise */ + const Word32 bitrate, /* i : core bitrate */ + const Word16 bwidth_fx, /* i : input bandwidth */ + Word16 *Q_stat_noise, /* i/o: noise scaling */ + Word16 *Q_stat_noise_ge /* i/o: noise scaling */ +); + +/* Just call preemph_copy_fx(), it does the same thing and that saves PROM */ +#define preemph_fx(signal,mu,L,mem) preemph_copy_fx((signal),(signal),(mu),(L),(mem)) + +void preemph_copy_fx( + const Word16 x[], /* i : input signal Qx */ + Word16 y[], /* o : output signal Qx */ + const Word16 mu, /* i : preemphasis coefficient Q15 */ + const Word16 lg, /* i : vector size Q0 */ + Word16 *mem /* i/o: memory (x[-1]) Qx */ +); + +Word16 vquant_fx( /* o: index of the winning codevector */ + Word16 x[], /* i: vector to quantize Q13 */ + const Word16 x_mean[], /* i: vector mean to subtract (0 if none)Q13*/ + Word16 xq[], /* o: quantized vector Q13 */ + const Word16 cb[], /* i: codebook Q13 */ + const Word16 dim, /* i: dimension of codebook vectors */ + const Word16 cbsize /* i: codebook size */ +); + +Word16 w_vquant_fx( + Word16 x[], /* i: vector to quantize in Q10 */ + Word16 Qx, + const Word16 weights[], /* i: error weights in Q0 */ + Word16 xq[], /* o: quantized vector in Q15 */ + const Word16 cb[], /* i: codebook in Q15 */ + const Word16 cbsize, /* i: codebook size */ + const Word16 rev_vect /* i: reverse codebook vectors */ +); + +void Vr_subt( + const Word16 x1[], /* i : Input vector 1 */ + const Word16 x2[], /* i : Input vector 2 */ + Word16 y[], /* o : Output vector that contains vector 1 - vector 2 */ + Word16 N /* i : Vector lenght */ +); + +Word16 gsc_gainQ_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 y_gain4[], /* i : Energy per band Q13 */ + Word16 y_gainQ[], /* o : quantized energy per band Q13 */ + const Word32 core_brate, /* i : Core rate */ + const Word16 coder_type, /* i : coding type */ + const Word16 bwidth /* i : input signal bandwidth */ +); + +Word16 emaximum_fx( /* o : return index with max energy value in vector Q0 */ + const Word16 Qvec, /* i : Q of input vector Q0 */ + const Word16 *vec, /* i : input vector Qx */ + const Word16 lvec, /* i : length of input vector Q0 */ + Word32 *ener_max /* o : maximum energy value Q0 */ +); + +void set16_fx( + Word16 y[], /* i/o: Vector to set */ + const Word16 a, /* i : Value to set the vector to */ + const Word16 N /* i : Lenght of the vector */ +); + +void set32_fx( + Word32 y[], /* i/o: Vector to set */ + const Word32 a, /* i : Value to set the vector to */ + const Word16 N /* i : Lenght of the vector */ +); + +void Copy( + const Word16 x[], /* i : input vector */ + Word16 y[], /* o : output vector */ + const Word16 L /* i : vector length */ +); + +void Copy32( + const Word32 x[], /* i : input vector */ + Word32 y[], /* o : output vector */ + const Word16 L /* i : vector length */ +); + +void Scale_sig32( + Word32 x[], /* i/o: signal to scale Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +); + +void Copy_Scale_sig( + const Word16 x[], /* i : signal to scale input Qx */ + Word16 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +); + +void Copy_Scale_sig_16_32( + const Word16 x[], /* i : signal to scale input Qx */ + Word32 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +); + +void Copy_Scale_sig_32_16( + const Word32 x[], /* i : signal to scale input Qx */ + Word16 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +); + +void init_lvq_fx( + Word32 offset_scale1[][MAX_NO_SCALES+1], + Word32 offset_scale2[][MAX_NO_SCALES+1], + Word32 offset_scale1_p[][MAX_NO_SCALES+1], + Word32 offset_scale2_p[][MAX_NO_SCALES+1], + Word16 no_scales[][2], + Word16 no_scales_p[][2] +); + +void hf_synth_reset_fx( + Word16 *seed2, /* i/o: random seed for HF noise gen */ + Word16 mem_hf[], /* o : HF band-pass filter memory */ + Word16 mem_syn_hf[], /* o : HF synthesis memory */ + Word16 mem_hp400[], /* o : memory of hp 400 Hz filter */ + Word16 mem_hp_interp[], /* o : interpol. memory */ + Word16 delay_syn_hf[] /* o : HF synthesis memory */ +); + +void hf_synth_init_fx( + Word16 mem_hp400[], /* o : 400 Hz high pass filter memory initialization */ + Word16 mem_hf[] /* o : band pass 6kHz to 7kHz FIR filter initialization */ +); + +Word16 Random( /* o : output random value */ + Word16 *seed /* i/o: random seed */ +); + +Word16 own_random2_fx( /* o : output random value */ + Word16 seed /* i : random seed */ +); + +void Random_Fill( + Word16 *seed, /* i/o: random seed */ + Word16 n, /* i : number of values */ + Word16 *y, /* o : output values */ + Word16 scaling /* i : scaling of values */ +); + +void iDiv_and_mod_32( + const Word32 Numer, /* i : 32 bits numerator */ + const Word16 Denom, /* i : 16 bits denominator */ + Word32 * Int_quotient, /* o : integer result of the division (int)(num/den) */ + Word32 * Int_mod, /* o : modulo result of the division num-((int)(num/den)*den)*/ + const Word16 rshift /* i : 0 if no right shift / 1 if the denom is right shifted by 1*/ +); + +void lsf2lsp_fx( + const Word16 lsf[], /* i : lsf[m] normalized (range: 0.0<=val<=0.5) x2.56 */ + Word16 lsp[], /* o : lsp[m] (range: -1<=val<1) Q15 */ + const Word16 m, /* i : LPC order Q0 */ + Word32 int_fs +); + +void bass_psfilter_init_fx( + Word16 old_syn[], /* o : Old synthesis buffer 1 */ + Word16 *mem_deemph_err, /* o : Error deemphasis memory */ + Word16 *lp_ener /* o : long_term error signal energy */ +); + +void decod_gen_voic_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + const Word16 L_frame_fx, /* i : length of the frame */ + const Word16 sharpFlag_fx, /* i : formant sharpening flag */ + const Word16 *Aq_fx, /* i : LP filter coefficient */ + const Word16 coder_type_fx, /* i : coding type */ + const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */ + const Word16 do_WI_fx, /* i : do interpolation after a FER */ + Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe */ + Word16 *voice_factors_fx, /* o : voicing factors */ + Word16 *exc_fx, /* i/o: adapt. excitation exc */ + Word16 *exc2_fx, /* i/o: adapt. excitation/total exc */ + Word16 *bwe_exc_fx, /* o : excitation for SWB TBE */ + Word16 *unbits, /* number of unused bits */ + Word16* gain_buf /*Q14*/ +); + +Word16 tc_classif_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 L_frame /* i : length of the frame */ +); + +void transition_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 coder_type, /* i : coder type */ + const Word16 tc_subfr, /* i : TC subframe index */ + Word16 *Jopt_flag, /* i : joint optimization flag */ + Word16 *exc, /* o : excitation signal */ + Word16 *T0, /* o : close loop integer pitch */ + Word16 *T0_frac, /* o : close loop fractional part of the pitch */ + Word16 *T0_min, /* i/o: delta search min for sf 2 & 4 */ + Word16 *T0_max, /* i/o: delta search max for sf 2 & 4 */ + Word16 **pt_pitch, /* o : floating pitch values */ + Word16 *position, /* i/o: first glottal impulse position in frame */ + Word16 *bwe_exc, /* o : excitation for SWB TBE */ + Word16 *Q_exc /*i/o : scaling of excitation */ +); + +void decod_tran_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + const Word16 L_frame_fx, /* i : length of the frame */ + const Word16 tc_subfr_fx, /* i : TC subframe index */ + const Word16 *Aq_fx, /* i : LP filter coefficient */ + const Word16 coder_type_fx, /* i : coding type */ + const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */ + Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe */ + Word16 *voice_factors_fx, /* o : voicing factors */ + Word16 *exc_fx, /* i/o: adapt. excitation exc */ + Word16 *exc2_fx, /* i/o: adapt. excitation/total exc */ + Word16 *bwe_exc_fx, /* i/o: excitation for SWB TBE */ + Word16 *unbits, /* i/o: number of unused bits */ + const Word16 sharpFlag, /* i : formant sharpening flag */ + Word16 *gain_buf /*Q14*/ +); + +void interp_code_4over2_fx( + const Word16 inp_code_fx[], /* i : input vector Qx */ + Word16 interp_code_fx[], /* o : output vector Qx */ + const Word16 inp_length /* i : length of input vector */ +); + +void pred_lt4_tc_fx( + Word16 exc[], /* i/o: excitation buffer */ + const Word16 T0, /* i : integer pitch lag */ + Word16 frac, /* i: fraction of lag */ + const Word16 *win, /* i : interpolation window */ + const Word16 imp_pos, /* i : glottal impulse position */ + const Word16 i_subfr /* i : subframe index */ +); + +void gaus_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + const Word32 core_brate, /* i */ /*1 : core bitrate */ + const Word16 i_subfr, /* i */ /*2 : subframe index */ + Word16 *code, /* o */ /*3 : unvoiced excitation Q12 */ + Word32 *L_norm_gain_code, /* o */ /*4 : gain of normalized gaussian excitation Q16 */ + Word16 *lp_gainp, /* i/o */ /*5 : lp filtered pitch gain(FER) Q14 */ + Word16 *lp_gainc, /* i/o */ /*6 : lp filtered code gain (FER) Q3 */ + Word16 *inv_gain_inov, /* o */ /*7 : unscaled innovation gain Q12 */ + Word16 *tilt_code, /* o */ /*8 : synthesis excitation spectrum tilt Q15 */ + Word16 *voice_fac, /* o */ /*9 : estimated voicing factor Q15 */ + Word16 *gain_pit, /* o */ /*10 : pitch gain Q14 */ + Word16 *pt_pitch_1, /* o */ /*11 : floating pitch buffer Q6 */ + Word16 *exc, /* o */ /*12 : excitation signal frame */ + Word32 *L_gain_code, /* o */ /*13 : gain of the gaussian excitation Q16 */ + Word16 *exc2, /* o */ /*14 : Scaled excitation signal frame */ + Word16 *bwe_exc_fx, + Word16 *sQ_exc, /* i/o */ /*15 : Excitation scaling factor (Decoder state) */ + Word16 *sQsubfr /* i/o */ /*16 : Past excitation scaling factors (Decoder State) */ +); + +void decod_unvoiced_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + const Word16 *Aq_fx, /* Q12 i : LP filter coefficient */ + const Word16 coder_type_fx, /* Q0 i : coding type */ + Word16 *tmp_noise_fx, /* Q5 o : long term temporary noise energy */ + Word16 *pitch_buf_fx, /* Q6 o : floating pitch values for each subframe */ + Word16 *voice_factors_fx, /* Q15 o : voicing factors */ + Word16 *exc_fx, /* Q_X o : adapt. excitation exc */ + Word16 *exc2_fx, /* Q_X o : adapt. excitation/total exc */ + Word16 *bwe_exc_fx, /* Q_X i/o: excitation for SWB TBE */ + Word16 *gain_buf +); + +Word32 gain_dec_gaus_fx( /* o : quantized codebook gain Q16 */ + Word16 index, /* i : quantization index */ + const Word16 bits, /* i : number of bits to quantize */ + const Word16 lowBound, /* i : lower bound of quantizer (dB) */ + const Word16 topBound, /* i : upper bound of quantizer (dB) */ + const Word16 inv_gain_inov, /* o : unscaled innovation gain Q12 */ + Word32 *L_norm_gain_code /* o : gain of normalized gaussian excitation Q16 */ +); + +void AVQ_demuxdec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 xriq[], /* o: decoded subvectors [0..8*Nsv-1] */ + Word16 *nb_bits, /* i/o: number of allocated bits */ + const Word16 Nsv, /* i: number of subvectors */ + Word16 nq_out[] /* i/o: AVQ nq index */ +); + +void re8_decode_base_index_fx(Word16 n, UWord16 I, Word16 *x); + +void re8_k2y_fx( + const Word16 *k, /* i : Voronoi index k[0..7] */ + const Word16 m, /* i : Voronoi modulo (m = 2^r = 1<=2) */ + Word16 *y /* o : 8-dimensional point y[0..7] in RE8 */ +); + +void re8_vor_fx( + const Word16 y[], /* i : point in RE8 (8-dimensional integer vector) */ + Word16 *n, /* o : codebook number n=0,2,3,4,... (scalar integer) */ + Word16 k[], /* o : Voronoi index (integer vector of dimension 8) used only if n>4*/ + Word16 c[], /* o : codevector in Q0, Q2, Q3, or Q4 if n<=4, y=c */ + Word16 *ka /* o : identifier of absolute leader (to index c) */ +); + +void re8_cod_fx( + Word16 x[], /* i : point in RE8 (8-dimensional integer vector) */ + Word16 *n, /* i : codebook number (*n is an integer defined in {0,2,3,4,..,n_max}) */ + UWord16 *I, /* o : index of c (pointer to unsigned 16-bit word) */ + Word16 k[] /* o : index of v (8-dimensional vector of binary indices) = Voronoi index */ +); + +void re8_PPV_fx( + const Word32 x[], /* i : point in R^8Q15 */ + Word16 y[] /* o : point in RE8 (8-dimensional integer vector) */ +); + +void re8_dec_fx( + Word16 n, /* i : codebook number (*n is an integer defined in {0,2,3,4,..,n_max}) */ + const UWord16 I, /* i : index of c (pointer to unsigned 16-bit word) */ + const Word16 k[], /* i : index of v (8-dimensional vector of binary indices) = Voronoi index */ + Word16 y[] /* o : point in RE8 (8-dimensional integer vector) */ +); + +void gain_dec_SQ_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 coder_type, /* i : coding type */ + const Word16 i_subfr, /* i : subframe number */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 *code, /* i : algebraic code excitation Q12*/ + const Word16 Es_pred, /* i : predicted scaled innov. energy Q8 */ + Word16 *gain_pit, /* o : Quantized pitch gain Q14*/ + Word32 *gain_code, /* o : Quantized codeebook gain Q16*/ + Word16 *gain_inov, /* o : unscaled innovation gain Q12*/ + Word32 *norm_gain_code /* o : norm. gain of the codebook excitation Q16*/ +); + +void gain_dec_amr_wb_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + Word16 *gain_pit, /* o : Quantized pitch gain */ + Word32 *gain_code, /* o : Quantized codeebook gain */ + Word16 *past_qua_en, /* i/o: gain quantization memory (4 words) */ + Word16 *gain_inov, /* o : unscaled innovation gain */ + const Word16 *code, /* i : algebraic code excitation */ + Word32 *norm_gain_code /* o : norm. gain of the codebook excitation */ +); + +void isf_dec_amr_wb_fx( + Decoder_State_fx *st, /* i/o: State structure */ + Word16 *Aq, /* o : quantized A(z) for 4 subframes */ + Word16 *isf_new, /* o : de-quantized ISF vector */ + Word16 *isp_new /* o : de-quantized ISP vector */ +); + +void syn_output_fx( + const Word16 codec_mode, /* i : MODE1 or MODE2 */ + Word16 *synth, /* i/o: float synthesis signal */ + const Word16 output_frame, /* i : output frame length */ + Word16 *synth_out, /* o : integer 16 bits synthesis signal */ + const Word16 Q_syn2 /* i : Synthesis scaling factor */ +); + +void amr_wb_dec_fx( + Word16 output_sp[], /* o : synthesis output */ + Decoder_State_fx *st_fx /* o : Decoder static variables structure */ +); + +void decod_amr_wb_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + const Word16 *Aq_fx, /* i : LP filter coefficients */ + Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe */ + Word16 *exc_fx, /* i/o: adapt. excitation exc */ + Word16 *exc2_fx, /* i/o: adapt. excitation/total exc */ + Word16 hf_gain_fx[NB_SUBFR], /* o : decoded HF gain */ + Word16 *voice_factors_fx, /* o : voicing factors */ + Word16 *gain_buf /*Q14*/ +); + +void disf_2s_46b_fx( + Word16 *indice, /* i : quantized indices (use indice[0] = -1 in the decoder) */ + Word16 *isf_q, /* o : quantized ISFs in the cosine domain */ + Word16 *mem_AR, /* o : quantizer memory for AR model */ + Word16 *mem_MA, /* i/o: quantizer memory for MA model */ + const Word16 enc_dec /* i : encoder (0), decoder (1) G722.2 FER */ +); + +void disf_2s_36b_fx( + Word16 *indice, /* i : quantized indices (use indice[0] = -1 in the decoder) */ + Word16 *isf_q, /* o : quantized ISFs in the cosine domain */ + Word16 *mem_AR, /* i/o: quantizer memory for AR model */ + Word16 *mem_MA, /* i/o: quantizer memory for MA model */ + const Word16 enc_dec /* i : encoder (0), decoder (1) G722.2 FER */ +); + +void transf_cdbk_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 coder_type, /* i : coding type */ + const Word16 harm_flag_acelp,/* i : harmonic flag for higher rates ACELP */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 Es_pred, /* i : predicited scaled innovation energy (Q8) */ + const Word32 gain_code, /* i : innovative excitation gain (Q16) */ + Word16 *mem_preemp, /* i/o: dequantizer preemhasis memory */ + Word16 *gain_preQ, /* o : prequantizer excitation gain (Q2) */ + Word32 *norm_gain_preQ,/* o : normalized prequantizer excitation gain (Q16) */ + Word16 code_preQ[], /* o : prequantizer excitation (Q8) */ + Word16 *unbits /* o : number of AVQ unused bits */ +); + +void gain_enc_SQ_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 coder_type, /* i : coding type */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 *xn, /* i : target vector Q_xn */ + const Word16 *yy1, /* i : zero-memory filtered adaptive excitation Q_xn */ + const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation Q9 */ + const Word16 *code, /* i : algebraic excitation Q9 */ + const Word16 Es_pred, /* i : predicted scaled innovation energy Q8 */ + Word16 *gain_pit, /* o : quantized pitch gain Q14 */ + Word32 *gain_code, /* o : quantized codebook gain Q16 */ + Word16 *gain_inov, /* o : gain of the innovation (used for normalization) Q12 */ + Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation Q16 */ + Word16 *g_corr, /* i/o: correlations , -2,, -2 and 2 */ + const Word16 clip_gain, /* i : gain pitch clipping flag (1 = clipping) */ + const Word16 Q_xn /* i : xn and y1 scaling */ +); + +void AVQ_cod_fx( /* o: comfort noise gain factor */ + const Word16 xri[], /* i: vector to quantize */ + Word16 xriq[], /* o: quantized normalized vector (assuming the bit budget is enough) */ + const Word16 NB_BITS, /* i: number of allocated bits */ + const Word16 Nsv, /* i: number of subvectors (lg=Nsv*8) */ + const Word16 Q_in /* i: Scaling input */ +); + +void AVQ_encmux_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 extl, /* i : extension layer */ + Word16 xriq[], /* i/o: rounded subvectors [0..8*Nsv-1] followed + by rounded bit allocations [8*Nsv..8*Nsv+Nsv-1] */ + Word16 *nb_bits, /* i/o: number of allocated bits */ + const Word16 Nsv, /* i: number of subvectors */ + Word16 nq_out[] /* o : AVQ nq index */ +); + +Word32 Dot_product( /* o : Sum */ + const Word16 x[], /* i : 12bits: x vector */ + const Word16 y[], /* i : 12bits: y vector */ + const Word16 lg /* i : vector length */ +); + +Word16 usquant_fx( /* o: index of the winning codeword */ + const Word16 x, /* i: scalar value to quantize Qx*/ + Word16 *xq, /* o: quantized value Qx*/ + const Word16 qlow, /* i: lowest codebook entry (index 0) Qx*/ + const Word16 delta, /* i: quantization step Qx-1*/ + const Word16 cbsize /* i: codebook size */ +); + +Word16 gain_quant_fx( /* o: quantization index */ + Word32 *gain, /* i/o: quantized gain */ + Word16 *gain16, + const Word16 c_min, /* i: log10 of lower limit in Q14 */ + const Word16 c_max, /* i: log10 of upper limit in Q13 */ + const Word16 bits, /* i: number of bits to quantize */ + Word16 *expg +); + +void gain_enc_mless_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 *xn, /* i : target vector */ + const Word16 *y1, /* i : zero-memory filtered adaptive excitation */ + const Word16 Q_xn, /* i : xn and y1 scaling */ + const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation */ + const Word16 *code, /* i : algebraic excitation */ + const Word16 Es_pred, /* i : predicted scaled innovation energy */ + Word16 *gain_pit, /* o : quantized pitch gain */ + Word32 *gain_code, /* o : quantized codebook gain */ + Word16 *gain_inov, /* o : gain of the innovation (used for normalization) */ + Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation */ + Word16 *g_corr, /* i/o: correlations , -2,, -2 and 2 */ + const Word16 clip_gain /* i : gain pitch clipping flag (1 = clipping) */ +); + +Word16 gain_enc_gaus_fx( /* o : Return index of quantization */ + Word32 *gain, /* i/o: Code gain to quantize */ + const Word16 bits, /* i : number of bits to quantize */ + const Word16 lowBound, /* i : lower bound of quantizer (dB) Q8 */ + const Word16 stepSize, /* i : Step size choice Q14 */ + const Word16 inv_stepSize /* i : Step size choice Q15 */ +); + +void gain_enc_tc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 xn_fx[], /* i : target vector */ + const Word16 y2_fx[], /* i : zero-memory filtered algebraic codebook excitation */ + const Word16 code_fx[], /* i : algebraic excitation */ + const Word16 Es_pred_fx, /* i : predicted scaled innovation energy */ + Word16 *gain_pit_fx, /* o : Pitch gain / Quantized pitch gain */ + Word32 *gain_code_fx, /* o : quantized codebook gain */ + Word16 *gain_inov_fx, /* o : innovation gain */ + Word32 *norm_gain_code_fx, /* o : norm. gain of the codebook excitation */ + const Word16 Q_xn /* i : xn and y1 scaling Q0 */ +); + +Word16 gaus_encode_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 *h1, /* i : weighted filter input response */ + const Word16 *xn, /* i : target vector */ + Word16 *exc, /* o : pointer to excitation signal frame */ + Word16 *mem_w0, /* o : weighting filter denominator memory */ + Word16 *clip_gain, /* o : memory of gain of pitch clipping algorithm */ + Word16 *tilt_code, /* o : synthesis excitation spectrum tilt */ + Word16 *code, /* o : algebraic excitation Q9 */ + Word32 *gain_code, /* o : Code gain. Q16 */ + Word16 *y2, /* o : zero-memory filtered adaptive excitation Q9 */ + Word16 *gain_inov, /* o : innovation gain Q12 */ + Word16 *voice_fac, /* o : voicing factor Q15 */ + Word16 *gain_pit, /* o : adaptive excitation gain Q14 */ + const Word16 Q_new, /* i : scaling factor */ + const Word16 shift, /* i : scaling factor */ + Word32 *norm_gain_code, /* o : normalized innovative cb. gain Q16 */ + const Word32 core_brate /* i : core bitrate */ +); + +void encod_unvoiced_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 *speech_fx, /* i : Input speech */ + const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */ + const Word16 *Aq_fx, /* i : 12k8 Lp coefficient */ + const Word16 vad_flag_fx, + const Word16 *res_fx, /* i : residual signal */ + Word16 *syn_fx, /* o : core synthesis */ + Word16 *tmp_noise_fx, /* o : long-term noise energy */ + Word16 *exc_fx, /* i/o: current non-enhanced excitation */ + Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe */ + Word16 *voice_factors_fx, /* o : voicing factors */ + Word16 *bwe_exc_fx, /* i/o: excitation for SWB TBE */ + const Word16 Q_new, + const Word16 shift +); + +void transf_cdbk_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 extl, /* i : extension layer */ + const Word16 coder_type, /* i : coding type */ + const Word16 harm_flag_acelp, /* i : harmonic flag for higher rates ACELP */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + Word16 cn[], /* i/o: target vector in residual domain */ + Word16 exc[], /* i/o: pointer to excitation signal frame */ + const Word16 *p_Aq, /* i : 12k8 Lp coefficient */ + const Word16 Ap[], /* i : weighted LP filter coefficients */ + const Word16 h1[], /* i : weighted filter input response */ + Word16 xn[], /* i/o: target vector */ + Word16 xn2[], /* i/o: target vector for innovation search */ + Word16 y1[], /* i/o: zero-memory filtered adaptive excitation */ + const Word16 y2[], /* i : zero-memory filtered innovative excitation */ + const Word16 Es_pred, /* i : predicited scaled innovation energy */ + Word16 *gain_pit, /* i/o: adaptive excitation gain */ + const Word32 gain_code, /* i : innovative excitation gain */ + Word16 g_corr[], /* o : ACELP correlation values */ + const Word16 clip_gain, /* i : adaptive gain clipping flag */ + Word16 *mem_deemp, /* i/o: prequantizer deemhasis memory */ + Word16 *mem_preemp, /* i/o: prequantizer preemhasis memory */ + Word16 *gain_preQ, /* o : prequantizer excitation gain */ + Word16 code_preQ[], /* o : prequantizer excitation */ + Word16 *unbits, /* o : number of AVQ unused bits */ + const Word16 Q_new, /* i : Current frame scaling */ + const Word16 shift /* i : shifting applied to y1, xn,... */ +); + +Word16 encod_tran_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 L_frame_fx, /* i : length of the frame */ + const Word16 speech_fx[], /* i : input speech */ + const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */ + const Word16 coder_type, /* i : coding type */ + const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */ + const Word16 T_op_fx[], /* i : open loop pitch */ + const Word16 voicing_fx[], /* i : voicing */ + const Word16 *res_fx, /* i : residual signal */ + Word16 *syn_fx, /* i/o: core synthesis */ + Word16 *exc_fx, /* i/o: current non-enhanced excitation */ + Word16 *exc2_fx, /* i/o: current enhanced excitation */ + Word16 *pitch_buf_fx, /* i/o: floating pitch values for each subframe */ + Word16 *voice_factors, /* o : voicing factors */ + Word16 *bwe_exc_fx, /* i/o: excitation for SWB TBE */ + const Word16 gsc_attack_flag, /* i : Flag to indicate when an audio attack is deal with TM */ + Word16 *unbits, /* i/o: number of unused bits */ + Word16 sharpFlag, /* o : formant sharpening flag */ + const Word16 shift, /* i : Scaling to get 12 bits */ + const Word16 Q_new /* i : Input scaling */ +); + +Word16 est_tilt_fx( /* o : tilt of the code Q15 */ + const Word16 *exc, /* i : adaptive excitation vector Qx */ + const Word16 gain_pit, /* i : adaptive gain Q14 */ + const Word16 *code, /* i : algebraic exctitation vector Q9 */ + const Word32 gain_code, /* i : algebraic code gain Q16 */ + Word16 *voice_fac, /* o : voicing factor Q15 */ + const Word16 Q_exc /* i : Scaling factor of excitation Q0 */ +); + +Word16 Est_tilt2( /* o : tilt of the code */ + const Word16 *exc, /* i : adaptive excitation vector Qx */ + const Word16 gain_pit, /* i : adaptive gain Q14 */ + const Word16 *code, /* i : algebraic exctitation vector Q9 */ + const Word32 gain_code, /* i : algebraic code gain Q16 */ + Word16 *voice_fac, /* o : voicing factor Q15 */ + const Word16 Q_exc /* i : Scaling factor of excitation Q0 */ +); + +void transition_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + const Word16 i_subfr, /* i : subframe index */ + Word16 *tc_subfr, /* i/o: TC subframe index */ + Word16 *Jopt_flag, /* i : joint optimization flag */ + Word16 *position, /* i/o: maximum of residual signal index */ + const Word16 voicing_fx[], /* i : normalized correlations (from OL pitch) Q15*/ + const Word16 T_op_fx[], /* i : open loop pitch estimates in current frame Q0*/ + Word16 *T0, /* i/o: close loop integer pitch Q0*/ + Word16 *T0_frac, /* i/o: close loop fractional part of the pitch Q0*/ + Word16 *T0_min, /* i/o: lower limit for close-loop search Q0*/ + Word16 *T0_max, /* i/o: higher limit for close-loop search Q0*/ + Word16 *exc_fx, /* i/o: pointer to excitation signal frame Q_new*/ + Word16 *y1_fx, /* o : zero-memory filtered adaptive excitation Q_new-1+shift*/ + const Word16 *res_fx, /* i : pointer to the LP residual signal frame Q_new*/ + const Word16 *h1_fx, /* i : weighted filter input response Q(14+shift)*/ + const Word16 *xn_fx, /* i : target vector Q_new-1+shift*/ + Word16 *xn2_fx, /* o : target vector for innovation search Q_new-1+shift*/ + Word16 *gp_cl_fx, /* i/o: memory of gain of pitch clipping algorithm */ + Word16 *gain_pit_fx, /* o : adaptive excitation gain Q14*/ + Word16 *g_corr_fx, /* o : ACELP correlation values */ + Word16 *clip_gain, /* i/o: adaptive gain clipping flag */ + Word16 **pt_pitch_fx, /* o : floating pitch values */ + Word16 *bwe_exc_fx, /* o : excitation for SWB TBE Q_new*/ + Word16 Q_new, /* i : Current scaling */ + Word16 shift /* i : downscaling needs for 12 bits convolutions */ +); + +Word16 abs_pit_enc_fx( /* o : pitch index */ + const Word16 fr_steps, /* i : fractional resolution steps (2 or 4) for shortest pitches*/ + const Word16 limit_flag, /* i : restrained(0) or extended(1) limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac /* i : pitch fraction */ +); + +Word16 delta_pit_enc_fx( /* o : pitch index */ + const Word16 fr_steps, /* i : fractional resolution steps (2 or 4)*/ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + const Word16 T0_min /* i : delta search min */ +); + +void set_impulse_fx( + const Word16 xn_fx[], /* i : target signal */ + const Word16 h_orig_fx[], /* i : impulse response of weighted synthesis filter */ + Word16 exc_fx[], /* o : adaptive codebook excitation */ + Word16 yy1_fx[], /* o : filtered adaptive codebook excitation */ + Word16 *imp_shape, /* o : adaptive codebook index */ + Word16 *imp_pos, /* o : position of the glotal impulse center index */ + Word32 *gain_trans_fx, /* o : transition gain Q7 */ + Word16 Q_new /* i : Current scaling */ +); + +void pit16k_Q_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* o : delta search max */ +); + +void gain_enc_amr_wb_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 *xn, /* i : target vector */ + const Word16 Q_xn, /* i : xn and yy1 format Q0 */ + const Word16 *yy1, /* i : zero-memory filtered adaptive excitation */ + const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation */ + const Word16 *code, /* i : algebraic excitation */ + const Word32 core_brate, /* i : core bitrate */ + Word16 *gain_pit, /* i/o: pitch gain / Quantized pitch gain */ + Word32 *gain_code, /* o : quantized codebook gain */ + Word16 *gain_inov, /* o : gain of the innovation (used for normalization) */ + Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation */ + Word16 *g_coeff, /* i/o: correlations , -2,, -2 and 2 */ + const Word16 clip_gain, /* i : gain pitch clipping flag (1 = clipping) */ + Word16 *past_qua_en /* i/o: gain quantization memory (4 words) */ +); + +void gain_enc_lbr_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 coder_type, /* i : coding type */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 *xn, /* i : target vector Q_xn*/ + const Word16 *y1, /* i : zero-memory filtered adaptive excitation Q_xn*/ + const Word16 Q_xn, /* i : xn and y1 format */ + const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation Q9*/ + const Word16 *code, /* i : algebraic excitation Q9*/ + Word16 *gain_pit, /* o : quantized pitch gain Q14*/ + Word32 *gain_code, /* o : quantized codebook gain Q16*/ + Word16 *gain_inov, /* o : gain of the innovation (used for normalization) Q12*/ + Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation Q16*/ + Word16 *g_corr, /* i/o: correlations , -2,, -2 and 2 mant/exp*/ + Word32 gc_mem[], /* i/o: gain_code from previous subframes */ + Word16 gp_mem[], /* i/o: gain_pitch from previous subframes */ + const Word16 clip_gain /* i : gain pitch clipping flag (1 = clipping) */ +); + +void gp_clip_test_gain_pit_fx( + const Word32 core_brate, /* i : core bitrate */ + const Word16 gain_pit, /* i : gain of quantized pitch Q14 */ + Word16 mem[] /* i/o: memory of gain of pitch clipping algorithm */ +); + +void gp_clip_test_lsf_fx( + const Word16 lsf[], /* i : lsf values (in frequency domain) */ + Word16 mem[], /* i/o: memory of gain of pitch clipping algorithm */ + const Word16 Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */ +); + +Word16 inov_encode_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 last_L_frame, /* i : length of the last frame */ + const Word16 coder_type, /* i : coding type */ + const Word16 bwidth, /* i : input signal bandwidth */ + const Word16 sharpFlag, /* i : formant sharpening flag */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 *p_Aq, /* i : LP filter coefficients Q12*/ + const Word16 gain_pit, /* i : adaptive excitation gain Q14*/ + Word16 *cn, /* i/o: target vector in residual domain Q_new*/ + const Word16 *exc, /* i : pointer to excitation signal frame Q_new*/ + Word16 *h2, /* i/o: weighted filter input response Q12*/ + const Word16 tilt_code, /* i : tilt of the excitation of previous subframe Q15*/ + const Word16 pt_pitch, /* i : pointer to current subframe fractional pitch Q6*/ + const Word16 *xn2, /* i : target vector for innovation search Q_new-1+shift*/ + Word16 *code, /* o : algebraic excitation Q9*/ + Word16 *y2, /* o : zero-memory filtered algebraic excitation Q9*/ + Word16 *unbits, /* o : number of unused bits for PI */ + Word16 shift +); + +Word32 sum2_fx( /* o : sum of all squared vector elements Q(2x+1)*/ + const Word16 *vec, /* i : input vector Qx*/ + const Word16 lvec /* i : length of input vector */ +); + +Word32 sum2_fx_mod( /* o : sum of all squared vector elements Q(2x+1)*/ + const Word16 *vec, /* i : input vector Qx*/ + const Word16 lvec /* i : length of input vector */ +); + +Word16 usdequant_fx( /* Qx*/ + const Word16 idx, /* i: quantizer index Q0*/ + const Word16 qlow, /* i: lowest codebook entry (index 0) Qx*/ + const Word16 delta /* i: quantization step Qy*/ +); + +Word16 gain_dequant_fx( /* o: decoded gain */ + Word16 index, /* i: quantization index */ + const Word16 min, /* i: value of lower limit */ + const Word16 max, /* i: value of upper limit */ + const Word16 bits, /* i: number of bits to dequantize */ + Word16 *expg +); + +void Es_pred_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *Es_pred, /* o : predicited scaled innovation energy Q8*/ + const Word16 coder_type, /* i : coder type */ + const Word32 core_brate /* i : core bitrate */ +); + +void gain_dec_tc_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate_fx, /* i : core bitrate */ + const Word16 *code_fx, /* i : algebraic code excitation */ + const Word16 L_frame_fx, /* i : length of the frame */ + const Word16 i_subfr_fx, /* i : subframe number */ + const Word16 tc_subfr_fx, /* i : TC subframe index */ + const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */ + Word16 *gain_pit_fx, /* o : pitch gain */ + Word32 *gain_code_fx, /* o : Quantized codeebook gain */ + Word16 *gain_inov_fx, /* o : unscaled innovation gain */ + Word32 *norm_gain_code_fx /* o : norm. gain of the codebook excit. */ +); + +void gain_dec_mless_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate_fx, /* i : core bitrate */ + const Word16 L_frame_fx, /* i : length of the frame */ + const Word16 coder_type_fx, /* i : coding type */ + const Word16 i_subfr_fx, /* i : subframe number */ + const Word16 tc_subfr_fx, /* i : TC subframe index */ + const Word16 *code_fx, /* i : algebraic code excitation */ + const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */ + Word16 *gain_pit_fx, /* o : Quantized pitch gain Q14*/ + Word32 *gain_code_fx, /* o : Quantized codeebook gain Q16*/ + Word16 *gain_inov_fx, /* o : unscaled innovation gain Q12*/ + Word32 *norm_gain_code_fx /* o : norm. gain of the codebook excitation Q16*/ +); + +void pre_echo_att_fx( + Word32 *Last_frame_ener_fx, /* i/o: Energy of the last frame 2*Q_new+1*/ + Word16 *exc_fx, /* i/o: Excitation of the current frame Q_new*/ + const Word16 gsc_attack_flag_fx, /* i : flag signalling attack encoded by AC mode (GSC) */ + const Word16 Q_new + ,const Word16 last_coder_type_fx /* i : Last coding mode */ +); + +void gain_dec_lbr_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 coder_type, /* i : coding type */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 *code_fx, /* i : algebraic excitation Q12*/ + Word16 *gain_pit_fx, /* o : quantized pitch gain Q14*/ + Word32 *gain_code_fx, /* o : quantized codebook gain Q16*/ + Word16 *gain_inov_fx, /* o : gain of the innovation (used for normalization) Q12*/ + Word32 *norm_gain_code_fx, /* o : norm. gain of the codebook excitation Q16*/ + Word32 gc_mem[], /* i/o: gain_code from previous subframes */ + Word16 gp_mem[] /* i/o: gain_pitch from previous subframes */ +); + +void lp_gain_updt_fx( + const Word16 i_subfr, /* i : subframe number Q0 */ + const Word16 gain_pit, /* i : Decoded gain pitch Q14 */ + const Word32 norm_gain_code, /* i : Normalised gain code Q16 */ + Word16 *lp_gainp, /* i/o: LP-filtered pitch gain(FEC) Q14 */ + Word16 *lp_gainc, /* i/o: LP-filtered code gain (FEC) Q3 */ + const Word16 L_frame /* i : length of the frame */ +); + +void pit_Q_dec_fx( + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 pitch_index, /* i : pitch index */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 delta, /* i : Half the CL searched interval */ + const Word16 pit_flag, /* i : absolute(0) or delta(1) pitch Q */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) Q limits */ + Word16 *T0, /* o : integer pitch lag */ + Word16 *T0_frac, /* o : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* i/o: delta search max */ + ,Word16 *BER_detect /* o : BER detect flag */ +); + +void abs_pit_dec_fx( + const Word16 fr_steps, /* i: fractional resolution steps (0, 2, 4) */ + Word16 pitch_index, /* i: pitch index */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) limits */ + Word16 *T0, /* o: integer pitch lag */ + Word16 *T0_frac /* o: pitch fraction */ +); + +void limit_T0_fx( + const Word16 L_frame, /* i : length of the frame */ + const Word16 delta, /* i : Half the close-loop searched interval */ + const Word16 pit_flag, /* i : selecting absolute(0) or delta(1) pitch quantization */ + const Word16 limit_flag, /* i : flag for Q limits (0=restrained, 1=extended) */ + const Word16 T0, /* i : rough pitch estimate around which the search is done */ + const Word16 T0_frac, /* i : pitch estimate fractional part */ + Word16 *T0_min, /* o : lower pitch limit */ + Word16 *T0_max /* o : higher pitch limit */ +); + +void delta_pit_dec_fx( + const Word16 fr_steps, /* i : fractional resolution steps (0, 2, 4) */ + const Word16 pitch_index, /* i : pitch index */ + Word16 *T0, /* o : integer pitch lag */ + Word16 *T0_frac, /* o : pitch fraction */ + const Word16 T0_min /* i : delta search min */ +); + +Word16 pit_decode_fx( /* o : floating pitch value */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + Word16 i_subfr, /* i : subframe index */ + const Word16 coder_type, /* i : coding type */ + Word16 *limit_flag, /* i/o: restrained(0) or extended(1) Q limits */ + Word16 *T0, /* o : close loop integer pitch */ + Word16 *T0_frac, /* o : close loop fractional part of the pitch */ + Word16 *T0_min, /* i/o: delta search min for sf 2 & 4 */ + Word16 *T0_max, /* i/o: delta search max for sf 2 & 4 */ + const Word16 L_subfr /* i : subframe length */ +); + +void pred_lt4( + const Word16 excI[], /* in: excitation buffer */ + Word16 excO[], /* out: excitation buffer */ + Word16 T0, /* input : integer pitch lag */ + Word16 frac, /* input : fraction of lag */ + Word16 L_subfr, /* input : subframe size */ + const Word16 *win, /* i : interpolation window */ + const Word16 nb_coef, /* i : nb of filter coef */ + const Word16 up_sample /* i : up_sample */ +); + +void lp_filt_exc_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 codec_type, /* i : coder type */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 coder_type, /* i : coding type */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 L_subfr, /* i : subframe size */ + const Word16 L_frame, /* i : frame size */ + Word16 lp_flag, /* i : operation mode signalling */ + Word16 *exc +); + +void inov_decode_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + const Word16 sharpFlag, /* i : formant sharpening flag */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 *p_Aq, /* i : LP filter coefficients Q12 */ + const Word16 tilt_code, /* i : tilt of the excitation of previous subframe Q15 */ + const Word16 pt_pitch, /* i : pointer to current subframe fractional pitch Q6*/ + Word16 *code /* o : algebraic excitation */ +); + +void dec_acelp_1t64_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 code[] /* o: algebraic (fixed) codebook excitation Q12*/ +); + +void dec_acelp_2t32_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 code[] /* o: algebraic (fixed) codebook excitation */ +); + +void dec_acelp_4t64_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 nbbits, /* i : number of bits per codebook */ + Word16 code[], /* o : algebraic (fixed) codebook excitation Q9*/ + const Word16 Opt_AMR_WB +); + +void weight_a_lc_fx( + const Word16 a[], /* i: LP filter coefficients Q12 */ + Word16 ap[], /* o: weighted LP filter coefficients Q12 */ + const Word16 *gammatbl, /* i: weighting factor Q15 */ + const Word16 m /* i: order of LP filter Q0 */ +); + +void weight_a_fx( + const Word16 a[], /* i: LP filter coefficients Q12 */ + Word16 ap[], /* o: weighted LP filter coefficients Q12 */ + const Word16 gamma, /* i: weighting factor Q15 */ + const Word16 m /* i: order of LP filter Q0 */ +); + +void Residu3_lc_fx( + const Word16 a[], /* i : prediction coefficients Q12 */ + const Word16 m, /* i : order of LP filter Q0 */ + const Word16 x[], /* i : input signal (usually speech) Qx */ + Word16 y[], /* o : output signal (usually residual) Qx */ + const Word16 lg, /* i : vector size Q0 */ + const Word16 shift /* i : 0=residu2, 1=residu */ +); + +void Residu3_10_fx( + const Word16 a[], /* i : prediction coefficients Q12 */ + const Word16 x[], /* i : input signal (usually speech) Qx */ + /* (note that values x[-10..-1] are needed) */ + Word16 y[], /* o : output signal (usually residual) Qx */ + const Word16 lg, /* i : vector size Q0 */ + const Word16 shift /* i : 0=residu2, 1=residu */ +); + +void Residu3_fx( + const Word16 a[], /* i : prediction coefficients Q12 */ + const Word16 x[], /* i : input signal (usually speech) Qx */ + /* (note that values x[-M..-1] are needed) */ + Word16 y[], /* o : output signal (usually residual) Qx */ + const Word16 lg, /* i : vector size Q0 */ + const Word16 shift /* i : 0=residu2, 1=residu */ +); + +void pre_exc_fx( + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 *speech, /* i : input speech Q_new-1*/ + const Word16 *p_Aq, /* i : 12k8 Lp coefficient Q12*/ + const Word16 *p_A, /* i : unquantized A(q) filter with bandwidth expansion Q12*/ + const Word16 coder_type, /* i : coding type */ + const Word16 i_subfr, /* i : current sub frame indicator */ + Word16 *Ap, /* o : weighted LP filter coefficients Q12*/ + const Word16 *res, /* i : residual signal Q_new*/ + Word16 *exc, /* o : excitation signal Q_new*/ + Word16 *h1, /* o : impulse response of weighted synthesis filter Q(14+shift)*/ + Word16 *h2, /* o : impulse response of weighted synthesis filter Q(12+shift), for codebook search*/ + Word16 *xn, /* o : close-loop Pitch search target vector Q_new-1+shift*/ + Word16 *cn, /* o : target vector in residual domain Q_new*/ + Word16 *mem_syn, /* i/o: memory of the synthesis filter Q_new-1*/ + Word16 *mem_w0, /* i/o: weighting filter denominator memory Q_new-1*/ + const Word16 L_subfr, /* i : subframe length */ + Word16 shift +); + +void encod_audio_fx( + Encoder_State_fx *st_fx, /* i/o: State structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 speech[], /* i : input speech Q_new */ + const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */ + const Word16 T_op[], /* i : open loop pitch */ + const Word16 voicing[], /* i : voicing Q15 */ + const Word16 *res, /* i : residual signal Q_new */ + Word16 *synth, /* i/o: core synthesis Q-1 */ + Word16 *exc, /* i/o: current non-enhanced excitation Q_new */ + Word16 *pitch_buf, /* i/o: floating pitch values for each subframe Q6 */ + Word16 *voice_factors, /* o : voicing factors Q15 */ + Word16 *bwe_exc, /* o : excitation for SWB TBE Q0 */ + const Word16 gsc_attack_flag, /* i : Flag that point to an attack coded with AC mode (GSC) */ + const Word16 coder_type, /* i : coding type */ + Word16 *lsf_new, /* i : current frame ISF vector */ + Word16 *tmp_noise, /* o : noise energy */ + Word16 Q_new, + Word16 shift +); + +Word16 pit_encode_fx( /* o : Fractional pitch for each subframe */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + Word16 *limit_flag, /* i/o: restrained(0) or extended(1) Q limits */ + const Word16 i_subfr, /* i : subframe index */ + Word16 *exc, /* i/o: pointer to excitation signal frame */ + const Word16 L_subfr, /* i : subframe length */ + const Word16 *T_op, /* i : open loop pitch estimates in current frame */ + Word16 *T0_min, /* i/o: lower limit for close-loop search */ + Word16 *T0_max, /* i/o: higher limit for close-loop search */ + Word16 *T0, /* i/o: close loop integer pitch */ + Word16 *T0_frac, /* i/o: close loop fractional part of the pitch */ + const Word16 *h1, /* i : weighted filter input response */ + const Word16 *xn /* i : target vector */ +); + +Word32 dotp_fx( /* o : dot product of x[] and y[] */ + const Word16 x[], /* i : vector x[] */ + const Word16 y[], /* i : vector y[] */ + const Word16 n, /* i : vector length */ + Word16 * exp /* (o) : exponent of result (0..+30) */ +); + +Word32 syn_kern_16( + Word32 L_tmp, + const Word16 a[], + const Word16 y[] +); + +void syn_filt_s_lc_fx( + const Word16 shift, /* i : scaling to apply Q0 */ + const Word16 a[], /* i : LP filter coefficients Q12 */ + const Word16 x[], /* i : input signal Qx */ + Word16 y[], /* o : output signal Qx-s */ + const Word16 lg /* i : size of filtering Q0 */ +); + +void acelp_2t32_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 dn[], /* i : corr. between target and h[]. */ + const Word16 h[], /* i : impulse response of weighted synthesis filter */ + Word16 code[], /* o : algebraic (fixed) codebook excitation */ + Word16 y[] /* o : filtered fixed codebook excitation */ +); + +Word16 acelp_4t64_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 dn[], /* i : corr. between target and h[]. */ + const Word16 cn[], /* i : residual after long term prediction Q_new*/ + const Word16 H[], /* i : impulse response of weighted synthesis filter Q12*/ + Word16 R[], /* i : autocorrelation values */ + const Word16 acelpautoc, /* i : autocorrealtion flag */ + Word16 code[], /* o : algebraic (fixed) codebook excitation Q9*/ + Word16 y[], /* o : filtered fixed codebook excitation Q9*/ + Word16 nbbits, /* i : number of bits per codebook */ + const Word16 cmpl_flag, /* i : coomplexity reduction flag */ + const Word16 Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */ +); + +void acelp_1t64_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 dn[], /* i : corr. between target and h[]. */ + const Word16 h[], /* i : impulse response of weighted synthesis filter */ + Word16 code[], /* o : algebraic (fixed) codebook excitation */ + Word16 y[] /* o : filtered fixed codebook excitation */ +); + +void cb_shape_fx( + const Word16 preemphFlag, /* i : flag for pre-emphasis */ + const Word16 pitchFlag, /* i : flag for pitch sharpening */ + const Word16 scramblingFlag, /* i : flag for phase scrambling */ + const Word16 sharpFlag, /* i : flag for formant sharpening */ + const Word16 formantTiltFlag, /* i : flag for formant tilt */ + const Word16 g1, /* i : formant sharpening numerator weighting */ + const Word16 g2, /* i : formant sharpening denominator weighting */ + const Word16 *p_Aq, /* i : LP filter coefficients */ + Word16 *code, /* i/o: signal to shape */ + const Word16 tilt_code, /* i : tilt of code */ + const Word16 pt_pitch, /* i : pointer to current subframe fractional pitch */ + const Word16 shift +); + +void corr_xh_fx( + const Word16 x[], /* i : target signal */ + Word16 dn[], /* o : correlation between x[] and h[] */ + const Word16 h[] /* i : impulse response (of weighted synthesis filter) */ +); + +void corr_xh_jopt_fx( + const Word16 h[], /* i : impulse response of weighted synthesis filter Q12 */ + const Word16 x[], /* i : target vector Q0 */ + Word16 dn[], /* o : correlation between target and h[] Q12 */ + Word16 gain, /* i : Unquantized ACB gain Q14 */ + Word16 clip, /* i : clip Q0 */ + Word16 shift /* i : scaling of x Q0 */ +); + +void enhancer_fx( + const Word32 core_brate, /* i : decoder bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 coder_type, /* i : coder type */ + const Word16 i_subfr, /* i : subframe number */ + const Word16 L_frame, /* i : frame size */ + const Word16 voice_fac, /* i : subframe voicing estimation Q15 */ + const Word16 stab_fac, /* i : LP filter stablility measure Q15 */ + Word32 norm_gain_code,/* i : normalised innovative cb. gain Q16 */ + const Word16 gain_inov, /* i : gain of the unscaled innovation Q12 */ + Word32 *gc_threshold, /* i/o: gain code threshold Q16 */ + Word16 *code, /* i/o: innovation Q12 */ + Word16 *exc2, /* i/o: adapt. excitation/total exc. Q_exc*/ + const Word16 gain_pit, /* i : quantized pitch gain Q14 */ + struct dispMem_fx *dm_fx, /* i/o: phase dispersion algorithm memory */ + const Word16 Q_exc /* i : Q of the excitation */ +); + +Word16 Rescale_exc( + Word16 dct_post_old_exc_fx[], /* i/o: Music post processing memory */ + Word16 exc[], /* i/o: excitation to rescale Q_exc */ + Word16 bwe_exc[], + Word16 *last_exc_dct_in, + Word16 lg, /* i : frame size */ + Word16 lg32, + Word32 L_gain_code, /* i : decoded codebook gain Q16 */ + Word16 *sQ_exc, /* i/o: Excitation scaling factor */ + Word16 *sQsubfr, /* i/o: Past excitation scaling factors */ + Word16 exc2[], /* o : local excitation vector */ + Word16 i_subfr, /* i : subframe number */ + const Word16 coder_type +); + +void Prep_music_postP_fx( + Word16 exc_buffer_in[], /* i/o: excitation buffer Q_exc*/ + Word16 dct_buffer_out[], /* o : DCT output buffer (qdct)*/ + Word16 filt_lfE[], /* i/o: long term spectrum energy Q15 */ + const Word16 last_core, /* i : last core */ + const Word16 *pitch_buf, /* i : current frame pitch information Q6*/ + Word16 *LDm_enh_lp_gbin, /* o : smoothed suppression gain, per bin FFT Q15*/ + const Word16 Q_exc, /* i : excitation scaling */ + Word16 *qdct /* o : Scaling factor of dct coefficient */ +); + +void Post_music_postP_fx( + Word16 dct_buffer_in[], /* i/o: excitation buffer */ + Word16 *exc2, /* i/o: Current excitation to be overwriten */ + const Word16 *mem_tmp, /* i : previous frame synthesis memory */ + Word16 *st_mem_syn2, /* i/o: current frame synthesis memory */ + const Word16 *Aq, /* i : LPC filter coefficients */ + Word16 *syn, /* i/o: 12k8 synthesis */ + Word16 *Q_exc, /* i : excitation scaling */ + Word16 *prev_Q_syn, /* i : previsous frame synthesis scaling */ + Word16 *Q_syn, /* i : Current frame synthesis scaling */ + Word16 *mem_syn_clas_estim_fx, /* i : old 12k8 synthesis used for frame classification*/ + const Word16 IsIO, /* i: Flag to indicate IO mode */ + Word16 *mem_deemph, /* i/o: speech deemph filter memory */ + Word16 *st_pst_old_syn_fx, /* i/o: psfiler */ + Word16 *st_pst_mem_deemp_err_fx, /* i/o: psfiler */ + Word16 *mem_agc, + PFSTAT *pf_stat, /* i/o: All memories related to NB post filter */ + const Word16 *tmp_buffer /* tmp_buffer in Q-1 */ + ,Word16 *mem_tmp2 /* Temporary memory used with scale_syn */ +); + +void unscale_AGC( + const Word16 x[], + const Word16 Qx, + Word16 y[], + Word16 mem[], + const Word16 n +); + +void LD_music_post_filter_fx( + const Word16 dtc_in[], /* i : input synthesis Qdct */ + Word16 dtc_out[], /* o : output synthesis Qdct */ + const Word32 core_brate, /* i : core bitrate Q0 */ + Word16 *last_music_flag, /* i/o : Previous music detection ouptut Q0 */ + Word16 *thresh, /* i/o : Detection thresold Q0 */ + Word16 *nb_thr_1, /* i/o : Number of consecutives frames of level 1 Q0 */ + Word16 *nb_thr_3, /* i/o : Number of consecutives frames of level 3 Q0 */ + Word16 *lt_diff_etot, /* i/o : Long term total energy variation Q8 */ + Word16 *mem_etot, /* i/o : Total energy memory Q8 */ + const Word16 min_ns_gain, /* i : minimum gain for inter-harm noise red. Q15 */ + Word32 bckr[], /* i/o : per band bckgnd. noise energy estimate */ + Word32 lf_EO[], /* i/o : old per bin E for previous half frame 2*Qdct+10 */ + Word16 lp_gbin[], /* i/o : smoothed suppression gain, per FFT bin Q15 */ + Word16 *filt_lfE, /* i : post filter weighting coefficient Q15 */ + Word16 *last_nonfull_music, /* i : Number of frames sinces la "speech like" frame Q0*/ + Word16 *Old_ener_Q, /* i/o : Old energy scaling factor */ + const Word16 coder_type, /* i : Coder type : -1 in case of IO Q0 */ + const Word16 Last_coder_type, /* i : input scaling Q0 */ + const Word16 Qdct /* i : input scaling Q0 */ +); + +void Rescale_mem( + const Word16 Q_exc, /* i : current excitation scaling (>=0) */ + Word16 *prev_Q_syn, /* i/o : scaling factor of previous frame */ + Word16 *Q_syn, /* i/o : scaling factor of frame */ + Word16 *mem_syn2, /* i/o : modified synthesis memory */ + Word16 *mem_syn_clas_estim_fx, /* i/o : old 12k8 core memory for classification */ + const Word16 MaxScaling, /* i: Minimal difference between excitation scaling and synthesis scaling */ + Word16 *mem_deemph, /* i/o: speech deemph filter memory */ + Word16 *pst_old_syn, /* i/o: psfiler */ + Word16 *pst_mem_deemp_err, /* i/o: psfiler */ + Word16 *mem_agc, + PFSTAT *pf_stat, /* i/o: All memories related to NB post filter */ + const Word16 Vad_flag, + const Word16 Cna_flag, + const Word16 *tmp_buffer /* tmp_buffer in Q-1 */ +); + +void Scale_sig( + Word16 x[], /* i/o: signal to scale Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +); + +void isf2lsf_fx( + const Word16 *isf, /* i : ISF vector */ + Word16 *lsf, /* o : LSF vector */ + Word16 *stable_lsp /* i/o: stable LSP filter coefficients */ +); + +void isp2lsp_fx( + const Word16 *isp, /* i : LSP vector */ + Word16 *lsp, /* o : ISP filter coefficients */ + Word16 *stable_lsp, /* i/o: stable LSP filter coefficients */ + const Word16 m /* i : order of LP analysis */ +); + +void lsf2isf_fx( + const Word16 *lsf, /* i : LSF vector */ + Word16 *isf, /* o : ISF vector */ + Word16 *stable_isp, /* i/o: stable ISP filter coefficients */ + const Word16 m /* i : order of LP analysis */ +); + +void lsp2isp_fx( + const Word16 *lsp, /* i : LSP vector */ + Word16 *isp, /* o : ISP filter coefficients */ + Word16 *stable_isp, /* i/o: ISP filter coefficients */ + const Word16 m /* i : order of LP analysis */ +); + +void updt_IO_switch_dec_fx( + const Word16 output_frame, /* i : output frame length */ + Decoder_State_fx *st_fx /* o : Decoder static variables structure */ +); + +void prep_tbe_exc_fx( + const Word16 L_frame_fx, /* i : length of the frame */ + const Word16 i_subfr_fx, /* i : subframe index */ + const Word16 gain_pit_fx, /* i : Pitch gain Q14*/ + const Word32 gain_code_fx, /* i : algebraic codebook gain 16+Q_exc*/ + const Word16 code_fx[], /* i : algebraic excitation Q9*/ + const Word16 voice_fac_fx, /* i : voicing factor Q15*/ + Word16 *voice_factors_fx, /* o : TBE voicing factor Q15*/ + Word16 bwe_exc_fx[], /* i/o: excitation for TBE Q_exc*/ + const Word16 gain_preQ_fx, /* i : prequantizer excitation gain */ + const Word16 code_preQ_fx[], /* i : prequantizer excitation */ + const Word16 Q_exc, /* i : Excitation, bwe_exc Q-factor */ + Word16 T0, /* i : integer pitch variables Q0 */ + Word16 T0_frac, /* i : Fractional pitch variables Q0*/ + const Word16 coder_type, /* i : coding type */ + Word32 core_brate /* i :core bitrate */ +); + +void interp_code_5over2_fx( + const Word16 inp_code[], /* i : input vector */ + Word16 interp_code[], /* o : output vector */ + const Word16 inp_length /* i : length of input vector */ +); + +void lsp2lsf_fx( + const Word16 lsp[], /* i : lsp[m] (range: -1<=val<1) Q15*/ + Word16 lsf[], /* o : lsf[m] normalized (range: 0.0<=val<=0.5) Q(x2.56)*/ + const Word16 m, /* i : LPC order Q0*/ + Word32 int_fs +); + +void lsf_enc_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + Word16 *lsf_new, /* o : quantized LSF vector */ + Word16 *lsp_new, /* i/o: LSP vector to quantize/quantized */ + Word16 *lsp_mid, /* i/o : mid-frame LSP vector */ + Word16 *Aq, /* o : quantized A(z) for 4 subframes */ + Word16 *stab_fac, /* o : LSF stability factor */ + const Word16 Nb_ACELP_frames, + const Word16 Q_new +); + +void lsf_mid_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 int_fs, /* i : internal (ACELP) sampling frequency */ + Word16 qlsp0[], /* i : quantized LSPs from frame beginning Q15*/ + Word16 qlsp1[], /* i : quantized LSPs from frame endSQ15*/ + Word16 coder_type, /* i : Coder type */ + Word16 qlsp[], /* o : quantized LSPs Q15*/ + const Word32 core_brate, /* i : core bitrate */ + Word16 ppp_mode, + Word16 nelp_mode, + Word16 prev_bfi, + Word16 *mid_lsf_int, + Word16 safety_net +); + +Word16 lsf_stab_fx( /* o : LP filter stability Q15*/ + const Word16 *lsf, /* i : LSF vector Q(x2.56)*/ + const Word16 *lsfold, /* i : old LSF vector Q(x2.56)*/ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame /* i : frame length */ +); + +void lsf_allocate_fx( + const Word16 nBits, /* i : Number of bits to use for quantization */ + const Word16 framemode, /* i : ISF quantizer mode */ + const Word16 framemode_p, /* i : ISF quantizer mode predmode (mode_lvq_p) */ + Word16 *stages0, /* o : Number of stages for safety-net quantizer */ + Word16 *stages1, /* o : Number of stages for predictive quantizer */ + Word16 levels0[], /* o : Number of vectors for each stage for SFNET */ + Word16 levels1[], /* o : Number of vectors for each stage for pred */ + Word16 bits0[], /* o : Number of bits for each stage safety net */ + Word16 bits1[] /* o : Number of bits for each stage pred */ +); +Word16 vq_dec_lvq_fx ( + Word16 sf_flag, /* i : safety net flag */ + Word16 x[], /* o : Decoded vector Q(x2.56)*/ + Word16 indices[], /* i : Indices */ + Word16 stages, /* i : Number of stages */ + Word16 N, /* i : Vector dimension */ + Word16 mode, /* (i): mode_lvq, or mode_lvq_p */ + Word16 no_bits, /* (i): no. bits for lattice */ + Word32 *p_offset_scale1, + Word32 *p_offset_scale2, + Word32 *p_offset_scale1_p, + Word32 *p_offset_scale2_p, + Word16 *p_no_scales, + Word16 *p_no_scales_p +); + +Word16 qlsf_ARSN_tcvq_Dec_16k_fx ( + Word16 *y_fx, /* o : Quantized LSF vector */ + Word16 *indice, /* i : Indices */ + const Word16 nBits /* i : number of bits */ +); + +void tcvq_Dec_fx(Word16 *ind, + /*float *d_out, */ + Word16 *d_out_fx, + Word16 safety_net + ); + +Word32 qlsf_ARSN_tcvq_Enc_16k_fx( + const Word16 *x_fx, /* i : Vector to be encoded x2.65 */ + Word16 *y_fx, /* o : Quantized LSF vector x2.65 */ + Word16 *indice, /* o : Indices */ + const Word16 *w_fx, /* i : LSF Weights Q10 */ + const Word16 nBits, /* i : number of bits */ + Word16 safety_net /* i : safety_net flag */ +); + +void Vr_add( + const Word16 *in1, /* i : Input vector 1 */ + const Word16 *in2, /* i : Input vector 2 */ + Word16 *out, /* o : Output vector that contains vector 1 + vector 2 */ + Word16 Len /* i : Vector lenght */ +); + +void Vr_subt( + const Word16 *in1, /* i : Input vector 1 */ + const Word16 *in2, /* i : Input vector 2 */ + Word16 *out, /* o : Output vector that contains vector 1 + vector 2 */ + Word16 Len /* i : Vector lenght */ +); + +void index_lvq_fx ( + Word16 *quant, /* i : codevector to be indexed (2 8-dim subvectors) Q13*/ + Word16 *idx_lead, /* i : leader class index for each subvector */ + Word16 *idx_scale, /* i : scale index for each subvector */ + Word16 mode, /* i : integer signalling the quantizer structure for the current bitrate */ + Word16 *index, /* o : encoded index (represented on 3 short each with 15 bits ) */ + Word32 * p_offset_scale1, + Word32 * p_offset_scale2, + Word16 * p_no_scales +); + +void multiply32_32_64_fx( + Word32 x, + Word32 y, + Word32 *res +); + +void permute_fx( + Word16 *pTmp1, /* i/o: vector whose components are to be permuted */ + const Word16 *perm /* i : permutation info (indexes that should be interchanged), max two perms */ +); + +Word32 mslvq_fx ( + Word16 *pTmp, /* i : M-dimensional input vector */ + Word16 *quant, /* o : quantized vector */ + Word16 *cv_out, /* o : corresponding 8-dim lattice codevectors (without the scaling) */ + Word16 *idx_lead, /* o : leader index for each 8-dim subvector */ + Word16 *idx_scale, /* o : scale index for each subvector */ + Word16 *w, /* i : weights for LSF quantization */ + Word16 mode, /* i : number indicating the coding type (V/UV/G...)*/ + Word16 mode_glb, /* i : LVQ coding mode */ + Word16 pred_flag, /* i : prediction flag (0: safety net, 1 - predictive )*/ + Word16 no_scales[][2] +); + +Word32 mslvq_cng_fx ( + Word16 idx_cv, /* i : index of cv from previous stage */ + Word16 *pTmp, /* i : 16 dimensional input vector x2.56*/ + Word16 *quant, /* o : quantized vector x2.56*/ + Word16 *cv_out, /* o : corresponding 8-dim lattice codevectors (without the scaling) Q13*/ + Word16 *idx_lead, /* o : leader index for each 8-dim subvector */ + Word16 *idx_scale, /* o : scale index for each subvector */ + const Word16 *w, /* i : weights for LSF quantization Q10*/ + Word16 * no_scales +); + +void sort_fx( + Word16 *r, /* i/o: Vector to be sorted in place */ + Word16 lo, /* i : Low limit of sorting range */ + Word16 up /* I : High limit of sorting range */ +); + +void lsf_dec_fx( + Decoder_State_fx *st_fx, /* i/o: State structure */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + const Word16 bwidth, /* i : input signal bandwidth */ + Word16 *Aq, /* o : quantized A(z) for 4 subframes */ + Word16 *LSF_Q_prediction, /* o : LSF prediction mode */ + Word16 *lsf_new, /* o : de-quantized LSF vector */ + Word16 *lsp_new, /* o : de-quantized LSP vector */ + Word16 *lsp_mid /* o : de-quantized mid-frame LSP vector */ +); + +void lsf_end_enc_fx( + Encoder_State_fx *st, + const Word16 *lsf, + Word16 *qlsf, + Word16 *mem_AR, + Word16 * mem_MA, + const Word16 nBits, + const Word16 coder_type_org, + const Word16 bwidth, + Word32 *Bin_Ener, + Word16 Q_ener, + const Word32 int_fs, + Word32 core_brate, + Word16 *streaklimit, + Word16 *pstreaklen, + Word16 force_sf, + Word16 RF_flag, + Word16 mode2_flag, + Word16 * lpc_param, + Word16 * no_stages, + Word16 * bits_param_lpc, + Word16 coder_type_raw +); + +void lsf_end_dec_fx( + Decoder_State_fx *st, + Word16 mode2_flag, + const Word16 coder_type_org, + const Word16 bwidth, + const Word16 nBits, + Word16 *qlsf, + Word16 *mem_AR, + Word16 *mem_MA, + const Word32 int_fs, + Word32 core_brate, + Word32 *p_offset_scale1, + Word32 *p_offset_scale2, + Word32 *p_offset_scale1_p, + Word32 *p_offset_scale2_p, + Word16 *p_no_scales, + Word16 *p_no_scales_p, + Word16 *safety_net, + Word16 *lpc_param, + Word16 *LSF_Q_prediction, /* o : LSF prediction mode */ + Word16 * nb_indices +); + +Word16 find_pred_mode( + const Word16 coder_type, + const Word16 bwidth, + const Word32 int_fs, + Word16 * p_mode_lvq, + Word16 * p_mode_lvq_p, + Word32 core_brate +); + +Word16 xsf_to_xsp( + Word16 lsf +); + +Word16 xsp_to_xsf( + Word16 lsp +); + +void int_lsp4_fx( + const Word16 L_frame, /* i : length of the frame */ + const Word16 lsp_old[], /* i : LSPs from past frame Q15*/ + const Word16 lsp_mid[], /* i : LSPs from mid-frame Q15*/ + const Word16 lsp_new[], /* i : LSPs from present frame Q15*/ + Word16 *Aq, /* o : LP coefficients in both subframes Q12*/ + const Word16 m, /* i : order of LP filter */ + Word16 relax_prev_lsf_interp /* i : relax prev frame lsf interp after erasure */ +); + +Word16 modify_Fs_fx( /* o : length of output Q0 */ + const Word16 sigIn_fx[], /* i : signal to decimate Q0 */ + Word16 lg, /* i : length of input Q0 */ + const Word32 fin, /* i : frequency of input Q0 */ + Word16 sigOut_fx[], /* o : decimated signal Q0 */ + const Word32 fout, /* i : frequency of output Q0 */ + Word16 mem_fx[], /* i/o: filter memory Q0 */ + const Word16 nblp /* i : flag indicating if NB low-pass is applied */ +); + +void addBassPostFilterFx( + const Word16 *harm_timeIn_Fx, + Word32 **rAnalysis_Fx, + Word32 **iAnalysis_Fx, + HANDLE_CLDFB_FILTER_BANK cldfbBank_bpf_Fx, + Word32 *workBuffer, + const Word16 timeIn_e, + const Word16 nTimeSlots, + const Word16 nTimeSlotsTotal, + const Word16 nBandsTotal, + CLDFB_SCALE_FACTOR *cldfb_scale +); + +void bass_psfilter_fx( + const Word16 Opt_AMR_WB, /* i : AMR-WB IO flag */ + Word16 synth_in_fx[], /* i : input synthesis (at 16kHz) */ + const Word16 L_frame, /* i : length of the last frame */ + Word16 pitch_buf_fx[], /* i : pitch for every subfr [0,1,2,3] */ + Word16 old_syn_fx[], /* i/o: NBPSF_PIT_MAX */ + Word16 *mem_deemph_err, /* o : Error deemphasis memory */ + Word16 *lp_ener, /* o : long_term error signal energy */ + const Word16 bpf_off, /* i : do not use BPF when set to 1 */ + Word16 v_stab_fx, /* i : stability factor */ + Word16 *v_stab_smooth_fx, /* i/o: smoothed stability factor */ + Word16 *mem_mean_pit, /* i/o: average pitch memory */ + Word16 *Track_on_hist, /* i/o: History of half frame usage */ + Word16 *vibrato_hist, /* i/o: History of frames declared as vibrato*/ + Word16 *psf_att, /* i/o: Post filter attenuation factor */ + const Word16 coder_type, /* i : coder_type */ + Word16 Q_syn, + Word16 bpf_noise_buf[] /* o : BPF error signal (at int_fs) */ +); + +void speech_music_classif_fx( + Encoder_State_fx *st, /* i/o: state structure */ + Word16 *sp_aud_decision0, + Word16 *sp_aud_decision1, /* o : 1st stage speech/music */ + Word16 *sp_aud_decision2, /* o : 2nd stage speech/music */ + const Word16 *new_inp, /* i : new input signal */ + const Word16 *inp, /* i : input signal to locate attach position */ + const Word16 vad_flag, + const Word16 localVAD, + const Word16 localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ + const Word16 pitch[3], /* i : open-loop pitch estimate in three subframes */ + const Word16 voicing[3], /* i : voicing estimate in three subframes Q15 */ + const Word16 lsp_new[M], /* i : LSPs in current frame Q15 */ + const Word16 cor_map_sum, /* i : correlation map sum (from multi-harmonic anal.)Q8*/ + const Word32 epsP[M+1], /* i : LP prediciton error Q_esp*/ + const Word32 PS[], /* i : energy spectrum Q_new+QSCALE*/ + const Word16 Etot, /* i : total frame energy Q8 */ + const Word16 old_cor, /* i : max correlation from previous frame Q15 */ + Word16 *coder_type, /* i/o: coding type */ + Word16 *attack_flag, /* o : flag to indicate if attack is to be treated by TC or GSC */ + Word16 non_sta, /* i : unbound non-stationarity for sp/mus classifier */ + Word16 relE, /* i : relative frame energy */ + Word16 Q_esp, /* i : scaling of esP */ + Word16 Q_inp /* i : scaling of input */ + ,Word16 *high_lpn_flag_ptr /* o : noise log prob flag for NOISE_EST */ + ,Word16 flag_spitch /* i: flag to indicate very short stable pitch */ +); + +Word32 sub_lsp2lsf_fx( + const Word16 lsp_i /* i : lsp[m] (range: -1<=val<1) Q15*/ +); +Word16 lsp_convert_poly_fx( + Word16 w[], /* i/o: LSP or ISP parameters */ + const Word16 L_frame, /* i : flag for up or down conversion */ + const Word16 Opt_AMRWB /* i : flag for the AMR-WB IO mode */ +); + +void StableHighPitchDetect_fx( + Word16 *flag_spitch, /* o : flag to indicate very short stable pitch */ + Word16 pitch[], /* i/o: OL pitch buffer */ + const Word16 voicing[], /* i : OL pitch gains */ + const Word16 wsp[], /* i : weighted speech */ + const Word16 localVAD, + Word16 *voicing_sm, /* i/o: smoothed open-loop pitch gains */ + Word16 *voicing0_sm, /* i/o: smoothed high pitch gains */ + Word16 *LF_EnergyRatio_sm, /* i/o: smoothed [0, 300Hz] relative peak energy*/ + Word16 *predecision_flag, /* i/o: predecision flag */ + Word32 *diff_sm, /* i/o: smoothed pitch frequency difference */ + Word32 *energy_sm , /* i/o: smoothed energy around pitch frequency */ + Word16 Q_new, + Word16 EspecdB[] +); + +void Es_pred_enc_fx( + Word16 *Es_pred, /* o : predicited scaled innovation energy Q8 */ + Word16 *indice, /* o : indice of quantization */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 *res, /* i : residual signal */ + const Word16 *voicing, /* i : normalized correlation in three 1/2frames */ + const Word16 nb_bits, /* i : allocated number of bits */ + const Word16 no_ltp, /* i : no_ltp flag */ + Word16 Q_new /* i : Scaling in speech Q0 */ +); + +void calc_residu_fx( + Encoder_State_fx *st, /* i/o: state structure */ + const Word16 *speech, /* i : weighted speech signal */ + Word16 *res, /* o : residual signal */ + const Word16 *p_Aq, /* i : quantized LP filter coefficients */ + const Word16 vad_hover_flag, + const Word16 vad_flag_dtx +); +void updt_IO_switch_enc_fx( + Encoder_State_fx *st, /* i/o: state structure */ + const Word16 input_frame /* i : input frame length */ +); +/*-------------------------------------------------------------------* + * pre_proc() + * + * Pre-processing (spectral analysis, LP analysis, VAD, OL pitch calculation, coder mode selection, ...) + *--------------------------------------------------------------------*/ + +void pre_proc_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 input_frame, /* i : frame length */ + const Word16 signal_in[], /* i : new samples */ + Word16 old_inp_12k8[], /* i/o: buffer of old input signal */ + Word16 old_inp_16k[], /* i/o: buffer of old input signal @ 16kHz */ + Word16 **inp, /* o : ptr. to inp. signal in the current frame */ + Word16 *sp_aud_decision1, /* o : 1st stage speech/music classification */ + Word16 *sp_aud_decision2, /* o : 2nd stage speech/music classification */ + Word32 fr_bands[2*NB_BANDS], /* o : energy in frequency bands */ + Word16 *vad_flag, + Word16 *localVAD, + Word16 *Etot, /* o : total energy */ + Word32 *ener, /* o : residual energy from Levinson-Durbin */ + Word16 pitch[3], /* o : open-loop pitch values for quantiz. */ + Word16 voicing[3], /* o : OL maximum normalized correlation */ + Word16 A[NB_SUBFR16k*(M+1)], /* o : A(z) unquantized for the 4 subframes */ + Word16 Aw[NB_SUBFR16k*(M+1)], /* o : weighted A(z) unquantized for subframes */ + Word16 epsP_h[M+1], /* o : LP prediction errors */ + Word16 epsP_l[M+1], /* o : LP prediction errors */ + Word32 epsP[M+1], /* o : LP prediction errors */ + Word16 lsp_new[M], /* o : LSPs at the end of the frame */ + Word16 lsp_mid[M], /* o : LSPs in the middle of the frame */ + Word16 *coder_type, /* o : coder type */ + Word16 *sharpFlag, /* o : formant sharpening flag */ + Word16 *vad_hover_flag, + Word16 *attack_flag, /* o : flag signalling attack encoded by AC mode (GSC) */ + Word16 *new_inp_resamp16k, /* o : new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ + Word16 *Voicing_flag, /* o : voicing flag for HQ FEC */ + + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o : cldfb real buffer */ + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o : cldfb imag buffer */ + CLDFB_SCALE_FACTOR *cldfbScale, /* o : cldfb scale */ + Word16 *old_exc, /* i/o: static excitation memory */ + Word16 *hq_core_type, /* o : HQ core type */ + Word16 *Q_new, + Word16 *shift, + Word16 *Q_r +); + +Word16 mdct_classifier_fx( /* o: MDCT A/B decision */ + const Word16 *Y, /* i: re[0], re[1], ..., re[n/2], im[n/2 - 1], im[n/2 - 2], ..., im[1] */ + Encoder_State_fx *st_fx, /* i/o: Encoder state variable */ + Word16 vadflag + ,Word32 *cldfbBuf_Ener + ,Word16 enerBuffer_exp +); + +void floating_point_add( + Word32 *mx, /* io: mantissa of the addend Q31 */ + Word16 *ex, /* io: exponent of the addend Q0 */ + const Word32 my, /* i: mantissa of the adder Q31 */ + const Word16 ey /* i: exponent of the adder Q0 */ +); + +void MDCT_selector( + Encoder_State_fx *st /* i/o: Encoder State */ + , Word16 sp_floor /* i : Noise floor estimate Q7 */ + , Word16 Etot /* i : Total energy Q8 */ + , Word16 cor_map_sum /* i : harmonicity factor Q8 */ + , const Word16 voicing[] /* i : voicing factors Q15*/ + , const Word32 enerBuffer[] /* i : CLDFB buffers */ + , Word16 enerBuffer_exp /* i : exponent of enerBuffer */ + , Word16 vadflag +); + +void MDCT_selector_reset( + Encoder_State_fx *st); /* i/o: Encoder State */ + +Word16 minimum_fx( /* o : index of the minimum value in the input vector */ + const Word16 *vec_fx, /* i : input vector */ + const Word16 lvec_fx, /* i : length of input vector */ + Word16 *min_fx /* o : minimum value in the input vector */ +); +Word16 minimum_32_fx( /* o : index of the minimum value in the input vector */ + const Word32 *vec_fx, /* i : input vector */ + const Word16 lvec_fx, /* i : length of input vector */ + Word32 *min_fx /* o : minimum value in the input vector */ +); +Word16 maximum_32_fx( /* o : index of the maximum value in the input vector */ + const Word32 *vec, /* i : input vector */ + const Word16 lvec, /* i : length of input vector */ + Word32 *max /* o : maximum value in the input vector */ +); +Word16 maximum_fx( /* o : index of the maximum value in the input vector */ + const Word16 *vec_fx, /* i : input vector */ + const Word16 lvec_fx, /* i : length of input vector */ + Word16 *max_fx /* o : maximum value in the input vector */ +); +Word16 Exp32Array( + const Word16 n, /* (i): Array size */ + const Word32 *sx /* (i): Data array */ +); +Word16 Exp16Array( + const Word16 n, /* (i): Array size */ + const Word16 *sx /* (i): Data array */ +); + +Word32 sum16_32_fx( /* o : sum of all vector elements Qx*/ + const Word16 *vec, /* i : input vector Qx*/ + const Word16 lvec /* i : length of input vector */ +); +Word32 dot_product_mat_fx( /* o : the dot product x'*A*x */ + const Word16 *x, /* i : vector x Q15 */ + const Word32 *A, /* i : matrix A Q0*/ + const Word16 m /* i : vector & matrix size */ + +); + +Word16 std_fx( /* o: standard deviation */ + const Word16 *x, /* i: input vector */ + const Word16 len /* i: length of the input vector */ +); + +Word16 stab_est_fx( + Word16 etot, /* i : Total energy of the current frame */ + Word16 *lt_diff_etot, /* i/o : Long term total energy variation */ + Word16 *mem_etot, /* i/o : Total energy memory */ + Word16 *nb_thr_3, /* i/o : Number of consecutives frames of level 3 */ + Word16 *nb_thr_1, /* i/o : Number of consecutives frames of level 1 */ + Word16 *thresh, /* i/o : Detection thresold */ + Word16 *last_music_flag,/* i/o : Previous music detection ouptut */ + Word16 vad_flag +); +Word16 var_fx( /* o: variance of vector Qx*/ + const Word16 *x, /* i: input vector Qx*/ + const Word16 Qx, + const Word16 len /* i: length of inputvector */ +); +void conv_fx( + const Word16 x[], /* i : input vector Q_new*/ + const Word16 h[], /* i : impulse response (or second input vector) Q(15)*/ + Word16 y[], /* o : output vetor (result of convolution) 12 bits*/ + const Word16 L /* i : vector size */ +); +void norm_corr_fx( + const Word16 exc[], /* i : excitation buffer Q_new*/ + const Word16 xn[], /* i : target signal Q_new-1+shift*/ + const Word16 h[], /* i : weighted synthesis filter impulse response Q(14+shift)*/ + const Word16 t_min, /* i : minimum value of searched range */ + const Word16 t_max, /* i : maximum value of searched range */ + Word16 ncorr[], /* o : normalized correlation Q15 */ + const Word16 L_subfr /* i : subframe size */ +); +void pit_Q_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 delta, /* i : Half the CL searched interval */ + const Word16 pit_flag, /* i : absolute(0) or delta(1) pitch Q */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* o : delta search max */ +); +/*void pit16k_Q_enc_fx( */ +/*Encoder_State_fx *st_fx, */ /* i/o: encoder state structure */ +/* const Word16 nBits, */ /* i : # of Q bits */ +/* const Word16 i_subfr, */ /* i : subframe index */ +/* const Word16 limit_flag, */ /* i : restrained(0) or extended(1) Q limits */ +/* const Word16 T0, */ /* i : integer pitch lag */ +/* const Word16 T0_frac, */ /* i : pitch fraction */ +/* Word16 *T0_min, */ /* i/o: delta search min */ +/* Word16 *T0_max */ /* o : delta search max */ +/*); */ + +Word16 pitch_fr4_fx( /* o : chosen integer pitch lag */ + const Word16 exc[], /* i : excitation buffer Q_new*/ + const Word16 xn[], /* i : target signal Q_new-1+shift*/ + const Word16 h[], /* i : weighted synthesis filter impulse response Q(14+shift)*/ + const Word16 t0_min, /* i : minimum value in the searched range. Q0*/ + const Word16 t0_max, /* i : maximum value in the searched range. Q0*/ + Word16 *pit_frac, /* o : chosen fraction (0, 1, 2 or 3) */ + const Word16 i_subfr, /* i : flag to first subframe */ + const Word16 limit_flag, /* i : flag for limits (0=restrained, 1=extended) */ + const Word16 t0_fr2, /* i : minimum value for resolution 1/2 */ + const Word16 t0_fr1, /* i : minimum value for resolution 1 */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 L_subfr /* i : size of subframe */ +); + +Word32 var_fx_32( /* o: variance of vector Qx+16*/ + const Word16 *x, /* i: input vector Qx*/ + const Word16 Qx, + const Word16 len /* i: length of inputvector */ +); + +Word16 sum16_fx( /* o : sum of all vector elements Qx*/ + const Word16 *vec, /* i : input vector Qx*/ + const Word16 lvec /* i : length of input vector */ +); + +Word32 sum32_fx( /* o : sum of all vector elements Qx*/ + const Word32 *vec, /* i : input vector Qx*/ + const Word16 lvec /* i : length of input vector */ +); + +Word32 Mean32( /* o : mean of the elements of the vector */ + const Word32 in[], /* i : input vector */ + const Word16 L /* i : length of input vector */ +); + +void Deemph2( + Word16 x[], /* i/o: input signal overwritten by the output Qx/Qx-1 */ + const Word16 mu, /* i : deemphasis factor Q15 */ + const Word16 L, /* i : vector size Q0 */ + Word16 *mem /* i/o: memory (y[-1]) Qx-1 */ +); + +void deemph_fx( + Word16 *signal, /* i/o: signal Qx */ + const Word16 mu, /* i : deemphasis factor Q15 */ + const Word16 L, /* i : vector size Q0 */ + Word16 *mem /* i/o: memory (y[-1]) Qx */ +); +Word16 deindex_lvq_fx( + Word16 *index, /* i : index to be decoded, as an array of 3 short */ + Word16 *x_lvq, /* o : decoded codevector Q(x2.56)*/ + Word16 mode, /* i : LVQ coding mode (select scales & no_lead ), or idx_cv */ + Word16 sf_flag, /* i : safety net flag */ + Word16 no_bits, /* i : number of bits for lattice */ + Word32 *p_offset_scale1, /* i : offset for first subvector */ + Word32 *p_offset_scale2, /* i : offset for the second subvector */ + Word16 *p_no_scales +); +void Syn_filt_s( + const Word16 shift, /* i : scaling to apply Q0 */ + const Word16 a[], /* i : LP filter coefficients Q12 */ + const Word16 m, /* i : order of LP filter Q0 */ + const Word16 x[], /* i : input signal Qx */ + Word16 y[], /* o : output signal Qx-s */ + const Word16 lg, /* i : size of filtering Q0 */ + Word16 mem[], /* i/o: memory associated with this filtering. Qx-s */ + const Word16 update /* i : 0=no update, 1=update of memory. Q0 */ +); +void hp400_12k8_fx( + Word16 signal[], /* i/o: input signal / output is divided by 16 */ + const Word16 lg, /* i : lenght of signal */ + Word16 mem[] /* i/o: filter memory [6] */ +); +Word16 dot_prod_satcontr(const Word16 *x, const Word16 *y, Word16 qx, Word16 qy, Word16 *qo, Word16 len); +void syn_12k8_fx( + Word16 L_frame, + const Word16 *Aq, /* i : LP filter coefficients Q12 */ + const Word16 *exc, /* i : input signal Q_exc */ + Word16 *synth, /* o : output signal Q_syn */ + Word16 *mem, /* i/o: initial filter states Q_syn */ + const Word16 update_m, /* i : update memory flag: 0 --> no memory update Q0 */ + /* 1 --> update of memory */ + const Word16 Q_exc, /* i : Excitation scaling Q0 */ + const Word16 Q_syn /* i : Synthesis scaling Q0 */ +); +void updt_dec_fx( + Decoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + const Word16 *old_exc_fx, /* i : buffer of excitation */ + const Word16 *pitch_buf_fx, /* i : floating pitch values for each subframe */ + const Word16 Es_pred, /* i : predicited scaled innovation energy */ + const Word16 *Aq, /* i : A(z) quantized for all subframes */ + const Word16 *lsf_new_fx, /* i : current frame LSF vector */ + const Word16 *lsp_new_fx, /* i : current frame LSP vector */ + const Word16 voice_factors[], /* i : voicing factors */ + const Word16 *old_bwe_exc_fx /* i : buffer of excitation */ + , const Word16 *gain_buf /*Q14*/ +); +Word32 Interpol_lc_fx( /* o : interpolated value Qx+16 */ + const Word16 *x, /* i : input vector Q0 */ + const Word16 *win, /* i : interpolation window Q14 */ + const Word16 frac, /* i : fraction (0..up_samp) Q0 */ + const Word16 up_samp, /* i : upsampling factor Q0 */ + const Word16 nb_coef /* i : number of coefficients Q0 */ +); + +Word16 corr_xy1_fx( /* o : pitch gain (0..GAIN_PIT_MAX) */ + const Word16 xn_1[], /* i : target signal */ + const Word16 y1_1[], /* i : filtered adaptive codebook excitation */ + Word16 g_corr[], /* o : correlations and -2 */ + const Word16 L_subfr, /* i : vector length */ + const Word16 norm_flag /* i : flag for constraining pitch contribution */ +); + +void updt_tar_fx( + const Word16 *x, /* i : old target (for pitch search) */ + Word16 *x2, /* o : new target (for codebook search) */ + const Word16 *y, /* i : filtered adaptive codebook vector */ + const Word16 gain, /* i : adaptive codebook gain */ + const Word16 L /* i : subframe size */ +); +void updt_tar_HR_fx( + const Word16 *x, /* i : old target (for pitch search) */ + Word16 *x2, /* o : new target (for codebook search) */ + const Word16 *y, /* i : filtered adaptive codebook vector */ + const Word16 gain, /* i : adaptive codebook gain */ + const Word16 Qx, /* i : Scaling factor to adapt output to input */ + const Word16 L /* i : subframe size */ +); + +Word16 lp_filt_exc_enc_fx( + const Word16 codec_mode, /* i : MODE1 or MODE2 Q0 */ + const Word32 core_brate, /* i : core bitrate Q0 */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode Q0 */ + const Word16 coder_type, /* i : coding type Q0 */ + const Word16 i_subfr, /* i : subframe index Q0 */ + Word16 *exc, /* i/o: pointer to excitation signal frame Q_new */ + const Word16 *h1, /* i : weighted filter input response Q(14+shift) */ + const Word16 *xn, /* i : target vector Q_new-1+shift */ + Word16 *y1, /* o : zero-memory filtered adaptive excitation Q_new-1+shift */ + Word16 *xn2, /* o : target vector for innovation search Q_new-1+shift */ + const Word16 L_subfr, /* i : length of vectors for gain quantization Q0 */ + const Word16 L_frame, /* i : frame size Q0 */ + Word16 *g_corr, /* o : ACELP correlation values mant/exp */ + const Word16 clip_gain, /* i : adaptive gain clipping flag Q0 */ + Word16 *gain_pit, /* o : adaptive excitation gain Q14 */ + Word16 *lp_flag /* i/o: mode selection Q0 */ +); + +Word16 Interpol_4( /* o : interpolated value */ + Word16 * x, /* i : input vector */ + Word16 frac /* i : fraction (-4..+3) */ +); + +void r_fft_fx_lc( + const Word16 *phs_tbl, /* i : Table of phase */ + const Word16 SIZE, /* i : Size of the FFT */ + const Word16 SIZE2, /* i : Size / 2 */ + const Word16 NUM_STAGE, /* i : Number of stage */ + const Word16 *in_ptr, /* i : coeffients in the order re[0], re[1], ... re[n/2], im[1], im[2], ..., im[n/2-1] */ + Word16 *out_ptr, /* o : coeffients in the order re[0], re[1], ... re[n/2], im[1], im[2], ..., im[n/2-1] */ + const Word16 isign /* i : 1=fft, otherwize it's ifft */ +); + +void hf_synth_fx( + const Word32 core_brate, /* i : core bitrate */ + const Word16 output_frame, /* i : output frame length */ + const Word16 *Aq, /* i : quantized Az */ + const Word16 *exc, /* i : excitation at 12.8 kHz */ + Word16 *synth, /* i : 12.8kHz synthesis signal */ + Word16 *synth16k, /* o : 16kHz synthesis signal */ + Word16 *seed2, /* i/o: random seed for HF noise gen */ + Word16 *mem_hp400, /* i/o: memory of hp 400 Hz filter */ + Word16 *mem_syn_hf, /* i/o: HF synthesis memory */ + Word16 *mem_hf, /* i/o: HF band-pass filter memory */ + const Word16 Q_exc, /* i : excitation scaling */ + const Word16 Q_syn2, /* i : synthesis scaling */ + Word16 *delay_syn_hf, /*i/o: HF synthesis memory */ + Word16 *memExp1, /* o : HF excitation exponent */ + Word16 *mem_hp_interp, /* i/o: interpol. memory */ + const Word16 extl, /* i : flag indicating BWE */ + const Word16 CNG_mode /* i : CNG_mode */ +); +void acelp_core_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 synth_out[], /* o : synthesis */ + Word32 bwe_exc_extended[], /* i/o: bandwidth extended excitation */ + Word16 *voice_factors, /* o : voicing factors */ + Word16 old_syn_12k8_16k[], /* o : intermediate ACELP synthesis at 12.8kHz or 16kHz to be used by SWB BWE */ + Word16 coder_type_fx, /* i : coder type */ + Word16 sharpFlag, + Word16 pitch_buf_fx[NB_SUBFR16k], /* o : floating pitch for each subframe */ + Word16 *unbits /* o : number of unused bits */ + ,Word16 *sid_bw /* o : 0-NB/WB, 1-SWB SID */ +); +void Inac_swtch_ematch_fx( + Word16 exc2[], /* i/o: CELP/GSC excitation buffer Q_exc*/ + Word16 dct_exc_tmp[], /* i : GSC excitation in DCT domain */ + Word16 lt_ener_per_band[], /* i/o: Long term energy per band Q12 */ + const Word16 coder_type, /* i : Coding mode */ + const Word16 L_frame, /* i : Frame lenght */ + const Word32 core_brate, /* i : Core bit rate */ + const Word16 Q_exc /* i : input and output format of exc2 */ + ,const Word16 bfi /* i : frame lost indicator */ + ,const short last_core, /* i : Last core used */ + const short last_codec_mode /* i : Last codec mode */ +); +void stat_noise_uv_enc_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 coder_type, /* i : coding type */ + const Word32 *LepsP, /* i : LP prediction errors */ + Word16 *isp_new, /* i : immittance spectral pairs at 4th sfr */ + Word16 *isp_mid, /* i : immittance spectral pairs at 2nd sfr */ + Word16 *Aq, /* i : A(z) quantized for the 4 subframes */ + Word16 *exc2, /* i/o: excitation buffer */ + Word16 Q_new +); + +void updt_enc_fx( + Encoder_State_fx *st, /* i/o: state structure */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : speech coder type */ + const Word16 *old_exc, /* i : buffer of excitation */ + const Word16 *pitch_buf, /* i : floating pitch for each subframe */ + const Word16 Es_pred, /* i : predicited scaled innovation energy */ + const Word16 *Aq, /* i : A(z) quantized for all subframes */ + const Word16 *lsf_new, /* i : current frame LSF vector */ + const Word16 *lsp_new, /* i : current frame LSP vector */ + const Word16 *old_bwe_exc /* i : buffer of excitation */ +); +void FEC_encode_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *synth, /* i : pointer to synthesized speech for E computation */ + const Word16 coder_type, /* i : type of coder */ + Word16 clas, /* i : signal clas for current frame */ + const Word16 *fpit, /* i : close loop fractional pitch buffer */ + const Word16 *res, /* i : LP residual signal frame */ + Word16 *last_pulse_pos, /* i/o: Position of the last pulse */ + const Word16 L_frame, /* i : Frame length */ + const Word32 total_brate, /* i : total codec bitrate */ + const Word32 core_brate, /* i : total codec bitrate */ + const Word16 Q_new, /* i : input scaling */ + const Word16 shift /* i : scaling to get 12bits */ +); +void Ener_per_band_comp_fx( + const Word16 exc_diff[], /* i : target signal Q_exc_diff */ + Word16 y_gain4[], /* o : Energy per band to quantize Q12 */ + const Word16 Q_exc_diff, + const Word16 Mband, /* i : Max band */ + const Word16 Eflag +); +void acelp_core_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 inp_fx[], /* i : input signal of the current frame */ + const Word16 vad_flag_fx, + const Word32 ener_fx, /* i : residual energy from Levinson-Durbin*/ + const Word16 pitch[3], /* i : open-loop pitch values for quantiz. */ + const Word16 voicing_fx[3], /* i : Open-loop pitch gains */ + Word16 A_fx[NB_SUBFR16k*(M+1)], /* i : A(z) unquantized for the 4 subframes*/ + Word16 Aw_fx[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/ + const Word16 epsP_h_fx[M+1], /* i : LP prediction errors */ + const Word16 epsP_l_fx[M+1], /* i : LP prediction errors */ + Word16 lsp_new_fx[M], /* i : LSPs at the end of the frame */ + Word16 lsp_mid_fx[M], /* i : LSPs in the middle of the frame */ + Word16 coder_type_fx, /* i : coding type */ + const Word16 sharpFlag_fx, /* i : formant sharpening flag */ + Word16 vad_hover_flag_fx, + const Word16 gsc_attack_flag_fx, /* i : flag signalling attack encoded by AC mode (GSC) */ + Word32 bwe_exc_extended_fx[], /* i/o: bandwidth extended excitation */ + Word16 *voice_factors_fx, /* o : voicing factors */ + Word16 old_syn_12k8_16k_fx[], /* o : intermediate ACELP synthesis at 12.8kHz or 16kHz to be used by SWB BWE */ + Word16 pitch_buf_fx[NB_SUBFR16k], /* o : floating pitch for each subframe */ + Word16 *unbits_fx, /* o : number of unused bits */ + const Word16 Q_new, + const Word16 shift +); + +#define EDCT_FACTOR_SCALE 2 +void edct_fx( + const Word32 *x, /* i : input signal Qq */ + Word32 *y, /* o : output transform Qq */ + Word16 length, /* i : length */ + Word16 *q /* i : Q value of input signal */ +); + +void edst_fx( + const Word32 *x, /* i : input signal Qq */ + Word32 *y, /* o : output transform Qq */ + Word16 length, /* i : length */ + Word16 *q /* i : Q value of input signal */ +); + +void DoRTFTn_fx( + Word32 *x, /* i/o : real part of input and output data */ + Word32 *y, /* i/o : imaginary part of input and output data */ + const Word16 n /* i : size of the FFT up to 1024 */ +); + +void edct2_fx( + Word16 n, + Word16 isgn, + Word16 *in, + Word32 *a, + Word16 *q, + const Word16 *ip, + const Word16 *w +); +void DoRTFT160_16fx( + Word16 x[], /* i/o : real part of input and output data */ + Word16 y[] /* i/o : imaginary part of input and output data */ +); +void DoRTFT320_16fx( + Word16 *x, /* i/o : real part of input and output data */ + Word16 *y /* i/o : imaginary part of input and output data */ +); +void DoRTFT128_16fx( + Word16 *x, /* i/o : real part of input and output data Q(Qx+Q_edct)*/ + Word16 *y /* i/o : imaginary part of input and output data Q(Qx+Q_edct)*/ +); +void edct_16fx( + const Word16 *x, /* i : input signal Qx */ + Word16 *y, /* o : output transform Qx */ + Word16 length, /* i : length */ + Word16 bh /* bit-headroom */ +); +void highband_exc_dct_in_fx( + const Word32 core_brate, /* i : core bitrate */ + const Word16 *mfreq_bindiv_loc, /* i : bin per bands tables */ + Word16 last_bin, /* i : last bin of bit allocation */ + Word16 Diff_len, /* i : number of bin before cut-off frequency */ + Word16 noise_lev, /* i : pulses dynamic */ + Word16 pit_band_idx, /* i : bin position of the cut-off frequency */ + Word16 *exc_diffQ, /* i : frequency coefficients of per band */ + Word16 *seed_tcx, /* i : Seed for noise */ + Word16 *Ener_per_bd_iQ, /* i : Quantized energy of targeted vector */ + Word16 nb_subfr, /* i : Number of subframe considered */ + Word16 *exc_dct_in, /* o : dct of residual signal */ + Word16 last_coder_type, /* i : coding type of last frame */ + Word16 *bitallocation_band, /* i : bit allocation flag of each band */ + Word16 *lsf_new, /* i : LSFs at the end of the frame */ + Word16 *last_exc_dct_in, /* i : dct of residual signal of last frame */ + Word16 *last_ener, /* i : frequency energy of last frame */ + Word16 *last_bitallocation_band, /* i : bit allocation flag of each band of last frame */ + Word16 *bitallocation_exc, /* i : flag of decoded coefficients */ + Word16 bfi, /* i : bad frame indicator */ + const Word16 coder_type, /* i : coder type */ + Word16 bwidth, + Word16 *exc_wo_nf , /* o : temporal excitation (in f domain) without noisefill */ + Word16 Qexc_diffQ, + Word16 Q_exc, + const Word16 GSC_noisy_speech + ,Word16 *lt_ener_per_band_fx /* i/o: Average per band energy */ +); + + +void long_enr_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 Etot, /* i : total channel E (see lib_enc\analy_sp.c) */ + const Word16 localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ + Word16 high_lpn_flag +); + +Word16 correlation_shift_fx( /* o : noise dependent voicing correction Q15 */ + Word16 totalNoise_fx /* i/o: noise estimate over all critical bands Q8 */ +); + +void analy_lp_fx( + const Word16 speech[], /* i : pointer to the speech frame */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 L_look, /* i : look-ahead */ + Word32 *ener, /* o : residual energy from Levinson-Durbin */ + Word16 A[], /* o : A(z) filter coefficients */ + Word16 epsP_h[], /* o : LP analysis residual energies for each iteration */ + Word16 epsP_l[], /* o : LP analysis residual energies for each iteration */ + Word16 lsp_new[], /* o : current frame LSPs */ + Word16 lsp_mid[], /* o : current mid-frame LSPs */ + Word16 lsp_old[], /* i/o: previous frame unquantized LSPs */ + const Word16 Top[2], /* i : open loop pitch lag */ + const Word16 Tnc[2], /* i : open loop pitch gain */ + const Word32 Core_sr, /* i : Internal core sampling rate */ + Word16 Q_new, + Word16 *Q_r +); + +void analy_lp_AMR_WB_fx( + const Word16 speech[], /* i : pointer to the speech frame */ + Word32 *ener, /* o : residual energy from Levinson-Durbin */ + Word16 A[], /* o : A(z) filter coefficients */ + Word16 epsP_h[], /* o : LP analysis residual energies for each iteration */ + Word16 epsP_l[], /* o : LP analysis residual energies for each iteration */ + Word16 isp_new[], /* o : current frame ISPs */ + Word16 isp_old[], /* i/o: previous frame unquantized ISPs */ + Word16 isf_new[], /* o : current frame ISPs */ + Word16 Top, /* i : open loop pitch lag */ + Word16 Tnc, /* i : open loop pitch gain */ + Word16 Q_new, + Word16 *Q_r +); + +void a2rc_fx(const Word16 *a, Word16 *refl,Word16 lpcorder); + +Word32 invert_dp(Word40 Linput, Word16 n, Word16 *Qout, Word16 wb_mode_bit); + +void vad_param_updt_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + Word16 pitch[3], /* i : open loop pitch lag for each half-frame Q0*/ + Word16 voicing[3], /* i : maximum normalized correlation for each half-frame Q15*/ + const Word16 old_pitch1,/* i : OL pitch value from last frame */ + Word16 corr_shift, /* i : correlation shift Q15*/ + Word16 vad_flag, /* i : vad flag Q0*/ + const Word16 Az[] /* i: a coeffs */ +); + +void pitch_ol2_fx( + const Word16 pit_min, /* i : minimum pitch value (20 or 29) */ + const Word16 pitch_ol, /* i : pitch to be improved */ + Word16 *pitch_fr_fx, /* o : adjusted 1/4 fractional pitch */ /*Q7 */ + Word16 *voicing_fr_fx, /* o : adjusted 1/4 fractional voicing */ /*Q15 */ + const Word16 pos, /* i : position in frame where to calculate the improv. */ + const Word16 *wsp_fx, /* i : weighted speech for current frame and look-ahead */ /*Q_new-1+shift*/ + const Word16 delta /* i : delta for pitch search (2 or 7) */ +); + +void pitch_ol_fx( + Word16 pitch[3], /* o : open loop pitch lag for each half-frame in range [29,231] Q0 */ + Word16 voicing[3], /* o : maximum normalized correlation for each half-frame in [0,1.0[ Q15 */ + Word16 *old_pitch, /* i/o: pitch of the 2nd half-frame of previous frame (i.e. pitch[1]) Q0 */ + Word16 *old_corr, /* i/o: correlation of old_pitch (i.e. voicing[1] or corr_mean) Q15 */ + Word16 corr_shift, /* i : normalized correlation correction Q15 */ + Word16 *old_thres, /* i/o: maximum correlation weighting with respect to past frame pitch Q15 */ + Word16 *delta_pit, /* i/o: old pitch extrapolation correction in range [-14,+14] Q0 */ + Word16 *st_old_wsp2, /* i/o: weighted speech memory qwsp */ + const Word16 *wsp, /* i : weighted speech for current frame and look-ahead qwsp */ + Word16 mem_decim2[3], /* i/o: wsp decimation filter memory qwsp */ + const Word16 relE, /* i : relative frame energy Q8 */ + const Word16 last_class, /* i : frame classification of last frame */ + const Word16 bwidth, /* i : bandwidth */ + const Word16 Opt_SC_VBR /* i : SC-VBR flag */ +); + +void Scale_wsp( + Word16 *wsp, /* i : Weigthed speech */ + Word16 *old_wsp_max, /* i : Last weigthed speech maximal valu */ + Word16 *shift, /* i/o: Scaling of current frame */ + Word16 *Q_exp, /* i/o: Differential scaling factor */ + Word16 *old_wsp_shift, /* i/o: Last wsp scaling */ + Word16 *old_wsp, /* i/o: Old weighted speech buffer */ + Word16 *mem_decim2, /* i/o: Decimation buffer */ + Word16 *old_wsp12k8, /* i/o: wsp memory @ 12.8 kHz used in pitol2 */ + const Word16 Len_p_look /* i : L_frame + look ahead */ +); + +Word16 multi_harm_fx( /* o : frame multi-harmonicity (1-harmonic, 0-not) */ + const Word16 Bin_E[], /* i : log-energy spectrum of the current frame Q7 */ + Word16 old_S[], /* i/o: prev. log-energy spectrum w. subtracted floor Q7 */ + Word16 cor_map_LT[], /* i/o: LT correlation map Q15 */ + Word16 *multi_harm_limit, /* i/o: multi harminic threshold Q9 */ + const Word32 total_brate, /* i : total bitrate Q0 */ + const Word16 bwidth, /* i : input signal bandwidth Q0 */ + Word16 *cor_strong_limit, /* i/o: HF correlation indicator Q0 */ + Word16 *st_mean_avr_dyn, /* i/o: long term average dynamic Q7 */ + Word16 *st_last_sw_dyn, /* i/o: last dynamic Q7 */ + Word16 *cor_map_sum /* Q8 */ + , Word16 *sp_floor /* o : noise floor estimate Q7 */ +); + +Word16 find_uv_fx( /* o : coding type */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *T_op_fr, /* i : pointer to adjusted fractional pitch (4 val.) Q6 */ + const Word16 *voicing_fr, /* i : refined correlation for each subframes Q15 */ + const Word16 *voicing, /* i : correlation for 3 half-frames Q15 */ + const Word16 *speech, /* i : pointer to speech signal for E computation Q_new*/ + const Word16 localVAD, /* i : vad without hangover */ + const Word32 *ee, /* i : lf/hf Energy ratio for present frame Q6 */ + const Word16 corr_shift, /* i : normalized correlation correction in noise Q15 */ + const Word16 relE, /* i : relative frame energy Q8 */ + const Word16 Etot, /* i : total energy Q8 */ + const Word32 hp_E[], /* i : energy in HF Q_new + Q_SCALE */ + const Word16 Q_new, + Word16 *flag_spitch, /* i/o: flag to indicate very short stable pitch and high correlation */ + const Word16 voicing_sm /* i : smoothed open-loop pitch gains */ + , const Word16 shift + , const Word16 last_core_orig /* i : original last core */ +); + +Word16 signal_clas_fx( /* o : classification for current frames */ + Encoder_State_fx *st, /* i/o: encoder state structure */ + Word16 *coder_type, /* i/o: coder type */ + const Word16 voicing[3], /* i : normalized correlation for 3 half-frames */ + const Word16 *speech, /* i : pointer to speech signal for E computation */ + const Word16 localVAD, /* i : vad without hangover */ + const Word16 pit[3], /* i : open loop pitch values for 3 half-frames */ + const Word32 *ee, /* i : lf/hf E ration for 2 half-frames */ + const Word16 relE, /* i : frame relative E to the long term average */ + const Word16 L_look , /* i : look-ahead */ + Word16 *uc_clas /* o : temporary classification used in music/speech class*/ +); + +void find_tilt_fx( + const Word32 fr_bands[], /* i : energy in frequency bands Q_new + Q_SCALE*/ + const Word32 bckr[], /* i : per band background noise energy estimate Q_new + Q_SCALE*/ + Word32 ee[2], /* o : lf/hf E ration for present frame Q6*/ + const Word16 pitch[3], /* i : open loop pitch values for 3 half-frames Q0*/ + const Word16 voicing[3], /* i : normalized correlation for 3 half-frames Q15*/ + const Word32 *lf_E, /* i : per bin energy for low frequencies Q_new + Q_SCALE - 2*/ + const Word16 corr_shift, /* i : normalized correlation correction Q15*/ + const Word16 bwidth, /* i : input signal bandwidth */ + const Word16 max_band, /* i : maximum critical band */ + Word32 hp_E[], /* o : energy in HF Q_new + Q_SCALE*/ + const Word16 codec_mode, /* i : MODE1 or MODE2 */ + const Word16 Q_new, /* i : scaling factor */ + Word32 *bckr_tilt_lt + ,Word16 Opt_vbr_mode +); +void synth_mem_updt2( + const Word16 L_frame, /* i : frame length */ + const Word16 last_L_frame, /* i : frame length */ + Word16 old_exc[], /* i/o: excitation buffer */ + Word16 mem_syn_r[], /* i/o: synthesis filter memory */ + Word16 mem_syn2[], /* o : synthesis filter memory for find_target */ + Word16 mem_syn[], /* o : synthesis filter memory for find_target */ + const Word16 dec /* i : flag for decoder indication */ +); +void swb_hr_noise_fill_fx( + const Word16 is_transient, /* i : transient flag */ + const Word16 spect_start, /* i : spectrum start point */ + const Word16 spect_end, /* i : spectrum end point */ + const Word16 tilt_wb, /* i : tilt of wideband signal */ + const Word16 pitch, /* i : pitch value */ + const Word16 nq[], /* i : AVQ nq index */ + Word16 Nsv, /* i : number of subband */ + Word16 *bwe_highrate_seed, /* i/o: seed of random noise */ + Word16 *t_audio, /* i/o: mdct spectrum */ + Word16 Q_audio +); +Word16 swb_bwe_dec_hr_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 *syn_12k8_16k_fx, /* i : ACELP core synthesis @16kHz */ + const Word16 old_syn_exp, /* i : Exponent of core synthesis */ + Word16 *hb_synth_fx, /* o : SHB synthesis */ + const Word16 output_frame, /* i : frame length */ + const Word16 unbits, /* i : number of core unused bits */ + const Word16 pitch_buf[] /* i : pitch buffer */ +); +Word32 calc_tilt_bwe_fx( /* o : Tilt in Q24 */ + const Word16 *sp0, /* i : input signal */ + const Word16 exp, /* i : Exp of inp signal */ + const Word16 N /* i : signal length */ +); +void Inverse_Transform( + const Word32 *in_mdct, /* i : input MDCT vector */ + Word16 *Q, /* i/o: Q value of input */ + Word32 *out, /* o : output vector */ + const Word16 is_transient, /* i : transient flag */ + const Word16 L, /* i : output frame length */ + const Word16 L_inner /* i : length of the transform */ +); +void iedct_short_fx( + const Word32 *in, /* i : input vector */ + Word16 *Q, /* i/o: Q value of input */ + Word32 *out, /* o : output vector */ + const Word16 segment_length /* i : length */ +); + +void swb_bwe_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *old_input_12k8_fx, /* i : input signal @12.8kHz for SWB BWE */ + Word16 *old_input_16k_fx, /* i : input signal @16kHz for SWB BWE */ + const Word16 *old_syn_12k8_16k_fx, /* i : ACELP core synthesis at 12.8kHz or 16kHz */ + const Word16 *new_swb_speech_fx, /* i : original input signal at 32kHz */ + Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz */ + const Word16 coder_type, /* i : coding type */ + Word16 Q_shb_speech, + Word16 Q_slb_speech +); +void wb_bwe_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *new_wb_speech_fx, /* i : original input signal at 16kHz */ + Word16 coder_type /* i : coding type */ +); + +Word16 WB_BWE_encoding_fx( /* o : classification of wb signal */ + const Word16 coder_type, /* i : coder type */ + const Word16 *yos_fx, /* i : MDCT coefficients of weighted original */ + Word16 *WB_fenv_fx, /* i/o: energy of WB envelope */ + Encoder_State_fx *st_fx, /* i/o: Encoder structure */ + Word16 Q_synth, + Word16 Q_synth_lf +); + + +Word16 wb_bwe_dec_fx( + Word16 *synth_fx, /* i/o: ACELP core synthesis/final synthesis */ + Word16 *hb_synth_fx, /* o : SHB synthesis/final synthesis */ + const Word16 output_frame, /* i : frame length */ + Word16 coder_type, /* i : coding type */ + Word16 *voice_factors_fx, /* i : voicing factors */ + const Word16 pitch_buf_fx[], /* i : pitch buffer */ + Decoder_State_fx *st_fx /* i/o: decoder state structure */ + ,Word16 * Qpost +); + +Word16 WB_BWE_gain_deq_fx( + Decoder_State_fx *st_fx , /* i/o: decoder state structure */ + Word16 *WB_fenv +); +Word16 swb_bwe_gain_deq_fx( /* o : BWE class */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 core, /* i : core */ + Word16 *SWB_tenv, /* o : Q0, time-domain BWE envelope */ + Word16 *SWB_fenv, /* o : Q1, frequency-domain BWE envelope */ + const Word16 hr_flag, /* i : high rate flag */ + const Word16 hqswb_clas /* i : HQ BWE class */ +); + +Word16 swb_bwe_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *synth_fx, /* i : ACELP core synthesis/final synthesis */ + Word16 *hb_synth, /* o : SHB synthesis/final synthesis */ + const Word16 output_frame /* i : frame length */ + ,Word16 * Qpost + ,Word16 coder_type /* i : coding type */ +); + +Word16 WB_BWE_gain_pred_fx( + Word16 *WB_fenv, /* o : WB frequency envelopes */ + const Word16 *core_dec_freq, /* i : Frequency domain core decoded signal */ + const Word16 coder_type, /* i : coding type */ + Word16 prev_coder_type, /* i : coding type of last frame */ + Word16 prev_WB_fenv, /* i : envelope for last frame */ + Word16 *voice_factors, /* i : voicing factors Q15 */ + const Word16 pitch_buf[], /* i : pitch buffer Q6 */ + Word32 last_core_brate, /* i : previous frame core bitrate */ + Word16 last_wb_bwe_ener , /* i : previous frame wb bwe signal energy */ + Word16 Q_syn + ,Word16 last_extl_fx, + Word16 tilt_wb_fx +); +void calc_normal_length_fx( + const Word16 core, /* i : core */ + const Word16 *sp, /* i : input signal */ + const Word16 mode, /* i : input mode */ + const Word16 extl, /* i : extension layer */ + Word16 *L_swb_norm, /* o : normalize length */ + Word16 *prev_L_swb_norm, /*i/o : last normalize length */ + Word16 Q_syn +); + +void calc_norm_envelop_fx( + const Word16 SWB_signal[], /* i : SWB spectrum Q_syn*/ + Word32 *envelope, /* o : normalized envelope Q_syn*/ + const Word16 L_swb_norm, /* i : length of envelope Q0 */ + const Word16 SWB_flength, /* i : Length of input/output */ + const Word16 st_offset /* i : offset */ +); + +void WB_BWE_decoding_fx( + const Word16 *core_dec_freq, /* i : Frequency domain core decoded signal */ + Word16 *WB_fenv, /* i : WB frequency envelopes */ + Word32 *WB_signal32, /* o : WB signal in MDCT domain */ + const Word16 WB_flength, /* i : Length of input/output */ + const Word16 mode, /* i : classification for WB signal */ + const Word16 last_extl, /* i : extl. layer for last frame */ + Word32 *prev_Energy, /* i/o: energy for last frame */ + Word16 *prev_WB_fenv, /* i/o: envelope for last frame */ + Word16 *prev_L_wb_norm, /* i/o: length for last frame wb norm */ + const Word16 extl, /* i : extension layer */ + const Word16 coder_type, /* i : coding type */ + const Word32 total_brate, /* i : core layer bitrate */ + Word16 *Seed, /* i/o: random generator seed */ + Word16 *prev_flag, /* i/o: attenu flag of last frame */ + Word16 prev_coder_type , /* i : coding type of last frame */ + Word16 Q_syn, + Word16 *Q_syn_hb /*o : Q value of WB_signal_32 */ +); + +void SWB_BWE_decoding_fx( + const Word16 *core_dec_freq, /* i : Frequency domain core decoded signal */ + Word16 *SWB_fenv, /* i/o: SWB frequency envelopes */ + Word32 *SWB_signal, /* o : SWB signal in MDCT domain */ + const Word16 SWB_flength, /* i : Length of input/output */ + const Word16 mode, /* i : classification for SWB signal */ + Word16 *frica_flag, /* o : fricative signal flag */ + Word16 *prev_Energy, /* i/o: energy for last frame */ + Word16 *prev_SWB_fenv, /* i/o: envelope for last frame */ + Word16 *prev_L_swb_norm, /* i/o: length for last frame wb norm */ + const Word16 tilt_nb, /* i : tilt of synthesis wb signal */ + Word16 *Seed, /* i/o: random generator seed */ + const Word16 st_offset, /* i : offset value due to different core */ + Word16 *prev_weight, /* i/o: excitation weight value of last frame */ + const Word16 extl , /* i : extension layer */ + Word16 Q_syn + ,const Word16 last_extl /* i : extension layer of last frame */ +); +void time_envelop_shaping_fx( + Word16 werr[], /* i/o: SHB synthesis Q_synth*/ + Word32 SWB_tenv[], /* i/o: frequency envelope Q15*/ + const Word16 L , /* i : frame length */ + Word16 *Q_synth +); +void time_reduce_pre_echo_fx( + const Word16 *synth, /* i : ACELP core synthesis Q_syn*/ + Word16 *error, /* i/o: SHB BWE synthesis Q0*/ + Word16 prev_td_energy, /* o : last td energy Q0*/ + const Word16 L, /* i : subframe length */ + Word16 Q_syn, + Word16 Q_synth +); +/*Word16 detect_transient_fx( */ +/* const Word16 *in_fx, *//*Q_new */ +/* Encoder_State *st, */ +/* const Word16 L, */ +/* const Word16 coder_type , */ /* i : coder type */ +/* Word16 Q_new, */ +/*Encoder_State_fx *st_fx */ +/*); */ + + +void preset_hq2_swb_fx +( + const Word16 hqswb_clas_fx, /* i : HQ2 class information */ + const Word16 band_end_fx[], /* i : band end of each SB */ + Word16 *har_bands_fx, /* i/o : Number of LF harmonic bands */ + Word16 p2a_bands_fx, /* i : flag for peakness */ + const Word16 length_fx, /* i : processed band length */ + const Word16 bands_fx, /* i : Total number of Subbands in a frame */ + Word16 *lowlength_fx, /* o : lowband length */ + Word16 *highlength_fx, /* o : highband length */ + Word32 L_m[] /* o : MDCT */ +); +void post_hq2_swb_fx +( + const Word32 L_m[], /* i : input_signal */ + const Word16 lowlength_fx, /* i : lowband length */ + const Word16 highlength_fx, /* i : highband length */ + const Word16 hqswb_clas_fx, /* i : HQ2 class information */ + const Word16 har_bands_fx, /* i : Number of LF harmonic bands */ + const Word16 bands_fx, /* i : Total number of Subbands in a frame */ + const Word16 p2a_flags_fx[], /* i : HF tonal indicator */ + const Word16 band_start_fx[], /* i : band start of each SB */ + const Word16 band_end_fx[], /* i : band end of each SB */ + Word32 L_y2[], /* o : output signal */ + Word16 npulses_fx[] /* i/o : Number of coded spectrum */ +); + +void swb_bwe_enc_lr_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 L_m_core[], /* i : lowband synthesis */ + Word16 QsL, + const Word32 L_m_orig[], /* i/o: scaled orig signal (MDCT) */ + Word32 L_m[], /* o : highband synthesis with lowband zeroed */ + const Word32 L_total_brate, /* i : total bitrate for selecting subband pattern */ + Word16 BANDS_fx, /* i : Total number of Subbands in a frame */ + Word16 *band_start_fx, /* i : band start of each SB */ + Word16 *band_end_fx, /* i : band end of each SB */ + Word32 *L_band_energy, /* i : band_energy of each SB */ + Word16 Qbe, /* i : Q value of band energy */ + Word16 *p2a_flags_fx, /* i : HF tonal indicator */ + const Word16 hqswb_clas_fx, /* i : HQ_NORMAL2 or HQ_HARMONIC mode */ + Word16 lowlength_fx, /* i : lowband length */ + Word16 highlength_fx, /* i : highband length */ + Word16 *prev_frm_index_fx, /* i/o: previous frame lag index for harmonic mode */ + const Word16 har_bands_fx, /* i : Number of LF harmonic bands */ + Word16 *prev_frm_hfe2, /* i/o: */ + Word16 *prev_stab_hfe2, /* i/o: */ + const Word16 band_width_fx[], /* i : band_width information */ + const Word32 L_y2_ni[], /* i : band_width information */ + Word16 *ni_seed_fx /* i/o: random seed for search buffer NI */ +); + +void swb_bwe_dec_lr_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 L_m_core[], /* i : lowband synthesis */ + const Word16 QsL, /* i : Q value of m_core */ + Word32 L_m[], /* o : highband synthesis with lowband zeroed */ + const Word32 L_total_brate, /* i : total bitrate for selecting subband pattern */ + Word16 BANDS_fx, /* i : Number subbands/Frame */ + Word16 *band_start_fx, /* i : Band Start of each SB */ + Word16 *band_end_fx, /* i : Band end of each SB */ + Word32 *L_band_energy, /* i : Band energy of each SB : Qbe */ + Word16 Qbe, /* i : Q value of band energy */ + Word16 *p2a_flags_fx, /* i : HF tonal Indicator */ + const Word16 hqswb_clas_fx, /* i : class information */ + Word16 lowlength_fx, /* i : Lowband Length */ + Word16 highlength_fx, /* i : Highband Length */ + const Word16 har_bands_fx, /* i : Number of LF harmonic bands */ + Word16 *prev_frm_hfe2_fx, /* i/o: */ + Word16 *prev_stab_hfe2_fx, /* i/o: */ + Word16 band_width_fx[], /* i : subband bandwidth */ + const Word32 L_y2_ni[], /* i/o: Sparse filled corecoder */ + Word16 *ni_seed_fx /* i/o: random seed */ +); + +void GetPredictedSignal_fx( + const Word16 *predBuf_fx, /* i: Q8 */ + Word32 *L_outBuf, /* o: Q9 */ + const Word16 lag_fx, /* i: Q0 */ + const Word16 fLen_fx, /* i: Q0 */ + const Word16 lagGains_fx, /* i: Qgain */ + const Word16 Qgain /* i: Q0 */ +); + +void Get20Log10Spec_fx( + const Word32 *L_inBuf, /* i : input Q_inBuf */ + Word16 *outBuf_fx, /* o : output Q7 */ + const Word16 fLen, /* i : loop length */ + const Word16 Q_inBuf /* i : Qvalue of L_inBuf */ +); + +void convert_lagIndices_pls2smp_fx( + Word16 lagIndices_in_fx[], + Word16 nBands_search_fx, + Word16 lagIndices_out_fx[], + const Word16 sspectra_fx[], + const Word16 sbWidth_fx[], + const Word16 fLenLow_fx +); + +Word16 get_usebit_npswb_fx( + Word16 hqswb_clas_fx +); + +void SpectrumSmoothing_nss_fx( + const Word32 *L_inBuf, /* i : lowband MDCT */ + Word16 *outBuf_fx, /* o : output */ + Word16 *Qss, /* o : Q value for output vector */ + const Word16 fLen /* i : length */ +); + +void SpectrumSmoothing_fx( + const Word32 *L_inBuf, /* i : Qs Low band MDCT */ + Word16 *outBuf_fx, /* o : Qss output */ + Word16 *Qss, /* o : Q0 Q value of output vector */ + const Word16 fLen, /* i : Q0 length */ + const Word16 th_cut_fx /* i : Qss threshold of cut */ +); + +void GetSynthesizedSpecThinOut_fx( + const Word16 *predBuf_fx, /* i : Qss: prediction buffer (i.e., lowband) */ + const Word16 Qss, /* i : Q value of input vector */ + Word32 *L_outBuf, /* o : QsL: synthesized spectrum */ + Word16 QsL, /* o : Q value of synthesized spectrum */ + const Word16 nBands_fx, /* i : Q0: number of subbands calculated */ + const Word16 *sbWidth_fx, /* i : Q0: subband lengths */ + const Word16 *lagIndices_fx, /* i : Q0: lowband index for each subband */ + const Word16 *lagGains_fx, /* i : Qgain: lagGain for each subband */ + const Word16 *QlagGains_fx, /* i : Q0: Q value of lagGains_fx */ + const Word16 predBufLen_fx /* i : Q0: lowband length */ +); + +Word32 hq2_bit_alloc_fx ( + const Word32 L_band_energy[], /* i : band energy of each subband */ + const Word16 bands, /* i : total number of subbands in a frame */ + Word32 L_Rk[], /* i/o: Bit allocation/Adjusted bit alloc. */ + Word16 *bit_budget_fx, /* i/o: bit bugdet */ + Word16 *p2a_flags, /* i : HF tonal indicator */ + const Word16 weight_fx, /* i : weight */ + const Word16 band_width[], /* i : Sub band bandwidth */ + const Word16 num_bits, /* i : available bits */ + const Word16 hqswb_clas, /* i : HQ2 class information */ + const Word16 bwidth, /* i : input bandwidth */ + const Word16 is_transient /* i : indicator HQ_TRANSIENT or not */ +); + +void hq2_noise_inject_fx( + Word32 L_y2[], + const Word16 band_start[], + const Word16 band_end[], + const Word16 band_width[], + Word32 Ep_fx[], + Word32 Rk_fx[], + const Word16 npulses[], + Word16 ni_seed, + const Word16 bands, + const Word16 ni_start_band, + const Word16 bw_low, + const Word16 bw_high, + const Word32 enerL_fx, + const Word32 enerH_fx, + Word32 last_ni_gain_fx[], + Word16 last_env_fx[], + Word16 *last_max_pos_pulse, + Word16 *p2a_flags, + Word16 p2a_bands, + const Word16 hqswb_clas, + const Word16 bwidth, + const Word32 bwe_br +); + +void reordvct_fx( + Word16 *y, /* i/o: vector to rearrange */ + const Word16 N, /* i : dimensions */ + Word16 *idx /* o : reordered vector index */ +); + +void Bits2indvsb_fx ( + const Word32 *L_be, /* i : Q14 Band Energy of sub-band */ + const Word16 start_band, /* i : Q0 start band indices */ + const Word16 end_band, /* i : Q0 end band indices */ + const Word16 Bits, /* i : Q0 Total number of bits allocated to a group */ + const Word32 L_Bits_needed, /* i : Q0 smallest bit number for allocation in group */ + Word32 *L_Rsubband, /* o : Q18 bit allocation of sub-band */ + Word16 *p2aflags_fx /* i/o: Q0 peaky/noise subband flag */ +); + +void hq2_bit_alloc_har_fx ( + const Word32 *L_y, /* i : Q14 band energy of sub-vectors */ + Word16 B_fx, /* i : Q0 number of available bits */ + const Word16 N_fx, /* i : Q0 number of sub-vectors */ + Word32 *L_Rsubband, /* o : Q18 sub-band bit-allocation vector */ + Word16 p2a_bands_fx, /* i : Q0 highfreq bands */ + const Word32 L_core_brate, /* i : Q0 core bit rate */ + Word16 p2a_flags_fx[], /* i/o: Q0 p2a_flags */ + const Word16 band_width_fx[] /* i : Q0 table of band_width */ +); + +void hq2_core_configure_fx ( + const Word16 frame_length, + const Word16 num_bits, + const Word16 is_transient, + Word16 *bands, + Word16 *length, + Word16 band_width[], + Word16 band_start[], + Word16 band_end[], + Word32 *L_qint, + Word16 *eref, + Word16 *bit_alloc_weight, + Word16 *gqlevs, + Word16 *Ngq, + Word16 *p2a_bands, + Word16 *p2a_th, + Word16 *pd_thresh, + Word16 *ld_slope, + Word16 *ni_coef, + Word32 L_bwe_br +); + +void hq_lr_enc_fx( + Encoder_State_fx *st_fx, /* i/o: : encoder state structure */ + Word32 L_t_audio[], /* i/o: Q12 : transform-domain coefs. */ + const Word16 inner_frame_fx, /* i : Q0 : inner frame length */ + Word16 *num_bits_fx, /* i/o: Q0 : number of available bits */ + const Word16 is_transient_fx /* i : Q0 : transient flag */ +); + +void hq_lr_dec_fx( + Decoder_State_fx *st_fx, /* i/o: : decoder state structure */ + Word32 L_yout[], /* o : Q12 : transform-domain output coefs. */ + const Word16 inner_frame, /* i : Q0 : inner frame length */ + Word16 num_bits, /* i : Q0 : number of available bits */ + Word16 *is_transient_fx /* o : Q0 : transient flag */ +); + +void reverse_transient_frame_energies_fx( + Word32 L_band_energy[], /* o : Q14 : band energies */ + const Word16 bands /* i : Q0 : number of bands */ +); + +Word16 har_est_fx( + Word32 L_spectra[], /* i : coded spectrum */ + Word16 N, /* i : length of the desired spectrum */ + Word16 *har_freq_est1, /* i/o: Estimation harmonics 1 */ + Word16 *har_freq_est2, /* o : Estimation harmonics 2 */ + Word16 *flag_dis, /* i/o: flag for BWE reconstruction */ + Word16 *prev_frm_hfe2, /* i/o: Estimated harmonic update */ + const Word16 subband_search_offset[], /* i : Subband Search range */ + const Word16 sbWidth[], /* i : Subband Search range */ + Word16 *prev_stab_hfe2 /* i/o: Estimated harmonic position */ +); + +typedef struct GainItemStr_fx +{ + Word16 nmrValue_fx; + Word16 gainIndex_fx; +} GainItem_fx; + +void genhf_noise_fx( + Word16 noise_flr_fx[], /* i : Qss smoothed non tonal */ /* sspectra_diff_fx:Qss */ + Word16 Qss, /* i : Q0 Q value */ + Word32 L_xSynth_har[], /* o : QsL hf non tonal components */ /* xSynth_har:QsL */ + Word16 QsL, /* i : Q0 Q value */ + Word16 *predBuf_fx, /* i : Qss smoothed tonal compone */ /* sspectra:Qss */ + Word16 bands, /* i : Q0 total number of subbands in a frame */ + Word16 harmonic_band, /* i : Q0 Number of LF harmonic frames */ + Word16 har_freq_est2, /* i : Q0 harmonic signal parameter */ + Word16 pos_max_hfe2, /* i : Q0 last pulse in core coder */ + Word16 *pul_res, /* o : Q0 pulse resolution */ + GainItem_fx pk_sf_fx[], /* o : representative region */ + const Word16 fLenLow, /* i : Q0 low frequency length */ + const Word16 fLenHigh, /* i : Q0 high frequency length */ + const Word16 sbWidth[], /* i : Q0 bandwidth for high bands */ + const Word16 lagIndices[], /* i : Q0 correlation indices for most representative */ + const Word16 subband_offsets[], /* i : Q0 band offsets for HF reconstruction */ + const Word16 subband_search_offset[] /* i : Q0 most representative regions offsets in LF */ +); + +void spt_shorten_domain_pre_fx( + const Word16 band_start[], /* i: Starting position of sub band */ + const Word16 band_end[], /* i: End position of sub band */ + const Word16 prev_SWB_peak_pos[], /* i: Spectral peak */ + const Word16 BANDS, /* i: total number of bands */ + const Word32 L_bwe_br, /* i: bitrate information */ + Word16 new_band_start[], /* o: Starting position of new shorten sub band */ + Word16 new_band_end[], /* o: End position of new shorten sub band */ + Word16 new_band_width[] /* o: new sub band bandwidth */ +); + +void spt_shorten_domain_band_save_fx( + const Word16 bands, /* i: total subband */ + const Word16 band_start[], /* i: starting position of subband */ + const Word16 band_end[], /* i: end position of subband */ + const Word16 band_width[], /* i: band width of subband */ + Word16 org_band_start[], /* o: starting position of subband */ + Word16 org_band_end[], /* o: end position of subband */ + Word16 org_band_width[] /* o: band width of subband */ +); + +void spt_shorten_domain_band_restore_fx( + const Word16 bands, /* i: total subband */ + Word16 band_start[], /* i/o: starting position of subband */ + Word16 band_end[], /* i/o: end position of subband */ + Word16 band_width[], /* i/o: band width of subband */ + const Word16 org_band_start[], /* o: starting position of subband */ + const Word16 org_band_end[], /* o: end position of subband */ + const Word16 org_band_width[] /* o: band width of subband */ +); + +void spt_swb_peakpos_tmp_save_fx( + const Word32 L_y2[], /* i: coded spectral information */ + const Word16 bands, /* i: total number of bands */ + const Word16 band_start[], /* i: starting position of subband */ + const Word16 band_end[], /* i: end position of subband */ + Word16 prev_SWB_peak_pos_tmp[] /* o: spectral peaks */ +); + +Word16 div_s_ss( /* o: result of division (Word16 Q0) */ + const Word16 n, /* i: numerator (Word16 Q0 */ + const Word16 d /* i: denominator (Word16 Q0) */ +); + +void updat_prev_frm_fx( + Word32 L_y2[], /* i/o: core coder buffer */ + Word32 L_t_audio[], /* o: core coder buffer */ + Word32 L_bwe_br, /* i: core bitrate */ + Word16 length_fx, /* i: frame length coded bw */ + const Word16 inner_frame_fx, /* i: input frame length */ + Word16 bands_fx, /* i: sub band resolution */ + Word16 bwidth_fx, /* i: NB/WB/SWB indicator */ + const Word16 is_transient_fx, /* i: signal class information */ + Word16 hqswb_clas_fx, /* i: signal class information */ + Word16 *prev_hqswb_clas_fx, /* o: update signal class information */ + Word16 prev_SWB_peak_pos_fx[], /* o: update core coder last coded peaks*/ + Word16 prev_SWB_peak_pos_tmp_fx[], /* o: update core coder last coded peaks*/ + Word16 *prev_frm_hfe2_fx, /* o: update harmonics */ + Word16 *prev_stab_hfe2_fx, /* o: update harmonics */ + Word16 bws_cnt_fx /* i: band width detector */ +); + +void hf_parinitiz_fx( + const Word32 L_total_brate, + const Word16 hqswb_clas_fx, + Word16 lowlength_fx, + Word16 highlength_fx, + Word16 wBands_fx[], + const Word16 **subband_search_offset_fx, + const Word16 **subband_offsets_fx, + Word16 *nBands_fx, + Word16 *nBands_search_fx, + Word16 *swb_lowband_fx, + Word16 *swb_highband_fx +); + +void GetlagGains_fx( + const Word16 *predBuf_fx, /* i: Qss Low freq. Smoothed Spectrum */ + const Word16 Qss, /* i: Q0 Q value of predBuf */ + const Word32 *L_band_energy, /* i: Qbe Band Energy */ + const Word16 Qbe, /* i: Q0 Q value of band energy */ + const Word16 nBands, /* i: Q0 number of SWB subbands */ + const Word16 *sbWidth, /* i: Q0 width of SWB subbands */ + const Word16 *lagIndices, /* i: Q0 lagIndices */ + const Word16 predBufLen, /* i: Q0 length of predBuf */ + Word16 *lagGains_fx, /* o: QlagGains lagGains */ + Word16 *QlagGains /* o: Q0 Q value of lagGains */ +); + +void noise_extr_corcod_fx( + Word32 L_spectra[], /* i : QsL core coder */ + const Word32 L_spectra_ni[], /* i : QsL core coder with sparse filling */ + Word16 sspectra_fx[], /* o : Qss Smoothed tonal information from core coder */ + Word16 sspectra_diff_fx[], /* o : Qss non tonal infomration for gap filling */ + Word16 sspectra_ni_fx[], /* o : Qss smoothed core coder */ + const Word16 fLenLow_fx, /* i : Q0 low frequency bands width */ + Word16 prev_hqswb_clas_fx, /* i : Q0 classification information */ + Word16 *prev_ni_ratio_fx, /* i : Q15 noise paraemeter */ + Word16 *Qss /* o : Q0 Q value for sspectra_*_fx */ +); + +void ton_ene_est_fx( + Word32 L_xSynth_har[], /* i : QsL buffer with non tonal compoents */ + Word16 QsL, /* i : Q0 Q value for xSynth_har */ + Word32 L_be_tonal[], /* o : QbeL tonal energy of the missing bands */ + Word16 *QbeL, /* o : Q0 Q value for be_tonal */ + Word32 L_band_energy[], /* i : Qbe subband energies */ + Word16 Qbe, /* i : Q0 Q value for band_energy */ + const Word16 band_start[], /* i : Q0 subband start indices */ + const Word16 band_end[], /* i : Q0 subband end indices */ + const Word16 band_width[], /* i : Q0 subband widths */ + const Word16 fLenLow, /* i : Q0 low frequency width */ + const Word16 fLenHigh, /* i : Q0 High frequency width */ + Word16 bands, /* i : Q0 total subbands */ + Word16 har_bands, /* i : Q0 total number of harmonics bands */ + Word16 ni_lvl_fx, /* i : Q11 noise enve for the hf bands */ + GainItem_fx pk_sf_fx[], /* i : */ + Word16 Qss, /* i : Q0 Q value for GainItem_fx->nmrValue */ + Word16 *pul_res /* i : Q0 tonal resolution */ +); + +void Gettonl_scalfact_fx +( + Word32 *L_outBuf, /* i/o: QsL synthesized spectrum */ + Word16 QsL, /* i : Q0 Q value for outBuf */ + const Word32 *L_codbuf, /* i : QsL core coder */ + const Word16 fLenLow, /* i : Q0 lowband length */ + const Word16 fLenHigh, /* i : Q0 highband length */ + const Word16 harmonic_band, /* i : Q0 total number of Low frequency bands */ + const Word16 bands, /* i : Q0 total number of subbands in a frame */ + Word32 *L_band_energy, /* i : Qbe band energy of each subband */ + Word16 Qbe, /* i : Q0 Q value for band_energy */ + const Word16 *band_start, /* i : Q0 subband start indices */ + const Word16 *band_end, /* i : Q0 subband end indices */ + const Word16 p2aflags[], /* i : Q0 missing bands in the core coder */ + Word32 L_be_tonal[], /* i : QbeL tonal energy */ + Word16 QbeL, /* i : Q0 Q value for be_tonal */ + GainItem_fx *pk_sf_fx, /* i : toanl information for Sparse filling */ + Word16 Qss, /* i : Q0 Q value for pk_sf.nmrValue */ + Word16 *pul_res_pk /* i : Q0 pulse resolution information */ +); + + +void get_sigma_fx_har( + const Word32 L_x_abs[], /* i: Qi absolute input */ + const Word16 Qi, /* i: Q0 Q value of x_abs */ + const Word16 avg_fx, /* i: Qavg average of x_abs */ + const Word16 Qavg, /* i: Q0 Q value of avg */ + const Word16 length_fx, /* i: Q0 length */ + Word16 *sigma_fx, /* o: Qsigma sigma */ + Word16 *Qsigma /* o: Q0 Q value of sigma */ +); + +void FindNBiggest2_simple_fx_har( + const Word32 *L_inBuf, /* i : input buffer (searched) */ + const Word16 Qabs_in, /* i : Q value of input buffer */ + GainItem_fx *pk_sf_fx, /* o : N biggest components found */ + const Word16 nIdx_fx, /* i : search length */ + Word16 *n_fx, /* i : number of components searched (N biggest) */ + Word16 n_nbiggestsearch +); + +Word16 spectrumsmooth_noiseton_fx( /* o : Qss ss_min */ + Word32 L_spectra[], /* i : Qs core coder */ + /*Word16 Qs,*/ /* i : Q0 Q value for spectra, spectra_ni */ + const Word32 L_spectra_ni[], /* i : Qs core coder with sparse filling */ + Word16 sspectra_fx[], /* o : Qss Smoothed tonal information from core coder */ + Word16 sspectra_diff_fx[], /* o : Qss non tonal infomration for gap filling */ + Word16 sspectra_ni_fx[], /* o : Qss smoothed core coder */ + Word16 *Qss, /* o : Q0 Q value for sspectra* */ + const Word16 fLenLow_fx, /* i : Q0 low frequency boundaries */ + Word16 *ni_seed_fx /* io : Q0 random seed */ +); + +void noiseinj_hf_fx( + Word32 L_xSynth_har[], /* i/o : Qs gap filled information */ + Word16 Qs, /* i : Q0 Q value for xSynth_har */ + Word32 L_th_g[], /* i : Qs level adjustment information */ + Word32 L_band_energy[], /* i : Qbe subband energies */ + Word16 Qbe, /* i : Q0 Q value for band_energy */ + Word16 *prev_En_sb_fx, /* i/o : QsEn smoothed sqrt band Energies */ + const Word16 p2a_flags_fx[], /* i : Q0 Missing bands in the core coder */ + const Word16 BANDS_fx, /* i : Q0 total bands */ + const Word16 band_start_fx[], /* i : Q0 band start indices */ + const Word16 band_end_fx[], /* i : Q0 band end indices */ + const Word16 fLenLow_fx, /* i : Q0 low frequency bandwidth */ + const Word16 fLenHigh_fx /* i : Q0 SWB frequency bandwidth */ +); + +void sqrt_32n_16_fx( + Word32 L_in, /* i : input vector (Word32) */ + Word16 Qin, /* i : Q value for L_in */ + Word16 *out_fx, /* o : sqrt input vector (Word16) */ + Word16 *Qout /* o : Q value for out_fx */ +); + +void norm_vec_32_16_scale_fx( + Word32 *L_vec_in, /* i : input vector */ + Word16 Qin, /* i : Q value for input vector */ + Word16 length_fx, /* i :vector size */ + Word16 *vec_out_fx, /* o : output vectror */ + Word16 *Qout, /* o : Q value for output vectro */ + Word16 exp_safe /* i : suppress left shift: for prevend overflow on sum */ +); + +void return_bits_normal2_fx( + Word16 *bit_budget_fx, /* i/o : bit budget */ + const Word16 p2a_flags_fx[], /* i : HF tonal indicator */ + const Word16 bands_fx, /* i : Total number of Subbands in a frame */ + const Word16 bits_lagIndices_fx[] /* i : bits for lagIndices */ +); + +Word16 peak_avrg_ratio_fx( + const Word32 total_brate, + const Word32 *input_hi_fx, /* i : input signal */ + const Word16 length, /* i : number of coefficients */ + Word16 *mode_count, /* i/o: HQ_HARMONIC mode count */ + Word16 *mode_count1, /* i/o: HQ_NORMAL mode count */ + Word16 Q_coeff +); + +void diffcod_fx( + const Word16 N, /* (i) number of sub-vectors */ + Word16 *y, /* (i/o) indices of quantized norms */ + Word16 *difidx /* (o) differential code */ +); + +void diffcod_lrmdct_fx( + const Word16 N, /* i : number of sub-vectors */ + const Word16 be_ref, /* i : band energy reference */ + Word16 *y, /* i/o: indices of quantized norms */ + Word16 *difidx, /* o : differential code */ + const Word16 is_transient /* i : transient flag */ +); + +Word16 encode_envelope_indices_fx( /* o : Number of bits if flag_pack=0,0 if flag_pack=1 Q0 */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 num_sfm, /* i : Number of subbands Q0 */ + const Word16 numnrmibits, /* i : Bitrate of fall-back coding mode Q0 */ + Word16 *difidx, /* i/o: Diff indices/encoded diff indices Q0 */ + Word16 *LCmode, /* o : Coding mode if flag_pack=0, i : if flag_pack=1 Q0 */ + const Word16 flag_pack, /* i : indicator of packing or estimating bits Q0 */ + const Word16 flag_HQ2 /* i : indicator of HQ2 core Q0 */ + , + const Word16 is_transient /* i : indicator of HQ_TRANSIENT Q0 */ +); +Word16 decode_envelope_indices_fx( /* o : Number of bits */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 start_norm, /* i : starting band index */ + const Word16 num_sfm, /* i : Number of subbands */ + const Word16 numnrmibits, /* i : Bitrate of fall-back coding mode */ + Word16 *difidx, /* o : Diff indices/encoded diff indices */ + const Word16 flag_HQ2 /* i : indicator of HQ2 core */ + , + const Word16 is_transient /* i : indicator of HQ_TRANSIENT */ +); + +void hdecnrm_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 numNorms, /* (i) number of norms */ + Word16 *index); /* (o) indices of quantized norms */ + +Word16 decode_huff_context_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 *hufftab, + Word16 *rbits +); + +void hdecnrm_context_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 N, + Word16 *index, + Word16 *n_length +); + +void hdecnrm_resize_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 N, /* (i) number of SFMs */ + Word16 *index /* (o) norm quantization index vector */ +); + +void hdecnrm_tran_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 N, /* i : number of norms */ + Word16 *index /* o : indices of quantized norms */ +); + +void mdct_spectrum_denorm_fx( + const Word16 inp_vector[], /* i : Q0 : */ + Word32 L_y2[], /* i/o : Qs : decoded spectrum */ + const Word16 band_start[], /* i : Q0 : table of start freq for every subband */ + const Word16 band_end[], /* i : Q0 : table of end freq for every subband */ + const Word16 band_width[], /* i : Q0 : table of bandwidth for every subband */ + const Word32 L_band_energy[], /* i : Qbe : band energy */ + const Word16 npulses[], /* i : Q0 : number of coded spectrum */ + const Word16 bands, /* i : Q0 : numbers of subbands */ + const Word16 ld_slope_fx, /* i : Q15 : */ + const Word16 pd_thresh_fx /* i : Q15 : */ +); + +/* y(n)(Qx) = alpha(Q15) * x(Qx) + (1.0f-alpha)* y(n-1) (Qx) */ +Word16 noise_est_AR1_Qx( /* o: Qx y(n) */ + Word16 x, /* i : Qx x(n) */ + Word16 y, /* i : Qx y(n-1) */ + Word16 alpha /*i : Q15 scaling of driving x(n) */ +); +void noise_est_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word32 tmpN[], /* i : temporary noise update Q_new + QSCALE */ + const Word16 *pit, /* i : open-loop pitch values for each half-frame Q0 */ + const Word16 cor[], /* i : normalized correlation for all half-frames Q15 */ + const Word16 epsP_h[], /* i : msb prediction error energies Q_r-1 */ + const Word16 epsP_l[], /* i : msb prediction error energies Q_r-1 */ + const Word16 Etot, /* i : total channel E (see find_enr_fx.c) Q8 */ + const Word16 relE, /* i : (VA_CHECK addition) relative frame energy Q8? */ + const Word16 corr_shift, /* i : normalized correlation correction Q15 */ + const Word32 enr[], /* i : averaged energy over both subframes Q_new + Q_SCALE */ + Word32 fr_bands[], /* i : spectrum per critical bands of the current frame Q_new + Q_SCALE */ + Word16 *cor_map_sum, /* o : Q8 */ + Word16 *sp_div, /* o : Q_sp_div */ + Word16 *Q_sp_div, /* o : Q factor for sp_div */ + Word16 *non_staX, /* o : non-stationarity for sp/mus classifier */ + Word16 *loc_harm , /* o : multi-harmonicity flag for UV classifier */ + const Word32 *lf_E, /* i : per bin energy for low frequencies Q_new + Q_SCALE -2 */ + Word16 *st_harm_cor_cnt, /* i/o : 1st harm correlation timer Q0 */ + const Word16 Etot_l_lp, /* i : Smoothed low energy Q8 */ + const Word16 Etot_v_h2, /* i : Energy variations Q8 */ + Word16 *bg_cnt, /* i : Background burst length timer Q0 */ + Word16 EspecdB[], /* i/o: log E spectrum (with f=0) of the current frame Q7 */ + Word16 Q_new , /* i : Scaling of current frame */ + + const Word32 Le_min_scaled /*i : Minimum energy value */ + , Word16 *sp_floor /* o : noise floor estimate Q7 */ +); + + +void autocorr_fx( + const Word16 x[], /* i : Input signal */ + const Word16 m, /* i : LPC order Q0 */ + Word16 r_h[], /* o : Autocorrelations (msb) Q15 */ + Word16 r_l[], /* o : Autocorrelations (lsb) */ + Word16 *Q_r, /* o : normailsation shift of r Q0 */ + const Word16 len, /* i : Frame lenght */ + const Word16* wind, /* i : Window used */ + Word16 rev_flag, + const Word16 sym_flag /* i : symmetric window flag */ +); +void freq_dnw_scaling_fx( + const Word16 cor_strong_limit, /* i : HF correlation */ + const Word16 coder_type, /* i : coder type */ + const Word16 noise_lev, /* i : Noise level */ + const Word32 core_brate, /* i : Core bitrate */ + Word16 fy_norm[], /* i/o: Frequency quantized parameter */ + Word16 Qx /* Q format of fy_norm*/ +); +void Comp_and_apply_gain_fx( + Word16 exc_diffQ[], /* i/o: Quantized excitation */ + Word16 Ener_per_bd_iQ[], /* i : Target ener per band Q13 */ + Word16 Ener_per_bd_yQ[], /* i/o : Ener per band for norm vector i->Q13/o->Q13 */ + Word16 Mbands_gn, /* i : number of bands */ + const Word16 ReUseGain , /* i : Reuse the gain in Ener_per_bd_yQ */ + Word16 Qexc_diff, + Word16 Q_exc +); +void dec_pit_exc_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + const Word16 *Aq_fx, /* i : LP filter coefficient */ + const Word16 coder_type_fx, /* i : coding type */ + const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */ + Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe */ + Word16 *code_fx, /* o : innovation */ + Word16 *exc_fx, /* i/o: adapt. excitation exc */ + Word16 *bwe_exc_fx, /* o : excitation for SWB TBE */ + const Word16 nb_subfr_fx /* i : Number of subframe considered */ + , Word16 *gain_buf /*Q14*/ +); +Word16 mean_fx( /* o : mean of vector */ + const Word16 *vec_fx, /* i : input vector */ + const Word16 lvec_fx /* i : length of input vector */ +); +void gsc_dec_fx( + Decoder_State_fx *st_fx, /* i/o: State structure */ + Word16 exc_dct_in[], /* i/o: dct of pitch-only excitation / total excitation */ + const Word16 pit_band_idx, /* i : bin position of the cut-off frequency */ + const Word16 Diff_len, /* i : Lenght of the difference signal (before pure spectral)*/ + const Word16 bits_used, /* i : Number of bit used before frequency Q */ + const Word16 nb_subfr, /* i : Number of subframe considered */ + const Word16 coder_type, /* i : coding type */ + Word16 *last_bin, /* i : last bin of bit allocation */ + Word16 *lsf_new, /* i : ISFs at the end of the frame */ + Word16 *exc_wo_nf, /* o : excitation (in f domain) without noisefill */ + Word16 Q_exc +); +void fft_rel_fx( + Word16 x[], /* i/o: input/output vector */ + const Word16 n, /* i : vector length */ + const Word16 m /* i : log2 of vector length */ +); +void ifft_rel_fx( + Word16 io[], /* i/o: input/output vector */ + const Word16 n, /* i : vector length */ + const Word16 m /* i : log2 of vector length */ +); + +Word16 gsc_gaindec_fx( /* o : average frequency gain */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 y_gainQ_fx[], /* o : quantized gain per band */ + const Word32 core_brate_fx, /* i : core used */ + Word16 old_y_gain_fx[], /* i/o: AR gain quantizer for low rate */ + const Word16 coder_type_fx, /* i : coding type */ + const Word16 bwidth_fx /* i : input signal bandwidth */ +); +void Copy_Scale_sig( + const Word16 x[], /* i : signal to scale input Qx */ + Word16 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +); + +void bands_and_bit_alloc_fx( + const Word16 cor_strong_limit, /* i : HF correlation */ + const Word16 noise_lev, /* i : dwn scaling factor */ + const Word32 core_brate, /* i : core bit rate */ + const Word16 Diff_len, /* i : Lenght of the difference signal (before pure spectral)*/ + const Word16 bits_used, /* i : Number of bit used before frequency Q */ + Word16 *bit, /* i/o: Number of bit allowed for frequency quantization */ + const Word16 *Ener_per_bd_iQ, /* i/o: Quantized energy vector */ + Word16 *max_ener_band, /* o : Sorted order */ + Word16 *bits_per_bands, /* i/o: Number of bit allowed per allowed subband Q3 */ + Word16 *nb_subbands, /* o : Number of subband allowed */ + const Word16 *exc_diff, /* i : Difference signal to quantize (encoder side only) */ + Word16 *concat_in, /* o : Concatened PVQ's input vector (encoder side only) */ + Word16 *pvq_len, /* o : Number of bin covered with the PVQ */ + const Word16 coder_type, /* i : coding type */ + const Word16 bwidth, /* i : input signal bandwidth */ + const Word16 GSC_noisy_speech +); + + +void decod_audio_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + Word16 dct_epit[], /* o : GSC excitation in DCT domain */ + const Word16 *Aq, /* i : LP filter coefficient */ + const Word16 coder_type, /* i : coding type */ + Word16 *pitch_buf, /* o : floating pitch values for each subframe */ + Word16 *voice_factors, /* o : voicing factors */ + Word16 *exc, /* i/o: adapt. excitation exc */ + Word16 *exc2, /* i/o: adapt. excitation/total exc */ + Word16 *bwe_exc, /* o : excitation for SWB TBE */ + Word16 *lsf_new /* i : ISFs at the end of the frame */ + , Word16 *gain_buf /*Q14*/ +); +Word16 Pit_exc_contribution_len_fx( /* o : bin where pitch contribution is significant */ + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 *dct_res, /* i : DCT of residual */ + Word16 *dct_pitex, /* i/o: DCT of pitch contribution */ + Word16 *pitch_buf, /* i/o: Pitch per subframe */ + const Word16 nb_subfr, /* i : Number of subframe considered */ + Word16 *hangover, /* i : hangover for the time contribution switching */ + const Word16 coder_type, /* i : coding type */ + Word16 Qnew +); +void enc_pit_exc_fx( + Encoder_State_fx *st_fx, /* i/o: State structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 *speech, /* i : Input speech */ + const Word16 Aw[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq[], /* i : 12k8 Lp coefficient */ + const Word16 Es_pred, /* i : predicted scaled innov. energy */ + const Word16 *T_op, /* i : open loop pitch */ + const Word16 *voicing, /* i : voicing */ + const Word16 *res, /* i : residual signal */ + Word16 *synth, /* i/o: core synthesis */ + Word16 *exc, /* i/o: current non-enhanced excitation */ + Word16 *T0, /* i/o: close loop integer pitch */ + Word16 *T0_frac, /* i/o: close-loop pitch period - fractional part */ + Word16 *pitch_buf, /* i/o: Fractionnal per subframe pitch */ + const Word16 nb_subfr, /* i : Number of subframe considered */ + Word16 *gpit, /* o : pitch mean gpit */ + Word16 *saved_bit_pos, /* o : saved position in the bitstream before pitch contribution */ + Word16 Q_new, + Word16 shift +); +void encod_amr_wb_fx( + Encoder_State_fx *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 speech[], /* i : input speech */ + const Word16 Aw[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq[], /* i : 12k8 Lp coefficient */ + const Word16 pitch[3], /* i : open-loop pitch values for quantiz. */ + const Word16 voicing[], /* i : voicing */ + const Word16 *res, /* i : residual signal */ + Word16 *syn, /* i/o: core synthesis */ + Word16 *exc, /* i/o: current non-enhanced excitation */ + Word16 *exc2, /* i/o: current enhanced excitation */ + Word16 *pitch_buf, /* i/o: floating pitch values for each subframe */ + Word16 hf_gain_fx[NB_SUBFR], /* o : decoded HF gain */ + const Word16 *speech16k_fx, + Word16 shift, + Word16 Q_new +); +void amr_wb_enc_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 input_sp[], /* i : input signal */ + const Word16 n_samples /* i : number of input samples */ +); +void encod_gen_voic_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 L_frame_fx, /* i : length of the frame */ + const Word16 sharpFlag_fx, /* o : formant sharpening flag */ + const Word16 speech_fx[], /* i : input speech */ + const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */ + const Word16 A_fx[], /* i : unquantized A(z) filter with bandwidth expansion */ + const Word16 coder_type_fx, /* i : coding type */ + const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */ + const Word16 T_op_fx[], /* i : open loop pitch */ + const Word16 voicing_fx[], /* i : voicing */ + const Word16 *res_fx, /* i : residual signal */ + Word16 *syn_fx, /* i/o: core synthesis */ + Word16 *exc_fx, /* i/o: current non-enhanced excitation */ + Word16 *exc2_fx, /* i/o: current enhanced excitation */ + Word16 *pitch_buf_fx, /* i/o: floating pitch values for each subframe */ + Word16 *voice_factors_fx, /* o : voicing factors */ + Word16 *bwe_exc_fx, /* o : excitation for SWB TBE */ + Word16 *unbits_fx, /* i/o: number of unused bits */ + Word16 shift, + Word16 Q_new +); +void bw_detect_fx( + Encoder_State_fx *st, /* i/o: Encoder State */ + const Word16 signal_in[], /* i : input signal */ + const Word16 localVAD, + Word32 *enerBuffer, /* i : CLDFB Energy */ + Word16 *cldfbBuf_Ener_Exp /* i : CLDFB Energy Exponent */ +); +void hf_synth_amr_wb_init_fx( + Word16 *prev_r, /* o : previous sub-frame gain */ + Word16 *fmerit_w_sm, /* o : 1 sample memory fmerit_w param */ + Word16 mem_syn_hf_fx[], /* o : HF LPC synthesis filter initialization */ + Word16 *frame_count, /* o : frame counter initialization */ + Word16 *ne_min, /* o : minimum Noise gate - short-term energy initialization*/ + Word16 *fmerit_m_sm, /* o : 1 sample memory fmerit_m param */ + Word16 *voice_fac, /* o : voice factor initialization */ + Word16 *unvoicing, /* o : unvoiced parameter */ + Word16 *unvoicing_sm, /* o : smoothed unvoiced parameter */ + Word16 *unvoicing_flag, /* o : unvoiced flag */ + Word16 *voicing_flag, /* o : voiced flag */ + Word16 *start_band_old, /* o : previous start point for copying frequency band */ + Word32 *OptCrit_old /* o : previous criterion value for deciding the start point */ +); + +void hf_synth_amr_wb_reset_fx( + Word16 *seed2, /* i/o: random seed for HF noise gen */ + Word16 mem_syn_hf[], /* o : HF synthesis memory */ + Word16 mem_hp_interp[], /* o : interpol. memory */ + Word16 *prev_r, /* o : previous sub-frame gain */ + Word16 *fmerit_w_sm, /* o : 1 sample memory fmerit_w param */ + Word16 delay_syn_hf[], /* o : HF synthesis memory */ + Word16 *frame_count, /* o : frame counter memory */ + Word16 *ne_min, /* o : minimum Noise gate - short-term energy memory */ + Word16 *fmerit_m_sm, /* o : 1 sample memory fmerit_m param */ + Word16 *voice_fac, /* o : voice factor memory */ + Word16 *unvoicing, /* o : unvoiced parameter */ + Word16 *unvoicing_sm, /* o : smoothed unvoiced parameter */ + Word16 *unvoicing_flag, /* o : unvoiced flag */ + Word16 *voicing_flag, /* o : voiced flag */ + Word16 *start_band_old, /* o : previous start point for copying frequency band */ + Word32 *OptCrit_old /* o : previous criterion value for deciding the start point */ +); + +void hf_synth_amr_wb_fx( + const Word32 core_brate, /* i : core bitrate */ + const Word16 output_frame, /* i : output frame length */ + const Word16 *Aq, /* i : quantized Az : Q12 */ + const Word16 *exc, /* i : excitation at 12.8 kHz : Qexc */ + Word16 *synth, /* i/o: synthesis signal at 12.8k : Qsyn */ + Word16 *mem_syn_hf, /* i/o: HF synthesis memory : Qout */ + Word16 *delay_syn_hf, /* i/o: HF synthesis memory : Qout */ + Word16 *prev_r, /* i/o : previous sub-frame gain : Q10 */ + Word16 *fmerit_w_sm, /* i/o: smoothed fmerit_w : Q14 */ + Word16 *amr_io_class, /* i : signal class (determined by FEC algorithm) */ + Word16 *mem_hp_interp, /* i/o: interpol. memory : Qout */ + Word16 *synth_out, /* i/o: output signal at output Fs : Qout */ + Word16 fmerit, /* i : classify parameter from FEC : Q14 */ + const Word16 *hf_gain, /* i : decoded HF gain */ + const Word16 *voice_factors, /* i : voicing factors : Q15 */ + const Word16 pitch_buf[], /* i : pitch buffer : Q5 */ + const Word16 ng_ener_ST, /* i : Noise gate - short-term energy : Q8 */ + const Word16 *lsf_new, /* i : ISF vector : Q2 */ + Word16 *frame_count, /* i/o: frame counter */ + Word16 *ne_min, /* i/o: minimum Noise gate : Q8 */ + Word16 *fmerit_m_sm, /* i/o: smoothed fmerit_m : Q14 */ + Word16 *voice_facor_sm, /* o : voice factor memory : Q15 */ + Word16 *unvoicing, /* o : unvoiced parameter : Q15 */ + Word16 *unvoicing_sm, /* o : smoothed unvoiced parameter : Q15 */ + Word16 *unvoicing_flag, /* o : unvoiced flag */ + Word16 *voicing_flag, /* o : voiced flag */ + Word16 *start_band_old, /* o : previous start point for copying frequency band */ + Word32 *OptCrit_old, /* o : previous criterion value for deciding the start point */ + const Word16 Q_exc, /* i : exc scaling */ + const Word16 Q_out /* i : synth_out scaling */ +); + +void hf_cod_init_fx( + Word16 *mem_hp400_enc, /* o: memory of hp 400 Hz filter */ + Word16 *mem_hf1_enc, /* o: HF band-pass filter memory */ + Word16 *mem_syn_hf_enc, /* o: HF synthesis memory */ + Word16 *mem_hf2_enc, /* o: HF band-pass filter memory */ + Word16 *gain_alpha_fx /* o: smoothing gain for transitions between active and inactive frames */ +); + +void hf_cod_fx( + const Word32 core_brate_fx, /* i : core bitrate */ + const Word16 *speech16k_fx, /* i : original speech at 16 kHz */ + const Word16 Aq_fx[], /* i : quantized Aq */ + const Word16 exc_fx[], /* i : excitation at 12.8 kHz */ + Word16 synth_fx[], /* i : 12.8kHz synthesis signal */ + Word16 *seed2_enc_fx, /* i/o: random seed for HF noise gen */ + Word16 *mem_hp400_enc_fx, /* i/o: memory of hp 400 Hz filter */ + Word16 *mem_syn_hf_enc_fx, /* i/o: HF synthesis memory */ + Word16 *mem_hf1_enc_fx, /* i/o: HF band-pass filter memory */ + Word16 *mem_hf2_enc_fx, /* i/o: HF band-pass filter memory */ + const Word16 dtxHangoverCount_fx, + Word16 *gain_alpha_fx, /* i/o: smoothing gain for transitions between active and inactive frames */ + Word16 *hf_gain_fx, /* o : HF gain to be transmitted to decoder */ + Word16 Q_exc, + Word16 Q_syn +); + +void re8_compute_base_index_fx( + const Word16 *x, /* i : Elemen of Q2, Q3 or Q4 */ + const Word16 ka, /* i : Identifier of the absolute leader related to x */ + UWord16 *I /* o : index */ +); + +void InitSWBencBuffer_fx( + Encoder_State_fx* st_fx /* i/o: SHB encoder structure */ +); + +void ResetSHBbuffer_Enc_fx( + Encoder_State_fx* st_fx /* i/o: SHB encoder structure */ +); +void wb_tbe_extras_reset_synth_fx( Word16 state_lsyn_filt_shb[], Word16 state_lsyn_filt_dwn_shb[], + Word16 state_32and48k_WB_upsample[] + ,Word16 state_resamp_HB[] + ); + +void pz_filter_sp_fx ( + const Word16 b [], + const Word16 a [], + Word16 x [], + Word16 y [], + Word16 buf [], + Word16 PNR, + Word16 PDR, + Word16 N, + Word16 Qa +); + +void Decimate_allpass_steep_fx( + const Word16 *in_fx, + Word16 state_fx[], /* array of size: 2*ALLPASSSECTIONS_STEEP+1 */ + Word16 N, /* number of input samples */ + Word16 out_fx[] /* array of size N/2 */ +); + +Word32 root_a_fx( + Word32 a, + Word16 Q_a, + Word16 *exp_out +); + +Word32 root_a_over_b_fx( + Word32 a, + Word16 Q_a, + Word32 b, + Word16 Q_b, + Word16 *exp_out +); + + +void fir_fx( + const Word16 x[], /* i : input vector */ + const Word16 h[], /* i : impulse response of the FIR filter */ + Word16 y[], /* o : output vector (result of filtering) */ + Word16 mem[], /* i/o: memory of the input signal (M samples) */ + const Word16 L, /* i : input vector size */ + const Word16 K, /* i : order of the FIR filter (M+1 coefs.) */ + const Word16 upd, /* i : 1 = update the memory, 0 = not */ + Word16 shift /* i : difference between Q15 and scaling of h[] */ +); + + +void Interpolate_allpass_steep_fx( + const Word16 *in_fx, /* i : input signal */ + Word16 state_fx[], /* array of size: 2*ALLPASSSECTIONS_STEEP+1 */ + Word16 N, /* number of input samples */ + Word16 out_fx[] /* o : output signal, size 2*N */ +); + +void interpolate_3_over_2_allpass_fx( + const Word16 *input_fx, + const Word16 len, + Word16 *out_fx, + Word16 *mem_fx, + const Word16 *filt_coeff_fx +); +void interpolate_3_over_1_allpass_fx( + const Word16 *input_fx, + const Word16 len, + Word16 *out_fx, + Word16 *mem_fx, + const Word16 *filt_coeff_fx +); +void decimate_2_over_3_allpass_fx( + const Word16 *input_fx, + const Word16 len, + Word16 *out_fx, + Word16 *mem_fx, + const Word16 *filt_coeff_fx, + const Word16 *lp_num_fx, + const Word16 *lp_den_fx, + Word16 *lp_mem_fx +); + +void retro_interp4_5_fx( + const Word16 *syn_fx, + Word16 *pst_old_syn_fx +); +void retro_interp5_4_fx( + Word16 *pst_old_syn_fx +); + +void lsp2lpc_fx( + Word16 *a, + Word16 *freq, + Word16 *prev_a, + Word16 order +); + +void PostShortTerm_fx( + Word16 *sig_in, /* i : input signal (pointer to current subframe */ + Word16 *lpccoeff, /* i : LPC coefficients for current subframe */ + Word16 *sig_out, /* o : postfiltered output */ + Word16 *mem_stp, /* i/o: postfilter memory*/ + Word16 *ptr_mem_stp, /* i/o: pointer to postfilter memory*/ + Word16 *ptr_gain_prec, /* i/o: for gain adjustment*/ + Word16 *mem_zero, /* i/o: null memory to compute h_st*/ + Word16 formant_fac_fx /* i : Strength of post-filter*/ +); + +void GenShapedWBExcitation_fx( + Word16 *excSHB, /* o : synthesized shaped shb exctiation */ + const Word16 *lpc_shb, /* i : lpc coefficients */ + Word16 *exc4kWhtnd, /* o : whitened synthesized shb excitation */ + Word32 *mem_csfilt, /* i/o : memory */ + Word16 *mem_genSHBexc_filt_down1, /* i/o : memory */ + Word16 *mem_genSHBexc_filt_down2, /* i/o : memory */ + Word16 *mem_genSHBexc_filt_down3, /* i/o : memory */ + Word16 *state_lpc_syn, /* i/o : memory */ + const Word16 coder_type, /* i : coding type */ + const Word16 *bwe_exc_extended, /* i : bandwidth extended exciatation */ + const Word16 Q_bwe_exc, + Word16 bwe_seed[], /* i/o : random number generator seed */ + const Word16 voice_factors[], /* i : voicing factor */ + const Word16 signal_type + , const Word16 igf_flag +); + +void GenWBSynth_fx( + const Word16 *input_synspeech, /* i : input synthesized speech */ + Word16 *shb_syn_speech_16k, /* o : output highband compnent */ + Word16 *state_lsyn_filt_shb1, /* i/o: memory */ + Word16 *state_lsyn_filt_shb2 /* i/o: memory */ +); + +void GenSHBSynth_fx( + const Word16 *shb_target_speech, /* i : input synthesized speech */ + Word16 *shb_syn_speech_32k, /* o : output highband component */ + Word32 Hilbert_Mem[], /* i/o: memory */ + Word16 genSHBsynth_allpass_mem[], /* i/o: memory */ + const Word16 L_frame, /* i : ACELP Frame length */ + Word16 *syn_dm_phase +); + +Word16 swb_formant_fac_fx( /* o : Formant filter strength [0,1] */ + const Word16 lpc_shb2, /* Q12 i : 2nd HB LPC coefficient */ + Word16* tilt_mem /* i/o: Tilt smoothing memory */ +); + +void compute_poly_product_fx(Word16 *coef, Word32 *p,Word16 order); + +void ScaleShapedSHB_fx( + const Word16 length, /* i : SHB overlap length */ + Word16 *synSHB, /* i/o: synthesized shb signal */ + Word16 *overlap, /* i/o: buffer for overlap-add */ + const Word16 *subgain, /* i : subframe gain */ + const Word32 frame_gain, /* i : frame gain */ + const Word16 *win, /* i : window */ + const Word16 *subwin, /* i : subframes window */ + Word16 *Q_bwe_exc + ,Word16 *Qx + ,Word16 n_mem3 + ,Word16 prev_Q_bwe_syn2 +); + +void ScaleShapedWB_fx( + const Word16 length, /* i : SHB overlap length */ + Word16* synSHB, /* i/o : synthesized shb signal */ + Word16* overlap, /* i/o : buffer for overlap-add */ + const Word16* subgain, /* i : subframe gain */ + const Word32 frame_gain, /* i : frame gain */ + const Word16* win, /* i : window */ + const Word16* subwin, /* i : subframes window */ + const Word16 Q_bwe_exc + ,Word16 L_frame /* i : Frame length - determines whether 12.8 or 16kHz core in-use */ + ,Word16 dynQ /* i : indicate whether output is dynamic Q, or Q0 */ + ,Word16* Qx /* o : newly computed Q factor for synSHB */ + ,Word16 prev_Qx /* i : prev_Qx for memory scaling */ + ,Word32* Hilbert_Mem /* i : Hilbert memory used for computing Qx */ +); + +void GenShapedSHBExcitation_fx( + Word16 *excSHB, /* o : synthesized shaped shb excitation Q_bwe_exc*/ + const Word16 *lpc_shb, /* i : lpc coefficients Q12*/ + Word16 *White_exc16k_FB, /* o : white excitation for the Fullband extension Q_bwe_exc */ + Word32 *mem_csfilt, /* i/o: memory */ + Word16 *mem_genSHBexc_filt_down_shb, /* i/o: memory */ + Word16 *state_lpc_syn, /* i/o: memory */ + const Word16 coder_type, /* i : coding type */ + const Word16 *bwe_exc_extended, /* i : bandwidth extended excitation */ + Word16 bwe_seed[], /* i/o: random number generator seed */ + Word16 voice_factors[], /* i : voicing factor*/ + const Word16 extl, /* i : extension layer */ + Word16 *tbe_demph, /* i/o: de-emphasis memory */ + Word16 *tbe_premph, /* i/o: pre-emphasis memory */ + Word16 *lpc_shb_sf, /* i: LP coefficients */ + const Word32 shb_ener_sf_32, + Word16 *shb_res_gshape, + Word16 *shb_res, + Word16 *vf_ind, + const Word16 formant_fac, /* i : Formant sharpening factor [0..1] */ + Word16 fb_state_lpc_syn[], /* i/o: memory */ + Word16 *fb_tbe_demph, /* i/o: fb de-emphasis memory */ + Word16 *Q_bwe_exc, + Word16 *Q_bwe_exc_fb, + const Word16 Q_shb, + Word16 n_mem2, /* i : n_mem2 scale factor to adjust 24.4/32kbps memories */ + Word16 prev_Q_bwe_syn, /* i : st_fx->prev_Q_bwe_syn */ + const Word32 bitrate, + const Word16 prev_bfi +); + + +void space_lsfs_fx ( + Word16 *lsfs, /* i/o: Line spectral frequencies */ + const Word16 order /* i : order of LP analysis */ +); + + +void lsp_weights_fx( + Word16 lsp_nq_fx[], + Word16 w[], + Word16 Order, + Word16 *Qout +); + + +void lsp_convolve_fx(Word32 x, Word32 *p1, Word32 *p2, Word16 len); +Word32 poscos_fx(Word16 w); + +void flip_spectrum_and_decimby4_fx( + const Word16 input[], /* i : input spectrum */ + Word16 output[], /* o : output spectrum */ + const Word16 length, /* i : vector length */ + Word16 mem1[], /* i/o : memory */ + Word16 mem2[], /* i/o : memory */ + const Word16 ramp_flag /* i : flag to trigger slow ramp-up of output following change of core */ +); + + +Word16 lpc2lsp_fx( + Word32 *a, + Word16 *freq, + Word16 *old_freq, + Word16 order +); + +Word16 usquant_fx( /* o: index of the winning codeword */ + const Word16 x, /* i: scalar value to quantize Qx*/ + Word16 *xq, /* o: quantized value Qx*/ + const Word16 qlow, /* i: lowest codebook entry (index 0) Qx*/ + const Word16 delta, /* i: quantization step Qx-1*/ + const Word16 cbsize /* i: codebook size */ +); + +void wb_tbe_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 coder_type, /* i : coding type */ + const Word16 *hb_speech, /* i : HB target signal (6-8kHz) at 16kHz */ + const Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation */ + const Word16 Q_new, /* i : input HB speech Q factor */ + const Word16 voice_factors[], /* i : voicing factors */ + const Word16 pitch_buf[], /* i : pitch for each subframe */ + const Word16 voicing[] /* i : OL maximum normalized correlation */ +); + +void wb_pre_proc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *new_inp_resamp16k, /* i : original input signal */ + Word16 *hb_speech /* o : HB target signal (6-8kHz) at 16kHz */ +); + + +void pz_filter_dp_fx ( + const Word16 b [], + const Word16 a [], + Word16 x [], + Word16 y [], + Word32 buf [], + Word16 PNR, + Word16 PDR, + Word16 N, + Word16 Qa +); + +void flip_and_downmix_generic_fx( + Word16 input[], /* i : input spectrum */ + Word16 output[], /* o : output spectrum */ + const Word16 length, /* i : length of spectra */ + Word32 mem1_ext[HILBERT_ORDER1], /* i/o: Hilbert filter memory */ + Word32 mem2_ext[2*HILBERT_ORDER2], /* i/o: memory */ + Word32 mem3_ext[2*HILBERT_ORDER2], /* i/o: memory */ + Word16 *phase_state /* i/o: Phase state in case frequency isn't multiple of 50 Hz */ +); + + +void wb_tbe_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 coder_type, /* i : coding type */ + Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation */ + const Word16 Q_exc, + const Word16 voice_factors[], /* i : voicing factors */ + Word16 *synth, /* i/o: ACELP core synthesis/final synthesis */ + Word16 *Q_synth +); + +void swb_tbe_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 coder_type_fx, /* i : coding type */ + Word16 *new_speech_fx, /* i : original input signal */ + Word32 *bwe_exc_extended_fx, /* i : bandwidth extended excitation */ + const Word16 voice_factors_fx[], /* i : voicing factors */ + Word16 *White_exc16k_fx, /* o : shaped white excitation for the FB TBE */ + Word16 *Q_white_exc, /* o : generated white noise for FB Q factor */ + Word16 Q_bwe_exc, /* i : bandwidth extended excitation Q factor */ + Word16 Q_shb, /* i : SHB target Q factor */ + Word16 *voicing_fx, /* i : OL maximum normalized correlation */ + const Word16 pitch_buf[] /* i : pitch for each subframe */ +); + +void swb_pre_proc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *input_fx, /* i : original input signal */ + Word16 *new_swb_speech_fx, /* o : original input signal at 32kHz */ + Word16 *shb_speech_fx, /* o : SHB target signal (6-14kHz) at 16kHz */ + Word16 *Q_shb_spch /* o : shb target signal Q factor */ + , Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] /* i : real buffer */ + , Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] /* i : imag buffer */ + ,const CLDFB_SCALE_FACTOR *cldfbScale /* i : scale data of real and imag CLDFB buffers */ +); + +void wb_tbe_extras_reset_fx( + Word16 mem_genSHBexc_filt_down_wb2[], + Word16 mem_genSHBexc_filt_down_wb3[] +); + +void swb_tbe_reset_synth_fx( + Word32 genSHBsynth_Hilbert_Mem[], + Word16 genSHBsynth_state_lsyn_filt_shb_local_fx[] +); + +void swb_tbe_reset_fx( + Word32 mem_csfilt[], + Word16 mem_genSHBexc_filt_down_shb[], + Word16 state_lpc_syn[], + Word16 syn_overlap[], + Word16 state_syn_shbexc[], + Word16 *tbe_demph, + Word16 *tbe_premph, + Word16 mem_stp_swb[], + Word16 *gain_prec_swb +); + +void InitSWBdecBuffer_fx( + Decoder_State_fx *swb_dnc_fx /* i/o: SHB decoder structure */ +); + +void ResetSHBbuffer_Dec_fx( + Decoder_State_fx *st_fx /* i/o: decoder state structure */ +); + +Word16 squant_fx( /* o: index of the winning codeword */ + const Word16 x, /* i: scalar value to quantize */ + Word16* xq, /* o: quantized value */ + const Word16 cb[], /* i: codebook */ + const Word16 cbsize /* i: codebook size */ +); + +void swb_tbe_dec_fx( + Decoder_State_fx* st_fx, /* i/o: decoder state structure */ + const Word16 coder_type, /* i : coding type */ + Word32* bwe_exc_extended, /* i : bandwidth extended exciatation 2*Q_exc*/ + Word16 Q_exc, + const Word16 voice_factors[], /* i : voicing factors */ + const Word16 old_syn_12k8_16k[], /* i : low band synthesis*/ + Word16* White_exc16k, /* o : shaped white excitation for the FB TBE */ + Word16* Q_white_exc, + Word16* synth, /* o : SHB synthesis/final synthesis */ + Word16* Q_synth, + Word16* pitch_buf +); + + +void tbe_write_bitstream_fx( + Encoder_State_fx *st_fx /* i/o: encoder state structure */ +); + +void tbe_read_bitstream_fx( + Decoder_State_fx *st_fx /* i/o: encoder state structure */ +); + +Word16 get_tbe_bits_fx( /* o : TBE bit consumption per frame */ + Word32 bitrate, /* i : overall bitrate */ + Word16 bandwidth /* i : bandwidht mode */ + ,Word16 rf_mode +); + +void GenTransition_fx( + const Word16 *input, /* i : gain shape overlap buffer */ + const Word16 *old_hb_synth, /* i : synthesized HB from previous frame */ + Word16 length, /* i : targeted length of transition signal */ + Word16 *output, /* o : synthesized transitions signal */ + Word32 Hilbert_Mem[], /* i/o: memory */ + Word16 state_lsyn_filt_shb_local[],/* i/o: memory */ + Word16 mem_resamp_HB_32k[], /* i/o: memory */ + Word16 *syn_dm_phase, + Word32 output_Fs, + Word16 *up_mem, + Word16 rf_flag + , Word32 bitrate +); + +void GenTransition_WB_fx( + const Word16 *input, /* i : gain shape overlap buffer */ + const Word16 *old_hb_synth, /* i : synthesized HB from previous frame */ + const Word16 prev_Qx, /* i : scaling of old_hb_synth */ + Word16 length, /* i : targeted length of transition signal */ + Word16 *output, /* o : synthesized transitions signal */ + Word16 state_lsyn_filt_shb1[], + Word16 state_lsyn_filt_shb2[], + Word32 output_Fs, + Word16 *up_mem +); + +void TBEreset_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 bandwidth /* i : bandwidth mode */ +); + +void TBEreset_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 bandwidth /* i : bandwidth mode */ +); + +void fb_tbe_enc_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 new_input[], /* i : input speech at 48 kHz sample rate */ + const Word16 fb_exc[], /* i : FB excitation from the SWB part */ + Word16 Q_fb_exc +); + +void fb_tbe_dec_fx( + Decoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 fb_exc[], /* i : FB excitation from the SWB part */ + Word16 Q_fb_exc, + Word16 *hb_synth, /* o : high-band synthesis */ + Word16 hb_synth_exp +); + +void elliptic_bpf_48k_generic_fx( + const Word16 input_fx[], /* i : input signal */ + Word16 *Q_input_fx, + Word16 output_fx[], /* o : output signal */ + Word32 memory_fx[][4], /* i/o: 4 arrays of 4 for memory */ + Word16 memory_fx_Q[], + const Word16 full_band_bpf[][5] /* i : filter coefficients b0,b1,b2,a0,a1,a2 Q13 */ +); +void synthesise_fb_high_band_fx( + const Word16 excitation_in[], /* i : full band excitation */ + Word16 Q_fb_exc, + Word16 output[], /* o : high band speech - 14.0 to 20 kHz */ + const Word32 fb_exc_energy, /* i : full band excitation energy */ + const Word16 ratio, /* i : energy ratio */ + const Word16 L_frame, /* i : ACELP frame length */ + const Word16 bfi, /* i : fec flag */ + Word16 *prev_fbbwe_ratio, /* o : previous frame energy for FEC */ + Word32 bpf_memory[][4], /* i/o: memory for elliptic bpf 48k */ + Word16 bpf_memory_Q[], + Word16 Qout +); + +void lsf_syn_mem_restore_fx( + Encoder_State_fx *st_fx, /* o: state structure */ + LPD_state* LPDmem, /* o: LPD_state vewctor */ + Word16 btilt_code_fx, /* i: */ + Word32 gc_threshold_fx, /* i: */ + Word16 *clip_var_bck_fx, /* i: */ + Word16 next_force_sf_bck_fx, /* i: */ + Word16 *lsp_new, /* o: LSP vector to quantize */ + Word16 *lsf_new, /* o: quantized LSF vector */ + Word16 *lsp_mid, /* o: mid-frame LSP vector */ + Word16 clip_var, /* i: pitch clipping state var */ + Word16 *mem_AR, /* i: quantizer memory for AR model */ + Word16 *mem_MA, /* i: quantizer memory for MA model */ + Word16 *lsp_new_bck, /* i: LSP vector to quantize- backup */ + Word16 *lsf_new_bck, /* i: quantized LSF vector - backup */ + Word16 *lsp_mid_bck, /* i: mid-frame LSP vector - backup */ + Word16 mCb1, /* i: counter for stationary frame after a transition frame */ + Word32 *Bin_E, /* i: FFT Bin energy 128 *2 sets */ + Word32 *Bin_E_old, /* i: FFT Bin energy 128 sets */ + Word16 *mem_syn_bck, /* i: synthesis filter memory */ + Word16 mem_w0_bck, /* i: memory of the weighting filter */ + Word16 streaklimit, /* i:LSF quantizer */ + Word16 pstreaklen /* i:LSF quantizer */ +); + +void encod_nelp_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 *speech_fx, /* i : input speech */ + const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */ + Word16 *res_fx, /* o : residual signal */ + Word16 *synth_fx, /* o : core synthesis */ + Word16 *tmp_noise_fx, /* o : long-term noise energy */ + Word16 *exc_fx, /* i/o: current non-enhanced excitation */ + Word16 *exc2_fx, /* i/o: current enhanced excitation */ + Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe */ + Word16* voice_factors_fx, /* o : voicing factors */ + Word16* bwe_exc_fx, /* o : excitation for SWB TBE */ + Word16 Q_new, + Word16 shift +); + +void nelp_encoder_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state */ + Word16 *in_fx, /* i : residual signal */ + Word16 *exc_fx, /* o : NELP quantized excitation signal */ + Word16 *qIn1 + ,Word16 reduce_gains +); + +Word16 dequantize_uvg_fx( + Word16 iG1, /* i: gain 1 index */ + Word16 *iG2, /* i: gain 2 index */ + Word16 *G, /* o: quantized gain */ + Word16 bandwidth /* i: bandwidth */ + ,Word16 do_scale +); + +void quantize_uvg_fx( + Word16 *G, + Word16 *iG1, + Word16 *iG2, + Word16 *quantG, + Word16 bandwidth +); + + +void generate_nelp_excitation_fx( + Word16 *seed, + Word16 *Gains, + Word16 *output, + Word16 gain_fac +); + + +Word16 find_rem( + Word16 n, + Word16 m, + Word16 *r +); + +Word32 find_remd( + Word32 n, + Word32 m, + Word32 *r +); + +void set_ppp_mode_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + Word16 *coder_type /* i : coding type */ + ,const Word16 noisy_speech_HO, /* i : SC-VBR noisy speech HO flag */ + const Word16 clean_speech_HO, /* i : SC-VBR clean speech HO flag */ + const Word16 NB_speech_HO, /* i : SC-VBR NB speech HO flag */ + const Word16 localVAD, + const Word16 localVAD_he, /* i : HE-SAD flag without hangover */ + Word16 *vad_flag + ,Word16 T_op_fx[] /* i : open loop pitch lag */ + ,Word16 sp_aud_decision1 /* i : Speech Audio Decision */ +); + +void update_average_rate_fx( + Encoder_State_fx *st_fx /* i/o: encoder state structure */ +); + + +void encod_ppp_fx( + Encoder_State_fx * st_fx, /* i/o: state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 speech_fx[], /* i : input speech Q_new*/ + const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */ + Word16 *coder_type, /* i/o : coding type */ + Word16 sharpFlag_fx, /* i : formant sharpening flag */ + const Word16 T_op_fx[], /* i : open loop pitch */ + const Word16 voicing_fx[], /* i : voicing Q14*/ + Word16 *res_fx, /* i/o: residual signal Q_new*/ + Word16 *synth_fx, /* i/o: core synthesis Q-1*/ + Word16 *exc_fx, /* i/o: current non-enhanced excitation Q_new*/ + Word16 *exc2_fx, /* o: current enhanced excitation Q0*/ + Word16 *pitch_buf_fx, /* o: floating pitch values for each subframe Q6*/ + Word16 *voice_factors, /* o : voicing factors */ + Word16 *bwe_exc, /* o : excitation for SWB TBE */ + Word16 Q_new, + Word16 shift +); + +void ppp_voiced_encoder_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + Word16 *in_fx, /* i : residual signal */ + Word16 *out_fx, /* o : Quantized residual signal */ + Word16 delay_fx, /* i : open loop pitch */ + Word16 *lpc1_fx, /* i : prev frame de-emphasized LPC */ + Word16* lpc2_fx, /* i : current frame de-emphasized LPC */ + Word16 *exc_fx, /* i: previous frame quantized excitation */ + Word16 *pitch_fx, /* o: floating pitch values for each subframe */ + Word16 vadsnr_fx, /* i: current frame SNR Q7*/ + Word16 Qres +); + +Word16 rint_new_fx( + Word32 x /* i/o: Round to the nearest integer with mid point exception */ +); + +void decod_nelp_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + const Word16 coder_type, /* i : coding type */ + Word16 *tmp_noise_fx, /* o : long term temporary noise energy */ + Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe*/ + Word16 *exc_fx, /* o : adapt. excitation exc */ + Word16 *exc2_fx, /* o : adapt. excitation/total exc */ + Word16 *voice_factors, /* o : Voice factor */ + Word16 *bwe_exc, + Word16 *Q_exc, + Word16 bfi /* i : frame error rate */ + , Word16 *gain_buf /*Q14*/ +); + +void nelp_decoder_fx( + Decoder_State_fx *st, /* i/o: decoder static memory */ + Word16 *exc_nelp, /* o : adapt. excitation/total exc */ + Word16 *exc, /* o : adapt. excitation exc */ + Word16 *Q_exc, + Word16 bfi, /* i : frame error rate */ + const Word16 coder_type /* i : coding type */ + , Word16 *gain_buf /*Q14*/ +); + +void core_switching_pre_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 output_frame /* i : frame length */ +); + +void fb_tbe_reset_synth_fx( + Word32 fbbwe_hpf_mem_fx[][4], + Word16 fbbwe_hpf_mem_fx_Q[], + Word16 *prev_fbbwe_ratio_fx +); + +void core_switching_post_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *synth, /* i/o: output synthesis Qsynth */ + const Word16 output_frame, /* i : frame length */ + const Word16 core_switching_flag, /* i : ACELP->HQ switching flag */ + const Word16 coder_type, /* i : ACELP coder type */ + Word16 *Qsynth +); +void acelp_core_switch_dec_bfi_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 synth_out[], /* o : synthesis Q_syn */ + const Word16 coder_type /* i : coder type */ +); +void acelp_core_switch_dec_fx( + Decoder_State_fx *st_fx, /* decoder state structure */ + Word16 *synth_subfr_out, /* o synthesized ACELP subframe Q_syn*/ + Word16 *tmp_synth_bwe, /* o synthesized ACELP subframe BWE Q_syn*/ + const Word16 output_frame, /* i : input frame legth */ + const Word16 core_switching_flag, /* i : core switching flag */ + Word16 *mem_synth, /* o : synthesis to overlap */ + Word16 *Q_syn +); + +void core_switching_hq_prepare_dec_fx( + Decoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *num_bits, /* i/o: bit budget update */ + const Word16 output_frame /* i : output frame length */ +); +void fb_tbe_reset_enc_fx( + Word32 elliptic_bpf_2_48k_mem_fx[][4], + Word32 *prev_fb_energy_fx, + Word16 elliptic_bpf_2_48k_mem_fx_Q[], + Word16 *prev_fb_energy_fx_Q +); + +void core_switching_OLA_fx( + Word16 *mem_over_hp, /* i : upsampling filter memory Q0 */ + const Word16 last_L_frame, /* i : last L_frame lengthture */ + const Word32 output_Fs, /* i : output sampling rate */ + Word16 *synth, /* i/o: synthesized signal from HQ core Q0 */ + Word16 *synth_subfr_out, /* i : synthesized signal from ACELP core Q0 */ + Word16 *synth_subfr_bwe, /* i : synthesized BWE from ACELP core Q0 */ + const Word16 output_frame, /* i : output frame length */ + const Word16 bwidth, /* i : output bandwidth */ + Word16* Qsynth, + Word16* Qsubfr +); + +void acelp_core_switch_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + LPD_state *mem, + const Word16 inp12k8[], /* i : input signal @12.8 kHz Q0 */ + const Word16 inp16k[], /* i : input signal @16 kHz Q0 */ + const Word16 T_op_orig[2], /* i : open-loop pitch values for quantiz. Q0*/ + const Word16 voicing[3], /* i : Open-loop pitch gains Q15 */ + const Word16 A[NB_SUBFR16k*(M+1)], /* i : A(z) unquantized for the 4 subframes Q12*/ + Word16 shift, + Word16 Q_new +); + +void core_switching_hq_prepare_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *num_bits, /* i/o: bit budget update */ + const Word16 input_frame, /* i : frame length */ + Word32 *wtda_audio, /* shall be q_audio + 15, audio allready scalled in wtda function */ + const Word16 *audio +); + +void core_switching_pre_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + LPD_state *mem, /* i/o: encoder state structure */ + const Word16 *old_inp_12k8, /* i : old input signal @12.8kHz */ + const Word16 *old_inp_16k /* i : old input signal @16kHz */ +); + +void core_switching_post_enc_fx( /*done */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 inp12k8[], /* i : input signal @12.8 kHz */ + const Word16 inp16k[], /* i : input signal @16 kHz */ + const Word16 T_op[2], /* i : open-loop pitch values for quantiz. */ + const Word16 voicing[3], /* i : Open-loop pitch gains */ + const Word16 A[], /* i : unquant. LP filter coefs. (Q12) */ + Word16 Qshift, + Word16 Q_new, + const Word16 Qsp, /* i/o : Q from acelp synthsis */ + Word16 *Qmus /* i/o : Q from mdct synthsis / Q of output synthesis */ +); + +Word16 modify_Fs_intcub3m_sup_fx( /* o : length of output */ + const Word16 sigIn[], /* i : signal to decimate with memory of 2 samples (indexes -2 & -1) */ + const Word16 lg, /* i : length of input (suppose that lg is such that lg_out is integer, ex multiple of 5 in case of 16kHz to 12.8 kHz) */ + const Word32 fin, /* i : frequency of input */ + Word16 sigOut[], /* o : decimated signal */ + const Word32 fout, /* i : frequency of output */ + Word16 *delayout /* o : delay of output */ +); +void add_vec_fx( + const Word16 x1[], /* i : Input vector 1 */ + const Word16 Qx1, /* i : SCaling of iput 1 */ + const Word16 x2[], /* i : Input vector 2 */ + const Word16 Qx2, /* i : SCaling of iput 1 */ + Word16 y[], /* o : Output vector that contains vector 1 + vector 2 */ + const Word16 Qy, /* i : SCaling of output 1 */ + const Word16 N /* i : Vector lenght */ +); + +/******************************* wrappers related functions **************/ +void convert_fl_2_fx(const float *var_fl, Word16 *var_fx, Word16 count, Word16 Q_format); +void convert_fl_2_fx_32(const float *var_fl, Word32 *var_fx, Word16 count, Word16 Q_format); +void convert_fl_2_fx_32_MIN(const float *var_fl, Word32 *var_fx, Word16 count, Word16 Q_format, Word32 MIN_VAL); +void convert_sh_2_fx(const short *var_fl, Word16 *var_fx, Word16 count, Word16 Q_format); +void convert_dl_2_fx_32(double *var_fl, Word32 *var_fx, Word16 count, Word16 Q_format); +void convert_fx_2_fl(float *var_fl, const Word16 *var_fx, Word16 count, Word16 Q_format); +void convert_fx_2_sh(short *var_fl, const Word16 *var_fx, Word16 count, Word16 Q_format); +void convert_fx_2_dl_32(double *var_fl, const Word32 *var_fx, Word16 count, Word16 Q_format); +void convert_fx_2_fl_32(float *var_fl, const Word32 *var_fx, Word16 count, Word16 Q_format); +void convert_fx_2_fl_32_floor(float *var_fl, const Word32 *var_fx, Word16 count, Word16 Q_format); +/* void pre_proc_acelp_core_dec(Decoder_State *st,Decoder_State_fx *st_fx); */ +/* void post_proc_acelp_core_dec(Decoder_State *st,Decoder_State_fx *st_fx); */ + +void convert_fl_2_fx_q(const float *x, Word16 *x_fx, Word16 len, Word16 *q); +/******************************* END OF wrappers related functions **************/ + +/******************************* END of temporary Hybride function related functions **************/ + +void Copy_Scale_sig32_16( + const Word32 *src, /* i : signal to scale Qx */ + Word16 *dst, /* o : scaled signal Qx */ + Word16 len, /* i : size of x[] Q0 */ + Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +); +Word32 Add_flt32_flt32(/* o: Result */ + Word32 a, /* i: 1st Value */ + Word16 exp_a, /* i: Exponent of 1st Value (Q of Value) */ + Word32 b, /* i: 2nd Value */ + Word16 exp_b, /* i: Exponent of 2nd Value (Q of Value) */ + Word16 *exp_out /* o: Exponent of Result */ +); +Word32 Mul_flt32_Q15( /* o: Result (Normalized) */ + Word32 value, /* i: Pseudo_float Value */ + Word16 *exp_v, /*i/o: Exponent of Value (Q of Value) */ + Word16 frac /* i: Q15 value */ +); +Word32 Div_flt32_flt32(/* o: Result (Normalized) */ + Word32 a, /* i: 1st Value */ + Word16 exp_a, /* i: Exponent of 1st Value (Q of Value) */ + Word32 b, /* i: 2nd Value */ + Word16 exp_b, /* i: Exponent of 2nd Value (Q of Value) */ + Word16 *exp_out /* o: Exponent of Result */ +); +Word32 Calc_Energy_Autoscaled(/* o: Result (Energy) */ + const Word16 *signal, /* i: Signal */ + Word16 signal_exp, /* i: Exponent of Signal (Q of Signal) */ + Word16 len, /* i: Frame Length */ + Word16 *energy_exp /* o: Exponent of Energy (Q of Energy) */ +); +Word16 Find_Max_Norm16(const Word16 *src, Word16 len); +Word16 Find_Max_Norm32(const Word32 *src, Word16 len); +Word32 Sqrt_Ratio32(Word32 L_val1, Word16 exp1, Word32 L_val2, Word16 exp2, Word16 *exp); +Word16 Invert16( /* result in Q'15 + 'exp' */ + Word16 val, + Word16 *exp); + +void swb_bwe_enc_hr_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *new_input_fx, /* i : input signal */ + Word16 new_input_fx_exp, /* i : Exponent of input signal */ + const Word16 input_frame, /* i : frame length */ + const Word16 coder_type, /* i : coding type */ + const Word16 unbits /* i : number of core unused bits */ +); + +void wtda_fx( + Word16 *new_audio, /* i : input audio Q0 */ + Word16 *Q, /* i/o : Q of Output Audio (use 15 for 'qout' for backward compatibility - NON SWB ENC HR FX MODULES) */ + Word32 *wtda_audio, /* o : windowed audio Qout */ + Word16 *old_wtda, /* i/o: windowed audio from previous frame Qout */ + Word16 *Qold_wtda, + Word16 left_mode, + Word16 right_mode, /* window overlap of current frame (0: full, 2: none, or 3: half) */ + const Word16 L +); + +void direct_transform_fx( + const Word32 in32_fx[], + Word32 out32_fx[], + const Word16 is_transient, + const Word16 L, + Word16 *Q +); + + +void r_fft_4_fx(Word16 * farray_ptr_fx, Word16 size, Word16 stage, Word16 isign); + +DTFS_STRUCTURE_FX* DTFS_new_fx( + void +); + +void DTFS_copy_fx( + DTFS_STRUCTURE_FX *Xout_fx, /* o: DTFS structure */ + DTFS_STRUCTURE_FX Xinp_fx /* i: DTFS structure */ +); + +DTFS_STRUCTURE_FX DTFS_sub_fx( + DTFS_STRUCTURE_FX X1, /* i: DTFS input 1 */ + DTFS_STRUCTURE_FX X2 /* i: DTFS input 2 */ +); /* o: X1 - X2 */ + + +void DTFS_to_fs_fx( + const Word16 *x, /* i : time domain signal */ + Word16 N, /* i : Length of input vector */ + DTFS_STRUCTURE_FX *X_fx, /* o : DTFS structure with a, b, lag */ + Word16 Fs, /* i : sampling rate */ + Word16 FR_flag, /* i: FR flag */ + Word16 *S_fx, + Word16 *C_fx +); + +void DTFS_fast_fs_inv_fx( DTFS_STRUCTURE_FX *This,Word16 *out_fx, Word16 N_fx, Word16 LOG2N); + +void DTFS_car2pol_fx( + DTFS_STRUCTURE_FX *X_fx /* i/o : DTFS structure a, b, lag */ +); +void copy_phase_fx( DTFS_STRUCTURE_FX *X1_fx, DTFS_STRUCTURE_FX X2_fx, DTFS_STRUCTURE_FX *retX_fx); +Word32 getSpEngyFromResAmp_fx( DTFS_STRUCTURE_FX *X_fx,Word16 lband, Word16 hband, + const Word16 *curr_lpc, Word16 *sin_tab, + Word16 *cos_tab); + +Word32 DTFS_setEngyHarm_fx( + Word16 f1_fx, /* i : lower band freq of input to control energy */ + Word16 f2_fx, /* i : upper band freq of input to control energy */ + Word16 g1_fx, /* i : lower band freq of output to control energy */ + Word16 g2_fx, /* i : upper band freq of output to control energy */ + Word32 en2_fx, /* i : Target Energy to set the DTFS to */ + Word16 Qen2_fx, /* i : Input Q format for en2 */ + Word16 *Qa_fx, /* i : Output Q format for x->a */ + DTFS_STRUCTURE_FX *X_fx /* i/o: DTFS to adjust the energy of */ +); + +void rshiftHarmBand_fx( DTFS_STRUCTURE_FX *X_fx,Word16 lband_fx, Word16 hband_fx, Word16 shift_fx); +void quant_target_fx( DTFS_STRUCTURE_FX *X_fx,const Word16 *curr_lpc, Word16 *w, Word16 *target, + Word16 *sin_tab, Word16 *cos_tab); + +void GetSinCosTab_fx(Word16 L, Word16 *sinTab, Word16 *cosTab); + +void DTFS_to_erb_fx( + const DTFS_STRUCTURE_FX X_fx, /* i : DTFS input */ + Word16 *out_fx /* o : ERB output */ +); + +void DTFS_zeroPadd_fx(Word16 N_fx,DTFS_STRUCTURE_FX *X_fx); + +Word32 DTFS_getEngy_fx( DTFS_STRUCTURE_FX *X_fx); + +Word32 DTFS_getEngy_P2A_fx( DTFS_STRUCTURE_FX *X_fx); + + +Word32 DTFS_getEngy_band_fx( + DTFS_STRUCTURE_FX X_fx, + Word16 lband, + Word16 hband +); + +Word32 DTFS_getEngy_band_wb_fx( + DTFS_STRUCTURE_FX X_fx, + Word16 lband, + Word16 hband +); + +Word32 DTFS_freq_corr_fx( + DTFS_STRUCTURE_FX X1_DTFS_fx, /* i : X1 DTFS */ + DTFS_STRUCTURE_FX X2_DTFS_fx, /* i : X2 DTFS */ + Word16 lband, /* i : low cutoff */ + Word16 hband, /* i : high cutoff */ + Word16 *Qout /* o : Correlation Q format */ +); /* o : Correlation */ + +Word32 DTFS_setEngy_fx( DTFS_STRUCTURE_FX *X_DTFS_FX,Word32 en2_fx); + +void DTFS_adjustLag_fx( + DTFS_STRUCTURE_FX *X_DTFS_FX, /* i/o : DTFS to adjust lag for */ + Word16 N_fx /* i : Target lag */ +); + +void DTFS_poleFilter_fx( DTFS_STRUCTURE_FX *X_fx,Word16 *LPC, Word16 N, Word16 *S_fx, Word16 *C_fx); +void DTFS_poleFilter_fx_9( DTFS_STRUCTURE_FX *X_fx, Word16 *pf_temp1, Word16 *pf_temp2, Word16 *pf_temp, Word16 *pf_n2_temp1); +void poleFilter_setup_fx(const Word16 *LPC, Word16 N, DTFS_STRUCTURE_FX X_fx, Word16 *S_fx, Word16 *C_fx, Word16 *pf_temp1, Word16 *pf_temp2, Word16 *pf_temp, Word16 *pf_n2_temp1); + +void DTFS_zeroFilter_fx( + DTFS_STRUCTURE_FX *X_fx, + Word16 *LPC, + Word16 N, + Word16 *S_fx, + Word16 *C_fx +); + +Word16 DTFS_alignment_full_fx( + DTFS_STRUCTURE_FX X1_DTFS_fx, /* i : reference DTFS */ + DTFS_STRUCTURE_FX X2_DTFS_fx, /* i : DTFS to shift */ + Word16 ph_offset_fx, /* i : resolution */ + Word16 *S_fx, + Word16 *C_fx + , Word16 FR_flag +); + +Word16 DTFS_alignment_extract_td_fx(Word16 *x1, Word16 *x2, Word16 lag); + +Word16 DTFS_alignment_weight_fx( + DTFS_STRUCTURE_FX *X_fx, + DTFS_STRUCTURE_FX X2, + Word16 Eshift, + const Word16 *LPC1, + const Word16 *LPC2, + Word16 *S_fx, + Word16 *C_fx, + Word16 *pf_temp1, + Word16 *pf_temp2, + Word16 *pf_temp, + Word16 *pf_n2 +); + + +Word16 DTFS_alignment_fine_new_fx( DTFS_STRUCTURE_FX X1_fx, DTFS_STRUCTURE_FX X2_fx, Word16 *S_fx, Word16 *C_fx); + + +void DTFS_phaseShift_fx( DTFS_STRUCTURE_FX *X_fx,Word16 ph, Word16 Lag, Word16 *S_fx, Word16 *C_fx); +void Q2phaseShift_fx( DTFS_STRUCTURE_FX *X_fx,Word16 ph, Word16 Lag, Word16 *S_fx, Word16 *C_fx); + + +void DTFS_erb_inv_fx( + Word16 *in_fx, /* i : ERB inpt */ + Word16 *slot_fx, /* i : ERB slots filled based on lag */ + Word16 *mfreq_fx, /* i : erb frequence edges */ + DTFS_STRUCTURE_FX *X_fx, /* o : DTFS after erb-inv */ + Word16 num_erb_fx /* i : Number of ERB bands */ +); + +void erb_add_fx( + Word16 *curr_erb_fx, /* i/o: current ERB */ + Word16 l_fx, /* i : current lag */ + const Word16 *prev_erb_fx, /* i : previous ERB */ + Word16 pl_fx, /* i : previous lag */ + const Word16 *index_fx, /* i : ERB index */ + Word16 num_erb_fx /* i : number of ERBs */ +); + +void LPCPowSpect_fx(Word16 *freq, Word16 Nf, Word16 *LPC, Word16 Np, + Word16 *out); + +void erb_slot_fx( + Word16 lag_fx, /* i : input lag */ + Word16 *out_fx, /* o : ERB slots */ + Word16 *mfreq_fx, /* i : ERB frequencies */ + Word16 num_erb_fx /* i : number of ERBs */ +); + +Word16 DTFS_quant_cw_fx( + DTFS_STRUCTURE_FX *X_fx, /* i/o: DTFS unquant inp, quant out */ + Word16 pl, /* i : Previous lag */ + const Word16 *curr_lpc_fx, /* i : LPC */ + Word16 *POWER_IDX, /* o : Power index */ + Word16 *AMP_IDX, /* o : Amplitude index */ + Word16 *lastLgainE_fx, /* i/o: last frame lowband gain */ + Word16 *lastHgainE_fx, /* i/o: last frame highband gain */ + Word16 *lasterbE_fx, /* i/o: last frame ERB vector */ + Word16 *sin_tab, + Word16 *cos_tab +); + + +void DTFS_dequant_cw_fx( + Word16 pl_fx, /* i : Previous lag */ + Word16 POWER_IDX_fx, /* i : POWER index */ + const Word16 *AMP_IDX_fx, /* i : Amp Shape index */ + Word16 *lastLgainD_fx, /* i/o: low band last gain */ + Word16 *lastHgainD_fx, /* i/o: high band last gain */ + Word16 *lasterbD_fx, /* i/o: last frame ERB vector */ + DTFS_STRUCTURE_FX *X_fx, /* o : DTFS structure dequantized */ + Word16 num_erb_fx +); + +void DTFS_transform_fx( + DTFS_STRUCTURE_FX X_fx, /* i : Starting DTFS to use in WI */ + DTFS_STRUCTURE_FX X2_fx, /* i : Ending DTFS to use in WI */ + const Word32 *phase_fx, /* i : Phase contour */ + Word16 *out_fx, /* o : Output time domain waveform */ + Word16 N, /* i : Number of samples to generate */ + Word16 FR_flag /* i : Flag to indicate called in FR context */ +); + +void DTFS_peaktoaverage_fx( + DTFS_STRUCTURE_FX X_fx, /* i : DTFS */ + Word32 *pos_fx, /* o : positive peak to ave */ + Word16 *Qpos, /* o : positive peak to ave Q format */ + Word32 *neg_fx, /* o : negative peak to ave */ + Word16 *Qneg /* o : negative peak to ave Q format */ +); + + + +Word16 ppp_extract_pitch_period_fx( + const Word16 *in, /* i : input residual */ + Word16 *out, /* o : output residual */ + Word16 l, /* i : lag */ + Word16 *out_of_bound, /* o : out of bound flag */ + Word16 Qres + +); + +void Interpol_delay_fx( + Word16 *out_fx, + Word16 last_fx, + Word16 current_fx, + Word16 SubNum, + const Word16* frac_fx +); + + +Word16 ppp_quarter_encoder_fx( + DTFS_STRUCTURE_FX *CURRCW_Q_FX, /* o : Quantized (amp/phase) DTFS */ + DTFS_STRUCTURE_FX *TARGETCW_FX, /* o : DTFS with quant phase but unquant Amp */ + Word16 prevCW_lag, /* i : previous lag */ + DTFS_STRUCTURE_FX CURRCW_NQ_FX, /* i : Unquantized DTFS */ + const Word16 *curr_lpc_fx, /* i : LPCS */ + Word16 *lastLgainE_fx, /* i/o: last low band gain */ + Word16 *lastHgainE_fx, /* i/o: last high band gain */ + Word16 *lasterbE_fx, /* i/o: last ERB vector */ + DTFS_STRUCTURE_FX PREV_CW_E_FX, /* i : past DTFS */ + Word16 *S_fx, /* i : sin table, Q15 */ + Word16 *C_fx, /* i : cos table, Q15 */ + Encoder_State_fx *st_fx +); + + +void WIsyn_fx( + DTFS_STRUCTURE_FX PREVCW_FX, + DTFS_STRUCTURE_FX *CURR_CW_DTFS_FX, + const Word16 *curr_lpc_fx, + Word16 *ph_offset_fx, + Word16 *out_fx, + Word16 N, + Word16 FR_flag, /* i : called for post-smoothing in FR */ + Word16 *S_fx, + Word16* C_fx, + Word16 *pf_temp1, + Word16 *pf_temp2, + Word16 *pf_temp, + Word16 *pf_n2 +); + +void deemph_lpc_fx( + Word16 *p_Aq_curr_fx, /* i : LP coefficients current frame */ + Word16 *p_Aq_old_fx, /* i : LP coefficients previous frame */ + Word16 *LPC_de_curr_fx, /* o : De-emphasized LP coefficients current frame */ + Word16 *LPC_de_old_fx, /* o : De-emphasized LP coefficients previous frame */ + Word16 deemph_old + +); + +Word16 erb_diff_search_fx(Word16 *prev_erb, const Word16 *curr_erb, Word16 *dif_erb, + Word16 *pow_spec, const Word16 *cb_fx, + Word16 cb_size, Word16 cb_dim, Word16 offset + ); + + +void Acelp_dec_total_exc( + Word16 *exc_fx, /* i/o: adapt. excitation exc */ + Word16 *exc2_fx, /* i/o: adapt. excitation/total exc */ + const Word16 gain_code16, /* i : Gain code Q0 */ + const Word16 gain_pit_fx, /* i ; Pitch gain in Q14 */ + const Word16 i_subfr, /* i ; subfr */ + const Word16 *code_fx /* i : code in Q12 */ +); +void tbe_celp_exc( + const Word16 L_frame_fx, /* i : Frame lenght */ + const Word16 i_subfr_fx, /* i : sub frame */ + const Word16 T0_fx, /* i : Integer pitch */ + const Word16 T0_frac_fx, /* i : Fractional part of the pitch */ + Word16 *error_fx, /* i/o: Error */ + Word16 *bwe_exc_fx /* i/o: bandwitdh extension signal */ +); +Word16 tbe_celp_exc_offset( + const Word16 T0_fx, /* i : Integer pitch */ + const Word16 T0_frac_fx, /* i : Fractional part of the pitch */ + const Word16 L_frame /* i : frame lenght */ +); +void lsf_syn_mem_backup_fx( + Encoder_State_fx *st_fx, /* i: state structure */ + LPD_state* LPDmem, /* i: LPD state memory structure */ + Word16 *btilt_code, /* i: tilt code */ + Word32 *bgc_threshold, /* i: */ + Word16 *clip_var_bck, /* o: */ + Word16 *next_force_sf_bck, /* o: */ + Word16 *lsp_new, /* i: LSP vector to quantize */ + Word16 *lsf_new, /* i: quantized LSF vector */ + Word16 *lsp_mid, /* i: mid-frame LSP vector */ + Word16 *clip_var, /* o: pitch clipping state var */ + Word16 *mem_AR, /* o: quantizer memory for AR model */ + Word16 *mem_MA, /* o: quantizer memory for AR model */ + Word16 *lsp_new_bck, /* o: LSP vector to quantize- backup */ + Word16 *lsf_new_bck, /* o: quantized LSF vector - backup */ + Word16 *lsp_mid_bck, /* o: mid-frame LSP vector - backup */ + Word16 *mCb1, /* o: counter for stationary frame after a transition frame */ + Word32 *Bin_E, /* o: FFT Bin energy 128 *2 sets */ + Word32 *Bin_E_old, /* o: FFT Bin energy 128 sets */ + Word16 *mem_syn_bck, /* o: synthesis filter memory */ + Word16 *mem_w0_bck, /* o: memory of the weighting filter */ + Word16 *streaklimit, + Word16 *pstreaklen +); + +void decod_ppp_fx( + Decoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */ + Word16 *pitch_buf_fx, /* i/o: fixed pitch values for each subframe */ + Word16 *exc_fx, /* i/o: current non-enhanced excitation */ + Word16 *exc2_fx, /* i/o: current enhanced excitation */ + Word16 bfi /* i : bad frame indicator */ + ,Word16 *gain_buf /*Q14*/ + ,Word16 *voice_factors, /* o : voicing factors */ + Word16 *bwe_exc_fx /* o : excitation for SWB TBE */ +); + +void ppp_quarter_decoder_fx( + DTFS_STRUCTURE_FX *CURRCW_Q_DTFS_FX, /* i/o: Current CW DTFS */ + Word16 prevCW_lag_fx, /* i : Previous lag */ + Word16 *lastLgainD_fx, /* i/o: Last gain lowband Q11 */ + Word16 *lastHgainD_fx, /* i/o: Last gain highwband Q11 */ + Word16 *lasterbD_fx, /* i/o: Last ERB vector Q13 */ + Word16 bfi, /* i : FER flag */ + Word16 *S_fx, /* i : sine table, Q15 */ + Word16 *C_fx, /* i : cosine table, Q15 */ + DTFS_STRUCTURE_FX PREV_CW_D_FX /* i : Previous DTFS */ + ,Decoder_State_fx *st +); + + +void ppp_voiced_decoder_fx( + Decoder_State_fx *st_fx, /* i/o: state structure */ + Word16 *out_fx, /* o : residual signal */ + const Word16 *lpc2_fx, /* i : current frame LPC */ + Word16 *exc_fx, /* i : previous frame excitation */ + Word16 *pitch, /* o : floating pitch values for each subframe */ + Word16 bfi /* i : Frame error rate */ +); + + +void bandwidth_switching_detect_fx( + Decoder_State_fx *st_fx /* i/o: encoder state structure */ +); + +void bw_switching_pre_proc_fx( + const Word16 *old_syn_12k8_16k_fx, /* i : ACELP core synthesis at 12.8kHz or 16kHz */ + Decoder_State_fx *st_fx /* i/o: decoder state structure */ +); + +void updt_bw_switching_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 *synth, /* i : float synthesis signal */ + const Word16 Qpost +); +void updt_dec_common_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 hq_core_type_fx, /* i : HQ core type */ + const Word16 *synth /* i : decoded synthesis */ +); + +void sort_32_fx( + Word32 *r, /* i/o: Vector to be sorted in place */ + const Word16 lo, /* i : Low limit of sorting range */ + const Word16 up /* I : High limit of sorting range */ +); +Word16 FEC_SinOnset_fx ( + Word16 *exc, /* i/o : exc vector to modify */ + Word16 puls_pos, /* i : last pulse position desired */ + const Word16 T0, /* i : Pitch information of the 1 subfr */ + Word32 enr_q, /* i : energy provide by the encoder */ + Word16 *Aq, /* i : A(z) filter Q12 */ + const Word16 L_frame /* i : frame length */ + ,const Word16 Qold +); +Word16 FEC_enhACB_fx( + const Word16 L_frame, /* i : frame length */ + const Word16 last_L_frame, /* i : frame length of previous frame */ + Word16 *exc_io, /* i/o : adaptive codebook memory */ + const Word16 new_pit, /* i : decoded first frame pitch */ + const Word16 puls_pos, /* i : decoder position of the last glottal pulses decoded in the previous frame */ + const Word16 bfi_pitch /* i : Q6 pitch used for concealment */ +); + + +void fft3_fx(const Word16 [], Word16 [], const Word16); +void ifft3_fx(const Word16 [], Word16 [], const Word16); +void hq_ecu_fx( + const Word16 *prevsynth, /* i : buffer of previously synthesized signal */ + Word32 *ecu_rec, /* o : reconstructed frame in tda domain */ + Word16 *time_offs, + Word16 *X_sav, + Word16 *Q_spec, /* i/o : Q value of stored spectrum */ + Word16 *num_p, + Word16 *plocs, + Word32 *plocsi, /* o : Interpolated positions of the identified peaks (Q16) */ + const Word16 env_stab, + Word16 *last_fec, + const Word16 ph_ecu_HqVoicing, + Word16 *ph_ecu_active, /* i : Phase ECU active flag */ + Word16 *gapsynth, + const Word16 prev_bfi, /* i : indicating burst frame error */ + const Word16 old_is_transient[2], /* i : flags indicating previous transient frames */ + Word16 *mag_chg_1st, /* i/o: per band magnitude modifier for transients*/ + Word16 *Xavg, /* i/o: Frequency group average gain to fade to */ + Word16 *beta_mute, /* o : Factor for long-term mute */ + const Word16 output_frame, /* i : frame length */ + Decoder_State_fx *st_fx /* i/o: decoder state structure */ +); + +void hq_timedomain_conc_fx( + Word32 *ecu_rec, /* o : reconstructed frame in tda domain */ + Word16 *gapsynth, /* o : Gap synthesis */ + const Word16 output_frame, /* i : frame length */ + const Word16 *prevsynth, /* i : buffer of previously synthesized signal */ + Decoder_State_fx *st_fx /* i/o: decoder state structure */ +); + +Word16 ratio(const Word32, const Word32, Word16 *); + + +void nearProjQ15_fx( + Word16 x, + Word16 *result +); + +void Ratio_rQ3_fx( + Word16 opp, + Word16 near, + Word16 *result +); + +void densityAngle2RmsProjDec_fx( + Word16 D, /* i: density */ + Word16 indexphi, /* i: decoded index from AR dec */ + Word16 *oppQ15, /* o: proj*/ + Word16 *nearQ15, /* o: */ + Word16 *oppRatioQ3 /* o: */ +) ; + +void densityAngle2RmsProjEnc_fx ( + Word16 D, + Word16 phiQ14uq, + Word16 *indexphi, /* o: index to send to AR */ + Word16 *oppQ15, /* o: proj*/ + Word16 *nearQ15, + Word16 *oppRatioQ3 +) ; +void dsDiracPerQuanta_fx( + const Word16 td, + const Word16 t_quanta, + const Word16 dsm, + const unsigned char* const *frQuanta, + Word16 *DsIdx +); + +void QuantaPerDsDirac_fx( + Word16 td, + Word16 dsDiracIndex, + const unsigned char* const* dimFrQuanta, + Word16 *Quanta +); + +void obtainEnergyQuantizerDensity_fx( + const Word16 L, + const Word16 R, + Word16 *Density +); + +void dsDirac2Dirac_fx( + const Word16 dsDiracIndex, + Word16 *diracs +); + + +void NearOppSplitAdjustment_fx( + const Word16 qband, + const Word16 qzero, + const Word16 Qac, + const UWord32 INTac, + const Word16 qglobal, + const Word16 FlagCons, + const Word16 Np, + const Word16 Nhead, + const Word16 Ntail, + const Word16 Nnear, + const Word16 Nopp, + Word16 oppRQ3, + Word16 *qnear, + Word16 *qopp, + Word16 *qglobalupd +) ; + + + + +/* IGFEnc.c */ +void IGFEncApplyMono(const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + const Word16 igfGridIdx, /**< in: Q0 | IGF grid index */ + Encoder_State_fx *st, /**< in: | Encoder state */ + Word32 *pMDCTSpectrum, /**< in: Q31 | MDCT spectrum */ + Word16 MDCTSpectrum_e, /**< in: | exponent of MDCT spectrum */ + Word32 *pPowerSpectrum, /**< in: Q31 | MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 PowerSpectrum_e, /**< in: | exponent of pPowerSpectrum */ + Word16 isTCX20, /**< in: Q0 | flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + Word16 isTNSActive, /**< in: Q0 | flag indicating if the TNS is active */ + Word16 last_core_acelp /**< in: Q0 | indictaor if last frame was acelp coded */ + ); + +void IGFEncConcatenateBitstream(const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + Word16 bsBits, /**< in: Q0 | number of IGF bits written to list of indices */ + Word16 *next_ind, /**< in/out: | pointer to actual bit indice */ + Word16 *nb_bits, /**< in/out: | total number of bits already written */ + Indice_fx *ind_list_fx /**< in: | pointer to list of indices */ + ); + +void IGFEncResetTCX10BitCounter(const IGF_ENC_INSTANCE_HANDLE hInstance /**< in: | instance handle of IGF Encoder */ + ); + +void IGFEncSetMode(const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + const Word32 bitRate, /**< in: Q0 | encoder bitrate */ + const Word16 mode /**< in: Q0 | encoder bandwidth mode */ + , const Word16 rf_mode /**< in: | flag to signal the RF mode */ + + ); + +Word16 IGFEncWriteBitstream( /**< out: | number of bits written per frame */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + Encoder_State_fx *st, /**< in: | encoder state */ + Word16 *pBitOffset, /**< in: | ptr to bitOffset counter */ + const Word16 igfGridIdx, /**< in: Q0 | igf grid index see declaration of IGF_GRID_IDX for details */ + const Word16 isIndepFlag /**< in: Q0 | if 1 frame is independent, 0 = frame is coded with data from previous frame */ +); + +Word16 IGFEncWriteConcatenatedBitstream( /**< out: Q0 | total number of bits written */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + void *st /**< in: | encoder state */ +); + +/* IGFDec.c */ +void IGFDecApplyMono(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + Word32 *spectrum, /**< in/out: | MDCT spectrum */ + Word16 *spectrum_e, /**< in/out: | exponent of spectrum */ + const Word16 igfGridIdx, /**< in: | in case of CELP->TCX switching, use 1.25 framelength */ + Word16 bfi /**< in: | frame loss == 1, frame good == 0 */ + ); + +void IGFDecCopyLPCFlatSpectrum(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const Word32 *pSpectrumFlat, /**< in: Q31 | LPC flattend spectrum from TCX dec */ + const Word16 pSpectrumFlat_exp, /**< in: | exponent of pSpectrumFlat */ + const Word16 igfGridIdx /**< in: Q0 | IGF grid index */ + ); + +void IGFDecReadData(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Deccoder */ + Decoder_State_fx *st, /**< in: | decoder state */ + const Word16 igfGridIdx, /**< in: Q0 | in case of CELP->TCX switching, use 1.25 framelength */ + const Word16 isIndepFrame /**< in: Q0 | if 1: arith dec force reset, if 0: no reset */ + ); + +void IGFDecReadLevel( const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Deccoder */ + Decoder_State_fx *st, /**< in: | decoder state */ + const Word16 igfGridIdx, /**< in: Q0 | in case of CELP->TCX switching, use 1.25 framelength */ + const Word16 isIndepFrame /**< in: Q0 | if 1: arith dec force reset, if 0: no reset */ + ); + +void IGFDecRestoreTCX10SubFrameData(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const Word16 subFrameIdx /**< in: Q0 | index of subframe */ + ); + +void IGFDecSetMode(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const Word32 bitRate, /**< in: Q0 | bitrate */ + const Word16 mode, /**< in: Q0 | bandwidth mode */ + const Word16 defaultStartLine, /**< in: Q0 | default start subband index */ + const Word16 defaultStopLine /**< in: Q0 | default stop subband index */ + , const Word16 rf_mode /**< in: | flag to signal the RF mode */ + ); + +void IGFDecStoreTCX10SubFrameData(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const Word16 subFrameIdx /**< in: Q0 | index of subframe */ + ); + +void IGFDecUpdateInfo(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const Word16 igfGridIdx /**< in: | IGF grid index */ + ); + +/* iisBaseLib.c */ +void IGFCommonFuncsCalcSfbEnergyPowerSpec(const Word16 startSfb, /**< in: Q0 | start sfb index */ + const Word16 stopSfb, /**< in: Q0 | stop sfb index */ + const Word16 *swb_offset, /**< in: Q0 | IGF swb offset table */ + Word32 *pPowerSpectrum, /**< in: Q31 | power spectrum */ + Word16 *pPowerSpectrum_exp, /**< in: | Exponent of PowerSpectrum */ + Word32 *sfbEnergy, /**< out:Q31 | SFB energies , will be initialized inside this function */ + Word16 *sfbEnergy_exp /**< out: | Exponent of PowerSpectrum */ + ); + +Word16 IGFCommonFuncsIGFConfiguration( /**< out: | error value: 0 -> error, 1 -> ok */ + Word32 bitRate, /**< in: Q0 | bitrate in bs e.g. 9600 for 9.6kbs */ + Word16 mode, /**< in: Q0 | bandwidth mode */ + H_IGF_INFO hIGFInfo /**< out: | IGF info handle */ + ,Word16 rf_mode /**< in: flag to signal the RF mode */ +); + +Word16 IGFCommonFuncsIGFGetCFTables( /**< out: | error value: 0 -> error, 1 -> ok */ + Word32 bitRate, /**< in: Q0 | bitrate in bs e.g. 9600 for 9.6kbs */ + Word16 mode, /**< in: Q0 | bandwidth mode */ + Word16 rf_mode, /**< in: | flag to signal the RF mode */ + const Word16 **cf_se00, /**< out: | CF table for t == 0 and f == 0 */ + const Word16 **cf_se01, /**< out: | CF table for t == 0 and f == 1 */ + Word16 *cf_off_se01, /**< out: | offset for CF table above */ + const Word16 **cf_se02, /**< out: | CF tables for t == 0 and f >= 2 */ + const Word16 **cf_off_se02, /**< out: | offsets for CF tables above */ + const Word16 **cf_se10, /**< out: | CF table for t == 1 and f == 0 */ + Word16 *cf_off_se10, /**< out: | offset for CF table above */ + const Word16 **cf_se11, /**< out: | CF tables for t == 1 and f >= 1 */ + const Word16 **cf_off_se11 /**< out: | offsets for CF tables above */ +); + +void IGFCommonFuncsMDCTSquareSpec(const Word16 sqrtBgn, /**< in: Q0 | start MDCT subband index */ + const Word16 sqrtEnd, /**< in: Q0 | stop MDCT subband index */ + const Word32 *mdctSpec, /**< in: Q31 | MDCT spectrum to square */ + const Word16 mdctSpec_e, /**< in: | exponent of mdctSpectrum */ + Word32 *mdctSquareSpec, /**< out:Q31 | MDCT square spectrum */ + Word16 *mdctSquareSpec_e, /**< out: | exponent of mdctSquareSpec */ + Word16 indexOffset /**< in: Q0 | index offset */ + ); + +void IGFCommonFuncsWriteSerialBit(void *st, /**< in: | encoder/decoder state structure */ + Word16 *pBitOffset, /**< out: Q0 | bit offset */ + Word16 bit /**< in: Q0 | value of bit */ + ); + +/* IGFSCFEncoder.c */ +void IGFSCFEncoderOpen( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /* i/o: handle to public data */ + Word16 scfCountLongBlock, /* i: number of SCFs for a long block */ + Word32 bitRate, /* i: bitrate in bps */ + Word16 mode /* i: operating mode */ + , Word16 rf_mode /**< in: flag to signal the RF mode */ +); + +void IGFSCFEncoderReset( + IGFSCFENC_INSTANCE_HANDLE hPublicData /* i/o: handle to public data */ +); + +Word16 IGFSCFEncoderEncode( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /* i/o: handle to public data */ + Encoder_State_fx *st, /* i/o: pointer to encoder state */ + Word16 bitCount, /* i: offset to the first bit in bitbuffer which should be written by the raw AC functions */ + Word16 *sfe, /* i: pointer to an array which contains the quantized SCF energies to be encoded */ + Word16 indepFlag, /* i: 1 if the block is an independent block, 0 otherwise */ + Word16 doRealEncoding /* i: whether the real encoding is needed, otherwise only the number of bits is used */ +); + +void IGFSCFEncoderSaveContextState( + IGFSCFENC_INSTANCE_HANDLE hPublicData /* i/o: handle to public data */ +); + +void IGFSCFEncoderRestoreContextState( + IGFSCFENC_INSTANCE_HANDLE hPublicData /* i/o: handle to public data */ +); + +/* IGFSCFDecoder.c */ +void IGFSCFDecoderOpen( + IGFSCFDEC_INSTANCE_HANDLE hPublicData, /* i/o: handle to public data */ + Word16 scfCountLongBlock, /* i: number of SCFs for a long block */ + Word32 bitRate, /* i: bitrate in bps */ + Word16 mode /* i: operating mode */ + ,Word16 rf_mode +); + +void IGFSCFDecoderReset( + IGFSCFDEC_INSTANCE_HANDLE hPublicData /* i/o: handle to public data */ +); + +void IGFSCFDecoderDecode( + IGFSCFDEC_INSTANCE_HANDLE hPublicData, /* i/o: handle to public data */ + Decoder_State_fx *st, /* i/o: pointer to decoder state */ + Word16 *sfe, /* o: pointer to an array which will contain the decoded quantized SCFs */ + Word16 indepFlag /* i: 1 if the block is an independent block, 0 otherwise */ +); + +Word32 SFM_Cal(Word32 magn[], Word16 n); + + +void Unified_weighting_fx( + Word32 Bin_Ener_128_fx[], /* i : FFT Bin energy 128 bins in two sets Q_ener */ + Word16 Q_ener, + const Word16 lsf_fx[], /* i : LSF vector x2.56 */ + Word16 w_fx[], /* o : LP weighting filter (numerator) Q8 */ + const Word16 narrowBand, /* i : flag for Narrowband */ + const Word16 unvoiced, /* i : flag for Unvoiced frame */ + const Word32 sr_core, /* i : sampling rate of core-coder */ + const Word16 order /* i : LP order */ +); + +void lsf_dec_bfi( + const Word16 codec_mode, /* i: : codec mode: MODE1 | MODE2 */ + Word16*lsf, /*!< o : 14Q1*1.28 quantized ISFs */ + const Word16*lsfold, /*!< i : 14Q1*1.28 past quantized ISF */ + Word16*lsf_adaptive_mean, /*!< i : 14Q1*1.28 ISF adaptive mean, updated when BFI==0 */ + const Word16 lsfBase[], /* i : base for differential lsf coding */ + Word16*mem_MA, /*!< i/o: 14Q1*1.28 quantizer memory for MA model */ + Word16*mem_AR, /*!< i/o: 14Q1*1.28 quantizer memory for MA model */ + Word16 stab_fac, /*!< i : ISF stability factor (shifted right by 1) */ + const Word16 last_coder_type, /*!< i : coding type in last good received fr. */ + Word16 L_frame, + const Word16 last_good, /*!< i : last good received frame */ + const Word16 nbLostCmpt, /*!< i : counter of consecutive bad frames */ + Word8 plcBackgroundNoiseUpdated, + Word16 *lsf_q_cng, /* o : quantized ISFs for background noise (14Q1*1.28) */ + Word16 *lsf_cng, + Word16 *old_lsf_q_cng, /* o : old quantized ISFs for background noise */ + const Word16 Last_GSC_pit_band_idx, + const Word16 Opt_AMR_WB, /* i : IO flag */ + const Word8 tcxonly + ,const short MODE1_bwidth /* i: coded bandwidth */ +); + + +void lpc_quantization( + Encoder_State_fx * st, + const Word16 core, + const Word16 lpcQuantization, + const Word16 lsfold_q[], + const Word16 lsp[], + const Word16 lspmid[], + Word16 lsp_q[], + Word16 lsf_q[], /* 14Q1*1.28 */ + Word16 lspmid_q[], + Word16 lspq_ind[], + Word16 clip_var[], + Word16 mem_MA[], + Word16 mem_AR[], + const Word8 narrowBand, + const Word16 coder_type, + const Word8 acelp_midLpc, + Word16 param_lpc[], + Word16 nbits_lpc[], + Word16 * bits_param_lpc, + Word16 *no_param_lpc, + Word16 *seed_acelp, + Word32 * Bin_Ener_fx, + Word32 * Bin_Ener_old_fx, + const Word16 Q_ener +); + + + +/* enc_util.c */ +void Scale_sig( + Word16 x[], /* i/o: signal to scale Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx xx exp */ +); +void E_UTIL_f_preemph(Word16 *signal, const Word16 mu, const Word16 lg, Word16 *mem); +void E_UTIL_f_preemph2(Word16 shift, Word16 *signal, const Word16 mu, const Word16 lg, Word16 *mem); +Word16 E_UTIL_f_preemph3(Word16 *signal, const Word16 mu, const Word16 lg, Word16 *mem, Word16 bits); +void deemph_fx(Word16 * signal, const Word16 mu, const Word16 L, Word16 * mem); +void E_UTIL_deemph2(Word16 shift, Word16 *x, const Word16 mu, const Word16 L, Word16 *mem); +void E_UTIL_synthesis(const Word16 shift, const Word16 a[], const Word16 x[], Word16 y[], + const Word16 lg, Word16 mem[], const Word16 update, const Word16 m); +void E_UTIL_f_convolve(const Word16 x[], const Word16 h[], Word16 y[], const Word16 size); + +Word16 E_ACELP_hh_corr(Word16 *x, Word16 *y, Word16 L_subfr, Word16 bits); +Word16 E_ACELP_toeplitz_mul(const Word16 R[], const Word16 c[], Word16 d[], const Word16 L_subfr, const Word16 highrate); + +void E_ACELP_weighted_code( + const Word16 code[], /* i: code */ + const Word16 H[], /* i: impulse response */ + Word16 Q, /* i: Q format of H */ + Word16 y[] /* o: weighted code */ +); + +void E_ACELP_conv( + const Word16 xn2[], /* i */ + const Word16 h2[], /* i */ + Word16 cn2[] /* o */ +); + +void E_ACELP_build_code( + Word16 nb_pulse, /* i */ + const Word16 codvec[], /* i */ + const Word16 sign[], /* i */ + Word16 code[], /* o */ + Word16 ind[] /* o */ +); + +void E_ACELP_setup_pulse_search_pos( + const PulseConfig *config, /* i: pulse configuration */ + Word16 k, /* i: interation number */ + UWord8 ipos[] /* o: pulse search positions */ +); + +void find_wsp( + const Word16 Az[], + const Word16 speech[], + Word16 wsp[], + Word16 *mem_wsp, + const Word16 preemph_fac, + const Word16 L_frame, + const Word16 lookahead, + const Word16 L_subfr, + Word16 Aw[], /* o : weighted A(z) filter coefficients */ + const Word16 gamma, /* i : weighting factor */ + const Word16 nb_subfr /* i : number of subframes */ +); + +void init_sig_buffers( Encoder_State_fx *st, const Word16 L_frame_old, const Word16 L_subfr ); + +void E_UTIL_cb_shape( + const Word16 preemphFlag, /* i : flag for pre-emphasis */ + const Word16 pitchFlag, /* i : flag for pitch sharpening */ + const Word16 scramblingFlag, /* i : flag for phase scrambling */ + const Word16 formant_enh, /* i : use formant enhancement Q15 */ + const Word16 formant_tilt, /* i : use tilt of formant enhancement Q0 */ + const Word16 g1, /* i : formant sharpening numerator weighting */ + const Word16 g2, /* i : formant sharpening denominator weighting */ + const Word16 *Aq, /* i : quantized LPC coefficients 3Q12 */ + Word16 *code, /* i/o: <14b */ + const Word16 tilt_code, /* i : tilt factor Q15 */ + const Word16 pitch /* i : pointer to current subframe fractional pitch */ +); + +void E_UTIL_voice_factor( Word16 *exc, /* i : pointer to the excitation frame Q_new */ + Word16 i_subfr, /* i : subframe index */ + Word16 *code, /* i : innovative codebook Q9 */ + Word16 gain_pit, /* i : adaptive codebook gain 1Q14 */ + Word32 gain_code, /* i : innovative cb. gain 15Q16 */ + Word16 *voice_fac, /* o : subframe voicing estimation Q15 */ + Word16 *tilt_code, /* o : tilt factor Q15 */ + Word16 L_subfr, /* i : subframe length */ + Word16 flag_tilt, /* i : Flag for triggering new voice factor tilt*/ + Word16 Q_new, /* i : excitation buffer format */ + Word16 shift /* i : scaling to get 12bit */ + ); + +Word16 E_UTIL_enhancer( + Word16 voice_fac, /* i : subframe voicing estimation Q15 */ + Word16 stab_fac, /* i : LP filter stability measure Q15 */ + Word32 gain_code, /* i : innovative cb. gain 15Q16 */ + Word16 gain_inov, /* i : gain of the unscaled innovation Q12 */ + Word32 *gc_threshold, /* i/o: gain code threshold 15Q16 */ + Word16 *code, /* i/o: innovation(in: Q9) code_exp */ + Word16 *exc2, /* i/o: adapt. excitation/total exc. Q15 */ + Word16 gain_pit, /* i : Quantized pitch gain 1Q14 */ + Word32 *prev_gain_code, /* i/o: previous codebook gain 15Q16 */ + Word16 prev_gain_pit[], /* i/o: previous pitch gain, size=6 1Q14 */ + Word16 *prev_state, /* i/o: Phase dispersion algorithm memory Q0 */ + Word16 coder_type, /* i : coder type */ + Word16 cdk_index, /* i : */ + Word16 L_subfr, /* i : */ + Word16 L_frame, /* i : frame size */ + Word16 Q_new +); + +Word32 E_LPC_schur(Word32 r[], Word16 reflCoeff[], Word32 epsP[], const Word16 m); +Word16 E_LPC_lev_dur_stab(const Word16 Rh[], const Word16 Rl[], Word16 A[], + Word32 epsP[], const Word16 order, Word16 *parcorr, Word16 k_max + ); +Word16 E_LPC_lev_dur(const Word16 Rh[], const Word16 Rl[], Word16 A[], + Word32 epsP[], const Word16 order, Word16 *parcorr + ); + +void E_LPC_a_weight_inv(const Word16 *a, Word16 *ap, const Word16 gamma, const Word16 m); +void E_LPC_a_add_tilt(const Word16 *a, Word16 *ap, Word16 gamma, Word16 m); +void E_LPC_a_lsf_isf_conversion(Word16 *lpcCoeffs, Word16 *lsf, const Word16 *old_lsf, Word16 lpcOrder, Word8 lpcRep); +void E_LPC_a_lsp_conversion( + const Word16 *a, /* input : LP filter coefficients */ + Word16 *lsp, /* output: Line spectral pairs (in the cosine domain) */ + const Word16 *old_lsp, /* input : LSP vector from past frame */ + const Word16 m /* input : LPC order */ +); +void E_LPC_lsp_lsf_conversion( + const Word16 lsp[], /* input: lsp[m] (range: -1<=val<1) */ + Word16 lsf[], /* output : lsf[m] normalized (range: 0<=val<=6400) */ + const Word16 m /* input : LPC order */ +); +void E_LPC_lsf_lsp_conversion( + const Word16 lsf[], /* input : lsf[m] normalized (range: 0<=val<=6400) */ + Word16 lsp[], /* output: lsp[m] (range: -1<=val<1) */ + const Word16 m /* input : LPC order */ +); + +void E_LPC_f_lsp_a_conversion(const Word16 *lsp, Word16 *a, const Word16 m); +void E_LPC_a_isp_conversion( + const Word16 *a, /* input : LP filter coefficients */ + Word16 *isp, /* output: Line spectral pairs (in the cosine domain) */ + const Word16 *old_isp,/* input : LSP vector from past frame */ + const Word16 m /* input : LPC order */ +); +void E_LPC_isp_isf_conversion(const Word16 isp[], Word16 isf[], const Word16 m); +void E_LPC_isf_isp_conversion(const Word16 isf[], Word16 isp[], const Word16 m); +void E_LPC_f_isp_a_conversion(const Word16 *isp, Word16 *a, const Word16 m); +void E_LPC_int_lpc_tcx(const Word16 lsp_old[], /* input : LSPs from past frame (1Q14) */ + const Word16 lsp_new[], /* input : LSPs from present frame (1Q14) */ + Word16 a[] /* output: interpolated LP coefficients (4Q11) */ + ); + +/* enc_gain.c */ + +Word16 E_GAIN_closed_loop_search(Word16 exc[], + Word16 xn[], Word16 h[], + Word16 t0_min, Word16 t0_min_frac, Word16 t0_max, Word16 t0_max_frac, Word16 t0_min_max_res, Word16 *pit_frac, Word16 *pit_res, Word16 pit_res_max, + Word16 i_subfr, Word16 pit_min, Word16 pit_fr2, Word16 pit_fr1, Word16 L_subfr); +void E_GAIN_norm_corr(Word16 exc[], Word16 xn[], Word16 h[], + Word16 t_min, Word16 t_max, Word16 corr_norm[], Word16 L_subfr); + +/* enc_acelp.c */ +void E_ACELP_xy2_corr(Word16 xn[], Word16 y1[], Word16 y2[], ACELP_CbkCorr *g_corr, Word16 L_subfr, Word16 exp_xn); +Word16 E_ACELP_xy1_corr(Word16 xn[], Word16 y1[], ACELP_CbkCorr *g_corr, Word16 norm_flag, Word16 L_subfr, Word16 exp_xn); +void E_ACELP_codebook_target_update(Word16 *x, Word16 *x2, Word16 *y, Word16 gain, Word16 L_subfr); +void E_ACELP_h_vec_corr1(Word16 h[], Word16 vec[], UWord8 track, Word16 sign[], Word16 (*rrixix)[16], Word16 cor[], Word16 dn2_pos[], Word16 nb_pulse); +void E_ACELP_h_vec_corr2(Word16 h[], Word16 vec[], UWord8 track, Word16 sign[], Word16 (*rrixix)[16], Word16 cor[]); +void E_ACELP_4tsearch(Word16 dn[], const Word16 cn[], const Word16 H[], Word16 code[], const PulseConfig *config, Word16 ind[], Word16 y[]); +void E_ACELP_4tsearchx(Word16 dn[], const Word16 cn[], Word16 Rw[], Word16 code[], const PulseConfig *config, Word16 ind[]); +void E_ACELP_pulsesign(const Word16 cn[], Word16 dn[], Word16 dn2[], Word16 sign[], Word16 vec[], const Word16 alp, Word16 const sign_val, const Word16 L_subfr); + +Word16 E_ACELP_indexing(const Word16 code[], const PulseConfig *config, Word16 num_tracks, Word16 prm[]); +void E_ACELP_findcandidates(Word16 dn2[], Word16 dn2_pos[], Word16 pos_max[]); +void E_ACELP_vec_neg(Word16 h[], Word16 h_inv[], Word16 L_subfr); +void E_ACELP_corrmatrix(Word16 h[], Word16 sign[], Word16 vec[], Word16 rrixix[4][16], Word16 rrixiy[4][256]); +void E_ACELP_codearithp(const Word16 v[], UWord32 *n, UWord32 *ps, Word16 *p); + +void find_targets_fx( + const Word16 *speech, /* i : pointer to the speech frame Q_new-1*/ + const Word16 *mem_syn, /* i : memory of the synthesis filter Q_new-1*/ + const Word16 i_subfr, /* i : subframe index */ + Word16 *mem_w0, /* i/o: weighting filter denominator memory Q_new-1*/ + const Word16 *p_Aq, /* i : interpolated quantized A(z) filter Q12*/ + const Word16 *res, /* i : residual signal Q_new*/ + const Word16 L_subfr, /* i : length of vectors for gain quantization */ + const Word16 *Ap, /* i : unquantized A(z) filter with bandwidth expansion Q12*/ + Word16 tilt_fac, /* i : tilt factor Q15 */ + Word16 *xn, /* o : Close-loop Pitch search target vector Q_new-1*/ + Word16 *cn /* o : target vector in residual domain Q_new*/ + ,Word16 *h1 /* Q14 ?*/ +); + +void E_ACELP_adaptive_codebook( + Word16 *exc, /* i : pointer to the excitation frame */ + Word16 T0, /* i : integer pitch lag */ + Word16 T0_frac, /* i : fraction of lag */ + Word16 T0_res, /* i : pitch resolution */ + Word16 T0_res_max, /* i : maximum pitch resolution */ + Word16 mode, /* i : filtering mode (0: no, 1: yes, 2: adaptive) */ + Word16 i_subfr, /* i : subframe index */ + Word16 L_subfr, /* i : subframe length */ + Word16 L_frame, /* i : subframe length */ + Word16 *h1, /* i : impulse response of weighted synthesis filter */ + Word16 clip_gain, + Word16 *xn, /* i : Close-loop Pitch search target vector */ + Word16 *y1, /* o : zero-memory filtered adaptive excitation */ + ACELP_CbkCorr *g_corr, /* o : ACELP correlation values */ + Word16 **pt_indice, /* i/o: quantization indices pointer */ + Word16 *pitch_gain, /* o : adaptive codebook gain */ + Word16 exp_xn + ,Word16 rf_mode + ,Word16 use_prev_sf_pit_gain + ,Word16* lp_select +); + +void E_ACELP_innovative_codebook( + Word16 *exc, /* i : pointer to the excitation frame */ + Word16 T0, /* i : integer pitch lag */ + Word16 T0_frac, /* i : fraction of lag */ + Word16 T0_res, /* i : pitch resolution */ + Word16 gain_pit, /* i : adaptive codebook gain */ + Word16 tilt_code, /* i : tilt factor */ + Word16 mode, /* i : innovative codebook mode */ + Word16 formant_enh, /* i : use formant enhancement Q15 */ + Word16 formant_tilt, /* i : use tilt of formant enhancement */ + const Word16 formant_enh_num, /* i : formant sharpening numerator weighting */ + const Word16 foramnt_enh_den, /* i : formant sharpening denominator weighting */ + Word16 pitch_sharpening,/* i : use pitch sharpening */ + Word16 pre_emphasis, + Word16 phase_scrambling, + Word16 i_subfr, /* i : subframe index */ + const Word16 *Aq, /* i : quantized LPC coefficients */ + Word16 *h1, /* i : impulse response of weighted synthesis filter */ + Word16 *xn, /* i : Close-loop Pitch search target vector */ + Word16 *cn, /* i : Innovative codebook search target vector */ + Word16 *y1, /* i : zero-memory filtered adaptive excitation */ + Word16 *y2, /* o : zero-memory filtered algebraic excitation */ + Word8 acelpautoc, /* i : autocorrelation mode enabled */ + Word16 **pt_indice, /* i/o: quantization indices pointer */ + Word16 *code, /* o : innovative codebook Q9 */ + Word16 shift /* i : Scaling to get 12 bits */ + ,const Word16 L_frame, /* i : length of the frame */ + const Word16 last_L_frame, /* i : length of the last frame */ + const Word32 total_brate /* i : total bit-rate */ +); + +Word16 E_ACELP_code43bit(const Word16 code[], UWord32 *ps, Word16 *p, UWord16 idxs[]); +void fcb_pulse_track_joint(UWord16 *idxs, Word16 wordcnt, UWord32 *index_n, Word16 *pulse_num, Word16 track_num); + +void encode_acelp_gains( + Word16 *code, /* Q9 */ + Word16 gains_mode, + Word16 mean_ener_code, + Word16 clip_gain, + ACELP_CbkCorr *g_corr, + Word16 *gain_pit, /* Q14 */ + Word32 *gain_code, /* 15Q16 */ + Word16 **pt_indice, + Word32 *past_gcode, /* 15Q16 */ + Word16 *gain_inov, /* Q12 */ + Word16 L_subfr, + Word16 *code2, + Word32 *gain_code2, + Word8 noisy_speech_flag /* (i) : noisy speech flag */ +); + +extern const long int pulsestable[6][7]; +extern const PulseConfig PulseConfTable[]; +extern const Word16 ACELP_CDK_BITS[]; + +void D_ACELP_indexing( + Word16 code[], + PulseConfig config, + Word16 num_tracks, + Word16 index[] + ,Word16 *BER_detect +); + +void D_ACELP_decode_43bit(UWord16 idxs[], Word16 code[], Word16 *pulsestrack); +void fcb_pulse_track_joint_decode(UWord16 *idxs, Word16 wordcnt, UWord32 *index_n, Word16 *pulse_num, Word16 track_num); + +/* lag window lag_wind.c */ +void lag_wind( + Word16 r_h[], /* in/out: autocorrelations */ + Word16 r_l[], /* in/out: autocorrelations */ + Word16 m, /* input : order of LP filter */ + Word32 sr, /* input : sampling rate */ + Word16 strength /* input : LAGW_WEAK, LAGW_MEDIUM, or LAGW_STRONG */ +); + +void adapt_lag_wind( + Word16 r_h[], /* in/out: autocorrelations */ + Word16 r_l[], /* in/out: autocorrelations */ + Word16 m, /* input : order of LP filter */ + const Word16 Top, /* input : open loop pitch lag */ + const Word16 Tnc, /* input : open loop pitch gain */ + Word32 sr /* input : sampling rate */ +); + +void hp20(Word16 signal[], /* i/o: signal to filter any */ + const Word16 stride, /* i : stride to be applied accessing signal */ + const Word16 lg, /* i : length of signal (integer) Q0 */ + Word32 mem[5], /* i/o: static filter memory with this layout: */ + /* mem[0]: y[-2] (32-bit) */ + /* mem[1]; y[-1] (32-bit) */ + /* mem[2]: x[-2] << 16 */ + /* mem[3]: x[-1] << 16 */ + /* Note: mem[0..3] need to be scaled per frame */ + /* mem[4]: states scale */ + const Word32 sFreq); /* i : input sampling rate Q0 */ + +/* pit_fr4.c */ +void Mode2_pred_lt4(Word16 exc[], /* in/out: excitation buffer */ + Word16 T0, /* input : integer pitch lag */ + Word16 frac, /* input : fraction of lag */ + Word16 T0_res, /* input : pitch lag resolution */ + Word16 T0_res_max, /* input : maximum resolution */ + Word16 L_subfr); /* input : subframe size */ + + +#define mvr2r_Word32(x,y,n) Copy32(x,y,n) +#define mvr2r_Word16(x,y,n) Copy(x,y,n) +#define vr_intset(val, vector, count) { Word16 i; FOR(i=0; i<(count); i++) { vector[i]=val; } } + +float mean( /* o : the mean of the elements of the vector */ + const float *vec, /* i : input vector */ + const short lvec /* i : length of input vector */ +); + +/* window.c */ +void ham_cos_window(Word16 *fh, const Word16 n1, const Word16 n2); + + +/*---------------------------------------------------------------------* + * main routines * + *---------------------------------------------------------------------*/ + +void init_coder_ace_plus( Encoder_State_fx* st,const Word16 shift); +void core_coder_reconfig( Encoder_State_fx *st); +void core_coder_mode_switch( Encoder_State_fx *st, const Word16 bandwidth_in, const Word32 bitrate, const Word16 shift); + +void enc_acelp_tcx_main( + const Word16 new_samples[], /* i : new samples */ + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 coder_type, /* i : coding type */ + const Word16 pitch[3], /* i : open-loop pitch values for quantiz. */ + const Word16 voicing[3], /* i : open-loop pitch gains */ + Word16 Aw[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/ + const Word16 lsp_new[M], /* i : LSPs at the end of the frame */ + const Word16 lsp_mid[M], /* i : LSPs at the middle of the frame */ + HANDLE_FD_CNG_ENC hFdCngEnc, /* i/o: FD CNG handle */ + Word32 bwe_exc_extended[], /* i/o: bandwidth extended excitation */ + Word16 *voice_factors, /* o : voicing factors */ + Word16 pitch_buf[], /* o : floating pitch for each subframe */ + Word16 vad_hover_flag, + const Word16 vad_flag_dtx, + Word16 *Q_new, + Word16 *shift +); + +/*-----------------------------------------------------------------* + * Pitch prediction for frame erasure * + *-----------------------------------------------------------------*/ +void pitch_pred_linear_fit( + const Word16 /*short*/ bfi_cnt, /* i: bfi counter */ /*Q0 */ + const Word16 /*short*/ last_good, /* i: last classification type */ /*Q0 */ + Word32 /*float*/ *old_pitch_buf, /* i: pitch lag buffer */ /*Q16*/ + Word32 /*float*/ *old_fpitch, /* i: */ /*Q16*/ + Word32 /*float*/ *T0_out, /* o: estimated close loop pitch */ /*Q16*/ + Word16 /* int*/ pit_min, /* i: Minimum pitch lag */ /*Q0 */ + Word16 /* int*/ pit_max, /* i: Maximum pitch lag */ /*Q0 */ + Word16 /*float*/ *mem_pitch_gain, /* i: pitch gain [0] is the most recent subfr gain */ /*Q0*/ + Word16 /* int*/ limitation, + Word8 /*short*/ plc_use_future_lag, /* i: */ /*Q0 */ + Word16 /*short*/ *extrapolationFailed, /* o: flag if extrap decides not to change the pitch *//*Q0 */ + Word16 nb_subfr /* i: number of ACELP subframes */ +); + +void get_subframe_pitch( + Word16 nSubframes, /* i: number of subframes */ /* Q0 */ + Word32 pitchStart, /* i: starting pitch lag (in subframe -1) */ /*15Q16*/ + Word32 pitchEnd, /* i: ending pitch lag (in subframe nSubframes-1) */ /*15Q16*/ + Word32 *pitchBuf /* o: interpolated pitch lag per subframe */ /*15Q16*/ +); + +void core_encode_openloop( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 coder_type, /* i : coding type */ + const Word16 pitch[3], /* i : open-loop pitch values for quantiz. */ + const Word16 voicing[3], /* i : open-loop pitch gains */ + const Word16 Aw[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/ + const Word16 *lsp_new, /* i : LSPs at the end of the frame */ + const Word16 *lsp_mid, /* i : LSPs at the middle of the frame */ + Word16 *pitch_buf, /* i/o: floating pitch values for each subfr*/ + Word16 *voice_factors, /* o : voicing factors */ + Word16 *ptr_bwe_exc, /* o : excitation for SWB TBE */ + const Word16 vad_hover_flag, + const Word16 vad_flag_dtx, + Word16 Q_new, + Word16 shift +); + +void core_acelp_tcx20_switching( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 vad_flag, + Word16 sp_aud_decision0, + Word16 non_staX, + Word16 *pitch, /* i : open-loop pitch values for quantiz. */ + Word16 *pitch_fr, /* i/o: fraction pitch values */ + Word16 *voicing_fr, /* i/o: fractional voicing values */ + const Word16 currFlatness, /* i : flatness */ + const Word16 lsp_mid[M], /* i : LSPs at the middle of the frame */ + const Word16 stab_fac, /* i : LP filter stability */ + Word16 Q_new, + Word16 shift +); + +void core_encode_twodiv( + const Word16 new_samples[], + Encoder_State_fx *st, + const Word16 coder_type, /* i : coding type */ + const Word16 pitch[3], /* i : open-loop pitch values for quantiz. */ + const Word16 voicing[3], /* i : open-loop pitch gains */ + Word16 Aw[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/ + Word16 *Q_new, + Word16 *shift +); + +void core_encode_update( Encoder_State_fx *st); + +void core_encode_update_cng( Encoder_State_fx *st, + Word16 *timeDomainBuffer, + Word16 *A, + Word16 *Aw, + Word16 Q_new, + Word16 shift + ); + +/* core_sig_ana.c */ +void core_signal_analysis_post(const Word16 *new_samples, Encoder_State_fx *st); + +/* ext_sig_ana.c */ +void core_signal_analysis_enc(const Word16 *new_samples, /*, -2,, -2 and 2*/ + Word16 mean_ener, /*, -2,, -2 and 2*/ + Word16 mean_ener, /*syn */ + Word8 fb /* i: fullband flag */ +); + +Word16 tcx_get_segSnr(Word16 *wsig, Word16 wsig_e, + Word32 *X, Word16 X_e, + Word32 *Xq, Word16 Xq_e, + Word8 *memQuantZeros, + const Word16 snrPenalty, /* 1Q14 */ + Word16 gainlpc_reweight[], Word16 gainlpc_reweight_e[], + Word16 fdns_npts, + Word8 narrowBand, + Word16 gain_tcx, Word16 gain_tcx_e, + Word16 L_frame, + Word16 L_frame_glob, + Word16 L_subfr + ); + +/* Returns: number of bits used (including "bits") Q0 */ +Word16 tcx_ari_res_Q_spec( + const Word32 x_orig[], /* i: original spectrum Q31-e */ + Word16 x_orig_e, /* i: original spectrum exponent Q0 */ + const Word16 signs[], /* i: signs (x_orig[.]<0) Q0 */ + Word32 x_Q[], /* i/o: quantized spectrum Q31-e */ + Word16 x_Q_e, /* i: quantized spectrum exponent Q0 */ + Word16 L_frame, /* i: number of lines Q0 */ + Word16 gain, /* i: TCX gain Q15-e */ + Word16 gain_e, /* i: TCX gain exponent Q0 */ + Word16 prm[], /* o: bit-stream Q0 */ + Word16 target_bits, /* i: number of bits available Q0 */ + Word16 bits, /* i: number of bits used so far Q0 */ + Word16 deadzone, /* i: quantizer deadzone Q15 */ + const Word16 x_fac[] /* i: spectrum post-quantization factors Q14 */ +); + +/* Returns: number of bits used (including "bits") */ +Word16 tcx_ari_res_invQ_spec( + Word32 x_Q[], /* i/o: quantized spectrum Q31-e */ + Word16 x_Q_e, /* i: quantized spectrum exponent Q0 */ + Word16 L_frame, /* i: number of lines Q0 */ + const Word16 prm[], /* i: bit-stream Q0 */ + Word16 target_bits, /* i: number of bits available Q0 */ + Word16 bits, /* i: number of bits used so far Q0 */ + Word16 deadzone, /* i: quantizer deadzone Q15 */ + const Word16 x_fac[] /* i: spectrum post-quantization factors Q14 */ +); + +Word16 tcx_res_Q_gain( + Word16 sqGain, + Word16 sqGain_e, + Word16 *gain_tcx, + Word16 *gain_tcx_e, + Word16 *prm, + Word16 sqTargetBits +); + +Word16 tcx_res_Q_spec( + Word32 *x_orig, + Word16 x_orig_e, + Word32 *x_Q, + Word16 x_Q_e, + Word16 L_frame, + Word16 sqGain, + Word16 sqGain_e, + Word16 *prm, + Word16 sqTargetBits, + Word16 bits, + Word16 sq_round, + const Word16 lf_deemph_factors[] +); + +Word16 tcx_res_invQ_gain( + Word16 *gain_tcx, + Word16 *gain_tcx_e, + Word16 *prm, + Word16 resQBits +); + +Word16 tcx_res_invQ_spec( + Word32 *x, + Word16 x_e, + Word16 L_frame, + Word16 *prm, + Word16 resQBits, + Word16 bits, + Word16 sq_round, + const Word16 lf_deemph_factors[] +); + +void InitTnsConfigs( + Word32 nSampleRate, + Word16 L_frame, + STnsConfig tnsConfig[2][2] + ,Word16 igfStopFreq + ,Word32 bitrate +); + +void SetTnsConfig(TCX_config * tcx_cfg, Word8 isTCX20, Word8 isAfterACELP); + + +/* ari.c */ +Word32 L_multi31x16_X2(Word16 xh, Word16 xl, Word16 y); +Word32 mul_sbc_14bits(Word32 r, Word16 c); + +void ari_copy_states( + TastatEnc *source, + TastatEnc *dest +); + +void ari_start_encoding_14bits( + TastatEnc *s +); + +Word16 ari_done_encoding_14bits( + Word16 *ptr, + Word16 bp, + TastatEnc *s +); + +Word16 ari_encode_14bits_ext( + Word16 *ptr, + Word16 bp, + TastatEnc *s, + Word32 symbol, + UWord16 const *cum_freq +); + +void ari_start_decoding_14bits( + Decoder_State_fx *st, + TastatDec *s +); + +Word16 ari_decode_14bits_s17_ext( + Decoder_State_fx *st, + TastatDec *s, + UWord16 const *cum_freq +); + +Word16 ari_decode_14bits_s27_ext( + Decoder_State_fx *st, + TastatDec *s, + UWord16 const *cum_freq +); + +Word16 ari_decode_14bits_bit_ext( + Decoder_State_fx *st, + TastatDec *s +); + + +Word16 ari_encode_overflow(TastatEnc *s); +Word16 ari_encode_14bits_range(Word16 *ptr, Word16 bp, Word16 bits, TastatEnc *s, Word16 cum_freq_low, Word16 cum_freq_high); +Word16 ari_encode_14bits_sign(Word16 *ptr, Word16 bp, Word16 bits, TastatEnc *s, Word16 sign); +Word16 ari_done_cbr_encoding_14bits(Word16 *ptr, Word16 bp, Word16 bits, TastatEnc *s); +Word16 ari_decode_overflow(TastatDec *s); +Word16 ari_decode_14bits_pow(Word16 *ptr, Word16 bp, Word16 bits, Word16 *res, TastatDec *s, Word16 base); +Word16 ari_decode_14bits_sign(Word16 *ptr, Word16 bp, Word16 bits, Word16 *res, TastatDec *s); +Word16 ari_start_decoding_14bits_prm(const Word16 *ptr, Word16 bp, TastatDec *s); + +/*arith_code.c*/ +Word32 expfp( /* o: Q31 */ + Word16 x, /* i: mantissa Q-e */ + Word16 x_e); /* i: exponent Q0 */ + +void powfp_odd2(Word16 base, /* Q15 */ + Word16 exp, /* Q0 */ + Word16 *pout1, /* Q15 */ + Word16 *pout2); /* Q15 */ + +void tcx_arith_scale_envelope( + Word16 L_spec_core, /* i: number of lines to scale Q0 */ + Word16 L_frame, /* i: number of lines Q0 */ + Word32 env[], /* i: unscaled envelope Q16 */ + Word16 target_bits, /* i: number of available bits Q0 */ + Word16 low_complexity, /* i: low-complexity flag Q0 */ + Word16 s_env[], /* o: scaled envelope Q15-e */ + Word16 *s_env_e /* o: scaled envelope exponent Q0 */ +); + +void tcx_arith_render_envelope( + const Word16 A_ind[], /* i: LPC coefficients of signal envelope */ + Word16 L_frame, /* i: number of spectral lines */ + Word16 L_spec, + Word16 preemph_fac, /* i: pre-emphasis factor */ + Word16 gamma_w, /* i: A_ind -> weighted envelope factor */ + Word16 gamma_uw, /* i: A_ind -> non-weighted envelope factor */ + Word32 env[] /* o: shaped signal envelope */ +); + +void tcx_get_gain(Word32 *x, /* i: spectrum 1 */ + Word16 x_e, /* i: spectrum 1 exponent */ + Word32 *y, /* i: spectrum 2 */ + Word16 y_e, /* i: spectrum 2 exponent */ + Word16 n, /* i: length */ + Word16 *gain, /* o: gain */ + Word16 *gain_e, /* o: gain exponent */ + Word32 *en_y, /* o: energy of y (optional) */ + Word16 *en_y_e /* o: energy of y exponent (optional) */ + ); + +void init_TCX_config(TCX_config *tcx_cfg, + Word16 L_frame, + Word16 fscale + ,Word16 L_frameTCX + ,Word16 fscaleFB + ); + +void tcx_arith_encode_envelope( + Word32 spectrum[], /* i/o: MDCT coefficients Q31-e */ + Word16 *spectrum_e, /* i/o: MDCT exponent Q0 */ + Word16 signs[], /* o: signs (spectrum[.]<0) Q0 */ + Word16 L_frame, /* i: frame or MDCT length Q0 */ + Word16 L_frame_orig, /* i: length w/o BW limitation Q0 */ + Encoder_State_fx *st, /* i/o: coder state */ + const Word16 A_ind[], /* i: quantised LPC coefficients Q12 */ + Word16 target_bits, /* i: number of available bits Q0 */ + Word16 prm[], /* o: bitstream parameters Q0 */ + Word8 use_hm, /* i: use HM in current frame? */ + Word16 prm_hm[], /* o: HM parameter area Q0 */ + Word16 tcxltp_pitch, /* i: TCX LTP pitch in FD, -1 if n/a Q0*/ + Word16 *arith_bits, /* o: bits used for ari. coding Q0 */ + Word16 *signaling_bits, /* o: bits used for signaling Q0 */ + Word16 *nf_seed /* o: noise filling seed Q0 */ + ,Word16 low_complexity /* i: low-complexity flag Q0 */ +); +void tcx_arith_decode_envelope( + Word32 q_spectrum[], /* o: quantised MDCT coefficients Q31-e */ + Word16 *q_spectrum_e, /* o: MDCT exponent Q0 */ + Word16 L_frame, /* i: frame or MDCT length */ + Word16 L_frame_orig, /* i: length w/o BW limitation */ + Decoder_State_fx *st, + const Word16 A_ind[], /* i: quantised LPC coefficients */ + Word16 target_bits, /* i: number of available bits */ + Word16 prm[], /* i: bitstream parameters */ + Word8 use_hm, /* i: use HM in current frame? */ + Word16 prm_hm[], /* i: HM parameter area */ + Word16 tcxltp_pitch, /* i: TCX LTP pitch in FD, -1 if n/a*/ + Word16 *arith_bits, /* o: bits used for ari. coding */ + Word16 *signaling_bits, /* o: bits used for signaling */ + Word16 *nf_seed /* o: noise filling seed Q0 */ + ,Word16 low_complexity /* i: low-complexity flag Q0 */ + +); + +# define GET_ADJ2(T,L,F) (((L) << (F)) - (T)) + +int tcx_hm_render( + Word32 lag, /* i: pitch lag Q0 */ + Word16 fract_res, /* i: fractional resolution of the lag Q0 */ + Word16 p[] /* o: harmonic model Q13 */ +); + +void tcx_hm_modify_envelope( + Word16 gain, /* i: HM gain Q11 */ + Word32 lag, /* i: pitch lag Q0 */ + Word16 fract_res, /* i: fractional resolution of the lag Q0 */ + Word16 p[], /* i: harmonic model Q13 */ + Word32 env[], /* i/o: envelope Q16 */ + Word16 L_frame /* i: number of spectral lines Q0 */ +); + +void UnmapIndex( + Word16 PeriodicityIndex, + Word16 Bandwidth, + Word16 LtpPitchLag, + Word8 SmallerLags, + Word16 *FractionalResolution, + Word32 *Lag); + +/* Returns: PeriodicityIndex */ +Word16 SearchPeriodicityIndex( + const Word32 Mdct[], /* (I) Coefficients, Mdct[0..NumCoeffs-1] */ + const Word32 UnfilteredMdct[], /* (I) Unfiltered coefficients, UnfilteredMdct[0..NumCoeffs-1] */ + Word16 NumCoeffs, /* (I) Number of coefficients */ + Word16 TargetBits, /* (I) Target bit budget (excl. Done flag) */ + Word16 LtpPitchLag, + Word16 LtpGain, /* (I) LTP gain */ + Word16 *RelativeScore /* (O) Energy concentration factor */ +); + +void ConfigureContextHm( + Word16 NumCoeffs, /* (I) Number of coefficients */ + Word16 TargetBits, /* (I) Target bit budget (excl. Done flag) */ + Word16 PeriodicityIndex, /* (I) Pitch related index */ + Word16 LtpPitchLag, /* (I) TCX-LTP pitch in F.D. */ + CONTEXT_HM_CONFIG *hm_cfg /* (O) Context-based harmonic model configuration */ +); + +Word16 EncodeIndex( + Word16 Bandwidth, /* 0: NB, 1: (S)WB */ + Word16 PeriodicityIndex, + Encoder_State_fx *st); + +Word16 CountIndexBits( + Word16 Bandwidth, /* 0: NB, 1: (S)WB */ + Word16 PeriodicityIndex); + +Word16 +DecodeIndex( + Decoder_State_fx *st, + Word16 Bandwidth, + Word16 *PeriodicityIndex); + + +void tcx_hm_analyse( + const Word32 abs_spectrum[], /* i: absolute spectrum Q31-e */ + Word16 *spectrum_e, /* i: absolute spectrum exponent Q0 */ + Word16 L_frame, /* i: number of spectral lines Q0 */ + Word32 env[], /* i/o: envelope shape Q16 */ + Word16 targetBits, /* i: target bit budget Q0 */ + Word16 coder_type, /* i: coder type Q0 */ + Word16 prm_hm[], /* o: HM parameters Q0 */ + Word16 LtpPitchLag, /* i: LTP pitch lag or -1 if none Q0 */ + Word16 LtpGain, /* i: LTP gain Q15 */ + Word16 *hm_bits /* o: bit consumption Q0 */ +); + +void tcx_hm_decode( + Word16 L_frame, /* i: number of spectral lines Q0 */ + Word32 env[], /* i/o: envelope shape Q16 */ + Word16 targetBits, /* i: target bit budget Q0 */ + Word16 coder_type, /* i: coder_type Q0 */ + Word16 prm_hm[], /* i: HM parameters Q0 */ + Word16 LtpPitchLag, /* i: LTP pitch lag or -1 if none Q0 */ + Word16 *hm_bits /* o: bit consumption Q0 */ +); + +void coder_tcx( + Word16 n, + TCX_config *tcx_cfg, /*input: configuration of TCX*/ + Word16 A[], /* input: quantized coefficients NxAz_q[M+1] */ + Word16 Aqind[], /* input: frame-independent quantized coefficients (M+1) */ + Word16 synth[], + Word16 L_frame_glob, /* input: frame length */ + Word16 L_frameTCX_glob, + Word16 L_spec, + Word16 nb_bits, /*input: bit budget*/ + Word8 tcxonly, /*input: only TCX flag*/ + Word32 spectrum[], /* i/o: MDCT spectrum */ + Word16 *spectrum_e, /* i/o: MDCT spectrum exponent */ + LPD_state *LPDmem, /*i/o: memories*/ + Word16 prm[], /* output: tcx parameters */ + Encoder_State_fx *st, + CONTEXT_HM_CONFIG *hm_cfg +); + +void coder_tcx_post(Encoder_State_fx *st, + LPD_state *LPDmem, + TCX_config *tcx_cfg, + Word16 *synth, + const Word16 *A, + const Word16 *Ai, + Word16 *wsig, + Word16 Q_new, + Word16 shift + ); + +void decoder_tcx( + TCX_config *tcx_cfg, /* input: configuration of TCX */ + Word16 prm[], /* input: parameters */ + Word16 A[], /* input: coefficients NxAz[M+1] */ + Word16 Aind[], /* input: frame-independent coefficients Az[M+1] */ + Word16 L_frame_glob, /* input: frame length */ + Word16 L_frameTCX, + Word16 L_spec, + Word16 synth[], /* in/out: synth[-M-LFAC..lg] */ + Word16 synthFB[], + Decoder_State_fx*st, + Word16 coder_type, /* input : coder type */ + Word16 bfi, /* input: Bad frame indicator */ + Word16 frame_cnt, /* input: frame counter in the super_frame */ + Word16 stab_fac /* input: stability of isf */ +); + +void decoder_tcx_post(Decoder_State_fx *st_fx, + Word16 *synth, + Word16 *synthFB, + Word16 *A, + Word16 bfi + ); + +/* cod_ace.c */ +Word16 coder_acelp( /* output SEGSNR for CL decision */ + ACELP_config *acelp_cfg, /*input/output: configuration of the ACELP coding*/ + const Word16 coder_type, /* input: coding type */ + const Word16 A[], /* input: coefficients 4xAz[M+1] */ + const Word16 Aq[], /* input: coefficients 4xAz_q[M+1] */ + Word16 speech[], /* input: speech[-M..lg] */ + Word16 synth[], + LPD_state *LPDmem, + const Word16 voicing[], /* input: open-loop LTP gain */ + const Word16 T_op[], /* input: open-loop LTP lag */ + Word16 *prm, /* output: acelp parameters */ + Word16 stab_fac, + Encoder_State_fx *st, + HANDLE_PLC_ENC_EVS hPlc_Ext, + Word16 target_bits, /* i/o : coder memory state */ + Word16 Q_new, + Word16 shift, + Word16 *pitch_buf, /* output : pitch values for each subfr.*/ + Word16 *voice_factors, /* output : voicing factors */ + Word16 *bwe_exc /* output : excitation for SWB TBE */ +); + + +void decoder_acelp( + Decoder_State_fx *st, + Word16 coder_type, /* input: coder type */ + Word16 prm[], /* input: parameters */ + Word16 A[], /* input: coefficients NxAz[M+1] */ + ACELP_config acelp_cfg, /* input: ACELP config */ + Word16 synth[], /* i/o: synth[-2*LFAC..L_DIV] Q0 */ + Word16 *pT, /* out: pitch for all subframe Q0 */ + Word16 *pgainT, /* out: pitch gain for all subfr 1Q14 */ + Word16 stab_fac, /* input: stability of isf */ + Word16 *pitch_buffer, /* out: pitch values for each subfr.*/ + Word16 *voice_factors, /* out: voicing factors */ + const Word16 LSF_Q_prediction,/* i : LSF prediction mode */ + Word16 *bwe_exc /* out: excitation for SWB TBE */ +); + +void enc_prm( + const Word16 coder_type, /* (i) : coding type */ + Word16 param[], /* (i) : parameters */ + Word16 param_lpc[], /* (i) : LPC parameters */ + Encoder_State_fx *st, /* io: quantization Analysis values */ + Word16 L_Frame, + CONTEXT_HM_CONFIG hm_cfg[], + Word16 * bits_param_lpc, + Word16 no_param_lpc +); + +void enc_prm_rf( + Encoder_State_fx *st, + const Word16 rf_frame_type, + const Word16 fec_offset +); + +void dec_prm( + Word16 *coder_type, + Word16 param[], /* (o) : decoded parameters */ + Word16 param_lpc[], /* (o) : LPC parameters */ + Word16 *total_nbbits, /* i/o : number of bits / decoded bits */ + Decoder_State_fx *st, + Word16 L_frame, + Word16 *bitsRead +); + +void dec_prm_core( + Decoder_State_fx *st +); + +void analy_sp( /* o: fft0 bin energy Q0 */ + Word16 *speech, /* i: speech buffer Q_new - preemph_bits */ + const Word16 Q_new, /* i: current scaling exp Q0 */ + Word32 *fr_bands, /* o: energy in critical frequency bands Q_new + QSCALE */ + Word32 *lf_E, /* o: per bin E for first... Q_new + QSCALE - 2*/ + Word16 *Etot, /* o: total input energy Q8 */ + const Word16 min_band, /* i: minimum critical band Q0 */ + const Word16 max_band, /* i: maximum critical band Q0 */ + const Word32 e_min_scaled, /* i: minimum energy scaled Q_new + QSCALE */ + Word16 Scale_fac[2], /* o: FFT scales factors (2 values by frame) Q0 */ + Word32 *Bin_E, /* o : per bin log energy spectrum */ + Word32 *Bin_E_old, /* o : per bin log energy spectrum for mid-frame */ + Word32 *PS, /* o : Per bin energy spectrum */ + Word16 *EspecdB, /* o : log E spectrum (with f=0) of the current frame Q7 */ + Word32 *band_energies, /* o : energy in critical frequency bands without minimum noise floor MODE2_E_MIN */ + Word16 *fft_buff /* o : FFT coefficients */ +); + +void E_UTIL_copy_scale_sig( + const Word16 x[], /* i : signal to scale input Qx */ + Word16 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx xx exp */ +); + +void scale_sig32( + Word32 x[], /* i/o: signal to scale Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx xx exp */ +); + + +Word32 scale_mem( /* o : Min energy scaled */ + Word16 ini_frames, /* i : Frame number */ + Word16 Q_exp, /* i : Diff scaling factor */ + Word16 *Q_new, /* i/o: Absolute scaling factor */ + Word16 *old_speech, /* i/o: Speech memory */ + Word16 *old_speech_ns, /* i/o: Speech denoised memory */ + Word16 *mem_wsp, /* i/o: wsp vector memory */ + Word32 *enrO, /* i/o: Enr mem */ + Word32 *bckr, /* i/o: Back ground_fx ener mem */ + Word32 *lf_EO, /* i/o: Energy per low freq bin mem */ + Word32 *ave_enr, /* i/o: Ave_enr mem */ + Word32 *st_fr_bands1, /* i/o: spectrum per critical bands of the previous frame */ + Word32 *st_fr_bands2, /* i/o: spectrum per critical bands 2 frames ago */ + Word32 *ave_enr2 /* i/o: LT average E per crit. band (for non_sta2) Q_new + QSCALE */ +); + +Word16 rescale_exc( + Word16 exc[], /* i/o: excitation to rescale Q_exc */ + Word16 lg, /* i : frame size */ + Word32 L_gain_code, /* i : decoded codebook gain Q16 */ + Word16 *sQ_exc, /* i/o: Excitation scaling factor */ + Word16 *sQsubfr, /* i/o: Past excitation scaling factors */ + Word16 exc2[], /* o : local excitation vector */ + Word16 i_subfr /* i : subframe number */ +); + +Word16 rescale_mem( + const Word16 *Q_exc, /* i : current excitation scaling (>=0) */ + Word16 *prev_Q_syn, /* i/o : scaling factor of previous frame */ + Word16 *Q_syn, /* i/o : scaling factor of frame */ + Word16 *mem_syn2, /* i/o : modified synthesis memory */ + Word16 *syn, /* i/o : synthesis to rescale Q_syn */ + Word16 mem_len, /* i : lenght of modified synthesis memory */ + Word16 i_subfr /* i : subframe number */ +); + +void gauss_L2( + const Word16 h[], /* i : weighted LP filter impulse response Q14+s */ + Word16 code2[], /* o : gaussian excitation Q9 */ + const Word16 y2[], /* i : zero-memory filtered code. excitation Q9 */ + Word16 y11[], /* o : zero-memory filtered gauss. excitation Q9 */ + Word32 *gain, /* o : excitation gain */ + ACELP_CbkCorr *g_corr, /*i/o : correlation structure for gain coding */ + const Word16 gain_pit, /* i : unquantized gain of code */ + const Word16 tilt_code, /* i : tilt of code Q15 */ + const Word16 *Aq, /* i : quantized LPCs Q12 */ + const Word16 formant_enh, /* i : formant enhancement factor Q15 */ + Word16 *seed_acelp, /*i/o : random seed Q0 */ + const Word16 shift +); + +void gaus_L2_dec( + Word16 *code, /* o : decoded gaussian codevector Q9 */ + Word16 tilt_code, /* i : tilt of code Q15 */ + const Word16 *A, /* i : quantized LPCs Q12 */ + Word16 formant_enh, /* i : formant enhancement factor Q15 */ + Word16 *seed_acelp /*i/o : random seed Q0 */ +); + +void tcx_ltp_get_lpc( + Word16 *x, + Word16 L, + Word16 *A, + Word16 order +); + +void predict_signal( + const Word16 excI[], /* i : input excitation buffer */ + Word16 excO[], /* o : output excitation buffer */ + const Word16 T0, /* i : integer pitch lag */ + Word16 frac, /* i : fraction of lag */ + const Word16 frac_max, /* i : max fraction */ + const Word16 L_subfr /* i : subframe size */ +); + +void tcx_ltp_pitch_search( + Word16 pitch_ol, + Word16 *pitch_int, + Word16 *pitch_fr, + Word16 *index, + Word16 *norm_corr, + const Word16 len, + Word16 *wsp, + Word16 pitmin, + Word16 pitfr1, + Word16 pitfr2, + Word16 pitmax, + Word16 pitres +); + +void tcx_ltp_encode( Word8 tcxltp_on, + Word8 tcxOnly, + Word16 tcxMode, + Word16 L_frame, + Word16 L_subfr, + Word16 *speech, + Word16 *speech_ltp, + Word16 *wsp, + Word16 Top, + Word16 *ltp_param, + Word16 *ltp_bits, + Word16 *pitch_int, + Word16 *pitch_fr, + Word16 *gain, + Word16 *pitch_int_past, + Word16 *pitch_fr_past, + Word16 *gain_past, + Word16 *norm_corr_past, + Word16 last_core, + Word16 pitmin, + Word16 pitfr1, + Word16 pitfr2, + Word16 pitmax, + Word16 pitres, + struct TransientDetection const * pTransientDetection, + Word8 SideInfoOnly, + Word16 *A, + Word16 lpcorder + ); + +void tcx_ltp_post( Word8 tcxltp_on, + Word16 core, + Word16 L_frame, + Word16 L_frame_core, + Word16 delay, + Word16 *sig, + Word16 *tcx_buf, + Word16 tcx_buf_len, + Word16 bfi, + Word16 pitch_int, + Word16 pitch_fr, + Word16 gain, + Word16 *pitch_int_past, + Word16 *pitch_fr_past, + Word16 *gain_past, + Word16 *filtIdx_past, + Word16 pitres, + Word16 *pitres_past, + Word16 damping, + Word16 SideInfoOnly, + Word16 *mem_in, + Word16 *mem_out, + Word32 bitrate + ); + +Word16 tcx_ltp_decode_params( Word16 *ltp_param, + Word16 *pitch_int, + Word16 *pitch_fr, + Word16 *gain, + Word16 pitmin, + Word16 pitfr1, + Word16 pitfr2, + Word16 pitmax, + Word16 pitres + ); + +/*isf_msvq_ma.c, lsf_msvq_ma.c*/ +void msvq_enc +( + const Word16 *const*cb, /* i : Codebook (indexed cb[*stages][levels][p]) (0Q15) */ + const Word16 dims[], /* i : Dimension of each codebook stage (NULL: full dim.) */ + const Word16 offs[], /* i : Starting dimension of each codebook stage (NULL: 0) */ + const Word16 u[], /* i : Vector to be encoded (prediction and mean removed)(14Q1*1.28) */ + const Word16 *levels, /* i : Number of levels in each stage */ + const Word16 maxC, /* i : Tree search size (number of candidates kept from */ + /* one stage to the next == M-best) */ + const Word16 stages, /* i : Number of stages */ + const Word16 w[], /* i : Weights Q8 */ + const Word16 N, /* i : Vector dimension */ + const Word16 maxN, /* i : Codebook dimension */ + Word16 Idx[] /* o : Indices */ +); +void msvq_dec +( + const Word16 *const*cb, /* i : Codebook (indexed cb[*stages][levels][p]) (0Q15) */ + const Word16 dims[], /* i : Dimension of each codebook stage (NULL: full dim.) */ + const Word16 offs[], /* i : Starting dimension of each codebook stage (NULL: 0) */ + const Word16 stages, /* i : Number of stages */ + const Word16 N, /* i : Vector dimension */ + const Word16 maxN, /* i : Codebook dimension */ + const Word16 Idx[], /* i : Indices */ + Word16 *uq /* o : quantized vector (3Q12) */ +); + + +/*------------------------------------------------------------------------- +* Recovery tools for resynchronization +*------------------------------------------------------------------------*/ +/*er_sync_exc.c*/ +/** Resynchronize glotal pulse positions of the signal in src_exc and store it in dst_exc. + * src_exc holds on call the harmonic part of the signal with the constant pitch, constructed by repeating the last pitch cycle of length pitchStart. + * dst_exc holds on return the harmonic part of the signal with the pitch changing from pitchStart to pitchEnd. + * src_exc and dst_exc can overlap, but src_exc < dst_exc must be fullfiled. + * @param src_exc Input excitation buffer. + * @param dst_exc Output excitation buffer. + * @param nFrameLength Length of the frame, that is the length of the valid data in the excitation buffer on return. + * @param nSubframes Number of subframes in the excitation buffer. nFrameLength must be divisible by nSubframes. + * @param pitchStart Pitch at the end of the last frame. + * @param pitchEnd Pitch at the end of the current frame. + */ +void PulseResynchronization( + Word16 /*float*/ const * const src_exc, /*i Q15*/ + Word16 /*float*/ * const dst_exc, /*o Q15*/ + Word16 /*int*/ const nFrameLength, /*i Q0 */ + Word16 /*int*/ const nSubframes, /*i Q0 */ + Word32 /*float*/ const pitchStart, /*i Q16*/ + Word32 /*float*/ const pitchEnd /*i Q16*/ +); + +/* er_util.c*/ +/* PLC: [TCX: TD PLC] + * PLC: FindSubframePitchInTCX: function to find the pitch per half a frame for the last TCX */ +/*VERSIONINFO: This port is up to date with trunk rev. 30479*/ +/*VERSIONINFO: This port is up to date with trunk rev. 7611*/ + +void con_acelp( + const Word16 A[], /*mem_syn >rescaling done */ + , Word16 *pitch_buffer + , Word16 *voice_factors + , Word16 *bwe_exc +); + +void con_tcx( + Decoder_State_fx *st, /* i/o: coder memory state */ + Word16 /*float*/ synth[] /* i/o: synth[] *//*Q0 */ +); + + +/* isf_msvq_ma.c */ +void isf_msvq_ma_enc(const Word16 *isf, /* i: isf coefficients (3Q12) */ + Word16 *isfq, /* o: quantized isf */ + Word16 *isfq_ind, + Word16 *indices, /* o: quantizer indices */ + Word16 *nb_indices, /* o: number of bits for the indices */ + Word16 *mem_MA, /* i/o: moving average filter buffer (3Q12) */ + Word16 *parcorr, + const Word16 m, /* i: lpc order */ + const Word16 acelp_mode, /* i: acelp mode */ + const Word8 narrow_band /* i: narrow-band flag */ + ); +void isf_msvq_ma_dec( Word16 *isfq, + Word16 *isfq_ind, + Word16 *indices, + Word16 *nb_indices, + Word16 *mem_MA, + Word16 m, + Word16 acelp_mode, + Word8 narrow_band /* i: narrow-band flag */ + ); +Word16 isf_msvq_ma_encprm( Encoder_State_fx *st, Word16 *param_lpc, Word16 core, Word16 acelp_mode, Word16 acelp_midLpc, Word16 m ); +Word16 isf_msvq_ma_decprm( Decoder_State_fx *st, Word16 *param_lpc, Word16 core, Word16 acelp_mode, Word16 acelp_midLpc, Word16 m ); + +/* Returns: non-zero on conversion error, 0 otherwise */ +Word16 E_LPC_lsp_unweight( + /* const */ Word16 xsp_w[], /* (I): weighted xSP */ + Word16 xsp_uw[], /* (O): unweighted xSP */ + Word16 xsf_uw[], /* (O): unweighted xSF */ + Word16 inv_gamma, /* (I): inverse weighting factor */ + Word16 lpcorder /* (I): prediction order */ +); + +Word16 lsf_ind_is_active( + const Word16 lsf_q_ind[], + const Word16 means[], + Word16 bandwidth, + Word16 cdk); + +void lsf_update_memory( + Word16 narrowband, /* i : narrowband flag */ + const Word16 qisf[], /* i : quantized xSF coefficients */ + Word16 old_mem_MA[], /* i : MA memory */ + Word16 mem_MA[], /* o : updated MA memory */ + Word16 lpcorder /* i : LPC order */ +); + +/* Returns: number of indices */ +Word16 Q_lsf_tcxlpc( + /* const */ Word16 xsf[], /* (I) original xSF */ + Word16 xsf_q[], /* (O) quantized xSF */ + Word16 xsf_q_ind[], /* (O) quantized xSF (w/o MA prediction) */ + Word16 indices[], /* (O) VQ indices */ + Word16 lpcorder, /* (I) LPC order */ + Word16 narrowband, /* (I) narrowband flag */ + Word16 cdk, /* (I) codebook selector */ + Word16 mem_MA[], /* (I) MA memory */ + Word16 coder_type, + Word32 * Bin_Ener, + const Word16 Q_ener +); + +/* Returns: number of indices */ +Word16 D_lsf_tcxlpc( + const Word16 indices[], /* (I) VQ indices */ + Word16 xsf_q[], /* (O) quantized xSF */ + Word16 xsf_q_ind[], /* (O) quantized xSF (w/o MA prediction) */ + Word16 narrowband, /* (I) narrowband flag */ + Word16 cdk, /* (I) codebook selector */ + Word16 mem_MA[] /* (I) MA memory */ +); + +/* Returns: number of bits written */ +Word16 enc_lsf_tcxlpc( + Word16 **indices, /* (I) Ptr to VQ indices */ + Encoder_State_fx *st /* (I/O) Encoder state */ +); + +/* Returns: number of bits read */ +Word16 dec_lsf_tcxlpc( + Decoder_State_fx *st, /* (I/O) Decoder state */ + Word16 **indices, /* (O) Ptr to VQ indices */ + Word16 narrowband, /* (I) narrowband flag */ + Word16 cdk /* (I) codebook selector */ +); + +/* Returns: codebook index */ +Word16 tcxlpc_get_cdk( + Word16 coder_type /* (I) VOICED indicator */ +); + +/* lsf_msvq_ma.c */ +void lsf_msvq_ma_enc( + const Word16 *lsf, /* i: lsf coefficients (14Q1*1.28)*/ + Word16 *lsfq, /* o: quantized lsf */ + Word16 *lsfq_ind, + Word32 * Bin_Ener_128_fx, + const Word16 Q_ener, + Word16 *indices, /* o: quantizer indices */ + Word16 *nb_indices, /* o: number of bits for the indices */ + Word16 *mem_MA, /* i/o: moving average filter buffer (3Q12*1.28)*/ + const Word16 m, /* i: lpc order */ + const Word16 acelp_mode /* i: acelp mode */ +); + +void lsf_msvq_ma_dec( Word16 *lsfq, + Word16 *lsfq_ind, + Word16 *indices, + Word16 *nb_indices, + Word16 *mem_MA, + Word16 m, + Word16 acelp_mode + ); + +Word16 lsf_msvq_ma_encprm( Encoder_State_fx * st, + Word16 *param_lpc, + Word16 core, + Word16 acelp_mode, + Word16 acelp_midLpc, + Word16 * bits_param_lpc, + Word16 no_indices + ); +Word16 lsf_msvq_ma_decprm( Decoder_State_fx *st, Word16 *param_lpc, Word16 core, Word16 acelp_mode, Word16 acelp_midLpc + ,Word16 narrowBand + ,Word32 sr_core + ); + +Word16 lsf_bctcvq_encprm( + Encoder_State_fx *st, + Word16 *param_lpc, + Word16 * bits_param_lpc, + Word16 no_indices +); + +Word16 lsf_bctcvq_decprm( + Decoder_State_fx * st, + Word16 *param_lpc +); +void lpc_unquantize( + Decoder_State_fx * st, + Word16 *lsfold, + Word16 *lspold, + Word16 *lsf, + Word16 *lsp, + const Word16 m, + const Word16 lpcQuantization, + Word16 *param_lpc, + const Word16 numlpc, + const Word16 core, + Word16 *mem_MA, + Word16 *mem_AR, + Word16 *lspmid, + Word16 *lsfmid, + Word16 coder_type, + Word16 acelp_midLpc, + Word8 narrow_band, + Word16 *seed_acelp, + Word32 sr_core, + Word16 *mid_lsf_int, + Word16 prev_bfi, + Word16 *LSF_Q_prediction, /* o : LSF prediction mode */ + Word16 *safety_net +); + +void midlsf_enc(const Word16 qlsf0[], /* i: quantized lsf coefficients (3Q12) */ + const Word16 qlsf1[], /* i: quantized lsf coefficients (3Q12) */ + const Word16 lsf[], /* i: lsf coefficients (3Q12) */ + Word16 *idx, /* o: codebook index */ + const Word16 lpcorder /* i: order of the lpc */ + , Word32 * Bin_Ener_128_fx + ,const Word16 Q_ener + ,Word8 narrowBand + ,Word32 sr_core + ,Word16 coder_type + ); + + +void midlsf_dec( + const Word16 qlsf0[], /* i: quantized lsf coefficients (3Q12) */ + const Word16 qlsf1[], /* i: quantized lsf coefficients (3Q12) */ + Word16 idx, /* i: codebook index */ + Word16 qlsf[], /* o: decoded lsf coefficients (3Q12) */ + Word16 coder_type, + Word16 *mid_lsf_int, + Word16 prev_bfi, + Word16 safety_net); + + +Word16 const * PlcGetLsfBase (Word16 const lpcQuantization, + Word16 const narrowBand, + Word32 const sr_core); + +/* tcx_mdct.h */ +#define MDCT_A_E 1 + +#define TCX_IMDCT_SCALE 15 +#define TCX_IMDCT_HEADROOM 1 + +void TCX_MDCT(const Word16 *x, Word32 *y, Word16 *y_e, Word16 l, Word16 m, Word16 r); + +void TCX_MDST(const Word16 *x, Word32 *y, Word16 *y_e, Word16 l, Word16 m, Word16 r); + +void TCX_MDCT_Inverse(Word32 *x, Word16 x_e, Word16 *y, Word16 l, Word16 m, Word16 r); + + +/* post_dec.h */ +void post_decoder( + Decoder_State_fx *st, + Word16 coder_type, + Word16 synth_buf[], + Word16 pit_gain[], + Word16 pitch[], + Word16 signal_out[], + Word16 * bpf_noise_buf +); + +Word16 bass_pf_enc( + Word16 *orig, /* (i) : 12.8kHz original signal Q0 */ + Word16 *syn, /* (i) : 12.8kHz synthesis to postfilter Q0 */ + Word16 *T_sf, /* (i) : Pitch period for all subframes (T_sf[16]) Q0 */ + Word16 *gainT_sf, /* (i) : Pitch gain for all subframes (gainT_sf[16]) Q14 */ + Word16 l_frame, /* (i) : frame length (should be multiple of l_subfr) Q0 */ + Word16 l_subfr, /* (i) : sub-frame length (60/64) Q0 */ + Word16 *gain_factor_param, /* (o) : quantized gain factor Q0 */ + Word16 mode, /* (i) : coding mode of adapt bpf */ + struct MEM_BPF *mem_bpf /* i/o : memory state */ +); +void cldfb_synth_set_bandsToZero( + Decoder_State_fx *st, + Word32 **rAnalysis, + Word32 **iAnalysis, + const Word16 nTimeSlots, + const CLDFB_SCALE_FACTOR scaleFactor +); +/* fd_cng_common.h */ +/* Create an instance of type FD_CNG */ +void createFdCngCom(HANDLE_FD_CNG_COM* hFdCngCom); + +void initFdCngCom(HANDLE_FD_CNG_COM hFdCngCom, Word16 scale); + +/* Delete the instance of type FD_CNG */ +void deleteFdCngCom(HANDLE_FD_CNG_COM * hFdCngCom); + +void resetFdCngEnc( Encoder_State_fx * st); + +/* Initialize the spectral partitioning */ +void initPartitions( const Word16* part_in, + Word16 npart_in, + Word16 startBand, + Word16 stopBand, + Word16* part_out, + Word16* npart_out, + Word16* midband, + Word16* psize, + Word16* psize_norm, + Word16* psize_norm_exp, + Word16* psize_inv, + Word16 stopBandFR); + +/* Noise estimation using Minimum Statistics (MS) */ +void compress_range(Word32 *in, + Word16 in_exp, + Word16 *out, + Word16 len + ); + +void expand_range(Word16 *in, + Word32 *out, + Word16 *out_exp, + Word16 len + ); + +void minimum_statistics(Word16 len, /* i : Total number of partitions (CLDFB or FFT) */ + Word16 lenFFT, /* i : Number of FFT partitions */ + Word16 *psize, /* i : Partition sizes, fractional */ + Word16 *msPeriodog, /* i : Periodogram (energies) */ + Word16 *msNoiseFloor, /* i/o: Noise floors (energies) */ + Word16 *msNoiseEst, /* i/o: Noise estimates (energies) */ + Word32 *msAlpha, /* i/o: Forgetting factors */ + Word16 *msPsd, /* i/o: Power Spectral Density (smoothed periodogram => energies) */ + Word16 *msPsdFirstMoment, /* i/o: PSD statistics of 1st order (energy means) */ + Word32 *msPsdSecondMoment, /* i/o: PSD statistics of 2nd order (energy variances) */ + Word32 *msMinBuf, /* i/o: Buffer of minima (energies) */ + Word32 *msBminWin, /* o : Bias correction factors */ + Word32 *msBminSubWin, /* o : Bias correction factors */ + Word32 *msCurrentMin, /* i/o: Local minima (energies) */ + Word32 *msCurrentMinOut, /* i/o: Local minima (energies) */ + Word32 *msCurrentMinSubWindow, /* i/o: Local minima (energies) */ + Word16 *msLocalMinFlag, /* i : Binary flag */ + Word16 *msNewMinFlag, /* i : Binary flag */ + Word16 *msPeriodogBuf, /* i/o: Buffer of periodograms (energies) */ + Word16 *msPeriodogBufPtr, /* i/o: Counter */ + HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing buffers and variables */ + ); + +/* Generate the comfort noise based on the target noise level */ +void generate_comfort_noise_enc (Encoder_State_fx *stcod, + Word16 Q_new, + Word16 gen_exc + ); +void generate_comfort_noise_dec (Word32 **bufferReal, /* o : matrix to real part of input bands */ + Word32 **bufferImag, /* o : matrix to imaginary part of input bands */ + Word16 *bufferScale, /* o : pointer to scalefactor for real and imaginary part of input bands */ + Decoder_State_fx *stdec, + Word16 *Q_new, + Word16 gen_exc + ); +void +generate_comfort_noise_dec_hf (Word32 **bufferReal, /* o : matrix to real part of input bands */ + Word32 **bufferImag, /* o : matrix to imaginary part of input bands */ + Word16 *bufferScale, /* o : pointer to scalefactor for real and imaginary part of input bands */ + Decoder_State_fx *stdec + ); + +/* Generate the comfort noise based on the target noise level */ +void generate_masking_noise (Word16 *timeDomainBuffer, /* i/o: time-domain signal */ + Word16 Q, + HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing all buffers and variables */ + ,Word16 length + ,Word16 core + ); + +void generate_masking_noise_update_seed ( + HANDLE_FD_CNG_COM st /* i/o : pointer to FD_CNG_COM structure */ +); + +void generate_masking_noise_mdct (Word32 *mdctBuffer, /* i/o: time-domain signal */ + Word16 *mdctBuffer_e, /* i/o: exponent time-domain signal */ + HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing all buffers and variables */ + ,Word16 L_frame + ); + +/* Apply bitrate-dependant scale */ +void apply_scale(Word32 *scale, + Word16 bwmode, + Word32 bitrate + ); + +/* Compute the power for each partition */ +void bandcombinepow(Word32* bandpow, /* i : Power for each band */ + Word16 exp_bandpow, /* i : exponent of bandpow */ + Word16 nband, /* i : Number of bands */ + Word16* part, /* i : Partition upper boundaries (band indices starting from 0) */ + Word16 npart, /* i : Number of partitions */ + Word16* psize_inv, /* i : Inverse partition sizes */ + Word32* partpow, /* o : Power for each partition */ + Word16* exp_partpow + ); + +/* Scale partitions (with smoothing) */ +void scalebands (Word32 *partpow, /* i : Power for each partition */ + Word16 *part, /* i : Partition upper boundaries (band indices starting from 0) */ + Word16 npart, /* i : Number of partitions */ + Word16 *midband, /* i : Central band of each partition */ + Word16 nFFTpart, /* i : Number of FFT partitions */ + Word16 nband, /* i : Number of bands */ + Word32 *bandpow, /* o : Power for each band */ + Word16 flag_fft_en + ); + +/* Get central band for each partition */ +void getmidbands(Word16* part, /* i : Partition upper boundaries (band indices starting from 0) */ + Word16 npart, /* i : Number of partitions */ + Word16* midband, /* o : Central band of each partition */ + Word16* psize, /* o : Partition sizes */ + Word16* psize_norm, /* o : Partition sizes, fractional values */ + Word16* psize_norm_exp, /* o : Exponent for fractional partition sizes */ + Word16* psize_inv /* o : Inverse of partition sizes */ + ); + +/* STFT analysis filterbank */ +void AnalysisSTFT (const Word16 *timeDomainInput, /* i : pointer to time signal */ + Word16 Q, + Word32 *fftBuffer, /* o : FFT bins */ + Word16 *fftBuffer_exp, /* i : exponent of FFT bins */ + HANDLE_FD_CNG_COM st /* i/o: FD_CNG structure containing all buffers and variables */ + ); + +/* STFT synthesis filterbank */ +void SynthesisSTFT (Word32 *fftBuffer, /* i : pointer to FFT bins */ + Word16 fftBufferExp, /* i : exponent of FFT bins */ + Word16 *timeDomainOutput, /* o : pointer to time domain signal */ + Word16 *olapBuffer, /* i/o : pointer to overlap buffer */ + const PWord16 *olapWin, /* i : pointer to overlap window */ + Word16 tcx_transition, + HANDLE_FD_CNG_COM st, /* i/o : pointer to FD_CNG structure containing all buffers and variables */ + Word16 gen_exc, + Word16 *Q_new + ); + +/* Compute some calues used in the bias correction of the minimum statistics algorithm */ +void mhvals(Word16 d, Word16 * m/*, float * h*/); + +/* Random generator with Gaussian distribution with mean 0 and std 1 */ +Word32 rand_gauss (Word16 *seed); + +void lpc_from_spectrum (Word32 *powspec, + Word16 powspec_exp, + Word16 start, + Word16 stop, + Word16 fftlen, + Word16 *A, + Word16 lpcorder, + Word16 preemph_fac); + +void msvq_decoder(const Word16 *const cb[], /* i : Codebook (indexed cb[*stages][levels][p]) */ + Word16 stages, /* i : Number of stages */ + Word16 N, /* i : Vector dimension */ + Word16 maxN, /* i : Codebook vector dimension */ + Word16 Idx[], /* i : Indices */ + Word16 *uq /* o : quantized vector */ + ); + +/*fd_cng_dec.h*/ +/* Create an instance of type FD_CNG */ +void createFdCngDec(HANDLE_FD_CNG_DEC* hFdCngDec); + +Word16 initFdCngDec(HANDLE_FD_CNG_DEC hFdCngDec, Word16 scale); +extern void E_LPC_isf_isp_conversion(const Word16 isf[], Word16 isp[], const Word16 m); +extern void E_LPC_f_isp_a_conversion(const Word16 *isp, Word16 *a, const Word16 m); + +/* Delete the instance of type FD_CNG */ +void deleteFdCngDec(HANDLE_FD_CNG_DEC * hFdCngDec); + +/* Configure CLDFB-CNG */ +void configureFdCngDec(HANDLE_FD_CNG_DEC hs, /* i/o: Contains the variables related to the CLDFB-based CNG process */ + Word16 bandwidth, + Word32 bitrate, + Word16 cng_type); + + +/* Apply the CLDFB-based CNG */ +Word16 ApplyFdCng (Word16 * timeDomainInput, /* i : pointer to time domain input */ + Word16 Q, + Word32 ** cldfbBufferReal, /* i/o: real part of the CLDFB buffer */ + Word32 ** cldfbBufferImag, /* i/o: imaginary part of the CLDFB buffer */ + Word16 * cldfbBufferScale, /* o : pointer to the scalefactor for real and imaginary part of the CLDFB buffer */ + HANDLE_FD_CNG_DEC st, /* i/o: pointer to FD_CNG structure containing all buffers and variables */ + Word16 m_frame_type, /* i : type of frame at the decoder side */ + Decoder_State_fx *stdec, + const Word16 concealWholeFrame, /* i : binary flag indicating frame loss */ + Word16 is_music + ); + +/* Perform noise estimation */ +void perform_noise_estimation_dec(const Word16 *timeDomainInput, /* i: pointer to time domain input */ + Word16 Q, + HANDLE_FD_CNG_DEC st /* i/o: FD_CNG structure containing all buffers and variables */ + ); + +/* Decode the CLDFB-CNG bitstream */ +void FdCng_decodeSID(HANDLE_FD_CNG_COM st, /* i/o: FD_CNG structure containing all buffers and variables */ + Decoder_State_fx *corest); /* i/o: decoder state structure */ + +void FdCng_exc( + HANDLE_FD_CNG_COM hs, + Word16 *CNG_mode, + Word16 L_frame, + Word16 *lsp_old, + Word16 first_CNG, + Word16 *lsp_CNG, + Word16 *Aq, /* o: LPC coeffs */ + Word16 *lsp_new, /* o: lsp */ + Word16 *lsf_new, /* o: lsf */ + Word16 *exc, /* o: LP excitation */ + Word16 *exc2, /* o: LP excitation */ + Word16 *bwe_exc /* o: LP excitation for BWE */ +); + +void noisy_speech_detection( + const Word16 vad, + const Word16 *ftimeInPtr, /* i : input time-domain frame */ + const Word16 frameSize, /* i : frame size */ + const Word16 Q, + const Word32 *msNoiseEst, /* i : noise estimate over all critical bands */ + const Word16 msNoiseEst_exp, /* i : exponent for noise estimate over all critical bands */ + const Word16 *psize_norm, + const Word16 psize_norm_exp, + const Word16 nFFTpart, /* i : Number of partitions taken into account */ + Word32 *lp_noise, /* i/o: pointer to long term total Noise energy average */ + Word32 *lp_speech, /* i/o: pointer to long term active speech energy average */ + Word16 *flag_noisy_speech +); + +/* Create an instance of type FD_CNG */ +void createFdCngEnc(HANDLE_FD_CNG_ENC* hFdCngEnc); + +void initFdCngEnc(HANDLE_FD_CNG_ENC hsEnc, Word32 input_Fs, Word16 scale); + +/* Delete the instance of type FD_CNG */ +void deleteFdCngEnc(HANDLE_FD_CNG_ENC * hFdCngEnc); + +/* Configure CLDFB-CNG */ +void configureFdCngEnc(HANDLE_FD_CNG_ENC hs, /* i/o: Contains the variables related to the CLDFB-based CNG process */ + Word16 bandwidth, /* i: bandwidth */ + Word32 bitrate); + +/* Perform noise estimation */ +void perform_noise_estimation_enc( + Word32 *band_energies, /* i: energy in critical bands without minimum noise floor MODE2_E_MIN */ + Word16 exp_band_energies, + Word32 *enerBuffer, + Word16 enerBuffer_exp, + HANDLE_FD_CNG_ENC st); /* i/o: FD_CNG structure containing all buffers and variables */ + +/* Adjust the noise estimator at the beginning of each CNG phase (encoder-side) */ +Word16 +AdjustFirstSID(Word16 npart, + Word32 *msPeriodog, + Word16 msPeriodog_exp, + Word32 *energy_ho, + Word16 *energy_ho_exp, + Word32 *msNoiseEst, + Word16 *msNoiseEst_exp, + Word32 *msNoiseEst_old, + Word16 *msNoiseEst_old_exp, + Word16 *active_frame_counter, + Encoder_State_fx *stcod + ); + +/* Generate a bitstream out of the partition levels */ +void FdCng_encodeSID (HANDLE_FD_CNG_ENC st, /* i/o: FD_CNG structure containing all buffers and variables */ + Encoder_State_fx *corest, + Word16 preemph_fac /* i : preemphase factor */ + ); + +/*parameter_bitmaping.h*/ +/** Writes parameters from paramsBitMap into a stream. + * @param paramsBitMap Definition of parameters and mappings to a bitstream. + * @param nParam Size of paramsBitMap. + * @param pParameter A parameter to be used in get and set functions from paramsBitMap. + * @param pStream Pointer to a stream where parameters should be stored. + * @param pnSize Set to the number of elements written to the stream. + * @param pnBits Set to the number of required bits. + */ +void GetParameters(ParamsBitMap const * paramsBitMap, Word16 nParams, void const * pParameter, Word16 ** pStream, Word16 * pnSize, Word16 * pnBits); + +/** Reads parameters from a stream into paramsBitMap. + * @param paramsBitMap Definition of parameters and mappings to a bitstream. + * @param nParam Size of paramsBitMap. + * @param pParameter A parameter to be used in get and set functions from paramsBitMap. + * @param pStream Pointer to a stream from which parameters are read. + * @param pnSize Set to the number of elements read from the stream. + */ +void SetParameters(ParamsBitMap const * paramsBitMap, Word16 nParams, void * pParameter, Word16 const ** pStream, Word16 * pnSize); + +/** Writes parameters from a stream into a bitstream. + * @param paramsBitMap Definition of parameters and mappings to a bitstream. + * @param nParam Size of paramsBitMap. + * @param pStream Pointer to a stream from which parameters are read. + * @param pnSize Set to the number of elements read from the stream. + * @param st Encoder state. + * @param pnBits Set to the number of bits written. + */ +void WriteToBitstream(ParamsBitMap const * paramsBitMap, Word16 nParams, Word16 const ** pStream, Word16 * pnSize, Encoder_State_fx *st, Word16 * pnBits); + +/** Reads parameters from a bitstream into a stream. + * @param paramsBitMap Definition of parameters and mappings to a bitstream. + * @param nArrayLength Size of paramsBitMap. + * @param st Decoder state. + * @param pStream Pointer to a stream where parameters should be stored. + * @param pnSize Set to the number of elements written to the stream. + */ +void ReadFromBitstream(ParamsBitMap const * paramsBitMap, Word16 nArrayLength, Decoder_State_fx *st, Word16 ** pStream, Word16 * pnSize); + +void const * GetTnsFilterOrder(void const * p, Word16 index, Word16 * pValue); +void * SetTnsFilterOrder(void * p, Word16 index, Word16 value); +void const * GetNumOfTnsFilters(void const * p, Word16 index, Word16 * pValue); +void * SetNumOfTnsFilters(void * p, Word16 index, Word16 value); +void const * GetTnsEnabled(void const * p, Word16 index, Word16 * pValue); +void * SetTnsEnabled(void * p, Word16 index, Word16 value); +void const * GetTnsEnabledSingleFilter(void const * p, Word16 index, Word16 * pValue); +void * SetTnsEnabledSingleFilter(void * p, Word16 index, Word16 value); +void const * GetTnsFilterCoeff(void const * p, Word16 index, Word16 * pValue); +void * SetTnsFilterCoeff(void * p, Word16 index, Word16 value); + + +Word16 GetSWBTCX10TnsFilterCoeffBits(Word16 value, Word16 index); +Word16 EncodeSWBTCX10TnsFilterCoeff(Word16 value, Word16 index); +Word16 DecodeSWBTCX10TnsFilterCoeff(Decoder_State_fx *st, Word16 index, Word16 * pValue); +Word16 GetSWBTCX20TnsFilterCoeffBits(Word16 value, Word16 index); +Word16 EncodeSWBTCX20TnsFilterCoeff(Word16 value, Word16 index); +Word16 DecodeSWBTCX20TnsFilterCoeff(Decoder_State_fx *st, Word16 index, Word16 * pValue); + +Word16 GetWBTCX20TnsFilterCoeffBits(Word16 value, Word16 index); +Word16 EncodeWBTCX20TnsFilterCoeff(Word16 value, Word16 index); +Word16 DecodeWBTCX20TnsFilterCoeff(Decoder_State_fx *st, Word16 index, Word16 * pValue); + +Word16 GetTnsFilterOrderBitsSWBTCX10(Word16 value, Word16 index); +Word16 EncodeTnsFilterOrderSWBTCX10(Word16 value, Word16 index); +Word16 DecodeTnsFilterOrderSWBTCX10(Decoder_State_fx *st, Word16 index, Word16 * pValue); +Word16 GetTnsFilterOrderBitsSWBTCX20(Word16 value, Word16 index); +Word16 EncodeTnsFilterOrderSWBTCX20(Word16 value, Word16 index); +Word16 DecodeTnsFilterOrderSWBTCX20(Decoder_State_fx *st, Word16 index, Word16 * pValue); +Word16 GetTnsFilterOrderBits(Word16 value, Word16 index); +Word16 EncodeTnsFilterOrder(Word16 value, Word16 index); +Word16 DecodeTnsFilterOrder(Decoder_State_fx *st, Word16 index, Word16 * pValue); + + +/*tns_base.h*/ +/** Reset TNS data. + * Resets TNS data to the initial state. + * @param pTnsData pointer to a TNS data to be reset. + */ +void ResetTnsData(STnsData * pTnsData); + +/** Clear TNS filter data. + * Resets TNS filter order and all coefficients to 0. + * @param pTnsFilter pointer to a TNS filter to be cleared. + */ +void ClearTnsFilterCoefficients(STnsFilter * pTnsFilter); + +/** Init TNS configuration. + * Fills STnsConfig structure with sensible content. + * @param nSampleRate Sampling rate of the input. + * @param nFrameLength Frame length. + * @param pTnsConfig TNS configuration to be initialized. + * @return 0 on success, otherwise 1. + */ +Word16 InitTnsConfiguration(Word32 nSampleRate, + Word16 frameLength, + STnsConfig * pTnsConfig + ,Word16 igfStopFreq + ,Word32 bitrate + ); + +/** Detect TNS parameters. + * Detects if TNS should be used and fills TNS data in pTnsData. + * @param pTnsConfig TNS configuration. + * @param pSpectrum Spectrum lines. + TNS is tested on the spectrum defined by pSpectrum. + * @param sbCnt Number of active subbands. + * @param pTnsData TNS data is filled with sensible information. + * @return Returns 1 if Tns should be used, otherwise 0. + */ +Word16 DetectTnsFilt(STnsConfig const * pTnsConfig, + Word32 const pSpectrum[], + STnsData * pTnsData, + Word16 *predictionGain); + +/** Modify spectrum using TNS filter. + * Modifies spectrum unsing TNS filter defined by pTnsData. + * If fIsAnalyses is true considers spectrum to be + * an input of encoder and returns residum. + * If fIsAnalyses is false considers spectrum to be + * a residum from decoder and returns output spectrum. + * @param pTnsConfig TNS configuration. + * @param pTnsData TNS data describing filters. + * @param spectrum Input/output spectrum. + * @param fIsAnalysis Defines if TNS filter is applied + * in encoder (TRUE) or in decoder (FALSE). + * @return 0 on success, otherwise 1. + */ +Word16 ApplyTnsFilter(STnsConfig const * pTnsConfig, + STnsData const * pTnsData, + Word32 spectrum[], + Word8 fIsAnalysis); + +Word16 ITF_Detect_fx(Word32 const pSpectrum[], + Word16 startLine, + Word16 stopLine, + Word16 maxOrder, + Word16* A, + Word16* Q_A, + Word16* predictionGain, + Word16* curr_order, + Word16 Q); + +TNS_ERROR ITF_Apply_fx(Word32 spectrum[], + Word16 startLine, Word16 stopLine, const Word16* A, + Word16 Q_A, + Word16 curr_order); + +/** Write TNS data into a stream of integers. + * Writes TNS data into a stream of integers. + * @param pTnsConfig TNS configuration. + * @param pTnsData TNS data to be written to a bitstream. + * @param stream Output stream of integers. + * @param pnSize Set to the number of elements written to the stream. + * @param pnBits Set to the number of required. + * @return 0 on success, otherwise 1. + */ +Word16 EncodeTnsData(STnsConfig const * pTnsConfig, + STnsData const * pTnsData, + Word16 * stream, + Word16 * pnSize, + Word16 * pnBits); + +/** Read TNS data from a stream of integers. + * Reads TNS data from a stream of integers. + * @param pTnsConfig TNS configuration. + * @param stream Input stream of integers. + * @param pnSize Set to the number of elements read from stream. + * @param pTnsData TNS data to be read from the bitstream. + * @return 1 if TNS is active, otherwise 0. + */ +Word16 DecodeTnsData(STnsConfig const * pTnsConfig, + Word16 const * stream, + Word16 * pnSize, + STnsData * pTnsData); + +/** Write TNS data into a bitstream. + * Writes TNS data into a bitstream. + * @param pTnsConfig TNS configuration. + * @param stream Contains TNS data written with EncodeTnsData. + * @param pnSize Set to the number of used elements from stream. + * @param st Encoder state. + * @param pnBits Set to the number of bits written. + * @return 0 on success, otherwise 1. + */ +Word16 WriteTnsData(STnsConfig const * pTnsConfig, + Word16 const * stream, + Word16 * pnSize, + Encoder_State_fx *st, + Word16 * pnBits); + +/** Read TNS data from a bitstream. + * Reads TNS data from a bitstream using bin2int. + * @param pTnsConfig TNS configuration. + * @param st Decoder state. + * @param pnBits Set to the number of bits written. + * @param stream Contains TNS data that can be decoded with DecodeTnsData. + * @param pnSize Set to the number of used elements from stream. + * @return 0 on success, otherwise 1. + */ +Word16 ReadTnsData(STnsConfig const * pTnsConfig, + Decoder_State_fx *st, + Word16 * pnBits, + Word16 * stream, + Word16 * pnSize); + +Word16 +CLDFB_getNumChannels(Word32 sampleRate); + +void +cldfbAnalysisFiltering( HANDLE_CLDFB_FILTER_BANK anaCldfb, /*!< Handle of Cldfb Analysis Bank */ + Word32 **cldfbReal, /*!< Pointer to real subband slots */ + Word32 **cldfbImag, /*!< Pointer to imag subband slots */ + CLDFB_SCALE_FACTOR *scaleFactor, /*!< Scale factors of CLDFB data */ + const Word16 *timeIn, /*!< Time signal */ + const Word16 timeIn_e, /*!< Time signal */ + const Word16 nTimeSlots, /*!< Time slots to be processed */ + Word32 *pWorkBuffer /*!< pointer to temporal working buffer */ + ); + +void +cldfbSynthesisFiltering(HANDLE_CLDFB_FILTER_BANK synCldfb, /*!< Handle of Cldfb Synthesis Bank */ + Word32 **CldfbBufferReal, /*!< Pointer to 32 bit real subband slots */ + Word32 **CldfbBufferImag, /*!< Pointer to 32 bit imag subband slots */ + const CLDFB_SCALE_FACTOR *scaleFactor, /*!< Scale factors of CLDFB data */ + Word16 *timeOut, /*!< Time signal */ + const Word16 timeOut_e, /*!< Target exponent for output signal */ + const Word16 nTimeSlots, /*!< number of time slots to be processed */ + Word32 *pWorkBuffer /*!< pointer to temporal working buffer */ + ); + +Word16 +cldfbInitAnalysisFilterBank(HANDLE_CLDFB_FILTER_BANK h_Cldfb, /*!< CLDFB Handle */ + Word16 *pFilterStates, /*!< Pointer to filter state buffer */ + Word16 frameSize, /*!< FrameSize */ + Word16 lsb, /*!< Number of lower bands */ + Word16 usb, /*!< Number of upper bands */ + Word16 no_channels, /*!< Number of critically sampled bands */ + UWord16 flags /*!< Flags */ + ); + +void +cldfbAnalysisFilteringSlot(HANDLE_CLDFB_FILTER_BANK anaCldfb, /*!< Handle of Cldfb Synthesis Bank */ + Word32 *cldfbReal, /*!< Low and High band, real */ + Word32 *cldfbImag, /*!< Low and High band, imag */ + Word32 *pWorkBuffer /*!< pointer to temporal working buffer */ + ); + +Word16 +cldfbInitSynthesisFilterBank(HANDLE_CLDFB_FILTER_BANK h_Cldfb, /*!< CLDFB Handle */ + Word16 *pFilterStates, /*!< Pointer to filter state buffer */ + Word16 noCols, /*!< Number of time slots */ + Word16 lsb, /*!< Number of lower bands */ + Word16 usb, /*!< Number of upper bands */ + Word16 no_channels, /*!< Number of critically sampled bands */ + UWord16 flags /*!< Flags */ + ); + +void cldfbSynthesisFilteringSlot(HANDLE_CLDFB_FILTER_BANK synCldfb, + const Word32 *realSlot, + const Word32 *imagSlot, + const Word16 scaleFactorLowBand, + const Word16 scaleFactorHighBand, + Word16 *timeOut, + const Word16 stride, + Word32 *pWorkBuffer + ); + + +void configureCldfb ( HANDLE_CLDFB_FILTER_BANK h_cldfb, /*!< CLDFB Handle */ + const Word16 no_channels, /*!< Number of critically sampled bands */ + const Word16 frameSize /*!< FrameSize */ + ); + +void openCldfb ( HANDLE_CLDFB_FILTER_BANK *h_cldfb, /*!< CLDFB Handle */ + const Word16 type, /*!< analysis or synthesis */ + const Word16 maxCldfbBands, /*!< number of cldfb bands */ + const Word16 frameSize /*!< FrameSize */ + ); + +void resampleCldfb ( + HANDLE_CLDFB_FILTER_BANK hs, /*!< CLDFB Handle */ + const Word16 newCldfbBands, /*!< number of cldfb bands */ + const Word16 frameSize, /*!< FrameSize */ + const Word8 firstFrame +); + +void +deleteCldfb (HANDLE_CLDFB_FILTER_BANK * h_cldfb); /*!< CLDFB Handle */ + +Word16 +CreateCldfbAnalysisFilterBank (HANDLE_CLDFB_FILTER_BANK *hAnalysisCldfb, + const Word16 maxCldfbBands, + const Word16 frameSize, + UWord16 flags + ); + +Word16 +DestroyCldfbAnalysisFilterBank (HANDLE_CLDFB_FILTER_BANK *hAnalysisCldfb + ); + +Word16 +CreateCldfbSynthesisFilterBank (HANDLE_CLDFB_FILTER_BANK *hSynthesisCldfb, + const Word16 maxCldfbBands, + const Word16 frameSize, + UWord16 flags + ); + +Word16 +DestroyCldfbSynthesisFilterBank (HANDLE_CLDFB_FILTER_BANK *hSynthesisCldfb + ); + +Word16 +ResampleCldfbAnalysisFilterBank (HANDLE_CLDFB_FILTER_BANK hs, + const Word16 newCldfbBands, + Word16 newFrameSize, + UWord16 flags, + Word8 firstFrame + ); + + + +Word16 +AnalysisPostSpectrumScaling_Fx (HANDLE_CLDFB_FILTER_BANK cldfbBank, + Word32 **rSubband32, + Word32 **iSubband32, + Word16 **rSubband16, + Word16 **iSubband16, + Word16 *cldfbScale + ); + +void +GetEnergyFromCplxCldfbData_Fx(Word32 **energyValues, + Word32 *energyLookahead, + Word16 *sf_energyLookahead, + const Word16 numLookahead, + Word16 **realValues, + Word16 **imagValues, + Word16 sf_Values, + Word16 numberBands, + Word16 numberCols, + Word32 *energyHF, + Word16 *energyHF_Exp + ); + +void +GetEnergyCldfb( Word32 *energyLookahead, /*!< o: Q31 | pointer to the result in the core look-ahead slot */ + Word16 *sf_energyLookahead, /*!< o: pointer to the scalefactor of the result in the core look-ahead slot - apply as negative exponent*/ + const Word16 numLookahead, /*!< i: Q0 the number of look-ahead time-slots */ + Word16 **realValues, /*!< i: Q15 | the real part of the CLDFB subsamples */ + Word16 **imagValues, /*!< i: Q15 | the imaginary part of the CLDFB subsamples */ + Word16 sf_Values, /*!< i: scalefactor of the CLDFB subcamples - apply as a negated Exponent */ + Word16 numberBands, /*!< i: Q0 | number of CLDFB bands */ + Word16 numberCols, /*!< i: Q0 | number of CLDFB subsamples */ + Word32 *energyHF, /*!< o: Q31 | pointer to HF energy */ + Word16 *energyHF_Exp, /*!< o: pointer to exponent of HF energy */ + Word32 *energyValuesSum, /*!< o: Q31 | pointer to sum array of energy values, not initialized*/ + Word16 *energyValuesSum_Exp /*!< o: pointer to exponents of energyValuesSum, not initialized */ + , HANDLE_TEC_ENC_FX hTecEnc + ); + +/*bits_alloc.h*/ +Word16 BITS_ALLOC_get_rate_mode( + const Word16 frame_size_index /*i: frame_size_index*/ +); + +void BITS_ALLOC_init_config_acelp( + const Word32 bit_rate, + const Word8 narrowBand, + const Word16 nb_subfr, + ACELP_config *pConfigAcelp /*o: configuration structure of ACELP*/ +); + +Word16 BITS_ALLOC_config_acelp( + const Word16 bits_frame, /*i: remaining bit budget for the frame */ + const Word16 coder_type, /*i: coder type */ + ACELP_config *pConfigAcelp, /*i/o: configuration structure of ACELP*/ + const Word16 narrowband, + const Word16 nb_subfr +); + +void BITS_ALLOC_ACELP_config_rf(const Word16 coder_type, + Word16 *tilt_code, + Word16 *rf_frame_type, + Word16 *rf_target_bits, + Word16 nb_subfr + , Word16 rf_fec_indicator + , Word16 *pitch_buf + ); +void BITS_ALLOC_TCX_config_rf( + Word16 *rf_frame_type, + Word16 *rf_target_bits, + Word16 PLC_Mode, + Word16 coder_type, + Word16 last_core, + Word16 TD_mode +); + +Word16 BITS_ALLOC_adjust_acelp_fixed_cdk( + const Word16 bits_frame, /*i: bit budget */ + Word16 *fixed_cdk_index, /*o: codebook index */ + const Word16 nb_subfr /*i: number of subframes*/ +); + + + +Word16 BITS_ALLOC_adjust_acelp_fixed_16KHZ_cdk( + const Word16 bits_frame, /*i: bit budget */ + Word16 *fixed_cdk_index, /*o: codebook index */ + const Word16 nb_subfr /*i: number of subframes*/ +); + +/*transient_detection.h*/ +/** Init transient detection. + * Fills TransientDetection structure with sensible content. + * @param nFrameLength Frame length. + * @param nTCXDelay Delay for the TCX Long/Short transient detector. + * Don't include the delay of the MDCT overlap. + * @param pTransientDetection Structure to be initialized. It contains all transient detectors to be used. + */ +void InitTransientDetection(Word16 nFrameLength, + Word16 nTCXDelay, + struct TransientDetection * pTransientDetection); + +/** Runs transient detection. + * Runs all transient detectors defined in pTransientDetection + * and calculates mean zero crossing. + * @param input New input samples. + * @param nSamplesAvailable Number of new input samples available. + * @param pTransientDetection Structure that contains transient detectors to be run. + */ +void RunTransientDetection(Word16 const * input, Word16 nSamplesAvailable, struct TransientDetection * pTransientDetection); + + +/** Get the average temporal flatness measure using subblock energies aligned with the TCX. + * @param pTransientDetection Structure that contains transient detectors to be run. + * @param nCurrentSubblocks Number of the subblocks from the current frame to use for the calculation. + A lookeahead can also be use if it exists. + * @param nPrevSubblocks Number of subblocks from the previous frames to use for the calculation. + * @return average temporal flatness measure with exponent AVG_FLAT_E + */ +Word16 GetTCXAvgTemporalFlatnessMeasure(struct TransientDetection const * pTransientDetection, Word16 nCurrentSubblocks, Word16 nPrevSubblocks); + + +/** Get the maximum energy change using subblock energies aligned with the TCX. + * @param pTransientDetection Structure that contains transient detectors to be run. + * @param nCurrentSubblocks Number of the subblocks from the current frame to use for the calculation. + A lookeahead can also be use if it exists. + * @param nPrevSubblocks Number of subblocks from the previous frames to use for the calculation. + * @param maximum energy change with exponent NRG_CHANGE_E + */ +Word16 GetTCXMaxenergyChange(struct TransientDetection const * pTransientDetection, + const Word8 isTCX10, + const Word16 nCurrentSubblocks, const Word16 nPrevSubblocks); + +/** Set TCX window length and overlap configuration + * @param prevEnergyHF previous HF energy. Exponent must be the same as for currEnergyHF. + * @param currEnergyHF current HF energy. Exponent must be the same as for prevEnergyHF. + */ +void SetTCXModeInfo(Encoder_State_fx *st, + struct TransientDetection const * pTransientDetection, + Word16 * tcxModeOverlap); + +/* Tonal Concealment */ + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_Init( TonalMDCTConcealPtr self, + Word16 nSamples, + Word16 nSamplesCore, + Word16 nScaleFactors, + TCX_config * tcx_cfg + ); + + +/* Must be called only when a good frame is recieved - concealment is inactive */ +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_SaveFreqSignal( TonalMDCTConcealPtr self, + Word32 const *mdctSpectrum, + Word16 const mdctSpectrum_exp, + Word16 nNewSamples, + Word16 nNewSamplesCore, + Word16 const *scaleFactors, + Word16 const *scaleFactors_exp, + Word16 const gain_tcx_exp + ); + +/* The call to TonalMDCTConceal_UpdateState() should be called after TonalMDCTConceal_Apply. */ +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_UpdateState(TonalMDCTConcealPtr self, + Word16 nNewSamples, + Word32 pitchLag, + Word16 badBlock, + Word8 tonalConcealmentActive + ); + +/* The call to TonalMDCTConceal_SaveTimeSignal() should be at the + * place where the TD signal corresponds to the FD signal stored with TonalMDCTConceal_SaveFreqSignal. */ +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_SaveTimeSignal( TonalMDCTConcealPtr self, + Word16 *timeSignal, + Word16 numSamples + ); + +/* Calculates MDST, power spectrum and performs peak detection. + * Uses the TD signal in pastTimeSignal; if pastTimeSignal is NULL, uses the + * TD signal stored using TonalMDCTConceal_SaveTimeSignal. If the + * second last frame was also lost, it is expected that pastTimeSignal + * could hold a signal somewhat different from the one stored in + * TonalMDCTConceal_SaveTimeSignal (e.g. including fade-out).*/ +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_Detect( TonalMDCTConcealPtr const self, /*IN */ + Word32 const pitchLag, /*IN */ + Word16 * const umIndices /*OUT*/ + ); + +/* Conceals the lost frame using the FD signal previously stored using + * TonalMDCTConceal_SaveFreqSignal. Stores the concealed harmonic part of + * the signal in mdctSpectrum, the rest of the spectrum is unchanged. */ +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_Apply( TonalMDCTConcealPtr self, /*IN */ + Word32 * mdctSpectrum, /*OUT*/ + Word16 * mdctSpectrum_exp /*OUT*/ + ); + +/* Conceals the lost frame using the FD signal previously stored using + * TonalMDCTConceal_SaveFreqSignal. Stores the concealed noise part of + * the signal in mdctSpectrum, the rest of the spectrum is unchanged. */ +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_InsertNoise( TonalMDCTConcealPtr self, /*IN */ + Word32* mdctSpectrum, /*OUT*/ + Word16* mdctSpectrum_exp, /*OUT*/ + Word8 tonalConcealmentActive, + Word16* pSeed, /*IN/OUT*/ + Word16 tiltCompFactor, + Word16 crossfadeGain, + Word16 crossOverFreq); + +/* Detect tonal components in the lastMDCTSpectrum, use + * secondLastPowerSpectrum for the precise location of the peaks and + * store them in indexOfTonalPeak. Updates lowerIndex, upperIndex, + * pNumIndexes accordingly. */ +void DetectTonalComponents(Word16 indexOfTonalPeak[], /* OUT */ + Word16 lowerIndex[], /* OUT */ + Word16 upperIndex[], /* OUT */ + Word16 * pNumIndexes, /* OUT */ + Word32 lastPitchLag, Word32 currentPitchLag, /* IN */ + Word16 const lastMDCTSpectrum[], /* IN */ + Word16 lastMDCTSpectrum_exp, /* IN */ + Word16 const scaleFactors[], /* IN */ + Word16 const scaleFactors_exp[], /* IN */ + Word16 const scaleFactors_max_e, /* IN */ + Word32 const secondLastPowerSpectrum[], /* IN */ + Word16 nSamples /* IN */ + ,Word16 nSamplesCore + ,Word16 floorPowerSpectrum /* IN */ + ); + +/* When called, the tonal components are already stored in + * indexOfTonalPeak. Detect tonal components in the lastMDCTSpectrum, + * use secondLastPowerSpectrum for the precise location of the peaks and + * then keep in indexOfTonalPeak only the tonal components that are + * again detected Updates indexOfTonalPeak, lowerIndex, upperIndex, + * phaseDiff, phases, pNumIndexes accordingly. */ +void RefineTonalComponents(Word16 indexOfTonalPeak[], /* OUT */ + Word16 lowerIndex[], /* OUT */ + Word16 upperIndex[], /* OUT */ + Word16 phaseDiff[], /* OUT */ + Word16 phases[], /* OUT */ + Word16 * pNumIndexes, /* OUT */ + Word32 lastPitchLag, /* IN */ + Word32 currentPitchLag, /* IN */ + Word16 const lastMDCTSpectrum[], /* IN */ + Word16 const lastMDCTSpectrum_exp, /* IN */ + Word16 const scaleFactors[], /* IN */ + Word16 const scaleFactors_exp[], /* IN */ + Word16 const scaleFactors_max_e, /* IN */ + Word32 const secondLastPowerSpectrum[], /* IN */ + Word16 nSamples /* IN */ + ,Word16 nSamplesCore + ,Word16 floorPowerSpectrum /* IN */ + ); + +void set_state(Word16 *state, Word16 num, Word16 N); +void concealment_init_x(Word16 N, void *_plcInfo); +void concealment_update_x(Word16 bfi, Word16 curr_mode, Word16 harmonic, Word32 *invkoef, Word16 *invkoef_scale, void *_plcInfo); + +void waveform_adj2_fix( Word16 *overlapbuf, + Word16 *outx_new, + Word16 *data_noise, + Word16 *outx_new_n1, + Word16 *nsapp_gain, + Word16 *nsapp_gain_n, + Word16 *recovery_gain, + Word16 step_concealgain, + Word16 pitch, + Word16 Framesize, + Word16 delay, + Word16 bfi_cnt, + Word16 bfi + ); + +Word16 ffr_getSfWord16(Word16 *vector, /*!< Pointer to input vector */ + Word16 len); /*!< Length of input vector */ + +void concealment_decode_fix(Word16 curr_mode, Word32 *invkoef, Word16 *invkoef_scale,void *_plcInfo); + +void concealment_signal_tuning_fx(Word16 bfi, + Word16 curr_mode, + Word16 *outx_new_fx, + void *_plcInfo, + Word16 nbLostCmpt, + Word16 pre_bfi, + Word16 *OverlapBuf_fx, + Word16 past_core_mode, + Word16 *outdata2_fx, + Decoder_State_fx *st); + +Word16 Spl_GetScalingSquare_x(Word16 *in_vector, Word16 in_vector_length, Word16 times); +Word32 Spl_Energy_x(Word16* vector, Word16 vector_length, Word16* scale_factor); +void Log10OfEnergy_x(Word16 *s, Word32 *enerlogval, Word16 len); +void concealment_update2_x(Word16 *outx_new, void *_plcInfo, Word16 FrameSize); +Word16 Sqrt_x_fast(Word32 value); + +Word32 dot_w32_accuracy_x(Word16 *s1, Word16 *s2, Word16 nbits, Word16 N); + +Word16 int_div_s_x(Word16 a, Word16 b); + +Word16 GetW32Norm_x(Word32 *s, Word16 N); + +Word16 harmo_x(Word32 *X, Word16 Framesize, Word16 pitch); + + +void LpFilter2_x(Word16 *x, Word16 *y, Word16 N); + +void sig_tilt_x(Word16 *s, Word16 FrameSize, Word32 *enr1, Word32 *enr2) ; + +void get_maxConv_and_pitch_x(Word16 *s_LP, Word16 s, Word16 e, Word16 N, + Word32 *maxConv, Word16 *maxConv_bits, Word16 *pitch); + +Word16 get_voicing_x(Word16 *s_LP, Word16 pitch, Word32 covMax,Word16 maxConv_bits, Word16 Framesize); + +void pitch_modify_x(Word16 *s_LP, Word16 *voicing, Word16 *pitch, Word16 FrameSize); + +Word16 Is_Periodic_x(Word32 *mdct_data, Word16 cov_max, Word16 zp, Word32 ener, + Word32 ener_mean, Word16 pitch, Word16 Framesize); + +Word16 get_conv_relation_x(Word16 *s_LP, Word16 shift, Word16 N); + + + +/* 14Q1*1.28 */ +#define LSF_GAP_VAL(x) (Word16)((x)*2.0f*1.28f) + +/*longarith.h*/ + +/** + * \brief inplace long shift right: a[] = a[] >> bits + * Logical shift right of UWord32 vector a[] by 'bits' positions. + */ + +void longshr (UWord32 a[], Word16 bits, Word16 len); + + +/*qlpc_avq.h*/ +void lsf_weight_2st(const Word16 *lsfq, /* input: quantized lsf coefficients (3Q12) */ + Word16 *w, /* output: weighting function (0Q15) */ + const Word16 mode /* input: operational mode */ + ); + + + +void qlpc_avq( + const Word16 *lsf, /* (i) Input LSF vectors */ + const Word16 *lsfmid, /* (i) Input LSF vectors */ + Word16 *lsf_q, /* (o) Quantized LFS vectors */ + Word16 *lsfmid_q, /* (o) Quantized LFS vectors */ + Word16 *index, /* (o) Quantization indices */ + Word16 *nb_indices, /* (o) Number of quantization indices */ + Word16 *nbbits, /* (o) Number of quantization bits */ + const Word16 core, /* (i) TCX10 or TCX20 */ + Word32 sr_core +); + +Word16 encode_lpc_avq( Encoder_State_fx *st, Word16 numlpc, Word16 *param_lpc, Word16 mode ); + +Word16 dlpc_avq( + Word16 *index, /* (i) Quantization indices */ + Word16 *LSF_Q, /* (o) Quantized LSF vectors */ + Word16 numlpc, /* (i) Number of sets of lpc */ + Word32 sr_core +); + +Word16 decode_lpc_avq( Decoder_State_fx *st, Word16 numlpc, Word16 *param_lpc ); + +Word16 vlpc_1st_cod(const Word16 *lsf, /* input: vector to quantize */ + Word16 *lsfq /* i/o: i:prediction o:quantized lsf */ + ,Word16 *wout /* o: lsf weights */ + ,Word16 rf_mode + ); + +Word16 vlpc_2st_cod( /* output: number of allocated bits */ + const Word16 *lsf, /* input: normalized vector to quantize (3Q12) */ + Word16 *lsfq, /* i/o: i:1st stage o:1st+2nd stage (3Q12) */ + Word16 *indx, /* output: index[] (4 bits per words) */ + Word16 mode, /* input: 0=abs, >0=rel */ + Word32 sr_core +); + +void vlpc_2st_dec( + Word16 *lsfq, /* i/o: i:1st stage o:1st+2nd stage */ + Word16 *indx, /* input: index[] (4 bits per words) */ + Word16 mode, /* input: 0=abs, >0=rel */ + Word32 sr_core); + +void open_decoder_LPD( + Decoder_State_fx *st, + Word32 bitrate, + Word16 bandwidth +); + + +void update_decoder_LPD_cng( + Decoder_State_fx *st, + Word16 coder_type, + Word16 *timeDomainBuffer, + Word16 *A, + Word16 *bpf_noise_buf +); + +void reconfig_decoder_LPD( Decoder_State_fx *st, Word16 bits_frame, Word16 bandwidth_mode, Word32 bitrate, Word16 L_frame_old); + +void mode_switch_decoder_LPD( Decoder_State_fx *st, Word16 bandwidth_in, Word32 bitrate, Word16 frame_size_index + ); + +void decoder_LPD( + Word16 signal_out[], /* output: signal with LPD delay (7 subfrs) */ + Word16 signal_outFB[], + Word16 *total_nbbits, /* i/o: number of bits / decoded bits */ + Decoder_State_fx *st , /* i/o: decoder memory state pointer */ + Word16 *bpf_noise_buf, + Word16 bfi, + Word16 *bitsRead, + Word16 *coder_type, + Word16 param[], + Word16 *pitch_buf, + Word16 *voice_factors, + Word16 *ptr_bwe_exc +); + +Word16 dec_acelp_tcx_frame( + Decoder_State_fx *st, + Word16 *coder_type, + Word16 *concealWholeFrame, + Word16 *pcmBuf, + Word16 * bpf_noise_buf, + Word16 * pcmbufFB, + Word32 bwe_exc_extended[], + Word16 *voice_factors, + Word16 pitch_buf[] +); + + +Word16 tcxGetNoiseFillingTilt(Word16 A[], + Word16 lpcorder, + Word16 L_frame, + Word16 mode, + Word16 *noiseTiltFactor + ); + + +void tcxFormantEnhancement( + Word16 xn_buf[], + Word16 gainlpc[], Word16 gainlpc_e[], + Word32 spectrum[], Word16 *spectrum_e, + Word16 L_frame + ,Word16 L_frameTCX +); + + +void tcxInvertWindowGrouping(TCX_config *tcx_cfg, + Word32 xn_buf[], + Word32 spectrum[], + Word16 L_frame, + Word8 fUseTns, + Word16 last_core, + Word16 index, + Word16 frame_cnt, + Word16 bfi); + +/*lerp.h*/ + +void lerp(Word16 *f, Word16 *f_out, Word16 bufferNewSize, Word16 bufferOldSize); + +void attenuateNbSpectrum(Word16 L_frame, Word32 *spectrum); + +Word8 getTcxonly(const Word32 bitrate); +Word8 getCtxHm(const Word32 bitrate, const Word16 rf_flag); +Word8 getResq(const Word32 bitrate); + +Word8 getTnsAllowed(const Word32 bitrate + ,const Word16 igf + ); + +Word8 getRestrictedMode(const Word32 bitrate, const Word16 Opt_AMR_WB); + +Word16 sr2fscale(const Word32 sr); + +Word32 getCoreSamplerateMode2(const Word32 bitrate, const Word16 bandwidth, const Word16 rf_flag); +Word16 getTcxBandwidth(const Word16 bandwidth); + +Word8 getIgfPresent( + const Word32 bitrate, + const Word16 bandwidth + , const Word16 rf_mode +); + +Word8 getCnaPresent( + const Word32 bitrate, + const Word16 bandwidth +); + +Word8 getTcxLtp( + const Word32 sr_core +); + +Word16 initPitchLagParameters( + const Word32 sr_core, + Word16 *pit_min, + Word16 *pit_fr1, + Word16 *pit_fr1b, + Word16 *pit_fr2, + Word16 *pit_max +); + +Word16 getNumTcxCodedLines(const Word16 bwidth); + +Word16 getTcxLpcShapedAri( + const Word32 total_brate, + const Word16 bwidth + ,const Word16 rf_mode +); + + +Word16 vad_init(T_CldfbVadState *vad_state); + +void subband_FFT( + Word32 ** Sr, /*(i) real part of the CLDFB*/ + Word32 ** Si, /*(i) imag part of the CLDFB*/ + Word32 *spec_amp, /*(o) spectral amplitude*/ + Word32 Offset, /*(i) offset of the CLDFB*/ + Word16 *fftoQ /*(o) the Scaling */ +); + +void UpdateState( T_CldfbVadState *vad_state, + Word16 vad_flag, + Word32 frame_energy, /*(i) current frame energy*/ + Word16 sacle_sbpower, /*(i) the Scaling of current frame energy*/ + Word32 update_flag, /*(i) current frame update flag*/ + Word16 music_backgound_f, /*(i) backgound music flag*/ + Word32 HB_Power, /*(i) current frame high frequency energy*/ + Word16 HB_Power_Q /*(i) the Scaling of current frame high frequency energy*/ + ,Word32 snr + ); + +void calc_snr_flux( Word32 tsnr_fix, /*(i) time-domain SNR*/ + Word32 *pre_snr, /*(io)time-domain SNR storage*/ + Word32 *snr_flux /*(o) average tsnr*/ + ); + +Word16 update_decision( + T_CldfbVadState *st, + Word32 frame_energy, /*(i) current frame energy*/ + Word32 HB_Power, /*(i) current frame high frequency energy*/ + Word16 frameloop, /*(i) amount of frames*/ + Word16 bw, /*(i) band width index*/ + Word16 frame_energy_Q, /*(i) the Scaling of current frame energy*/ + Word16 HB_Power_Q, /*(i) the Scaling of current frame high frequency energy*/ + Word32 snr, /*(i) frequency domain SNR */ + Word32 tsnr, /*(i) time domain SNR */ + Word16 vad_flag, + Word16 music_backgound_f /*(i) background music flag*/ +); + +void frame_spec_dif_cor_rate( T_CldfbVadState *st, /*(io) vad state*/ + Word32 *spec_amp, /*(i) spectral amplitude*/ + Word16 sacle, /*(i) the scaling of spec_amp*/ + Word16 f_tonality_rate[3] /*(o) tonality rate*/ + ); + +void ltd_stable( T_CldfbVadState *st, /*(io) vad state*/ + Word16 *ltd_stable_rate, /*(o) time-domain stable rate*/ + Word32 frame_energy, /*(i) current frame energy*/ + Word16 frameloop, /*(i) amount of frames*/ + Word16 Q_frames_power /*(i) the Scaling of frames_power*/ + ); + +void snr_calc( T_CldfbVadState *st, /*(io) vad state*/ + Word16 sacle_sbpower, /*(i) the Scaling of sbpower*/ + Word32 *snr, /*(o) frequency domain SNR */ + Word32 *tsnr, /*(o) time domain SNR */ + Word32 frame_energy, /*(i) current frame energy */ + Word32 bandwith /*(i) band width*/ + ); + +void bg_music_decision( T_CldfbVadState *st, + Word16 *music_backgound_f, /*(i) background music flag*/ + Word32 frame_energy, /*(i) current frame energy 1*/ + Word16 frame_energy_Q /*(i) the Scaling of current frame energy*/ + ); + +void background_update( T_CldfbVadState *st, + Word16 scale, /*(i) the Scaling of frame energy*/ + Word32 frame_energy, /*(i) current frame energy*/ + Word32 update_flag, /*(i) update flag*/ + Word16 music_backgound_f /*(i) background music flag*/ + ,Word32 snr + ); + +void spec_center( Word32* sb_power, /*(i) energy of sub-band divided uniformly*/ + Word16* sp_center, /*(o) spectral center*/ + Word32 bandwith, /*(i) band width*/ + Word16 Q_sb_p /*(i) the Scaling of sb_power*/ + ); + +void spec_flatness( Word32 *spec_amp, /*(i) spectral amplitude*/ + Word32 smooth_spec_amp[], /*(i) smoothed spectral amplitude*/ + Word16 sSFM[5] /*(o) spectral flatness rate*/ + ); + +void calc_lt_snr( T_CldfbVadState *st, /*(io) vad state*/ + Word32 *lt_snr_org, /*(o) original long time SNR*/ + Word32 *lt_snr, /*(o) long time SNR calculated by fg_energy and bg_energy*/ + Word32 fg_energy, /*(i) foreground energy sum */ + Word16 fg_energy_count, /*(i) amount of the foreground energy frame */ + Word32 bg_energy, /*(i) background energy sum */ + Word16 bg_energy_count, /*(i) amount of the background energy frame */ + Word16 bw_index, /*(i) band width index*/ + Word16 lt_noise_sp_center0 /*(i) long time noise spectral center by 0*/ + ); + +Word16 vad_decision( T_CldfbVadState *st, + Word32 l_snr, /*(i) long time frequency domain*/ + Word32 lt_snr_org, /*(i) original long time SNR*/ + Word32 lt_snr, /*(i) long time SNR calculated by fg_energy and bg_energy*/ + Word32 snr_flux, /*(i) average tsnr of several frames*/ + Word32 snr, /*(i) frequency domain SNR */ + Word32 tsnr, /*(i) time domain SNR */ + Word32 frame_energy, /*(i) current frame energy */ + Word16 music_backgound_f, /*(i) background music flag*/ + Word16 frame_energy_Q /*(i) the scaling of current frame energy*/ + ); + +Word16 comvad_decision( T_CldfbVadState *st, + Word32 l_snr, /*(i) long time frequency domain*/ + Word32 lt_snr_org, /*(i) original long time SNR*/ + Word32 lt_snr, /*(i) long time SNR calculated by fg_energy and bg_energy*/ + Word32 snr_flux, /*(i) average tsnr of several frames*/ + Word32 snr, /*(i) frequency domain SNR */ + Word32 tsnr, /*(i) time domain SNR */ + Word32 frame_energy, /*(i) current frame energy */ + Word16 music_backgound_f, /*(i) background music flag*/ + Word16 frame_energy_Q, /*(i) the Scaling of current frame energy*/ + Word16 *cldfb_addition, /*(o) adjust the harmonized hangover */ + Word16 vada_flag + ); + +void calc_lf_snr( + Word32 *lf_snr_smooth, /*(o) smoothed lf_snr*/ + Word32 *lf_snr, /*(o) long time frequency domain SNR calculated by l_speech_snr and l_silence_snr*/ + Word32 l_speech_snr, /*(i) sum of active frames snr */ + Word32 l_speech_snr_count, /*(i) amount of the active frame */ + Word32 l_silence_snr, /*(i) sum of the nonactive frames snr*/ + Word32 l_silence_snr_count, /*(i) amount of the nonactive frame */ + Word16 fg_energy_count, /*(i) amount of the foreground energy frame */ + Word16 bg_energy_count, /*(i) amount of the background energy frame */ + Word16 bw_index /*(i) band width index*/ +); + +Word32 construct_snr_thresh( Word16 sp_center[], /*(i) spectral center*/ + Word32 snr_flux, /*(i) snr flux*/ + Word32 lt_snr, /*(i) long time time domain snr*/ + Word32 l_snr, /*(i) long time frequency domain snr*/ + Word32 continuous_speech_num, /*(i) amount of continuous speech frames*/ + Word16 continuous_noise_num, /*(i) amount of continuous noise frames*/ + Word32 fg_energy_est_start, /*(i) whether if estimated energy*/ + Word16 bw_index /*(i) band width index*/ + ); + +Word16 vad_proc(T_CldfbVadState *vad_st, + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i: real values */ + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i: imag values */ + Word16 riBuffer_exp, /* i: exponent of real & imag Buffer */ + + Word16 *cldfb_addition, /*o: adjust the harmonized hangover */ + Word32 enerBuffer[CLDFB_NO_CHANNELS_MAX], /* i: energy vector per band */ + Word16 enerBuffer_exp, /* i: exponent of energy vector */ + Word16 bandwidth, /* 1: NB; 2:WB;3:SWB;4:FB*/ + Word16 vada_flag + ); + +void est_energy(Word32 enerBuffer[CLDFB_NO_CHANNELS_MAX], /* i: energy vector per band */ + Word16 enerBuffer_exp, /* i: exponent of energy vector */ + Word32 *frame_sb_energy, /*(o) energy of sub-band divided non-uniformly*/ + Word32 *frame_energy2_p, /*(o) frame energy 2*/ + Word32 *HB_Power_p, /*(o) high frequency energy*/ + Word32 *frame_energy_p, /*(o) frame energy 1*/ + Word16 *sb_power_Q, /*(o) the scaling of sb_power*/ + Word16 *frame_energy2_Q, /*(o) the scaling of frame_energy*/ + Word16 *HB_Power_Q, /*(o) the scaling of HB_Power*/ + Word16 *frame_energy_Q, /*(o) the Scaling of frame_energy*/ + Word16 *frame_sb_energy_scale, /*(o) the Scaling of frame_sb_energy[]*/ + Word32 bandwidth /*(i) band width*/ + ); + +/** + * \brief Function performs a complex 16-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR16 bits. + * + * WOPS FLC version: 196 cycles + * WOPS with 32x16 bit multiplications (scale on ): 288 cycles + * WOPS with 32x16 bit multiplications (scale off): 256 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ +void fft16(Word32 *re, Word32 *im, Word16 s, Word16 bScale); + + + +void dlpc_bfi( + const Word16 L_frame, + Word16 *lsf_q, /* o : quantized LSFs */ + const Word16 *lsfold, /* i : past quantized LSF */ + const Word16 last_good, /* i : last good received frame */ + const Word16 nbLostCmpt, /* i : counter of consecutive bad frames */ + Word16 mem_MA[], /* i/o: quantizer memory for MA model */ + Word16 mem_AR[], /* i/o: quantizer memory for AR model */ + Word16 *stab_fac, /* i : LSF stability factor */ + Word16 *lsf_adaptive_mean,/* i : LSF adaptive mean, updated when BFI==0 */ + Word16 numlpc, /* i : Number of division per superframe */ + Word16 lsf_cng[], + Word8 plcBackgroundNoiseUpdated, + Word16 *lsf_q_cng, /* o : quantized LSFs */ + Word16 *old_lsf_q_cng, /* o : old quantized LSFs for background noise */ + const Word16* lsfBase, /* i : base for differential LSF coding */ + Word8 tcxonly +); + +void isf_dec_bfi( + const Word16 last_type, /*!< i : coding type in last good received fr. */ + Word16*isf_q, /*!< o : 14Q1*1.28 quantized ISFs */ + const Word16*isfold, /*!< i : 14Q1*1.28 past quantized ISF */ + const Word16 last_good, /*!< i : last good received frame */ + const Word16 bfi_cnt, /*!< i : counter of consecutive bad frames */ + Word16*mem_MA, /*!< i/o: 14Q1*1.28 quantizer memory for MA model */ + Word16 stab_fac, /*!< i : ISF stability factor (shifted right by 1) */ + Word16*isf_adaptive_mean, /*!< i : 14Q1*1.28 ISF adaptive mean, updated when BFI==0 */ + const Word16 coder_type, /*!< i : Coders frame type */ + Word16 lpcorder, /*!< i: : lpc order */ + Word16 *isf_cng, + Word8 plcBackgroundNoiseUpdated, + Word16 *isf_q_cng, /* o : quantized ISFs for background noise */ + Word16 *old_isf_q_cng, /* o : old quantized ISFs for background noise */ + const Word16 xsfBase[] /* i : base for differential XSF coding */ +); + +void tfaCalcEnv_fx(const Word16* shb_speech, Word32* enr); +Word16 tfaEnc_TBE_fx(Word32* enr, + Word16 last_core, + Word16* voicing, /* Q15 */ + Word16* pitch_buf, /* Q6 */ + Word16 Q_enr + ); + +void tecEnc_TBE_fx(Word16* corrFlag, const Word16* voicing, Word16 coder_type); + +void set_TEC_TFA_code_fx(const Word16 corrFlag, Word16* tec_flag, Word16* tfa_flag); + +Word16 procTecTfa_TBE_Fx(Word16 *hb_synth_Fx, + Word16 hb_synth_fx_exp, + Word16 *gain_m, + Word16 *gain_e, + Word16 flat_flag, + Word16 last_core + , Word16 l_subfr + , Word16 code + ); + + +void +calcGainTemp_TBE_Fx( + Word32** pCldfbRealSrc_Fx, + Word32** pCldfbImagSrc_Fx, + Word16 cldfb_exp, + Word16* loBuffer_Fx, + Word16 startPos, /*!< Start position of the current envelope. */ + Word16 stopPos, /*!< Stop position of the current envelope. */ + Word16 lowSubband, /* lowSubband */ + Word16* pGainTemp_m, + Word16* pGainTemp_e + , Word16 code +); + +void resetTecEnc_Fx( + HANDLE_TEC_ENC_FX hTecEnc, + Word16 flag + +); + +void +resetTecDec_Fx( + HANDLE_TEC_DEC_FX hTecDec +); + +void calcHiEnvLoBuff_Fix( + Word16 noCols, + Word16* pFreqBandTable, /*!< freqbandTable. */ + Word16 nSfb, /*!< Number of scalefactors. */ + Word32** pCldfbPow_Fix /*float** pCldfbPow*/, + Word16* loBuffer_Fix /*float* loBuffer Q8*/, + Word16* hiTempEnvOrig_Fix /*float* hiTempEnvOrig*/, + Word16 pCldfbPow_FixScale +); + +void calcLoEnvCheckCorrHiLo_Fix( + Word16 noCols, + Word16* pFreqBandTable, /*!< freqbandTable. */ + Word16* loBuffer_Fix /*float* loBuffer*/, + Word16* loTempEnv_Fix /*float* loTempEnv*/, + Word16* loTempEnv_ns_Fix /* float* loTempEnv_ns*/, + Word16* hiTempEnvOrig_Fix /*float* hiTempEnvOrig*/, + Word16* corrFlag /*int* corrFlag*/ +); + + + +/**************************** Moved from er_util.h: ********************************/ + +/*----------------------------------------------------------------------* + * PLC: [ACELP: Fade-out] + * PLC: getLevelSynDeemph: derive on subframe basis the level of LPC + * synthesis and deeemphasis based on the given input + *----------------------------------------------------------------------*/ + +Word16 getLevelSynDeemph( /*10Q5*/ + Word16 h1Init[], /* i: input value or vector to be processed */ /* Q15 */ + Word16 const A[], /* i: LPC coefficients */ /* Qx */ + Word16 const lpcorder, /* i: LPC order */ /* Q0 */ + Word16 const lenLpcExc, /* i: length of the LPC excitation buffer */ /* Q0 */ + Word16 const preemph_fac, /* i: preemphasis factor */ /* Q15 */ + Word16 const numLoops, /* i: number of loops */ /* Q0 */ + Word16 *Exp /* o: exponent of return value Q15 */ +); + + +/*-----------------------------------------------------------------* + * PLC: [ACELP: general] + * PLC: high pass filtering + *-----------------------------------------------------------------*/ +void highPassFiltering( + const Word16 last_good, /* i: short last classification type */ + const Word16 L_buffer, /* i: int buffer length */ + Word16 exc2[], /* i/o: Qx unvoiced excitation before the high pass filtering */ + const Word16 hp_filt[], /* i: Q15 high pass filter coefficients */ + const Word16 l_fir_fer); /* i: high pass filter length */ + + +/*----------------------------------------------------------------------------------* + * PLC: [Common: mode decision] + * PLC: Decide which Concealment to use. Update pitch lags if needed + *----------------------------------------------------------------------------------*/ +Word16 GetPLCModeDecision( Decoder_State_fx *st + ); + +/* PLC: [Common: Fade-out] + * PLC: and for PLC fade out */ + +void minimumStatistics(Word16* noiseLevelMemory, /* Q15, internal state */ + Word16* noiseLevelIndex, /* Q0, internal state */ + Word16* currLevelIndex, /* Q0, internal state (circular buffer) */ + Word16* noiseEstimate, /* Q15, previous estimate of background noise */ + Word16* lastFrameLevel, /* Q15, level of the last frame */ + Word16 currentFrameLevel, /* Q15, level of the current frame */ + Word16* noiseLevelMemory_e, /* scaling factor for noiseLevelMemory */ + Word16 const noiseEstimate_e, /* exponent of noiseEstimate */ + Word16* new_noiseEstimate_e, /* new exponent of noise Estimate*/ + Word16* const lastFrameLevel_e, /* exponent of lastFrameLevel */ + Word16 currentFrameLevel_e); /* exponent of currentFrameLevel */ + +/*-----------------------------------------------------------------------------------* + * PLC: [ACELP: innovative codebook] + * PLC: genPlcFiltBWAdapt : deriuve filter coefficients for filtering + the first pitch cycle, bitrate dependent + *-----------------------------------------------------------------------------------*/ + +void genPlcFiltBWAdap( + Word32 const sr_core, /*Qold) */ + Word16 *old_exc, /* i: input excitation in Q(st->Qold) */ + Word16 L_frame /* i: input frame length */ +); + +void encoderSideLossSimulation( + Encoder_State_fx *st, + HANDLE_PLC_ENC_EVS hPlc_Ext, + Word16 *isf_q, /* Q1*1.28 */ + Word16 stab_fac, /* Q15 */ + Word8 calcOnlyISF, + const Word16 L_frame +); + +void enc_prm_side_Info( HANDLE_PLC_ENC_EVS hPlc_Ext, Encoder_State_fx *st ); + +void GplcTcxEncSetup(Encoder_State_fx *st, + HANDLE_PLC_ENC_EVS hPlc_Ext, + Word16 Q_new); +Word16 encSideSpecPowDiffuseDetector( + Word16 *isf_ref, + Word16 *isf_con, + Word32 sr_core, + Word16 *prev_isf4_mean, + Word8 sw + , Word16 coder_type +); + +void updateSpecPowDiffuseIdx( Encoder_State_fx *st); + +void blend_subfr2( + Word16 *sigIn1, /* i : input signal for fade-out */ + Word16 *sigIn2, /* i : input signal for fade-in */ + Word16 *sigOut /* o : output signal */ +); + + +void BASOP_cfft(cmplx *pComplexBuf, Word16 sizeOfFft, Word16 *scale, Word32 workBuffer[2*BASOP_CFFT_MAX_LENGTH]); +void BASOP_cfft16(Word16 *re, Word16 *im, Word16 sizeOfFft, Word16 s, Word16 *scale); +void BASOP_rfft(Word32 *x, Word16 sizeOfFft, Word16 *scale, Word16 isign); +void BASOP_rfft16(Word16 *x, Word16 sizeOfFft, Word16 *scale, Word16 isign); + +void open_PLC_ENC_EVS( + HANDLE_PLC_ENC_EVS hPlcExt, + Word32 sampleRate +); + +void gPLC_encInfo ( + HANDLE_PLC_ENC_EVS self, + Word32 modeBitrate, + Word16 modeBandwidth, + Word16 old_clas, + Word16 acelp_ext_mode +); + +void v_sort(Word16 *r, const Word16 lo, const Word16 up); + +void coder_acelp_rf( + ACELP_config *acelp_cfg_rf, /*input/output: configuration of the ACELP coding*/ + const Word16 coder_type, /* input: coding type */ + const Word16 A[], /* input: coefficients 4xAz[M+1] */ + const Word16 Aq[], /* input: coefficients 4xAz_q[M+1] */ + Word16 speech[], /* input: speech[-M..lg] */ + const Word16 voicing[], /* input: open-loop LTP gain */ + const Word16 T_op[], /* input: open-loop LTP lag */ + Word16 stab_fac, + Encoder_State_fx *st, + Word16 target_bits, /* i/o : coder memory state */ + const Word16 rf_frame_type, /* i : rf_frame_type */ + Word16 *exc_rf, /* i/o: pointer to RF excitation */ + Word16 *syn_rf, /* i/o: pointer to RF synthesis */ + Word16 Q_new, + Word16 shift +); + + +#endif /*PROT_COM_FX_H */ diff --git a/lib_com/pvq_com_fx.c b/lib_com/pvq_com_fx.c new file mode 100644 index 0000000..69b5518 --- /dev/null +++ b/lib_com/pvq_com_fx.c @@ -0,0 +1,753 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ + +#include "prot_fx.h" /* Function prototypes */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" /* required for wmc_tool */ + + +#include "options.h" + + +UWord32 intLimCDivPos_fx( + UWord32 NUM, + Word16 DEN +) +{ + UWord32 UL_ru, UL_rl; + Mpy_32_32_uu(UL_lshl(NUM, 1), intLimCDivInvDQ31[DEN], &UL_ru, &UL_rl); + return UL_ru; +} + + +Word32 intLimCDivSigned_fx( + Word32 NUM, + Word16 DEN) +{ + Word32 L_tmp; + + L_tmp = intLimCDivPos_fx( L_abs(NUM) , DEN); + if (NUM < 0) + { + L_tmp= L_negate(L_tmp); /* one op */ + } + return L_tmp; +} + + +Word16 shrtCDivSignedApprox( const Word16 num, + const Word16 den + ) +{ + Word16 pool_part; + + pool_part = extract_h( L_mult( negate(abs_s(num)), lim_neg_inv_tbl_fx[den] )); + /* neg_in always, positive out always, so that positive truncation(rounding) is used */ + if ( num < 0 ) + { + pool_part = negate(pool_part); /* make negative, one op */ + } + return pool_part; +} + +void nearProjQ15_fx( + Word16 x, + Word16 *result +) +{ + const Word16 a[4] = {14967, -25518, 3415, 32351}; + Word32 b; + UWord16 lsb; + + b = L_deposit_l(a[0]); + b = L_shl((Word32)add(a[1], extract_h(L_mult0((Word16)b, x))), 1); + Mpy_32_16_ss(b, x, &b, &lsb); + b = L_add((Word32)a[2], b); + Mpy_32_16_ss(b, x, &b, &lsb); + b = L_add((Word32)a[3], b); + *result = extract_l(b); + return ; +} + +/*-------------------------------------------------------------------* + * obtainEnergyQuantizerDensity_fx() + * + * + *-------------------------------------------------------------------*/ +void obtainEnergyQuantizerDensity_fx( + const Word16 L, + const Word16 R, + Word16 *Density ) +{ + Word16 Rnrg, den, n; + + den = sub(shl(L, 1), 1); + IF( den <= 67 ) + { + Rnrg = extract_l(intLimCDivPos_fx( L_deposit_l(R) , den)); + } + ELSE + { + n = norm_s(den); + Rnrg = shr(div_s(R, shl(den, n)), sub(15, n)); + } + Rnrg = add(Rnrg, 28); + + Rnrg = s_min(Rnrg, 56); + Rnrg = s_min(Rnrg, sub(R, 96)); + + Rnrg = s_max(Rnrg, 3); + *Density = obtainEnergyQuantizerDensity_f[Rnrg]; + return; +} + + +/*-------------------------------------------------------------------* + * dsDirac2Dirac_fx() + * + * + *-------------------------------------------------------------------*/ +void dsDirac2Dirac_fx( + const Word16 dsDiracIndex, + Word16 *diracs +) +{ + *diracs = dsDiracsTab[dsDiracIndex]; + return; +} + +void dsDiracPerQuanta_fx( + const Word16 td, + const Word16 t_quanta, + const Word16 dsm, + const unsigned char* const *frQuanta, + Word16 *DsIdx +) +{ + const unsigned char *sv; + Word16 nsv; + Word16 t_quanta_o; + Word16 dsIndex; + Word16 i; + + sv = frQuanta[td]; + nsv = sv[0]; + + t_quanta_o = sub(t_quanta, QUANTAQ3OFFSET); + + IF (GE_16(t_quanta_o, sv[nsv])) + { + *DsIdx = nsv; + move16(); + return ; + } + + IF (LE_16(t_quanta_o, sv[1])) + { + *DsIdx = 1; + move16(); + return ; + } + + + dsIndex = shl(1, frQuanta[0][td]); + if (GT_16(t_quanta_o, sv[shr(nsv, 1) ])) + { + dsIndex = sub(nsv, dsIndex ); + } + FOR (i = sub(frQuanta[0][td], 1); i >= 0; i--) + { + dsIndex = add(dsIndex, shl(sub(shl(lshr(sub(sv[dsIndex], t_quanta_o), 15), 1), 1), i)); + } + + dsIndex = add(dsIndex, lshr(sub(sv[dsIndex], t_quanta_o), 15)); + dsIndex = sub(dsIndex, lshr(sub(1, dsIndex), 15)); + + IF (dsm > 0) + { + *DsIdx=dsIndex; + move16(); + return; + } + *DsIdx = add(dsIndex, lshr(sub(add(sv[add(dsIndex,1)], sv[dsIndex]), shl(t_quanta_o, 1)), 15)); + return; +} + +void QuantaPerDsDirac_fx( + Word16 td, + Word16 dsDiracIndex, + const unsigned char* const* dimFrQuanta, + Word16 *Quanta +) +{ + *Quanta = dimFrQuanta[td][dsDiracIndex]; + move16(); + if(dsDiracIndex == 0) + { + *Quanta = -1; /* single op */ move16(); + } + *Quanta = add(*Quanta, QUANTAQ3OFFSET); + return ; +} + +void conservativeL1Norm_fx( + Word16 L, + Word16 Qvec, + Word16 Fcons, + Word16 Qavail, + Word16 Qreserv, + Word16 Dspec, + Word16 *Dvec, + Word16 *Qspare, + Word16 *Qreservplus, + Word16 *Dspecplus +) +{ + + Word16 Minit, Mprime; + Word16 Qtestminus; + const unsigned char *frQuantaL; + + frQuantaL = hBitsN[L]; + + *Qreservplus = add(Qreserv, sub(Qvec, QUANTAQ3OFFSET)); + + dsDiracPerQuanta_fx(L, Qvec, Fcons, hBitsN, &Minit); + + Mprime = Minit; + move16(); + DO + { + Qtestminus = (short)frQuantaL[Mprime]; + move16(); + *Qspare = sub(Qavail, Qtestminus); + Mprime = sub(Mprime, 1); + } + WHILE ( (Mprime >= 0) && LT_16(*Qspare, QUANTAQ3OFFSET )); + + if(Mprime < 0) + { + *Qspare = add(Qavail, QUANTAQ3OFFSET); /* single op */ + } + dsDirac2Dirac_fx(add(Mprime, 1), Dvec); + + *Dspecplus = add(Dspec, *Dvec); + *Qreservplus = sub(*Qreservplus, (short)frQuantaL[Minit]); + *Qspare = sub(*Qspare, QUANTAQ3OFFSET); + + return; +} + + + + + +void bandBitsAdjustment_fx( + Word16 Brc, + UWord32 INTrc, + Word16 Bavail, + Word16 Nbands, + Word16 D, + Word16 L, + Word16 Bband, + Word16 Breserv, + Word16 *Bband_adj, + Word16 *Brem, + Word16 *Breservplus) +{ + Word16 Btemp; + Word16 Bff; + Word32 L_tmp; + + rangeCoderFinalizationFBits_fx(Brc, INTrc, &Bff); + + IF(LT_16(D, Nbands)) + { + L_tmp = L_deposit_l(sub(Breserv, Bff)); + Btemp = extract_l(intLimCDivSigned_fx(L_tmp, s_min(D, 3))); /* result always fits in Word16 */ + *Breservplus = add(Bband, Breserv); + } + ELSE + { + Btemp = 0; + move16(); + *Breservplus = add(Bband, Bff); + } + *Bband_adj = s_min(extract_l(L_mult(L, 40)), Bband); + *Brem = sub(Bavail, Bff); + *Bband_adj = s_min(*Brem, add(*Bband_adj, Btemp)); + *Bband_adj = s_max(0, *Bband_adj); +} + + + +static Word16 Ratio_base2Q11_fx( /* o : Q11 */ + const Word16 opp, /* i : Q15 */ + const Word16 near /* i : Q15 */ +) +{ + Word16 mc, nc, ms, ns, d, z; + Word16 result; + Word32 acc; + + ns = norm_s(opp ); /* exponent */ + nc = norm_s(near ); /* exponent */ + + ms = shl(opp, ns); /* mantissa */ + mc = shl(near, nc); /* mantissa */ + + acc = L_mac(538500224L, mc, -2776); /* a0*mc + a1, acc(Q27), a0(Q11), a1(Q27) */ + z = mac_r(acc, ms, -2776); /* z in Q11, a0 in Q11 */ + d = sub(ms, mc); /* d in Q15 */ + z = mult_r(z, d); /* z in Q11 */ + + result = add(z, shl(sub(nc, ns), 11)); + + return result; +} + +void Ratio_rQ3_fx( + Word16 opp, + Word16 near, + Word16 *result +) +{ + Word16 tmp; + + tmp = add(1<<7 , Ratio_base2Q11_fx(opp, near)); + *result = shr(tmp, 8); + return ; +} + + +void densityAngle2RmsProjDec_fx( + Word16 D, + Word16 indexphi, + Word16 *oppQ15, + Word16 *nearQ15, + Word16 *oppRatioQ3 +) +{ + Word16 phiQ14q; + Word16 oppTail, nearTail; + + phiQ14q = (Word16)intLimCDivPos_fx(L_shl(L_deposit_l(indexphi), 13), shr(D, 1)); + if (indexphi < 0) + { + phiQ14q = 1 << 13; /* one op */ move16(); + } + + oppTail = shr(sub(16320, phiQ14q), 15); + nearTail = shr(sub(phiQ14q, 64), 15); + + IF (s_or(oppTail, nearTail) < 0) + { + *oppQ15 = s_and(oppTail, (1 << 15) - 1); + *nearQ15 = s_and(nearTail, (1 << 15) - 1); + *oppRatioQ3 = shl(add(1, shl(nearTail, 1)), 14); + } + ELSE + { + nearProjQ15_fx( shl(sub(1 << 14, phiQ14q), 1), oppQ15); + nearProjQ15_fx(shl(phiQ14q, 1), nearQ15); + Ratio_rQ3_fx(*oppQ15, *nearQ15, oppRatioQ3); + } + + return; +} + +void densityAngle2RmsProjEnc_fx( + Word16 D, + Word16 phiQ14uq, + Word16 *indexphi, + Word16 *oppQ15, + Word16 *nearQ15, + Word16 *oppRatioQ3 +) +{ + *indexphi = mult_r(shl(D, 1), phiQ14uq); + if (s_and(D, 1) > 0) + { + *indexphi = -1; /* one op */ move16(); + } + densityAngle2RmsProjDec_fx(D, *indexphi, oppQ15, nearQ15, oppRatioQ3); + + return; +} + +void NearOppSplitAdjustment_fx( + const Word16 qband, + const Word16 qzero, + const Word16 Qac, + const UWord32 INTac, + const Word16 qglobal, + const Word16 FlagCons, + const Word16 Np, + const Word16 Nhead, + const Word16 Ntail, + const Word16 Nnear, + const Word16 Nopp, + Word16 oppRQ3, + Word16 *qnear, + Word16 *qopp, + Word16 *qglobalupd +) +{ + + Word16 qac, qboth, qskew, qavg, qmin, Midx; + Word32 L_QIb, L_qnum; + Word16 QIb, QIa; + + rangeCoderFinalizationFBits_fx(Qac, INTac, &qac); + qboth = sub(qband, sub(qac, qzero)); + /* skew calc code */ + qskew = 0 ; + move16(); + IF (GT_16(Nhead, 1)) + { + qavg = extract_h(L_shl(intLimCDivSigned_fx((Word32)qboth, Np),16)); /* qboth may be negative */ + dsDiracPerQuanta_fx(Ntail, qavg, FlagCons, hBitsN, &Midx ); + QuantaPerDsDirac_fx(Nhead, Midx, hBitsN, &qmin); + qskew = sub(qavg, qmin); + qskew = s_max(0, qskew); + } /* end of skew calc code*/ + + QIa = add(extract_l(intLimCDivPos_fx((UWord32)L_deposit_l(Nopp), Nnear)), 1); /* always positive Word16 out */ + L_qnum = L_sub( L_deposit_l(sub(sub(add(qband, qzero), qac), qskew)), L_mult0(Nopp, oppRQ3)); + + L_QIb = L_deposit_l(0); + IF (L_qnum > 0) + { + L_QIb = (Word32) intLimCDivPos_fx(L_qnum, QIa); + } + *qnear = qboth; + QIb = extract_h(L_shl(L_QIb, 16)); /* may saturate */ + if (LE_16(QIb, qboth)) + { + *qnear = QIb; + } + *qopp = sub(qboth, *qnear); + *qglobalupd = sub(qglobal, sub(qac, qzero)); + + return; +} + + +/*--------------------------------------------------------------------------* + * apply_gain() + * + * Apply gain + *--------------------------------------------------------------------------*/ + +void apply_gain_fx( + const Word16 *ord, /* i : Indices for energy order */ + const Word16 *band_start, /* i : Sub band start indices */ + const Word16 *band_end, /* i : Sub band end indices */ + const Word16 num_sfm, /* i : Number of bands */ + const Word16 *gains, /* i : Band gain vector Q12 */ + Word16 *xq /* i/o: Float synthesis / Gain adjusted synth Q15/Q12 */ +) +{ + Word16 band,i; + Word16 g; /* Q12 */ + + FOR ( band = 0; band < num_sfm; band++) + { + g = gains[ord[band]]; + + FOR( i = band_start[band]; i < band_end[band]; i++) + { + /*xq[i] *= g; */ + xq[i] = mult_r(g, xq[i]); + move16(); /*12+15+1-16=12 */ + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * fine_gain_quant() + * + * Fine gain quantization + *--------------------------------------------------------------------------*/ + +void fine_gain_quant_fx( + Encoder_State_fx *st_fx, + const Word16 *ord, /* i : Indices for energy order */ + const Word16 num_sfm, /* i : Number of bands */ + const Word16 *gain_bits, /* i : Gain adjustment bits per sub band */ + Word16 *fg_pred, /* i/o: Predicted gains / Corrected gains Q12 */ + const Word16 *gopt /* i : Optimal gains Q12 */ +) +{ + Word16 band; + Word16 gbits; + Word16 idx; + Word16 gain_db,gain_dbq; + Word16 err; + + Word16 tmp1, tmp2, exp1, exp2; + Word32 L_tmp; + UWord16 lsb; + + FOR ( band = 0; band < num_sfm; band++) + { + gbits = gain_bits[ord[band]]; + test(); + IF ( fg_pred[band] != 0 && gbits > 0 ) + { + exp1 = norm_s(gopt[band]); + exp1 = sub(exp1, 1); + tmp1 = shl(gopt[band], exp1); + exp2 = norm_s(fg_pred[band]); + tmp2 = shl(fg_pred[band], exp2); + exp1 = add(15, sub(exp1, exp2)); + err = div_s(tmp1, tmp2); + tmp1 = norm_s(err); + exp2 = Log2_norm_lc(L_deposit_h(shl(err, tmp1))); + tmp1 = sub(14, tmp1); + tmp1 = sub(tmp1, exp1); + L_tmp = L_Comp(tmp1, exp2); + Mpy_32_16_ss(L_tmp, 24660, &L_tmp, &lsb); /* 24660 = 20*log10(2) in Q12 */ /*16+12-15=13 */ + gain_db = round_fx(L_shl(L_tmp, 17)); + + idx = squant_fx(gain_db, &gain_dbq, finegain_fx[gbits-1], gain_cb_size[gbits-1]); + push_indice_fx( st_fx, IND_PVQ_FINE_GAIN, idx, gbits ); + + L_tmp = L_mult0(gain_dbq, 21771); /* 21771=0.05*log2(10) */ /* 14+17=31 */ + L_tmp = L_shr(L_tmp, 15); + tmp1 = L_Extract_lc(L_tmp, &exp1); + tmp1 = abs_s(tmp1); + tmp1 = extract_l(Pow2(14, tmp1)); + exp1 = sub(14, exp1); + + L_tmp = L_mult0(fg_pred[band], tmp1); /*12+exp1 */ + fg_pred[band] = round_fx(L_shl(L_tmp, sub(16, exp1))); /*12+exp1+16-exp1-16=12 */ + } + } + + return; +} + +/*-------------------------------------------------------------------* + * srt_vec_ind() + * + * sort vector and save sorting indeces + *-------------------------------------------------------------------*/ + +void srt_vec_ind16_fx ( + const Word16 *linear, /* linear input */ + Word16 *srt, /* sorted output*/ + Word16 *I, /* index for sorted output */ + Word16 length +) +{ + Word16 pos,npos; + Word16 idxMem; + Word16 valMem; + + /*initilize */ + FOR (pos = 0; pos < length; pos++) + { + I[pos] = pos; + move16(); + } + + Copy(linear, srt,length); + + /* now iterate */ + FOR (pos = 0; pos < (length - 1); pos++) + { + FOR (npos = (pos + 1); npos < length; npos++) + { + IF (LT_16(srt[npos], srt[pos])) + { + idxMem = I[pos]; + move16(); + I[pos] = I[npos]; + move16(); + I[npos] = idxMem; + move16(); + + valMem = srt[pos]; + move16(); + srt[pos] = srt[npos]; + move16(); + srt[npos] = valMem; + move16(); + } + } + } + + return; +} + +/*----------------------------------------------------------------------------- + * atan2_fx(): + * + * Approximates arctan piecewise with various 4th to 5th order least square fit + * polynomials for input in 5 segments: + * - 0.0 to 1.0 + * - 1.0 to 2.0 + * - 2.0 to 4.0 + * - 4.0 to 8.0 + * - 8.0 to infinity + *---------------------------------------------------------------------------*/ +Word16 atan2_fx( /* o: Angle between 0 and PI/2 radian (Q14) */ + const Word32 y, /* i: Argument must be positive (Q15) */ + const Word32 x /* i: Q15 */ +) +{ + Word32 acc, arg; + Word16 man, expo, reciprocal; + Word16 angle, w, z; + + IF (x == 0) + { + return 25736; /* PI/2 in Q14 */ + } + man = ratio(y, x, &expo); /* man in Q14 */ + expo = sub(expo, (15 - 14)); /* Now, man is considered in Q15 */ + arg = L_shr((Word32)man, expo); + + IF (L_shr(arg, 3+15) != 0) + /*===============================* + * 8.0 <= x < infinity * + *===============================*/ + { + /* atan(x) = PI/2 - 1/x + 1/(3x^3) - 1/(5x^5) + ... + * ~ PI/2 - 1/x, for x >= 8. + */ + expo = norm_l(arg); + man = extract_h(L_shl(arg, expo)); + reciprocal = div_s(0x3fff, man); + expo = sub(15 + 1, expo); + reciprocal = shr(reciprocal, expo); /* Q14 */ + angle = sub(25736, reciprocal); /* Q14 (PI/2 - 1/x) */ + + /* For 8.0 <= x < 10.0, 1/(5x^5) is not completely negligible. + * For more accurate result, add very small correction term. + */ + if (LT_32(L_shr(arg, 15), 10L)) + { + angle = add(angle, 8); /* Add tiny correction term. */ + } + } + ELSE IF (L_shr(arg, 2+15) != 0) + /*==========================* + * 4.0 <= x < 8.0 * + *==========================*/ + { + /* interval: [3.999, 8.001] + * atan(x) ~ (((a0*x + a1)*x + a2)*x + a3)*x + a4 + * = (((a0*8*y + a1)*8*y + a2)*8*y + a3)*8*y + a4 Substitute 8*y -> x + * = (((a0*8^3*y + a1*8^2)*y + a2*8)*y + a3)*8*y + a4 + * = ((( c0*y + c1)*y + c2)*y + c3)*8*y + c4, + * where y = x/8 + * and a0 = -1.28820869667651e-04, a1 = 3.88263533346295e-03, + * a2 = -4.64216306484597e-02, a3 = 2.75986060068931e-01, + * a4 = 7.49208077809799e-01. + */ + w = extract_l(L_shr(arg, 3)); /* Q15 y = x/8 */ + acc = L_add(533625337L, 0); /* Q31 c1 = a1*8^2 */ + z = mac_r(acc, w, -2161); /* Q15 c0 = a0*8^3 */ + acc = L_add(-797517542L, 0); /* Q31 c2 = a2*8 */ + z = mac_r(acc, w, z); /* Q15 */ + acc = L_add(592675551L, 0); /* Q31 c3 = a3 */ + z = mac_r(acc, w, z); /* z (in:Q15, out:Q12) */ + acc = L_add(201114012L, 0); /* Q28 c4 = a4 */ + acc = L_mac(acc, w, z); /* Q28 */ + angle = extract_l(L_shr(acc, (28 - 14))); /* Q14 result of atan(x), where 4 <= x < 8 */ + } + ELSE IF (L_shr(arg, 1+15) != 0) + /*==========================* + * 2.0 <= x < 4.0 * + *==========================*/ + { + /* interval: [1.999, 4.001] + * atan(x) ~ (((a0*x + a1)*x + a2)*x + a3)*x + a4 + * = (((a0*4*y + a1)*4*y + a2)*4*y + a3)*4*y + a4 Substitute 4*y -> x + * = (((a0*16*y + a1*4)*y + a2)*4*y + a3)*4*y + a4 + * = (((a0*32*y + a1*8)*y + a2*2)*2*y + a3)*4*y + a4 + * = ((( c0*y + c1)*y + c2)*2*y + c3)*4*y + c4, + * where y = x/4 + * and a0 = -0.00262378195660943, a1 = 0.04089687039888652, + * a2 = -0.25631148958325911, a3 = 0.81685854627399479, + * a4 = 0.21358070563097167 + * */ + w = extract_l(L_shr(arg, 2)); /* Q15 y = x/4 */ + acc = L_add(702602883L, 0); /* Q31 c1 = a1*8 */ + z = mac_r(acc, w, -2751); /* Q15 c0 = a0*32 */ + acc = L_add(-1100849465L, 0); /* Q31 c2 = a2*2 */ + z = mac_r(acc, w, z); /* z (in:Q15, out:Q14) */ + acc = L_add(877095185L, 0); /* Q30 c3 = a3 */ + z = mac_r(acc, w, z); /* z (in:Q14, out:Q12) */ + acc = L_add(57332634L, 0); /* Q28 c4 = a4 */ + acc = L_mac(acc, w, z); /* Q28 */ + angle = extract_l(L_shr(acc, (28 - 14))); /* Q14 result of atan(x) where 2 <= x < 4 */ + } + ELSE IF (L_shr(arg, 15) != 0) + /*==========================* + * 1.0 <= x < 2.0 * + *==========================*/ + { + /* interval: [0.999, 2.001] + * atan(x) ~ (((a0*x + 1)*x + a2)*x + a3)*x + a4 + * = (((a0*2*y + a1)*2*y + a2)*2*y + a3)*2*y + a4 Substitute 2*y -> x + * = (((a0*4*y + a1*2)*y + a2)*2*y + a3)*2*y + a4 + * = (((a0*4*y + a1*2)*y + a2)*y + a3/2)*4*y + a4 + * = ((( c0*y + c1)*y + c2)*y + c3)*4*y + c4, + * where y = x/2 + * and a0 = -0.0160706457245251, a1 = 0.1527106504065224, + * a2 = -0.6123208404800871, a3 = 1.3307896976322915, + * a4 = -0.0697089375247448 + */ + w = extract_l(L_shr(arg, 1)); /* Q15 y= x/2 */ + acc = L_add(655887249L, 0); /* Q31 c1 = a1*2 */ + z = mac_r(acc, w, -2106); /* Q15 c0 = a0*4 */ + acc = L_add(-1314948992L, 0); /* Q31 c2 = a2 */ + z = mac_r(acc, w, z); + acc = L_add(1428924557L, 0); /* Q31 c3 = a3/2 */ + z = mac_r(acc, w, z); /* z (in:Q15, out:Q13) */ + acc = L_add(-37424701L, 0); /* Q29 c4 = a4 */ + acc = L_mac(acc, w, z); /* Q29 */ + angle = extract_l(L_shr(acc, (29 - 14))); /* Q14 result of atan(x) where 1 <= x < 2 */ + } + ELSE + /*==========================* + * 0.0 <= x < 1.0 * + *==========================*/ + { + /* interval: [-0.001, 1.001] + * atan(x) ~ ((((a0*x + a1)*x + a2)*x + a3)*x + a4)*x + a5 + * = ((((a0*2*x + a1*2)*x/2 + a2)*x + a3)*x + a4)*x + a5 + * = (((( c0*x + c1)*x/2 + c2)*x + c3)*x + c4)*x + c5 + * where + * a0 = -5.41182677118661e-02, a1 = 2.76690449232515e-01, + * a2 = -4.63358392562492e-01, a3 = 2.87188466598566e-02, + * a4 = 9.97438122814383e-01, a5 = 5.36158556179092e-05. + */ + w = extract_l(arg); /* Q15 */ + acc = L_add(1188376431L, 0); /* Q31 c1 = a1*2 */ + z = mac_r(acc, w, -3547); /* Q15 c0 = a0*2 */ + acc = L_add(-995054571L, 0); /* Q31 c2 = a2 */ + z = extract_h(L_mac0(acc, w, z)); /* Q15 non-fractional mode multiply */ + acc = L_add(61673254L, 0); /* Q31 c3 = a3 */ + z = mac_r(acc, w, z); + acc = L_add(2141982059L, 0); /* Q31 c4 = a4 */ + z = mac_r(acc, w, z); + acc = L_add(115139L, 0); /* Q31 c5 = a5 */ + acc = L_mac(acc, w, z); /* Q31 */ + angle = extract_l(L_shr(acc, 31 - 14)); /* Q14 result of atan(x), where 0 <= x < 1 */ + } + + return angle; /* Q14 between 0 and PI/2 radian. */ +} + + + diff --git a/lib_com/range_com_fx.c b/lib_com/range_com_fx.c new file mode 100644 index 0000000..1e7aa09 --- /dev/null +++ b/lib_com/range_com_fx.c @@ -0,0 +1,62 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required for wmc_tool */ + + +/*-------------------------------------------------------------------* + * rc_get_bits2() + * + * Get number of bits needed to finalize range coder + *-------------------------------------------------------------------*/ + +Word16 rc_get_bits2_fx( /* o: Number of bits needed */ + const Word16 N, /* i: Number of bits currently used */ + const UWord32 range /* i: Range of range coder */ +) +{ + return add(add(N, 2), norm_ul(range)); +} + +void rangeCoderFinalizationFBits_fx( + Word16 Brc, + UWord32 INTrc, + Word16 *FBits +) +{ + Word32 L_Bq15; + UWord32 h, UL_tmp; + UWord16 Bq15ui16, l; + Word16 B, E, x, k; + *FBits = shl(add(Brc, 32), 3); + + B = sub(30, norm_ul(INTrc)); + x = sub(B, RCF_INIT_SHIFT ); + L_Bq15 = 0; + move16(); + if (x >= 0) + { + L_Bq15 = (Word32)UL_lshr(INTrc, x); + } + + E = 2; + move16(); + FOR(k = 1; k < 4; k++) + { + Bq15ui16 = u_extract_l(L_shr(L_Bq15, s_and(E, 1))); + UL_tmp = UL_lshl(UL_deposit_l(Bq15ui16), 1); + Mpy_32_16_uu(UL_tmp, Bq15ui16, &h , &l); + L_Bq15 = (Word32) h; + E = add(shl(B, 1), extract_l(L_lshr(L_sub(((1L << 16) - 1L), L_Bq15), 31))); + B = E; + move16(); + } + *FBits = sub(*FBits, B); + return; +} + diff --git a/lib_com/re8_ppv_fx.c b/lib_com/re8_ppv_fx.c new file mode 100644 index 0000000..873ff54 --- /dev/null +++ b/lib_com/re8_ppv_fx.c @@ -0,0 +1,193 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * Prototypes + *-------------------------------------------------------------------*/ + +static void nearest_neighbor_2D8_fx( const Word32 x[], Word16 y[] ); +static Word32 compute_error_2D8_fx( const Word32 x[], const Word16 y[] ); + +/*--------------------------------------------------------------* + * RE8_PPV: + * + * NEAREST NEIGHBOR SEARCH IN INFINITE LATTICE RE8 + * the algorithm is based on the definition of RE8 as + * RE8 = (2D8) U (2D8+[1,1,1,1,1,1,1,1]) + * it applies the coset decoding of Sloane and Conway + * --------------------------------------------------------------*/ + +void re8_PPV_fx( + const Word32 x[], /* i : point in R^8Q15 */ + Word16 y[] /* o : point in RE8 (8-dimensional integer vector) */ +) +{ + Word16 i, y0[8]; + Word32 e0, e1, x1[8]; + + /*--------------------------------------------------------------* + * find the nearest neighbor y0 of x in 2D8 + *--------------------------------------------------------------*/ + nearest_neighbor_2D8_fx( x, y0 ); + + /*--------------------------------------------------------------* + * find the nearest neighbor y1 of x in 2D8+(1,...,1) (by coset decoding) + *--------------------------------------------------------------*/ + + FOR( i=0; i<8; i++ ) + { + x1[i] = L_sub(x[i], QR); + move32(); + } + nearest_neighbor_2D8_fx( x1, y ); + + FOR ( i = 0; i < 8; i++ ) + { + y[i] = add(y[i], 1); + move16(); + } + + /*--------------------------------------------------------------* + * compute e0=||x-y0||^2 and e1=||x-y1||^2 + *--------------------------------------------------------------*/ + + e0 = compute_error_2D8_fx( x, y0 ); + e1 = compute_error_2D8_fx( x, y ); + + + /*--------------------------------------------------------------* + * select best candidate y0 or y1 to minimize distortion + *--------------------------------------------------------------*/ + IF( LT_32(e0, e1)) + { + Copy( y0, y, 8 ); + } + + return; +} + + +/*--------------------------------------------------------------* + * Nearest_neighbor_2D8(x,y) + * + * NEAREST NEIGHBOR SEARCH IN INFINITE LATTICE 2D8 + * algorithm: nn_2D8(x) = 2*nn_D8(x/2) + * nn_D8 = decoding of Z^8 with Wagner rule + * (see Conway and Sloane's paper in IT-82) + --------------------------------------------------------------*/ + +static void nearest_neighbor_2D8_fx( + const Word32 x[], /* i : point in R^8 */ + Word16 y[] /* o : point in 2D8 (8-dimensional integer vector) */ +) +{ + Word16 i,j; + Word16 sum, tmp16, tmp16b; + Word32 s, e, em; + + /*--------------------------------------------------------------* + * round x into 2Z^8 i.e. compute y=(y1,...,y8) such that yi = 2[xi/2] + * where [.] is the nearest integer operator + * in the mean time, compute sum = y1+...+y8 + *--------------------------------------------------------------*/ + sum = 0; + move16(); + + FOR( i=0; i<8; i++ ) + { + /* round to ..., -2, 0, 2, ... ([-1..1[ --> 0) */ + tmp16 = round_fx(L_add(x[i], L_shr(x[i], 31))); + y[i] = shl(tmp16, 1); + move16(); + /* sum += y[i] */ + sum = add(sum, y[i]); + } + + /*--------------------------------------------------------------* + * check if y1+...+y8 is a multiple of 4 + * if not, y is not round xj in the wrong way where j is defined by + * j = arg max_i | xi -yi| + * (this is called the Wagner rule) + *--------------------------------------------------------------*/ + IF( s_and(sum, 2) != 0 ) + { + /* find j = arg max_i | xi -yi| */ + em = L_deposit_l(0); + j = 0; + move16(); + + FOR( i=0; i<8; i++ ) + { + /* compute ei = xi-yi */ + /* e[i]=x[i]-y[i] */ + e = L_msu(x[i], y[i], QR/2); + + /* compute |ei| = | xi-yi | */ + s = L_abs(e); + + /* check if |ei| is maximal, if so, set j=i */ + if( LT_32(em, s)) + { + j = i; + move16(); + } + em = L_max(s, em); + } + + /* round xj in the "wrong way" */ + e = L_msu(x[j], y[j], QR/2); + tmp16 = extract_h(e); + tmp16b = add(y[j], 2); + + if( tmp16 < 0 ) + { + tmp16b = sub(tmp16b, 2+2); + } + y[j] = tmp16b; + move16(); + } + + return; +} + + +/*--------------------------------------------------------------* + * Compute_error_2D8(x,y) + * + * Compute mean square error between input vector and + * (quantized) point in 2D8. + --------------------------------------------------------------*/ + +static Word32 compute_error_2D8_fx( /* o : mean squared error */ + const Word32 x[], /* i : input vector */ + const Word16 y[] /* i : point in 2D8 (8-dimensional integer vector) */ +) +{ + Word16 i, hi, lo; + Word32 err, Ltmp; + + err = L_deposit_l(0); + FOR( i=0; i<8; i++ ) + { + /*tmp = x[i]-y[i];*/ + Ltmp = L_msu(x[i], y[i], 16384); + hi = extract_h(L_shl(Ltmp, 1)); + lo = extract_l(L_msu(Ltmp, hi, 16384)); + + Ltmp = L_mult(hi, hi); + Ltmp = L_shl(Ltmp, 14); + Ltmp = L_mac(Ltmp, hi, lo); + Ltmp = L_mac0(Ltmp, mult(lo, lo), 1); + + /* err+=tmp*tmp */ + err = L_add(Ltmp, err); + } + + return( err ); +} diff --git a/lib_com/re8_util_fx.c b/lib_com/re8_util_fx.c new file mode 100644 index 0000000..b67c73f --- /dev/null +++ b/lib_com/re8_util_fx.c @@ -0,0 +1,387 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + + +/*-------------------------------------------------------------------* + * Prototypes + *-------------------------------------------------------------------*/ + +static Word16 re8_identify_absolute_leader_fx( const Word16 y[] ); +static void re8_coord_fx( const Word16 *y, Word16 *k) ; + + +/*----------------------------------------------------------------* + * re8_vor_fx() + * + * MULTI-RATE RE8 INDEXING BY VORONOI EXTENSION + *----------------------------------------------------------------*/ +void re8_vor_fx( + const Word16 y[], /* i : point in RE8 (8-dimensional integer vector) */ + Word16 *n, /* o : codebook number n=0,2,3,4,... (scalar integer) */ + Word16 k[], /* o : Voronoi index (integer vector of dimension 8) used only if n>4*/ + Word16 c[], /* o : codevector in Q0, Q2, Q3, or Q4 if n<=4, y=c */ + Word16 *ka /* o : identifier of absolute leader (to index c) */ +) +{ + Word16 i, r, iter, ka_tmp, n_tmp, mask; + Word16 k_tmp[8], v[8], c_tmp[8], k_mod[8]; + Word32 Ltmp, Lsphere; + + /*----------------------------------------------------------------* + * verify if y is in Q0, Q2, Q3 or Q4 + * (a fast search is used here: + * the codebooks Q0, Q2, Q3 or Q4 are specified in terms of RE8 absolute leaders + * (see FORinstance Xie and Adoul's paper in ICASSP 96) + * - a unique code identifying the absolute leader related to y is computed + * in re8_identify_absolute_leader() + * this code is searched FORin a pre-defined list which specifies Q0, Q2, Q3 or Q4) + * the absolute leader is identified by ka + * - a translation table maps ka to the codebook number n) + *----------------------------------------------------------------*/ + *ka = re8_identify_absolute_leader_fx( y ); + move16(); + + /*----------------------------------------------------------------* + * compute codebook number n of Qn (by table look-up) + * at this stage, n=0,2,3,4 or out=100 + *----------------------------------------------------------------*/ + *n = Da_nq_fx[*ka]; + move16(); + + /*----------------------------------------------------------------* + * decompose y into : + * (if n<=4:) + * y = c where c is in Q0, Q2, Q3 or Q4 + * or + * (if n>4:) + * y = m c + v where c is in Q3 or Q4, v is a Voronoi codevector + * m=2^r (r integer >=2) + * + * in the latter case (if n>4), as a side-product, compute the (Voronoi) index k[] of v + * and replace n by n = n' + 2r where n' = 3 or 4 (c is in Qn') and r is defined above + *----------------------------------------------------------------*/ + + IF( LE_16(*n, 4)) + { + Copy( y, c, 8 ); + } + ELSE + { + /*------------------------------------------------------------* + * initialize r and m=2^r based on || y ||^2/8 + *------------------------------------------------------------*/ + Ltmp = L_mult(y[0], y[0]); + FOR( i = 1; i < 8; i++ ) + { + Ltmp = L_mac( Ltmp, y[i], y[i]); + } + + Lsphere = L_shr(Ltmp, 5+1); /* *0.125*0.25 / 2 to remove L_mac effect */ + + r = 1; + move16(); + FOR( ; Lsphere > 11; Lsphere >>= 2 ) + { + r = add(r, 1); + } + /*------------------------------------------------------------* + * compute the coordinates of y in the RE8 basis + *------------------------------------------------------------*/ + re8_coord_fx( y, k_mod ); + + /*------------------------------------------------------------* + * compute m and the mask needed for modulo m (for Voronoi coding) + *------------------------------------------------------------*/ + mask = sub(shl(1, r), 1); /* 0x0..011...1 */ + + /*------------------------------------------------------------* + * find the minimal value of r (or equivalently of m) in 2 iterations + *------------------------------------------------------------*/ + + FOR( iter=0; iter<2; iter++ ) + { + /*--------------------------------------------------------* + * compute v such that y is in m RE_8 +v (by Voronoi coding) + *--------------------------------------------------------*/ + FOR( i=0; i<8; i++ ) + { + k_tmp[i] = s_and( k_mod[i], mask); + move16(); + } + + re8_k2y_fx( k_tmp, r, v ); + + /*--------------------------------------------------------* + * compute c = (y-v)/m + * (y is in RE8, c is also in RE8 by definition of v) + *--------------------------------------------------------*/ + + FOR( i=0; i<8; i++ ) + { + c_tmp[i] = shr(sub(y[i], v[i]), r); + move16(); + } + + /*--------------------------------------------------------* + * verify if c_tmp is in Q2, Q3 or Q4 + *--------------------------------------------------------*/ + ka_tmp = re8_identify_absolute_leader_fx( c_tmp ); + + /*--------------------------------------------------------* + * at this stage, n_tmp=2,3,4 or out = 100 -- n=0 is not possible + *--------------------------------------------------------*/ + n_tmp = Da_nq_fx[ka_tmp]; + move16(); + + IF( GT_16(n_tmp, 4)) + { + /*--------------------------------------------------------* + * if c is not in Q2, Q3, or Q4 (i.e. n_tmp>4), use m = 2^(r+1) instead of 2^r + *--------------------------------------------------------*/ + r = add(r, 1); + mask = add(shl(mask, 1), 1); /* mask = m-1 <- this is less complex */ + } + ELSE + { + /*--------------------------------------------------------* + * c is in Q2, Q3, or Q4 -> the decomposition of y as y = m c + v is valid + * + * since Q2 is a subset of Q3, indicate n=3 instead of n=2 (this is because + * for n>4, n=n'+2r with n'=3 or 4, so n'=2 is not valid) + *--------------------------------------------------------*/ + n_tmp = s_max(n_tmp, 3); + + /*--------------------------------------------------------* + * save current values into ka, n, k and c + *--------------------------------------------------------*/ + *ka = ka_tmp; + move16(); + *n = add(n_tmp, shl(r, 1)); + move16(); + Copy( k_tmp, k, 8 ); + Copy( c_tmp, c, 8 ); + + /*--------------------------------------------------------* + * try m = 2^(r-1) instead of 2^r to be sure that m is minimal + *--------------------------------------------------------*/ + r = sub(r, 1); + mask = shr(mask, 1); + } + } + } + + return; +} + + +/*------------------------------------------------------------------------- + * re8_k2y_fx() + * + * VORONOI INDEXING (INDEX DECODING) k -> y + -------------------------------------------------------------------------*/ +void re8_k2y_fx( + const Word16 *k, /* i : Voronoi index k[0..7] */ + const Word16 m, /* i : Voronoi modulo (m = 2^r = 1<=2) */ + Word16 *y /* o : 8-dimensional point y[0..7] in RE8 */ +) +{ + Word16 i, v[8], *ptr1, *ptr2, m_tmp, mm; + Word32 ytp[8], z[8], Ltmp, Lsum ; + + /*---------------------------------------------------------------* + * compute y = k M and z=(y-a)/m, where + * M = [4 ] + * [2 2 ] + * [| \ ] + * [2 2 ] + * [1 1 _ 1 1] + * a=(2,0,...,0) + *---------------------------------------------------------------*/ + m_tmp = sub(15, m); + + Lsum = L_deposit_l(k[7]); + ytp[7] = Lsum; + move32(); + z[7] = L_shl(Lsum, m_tmp); + move32(); /* (int)(floor(y[7]*QR+0.5))>>m */ + + FOR( i=6; i>=1; i-- ) + { + Ltmp = L_deposit_l( shl(k[i],1) ); + Lsum = L_add (Lsum, Ltmp); + ytp[i] = L_add(ytp[7], Ltmp); + move32(); + z[i] = L_shl(ytp[i], m_tmp); + move32(); /* (int)(floor(y[7]*QR+0.5))>>m */ + } + + Lsum = L_add( Lsum, L_deposit_l(shl(k[0],2) )); + ytp[0] = Lsum; + move32(); + z[0] = L_shl(L_sub(Lsum, 2), m_tmp); + move32(); /* (int)(floor(y[7]*QR+0.5))>>m */ + + /*---------------------------------------------------------------* + * find nearest neighbor v of z in infinite RE8 + *---------------------------------------------------------------*/ + re8_PPV_fx( z, v ); + + /*---------------------------------------------------------------* + * compute y -= m v + *---------------------------------------------------------------*/ + ptr1=y; + ptr2=v; + + mm = shr(shl(1, m), 1); /* shr to remove effect of L_mult in L_msu */ + + FOR( i=0; i<8; i++ ) + { + Ltmp = L_msu(ytp[i], *ptr2++, mm); + *ptr1++ = extract_l(Ltmp); + } + + return; +} + + +/*-----------------------------------------------------------------------* + * re8_identify_absolute_leader: + * + * IDENTIFY THE ABSOLUTE LEADER RELATED TO y USING A PRE-DEFINED TABLE WHICH + * SPECIFIES THE CODEBOOKS Q0, Q2, Q3 and Q4 + -----------------------------------------------------------------------*/ + +static Word16 re8_identify_absolute_leader_fx( /* o : integer indicating if y if in Q0, Q2, Q3 or Q4 (or if y is an outlier) */ + const Word16 y[] /* i : point in RE8 (8-dimensional integer vector) */ +) +{ + Word16 i,s,id,nb,pos,ka, tmp16; + Word32 Ltmp, Ls; + Word32 C; + const Word16 *ptr; + + /*-----------------------------------------------------------------------* + * compute the RE8 shell number s = (y1^2+...+y8^2)/8 and C=(y1^2, ..., y8^2) + *-----------------------------------------------------------------------*/ + Ls = L_mult(y[0], y[0]); + FOR( i = 1; i < 8; i++ ) + { + Ls = L_mac( Ls, y[i], y[i]); + } + s = extract_h(L_shl(Ls, 16-(3+1))); /* s can saturate here */ + + /*-----------------------------------------------------------------------* + * compute the index 0 <= ka <= NB_LEADER+1 which identifies an absolute leader of Q0, Q2, Q3 or Q4 + * + * by default, ka=index of last element of the table (to indicate an outlier) + *-----------------------------------------------------------------------*/ + /*-------------------------------------------------------------------* + * if s=0, y=0 i.e. y is in Q0 -> ka=index of element indicating Q0 + *-------------------------------------------------------------------*/ + ka = NB_LEADER; + move16(); + IF( s != 0 ) + { + ka = NB_LEADER+1; + move16(); + /*-------------------------------------------------------------------* + * the maximal value of s for y in Q0, Q2, Q3 or Q4 is NB_SPHERE + * if s> NB_SPHERE, y is an outlier (the value of ka is set correctly) + *-------------------------------------------------------------------*/ + IF( LE_16(s, NB_SPHERE)) + { + /*---------------------------------------------------------------* + * compute the unique identifier id of the absolute leader related to y: + * s = (y1^4 + ... + y8^4)/8 + *---------------------------------------------------------------*/ + C = L_mult(y[0], y[0]); + tmp16 = extract_h(L_shl(C, 16-1)); + Ltmp = L_mult(tmp16, tmp16); + FOR( i=1; i<8; i++ ) + { + C = L_mult(y[i], y[i]); + tmp16 = extract_h(L_shl(C, 16-1)); + Ltmp = L_mac(Ltmp, tmp16, tmp16); + } + id = extract_h(L_shl(Ltmp, 16-(3+1))); /* id can saturate to 8192 */ + + /*---------------------------------------------------------------* + * search for id in table Da_id + * (containing all possible values of id if y is in Q2, Q3 or Q4) + * this search is focused based on the shell number s so that + * only the id's related to the shell of number s are checked + *---------------------------------------------------------------*/ + + nb = Da_nb_fx[s - 1]; /* get the number of absolute leaders used on the shell of number s */ + pos = Da_pos_fx[s - 1]; /* get the position of the first absolute leader of shell s in Da_id */ + move16(); + move16(); + + ptr = &Da_id_fx[pos]; + move16(); + FOR( i=0; i=1; i-- ) + { + /* apply factor 2/4 from M^-1 */ + k[i] = shr(sub(y[i], tmp), 1); + move16(); + sum = sub(sum, y[i]); + } + /* apply factor 1/4 from M^-1 */ + k[0]= shr(add(y[0], sum), 2); + move16(); + + return; +} diff --git a/lib_com/recovernorm_fx.c b/lib_com/recovernorm_fx.c new file mode 100644 index 0000000..f061c71 --- /dev/null +++ b/lib_com/recovernorm_fx.c @@ -0,0 +1,62 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "stl.h" /* required for wmc_tool */ +#include "prot_fx.h" /* Function prototypes */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ + +/*--------------------------------------------------------------------------* + * recovernorm_fx() + * + * Recover reordered quantization indices and norms + *--------------------------------------------------------------------------*/ + +void recovernorm_fx( + Word16 *idxbuf, /* i : reordered quantization indices */ + Word16 *ynrm, /* o : recovered quantization indices */ + Word16 *normqlg2, /* o : recovered quantized norms */ + Word16 nb_sfm /* i : number of SFMs */ +) +{ + Word16 i,j,k; + const Word16 *order = NULL; + move16(); + + SWITCH (nb_sfm) + { + case NB_SFM: + order = norm_order_48; + move16(); + BREAK; + case SFM_N_SWB: + order = norm_order_32; + move16(); + BREAK; + case SFM_N_WB: + order = norm_order_16; + move16(); + BREAK; + default: + order = norm_order_48; + move16(); + BREAK; + } + + FOR (i = 0; i < nb_sfm; i++) + { + j = order[i]; + move16(); + k = idxbuf[i]; + move16(); + ynrm[j] = k; + move16(); + normqlg2[j] = dicnlg2[k]; + move16(); + } + + return; +} + diff --git a/lib_com/reordvct_fx.c b/lib_com/reordvct_fx.c new file mode 100644 index 0000000..952c483 --- /dev/null +++ b/lib_com/reordvct_fx.c @@ -0,0 +1,58 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "stl.h" +#include "prot_fx.h" /* Function prototypes */ + + +/*--------------------------------------------------------------------------* + * reordvct() + * + * Rearrange a vector in decreasing order + *--------------------------------------------------------------------------*/ + +void reordvct_fx( + Word16 *y, /* i/o: vector to rearrange */ + const Word16 N, /* i : dimensions */ + Word16 *idx /* o : reordered vector index */ +) +{ + Word16 i, j, k, n, im, temp; + + n = sub(N, 1); + move16(); + FOR (i=0; i 0) + q = add(q, shift); + *y++ = shl(x[0], shift); + move16(); + + FOR (i = 1; i < m; i++) + { + s = L_mult(x[i], a[0]); + /* Stop at i to Avoid Mults with Zeros */ + FOR (j = 1; j <= i; j++) + { + s = L_mac(s, x[i-j], a[j]); + } + + s = L_shl(s, q); + *y++ = round_fx(s); + } + + FOR (; i < lg; i++) + { + s = L_mult(x[i], a[0]); + FOR (j = 1; j <= m; j++) + { + s = L_mac(s, x[i-j], a[j]); + } + + s = L_shl(s, q); + *y++ = round_fx(s); + } +} + +/*--------------------------------------------------------------------* + * Residu3_10_fx: + * + * Compute the LP residual by filtering the input speech through A(z) + * Output is in Qx + *--------------------------------------------------------------------*/ +void Residu3_10_fx( + const Word16 a[], /* i : prediction coefficients Q12 */ + const Word16 x[], /* i : input signal (usually speech) Qx */ + /* (note that values x[-10..-1] are needed) */ + Word16 y[], /* o : output signal (usually residual) Qx */ + const Word16 lg, /* i : vector size Q0 */ const Word16 shift +) +{ + Word16 i,j; + Word32 s; + Word64 s64; + Word16 q; + q = add( norm_s(a[0]), 1 ); + if (shift != 0) + q = add(q, shift); + FOR (i = 0; i < lg; i++) + { + s64 = 0; + FOR (j = 0; j <= 10; j++) + { + s64 = W_mac_16_16(s64, x[i-j], a[j]); + } + s = W_shl_sat_l(s64, q); + y[i] = round_fx(s); + } +} +/*--------------------------------------------------------------------* + * Residu3_fx: + * + * Compute the LP residual by filtering the input speech through A(z) + * Output is in Qx + *--------------------------------------------------------------------*/ +void Residu3_fx( + const Word16 a[], /* i : prediction coefficients Q12 */ + const Word16 x[], /* i : input signal (usually speech) Qx */ + /* (note that values x[-M..-1] are needed) */ + Word16 y[], /* o : output signal (usually residual) Qx */ + const Word16 lg, /* i : vector size Q0 */ + const Word16 shift +) +{ + Word16 i, j; + Word64 s64; + Word32 s32; + Word16 q; + q = add( norm_s(a[0]), 1 ); + if (shift != 0) + q = add(q, shift); + FOR (i = 0; i < lg; i++) + { + s64 = 0; + FOR (j = 0; j <= 15; j++) + { + s64 = W_mac_16_16(s64, x[i-j], a[j]); + } + s64 = W_mac_16_16(s64, x[i-16], a[16]); + s32 = W_shl_sat_l(s64, q); + y[i] = round_fx( s32 ); + } +} +/*==========================================================================*/ +/* FUNCTION : void calc_residu() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Compute the LP residual by filtering the input through */ +/* A(z) in all subframes */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 *speech i : weighted speech signal Qx */ +/* Word16 L_frame i : order of LP filter Q0 */ +/* Word16 *p_Aq i : quantized LP filter coefficients Q12 */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* Word16 *res o : residual signal Qx+1 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*==========================================================================*/ + +void calc_residu_fx( + Encoder_State_fx *st, /* i/o: state structure */ + const Word16 *speech, /* i : weighted speech signal */ + Word16 *res, /* o : residual signal */ + const Word16 *p_Aq, /* i : quantized LP filter coefficients */ + const Word16 vad_hover_flag, + const Word16 vad_flag_dtx +) +{ + Word16 i_subfr; + Word16 i; + Word16 att; + Word16 offset; + + FOR( i_subfr = 0; i_subfr < st->L_frame_fx; i_subfr += L_SUBFR ) + { + /* calculate the residual signal */ + Residu3_fx( p_Aq, &speech[i_subfr], &res[i_subfr], L_SUBFR, 1 ); + + /* next subframe */ + p_Aq += (M+1); + } + /* smoothing in case of CNG */ + test(); + IF( (st->Opt_DTX_ON_fx != 0 ) && (vad_hover_flag != 0) ) /* corresponds to line 504 in FLT acelp_core_enc.c */ + { + st->burst_ho_cnt_fx = add(st->burst_ho_cnt_fx,1); + st->burst_ho_cnt_fx = s_min(st->burst_ho_cnt_fx, HO_HIST_SIZE); + IF( NE_16(st->bwidth_fx, NB)) + { + offset = 5; + test(); + if( EQ_16(st->bwidth_fx, WB)&&st->CNG_mode_fx>=0) + { + offset = st->CNG_mode_fx; + move16(); + } + + att = CNG_burst_att_fx[offset][sub(st->burst_ho_cnt_fx,1)]; /*Q15*/ + + FOR( i = 0; i < st->L_frame_fx; i++ ) + { + res[i] = mult_r(res[i], att); + move16(); + } + } + } + ELSE + { + test(); + IF( (st->Opt_DTX_ON_fx != 0) && (vad_flag_dtx != 0) ) + { + st->burst_ho_cnt_fx = 0; + move16(); + } + } + return; +} + diff --git a/lib_com/rom_basop_util.c b/lib_com/rom_basop_util.c new file mode 100644 index 0000000..646653e --- /dev/null +++ b/lib_com/rom_basop_util.c @@ -0,0 +1,991 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "rom_basop_util.h" +#include "stl.h" +#include +#include +#include "options.h" + + +/** + * \brief Lookup-Table for binary logarithm + */ +const Word16 ldCoeff[7] = +{ + -32768, -16384, -10923, -8192, -6554, -5461, -4681 + /* -4096, -3641, -3277 */ +}; + +/** + \brief Lookup-Table for binary power algorithm + + 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[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, + 0x6BA27E65,0x6DFDDBCC,0x70666F76,0x72DC8374, + 0x75606374,0x77F25CCE,0x7A92BE8B,0x7D41D96E +}; + +/** + \brief Lookup-Table for binary power algorithm + + 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[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, + 0x410C57A2,0x41179E3D,0x4122E6CD,0x412E3152, + 0x41397DCC,0x4144CC3B,0x41501CA0,0x415B6EFB +}; + +/** + \brief Lookup-Table for binary power algorithm + + 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[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, + 0x400851E4,0x4008AAA8,0x4009036E,0x40095C33, + 0x4009B4FA,0x400A0DC0,0x400A6688,0x400ABF4F +}; + +/* square root tables */ +const Word32 SqrtTable[32] = /* Q31 */ +{ + 0x5A82D429, 0x5BEA10FE, 0x5D4BE6E5, 0x5EA89270, 0x60004BE2, 0x615347A1, 0x62A1B68C, 0x63EBC651, + 0x6531A1B5, 0x667370D4, 0x67B1595F, 0x68EB7EC8, 0x6A220277, 0x6B5503F0, 0x6C84A0F9, 0x6DB0F5BD, + 0x6EDA1CE9, 0x70002FC7, 0x7123465A, 0x72437773, 0x7360D8C5, 0x747B7EFA, 0x75937DC4, 0x76A8E7EB, + 0x77BBCF60, 0x78CC4545, 0x79DA5A00, 0x7AE61D3E, 0x7BEF9E07, 0x7CF6EAC2, 0x7DFC113F, 0x7EFF1EC0 +}; + +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[32] = /* Q31 */ +{ + 0x7FFE7F85, 0x7E0A4E25, 0x7C2C56C7, 0x7A63002C, 0x78ACD922, 0x7708939D, 0x75750088, 0x73F10C2D, + 0x727BBB1A, 0x71142774, 0x6FB97EA5, 0x6E6AFF54, 0x6D27F79D, 0x6BEFC388, 0x6AC1CBA4, 0x699D83DA, + 0x68826A53, 0x6770068E, 0x6665E882, 0x6563A7DF, 0x6468E364, 0x63754043, 0x62886999, 0x61A20FEE, + 0x60C1E8C8, 0x5FE7AE45, 0x5F131EBE, 0x5E43FC76, 0x5D7A0D4F, 0x5CB51A81, 0x5BF4F061, 0x5B395E26 +}; + +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, 0x3996, 0x380A, + 0x368F, 0x3524, 0x33C9, 0x327C, 0x313D, 0x300B, 0x2EE5, 0x2DCA +}; + +/* 1/x tables */ +const Word32 InvTable[32] = /* Q31 */ +{ + 0x7FFBFE40, 0x7C1B608E, 0x78752176, 0x750440BA, 0x71C44C49, 0x6EB14D0A, 0x6BC7B6B4, 0x69045A19, + 0x6664598A, 0x63E51EE2, 0x61845308, 0x5F3FD698, 0x5D15BB8E, 0x5B043FD0, 0x5909C861, 0x5724DD3C, + 0x555425B2, 0x53966532, 0x51EA787F, 0x504F5331, 0x4EC3FD84, 0x4D479267, 0x4BD93DBE, 0x4A783ADC, + 0x4923D31D, 0x47DB5CAE, 0x469E3974, 0x456BD608, 0x4443A8D9, 0x43253159, 0x420FF746, 0x41038A01 +}; + +/* inverse integer (1/i) */ +const Word16 InvIntTable[65] = +{ + 0x7FFF, + 0x7FFF, 0x4000, 0x2AAB, 0x2000, 0x199A, 0x1555, 0x1249, 0x1000, + 0x0E39, 0x0CCD, 0x0BA3, 0x0AAB, 0x09D9, 0x0925, 0x0889, 0x0800, + 0x0788, 0x071C, 0x06BD, 0x0666, 0x0618, 0x05D1, 0x0591, 0x0555, + 0x051F, 0x04EC, 0x04BE, 0x0492, 0x046A, 0x0444, 0x0421, 0x0400, + 0x03E1, 0x03C4, 0x03A8, 0x038E, 0x0376, 0x035E, 0x0348, 0x0333, + 0x031F, 0x030C, 0x02FA, 0x02E9, 0x02D8, 0x02C8, 0x02B9, 0x02AB, + 0x029D, 0x028F, 0x0283, 0x0276, 0x026A, 0x025F, 0x0254, 0x0249, + 0x023F, 0x0235, 0x022B, 0x0222, 0x0219, 0x0211, 0x0208, 0x0200 +}; + +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, 0x2C20, 0x2A8D, + 0x290F, 0x27A4, 0x264C, 0x2506, 0x23CF, 0x22A7, 0x218E, 0x2081 +}; + +const Word32 BASOP_util_normReciprocal[CHEAP_NORM_SIZE] = +{ + 0l/*0.0 Q31*/, 2147483647l/*1.0000000000 Q31*/, 1073741824l/*0.5000000000 Q31*/, 715827883l/*0.3333333333 Q31*/, 536870912l/*0.2500000000 Q31*/, 429496730l/*0.2000000000 Q31*/, + 357913941l/*0.1666666667 Q31*/, 306783378l/*0.1428571429 Q31*/, 268435456l/*0.1250000000 Q31*/, 238609294l/*0.1111111111 Q31*/, 214748365l/*0.1000000000 Q31*/, 195225786l/*0.0909090909 Q31*/, + 178956971l/*0.0833333333 Q31*/, 165191050l/*0.0769230769 Q31*/, 153391689l/*0.0714285714 Q31*/, 143165577l/*0.0666666667 Q31*/, 134217728l/*0.0625000000 Q31*/, 126322568l/*0.0588235294 Q31*/, + 119304647l/*0.0555555556 Q31*/, 113025455l/*0.0526315789 Q31*/, 107374182l/*0.0500000000 Q31*/, 102261126l/*0.0476190476 Q31*/, 97612893l/*0.0454545455 Q31*/, 93368854l/*0.0434782609 Q31*/, + 89478485l/*0.0416666667 Q31*/, 85899346l/*0.0400000000 Q31*/, 82595525l/*0.0384615385 Q31*/, 79536431l/*0.0370370370 Q31*/, 76695845l/*0.0357142857 Q31*/, 74051160l/*0.0344827586 Q31*/, + 71582788l/*0.0333333333 Q31*/, 69273666l/*0.0322580645 Q31*/, 67108864l/*0.0312500000 Q31*/, 65075262l/*0.0303030303 Q31*/, 63161284l/*0.0294117647 Q31*/, 61356676l/*0.0285714286 Q31*/, + 59652324l/*0.0277777778 Q31*/, 58040099l/*0.0270270270 Q31*/, 56512728l/*0.0263157895 Q31*/, 55063683l/*0.0256410256 Q31*/, 53687091l/*0.0250000000 Q31*/, 52377650l/*0.0243902439 Q31*/, + 51130563l/*0.0238095238 Q31*/, 49941480l/*0.0232558140 Q31*/, 48806446l/*0.0227272727 Q31*/, 47721859l/*0.0222222222 Q31*/, 46684427l/*0.0217391304 Q31*/, 45691141l/*0.0212765957 Q31*/, + 44739243l/*0.0208333333 Q31*/, 43826197l/*0.0204081633 Q31*/, 42949673l/*0.0200000000 Q31*/, 42107522l/*0.0196078431 Q31*/, 41297762l/*0.0192307692 Q31*/, 40518559l/*0.0188679245 Q31*/, + 39768216l/*0.0185185185 Q31*/, 39045157l/*0.0181818182 Q31*/, 38347922l/*0.0178571429 Q31*/, 37675152l/*0.0175438596 Q31*/, 37025580l/*0.0172413793 Q31*/, 36398028l/*0.0169491525 Q31*/, + 35791394l/*0.0166666667 Q31*/, 35204650l/*0.0163934426 Q31*/, 34636833l/*0.0161290323 Q31*/, 34087042l/*0.0158730159 Q31*/, 33554432l/*0.0156250000 Q31*/, 33038210l/*0.0153846154 Q31*/, + 32537631l/*0.0151515152 Q31*/, 32051995l/*0.0149253731 Q31*/, 31580642l/*0.0147058824 Q31*/, 31122951l/*0.0144927536 Q31*/, 30678338l/*0.0142857143 Q31*/, 30246248l/*0.0140845070 Q31*/, + 29826162l/*0.0138888889 Q31*/, 29417584l/*0.0136986301 Q31*/, 29020049l/*0.0135135135 Q31*/, 28633115l/*0.0133333333 Q31*/, 28256364l/*0.0131578947 Q31*/, 27889398l/*0.0129870130 Q31*/, + 27531842l/*0.0128205128 Q31*/, 27183337l/*0.0126582278 Q31*/, 26843546l/*0.0125000000 Q31*/, 26512144l/*0.0123456790 Q31*/, 26188825l/*0.0121951220 Q31*/, 25873297l/*0.0120481928 Q31*/, + 25565282l/*0.0119047619 Q31*/, 25264514l/*0.0117647059 Q31*/, 24970740l/*0.0116279070 Q31*/, 24683720l/*0.0114942529 Q31*/, 24403223l/*0.0113636364 Q31*/, 24129030l/*0.0112359551 Q31*/, + 23860929l/*0.0111111111 Q31*/, 23598721l/*0.0109890110 Q31*/, 23342214l/*0.0108695652 Q31*/, 23091222l/*0.0107526882 Q31*/, 22845571l/*0.0106382979 Q31*/, 22605091l/*0.0105263158 Q31*/, + 22369621l/*0.0104166667 Q31*/, 22139007l/*0.0103092784 Q31*/, 21913098l/*0.0102040816 Q31*/, 21691754l/*0.0101010101 Q31*/, 21474836l/*0.0100000000 Q31*/, 21262214l/*0.0099009901 Q31*/, + 21053761l/*0.0098039216 Q31*/, 20849356l/*0.0097087379 Q31*/, 20648881l/*0.0096153846 Q31*/, 20452225l/*0.0095238095 Q31*/, 20259280l/*0.0094339623 Q31*/, 20069941l/*0.0093457944 Q31*/, + 19884108l/*0.0092592593 Q31*/, 19701685l/*0.0091743119 Q31*/, 19522579l/*0.0090909091 Q31*/, 19346700l/*0.0090090090 Q31*/, 19173961l/*0.0089285714 Q31*/, 19004280l/*0.0088495575 Q31*/, + 18837576l/*0.0087719298 Q31*/, 18673771l/*0.0086956522 Q31*/, 18512790l/*0.0086206897 Q31*/, 18354561l/*0.0085470085 Q31*/, 18199014l/*0.0084745763 Q31*/, 18046081l/*0.0084033613 Q31*/, + 17895697l/*0.0083333333 Q31*/, 17747799l/*0.0082644628 Q31*/, 17602325l/*0.0081967213 Q31*/, 17459217l/*0.0081300813 Q31*/, 17318416l/*0.0080645161 Q31*/, 17179869l/*0.0080000000 Q31*/, + 17043521l/*0.0079365079 Q31*/, 16909320l/*0.0078740157 Q31*/, 16777216l/*0.0078125000 Q31*/, 16647160l/*0.0077519380 Q31*/, 16519105l/*0.0076923077 Q31*/, 16393005l/*0.0076335878 Q31*/, + 16268816l/*0.0075757576 Q31*/, 16146494l/*0.0075187970 Q31*/, 16025997l/*0.0074626866 Q31*/, 15907286l/*0.0074074074 Q31*/, 15790321l/*0.0073529412 Q31*/, 15675063l/*0.0072992701 Q31*/, + 15561476l/*0.0072463768 Q31*/, 15449523l/*0.0071942446 Q31*/, 15339169l/*0.0071428571 Q31*/, 15230381l/*0.0070921986 Q31*/, 15123124l/*0.0070422535 Q31*/, 15017368l/*0.0069930070 Q31*/, + 14913081l/*0.0069444444 Q31*/, 14810232l/*0.0068965517 Q31*/, 14708792l/*0.0068493151 Q31*/, 14608732l/*0.0068027211 Q31*/, 14510025l/*0.0067567568 Q31*/, 14412642l/*0.0067114094 Q31*/, + 14316558l/*0.0066666667 Q31*/, 14221746l/*0.0066225166 Q31*/, 14128182l/*0.0065789474 Q31*/, 14035841l/*0.0065359477 Q31*/, 13944699l/*0.0064935065 Q31*/, 13854733l/*0.0064516129 Q31*/, + 13765921l/*0.0064102564 Q31*/, 13678240l/*0.0063694268 Q31*/, 13591669l/*0.0063291139 Q31*/, 13506187l/*0.0062893082 Q31*/, 13421773l/*0.0062500000 Q31*/ +}; + +const Word16 f_atan_expand_range[MAXSFTAB-(MINSFTAB-1)] = +{ + /***************************************************************************** + * + * Table holds fixp_atan() output values which are outside of input range + * of fixp_atan() to improve SNR of fixp_atan2(). + * + * This Table might also be used in fixp_atan() [todo] so there a wider input + * range can be covered, too. + * + * Matlab (generate table): + * for scl = 7:25 % MINSFTAB .. MAXSFTAB + * at=atan(0.5 *(2^scl)); % 0.5 because get in 'middle' area of current scale level 'scl' + * at/2 % div at by ATO_SCALE + * end + * + * Table divided by 2=ATO_SCALE <-- SF=ATO_SF + *****************************************************************************/ + 25480/*7.775862990872099e-001 Q15*/, 25608/*7.814919928673978e-001 Q15*/, 25672/*7.834450483314648e-001 Q15*/, + 25704/*7.844216021392089e-001 Q15*/, 25720/*7.849098823026687e-001 Q15*/, 25728/*7.851540227918509e-001 Q15*/, + 25732/*7.852760930873737e-001 Q15*/, 25734/*7.853371282415015e-001 Q15*/, 25735/*7.853676458193612e-001 Q15*/, + 25735/*7.853829046083906e-001 Q15*/, 25736/*7.853905340029177e-001 Q15*/, 25736/*7.853943487001828e-001 Q15*/, + 25736/*7.853962560488155e-001 Q15*/, 25736/*7.853972097231319e-001 Q15*/, 25736/*7.853976865602901e-001 Q15*/, + 25736/*7.853979249788692e-001 Q15*/, 25736/*7.853980441881587e-001 Q15*/, 25736/*7.853981037928035e-001 Q15*/, + 25736/*7.853981335951259e-001 Q15*/ + /* pi/4 = 0.785398163397448 = pi/2/ATO_SCALE */ +}; + + +/* + Sine tables + */ +#define STC(x) WORD322WORD16(x) + +/* #define STCP(a,b) (((Word32)STC(b)<<16) | STC(a)) */ +#define STCP(a,b) { { STC(a), STC(b) } } + +const PWord16 SineTable512[] = +{ + STCP(0x7fffffff, 0x00000000), STCP(0x7fffd886, 0x006487e3), STCP(0x7fff6216, 0x00c90f88), STCP(0x7ffe9cb2, 0x012d96b1), + STCP(0x7ffd885a, 0x01921d20), STCP(0x7ffc250f, 0x01f6a297), STCP(0x7ffa72d1, 0x025b26d7), STCP(0x7ff871a2, 0x02bfa9a4), + STCP(0x7ff62182, 0x03242abf), STCP(0x7ff38274, 0x0388a9ea), STCP(0x7ff09478, 0x03ed26e6), STCP(0x7fed5791, 0x0451a177), + STCP(0x7fe9cbc0, 0x04b6195d), STCP(0x7fe5f108, 0x051a8e5c), STCP(0x7fe1c76b, 0x057f0035), STCP(0x7fdd4eec, 0x05e36ea9), + STCP(0x7fd8878e, 0x0647d97c), STCP(0x7fd37153, 0x06ac406f), STCP(0x7fce0c3e, 0x0710a345), STCP(0x7fc85854, 0x077501be), + STCP(0x7fc25596, 0x07d95b9e), STCP(0x7fbc040a, 0x083db0a7), STCP(0x7fb563b3, 0x08a2009a), STCP(0x7fae7495, 0x09064b3a), + STCP(0x7fa736b4, 0x096a9049), STCP(0x7f9faa15, 0x09cecf89), STCP(0x7f97cebd, 0x0a3308bd), STCP(0x7f8fa4b0, 0x0a973ba5), + STCP(0x7f872bf3, 0x0afb6805), STCP(0x7f7e648c, 0x0b5f8d9f), STCP(0x7f754e80, 0x0bc3ac35), STCP(0x7f6be9d4, 0x0c27c389), + STCP(0x7f62368f, 0x0c8bd35e), STCP(0x7f5834b7, 0x0cefdb76), STCP(0x7f4de451, 0x0d53db92), STCP(0x7f434563, 0x0db7d376), + STCP(0x7f3857f6, 0x0e1bc2e4), STCP(0x7f2d1c0e, 0x0e7fa99e), STCP(0x7f2191b4, 0x0ee38766), STCP(0x7f15b8ee, 0x0f475bff), + STCP(0x7f0991c4, 0x0fab272b), STCP(0x7efd1c3c, 0x100ee8ad), STCP(0x7ef05860, 0x1072a048), STCP(0x7ee34636, 0x10d64dbd), + STCP(0x7ed5e5c6, 0x1139f0cf), STCP(0x7ec8371a, 0x119d8941), STCP(0x7eba3a39, 0x120116d5), STCP(0x7eabef2c, 0x1264994e), + STCP(0x7e9d55fc, 0x12c8106f), STCP(0x7e8e6eb2, 0x132b7bf9), STCP(0x7e7f3957, 0x138edbb1), STCP(0x7e6fb5f4, 0x13f22f58), + STCP(0x7e5fe493, 0x145576b1), STCP(0x7e4fc53e, 0x14b8b17f), STCP(0x7e3f57ff, 0x151bdf86), STCP(0x7e2e9cdf, 0x157f0086), + STCP(0x7e1d93ea, 0x15e21445), STCP(0x7e0c3d29, 0x16451a83), STCP(0x7dfa98a8, 0x16a81305), STCP(0x7de8a670, 0x170afd8d), + STCP(0x7dd6668f, 0x176dd9de), STCP(0x7dc3d90d, 0x17d0a7bc), STCP(0x7db0fdf8, 0x183366e9), STCP(0x7d9dd55a, 0x18961728), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d769bb5, 0x195b49ea), STCP(0x7d628ac6, 0x19bdcbf3), STCP(0x7d4e2c7f, 0x1a203e1b), + STCP(0x7d3980ec, 0x1a82a026), STCP(0x7d24881b, 0x1ae4f1d6), STCP(0x7d0f4218, 0x1b4732ef), STCP(0x7cf9aef0, 0x1ba96335), + STCP(0x7ce3ceb2, 0x1c0b826a), STCP(0x7ccda169, 0x1c6d9053), STCP(0x7cb72724, 0x1ccf8cb3), STCP(0x7ca05ff1, 0x1d31774d), + STCP(0x7c894bde, 0x1d934fe5), STCP(0x7c71eaf9, 0x1df5163f), STCP(0x7c5a3d50, 0x1e56ca1e), STCP(0x7c4242f2, 0x1eb86b46), + STCP(0x7c29fbee, 0x1f19f97b), STCP(0x7c116853, 0x1f7b7481), STCP(0x7bf88830, 0x1fdcdc1b), STCP(0x7bdf5b94, 0x203e300d), + STCP(0x7bc5e290, 0x209f701c), STCP(0x7bac1d31, 0x21009c0c), STCP(0x7b920b89, 0x2161b3a0), STCP(0x7b77ada8, 0x21c2b69c), + STCP(0x7b5d039e, 0x2223a4c5), STCP(0x7b420d7a, 0x22847de0), STCP(0x7b26cb4f, 0x22e541af), STCP(0x7b0b3d2c, 0x2345eff8), + STCP(0x7aef6323, 0x23a6887f), STCP(0x7ad33d45, 0x24070b08), STCP(0x7ab6cba4, 0x24677758), STCP(0x7a9a0e50, 0x24c7cd33), + STCP(0x7a7d055b, 0x25280c5e), STCP(0x7a5fb0d8, 0x2588349d), STCP(0x7a4210d8, 0x25e845b6), STCP(0x7a24256f, 0x26483f6c), + STCP(0x7a05eead, 0x26a82186), STCP(0x79e76ca7, 0x2707ebc7), STCP(0x79c89f6e, 0x27679df4), STCP(0x79a98715, 0x27c737d3), + STCP(0x798a23b1, 0x2826b928), STCP(0x796a7554, 0x288621b9), STCP(0x794a7c12, 0x28e5714b), STCP(0x792a37fe, 0x2944a7a2), + STCP(0x7909a92d, 0x29a3c485), STCP(0x78e8cfb2, 0x2a02c7b8), STCP(0x78c7aba2, 0x2a61b101), STCP(0x78a63d11, 0x2ac08026), + STCP(0x78848414, 0x2b1f34eb), STCP(0x786280bf, 0x2b7dcf17), STCP(0x78403329, 0x2bdc4e6f), STCP(0x781d9b65, 0x2c3ab2b9), + STCP(0x77fab989, 0x2c98fbba), STCP(0x77d78daa, 0x2cf72939), STCP(0x77b417df, 0x2d553afc), STCP(0x7790583e, 0x2db330c7), + STCP(0x776c4edb, 0x2e110a62), STCP(0x7747fbce, 0x2e6ec792), STCP(0x77235f2d, 0x2ecc681e), STCP(0x76fe790e, 0x2f29ebcc), + STCP(0x76d94989, 0x2f875262), STCP(0x76b3d0b4, 0x2fe49ba7), STCP(0x768e0ea6, 0x3041c761), STCP(0x76680376, 0x309ed556), + STCP(0x7641af3d, 0x30fbc54d), STCP(0x761b1211, 0x3158970e), STCP(0x75f42c0b, 0x31b54a5e), STCP(0x75ccfd42, 0x3211df04), + STCP(0x75a585cf, 0x326e54c7), STCP(0x757dc5ca, 0x32caab6f), STCP(0x7555bd4c, 0x3326e2c3), STCP(0x752d6c6c, 0x3382fa88), + STCP(0x7504d345, 0x33def287), STCP(0x74dbf1ef, 0x343aca87), STCP(0x74b2c884, 0x34968250), STCP(0x7489571c, 0x34f219a8), + STCP(0x745f9dd1, 0x354d9057), STCP(0x74359cbd, 0x35a8e625), STCP(0x740b53fb, 0x36041ad9), STCP(0x73e0c3a3, 0x365f2e3b), + STCP(0x73b5ebd1, 0x36ba2014), STCP(0x738acc9e, 0x3714f02a), STCP(0x735f6626, 0x376f9e46), STCP(0x7333b883, 0x37ca2a30), + STCP(0x7307c3d0, 0x382493b0), STCP(0x72db8828, 0x387eda8e), STCP(0x72af05a7, 0x38d8fe93), STCP(0x72823c67, 0x3932ff87), + STCP(0x72552c85, 0x398cdd32), STCP(0x7227d61c, 0x39e6975e), STCP(0x71fa3949, 0x3a402dd2), STCP(0x71cc5626, 0x3a99a057), + STCP(0x719e2cd2, 0x3af2eeb7), STCP(0x716fbd68, 0x3b4c18ba), STCP(0x71410805, 0x3ba51e29), STCP(0x71120cc5, 0x3bfdfecd), + STCP(0x70e2cbc6, 0x3c56ba70), STCP(0x70b34525, 0x3caf50da), STCP(0x708378ff, 0x3d07c1d6), STCP(0x70536771, 0x3d600d2c), + STCP(0x7023109a, 0x3db832a6), STCP(0x6ff27497, 0x3e10320d), STCP(0x6fc19385, 0x3e680b2c), STCP(0x6f906d84, 0x3ebfbdcd), + STCP(0x6f5f02b2, 0x3f1749b8), STCP(0x6f2d532c, 0x3f6eaeb8), STCP(0x6efb5f12, 0x3fc5ec98), STCP(0x6ec92683, 0x401d0321), + STCP(0x6e96a99d, 0x4073f21d), STCP(0x6e63e87f, 0x40cab958), STCP(0x6e30e34a, 0x4121589b), STCP(0x6dfd9a1c, 0x4177cfb1), + STCP(0x6dca0d14, 0x41ce1e65), STCP(0x6d963c54, 0x42244481), STCP(0x6d6227fa, 0x427a41d0), STCP(0x6d2dd027, 0x42d0161e), + STCP(0x6cf934fc, 0x4325c135), STCP(0x6cc45698, 0x437b42e1), STCP(0x6c8f351c, 0x43d09aed), STCP(0x6c59d0a9, 0x4425c923), + STCP(0x6c242960, 0x447acd50), STCP(0x6bee3f62, 0x44cfa740), STCP(0x6bb812d1, 0x452456bd), STCP(0x6b81a3cd, 0x4578db93), + STCP(0x6b4af279, 0x45cd358f), STCP(0x6b13fef5, 0x4621647d), STCP(0x6adcc964, 0x46756828), STCP(0x6aa551e9, 0x46c9405c), + STCP(0x6a6d98a4, 0x471cece7), STCP(0x6a359db9, 0x47706d93), STCP(0x69fd614a, 0x47c3c22f), STCP(0x69c4e37a, 0x4816ea86), + STCP(0x698c246c, 0x4869e665), STCP(0x69532442, 0x48bcb599), STCP(0x6919e320, 0x490f57ee), STCP(0x68e06129, 0x4961cd33), + STCP(0x68a69e81, 0x49b41533), STCP(0x686c9b4b, 0x4a062fbd), STCP(0x683257ab, 0x4a581c9e), STCP(0x67f7d3c5, 0x4aa9dba2), + STCP(0x67bd0fbd, 0x4afb6c98), STCP(0x67820bb7, 0x4b4ccf4d), STCP(0x6746c7d8, 0x4b9e0390), STCP(0x670b4444, 0x4bef092d), + STCP(0x66cf8120, 0x4c3fdff4), STCP(0x66937e91, 0x4c9087b1), STCP(0x66573cbb, 0x4ce10034), STCP(0x661abbc5, 0x4d31494b), + STCP(0x65ddfbd3, 0x4d8162c4), STCP(0x65a0fd0b, 0x4dd14c6e), STCP(0x6563bf92, 0x4e210617), STCP(0x6526438f, 0x4e708f8f), + STCP(0x64e88926, 0x4ebfe8a5), STCP(0x64aa907f, 0x4f0f1126), STCP(0x646c59bf, 0x4f5e08e3), STCP(0x642de50d, 0x4faccfab), + STCP(0x63ef3290, 0x4ffb654d), STCP(0x63b0426d, 0x5049c999), STCP(0x637114cc, 0x5097fc5e), STCP(0x6331a9d4, 0x50e5fd6d), + STCP(0x62f201ac, 0x5133cc94), STCP(0x62b21c7b, 0x518169a5), STCP(0x6271fa69, 0x51ced46e), STCP(0x62319b9d, 0x521c0cc2), + STCP(0x61f1003f, 0x5269126e), STCP(0x61b02876, 0x52b5e546), STCP(0x616f146c, 0x53028518), STCP(0x612dc447, 0x534ef1b5), + STCP(0x60ec3830, 0x539b2af0), STCP(0x60aa7050, 0x53e73097), STCP(0x60686ccf, 0x5433027d), STCP(0x60262dd6, 0x547ea073), + STCP(0x5fe3b38d, 0x54ca0a4b), STCP(0x5fa0fe1f, 0x55153fd4), STCP(0x5f5e0db3, 0x556040e2), STCP(0x5f1ae274, 0x55ab0d46), + STCP(0x5ed77c8a, 0x55f5a4d2), STCP(0x5e93dc1f, 0x56400758), STCP(0x5e50015d, 0x568a34a9), STCP(0x5e0bec6e, 0x56d42c99), + STCP(0x5dc79d7c, 0x571deefa), STCP(0x5d8314b1, 0x57677b9d), STCP(0x5d3e5237, 0x57b0d256), STCP(0x5cf95638, 0x57f9f2f8), + STCP(0x5cb420e0, 0x5842dd54), STCP(0x5c6eb258, 0x588b9140), STCP(0x5c290acc, 0x58d40e8c), STCP(0x5be32a67, 0x591c550e), + STCP(0x5b9d1154, 0x59646498), STCP(0x5b56bfbd, 0x59ac3cfd), STCP(0x5b1035cf, 0x59f3de12), STCP(0x5ac973b5, 0x5a3b47ab), + STCP(0x5a82799a, 0x5a82799a), +}; + +const PWord16 SineTable320[] = +{ + STCP(0x7fffffff, 0x00000000), STCP(0x7fff9aef, 0x00a0d951), + STCP(0x7ffe6bbf, 0x0141b1a5), STCP(0x7ffc726f, 0x01e287fc), + STCP(0x7ff9af04, 0x02835b5a), STCP(0x7ff62182, 0x03242abf), + STCP(0x7ff1c9ef, 0x03c4f52f), STCP(0x7feca851, 0x0465b9aa), + STCP(0x7fe6bcb0, 0x05067734), STCP(0x7fe00716, 0x05a72ccf), + STCP(0x7fd8878e, 0x0647d97c), STCP(0x7fd03e23, 0x06e87c3f), + STCP(0x7fc72ae2, 0x07891418), STCP(0x7fbd4dda, 0x0829a00c), + STCP(0x7fb2a71b, 0x08ca1f1b), STCP(0x7fa736b4, 0x096a9049), + STCP(0x7f9afcb9, 0x0a0af299), STCP(0x7f8df93c, 0x0aab450d), + STCP(0x7f802c52, 0x0b4b86a8), STCP(0x7f719611, 0x0bebb66c), + STCP(0x7f62368f, 0x0c8bd35e), STCP(0x7f520de6, 0x0d2bdc80), + STCP(0x7f411c2f, 0x0dcbd0d5), STCP(0x7f2f6183, 0x0e6baf61), + STCP(0x7f1cde01, 0x0f0b7727), STCP(0x7f0991c4, 0x0fab272b), + STCP(0x7ef57cea, 0x104abe71), STCP(0x7ee09f95, 0x10ea3bfd), + STCP(0x7ecaf9e5, 0x11899ed3), STCP(0x7eb48bfb, 0x1228e5f8), + STCP(0x7e9d55fc, 0x12c8106f), STCP(0x7e85580c, 0x13671d3d), + STCP(0x7e6c9251, 0x14060b68), STCP(0x7e5304f2, 0x14a4d9f4), + STCP(0x7e38b017, 0x154387e6), STCP(0x7e1d93ea, 0x15e21445), + STCP(0x7e01b096, 0x16807e15), STCP(0x7de50646, 0x171ec45c), + STCP(0x7dc79529, 0x17bce621), STCP(0x7da95d6c, 0x185ae269), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d6a9ad5, 0x199666a0), + STCP(0x7d4a105d, 0x1a33ec9c), STCP(0x7d28c00c, 0x1ad14938), + STCP(0x7d06aa16, 0x1b6e7b7a), STCP(0x7ce3ceb2, 0x1c0b826a), + STCP(0x7cc02e15, 0x1ca85d12), STCP(0x7c9bc87a, 0x1d450a78), + STCP(0x7c769e18, 0x1de189a6), STCP(0x7c50af2b, 0x1e7dd9a4), + STCP(0x7c29fbee, 0x1f19f97b), STCP(0x7c02849f, 0x1fb5e836), + STCP(0x7bda497d, 0x2051a4dd), STCP(0x7bb14ac5, 0x20ed2e7b), + STCP(0x7b8788ba, 0x2188841a), STCP(0x7b5d039e, 0x2223a4c5), + STCP(0x7b31bbb2, 0x22be8f87), STCP(0x7b05b13d, 0x2359436c), + STCP(0x7ad8e482, 0x23f3bf7e), STCP(0x7aab55ca, 0x248e02cb), + STCP(0x7a7d055b, 0x25280c5e), STCP(0x7a4df380, 0x25c1db44), + STCP(0x7a1e2082, 0x265b6e8a), STCP(0x79ed8cad, 0x26f4c53e), + STCP(0x79bc384d, 0x278dde6e), STCP(0x798a23b1, 0x2826b928), + STCP(0x79574f28, 0x28bf547b), STCP(0x7923bb01, 0x2957af74), + STCP(0x78ef678f, 0x29efc925), STCP(0x78ba5524, 0x2a87a09d), + STCP(0x78848414, 0x2b1f34eb), STCP(0x784df4b3, 0x2bb68522), + STCP(0x7816a759, 0x2c4d9050), STCP(0x77de9c5b, 0x2ce45589), + STCP(0x77a5d413, 0x2d7ad3de), STCP(0x776c4edb, 0x2e110a62), + STCP(0x77320d0d, 0x2ea6f827), STCP(0x76f70f05, 0x2f3c9c40), + STCP(0x76bb5521, 0x2fd1f5c1), STCP(0x767edfbe, 0x306703bf), + STCP(0x7641af3d, 0x30fbc54d), STCP(0x7603c3fd, 0x31903982), + STCP(0x75c51e61, 0x32245f72), STCP(0x7585becb, 0x32b83634), + STCP(0x7545a5a0, 0x334bbcde), STCP(0x7504d345, 0x33def287), + STCP(0x74c34820, 0x3471d647), STCP(0x74810499, 0x35046736), + STCP(0x743e0918, 0x3596a46c), STCP(0x73fa5607, 0x36288d03), + STCP(0x73b5ebd1, 0x36ba2014), STCP(0x7370cae2, 0x374b5cb9), + STCP(0x732af3a7, 0x37dc420c), STCP(0x72e4668f, 0x386ccf2a), + STCP(0x729d2409, 0x38fd032d), STCP(0x72552c85, 0x398cdd32), + STCP(0x720c8075, 0x3a1c5c57), STCP(0x71c3204c, 0x3aab7fb7), + STCP(0x71790c7e, 0x3b3a4672), STCP(0x712e457f, 0x3bc8afa5), + STCP(0x70e2cbc6, 0x3c56ba70), STCP(0x70969fca, 0x3ce465f3), + STCP(0x7049c203, 0x3d71b14d), STCP(0x6ffc32eb, 0x3dfe9ba1), + STCP(0x6fadf2fc, 0x3e8b240e), STCP(0x6f5f02b2, 0x3f1749b8), + STCP(0x6f0f6289, 0x3fa30bc1), STCP(0x6ebf12ff, 0x402e694c), + STCP(0x6e6e1492, 0x40b9617d), STCP(0x6e1c67c4, 0x4143f379), + STCP(0x6dca0d14, 0x41ce1e65), STCP(0x6d770506, 0x4257e166), + STCP(0x6d23501b, 0x42e13ba4), STCP(0x6cceeed8, 0x436a2c45), + STCP(0x6c79e1c2, 0x43f2b271), STCP(0x6c242960, 0x447acd50), + STCP(0x6bcdc639, 0x45027c0c), STCP(0x6b76b8d6, 0x4589bdcf), + STCP(0x6b1f01c0, 0x461091c2), STCP(0x6ac6a180, 0x4696f710), + STCP(0x6a6d98a4, 0x471cece7), STCP(0x6a13e7b8, 0x47a27271), + STCP(0x69b98f48, 0x482786dc), STCP(0x695e8fe5, 0x48ac2957), + STCP(0x6902ea1d, 0x4930590f), STCP(0x68a69e81, 0x49b41533), + STCP(0x6849ada3, 0x4a375cf5), STCP(0x67ec1817, 0x4aba2f84), + STCP(0x678dde6e, 0x4b3c8c12), STCP(0x672f013f, 0x4bbe71d1), + STCP(0x66cf8120, 0x4c3fdff4), STCP(0x666f5ea6, 0x4cc0d5ae), + STCP(0x660e9a6a, 0x4d415234), STCP(0x65ad3505, 0x4dc154bb), + STCP(0x654b2f10, 0x4e40dc79), STCP(0x64e88926, 0x4ebfe8a5), + STCP(0x648543e4, 0x4f3e7875), STCP(0x64215fe5, 0x4fbc8b22), + STCP(0x63bcddc7, 0x503a1fe5), STCP(0x6357be2a, 0x50b735f8), + STCP(0x62f201ac, 0x5133cc94), STCP(0x628ba8ef, 0x51afe2f6), + STCP(0x6224b495, 0x522b7859), STCP(0x61bd253f, 0x52a68bfb), + STCP(0x6154fb91, 0x53211d18), STCP(0x60ec3830, 0x539b2af0), + STCP(0x6082dbc1, 0x5414b4c1), STCP(0x6018e6eb, 0x548db9cb), + STCP(0x5fae5a55, 0x55063951), STCP(0x5f4336a7, 0x557e3292), + STCP(0x5ed77c8a, 0x55f5a4d2), STCP(0x5e6b2ca8, 0x566c8f55), + STCP(0x5dfe47ad, 0x56e2f15d), STCP(0x5d90ce45, 0x5758ca31), + STCP(0x5d22c11c, 0x57ce1917), STCP(0x5cb420e0, 0x5842dd54), + STCP(0x5c44ee40, 0x58b71632), STCP(0x5bd529eb, 0x592ac2f7), + STCP(0x5b64d492, 0x599de2ee), STCP(0x5af3eee6, 0x5a107561), + STCP(0x5a82799a, 0x5a82799a) +}; + +/* + Sine windows + */ +#define WTC(x) WORD322WORD16(x) + +#define WTCP(a,b) { { WTC(a), WTC(b) } } + +const PWord16 SineWindow10[5] = +{ + WTCP(0x7f9afcb9, 0x0a0af299), WTCP(0x7c769e18, 0x1de189a6), WTCP(0x7641af3d, 0x30fbc54d), WTCP(0x6d23501b, 0x42e13ba4), + WTCP(0x6154fb91, 0x53211d18), +}; + +const PWord16 SineWindow16[8] = +{ + WTCP(0x7fd8878e, 0x0647d97c), WTCP(0x7e9d55fc, 0x12c8106f), WTCP(0x7c29fbee, 0x1f19f97b), WTCP(0x78848414, 0x2b1f34eb), + WTCP(0x73b5ebd1, 0x36ba2014), WTCP(0x6dca0d14, 0x41ce1e65), WTCP(0x66cf8120, 0x4c3fdff4), WTCP(0x5ed77c8a, 0x55f5a4d2), +}; + +const PWord16 SineWindow20[10] = +{ + WTCP(0x7fe6bcb0, 0x05067734), WTCP(0x7f1cde01, 0x0f0b7727), WTCP(0x7d8a5f40, 0x18f8b83c), WTCP(0x7b31bbb2, 0x22be8f87), + WTCP(0x7816a759, 0x2c4d9050), WTCP(0x743e0918, 0x3596a46c), WTCP(0x6fadf2fc, 0x3e8b240e), WTCP(0x6a6d98a4, 0x471cece7), + WTCP(0x648543e4, 0x4f3e7875), WTCP(0x5dfe47ad, 0x56e2f15d), +}; + +const PWord16 SineWindow30[15] = +{ + 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), +}; + +const PWord16 SineWindow32[16] = +{ + WTCP(0x7ff62182, 0x03242abf), WTCP(0x7fa736b4, 0x096a9049), WTCP(0x7f0991c4, 0x0fab272b), WTCP(0x7e1d93ea, 0x15e21445), + WTCP(0x7ce3ceb2, 0x1c0b826a), WTCP(0x7b5d039e, 0x2223a4c5), WTCP(0x798a23b1, 0x2826b928), WTCP(0x776c4edb, 0x2e110a62), + WTCP(0x7504d345, 0x33def287), WTCP(0x72552c85, 0x398cdd32), WTCP(0x6f5f02b2, 0x3f1749b8), WTCP(0x6c242960, 0x447acd50), + WTCP(0x68a69e81, 0x49b41533), WTCP(0x64e88926, 0x4ebfe8a5), WTCP(0x60ec3830, 0x539b2af0), WTCP(0x5cb420e0, 0x5842dd54) +}; + +const PWord16 SineWindow40[20] = +{ + WTCP(0x7ff9af04, 0x02835b5a), WTCP(0x7fc72ae2, 0x07891418), WTCP(0x7f62368f, 0x0c8bd35e), WTCP(0x7ecaf9e5, 0x11899ed3), + WTCP(0x7e01b096, 0x16807e15), WTCP(0x7d06aa16, 0x1b6e7b7a), WTCP(0x7bda497d, 0x2051a4dd), WTCP(0x7a7d055b, 0x25280c5e), + WTCP(0x78ef678f, 0x29efc925), WTCP(0x77320d0d, 0x2ea6f827), WTCP(0x7545a5a0, 0x334bbcde), WTCP(0x732af3a7, 0x37dc420c), + WTCP(0x70e2cbc6, 0x3c56ba70), WTCP(0x6e6e1492, 0x40b9617d), WTCP(0x6bcdc639, 0x45027c0c), WTCP(0x6902ea1d, 0x4930590f), + WTCP(0x660e9a6a, 0x4d415234), WTCP(0x62f201ac, 0x5133cc94), WTCP(0x5fae5a55, 0x55063951), WTCP(0x5c44ee40, 0x58b71632), +}; + +const PWord16 SineWindow48[24] = +{ + WTCP(0x7ffb9d15, 0x02182427), WTCP(0x7fd8878e, 0x0647d97c), WTCP(0x7f92661d, 0x0a75d60e), WTCP(0x7f294bfd, 0x0ea0f48c), + WTCP(0x7e9d55fc, 0x12c8106f), WTCP(0x7deeaa7a, 0x16ea0646), WTCP(0x7d1d7958, 0x1b05b40f), WTCP(0x7c29fbee, 0x1f19f97b), + WTCP(0x7b1474fd, 0x2325b847), WTCP(0x79dd3098, 0x2727d486), WTCP(0x78848414, 0x2b1f34eb), WTCP(0x770acdec, 0x2f0ac320), + WTCP(0x757075ac, 0x32e96c09), WTCP(0x73b5ebd1, 0x36ba2014), WTCP(0x71dba9ab, 0x3a7bd382), WTCP(0x6fe2313c, 0x3e2d7eb1), + WTCP(0x6dca0d14, 0x41ce1e65), WTCP(0x6b93d02e, 0x455cb40c), WTCP(0x694015c3, 0x48d84609), WTCP(0x66cf8120, 0x4c3fdff4), + WTCP(0x6442bd7e, 0x4f9292dc), WTCP(0x619a7dce, 0x52cf758f), WTCP(0x5ed77c8a, 0x55f5a4d2), WTCP(0x5bfa7b82, 0x590443a7) +}; + +const PWord16 SineWindow60[60] = +{ + WTCP(0x7ffd3154, 0x01aceb7c), WTCP(0x7fe6bcb0, 0x05067734), WTCP(0x7fb9d759, 0x085f2137), WTCP(0x7f76892f, 0x0bb65336), + WTCP(0x7f1cde01, 0x0f0b7727), WTCP(0x7eace58a, 0x125df75b), WTCP(0x7e26b371, 0x15ad3e9a), WTCP(0x7d8a5f40, 0x18f8b83c), + WTCP(0x7cd80464, 0x1c3fd045), WTCP(0x7c0fc22a, 0x1f81f37c), WTCP(0x7b31bbb2, 0x22be8f87), WTCP(0x7a3e17f2, 0x25f51307), + WTCP(0x793501a9, 0x2924edac), WTCP(0x7816a759, 0x2c4d9050), WTCP(0x76e33b3f, 0x2f6e6d16), WTCP(0x759af34c, 0x3286f779), + WTCP(0x743e0918, 0x3596a46c), WTCP(0x72ccb9db, 0x389cea72), WTCP(0x71474660, 0x3b9941b1), WTCP(0x6fadf2fc, 0x3e8b240e), + WTCP(0x6e010780, 0x41720d46), WTCP(0x6c40cf2c, 0x444d7aff), WTCP(0x6a6d98a4, 0x471cece7), WTCP(0x6887b5e2, 0x49dfe4c2), + WTCP(0x668f7c25, 0x4c95e688), WTCP(0x648543e4, 0x4f3e7875), WTCP(0x626968be, 0x51d92321), WTCP(0x603c496c, 0x54657194), + WTCP(0x5dfe47ad, 0x56e2f15d), WTCP(0x5bafc837, 0x595132a2), +}; + +const PWord16 SineWindow64[32] = +{ + WTCP(0x7ffd885a, 0x01921d20), WTCP(0x7fe9cbc0, 0x04b6195d), WTCP(0x7fc25596, 0x07d95b9e), WTCP(0x7f872bf3, 0x0afb6805), + WTCP(0x7f3857f6, 0x0e1bc2e4), WTCP(0x7ed5e5c6, 0x1139f0cf), WTCP(0x7e5fe493, 0x145576b1), WTCP(0x7dd6668f, 0x176dd9de), + WTCP(0x7d3980ec, 0x1a82a026), WTCP(0x7c894bde, 0x1d934fe5), WTCP(0x7bc5e290, 0x209f701c), WTCP(0x7aef6323, 0x23a6887f), + WTCP(0x7a05eead, 0x26a82186), WTCP(0x7909a92d, 0x29a3c485), WTCP(0x77fab989, 0x2c98fbba), WTCP(0x76d94989, 0x2f875262), + WTCP(0x75a585cf, 0x326e54c7), WTCP(0x745f9dd1, 0x354d9057), WTCP(0x7307c3d0, 0x382493b0), WTCP(0x719e2cd2, 0x3af2eeb7), + WTCP(0x7023109a, 0x3db832a6), WTCP(0x6e96a99d, 0x4073f21d), WTCP(0x6cf934fc, 0x4325c135), WTCP(0x6b4af279, 0x45cd358f), + WTCP(0x698c246c, 0x4869e665), WTCP(0x67bd0fbd, 0x4afb6c98), WTCP(0x65ddfbd3, 0x4d8162c4), WTCP(0x63ef3290, 0x4ffb654d), + WTCP(0x61f1003f, 0x5269126e), WTCP(0x5fe3b38d, 0x54ca0a4b), WTCP(0x5dc79d7c, 0x571deefa), WTCP(0x5b9d1154, 0x59646498), +}; + +const PWord16 SineWindow80[40] = +{ + WTCP(0x7ffe6bbf, 0x0141b1a5), WTCP(0x7ff1c9ef, 0x03c4f52f), WTCP(0x7fd8878e, 0x0647d97c), WTCP(0x7fb2a71b, 0x08ca1f1b), + WTCP(0x7f802c52, 0x0b4b86a8), WTCP(0x7f411c2f, 0x0dcbd0d5), WTCP(0x7ef57cea, 0x104abe71), WTCP(0x7e9d55fc, 0x12c8106f), + WTCP(0x7e38b017, 0x154387e6), WTCP(0x7dc79529, 0x17bce621), WTCP(0x7d4a105d, 0x1a33ec9c), WTCP(0x7cc02e15, 0x1ca85d12), + WTCP(0x7c29fbee, 0x1f19f97b), WTCP(0x7b8788ba, 0x2188841a), WTCP(0x7ad8e482, 0x23f3bf7e), WTCP(0x7a1e2082, 0x265b6e8a), + WTCP(0x79574f28, 0x28bf547b), WTCP(0x78848414, 0x2b1f34eb), WTCP(0x77a5d413, 0x2d7ad3de), WTCP(0x76bb5521, 0x2fd1f5c1), + WTCP(0x75c51e61, 0x32245f72), WTCP(0x74c34820, 0x3471d647), WTCP(0x73b5ebd1, 0x36ba2014), WTCP(0x729d2409, 0x38fd032d), + WTCP(0x71790c7e, 0x3b3a4672), WTCP(0x7049c203, 0x3d71b14d), WTCP(0x6f0f6289, 0x3fa30bc1), WTCP(0x6dca0d14, 0x41ce1e65), + WTCP(0x6c79e1c2, 0x43f2b271), WTCP(0x6b1f01c0, 0x461091c2), WTCP(0x69b98f48, 0x482786dc), WTCP(0x6849ada3, 0x4a375cf5), + WTCP(0x66cf8120, 0x4c3fdff4), WTCP(0x654b2f10, 0x4e40dc79), WTCP(0x63bcddc7, 0x503a1fe5), WTCP(0x6224b495, 0x522b7859), + WTCP(0x6082dbc1, 0x5414b4c1), WTCP(0x5ed77c8a, 0x55f5a4d2), WTCP(0x5d22c11c, 0x57ce1917), WTCP(0x5b64d492, 0x599de2ee), +}; + +const PWord16 SineWindow70[35] = +{ + WTCP(0x7ffdeffe, 0x016fa5fd), WTCP(0x7fed7058, 0x044ec292), WTCP(0x7fcc732b, 0x072d5101), WTCP(0x7f9afcb9, 0x0a0af299), + WTCP(0x7f591361, 0x0ce748ca), WTCP(0x7f06bfa3, 0x0fc1f52d), WTCP(0x7ea40c1b, 0x129a9991), WTCP(0x7e310583, 0x1570d80b), + WTCP(0x7dadbaaf, 0x184452fd), WTCP(0x7d1a3c8a, 0x1b14ad24), WTCP(0x7c769e18, 0x1de189a6), WTCP(0x7bc2f470, 0x20aa8c19), + WTCP(0x7aff56bc, 0x236f5896), WTCP(0x7a2bde32, 0x262f93be), WTCP(0x7948a614, 0x28eae2cb), WTCP(0x7855cbae, 0x2ba0eb97), + WTCP(0x77536e4c, 0x2e5154ac), WTCP(0x7641af3d, 0x30fbc54d), WTCP(0x7520b1ca, 0x339fe582), WTCP(0x73f09b33, 0x363d5e23), + WTCP(0x72b192ac, 0x38d3d8e3), WTCP(0x7163c154, 0x3b63005e), WTCP(0x70075233, 0x3dea8020), WTCP(0x6e9c7233, 0x406a04b2), + WTCP(0x6d23501b, 0x42e13ba4), WTCP(0x6b9c1c87, 0x454fd398), WTCP(0x6a0709e6, 0x47b57c4e), WTCP(0x68644c6e, 0x4a11e6aa), + WTCP(0x66b41a1a, 0x4c64c4c4), WTCP(0x64f6aa9f, 0x4eadc9ee), WTCP(0x632c3769, 0x50ecaabd), WTCP(0x6154fb91, 0x53211d18), + WTCP(0x5f7133d4, 0x554ad83c), WTCP(0x5d811e90, 0x576994c8), WTCP(0x5b84fbb6, 0x597d0cc7) +}; + +const PWord16 SineWindow96[48] = +{ + WTCP(0x7ffee744, 0x010c1460), WTCP(0x7ff62182, 0x03242abf), WTCP(0x7fe49698, 0x053c0a01), WTCP(0x7fca47b9, 0x07538d6b), + WTCP(0x7fa736b4, 0x096a9049), WTCP(0x7f7b65ef, 0x0b80edf1), WTCP(0x7f46d86c, 0x0d9681c2), WTCP(0x7f0991c4, 0x0fab272b), + WTCP(0x7ec3962a, 0x11beb9aa), WTCP(0x7e74ea6a, 0x13d114d0), WTCP(0x7e1d93ea, 0x15e21445), WTCP(0x7dbd98a4, 0x17f193c5), + WTCP(0x7d54ff2e, 0x19ff6f2a), WTCP(0x7ce3ceb2, 0x1c0b826a), WTCP(0x7c6a0ef2, 0x1e15a99a), WTCP(0x7be7c847, 0x201dc0ef), + WTCP(0x7b5d039e, 0x2223a4c5), WTCP(0x7ac9ca7a, 0x2427319d), WTCP(0x7a2e26f2, 0x26284422), WTCP(0x798a23b1, 0x2826b928), + WTCP(0x78ddcbf5, 0x2a226db5), WTCP(0x78292b8d, 0x2c1b3efb), WTCP(0x776c4edb, 0x2e110a62), WTCP(0x76a742d1, 0x3003ad85), + WTCP(0x75da14ef, 0x31f30638), WTCP(0x7504d345, 0x33def287), WTCP(0x74278c72, 0x35c750bc), WTCP(0x73424fa0, 0x37abff5d), + WTCP(0x72552c85, 0x398cdd32), WTCP(0x71603361, 0x3b69c947), WTCP(0x706374ff, 0x3d42a2ec), WTCP(0x6f5f02b2, 0x3f1749b8), + WTCP(0x6e52ee52, 0x40e79d8c), WTCP(0x6d3f4a40, 0x42b37e96), WTCP(0x6c242960, 0x447acd50), WTCP(0x6b019f1a, 0x463d6a87), + WTCP(0x69d7bf57, 0x47fb3757), WTCP(0x68a69e81, 0x49b41533), WTCP(0x676e5183, 0x4b67e5e4), WTCP(0x662eedc3, 0x4d168b8b), + WTCP(0x64e88926, 0x4ebfe8a5), WTCP(0x639b3a0b, 0x5063e008), WTCP(0x62471749, 0x520254ef), WTCP(0x60ec3830, 0x539b2af0), + WTCP(0x5f8ab487, 0x552e4605), WTCP(0x5e22a487, 0x56bb8a90), WTCP(0x5cb420e0, 0x5842dd54), WTCP(0x5b3f42ae, 0x59c42381) +}; + +const PWord16 SineWindow112[56] = +{ + WTCP(0x7fff31bf, 0x00e5c87e), WTCP(0x7ff8bfc7, 0x02b14de9), WTCP(0x7febdc2a, 0x047cb09e), WTCP(0x7fd8878e, 0x0647d97c), + WTCP(0x7fbec2ec, 0x0812b164), WTCP(0x7f9e8f91, 0x09dd213a), WTCP(0x7f77ef1c, 0x0ba711ea), WTCP(0x7f4ae37e, 0x0d706c64), + WTCP(0x7f176efc, 0x0f3919a0), WTCP(0x7edd942d, 0x110102a0), WTCP(0x7e9d55fc, 0x12c8106f), WTCP(0x7e56b7a4, 0x148e2c22), + WTCP(0x7e09bcb4, 0x16533edc), WTCP(0x7db6690c, 0x181731cd), WTCP(0x7d5cc0df, 0x19d9ee32), WTCP(0x7cfcc8af, 0x1b9b5d5a), + WTCP(0x7c968552, 0x1d5b68a2), WTCP(0x7c29fbee, 0x1f19f97b), WTCP(0x7bb731fb, 0x20d6f969), WTCP(0x7b3e2d40, 0x22925203), + WTCP(0x7abef3d5, 0x244becf6), WTCP(0x7a398c22, 0x2603b406), WTCP(0x79adfcdf, 0x27b9910e), WTCP(0x791c4d13, 0x296d6e00), + WTCP(0x78848414, 0x2b1f34eb), WTCP(0x77e6a986, 0x2ccecff7), WTCP(0x7742c55c, 0x2e7c2969), WTCP(0x7698dfd8, 0x30272ba0), + WTCP(0x75e90186, 0x31cfc11e), WTCP(0x75333343, 0x3375d481), WTCP(0x74777e35, 0x35195088), WTCP(0x73b5ebd1, 0x36ba2014), + WTCP(0x72ee85d5, 0x38582e27), WTCP(0x7221564d, 0x39f365e9), WTCP(0x714e678c, 0x3b8bb2a3), WTCP(0x7075c433, 0x3d20ffc8), + WTCP(0x6f977729, 0x3eb338ef), WTCP(0x6eb38ba1, 0x404249d5), WTCP(0x6dca0d14, 0x41ce1e65), WTCP(0x6cdb0745, 0x4356a2ad), + WTCP(0x6be6863c, 0x44dbc2ec), WTCP(0x6aec9649, 0x465d6b89), WTCP(0x69ed4403, 0x47db8918), WTCP(0x68e89c43, 0x4956085b), + WTCP(0x67deac2c, 0x4accd644), WTCP(0x66cf8120, 0x4c3fdff4), WTCP(0x65bb28c7, 0x4daf12ba), WTCP(0x64a1b10b, 0x4f1a5c1a), + WTCP(0x6383281a, 0x5081a9c9), WTCP(0x625f9c5f, 0x51e4e9ae), WTCP(0x61371c8b, 0x534409e8), WTCP(0x6009b78a, 0x549ef8c6), + WTCP(0x5ed77c8a, 0x55f5a4d2), WTCP(0x5da07af6, 0x5747fcca), WTCP(0x5c64c278, 0x5895efa4), WTCP(0x5b2462f5, 0x59df6c8f) +}; + +const PWord16 SineWindow120[60] = +{ + WTCP(0x7fff4c54, 0x00d676eb), WTCP(0x7ff9af04, 0x02835b5a), WTCP(0x7fee74a2, 0x0430238f), WTCP(0x7fdd9dad, 0x05dcbcbe), + WTCP(0x7fc72ae2, 0x07891418), WTCP(0x7fab1d3d, 0x093516d4), WTCP(0x7f8975f9, 0x0ae0b22c), WTCP(0x7f62368f, 0x0c8bd35e), + WTCP(0x7f3560b9, 0x0e3667ad), WTCP(0x7f02f66f, 0x0fe05c64), WTCP(0x7ecaf9e5, 0x11899ed3), WTCP(0x7e8d6d91, 0x13321c53), + WTCP(0x7e4a5426, 0x14d9c245), WTCP(0x7e01b096, 0x16807e15), WTCP(0x7db3860f, 0x18263d36), WTCP(0x7d5fd801, 0x19caed29), + WTCP(0x7d06aa16, 0x1b6e7b7a), WTCP(0x7ca80038, 0x1d10d5c2), WTCP(0x7c43de8e, 0x1eb1e9a7), WTCP(0x7bda497d, 0x2051a4dd), + WTCP(0x7b6b45a5, 0x21eff528), WTCP(0x7af6d7e6, 0x238cc85d), WTCP(0x7a7d055b, 0x25280c5e), WTCP(0x79fdd35c, 0x26c1af22), + WTCP(0x7979477d, 0x28599eb0), WTCP(0x78ef678f, 0x29efc925), WTCP(0x7860399e, 0x2b841caf), WTCP(0x77cbc3f2, 0x2d168792), + WTCP(0x77320d0d, 0x2ea6f827), WTCP(0x76931bae, 0x30355cdd), WTCP(0x75eef6ce, 0x31c1a43b), WTCP(0x7545a5a0, 0x334bbcde), + WTCP(0x74972f92, 0x34d3957e), WTCP(0x73e39c49, 0x36591cea), WTCP(0x732af3a7, 0x37dc420c), WTCP(0x726d3dc6, 0x395cf3e9), + WTCP(0x71aa82f7, 0x3adb21a1), WTCP(0x70e2cbc6, 0x3c56ba70), WTCP(0x701620f5, 0x3dcfadb0), WTCP(0x6f448b7e, 0x3f45ead8), + WTCP(0x6e6e1492, 0x40b9617d), WTCP(0x6d92c59b, 0x422a0154), WTCP(0x6cb2a837, 0x4397ba32), WTCP(0x6bcdc639, 0x45027c0c), + WTCP(0x6ae429ae, 0x466a36f9), WTCP(0x69f5dcd3, 0x47cedb31), WTCP(0x6902ea1d, 0x4930590f), WTCP(0x680b5c33, 0x4a8ea111), + WTCP(0x670f3df3, 0x4be9a3db), WTCP(0x660e9a6a, 0x4d415234), WTCP(0x65097cdb, 0x4e959d08), WTCP(0x63fff0ba, 0x4fe6756a), + WTCP(0x62f201ac, 0x5133cc94), WTCP(0x61dfbb8a, 0x527d93e6), WTCP(0x60c92a5a, 0x53c3bcea), WTCP(0x5fae5a55, 0x55063951), + WTCP(0x5e8f57e2, 0x5644faf4), WTCP(0x5d6c2f99, 0x577ff3da), WTCP(0x5c44ee40, 0x58b71632), WTCP(0x5b19a0c8, 0x59ea5454), +}; + +const PWord16 SineWindow128[64] = +{ + WTCP(0x7fff6216, 0x00c90f88), WTCP(0x7ffa72d1, 0x025b26d7), WTCP(0x7ff09478, 0x03ed26e6), WTCP(0x7fe1c76b, 0x057f0035), + WTCP(0x7fce0c3e, 0x0710a345), WTCP(0x7fb563b3, 0x08a2009a), WTCP(0x7f97cebd, 0x0a3308bd), WTCP(0x7f754e80, 0x0bc3ac35), + WTCP(0x7f4de451, 0x0d53db92), WTCP(0x7f2191b4, 0x0ee38766), WTCP(0x7ef05860, 0x1072a048), WTCP(0x7eba3a39, 0x120116d5), + WTCP(0x7e7f3957, 0x138edbb1), WTCP(0x7e3f57ff, 0x151bdf86), WTCP(0x7dfa98a8, 0x16a81305), WTCP(0x7db0fdf8, 0x183366e9), + WTCP(0x7d628ac6, 0x19bdcbf3), WTCP(0x7d0f4218, 0x1b4732ef), WTCP(0x7cb72724, 0x1ccf8cb3), WTCP(0x7c5a3d50, 0x1e56ca1e), + WTCP(0x7bf88830, 0x1fdcdc1b), WTCP(0x7b920b89, 0x2161b3a0), WTCP(0x7b26cb4f, 0x22e541af), WTCP(0x7ab6cba4, 0x24677758), + WTCP(0x7a4210d8, 0x25e845b6), WTCP(0x79c89f6e, 0x27679df4), WTCP(0x794a7c12, 0x28e5714b), WTCP(0x78c7aba2, 0x2a61b101), + WTCP(0x78403329, 0x2bdc4e6f), WTCP(0x77b417df, 0x2d553afc), WTCP(0x77235f2d, 0x2ecc681e), WTCP(0x768e0ea6, 0x3041c761), + WTCP(0x75f42c0b, 0x31b54a5e), WTCP(0x7555bd4c, 0x3326e2c3), WTCP(0x74b2c884, 0x34968250), WTCP(0x740b53fb, 0x36041ad9), + WTCP(0x735f6626, 0x376f9e46), WTCP(0x72af05a7, 0x38d8fe93), WTCP(0x71fa3949, 0x3a402dd2), WTCP(0x71410805, 0x3ba51e29), + WTCP(0x708378ff, 0x3d07c1d6), WTCP(0x6fc19385, 0x3e680b2c), WTCP(0x6efb5f12, 0x3fc5ec98), WTCP(0x6e30e34a, 0x4121589b), + WTCP(0x6d6227fa, 0x427a41d0), WTCP(0x6c8f351c, 0x43d09aed), WTCP(0x6bb812d1, 0x452456bd), WTCP(0x6adcc964, 0x46756828), + WTCP(0x69fd614a, 0x47c3c22f), WTCP(0x6919e320, 0x490f57ee), WTCP(0x683257ab, 0x4a581c9e), WTCP(0x6746c7d8, 0x4b9e0390), + WTCP(0x66573cbb, 0x4ce10034), WTCP(0x6563bf92, 0x4e210617), WTCP(0x646c59bf, 0x4f5e08e3), WTCP(0x637114cc, 0x5097fc5e), + WTCP(0x6271fa69, 0x51ced46e), WTCP(0x616f146c, 0x53028518), WTCP(0x60686ccf, 0x5433027d), WTCP(0x5f5e0db3, 0x556040e2), + WTCP(0x5e50015d, 0x568a34a9), WTCP(0x5d3e5237, 0x57b0d256), WTCP(0x5c290acc, 0x58d40e8c), WTCP(0x5b1035cf, 0x59f3de12), +}; + +const PWord16 SineWindow140[70] = +{ + WTCP(0x7fff7bff, 0x00b7d3bc), WTCP(0x7ffb5c00, 0x02277547), WTCP(0x7ff31c25, 0x0397050d), WTCP(0x7fe6bcb0, 0x05067734), + WTCP(0x7fd63e09, 0x0675bfe7), WTCP(0x7fc1a0b6, 0x07e4d34d), WTCP(0x7fa8e564, 0x0953a594), WTCP(0x7f8c0cdc, 0x0ac22ae8), + WTCP(0x7f6b180f, 0x0c30577a), WTCP(0x7f46080a, 0x0d9e1f7d), WTCP(0x7f1cde01, 0x0f0b7727), WTCP(0x7eef9b46, 0x107852b2), + WTCP(0x7ebe414f, 0x11e4a65c), WTCP(0x7e88d1b4, 0x13506668), WTCP(0x7e4f4e2c, 0x14bb871b), WTCP(0x7e11b894, 0x1625fcc3), + WTCP(0x7dd012e6, 0x178fbbb1), WTCP(0x7d8a5f40, 0x18f8b83c), WTCP(0x7d409fe1, 0x1a60e6c3), WTCP(0x7cf2d72b, 0x1bc83baa), + WTCP(0x7ca1079d, 0x1d2eab5d), WTCP(0x7c4b33dc, 0x1e942a4d), WTCP(0x7bf15eac, 0x1ff8acf7), WTCP(0x7b938af1, 0x215c27dc), + WTCP(0x7b31bbb2, 0x22be8f87), WTCP(0x7acbf416, 0x241fd88e), WTCP(0x7a623764, 0x257ff78e), WTCP(0x79f48904, 0x26dee12c), + WTCP(0x7982ec80, 0x283c8a1b), WTCP(0x790d6581, 0x2998e716), WTCP(0x7893f7d1, 0x2af3ece2), WTCP(0x7816a759, 0x2c4d9050), + WTCP(0x77957822, 0x2da5c63e), WTCP(0x77106e58, 0x2efc8393), WTCP(0x76878e43, 0x3051bd43), WTCP(0x75fadc4d, 0x31a56850), + WTCP(0x756a5cff, 0x32f779c7), WTCP(0x74d61500, 0x3447e6c3), WTCP(0x743e0918, 0x3596a46c), WTCP(0x73a23e2d, 0x36e3a7fa), + WTCP(0x7302b945, 0x382ee6b0), WTCP(0x725f7f84, 0x397855e1), WTCP(0x71b8962b, 0x3abfeaf1), WTCP(0x710e029e, 0x3c059b4f), + WTCP(0x705fca59, 0x3d495c7e), WTCP(0x6fadf2fc, 0x3e8b240e), WTCP(0x6ef88241, 0x3fcae7a1), WTCP(0x6e3f7e01, 0x41089ce8), + WTCP(0x6d82ec32, 0x424439a6), WTCP(0x6cc2d2e9, 0x437db3b0), WTCP(0x6bff3855, 0x44b500eb), WTCP(0x6b3822c6, 0x45ea1750), + WTCP(0x6a6d98a4, 0x471cece7), WTCP(0x699fa078, 0x484d77ce), WTCP(0x68ce40e4, 0x497bae33), WTCP(0x67f980a8, 0x4aa7865b), + WTCP(0x6721669f, 0x4bd0f69b), WTCP(0x6645f9c0, 0x4cf7f55d), WTCP(0x6567411d, 0x4e1c791f), WTCP(0x648543e4, 0x4f3e7875), + WTCP(0x63a0095c, 0x505dea05), WTCP(0x62b798ea, 0x517ac48c), WTCP(0x61cbfa0b, 0x5294fedd), WTCP(0x60dd3457, 0x53ac8fde), + WTCP(0x5feb4f7f, 0x54c16e8e), WTCP(0x5ef6534f, 0x55d391ff), WTCP(0x5dfe47ad, 0x56e2f15d), WTCP(0x5d033497, 0x57ef83e9), + WTCP(0x5c052224, 0x58f940fa), WTCP(0x5b041885, 0x5a002001) +}; + +const PWord16 SineWindow160[80] = +{ + WTCP(0x7fff9aef, 0x00a0d951), WTCP(0x7ffc726f, 0x01e287fc), WTCP(0x7ff62182, 0x03242abf), WTCP(0x7feca851, 0x0465b9aa), + WTCP(0x7fe00716, 0x05a72ccf), WTCP(0x7fd03e23, 0x06e87c3f), WTCP(0x7fbd4dda, 0x0829a00c), WTCP(0x7fa736b4, 0x096a9049), + WTCP(0x7f8df93c, 0x0aab450d), WTCP(0x7f719611, 0x0bebb66c), WTCP(0x7f520de6, 0x0d2bdc80), WTCP(0x7f2f6183, 0x0e6baf61), + WTCP(0x7f0991c4, 0x0fab272b), WTCP(0x7ee09f95, 0x10ea3bfd), WTCP(0x7eb48bfb, 0x1228e5f8), WTCP(0x7e85580c, 0x13671d3d), + WTCP(0x7e5304f2, 0x14a4d9f4), WTCP(0x7e1d93ea, 0x15e21445), WTCP(0x7de50646, 0x171ec45c), WTCP(0x7da95d6c, 0x185ae269), + WTCP(0x7d6a9ad5, 0x199666a0), WTCP(0x7d28c00c, 0x1ad14938), WTCP(0x7ce3ceb2, 0x1c0b826a), WTCP(0x7c9bc87a, 0x1d450a78), + WTCP(0x7c50af2b, 0x1e7dd9a4), WTCP(0x7c02849f, 0x1fb5e836), WTCP(0x7bb14ac5, 0x20ed2e7b), WTCP(0x7b5d039e, 0x2223a4c5), + WTCP(0x7b05b13d, 0x2359436c), WTCP(0x7aab55ca, 0x248e02cb), WTCP(0x7a4df380, 0x25c1db44), WTCP(0x79ed8cad, 0x26f4c53e), + WTCP(0x798a23b1, 0x2826b928), WTCP(0x7923bb01, 0x2957af74), WTCP(0x78ba5524, 0x2a87a09d), WTCP(0x784df4b3, 0x2bb68522), + WTCP(0x77de9c5b, 0x2ce45589), WTCP(0x776c4edb, 0x2e110a62), WTCP(0x76f70f05, 0x2f3c9c40), WTCP(0x767edfbe, 0x306703bf), + WTCP(0x7603c3fd, 0x31903982), WTCP(0x7585becb, 0x32b83634), WTCP(0x7504d345, 0x33def287), WTCP(0x74810499, 0x35046736), + WTCP(0x73fa5607, 0x36288d03), WTCP(0x7370cae2, 0x374b5cb9), WTCP(0x72e4668f, 0x386ccf2a), WTCP(0x72552c85, 0x398cdd32), + WTCP(0x71c3204c, 0x3aab7fb7), WTCP(0x712e457f, 0x3bc8afa5), WTCP(0x70969fca, 0x3ce465f3), WTCP(0x6ffc32eb, 0x3dfe9ba1), + WTCP(0x6f5f02b2, 0x3f1749b8), WTCP(0x6ebf12ff, 0x402e694c), WTCP(0x6e1c67c4, 0x4143f379), WTCP(0x6d770506, 0x4257e166), + WTCP(0x6cceeed8, 0x436a2c45), WTCP(0x6c242960, 0x447acd50), WTCP(0x6b76b8d6, 0x4589bdcf), WTCP(0x6ac6a180, 0x4696f710), + WTCP(0x6a13e7b8, 0x47a27271), WTCP(0x695e8fe5, 0x48ac2957), WTCP(0x68a69e81, 0x49b41533), WTCP(0x67ec1817, 0x4aba2f84), + WTCP(0x672f013f, 0x4bbe71d1), WTCP(0x666f5ea6, 0x4cc0d5ae), WTCP(0x65ad3505, 0x4dc154bb), WTCP(0x64e88926, 0x4ebfe8a5), + WTCP(0x64215fe5, 0x4fbc8b22), WTCP(0x6357be2a, 0x50b735f8), WTCP(0x628ba8ef, 0x51afe2f6), WTCP(0x61bd253f, 0x52a68bfb), + WTCP(0x60ec3830, 0x539b2af0), WTCP(0x6018e6eb, 0x548db9cb), WTCP(0x5f4336a7, 0x557e3292), WTCP(0x5e6b2ca8, 0x566c8f55), + WTCP(0x5d90ce45, 0x5758ca31), WTCP(0x5cb420e0, 0x5842dd54), WTCP(0x5bd529eb, 0x592ac2f7), WTCP(0x5af3eee6, 0x5a107561), +}; + +const PWord16 SineWindow180[90] = +{ + WTCP(0x7fffb026, 0x008efa17), WTCP(0x7ffd3154, 0x01aceb7c), WTCP(0x7ff833bd, 0x02cad485), WTCP(0x7ff0b77a, 0x03e8af9e), + WTCP(0x7fe6bcb0, 0x05067734), WTCP(0x7fda4391, 0x062425b6), WTCP(0x7fcb4c5b, 0x0741b592), WTCP(0x7fb9d759, 0x085f2137), + WTCP(0x7fa5e4e1, 0x097c6313), WTCP(0x7f8f7559, 0x0a997598), WTCP(0x7f76892f, 0x0bb65336), WTCP(0x7f5b20df, 0x0cd2f660), + WTCP(0x7f3d3cf4, 0x0def598a), WTCP(0x7f1cde01, 0x0f0b7727), WTCP(0x7efa04a8, 0x102749af), WTCP(0x7ed4b198, 0x1142cb98), + WTCP(0x7eace58a, 0x125df75b), WTCP(0x7e82a146, 0x1378c774), WTCP(0x7e55e59e, 0x1493365f), WTCP(0x7e26b371, 0x15ad3e9a), + WTCP(0x7df50bab, 0x16c6daa6), WTCP(0x7dc0ef44, 0x17e00505), WTCP(0x7d8a5f40, 0x18f8b83c), WTCP(0x7d515caf, 0x1a10eed3), + WTCP(0x7d15e8ad, 0x1b28a351), WTCP(0x7cd80464, 0x1c3fd045), WTCP(0x7c97b109, 0x1d56703c), WTCP(0x7c54efdc, 0x1e6c7dc7), + WTCP(0x7c0fc22a, 0x1f81f37c), WTCP(0x7bc8294d, 0x2096cbf1), WTCP(0x7b7e26aa, 0x21ab01c0), WTCP(0x7b31bbb2, 0x22be8f87), + WTCP(0x7ae2e9e4, 0x23d16fe8), WTCP(0x7a91b2c7, 0x24e39d85), WTCP(0x7a3e17f2, 0x25f51307), WTCP(0x79e81b06, 0x2705cb19), + WTCP(0x798fbdb0, 0x2815c06a), WTCP(0x793501a9, 0x2924edac), WTCP(0x78d7e8b6, 0x2a334d96), WTCP(0x787874a7, 0x2b40dae2), + WTCP(0x7816a759, 0x2c4d9050), WTCP(0x77b282b3, 0x2d5968a3), WTCP(0x774c08ab, 0x2e645ea1), WTCP(0x76e33b3f, 0x2f6e6d16), + WTCP(0x76781c7a, 0x30778ed2), WTCP(0x760aae73, 0x317fbeab), WTCP(0x759af34c, 0x3286f779), WTCP(0x7528ed32, 0x338d341b), + WTCP(0x74b49e5f, 0x34926f74), WTCP(0x743e0918, 0x3596a46c), WTCP(0x73c52fab, 0x3699cdf2), WTCP(0x734a1475, 0x379be6f6), + WTCP(0x72ccb9db, 0x389cea72), WTCP(0x724d224f, 0x399cd362), WTCP(0x71cb504e, 0x3a9b9cca), WTCP(0x71474660, 0x3b9941b1), + WTCP(0x70c10718, 0x3c95bd26), WTCP(0x70389514, 0x3d910a3c), WTCP(0x6fadf2fc, 0x3e8b240e), WTCP(0x6f212385, 0x3f8405bc), + WTCP(0x6e92296e, 0x407baa6a), WTCP(0x6e010780, 0x41720d46), WTCP(0x6d6dc08f, 0x42672981), WTCP(0x6cd8577a, 0x435afa54), + WTCP(0x6c40cf2c, 0x444d7aff), WTCP(0x6ba72a98, 0x453ea6c7), WTCP(0x6b0b6cbd, 0x462e78f9), WTCP(0x6a6d98a4, 0x471cece7), + WTCP(0x69cdb162, 0x4809fdeb), WTCP(0x692bba14, 0x48f5a767), WTCP(0x6887b5e2, 0x49dfe4c2), WTCP(0x67e1a7ff, 0x4ac8b16b), + WTCP(0x673993a9, 0x4bb008d9), WTCP(0x668f7c25, 0x4c95e688), WTCP(0x65e364c4, 0x4d7a45fe), WTCP(0x653550e2, 0x4e5d22c6), + WTCP(0x648543e4, 0x4f3e7875), WTCP(0x63d34137, 0x501e42a5), WTCP(0x631f4c54, 0x50fc7cfb), WTCP(0x626968be, 0x51d92321), + WTCP(0x61b19a00, 0x52b430c9), WTCP(0x60f7e3b0, 0x538da1ae), WTCP(0x603c496c, 0x54657194), WTCP(0x5f7ecedd, 0x553b9c45), + WTCP(0x5ebf77b5, 0x56101d94), WTCP(0x5dfe47ad, 0x56e2f15d), WTCP(0x5d3b428c, 0x57b41384), WTCP(0x5c766c1c, 0x58837ff4), + WTCP(0x5bafc837, 0x595132a2), WTCP(0x5ae75ab9, 0x5a1d278d), +}; + + +const PWord16 SineWindow224[112] = +{ + WTCP(0x7fffcc70, 0x0072e46e), WTCP(0x7ffe2fee, 0x0158abd6), WTCP(0x7ffaf6f1, 0x023e6ee8), WTCP(0x7ff62182, 0x03242abf), + WTCP(0x7fefafb1, 0x0409dc76), WTCP(0x7fe7a192, 0x04ef8129), WTCP(0x7fddf741, 0x05d515f5), WTCP(0x7fd2b0da, 0x06ba97f4), + WTCP(0x7fc5ce84, 0x07a00445), WTCP(0x7fb75068, 0x08855802), WTCP(0x7fa736b4, 0x096a9049), WTCP(0x7f95819c, 0x0a4faa38), + WTCP(0x7f82315a, 0x0b34a2ec), WTCP(0x7f6d462b, 0x0c197784), WTCP(0x7f56c053, 0x0cfe251d), WTCP(0x7f3ea01a, 0x0de2a8d7), + WTCP(0x7f24e5cf, 0x0ec6ffd1), WTCP(0x7f0991c4, 0x0fab272b), WTCP(0x7eeca451, 0x108f1c07), WTCP(0x7ece1dd3, 0x1172db86), + WTCP(0x7eadfeae, 0x125662c9), WTCP(0x7e8c4748, 0x1339aef3), WTCP(0x7e68f80e, 0x141cbd28), WTCP(0x7e441171, 0x14ff8a8c), + WTCP(0x7e1d93ea, 0x15e21445), WTCP(0x7df57ff3, 0x16c45777), WTCP(0x7dcbd60e, 0x17a6514a), WTCP(0x7da096c2, 0x1887fee6), + WTCP(0x7d73c299, 0x19695d74), WTCP(0x7d455a24, 0x1a4a6a1c), WTCP(0x7d155df9, 0x1b2b220b), WTCP(0x7ce3ceb2, 0x1c0b826a), + WTCP(0x7cb0acef, 0x1ceb8869), WTCP(0x7c7bf954, 0x1dcb3134), WTCP(0x7c45b48d, 0x1eaa79fa), WTCP(0x7c0ddf47, 0x1f895fed), + WTCP(0x7bd47a36, 0x2067e03e), WTCP(0x7b998614, 0x2145f81f), WTCP(0x7b5d039e, 0x2223a4c5), WTCP(0x7b1ef397, 0x2300e366), + WTCP(0x7adf56c8, 0x23ddb139), WTCP(0x7a9e2dfd, 0x24ba0b76), WTCP(0x7a5b7a09, 0x2595ef56), WTCP(0x7a173bc2, 0x26715a16), + WTCP(0x79d17405, 0x274c48f2), WTCP(0x798a23b1, 0x2826b928), WTCP(0x79414bae, 0x2900a7f9), WTCP(0x78f6ece5, 0x29da12a7), + WTCP(0x78ab0847, 0x2ab2f674), WTCP(0x785d9ec8, 0x2b8b50a5), WTCP(0x780eb161, 0x2c631e82), WTCP(0x77be4111, 0x2d3a5d53), + WTCP(0x776c4edb, 0x2e110a62), WTCP(0x7718dbc8, 0x2ee722fb), WTCP(0x76c3e8e3, 0x2fbca46d), WTCP(0x766d773f, 0x30918c08), + WTCP(0x761587f3, 0x3165d71c), WTCP(0x75bc1c1a, 0x323982ff), WTCP(0x756134d4, 0x330c8d05), WTCP(0x7504d345, 0x33def287), + WTCP(0x74a6f899, 0x34b0b0df), WTCP(0x7447a5fc, 0x3581c569), WTCP(0x73e6dca3, 0x36522d83), WTCP(0x73849dc5, 0x3721e68d), + WTCP(0x7320ea9f, 0x37f0edea), WTCP(0x72bbc472, 0x38bf40ff), WTCP(0x72552c85, 0x398cdd32), WTCP(0x71ed2421, 0x3a59bfee), + WTCP(0x7183ac96, 0x3b25e69e), WTCP(0x7118c739, 0x3bf14eaf), WTCP(0x70ac7560, 0x3cbbf594), WTCP(0x703eb86a, 0x3d85d8bd), + WTCP(0x6fcf91b9, 0x3e4ef5a1), WTCP(0x6f5f02b2, 0x3f1749b8), WTCP(0x6eed0cc0, 0x3fded27c), WTCP(0x6e79b152, 0x40a58d69), + WTCP(0x6e04f1dd, 0x416b7801), WTCP(0x6d8ecfd8, 0x42308fc4), WTCP(0x6d174cc0, 0x42f4d237), WTCP(0x6c9e6a16, 0x43b83ce3), + WTCP(0x6c242960, 0x447acd50), WTCP(0x6ba88c28, 0x453c810d), WTCP(0x6b2b93fd, 0x45fd55a9), WTCP(0x6aad4270, 0x46bd48b7), + WTCP(0x6a2d9919, 0x477c57cb), WTCP(0x69ac9994, 0x483a807f), WTCP(0x692a4580, 0x48f7c06d), WTCP(0x68a69e81, 0x49b41533), + WTCP(0x6821a640, 0x4a6f7c74), WTCP(0x679b5e68, 0x4b29f3d1), WTCP(0x6713c8ac, 0x4be378f4), WTCP(0x668ae6bf, 0x4c9c0985), + WTCP(0x6600ba5b, 0x4d53a332), WTCP(0x6575453d, 0x4e0a43ab), WTCP(0x64e88926, 0x4ebfe8a5), WTCP(0x645a87dd, 0x4f748fd4), + WTCP(0x63cb432a, 0x502836f4), WTCP(0x633abcdc, 0x50dadbc1), WTCP(0x62a8f6c4, 0x518c7bfb), WTCP(0x6215f2b9, 0x523d1567), + WTCP(0x6181b292, 0x52eca5ca), WTCP(0x60ec3830, 0x539b2af0), WTCP(0x60558573, 0x5448a2a5), WTCP(0x5fbd9c41, 0x54f50abb), + WTCP(0x5f247e83, 0x55a06106), WTCP(0x5e8a2e27, 0x564aa35d), WTCP(0x5deead1f, 0x56f3cf9d), WTCP(0x5d51fd5e, 0x579be3a4), + WTCP(0x5cb420e0, 0x5842dd54), WTCP(0x5c15199f, 0x58e8ba94), WTCP(0x5b74e99d, 0x598d794c), WTCP(0x5ad392de, 0x5a31176a) +}; + + +const PWord16 SineWindow256[128] = +{ + WTCP(0x7fffd886, 0x006487e3), WTCP(0x7ffe9cb2, 0x012d96b1), WTCP(0x7ffc250f, 0x01f6a297), WTCP(0x7ff871a2, 0x02bfa9a4), + WTCP(0x7ff38274, 0x0388a9ea), WTCP(0x7fed5791, 0x0451a177), WTCP(0x7fe5f108, 0x051a8e5c), WTCP(0x7fdd4eec, 0x05e36ea9), + WTCP(0x7fd37153, 0x06ac406f), WTCP(0x7fc85854, 0x077501be), WTCP(0x7fbc040a, 0x083db0a7), WTCP(0x7fae7495, 0x09064b3a), + WTCP(0x7f9faa15, 0x09cecf89), WTCP(0x7f8fa4b0, 0x0a973ba5), WTCP(0x7f7e648c, 0x0b5f8d9f), WTCP(0x7f6be9d4, 0x0c27c389), + WTCP(0x7f5834b7, 0x0cefdb76), WTCP(0x7f434563, 0x0db7d376), WTCP(0x7f2d1c0e, 0x0e7fa99e), WTCP(0x7f15b8ee, 0x0f475bff), + WTCP(0x7efd1c3c, 0x100ee8ad), WTCP(0x7ee34636, 0x10d64dbd), WTCP(0x7ec8371a, 0x119d8941), WTCP(0x7eabef2c, 0x1264994e), + WTCP(0x7e8e6eb2, 0x132b7bf9), WTCP(0x7e6fb5f4, 0x13f22f58), WTCP(0x7e4fc53e, 0x14b8b17f), WTCP(0x7e2e9cdf, 0x157f0086), + WTCP(0x7e0c3d29, 0x16451a83), WTCP(0x7de8a670, 0x170afd8d), WTCP(0x7dc3d90d, 0x17d0a7bc), WTCP(0x7d9dd55a, 0x18961728), + WTCP(0x7d769bb5, 0x195b49ea), WTCP(0x7d4e2c7f, 0x1a203e1b), WTCP(0x7d24881b, 0x1ae4f1d6), WTCP(0x7cf9aef0, 0x1ba96335), + WTCP(0x7ccda169, 0x1c6d9053), WTCP(0x7ca05ff1, 0x1d31774d), WTCP(0x7c71eaf9, 0x1df5163f), WTCP(0x7c4242f2, 0x1eb86b46), + WTCP(0x7c116853, 0x1f7b7481), WTCP(0x7bdf5b94, 0x203e300d), WTCP(0x7bac1d31, 0x21009c0c), WTCP(0x7b77ada8, 0x21c2b69c), + WTCP(0x7b420d7a, 0x22847de0), WTCP(0x7b0b3d2c, 0x2345eff8), WTCP(0x7ad33d45, 0x24070b08), WTCP(0x7a9a0e50, 0x24c7cd33), + WTCP(0x7a5fb0d8, 0x2588349d), WTCP(0x7a24256f, 0x26483f6c), WTCP(0x79e76ca7, 0x2707ebc7), WTCP(0x79a98715, 0x27c737d3), + WTCP(0x796a7554, 0x288621b9), WTCP(0x792a37fe, 0x2944a7a2), WTCP(0x78e8cfb2, 0x2a02c7b8), WTCP(0x78a63d11, 0x2ac08026), + WTCP(0x786280bf, 0x2b7dcf17), WTCP(0x781d9b65, 0x2c3ab2b9), WTCP(0x77d78daa, 0x2cf72939), WTCP(0x7790583e, 0x2db330c7), + WTCP(0x7747fbce, 0x2e6ec792), WTCP(0x76fe790e, 0x2f29ebcc), WTCP(0x76b3d0b4, 0x2fe49ba7), WTCP(0x76680376, 0x309ed556), + WTCP(0x761b1211, 0x3158970e), WTCP(0x75ccfd42, 0x3211df04), WTCP(0x757dc5ca, 0x32caab6f), WTCP(0x752d6c6c, 0x3382fa88), + WTCP(0x74dbf1ef, 0x343aca87), WTCP(0x7489571c, 0x34f219a8), WTCP(0x74359cbd, 0x35a8e625), WTCP(0x73e0c3a3, 0x365f2e3b), + WTCP(0x738acc9e, 0x3714f02a), WTCP(0x7333b883, 0x37ca2a30), WTCP(0x72db8828, 0x387eda8e), WTCP(0x72823c67, 0x3932ff87), + WTCP(0x7227d61c, 0x39e6975e), WTCP(0x71cc5626, 0x3a99a057), WTCP(0x716fbd68, 0x3b4c18ba), WTCP(0x71120cc5, 0x3bfdfecd), + WTCP(0x70b34525, 0x3caf50da), WTCP(0x70536771, 0x3d600d2c), WTCP(0x6ff27497, 0x3e10320d), WTCP(0x6f906d84, 0x3ebfbdcd), + WTCP(0x6f2d532c, 0x3f6eaeb8), WTCP(0x6ec92683, 0x401d0321), WTCP(0x6e63e87f, 0x40cab958), WTCP(0x6dfd9a1c, 0x4177cfb1), + WTCP(0x6d963c54, 0x42244481), WTCP(0x6d2dd027, 0x42d0161e), WTCP(0x6cc45698, 0x437b42e1), WTCP(0x6c59d0a9, 0x4425c923), + WTCP(0x6bee3f62, 0x44cfa740), WTCP(0x6b81a3cd, 0x4578db93), WTCP(0x6b13fef5, 0x4621647d), WTCP(0x6aa551e9, 0x46c9405c), + WTCP(0x6a359db9, 0x47706d93), WTCP(0x69c4e37a, 0x4816ea86), WTCP(0x69532442, 0x48bcb599), WTCP(0x68e06129, 0x4961cd33), + WTCP(0x686c9b4b, 0x4a062fbd), WTCP(0x67f7d3c5, 0x4aa9dba2), WTCP(0x67820bb7, 0x4b4ccf4d), WTCP(0x670b4444, 0x4bef092d), + WTCP(0x66937e91, 0x4c9087b1), WTCP(0x661abbc5, 0x4d31494b), WTCP(0x65a0fd0b, 0x4dd14c6e), WTCP(0x6526438f, 0x4e708f8f), + WTCP(0x64aa907f, 0x4f0f1126), WTCP(0x642de50d, 0x4faccfab), WTCP(0x63b0426d, 0x5049c999), WTCP(0x6331a9d4, 0x50e5fd6d), + WTCP(0x62b21c7b, 0x518169a5), WTCP(0x62319b9d, 0x521c0cc2), WTCP(0x61b02876, 0x52b5e546), WTCP(0x612dc447, 0x534ef1b5), + WTCP(0x60aa7050, 0x53e73097), WTCP(0x60262dd6, 0x547ea073), WTCP(0x5fa0fe1f, 0x55153fd4), WTCP(0x5f1ae274, 0x55ab0d46), + WTCP(0x5e93dc1f, 0x56400758), WTCP(0x5e0bec6e, 0x56d42c99), WTCP(0x5d8314b1, 0x57677b9d), WTCP(0x5cf95638, 0x57f9f2f8), + WTCP(0x5c6eb258, 0x588b9140), WTCP(0x5be32a67, 0x591c550e), WTCP(0x5b56bfbd, 0x59ac3cfd), WTCP(0x5ac973b5, 0x5a3b47ab), +}; + +const PWord16 SineWindow280[140] = +{ + WTCP(0x7fffdf00, 0x005be9f6), WTCP(0x7ffed6ff, 0x0113bd23), WTCP(0x7ffcc6ff, 0x01cb8e18), WTCP(0x7ff9af04, 0x02835b5a), + WTCP(0x7ff58f15, 0x033b236c), WTCP(0x7ff0673a, 0x03f2e4d4), WTCP(0x7fea377e, 0x04aa9e17), WTCP(0x7fe2ffee, 0x05624dba), + WTCP(0x7fdac098, 0x0619f243), WTCP(0x7fd1798e, 0x06d18a36), WTCP(0x7fc72ae2, 0x07891418), WTCP(0x7fbbd4aa, 0x08408e70), + WTCP(0x7faf76fe, 0x08f7f7c3), WTCP(0x7fa211f6, 0x09af4e96), WTCP(0x7f93a5af, 0x0a66916f), WTCP(0x7f843246, 0x0b1dbed5), + WTCP(0x7f73b7da, 0x0bd4d54d), WTCP(0x7f62368f, 0x0c8bd35e), WTCP(0x7f4fae88, 0x0d42b78f), WTCP(0x7f3c1fec, 0x0df98066), + WTCP(0x7f278ae1, 0x0eb02c6a), WTCP(0x7f11ef95, 0x0f66ba22), WTCP(0x7efb4e31, 0x101d2817), WTCP(0x7ee3a6e7, 0x10d374cf), + WTCP(0x7ecaf9e5, 0x11899ed3), WTCP(0x7eb1475f, 0x123fa4ab), WTCP(0x7e968f8b, 0x12f584e0), WTCP(0x7e7ad29e, 0x13ab3dfa), + WTCP(0x7e5e10d3, 0x1460ce82), WTCP(0x7e404a65, 0x15163503), WTCP(0x7e217f90, 0x15cb7006), WTCP(0x7e01b096, 0x16807e15), + WTCP(0x7de0ddb6, 0x17355dba), WTCP(0x7dbf0736, 0x17ea0d81), WTCP(0x7d9c2d5a, 0x189e8bf6), WTCP(0x7d78506a, 0x1952d7a3), + WTCP(0x7d5370b2, 0x1a06ef15), WTCP(0x7d2d8e7b, 0x1abad0d8), WTCP(0x7d06aa16, 0x1b6e7b7a), WTCP(0x7cdec3d2, 0x1c21ed87), + WTCP(0x7cb5dc00, 0x1cd5258f), WTCP(0x7c8bf2f7, 0x1d88221e), WTCP(0x7c61090b, 0x1e3ae1c5), WTCP(0x7c351e96, 0x1eed6311), + WTCP(0x7c0833f3, 0x1f9fa494), WTCP(0x7bda497d, 0x2051a4dd), WTCP(0x7bab5f93, 0x2103627d), WTCP(0x7b7b7697, 0x21b4dc06), + WTCP(0x7b4a8eeb, 0x2266100a), WTCP(0x7b18a8f4, 0x2316fd1b), WTCP(0x7ae5c518, 0x23c7a1cc), WTCP(0x7ab1e3c2, 0x2477fcb1), + WTCP(0x7a7d055b, 0x25280c5e), WTCP(0x7a472a51, 0x25d7cf68), WTCP(0x7a105313, 0x26874464), WTCP(0x79d88013, 0x273669e9), + WTCP(0x799fb1c2, 0x27e53e8e), WTCP(0x7965e897, 0x2893c0e9), WTCP(0x792b2508, 0x2941ef93), WTCP(0x78ef678f, 0x29efc925), + WTCP(0x78b2b0a7, 0x2a9d4c38), WTCP(0x787500ce, 0x2b4a7766), WTCP(0x78365881, 0x2bf7494a), WTCP(0x77f6b844, 0x2ca3c07f), + WTCP(0x77b62098, 0x2d4fdba2), WTCP(0x77749203, 0x2dfb9950), WTCP(0x77320d0d, 0x2ea6f827), WTCP(0x76ee923e, 0x2f51f6c4), + WTCP(0x76aa2222, 0x2ffc93c9), WTCP(0x7664bd46, 0x30a6cdd3), WTCP(0x761e6439, 0x3150a385), WTCP(0x75d7178c, 0x31fa1381), + WTCP(0x758ed7d2, 0x32a31c68), WTCP(0x7545a5a0, 0x334bbcde), WTCP(0x74fb818e, 0x33f3f387), WTCP(0x74b06c33, 0x349bbf09), + WTCP(0x7464662c, 0x35431e09), WTCP(0x74177014, 0x35ea0f2e), WTCP(0x73c98a8a, 0x36909120), WTCP(0x737ab630, 0x3736a287), + WTCP(0x732af3a7, 0x37dc420c), WTCP(0x72da4395, 0x38816e5b), WTCP(0x7288a69f, 0x3926261e), WTCP(0x72361d6e, 0x39ca6802), + WTCP(0x71e2a8ad, 0x3a6e32b4), WTCP(0x718e4907, 0x3b1184e2), WTCP(0x7138ff2a, 0x3bb45d3b), WTCP(0x70e2cbc6, 0x3c56ba70), + WTCP(0x708baf8d, 0x3cf89b31), WTCP(0x7033ab34, 0x3d99fe31), WTCP(0x6fdabf6e, 0x3e3ae223), WTCP(0x6f80ecf4, 0x3edb45ba), + WTCP(0x6f26347f, 0x3f7b27ac), WTCP(0x6eca96ca, 0x401a86b0), WTCP(0x6e6e1492, 0x40b9617d), WTCP(0x6e10ae96, 0x4157b6ca), + WTCP(0x6db26597, 0x41f58552), WTCP(0x6d533a56, 0x4292cbcf), WTCP(0x6cf32d99, 0x432f88fc), WTCP(0x6c924024, 0x43cbbb97), + WTCP(0x6c3072c1, 0x4467625d), WTCP(0x6bcdc639, 0x45027c0c), WTCP(0x6b6a3b58, 0x459d0766), WTCP(0x6b05d2ea, 0x4637032c), + WTCP(0x6aa08dbf, 0x46d06e1f), WTCP(0x6a3a6ca8, 0x47694703), WTCP(0x69d37078, 0x48018c9e), WTCP(0x696b9a02, 0x48993db5), + WTCP(0x6902ea1d, 0x4930590f), WTCP(0x689961a1, 0x49c6dd74), WTCP(0x682f0167, 0x4a5cc9af), WTCP(0x67c3ca4c, 0x4af21c89), + WTCP(0x6757bd2b, 0x4b86d4cf), WTCP(0x66eadae5, 0x4c1af14f), WTCP(0x667d2459, 0x4cae70d6), WTCP(0x660e9a6a, 0x4d415234), + WTCP(0x659f3dfc, 0x4dd3943b), WTCP(0x652f0ff4, 0x4e6535bd), WTCP(0x64be113a, 0x4ef6358d), WTCP(0x644c42b8, 0x4f869280), + WTCP(0x63d9a556, 0x50164b6d), WTCP(0x63663a03, 0x50a55f2c), WTCP(0x62f201ac, 0x5133cc94), WTCP(0x627cfd41, 0x51c19281), + WTCP(0x62072db3, 0x524eafce), WTCP(0x619093f5, 0x52db2357), WTCP(0x611930fc, 0x5366ebfc), WTCP(0x60a105be, 0x53f2089b), + WTCP(0x60281333, 0x547c7817), WTCP(0x5fae5a55, 0x55063951), WTCP(0x5f33dc1d, 0x558f4b2d), WTCP(0x5eb8998a, 0x5617ac90), + WTCP(0x5e3c9399, 0x569f5c62), WTCP(0x5dbfcb4a, 0x5726598b), WTCP(0x5d42419f, 0x57aca2f3), WTCP(0x5cc3f79a, 0x58323787), + WTCP(0x5c44ee40, 0x58b71632), WTCP(0x5bc52696, 0x593b3de2), WTCP(0x5b44a1a5, 0x59bead87), WTCP(0x5ac36076, 0x5a416413) +}; + +const PWord16 SineWindow320[160] = +{ + WTCP(0x7fffe6bc, 0x00506cb9), WTCP(0x7fff1c9b, 0x00f145ab), WTCP(0x7ffd885a, 0x01921d20), WTCP(0x7ffb29fd, 0x0232f21a), + WTCP(0x7ff80186, 0x02d3c39b), WTCP(0x7ff40efa, 0x037490a5), WTCP(0x7fef5260, 0x0415583b), WTCP(0x7fe9cbc0, 0x04b6195d), + WTCP(0x7fe37b22, 0x0556d30f), WTCP(0x7fdc608f, 0x05f78453), WTCP(0x7fd47c14, 0x06982c2b), WTCP(0x7fcbcdbc, 0x0738c998), + WTCP(0x7fc25596, 0x07d95b9e), WTCP(0x7fb813b0, 0x0879e140), WTCP(0x7fad081b, 0x091a597e), WTCP(0x7fa132e8, 0x09bac35d), + WTCP(0x7f949429, 0x0a5b1dde), WTCP(0x7f872bf3, 0x0afb6805), WTCP(0x7f78fa5b, 0x0b9ba0d5), WTCP(0x7f69ff76, 0x0c3bc74f), + WTCP(0x7f5a3b5e, 0x0cdbda79), WTCP(0x7f49ae2a, 0x0d7bd954), WTCP(0x7f3857f6, 0x0e1bc2e4), WTCP(0x7f2638db, 0x0ebb962c), + WTCP(0x7f1350f8, 0x0f5b5231), WTCP(0x7effa069, 0x0ffaf5f6), WTCP(0x7eeb274d, 0x109a807e), WTCP(0x7ed5e5c6, 0x1139f0cf), + WTCP(0x7ebfdbf5, 0x11d945eb), WTCP(0x7ea909fc, 0x12787ed8), WTCP(0x7e917000, 0x13179a9b), WTCP(0x7e790e25, 0x13b69836), + WTCP(0x7e5fe493, 0x145576b1), WTCP(0x7e45f371, 0x14f43510), WTCP(0x7e2b3ae8, 0x1592d257), WTCP(0x7e0fbb22, 0x16314d8e), + WTCP(0x7df3744b, 0x16cfa5b9), WTCP(0x7dd6668f, 0x176dd9de), WTCP(0x7db8921c, 0x180be904), WTCP(0x7d99f721, 0x18a9d231), + WTCP(0x7d7a95cf, 0x1947946c), WTCP(0x7d5a6e57, 0x19e52ebb), WTCP(0x7d3980ec, 0x1a82a026), WTCP(0x7d17cdc2, 0x1b1fe7b3), + WTCP(0x7cf5550e, 0x1bbd046c), WTCP(0x7cd21707, 0x1c59f557), WTCP(0x7cae13e4, 0x1cf6b97c), WTCP(0x7c894bde, 0x1d934fe5), + WTCP(0x7c63bf2f, 0x1e2fb79a), WTCP(0x7c3d6e13, 0x1ecbefa4), WTCP(0x7c1658c5, 0x1f67f70b), WTCP(0x7bee7f85, 0x2003ccdb), + WTCP(0x7bc5e290, 0x209f701c), WTCP(0x7b9c8226, 0x213adfda), WTCP(0x7b725e8a, 0x21d61b1e), WTCP(0x7b4777fe, 0x227120f3), + WTCP(0x7b1bcec4, 0x230bf065), WTCP(0x7aef6323, 0x23a6887f), WTCP(0x7ac23561, 0x2440e84d), WTCP(0x7a9445c5, 0x24db0edb), + WTCP(0x7a659496, 0x2574fb36), WTCP(0x7a362220, 0x260eac6a), WTCP(0x7a05eead, 0x26a82186), WTCP(0x79d4fa89, 0x27415996), + WTCP(0x79a34602, 0x27da53a9), WTCP(0x7970d165, 0x28730ecd), WTCP(0x793d9d03, 0x290b8a12), WTCP(0x7909a92d, 0x29a3c485), + WTCP(0x78d4f634, 0x2a3bbd37), WTCP(0x789f846b, 0x2ad37338), WTCP(0x78695428, 0x2b6ae598), WTCP(0x783265c0, 0x2c021369), + WTCP(0x77fab989, 0x2c98fbba), WTCP(0x77c24fdb, 0x2d2f9d9f), WTCP(0x77892910, 0x2dc5f829), WTCP(0x774f4581, 0x2e5c0a6b), + WTCP(0x7714a58b, 0x2ef1d377), WTCP(0x76d94989, 0x2f875262), WTCP(0x769d31d9, 0x301c863f), WTCP(0x76605edb, 0x30b16e23), + WTCP(0x7622d0ef, 0x31460922), WTCP(0x75e48874, 0x31da5651), WTCP(0x75a585cf, 0x326e54c7), WTCP(0x7565c962, 0x3302039b), + WTCP(0x75255392, 0x339561e1), WTCP(0x74e424c5, 0x34286eb3), WTCP(0x74a23d62, 0x34bb2927), WTCP(0x745f9dd1, 0x354d9057), + WTCP(0x741c467b, 0x35dfa35a), WTCP(0x73d837ca, 0x3671614b), WTCP(0x7393722a, 0x3702c942), WTCP(0x734df607, 0x3793da5b), + WTCP(0x7307c3d0, 0x382493b0), WTCP(0x72c0dbf3, 0x38b4f45d), WTCP(0x72793edf, 0x3944fb7e), WTCP(0x7230ed07, 0x39d4a82f), + WTCP(0x71e7e6dc, 0x3a63f98d), WTCP(0x719e2cd2, 0x3af2eeb7), WTCP(0x7153bf5d, 0x3b8186ca), WTCP(0x71089ef2, 0x3c0fc0e6), + WTCP(0x70bccc09, 0x3c9d9c28), WTCP(0x70704718, 0x3d2b17b3), WTCP(0x7023109a, 0x3db832a6), WTCP(0x6fd52907, 0x3e44ec22), + WTCP(0x6f8690db, 0x3ed14349), WTCP(0x6f374891, 0x3f5d373e), WTCP(0x6ee750a8, 0x3fe8c724), WTCP(0x6e96a99d, 0x4073f21d), + WTCP(0x6e4553ef, 0x40feb74f), WTCP(0x6df35020, 0x418915de), WTCP(0x6da09eb1, 0x42130cf0), WTCP(0x6d4d4023, 0x429c9bab), + WTCP(0x6cf934fc, 0x4325c135), WTCP(0x6ca47dbf, 0x43ae7cb7), WTCP(0x6c4f1af2, 0x4436cd58), WTCP(0x6bf90d1d, 0x44beb240), + WTCP(0x6ba254c7, 0x45462a9a), WTCP(0x6b4af279, 0x45cd358f), WTCP(0x6af2e6bc, 0x4653d24b), WTCP(0x6a9a321d, 0x46d9fff8), + WTCP(0x6a40d527, 0x475fbdc3), WTCP(0x69e6d067, 0x47e50ad8), WTCP(0x698c246c, 0x4869e665), WTCP(0x6930d1c4, 0x48ee4f98), + WTCP(0x68d4d900, 0x497245a1), WTCP(0x68783ab1, 0x49f5c7ae), WTCP(0x681af76a, 0x4a78d4f0), WTCP(0x67bd0fbd, 0x4afb6c98), + WTCP(0x675e843e, 0x4b7d8dd8), WTCP(0x66ff5584, 0x4bff37e2), WTCP(0x669f8425, 0x4c8069ea), WTCP(0x663f10b7, 0x4d012324), + WTCP(0x65ddfbd3, 0x4d8162c4), WTCP(0x657c4613, 0x4e012800), WTCP(0x6519f010, 0x4e80720e), WTCP(0x64b6fa66, 0x4eff4025), + WTCP(0x645365b2, 0x4f7d917c), WTCP(0x63ef3290, 0x4ffb654d), WTCP(0x638a619e, 0x5078bad1), WTCP(0x6324f37d, 0x50f59141), + WTCP(0x62bee8cc, 0x5171e7d9), WTCP(0x6258422c, 0x51edbdd4), WTCP(0x61f1003f, 0x5269126e), WTCP(0x618923a9, 0x52e3e4e6), + WTCP(0x6120ad0d, 0x535e3479), WTCP(0x60b79d10, 0x53d80065), WTCP(0x604df459, 0x545147eb), WTCP(0x5fe3b38d, 0x54ca0a4b), + WTCP(0x5f78db56, 0x554246c6), WTCP(0x5f0d6c5b, 0x55b9fc9e), WTCP(0x5ea16747, 0x56312b17), WTCP(0x5e34ccc3, 0x56a7d174), + WTCP(0x5dc79d7c, 0x571deefa), WTCP(0x5d59da1e, 0x579382ee), WTCP(0x5ceb8355, 0x58088c96), WTCP(0x5c7c99d1, 0x587d0b3b), + WTCP(0x5c0d1e41, 0x58f0fe23), WTCP(0x5b9d1154, 0x59646498), WTCP(0x5b2c73bb, 0x59d73de3), WTCP(0x5abb4629, 0x5a498950), +}; + + +const PWord16 SineWindow420[210] = +{ + WTCP(0x7ffff155, 0x003d46a7), WTCP(0x7fff7bff, 0x00b7d3bc), WTCP(0x7ffe9154, 0x01326029), WTCP(0x7ffd3154, 0x01aceb7c), + WTCP(0x7ffb5c00, 0x02277547), WTCP(0x7ff9115b, 0x02a1fd18), WTCP(0x7ff65166, 0x031c8280), WTCP(0x7ff31c25, 0x0397050d), + WTCP(0x7fef7199, 0x0411844f), WTCP(0x7feb51c6, 0x048bffd7), WTCP(0x7fe6bcb0, 0x05067734), WTCP(0x7fe1b25b, 0x0580e9f6), + WTCP(0x7fdc32cc, 0x05fb57ac), WTCP(0x7fd63e09, 0x0675bfe7), WTCP(0x7fcfd415, 0x06f02235), WTCP(0x7fc8f4f7, 0x076a7e27), + WTCP(0x7fc1a0b6, 0x07e4d34d), WTCP(0x7fb9d759, 0x085f2137), WTCP(0x7fb198e5, 0x08d96773), WTCP(0x7fa8e564, 0x0953a594), + WTCP(0x7f9fbcdc, 0x09cddb27), WTCP(0x7f961f57, 0x0a4807be), WTCP(0x7f8c0cdc, 0x0ac22ae8), WTCP(0x7f818577, 0x0b3c4435), + WTCP(0x7f76892f, 0x0bb65336), WTCP(0x7f6b180f, 0x0c30577a), WTCP(0x7f5f3221, 0x0caa5092), WTCP(0x7f52d771, 0x0d243e0d), + WTCP(0x7f46080a, 0x0d9e1f7d), WTCP(0x7f38c3f7, 0x0e17f471), WTCP(0x7f2b0b45, 0x0e91bc79), WTCP(0x7f1cde01, 0x0f0b7727), + WTCP(0x7f0e3c36, 0x0f85240a), WTCP(0x7eff25f3, 0x0ffec2b3), WTCP(0x7eef9b46, 0x107852b2), WTCP(0x7edf9c3c, 0x10f1d398), + WTCP(0x7ecf28e5, 0x116b44f6), WTCP(0x7ebe414f, 0x11e4a65c), WTCP(0x7eace58a, 0x125df75b), WTCP(0x7e9b15a6, 0x12d73784), + WTCP(0x7e88d1b4, 0x13506668), WTCP(0x7e7619c3, 0x13c98397), WTCP(0x7e62ede5, 0x14428ea2), WTCP(0x7e4f4e2c, 0x14bb871b), + WTCP(0x7e3b3aaa, 0x15346c93), WTCP(0x7e26b371, 0x15ad3e9a), WTCP(0x7e11b894, 0x1625fcc3), WTCP(0x7dfc4a26, 0x169ea69e), + WTCP(0x7de6683a, 0x17173bbd), WTCP(0x7dd012e6, 0x178fbbb1), WTCP(0x7db94a3c, 0x1808260c), WTCP(0x7da20e53, 0x18807a5f), + WTCP(0x7d8a5f40, 0x18f8b83c), WTCP(0x7d723d18, 0x1970df36), WTCP(0x7d59a7f1, 0x19e8eedd), WTCP(0x7d409fe1, 0x1a60e6c3), + WTCP(0x7d272501, 0x1ad8c67c), WTCP(0x7d0d3767, 0x1b508d98), WTCP(0x7cf2d72b, 0x1bc83baa), WTCP(0x7cd80464, 0x1c3fd045), + WTCP(0x7cbcbf2d, 0x1cb74afa), WTCP(0x7ca1079d, 0x1d2eab5d), WTCP(0x7c84ddcf, 0x1da5f0ff), WTCP(0x7c6841db, 0x1e1d1b73), + WTCP(0x7c4b33dc, 0x1e942a4d), WTCP(0x7c2db3ee, 0x1f0b1d1f), WTCP(0x7c0fc22a, 0x1f81f37c), WTCP(0x7bf15eac, 0x1ff8acf7), + WTCP(0x7bd28991, 0x206f4923), WTCP(0x7bb342f3, 0x20e5c793), WTCP(0x7b938af1, 0x215c27dc), WTCP(0x7b7361a7, 0x21d2698f), + WTCP(0x7b52c733, 0x22488c42), WTCP(0x7b31bbb2, 0x22be8f87), WTCP(0x7b103f43, 0x233472f3), WTCP(0x7aee5205, 0x23aa361a), + WTCP(0x7acbf416, 0x241fd88e), WTCP(0x7aa92596, 0x249559e6), WTCP(0x7a85e6a5, 0x250ab9b4), WTCP(0x7a623764, 0x257ff78e), + WTCP(0x7a3e17f2, 0x25f51307), WTCP(0x7a198872, 0x266a0bb5), WTCP(0x79f48904, 0x26dee12c), WTCP(0x79cf19cb, 0x27539302), + WTCP(0x79a93ae9, 0x27c820ca), WTCP(0x7982ec80, 0x283c8a1b), WTCP(0x795c2eb5, 0x28b0ce8a), WTCP(0x793501a9, 0x2924edac), + WTCP(0x790d6581, 0x2998e716), WTCP(0x78e55a62, 0x2a0cba5e), WTCP(0x78bce070, 0x2a80671b), WTCP(0x7893f7d1, 0x2af3ece2), + WTCP(0x786aa0a9, 0x2b674b49), WTCP(0x7840db1f, 0x2bda81e6), WTCP(0x7816a759, 0x2c4d9050), WTCP(0x77ec057d, 0x2cc0761e), + WTCP(0x77c0f5b3, 0x2d3332e5), WTCP(0x77957822, 0x2da5c63e), WTCP(0x77698cf3, 0x2e182fbe), WTCP(0x773d344d, 0x2e8a6efd), + WTCP(0x77106e58, 0x2efc8393), WTCP(0x76e33b3f, 0x2f6e6d16), WTCP(0x76b59b2a, 0x2fe02b1e), WTCP(0x76878e43, 0x3051bd43), + WTCP(0x765914b5, 0x30c3231d), WTCP(0x762a2eaa, 0x31345c44), WTCP(0x75fadc4d, 0x31a56850), WTCP(0x75cb1dca, 0x321646d9), + WTCP(0x759af34c, 0x3286f779), WTCP(0x756a5cff, 0x32f779c7), WTCP(0x75395b10, 0x3367cd5d), WTCP(0x7507edac, 0x33d7f1d3), + WTCP(0x74d61500, 0x3447e6c3), WTCP(0x74a3d13a, 0x34b7abc6), WTCP(0x74712288, 0x35274076), WTCP(0x743e0918, 0x3596a46c), + WTCP(0x740a8519, 0x3605d743), WTCP(0x73d696bb, 0x3674d894), WTCP(0x73a23e2d, 0x36e3a7fa), WTCP(0x736d7b9f, 0x3752450f), + WTCP(0x73384f41, 0x37c0af6d), WTCP(0x7302b945, 0x382ee6b0), WTCP(0x72ccb9db, 0x389cea72), WTCP(0x72965134, 0x390aba4f), + WTCP(0x725f7f84, 0x397855e1), WTCP(0x722844fb, 0x39e5bcc5), WTCP(0x71f0a1cc, 0x3a52ee96), WTCP(0x71b8962b, 0x3abfeaf1), + WTCP(0x7180224b, 0x3b2cb170), WTCP(0x71474660, 0x3b9941b1), WTCP(0x710e029e, 0x3c059b4f), WTCP(0x70d45738, 0x3c71bde8), + WTCP(0x709a4465, 0x3cdda919), WTCP(0x705fca59, 0x3d495c7e), WTCP(0x7024e94b, 0x3db4d7b5), WTCP(0x6fe9a16f, 0x3e201a5b), + WTCP(0x6fadf2fc, 0x3e8b240e), WTCP(0x6f71de2a, 0x3ef5f46c), WTCP(0x6f35632e, 0x3f608b13), WTCP(0x6ef88241, 0x3fcae7a1), + WTCP(0x6ebb3b9a, 0x403509b4), WTCP(0x6e7d8f72, 0x409ef0ed), WTCP(0x6e3f7e01, 0x41089ce8), WTCP(0x6e010780, 0x41720d46), + WTCP(0x6dc22c28, 0x41db41a5), WTCP(0x6d82ec32, 0x424439a6), WTCP(0x6d4347da, 0x42acf4e8), WTCP(0x6d033f58, 0x4315730c), + WTCP(0x6cc2d2e9, 0x437db3b0), WTCP(0x6c8202c6, 0x43e5b676), WTCP(0x6c40cf2c, 0x444d7aff), WTCP(0x6bff3855, 0x44b500eb), + WTCP(0x6bbd3e7f, 0x451c47dc), WTCP(0x6b7ae1e6, 0x45834f72), WTCP(0x6b3822c6, 0x45ea1750), WTCP(0x6af5015c, 0x46509f16), + WTCP(0x6ab17de7, 0x46b6e668), WTCP(0x6a6d98a4, 0x471cece7), WTCP(0x6a2951d2, 0x4782b236), WTCP(0x69e4a9ae, 0x47e835f7), + WTCP(0x699fa078, 0x484d77ce), WTCP(0x695a366f, 0x48b2775d), WTCP(0x69146bd3, 0x49173448), WTCP(0x68ce40e4, 0x497bae33), + WTCP(0x6887b5e2, 0x49dfe4c2), WTCP(0x6840cb0e, 0x4a43d799), WTCP(0x67f980a8, 0x4aa7865b), WTCP(0x67b1d6f3, 0x4b0af0ae), + WTCP(0x6769ce2f, 0x4b6e1637), WTCP(0x6721669f, 0x4bd0f69b), WTCP(0x66d8a085, 0x4c33917f), WTCP(0x668f7c25, 0x4c95e688), + WTCP(0x6645f9c0, 0x4cf7f55d), WTCP(0x65fc199a, 0x4d59bda3), WTCP(0x65b1dbf8, 0x4dbb3f02), WTCP(0x6567411d, 0x4e1c791f), + WTCP(0x651c494d, 0x4e7d6ba2), WTCP(0x64d0f4ce, 0x4ede1631), WTCP(0x648543e4, 0x4f3e7875), WTCP(0x643936d4, 0x4f9e9214), + WTCP(0x63eccde5, 0x4ffe62b6), WTCP(0x63a0095c, 0x505dea05), WTCP(0x6352e980, 0x50bd27a7), WTCP(0x63056e98, 0x511c1b47), + WTCP(0x62b798ea, 0x517ac48c), WTCP(0x626968be, 0x51d92321), WTCP(0x621ade5c, 0x523736ae), WTCP(0x61cbfa0b, 0x5294fedd), + WTCP(0x617cbc14, 0x52f27b58), WTCP(0x612d24c0, 0x534fabcb), WTCP(0x60dd3457, 0x53ac8fde), WTCP(0x608ceb22, 0x5409273e), + WTCP(0x603c496c, 0x54657194), WTCP(0x5feb4f7f, 0x54c16e8e), WTCP(0x5f99fda4, 0x551d1dd5), WTCP(0x5f485426, 0x55787f17), + WTCP(0x5ef6534f, 0x55d391ff), WTCP(0x5ea3fb6c, 0x562e563a), WTCP(0x5e514cc8, 0x5688cb75), WTCP(0x5dfe47ad, 0x56e2f15d), + WTCP(0x5daaec6a, 0x573cc79f), WTCP(0x5d573b49, 0x57964de9), WTCP(0x5d033497, 0x57ef83e9), WTCP(0x5caed8a2, 0x5848694d), + WTCP(0x5c5a27b8, 0x58a0fdc3), WTCP(0x5c052224, 0x58f940fa), WTCP(0x5bafc837, 0x595132a2), WTCP(0x5b5a1a3d, 0x59a8d26a), + WTCP(0x5b041885, 0x5a002001), WTCP(0x5aadc35e, 0x5a571b18) +}; + + + + +/** + * \brief Helper table containing the length, rasterand shape mapping to individual window slope tables. + * [0: sine ][0: radix2 raster ][ceil(log2(length)) length 4 .. 1024 ] + * [1: 640 raster + */ +const PWord16 *const windowSlopes[1][2][8] = +{ + { /* Sine */ + { /* Radix 2 */ + NULL, + NULL, + SineWindow16, + SineWindow32, + SineWindow64, + SineWindow128, + SineWindow256, + NULL + }, + { /* 640 raster */ + NULL, /* 2.5 */ + NULL, /* 5 */ + SineWindow10, + SineWindow20, + SineWindow40, + SineWindow80, + SineWindow160, + SineWindow320 + }, + } +}; + +#define DCTIV_SINETABLE SineTable512 +#define DCTIV_SINETABLE_SIZE_LD 9 + +#define DCTIV_SINETABLE320 SineTable320 +#define DCTIV_SINETABLE320_SIZE_LD 8 + +void BASOP_getTables(const PWord16 **ptwiddle, const PWord16 **sin_twiddle, Word16 *psin_step, Word16 length) +{ + const PWord16 *twiddle; + const PWord16 *sine; + Word16 ld2_length, sin_step; + + /* Get ld2 of length - 2 + 1 + -2: because first table entry is window of size 4 + +1: because we already include +1 because of ceil(log2(length)) */ + ld2_length = sub(16 -1 -1, norm_s(length)); + + /* Extract sort of "eigenvalue" (the 5 left most bits) of length. */ + SWITCH ( (unsigned short)lshl(length, sub(15, ld2_length) ) ) + { + case 0xa000: /* 640 */ + move16(); + move16(); + sine = DCTIV_SINETABLE320; + sin_step = shl(1, sub(DCTIV_SINETABLE320_SIZE_LD+1, ld2_length)); + twiddle = windowSlopes[0][1][sub(ld2_length,1)]; + BREAK; + + case 0x8000: /* radix 2 */ + move16(); + move16(); + sine = DCTIV_SINETABLE; + sin_step = shl(1, sub(DCTIV_SINETABLE_SIZE_LD+1, ld2_length)); + twiddle = windowSlopes[0][0][sub(ld2_length,2)]; + BREAK; + + default: /* not instrumented, probably obsolete */ + sine = NULL; + sin_step = 0; + twiddle = NULL; + BREAK; + } + + if (ptwiddle != NULL) + { + assert(twiddle != NULL || length == 0); + move16(); + *ptwiddle = twiddle; + } + + if (sin_twiddle != NULL) + { + move16(); + *sin_twiddle = sine; + } + if ( psin_step != NULL ) + { + assert(sin_step > 0 || length == 0); + move16(); + *psin_step = sin_step; + } +} + +const PWord16* getSineWindowTable(Word16 length) +{ + const PWord16 *p = NULL; + + switch (length) + { + case 10: + p = SineWindow10; + BREAK; + case 16: + p = SineWindow16; + BREAK; + case 20: + p = SineWindow20; + BREAK; + case 30: + p = SineWindow30; + BREAK; + case 32: + p = SineWindow32; + BREAK; + case 40: + p = SineWindow40; + BREAK; + case 48: + p = SineWindow48; + BREAK; + case 60: + p = SineWindow60; + BREAK; + case 70: + p = SineWindow70; + BREAK; + case 96: + p = SineWindow96; + BREAK; + case 112: + p = SineWindow112; + BREAK; + case 120: + p = SineWindow120; + BREAK; + case 140: + p = SineWindow140; + BREAK; + case 180: + p = SineWindow180; + BREAK; + case 224: + p = SineWindow224; + BREAK; + case 280: + p = SineWindow280; + BREAK; + case 420: + p = SineWindow420; + BREAK; + } + + assert(p != NULL); + + return p; +} + diff --git a/lib_com/rom_basop_util.h b/lib_com/rom_basop_util.h new file mode 100644 index 0000000..5f23589 --- /dev/null +++ b/lib_com/rom_basop_util.h @@ -0,0 +1,81 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#ifndef __BASOP_UTIL_ROM_H__ +#define __BASOP_UTIL_ROM_H__ + +#include "typedef.h" +#include "basop_util.h" + +#define LD_INT_TAB_LEN 120 +#define INV_TABLE_SIZE 256 +#define SQRT_TABLE_SIZE 256 + +#ifndef CHEAP_NORM_SIZE +#define CHEAP_NORM_SIZE 161 +#endif + +#define MINSFTAB 7 +#define MAXSFTAB 25 + +/** + * \brief Lookup-Table for binary logarithm + */ +extern const Word16 ldCoeff[7]; + +/** + \brief Lookup-Table for binary power algorithm +*/ +extern const UWord32 exp2_tab_long[32]; + +/** + \brief Lookup-Table for binary power algorithm +*/ +extern const UWord32 exp2w_tab_long[32]; + +/** + \brief Lookup-Table for binary power algorithm +*/ +extern const UWord32 exp2x_tab_long[32]; + +/** + \brief Lookup-Table for integer binary logarithm +*/ +extern const Word32 ldIntCoeff[LD_INT_TAB_LEN]; + +/** + * \brief Lookup-Table for 1/x +*/ +extern const Word16 invTable[INV_TABLE_SIZE+1]; + +/** + * \brief 1/x, x=[0,1,2,3...] table + */ +extern const Word16 InvIntTable[65]; + +/** + * \brief Lookup-Table for Squareroot +*/ +extern const Word16 sqrtTable[SQRT_TABLE_SIZE+1]; +extern const Word16 invSqrtTable[SQRT_TABLE_SIZE+1]; + +extern const Word32 BASOP_util_normReciprocal[CHEAP_NORM_SIZE]; +extern const Word16 f_atan_expand_range[MAXSFTAB-(MINSFTAB-1)]; + +/** + * \ brief Sine table + */ +extern const PWord16 SineTable512[257]; +extern const PWord16 SineTable480[241]; +extern const PWord16 SineTable400[201]; +extern const PWord16 SineTable384[193]; +extern const PWord16 SineTable320[161]; + +/** + * \ brief Lookup for sine tables and windows. + */ +void BASOP_getTables(const PWord16 **ptwiddle, const PWord16 **sin_twiddle, Word16 *sin_step, Word16 length); +const PWord16* getSineWindowTable(Word16 length); + +#endif diff --git a/lib_com/rom_com_fx.c b/lib_com/rom_com_fx.c new file mode 100644 index 0000000..dba0f3a --- /dev/null +++ b/lib_com/rom_com_fx.c @@ -0,0 +1,21195 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" +#include "rom_com_fx.h" /* Static table prototypes */ +#include "cnst_fx.h" /* Decoder static structure */ +#include "stl.h" + +#include "basop_util.h" + + + + +/*----------------------------------------------------------------------------------* + * Table of bitrates + *----------------------------------------------------------------------------------*/ + +const Word32 brate_tbl[SIZE_BRATE_TBL] = +{ + ACELP_7k20, ACELP_8k00, ACELP_9k60, ACELP_13k20, ACELP_16k40, ACELP_24k40, + ACELP_32k, ACELP_48k, ACELP_64k, HQ_96k, HQ_128k +}; + +/*----------------------------------------------------------------------------------* + * Conversion of ACELP signalling parameters (ACELP internal Fs, coder type, bandwidth, sharpening flag) to index + * (to be consulted with the decision matrix) + * + * - in order to retrieve the index, each section in this table starts with a bitrate + * - the second value in each section corresponds to the number of bits + * - the other values represent indices created by combining different parameters into a single value through the macro SIG2IND() + *----------------------------------------------------------------------------------*/ + +/* Combine coder_type, bandwidth, formant sharpening flag, and channel-aware flag into one indice */ +#define SIG2IND(ctype, bw, sf, ca_rf) ( ctype | (bw << 3) | (sf << 6) | (ca_rf << 7) ) + +const Word32 acelp_sig_tbl[MAX_ACELP_SIG] = +{ + /* GENERIC UNVOICED VOICED TRANSITION AUDIO INACTIVE */ + ACELP_7k20, 4, + SIG2IND(GENERIC, NB, 1, 0), SIG2IND(UNVOICED, NB, 0, 0), SIG2IND(VOICED, NB, 1, 0), SIG2IND(TRANSITION, NB, 1, 0), SIG2IND(AUDIO, NB, 0, 0), SIG2IND(INACTIVE, NB, 0, 0), + SIG2IND(GENERIC, WB, 1, 0), SIG2IND(UNVOICED, WB, 0, 0), SIG2IND(VOICED, WB, 1, 0), SIG2IND(TRANSITION, WB, 1, 0), SIG2IND(AUDIO, WB, 0, 0), SIG2IND(INACTIVE, WB, 0, 0), + SIG2IND(GENERIC, NB, 0, 0), + SIG2IND(GENERIC, WB, 0, 0), + SIG2IND(LR_MDCT, NB, 0, 0), + + ACELP_8k00, 4, + SIG2IND(GENERIC, NB, 1, 0), SIG2IND(UNVOICED, NB, 0, 0), SIG2IND(VOICED, NB, 1, 0), SIG2IND(TRANSITION, NB, 1, 0), SIG2IND(AUDIO, NB, 0, 0), SIG2IND(INACTIVE, NB, 0, 0), + SIG2IND(GENERIC, WB, 1, 0), SIG2IND(UNVOICED, WB, 0, 0), SIG2IND(VOICED, WB, 1, 0), SIG2IND(TRANSITION, WB, 1, 0), SIG2IND(AUDIO, WB, 0, 0), SIG2IND(INACTIVE, WB, 0, 0), + SIG2IND(GENERIC, NB, 0, 0), + SIG2IND(GENERIC, WB, 0, 0), + SIG2IND(LR_MDCT, NB, 0, 0), + + ACELP_13k20, 5, + SIG2IND(GENERIC, NB, 1, 0), SIG2IND(VOICED, NB, 1, 0), SIG2IND(TRANSITION, NB, 0, 0), SIG2IND(AUDIO, NB, 0, 0), SIG2IND(INACTIVE, NB, 0, 0), + SIG2IND(GENERIC, WB, 1, 0), SIG2IND(VOICED, WB, 1, 0), SIG2IND(TRANSITION, WB, 0, 0), SIG2IND(AUDIO, WB, 0, 0), SIG2IND(INACTIVE, WB, 0, 0), + SIG2IND(GENERIC, SWB, 1, 0), SIG2IND(VOICED, SWB, 1, 0), SIG2IND(TRANSITION, SWB, 0, 0), SIG2IND(AUDIO, SWB, 0, 0), SIG2IND(INACTIVE, SWB, 0, 0), + SIG2IND(GENERIC, NB, 0, 0), SIG2IND(VOICED, NB, 0, 0), + SIG2IND(GENERIC, WB, 0, 0), SIG2IND(VOICED, WB, 0, 0), + SIG2IND(GENERIC, SWB, 0, 0), SIG2IND(VOICED, SWB, 0, 0), + SIG2IND(GENERIC, WB, 1, 1), SIG2IND(UNVOICED, WB, 0, 1), SIG2IND(VOICED, WB, 1, 1), SIG2IND(INACTIVE, WB, 0, 1), + SIG2IND(GENERIC, SWB, 1, 1), SIG2IND(UNVOICED, SWB, 0, 1), SIG2IND(VOICED, SWB, 1, 1), SIG2IND(INACTIVE, SWB, 0, 1), + SIG2IND(LR_MDCT, NB, 0, 0), + SIG2IND(LR_MDCT, WB, 0, 0), + SIG2IND(LR_MDCT, SWB, 0, 0), + + ACELP_32k, 4, + SIG2IND(GENERIC, WB, 1, 0), SIG2IND(TRANSITION, WB, 1, 0), SIG2IND(INACTIVE, WB, 0, 0), + SIG2IND(GENERIC, SWB, 1, 0), SIG2IND(TRANSITION, SWB, 1, 0), SIG2IND(INACTIVE, SWB, 0, 0), + SIG2IND(GENERIC, FB, 1, 0), SIG2IND(TRANSITION, FB, 1, 0), SIG2IND(INACTIVE, FB, 0, 0), + SIG2IND(GENERIC, WB, 0, 0), SIG2IND(TRANSITION, WB, 0, 0), + SIG2IND(GENERIC, SWB, 0, 0), SIG2IND(TRANSITION, SWB, 0, 0), + SIG2IND(GENERIC, FB, 0, 0), SIG2IND(TRANSITION, FB, 0, 0), + + ACELP_64k, 4, + SIG2IND(GENERIC, WB, 0, 0), SIG2IND(TRANSITION, WB, 0, 0), SIG2IND(INACTIVE, WB, 0, 0), + SIG2IND(GENERIC, SWB, 1, 0), SIG2IND(TRANSITION, SWB, 1, 0), SIG2IND(INACTIVE, SWB, 0, 0), + SIG2IND(GENERIC, FB, 1, 0), SIG2IND(TRANSITION, FB, 1, 0), SIG2IND(INACTIVE, FB, 0, 0), + SIG2IND(GENERIC, SWB, 0, 0), SIG2IND(TRANSITION, SWB, 0, 0), + SIG2IND(GENERIC, FB, 0, 0), SIG2IND(TRANSITION, FB, 0, 0), +}; + +/*----------------------------------------------------------------------------------* + * ACELP bit allocation tables + *----------------------------------------------------------------------------------*/ + +/* bit allocation table for end-frame LSF quantizer */ +const Word16 LSF_bits_tbl[] = +{ + /* IC UC VC GC TC AC */ + 22, 37, 31, 29, 31, 22, /* ACELP_7k20 */ + 22, 40, 36, 33, 34, 22, /* ACELP_8k00 */ + 31, 0, 37, 37, 40, 31, /* ACELP_11k60 */ + 31, 0, 39, 39, 41, 31, /* ACELP_12k15 */ + 31, 0, 38, 38, 40, 31, /* ACELP_12k85 */ + 31, 0, 38, 38, 40, 31, /* ACELP_13k20 */ + 31, 0, 37, 42, 42, 31, /* ACELP_14k80 */ + 31, 0, 43, 40, 40, 31, /* ACELP_16k40 */ + 31, 0, 42, 40, 40, 0, /* ACELP_22k60 */ + 31, 0, 46, 41, 41, 31, /* ACELP_24k40 */ + 41, 0, 0, 41, 41, 0, /* ACELP_29k00 */ + 41, 0, 0, 41, 41, 0, /* ACELP_29k20 */ + 41, 0, 0, 41, 41, 0, /* ACELP_30k20 */ + 41, 0, 0, 41, 41, 0, /* ACELP_30k40 */ + 41, 0, 0, 41, 41, 0, /* ACELP_32k */ + 41, 0, 0, 41, 41, 0, /* ACELP_48k */ + 41, 0, 0, 41, 41, 0, /* ACELP_64k */ +}; + +/* bit allocation table for mid-frame LSF quantizer */ +const Word16 mid_LSF_bits_tbl[] = +{ + /* IC UC VC GC TC AC */ + 2, 5, 4, 5, 5, 2, /* ACELP_7k20 */ + 2, 5, 4, 5, 5, 2, /* ACELP_8k00 */ + 2, 0, 4, 5, 5, 2, /* ACELP_11k60 */ + 2, 0, 5, 5, 5, 2, /* ACELP_12k15 */ + 2, 0, 5, 5, 5, 2, /* ACELP_12k85 */ + 2, 0, 5, 5, 5, 2, /* ACELP_13k20 */ + 4, 0, 5, 5, 5, 4, /* ACELP_14k80 */ + 4, 0, 5, 5, 5, 4, /* ACELP_16k40 */ + 5, 0, 5, 5, 5, 5, /* ACELP_22k60 */ + 5, 0, 5, 5, 5, 5, /* ACELP_24k40 */ + 5, 0, 0, 5, 5, 5, /* ACELP_29k00 */ + 5, 0, 0, 5, 5, 5, /* ACELP_29k20 */ + 5, 0, 0, 5, 5, 5, /* ACELP_30k20 */ + 5, 0, 0, 5, 5, 5, /* ACELP_30k40 */ + 5, 0, 0, 5, 5, 5, /* ACELP_32k */ + 5, 0, 0, 5, 5, 5, /* ACELP_48k */ + 5, 0, 0, 5, 5, 5, /* ACELP_64k */ +}; + + +/* bit allocation table for scaled innovation energy prediction */ +const Word16 Es_pred_bits_tbl[] = +{ + /* UC VC GC TC */ + 0, 0, 0, 4, /* ACELP_7k20 */ + 0, 0, 0, 4, /* ACELP_8k00 */ + 0, 5, 4, 4, /* ACELP_11k60 */ + 0, 5, 5, 5, /* ACELP_12k15 */ + 0, 5, 4, 5, /* ACELP_12k85 */ + 0, 5, 4, 4, /* ACELP_13k20 */ + 0, 5, 5, 5, /* ACELP_14k80 */ + 0, 5, 5, 5, /* ACELP_16k40 */ + 0, 5, 5, 5, /* ACELP_22k60 */ + 0, 5, 5, 5, /* ACELP_24k40 */ + 0, 0, 5, 5, /* ACELP_29k00 */ + 0, 0, 5, 5, /* ACELP_29k20 */ + 0, 0, 5, 5, /* ACELP_30k20 */ + 0, 0, 5, 5, /* ACELP_30k40 */ + 0, 0, 5, 5, /* ACELP_32k */ + 0, 0, 5, 5, /* ACELP_48k */ + 0, 0, 5, 5, /* ACELP_64k */ +}; + +/* bit allocation table for gain quantizer (ACELP@12.8kHz) */ +/* the 4 values allocated correspond to 4 subframes */ +const Word16 gain_bits_tbl[] = +{ + /* UC VC GC TC0_0 TC0_64 TC0_128 TC0_192 TC64 TC128 TC192 */ + 7,7,7,7, 7,6,6,6, 6,6,6,6, 5,5,5,5, 5,5,6,5, 5,3,6,6, 5,3,3,6, 3,6,6,6, 3,3,6,6, 3,3,3,10, /* ACELP_7k20 */ + 7,7,7,7, 8,7,6,6, 8,7,6,6, 5,5,5,5, 5,6,5,5, 5,3,6,6, 5,3,3,6, 3,5,5,5, 3,3,6,6, 3,3,3,14, /* ACELP_8k00 */ + 0,0,0,0, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,3,6,6, 6,3,3,6, 3,6,6,6, 3,3,6,6, 3,3,3,13, /* ACELP_11k60 */ + 0,0,0,0, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,3,6,6, 6,3,3,6, 3,6,6,6, 3,3,6,6, 3,3,3,14, /* ACELP_12k15 */ + 0,0,0,0, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,3,6,6, 6,3,3,6, 3,6,6,6, 3,3,6,5, 3,3,3,14, /* ACELP_12k85 */ + 0,0,0,0, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,3,6,6, 6,3,3,6, 3,6,6,6, 3,3,6,6, 3,3,3,15, /* ACELP_13k20 */ + 0,0,0,0, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,3,6,6, 6,3,3,6, 3,6,6,6, 3,3,6,6, 3,3,3,15, /* ACELP_14k80 */ + 0,0,0,0, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,3,6,6, 6,3,3,6, 3,6,6,6, 3,3,6,6, 3,3,3,15, /* ACELP_16k40 */ + 0,0,0,0, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,3,6,6, 6,3,3,6, 3,6,6,6, 3,3,6,6, 3,3,3,14, /* ACELP_22k60 */ + 0,0,0,0, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,3,6,6, 6,3,3,6, 3,6,6,6, 3,3,6,6, 3,3,3,15, /* ACELP_24k40 */ +}; + +/* bit allocation table for gain gain quantizer (ACELP@16kHz) */ +/* the 5 values allocated correspond to 5 subframes */ +const Word16 gain_bits_16kHz_tbl[] = +{ + /* IC GC TC0 TC64 TC128 TC192 TC256 */ + 0,0,0,0,0, 6,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0, 0, /* ACELP_8k00 */ + 0,0,0,0,0, 6,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0, 0, /* ACELP_14k80 */ + 6,6,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 3,6,6,6,6, 3,3,6,6,6, 3,3,3,6,6, 3,3,3,3,15, /* ACELP_22k60 */ + 6,6,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 3,6,6,6,6, 3,3,6,6,6, 3,3,3,6,6, 3,3,3,3,16, /* ACELP_24k40 */ + 6,6,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 3,6,6,6,6, 3,3,6,6,6, 3,3,3,6,6, 3,3,3,3,14, /* ACELP_29k00 */ + 6,6,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 3,6,6,6,6, 3,3,6,6,6, 3,3,3,6,6, 3,3,3,3,14, /* ACELP_29k20 */ + 6,6,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 3,6,6,6,6, 3,3,6,6,6, 3,3,3,6,6, 3,3,3,3,14, /* ACELP_30k20 */ + 6,6,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 3,6,6,6,6, 3,3,6,6,6, 3,3,3,6,6, 3,3,3,3,14, /* ACELP_30k40 */ + 6,6,6,6,6, 6,6,6,6,6, 6,6,6,6,6, 3,6,6,6,6, 3,3,6,6,6, 3,3,3,6,6, 3,3,3,3,14, /* ACELP_32k */ + 12,12,12,12,12, 12,12,12,12,12, 12,12,12,12,12, 6,12,12,12,12, 6,6,12,12,12, 6,6,6,12,12, 6,6,6,6,12, /* ACELP_48k */ + 12,12,12,12,12, 12,12,12,12,12, 12,12,12,12,12, 6,12,12,12,12, 6,6,12,12,12, 6,6,6,12,12, 6,6,6,6,12 /* ACELP_64k */ +}; + +/* bit allocation table for adaptive codebook (pitch) (ACELP@12.8kHz) */ +/* the 4 values correspond to 4 subframes */ +const Word16 ACB_bits_tbl[] = +{ + /* UC VC GC TC0_0 TC0_64 TC0_128 TC0_192 TC64 TC128 TC192 */ + 0,0,0,0, 9,5,5,5, 8,5, 8,5, 6,5,6,6, 0,7,6,6, 0,0,7,6, 0,0,0,7, 0,0,9,6, 0,0,5,9, 0,0,0,8, /* ACELP_7k20 */ + 0,0,0,0, 10,5,5,5, 9,5, 8,5, 6,5,6,6, 0,7,6,6, 0,0,7,5, 0,0,0,7, 0,0,9,6, 0,0,5,9, 0,0,0,9, /* ACELP_8k00 */ + 0,0,0,0, 10,5,5,5, 10,6, 9,6, 6,5,6,6, 0,7,6,6, 0,0,7,6, 0,0,0,7, 0,0,9,6, 0,0,5,9, 0,0,0,9, /* ACELP_11k60 */ + 0,0,0,0, 10,5,5,5, 10,6, 9,6, 6,6,6,6, 0,7,6,6, 0,0,7,6, 0,0,0,7, 0,0,9,6, 0,0,5,9, 0,0,0,9, /* ACELP_12k15 */ + 0,0,0,0, 10,5,5,5, 10,6, 9,6, 6,5,6,6, 0,7,6,6, 0,0,7,6, 0,0,0,7, 0,0,9,6, 0,0,5,9, 0,0,0,9, /* ACELP_12k85 */ + 0,0,0,0, 10,5,5,5, 10,6, 9,6, 6,5,6,6, 0,7,6,6, 0,0,7,6, 0,0,0,7, 0,0,9,6, 0,0,5,9, 0,0,0,9, /* ACELP_13k20 */ + 0,0,0,0, 10,5,5,5, 10,6,10,6, 6,6,6,6, 0,7,6,6, 0,0,7,6, 0,0,0,7, 0,0,9,6, 0,0,5,9, 0,0,0,9, /* ACELP_14k80 */ + 0,0,0,0, 10,5,5,5, 10,6,10,6, 6,6,6,6, 0,7,6,6, 0,0,7,6, 0,0,0,7, 0,0,9,6, 0,0,5,9, 0,0,0,9, /* ACELP_16k40 */ + 0,0,0,0, 10,5,5,5, 10,6,10,6, 6,6,6,6, 0,7,6,6, 0,0,7,6, 0,0,0,7, 0,0,9,6, 0,0,5,9, 0,0,0,9, /* ACELP_22k60 */ + 0,0,0,0, 10,5,5,5, 10,6,10,6, 6,6,6,6, 0,7,6,6, 0,0,7,6, 0,0,0,7, 0,0,9,6, 0,0,5,9, 0,0,0,9, /* ACELP_24k40 */ +}; + +/* bit allocation table for adaptive codebook (pitch) (ACELP@16kHz) */ +/* the 5 values correspond to 5 subframes */ +const Word16 ACB_bits_16kHz_tbl[] = +{ + /* IC GC TC0 TC64 TC128 TC192 TC256 */ + 0,0, 0,0,0, 9,0, 0,0,0, 0,0, 0,0,0, 0,0, 0,0,0, 0,0, 0,0,0, 0,0,0, 0,0, 0,0,0,0, 0, /* ACELP_8k00 */ + 0,0, 0,0,0, 10,0, 0,0,0, 0,0, 0,0,0, 0,0, 0,0,0, 0,0, 0,0,0, 0,0,0, 0,0, 0,0,0,0, 0, /* ACELP_14k80 */ + 10,6,10,6,6, 10,6,10,6,6, 5,8,10,6,6, 0,6,10,6,6, 0,0,10,6,6, 0,0,0,10,6, 0,0,0,0,10, /* ACELP_22k60 */ + 10,6,10,6,6, 10,6,10,6,6, 5,8,10,6,6, 0,6,10,6,6, 0,0,10,6,6, 0,0,0,10,6, 0,0,0,0,10, /* ACELP_24k40 */ + 10,6,10,6,6, 10,6,10,6,6, 6,8,10,6,6, 0,6,10,6,6, 0,0,10,6,6, 0,0,0,10,6, 0,0,0,0,10, /* ACELP_29k00 */ + 10,6,10,6,6, 10,6,10,6,6, 6,8,10,6,6, 0,6,10,6,6, 0,0,10,6,6, 0,0,0,10,6, 0,0,0,0,10, /* ACELP_29k20 */ + 10,6,10,6,6, 10,6,10,6,6, 6,8,10,6,6, 0,6,10,6,6, 0,0,10,6,6, 0,0,0,10,6, 0,0,0,0,10, /* ACELP_30k20 */ + 10,6,10,6,6, 10,6,10,6,6, 6,8,10,6,6, 0,6,10,6,6, 0,0,10,6,6, 0,0,0,10,6, 0,0,0,0,10, /* ACELP_30k40 */ + 10,6,10,6,6, 10,6,10,6,6, 6,8,10,6,6, 0,6,10,6,6, 0,0,10,6,6, 0,0,0,10,6, 0,0,0,0,10, /* ACELP_32k */ + 10,6,10,6,6, 10,6,10,6,6, 6,8,10,6,6, 0,6,10,6,6, 0,0,10,6,6, 0,0,0,10,6, 0,0,0,0,10, /* ACELP_48k */ + 10,6,10,6,6, 10,6,10,6,6, 6,8,10,6,6, 0,6,10,6,6, 0,0,10,6,6, 0,0,0,10,6, 0,0,0,0,10 /* ACELP_64k */ +}; + +/* bit allocation table for algebraic (fixed) codebook (innovation) (ACELP@12.8kHz) */ +/* the 4 values correspond to 4 subframes */ +const Word16 FCB_bits_tbl[] = +{ + /* UC VC GC TC0_0 TC0_64 TC0_128 TC0_192 TC64 TC128 TC192 */ + 13,13,13,13, 12,12,12,20, 12,12,12,20, 12, 7,12,12, 12,12, 7,12, 12,12,12,12, 12,12,20,12, 12,12,12,12, 12,12,12,12, 12,12,12,20, /* ACELP_7k20 */ + 13,13,13,13, 12,20,12,20, 12,20,12,20, 20,12,12,12, 20,12,12,12, 20,12,20,12, 20,12,20,20, 20,12,12,20, 20,12,20,12, 12,20,12,20, /* ACELP_8k00 */ + 0, 0, 0, 0, 28,36,28,36, 28,28,28,36, 28,28,28,28, 28,28,28,28, 28,28,36,28, 28,36,28,36, 28,36,28,28, 28,28,28,36, 28,36,28,36, /* ACELP_11k60 */ + 0, 0, 0, 0, 28,36,36,36, 28,36,28,36, 36,28,28,28, 36,28,28,28, 36,28,36,28, 36,36,28,43, 28,36,28,36, 28,36,28,36, 28,36,36,36, /* ACELP_12k15 */ + 0, 0, 0, 0, 36,36,36,43, 36,36,36,36, 36,36,28,36, 36,28,36,36, 36,36,36,36, 36,36,43,43, 36,36,36,36, 36,36,36,43, 36,36,36,43, /* ACELP_12k85 */ + 0, 0, 0, 0, 36,43,36,43, 36,36,36,43, 36,36,36,36, 36,36,36,36, 36,36,43,36, 36,43,43,43, 36,43,36,36, 43,36,43,36, 36,43,36,43, /* ACELP_13k20 */ + 0, 0, 0, 0, 43,50,43,50, 43,43,43,43, 43,43,43,43, 43,43,43,43, 43,43,50,43, 43,50,50,50, 43,43,43,50, 50,43,50,43, 43,50,43,50, /* ACELP_14k80 */ + 0, 0, 0, 0, 50,56,50,56, 50,50,50,56, 56,50,50,50, 56,50,50,50, 56,50,56,56, 56,56,56,56, 50,56,50,56, 50,56,56,56, 50,56,56,56, /* ACELP_16k40 */ + 0, 0, 0, 0, 83,83,83,87, 78,83,83,83, 83,78,83,83, 83,78,83,87, 83,87,83,87, 83,87,87,92, 87,83,87,83, 87,83,87,87, 83,87,87,87, /* ACELP_22k60 */ + 0, 0, 0, 0, 92,92,92,92, 87,92,92,92, 92,87,92,92, 92,87,92,92, 92,92,92,92, 92,92,92,92, 92,92,92,92, 92,92,92,92, 92,92,92,92, /* ACELP_24k40 */ +}; + +/* bit allocation table for algebraic (fixed) codebook (innovation) (ACELP@16kHz) */ +/* the 5 values correspond to 5 subframes */ +const Word16 FCB_bits_16kHz_tbl[] = +{ + /* IC GC TC0 TC64 TC128 TC192 TC256 */ + 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ACELP_8k00 */ + 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ACELP_14k80 */ + 0, 0, 0, 0, 0, 62,56,56,56,62, 62,56,56,56,56, 56,56,56,56,73, 62,56,62,62,62, 56,62,62,62,73, 62,62,62,62,68, /* ACELP_22k60 */ + 0, 0, 0, 0, 0, 68,68,68,73,73, 68,68,68,68,73, 68,73,68,73,73, 73,73,73,73,73, 73,78,73,73,78, 73,78,73,73,78, /* ACELP_24k40 */ + 12,12,12,12,12, 36,28,28,36,36, 36,28,28,36,36, 36,28,28,36,36, 36,28,28,36,36, 36,28,28,36,36, 36,28,28,36,36, /* ACELP_29k00 */ + 12,12,12,12,12, 36,28,28,36,36, 36,28,28,36,36, 36,28,28,36,36, 36,28,28,36,36, 36,28,28,36,36, 36,28,28,36,36, /* ACELP_29k20 */ + 12,12,12,12,12, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, /* ACELP_30k20 */ + 12,12,12,12,12, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, /* ACELP_30k40 */ + 12,12,12,12,12, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, /* ACELP_32k */ + 12,12,12,12,12, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, /* ACELP_48k */ + 12,12,12,12,12, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36, 36,36,36,36,36 /* ACELP_64k */ +}; + +/* bit allocation table for AVQ bits in active segments (ACELP@16kHz) */ +const Word16 AVQ_bits_16kHz_tbl[] = +{ + /* IC GC TC0 TC64 TC128 TC192 TC256 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ACELP_8k00 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ACELP_14k80 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ACELP_22k60 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ACELP_24k40 */ + 78, 78, 78, 78, 78, 48, 48, 48, 48, 49, 48, 49, 49, 48, 49, 50, 50, 51, 52, 52, 50, 54, 53, 54, 54, 55, 55, 55, 55, 54, 52, 56, 56, 56, 56, /* ACELP_29k00 */ + 79, 79, 79, 79, 78, 49, 49, 49, 49, 49, 50, 49, 49, 50, 49, 52, 52, 51, 52, 52, 54, 54, 53, 54, 54, 56, 55, 55, 56, 56, 56, 56, 56, 56, 56, /* ACELP_29k20 */ + 78, 78, 78, 78, 78, 50, 50, 50, 50, 49, 51, 50, 50, 50, 50, 53, 53, 53, 52, 52, 55, 55, 55, 54, 54, 57, 57, 56, 56, 56, 57, 57, 57, 57, 56, /* ACELP_30k20 */ + 79, 79, 79, 79, 78, 51, 51, 51, 50, 50, 51, 51, 51, 51, 51, 54, 54, 53, 53, 53, 56, 56, 56, 55, 54, 58, 57, 57, 57, 57, 58, 58, 58, 57, 57, /* ACELP_30k40 */ + 86, 85, 85, 85, 85, 57, 57, 57, 57, 57, 58, 58, 57, 57, 57, 60, 60, 60, 60, 59, 62, 62, 62, 62, 61, 64, 64, 64, 63, 63, 64, 64, 64, 64, 64, /* ACELP_32k */ + 143,142,142,142,142, 116,115,115,115,115, 116,116,115,115,115, 119,119,118,118,118, 121,121,121,121,121, 124,124,123,123,123, 126,126,126,126,126, /* ACELP_48k */ + 207,206,206,206,206, 180,179,179,179,179, 180,180,179,179,179, 183,183,182,182,182, 185,185,185,185,185, 188,188,187,187,187, 190,190,190,190,190 /* ACELP_64k */ +}; + +/* bit allocation table for reserved bits (ACELP@12.8kHz) */ +const Word16 reserved_bits_tbl[] = +{ + /* UC VC GC TC0_0 TC0_64 TC0_128 TC0_192 TC64 TC128 TC192 */ + 1, 0, 0, 0, 0, 2, 4, 0, 3, 0, /* ACELP_7k20 */ + 14, 0, 0, 0, 0, 0, 1, 0, 0, 0, /* ACELP_8k00 */ + 0, 0, 0, 0, 1, 3, 6, 2, 6, 0, /* ACELP_11k60 */ + 0, 0, 0, 0, 2, 4, 0, 3, 7, 0, /* ACELP_12k15 */ + 0, 0, 0, 0, 1, 3, 0, 2, 0, 0, /* ACELP_12k85 */ + 0, 0, 0, 0, 1, 4, 1, 3, 0, 0, /* ACELP_13k20 */ + 0, 0, 0, 0, 2, 5, 2, 4, 1, 1, /* ACELP_14k80 */ + 0, 0, 0, 0, 2, 0, 5, 5, 3, 3, /* ACELP_16k40 */ + 0, 0, 2, 2, 0, 1, 3, 0, 0, 1, /* ACELP_22k60 */ + 0, 0, 1, 1, 3, 8, 19, 7, 11, 11, /* ACELP_24k40 */ +}; + + + +/*----------------------------------------------------------------------------------* + * Power of 2 table (2^x) + *----------------------------------------------------------------------------------*/ + +const Word32 pow2[] = +{ + 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576 +}; +const Word16 crit_bins_corr_fx[CRIT_NOIS_BAND] = +{ + /*.9f, .9f, .85f, .8f, .775f, .75f, .725f , .7f , .675f, .65f, .625f , .60f, .6f, .6f, .6f, .6f, .6f, .6f, .6f, .6f, .6f, .6f, .6f*/ + 29491, 29491, 27853, 26214, 25395, 24576, 23577 , 22938, 22118, 21299, 20480, + 19661, 19661, 19661, 19661, 19661, 19661, 19661, 19661, 19661, 19661, 19661, 19661 +}; +const Word16 crit_bins[CRIT_NOIS_BAND] = +{ + 4, 4, 4, 4, 4, 5, 6, 6, 6, 8, 8, 10, 11, 13, 15, 18, 22, 16, 16, 20, 20, 20, 16 +}; +const Word16 mfreq_bindiv_loc[] = { 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 32, 32, 32 }; +const Word16 mfreq_bindiv_LD[] = {10, 10, 10, 10, 11, 12, 14, 15, 16, 19, 21, 24, 28, 32, 38, 45, 55, 70, 90, 110}; +const Word16 mfreq_loc_LD[] = { 100, 200, 300, 400, 510, 630, 770, 920, 1080, 1270, 1480, + 1720, 2000, 2320, 2700, 3150, 3700, 4400, 5300, (6400-BIN_16kdct) + }; + +/* bit allocation table for gain quantizer (ACELP@12.8kHz) */ +/* the 4 values allocated correspond to 4 subframes */ + +/*----------------------------------------------------* + * Table for FFT + -----------------------------------------------------*/ + +const Word16 Odx_fft32_5[32] = { 0,27,22,17,12,7,2,29,24,19,14,9,4,31,26,21,16,11,6,1,28,23,18,13,8,3,30,25,20,15,10,5 }; + +const Word16 Idx_dortft160[160] = +{ + 0,65,130,35,100,5,70,135,40,105,10,75,140,45,110,15,80,145, + 50,115,20,85,150,55,120,25,90,155,60,125,30,95,96,1,66,131, + 36,101,6,71,136,41,106,11,76,141,46,111,16,81,146,51,116,21, + 86,151,56,121,26,91,156,61,126,31,32,97,2,67,132,37,102,7, + 72,137,42,107,12,77,142,47,112,17,82,147,52,117,22,87,152,57, + 122,27,92,157,62,127,128,33,98,3,68,133,38,103,8,73,138,43, + 108,13,78,143,48,113,18,83,148,53,118,23,88,153,58,123,28,93, + 158,63,64,129,34,99,4,69,134,39,104,9,74,139,44,109,14,79, + 144,49,114,19,84,149,54,119,24,89,154,59,124,29,94,159 +}; + +const Word16 nextstate[STATES][2] = {{0, 1}, {2, 3}, {4, 5}, {6, 7}, {0, 1}, {2, 3}, {4, 5}, {6, 7}};/*current state points to next two states */ + +const Word16 fine_gain_bits[8] = {0, 0, 0, 1, 2, 2, 4, 5}; + + +const Word16 resize_huffsizn[32] = +{ + 0, 0, 0, 0, 0, 11, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 0, 0, 0, 0, 0 +}; + +const Word16 huffsizn[32] = +{ + 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 4, 4, 3, 3, + 3, 3, 4, 4, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7 +}; + +const Word16 huffnorm_tran[32] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,122, 10, 6, 1, + 0, 3, 2, 26, 58, 186, 442, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const Word16 huffsizn_tran[32] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 5, 3, 2, 2, + 2, 4, 6, 8, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const Word16 pgain_huffsizn[32] = +{ + 10, 11, 10, 10, 9, 8, 6, 5, 5, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 5, 5, 6, 7, 7, 8, 10, 10, 12, 12 +}; + +const Word16 dicnlg2[40] = +{ + 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, + 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, + 4, 3, 2, 1, 0, -1, -2, -3, -4, -5 +}; + +/*** Table for quantization of MLT coefficients ***/ +const Word16 norm_order_48[NB_SFM] = +{ + 0, 1, 8, 9, 16, 20, 24, 28, 32, 36, 40, 41, 37, 33, 29, 25, 21, 17, 11, 10, 3, 2, + 4, 5, 12, 13, 18, 22, 26, 30, 34, 38, 42, 43, 39, 35, 31, 27, 23, 19, 15, 14, 7, 6 +}; +const Word16 norm_order_32[SFM_N_SWB] = +{ + 0, 1, 8, 9, 16, 20, 24, 28, 32, 36, 37, 33, 29, 25, 21, 17, 11, 10, 3, 2, + 4, 5, 12, 13, 18, 22, 26, 30, 34, 38, 35, 31, 27, 23, 19, 15, 14, 7, 6 +}; +const Word16 norm_order_16[SFM_N_WB] = +{ + 0, 1, 8, 9, 16, 20, 24, 21, 17, 11, 10, 3, 2, + 4, 5, 12, 13, 18, 22, 25, 23, 19, 15, 14, 7, 6 +}; + +const Word16 intl_bw_16[N_INTL_GRP_16] = {16, 16}; +const Word16 intl_bw_32[N_INTL_GRP_32] = {16, 24}; +const Word16 intl_bw_48[N_INTL_GRP_48] = {16, 24, 32}; +const Word16 intl_cnt_16[N_INTL_GRP_16] = {4, 1}; +const Word16 intl_cnt_32[N_INTL_GRP_32] = {4, 4}; +const Word16 intl_cnt_48[N_INTL_GRP_48] = {4, 3, 2}; + +const Word16 band_start_HQ[44] = +{ + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, + 96, 104, 112, 120, 128, 144, 160, 176, 192, 208, 224, 240, + 256, 280, 304, 328, 352, 376, 400, 424, 448, 472, 496, 520, + 544, 576, 608, 640, 672, 704, 736, 768 +}; + +const Word16 band_end_HQ[44] = +{ + 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, + 104, 112, 120, 128, 144, 160, 176, 192, 208, 224, 240, 256, + 280, 304, 328, 352, 376, 400, 424, 448, 472, 496, 520, 544, + 576, 608, 640, 672, 704, 736, 768, 800 +}; + +const Word16 band_len_HQ[44] = +{ + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 32, 32, 32, 32, 32, 32, 32, 32 +}; + +const Word16 band_start_wb[26] = +{ + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, + 96, 104, 112, 120, 128, 144, 160, 176, 192, 208, 224, 240, + 256, 288 +}; + +const Word16 band_end_wb[26] = +{ + 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, + 104, 112, 120, 128, 144, 160, 176, 192, 208, 224, 240, 256, + 288, 320 +}; + +const Word16 band_len_wb[26] = +{ + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, + 32, 32 +}; + +const Word16 band_len_harm[SFM_N_HARM_FB] = +{ + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 16, 16, 16, 16, 16, 16, 32, 32, 32, 48, 48, 48, 48, 64, 64, 64, 96 +}; + +const Word16 band_start_harm[SFM_N_HARM_FB] = +{ + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, + 128, 144, 160, 176, 192, 208, 224, 256, 288, 320, 368, 416, 464, 512, 576, 640, 704 +}; + +const Word16 band_end_harm[SFM_N_HARM_FB] = +{ + 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, + 144, 160, 176, 192, 208, 224, 256, 288, 320, 368, 416, 464, 512, 576, 640, 704, 800 +}; + +const Word16 min_lat_bits_SN_fx[] = {-1, -1, 17, 12, 17, 17, -1, -1, 17, 12, 17, 17, -1, -1, 22, -1, 32, 26 + }; + +const Word16 min_lat_bits_pred_fx[] = {17, 18, 9, 15, -1, 21, 17, 14, 9, 15, -1, 21, 17, -1, -1, 26, -1, 26, 16}; + +const Word16 offset_in_lvq_mode_SN_fx[][21] = +{ + {0}, /* I NB */ + {0,1,1,1,1,1,2,3,3,3,3,4,4,4,5}, /* UV NB*/ + {0,1,1,1,1,2,3,4,5,5,6,6,7,7,7,7,7,8,8,8,9}, /* V NB */ + {0,0,0,0,1,1,1,2,3,4,5,6,6,7,8,9,10,11,12,13,14}, /* G NB */ + {0,1,1,1,1,2,3,4,5,5,5,6,6,6,7,8}, /* T NB */ + {0,0,0,0,1,2,2,2,2,3,4,5}, /* A NB */ + {0}, /* I WB */ + {0,1,1,1,2,3,3,3,3,3,3,4,4,4,5}, /* UV WB*/ + {0,1,1,1,2,3,3,3,4,5,6,7,8,9,9,10,11,12,12,12,13}, /* V WB */ + {0,0,0,0,1,1,1,2,3,4,5,6,6,7,8,9,10,11,12,13,14}, /* G WB */ + {0,1,1,1,2,3,3,4,5,5,5,6,6,7,8,9,10}, /* T WB */ + {0,0,0,0,1,2,2,2,3,4,4,4,4,4,4,4,4,4,4,5}, /* A WB */ + {0}, + {0}, + {0,0,0,0,0,0,1,2,3,3,4,5,6,6,6,7}, /* V 16k */ + {0}, /* G 16k */ + {0,1}, /* T 16k */ + {0}, /*{0,0,0,0,0,0,0,0,0,0,1} */ /* A 16k */ +}; +const Word16 offset_in_lvq_mode_pred_fx[][32] = +{ + {0,0,0,0,1,2,2,2,3,4,5,5,5,5,5,5,5,5,5,6}, /* I NB */ + {0,1,1,1,2,3,4,4,4,4,4,5,5,5,6}, /* UV NB */ + {0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,3,4,4,5,6,7,8,9,10,10,11,12,13,13,13,14}, /* V NB */ + {0,0,0,0,1,1,1,2,3,4,5,6,6,7,8,9,10,11,12,13,14}, /* G NB */ + {0}, /* T NB */ + {0,0,0,0,1,2,2,2,2,3,4,5}, /* A NB */ + {0,0,0,0,1,2,2,2,3,4,5,5,5,5,5,5,5,5,5,6}, /* I WB */ + {0,1,1,1,2,3,4,4,4,4,4,5,5,5,6}, /* UV WB */ + {0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,3,4,4,5,6,7,8,9,10,10,11,12,13,13,13,14}, /* V WB */ + {0,0,0,0,1,1,1,2,3,4,5,6,6,7,8,9,10,11,12,13,14}, /* G WB */ + {0}, /* T WB */ + {0,0,0,0,1,2,2,2,3,4,4,4,4,4,4,4,4,4,4,5}, /* A WB */ + {0,0,0,0,1,2,2,2,3,4,5,5,5,5,5,5,5,5,5,6}, /* I 16k */ + {0}, /* UV 16k */ + {0,0,0,0,0,0,1,2,3,3,4,5,6,6,6,7}, /* V 16k */ + {0,0,0,0,0,0,1,2,3,4,5,6}, /* G 16k */ + {0}, /* T 16k */ + {0,0,0,0,0,0,1,2,3,4,5,6}, /* A 16k */ + {0,0,0,0,0,1,1,1,2,3,4,5,6,6,7,8,9,10,11,12,13,14}, /* G WB MA*/ +}; + + +const Word16 offset_lvq_modes_SN_fx[] = {-1,-1,26,51,77,96,-1,-1,12,36,66,90,-1,-1,105,-1,88,102, + 112 + }; /* CNG */ + +const Word16 offset_lvq_modes_pred_fx[] = {74, 95, 15, 45, -1, 66, 81, 102, 0, 30, -1, 60, 88, -1, 109, 117, -1, 139, 124}; + +const Word16 sfm_width[20] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7, 8}; +const Word16 a_table_fx[20] = {8, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 5, 7, 11}; + + +const Word16 inner_frame_tbl[4] = {L_FRAME8k, L_FRAME16k, L_FRAME32k, L_FRAME48k}; /* corresponds to NB, WB, SWB, FB */ + + + +/*------------------------------------------------------------------------------* + * SWB BWE tables + *------------------------------------------------------------------------------*/ + +const Word16 fb_bwe_subband[DIM_FB+1] = {640, 680, 720, 800}; +const Word16 fb_bwe_sm_subband[DIM_FB] = {656, 696, 760}; + +/*------------------------------------------------------------------------------* + * SWB TBE tables + *------------------------------------------------------------------------------*/ + +const Word16 lsf_q_num_bits[NUM_Q_LSF] = { 4, 4, 3, 3, 3 }; + +const Word16 skip_bands_SWB_TBE[NUM_SHB_SUBFR+1] = {0, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300, 320}; /* bands for SWB TBE quantisation */ +const Word16 skip_bands_WB_TBE[NUM_SHB_SUBFR/2+1] = {0, 10, 20, 30, 40, 50, 60, 70, 80}; /* bands for WB TBE quantisation */ + +const Word16 swb_lsp_prev_interp_init[10] = {32767, 31164, 26510, 19261, 10126, 0, -10126, -19261, -26510, -31164}; +/* st->swb_lsp_prev_interp[i] = (float)cos( (float)i * PI / (float)10.0f )*/ + +const Word16 allpass_poles_3_ov_2[9] = /* Q15 */ +{ + 2368, + 20545, + 30606, + 25520, + 7188, + 31808, + 28575, + 14384, + 32472 +}; +const Word16 decimate_3_ov_2_lowpass_num[3] = /* Q15 */ +{ + 6399, + 12797, + 6399 +}; +const Word16 decimate_3_ov_2_lowpass_den[3] = /* Q15 */ +{ + 32767, + 0, + 5624 +}; + +const Word16 interpol_frac_shb[NB_SUBFR*2] = +{ + 22938, 9830, 13107, 19660, 3277, 29490, 0, 32767 /* Q15*/ + /*0.7f, 0.3f, 0.4f, 0.6f, 0.1f, 0.9f, 0.0f, 1.0f */ +}; + +/*----------------------------------------------------------------------------------* +* ACELP/HQ core switching +*----------------------------------------------------------------------------------*/ +/* bandwidths */ +const Word16 Nb[ NB_SFM] = +{ + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, + 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 32, 32, 32, 32, 32, 32, 32, 32 +}; + +/* log2(Nb) to calculate minimum bits for one pulse in PVQ */ +const Word16 LNb[ NB_SFM] = +{ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5 +}; + + +const Word16 sin_switch_8[15] = {3212, 6393, 9512, 12540, 15447, 18205, 20788, 23170, + 25330, 27246, 28899, 30274, 31357, 32138, 32610 + }; + +const Word16 sin_switch_16[30] = {1660, 3315, 4962, 6596, 8213, 9810, 11380, 12922, + 14431, 15902, 17333, 18719, 20057, 21344, 22576, 23750, + 24863, 25912, 26895, 27808, 28651, 29419, 30112, 30728, + 31265, 31722, 32097, 32390, 32600, 32726 + }; + + +const Word16 sin_switch_32[60] = {844, 1687, 2529, 3369, 4207, 5043, 5875, 6703, + 7526, 8345, 9158, 9965, 10766, 11559, 12345, 13122, + 13891, 14650, 15400, 16140, 16869, 17586, 18293, 18986, + 19668, 20336, 20991, 21632, 22258, 22870, 23467, 24048, + 24613, 25162, 25694, 26209, 26707, 27187, 27649, 28092, + 28518, 28924, 29311, 29678, 30026, 30354, 30662, 30949, + 31216, 31462, 31688, 31892, 32075, 32237, 32378, 32497, + 32594, 32670, 32725, 32757 + }; + + +const Word16 sin_switch_48[90] = {566, 1131, 1696, 2261, 2825, 3388, 3950, 4511, + 5070, 5628, 6185, 6739, 7292, 7842, 8390, 8935, + 9478, 10018, 10555, 11089, 11620, 12147, 12670, 13190, + 13706, 14218, 14725, 15228, 15727, 16220, 16709, 17194, + 17672, 18146, 18614, 19077, 19534, 19985, 20431, 20870, + 21303, 21729, 22149, 22563, 22970, 23370, 23763, 24148, + 24527, 24899, 25263, 25619, 25968, 26309, 26642, 26968, + 27285, 27594, 27895, 28188, 28472, 28747, 29015, 29273, + 29523, 29764, 29996, 30219, 30433, 30639, 30835, 31021, + 31199, 31367, 31526, 31676, 31816, 31946, 32068, 32179, + 32281, 32373, 32456, 32529, 32592, 32646, 32690, 32724, + 32748, 32763 + }; + + +const Word16 one_on_win_48k_fx[210] = +{ + 16399, 16412, 16425, 16439, 16452, 16465, 16479, 16492, + 16506, 16519, 16533, 16547, 16561, 16575, 16589, 16603, + 16618, 16632, 16647, 16662, 16677, 16692, 16707, 16722, + 16738, 16754, 16770, 16786, 16802, 16818, 16835, 16851, + 16868, 16885, 16902, 16919, 16937, 16955, 16972, 16990, + 17008, 17027, 17045, 17064, 17083, 17102, 17121, 17140, + 17160, 17180, 17200, 17220, 17240, 17261, 17281, 17302, + 17323, 17345, 17366, 17388, 17410, 17432, 17454, 17477, + 17499, 17522, 17545, 17569, 17592, 17616, 17640, 17664, + 17689, 17713, 17738, 17763, 17789, 17814, 17840, 17866, + 17892, 17918, 17945, 17972, 17999, 18027, 18054, 18082, + 18110, 18139, 18167, 18196, 18225, 18255, 18284, 18314, + 18345, 18375, 18406, 18437, 18468, 18499, 18531, 18563, + 18596, 18628, 18661, 18695, 18728, 18762, 18796, 18830, + 18865, 18900, 18935, 18971, 19007, 19043, 19080, 19117, + 19154, 19191, 19229, 19267, 19306, 19345, 19384, 19423, + 19463, 19504, 19544, 19585, 19626, 19668, 19710, 19752, + 19795, 19838, 19882, 19926, 19970, 20015, 20060, 20105, + 20151, 20198, 20244, 20291, 20339, 20387, 20435, 20484, + 20533, 20583, 20633, 20684, 20735, 20787, 20839, 20891, + 20944, 20997, 21051, 21106, 21161, 21216, 21272, 21328, + 21385, 21443, 21501, 21559, 21618, 21678, 21738, 21799, + 21860, 21922, 21984, 22048, 22111, 22175, 22240, 22306, + 22372, 22439, 22506, 22574, 22643, 22712, 22782, 22853, + 22924, 22996, 23069, 23142, 23216, 23291, 23367, 23443, + 23521, 23599, 23677, 23757, 23837, 23918, 24000, 24083, + 24167, 24251 +}; + +const Word16 one_on_win_8k_16k_48k_fx[70] = +{ + 16432, 16472, 16512, 16554, 16596, 16639, 16684, 16730, + 16778, 16826, 16876, 16928, 16981, 17036, 17092, 17150, + 17210, 17271, 17334, 17399, 17465, 17534, 17604, 17676, + 17751, 17827, 17905, 17986, 18068, 18153, 18240, 18329, + 18421, 18515, 18612, 18711, 18813, 18918, 19025, 19135, + 19248, 19364, 19483, 19606, 19731, 19860, 19992, 20128, + 20268, 20411, 20558, 20709, 20865, 21024, 21188, 21357, + 21530, 21708, 21891, 22079, 22273, 22472, 22677, 22888, + 23105, 23329, 23560, 23797, 24041, 24251 +}; + + + +/* short filters for BWE of ACELP->HQ switching frame in Q15 */ +const Word16 hp12800_16000_fx[21] = +{ + -0, 70, -207, 380, -405, 0, 1041, -2668, 4505, + -5968, 6526, -5968, 4505, -2668, 1041, 0, -405, 380, + -207, 70, -0 +}; + +const Word16 hp12800_32000_fx[41] = +{ + -0, 45, 35, -47, -104, 0, 191, 156, + -203, -422, -0, 675, 523, -656, -1341, 0, + 2264, 1943, -2999, -9872, 19678, -9872, -2999, 1943, + 2264, 0, -1341, -656, 523, 675, -0, -422, + -203, 156, 191, 0, -104, -47, 35, 45, -0 +}; + +const Word16 hp12800_48000_fx[61] = +{ + -0, 22, 33, 23, -10, -51, -69, -37, 45, 127, + 140, 40, -136, -271, -238, 0, 326, 507, 349, -143, + -696, -894, -450, 535, 1509, 1696, 521, -1998, -5136, -7735, + 24039, -7735, -5136, -1998, 521, 1696, 1509, 535, -450, -894, + -696, -143, 349, 507, 326, 0, -238, -271, -136, 40, + 140, 127, 45, -37, -69, -51, -10, 23, 33, 22, -0, +}; + + +const Word16 hp16000_32000_fx[33] = +{ + -0, 62, -0, -127, -0, 270, -0, -523, -0, 940, + -0, -1662, -0, 3212, -0, -10353, 16407, -10353, -0, 3212, + -0, -1662, -0, 940, -0, -523, -0, 270, -0, -127, + -0, 62, -0 +}; + +const Word16 hp16000_48000_fx[49] = +{ + -0, 33, 39, -0, -64, -83, -0, 138, 175, 0, + -272, -334, -0, 493, 596, 0, -870, -1059, -0, 1636, + 2120, 0, -4448, -9003, 21858, -9003, -4448, 0, 2120, 1636, + -0, -1059, -870, 0, 596, 493, -0, -334, -272, 0, + 175, 138, -0, -83, -64, -0, 39, 33, -0 +}; + + + +const Word16 inner_frame_tbl_fx[4] = {L_FRAME8k, L_FRAME16k, L_FRAME32k, L_FRAME48k}; /* corresponds to NB, WB, SWB, FB */ + + +const Word16 cu15_fx[28][3] = /*Q13*/ +{ + /* xx/3, xx*xx/3, xx*xx*xx/3 xx v */ + /* 0:*/ { 182, 12, 1 }, /* 1/15 */ + /* 1:*/ { 364, 49, 6 }, /* 2/15 */ + /* 2:*/ { 546, 109, 22 }, /* 3/15 */ + /* 3:*/ { 728, 194, 52 }, /* 4/15 */ + /* 4:*/ { 910, 303, 101 }, /* 5/15 */ + /* 5:*/ { 1092, 437, 175 }, /* 6/15 */ + /* 6:*/ { 1274, 595, 278 }, /* 7/15 */ + /* 7:*/ { 1456, 777, 414 }, /* 8/15 */ + /* 8:*/ { 1638, 983, 590 }, /* 9/15 */ + /* 9:*/ { 1820, 1214, 809 }, /* 10/15 */ + /*10:*/ { 2002, 1468, 1077 }, /* 11/15 */ + /*11:*/ { 2185, 1748, 1398 }, /* 12/15 */ + /*12:*/ { 2367, 2051, 1778 }, /* 13/15 */ + /*13:*/ { 2549, 2379, 2220 }, /* 14/15 */ + /*14:*/ { 2913, 3107, 3314 }, /* 16/15 */ + /*15:*/ { 3095, 3507, 3975 }, /* 17/15 */ + /*16:*/ { 3277, 3932, 4719 }, /* 18/15 */ + /*17:*/ { 3459, 4381, 5550 }, /* 19/15 */ + /*18:*/ { 3641, 4855, 6473 }, /* 20/15 */ + /*19:*/ { 3823, 5352, 7493 }, /* 21/15 */ + /*20:*/ { 4005, 5874, 8615 }, /* 22/15 */ + /*21:*/ { 4187, 6420, 9844 }, /* 23/15 */ + /*22:*/ { 4369, 6991, 11185 }, /* 24/15 */ + /*23:*/ { 4551, 7585, 12642 }, /* 25/15 */ + /*24:*/ { 4733, 8204, 14221 }, /* 26/15 */ + /*25:*/ { 4915, 8847, 15925 }, /* 27/15 */ + /*26:*/ { 5097, 9515, 17761 }, /* 28/15 */ + /*27:*/ { 5279, 10207, 19733 }, /* 29/15 */ +}; + +const Word16 cu4_fx[6][3] = /*Q13*/ +{ + /* xx/3, xx*xx/3, xx*xx*xx/3 xx v */ + /* 0:*/ { 683, 171, 43 }, /* 1/4 */ + /* 1:*/ { 1365, 683, 341 }, /* 2/4 */ + /* 2:*/ { 2048, 1536, 1152 }, /* 3/4 */ + /* 3:*/ { 3413, 4267, 5333 }, /* 5/4 */ + /* 4:*/ { 4096, 6144, 9216 }, /* 6/4 */ + /* 5:*/ { 4779, 8363, 14635 }, /* 7/4 */ +}; + +const Word16 ct2_fx[7][14] = +{ + /* accepted configurations */ + /*input 12.8, output : fout/fin Q13*/ + /*8*/ {30, 22, 30, 16, 25, 30, 19, 30, 30, 0, 8, 4, 15, 5120}, + /*16*/ {25, 22, 19, 16, 16, 0, 0, 0, 12, 1, 4, 4, 15, 10240}, + /*32*/ {19, 16, 19, 16, 16, 0, 0, 0, 6, 2, 2, 4, 15, 20480}, + /*48*/ {17, 14, 15, 16, 16, 0, 0, 0, 4, 3, 4, 4, 15, 30720}, + + /*input 16, output :*/ + /*12*/ { 9, 3, 4, 5, 9, 0, 0, 0, 5, 0, 5, 5, 4, 6554}, + /*32*/ { 4, 4, 4, 4, 4, 0, 0, 0, 2, 1, 1, 4, 4, 16384}, + /*48*/ {18, 18, 18, 18, 18, 0, 0, 0, 5, 2, 1, 4, 15, 24576}, +}; + + +/* stable ISF vector */ +const Word16 stable_ISF_fx[M] = +{ 1023, 2048, 3072, 4096, 5120, 6144, 7168, 8192, 9216, 10240, 11264, 12288, 13311, 14335, 15361, 3978}; +/*------------------------------------------------------------------------------* + * SWB CNG table + *------------------------------------------------------------------------------*/ +const Word16 lsp_shb_prev_tbl_fx[LPC_SHB_ORDER]= +{ + /*Q15 */ + 0, + 1638, + 3277, + 4915, + 6554, + 8192, + 9830, + 11469, + 13107, + 14746 +}; +const Word16 ENR_ATT_fx[5] = /*Q8*/ +{ + 459, 357, 281, 255, 255 +}; + +const Word16 sin_table256_fx[] = +{ + 101, 302, 503, 704, 905, 1106, 1307, 1507, 1708, + 1909, 2110, 2310, 2511, 2711, 2912, 3112, 3312, 3512, + 3712, 3911, 4111, 4310, 4510, 4709, 4907, 5106, 5305, + 5503, 5701, 5899, 6097, 6294, 6491, 6688, 6885, 7081, + 7278, 7473, 7669, 7864, 8059, 8254, 8449, 8643, 8836, + 9030, 9223, 9416, 9608, 9800, 9992, 10183, 10374, 10565, + 10755, 10945, 11134, 11323, 11511, 11699, 11887, 12074, 12261, + 12447, 12633, 12818, 13003, 13187, 13371, 13554, 13737, 13919, + 14101, 14282, 14463, 14643, 14823, 15002, 15180, 15358, 15535, + 15712, 15888, 16064, 16239, 16413, 16587, 16760, 16932, 17104, + 17275, 17446, 17616, 17785, 17953, 18121, 18288, 18455, 18621, + 18786, 18950, 19114, 19277, 19439, 19601, 19761, 19921, 20081, + 20239, 20397, 20554, 20710, 20865, 21020, 21174, 21327, 21479, + 21631, 21781, 21931, 22080, 22228, 22375, 22522, 22668, 22812, + 22956, 23099, 23241, 23383, 23523, 23663, 23801, 23939, 24076, + 24212, 24347, 24481, 24614, 24746, 24878, 25008, 25138, 25266, + 25394, 25520, 25646, 25771, 25894, 26017, 26139, 26259, 26379, + 26498, 26616, 26733, 26848, 26963, 27077, 27190, 27301, 27412, + 27522, 27630, 27738, 27844, 27950, 28054, 28158, 28260, 28361, + 28461, 28560, 28658, 28755, 28851, 28946, 29040, 29132, 29224, + 29314, 29404, 29492, 29579, 29665, 29750, 29833, 29916, 29997, + 30078, 30157, 30235, 30312, 30388, 30462, 30536, 30608, 30680, + 30750, 30819, 30886, 30953, 31018, 31082, 31146, 31207, 31268, + 31328, 31386, 31443, 31499, 31554, 31608, 31660, 31711, 31761, + 31810, 31858, 31904, 31950, 31994, 32037, 32078, 32119, 32158, + 32196, 32233, 32268, 32303, 32336, 32368, 32398, 32428, 32456, + 32483, 32509, 32534, 32557, 32579, 32600, 32620, 32638, 32656, + 32672, 32686, 32700, 32712, 32723, 32733, 32742, 32749, 32756, + 32760, 32764, 32767, 32767 +}; +/*----------------------------------------------------------------------------------* + * 2nd order high-pass filter with cut-off frequency at 400 Hz. + * Designed with Chebyshev of 2nd type + * Optimized for fixed-point to get the following frequency response: + * + * frequency: 0Hz 100Hz 200Hz 300Hz 400Hz 630Hz 1.5kHz 3kHz + * dB loss: -infdB -30dB -20dB -10dB -3dB +6dB +1dB 0dB + * + * Algorithm: + * + * y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] + * + a[1]*y[i-1] + a[2]*y[i-2]; + * + * short b[3] = {3660, -7320, 3660}; in Q12 + * short a[3] = {4096, 7320, -3540}; in Q12 + *----------------------------------------------------------------------------------*/ +const Word16 b_hp400_fx[3] = { 3660, -7320, 3660}; /* Q12 (/4) */ +const Word16 a_hp400_fx[3] = {16384, 29280, -14160}; /* Q12 (x4) */ +/*----------------------------------------------------------------------------------* + * 15th-order band-pass 6kHz to 7kHz FIR filter. + * + * frequency: 4kHz 5kHz 5.5kHz 6kHz 6.5kHz 7kHz 7.5kHz 8kHz + * dB loss: -60dB -45dB -13dB -3dB 0dB -3dB -13dB -45dB + * + * gain = 4.0 + *----------------------------------------------------------------------------------*/ +const Word16 fir_6k_7k_fx[31] = +{ + -32, 47, 32, -27, -369, + 1122, -1421, 0, 3798, -8880, + 12349, -10984, 3548, 7766, -18001, + 22118, -18001, 7766, 3548, -10984, + 12349, -8880, 3798, 0, -1421, + 1122, -369, -27, 32, 47, + -32 +}; + + +const Word16 no_lead_fx[][MAX_NO_SCALES*2] = +{ + { 1, 0, 0, 1, 0, 0, }, /* 14 */ + { 2, 0, 0, 1, 0, 0, }, /* 15 */ + { 4, 2, 0, 1, 0, 0, }, /* 18 */ + { 4, 2, 0, 2, 0, 0, }, /* 19 */ + { 7, 5, 2, 5, 4, 2, }, /* 25 */ + { 8, 8, 3, 8, 6, 2, }, /* 28 */ /* mode UV WB*/ + { 4, 2, 0, 1, 0, 0, }, /* 18 */ + { 4, 0, 0, 2, 1, 0, }, /* 19 */ + { 9, 8, 8, 2, 2, 1, }, /* 24 */ + { 8, 5, 2, 5, 2, 1, }, /* 25 */ + { 18, 16, 8, 5, 5, 1, }, /* 29 */ + { 24, 21, 10, 8, 8, 2, }, /* 32 */ /* mode UV NB*/ + + { 2, 0, 0, 2, 0, 0, }, /* 17 */ + { 4, 2, 0, 1, 0, 0, }, /* 18 */ + { 7, 5, 2, 2, 0, 0, }, /* 21 */ + { 5, 2, 1, 4, 1, 0, }, /* 22 */ + { 8, 5, 2, 5, 2, 0, }, /* 25 */ + { 8, 7, 4, 5, 3, 2, }, + { 8, 8, 4, 6, 5, 2, }, + { 13, 8, 5, 6, 5, 2, }, + { 13, 8, 5, 8, 6, 2, }, + { 13, 8, 5, 11, 8, 2, }, /* 30 */ + { 24, 21, 8, 9, 8, 2, }, /* 32 */ + { 23, 18, 8, 13, 11, 3, }, + { 23, 21, 8, 17, 13, 4, }, /* 34 */ + { 31, 31, 17, 26, 25, 9, }, /* 37 */ /* mode V WB*/ + { 2, 0, 0, 2, 2, 0, }, /* 17 */ + { 4, 2, 0, 1, 0, 0, }, /* 18 */ + { 7, 5, 2, 2, 2, 0, }, /* 22 */ + { 8, 7, 2, 2, 2, 0, }, /* 23 */ + { 11, 8, 2, 2, 2, 0, }, /* 24 */ + { 13, 13, 9, 2, 2, 0, }, /* 25 */ + { 13, 11, 7, 5, 2, 0, }, /* 27 */ + { 18, 14, 9, 5, 5, 2, }, /* 29 */ + { 31, 31, 14, 11, 11, 5, }, /* 34 */ + { 31, 31, 27, 24, 21, 14, }, /* 37 */ /* mode V NB */ + { 5, 4, 0, 0, 0, 0, }, /* 12 (11.883) */ + { 2, 0, 0, 2, 0, 0, }, /* 16 (15.826) */ + { 4, 2, 0, 2, 0, 0, }, /* 19 (18.572) */ + { 5, 4, 0, 2, 0, 0, }, /* 20 (19.796) */ + { 7, 5, 2, 2, 0, 0, }, /* 21 (20.910) */ + { 8, 7, 2, 2, 0, 0, }, /* 22 (21.776) */ + { 5, 5, 2, 4, 2, 0, }, /* 23 (22.959) */ + { 8, 8, 5, 4, 2, 0, }, /* 25 (24.992) */ + { 8, 8, 7, 5, 2, 0, }, /* 26 (25.904) */ + { 13, 9, 8, 5, 2, 0, }, /* 27 (26.829) */ + { 13, 11, 8, 5, 5, 1, }, /* 28 (27.989) */ + { 13, 9, 8, 8, 5, 2, }, /* 29 (28.984) */ + { 22, 16, 10, 6, 5, 2, }, /* 30 (29.980) */ + { 21, 14, 10, 8, 7, 2, }, /* 31 (30.966) */ + { 24, 21, 10, 8, 8, 2, }, /* 32 (31.995) */ /* G WB*/ + + { 5, 4, 1, 0, 0, 0, }, /* 12 (11.925) */ + { 2, 0, 0, 2, 0, 0, }, /* 16 (15.826) */ + { 5, 4, 1, 1, 0, 0, }, /* 19 (18.745) */ + { 5, 4, 1, 2, 0, 0, }, /* 20 (19.838) */ + { 7, 5, 2, 2, 0, 0, }, /* 21 (20.910) */ + { 8, 5, 2, 2, 1, 0, }, /* 22 (21.985) */ + { 9, 8, 5, 2, 1, 0, }, /* 23 (22.815) */ + { 14, 13, 8, 2, 2, 0, }, /* 25 (24.996) */ + { 13, 8, 7, 4, 2, 0, }, /* 26 (25.993) */ + { 13, 9, 8, 5, 2, 2, }, /* 27 (26.954) */ + { 18, 13, 8, 5, 2, 2, }, /* 28 (27.992) */ + { 21, 13, 11, 5, 3, 2, }, /* 29 (28.996) */ + { 22, 21, 13, 5, 5, 2, }, /* 30 (29.988) */ + { 23, 21, 17, 7, 5, 2, }, /* 31 (30.962) */ + { 27, 23, 21, 8, 5, 2, }, /* 32 (31.987) */ /* G NB*/ + { 2, 0, 0, 2, 0, 0, }, /* 17 */ + { 4, 2, 0, 1, 0, 0, }, /* 18 */ + { 4, 1, 0, 4, 0, 0, }, /* 21 */ + { 5, 2, 0, 4, 1, 0, }, /* 22 */ + { 8, 5, 2, 4, 0, 0, }, /* 24 */ + { 8, 5, 2, 5, 2, 0, }, /* 25 */ + { 14, 10, 5, 5, 5, 1, }, /* 28 */ + { 14, 10, 5, 8, 8, 4, }, /* 30 */ + { 13, 10, 5, 13, 8, 8, }, + { 23, 21, 8, 8, 8, 4, }, + { 23, 18, 5, 13, 8, 8, }, /* 33 */ + /* mode T WB */ + { 2, 0, 0, 2, 2, 0, }, /* 17 */ + { 4, 2, 0, 1, 0, 0, }, /* 18 */ + { 7, 5, 2, 2, 2, 0, }, /* 22 */ + { 8, 7, 4, 2, 2, 0, }, /* 23 */ + { 11, 8, 5, 2, 2, 0, }, /* 24 */ + { 18, 8, 5, 2, 2, 0, }, /* 25 */ + { 16, 8, 5, 5, 5, 2, }, /* 28 */ + { 28, 23, 8, 5, 5, 5, }, /* 31 */ + { 31, 31, 8, 5, 5, 7, }, /* 32 */ /* mode T NB */ + + { 18, 18, 11, 9, 6, 5, }, /* 31 */ + { 24, 23, 13, 9, 6, 5, }, /* 32 */ /* mode G 16k */ + + { 24, 23, 13, 9, 6, 5, }, /* 32 (31.998) */ + { 36, 31, 18, 9, 6, 5, }, /* 33 (32.983) */ /* T 16k */ + + { 2, 0, 0, 2, 2, 0, }, /* 17 */ + { 7, 5, 2, 2, 0, 0, }, /* 21 */ + { 7, 5, 2, 2, 2, 0, }, /* 22 */ + { 9, 8, 3, 4, 2, 0, }, /* 25 */ + { 11, 9, 8, 4, 2, 0, }, /* 26 */ + { 48, 48, 34, 13, 11, 9 }, /* 36 */ /* mode AUDIO_WB 36 + 4 + 1 */ + + { 22, 10, 3, 0, 0, 0 }, /* 17 */ + { 6, 6, 2, 2, 0, 0 }, /* 21 */ + { 6, 6, 2, 2, 2, 0 }, /* 22 */ + { 23, 10, 3, 2, 2, 0 }, /* 26 */ + { 32, 16, 3, 2, 2, 0 }, /* 27 */ /* AUDIO_NB */ + { 39, 30, 12, 2, 2, 0 }, /* 28 */ /* AUDIO_NB */ + { 11, 9, 8, 4, 2, 0, }, /* 26 */ + { 48, 48, 48, 13, 9, 8 }, /* 36 */ /* mode AUDIO_WB 16k 15-36 + 4 + 1*/ + { 8, 7, 2, 2, 0, 0, }, /* 22 (21.776) */ + { 13, 13, 5, 5, 5, 0, }, /* 28 (27.994) */ + { 18, 17, 5, 5, 5, 1, }, /* 29 (28.996) */ + { 17, 13, 5, 8, 6, 2, }, /* 30 (29.991) */ + { 23, 21, 8, 9, 8, 3, }, /* 32 (31.992) */ + { 31, 29, 16, 8, 8, 3, }, /* 33 (32.993) */ + { 31, 25, 16, 12, 8, 8, }, /* 34 (33.968) */ + { 46, 48, 18, 18, 18, 12, }, /* 37 (36.995) */ /* VOICED 16k */ + { 14, 12, 9, 2, 2, 0, }, /* 25 (24.980) */ + { 15, 13, 3, 2, 2, 0, }, /* 25 (24.974) */ + { 17, 3, 0, 2, 2, 1, }, /* 25 (24.852) */ + { 13, 10, 3, 2, 2, 2, }, /* 25 (24.994) */ + { 14, 13, 8, 2, 2, 0, }, /* 25 (24.996) */ + { 7, 3, 0, 5, 3, 1, }, /* 25 (24.671) */ + { 4, 3, 2, 6, 6, 5, }, /* 25 (24.936) */ + { 4, 2, 0, 9, 9, 3, }, /* 25 (24.955) */ + { 4, 2, 0, 9, 8, 2, }, /* 25 (24.853) */ + { 4, 2, 0, 9, 7, 6, }, /* 25 (24.881) */ + { 6, 3, 0, 6, 3, 2, }, /* 25 (24.939) */ + { 3, 2, 0, 9, 8, 5, }, /* 25 (24.996) */ + { 2, 2, 0, 15, 3, 3, }, /* 25 (24.310) */ + { 4, 2, 0, 9, 9, 3, }, /* 25 (24.955) */ + { 4, 4, 2, 7, 6, 3, }, /* 25 (24.984) */ + { 3, 2, 0, 9, 7, 6, }, /* 25 (24.866) */ + +}; + +const Word16 no_lead_p_fx[][MAX_NO_SCALES*2] = +{ + + { 2, 1, 0, 0, 0, 0, }, /* 9 (8.464) */ + { 4, 2, 0, 2, 0, 0, }, /* 19 (18.572) */ + { 5, 5, 2, 4, 2, 0, }, /* 23 (22.959) */ + { 8, 5, 2, 4, 0, 0, }, /* 24 (23.949) */ + { 8, 8, 5, 4, 2, 0, }, /* 25 (24.992) */ + { 13, 11, 5, 5, 2, 0, }, /* 27 (26.902) */ + { 11, 10, 5, 6, 5, 2, }, /* 28 (27.996) */ + { 14, 13, 5, 7, 5, 2, }, /* 29 (28.937) */ + { 16, 13, 5, 8, 7, 2, }, /* 30 (29.954) */ + { 21, 21, 5, 8, 5, 2, }, /* 31 (30.978) */ + { 24, 21, 5, 8, 8, 4, }, /* 32 (31.978) */ + { 32, 23, 5, 13, 11, 5, }, /* 34 (33.975) */ + { 36, 31, 8, 16, 13, 5, }, /* 35 (34.975) */ + { 45, 35, 16, 18, 13, 5, }, /* 36 (35.889) */ + { 45, 35, 16, 38, 31, 8, }, /* 39 (38.488) */ /* V WB*/ /* 14 */ + + { 2, 0, 0, 0, 0, 0, }, /* 8 (7.913) */ + { 4, 2, 0, 2, 0, 0, }, /* 19 (18.572) */ + { 8, 7, 2, 2, 2, 0, }, /* 23 (22.773) */ + { 13, 11, 5, 2, 1, 0, }, /* 24 (23.999) */ + { 8, 8, 5, 4, 2, 0, }, /* 25 (24.992) */ + { 13, 11, 5, 5, 2, 1, }, /* 27 (26.962) */ + { 13, 11, 5, 5, 5, 2, }, /* 28 (27.835) */ + { 14, 13, 5, 7, 5, 2, }, /* 29 (28.937) */ + { 23, 21, 5, 5, 5, 2, }, /* 30 (29.969) */ + { 23, 18, 5, 8, 5, 2, }, /* 31 (30.952) */ + { 24, 21, 5, 8, 8, 4, }, /* 32 (31.978) */ + { 43, 41, 13, 9, 8, 5, }, /* 34 (33.992) */ + { 43, 36, 13, 13, 10, 5, }, /* 35 (35.000) */ + { 43, 40, 13, 17, 13, 9, }, /* 36 (35.980) */ + { 43, 42, 13, 31, 30, 18, }, /* 39 (38.512) */ /* V NB*/ /* 29 */ + + { 2, 0, 0, 1, 0, 0, }, /* 15 (14.733) */ + { 5, 4, 1, 1, 0, 0, }, /* 19 (18.745) */ + { 8, 7, 2, 2, 0, 0, }, /* 22 (21.776) */ + { 10, 9, 5, 2, 0, 0, }, /* 23 (22.791) */ + { 14, 13, 8, 2, 0, 0, }, /* 24 (23.999) */ + { 14, 13, 8, 2, 2, 0, }, /* 25 (24.996) */ + { 18, 17, 13, 2, 2, 0, }, /* 26 (25.934) */ + { 14, 13, 8, 5, 4, 0, }, /* 28 (27.969) */ + { 18, 17, 13, 5, 4, 2, }, /* 29 (28.996) */ + { 22, 21, 13, 5, 5, 2, }, /* 30 (29.988) */ + { 31, 23, 21, 5, 5, 2, }, /* 31 (30.931) */ + { 27, 23, 21, 8, 5, 2, }, /* 32 (31.987) */ + { 31, 23, 21, 9, 8, 5, }, /* 33 (32.982) */ + { 32, 31, 24, 11, 8, 5, }, /* 34 (33.967) */ + { 32, 32, 28, 13, 11, 8, }, /* 35 (34.994) */ /* G WB*/ /* 44 */ + + { 2, 0, 0, 1, 0, 0, }, /* 15 (14.733) */ + { 5, 4, 2, 1, 0, 0, }, /* 19 (18.792) */ + { 8, 5, 2, 2, 1, 0, }, /* 22 (21.985) */ + { 8, 7, 2, 2, 2, 0, }, /* 23 (22.773) */ + { 13, 11, 2, 2, 1, 0, }, /* 24 (23.932) */ + { 16, 13, 2, 2, 2, 0, }, /* 25 (24.955) */ + { 21, 17, 2, 2, 2, 0, }, /* 26 (25.991) */ + { 13, 12, 2, 5, 5, 2, }, /* 28 (27.979) */ + { 18, 16, 2, 5, 5, 2, }, /* 29 (28.878) */ + { 23, 21, 2, 5, 5, 2, }, /* 30 (29.954) */ + { 32, 28, 2, 5, 5, 2, }, /* 31 (30.893) */ + { 38, 31, 2, 7, 5, 2, }, /* 32 (31.963) */ + { 33, 31, 2, 8, 8, 4, }, /* 33 (32.997) */ + { 42, 31, 2, 9, 9, 8, }, /* 34 (33.986) */ + { 42, 31, 2, 13, 11, 9, }, /* 35 (34.952) */ /* G NB*/ /* 59 */ + + { 7, 5, 2, 2, 0, 0, }, /* 21 (20.910) */ + { 8, 8, 5, 4, 2, 0, }, /* 25 (24.992) */ + { 13, 8, 5, 4, 2, 0, }, /* 26 */ + { 13, 8, 5, 8, 6, 2, }, /* 29 */ + { 13, 8, 5, 9, 8, 5, }, /* 30 */ + { 48, 48, 48, 36, 36, 28 }, /* 40 */ /* mode 7 AUDIO_WB */ /* 65*/ + + { 7, 5, 2, 2, 0, 0 }, /* 21 */ + { 13, 13, 9, 2, 2, 0 }, /* 25 */ + { 18, 18, 9, 2, 2, 0 }, /* 26 */ + { 24, 23, 10, 5, 4, 2 }, /* 30 */ + { 31, 31, 12, 5, 5, 2 }, /* 31 */ /*AUDIO_NB */ /* 70 */ + { 43, 34, 12, 5, 5, 4 }, /* 32 */ /*AUDIO_NB */ /* 71 */ + { 13, 8, 5, 9, 8, 5, }, /* 30 */ + { 48, 48, 45, 45, 31, 25 }, /* 40 */ /* mode AUDIO_WB 16k */ /* 73*/ + + { 2, 0, 0, 2, 2, 0, }, /* 17 (16.823) */ + { 7, 5, 2, 2, 0, 0, }, /* 21 (20.910) */ + { 7, 5, 2, 2, 2, 0, }, /* 22 (21.907) */ + { 13, 11, 10, 2, 2, 0, }, /* 25 (24.863) */ + { 18, 18, 10, 2, 2, 0, }, /* 26 (25.921) */ + { 13, 9, 9, 5, 2, 0, }, /* 27 (26.837) */ + { 40, 28, 25, 18, 17, 2, }, /* 36 (35.998) */ /* INACTIVE NB*/ /* 80*/ + + { 18, 17, 11, 0, 0, 0, }, /* 17 (16.932) */ + { 7, 5, 2, 2, 0, 0, }, /* 21 (20.910) */ + { 8, 5, 2, 2, 1, 0, }, /* 22 (21.985) */ + { 13, 13, 9, 2, 2, 0, }, /* 25 (24.845) */ + { 18, 18, 12, 2, 2, 0, }, /* 26 (25.999) */ + { 23, 23, 16, 2, 2, 0, }, /* 27 (26.981) */ + { 36, 32, 24, 17, 13, 13, }, /* 36 (35.929) */ /* INACTIVE WB */ /* 87 */ + + { 2, 2, 0, 2, 0, 0, }, /* 17 (16.823) */ + { 7, 5, 2, 2, 0, 0, }, /* 21 (20.910) */ + { 8, 5, 2, 2, 1, 0, }, /* 22 (21.985) */ + { 13, 13, 9, 2, 2, 0, }, /* 25 (24.845) */ + { 18, 17, 13, 2, 2, 0, }, /* 26 (25.934) */ + { 23, 22, 17, 2, 2, 0, }, /* 27 (26.914) */ + { 34, 32, 24, 16, 16, 13, }, /* 36 (35.915) */ /* INACTIVE WB 16k*/ /* 94 */ + + { 4, 2, 0, 1, 0, 0, }, /* 18 (17.479) */ + { 5, 4, 0, 1, 0, 0, }, /* 19 (18.703) */ + { 8, 7, 2, 2, 0, 0, }, /* 22 (21.776) */ + { 10, 9, 5, 2, 0, 0, }, /* 23 (22.791) */ + { 15, 13, 5, 2, 0, 0, }, /* 24 (23.999) */ + { 18, 16, 8, 5, 5, 1, }, /* 29 (28.966) */ + { 42, 32, 31, 5, 5, 2, }, /* 32 (31.990) */ /* UNVOICED NB*/ /* 100 */ + + { 1, 0, 0, 1, 0, 0, }, /* 14 (13.640) */ + { 2, 0, 0, 1, 0, 0, }, /* 15 (14.733) */ + { 4, 2, 0, 1, 0, 0, }, /* 18 (17.479) */ + { 4, 2, 0, 2, 0, 0, }, /* 19 (18.572) */ + { 5, 4, 0, 2, 0, 0, }, /* 20 (19.796) */ + { 8, 8, 5, 4, 2, 0, }, /* 25 (24.992) */ + { 11, 10, 5, 6, 5, 2, }, /* 28 (27.996) */ /* UNVOICED WB */ /* 106 */ + { 9, 3, 0, 4, 0, 0, }, /* 24 (23.818) */ + { 18, 13, 10, 8, 3, 0, }, /* 30 (29.992) */ + { 24, 18, 10, 9, 3, 0, }, /* 31 (30.998) */ + { 32, 25, 10, 9, 3, 0, }, /* 32 (31.987) */ + { 42, 31, 10, 12, 3, 2, }, /* 34 (33.994) */ + { 44, 32, 27, 15, 3, 2, }, /* 35 (35.000) */ + { 44, 32, 25, 19, 3, 2, }, /* 36 (35.994) */ + { 48, 39, 32, 35, 15, 3, }, /* 39 (38.301) */ /* VOICED 16k */ + { 11, 10, 5, 4, 2, 0, }, /* 26 (25.917) */ /* 107 */ + { 23, 23, 17, 8, 7, 2, }, /* 32 (31.980) */ + { 32, 31, 18, 9, 7, 5, }, /* 33 (32.990) */ + { 31, 31, 18, 11, 9, 8, }, /* 34 (33.974) */ + { 32, 32, 20, 13, 12, 8, }, /* 35 (34.989) */ + { 32, 32, 23, 18, 17, 8, }, /* 36 (35.988) */ + { 32, 32, 23, 23, 22, 10, }, /* 37 (36.989) */ /* GENERIC 16k*/ /* 113 */ + + { 2, 0, 0, 2, 0, 0, }, /* 16 (15.826) */ /* 114 */ + { 7, 5, 2, 2, 0, 0, }, /* 21 (20.910) */ + { 14, 13, 8, 2, 0, 0, }, /* 24 (23.999) */ + { 8, 8, 5, 4, 2, 0, }, /* 25 (24.992) */ + { 11, 10, 5, 4, 2, 0, }, /* 26 (25.917) */ + { 16, 13, 8, 4, 2, 0, }, /* 27 (26.883) */ + { 13, 13, 8, 5, 4, 2, }, /* 28 (27.901) */ + { 23, 18, 13, 5, 5, 2, }, /* 30 (29.916) */ + { 23, 23, 13, 7, 5, 2, }, /* 31 (30.993) */ + { 23, 23, 17, 8, 7, 2, }, /* 32 (31.980) */ + { 32, 31, 24, 8, 7, 2, }, /* 33 (32.958) */ + { 42, 32, 31, 9, 9, 4, }, /* 34 (33.987) */ + { 40, 32, 29, 12, 9, 9, }, /* 35 (34.994) */ + { 40, 32, 31, 17, 11, 11, }, /* 36 (35.968) */ + { 41, 32, 31, 20, 18, 13, }, /* 37 (36.971) */ /* GENERIC 12.8k MA*/ /* 128 */ + + { 11, 10, 5, 4, 2, 0, }, /* 26 (25.917) */ /* 129 */ + { 23, 23, 17, 8, 7, 2, }, /* 32 (31.980) */ + { 31, 31, 18, 9, 8, 2, }, /* 33 (32.995) */ + { 48, 32, 24, 9, 8, 3, }, /* 34 (33.993) */ + { 48, 32, 28, 11, 10, 3, }, /* 35 (34.992) */ + { 48, 37, 32, 16, 12, 4, }, /* 36 (35.997) */ + { 48, 37, 32, 18, 17, 12, }, /* 37 (36.961) */ /* AUDIO 16k */ +}; + +const Word16 pl_HQ_fx[] = /* Q1 vectors in first layers */ +{ + 2, 2, 0, 0, 0, 0, 0, 0, /* 112, 4, 28 */ + 1, 1, 1, 1, 1, 1, 1, 1, /* 128, 128, 1 */ + 2, 2, 2, 2, 0, 0, 0, 0, /* 1120, 16, 70 */ + 4, 0, 0, 0, 0, 0, 0, 0, /* 16 , 2, 8 */ + 3, 1, 1, 1, 1, 1, 1, 1, /* 5 */ /* 1024,128, 8 */ + 2, 2, 2, 2, 2, 2, 0, 0, /* 1792, 64, 28 */ + 4, 2, 2, 0, 0, 0, 0, 0, /* 1344, 8, 168 */ + 3, 3, 1, 1, 1, 1, 1, 1, /* 3584, 128, 28*/ + 2, 2, 2, 2, 2, 2, 2, 2, /*256, 256, 1*/ + 4, 2, 2, 2, 2, 0, 0, 0, /* 10 */ /* 8960, 32, 280 */ + 4, 4, 0, 0, 0, 0, 0, 0, /* 112, 4, 28 */ + 3, 3, 3, 1, 1, 1, 1, 1, /* 7168, 128, 56 */ + 5, 1, 1, 1, 1, 1, 1, 1, /* 1024, 128, 8*/ + 4, 2, 2, 2, 2, 2, 2, 0, /* 7168, 128, 56*/ + 4, 4, 2, 2, 0, 0, 0, 0, /* 15 */ /* 6720, 16, 420 */ + 6, 2, 0, 0, 0, 0, 0, 0, /* 224, 4, 56 */ + 3, 3, 3, 3, 1, 1, 1, 1, /* 8960, 128, 70 */ + 5, 3, 1, 1, 1, 1, 1, 1, /* 7168, 128, 56*/ + 4, 4, 2, 2, 2, 2, 0, 0, /* 26880, 64, 420 */ + 4, 4, 4, 0, 0, 0, 0, 0, /*20 */ /* 448, 8, 56 */ + 6, 2, 2, 2, 0, 0, 0, 0, /* 4480, 16, 280 */ + 3, 3, 3, 3, 3, 1, 1, 1, /* 7168, 128, 56 */ + 5, 3, 3, 1, 1, 1, 1, 1, /* 21504, 128, 168 */ + 4, 4, 2, 2, 2, 2, 2, 2, /* 7168, 256, 28 */ + 4, 4, 4, 2, 2, 0, 0, 0, /* 25 */ /* 17920, 32, 560 */ + 6, 2, 2, 2, 2, 2, 0, 0, /* 10752, 64, 168 */ + 6, 4, 2, 0, 0, 0, 0, 0, /* 2688, 8, 336 */ + 3, 3, 3, 3, 3, 3, 1, 1, /* 3584, 128, 28 */ + 5, 3, 3, 3, 1, 1, 1, 1, /* 35840,128,280*/ + 5, 5, 1, 1, 1, 1, 1, 1, /*30 */ /* 3584, 128, 28*/ + 7, 1, 1, 1, 1, 1, 1, 1, /* 1024,128, 8 */ + 4, 4, 4, 2, 2, 2, 2, 0, + 4, 4, 4, 4, 0, 0, 0, 0, + 6, 2, 2, 2, 2, 2, 2, 2, + 6, 4, 2, 2, 2, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 1, + 5, 3, 3, 3, 3, 1, 1, 1, + 5, 5, 3, 1, 1, 1, 1, 1, + 7, 3, 1, 1, 1, 1, 1, 1, + 4, 4, 4, 4, 2, 2, 0, 0, + 6, 4, 2, 2, 2, 2, 2, 0, + 6, 4, 4, 2, 0, 0, 0, 0, + 6, 6, 0, 0, 0, 0, 0, 0, + 8, 2, 2, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, + 5, 3, 3, 3, 3, 3, 1, 1, + 5, 5, 3, 3, 1, 1, 1, 1, + 7, 3, 3, 1, 1, 1, 1, 1 +}; + +const Word32 table_no_cv_fx[] = { 0, 112, 240, 1360, 1376, 2400, 4192, 5536, 9120, 9376, 18336, 18448, 25616, 26640, 33808, 40528, 40752, + 49712, 56880, 83760, 84208, 88688, 95856, 117360, 124528, 142448, 153200, 155888, 159472, 195312, 198896, 199920, + 235760, 236880, 238928, 274768, 274784, 275808, 311648, 333152, 340320, 367200, 410208, 423648,423760, 425104, 425232, 446736, 500496, 522000 + ,0 + }; + + + +/* Innovative codebook config */ +const PulseConfig PulseConfTable[ACELP_FIXED_CDK_NB] = +{ + /* Design rules: + * ---> "fixed" + "tried-pair-pos"*2 = pulses & 0xfe + * ---> tracks with pulses % 3 == 0, have always TRACKPOS_FIXED_FIRST */ + /* bits,iter,alp,pulses,fixed,tried-pair-pos,codetrack*/ + { 7, 4, 16384/*2.0f Q13*/, 1, 0, {8}, TRACKPOS_FREE_ONE }, /* 7 bits, 1 pulses, 4 tracks, 1000 free track */ + { 10, 4, 16384/*2.0f Q13*/, 2, 0, {8}, TRACKPOS_FIXED_EVEN }, /* 10 bits, 2 pulses, 4 tracks 1010 (used only even tracks designed for NB) */ + { 12, 4, 16384/*2.0f Q13*/, 2, 0, {8}, TRACKPOS_FIXED_TWO }, /* 12 bits, 2 pulses, 2 tracks 11 used all tracks ala AMR-WB 6.6 */ + { 15, 4, 16384/*2.0f Q13*/, 3, 0, {8}, TRACKPOS_FIXED_FIRST }, /* 15 bits, 3 pulses, 4 tracks 1110 fixed track to first ? */ + { 17, 6, 16384/*2.0f Q13*/, 3, 0, {8}, TRACKPOS_FREE_THREE }, /* 17 bits, 3 pulses, 4 tracks (used all tracks) - 1110, 1101, 1011, 0111 */ + { 20, 4, 16384/*2.0f Q13*/, 4, 0, {4, 8}, TRACKPOS_FIXED_FIRST }, /* 20 bits, 4 pulses, 4 tracks 1111 */ + { 24, 4, 16384/*2.0f Q13*/, 5, 0, {4, 8}, TRACKPOS_FIXED_FIRST }, /* 24 bits, 5 pulses, 4 tracks 2111 fixed track to first */ + { 26, 4, 16384/*2.0f Q13*/, 5, 0, {4, 8}, TRACKPOS_FREE_ONE }, /* 26 bits, 5 pulses, 4 tracks 2111 one free track ? */ + { 28, 4, 12288/*1.5f Q13*/, 6, 0, {4, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 28 bits, 6 pulses, 4 tracks 2211 */ + { 30, 4, 12288/*1.5f Q13*/, 6, 0, {4, 8, 8}, TRACKPOS_FIXED_TWO }, /* 30 bits, 6 pulses, 4 tracks 2211 free consecutive track positions ? */ + { 32, 4, 12288/*1.5f Q13*/, 7, 0, {4, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 32 bits, 6 pulses, 4 tracks 2221 fixed ?*/ + { 34, 4, 12288/*1.5f Q13*/, 7, 0, {4, 8, 8}, TRACKPOS_FREE_THREE }, /* 34 bits, 6 pulses, 4 tracks 2221 free track positions ? */ + { 36, 4, 8192/*1.0f Q13*/, 8, 2, {4, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 36 bits, 8 pulses, 4 tracks 2222 */ + { 40, 4, 8192/*1.0f Q13*/, 9, 2, {4, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 40 bits, 9 pulses, 4 tracks 3222 fixed ?*/ + { 43, 4, 8192/*1.0f Q13*/, 10, 2, {4, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 44 bits, 10 pulses, 4 tracks 3322 */ + { 46, 4, 8192/*1.0f Q13*/, 10, 2, {4, 6, 8, 8}, TRACKPOS_FIXED_TWO }, /* 46 bits, 10 pulses, 4 tracks 3322 free consecutive tracks ? */ + { 47, 4, 8192/*1.0f Q13*/, 11, 2, {4, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 47 bits, 10 pulses, 4 tracks 3332 fixed ? */ + { 49, 4, 8192/*1.0f Q13*/, 11, 2, {4, 6, 8, 8}, TRACKPOS_FREE_THREE }, /* 49 bits, 10 pulses, 4 tracks 3332 free three track positions ? */ + { 50, 4, 8192/*1.0f Q13*/, 12, 4, {4, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 50 bits, 12 pulses, 4 tracks 3333 */ + { 53, 4, 8192/*1.0f Q13*/, 13, 4, {4, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 53 bits, 13 pulses, 4 tracks 4333 fixed ? */ + { 55, 4, 8192/*1.0f Q13*/, 13, 4, {4, 6, 8, 8}, TRACKPOS_FREE_ONE }, /* 55 bits, 13 pulses, 4 tracks 4333 free one ? */ + { 56, 4, 8192/*1.0f Q13*/, 14, 4, {4, 6, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 56 bits, 14 pulses, 4 tracks 4433 fixed ?!?! */ + { 58, 4, 8192/*1.0f Q13*/, 14, 4, {4, 6, 6, 8, 8}, TRACKPOS_FIXED_TWO }, /* 58 bits, 14 pulses, 4 tracks 4433 free consecutive ? */ + { 59, 4, 8192/*1.0f Q13*/, 15, 4, {4, 6, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 59 bits, 15 pulses, 4 tracks 4443 fixed ? */ + { 61, 4, 8192/*1.0f Q13*/, 15, 4, {4, 6, 6, 8, 8}, TRACKPOS_FREE_THREE }, /* 61 bits, 15 pulses, 4 tracks 4443 free ? */ + { 62, 3, 6554/*0.8f Q13*/, 16, 4, {4, 4, 6, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 62 bits, 16 pulses, 4 tracks 4444 */ + { 65, 3, 6554/*0.8f Q13*/, 17, 4, {4, 4, 6, 6, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 65 bits, 17 pulses, 4 tracks 5444 fixed ?*/ + { 68, 3, 6144/*0.75f Q13*/, 18, 4, {2, 3, 4, 5, 6, 7, 8}, TRACKPOS_FIXED_FIRST }, /* 68 bits, 18 pulses, 4 tracks 5544 */ + { 70, 3, 6144/*0.75f Q13*/, 19, 4, {2, 3, 4, 5, 6, 7, 8}, TRACKPOS_FIXED_FIRST }, /* 70 bits, 19 pulses, 4 tracks 5554 fixed ? */ + { 73, 3, 6144/*0.75f Q13*/, 20, 4, {2, 3, 4, 5, 6, 7, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 73 bits, 20 pulses, 4 tracks 5555 fixed ? */ + { 75, 3, 6144/*0.75f Q13*/, 21, 4, {2, 3, 4, 5, 6, 7, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 75 bits, 21 pulses, 4 tracks 6555 fixed ? */ + { 78, 3, 6144/*0.75f Q13*/, 22, 4, {2, 3, 4, 5, 6, 7, 8, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 78 bits, 22 pulses, 4 tracks 6655 fixed ? */ + { 80, 3, 6144/*0.75f Q13*/, 23, 4, {2, 3, 4, 5, 6, 7, 8, 8, 8}, TRACKPOS_FIXED_FIRST }, /* 80 bits, 23 pulses, 4 tracks 6665 fixed ? */ + { 83, 2, 2458/*0.30f Q13*/, 24, 4, {2, 3, 4, 5, 6, 7, 8, 8, 8, 8}, TRACKPOS_FIXED_FIRST}, /* 83 bits, 24 pulses, 4 tracks 6666 */ + { 85, 2, 2458/*0.30f Q13*/, 25, 4, {2, 3, 4, 5, 6, 7, 8, 8, 8, 8}, TRACKPOS_FIXED_FIRST}, /* 85 bits, 25 pulses, 4 tracks 7666 */ + { 87, 2, 2048/*0.25f Q13*/, 26, 4, {2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8}, TRACKPOS_FIXED_FIRST}, /* 87 bits, 26 pulses, 4 tracks 7766 */ + { 89, 2, 2048/*0.25f Q13*/, 27, 4, {2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8}, TRACKPOS_FIXED_FIRST}, /* 89 bits, 27 pulses, 4 tracks 7776 */ + { 92, 2, 2048/*0.25f Q13*/, 28, 4, {2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8}, TRACKPOS_FIXED_FIRST}, /* 92 bits, 28 pulses, 4 tracks 7777 */ + { 94, 2, 2048/*0.25f Q13*/, 29, 4, {2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8}, TRACKPOS_FIXED_FIRST}, /* 94 bits, 29 pulses, 4 tracks 8777 */ + { 96, 1, 1638/*0.20f Q13*/, 30, 4, {2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8}, TRACKPOS_FIXED_FIRST}, /* 96 bits, 30 pulses, 4 tracks 8877 */ + { 98, 1, 1638/*0.20f Q13*/, 31, 4, {2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8}, TRACKPOS_FIXED_FIRST}, /* 98 bits, 31 pulses, 4 tracks 8887 */ +}; + +/*----------------------------------------------------------------------------------* + * LSF quantization for CNG + *----------------------------------------------------------------------------------*/ +const Word16 cng_sort_fx[] = {/*5f */1,1,0,1,0,0, /* 4f */0,1,0,1,0,0,1,1,1,1}; + +const Word16 perm_MSLVQ_fx[][4] = +{ + /* 5f*/ + {6,11,7,15}, + {6,15,-1,0}, + {5,8,7,15}, + {7,10,-1,0}, + {-1,0,0,0}, + {-1,0,0,0}, + /* 4f */ + {-1,0,0,0}, + {0,9,7,10}, + {-1,0,0,0}, + {7,15,-1,0}, + {-1,0,0,0}, + {-1,0,0,0}, + {6,10,7,11}, + {6,11,7,12}, + {6,11,7,12}, + {6,11,7,12} +}; +/*----------------------------------------------------------------------------------* + * table of cos(x) in Q15 used in FFT for spectral analysis + *----------------------------------------------------------------------------------*/ +const Word16 cos_table_129[129] = +{ + 32767, + 32758, 32729, 32679, 32610, 32522, 32413, 32286, 32138, + 31972, 31786, 31581, 31357, 31114, 30853, 30572, 30274, + 29957, 29622, 29269, 28899, 28511, 28106, 27684, 27246, + 26791, 26320, 25833, 25330, 24812, 24279, 23732, 23170, + 22595, 22006, 21403, 20788, 20160, 19520, 18868, 18205, + 17531, 16846, 16151, 15447, 14733, 14010, 13279, 12540, + 11793, 11039, 10279, 9512, 8740, 7962, 7180, 6393, + 5602, 4808, 4011, 3212, 2411, 1608, 804, 0, + -804, -1608, -2411, -3212, -4011, -4808, -5602, -6393, + -7180, -7962, -8740, -9512, -10279, -11039, -11793, -12540, + -13279, -14010, -14733, -15447, -16151, -16846, -17531, -18205, + -18868, -19520, -20160, -20788, -21403, -22006, -22595, -23170, + -23732, -24279, -24812, -25330, -25833, -26320, -26791, -27246, + -27684, -28106, -28511, -28899, -29269, -29622, -29957, -30274, + -30572, -30853, -31114, -31357, -31581, -31786, -31972, -32138, + -32286, -32413, -32522, -32610, -32679, -32729, -32758, -32768 +}; + +/*----------------------------------------------------------------------------------* + * slope in Q11 used to compute y = acos(x) + ----------------------------------------------------------------------------------*/ +const Word16 acos_slope[128] = +{ + -26214, -9039, -5243, -3799, -2979, -2405, -2064, -1771, + -1579, -1409, -1279, -1170, -1079, -1004, -933, -880, + -827, -783, -743, -708, -676, -647, -621, -599, + -576, -557, -538, -521, -506, -492, -479, -466, + -456, -445, -435, -426, -417, -410, -402, -395, + -389, -383, -377, -372, -367, -363, -359, -355, + -351, -348, -345, -342, -340, -337, -335, -333, + -331, -330, -329, -328, -327, -326, -326, -326, + -326, -326, -326, -327, -328, -329, -330, -331, + -333, -335, -337, -340, -342, -345, -348, -351, + -355, -359, -363, -367, -372, -377, -383, -389, + -395, -402, -410, -417, -426, -435, -445, -456, + -466, -479, -492, -506, -521, -538, -557, -576, + -599, -621, -647, -676, -708, -743, -783, -827, + -880, -933, -1004, -1079, -1170, -1279, -1409, -1579, + -1771, -2064, -2405, -2979, -3799, -5243, -9039,-26214 +}; + +/*----------------------------------------------------------------------------------* + * Quantization table for scaled innovation energy prediciton in Q8 + *----------------------------------------------------------------------------------*/ +const Word16 Es_pred_qua_5b_fx[32] = +{ + -2048, + -525, + 642, + 1688, + 2547, + 3326, + 4026, + 4647, + 5211, + 5740, + 6221, + 6661, + 7067, + 7447, + 7815, + 8170, + 8518, + 8865, + 9204, + 9551, + 9912, + 10284, + 10669, + 11077, + 11509, + 11976, + 12486, + 13049, + 13695, + 14434, + 15354, + 16640, +}; + + +const Word16 Es_pred_qua_4b_fx[16] = +{ + -2048, + -36, + 1828, + 3284, + 4584, + 5742, + 6821, + 7834, + /*8779, */ + 8778, + 9701, + 10610, + 11524, + 12487, + 13560, + 14862, + 16640 +}; + + +const Word16 Es_pred_qua_3b_fx[8] = +{ + 1521/* 5.9422f Q8*/, + 3909/*15.2711f Q8*/, + 5987/*23.3857f Q8*/, + 7816/*30.5310f Q8*/, + 9477/*37.0190f Q8*/, + 11124/*43.4539f Q8*/, + 12863/*50.2442f Q8*/, + 15031/*58.7164f Q8*/ +}; +const Word16 Es_pred_qua_4b_no_ltp_fx[16] = +{ + -1280/*-5.f Q8*/, + 0/* 0.f Q8*/, + 1280/* 5.f Q8*/, + 2560/*10.f Q8*/, + 3840/*15.f Q8*/, + 5120/*20.f Q8*/, + 6400/*25.f Q8*/, + 7680/*30.f Q8*/, + 8960/*35.f Q8*/, + 10240/*40.f Q8*/, + 11520/*45.f Q8*/, + 12800/*50.f Q8*/, + 14080/*55.f Q8*/, + 15360/*60.f Q8*/, + 16640/*65.f Q8*/, + 17920/*70.f Q8*/ +}; +/*----------------------------------------------------------------------------------* + * Transition coding - gain quantization table + *----------------------------------------------------------------------------------*/ +const Word16 tbl_gain_code_tc_fx[N_GAIN_CODE_TC] = /*q13 */ +{ + 2966, + 5930, + 7924, + 9712, + 11566, + 13754, + 16993, + 27280 +}; +/*----------------------------------------------------------------------------------* + * MA predicition coefficients for gain quantizer + *----------------------------------------------------------------------------------*/ + +const Word16 pred_gain_fx[GAIN_PRED_ORDER] = {8192, 6554, 4915, 3277}; + +const Word16 t_qua_gain6b_fx[64*2] = +{ + 1566, 1332, + 1577, 3557, + 3071, 6490, + 4193, 10163, + 4496, 2534, + 5019, 4488, + 5586, 15614, + 5725, 1422, + 6453, 580, + 6724, 6831, + 7657, 3527, + 8072, 2099, + 8232, 5319, + 8827, 8775, + 9740, 2868, + 9856, 1465, + 10087, 12488, + 10241, 4453, + 10859, 6618, + 11321, 3587, + 11417, 1800, + 11643, 2428, + 11718, 988, + 12312, 5093, + 12523, 8413, + 12574, 26214, + 12601, 3396, + 13172, 1623, + 13285, 2423, + 13418, 6087, + 13459, 12810, + 13656, 3607, + 14111, 4521, + 14144, 1229, + 14425, 1871, + 14431, 7234, + 14445, 2834, + 14628, 10036, + 14860, 17496, + 15161, 3629, + 15209, 5819, + 15299, 2256, + 15518, 4722, + 15663, 1060, + 15759, 7972, + 15939, 11964, + 16020, 2996, + 16086, 1707, + 16521, 4254, + 16576, 6224, + 16894, 2380, + 16906, 681, + 17213, 8406, + 17610, 3418, + 17895, 5269, + 18168, 11748, + 18230, 1575, + 18607, 32767, + 18728, 21684, + 19137, 2543, + 19422, 6577, + 19446, 4097, + 19450, 9056, + 20371, 14885 +}; + +const Word16 t_qua_gain7b_fx[128*2] = +{ + 204, 441, + 464, 1977, + 869, 1077, + 1072, 3062, + 1281, 4759, + 1647, 1539, + 1845, 7020, + 1853, 634, + 1995, 2336, + 2351, 15400, + 2661, 1165, + 2702, 3900, + 2710, 10133, + 3195, 1752, + 3498, 2624, + 3663, 849, + 3984, 5697, + 4214, 3399, + 4415, 1304, + 4695, 2056, + 5376, 4558, + 5386, 676, + 5518, 23554, + 5567, 7794, + 5644, 3061, + 5672, 1513, + 5957, 2338, + 6533, 1060, + 6804, 5998, + 6820, 1767, + 6937, 3837, + 7277, 414, + 7305, 2665, + 7466, 11304, + 7942, 794, + 8007, 1982, + 8007, 1366, + 8326, 3105, + 8336, 4810, + 8708, 7954, + 8989, 2279, + 9031, 1055, + 9247, 3568, + 9283, 1631, + 9654, 6311, + 9811, 2605, + 10120, 683, + 10143, 4179, + 10245, 1946, + 10335, 1218, + 10468, 9960, + 10651, 3000, + 10951, 1530, + 10969, 5290, + 11203, 2305, + 11325, 3562, + 11771, 6754, + 11839, 1849, + 11941, 4495, + 11954, 1298, + 11975, 15223, + 11977, 883, + 11986, 2842, + 12438, 2141, + 12593, 3665, + 12636, 8367, + 12658, 1594, + 12886, 2628, + 12984, 4942, + 13146, 1115, + 13224, 524, + 13341, 3163, + 13399, 1923, + 13549, 5961, + 13606, 1401, + 13655, 2399, + 13782, 3909, + 13868, 10923, + 14226, 1723, + 14232, 2939, + 14278, 7528, + 14439, 4598, + 14451, 984, + 14458, 2265, + 14792, 1403, + 14818, 3445, + 14899, 5709, + 15017, 15362, + 15048, 1946, + 15069, 2655, + 15405, 9591, + 15405, 4079, + 15570, 7183, + 15687, 2286, + 15691, 1624, + 15699, 3068, + 15772, 5149, + 15868, 1205, + 15970, 696, + 16249, 3584, + 16338, 1917, + 16424, 2560, + 16483, 4438, + 16529, 6410, + 16620, 11966, + 16839, 8780, + 17030, 3050, + 17033, 18325, + 17092, 1568, + 17123, 5197, + 17351, 2113, + 17374, 980, + 17566, 26214, + 17609, 3912, + 17639, 32767, + 18151, 7871, + 18197, 2516, + 18202, 5649, + 18679, 3283, + 18930, 1370, + 19271, 13757, + 19317, 4120, + 19460, 1973, + 19654, 10018, + 19764, 6792, + 19912, 5135, + 20040, 2841, + 21234, 19833 +}; +/*----------------------------------------------------------------------------------* + * Tables for mode TC + * (tbl_gain_code_tc[i]+(tbl_gain_code_tc[i+1]-tbl_gain_code_tc[i])/2) + *----------------------------------------------------------------------------------*/ +const Word16 tbl_gain_code_tc_quant_mean[N_GAIN_CODE_TC-1] = +{ + 4448, 6927, 8818, 10639, + 12660, 15374, 22136 +}; /* Q13 */ + +const Word16 gain_qua_mless_7b_fx[128*2] = +{ + 419, 28, + 1499, 607, + 1586, 322, + 1632, 144, + 1686, 229, + 1745, 495, + 2182, 409, + 2515, 716, + 2772, 824, + 3069, 1069, + 3211, 936, + 3218, 89, + 3477, 1244, + 3755, 272, + 3865, 549, + 3881, 348, + 4171, 181, + 4414, 627, + 4419, 472, + 4909, 1429, + 5238, 404, + 5241, 1651, + 5721, 85, + 5833, 250, + 5846, 693, + 5897, 325, + 6036, 544, + 6088, 779, + 6459, 1889, + 6650, 157, + 6678, 462, + 6798, 879, + 6922, 993, + 6929, 1130, + 7352, 620, + 7461, 386, + 7864, 232, + 7999, 314, + 8136, 536, + 8398, 712, + 8680, 459, + 8797, 1276, + 9046, 806, + 9198, 86, + 9434, 398, + 9730, 587, + 9735, 267, + 9742, 175, + 9917, 917, + 10042, 509, + 10053, 655, + 10132, 1030, + 10238, 339, + 10694, 1560, + 10817, 447, + 10964, 723, + 11405, 1149, + 11526, 549, + 11582, 386, + 11602, 791, + 11618, 286, + 11883, 862, + 11954, 607, + 12057, 214, + 12104, 496, + 12170, 1397, + 12437, 668, + 12616, 335, + 12668, 952, + 12684, 435, + 12983, 112, + 13235, 742, + 13399, 549, + 13525, 380, + 13527, 270, + 13625, 1044, + 13733, 482, + 13820, 617, + 14036, 817, + 14041, 1257, + 14295, 425, + 14346, 684, + 14367, 319, + 14416, 199, + 14644, 898, + 14944, 518, + 15090, 364, + 15154, 578, + 15309, 462, + 15360, 1933, + 15362, 756, + 15381, 262, + 15566, 1127, + 15699, 639, + 15804, 410, + 16081, 316, + 16161, 993, + 16359, 701, + 16451, 828, + 16500, 543, + 16540, 491, + 16617, 1729, + 16630, 196, + 16749, 369, + 16959, 1530, + 17028, 442, + 17139, 603, + 17369, 898, + 17393, 268, + 17972, 763, + 17985, 1361, + 18016, 333, + 18032, 667, + 18234, 406, + 18270, 105, + 18299, 554, + 18342, 488, + 18747, 1207, + 19027, 1073, + 19530, 216, + 19566, 963, + 19751, 835, + 19794, 615, + 19810, 298, + 19988, 710, + 19990, 449, + 20005, 374, + 20149, 531, +}; +const Word16 gain_qua_mless_6b_fx[64*2] = +{ + 1676, 71, + 2128, 198, + 2318, 491, + 2348, 339, + 2798, 625, + 2893, 785, + 3911, 1099, + 4779, 244, + 4781, 427, + 5115, 935, + 5294, 1509, + 5767, 114, + 6018, 543, + 6152, 335, + 6205, 675, + 6234, 1822, + 6740, 1251, + 7034, 802, + 7782, 434, + 8005, 230, + 9232, 622, + 9337, 336, + 9388, 520, + 9770, 1038, + 9865, 734, + 10224, 879, + 10617, 118, + 10776, 426, + 11518, 249, + 11708, 1399, + 12044, 587, + 12270, 501, + 12277, 348, + 12498, 684, + 13020, 786, + 13097, 1196, + 13530, 422, + 13818, 917, + 14123, 290, + 14500, 1039, + 14538, 636, + 14636, 556, + 14667, 484, + 14931, 362, + 15055, 210, + 15653, 1594, + 15830, 1874, + 15868, 717, + 15897, 828, + 16153, 434, + 16540, 294, + 16874, 608, + 16936, 513, + 17182, 373, + 17644, 1337, + 17696, 126, + 18342, 1122, + 18461, 944, + 18991, 242, + 19114, 795, + 19187, 674, + 19256, 449, + 19485, 557, + 19515, 344, +}; + +const Word16 gain_qua_mless_5b_fx[32*2] = +{ + 2695, 109, + 3444, 271, + 3529, 433, + 4284, 801, + 4365, 607, + 4935, 1089, + 6896, 1407, + 7722, 324, + 7913, 146, + 8090, 468, + 9049, 913, + 9499, 600, + 9894, 741, + 9942, 1840, + 11906, 382, + 12008, 1103, + 12349, 243, + 12429, 501, + 13687, 630, + 13974, 896, + 14510, 748, + 15160, 322, + 15424, 428, + 15679, 541, + 15832, 1574, + 15999, 1281, + 17223, 211, + 17719, 1029, + 18185, 649, + 18432, 818, + 18638, 353, + 18889, 493, +}; + +const Word16 gp_gamma_1sfr_8b_fx[2*256] = /*Q14/Q9 */ +{ + 305, 152, + 333, 37, + 352, 556, + 573, 82, + 652, 12, + 694, 207, + 808, 389, + 915, 776, + 986, 1089, + 987, 1583, + 1055, 60, + 1202, 2779, + 1205, 20, + 1346, 127, + 1432, 332, + 1689, 6554, + 1715, 261, + 1820, 49, + 2041, 698, + 2179, 4032, + 2199, 100, + 2272, 1303, + 2317, 461, + 2340, 175, + 2562, 26, + 2574, 14814, + 2657, 2101, + 2732, 66, + 2818, 9, + 2836, 296, + 2929, 938, + 3479, 130, + 3510, 220, + 3651, 3154, + 3667, 717, + 3720, 384, + 3783, 530, + 3811, 10744, + 3883, 5385, + 3941, 1609, + 3964, 46, + 4120, 80, + 4402, 15, + 4440, 1181, + 4485, 173, + 4740, 311, + 4848, 31, + 5125, 7642, + 5147, 110, + 5167, 908, + 5237, 252, + 5323, 623, + 5376, 2514, + 5590, 7, + 5595, 4475, + 5634, 64, + 5654, 461, + 5822, 22, + 5893, 140, + 5905, 1810, + 6177, 367, + 6268, 201, + 6352, 1092, + 6567, 752, + 6626, 50, + 6734, 95, + 6758, 295, + 6882, 3085, + 6962, 1363, + 7274, 540, + 7413, 166, + 7635, 2120, + 7642, 38, + 7671, 393, + 7730, 227, + 7860, 75, + 7980, 115, + 8011, 955, + 8092, 3687, + 8120, 17, + 8146, 5902, + 8453, 672, + 8524, 1602, + 8583, 58, + 8679, 275, + 8873, 332, + 8920, 454, + 8969, 9712, + 9129, 2566, + 9159, 196, + 9193, 1127, + 9219, 142, + 9300, 9, + 9302, 828, + 9409, 91, + 9736, 26, + 9872, 574, + 10066, 246, + 10131, 1352, + 10154, 1971, + 10196, 399, + 10238, 15785, + 10255, 4254, + 10401, 67, + 10439, 43, + 10511, 116, + 10531, 7399, + 10706, 998, + 10798, 722, + 10845, 171, + 10848, 304, + 10876, 2981, + 11069, 28204, + 11139, 507, + 11280, 12, + 11427, 388, + 11459, 214, + 11647, 1174, + 11710, 5061, + 11742, 1614, + 11793, 806, + 11816, 82, + 11890, 132, + 11996, 2301, + 12000, 603, + 12060, 55, + 12232, 256, + 12299, 33, + 12438, 338, + 12452, 458, + 12627, 3563, + 12646, 9489, + 12665, 934, + 12801, 1329, + 12802, 190, + 12877, 683, + 12941, 103, + 13038, 1890, + 13209, 6209, + 13222, 12674, + 13318, 21, + 13374, 283, + 13385, 149, + 13391, 383, + 13453, 545, + 13564, 1064, + 13596, 2561, + 13771, 810, + 13834, 1481, + 13874, 69, + 14027, 226, + 14093, 4429, + 14147, 7, + 14171, 609, + 14185, 47, + 14223, 3051, + 14273, 434, + 14321, 314, + 14415, 120, + 14443, 1252, + 14500, 173, + 14557, 933, + 14616, 1696, + 14639, 8229, + 14724, 89, + 14837, 703, + 14902, 2072, + 14917, 366, + 15000, 487, + 15009, 30, + 15095, 256, + 15138, 1119, + 15228, 3580, + 15371, 1386, + 15387, 5525, + 15398, 17932, + 15462, 149, + 15471, 791, + 15551, 569, + 15554, 2467, + 15559, 201, + 15616, 14, + 15664, 319, + 15798, 401, + 15811, 974, + 15874, 41, + 15929, 1649, + 15945, 79, + 16046, 111, + 16225, 647, + 16230, 1240, + 16297, 4110, + 16328, 10499, + 16331, 278, + 16355, 3003, + 16383, 455, + 16404, 169, + 16435, 2172, + 16438, 850, + 16745, 7090, + 16776, 354, + 16801, 1063, + 16803, 62, + 16812, 223, + 16927, 530, + 16951, 721, + 17039, 1447, + 17208, 1837, + 17233, 135, + 17371, 4642, + 17570, 406, + 17608, 267, + 17696, 906, + 17702, 2529, + 17705, 23239, + 17709, 1209, + 17745, 592, + 17800, 92, + 17858, 35, + 17860, 3360, + 17866, 9, + 17978, 184, + 18035, 321, + 18255, 754, + 18274, 480, + 18320, 18, + 18406, 55, + 18582, 13017, + 18677, 1516, + 18726, 1998, + 18904, 25, + 18914, 6103, + 19020, 8567, + 19022, 1116, + 19025, 349, + 19147, 239, + 19224, 604, + 19251, 160, + 19270, 4870, + 19358, 3789, + 19394, 126, + 19394, 103, + 19433, 72, + 19444, 46, + 19448, 2842, + 19489, 430, + 19575, 815, + 19628, 1306, + 19631, 972, + 19637, 202, + 19642, 289, + 19660, 527, + 19717, 1697, + 19731, 2263, + 19754, 676, + 19854, 382, +}; + +const Word16 gp_gamma_1sfr_7b_fx[2*128] = /*Q14/Q9 */ +{ + 350, 85, + 428, 24, + 438, 681, + 642, 195, + 1071, 2012, + 1080, 402, + 1148, 1236, + 1159, 62, + 1424, 12, + 1662, 134, + 1985, 299, + 2100, 34, + 2163, 3168, + 2219, 538, + 2393, 6580, + 2499, 967, + 2882, 221, + 2974, 12743, + 3251, 98, + 3294, 51, + 3586, 1560, + 3711, 411, + 3721, 700, + 3862, 21, + 3947, 169, + 4001, 2249, + 4198, 4632, + 4372, 8, + 4993, 70, + 5022, 265, + 5568, 1194, + 5664, 495, + 5698, 115, + 5885, 854, + 6115, 2990, + 6266, 153, + 6376, 39, + 6432, 16, + 6601, 345, + 7108, 1957, + 7231, 660, + 7491, 202, + 7687, 93, + 8054, 3882, + 8108, 9624, + 8186, 1424, + 8243, 59, + 8354, 935, + 8358, 6401, + 8383, 439, + 8794, 285, + 8940, 124, + 9643, 25, + 9643, 581, + 9670, 2709, + 10065, 160, + 10218, 9, + 10240, 1728, + 10249, 80, + 10418, 1113, + 10497, 373, + 10650, 236, + 11095, 44, + 11095, 756, + 11284, 4978, + 11290, 16722, + 11815, 2299, + 11882, 482, + 12059, 114, + 12332, 8550, + 12363, 1394, + 12392, 186, + 12517, 336, + 12549, 3413, + 12694, 953, + 13096, 614, + 13185, 71, + 13247, 262, + 13479, 1914, + 13791, 14, + 13805, 30, + 14064, 138, + 14182, 420, + 14212, 1175, + 14477, 765, + 14605, 2745, + 14612, 6324, + 14730, 4199, + 14833, 301, + 14842, 203, + 14910, 12790, + 15171, 100, + 15191, 1625, + 15289, 532, + 15405, 52, + 15550, 985, + 16096, 357, + 16175, 2113, + 16284, 232, + 16333, 669, + 16363, 22999, + 16396, 156, + 16443, 1270, + 16455, 3482, + 16543, 8, + 16650, 5425, + 16878, 452, + 16989, 84, + 17024, 9676, + 17194, 876, + 17730, 20, + 17780, 1442, + 17864, 38, + 17874, 254, + 17929, 526, + 18011, 2403, + 18751, 7153, + 18786, 117, + 18820, 4420, + 19002, 63, + 19099, 401, + 19111, 183, + 19197, 776, + 19202, 2953, + 19236, 1052, + 19255, 301, + 19354, 1760, + 19432, 593, +}; + +const Word16 gp_gamma_1sfr_6b_fx[2*64] = /*Q14/Q9 */ +{ + 436, 182, + 473, 63, + 962, 16, + 992, 647, + 1258, 1582, + 1447, 351, + 1711, 125, + 1809, 46, + 2569, 4173, + 2607, 957, + 2826, 251, + 2904, 12481, + 3248, 26, + 3594, 2254, + 3664, 78, + 3715, 483, + 4232, 8, + 4681, 188, + 5066, 6623, + 5232, 1273, + 6232, 695, + 6234, 49, + 6238, 113, + 6312, 318, + 7012, 17, + 7327, 3183, + 8008, 1739, + 8692, 446, + 8769, 163, + 8923, 1019, + 9094, 81, + 10358, 286, + 10491, 28, + 10612, 9788, + 10715, 760, + 11045, 4822, + 11319, 2403, + 11684, 56, + 12314, 108, + 12460, 556, + 12580, 9, + 12716, 213, + 12821, 1336, + 14202, 374, + 14325, 16971, + 14612, 838, + 14625, 3285, + 14668, 6231, + 14919, 39, + 15131, 137, + 15476, 1847, + 16056, 255, + 16277, 494, + 16290, 66, + 16582, 1048, + 16859, 17, + 17220, 8723, + 17443, 4295, + 18069, 2499, + 18212, 176, + 18499, 91, + 18517, 1445, + 18522, 332, + 18596, 663, +}; + +const Word16 gp_gamma_2sfr_7b_fx[2*128] = /*Q14/Q9 */ +{ + 99, 1224, + 156, 243, + 168, 579, + 290, 355, + 437, 441, + 475, 187, + 734, 738, + 930, 93, + 1133, 153, + 1136, 298, + 1490, 508, + 1946, 401, + 1978, 16790, + 2098, 224, + 2117, 962, + 2407, 119, + 2686, 339, + 2929, 555, + 3404, 271, + 3465, 171, + 3469, 422, + 3714, 663, + 4436, 494, + 4494, 332, + 4571, 220, + 4583, 2182, + 4997, 848, + 5346, 380, + 5419, 108, + 5570, 579, + 5758, 266, + 5875, 442, + 5927, 170, + 6204, 3338, + 6394, 6435, + 6515, 328, + 6638, 730, + 6687, 1472, + 7045, 1056, + 7101, 498, + 7123, 210, + 7163, 9668, + 7345, 386, + 7598, 280, + 7853, 627, + 8462, 442, + 8648, 331, + 8822, 236, + 8887, 551, + 8953, 906, + 9317, 136, + 9587, 386, + 9651, 691, + 9796, 286, + 9852, 489, + 10005, 1215, + 10041, 192, + 10623, 576, + 10758, 329, + 10840, 425, + 10944, 792, + 11038, 257, + 11190, 1870, + 11541, 501, + 11729, 642, + 11873, 367, + 12064, 163, + 12332, 216, + 12339, 1100, + 12339, 295, + 12478, 444, + 12561, 568, + 12665, 845, + 13257, 396, + 13317, 677, + 13411, 511, + 13709, 324, + 13710, 1547, + 13711, 246, + 14054, 991, + 14112, 447, + 14246, 580, + 14355, 748, + 14394, 175, + 14453, 99, + 14604, 363, + 14887, 491, + 15074, 282, + 15110, 637, + 15242, 1292, + 15351, 413, + 15430, 843, + 15700, 541, + 15776, 204, + 15964, 335, + 15992, 688, + 16077, 453, + 16315, 4617, + 16406, 1032, + 16549, 595, + 16666, 384, + 16850, 776, + 16851, 482, + 16916, 253, + 17234, 309, + 17307, 2128, + 17469, 546, + 17666, 643, + 17699, 421, + 17852, 882, + 17870, 146, + 18146, 1244, + 18457, 489, + 18478, 346, + 18588, 723, + 18826, 208, + 19011, 1731, + 19042, 586, + 19286, 281, + 19428, 944, + 19446, 382, + 19555, 444, + 19689, 792, + 19755, 1111, + 19762, 527, + 19769, 1405, + 19774, 657, + 19780, 2675, +}; + +const Word16 gp_gamma_2sfr_6b_fx[2*64] = /*Q14/Q9 */ +{ + 185, 306, + 435, 519, + 458, 145, + 1000, 211, + 1217, 394, + 1241, 751, + 1788, 93, + 2026, 1234, + 2162, 265, + 2397, 158, + 2617, 472, + 3324, 340, + 3391, 623, + 3835, 207, + 4503, 17210, + 4628, 407, + 4939, 897, + 5102, 275, + 5300, 120, + 5560, 511, + 6309, 1909, + 6571, 335, + 6770, 205, + 6990, 642, + 7085, 5087, + 7500, 428, + 8357, 827, + 8452, 261, + 9079, 537, + 9289, 354, + 9854, 1176, + 9864, 165, + 10436, 8580, + 10549, 437, + 10615, 677, + 11010, 282, + 11940, 530, + 12183, 367, + 12475, 920, + 12865, 225, + 13359, 618, + 13431, 441, + 13521, 1623, + 14177, 341, + 14299, 130, + 14452, 775, + 14799, 508, + 15250, 276, + 15715, 1130, + 15757, 660, + 15879, 422, + 16355, 3256, + 16439, 187, + 16751, 562, + 16906, 331, + 17178, 827, + 17889, 471, + 18219, 2175, + 18786, 248, + 18985, 1354, + 19067, 703, + 19220, 384, + 19349, 954, + 19422, 553, +}; +const Word16 gp_gamma_3sfr_6b_fx[2*64] = /*Q14/Q9 */ +{ + 195, 150, + 817, 288, + 1152, 616, + 1366, 188, + 1377, 410, + 1526, 902, + 1570, 98, + 2258, 238, + 2489, 518, + 2935, 338, + 3142, 161, + 3456, 1705, + 3990, 432, + 4159, 709, + 4187, 270, + 4374, 1236, + 5283, 526, + 5431, 131, + 5507, 356, + 5762, 211, + 6792, 620, + 6842, 446, + 6969, 304, + 7671, 807, + 8362, 245, + 8448, 530, + 8610, 380, + 9314, 1088, + 9828, 170, + 9921, 7010, + 10026, 459, + 10193, 312, + 10261, 658, + 11554, 394, + 11739, 882, + 11791, 542, + 11985, 4329, + 11996, 246, + 12762, 13441, + 12844, 1512, + 13131, 465, + 13135, 339, + 13215, 740, + 14138, 608, + 14524, 417, + 14780, 1030, + 14823, 283, + 15016, 171, + 15264, 527, + 15823, 2706, + 15943, 699, + 15959, 360, + 16350, 473, + 17211, 573, + 17366, 901, + 17517, 238, + 17799, 414, + 18069, 1415, + 18630, 1920, + 18887, 634, + 19018, 318, + 19304, 495, + 19400, 1114, + 19413, 767, +}; + + +const Word16 gp_gamma_4sfr_6b_fx[2*64] = /*Q14/Q9 */ +{ + 153, 141, + 282, 501, + 399, 239, + 783, 369, + 1110, 744, + 1430, 183, + 1440, 1748, + 1524, 1091, + 1602, 296, + 1828, 99, + 2000, 439, + 2678, 228, + 2815, 600, + 3084, 347, + 3861, 477, + 4154, 163, + 4214, 285, + 4428, 733, + 4976, 384, + 5482, 566, + 5552, 234, + 6158, 929, + 6536, 470, + 6560, 326, + 7288, 173, + 7429, 663, + 7447, 10616, + 7871, 407, + 8457, 266, + 8559, 550, + 8679, 1421, + 9457, 356, + 9533, 785, + 9854, 471, + 10584, 5781, + 10792, 3815, + 10813, 206, + 10829, 302, + 10986, 606, + 11380, 433, + 11468, 1073, + 12485, 356, + 12726, 520, + 12783, 721, + 13554, 259, + 13763, 139, + 13884, 430, + 14060, 2592, + 14266, 599, + 14332, 925, + 14997, 337, + 15355, 485, + 15526, 712, + 16440, 587, + 16504, 395, + 16626, 204, + 17228, 1287, + 17563, 805, + 17629, 517, + 18159, 1814, + 18320, 303, + 19228, 437, + 19263, 636, + 19417, 989, +}; + +const Word16 b_1sfr_fx[2] = /*Q12 */ +{ + 9697, -920 +}; +const Word16 b_2sfr_fx[4] = /*Q12 */ +{ + -1, 70, 3763, 542 +}; +const Word16 b_3sfr_fx[6] = +{ + -478, 110, 553, 3264, 92, 730 +}; +const Word16 b_4sfr_fx[8] = +{ + -381, 65, -271, 836, 3246, 34, 143, 650 +}; +/*-------------------------------------------------------------------* + * 1/4 resolution interpolation filter (-3 dB at 0.913*fs/2) + * Used in lib_com_fx\PRED_LT4_FX.C + * Q14 + *-------------------------------------------------------------------*/ +const Word16 inter4_2_fx[] = +{ + 0, 1, 2, 1, + -2, -7, -10, -7, + 4, 19, 28, 22, + -2, -33, -55, -49, + -10, 47, 91, 92, + 38, -52, -133, -153, + -88, 43, 175, 231, + 165, -9, -209, -325, + -275, -60, 226, 431, + 424, 175, -213, -544, + -619, -355, 153, 656, + 871, 626, -16, -762, + -1207, -1044, -249, 853, + 1699, 1749, 780, -923, + -2598, -3267, -2147, 968, + 5531, 10359, 14031, 15401, + 14031, 10359, 5531, 968, + -2147, -3267, -2598, -923, + 780, 1749, 1699, 853, + -249, -1044, -1207, -762, + -16, 626, 871, 656, + 153, -355, -619, -544, + -213, 175, 424, 431, + 226, -60, -275, -325, + -209, -9, 165, 231, + 175, 43, -88, -153, + -133, -52, 38, 92, + 91, 47, -10, -49, + -55, -33, -2, 22, + 28, 19, 4, -7, + -10, -7, -2, 1, + 2, 1, 0, 0 +}; + +const Word16 pwf_fx[17]= +{ + 22938, 16056, 11239, 7868, 5507, 3855, 2699, 1889, + 1322, 926, 648, 454, 317, 222, 156, 109, + 76 +}; + +const Word16 Gamma_29491_Tbl[] = +{ + 29491, 26542, 23888, 21499, 19349, 17414, 15672, 14105, + 12694, 11425, 10282, 9254, 8329, 7496, 6746, 6071 +}; + + +/* Used in 'lsp2lsf_fx.c' */ +const Word8 Ind_Guess[256]= +{ + 126, 122, 120, 119, 117, 116, 115, 114, + 113, 112, 111, 110, 110, 109, 108, 108, + 107, 106, 106, 105, 104, 104, 103, 103, + 102, 102, 101, 101, 100, 100, 99, 99, + 98, 98, 97, 97, 96, 96, 95, 95, + 94, 94, 94, 93, 93, 92, 92, 91, + 91, 91, 90, 90, 89, 89, 89, 88, + 88, 87, 87, 87, 86, 86, 86, 85, + 85, 84, 84, 84, 83, 83, 83, 82, + 82, 82, 81, 81, 81, 80, 80, 80, + 79, 79, 78, 78, 78, 77, 77, 77, + 76, 76, 76, 75, 75, 75, 74, 74, + 74, 73, 73, 73, 72, 72, 72, 72, + 71, 71, 71, 70, 70, 70, 69, 69, + 69, 68, 68, 68, 67, 67, 67, 66, + 66, 66, 65, 65, 65, 64, 64, 64, + 64, 63, 63, 63, 62, 62, 62, 61, + 61, 61, 60, 60, 60, 59, 59, 59, + 58, 58, 58, 57, 57, 57, 56, 56, + 56, 55, 55, 55, 55, 54, 54, 54, + 53, 53, 53, 52, 52, 52, 51, 51, + 51, 50, 50, 50, 49, 49, 49, 48, + 48, 47, 47, 47, 46, 46, 46, 45, + 45, 45, 44, 44, 44, 43, 43, 43, + 42, 42, 41, 41, 41, 40, 40, 40, + 39, 39, 38, 38, 38, 37, 37, 36, + 36, 36, 35, 35, 34, 34, 33, 33, + 33, 32, 32, 31, 31, 30, 30, 29, + 29, 28, 28, 27, 27, 26, 26, 25, + 25, 24, 24, 23, 23, 22, 21, 21, + 20, 19, 19, 18, 17, 17, 16, 15, + 14, 13, 12, 11, 10, 8, 7, 5 +}; +/* Version 101 points */ + + +const Word16 tbl_mid_voi_wb_1b_fx[] = /* Q13*/ +{ + 4551, 4599, 4754, 5035, 4982, 5228, 5318, 5603, 5699, 5652, 5642, 5766, 5825, 5874, 5819, 6056, + 3816, 3355, 2321, 2712, 2900, 2715, 2790, 2508, 2506, 2610, 2617, 2419, 2538, 2622, 3004, 2725, +}; +const Word16 tbl_mid_voi_wb_4b_fx[] = +{ + 4337, 4235, 3526, 4083, 3514, 5457, 3168, 2509, 4418, 5021, 1313, 2952, 5347, 3893, 8325, 11758, + 4180, 4037, 3965, 3481, 4028, 3284, 2644, 4585, 4749, 3076, 3211, 1101, 4175, 7440, 5745, -4105, + 4239, 3957, 4450, 4974, 5400, 5734, 6246, 6586, 7774, 2699, 2783, 3474, 1345, -316, 5069, 4904, + 3964, 3810, 2673, 3031, 2249, 3168, 3155, 4204, 7316, 7176, 8680, 7147, 4918, 4136, 3142, 3011, + 4071, 3853, 3898, 3973, 3464, 2878, 5783, 5341, 1725, 801, 1194, 4239, 6866, 4950, 794, 6270, + 3933, 3750, 4931, 3667, 3585, 2550, 4308, 5757, 4503, 7081, 4893, 1076, 109, 1650, 1887, 8861, + 4803, 4827, 4969, 5511, 5768, 4327, 5277, 4934, 6909, 7672, 5355, 3940, 9990, 9622, 7457, 4202, + 4515, 4259, 2444, 4847, 3728, 4599, 4975, 6144, 4087, 4367, 7025, 5028, 2405, 7014, 13366, 6264, + 4746, 4556, 5408, 5866, 4733, 4088, 3965, 3329, 4669, 3105, 5918, 7824, 6026, 9177, 1856, 13229, + 4130, 4214, 2516, 3542, 4847, 3751, 3704, 2380, 4190, 4787, 4651, 4981, 5702, -27, -2961, 129, + 4461, 4724, 5233, 4680, 6010, 7222, 6351, 3069, 605, 5934, 5627, 3836, 3490, 6060, 3556, 2585, + 4628, 4723, 5465, 4180, 4460, 6173, 5915, 7260, 4703, 4114, 3938, 9585, 8085, 3781, 7520, 625, + 5002, 5621, 6352, 6914, 7170, 7719, 7585, 8408, 8360, 7883, 7370, 7222, 6616, 6002, 5565, 9394, + 4059, 4121, 4178, 4417, 3437, 1460, 1031, 111, 585, 1708, 4219, 5419, 2585, 3195, 6149, 3221, + 3394, 2776, 1970, 2707, 2983, 3931, 3247, 1729, 449, -109, -46, -469, 397, 1980, 2305, 1573, + 3259, 1870, 242, 392, 748, 615, 1185, 1285, 2259, 2687, 2212, 1762, 2174, 1887, 1847, 2073, +}; +const Word16 tbl_mid_voi_wb_5b_fx[] = +{ + 4182, 3820, 4103, 5620, 4100, 4478, 3949, 5053, 2918, 3083, 4229, 3732, 1823, 6350, 17230, 4601, + 4361, 4077, 2236, 4128, 3216, 4673, 6022, 6522, 5746, 4282, 3121, 4448, 6457, 12573, 4401, 7796, + 4228, 4086, 4375, 4320, 4474, 4735, 4427, 5616, 5975, 138, 5887, 3722, 2304, -3430, 4995, 6246, + 4320, 4344, 4008, 4327, 3323, 6835, 3627, 3330, 3123, 3971, 2382, 1801, 6422, 3162, 9038, 14129, + 4193, 4202, 4413, 2703, 4175, 4330, 2615, 7600, 1717, 3506, 5671, 7170, 3545, 2350, -2738, 7287, + 4170, 3912, 4323, 3821, 4450, 6765, 7496, 8107, 7447, 5525, 3088, 1963, 2014, 3330, 976, 1002, + 4583, 4419, 3584, 4125, 4783, 5133, 3188, 5000, 4812, 4639, 10038, 7018, 5114, 5567, 3292, -6364, + 3926, 4092, 2710, 2721, 1799, 3509, 4542, 3351, 4583, 5877, 6539, 5135, 981, 4029, 7221, 592, + 4624, 4567, 4468, 4630, 5710, 5222, 5883, 2562, 8453, 2825, 109, 6491, 1210, 2921, 7292, 7118, + 4245, 4160, 5119, 4356, 5544, 3034, 1507, 4179, 5971, 1949, 3388, 613, 4995, 9019, 6755, -628, + 4905, 4962, 4529, 7025, 4905, 4470, 5063, 3440, 6348, 6102, 4319, 4395, 7515, 6549, -3697, 6513, + 4683, 4592, 5303, 4593, 4171, 5264, 6116, 7434, 4105, 5454, 2544, 8493, 6491, 894, 8983, -2406, + 3632, 3435, 3988, 4195, 3684, 2173, 6735, 4552, -339, 763, 308, 3463, 6123, 2895, 2831, 5715, + 4316, 4111, 2236, 2682, 1058, 544, 2541, 1677, 3549, 2767, 3376, 5901, 6689, 5811, 6617, 3311, + 4487, 4285, 4992, 3656, 5970, 4547, 3975, 5998, 4985, 6614, 4807, 1971, 14937, 4388, 6153, 3352, + 4601, 4710, 4957, 4454, 4873, 7207, 5881, 3461, 2282, 1829, 5617, 9926, 10043, 7722, 3232, 4629, + 3965, 3837, 2088, 4265, 5042, 3478, 4453, 2804, 4162, 4858, 4315, 4343, 5193, -1823, -5028, -1137, + 3439, 2837, 2549, 4062, 2857, 2657, 2662, 5088, 10548, 8913, 6631, 6395, 5568, 3210, 2431, 3400, + 4073, 3839, 5806, 5296, 3766, 2342, 2585, 891, 3144, 2988, 6807, 4626, 3700, 5854, 1543, 16158, + 4189, 4045, 4293, 4527, 4008, 1413, 4871, 6081, 3297, 6546, 5006, -365, -2369, 1375, 5522, 8787, + 4778, 4782, 4941, 4538, 4497, 3129, 4934, 4371, 7175, 6923, 8620, 10236, 8664, 10088, 10923, 7314, + 4945, 5016, 6439, 6353, 6624, 6463, 6938, 7547, 7004, 7283, 7655, 7149, 7650, 2747, 3416, 14892, + 4776, 5431, 5515, 6194, 5700, 5485, 2795, 5476, 4024, 8891, 2930, 7916, 3428, 8070, 5920, 13440, + 4718, 4986, 4800, 5286, 6567, 6554, 6601, 1235, -1216, 6556, 6098, 3962, 4361, 5536, 5517, 3935, + 4741, 4679, 5593, 4891, 3849, 5675, 6487, 6239, 7062, 12044, 10918, 2438, 3977, 7296, 8445, 6625, + 4859, 5781, 6592, 7399, 8027, 8858, 8139, 8951, 8760, 5506, 6294, 6540, 6516, 7527, 7688, 4084, + 4077, 3771, 3650, 3381, 3367, 4048, 3899, 4382, 3017, -2156, -1464, -2207, 828, 4838, 2071, 2363, + 3796, 3437, 3558, 3842, 2170, 4311, 2602, 696, 1939, 2576, 1239, 328, -129, -647, 1702, 2893, + 4015, 3506, 367, 1350, 3328, 3700, 3827, 2439, 1434, 3887, 2279, 1593, 3673, 5508, 3905, -2973, + 4088, 3990, 3732, 3256, 4718, 1375, 152, -99, -254, 1140, 3578, 3316, 2195, 2408, 5027, 999, + 3749, 3175, 1475, 686, 2006, 1959, 1558, 3059, 5374, 5014, 2439, 2396, 2467, 2218, 1031, 7866, + 2037, 701, 124, 278, 328, 253, 660, 528, 826, 473, 801, 800, 1053, 1330, 804, 967, +}; + +const Word16 tbl_mid_unv_wb_4b_fx[] = +{ + 5190, 3143, 50, 2521, 5180, 6320, 3890, 3365, 3582, 3517, 3406, 3049, 2864, 1621, 1932, -950, + 6813, 6650, 2135, 972, 452, 1453, 3221, 1697, 3165, 4443, 5924, 6297, 3907, 2862, 3586, 4625, + 3204, 2673, 6499, 4319, 1054, 559, 4404, 5815, 5072, 6625, 4493, 2479, 1773, 1606, 2099, 8330, + 1924, 2666, 4171, 5517, 5898, 7238, 7318, 7696, 7250, 6269, 6164, 6038, 5249, 4284, 4147, 2828, + 2834, 788, 77, 2016, 1824, 3224, 3441, 4472, 6286, 6717, 6783, 6743, 6715, 7051, 6562, 2531, + 6386, 5634, 5761, 5184, 3523, 4284, 1867, 1045, 579, 1176, 1743, 2599, 5276, 5564, 5368, 7914, + 1795, 1380, 5184, 9326, 8023, 3138, 1258, 1729, 3328, 3934, 5169, 5645, 5271, 5894, 5591, 5145, + 5734, 5844, 8799, 8753, 5628, 5710, 5255, 4872, 5349, 3431, 3006, 2486, 1418, 974, 1115, 2035, + 4194, 8421, 1812, 6078, 3003, 3455, 6719, 7501, 2120, 1892, 2658, 2317, 2296, 5735, 6553, 4485, + 8072, 11456, 6455, 5069, 4918, 4936, 4819, 4932, 6029, 6246, 6289, 6704, 6749, 5337, 4526, 3974, + 3709, 5584, 4884, -1502, 4864, 2333, 606, 5976, 6438, 2413, 1937, 3663, 5593, 6989, 6450, 3555, + 3843, -6887, 3697, 3880, 4448, 4264, 5961, 4198, 3583, 3942, 3606, 3768, 4457, 4374, 4096, 4524, + 2551, 6781, 7017, 2902, 9227, 8728, 7130, 1873, 2308, 4393, 3981, 3976, 4002, 4080, 4820, 5611, + 220, -174, -43, -542, 449, 1470, 1759, 1893, 1294, 995, 723, 723, 769, 994, 1369, 4413, + 1651, 2259, 3079, 2913, 1176, -491, -1262, -827, -217, 908, 1126, 1751, 1901, 1765, 2656, 247, + 5380, 7307, 7727, 8135, 8270, 8471, 8792, 8573, 8335, 8420, 8057, 7562, 7119, 7458, 6806, 7385, +}; +const Word16 tbl_mid_unv_wb_5b_fx[] = +{ + 6237, 6323, 1151, 763, 4218, 6546, 8437, 8701, 7456, 6604, 4631, 2901, 3050, 1793, 1955, 2260, + 5542, 4318, 5343, 5521, 5999, 5477, 5265, 5234, 4616, 3329, 3444, 1816, -442, 45, -2, 8922, + 6370, 8208, 6583, 5630, 5401, 5458, 5188, 5595, 6637, 6891, 6962, 6967, 7014, 6330, 5445, 3101, + 2750, 2858, 5206, 4594, 3310, 3494, 2463, 3410, 3405, 6151, 7682, 8593, 4440, 3715, 2946, -4371, + 1157, 661, 3743, 6418, 7515, 8319, 7485, 7298, 7928, 7515, 6812, 5671, 5095, 5122, 4997, 3940, + 5133, 3446, 2693, 1620, 1860, 2663, 4603, 6289, 7451, 7255, 7511, 7486, 8869, 8704, 8431, 6632, + 2497, 6706, 7036, 3437, 10854, 8893, 6033, 3021, 2936, 4766, 4145, 4097, 5177, 4883, 5920, 7612, + -152, -54, 3955, 1170, 5562, 4695, 1370, 8293, 3106, 1942, 5508, 4878, 3495, 1094, 1079, 5401, + 482, 373, 220, -355, -236, -328, -426, -147, 244, 563, 567, 915, 1012, 676, 804, 2721, + 437, 816, 3208, 3395, 2501, 3795, 4380, 2553, 399, 31, -519, -475, -162, 1755, 2852, 1040, + 2067, 2125, 1247, 2393, 2872, 2218, 3502, 3977, 4712, 4275, 2600, 2380, 2314, 2893, 3555, 13929, + 3967, -635, -1752, 2490, 303, 969, 1045, 2839, 5670, 4651, 5202, 5248, 4182, 4381, 5492, 53, + 3041, 2494, 9264, 4970, 360, -3795, 6296, 6475, 4482, 6667, 5265, 2908, 2381, 2889, 3718, 5160, + 3364, 4119, 5929, 3164, -745, 9368, 1652, -719, 6323, 5113, 1919, 1260, 2630, 3585, 2224, 3178, + 1643, 837, 8074, 8337, 4237, 2332, 2190, -1176, 1968, 1238, 2354, 4756, 5269, 5759, 4962, 5411, + 7590, 6471, 2635, 1869, 1209, 1505, 2118, 892, 1652, 3717, 5010, 3969, 2265, 2428, 3278, 5027, + 7289, 8658, 11183, 8913, 6084, 6673, 5961, 4041, 3839, 2643, 2094, 3215, 2956, 2895, 3327, 5063, + 5814, -4982, 1120, 2112, 4384, 5288, 6052, 4305, 4724, 5062, 3380, 4200, 5838, 7181, 6383, 4771, + 3891, 7361, 4160, 1422, 4971, 939, 281, 3585, 4817, 1176, -306, 260, 3815, 8273, 7095, 1529, + 8179, 19416, 3518, 3547, 4619, 4231, 3359, 3606, 5131, 4469, 5204, 5115, 4941, 4772, 4175, 5160, + 4539, 5393, 2706, 5371, 1468, 8488, 10356, 2778, 1426, 371, 8093, 7808, 5208, 5996, 6081, 5057, + 3266, 3481, -4953, -5638, 4022, 5502, 3586, 3117, 2737, 3826, 3658, 3933, 3602, 4920, 4959, 3483, + 3846, 9592, 3360, 6480, 1215, 3170, 5218, 8641, 664, 2695, 3353, 1479, 1687, 6049, 7074, 4696, + 2231, 4497, 6761, 6799, 5941, 5445, 8083, 7944, 5879, 3744, 2518, 6482, 6581, 6096, 6379, -133, + 3360, 6078, 1064, 13807, 8185, 3605, 4327, 3777, 6211, 4977, 5015, 4871, 5825, 2506, 2130, 4946, + 5412, 4507, 952, 4098, 5027, 3949, 3501, 1778, 1955, 2126, 1626, 3669, 4446, -1101, 736, -2708, + 4824, 7481, 8884, -2619, -2754, 281, 4158, 3251, 4602, 2946, 3915, 6169, 6075, 3495, 3266, 4375, + 6135, 2668, 6784, 10326, 6892, 5479, 1511, 3070, 6410, 9193, 6954, 1084, 2873, 7030, 8139, 5670, + 7255, 5764, 5122, 5787, 3129, 5475, -2720, 3770, -827, 872, 1591, 4645, 7218, 5513, 5778, 6323, + 1185, -13100, 5560, 5867, 4153, 2591, 4923, 3450, 2062, 4251, 4289, 3397, 3835, 2082, 2343, 3172, + 4460, 4411, 3940, 4420, 9410, -2789, -2525, -2877, -1868, 2850, 4490, 4093, 3162, 3889, 3800, 3492, + 6408, 8292, 8434, 8544, 8707, 9146, 9377, 9301, 9063, 8945, 8346, 8173, 7175, 7254, 6120, 7420, +}; +const Word16 tbl_mid_gen_wb_2b_fx[] = +{ + 3814, 5145, 5856, 5290, 5277, 4880, 4877, 4273, 3868, 3776, 3392, 3163, 3120, 3019, 3395, 5814, + 1482, 861, 1968, 3198, 3105, 3737, 3749, 4525, 4982, 4828, 5023, 5335, 5327, 5296, 5092, 3444, + 3955, 3851, 1520, 1666, 1554, 1385, 1537, 1276, 1443, 1526, 1597, 1636, 1867, 2041, 2483, 2059, + 7038, 8112, 7324, 6969, 6877, 7028, 6987, 7098, 7003, 6955, 6927, 6808, 6685, 6459, 5871, 6047, +}; + + +const Word16 tbl_mid_gen_wb_5b_fx[] = +{ + 6510, 8058, 7103, 6095, 6483, 5866, 6026, 6443, 6882, 6907, 7015, 6581, 5649, 4044, 2816, 2519, + 3778, 2123, 3580, 4221, 2598, 4631, 2844, 4905, 5446, 4529, 5186, 6228, 6210, 5693, 6213, -4670, + 9050, 9934, 8441, 7921, 7546, 7840, 7977, 8335, 8679, 8706, 8703, 8607, 8560, 8375, 7759, 6405, + 4243, 5775, 2939, 5887, 4078, 3117, 5267, 5680, 4589, 2401, 731, 1011, 1657, 4733, 7051, 3992, + 2508, 3156, 3347, 1605, 4450, 4633, 3476, 6019, 4083, 3824, 5133, 6020, 3253, 1368, 1736, 13507, + 5934, 6372, 4494, 2957, 4424, 6667, 8167, 8413, 7957, 7139, 5518, 3059, 2829, 2821, 2773, 3274, + 4984, 5566, 5831, 4556, 5732, 6738, 6689, 4683, 2265, 4214, 7242, 9989, 9776, 9068, 4748, 2292, + 2601, 4933, 2764, 4923, 3763, 3678, 5596, 2079, 6108, 6824, 5507, 5612, 6793, 5553, 1140, 9993, + 7084, 6685, 5313, 5196, 3111, 5337, 3535, 2476, 2477, 1737, 2090, 4033, 5680, 6548, 7310, 11811, + 8140, 8602, 7166, 6738, 6018, 5299, 5686, 4722, 4108, 4456, 3713, 3131, 2658, 2336, 2250, 8051, + 727, 1865, 6073, 3932, 2258, 2413, 4823, 5733, 5101, 6126, 4690, 1130, 1172, 1479, 3956, 7204, + 6042, 1024, 5371, 5997, 4964, 5575, 5078, 5843, 6909, 8465, 8601, 6137, 5699, 8049, 9922, 8318, + 2728, 1625, 4750, 5004, 5799, 4938, 6353, 3274, 1781, 3095, 1479, 3136, 5470, 1391, -626, 2422, + 4407, 3228, 1266, 1488, 1222, 963, 1148, 1182, 1330, 1770, 860, 381, 813, 1268, 2352, 3956, + 1683, -120, 83, 1239, 946, 1609, 1982, 3215, 3950, 4200, 4497, 4898, 4551, 3595, 2345, 2444, + 1055, 3207, 7460, 6808, 7103, 6980, 7902, 8196, 6821, 6190, 6405, 7414, 7967, 7506, 6921, 9871, + 3164, 7995, 8446, 8770, 8443, 8302, 7372, 7049, 6090, 5698, 5090, 4792, 4996, 4874, 4285, 6685, + 3681, 319, 536, 3174, 4495, 5486, 5807, 5751, 5461, 4423, 3556, 3449, 5148, 7560, 6277, 3783, + 1987, 4209, 6954, 5880, 7459, 7762, 4326, 4958, 5154, 2150, 2988, 2469, 1175, 1099, 3999, 3950, + 1306, 2303, 7748, 8238, 6116, 2824, 1772, 1130, 2538, 3345, 5317, 4773, 3668, 5458, 5519, 5594, + 4140, 4329, 3339, 3001, 2669, -79, -582, -1729, -680, 1294, 2752, 3700, 3627, 4428, 4950, 2744, + 5309, 3611, 993, 3526, 2043, 3938, 2069, 1434, 4173, 2609, 2704, 3690, 3686, 1894, 1401, -1682, + 6091, 4810, 970, 1063, 1707, 3056, 4597, 6742, 7397, 6913, 7359, 7884, 7571, 6830, 6039, 3823, + 6599, 6006, 1248, 4330, 6935, 3784, 3535, 3902, 3221, 5384, 5691, 5997, 5975, 6731, 9125, 5385, + 204, 242, 2009, 3375, 3412, 3407, 2691, 2547, 598, -150, 67, 250, 618, 1185, 1987, 1157, + 4986, 7977, 6971, 1528, 86, 281, 1497, 3002, 4193, 4430, 4721, 5317, 6001, 6181, 6962, 5480, + 6914, 7963, 5254, 3050, 5365, 3224, 3781, 3044, 2571, 3155, 2243, 1612, 2157, 2526, 2784, -1629, + 7350, 6702, 2435, 1937, 2549, 1978, 2819, 2817, 2059, 2493, 3408, 2344, 1239, 1177, 914, 3763, + 4362, 3105, -1457, -1760, 314, 1452, 2603, 1642, 1670, 1652, 2258, 2492, 3844, 4399, 5213, 660, + 350, 357, 109, 83, -555, -886, -714, -587, -120, 25, 189, 531, 591, 146, 156, 1435, + 498, 211, 3062, 6766, 7150, 8142, 7531, 7527, 7855, 6898, 6613, 6480, 5290, 4310, 5341, 4129, + 2753, 6959, 7088, 4622, 2646, 2395, 1756, 325, 488, 259, -125, -577, -553, 615, 557, 4617, +}; + +const Word16 CBsizes_fx[] = +{ + 1,2,4,8,16,32,64 +}; + +/*----------------------------------------------------------------------------------* + * LSF quantization - LSF mode/codebook selection tables + *----------------------------------------------------------------------------------*/ +const Word16 CB_lsf_fx[] = +{ + -1, /* Mode 0 : INACTIVE NB, Safety net */ + -1, /* Mode 1 : UNVOICED NB, Safety net */ + 0, /* Mode 2 : VOICED NB, Safety net */ + 2, /* Mode 3 : GENERIC NB, Safety net */ + 2, /* Mode 4 : TRANSITION NB, Safety net */ + 4, /* Mode 5 : AUDIO NB, Safety net */ + -1, /* Mode 6 : INACTIVE WB, Safety net */ + -1, /* Mode 7 : UNVOICED WB, Safety net */ + 5, /* Mode 8 : VOICED WB, Safety net */ + 7, /* Mode 9 : GENERIC WB, Safety net */ + 7, /* Mode 10 : TRANSITION WB, Safety net */ + 9, /* Mode 11 : AUDIO WB, Safety net */ + -1, /* Mode 12 : INACTIVE WB16k, Safety net */ + -1, /* Mode 13 : UNVOICED WB16k, Safety net */ + -1, /* Mode 14 : VOICED WB16k, Safety net */ + -1, /* Mode 15 : GENERIC WB 16k, Safety net */ + 10, /* Mode 16 : TRANSITION WB16k, Safety net */ + -1, /* Mode 17 : AUDIO WB16k, Safety net */ + 13 /* Mode 18 : CNG, Safety net */ +}; + +const Word16 CB_p_lsf_fx[] = +{ + 0, /* Mode 0 : INACTIVE NB, Predictive */ + 1, /* Mode 1 : UNVOICED NB, Predictive */ + 4, /* Mode 2 : VOICED NB, Predictive */ + 4, /* Mode 3 : GENERIC NB, Predictive */ + -1, /* Mode 4 : TRANSITION NB, Predictive */ + -1, /* Mode 5 : AUDIO NB, Predictive */ + 0, /* Mode 6 : INACTIVE WB, Predictive */ + 1, /* Mode 7 : UNVOICED WB, Predictive */ + 6, /* Mode 8 : VOICED WB, Predictive */ + 6, /* Mode 9 : GENERIC WB, Predictive */ + -1, /* Mode 10 : TRANSITION WB, Predictive */ + -1, /* Mode 11 : AUDIO WB, Predictive */ + 0, /* Mode 12 : INACTIVE WB16k, Predictive */ + -1, /* Mode 13 : UNVOICED WB16k, Predictive */ + -1, /* Mode 14 : VOICED WB16k, Predictive */ + 8, /* Mode 15 : GENERIC WB16k, Predictive */ + -1, /* Mode 16 : TRANSITION WB16k, Predictive */ + 10, /* Mode 17 : AUDIO WB16k, Predictive */ + 9, /* Mode 18 : GENERIC WB, MA Predictive */ +}; +const Word16 CBbits_fx[] = +{ + -1, /* Mode 0 : INACTIVE NB, Safety net */ + -1, /* Mode 1 : UNVOICED NB, Safety net */ + 4, /* Mode 2 : VOICED NB, Safety net */ + 5, /* Mode 3 : GENERIC NB, Safety net */ + 5, /* Mode 4 : TRANSITION NB, Safety net */ + 4, /* Mode 5 : AUDIO NB, Safety net */ + -1, /* Mode 6 : INACTIVE WB, Safety net */ + -1, /* Mode 7 : UNVOICED WB, Safety net */ + 4, /* Mode 8 : VOICED WB, Safety net */ + 5, /* Mode 9 : GENERIC WB, Safety net */ + 5, /* Mode 10 : TRANSITION WB, Safety net */ + 4, /* Mode 11 : AUDIO WB, Safety net */ + -1, /* Mode 12 : INACTIVE WB16k, Safety net */ + -1, /* Mode 13 : UNVOICED WB16k, Safety net */ + 4, /* Mode 14 : VOICED WB16k, Safety net */ + -1, /* Mode 15 : GENERIC WB16k, Safety net */ + 4, /* Mode 16 : TRANSITION WB16k, Safety net */ + -1, /* Mode 17 : AUDIO WB16k, Safety net */ + 4, /* Mode 18: CNG, Safety net */ +}; + + +const Word16 CBbits_p_fx[] = +{ + 5, /* Mode 0 : INACTIVE NB, Predictive */ + 4, /* Mode 1 : UNVOICED NB, Predictive */ + 3, /* Mode 2 : VOICED NB, Predictive */ + 3, /* Mode 3 : GENERIC NB, Predictive */ + -1, /* Mode 4 : TRANSITION NB, Predictive */ + 0, /* Mode 5 : AUDIO NB, Predictive */ + 5, /* Mode 6 : INACTIVE WB, Predictive */ + 4, /* Mode 7 : UNVOICED WB, Predictive */ + 3, /* Mode 8 : VOICED WB, Predictive */ + 3, /* Mode 9 : GENERIC WB, Predictive */ + -1, /* Mode 10 : TRANSITION WB, Predictive */ + 0, /* Mode 11 : AUDIO WB, Predictive */ + 5, /* Mode 12 : INACTIVE WB16k, Predictive */ + -1, /* Mode 13 : UNVOICED WB16k, Predictive */ + 3, /* Mode 14 : VOICED WB16k, Predictive */ + 5, /* Mode 15 : GENERIC WB16k, Predictive */ + -1, /* Mode 16 : TRANSITION WB16k, Predictive */ + 5, /* Mode 17 : AUDIO WB16k, Predictive */ + 5, /* Mode 9 : GENERIC WB, Predictive */ +}; + + + +const Word16 BitsVQ_fx[]= +{ + -1, /* Mode 0 : INACTIVE NB, Safety net */ + -1, /* Mode 1 : UNVOICED NB, Safety net */ + 8, /* Mode 2 : VOICED NB, Safety net */ + 9, /* Mode 3 : GENERIC NB, Safety net */ + 9, /* Mode 4 : TRANSITION NB, Safety net */ + 4, /* Mode 5 : AUDIO NB, Safety net */ + -1, /* Mode 6 : INACTIVE WB, Safety net */ + -1, /* Mode 7 : UNVOICED WB, Safety net */ + 8, /* Mode 8 : VOICED WB, Safety net */ + 9, /* Mode 9 : GENERIC WB, Safety net */ + 9, /* Mode 10 : TRANSITION WB, Safety net */ + 4, /* Mode 11 : AUDIO WB, Safety net */ + -1, /* Mode 12 : INACTIVE WB16k, Safety net */ + -1, /* Mode 13 : UNVOICED WB16k, Safety net */ + 8, /* Mode 14 : VOICED WB16k, Safety net */ + -1, /* Mode 15 : GENERIC WB16k, Safety net */ + 8, /* Mode 16 : TRANSITION WB16k, Safety net */ + -1, /* Mode 17 : AUDIO WB16k, Safety net */ + 4, /* Mode 18: CNG, Safety net */ +}; + + +const Word16 BitsVQ_p_fx[]= +{ + 5, /* Mode 0 : INACTIVE NB, Predictive */ + 8, /* Mode 1 : UNVOICED NB, Predictive */ + 6, /* Mode 2 : VOICED NB, Predictive */ + 6, /* Mode 3 : GENERIC NB, Predictive */ + -1, /* Mode 4 : TRANSITION NB, Predictive */ + 0, /* Mode 5 : AUDIO NB, Predictive */ + 5, /* Mode 6 : INACTIVE WB, Predictive */ + 12, /* Mode 7 : UNVOICED WB, Predictive */ + 6, /* Mode 8 : VOICED WB, Predictive */ + 6, /* Mode 9 : GENERIC WB, Predictive */ + -1, /* Mode 10 : TRANSITION WB, Predictive */ + 0, /* Mode 11 : AUDIO WB, Predictive */ + 5, /* Mode 12 : INACTIVE WB16k, Predictive */ + -1, /* Mode 13 : UNVOICED WB16k, Predictive */ + 6, /* Mode 14 : VOICED WB16k, Predictive */ + 5, /* Mode 15 : GENERIC WB16k, Predictive */ + -1, /* Mode 16 : TRANSITION WB16k, Predictive */ + 5, /* Mode 17 : AUDIO WB16k, Predictive */ + 5, /* Mode 18 : GENERIC WB, MA Predictive */ +}; + + +const Word16 predmode_tab[][6] = +{ + {1,1,2,2,0,2}, + {1,1,2,2,0,2}, + {1,-1,2,1,0,1}, + {1,1,2,1,0,2} /* should check how is the cb for audio mode at 13.2*/ +}; + +/* Stable ISP vector in Q15 */ +const Word16 stable_ISP_fx[16] = { 32139, 30274, 27247, 23170, 18206, 12540, 6393, 0, -6390, -12537, -18203, -23170, -27243, -30271, -32139, 1475 }; +/* Stable LSP vector in Q15 */ +/* This LSP corresponds to GEWB_Ave_fx */ +const Word16 stable_LSP_fx[16] = {32437, 31676, 29486, 25681, 21564, 16413, 10838, 5385, -735, -6405, -11986, -17040, -22052, -26346, -29678, -31784}; +/* Length 16 vector in Scale = 2.56f */ +const Word16 SVWB2_Ave_fx[16] = {998, 1488, 2682, 3823, 5084, 6305, 7485, 8686, 9861, 11004, 12339, 13664, 15088, 16330, 17663, 18754 }; +/* An 16-by-1 matrix */ +const Word16 IANB_Ave_fx[16] = +{ + 726, 1433, 2493, 3408, 4340, 5215, 6103, 6947, 7772, 8536, 9252, 10012, 10909, 12427, 13997, 15193 +}; +/* An 16-by-1 matrix */ +const Word16 IAWB_Ave_fx[16] = +{ + 577, 1350, 2526, 3535, 4539, 5504, 6497, 7460, 8445, 9396, 10371, 11319, 12307, 13268, 14249, 15207 +}; +/* An 16-by-1 matrix */ +const Word16 IAWB2_Ave_fx[16] = +{ + 731, 1777, 3194, 4386, 5629, 6806, 8012, 9164, 10329, 11469, 12731, 14037, 15326, 16538, 17801, 18927 +}; +/* Length 16 vector in Scale = 2.56f */ +const Word16 UVNB_Ave_fx[16] = {1018, 1764, 2856, 3751, 4611, 5410, 6233, 6961, 7685, 8304, 8859, 9325, 9977, 11741, 13699, 15074 }; +/* Length 16 vector in Scale = 2.56f */ +const Word16 UVWB_Ave_fx[16] = {898, 1900, 3172, 4190, 5181, 6161, 7134, 8066, 8995, 9888, 10784, 11636, 12527, 13396, 14301, 15183 }; +/* Length 16 vector in Scale = 2.56f */ +const Word16 SVNB_Ave_fx[16] = {890, 1268, 1930, 2902, 3938, 4823, 5832, 6644, 7487, 8202, 8906, 9545, 10788, 12565, 13959, 15183 }; +/* Length 16 vector in Scale = 2.56f */ +const Word16 SVWB_Ave_fx[16] = {832, 1248, 1949, 3083, 4131, 5117, 6179, 7067, 8008, 8922, 9875, 10741, 11785, 12860, 13968, 15048 }; +/* Length 16 vector in Scale = 2.56f */ +const Word16 GEWB_Ave_fx[16] = {742, 1350, 2354, 3495, 4446, 5456, 6434, 7331, 8309, 9218, 10145, 11044, 12042, 13063, 14101, 15103 }; +/* Length 16 vector in Scale = 2.56f */ +const Word16 GEWB2_Ave_fx[16] = {909, 1783, 3227, 4443, 5685, 6851, 7996, 9116, 10213, 11263, 12465, 13754, 15090, 16293, 17621, 18695 }; +/* Length 16 vector in Scale = 2.56f */ +const Word16 GENB_Ave_fx[16] = {836, 1344, 2257, 3263, 4173, 5031, 5950, 6707, 7514, 8234, 8881, 9439, 10393, 12226, 13855, 15135 }; +/* Length 16 vector in Scale = 2.56f */ +const Word16 TRNB_Ave_fx[16] = {919, 1335, 2106, 3142, 4092, 4938, 5905, 6670, 7490, 8199, 8868, 9444, 10544, 12383, 13900, 15156 }; +/* Length 16 vector in Scale = 2.56f */ +const Word16 TRWB_Ave_fx[16] = {834, 1326, 2151, 3341, 4305, 5299, 6318, 7198, 8167, 9071, 10001, 10867, 11871, 12912, 13986, 15046 }; +/* Length 16 vector in Scale = 2.56f */ +const Word16 TRWB2_Ave_fx[16] = {945, 1546, 2866, 4150, 5342, 6568, 7660, 8809, 9894, 10934, 12170, 13577, 14981, 16280, 17614, 18778 }; +/* Length 16 vector in Scale = 2.56f */ +const Word16 AUNB_Ave_fx[16] = {887, 1443, 2356, 3194, 4105, 4949, 5841, 6635, 7437, 8181, 8867, 9478, 10385, 12182, 13858, 15131 }; +/* Length 16 vector in Scale = 2.56f */ +const Word16 AUWB_Ave_fx[16] = {810, 1468, 2476, 3417, 4396, 5342, 6311, 7215, 8171, 9078, 10030, 10969, 12014, 13075, 14146, 15133 }; +/* Length 16 vector in Scale = 2.56f */ +const Word16 AUWB2_Ave_fx[16] = {933, 1745, 3040, 4157, 5379, 6490, 7646, 8725, 9852, 10930, 12214, 13647, 15062, 16297, 17636, 18768 }; +/* Length 16 vector in Scale = 2.56f */ +const Word16 means_wb_cleanspeech_lsf16k0[16] = {727, 1426, 2582, 3554, 4548, 5481, 6397, 7293, 8170, 9010, 9972, 11003, 12072, 13034, 14097, 14956 }; +/* Length 16 vector in Scale = 2.56f */ +const Word16 means_swb_cleanspeech_lsf25k6[16] = {786, 1840, 2892, 3833, 4778, 5658, 6641, 7662, 8692, 9630, 10603, 11534, 12489, 13387, 14349, 15217 }; +/* Length 16 vector in Scale = 2.56f */ +const Word16 means_swb_cleanspeech_lsf32k0[16] = {757, 1855, 2862, 3798, 4705, 5661, 6742, 7692, 8658, 9577, 10513, 11401, 12358, 13269, 14275, 15149 }; + +/* Length 16 vector in Q = 15 */ +const Word16 Predictor0_fx[16] = {27361, 27361, 27361, 27197, 27197, 27197, 26378, 26460, 26214, 25985, 26460, 26460, 25985, 25723, 25723, 24740 }; +/* Length 16 vector in Q = 15 */ +const Word16 Predictor1_fx[16] = {27034, 27034, 27034, 26640, 26313, 26640, 26640, 26132, 26214, 26214, 26460, 26870, 26870, 26706, 27034, 26640 }; +/* Length 16 vector in Q = 15 */ +const Word16 Predictor2_fx[16] = {24248, 23593, 24510, 24248, 24510, 24019, 24019, 23757, 23757, 24019, 24248, 24248, 23593, 23101, 23593, 23101 }; +/* Length 16 vector in Q = 15 */ +const Word16 Predictor3_fx[16] = {24248, 24248, 24740, 24248, 24510, 23757, 23429, 23101, 22610, 23101, 23593, 24740, 25002, 24740, 25002, 24838 }; +/* Length 16 vector in Q = 15 */ +const Word16 Predictor4_fx[16] = {19005, 18350, 19268, 19005, 19268, 18776, 18776, 18514, 18514, 18776, 19005, 19005, 18350, 17859, 17695, 17203 }; +/* Length 16 vector in Q = 15 */ +const Word16 Predictor5_fx[16] = {23839, 23593, 23593, 23839, 23839, 23593, 23593, 23593, 23839, 24084, 24347, 24576, 24576, 23364, 23364, 23364 }; +/* Length 16 vector in Q = 15 */ +const Word16 Predictor6_fx[16] = {24084, 23839, 24084, 23593, 23593, 22938, 22381, 21791, 21135, 21955, 22381, 24347, 24576, 23593, 24576, 24347 }; +/* Length 16 vector in Q = 15 */ +const Word16 Predictor7_fx[16] = {24347, 24084, 24347, 24347, 24347, 24084, 24347, 24576, 24576, 24740, 25068, 24347, 24084, 23839, 23364, 24740 }; +/* Length 16 vector in Q = 15 */ +const Word16 Predictor8_fx[16] = {24740, 24740, 24740, 24576, 24576, 24576, 24084, 23839, 23593, 23364, 23839, 23839, 23364, 23101, 23101, 22118 }; + +const Word16 *const ModeMeans_fx[] = {IANB_Ave_fx, UVNB_Ave_fx, SVNB_Ave_fx, GENB_Ave_fx, TRNB_Ave_fx, AUNB_Ave_fx, IAWB_Ave_fx, UVWB_Ave_fx, + SVWB_Ave_fx, GEWB_Ave_fx, TRWB_Ave_fx, AUWB_Ave_fx, IAWB2_Ave_fx, NULL, SVWB2_Ave_fx, GEWB2_Ave_fx, TRWB2_Ave_fx, AUWB2_Ave_fx + }; +const Word16 * const Predictors_fx[] = {Predictor6_fx, NULL, Predictor1_fx, Predictor3_fx, NULL, Predictor6_fx,Predictor5_fx, NULL, Predictor0_fx, + Predictor2_fx, NULL, Predictor5_fx, Predictor7_fx, NULL, Predictor8_fx, Predictor4_fx, NULL, Predictor7_fx + }; +/* An 16-by-16 matrix in Scale = 2.56f */ +const Word16 UVD_MA1_fx[256] = +{ + -301, -503, -426, -187, -131, -64, -45, -20, 11, 56, 63, 90, 110, 175, 97, 33, + 161, 353, 474, 502, 709, 782, 794, 765, 632, 532, 406, 285, 230, 145, 97, 52, + -37, -5, 205, 323, 412, 349, 221, 91, -6, -59, -86, -112, -32, 209, 73, 23, + -273, -615, -820, -794, -834, -838, -822, -819, -751, -701, -641, -562, -391, -271, -184, -63, + 262, 168, 104, -9, -78, -163, -141, -199, -191, -249, -245, -317, -168, 535, 109, 33, + -410, -675, -681, -611, -500, -396, -273, -183, -47, 60, 194, 357, 1044, 1080, 335, 140, + 154, 185, 256, 238, 203, 238, 280, 260, 300, 267, 258, 196, 121, -618, -263, -60, + 345, 705, 859, 786, 743, 584, 425, 267, 168, 105, 74, 28, 119, 267, 105, 39, + -39, -166, -230, -196, -255, -276, -318, -349, -387, -438, -539, -613, -752, -956, -1353, -1628, + 498, 479, 414, 231, 98, 5, -18, -41, -60, -78, -91, -96, -81, 72, 30, -8, + 41, 120, 65, 141, 117, 186, 249, 299, 418, 520, 566, 618, 692, 579, 321, 166, + -236, -278, -69, 13, 113, 362, 445, 539, 503, 387, 269, 172, 120, -21, 1, 4, + -103, -46, -137, -132, -108, -97, -67, -37, -8, 41, 82, 107, 43, -605, -189, -56, + -220, -315, -482, -516, -489, -445, -415, -362, -304, -205, -136, -68, -7, 131, 70, 25, + -10, -121, -210, -237, -224, -302, -246, -310, -271, -343, -285, -364, 28, 703, 135, 54, + 118, 50, -67, -166, -349, -416, -442, -446, -439, -420, -382, -319, -245, -209, -140, -82 +}; +/* An 16-by-16 matrix in Scale = 2.56f */ +const Word16 UVD_MA2_fx[256] = +{ + -75, -64, -150, -231, -272, -278, -248, -194, -156, -107, -74, -43, -92, -21, 9, 5, + 393, 275, -12, -156, -208, -215, -162, -132, -115, -109, -94, -85, -104, -10, 5, -1, + -297, -389, -99, -78, -66, -19, -12, 8, 0, -3, -15, -22, -113, -82, -16, 2, + 59, -11, 5, -33, -11, -61, -70, -139, -143, -239, -207, -223, 711, 701, 143, 68, + -195, 406, 222, 49, -6, -23, -6, 9, 0, 13, 26, 49, -44, -129, -18, -7, + 23, -30, -141, 79, -18, -76, -55, -14, 44, 98, 88, 86, -96, -351, -112, -39, + 380, 329, 235, 173, 141, 72, 25, -4, -6, -19, -21, -33, -55, -23, 3, -1, + -81, -210, -284, 158, 396, 290, 163, 59, -25, -22, -10, -6, -46, -32, 9, 5, + 9, 34, -15, 5, 23, -48, -127, -243, -347, -421, -455, -475, -495, -449, -294, -163, + -13, -171, -416, -414, -245, -25, 69, 102, 104, 84, 50, 33, -38, -4, 0, 5, + 50, 118, 68, 37, 147, 319, 371, 355, 291, 204, 130, 81, 21, 46, 36, 22, + -95, -108, 311, 214, -28, -153, -226, -192, -129, -69, -42, -11, -48, -17, 13, 2, + -185, -223, -104, 26, 53, 89, 132, 181, 258, 346, 397, 445, 392, 241, 125, 58, + 83, 33, -9, -81, 40, 99, 56, 8, -51, -85, -106, -124, -196, 5, 5, 0, + 143, 148, 19, -121, -247, -211, -67, 83, 198, 268, 290, 300, 240, 164, 86, 37, + -198, -136, 370, 372, 300, 240, 156, 113, 79, 60, 44, 29, -35, -38, 6, 7 +}; +/* An 16-by-16 matrix in Scale = 2.56f */ +const Word16 UVWB_MA3_fx[256] = +{ + -26, 23, 7, -6, -1, 3, 40, 35, -43, -24, 56, 157, 265, 423, 382, 260, + 61, -300, -130, -101, -8, 106, 108, 114, 88, 43, -2, -33, -56, 67, 29, 13, + -31, 47, 45, -121, 46, 22, 111, 233, -256, -252, -123, -71, -31, 54, 56, 33, + 20, -154, 67, 198, -232, -167, -86, -12, 79, 116, 88, 78, 44, 75, 27, -7, + -14, 153, -166, 21, 107, 64, 233, -223, -147, -27, -1, 43, 61, 70, 50, 18, + 3, -115, -8, 143, 192, 193, -124, -195, -198, -162, -75, 14, 45, 83, 79, 49, + 12, -57, 25, -29, -11, 12, -7, -13, -12, 31, 74, 99, -10, -421, -209, -111, + -25, 115, 119, -19, -117, -164, -203, -237, -206, -169, -110, -41, -11, 15, 1, -7, + -13, 170, -143, -128, -224, -94, 1, 96, 144, 102, 29, 2, -37, 46, 7, -12, + -11, 10, -34, 38, 24, 86, 149, 211, 240, 279, 247, 218, 154, 161, 74, 15, + -24, 64, 110, 125, -24, 123, 161, 166, 177, 18, -112, -116, -141, -117, -113, -91, + -4, -20, -17, -11, -27, 13, -15, -40, -58, -157, -252, -283, -288, -186, -162, -112, + -20, 2, 32, 44, -31, -49, 8, 13, 55, -59, -162, -212, -61, 384, 115, 36, + -4, 42, -75, 92, 268, -203, -125, 10, 52, 121, 72, -43, -109, -47, -66, -76, + -39, 76, 268, -254, -28, 87, 2, 91, 85, 68, 89, 96, 42, 90, 39, 4, + 2, 2, -56, 7, 67, -31, -219, -192, -24, 146, 249, 269, 209, 199, 106, 31 +}; +/* An 16-by-16 matrix in Scale = 2.56f */ +const Word16 SVNB_SN1_fx[256] = +{ + 135, 109, 135, -153, -549, 214, 416, 195, 291, 247, 100, -127, -579, -160, -66, -32, + -107, -150, -274, -149, 642, 594, 338, 183, 81, -31, -14, -150, -387, -40, -44, -18, + 73, 42, 171, 339, 213, 42, -137, -277, -379, -441, -440, -478, 270, 126, -4, 6, + -307, -479, -636, -596, -100, 83, 167, 200, 260, 376, 523, 1051, 1142, 490, 249, 108, + -148, -215, -324, -570, -917, -685, -208, 127, 285, 353, 441, 940, 1100, 458, 229, 100, + 427, 432, 548, 426, 133, 13, -9, -141, -108, -144, -195, -419, -733, -144, -109, -45, + -115, -220, -194, 661, 896, 688, 489, 351, 211, 258, 147, 30, -746, -784, -156, -95, + 16, -48, -88, -430, -798, 36, 204, 68, 174, 162, 20, 61, 627, 266, 102, 48, + -252, -370, -630, -614, 680, 1024, 869, 598, 419, 259, 193, 27, 90, 156, 53, 27, + -48, 33, 26, -227, -556, -766, -391, 231, 413, 282, 226, 89, 194, 187, 44, 30, + -204, -291, -345, -131, 125, 72, 16, -29, -106, -49, -27, 183, 714, 277, 114, 49, + -11, 205, 285, 69, -58, -207, -301, -160, -30, -2, 12, -99, -580, -178, -80, -41, + 120, 189, 281, 427, 234, 138, 124, 126, 50, 205, 121, 76, -797, -1204, -235, -133, + 63, -18, 146, 666, 480, 236, 134, -39, -97, -130, -175, -378, -746, -159, -106, -46, + 386, 399, 415, 157, -175, -282, -315, -318, -222, -225, -267, -342, 317, 152, 15, 14, + 39, 56, 71, -95, -387, -509, -595, -466, -395, -186, -24, 421, 814, 292, 127, 52 +}; +/* An 16-by-16 matrix in Scale = 2.56f */ +const Word16 SVNB_SN2_fx[256] = +{ + -16, 111, 111, -89, -115, -404, -514, 162, 277, 41, -94, -89, 15, 31, 2, 2, + -82, -99, -25, -287, -464, 204, 18, -123, -38, 56, 109, 198, 160, 96, 41, 19, + -95, -62, -242, -415, 318, 118, -121, 44, 74, 40, 85, 114, 52, 36, 21, 8, + 29, 40, 43, 23, -202, -149, 288, 149, -20, -109, -186, -275, -127, 18, -25, -6, + 20, 36, -97, -228, 565, 508, 134, 42, -70, -237, -258, -259, -123, -9, -29, -10, + -72, -169, 492, 463, 193, 204, -13, -75, -82, -125, -181, -230, -181, -10, -40, -12, + -108, -221, -229, 648, 575, 288, 146, 1, -14, -4, -51, -120, -81, -14, -17, -5, + -199, -264, -309, 209, 8, -128, 24, -47, 87, 257, 240, 185, 93, 70, 34, 16, + 25, 82, -60, -155, -407, -615, 29, 100, -113, 32, 207, 258, 203, 111, 49, 21, + 37, 127, 95, 4, 112, -45, -217, -158, -277, -407, -304, -152, 72, 52, -6, 0, + -30, -81, -116, -416, -219, 677, 538, 328, 213, 60, -60, -109, -78, 0, -5, 0, + 9, -15, 26, 75, -175, -336, -673, -586, 238, 310, 198, 189, 212, 126, 48, 24, + -18, -4, -80, 102, 130, -116, -268, -471, -567, -104, 205, 221, 143, 81, 29, 12, + 4, 39, 65, 115, 88, 189, 136, 124, 49, 106, 37, 89, -375, -626, -114, -73, + 540, 525, 472, 221, 118, -31, 15, 7, -71, -139, -108, -93, -13, -4, -13, -8, + -44, -44, -143, -272, -525, -365, 479, 502, 312, 225, 161, 72, 28, 42, 26, 12 +}; +/* An 16-by-16 matrix in Scale = 2.56f */ +const Word16 SVWB_SN1_fx[256] = +{ + -71, -61, -170, -563, -962, -845, 186, 421, 282, 344, 260, 155, 186, 52, -18, -11, + -107, -139, -289, -270, 788, 615, 249, 174, -1, -24, 159, 106, -46, -183, -187, -107, + -144, -221, -215, 359, 192, -34, -186, -326, -256, -124, -49, 84, 214, 237, 186, 91, + 218, 332, 335, 41, -191, -394, -614, -543, -415, -379, -285, -153, -86, -101, -69, -13, + 587, 616, 732, 419, 270, 252, 102, 40, 53, -35, -57, -34, 19, -14, -15, -120, + -76, -222, -127, 1216, 1188, 815, 532, 320, 311, 228, 34, -59, -96, -86, -44, -38, + -176, -282, -507, -455, 1122, 1359, 965, 742, 610, 448, 474, 412, 185, 127, 127, -24, + -156, -225, 16, 458, 423, 438, 393, 400, 525, 658, 682, 681, 612, 438, 267, 68, + 89, 120, 172, 355, 195, -8, -22, -67, -110, -40, -93, -163, -382, -685, -926, -468, + -227, -362, -452, -577, -213, -22, 56, 82, 132, 216, 348, 420, 358, 299, 257, 143, + 38, -77, 117, 856, 486, 282, 16, -154, -130, -315, -618, -783, -892, -545, -88, 59, + 218, 324, 232, -162, -583, -552, 126, 62, -40, -27, -227, -348, -334, -324, -238, -65, + 82, 16, -20, -539, -787, 604, 340, 259, 260, -53, -251, -211, -12, 127, 171, 99, + -24, 168, 202, -142, -223, -448, -282, 122, 148, 155, 363, 380, 347, 263, 124, -68, + 165, 150, 226, 95, -172, -257, -413, -510, -533, -734, -1014, -1206, -834, -162, 6, 97, + -78, -72, -81, -322, -605, -731, -740, -564, -356, -219, -151, 11, 200, 237, 212, 170 +}; +/* An 16-by-16 matrix in Scale = 2.56f */ +const Word16 SVWB_SN2_fx[256] = +{ + -126, -152, -342, -423, 311, 95, 3, 29, -93, 4, 227, 193, 142, 120, 93, 62, + 190, 258, 382, 310, 166, -11, -77, -67, -217, -327, -330, -378, -461, -309, -142, -47, + -16, -58, -77, -339, -534, 469, 399, 237, 290, 135, 34, 86, -14, -77, -30, 10, + 13, -4, 644, 572, 412, 438, 272, 286, 234, 177, 118, 147, 131, 138, 127, 38, + -73, -88, -112, 42, 36, 141, 424, 386, 504, 576, 523, 483, 431, 328, 233, 59, + -120, -169, -270, -445, -593, -268, -133, -138, -11, 56, 133, 210, 166, 116, 122, 137, + 282, 370, 255, 76, -89, -191, 139, 80, 12, 176, 185, 145, 244, 253, 173, -18, + 13, 14, -43, 73, -59, -270, -448, -622, -59, 374, 353, 293, 189, -54, -199, -122, + -75, -106, -281, -312, 585, 405, 185, 62, -176, -319, -330, -400, -418, -162, -4, 78, + -31, -11, -79, -83, -88, -274, -343, -431, -623, -518, -148, -11, -17, -21, 21, 90, + -101, -173, -240, 444, 303, 121, 104, -37, 185, 134, -45, -136, -164, 4, 153, 114, + -8, 40, 107, -76, -254, -551, -673, 288, 318, 25, 14, -62, -97, -2, 13, -20, + 87, 127, 80, 216, 336, 147, 188, 165, -10, 125, 193, 87, -126, -396, -736, -669, + 2, 4, 96, 185, 6, 62, -37, -136, -177, -250, -227, 201, 744, 651, 351, 74, + -16, -39, -82, -177, -380, -183, -24, -109, -194, -407, -641, -615, -157, 146, 191, 167, + -21, -12, -39, -63, -159, -128, 20, 6, 16, 39, -60, -243, -594, -733, -364, 46 +}; + +/* An 16-by-32 matrix in Scale = 2.56f */ +const Word16 GEWB_MA1_fx[512] = +{ + 269, 268, 416, 287, 157, 7, -132, -276, -482, -701, -1025, -1350, -1642, -982, -321, -49, + 237, 949, 1374, 1228, 1337, 1219, 1123, 1016, 852, 752, 664, 559, 448, 306, 194, 83, + -6, -176, -373, -111, -221, -387, -483, -639, -753, -786, -774, -655, -328, -114, -25, 27, + 135, 164, -4, -181, -364, -528, -464, -424, -393, -314, -242, -185, -104, -61, -32, -37, + 15, -218, -322, 668, 597, 343, 196, -5, -46, -159, -359, -524, -629, -548, -308, -95, + 242, 463, 767, 661, 558, 403, 268, 191, 71, -4, -51, -103, -141, -176, -161, -142, + -179, -147, 715, 865, 970, 932, 822, 763, 602, 514, 436, 370, 285, 189, 106, 36, + -49, -227, -589, -933, -1172, -700, -248, -175, -132, -132, -125, -103, -47, -49, -12, 60, + -7, -227, -404, 272, 83, -50, -165, -319, -343, -501, -731, -939, -1013, -607, -202, -2, + -76, -271, -661, -582, 296, 86, -60, -166, -335, -314, -213, -285, -324, -280, -164, -39, + -264, -452, -111, 171, 229, 357, 355, 461, 509, 517, 489, 441, 347, 246, 158, 75, + 67, -49, -340, -546, -758, -919, -876, -727, -658, -567, -492, -400, -234, -140, -63, 36, + -142, 94, 514, 400, 406, 389, 379, 413, 391, 377, 354, 314, 245, 156, 94, 34, + 97, -47, -316, -620, -874, -179, -206, -290, -304, -514, -690, -723, -503, -252, -73, 39, + 485, 674, 532, 195, 38, -60, 17, 52, 63, 74, 85, 62, 35, -10, -22, -51, + -105, -23, 287, 394, 469, 609, 706, 860, 933, 933, 874, 789, 638, 465, 297, 148, + -223, -499, -837, -813, -391, -231, -178, -182, -81, 2, 84, 113, 131, 142, 127, 107, + -64, 269, 879, 849, 1013, 1157, 1250, 1337, 1263, 1176, 1048, 900, 703, 502, 318, 165, + 61, 1, -198, -209, -345, -417, -280, -280, -307, -272, -341, -418, -604, -738, -887, -394, + 45, 77, 124, 152, 99, 43, 20, -4, -91, -85, -192, -280, -544, -754, -1176, -1296, + 173, 69, -49, -226, -344, -479, -489, -618, -727, -909, -1122, -1446, -1292, -492, -205, 10, + -80, -80, 338, 285, 123, 48, -76, -80, -105, -118, -108, -80, -58, -28, -9, -8, + 74, -79, -292, -618, -756, 345, 216, 180, 143, -73, -186, -223, -200, -143, -52, -21, + -253, -519, -578, -188, -96, -35, -7, 27, 133, 218, 258, 258, 231, 180, 120, 70, + 273, 740, 950, 736, 701, 635, 611, 602, 566, 533, 494, 447, 350, 230, 131, 42, + -100, -345, -702, -352, 709, 682, 485, 324, 161, 112, 148, 25, -88, -106, -86, -101, + 307, 265, 253, 65, -63, -75, -169, -282, -390, -501, -550, -532, -406, -296, -186, -132, + -26, 70, 50, -84, -89, 28, 106, 199, 305, 391, 450, 469, 419, 301, 191, 80, + 22, 39, -154, -426, -597, -497, -159, -69, 41, 95, 114, 114, 99, 33, -7, -40, + -162, -356, -511, -461, -475, -513, -477, -485, -395, -249, -136, -71, -4, 33, 54, 64, + -82, -295, -562, 241, 65, -163, -227, -384, -237, -229, -266, -223, -94, 10, 41, 31, + -104, -323, -302, 733, 646, 418, 271, 149, 155, 154, 119, 99, 89, 63, 13, -16 +}; +/* An 16-by-32 matrix in Scale = 2.56f */ +const Word16 GETRNB_SN1_fx[512] = +{ + -119, -271, -427, 447, 321, 58, 37, -105, -65, 99, 106, 21, -277, 53, 9, -6, + -93, -241, -433, -826, -1028, 17, 180, 138, 320, 234, 152, 235, 973, 594, 199, 96, + -300, -474, -553, -497, -374, -231, -224, -170, -145, 51, 154, 714, 1338, 690, 271, 118, + -115, -228, -248, 9, -27, -196, -240, -269, -293, -310, -276, -254, 769, 481, 117, 59, + 172, 58, 469, 585, 512, 336, 145, -52, -167, -344, -379, -487, 285, 377, 27, 27, + 81, 34, 574, 859, 818, 702, 521, 344, 177, 23, -116, -274, -611, -78, -61, -35, + 76, 19, -104, -388, -687, 54, 279, 144, 237, 223, 110, 9, -335, 4, 3, -10, + 115, 380, 486, 446, 389, 316, 239, 249, 197, 207, 162, 141, -435, -1516, -409, -136, + -146, -348, -425, 645, 998, 790, 609, 468, 282, 287, 153, 87, -461, -592, -88, -64, + -249, -471, -835, -642, 589, 960, 887, 637, 442, 286, 242, 132, 142, 299, 99, 44, + 128, 37, -120, -314, -571, -730, -868, -558, -259, -109, 8, 413, 1145, 593, 210, 92, + 151, 331, 267, 130, -24, -89, -133, -43, -75, 57, 19, 94, -469, -796, -124, -90, + -339, -468, -292, -34, 76, 179, 231, 269, 259, 281, 275, 204, -93, 157, 53, 16, + 33, 176, 25, -201, -311, -497, -509, -242, -47, 6, 86, 48, -165, 176, 24, 8, + 27, 223, 461, 500, 479, 475, 489, 560, 635, 741, 924, 1347, 1546, 806, 277, 54, + 510, 464, 402, 114, -80, -285, -290, -321, -283, -368, -325, -424, 388, 402, 52, 38, + 521, 614, 732, 549, 428, 278, 180, 81, 14, -110, -204, -355, -649, -32, -56, -36, + 72, 26, 262, 263, 159, 113, 60, -10, -73, -121, -201, -329, -768, -61, -60, -39, + 85, 57, 116, -40, -78, -159, -154, -247, -220, -366, -331, -532, -35, 344, 0, 25, + 527, 919, 1339, 1225, 1190, 1023, 774, 577, 393, 160, -4, -184, -281, 29, -21, -12, + -230, -283, -338, -379, -313, -293, -163, -122, 15, 97, 243, 168, 361, 449, 102, 61, + 378, 369, 369, 136, 42, -72, -73, -154, -155, -260, -270, -444, -562, 173, -36, -9, + 168, 108, -36, -347, -559, -436, -254, -263, -236, -227, -247, -238, 796, 488, 123, 62, + -151, -118, 163, 452, 430, 484, 456, 418, 377, 363, 256, 183, -403, -1429, -382, -126, + -204, -366, -652, -512, 428, 353, 182, 88, -10, -94, -54, -11, 801, 527, 151, 76, + 60, 79, -169, -465, -789, -844, -55, 181, 209, 172, 210, 107, 260, 399, 91, 52, + -69, -205, -377, -164, 647, 584, 302, 151, 32, -135, -136, -223, -269, 170, 4, 5, + 38, 418, 885, 979, 990, 1027, 870, 804, 669, 537, 360, 241, -336, -1281, -338, -111, + -420, -700, -912, -622, -337, -51, 67, 173, 326, 554, 766, 1395, 1656, 894, 390, 178, + -141, -252, -507, -822, -1084, -845, -280, 20, 149, 242, 393, 951, 1428, 740, 303, 135, + -120, -37, 31, 105, 72, 99, 53, 117, 59, 171, 120, 177, -414, -993, -160, -98, + -382, -612, -631, -167, 4, 104, 130, 141, 242, 325, 348, 430, 1048, 651, 222, 109 +}; +/* An 16-by-16 matrix in Scale = 2.56f */ +const Word16 GETRNB_SN2_fx[256] = +{ + -27, 71, 45, -4, 28, 69, 25, 94, 45, 90, 45, 87, -177, -567, -116, -59, + -208, -147, 531, 399, 199, 113, -21, -28, -34, -38, -48, -46, -47, 18, -1, -1, + 69, -20, -115, -355, -380, 388, 379, 193, 134, 37, -42, -60, -35, 29, 6, 5, + 107, 89, -98, -189, 379, 289, 68, 22, -71, -179, -187, -192, -137, 4, -17, -7, + -44, -81, -371, -448, 226, 75, -52, 43, 40, 36, 79, 120, 130, 76, 36, 15, + 131, 115, 192, 177, 25, -7, -23, -95, -132, -184, -206, -245, -200, -12, -29, -11, + 45, -25, -249, 50, -189, -358, 253, 145, -39, 27, 34, -20, -52, 13, 1, 2, + -254, -155, 23, -89, -30, 23, -23, -21, -45, -86, -92, -109, -48, 52, 3, 3, + -248, -233, 139, 213, 232, 361, 349, 401, 373, 301, 230, 207, 204, 101, 32, 14, + 491, 546, 409, 147, 34, -18, 52, 59, 48, 27, 14, 7, -1, -37, -16, -9, + 36, 41, 0, -21, -29, -64, -207, -346, -516, -355, -64, 73, 156, 94, 30, 11, + -28, -173, -278, 506, 427, 164, 111, 21, -33, -61, -78, -90, -32, 39, 4, 4, + -44, -60, -215, -373, -485, -270, 12, 151, 271, 265, 215, 178, 153, 71, 32, 17, + 110, 155, -29, -259, -218, -183, -175, -132, -85, -98, -87, -93, -77, 0, -9, -4, + -116, -14, 235, 1, -238, -398, -419, -55, 109, 77, 62, 74, 73, 47, 16, 8, + -20, -108, -219, 246, 20, -184, -328, -449, -67, 142, 125, 110, 91, 74, 28, 13 +}; +/* An 16-by-32 matrix in Scale = 2.56f */ +const Word16 GETRWB_SN1_fx[512] = +{ + -232, -191, 282, 248, 344, 390, 428, 490, 538, 592, 620, 607, 533, 372, 261, 136, + -59, -227, -418, -288, -247, -448, -501, -644, -760, -922, -1112, -1204, -523, -130, 12, 131, + 139, 838, 1402, 1327, 1465, 1391, 1371, 1342, 1220, 1147, 1041, 910, 733, 518, 335, 181, + 211, 148, -94, -275, -484, -586, -541, -634, -583, -511, -424, -322, -285, -299, -194, -87, + 410, 362, 337, 73, -36, -113, -180, -274, -373, -493, -501, -473, -393, -361, -271, -251, + -85, -366, -819, -532, 753, 688, 414, 203, 24, -43, 129, 60, -100, -123, -97, -114, + 4, 37, 484, 514, 340, 225, 89, 59, 40, 3, -5, -1, -11, -49, -43, -48, + -223, -471, -661, -567, -496, -519, -464, -542, -484, -343, -276, -185, -43, 17, 84, 133, + -106, -312, -668, -741, 385, 329, 121, -157, -423, -710, -957, -1280, -1143, -330, -20, 131, + 250, 157, 71, -310, -552, -740, -745, -778, -827, -1064, -1336, -1629, -788, -195, -44, 131, + 140, 633, 970, 864, 867, 761, 683, 648, 572, 544, 516, 469, 383, 238, 143, 55, + 116, 143, 229, 134, -25, -120, -232, -333, -535, -642, -985, -1259, -1873, -1727, -330, -10, + -64, -82, -62, -232, -308, -346, -296, -272, -153, -26, 108, 205, 232, 158, 129, 53, + 82, -92, -309, -791, -1128, -259, -243, -405, -367, -637, -903, -1084, -675, -199, 17, 146, + -247, -569, -886, -758, -334, -206, -158, -150, -64, 57, 190, 252, 261, 210, 163, 129, + -23, -319, -458, 791, 718, 400, 233, -81, -174, -400, -758, -1048, -1338, -1038, -288, -6, + 50, 462, 303, -47, -122, -134, 15, 137, 179, 222, 266, 249, 219, 123, 80, 30, + -116, -332, -650, -1104, -1367, -691, -376, -295, -178, -199, -170, -24, 125, 95, 125, 168, + -66, -314, -526, 325, 156, -56, -114, -287, -126, -185, -292, -298, -189, -81, 1, 23, + 147, -30, -291, -771, -939, 262, 182, 126, 127, -100, -163, -134, -91, -95, -52, -19, + -225, -496, -449, -61, 46, 135, 182, 247, 324, 404, 457, 464, 420, 305, 209, 106, + 418, 312, 415, 74, -156, -345, -400, -634, -769, -1057, -1362, -1841, -1848, -471, -147, 87, + 38, 19, -232, -552, -698, -941, -483, 119, 54, -34, 70, -68, -144, -192, -253, -236, + 80, -30, -214, -157, -292, -312, -283, -347, -384, -372, -487, -503, -746, -950, -1372, -644, + 44, 55, 124, 181, 125, 109, 61, 29, -73, -54, -206, -278, -638, -929, -1563, -1742, + 802, 823, 726, 353, 272, 122, 117, 94, 80, 40, 68, 47, 42, -19, -26, -69, + 50, -97, -306, -666, -918, -1109, -1124, -776, -710, -728, -675, -486, -150, -3, 93, 160, + 81, -144, -131, 319, 227, -96, -236, -517, -711, -949, -1231, -1644, -1625, -444, -117, 86, + -230, -237, 586, 799, 931, 1023, 1077, 1179, 1133, 1101, 1027, 909, 731, 515, 330, 171, + 448, 632, 1047, 782, 631, 390, 155, -82, -342, -685, -1103, -1520, -1779, -931, -214, 34, + -77, -352, -353, 787, 938, 677, 513, 352, 284, 278, 247, 181, 141, 73, 8, -39, + 54, 42, -67, -298, -465, -593, -533, -547, -626, -741, -977, -1317, -1665, -613, -119, 80 +}; +/* An 16-by-16 matrix in Scale = 2.56f */ +const Word16 GETRWB_SN2_fx[256] = +{ + -202, -246, -356, -356, -232, -164, -79, 4, 78, 130, 152, 165, 170, 141, 90, 70, + 38, 78, -72, -185, -446, -552, 269, 295, 104, 77, -54, -184, -168, -72, -32, -2, + 69, 93, 39, 116, 100, 46, 50, -1, -2, 62, 8, -105, -404, -656, -494, -224, + -285, -305, 263, 97, 29, 33, -24, 54, 35, 25, -4, -6, -30, 13, 20, 21, + -28, -70, -160, 34, 5, -145, -264, -425, -539, -329, -19, 228, 411, 280, 141, 51, + 244, 245, 19, -319, -461, -184, -10, 47, 220, 293, 309, 330, 281, 140, 71, 12, + -128, -251, -374, 424, 279, 68, 35, -68, 13, 45, -6, -41, -73, -17, 8, 27, + -55, -7, 438, 500, 493, 442, 286, 211, 68, -39, -117, -167, -180, -131, -75, -63, + 30, 31, 69, 114, -172, -407, -596, -391, 102, 169, 158, 131, 46, 4, -6, -3, + 69, 76, 33, 238, 164, 119, 160, 165, 273, 342, 383, 419, 456, 378, 262, 96, + -55, 43, -59, -273, -200, -286, -287, -221, -247, -245, -194, -160, -129, -36, -31, 3, + -35, -46, -272, -357, 484, 246, -11, 21, -123, -197, -102, -94, -96, -22, 6, 6, + -117, -188, -252, -227, 0, 460, 506, 526, 501, 389, 250, 131, -28, -32, 24, 17, + 399, 511, 390, 146, 80, -84, -81, -57, -123, -138, -95, -82, -51, -33, -14, -45, + -9, 12, 300, 304, 182, 27, -197, -258, -344, -393, -384, -318, -140, -5, -6, 6, + 64, 25, -7, -256, -306, 381, 243, 96, -17, -190, -285, -246, -65, 48, 37, 29 +}; +/* An 16-by-16 matrix in Scale = 2.56f */ +const Word16 TRWB2_SN1_fx[256] = +{ + -74, -384, -764, -964, -1122, -912, -819, -740, -728, -572, -379, -317, -250, -51, -67, 85, + -311, -618, -439, -108, 156, 257, 404, 543, 643, 729, 732, 572, 446, 329, 236, 164, + 523, 1549, 1557, 1476, 1374, 1192, 1068, 923, 901, 788, 717, 401, 262, 6, -100, -368, + -13, -80, -189, -386, -486, -357, -216, -63, 65, 189, 248, 194, 218, 219, 205, 169, + -104, -519, -772, 492, 224, 18, -203, -244, -126, -220, -362, -417, -271, -71, -34, -50, + -202, 124, 811, 975, 1326, 1468, 1613, 1527, 1474, 1366, 1220, 906, 700, 509, 351, 207, + -57, -196, -238, -281, -267, -239, -190, -137, -27, 4, 77, -178, -256, -553, -669, -1105, + -183, -211, 804, 789, 685, 529, 479, 403, 371, 313, 279, 49, -19, -156, -179, -335, + 758, 848, 608, 313, 271, 176, 177, 73, 106, 61, 59, -159, -203, -287, -268, -343, + 199, 70, 95, -29, -245, -411, -745, -1009, -1473, -1921, -2633, -1648, -537, -284, -87, 207, + 82, -217, -460, -646, -718, -821, -983, -1282, -1580, -2108, -1863, -609, -407, -122, -50, 243, + -132, 364, 364, 340, 489, 496, 596, 606, 704, 756, 777, 616, 521, 409, 305, 211, + 123, -189, -91, -306, -319, -407, -600, -679, -911, -855, -566, -249, -65, -1, -65, -25, + 79, -58, -103, -150, -268, -265, -426, -479, -614, -671, -1005, -1378, -2027, -1547, -568, -52, + -275, -669, -1070, -1097, -688, -433, -340, -148, -27, 194, 309, 277, 229, 188, 82, 127, + 397, 1343, 1482, 1729, 1978, 2012, 1969, 1852, 1729, 1574, 1407, 1087, 848, 636, 431, 278 +}; +/* An 16-by-16 matrix in Scale = 2.56f */ +const Word16 TRWB2_SN2_fx[256] = +{ + 50, -66, -486, -850, 504, 345, 261, 10, -207, -218, -174, -18, 72, 69, 3, 24, + -171, -439, -632, 390, 143, -89, -292, -314, -227, -157, 33, 181, 185, 204, 128, 167, + 458, 459, 78, -250, -365, -381, -353, -382, -327, -284, -191, -18, 3, 37, 29, 95, + -169, -227, -423, -448, -485, -426, -364, -284, -238, -184, -228, -190, -145, 17, 65, 145, + -4, -120, -170, -333, -677, -782, -719, -391, -112, 232, 464, 392, 275, 215, 121, 139, + -94, -130, 453, 295, -45, -286, -444, -473, -519, -428, -268, -40, -12, 46, 39, 118, + -189, -245, 805, 815, 518, 293, 162, 110, -67, -158, -223, -120, -36, 15, 26, 60, + 23, 130, 107, 0, -31, -66, 33, 22, 101, -10, -32, -232, -281, -590, -672, -1089, + 51, 106, 157, 132, 40, 11, -73, -66, -165, -294, -561, -770, -742, -489, -202, 4, + 25, 230, 286, 179, 75, 18, 15, 24, 109, 187, 310, 334, 328, 291, 237, 212, + -238, -492, -550, 563, 764, 610, 542, 427, 373, 261, 166, 171, 122, 34, -21, -92, + -359, -462, -10, 22, -42, -2, 78, 167, 154, 155, 74, 73, 66, 94, 89, 126, + -5, -110, -374, -546, -386, -136, 95, 305, 437, 570, 615, 558, 463, 335, 209, 151, + 23, 376, 292, 235, 485, 519, 657, 549, 478, 338, 186, 7, -28, -155, -95, -188, + 166, 139, -277, -716, -822, 234, 319, 326, 234, 36, -155, -317, -247, -80, 49, 117, + 431, 853, 745, 512, 325, 139, 83, -31, -25, -47, -17, -12, -24, -43, -5, 13 +}; +/* An 16-by-32 matrix in Scale = 2.56f */ +const Word16 GEWB2_MA1_fx[512] = +{ + 659, 1694, 1634, 1513, 1305, 1098, 933, 805, 733, 624, 525, 339, 239, 50, -35, -215, + 6, 65, 125, 55, -85, -126, -272, -316, -507, -586, -1010, -1278, -1941, -1910, -426, 78, + 281, 315, 236, -4, -102, -171, -232, -335, -362, -425, -488, -603, -669, -736, -648, -593, + 29, -251, -582, -871, -969, -897, -991, -1077, -1275, -1480, -998, -393, -247, -9, 28, 271, + -60, -361, 401, 552, 236, 35, -196, -215, -496, -683, -911, -820, -576, -299, -240, -141, + 416, 574, 662, 350, 133, -160, -431, -781, -1200, -1652, -2035, -1092, -449, -192, -11, 263, + -206, -609, -931, 28, -229, -358, -543, -462, -377, -360, -336, -251, -105, 35, 26, 80, + 369, 1256, 1380, 1571, 1726, 1727, 1644, 1521, 1350, 1156, 984, 748, 580, 395, 254, 108, + -147, -479, -330, -73, -272, -441, -685, -837, -1139, -1458, -1370, -414, -208, -12, 14, 213, + -50, 100, -82, -253, -7, 119, 294, 392, 494, 578, 589, 523, 462, 383, 300, 249, + -94, -362, -575, -770, -987, -999, -922, -697, -582, -305, -135, -31, -8, 23, -33, 62, + 29, -64, -4, -123, -344, -414, -679, -767, -1152, -1401, -2105, -1905, -582, -300, -64, 223, + 428, 990, 1019, 809, 681, 470, 366, 179, 126, -26, -141, -363, -423, -536, -437, -545, + -133, -357, 364, 241, -39, -227, -334, -305, -426, -292, -102, 87, 159, 182, 160, 190, + 560, 764, 531, 156, 22, -18, 23, -20, 19, 0, 13, -61, -35, -44, -12, -48, + 33, -235, -634, -1093, 136, -31, -68, -285, -529, -535, -462, -249, -95, -53, -116, -61, + -188, -628, -894, 702, 700, 373, 196, 51, 95, -56, -191, -181, -173, -132, -116, -218, + 37, -188, -661, -1087, -1322, -258, -186, -181, -238, -372, -418, -508, -433, -197, -73, 28, + -231, -222, 911, 875, 669, 440, 363, 301, 257, 192, 147, 68, 77, 43, 57, 17, + -4, -187, -356, -410, -569, -499, -584, -568, -660, -703, -965, -1201, -1540, -708, -252, 87, + 220, 64, -67, -357, -572, -744, -913, -1176, -1439, -1894, -2152, -762, -419, -146, -10, 281, + -253, -627, -1075, -1206, -721, -398, -337, -188, -118, 50, 125, 198, 200, 190, 96, 164, + -348, -741, -854, -357, -163, -103, -26, 143, 231, 318, 335, 325, 274, 233, 167, 190, + -143, -256, -191, -280, -250, -191, -82, 37, 126, 102, 67, -130, -202, -430, -495, -810, + 232, 107, -22, -341, -497, -523, -607, -646, -746, -690, -478, -295, -160, -77, -53, -7, + -33, -98, -258, -501, -589, -438, -316, -168, -58, 82, 175, 219, 249, 259, 237, 226, + -393, -665, -19, 185, 249, 266, 378, 468, 499, 508, 464, 388, 310, 238, 186, 145, + -240, -99, 408, 480, 693, 761, 946, 943, 951, 893, 782, 613, 482, 351, 260, 163, + -23, 523, 885, 903, 1172, 1287, 1482, 1491, 1476, 1402, 1240, 1005, 787, 604, 433, 292, + 262, 988, 904, 732, 734, 665, 715, 656, 673, 615, 541, 372, 284, 139, 68, -84, + -119, 446, 1118, 1215, 1372, 1280, 1208, 989, 881, 675, 557, 319, 227, 23, -39, -256, + -102, 178, 379, 252, 365, 319, 455, 377, 413, 278, 225, -36, -67, -351, -375, -772 +}; +/* An 16-by-16 matrix in Scale = 2.56f */ +const Word16 AUNB_SN1_fx[256] = +{ + -180, -79, -51, 39, 66, 99, 48, 108, 56, 127, 34, 46, -470, -845, -141, -90, + -212, 82, 284, 422, 416, 416, 313, 289, 233, 210, 108, 55, -439, -1323, -336, -123, + -9, 405, 532, 659, 710, 798, 844, 971, 1072, 1181, 1464, 1913, 2028, 1232, 549, 265, + 75, 49, 330, 493, 448, 329, 204, 67, -18, -134, -235, -400, -605, -30, -67, -36, + -9, -7, -95, -222, -322, -421, -321, -233, -110, -86, 67, -19, 3, 345, 41, 30, + 153, 34, -172, -386, -500, -548, -503, -420, -317, -207, -114, 183, 1096, 661, 198, 94, + 616, 501, 471, 220, 157, 55, 4, -161, -178, -314, -267, -389, 216, 429, 46, 38, + -559, -854, -789, -369, -153, 64, 146, 296, 388, 520, 574, 958, 1481, 898, 340, 164, + 131, 137, 116, 57, 64, -21, -38, -112, -123, -199, -214, -379, -641, 83, -53, -21, + -101, -324, -648, -801, -835, -737, -501, -296, -86, 144, 400, 1025, 1501, 861, 322, 151, + -231, -397, -512, -506, -308, -200, -127, -91, -18, 17, 94, 114, 798, 625, 161, 88, + -518, -617, -201, 103, 258, 279, 273, 267, 281, 251, 214, 114, 58, 270, 70, 31, + 17, -86, -78, -82, -22, -73, -171, -299, -334, -431, -422, -526, 517, 511, 71, 53, + 276, 182, -40, -336, -461, -93, 342, 267, 166, 18, -43, -196, -146, 236, 18, 14, + 227, 338, 224, 188, 107, 80, 57, 92, 34, 80, -5, -4, -515, -927, -174, -100, + 731, 744, 797, 675, 590, 438, 328, 215, 144, 24, -96, -239, -486, -175, -65, -41 +}; +/* An 16-by-16 matrix in Scale = 2.56f */ +const Word16 AUWB_SN1_fx[256] = +{ + 328, 137, 358, 330, 184, 145, -60, -294, -555, -784, -945, -872, -601, -337, -155, -33, + 32, -212, -488, -651, -752, -877, -892, -886, -853, -795, -705, -549, -330, -224, -127, -9, + 372, 327, 197, 33, 13, -55, -87, -124, -125, -148, -144, -168, -175, -184, -127, -125, + 752, 727, 623, 519, 449, 350, 309, 289, 272, 252, 185, 124, 118, 35, 22, -20, + 14, 144, 296, 432, 416, 325, 177, 166, 151, 123, 109, 104, 47, -22, -45, -49, + 310, 112, -141, -529, -654, -53, 162, -33, -297, -551, -772, -817, -540, -287, -95, -7, + -158, 241, 443, 543, 559, 579, 566, 606, 610, 622, 602, 578, 485, 331, 197, 104, + -471, -530, 37, 272, 397, 442, 466, 523, 561, 592, 608, 576, 485, 348, 222, 133, + 162, 0, -87, -85, -151, -331, -410, -603, -767, -1030, -1348, -1812, -1735, -678, -284, -6, + -156, 36, 15, 26, 41, 118, 201, 265, 339, 382, 420, 435, 377, 264, 159, 84, + -69, -274, -411, -158, 60, -56, -190, -305, -371, -389, -411, -407, -338, -276, -173, -99, + 0, -26, -196, -379, -369, -327, -193, -148, -77, -10, 63, 98, 98, 49, 40, -5, + -149, -432, -729, -923, -927, -766, -568, -455, -333, -219, -122, -29, 11, 9, 20, 54, + 177, 64, -60, -232, -411, -552, -557, -550, -509, -464, -380, -331, -297, -288, -215, -170, + -16, 439, 971, 1104, 1209, 1323, 1339, 1374, 1317, 1223, 1107, 983, 781, 535, 315, 151, + -432, -727, -686, -340, -156, -40, 18, 102, 169, 257, 306, 335, 296, 213, 137, 97 +}; + +/* An 16-by-16 matrix in Scale = 2.56f */ +const Word16 AUWB2_SN1_fx[256] = +{ + -107, -446, -835, -1041, -1152, -1161, -1146, -969, -828, -533, -251, -242, -139, 172, 95, 466, + 1052, 1008, 1052, 875, 864, 748, 783, 690, 754, 715, 688, 342, 195, -32, -251, -509, + -311, -170, 366, 632, 748, 863, 983, 1042, 1118, 1188, 1133, 895, 728, 621, 460, 418, + 608, 525, 322, 30, -237, -483, -862, -1178, -1651, -2184, -2770, -1349, -430, -28, 128, 562, + 296, 171, -192, -429, -488, -470, -492, -473, -448, -352, -242, -309, -337, -210, -265, -182, + 831, 703, 456, 217, 165, 65, 17, -53, -67, -78, -38, -222, -340, -329, -349, -391, + 162, -13, -158, -335, -526, -705, -986, -1245, -1640, -2149, -2754, -1344, -372, -12, 134, 564, + -79, -389, -569, -699, -811, -940, -1058, -1299, -1534, -2077, -1953, -507, -216, 143, 191, 607, + -106, -116, -210, -225, -323, -330, -494, -491, -700, -757, -1057, -1424, -2222, -1509, -259, 348, + -366, -748, -1177, -1216, -1017, -698, -444, -154, 10, 285, 361, 284, 255, 359, 187, 365, + 77, 447, 418, 475, 453, 459, 475, 515, 562, 648, 658, 452, 367, 334, 244, 204, + 10, 197, 170, 166, 144, 60, 52, -2, -20, -40, 18, -238, -279, -434, -451, -807, + -460, -713, -547, -153, 64, 243, 386, 492, 620, 752, 759, 536, 445, 324, 151, -32, + -246, -396, -413, -371, -354, -317, -307, -228, -195, -101, -36, -174, -197, -162, -261, -349, + -329, -240, 326, 462, 428, 344, 405, 374, 439, 434, 467, 127, 85, -154, -248, -683, + -12, 15, -222, -227, -31, 124, 200, 294, 357, 541, 607, 459, 376, 352, 282, 283 +}; + +/* An 16-by-16 matrix */ +const short CNG_SN1_fx[256] = +{ + 600, 1640, 3039, 4257, 5512, 6740, 7989, 9169, 10393, 11612, 12880, 14100, 15378, 16554, 17816, 18918, + 1188, 2487, 3746, 4903, 6103, 7261, 8437, 9587, 10776, 11954, 13172, 14355, 15564, 16712, 17913, 19012, + 346, 799, 2259, 3555, 4876, 6175, 7516, 8803, 10073, 11323, 12631, 13938, 15282, 16553, 17817, 19039, + 439, 1616, 3446, 4743, 6073, 7288, 8553, 9726, 10947, 12106, 13312, 14474, 15650, 16773, 17894, 18977, + 921, 1800, 2976, 4007, 5105, 6137, 7178, 8150, 9057, 9914, 11009, 12545, 13671, 15502, 17428, 18927, + 896, 1899, 3035, 4128, 5301, 6429, 7604, 8719, 9886, 11059, 12417, 13621, 14962, 16135, 17475, 18460, + 722, 1507, 2537, 3437, 4328, 5190, 6018, 6841, 7587, 8343, 8925, 9511, 9919, 11075, 13613, 15021, + 315, 612, 1671, 2910, 3990, 5083, 6120, 7170, 8188, 9173, 10148, 11186, 12250, 13262, 14290, 15284, + 885, 1928, 3010, 3973, 4952, 5900, 6848, 7769, 8701, 9609, 10581, 11540, 12508, 13450, 14412, 15349, + 338, 1020, 2657, 3736, 4839, 5791, 6806, 7760, 8738, 9659, 10627, 11567, 12534, 13468, 14416, 15334, + 1126, 1964, 2999, 3855, 4764, 5608, 6482, 7286, 8109, 8827, 9570, 10649, 11999, 13125, 14223, 15252, + 385, 815, 2000, 2939, 3906, 4879, 5793, 6734, 7661, 8526, 9309, 10146, 11597, 12955, 14106, 15241, + 633, 1445, 2400, 3293, 4235, 5171, 6143, 7084, 8057, 8980, 9924, 10924, 11987, 12998, 14016, 15058, + 584, 1248, 2250, 3131, 4050, 4920, 5811, 6652, 7471, 8244, 8913, 9480, 10188, 12225, 13871, 15123, + 1157, 1820, 2745, 3505, 4354, 5097, 5932, 6648, 7408, 8034, 8635, 9083, 9977, 12228, 13819, 15108, + 572, 1401, 2514, 3501, 4503, 5465, 6469, 7435, 8416, 9328, 10306, 11309, 12328, 13303, 14306, 15261, +}; +/* An 16-by-32 matrix */ +const Word16 IAA_MA1_fx[512] = +{ + -175, -490, -520, -631, -645, -614, -610, -548, -503, -432, -353, -301, -238, -141, -67, 26, + 301, 407, 227, 96, -12, -18, -13, 2, 39, 107, 124, 92, 83, 100, 62, 72, + -280, -737, -569, -164, -9, 100, 141, 211, 252, 281, 274, 217, 206, 219, 117, 106, + -266, -753, -841, -587, -487, -345, -263, -167, -114, -30, 8, 32, 34, 61, 55, 104, + -91, -137, -293, -349, -352, -326, -268, -247, -178, -129, -56, -96, -11, 219, 49, 56, + -18, 1, -33, -14, -19, -5, -22, -14, -43, -37, -104, -143, -375, -770, -190, -100, + 72, -22, -121, -220, -320, -378, -500, -587, -729, -795, -1056, -1305, -1691, -1090, -452, -60, + 19, -279, -453, -580, -588, -739, -858, -1044, -1281, -1614, -921, -376, -273, -84, -2, 187, + 853, 759, 591, 376, 260, 122, 39, -71, -133, -184, -209, -297, -299, -171, -124, -83, + 266, 34, -182, -367, -516, -686, -881, -1121, -1414, -1834, -2110, -997, -519, -274, -109, 137, + -2, -8, 42, 91, 172, 211, 298, 336, 433, 409, 546, 1043, 1499, 1038, 410, 189, + 86, 254, 259, 254, 246, 219, 184, 122, 79, 11, -55, -170, -363, -934, -371, -188, + 168, 167, -122, -244, -325, -340, -359, -343, -331, -291, -278, -270, -272, -162, -101, -46, + -244, -459, -367, -340, -295, -220, -173, -107, -22, 53, 103, 293, 1084, 807, 260, 117, + -319, -650, -685, -427, -290, -105, 25, 161, 303, 418, 587, 1074, 1563, 1085, 400, 170, + 146, 257, 282, 295, 303, 294, 297, 262, 237, 193, 92, 341, 1220, 884, 315, 144, + -291, -558, 147, 201, 282, 280, 310, 302, 313, 306, 292, 239, 198, 188, 106, 94, + -11, -8, -156, -204, -231, -250, -265, -289, -269, -316, -322, -450, -488, -676, -778, -973, + -117, -27, 4, 96, 174, 229, 271, 310, 344, 362, 344, 273, 209, 180, 109, 106, + -260, -290, 151, 269, 406, 442, 551, 590, 679, 681, 900, 1293, 1631, 1132, 477, 221, + -37, 374, 394, 414, 419, 395, 345, 313, 282, 255, 211, 126, 84, 51, -10, -53, + 404, 327, 174, 28, -124, -290, -490, -695, -1011, -1111, -529, -288, -183, -69, -7, 142, + 563, 752, 585, 555, 512, 478, 424, 396, 376, 343, 300, 194, 193, 162, 78, 46, + -59, -131, -35, 49, 54, -12, -92, -185, -243, -289, -288, -344, -326, 0, -38, 6, + 496, 582, 564, 514, 521, 490, 486, 436, 432, 320, 456, 1060, 1523, 1058, 419, 194, + 174, 77, 18, -89, -112, -196, -165, -247, -222, -326, -332, -494, 499, 617, 121, 60, + 315, 299, 229, 137, 78, -3, -40, -138, -198, -307, -375, -502, -515, -25, -88, -49, + -232, -29, 353, 399, 485, 487, 523, 526, 556, 559, 520, 415, 328, 283, 187, 166, + 182, 385, 403, 453, 515, 572, 635, 691, 787, 852, 1154, 1483, 1779, 1231, 524, 246, + -273, -492, -185, -97, -52, -51, -17, -27, 13, 20, 45, -20, 52, 244, 58, 56, + 20, -3, -241, -267, -194, -86, 4, 75, 140, 191, 200, 154, 137, 146, 85, 77, + 92, 628, 611, 708, 706, 716, 672, 694, 655, 619, 550, 432, 354, 284, 204, 172 +}; +/* An 16-by-8 matrix in Scale = 2.56f */ +const Word16 GESVNB_AR1_fx[128] = +{ + -25, -64, -140, -118, 270, 240, 127, 70, 20, -40, -56, -111, -82, 64, 2, 5, + 81, 104, 71, 70, 0, -49, -54, -73, -59, -92, -102, -201, -404, -52, -40, -15, + -112, -217, -251, -202, -34, 57, 58, 62, 79, 127, 177, 306, 524, 315, 112, 53, + 17, -6, 34, 66, 14, -26, -174, -196, -142, -131, -102, -97, 180, 154, 29, 17, + 5, -27, -107, -197, -343, -333, -182, -143, -91, -17, 43, 120, 383, 267, 83, 40, + -1, -15, -35, -56, -169, -145, 86, 101, 77, 48, 29, 78, -9, 68, 15, 9, + 3, 9, 320, 450, 385, 348, 215, 155, 105, 45, -13, -75, -272, -129, -52, -23, + 4, 49, 54, 90, 92, 101, 59, 69, 20, 70, 23, 43, -280, -624, -114, -55 +}; +/* An 16-by-8 matrix in Scale = 2.56f */ +const Word16 GESVNB_AR2_fx[128] = +{ + -22, -35, -31, -166, -164, 217, 212, 155, 166, 123, 67, 33, -21, -41, -3, -1, + -14, -20, -16, -70, -77, -53, 23, -7, -98, -123, -99, -49, 357, 114, 36, 19, + -57, -119, -303, -215, -33, -103, -97, -117, -105, -102, -67, -134, -176, 113, 16, 8, + -12, 14, 30, -37, -112, -226, -206, -25, 125, 134, 99, 83, 55, -4, 9, 4, + -19, 23, 171, 57, 13, -15, -26, -42, -65, -69, -77, -169, -351, -105, -49, -21, + -14, -10, 8, 35, 161, 104, -74, -102, -135, -47, 45, 264, 52, -69, -1, -5, + 213, 284, 230, 121, 50, 12, 43, 48, 27, -7, -24, -39, 75, 1, -9, -3, + -75, -137, -89, 275, 164, 65, 125, 91, 86, 91, 56, 10, 9, -10, 0, 0 +}; +/* An 16-by-8 matrix in Scale = 2.56f */ +const Word16 GESVWB_AR1_fx[128] = +{ + -3, -16, -31, 2, -81, -123, -226, -260, -196, -122, -20, 78, 178, 145, 84, 46, + 55, 42, 15, 32, -48, -81, -109, -137, -187, -264, -330, -387, -363, -176, -38, 37, + -32, -70, -144, -269, -337, -183, 59, 58, 44, 49, 42, 51, 72, 50, 26, 38, + -18, -58, -79, 125, 352, 291, 180, 118, 72, 25, -23, -82, -185, -167, -33, 6, + -10, 135, 544, 517, 517, 561, 515, 528, 500, 472, 413, 383, 318, 219, 118, 57, + -54, -280, -614, -548, -521, -522, -448, -479, -457, -438, -377, -355, -318, -271, -222, -89, + -62, -96, -86, -10, 104, 155, 120, 112, 190, 264, 291, 272, 232, 166, 95, 27, + 33, 61, 155, 121, 9, -28, 6, 103, 64, 17, 4, -2, -31, -88, -209, -206 +}; +/* An 16-by-8 matrix in Scale = 2.56f */ +const Word16 GESVWB_AR2_fx[128] = +{ + -147, -326, -421, -91, -22, -25, -14, -21, 32, 76, 104, 102, 65, 47, 50, 41, + -39, -16, 61, -13, -38, -56, 47, 153, 195, 213, 212, 220, 245, 245, 209, 86, + -34, -73, 82, 387, 199, 71, 56, -18, -33, -56, -88, -79, -5, 59, 55, 29, + -7, -21, -21, -158, -123, 304, 226, 168, 124, 8, -75, -91, -54, -5, 37, 30, + -26, -22, -67, -225, 107, 38, -82, -113, -213, -205, -62, 28, 89, 95, 52, 17, + 227, 404, 325, 134, 45, -16, 3, -15, -55, -65, -55, -54, -18, -8, 1, -14, + 19, 30, 12, 28, 48, 13, 2, -47, -38, 41, 29, -8, -154, -315, -411, -242, + 8, 24, 29, -61, -215, -329, -237, -106, -12, -12, -64, -118, -167, -119, 8, 52 +}; + +/* An 16-by-32 matrix in Scale = 2.56f */ +const Word16 AUWB2_MA1_fx[512] = +{ + 391, 298, 179, -37, -225, -387, -627, -864, -1216, -1644, -2108, -804, -277, -5, 121, 468, + 351, 213, 141, -75, -130, -164, -332, -410, -524, -573, -575, -474, -331, -103, -22, 201, + 81, 874, 1137, 1223, 1242, 1262, 1238, 1185, 1141, 1085, 993, 733, 570, 424, 256, 145, + -6, -25, -105, -147, -327, -342, -587, -620, -954, -1143, -1878, -2059, -356, -100, 134, 477, + -197, -505, -826, -1043, -863, -485, -296, -103, -6, 178, 269, 245, 231, 320, 243, 413, + -518, -605, 282, 430, 532, 596, 676, 748, 808, 861, 834, 681, 534, 498, 293, 337, + -244, -563, -720, -599, -500, -494, -627, -739, -1028, -1219, -297, 9, 71, 272, 285, 563, + -448, -854, -916, -518, -287, -52, 56, 245, 347, 524, 557, 497, 416, 452, 321, 437, + 150, 113, 28, -26, 1, -80, -177, -226, -193, -156, -62, -227, -240, -383, -535, -809, + -240, -246, -174, -66, 80, 149, 244, 284, 413, 434, 473, 158, 56, -167, -326, -723, + 131, -11, 141, 32, 24, -122, -397, -610, -888, -812, 30, 232, 306, 371, 341, 446, + -158, -545, -529, 151, 142, -101, -426, -716, -1031, -1479, -1550, -352, -132, 145, 187, 517, + 148, -104, -445, -841, -31, 183, -86, -316, -615, -660, -231, 84, 192, 275, 201, 311, + -183, -220, -243, -182, -237, -176, -266, -233, -336, -339, -650, -1019, -1652, -846, -52, 387, + -104, -117, -254, -332, -191, 1, 64, 182, 317, 495, 626, 574, 519, 508, 456, 505, + -151, -237, 492, 479, 273, 139, 36, -60, -119, 74, 174, 188, 298, 366, 347, 478, + 158, 23, -210, -450, -673, -637, -423, -331, -133, 14, 128, 69, 62, 143, 171, 313, + 501, 394, 37, -57, 67, 70, 46, 35, 92, 120, 337, 258, 276, 283, 368, 500, + 42, -157, -398, -600, -742, -780, -781, -980, -1166, -1629, -968, -149, -99, 188, 209, 529, + -240, 190, 465, 543, 575, 565, 605, 596, 653, 599, 583, 279, 203, -51, -186, -589, + 316, 371, 417, 372, 293, 189, 230, 154, 184, 91, 94, -175, -198, -358, -454, -736, + 72, -159, -362, -499, -633, -690, -794, -739, -662, -456, -360, -338, -251, -6, 50, 346, + -202, -332, -428, -462, -508, -440, -552, -647, -885, -1217, -1733, -619, -162, 95, 202, 510, + -91, -391, -709, -884, -1012, -1001, -936, -714, -509, -198, 42, 99, 119, 261, 238, 496, + -370, 92, 476, 604, 681, 762, 826, 893, 934, 1001, 954, 783, 629, 590, 412, 467, + -193, -22, -28, 46, 214, 387, 502, 643, 728, 864, 859, 723, 581, 569, 435, 483, + 223, 291, 633, 508, 350, 141, -156, -476, -930, -1417, -1809, -764, -206, 77, 191, 515, + -475, -791, -417, 75, 201, 343, 408, 549, 612, 707, 686, 572, 463, 457, 321, 373, + 842, 716, 669, 593, 419, 423, 373, 321, 273, 280, 354, 217, 193, 232, 175, 294, + 116, -60, -144, -299, -421, -551, -732, -952, -1203, -1662, -1996, -537, -240, 55, 138, 486, + -323, -665, -686, -214, -201, -260, -373, -329, -333, -165, 66, 96, 175, 310, 291, 486, + -19, 43, 35, 40, 42, 55, 63, 101, 133, 194, 222, 152, 117, 145, 133, 213 +}; + + +const Word16 *const Quantizers_fx[] = {SVNB_SN1_fx, SVNB_SN2_fx, GETRNB_SN1_fx, GETRNB_SN2_fx, AUNB_SN1_fx,SVWB_SN1_fx, SVWB_SN2_fx, GETRWB_SN1_fx, + GETRWB_SN2_fx, AUWB_SN1_fx,/* U13, */ + TRWB2_SN1_fx, TRWB2_SN2_fx, AUWB2_SN1_fx, CNG_SN1_fx + }; +const Word16 *const Quantizers_p_fx[] = {IAA_MA1_fx, UVD_MA1_fx, UVD_MA2_fx, UVWB_MA3_fx, GESVNB_AR1_fx, GESVNB_AR2_fx, GESVWB_AR1_fx, GESVWB_AR2_fx, + GEWB2_MA1_fx,GEWB_MA1_fx, AUWB2_MA1_fx + }; + +/* Q1 */ +const Word16 sigma_MSLVQ_fx[][16] = +{ + {3}, + {3}, + {107, 113, 160, 185, 202, 211, 219, 222, 222, 217, 218, 270, 327, 176, 66, 43}, + {125, 130, 182, 185, 191, 199, 204, 207, 205, 191, 179, 227, 305, 261, 95, 64}, + {123, 123, 176, 197, 207, 218, 228, 235, 232, 218, 209, 272, 342, 216, 89, 68}, + {219, 212, 255, 271, 273, 274, 260, 255, 250, 248, 249, 302, 328, 394, 85, 37}, + {3}, + {3}, + {113, 134, 220, 253, 260, 275, 274, 287, 304, 323, 321, 325, 349, 350, 376, 332}, + {158, 179, 242, 248, 246, 259, 257, 267, 278, 274, 276, 289, 309, 309, 312, 306}, + {146, 146, 222, 256, 261, 278, 290, 302, 318, 313, 323, 352, 394, 407, 415, 399}, + {217, 227, 287, 303, 316, 310, 296, 304, 303, 305, 317, 327, 355, 321, 305, 279}, + {3}, + {3}, + {193, 216, 283, 320, 343, 359, 375, 408, 413, 445, 479, 489, 502, 466, 456, 479}, + {230, 238, 312, 330, 334, 329, 339, 357, 353, 358, 391, 403, 441, 459, 379, 497}, + {231, 277, 304, 322, 347, 353, 366, 372, 373, 397, 438, 451, 424, 413, 381, 447}, + {264, 287, 364, 386, 384, 373, 382, 373, 393, 403, 448, 438, 403, 430, 401, 586}, + {224, 298, 262, 264, 258, 244, 260, 283, 313, 295, 275, 279, 260, 286, 286, 399}, + {411, 314, 301, 332, 335, 343, 356, 409, 430, 413, 363, 364, 338, 332, 315, 412}, + {136, 269, 343, 367, 405, 430, 411, 421, 444, 466, 435, 423, 328, 247, 235, 240}, + {178, 433, 305, 268, 258, 252, 253, 246, 250, 250, 245, 256, 242, 273, 300, 371}, + {349, 334, 335, 341, 336, 331, 343, 425, 505, 722, 783, 655,1006, 862, 346, 248}, + {315, 306, 323, 306, 300, 278, 276, 287, 380, 394, 327, 333, 339, 382, 370, 626}, + {236, 250, 241, 231, 241, 245, 238, 221, 215, 190, 181, 178, 183, 428, 184, 55}, + {113, 189, 360, 312, 332, 326, 296, 268, 272, 282, 320, 275, 219, 203, 179, 143}, + {273, 255, 245, 237, 242, 236, 214, 217, 223, 260, 233, 193, 187, 183, 174, 163}, + {111, 321, 275, 219, 213, 207, 202, 205, 205, 225, 239, 208, 192, 187, 168, 152}, + {383, 326, 300, 287, 290, 292, 276, 251, 258, 291, 430, 521, 397, 305, 274, 269}, + {152, 221, 271, 291, 344, 310, 308, 257, 252, 256, 339, 491, 499, 199, 179, 107}, + {226, 237, 236, 239, 250, 238, 228, 223, 227, 241, 311, 312, 299, 313, 421, 360}, + {221, 238, 214, 220, 246, 244, 232, 221, 210, 208, 200, 229, 368, 431, 106, 71}, + {249, 259, 267, 283, 278, 275, 251, 237, 203, 209, 198, 279, 543, 509, 122, 90}, + {192, 249, 256, 235, 231, 230, 213, 215, 210, 247, 284, 237, 214, 210, 199, 181}, +}; + +/* An 16-by-19 matrix in Scale = 2.56f */ +const Word16 sigma_p_fx[][16] = +{ + {152, 164, 179, 170, 172, 176, 171, 169, 169, 174, 175, 216, 247, 304, 113, 110}, + {131, 171, 178, 176, 174, 178, 178, 178, 135, 166, 167, 176, 183, 197, 199, 206}, + {84, 89, 120, 142, 154, 175, 184, 186, 189, 181, 178, 198, 245, 190, 54, 28}, + {138, 157, 200, 194, 189, 208, 207, 206, 214, 197, 186, 222, 311, 302, 103, 43}, + {3}, + {146, 165, 183, 194, 197, 202, 191, 190, 187, 186, 171, 189, 281, 311, 61, 34}, + {142, 168, 184, 183, 187, 190, 187, 188, 189, 193, 200, 212, 231, 245, 169, 177}, + {174, 164, 168, 197, 300, 372, 199, 59, 208, 208, 209, 218, 231, 246, 237, 232}, + {91, 101, 147, 165, 174, 195, 207, 210, 218, 230, 230, 244, 268, 272, 269, 250}, + {157, 192, 226, 210, 211, 228, 228, 241, 245, 246, 248, 263, 274, 275, 270, 251}, + {3}, + {131, 160, 183, 193, 202, 205, 203, 212, 212, 213, 217, 220, 229, 214, 203, 200}, + {187, 221, 231, 229, 237, 232, 232, 236, 249, 259, 286, 284, 250, 238, 238, 296}, + {3}, + {140, 173, 241, 320, 314, 315, 304, 295, 329, 359, 369, 357, 388, 354, 359, 396}, + {248, 300, 339, 344, 360, 350, 363, 361, 368, 391, 431, 433, 406, 400, 377, 467}, + {3}, + {141, 180, 213, 223, 232, 234, 242, 240, 250, 253, 268, 255, 245, 235, 227, 200}, + {178, 205, 259, 258, 273, 285, 275, 289, 299, 300, 310, 320, 335, 329, 316, 269}, +}; + +/* An 16-by-33 matrix in Scale = 32768.00f */ +const Word16 inv_sigma_MSLVQ_fx[][16] = +{ + {32767}, + {32767}, + {783, 746, 523, 453, 416, 397, 384, 378, 378, 386, 384, 310, 256, 477, 1273, 1935}, + {670, 647, 461, 452, 440, 421, 412, 405, 410, 440, 468, 369, 275, 321, 883, 1305}, + {679, 682, 477, 426, 405, 385, 368, 357, 362, 385, 401, 308, 245, 388, 942, 1231}, + {383, 395, 329, 309, 307, 307, 322, 329, 335, 338, 337, 278, 256, 213, 989, 2243}, + {32767}, + {32767}, + {740, 628, 382, 332, 322, 305, 306, 292, 276, 259, 261, 258, 240, 240, 223, 253}, + {530, 469, 346, 338, 341, 323, 326, 314, 302, 306, 304, 290, 271, 272, 269, 274}, + {576, 576, 378, 327, 322, 302, 289, 278, 264, 268, 259, 238, 213, 206, 202, 210}, + {386, 370, 292, 277, 266, 271, 284, 276, 276, 275, 264, 257, 236, 262, 275, 300}, + {32767}, + {32767}, + {435, 389, 296, 262, 244, 233, 223, 205, 203, 188, 175, 172, 167, 180, 184, 175}, + {365, 352, 268, 254, 251, 255, 247, 235, 237, 234, 214, 208, 190, 183, 221, 169}, + {363, 302, 276, 261, 241, 237, 229, 226, 225, 211, 191, 186, 198, 203, 220, 188}, + {318, 292, 230, 218, 218, 225, 219, 225, 213, 208, 187, 192, 208, 195, 209, 143}, + {374, 281, 320, 318, 325, 344, 322, 296, 268, 284, 305, 301, 322, 294, 293, 210}, + {204, 267, 279, 253, 250, 245, 235, 205, 195, 203, 231, 231, 248, 252, 266, 204}, + {616, 312, 245, 229, 207, 195, 204, 199, 189, 180, 193, 198, 256, 340, 356, 349}, + {471, 194, 275, 313, 325, 333, 332, 342, 335, 336, 342, 328, 347, 307, 280, 226}, + {241, 251, 250, 246, 250, 254, 245, 197, 166, 116, 107, 128, 83, 97, 242, 339}, + {266, 274, 259, 274, 279, 302, 304, 292, 221, 213, 257, 252, 247, 219, 227, 134}, + {355, 336, 348, 363, 348, 342, 353, 379, 391, 442, 462, 472, 458, 196, 456,1518}, + {744, 443, 233, 269, 253, 257, 283, 313, 308, 298, 262, 305, 383, 413, 469, 585}, + {308, 330, 343, 353, 347, 356, 392, 387, 376, 322, 359, 435, 448, 458, 482, 514}, + {756, 261, 305, 384, 394, 406, 415, 409, 409, 372, 352, 403, 438, 448, 498, 552}, + {219, 257, 280, 293, 289, 288, 304, 335, 325, 289, 195, 161, 211, 275, 306, 312}, + {550, 380, 309, 288, 244, 271, 272, 326, 332, 328, 248, 171, 168, 421, 468, 781}, + {371, 355, 356, 350, 336, 353, 368, 376, 369, 348, 269, 269, 281, 268, 199, 233}, + {380, 353, 392, 381, 342, 344, 362, 379, 399, 403, 420, 367, 228, 195, 789,1184}, + {337, 324, 314, 297, 301, 305, 335, 354, 414, 401, 425, 301, 154, 165, 690, 927}, + {438, 337, 327, 357, 363, 365, 394, 390, 400, 340, 295, 354, 392, 399, 421, 462}, +}; + +/* An 16-by-19 matrix in Scale = 32768.00f */ +const Word16 inv_sigma_p_fx[][16] = +{ + {552, 513, 469, 494, 486, 478, 492, 496, 496, 482, 480, 388, 339, 276, 743, 760}, + {640, 492, 472, 478, 482, 471, 470, 471, 623, 504, 501, 477, 459, 425, 421, 408}, + {1001, 939, 696, 589, 545, 480, 456, 451, 444, 462, 472, 424, 342, 441, 1567, 3002}, + {609, 534, 419, 432, 444, 403, 406, 407, 391, 425, 452, 378, 269, 278, 818, 1939}, + {32767}, + {574, 507, 459, 432, 425, 415, 440, 442, 449, 450, 490, 443, 299, 270, 1377, 2451}, + {591, 499, 456, 457, 449, 441, 448, 446, 443, 436, 420, 397, 364, 342, 496, 475}, + {482, 512, 498, 426, 280, 225, 422, 1411, 404, 404, 402, 385, 364, 342, 355, 361}, + {917, 831, 572, 507, 482, 430, 406, 399, 385, 365, 364, 344, 313, 309, 311, 335}, + {533, 436, 371, 399, 398, 368, 367, 348, 343, 342, 338, 319, 306, 305, 311, 334}, + {32767}, + {641, 523, 458, 434, 415, 410, 412, 395, 397, 394, 386, 381, 366, 392, 413, 419}, + {449, 380, 364, 366, 354, 362, 362, 356, 337, 323, 293, 296, 336, 352, 353, 283}, + {32767}, + {601, 485, 348, 262, 267, 266, 276, 285, 255, 233, 227, 235, 216, 237, 233, 212}, + {338, 279, 247, 244, 233, 239, 231, 232, 228, 215, 194, 194, 207, 210, 222, 180}, + {32767}, + {594, 466, 394, 376, 362, 358, 346, 350, 336, 332, 313, 329, 343, 358, 370, 419}, + {471, 409, 323, 325, 308, 295, 305, 290, 281, 280, 271, 262, 251, 255, 266, 312}, +}; + +const Word16 CNG_details_codebook_fx[64][NUM_ENV_CNG]= /* Q6 */ +{ + {443,547,613,547,510,471,540,479,586,535,565,611,532,500,462,551,498,463,446,484}, + {600,499,472,537,633,654,641,646,674,677,687,693,693,690,688,700,693,696,640,571}, + {529,537,501,582,537,474,505,491,521,545,561,591,566,609,570,608,636,655,649,524}, + {648,690,689,684,693,599,668,714,663,675,524,519,726,658,673,696,654,715,708,668}, + {623,630,660,656,686,688,637,666,630,555,470,468,464,445,502,583,615,545,605,592}, + {659,668,669,625,662,700,700,693,702,702,688,677,654,584,525,492,446,477,634,615}, + {634,648,656,552,520,557,662,659,572,617,691,683,684,666,673,695,682,698,680,623}, + {756,743,734,709,730,757,746,722,484,552,779,688,686,610,616,749,758,694,745,729}, + {549,568,556,625,683,619,609,667,663,684,709,649,691,668,594,511,525,617,542,684}, + {550,467,533,760,739,692,773,756,743,770,765,791,779,784,775,792,759,577,642,553}, + {658,674,656,651,670,582,593,520,467,470,522,589,600,596,587,631,652,679,645,669}, + {788,765,787,797,785,799,787,786,780,692,641,550,501,513,726,747,670,687,734,773}, + {641,654,668,673,665,682,689,684,697,665,664,593,544,494,458,537,622,650,635,635}, + {706,753,762,716,748,762,788,792,785,788,799,777,782,766,760,710,704,503,519,735}, + {748,775,784,635,717,504,539,640,764,778,681,721,791,786,787,780,780,770,774,781}, + {752,516,624,780,713,753,569,548,770,784,749,740,690,755,776,748,744,730,767,698}, + {453,471,516,517,561,653,659,616,629,608,682,698,679,681,645,587,594,522,499,469}, + {617,534,506,615,782,792,754,771,740,787,791,776,782,787,793,788,775,778,651,736}, + {661,593,490,495,491,495,554,656,658,611,628,660,680,677,698,678,673,699,687,679}, + {798,793,786,795,799,772,771,696,624,557,507,545,724,757,747,770,780,785,793,784}, + {703,695,703,714,697,701,697,631,598,498,475,451,503,611,648,664,664,683,679,688}, + {744,672,659,762,785,745,757,761,761,767,722,757,761,737,699,471,582,770,724,756}, + {775,746,535,680,541,513,697,723,743,744,769,741,741,738,769,772,779,743,714,724}, + {767,771,697,756,766,752,710,477,602,783,746,766,692,708,783,782,761,778,787,785}, + {483,588,700,665,665,640,650,717,699,707,692,698,700,692,668,650,609,610,540,484}, + {507,618,788,766,754,692,709,785,788,770,793,785,799,784,767,776,789,759,761,495}, + {709,712,706,678,661,604,503,480,653,664,664,639,621,675,695,689,704,681,711,709}, + {788,740,770,768,771,776,732,749,739,764,714,492,544,783,714,708,717,559,739,768}, + {758,771,789,779,777,799,791,785,779,779,752,675,718,510,501,600,727,750,752,758}, + {759,765,676,658,774,767,737,749,769,784,778,738,755,769,788,756,473,530,777,725}, + {669,665,721,653,499,774,780,781,767,561,690,747,722,779,757,727,764,745,770,736}, + {731,768,745,775,783,782,715,741,786,673,766,777,764,730,773,769,774,781,778,764}, + {557,505,545,604,660,672,604,596,580,612,587,556,546,597,530,494,437,480,546,555}, + {560,588,510,495,606,720,718,742,756,755,767,774,776,778,772,772,776,776,754,592}, + {680,644,620,612,516,477,471,499,502,598,664,588,656,682,689,671,668,672,682,692}, + {757,778,781,799,775,750,799,758,789,774,489,579,799,739,774,723,686,788,787,778}, + {705,685,654,680,672,680,657,579,574,619,639,518,482,545,665,587,540,599,606,651}, + {729,767,767,773,783,778,793,773,784,779,757,768,686,654,679,564,483,549,490,522}, + {725,693,715,588,522,629,721,647,697,684,614,725,708,674,715,729,717,725,689,738}, + {797,783,795,797,782,757,636,624,508,517,703,750,746,757,772,771,774,790,779,799}, + {556,591,652,692,728,712,698,688,704,718,728,717,713,693,716,558,490,540,620,678}, + {532,617,777,775,763,789,768,785,778,791,792,792,793,777,781,724,551,665,540,509}, + {710,697,706,717,673,679,620,581,546,474,562,684,680,675,660,656,702,680,701,708}, + {771,793,788,787,794,791,792,783,791,792,733,770,532,525,692,761,777,753,734,728}, + {724,695,678,652,695,735,697,712,714,721,696,710,569,581,570,522,642,704,748,726}, + {796,754,785,782,732,814,803,794,799,790,810,806,794,797,756,745,749,506,741,779}, + {793,767,785,780,724,648,488,747,784,771,793,740,759,805,794,796,795,795,801,806}, + {787,508,640,775,722,792,774,705,781,801,774,800,786,806,808,783,795,797,784,782}, + {654,649,601,597,594,667,646,662,615,623,651,671,669,674,682,653,624,484,473,665}, + {790,765,479,527,746,728,770,753,721,774,794,802,789,782,803,795,764,804,779,776}, + {738,699,642,509,515,501,466,614,702,612,683,720,687,717,704,739,714,733,721,718}, + {778,795,791,786,758,783,783,743,744,527,554,789,762,767,722,722,777,788,776,782}, + {694,696,700,696,709,710,696,689,674,662,581,538,496,637,644,681,679,671,689,704}, + {776,788,742,796,779,756,788,789,782,798,795,804,771,753,571,611,504,545,593,779}, + {799,717,747,682,487,573,766,774,775,762,711,802,799,796,790,787,802,789,773,786}, + {795,797,790,804,788,791,774,706,532,770,786,743,789,708,755,785,804,803,807,770}, + {568,722,738,680,713,703,693,749,703,705,740,720,712,631,621,727,730,722,574,612}, + {626,762,734,770,759,750,792,775,790,792,788,786,791,767,782,778,794,745,504,544}, + {774,784,779,753,654,560,530,532,555,699,742,695,716,767,770,772,778,780,779,782}, + {781,781,790,783,792,798,787,792,765,740,701,537,564,773,767,756,786,797,789,801}, + {738,717,799,794,772,784,774,790,788,748,789,769,768,763,504,587,783,751,784,732}, + {776,789,763,772,800,786,802,787,805,799,776,773,792,761,750,702,532,745,807,735}, + {765,778,764,484,607,791,757,760,700,687,789,777,779,783,768,791,778,757,784,770}, + {800,825,775,782,821,679,805,824,752,824,796,785,829,817,824,803,814,807,762,779} +}; + +const Word16 interpol_frac_mid_fx[NB_SUBFR*3] = { 16384, 16384, 0, + 0, 32767, 0, + 0, 16384, 16384, + 0, 0, 32767 + }; + +const Word16 interpol_frac_mid_16k_fx[NB_SUBFR16k*3] = { 18022, 14746, 0, + 4915, 27853, 0, + 0, 24576, 8192, + 0, 11469, 21299, + 0, 0, 32767 + }; + + +const Word16 pi0_fx[] = {28,1,70,8,8,28,168,28,1,280,28,56,8,56,420,56, 70, 56,420, 56, 280, 56, 168, 28, 560, 168,336,28,280,28,8 + ,280,70, 8, 1120, 8, 8, 280, 168, 56, 420, 336, 840, 28, 168, 1, 168, 420, 168 + }; + +const Word16 pl_par_fx[] = /* 1 if even number of signs */ +{ + 0, 1, 0, 0, -1, 0, 0, 1, 0, 0, + 0, -1, 1, 0, 0, 0, 1, -1, 0, 0, + 0, -1, 1, 0, 0, 0, 0, 1, -1, 1, -1, 0, + 0, 0, 0, 0, -1, 1, -1, 1, 0, 0, 0, 0, 0, 1, -1, 1, -1 +}; +const Word16 no_vals_fx[NO_LEADERS]= {2,1,2,2,2,2,3,2,1,3,2,2,2,3,3,3,2,3,3,2,3,2,3,2,3,3,4,2,3,2,2,3,2,2,4,2,2,3,3,3,3,4,4,2,3,1,3,3,3}; + +const Word16 no_vals_ind_fx[NO_LEADERS][MAX_NO_VALS]= +{ + {2,6,0,0}, + {8,0,0,0}, + {4,4,0,0}, + {1,7,0,0}, + {1,7,0,0}, + {6,2,0,0}, + {1,2,5,0}, + {2,6,0,0}, + {8,0,0,0}, + {1,4,3,0}, + {2,6,0,0}, + {3,5,0,0}, + {1,7,0,0}, + {1,6,1,0}, + {2,2,4,0}, + {1,1,6,0}, + {4,4,0,0}, + {1,1,6,0}, + {2,4,2,0}, + {3,5,0,0}, + {1,3,4,0}, + {5,3,0,0}, + {1,2,5,0}, + {2,6,0,0}, + {3,2,3,0}, + {1,5,2,0}, + {1,1,1,5}, + {6,2,0,0}, + {1,3,4,0}, + {2,6,0,0}, + {1,7,0,0}, + {3,4,1,0}, + {4,4,0,0}, + {1,7,0,0}, + {1,1,3,3}, + {1,7,0,0}, + {7,1,0,0}, + {1,4,3,0}, + {2,1,5,0}, + {1,1,6,0}, + {4,2,2,0}, + {1,1,5,1}, + {1,2,1,4}, + {2,6,0,0}, + {1,2,5,0}, + {8,0,0,0}, + {1,5,2,0}, + {2,2,4,0}, + {1,2,5,0} +}; + +const Word16 C_VQ_fx[LATTICE_DIM+1][LATTICE_DIM+1]= +{ + {1,0,0,0,0,0,0,0,0}, + {1,1,0,0,0,0,0,0,0}, + {1,2,1,0,0,0,0,0,0}, + {1,3,3,1,0,0,0,0,0}, + {1,4,6,4,1,0,0,0,0}, + {1,5,10,10,5,1,0,0,0}, + {1,6,15,20,15,6,1,0,0}, + {1,7,21,35,35,21,7,1,0}, + {1,8,28,56,70,56,28,8,1} +}; + +const Word16 vals_fx[NO_LEADERS][MAX_NO_VALS]= /*Q1 */ +{ + {2, 0, 0, 0}, + {1, 0, 0, 0}, + {2, 0, 0, 0}, + {4, 0, 0, 0}, + {3, 1, 0, 0}, + {2, 0, 0, 0}, + {4, 2, 0, 0}, + {3, 1, 0, 0}, + {2, 0, 0, 0}, + {4, 2, 0, 0}, + {4, 0, 0, 0}, + {3, 1, 0, 0}, + {5, 1, 0, 0}, + {4, 2, 0, 0}, + {4, 2, 0, 0}, + {6, 2, 0, 0}, + {3, 1, 0, 0}, + {5, 3, 1, 0}, + {4, 2, 0, 0}, + {4, 0, 0, 0}, + {6, 2, 0, 0}, + {3, 1, 0, 0}, + {5, 3, 1, 0}, + {4, 2, 0, 0}, + {4, 2, 0, 0}, + {6, 2, 0, 0}, + {6, 4, 2, 0}, + {3, 1, 0, 0}, + {5, 3, 1, 0}, + {5, 1, 0, 0}, + {7, 1, 0, 0}, + {4, 2, 0, 0}, + {4, 0, 0, 0}, + {6, 2, 0, 0}, + {6, 4, 2, 0}, + {8, 0, 0, 0}, + {3, 1, 0, 0}, + {5, 3, 1, 0}, + {5, 3, 1, 0}, + {7, 3, 1, 0}, + {4, 2, 0, 0}, + {6, 4, 2, 0}, + {6, 4, 2, 0}, + {6, 0, 0, 0}, + {8, 2, 0, 0}, + {3, 0, 0, 0}, + {5, 3, 1, 0}, + {5, 3, 1, 0}, + {7, 3, 1, 0}, +}; + +/* An 6-by-128 matrix in Scale = 2048.00f */ +const Word16 scales_fx[][6] = +{ + {3129, 0, 0, 3138, 0, 0, }, /* 14 */ + {3287, 0, 0, 3138, 0, 0, }, /* 15 */ + {2611, 5034, 0, 3138, 0, 0, }, + {2611, 5034, 0, 3340, 0, 0, }, + {2165, 3674, 5931, 2363, 3809, 6281, }, + {1898, 2986, 4745, 2116, 3668, 7045, }, /* 28 */ /* mode 0 UV WB*/ + {2630, 5480, 0, 2972, 0, 0, }, + {2802, 0, 0, 2869, 5073, 0, }, + {1763, 2546, 3723, 2515, 4559, 21109, }, + {2195, 3961, 7440, 2501, 6017, 21961, }, + {1841, 2902, 1386, 2116, 3762, 22309, }, + {1700, 2710, 1288, 1866, 3246, 20660, }, /* 32 */ /* mode 1 UV NB*/ + + + {3222, 0, 0, 3391, 0, 0, }, + {2537, 4923, 0, 3187, 0, 0, }, + {2161, 3482, 9091, 3391, 0, 0, }, + {2560, 4923, 8462, 2775, 4835, 0, }, + {2163, 3656, 9263, 2699, 5296, 0, }, + {2040, 3082, 6871, 2427, 3637, 5587, }, + {1903, 2841, 6875, 2212, 3484, 5908, }, + {1888, 3058, 6900, 2212, 3484, 5908, }, + {1888, 3058, 6900, 2183, 3469, 6420, }, + {1888, 3058, 6900, 1970, 3174, 8081, }, + {1528, 2269, 5876, 1964, 3033, 8002, }, + {1577, 2445, 5782, 1858, 2871, 4334, }, + + {1532, 2259, 5870, 2421, 1661, 6824, }, /* 34 */ + + {1386, 1972, 4356, 1487, 2216, 4514, }, /* 37 */ /* mode 2 V WB*/ + {3357, 0, 0, 2494, 4426, 0, }, + {2634, 5009, 0, 2888, 0, 0, }, + {2224, 3539, 7696, 2494, 4426, 0, }, + {2120, 3226, 9861, 2494, 4426, 0, }, + {1974, 3140, 10121, 2494, 4426, 0, }, + {1722, 2454, 4059, 2494, 4426, 0, }, + {1839, 2658, 4473, 2490, 5456, 0, }, + {1722, 2533, 4581, 2038, 3394, 5808, }, + + {1427, 2009, 4184, 1915, 3082, 1350, }, + {1370, 1862, 2720, 2017, 1339, 3914, }, /* 37 */ /* mode 3 V NB */ + + {2482, 3885, 0, 0, 0, 0, }, + {3346, 0, 0, 3418, 0, 0, }, + {2638, 4962, 0, 3418, 0, 0, }, + {2482, 3885, 0, 3418, 0, 0, }, + {2218, 3617, 6502, 3418, 0, 0, }, + {2124, 3295, 8659, 3418, 0, 0, }, + {2243, 3398, 5562, 2693, 5132, 0, }, + {1927, 2839, 4549, 2693, 5132, 0, }, + {1860, 2675, 3893, 2703, 5372, 0, }, + {2202, 3619, 1618, 2703, 5372, 0, }, + {2093, 3135, 1554, 2273, 3594, 5313, }, + {2202, 3619, 1618, 2238, 3895, 6173, }, + {1829, 3015, 1382, 2259, 3625, 5820, }, + {1864, 3170, 1403, 2114, 3381, 5147, }, + {1692, 2572, 1294, 2009, 3158, 4540, }, /* 32 (31.995) */ /* G WB*/ + {2425, 3707, 5655, 0, 0, 0, }, + {3299, 0, 0, 3314, 0, 0, }, + {2425, 3707, 5655, 3174, 0, 0, }, + {2425, 3707, 5655, 3314, 0, 0, }, + {2177, 3557, 6113, 3314, 0, 0, }, + {2208, 3738, 6476, 3009, 4606, 0, }, + {2816, 1874, 4264, 3009, 4606, 0, }, + {1966, 2914, 1434, 2683, 4366, 0, }, + {2302, 1626, 3895, 2628, 4714, 0, }, + {2206, 3537, 1571, 2560, 3996, 6105, }, + {1911, 3013, 1403, 2560, 3996, 6105, }, + {1898, 3277, 1380, 2363, 3637, 5845, }, + {2144, 1479, 3656, 2163, 3363, 5532, }, + {1989, 1409, 3090, 2136, 3543, 6003, }, + {1882, 1356, 2800, 2165, 3703, 6285, }, /* 32 (31.987) */ /* G NB*/ + {3312, 0, 0, 3394, 0, 0, }, + {2611, 4706, 0, 3201, 0, 0, }, + {2679, 4821, 0, 2841, 0, 0, }, + {2644, 4952, 0, 2775, 5003, 0, }, + {2210, 3623, 6169, 2841, 0, 0, }, + {2210, 3623, 6169, 2714, 5233, 0, }, + {1837, 2744, 5333, 2191, 3459, 5175, }, + {1837, 2744, 5333, 1923, 2978, 4266, }, + {1853, 2718, 5323, 2271, 1591, 3492, }, + {1561, 2255, 4831, 1923, 2978, 4266, }, + {1626, 2511, 6513, 2271, 1591, 3492, }, /* 33 */ + /* mode 6 T WB */ + {3336, 0, 0, 2439, 4528, 0, }, + {2615, 5237, 0, 2800, 0, 0, }, + {2216, 3607, 8047, 2439, 4528, 0, }, + {2085, 3144, 5751, 2439, 4528, 0, }, + {1933, 3025, 5659, 2439, 4528, 0, }, + {1864, 3572, 6793, 2439, 4528, 0, }, + {1884, 3375, 6283, 1985, 3447, 8096, }, + {1513, 2275, 5517, 1800, 2890, 4721, }, + {1452, 2114, 5564, 1659, 2550, 3736, }, /* 32 */ /* mode 7 T NB */ + + {1552, 2286, 4022, 2497, 4139, 1634,}, + {1432, 2118, 4051, 2497, 4139, 1634, }, /* 32 */ /* mode 8 G 16k */ + + {1487, 2150, 3779, 2775, 1761, 4516, }, + {1386, 2042, 3418, 2775, 1761, 4516, }, /* 33 (32.983) */ /* T 16k */ + + {3371, 0, 0, 2568, 5036, 0, }, + {2198, 3815, 6617, 3437, 0, 0, }, + {2198, 3815, 6617, 2568, 5036, 0, }, + {1948, 3056, 5112, 2570, 6085, 0, }, + {2351, 3770, 1665, 2570, 6085, 0, }, /* 26 */ + {1233, 1780, 2904, 2589, 1565, 4542, }, /* 36 */ /* mode 10 AUDIO_WB 36 + 4 + 1 */ + + {1747, 3623, 9062, 0, 0, 0, }, + {2071, 3406, 9017, 3232, 0, 0, }, + {2071, 3406, 9017, 2462, 4964, 0, }, + {1804, 3314, 8471, 2462, 4964, 0, }, + {1735, 3668, 9146, 2462, 4964, 0, }, /* 27 */ /* AUDIO_NB */ + {1372, 2277, 4893, 2462, 4964, 0, }, /* 28 */ /* AUDIO_NB */ + {2316, 3717, 1630, 2591, 5722, 0, }, + {1167, 1647, 2451, 2380, 3992, 1491, }, /* 36 */ /* mode 12 AUDIO_WB 16k 15-36 + 4 + 1*/ + {2140, 3248, 7688, 3418, 0, 0, }, + {1802, 2621, 5784, 2251, 3553, 0, }, + {1702, 2488, 5994, 2230, 3498, 5077, }, + {1782, 2718, 5951, 2183, 3521, 5480, }, + + {1581, 2298, 4815, 2961, 1933, 4243, }, + + {1436, 2001, 3559, 1939, 2976, 4264, }, + + {1473, 2091, 3484, 2292, 1626, 3473, }, + + {1311, 1810, 3547, 1546, 2232, 3170, }, /* 37 (36.995) */ /* VOICED 16k */ + {2494, 1630, 4676, 2642, 6810, 0, }, + {3256, 1710, 9085, 2247, 6287, 0, }, + + {2036, 5360, 0, 2234, 4573, 7080, }, + {1817, 3222, 7256, 2228, 3742, 6281, }, + {1714, 2535, 3897, 2658, 5728, 0, }, + {2331, 5788, 0, 2265, 5726, 8993, }, + {1927, 3955, 9161, 1395, 2593, 4768, }, + {2769, 8872, 0, 1679, 3164, 8550, }, + {2750, 7387, 0, 1759, 2976, 5304, }, + {2474, 5612, 0, 1554, 2540, 4469, }, + {2300, 5603, 0, 1790, 3068, 5296, }, + {1882, 5061, 0, 1260, 2195, 4293, }, + {3170, 9232, 0, 1690, 4461, 8817, }, + {2492, 5935, 0, 1509, 2492, 3953, }, + + {1999, 4485, 11706, 3084, 1315, 8624, }, + {2267, 5315, 0, 2666, 1237, 1802}, /* CNG */ + +};/* An 6-by-146 matrix in Scale = 2048.00f */ +const Word16 scales_p_fx[][6] = +{ + {2998, 4862, 0, 0, 0, 0, }, + {2591, 5251, 0, 3355, 0, 0, }, + {2177, 3488, 5745, 2650, 4819, 0, }, + {2177, 3926, 6273, 2796, 0, 0, }, + {1872, 2892, 4553, 2650, 4819, 0, }, + {1806, 2869, 4919, 2689, 4999, 0, }, + {2777, 1776, 4868, 2191, 3453, 5214, }, + {1733, 2761, 5214, 2204, 3568, 5444, }, + {1731, 2824, 5255, 2087, 3230, 5003, }, + {1548, 2435, 5732, 2220, 3695, 5648, }, + {1546, 2494, 5777, 1933, 2935, 4041, }, + {1483, 2529, 6025, 2570, 1737, 4096, }, + {1407, 2279, 4788, 1747, 2720, 3981, }, + {1327, 2107, 3760, 1749, 2777, 4016, }, + {1327, 2107, 3760, 1407, 2167, 3891, }, /* 39 (38.488) */ /* V WB*/ /* 14 */ + {3303, 0, 0, 0, 0, 0, }, + {2595, 5069, 0, 3316, 0, 0, }, + {2077, 3338, 5046, 2632, 4405, 0, }, + {1829, 2847, 4739, 3000, 4708, 0, }, + {1905, 2869, 4403, 2621, 4616, 0, }, + {1829, 2847, 4739, 2613, 4518, 6111, }, + {1829, 2847, 4739, 2122, 3371, 5061, }, + {1755, 2738, 5046, 2136, 3543, 5376, }, + {1567, 2497, 3181, 2122, 3371, 5061, }, + {1616, 2720, 3383, 2154, 3654, 5542, }, + {1565, 2507, 3185, 1884, 2955, 4168, }, + {1358, 2173, 2535, 2824, 1839, 3996, }, + {1378, 2261, 2675, 2578, 1696, 4002, }, + {1364, 2193, 2558, 1645, 2542, 3541, }, + {1348, 2128, 2486, 1946, 1333, 2927, }, /* 39 (38.512) */ /* V NB*/ /* 29 */ + {3277, 0, 0, 3181, 0, 0, }, + {2322, 4067, 6748, 3181, 0, 0, }, + {2021, 3662, 5446, 3373, 0, 0, }, + {1841, 3281, 5282, 3373, 0, 0, }, + {1632, 2650, 4383, 3373, 0, 0, }, + {1632, 2650, 4383, 2734, 4557, 0, }, + {1518, 2357, 3719, 2734, 4557, 0, }, + {1632, 2650, 4383, 2429, 3957, 0, }, + {1518, 2357, 3719, 2384, 3734, 5671, }, + {1450, 2306, 4000, 2204, 3543, 5687, }, + {1352, 2148, 3217, 2204, 3543, 5687, }, + {1356, 2101, 3183, 2200, 3918, 6189, }, + {1352, 2148, 3217, 2947, 1896, 4364, }, + {1290, 1978, 3117, 2687, 1804, 4520, }, + {1264, 1886, 2963, 2114, 3172, 1548, }, /* 35 (34.994) */ /* G WB*/ /* 44 */ + {3267, 0, 0, 3076, 0, 0, }, + {2300, 3985, 7643, 3076, 0, 0, }, + {2116, 4250, 8886, 2906, 5009, 0, }, + {2017, 3672, 12216, 2623, 4760, 0, }, + {1804, 3289, 14326, 2906, 5009, 0, }, + {1729, 3240, 14377, 2623, 4760, 0, }, + {1616, 3113, 14752, 2623, 4760, 0, }, + {1780, 3168, 14326, 2109, 3592, 6353, }, + {1673, 3056, 14582, 2109, 3592, 6353, }, + {1546, 2830, 14608, 2109, 3592, 6353, }, + {1446, 2693, 14797, 2109, 3592, 6353, }, + {1411, 2654, 14930, 2081, 3840, 6633, }, + {1430, 2611, 14764, 1872, 3170, 4983, }, + {1391, 2693, 14930, 2517, 3779, 1665, }, + {1391, 2693, 14930, 2433, 1581, 4004, }, /* 35 (34.952) */ /* G NB*/ /* 59 */ + + {2070, 3639, 5652, 3305, 0,0,}, + {1747, 2830, 4231, 2550, 5487, 0,}, + {2472, 1593, 4522, 2550, 5487, 0,}, + {2472, 1593, 4522, 2075, 3752, 6253}, + {2472, 1593, 4522, 2908, 1786, 4772,}, + {1075, 1577, 2198, 1669, 2533, 1161}, /* 40 (39.990) */ /* AUDIO_WB */ /* 65 */ + + {2191, 3668, 7993, 3275, 0, 0, }, + {1679, 2492, 4278, 2570, 4690, 0, }, + {1597, 2394, 5110, 2570, 4690, 0, }, + {2202, 1481, 4835, 2273, 4016, 7150, }, + + {1415, 2107, 4786, 2118, 3668, 8200, }, /* 31 */ /*AUDIO_NB */ /* 70 */ + {1374, 2204, 5337, 1956, 3168, 5149, }, /* 32 */ /*AUDIO_NB */ /* 71 */ + {2425, 4336, 1589,3420, 2165, 1380, }, + {1067, 1530, 2116, 1630, 2730, 1110,}, /* 40 */ /* mode AUDIO_WB 16k */ /* 73*/ + + {3439, 0, 0, 2626, 5061, 0, }, + {2228, 3787, 6543, 3455, 0, 0, }, + {2228, 3787, 6543, 2626, 5061, 0, }, + {2306, 3459, 1618, 2626, 5061, 0, }, + {1905, 2830, 1397, 2626, 5061, 0, }, + {2284, 1626, 3793, 2623, 6212, 0, }, + {1720, 2818, 1276, 1638, 2900, 8724, }, /* 36 (35.998) */ /* INACTIVE NB */ + {1640, 2351, 3690, 0, 0, 0, }, + {2230, 3711, 6496, 3434, 0, 0, }, + {2230, 3899, 6597, 3115, 5396, 0, }, + {1731, 2482, 3961, 2689, 4954, 0, }, + {1595, 2243, 3482, 2689, 4954, 0, }, + {1481, 2079, 3408, 2689, 4954, 0, }, + {1829, 1335, 2945, 2204, 1475, 3674, }, /* 36 (35.929) */ /* INACTIVE WB*/ + {2783, 4723, 0, 3418, 0, 0, }, + {2206, 3946, 7262, 3418, 0, 0, }, + {2206, 4162, 7328, 2927, 5552, 0, }, + {1706, 2566, 4311, 2628, 5235, 0, }, + {1589, 2359, 3805, 2628, 5235, 0, }, + {1473, 2183, 3547, 2628, 5235, 0, }, + {1927, 1333, 3205, 1479, 2437, 3973, }, /* 36 (35.915) */ /* INACTIVE 16k*/ + + {2646, 5077, 0, 3156, 0, 0, }, + {2462, 3897, 0, 3156, 0, 0, }, + {2105, 3361, 5028, 3375, 0, 0, }, + {2554, 1798, 4770, 3375, 0, 0, }, + {1767, 2781, 5165, 3375, 0, 0, }, + {1673, 2503, 4116, 2200, 3656, 5597, }, + {1669, 1253, 2623, 2161, 3531, 6046, }, /* 32 (31.990) */ /* UNVOICED NB*/ + + {3164, 0, 0, 3170, 0, 0, }, + {3359, 0, 0, 3170, 0, 0, }, + {2636, 5630, 0, 3170, 0, 0, }, + {2636, 5630, 0, 3387, 0, 0, }, + {2437, 4149, 0, 3387, 0, 0, }, + {1907, 2986, 5018, 2650, 5616, 0, }, + {1796, 2859, 5605, 2214, 3719, 6881, }, /* 28 (27.996) */ /* UNVOICED WB */ + {2316, 3351, 0, 2808, 0, 0, }, + {1913, 2615, 1491, 2370, 3475, 0, }, + {1706, 2380, 1348, 2357, 3455, 0, }, + {1538, 2114, 1225, 2357, 3455, 0, }, + {1452, 2058, 1167, 2171, 3629, 5569, }, + {1528, 2050, 1231, 2056, 3693, 5923, }, + {1522, 2048, 1227, 1917, 3811, 5886, }, + {1587, 1257, 2124, 1630, 2671, 3901, }, /* 39 (38.301) */ /* VOICED 16k */ + {1831, 2742, 5220, 2679, 5327, 0, }, + {1475, 2073, 3273, 3097, 1896, 4377, }, + {1395, 1993, 3377, 2828, 1794, 4360, }, + {1401, 1974, 3359, 2392, 3637, 1612, }, + {1368, 1915, 3176, 2081, 3109, 1458, }, + {1350, 1866, 2918, 2738, 1821, 1315, }, + {1350, 1866, 2918, 1718, 2636, 1243, }, /* 37 (36.989) */ /* GENERIC 16k*/ + {3344, 0, 0, 3455, 0, 0, }, + {2204, 3666, 6025, 3455, 0, 0, }, + {1708, 2517, 3871, 3455, 0, 0, }, + {1921, 2875, 4409, 2675, 5386, 0, }, + {2744, 1815, 4751, 2675, 5386, 0, }, + {1706, 2560, 3908, 2675, 5386, 0, }, + {1706, 2484, 3836, 2304, 3766, 5773, }, + {1567, 2380, 3461, 2097, 3559, 5812, }, + {1485, 2150, 3668, 3031, 1888, 6357, }, + {1458, 2073, 3172, 3060, 1849, 6889, }, + {1350, 1898, 2779, 3060, 1849, 6889, }, + {1683, 1257, 2638, 1864, 3090, 4618, }, + {1722, 1278, 2617, 2378, 1561, 3703, }, + {1716, 1274, 2593, 2212, 1456, 3502, }, + {1704, 1268, 2611, 1921, 2929, 1319, }, /* 37 (36.971) */ /* GENERIC 12.8k MA*/ + {1810, 2763, 5263, 2691, 5343, 0, }, + {1456, 2085, 3308, 3035, 1886, 7027, }, + + {1391, 1995, 3398, 1942, 3172, 7062, }, + + {1702, 1266, 3033, 1911, 3101, 4731, }, + {1671, 1249, 2871, 2920, 1796, 4639, }, + {1612, 2574, 1221, 1759, 2963, 4979, }, + {1612, 2574, 1221, 2265, 1505, 3398}, /* 37 (36.993) */ /* AUDIO 16k */ + +}; + + + +/*-----------------------------------------------------------------* + * BC-TCVQ frame-end quantization tables (BC-TCVQ is used in Voiced mode for 16kHz isf) + *-----------------------------------------------------------------*/ +const Word16 NTRANS[4][NUM_STATE] = {{0,2,4,6,8,10,12,14,0,2,4,6,8,10,12,14}, /* indices of previous state of first branche */ + {1,3,5,7,9,11,13,15,1,3,5,7,9,11,13,15}, /* indices of previous state of second branches */ + {4,2,1,3,0,2,1,3,2,0,3,1,7,0,3,1}, /* indices of previous subset of first branch */ + {2,0,3,6,2,0,3,1,0,2,1,3,0,2,1,5} /* indices of previous subset of second branch */ +}; + +const Word16 NTRANS2[4][NUM_STATE] = {{0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7}, + {8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15}, + {4,2,2,0,1,3,3,6,0,2,2,0,1,3,3,1}, + {2,0,0,2,3,1,1,3,7,0,0,2,3,1,1,5} +}; + +/* BC-TCQ Bit Allocations */ +const Word16 BC_TCVQ_BIT_ALLOC_40B[M/2+4] = {1, 4, 5,5,4,4, 2,2,2,2, 5,4 }; /*1+39bit*/ + +const Word16 FixBranch_tbl[4][4][N_STAGE_VQ - 4] = +{ + {{0, 0, 0, 0}, {1, 0, 0, 0}, {0, 1, 0, 0}, {1, 1, 0, 0}}, /* incase of initial state 0 */ + {{0, 0, 1, 0}, {1, 0, 1, 0}, {0, 1, 1, 0}, {1, 1, 1, 0}}, /* incase of initial state 4 */ + {{0, 0, 0, 1}, {1, 0, 0, 1}, {0, 1, 0, 1}, {1, 1, 0, 1}}, /* incase of initial state 8 */ + {{0, 0, 1, 1}, {1, 0, 1, 1}, {0, 1, 1, 1}, {1, 1, 1, 1}} /* incase of initial state 12 */ +}; + +const Word16 AR_IntraCoeff_fx[N_STAGE_VQ-1][2][2] = /* Q15 */ +{ + {{-9584, 22162}, {-13849, 7127}}, + {{ 1604, 16400}, { 2861, 9414}}, + {{ 6537, 16475}, { 3498, 13792}}, + {{ 7879, 14434}, { 7021, 12992}}, + {{ 6329, 16215}, { 5200, 10052}}, + {{ 3062, 12146}, { 2147, 4857}}, + {{ 1226, 11040}, { -794, 6137}} +}; +const Word16 SN_IntraCoeff_fx[N_STAGE_VQ-1][2][2] = /* Q15 */ +{ + {{-14822, 26501}, {-17180, 10012}}, + {{ 317, 19858}, { -432, 13799}}, + {{ 4747, 22069}, { 2653, 19016}}, + {{ 6823, 20747}, { 7077, 19154}}, + {{ 1665, 25161}, { 2519, 13654}}, + {{ 166, 18043}, { -221, 9732}}, + {{ -781, 20026}, { -5332, 18882}} +}; +const Word16 scale_ARSN_fx[M] = /* Q14 */ +{ + 29994, 30153, 29506, 28534, 28246, 28618, 26388, 27029, + 25726, 25474, 25797, 26540, 25613, 24968, 25880, 25584 +}; +const Word16 scale_inv_ARSN_fx[M] = /* Q15 */ +{ + 17898, 17806, 18196, 18815, 19005, 18760, 20342, 19864, + 20870, 21076, 20811, 20228, 20962, 21502, 20745, 20985 +}; +const Word16 AR_TCVQ_CB_SUB1_fx[2][128][2] = /* x2.65 */ +{ + { + {-435 , -434}, {-233 , 124}, {-381 , 44}, {-274 , -88}, {-332 , -224}, {-563 , -600}, {-332 , 134}, { 53 , -739}, + {-567 , 0}, { 149 , 316}, {-191 , 541}, {-123 , 317}, {-493 , -634}, {-528 , 268}, {-321 , -386}, {-432 , -220}, + {-244 , -230}, { -33 , 454}, {-188 , -642}, {-131 , -215}, {-676 , 263}, {-472 , -403}, {-312 , -159}, {-340 , 297}, + {-121 , -217}, { -6 , 241}, {-203 , -211}, {-126 , -15}, {-734 , -374}, {-458 , -6}, {-297 , -27}, {-307 , -553}, + {-177 , 3}, {-175 , -273}, { 63 , 363}, { 133 , 527}, {-133 , -185}, {-449 , -1206}, {-287 , -281}, {-131 , 869}, + {-100 , -105}, { -75 , -179}, {-141 , 131}, { -32 , 108}, { -81 , 161}, {-446 , -230}, {-283 , -884}, {-128 , -165}, + {-153 , -451}, {-177 , -114}, {-113 , -127}, {-223 , -355}, {-246 , -447}, {-396 , -705}, {-280 , 329}, { -37 , -64}, + {-118 , 208}, { -82 , 64}, {-339 , -367}, { -58 , -132}, {-458 , 644}, {-381 , -543}, {-272 , 557}, { 62 , 75}, + {-307 , -829}, { 310 , 445}, { 73 , -26}, { 95 , 219}, { 223 , 611}, { 279 , 195}, { 430 , 575}, { 424 , 221}, + { -25 , 2}, { 323 , 236}, {-100 , -310}, { 11 , -35}, { 83 , -3}, { 281 , 738}, { 495 , 393}, { 89 , 1284}, + { 32 , 136}, { 29 , 34}, { 491 , 575}, { 105 , -188}, { 15 , -440}, { 285 , 10}, { 516 , -105}, { 313 , 704}, + { -6 , -274}, { -62 , -64}, { -12 , -127}, { 170 , 2387}, { 162 , 196}, { 336 , 413}, { 543 , 210}, { 231 , -70}, + { -2 , 691}, { 98 , 134}, { 25 , 141}, { 261 , 305}, { 312 , -322}, { 336 , 228}, { 561 , 781}, { 766 , 514}, + { -14 , -117}, { 166 , 905}, { -50 , 1}, { 471 , 369}, { 345 , 247}, { 347 , -383}, { 561 , 1128}, { 513 , 1030}, + { 100 , -15}, { 185 , 70}, { 167 , 131}, { 122 , 36}, { 561 , 743}, { 401 , 111}, { 595 , -579}, { 674 , 215}, + { 191 , 189}, { 38 , -78}, { 428 , 0}, { 261 , 136}, { -29 , -99}, { 405 , 308}, { 614 , 574}, {1682 , 1704} + }, + { + {-942 , -168}, {-262 , -361}, { -53 , -171}, {-245 , 472}, {-2145 , -2315}, {-1307 , 1261}, {-870 , -1940}, { -652 , -564}, + {-500 , 447}, {-578 , -198}, {-554 , 111}, { -98 , -84}, {-1315 , 0}, {-1229 , -1618}, {-868 , 230}, { -385 , 1061}, + {-768 , -998}, {-202 , -60}, {-283 , -197}, {-142 , -325}, { -558 , 755}, {-1217 , 456}, {-803 , 766}, { -982 , 743}, + {-415 , -357}, { -28 , 1054}, { 114 , -246}, { 81 , 732}, { -804 , -506}, {-1126 , -112}, {-797 , -132}, { -289 , -204}, + {-347 , -29}, { -37 , -259}, {-142 , -438}, {-249 , 87}, { -874 , 341}, {-1074 , -2635}, {-668 , -1552}, {-1140 , -764}, + {-245 , -513}, { -48 , 526}, { 14 , 395}, {-452 , -646}, { -441 , -969}, { -953 , -1284}, {-645 , -387}, { -736 , 111}, + {-163 , 305}, {-349 , 224}, {-225 , 736}, { 94 , -85}, { -302 , -549}, { -937 , -892}, {-605 , -1089}, { -64 , -101}, + {-161 , -211}, {-392 , -1299}, {-148 , 125}, { 14 , 131}, { -432 , -127}, { -920 , -510}, {-598 , -730}, { 85 , 154}, + { 25 , -155}, { -57 , 238}, { 471 , 276}, { 421 , 680}, { -173 , 316}, { 597 , 1805}, { 906 , -673}, { 538 , 450}, + {-267 , -805}, { 2 , -19}, { 222 , 219}, { 185 , 352}, { -33 , -178}, { 606 , 118}, { 959 , -70}, { 350 , -91}, + { -87 , 42}, { 727 , 905}, { 54 , 33}, { 316 , 44}, { 251 , 15}, { 610 , -122}, { 990 , 1436}, { 82 , 1480}, + { 181 , 535}, { 177 , 130}, { 700 , 565}, { 626 , 331}, { 279 , 551}, { 680 , 707}, {1012 , 727}, { 1057 , 766}, + { -13 , -396}, { 364 , 412}, { 442 , -181}, { 202 , -386}, { 565 , 1397}, { 740 , 2621}, {1080 , 361}, { 1118 , 191}, + { 81 , 266}, { 217 , -130}, { 349 , 1009}, { 678 , -476}, { 1361 , 878}, { 795 , 472}, {1267 , 1034}, { 1040 , 1255}, + { 351 , 201}, { -69 , -633}, { -36 , -1046}, { 808 , 30}, { 1300 , -198}, { 803 , 1026}, {1390 , -326}, { 2291 , 2479}, + { 166 , 13}, { 521 , 84}, { 255 , -717}, { 987 , 448}, { 777 , 220}, { 811 , 208}, {1395 , 2021}, { 1499 , 417} + } +}; +const Word16 AR_TCVQ_CB_SUB2_fx[2][64][2] = +{ + { + {-357 , -53}, {-525 , 167}, {-232 , 255}, {-132 , -359}, {-940 , -221}, { -260 , -1296}, {-1197 , -455}, { -833 , 49}, + {-132 , -1}, {-401 , -280}, {-212 , -217}, {-194 , 92}, {-580 , -710}, { -862 , -750}, { -669 , 430}, { -521 , 719}, + {-620 , -454}, {-239 , 509}, { -15 , -575}, { 389 , 704}, {-890 , 518}, {-1154 , 84}, { -632 , -1023}, { -620 , -1263}, + {-268 , -470}, {-326 , -738}, { 44 , 635}, { 73 , 362}, {-226 , -22}, { -625 , -106}, { -720 , -114}, {-1114 , -1070}, + { 19 , -250}, { 83 , 99}, { 35 , -16}, { 263 , -316}, { 472 , 1096}, { -52 , -328}, { -249 , 971}, { 1387 , 876}, + { 10 , 203}, { 869 , 649}, { 225 , 170}, { 301 , 83}, {1256 , 482}, { 391 , -777}, { 1064 , -320}, { 52 , 1207}, + { 309 , 375}, { 469 , 226}, { 619 , 400}, { 60 , -93}, { 335 , 244}, { 316 , -65}, { -45 , -987}, { 648 , -294}, + { 218 , -66}, {-108 , -133}, { 500 , -19}, { 824 , 163}, { 483 , -443}, { 1297 , 240}, { 1000 , 1205}, { 623 , 1347} + }, + { + {-424 , -965}, { -46 , -194}, { 20 , 298}, {-333 , -278}, {-797 , -522}, {-868 , -60}, { -20 , -140}, {-1085 , -904}, + {-615 , -243}, {-367 , 22}, {-261 , -519}, {-111 , -27}, {-745 , 142}, {-484 , -1519}, { -329 , 13}, {-1077 , 92}, + {-529 , 218}, {-519 , -597}, {-276 , -72}, { -87 , -398}, { -51 , -1257}, {-291 , 409}, { -883 , 611}, { 176 , -401}, + {-134 , -245}, { 37 , 506}, { 23 , -10}, {-225 , 293}, {-913 , -1324}, {-174 , -290}, {-1086 , -386}, { -139 , -78}, + {-123 , 125}, { -26 , -738}, { 113 , -344}, { 175 , 182}, { 754 , -446}, {1207 , 529}, { 932 , 990}, { 136 , 122}, + { 267 , 327}, { 382 , -182}, { 718 , 471}, { 738 , 108}, { 158 , 130}, { 437 , 401}, { 358 , -667}, { 1380 , 836}, + { 184 , -17}, { 435 , 231}, { 403 , 63}, { 151 , -125}, {-109 , -237}, { 692 , -241}, { 1247 , 193}, { 885 , 324}, + {-283 , 661}, { 44 , 105}, { 156 , 911}, { 387 , 588}, { 690 , 1459}, { 664 , 1057}, { -38 , 1455}, { 645 , 909} + } +}; +const Word16 AR_TCVQ_CB_SUB3_fx[4][32][2] = +{ + { + {-487 , 9}, {-456 , -400}, { 96 , 451}, {-239 , 422}, {-685 , -1309}, { 68 , -709}, {-302 , -1185}, { 481 , -287}, + {-287 , -697}, {-194 , 73}, {-159 , -132}, {-161 , -312}, {-809 , 417}, {-860 , -926}, { -26 , -71}, {-1052 , -432}, + { 53 , 134}, { 106 , -140}, { 336 , -18}, { 404 , 735}, {-109 , -516}, { 719 , -65}, { -34 , 1336}, { -171 , 905}, + { 52 , -347}, { 359 , 266}, { 715 , 351}, { 100 , 133}, { 87 , 130}, { 975 , 999}, {1257 , 547}, { 738 , 1372} + }, + { + {-340 , -464}, {-216 , -779}, { 104 , -403}, { -92 , -221}, {-760 , -602}, {-914 , -811}, {-661 , -895}, {-1292 , -290}, + {-317 , 131}, {-575 , -154}, {-228 , -129}, {-257 , 487}, {-286 , -1354}, { -93 , -259}, {-798 , 179}, { -815 , -1368}, + { 215 , 570}, { -2 , 73}, { 545 , 167}, { 250 , 188}, { 76 , 48}, {-943 , 587}, { 379 , 1232}, { 1070 , 112}, + { 117 , -27}, { 389 , -142}, { 18 , 214}, { 735 , 581}, {1098 , 1244}, { 451 , 408}, {1482 , 650}, { -174 , 1160} + }, + { + {-256 , -485}, { -67 , 571}, { -5 , 161}, {-171 , 153}, {-1188 , -440}, {-1081 , 110}, {-641 , -921}, {-232 , -96}, + {-511 , 146}, {-288 , -93}, { 484 , 665}, {-610 , -366}, { -357 , -899}, { -861 , -1088}, { -78 , -105}, {-265 , -845}, + { 15 , 18}, { 79 , -383}, {-205 , -258}, { 306 , 264}, { 28 , 69}, { 34 , 65}, {1170 , 669}, { 133 , 74}, + { 521 , 183}, { 132 , 84}, { 362 , -90}, { 57 , -181}, { 894 , 456}, { 1147 , 742}, { 212 , 274}, { 891 , 262} + }, + { + { 94 , 464}, { 8 , 138}, {-365 , -640}, {-399 , 172}, {-249 , -109}, { -94 , -316}, {-163 , -250}, {-598 , -704}, + {-185 , 36}, {-470 , -199}, { 65 , 241}, {-104 , -362}, {-220 , -801}, {-866 , -66}, {-931 , -400}, {-172 , -132}, + {-148 , -494}, { 465 , 251}, {-179 , -72}, { 439 , 287}, { 824 , 559}, { 33 , 134}, { 59 , 134}, { 88 , 146}, + { 186 , 43}, { 69 , -261}, { 267 , -96}, { 40 , 79}, { 84 , 130}, { 678 , 378}, { 811 , 448}, { 920 , 541} + } +}; +const Word16 SN_TCVQ_CB_SUB1_fx[2][128][2] = +{ + { + {-639 , 105}, {-488 , -449}, {-530 , -811}, {-419 , -634}, {-781 , -1061}, {-585 , 386}, {-501 , -737}, {-489 , -728}, + {-702 , -685}, {-510 , -762}, {-390 , -287}, {-379 , -379}, {-573 , -848}, {-583 , -778}, {-500 , -810}, {-671 , -420}, + {-516 , 802}, {-265 , -492}, {-523 , -568}, {-195 , 2882}, {-600 , -172}, {-568 , -869}, {-497 , 663}, {-643 , -929}, + {-346 , -378}, {-253 , -313}, {-418 , 595}, {-240 , -465}, {-424 , -546}, {-556 , -305}, {-497 , 2453}, {-451 , -235}, + {-452 , -670}, {-368 , -624}, {-379 , -662}, {-305 , -85}, {-549 , 399}, {-546 , -644}, {-484 , -426}, {-387 , -546}, + {-325 , -550}, {-229 , 118}, { -83 , 1004}, {-120 , 465}, {-289 , -222}, {-516 , 155}, {-480 , 1494}, {-415 , 138}, + {-419 , -100}, {-347 , 1091}, {-434 , 76}, {-138 , -291}, {-434 , -719}, {-514 , 945}, {-473 , -26}, {-144 , -320}, + {-376 , 1505}, {-329 , 374}, {-316 , -504}, { -58 , -6}, {-270 , -466}, {-507 , -540}, {-466 , -181}, {-256 , -518}, + {-196 , 726}, { -88 , -356}, {-186 , -394}, { 31 , -201}, { -77 , -319}, { 408 , 136}, { 630 , 680}, { 875 , 1365}, + {-200 , -190}, { 166 , 1289}, { 600 , 1085}, { 276 , 464}, { 567 , 1575}, { 425 , 278}, { 666 , 377}, {1209 , 2344}, + {-182 , -409}, { -95 , -141}, { 65 , 507}, { 127 , 212}, { 340 , 235}, { 481 , 408}, { 721 , 1203}, {1112 , 756}, + { 162 , 362}, { 138 , 753}, {-169 , -128}, { 187 , -32}, { 68 , -93}, { 528 , 2866}, { 786 , 789}, {1247 , 1468}, + {-476 , 2428}, { 20 , 133}, { 2 , -236}, { 426 , 799}, { 393 , 590}, { 532 , 1562}, { 807 , 534}, {1410 , 1051}, + { -14 , -263}, { 83 , -158}, { 158 , -38}, { 616 , 550}, { 845 , 543}, { 536 , 238}, { 912 , 1521}, {1635 , 1344}, + { 115 , -55}, { 263 , 87}, {-126 , 234}, { 376 , 191}, { 459 , 2644}, { 542 , 927}, { 941 , 948}, {1896 , 1528}, + { -19 , 1853}, { 455 , 366}, { 545 , 283}, { 831 , 835}, {1217 , 846}, { 560 , 542}, {1013 , 650}, {1905 , 2343} + }, + { + {-528 , -246}, {-631 , 56}, {-717 , -277}, { -40 , 1327}, {-1011 , -688}, {-827 , -341}, {-656 , -1599}, { -992 , -1559}, + {-450 , 933}, {-540 , 2109}, {-598 , -1267}, {-387 , -512}, {-1100 , -1979}, {-812 , -617}, {-649 , -147}, { -874 , 586}, + {-720 , - 601}, {-281 , -279}, {-578 , 635}, { 169 , 80}, {-1020 , -134}, {-794 , 259}, {-638 , 821}, { -907 , 42}, + {-709 , -1525}, {-482 , 1340}, {-232 , -979}, { 104 , 2314}, { -918 , -1179}, {-790 , 1284}, {-609 , 2259}, { -854 , -978}, + {-624 , 326}, {-194 , 1705}, { -88 , 1060}, { 383 , 1190}, { -415 , 15}, {-789 , -1145}, {-604 , 407}, { -869 , 1136}, + {-503 , -1047}, {-545 , -794}, {-128 , 471}, { 84 , 638}, { -591 , -1509}, {-699 , 1746}, {-600 , -369}, { -784 , 1642}, + {-221 , -668}, {-223 , 261}, { -82 , -446}, {-378 , -1215}, { -741 , 969}, {-689 , -863}, {-569 , -595}, {-1012 , -403}, + {-331 , 518}, {-175 , 787}, {-220 , -3}, { -46 , -841}, { -960 , 297}, {-666 , 68}, {-565 , -1364}, { -265 , -21}, + { 649 , 767}, { 255 , 360}, { 338 , -342}, {1664 , 1627}, { 205 , -226}, { 967 , 31}, {1217 , 928}, { 1697 , 1233}, + { 322 , 1445}, { 320 , 1790}, { 413 , 212}, { 994 , 209}, { 766 , 264}, { 974 , 883}, {1228 , 241}, { 1679 , 801}, + { 75 , 312}, { 754 , 1425}, { 348 , 621}, { 644 , 474}, { 1008 , 763}, {1036 , 2024}, {1354 , 530}, { 1611 , 2129}, + { 162 , 931}, { 883 , 822}, { 990 , 488}, { 615 , -203}, { 1929 , 1234}, {1059 , 1375}, {1382 , 1426}, { 2048 , 1599}, + { 602 , 162}, { 380 , 820}, { 709 , 1064}, {1168 , 1374}, { 549 , 583}, {1062 , 470}, {1415 , 1092}, { 2095 , 2234}, + { 187 , -630}, { 118 , -493}, { 714 , 1787}, {1298 , 673}, { 957 , 1258}, {1082 , 1124}, {1460 , 786}, { 2124 , 1205}, + { 34 , -189}, { 54 , -35}, { 798 , 0}, { 747 , 2378}, { 1420 , 1152}, {1118 , 1673}, {1492 , 2287}, { 2416 , 1618}, + {1159 , 1795}, { 389 , -126}, {1194 , 1003}, {1578 , 1002}, { 1294 , 366}, {1148 , 694}, {1513 , 1791}, { 2746 , 2096} + } +}; +const Word16 SN_TCVQ_CB_SUB2_fx[2][64][2] = +{ + { + {-709 , -609}, {-615 , -1025}, {-430 , -321}, { -44 , 1032}, {-1050 , -32}, {-1028 , -1856}, {-970 , -109}, { -572 , -1426}, + {-568 , 154}, {-142 , -189}, { -80 , 533}, { -38 , -632}, { -391 , 1275}, { -986 , -732}, {-479 , -510}, { -966 , 96}, + {-847 , -1387}, {-895 , 607}, {-368 , -930}, {-386 , 352}, { -290 , 10}, { -833 , 94}, {-528 , 1718}, { -210 , 115}, + {-529 , 857}, {-727 , -230}, {-128 , 31}, { 133 , 76}, { -275 , -777}, { -615 , -1367}, {-339 , -13}, {-1035 , 1231}, + { 448 , 851}, { 599 , 106}, {1103 , 1112}, { 635 , 1249}, { 761 , 774}, { 531 , -71}, { 722 , 473}, { 767 , 413}, + { 258 , 276}, { 346 , -380}, { 487 , 504}, {1114 , 122}, { 882 , 1553}, { 1983 , 1239}, {2126 , 1217}, { 1742 , 1262}, + { 135 , -252}, { 216 , 545}, { 500 , -125}, {1379 , 1910}, { 304 , 76}, { 1509 , 609}, {1543 , 1385}, { 542 , 1831}, + {-240 , -467}, { 771 , 652}, { 913 , 280}, {1307 , 716}, { 1834 , 1029}, { 1049 , 491}, {1624 , 733}, { 2495 , 1944} + }, + { + {-729 , -852}, {-590 , 306}, {-398 , 295}, { -31 , 13}, {-659 , -75}, {-604 , -1229}, {-519 , -675}, {-823 , 47}, + {-755 , -207}, {-818 , -424}, {-705 , -1285}, {-258 , -828}, {-807 , -707}, {-182 , -712}, {-928 , 3}, {-455 , -1149}, + {-844 , 422}, {-596 , -1008}, {-504 , -470}, {-459 , 737}, {-338 , -728}, {-836 , 1028}, {-613 , 1242}, {-609 , 1292}, + {-285 , 36}, {-280 , -424}, { 100 , 126}, {-459 , -135}, {-159 , -151}, {-287 , 190}, { 56 , -262}, {-264 , -317}, + { -8 , 603}, { 63 , 301}, { 537 , -155}, { 289 , 569}, { 193 , -412}, { 864 , 79}, { 686 , 399}, { 842 , 1657}, + { 115 , -211}, { 608 , 340}, { 12 , -650}, { 711 , 1103}, { 101 , 510}, { 358 , -416}, {1266 , 453}, { 532 , 612}, + {-256 , -680}, { 41 , 1163}, { 597 , 793}, { 484 , -61}, { 476 , 256}, {1729 , 1246}, {1209 , 1483}, {1472 , 1113}, + { 389 , 330}, { 176 , -388}, {1025 , 317}, {1049 , 732}, {1480 , 1108}, {1285 , 616}, {1730 , 999}, {2001 , 1669} + } +}; +const Word16 SN_TCVQ_CB_SUB3_fx[4][32][2] = +{ + { + {-377 , -872}, {-407 , 801}, {-611 , -449}, {-397 , -87}, {-476 , -1063}, {-797 , -249}, {-263 , -662}, {-473 , 1508}, + {-716 , 310}, {-616 , -982}, {-742 , -1326}, { 197 , 327}, {-894 , -1556}, {-871 , -1259}, {-708 , -1380}, {-789 , -848}, + { 64 , -313}, { -59 , -547}, { -2 , 67}, { 363 , -167}, { 633 , 1840}, { 232 , -357}, {1243 , 1492}, {1640 , 973}, + { 203 , 518}, { 511 , 946}, { 612 , 241}, {1085 , 724}, { 811 , 326}, { 863 , 241}, { 556 , 534}, {1956 , 2087} + }, + { + {-948 , 28}, {-827 , -1180}, {-348 , -331}, { -36 , 216}, {-1453 , -1162}, {-682 , -639}, {-747 , -1517}, {-704 , 1228}, + {-535 , -988}, {-550 , -109}, {-478 , 580}, {-310 , -699}, {-1308 , -225}, {-775 , -1581}, {-831 , -613}, {-120 , -222}, + { 32 , 200}, { 120 , -221}, { 470 , 466}, { 808 , 313}, { 950 , 711}, { 430 , -576}, {1984 , 1405}, {1645 , 887}, + { 131 , 1148}, { 286 , 508}, { 342 , -236}, {1003 , 1202}, { 317 , -726}, {1493 , 732}, {1336 , 694}, {2382 , 1772} + }, + { + {-874 , -374}, {-237 , 26}, { 15 , 870}, {-710 , 433}, { 40 , -769}, {-1059 , -1350}, { 65 , 208}, {-1012 , -1369}, + { -79 , -459}, {-671 , -942}, { -12 , 56}, {-162 , -431}, {-820 , -1073}, { -886 , -136}, {-327 , -501}, { -55 , -14}, + { 652 , 647}, { 365 , 411}, { 614 , 252}, { 154 , 215}, { 12 , 62}, { 226 , 177}, {1689 , 1213}, { 751 , 179}, + { 31 , 182}, { 281 , -291}, {-354 , -642}, { 939 , 924}, { 619 , 90}, { 1675 , 1130}, { 827 , 272}, { 1550 , 1446} + }, + { + {-366 , -916}, {-346 , -234}, {-518 , -140}, { 26 , 305}, {-254 , -92}, {-634 , -976}, {-493 , -1076}, {-334 , -913}, + {-566 , 68}, { 102 , 216}, {-296 , -927}, {-501 , -1030}, {-437 , -1006}, {-146 , -145}, {-211 , -202}, { 62 , 359}, + { 163 , -122}, { 759 , 553}, { 82 , 207}, {-177 , -243}, { 163 , 343}, {1152 , 929}, { 197 , 248}, { 43 , -147}, + { 169 , 371}, {-468 , -1043}, { 686 , 418}, { 563, 245}, {1052 , 843}, { 259 , 341}, {1063 , 637}, { 865 , 654} + } +}; +const Word16 AR_SVQ_CB1_fx[32][8] = /* x2.56 */ +{ + { -1, 4, 16, 4, 45, -110, 10, 167, }, + { -3, 2, 8, -12, -7, 23, 279, -46, }, + { 0, 2, 1, 8, -73, -40, 71, -97, }, + { 0, 2, 42, 74, -39, 72, 27, 8, }, + { 0, 1, 9, -6, 40, -65, -55, -128, }, + { 0, 0, 8, -10, -43, 105, -5, -126, }, + { 0, 0, 12, -3, -98, -18, -88, -73, }, + { 0, 1, -6, -12, -49, -179, -30, -15, }, + { -1, 0, 24, 78, 25, -69, -26, -14, }, + { 0, 1, -1, -29, 23, -65, -126, 34, }, + { 2, -4, -23, -7, -13, -2, -22, -4, }, + { -1, 1, -2, 44, -54, -58, 107, 60, }, + { 0, 1, -3, -15, -54, 97, -100, 41, }, + { 0, -2, -81, 93, -13, 18, -31, -75, }, + { -1, 2, 0, -5, 166, -64, -48, 8, }, + { -2, 0, -27, -108, 36, 3, 12, -80, }, + { 0, 0, 0, 4, 82, -1, 79, 54, }, + { 1, -4, 5, -9, -38, 289, 16, 16, }, + { -1, 2, 6, -68, 61, 67, -31, 100, }, + { 3, -6, 2, -2, -1, -6, -217, 273, }, + { 0, 1, -43, -62, -7, -60, 28, 78, }, + { -1, 2, 10, 0, 76, 84, -55, -45, }, + { -1, -2, 4, 5, -32, 75, 70, 176, }, + { 2, -1, 0, 6, 27, 29, -220, -97, }, + { -1, 1, 90, -56, -10, -16, 29, 8, }, + { -1, 3, -10, 0, 2, -24, 49, -336, }, + { -1, 1, -8, -9, 55, -134, 105, -44, }, + { 0, 1, -16, 69, 51, 40, -51, 98, }, + { 0, 2, -12, -32, -140, 49, 50, 26, }, + { 0, 3, 8, 29, 77, 24, 76, -103, }, + { -1, 2, -24, -18, 7, 100, 94, 5, }, + { 0, -1, 10, 26, -87, -34, -56, 103, } +}; +const Word16 AR_SVQ_CB2_fx[16][8] = /* x2.56 */ +{ + { -37, -59, 208, -88, 54, 58, -16, -24, }, + { 0, -98, 9, -65, -182, -21, 19, 9, }, + { -1, 110, -8, 59, 201, 9, -38, -22, }, + { -1, 40, -22, -183, 46, -162, -38, -6, }, + { 12, 2, -193, 64, -43, -48, 11, 9, }, + { -83, 175, -8, -55, -65, 66, 26, 6, }, + { 29, 3, 2, -10, -100, 293, 75, -12, }, + { 7, -54, -76, -91, 63, 119, -84, -84, }, + { 3, 7, 6, 6, -30, 15, -176, 168, }, + { -10, 45, 26, 57, -92, -68, -117, -134, }, + { 0, -37, -34, -69, 106, 54, 121, 131, }, + { -25, -64, 7, 205, 1, 93, 27, 6, }, + { 64, 28, 51, 8, -7, 18, 27, 0, }, + { -20, 44, 57, 78, -55, -170, 88, 93, }, + { 12, -125, 12, 56, 100, -160, -87, -3, }, + { -7, -18, -7, -6, 36, -54, 175, -176, } +}; + +const Word16 interpol_frac_mid_relaxprev_12k8_fx[NB_SUBFR*3] = { 0, 22938, 9830, + 0, 0, 32767, + 0, 0, 32767, + 0, 0, 32767 + }; + +const Word16 interpol_frac_mid_FEC_fx[NB_SUBFR*3] = { 8192, 18022, 6554, + 0, 22938, 9830, + 0, 14746, 18022, + 0, 0, 32767 + }; + +const Word16 interpol_frac_mid_relaxprev_pred_12k8_fx[NB_SUBFR*3] = { 4915, 22938, 4915, + 1638, 21299, 9830, + 0, 16384, 16384, + 0, 0, 32767 + }; + +const Word16 interpol_frac_mid_relaxprev_16k_fx[NB_SUBFR16k*3] = { 0, 22938, 9830, + 0, 0, 32767, + 0, 0, 32767, + 0, 0, 32767, + 0, 0, 32767 + }; + +const Word16 interpol_frac_mid_16k_FEC_fx[NB_SUBFR16k*3] = { 13107, 13107, 6554, + 0, 26214, 6554, + 0, 21299, 11469, + 0, 4915, 27853, + 0, 0, 32767 + }; + +const Word16 interpol_frac_mid_relaxprev_pred_16k_fx[NB_SUBFR16k*3] = { 4915, 22938, 4915, + 1638, 21299, 9830, + 0, 16384, 16384, + 0, 4915, 27853, + 0, 0, 32767 + }; + +const Word16 filter_LP15_180H_fx[] = /* Sincfilt.m: N=180*2+1, Fmin=0, Fmax=1/15, hann( N )' */ +{ + 16384, 16263, 15904, 15317, 14516, 13524, + 12366, 11073, 9678, 8216, 6723, 5236, + 3790, 2416, 1144, 0, -997, -1831, + -2492, -2976, -3285, -3425, -3408, -3248, + -2966, -2583, -2123, -1610, -1070, -526, + 0, 487, 919, 1281, 1564, 1761, + 1869, 1891, 1830, 1695, 1496, 1244, + 954, 641, 318, 0, -300, -569, + -799, -982, -1113, -1188, -1209, -1176, + -1094, -969, -809, -623, -420, -209, + 0, 198, 377, 531, 653, 741, + 793, 807, 786, 732, 649, 543, + 418, 282, 140, 0, -133, -253, + -356, -438, -497, -531, -540, -526, + -489, -433, -362, -278, -187, -93, + 0, 88, 167, 234, 288, 325, + 347, 352, 342, 317, 280, 233, + 179, 120, 59, 0, -56, -105, + -147, -180, -203, -215, -217, -210, + -194, -170, -141, -107, -72, -35, + 0, 33, 61, 85, 103, 116, + 122, 122, 117, 107, 93, 76, + 58, 38, 19, 0, -17, -31, + -43, -51, -57, -59, -58, -55, + -49, -42, -34, -25, -16, -8, + 0, 7, 12, 16, 19, 20, + 21, 20, 18, 16, 13, 10, + 7, 4, 2, 0, -1, -2, + -3, -3, -3, -3, -2, -2, + -1, -1, 0, 0, 0, 0, + 0 +}; + +const Word16 filter_LP15_180H_13b_fx[6*31] = /*Q13 Sincfilt.m: N=180*2+1, Fmin=0, Fmax=1/12, hann( N )'*/ +{ + 8192, 8132, 7952, 7658, 7258, 6762, + 6183, 5536, 4839, 4108, 3362, 2618, + 1895, 1208, 572, 0, -498, -915, + -1246, -1488, -1643, -1713, -1704, -1624, + -1483, -1291, -1061, -805, -535, -263, + 0, 244, 459, 640, 782, 880, + 935, 945, 915, 848, 748, 622, + 477, 320, 159, 0, -150, -285, + -400, -491, -556, -594, -604, -588, + -547, -485, -405, -312, -210, -104, + 0, 99, 189, 265, 327, 371, + 396, 404, 393, 366, 325, 271, + 209, 141, 70, 0, -66, -127, + -178, -219, -248, -266, -270, -263, + -245, -217, -181, -139, -94, -46, + 0, 44, 83, 117, 144, 163, + 173, 176, 171, 158, 140, 116, + 89, 60, 30, 0, -28, -53, + -74, -90, -101, -108, -109, -105, + -97, -85, -70, -54, -36, -18, + 0, 16, 31, 43, 52, 58, + 61, 61, 58, 53, 47, 38, + 29, 19, 9, 0, -8, -16, + -21, -26, -28, -29, -29, -27, + -25, -21, -17, -13, -8, -4, + 0, 3, 6, 8, 10, 10, + 10, 10, 9, 8, 6, 5, + 3, 2, 1, 0, -1, -1, + -1, -2, -2, -1, -1, -1, + -1, 0, 0, 0, 0, 0, + 0 +}; +const Word16 filter_LP12_180H_fx[] = /* Sincfilt.m: N=180*2+1, Fmin=0, Fmax=1/12, hann( N )' */ +{ + 16384, 16196, 15641, 14741, 13533, 12067, + 10402, 8604, 6742, 4887, 3105, 1459, + 0, -1230, -2202, -2900, -3322, -3478, + -3392, -3095, -2628, -2037, -1371, -676, + 0, 618, 1143, 1550, 1822, 1954, + 1946, 1811, 1565, 1233, 842, 421, + 0, -394, -736, -1008, -1196, -1294, + -1299, -1217, -1059, -839, -576, -290, + 0, 274, 514, 707, 842, 913, + 920, 865, 755, 600, 413, 208, + 0, -197, -371, -511, -609, -662, + -667, -627, -548, -436, -300, -151, + 0, 143, 270, 371, 443, 481, + 485, 456, 398, 316, 217, 109, + 0, -104, -195, -268, -319, -346, + -348, -326, -284, -225, -155, -78, + 0, 73, 137, 189, 224, 242, + 243, 227, 198, 156, 107, 54, + 0, -50, -94, -128, -151, -163, + -163, -152, -131, -103, -70, -35, + 0, 32, 60, 82, 96, 103, + 102, 95, 81, 64, 43, 21, + 0, -19, -36, -48, -56, -59, + -58, -53, -45, -35, -23, -11, + 0, 10, 18, 24, 28, 29, + 28, 25, 21, 16, 10, 5, + 0, -4, -7, -9, -10, -10, + -9, -8, -6, -5, -3, -1, + 0, 1, 1, 2, 2, 1, + 1, 1, 0, 0, 0, 0, + 0 +}; +const Word16 filter_LP12_180H_13b_fx[] = /*Q13 Sincfilt.m: N=180*2+1, Fmin=0, Fmax=1/12, hann( N )*/ +{ + 8192, 8098, 7820, 7370, 6766, 6033, + 5201, 4302, 3371, 2443, 1553, 729, + 0, -615, -1101, -1450, -1661, -1739, + -1696, -1547, -1314, -1019, -685, -338, + 0, 309, 571, 775, 911, 977, + 973, 905, 783, 616, 421, 210, + 0, -197, -368, -504, -598, -647, + -649, -608, -529, -420, -288, -145, + 0, 137, 257, 353, 421, 457, + 460, 432, 377, 300, 206, 104, + 0, -99, -185, -255, -305, -331, + -333, -314, -274, -218, -150, -76, + 0, 72, 135, 186, 221, 240, + 242, 228, 199, 158, 109, 55, + 0, -52, -97, -134, -159, -173, + -174, -163, -142, -113, -77, -39, + 0, 37, 69, 94, 112, 121, + 121, 114, 99, 78, 53, 27, + 0, -25, -47, -64, -76, -81, + -81, -76, -66, -52, -35, -18, + 0, 16, 30, 41, 48, 52, + 51, 47, 41, 32, 21, 11, + 0, -10, -18, -24, -28, -30, + -29, -27, -23, -17, -12, -6, + 0, 5, 9, 12, 14, 14, + 14, 13, 10, 8, 5, 2, + 0, -2, -4, -5, -5, -5, + -5, -4, -3, -2, -1, -1, + 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, + 0 +}; + +const Word16 filter_LP24_90H_fx[] = +{ + + 10240, 10208, 10111, 9951, 9731, + 9452, 9119, 8734, 8304, 7834, + 7328, 6794, 6237, 5664, 5081, + 4495, 3913, 3339, 2780, 2241, + 1727, 1242, 791, 376, 0, + -335, -629, -880, -1089, -1256, + -1383, -1471, -1523, -1540, -1527, + -1487, -1422, -1337, -1235, -1119, + -994, -862, -727, -592, -460, + -333, -212, -101, 0, 90, + 167, 232, 285, 325, 354, + 371, 378, 376, 366, 349, + 326, 299, 269, 236, 203, + 171, 139, 109, 81, 56, + 34, 15, 0, -12, -21, + -27, -30, -31, -31, -29, + -26, -22, -18, -14, -10, + -7, -4, -2, -1, 0, + 0, 0, 0, 0, 0, + 0, + 0 + +}; + +const Word16 filter_LP24_90H_13b_fx[] = +{ + + 5120, 5104, 5056, 4976, 4865, + 4726, 4559, 4367, 4152, 3917, + 3664, 3397, 3119, 2832, 2541, + 2248, 1956, 1669, 1390, 1120, + 863, 621, 396, 188, 0, + -168, -315, -440, -545, -628, + -691, -735, -761, -770, -764, + -743, -711, -668, -617, -560, + -497, -431, -364, -296, -230, + -166, -106, -51, 0, 45, + 84, 116, 143, 163, 177, + 186, 189, 188, 183, 174, + 163, 149, 134, 118, 102, + 85, 69, 54, 40, 28, + 17, 8, 0, -6, -10, + -13, -15, -16, -15, -14, + -13, -11, -9, -7, -5, + -3, -2, -1, 0, 0, + 0, 0, 0, 0, 0, + 0, + 0 +}; + +const Word16 filter_LP3_90H_fx[] = /* Sincfilt.m: N=90*2+1, Fmin=0, Fmax=1/3, hann( N )' */ +{ + 16384, 13545, 6766, 0, -3371, -2689, + 0, 1907, 1661, 0, -1314, -1187, + 0, 990, 911, 0, -783, -729, + 0, 638, 598, 0, -529, -499, + 0, 445, 421, 0, -377, -357, + 0, 321, 305, 0, -274, -260, + 0, 234, 221, 0, -199, -188, + 0, 169, 159, 0, -142, -134, + 0, 119, 112, 0, -99, -93, + 0, 81, 76, 0, -66, -61, + 0, 52, 48, 0, -41, -37, + 0, 31, 28, 0, -23, -20, + 0, 16, 14, 0, -10, -9, + 0, 6, 5, 0, -3, -2, + 0, 1, 1, 0, 0, 0, + 0 +}; + +const Word16 filter_LP15_360H_13b_fx[] = /* Sincfilt.m: N=360*2+1, Fmin=0, Fmax=1/15, hann( N )' */ +{ + + 8192, 8132, 7954, 7662, 7265, 6772, 6196, 5552, + 4857, 4127, 3381, 2636, 1911, 1220, 579, 0, + -506, -931, -1269, -1519, -1681, -1757, -1752, -1674, + -1533, -1339, -1104, -840, -560, -276, 0, 258, + 488, 682, 836, 946, 1008, 1024, 996, 927, + 821, 687, 529, 357, 178, 0, -170, -325, + -458, -567, -646, -694, -710, -696, -652, -581, + -489, -379, -257, -129, 0, 124, 238, 338, + 420, 481, 518, 533, 523, 492, 440, 372, + 289, 197, 99, 0, -96, -184, -262, -326, + -374, -405, -417, -410, -386, -346, -293, -228, + -156, -78, 0, 76, 147, 209, 260, 299, + 324, 334, 329, 310, 279, 236, 184, 125, + 63, 0, -62, -119, -169, -211, -243, -263, + -271, -268, -252, -227, -192, -150, -102, -52, + 0, 50, 97, 138, 173, 198, 215, 222, + 219, 207, 186, 157, 123, 84, 42, 0, + -41, -80, -113, -142, -163, -176, -182, -180, + -170, -152, -129, -101, -69, -35, 0, 34, + 65, 93, 116, 133, 144, 149, 147, 139, + 125, 106, 82, 56, 28, 0, -28, -53, + -76, -95, -109, -118, -121, -120, -113, -101, + -86, -67, -46, -23, 0, 22, 43, 61, + 77, 88, 95, 98, 97, 91, 82, 69, + 54, 37, 19, 0, -18, -35, -49, -61, + -70, -76, -78, -77, -73, -65, -55, -43, + -29, -15, 0, 14, 27, 39, 48, 55, + 60, 62, 61, 57, 51, 43, 33, 23, + 11, 0, -11, -21, -30, -37, -43, -46, + -48, -47, -44, -39, -33, -26, -17, -9, + 0, 8, 16, 23, 28, 32, 35, 36, + 35, 33, 29, 25, 19, 13, 6, 0, + -6, -12, -17, -21, -24, -25, -26, -25, + -24, -21, -18, -14, -9, -5, 0, 4, + 8, 12, 14, 16, 18, 18, 17, 16, + 14, 12, 9, 6, 3, 0, -3, -6, + -8, -10, -11, -11, -12, -11, -10, -9, + -8, -6, -4, -2, 0, 2, 3, 5, + 6, 6, 7, 7, 7, 6, 5, 4, + 3, 2, 1, 0, -1, -2, -3, -3, + -3, -3, -3, -3, -3, -3, -2, -2, + -1, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0 + +}; + +const Resampling_cfg_fx resampling_cfg_tbl_fx[] = +{ + /* fin fout up.fac. den.fac. len.out filter coefs. filter mem./2 flags */ + {8000, 12800, 8, 5, 256, filter5_39s320_120_fx, 15, RS_INV_FAC }, + {12800, 8000, 5, 8, 160, filter5_39s320_120_fx, L_FILT_UP8k, RS_INV_FAC }, + {16000, 8000, 6, 12, 160, filter_LP12_180H_fx, 180/6, 0 }, + + {12800, 16000, 15, 12, 320, filter_LP15_180H_fx, L_FILT_UP16k, 0 }, + {12800, 32000, 15, 6, 640, filter_LP15_180H_fx, L_FILT_UP32k, 0 }, + {12800, 48000, 15, 4, 960, filter_LP15_180H_fx, L_FILT_UP48k , 0 }, + + {16000, 12800, 12, 15, 256, filter_LP15_180H_fx, L_FILT16k, 0 }, + {16000, 32000, 12, 6, 640, filter_LP12_180H_fx, L_FILT16k, 0 }, + {16000, 48000, 12, 4, 960, filter_LP12_180H_fx, L_FILT16k, 0 }, + + {32000, 12800, 6, 15, 256, filter_LP15_180H_13b_fx, L_FILT32k, 0 }, + {32000, 16000, 6, 12, 320, filter_LP12_180H_13b_fx, L_FILT32k, 0 }, + {32000, 25600, 12, 15, 512, filter_LP15_360H_13b_fx, L_FILT32k, 0 }, + {32000, 48000, 3, 2, 960, filter_LP3_90H_fx, L_FILT32k, 0 }, + + {48000, 12800, 4, 15, 256, filter_LP15_180H_13b_fx, L_FILT48k, 0 }, + {48000, 16000, 4, 12, 320, filter_LP12_180H_13b_fx, L_FILT48k, 0 }, + {48000, 25600, 8, 15, 512, filter_LP15_360H_13b_fx, L_FILT48k, 0 }, + {48000, 32000, 2, 3, 640, filter_LP3_90H_fx, L_FILT48k, 0 }, + + /* configs with NB 4kHz low-pass */ + {16000, 12800, 12, 15, 256, filter_LP24_90H_fx, L_FILT16k, 0 }, + {32000, 12800, 6, 15, 256, filter_LP24_90H_13b_fx, L_FILT32k, 0 }, + {48000, 12800, 4, 15, 256, filter_LP24_90H_13b_fx, L_FILT48k, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 } /* trailing entry (just to calculate the length of this table) */ +}; +/*-------------------------------------------------------------------* + * 1/4 resolution interpolation filter (-3 dB at 0.791*fs/2) + * for fractional pitch search + * Used in lib_enc\pit_enc.c Q14 + *-------------------------------------------------------------------*/ +const Word16 inter4_1_fx[32] = +{ + -12, -26, 32, 206, + 420, 455, 73, -766, + -1732, -2142,-1242, 1376, + 5429, 9910,13418,14746, + 13418, 9910, 5429, 1376, + -1242, -2142,-1732, -766, + 73, 455, 420, 206, + 32, -26, -12, 0 +}; +const Word16 CNG_burst_att_fx[6][8] = +{ + {30076, 27793, 25832, 24129, 22637, 21319, 20146, 19095}, + {29714, 27181, 25046, 23222, 21646, 20270, 20205, 20205}, + {29415, 26685, 24418, 22506, 22410, 22410, 22410, 22410}, + {29310, 26512, 24201, 23198, 23198, 23198, 23198, 23198}, + {29310, 26512, 24201, 23198, 23198, 23198, 23198, 23198}, + {29789, 27307, 25206, 23406, 21845, 20480, 19661, 19661} +}; +/* 2.0 - 6.4 kHz phase dispersion */ +const Word16 Low_H_phasedisp[L_SUBFR]= +{ + 16389, 16381, 16386, 16382, 16382, 16383, 16381, 16384, 16385, 10265, + 10154, 9894, 14052, 16343, -531, 13216, 16373, 15510, 9407, 15949, + 4726, 14593, 10404, 9796, -16336, -1815,-10623, 12647, 14556,-12683, + 11389, 8176, 16382,-14197, 11781, 10379, 7516, 10424,-12472, 16285, + -1200,-13137, 12659, -7446, 15684, -3763,-13418, -5280, 521, -9685, + -16375, -1219, 8436,-13059, -12861,-12775, 0, 3, 0, -2, + -1, -1, -1, 2 +}; + +/* 3.2 - 6.4 kHz phase dispersion */ +const Word16 Mid_H_phasedisp[L_SUBFR]= +{ + 16382, 16382, 16384, 16385, 16386, 16388, 16387, 16383, 16387, 16383, + 16386, 16386, 16386, 16384, 16382, 16388, 14847, 9629, 13249, 14487, + 10995, 643, 13818, 13779, 6468, 8665, 11634, 9781,-14636, -982, + 11746, -722, 16386,-16365, -11422, 16354, 7363, 13148,-11538,-13903, + -15051, -8862, 8812,-16371, -12146, 7661, -9637,-13253, -6922, 4, + -4, -1, -5, 1, 7, 6, -7, -1, 4, -4, + 0, -1, -3, 3 +}; +/* phase table needed in FFT */ +const Word16 phs_tbl_dec[64*2] = +{ + /* part of table that is not scaled by 2 */ + 16384, 0, 16305, -1606, 16069, -3196, 15678, -4756, 15136, -6270, + 14449, -7723, 13622, -9102, 12665, -10394, 11585, -11585, 10394, -12665, + 9102, -13622, 7723, -14449, 6270, -15136, 4756, -15678, 3196, -16069, + 1606, -16305, 0, -16384, -1606, -16305, -3196, -16069, -4756, -15678, + -6270, -15136, -7723, -14449, -9102, -13622, -10394, -12665, -11585, -11585, + -12665, -10394, -13622, -9102, -14449, -7723, -15136, -6270, -15678, -4756, + -16069, -3196, -16305, -1606, + /* part of table that is scaled by 2 (this save one operation in FFT inner loops) */ + 32767, 0, 32610, -3212, 32138, -6392, 31356, -9512, 30272, -12540, + 28898, -15446, 27244, -18204, 25330, -20788, 23170, -23170, 20788, -25330, + 18204, -27244, 15446, -28898, 12540, -30272, 9512, -31356, 6392, -32138, + 3212, -32610, 0, -32768, -3212, -32610, -6392, -32138, -9512, -31356, + -12540, -30272, -15446, -28898, -18204, -27244, -20788, -25330, -23170, -23170, + -25330, -20788, -27244, -18204, -28898, -15446, -30272, -12540, -31356, -9512, + -32138, -6392, -32610, -3212 +}; + +const Word16 FFT_W64[(64*2)*2] = +{ + 16384, 0, 16364, -804, 16305, -1606, 16207, -2404, + 16069, -3196, 15893, -3981, 15679, -4756, 15426, -5520, + 15137, -6270, 14811, -7005, 14449, -7723, 14053, -8423, + 13623, -9102, 13160, -9760, 12665, -10394, 12140, -11003, + 11585, -11585, 11003, -12140, 10394, -12665, 9760, -13160, + 9102, -13623, 8423, -14053, 7723, -14449, 7005, -14811, + 6270, -15137, 5520, -15426, 4756, -15679, 3981, -15893, + 3196, -16069, 2404, -16207, 1606, -16305, 804, -16364, + 0, -16384, -804, -16364, -1606, -16305, -2404, -16207, + -3196, -16069, -3981, -15893, -4756, -15679, -5520, -15426, + -6270, -15137, -7005, -14811, -7723, -14449, -8423, -14053, + -9102, -13623, -9760, -13160, -10394, -12665, -11003, -12140, + -11585, -11585, -12140, -11003, -12665, -10394, -13160, -9760, + -13623, -9102, -14053, -8423, -14449, -7723, -14811, -7005, + -15137, -6270, -15426, -5520, -15679, -4756, -15893, -3981, + -16069, -3196, -16207, -2404, -16305, -1606, -16364, -804, + /* The following is a duplication of the above but scaled up by a factor of 2. + * This save one operation in inverse FFT inner loops */ + 32767, 0, 32729, -1608, 32610, -3212, 32413, -4808, + 32138, -6393, 31786, -7962, 31357, -9512, 30853, -11039, + 30274, -12540, 29622, -14010, 28899, -15447, 28106, -16846, + 27246, -18205, 26320, -19520, 25330, -20788, 24279, -22006, + 23170, -23170, 22006, -24279, 20788, -25330, 19520, -26320, + 18205, -27246, 16846, -28106, 15447, -28899, 14010, -29622, + 12540, -30274, 11039, -30853, 9512, -31357, 7962, -31786, + 6393, -32138, 4808, -32413, 3212, -32610, 1608, -32729, + 0, -32768, -1608, -32729, -3212, -32610, -4808, -32413, + -6393, -32138, -7962, -31786, -9512, -31357, -11039, -30853, + -12540, -30274, -14010, -29622, -15447, -28899, -16846, -28106, + -18205, -27246, -19520, -26320, -20788, -25330, -22006, -24279, + -23170, -23170, -24279, -22006, -25330, -20788, -26320, -19520, + -27246, -18205, -28106, -16846, -28899, -15447, -29622, -14010, + -30274, -12540, -30853, -11039, -31357, -9512, -31786, -7962, + -32138, -6393, -32413, -4808, -32610, -3212, -32729, -1608 +}; + +const Word16 FFT_W128[] = +{ + /* part of table that is not scaled by 2 */ + 16384, 0, 16379, -402, 16364, -804, 16339, -1205, + 16305, -1606, 16260, -2006, 16206, -2404, 16142, -2801, + 16069, -3196, 15985, -3590, 15893, -3981, 15790, -4370, + 15678, -4756, 15557, -5139, 15426, -5519, 15286, -5896, + 15136, -6270, 14978, -6639, 14811, -7005, 14634, -7366, + 14449, -7723, 14255, -8075, 14053, -8423, 13842, -8765, + 13622, -9102, 13395, -9434, 13159, -9760, 12916, -10080, + 12665, -10394, 12406, -10701, 12139, -11002, 11866, -11297, + 11585, -11585, 11297, -11866, 11002, -12139, 10701, -12406, + 10394, -12665, 10080, -12916, 9760, -13159, 9434, -13395, + 9102, -13622, 8765, -13842, 8423, -14053, 8075, -14255, + 7723, -14449, 7366, -14634, 7005, -14811, 6639, -14978, + 6270, -15136, 5896, -15286, 5519, -15426, 5139, -15557, + 4756, -15678, 4370, -15790, 3981, -15893, 3590, -15985, + 3196, -16069, 2801, -16142, 2404, -16206, 2006, -16260, + 1606, -16305, 1205, -16339, 804, -16364, 402, -16379, + 0, -16384, -402, -16379, -804, -16364, -1205, -16339, + -1606, -16305, -2006, -16260, -2404, -16206, -2801, -16142, + -3196, -16069, -3590, -15985, -3981, -15893, -4370, -15790, + -4756, -15678, -5139, -15557, -5519, -15426, -5896, -15286, + -6270, -15136, -6639, -14978, -7005, -14811, -7366, -14634, + -7723, -14449, -8075, -14255, -8423, -14053, -8765, -13842, + -9102, -13622, -9434, -13395, -9760, -13159, -10080, -12916, + -10394, -12665, -10701, -12406, -11002, -12139, -11297, -11866, + -11585, -11585, -11866, -11297, -12139, -11002, -12406, -10701, + -12665, -10394, -12916, -10080, -13159, -9760, -13395, -9434, + -13622, -9102, -13842, -8765, -14053, -8423, -14255, -8075, + -14449, -7723, -14634, -7366, -14811, -7005, -14978, -6639, + -15136, -6270, -15286, -5896, -15426, -5519, -15557, -5139, + -15678, -4756, -15790, -4370, -15893, -3981, -15985, -3590, + -16069, -3196, -16142, -2801, -16206, -2404, -16260, -2006, + -16305, -1606, -16339, -1205, -16364, -804, -16379, -402, + /* part of table that is scaled by 2 (this save one operation in FFT inner loops) */ + 32767, 0, 32758, -804, 32728, -1608, 32678, -2410, + 32610, -3212, 32520, -4012, 32412, -4808, 32284, -5602, + 32138, -6392, 31970, -7180, 31786, -7962, 31580, -8740, + 31356, -9512, 31114, -10278, 30852, -11038, 30572, -11792, + 30272, -12540, 29956, -13278, 29622, -14010, 29268, -14732, + 28898, -15446, 28510, -16150, 28106, -16846, 27684, -17530, + 27244, -18204, 26790, -18868, 26318, -19520, 25832, -20160, + 25330, -20788, 24812, -21402, 24278, -22004, 23732, -22594, + 23170, -23170, 22594, -23732, 22004, -24278, 21402, -24812, + 20788, -25330, 20160, -25832, 19520, -26318, 18868, -26790, + 18204, -27244, 17530, -27684, 16846, -28106, 16150, -28510, + 15446, -28898, 14732, -29268, 14010, -29622, 13278, -29956, + 12540, -30272, 11792, -30572, 11038, -30852, 10278, -31114, + 9512, -31356, 8740, -31580, 7962, -31786, 7180, -31970, + 6392, -32138, 5602, -32284, 4808, -32412, 4012, -32520, + 3212, -32610, 2410, -32678, 1608, -32728, 804, -32758, + 0, -32768, -804, -32758, -1608, -32728, -2410, -32678, + -3212, -32610, -4012, -32520, -4808, -32412, -5602, -32284, + -6392, -32138, -7180, -31970, -7962, -31786, -8740, -31580, + -9512, -31356, -10278, -31114, -11038, -30852, -11792, -30572, + -12540, -30272, -13278, -29956, -14010, -29622, -14732, -29268, + -15446, -28898, -16150, -28510, -16846, -28106, -17530, -27684, + -18204, -27244, -18868, -26790, -19520, -26318, -20160, -25832, + -20788, -25330, -21402, -24812, -22004, -24278, -22594, -23732, + -23170, -23170, -23732, -22594, -24278, -22004, -24812, -21402, + -25330, -20788, -25832, -20160, -26318, -19520, -26790, -18868, + -27244, -18204, -27684, -17530, -28106, -16846, -28510, -16150, + -28898, -15446, -29268, -14732, -29622, -14010, -29956, -13278, + -30272, -12540, -30572, -11792, -30852, -11038, -31114, -10278, + -31356, -9512, -31580, -8740, -31786, -7962, -31970, -7180, + -32138, -6392, -32284, -5602, -32412, -4808, -32520, -4012, + -32610, -3212, -32678, -2410, -32728, -1608, -32758, -804 +}; + +const Word16 FFT_W256[(256*2)*2] = +{ + /* Each adjacent pair represents the real and imaginary part of a complex number: */ + /* W = exp{-j*(PI*n/256)} = cos(PI*n/256)*16384 -j*sin(PI*n/256)*16384 for n=0, 1, ..., 255. */ + 16384, 0, 16383, -201, 16379, -402, 16373, -603, + 16364, -804, 16353, -1005, 16340, -1205, 16324, -1406, + 16305, -1606, 16284, -1806, 16261, -2006, 16235, -2205, + 16207, -2404, 16176, -2603, 16143, -2801, 16107, -2999, + 16069, -3196, 16029, -3393, 15986, -3590, 15941, -3786, + 15893, -3981, 15843, -4176, 15791, -4370, 15736, -4563, + 15679, -4756, 15619, -4948, 15557, -5139, 15493, -5330, + 15426, -5520, 15357, -5708, 15286, -5897, 15213, -6084, + 15137, -6270, 15059, -6455, 14978, -6639, 14896, -6823, + 14811, -7005, 14724, -7186, 14635, -7366, 14543, -7545, + 14449, -7723, 14354, -7900, 14256, -8076, 14155, -8250, + 14053, -8423, 13949, -8595, 13842, -8765, 13733, -8935, + 13623, -9102, 13510, -9269, 13395, -9434, 13279, -9598, + 13160, -9760, 13039, -9921, 12916, -10080, 12792, -10238, + 12665, -10394, 12537, -10549, 12406, -10702, 12274, -10853, + 12140, -11003, 12004, -11151, 11866, -11297, 11727, -11442, + 11585, -11585, 11442, -11727, 11297, -11866, 11151, -12004, + 11003, -12140, 10853, -12274, 10702, -12406, 10549, -12537, + 10394, -12665, 10238, -12792, 10080, -12916, 9921, -13039, + 9760, -13160, 9598, -13279, 9434, -13395, 9269, -13510, + 9102, -13623, 8935, -13733, 8765, -13842, 8595, -13949, + 8423, -14053, 8250, -14155, 8076, -14256, 7900, -14354, + 7723, -14449, 7545, -14543, 7366, -14635, 7186, -14724, + 7005, -14811, 6823, -14896, 6639, -14978, 6455, -15059, + 6270, -15137, 6084, -15213, 5897, -15286, 5708, -15357, + 5520, -15426, 5330, -15493, 5139, -15557, 4948, -15619, + 4756, -15679, 4563, -15736, 4370, -15791, 4176, -15843, + 3981, -15893, 3786, -15941, 3590, -15986, 3393, -16029, + 3196, -16069, 2999, -16107, 2801, -16143, 2603, -16176, + 2404, -16207, 2205, -16235, 2006, -16261, 1806, -16284, + 1606, -16305, 1406, -16324, 1205, -16340, 1005, -16353, + 804, -16364, 603, -16373, 402, -16379, 201, -16383, + 0, -16384, -201, -16383, -402, -16379, -603, -16373, + -804, -16364, -1005, -16353, -1205, -16340, -1406, -16324, + -1606, -16305, -1806, -16284, -2006, -16261, -2205, -16235, + -2404, -16207, -2603, -16176, -2801, -16143, -2999, -16107, + -3196, -16069, -3393, -16029, -3590, -15986, -3786, -15941, + -3981, -15893, -4176, -15843, -4370, -15791, -4563, -15736, + -4756, -15679, -4948, -15619, -5139, -15557, -5330, -15493, + -5520, -15426, -5708, -15357, -5897, -15286, -6084, -15213, + -6270, -15137, -6455, -15059, -6639, -14978, -6823, -14896, + -7005, -14811, -7186, -14724, -7366, -14635, -7545, -14543, + -7723, -14449, -7900, -14354, -8076, -14256, -8250, -14155, + -8423, -14053, -8595, -13949, -8765, -13842, -8935, -13733, + -9102, -13623, -9269, -13510, -9434, -13395, -9598, -13279, + -9760, -13160, -9921, -13039, -10080, -12916, -10238, -12792, + -10394, -12665, -10549, -12537, -10702, -12406, -10853, -12274, + -11003, -12140, -11151, -12004, -11297, -11866, -11442, -11727, + -11585, -11585, -11727, -11442, -11866, -11297, -12004, -11151, + -12140, -11003, -12274, -10853, -12406, -10702, -12537, -10549, + -12665, -10394, -12792, -10238, -12916, -10080, -13039, -9921, + -13160, -9760, -13279, -9598, -13395, -9434, -13510, -9269, + -13623, -9102, -13733, -8935, -13842, -8765, -13949, -8595, + -14053, -8423, -14155, -8250, -14256, -8076, -14354, -7900, + -14449, -7723, -14543, -7545, -14635, -7366, -14724, -7186, + -14811, -7005, -14896, -6823, -14978, -6639, -15059, -6455, + -15137, -6270, -15213, -6084, -15286, -5897, -15357, -5708, + -15426, -5520, -15493, -5330, -15557, -5139, -15619, -4948, + -15679, -4756, -15736, -4563, -15791, -4370, -15843, -4176, + -15893, -3981, -15941, -3786, -15986, -3590, -16029, -3393, + -16069, -3196, -16107, -2999, -16143, -2801, -16176, -2603, + -16207, -2404, -16235, -2205, -16261, -2006, -16284, -1806, + -16305, -1606, -16324, -1406, -16340, -1205, -16353, -1005, + -16364, -804, -16373, -603, -16379, -402, -16383, -201, + + /* The following is a duplication of the above but scaled up by a factor of 2. + * This save one operation in inverse FFT inner loops */ + 32767, 0, 32766, -402, 32758, -804, 32746, -1206, + 32729, -1608, 32706, -2009, 32679, -2411, 32647, -2811, + 32610, -3212, 32568, -3612, 32522, -4011, 32470, -4410, + 32413, -4808, 32352, -5205, 32286, -5602, 32214, -5998, + 32138, -6393, 32058, -6787, 31972, -7180, 31881, -7571, + 31786, -7962, 31686, -8351, 31581, -8740, 31471, -9127, + 31357, -9512, 31238, -9896, 31114, -10279, 30986, -10660, + 30853, -11039, 30715, -11417, 30572, -11793, 30425, -12167, + 30274, -12540, 30118, -12910, 29957, -13279, 29792, -13646, + 29622, -14010, 29448, -14373, 29269, -14733, 29086, -15091, + 28899, -15447, 28707, -15800, 28511, -16151, 28311, -16500, + 28106, -16846, 27897, -17190, 27684, -17531, 27467, -17869, + 27246, -18205, 27020, -18538, 26791, -18868, 26557, -19195, + 26320, -19520, 26078, -19841, 25833, -20160, 25583, -20475, + 25330, -20788, 25073, -21097, 24812, -21403, 24548, -21706, + 24279, -22006, 24008, -22302, 23732, -22595, 23453, -22884, + 23170, -23170, 22884, -23453, 22595, -23732, 22302, -24008, + 22006, -24279, 21706, -24548, 21403, -24812, 21097, -25073, + 20788, -25330, 20475, -25583, 20160, -25833, 19841, -26078, + 19520, -26320, 19195, -26557, 18868, -26791, 18538, -27020, + 18205, -27246, 17869, -27467, 17531, -27684, 17190, -27897, + 16846, -28106, 16500, -28311, 16151, -28511, 15800, -28707, + 15447, -28899, 15091, -29086, 14733, -29269, 14373, -29448, + 14010, -29622, 13646, -29792, 13279, -29957, 12910, -30118, + 12540, -30274, 12167, -30425, 11793, -30572, 11417, -30715, + 11039, -30853, 10660, -30986, 10279, -31114, 9896, -31238, + 9512, -31357, 9127, -31471, 8740, -31581, 8351, -31686, + 7962, -31786, 7571, -31881, 7180, -31972, 6787, -32058, + 6393, -32138, 5998, -32214, 5602, -32286, 5205, -32352, + 4808, -32413, 4410, -32470, 4011, -32522, 3612, -32568, + 3212, -32610, 2811, -32647, 2411, -32679, 2009, -32706, + 1608, -32729, 1206, -32746, 804, -32758, 402, -32766, + 0, -32768, -402, -32766, -804, -32758, -1206, -32746, + -1608, -32729, -2009, -32706, -2411, -32679, -2811, -32647, + -3212, -32610, -3612, -32568, -4011, -32522, -4410, -32470, + -4808, -32413, -5205, -32352, -5602, -32286, -5998, -32214, + -6393, -32138, -6787, -32058, -7180, -31972, -7571, -31881, + -7962, -31786, -8351, -31686, -8740, -31581, -9127, -31471, + -9512, -31357, -9896, -31238, -10279, -31114, -10660, -30986, + -11039, -30853, -11417, -30715, -11793, -30572, -12167, -30425, + -12540, -30274, -12910, -30118, -13279, -29957, -13646, -29792, + -14010, -29622, -14373, -29448, -14733, -29269, -15091, -29086, + -15447, -28899, -15800, -28707, -16151, -28511, -16500, -28311, + -16846, -28106, -17190, -27897, -17531, -27684, -17869, -27467, + -18205, -27246, -18538, -27020, -18868, -26791, -19195, -26557, + -19520, -26320, -19841, -26078, -20160, -25833, -20475, -25583, + -20788, -25330, -21097, -25073, -21403, -24812, -21706, -24548, + -22006, -24279, -22302, -24008, -22595, -23732, -22884, -23453, + -23170, -23170, -23453, -22884, -23732, -22595, -24008, -22302, + -24279, -22006, -24548, -21706, -24812, -21403, -25073, -21097, + -25330, -20788, -25583, -20475, -25833, -20160, -26078, -19841, + -26320, -19520, -26557, -19195, -26791, -18868, -27020, -18538, + -27246, -18205, -27467, -17869, -27684, -17531, -27897, -17190, + -28106, -16846, -28311, -16500, -28511, -16151, -28707, -15800, + -28899, -15447, -29086, -15091, -29269, -14733, -29448, -14373, + -29622, -14010, -29792, -13646, -29957, -13279, -30118, -12910, + -30274, -12540, -30425, -12167, -30572, -11793, -30715, -11417, + -30853, -11039, -30986, -10660, -31114, -10279, -31238, -9896, + -31357, -9512, -31471, -9127, -31581, -8740, -31686, -8351, + -31786, -7962, -31881, -7571, -31972, -7180, -32058, -6787, + -32138, -6393, -32214, -5998, -32286, -5602, -32352, -5205, + -32413, -4808, -32470, -4410, -32522, -4011, -32568, -3612, + -32610, -3212, -32647, -2811, -32679, -2411, -32706, -2009, + -32729, -1608, -32746, -1206, -32758, -804, -32766, -402 +}; + +const Word16 FFT_W512[(512*2)*2] = +{ + 16384, 0, 16384, -101, 16383, -201, 16381, -302, + 16379, -402, 16376, -503, 16373, -603, 16369, -704, + 16364, -804, 16359, -904, 16353, -1005, 16347, -1105, + 16340, -1205, 16332, -1306, 16324, -1406, 16315, -1506, + 16305, -1606, 16295, -1706, 16284, -1806, 16273, -1906, + 16261, -2006, 16248, -2105, 16235, -2205, 16221, -2305, + 16207, -2404, 16192, -2503, 16176, -2603, 16160, -2702, + 16143, -2801, 16125, -2900, 16107, -2999, 16088, -3098, + 16069, -3196, 16049, -3295, 16029, -3393, 16008, -3492, + 15986, -3590, 15964, -3688, 15941, -3786, 15917, -3883, + 15893, -3981, 15868, -4078, 15843, -4176, 15817, -4273, + 15791, -4370, 15763, -4467, 15736, -4563, 15707, -4660, + 15679, -4756, 15649, -4852, 15619, -4948, 15588, -5044, + 15557, -5139, 15525, -5235, 15493, -5330, 15460, -5425, + 15426, -5520, 15392, -5614, 15357, -5708, 15322, -5803, + 15286, -5897, 15250, -5990, 15213, -6084, 15175, -6177, + 15137, -6270, 15098, -6363, 15059, -6455, 15019, -6547, + 14978, -6639, 14937, -6731, 14896, -6823, 14854, -6914, + 14811, -7005, 14768, -7096, 14724, -7186, 14680, -7276, + 14635, -7366, 14589, -7456, 14543, -7545, 14497, -7635, + 14449, -7723, 14402, -7812, 14354, -7900, 14305, -7988, + 14256, -8076, 14206, -8163, 14155, -8250, 14104, -8337, + 14053, -8423, 14001, -8509, 13949, -8595, 13896, -8680, + 13842, -8765, 13788, -8850, 13733, -8935, 13678, -9019, + 13623, -9102, 13567, -9186, 13510, -9269, 13453, -9352, + 13395, -9434, 13337, -9516, 13279, -9598, 13219, -9679, + 13160, -9760, 13100, -9841, 13039, -9921, 12978, -10001, + 12916, -10080, 12854, -10159, 12792, -10238, 12729, -10316, + 12665, -10394, 12601, -10471, 12537, -10549, 12472, -10625, + 12406, -10702, 12340, -10778, 12274, -10853, 12207, -10928, + 12140, -11003, 12072, -11077, 12004, -11151, 11935, -11224, + 11866, -11297, 11797, -11370, 11727, -11442, 11656, -11514, + 11585, -11585, 11514, -11656, 11442, -11727, 11370, -11797, + 11297, -11866, 11224, -11935, 11151, -12004, 11077, -12072, + 11003, -12140, 10928, -12207, 10853, -12274, 10778, -12340, + 10702, -12406, 10625, -12472, 10549, -12537, 10471, -12601, + 10394, -12665, 10316, -12729, 10238, -12792, 10159, -12854, + 10080, -12916, 10001, -12978, 9921, -13039, 9841, -13100, + 9760, -13160, 9679, -13219, 9598, -13279, 9516, -13337, + 9434, -13395, 9352, -13453, 9269, -13510, 9186, -13567, + 9102, -13623, 9019, -13678, 8935, -13733, 8850, -13788, + 8765, -13842, 8680, -13896, 8595, -13949, 8509, -14001, + 8423, -14053, 8337, -14104, 8250, -14155, 8163, -14206, + 8076, -14256, 7988, -14305, 7900, -14354, 7812, -14402, + 7723, -14449, 7635, -14497, 7545, -14543, 7456, -14589, + 7366, -14635, 7276, -14680, 7186, -14724, 7096, -14768, + 7005, -14811, 6914, -14854, 6823, -14896, 6731, -14937, + 6639, -14978, 6547, -15019, 6455, -15059, 6363, -15098, + 6270, -15137, 6177, -15175, 6084, -15213, 5990, -15250, + 5897, -15286, 5803, -15322, 5708, -15357, 5614, -15392, + 5520, -15426, 5425, -15460, 5330, -15493, 5235, -15525, + 5139, -15557, 5044, -15588, 4948, -15619, 4852, -15649, + 4756, -15679, 4660, -15707, 4563, -15736, 4467, -15763, + 4370, -15791, 4273, -15817, 4176, -15843, 4078, -15868, + 3981, -15893, 3883, -15917, 3786, -15941, 3688, -15964, + 3590, -15986, 3492, -16008, 3393, -16029, 3295, -16049, + 3196, -16069, 3098, -16088, 2999, -16107, 2900, -16125, + 2801, -16143, 2702, -16160, 2603, -16176, 2503, -16192, + 2404, -16207, 2305, -16221, 2205, -16235, 2105, -16248, + 2006, -16261, 1906, -16273, 1806, -16284, 1706, -16295, + 1606, -16305, 1506, -16315, 1406, -16324, 1306, -16332, + 1205, -16340, 1105, -16347, 1005, -16353, 904, -16359, + 804, -16364, 703, -16369, 603, -16373, 503, -16376, + 402, -16379, 302, -16381, 201, -16383, 101, -16384, + 0, -16384, -101, -16384, -201, -16383, -302, -16381, + -402, -16379, -503, -16376, -603, -16373, -704, -16369, + -804, -16364, -904, -16359, -1005, -16353, -1105, -16347, + -1205, -16340, -1306, -16332, -1406, -16324, -1506, -16315, + -1606, -16305, -1706, -16295, -1806, -16284, -1906, -16273, + -2006, -16261, -2105, -16248, -2205, -16235, -2305, -16221, + -2404, -16207, -2503, -16192, -2603, -16176, -2702, -16160, + -2801, -16143, -2900, -16125, -2999, -16107, -3098, -16088, + -3196, -16069, -3295, -16049, -3393, -16029, -3492, -16008, + -3590, -15986, -3688, -15964, -3786, -15941, -3883, -15917, + -3981, -15893, -4078, -15868, -4176, -15843, -4273, -15817, + -4370, -15791, -4467, -15763, -4563, -15736, -4660, -15707, + -4756, -15679, -4852, -15649, -4948, -15619, -5044, -15588, + -5139, -15557, -5235, -15525, -5330, -15493, -5425, -15460, + -5520, -15426, -5614, -15392, -5708, -15357, -5803, -15322, + -5897, -15286, -5990, -15250, -6084, -15213, -6177, -15175, + -6270, -15137, -6363, -15098, -6455, -15059, -6547, -15019, + -6639, -14978, -6731, -14937, -6823, -14896, -6914, -14854, + -7005, -14811, -7096, -14768, -7186, -14724, -7276, -14680, + -7366, -14635, -7456, -14589, -7545, -14543, -7635, -14497, + -7723, -14449, -7812, -14402, -7900, -14354, -7988, -14305, + -8076, -14256, -8163, -14206, -8250, -14155, -8337, -14104, + -8423, -14053, -8509, -14001, -8595, -13949, -8680, -13896, + -8765, -13842, -8850, -13788, -8935, -13733, -9019, -13678, + -9102, -13623, -9186, -13567, -9269, -13510, -9352, -13453, + -9434, -13395, -9516, -13337, -9598, -13279, -9679, -13219, + -9760, -13160, -9841, -13100, -9921, -13039, -10001, -12978, + -10080, -12916, -10159, -12854, -10238, -12792, -10316, -12729, + -10394, -12665, -10471, -12601, -10549, -12537, -10625, -12472, + -10702, -12406, -10778, -12340, -10853, -12274, -10928, -12207, + -11003, -12140, -11077, -12072, -11151, -12004, -11224, -11935, + -11297, -11866, -11370, -11797, -11442, -11727, -11514, -11656, + -11585, -11585, -11656, -11514, -11727, -11442, -11797, -11370, + -11866, -11297, -11935, -11224, -12004, -11151, -12072, -11077, + -12140, -11003, -12207, -10928, -12274, -10853, -12340, -10778, + -12406, -10702, -12472, -10625, -12537, -10549, -12601, -10471, + -12665, -10394, -12729, -10316, -12792, -10238, -12854, -10159, + -12916, -10080, -12978, -10001, -13039, -9921, -13100, -9840, + -13160, -9760, -13219, -9679, -13279, -9598, -13337, -9516, + -13395, -9434, -13453, -9352, -13510, -9269, -13567, -9186, + -13623, -9102, -13678, -9019, -13733, -8935, -13788, -8850, + -13842, -8765, -13896, -8680, -13949, -8595, -14001, -8509, + -14053, -8423, -14104, -8337, -14155, -8250, -14206, -8163, + -14256, -8076, -14305, -7988, -14354, -7900, -14402, -7812, + -14449, -7723, -14497, -7635, -14543, -7545, -14589, -7456, + -14635, -7366, -14680, -7276, -14724, -7186, -14768, -7096, + -14811, -7005, -14854, -6914, -14896, -6823, -14937, -6731, + -14978, -6639, -15019, -6547, -15059, -6455, -15098, -6363, + -15137, -6270, -15175, -6177, -15213, -6084, -15250, -5990, + -15286, -5897, -15322, -5803, -15357, -5708, -15392, -5614, + -15426, -5520, -15460, -5425, -15493, -5330, -15525, -5235, + -15557, -5139, -15588, -5044, -15619, -4948, -15649, -4852, + -15679, -4756, -15707, -4660, -15736, -4563, -15763, -4467, + -15791, -4370, -15817, -4273, -15843, -4176, -15868, -4078, + -15893, -3981, -15917, -3883, -15941, -3786, -15964, -3688, + -15986, -3590, -16008, -3492, -16029, -3393, -16049, -3295, + -16069, -3196, -16088, -3098, -16107, -2999, -16125, -2900, + -16143, -2801, -16160, -2702, -16176, -2603, -16192, -2503, + -16207, -2404, -16221, -2305, -16235, -2205, -16248, -2105, + -16261, -2006, -16273, -1906, -16284, -1806, -16295, -1706, + -16305, -1606, -16315, -1506, -16324, -1406, -16332, -1306, + -16340, -1205, -16347, -1105, -16353, -1005, -16359, -904, + -16364, -804, -16369, -703, -16373, -603, -16376, -503, + -16379, -402, -16381, -302, -16383, -201, -16384, -101, + /* The following is a duplication of the above but scaled up by a factor of 2. + * This save one operation in inverse FFT inner loops */ + 32767, 0, 32767, -201, 32766, -402, 32762, -603, + 32758, -804, 32753, -1005, 32746, -1206, 32738, -1407, + 32729, -1608, 32718, -1809, 32706, -2009, 32693, -2210, + 32679, -2411, 32664, -2611, 32647, -2811, 32629, -3012, + 32610, -3212, 32590, -3412, 32568, -3612, 32546, -3812, + 32522, -4011, 32496, -4211, 32470, -4410, 32442, -4609, + 32413, -4808, 32383, -5007, 32352, -5205, 32319, -5404, + 32286, -5602, 32251, -5800, 32214, -5998, 32177, -6195, + 32138, -6393, 32099, -6590, 32058, -6787, 32015, -6983, + 31972, -7180, 31927, -7376, 31881, -7571, 31834, -7767, + 31786, -7962, 31737, -8157, 31686, -8351, 31634, -8546, + 31581, -8740, 31527, -8933, 31471, -9127, 31415, -9319, + 31357, -9512, 31298, -9704, 31238, -9896, 31177, -10088, + 31114, -10279, 31050, -10469, 30986, -10660, 30920, -10850, + 30853, -11039, 30784, -11228, 30715, -11417, 30644, -11605, + 30572, -11793, 30499, -11980, 30425, -12167, 30350, -12354, + 30274, -12540, 30196, -12725, 30118, -12910, 30038, -13095, + 29957, -13279, 29875, -13463, 29792, -13646, 29707, -13828, + 29622, -14010, 29535, -14192, 29448, -14373, 29359, -14553, + 29269, -14733, 29178, -14912, 29086, -15091, 28993, -15269, + 28899, -15447, 28803, -15624, 28707, -15800, 28610, -15976, + 28511, -16151, 28411, -16326, 28311, -16500, 28209, -16673, + 28106, -16846, 28002, -17018, 27897, -17190, 27791, -17361, + 27684, -17531, 27576, -17700, 27467, -17869, 27357, -18037, + 27246, -18205, 27133, -18372, 27020, -18538, 26906, -18703, + 26791, -18868, 26674, -19032, 26557, -19195, 26439, -19358, + 26320, -19520, 26199, -19681, 26078, -19841, 25956, -20001, + 25833, -20160, 25708, -20318, 25583, -20475, 25457, -20632, + 25330, -20788, 25202, -20943, 25073, -21097, 24943, -21251, + 24812, -21403, 24680, -21555, 24548, -21706, 24414, -21856, + 24279, -22006, 24144, -22154, 24008, -22302, 23870, -22449, + 23732, -22595, 23593, -22740, 23453, -22884, 23312, -23028, + 23170, -23170, 23028, -23312, 22884, -23453, 22740, -23593, + 22595, -23732, 22449, -23870, 22302, -24008, 22154, -24144, + 22006, -24279, 21856, -24414, 21706, -24548, 21555, -24680, + 21403, -24812, 21251, -24943, 21097, -25073, 20943, -25202, + 20788, -25330, 20632, -25457, 20475, -25583, 20318, -25708, + 20160, -25833, 20001, -25956, 19841, -26078, 19681, -26199, + 19520, -26320, 19358, -26439, 19195, -26557, 19032, -26674, + 18868, -26791, 18703, -26906, 18538, -27020, 18372, -27133, + 18205, -27246, 18037, -27357, 17869, -27467, 17700, -27576, + 17531, -27684, 17361, -27791, 17190, -27897, 17018, -28002, + 16846, -28106, 16673, -28209, 16500, -28311, 16326, -28411, + 16151, -28511, 15976, -28610, 15800, -28707, 15624, -28803, + 15447, -28899, 15269, -28993, 15091, -29086, 14912, -29178, + 14733, -29269, 14553, -29359, 14373, -29448, 14192, -29535, + 14010, -29622, 13828, -29707, 13646, -29792, 13463, -29875, + 13279, -29957, 13095, -30038, 12910, -30118, 12725, -30196, + 12540, -30274, 12354, -30350, 12167, -30425, 11980, -30499, + 11793, -30572, 11605, -30644, 11417, -30715, 11228, -30784, + 11039, -30853, 10850, -30920, 10660, -30986, 10469, -31050, + 10279, -31114, 10088, -31177, 9896, -31238, 9704, -31298, + 9512, -31357, 9319, -31415, 9127, -31471, 8933, -31527, + 8740, -31581, 8546, -31634, 8351, -31686, 8157, -31737, + 7962, -31786, 7767, -31834, 7571, -31881, 7376, -31927, + 7180, -31972, 6983, -32015, 6787, -32058, 6590, -32099, + 6393, -32138, 6195, -32177, 5998, -32214, 5800, -32251, + 5602, -32286, 5404, -32319, 5205, -32352, 5007, -32383, + 4808, -32413, 4609, -32442, 4410, -32470, 4211, -32496, + 4011, -32522, 3812, -32546, 3612, -32568, 3412, -32590, + 3212, -32610, 3012, -32629, 2811, -32647, 2611, -32664, + 2411, -32679, 2210, -32693, 2009, -32706, 1809, -32718, + 1608, -32729, 1407, -32738, 1206, -32746, 1005, -32753, + 804, -32758, 603, -32762, 402, -32766, 201, -32767, + 0, -32768, -201, -32767, -402, -32766, -603, -32762, + -804, -32758, -1005, -32753, -1206, -32746, -1407, -32738, + -1608, -32729, -1809, -32718, -2009, -32706, -2210, -32693, + -2411, -32679, -2611, -32664, -2811, -32647, -3012, -32629, + -3212, -32610, -3412, -32590, -3612, -32568, -3812, -32546, + -4011, -32522, -4211, -32496, -4410, -32470, -4609, -32442, + -4808, -32413, -5007, -32383, -5205, -32352, -5404, -32319, + -5602, -32286, -5800, -32251, -5998, -32214, -6195, -32177, + -6393, -32138, -6590, -32099, -6787, -32058, -6983, -32015, + -7180, -31972, -7376, -31927, -7571, -31881, -7767, -31834, + -7962, -31786, -8157, -31737, -8351, -31686, -8546, -31634, + -8740, -31581, -8933, -31527, -9127, -31471, -9319, -31415, + -9512, -31357, -9704, -31298, -9896, -31238, -10088, -31177, + -10279, -31114, -10469, -31050, -10660, -30986, -10850, -30920, + -11039, -30853, -11228, -30784, -11417, -30715, -11605, -30644, + -11793, -30572, -11980, -30499, -12167, -30425, -12354, -30350, + -12540, -30274, -12725, -30196, -12910, -30118, -13095, -30038, + -13279, -29957, -13463, -29875, -13646, -29792, -13828, -29707, + -14010, -29622, -14192, -29535, -14373, -29448, -14553, -29359, + -14733, -29269, -14912, -29178, -15091, -29086, -15269, -28993, + -15447, -28899, -15624, -28803, -15800, -28707, -15976, -28610, + -16151, -28511, -16326, -28411, -16500, -28311, -16673, -28209, + -16846, -28106, -17018, -28002, -17190, -27897, -17361, -27791, + -17531, -27684, -17700, -27576, -17869, -27467, -18037, -27357, + -18205, -27246, -18372, -27133, -18538, -27020, -18703, -26906, + -18868, -26791, -19032, -26674, -19195, -26557, -19358, -26439, + -19520, -26320, -19681, -26199, -19841, -26078, -20001, -25956, + -20160, -25833, -20318, -25708, -20475, -25583, -20632, -25457, + -20788, -25330, -20943, -25202, -21097, -25073, -21251, -24943, + -21403, -24812, -21555, -24680, -21706, -24548, -21856, -24414, + -22006, -24279, -22154, -24144, -22302, -24008, -22449, -23870, + -22595, -23732, -22740, -23593, -22884, -23453, -23028, -23312, + -23170, -23170, -23312, -23028, -23453, -22884, -23593, -22740, + -23732, -22595, -23870, -22449, -24008, -22302, -24144, -22154, + -24279, -22006, -24414, -21856, -24548, -21706, -24680, -21555, + -24812, -21403, -24943, -21251, -25073, -21097, -25202, -20943, + -25330, -20788, -25457, -20632, -25583, -20475, -25708, -20318, + -25833, -20160, -25956, -20001, -26078, -19841, -26199, -19681, + -26320, -19520, -26439, -19358, -26557, -19195, -26674, -19032, + -26791, -18868, -26906, -18703, -27020, -18538, -27133, -18372, + -27246, -18205, -27357, -18037, -27467, -17869, -27576, -17700, + -27684, -17531, -27791, -17361, -27897, -17190, -28002, -17018, + -28106, -16846, -28209, -16673, -28311, -16500, -28411, -16326, + -28511, -16151, -28610, -15976, -28707, -15800, -28803, -15624, + -28899, -15447, -28993, -15269, -29086, -15091, -29178, -14912, + -29269, -14733, -29359, -14553, -29448, -14373, -29535, -14192, + -29622, -14010, -29707, -13828, -29792, -13646, -29875, -13463, + -29957, -13279, -30038, -13095, -30118, -12910, -30196, -12725, + -30274, -12540, -30350, -12354, -30425, -12167, -30499, -11980, + -30572, -11793, -30644, -11605, -30715, -11417, -30784, -11228, + -30853, -11039, -30920, -10850, -30986, -10660, -31050, -10469, + -31114, -10279, -31177, -10088, -31238, -9896, -31298, -9704, + -31357, -9512, -31415, -9319, -31471, -9127, -31527, -8933, + -31581, -8740, -31634, -8546, -31686, -8351, -31737, -8157, + -31786, -7962, -31834, -7767, -31881, -7571, -31927, -7376, + -31972, -7180, -32015, -6983, -32058, -6787, -32099, -6590, + -32138, -6393, -32177, -6195, -32214, -5998, -32251, -5800, + -32286, -5602, -32319, -5404, -32352, -5205, -32383, -5007, + -32413, -4808, -32442, -4609, -32470, -4410, -32496, -4211, + -32522, -4011, -32546, -3812, -32568, -3612, -32590, -3412, + -32610, -3212, -32629, -3012, -32647, -2811, -32664, -2611, + -32679, -2411, -32693, -2210, -32706, -2009, -32718, -1809, + -32729, -1608, -32738, -1407, -32746, -1206, -32753, -1005, + -32758, -804, -32762, -603, -32766, -402, -32767, -201 +}; + +const Word16 sincos_t_rad3_fx[T_SIN_PI_2+1] = +{ + 0, 134, 268, 402, 536, 670, 804, 938, + 1072, 1206, 1340, 1474, 1608, 1742, 1876, 2009, + 2143, 2277, 2411, 2544, 2678, 2811, 2945, 3078, + 3212, 3345, 3479, 3612, 3745, 3878, 4011, 4144, + 4277, 4410, 4543, 4675, 4808, 4941, 5073, 5205, + 5338, 5470, 5602, 5734, 5866, 5998, 6130, 6261, + 6393, 6524, 6655, 6787, 6918, 7049, 7180, 7310, + 7441, 7571, 7702, 7832, 7962, 8092, 8222, 8351, + 8481, 8610, 8740, 8869, 8998, 9127, 9255, 9384, + 9512, 9640, 9768, 9896, 10024, 10151, 10279, 10406, + 10533, 10660, 10786, 10913, 11039, 11165, 11291, 11417, + 11543, 11668, 11793, 11918, 12043, 12167, 12292, 12416, + 12540, 12664, 12787, 12910, 13033, 13156, 13279, 13401, + 13524, 13646, 13767, 13889, 14010, 14131, 14252, 14373, + 14493, 14613, 14733, 14852, 14972, 15091, 15210, 15328, + 15447, 15565, 15683, 15800, 15917, 16035, 16151, 16268, + 16384, 16500, 16616, 16731, 16846, 16961, 17075, 17190, + 17304, 17417, 17531, 17644, 17757, 17869, 17981, 18093, + 18205, 18316, 18427, 18538, 18648, 18758, 18868, 18978, + 19087, 19195, 19304, 19412, 19520, 19627, 19735, 19841, + 19948, 20054, 20160, 20265, 20371, 20475, 20580, 20684, + 20788, 20891, 20994, 21097, 21199, 21301, 21403, 21504, + 21605, 21706, 21806, 21906, 22006, 22105, 22204, 22302, + 22400, 22498, 22595, 22692, 22788, 22884, 22980, 23076, + 23170, 23265, 23359, 23453, 23546, 23640, 23732, 23824, + 23916, 24008, 24099, 24189, 24279, 24369, 24459, 24548, + 24636, 24724, 24812, 24900, 24986, 25073, 25159, 25245, + 25330, 25415, 25499, 25583, 25667, 25750, 25833, 25915, + 25997, 26078, 26159, 26239, 26320, 26399, 26478, 26557, + 26635, 26713, 26791, 26868, 26944, 27020, 27096, 27171, + 27246, 27320, 27394, 27467, 27540, 27612, 27684, 27756, + 27827, 27897, 27967, 28037, 28106, 28175, 28243, 28311, + 28378, 28445, 28511, 28577, 28642, 28707, 28771, 28835, + 28899, 28962, 29024, 29086, 29148, 29209, 29269, 29329, + 29389, 29448, 29506, 29564, 29622, 29679, 29736, 29792, + 29847, 29902, 29957, 30011, 30064, 30118, 30170, 30222, + 30274, 30325, 30375, 30425, 30475, 30524, 30572, 30620, + 30668, 30715, 30761, 30807, 30853, 30897, 30942, 30986, + 31029, 31072, 31114, 31156, 31197, 31238, 31278, 31318, + 31357, 31396, 31434, 31471, 31508, 31545, 31581, 31617, + 31651, 31686, 31720, 31753, 31786, 31818, 31850, 31881, + 31912, 31942, 31972, 32001, 32029, 32058, 32085, 32112, + 32138, 32164, 32190, 32214, 32239, 32262, 32286, 32308, + 32330, 32352, 32373, 32393, 32413, 32433, 32452, 32470, + 32488, 32505, 32522, 32538, 32553, 32568, 32583, 32597, + 32610, 32623, 32635, 32647, 32658, 32669, 32679, 32689, + 32698, 32706, 32714, 32722, 32729, 32735, 32741, 32746, + 32750, 32755, 32758, 32761, 32764, 32766, 32767, 32767, + 32767 +}; + +/*----------------------------------------------------------------------------------* + * Sine & Cosine - table for the FFT and IFFT of 1024 points, value range [0 ... sin(-5pi/4)] + * dimension of the table = 641=4*256*(5/8)+1 + *----------------------------------------------------------------------------------*/ +/* every 4th value is identical to sincos_t above, (but sincos_t is also used by swb_tbe_com) a separate table is used */ +const Word16 sincos_t_ext_fx[641] = +{ + 0, 201, 402, 603, 804, 1005, 1206, 1407, + 1608, 1809, 2009, 2210, 2411, 2611, 2811, 3012, + 3212, 3412, 3612, 3812, 4011, 4211, 4410, 4609, + 4808, 5007, 5205, 5404, 5602, 5800, 5998, 6195, + 6393, 6590, 6787, 6983, 7180, 7376, 7571, 7767, + 7962, 8157, 8351, 8546, 8740, 8933, 9127, 9319, + 9512, 9704, 9896, 10088, 10279, 10469, 10660, 10850, + 11039, 11228, 11417, 11605, 11793, 11980, 12167, 12354, + 12540, 12725, 12910, 13095, 13279, 13463, 13646, 13828, + 14010, 14192, 14373, 14553, 14733, 14912, 15091, 15269, + 15447, 15624, 15800, 15976, 16151, 16326, 16500, 16673, + 16846, 17018, 17190, 17361, 17531, 17700, 17869, 18037, + 18205, 18372, 18538, 18703, 18868, 19032, 19195, 19358, + 19520, 19681, 19841, 20001, 20160, 20318, 20475, 20632, + 20788, 20943, 21097, 21251, 21403, 21555, 21706, 21856, + 22006, 22154, 22302, 22449, 22595, 22740, 22884, 23028, + 23170, 23312, 23453, 23593, 23732, 23870, 24008, 24144, + 24279, 24414, 24548, 24680, 24812, 24943, 25073, 25202, + 25330, 25457, 25583, 25708, 25833, 25956, 26078, 26199, + 26320, 26439, 26557, 26674, 26791, 26906, 27020, 27133, + 27246, 27357, 27467, 27576, 27684, 27791, 27897, 28002, + 28106, 28209, 28311, 28411, 28511, 28610, 28707, 28803, + 28899, 28993, 29086, 29178, 29269, 29359, 29448, 29535, + 29622, 29707, 29792, 29875, 29957, 30038, 30118, 30196, + 30274, 30350, 30425, 30499, 30572, 30644, 30715, 30784, + 30853, 30920, 30986, 31050, 31114, 31177, 31238, 31298, + 31357, 31415, 31471, 31527, 31581, 31634, 31686, 31737, + 31786, 31834, 31881, 31927, 31972, 32015, 32058, 32099, + 32138, 32177, 32214, 32251, 32286, 32319, 32352, 32383, + 32413, 32442, 32470, 32496, 32522, 32546, 32568, 32590, + 32610, 32629, 32647, 32664, 32679, 32693, 32706, 32718, + 32729, 32738, 32746, 32753, 32758, 32762, 32766, 32767, + 32767, 32767, 32766, 32762, 32758, 32753, 32746, 32738, + 32729, 32718, 32706, 32693, 32679, 32664, 32647, 32629, + 32610, 32590, 32568, 32546, 32522, 32496, 32470, 32442, + 32413, 32383, 32352, 32319, 32286, 32251, 32214, 32177, + 32138, 32099, 32058, 32015, 31972, 31927, 31881, 31834, + 31786, 31737, 31686, 31634, 31581, 31527, 31471, 31415, + 31357, 31298, 31238, 31177, 31114, 31050, 30986, 30920, + 30853, 30784, 30715, 30644, 30572, 30499, 30425, 30350, + 30274, 30196, 30118, 30038, 29957, 29875, 29792, 29707, + 29622, 29535, 29448, 29359, 29269, 29178, 29086, 28993, + 28899, 28803, 28707, 28610, 28511, 28411, 28311, 28209, + 28106, 28002, 27897, 27791, 27684, 27576, 27467, 27357, + 27246, 27133, 27020, 26906, 26791, 26674, 26557, 26439, + 26320, 26199, 26078, 25956, 25833, 25708, 25583, 25457, + 25330, 25202, 25073, 24943, 24812, 24680, 24548, 24414, + 24279, 24144, 24008, 23870, 23732, 23593, 23453, 23312, + 23170, 23028, 22884, 22740, 22595, 22449, 22302, 22154, + 22006, 21856, 21706, 21555, 21403, 21251, 21097, 20943, + 20788, 20632, 20475, 20318, 20160, 20001, 19841, 19681, + 19520, 19358, 19195, 19032, 18868, 18703, 18538, 18372, + 18205, 18037, 17869, 17700, 17531, 17361, 17190, 17018, + 16846, 16673, 16500, 16326, 16151, 15976, 15800, 15624, + 15447, 15269, 15091, 14912, 14733, 14553, 14373, 14192, + 14010, 13828, 13646, 13463, 13279, 13095, 12910, 12725, + 12540, 12354, 12167, 11980, 11793, 11605, 11417, 11228, + 11039, 10850, 10660, 10469, 10279, 10088, 9896, 9704, + 9512, 9319, 9127, 8933, 8740, 8546, 8351, 8157, + 7962, 7767, 7571, 7376, 7180, 6983, 6787, 6590, + 6393, 6195, 5998, 5800, 5602, 5404, 5205, 5007, + 4808, 4609, 4410, 4211, 4011, 3812, 3612, 3412, + 3212, 3012, 2811, 2611, 2411, 2210, 2009, 1809, + 1608, 1407, 1206, 1005, 804, 603, 402, 201, + 0, -201, -402, -603, -804, -1005, -1206, -1407, + -1608, -1809, -2009, -2210, -2411, -2611, -2811, -3012, + -3212, -3412, -3612, -3812, -4011, -4211, -4410, -4609, + -4808, -5007, -5205, -5404, -5602, -5800, -5998, -6195, + -6393, -6590, -6787, -6983, -7180, -7376, -7571, -7767, + -7962, -8157, -8351, -8546, -8740, -8933, -9127, -9319, + -9512, -9704, -9896, -10088, -10279, -10469, -10660, -10850, + -11039, -11228, -11417, -11605, -11793, -11980, -12167, -12354, + -12540, -12725, -12910, -13095, -13279, -13463, -13646, -13828, + -14010, -14192, -14373, -14553, -14733, -14912, -15091, -15269, + -15447, -15624, -15800, -15976, -16151, -16326, -16500, -16673, + -16846, -17018, -17190, -17361, -17531, -17700, -17869, -18037, + -18205, -18372, -18538, -18703, -18868, -19032, -19195, -19358, + -19520, -19681, -19841, -20001, -20160, -20318, -20475, -20632, + -20788, -20943, -21097, -21251, -21403, -21555, -21706, -21856, + -22006, -22154, -22302, -22449, -22595, -22740, -22884, -23028, + -23028 +}; + + + + +const Word16 FFT_REORDER_1024[512] = +{ + 0, 512, 256, 768, 128, 640, 384, 896, + 64, 576, 320, 832, 192, 704, 448, 960, + 32, 544, 288, 800, 160, 672, 416, 928, + 96, 608, 352, 864, 224, 736, 480, 992, + 16, 528, 272, 784, 144, 656, 400, 912, + 80, 592, 336, 848, 208, 720, 464, 976, + 48, 560, 304, 816, 176, 688, 432, 944, + 112, 624, 368, 880, 240, 752, 496, 1008, + 8, 520, 264, 776, 136, 648, 392, 904, + 72, 584, 328, 840, 200, 712, 456, 968, + 40, 552, 296, 808, 168, 680, 424, 936, + 104, 616, 360, 872, 232, 744, 488, 1000, + 24, 536, 280, 792, 152, 664, 408, 920, + 88, 600, 344, 856, 216, 728, 472, 984, + 56, 568, 312, 824, 184, 696, 440, 952, + 120, 632, 376, 888, 248, 760, 504, 1016, + 4, 516, 260, 772, 132, 644, 388, 900, + 68, 580, 324, 836, 196, 708, 452, 964, + 36, 548, 292, 804, 164, 676, 420, 932, + 100, 612, 356, 868, 228, 740, 484, 996, + 20, 532, 276, 788, 148, 660, 404, 916, + 84, 596, 340, 852, 212, 724, 468, 980, + 52, 564, 308, 820, 180, 692, 436, 948, + 116, 628, 372, 884, 244, 756, 500, 1012, + 12, 524, 268, 780, 140, 652, 396, 908, + 76, 588, 332, 844, 204, 716, 460, 972, + 44, 556, 300, 812, 172, 684, 428, 940, + 108, 620, 364, 876, 236, 748, 492, 1004, + 28, 540, 284, 796, 156, 668, 412, 924, + 92, 604, 348, 860, 220, 732, 476, 988, + 60, 572, 316, 828, 188, 700, 444, 956, + 124, 636, 380, 892, 252, 764, 508, 1020, + 2, 514, 258, 770, 130, 642, 386, 898, + 66, 578, 322, 834, 194, 706, 450, 962, + 34, 546, 290, 802, 162, 674, 418, 930, + 98, 610, 354, 866, 226, 738, 482, 994, + 18, 530, 274, 786, 146, 658, 402, 914, + 82, 594, 338, 850, 210, 722, 466, 978, + 50, 562, 306, 818, 178, 690, 434, 946, + 114, 626, 370, 882, 242, 754, 498, 1010, + 10, 522, 266, 778, 138, 650, 394, 906, + 74, 586, 330, 842, 202, 714, 458, 970, + 42, 554, 298, 810, 170, 682, 426, 938, + 106, 618, 362, 874, 234, 746, 490, 1002, + 26, 538, 282, 794, 154, 666, 410, 922, + 90, 602, 346, 858, 218, 730, 474, 986, + 58, 570, 314, 826, 186, 698, 442, 954, + 122, 634, 378, 890, 250, 762, 506, 1018, + 6, 518, 262, 774, 134, 646, 390, 902, + 70, 582, 326, 838, 198, 710, 454, 966, + 38, 550, 294, 806, 166, 678, 422, 934, + 102, 614, 358, 870, 230, 742, 486, 998, + 22, 534, 278, 790, 150, 662, 406, 918, + 86, 598, 342, 854, 214, 726, 470, 982, + 54, 566, 310, 822, 182, 694, 438, 950, + 118, 630, 374, 886, 246, 758, 502, 1014, + 14, 526, 270, 782, 142, 654, 398, 910, + 78, 590, 334, 846, 206, 718, 462, 974, + 46, 558, 302, 814, 174, 686, 430, 942, + 110, 622, 366, 878, 238, 750, 494, 1006, + 30, 542, 286, 798, 158, 670, 414, 926, + 94, 606, 350, 862, 222, 734, 478, 990, + 62, 574, 318, 830, 190, 702, 446, 958, + 126, 638, 382, 894, 254, 766, 510, 1022 +}; + +const Word16 Gamma_19661_Tbl_fx[] = +{ + 19661, 11797, 7078, 4247, 2548, 1529, 917, 550, 330, 198, 119, 71, 43, 26, 16, 10 +};/*Q15 */ + +/*-----------------------------------------------------------------* + * Transition coding - gain quantization table for g_trans + *-----------------------------------------------------------------*/ +const Word16 tbl_gain_trans_tc_fx[N_GAIN_TC] = +{ + 4588, 11109, 19212, 29862,/*<- Q7 +Q4 ->*/ 5536, 8184, 13115, 24000 +}; +/*-----------------------------------------------------------------* + * Transition coding - table of prototype glottal impulses + *-----------------------------------------------------------------*/ +const Word16 Glottal_cdbk_fx[L_IMPULSE*NUM_IMPULSE] = /*Q13*/ +{ + /* impulse 0 */ + -715, -1690, -2903, -1742, -1295, -4266, + -4893, 1725, 8192, 5812, -628, -1956, + 581, 936, -81, 831, 1517, + + /* impulse 1 */ + -2168, -1356, -404, -2715, -4469, -2164, + -2180, -8058, -9140, 1163, 10343, 6677, + -1758, -2839, 377, 326, -490, + + /* impulse 2 */ + 360, 561, 4184, 2533, -3326, -2549, + 2059, -2112, -9542, -6134, 1307, 124, + -3421, -1465, 475, -886, -1262, + + /* impulse 3 */ + -1294, -715, -184, -1544, -1638, -219, + -3503, -9409, -7955, -1407, -285, -2494, + 305, 4658, 3289, 116, 1488, + + /* impulse 4 */ + 837, 2523, 2444, 2679, 5962, 6935, + -924, -9907, -7565, 643, 1350, -2577, + -2100, -277, -1546, -2279, -882, + + /* impulse 5 */ + -418, -886, -48, -494, -2368, -2060, + -1233, -5271,-10430, -6955, 3301, 7578, + 2599, -1665, -461, 735, -181, + + /* impulse 6 */ + -467, -1865, -1455, -127, -1881, -3776, + 822, 8335, 8192, 863, -2762, -375, + 757, -558, -285, 653, 150, + + /* impulse 7 */ + 1087, 471, -618, 706, 1546, -1605, + -3256, 2396, 8060, 5189, -99, -37, + 1105, -668, -1434, -59, -81 +}; + +/*----------------------------------------------------------------------------------* + * Gaussian codebook + *----------------------------------------------------------------------------------*/ +/*table in Q12*/ +const Word16 gaus_dico_fx[190] = +{ + -399, -125, 523, -466, 305, -658, -809, 47, + -141, -171, -583, -259, 296, 1334, -285, -401, + -478, -418, 140, -540, 177, -1089, 130, -292, + 143, 492, -310, -862, -320, 388, 546, 84, + -1202, 107, 108, 340, 239, -130, 930, 342, + 153, -264, -763, -113, 387, -535, 83, -856, + -361, -421, 120, 396, -367, 640, 817, 222, + -1017, -82, -120, 890, 340, -384, 47, 339, + -505, -430, 161, 979, 890, -267, 104, 508, + -150, -194, 442, 193, 413, -24, 395, -43, + -217, 69, -398, 167, 116, -936, -95, 1466, + -435, 461, 862, -136, -94, 1311, -371, 68, + 134, -296, -156, -564, -48, -487, 647, 315, + 513, -101, -685, -318, -344, -644, -66, 851, + 414, -29, 509, 414, 502, 399, 557, 649, + -299, 750, 546, -756, -12, -365, 593, -707, + 394, -131, -375, -62, -914, -256, -424, 64, + 464, -1140, 280, 91, -83, -288, -550, 389, + 52, -1228, 6, -430, 74, 205, -478, -148, + -592, 282, -73, 1212, 42, 580, -334, 484, + -765, 443, 649, 271, -739, 375, 613, -460, + -208, 235, -120, -49, -311, 605, 875, 521, + 202, -506, -548, -1088, -43, -221, 673, -245, + -27, 469, 353, 53, 744, 275 +}; + +const Word16 Idx_dortft320_16fx[320] = +{ + 0,65,130,195,260,5,70,135,200,265,10,75,140,205,270,15,80,145,210,275,20,85,150,215,280,25,90,155,220,285,30,95, + 160,225,290,35,100,165,230,295,40,105,170,235,300,45,110,175,240,305,50,115,180,245,310,55,120,185,250,315,60,125, + 190,255,256,1,66,131,196,261,6,71,136,201,266,11,76,141,206,271,16,81,146,211,276,21,86,151,216,281,26,91,156,221, + 286,31,96,161,226,291,36,101,166,231,296,41,106,171,236,301,46,111,176,241,306,51,116,181,246,311,56,121,186,251, + 316,61,126,191,192,257,2,67,132,197,262,7,72,137,202,267,12,77,142,207,272,17,82,147,212,277,22,87,152,217,282,27, + 92,157,222,287,32,97,162,227,292,37,102,167,232,297,42,107,172,237,302,47,112,177,242,307,52,117,182,247,312,57,122, + 187,252,317,62,127,128,193,258,3,68,133,198,263,8,73,138,203,268,13,78,143,208,273,18,83,148,213,278,23,88,153,218, + 283,28,93,158,223,288,33,98,163,228,293,38,103,168,233,298,43,108,173,238,303,48,113,178,243,308,53,118,183,248,313, + 58,123,188,253,318,63,64,129,194,259,4,69,134,199,264,9,74,139,204,269,14,79,144,209,274,19,84,149,214,279,24,89,154, + 219,284,29,94,159,224,289,34,99,164,229,294,39,104,169,234,299,44,109,174,239,304,49,114,179,244,309,54,119,184,249, + 314,59,124,189,254,319 +}; +const Word16 Ip_fft128_16fx[10] = {64, 1, 0, 128, 64, 192, 32, 160, 96, 224}; +const Word32 w_fft128_16fx[64] = +{ + 1073741824, 0, 759250112, 759250112, 992008064, 410903232, 410903232, 992008064, + 1053110144, 209476640, 596539008, 892783680, 892783680, 596539008, 209476640, 1053110144, + 1068571456, 105245104, 681174592, 830013632, 946955712, 506158400, 311690816, 1027506880, + 1027506880, 311690816, 506158400, 946955712, 830013632, 681174592, 105245104, 1068571456, + 1072448448, 52686008, 721080960, 795590208, 970651136, 459083776, 361732736, 1010975232, + 1041563136, 260897968, 552013632, 920979072, 862437504, 639627264, 157550640, 1062120192, + 1062120192, 157550640, 639627264, 862437504, 920979072, 552013632, 260897968, 1041563136, + 1010975232, 361732736, 459083776, 970651136, 795590208, 721080960, 52686008, 1072448448, +}; +const Word16 Ip_fft32_16fx[6] = {16,1,0,32,16,48}; +const Word16 Ip_fft64_16fx[6] = {32,1,0,64,32,96}; +const Word16 Odx_fft64_16fx[64] = +{ + 0,59,54,49,44,39,34,29,24,19,14,9,4,63,58,53,48,43,38,33,28,23,18,13,8,3,62,57,52,47,42,37, + 32,27,22,17,12,7,2,61,56,51,46,41,36,31,26,21,16,11,6,1,60,55,50,45,40,35,30,25,20,15,10,5 +}; +const Word32 w_fft32_16fx[16] = +{ + 1073741824, 0, 759250113, 759250113, 992008059, 410903236, 410903236, 992008059, + 1053110143, 209476636, 596539003, 892783685, 892783685, 596539003, 209476636, 1053110143 +}; +const Word16 edct_table_320_16fx[320] = +{ + 7747, 7747, 7747, 7746, 7746, 7745, 7744, 7742, + 7741, 7739, 7737, 7735, 7733, 7730, 7728, 7725, + 7722, 7719, 7716, 7712, 7708, 7704, 7700, 7696, + 7692, 7687, 7682, 7677, 7672, 7666, 7661, 7655, + 7649, 7643, 7637, 7630, 7623, 7617, 7610, 7602, + 7595, 7587, 7580, 7572, 7563, 7555, 7547, 7538, + 7529, 7520, 7511, 7501, 7492, 7482, 7472, 7462, + 7451, 7441, 7430, 7419, 7408, 7397, 7386, 7374, + 7362, 7350, 7338, 7326, 7314, 7301, 7288, 7275, + 7262, 7249, 7235, 7221, 7208, 7194, 7179, 7165, + 7150, 7136, 7121, 7106, 7091, 7075, 7060, 7044, + 7028, 7012, 6995, 6979, 6962, 6946, 6929, 6912, + 6894, 6877, 6859, 6842, 6824, 6806, 6787, 6769, + 6750, 6732, 6713, 6694, 6674, 6655, 6635, 6616, + 6596, 6576, 6556, 6535, 6515, 6494, 6473, 6452, + 6431, 6410, 6388, 6367, 6345, 6323, 6301, 6279, + 6257, 6234, 6211, 6189, 6166, 6143, 6119, 6096, + 6072, 6049, 6025, 6001, 5977, 5953, 5928, 5904, + 5879, 5854, 5829, 5804, 5779, 5753, 5728, 5702, + 5676, 5650, 5624, 5598, 5572, 5545, 5518, 5492, + 5465, 5438, 5411, 5383, 5356, 5328, 5301, 5273, + 5245, 5217, 5189, 5160, 5132, 5104, 5075, 5046, + 5017, 4988, 4959, 4930, 4900, 4871, 4841, 4811, + 4781, 4751, 4721, 4691, 4661, 4630, 4600, 4569, + 4538, 4508, 4477, 4446, 4414, 4383, 4352, 4320, + 4288, 4257, 4225, 4193, 4161, 4129, 4097, 4064, + 4032, 3999, 3967, 3934, 3901, 3868, 3835, 3802, + 3769, 3736, 3702, 3669, 3635, 3602, 3568, 3534, + 3500, 3466, 3432, 3398, 3364, 3330, 3295, 3261, + 3226, 3192, 3157, 3122, 3087, 3052, 3017, 2982, + 2947, 2912, 2877, 2841, 2806, 2771, 2735, 2699, + 2664, 2628, 2592, 2556, 2520, 2484, 2448, 2412, + 2376, 2340, 2304, 2267, 2231, 2194, 2158, 2121, + 2085, 2048, 2011, 1975, 1938, 1901, 1864, 1827, + 1790, 1753, 1716, 1679, 1642, 1605, 1567, 1530, + 1493, 1455, 1418, 1381, 1343, 1306, 1268, 1231, + 1193, 1156, 1118, 1080, 1043, 1005, 967, 930, + 892, 854, 816, 778, 740, 703, 665, 627, + 589, 551, 513, 475, 437, 399, 361, 323, + 285, 247, 209, 171, 133, 95, 57, 19 +}; +const Word16 edct_table_128_16fx[128] = /*Q15 */ +{ + 9742, 9740, 9737, 9733, 9727, 9720, 9711, 9701, + 9689, 9676, 9661, 9645, 9627, 9608, 9588, 9566, + 9543, 9518, 9492, 9464, 9435, 9405, 9373, 9339, + 9305, 9269, 9231, 9192, 9152, 9110, 9067, 9023, + 8977, 8930, 8882, 8832, 8781, 8728, 8675, 8619, + 8563, 8505, 8447, 8386, 8325, 8262, 8198, 8133, + 8067, 7999, 7930, 7860, 7789, 7717, 7643, 7568, + 7492, 7415, 7337, 7258, 7178, 7097, 7014, 6931, + 6846, 6761, 6674, 6586, 6498, 6408, 6318, 6226, + 6134, 6040, 5946, 5851, 5755, 5658, 5560, 5462, + 5362, 5262, 5161, 5059, 4957, 4854, 4750, 4645, + 4539, 4433, 4327, 4219, 4111, 4002, 3893, 3783, + 3673, 3562, 3450, 3338, 3226, 3113, 2999, 2885, + 2771, 2656, 2541, 2425, 2309, 2193, 2076, 1959, + 1842, 1724, 1607, 1489, 1370, 1252, 1133, 1014, + 895, 776, 657, 538, 418, 299, 179, 60 +}; +const Word16 edct_table_160_16fx[160] = +{ + 9213, 9212, 9211, 9208, 9204, 9200, 9195, 9188, + 9181, 9173, 9164, 9155, 9144, 9132, 9120, 9107, + 9093, 9078, 9062, 9045, 9027, 9009, 8989, 8969, + 8948, 8926, 8903, 8880, 8855, 8830, 8803, 8776, + 8748, 8719, 8690, 8659, 8628, 8596, 8563, 8529, + 8495, 8459, 8423, 8386, 8348, 8309, 8270, 8230, + 8188, 8147, 8104, 8061, 8016, 7971, 7926, 7879, + 7832, 7784, 7735, 7686, 7635, 7584, 7533, 7480, + 7427, 7373, 7319, 7263, 7207, 7151, 7093, 7035, + 6976, 6917, 6857, 6796, 6735, 6673, 6610, 6547, + 6483, 6418, 6353, 6287, 6221, 6154, 6086, 6018, + 5949, 5880, 5810, 5739, 5668, 5597, 5525, 5452, + 5379, 5305, 5231, 5156, 5081, 5005, 4929, 4852, + 4775, 4698, 4620, 4541, 4462, 4383, 4303, 4223, + 4142, 4061, 3980, 3898, 3816, 3734, 3651, 3568, + 3484, 3400, 3316, 3231, 3146, 3061, 2976, 2890, + 2804, 2718, 2631, 2544, 2457, 2370, 2282, 2195, + 2107, 2019, 1930, 1842, 1753, 1664, 1575, 1486, + 1397, 1307, 1218, 1128, 1038, 948, 858, 768, + 678, 588, 497, 407, 317, 226, 136, 45 +}; + +const Word16 ip_edct2_64_fx[6] = {16, 64, 0, 32, 16, 48}; + +const Word16 w_edct2_64_fx[80] = /*Q14 */ +{ + 16384, 0, 11585, 11585, 15137, 6270, 6270, 15137, + 16069, 3196, 9102, 13623, 13623, 9102, 3196, 16069, + 11585, 8190, 8182, 8170, 8153, 8130, 8103, 8071, + 8035, 7993, 7946, 7895, 7839, 7779, 7713, 7643, + 7568, 7489, 7405, 7317, 7225, 7128, 7027, 6921, + 6811, 6698, 6580, 6458, 6333, 6203, 6070, 5933, + 5793, 5649, 5501, 5351, 5197, 5040, 4880, 4717, + 4551, 4383, 4212, 4038, 3862, 3683, 3503, 3320, + 3135, 2948, 2760, 2570, 2378, 2185, 1990, 1795, + 1598, 1401, 1202, 1003, 803, 603, 402, 201 +}; +/*------------------------------------------------------------------------------* + * FIX POINT EDCT tables + *------------------------------------------------------------------------------*/ +const Word16 edct_table_80_fx[80] = /*Q16 */ +{ + 21911, 21903, 21886, 21860, 21827, 21784, 21734, 21675, + 21608, 21532, 21448, 21356, 21255, 21147, 21030, 20905, + 20772, 20631, 20482, 20325, 20161, 19988, 19808, 19621, + 19425, 19222, 19012, 18795, 18570, 18338, 18099, 17853, + 17600, 17340, 17074, 16801, 16522, 16236, 15944, 15646, + 15341, 15031, 14715, 14394, 14067, 13734, 13396, 13053, + 12705, 12352, 11994, 11632, 11265, 10894, 10519, 10139, + 9756, 9369, 8978, 8584, 8186, 7786, 7382, 6975, + 6566, 6155, 5741, 5324, 4906, 4486, 4064, 3640, + 3215, 2789, 2362, 1934, 1505, 1075, 645, 215 +}; + +const Word16 edct_table_100_fx[] = +{ + 20723, 20718, 20708, 20692, 20672, 20646, 20616, 20580, + 20539, 20493, 20442, 20386, 20325, 20259, 20188, 20112, + 20031, 19946, 19855, 19759, 19658, 19553, 19443, 19328, + 19208, 19083, 18954, 18820, 18681, 18538, 18390, 18238, + 18081, 17920, 17754, 17584, 17410, 17231, 17048, 16861, + 16670, 16474, 16275, 16071, 15864, 15652, 15437, 15218, + 14995, 14768, 14538, 14304, 14067, 13826, 13582, 13335, + 13084, 12830, 12573, 12312, 12049, 11783, 11513, 11241, + 10966, 10689, 10409, 10126, 9841, 9553, 9263, 8971, + 8676, 8379, 8081, 7780, 7477, 7173, 6867, 6559, + 6249, 5938, 5625, 5311, 4996, 4679, 4362, 4043, + 3723, 3403, 3081, 2759, 2436, 2112, 1788, 1464, + 1139, 814, 488, 163 +}; + +const Word16 edct_table_120_fx[120] = /*Q16 */ +{ + 19800, 19797, 19790, 19780, 19766, 19749, 19729, 19705, + 19678, 19648, 19614, 19576, 19536, 19492, 19445, 19394, + 19340, 19283, 19223, 19159, 19092, 19021, 18948, 18871, + 18791, 18708, 18621, 18531, 18438, 18342, 18243, 18141, + 18035, 17927, 17815, 17701, 17583, 17462, 17339, 17212, + 17082, 16950, 16815, 16676, 16535, 16391, 16244, 16095, + 15942, 15787, 15629, 15469, 15306, 15140, 14972, 14801, + 14628, 14452, 14273, 14092, 13909, 13723, 13535, 13345, + 13152, 12958, 12761, 12561, 12360, 12156, 11951, 11743, + 11533, 11322, 11108, 10893, 10675, 10456, 10235, 10012, + 9788, 9562, 9334, 9104, 8874, 8641, 8407, 8172, + 7935, 7697, 7457, 7217, 6975, 6732, 6487, 6242, + 5995, 5748, 5499, 5250, 4999, 4748, 4496, 4243, + 3990, 3736, 3481, 3225, 2969, 2713, 2456, 2199, + 1941, 1683, 1424, 1166, 907, 648, 389, 130 +}; + +const Word16 edct_table_320_fx[320] = /*Q16 */ +{ + 15495, 15495, 15494, 15493, 15491, 15489, 15487, 15484, + 15481, 15478, 15474, 15470, 15466, 15461, 15456, 15450, + 15444, 15438, 15431, 15424, 15417, 15409, 15401, 15392, + 15383, 15374, 15364, 15354, 15344, 15333, 15322, 15310, + 15298, 15286, 15273, 15260, 15247, 15233, 15219, 15205, + 15190, 15175, 15159, 15143, 15127, 15110, 15093, 15076, + 15058, 15040, 15021, 15002, 14983, 14964, 14944, 14924, + 14903, 14882, 14860, 14839, 14817, 14794, 14771, 14748, + 14725, 14701, 14677, 14652, 14627, 14602, 14576, 14550, + 14524, 14497, 14470, 14443, 14415, 14387, 14359, 14330, + 14301, 14271, 14242, 14212, 14181, 14150, 14119, 14088, + 14056, 14024, 13991, 13958, 13925, 13891, 13858, 13823, + 13789, 13754, 13719, 13683, 13647, 13611, 13575, 13538, + 13501, 13463, 13425, 13387, 13349, 13310, 13271, 13231, + 13192, 13152, 13111, 13071, 13030, 12988, 12947, 12905, + 12862, 12820, 12777, 12734, 12690, 12647, 12602, 12558, + 12513, 12468, 12423, 12377, 12331, 12285, 12239, 12192, + 12145, 12098, 12050, 12002, 11954, 11905, 11856, 11807, + 11758, 11708, 11658, 11608, 11557, 11507, 11455, 11404, + 11352, 11301, 11248, 11196, 11143, 11090, 11037, 10983, + 10930, 10876, 10821, 10767, 10712, 10657, 10601, 10546, + 10490, 10434, 10378, 10321, 10264, 10207, 10150, 10092, + 10034, 9976, 9918, 9859, 9800, 9741, 9682, 9623, + 9563, 9503, 9443, 9382, 9322, 9261, 9200, 9138, + 9077, 9015, 8953, 8891, 8829, 8766, 8703, 8640, + 8577, 8513, 8450, 8386, 8322, 8258, 8193, 8129, + 8064, 7999, 7933, 7868, 7802, 7737, 7671, 7604, + 7538, 7471, 7405, 7338, 7271, 7203, 7136, 7068, + 7001, 6933, 6865, 6796, 6728, 6659, 6591, 6522, + 6453, 6383, 6314, 6244, 6175, 6105, 6035, 5965, + 5895, 5824, 5754, 5683, 5612, 5541, 5470, 5399, + 5327, 5256, 5184, 5113, 5041, 4969, 4897, 4824, + 4752, 4680, 4607, 4534, 4462, 4389, 4316, 4243, + 4169, 4096, 4023, 3949, 3876, 3802, 3728, 3654, + 3580, 3506, 3432, 3358, 3284, 3209, 3135, 3060, + 2986, 2911, 2836, 2761, 2687, 2612, 2537, 2462, + 2386, 2311, 2236, 2161, 2085, 2010, 1934, 1859, + 1783, 1708, 1632, 1557, 1481, 1405, 1329, 1254, + 1178, 1102, 1026, 950, 874, 798, 722, 646, + 570, 494, 418, 342, 266, 190, 114, 38 +}; + +const Word16 edct_table_480_fx[480] = /*Q16 */ +{ + 14001, 14001, 14001, 14000, 14000, 13999, 13998, 13997, + 13996, 13995, 13993, 13991, 13990, 13988, 13986, 13983, + 13981, 13978, 13976, 13973, 13970, 13967, 13963, 13960, + 13956, 13953, 13949, 13945, 13940, 13936, 13932, 13927, + 13922, 13917, 13912, 13907, 13902, 13896, 13890, 13885, + 13879, 13872, 13866, 13860, 13853, 13846, 13840, 13833, + 13825, 13818, 13811, 13803, 13795, 13787, 13779, 13771, + 13763, 13754, 13746, 13737, 13728, 13719, 13709, 13700, + 13691, 13681, 13671, 13661, 13651, 13641, 13630, 13620, + 13609, 13598, 13587, 13576, 13565, 13553, 13542, 13530, + 13518, 13506, 13494, 13482, 13469, 13457, 13444, 13431, + 13418, 13405, 13392, 13378, 13365, 13351, 13337, 13323, + 13309, 13295, 13280, 13266, 13251, 13236, 13221, 13206, + 13191, 13175, 13160, 13144, 13128, 13112, 13096, 13080, + 13063, 13047, 13030, 13013, 12996, 12979, 12962, 12944, + 12927, 12909, 12891, 12873, 12855, 12837, 12819, 12800, + 12782, 12763, 12744, 12725, 12706, 12686, 12667, 12647, + 12628, 12608, 12588, 12568, 12547, 12527, 12506, 12486, + 12465, 12444, 12423, 12402, 12380, 12359, 12337, 12316, + 12294, 12272, 12250, 12227, 12205, 12182, 12160, 12137, + 12114, 12091, 12068, 12045, 12021, 11998, 11974, 11950, + 11926, 11902, 11878, 11854, 11829, 11804, 11780, 11755, + 11730, 11705, 11680, 11654, 11629, 11603, 11578, 11552, + 11526, 11500, 11474, 11447, 11421, 11394, 11368, 11341, + 11314, 11287, 11260, 11232, 11205, 11177, 11150, 11122, + 11094, 11066, 11038, 11010, 10981, 10953, 10924, 10895, + 10867, 10838, 10809, 10779, 10750, 10721, 10691, 10662, + 10632, 10602, 10572, 10542, 10512, 10481, 10451, 10420, + 10390, 10359, 10328, 10297, 10266, 10235, 10203, 10172, + 10140, 10109, 10077, 10045, 10013, 9981, 9949, 9917, + 9884, 9852, 9819, 9786, 9754, 9721, 9688, 9654, + 9621, 9588, 9554, 9521, 9487, 9454, 9420, 9386, + 9352, 9318, 9283, 9249, 9214, 9180, 9145, 9111, + 9076, 9041, 9006, 8971, 8935, 8900, 8865, 8829, + 8794, 8758, 8722, 8686, 8650, 8614, 8578, 8542, + 8505, 8469, 8432, 8396, 8359, 8322, 8285, 8248, + 8211, 8174, 8137, 8099, 8062, 8025, 7987, 7949, + 7912, 7874, 7836, 7798, 7760, 7721, 7683, 7645, + 7606, 7568, 7529, 7491, 7452, 7413, 7374, 7335, + 7296, 7257, 7218, 7178, 7139, 7100, 7060, 7020, + 6981, 6941, 6901, 6861, 6821, 6781, 6741, 6701, + 6661, 6620, 6580, 6539, 6499, 6458, 6418, 6377, + 6336, 6295, 6254, 6213, 6172, 6131, 6090, 6048, + 6007, 5966, 5924, 5883, 5841, 5799, 5758, 5716, + 5674, 5632, 5590, 5548, 5506, 5464, 5422, 5379, + 5337, 5295, 5252, 5210, 5167, 5124, 5082, 5039, + 4996, 4953, 4911, 4868, 4825, 4782, 4738, 4695, + 4652, 4609, 4566, 4522, 4479, 4435, 4392, 4348, + 4305, 4261, 4218, 4174, 4130, 4086, 4042, 3999, + 3955, 3911, 3867, 3823, 3778, 3734, 3690, 3646, + 3602, 3557, 3513, 3469, 3424, 3380, 3335, 3291, + 3246, 3202, 3157, 3112, 3068, 3023, 2978, 2933, + 2889, 2844, 2799, 2754, 2709, 2664, 2619, 2574, + 2529, 2484, 2439, 2394, 2349, 2303, 2258, 2213, + 2168, 2122, 2077, 2032, 1986, 1941, 1896, 1850, + 1805, 1759, 1714, 1668, 1623, 1577, 1532, 1486, + 1441, 1395, 1350, 1304, 1258, 1213, 1167, 1121, + 1076, 1030, 984, 939, 893, 847, 801, 756, + 710, 664, 618, 573, 527, 481, 435, 389, + 344, 298, 252, 206, 160, 115, 69, 23 +}; + +const Word16 edct_table_600_fx[] = +{ + 26483, 26483, 26483, 26482, 26481, 26481, 26479, 26478, + 26477, 26475, 26473, 26471, 26469, 26467, 26464, 26461, + 26459, 26455, 26452, 26449, 26445, 26441, 26437, 26433, + 26429, 26424, 26420, 26415, 26410, 26404, 26399, 26393, + 26387, 26381, 26375, 26369, 26362, 26356, 26349, 26342, + 26335, 26327, 26320, 26312, 26304, 26296, 26287, 26279, + 26270, 26261, 26252, 26243, 26234, 26224, 26214, 26204, + 26194, 26184, 26173, 26163, 26152, 26141, 26130, 26118, + 26107, 26095, 26083, 26071, 26059, 26046, 26033, 26021, + 26008, 25994, 25981, 25968, 25954, 25940, 25926, 25912, + 25897, 25883, 25868, 25853, 25838, 25823, 25807, 25791, + 25776, 25760, 25743, 25727, 25711, 25694, 25677, 25660, + 25643, 25625, 25608, 25590, 25572, 25554, 25535, 25517, + 25498, 25480, 25461, 25441, 25422, 25403, 25383, 25363, + 25343, 25323, 25302, 25282, 25261, 25240, 25219, 25198, + 25176, 25155, 25133, 25111, 25089, 25067, 25044, 25022, + 24999, 24976, 24953, 24929, 24906, 24882, 24858, 24834, + 24810, 24786, 24761, 24737, 24712, 24687, 24662, 24636, + 24611, 24585, 24559, 24533, 24507, 24481, 24454, 24427, + 24401, 24373, 24346, 24319, 24291, 24264, 24236, 24208, + 24180, 24151, 24123, 24094, 24065, 24036, 24007, 23978, + 23948, 23918, 23888, 23858, 23828, 23798, 23767, 23737, + 23706, 23675, 23644, 23612, 23581, 23549, 23518, 23486, + 23453, 23421, 23389, 23356, 23323, 23290, 23257, 23224, + 23191, 23157, 23123, 23090, 23056, 23021, 22987, 22953, + 22918, 22883, 22848, 22813, 22778, 22742, 22707, 22671, + 22635, 22599, 22563, 22526, 22490, 22453, 22416, 22379, + 22342, 22305, 22267, 22230, 22192, 22154, 22116, 22078, + 22039, 22001, 21962, 21923, 21884, 21845, 21806, 21766, + 21727, 21687, 21647, 21607, 21567, 21527, 21486, 21446, + 21405, 21364, 21323, 21282, 21241, 21199, 21157, 21116, + 21074, 21032, 20989, 20947, 20905, 20862, 20819, 20776, + 20733, 20690, 20647, 20603, 20560, 20516, 20472, 20428, + 20384, 20339, 20295, 20250, 20205, 20161, 20116, 20070, + 20025, 19980, 19934, 19888, 19842, 19796, 19750, 19704, + 19658, 19611, 19565, 19518, 19471, 19424, 19377, 19329, + 19282, 19234, 19186, 19139, 19091, 19042, 18994, 18946, + 18897, 18849, 18800, 18751, 18702, 18653, 18604, 18554, + 18505, 18455, 18405, 18355, 18305, 18255, 18205, 18154, + 18104, 18053, 18002, 17951, 17900, 17849, 17798, 17747, + 17695, 17643, 17592, 17540, 17488, 17436, 17383, 17331, + 17278, 17226, 17173, 17120, 17067, 17014, 16961, 16908, + 16854, 16801, 16747, 16693, 16640, 16586, 16531, 16477, + 16423, 16368, 16314, 16259, 16204, 16149, 16094, 16039, + 15984, 15929, 15873, 15818, 15762, 15706, 15650, 15595, + 15538, 15482, 15426, 15370, 15313, 15256, 15200, 15143, + 15086, 15029, 14972, 14914, 14857, 14800, 14742, 14684, + 14627, 14569, 14511, 14453, 14395, 14336, 14278, 14220, + 14161, 14103, 14044, 13985, 13926, 13867, 13808, 13749, + 13689, 13630, 13570, 13511, 13451, 13391, 13332, 13272, + 13212, 13151, 13091, 13031, 12971, 12910, 12849, 12789, + 12728, 12667, 12606, 12545, 12484, 12423, 12362, 12300, + 12239, 12177, 12116, 12054, 11992, 11930, 11868, 11806, + 11744, 11682, 11620, 11558, 11495, 11433, 11370, 11307, + 11245, 11182, 11119, 11056, 10993, 10930, 10867, 10803, + 10740, 10677, 10613, 10550, 10486, 10422, 10358, 10295, + 10231, 10167, 10103, 10039, 9974, 9910, 9846, 9781, + 9717, 9652, 9588, 9523, 9458, 9394, 9329, 9264, + 9199, 9134, 9069, 9003, 8938, 8873, 8808, 8742, + 8677, 8611, 8546, 8480, 8414, 8348, 8283, 8217, + 8151, 8085, 8019, 7953, 7886, 7820, 7754, 7688, + 7621, 7555, 7488, 7422, 7355, 7289, 7222, 7155, + 7088, 7022, 6955, 6888, 6821, 6754, 6687, 6620, + 6553, 6485, 6418, 6351, 6283, 6216, 6149, 6081, + 6014, 5946, 5879, 5811, 5743, 5676, 5608, 5540, + 5472, 5404, 5337, 5269, 5201, 5133, 5065, 4997, + 4928, 4860, 4792, 4724, 4656, 4587, 4519, 4451, + 4382, 4314, 4246, 4177, 4109, 4040, 3972, 3903, + 3834, 3766, 3697, 3629, 3560, 3491, 3422, 3354, + 3285, 3216, 3147, 3078, 3009, 2941, 2872, 2803, + 2734, 2665, 2596, 2527, 2458, 2389, 2320, 2251, + 2182, 2112, 2043, 1974, 1905, 1836, 1767, 1697, + 1628, 1559, 1490, 1421, 1351, 1282, 1213, 1144, + 1074, 1005, 936, 867, 797, 728, 659, 589, + 520, 451, 381, 312, 243, 173, 104, 35 +}; + +const Word16 edct_table_128_fx[128] = /*Q16 */ +{ + 19483, 19480, 19474, 19466, 19454, 19439, 19422, 19401, + 19378, 19351, 19322, 19290, 19255, 19217, 19176, 19132, + 19086, 19036, 18984, 18928, 18870, 18809, 18746, 18679, + 18610, 18537, 18462, 18385, 18304, 18221, 18135, 18046, + 17954, 17860, 17763, 17664, 17561, 17457, 17349, 17239, + 17126, 17011, 16893, 16773, 16650, 16524, 16396, 16266, + 16133, 15998, 15860, 15720, 15578, 15433, 15286, 15137, + 14985, 14831, 14675, 14516, 14356, 14193, 14028, 13861, + 13692, 13521, 13348, 13173, 12996, 12816, 12635, 12452, + 12268, 12081, 11892, 11702, 11510, 11316, 11121, 10924, + 10725, 10524, 10322, 10119, 9914, 9707, 9499, 9290, + 9079, 8867, 8653, 8438, 8222, 8005, 7786, 7566, + 7345, 7123, 6900, 6676, 6451, 6225, 5998, 5770, + 5541, 5312, 5081, 4850, 4618, 4385, 4152, 3918, + 3684, 3449, 3213, 2977, 2741, 2504, 2266, 2029, + 1791, 1552, 1314, 1075, 837, 598, 359, 120 +}; + +const Word16 edct_table_160_fx[160] = /*Q16 */ +{ + 18426, 18425, 18421, 18416, 18409, 18400, 18389, 18377, + 18362, 18346, 18329, 18309, 18288, 18265, 18240, 18214, + 18185, 18155, 18123, 18090, 18055, 18018, 17979, 17938, + 17896, 17852, 17806, 17759, 17710, 17659, 17607, 17552, + 17497, 17439, 17380, 17319, 17256, 17192, 17126, 17058, + 16989, 16918, 16846, 16772, 16696, 16619, 16540, 16459, + 16377, 16293, 16208, 16121, 16033, 15943, 15851, 15758, + 15664, 15568, 15470, 15371, 15271, 15169, 15065, 14960, + 14854, 14746, 14637, 14527, 14415, 14301, 14186, 14070, + 13953, 13834, 13714, 13592, 13469, 13345, 13220, 13093, + 12965, 12836, 12706, 12574, 12441, 12307, 12172, 12036, + 11898, 11759, 11620, 11479, 11337, 11193, 11049, 10904, + 10758, 10610, 10462, 10312, 10162, 10011, 9858, 9705, + 9551, 9395, 9239, 9082, 8925, 8766, 8606, 8446, + 8285, 8123, 7960, 7797, 7632, 7467, 7301, 7135, + 6968, 6800, 6632, 6463, 6293, 6122, 5952, 5780, + 5608, 5435, 5262, 5089, 4915, 4740, 4565, 4389, + 4214, 4037, 3861, 3684, 3506, 3328, 3150, 2972, + 2793, 2614, 2435, 2256, 2076, 1896, 1716, 1536, + 1356, 1175, 994, 814, 633, 452, 271, 90 +}; + +const Word16 edct_table_40_fx[40] = /*Q16 */ +{ + 26049, 26009, 25928, 25808, 25648, 25448, 25210, 24932, + 24616, 24262, 23870, 23442, 22977, 22477, 21943, 21375, + 20773, 20140, 19475, 18781, 18058, 17306, 16528, 15725, + 14897, 14047, 13174, 12282, 11370, 10441, 9496, 8536, + 7563, 6578, 5584, 4580, 3570, 2554, 1534, 512 +}; + +const Word16 edct_table_20_fx[20] = /*Q16 */ +{ + 30939, 30749, 30368, 29801, 29049, 28119, 27015, 25745, + 24316, 22737, 21018, 19169, 17202, 15129, 12963, 10717, + 8405, 6041, 3639, 1216 +}; + + +const Word16 edct_table_64_fx[] = +{ + 23167, 23153, 23125, 23083, 23027, 22958, 22874, 22777, + 22666, 22542, 22403, 22252, 22087, 21908, 21717, 21512, + 21295, 21064, 20821, 20565, 20297, 20017, 19725, 19420, + 19105, 18777, 18438, 18089, 17728, 17356, 16975, 16582, + 16180, 15769, 15347, 14917, 14477, 14029, 13572, 13107, + 12634, 12154, 11666, 11171, 10670, 10162, 9648, 9128, + 8603, 8072, 7537, 6997, 6453, 5905, 5353, 4798, + 4241, 3681, 3118, 2554, 1988, 1421, 853, 284 +}; + + +const Word16 edct_table_200_fx[] = +{ + 17427, 17426, 17423, 17420, 17416, 17411, 17404, 17397, + 17388, 17378, 17368, 17356, 17343, 17329, 17314, 17298, + 17281, 17262, 17243, 17223, 17201, 17179, 17155, 17131, + 17105, 17079, 17051, 17022, 16992, 16961, 16929, 16896, + 16862, 16827, 16791, 16754, 16716, 16676, 16636, 16595, + 16553, 16509, 16465, 16420, 16373, 16326, 16278, 16228, + 16178, 16126, 16074, 16021, 15966, 15911, 15855, 15797, + 15739, 15680, 15620, 15558, 15496, 15433, 15369, 15304, + 15238, 15171, 15103, 15035, 14965, 14894, 14823, 14751, + 14677, 14603, 14528, 14452, 14375, 14297, 14218, 14139, + 14058, 13977, 13895, 13812, 13728, 13643, 13558, 13471, + 13384, 13296, 13207, 13117, 13027, 12935, 12843, 12750, + 12657, 12562, 12467, 12371, 12274, 12177, 12078, 11979, + 11880, 11779, 11678, 11576, 11473, 11370, 11266, 11161, + 11055, 10949, 10843, 10735, 10627, 10518, 10409, 10299, + 10188, 10076, 9964, 9852, 9739, 9625, 9510, 9395, + 9280, 9164, 9047, 8930, 8812, 8694, 8575, 8455, + 8335, 8215, 8094, 7973, 7851, 7728, 7605, 7482, + 7358, 7234, 7109, 6984, 6858, 6732, 6606, 6479, + 6352, 6224, 6096, 5967, 5839, 5710, 5580, 5450, + 5320, 5190, 5059, 4928, 4796, 4664, 4532, 4400, + 4268, 4135, 4002, 3868, 3735, 3601, 3467, 3333, + 3198, 3064, 2929, 2794, 2659, 2523, 2388, 2252, + 2116, 1980, 1844, 1708, 1572, 1436, 1299, 1163, + 1026, 889, 753, 616, 479, 342, 205, 68 +}; + +const Word16 edct_table_240_fx[] = +{ + 16650, 16650, 16648, 16646, 16643, 16640, 16635, 16630, + 16625, 16618, 16611, 16603, 16595, 16585, 16575, 16565, + 16553, 16541, 16528, 16515, 16501, 16486, 16470, 16454, + 16437, 16419, 16401, 16381, 16362, 16341, 16320, 16298, + 16275, 16252, 16228, 16203, 16178, 16151, 16125, 16097, + 16069, 16040, 16010, 15980, 15949, 15918, 15885, 15852, + 15819, 15784, 15749, 15713, 15677, 15640, 15602, 15564, + 15525, 15485, 15445, 15404, 15362, 15320, 15277, 15233, + 15189, 15144, 15098, 15052, 15005, 14957, 14909, 14860, + 14811, 14761, 14710, 14659, 14607, 14554, 14501, 14447, + 14392, 14337, 14282, 14225, 14168, 14111, 14053, 13994, + 13934, 13874, 13814, 13753, 13691, 13629, 13566, 13502, + 13438, 13374, 13309, 13243, 13176, 13109, 13042, 12974, + 12905, 12836, 12767, 12696, 12626, 12554, 12482, 12410, + 12337, 12264, 12190, 12115, 12040, 11965, 11889, 11812, + 11735, 11657, 11579, 11501, 11422, 11342, 11262, 11182, + 11101, 11019, 10937, 10855, 10772, 10689, 10605, 10521, + 10436, 10351, 10265, 10179, 10093, 10006, 9919, 9831, + 9743, 9654, 9565, 9476, 9386, 9296, 9205, 9114, + 9023, 8931, 8839, 8746, 8653, 8560, 8466, 8372, + 8278, 8183, 8088, 7993, 7897, 7801, 7704, 7608, + 7511, 7413, 7315, 7217, 7119, 7020, 6921, 6822, + 6723, 6623, 6523, 6422, 6321, 6221, 6119, 6018, + 5916, 5814, 5712, 5609, 5507, 5404, 5300, 5197, + 5093, 4990, 4885, 4781, 4677, 4572, 4467, 4362, + 4257, 4151, 4046, 3940, 3834, 3728, 3622, 3515, + 3408, 3302, 3195, 3088, 2981, 2873, 2766, 2658, + 2551, 2443, 2335, 2227, 2119, 2011, 1903, 1795, + 1686, 1578, 1469, 1361, 1252, 1143, 1035, 926, + 817, 708, 599, 490, 381, 272, 163, 54 +}; + +const Word16 edct_table_256_fx[] = +{ + 16384, 16383, 16382, 16380, 16378, 16375, 16371, 16367, + 16362, 16356, 16350, 16343, 16336, 16328, 16319, 16310, + 16300, 16290, 16278, 16267, 16254, 16242, 16228, 16214, + 16199, 16184, 16168, 16151, 16134, 16116, 16098, 16079, + 16059, 16039, 16018, 15997, 15975, 15952, 15929, 15905, + 15881, 15856, 15830, 15804, 15777, 15750, 15722, 15693, + 15664, 15634, 15604, 15573, 15541, 15509, 15476, 15443, + 15409, 15375, 15340, 15304, 15268, 15231, 15194, 15156, + 15117, 15078, 15039, 14999, 14958, 14917, 14875, 14832, + 14789, 14746, 14702, 14657, 14612, 14566, 14520, 14473, + 14426, 14378, 14329, 14280, 14231, 14181, 14130, 14079, + 14027, 13975, 13922, 13869, 13815, 13761, 13706, 13651, + 13595, 13538, 13481, 13424, 13366, 13308, 13249, 13190, + 13130, 13069, 13008, 12947, 12885, 12823, 12760, 12697, + 12633, 12569, 12504, 12439, 12373, 12307, 12240, 12173, + 12106, 12038, 11969, 11901, 11831, 11762, 11691, 11621, + 11550, 11478, 11406, 11334, 11261, 11188, 11114, 11040, + 10965, 10891, 10815, 10740, 10663, 10587, 10510, 10433, + 10355, 10277, 10198, 10119, 10040, 9961, 9881, 9800, + 9719, 9638, 9557, 9475, 9393, 9310, 9227, 9144, + 9061, 8977, 8892, 8808, 8723, 8638, 8552, 8466, + 8380, 8293, 8206, 8119, 8032, 7944, 7856, 7768, + 7679, 7590, 7501, 7411, 7321, 7231, 7141, 7050, + 6960, 6868, 6777, 6685, 6593, 6501, 6409, 6316, + 6223, 6130, 6037, 5943, 5850, 5756, 5661, 5567, + 5472, 5377, 5282, 5187, 5092, 4996, 4900, 4804, + 4708, 4611, 4515, 4418, 4321, 4224, 4127, 4030, + 3932, 3835, 3737, 3639, 3541, 3442, 3344, 3246, + 3147, 3048, 2949, 2851, 2751, 2652, 2553, 2454, + 2354, 2255, 2155, 2055, 1956, 1856, 1756, 1656, + 1556, 1456, 1356, 1255, 1155, 1055, 954, 854, + 754, 653, 553, 452, 352, 251, 151, 50 +}; + +const Word16 edct_table_400_fx[] = +{ + 29308, 29308, 29307, 29306, 29304, 29302, 29299, 29296, + 29292, 29288, 29284, 29279, 29273, 29267, 29261, 29254, + 29247, 29239, 29231, 29223, 29214, 29204, 29194, 29184, + 29173, 29162, 29150, 29138, 29125, 29112, 29099, 29085, + 29070, 29055, 29040, 29024, 29008, 28991, 28974, 28957, + 28939, 28920, 28901, 28882, 28862, 28842, 28821, 28800, + 28779, 28757, 28734, 28711, 28688, 28664, 28640, 28615, + 28590, 28565, 28539, 28512, 28485, 28458, 28430, 28402, + 28373, 28344, 28315, 28285, 28255, 28224, 28192, 28161, + 28129, 28096, 28063, 28030, 27996, 27962, 27927, 27892, + 27856, 27820, 27784, 27747, 27710, 27672, 27634, 27595, + 27556, 27517, 27477, 27437, 27396, 27355, 27313, 27272, + 27229, 27186, 27143, 27100, 27055, 27011, 26966, 26921, + 26875, 26829, 26782, 26736, 26688, 26640, 26592, 26544, + 26495, 26445, 26395, 26345, 26294, 26243, 26192, 26140, + 26088, 26035, 25982, 25929, 25875, 25821, 25766, 25711, + 25655, 25600, 25543, 25487, 25430, 25372, 25315, 25256, + 25198, 25139, 25079, 25020, 24960, 24899, 24838, 24777, + 24715, 24653, 24591, 24528, 24465, 24401, 24337, 24273, + 24208, 24143, 24078, 24012, 23946, 23879, 23812, 23745, + 23677, 23609, 23541, 23472, 23403, 23334, 23264, 23194, + 23123, 23052, 22981, 22909, 22837, 22765, 22692, 22619, + 22546, 22472, 22398, 22324, 22249, 22174, 22098, 22023, + 21947, 21870, 21793, 21716, 21639, 21561, 21483, 21404, + 21326, 21246, 21167, 21087, 21007, 20927, 20846, 20765, + 20684, 20602, 20520, 20437, 20355, 20272, 20189, 20105, + 20021, 19937, 19852, 19768, 19682, 19597, 19511, 19425, + 19339, 19252, 19165, 19078, 18991, 18903, 18815, 18726, + 18638, 18549, 18459, 18370, 18280, 18190, 18100, 18009, + 17918, 17827, 17735, 17643, 17551, 17459, 17366, 17274, + 17181, 17087, 16994, 16900, 16805, 16711, 16616, 16521, + 16426, 16331, 16235, 16139, 16043, 15946, 15850, 15753, + 15656, 15558, 15461, 15363, 15265, 15166, 15068, 14969, + 14870, 14770, 14671, 14571, 14471, 14371, 14271, 14170, + 14069, 13968, 13867, 13765, 13663, 13562, 13459, 13357, + 13254, 13152, 13049, 12946, 12842, 12739, 12635, 12531, + 12427, 12323, 12218, 12113, 12008, 11903, 11798, 11693, + 11587, 11481, 11375, 11269, 11163, 11056, 10950, 10843, + 10736, 10628, 10521, 10414, 10306, 10198, 10090, 9982, + 9874, 9765, 9657, 9548, 9439, 9330, 9221, 9112, + 9002, 8892, 8783, 8673, 8563, 8453, 8342, 8232, + 8122, 8011, 7900, 7789, 7678, 7567, 7456, 7344, + 7233, 7121, 7010, 6898, 6786, 6674, 6562, 6450, + 6337, 6225, 6112, 6000, 5887, 5774, 5661, 5548, + 5435, 5322, 5209, 5096, 4982, 4869, 4755, 4642, + 4528, 4414, 4300, 4187, 4073, 3959, 3845, 3730, + 3616, 3502, 3388, 3273, 3159, 3044, 2930, 2815, + 2701, 2586, 2472, 2357, 2242, 2127, 2013, 1898, + 1783, 1668, 1553, 1438, 1323, 1208, 1093, 978, + 863, 748, 633, 518, 403, 288, 173, 58 +}; + +const Word16 Ip_fft16_fx[6] = {8,1,0,16,8,24}; + +const Word16 Ip_fft8_fx[6] = {4,1,0,8,4,12}; +const Word16 w_fft8_fx[4] = {16384, 0, 11585, 11585}; /*Q14 */ + +const Word16 Ip_fft32_fx[6] = {16,1,0,32,16,48}; +const Word16 Ip_fft64_fx[6] = {32,1,0,64,32,96}; +const Word16 Ip_fft4_fx[6] = {2,1,0,4,2,6}; +const Word16 w_fft4_fx[2] = {16384, 0}; /*Q14 */ + +const Word16 Ip_fft128_fx[10] = {64,1,0,128,64,192,32,160,96,224}; + +/* For the general fix point fft implementation */ +const Word16 sincos_t_fx[161] = +{ + /*Q15 */ + 0, + 804, 1607, 2410, 3211, 4011, + 4808, 5602, 6392, 7179, 7961, + 8739, 9512, 10278, 11039, 11793, + 12539, 13278, 14010, 14732, 15446, + 16151, 16846, 17530, 18204, 18868, + 19519, 20159, 20787, 21403, 22005, + 22594, 23170, 23732, 24279, 24812, + 25330, 25832, 26319, 26790, 27245, + 27684, 28106, 28511, 28898, 29269, + 29621, 29956, 30273, 30572, 30852, + 31114, 31357, 31581, 31785, 31971, + 32138, 32285, 32413, 32521, 32610, + 32679, 32728, 32758, 32767, 32758, + 32728, 32679, 32610, 32521, 32413, + 32285, 32138, 31971, 31785, 31581, + 31357, 31114, 30852, 30572, 30273, + 29956, 29621, 29269, 28898, 28511, + 28106, 27684, 27245, 26790, 26319, + 25832, 25330, 24812, 24279, 23732, + 23170, 22594, 22005, 21403, 20787, + 20159, 19519, 18868, 18204, 17530, + 16846, 16151, 15446, 14732, 14010, + 13278, 12539, 11793, 11039, 10278, + 9512, 8739, 7961, 7179, 6392, + 5602, 4808, 4011, 3211, 2410, + 1607, 804, 0, -804, -1607, + -2410, -3211, -4011, -4808, -5602, + -6392, -7179, -7961, -8739, -9512, + -10278, -11039, -11793, -12539, -13278, + -14010, -14732, -15446, -16151, -16846, + -17530, -18204, -18868, -19519, -20159, + -20787, -21403, -22005, -22594, -23170, +}; + +/*------------------------------------------------------------------------------* + * GSC tables + *------------------------------------------------------------------------------*/ + +const Word16 gsc_sfm_start[MBANDS_GN] = {0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240}; + +const Word16 gsc_sfm_end[MBANDS_GN] = {16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256}; + +const Word16 gsc_sfm_size[MBANDS_GN] = {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; + + +/*GSC related */ +const Word16 GSC_freq_bits[] = +{ + 21, 66, -6, 25, 15, 11, 10, 5, 0, 0, 5, 4, 0, 0, 4, 0, 0, /* ACELP_7k20*/ + 21, 74, -4, 26, 16, 12, 11, 9, 0, 0, 4, 4, 1, 1, 3, 0, 0, /* ACELP_8k00*/ + 26, 96, -4, 28, 18, 13, 12,10,10, 5, 4, 4, 1, 0, 1, 3, 4, /* ACELP_11k60*/ + 26, 96, -4, 28, 18, 13, 12,10,10, 5, 4, 4, 1, 0, 1, 3, 4, /* ACELP_12k15*/ + 26, 96, -4, 28, 18, 13, 12,10,10, 5, 4, 4, 1, 0, 1, 3, 4, /* ACELP_12k85*/ + 31, 96, -4, 28, 18, 13, 12,10,10, 5, 4, 4, 1, 0, 1, 3, 4, /* ACELP_13k20*/ +}; + +/***IN Q2 ****/ +const Word16 mfreq_loc_Q2fx[] = { 700, 1500, 3100, 4700, 6300, 7900, 9500, 11100, 12700, 14300, 15900, 17500, 19100, 20700, 22300, 25500, 28700, 31900 }; +const Word16 mfreq_loc_div_25[] = {7, 15, 31, 47, 63, 79, 95, 111, 127, 143, 159, 175, 191, 207, 223, 255, 287, 319}; + +const Word16 mfreq_bindiv_loc_fx[] = {8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 32, 32, 32 }; +/*const Word16 mean_gp_fx[] = {4795}; */ +const Word16 mean_gp_fx[] = {9590}; /*Q14*/ + +const Word16 dic_gp_fx[] = /*Q14*/ +{ + -9580, -7692, -6385, -4474, -3254, -2038, -806, -82, + 1034, 2259, 3457, 4684, 5290, 6544, 8548, 10052, + -8964, -8338, -7021, -5754, -5118, -3850, -2654, -1429, + 408, 1660, 2852, 4071, 5915, 7170, 7825, 9249 +}; + +const Word16 Gain_meanNB_fx[]= +{ + 9852, +};/* Q12 */ + +const Word16 Gain_mean_dicNB_fx[1*64] = /*Q12 */ +{ + -1309, -931, -568, -396, -54, 807, 1174, 1533, + 1901, 2092, 2286, 2493, 2698, 3130, 2909, 286, + -748, 990, 631, -1119, -1697, -2114, -2788, -5399, + -9841, -1902, -3270, -7975, -7438, -6926, -7192, -2325, + -1504, -2549, -3022, -3532, -3818, -4136, -4751, -5071, + -5756, -6093, -8998, -6389, -8765, -9438, 3369, 3917, + 3619, 4684, -8264, 4255, -4433, -6662, -9230, -7678, + 5859, 118, 457, -227, 1717, 1353, -8499, -9649 +}; + +const Word16 Mean_dic_NB_fx[1*10] = /*Q12 */ +{ + -444, -100, -120, -37, 25, + 70, 148, 63, 170, 229 +}; + +const Word16 Gain_dic1_NB_fx[3*64] = /*Q12 */ +{ + -606, -92, 5, + -1965, 294, 666, + -440, 119, 661, + -106, 267, 108, + -1213, 345, -136, + -1251, 618, 566, + -1905, -750, 648, + -1043, -360, -498, + -18, -322, 96, + 334, 116, -247, + -1929, 660, 23, + -1845, 1178, 485, + -180, 836, 167, + -1892, -922, -321, + 416, -437, -344, + 595, -548, 158, + -265, -807, -338, + -1065, -1015, -20, + -626, 595, -333, + -569, 1090, 651, + 27, 587, -331, + -184, -85, -503, + -1902, -1807, 326, + -1861, -159, -989, + -666, 143, -1163, + -1718, 1031, -744, + 847, 301, -59, + 720, -1001, -216, + 1380, -866, -969, + 803, -4, -608, + 233, 408, -998, + 1459, 87, 263, + 345, -615, -1026, + 877, -148, -7, + 68, -1075, 270, + 802, 329, 475, + -1923, -126, -38, + 1275, -419, -349, + 401, 926, 575, + 846, -233, 547, + 693, -1880, 356, + -362, -1683, -219, + 231, -339, 598, + 1227, -616, 267, + 1116, 91, -1316, + -551, -650, 530, + 444, 32, 181, + -384, 1207, -775, + -993, 1163, 41, + 784, -1018, 538, + 635, 636, -424, + 1373, -1367, 149, + 1442, 401, -444, + 1094, 888, 123, + 874, 1113, -1082, + -646, -1112, -1103, + 539, -1632, -683, + 402, 571, 99, + -1778, -1809, -849, + -732, -1691, 700, + -678, 526, 274, + 320, 1227, -118, + -1222, -180, 454, + 173, 349, 530 +}; + +const Word16 Gain_dic2_NB_fx[3*32] = /*Q12 */ +{ + 28, 0, -66, + -557, 4, 206, + 281, -642, 36, + -417, 81, -494, + -380, 684, 450, + 521, -1544, 258, + -1119, 613, -1151, + 514, 24, 797, + 292, -84, -526, + 296, 418, -231, + -419, -68, 976, + 2, -308, 398, + -456, -1007, 263, + -1221, -371, 446, + -221, -390, -181, + -1210, 588, 751, + -1093, 528, -174, + 590, 372, -1271, + -79, -251, -1241, + -1016, -487, -512, + 542, 581, 338, + -265, 456, -105, + 490, -71, 89, + 42, 235, 379, + 31, 1194, -202, + 173, -839, 850, + -46, 500, -802, + 152, 933, 1073, + 980, 345, -263, + 807, -580, -521, + -23, -992, -585, + 876, -576, 411 +}; + +const Word16 Gain_dic3_NB_fx[4*16] = /*Q12 */ +{ + -16, 65, -227, 11, + -214, 553, 366, 185, + 137, -338, -300, -625, + -122, 82, 538, -797, + 160, 285, -1103, 35, + -594, 312, -379, -423, + 169, -642, -395, 363, + 351, -1166, 630, -261, + -1190, 217, 416, 187, + -577, 244, -636, 858, + 580, 482, -220, 635, + 475, -188, 372, 27, + -65, -369, 504, 910, + -423, -442, 124, -40, + 480, 575, -41, -651, + 682, 680, 910, 489 +}; + +const Word16 Gain_dic2_NBHR_fx[3*64] = /*Q12 */ +{ + 29, 0, -94, + -605, -202, -174, + 324, -380, -163, + -126, -301, -306, + -288, 124, 112, + -86, 524, -115, + 234, 18, -464, + -55, -281, 179, + 161, 446, 632, + 366, -82, 97, + 228, -1149, 270, + 293, 286, -143, + -123, -35, -896, + -540, -675, 175, + 331, -483, -687, + -779, 204, -668, + -492, 768, -510, + -1215, -620, -483, + 681, -76, -296, + -671, 396, -45, + -759, 298, 564, + -284, 589, 321, + -1366, -592, 496, + -448, -585, -712, + 12, -756, -90, + 513, 167, -927, + -1172, 1060, -1198, + -477, 748, 1006, + 42, 103, 1277, + -940, 1049, 138, + -924, -14, -1469, + 684, 679, -1580, + 417, -374, -1572, + 607, 270, 256, + 567, 778, 843, + 1414, -223, -542, + 97, 200, 251, + 222, 1074, -547, + -714, -285, 1046, + 386, -684, 984, + 338, 674, 116, + -274, 171, -368, + 581, -1871, 342, + 94, 442, -597, + -293, -1205, 851, + -127, 501, -1247, + 175, 1700, 1357, + -24, 1224, 285, + 707, -952, -293, + 668, 492, -407, + 1164, 751, 201, + 381, -595, 288, + -1570, 481, -531, + -597, -160, 326, + -578, -1311, -40, + -118, -523, 576, + -1513, 527, 757, + -184, 40, 609, + -1215, 98, 68, + -65, -1324, -836, + 821, -299, 204, + 796, 21, 840, + 310, -133, 542, + 1042, -974, 537 +}; + +const Word16 Gain_dic3_NBHR_fx[4*128] = /*Q12 */ +{ + 293, 7, -202, -95, + 535, 110, 542, -512, + -578, 65, -560, -345, + 206, 332, 10, -533, + -76, 356, -14, 83, + 149, -372, -195, -490, + -478, -241, -55, 113, + -293, -470, -606, 62, + 797, -1448, 625, -1128, + 173, 464, -1686, -49, + -392, -295, -159, -464, + -715, 420, -146, -984, + -36, 28, -484, 119, + 472, 272, -729, -116, + 68, -87, -628, -429, + 429, -918, -158, -191, + -545, 230, -435, 261, + -128, 15, -791, 612, + 268, -387, -1258, 102, + 378, 238, 301, 3, + -494, 149, 131, -124, + 634, -308, 99, 24, + 572, 711, 754, -1137, + -1109, 400, 1093, 369, + -831, -423, 1583, 1089, + -83, 156, -105, 1078, + -930, 476, 152, 380, + 776, 1162, 788, -43, + 279, 50, 408, 597, + 476, 483, 73, 749, + 903, 686, 80, -411, + 195, -768, 280, 344, + -263, -999, -46, -284, + -66, 263, 315, -1239, + 435, 578, -234, -1169, + 199, -1669, 188, 114, + -57, 419, -509, -633, + 98, -119, 129, -816, + -157, -365, -249, 537, + 67, -624, 121, 1153, + 1444, 142, -584, 38, + 1086, -84, 162, 994, + 392, -384, -124, 533, + 252, 183, -1161, -885, + -431, -829, 102, 432, + -708, 987, -1021, -644, + -64, 120, -1684, 985, + 210, -494, -906, 1302, + 50, -186, 177, 185, + -256, 872, -1004, 387, + 564, -80, -679, 515, + -763, -40, -1174, 228, + -1029, 199, -59, -297, + 30, -47, 198, -264, + -396, -1435, 913, -1018, + -141, 962, 36, 458, + 36, -388, 776, -1000, + -74, 489, 1137, 140, + -970, -766, 666, -117, + 90, 599, 1665, 1405, + -313, -685, -764, -615, + 563, -462, -627, -768, + 792, 560, -1445, 556, + -581, 721, -559, 1137, + -699, -273, 274, -846, + 940, -690, 747, -253, + -177, -541, 1355, -217, + -586, 427, 1196, -868, + 147, 532, -550, 405, + 258, 677, -245, -166, + 772, 1062, -331, 482, + 388, 1870, -576, 1585, + 462, 865, 454, 1212, + 570, 528, -681, 1229, + -386, 607, 599, 865, + -154, -20, -211, -231, + 96, 736, 408, -259, + 763, -1533, 1094, 249, + 705, -1132, 1757, -1082, + 310, -481, 329, -395, + 194, -781, 59, -954, + -933, -957, -25, 1866, + -852, -224, -482, 822, + -1438, 490, 221, 1281, + 392, 677, 539, 347, + 884, -614, 1844, 678, + -773, 484, -928, 2477, + -274, -461, 378, -263, + -283, -312, 583, 342, + 453, -1541, 378, 1266, + 778, 1095, 1290, 824, + -958, -443, -208, -71, + 985, -1001, -123, 473, + 56, -1003, -513, 474, + -259, 1435, 975, 315, + -59, -169, 724, 961, + -210, 1030, 341, -977, + 1054, 2917, -7, -877, + -852, -228, 330, 625, + 9, -524, -97, -14, + 16, -50, 476, 2406, + 264, -238, 768, 56, + 187, 108, -169, 446, + 673, 238, 992, 671, + -218, 285, 485, 181, + 669, -526, 639, 571, + 650, 20, -188, -516, + 1031, 165, 526, 136, + -333, 307, 102, -569, + -157, 309, -934, -121, + -336, 141, 39, 536, + 662, 364, -133, 222, + -1284, 637, -636, 77, + 1241, 846, 467, 638, + 842, 328, 1330, -320, + 152, -1009, 550, -215, + -772, 13, 594, -122, + 336, -410, -547, -2, + 869, -106, 321, -1180, + 516, 1247, -828, -577, + -670, 873, 367, -132, + -415, 630, -287, -164, + -105, 138, 657, -441, + -160, -1085, 940, 704, + -128, -68, -369, -1052, + -1434, 594, 546, -665, + -1849, 75, 175, 174, + -1283, 729, -1590, 1032 +}; + + +const Word16 mean_m_fx[1*1] = /*Q12 */ +{ + 11762 +}; +const Word16 mean_gain_dic_fx[1*64]= +{ + -739, -519, -76, 147, 574, 779, 983, 1185, + 1384, 1580, 1784, 1989, 2204, 2643, 2864, 2422, + 362, -295, -1197, -1936, -2757, -11755, -8216, 3083, + 3311, -1434, -1682, -3341, -9284, -9057, -8616, -7783, + -7359, -6964, -6592, -6233, -5470, -5050, -4651, -3954, + -2470, -963, -2199, -3042, -3643, -4292, -5854, -10199, + 4103, 3548, 4390, 4717, 3817, -10525, -11521, -9570, + -9899, -9171, -10841, -11165, 5500, 5079, 6139, 6993 +}; /* Q12 */ + +const Word16 YGain_mean_LR_fx[1*12]= +{ + -385, -178, -143, -116, -46, -12, + 64, 50, 118, 68, 133, 151 +}; + +const Word16 YGain_dic1_LR_fx[3*32]= /*Q12 */ +{ + -1909, 159, -90, + -155, 416, -15, + -99, -84, 396, + -1832, -848, -320, + -779, 1024, 45, + -1860, -1761, 273, + 81, -341, -309, + -819, -3, -315, + 483, 215, -194, + 242, 937, -76, + -1830, -1753, -1102, + -1589, 868, -657, + -911, 389, 421, + -1834, 915, 390, + -144, 564, -869, + 878, -1544, 301, + 446, 332, 376, + -540, -822, -1001, + 548, -192, 232, + 920, -589, -175, + 869, 717, -564, + 797, -103, -1047, + -335, -1732, -186, + -1840, -345, 566, + 1205, 109, 43, + 985, -456, 570, + 650, -1223, -874, + 928, 752, 390, + -124, 833, 575, + -1811, -249, -1142, + -711, -767, 185, + 344, -876, 267, +}; + +const Word16 YGain_dic2_LR_fx[4*32] = /*Q12 */ +{ + -294, -73, -41, 11, + 276, 330, -1316, 173, + 26, -712, 86, 1, + -841, -539, 246, -479, + 43, -207, 709, 116, + 104, -197, 227, -548, + 261, -228, 165, 606, + 613, 403, -122, -420, + 14, 182, -544, -669, + -734, 392, -492, -131, + -1316, 274, 116, 331, + -1339, 535, -1261, 608, + -346, 277, -426, 729, + -1067, -836, -571, 388, + 643, 503, 484, 532, + -148, 447, 120, -392, + -600, 263, 519, -75, + 686, -346, 379, 23, + 130, 239, 376, -1366, + 68, 656, -361, 92, + 608, 286, -405, 487, + -1031, 507, 523, -971, + 51, -44, -521, 172, + -573, -500, 398, 632, + 240, 147, 104, 51, + -319, -680, -890, -398, + -195, 503, 306, 459, + 335, 368, 662, -389, + 378, -788, -537, 680, + 433, -1129, 472, -883, + 472, -312, -301, -207, + 378, -1346, 433, 408, +}; + +const Word16 YGain_dic3_LR_fx[5*32] = /*Q12 */ +{ + -332, -191, -122, -455, -210, + 364, -48, -664, 408, 225, + -576, -342, 367, 52, 270, + -392, -157, -77, 625, -224, + -183, -652, -406, 99, 266, + 24, 65, 74, 525, 613, + -805, 306, -383, -21, 247, + 16, 133, -416, -4, -567, + 294, -750, 443, -367, 228, + 536, 816, 767, 562, 594, + -54, 200, -1108, -582, 227, + 123, -43, 414, -376, -649, + 592, -652, -674, -386, -356, + 100, -58, -45, -108, 103, + -727, -194, -1170, 931, 1096, + 512, 758, -440, -769, -1051, + 362, 787, -276, -139, 149, + -218, 387, 457, -414, 265, + -202, 663, -1104, 882, -338, + -57, 405, 269, 257, -221, + 335, 864, 1164, -611, -618, + 1275, 494, -1783, 119, 1222, + 752, 76, 270, 73, -57, + 376, -1255, 145, 724, 603, + -989, 618, 659, 675, 560, + 128, -147, -138, -368, 963, + 140, -170, 866, 538, 127, + 122, -616, 166, 236, -396, + 374, 279, 407, 650, -1269, + -861, 613, -755, -1334, -972, + -922, 314, 416, -114, -648, + 265, 85, 61, -1110, 45 +}; + +const Word16 YG_mean16_fx[1*16] = /*Q12 */ +{ + -396, -192, -168, -136, -60, -17, 45, 39, + 120, 81, 90, 67, 147, 34, 163, 184 +}; + +const Word16 YG_dicMR_1_fx[4*64] = /*Q12 */ +{ + -1879, 826, 539, -210, + -120, 267, -137, -142, + -798, -473, 434, 243, + 297, -896, 369, 307, + -1883, -1333, 416, 510, + -1955, -660, -471, 224, + -905, -804, -517, 433, + -961, 20, -258, -224, + 209, 977, -213, -17, + 536, -244, 159, 97, + -265, 775, 412, -327, + 337, -391, -237, -472, + -1962, -1836, -692, 471, + 625, 173, -463, -15, + -965, 263, 62, 600, + -782, 889, -433, 211, + -1791, 852, -453, -776, + -182, -177, -1078, 80, + -364, 350, 280, 293, + -902, 1119, 295, -1194, + 16, 440, -342, 459, + -1825, -1584, -1382, -798, + 723, 57, -1235, -661, + 888, -1638, 277, 234, + 340, 345, 141, -610, + 1280, -23, 17, 144, + -639, -852, -520, -553, + 1032, 843, 149, 435, + 581, 783, 519, -196, + 457, 945, 498, -1289, + -1897, -41, 425, 514, + 787, 161, 506, 385, + -559, 1079, 319, 515, + 500, 340, 60, 106, + 251, -997, -1163, -960, + 261, -1288, -631, 335, + 1241, -620, -387, -662, + 167, 194, 476, 67, + 830, -261, 430, -1201, + -479, -123, 71, -1162, + 225, -1482, 132, -802, + 680, 763, -1010, 429, + 200, -125, 261, 590, + 771, -740, -183, 229, + -1860, -348, 278, -549, + -1768, 967, 281, 594, + -1727, -1697, 87, -764, + 1169, 631, -114, -471, + -1636, -101, -1324, -91, + 821, -745, 458, -264, + 1014, -576, 390, 470, + 1041, -517, -1018, 367, + 826, 17, 426, -326, + -467, -1641, 201, 325, + -1906, 428, -338, 222, + -1021, 630, 419, -75, + -86, -379, -203, 234, + 659, 527, -491, -1507, + -564, -1745, -979, -173, + -1764, -433, -743, -1090, + 242, 709, 269, 497, + 716, 74, -208, 618, + -297, 645, -864, -805, + -46, -326, 412, -296 +}; +const Word16 YG_dicMR_2_fx[4*32] = /*Q12 */ +{ + 93, 217, -122, 37, + -13, -83, 105, -491, + -398, -592, 399, -160, + 543, -81, -470, 408, + 394, -630, -94, -258, + -665, 133, -136, -125, + 397, -351, 630, -148, + -1166, 406, -865, 554, + -136, -302, -263, 81, + -674, -657, -571, -691, + -206, 381, -699, 122, + 272, -1506, 356, 15, + 451, -961, 638, -1133, + 316, -787, 165, 585, + 312, -144, 185, 274, + 39, -706, -997, 250, + -915, -871, -114, 458, + -834, 348, 364, -1188, + 450, 723, -256, 412, + 369, 468, -1371, 416, + 344, 164, 290, -1094, + 664, 122, 34, -218, + 555, 254, 559, 825, + 312, 492, 496, -27, + -399, 315, 690, -330, + -458, 710, 206, 415, + 290, 89, -662, -467, + -72, 593, -108, -460, + -217, 46, 319, 189, + -1366, 199, 365, 62, + -552, -166, 772, 861, + -159, 120, -215, 775 +}; +const Word16 YG_dicMR_3_fx[4*32] = /*Q12 */ +{ + -103, -143, -85, -19, + -404, 182, -795, 84, + 398, -594, -55, -256, + 283, 128, -472, 279, + -246, -628, 281, 297, + -853, 468, 358, -915, + 272, 149, 209, -443, + -168, -504, 452, -525, + 624, -427, 779, 117, + 1079, 404, -98, 80, + 136, 165, 142, -1394, + 513, -566, -150, 822, + 124, 646, 199, 272, + -165, -702, -615, 165, + 333, 810, -457, 1038, + -360, 105, -110, 537, + -224, 125, 562, -26, + 699, -1105, 809, -1323, + -1229, 841, -767, 571, + -310, 437, -114, -230, + -1045, 630, 564, 322, + 282, 1170, -723, -306, + -328, -247, -251, -598, + 354, 332, -1593, 499, + 332, -23, 219, 304, + 325, -1511, 378, 299, + -94, -54, 679, 956, + 507, 830, 861, -739, + -895, -135, 16, -34, + 677, 650, 961, 714, + 816, -665, -1741, -671, + 274, 93, -617, -433 +}; +const Word16 YG_dicMR_4_fx[4*16] = /*Q12 */ +{ + -163, -44, -108, 32, + 556, 153, 115, 120, + 617, 818, 802, 719, + -639, -665, 122, 664, + 353, -555, -352, -86, + -1162, 833, -1034, 326, + -511, -406, -478, -523, + 491, -1473, 404, -21, + 148, 288, -45, -544, + -61, 172, -791, -44, + 715, -449, 861, 504, + -108, 263, 610, 118, + 962, 826, -1013, -37, + -32, -495, 362, -214, + -37, 661, -75, 289, + -835, 243, 85, -105 +}; + + +/***********IN Q15*****************/ +const Word16 sm_table_fx[] = +{ + 32767, 32126, 31480, 30838, 30196, 29557, 28918, 28279, 27643, 27007, + 26375, 25746, 25120, 24494, 23875, 23255, 22643, 22033, 21427, 20824, + 20228, 19638, 19048, 18468, 17891, 17321, 16758, 16197, 15647, 15103, + 14562, 14031, 13507, 12989, 12481, 11980, 11488, 11000, 10525, 10056, + 9598, 9146, 8706, 8274, 7851, 7438, 7035, 6642, 6259, 5885, + 5521, 5171, 4830, 4499, 4178, 3870, 3572, 3287, 3011, 2746, + 2494, 2254, 2025, 1809, 1602, 1412, 1229, 1062, 904, 760, + 629, 511, 403, 308, 226, 157, 102, 56, 26, 7, +}; + +const Word32 GSC_freq_bits_fx[] = +{ + 5505024, 17563648, -1572864, 6553600, 3932160, 2883584, 2621440, 1310720, 0, 0, 1310720, 1048576, 0, 0, 1048576, 0, 0, /* ACELP_7k20*/ + 5505024, 19660800, -1048576, 6815744, 4194304, 3145728, 2883584, 2359296, 0, 0, 1048576, 1048576, 262144, 262144, 786432, 0, 0, /* ACELP_8k00*/ + 6815744, 25165824, -1048576, 7340032, 4718592, 3407872, 3145728, 2621440, 2621440, 1310720, 1048576, 1048576, 262144, 0, 262144, 786432, 1048576, /* ACELP_11k60*/ + 6815744, 25165824, -1048576, 7340032, 4718592, 3407872, 3145728, 2621440, 2621440, 1310720, 1048576, 1048576, 262144, 0, 262144, 786432, 1048576, /* ACELP_12k15*/ + 6815744, 25165824, -1048576, 7340032, 4718592, 3407872, 3145728, 2621440, 2621440, 1310720, 1048576, 1048576, 262144, 0, 262144, 786432, 1048576, /* ACELP_12k85*/ + 8126464, 25165824, -1048576, 7340032, 4718592, 3407872, 3145728, 2621440, 2621440, 1310720, 1048576, 1048576, 262144, 0, 262144, 786432, 1048576, /* ACELP_13k20*/ +}; + +const Word32 pow2_fx[] = +{ + 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576 +}; + + +/*----------------------------------------------------------------------------------* + * means of ISFs for WB active speech + *----------------------------------------------------------------------------------*/ +const Word16 Mean_isf_wb[M] = /* G722.2 active speech ISF's means */ +{ + 738, 1326, 2336, 3578, 4596, 5662, 6711, 7730, + 8750, 9753,10705, 11728, 12833, 13971,15043, 4037 +}; +const Word16 interpol_isp_amr_wb_fx[] = {14746, 26214, 31457, 32767}; +const Word16 interpol_frac_16k_fx[NB_SUBFR16k] = { 6554, 13107, 19661, 26214, 32767 }; +const Word16 interpol_frac_fx[NB_SUBFR] = {8192, 16384, 24576,32767}; + + +/*----------------------------------------------------------------------------------* + * ISF quantization (AMR-WB IO mode) + *----------------------------------------------------------------------------------*/ + +const Word16 mean_isf_amr_wb_fx[M] = +{ + 738, 1326, 2336, 3578, 4596, 5662, 6711, 7730, + 8750, 9753,10705, 11728, 12833, 13971,15043, 4037 +}; +const Word16 mean_isf_noise_amr_wb_fx[M]= +{ + 478, 1100, 2213, 3267, 4219, 5222, 6198, 7240, + 8229, 9153,10098, 11108, 12144, 13184,14165, 3803 +}; + +/* ISF codebook - common 1st stage, 1st split (only in AMR-WB IO mode) */ +/*------------------------------------------------------* + * Indirection for 1st stage 1st split of 46 bit cb. : + The transmitted_index = indirect_dico1[found_index]; + *------------------------------------------------------*/ +const Word16 Indirect_dico1[SIZE_BK1] = +{ + 2, 6, 18, 22, 34, 35, 38, 50, + 66, 67, 70, 82, 98, 99, 102, 130, + 131, 134, 146, 150, 162, 178, 194, 198, + 210, 226, 230, 242, 0, 1, 3, 4, + 5, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 19, 20, 21, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 36, 37, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 51, + 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 68, 69, + 71, 72, 73, 74, 75, 76, 77, 78, + 79, 80, 81, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 100, 101, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 132, + 133, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 147, 148, 149, 151, + 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 163, 164, 165, 166, 167, 168, + 169, 170, 171, 172, 173, 174, 175, 176, + 177, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 191, 192, 193, + 195, 196, 197, 199, 200, 201, 202, 203, + 204, 205, 206, 207, 208, 209, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 227, 228, 229, + 231, 232, 233, 234, 235, 236, 237, 238, + 239, 240, 241, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255 +}; + +const Word16 dico1_isf_fx[]= +{ + 740, 1263, 1292, 1006, 997, 1019, 1017, 976, 923, + 557, 946, 1049, 867, 846, 990, 1112, 1262, 1241, + 633, 898, 996, 756, 662, 683, 783, 909, 996, + 830, 736, 278, 820, 1254, 686, 712, 1039, 473, + 503, 885, 1508, 1307, 1282, 1172, 1119, 1209, 1061, + 416, 719, 989, 1227, 1001, 1052, 954, 741, 1044, + 585, 1132, 1233, 1091, 1247, 1433, 1512, 1448, 1314, + -31, 469, 803, 659, 619, 658, 843, 987, 1113, + 842, 1678, 1841, 1549, 1474, 1256, 1082, 905, 742, + 370, 1216, 1768, 1633, 1212, 636, 22, -330, 71, + 73, 738, 893, 968, 993, 1768, 2273, 1840, 1391, + 1513, 1714, 1238, 534, 276, 315, 461, 459, 508, + 421, 1293, 1640, 1623, 1742, 1617, 1499, 1284, 1006, + -95, 752, 1680, 1569, 1618, 1436, 1200, 980, 712, + -78, 831, 1194, 1110, 1378, 1481, 1492, 1365, 1217, + 670, 1208, 1168, 860, 742, 601, 528, 403, 309, + 397, 621, 966, 752, 579, 398, 400, 329, 252, + 510, 864, 1108, 807, 939, 902, 925, 717, 481, + 539, 835, 913, 719, 617, 544, 591, 565, 642, + 162, 889, 654, 108, -34, 244, 488, 561, 532, + -62, 1033, 1308, 1035, 1127, 1098, 1029, 961, 823, + -14, 945, 990, 801, 755, 815, 847, 913, 892, + 394, 1765, 1666, 1339, 1117, 806, 642, 479, 380, + 529, 1851, 2003, 1228, 622, -41, -416, 344, 819, + 635, 1058, 883, 492, 372, 312, 317, 274, 241, + 279, 966, 1642, 1478, 1463, 1123, 795, 525, 339, + 457, 955, 1177, 1214, 1427, 1457, 1345, 917, 539, + 148, 751, 1515, 1105, 867, 606, 474, 448, 399, + 579, 1081, 1035, 390, 3, -263, -198, -82, 38, + 18, -68, -12, 313, 761, 405, 249, 111, -76, + -91, 827, 948, 648, 613, 535, 522, 490, 421, + 41, -44, -281, -472, 652, 534, 193, 135, -90, + 41, -121, -356, -60, 663, 307, 61, -48, -344, + -118, -204, 328, 512, 870, 793, 610, 402, 186, + 156, 293, 74, -338, -475, -897, -594, -161, -497, + 226, 131, -138, 307, 169, -271, -164, -387, -624, + 62, -32, -61, -252, -541, -828, -1027, -523, -662, + 102, -61, 141, 112, -270, -251, -541, 25, -150, + 6, -132, -356, -686, -96, -322, -522, -31, -326, + -36, -209, -521, -229, 307, -132, -5, -99, -384, + 60, -51, -237, -668, -973, -407, -708, -75, -172, + 26, -138, -266, 111, -302, 43, -278, -356, -359, + 570, 822, 496, -154, -312, -92, 137, 279, 371, + -146, 368, 409, 68, 6, 77, 167, 202, 162, + -103, 294, 607, 415, 483, 462, 480, 431, 408, + -120, -338, -612, -524, 584, 331, 92, 433, 276, + -178, -293, -154, -41, 269, 100, -9, 213, 160, + -218, -304, 463, 454, 397, 273, 202, 286, 273, + -232, 7, 6, -388, -472, -427, -378, -167, -100, + -294, -183, 134, -47, 101, -88, -84, -117, -3, + 57, 17, -202, -634, -989, -1119, -533, 176, -36, + 120, -28, 23, 111, -319, 318, -22, -77, 266, + -271, -464, -434, -658, -640, -385, -385, -99, -69, + -198, -259, -266, -44, -39, -139, -137, 171, 66, + 9, -145, -377, -846, -1000, -111, -325, 342, 135, + -81, -286, -380, 192, -57, 307, 76, -24, -140, + 677, 702, 247, 56, 249, 141, -105, -236, -99, + 36, -39, -69, 348, 198, -93, 322, 91, -72, + -127, -376, -657, 139, 623, 223, 501, 306, 220, + -113, -384, -796, 504, 438, 85, 213, -83, -194, + -174, -422, 7, 1155, 1089, 1182, 1003, 945, 806, + 8, -126, -317, -103, -351, -695, -98, -268, -537, + 33, -103, -290, 167, -39, -407, 44, -208, -375, + 104, -23, -64, -291, -637, -851, -1084, -61, -112, + -75, -306, -434, 218, -148, -354, -680, -133, -216, + -121, -377, -718, -97, -130, -361, -156, -379, -599, + -56, -254, -586, 235, 157, -214, 11, -260, -149, + -124, -267, -397, -580, -593, -527, -805, -385, 346, + -193, -440, -708, -351, -141, -255, -499, -147, -185, + 448, 660, 494, 208, 509, 461, 338, 291, 149, + -223, 88, 335, 159, 212, 191, 286, 308, 205, + -171, -242, 514, 362, 295, 524, 552, 694, 585, + -64, -308, -448, -21, 284, 786, 446, 289, 92, + -218, -390, -7, 169, 206, 330, 352, 408, 358, + -36, 702, 959, 859, 861, 1115, 1269, 1357, 1305, + -133, -341, -65, 678, 417, 440, 486, 518, 780, + 33, -44, -191, -344, -461, -755, -201, 217, -31, + -353, -547, -44, 123, -61, -68, -79, 29, 60, + 73, -57, -406, -766, -1243, -1203, 240, 400, 165, + -73, -282, -601, -213, -171, -375, 332, 35, -103, + -29, -207, -553, -476, -638, -908, 172, -22, -135, + -192, -239, -164, -103, -111, -47, 153, 125, 110, + -1, -203, -570, -1030, -1424, -535, 155, 1, 147, + -333, -653, -865, -197, -158, -21, -44, 95, 108, + 389, 588, 490, 33, -237, -524, -628, -136, -260, + 40, -177, -462, 453, 862, 380, 131, -130, -405, + -76, -281, -741, -742, 898, 619, 277, 71, -222, + -32, -265, -556, -25, 994, 682, 305, 126, -165, + -69, -349, -585, 234, 1158, 903, 626, 510, 251, + -1, -99, -272, -210, -603, -351, -540, -811, -383, + -16, -230, -504, 410, 149, -205, -343, -651, -639, + 103, -9, -227, -205, -562, -781, -1079, -1208, -156, + 143, 63, -135, -67, -317, -602, -784, -1154, -640, + -144, -391, -674, -622, -200, -254, -660, -947, -395, + -40, -250, -625, 27, 543, 94, -131, -386, -673, + -123, -371, -757, -451, -564, -614, -415, -711, -35, + -116, -309, -593, -268, 239, -33, -338, -650, -135, + 94, 251, 554, 57, -312, -423, -154, -57, 235, + -268, -71, 381, 114, -44, -87, 125, 173, 133, + -131, -19, 1149, 670, 486, 356, 309, 369, 296, + -223, -501, -899, -722, -70, 6, 131, 310, 394, + -99, -303, -517, 249, 64, -53, 135, -11, 453, + -147, -399, -730, -401, 817, 738, 802, 749, 575, + -154, -435, -739, 800, 593, 366, 529, 318, 326, + -224, 45, -39, -387, -515, -518, -608, -384, -321, + -315, -377, 143, -101, -113, -377, -177, -144, -12, + 117, 40, -239, -651, -1051, -581, -737, -990, -328, + 26, -50, -157, -23, -453, -283, -531, -546, 192, + -252, -501, -743, -589, -627, -499, -328, -118, -72, + -324, -494, -244, -306, -144, -177, -262, -135, -78, + -36, -234, -519, -961, -1290, -314, -479, -371, -45, + -95, -292, -535, -8, -300, 112, -164, -277, 198, + -99, -128, 880, 836, 579, 351, 23, -95, -217, + -27, -258, 124, 1011, 597, 425, 144, 7, -73, + -69, -300, -683, -435, 1132, 899, 504, 332, 109, + -74, -323, -637, 563, 1074, 608, 371, 105, -49, + -259, -121, 1440, 1334, 1628, 1490, 1438, 1223, 933, + -82, -306, -613, -222, -378, -675, -545, -671, -845, + 53, -124, -347, 422, 52, -125, -270, -529, 9, + 79, -89, -320, -662, -999, -1199, -1243, -676, -297, + -68, -273, -611, 137, -146, -397, -627, -845, -220, + -112, -346, -797, -826, 234, -132, -188, -278, -522, + -159, -405, -734, -419, 293, 74, -167, -167, 184, + -153, -437, -833, -1080, -336, -472, -561, -340, -253, + -169, -423, -820, -904, -131, -19, -346, -604, 31, + 33, -31, 312, 62, -148, 49, -59, 564, 486, + -306, -333, 194, -44, 67, 72, 147, 205, 243, + -207, -49, 1360, 983, 969, 991, 1014, 1110, 973, + -211, -172, 883, 627, 711, 674, 705, 798, 746, + -88, -325, -763, -974, 687, 908, 514, 382, 172, + -292, -612, -805, 63, 131, 270, 259, 352, 348, + -235, -84, 955, 818, 1120, 1289, 1559, 1480, 1285, + -180, -461, -614, 657, 691, 745, 854, 783, 713, + -97, -309, -477, -614, -777, -734, -768, -526, -472, + -344, -476, -35, -169, 49, -77, -150, -240, -141, + -52, -268, -639, -919, -1278, -1113, -342, -333, -151, + -68, -242, -585, -73, -209, -478, -159, -429, 133, + -197, -499, -1005, -1268, -272, -224, -105, -67, 17, + -363, -618, -414, -116, -62, 20, 10, 116, 108, + -195, -475, -906, -1260, -891, -441, -277, -142, -28, + -226, -519, -950, -700, -275, -266, -116, -105, 82, + 404, 511, 520, 327, 17, -194, -333, -536, -586, + -114, -130, 276, 237, 204, 342, 135, -16, -111, + 191, 180, -137, -467, 272, 106, -95, 17, -192, + -80, -290, -626, 194, 598, 196, 21, -281, 77, + 137, 367, 534, 764, 670, 382, 296, 153, 84, + 303, 497, 144, -85, -125, -539, -482, -464, -764, + 233, 347, 68, -147, 169, -210, -242, -226, -482, + 307, 422, 154, -175, -386, -722, -724, -904, -1015, + 309, 308, 160, -60, -470, -420, -598, -791, -219, + 68, 121, -137, -560, -146, -446, -515, -494, -729, + 130, 53, -227, 46, 474, 32, -161, -192, -490, + 213, 164, -71, -465, -876, -161, -456, -587, -48, + 218, 117, 39, 177, -194, -88, -226, -418, 50, + 210, 547, 569, 279, 121, -44, -50, 10, -84, + 58, 140, 182, -5, 267, 117, 106, 211, 198, + 153, 559, 872, 460, 222, 108, 188, 180, 183, + 158, 119, 284, -153, -271, 229, 87, 110, -57, + -183, 82, 118, 21, 13, 40, 118, 191, 185, + 163, 56, 609, 341, 50, 329, 68, 266, 218, + 100, 206, 18, -304, -107, -436, -487, -65, -306, + -86, 154, 134, -30, -45, -73, -104, -80, -96, + 245, 330, 10, -440, -849, -1082, 79, 40, -265, + 196, 372, 272, -181, -493, -389, 275, 80, -59, + 2, -12, -246, -505, -100, -436, 21, -187, -431, + -221, -48, 36, -271, -186, -147, -109, 26, 71, + 213, 140, 72, -351, -620, -84, -363, 69, 46, + 91, 167, -3, -95, -99, -105, -48, 114, 147, + 259, 249, 172, 607, 406, 52, 59, -189, -320, + 115, -85, -54, 574, 128, 226, -59, -253, 130, + 39, 364, 757, 940, 728, 660, 659, 583, 770, + -115, -338, -760, -471, 394, 37, 441, 178, 6, + -57, -305, -525, 796, 453, 188, -4, -114, 248, + 71, 444, 797, 731, 1096, 1157, 1222, 1029, 811, + 135, 359, 551, 425, 749, 815, 874, 704, 502, + 132, 247, 0, -206, -449, -750, -258, -514, -633, + 248, 249, 91, 121, -195, -499, -90, -282, -435, + 78, 20, -277, -623, -983, -1224, -415, -458, -639, + 347, 509, 208, -179, -464, -728, -76, -237, -486, + -103, -343, -756, -713, -265, -609, -191, -398, -636, + -121, -383, -749, 567, 252, -36, -354, -417, -50, + 204, 100, -149, -650, -1081, -47, -7, -263, 111, + -46, -180, -267, -324, -562, -394, -692, 398, 292, + 482, 670, 683, 624, 442, 165, 116, 36, -149, + 108, 247, 291, 247, 355, 122, 109, 224, 296, + 292, 349, 725, 482, 388, 329, 429, 620, 667, + -34, 197, 213, -127, 84, 494, 620, 575, 375, + 126, 207, 172, 167, 362, 202, 296, 395, 455, + -6, 250, 539, 467, 636, 801, 1149, 1287, 1118, + 27, 240, 369, 280, 440, 411, 634, 892, 953, + 159, 170, -58, -395, -797, -690, 77, -211, -334, + -5, -28, -13, -74, -335, -603, 300, 88, -205, + 82, -33, -364, -698, -1203, -1153, 110, -146, -289, + 113, 1, -243, -588, -994, -496, 414, 160, 42, + -56, -247, -440, -693, -996, -479, 11, -178, -357, + -151, -353, -327, -211, -340, 141, 65, 425, 453, + 34, -169, -455, -932, -1215, 138, 499, 256, 324, + 68, 139, -15, -547, -478, 17, 306, 502, 481, + -32, -134, 445, 129, -143, -244, -503, -507, -599, + 61, -140, -345, 496, 458, -2, 20, -227, -514, + 215, 519, 920, 1053, 1090, 791, 528, 290, 155, + -54, -233, -647, -602, 639, 294, -2, -167, -442, + -78, -315, -791, -113, 820, 403, 158, -116, -356, + -105, -379, -236, 1224, 893, 749, 568, 356, 214, + -17, -199, -144, 50, -283, -247, -578, -846, -1087, + 69, -11, -381, -206, 209, -284, -387, -416, -716, + 39, -5, -145, -374, -682, -909, -1074, -1169, -1066, + 287, 226, 67, -221, -662, -171, -421, -642, -707, + -132, -348, -538, -448, -20, -4, -354, -748, -933, + 4, -75, -289, -598, 317, 52, -208, -297, -559, + -88, -264, -358, -589, -631, -248, -523, -822, -1071, + 70, -8, 54, -314, -515, 92, -146, -274, -493, + 199, 62, 391, 158, -141, 71, -219, -203, -207, + 152, 40, 329, 162, -29, 48, -149, 108, 127, + 267, 722, 1256, 882, 625, 248, 8, -81, -60, + -58, -138, -291, -600, -12, -2, -39, 147, 117, + -107, -345, -513, 459, 76, 92, -272, 388, 262, + 362, 516, 203, -409, -716, -831, -331, 185, 209, + -117, -391, -298, 671, 292, 538, 257, 166, -38, + -102, -319, -194, -283, -573, -262, -579, -219, -444, + -235, 78, 11, -168, -101, -229, -263, -321, -123, + 70, 50, -170, -599, -996, -588, -263, -516, -455, + 394, 363, 229, -136, -538, 21, -183, -348, -201, + -124, -368, -640, -879, -847, -209, -409, -494, -515, + -127, -341, -541, -425, -510, -10, -252, -473, -291, + 84, -69, -201, -676, -868, 103, -311, -132, -320, + 5, -173, -188, -297, -628, 197, -57, 7, -11, + 49, -160, 56, 558, 111, 33, -311, -440, -463, + -1, -246, -307, 862, 453, 139, -170, -355, -232, + -197, -38, 1702, 1331, 1252, 950, 692, 504, 426, + -108, -344, -861, -1172, 444, 354, 88, -46, -220, + -53, -321, -494, 1113, 744, 364, 198, -34, -75, + -69, 199, 897, 1140, 1343, 1183, 977, 742, 522, + 122, 44, -269, 27, -155, -562, -307, -590, -773, + 154, 42, -160, 252, -129, -305, -471, -733, -371, + 135, 185, -82, -416, -722, -913, -504, -743, -880, + 149, 214, -84, -329, -680, -835, -426, -661, -81, + -128, -380, -735, -998, -337, 17, -182, -467, -697, + -84, -290, -510, -592, 13, 440, 154, -38, -279, + 70, -61, -246, -727, -1047, -80, -381, -535, -704, + 178, -2, -146, -670, -938, 482, 138, 63, 65, + -11, 15, 772, 443, 142, -20, -209, -126, -161, + -32, -249, 95, 552, 124, 30, -343, 82, -86, + -163, -257, 899, 1097, 906, 751, 502, 390, 294, + -51, -258, -447, -806, -368, 763, 464, 364, 183, + -166, -374, -367, 87, 35, 399, 418, 856, 833, + -205, -310, 588, 778, 785, 1065, 1118, 1245, 1157, + -173, -312, 107, 345, 400, 790, 870, 1113, 1001, + -7, -120, -387, -410, -614, -943, -226, -384, -491, + -203, -288, -51, -331, -90, -178, -408, -573, -338, + 56, -29, -273, -627, -1041, -798, -247, -467, 148, + 66, -2, -205, -205, -575, -349, -57, -352, -58, + -45, -225, -471, -924, -497, 77, -32, 44, -135, + -277, -491, -497, -502, -424, -202, -137, 77, 96, + 26, -179, -469, -1008, -1260, 262, -35, -132, -259, + -66, -232, -447, -533, -789, -191, -100, -267, 364, + 111, 43, -287, -423, -608, -987, -922, -799, -827, + 77, 76, -101, -260, -549, -850, -88, -231, -329, + 75, 24, -66, -269, -427, -528, -773, 201, -5, + 67, 7, -61, -320, -487, 12, -200, -242, -94, + 27, -54, -149, -354, -661, -594, -450, -481, 560, + 31, -69, -246, -549, -1141, -178, -232, -275, -288, + 16, -84, -176, 7, -83, -210, -246, -424, -589, + 63, -60, -201, -90, -269, -400, -685, -1218, -258, + 169, 217, 142, -71, -243, -433, -504, -511, -537, + 6, -105, -234, -321, -188, -131, -307, -521, -1319, + -34, -151, -369, 11, 44, -95, -280, -500, 160, + 31, -37, -163, -334, 288, 89, -150, -86, -299, + -35, -161, -362, -74, -74, -263, 240, 9, -153, + -45, -208, -529, -896, 89, 24, -130, -313, -373, + 234, 276, 197, -10, -236, -162, -134, -85, -112, + 42, -73, 133, 392, 98, 72, -153, -162, -99, + -3, -145, -338, 408, 401, 133, -52, -296, -501, + 3, -109, -152, -85, -56, 42, -145, 703, 205, + -49, -149, -281, -134, -121, -41, -21, 16, 958, + 30, -107, -196, -463, -523, 490, 236, 70, -128, + -33, -161, -364, -148, 757, 516, 250, 43, -65, + -34, -193, -244, 750, 527, 349, 234, 172, 134, + -64, -223, -379, 55, 28, 248, 793, 442, 320, + 29, -85, -298, -622, -888, 127, 206, 387, 460, + -48, -170, -477, -876, 573, 635, 440, 375, 311, + 42, 3, -212, -441, -718, -821, 388, 373, 211, + -106, -155, 1092, 459, 570, 561, 506, 604, 514, + -144, -264, 0, 460, 619, 877, 916, 1273, 921 +}; +/* ISF codebook - common 1st stage, 2nd split (only in AMR-WB IO mode) */ +const Word16 dico2_isf_fx[] = +{ + 1357, 1313, 1136, 784, 438, 181, 145, + 636, 648, 667, 568, 442, 217, 362, + 427, 440, 674, 524, 332, 117, -417, + 121, 295, 468, 465, 230, 44, -221, + -147, -240, 149, 80, 390, 278, 106, + -418, -556, 552, 511, 235, 144, -95, + 43, 193, 274, 150, 67, 34, -273, + -43, -126, 171, 416, 282, 63, -354, + -372, -86, -344, -108, -94, -182, -89, + -600, -840, -200, 465, 258, -11, -253, + -48, 329, 97, -290, -543, -795, -354, + -570, -117, 187, 10, -133, -416, -76, + -618, -129, -247, -371, 45, -76, 277, + -1022, -1079, 126, 474, 254, 127, 52, + -281, 76, -167, -361, -283, -551, -283, + -119, -52, -1, 134, -32, -204, -415, + 1064, 827, 637, 684, 464, 209, 12, + 482, 416, 449, 371, 335, 294, 194, + 719, 576, 365, 135, 113, 91, -199, + 298, 176, 493, 366, 194, 163, 36, + -35, -236, -259, -36, -4, 99, 152, + -98, -306, -27, 228, 90, 111, -86, + 91, 13, -211, -258, -106, 86, -64, + 73, -35, -57, -31, 162, 35, -192, + -109, -335, -629, -66, -61, -128, 322, + -495, -669, -728, 193, 31, -220, 122, + 324, 95, -89, -91, -409, -710, -154, + 0, -234, 92, 33, -343, -609, -220, + -343, -408, -476, -655, -153, 82, 222, + -490, -745, -255, 49, -48, 135, -127, + 119, -67, -328, -390, -272, -545, -56, + -57, -130, -10, -7, -164, -47, -22, + 984, 1064, 961, 568, 210, -27, 16, + 811, 691, 754, 514, 224, -35, 166, + 662, 704, 618, 386, 57, -211, -257, + 510, 359, 418, 393, 91, -144, -18, + -193, -31, -27, 223, 89, -143, 24, + -112, -98, 471, 319, 185, 3, 175, + 252, 146, -47, 272, 48, -211, -234, + 146, 69, 203, 364, 68, -52, 51, + -259, -478, -697, -349, -758, -501, 63, + -501, -769, -289, 79, -311, -497, -106, + 251, 53, -235, -469, -895, -884, 145, + -416, -551, 140, -133, -523, -775, 44, + -326, -423, -713, -497, -86, -431, 99, + -757, -772, -160, -76, -46, -32, 379, + 85, -35, -200, -401, -663, -1040, -247, + -180, -330, -92, -376, 27, -183, -110, + 1279, 1086, 781, 502, 324, 164, 157, + 682, 466, 449, 277, 146, 28, 409, + 635, 472, 390, 107, -232, -538, -139, + 196, 396, 332, 213, 209, -29, -81, + 150, -95, -312, 76, -77, -320, -50, + 46, 9, 47, 175, 139, 30, 384, + 218, 206, -24, -250, -96, -276, -183, + 26, 119, 38, 14, -4, -133, -52, + -477, -614, -987, -715, -631, -813, 200, + -744, -1009, -1065, -745, -631, -171, 18, + -137, -251, -483, -613, -980, -1203, 12, + -605, -767, -562, -686, -1088, -515, 58, + -202, -428, -782, -1072, -96, -234, -179, + -480, -709, -1070, -897, -131, -92, 321, + -145, -193, -512, -729, -572, -765, -210, + -331, -585, -525, -631, -281, -208, -303, + 1165, 1104, 939, 828, 716, 426, 155, + 6, -109, 820, 778, 415, 113, -27, + 381, 339, 314, 265, 121, -9, -474, + -373, 47, 584, 442, 99, -231, -113, + -496, -38, -285, 262, 305, 170, 4, + -587, -556, 69, 66, 471, 354, 13, + -138, 70, -18, 106, 67, 167, -302, + -445, -141, 185, 191, 151, 83, -133, + -257, -521, -720, -198, 134, -46, -182, + -819, -1168, -777, 512, 359, 95, -113, + 137, -2, -74, -138, -401, -114, -371, + -242, -466, 204, 223, -31, -212, -192, + -532, -637, -466, -686, 256, 277, -139, + -1141, -1244, -381, -75, -54, 14, 88, + -311, 115, -143, -499, -343, 124, -416, + -616, -147, -135, 43, -4, 121, -369, + 835, 783, 641, 390, 355, 350, 64, + 72, 194, 443, 467, 436, 219, 372, + 464, 369, 192, 4, -156, -72, -226, + 57, 206, 303, 205, 188, 101, 265, + -40, -205, -488, -184, 276, 64, -26, + -217, -433, -297, 137, 328, 308, -289, + 378, 81, -308, -465, 57, -37, 227, + -100, 24, -36, -151, 199, 8, 143, + -426, -697, -1059, -133, 388, 161, 321, + -644, -1023, -1271, 39, 66, -123, 70, + 372, 177, -173, -556, -553, -304, -189, + -117, -369, -425, -122, -462, -152, -73, + -649, -850, -1189, -767, 497, 360, 222, + -798, -1139, -1455, -190, 430, 234, 179, + 42, -94, -405, -692, 38, -202, -246, + -169, -366, -290, -88, -64, 32, -292, + 1010, 923, 938, 710, 465, 230, 342, + 217, 300, 1054, 675, 68, -458, -179, + 78, 453, 316, 18, -237, -496, -243, + 167, 21, 424, 215, -91, -303, -170, + -290, -81, -70, -67, 40, 54, -59, + -353, -427, -90, 53, 94, 9, 54, + -28, 318, 283, 15, -240, -58, 79, + -75, -121, 229, 35, 58, 6, -133, + -351, -514, -744, -834, -705, -137, 164, + -1124, -1388, -1055, -230, -73, 40, 36, + -163, -233, -532, -785, -1170, -697, 96, + -788, -959, -246, -430, -624, -165, -8, + -856, -540, -630, -907, -337, -70, 76, + -937, -1042, -659, -733, -208, 199, -26, + -523, 78, -98, -501, -869, -890, -81, + -624, -703, -45, -348, -25, 87, -186, + 1005, 823, 546, 249, 90, -22, 207, + 298, 397, 381, 319, 200, 62, 303, + 473, 379, 133, -247, -632, -441, 75, + 284, 208, 391, 115, -25, 44, 95, + -72, 79, -95, -63, -129, -293, 203, + -164, -349, 115, 122, 69, -1, 378, + 348, 170, 99, 58, -179, -302, 188, + -190, -2, 150, 23, -51, -11, 216, + -615, -863, -1090, -1427, -802, -48, -6, + -961, -1276, -1548, -727, -58, 56, 223, + -124, -255, -561, -988, -1277, -148, -82, + -480, -660, -891, -1191, -1339, -325, 20, + -621, -917, -1296, -1350, 264, 289, 50, + -844, -1022, -1345, -1329, -293, 46, 278, + -260, -468, -829, -1176, -533, -560, -78, + -215, -484, -822, -1233, -791, 15, -138, + 1301, 1317, 1262, 1048, 716, 357, -64, + 578, 824, 925, 802, 630, 362, 102, + 470, 925, 767, 514, 327, 190, -112, + 225, 492, 495, 437, 598, 384, -45, + 43, 82, -42, 175, 519, 342, -64, + -304, -154, 159, 576, 403, 221, 327, + 214, 244, 122, -62, 312, 92, -160, + 218, 208, 310, 268, 306, 323, -199, + -285, -269, -79, -124, -143, -153, 236, + -205, -384, -426, 344, 59, -185, -184, + -272, 247, 126, -210, -518, -468, 78, + -99, -120, 502, 160, -280, -557, 304, + -423, -17, -283, -443, 215, 212, -140, + -564, -684, -228, 510, 361, 130, 323, + -428, 335, 98, -65, 36, -215, -246, + -362, 51, 364, -16, -234, 150, -165, + 914, 883, 751, 653, 676, 464, -153, + 631, 545, 535, 720, 596, 360, -81, + 783, 712, 512, 439, 341, 251, -391, + 497, 417, 249, 372, 295, 173, -193, + 128, -110, -385, 93, 39, 173, -231, + 216, -59, -253, 462, 389, 154, 69, + 455, 270, -4, -337, -49, 233, -322, + 307, 143, 53, 218, 128, 236, -156, + -37, -186, -240, -411, -110, 9, 399, + -140, -365, -628, 258, 380, 214, 277, + 131, 454, 177, -285, -520, 108, -214, + 77, -141, 201, -123, -490, -131, 60, + -14, -194, -521, -741, 273, 362, -33, + -362, -566, -287, -228, 161, 237, 317, + -269, 195, -75, -375, -204, 11, 77, + -128, -264, -156, -223, -475, 265, 27, + 1238, 1147, 916, 689, 432, 210, -280, + 800, 664, 879, 726, 411, 160, -164, + 454, 686, 536, 275, 147, 46, 111, + 303, 486, 512, 355, 241, 181, -69, + 79, 92, 29, 147, 233, 52, 17, + -171, 289, 131, 439, 271, 3, -10, + 413, 241, 144, 174, 155, -2, 14, + 58, 217, 247, 219, 149, 175, -18, + 228, -8, -240, -206, -513, -191, 202, + -96, -272, -454, 33, -300, -575, 46, + -10, -108, -246, -347, -770, -535, 9, + -326, -430, -61, -321, -704, -299, 201, + -1, -280, -603, -419, -185, 18, -36, + -516, -522, -379, -291, -181, -97, 27, + -159, -313, -525, -224, -510, -831, -197, + -292, -459, -59, -310, -562, -143, -351, + 1066, 912, 631, 389, 207, 86, -224, + 596, 512, 596, 505, 314, 122, -48, + 787, 861, 441, -93, -303, 33, -190, + 257, 469, 337, 51, 15, 298, -93, + 295, 73, -119, 25, 36, 23, 108, + -28, -3, -32, 114, 21, 185, 107, + 482, 305, 15, -279, -319, 52, 96, + 226, 46, 115, 72, -136, 133, -125, + 18, -207, -559, -590, -503, -482, 321, + -571, -789, -951, -172, -441, -538, 113, + 181, 14, -310, -641, -1001, -202, 159, + -136, -393, -433, -513, -911, -144, -22, + 72, -265, -706, -954, -159, 53, 332, + -338, -591, -852, -383, -395, 56, 44, + 43, -158, -464, -897, -631, -157, -294, + -161, -128, -328, -573, -483, -125, 11, + 1017, 906, 1051, 1005, 679, 341, -102, + 359, 334, 1567, 1314, 723, 105, 10, + -65, 726, 529, 301, 220, 43, -273, + -510, 436, 719, 566, 358, 179, 114, + -560, 298, 133, -120, 342, 225, 14, + -899, -101, 217, 617, 400, 146, -58, + -41, 352, 82, -196, 39, 121, -167, + -212, 59, 447, 284, 423, 250, -169, + -371, -484, -596, 30, -41, 249, 22, + -372, -650, -794, 477, 445, 216, -79, + -352, 275, 17, -443, -929, 92, 19, + -699, -696, 431, 264, -49, -310, 182, + -978, -217, -430, -400, 101, 261, 72, + -929, -889, -357, -13, 463, 378, 236, + -826, 56, 30, -299, -360, -128, -51, + -878, -299, -111, 75, 65, 36, 3, + 817, 368, -25, 354, 697, 591, -173, + 309, 212, 222, 751, 484, 140, -56, + 593, 379, 70, -8, 258, 180, 110, + 165, -46, 255, 297, 219, 273, 105, + 160, -70, -358, -181, 379, 330, 319, + -238, -369, -198, 740, 580, 319, -143, + 201, 109, -202, -456, 328, 276, -141, + 203, 170, 111, 42, 207, 360, 188, + -345, -399, -513, -233, 650, 422, 81, + -635, -961, -1220, 463, 539, 204, 209, + 202, -25, -194, -498, -787, 193, -143, + -449, -538, 195, -106, -331, 68, 62, + -228, -477, -840, -576, 317, 128, 283, + -671, -937, -807, -114, 391, 335, -62, + 246, 2, -314, -679, -303, 180, -88, + -107, -272, 90, -198, -28, 290, -112, + 885, 1149, 1021, 712, 496, 281, -83, + 269, 492, 787, 643, 347, 70, 124, + 336, 636, 499, 92, -229, -179, 191, + 26, 402, 564, 340, 149, -11, 135, + -440, 561, 470, 204, -72, -186, 140, + -720, 14, 355, 229, 68, -133, 465, + 110, 310, 103, 12, 106, 29, 158, + -178, 113, 161, 142, 121, 115, 27, + -651, -414, -645, -152, -164, -13, -429, + -639, -944, -681, -104, -81, 52, -189, + -663, -164, -316, -683, -954, -205, -83, + -609, -669, -172, -517, -694, 283, -80, + -646, -152, -383, -678, -246, -40, -143, + -747, -796, -745, -390, -98, 43, 275, + -599, -199, -398, -433, -436, -538, 31, + -1107, -568, -376, -265, -126, -21, 1, + 847, 573, 308, 392, 305, 101, 55, + 273, 293, 201, 267, 346, 201, 123, + 727, 480, 226, 2, -65, -138, 164, + 273, 208, 173, 292, 12, 253, 174, + 340, 207, 180, 88, 116, 46, 475, + -460, -166, -30, 13, 110, 173, 396, + 137, 88, 43, -137, -94, 34, 284, + 96, -14, 226, 40, 63, 70, 130, + -467, -735, -1012, -1174, -307, 305, -67, + -612, -920, -1146, -567, -8, 92, -25, + -182, -271, -492, -754, -857, 287, -75, + -494, -787, -689, -683, -709, 137, -326, + -288, -550, -903, -1105, 334, 321, -62, + -354, -653, -834, -445, 1, 377, -152, + -162, -306, -608, -937, -297, 247, -192, + -234, -477, -244, -488, -266, 342, -332 +}; + +/* ISF codebook - 46b, 2nd stage, 1st split (only in AMR-WB IO mode) */ +const Word16 dico21_isf_46b_fx[] = +{ + 329, 409, 249, + -33, 505, 160, + -29, -14, 582, + -262, 127, 354, + 145, 237, 175, + -152, 245, 122, + 27, 42, 340, + -84, -93, 311, + 285, 222, -156, + 47, -43, -504, + 234, 121, 385, + 104, -317, 45, + 176, 195, 8, + 104, -59, -94, + 177, 53, 192, + -34, -127, 152, + 570, 277, -34, + -67, -329, -639, + -157, -272, 462, + -177, -462, 198, + 322, 179, 115, + -386, 171, 19, + 19, -12, 195, + -120, -252, 201, + 304, 36, -336, + -128, -221, -380, + 171, -185, 296, + -242, -312, 23, + 198, 39, 16, + -3, -177, -111, + 111, -93, 76, + -92, -223, 4, + 177, 406, -44, + -168, 380, -149, + -4, 273, 331, + -420, 513, 277, + 21, 247, 47, + -58, 131, -2, + -3, 134, 180, + -145, 40, 175, + 189, 74, -145, + -27, -45, -325, + 370, -114, -21, + -83, -415, -173, + 77, 95, -51, + -40, -30, -67, + 71, 88, 86, + -35, -98, 14, + 69, 197, -334, + -196, 79, -231, + -348, -137, 218, + -352, -89, -85, + 47, 201, -130, + -165, 37, -15, + -43, 3, 86, + -161, -108, 79, + 83, 21, -237, + -81, -149, -238, + 150, -186, -251, + -186, -249, -162, + -19, 66, -139, + -26, -50, -181, + 24, 11, 0, + -130, -105, -98 +}; +/* ISF codebook - 46b, 2nd stage, 2st split (only in AMR-WB IO mode) */ +const Word16 dico22_isf_46b_fx[]= +{ + -127, 310, 42, + -242, 197, 5, + -151, 84, -17, + -214, 127, -149, + -247, -131, 159, + -268, -267, -95, + -217, 1, -79, + -271, -80, -185, + -45, 436, 159, + 165, 199, 391, + -33, 81, 187, + -66, -42, 355, + -298, -57, 343, + -108, -537, 226, + -144, -23, 193, + 176, -402, 87, + 53, 296, 25, + -84, 253, -104, + -58, 105, -126, + -169, 174, -314, + -48, 44, -294, + -164, -417, -242, + -139, 3, -194, + -155, -207, -211, + 119, 322, 213, + 333, 50, 380, + 237, 247, -2, + 466, -16, 201, + 238, -255, -107, + 67, -440, -149, + 122, -88, -139, + 88, -247, -73, + -41, 231, 167, + -62, 155, 16, + -65, 16, 77, + -68, -2, -63, + -151, -300, 160, + -18, -333, 54, + -56, -94, 5, + 2, -190, 14, + 92, 148, 209, + 108, 9, 272, + 108, 35, 110, + 142, -85, 145, + 47, -157, 279, + 3, -320, 246, + 43, -72, 68, + 86, -217, 135, + 36, 140, 79, + 56, 175, -49, + 26, 45, 3, + 73, 55, -101, + 109, -183, -242, + -4, -283, -242, + 48, -68, -48, + -6, -153, -122, + 161, 196, 96, + 232, 80, 190, + 165, 97, 11, + 258, -31, 71, + 267, -77, -91, + 311, -209, 87, + 152, -14, -22, + 150, -149, 9, + -324, 557, 187, + -384, 307, 46, + -251, 27, 77, + -365, 77, -52, + -482, -84, 160, + -424, -515, -64, + -294, -120, -4, + -476, -116, -109, + -97, 318, 365, + 106, 627, 445, + -190, 120, 287, + -146, 65, 619, + -427, 242, 363, + -361, -371, 432, + -347, 102, 168, + -629, 195, -14, + -65, 476, -47, + -297, 320, -168, + -55, 356, -264, + -391, 82, -286, + -51, -31, -556, + -178, -399, -586, + -205, -49, -360, + -343, -238, -337, + 220, 457, 58, + 561, 467, 259, + 340, 270, -168, + 450, 77, -280, + 60, 167, -413, + 133, -252, -492, + 216, 157, -290, + 282, 0, -495, + -226, 293, 183, + -157, 135, 122, + -158, -59, 39, + -133, -118, -97, + -332, -309, 113, + -160, -425, -6, + -149, -211, 24, + -80, -277, -90, + -11, 125, 338, + 130, -71, 465, + 5, -45, 184, + 237, -95, 253, + -139, -197, 297, + -19, -300, 511, + -63, -152, 139, + 250, -289, 336, + 124, 339, -150, + 34, 176, -208, + 171, 166, -116, + 94, 38, -229, + 75, -65, -339, + -78, -205, -385, + 0, -30, -163, + -56, -110, -242, + 321, 244, 194, + 505, 238, -1, + 317, 116, 65, + 309, 88, -74, + 452, -51, -50, + 334, -217, -290, + 211, 41, -152, + 238, -55, -260 +}; + +/* ISF codebook - 46b, 2nd stage, 3rd split (only in AMR-WB IO mode) */ +const Word16 dico23_isf_46b_fx[]= +{ + -10, 151, 359, + 136, 298, 223, + 255, -104, 290, + 423, 6, 183, + -270, -269, -98, + -52, -82, 13, + -82, -274, -97, + 90, -246, -72, + -299, -70, 421, + -88, 365, 430, + 187, -318, 381, + 380, 37, 488, + -373, -316, 79, + -308, -101, 5, + -135, -451, 8, + 72, -421, -154, + 180, 170, -121, + 62, 177, -40, + 326, 80, -105, + 248, 263, -5, + -168, -181, -221, + -2, -23, -158, + -14, -149, -121, + 119, -91, -147, + 119, 332, -153, + 49, 303, 34, + 442, -55, -69, + 217, 454, 58, + -359, -187, -375, + -42, 50, -274, + -8, -267, -249, + 85, -86, -346, + -77, -40, 345, + 89, 134, 219, + 156, -80, 160, + 108, 40, 116, + -158, -206, 29, + 5, -32, 175, + -65, -158, 146, + 55, -78, 73, + -114, -222, 353, + -47, 81, 211, + 49, -151, 268, + 105, 4, 302, + -263, -132, 183, + -151, -28, 201, + -177, -307, 166, + 101, -221, 130, + 74, 58, -98, + 32, 44, 13, + 194, 30, -142, + 170, 96, 8, + -136, -119, -91, + -65, 8, -55, + 3, -188, 12, + 45, -63, -49, + 149, -21, -19, + 24, 144, 95, + 254, -22, 60, + 161, 196, 96, + -158, -61, 48, + -70, 33, 82, + -23, -321, 58, + 155, -147, 5, + -364, 328, 77, + -21, 453, 173, + -108, 82, 630, + 367, 263, 208, + -300, -62, -176, + -205, 143, -158, + -169, -410, -264, + 257, -269, -100, + -636, 289, -2, + -292, 627, 173, + -382, -363, 387, + 248, 524, 447, + -521, -111, -107, + -395, 118, -274, + -343, -680, -125, + -172, -447, -663, + 75, 148, -367, + -79, 263, -94, + 249, 148, -286, + 380, 271, -162, + -142, -4, -186, + -57, 111, -125, + -35, -108, -254, + 100, 29, -242, + -80, 303, -264, + -78, 464, -57, + 248, -22, -494, + 661, 662, 44, + -193, -40, -330, + -178, 145, -337, + -90, -199, -400, + -40, -23, -498, + -192, 114, 315, + -41, 244, 190, + 88, -97, 485, + 241, 80, 212, + -246, 40, 87, + -156, 147, 134, + -2, -334, 239, + 308, -203, 110, + -459, 251, 422, + -218, 310, 228, + -86, -346, 654, + 184, 175, 425, + -481, -63, 169, + -349, 117, 188, + -125, -560, 310, + 158, -416, 94, + 46, 171, -192, + -63, 157, 14, + 256, -35, -271, + 322, 123, 53, + -214, 4, -76, + -156, 86, -18, + 128, -197, -232, + 265, -90, -98, + -308, 332, -145, + -131, 308, 58, + 509, 59, -339, + 562, 196, -14, + -378, 100, -47, + -234, 202, 1, + 104, -270, -493, + 319, -210, -325 +}; +/* ISF codebook - 46b, 2nd stage, 4th split (only in AMR-WB IO mode) */ +const Word16 dico24_isf_46b_fx[]= +{ + -79, -89, -4, + -171, 77, -211, + 160, -193, 98, + 120, -103, 323, + 32, -22, -129, + 72, 78, -268, + 182, -76, -66, + 309, 99, -145, + -229, -157, -84, + -383, 98, -71, + -90, -352, 12, + -284, -178, 178, + -65, -125, -166, + -87, -175, -351, + 42, -198, -48, + 154, -140, -243, + -77, 18, 108, + -39, 355, 91, + 87, 8, 155, + -4, 158, 239, + 128, 95, -54, + 7, 246, -124, + 258, 15, 89, + 206, 216, 98, + -201, 9, 18, + -312, 233, 204, + -39, -174, 155, + -144, -9, 284, + -57, 70, -69, + -157, 187, 18, + 54, -30, 23, + 24, 135, 55 +}; + +/* ISF codebook - 46b, 2nd stage, 5th split (only in AMR-WB IO mode) */ +const Word16 dico25_isf_46b_fx[]= +{ + 169, 142, -119, 115, + 206, -20, 94, 226, + -106, 313, -21, 16, + -62, 161, 71, 255, + -89, 101, -185, 125, + 72, -30, -201, 344, + -258, 33, -8, 81, + -104, -154, 72, 296, + 144, -68, -268, -25, + 81, -78, -87, 106, + 22, 155, -186, -119, + -46, -28, 27, 91, + -114, -37, -175, -33, + -94, -222, -189, 122, + -132, -119, -191, -270, + -172, -173, 18, -43, + 279, 135, -42, -128, + 187, -86, 229, -138, + 159, 240, 140, 46, + 69, 25, 227, 77, + 21, 115, 13, 8, + 68, -248, 126, 81, + -150, 137, 207, -9, + -154, -133, 289, 67, + 143, -37, -86, -326, + 180, -32, 19, -23, + 26, 168, 116, -233, + -32, -26, 118, -78, + 3, -8, -45, -115, + 57, -215, -54, -83, + -209, 112, -22, -167, + -91, -151, 168, -262 +}; + +/* ISF codebook - 36b, 2nd stage, 1st split (only in AMR-WB IO mode) */ +const Word16 dico21_isf_36b_fx[]= +{ + -52, -96, 212, 315, -73, + 82, -204, 363, 136, -197, + -126, -331, 183, 218, 143, + -49, -41, 557, 230, 72, + 2, -73, 163, 377, 221, + 133, 111, 278, 215, -110, + -102, -20, 284, 113, 273, + 84, 319, 290, 18, 85, + -25, -5, 125, 132, -204, + -38, -5, 286, -9, -356, + -140, -256, 92, 117, -189, + -144, 191, 313, 51, -98, + 167, -10, 44, 247, 36, + 381, 197, 238, 74, 6, + 38, -408, 29, -3, -85, + 92, 266, 157, -25, -200, + 161, -121, 70, 84, -140, + -16, -86, 112, -94, -189, + -269, -270, 351, 107, -24, + -68, -67, 492, -103, -155, + -53, -131, 62, 122, 10, + 135, 84, 283, -55, -120, + -12, -219, 331, -81, 167, + 220, -136, 147, -172, -42, + 140, -95, -109, -88, -194, + 0, -2, -4, -33, -381, + -66, -217, 152, -186, -402, + 244, 108, 156, -140, -395, + 113, -136, -196, 110, -24, + 214, 118, 11, -64, -131, + -110, -286, -6, -332, 16, + 94, 97, 79, -291, -205, + -5, -39, -20, 252, -96, + 76, 174, 101, 163, 61, + -69, -239, -55, 399, 6, + -115, 319, 164, 275, 196, + -15, 36, -47, 331, 121, + 226, 209, 271, 325, 184, + 13, -80, -218, 471, 353, + 288, 378, 16, -51, 251, + 174, 116, 52, 149, -279, + 235, 276, 39, 120, -48, + 0, -108, -108, 241, -339, + -93, 534, 45, 33, -87, + 194, 149, -71, 405, -44, + 409, 370, 81, -186, -154, + 25, -102, -448, 124, -173, + 22, 408, -110, -310, -214, + -26, 23, -83, 114, 14, + -110, 164, 52, 223, -82, + 37, -25, -263, 306, -15, + -466, 415, 292, 165, -18, + 29, -19, -171, 155, 182, + 179, 144, -27, 231, 258, + -103, -247, -396, 238, 113, + 375, -154, -109, -4, 156, + 98, 85, -292, -5, -124, + 116, 139, -116, -98, -294, + -14, -83, -278, -117, -378, + 106, 33, -106, -344, -484, + 119, 17, -412, 138, 166, + 384, 101, -204, 88, -156, + -121, -284, -300, -1, -166, + 280, 33, -152, -313, -81, + -37, 22, 229, 153, 37, + -60, -83, 236, -8, -41, + -169, -228, 126, -20, 363, + -235, 17, 364, -156, 156, + -25, -30, 72, 144, 156, + 153, -26, 256, 97, 144, + -21, -37, 48, -65, 250, + 63, 77, 273, -128, 124, + -129, -26, 40, 9, -115, + -6, 82, 38, -90, -182, + -336, -13, 28, 158, 91, + -30, 241, 137, -170, -17, + 146, 14, -11, 33, 61, + 192, 197, 54, -84, 85, + 23, -200, -78, -29, 140, + 122, 237, 106, -341, 136, + -57, -142, -85, -16, -74, + -59, -90, -8, -187, -20, + -211, -267, 216, -179, -110, + -50, -7, 220, -267, -70, + -57, -42, -17, -15, 71, + 32, 21, 63, -137, 33, + -137, -175, 104, -68, 97, + -67, -43, 133, -301, 221, + -116, -200, -81, -92, -272, + -64, -41, -54, -244, -220, + -287, -242, -50, -87, -89, + -245, 236, 102, -166, -295, + 66, 24, -162, -71, 95, + 66, 136, -90, -220, -36, + -98, -161, -222, -188, 29, + -18, 18, -19, -415, 9, + 49, 61, 100, 39, -56, + -111, 82, 135, -31, 52, + -90, -153, -93, 189, 182, + -214, 295, 119, -74, 284, + 2, 137, 37, 47, 182, + 92, 117, 184, -53, 373, + -21, -14, -35, 136, 391, + 146, 129, -164, -28, 333, + 92, 80, -84, 100, -134, + -8, 217, -32, 3, -47, + -151, 251, -215, 142, 92, + -224, 310, -172, -275, 98, + 159, 155, -177, 112, 53, + 205, 27, 8, -240, 192, + 169, 120, -319, -201, 106, + 11, 36, -86, -237, 455, + -109, -154, -163, 174, -55, + -38, 32, -101, -78, -59, + -205, -321, -97, 69, 79, + -310, 44, 18, -185, 34, + -115, -20, -148, -39, 203, + -29, 154, -30, -158, 166, + -45, -131, -317, -24, 363, + -165, -205, -112, -222, 265, + -32, -44, -150, 54, -193, + -6, -38, -255, -169, -115, + -266, 87, -189, -36, -169, + -60, -87, -266, -436, -170, + -68, -81, -278, 24, 38, + -23, -19, -155, -256, 141, + -61, -226, -565, -175, 71, + 9, -29, -237, -515, 263 +}; + +/* ISF codebook - 36b, 2nd stage, 2nd split (only in AMR-WB IO mode) */ +const Word16 dico22_isf_36b_fx[]= +{ + -298, -6, 95, 31, + -213, -87, -122, 261, + 4, -49, 208, 14, + -129, -110, 30, 118, + -214, 258, 110, -235, + -41, -18, -126, 120, + 103, 65, 127, -37, + 126, -36, -24, 25, + -138, -67, -278, -186, + -164, -194, -201, 78, + -211, -87, -51, -221, + -174, -79, -94, -39, + 23, -6, -157, -240, + 22, -110, -153, -68, + 148, -5, -2, -149, + -1, -135, -39, -179, + 68, 360, -117, -15, + 137, 47, -278, 146, + 136, 260, 135, 65, + 61, 116, -45, 97, + 231, 379, 87, -120, + 338, 177, -272, 3, + 266, 156, 28, -69, + 260, 84, -85, 86, + -266, 154, -256, -182, + -17, -65, -304, -6, + -40, 175, -151, -180, + -27, 27, -87, -63, + 121, 114, -166, -469, + 159, -66, -323, -231, + 214, 152, -141, -212, + 137, 36, -184, -51, + -282, -237, 40, 10, + -48, -235, -37, 251, + -54, -323, 136, 29, + -88, -174, 213, 198, + -390, 99, -63, -375, + 107, -169, -164, 424, + 69, -111, 141, -167, + 74, -129, 65, 144, + -353, -207, -205, -109, + -160, -386, -355, 98, + -176, -493, -20, -143, + -252, -432, -2, 216, + -90, -174, -168, -411, + 13, -284, -229, -160, + -87, -279, 34, -251, + -75, -263, -58, -42, + 420, 53, -211, -358, + 384, -35, -374, 396, + 68, -228, 323, -2, + 167, -307, 192, 194, + 459, 329, -5, -332, + 375, 79, -7, 313, + 282, -124, 200, -92, + 271, -162, -70, 180, + -157, -298, -514, -309, + 58, -163, -546, 18, + 124, -364, 167, -238, + 83, -411, -117, 96, + 140, -112, -388, -624, + 259, -133, -317, 41, + 163, -130, -64, -334, + 226, -165, -124, -110, + -466, -61, 6, 229, + -153, 205, -145, 242, + -159, 48, 195, 148, + -58, 28, 31, 279, + -303, 185, 279, -4, + -61, 197, 59, 86, + -114, 123, 168, -52, + 35, 36, 100, 126, + -407, 102, -77, -40, + -338, -1, -342, 156, + -179, 105, -34, -97, + -185, 84, -35, 108, + -133, 107, -91, -357, + -180, 54, -229, 24, + -44, 47, 47, -182, + -66, 13, 45, 4, + -339, 251, 64, 226, + -42, 101, -350, 275, + -99, 398, 142, 121, + 111, 12, -102, 260, + 0, 505, 260, -94, + 161, 285, -96, 224, + -4, 206, 314, 33, + 167, 139, 88, 204, + -235, 316, -60, -25, + -8, -150, -312, 201, + -36, 292, 61, -104, + -40, 174, -162, 42, + -21, 402, -29, -351, + 21, 152, -360, -93, + 57, 191, 212, -196, + 76, 158, -21, -69, + -328, -185, 331, 119, + -53, 285, 56, 337, + -107, -24, 405, 29, + -18, 137, 272, 277, + -255, 22, 173, -191, + 295, 322, 325, 302, + 21, -27, 332, -178, + 119, 13, 271, 129, + -455, -180, 116, -191, + -227, 62, -148, 524, + -176, -287, 282, -157, + -243, 13, 199, 430, + -59, -49, 115, -365, + 72, -172, -137, 93, + -138, -126, 141, -84, + 5, -124, 38, -20, + -258, 311, 601, 213, + 94, 130, -61, 502, + -1, -157, 485, 313, + 146, -74, 158, 345, + 276, 135, 280, -57, + 490, 252, 99, 43, + 267, -74, 429, 105, + 278, -23, 119, 94, + -542, 488, 257, -115, + -84, -244, -438, 478, + -113, -545, 387, 101, + -95, -306, 111, 498, + 95, 166, 22, -301, + 420, -15, -58, -78, + 270, 29, 122, -282, + 160, -240, 50, -38 +}; +/* ISF codebook - 36b, 2nd stage, 3rd split (only in AMR-WB IO mode) */ +const Word16 dico23_isf_36b_fx[]= +{ + 81, -18, 68, -27, -122, -280, -4, + 45, -177, 209, -30, -136, -74, 131, + -44, 101, -75, -88, -48, -137, -54, + -245, -28, 63, -18, -112, -103, 58, + -79, -6, 220, -65, 114, -35, -50, + 109, -65, 143, -114, 129, 76, 125, + 166, 90, -61, -242, 186, -74, -43, + -46, -92, 49, -227, 24, -155, 39, + 67, 85, 99, -42, 53, -184, -281, + 142, -122, 0, 21, -142, -15, -17, + 223, 92, -21, -48, -82, -14, -167, + 51, -37, -243, -30, -90, 18, -56, + 54, 105, 74, 86, 69, 13, -101, + 196, 72, -89, 43, 65, 19, 39, + 121, 34, 131, -82, 25, 213, -156, + 101, -102, -136, -21, 57, 214, 22, + 36, -124, 205, 204, 58, -156, -83, + 83, -117, 137, 137, 85, 116, 44, + -92, -148, -68, 11, -102, -197, -220, + -76, -185, -58, 132, -26, -183, 85, + -7, -31, -2, 23, 205, -151, 10, + -27, -37, -5, -18, 292, 131, 1, + 117, -168, 9, -93, 80, -59, -125, + -182, -244, 98, -24, 135, -22, 94, + 221, 97, 106, 42, 43, -160, 83, + 25, -64, -21, 6, 14, -15, 154, + 126, 15, -140, 150, -10, -207, -114, + 79, -63, -211, -70, -28, -217, 165, + 46, 38, -22, 281, 132, -62, 109, + 112, 54, -112, -93, 208, 27, 296, + 115, 10, -147, 41, 216, 42, -276, + 50, -115, -254, 167, 117, -2, 61, + 17, 144, 34, -72, -186, -150, 272, + -29, -66, -89, -95, -149, 129, 251, + 122, 0, -50, -234, -91, 36, 26, + -105, -102, -88, -121, -236, -7, -11, + -204, 109, 5, -191, 105, -15, 163, + -80, 32, -24, -209, 41, 294, 70, + -106, -94, -204, -118, 120, -50, -37, + -82, -241, 46, -131, -29, 150, -55, + 33, 155, 120, -89, -8, 7, 62, + 213, 82, 61, 18, -161, 144, 152, + 30, 131, 65, -87, -255, -17, -107, + -8, 85, -64, 51, -162, 223, -53, + -134, 261, 69, -56, 218, 72, -111, + 2, 155, -113, -87, 49, 85, -28, + -163, 42, -1, -196, 7, 39, -245, + 14, -137, -79, 11, -160, 202, -293, + -94, 33, 208, 100, 56, -44, 326, + -78, -41, 232, 13, -142, 227, 80, + -16, -87, 201, 33, -133, 15, -183, + -58, -192, -47, 184, -128, 133, 99, + -205, 11, -155, 78, 52, 72, 141, + -246, 26, 99, 151, 59, 115, -64, + -79, -47, -16, -14, 6, 47, -43, + -72, -178, -27, 162, 112, 43, -174, + -175, 238, 186, 71, -54, -188, -76, + -225, 233, 39, -39, -158, 122, 44, + -26, 43, 84, 130, -93, -51, 22, + 3, 92, -150, 136, -182, -57, 97, + -131, 179, -78, 80, 91, -165, 90, + -2, 148, 15, 130, 65, 175, 117, + -138, 114, -137, 132, 3, -10, -186, + 140, -4, -37, 254, -62, 92, -109 +}; + +/* ISF codebook for SID frames - 28b, 1st split */ +const Word16 dico1_ns_28b_fx[]= +{ + -269, -673, + -222, -537, + -233, -430, + -138, -451, + -212, -331, + -192, -241, + -87, -231, + -191, -128, + -70, -106, + -164, -6, + 74, -179, + 27, -33, + -102, 74, + -162, 115, + -94, 172, + -6, 130, + -143, 234, + 14, 218, + -65, 270, + 88, 182, + -124, 341, + -44, 381, + 38, 335, + 117, 274, + -112, 454, + 74, 431, + -5, 488, + 175, 384, + -83, 561, + 122, 529, + 21, 601, + 229, 481, + 231, 303, + 226, 608, + 300, 372, + 210, 187, + 306, 265, + 328, 473, + 382, 331, + 371, 132, + 139, 58, + 365, 21, + 250, -82, + 443, 218, + 483, 110, + 426, 415, + 579, 222, + 518, 333, + 573, 448, + 455, 529, + 685, 329, + 332, 580, + 595, 593, + 468, 645, + 762, 517, + 326, 709, + 485, 793, + 130, 684, + 671, 737, + 354, 876, + 88, 806, + -65, 706, + -35, 1016, + 266, 1123 +}; +/* ISF codebook for SID frames - 28b, 2nd spilt */ +const Word16 dico2_ns_28b_fx[]= +{ + -824, -884, -949, + -805, -456, -418, + -442, -438, -541, + -217, -578, -793, + -168, -444, -582, + -287, -492, -274, + -552, -297, -300, + -163, -333, -358, + -370, -232, -232, + -175, -358, -159, + -381, -21, -357, + -184, -159, -162, + -53, -191, -280, + 18, -267, -215, + -138, 61, -283, + 71, -95, -294, + 13, -156, -546, + 0, -83, -79, + 44, 97, -316, + 178, -52, -213, + 222, -261, -422, + 237, -118, -44, + 141, 145, -132, + 363, 81, -287, + 213, 65, 34, + -107, 94, -5, + 91, -29, 126, + -355, 51, -41, + -219, -76, 145, + -63, 100, 244, + -719, 44, 27, + -572, -124, 155, + -423, 133, 315, + -917, 71, 224, + -268, 318, 131, + -93, -190, 420, + -97, 122, 491, + -79, 317, 355, + 130, 100, 325, + 86, -293, 210, + 133, 258, 161, + 176, -73, 465, + 195, 300, 384, + 348, 22, 221, + 376, 183, 409, + 377, 286, 202, + 242, 213, 659, + 257, 565, 248, + 344, 408, -76, + 405, 440, 509, + 612, 385, 379, + 536, 607, 216, + -56, 582, 192, + 100, 517, 567, + -365, 448, 445, + 728, 347, 10, + 505, 357, 759, + 636, 582, 658, + 335, 517, 852, + 378, 809, 572, + -195, 878, 829, + 529, 707, 987, + 918, 726, 392, + 1250, 997, 1063 +}; + +/* ISF codebook for SID frames - 28b, 3rd spilt */ +const Word16 dico3_ns_28b_fx[]= +{ + -805, -838, -774, + -522, -627, -828, + -477, -486, -603, + -295, -481, -634, + -366, -384, -393, + -186, -414, -396, + -237, -394, -106, + -252, -202, -275, + -61, -177, -442, + -84, -198, -199, + -179, -125, -31, + -72, -47, -163, + -298, -220, 215, + -64, -168, 251, + -133, 156, -59, + -30, -2, 127, + 54, 66, -61, + -233, 21, 251, + 209, -50, 32, + 33, 194, 136, + -117, -18, 475, + 202, 46, 309, + 256, 185, 53, + 35, 200, 390, + 200, 263, 242, + -216, 302, 294, + 128, 358, 0, + 19, 431, 287, + 224, 447, 280, + 367, 165, 213, + 397, 314, 319, + 383, 379, 75, + 277, 325, 462, + 394, 505, 334, + 251, 98, -213, + 450, 153, 448, + 565, 226, 76, + 470, 383, 502, + 635, 390, 278, + 237, 135, 620, + 342, 401, 649, + 331, 551, 518, + 130, 418, 592, + 531, 306, 737, + 729, 389, 580, + 497, 557, 699, + 296, 383, 874, + 283, 624, 759, + 126, 622, 476, + 559, 595, 472, + 382, 770, 616, + 719, 613, 745, + 540, 639, 928, + 517, 826, 801, + 684, 811, 604, + 752, 786, 857, + 933, 661, 350, + 694, 450, 1061, + 562, 911, 1051, + 824, 813, 1104, + 758, 1047, 882, + 1140, 917, 889, + 1039, 1246, 1426, + 1483, 1666, 1876 +}; +/* ISF codebook for SID frames - 28b, 4th spilt */ +const Word16 dico4_ns_28b_fx[]= +{ + -776, -854, -891, -920, + -552, -610, -663, -741, + -321, -370, -476, -565, + 274, -160, -456, 201, + 265, 67, -160, -306, + -8, -210, 79, 272, + 163, 236, 307, 308, + 578, 317, 64, 298, + -9, 197, 342, 620, + 343, 232, 314, 622, + 173, 149, 548, 527, + 356, 370, 481, 376, + 135, 444, 488, 556, + 391, 471, 487, 653, + 228, 424, 576, 835, + 422, 372, 722, 682, + 295, 673, 693, 635, + 539, 596, 590, 449, + 475, 618, 659, 818, + 735, 517, 491, 673, + 602, 346, 257, 877, + 625, 635, 849, 720, + 727, 818, 698, 595, + 653, 481, 690, 1139, + 814, 762, 704, 908, + 507, 747, 898, 936, + 848, 855, 924, 785, + 646, 1037, 882, 795, + 772, 845, 1024, 1151, + 1133, 983, 818, 921, + 940, 1068, 1252, 1302, + 1588, 1767, 1718, 1513 +}; +/* ISF codebook for SID frames - 28b, 5th spilt */ +const Word16 dico5_ns_28b_fx[]= +{ + -810, -879, -945, -254, + 248, 184, 671, 128, + 288, 703, 918, 99, + 658, 558, 662, 219, + 552, 585, 910, 208, + 559, 804, 759, 119, + 606, 774, 921, -139, + 782, 761, 748, 208, + 756, 708, 983, 56, + 544, 864, 1010, 152, + 737, 698, 987, 299, + 771, 924, 879, 103, + 536, 785, 961, 405, + 667, 916, 801, 328, + 738, 705, 773, 439, + 823, 871, 992, 355, + 640, 1004, 1052, 369, + 724, 822, 949, 597, + 415, 655, 729, 482, + 1009, 896, 793, 363, + 908, 803, 687, -25, + 1016, 838, 1011, 189, + 947, 1112, 942, 222, + 914, 1049, 981, 527, + 956, 987, 1011, -120, + 781, 1049, 1121, 92, + 1178, 1053, 884, 47, + 1123, 1059, 1182, 118, + 933, 972, 1277, 357, + 1109, 918, 1101, 503, + 1039, 1286, 1220, 317, + 1351, 1207, 1010, 326 +}; + +/*----------------------------------------------------------------------------------* + * table of cos(x) in Q15 used in FFT for spectral analysis + *----------------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------------* + * Critical bands in Q0 + *------------------------------------------------------------------------------*/ + +const Word16 wind_sss_fx[LEN_WIN_SSS] = /*window for subsampling*/ +{ + 2621, 2627, 2645, 2675, 2717, 2771, 2836, 2914, + 3003, 3103, 3216, 3340, 3475, 3621, 3779, 3948, + 4127, 4318, 4519, 4730, 4952, 5184, 5426, 5677, + 5938, 6209, 6488, 6777, 7074, 7379, 7693, 8015, + 8344, 8681, 9025, 9375, 9733, 10097, 10466, 10842, + 11223, 11609, 12000, 12395, 12795, 13198, 13605, 14016, + 14429, 14845, 15263, 15683, 16105, 16527, 16951, 17376, + 17800, 18225, 18649, 19072, 19495, 19916, 20335, 20752, + 21166, 21578, 21987, 22392, 22794, 23191, 23585, 23973, + 24357, 24735, 25108, 25474, 25835, 26189, 26537, 26877, + 27210, 27536, 27853, 28163, 28464, 28757, 29041, 29316, + 29582, 29838, 30085, 30322, 30549, 30765, 30972, 31167, + 31352, 31526, 31690, 31842, 31983, 32112, 32230, 32337, + 32432, 32515, 32586, 32646, 32694, 32730, 32754, 32766, + 32767, 32096, 30111, 26894, 22575, 17333, 11380, 4962 +}; +/*----------------------------------------------------------------------------------* + * Low-pass FIR filter for low-frequency post-filtering @ 8kHz + * fir1(240,(3900/32000),hanning(241))*5 + *----------------------------------------------------------------------------------*/ + +const Word16 filter5_39s320_120_fx[121] = /* Q15 */ +{ + 19968, 19480, 18061, 15834, 12993, 9779, 6458, 3290, + 506, -1713, -3253, -4075, -4212, -3762, -2873, -1720, + -488, 654, 1568, 2160, 2389, 2263, 1838, 1201, + 460, -275, -903, -1348, -1566, -1546, -1312, -914, + -422, 90, 547, 891, 1083, 1108, 975, 716, + 376, 9, -331, -599, -762, -805, -732, -562, + -325, -61, 192, 399, 533, 582, 546, 435, + 272, 83, -103, -259, -366, -413, -398, -328, + -218, -86, 46, 161, 243, 283, 280, 238, + 166, 77, -14, -94, -153, -185, -188, -163, + -119, -62, -3, 50, 90, 113, 117, 104, + 78, 44, 9, -23, -47, -62, -65, -58, + -45, -27, -8, 9, 21, 28, 30, 27, + 20, 13, 5, -2, -7, -9, -9, -8, + -6, -3, -1, 0, 1, 1, 1, 0, + 0 + +}; + + +const Word16 Assym_window_W16fx[L_LP] = /*Q15*/ +{ + 2621, 2624, 2630, 2640, 2655, 2674, 2698, 2725, + 2757, 2792, 2833, 2877, 2925, 2978, 3034, 3095, + 3160, 3229, 3302, 3379, 3460, 3545, 3634, 3727, + 3824, 3925, 4029, 4138, 4250, 4366, 4486, 4609, + 4737, 4867, 5002, 5140, 5281, 5426, 5575, 5727, + 5882, 6040, 6202, 6367, 6535, 6707, 6881, 7059, + 7239, 7422, 7609, 7798, 7990, 8184, 8382, 8581, + 8784, 8989, 9196, 9406, 9618, 9832, 10049, 10268, + 10489, 10711, 10936, 11163, 11391, 11622, 11854, 12087, + 12322, 12559, 12797, 13037, 13278, 13520, 13763, 14007, + 14253, 14499, 14746, 14994, 15243, 15493, 15743, 15994, + 16245, 16496, 16748, 17000, 17253, 17505, 17758, 18010, + 18263, 18515, 18767, 19019, 19270, 19521, 19772, 20022, + 20271, 20519, 20767, 21014, 21260, 21504, 21748, 21991, + 22232, 22473, 22711, 22949, 23185, 23419, 23652, 23883, + 24113, 24340, 24566, 24790, 25012, 25231, 25449, 25664, + 25878, 26089, 26297, 26503, 26707, 26908, 27107, 27303, + 27496, 27687, 27874, 28059, 28241, 28420, 28596, 28769, + 28939, 29105, 29269, 29429, 29586, 29739, 29889, 30036, + 30179, 30319, 30455, 30588, 30717, 30842, 30964, 31082, + 31196, 31306, 31413, 31516, 31615, 31709, 31800, 31888, + 31971, 32050, 32125, 32196, 32263, 32325, 32384, 32439, + 32489, 32535, 32577, 32615, 32649, 32679, 32704, 32725, + 32742, 32755, 32763, 32767, 32767, 32758, 32741, 32715, + 32681, 32638, 32587, 32527, 32458, 32381, 32296, 32203, + 32101, 31991, 31873, 31746, 31612, 31470, 31320, 31162, + 30996, 30823, 30642, 30454, 30259, 30056, 29847, 29630, + 29407, 29177, 28940, 28697, 28448, 28193, 27931, 27664, + 27391, 27113, 26829, 26540, 26246, 25947, 25643, 25335, + 25022, 24706, 24385, 24060, 23732, 23401, 23066, 22728, + 22387, 22043, 21697, 21349, 20999, 20646, 20292, 19937, + 19580, 19223, 18864, 18505, 18145, 17785, 17425, 17065, + 16705, 16346, 15988, 15631, 15275, 14920, 14567, 14215, + 13866, 13519, 13174, 12832, 12492, 12156, 11823, 11493, + 11166, 10844, 10525, 10210, 9900, 9594, 9292, 8996, + 8704, 8418, 8137, 7861, 7591, 7327, 7068, 6816, + 6570, 6330, 6097, 5870, 5650, 5437, 5231, 5032, + 4840, 4656, 4479, 4310, 4148, 3994, 3848, 3709, + 3579, 3457, 3343, 3237, 3139, 3050, 2969, 2896, + 2832, 2776, 2729, 2690, 2660, 2639, 2626, 2621 +}; + +const Word16 assym_window_16k_fx[L_LP_16k] = /*Q15*/ +{ + 2621, 2623, 2627, 2634, 2643, 2655, 2670, 2688, + 2708, 2731, 2757, 2785, 2816, 2849, 2886, 2925, + 2966, 3011, 3058, 3107, 3159, 3214, 3271, 3331, + 3394, 3459, 3527, 3597, 3670, 3745, 3823, 3903, + 3985, 4071, 4158, 4248, 4341, 4436, 4533, 4632, + 4734, 4839, 4945, 5054, 5165, 5279, 5394, 5512, + 5632, 5754, 5879, 6005, 6134, 6264, 6397, 6531, + 6668, 6807, 6947, 7090, 7234, 7381, 7529, 7679, + 7831, 7984, 8140, 8297, 8455, 8616, 8778, 8941, + 9107, 9273, 9442, 9611, 9782, 9955, 10129, 10304, + 10481, 10659, 10838, 11019, 11200, 11383, 11567, 11752, + 11938, 12125, 12313, 12502, 12693, 12883, 13075, 13268, + 13461, 13655, 13850, 14046, 14242, 14439, 14637, 14835, + 15033, 15232, 15432, 15631, 15832, 16032, 16233, 16434, + 16635, 16837, 17039, 17240, 17442, 17644, 17846, 18048, + 18250, 18452, 18653, 18855, 19056, 19257, 19458, 19658, + 19858, 20058, 20257, 20456, 20654, 20852, 21049, 21245, + 21441, 21637, 21831, 22025, 22218, 22410, 22602, 22792, + 22982, 23170, 23358, 23545, 23730, 23915, 24098, 24280, + 24461, 24641, 24820, 24997, 25173, 25348, 25521, 25693, + 25863, 26032, 26200, 26366, 26530, 26693, 26854, 27014, + 27171, 27328, 27482, 27635, 27786, 27935, 28082, 28227, + 28371, 28513, 28652, 28790, 28926, 29059, 29191, 29320, + 29448, 29573, 29697, 29818, 29937, 30053, 30168, 30280, + 30390, 30498, 30603, 30706, 30807, 30905, 31002, 31095, + 31186, 31275, 31362, 31446, 31527, 31606, 31683, 31757, + 31828, 31897, 31963, 32027, 32088, 32147, 32203, 32257, + 32307, 32356, 32401, 32444, 32484, 32522, 32557, 32589, + 32619, 32646, 32670, 32692, 32711, 32727, 32741, 32751, + 32760, 32765, 32767, 32767, 32762, 32751, 32734, 32712, + 32685, 32652, 32614, 32570, 32521, 32466, 32406, 32341, + 32270, 32194, 32112, 32026, 31934, 31837, 31735, 31627, + 31515, 31398, 31275, 31148, 31016, 30878, 30737, 30590, + 30438, 30282, 30122, 29957, 29787, 29613, 29434, 29252, + 29065, 28874, 28679, 28480, 28277, 28070, 27859, 27644, + 27426, 27205, 26980, 26751, 26520, 26285, 26047, 25805, + 25561, 25314, 25065, 24812, 24557, 24300, 24040, 23777, + 23513, 23246, 22978, 22707, 22435, 22161, 21885, 21608, + 21329, 21049, 20768, 20485, 20202, 19918, 19632, 19347, + 19060, 18773, 18486, 18198, 17911, 17623, 17335, 17047, + 16760, 16473, 16186, 15900, 15614, 15330, 15046, 14763, + 14481, 14200, 13921, 13643, 13367, 13092, 12818, 12547, + 12277, 12010, 11744, 11481, 11220, 10961, 10705, 10451, + 10200, 9951, 9706, 9463, 9223, 8987, 8754, 8523, + 8297, 8073, 7854, 7637, 7425, 7216, 7011, 6810, + 6613, 6420, 6231, 6046, 5865, 5689, 5517, 5350, + 5187, 5028, 4875, 4726, 4581, 4442, 4307, 4177, + 4052, 3932, 3818, 3708, 3603, 3503, 3409, 3320, + 3236, 3157, 3084, 3016, 2953, 2895, 2844, 2797, + 2756, 2720, 2690, 2665, 2646, 2632, 2624, 2621 +}; +/*------------------------------------------------------------------------------* + * lag window for windowing the autocorrelations in LP analysis + * Used in lib_enc\analy_lp_fx.c + *------------------------------------------------------------------------------*/ +const Word16 Hamcos_Window[L_LP_AMR_WB] = +{ + 2621, 2622, 2626, 2632, 2640, 2650, 2662, 2677, + 2694, 2714, 2735, 2759, 2785, 2814, 2844, 2877, + 2912, 2949, 2989, 3031, 3075, 3121, 3169, 3220, + 3273, 3328, 3385, 3444, 3506, 3569, 3635, 3703, + 3773, 3845, 3919, 3996, 4074, 4155, 4237, 4321, + 4408, 4496, 4587, 4680, 4774, 4870, 4969, 5069, + 5171, 5275, 5381, 5489, 5599, 5710, 5824, 5939, + 6056, 6174, 6295, 6417, 6541, 6666, 6793, 6922, + 7052, 7185, 7318, 7453, 7590, 7728, 7868, 8009, + 8152, 8296, 8442, 8589, 8737, 8887, 9038, 9191, + 9344, 9499, 9655, 9813, 9971, 10131, 10292, 10454, + 10617, 10781, 10946, 11113, 11280, 11448, 11617, 11787, + 11958, 12130, 12303, 12476, 12650, 12825, 13001, 13178, + 13355, 13533, 13711, 13890, 14070, 14250, 14431, 14612, + 14793, 14975, 15158, 15341, 15524, 15708, 15891, 16076, + 16260, 16445, 16629, 16814, 16999, 17185, 17370, 17555, + 17740, 17926, 18111, 18296, 18481, 18666, 18851, 19036, + 19221, 19405, 19589, 19773, 19956, 20139, 20322, 20504, + 20686, 20867, 21048, 21229, 21408, 21588, 21767, 21945, + 22122, 22299, 22475, 22651, 22825, 22999, 23172, 23344, + 23516, 23686, 23856, 24025, 24192, 24359, 24525, 24689, + 24853, 25016, 25177, 25337, 25496, 25654, 25811, 25967, + 26121, 26274, 26426, 26576, 26725, 26873, 27019, 27164, + 27308, 27450, 27590, 27729, 27867, 28003, 28137, 28270, + 28401, 28531, 28659, 28785, 28910, 29033, 29154, 29274, + 29391, 29507, 29622, 29734, 29845, 29953, 30060, 30165, + 30268, 30370, 30469, 30566, 30662, 30755, 30847, 30936, + 31024, 31109, 31193, 31274, 31354, 31431, 31506, 31579, + 31651, 31719, 31786, 31851, 31914, 31974, 32032, 32088, + 32142, 32194, 32243, 32291, 32336, 32379, 32419, 32458, + 32494, 32528, 32560, 32589, 32617, 32642, 32664, 32685, + 32703, 32719, 32733, 32744, 32753, 32760, 32764, 32767, + 32767, 32765, 32757, 32745, 32727, 32705, 32678, 32646, + 32609, 32567, 32520, 32468, 32411, 32349, 32283, 32211, + 32135, 32054, 31968, 31877, 31781, 31681, 31575, 31465, + 31351, 31231, 31107, 30978, 30844, 30706, 30563, 30415, + 30263, 30106, 29945, 29779, 29609, 29434, 29255, 29071, + 28883, 28691, 28494, 28293, 28087, 27878, 27664, 27446, + 27224, 26997, 26767, 26533, 26294, 26052, 25806, 25555, + 25301, 25043, 24782, 24516, 24247, 23974, 23698, 23418, + 23134, 22847, 22557, 22263, 21965, 21665, 21361, 21054, + 20743, 20430, 20113, 19794, 19471, 19146, 18817, 18486, + 18152, 17815, 17476, 17134, 16789, 16442, 16092, 15740, + 15385, 15028, 14669, 14308, 13944, 13579, 13211, 12841, + 12470, 12096, 11721, 11344, 10965, 10584, 10202, 9819, + 9433, 9047, 8659, 8270, 7879, 7488, 7095, 6701, + 6306, 5910, 5514, 5116, 4718, 4319, 3919, 3519, + 3118, 2716, 2315, 1913, 1510, 1108, 705, 302 +}; +/*----------------------------------------------------------------------------------* + * AMR-WB IO WB BWE - deemphasis, values in Q15: + *----------------------------------------------------------------------------------*/ +const Word16 deem_tab_fx[56] = +{ + 20668, 20625, 20583, 20541, 20501, 20462, 20423, 20385, + 20348, 20313, 20277, 20243, 20210, 20177, 20146, 20115, + 20085, 20055, 20027, 19999, 19972, 19946, 19921, 19896, + 19873, 19850, 19827, 19806, 19785, 19766, 19746, 19728, + 19710, 19693, 19677, 19662, 19647, 19633, 19620, 19607, + 19596, 19585, 19574, 19565, 19556, 19548, 19540, 19533, + 19527, 19522, 19518, 19514, 19510, 19508, 19506, 19505 +}; + + +/*----------------------------------------------------------------------------------* + * AMR-WB IO WB BWE - HP filter in frequency domain, values in Q15: + *----------------------------------------------------------------------------------*/ +const Word16 filt_hp_fx[56] = +{ + 53, 153, 274, 415, 578, 765, 978, 1217, 1483, 1778, 2102, + 2457, 2843, 3261, 3710, 4192, 4706, 5252, 5829, 6438, 7077, + 7746, 8443, 9168, 9918, 10693, 11489, 12306, 13141, 13992, + 14856, 15732, 16615, 17504, 18395, 19287, 20174, 21056, 21928, + 22787, 23631, 24456, 25260, 26039, 26791, 27512, 28201, 28853, + 29468, 30043, 30574, 31061, 31502, 31894, 32237, 32529 +}; + +/*----------------------------------------------------------------------------------* + * AMR-WB IO WB BWE - gains for 23k85 mode, values in Q15: + *----------------------------------------------------------------------------------*/ +const Word16 HP_gain_fx[16] = +{ + 3624, 4673, 5597, 6479, 7425, 8378, 9324, 10264, + 11210, 12206, 13391, 14844, 16770, 19655, 24289, 32728 +}; + +/*----------------------------------------------------------------------------------* + * AMR-WB IO WB BWE - band-pass 6-8kHz FIR filter, values in Q15: + *----------------------------------------------------------------------------------*/ +const Word16 fir_6k_8k_fx[31] = +{ + 44, -155, 323, -482, 563, -590, 726, -1180, 1986, -2818, 3028, + -1991, -423, 3583, -6281, 7342, -6281, 3583, -423, -1991, 3028, + -2818, 1986, -1180, 726, -590, 563, -482, 323, -155, 44 +}; + +const Word16 exp_tab_q_fx[34] = /*Q14 */ +{ + 16384, -16068, 15137, -13622, + 11585, -9101, 6270, -3195, + 0, 3196, -6269, 9102, + -11584, 13623, -15136, 16069, + -16383, 0, -3195, 6270, + -9101, 11585, -13622, 15137, + -16068, 16384, -16068, 15137, + -13622, 11585, -9101, 6270, + -3195, 0 +}; + +const Word16 exp_tab_p_fx[34] = /*Q14 */ +{ + 16384, -11584, 0, 11585, + -16383, 11585, 0, -11584, + 16384, -11584, 0, 11585, + -16383, 11585, 0, -11584, + 16384, 0, -11584, 16384, + -11584, 0, 11585, -16383, + 11585, 0, -11584, 16384, + -11584, 0, 11585, -16383, + 11585, 0 +}; +const Word16 swb_bwe_trans_subband_width_fx[SWB_FENV_TRANS] = {76, 76, 84, 84}; +const Word16 sqrt_swb_bwe_trans_subband_width_fx[SWB_FENV_TRANS] = {17854, 17854, 18770, 18770};/*Q11 */ +const Word16 sqrt_swb_bwe_subband_fx_L1[SWB_FENV] = {16384, 20066, 16384, 20066, 16384, 20066, 16384, 20066, 20066, 20066, 20066, 20066, 23170, 23170}; /*Q12 */ +const Word16 sqrt_swb_bwe_subband_fx_L2[SWB_FENV/2] = {25905, 25905, 25905, 25905, 28378, 28378, 32767}; /*Q12 */ +const Word16 smooth_factor_fx[SWB_FENV-1] = {1638, 1638, 1638, 1638, 1638, 1638, 1638, 1366, 1366, 1366, 1366, 1024, 1024}; +const Word16 swb_bwe_sm_subband_fx[SWB_FENV] = {248, 268, 288, 308, 328, 348, 368, 388, 412, 436, 460, 484, 512, 544}; + +const Word16 swb_bwe_trans_subband_fx[SWB_FENV_TRANS+1] = {240, 316, 392, 476, 560}; +const Word16 swb_bwe_subband_fx[SWB_FENV+1] = {240, 256, 280, 296, 320, 336, 360, 376, 400, 424, 448, 472, 496, 528, 560}; +const Word16 F_2_5_fx[64] = /*Q10 */ +{ + 1189, 675, -5106, -5293, 10476, -12, 10860, 10026, + -382, -616, 6426, 339, 9681, 9068, 3002, 2216, + 3208, 3042, 8255, -604, 16133, 5171, 17641, 18769, + -2529, -3248, -1447, -1991, 15511, 14855, 11631, 11996, + 9654, -124, 7267, -1617, 12799, 3237, 10598, 1555, + 5510, -1775, 1149, -2292, 12659, 12425, 4382, -1814, + 6305, 5629, 3404, -2632, 19555, 9582, 7835, 7619, + -517, -3795, 19031, 11574, 19156, 18748, 23563, 23465, +}; + +const Word16 swb_inv_bwe_subband_width_fx[SWB_FENV] = {2048,1365,2048,1365,2048,1365,2048,1365,1365,1365,1365,1365,1024,1024}; + +const Word16 EnvCdbk11_fx [N_CB11 * DIM11] = /*Q8 */ +{ + -2220, 29, 1168, 2124, 2180, 1208, 741, + 1521, -312, -843, -1523, -1970, -2205, -2541, + 746, 1835, 3461, 4398, 4292, 4184, 3462, + 1627, 2475, 2937, 2839, 2198, 1729, 1325, + -514, -731, -557, -200, 100, 475, 540, + 655, 956, 1272, 1083, 774, 687, 459, + 5987, 5460, 4689, 4192, 3845, 3615, 3393, + 3571, 4840, 5784, 6266, 5933, 5158, 4433, + 2959, 2087, 1180, 979, 1180, 1371, 1636, + 6029, 6157, 6431, 6762, 6998, 7153, 7050, + -822, 210, 450, 178, -639, -1346, -1577, + 4451, 4184, 4111, 4329, 4833, 5232, 5512, + 3420, 3994, 4321, 4205, 3684, 3154, 2651, + -3734, -2305, -1388, -324, 22, -847, -1141, + 850, 510, 896, 1780, 2130, 2688, 2826, + 3294, 2823, 2510, 2516, 3029, 3413, 3843, + -3563, -3409, -3199, -2917, -2584, -2282, -1981, + -2738, -3185, -3752, -4320, -4484, -4524, -4329, + -7534, -7481, -7283, -7175, -6757, -6281, -5865, + -4868, -4836, -4603, -4422, -4086, -3738, -3323, + -13896, -13775, -13484, -13339, -12926, -12399, -11970, + 8409, 8420, 8305, 8103, 7954, 7778, 7496, + 7180, 6845, 6369, 5971, 5557, 5309, 5027, + 4633, 4008, 3267, 2422, 2072, 1778, 1510, + 10128, 10432, 10540, 10473, 10176, 9837, 9586, + 2933, 2695, 2060, 1286, 424, -254, -825, + -10032, -9847, -9544, -9420, -9000, -8508, -8084, + 1830, 927, -158, -388, -360, -368, -287, + -21962, -21904, -21548, -21471, -21004, -20511, -20064, + -6090, -6142, -5937, -5852, -5493, -5104, -4671, + -1382, -1640, -2205, -2557, -2785, -3019, -2994, + -1300, -1567, -1744, -1642, -1409, -1080, -902, +}; + +const Word16 EnvCdbk1st_fx [N_CB1ST * DIM1ST] = /*Q8 */ +{ + -1819, -1138, 751, + -494, 162, -826, + -3199, -123, 2479, + -2071, 238, -429, + -1819, 1780, 1233, + 284, 1187, -1123, + -1689, -722, -484, + -1256, 52, -1336, + -604, 3738, -1297, + 555, 412, 743, + -626, -1685, 1527, + 145, 1557, -224, + -638, 1370, 1589, + -1188, 37, -410, + -428, -3320, 1860, + 2597, -95, -2876, + -742, -583, -684, + 1607, -1671, -1874, + -1111, -936, -1374, + 275, -2314, 518, + 2682, 2368, -302, + 1809, -555, -579, + 3193, -1270, -1208, + 750, 84, 154, + -1160, 429, 1098, + 816, -613, -2897, + 2159, -1885, 1245, + -671, 426, 3177, + 867, -144, -639, + 843, -1888, 2271, + 1542, 259, -148, + -1680, 1027, 285, + 162, -763, 1666, + -1916, 1175, -1227, + -345, -907, -151, + 1979, 1062, 402, + -1231, 2437, 3130, + -2422, 361, 1040, + -4314, -4106, -4221, + 146, -1200, -1828, + 485, 889, -3847, + 384, -2461, -2845, + 1526, -600, 1599, + -838, -571, 1097, + 1776, -3393, 4058, + -3330, 2429, 1732, + 468, -2140, -934, + 833, 2292, -1129, + -20, -1029, 652, + -346, 168, 1834, + -1730, 838, 2234, + 1622, -1695, -194, + -3198, -773, 228, + 1070, 1741, 285, + 1655, -212, -1628, + 2178, 604, 1784, + 1801, -3224, -848, + -819, 348, 187, + 16, 300, 244, + 769, 201, 1554, + 719, -394, 780, + 311, 2853, 185, + 1163, 489, -1022, + -330, 459, 877, + 109, -541, -691, + -509, -267, 478, + -340, -417, -1403, + -860, -675, -2703, + 1025, 826, 250, + -1043, 1008, -434, + -1042, -631, 60, + -173, 332, -2084, + 984, 919, -2042, + -1257, -2287, 339, + 366, -1309, -158, + 1041, 1039, 1083, + 3566, 918, 227, + 62, -139, 936, + 2424, 730, -1022, + -745, 1954, 427, + -1091, -1358, -478, + -173, 2121, -2367, + -2175, 2535, -1946, + -880, -1964, -1549, + -249, -1203, -927, + -2377, -443, -1775, + -1439, -582, 2037, + -529, -3679, -550, + 608, -284, -1566, + 201, 63, -344, + 1376, 218, 816, + 2471, -348, 479, + -1388, 988, -2674, + 1429, -3538, 1125, + 864, -1351, 845, + 301, 977, 408, + -1122, 3364, 1107, + -213, 730, -329, + 839, -683, -92, + 631, 1172, 2364, + 598, 685, -329, + -780, -1317, 448, + -424, -153, -199, + 768, -331, 2825, + 882, -1047, -975, + -375, -1835, -299, + 2861, -3375, -3158, + 2099, 2168, -2630, + 1602, 1930, 1451, + 1294, 1265, -586, + -2500, -2570, -2667, + -806, -1529, 3272, + -522, 1072, 478, + 4035, -2491, 480, + -1908, 2414, -178, + -1563, -143, 438, + 205, 861, 1287, + -691, 963, -1374, + -2359, -2032, -886, + 162, -442, 160, + 194, 2494, 1960, + -2533, -2578, 1924, + 267, 1701, 937, + 2919, 2950, 2382, + -670, 2102, -859, + -3147, 1385, -215, + 1482, -595, 415, + 228, 290, -1060, +}; + +const Word16 EnvCdbk2nd_fx [N_CB2ND * DIM2ND] = /*Q8 */ +{ + 1104, -1833, -1110, -954, + 757, 853, -176, 286, + -873, -587, -7, 1458, + -462, -553, -350, 104, + 1938, 1957, -1340, -703, + 1202, -779, 21, 1996, + -2851, -169, 1049, 940, + -1355, -726, -1788, 1076, + -767, -641, -646, -880, + 135, -832, -197, -889, + -826, 3, 279, -502, + -714, 544, -526, 375, + 291, -1076, -816, -3929, + -1175, -475, 2219, -642, + 197, -219, -1052, -1601, + 1175, -162, -695, -336, + 1124, 126, -2326, -1573, + 1164, -1323, -1958, 1074, + -2080, -2152, 113, 649, + -637, -860, 721, 267, + -609, 1658, -1006, -1352, + 1631, 2225, 2128, 1827, + -1112, -1351, 1856, 1656, + -2132, 1006, 770, -1294, + -472, 776, 1661, 2248, + -121, -574, -1481, -316, + 2565, -1081, 188, 293, + 398, 2598, 704, -1129, + 1023, 104, 550, 499, + -416, 127, 253, -1894, + 456, -2578, 190, 1018, + -1488, 286, -1202, -915, + -1164, 1874, 1651, 302, + -1312, -1547, -1625, -1516, + 170, -233, 817, 1209, + -1090, 341, 709, 725, + 854, 819, -278, -1083, + -15, 113, 286, 283, + 1166, -906, 1880, 301, + 342, -7, -587, 776, + -785, -1259, -1166, 3194, + -1630, -1071, 300, -1080, + -12, 190, -538, -493, + 351, 907, 1929, -1534, + 480, 36, 593, -526, + 813, 1216, 986, 89, + 98, 1010, -2272, 268, + 2766, -102, -1307, -873, + -1660, -467, -365, 47, + 1496, 1277, -228, -2791, + 1565, -669, 520, -1598, + -361, 1078, 457, -364, + 543, -950, 28, 248, + 1904, 815, -1034, 1125, + -13, -1951, 1085, -1005, + -2223, 1519, -624, 857, + 1121, 831, 872, 1295, + 193, 2284, -422, 609, + -156, 827, -733, 2065, + -3390, -3384, -3197, -3220, + 31, 896, 539, 978, + -21, 408, 1502, 405, + -583, -1662, -665, -164, + 2193, 976, 613, -436, +}; + +const Word16 EnvCdbk3rd_fx [N_CB3RD * DIM3RD] = /*Q8 */ +{ + 1031, -2454, 748, + 2770, 2442, 1761, + -2348, 4079, -959, + 1874, -735, -2242, + -59, 35, 201, + -1518, 162, 1809, + -1977, -1063, -103, + 2485, 1212, -863, + 882, 192, 39, + 1356, 851, 979, + -1377, -2961, -1477, + 497, -808, 593, + -394, -748, -1564, + -950, -198, -436, + -503, -1420, -234, + 318, 985, -1905, + -118, 1783, 1563, + 220, 929, 400, + 857, 37, -995, + -807, 1943, -409, + -743, -524, 552, + 940, 1643, -299, + 805, -1421, -768, + -2330, 705, 156, + 61, 203, 1213, + -138, 517, -642, + 64, -501, -435, + 2194, -625, 157, + -1600, 341, -1611, + 1137, -351, 2353, + -811, -1715, 1522, + -870, 613, 446, +}; + +const Word16 EnvCdbk4th_fx [N_CB4TH * DIM4TH] = /*Q8 */ +{ + 1024, -210, -207, 591, + -280, -2486, -951, 958, + 1539, 1136, 411, 1314, + 1761, -202, 1339, 203, + -2438, -2109, -2028, -2125, + 1849, -1408, -670, 144, + -469, 2674, -1589, -3604, + 1642, -702, 139, 2476, + -483, 372, -861, 540, + -119, 827, 863, 952, + 23, 99, -24, -303, + 488, -2233, -1432, -1399, + 54, -43, 96, -1527, + 1170, 133, -119, -717, + 258, -1215, -439, 160, + -1049, 793, 970, -770, + -1914, -1245, 1281, 422, + -1194, 1005, 176, -2368, + -1631, 1316, -1125, -361, + 1124, 1132, 61, -2186, + 790, -2055, 1174, 938, + 2974, 3874, 2315, 2040, + -300, 2484, 59, -860, + 543, 1307, -1868, -725, + 389, -115, -945, -146, + -1837, -578, -620, 975, + 389, 1779, 1732, 296, + 377, 897, 1555, 2269, + -854, 26, 590, 1413, + -780, -985, 1389, 2639, + 312, -277, -935, -3289, + 1740, 1852, 641, -519, + 738, 898, -466, 115, + 1187, -286, -1514, -1309, + 74, -801, -583, -987, + 510, -667, 430, -191, + 418, -303, 806, 1258, + -1083, -1065, 362, -2114, + -1075, 82, 260, 286, + -2579, 14, 75, -854, + -661, -634, 482, -581, + -338, -306, 3255, 388, + -230, -24, 1161, 205, + 256, 546, -141, 1379, + -63, -775, -484, 1478, + -517, -546, -451, 86, + 1473, -1201, 430, -1892, + 394, 831, 620, -664, + 334, 64, 1773, -1576, + -1783, 1270, 1020, 944, + 1023, 98, -1908, 1330, + -560, -1044, 380, 707, + -427, -708, -1815, -90, + -54, 2298, -537, 1151, + -499, 703, -1018, 3322, + 92, 717, -607, -1032, + -1313, -1393, -580, -485, + 34, -2192, 788, -860, + 2641, 628, -776, -259, + -702, -159, -1483, -1638, + -33, -63, 97, 553, + 692, 523, 548, 349, + -913, 54, -456, -702, + -341, 944, 157, 100, +}; + +const Word16 w_NOR_fx[SWB_FENV] = /*Q15 */ +{ + 32767, 32056, 31374, 30720, 30093, 29491, 28913, + 28357, 27822, 27307, 26810, 26331, 25869, 25423, +}; + +const Word16 Mean_env_fx[SWB_FENV] = /*Q8 */ +{ + 7327, 7414, 7181, 7160, 6889, 6866, 6746, + 6651, 6385, 6152, 5873, 5668, 5435, 5222, +}; + +const Word16 Env_TR_Cdbk1_fx [N_CB_TR1 * DIM_TR1] = /*Q8 */ +{ + 229, -2347, + 8199, 7726, + -312, 1700, + 9881, 5949, + 8942, 8358, + 3865, 3287, + 2405, 796, + 3664, 1433, + 3059, 2215, + 618, 874, + -5479, -4636, + 2237, 2512, + 4265, 2428, + 6583, 2065, + 4548, 6579, + 11325, 7340, + 10578, 9264, + 8491, 6457, + -1380, -2484, + 3377, 5069, + 7393, 5120, + 4798, 4440, + 5506, 7614, + -3371, -3982, + 2806, 2959, + 2242, 3550, + 1334, 3065, + 2055, -1350, + 815, 5507, + 4940, 1457, + -1950, -1046, + 653, -1133, + 872, -3622, + -1756, 245, + 5792, 5542, + 4084, 7696, + 4569, 5204, + -810, -1555, + 10127, 10384, + 11341, 11713, + 6365, 4996, + 8641, 10527, + 5914, 3366, + 4522, 3266, + 5217, 2830, + 8107, 8980, + 3952, 5858, + 5848, 8990, + 6424, 5931, + 5185, 3823, + 6367, 6917, + 3548, 2683, + 1634, 2098, + 2729, -89, + 6964, 7664, + 3179, 3561, + 6388, 4193, + 4024, 4828, + -378, 434, + 9338, 9507, + 7593, 3483, + -6835, -6317, + 5207, 5029, + 11326, 10488, + 7411, 6086, + 10072, 8255, + -6099, -5652, + 7074, 8702, + -12228, -11384, + -11471, -10567, + -13025, -12253, + -12879, -11289, + -13952, -13062, + -16214, -15389, + -11659, -10789, + -12351, -11477, + -12789, -11947, + -15139, -14249, + -11326, -11219, + -11950, -11093, + -11800, -10928, + -23738, -22881, + 12795, 11890, + -3793, -2879, + -27373, -26492, + -11928, -11531, + -12110, -11258, + -20492, -19634, + -14371, -13608, + -12591, -11728, + -14055, -11739, + 9471, 7272, + -11184, -10335, + -13313, -11673, + -12209, -10610, + -13465, -12761, + 7690, 7115, + 2564, 4496, + 5587, 4551, + -813, -562, + -4483, -5521, + 1556, 98, + 2, 3468, + 1410, 1339, + 4049, 161, + -4538, -4026, + -9866, -9115, + -1616, -4727, + 2457, 1653, + 631, 2155, + -17982, -17082, + 2628, 6088, + -10791, -9933, + -12426, -11566, + 4322, 4000, + -1574, 2162, + -7968, -7599, + 1523, 4192, + 5621, 6537, + -2511, -1987, + 12471, 9218, + 8746, 4971, + 3642, 4148, + 5089, 5948, + 350, -92, + 7028, 6683, + -2430, -3216, + -3974, -886, +}; + +const Word16 Env_TR_Cdbk2_fx [N_CB_TR2 * DIM_TR2] = /*Q8 */ +{ + 2639, 375, + -481, 1694, + -2400, -3306, + 86, -4018, + -1301, 47, + 734, 299, + 957, -1039, + 2204, 1486, + 361, -1136, + 2628, -838, + -2010, 1296, + 373, 127, + -573, 2604, + 689, -1554, + 1676, -371, + 1298, 279, + -901, 1086, + 1747, -2723, + 214, -657, + -731, -909, + 1545, -1658, + -369, -2208, + -1276, 1748, + 1141, -522, + 186, -1893, + -1260, -2016, + -478, -504, + 1287, 1882, + -97, -1400, + -1372, -1165, + 800, -152, + 413, -240, + -208, -858, + -90, -399, + 492, 2519, + 913, 1368, + -344, 282, + 305, 526, + -251, 860, + -1066, 567, + -2800, -687, + 1, 674, + 176, 878, + -716, -153, + 706, 831, + -1083, -424, + 419, 1192, + -132, 565, + 708, -2406, + 600, -661, + 1712, 2969, + -1974, 379, + -672, 208, + 26, 296, + -1821, -501, + -513, 635, + 266, 1737, + -221, 1232, + -3498, 1632, + -337, -66, + -552, -1427, + 1329, 850, + -718, -2948, + -3, 0, +}; + +const Word16 Mean_env_tr_fx[5]= {6971, 6095, 6111, 4995}; /*Q8 */ + + +const Word16 EnvCdbkFB_fx [N_CB_FB * DIM_FB] = /*Q7 */ +{ + -2126, -1242, -945, + 1628, -686, -539, + 1230, 2245, 2532, + 2822, 3094, 2669, + -12376, -11507, -11342, + 2678, 3533, 3510, + 489, 903, 689, + 1930, 2929, 3025, + 3424, 4179, 4050, + -2500, -1707, -1415, + -3511, -2563, -2224, + -865, -987, -1212, + -424, 891, 1919, + 1976, 2520, 2277, + 673, 1667, 1945, + 5169, 6024, 5983, + -1367, -501, -236, + -254, 679, 989, + -18974, -18088, -17834, + -23007, -22053, -22109, + 2262, 2301, -625, + -124, 431, 372, + 1454, 1962, 1791, + 200, 1094, 1347, + -997, -110, 213, + -697, 267, 602, + -3066, -2172, -1876, + -4358, -3493, -3164, + -360, 59, -472, + -1813, -919, -601, + 4204, 4967, 4913, + 953, 1457, 1245 +}; + +const Word16 Mean_env_fb_fx[DIM_FB] = {1760, 805, 473}; /*Q8 */ + + +/*-------------------------------------------------------------------* + * Pulse indexing tables for ACELP innovation coding + *-------------------------------------------------------------------*/ + +const Word32 PI_select_table_fx[23][8] = +{ + {1, 0, 0, 0, 0, 0, 0, 0}, + {1, 1, 0, 0, 0, 0, 0, 0}, + {1, 2, 1, 0, 0, 0, 0, 0}, + {1, 3, 3, 1, 0, 0, 0, 0}, + {1, 4, 6, 4, 1, 0, 0, 0}, + {1, 5, 10, 10, 5, 1, 0, 0}, + {1, 6, 15, 20, 15, 6, 1, 0}, + {1, 7, 21, 35, 35, 21, 7, 1}, + {1, 8, 28, 56, 70, 56, 28, 8}, + {1, 9, 36, 84, 126, 126, 84, 36}, + {1, 10, 45, 120, 210, 252, 210, 120}, + {1, 11, 55, 165, 330, 462, 462, 330}, + {1, 12, 66, 220, 495, 792, 924, 792}, + {1, 13, 78, 286, 715, 1287, 1716, 1716}, + {1, 14, 91, 364, 1001, 2002, 3003, 3432}, + {1, 15, 105, 455, 1365, 3003, 5005, 6435}, + {1, 16, 120, 560, 1820, 4368, 8008, 11440}, + {1, 17, 136, 680, 2380, 6188, 12376, 19448}, + {1, 18, 153, 816, 3060, 8568, 18564, 31824}, + {1, 19, 171, 969, 3876, 11628, 27132, 50388}, + {1, 20, 190, 1140, 4845, 15504, 38760, 77520}, + {1, 21, 210, 1330, 5985, 20349, 54264, 116280}, + {1, 22, 231, 1540, 7315, 26334, 74613, 1705444} +}; + +const Word32 PI_offset_fx[8][8] = +{ + /* for 0p(0). */ + {0x00000,0x00000,0x00000,0x00000,0x00000,0x00000,0x00000,0x00000}, + /* for 1p(1). */ + {0x00000,0x00000,0x00000,0x00000,0x00000,0x00000,0x00000,0x00000}, + /* for 2p(2,1). */ + {0x00000,0x00000,0x00000,0x00000,0x00000,0x00000,0x00000,0x00000}, + /* for 3p(3,2,1). */ + {0x00000,0x00000,0x01180,0x01540,0x00000,0x00000,0x00000,0x00000}, + /* for 4p(4,3,2,1). */ + {0x00000,0x00000,0x071C0,0x0A640,0x0ABE0,0x00000,0x00000,0x00000}, + /* for 5p(5,4,3,2,1). */ + {0x00000,0x00000,0x22200,0x3E900,0x45200,0x45980,0x00000,0x00000}, + /* for 6p(6,5,4,3,2,1). */ + {0x00000,0x00000,0x07d200,0x127c00,0x16ed80,0x179c80,0x17a5e0,0x00000}, + /* for 7p(7,6,5,4,3,2,1). */ + {0x00000,0x00000,0x165800,0x454400,0x654200,0x6E2500,0x6F2B80,0x6F36C0} +}; + +const Word16 PI_factor_fx[7] = {0,0,120,560,1820,4368,8008}; + +/*------------------------------------------------------------------------------* + * AVQ - RE8 tables + *------------------------------------------------------------------------------*/ + +const Word16 select_table22_fx[5][9] = +{ + {1, 1, 1, 1, 1, 1, 1, 1, 1}, + {0, 1, 2, 3, 4, 5, 6, 7, 8}, + {0, 0, 1, 3, 6, 10, 15, 21, 28}, + {0, 0, 0, 1, 4, 10, 20, 35, 56}, + {0, 0, 0, 0, 1, 5, 15, 35, 70} +}; + +/* value of leader element */ +const Word16 vals_a_fx[36][4] = +{ + {1}, {0,2}, {0,2}, {1,3}, {0,4}, {2,0}, {1,3}, {0,2,4}, + {2}, {1,3}, {2,0,4}, {0,4}, {1,5}, {1,3}, {2,0,4}, {0,2,4}, + {1,3,5}, {0,2,6}, {0,4}, {0,2,6}, {0,2,4,6}, {1,7}, {0,8}, {0,6}, + {0,2,8}, {0,4,8}, {1,9}, {0,2,10}, {0,8}, {0,6,10}, {0,12}, {0,4,12}, + {0,10}, {0,2,14}, {0,8,12}, {0,16} +}; + +/* code parameter for every leader */ +const Word16 vals_q_fx[36][4] = +{ + {7,1}, {2,2,2}, {4,2,4}, {7,2,1}, {1,2,1}, {6,2,2}, {7,2,2}, {3,3,3,1}, + {8,1}, {7,2,3}, {5,3,4,1}, {2,2,2}, {7,2,1}, {7,2,4}, {7,3,2,1}, {4,3,4,2}, + {7,3,2,1}, {2,3,2,1}, {3,2,3}, {4,3,4,1}, {3,4,3,2}, {7,2,1}, {1,2,1}, {2,2,2}, + {3,3,3,1}, {2,3,2,1}, {7,2,1}, {2,3,2,1}, {2,2,2}, {2,3,2,1}, {1,2,1}, {2,3,2,1}, + {2,2,2}, {2,3,2,1}, {2,3,2,1}, {1,2,1} +}; + +/* codebook start address for every leader */ +const UWord16 Is_fx[36] = +{ + 0, 128, 256, 1376, 240, 0, 1792, 2400, 5376, 5632, 12800, 3744, + 21760, 22784, 31744, 38912, 45632, 3856, 52800, 53248, 57728, 60416, 4080, 61440, + 61552, 62896, 63120, 64144, 64368, 64480, 64704, 64720, 64944, 65056, 65280, 65504 +}; + +/* A3 - Number of the absolute leaders in codebook Q3 */ +const Word16 A3_fx[NB_LDQ3] = +{ + 0, 1, 4, 2, 3, 7, 11, 17, 22 +}; + +/* A4 - Number of the absolute leaders in codebook Q4 */ +const Word16 A4_fx[NB_LDQ4] = +{ + 5, 6, 8, 9, 10, 12, 13, 14, 15, + 16, 18, 19, 20, 21, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35 +}; + +/* I3 - Cardinality offsets for absolute leaders in Q3 */ +const UWord16 I3_fx[NB_LDQ3] = +{ + 0, 128, 240, 256, 1376, 2400, 3744, 3856, 4080 +}; + +/* I4 - Cardinality offset for absolute leaders in Q4 */ +const UWord16 I4_fx[NB_LDQ4] = +{ + 0, 1792, 5376, 5632, 12800, 21760, 22784, 31744, 38912, + 45632, 52800, 53248, 57728, 60416, 61440, 61552, 62896, 63120, + 64144, 64368, 64480, 64704, 64720, 64944, 65056, 65280, 65504 +}; + +/* Da_pos - Position of the first absolute leader on a spherical shell (or sphere) */ +const Word16 Da_pos_fx[NB_SPHERE] = +{ + 0, 2, 5, 8, 13, 18, 20, 22, 23, 25, 26, 27, 27, 28, 28, 28, + 29, 30, 31, 31, 32, 32, 32, 32, 32, 34, 35, 35, 35, 35, 35, 35 +}; + +/* Da_nb - Number of absolute leaders on a spherical shell */ +const Word16 Da_nb_fx[NB_SPHERE] = +{ + 2, 3, 3, 5, 5, 2, 2, 1, 2, 1, 1, 0, 1, 0, 0, 1, + 1, 1, 0, 1, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 1 +}; + +/* Da_id - identification code of an absolute leader */ +const Word16 Da_id_fx[NB_LEADER] = +{ + 0x0001, 0x0004, 0x0008, 0x000B, 0x0020, 0x000C, 0x0015, 0x0024, + 0x0010, 0x001F, 0x0028, 0x0040, 0x004F, 0x0029, 0x002C, 0x0044, + 0x0059, 0x00A4, 0x0060, 0x00A8, 0x00C4, 0x012D, 0x0200, 0x0144, + 0x0204, 0x0220, 0x0335, 0x04E4, 0x0400, 0x0584, 0x0A20, 0x0A40, + 0x09C4, 0x12C4, 0x0C20, 0x2000 +}; + +/* Da_nq - Codebook number for each absolute leader */ +const Word16 Da_nq_fx[NB_LEADER+2] = +{ + 2, 2, 3, 3, 2, 4, 4, 3, 4, 4, 4, 3, 4, 4, 4, 4, + 4, 3, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 0, 100 +}; + + +/*------------------------------------------------------------------------------* + * LP muisc post-filter + *------------------------------------------------------------------------------*/ + +const Word16 post_dct_wind_fx[OFFSET2] = /*Q15 */ +{ + 32767, 32766, 32759, 32748, 32733, 32713, 32689, 32660, + 32627, 32590, 32548, 32502, 32452, 32397, 32338, 32274, + 32207, 32135, 32059, 31979, 31894, 31805, 31712, 31615, + 31514, 31409, 31300, 31187, 31070, 30949, 30823, 30695, + 30562, 30425, 30285, 30141, 29993, 29841, 29686, 29527, + 29365, 29200, 29030, 28858, 28682, 28503, 28320, 28134, + 27945, 27753, 27558, 27360, 27159, 26955, 26749, 26539, + 26327, 26112, 25894, 25674, 25452, 25226, 24999, 24769, + 24537, 24303, 24067, 23828, 23588, 23345, 23101, 22855, + 22607, 22358, 22107, 21854, 21600, 21345, 21088, 20830, + 20570, 20310, 20049, 19786, 19523, 19258, 18993, 18728, + 18461, 18195, 17927, 17659, 17391, 17123, 16854, 16586, + 16317, 16048, 15779, 15511, 15243, 14975, 14707, 14440, + 14173, 13907, 13642, 13377, 13114, 12851, 12589, 12328, + 12068, 11809, 11552, 11296, 11041, 10787, 10536, 10285, + 10037, 9790, 9545, 9301, 9060, 8820, 8583, 8348, + 8115, 7884, 7655, 7429, 7205, 6983, 6765, 6548, + 6335, 6124, 5916, 5710, 5508, 5308, 5112, 4918, + 4728, 4540, 4356, 4175, 3998, 3824, 3653, 3485, + 3321, 3161, 3004, 2851, 2701, 2555, 2413, 2274, + 2139, 2009, 1882, 1758, 1639, 1524, 1413, 1306, + 1203, 1104, 1009, 918, 831, 749, 671, 597, + 527, 461, 400, 343, 291, 242, 199, 159, + 124, 93, 67, 45, 27, 14, 5, 1 +}; + +const Word16 mfreq_loc_LD_fx[] = { 100, 200, 300, 400, 510, 630, 770, 920, 1080, 1270, 1480, + 1720, 2000, 2320, 2700, 3150, 3700, 4400, 5300, (6400-BIN_16kdct_fx) + }; + +const Word16 inv_mfreq_bindiv_LD_fx[] = {3277, 3277, 3277, 3277, 2979, 2731, 2341, 2185, 2048, 1725, 1560, 1365, 1170, 1024, 862, 728, 596, 468, 364, 298}; /*Q15 */ + +const Word16 inv_mfreq_bindiv_LD_M1_fx[] = {3641, 3641, 3641, 3641, 3277, 2979, 2521, 2341, 2185, 1820, 1638, 1425, 1214, 1057, 886, 745, 607, 475, 368, 301}; /*Q15 */ + +const Word16 sc_qnoise_fx[] = {3277, 3277, 3277, 3277, 3277, 3277, 2979, 2979, 2979, 2979, 2979, 2979, 2979, 2979, 2979, 2185, 2185, 2185, 2185, 2185}; + +const Word16 MAX_SNR_SNR1_tab_FX[MBANDS_GN_LD] = { 16815, 16815, 16815, 16815, 16815, 16815, 16815, 16815, 16815, 16815, 16815, 16815, 16815, 16815, 16815, 16815, 17096, 17096, 17096, 17096}; + +const Word16 INV_MAX_SNR_tab_FX[MBANDS_GN_LD] = { 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 862, 1425, 1425, 1425, 1425}; + +/*const Word16 inv_mfreq_bindiv_LD1_fx[] = {13107, 13107, 13107, 13107, 11916, 10923, 9362, 8738, 8192, 6899, 6242, 5461, 4681, 4096, 3449, 2913, 2383, 1872, 1456, 1192}; //Q17 */ + +/*------------------------------------------------------------------------------* + * Highrate SWB BWE tables + *------------------------------------------------------------------------------*/ + +const Word16 overlap_coefs_48kHz_fx[NSV_OVERLAP*WIDTH_BAND] = /* in Q15 */ +{ + 9830, 11141, 11796, 12780, 13763, 14418, 15073, 15565, 16056, 16712, 17695, 18678, 20316, 23593, 27197, 31130 +}; + +const Word16 overlap_coefs_fx[NSV_OVERLAP*WIDTH_BAND] = /* in Q15 */ +{ + 8847, 10027, 10617, 11502, 12386, 12976, 13566, 14008, 14451, 15041, 15925, 16810, 18285, 21234, 24478, 28017 +}; + +const Word16 swb_hr_env_code1_fx[NUM_ENVLOPE_CODE_HR1*2] = /* in Q9 */ +{ + 23, 21, 268, 240, 344, 310, 504, 438, + 629, 580, 856, 734, 1305, 1209, 1637, 1693, + 1321, 2671, 2154, 3709, 1801, 890, 2243, 1410, + 2436, 2404, 3496, 3127, 2279, 5187, 3715, 6394, + 3435, 1000, 3381, 1894, 5434, 1299, 4806, 2171, + 3645, 4240, 4640, 3628, 4567, 4999, 5785, 6023, + 6032, 3010, 7194, 4949, 5735, 4609, 7391, 6777, + 7341, 1999, 10276, 2220, 9270, 4210, 11444, 4917, + 3708, 8481, 6030, 9814, 5694, 7913, 7457, 8888, + 9124, 6090, 8943, 7832, 10925, 6889, 10519, 8768, + 4637, 11437, 5754, 14762, 6791, 12873, 8317, 14468, + 7818, 11028, 8696, 12646, 10031, 11617, 10315, 13255, + 9112, 9960, 10901, 10336, 12338, 9772, 12090, 11543, + 12125, 8360, 13766, 9934, 13317, 8004, 14817, 8315, + 12848, 6332, 14189, 6791, 14505, 5289, 15684, 6580, + 12940, 3143, 14948, 3698, 16472, 2570, 16373, 4851 +}; + +const Word16 swb_hr_env_code2_fx[NUM_ENVLOPE_CODE_HR2*2] = /* in Q9 */ +{ + 262, 242, 686, 568, 1303, 901, 1600, 1559, + 2505, 1905, 2053, 2944, 2617, 1108, 3414, 1993, + 4329, 1409, 5695, 1801, 3391, 3052, 4384, 2562, + 4567, 3985, 5509, 3051, 6374, 4280, 7003, 5750, + 7000, 2794, 8434, 2006, 10706, 3294, 13034, 4412, + 8402, 3878, 9510, 5269, 11309, 6406, 10839, 8811, + 2701, 4927, 4656, 5773, 6116, 7956, 8474, 7704, + 3255, 8984, 6818, 11144, 3915, 13367, 1255, 16350 +}; + +const Word16 swb_hr_env_code3_fx[NUM_ENVLOPE_CODE_HR_TR*N_BANDS_TRANS_BWE_HR] = /* in Q9 */ +{ + 409, 347, 898, 622, 1457, 1033, 2242, 1012, + 3039, 1508, 2017, 2161, 4137, 1348, 3881, 2553, + 2538, 5306, 3962, 4430, 4730, 3610, 5225, 2877, + 5450, 2240, 5970, 1779, 5553, 1364, 6003, 838 +}; + + +const Word16 Ip_fft256_fx[10] = {128, 1, 0, 256, 128, 384, 64, 320,192, 448}; + +const Word16 Ip_fft512_fx[18] = {256, 1, 0, 512, 256, 768, 128, 640,384, 896, 64, 576, 320, 832, 192, 704,448, 960}; +const Word16 w_fft512_fx[256] = +{ + 16384, 0, 11585, 11585, 15137, 6270, 6270, 15137, + 16069, 3196, 9102, 13623, 13623, 9102, 3196, 16069, + 16305, 1606, 10394, 12665, 14449, 7723, 4756, 15679, + 15679, 4756, 7723, 14449, 12665, 10394, 1606, 16305, + 16364, 804, 11003, 12140, 14811, 7005, 5520, 15426, + 15893, 3981, 8423, 14053, 13160, 9760, 2404, 16207, + 16207, 2404, 9760, 13160, 14053, 8423, 3981, 15893, + 15426, 5520, 7005, 14811, 12140, 11003, 804, 16364, + 16379, 402, 11297, 11866, 14978, 6639, 5897, 15286, + 15986, 3590, 8765, 13842, 13395, 9434, 2801, 16143, + 16261, 2006, 10080, 12916, 14256, 8076, 4370, 15791, + 15557, 5139, 7366, 14635, 12406, 10702, 1205, 16340, + 16340, 1205, 10702, 12406, 14635, 7366, 5139, 15557, + 15791, 4370, 8076, 14256, 12916, 10080, 2006, 16261, + 16143, 2801, 9434, 13395, 13842, 8765, 3590, 15986, + 15286, 5897, 6639, 14978, 11866, 11297, 402, 16379, + 16383, 201, 11442, 11727, 15059, 6455, 6084, 15213, + 16029, 3393, 8935, 13733, 13510, 9269, 2999, 16107, + 16284, 1806, 10238, 12792, 14354, 7900, 4563, 15736, + 15619, 4948, 7545, 14543, 12537, 10549, 1406, 16324, + 16353, 1005, 10853, 12274, 14724, 7186, 5330, 15493, + 15843, 4176, 8250, 14155, 13039, 9921, 2205, 16235, + 16176, 2603, 9598, 13279, 13949, 8595, 3786, 15941, + 15357, 5708, 6823, 14896, 12004, 11151, 603, 16373, + 16373, 603, 11151, 12004, 14896, 6823, 5708, 15357, + 15941, 3786, 8595, 13949, 13279, 9598, 2603, 16176, + 16235, 2205, 9921, 13039, 14155, 8250, 4176, 15843, + 15493, 5330, 7186, 14724, 12274, 10853, 1005, 16353, + 16324, 1406, 10549, 12537, 14543, 7545, 4948, 15619, + 15736, 4563, 7900, 14354, 12792, 10238, 1806, 16284, + 16107, 2999, 9269, 13510, 13733, 8935, 3393, 16029, + 15213, 6084, 6455, 15059, 11727, 11442, 201, 16383 +}; +const Word16 sinq_16k[3*L_FRAME16k/20] = +{ + 536, 1608, 2678, 3745, 4808, 5866, 6918, 7962, + 8998, 10024, 11039, 12043, 13033, 14010, 14972, 15917, + 16846, 17757, 18648, 19520, 20371, 21199, 22006, 22788, + 23546, 24279, 24986, 25667, 26319, 26944, 27540, 28106, + 28642, 29147, 29622, 30064, 30475, 30852, 31197, 31508, + 31786, 32029, 32238, 32413, 32553, 32658, 32728, 32763 +}; +const Word16 sinq_32k[3*L_FRAME32k/20] = +{ + 268, 804, 1340, 1876, 2411, 2945, 3479, 4011, 4543, 5073, 5602, 6130, + 6655, 7180, 7702, 8222, 8740, 9255, 9768, 10279, 10786, 11291, 11793, 12292, + 12787, 13279, 13767, 14252, 14733, 15210, 15683, 16151, 16616, 17075, 17531, 17981, + 18427, 18868, 19304, 19734, 20160, 20580, 20994, 21403, 21806, 22203, 22595, 22980, + 23359, 23732, 24098, 24459, 24812, 25159, 25499, 25832, 26159, 26478, 26790, 27095, + 27393, 27684, 27967, 28243, 28511, 28771, 29024, 29269, 29506, 29735, 29956, 30170, + 30375, 30572, 30761, 30941, 31114, 31278, 31433, 31580, 31719, 31849, 31971, 32084, + 32189, 32285, 32372, 32451, 32521, 32582, 32634, 32678, 32713, 32740, 32757, 32766 +}; + +const Word16 sinq_48k[3*L_FRAME48k/20] = +{ + 179, 536, 893, 1251, 1608, 1965, 2321, 2678, 3034, 3390, 3745, 4100, + 4454, 4808, 5161, 5514, 5866, 6217, 6568, 6918, 7267, 7615, 7962, 8308, + 8654, 8998, 9341, 9683, 10024, 10364, 10702, 11039, 11375, 11710, 12043, 12375, + 12705, 13033, 13361, 13686, 14010, 14332, 14653, 14972, 15289, 15604, 15918, 16229, + 16539, 16846, 17152, 17455, 17757, 18056, 18353, 18648, 18941, 19232, 19520, 19806, + 20090, 20371, 20650, 20926, 21200, 21471, 21740, 22006, 22269, 22530, 22789, 23044, + 23297, 23547, 23794, 24038, 24280, 24519, 24754, 24987, 25217, 25444, 25667, 25888, + 26106, 26320, 26531, 26740, 26945, 27147, 27345, 27541, 27733, 27921, 28107, 28289, + 28468, 28643, 28815, 28984, 29149, 29310, 29468, 29623, 29774, 29922, 30066, 30206, + 30343, 30476, 30606, 30732, 30854, 30973, 31087, 31199, 31306, 31410, 31510, 31606, + 31699, 31788, 31873, 31954, 32031, 32105, 32175, 32241, 32303, 32361, 32415, 32466, + 32513, 32556, 32595, 32630, 32661, 32688, 32712, 32731, 32747, 32759, 32766, 32767 +}; +const Word16 Asr_LP16_fx[21] = +{ + /*Q15 */ + 0, 110, 0, -428, 0, 1153, 0, -2832, + 0, 10199, 16384, 10199, 0, -2832, 0, 1153, + 0, -428, 0, 110, 0 +}; + +const Word16 Asr_LP32_fx[41] = +{ + /*Q15 */ + 0, 24, 55, 58, 0, -113, -214, -198, + 0, 323, 576, 510, 0, -795, -1416, -1280, + 0, 2337, 5099, 7334, 8192, 7334, 5099, 2337, + 0, -1280, -1416, -795, 0, 510, 576, 323, + 0, -198, -214, -113, 0, 58, 55, 24, + 0 +}; + +const Word16 Asr_LP48_fx[61] = +{ + /*Q17 */ + 0, 38, 93, 146, 167, 123, 0, -192, + -408, -571, -592, -407, 0, 564, 1143, 1537, + 1546, 1035, 0, -1391, -2801, -3776, -3843, -2635, + 0, 3919, 8679, 13599, 17887, 20809, 21845, 20809, + 17887, 13599, 8679, 3919, 0, -2635, -3843, -3776, + -2801, -1391, 0, 1035, 1546, 1537, 1143, 564, + 0, -407, -592, -571, -408, -192, 0, 123, + 167, 146, 93, 38, 0 +}; +const Word16 short_window_48kHz_fx[L_FRAME48k/2/2] = /* second half is symetric and omitted */ +{ + 107, 322, 536, 751, 965, 1179, 1394, 1608, 1822, 2036, 2250, 2464, 2678, 2892, 3105, 3319, + 3532, 3745, 3958, 4171, 4383, 4596, 4808, 5020, 5232, 5444, 5655, 5866, 6077, 6288, 6498, 6708, + 6918, 7127, 7336, 7545, 7754, 7962, 8170, 8377, 8585, 8791, 8998, 9204, 9409, 9615, 9819, 10024, + 10228, 10431, 10634, 10837, 11039, 11241, 11442, 11643, 11843, 12043, 12242, 12441, 12639, 12836, 13033, 13230, + 13426, 13621, 13816, 14010, 14204, 14397, 14589, 14781, 14972, 15162, 15352, 15541, 15730, 15917, 16105, 16291, + 16477, 16662, 16846, 17030, 17213, 17395, 17576, 17757, 17937, 18116, 18294, 18472, 18648, 18824, 18999, 19174, + 19347, 19520, 19692, 19863, 20033, 20202, 20371, 20538, 20705, 20871, 21035, 21199, 21363, 21525, 21686, 21846, + 22006, 22164, 22322, 22478, 22634, 22788, 22942, 23095, 23246, 23397, 23546, 23695, 23843, 23989, 24135, 24279, + 24423, 24565, 24707, 24847, 24986, 25125, 25262, 25398, 25533, 25667, 25800, 25931, 26062, 26191, 26320, 26447, + 26573, 26698, 26821, 26944, 27066, 27186, 27305, 27423, 27540, 27655, 27770, 27883, 27995, 28106, 28216, 28324, + 28431, 28537, 28642, 28746, 28848, 28949, 29049, 29148, 29245, 29341, 29436, 29530, 29622, 29713, 29803, 29891, + 29979, 30064, 30149, 30232, 30315, 30395, 30475, 30553, 30630, 30705, 30780, 30853, 30924, 30994, 31063, 31131, + 31197, 31262, 31326, 31388, 31449, 31508, 31567, 31624, 31679, 31733, 31786, 31837, 31887, 31936, 31984, 32029, + 32074, 32117, 32159, 32200, 32239, 32276, 32313, 32348, 32381, 32413, 32444, 32473, 32501, 32528, 32553, 32577, + 32600, 32621, 32640, 32658, 32675, 32691, 32705, 32717, 32729, 32738, 32747, 32754, 32759, 32764, 32766, 32767, +}; +const Word16 short_window_32kHz_fx[L_FRAME32k/2/2] = /* second half is symetric and omitted */ +{ + 161, 483, 804, 1126, 1447, 1768, 2090, 2411, 2731, 3052, 3372, 3692, 4011, 4330, 4649, 4967, + 5285, 5602, 5919, 6235, 6550, 6865, 7180, 7493, 7806, 8118, 8429, 8740, 9049, 9358, 9666, 9973, + 10279, 10584, 10888, 11191, 11492, 11793, 12093, 12391, 12688, 12984, 13279, 13572, 13865, 14155, 14445, 14733, + 15019, 15305, 15588, 15871, 16151, 16430, 16708, 16984, 17258, 17531, 17802, 18071, 18338, 18604, 18868, 19130, + 19390, 19649, 19905, 20160, 20413, 20663, 20912, 21159, 21403, 21646, 21886, 22125, 22361, 22595, 22827, 23056, + 23284, 23509, 23732, 23953, 24171, 24387, 24601, 24812, 25021, 25228, 25432, 25633, 25833, 26029, 26223, 26415, + 26604, 26791, 26975, 27156, 27335, 27511, 27684, 27855, 28023, 28188, 28351, 28511, 28668, 28823, 28974, 29123, + 29269, 29412, 29553, 29690, 29825, 29957, 30086, 30212, 30335, 30455, 30572, 30687, 30798, 30906, 31012, 31114, + 31214, 31310, 31403, 31494, 31581, 31665, 31747, 31825, 31900, 31972, 32041, 32107, 32169, 32229, 32286, 32339, + 32389, 32437, 32481, 32522, 32559, 32594, 32626, 32654, 32679, 32701, 32720, 32736, 32749, 32758, 32764, 32767, +}; + +const Word16 short_window_16kHz_fx[L_FRAME16k/2/2] = /* second half is symetric and omitted */ +{ + 322, 965, 1608, 2250, 2892, 3532, 4171, 4808, 5444, 6077, 6708, 7336, 7962, 8585, 9204, 9819, + 10431, 11039, 11643, 12242, 12836, 13426, 14010, 14589, 15162, 15730, 16291, 16846, 17395, 17937, 18472, 18999, + 19520, 20033, 20538, 21035, 21525, 22006, 22478, 22942, 23397, 23843, 24279, 24707, 25125, 25533, 25931, 26320, + 26698, 27066, 27423, 27770, 28106, 28431, 28746, 29049, 29341, 29622, 29891, 30149, 30395, 30630, 30853, 31063, + 31262, 31449, 31624, 31786, 31936, 32074, 32200, 32313, 32413, 32501, 32577, 32640, 32691, 32729, 32754, 32766, +}; + +const Word16 short_window_8kHz_fx[L_FRAME8k/2/2] = /* second half is symetric and omitted */ +{ + 643, 1929, 3212, 4490, 5760, 7022, 8274, 9512, + 10736, 11943, 13132, 14300, 15447, 16569, 17666, 18736, + 19777, 20788, 21766, 22711, 23621, 24494, 25330, 26127, + 26883, 27598, 28270, 28899, 29483, 30022, 30514, 30959, + 31357, 31706, 32007, 32258, 32459, 32610, 32711, 32762, +}; + +const Word16 Hilbert_coeffs_fx[4*NUM_HILBERTS][HILBERT_ORDER1+1] = /* Q14 */ +{ + { 0, 14320, 0, -30699, 0, 16384}, /* num_Real[0] */ + {11897, 0, -28240, 0, 16384, 0}, /* num_Imag[0] */ + {16384, 0, -30699, 0, 14320, 0}, /* den_Real[0] */ + {16384, 0, -28240, 0, 11897, 0}, /* den_Imag[0] */ + {7671, 0, -23855, 0, 16384, 0}, /* num_Real[1] */ + { 2505, 0, -18139, 0, 16384, 0}, /* num_Imag[1] */ + {16384, 0, -23855, 0, 7671, 0}, /* den_Imag[1] */ + {16384, 0, -18139, 0, 2505, 0}, /* den_Imag[1] */ +}; + + +const Word16 win_flatten_4k_fx[L_FRAME16k/8] = /*Q15 */ +{ + 13, 114, 315, 615, 1013, 1505, 2089, 2761, + 3517, 4353, 5263, 6241, 7282, 8378, 9525, 10713, + 11937, 13188, 14458, 15741, 17027, 18310, 19580, 20831, + 22055, 23243, 24390, 25486, 26527, 27505, 28415, 29251, + 30007, 30679, 31263, 31755, 32153, 32453, 32654, 32755 +}; + +const Word16 gaus_dico_swb_fx[256] = +{ + /*Q15 */ + 709, 11759, -5333, -2701, 2397, -18, -4286, 2368, + -4576, -1584, -900, -940, 3676, 5441, -44, 2234, + -5698, 3082, -2671, 1666, -640, -3343, -1005, -1689, + 2048, 281, -3935, -3723, 5628, 385, -746, -3243, + -3332, -7228, -1748, -206, -5474, 2554, 2861, 3168, + 5039, 588, -508, -8167, 6549, -3433, 2187, -3666, + -5874, 2767, 8370, 1038, 6434, 6279, 625, 4030, + -1031, 1823, 9896, -1395, 2712, -1110, -742, 6142, + -4456, -10487, -144, -5104, 1968, -312, 6176, 2173, + 2334, -240, 2712, 7460, 2219, -3116, -56, 2770, + 5577, -1225, 770, 3557, 2246, 2322, 3077, 41, + 992, -4971, 441, -5039, 4913, 3811, 1142, -1283, + -6578, 4171, -1473, -3793, -5008, 1984, -1138, -1185, + 5646, 1014, -5118, 7141, 2656, -7241, -3538, 2337, + 7239, -504, -943, -10129, 702, -3811, -302, 2435, + 5090, 3744, 2335, -3904, -1401, -1662, -7256, 6484, + -6864, -5428, 1954, -7316, -1420, -1542, 5442, 311, + 3698, -1343, -2974, 8756, 324, -1903, 2580, 2635, + 4236, -1851, 3147, -772, -708, -3830, 2601, -1889, + -3444, -762, 3939, 3206, -7406, -837, -1167, -438, + 3707, -1015, -7472, 1849, 4277, 1459, -3047, -3760, + 740, -7134, -3753, -3092, 209, -12121, 1398, 2266, + 2505, -7974, -1121, -3481, -5644, 1329, 4532, 958, + 5311, -4258, -3195, -1769, -3055, 4399, -15, 10182, + 4503, 1912, -1574, 5054, -3163, 4881, -5364, 1925, + -1205, -6432, 2305, -8917, -1422, 514, -3001, 3928, + 2321, 360, -355, 1477, -3492, -4570, 1913, 2772, + -1380, -5161, 3812, 2614, 2204, -3135, 1244, -3066, + -4446, -6389, 4899, -5250, 1372, 1999, 1122, 5312, + 1310, -1189, -3310, 6403, 3818, 7734, 1620, -8533, + 706, 7498, -4472, 1272, -949, 3203, -4427, -2855, + 4419, 2283, 6410, 2584, -3397, -3382, -2976, -48, +}; + + +const Word16 win_flatten_fx[L_FRAME16k/2] = /*Q15 */ +{ + 3, 13, 28, 50, 78, 113, 154, 200, 254, 313, + 378, 450, 528, 611, 701, 797, 899, 1006, 1120, 1239, + 1365, 1496, 1632, 1775, 1923, 2076, 2235, 2400, 2569, 2745, + 2925, 3110, 3301, 3496, 3697, 3902, 4112, 4327, 4546, 4770, + 4999, 5232, 5469, 5710, 5955, 6205, 6458, 6715, 6976, 7240, + 7508, 7779, 8054, 8331, 8612, 8896, 9183, 9472, 9764, 10059, + 10356, 10655, 10956, 11260, 11566, 11873, 12182, 12493, 12805, 13119, + 13434, 13750, 14067, 14385, 14703, 15023, 15342, 15663, 15983, 16304, + 16625, 16945, 17265, 17586, 17905, 18224, 18542, 18860, 19176, 19492, + 19806, 20119, 20431, 20741, 21049, 21355, 21660, 21963, 22263, 22561, + 22857, 23150, 23441, 23729, 24014, 24297, 24576, 24852, 25125, 25395, + 25661, 25923, 26182, 26437, 26689, 26936, 27179, 27418, 27653, 27884, + 28110, 28332, 28549, 28761, 28969, 29172, 29370, 29563, 29751, 29934, + 30112, 30284, 30451, 30613, 30769, 30920, 31065, 31205, 31338, 31467, + 31589, 31705, 31816, 31921, 32020, 32113, 32199, 32280, 32355, 32423, + 32486, 32542, 32592, 32636, 32673, 32704, 32730, 32748, 32761, 32767 +}; +const Word16 AP1_STEEP_FX[ALLPASSSECTIONS_STEEP] = {1985, 14072, 26500}; /*Q15 Format */ +const Word16 AP2_STEEP_FX[ALLPASSSECTIONS_STEEP] = {7230, 20838, 30852}; /*Q15 Format */ + +const Word16 cos_fb_exc_fx[32] = /* Q15 */ +{ + /*Q35*/ + 32767, 32138, 30274, 27246, 23170, 18205, 12540, 6393, + 0, -6393, -12540, -18205, -23170, -27246, -30274, -32138, + -32768, -32138, -30274, -27246, -23170, -18205, -12540, -6393, + 0, 6393, 12540, 18205, 23170, 27246, 30274, 32138, +}; + + +const Word16 subwin_wb_fx[SHB_OVERLAP_LEN/2+1]= +{0, 5126, 10126, 14876, 19261, 23170, 26510, 29197, 31164, 32365, 32767 }; + +const Word16 window_wb_fx[L_SHB_LAHEAD/4]=/*sin, 1 */ +{ 7502, 18518, 27034, 31898, 32767}; /*Q15*/ + +const Word16 window_shb_fx[L_SHB_LAHEAD]= /*sin, 1, sin */ +{ + /*Q15(round) */ + 1513, 4527, 7502, 10413, 13236, 15945, 18518, 20934, 23170, 25210, + 27034, 28627, 29976, 31069, 31898, 32454, 32733, 32767, 32767, 32767, +}; + +const Word16 window_shb_32k_fx[2*L_SHB_LAHEAD] = +{ + /*Q15(round) */ + 1513, 3020, 4527, 6015, 7502, 8958, 10413, 11825, 13236, 14590, + 15945, 17232, 18518, 19726, 20934, 22052, 23170, 24190, 25210, 26122, + 27034, 27830, 28627, 29301, 29976, 30523, 31069, 31483, 31898, 32176, + 32454, 32593, 32733, 32751, 32767, 32767, 32767, 32767, 32767, 32767, +}; + +const Word16 subwin_shb_fx[SHB_OVERLAP_LEN+1]= +{ + /*Q15(round) */ + 0, 202, 802, 1786, 3129, + 4799, 6754, 8946, 11321, 13821, + 16384,18947, 21447, 23822, 26014, + 27969, 29639, 30982, 31966, 32566, + 32767 +}; + +/*----------------------------------------------------------------------------------* + * FEC for HQ core + *----------------------------------------------------------------------------------*/ + +const short Num_bands_NB[MAX_SB_NB] = {8,8,2}; + + +const Word16 hvq_cb_search_overlap24k[17] = +{ + 0, 8, 17, 27, + 39, 53, 69, 89, + 113, 128, 128, 128, + 128, 128, 128, 128, + 128 +}; + +const Word16 hvq_cb_search_overlap32k[21] = +{ + 0, 6, 13, 21, + 30, 40, 51, 64, + 78, 96, 116, 128, + 128, 128, 128, 128, + 128, 128, 128, 128, + 128 +}; + + +const Word16 hvq_pg_huff_offset[NUM_PG_HUFFLEN] = {0,2,3,8,9,11,13,15,19}; +const Word16 hvq_pg_huff_thres[NUM_PG_HUFFLEN] = {0,0x2,0x4,0x18,0x20,0x40,0x80,0x100,0x300}; + +const Word16 hvq_pg_huff_tab[32] = +{ + 30, 31, 1, 0, 2, 3, 28, 29, 4, 5, 27, 25, 26, 6, 24, 7, 8, 22, 23, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21 +}; + +const Word16 hvq_cp_huff_len[52] = +{ + 3, 4, 5, 6, 6, 6, 6, 6, 4, 4, 5, 5, 5, 5, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 8, + 8, 8, 8, 8, 9, 10, 10, 11, 11, 11, 10, 10, 10, 10, 11, 12, 12, 13, 13, 12, 12, 11, 12 +}; + +const Word16 hvq_cp_huff_val[52] = +{ + 7, 8, 6, 3, 4, 5, 6, 7, 9, 10, 7, 8, 9, 10, 11, 12, 13, 11, 12, 13, 14, 15, 8, 9, 10, + 11, 4, 5, 3, 4, 5, 6, 7, 5, 4, 5, 3, 4, 5, 6, 7, 8, 9, 6, 1, 2, 0, 1, 3, 4, 7, 5 +}; + +const Word16 hvq_cp_layer1_map5[HVQ_CP_MAP_LEN] = { 16, 8, 4, 2, 1, 18, 17, 9 }; + +const Word16 hvq_cp_huff_thres[HVQ_CP_HUFF_NUM_LEN] = { 0x0, 0x2, 0xC, 0x20, 0x50, 0x60, 0x100, 0x180, 0x600, 0x1000, 0x1C00 }; +const Word16 hvq_cp_huff_offset[HVQ_CP_HUFF_NUM_LEN] = { 0, 2, 7, 12, 18, 19, 24, 26, 35, 45, 51 }; + +const Word16 hvq_cp_huff_tab[52] = +{ + 46, 47, 44, 45, 48, 49, 51, 36, 37, 38, 43, 50, 34, 35, 39, 40, 41, 42, 33, 28, 29, 30, 31, 32, 26, 27, + 3, 4, 5, 6, 7, 22, 23, 24, 25, 2, 10, 11, 12, 13, 17, 18, 19, 20, 21, 1, 8, 9, 14, 15, 16, 0 +}; + + + + +const Word16 * const lsf_q_cb_fx[NUM_Q_LSF] = { lsf_q_cb_4b_fx, lsf_q_cb_4b_fx, lsf_q_cb_3b_fx, lsf_q_cb_3b_fx, lsf_q_cb_3b_fx }; +const Word16 lsf_q_cb_size_fx[NUM_Q_LSF] = {16, 16, 8, 8, 8}; +const Word16 grid_smoothing_fx[5] = { 6554, 11469, 16384, 24576, 26214 }; +const Word16 mirror_point_q_cb_fx[MIRROR_POINT_Q_CB_SIZE] = { 471, 692, 896, 1216}; + +const Word16 lbr_wb_bwe_lsfvq_cbook_2bit_fx[4*4] = +{ + /*Q15 */ + 3876, 5920, 8951, 11884, + 6556, 7979, 10835, 13133, + 4401, 6781, 10676, 13493, + 8453, 9693, 12024, 13921, +}; + +const Word32 SHBCB_FrameGain16_fx[16]= +{ + /*Q18*/ + 38968, 125277, 254474, 493383, 1043711, 2083177, 3792746, 6395076, + 10256080, 15738899, 23269902, 34118236, 48362464, 71128080, 107459896, 192888864 +}; +const Word16 full_band_bpf_1_fx[6][5] = /*in Q13*/ +{ + { 789, 802, 248, 802, 789}, + { 789, 1199, 838, 1199, 789}, + { 789, 136, -1123, 136, 789}, + { 8192, 19654, 24391, 17059, 6561}, + { 8192, 15339, 20118, 13819, 6190}, + { 8192, 21155, 26558, 17237, 5599} +}; + +/* 12th order elliptic Bandpass filter at 16.3 to 19.8 kHz sampled at 48 kHz b0,b1,b2,a0,a1,a2 */ +const Word16 full_band_bpf_2_fx[6][5] = /*in Q13*/ +{ + { 492, 912, 974, 912, 492}, + { 492, 1161, 1353, 1161, 492}, + { 492, 259, -311, 259, 492}, + { 8192, 22912, 30622, 21214, 7143}, + { 8192, 20364, 27329, 18844, 6886}, + { 8192, 23496, 31199, 20826, 6487} +}; + +/* 12th order elliptic Bandpass filter at 15.4 to 20.0 kHz sampled at 48 kHz b0,b1,b2,a0,a1,a2 */ +const Word16 full_band_bpf_3_fx[6][5] = /*in Q13*/ +{ + {611, 888, 717, 888, 611}, + {611, 1211, 1214, 1211, 611}, + {611, 197, -671, 197, 611}, + {8192, 21727, 28230, 19588, 6871}, + {8192, 18438, 24377, 16796, 6567}, + {8192, 22683, 29442, 19400, 6081} +}; + +const Word16 SHBCB_SubGain5bit_fx[128] = +{ + /*Q14 */ + -2388, -7806, -6576, -6024, + -7066, -5430, -4998, -3495, + -16722, -15343, -960, -7940, + -26291, -5921, -4917, -4378, + -1526, -6621, -8475, -9624, + -8047, -4086, -8940, -3043, + -3630, -5129, -4964, -7381, + -270, -18662, -24233, -25418, + -9246, -7551, -5584, -2053, + -2091, -4622, -9199, -14628, + -4645, -2197, -10255, -9697, + -2438, -9386, -11737, -4570, + -14366, -11436, -8252, -819, + -16192, -16332, -17043, -225, + -5407, -8588, -7577, -2296, + -26309, -21930, -7522, -2514, + -3260, -4246, -7947, -6614, + -1820, -5520, -15272, -19764, + -3706, -3737, -5850, -10520, + -10081, -4050, -4065, -5001, + -3908, -9909, -2881, -9604, + -520, -11156, -12620, -12768, + -4539, -5149, -6208, -4462, + -4866, -7672, -4235, -4407, + -9163, -13411, -2975, -3915, + -12267, -7568, -3842, -2827, + -7181, -4914, -2608, -9392, + -6275, -2868, -5962, -6511, + -12962, -1034, -8517, -10992, + -8247, -7608, -2502, -5026, + -5812, -4998, -3860, -5778, + -16907, -5974, -4434, -3276, +}; + + +/* 5-bit TD WB BWE temporal shaping codebook */ + +const Word16 HBCB_SubGain5bit_fx[128] = +{ + -15224, -17789, -9897, -5048, -456, -1232, -2238, -2782, + -3391, -3864, -4026, -4045, -2017, -1311, -878, -1973, + -12837, -15376, -8273, -4141, -2791, -3037, -2403, -342, + -3388, -3646, -3471, -2829, -157, -2025, -2318, -2243, + -14652, -16433, -7699, -1188, -2567, -1755, -346, -1682, + -2068, -2321, -2344, -2348, -1759, -1038, -1865, -2041, + -11396, -13719, -7749, -2734, -809, -1935, -1886, -781, + -2136, -1940, -942, -1571, -1926, -2378, -2572, -2145, + -17531, -19267, -7721, -2672, -714, -675, -1516, -2071, + -1925, -2325, -2523, -2657, -1644, -1674, -2036, -2017, + -12781, -14601, -6714, -1380, -2093, -1704, -1124, -756, + -2776, -2687, -2066, -1202, -1102, -680, -1956, -2376, + -14436, -15846, -4918, -2071, -1613, -744, -1807, -1381, + -620, -1294, -2026, -2162, -794, -1755, -1167, -1762, + -11627, -13377, -5876, -1959, -1009, -1879, -1027, -1915, + -1734, -1265, -2001, -1018, -698, -1733, -2172, -1195, + +}; + +const Word32 SHBCB_FrameGain64_fx[64]= +{ + /* Q18 */ + 11553, 19429, 27466, 35948, 45184, 54817, 65050, 76114, + 88089, 100815, 114314, 128727, 144236, 160812, 178639, 197656, + 217917, 239688, 263098, 288617, 315962, 345380, 376751, 410569, + 446867, 485779, 527885, 574220, 624562, 679333, 738912, 803391, + 873329, 949299, 1032054, 1121728, 1219559, 1327347, 1446046, 1576547, + 1720983, 1881933, 2062979, 2266614, 2496129, 2759206, 3060575, 3409584, + 3818114, 4295643, 4868000, 5551295, 6368310, 7329048, 8475924, 9889403, + 11649918, 13794493, 16487623, 19979932, 24732260, 31339886, 41958624, 64261100, +}; + +const Word16 lsf_grid_fx[4][5] = +{ + { 5242, 10229, 15516, 21804, 27540, }, + { 5117, 10059, 14949, 20478, 25493, }, + { 4648, 8732, 13022, 18247, 24474, }, + { 5052, 8925, 12903, 19427, 28382, } +}; + +const Word16 ola_win_shb_switch_fold_fx[L_SUBFR16k] = +{ + 322, 965, 1608, 2250, 2892, 3532, 4171, 4808, + 5444, 6077, 6708, 7336, 7962, 8585, 9204, 9819, + 10431, 11039, 11643, 12242, 12836, 13426, 14010, 14589, + 15162, 15730, 16291, 16846, 17395, 17937, 18472, 18999, + 19520, 20033, 20538, 21035, 21525, 22006, 22478, 22942, + 23397, 23843, 24279, 24707, 25125, 25533, 25931, 26320, + 26698, 27066, 27423, 27770, 28106, 28431, 28746, 29049, + 29341, 29622, 29891, 30149, 30395, 30630, 30853, 31063, + 31262, 31449, 31624, 31786, 31936, 32074, 32200, 32313, + 32413, 32501, 32577, 32640, 32691, 32729, 32754, 32766 +}; +const Word16 win_lpc_hb_wb_fx[(L_LOOK_12k8 + L_SUBFR + L_FRAME) * 5/32] = +{ + 17, 70, 157, 279, 435, 625, 849, 1106, + 1396, 1718, 2071, 2454, 2867, 3309, 3779, 4276, + 4799, 5346, 5917, 6510, 7125, 7759, 8411, 9081, + 9766, 10465, 11177, 11900, 12633, 13373, 14120, 14872, + 15627, 16384, 17141, 17896, 18648, 19395, 20135, 20868, + 21591, 22303, 23002, 23687, 24357, 25009, 25643, 26258, + 26851, 27422, 27969, 28492, 28989, 29459, 29901, 30314, + 30697, 31050, 31372, 31662, 31919, 32143, 32333, 32489, + 32611, 32698, 32751 +}; + +const Word16 wac_h[LPC_SHB_ORDER] = +{ + 32763, + 32751, + 32731, + 32703, + 32667, + 32622, + 32570, + 32510, + 32442, + 32366 +}; + +const Word16 wac_l[LPC_SHB_ORDER] = +{ + 31381, + 27317, + 20869, + 12529, + 2980, + 25869, + 16731, + 9600, + 5926, + 7354 +}; + +const Word16 lpc_weights_fx[LPC_SHB_ORDER+1] = +{ + 32767, 31948, 31150, 30371, 29612, + 28871, 28149, 27446, 26760, 26091, 25438 +}; + + + +const Word16 SHBCB_SubGain5bit_12_fx[128] = +{ + /*Q12 */ + -597, -1952, -1644, -1506, -1767, -1357, -1249, -874, + -4181, -3836, -240, -1985, -6573, -1480, -1229, -1094, + -381, -1655, -2119, -2406, -2012, -1022, -2235, -761, + -908, -1282, -1241, -1845, -68, -4666, -6058, -6355, + -2311, -1888, -1396, -513, -523, -1155, -2300, -3657, + -1161, -549, -2564, -2424, -609, -2346, -2934, -1142, + -3591, -2859, -2063, -205, -4048, -4083, -4261, -56, + -1352, -2147, -1894, -574, -6577, -5483, -1881, -628, + -815, -1061, -1987, -1654, -455, -1380, -3818, -4941, + -926, -934, -1463, -2630, -2520, -1013, -1016, -1250, + -977, -2477, -720, -2401, -130, -2789, -3155, -3192, + -1135, -1287, -1552, -1115, -1217, -1918, -1059, -1102, + -2291, -3353, -744, -979, -3067, -1892, -961, -707, + -1795, -1229, -652, -2348, -1569, -717, -1490, -1628, + -3240, -258, -2129, -2748, -2062, -1902, -625, -1257, + -1453, -1250, -965, -1445, -4227, -1494, -1108, -819, + + +}; + + +const Word16 lsf_q_cb_4b_fx[16] = +{ + 589, 773, 914, 1043, + 1173, 1302, 1430, 1558, + 1698, 1843, 1973, 2103, + 2258, 2470, 2787, 3282 + +}; + +const Word16 lsf_q_cb_3b_fx[8] = +{ + 679, 976, 1245, 1491, + 1739, 2011, 2365, 2953 +}; + +const Word16 pwAlpha[10]= {0x6666, 0x51ec, 0x4189, 0x346e, 0x29f1, + 0x218e, 0x1ad8, 0x157a, 0x112e, 0x0dbe + }; + +const Word16 wb_bwe_lsfvq_cbook_8bit_fx[256*6] = +{ + 2107, 3430, 5123, 6677, 9403, 13197, + 4031, 5069, 7343, 8910, 10647, 12245, + 2037, 3542, 6708, 8763, 10505, 12655, + 5732, 6373, 7912, 9546, 12584, 14230, + 2028, 3337, 5473, 7880, 10269, 12450, + 5809, 6497, 8317, 9624, 11497, 14007, + 2428, 3962, 5675, 7724, 11361, 13385, + 6348, 8307, 8898, 9948, 11058, 13350, + 3552, 4421, 5896, 7143, 9975, 13233, + 5719, 6344, 7482, 8403, 10765, 13455, + 3509, 4379, 5896, 7437, 11765, 14307, + 4521, 8122, 8791, 9856, 11232, 14020, + 2175, 3970, 7788, 9803, 11334, 12910, + 4511, 8156, 8886, 10450, 12686, 14959, + 4223, 5285, 7053, 8423, 11317, 14566, + 7159, 8379, 9040, 10122, 11799, 14270, + 1866, 3064, 4848, 7227, 11225, 13963, + 5915, 6631, 8740, 10002, 11385, 12726, + 3342, 4547, 6475, 9404, 11994, 13418, + 6156, 6880, 8932, 10353, 12380, 13746, + 2648, 4972, 7575, 9476, 12117, 13875, + 5822, 6526, 8747, 10941, 12671, 13971, + 4032, 5110, 7592, 9267, 11374, 14390, + 6864, 8384, 9086, 10649, 12944, 15026, + 3661, 4636, 6668, 8329, 10374, 12185, + 5802, 6444, 8344, 9811, 12234, 14843, + 3593, 4436, 6663, 8693, 11539, 14272, + 5110, 8270, 9006, 10703, 12269, 13901, + 1992, 3229, 5616, 9085, 11419, 13254, + 4319, 5859, 9602, 11396, 12836, 14199, + 3836, 4822, 8285, 10190, 11728, 13302, + 8016, 8698, 10179, 11434, 12944, 14783, + 1891, 3329, 6168, 8307, 10818, 14213, + 5803, 6442, 7973, 9131, 11090, 12657, + 2803, 5499, 8093, 9694, 11223, 12849, + 6222, 6981, 8615, 9848, 12016, 13380, + 2543, 4747, 7638, 9373, 11129, 13652, + 5912, 6615, 9006, 10553, 11959, 13312, + 3604, 4520, 7650, 9833, 12161, 14748, + 7970, 8729, 9780, 10789, 12483, 13985, + 3793, 4716, 7041, 8547, 10610, 13601, + 5640, 6235, 7313, 8370, 12057, 14300, + 3765, 4699, 6784, 9512, 12663, 14216, + 4634, 8363, 9195, 10385, 11477, 13310, + 2462, 4816, 8556, 10394, 11920, 13468, + 3698, 7974, 9207, 10962, 13507, 15208, + 3738, 4667, 7545, 10775, 13024, 14559, + 7267, 8610, 9509, 11264, 12821, 14495, + 2624, 4295, 6173, 8897, 12343, 14174, + 6324, 7135, 8742, 10013, 12598, 14108, + 4448, 5839, 8842, 10335, 11737, 13071, + 6147, 6988, 9510, 10893, 12240, 13535, + 3025, 5140, 7152, 9223, 11404, 13255, + 5985, 6782, 9611, 11341, 12723, 14007, + 4679, 5958, 8100, 9842, 11835, 13492, + 7740, 8565, 9432, 10478, 12611, 14609, + 3830, 4784, 7681, 9528, 11134, 12675, + 5742, 6527, 8359, 10728, 13195, 14626, + 4491, 5635, 7284, 8749, 11594, 13785, + 6772, 8490, 9253, 10943, 12476, 13973, + 2024, 3588, 7524, 10453, 12198, 13858, + 5783, 8882, 9978, 11763, 13237, 14829, + 3979, 5009, 8342, 10323, 12231, 14313, + 8148, 8903, 10193, 11350, 13246, 14490, + 2297, 3810, 5638, 7265, 9162, 11514, + 5809, 6518, 7832, 8766, 10327, 11957, + 2535, 4591, 7415, 9080, 10623, 12257, + 5948, 6598, 8515, 10082, 12721, 14188, + 2443, 4278, 6581, 8172, 9883, 11807, + 5913, 6535, 8878, 10296, 12141, 14245, + 2428, 3925, 6409, 9835, 11962, 13628, + 7430, 8531, 9302, 10259, 11444, 12933, + 3701, 4694, 6372, 7671, 9445, 11571, + 5822, 6470, 7807, 8885, 11506, 14529, + 3742, 4580, 6232, 7860, 11252, 13127, + 5710, 8330, 8943, 10243, 11696, 14511, + 2607, 4197, 6714, 10408, 12714, 14320, + 4116, 8438, 9717, 11018, 12156, 13663, + 4224, 5318, 7486, 10110, 12779, 14331, + 5565, 8413, 9115, 10930, 12588, 14759, + 1898, 3150, 5779, 9497, 12432, 14439, + 6274, 7186, 9258, 10404, 11733, 12952, + 3700, 4591, 7575, 9533, 11461, 13777, + 6234, 7104, 9032, 10986, 13088, 14417, + 2354, 4579, 7744, 9960, 12629, 14802, + 6050, 6729, 9345, 10745, 12436, 14253, + 4345, 5529, 8117, 9718, 12433, 14109, + 8009, 8701, 9863, 10954, 13046, 14474, + 4184, 5186, 6876, 8428, 11236, 12973, + 6113, 6842, 8386, 9659, 12892, 14707, + 3989, 4936, 7152, 8879, 11743, 13632, + 5169, 8411, 9209, 11361, 13452, 15076, + 2397, 4387, 7033, 9035, 11821, 13736, + 3607, 8128, 10170, 11565, 12819, 14147, + 4449, 5805, 8963, 10676, 12596, 14558, + 7911, 8741, 10040, 11622, 13579, 15092, + 2372, 4290, 6990, 8705, 10637, 13685, + 6137, 6917, 8382, 9380, 10859, 12348, + 3235, 5973, 8187, 10174, 12420, 14382, + 6077, 6764, 8551, 9803, 12150, 14079, + 2952, 5097, 6853, 8952, 12066, 14080, + 6606, 7683, 9508, 10695, 12182, 13601, + 3707, 4638, 7468, 10484, 12295, 13754, + 7960, 8715, 10051, 11348, 12757, 14072, + 4139, 5241, 7576, 9037, 10912, 13485, + 5838, 6444, 7768, 8965, 12867, 14998, + 4245, 5338, 7248, 9190, 12328, 14047, + 6159, 8874, 9899, 11134, 12150, 13512, + 2250, 4288, 8698, 10944, 12624, 14316, + 3146, 6848, 9904, 11775, 13534, 14953, + 4044, 5161, 8365, 10294, 12945, 14907, + 7398, 8724, 9813, 11821, 13246, 14552, + 2121, 3890, 6855, 9274, 12059, 14663, + 6329, 7182, 8789, 10081, 13001, 14917, + 4484, 5761, 8634, 10295, 12111, 14022, + 6326, 7208, 9672, 11078, 12830, 14529, + 3230, 5564, 7646, 9955, 12011, 13683, + 4683, 6896, 10002, 11805, 13329, 14747, + 4771, 6044, 8081, 10305, 12526, 14037, + 8231, 9203, 10351, 11427, 12926, 14635, + 4385, 5774, 7989, 9305, 10751, 12299, + 5810, 6658, 9062, 11629, 13359, 14655, + 4288, 5388, 7804, 9378, 11781, 13652, + 4398, 8560, 9646, 11161, 12701, 14872, + 1947, 3440, 7202, 10953, 13222, 14806, + 4686, 8972, 10615, 12054, 13260, 14615, + 3801, 4849, 8922, 11200, 12882, 14423, + 8061, 8813, 10453, 11912, 13335, 14710, + 2365, 3888, 5664, 7346, 10407, 14331, + 4563, 5839, 7472, 8684, 10572, 12800, + 2593, 4197, 6719, 9323, 11229, 12919, + 6081, 6774, 8132, 9244, 12202, 13918, + 2405, 3981, 6144, 8740, 11347, 13796, + 5793, 6444, 8286, 10049, 12152, 13520, + 2795, 4727, 6528, 8506, 11323, 13474, + 6181, 8598, 9346, 10614, 11725, 13545, + 4002, 5001, 6596, 7792, 9987, 13065, + 5748, 6365, 7759, 9028, 11818, 13487, + 3906, 4863, 6462, 7763, 10705, 14359, + 4315, 8428, 9322, 10582, 11942, 14500, + 2812, 4622, 7346, 10036, 11745, 13429, + 4221, 8338, 9277, 11280, 12869, 14317, + 4345, 5427, 7121, 8736, 12787, 14837, + 7678, 8614, 9456, 10461, 12024, 13852, + 2193, 3662, 5609, 7867, 12276, 14739, + 6083, 6864, 8879, 10080, 11623, 13720, + 4114, 5125, 7224, 9729, 11808, 13297, + 6383, 7232, 9252, 10720, 12622, 14030, + 2788, 5189, 8074, 9953, 11795, 14361, + 6079, 6987, 8662, 10589, 12444, 14390, + 4480, 5690, 7708, 9115, 11800, 14576, + 7848, 8763, 9802, 10924, 12515, 14832, + 3582, 4575, 6729, 9084, 11139, 12800, + 5885, 6534, 8853, 10432, 12664, 14960, + 3891, 4850, 7195, 8932, 12097, 14665, + 5797, 8545, 9385, 11556, 12997, 14392, + 1962, 3544, 7039, 9349, 11272, 13857, + 4106, 5493, 9652, 12038, 13603, 14932, + 4328, 5413, 7949, 10282, 12164, 13618, + 8135, 8918, 10057, 11085, 13190, 15015, + 2702, 4627, 6447, 8009, 10197, 13676, + 5998, 6656, 8315, 9496, 11597, 13122, + 3146, 6293, 8530, 10158, 11798, 13558, + 6374, 7289, 8698, 9776, 11885, 14236, + 3171, 5794, 7737, 9377, 11312, 13878, + 6279, 7150, 9192, 10414, 12052, 14174, + 4117, 5195, 7805, 9512, 12450, 14849, + 7963, 8955, 10071, 11129, 12324, 13605, + 4365, 5505, 7013, 8171, 10488, 13658, + 6124, 6894, 8286, 9349, 11859, 14737, + 3753, 4673, 6421, 8146, 12726, 14980, + 5457, 8706, 9598, 11035, 12294, 14268, + 2783, 4916, 7947, 10568, 12395, 14123, + 3909, 8145, 9524, 11951, 14052, 15282, + 3952, 5139, 8180, 11380, 13699, 15085, + 7200, 9031, 10025, 11484, 12924, 14848, + 2533, 4412, 6472, 8299, 11405, 14627, + 6563, 7530, 9064, 10267, 12560, 14422, + 4849, 6618, 8678, 10166, 11983, 13841, + 6393, 7569, 9960, 11300, 12644, 13906, + 3170, 5117, 7158, 9665, 11687, 14114, + 6122, 7071, 10013, 11733, 13170, 14466, + 4308, 5441, 7607, 9900, 11904, 14292, + 8129, 9024, 10087, 11081, 12670, 14356, + 4253, 5392, 8175, 9780, 11353, 12988, + 5453, 6638, 8596, 11453, 13885, 15263, + 4664, 5903, 7618, 9420, 12198, 13853, + 7149, 8859, 9746, 11029, 12219, 14188, + 2318, 4251, 7702, 9889, 11778, 14182, + 6679, 9280, 10573, 11950, 13100, 14491, + 4010, 5176, 8989, 10821, 12250, 13654, + 8076, 8886, 10411, 11722, 12992, 14267, + 2308, 4017, 6024, 7618, 9736, 13081, + 6001, 6751, 7987, 8966, 10964, 13589, + 2908, 5350, 7266, 8739, 10442, 12981, + 6143, 6839, 9027, 10366, 12881, 14416, + 2667, 4224, 6172, 8378, 10717, 12602, + 6275, 7120, 9249, 10613, 12580, 14823, + 2692, 4586, 6968, 9858, 12120, 14209, + 7771, 8769, 9743, 10745, 11943, 13225, + 4201, 5355, 7129, 8337, 9975, 11767, + 6216, 7100, 8444, 9442, 11298, 13690, + 4111, 5040, 6562, 8071, 12034, 13923, + 6657, 8599, 9337, 10665, 12040, 14704, + 3060, 5215, 7260, 10118, 12577, 14386, + 5103, 8913, 10157, 11519, 12669, 14220, + 4633, 5920, 7804, 9514, 12741, 14690, + 6720, 8585, 9448, 11556, 13510, 15095, + 2361, 3970, 6213, 9335, 13270, 15075, + 6506, 7440, 9041, 10179, 12024, 13587, + 4221, 5405, 8311, 9818, 11579, 14044, + 6216, 7224, 9515, 11389, 13545, 15068, + 2872, 5507, 8153, 10650, 13065, 14825, + 6002, 6676, 9393, 11023, 12965, 14755, + 4438, 5642, 8268, 10097, 12295, 14724, + 7797, 8622, 9642, 10932, 13287, 15118, + 4471, 5638, 7551, 9217, 11440, 12928, + 6051, 6890, 8906, 10655, 13437, 15116, + 3953, 4934, 7779, 9619, 12204, 14012, + 5439, 8649, 9791, 12232, 13899, 15193, + 2728, 4495, 6728, 9363, 11344, 14053, + 4069, 8460, 9835, 11742, 13366, 14825, + 4874, 6937, 9226, 10944, 12845, 14547, + 8195, 9093, 10392, 11594, 13355, 15010, + 2956, 5192, 7080, 8765, 11014, 14174, + 6384, 7287, 8812, 9816, 11336, 12808, + 2912, 6122, 9132, 10874, 12583, 14265, + 6148, 6925, 8821, 10030, 12212, 14758, + 2572, 4778, 7325, 9216, 11620, 14651, + 6654, 7718, 9546, 10806, 12633, 14354, + 4328, 5514, 8231, 10852, 12821, 14261, + 8051, 9205, 10385, 11490, 12674, 13988, + 4624, 6013, 7907, 9239, 11160, 13787, + 5786, 6531, 8210, 9968, 13410, 15249, + 3859, 4898, 7132, 9692, 13395, 15118, + 6712, 8944, 10028, 11521, 12690, 14118, + 2417, 4875, 9132, 11671, 13382, 14841, + 4113, 8355, 10734, 12517, 13905, 15115, + 4455, 5753, 7923, 10298, 13343, 15030, + 6998, 8878, 10113, 12233, 13768, 15107, + 2720, 4801, 6883, 9267, 12694, 14837, + 6507, 7496, 9312, 10696, 13185, 14850, + 4631, 6341, 9164, 10796, 12325, 13734, + 6602, 7817, 9932, 11349, 13132, 14672, + 3089, 5561, 7579, 9433, 12256, 14633, + 6246, 7715, 10371, 12065, 13563, 14878, + 4757, 6352, 8543, 10216, 12748, 14620, + 8183, 9366, 10628, 11857, 13185, 14599, + 4734, 6314, 8348, 9716, 11274, 12942, + 5824, 6871, 9829, 12268, 13874, 15138, + 4719, 6142, 8224, 9683, 11915, 14350, + 6288, 8774, 9655, 11204, 12696, 14867, + 2661, 4586, 7326, 10934, 13501, 15026, + 5932, 9323, 10877, 12454, 13715, 15004, + 4467, 6039, 8842, 11164, 13356, 14901, + 7880, 9158, 10593, 12209, 13609, 14989, +}; + +const Word16 swb_tbe_lsfvq_cbook_8b[256*LPC_SHB_ORDER] = /* Q15 */ +{ + 1705, 3230, 4202, 5086, 6148, 7221, 8127, 10728, 13656, 15364, + 1668, 2958, 4063, 5644, 7356, 9440, 11046, 12261, 13228, 14503, + 1546, 2917, 4226, 5477, 6976, 8349, 9709, 11882, 13218, 14715, + 1158, 2729, 5177, 6967, 8297, 9611, 10655, 11668, 12757, 14415, + 1616, 3005, 4368, 5810, 7107, 8129, 9376, 10457, 12738, 14835, + 1232, 2451, 4145, 6446, 7741, 8993, 10377, 11898, 14213, 15314, + 1638, 3089, 5134, 6351, 7360, 8304, 9787, 12377, 13755, 15209, + 1264, 2543, 5564, 6686, 7958, 9481, 11021, 12517, 13875, 15147, + 1304, 2537, 3713, 4863, 6564, 7910, 9400, 11794, 13268, 14834, + 1652, 3245, 4686, 6405, 7931, 9223, 10591, 12020, 13193, 14759, + 1302, 2619, 4287, 5884, 7166, 8556, 10512, 12471, 13767, 15075, + 2034, 3467, 5577, 6530, 7674, 8783, 10920, 12798, 13727, 15002, + 2621, 3956, 5275, 6542, 7509, 8517, 9456, 10781, 12456, 14099, + 1496, 2653, 4147, 5637, 7370, 9233, 11817, 12986, 13968, 15046, + 2224, 3324, 4700, 5868, 7211, 8638, 11369, 12695, 13600, 14559, + 1267, 3050, 4707, 6321, 8663, 10140, 11174, 12453, 13425, 14844, + 1662, 2980, 4155, 5414, 6639, 7797, 9253, 11360, 12838, 14440, + 1521, 2856, 4944, 6367, 7506, 8857, 10971, 12183, 13275, 15006, + 1454, 2859, 4563, 5971, 7186, 8569, 10151, 11770, 13396, 14984, + 1143, 2942, 5267, 6840, 8377, 9457, 10589, 11615, 13892, 15271, + 1674, 3053, 4605, 5768, 7104, 8452, 10094, 11782, 12793, 13758, + 1702, 3261, 4723, 6245, 7899, 9494, 11010, 12387, 13680, 15066, + 1365, 2796, 5406, 6505, 7488, 8679, 10447, 12000, 13637, 15046, + 2090, 3931, 5788, 7157, 8254, 9717, 11007, 12081, 13238, 14880, + 1952, 3157, 4132, 5164, 6334, 7389, 9004, 11798, 14096, 15505, + 1641, 3212, 4919, 6364, 7863, 9311, 10766, 12234, 13694, 15054, + 1653, 3008, 4213, 5354, 6980, 8821, 11185, 12685, 13903, 15251, + 1856, 3444, 5146, 6579, 7801, 9250, 11062, 12947, 14145, 15291, + 1365, 3567, 5552, 6474, 7332, 8254, 9952, 11364, 13505, 14951, + 1488, 2896, 4521, 6279, 7880, 9446, 11418, 12921, 14431, 15465, + 1516, 3174, 5364, 6410, 7295, 8285, 10799, 12594, 14172, 15424, + 1738, 3416, 5237, 6878, 8440, 10539, 12105, 13063, 13924, 15150, + 1431, 2659, 3909, 5328, 6641, 7950, 9347, 11037, 13510, 14992, + 1400, 2646, 4233, 6366, 7749, 9220, 10560, 11594, 13046, 14992, + 1115, 2198, 3607, 5279, 8055, 9774, 11024, 12426, 13972, 15232, + 1360, 3418, 5724, 6973, 7912, 9078, 10810, 12437, 13630, 14826, + 1422, 3051, 5132, 6141, 7206, 8275, 9355, 10859, 13814, 15202, + 1080, 2227, 4117, 6404, 8080, 9318, 10934, 12404, 13688, 14827, + 1611, 3423, 4928, 6214, 7426, 8723, 10502, 11915, 13438, 15105, + 1947, 3524, 5198, 7008, 8358, 10006, 11397, 12444, 13583, 15135, + 1394, 2672, 4004, 5681, 6953, 8301, 9815, 12000, 13709, 15079, + 1788, 3193, 4579, 6221, 7874, 9170, 11186, 12647, 13521, 14538, + 1548, 2811, 4058, 5331, 6528, 7769, 10982, 12743, 13822, 15131, + 1751, 4007, 5154, 6463, 7935, 9470, 11103, 12406, 13337, 14520, + 2004, 3172, 5079, 6116, 7109, 8155, 10351, 12192, 13413, 14773, + 1644, 3185, 4750, 6290, 7816, 9271, 11041, 12831, 14139, 15341, + 2311, 3779, 5116, 6100, 7321, 9139, 10353, 12134, 13834, 15172, + 1723, 3339, 5049, 6754, 8353, 10290, 12048, 13157, 14206, 15460, + 2218, 3501, 4639, 5764, 6789, 7834, 9804, 11907, 13182, 14689, + 1640, 3173, 4679, 6202, 7660, 9120, 10773, 12395, 13894, 15200, + 1591, 3070, 4537, 6005, 7341, 8802, 10480, 12240, 13768, 15130, + 1169, 3611, 5983, 7054, 8601, 10022, 10948, 11927, 12834, 14747, + 1708, 3191, 4642, 6156, 7396, 8805, 10028, 11733, 13206, 14857, + 1519, 3082, 4752, 6484, 7730, 9328, 10796, 12003, 14524, 15513, + 2153, 3558, 5162, 6714, 7762, 8857, 10008, 12012, 13725, 15209, + 2680, 4053, 5310, 6996, 8309, 9343, 10361, 12333, 14224, 15498, + 2356, 3805, 5032, 5970, 6915, 7880, 8924, 12060, 13838, 15185, + 1807, 3439, 4962, 6483, 8013, 9556, 10952, 12327, 13686, 15059, + 1571, 2900, 4208, 6449, 7675, 8592, 11138, 12775, 14181, 15422, + 2006, 4262, 5508, 6414, 7621, 8725, 10788, 12605, 13609, 14776, + 1785, 3741, 5267, 6702, 8097, 9460, 10487, 11481, 12889, 14885, + 1647, 3223, 4795, 6391, 8007, 9620, 11575, 12955, 14100, 15381, + 1518, 3214, 5233, 6509, 7687, 8803, 11778, 13932, 14760, 15491, + 2136, 3647, 5373, 7317, 8671, 10261, 11786, 12933, 13820, 15186, + 1633, 3265, 4672, 5640, 6776, 7783, 8907, 10184, 12066, 14492, + 1690, 3028, 4184, 6049, 7489, 8678, 11045, 12244, 13372, 15016, + 1649, 3080, 4358, 5795, 7364, 8601, 10257, 12126, 13328, 15113, + 1850, 3286, 5392, 6765, 7826, 9185, 10506, 11776, 13248, 15163, + 2111, 3522, 4870, 6087, 7162, 8385, 9645, 10861, 12341, 14302, + 1529, 2909, 4136, 6783, 8064, 9325, 10942, 12094, 13886, 15169, + 1847, 3281, 4752, 6098, 7310, 8744, 10129, 12278, 13554, 14930, + 1149, 2767, 5869, 7479, 8514, 9723, 11235, 12300, 13871, 15068, + 1689, 3066, 4325, 5613, 6772, 7936, 9051, 12135, 13730, 15025, + 2127, 3394, 5263, 6880, 7874, 9155, 10305, 12136, 13494, 14437, + 1682, 3054, 4412, 6053, 7380, 8465, 9817, 12460, 14155, 15285, + 1799, 3430, 5123, 6594, 7934, 9609, 11472, 12791, 13686, 14849, + 1899, 3656, 5369, 6355, 7516, 8800, 9888, 11646, 13024, 13965, + 1410, 3252, 5101, 6050, 7480, 9912, 11739, 12806, 14085, 15186, + 1487, 3934, 5351, 6390, 7519, 8890, 11488, 12818, 13787, 14941, + 1562, 3156, 5075, 7044, 8872, 10271, 11479, 12632, 13907, 14993, + 1548, 2926, 4338, 5796, 7011, 8143, 9336, 11323, 13461, 14904, + 1421, 2907, 4736, 6272, 7730, 8977, 10453, 12374, 13840, 15234, + 1495, 2996, 4496, 6036, 7545, 9034, 10534, 12014, 13486, 14958, + 1388, 3203, 5691, 7076, 8578, 9661, 10874, 12326, 14433, 15423, + 1248, 2983, 5304, 6423, 7544, 8611, 10290, 11682, 12904, 14549, + 1496, 2988, 4632, 6342, 7852, 9329, 11175, 12546, 13758, 15182, + 1373, 3379, 5067, 6179, 7379, 8775, 10005, 11464, 14147, 15386, + 2537, 3849, 5533, 7263, 8318, 9657, 11346, 12355, 13955, 15314, + 2113, 3405, 4419, 5268, 6436, 8005, 10292, 12442, 13655, 15176, + 1620, 3681, 5454, 6406, 7459, 9354, 10872, 12035, 14163, 15279, + 1903, 3232, 4517, 5758, 7156, 8851, 10670, 12413, 14518, 15565, + 1714, 3779, 5166, 6557, 8107, 9168, 10560, 12854, 14208, 15329, + 1926, 3645, 5521, 7072, 7999, 8974, 9806, 11088, 13527, 15298, + 1820, 2840, 4726, 7091, 8261, 9758, 11218, 12148, 14064, 15262, + 2072, 3303, 5391, 6710, 7504, 8497, 10457, 12394, 14480, 15541, + 1627, 3294, 5209, 7432, 8846, 10147, 11517, 12890, 14488, 15411, + 2172, 3405, 4580, 5623, 6732, 7648, 8485, 9913, 13396, 15213, + 1581, 3058, 4633, 6225, 7724, 9238, 10779, 12240, 13650, 15094, + 1675, 2927, 4090, 5753, 7461, 8922, 10277, 11670, 13987, 15336, + 1868, 3611, 5256, 6927, 8093, 9434, 10998, 12144, 13380, 15165, + 1498, 3635, 5273, 6823, 7825, 8916, 9811, 10903, 12514, 14884, + 1448, 2626, 3930, 6895, 8348, 9746, 11404, 12565, 14288, 15325, + 1945, 3408, 4987, 6340, 7627, 8954, 10251, 12381, 13481, 14983, + 1956, 3759, 5388, 6894, 8466, 9962, 11460, 12759, 14145, 15321, + 1670, 3271, 4588, 5970, 7185, 8366, 9640, 12011, 13488, 14833, + 1964, 3444, 4826, 6213, 7936, 9097, 10785, 12617, 13612, 15229, + 1646, 3390, 4669, 6049, 7001, 7940, 10461, 12478, 14675, 15704, + 2202, 3782, 5107, 6754, 8280, 9628, 11687, 13028, 13871, 15207, + 2354, 3830, 5174, 6360, 7555, 8997, 10681, 11977, 13066, 14781, + 2351, 3525, 4892, 6386, 7616, 9133, 11859, 13061, 13946, 15004, + 2252, 3772, 5155, 6485, 7799, 9145, 10769, 12561, 13763, 15241, + 1714, 3107, 4725, 6097, 9158, 10459, 11619, 12699, 14346, 15256, + 1830, 3506, 4969, 5973, 6900, 7836, 8994, 11088, 13366, 14860, + 1856, 3406, 4898, 6367, 7810, 9186, 10422, 12172, 13969, 15331, + 2006, 3382, 4743, 6100, 7430, 8753, 10805, 12234, 13673, 15195, + 1491, 3607, 5343, 7464, 9179, 10087, 11024, 12099, 13199, 14956, + 1749, 3371, 5121, 6500, 7646, 8770, 9968, 11673, 13339, 14931, + 1857, 3506, 5083, 6595, 8200, 9739, 11138, 12528, 13884, 15137, + 1780, 3860, 5581, 6692, 7837, 8989, 10304, 12318, 13611, 15109, + 2164, 4463, 5655, 7632, 9047, 9922, 10784, 12950, 14723, 15589, + 2305, 3300, 4366, 5608, 6857, 7795, 10006, 11950, 14376, 15700, + 1628, 3408, 5074, 6761, 8312, 9687, 11104, 12332, 13619, 15076, + 1842, 3314, 4771, 6460, 7463, 8661, 11191, 12739, 14592, 15633, + 1808, 4360, 5904, 6869, 8134, 9174, 10780, 12589, 13995, 15150, + 2966, 4354, 5686, 6983, 7938, 9092, 10062, 11747, 13307, 14611, + 1932, 3293, 4910, 6818, 7690, 9074, 11715, 13019, 14429, 15478, + 1978, 3772, 5429, 6580, 7448, 8496, 11755, 13132, 14549, 15560, + 1881, 3635, 5627, 7292, 8573, 10911, 12325, 13200, 14068, 15243, + 1436, 2716, 4002, 5347, 6553, 7646, 8955, 10690, 12967, 14784, + 1426, 2825, 4206, 5726, 8100, 9391, 10712, 12262, 13506, 14954, + 1448, 2767, 4089, 5265, 7185, 8684, 10378, 12257, 13431, 14803, + 1669, 3312, 4990, 6887, 8050, 9595, 10943, 12015, 13145, 14920, + 1534, 2814, 4191, 5933, 7393, 8687, 9865, 11185, 12958, 14743, + 1397, 2706, 4322, 6052, 7618, 9168, 10995, 12433, 13931, 15267, + 1717, 3164, 4630, 6329, 7519, 8846, 10088, 12116, 14012, 15197, + 1606, 3316, 5165, 6942, 8278, 9625, 11461, 12806, 14095, 15299, + 2014, 3357, 4281, 5076, 6191, 7372, 9501, 12414, 13419, 14901, + 1322, 3655, 5269, 6494, 7613, 9253, 10752, 11974, 13302, 14833, + 1687, 3291, 4718, 5817, 7001, 8136, 10741, 12692, 13884, 15224, + 2255, 3723, 5555, 7021, 8101, 9345, 10765, 12705, 13693, 15223, + 2376, 3715, 5249, 6505, 7410, 8345, 10176, 11618, 12708, 14488, + 1842, 3232, 4371, 5954, 7832, 9126, 11296, 12743, 13862, 15331, + 2046, 3597, 5325, 6453, 7353, 8588, 10588, 12082, 13664, 15152, + 1970, 3564, 4925, 6547, 8672, 9980, 11383, 12786, 13969, 15234, + 1497, 2938, 4909, 6099, 7102, 8072, 9514, 11294, 12761, 14578, + 1666, 3164, 5098, 6255, 7350, 8902, 10694, 12503, 13808, 14980, + 1467, 2774, 4556, 6308, 7435, 8644, 10040, 12356, 13597, 14776, + 1915, 3618, 5160, 6707, 8479, 9521, 10481, 11536, 14163, 15479, + 1857, 3466, 4760, 6205, 7312, 8801, 10376, 11978, 13161, 14235, + 1615, 3107, 4710, 6452, 8069, 9877, 11348, 12575, 13751, 15049, + 1563, 3092, 4977, 6851, 8056, 9025, 10327, 12181, 14039, 15192, + 2294, 3843, 5781, 7222, 8505, 9851, 11210, 12802, 13676, 15158, + 1931, 3436, 4681, 5837, 6908, 7825, 9440, 12600, 14162, 15305, + 1572, 3189, 4879, 6680, 7970, 9293, 10974, 12193, 13506, 15218, + 1759, 3172, 4687, 5950, 7484, 8874, 10563, 12821, 14112, 15299, + 1461, 4009, 5495, 6608, 7867, 9497, 11307, 12520, 14357, 15467, + 1922, 4314, 5736, 6599, 7481, 8598, 9852, 11345, 14012, 15280, + 1249, 2609, 4690, 7006, 8061, 9011, 11477, 13214, 14382, 15337, + 2251, 3776, 5514, 6458, 7300, 8078, 10961, 12696, 14279, 15567, + 1697, 3374, 5134, 6984, 8675, 10700, 12194, 13233, 14184, 15464, + 1985, 3326, 4440, 5685, 6870, 8207, 9545, 11223, 13672, 15143, + 1453, 2824, 4722, 6476, 7730, 8963, 10217, 11743, 13545, 15152, + 1217, 2442, 3821, 5409, 7315, 8949, 10797, 12564, 14281, 15410, + 1546, 3204, 5604, 6730, 8040, 9677, 11029, 12107, 13803, 15267, + 2042, 3424, 4830, 6328, 7473, 8525, 9386, 10755, 13398, 14998, + 1106, 2508, 4816, 7337, 8399, 9630, 11278, 12453, 14067, 15024, + 1764, 3305, 4955, 6537, 7767, 9117, 10404, 11961, 13576, 15021, + 1604, 3797, 5700, 7128, 8515, 9896, 11389, 12534, 13696, 15136, + 1623, 3004, 4355, 6217, 7351, 8437, 9819, 11537, 13974, 15340, + 2457, 3890, 4962, 5848, 7311, 9718, 11213, 12292, 13705, 15111, + 1601, 3330, 4648, 6043, 7138, 8179, 11247, 13078, 14768, 15641, + 2457, 3677, 5174, 6432, 7982, 10024, 11164, 12170, 13704, 15112, + 1552, 3777, 5267, 6325, 7532, 8642, 9894, 12404, 13569, 14620, + 1961, 3463, 4720, 6498, 8059, 9304, 11486, 12824, 14102, 15458, + 2443, 3699, 5252, 6348, 7638, 8733, 10224, 12666, 13768, 15009, + 2204, 3657, 5086, 6792, 8300, 10152, 12313, 13306, 14079, 15287, + 2360, 3731, 5002, 6094, 6952, 8009, 9152, 11586, 13038, 14158, + 1888, 3469, 4880, 6183, 7603, 9244, 10801, 12319, 13657, 15002, + 1670, 3283, 4591, 6080, 7801, 8951, 10534, 12572, 13620, 14969, + 1304, 4140, 5864, 7008, 8377, 9651, 10825, 11805, 13637, 15300, + 2077, 3547, 4890, 6216, 7303, 8608, 9810, 11796, 13525, 14984, + 1658, 3252, 4916, 6498, 8069, 9529, 11029, 12538, 13903, 15184, + 2206, 3648, 4949, 6636, 7875, 8833, 9853, 12624, 14448, 15475, + 3039, 4664, 5792, 7321, 8798, 9724, 10485, 12329, 14465, 15650, + 1885, 3201, 5227, 6590, 7343, 8049, 9372, 12313, 14594, 15645, + 1826, 3446, 5138, 6665, 8008, 9352, 10668, 12583, 13810, 15065, + 1455, 3065, 5233, 6306, 7404, 8776, 11422, 12775, 14032, 15239, + 2395, 4674, 5883, 6877, 7900, 9322, 10931, 12537, 13765, 14888, + 1840, 4359, 5629, 6875, 7968, 9185, 10266, 11861, 13202, 14464, + 1662, 3278, 4865, 6555, 8122, 10011, 11874, 13087, 14128, 15418, + 1643, 3366, 5837, 7033, 7854, 8928, 11487, 12972, 14409, 15467, + 1878, 3685, 5789, 7325, 8714, 10906, 12273, 13110, 13834, 14837, + 2259, 3652, 4995, 6055, 7005, 7900, 8843, 10024, 12609, 14736, + 1568, 2949, 4504, 6035, 7428, 9194, 10893, 12444, 13595, 14939, + 1678, 3143, 4416, 5872, 7501, 8768, 10418, 12127, 13144, 14622, + 1878, 3549, 5481, 7178, 8322, 9347, 10532, 12117, 13554, 15167, + 2055, 3346, 4814, 6193, 7418, 8757, 10144, 11365, 12698, 14779, + 1486, 2779, 3954, 6134, 8290, 9646, 10767, 12112, 14441, 15428, + 1787, 3511, 4962, 6055, 7295, 8858, 10179, 12437, 13813, 15217, + 1374, 3184, 5771, 7998, 9354, 10209, 11249, 12469, 14015, 15248, + 1627, 2947, 4046, 5182, 6798, 8225, 9770, 12661, 14250, 15408, + 2117, 3704, 5007, 6630, 8002, 9222, 10550, 12108, 13472, 15034, + 1365, 2885, 4896, 6144, 7426, 9137, 10283, 12727, 14709, 15505, + 2073, 3691, 5305, 6800, 8134, 9508, 11139, 12857, 13896, 15239, + 1564, 4084, 5497, 6495, 7391, 8539, 10468, 11705, 12804, 14704, + 1844, 3180, 4380, 5754, 8181, 9923, 11738, 12995, 14138, 15232, + 2157, 3736, 5059, 5932, 7192, 8916, 11216, 12783, 13945, 15189, + 1782, 2860, 4362, 7179, 9083, 10438, 11580, 12929, 14789, 15500, + 1651, 3273, 4587, 5886, 7069, 8346, 9787, 11277, 13152, 14811, + 1549, 3138, 5049, 6704, 7803, 9102, 10748, 12577, 13813, 15215, + 1674, 3187, 4709, 6204, 7622, 9024, 10541, 12135, 13576, 15063, + 1888, 3562, 5468, 7111, 8694, 9948, 11111, 12286, 14070, 15300, + 1905, 3158, 5368, 6372, 7554, 8719, 10568, 12430, 13449, 14427, + 1953, 3411, 4718, 6545, 8090, 9298, 11232, 12723, 13668, 15077, + 1459, 3444, 5688, 6814, 7843, 8977, 10119, 12107, 14316, 15368, + 2450, 4363, 5827, 7349, 8683, 10032, 11143, 12131, 13519, 15058, + 2482, 3664, 4763, 5944, 7191, 8390, 10105, 12234, 13702, 15188, + 1838, 3465, 5255, 6751, 8016, 9254, 10946, 12321, 13790, 15337, + 2497, 3548, 4702, 5987, 7645, 8883, 10740, 12247, 14393, 15540, + 1717, 3679, 5335, 6587, 8564, 9808, 10735, 12675, 14672, 15558, + 2454, 3997, 5364, 6810, 8026, 8913, 9715, 11315, 14258, 15605, + 1906, 3443, 4901, 6363, 8186, 9716, 11074, 13186, 14701, 15474, + 1992, 3246, 5488, 6514, 7455, 8324, 10807, 13238, 14763, 15579, + 1721, 3438, 5244, 7173, 9106, 10873, 12178, 13181, 14060, 15415, + 2191, 3555, 4802, 6108, 7015, 7850, 8947, 11115, 14483, 15593, + 1925, 3232, 4601, 6574, 7791, 8989, 11038, 12282, 13630, 15136, + 1816, 3167, 4292, 5730, 7588, 9096, 10743, 12341, 13760, 15252, + 2069, 3850, 5424, 6815, 8274, 9569, 10910, 12283, 13835, 15185, + 2419, 3773, 5288, 6591, 7672, 8909, 9832, 10975, 13163, 14998, + 1215, 2710, 4939, 6437, 8745, 9918, 11200, 12553, 14234, 15384, + 1867, 3527, 5134, 6496, 7656, 8923, 10602, 12568, 13896, 15276, + 2259, 4214, 5751, 7270, 8590, 10120, 11611, 12822, 14130, 15258, + 1911, 3261, 4446, 5685, 6897, 8494, 10128, 11970, 13707, 15106, + 1762, 3549, 4874, 6153, 8146, 9634, 10690, 11886, 13713, 15057, + 2371, 3716, 4778, 6111, 7097, 8063, 10544, 12615, 14716, 15724, + 2254, 3759, 5627, 6870, 7896, 9379, 11627, 12889, 13795, 15272, + 2516, 4000, 5378, 6444, 7496, 8634, 9767, 12110, 13503, 14640, + 2385, 3201, 4283, 6677, 8216, 9689, 11654, 12319, 14142, 15367, + 2775, 4055, 5455, 6553, 7821, 8901, 10890, 12775, 13696, 14884, + 1568, 3940, 5341, 6824, 9355, 10305, 11405, 12879, 14291, 15334, + 2436, 3807, 5183, 6189, 7099, 8116, 9655, 11275, 13641, 15137, + 1755, 3340, 4871, 6382, 7790, 9316, 10921, 12432, 13903, 15217, + 1932, 3246, 4603, 6454, 7590, 8678, 10609, 12641, 13938, 15245, + 1417, 4366, 6289, 7362, 8846, 10151, 11160, 12134, 13593, 15216, + 1820, 3378, 4782, 6421, 7788, 9056, 10070, 11271, 13614, 15297, + 1855, 3399, 4933, 6526, 8097, 9655, 11043, 12475, 14301, 15370, + 1901, 3653, 6053, 7290, 8154, 8986, 10262, 12993, 14405, 15387, + 1958, 4295, 5824, 8196, 9580, 10318, 11267, 12551, 13716, 15374, + 2082, 4060, 5500, 6423, 7298, 8128, 9713, 12497, 14442, 15562, + 1878, 3425, 4781, 7062, 8455, 9625, 10810, 12311, 13948, 15201, + 2035, 3727, 4804, 6256, 7248, 9235, 11563, 13120, 14882, 15662, + 2143, 3982, 6527, 7709, 8742, 9804, 11240, 12658, 14397, 15409, + 2593, 4431, 5861, 7222, 8381, 9351, 10400, 11837, 13286, 15326, + 1840, 3798, 5465, 6800, 7919, 9752, 12004, 13265, 14424, 15420, + 2157, 4145, 5394, 6454, 7240, 8776, 11093, 12831, 14856, 15708, + 1467, 3782, 5811, 8123, 9314, 10456, 11641, 13211, 14562, 15331, +}; + + +const Word16 wac_swb_h[LPC_SHB_ORDER] = +{ + 32758, + 32731, + 32686, + 32622, + 32541, + 32442, + 32325, + 32191, + 32039, + 31870 +}; + +const Word16 wac_swb_l[LPC_SHB_ORDER] = +{ + 29673, + 20874, + 7850, + 25873, + 12831, + 5927, + 10541, + 239, + 15037, + 30328 +}; + + + + +const Word16 lsf_q_diff_cb_8b_rf[256*16] = /* Q6 */ +{ + -3145, 863, -1389, 4087, 1110, 3193, 290, -3160, 824, 212, -2936, -5827, -10181, -15650, -13373, -3849, + -4602, -3228, -8398, -1649, -5788, -8971, -2025, -2971, -1476, -2748, -2458, 966, -4, -1802, -1360, 654, + -8629, -7702, 6280, 3296, -1205, 365, -5964, 3125, 2443, 1442, 1149, -3835, -9867, -4238, -1977, -1955, + -2629, -759, -2056, -2297, -1839, 1678, -2412, -7539, -13208, -9624, -1688, -2171, 943, -454, 536, 2644, + -2840, -1391, -10500, 2516, 907, 146, -2762, -6750, 2949, -2282, -4614, -5663, -7773, -5510, -5947, -3727, + -4006, -939, -2500, -771, -3414, -4521, -6417, -4064, 3698, 3969, 4300, 4177, -3195, -10419, -13072, -6695, + -4284, -1172, -4415, -1601, -6029, 66, -4338, -2300, -3402, -5614, -7181, -7288, 7154, 6538, 64, -3263, + -6470, -4503, -9698, -5885, 235, 5049, 2698, -3656, -3600, -6261, -4270, 766, 1037, -1511, -1274, 1800, + 669, 2937, -3464, -1034, -4098, -11296, -382, -4610, -9613, -2081, 3947, 2832, 2962, -332, -9039, -10702, + -11109, -5950, -7200, -6525, -4260, -5060, -8936, -91, -672, 4557, 3192, -147, -2247, 1566, -734, -3007, + -2411, 1587, -2575, 2172, -3270, 10648, 7093, 1517, 1512, -392, 49, -9117, -16895, -908, -8443, -9923, + -1934, -603, -6588, 5335, -1565, -11521, 5944, -5092, -615, -2221, -7703, -1903, -5195, 2323, 3958, 3050, + -7094, 5361, -7885, -3299, -3282, -3125, -1888, -406, 1522, -23, -1506, -6075, -8517, -7605, -3450, -3362, + -3573, -2421, 1385, -181, -11027, 4778, -4014, -4956, 7316, 3138, 2351, 3406, -1998, -968, -2375, -3262, + -141, 6652, 11944, -4131, -2073, -2592, -1562, 1521, -1804, -2585, -2685, -5798, -10850, -11629, -4300, -4287, + -1569, 2229, 2330, 3147, -1026, -7010, 265, -1320, -3648, 1942, -5375, 73, 10348, 3913, -5535, -5938, + -5642, -3433, -8423, 1178, -540, -4790, -1976, 4686, 1701, -1323, -2009, -5997, -5693, -3852, -7604, -5361, + -1784, -325, -8561, -17592, 1663, 1377, 2347, -245, -2426, 141, -137, 985, -4926, -7898, -3559, 895, + -2548, -1563, -5007, 7311, 4409, 3177, 3920, 1546, -725, -5252, -9754, -9267, -5701, -6900, -961, 1772, + -1676, 889, -4798, 8060, 3460, -1911, 415, -4044, -6146, -12074, -10588, 13056, 2765, 1396, -4737, -4905, + 943, 3342, -8515, 4676, -774, -3963, -5503, -1625, 3909, -3614, 12347, 2835, -9710, 5877, 297, -918, + -5317, -2799, -3708, -4084, -8175, -6155, 1752, 6801, 7493, 6271, 4083, 3132, -809, -4200, -5389, -5982, + -5060, -5285, -1533, -2751, 2259, -3893, -3473, -108, -4711, -2627, -2069, -2320, -172, 1547, 770, 309, + -4485, -2618, -7238, 1767, -2965, 6693, 5256, 18, -1789, -5076, 7167, 3204, -1242, 1628, 4519, 1796, + -114, 1225, -3083, 321, -4002, 4834, -3014, -741, -4189, -5946, 6871, -2068, -13016, -9772, -3235, 2044, + 559, 10477, -9704, -7733, -8989, -10787, -10342, -8585, -2844, 1474, 5638, 9798, 10986, 9105, 4619, 2186, + 1576, 9039, 4354, 2073, 1861, -1492, -715, 1840, -6736, -10798, 994, -2921, -6369, 779, 2668, -443, + -2067, -1020, 1, 14571, 2253, -2163, 5255, 973, -1722, 4173, 102, -3633, -1430, -1720, 1243, 1749, + -6589, -1601, -9469, -5581, 3018, 1186, -11, 1252, 5708, 3338, 187, -3950, -6035, -3294, -106, -1130, + -2490, 445, -2543, -3283, -3432, -6963, 9950, 4072, 2294, 4517, 2736, 8173, 4270, -8347, -9374, 4776, + -66, 3476, 537, 2659, -677, 1552, 1974, -1703, -2139, -634, -1988, 694, 1921, -12938, -16525, 5848, + -9849, 7389, 4653, -1158, 1340, -2250, -2460, -2201, -3122, -90, 3974, 5105, 9127, 8701, 6184, 3770, + -5086, -3159, -3197, -9944, -7474, 961, 1158, -3536, 1050, 5572, -1480, -11120, -9276, -1841, -2086, -24, + -1019, -346, -6765, -8343, -6302, -3019, -5606, 2728, -3994, -6909, 10146, 6321, -230, -393, -846, -1536, + -1598, 3610, 3330, -233, -1215, -1953, -1330, 19, -4839, -10681, -11699, -1104, 1146, -6143, -6849, 422, + 892, 7937, -5005, -5547, 1756, -4020, -3420, -6811, -6304, -7812, -6019, 5109, 5503, 5568, 4600, 6472, + -3296, -2230, -6010, 3497, 5502, -2291, -2342, -6544, -12576, 2192, -1004, -5205, -500, -6764, -6200, 1816, + 5114, 4922, 6498, 6613, 4909, 2318, -5626, -11915, 3072, 11570, 1766, 4361, 552, -8139, -14006, -17228, + -3321, -1514, -473, 3295, -1028, -4536, -12374, 12452, 7396, -2269, -5052, 554, 1053, -4370, -5859, 97, + -2532, 2546, -4920, -13800, 8116, 2425, 1695, -2088, -5105, -346, -2869, -2457, 9336, 13166, 6150, 5166, + -2329, 72, 11513, -3075, -7745, -5492, -8015, -5108, -16, 3261, 876, -357, -3241, -2956, -4265, -2320, + -7869, -6495, -16668, -1339, -3678, 975, -2740, -2776, 3755, 141, -190, 1026, 5972, 3232, -924, -3212, + -1077, 568, -5606, 1478, -243, 2479, 10198, 3667, 682, -2873, -9164, -9042, 2186, 4347, -750, 5303, + 556, 5098, -6825, -2564, -3946, -5752, 1977, -6171, -5627, 4580, -835, -6362, 10132, 9511, 6475, 2861, + 3320, 11074, -483, 2698, -20, -4084, -4213, -3931, -231, -17, -1826, -2737, -5920, -1539, -1897, -3347, + -1346, 2075, -1230, -5248, 10906, 9461, 5046, 3485, -267, -948, 4273, 1889, 81, -488, -4763, -5532, + -1237, 6446, 3974, 5166, -723, -10033, 8338, 4102, 683, 1474, 624, -5287, -8628, -7519, -6290, 1767, + 207, 2676, 870, 13754, 7087, 2357, -922, -1734, -4651, 352, 14028, 10050, 8916, 2725, -5722, -9415, + 364, 3660, -813, 4370, -2151, -2115, 5570, -2545, -8167, -1978, -8301, -10715, 959, -5127, -11250, -7721, + -1668, -1437, -5508, -11155, -15130, 6829, 6070, -1555, -3048, -314, -528, 1714, 1474, -42, -541, 3361, + -15356, -12047, -4659, -1598, 4105, 3069, 2375, 3647, 1217, 140, -2518, -4195, -3080, 2155, 66, -570, + 84, 1523, -742, 13326, 5544, -2653, -5484, -3816, -9239, -10794, 6967, 2095, -4231, -2102, 4368, 8737, + 2959, 3968, -2430, 4601, 317, 5804, -3547, -11099, 5849, 273, -5513, 767, -9421, -11095, 3029, 8472, + -518, 2355, 2733, 53, -1439, -2709, -394, 5355, -2408, -3122, 8729, 5660, 7771, 4999, -7588, -15134, + -2240, 2281, 6677, -5155, 5663, 266, -4355, -7052, -3825, -2235, -2745, -3212, -2018, 1828, 1971, 2086, + -1241, 699, -2126, 3835, 1147, 4456, -3810, -23, 1284, -4878, 3807, 14029, 2820, -6773, 9556, 6600, + -1716, 315, -3259, -3282, -2859, -2219, 3508, -3452, -7850, 623, -5558, -2168, 1842, -8228, -885, 15388, + -8177, -7705, -14377, -6808, -7099, -7676, -4141, -5548, 3677, 5846, 6160, 10031, 11318, 8141, 3326, 904, + -3072, 1139, 1875, 4811, 3767, 7294, 4507, 1476, -1622, -6385, 384, 3318, -3867, -10447, -6387, -4252, + -19, 1102, -6317, 3433, -1856, -5732, 7225, -2107, -6977, 9620, 7964, 3013, 7152, 4986, -2184, 2136, + -524, 1479, -923, 3729, -259, 227, 6477, 2660, 4208, 1017, -423, -6090, -13677, 5309, 702, 2721, + -822, 2175, 1717, 3580, 1133, 3835, 980, 13265, 6367, 2741, 7462, 6211, -2347, -7635, 4781, 4132, + -8168, 13481, 5777, -963, 643, -2853, -2086, -1593, -2092, 2348, 3867, 413, 461, 1644, -259, -1656, + -846, 1615, -2805, 935, 3206, 1907, 7862, 3901, -975, 4507, 3151, 1433, 15449, 4412, -1221, 1001, + -3952, 1411, -2148, -1025, -2553, -4164, -4725, -3465, -2654, -3828, -6151, -7679, -5881, -2007, -581, -2499, + -1744, 4546, -8725, -6274, -1364, -1087, -2198, -4504, -3542, -1966, -516, -802, 448, -162, -1277, -2081, + -12133, -10923, 10206, 4436, 611, -2300, -4926, -4708, -5138, -3373, 2358, 295, -370, 4406, 2947, 351, + 1477, 3584, 3776, 4714, -1508, 2029, 426, -5245, -2805, -5852, -8752, 199, -3945, 10358, 10127, 4852, + -1894, 528, -776, 2698, -1298, -7579, -12457, -12545, 2483, 2421, -140, 723, -395, -292, -4196, -1766, + -3071, 1449, -3716, 3712, -3017, 543, -391, -1984, 3301, 375, 1107, -2635, 4730, 870, -19666, -12653, + -2823, 3165, 5399, -10321, -6087, -2824, -329, -1699, -268, -1995, -2254, 2744, 319, 51, 2834, 452, + -2837, -240, -1298, 2244, 1977, 3061, 3676, -1207, -3774, -2607, -3405, 9701, 12102, -3052, -10263, 1164, + -1548, -515, -3862, 1117, 3329, 4105, -804, -4141, -9321, -3136, 1792, 3484, 2025, -6747, -11991, -10905, + -3361, -2922, -3472, 1165, -3055, -1620, -4751, -8940, -477, 1932, 1054, 4687, 5735, 5566, 2447, -778, + 1791, 3768, 602, -2421, -6876, 9505, 7350, 2428, -3175, -6252, -707, -3720, -7723, -42, 4292, -1141, + -2469, 269, -1028, 1057, -890, 383, -128, 821, -2854, -5548, -2437, -3349, 3935, 1474, 14267, 13393, + -3416, 14072, 1196, -3166, -4252, -711, 521, 2462, 5346, 1483, -4287, -7676, -5805, -321, 867, 475, + -1674, 1391, 539, -471, -5201, -25, 6911, -2142, 10454, 10963, 1353, -2831, -3219, -131, -3005, -4468, + 3476, 4986, 6318, -2959, -9204, -87, 3906, -833, -247, 5687, 451, 716, -2970, -5788, -6743, -9436, + 4831, 6767, 3852, 2164, -1362, -1404, -3260, -4807, 2809, -2699, -4693, 21984, 10803, 4063, 2353, 6177, + -2813, -890, -5363, -165, -5755, -20361, 3639, 4639, -2073, 1798, -1097, -6169, 30, -1827, -4590, -2586, + -5855, -6418, -10115, -6038, 2674, 3620, 1206, 1379, -520, 5333, 5334, 3618, 439, -1048, 439, 777, + -7871, 2657, -3649, 7671, 10875, 5285, 423, 1869, -2283, -6081, -2750, -3935, -1815, 2851, 754, -2545, + -2253, -245, 87, 3432, 4323, 803, -3981, -8416, -12174, 6263, 9281, 7472, 2558, 327, -3198, -1436, + -1398, -211, -6595, 4670, 63, 2041, -4372, 967, 2444, -9123, -11355, 1727, -4221, -3144, 6411, 4338, + -4409, -3256, -6504, 6064, 4055, -2268, 5638, 5466, 82, -516, 6974, 5206, 1235, -364, -4919, -6016, + 2, 7, -5, 5, 1, 2, -8, 4, 4, 2, 4, 5, 0, -1, -3, 1, + -1139, 1101, -1501, -3122, 2059, 9130, 5593, -2976, -5845, -8198, 10800, 771, -4815, 20594, 5385, 9434, + -497, 877, -5365, -1190, -2940, -6216, 4700, 872, -2276, 9901, 5530, 417, -4381, -9743, -1935, -1025, + -3555, -643, -5254, -6674, -6586, -4879, -3791, -2733, 1046, 2275, 3157, 3643, 8384, 10607, 11929, 9237, + 1573, 3323, 130, 12128, 9521, 6522, 4035, -1444, -7190, 565, 2160, -2808, -3716, -9398, -1115, 4631, + -1938, -2034, -5142, 6407, 5972, 302, -3078, -7362, -12229, 6591, 5640, 1240, 2727, 3243, 9738, 7334, + -8793, 935, -4176, 103, 2398, 1724, 1579, 7649, 5685, 2791, 1754, -453, -5030, -4870, -3871, -3139, + -243, 3111, -2068, 3022, -4587, -11340, 14571, 7771, 3558, 5750, 1203, 4665, -1981, -109, 4442, 1369, + -2041, 3713, 1013, 1345, 4716, 129, 3062, 1444, -3639, -6184, 7457, 7819, 958, -8391, -8799, 9312, + 235, 3895, 12172, 2716, -1347, -1094, -4869, -880, 7519, 9011, 9914, 5683, 5909, 7805, 4428, 2129, + -1538, -36, -678, 1486, -649, 1517, -5121, 8530, 5048, -1844, -4781, -9145, -11353, -8076, -4133, -307, + -2707, 80, -5905, -4315, -4389, -6758, -6105, -9003, -10744, -1701, 3765, 6091, 10523, 7504, 4350, 4312, + 786, 3663, 9280, 6578, 391, 1514, -7019, 5089, 3483, -6871, -8172, -180, -7469, 1419, -121, 838, + 2692, 6995, 1431, -1074, 1394, -268, -1170, -3367, -7586, -5698, 7587, 7378, 5733, 8353, 10152, 10834, + -8158, -6271, -9914, 9985, 5364, -2601, -1959, -6260, -4097, 3235, 2097, -196, 2968, 3371, 2095, -1207, + -2269, 648, -1910, 7766, 5356, 3667, 981, 2825, 4288, 6668, 696, -661, 4042, -5356, -12858, -3646, + -4703, -3239, 10100, -2312, -256, -2120, -2612, 4835, -1675, 1068, 5746, -140, -869, 3620, 3505, 1703, + -3250, -2423, -1423, -674, -4843, 10905, 4109, 635, -1606, -6241, -2449, 3295, 6275, 14389, 8002, 4352, + -842, 3170, 1430, 1513, -4583, -12820, 1470, -4220, -8952, 6987, 4718, 532, -2136, -3700, -1727, 4512, + -3663, -2257, -8998, 5471, 843, -2858, -4142, 5134, 7250, 525, 3002, 118, 423, 6929, 5389, -1003, + -3457, -2564, 4399, 5758, -1462, 9992, 2582, 885, 6350, -670, -4446, -5882, -1814, -1178, -3073, 1157, + 2529, 7505, 5440, 202, -5746, -976, 8235, 1049, -181, -142, -6919, -6675, 18283, 16554, 8385, 3001, + 2266, 12753, -3253, -3832, -7200, -5627, -4778, -925, 239, 539, 2225, 324, 3182, 1914, -309, -507, + 5074, 4381, 9167, 1915, -3908, 1754, -5997, 2537, 17796, 13293, 7314, 12286, 1815, -4329, -8064, -20774, + -2484, 4942, 14515, 5406, -2595, -1380, 8417, 5956, 1651, 1559, -1389, 24, -6421, -4047, 2557, -1331, + -3164, 848, 15096, 9663, 6043, 3180, 595, 2733, 830, 1861, 9051, 8435, 8904, 6571, 2208, -762, + -135, 870, -2484, -3227, -9497, -586, 14177, 5880, -3708, 505, -1483, -415, 2507, -1973, -13853, -8468, + -3854, -2420, -9258, -4766, -3435, -2360, 10467, 7572, 598, -4099, 3457, 402, -195, 4193, 2023, 1851, + -4359, -3760, -1315, -585, 11411, 2958, 5446, 1608, 228, 4691, 1446, -1971, -3898, -3822, -1651, -1697, + 5112, 1738, -12375, 11069, 8416, -139, -721, 740, -8678, -7527, 10378, 4791, 5388, 2724, 4652, 1931, + -1419, 520, -6325, 10393, 8379, 2544, -2104, -11110, 7461, 2884, -1766, 548, -217, -2709, -1287, -2598, + 1996, 4969, 3862, 5813, -629, -7138, 7107, 9009, 5157, 1564, 5244, 1326, 78, 263, -4389, -5858, + -5423, -34, 1648, 2316, -3981, -5525, -1762, -996, 2075, 878, 718, 1458, 613, 3914, 3912, 2074, + -1176, 643, -3222, -444, 779, 9634, 14238, 11755, 3727, 1970, -1421, 3653, 1795, -2315, 10947, 8623, + 19, 6095, 3277, 2648, 2148, 509, 3577, 978, 1862, 5842, 1302, -3853, -10993, -12406, 858, 7763, + -4944, -1993, -5563, 833, -1365, -2240, -25, 2546, 10150, 10369, 10670, 10551, 9322, 5582, 881, -1029, + -763, 4474, 9314, 8818, 2703, 4844, 7776, 1684, 1, -3980, -9739, 5565, 2667, 1185, 2203, 1611, + -635, 724, -4112, 8414, 3049, 1437, 2314, -2611, -5835, 5541, -3027, 1017, 14246, 10165, 9910, 14393, + 2201, 3204, -295, 2519, -855, 5303, -2184, -12725, 10839, 1337, 154, -5290, -7908, 9490, 4292, 5533, + 544, 3574, 602, -783, -3121, 21721, 8166, -1137, 4729, -2399, 2504, 3721, -2704, -10309, 4957, 8028, + 2782, 11109, 5440, 2691, -3942, 3286, 2848, -532, -186, -2661, 7318, 6015, -1200, 2174, 5498, -379, + 4440, 6050, 3576, -819, -3697, 13144, 9664, -2178, 2966, 3302, -623, 10572, 15713, 9000, 2137, -5160, + -1593, 613, 3985, -7128, -5989, 2429, 721, -5488, -11848, 981, -3054, -4499, -4102, -7743, -7416, -340, + -2759, -2449, -4426, -6796, -13804, -7472, -1409, -1103, 181, 3071, 434, -741, 1045, 1976, 1407, 1365, + -2578, -1275, 5323, 9313, 4798, -1130, -6220, -2101, -3402, -868, -1959, -4365, -4536, -1626, -3701, -5011, + -3479, -3407, -9706, 4812, -812, -4014, 2558, -5416, -10543, -5186, -3840, 1189, 3804, 5839, 4744, 1003, + -3585, -2339, -4745, 3869, -2763, 1306, -6059, -8604, -1377, -5116, -730, -1693, -3321, 888, -685, 876, + -3492, 910, -7012, -2555, -5147, -1372, -1910, -8518, 2661, 7652, 6967, 7296, 4514, -4741, -9827, 873, + -1258, 4649, 3654, 653, -5264, -5509, -4222, 1703, 3992, -5102, -4342, -6447, 6603, 2642, -923, 6242, + -992, 647, 1228, -3124, -3463, 15067, 838, -6186, -3433, 872, 97, 2876, 3686, -2643, -6780, 356, + -1727, 2555, 2552, -1938, -8798, -773, -757, -3588, -7005, -6121, 4601, 235, -4446, 2984, 1353, -776, + -15055, -12154, -6273, 84, 390, -3286, -4758, -3713, -2185, -1512, 1403, 3479, 7578, 6327, 5045, 3075, + 2469, 8960, 6679, 3813, 1059, 9183, 2971, 4300, -1040, -927, -2376, -6240, -5131, -6030, -7385, -7560, + 933, 4512, -899, -1226, -7230, -10649, 11249, 4655, -7924, -5423, -5107, 993, 588, 2896, 4305, 1369, + -1938, 11282, -2696, -7285, 1163, -6289, -344, -2329, 3632, 2191, -1017, -1404, -2305, -6223, -2822, -1369, + -3688, -918, -3118, 256, -5446, 8638, 6195, 2855, 7432, 6937, 8638, 4020, -3296, -4260, 21, -3914, + 3006, 5845, 16377, 17059, 3579, 103, 204, -563, 1735, 6204, -405, -2618, -7929, -14028, -9415, -5277, + 303, 934, -305, 3211, -2970, 2963, 10231, 2833, 1656, 1162, -4439, 6346, 9314, 7062, -5015, -15980, + -320, 499, -14803, 4610, 2112, -4049, 7242, -245, -3115, 1323, -1276, -4286, -1951, 100, -1389, -1612, + -4391, -2691, -5202, -11000, 373, -2423, 4221, 4146, 1045, 503, -4063, -2244, 2311, 1646, -1779, -3188, + -3374, 346, -3243, -3662, 5971, 5519, 3022, 516, -4538, -6550, -5227, -6165, -4919, -1105, 30, 721, + 2935, 3922, -1041, 4217, 2528, 1985, 661, -824, -10133, -13715, 8714, 2218, 3769, 3384, 1193, -6246, + -5357, -2959, -8106, 5394, 1542, -4964, -7749, -4183, 877, 1146, 8307, 2891, -4905, -5775, 1888, 1442, + -2472, -850, 1278, 1397, -4545, -3625, -11722, 9811, 7790, 7832, 12234, 6079, -2436, -890, -1820, -234, + -3905, -1081, -7818, 2577, -299, 5742, 4982, -1421, 3506, -604, -4944, 2130, 544, 1545, -2399, -3202, + -895, -203, 783, -203, -2734, 10200, 7718, 3943, -6098, 9859, 9374, 6777, 2263, -2089, 866, 3381, + -3828, 1991, -2866, -1612, 747, -3896, 6041, 2875, -5838, -6829, -2319, -1146, -8845, -10612, 3630, 2942, + -509, 5457, 1119, -3222, -3623, -6421, -9746, -8661, 5658, 8283, 8062, 6310, 1787, 454, 1766, 2750, + -1632, 7787, 5349, 243, -1526, 3143, 5218, 10290, 1446, -6324, -3035, -1055, 2974, -7871, 39, 3664, + -769, -9, -8896, 9699, 4546, -1295, 6107, -4534, 3367, 1450, -3607, 8816, 3219, -5601, 1298, 12366, + -7130, -4420, -6848, 3453, 3599, 4371, 609, -6059, 8057, 9067, 2408, -3523, -6908, -6822, -6636, -2017, + -477, 5145, -1462, -475, -2003, -3769, 7781, 4563, 4437, 2134, -2726, 15777, 2839, -1929, 2913, 2174, + 841, 2396, 754, 14163, 4130, -1807, -177, -3884, -6782, 9287, 1864, -599, 5913, -2587, -10749, 5856, + 1304, 7980, -2237, -2092, -4384, -828, 552, -6108, 2193, 10107, 6057, 9885, 13003, 8977, 4006, -926, + -1523, 1282, -1805, -2709, -6024, -7618, -10251, 832, -689, -1488, 1528, -1635, -4512, -3974, 3366, 5884, + -2891, -646, -4227, -16787, 4586, 2689, -48, 1956, -5398, -5693, 4030, 1138, 2292, 2634, 6453, 3271, + -3526, 9059, 2896, 8101, 3313, -270, -1336, -3002, 826, -1572, -3793, -2235, -1597, 272, 910, -778, + -1195, 3634, 1576, 2036, -3675, -10512, -6414, -3268, -9714, -6636, 3287, -947, 6643, 7755, 4317, 2928, + -592, -46, -6118, -3775, 11750, 5301, -2878, -7240, -4674, 1543, -626, -1300, -608, -1661, -4053, -3154, + -2514, -545, 771, 7292, 3641, 749, -1664, -1652, 2686, 8715, 10176, 4547, -6065, -7417, -6454, -4928, + -576, 940, 681, 2977, -2947, -1968, -6468, 10093, 7720, -2235, -3869, -8057, -4152, 7399, 8617, 5658, + -1043, 1637, -3699, -5968, 13092, 1526, 1185, -3128, -2234, 3343, 5773, 9935, 7870, 6240, 3284, 3932, + 377, 5872, 3528, 3824, -852, -1575, -3799, -8401, -5628, -3612, -2451, 1396, 1471, -1669, -579, -384, + -6978, -4522, -6731, -1881, 1485, -73, -38, -3990, 11379, 4104, 1154, 5492, 3709, -645, -641, -750, + -97, 2556, 1619, 3351, 1996, 10845, 8411, 2751, 3099, -165, -6582, -11822, 8128, 7722, 4495, 3322, + 950, 2744, -2039, -3959, -6098, -2113, 4512, -1699, -758, 3243, -4760, 7788, 11837, 5336, 7626, 5509, + -4876, 13906, -3059, 1351, 4037, 2283, 614, -5014, 2149, 613, 744, -4239, -5981, -4296, -1799, -3121, + -2111, 3530, -1221, 1654, 9442, 10361, 6422, 7826, 7510, 7790, 3836, -323, -761, 1652, 330, -386, + -3239, 3070, 7009, -1209, 6710, 213, 5225, 3105, 1173, 842, -1774, -5027, -3901, -1359, -2786, -3513, + 1481, 1904, 7402, 23443, 5946, -3615, -1528, -4317, -2629, 11277, 7171, 5620, 7938, 4715, 3575, -3794, + 2315, 5200, 63, 4010, -400, -2074, 6624, -516, -731, -2133, -10088, 6969, -3380, -7450, -7347, -6915, + -3407, -3447, -1422, -4020, -11809, 3562, 3865, 570, 7656, 6367, 5964, 802, -2306, 5862, 7700, 6476, + -17049, -2577, 3748, -1004, 990, 2569, 4487, 2137, -3540, -3508, 608, -2102, 90, 4634, 3115, 1273, + -1960, -1414, 1516, 9460, 6833, 2088, -3598, -3590, -2554, -1783, 2680, 2127, 939, 8562, 4170, 1914, + 3335, 6241, -2988, 1816, 3233, -951, 587, -5590, -3415, -926, -7987, 8897, 3700, -12712, 5722, 4683, + -756, 1823, 2804, 3392, -2019, 801, -2923, 43, 5720, 2302, 3604, 14791, 4960, -425, -7298, -6606, + 205, 5909, 8599, 4641, -4600, -1580, -4536, -5178, 2346, 6910, 3641, -2630, -6079, 351, 5478, 5524, + 151, 1252, -2569, 6834, 5377, 4284, 450, -1607, 7257, 4429, -2568, 9851, 9183, 2197, 20053, 9155, + -1462, 924, -3196, -3257, -8953, 6147, 6251, -3186, 3285, 3198, 2326, 1225, -8446, -11295, 5393, 10785, + -2381, -2014, -9329, 4719, -880, -2308, -4714, 4429, 3675, -1874, 3253, 9686, 12557, 9338, 4719, 3836, + -3103, 7031, 11258, 6883, 11690, 8131, 3644, -307, -2590, -274, 1004, -1314, -166, 3063, 695, -1815, + -2455, 811, -1161, 2731, 5931, 2352, 3361, -363, -7371, 2805, 4053, 3586, 7364, 242, -1692, 17531, + -4497, -535, 286, 214, 3804, 11412, 4562, -1157, 550, 4841, 1657, -4984, -6307, 1482, 5745, 3540, + -2763, -1313, -1385, 3735, -2423, 5601, 14635, 10815, 9726, 6141, 4010, 3556, -104, -3353, -7143, 7077, + -245, 8209, 15457, 5234, 1860, -2195, -4620, -4895, -4263, -759, 2016, 2664, 3153, 2966, 1601, 30, + -4764, -1351, 3227, 2660, 1556, 198, 5379, 11277, 8580, 6978, 2506, 3310, 13165, 9623, 7120, 1665, + -59, 558, 3194, 1299, -2918, -2455, 3754, -3394, -3634, -2782, -7987, -7903, -7058, -2214, -1060, 2183, + -1954, -186, -11418, -2859, -1110, -2027, -932, -2040, 1282, 174, -161, -2628, -3341, 2675, 4169, 2475, + -5934, -5196, 10580, 9382, 1417, -1362, -2572, -4391, 7418, 4314, 148, 31, -82, 461, -2595, -570, + -3639, -2081, -1014, 4355, 5943, 6217, 2491, -4106, -6520, -4050, -5030, -2053, 6821, 6135, 2456, 1015, + -3447, -1303, -5380, -6759, -3272, -129, -4989, -11231, 5106, 1264, -3433, -3327, -3139, -1282, 1031, 1558, + 4180, 1592, -3435, 2252, -4803, -6443, 8937, 1696, -5599, 9240, 5481, -328, 3197, -4392, -12452, -16482, + -4613, 5693, 11596, -9035, 1399, 1388, 5182, 4750, 958, 310, -866, 829, 5122, 1203, -115, -759, + -3551, -1843, -3272, -1753, -195, 17324, 8182, -502, -2987, -146, -2640, 6865, 6979, -3675, -6047, 12865, + 3739, 8307, 5634, -2783, 96, 1167, -274, -636, -5808, -8880, 835, 6363, 5092, -700, -8229, -7634, + -6799, -5871, 4391, 1265, -1493, 440, -7322, 2387, 1763, -1406, 4030, 8075, 8810, 5655, 1375, 2309, + 3191, 6527, 2671, -128, -5345, 14221, 13006, 1792, -548, -2974, -7549, -3471, 1835, -1490, -3556, -4240, + -3368, -1748, -3945, 8349, 2444, -5349, 5825, 4222, -1891, -3570, -10832, 8764, 2791, 5495, 9332, 5366, + 1020, 5766, -8313, 522, -568, -20, -2169, 3981, 6641, 4235, 1781, -4362, -7143, -3864, -2205, -3217, + -3300, -1346, -1200, 5950, -1315, -285, 2642, -180, 12986, 11560, 5996, 6755, -2578, -1417, 1848, 5560, + 10662, 13080, 11225, 419, -4335, -128, 6716, 1638, -4903, 154, -2404, -4228, 5262, -364, -5170, -12310, + 360, 1588, 2173, 8939, 4304, 7241, 367, -2361, 6569, 837, -4801, 8650, 7208, 5996, 3566, 1112, + -5017, 4300, 2649, 3064, -6110, -14292, 2204, 13008, 5245, 1594, -6536, -11045, 5146, -211, -4067, -11435, + -530, 1840, 187, -12175, 1984, -1576, 3659, 4293, -1971, 8025, 8287, 4420, 3935, 358, -1691, -2707, + -3429, 252, 1235, 3895, 13024, 5900, 317, 1720, 3724, 1510, -3576, -6091, -8218, -3620, -844, -406, + 2105, 7096, 3064, 3952, 2071, -2774, 8459, 1501, -10913, 1387, -405, 12863, 2328, 4475, 3498, -1584, + -3085, -920, -7032, 8494, 2146, 1346, 1867, -404, 1886, -1042, -378, -2121, -10433, -7336, 15525, 9808, + -15685, -7623, 1925, 2963, 4001, -105, 3843, 5498, 4039, 6151, 6044, 3867, 1730, 2971, 1484, -319, + 3080, 9412, -1223, -3973, 4734, 2248, 3127, 1119, -1738, -1669, -1477, -1472, 1412, 1213, 773, 1674, + -730, 2282, 495, 1849, 753, 4313, 2052, 11060, 2638, -4153, 12967, 4232, 1600, 8305, 6247, 4101, + 1078, -516, -6160, -2738, -3949, 549, 2665, 313, -11805, 5780, 13753, 4964, -3343, -3825, 7392, 657, + -3356, -672, 2091, 1930, -1942, -6931, -7983, -7306, 1452, 3417, 9758, 12537, 14305, 11570, 5653, 1593, + 2820, 8229, 5573, 6212, 5169, 4568, 4877, 1219, -5520, -3569, -4997, 3799, -1152, -6233, 13054, 8210, + -1905, -1112, -1728, 19102, 8663, -331, 3226, 1066, -1807, 8189, 5678, 1987, 4661, 3278, 7947, 11458, + -4574, -517, -5124, 4711, -740, 416, 4847, 4427, 11056, 3251, -1915, -3528, -2529, -2213, 1857, 1203, + 316, 3731, 4619, -1294, -3138, -336, 8691, 7311, 3124, 9892, 5880, 614, 1873, 1916, 3856, 3588, + 1323, 8284, 7332, 4197, 626, 4877, 9117, 4163, 1998, 4387, 5489, 4184, 2124, -5170, -10914, 3921, + -1504, 12727, 938, 3478, 1876, -1017, 389, 3233, 8278, 8027, 8392, 12663, 13264, 9858, 5767, 4287, + -4008, 49, -1854, -5454, -9369, 5309, -1597, 6002, 6031, -2543, -4793, -2340, -2559, 229, -983, -2068, + -3514, 815, -7510, -3824, -931, -1573, -1337, -1189, -2019, 245, 4084, 4416, 6165, 7239, 3899, 2461, + -4781, -2173, 17577, 2751, -894, 2264, 1789, -623, 992, -322, -3113, -1854, -1553, 2213, 731, 850, + 2054, 3456, 3747, 3842, 980, -940, -5065, -5905, 423, -2009, 74, 3933, 13511, 12742, 8908, 5783, + 894, 6872, -2742, 7127, 5497, -660, -2361, -3114, -5552, -884, -1825, -8536, 4278, 4047, 3263, 2117, + 46, 3829, 3392, 7000, 5004, 11640, 7090, 2661, 2072, 3834, 6408, 9453, 4328, -5807, -11811, -6081, + 1119, 3292, 8329, 5549, -1361, -4414, -15806, 7144, 6824, -4515, -1143, 4774, 1451, 5261, 4830, 5562, + -1393, 5662, 4446, 1807, 8826, 6248, 6415, 4547, -1665, 1181, 6405, 5864, 8293, 10387, 7545, 4688, + 1312, 7883, 6317, -3965, -8535, -2725, 1117, -5447, -7012, 3655, 3196, 4576, 6822, -341, -646, 6098, + -6332, -4527, -5839, 4942, 2805, 6652, 925, -1187, 3859, 4466, 5194, 4814, 7489, 8532, 2922, 2874, + -1137, 1068, 2253, 3741, -2505, 9887, 10247, 3472, 9158, 1176, -2976, 1937, -2064, 7351, 6057, 2696, + 532, 4702, 4601, 502, -1350, -5364, 9112, 2103, -4340, 18, -1329, -2532, 2939, 15707, 4071, -2154, + -628, 13794, -2239, -2982, -3391, -2332, -1483, 5699, 7418, 5487, 5469, 3426, 2471, 2248, -610, -2978, + 4520, 7035, 8360, 8190, 4367, 11231, 9045, 6518, 5468, 6414, -626, -2179, -2327, -6601, -11740, -18010, + 872, 6597, 9823, 6115, 5121, 3028, -3065, 9266, 9664, 2144, 2461, -758, -3373, -348, -421, -2786, + -2998, -2310, 5826, 14327, 10399, 10344, 5906, 4646, 4013, 7488, 6656, 3601, 212, 2499, 812, -4251, + -3455, -259, -2801, -3743, -3930, 4402, 11531, 8368, 3812, 2663, -1885, -3062, -3413, -12432, -6348, -1832, + -2574, 1227, -6578, -7396, -131, 1139, 3464, 2303, 6848, 4302, 422, 1994, 4840, 6023, 4369, 1222, + -5186, -3043, -5221, 9413, 9009, 6329, 6302, 7712, 4428, -1745, -1711, 1216, 1855, 1215, 1003, 58, + 3844, 4380, -2452, 17587, 5229, 106, 3809, 5238, 2909, -6280, 6367, 4649, 3777, 2815, 4377, 9833, + -3469, 6722, -2982, 1867, 2944, 3428, -115, -6063, 4740, 2369, 3681, 2580, 319, 76, 4169, 1079, + 5357, 7937, 8749, 6732, 3237, 475, 10599, 7708, 2300, 9384, 6872, 6516, 11437, 2109, -2788, -10922, + -2925, 1420, 3109, 500, 6953, 1289, -522, 1064, 2885, 6445, 3595, 2000, 2669, 2797, 2174, 873, + 1980, 6159, 1331, 1321, -1922, 6722, 11666, 3321, -1515, 1233, -1664, 9262, 9668, 2502, 13862, 9666, + 3582, 10575, 2715, -603, 596, -1567, 4182, 49, 2208, 1795, 10525, 9472, -2866, -8439, 7591, 11197, + -2356, 153, -10244, -4768, -2178, -2408, 1367, 708, 4615, 9681, 13007, 14875, 15382, 12708, 8355, 5074, + -358, 1803, 1987, 7888, 9168, 16089, 2288, -2716, -1669, 1078, 1165, 5324, 4412, -4354, 298, 6519, + 4826, 9355, 6507, 12087, 4177, -6, 2865, -2898, -5149, 6100, -1829, 80, 12459, 4967, 591, 7846, + -3452, 13887, -142, 4052, 5842, 3702, 4535, 2718, 4976, 3690, 1377, -72, -1938, -836, 961, -1944, + 4315, 5391, 6496, 1795, -2279, 20485, 16142, 9768, 8889, 6390, 1789, 3149, 4186, 487, -922, -2249, + -1225, 14246, 10277, 980, 2427, 180, 5713, 4730, -901, 590, 3351, 1871, 4389, 4760, 8650, 3433, + 1760, 3580, 5798, 6813, 4246, 17695, 7227, 4364, 2222, 13912, 11731, 10965, 14919, 7273, -6023, 6474, +}; + + +const Word16 win_lpc_shb_fx[(L_LOOK_12k8 + L_SUBFR + L_FRAME) * 5/8] = +{ + /*Q15 */ + 1, 4, 10, 18, 28, 40, 54, 71, 89, 110, 134, 159, 186, 216, 248, + 282, 318, 357, 397, 440, 485, 532, 581, 632, 686, 741, 799, 859, 921, + 984, 1050, 1119, 1189, 1261, 1335, 1411, 1490, 1570, 1652, 1736, 1823, + 1911, 2001, 2093, 2187, 2283, 2381, 2481, 2582, 2686, 2791, 2898, 3007, + 3118, 3230, 3345, 3461, 3579, 3698, 3819, 3942, 4067, 4193, 4321, 4451, + 4582, 4715, 4849, 4985, 5123, 5261, 5402, 5544, 5687, 5832, 5978, 6126, + 6275, 6426, 6577, 6730, 6885, 7041, 7197, 7356, 7515, 7676, 7837, 8000, + 8164, 8329, 8496, 8663, 8831, 9001, 9171, 9342, 9515, 9688, 9862, 10037, + 10213, 10390, 10567, 10745, 10924, 11104, 11285, 11466, 11648, 11830, 12013, + 12197, 12381, 12566, 12751, 12937, 13123, 13310, 13497, 13684, 13872, 14060, + 14249, 14438, 14627, 14816, 15006, 15195, 15385, 15575, 15765, 15955, 16146, + 16336, 16526, 16716, 16907, 17097, 17287, 17477, 17667, 17856, 18046, 18235, + 18424, 18612, 18801, 18989, 19176, 19364, 19551, 19737, 19923, 20109, 20294, + 20478, 20662, 20846, 21028, 21210, 21392, 21573, 21753, 21932, 22111, 22289, + 22466, 22642, 22818, 22992, 23166, 23339, 23510, 23681, 23851, 24020, 24188, + 24355, 24520, 24685, 24848, 25011, 25172, 25332, 25491, 25648, 25804, 25960, + 26113, 26266, 26417, 26567, 26715, 26862, 27007, 27152, 27294, 27435, 27575, + 27713, 27850, 27985, 28119, 28251, 28381, 28510, 28637, 28762, 28886, 29008, + 29129, 29248, 29364, 29480, 29593, 29705, 29815, 29923, 30029, 30133, 30236, + 30337, 30435, 30532, 30627, 30720, 30811, 30901, 30988, 31073, 31156, 31238, + 31317, 31394, 31469, 31543, 31614, 31683, 31750, 31815, 31878, 31938, 31997, + 32054, 32108, 32161, 32211, 32259, 32305, 32349, 32390, 32430, 32467, 32502, + 32535, 32566, 32595, 32621, 32645, 32667, 32687, 32705, 32720, 32734, 32745, + 32753, 32760, 32765, 32767 +}; + +#define SHC(x) ((Word16)x) + +const Word16 cos_coef_new[4]= { SHC(0x02BA), SHC(0xE60A), SHC(0xEEEF), SHC(0xAAAB)}; + +/*Sachin: New table. cos_diff_table[i] = sub(cos_table[i+1],cos_table[i]) */ +const Word16 cos_diff_table[512] = +{ + SHC(0xFFFF), SHC(0xFFF8), SHC(0xFFF4), SHC(0xFFEF), SHC(0xFFE9), SHC(0xFFE5), SHC(0xFFE0), SHC(0xFFDB), + SHC(0xFFD6), SHC(0xFFD2), SHC(0xFFCC), SHC(0xFFC7), SHC(0xFFC3), SHC(0xFFBE), SHC(0xFFB8), SHC(0xFFB4), + SHC(0xFFB0), SHC(0xFFAA), SHC(0xFFA5), SHC(0xFFA1), SHC(0xFF9C), SHC(0xFF97), SHC(0xFF92), SHC(0xFF8E), + SHC(0xFF89), SHC(0xFF84), SHC(0xFF80), SHC(0xFF7B), SHC(0xFF76), SHC(0xFF71), SHC(0xFF6D), SHC(0xFF69), + SHC(0xFF64), SHC(0xFF5F), SHC(0xFF5B), SHC(0xFF56), SHC(0xFF52), SHC(0xFF4D), SHC(0xFF49), SHC(0xFF45), + SHC(0xFF40), SHC(0xFF3C), SHC(0xFF38), SHC(0xFF33), SHC(0xFF2F), SHC(0xFF2B), SHC(0xFF27), SHC(0xFF23), + SHC(0xFF1E), SHC(0xFF1B), SHC(0xFF16), SHC(0xFF13), SHC(0xFF0E), SHC(0xFF0B), SHC(0xFF06), SHC(0xFF03), + SHC(0xFEFF), SHC(0xFEFB), SHC(0xFEF8), SHC(0xFEF3), SHC(0xFEF1), SHC(0xFEEC), SHC(0xFEE9), SHC(0xFEE5), + SHC(0xFEE2), SHC(0xFEDF), SHC(0xFEDB), SHC(0xFED8), SHC(0xFED4), SHC(0xFED1), SHC(0xFECE), SHC(0xFECB), + SHC(0xFEC7), SHC(0xFEC5), SHC(0xFEC1), SHC(0xFEBF), SHC(0xFEBB), SHC(0xFEB9), SHC(0xFEB6), SHC(0xFEB3), + SHC(0xFEB0), SHC(0xFEAE), SHC(0xFEAB), SHC(0xFEA8), SHC(0xFEA6), SHC(0xFEA3), SHC(0xFEA1), SHC(0xFE9F), + SHC(0xFE9C), SHC(0xFE9A), SHC(0xFE98), SHC(0xFE95), SHC(0xFE94), SHC(0xFE91), SHC(0xFE8F), SHC(0xFE8E), + SHC(0xFE8B), SHC(0xFE8A), SHC(0xFE88), SHC(0xFE86), SHC(0xFE85), SHC(0xFE83), SHC(0xFE81), SHC(0xFE80), + SHC(0xFE7F), SHC(0xFE7D), SHC(0xFE7B), SHC(0xFE7B), SHC(0xFE79), SHC(0xFE79), SHC(0xFE77), SHC(0xFE76), + SHC(0xFE75), SHC(0xFE74), SHC(0xFE73), SHC(0xFE73), SHC(0xFE72), SHC(0xFE71), SHC(0xFE71), SHC(0xFE70), + SHC(0xFE6F), SHC(0xFE70), SHC(0xFE6E), SHC(0xFE6F), SHC(0xFE6E), SHC(0xFE6E), SHC(0xFE6E), SHC(0xFE6E), + SHC(0xFE6E), SHC(0xFE6E), SHC(0xFE6E), SHC(0xFE6E), SHC(0xFE6F), SHC(0xFE6E), SHC(0xFE70), SHC(0xFE6F), + SHC(0xFE70), SHC(0xFE71), SHC(0xFE71), SHC(0xFE72), SHC(0xFE73), SHC(0xFE73), SHC(0xFE74), SHC(0xFE75), + SHC(0xFE76), SHC(0xFE77), SHC(0xFE79), SHC(0xFE79), SHC(0xFE7B), SHC(0xFE7B), SHC(0xFE7D), SHC(0xFE7F), + SHC(0xFE80), SHC(0xFE81), SHC(0xFE83), SHC(0xFE85), SHC(0xFE86), SHC(0xFE88), SHC(0xFE8A), SHC(0xFE8B), + SHC(0xFE8E), SHC(0xFE8F), SHC(0xFE91), SHC(0xFE94), SHC(0xFE95), SHC(0xFE98), SHC(0xFE9A), SHC(0xFE9C), + SHC(0xFE9F), SHC(0xFEA1), SHC(0xFEA3), SHC(0xFEA6), SHC(0xFEA8), SHC(0xFEAB), SHC(0xFEAE), SHC(0xFEB0), + SHC(0xFEB3), SHC(0xFEB6), SHC(0xFEB9), SHC(0xFEBB), SHC(0xFEBF), SHC(0xFEC1), SHC(0xFEC5), SHC(0xFEC7), + SHC(0xFECB), SHC(0xFECE), SHC(0xFED1), SHC(0xFED4), SHC(0xFED8), SHC(0xFEDB), SHC(0xFEDF), SHC(0xFEE2), + SHC(0xFEE5), SHC(0xFEE9), SHC(0xFEEC), SHC(0xFEF1), SHC(0xFEF3), SHC(0xFEF8), SHC(0xFEFB), SHC(0xFEFF), + SHC(0xFF03), SHC(0xFF06), SHC(0xFF0B), SHC(0xFF0E), SHC(0xFF13), SHC(0xFF16), SHC(0xFF1B), SHC(0xFF1E), + SHC(0xFF23), SHC(0xFF27), SHC(0xFF2B), SHC(0xFF2F), SHC(0xFF33), SHC(0xFF38), SHC(0xFF3C), SHC(0xFF40), + SHC(0xFF45), SHC(0xFF49), SHC(0xFF4D), SHC(0xFF52), SHC(0xFF56), SHC(0xFF5B), SHC(0xFF5F), SHC(0xFF64), + SHC(0xFF69), SHC(0xFF6D), SHC(0xFF71), SHC(0xFF76), SHC(0xFF7B), SHC(0xFF80), SHC(0xFF84), SHC(0xFF89), + SHC(0xFF8E), SHC(0xFF92), SHC(0xFF97), SHC(0xFF9C), SHC(0xFFA1), SHC(0xFFA5), SHC(0xFFAA), SHC(0xFFB0), + SHC(0xFFB4), SHC(0xFFB8), SHC(0xFFBE), SHC(0xFFC3), SHC(0xFFC7), SHC(0xFFCC), SHC(0xFFD2), SHC(0xFFD6), + SHC(0xFFDB), SHC(0xFFE0), SHC(0xFFE5), SHC(0xFFE9), SHC(0xFFEF), SHC(0xFFF4), SHC(0xFFF8), SHC(0xFFFF), + SHC(0x0001), SHC(0x0008), SHC(0x000C), SHC(0x0011), SHC(0x0017), SHC(0x001B), SHC(0x0020), SHC(0x0025), + SHC(0x002A), SHC(0x002E), SHC(0x0034), SHC(0x0039), SHC(0x003D), SHC(0x0042), SHC(0x0048), SHC(0x004C), + SHC(0x0050), SHC(0x0056), SHC(0x005B), SHC(0x005F), SHC(0x0064), SHC(0x0069), SHC(0x006E), SHC(0x0072), + SHC(0x0077), SHC(0x007C), SHC(0x0080), SHC(0x0085), SHC(0x008A), SHC(0x008F), SHC(0x0093), SHC(0x0097), + SHC(0x009C), SHC(0x00A1), SHC(0x00A5), SHC(0x00AA), SHC(0x00AE), SHC(0x00B3), SHC(0x00B7), SHC(0x00BB), + SHC(0x00C0), SHC(0x00C4), SHC(0x00C8), SHC(0x00CD), SHC(0x00D1), SHC(0x00D5), SHC(0x00D9), SHC(0x00DD), + SHC(0x00E2), SHC(0x00E5), SHC(0x00EA), SHC(0x00ED), SHC(0x00F2), SHC(0x00F5), SHC(0x00FA), SHC(0x00FD), + SHC(0x0101), SHC(0x0105), SHC(0x0108), SHC(0x010D), SHC(0x010F), SHC(0x0114), SHC(0x0117), SHC(0x011B), + SHC(0x011E), SHC(0x0121), SHC(0x0125), SHC(0x0128), SHC(0x012C), SHC(0x012F), SHC(0x0132), SHC(0x0135), + SHC(0x0139), SHC(0x013B), SHC(0x013F), SHC(0x0141), SHC(0x0145), SHC(0x0147), SHC(0x014A), SHC(0x014D), + SHC(0x0150), SHC(0x0152), SHC(0x0155), SHC(0x0158), SHC(0x015A), SHC(0x015D), SHC(0x015F), SHC(0x0161), + SHC(0x0164), SHC(0x0166), SHC(0x0168), SHC(0x016B), SHC(0x016C), SHC(0x016F), SHC(0x0171), SHC(0x0172), + SHC(0x0175), SHC(0x0176), SHC(0x0178), SHC(0x017A), SHC(0x017B), SHC(0x017D), SHC(0x017F), SHC(0x0180), + SHC(0x0181), SHC(0x0183), SHC(0x0185), SHC(0x0185), SHC(0x0187), SHC(0x0187), SHC(0x0189), SHC(0x018A), + SHC(0x018B), SHC(0x018C), SHC(0x018D), SHC(0x018D), SHC(0x018E), SHC(0x018F), SHC(0x018F), SHC(0x0190), + SHC(0x0191), SHC(0x0190), SHC(0x0192), SHC(0x0191), SHC(0x0192), SHC(0x0192), SHC(0x0192), SHC(0x0192), + SHC(0x0192), SHC(0x0192), SHC(0x0192), SHC(0x0192), SHC(0x0191), SHC(0x0192), SHC(0x0190), SHC(0x0191), + SHC(0x0190), SHC(0x018F), SHC(0x018F), SHC(0x018E), SHC(0x018D), SHC(0x018D), SHC(0x018C), SHC(0x018B), + SHC(0x018A), SHC(0x0189), SHC(0x0187), SHC(0x0187), SHC(0x0185), SHC(0x0185), SHC(0x0183), SHC(0x0181), + SHC(0x0180), SHC(0x017F), SHC(0x017D), SHC(0x017B), SHC(0x017A), SHC(0x0178), SHC(0x0176), SHC(0x0175), + SHC(0x0172), SHC(0x0171), SHC(0x016F), SHC(0x016C), SHC(0x016B), SHC(0x0168), SHC(0x0166), SHC(0x0164), + SHC(0x0161), SHC(0x015F), SHC(0x015D), SHC(0x015A), SHC(0x0158), SHC(0x0155), SHC(0x0152), SHC(0x0150), + SHC(0x014D), SHC(0x014A), SHC(0x0147), SHC(0x0145), SHC(0x0141), SHC(0x013F), SHC(0x013B), SHC(0x0139), + SHC(0x0135), SHC(0x0132), SHC(0x012F), SHC(0x012C), SHC(0x0128), SHC(0x0125), SHC(0x0121), SHC(0x011E), + SHC(0x011B), SHC(0x0117), SHC(0x0114), SHC(0x010F), SHC(0x010D), SHC(0x0108), SHC(0x0105), SHC(0x0101), + SHC(0x00FD), SHC(0x00FA), SHC(0x00F5), SHC(0x00F2), SHC(0x00ED), SHC(0x00EA), SHC(0x00E5), SHC(0x00E2), + SHC(0x00DD), SHC(0x00D9), SHC(0x00D5), SHC(0x00D1), SHC(0x00CD), SHC(0x00C8), SHC(0x00C4), SHC(0x00C0), + SHC(0x00BB), SHC(0x00B7), SHC(0x00B3), SHC(0x00AE), SHC(0x00AA), SHC(0x00A5), SHC(0x00A1), SHC(0x009C), + SHC(0x0097), SHC(0x0093), SHC(0x008F), SHC(0x008A), SHC(0x0085), SHC(0x0080), SHC(0x007C), SHC(0x0077), + SHC(0x0072), SHC(0x006E), SHC(0x0069), SHC(0x0064), SHC(0x005F), SHC(0x005B), SHC(0x0056), SHC(0x0050), + SHC(0x004C), SHC(0x0048), SHC(0x0042), SHC(0x003D), SHC(0x0039), SHC(0x0034), SHC(0x002E), SHC(0x002A), + SHC(0x0025), SHC(0x0020), SHC(0x001B), SHC(0x0017), SHC(0x0011), SHC(0x000C), SHC(0x0008), SHC(0x0001) +}; + +const Word16 cos_table[512]= +{ + SHC(0x7fff), + SHC(0x7ffe), + SHC(0x7ff6), + SHC(0x7fea), + SHC(0x7fd9), + SHC(0x7fc2), + SHC(0x7fa7), + SHC(0x7f87), + SHC(0x7f62), + SHC(0x7f38), + SHC(0x7f0a), + SHC(0x7ed6), + SHC(0x7e9d), + SHC(0x7e60), + SHC(0x7e1e), + SHC(0x7dd6), + SHC(0x7d8a), + SHC(0x7d3a), + SHC(0x7ce4), + SHC(0x7c89), + SHC(0x7c2a), + SHC(0x7bc6), + SHC(0x7b5d), + SHC(0x7aef), + SHC(0x7a7d), + SHC(0x7a06), + SHC(0x798a), + SHC(0x790a), + SHC(0x7885), + SHC(0x77fb), + SHC(0x776c), + SHC(0x76d9), + SHC(0x7642), + SHC(0x75a6), + SHC(0x7505), + SHC(0x7460), + SHC(0x73b6), + SHC(0x7308), + SHC(0x7255), + SHC(0x719e), + SHC(0x70e3), + SHC(0x7023), + SHC(0x6f5f), + SHC(0x6e97), + SHC(0x6dca), + SHC(0x6cf9), + SHC(0x6c24), + SHC(0x6b4b), + SHC(0x6a6e), + SHC(0x698c), + SHC(0x68a7), + SHC(0x67bd), + SHC(0x66d0), + SHC(0x65de), + SHC(0x64e9), + SHC(0x63ef), + SHC(0x62f2), + SHC(0x61f1), + SHC(0x60ec), + SHC(0x5fe4), + SHC(0x5ed7), + SHC(0x5dc8), + SHC(0x5cb4), + SHC(0x5b9d), + SHC(0x5a82), + SHC(0x5964), + SHC(0x5843), + SHC(0x571e), + SHC(0x55f6), + SHC(0x54ca), + SHC(0x539b), + SHC(0x5269), + SHC(0x5134), + SHC(0x4ffb), + SHC(0x4ec0), + SHC(0x4d81), + SHC(0x4c40), + SHC(0x4afb), + SHC(0x49b4), + SHC(0x486a), + SHC(0x471d), + SHC(0x45cd), + SHC(0x447b), + SHC(0x4326), + SHC(0x41ce), + SHC(0x4074), + SHC(0x3f17), + SHC(0x3db8), + SHC(0x3c57), + SHC(0x3af3), + SHC(0x398d), + SHC(0x3825), + SHC(0x36ba), + SHC(0x354e), + SHC(0x33df), + SHC(0x326e), + SHC(0x30fc), + SHC(0x2f87), + SHC(0x2e11), + SHC(0x2c99), + SHC(0x2b1f), + SHC(0x29a4), + SHC(0x2827), + SHC(0x26a8), + SHC(0x2528), + SHC(0x23a7), + SHC(0x2224), + SHC(0x209f), + SHC(0x1f1a), + SHC(0x1d93), + SHC(0x1c0c), + SHC(0x1a83), + SHC(0x18f9), + SHC(0x176e), + SHC(0x15e2), + SHC(0x1455), + SHC(0x12c8), + SHC(0x113a), + SHC(0xfab), + SHC(0xe1c), + SHC(0xc8c), + SHC(0xafb), + SHC(0x96b), + SHC(0x7d9), + SHC(0x648), + SHC(0x4b6), + SHC(0x324), + SHC(0x192), + SHC(0x0), + SHC(0xfe6e), + SHC(0xfcdc), + SHC(0xfb4a), + SHC(0xf9b8), + SHC(0xf827), + SHC(0xf695), + SHC(0xf505), + SHC(0xf374), + SHC(0xf1e4), + SHC(0xf055), + SHC(0xeec6), + SHC(0xed38), + SHC(0xebab), + SHC(0xea1e), + SHC(0xe892), + SHC(0xe707), + SHC(0xe57d), + SHC(0xe3f4), + SHC(0xe26d), + SHC(0xe0e6), + SHC(0xdf61), + SHC(0xdddc), + SHC(0xdc59), + SHC(0xdad8), + SHC(0xd958), + SHC(0xd7d9), + SHC(0xd65c), + SHC(0xd4e1), + SHC(0xd367), + SHC(0xd1ef), + SHC(0xd079), + SHC(0xcf04), + SHC(0xcd92), + SHC(0xcc21), + SHC(0xcab2), + SHC(0xc946), + SHC(0xc7db), + SHC(0xc673), + SHC(0xc50d), + SHC(0xc3a9), + SHC(0xc248), + SHC(0xc0e9), + SHC(0xbf8c), + SHC(0xbe32), + SHC(0xbcda), + SHC(0xbb85), + SHC(0xba33), + SHC(0xb8e3), + SHC(0xb796), + SHC(0xb64c), + SHC(0xb505), + SHC(0xb3c0), + SHC(0xb27f), + SHC(0xb140), + SHC(0xb005), + SHC(0xaecc), + SHC(0xad97), + SHC(0xac65), + SHC(0xab36), + SHC(0xaa0a), + SHC(0xa8e2), + SHC(0xa7bd), + SHC(0xa69c), + SHC(0xa57e), + SHC(0xa463), + SHC(0xa34c), + SHC(0xa238), + SHC(0xa129), + SHC(0xa01c), + SHC(0x9f14), + SHC(0x9e0f), + SHC(0x9d0e), + SHC(0x9c11), + SHC(0x9b17), + SHC(0x9a22), + SHC(0x9930), + SHC(0x9843), + SHC(0x9759), + SHC(0x9674), + SHC(0x9592), + SHC(0x94b5), + SHC(0x93dc), + SHC(0x9307), + SHC(0x9236), + SHC(0x9169), + SHC(0x90a1), + SHC(0x8fdd), + SHC(0x8f1d), + SHC(0x8e62), + SHC(0x8dab), + SHC(0x8cf8), + SHC(0x8c4a), + SHC(0x8ba0), + SHC(0x8afb), + SHC(0x8a5a), + SHC(0x89be), + SHC(0x8927), + SHC(0x8894), + SHC(0x8805), + SHC(0x877b), + SHC(0x86f6), + SHC(0x8676), + SHC(0x85fa), + SHC(0x8583), + SHC(0x8511), + SHC(0x84a3), + SHC(0x843a), + SHC(0x83d6), + SHC(0x8377), + SHC(0x831c), + SHC(0x82c6), + SHC(0x8276), + SHC(0x822a), + SHC(0x81e2), + SHC(0x81a0), + SHC(0x8163), + SHC(0x812a), + SHC(0x80f6), + SHC(0x80c8), + SHC(0x809e), + SHC(0x8079), + SHC(0x8059), + SHC(0x803e), + SHC(0x8027), + SHC(0x8016), + SHC(0x800a), + SHC(0x8002), + SHC(0x8001), + SHC(0x8002), + SHC(0x800a), + SHC(0x8016), + SHC(0x8027), + SHC(0x803e), + SHC(0x8059), + SHC(0x8079), + SHC(0x809e), + SHC(0x80c8), + SHC(0x80f6), + SHC(0x812a), + SHC(0x8163), + SHC(0x81a0), + SHC(0x81e2), + SHC(0x822a), + SHC(0x8276), + SHC(0x82c6), + SHC(0x831c), + SHC(0x8377), + SHC(0x83d6), + SHC(0x843a), + SHC(0x84a3), + SHC(0x8511), + SHC(0x8583), + SHC(0x85fa), + SHC(0x8676), + SHC(0x86f6), + SHC(0x877b), + SHC(0x8805), + SHC(0x8894), + SHC(0x8927), + SHC(0x89be), + SHC(0x8a5a), + SHC(0x8afb), + SHC(0x8ba0), + SHC(0x8c4a), + SHC(0x8cf8), + SHC(0x8dab), + SHC(0x8e62), + SHC(0x8f1d), + SHC(0x8fdd), + SHC(0x90a1), + SHC(0x9169), + SHC(0x9236), + SHC(0x9307), + SHC(0x93dc), + SHC(0x94b5), + SHC(0x9592), + SHC(0x9674), + SHC(0x9759), + SHC(0x9843), + SHC(0x9930), + SHC(0x9a22), + SHC(0x9b17), + SHC(0x9c11), + SHC(0x9d0e), + SHC(0x9e0f), + SHC(0x9f14), + SHC(0xa01c), + SHC(0xa129), + SHC(0xa238), + SHC(0xa34c), + SHC(0xa463), + SHC(0xa57e), + SHC(0xa69c), + SHC(0xa7bd), + SHC(0xa8e2), + SHC(0xaa0a), + SHC(0xab36), + SHC(0xac65), + SHC(0xad97), + SHC(0xaecc), + SHC(0xb005), + SHC(0xb140), + SHC(0xb27f), + SHC(0xb3c0), + SHC(0xb505), + SHC(0xb64c), + SHC(0xb796), + SHC(0xb8e3), + SHC(0xba33), + SHC(0xbb85), + SHC(0xbcda), + SHC(0xbe32), + SHC(0xbf8c), + SHC(0xc0e9), + SHC(0xc248), + SHC(0xc3a9), + SHC(0xc50d), + SHC(0xc673), + SHC(0xc7db), + SHC(0xc946), + SHC(0xcab2), + SHC(0xcc21), + SHC(0xcd92), + SHC(0xcf04), + SHC(0xd079), + SHC(0xd1ef), + SHC(0xd367), + SHC(0xd4e1), + SHC(0xd65c), + SHC(0xd7d9), + SHC(0xd958), + SHC(0xdad8), + SHC(0xdc59), + SHC(0xdddc), + SHC(0xdf61), + SHC(0xe0e6), + SHC(0xe26d), + SHC(0xe3f4), + SHC(0xe57d), + SHC(0xe707), + SHC(0xe892), + SHC(0xea1e), + SHC(0xebab), + SHC(0xed38), + SHC(0xeec6), + SHC(0xf055), + SHC(0xf1e4), + SHC(0xf374), + SHC(0xf505), + SHC(0xf695), + SHC(0xf827), + SHC(0xf9b8), + SHC(0xfb4a), + SHC(0xfcdc), + SHC(0xfe6e), + SHC(0x0), + SHC(0x192), + SHC(0x324), + SHC(0x4b6), + SHC(0x648), + SHC(0x7d9), + SHC(0x96b), + SHC(0xafb), + SHC(0xc8c), + SHC(0xe1c), + SHC(0xfab), + SHC(0x113a), + SHC(0x12c8), + SHC(0x1455), + SHC(0x15e2), + SHC(0x176e), + SHC(0x18f9), + SHC(0x1a83), + SHC(0x1c0c), + SHC(0x1d93), + SHC(0x1f1a), + SHC(0x209f), + SHC(0x2224), + SHC(0x23a7), + SHC(0x2528), + SHC(0x26a8), + SHC(0x2827), + SHC(0x29a4), + SHC(0x2b1f), + SHC(0x2c99), + SHC(0x2e11), + SHC(0x2f87), + SHC(0x30fc), + SHC(0x326e), + SHC(0x33df), + SHC(0x354e), + SHC(0x36ba), + SHC(0x3825), + SHC(0x398d), + SHC(0x3af3), + SHC(0x3c57), + SHC(0x3db8), + SHC(0x3f17), + SHC(0x4074), + SHC(0x41ce), + SHC(0x4326), + SHC(0x447b), + SHC(0x45cd), + SHC(0x471d), + SHC(0x486a), + SHC(0x49b4), + SHC(0x4afb), + SHC(0x4c40), + SHC(0x4d81), + SHC(0x4ec0), + SHC(0x4ffb), + SHC(0x5134), + SHC(0x5269), + SHC(0x539b), + SHC(0x54ca), + SHC(0x55f6), + SHC(0x571e), + SHC(0x5843), + SHC(0x5964), + SHC(0x5a82), + SHC(0x5b9d), + SHC(0x5cb4), + SHC(0x5dc8), + SHC(0x5ed7), + SHC(0x5fe4), + SHC(0x60ec), + SHC(0x61f1), + SHC(0x62f2), + SHC(0x63ef), + SHC(0x64e9), + SHC(0x65de), + SHC(0x66d0), + SHC(0x67bd), + SHC(0x68a7), + SHC(0x698c), + SHC(0x6a6e), + SHC(0x6b4b), + SHC(0x6c24), + SHC(0x6cf9), + SHC(0x6dca), + SHC(0x6e97), + SHC(0x6f5f), + SHC(0x7023), + SHC(0x70e3), + SHC(0x719e), + SHC(0x7255), + SHC(0x7308), + SHC(0x73b6), + SHC(0x7460), + SHC(0x7505), + SHC(0x75a6), + SHC(0x7642), + SHC(0x76d9), + SHC(0x776c), + SHC(0x77fb), + SHC(0x7885), + SHC(0x790a), + SHC(0x798a), + SHC(0x7a06), + SHC(0x7a7d), + SHC(0x7aef), + SHC(0x7b5d), + SHC(0x7bc6), + SHC(0x7c2a), + SHC(0x7c89), + SHC(0x7ce4), + SHC(0x7d3a), + SHC(0x7d8a), + SHC(0x7dd6), + SHC(0x7e1e), + SHC(0x7e60), + SHC(0x7e9d), + SHC(0x7ed6), + SHC(0x7f0a), + SHC(0x7f38), + SHC(0x7f62), + SHC(0x7f87), + SHC(0x7fa7), + SHC(0x7fc2), + SHC(0x7fd9), + SHC(0x7fea), + SHC(0x7ff6), + SHC(0x7ffe) +}; + + + +const Word16 window_8_16_32kHz_fx[370] = +{ + 3, 9, 19, 33, 49, 69, 93, 119, + 149, 182, 219, 258, 301, 347, 396, 448, + 503, 561, 623, 687, 755, 825, 898, 974, + 1054, 1136, 1221, 1309, 1399, 1493, 1589, 1688, + 1790, 1895, 2002, 2112, 2225, 2340, 2458, 2579, + 2702, 2827, 2955, 3086, 3219, 3355, 3493, 3633, + 3775, 3920, 4068, 4217, 4369, 4523, 4679, 4837, + 4998, 5160, 5325, 5491, 5660, 5830, 6003, 6177, + 6353, 6531, 6711, 6892, 7076, 7260, 7447, 7635, + 7825, 8016, 8209, 8403, 8599, 8796, 8995, 9195, + 9396, 9598, 9802, 10007, 10212, 10419, 10628, 10837, + 11047, 11248, 11437, 11623, 11809, 11997, 12185, 12374, + 12564, 12754, 12944, 13135, 13326, 13517, 13709, 13901, + 14093, 14286, 14478, 14671, 14864, 15057, 15250, 15443, + 15636, 15829, 16023, 16216, 16409, 16602, 16794, 16987, + 17179, 17372, 17564, 17755, 17947, 18138, 18329, 18519, + 18710, 18899, 19089, 19278, 19466, 19654, 19841, 20028, + 20214, 20400, 20585, 20770, 20954, 21137, 21319, 21501, + 21682, 21862, 22042, 22220, 22398, 22575, 22751, 22926, + 23101, 23274, 23446, 23618, 23788, 23958, 24126, 24266, + 24321, 24460, 24625, 24789, 24953, 25114, 25275, 25435, + 25593, 25751, 25907, 26061, 26215, 26367, 26518, 26668, + 26817, 26964, 27110, 27254, 27398, 27540, 27680, 27819, + 27957, 28093, 28228, 28362, 28494, 28625, 28754, 28882, + 29008, 29133, 29256, 29378, 29499, 29618, 29736, 29852, + 29966, 30079, 30191, 30301, 30410, 30517, 30623, 30727, + 30830, 30931, 31031, 31129, 31226, 31322, 31416, 31508, + 31599, 31689, 31777, 31864, 31950, 32035, 32118, 32200, + 32280, 32360, 32439, 32517, 32595, 32673, 32673, 32593, + 32513, 32432, 32349, 32265, 32178, 32090, 31999, 31907, + 31812, 31715, 31615, 31514, 31410, 31304, 31196, 31085, + 30972, 30857, 30739, 30619, 30497, 30372, 30245, 30116, + 29984, 29850, 29714, 29575, 29434, 29290, 29144, 28996, + 28845, 28692, 28537, 28379, 28219, 28057, 27892, 27725, + 27555, 27383, 27209, 27033, 26854, 26672, 26489, 26303, + 26115, 25924, 25731, 25536, 25338, 25138, 24936, 24731, + 24525, 24316, 24104, 23890, 23674, 23456, 23236, 23013, + 22788, 22561, 22331, 22138, 22060, 21865, 21629, 21390, + 21150, 20907, 20662, 20414, 20165, 19913, 19659, 19403, + 19145, 18885, 18622, 18357, 18090, 17821, 17550, 17277, + 17001, 16723, 16443, 16161, 15877, 15591, 15303, 15012, + 14719, 14425, 14127, 13828, 13527, 13223, 12918, 12610, + 12300, 11988, 11673, 11356, 11038, 10716, 10393, 10067, + 9739, 9408, 9076, 8740, 8403, 8062, 7720, 7374, + 7026, 6675, 6322, 5965, 5606, 5243, 4878, 4508, + 4136, 3759, 3378, 2993, 2603, 2208, 1807, 1397, + 978, 545 +}; + + + + +const Word16 window_48kHz_fx[1110] = +{ + 0, 1, 2, 3, 5, 8, 10, 13, + 17, 21, 25, 30, 35, 40, 46, 52, + 58, 65, 72, 80, 88, 96, 105, 114, + 124, 133, 144, 154, 165, 176, 188, 200, + 212, 225, 238, 251, 265, 279, 293, 308, + 323, 339, 354, 371, 387, 404, 421, 439, + 457, 475, 493, 512, 532, 551, 571, 591, + 612, 633, 654, 676, 698, 720, 743, 766, + 789, 813, 837, 861, 885, 910, 936, 961, + 987, 1013, 1040, 1067, 1094, 1122, 1149, 1178, + 1206, 1235, 1264, 1293, 1323, 1353, 1384, 1414, + 1445, 1477, 1508, 1540, 1573, 1605, 1638, 1671, + 1705, 1739, 1773, 1807, 1842, 1877, 1912, 1948, + 1984, 2020, 2057, 2093, 2130, 2168, 2206, 2244, + 2282, 2320, 2359, 2399, 2438, 2478, 2518, 2558, + 2599, 2640, 2681, 2722, 2764, 2806, 2848, 2891, + 2934, 2977, 3020, 3064, 3108, 3152, 3196, 3241, + 3286, 3332, 3377, 3423, 3469, 3515, 3562, 3609, + 3656, 3704, 3751, 3799, 3847, 3896, 3945, 3994, + 4043, 4092, 4142, 4192, 4242, 4293, 4343, 4394, + 4445, 4497, 4549, 4600, 4653, 4705, 4758, 4811, + 4864, 4917, 4971, 5024, 5078, 5133, 5187, 5242, + 5297, 5352, 5407, 5463, 5519, 5575, 5631, 5688, + 5744, 5801, 5859, 5916, 5974, 6031, 6089, 6147, + 6206, 6265, 6323, 6382, 6442, 6501, 6561, 6620, + 6680, 6741, 6801, 6862, 6922, 6983, 7045, 7106, + 7168, 7229, 7291, 7353, 7416, 7478, 7541, 7604, + 7667, 7730, 7793, 7857, 7920, 7984, 8048, 8112, + 8177, 8241, 8306, 8371, 8436, 8501, 8566, 8632, + 8697, 8763, 8829, 8895, 8961, 9028, 9094, 9161, + 9228, 9295, 9362, 9429, 9497, 9564, 9632, 9700, + 9768, 9836, 9904, 9972, 10041, 10109, 10178, 10247, + 10316, 10385, 10454, 10523, 10593, 10662, 10732, 10802, + 10871, 10941, 11012, 11082, 11152, 11222, 11283, 11344, + 11406, 11467, 11529, 11591, 11653, 11716, 11778, 11840, + 11903, 11966, 12028, 12091, 12154, 12217, 12280, 12343, + 12406, 12469, 12532, 12595, 12658, 12722, 12785, 12849, + 12912, 12976, 13039, 13103, 13166, 13230, 13294, 13358, + 13421, 13485, 13549, 13613, 13677, 13741, 13805, 13869, + 13933, 13997, 14061, 14125, 14189, 14253, 14318, 14382, + 14446, 14510, 14574, 14639, 14703, 14767, 14832, 14896, + 14960, 15025, 15089, 15153, 15218, 15282, 15346, 15411, + 15475, 15540, 15604, 15668, 15733, 15797, 15862, 15926, + 15990, 16055, 16119, 16183, 16248, 16312, 16376, 16441, + 16505, 16569, 16634, 16698, 16762, 16826, 16891, 16955, + 17019, 17083, 17147, 17211, 17275, 17339, 17404, 17468, + 17532, 17596, 17659, 17723, 17787, 17851, 17915, 17979, + 18042, 18106, 18170, 18233, 18297, 18361, 18424, 18488, + 18551, 18614, 18678, 18741, 18804, 18868, 18931, 18994, + 19057, 19120, 19183, 19246, 19309, 19372, 19434, 19497, + 19560, 19622, 19685, 19748, 19810, 19872, 19935, 19997, + 20059, 20121, 20183, 20245, 20307, 20369, 20431, 20493, + 20554, 20616, 20677, 20739, 20800, 20862, 20923, 20984, + 21045, 21106, 21167, 21228, 21289, 21349, 21410, 21471, + 21531, 21591, 21652, 21712, 21772, 21832, 21892, 21952, + 22012, 22071, 22131, 22190, 22250, 22309, 22368, 22427, + 22486, 22545, 22604, 22663, 22722, 22780, 22839, 22897, + 22955, 23013, 23071, 23129, 23187, 23245, 23303, 23360, + 23418, 23475, 23532, 23589, 23646, 23703, 23760, 23817, + 23873, 23930, 23986, 24042, 24098, 24154, 24210, 24266, + 24321, 24377, 24432, 24488, 24543, 24598, 24653, 24707, + 24762, 24817, 24871, 24925, 24979, 25034, 25087, 25141, + 25195, 25248, 25302, 25355, 25408, 25461, 25514, 25567, + 25620, 25672, 25724, 25777, 25829, 25881, 25932, 25984, + 26036, 26087, 26138, 26189, 26240, 26291, 26342, 26393, + 26443, 26493, 26543, 26593, 26643, 26693, 26743, 26792, + 26841, 26890, 26939, 26988, 27037, 27086, 27134, 27182, + 27230, 27278, 27326, 27374, 27421, 27469, 27516, 27563, + 27610, 27657, 27703, 27750, 27796, 27842, 27888, 27934, + 27980, 28025, 28071, 28116, 28161, 28206, 28250, 28295, + 28340, 28384, 28428, 28472, 28516, 28559, 28603, 28646, + 28689, 28732, 28775, 28818, 28860, 28903, 28945, 28987, + 29029, 29071, 29112, 29154, 29195, 29236, 29277, 29318, + 29358, 29399, 29439, 29479, 29519, 29559, 29598, 29638, + 29677, 29716, 29755, 29794, 29832, 29871, 29909, 29947, + 29985, 30023, 30061, 30098, 30135, 30172, 30209, 30246, + 30283, 30319, 30356, 30392, 30428, 30464, 30499, 30535, + 30570, 30605, 30640, 30675, 30710, 30744, 30779, 30813, + 30847, 30881, 30914, 30948, 30981, 31014, 31047, 31080, + 31113, 31145, 31178, 31210, 31242, 31274, 31306, 31337, + 31369, 31400, 31431, 31462, 31493, 31523, 31554, 31584, + 31614, 31644, 31674, 31704, 31733, 31763, 31792, 31821, + 31850, 31879, 31907, 31936, 31964, 31992, 32020, 32048, + 32076, 32104, 32131, 32159, 32186, 32213, 32240, 32267, + 32294, 32320, 32347, 32373, 32399, 32426, 32452, 32478, + 32504, 32530, 32556, 32582, 32607, 32633, 32659, 32685, + 32712, 32739, 32739, 32712, 32685, 32659, 32633, 32606, + 32580, 32553, 32527, 32500, 32473, 32446, 32418, 32391, + 32363, 32335, 32307, 32279, 32251, 32222, 32193, 32164, + 32134, 32105, 32075, 32045, 32015, 31984, 31953, 31922, + 31891, 31859, 31828, 31796, 31764, 31731, 31698, 31665, + 31632, 31599, 31565, 31531, 31497, 31462, 31428, 31393, + 31357, 31322, 31286, 31250, 31214, 31177, 31141, 31104, + 31066, 31029, 30991, 30953, 30915, 30876, 30837, 30798, + 30759, 30719, 30679, 30639, 30599, 30558, 30517, 30476, + 30435, 30393, 30351, 30309, 30266, 30224, 30181, 30138, + 30094, 30050, 30006, 29962, 29917, 29873, 29827, 29782, + 29737, 29691, 29645, 29598, 29551, 29505, 29457, 29410, + 29362, 29314, 29266, 29218, 29169, 29120, 29070, 29021, + 28971, 28921, 28871, 28820, 28769, 28718, 28667, 28615, + 28563, 28511, 28459, 28406, 28353, 28300, 28246, 28192, + 28138, 28084, 28030, 27975, 27920, 27864, 27809, 27753, + 27697, 27640, 27584, 27527, 27470, 27412, 27355, 27297, + 27238, 27180, 27121, 27062, 27003, 26944, 26884, 26824, + 26763, 26703, 26642, 26581, 26520, 26458, 26396, 26334, + 26272, 26209, 26146, 26083, 26020, 25956, 25892, 25828, + 25763, 25699, 25634, 25568, 25503, 25437, 25371, 25305, + 25239, 25172, 25105, 25037, 24970, 24902, 24834, 24766, + 24697, 24628, 24559, 24490, 24420, 24351, 24281, 24210, + 24140, 24069, 23998, 23926, 23855, 23783, 23711, 23638, + 23566, 23493, 23420, 23346, 23273, 23199, 23125, 23050, + 22976, 22901, 22826, 22750, 22675, 22599, 22523, 22446, + 22370, 22293, 22215, 22138, 22060, 21983, 21904, 21826, + 21747, 21669, 21589, 21510, 21430, 21351, 21271, 21190, + 21110, 21029, 20948, 20866, 20785, 20703, 20621, 20538, + 20456, 20373, 20290, 20207, 20123, 20039, 19955, 19871, + 19787, 19702, 19617, 19532, 19446, 19360, 19274, 19188, + 19102, 19015, 18928, 18841, 18754, 18666, 18578, 18490, + 18402, 18313, 18224, 18135, 18046, 17956, 17866, 17776, + 17686, 17595, 17505, 17414, 17322, 17231, 17139, 17047, + 16955, 16863, 16770, 16677, 16584, 16490, 16397, 16303, + 16209, 16114, 16020, 15925, 15830, 15735, 15639, 15543, + 15447, 15351, 15254, 15158, 15061, 14964, 14866, 14768, + 14671, 14572, 14474, 14375, 14276, 14177, 14078, 13978, + 13878, 13778, 13678, 13578, 13477, 13376, 13274, 13173, + 13071, 12969, 12867, 12764, 12662, 12559, 12455, 12352, + 12248, 12144, 12040, 11936, 11831, 11726, 11621, 11515, + 11410, 11304, 11197, 11091, 10984, 10877, 10770, 10663, + 10555, 10447, 10339, 10230, 10122, 10013, 9904, 9794, + 9684, 9574, 9464, 9353, 9243, 9131, 9020, 8908, + 8797, 8684, 8572, 8459, 8346, 8233, 8119, 8006, + 7892, 7777, 7662, 7547, 7432, 7317, 7201, 7085, + 6968, 6851, 6734, 6617, 6499, 6381, 6263, 6144, + 6025, 5906, 5786, 5666, 5546, 5425, 5304, 5183, + 5061, 4939, 4817, 4694, 4570, 4447, 4323, 4198, + 4074, 3948, 3823, 3696, 3570, 3443, 3315, 3187, + 3058, 2929, 2800, 2669, 2539, 2407, 2275, 2142, + 2009, 1875, 1740, 1604, 1467, 1330, 1191, 1051, + 909, 766, 621, 474, 324, 169 +}; + + +const Word16 window_256kHz[592] = /*ALDO at 25.6 maybe not needed ?*/ +{ + 1, 3, 7, 12, 19, 27, 36, 47, + 58, 72, 86, 102, 119, 138, 157, 178, + 201, 224, 249, 275, 302, 331, 361, 391, + 424, 457, 492, 527, 564, 603, 642, 683, + 724, 767, 811, 857, 903, 951, 999, 1049, + 1100, 1152, 1205, 1260, 1315, 1372, 1430, 1488, + 1548, 1609, 1671, 1735, 1799, 1864, 1931, 1998, + 2066, 2136, 2207, 2278, 2351, 2424, 2499, 2575, + 2651, 2729, 2808, 2887, 2968, 3049, 3132, 3215, + 3300, 3385, 3472, 3559, 3647, 3736, 3826, 3917, + 4009, 4101, 4195, 4289, 4385, 4481, 4578, 4676, + 4774, 4874, 4974, 5075, 5177, 5280, 5384, 5488, + 5593, 5699, 5806, 5913, 6021, 6130, 6240, 6350, + 6461, 6573, 6685, 6798, 6912, 7026, 7141, 7257, + 7373, 7491, 7608, 7726, 7845, 7965, 8085, 8206, + 8327, 8449, 8571, 8694, 8817, 8941, 9066, 9191, + 9316, 9442, 9569, 9696, 9823, 9951, 10079, 10208, + 10337, 10467, 10597, 10727, 10858, 10990, 11121, 11253, + 11367, 11482, 11598, 11714, 11831, 11948, 12065, 12182, + 12300, 12418, 12536, 12654, 12772, 12891, 13010, 13129, + 13248, 13367, 13486, 13605, 13725, 13844, 13964, 14084, + 14203, 14323, 14443, 14563, 14683, 14804, 14924, 15044, + 15164, 15284, 15405, 15525, 15645, 15765, 15885, 16006, + 16126, 16246, 16366, 16486, 16606, 16726, 16846, 16966, + 17086, 17206, 17325, 17445, 17564, 17684, 17803, 17922, + 18041, 18160, 18279, 18397, 18516, 18634, 18753, 18871, + 18988, 19106, 19224, 19341, 19458, 19575, 19692, 19809, + 19925, 20041, 20157, 20273, 20388, 20503, 20618, 20733, + 20848, 20962, 21076, 21190, 21303, 21416, 21529, 21642, + 21754, 21866, 21978, 22089, 22200, 22311, 22421, 22531, + 22641, 22751, 22860, 22968, 23077, 23185, 23293, 23400, + 23507, 23613, 23719, 23825, 23931, 24036, 24140, 24244, + 24348, 24452, 24555, 24657, 24759, 24861, 24962, 25063, + 25163, 25263, 25363, 25462, 25561, 25659, 25756, 25854, + 25950, 26047, 26142, 26238, 26333, 26427, 26521, 26614, + 26707, 26799, 26891, 26982, 27073, 27164, 27253, 27343, + 27432, 27520, 27608, 27695, 27781, 27868, 27953, 28038, + 28123, 28207, 28290, 28373, 28456, 28537, 28619, 28699, + 28780, 28859, 28938, 29017, 29095, 29172, 29249, 29325, + 29401, 29476, 29550, 29624, 29698, 29771, 29843, 29915, + 29986, 30056, 30126, 30196, 30264, 30333, 30400, 30467, + 30534, 30600, 30665, 30730, 30794, 30858, 30921, 30984, + 31046, 31107, 31168, 31228, 31288, 31347, 31406, 31464, + 31522, 31579, 31635, 31691, 31746, 31801, 31856, 31909, + 31963, 32016, 32068, 32120, 32171, 32222, 32273, 32323, + 32372, 32422, 32471, 32520, 32568, 32617, 32666, 32715, + 32715, 32666, 32616, 32567, 32517, 32466, 32415, 32364, + 32311, 32258, 32204, 32150, 32094, 32038, 31981, 31923, + 31864, 31805, 31744, 31683, 31621, 31557, 31494, 31429, + 31363, 31296, 31229, 31161, 31091, 31021, 30950, 30878, + 30805, 30731, 30657, 30581, 30505, 30427, 30349, 30270, + 30189, 30108, 30026, 29943, 29860, 29775, 29689, 29603, + 29515, 29427, 29337, 29247, 29156, 29064, 28971, 28877, + 28782, 28687, 28590, 28492, 28394, 28294, 28194, 28093, + 27991, 27888, 27784, 27679, 27573, 27466, 27358, 27250, + 27140, 27030, 26919, 26806, 26693, 26579, 26464, 26349, + 26232, 26114, 25996, 25876, 25756, 25635, 25512, 25389, + 25265, 25140, 25015, 24888, 24761, 24632, 24503, 24373, + 24242, 24110, 23977, 23843, 23708, 23573, 23436, 23299, + 23161, 23022, 22882, 22741, 22599, 22457, 22313, 22169, + 22024, 21878, 21731, 21583, 21435, 21285, 21135, 20984, + 20832, 20679, 20525, 20370, 20215, 20059, 19901, 19743, + 19584, 19425, 19264, 19103, 18940, 18777, 18613, 18448, + 18283, 18116, 17949, 17781, 17612, 17442, 17271, 17100, + 16927, 16754, 16580, 16405, 16230, 16053, 15876, 15698, + 15518, 15339, 15158, 14976, 14794, 14611, 14427, 14242, + 14056, 13869, 13682, 13494, 13305, 13115, 12924, 12732, + 12540, 12346, 12152, 11957, 11761, 11564, 11366, 11168, + 10968, 10768, 10566, 10364, 10161, 9957, 9752, 9547, + 9340, 9132, 8924, 8714, 8503, 8292, 8079, 7866, + 7651, 7436, 7219, 7002, 6783, 6563, 6343, 6121, + 5897, 5673, 5448, 5221, 4993, 4764, 4533, 4301, + 4067, 3832, 3596, 3358, 3118, 2876, 2632, 2387, + 2139, 1888, 1635, 1379, 1119, 854, 583, 304 +}; + +const Word16 small_overlap_48[R2_48/7]= +{ + 429, 1286, 2143, 2998, 3851, 4702, 5549, 6393, + 7232, 8066, 8895, 9717, 10533, 11342, 12142, 12935, + 13719, 14493, 15257, 16011, 16754, 17485, 18205, 18912, + 19606, 20286, 20953, 21605, 22243, 22865, 23472, 24062, + 24636, 25193, 25733, 26255, 26760, 27246, 27713, 28161, + 28590, 28999, 29389, 29758, 30107, 30435, 30743, 31029, + 31294, 31538, 31760, 31960, 32138, 32295, 32429, 32541, + 32631, 32698, 32743, 32765 +}; + +const Word16 small_overlap_25[R2_25/7]= +{ + 804, 2411, 4011, 5602, 7180, 8740, 10279, 11793, + 13279, 14733, 16151, 17531, 18868, 20160, 21403, 22595, + 23732, 24812, 25833, 26791, 27684, 28511, 29269, 29957, + 30572, 31114, 31581, 31972, 32286, 32522, 32679, 32758 +}; + +const Word16 small_overlap_int[R2_16/7]= +{ + 2571, 5126, + 7650, 10126, 12540, 14876, 17121, 19261, 21281, 22865, + 23472, 24917, 26510, 27939, 29197, 30274, 31164, 31863, + 32365, 32667 +}; + + +const Word16 half_overlap_48[3*R2_48/7]= +{ + 143, 429, + 715, 1001, 1286, 1572, 1858, 2143, 2428, 2713, + 2998, 3283, 3567, 3851, 4135, 4419, 4702, 4985, + 5267, 5549, 5831, 6112, 6393, 6673, 6953, 7232, + 7510, 7788, 8066, 8343, 8619, 8895, 9169, 9444, + 9717, 9990, 10262, 10533, 10803, 11073, 11342, 11609, + 11876, 12142, 12408, 12672, 12935, 13197, 13458, 13719, + 13978, 14236, 14493, 14749, 15004, 15257, 15510, 15761, + 16011, 16260, 16508, 16754, 16999, 17243, 17485, 17727, + 17966, 18205, 18442, 18678, 18912, 19145, 19376, 19606, + 19834, 20061, 20286, 20510, 20732, 20953, 21172, 21390, + 21605, 21820, 22032, 22243, 22452, 22659, 22865, 23069, + 23271, 23472, 23670, 23867, 24062, 24255, 24447, 24636, + 24824, 25010, 25193, 25375, 25555, 25733, 25909, 26083, + 26255, 26426, 26594, 26760, 26924, 27086, 27246, 27403, + 27559, 27713, 27864, 28014, 28161, 28306, 28449, 28590, + 28729, 28865, 28999, 29131, 29261, 29389, 29514, 29637, + 29758, 29877, 29993, 30107, 30219, 30328, 30435, 30540, + 30643, 30743, 30840, 30936, 31029, 31120, 31208, 31294, + 31378, 31459, 31538, 31614, 31688, 31760, 31829, 31896, + 31960, 32022, 32081, 32138, 32193, 32245, 32295, 32342, + 32387, 32429, 32469, 32506, 32541, 32573, 32603, 32631, + 32655, 32678, 32698, 32715, 32730, 32743, 32753, 32760, + 32765, 32767 +}; + +const Word16 half_overlap_25[3*R2_25/7]= +{ + 268, 804, 1340, 1876, 2411, 2945, 3479, 4011, + 4543, 5073, 5602, 6130, 6655, 7180, 7702, 8222, + 8740, 9255, 9768, 10279, 10786, 11291, 11793, 12292, + 12787, 13279, 13767, 14252, 14733, 15210, 15683, 16151, + 16616, 17075, 17531, 17981, 18427, 18868, 19304, 19735, + 20160, 20580, 20994, 21403, 21806, 22204, 22595, 22980, + 23359, 23732, 24099, 24459, 24812, 25159, 25499, 25833, + 26159, 26478, 26791, 27096, 27394, 27684, 27967, 28243, + 28511, 28771, 29024, 29269, 29506, 29736, 29957, 30170, + 30375, 30572, 30761, 30942, 31114, 31278, 31434, 31581, + 31720, 31850, 31972, 32085, 32190, 32286, 32373, 32452, + 32522, 32583, 32635, 32679, 32714, 32741, 32758, 32767 +}; + +const Word16 half_overlap_int[3*R2_16/7]= +{ + 858, 1715, 2571, 3425, 4277, 5126, + 5971, 6813, 7650, 8481, 9307, 10126, 10938, 11743, + 12540, 13328, 14107, 14876, 15636, 16384, 17121, 17847, + 18560, 19261, 19948, 20622, 21281, 21926, 22556, 23069, + 23271, 23769, 24351, 24917, 25466, 25997, 26510, 27005, + 27482, 27939, 28378, 28797, 29197, 29576, 29935, 30274, + 30592, 30888, 31164, 31419, 31651, 31863, 32052, 32219, + 32365, 32488, 32588, 32667, 32723, 32757 +}; + + +/*----------------------------------------------------------------------------------* + * SC-VBR + *----------------------------------------------------------------------------------*/ + +const Word16 bp1_num_coef_wb_fx[5]= { 15286, 0, -30572, 0, 15286, }; /* Q14 */ + +const Word16 bp1_den_coef_wb_fx[5]= { 16384, 0, -30498, 0, 14262, }; /* Q14 */ + + + +const Word16 shape1_num_coef_fx[11]= /* Q15 */ +{ + 31437, -2443, -13636, 4316, + -10188, 48, 2639, -3575, + -776, 1046, 399 +}; + + +const Word16 shape1_den_coef_fx[11]= { 32767, /* Q15 */ + 2940, -12237, 4032, -9609, + -1998, 2335, -3900, -1595, + 857, 253 + }; + +const Word16 shape2_num_coef_fx[11]= /* Q15 */ +{ + 30760, 31, -9699, 9516, + -5878, -7249, -10468, 442, + 3278, -63, 1115 +}; + + +const Word16 shape2_den_coef_fx[11]= { 32767, /* Q15 */ + 16019, -890, 12799, 2346, + -6985, -13192, -5795, -949, + -1492, -304 + }; + + +const Word16 shape3_num_coef_fx[11]= /* Q15 */ +{ + 30685, -383, -9937, -9605, + -5997, 7611, -10393, -355, + 3239, 12, 1196 +}; + + +const Word16 shape3_den_coef_fx[11]= { 32767, /* Q15 */ + -16498, -911, -12947, 2286, + 7430, -13385, 6066, -1182, + 1580, -273 + }; + + + +const Word16 txlpf1_num_coef_fx[11] = /* Q13 */ +{ + 138, 198, 514, 681, 921, + 964, 921, 681, 514, 198, + 138, +}; + + + +const Word16 txlpf1_den_coef_fx[11] = /* Q13 */ +{ + 8192,-18945, 31613,-31149, 24494, + -12753, 5528, -1436, 347, -25, + 4, +}; + + + +const Word16 txhpf1_num_coef_fx[11] = /* Q13 */ +{ + 138, -198, 514, -681, 921, + -964, 921, -681, 514, -198, + 138, +}; + + +const Word16 txhpf1_den_coef_fx[11] = /* Q13 */ +{ + 8192, 18945, 31613, 31149, 24494, + 12753, 5528, 1436, 347, 25, + 4, +}; + +/* NELP filter coefficients */ + +/*BP1_ORDER = 7; */ +const Word16 bp1_num_coef_nb_fx_order7[8] = +{ + /* Q = BP1_COEF_NB_QF_ORDER7 = 13 */ + 1481, 6730, 15579, 22923, 22923, 15579, 6730, 1481, + +}; +const Word16 bp1_den_coef_nb_fx_order7[8] = +{ + /* Q = BP1_COEF_NB_QF_ORDER7 = 13 */ + 8192, 16156, 23814, 21855, 14620, 6614, 1907, 268, +}; + + +/* NELP gain tables */ + +const Word16 UVG1CB_WB_FX[UVG1_CBSIZE][2] = /* Q13 */ +{ + { -2224, -2114, }, + { 12666, 12314, }, + { 3723, 9690, }, + { 17880, 17978, }, + { 4136, 3946, }, + { 11605, 21280, }, + { 9777, 9340, }, + { 21701, 21627, }, + { 1088, 1679, }, + { 13993, 13697, }, + { 10443, 5214, }, + { 19702, 19692, }, + { 5458, 5317, }, + { 17051, 16918, }, + { 14206, 8503, }, + { 24330, 24271, }, + { -118, -279, }, + { 11615, 14863, }, + { 6898, 6544, }, + { 18913, 18637, }, + { 1142, 6811, }, + { 15995, 16070, }, + { 6921, 13182, }, + { 22857, 22741, }, + { 3017, 2260, }, + { 14952, 14992, }, + { 8176, 8093, }, + { 20721, 20549, }, + { 7441, 2370, }, + { 17897, 13988, }, + { 10986, 10966, }, + { 26098, 25992, }, +}; + +const Word16 UVG1CB_NB_FX[UVG1_CBSIZE][2] = /* Q13 */ +{ + { -4791, -5157, }, + { 4824, 4937, }, + { -3443, 3610, }, + { 5539, 15293, }, + { -469, -3986, }, + { 7977, 8157, }, + { 2748, 2492, }, + { 14070, 14014, }, + { -2486, -2863, }, + { 6033, 5892, }, + { 2678, -441, }, + { 11741, 11804, }, + { -256, -847, }, + { 9153, 8922, }, + { -106, 5979, }, + { 16876, 16741, }, + { -3584, -3873, }, + { 3511, 9538, }, + { 401, 416, }, + { 11082, 10550, }, + { -1418, -1725, }, + { 8988, 5255, }, + { 6275, 1137, }, + { 15372, 15247, }, + { -3899, 301, }, + { 6976, 7095, }, + { 1581, 1453, }, + { 12988, 12824, }, + { 2692, -3093, }, + { 9778, 10153, }, + { 3938, 3628, }, + { 18823, 18695, }, +}; + +const Word16 UVG2CB1_WB_FX[UVG2_CBSIZE][5] = /* Q12 */ +{ + { 914, 990, 1490, 5954, 2618, }, + { 5599, 4621, 4078, 3493, 3057, }, + { 4930, 4031, 2999, 2150, 1706, }, + { 7722, 3021, 1804, 1478, 1452, }, + { 1171, 1390, 6895, 2592, 1486, }, + { 4155, 4287, 4409, 4515, 4577, }, + { 3633, 3661, 3694, 3711, 3736, }, + { 13212, 5009, 2611, 2175, 2048, }, + { 3716, 2887, 2253, 1965, 1723, }, + { 7141, 4567, 3434, 2970, 2396, }, + { 2856, 3038, 3259, 3481, 3709, }, + { 5929, 5459, 4923, 4448, 4084, }, + { 980, 1024, 1550, 5686, 8038, }, + { 3516, 7354, 10392, 3619, 2856, }, + { 2598, 3093, 3582, 4780, 5965, }, + { 1962, 10993, 5020, 2861, 2587, }, + { 796, 916, 1010, 1175, 7720, }, + { 4445, 4406, 4344, 4249, 4175, }, + { 1454, 6493, 2611, 1758, 1765, }, + { 6296, 7686, 4763, 2945, 2203, }, + { 1502, 1573, 1895, 2981, 5464, }, + { 4750, 4829, 4909, 4929, 4895, }, + { 3644, 3774, 3922, 4037, 4116, }, + { 9051, 7403, 6003, 4746, 4081, }, + { 1558, 1869, 2331, 3000, 3595, }, + { 4671, 4646, 4614, 4553, 4482, }, + { 2262, 2608, 3158, 3890, 4468, }, + { 5556, 5441, 6824, 7146, 5724, }, + { 1470, 1550, 2016, 11169, 3828, }, + { 5488, 6270, 6771, 8202, 9281, }, + { 3477, 3693, 4113, 4460, 4705, }, + { 10877, 17984, 10194, 7291, 2824, }, + { 1327, 1498, 1476, 1667, 2138, }, + { 4463, 4299, 4094, 3880, 3731, }, + { 3188, 3164, 3156, 3104, 3140, }, + { 9757, 5690, 3366, 2296, 1792, }, + { 1731, 1753, 12406, 4082, 2247, }, + { 3866, 4060, 5007, 5274, 5225, }, + { 3998, 3957, 3900, 3839, 3789, }, + { 18040, 9417, 5567, 3465, 2504, }, + { 2160, 2532, 2895, 2577, 2321, }, + { 5052, 4789, 4490, 4203, 3953, }, + { 3381, 3415, 3458, 3496, 3536, }, + { 6166, 5811, 5440, 5035, 4650, }, + { 2839, 3389, 5057, 7558, 10414, }, + { 3875, 4431, 5183, 6310, 7166, }, + { 4311, 4130, 3571, 3070, 8555, }, + { 8791, 8260, 7299, 6243, 5421, }, + { 1191, 1237, 1368, 1814, 11819, }, + { 2486, 5729, 6150, 4222, 3667, }, + { 4018, 3825, 3600, 3388, 3256, }, + { 7504, 5817, 4989, 4065, 3322, }, + { 1430, 1962, 5546, 4096, 4681, }, + { 5393, 5378, 5324, 5230, 5052, }, + { 4041, 4090, 4132, 4159, 4181, }, + { 12469, 9221, 5735, 3617, 2501, }, + { 2482, 2565, 2768, 3088, 3461, }, + { 5209, 5080, 4905, 4706, 4522, }, + { 3139, 3362, 3647, 3910, 4156, }, + { 7139, 6588, 5941, 5251, 4674, }, + { 1719, 1866, 7993, 7634, 3987, }, + { 3587, 5289, 7882, 13519, 16095, }, + { 2409, 2515, 2749, 7316, 4636, }, + { 30391, 18493, 13798, 4799, 2283, }, +}; + +const Word16 UVG2CB2_WB_FX[UVG2_CBSIZE][5] = /* Q12 */ +{ + { 1565, 1391, 1635, 5228, 2681, }, + { 2156, 2558, 6205, 5561, 3944, }, + { 2039, 2406, 3094, 3409, 3968, }, + { 5090, 5065, 4989, 4858, 4764, }, + { 1436, 1736, 2816, 2362, 2400, }, + { 4375, 4425, 4465, 4478, 4493, }, + { 4648, 4081, 3550, 2981, 2667, }, + { 1705, 1950, 3679, 7828, 9895, }, + { 2839, 1826, 1443, 1210, 1245, }, + { 1387, 1410, 1768, 8873, 4383, }, + { 4022, 3784, 3565, 3316, 3096, }, + { 9983, 7147, 5225, 3742, 3027, }, + { 6769, 2357, 1531, 1448, 1556, }, + { 4591, 4671, 4735, 4765, 4789, }, + { 4308, 4198, 4052, 3896, 3769, }, + { 2288, 2550, 4922, 8294, 14878, }, + { 1361, 1480, 1511, 1991, 10450, }, + { 2933, 3131, 3694, 4687, 5201, }, + { 3984, 3048, 2479, 2644, 5514, }, + { 5353, 5480, 5488, 5434, 5437, }, + { 3319, 2881, 2528, 2152, 1927, }, + { 4873, 4748, 4578, 4407, 4257, }, + { 6185, 4396, 3751, 3400, 2899, }, + { 2159, 8067, 7534, 5121, 3640, }, + { 2265, 10177, 3803, 2588, 2441, }, + { 2188, 2206, 4293, 12691, 5893, }, + { 3587, 3651, 3760, 3864, 3960, }, + { 13158, 9752, 7171, 5431, 5364, }, + { 5710, 4173, 2928, 2090, 1774, }, + { 3531, 3831, 4641, 5787, 6622, }, + { 4395, 4356, 4281, 4194, 4111, }, + { 2243, 2476, 5814, 3965, 27176, }, + { 1575, 1667, 7544, 3005, 1984, }, + { 2583, 2511, 11684, 5765, 4807, }, + { 3632, 3458, 3277, 3114, 2971, }, + { 8569, 6778, 5866, 5515, 5141, }, + { 3267, 3035, 2940, 2782, 2691, }, + { 3929, 4249, 4577, 4877, 5162, }, + { 4443, 4173, 3864, 3590, 3337, }, + { 3998, 4725, 5728, 6873, 7885, }, + { 4369, 2824, 2237, 1648, 1404, }, + { 1000, 1022, 1477, 2682, 15276, }, + { 3916, 3851, 3766, 3664, 3591, }, + { 13206, 4485, 3230, 3897, 3648, }, + { 10002, 3515, 2393, 2233, 2211, }, + { 4603, 4836, 5071, 5259, 5411, }, + { 3919, 4035, 4177, 4304, 4419, }, + { 3046, 8332, 16475, 11172, 10858, }, + { 1027, 1007, 1196, 1578, 5937, }, + { 1892, 2422, 3227, 3920, 7400, }, + { 3584, 3532, 3508, 3470, 3437, }, + { 5363, 6155, 6805, 6854, 6811, }, + { 4038, 3512, 3030, 2636, 2332, }, + { 6760, 6124, 5235, 4299, 3687, }, + { 4125, 6528, 4068, 3238, 3483, }, + { 5020, 5905, 7082, 8554, 9623, }, + { 1399, 5868, 3069, 1726, 1655, }, + { 4691, 4234, 3974, 3757, 9616, }, + { 3978, 4003, 4003, 3983, 3960, }, + { 2103, 16858, 9252, 4860, 4727, }, + { 8043, 5294, 3970, 3098, 2583, }, + { 4680, 5109, 5576, 5965, 6275, }, + { 4867, 4584, 4276, 3958, 3682, }, + { 1213, 3115, 6552, 22778, 20977, }, +}; + + +const Word16 UVG2CB1_NB_FX[UVG2_CBSIZE][5] = /* Q12 */ +{ + { 773, 785, 785, 785, 860, }, + { 3560, 3521, 3410, 3265, 3167, }, + { 1766, 2982, 10273, 3790, 2248, }, + { 4986, 4753, 4496, 4172, 3922, }, + { 2036, 2030, 2009, 1973, 1897, }, + { 3291, 3554, 3868, 4126, 4345, }, + { 3207, 3122, 3026, 2913, 2797, }, + { 13220, 6844, 3967, 2746, 2466, }, + { 1553, 1627, 1392, 1766, 3679, }, + { 5379, 4640, 3844, 3254, 2635, }, + { 1600, 1622, 2430, 9446, 4214, }, + { 5115, 5200, 5311, 5365, 5343, }, + { 6229, 3008, 1989, 1622, 1597, }, + { 1726, 2114, 7046, 6162, 4301, }, + { 1004, 1056, 1841, 6006, 7101, }, + { 6388, 9659, 4510, 2774, 2113, }, + { 1060, 1153, 1400, 1733, 2121, }, + { 3448, 3523, 3612, 3683, 3770, }, + { 1496, 2045, 2910, 3563, 4058, }, + { 4419, 4592, 4795, 4921, 4978, }, + { 1407, 5314, 2788, 1675, 1350, }, + { 4210, 4225, 4227, 4186, 4169, }, + { 2247, 8245, 4392, 2522, 1709, }, + { 7211, 6741, 6110, 5397, 4680, }, + { 3602, 2286, 1577, 1229, 1148, }, + { 6674, 5227, 3576, 2448, 1901, }, + { 954, 1035, 1079, 1683, 9558, }, + { 4011, 5853, 8979, 7138, 4484, }, + { 2784, 2702, 2637, 2546, 2471, }, + { 4414, 4065, 4627, 4208, 9275, }, + { 2771, 3012, 3357, 3735, 4066, }, + { 19742, 8603, 3943, 2546, 2085, }, + { 1132, 1123, 1107, 1093, 1114, }, + { 3913, 3838, 3733, 3630, 3548, }, + { 948, 1565, 6063, 2654, 1667, }, + { 6159, 5567, 4884, 4241, 3770, }, + { 925, 1164, 1585, 6062, 3090, }, + { 3818, 4037, 4322, 4536, 4726, }, + { 4291, 3894, 3441, 3006, 2733, }, + { 8544, 6487, 4962, 3812, 2970, }, + { 1744, 1758, 1704, 1633, 1576, }, + { 4416, 4259, 4044, 3810, 3628, }, + { 1919, 2159, 3323, 13977, 7898, }, + { 5952, 5731, 5419, 5061, 4732, }, + { 2775, 2812, 2507, 2540, 6585, }, + { 3436, 3960, 4661, 5975, 6274, }, + { 3082, 3150, 3246, 3337, 3404, }, + { 4089, 16018, 8285, 4116, 2704, }, + { 1419, 1425, 1400, 1371, 1363, }, + { 3825, 3890, 3953, 3993, 4015, }, + { 2498, 2689, 2846, 3011, 3213, }, + { 5122, 5024, 4881, 4691, 4524, }, + { 2285, 2325, 2317, 2313, 2271, }, + { 4493, 4529, 4517, 4478, 4443, }, + { 9138, 3969, 2522, 2222, 2415, }, + { 10009, 8719, 7292, 5837, 4532, }, + { 831, 908, 1039, 1656, 6813, }, + { 2070, 5478, 5174, 3911, 3694, }, + { 1577, 1565, 1635, 2583, 13154, }, + { 5590, 5788, 5922, 6752, 7063, }, + { 4061, 3497, 2710, 2099, 1716, }, + { 2750, 3118, 16574, 7891, 3651, }, + { 2598, 3072, 3809, 4906, 5172, }, + { 15348, 10948, 7740, 4979, 3446, }, +}; + +const Word16 UVG2CB2_NB_FX[UVG2_CBSIZE][5]= /* Q12 */ +{ + { 961, 867, 812, 771, 775, }, + { 2544, 2686, 3010, 3605, 5048, }, + { 1524, 1818, 2889, 3029, 3046, }, + { 4195, 4301, 4421, 4497, 4580, }, + { 2026, 1990, 1965, 1943, 1939, }, + { 4338, 4156, 3963, 3750, 3590, }, + { 7732, 2904, 1804, 1407, 1513, }, + { 1613, 2353, 11315, 5764, 4291, }, + { 1519, 1462, 1434, 1341, 1294, }, + { 1627, 1710, 2163, 9654, 5615, }, + { 2322, 7293, 3251, 2020, 2066, }, + { 4967, 5112, 5174, 5203, 5230, }, + { 1590, 1449, 1943, 5947, 3563, }, + { 7747, 5170, 3268, 2392, 2082, }, + { 3970, 3559, 3164, 2774, 2493, }, + { 1993, 2210, 3204, 3717, 23534, }, + { 1185, 1236, 1423, 2115, 4772, }, + { 3935, 3840, 3714, 3583, 3477, }, + { 1640, 1550, 1800, 2609, 10880, }, + { 4067, 4437, 4811, 5108, 5536, }, + { 1472, 1367, 1533, 2132, 7352, }, + { 4310, 4284, 4216, 4117, 4057, }, + { 10817, 4587, 2611, 2066, 2037, }, + { 2089, 2427, 4698, 14635, 7517, }, + { 2529, 1561, 1209, 976, 945, }, + { 2908, 3070, 4055, 5862, 6448, }, + { 2676, 2861, 3115, 3295, 3408, }, + { 2932, 14330, 6533, 3739, 3462, }, + { 3681, 3079, 2559, 2151, 1903, }, + { 5636, 5316, 4978, 4690, 4425, }, + { 2298, 7228, 6976, 4251, 3347, }, + { 2504, 3421, 6784, 8483, 15064, }, + { 1253, 1180, 1136, 1094, 1076, }, + { 3451, 3524, 3600, 3646, 3707, }, + { 1701, 2030, 6574, 4746, 4451, }, + { 4688, 4751, 4762, 4727, 4722, }, + { 2977, 2363, 1883, 1563, 1399, }, + { 5080, 4685, 4275, 3835, 3513, }, + { 5445, 3828, 2851, 2242, 1948, }, + { 1929, 5037, 17760, 8346, 6300, }, + { 1839, 1782, 1680, 1586, 1534, }, + { 3086, 3472, 4031, 4950, 9695, }, + { 3199, 3052, 2896, 2751, 2622, }, + { 5822, 5782, 5727, 5566, 5478, }, + { 1548, 2234, 6748, 2562, 1722, }, + { 6699, 5216, 4475, 3531, 3028, }, + { 3773, 3628, 3460, 3279, 3155, }, + { 1581, 1672, 2929, 20221, 16432, }, + { 1210, 1215, 1389, 1678, 2177, }, + { 3863, 3886, 3937, 3961, 3989, }, + { 1541, 1745, 1829, 3479, 15563, }, + { 4444, 4952, 5573, 6056, 6545, }, + { 2460, 2397, 2284, 2133, 2041, }, + { 4808, 4676, 4493, 4322, 4213, }, + { 15031, 6644, 3315, 2900, 2885, }, + { 4003, 4760, 6946, 8274, 8401, }, + { 5001, 2495, 1594, 1337, 1365, }, + { 3428, 3706, 4073, 4457, 4670, }, + { 3326, 3277, 3222, 3142, 3088, }, + { 6162, 6317, 6494, 6459, 6530, }, + { 2659, 2599, 2537, 2482, 2546, }, + { 8554, 6902, 5233, 4116, 3650, }, + { 4643, 4099, 3616, 3201, 2895, }, + { 9589, 26630, 15412, 12532, 8715, }, +}; + + +const Word16 frac_4sf_fx[NB_SUBFR+2]= {4,8,12,16,16,16}; /* Q4 */ + +/* ERB table for PPP-ampl-quant */ + +/* ERB table for PPP-ampl-quant */ +const Word16 erb_WB_fx[NUM_ERB_WB+1]= {0, 238, 475, 713, 950, 1188, 1426, 1663, 1911, 2185, 2490, 2826, 3205, 3624, 4094, 4620, 5210, 5875, 6626, 7478, 8448, 9558, 11264, 13568, 16387}; + + +/* ERB table for PPP-ampl-quant */ +const Word16 erb_NB_fx[NUM_ERB_NB+1]= {0, 238, 475, 713, 950, 1188, 1426, 1663, 1911, 2185, 2490, 2826, 3205, 3624, 4094, 4620, 5210, 5875, 6626, 7478, 8448, 9558, 10243}; + + +const Word16 AmpCB1_WB_fx[640] = +{ + 5655, 1589, -653, 3568, -3173, -1852, -3204, -4623, -2100, -5103, + -923, -67, -7152, -4958, -2019, -1810, -8532, -648, 6581, 8043, + 160, 778, -1535, 863, 5482, 1674, -3576, 123, -3163, -3595, + -852, -53, -1080, -2683, -3199, -950, -1353, 6258, -1431, 1249, + 2059, 677, 146, 1011, 956, -2022, -25, 300, 421, -5859, + 1027, -452, -7343, -1052, 3818, 1099, -1005, 659, -511, -658, + 2091, 720, -600, 145, -1504, -1716, -442, -2172, -1505, 2702, + 731, 1473, -213, -4120, -2976, 688, 3205, 1213, 679, 232, + 3672, 4770, -1198, -298, -1714, -3669, -2833, -664, -1859, -2380, + -1169, -1593, -453, 295, -1225, -3110, -1776, 2112, 2710, 3333, + 1022, 1248, 1091, 1164, 1200, 1782, -809, -2306, -3124, -2194, + -1567, 465, 2223, -1301, -463, -2157, 729, 2279, -1938, 610, + 437, -803, -1025, 775, -171, -637, 163, 2251, 316, -1663, + -4123, -20, -2827, -1529, -1436, 3447, 79, -274, 1650, 4097, + 2369, 927, 448, -449, 293, -239, -1028, -4805, 1354, 431, + -2219, -490, -3849, 1639, -2925, 817, 1485, 2527, 5444, -1994, + 1476, 506, -1643, 2003, -1676, -788, -1681, -2011, 1389, 452, + 593, 3, -1200, -3987, -1634, -4310, -686, 882, 6235, 2420, + -196, -1257, -2038, -498, 1394, 671, -2302, -809, -446, 3644, + -1643, -2304, -828, 105, -323, -3906, -960, 7324, 3095, -786, + 95, 633, 1266, 750, 1509, -2033, -3134, 432, 1028, -1825, + 1258, 256, -3249, -6868, -523, -325, -1779, 4313, 2524, 3433, + -600, -410, -88, 410, -1182, -1140, -1448, -1344, -5074, 6054, + 2194, 1505, -681, -2408, 1376, 1389, 1209, 1048, -4199, -2939, + 1855, 1744, -1344, -1431, -1955, -1805, -4992, 512, 624, 2749, + -3446, -1215, -3764, -2169, -3601, -1321, 67, 4326, 6624, 5816, + -334, -1746, -441, -754, 1853, 3889, -595, -493, 441, -811, + -48, -764, -1473, -683, 603, -1754, 780, 698, 1084, 1713, + 560, -808, -754, -2890, -1205, -318, -1021, 3195, 5693, -4603, + 1343, -1061, -2441, -1784, 721, 267, 227, -622, 3013, -768, + -472, 90, 13, 290, 1055, 948, 1617, -2368, -1087, 1103, + -4784, -3872, 5125, -2518, -215, 6962, 1095, -1521, 2091, -2962, + 2285, 1117, 1174, 2635, -1907, -1012, 814, -417, -2162, -2805, + -1188, -707, -808, -1757, 260, -1093, -3957, -3266, 4132, 5980, + 177, -1478, 960, 2029, 3989, 597, -3062, -3940, -1688, 236, + -1559, 150, 2432, 348, -242, -2014, -1027, 6298, -2957, -3960, + 1090, 1014, -1261, -744, -954, -938, -3713, -3272, 5356, -2356, + -1439, 3808, -2330, -4437, 5177, -3606, -1382, 1824, 407, 325, + 649, 330, 85, 206, -415, 183, -646, 602, -2656, 808, + 1039, 29, -3202, -6168, -3640, 3736, 4183, 3959, 330, 339, + 2701, 343, 1501, 1879, -3194, -4648, -1630, 1656, -1578, -84, + -3065, -4126, 24, -260, 263, -1705, -1289, 2432, 1229, 7481, + 2586, 1696, 646, -1773, -792, 1932, -1908, -1897, -1129, 112, + -5667, -1592, 2253, -980, 1581, 211, 5277, 4846, -288, -159, + 956, 1196, 771, -973, -1785, -516, -1015, 847, 614, -791, + -442, -1594, -4632, -4392, -416, 1398, 2570, 752, 264, 6570, + 1655, 546, 1238, -1362, -1330, -2005, 3590, -2155, -184, -1224, + -1452, -1533, -534, 1010, -1707, 801, 3628, -289, 2414, 132, + 2643, -2813, -4524, 5092, -7362, 740, 428, -510, 81, -1209, + 616, 1454, 1861, -3958, -4084, 189, -1219, -875, 3764, 2086, + -1554, -2071, 1515, 3392, 12, -686, -2414, -1382, 176, 1685, + 2055, -5698, 1582, 4117, -4846, -2922, 610, 2082, 4682, -2487, + 348, 2258, -338, -1379, 1472, 618, -202, -1122, -76, -2468, + -1216, -986, -327, -1441, 102, 403, -2105, 2411, 1510, 1288, + -715, -577, 1074, 2533, -3521, -3449, 2140, -751, -307, 3805, + 158, -1385, -404, -1378, -1948, 3785, 4216, 2667, -1894, -1559, + 1037, 1371, 989, -205, -333, -4784, -3429, -1283, 3299, 859, + -4922, -5481, -1196, -1748, -720, 516, 113, 4590, 7071, 4345, + -5729, -3862, 3590, 1463, 7094, 4991, 854, -66, -1630, -686, + -923, -3266, -1988, 2345, 785, -1420, 3004, 2934, -1245, -65, + -2696, -3088, -1438, 614, 1584, -239, -1552, 580, 6285, -1673, + -1598, -4018, -1909, 747, 3191, 366, 1467, -1933, 2759, 2804, + 518, 193, -1149, -3108, 441, 1458, 2791, -4131, 2694, 3372, + -5023, -6491, 1794, 2739, 1463, 5843, 2869, 1993, -1409, 4832 +}; + +const Word16 pwf78_fx[17]= { 25559, 19936, 15550, 12129, 9460, 7379, 5755, 4489, + 3501, 2731, 2130, 1661, 1296, 1011, 788, 615, + 479 + }; /* 0.78^i (i=1,...,17), Q15 */ + + + + +const Word16 AmpCB2_WB_fx[64*(NUM_ERB_WB-13)]= +{ + -5276, -7711, -3518, -2416, -382, 319, -1900, -900, 1725, 884, + 4071, -4052, -2430, -336, 2136, 3006, 591, -3893, -2731, 2625, + 2390, -1047, -883, -3368, -4235, -3726, 189, -1803, 784, 2336, + 206, -2140, 3001, -730, -2279, 85, -3395, 4367, 2214, -254, + -3114, -2348, 2763, 686, -7495, -6618, 3164, -3957, -2681, -2049, + 1659, 3634, 2962, 1574, 379, -2478, 2861, 616, 1124, 205, + -3075, -348, -2006, -90, 761, 1157, -114, -9460, -2786, -3254, + -1120, -1500, -446, 2835, -314, 3205, 2115, -837, -261, 36, + 80, -485, 1133, 2124, -1031, -401, -3166, 1145, -1616, -3425, + -3071, -6891, -4198, 2292, 5160, -46, 1430, 280, 1378, 1700, + -1673, -1126, 5270, 5096, -975, -1070, 1314, -2389, -2982, 20, + -3218, -892, -636, -876, -302, -2923, -3240, 4121, 1625, -557, + 994, 544, 2657, 7133, -273, -3530, -1419, 1431, -936, -2622, + 303, 75, -5444, -5549, 4183, 1248, 3474, -789, 2375, -1778, + 1660, 1520, -1433, -4047, 531, 7001, 695, 1889, 4261, -2791, + -1557, -2980, -316, 415, 1134, 1501, -6923, 521, -3134, -1812, + 1848, 676, -1733, 734, 2207, 2029, -476, -1976, -161, 29, + 7147, -1774, 720, -1070, -372, -1626, -6473, -2448, -5235, -2651, + -1800, -1477, -767, 1335, 471, 4857, 888, 593, -370, 196, + 907, 174, 557, -720, -1339, 1590, 37, -1247, -1307, 276, + -1739, -6032, -3088, -2499, -497, -393, -569, 3003, 2694, 3751, + 4652, -258, -1305, 175, 189, -344, -2381, -1992, 463, 529, + -6375, 3966, -3558, -3001, -640, 3117, 1120, 966, 1316, -561, + 27, 2794, 2831, 3512, 3453, -418, -2319, -6741, -3443, 80, + 1281, 1691, 1500, -591, -739, 2385, -4676, -5822, -1437, 730, + 3593, -437, 1090, 3497, -1932, 2854, 4858, 2654, 947, 1879, + -4115, 2700, -3092, -1524, 225, -8272, -6736, -1277, 2991, 2983, + 1129, -1661, 2817, 468, 491, -744, 390, 677, 8129, -3130, + -687, -433, 1488, -3763, -177, -581, -764, 39, 1537, -2203, + -1678, 263, -1214, 2175, -1857, 3097, -894, 4207, -1943, -834, + 1513, -4123, 3981, 6041, 653, -757, -313, -3024, -4614, -3139, + -2966, 178, 4956, -427, -41, 2376, 1008, -1351, -92, 978, + 1998, 5146, 2069, 117, -1754, -2756, 4425, 168, -1807, -1761, + -1215, 178, -1562, -3369, -919, -2576, 3614, 4968, -30, -396, + -1151, -1146, 868, 1073, -359, 2732, 546, 4431, -321, -1081, + 1410, -3214, -2316, -4889, -2460, -3844, -7323, -1438, -1488, 1849, + 4037, 2421, 2697, -2372, -1877, 670, 3674, -907, 888, -3703, + 375, -1278, -1477, 2501, -936, -1682, -1353, -335, -4440, 383, + -2730, -2130, -1105, 1588, 3340, 4816, -4023, 502, -4146, 236, + 4481, 589, -3696, 826, -97, 222, -8037, -2244, 142, 810, + -2195, 1315, 656, 1901, -485, 317, 1512, 1465, -2026, 1853, + 929, 1670, -2736, -463, -836, -4946, -134, 2769, 2972, -5148, + -3147, 913, -1483, 267, -1560, 3903, 1507, 1105, -1496, 210, + -1196, 3764, 601, 1630, 3842, 6374, -1293, -4555, -3087, 199, + -1917, -3331, -2317, -1774, 479, 3712, 2729, 1309, -3047, -514, + 861, -213, 1317, -2035, 4369, 5228, 942, -3052, -2316, -3377, + 1123, -65, 2507, 2711, -2096, -2164, -2634, -5215, -3919, 1551, + -47, 1990, 2370, 2025, -2401, 4833, -3879, -162, -3081, 501, + -510, 2744, -907, 253, -1746, -2520, 3418, -1461, 2140, 2507, + 135, 1457, 3195, -1277, -2558, -66, 10850, -1633, -1051, -3436, + -1617, 1438, -1231, -1744, 696, -348, 3434, 2121, -1629, -2460, + -4065, 1159, -1288, 2843, 697, -862, 4, 966, -444, -1860, + 1450, 6426, 5544, 1456, -2826, -1303, -2778, -1278, -6656, -3241, + -7083, 2234, 204, 1753, 803, 499, 1641, 87, 1471, -1325, + 398, 2983, 4340, -1382, 735, -600, -4671, -254, 2327, -1008, + -144, -1453, -1806, -1669, 395, -3285, -1803, -2119, 1232, 2914, + 1480, 8610, 1788, 2644, 1359, 3783, -110, -1339, -1337, -3427, + -630, -1189, -2560, 976, 483, -2744, -3653, -1289, 2910, -2437, + 3171, 1479, 157, 823, 4631, -1910, 3736, -424, -155, -5470, + -741, 3829, -2794, -55, -1447, -3469, -1947, 2914, -61, -3430, + 3544, -1867, 2986, 1009, -1051, 725, 2933, 2926, 5849, 257, + -2666, 6286, -2282, -2998, -2576, -975, -3655, -1867, -5040, -1440, + 3542, -603, 4806, -2808, -1633, 1388, 1149, -1616, -1851, 2122, + 4477, 2485, 1376, 721, 2174, -3072, 1378, -2574, -37, 1322, + -1646, -3612, 4443, 1612, -3403, 711, 132, 119, -227, 5059, + 2892, 840, 5462, -3471, -1340, 2097, 143, 1750, -3052, -1932, + -6352, -4166, -645, 4317, 633, 3681, 2811, 2346, 2374, -2999, + -1265, -210, 5115, 4652, 1305, 3704, -1456, -307, -457, -1455, + -3580, 674, 2215, 2458, -3021, -66, 2535, -652, 1226, 685, + 875, -1753, -1164, -609, 3444, 563, 3826, 1607, 3798, 1385, + 3902, -1990, -4078, -2509 +}; + + +const Word16 AmpCB1_NB_fx[640] = +{ + -1355, 185, -222, -221, 1976, 3119, 540, 1333, -3646, -2511, + -979, 1664, 2087, 951, 787, -1687, -855, 1594, 1264, -4990, + -1957, -215, -850, 1369, -113, 2541, -2904, 743, 634, -657, + -3438, -2047, 706, 85, -596, -50, 212, 944, 118, 1380, + -1203, -78, -213, -1811, -781, -1970, 6607, -2971, 147, -1483, + 38, 5607, 5222, -4567, -4040, -2259, -3110, -2120, 932, -236, + -1052, 1039, -872, 334, -919, 2761, 3320, -5828, 53, 1063, + -1064, -75, -1015, -2137, -722, 565, 629, 1961, -454, 866, + -888, 2652, 1996, -2170, -885, 3325, -645, -1898, -984, -643, + -1008, 2472, 2400, -3708, -2408, -1051, 2029, 1357, -636, -470, + -1307, 655, 663, 29, 892, -95, -91, -2966, -1610, 2657, + -2175, -3170, -3799, -3065, 1130, 1351, 3814, 2791, 1478, 1520, + -1326, -520, -692, 899, 1979, -397, -407, 450, -569, -611, + -1228, 864, 2549, 3067, -2511, -4737, -2701, -304, 680, 1426, + -1070, -19, -1582, -2813, -1832, 3010, 250, -613, 3390, -171, + -1450, -417, -773, -651, -405, -2304, -780, 6656, -3270, -1322, + 70, 5105, 3202, -83, -925, -458, 1203, -1582, -4158, -3630, + -1702, -849, -55, -986, -1963, -1140, -1942, 3347, 3526, -435, + -1429, -2089, -1620, -1271, 2851, 2184, -2472, 3216, 2885, -2922, + -1217, 86, -186, -279, -746, 1288, 3016, -651, -2719, 317, + -1307, -127, -1110, 1389, 212, 1783, 2619, -1718, 1795, -4086, + -1295, 743, 301, -1823, -223, -651, -1774, -405, 1687, 2031, + -865, 1059, -391, 505, -2739, -2773, 16, -2960, 3071, 3325, + -791, 2301, 435, 107, -4039, 801, -1224, 1854, -1039, 507, + -518, 997, 837, 3311, 506, 1026, -232, -1920, -3904, 406, + -1857, -529, -776, -700, -663, -1520, 1699, 814, 2084, -477, + -1341, -1123, -2564, -2784, 2457, 3223, -959, 385, -1864, 3754, + -1351, -1347, -2229, -2882, -1061, -1499, -3028, 3302, 2250, 5539, + -957, -340, 27, 1508, 167, -3513, 1689, 2577, -1810, -516, + -1061, 2171, 1774, 2031, 923, -1933, -1640, -2881, 859, -834, + 408, 2462, 2073, 2107, -2671, 1140, -3497, -2497, 2984, -2707, + -1762, -2524, -2196, 279, -2580, 477, 2306, 4645, 693, -909, + -1089, 1952, 3034, -1790, 786, -1149, -3117, 3605, -1933, -1886, + -959, 934, 246, -2177, -2440, 1356, 871, 3472, 2558, -4512, + -782, 1262, 893, 1979, 2386, -1809, -4357, -392, -1928, 1576, + -1751, -327, -1018, -617, -2370, -2910, 4230, -90, -1361, 3596, + -1069, -315, -162, -339, -313, 33, 4684, 2811, -2717, -3684, + 695, 4567, -745, -2311, -776, -2600, -827, -1040, -997, 2480, + -1549, -748, -622, -260, 1460, 1116, -302, -2529, 2156, -42, + -1318, -568, -266, -446, -2212, 2690, -4669, 5325, -2022, 1358, + -1312, 2293, 1528, 706, 970, -291, 383, -683, -1532, -1843, + -1379, 845, 1218, 395, -1884, 14, 676, -1711, 795, 290, + -742, 386, -435, 411, 1311, 549, -4181, -4922, 1497, 4465, + -1722, -699, -1958, -4126, -3727, -655, 1553, 1793, 4933, 3055, + -1260, -618, 535, -2008, 3802, -3784, 2527, -833, 193, -1062, + -866, 823, 1562, 147, -623, -1808, -1099, 694, -577, 745, + -2282, -4139, -3171, 76, 25, -1077, 477, 545, 6081, 3244, + -1332, -785, 98, -1681, -3603, -3937, 524, 4648, 1114, 2547, + -1145, 407, 2030, 3120, -1739, -513, -518, 1325, -1700, -2860, + -1427, 520, -1040, -792, -366, -2174, -522, -240, 5660, -3163, + -1449, -1653, -1507, 581, 1338, -2627, -1863, 1831, 1301, 2106, + -1252, 974, 199, 68, -69, -869, 864, 2373, -5818, 2873, + 26, 972, 359, -561, -390, 376, 225, 517, 649, -1767, + -653, 2167, 882, -698, 214, -4084, -4134, 2092, 2798, -523, + -1002, 486, 648, -1082, 404, -1490, 1560, -4984, 5614, -1441, + -1024, -311, 427, 356, -2342, 215, -2312, 445, -2378, 5111, + -568, 85, 1328, 1847, 3506, 1183, -2521, -2070, -794, -1881, + -485, 1121, 1242, 1301, -4365, -2222, 2602, -387, 1498, -1344, + -1272, -1365, -2207, -213, -1877, 2858, 849, -915, 333, 2488, + -2019, -2048, -1461, -1930, -1409, -400, 490, -2222, 1276, 7305, + -1530, -1741, -2663, 3159, 1162, -1490, 1516, -1498, 1222, 838, + 1325, 5387, 3888, 1944, -1706, -2890, -1905, -3901, -3207, 206, + -1411, -959, -292, -396, -1547, -84, -4405, -1073, 5532, 1796, + 3160, 48, -2339, -5884, -184, -52, 129, 5398, 378, -321 +}; + +const Word16 AmpCB2_NB_fx[64*(NUM_ERB_NB-13)]= +{ + -2681, -4389, -4270, -4727, -239, 1938, 1748, 2311, 4300, -3957, + -1299, 3487, 1595, -377, 295, -1193, -1588, 2112, -1573, -6362, + -504, 1796, -2521, -68, 1322, 1223, 2263, -503, -3906, 3686, + -3899, -139, 2086, 48, 349, 547, -6387, 1340, -1467, -1062, + -193, 1325, -1190, 2394, 1671, -1982, -2597, -390, -1504, 2271, + -379, -2350, 4071, 70, -955, -883, -1770, -1065, -2443, -1779, + -1101, -661, 6325, 1871, -2673, 3596, 3773, -681, 3340, -1418, + 701, -4253, -3931, -1840, -2388, -2677, -3545, -41, 3675, 3843, + 2198, -1713, -324, 599, 1323, 1827, -4909, -1668, 616, 2608, + 360, -1769, -5263, -1278, 3490, 1935, 1355, -1298, 952, 1801, + 449, 251, -1021, -3666, 479, 3497, 1542, -2234, -3414, -4483, + -5785, 1406, 1207, 2984, 1767, 3262, -799, -3124, 5237, 460, + 2007, -1525, -2106, -770, 546, 137, 401, -1308, 969, 204, + -1626, -589, -4257, 1744, 2836, 2383, 2740, -423, 3166, 1920, + -690, -3000, -4489, 2523, -6693, -5135, -739, -1919, 1228, 2354, + 3340, 1902, 1069, -3185, -2614, 2764, -212, -2061, -1377, 698, + 3694, -125, -954, -4132, -404, 4297, 1294, 1765, 2446, -2287, + -1387, -14, 508, 1149, 9, -437, 519, -420, 450, -751, + -1632, -1391, -2208, -1955, -1170, 4818, 1112, 1086, -782, 1337, + 846, -3434, 569, 1721, -776, -2723, 1207, 982, -1432, -887, + 315, -3031, 3452, 765, -1263, -2146, 2959, -2619, 1507, 1312, + 4087, 3125, 1637, -1402, -45, -3193, 1397, -2611, -3641, -2478, + -1706, 588, 199, 3721, 1217, -1249, -1196, 7228, 996, 879, + -1339, 11, -971, -1680, 716, -39, 233, 1945, 1548, -1476, + 550, -2277, 307, 7413, 2094, -1631, -569, -1351, -198, -483, + -515, -1347, -212, -2649, -519, 195, 2944, -795, 1470, 654, + -1448, 3156, 1369, 3966, 3382, -2782, -4255, -1157, -212, 392, + 861, 5064, 4740, -2513, -3413, -552, -2298, -575, 1130, 1178, + 1568, 4591, 1238, 367, 1626, 600, -5889, 163, -3742, -3650, + -3911, 716, 919, -1501, 55, 1807, 3801, -5571, -4635, 1225, + 3211, 3804, 1491, -906, 100, 404, -1742, -1878, -2140, 1651, + 1640, 3976, -3432, -1149, 1365, 2042, 392, 768, -1534, 1096, + 3811, -211, -2067, -1315, -4167, 1145, -2747, -149, 5296, -735, + 438, 56, -404, -159, -2164, -959, 3492, -690, -688, -1081, + 2762, -1191, 654, 2051, -2144, -3210, -1823, 743, 686, -751, + 2483, 160, 1279, 3246, 1874, 2488, 1192, -5977, -478, 120, + -349, -65, -2350, -222, -1678, -3584, 1114, 3269, 1462, -1114, + -138, 2360, -2762, 720, -3822, 2523, 216, 1170, 4398, -4229, + -1850, 1272, 383, 1736, -383, -1295, 85, -132, 1133, 1505, + 1467, -2389, -2175, 4028, -2752, 241, -4353, -2103, -562, 817, + 3959, 5471, 1941, -1598, -2349, 201, 1412, -796, 2791, -4226, + 3227, -1992, -159, -159, 4085, -1549, 1020, -2179, -776, -2088, + -147, -42, 1880, -1029, 4982, -2056, 111, 1420, 2141, 302, + -2574, -986, -477, -3697, -2349, -2064, -335, -220, 5857, 57, + -7, -5407, -546, -353, 2866, 137, -136, 3508, 992, -2059, + -2034, -1127, -189, -300, -2153, 3606, 2523, -3727, 1526, -3797, + 2134, 4352, -920, -459, 2722, 1784, -71, -3030, -877, 1967, + -1645, -4432, 512, 39, 1757, 2875, -947, 1842, 1365, 1500, + 851, 594, -2892, -404, 3327, -3078, -1575, -1258, -973, -191, + -390, 45, 627, -227, 1624, -143, 215, 2157, 4846, 5335, + 3397, -199, -4443, -3091, -283, -216, 1237, -1478, -5639, -775, + 525, 2107, 2469, 2934, -255, 2438, 824, 5973, -1820, -1330, + -1202, -2433, 900, 650, -5654, 2891, -1539, -453, 1662, 231, + -145, 1661, 741, -332, 1221, 1809, 943, 4831, -1588, -4619, + 65, -790, -985, -893, 3374, 3148, 289, 2947, -4980, -661, + -427, 1441, 7696, 158, -1914, -2069, -1717, -418, 2657, 4219, + 1505, -1096, 601, -1466, -1754, -479, -159, 3378, 5252, 5060, + 4001, 1301, 420, -1268, -2813, -4196 +}; + +const Word16 PowerCB_WB_fx[128] = +{ + -3371, -1712, + -170, 350, + -638, -939, + 56, 1074, + -1559, -626, + 200, 344, + -397, 238, + 284, 1415, + -1323, -1880, + -544, 1170, + -619, -255, + 587, 974, + -1262, -98, + 327, 151, + 41, -302, + 941, 1876, + -2257, -1233, + 28, 202, + -520, -561, + 338, 1048, + -1080, -495, + 190, 582, + -284, -24, + 578, 1585, + -1324, -1089, + -71, 568, + -471, -26, + 1140, 909, + -856, -128, + 425, 740, + 140, 12, + 1595, 1891, + -2176, -2310, + -308, 541, + -315, -859, + -80, 1314, + -1782, 510, + 403, 450, + -607, 582, + 145, 1837, + -920, -1386, + -225, 872, + -395, -258, + 829, 981, + -945, 345, + 643, 241, + -56, -23, + 1211, 1482, + -1793, -1459, + 40, 400, + -239, -471, + 532, 1238, + -774, -516, + 244, 831, + -157, 152, + 576, 2287, + -928, -844, + 41, 759, + -161, -198, + 873, 1353, + -640, 105, + 695, 623, + 364, -184, + 1238, 2446 +}; + + + +const Word16 PowerCB_NB_fx[128] = +{ + -3349, -2784, + -784, 385, + -891, -562, + 126, 915, + -1518, -1438, + 304, 53, + -314, -447, + 687, 1219, + -2585, -1807, + -65, 153, + -1219, -337, + 497, 700, + -894, -1051, + 161, 451, + -46, -516, + 987, 1519, + -2277, -2303, + -354, 445, + -532, -540, + 5, 1271, + -1047, -1433, + 672, -225, + -335, -75, + 1007, 1056, + -1362, -1879, + -93, 367, + -468, -259, + 1800, -290, + -1118, -793, + 412, 472, + -9, -197, + 1471, 1634, + -2627, -2847, + -269, 164, + -689, -373, + 432, 940, + -1601, -839, + 311, 271, + -212, -251, + 543, 1714, + -2014, -1336, + 109, 241, + -789, -110, + 729, 888, + -418, -1277, + 256, 674, + 218, -217, + 1027, 2065, + -1769, -2293, + -276, 853, + -360, -764, + 376, 1247, + -1274, -1122, + 602, 272, + -133, -32, + 1374, 1118, + -1860, -1795, + -23, 620, + -525, 60, + 1070, 548, + -691, -799, + 701, 572, + 81, 18, + 1949, 2120 +}; + + +const Word16 sinc_fx[8][12]= /* sinc for warp/extrapolate, in Q14 */ +{ + {0,0,0,0,0,16384,0,0,0,0,0,0,}, + {-388,484,-638,939,-1773,15966,2281,-1063,694,-514,409,-339,}, + {-701,868,-1134,1639,-2949,14751,4917,-2106,1341,-982,776,-640,}, + {-895,1101,-1427,2029,-3503,12849,7709,-2964,1835,-1328,1042,-856,}, + {-947,1159,-1489,2086,-3476,10430,10430,-3476,2086,-1489,1159,-947,}, + {-856,1042,-1328,1835,-2964,7709,12849,-3503,2029,-1427,1101,-895,}, + {-640,776,-982,1341,-2106,4917,14751,-2949,1639,-1134,868,-701,}, + {-339,409,-514,694,-1063,2281,15966,-1773,939,-638,484,-388,}, +}; + + +const Word32 inverse_table[]= +{ + 0, + 134217728, 67108864, 44739242, 33554432, 26843545, 22369621, 19173961, 16777216, 14913080, 13421772, 12201611, 11184810, 10324440, 9586980, 8947848, 8388608, 7895160, 7456540, 7064090, 6710886, 6391320, 6100805, 5835553, 5592405, 5368709, 5162220, 4971026, 4793490, 4628197, 4473924, 4329604, 4194304, 4067203, 3947580, 3834792, 3728270, 3627506, 3532045, 3441480, 3355443, 3273603, 3195660, 3121342, 3050402, 2982616, 2917776, 2855696, 2796202, 2739137, 2684354, 2631720, 2581110, 2532409, 2485513, 2440322, 2396745, 2354696, 2314098, 2274876, 2236962, 2200290, 2164802, 2130440, 2097152, 2064888, 2033601, 2003249, 1973790, 1945184, 1917396, 1890390, 1864135, 1838599, 1813753, 1789569, 1766022, 1743087, 1720740, 1698958, 1677721, 1657008, 1636801, 1617081, 1597830, 1579032, 1560671, 1542732, 1525201, 1508064, 1491308, 1474920, 1458888, 1443201, 1427848, 1412818, 1398101, 1383687, 1369568, 1355734, 1342177, 1328888, 1315860, 1303084, 1290555, 1278264, 1266204, 1254371, 1242756, 1231355, 1220161, 1209168, 1198372, 1187767, 1177348, 1167110, 1157049, 1147160, 1137438, 1127880, 1118481, 1109237, 1100145, 1091201, 1082401, 1073741, 1065220, 1056832, 1048576, 1040447, 1032444, 1024562, 1016800, 1009155, 1001624, 994205, 986895, 979691, 972592, 965595, 958698, 951898, 945195, 938585, 932067, 925639, 919299, 913045, 906876, 900790, 894784, 888859, 883011, 877240, 871543, 865920, 860370, 854889, 849479, 844136, 838860, 833650, 828504, 823421, 818400, 813440, 808540, 803698, 798915, 794187, 789516, 784898, 780335, 775825, 771366, 766958, 762600, 758292, 754032, 749819, 745654, 741534, 737460, 733430, 729444, 725501, 721600, 717741, 713924, 710146, 706409, 702710, 699050, 695428, 691843, 688296, 684784, 681308, 677867, 674460, 671088, 667749, 664444, 661171, 657930, 654720, 651542, 648394, 645277, 642190, 639132, 636102, 633102, 630130, 627185, 624268, 621378, 618514, 615677, 612866, 610080, 607320, 604584, 601873, 599186, 596523, 593883, 591267, 588674, 586103, 583555, 581029, 578524, 576041, 573580, 571139, 568719, 566319, 563940, 561580, 559240, 556920, 554618, 552336, 550072, 547827, 545600, 543391, 541200, 539027, 536870, 534731, 532610, 530504, 528416, 526344, +}; + + +const Word16 W_DTX_HO_FX[HO_HIST_SIZE] = /* Q15 */ +{ + 6554, 5243, 4194, 3355, 2684, 2147, 1718, 344 +}; + +const Word16 HO_ATT_FX[5] = /* Q15 */ +{ + 17597, 20205, 22410, 23198, 23198 +}; + +/*----------------------------------------------------------------------------------* + * SWB HR BWE + *----------------------------------------------------------------------------------*/ + +const Word16 wscw16q15_fx[240] = +{ + -32768, -32766, -32764, -32759, -32754, -32747, -32738, -32729, -32717, -32705, -32691, + -32675, -32658, -32640, -32621, -32600, -32577, -32553, -32528, -32501, -32473, -32444, + -32413, -32381, -32348, -32313, -32276, -32239, -32200, -32159, -32117, -32074, -32029, + -31984, -31936, -31887, -31837, -31786, -31733, -31679, -31624, -31567, -31508, -31449, + -31388, -31326, -31262, -31197, -31131, -31063, -30994, -30924, -30853, -30780, -30705, + -30630, -30553, -30475, -30395, -30315, -30232, -30149, -30064, -29979, -29891, -29803, + -29713, -29622, -29530, -29436, -29341, -29245, -29148, -29049, -28949, -28848, -28746, + -28642, -28537, -28431, -28324, -28216, -28106, -27995, -27883, -27770, -27655, -27540, + -27423, -27305, -27186, -27066, -26944, -26821, -26698, -26573, -26447, -26320, -26191, + -26062, -25931, -25800, -25667, -25533, -25398, -25262, -25125, -24986, -24847, -24707, + -24565, -24423, -24279, -24135, -23989, -23843, -23695, -23546, -23397, -23246, 23095, + 22942, 22788, 22634, 22478, 22322, 22164, 22006, 21846, 21686, 21525, 21363, + 21199, 21035, 20871, 20705, 20538, 20371, 20202, 20033, 19863, 19692, 19520, + 19347, 19174, 18999, 18824, 18648, 18472, 18294, 18116, 17937, 17757, 17576, + 17395, 17213, 17030, 16846, 16662, 16477, 16291, 16105, 15917, 15730, 15541, + 15352, 15162, 14972, 14781, 14589, 14397, 14204, 14010, 13816, 13621, 13426, + 13230, 13033, 12836, 12639, 12441, 12242, 12043, 11843, 11643, 11442, 11241, + 11039, 10837, 10634, 10431, 10228, 10024, 9819, 9615, 9409, 9204, 8998, + 8791, 8585, 8377, 8170, 7962, 7754, 7545, 7336, 7127, 6918, 6708, + 6498, 6288, 6077, 5866, 5655, 5444, 5232, 5020, 4808, 4596, 4383, + 4171, 3958, 3745, 3532, 3319, 3105, 2892, 2678, 2464, 2250, 2036, + 1822, 1608, 1394, 1179, 965, 751, 536, 322, 107 +}; +const Word16 wscw16q15_8_fx[40] = +{ + -32762, -32711, -32610, -32459, -32258, -32007, -31706, -31357, + -30959, -30514, -30022, -29483, -28899, -28270, -27598, -26883, + -26127, -25330, -24494, -23621, 22711, 21766, 20788, 19777, + 18736, 17666, 16569, 15447, 14300, 13132, 11943, 10736, + 9512, 8274, 7022, 5760, 4490, 3212, 1929, 643 +}; +const Word16 wscw16q15_16_fx[80] = +{ + -32766, -32754, -32729, -32691, -32640, -32577, -32501, -32413, + -32313, -32200, -32074, -31936, -31786, -31624, -31449, -31262, + -31063, -30853, -30630, -30395, -30149, -29891, -29622, -29341, + -29049, -28746, -28431, -28106, -27770, -27423, -27066, -26698, + -26320, -25931, -25533, -25125, -24707, -24279, -23843, -23397, + 22942, 22478, 22006, 21525, 21035, 20538, 20033, 19520, + 18999, 18472, 17937, 17395, 16846, 16291, 15730, 15162, + 14589, 14010, 13426, 12836, 12242, 11643, 11039, 10431, + 9819, 9204, 8585, 7962, 7336, 6708, 6077, 5444, + 4808, 4171, 3532, 2892, 2250, 1608, 965, 322 +}; +const Word16 wscw16q15_32_fx[160] = +{ + -32768, -32764, -32758, -32749, -32736, -32720, -32701, -32679, -32654, -32626, -32594, + -32559, -32522, -32481, -32437, -32389, -32339, -32286, -32229, -32169, -32107, -32041, + -31972, -31900, -31825, -31747, -31665, -31581, -31494, -31403, -31310, -31214, -31114, + -31012, -30906, -30798, -30687, -30572, -30455, -30335, -30212, -30086, -29957, -29825, + -29690, -29553, -29412, -29269, -29123, -28974, -28823, -28668, -28511, -28351, -28188, + -28023, -27855, -27684, -27511, -27335, -27156, -26975, -26791, -26604, -26415, -26223, + -26029, -25833, -25633, -25432, -25228, -25021, -24812, -24601, -24387, -24171, -23953, + -23732, -23509, -23284, 23056, 22827, 22595, 22361, 22125, 21886, 21646, 21403, + 21159, 20912, 20663, 20413, 20160, 19905, 19649, 19390, 19130, 18868, 18604, + 18338, 18071, 17802, 17531, 17258, 16984, 16708, 16430, 16151, 15871, 15588, + 15305, 15019, 14733, 14445, 14155, 13865, 13572, 13279, 12984, 12688, 12391, + 12093, 11793, 11492, 11191, 10888, 10584, 10279, 9973, 9666, 9358, 9049, + 8740, 8429, 8118, 7806, 7493, 7180, 6865, 6550, 6235, 5919, 5602, + 5285, 4967, 4649, 4330, 4011, 3692, 3372, 3052, 2731, 2411, 2090, + 1768, 1447, 1126, 804, 483, 161 +}; + +/*------------------------------------------------------------------------------* + * HQ MDCT tables + *------------------------------------------------------------------------------*/ +const Word16 hvq_class_c_fx[16] = /* Q15 */ +{ + -7617, -14387, 2136, 6914, + 4821, -4428, 14131, -4538, + -4538, 14131, -4428, 4821, + 6914, 2136, -14387, -7617 +}; +const Word32 dicn_fx[40] = /* Q=14 */ +{ + 2147483647, 1518500224, + 1073741824, 759250112, + 536870912, 379625056, + 268435456, 189812528, + 134217728, 94906264, + 67108864, 47453132, + 33554432, 23726566, + 16777216, 11863283, + 8388608, 5931642, + 4194304, 2965821, + 2097152, 1482910, + 1048576, 741455, + 524288, 370728, + 262144, 185364, + 131072, 92682, + 65536, 46341, + 32768, 23170, + 16384, 11585, + 8192, 5793, + 4096, 2896 +}; +const Word16 sqac_headroom_fx[146] = /* Q0 */ +{ + 0 /*not used */, 0, 0, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, + 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4 +}; + +const Word16 inv_N_fx[32] = /* Q15 */ +{ + 0, 1056, 2113, 3170, + 4227, 5284, 6341, 7398, + 8455, 9512, 10569, 11626, + 12683, 13740, 14797, 15854, + 16912, 17969, 19026, 20083, + 21140, 22197, 23254, 24311, + 25368, 26425, 27482, 28539, + 29596, 30653, 31710, 32767 +}; + +const Word16 hvq_bwe_fac_fx[16] = /* Q15 */ +{ + 16384, 17408, 18432, 19456, + 20480, 21504, 22528, 23552, + 24576, 25600, 26624, 27648, + 28672, 29696, 30720, 31744 +}; + +const Word16 att_step_fx[4]= /* Q=13 */ +{ + 32767, 16384, 10923, 8192 +}; + +const Word16 gain_att_fx[40]= /* Q=15 */ +{ + 15711, 19367, 21781, 23743, 24899, 25929, 26758, 27514, + 28059, 28562, 28994, 29398, 29693, 29970, 30213, 30442, + 30619, 30786, 30936, 31077, 31190, 31298, 31395, 31488, + 31564, 31637, 31704, 31768, 31822, 31873, 31920, 31966, + 32005, 32042, 32077, 32111, 32140, 32168, 32195, 32220 +}; + +const Word16 stab_trans_fx[10] = /* Q15 */ +{ + 16384, 11381, 7232, 4292, 2433, + 1341, 728, 391, 209, 112 +}; + +const Word16 env_stab_tp_fx[2][2] = /* Q15 */ +{ + {32735, 16384}, + {33, 16384} +}; + + +const Word16 subf_norm_groups_fx[4][11] = +{ + {0,1,8,9,16,20,24,28,32,36,40}, + {2,3,10,11,17,21,25,29,33,37,41}, + {4,5,12,13,18,22,26,30,34,38,42}, + {6,7,14,15,19,23,27,31,35,39,43} +}; + +const Word32 dicn_pg_fx[45] = /* Q12 */ +{ + 536870912, 451452834, 379625056, 319225344, 268435456, + 225726416, 189812528, 159612672, 134217728, 112863208, + 94906264, 67108864, 47453132, 33554432, 23726566, + 16777216, 11863283, 8388608, 5931641, 4194304, + 2965821, 2097152, 1482910, 1048576, 741455, + 524288, 370728, 262144, 185364, 131072, + 92682, 65536, 46341, 32768, 23170, + 16384, 11585, 8192, 5793, 4096, + 2896, 2048, 1448, 1024, 724 +}; + +const Word16 hvq_peak_cb_fx[1024] = /* Q15 */ +{ + -22652,-20549,-23019, 13968,-25496,-27493, -6957, 5753,-19678,-20274, + -6119, 18297, -5329,-22843,-21254, 13929,-27525,-29034, 563, 7265, + -26138,-13138, -9678, 7972, -517,-20830,-10703, 26832,-27818,-21449, + 208, 6297,-14803,-28396, -7655, 5118, 15134,-24005,-21776, 25330, + -11282,-23669,-20340, -2006,-16212,-24127, 9075, 22581,-20047,-25695, + -254, 6509,-17174,-29714, 1589, 7104,-17683, -4117, -4049, 22347, + -28338,-13898, 671, 6777,-18368,-17925, -7409, 5169,-22093,-19561, + 702, 5969, -6610,-27398, -4875, 8773,-29634, -5552, 272, 6992, + -9167,-19887, -9136, 6447,-23125,-25612, 9760, 5749,-10410,-29816, + 1606, 7019,-13758,-24849, 2084, 7129,-17795,-16160, 596, 7287, + -22276,-11145, 521, 6474,-13471,-20705, -74, 6740, 1891,-16245, + -12763, 13602, -1617,-27384, -9648, 2511,-21802,-11734, -4836, -1602, + -9670,-27913, 6456, 6338,-23227, -4603, 754, 5830, -7699,-24416, + 2204, 6518,-27591, 2763, 1885, 6839,-15248,-10500, 344, 6942, + -13247, -9761, -4486, 4294,-12097,-15164, 637, 6142,-25994,-16384, + 17277, 6511,-10346,-26179, 923, -2374,-13316,-18125, 6841, 7100, + -21083,-24251, 4207, -9464,-22914, -7057, 8647, 8026, 2488,-20731, + -799, 13754, -3451,-12872, 2545, 17315, 2576,-19594,-10340, 4361, + -7007,-19401, 1937, 6751, 17502,-24923,-16948, 8534, -3436,-29004, + 6315, 6467,-16936, -4957, 591, 6604, 1099,-26790, -708, 5543, + -5949,-14167, -4750, 4068,-10682,-14990, -7489, -5197, 169, -6472, + -5143, 16200,-20331, 1722, 395, 6233,-15661,-22913, 24689, 14221, + -3892,-22862, 5154, 6301, -8786,-10120, 216, 6831,-12390,-11062, + 4824, 6473, -7705, -4195, -5326, 6572, -560,-20773, -2777, 1822, + -6703,-14413, 2409, 6083,-10595,-25038, 14291, 4825, 2064,-25736, + 16863, 20463, -2752,-29103, 12609, 7539, -7638,-18024, 1948, 689, + -10961, -5839, 683, 6170,-26004, 12209, 10742, 15580, -2105, -8625, + -4932, 6977, -9940,-15129, 12160, 9806,-13921, -55, 440, 6315, + -305, -6080, 11303, 25730,-12423, -3161, 6875, 9836, -2780,-16434, + 4128, 5778, 17790,-10991, -6633, 21111, 12367,-26550,-10581, -2530, + -6713,-10210, 4804, 6280, -5932, 2832, 4978, 18330, 2696,-23822, + -11870,-13313, 5266,-10870, -7933, 4455, -3155,-10994, 2225, 5803, + 820,-11966, -1397, 5344, -5027, -7230, 1236, 5812, -1649,-21007, + 8948, 5539,-16246, -801, -533, -3132, -8272, -1302, 367, 5958, + -26574, -3470, 7126, -8876, -4819, -5380, -3923, 1466, 1929,-20655, + 4419, 3663, 2437,-26758, 10897, 5616, -6601,-10394, 2148, 137, + 15007,-22909, -3948, 6197, -9059,-27702, 23041, 4088, 8312, -267, + 2973, 25579, -3795, -3612, -489, 5401, 7711,-25887, 3443, 2623, + -24306, 3091, 13248, 3273, -3113, -1410, 3541, 12047, 306,-11933, + -4493, -1997,-18725, 8257, 7593, 7218,-13588, -8411, 8715, -1137, + -12028, 5907, 17904, 21327, -2223,-22989, 9863, -1633, -723, -5944, + 714, 5170, 2128,-15199, 2081, 1626, -482, -8521, 8131, 10765, + 53,-12020, 5152, 5033, 2361,-13747, 24714, 26357, 1074,-28538, + 18087, 4333, 1067,-22148, 14277, 5540, 729,-15049, 7936, 4648, + -16646, -6350, 23646, 9628, -91, -8477, 3298, 4297, 3499, -7417, + -2214, 2931, -4795, -4424, 6487, 4264, -9333, 3377, 6570, 5734, + 1733,-17598, 11163, 4167, -2713,-16183, 14693, 4188,-23780, 9825, + 25701, 15331, 586,-19288, 21576, 12040, 11328,-15656, 2944, 7335, + 9203,-16906, -5723, -5371, -7906, -4632, 12470, 5724, -123,-16520, + 976, -8288, 1262, -3966, -3014, -148, 230, -2169, 505, 3954, + -2256,-11474, 9990, 2644, 4841, -8017, -4617, -2959, 24226,-22733, + 7475, 17722, 6747, -5782, 4877, 8664, -6893,-24218, 12181,-14683, + 2839, -7574, 4815, 2376, 2680, -3986, 1749, 2061, -563, 3232, + 3039, 5761, 343, -4150, 6600, 3792, 6356, 7199, 10702, 24266, + -25636,-12157, 22874,-14633, 2438, -8680, 8312, 3091, 7135, -3110, + 268, 4547, 4272, 4886, 5861, 14177, 11382,-10386, -767, 1448, + 1770,-28758, 27658, 4643, -3008,-10314, 18024, 5252, 6999,-17854, + 9789, 909, 1556,-21532, 20929, 3182, 26836,-23774, -2868, 3509, + -9884,-14471, 24685, 193, -3300, -5891, 5237, -5722, -9043,-14338, + 17448, -7167, -683, 26, 4002, -235, 3072,-12689, 13537, 2670, + 3577,-10477, 10097, 1435, 17713,-24555, 7486, 1713, 6633, -6645, + 1863, -783, 3185, -8349, 3975, -3967, 8090,-23915, 7470, -8732, + 2793,-16733, 17412, 1948, -5975,-14195, 1741,-22095, 3376, -782, + 18258, 16642, 3845, -3536, 5136, 335, 3267, -719, 10538, 7756, + -10993, 5165, 17885, 4767, 4733, -7751, 15643, 8215, 3678, 1686, + 3571, 2189,-11186, 1470, 6152,-11489, 4353, -2197, 1357, -3164, + 4258, -6029, 8420, -230, 6220, -1478, 2105, -787, -4229, -4632, + 15095, -1672, 1986,-16134, 14035, -6088, 7849,-14512, 2875,-10127, + 4796,-14269, -8761,-25428, 1192,-24490, 22001, -6216, 258,-10418, + 27459, 10524, -754, 7182, 7574, 3444, 5995, 3253, 25190, 25483, + 6379, -6363, 409, -8435, -3319, 3253, 12035, 1358, 3184, -6482, + 12864, -216, 25363, -7652, -2971, 5718, 4969, -3415, 7040, -2605, + 2616,-21129, 28211, 1289, 2553,-15075, 23833, 1871, 14598, -6793, + 7189, 4535, 5581, -1997, 4257, -4337, 6027,-10630, 9913, -5633, + 3695,-11614, 19091, 585, 4415, -8798, 15569, -1099, -879, 752, + 19480, 5412, 5743, 448, 9863, 1342, 20634,-16941, -7404,-16938, + -11946, 17852, 19422, 5918, 12538,-20829, 22707, 1113, 4715, -4341, + 12573, -3709, 4015, -8219, 3349,-17549, 6395, -1551, 4414, -8302, + 24598,-24474, 21909, 9778, 5346, 1386, 6942, -4708, -1507, 2077, + 8224,-10420, 6088, -3411, 8824, -6355, 7219, 17353, 22325, 25889, + 6666, -1811, 1964,-13461, 8123, -4454, 26614, 11418, 4582, -7133, + 18420, -3918, -264, 10545, 24810, 12821, 6936,-22880, 10241,-24118, + 3108, -7220, 11991,-12963, 4237,-10392, 23417, -2591, 4624,-14780, + 29121, -1235, 7543, -1157, 17358, 1244, 20161, -6319, 2575, -5204, + 4384, 5974, 10993, -2909, 1619, -4017, 26017, 722, 4659, 11545, + 14463, 4774, -2892, 10593, 15058, -4543, 1972,-15782, 26652,-10199, + 6046, -562, 11992, -8022, 6197, -349, 7928,-12070, 21399,-13670, + 15116, 99, 5829, -4061, 16713, -7200, -8904, 4170, 24814, -7599, + 12177, 6080, 19388, 11094, 4262, 1544, 17090, -4775, -6957, -5908, + 19576,-23176, 7126,-23499, 24889,-17683, 5514, -5416, 23284, -5830, + 6388, -1788, 14378,-11597, 5099, -8771, 28791, -4573, 6029, -4164, + 3217,-26929, 6427, 145, 9306,-17874, 5544, 3835, 25432, -15, + 8297,-10673, 21003,-15084, 6019, -7628, 13891,-22535, 27144, 1685, + 10077, 4230, 5211, -1543, 22179,-10638, 6385, 5710, 13476,-12976, + 5272, 17571, 23747, 5084, -2100, 9127, 13746,-20852,-16310, 15716, + 21422,-23074, 6532, -31, 17127,-16620, 5397, -3362, 28477, -9453, + 6238, 1258, 13189,-22475, 12895, -4568, 8062,-26648, 2873, 5975, + 22151,-15208, 6319, -507, 23117,-17415, 24129,-14207, 12908,-21101, + 7262, 8470, 25405, -9450, 5424, -1162, 29494,-16114, 21373, 22875, + 24554, 16783, 6684, 2453, 15785,-28885, 6504, 1085, 21619,-24241, + 21468, 620, 23222, -7235, 10917, 8863, 18570,-21606, 6710, -2091, + 28961,-25837, 6884, 20869, 27603, -8999, 6798, 5617, 28706,-21501, + 6066, 4720, 25084,-28951 +}; + +const Word16 rat_fx[SFM_N_WB] = { 24576, 24576, 24576, 24576, 24576, 24576, 24576, 24576, 24576, 24576, 24576, 24576, 24576, 24576, 24576, 24576, + 16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384, 13107, 13107 + }; + +const Word16 fb_inv_bwe_subband_width_fx[DIM_FB] = {819, 819, 409}; +const Word16 fb_smooth_factor_fx[DIM_FB] = {1024, 819, 512}; + +const Word16 hvq_thr_adj_fx[5] = { 23170, 16384, 8192, 16384, 23170}; /* Q15 */ + +const Word16 hvq_index_mapping_fx[4] = {0, 1, 3, 4}; + +const Word16 hq_nominal_scaling_inv[7] = {0, 8192, 11585, 0, 16384, 0, 20066}; /*Q13 */ +const Word16 hq_nominal_scaling[7] = {0, 32767, 23170, 0, 16384, 0, 13377}; /*Q15 */ + +/* %* lowered Table ROM, call with band_len_idx[sfm_size>>3] */ +/* % sfms =[ 8, 16, 24, 32, 48, 64, 80, 96 ], */ +/* sfm/8= [ 1 2 3 4 6 8 10 12]; */ +/* % idx= 0 1 2 3 4 5 6 7; */ +/* call with band_len_idx[sfm_size>>3] */ +const Word16 band_len_idx[1+(MAX_SFM_LEN_FX/8)] = +{ + /*sfm/8*/ /*1*/ /*2 */ /*3 */ /*4 */ /*6 */ /*8 */ /*10*/ /*12*/ + -1 , 0/*8*/, 1/*16*/,2/*24*/,3/*32*/,-1, 4/*48 */,-1, 5/*64 */,-1, 6/*80*/,-1, 7/*96*/ +}; +const Word16 band_len_ener_shift[8] = {1, 2, 2, 2, 3, 3 , 4/*sfm==80*/, 4 /*sfm==96*/}; /* 96 requires 1 bit more than 48 */ +/*% sfms=[8,16,24,32,48,64,80,96], round(sqrt(sfms)*2^11) */ +const Word16 fine_gain_pred_sqrt_bw[8] = {5793, 8192, 10033, 11585, 14189, 16384, 18318 , 20066 }; /* (Q11) */ +const Word32 SQRT_DIM_fx[1+PVQ_MAX_BAND_SIZE] = /* sqrt(x) for x = 0, 1, ..., 64. in Q15 */ +{ + 0, 32768, 46341, 56756, 65536, 73271, 80265, 86696, + 92682, 98304, 103622, 108679, 113512, 118147, 122607, 126910, + 131072, 135106, 139023, 142832, 146543, 150162, 153696, 157150, + 160530, 163840, 167085, 170268, 173392, 176461, 179478, 182445, + 185364, 188238, 191069, 193858, 196608, 199320, 201996, 204636, + 207243, 209818, 212361, 214874, 217358, 219814, 222243, 224646, + 227023, 229376, 231705, 234010, 236293, 238555, 240795, 243014, + 245213, 247393, 249554, 251696, 253820, 255926, 258015, 260088, + 262144 +}; + + + + + + +const Word16 finegain_1_fx[2] = {-12204, 12647}; /* Q14 */ +const Word16 finegain_2_fx[4] = {-17773, -5925, 6010, 18769}; /* Q14 */ +const Word16 finegain_3_fx[8] = {-16384, -11703, -7022, -2341, 2341, 7022, 11703, 16384}; /* Q14 */ +const Word16 finegain_4_fx[16] = /* Q14 */ +{ + -21683, -18292, -14998, -11876, -8936, -6239, -3702, -1371, + 945, 3275, 6088, 9079, 12450, 15999, 19796, 23868 +}; +const Word16 finegain_5_fx[32] = /* Q14 */ +{ + -21462, -18895, -16284, -14135, -12605, -11307, -10139, -8910, + -8028, -6792, -5638, -4812, -3672, -2681, -1725, -479, + 449, 1390, 2364, 3433, 4579, 5516, 6769, 7767, + 9085, 10152, 11009, 12535, 14765, 17093, 20094, 24716 +}; +const Word16* finegain_fx[5] = { finegain_1_fx, finegain_2_fx, finegain_3_fx, finegain_4_fx, finegain_5_fx }; +const Word16 gain_cb_size[MAX_GAIN_BITS] = {2, 4, 8, 16, 32}; + +const UWord32 exactdivodd_fx[ODD_DIV_SIZE_FX]=/* exactdivodd[0]=1/1,exactdivodd[1]=1/3 exactdivodd[47]=1/95 */ +{ + 1U, 2863311531U, 3435973837U, 3067833783U, 954437177U, 3123612579U, 3303820997U, 4008636143U, + 4042322161U, 678152731U, 1022611261U, 3921491879U, 3264175145U, 1749801491U, 1332920885U, 3186588639U, + 1041204193U, 2331553675U, 2437684141U, 2532929431U, 3247414297U, 799063683U, 2767867813U, 1736263375U, + 438261969U, 4210752251U, 2350076445U, 1483715975U, 3089362441U, 2693454067U, 3238827797U, 3204181951U, + 3237744577U, 128207979U, 2738819725U, 3811027319U, 3353604601U, 2519714147U, 1059797125U, 1631000239U, + 2014922929U, 724452315U, 4244438269U, 1875962727U, 4198451177U, 3539808211U, 1062196213U, 3571604383U +}; + + +const Word32 thren_fx[39] = /* Q8 */ +{ + 28215802, 19951584, 14107901, + 9975792, 7053951, 4987896, + 3526975, 2493948, 1763488, + 1246974, 881744, 623487, + 440872, 311744, 220436, + 155872, 110218, 77936, + 55109, 38968, 27554, + 19484, 13777, 9742, + 6889, 4871, 3444, + 2435, 1722, 1218, + 861, 609, 431, + 304, 215, 152, + 108, 76, 54 +}; + +/*------------------------------------------------------------------------------* + * LR-MDCT tables + *------------------------------------------------------------------------------*/ +/* NB short win: 7200/8000/9600, 13200/16400/24400 */ +static const Word16 band_width_40_4_6_0_0_0[4] = { 6, 8, 11, 15 }; +static const Word16 band_width_40_5_6_0_0_0[5] = { 6, 7, 7, 9, 11 }; + +/* NB long win: 7200, 8000, 9600, 13200, 16400/24400 */ +static const Word16 band_width_160_13_6_2_0_0[13] = { 6, 6, 6, 6, 7, 8, 9, 10, 13, 15, 19, 24, 31 }; +static const Word16 band_width_160_14_6_3_0_0[14] = { 6, 6, 6, 6, 6, 7, 8, 9, 10, 12, 15, 18, 22, 29 }; +static const Word16 band_width_160_17_6_3_0_0[17] = { 6, 6, 6, 6, 6, 6, 7, 7, 8, 8, 9, 10, 11, 13, 15, 17, 19 }; +static const Word16 band_width_160_18_6_4_0_0[18] = { 6, 6, 6, 6, 6, 6, 6, 7, 7, 8, 8, 9, 10, 11, 12, 14, 15, 17 }; + +/* WB short win: 13200/16400/24400 */ +static const Word16 band_width_80_7_6_0_0_0[7] = { 6, 7, 8, 10, 12, 16, 21 }; + +/* WB long win: 12800, 16000, 24000 */ +static const Word16 band_width_320_18_6_3_0_0[18] = { 6, 6, 6, 6, 6, 7, 7, 8, 10, 11, 13, 16, 19, 24, 30, 37, 47, 61 }; +static const Word16 band_width_320_20_6_3_0_0[20] = { 6, 6, 6, 6, 6, 6, 7, 8, 8, 9, 11, 12, 14, 17, 20, 23, 28, 34, 42, 51 }; + +/* SWB short win: 12800, 16000, 24000 */ +static const Word16 band_width_142_8_8_0_0_0[8] = {7,8,10,11,15,21,29,41 }; +static const Word16 band_width_160_8_8_0_0_0[8] = { 8, 9, 11,13,17,23,32,47 }; + +/* SWB long win: 12800, 16000, 24000 */ +static const Word16 band_width_568_22_6_2_0_0[22] = { 6, 6, 6, 6, 6, 6, 7, 8, 9, 10, 11, 13, 16, 19, 23, 28, 34, 42, 55, 68, 84, 105}; +static const Word16 band_width_640_24_6_4_0_0[24] = { 6, 6, 6, 6, 6, 6, 7, 7, 8, 9, 10, 11, 13, 15, 18, 21, 26, 32, 39, 48, 59, 74, 92,115 }; + +/* LR-MDCT: NB configuration tables */ +const Xcore_Config_fx xcore_config_8kHz_007200bps_long_fx = { 13, L_FRAME8k, band_width_160_13_6_2_0_0, 536870912L, 24576, 13107, 2, 2, 0, 0, 13107, 4260, 19661 }; +const Xcore_Config_fx xcore_config_8kHz_008000bps_long_fx = { 14, L_FRAME8k, band_width_160_14_6_3_0_0, 536870912L, 24576, 13107, 2, 2, 0, 0, 13107, 4260, 19661 }; +const Xcore_Config_fx xcore_config_8kHz_013200bps_long_fx = { 17, L_FRAME8k, band_width_160_17_6_3_0_0, 429496730L, 24576, 13107, 2, 4, 2, 24576, 13107, 4260, 19661 }; +const Xcore_Config_fx xcore_config_8kHz_016400bps_long_fx = { 18, L_FRAME8k, band_width_160_18_6_4_0_0, 322122547L, 24576, 13107, 2, 2, 0, 0, 13107, 4260, 19661 }; + +const Xcore_Config_fx xcore_config_8kHz_007200bps_short_fx = { 4, L_FRAME8k / NUM_TIME_SWITCHING_BLOCKS, band_width_40_4_6_0_0_0, 966367642L, 24576, 13107, 2, 2, 0, 0, 9830, 2949, 19661 }; +const Xcore_Config_fx xcore_config_8kHz_008000bps_short_fx = { 4, L_FRAME8k / NUM_TIME_SWITCHING_BLOCKS, band_width_40_4_6_0_0_0, 1181116006L, 24576, 13107, 2, 4, 0, 0, 9830, 2949, 19661 }; +const Xcore_Config_fx xcore_config_8kHz_013200bps_short_fx = { 5, L_FRAME8k / NUM_TIME_SWITCHING_BLOCKS, band_width_40_5_6_0_0_0, 751619276L, 24576, 11469, 2, 4, 0, 0, 22938, 3604, 19661 }; +const Xcore_Config_fx xcore_config_8kHz_016400bps_short_fx = { 5, L_FRAME8k / NUM_TIME_SWITCHING_BLOCKS, band_width_40_5_6_0_0_0, 536870912L, 24576, 11469, 2, 6, 0, 0, 22491, 3604, 19661 }; + +/* LR-MDCT: WB configuration tables */ +const Xcore_Config_fx xcore_config_16kHz_013200bps_long_fx = { 18, L_FRAME16k, band_width_320_18_6_3_0_0, 429496730L, 24576, 13106, 2, 6, 3, 24576, 13107, 3932, 18022 }; +const Xcore_Config_fx xcore_config_16kHz_016400bps_long_fx = { 20, L_FRAME16k, band_width_320_20_6_3_0_0, 429496730L, 24576, 13106, 2, 6, 3, 24576, 13107, 3932, 19660 }; + +const Xcore_Config_fx xcore_config_16kHz_013200bps_short_fx = { 7, L_FRAME16k / NUM_TIME_SWITCHING_BLOCKS, band_width_80_7_6_0_0_0, 966367642L, 24576, 9830, 2, 4, 0, 0, 9830, 4258, 18022 }; +const Xcore_Config_fx xcore_config_16kHz_016400bps_short_fx = { 7, L_FRAME16k / NUM_TIME_SWITCHING_BLOCKS, band_width_80_7_6_0_0_0, 966367642L, 24576, 11468, 2, 8, 0, 0, 9830, 4258, 19660 }; + +/* LR-MDCT: SWB configuration tables */ +const Xcore_Config_fx xcore_config_32kHz_013200bps_long_fx = { 22, 568, band_width_568_22_6_2_0_0, 322122547L, 24576, 6554, 2, 4, 5, 28672, 13107, 4260, 19661 }; +const Xcore_Config_fx xcore_config_32kHz_016400bps_long_fx = { 24, 640, band_width_640_24_6_4_0_0, 322122547L, 24576, 8192, 2, 4, 5, 28672, 13107, 4260, 19661 }; + +const Xcore_Config_fx xcore_config_32kHz_013200bps_short_fx = { 8, 568 / NUM_TIME_SWITCHING_BLOCKS, band_width_142_8_8_0_0_0, 1610612736L, 24576, 13107, 2, 4, 0, 0, 16384, 3604, 19661 }; +const Xcore_Config_fx xcore_config_32kHz_016400bps_short_fx = { 8, 640 / NUM_TIME_SWITCHING_BLOCKS, band_width_160_8_8_0_0_0, 644245094L, 24576, 8192, 2, 4, 0, 0, 9830, 4260, 19661 }; + +/*------------------------------------------------------------------------------* + * LR MDCT SWB BWE coding tables + *------------------------------------------------------------------------------*/ +const Word16 subband_offsets_12KBPS[NB_SWB_SUBBANDS] = {SWB_SB_OFF0_12KBPS, SWB_SB_OFF1_12KBPS, SWB_SB_OFF2_12KBPS, SWB_SB_OFF3_12KBPS}; +const Word16 subband_offsets_16KBPS[NB_SWB_SUBBANDS] = {SWB_SB_OFF0_16KBPS, SWB_SB_OFF1_16KBPS, SWB_SB_OFF2_16KBPS, SWB_SB_OFF3_16KBPS}; +const Word16 gain_table_SWB_BWE_fx[NB_SWB_SUBBANDS] = { -6554/*-0.4f*/, 1638/*0.1f*/, 9830/*0.6f*/, 18022/*1.1f*/ }; /* Q14 */ + +const Word16 bits_lagIndices_modeNormal_fx[NB_SWB_SUBBANDS] = {2, 2, 1, 1}; + +/* Search offset for the subbands that use a partial search */ +const Word16 subband_search_offsets_fx[NB_SWB_SUBBANDS] = +{ + 0, 0, 64, 64 +}; +/* SPT : shorten subband length table */ +const Word16 bw_SPT_tbl[2][SPT_SHORTEN_SBNUM]= +{ + {15, 31, 31, 31}, /* 13.2kbps: original band_width 53, 66, 82, 102 */ + {15, 15, 31, 31} /* 16.4kbps: original band_width 51 64, 80, 90 */ +}; + +/* Harmonic Mode */ +const Word16 bits_lagIndices_mode0_Har_fx[NB_SWB_SUBBANDS_HAR_SEARCH_SB] = {1,1}; + +/* 13.2 kbps */ +const Word16 subband_offsets_sub5_13p2kbps_Har_fx[NB_SWB_SUBBANDS_HAR] = +{ + SWB_SB_OFF0_SUB5_12KBPS_HAR, SWB_SB_OFF1_SUB5_12KBPS_HAR, SWB_SB_OFF2_SUB5_12KBPS_HAR, SWB_SB_OFF3_SUB5_12KBPS_HAR +}; + +/* Search offset for the subbands that use a partial search */ +const Word16 subband_search_offsets_13p2kbps_Har_fx[NB_SWB_SUBBANDS_HAR_SEARCH_SB] = +{ + 120, 210 +}; + +/* 16.4 kbps */ +const Word16 subband_offsets_sub5_16p4kbps_Har_fx[NB_SWB_SUBBANDS_HAR] = +{ + SWB_SB_OFF0_SUB5_16KBPS_HAR, SWB_SB_OFF1_SUB5_16KBPS_HAR, SWB_SB_OFF2_SUB5_16KBPS_HAR, SWB_SB_OFF3_SUB5_16KBPS_HAR +}; + +/* Search offset for the subbands that use a partial search */ +const Word16 subband_search_offsets_16p4kbps_Har_fx[NB_SWB_SUBBANDS_HAR_SEARCH_SB] = +{ + 120, 210 +}; + +const Word16 inv_tbl_fx[146] = +{ + 0, 32767, 16384, 10923, 8192, 6554, 5462, 4681, + 4096, 3641, 3277, 2979, 2731, 2521, 2341, 2185, + 2048, 1928, 1820, 1725, 1638, 1560, 1489, 1425, + 1365, 1311, 1260, 1214, 1170, 1130, 1092, 1057, + 1024, 993, 964, 936, 910, 886, 862, 840, + 819, 799, 780, 762, 745, 728, 712, 697, + 683, 669, 655, 643, 630, 618, 607, 596, + 585, 575, 565, 555, 546, 537, 529, 520, + 512, 504, 496, 489, 482, 475, 468, 462, + 455, 449, 443, 437, 431, 426, 420, 415, + 410, 405, 400, 395, 390, 386, 381, 377, + 372, 368, 364, 360, 356, 352, 349, 345, + 341, 338, 334, 331, 328, 324, 321, 318, + 315, 312, 309, 306, 303, 301, 298, 295, + 293, 290, 287, 285, 282, 280, 278, 275, + 273, 271, 269, 266, 264, 262, 260, 258, + 256, 254, 252, 250, 248, 246, 245, 243, + 241, 239, 237, 236, 234, 232, 231, 229, + 228, 226 +}; +const Word32 table_logcum_fx[563] = +{ + 0, 0, 0, 65536, 169408, 300480, 452650, 622058, 806041, + 1002649, 1210393, 1428099, 1654816, 1889761, 2132272, 2381791, 2637833, + 2899977, 3167853, 3441134, 3719526, 4002767, 4290623, 4582876, 4879332, + 5179812, 5484152, 5792200, 6103816, 6418871, 6737244, 7058822, 7383500, + 7711180, 8041769, 8375181, 8711333, 9050150, 9391557, 9735485, 10081869, + 10430647, 10781759, 11135150, 11490766, 11848556, 12208469, 12570461, 12934487, + 13300503, 13668469, 14038345, 14410092, 14783676, 15159061, 15536214, 15915101, + 16295692, 16677956, 17061866, 17447390, 17834504, 18223180, 18613394, 19005122, + 19398338, 19793020, 20189146, 20586692, 20985640, 21385968, 21787658, 22190686, + 22595040, 23000696, 23407638, 23815850, 24225314, 24636014, 25047934, 25461060, + 25875374, 26290862, 26707510, 27125304, 27544232, 27964278, 28385428, 28807674, + 29231000, 29655392, 30080844, 30507338, 30934866, 31363416, 31792978, 32223540, + 32655092, 33087624, 33521126, 33955588, 34391000, 34827352, 35264636, 35702840, + 36141960, 36581988, 37022908, 37464716, 37907404, 38350964, 38795388, 39240668, + 39686792, 40133760, 40581560, 41030188, 41479632, 41929888, 42380948, 42832808, + 43285456, 43738892, 44193104, 44648088, 45103840, 45560348, 46017612, 46475624, + 46934376, 47393864, 47854080, 48315024, 48776684, 49239060, 49702144, 50165928, + 50630412, 51095588, 51561452, 52028000, 52495224, 52963124, 53431688, 53900916, + 54370808, 54841348, 55312540, 55784380, 56256856, 56729972, 57203720, 57678096, + 58153096, 58628716, 59104952, 59581800, 60059256, 60537316, 61015980, 61495236, + 61975084, 62455524, 62936548, 63418156, 63900340, 64383100, 64866428, 65350328, + 65834792, 66319816, 66805396, 67291536, 67778224, 68265456, 68753240, 69241560, + 69730424, 70219816, 70709744, 71200208, 71691192, 72182704, 72674736, 73167280, + 73660344, 74153920, 74648008, 75142600, 75637704, 76133296, 76629400, 77125992, + 77623080, 78120656, 78618728, 79117280, 79616320, 80115840, 80615832, 81116312, + 81617256, 82118680, 82620568, 83122920, 83625744, 84129024, 84632768, 85136968, + 85641624, 86146728, 86652288, 87158304, 87664760, 88171664, 88679008, 89186792, + 89695016, 90203680, 90712776, 91222304, 91732256, 92242648, 92753464, 93264704, + 93776368, 94288448, 94800952, 95313872, 95827208, 96340960, 96855120, 97369696, + 97884672, 98400064, 98915856, 99432048, 99948648, 100465640, 100983040, 101500832, + 102019016, 102537592, 103056568, 103575928, 104095672, 104615808, 105136328, 105657232, + 106178520, 106700184, 107222232, 107744656, 108267456, 108790632, 109314176, 109838096, + 110362384, 110887040, 111412064, 111937448, 112463208, 112989320, 113515800, 114042640, + 114569832, 115097392, 115625304, 116153568, 116682184, 117211160, 117740480, 118270152, + 118800168, 119330536, 119861248, 120392312, 120923712, 121455448, 121987536, 122519960, + 123052720, 123585816, 124119248, 124653016, 125187120, 125721552, 126256320, 126791416, + 127326840, 127862592, 128398664, 128935072, 129471800, 130008856, 130546224, 131083920, + 131621936, 132160272, 132698920, 133237888, 133777176, 134316768, 134856688, 135396912, + 135937440, 136478288, 137019440, 137560912, 138102688, 138644768, 139187152, 139729840, + 140272832, 140816128, 141359712, 141903616, 142447808, 142992304, 143537104, 144082192, + 144627568, 145173248, 145719232, 146265504, 146812064, 147358912, 147906048, 148453488, + 149001200, 149549216, 150097504, 150646096, 151194960, 151744112, 152293536, 152843264, + 153393264, 153943536, 154494096, 155044944, 155596064, 156147456, 156699120, 157251072, + 157803296, 158355792, 158908560, 159461616, 160014928, 160568512, 161122368, 161676496, + 162230896, 162785568, 163340496, 163895696, 164451168, 165006896, 165562896, 166119152, + 166675664, 167232448, 167789504, 168346816, 168904368, 169462208, 170020288, 170578624, + 171137232, 171696080, 172255200, 172814560, 173374192, 173934064, 174494192, 175054576, + 175615216, 176176096, 176737232, 177298608, 177860256, 178422128, 178984256, 179546640, + 180109264, 180672128, 181235248, 181798608, 182362208, 182926064, 183490144, 184054480, + 184619056, 185183872, 185748928, 186314224, 186879760, 187445520, 188011536, 188577776, + 189144272, 189710992, 190277936, 190845136, 191412560, 191980208, 192548112, 193116224, + 193684592, 194253168, 194821984, 195391040, 195960320, 196529824, 197099568, 197669520, + 198239712, 198810144, 199380784, 199951648, 200522752, 201094080, 201665616, 202237392, + 202809376, 203381600, 203954032, 204526688, 205099568, 205672672, 206246000, 206819536, + 207393296, 207967280, 208541472, 209115888, 209690528, 210265376, 210840432, 211415712, + 211991216, 212566912, 213142848, 213718976, 214295328, 214871888, 215448672, 216025664, + 216602864, 217180272, 217757888, 218335712, 218913760, 219492000, 220070464, 220649120, + 221228000, 221807072, 222386368, 222965856, 223545552, 224125456, 224705568, 225285872, + 225866400, 226447120, 227028032, 227609168, 228190496, 228772016, 229353760, 229935680, + 230517824, 231100160, 231682688, 232265424, 232848352, 233431472, 234014800, 234598336, + 235182048, 235765968, 236350080, 236934400, 237518896, 238103600, 238688496, 239273600, + 239858880, 240444352, 241030032, 241615888, 242201952, 242788192, 243374640, 243961264, + 244548096, 245135104, 245722304, 246309696, 246897280, 247485056, 248073008, 248661152, + 249249488, 249838016, 250426720, 251015616, 251604704, 252193968, 252783424, 253373056, + 253962880, 254552896, 255143088, 255733472, 256324032, 256914768, 257505696, 258096800, + 258688096, 259279568, 259871216, 260463056, 261055056, 261647264, 262239632, 262832192, + 263424928, 264017840, 264610928, 265204192, 265797632, 266391264, 266985072, 267579040, + 268173200, 268767520, 269362048, 269956736, 270551584, 271146624, 271741824, 272337216, + 272932768, 273528480, 274124384, 274720480, 275316704, 275913120, 276509728, 277106496, + 277703424, 278300544, 278897824, 279495264, 280092896, 280690688, 281288640, 281886752, + 282485056, 283083520 +}; +const Word32 pow_getbitsfrompulses_fx[16] = /*Q21 */ +{ + 2097152, 2190001, 2286961, 2388214, 2493948, 2604365, 2719671, 2840081, + 2965822, 3097129, 3234251, 3377442, 3526976, 3683128, 3846194, 4016480 +}; +const Word16 DDP_fx[4] = { 3, 0, 1, 2 }; +const Word16 step_tcq_fx[8][STATES] = { {0,4}, {0,4}, {1,5}, {1,5}, {2,6}, {2,6}, {3,7}, {3,7} }; +const Word16 denc_fx[8][STATES] = { {0,2}, {2,0}, {1,3}, {3,1}, {2,0}, {0,2}, {3,1}, {1,3} }; /* enc trellis */ +const Word16 ddec_fx[8][STATES] = { {0,2}, {1,3}, {2,0}, {3,1}, {2,0}, {3,1}, {0,2}, {1,3} }; /* dec trellis */ + +const Word16 step_LSB_fx[STATES_LSB][2] = { {0,1}, {2,3}, {0,1}, {2,3} }; +const Word16 denc_LSB_fx[STATES_LSB][2] = { {0,3}, {2,1}, {3,0}, {1,2} }; +const Word16 dqnt_LSB_fx[STATES_LSB][4] = { {0,8,1,8}, {0,8,1,8}, {8,0,8,1}, {8,0,8,1} }; + +const Word16 dstep_LSB_fx[4][2] = { {0,2}, {0,2}, {1,3}, {1,3} }; +const Word16 ddec_LSB_fx[4][2] = { {0,3}, {3,0}, {2,1}, {1,2} }; + + +const Word16 SmoothingWin_NB875_fx[70] = /*Q15*/ +{ + 0, 16, 66, 148, 263, 411, 590, 802, 1045, 1318, + 1623, 1956, 2319, 2710, 3129, 3574, 4046, 4542, 5062, 5604, + 6169, 6754, 7358, 7981, 8620, 9275, 9945, 10627, 11321, 12025, + 12738, 13459, 14185, 14915, 15649, 16384, 17119, 17853, 18583, 19309, + 20030, 20743, 21447, 22141, 22823, 23493, 24148, 24787, 25410, 26014, + 26599, 27164, 27706, 28226, 28722, 29194, 29639, 30058, 30449, 30812, + 31145, 31450, 31723, 31966, 32178, 32357, 32505, 32620, 32702, 32752 +}; + +const Word16 SmoothingWin_NB2_fx[16] = +{ + 0, 315, 1247, 2761, 4799, 7282, 10114, 13188, 16384, 19580, 22654, 25486, 27969, 30007, 31521, 32453 +}; + + +const Word16 crit_bands_loc_fx[CRIT_NOIS_BAND] = +{ + 100, 200, 300, 400, 510, 630, 770, 920, 1080, 1270, 1480, 1720, + 2000, 2320, 2700, 3150, 3700, 4100, 4500, 5000, 5500, 6000, 6375 +}; + +const unsigned char hBitsMinus1_N01[2] = {1, 7}; + +const unsigned char hBitsMinus1_N02[65]= +{ + 64, 15, 23, 28, 31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, + 47, 48, 49, 49, 50, 51, 52, 53, 54, 54, 55, 56, 57, 57, 58, 59, + 60, 61, 62, 63, 63, 64, 65, 65, 67, 68, 69, 69, 70, 71, 72, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 80, 81, 82, 83, 84, 85, 86, 87, + 87 +}; + +const unsigned char hBitsMinus1_N03[65]= +{ + 64, 20, 33, 41, 48, 53, 57, 61, 64, 66, 69, 71, 73, 75, 76, 78, + 80, 81, 82, 83, 85, 86, 88, 90, 92, 93, 95, 96, 98, 99, 100, 102, + 104, 106, 108, 110, 111, 113, 114, 115, 118, 120, 122, 123, 125, 127, 128, 129, + 131, 133, 135, 137, 139, 141, 142, 144, 145, 146, 149, 151, 153, 155, 157, 158, + 160 +}; + +const unsigned char hBitsMinus1_N04[65]= +{ + 64, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94, 97, 100, 102, 105, + 107, 109, 111, 113, 115, 116, 119, 122, 125, 127, 130, 132, 134, 136, 138, 141, + 144, 147, 150, 152, 154, 156, 158, 160, 164, 167, 170, 173, 175, 177, 180, 182, + 184, 187, 190, 193, 196, 199, 201, 203, 205, 207, 211, 214, 217, 220, 222, 225, + 227 +}; + +const unsigned char hBitsMinus1_N05[54]= +{ + 53, 26, 45, 59, 70, 79, 87, 94, 100, 105, 110, 114, 118, 122, 125, 128, + 131, 134, 136, 139, 141, 144, 148, 152, 155, 158, 161, 164, 167, 170, 172, 176, + 181, 184, 188, 191, 194, 197, 200, 202, 207, 211, 215, 219, 222, 225, 228, 231, + 233, 238, 242, 246, 250, 253 +}; + +const unsigned char hBitsMinus1_N06[42]= +{ + 41, 28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149, + 153, 156, 159, 162, 165, 168, 173, 178, 183, 187, 191, 194, 198, 201, 204, 209, + 214, 219, 224, 228, 231, 235, 238, 241, 247, 253 +}; + +const unsigned char hBitsMinus1_N07[34]= +{ + 33, 30, 52, 70, 85, 98, 109, 118, 126, 134, 141, 147, 153, 158, 163, 168, + 172, 176, 180, 184, 188, 191, 197, 203, 208, 213, 218, 222, 226, 230, 233, 240, + 246, 252 +}; + +const unsigned char hBitsMinus1_N08[29]= +{ + 28, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180, 185, + 190, 195, 200, 204, 208, 212, 219, 226, 232, 238, 243, 248, 253 +}; + +const unsigned char hBitsMinus1_N09[25]= +{ + 24, 33, 58, 79, 97, 112, 125, 137, 148, 157, 166, 174, 182, 189, 195, 201, + 207, 212, 217, 222, 227, 231, 240, 247, 254 +}; + +const unsigned char hBitsMinus1_N10[22]= +{ + 21, 34, 61, 83, 101, 118, 132, 145, 157, 167, 177, 186, 194, 202, 209, 216, + 222, 228, 234, 239, 245, 250 +}; + +const unsigned char hBitsMinus1_N11[19]= +{ + 18, 35, 63, 86, 106, 123, 139, 152, 165, 176, 187, 197, 206, 214, 222, 230, + 237, 243, 250 +}; + +const unsigned char hBitsMinus1_N12[17]= +{ + 16, 36, 65, 89, 110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, + 250 +}; + +const unsigned char hBitsMinus1_N13[16]= +{ + 15, 37, 67, 92, 113, 133, 150, 165, 180, 193, 205, 216, 227, 237, 246, 254, +}; + +const unsigned char hBitsMinus1_N14[14]= +{ + 13, 38, 68, 94, 117, 137, 155, 171, 186, 200, 213, 225, 236, 247 +}; + +const unsigned char hBitsMinus1_N15[13]= +{ + 12, 39, 70, 97, 120, 141, 160, 177, 193, 207, 221, 233, 245 +}; + +const unsigned char hBitsMinus1_N16[13]= +{ + 12, 39, 71, 99, 123, 144, 164, 182, 198, 214, 228, 241, 253 +}; + +const unsigned char hBitsMinus1_N17[12]= +{ + 11, 40, 73, 101, 126, 148, 168, 187, 204, 220, 234, 248 +}; + +const unsigned char hBitsMinus1_N18[12]= +{ + 11, 41, 74, 103, 128, 151, 172, 191, 209, 225, 241, 255 +}; + +const unsigned char hBitsMinus1_N19[11]= +{ + 10, 41, 75, 105, 131, 154, 176, 196, 214, 231, 247 +}; + +const unsigned char hBitsMinus1_N20[11]= +{ + 10, 42, 77, 107, 133, 157, 179, 200, 219, 236, 253 +}; + +const unsigned char hBitsMinus1_N21[10]= +{ + 9, 43, 78, 108, 135, 160, 183, 204, 223, 241 +}; + +const unsigned char hBitsMinus1_N22[10]= +{ + 9, 43, 79, 110, 138, 163, 186, 207, 227, 246 +}; + +const unsigned char hBitsMinus1_N23[10]= +{ + 9, 44, 80, 111, 140, 165, 189, 211, 231, 250 +}; + +const unsigned char hBitsMinus1_N24[10]= +{ + 9, 44, 81, 113, 142, 168, 192, 214, 235, 255 +}; + +const unsigned char hBitsMinus1_N25[9]= +{ + 8, 45, 82, 114, 143, 170, 195, 217, 239 +}; + +const unsigned char hBitsMinus1_N26[9]= +{ + 8, 45, 83, 116, 145, 172, 197, 221, 242 +}; + +const unsigned char hBitsMinus1_N27[9]= +{ + 8, 46, 84, 117, 147, 175, 200, 224, 246 +}; + +const unsigned char hBitsMinus1_N28[9]= +{ + 8, 46, 84, 118, 149, 177, 202, 227, 249 +}; +const unsigned char hBitsMinus1_N29[9]= +{ + 8, 46, 85, 119, 150, 179, 205, 229, 252 +}; +const unsigned char hBitsMinus1_N30[8]= +{ + 7, 47, 86, 121, 152, 181, 207, 232 +}; +const unsigned char hBitsMinus1_N31[8]= +{ + 7, 47, 87, 122, 153, 182, 209, 235 +}; +const unsigned char hBitsMinus1_N32[8]= +{ + 7, 47, 87, 123, 155, 184, 212, 237 +}; +const unsigned char hBitsMinus1_N33[8]= +{ + 7, 48, 88, 124, 156, 186, 214, 240 +}; +const unsigned char hBitsMinus1_N34[8]= +{ + 7, 48, 89, 125, 158, 188, 216, 242 +}; +const unsigned char hBitsMinus1_N35[8]= +{ + 7, 49, 90, 126, 159, 189, 218, 245 +}; +const unsigned char hBitsMinus1_N36[8]= +{ + 7, 49, 90, 127, 160, 191, 220, 247 +}; +const unsigned char hBitsMinus1_N37[8]= +{ + 7, 49, 91, 128, 162, 193, 222, 249 +}; +const unsigned char hBitsMinus1_N38[8]= +{ + 7, 49, 91, 129, 163, 194, 224, 251 +}; +const unsigned char hBitsMinus1_N39[8]= +{ + 7, 50, 92, 130, 164, 196, 225, 253 +}; +const unsigned char hBitsMinus1_N40[8]= +{ + 7, 50, 93, 131, 165, 197, 227, 255 +}; +const unsigned char hBitsMinus1_N41[7]= +{ + 6, 50, 93, 131, 166, 199, 229 +}; +const unsigned char hBitsMinus1_N42[7]= +{ + 6, 51, 94, 132, 167, 200, 230 +}; +const unsigned char hBitsMinus1_N43[7]= +{ + 6, 51, 94, 133, 168, 201, 232 +}; +const unsigned char hBitsMinus1_N44[7]= +{ + 6, 51, 95, 134, 170, 203, 234 +}; +const unsigned char hBitsMinus1_N45[7]= +{ + 6, 51, 95, 135, 171, 204, 235 +}; +const unsigned char hBitsMinus1_N46[7]= +{ + 6, 52, 96, 135, 172, 205, 237 +}; +const unsigned char hBitsMinus1_N47[7]= +{ + 6, 52, 96, 136, 173, 206, 238 +}; +const unsigned char hBitsMinus1_N48[7]= +{ + 6, 52, 97, 137, 174, 208, 240 +}; +const unsigned char hBitsMinus1_N49[7]= +{ + 6, 52, 97, 138, 175, 209, 241 +}; +const unsigned char hBitsMinus1_N50[7]= +{ + 6, 53, 98, 138, 175, 210, 243 +}; +const unsigned char hBitsMinus1_N51[7]= +{ + 6, 53, 98, 139, 176, 211, 244 +}; +const unsigned char hBitsMinus1_N52[7]= +{ + 6, 53, 99, 140, 177, 212, 245 +}; +const unsigned char hBitsMinus1_N53[7]= +{ + 6, 53, 99, 140, 178, 213, 247 +}; +const unsigned char hBitsMinus1_N54[7]= +{ + 6, 54, 100, 141, 179, 214, 248 +}; +const unsigned char hBitsMinus1_N55[7]= +{ + 6, 54, 100, 142, 180, 216, 249 +}; +const unsigned char hBitsMinus1_N56[7]= +{ + 6, 54, 100, 142, 181, 217, 250 +}; +const unsigned char hBitsMinus1_N57[7]= +{ + 6, 54, 101, 143, 181, 218, 252 +}; +const unsigned char hBitsMinus1_N58[7]= +{ + 6, 54, 101, 143, 182, 219, 253 +}; +const unsigned char hBitsMinus1_N59[7]= +{ + 6, 55, 102, 144, 183, 220, 254 +}; +const unsigned char hBitsMinus1_N60[7]= +{ + 6, 55, 102, 145, 184, 221, 255 +}; +const unsigned char hBitsMinus1_N61[6]= +{ + 5, 55, 102, 145, 185, 221 +}; +const unsigned char hBitsMinus1_N62[6]= +{ + 5, 55, 103, 146, 185, 222 +}; +const unsigned char hBitsMinus1_N63[6]= +{ + 5, 55, 103, 146, 186, 223 +}; +const unsigned char hBitsMinus1_N64[6]= +{ + 5, 55, 103, 147, 187, 224 +}; + + + +const Word16 dsDiracsTab[65] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 23, 25, + 27, 29, 31, 33, 35, 37, 39, 43, + 47, 51, 55, 59, 63, 67, 71, 75, + 83, 91, 99, 107, 115, 123, 131, 139, + 147, 163, 179, 195, 211, 227, 243, 259, + 275, 291, 323, 355, 387, 419, 451, 483, + 512 +}; + +const unsigned int intLimCDivInvDQ31[67+1] = +{ + 0x00000000, 0x80000000, 0x40000000, 0x2aaaaaab, 0x20000000, 0x1999999a, 0x15555556, 0x12492493, + 0x10000000, 0x0e38e38f, 0x0ccccccd, 0x0ba2e8bb, 0x0aaaaaab, 0x09d89d8a, 0x0924924a, 0x08888889, + 0x08000000, 0x07878788, 0x071c71c8, 0x06bca1b0, 0x06666667, 0x06186187, 0x05d1745e, 0x0590b217, + 0x05555556, 0x051eb852, 0x04ec4ec5, 0x04bda130, 0x04924925, 0x0469ee59, 0x04444445, 0x04210843, + 0x04000000, 0x03e0f83f, 0x03c3c3c4, 0x03a83a84, 0x038e38e4, 0x03759f23, 0x035e50d8, 0x03483484, + 0x03333334, 0x031f3832, 0x030c30c4, 0x02fa0be9, 0x02e8ba2f, 0x02d82d83, 0x02c8590c, 0x02b93106, + 0x02aaaaab, 0x029cbc15, 0x028f5c29, 0x02828283, 0x02762763, 0x026a43a0, 0x025ed098, 0x0253c826, + 0x02492493, 0x023ee090, 0x0234f72d, 0x022b63cc, 0x02222223, 0x02192e2a, 0x02108422, 0x02082083, + 0x02000000, 0x01f81f82, 0x01f07c20, 0x01e9131b +}; + +const unsigned char obtainEnergyQuantizerDensity_f[57] = +{ + 1, 1, 1, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 4, 4, 4, + 4, 4, 4, 6, 6, 6, 6, 8, + 8, 8, 10,10,12,12,14,14, + 16,18,20,20,22,24,26,30, + 32,34,38,42,46,50,54,58, + 64,70,76,82,90,98,108,118, 128 +}; + + +/* (char)ceil(log2(hBitsN[N][0])) - 2) */ +unsigned char f_log2_n[ PVQ_MAX_BAND_SIZE + 1] = +{ + 0xff, 0xff, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01 +}; + +const unsigned char* const hBitsN[ PVQ_MAX_BAND_SIZE + 1 ]= +{ + f_log2_n/*N=0*/, hBitsMinus1_N01, hBitsMinus1_N02, hBitsMinus1_N03, hBitsMinus1_N04, + hBitsMinus1_N05, hBitsMinus1_N06, hBitsMinus1_N07, hBitsMinus1_N08, hBitsMinus1_N09, + hBitsMinus1_N10, hBitsMinus1_N11, hBitsMinus1_N12, hBitsMinus1_N13, hBitsMinus1_N14, + hBitsMinus1_N15, hBitsMinus1_N16, hBitsMinus1_N17, hBitsMinus1_N18, hBitsMinus1_N19, + hBitsMinus1_N20, hBitsMinus1_N21, hBitsMinus1_N22, hBitsMinus1_N23, hBitsMinus1_N24, + hBitsMinus1_N25, hBitsMinus1_N26, hBitsMinus1_N27, hBitsMinus1_N28, hBitsMinus1_N29, + hBitsMinus1_N30, hBitsMinus1_N31, hBitsMinus1_N32, hBitsMinus1_N33, hBitsMinus1_N34, + hBitsMinus1_N35, hBitsMinus1_N36, hBitsMinus1_N37, hBitsMinus1_N38, hBitsMinus1_N39, + hBitsMinus1_N40, hBitsMinus1_N41, hBitsMinus1_N42, hBitsMinus1_N43, hBitsMinus1_N44, + hBitsMinus1_N45, hBitsMinus1_N46, hBitsMinus1_N47, hBitsMinus1_N48, hBitsMinus1_N49, + hBitsMinus1_N50, hBitsMinus1_N51, hBitsMinus1_N52, hBitsMinus1_N53, hBitsMinus1_N54, + hBitsMinus1_N55, hBitsMinus1_N56, hBitsMinus1_N57, hBitsMinus1_N58, hBitsMinus1_N59, + hBitsMinus1_N60, hBitsMinus1_N61, hBitsMinus1_N62, hBitsMinus1_N63, hBitsMinus1_N64, +}; + + +const Word16 lim_neg_inv_tbl_fx[MAX_SPLITS + 1] = +{ + 0, + -32768, -16384, -10923, -8192, -6554, + -5462, -4681, -4096, -3641, -3277 +}; + + + +const Word16 Idx2Freq_Tbl[] = { 6554/*12.8*512*/, 48*512, 13108/*25.6*512*/, 32*512, 16*512, 8*512 }; /* in Q9 */ + +/*-------------------------------------------------------------------* + * inverse (reciprocal) of integer, used in FEC_fx.c, pitch_extr and in pitchDoubling_det + * 1/n = One_div[n-1] + *-------------------------------------------------------------------*/ +const Word16 One_div_fx[] = /* in Q15 */ +{ + 32767, /* 1/1 */ + 16384, /* 1/2 */ + 10923, /* 1/3 */ + 8192, /* 1/4 */ + 6554, /* 1/5 */ + 5461, /* 1/6 */ + 4681, /* 1/7 */ + 4096 /* 1/8 */ +}; + +/* + * 1/4 resolution interpolation filter (-3 dB at 0.791*fs/2) + */ +const Word16 E_ROM_inter4_1[UP_SAMP * L_INTERPOL1 + 1] = +{ + /* cut-off frequency at 0.9*fs/2 */ + 14746/*0.900000F Q14*/, + 13418/*0.818959F Q14*/, 9910/*0.604850F Q14*/, 5429/*0.331379F Q14*/, 1376/*0.083958F Q14*/, + -1242/*-0.075795F Q14*/, -2142/*-0.130717F Q14*/, -1732/*-0.105685F Q14*/, -766/*-0.046774F Q14*/, + 73/*0.004467F Q14*/, 455/*0.027789F Q14*/, 420/*0.025642F Q14*/, 206/*0.012571F Q14*/, + 32/*0.001927F Q14*/, -26/*-0.001571F Q14*/, -12/*-0.000753F Q14*/, 0/*0.000000f Q14*/ +}; +/* + * 1/6 resolution interpolation filter (-3 dB at 0.9*fs/2) + */ +const Word16 E_ROM_inter6_1[PIT_UP_SAMP6 * L_INTERPOL1 + 1] = +{ + 14759/*0.900848F Q14*/, + 14158/*0.864136F Q14*/, + 12453/*0.760071F Q14*/, + 9919/*0.605408F Q14*/, + 6948/*0.424072F Q14*/, + 3972/*0.242462F Q14*/, + 1377/*0.0840759F Q14*/, + -563/*-0.0343933F Q14*/, + -1729/*-0.105560F Q14*/, + -2152/*-0.131348F Q14*/, + -1984/*-0.121124F Q14*/, + -1450/*-0.0884705F Q14*/, + -780/*-0.0476379F Q14*/, + -168/*-0.0102539F Q14*/, + 267/*0.0162964F Q14*/, + 485/*0.0296021F Q14*/, + 512/*0.0312195F Q14*/, + 412/*0.0251160F Q14*/, + 258/*0.0157471F Q14*/, + 110/*0.00671387F Q14*/, + 0/*0.000000F Q14*/, + -65/*-0.00399780F Q14*/, + -97/*-0.00592041F Q14*/, + -108/*-0.00656128F Q14*/, + 0/*0.000000F Q14*/ +}; + + +const Word16 Grid[GRID100_POINTS+1] = +{ + 32767, 32751, 32703, 32622, 32509, 32364, + 32187, 31978, 31738, 31466, 31164, 30830, + 30466, 30072, 29649, 29196, 28714, 28204, + 27666, 27101, 26509, 25891, 25248, 24579, + 23886, 23170, 22431, 21669, 20887, 20083, + 19260, 18418, 17557, 16680, 15786, 14876, + 13951, 13013, 12062, 11099, 10125, 9141, + 8149, 7148, 6140, 5126, 4106, 3083, + 2057, 1029, 0, -1029, -2057, -3083, + -4106, -5126, -6140, -7148, -8149, -9141, + -10125, -11099, -12062, -13013, -13951, -14876, + -15786, -16680, -17557, -18418, -19260, -20083, + -20887, -21669, -22431, -23170, -23886, -24579, + -25248, -25891, -26509, -27101, -27666, -28204, + -28714, -29196, -29649, -30072, -30466, -30830, + -31164, -31466, -31738, -31978, -32187, -32364, + -32509, -32622, -32703, -32751, -32760 +}; + +/* 16-byte align end */ + +/*----------------------------------------------------------------------------------* + * impulse response with phase dispersion + * Used in lib_dec\enhancer.c + *----------------------------------------------------------------------------------*/ +/* 2.0 - 6.4 kHz phase dispersion in frequency domain (output of fft_rel) */ +const Word16 low_H[64] = /* (1Q14) */ +{ + 16388, 16380, 16386, 16381, 16382, 16382, 16381, 16383, 16385, 10265, + 10154, 9894, 14051, 16342, -531, 13216, 16372, 15509, 9406, 15948, + 4726, 14593, 10404, 9795, -16337, -1815, -10624, 12646, 14555, -12684, + 11388, 8175, 16382, -14198, 11781, 10378, 7515, 10423, -12473, 16284, + -1200, -13137, 12658, -7446, 15683, -3764, -13419, -5281, 521, -9686, + -16375, -1219, 8435, -13059, -12862, -12775, -1, 2, 0, -3, + -1, -1, -2, 1 +}; + +const Word16 low_H16k[80] = /* (1Q14) */ +{ + 16388, 16380, 16386, 16381, 16382, 16382, 16381, 16383, 16385, 10265, + 10154, 9894, 14051, 16342, -531, 13216, 16372, 15509, 9406, 15948, + 4726, 14593, 10404, 9795, -16337, -1815, -10624, 12646, 14555, -12684, + 11388, 8175, -4121, -13408, 10605, -12308, 16358, 4699, 7640, -7360, + 16382, -14639, -14494, 15695, -907, -10815, -12489, 9416, 15857, + -14198, 11781, 10378, 7515, 10423, -12473, 16284, -1200, -13137, 12658, + -7446, 15683, -3764, -13419, -5281, 521, -9686, -16375, -1219, 8435, + -13059, -12862, -12775, -1, 2, 0, -3, -1, -1, -2, 1 +}; + +/* 3.2 - 6.4 kHz phase dispersion in frequency domain (output of fft_rel) */ +const Word16 mid_H[64] = /* (1Q14) */ +{ + 16382, 16381, 16384, 16384, 16385, 16387, 16386, 16382, 16387, 16382, + 16385, 16385, 16385, 16384, 16382, 16388, 14847, 9629, 13248, 14486, + 10995, 642, 13817, 13779, 6468, 8664, 11634, 9780, -14636, -982, + 11746, -722, 16385, -16366, -11423, 16354, 7362, 13147, -11538, -13904, + -15052, -8862, 8811, -16371, -12146, 7660, -9638, -13254, -6923, 3, + -5, -2, -6, 1, 6, 5, -8, -2, 3, -5, + 0, -2, -4, 3 +}; + +const Word16 mid_H16k[80] = /* (1Q14) */ +{ + 16382, 16381, 16384, 16384, 16385, 16387, 16386, 16382, 16387, 16382, + 16385, 16385, 16385, 16384, 16382, 16388, 14847, 9629, 13248, 14486, + 10995, 642, 13817, 13779, 6468, 8664, 11634, 9780, -14636, -982, + 11746, -722, 108, -16195, -13199, -13289, 5114, 12941, 7110, 8873, + 16385, -13774, -14761, 10047, -15566, -9584, 9707, 2483, 16383, + -16366, -11423, 16354, 7362, 13147, -11538, -13904, -15052, -8862, + 8811, -16371, -12146, 7660, -9638, -13254, -6923, 3, -5, -2, -6, + 1, 6, 5, -8, -2, 3, -5, 0, -2, -4, 3 +}; + + +/*----------------------------------------------------------------------------------* + * Tables for ISF Quantizers + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Used in lib_com\disf.c, lib_dec\isf_dec.c and lib_enc\isf_enc.c + *----------------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------------* + * MA prediction coefficients for gain quantizer + * Used in "lib_enc\gain_enc.c" and "lib_dec\gain_dec.c". + *----------------------------------------------------------------------------------*/ + + +/* Initial LSF/ISF memory */ +const Word16 lsf_init[16] = /*14Q1*1.28*/ +{ + 960, 1920, 2880, 3840, 4800, 5760, 6720, 7680, 8640, 9600, 10560, 11520, 12480, 13440, 14400, 15360 +}; + + +/*----------------------------------------------------------------------------------* + * Bitstream packing ordering: + * Nb of bits per quantization index for each coding mode for layers R1 - R5 + * Used in lib_enc\bits_enc.c and lib_dec\bits_dec.c + *----------------------------------------------------------------------------------*/ + +const Word16 gain_corr_fac[3]= {0x4155, 0x40A9, 0x4055}; /* pow(10, 2^(-n-2)/28) (1Q14) */ +const Word16 gain_corr_inv_fac[3]= {0x7D67, 0x7EB2, 0x7F59}; /* pow(10,-2^(-n-2)/28) (0Q15) */ + +/* interpolation windows: Hann * modified Hamming */ +const Word16 inter4_2tcx2[4][4] = +{ + { 7620/*0.2325402f Q15*/, 17528/*0.5349195f Q15*/, 7620/*0.2325402f Q15*/, 0/*0.0000000f Q15*/ }, + { 4434/*0.1353017f Q15*/, 16694/*0.5094465f Q15*/, 11141/*0.3400065f Q15*/, 500/*0.0152453f Q15*/ }, + { 1995/*0.0608774f Q15*/, 14389/*0.4391226f Q15*/, 14389/*0.4391226f Q15*/, 1995/*0.0608774f Q15*/ }, + { 500/*0.0152453f Q15*/, 11141/*0.3400065f Q15*/, 16694/*0.5094465f Q15*/, 4434/*0.1353017f Q15*/ } +}; +const Word16 inter6_2tcx2[6][4] = +{ + { 7345/*0.2241379f Q15*/, 18079/*0.5517241f Q15*/, 7345/*0.2241379f Q15*/, 0/*0.0000000f Q15*/ }, + { 5119/*0.1562044f Q15*/, 17657/*0.5388595f Q15*/, 9798/*0.2990011f Q15*/, 194/*0.0059349f Q15*/ }, + { 3249/*0.0991379f Q15*/, 16444/*0.5018346f Q15*/, 12288/*0.3750000f Q15*/, 787/*0.0240275f Q15*/ }, + { 1800/*0.0549361f Q15*/, 14584/*0.4450639f Q15*/, 14584/*0.4450639f Q15*/, 1800/*0.0549361f Q15*/ }, + { 787/*0.0240275f Q15*/, 12288/*0.3750000f Q15*/, 16444/*0.5018346f Q15*/, 3249/*0.0991379f Q15*/ }, + { 194/*0.0059349f Q15*/, 9798/*0.2990011f Q15*/, 17657/*0.5388595f Q15*/, 5119/*0.1562044f Q15*/ } +}; + +const Word16 inter_core_12_8kHz_output_8kHz[] = +{ + 17528/*0.5349196f Q15*/, 16694/*0.5094466f Q15*/, 14389/*0.4391227f Q15*/, 11141/*0.3400065f Q15*/, + 7620/*0.2325402f Q15*/, 4434/*0.1353016f Q15*/, 1995/*0.0608773f Q15*/, 500/*0.0152453f Q15*/, + 0/*0.0000000f Q15*/ +}; +const Word16 inter_core_12_8kHz_output_16kHz[] = +{ + 14023/*0.4279357f Q15*/, 13592/*0.4147958f Q15*/, 12367/*0.3774199f Q15*/, 10533/*0.3214508f Q15*/, + 8350/*0.2548195f Q15*/, 6096/*0.1860321f Q15*/, 4017/*0.1225801f Q15*/, 2291/*0.0699165f Q15*/, + 1023/*0.0312127f Q15*/, 256/*0.0078047f Q15*/, 0/*0.0000000f Q15*/, 0/*0.0000000f Q15*/, + 0/*0.0000000f Q15*/ +}; +const Word16 inter_core_12_8kHz_output_32kHz[] = +{ + 7011/*0.2139679f Q15*/, 6957/*0.2123089f Q15*/, 6796/*0.2073979f Q15*/, 6535/*0.1994284f Q15*/, + 6184/*0.1887100f Q15*/, 5756/*0.1756491f Q15*/, 5267/*0.1607254f Q15*/, 4734/*0.1444646f Q15*/, + 4175/*0.1274097f Q15*/, 3608/*0.1100939f Q15*/, 3048/*0.0930161f Q15*/, 2511/*0.0766219f Q15*/, + 2008/*0.0612900f Q15*/, 1551/*0.0473253f Q15*/, 1146/*0.0349583f Q15*/, 798/*0.0243509f Q15*/, + 511/*0.0156063f Q15*/, 288/*0.0087817f Q15*/, 128/*0.0039024f Q15*/, 32/*0.0009753f Q15*/, + 0/*0.0000000f Q15*/ +}; +const Word16 inter_core_12_8kHz_output_48kHz[] = +{ + 4674/*0.1426452f Q15*/, 4658/*0.1421528f Q15*/, 4610/*0.1406841f Q15*/, 4531/*0.1382653f Q15*/, + 4422/*0.1349386f Q15*/, 4285/*0.1307618f Q15*/, 4122/*0.1258066f Q15*/, 3937/*0.1201564f Q15*/, + 3732/*0.1139041f Q15*/, 3511/*0.1071503f Q15*/, 3277/*0.1000000f Q15*/, 3033/*0.0925607f Q15*/, + 2783/*0.0849398f Q15*/, 2531/*0.0772420f Q15*/, 2280/*0.0695677f Q15*/, 2032/*0.0620107f Q15*/, + 1791/*0.0546572f Q15*/, 1559/*0.0475844f Q15*/, 1339/*0.0408600f Q15*/, 1132/*0.0345417f Q15*/, + 940/*0.0286774f Q15*/, 764/*0.0233055f Q15*/, 605/*0.0184558f Q15*/, 464/*0.0141503f Q15*/, + 341/*0.0104042f Q15*/, 237/*0.0072274f Q15*/, 152/*0.0046257f Q15*/, 85/*0.0026016f Q15*/, + 38/*0.0011560f Q15*/, 9/*0.0002890f Q15*/, 0/*0.0000000f Q15*/, 0/*0.0000000f Q15*/, + 0/*0.0000000f Q15*/ +}; +const Word16 inter_core_16kHz_output_8kHz[] = +{ + 18079/*0.5517241f Q15*/, 17657/*0.5388595f Q15*/, 16444/*0.5018346f Q15*/, 14584/*0.4450639f Q15*/, 12288/*0.3750000f Q15*/, 9798/*0.2990011f Q15*/, + 7345/*0.2241379f Q15*/, 5119/*0.1562044f Q15*/, 3249/*0.0991379f Q15*/, 1800/*0.0549361f Q15*/, 787/*0.0240275f Q15*/, 194/*0.0059349f Q15*/, + 0/*0.0000000f Q15*/ +}; +const Word16 inter_core_16kHz_output_16kHz[] = +{ + 18079/*0.5517241f Q15*/, 17657/*0.5388595f Q15*/, 16444/*0.5018346f Q15*/, 14584/*0.4450639f Q15*/, 12288/*0.3750000f Q15*/, 9798/*0.2990011f Q15*/, + 7345/*0.2241379f Q15*/, 5119/*0.1562044f Q15*/, 3249/*0.0991379f Q15*/, 1800/*0.0549361f Q15*/, 787/*0.0240275f Q15*/, 194/*0.0059349f Q15*/, + 0/*0.0000000f Q15*/ +}; +const Word16 inter_core_16kHz_output_32kHz[] = +{ + 9039/*0.2758621f Q15*/, 8986/*0.2742414f Q15*/, 8829/*0.2694298f Q15*/, 8571/*0.2615753f Q15*/, 8222/*0.2509173f Q15*/, 7791/*0.2377748f Q15*/, + 7292/*0.2225320f Q15*/, 6738/*0.2056203f Q15*/, 6144/*0.1875000f Q15*/, 5526/*0.1686403f Q15*/, 4899/*0.1495006f Q15*/, 4277/*0.1305132f Q15*/, + 3672/*0.1120690f Q15*/, 3097/*0.0945060f Q15*/, 2559/*0.0781022f Q15*/, 2067/*0.0630725f Q15*/, 1624/*0.0495690f Q15*/, 1235/*0.0376861f Q15*/, + 900/*0.0274680f Q15*/, 620/*0.0189188f Q15*/, 394/*0.0120137f Q15*/, 220/*0.0067120f Q15*/, 97/*0.0029675f Q15*/, 24/*0.0007394f Q15*/, + 0/*0.0000000f Q15*/ +}; +const Word16 inter_core_16kHz_output_48kHz[] = +{ + 6026/*0.1839080f Q15*/, 6011/*0.1834272f Q15*/, 5963/*0.1819912f Q15*/, 5886/*0.1796198f Q15*/, 5778/*0.1763457f Q15*/, 5643/*0.1722133f Q15*/, + 5481/*0.1672782f Q15*/, 5296/*0.1616061f Q15*/, 5088/*0.1552712f Q15*/, 4861/*0.1483546f Q15*/, 4618/*0.1409433f Q15*/, 4362/*0.1331275f Q15*/, + 4096/*0.1250000f Q15*/, 3823/*0.1166535f Q15*/, 3545/*0.1081796f Q15*/, 3266/*0.0996670f Q15*/, 2988/*0.0912002f Q15*/, 2715/*0.0828579f Q15*/, + 2448/*0.0747126f Q15*/, 2190/*0.0668293f Q15*/, 1942/*0.0592649f Q15*/, 1706/*0.0520681f Q15*/, 1484/*0.0452794f Q15*/, 1276/*0.0389306f Q15*/, + 1083/*0.0330460f Q15*/, 906/*0.0276422f Q15*/, 745/*0.0227295f Q15*/, 600/*0.0183120f Q15*/, 472/*0.0143894f Q15*/, 359/*0.0109575f Q15*/, + 262/*0.0080092f Q15*/, 181/*0.0055360f Q15*/, 116/*0.0035286f Q15*/, 65/*0.0019783f Q15*/, 29/*0.0008771f Q15*/, 7/*0.0002189f Q15*/, + 0/*0.0000000f Q15*/ +}; +const Word16 inter_core_25_6kHz_output_8kHz[] = +{ + 17528/*0.5349196f Q15*/, 16694/*0.5094466f Q15*/, 14389/*0.4391227f Q15*/, 11141/*0.3400065f Q15*/, + 7620/*0.2325402f Q15*/, 4434/*0.1353016f Q15*/, 1995/*0.0608773f Q15*/, 500/*0.0152453f Q15*/, + 0/*0.0000000f Q15*/ +}; +const Word16 inter_core_25_6kHz_output_16kHz[] = +{ + 17528/*0.5349196f Q15*/, 16694/*0.5094466f Q15*/, 14389/*0.4391227f Q15*/, 11141/*0.3400065f Q15*/, + 7620/*0.2325402f Q15*/, 4434/*0.1353016f Q15*/, 1995/*0.0608773f Q15*/, 500/*0.0152453f Q15*/, + 0/*0.0000000f Q15*/ +}; +const Word16 inter_core_25_6kHz_output_32kHz[] = +{ + 14023/*0.4279357f Q15*/, 13592/*0.4147958f Q15*/, 12367/*0.3774199f Q15*/, 10533/*0.3214508f Q15*/, + 8350/*0.2548195f Q15*/, 6096/*0.1860321f Q15*/, 4017/*0.1225801f Q15*/, 2291/*0.0699165f Q15*/, + 1023/*0.0312127f Q15*/, 256/*0.0078047f Q15*/, 0/*0.0000000f Q15*/, 0/*0.0000000f Q15*/, + 0/*0.0000000f Q15*/ +}; +const Word16 inter_core_25_6kHz_output_48kHz[] = +{ + 9349/*0.2852965f Q15*/, 9220/*0.2813740f Q15*/, 8843/*0.2698819f Q15*/, 8245/*0.2516166f Q15*/, + 7465/*0.2278099f Q15*/, 6554/*0.2000000f Q15*/, 5567/*0.1698781f Q15*/, 4559/*0.1391327f Q15*/, + 3582/*0.1093111f Q15*/, 2678/*0.0817166f Q15*/, 1879/*0.0573517f Q15*/, 1209/*0.0369093f Q15*/, + 682/*0.0208069f Q15*/, 303/*0.0092505f Q15*/, 76/*0.0023118f Q15*/, 0/*0.0000000f Q15*/, + 0/*0.0000000f Q15*/ +}; + +const TCX_LTP_FILTER tcxLtpFilters[12] = +{ + { inter_core_12_8kHz_output_8kHz, 2 }, + { inter_core_12_8kHz_output_16kHz, 3 }, + { inter_core_12_8kHz_output_32kHz, 5 }, + { inter_core_12_8kHz_output_48kHz, 8 }, + { inter_core_16kHz_output_8kHz, 2 }, + { inter_core_16kHz_output_16kHz, 2 }, + { inter_core_16kHz_output_32kHz, 4 }, + { inter_core_16kHz_output_48kHz, 6 }, + { inter_core_25_6kHz_output_8kHz, 2 }, + { inter_core_25_6kHz_output_16kHz, 2 }, + { inter_core_25_6kHz_output_32kHz, 3 }, + { inter_core_25_6kHz_output_48kHz, 4 }, +}; + +const SCALE_TCX_SETUP scaleTcxTable[13] = +{ + { 0, 0, 8000, 21955/*0.67f Q15*/ }, + { 0, 8000, 9600, 22938/*0.70f Q15*/ }, + { 0, 9600, 13200, 24904/*0.76f Q15*/ }, + { 0, 13200, 16400, 28180/*0.86f Q15*/ }, + { 0, 16400, 24400, 29491/*0.90f Q15*/ }, + { 0, 24400, 64000, 31457/*0.96f Q15*/ }, + { 1, 0, 8000, 32767/*1.f Q15*/ }, + { 1, 8000, 9600, 32767/*1.f Q15*/ }, + { 1, 9600, 13200, 32767/*1.f Q15*/ }, + { 1, 13200, 16400, 27853/*0.85f Q15*/ }, + { 1, 16400, 24400, 28836/*0.88f Q15*/ }, + { 1, 24400, 32000, 29491/*0.90f Q15*/ }, + { 1, 32000, 32400, 31130/*0.95f Q15*/ }, +}; + + +/*----------------------------------------------------------------------------------* +* Quantization table for pitch and innovation gain (gamma) * +*----------------------------------------------------------------------------------*/ +const Word16 E_ROM_qua_gain5b_const[NB_QUA_GAIN5B * 2] = +{ + 1774,577, + 2090,1805, + 2103,3371, + 3908,1116, + 4834,2500, + 6030,4763, + 6838,1334, + 7490,2033, + 8585,3036, + 9845,1575, + 10437,2320, + 10649,3739, + 11298,945, + 12108,1920, + 12310,5108, + 12391,2758, + 12659,1237, + 13729,1557, + 13798,2201, + 13972,3275, + 14881,993, + 15175,1776, + 15409,16190, + 15551,2395, + 15879,4048, + 16341,1335, + 16988,2918, + 18317,7449, + 18368,2026, + 19114,1364, + 19991,4472, + 20644,2790, +}; +#define QUA_PITCH_E 1 +#define QUA_CODE_E 4 + +const Word16 E_ROM_qua_gain6b_const[NB_QUA_GAIN6B * 2] = +{ + 0,2758, + 143,3562, + 397,2146, + 544,4306, + 952,1726, + 1236,724, + 1779,3158, + 1820,5448, + 1975,2473, + 2121,1343, + 3049,3912, + 3081,1885, + 3289,8261, + 3416,2843, + 3495,2204, + 3831,3386, + 4295,4590, + 4300,2476, + 4345,1545, + 4913,1122, + 5198,2080, + 5200,3079, + 5448,3714, + 5482,2689, + 5546,1817, + 5783,17318, + 5934,6236, + 6156,2320, + 6481,4225, + 6828,3351, + 6832,5045, + 6888,2895, + 7186,2559, + 7214,1663, + 7373,2052, + 7906,3819, + 8192,1372, + 8452,3063, + 8464,2354, + 9021,4468, + 9037,2715, + 9175,1874, + 9219,3463, + 9831,2155, + 10523,5383, + 10557,9061, + 10618,3093, + 10633,3949, + 10890,2465, + 11141,1654, + 12132,2790, + 12180,3477, + 12376,2079, + 12494,4560, + 14430,2468, + 14573,3914, + 14576,3111, + 15043,1827, + 15207,1329, + 16073,6155, + 17519,4719, + 18345,2148, + 18554,2784, + 18576,3563, +}; + +const Word16 E_ROM_qua_gain7b_const[NB_QUA_GAIN7B * 2] = +{ + 123,2777, + 369,2102, + 404,4368, + 693,3486, + 1107,719, + 1222,1679, + 1657,1293, + 1667,5547, + 1805,2425, + 2369,3075, + 2489,12063, + 2681,1901, + 2693,3984, + 3031,7547, + 3248,990, + 3466,2672, + 3674,2165, + 3718,1513, + 3844,3456, + 4120,4656, + 4748,2967, + 4821,19622, + 4855,2400, + 4912,1776, + 5245,3860, + 5312,6282, + 5500,1176, + 5713,2056, + 5872,3287, + 5960,2662, + 6170,9756, + 6364,5021, + 6545,1476, + 6788,2283, + 6796,4163, + 7038,2949, + 7216,1831, + 7274,3516, + 7707,2510, + 8123,5762, + 8361,4485, + 8376,2110, + 8594,3135, + 8611,3755, + 8634,1570, + 8636,2748, + 8683,8222, + 9274,335, + 9512,2404, + 9640,5020, + 9690,1893, + 9778,3361, + 9808,15435, + 9936,4029, + 10194,2767, + 10306,6510, + 10325,1252, + 10686,2186, + 10844,32767, + 10913,4453, + 10968,3078, + 11044,1666, + 11076,3609, + 11398,2509, + 11423,5160, + 11848,1994, + 11997,2823, + 12002,3880, + 12084,7573, + 12129,3325, + 12214,5867, + 12331,1496, + 12450,4245, + 12458,2283, + 12768,901, + 12896,4741, + 12898,1811, + 12902,2569, + 12983,2959, + 13173,3331, + 13413,2059, + 13416,3734, + 13429,10641, + 13448,1148, + 13615,5340, + 13674,1425, + 13779,2332, + 13847,4264, + 13909,2657, + 13958,6488, + 14047,3085, + 14130,1648, + 14547,1915, + 14554,3684, + 14749,2739, + 14868,5017, + 14875,2216, + 14898,3197, + 14988,1085, + 15026,4246, + 15375,7971, + 15421,1446, + 15548,2462, + 15722,5920, + 15882,3449, + 15960,1782, + 15994,2863, + 16365,3977, + 16419,4754, + 16472,2162, + 17378,3101, + 17410,2550, + 17743,1339, + 17856,5485, + 17979,1982, + 17996,3628, + 18041,7110, + 18242,4381, + 18602,22207, + 19373,12827, + 19533,2777, + 19640,1678, + 19728,2272, + 19795,8861, + 20065,3275, + 20133,4881, + 20198,3947, + 20290,6128, +}; + +/*----------------------------------------------------------------------------------* + * Quantization table for scaled innovation energy prediction, Q8 * + * Used in "gain_pre.c" * + *----------------------------------------------------------------------------------*/ +const Word16 Es_pred_qua[8] = +{ + 1521/* 5.9422f Q8*/, + 3909/*15.2711f Q8*/, + 5987/*23.3857f Q8*/, + 7816/*30.5310f Q8*/, + 9477/*37.0190f Q8*/, + 11124/*43.4539f Q8*/, + 12863/*50.2442f Q8*/, + 15031/*58.7164f Q8*/ +}; + +const Word16 Es_pred_qua_2[16] = +{ + -1280/*-5.f Q8*/, + 0/* 0.f Q8*/, + 1280/* 5.f Q8*/, + 2560/*10.f Q8*/, + 3840/*15.f Q8*/, + 5120/*20.f Q8*/, + 6400/*25.f Q8*/, + 7680/*30.f Q8*/, + 8960/*35.f Q8*/, + 10240/*40.f Q8*/, + 11520/*45.f Q8*/, + 12800/*50.f Q8*/, + 14080/*55.f Q8*/, + 15360/*60.f Q8*/, + 16640/*65.f Q8*/, + 17920/*70.f Q8*/ +}; + + +const Word16 lag_window_8k[2][16] = /* LAGW_STRONG */ +{ + /* h */ { 32728, 32619, 32438, 32187, 31867, 31480, 31029, 30517, 29946, 29321, 28645, 27923, 27158, 26356, 25521, 24658 }, + /* l */ { 11904, 17280, 30720, 25856, 24192, 28992, 24384, 7360, 19456, 14720, 22080, 12928, 31040, 27328, 22080, 5184 } +}; +const Word16 lag_window_12k8[NUM_LAGW_STRENGTHS][2][16] = +{ + /* LAGW_WEAK */ + { + /* h */ { 32763, 32758, 32750, 32739, 32725, 32707, 32687, 32663, 32637, 32607, 32574, 32538, 32498, 32456, 32411, 32362 }, + /* l */ { 4736, 13312, 16896, 15360, 8896, 30464, 14528, 27008, 2496, 6720, 7296, 4480, 31424, 22976, 12160, 32384 } + }, + /* LAGW_MEDIUM */ + { + /* h */ { 32758, 32739, 32707, 32663, 32607, 32538, 32456, 32362, 32257, 32139, 32009, 31867, 31714, 31549, 31374, 31187 }, + /* l */ { 13312, 15360, 30464, 27008, 6720, 4480, 22976, 32384, 3520, 5888, 11200, 24192, 17472, 29376, 576, 3136 } + }, + /* LAGW_STRONG */ + { + /* h */ { 32750, 32707, 32637, 32538, 32411, 32257, 32075, 31867, 31633, 31374, 31089, 30780, 30449, 30094, 29718, 29321 }, + /* l */ { 16896, 30464, 2496, 4480, 12160, 3520, 24256, 24192, 20736, 576, 18240, 31488, 128, 16704, 11520, 14720 } + } +}; +const Word16 lag_window_16k[NUM_LAGW_STRENGTHS][2][16] = +{ + /* LAGW_WEAK */ + { + /* h */ { 32763, 32760, 32755, 32748, 32739, 32728, 32715, 32700, 32682, 32663, 32642, 32619, 32594, 32567, 32538, 32507 }, + /* l */ { 23360, 22272, 20672, 18304, 15360, 11904, 8000, 3648, 31808, 27008, 22080, 17280, 12608, 8256, 4480, 1344 } + }, + /* LAGW_MEDIUM */ + { + /* h */ { 32760, 32748, 32728, 32700, 32663, 32619, 32567, 32507, 32438, 32362, 32279, 32187, 32088, 31981, 31867, 31746 }, + /* l */ { 22272, 18304, 11904, 3648, 27008, 17280, 8256, 1344, 30720, 32384, 8256, 25856, 21824, 31360, 24192, 3072 } + }, + /* LAGW_STRONG */ + { + /* h */ { 32755, 32728, 32682, 32619, 32538, 32438, 32322, 32187, 32036, 31867, 31682, 31480, 31263, 31029, 30780, 30517 }, + /* l */ { 20672, 11904, 31808, 17280, 4480, 30720, 2944, 25856, 8320, 24192, 16896, 28992, 5824, 24384, 31488, 7360 } + } +}; +const Word16 lag_window_25k6[NUM_LAGW_STRENGTHS][2][16] = +{ + /* LAGW_WEAK */ + { + /* h */ { 32764, 32763, 32761, 32758, 32754, 32750, 32745, 32739, 32732, 32725, 32716, 32707, 32698, 32687, 32676, 32663 }, + /* l */ { 10752, 4736, 5568, 13312, 28096, 16896, 12672, 15360, 25024, 8896, 32576, 30464, 2624, 14528, 832, 27008 } + }, + /* LAGW_MEDIUM */ + { + /* h */ { 32763, 32758, 32750, 32739, 32725, 32707, 32687, 32663, 32637, 32607, 32574, 32538, 32498, 32456, 32411, 32362 }, + /* l */ { 4736, 13312, 16896, 15360, 8896, 30464, 14528, 27008, 2496, 6720, 7296, 4480, 31424, 22976, 12160, 32384 } + }, + /* LAGW_STRONG */ + { + /* h */ { 32761, 32750, 32732, 32707, 32676, 32637, 32591, 32538, 32478, 32411, 32337, 32257, 32169, 32075, 31975, 31867 }, + /* l */ { 5568, 16896, 25024, 30464, 832, 2496, 3328, 4480, 7040, 12160, 21440, 3520, 25728, 24256, 1216, 24192 } + } +}; +const Word16 lag_window_32k[NUM_LAGW_STRENGTHS][2][16] = +{ + /* LAGW_WEAK */ + { + /* h */ { 32764, 32763, 32762, 32760, 32758, 32755, 32752, 32748, 32744, 32739, 32734, 32728, 32722, 32715, 32707, 32700 }, + /* l */ { 15424, 23360, 14720, 22272, 13312, 20672, 11328, 18304, 8704, 15360, 5504, 11904, 1792, 8000, 30464, 3648 } + }, + /* LAGW_MEDIUM */ + { + /* h */ { 32763, 32760, 32755, 32748, 32739, 32728, 32715, 32700, 32682, 32663, 32642, 32619, 32594, 32567, 32538, 32507 }, + /* l */ { 23360, 22272, 20672, 18304, 15360, 11904, 8000, 3648, 31808, 27008, 22080, 17280, 12608, 8256, 4480, 1344 } + }, + /* LAGW_STRONG */ + { + /* h */ { 32762, 32755, 32744, 32728, 32707, 32682, 32653, 32619, 32581, 32538, 32490, 32438, 32382, 32322, 32257, 32187 }, + /* l */ { 14720, 20672, 8704, 11904, 30464, 31808, 16384, 17280, 2240, 4480, 24704, 30720, 23168, 2944, 3520, 25856 } + } +}; +const Word16 lag_window_48k[2][16] = /* LAGW_STRONG */ +{ + /* h */ { 32763, 32760, 32755, 32748, 32739, 32728, 32715, 32700, 32682, 32663, 32642, 32619, 32594, 32567, 32538, 32507 }, + /* l */ { 23360, 22272, 20672, 18304, 15360, 11904, 8000, 3648, 31808, 27008, 22080, 17280, 12608, 8256, 4480, 1344 } +}; + + +#define W16(x) ((Word16)x) + +const Word16 d_array[18] = { 1, 2, 5, 8, 10, 15, 20, 30, 40, 60, 80, 120, 140, 160, 180, 220, 260, 300 }; +const Word16 m_array[18] = { 0/*0.000f Q15*/, 8520/*0.260f Q15*/, 15729/*0.480f Q15*/, 19005/*0.580f Q15*/, 19988/*0.610f Q15*/, 21889/*0.668f Q15*/, 23101/*0.705f Q15*/, 24969/*0.762f Q15*/, 26214/*0.800f Q15*/, 27558/*0.841f Q15*/, 28344/*0.865f Q15*/, 29164/*0.890f Q15*/, 29491/*0.900f Q15*/, 29819/*0.910f Q15*/, 30147/*0.920f Q15*/, 30474/*0.930f Q15*/, 30638/*0.935f Q15*/, 30802/*0.940f Q15*/ }; +const Word16 msQeqInvAv_thresh[3] = { 328/*0.01f Q15*/, 983/*0.03f Q15*/, 1638/*0.05f Q15*/ }; +const Word16 msNoiseSlopeMax[4] = { 32767/*2.f Q14*/, 26214/*1.6f Q14*/, 21299/*1.3f Q14*/, 18022/*1.1f Q14*/ }; +const Word16 preemphCompensation[NB_BANDS] = { 19960/*9.7461f Q11*/, 19493/*9.5182f Q11*/, 18486/*9.0262f Q11*/, 17099/*8.3493f Q11*/, 15516/*7.5764f Q11*/, 13893/*6.7838f Q11*/, 11956/*5.8377f Q11*/, 9933/*4.8502f Q11*/, 8263/*4.0346f Q11*/, 6715/*3.2788f Q11*/, 5383/*2.6283f Q11*/, 4284/*2.0920f Q11*/, 3339/*1.6304f Q11*/, 2632/*1.2850f Q11*/, 2070/*1.0108f Q11*/, 1621/*0.7916f Q11*/, 1284/*0.6268f Q11*/, 1026/*0.5011f Q11*/, 844/*0.4119f Q11*/, 745/*0.3637f Q11*/ }; + +const SCALE_SETUP scaleTable[20] = +{ + { 0, 8000, -704/*-5.5f Q7*/, 0 }, + { 8000, 9600, -640/*-5.0f Q7*/, 0 }, + { 9600, 13200, -512/*-4.0f Q7*/, 0 }, + { 13200, 16400, -384/*-3.0f Q7*/, 0 }, + { 16400, 24400, -192/*-1.5f Q7*/, 0 }, + { 24400, 64001, -64/*-0.5f Q7*/, 0 }, + + { 0, 8000, -704/*-5.5f Q7*/, 1 }, + { 8000, 9600, -640/*-5.0f Q7*/, 1 }, + + { 9600, 13200, -198/*-1.55f Q7*/, 1 }, + { 13200, 16400, -384/*-3.0f Q7*/, 1 }, + + { 16400, 24400, -77/*-0.6f Q7*/, 1 }, + { 24400, 32000, -26/*-0.2f Q7*/, 1 }, + { 32000,128001, 0/* 0.0f Q7*/, 1 }, + + { 0, 8000, -115/*-0.9f Q7*/, 2 }, + { 8000, 9600, -83/*-0.65f Q7*/, 2 }, + { 9600, 13200, -256/*-2.0f Q7*/, 2 }, + { 13200, 16400, -384/*-3.0f Q7*/, 2 }, + + { 16400, 24400, -102/*-0.8f Q7*/, 2 }, + { 24400, 32000, -32/*-0.25f Q7*/, 2 }, + { 32000,128001, 0/* 0.0f Q7*/, 2 }, +}; + +/* + Element scale is precalculated in the following way (fomat: Q2.14): + - scaleTable_cn_only[i].scale = pow( 10.f,-scaleTable_cn_only[i].scale/10.f ) - 1.f; +*/ +const SCALE_SETUP scaleTable_cn_only[18] = +{ + { 0, 8000, 20295/*1.2387211385 Q14*/ /*-3.5f*/, 0 }, + { 8000, 9600, 16306/*0.9952622652 Q14*/ /*-3.0f*/, 0 }, + { 9600, 13200, 12751/*0.7782794237 Q14*/ /*-2.5f*/, 0 }, + { 13200, 16400, 9583/*0.5848932266 Q14*/ /*-2.0f*/, 0 }, + { 16400,128001, 0/*0.0000000000 Q14*/ /* 0.0f*/, 0 }, + + { 0, 8000, 16306/*0.9952622652 Q14*/ /*-3.0f*/, 1 }, + { 8000, 9600, 12751/*0.7782794237 Q14*/ /*-2.5f*/, 1 }, + { 9600, 13200, 6759/*0.4125375748 Q14*/ /*-1.5f*/, 1 }, + { 13200, 16400, 12751/*0.7782794237 Q14*/ /*-2.5f*/, 1 }, + { 16400, 24400, 1999/*0.1220184565 Q14*/ /*-0.5f*/, 1 }, + { 24400,128001, 0/*0.0000000000 Q14*/ /* 0.0f*/, 1 }, + + { 0, 8000, 12751/*0.7782794237 Q14*/ /*-2.0f*/, 2 }, + { 8000, 9600, 12751/*0.7782794237 Q14*/ /*-2.0f*/, 2 }, + { 9600, 13200, 9583/*0.5848932266 Q14*/ /*-2.0f*/, 2 }, + { 13200, 16400, 4242/*0.2589254379 Q14*/ /*-1.0f*/, 2 }, + + { 16400, 24400, 1999/*0.1220184565 Q14*/ /*-0.5f*/, 2 }, + { 24400, 32000, 0/*0.0000000000 Q14*/ /* 0.0f*/, 2 }, + { 32000,128001, 0/*0.0000000000 Q14*/ /* 0.0f*/, 2 } +}; + +const Word16 scaleTable_cn_only_amrwbio[3][2] = +{ + { ACELP_6k60, 24771/*1.5118864315 Q14*/ }, + { ACELP_8k85, 16306/*0.9952622652 Q14*/ }, + { ACELP_12k65, 9583/*0.5848932266 Q14*/ }, +}; + +const Word16 sidparts_encoder_noise_est[24] = { 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 58, 68, 80, 92, 108, 126, 148, 176, 212, 255, 259, 264, 269, 279 }; + +const Word16 sidPartitions_nb[] = { 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 58, 68, 80, 92, 108, 126, 159 }; +const Word16 sidPartitions_wb1[] = { 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 58, 68, 80, 92, 108, 126, 148, 176, 212, 255 }; +const Word16 sidPartitions_wb2[] = { 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 58, 68, 80, 92, 108, 126, 148, 176, 212, 255, 259 }; +const Word16 sidPartitions_wb3[] = { 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 58, 68, 80, 92, 108, 126, 148, 176, 212, 255, 319 }; +const Word16 sidPartitions_swb1[] = { 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 58, 68, 80, 92, 108, 126, 148, 176, 212, 255, 259, 264, 269, 274 }; +const Word16 sidPartitions_swb2[] = { 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 58, 68, 80, 92, 108, 126, 148, 176, 212, 255, 319, 324, 329, 339 }; + +const Word16 shapingPartitions_nb[] = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 28, 31, 34, 37, 40, 43, 47, 51, 55, 59, 64, 69, 74, 80, 86, 93, 100, 108, 117, 126, 136, 159 }; +const Word16 shapingPartitions_wb1[] = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 28, 31, 34, 37, 40, 43, 47, 51, 55, 59, 64, 69, 74, 80, 86, 93, 100, 108, 117, 126, 135, 148, 162, 176, 192, 212, 232, 255 }; +const Word16 shapingPartitions_wb2[] = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 28, 31, 34, 37, 40, 43, 47, 51, 55, 59, 64, 69, 74, 80, 86, 93, 100, 108, 117, 126, 135, 148, 162, 176, 192, 212, 232, 255 }; +const Word16 shapingPartitions_wb3[] = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 28, 31, 34, 37, 40, 43, 47, 51, 55, 59, 64, 69, 74, 80, 86, 93, 100, 108, 117, 126, 136, 148, 176, 212, 256, 308, 319 }; +const Word16 shapingPartitions_swb1[] = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 28, 31, 34, 37, 40, 43, 47, 51, 55, 59, 64, 69, 74, 80, 86, 93, 100, 108, 117, 126, 135, 148, 162, 176, 192, 212, 232, 255 }; +const Word16 shapingPartitions_swb2[] = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 28, 31, 34, 37, 40, 43, 47, 51, 55, 59, 64, 69, 74, 80, 86, 93, 100, 108, 117, 126, 136, 148, 176, 212, 256, 308, 319 }; + +const FD_CNG_SETUP FdCngSetup_nb = { 512, 160, sizeof(sidPartitions_nb)/sizeof(Word16), sidPartitions_nb, sizeof(shapingPartitions_nb)/sizeof(Word16), shapingPartitions_nb }; +const FD_CNG_SETUP FdCngSetup_wb1 = { 512, 256, sizeof(sidPartitions_wb1)/sizeof(Word16), sidPartitions_wb1, sizeof(shapingPartitions_wb1)/sizeof(Word16), shapingPartitions_wb1 }; +const FD_CNG_SETUP FdCngSetup_wb2 = { 512, 256, sizeof(sidPartitions_wb2)/sizeof(Word16), sidPartitions_wb2, sizeof(shapingPartitions_wb2)/sizeof(Word16), shapingPartitions_wb2 }; +const FD_CNG_SETUP FdCngSetup_wb3 = { 640, 320, sizeof(sidPartitions_wb3)/sizeof(Word16), sidPartitions_wb3, sizeof(shapingPartitions_wb3)/sizeof(Word16), shapingPartitions_wb3 }; +const FD_CNG_SETUP FdCngSetup_swb1 = { 512, 256, sizeof(sidPartitions_swb1)/sizeof(Word16), sidPartitions_swb1, sizeof(shapingPartitions_swb1)/sizeof(Word16), shapingPartitions_swb1 }; +const FD_CNG_SETUP FdCngSetup_swb2 = { 640, 320, sizeof(sidPartitions_swb2)/sizeof(Word16), sidPartitions_swb2, sizeof(shapingPartitions_swb2)/sizeof(Word16), shapingPartitions_swb2 }; + +const Word16 maxN_37bits = 24; +const Word16 maxC_37bits = 8; +const Word16 stages_37bits = 6; +const Word16 levels_37bits[6] = { 128, 64, 64, 64, 64, 64 }; +const Word16 bits_37bits[6] = { 7, 6, 6, 6, 6, 6 }; + +const Word16 cdk_37bits_1_fx[3072] = +{ + W16(0x017B), W16(0x0548), W16(0x068C), W16(0x058B), W16(0x0572), W16(0x0577), W16(0x04BC), W16(0x03C0), + W16(0x0399), W16(0x0237), W16(0x00A1), W16(0xFEB3), W16(0xFCFA), W16(0xFC2F), W16(0xFACB), W16(0xFA70), + W16(0xF914), W16(0xF6A8), W16(0xF439), W16(0xF145), W16(0xF02C), W16(0xEFDD), W16(0xEE63), W16(0xED8C), + W16(0x089B), W16(0x0B41), W16(0x08E4), W16(0x079C), W16(0x05CF), W16(0x03F9), W16(0x03E0), W16(0x031E), + W16(0x02E2), W16(0x0212), W16(0x0015), W16(0xFECD), W16(0xFF39), W16(0xFE3F), W16(0xFBE8), W16(0xFA04), + W16(0xF7FF), W16(0xF5BC), W16(0xF361), W16(0xF14A), W16(0xEFCE), W16(0xEDF1), W16(0xEC58), W16(0xEB8A), + W16(0x0815), W16(0x0642), W16(0x0569), W16(0x03C1), W16(0x044B), W16(0x04DB), W16(0x0474), W16(0x03DF), + W16(0x0432), W16(0x030C), W16(0x0121), W16(0xFF19), W16(0xFD1C), W16(0xFCAE), W16(0xFAF1), W16(0xF9F7), + W16(0xF85E), W16(0xF5DD), W16(0xF370), W16(0xF072), W16(0xEF52), W16(0xEF6F), W16(0xEE06), W16(0xED0C), + W16(0x10A9), W16(0x0DA2), W16(0x0C21), W16(0x0A1E), W16(0x0854), W16(0x07D7), W16(0x0690), W16(0x0658), + W16(0x043C), W16(0x036E), W16(0x00B9), W16(0xFE78), W16(0xFC8A), W16(0xFAEB), W16(0xF926), W16(0xF6C2), + W16(0xF4B5), W16(0xF2B1), W16(0xF0CD), W16(0xEED0), W16(0xEDF7), W16(0xEC97), W16(0xEBD3), W16(0xEB6E), + W16(0xFA8A), W16(0x0181), W16(0x03DF), W16(0x04A4), W16(0x0331), W16(0x0599), W16(0x04DB), W16(0x03CB), + W16(0x0005), W16(0x0161), W16(0xFF3F), W16(0xFEFE), W16(0xFEC7), W16(0xFCED), W16(0xFB97), W16(0xFBA7), + W16(0xFBFC), W16(0xFA73), W16(0xF96A), W16(0xF909), W16(0xF92B), W16(0xF7C3), W16(0xF6C5), W16(0xF5F7), + W16(0x1095), W16(0x0E41), W16(0x096C), W16(0x0813), W16(0x0652), W16(0x046A), W16(0x0423), W16(0x0350), + W16(0x034C), W16(0x023D), W16(0x0074), W16(0xFEC0), W16(0xFF76), W16(0xFE66), W16(0xFB60), W16(0xF90E), + W16(0xF6CC), W16(0xF4B3), W16(0xF27A), W16(0xF058), W16(0xEF09), W16(0xED48), W16(0xEBE3), W16(0xEB2E), + W16(0x0DA9), W16(0x0772), W16(0x056E), W16(0x041F), W16(0x039A), W16(0x0308), W16(0x02C3), W16(0x0275), + W16(0x0221), W16(0x01B5), W16(0x00ED), W16(0x0049), W16(0xFEF4), W16(0xFD31), W16(0xFC0A), W16(0xFBD5), + W16(0xFB17), W16(0xF8FF), W16(0xF705), W16(0xF603), W16(0xF494), W16(0xF2D4), W16(0xF031), W16(0xEDB6), + W16(0x14D0), W16(0x0F44), W16(0x0DF3), W16(0x0C0E), W16(0x0938), W16(0x07D3), W16(0x06C1), W16(0x0522), + W16(0x0475), W16(0x02EA), W16(0x004B), W16(0xFE88), W16(0xFC2B), W16(0xFAAC), W16(0xF8C9), W16(0xF73A), + W16(0xF605), W16(0xF554), W16(0xF3ED), W16(0xF31F), W16(0xF305), W16(0xF26A), W16(0xF225), W16(0xF1E6), + W16(0xFE9B), W16(0x0403), W16(0x0558), W16(0x0336), W16(0x0433), W16(0x02F7), W16(0x01DD), W16(0x012C), + W16(0x016C), W16(0x0124), W16(0x0041), W16(0xFFAF), W16(0xFF0E), W16(0xFE2D), W16(0xFCE7), W16(0xFC8B), + W16(0xFCA0), W16(0xFB7D), W16(0xF975), W16(0xF831), W16(0xF73E), W16(0xF582), W16(0xF394), W16(0xF20E), + W16(0x079D), W16(0x0AD6), W16(0x0B5A), W16(0x09A9), W16(0x084A), W16(0x0738), W16(0x066E), W16(0x0608), + W16(0x047C), W16(0x02E1), W16(0x0059), W16(0xFE81), W16(0xFCD0), W16(0xFABD), W16(0xF93B), W16(0xF769), + W16(0xF5A1), W16(0xF44F), W16(0xF26B), W16(0xEFCD), W16(0xEE85), W16(0xECDA), W16(0xEBE5), W16(0xEB83), + W16(0x04A1), W16(0x0509), W16(0x0556), W16(0x044A), W16(0x038A), W16(0x030A), W16(0x02B8), W16(0x0255), + W16(0x0212), W16(0x01BB), W16(0x0101), W16(0x0035), W16(0xFEEC), W16(0xFD22), W16(0xFC1D), W16(0xFBF2), + W16(0xFB3F), W16(0xF91E), W16(0xF70F), W16(0xF5E9), W16(0xF49C), W16(0xF2E0), W16(0xF02D), W16(0xEDA3), + W16(0x0D77), W16(0x0DC1), W16(0x0D75), W16(0x0AA8), W16(0x0814), W16(0x065D), W16(0x0456), W16(0x0451), + W16(0x0310), W16(0x02B3), W16(0x0134), W16(0xFEFC), W16(0xFD02), W16(0xFB55), W16(0xFA2D), W16(0xF891), + W16(0xF7E0), W16(0xF6F0), W16(0xF59C), W16(0xF425), W16(0xF3A2), W16(0xF253), W16(0xF1DF), W16(0xF188), + W16(0x0274), W16(0x04F8), W16(0x0575), W16(0x048C), W16(0x044E), W16(0x0467), W16(0x0413), W16(0x040C), + W16(0x0213), W16(0x00C8), W16(0x001D), W16(0xFEF2), W16(0xFE21), W16(0xFCF7), W16(0xFC59), W16(0xFB5C), + W16(0xFA76), W16(0xF9A5), W16(0xF914), W16(0xF8D4), W16(0xF853), W16(0xF770), W16(0xF5D5), W16(0xF40D), + W16(0x1148), W16(0x0E53), W16(0x09F3), W16(0x085C), W16(0x0711), W16(0x04CC), W16(0x0453), W16(0x03F2), + W16(0x03BA), W16(0x0278), W16(0x0090), W16(0xFF0A), W16(0xFED1), W16(0xFD92), W16(0xFA84), W16(0xF871), + W16(0xF6BA), W16(0xF489), W16(0xF23B), W16(0xEFD0), W16(0xEED3), W16(0xED71), W16(0xEC93), W16(0xEBF6), + W16(0x0AED), W16(0x075D), W16(0x05A3), W16(0x0493), W16(0x0446), W16(0x0463), W16(0x0411), W16(0x0422), + W16(0x0219), W16(0x00C6), W16(0x001A), W16(0xFF06), W16(0xFE27), W16(0xFCEF), W16(0xFC57), W16(0xFB4F), + W16(0xFA6B), W16(0xF9A0), W16(0xF90D), W16(0xF8CA), W16(0xF827), W16(0xF757), W16(0xF5C4), W16(0xF400), + W16(0x155D), W16(0x0F9F), W16(0x0C38), W16(0x09DC), W16(0x07A7), W16(0x053D), W16(0x03A9), W16(0x051C), + W16(0x04ED), W16(0x02A2), W16(0x00D4), W16(0xFF7C), W16(0xFDB2), W16(0xFBBA), W16(0xF8EA), W16(0xF824), + W16(0xF7FD), W16(0xF68C), W16(0xF3DB), W16(0xF2A3), W16(0xF27D), W16(0xF19C), W16(0xF0C9), W16(0xEFDB), + W16(0xFFCD), W16(0x038E), W16(0x0463), W16(0x037C), W16(0x0340), W16(0x02A6), W16(0x02AB), W16(0x0290), + W16(0x0288), W16(0x01E2), W16(0x00EF), W16(0x002F), W16(0xFEA6), W16(0xFDA9), W16(0xFCAC), W16(0xFBAE), + W16(0xFAAF), W16(0xF96E), W16(0xF84B), W16(0xF6F3), W16(0xF4CD), W16(0xF2DA), W16(0xF0F7), W16(0xEEFD), + W16(0x0C53), W16(0x0BF8), W16(0x0C2B), W16(0x0A1A), W16(0x077A), W16(0x0556), W16(0x03F4), W16(0x03E3), + W16(0x0259), W16(0x01FA), W16(0x0084), W16(0xFE9B), W16(0xFD34), W16(0xFBF2), W16(0xFAFB), W16(0xF9EA), + W16(0xF9DD), W16(0xF9E2), W16(0xF898), W16(0xF6CB), W16(0xF505), W16(0xF2D8), W16(0xF195), W16(0xF0B6), + W16(0x07BE), W16(0x054B), W16(0x0435), W16(0x030E), W16(0x03A2), W16(0x03DA), W16(0x0342), W16(0x026B), + W16(0x01E4), W16(0x0170), W16(0x00CE), W16(0x0009), W16(0xFDFF), W16(0xFE36), W16(0xFCBF), W16(0xFC00), + W16(0xF9B8), W16(0xF7AD), W16(0xF51D), W16(0xF180), W16(0xF15B), W16(0xF1C5), W16(0xF045), W16(0xEF23), + W16(0x0FD5), W16(0x0D41), W16(0x0B8A), W16(0x09BD), W16(0x0838), W16(0x0754), W16(0x0692), W16(0x0611), + W16(0x0487), W16(0x02ED), W16(0x0044), W16(0xFE7B), W16(0xFCBA), W16(0xFAA6), W16(0xF92D), W16(0xF773), + W16(0xF59D), W16(0xF47B), W16(0xF29E), W16(0xEFF4), W16(0xEE86), W16(0xECCF), W16(0xEBD8), W16(0xEB78), + W16(0xFDB6), W16(0x0365), W16(0x05CE), W16(0x0610), W16(0x0505), W16(0x035E), W16(0x02CE), W16(0x01CF), + W16(0x0089), W16(0x00B8), W16(0xFFD1), W16(0xFF08), W16(0xFEAA), W16(0xFE04), W16(0xFDC1), W16(0xFC29), + W16(0xFC4E), W16(0xFB7A), W16(0xFAAD), W16(0xF9D2), W16(0xF818), W16(0xF6F3), W16(0xF5A0), W16(0xF46B), + W16(0x1008), W16(0x0D2C), W16(0x08D0), W16(0x0746), W16(0x05AB), W16(0x039D), W16(0x035A), W16(0x0295), + W16(0x02A9), W16(0x01D8), W16(0x001B), W16(0xFF0D), W16(0xFF48), W16(0xFE4F), W16(0xFBEB), W16(0xFA8C), + W16(0xF912), W16(0xF65C), W16(0xF3E1), W16(0xF14F), W16(0xEF83), W16(0xED7D), W16(0xEBAE), W16(0xEACA), + W16(0x0DAD), W16(0x08AD), W16(0x075B), W16(0x059B), W16(0x04DC), W16(0x0476), W16(0x03F2), W16(0x025C), + W16(0x010B), W16(0x009F), W16(0xFFDA), W16(0xFE63), W16(0xFDF1), W16(0xFDBE), W16(0xFD7D), W16(0xFC45), + W16(0xFB08), W16(0xFA08), W16(0xF8CA), W16(0xF795), W16(0xF5B6), W16(0xF412), W16(0xF2D3), W16(0xF1F4), + W16(0x15E3), W16(0x0F2D), W16(0x0DD2), W16(0x0BB2), W16(0x0912), W16(0x080C), W16(0x06B1), W16(0x0509), + W16(0x03F9), W16(0x0210), W16(0xFF8C), W16(0xFE56), W16(0xFC61), W16(0xFAFD), W16(0xF94E), W16(0xF7D6), + W16(0xF6BB), W16(0xF61C), W16(0xF49D), W16(0xF3F1), W16(0xF3E4), W16(0xF35B), W16(0xF31D), W16(0xF2DF), + W16(0x02E6), W16(0x0643), W16(0x0700), W16(0x05A9), W16(0x04E3), W16(0x047E), W16(0x03C0), W16(0x0266), + W16(0x012B), W16(0x0098), W16(0xFFD2), W16(0xFE89), W16(0xFDF6), W16(0xFD9F), W16(0xFD4A), W16(0xFC4C), + W16(0xFB32), W16(0xFA7B), W16(0xF96E), W16(0xF878), W16(0xF743), W16(0xF5CA), W16(0xF486), W16(0xF36B), + W16(0x080C), W16(0x0B47), W16(0x0BE1), W16(0x0A0A), W16(0x086F), W16(0x079C), W16(0x06AD), W16(0x063D), + W16(0x0465), W16(0x031D), W16(0x0054), W16(0xFE68), W16(0xFCB0), W16(0xFAAD), W16(0xF917), W16(0xF735), + W16(0xF525), W16(0xF3D8), W16(0xF29D), W16(0xF191), W16(0xF0EF), W16(0xF025), W16(0xEF93), W16(0xEF3F), + W16(0x0839), W16(0x0628), W16(0x04DB), W16(0x039C), W16(0x0365), W16(0x02CB), W16(0x029E), W16(0x02A9), + W16(0x02BC), W16(0x01F6), W16(0x0101), W16(0x0026), W16(0xFEB0), W16(0xFDA0), W16(0xFC84), W16(0xFB74), + W16(0xFA68), W16(0xF932), W16(0xF804), W16(0xF691), W16(0xF46D), W16(0xF26E), W16(0xF079), W16(0xEE80), + W16(0x0AC8), W16(0x0CCE), W16(0x0DA8), W16(0x0C60), W16(0x0994), W16(0x083E), W16(0x06D0), W16(0x0529), + W16(0x03EA), W16(0x0249), W16(0xFFB9), W16(0xFE3A), W16(0xFC21), W16(0xFAFA), W16(0xF90B), W16(0xF78E), + W16(0xF65C), W16(0xF571), W16(0xF418), W16(0xF331), W16(0xF33A), W16(0xF29F), W16(0xF24C), W16(0xF219), + W16(0x05E1), W16(0x05CC), W16(0x05EE), W16(0x060D), W16(0x0517), W16(0x0357), W16(0x02C0), W16(0x01D0), + W16(0x0085), W16(0x00B0), W16(0xFFD1), W16(0xFF12), W16(0xFEAD), W16(0xFE06), W16(0xFDBA), W16(0xFC2D), + W16(0xFC50), W16(0xFB87), W16(0xFAB7), W16(0xF9DA), W16(0xF80B), W16(0xF6EC), W16(0xF59D), W16(0xF469), + W16(0x11D1), W16(0x0F70), W16(0x0A08), W16(0x087F), W16(0x068E), W16(0x04B0), W16(0x0432), W16(0x0375), + W16(0x0389), W16(0x023A), W16(0x0028), W16(0xFEB9), W16(0xFF3A), W16(0xFE36), W16(0xFAFC), W16(0xF915), + W16(0xF6F6), W16(0xF510), W16(0xF2CC), W16(0xF0F8), W16(0xEFEB), W16(0xEE83), W16(0xED84), W16(0xECD7), + W16(0x0B3B), W16(0x096D), W16(0x06CD), W16(0x050E), W16(0x04AD), W16(0x034C), W16(0x0288), W16(0x0224), + W16(0x0190), W16(0x0137), W16(0x0015), W16(0xFF8F), W16(0xFE3C), W16(0xFDD9), W16(0xFD04), W16(0xFC60), + W16(0xFB77), W16(0xFAAD), W16(0xF9FB), W16(0xF936), W16(0xF7EF), W16(0xF65B), W16(0xF5A2), W16(0xF4D2), + W16(0x16C0), W16(0x0F48), W16(0x0C90), W16(0x09AC), W16(0x0757), W16(0x058C), W16(0x03D0), W16(0x03AF), + W16(0x0284), W16(0x0249), W16(0x00FA), W16(0xFF36), W16(0xFD66), W16(0xFC00), W16(0xFB05), W16(0xF96E), + W16(0xF8C8), W16(0xF7E7), W16(0xF66D), W16(0xF49F), W16(0xF350), W16(0xF21E), W16(0xF1CA), W16(0xF174), + W16(0xFFE5), W16(0x03B4), W16(0x04C3), W16(0x0399), W16(0x0448), W16(0x049E), W16(0x0425), W16(0x035F), + W16(0x03B2), W16(0x0263), W16(0x00C3), W16(0xFED0), W16(0xFCF3), W16(0xFCDA), W16(0xFBD9), W16(0xFADE), + W16(0xF96B), W16(0xF760), W16(0xF516), W16(0xF1F5), W16(0xF126), W16(0xF0FC), W16(0xEFBB), W16(0xEE91), + W16(0x0A14), W16(0x0BD9), W16(0x0A05), W16(0x08A9), W16(0x06EE), W16(0x04E1), W16(0x0468), W16(0x03AB), + W16(0x0385), W16(0x026A), W16(0x005B), W16(0xFED5), W16(0xFECC), W16(0xFD95), W16(0xFAE2), W16(0xF8D1), + W16(0xF6EB), W16(0xF51F), W16(0xF2F7), W16(0xF0C4), W16(0xEFFB), W16(0xEEB0), W16(0xEDCF), W16(0xED30), + W16(0x0A84), W16(0x07B7), W16(0x0699), W16(0x0588), W16(0x04F8), W16(0x0512), W16(0x0439), W16(0x0387), + W16(0x0354), W16(0x01E7), W16(0x0081), W16(0xFEBF), W16(0xFD3C), W16(0xFC6A), W16(0xFB27), W16(0xFB1A), + W16(0xF9D4), W16(0xF7D3), W16(0xF57F), W16(0xF254), W16(0xF0C2), W16(0xF08D), W16(0xEF08), W16(0xEE09), + W16(0x10BB), W16(0x0E08), W16(0x0CA3), W16(0x0ABA), W16(0x0932), W16(0x0815), W16(0x0737), W16(0x0671), + W16(0x04A3), W16(0x0325), W16(0x0024), W16(0xFE61), W16(0xFC7D), W16(0xFA41), W16(0xF8AF), W16(0xF6FF), + W16(0xF459), W16(0xF2FA), W16(0xF103), W16(0xEF58), W16(0xEE8C), W16(0xED3F), W16(0xEC8D), W16(0xEC48), + W16(0xFCE7), W16(0x0381), W16(0x0337), W16(0x05B9), W16(0x054D), W16(0x01C2), W16(0x0285), W16(0x05FF), + W16(0x013C), W16(0x0143), W16(0x0019), W16(0xFFAB), W16(0xFE36), W16(0xFDDC), W16(0xFC25), W16(0xFB58), + W16(0xFA9A), W16(0xF9FC), W16(0xF8BF), W16(0xF861), W16(0xF87B), W16(0xF713), W16(0xF660), W16(0xF5C9), + W16(0x112E), W16(0x0E94), W16(0x08F3), W16(0x07FC), W16(0x0620), W16(0x044C), W16(0x0403), W16(0x035F), + W16(0x0357), W16(0x0235), W16(0x0029), W16(0xFEA5), W16(0xFF72), W16(0xFE6C), W16(0xFB9C), W16(0xF945), + W16(0xF71B), W16(0xF4FC), W16(0xF2BD), W16(0xF0CA), W16(0xEF8E), W16(0xEDBD), W16(0xEC47), W16(0xEB7F), + W16(0x0E4C), W16(0x084A), W16(0x05D9), W16(0x0481), W16(0x034C), W16(0x02CB), W16(0x0294), W16(0x0222), + W16(0x01EB), W16(0x018D), W16(0x00E0), W16(0x001B), W16(0xFED4), W16(0xFD0C), W16(0xFC56), W16(0xFC9B), + W16(0xFBEE), W16(0xF9CE), W16(0xF7CA), W16(0xF718), W16(0xF5C9), W16(0xF440), W16(0xF1F2), W16(0xEFE7), + W16(0x1518), W16(0x0FD5), W16(0x0E18), W16(0x0C03), W16(0x08E7), W16(0x072A), W16(0x0631), W16(0x04D7), + W16(0x04EC), W16(0x039D), W16(0x00F4), W16(0xFF9B), W16(0xFC59), W16(0xFA81), W16(0xF87B), W16(0xF6DF), + W16(0xF59C), W16(0xF4DC), W16(0xF365), W16(0xF2A1), W16(0xF298), W16(0xF1F8), W16(0xF1A0), W16(0xF168), + W16(0x0193), W16(0x04EA), W16(0x0536), W16(0x03C4), W16(0x0354), W16(0x02B6), W16(0x022D), W16(0x01B1), + W16(0x01AC), W16(0x011E), W16(0x007D), W16(0xFF96), W16(0xFE78), W16(0xFE21), W16(0xFD66), W16(0xFCDE), + W16(0xFC5D), W16(0xFB38), W16(0xFA40), W16(0xF988), W16(0xF86B), W16(0xF70D), W16(0xF58F), W16(0xF3DD), + W16(0x0872), W16(0x0B35), W16(0x0BE0), W16(0x0A14), W16(0x085B), W16(0x07D8), W16(0x0687), W16(0x064C), + W16(0x042E), W16(0x034F), W16(0x00AC), W16(0xFE7B), W16(0xFC91), W16(0xFAF1), W16(0xF933), W16(0xF6D6), + W16(0xF4CC), W16(0xF2CC), W16(0xF0E3), W16(0xEED3), W16(0xEE16), W16(0xECB7), W16(0xEBFA), W16(0xEB9C), + W16(0x0708), W16(0x0631), W16(0x05B1), W16(0x0338), W16(0x042E), W16(0x02E0), W16(0x01D3), W16(0x0124), + W16(0x0171), W16(0x0125), W16(0x003C), W16(0xFFB6), W16(0xFF19), W16(0xFE36), W16(0xFCDF), W16(0xFC93), + W16(0xFCB2), W16(0xFB91), W16(0xF970), W16(0xF83C), W16(0xF74E), W16(0xF596), W16(0xF399), W16(0xF20D), + W16(0x0E8A), W16(0x0F20), W16(0x0E41), W16(0x0B71), W16(0x087A), W16(0x0680), W16(0x049F), W16(0x0516), + W16(0x03B9), W16(0x02FF), W16(0x00FE), W16(0xFF01), W16(0xFCC6), W16(0xFAF5), W16(0xF9B5), W16(0xF808), + W16(0xF723), W16(0xF645), W16(0xF4AE), W16(0xF322), W16(0xF373), W16(0xF254), W16(0xF1FF), W16(0xF1A5), + W16(0x0539), W16(0x05F3), W16(0x0351), W16(0x05D6), W16(0x057A), W16(0x01D0), W16(0x02A3), W16(0x061D), + W16(0x0131), W16(0x0123), W16(0x001A), W16(0xFFA6), W16(0xFE21), W16(0xFDF1), W16(0xFC22), W16(0xFB38), + W16(0xFA75), W16(0xF9E5), W16(0xF892), W16(0xF846), W16(0xF85C), W16(0xF702), W16(0xF669), W16(0xF5E2), + W16(0x11C4), W16(0x0EE5), W16(0x09CF), W16(0x086F), W16(0x068D), W16(0x04AD), W16(0x043D), W16(0x0386), + W16(0x0384), W16(0x027C), W16(0x0077), W16(0xFED8), W16(0xFF16), W16(0xFDD4), W16(0xFB2A), W16(0xF8DE), + W16(0xF6C3), W16(0xF499), W16(0xF24C), W16(0xF02F), W16(0xEF1F), W16(0xEDB6), W16(0xECAD), W16(0xEC0A), + W16(0x09CA), W16(0x0743), W16(0x0573), W16(0x03BB), W16(0x034A), W16(0x02AD), W16(0x0229), W16(0x01B9), + W16(0x018E), W16(0x0112), W16(0x0075), W16(0xFF8F), W16(0xFE7F), W16(0xFE2A), W16(0xFD67), W16(0xFCF4), + W16(0xFC7F), W16(0xFB43), W16(0xFA39), W16(0xF989), W16(0xF871), W16(0xF721), W16(0xF598), W16(0xF3DE), + W16(0x16BC), W16(0x10D3), W16(0x0D86), W16(0x0A30), W16(0x079A), W16(0x057B), W16(0x0420), W16(0x0535), + W16(0x0495), W16(0x0281), W16(0x00C9), W16(0xFF84), W16(0xFD9F), W16(0xFB53), W16(0xF904), W16(0xF835), + W16(0xF809), W16(0xF6A4), W16(0xF4AF), W16(0xF3FE), W16(0xF3EE), W16(0xF31F), W16(0xF259), W16(0xF157), + W16(0x01AD), W16(0x053B), W16(0x0656), W16(0x0556), W16(0x046F), W16(0x03B5), W16(0x0334), W16(0x02C7), + W16(0x0264), W16(0x01B2), W16(0x00D3), W16(0xFF8F), W16(0xFE4B), W16(0xFD3C), W16(0xFC6F), W16(0xFB21), + W16(0xFA52), W16(0xF98D), W16(0xF87D), W16(0xF719), W16(0xF592), W16(0xF3B2), W16(0xF1D6), W16(0xF003), + W16(0x0C15), W16(0x0D4E), W16(0x0C6F), W16(0x09F0), W16(0x0798), W16(0x057F), W16(0x03B6), W16(0x053F), + W16(0x04D0), W16(0x027D), W16(0x00B2), W16(0xFF76), W16(0xFD90), W16(0xFB93), W16(0xF8F0), W16(0xF84F), + W16(0xF81D), W16(0xF6AC), W16(0xF3F7), W16(0xF2AC), W16(0xF2B0), W16(0xF1D0), W16(0xF0FF), W16(0xF006), + W16(0x085E), W16(0x06B3), W16(0x05AE), W16(0x0410), W16(0x0456), W16(0x04FE), W16(0x0396), W16(0x01B6), + W16(0x01EC), W16(0x01B1), W16(0x00D9), W16(0xFEC7), W16(0xFC6D), W16(0xFD63), W16(0xFD25), W16(0xFC60), + W16(0xFACF), W16(0xF9CC), W16(0xF78F), W16(0xF3CC), W16(0xF205), W16(0xF190), W16(0xF022), W16(0xEEC5), + W16(0x1269), W16(0x0F13), W16(0x0C2F), W16(0x09FB), W16(0x08A4), W16(0x07AC), W16(0x065B), W16(0x05EC), + W16(0x045F), W16(0x0299), W16(0x0050), W16(0xFE59), W16(0xFC74), W16(0xFA2F), W16(0xF8C8), W16(0xF7B8), + W16(0xF6A4), W16(0xF54D), W16(0xF3CB), W16(0xF224), W16(0xF148), W16(0xF06F), W16(0xEF7F), W16(0xEE7E), + W16(0xFFA0), W16(0xFFC1), W16(0xFFFB), W16(0x0001), W16(0xFFFD), W16(0xFFCA), W16(0xFFF1), W16(0x0006), + W16(0xFFE3), W16(0xFFCB), W16(0xFFF5), W16(0xFFD8), W16(0xFFD5), W16(0xFFFA), W16(0xFFE9), W16(0xFFCE), + W16(0xFFE8), W16(0xFFEE), W16(0xFFF6), W16(0xFFE1), W16(0x0003), W16(0xFF8C), W16(0xFFD1), W16(0xFF89), + W16(0x1069), W16(0x0D77), W16(0x08FD), W16(0x07C3), W16(0x061F), W16(0x03F0), W16(0x03F7), W16(0x0359), + W16(0x031A), W16(0x0270), W16(0x001B), W16(0xFED7), W16(0xFF68), W16(0xFE31), W16(0xFBAB), W16(0xF969), + W16(0xF779), W16(0xF559), W16(0xF2FD), W16(0xF114), W16(0xEF9C), W16(0xEDC8), W16(0xEC2D), W16(0xEB5B), + W16(0x0BD5), W16(0x0963), W16(0x07B7), W16(0x059A), W16(0x0436), W16(0x030F), W16(0x02AB), W16(0x029A), + W16(0x0257), W16(0x01D3), W16(0x00C4), W16(0xFF32), W16(0xFE18), W16(0xFDB7), W16(0xFCD5), W16(0xFBB2), + W16(0xFB00), W16(0xFA03), W16(0xF8EB), W16(0xF7B3), W16(0xF66E), W16(0xF4C1), W16(0xF341), W16(0xF1C3), + W16(0x186B), W16(0x111B), W16(0x0E20), W16(0x0BE5), W16(0x0994), W16(0x082F), W16(0x06C3), W16(0x0601), + W16(0x03CB), W16(0x0249), W16(0xFFC8), W16(0xFD34), W16(0xFB66), W16(0xFA33), W16(0xF94F), W16(0xF816), + W16(0xF76C), W16(0xF6E3), W16(0xF580), W16(0xF44A), W16(0xF3F4), W16(0xF2F1), W16(0xF2CF), W16(0xF28D), + W16(0x02D3), W16(0x06E5), W16(0x0678), W16(0x050E), W16(0x04A0), W16(0x035A), W16(0x027D), W16(0x0212), + W16(0x019A), W16(0x0120), W16(0x0016), W16(0xFF9E), W16(0xFE40), W16(0xFDCC), W16(0xFD09), W16(0xFC6A), + W16(0xFB8A), W16(0xFAC7), W16(0xFA21), W16(0xF976), W16(0xF835), W16(0xF696), W16(0xF5F2), W16(0xF50D), + W16(0x0A01), W16(0x0C87), W16(0x0BD7), W16(0x09CF), W16(0x086E), W16(0x076D), W16(0x062A), W16(0x05DD), + W16(0x0447), W16(0x0273), W16(0x0050), W16(0xFE70), W16(0xFC86), W16(0xFA57), W16(0xF910), W16(0xF7E5), + W16(0xF6D3), W16(0xF563), W16(0xF3DE), W16(0xF23B), W16(0xF17A), W16(0xF0BD), W16(0xEFBF), W16(0xEE9E), + W16(0x0A10), W16(0x079A), W16(0x06A0), W16(0x0554), W16(0x0475), W16(0x03BB), W16(0x0339), W16(0x02DB), + W16(0x0266), W16(0x01BF), W16(0x00E0), W16(0xFFA1), W16(0xFE4A), W16(0xFD45), W16(0xFC62), W16(0xFAF5), + W16(0xFA2F), W16(0xF979), W16(0xF869), W16(0xF6ED), W16(0xF555), W16(0xF37E), W16(0xF18A), W16(0xEFB7), + W16(0x0D46), W16(0x0D11), W16(0x0DEA), W16(0x0C1D), W16(0x0970), W16(0x084C), W16(0x06D2), W16(0x04E1), + W16(0x03A5), W16(0x020C), W16(0xFFA4), W16(0xFE5E), W16(0xFC58), W16(0xFB02), W16(0xF934), W16(0xF7BF), + W16(0xF692), W16(0xF5F1), W16(0xF48F), W16(0xF3D2), W16(0xF402), W16(0xF368), W16(0xF32B), W16(0xF2F2), + W16(0x0876), W16(0x07D2), W16(0x0757), W16(0x0496), W16(0x05DC), W16(0x045E), W16(0x02DF), W16(0x01A8), + W16(0x01EA), W16(0x0169), W16(0x0001), W16(0xFF2F), W16(0xFE65), W16(0xFD1C), W16(0xFBA4), W16(0xFB98), + W16(0xFBFE), W16(0xFB3B), W16(0xF953), W16(0xF821), W16(0xF7CD), W16(0xF644), W16(0xF4DD), W16(0xF399), + W16(0x10A3), W16(0x0E7E), W16(0x0943), W16(0x081D), W16(0x05EA), W16(0x0408), W16(0x037A), W16(0x031F), + W16(0x02C7), W16(0x01C3), W16(0x0046), W16(0xFEAD), W16(0xFFE1), W16(0xFEC1), W16(0xFBF2), W16(0xF9BF), + W16(0xF7A7), W16(0xF5C0), W16(0xF418), W16(0xF2DA), W16(0xF21C), W16(0xF133), W16(0xF05E), W16(0xEFBD), + W16(0x0DD5), W16(0x0AB1), W16(0x07A5), W16(0x05A6), W16(0x039F), W16(0x0209), W16(0x011E), W16(0x0100), + W16(0x010F), W16(0x012F), W16(0x008E), W16(0xFFF7), W16(0xFF30), W16(0xFE68), W16(0xFDC0), W16(0xFD5D), + W16(0xFCC0), W16(0xFB85), W16(0xFA5F), W16(0xF96C), W16(0xF839), W16(0xF71D), W16(0xF53F), W16(0xF428), + W16(0x1716), W16(0x11B9), W16(0x0DD2), W16(0x0A4B), W16(0x078C), W16(0x05AC), W16(0x042E), W16(0x0529), + W16(0x04B4), W16(0x0269), W16(0x00B9), W16(0xFF59), W16(0xFD99), W16(0xFB32), W16(0xF900), W16(0xF87D), + W16(0xF7F9), W16(0xF6CC), W16(0xF57A), W16(0xF51D), W16(0xF511), W16(0xF454), W16(0xF397), W16(0xF29F), + W16(0x02C7), W16(0x058B), W16(0x0656), W16(0x05B0), W16(0x052D), W16(0x04E3), W16(0x03C6), W16(0x02CC), + W16(0x02A2), W16(0x01CE), W16(0x00A6), W16(0xFF3B), W16(0xFD87), W16(0xFCC8), W16(0xFB6D), W16(0xFB5E), + W16(0xF9F2), W16(0xF7BA), W16(0xF574), W16(0xF25D), W16(0xF166), W16(0xF16B), W16(0xEFD8), W16(0xEF18), + W16(0x0910), W16(0x0C5A), W16(0x0967), W16(0x0839), W16(0x065E), W16(0x045E), W16(0x0412), W16(0x036E), + W16(0x0345), W16(0x0235), W16(0x006F), W16(0xFEB8), W16(0xFF3E), W16(0xFE47), W16(0xFB6E), W16(0xF930), + W16(0xF700), W16(0xF4E2), W16(0xF2AA), W16(0xF095), W16(0xEF83), W16(0xEDD9), W16(0xEC8E), W16(0xEBD7), + W16(0x09A7), W16(0x07C5), W16(0x06F4), W16(0x05C1), W16(0x05B1), W16(0x059E), W16(0x04D3), W16(0x03A8), + W16(0x037B), W16(0x022E), W16(0x00A4), W16(0xFEBE), W16(0xFCF4), W16(0xFC2C), W16(0xFAC8), W16(0xFA59), + W16(0xF8EB), W16(0xF684), W16(0xF414), W16(0xF147), W16(0xF047), W16(0xEFF3), W16(0xEE8A), W16(0xEDC3), + W16(0x106C), W16(0x0D7F), W16(0x0BFD), W16(0x0A0C), W16(0x0897), W16(0x079B), W16(0x06B6), W16(0x0638), + W16(0x0494), W16(0x0315), W16(0x005C), W16(0xFE8A), W16(0xFCCC), W16(0xFA95), W16(0xF905), W16(0xF730), + W16(0xF4BB), W16(0xF34B), W16(0xF14A), W16(0xEF4B), W16(0xEE4B), W16(0xECE3), W16(0xEC19), W16(0xEBD6), + W16(0xFB0B), W16(0x0267), W16(0x048B), W16(0x0582), W16(0x03A0), W16(0x0601), W16(0x0513), W16(0x03E6), + W16(0x0004), W16(0x019D), W16(0xFF41), W16(0xFF1D), W16(0xFD75), W16(0xFCF1), W16(0xFBE7), W16(0xFBD7), + W16(0xFB42), W16(0xFA9B), W16(0xF9D3), W16(0xF97A), W16(0xF991), W16(0xF7F4), W16(0xF72B), W16(0xF5EF), + W16(0x10F7), W16(0x0EDE), W16(0x099F), W16(0x089E), W16(0x0663), W16(0x046B), W16(0x041E), W16(0x038F), + W16(0x035D), W16(0x0207), W16(0x0097), W16(0xFEB0), W16(0xFF14), W16(0xFE44), W16(0xFB5A), W16(0xF923), + W16(0xF705), W16(0xF4FB), W16(0xF2DA), W16(0xF0DF), W16(0xEFC8), W16(0xEDFA), W16(0xEC6A), W16(0xEBA3), + W16(0x0F44), W16(0x09B4), W16(0x0661), W16(0x04A1), W16(0x035A), W16(0x02DD), W16(0x0284), W16(0x0201), + W16(0x01CE), W16(0x01CB), W16(0x012A), W16(0x0044), W16(0xFEED), W16(0xFD34), W16(0xFC6E), W16(0xFC2C), + W16(0xFB81), W16(0xF985), W16(0xF769), W16(0xF645), W16(0xF538), W16(0xF3BD), W16(0xF0F6), W16(0xEE24), + W16(0x159C), W16(0x0F76), W16(0x0E25), W16(0x0C81), W16(0x098C), W16(0x083A), W16(0x06FD), W16(0x0592), + W16(0x0447), W16(0x027F), W16(0xFF9F), W16(0xFDDE), W16(0xFBC9), W16(0xFB42), W16(0xF8E5), W16(0xF761), + W16(0xF618), W16(0xF553), W16(0xF419), W16(0xF34C), W16(0xF35C), W16(0xF2E3), W16(0xF2AB), W16(0xF27E), + W16(0xFFEE), W16(0x05AA), W16(0x071D), W16(0x048C), W16(0x05D5), W16(0x0462), W16(0x02D5), W16(0x0197), + W16(0x01EF), W16(0x0172), W16(0x000F), W16(0xFF30), W16(0xFE66), W16(0xFD1C), W16(0xFBA3), W16(0xFB95), + W16(0xFC03), W16(0xFB3B), W16(0xF952), W16(0xF821), W16(0xF7E2), W16(0xF650), W16(0xF4EB), W16(0xF3A7), + W16(0x077D), W16(0x0A1F), W16(0x0ADC), W16(0x0956), W16(0x080F), W16(0x06D7), W16(0x0609), W16(0x0562), + W16(0x03B9), W16(0x0259), W16(0x0029), W16(0xFE97), W16(0xFCE1), W16(0xFB12), W16(0xF9D3), W16(0xF82B), + W16(0xF6EC), W16(0xF63E), W16(0xF528), W16(0xF2AC), W16(0xF084), W16(0xEE88), W16(0xED6A), W16(0xECA7), + W16(0x05E5), W16(0x05FC), W16(0x05B6), W16(0x0489), W16(0x0361), W16(0x02CE), W16(0x0299), W16(0x0210), + W16(0x01D8), W16(0x018E), W16(0x00E1), W16(0x0010), W16(0xFEC5), W16(0xFD05), W16(0xFC5B), W16(0xFCA7), + W16(0xFC05), W16(0xF9DD), W16(0xF7C1), W16(0xF717), W16(0xF5EC), W16(0xF446), W16(0xF1F0), W16(0xEFE7), + W16(0x0FC3), W16(0x0E43), W16(0x0D5A), W16(0x0A7E), W16(0x07E0), W16(0x05F8), W16(0x0422), W16(0x03E4), + W16(0x02BD), W16(0x026A), W16(0x00D4), W16(0xFEEF), W16(0xFD6B), W16(0xFBF5), W16(0xFAA4), W16(0xF8FD), + W16(0xF838), W16(0xF782), W16(0xF601), W16(0xF4A9), W16(0xF44B), W16(0xF307), W16(0xF2BC), W16(0xF270), + W16(0x0367), W16(0x05CB), W16(0x063A), W16(0x0526), W16(0x0498), W16(0x043E), W16(0x03A2), W16(0x02F4), + W16(0x0231), W16(0x0138), W16(0x0059), W16(0xFF18), W16(0xFE05), W16(0xFD20), W16(0xFC74), W16(0xFB8F), + W16(0xFA94), W16(0xF9C9), W16(0xF96E), W16(0xF949), W16(0xF8F1), W16(0xF80E), W16(0xF680), W16(0xF4B2), + W16(0x1231), W16(0x0E64), W16(0x0A87), W16(0x08C5), W16(0x06FC), W16(0x05D6), W16(0x0537), W16(0x04D6), + W16(0x03A3), W16(0x02C8), W16(0x002D), W16(0xFE7A), W16(0xFE22), W16(0xFCCD), W16(0xFA62), W16(0xF84A), + W16(0xF673), W16(0xF4BD), W16(0xF2A2), W16(0xF06F), W16(0xEFA0), W16(0xEE75), W16(0xEDAD), W16(0xED15), + W16(0x0BB9), W16(0x082C), W16(0x065F), W16(0x0530), W16(0x04A2), W16(0x0450), W16(0x03A7), W16(0x02F5), + W16(0x022F), W16(0x0136), W16(0x005D), W16(0xFF10), W16(0xFE02), W16(0xFD19), W16(0xFC6E), W16(0xFB88), + W16(0xFA8F), W16(0xF9C3), W16(0xF971), W16(0xF949), W16(0xF8E5), W16(0xF80B), W16(0xF680), W16(0xF4B1), + W16(0x1535), W16(0x1077), W16(0x0D5E), W16(0x0A03), W16(0x07A1), W16(0x05C2), W16(0x03E0), W16(0x053D), + W16(0x04B8), W16(0x025C), W16(0x009E), W16(0xFF61), W16(0xFD71), W16(0xFB83), W16(0xF8EF), W16(0xF856), + W16(0xF834), W16(0xF6D9), W16(0xF455), W16(0xF335), W16(0xF312), W16(0xF22D), W16(0xF15B), W16(0xF05C), + W16(0x00C3), W16(0x0490), W16(0x052A), W16(0x0455), W16(0x038A), W16(0x02EC), W16(0x02DF), W16(0x0265), + W16(0x021F), W16(0x0177), W16(0x00B8), W16(0xFFBB), W16(0xFE77), W16(0xFD94), W16(0xFCE7), W16(0xFC16), + W16(0xFB34), W16(0xFA39), W16(0xF949), W16(0xF82F), W16(0xF630), W16(0xF481), W16(0xF32D), W16(0xF19B), + W16(0x0CC9), W16(0x0C4E), W16(0x0C59), W16(0x09DA), W16(0x0795), W16(0x05C3), W16(0x03E9), W16(0x03D1), + W16(0x02C0), W16(0x026A), W16(0x00FD), W16(0xFF2B), W16(0xFD60), W16(0xFBC8), W16(0xFABF), W16(0xF92B), + W16(0xF88B), W16(0xF7D4), W16(0xF646), W16(0xF445), W16(0xF330), W16(0xF216), W16(0xF1D4), W16(0xF19B), + W16(0x0877), W16(0x069D), W16(0x0590), W16(0x0438), W16(0x04B3), W16(0x0508), W16(0x044D), W16(0x0304), + W16(0x0374), W16(0x0231), W16(0x00AB), W16(0xFE4C), W16(0xFC8B), W16(0xFC90), W16(0xFC1E), W16(0xFB28), + W16(0xF9F8), W16(0xF821), W16(0xF5B6), W16(0xF287), W16(0xF18B), W16(0xF10C), W16(0xEFD5), W16(0xEE9B), + W16(0x0FEF), W16(0x0C87), W16(0x0AF8), W16(0x094C), W16(0x0813), W16(0x06D4), W16(0x061E), W16(0x0572), + W16(0x03C3), W16(0x0254), W16(0x001C), W16(0xFE86), W16(0xFCDC), W16(0xFB0D), W16(0xF9D8), W16(0xF82F), + W16(0xF6E0), W16(0xF631), W16(0xF519), W16(0xF2AD), W16(0xF077), W16(0xEE89), W16(0xED6C), W16(0xECA4), + W16(0xFF6F), W16(0x0439), W16(0x05C2), W16(0x0700), W16(0x069C), W16(0x036E), W16(0x02AC), W16(0x011B), + W16(0x0056), W16(0x0068), W16(0x0017), W16(0xFF54), W16(0xFE8E), W16(0xFDF1), W16(0xFD91), W16(0xFC01), + W16(0xFBF7), W16(0xFA9F), W16(0xF9FE), W16(0xF95F), W16(0xF7F6), W16(0xF6F8), W16(0xF62B), W16(0xF5CD), + W16(0x113D), W16(0x0EA0), W16(0x0982), W16(0x0790), W16(0x0603), W16(0x03FC), W16(0x03BB), W16(0x02F3), + W16(0x02B1), W16(0x0200), W16(0x0053), W16(0xFEA6), W16(0xFF21), W16(0xFE15), W16(0xFBCF), W16(0xFA70), + W16(0xF836), W16(0xF5C7), W16(0xF364), W16(0xF0FE), W16(0xEFB5), W16(0xEE15), W16(0xECF4), W16(0xEC36), + W16(0x0D80), W16(0x08AB), W16(0x06F6), W16(0x0577), W16(0x04C6), W16(0x03FE), W16(0x036A), W16(0x0269), + W16(0x011F), W16(0x007F), W16(0xFF7D), W16(0xFEDB), W16(0xFE1D), W16(0xFD6A), W16(0xFCEB), W16(0xFCE8), + W16(0xFC19), W16(0xFAD7), W16(0xF9CA), W16(0xF8EF), W16(0xF7A0), W16(0xF637), W16(0xF4E5), W16(0xF3C8), + W16(0x154E), W16(0x0F85), W16(0x0E6E), W16(0x0C99), W16(0x09C2), W16(0x089D), W16(0x06F1), W16(0x04BB), + W16(0x030D), W16(0x01D2), W16(0xFF8A), W16(0xFE83), W16(0xFC74), W16(0xFB0D), W16(0xF947), W16(0xF7B0), + W16(0xF692), W16(0xF5F4), W16(0xF492), W16(0xF3EA), W16(0xF3DB), W16(0xF344), W16(0xF300), W16(0xF2C7), + W16(0x059C), W16(0x0678), W16(0x0739), W16(0x059B), W16(0x04D3), W16(0x0434), W16(0x03C7), W16(0x029A), + W16(0x0135), W16(0x00BA), W16(0xFFCA), W16(0xFE7B), W16(0xFDE8), W16(0xFDB0), W16(0xFD54), W16(0xFC50), + W16(0xFB26), W16(0xFA10), W16(0xF8CA), W16(0xF79D), W16(0xF5E8), W16(0xF43C), W16(0xF2F5), W16(0xF200), + W16(0x0A2C), W16(0x0BF7), W16(0x0BB0), W16(0x09DA), W16(0x087D), W16(0x079C), W16(0x0640), W16(0x05D4), + W16(0x0434), W16(0x0286), W16(0x0059), W16(0xFE6B), W16(0xFC7B), W16(0xFA60), W16(0xF901), W16(0xF7CA), + W16(0xF6AE), W16(0xF583), W16(0xF462), W16(0xF368), W16(0xF2E5), W16(0xF24B), W16(0xF1B0), W16(0xF143), + W16(0x080E), W16(0x063B), W16(0x04D7), W16(0x03B5), W16(0x032F), W16(0x0286), W16(0x0297), W16(0x0258), + W16(0x01F5), W16(0x0194), W16(0x00B5), W16(0xFFEE), W16(0xFEAA), W16(0xFDBF), W16(0xFD14), W16(0xFC38), + W16(0xFB7B), W16(0xFA4B), W16(0xF95B), W16(0xF827), W16(0xF5DF), W16(0xF427), W16(0xF2A4), W16(0xF0D8), + W16(0x0BF7), W16(0x0DAE), W16(0x0E6C), W16(0x0CA8), W16(0x0988), W16(0x07CC), W16(0x06AC), W16(0x053F), + W16(0x0504), W16(0x0391), W16(0x00A8), W16(0xFEE6), W16(0xFBE1), W16(0xFA1C), W16(0xF842), W16(0xF6C8), + W16(0xF599), W16(0xF4E4), W16(0xF393), W16(0xF2CE), W16(0xF319), W16(0xF280), W16(0xF238), W16(0xF1FF), + W16(0x071A), W16(0x069C), W16(0x0603), W16(0x070B), W16(0x06A3), W16(0x0371), W16(0x02AE), W16(0x0120), + W16(0x0054), W16(0x0072), W16(0x0020), W16(0xFF5E), W16(0xFE81), W16(0xFDEB), W16(0xFD8C), W16(0xFBF4), + W16(0xFBEF), W16(0xFA96), W16(0xF9F7), W16(0xF954), W16(0xF7CB), W16(0xF6D2), W16(0xF602), W16(0xF59F), + W16(0x11C4), W16(0x0EBE), W16(0x09D4), W16(0x083C), W16(0x0610), W16(0x046E), W16(0x0439), W16(0x0387), + W16(0x035C), W16(0x0209), W16(0x00B5), W16(0xFE91), W16(0xFF44), W16(0xFE67), W16(0xFB2E), W16(0xF948), + W16(0xF6F6), W16(0xF530), W16(0xF34C), W16(0xF1B8), W16(0xF0E9), W16(0xEFBC), W16(0xEEDB), W16(0xEE5B), + W16(0x0C81), W16(0x0AAB), W16(0x082C), W16(0x06AA), W16(0x05BA), W16(0x048D), W16(0x02A0), W16(0x01BC), + W16(0x0207), W16(0x00EF), W16(0xFF91), W16(0xFE7F), W16(0xFE1E), W16(0xFD9A), W16(0xFCFD), W16(0xFC21), + W16(0xFB7F), W16(0xFB22), W16(0xFA12), W16(0xF8D4), W16(0xF79C), W16(0xF67E), W16(0xF578), W16(0xF49A), + W16(0x15E4), W16(0x0FAA), W16(0x0D3B), W16(0x0AAE), W16(0x0793), W16(0x055C), W16(0x042F), W16(0x0411), + W16(0x024D), W16(0x0223), W16(0x003E), W16(0xFE80), W16(0xFD25), W16(0xFBCD), W16(0xFAB4), W16(0xF9F2), + W16(0xFA0B), W16(0xFA0B), W16(0xF8CB), W16(0xF71B), W16(0xF541), W16(0xF318), W16(0xF1D1), W16(0xF0E5), + W16(0x00C1), W16(0x04F8), W16(0x05DF), W16(0x04A6), W16(0x04E6), W16(0x051A), W16(0x03EE), W16(0x0222), + W16(0x027D), W16(0x01C6), W16(0x00A1), W16(0xFE74), W16(0xFC93), W16(0xFD00), W16(0xFCA2), W16(0xFBD6), + W16(0xFA8F), W16(0xF921), W16(0xF6B4), W16(0xF360), W16(0xF234), W16(0xF1CC), W16(0xF098), W16(0xEF7C), + W16(0x09A6), W16(0x0B5C), W16(0x08FD), W16(0x0823), W16(0x0635), W16(0x046C), W16(0x0414), W16(0x0355), + W16(0x032D), W16(0x020B), W16(0x005C), W16(0xFE99), W16(0xFF5B), W16(0xFE74), W16(0xFB94), W16(0xF948), + W16(0xF71E), W16(0xF579), W16(0xF3B1), W16(0xF238), W16(0xF1A5), W16(0xF0B2), W16(0xEFF3), W16(0xEF8A), + W16(0x0B75), W16(0x0825), W16(0x06AA), W16(0x05E4), W16(0x058D), W16(0x04CD), W16(0x0380), W16(0x0277), + W16(0x0230), W16(0x01A7), W16(0x00CD), W16(0xFF92), W16(0xFDBE), W16(0xFCF0), W16(0xFB7E), W16(0xFB60), + W16(0xF9ED), W16(0xF79E), W16(0xF567), W16(0xF25B), W16(0xF175), W16(0xF1B3), W16(0xF00F), W16(0xEF68), + W16(0x10BA), W16(0x0DA4), W16(0x0C13), W16(0x0A09), W16(0x0881), W16(0x07B1), W16(0x0695), W16(0x0646), + W16(0x0441), W16(0x0314), W16(0x0082), W16(0xFE65), W16(0xFC91), W16(0xFAB2), W16(0xF912), W16(0xF718), + W16(0xF54B), W16(0xF40C), W16(0xF2E2), W16(0xF1EA), W16(0xF11C), W16(0xF056), W16(0xEFC2), W16(0xEF69), + W16(0xFF55), W16(0x0390), W16(0x0492), W16(0x0613), W16(0x050A), W16(0x0220), W16(0x02D3), W16(0x04A9), + W16(0x0184), W16(0x00B1), W16(0xFFC3), W16(0xFF2D), W16(0xFE4D), W16(0xFDF9), W16(0xFCC9), W16(0xFC03), + W16(0xFB22), W16(0xFAC1), W16(0xFA3B), W16(0xFA38), W16(0xFA06), W16(0xF8D8), W16(0xF7EA), W16(0xF728), + W16(0x11B5), W16(0x0EF5), W16(0x09CB), W16(0x0809), W16(0x064A), W16(0x042E), W16(0x040C), W16(0x0357), + W16(0x02F1), W16(0x024E), W16(0x0056), W16(0xFEAF), W16(0xFF65), W16(0xFE60), W16(0xFB98), W16(0xF94B), + W16(0xF73A), W16(0xF534), W16(0xF2EF), W16(0xF0CD), W16(0xEF97), W16(0xEE13), W16(0xECFC), W16(0xEC4C), + W16(0x0E1A), W16(0x07FF), W16(0x0574), W16(0x0424), W16(0x0308), W16(0x0288), W16(0x025B), W16(0x01DC), + W16(0x01A6), W16(0x0194), W16(0x00BD), W16(0xFFF1), W16(0xFED2), W16(0xFD0A), W16(0xFC7C), W16(0xFD39), + W16(0xFCBF), W16(0xFAB3), W16(0xF883), W16(0xF858), W16(0xF754), W16(0xF580), W16(0xF326), W16(0xF164), + W16(0x1578), W16(0x1060), W16(0x0F1C), W16(0x0D00), W16(0x09C6), W16(0x0813), W16(0x06DB), W16(0x056D), + W16(0x051A), W16(0x03B2), W16(0x0098), W16(0xFEA8), W16(0xFBA2), W16(0xF9EC), W16(0xF816), W16(0xF6B4), + W16(0xF57B), W16(0xF4BD), W16(0xF36B), W16(0xF2CB), W16(0xF2DA), W16(0xF255), W16(0xF211), W16(0xF1D9), + W16(0x037E), W16(0x060E), W16(0x0676), W16(0x0551), W16(0x04A6), W16(0x03E7), W16(0x0350), W16(0x0258), + W16(0x0116), W16(0x0082), W16(0xFF71), W16(0xFEE3), W16(0xFE38), W16(0xFD84), W16(0xFCFA), W16(0xFCF9), + W16(0xFC31), W16(0xFB55), W16(0xFA9A), W16(0xF9FC), W16(0xF8C4), W16(0xF77C), W16(0xF655), W16(0xF56C), + W16(0x084B), W16(0x0BA1), W16(0x0C77), W16(0x0AAE), W16(0x0923), W16(0x080C), W16(0x071E), W16(0x0665), + W16(0x04A1), W16(0x0315), W16(0x0026), W16(0xFE65), W16(0xFC85), W16(0xFA45), W16(0xF8C1), W16(0xF712), + W16(0xF46E), W16(0xF315), W16(0xF120), W16(0xEF4A), W16(0xEE87), W16(0xED2A), W16(0xEC77), W16(0xEC38), + W16(0x0999), W16(0x071B), W16(0x0556), W16(0x042B), W16(0x036A), W16(0x030C), W16(0x02F3), W16(0x0244), + W16(0x023C), W16(0x017E), W16(0x00BA), W16(0xFFC4), W16(0xFE76), W16(0xFD99), W16(0xFCD2), W16(0xFC0E), + W16(0xFB2C), W16(0xFA4D), W16(0xF98D), W16(0xF8D6), W16(0xF71A), W16(0xF57C), W16(0xF44B), W16(0xF2E6), + W16(0x0EC4), W16(0x0F57), W16(0x0DAE), W16(0x0A4B), W16(0x0792), W16(0x05B9), W16(0x042F), W16(0x052A), + W16(0x04B9), W16(0x0265), W16(0x00B7), W16(0xFF57), W16(0xFD8E), W16(0xFB34), W16(0xF8FA), W16(0xF87C), + W16(0xF7F8), W16(0xF6CD), W16(0xF574), W16(0xF502), W16(0xF522), W16(0xF458), W16(0xF39D), W16(0xF2A2), + W16(0x041B), W16(0x055C), W16(0x037A), W16(0x0524), W16(0x046C), W16(0x018B), W16(0x023A), W16(0x0577), + W16(0x011B), W16(0x014E), W16(0x000F), W16(0xFF9F), W16(0xFE98), W16(0xFE17), W16(0xFC95), W16(0xFBDD), + W16(0xFB20), W16(0xFA7B), W16(0xF99C), W16(0xF917), W16(0xF8F0), W16(0xF7A1), W16(0xF6A6), W16(0xF5EF), + W16(0x124C), W16(0x0F7E), W16(0x0A28), W16(0x07F6), W16(0x0685), W16(0x046A), W16(0x0448), W16(0x03B7), + W16(0x0369), W16(0x0234), W16(0x0091), W16(0xFE7E), W16(0xFF1D), W16(0xFE27), W16(0xFB41), W16(0xF906), + W16(0xF6DA), W16(0xF4B7), W16(0xF2AD), W16(0xF08B), W16(0xEF6C), W16(0xEDE1), W16(0xECAB), W16(0xEBFF), + W16(0x0AC7), W16(0x090A), W16(0x066E), W16(0x050B), W16(0x0486), W16(0x0345), W16(0x025D), W16(0x01DD), + W16(0x016D), W16(0x00DB), W16(0xFFF7), W16(0xFF86), W16(0xFE3F), W16(0xFDC9), W16(0xFD3F), W16(0xFCD6), + W16(0xFC18), W16(0xFB8D), W16(0xFB22), W16(0xFAA9), W16(0xF935), W16(0xF7A8), W16(0xF71D), W16(0xF5F9), + W16(0x1773), W16(0x11C9), W16(0x0E4C), W16(0x0B28), W16(0x0863), W16(0x06A2), W16(0x04C0), W16(0x04F4), + W16(0x03AC), W16(0x02F9), W16(0x00FF), W16(0xFF05), W16(0xFCDD), W16(0xFAF6), W16(0xF9B8), W16(0xF7F2), + W16(0xF720), W16(0xF63F), W16(0xF4B7), W16(0xF379), W16(0xF34D), W16(0xF22F), W16(0xF1E0), W16(0xF189), + W16(0x0386), W16(0x0768), W16(0x07CF), W16(0x05BE), W16(0x0445), W16(0x031D), W16(0x02BA), W16(0x02A4), + W16(0x0253), W16(0x01D0), W16(0x00B7), W16(0xFF23), W16(0xFE0F), W16(0xFDB2), W16(0xFCC0), W16(0xFBB3), + W16(0xFB0F), W16(0xFA0E), W16(0xF8FB), W16(0xF7BA), W16(0xF676), W16(0xF4C6), W16(0xF335), W16(0xF1B7), + W16(0x0D50), W16(0x0E22), W16(0x0D40), W16(0x0A33), W16(0x078C), W16(0x058E), W16(0x040F), W16(0x053B), + W16(0x04AC), W16(0x0277), W16(0x00BB), W16(0xFF75), W16(0xFD8E), W16(0xFB57), W16(0xF907), W16(0xF847), + W16(0xF816), W16(0xF6AD), W16(0xF47E), W16(0xF38D), W16(0xF3A2), W16(0xF2BA), W16(0xF1E9), W16(0xF0F0), + W16(0x0956), W16(0x078B), W16(0x0679), W16(0x050A), W16(0x0501), W16(0x04D6), W16(0x03A7), W16(0x0243), + W16(0x0288), W16(0x01A6), W16(0x008F), W16(0xFE95), W16(0xFD0F), W16(0xFCDF), W16(0xFC73), W16(0xFBE7), + W16(0xFAA5), W16(0xF93B), W16(0xF6D9), W16(0xF3BD), W16(0xF254), W16(0xF203), W16(0xF0F4), W16(0xEFE0), + W16(0x1206), W16(0x0EA1), W16(0x0BE4), W16(0x09D1), W16(0x0868), W16(0x0769), W16(0x0635), W16(0x05ED), + W16(0x044B), W16(0x029D), W16(0x003D), W16(0xFE68), W16(0xFC72), W16(0xFA57), W16(0xF901), W16(0xF7E0), + W16(0xF6D5), W16(0xF5A0), W16(0xF464), W16(0xF31B), W16(0xF272), W16(0xF1E0), W16(0xF13B), W16(0xF0C5), + W16(0x0030), W16(0x0026), W16(0xFFFE), W16(0x000F), W16(0x000E), W16(0x002B), W16(0x001B), W16(0xFFFA), + W16(0xFFFD), W16(0x0031), W16(0x000C), W16(0xFFF6), W16(0x0000), W16(0x0025), W16(0x000E), W16(0x0019), + W16(0x002D), W16(0x000F), W16(0xFFFA), W16(0x0019), W16(0x0004), W16(0x0009), W16(0xFFE3), W16(0x001A), + W16(0x1088), W16(0x0E1C), W16(0x0925), W16(0x0774), W16(0x05E9), W16(0x0444), W16(0x03AF), W16(0x031D), + W16(0x02ED), W16(0x01D6), W16(0x001A), W16(0xFEAB), W16(0xFF43), W16(0xFE92), W16(0xFC13), W16(0xF9E1), + W16(0xF7B9), W16(0xF5B2), W16(0xF370), W16(0xF175), W16(0xF007), W16(0xEE39), W16(0xEC85), W16(0xEBB2), + W16(0x0C41), W16(0x0B9B), W16(0x08F6), W16(0x060A), W16(0x047E), W16(0x0367), W16(0x02EB), W16(0x02B5), + W16(0x0229), W16(0x01CD), W16(0x00D1), W16(0xFF51), W16(0xFE2E), W16(0xFD6C), W16(0xFC3C), W16(0xFB9B), + W16(0xFAF3), W16(0xF9FB), W16(0xF904), W16(0xF794), W16(0xF5EB), W16(0xF448), W16(0xF297), W16(0xF112), + W16(0x1841), W16(0x1114), W16(0x0E1F), W16(0x0BC4), W16(0x0928), W16(0x07F2), W16(0x0645), W16(0x0597), + W16(0x0320), W16(0x020F), W16(0xFFBD), W16(0xFD59), W16(0xFB76), W16(0xFA6A), W16(0xF9D9), W16(0xF8B4), + W16(0xF85A), W16(0xF7E9), W16(0xF6BF), W16(0xF59E), W16(0xF4BC), W16(0xF374), W16(0xF2FA), W16(0xF28E), + W16(0x040C), W16(0x085D), W16(0x07F5), W16(0x06B2), W16(0x05B3), W16(0x0489), W16(0x02A3), W16(0x01C6), + W16(0x0210), W16(0x00FA), W16(0xFF92), W16(0xFE81), W16(0xFE16), W16(0xFD92), W16(0xFCF3), W16(0xFC22), + W16(0xFB81), W16(0xFB21), W16(0xFA10), W16(0xF8D1), W16(0xF7AE), W16(0xF682), W16(0xF57B), W16(0xF499), + W16(0x0A70), W16(0x0CC9), W16(0x0C30), W16(0x0A4C), W16(0x08C0), W16(0x07E8), W16(0x068B), W16(0x0608), + W16(0x047C), W16(0x02D7), W16(0x0045), W16(0xFE38), W16(0xFC5A), W16(0xFA03), W16(0xF87A), W16(0xF794), + W16(0xF68A), W16(0xF541), W16(0xF3C7), W16(0xF219), W16(0xF161), W16(0xF04C), W16(0xEF66), W16(0xEE85), + W16(0x09B5), W16(0x0777), W16(0x062C), W16(0x0522), W16(0x041F), W16(0x0379), W16(0x030C), W16(0x028F), + W16(0x022B), W16(0x0180), W16(0x00C3), W16(0xFF88), W16(0xFE4D), W16(0xFD43), W16(0xFCCD), W16(0xFBBF), + W16(0xFABA), W16(0xF9D8), W16(0xF8C3), W16(0xF794), W16(0xF5E1), W16(0xF440), W16(0xF2BA), W16(0xF0EB), + W16(0x0E79), W16(0x0E14), W16(0x0DAD), W16(0x0BF1), W16(0x0986), W16(0x0850), W16(0x069D), W16(0x05E7), + W16(0x0365), W16(0x01E7), W16(0xFF95), W16(0xFD26), W16(0xFB64), W16(0xFA4C), W16(0xF992), W16(0xF86A), + W16(0xF7F2), W16(0xF753), W16(0xF60A), W16(0xF4B6), W16(0xF478), W16(0xF34C), W16(0xF309), W16(0xF2C1), + W16(0x0629), W16(0x085C), W16(0x07B5), W16(0x05D5), W16(0x03A3), W16(0x0232), W16(0x01A6), W16(0x01AA), + W16(0x019D), W16(0x0164), W16(0x00B9), W16(0xFF98), W16(0xFE70), W16(0xFE08), W16(0xFDAD), W16(0xFCF3), + W16(0xFC70), W16(0xFB8D), W16(0xFA6A), W16(0xF94F), W16(0xF7E8), W16(0xF675), W16(0xF524), W16(0xF3D5), + W16(0x11B2), W16(0x0E4F), W16(0x08FA), W16(0x0833), W16(0x0622), W16(0x0493), W16(0x0451), W16(0x02EE), + W16(0x02A4), W16(0x0151), W16(0xFFDB), W16(0xFE6E), W16(0xFEA3), W16(0xFE6B), W16(0xFBEF), W16(0xFA4A), + W16(0xF887), W16(0xF696), W16(0xF461), W16(0xF27D), W16(0xF1CA), W16(0xF0EB), W16(0xF04C), W16(0xF014), + W16(0x0E96), W16(0x0B2E), W16(0x0818), W16(0x05E8), W16(0x03AA), W16(0x0250), W16(0x01F1), W16(0x01F9), + W16(0x01D1), W16(0x016C), W16(0x00CA), W16(0xFF64), W16(0xFE0D), W16(0xFDE3), W16(0xFDAE), W16(0xFCC4), + W16(0xFC4E), W16(0xFB93), W16(0xFA73), W16(0xF957), W16(0xF7B4), W16(0xF62B), W16(0xF527), W16(0xF3B7), + W16(0x17EA), W16(0x10B1), W16(0x0D83), W16(0x0A75), W16(0x07F4), W16(0x0606), W16(0x042B), W16(0x03F9), + W16(0x02B8), W16(0x027D), W16(0x00F7), W16(0xFEED), W16(0xFD61), W16(0xFBC5), W16(0xFA88), W16(0xF8F0), + W16(0xF82A), W16(0xF775), W16(0xF601), W16(0xF4EB), W16(0xF453), W16(0xF321), W16(0xF2CA), W16(0xF274) +}; + +const Word16 cdk_37bits_2_fx[1536] = +{ + W16(0xFFB3), W16(0xFFD1), W16(0xFFDB), W16(0xFFB1), W16(0xFFE5), W16(0x0002), W16(0xFFE4), W16(0xFFED), + W16(0x0018), W16(0x0058), W16(0x005D), W16(0x006D), W16(0x0055), W16(0x0018), W16(0xFFB1), W16(0xFF83), + W16(0xFF6E), W16(0xFF10), W16(0xFEBF), W16(0xFE86), W16(0xFE7C), W16(0xFE80), W16(0xFE8F), W16(0xFEB7), + W16(0xFD2D), W16(0xFEBB), W16(0x0033), W16(0x017C), W16(0xFFED), W16(0xFF59), W16(0x0125), W16(0x0143), + W16(0xFFA1), W16(0xFFB6), W16(0xFFCD), W16(0xFFD2), W16(0xFF67), W16(0x0008), W16(0x0053), W16(0xFFDB), + W16(0xFFC0), W16(0x0014), W16(0xFFC0), W16(0xFF6B), W16(0xFF62), W16(0xFF1F), W16(0xFF27), W16(0xFE5D), + W16(0xFE2D), W16(0xFF2A), W16(0xFF78), W16(0xFF50), W16(0xFF70), W16(0xFFA8), W16(0xFF9A), W16(0xFFDD), + W16(0xFFED), W16(0xFFEE), W16(0x0005), W16(0x0058), W16(0x0061), W16(0x0046), W16(0x0033), W16(0x0038), + W16(0x0028), W16(0x003C), W16(0x0034), W16(0x002D), W16(0xFFCC), W16(0xFFBE), W16(0xFF8D), W16(0xFF79), + W16(0xFEF1), W16(0xFF29), W16(0xFF4E), W16(0xFF83), W16(0xFFA8), W16(0xFFE0), W16(0x0016), W16(0x0049), + W16(0x0085), W16(0x0044), W16(0x0040), W16(0x002F), W16(0x0001), W16(0xFFF3), W16(0xFFAF), W16(0xFFB5), + W16(0xFF89), W16(0xFF71), W16(0xFF59), W16(0xFF44), W16(0xFF48), W16(0xFF52), W16(0xFF54), W16(0xFF57), + W16(0x0021), W16(0xFF57), W16(0xFFC3), W16(0xFFEF), W16(0x006E), W16(0x007D), W16(0x0042), W16(0x0015), + W16(0x0004), W16(0x0006), W16(0x0015), W16(0x000B), W16(0xFFFA), W16(0xFFB0), W16(0xFFA3), W16(0xFFB1), + W16(0xFF96), W16(0xFF7B), W16(0xFF7E), W16(0xFF93), W16(0xFF83), W16(0xFF84), W16(0xFF8F), W16(0xFFA2), + W16(0xFFDE), W16(0xFF98), W16(0xFFB5), W16(0xFF7D), W16(0xFFC8), W16(0x004A), W16(0x0095), W16(0x0118), + W16(0x0018), W16(0xFFB7), W16(0xFF95), W16(0xFF9B), W16(0xFF9D), W16(0xFF73), W16(0xFFC4), W16(0x0033), + W16(0x003B), W16(0xFFAF), W16(0xFFA1), W16(0xFF9B), W16(0x0013), W16(0x0077), W16(0x0058), W16(0x0073), + W16(0xFF2B), W16(0xFFBF), W16(0xFFFD), W16(0x003C), W16(0x0040), W16(0x0096), W16(0x0067), W16(0x0095), + W16(0x0069), W16(0x003F), W16(0x000F), W16(0xFFE4), W16(0xFFAA), W16(0xFF59), W16(0xFF7C), W16(0xFF83), + W16(0xFF92), W16(0xFF82), W16(0xFFA1), W16(0xFFCC), W16(0xFFF5), W16(0x006F), W16(0x00B8), W16(0x00D2), + W16(0x0123), W16(0xFFB5), W16(0xFFA8), W16(0xFFC4), W16(0xFFB1), W16(0xFFBE), W16(0xFFDA), W16(0x000D), + W16(0x002E), W16(0x0047), W16(0x004A), W16(0x003D), W16(0x0038), W16(0x0008), W16(0xFFE0), W16(0xFFC3), + W16(0xFFCA), W16(0xFFA9), W16(0xFFB6), W16(0xFFA2), W16(0xFF8F), W16(0xFF6E), W16(0xFF69), W16(0xFF76), + W16(0xFFDE), W16(0xFF74), W16(0xFF2C), W16(0xFEEE), W16(0xFEF8), W16(0xFF28), W16(0xFF7F), W16(0xFFD0), + W16(0xFFF8), W16(0x002D), W16(0x007E), W16(0x0075), W16(0x006F), W16(0x006B), W16(0x0068), W16(0x0031), + W16(0x0006), W16(0xFFB4), W16(0xFF96), W16(0xFF61), W16(0xFF3E), W16(0xFF33), W16(0xFF24), W16(0xFF32), + W16(0xFF74), W16(0x0009), W16(0x000A), W16(0xFF60), W16(0x000F), W16(0x0039), W16(0x002C), W16(0x0019), + W16(0xFFED), W16(0xFFF5), W16(0xFFF6), W16(0xFFE6), W16(0x0009), W16(0xFFF4), W16(0xFFFD), W16(0xFFDF), + W16(0xFFDC), W16(0xFFAD), W16(0xFFA0), W16(0xFF7E), W16(0xFF5A), W16(0xFF45), W16(0xFF42), W16(0xFF54), + W16(0xFFAD), W16(0xFF8E), W16(0xFF94), W16(0xFFD4), W16(0x002A), W16(0xFFDA), W16(0xFF38), W16(0xFF1F), + W16(0xFF4F), W16(0xFFCA), W16(0x000A), W16(0x008E), W16(0x00B2), W16(0x0058), W16(0x002B), W16(0x0062), + W16(0x005D), W16(0x000C), W16(0xFFDF), W16(0x001B), W16(0x005D), W16(0x0085), W16(0x0044), W16(0x006D), + W16(0xFFAB), W16(0xFFA3), W16(0xFF6B), W16(0xFFB2), W16(0xFFEE), W16(0xFFD1), W16(0xFFE9), W16(0xFFFE), + W16(0x000A), W16(0xFFF3), W16(0x000A), W16(0x0022), W16(0x002D), W16(0x000B), W16(0x000D), W16(0xFFFC), + W16(0xFFEF), W16(0xFFE3), W16(0xFFD6), W16(0xFFDF), W16(0xFFDE), W16(0xFFE5), W16(0xFFF3), W16(0x0003), + W16(0x0058), W16(0xFF6D), W16(0xFEDB), W16(0x0148), W16(0x002F), W16(0xFEF8), W16(0x0025), W16(0x00F8), + W16(0x007F), W16(0x001A), W16(0xFFFD), W16(0x0016), W16(0x000A), W16(0x0003), W16(0xFF8F), W16(0xFFB0), + W16(0xFFC4), W16(0xFFEC), W16(0xFFB3), W16(0xFFB1), W16(0xFF88), W16(0xFF36), W16(0xFECB), W16(0xFE30), + W16(0x000E), W16(0x0038), W16(0x00C8), W16(0x0124), W16(0x013B), W16(0x00A4), W16(0x0050), W16(0x0061), + W16(0x0053), W16(0x0022), W16(0xFFC3), W16(0xFFC8), W16(0xFFB0), W16(0xFF77), W16(0xFF89), W16(0xFF67), + W16(0xFF57), W16(0xFF51), W16(0xFF46), W16(0xFF20), W16(0xFF1B), W16(0xFF2D), W16(0xFF2F), W16(0xFF42), + W16(0xFF7C), W16(0xFF55), W16(0xFF89), W16(0xFFC7), W16(0x0030), W16(0x0076), W16(0x003C), W16(0xFFC6), + W16(0xFFAA), W16(0xFF6A), W16(0xFF99), W16(0xFFC6), W16(0x002C), W16(0x0079), W16(0x0055), W16(0x0003), + W16(0xFFE7), W16(0x0025), W16(0x0019), W16(0xFFE8), W16(0xFFE1), W16(0xFFDC), W16(0xFFEB), W16(0xFFF7), + W16(0x0065), W16(0x0005), W16(0xFFC6), W16(0x0050), W16(0x0034), W16(0x003B), W16(0x0021), W16(0xFFFF), + W16(0x0016), W16(0x0004), W16(0xFFF6), W16(0x0022), W16(0xFFE4), W16(0xFF9E), W16(0xFFC9), W16(0xFFEF), + W16(0x0003), W16(0x001B), W16(0x003A), W16(0x0053), W16(0x0047), W16(0x0049), W16(0x0050), W16(0x005C), + W16(0x001D), W16(0xFFFA), W16(0x0042), W16(0x0045), W16(0x0074), W16(0xFFC3), W16(0xFFB3), W16(0xFFCF), + W16(0x005C), W16(0x0038), W16(0x003E), W16(0x0038), W16(0x0018), W16(0x0004), W16(0xFFCD), W16(0xFFB4), + W16(0xFFA0), W16(0xFFA0), W16(0xFF9C), W16(0xFF96), W16(0xFFA3), W16(0xFF9F), W16(0xFFB6), W16(0xFFD0), + W16(0xFED6), W16(0xFFA8), W16(0xFFDC), W16(0xFFD1), W16(0xFFDB), W16(0xFFFF), W16(0x0015), W16(0x0024), + W16(0x001F), W16(0x0002), W16(0xFFD6), W16(0xFFDB), W16(0xFFE0), W16(0xFFDC), W16(0x0009), W16(0x0022), + W16(0x0036), W16(0x0040), W16(0x0047), W16(0x0068), W16(0x0035), W16(0x001B), W16(0x000A), W16(0x000E), + W16(0xFFDD), W16(0xFF6B), W16(0xFF4C), W16(0xFF80), W16(0xFF71), W16(0xFF90), W16(0xFFAF), W16(0xFFCD), + W16(0xFFCC), W16(0xFFF8), W16(0x0011), W16(0x0039), W16(0x003A), W16(0x0018), W16(0x0047), W16(0x0064), + W16(0x0079), W16(0x0081), W16(0x00DA), W16(0x0122), W16(0x013D), W16(0x014D), W16(0x0166), W16(0x0164), + W16(0xFFD7), W16(0xFF25), W16(0xFEAE), W16(0xFEAA), W16(0xFF89), W16(0x0022), W16(0xFFDF), W16(0x0003), + W16(0x002B), W16(0x0009), W16(0x0003), W16(0x0020), W16(0x0032), W16(0xFFFE), W16(0xFFE6), W16(0x0001), + W16(0x0004), W16(0x000C), W16(0x001D), W16(0x002B), W16(0x0001), W16(0x0016), W16(0x0071), W16(0x0073), + W16(0x0078), W16(0x0042), W16(0x0005), W16(0xFFA0), W16(0x003D), W16(0x0046), W16(0x0018), W16(0xFFCE), + W16(0xFFF6), W16(0xFFEF), W16(0x0010), W16(0xFFE3), W16(0x0004), W16(0x0003), W16(0xFFF9), W16(0xFFE9), + W16(0xFFD6), W16(0xFFC6), W16(0xFFCD), W16(0xFFC6), W16(0xFFB9), W16(0xFFC7), W16(0xFFCB), W16(0xFFDD), + W16(0x00A0), W16(0xFFEB), W16(0xFFE2), W16(0xFF8B), W16(0x000C), W16(0x0079), W16(0x007F), W16(0x00BD), + W16(0x0098), W16(0x002C), W16(0x000B), W16(0xFFD9), W16(0xFFD6), W16(0xFFB0), W16(0xFF62), W16(0xFF53), + W16(0xFF5C), W16(0xFF4D), W16(0xFF42), W16(0xFF63), W16(0xFFAE), W16(0xFFD8), W16(0x0007), W16(0x004E), + W16(0xFF5C), W16(0x0027), W16(0x0008), W16(0x001B), W16(0x0020), W16(0x002A), W16(0x0043), W16(0xFFE7), + W16(0x0049), W16(0x0023), W16(0x0019), W16(0xFFDB), W16(0xFFFC), W16(0xFFF1), W16(0xFFC8), W16(0xFFB7), + W16(0xFFC1), W16(0xFFEF), W16(0x0057), W16(0x00C2), W16(0x00F7), W16(0x0133), W16(0x0193), W16(0x0204), + W16(0x00E7), W16(0xFFB8), W16(0xFF59), W16(0xFF4C), W16(0xFFA9), W16(0xFF9E), W16(0xFFB3), W16(0xFFBF), + W16(0xFFA9), W16(0xFFC1), W16(0xFFEF), W16(0x001A), W16(0x0053), W16(0x0056), W16(0x0051), W16(0x0071), + W16(0x006A), W16(0x0042), W16(0x003B), W16(0x003E), W16(0x0035), W16(0x003A), W16(0x0045), W16(0x0055), + W16(0xFF39), W16(0xFFE6), W16(0xFFED), W16(0xFF80), W16(0xFF51), W16(0xFF63), W16(0xFF81), W16(0xFFC1), + W16(0x0085), W16(0x00B5), W16(0x0078), W16(0x001F), W16(0xFFFA), W16(0xFFC4), W16(0xFFF2), W16(0x0030), + W16(0x005A), W16(0x0026), W16(0x0010), W16(0x0001), W16(0xFFD9), W16(0xFFB9), W16(0xFF83), W16(0xFF55), + W16(0xFF8A), W16(0x0105), W16(0x010B), W16(0xFFD4), W16(0xFFBC), W16(0xFF9B), W16(0xFFD3), W16(0xFFFA), + W16(0xFFF9), W16(0x0026), W16(0x001B), W16(0x001B), W16(0x0020), W16(0x000A), W16(0x0021), W16(0x002E), + W16(0x000E), W16(0x0001), W16(0x0005), W16(0xFFEE), W16(0xFFEA), W16(0x0024), W16(0x0020), W16(0x0022), + W16(0xFFB2), W16(0xFFF7), W16(0xFFB1), W16(0xFF56), W16(0xFF75), W16(0xFFB1), W16(0xFFCD), W16(0xFFBF), + W16(0xFFD3), W16(0xFFD5), W16(0xFFEF), W16(0xFFF9), W16(0x0003), W16(0x0031), W16(0x0039), W16(0x008B), + W16(0x00C8), W16(0x0076), W16(0x0055), W16(0x0034), W16(0x000F), W16(0x0003), W16(0xFFEF), W16(0xFFD6), + W16(0x0028), W16(0xFFFC), W16(0xFFFA), W16(0xFFD1), W16(0xFF1C), W16(0x002B), W16(0x001E), W16(0x000D), + W16(0x0027), W16(0x0018), W16(0x001B), W16(0xFFF3), W16(0x0029), W16(0x0024), W16(0x000A), W16(0xFFFE), + W16(0xFFEB), W16(0xFFED), W16(0xFFFB), W16(0x0002), W16(0xFFFF), W16(0x0004), W16(0x0010), W16(0x001F), + W16(0x008D), W16(0x000D), W16(0xFFDE), W16(0xFFE5), W16(0x0016), W16(0xFFFB), W16(0xFFCA), W16(0xFFDE), + W16(0xFFBB), W16(0xFFA1), W16(0xFFCE), W16(0xFFD8), W16(0x0006), W16(0x0005), W16(0x000E), W16(0x0080), + W16(0x00AB), W16(0x0041), W16(0xFFDE), W16(0xFFA4), W16(0xFF6E), W16(0xFF47), W16(0xFF30), W16(0xFF31), + W16(0xFF69), W16(0xFFAC), W16(0xFF93), W16(0xFF7F), W16(0x0021), W16(0x003F), W16(0xFFD0), W16(0xFF89), + W16(0xFF75), W16(0xFF81), W16(0xFF9C), W16(0xFF4B), W16(0xFF1F), W16(0x0011), W16(0x015C), W16(0x018B), + W16(0x0053), W16(0x001B), W16(0xFF65), W16(0xFED5), W16(0x0002), W16(0x0108), W16(0x0023), W16(0x0033), + W16(0xFFC2), W16(0x0007), W16(0x0014), W16(0x008D), W16(0x0088), W16(0x0096), W16(0x00C7), W16(0x0039), + W16(0xFFCB), W16(0xFF6F), W16(0xFF89), W16(0xFF74), W16(0xFF8B), W16(0xFFC2), W16(0x000E), W16(0x0031), + W16(0x001F), W16(0x0022), W16(0x0056), W16(0x0053), W16(0x0001), W16(0xFF91), W16(0xFF5F), W16(0xFF4A), + W16(0x00C6), W16(0x00D2), W16(0x00BF), W16(0x003B), W16(0x0078), W16(0x008A), W16(0x0068), W16(0x0017), + W16(0x003D), W16(0x0026), W16(0xFFF2), W16(0xFFC0), W16(0xFFA7), W16(0xFFAB), W16(0xFF98), W16(0xFFC2), + W16(0xFFC0), W16(0xFFD2), W16(0xFFCB), W16(0xFFE4), W16(0x0019), W16(0x0033), W16(0x0060), W16(0x0080), + W16(0x000D), W16(0xFFE0), W16(0x005B), W16(0xFFFC), W16(0x0006), W16(0xFFEA), W16(0x001F), W16(0x00A3), + W16(0x00C5), W16(0x00A1), W16(0x00B4), W16(0x006A), W16(0xFFFF), W16(0xFFB6), W16(0xFF4C), W16(0xFEFA), + W16(0xFECE), W16(0xFEDC), W16(0xFF33), W16(0xFF14), W16(0xFF40), W16(0xFF57), W16(0xFF4B), W16(0xFF76), + W16(0xFE80), W16(0xFFD5), W16(0x0044), W16(0x0041), W16(0x0053), W16(0x001C), W16(0x0021), W16(0xFFF9), + W16(0x000C), W16(0xFFEE), W16(0xFFEB), W16(0x001A), W16(0x0020), W16(0xFFEE), W16(0xFFE3), W16(0xFFD5), + W16(0xFFB2), W16(0xFFB4), W16(0xFFAD), W16(0xFFB6), W16(0xFF93), W16(0xFF95), W16(0xFFA8), W16(0xFFB7), + W16(0xFF19), W16(0xFEF4), W16(0xFEC3), W16(0xFEBE), W16(0xFF0D), W16(0xFF3D), W16(0xFF49), W16(0xFF58), + W16(0xFF69), W16(0xFFA0), W16(0x0011), W16(0x0086), W16(0x0065), W16(0x00AB), W16(0x00BE), W16(0x00F6), + W16(0x00B1), W16(0x00C3), W16(0x00C5), W16(0x0089), W16(0x0043), W16(0x0072), W16(0x0060), W16(0x003E), + W16(0xFF96), W16(0xFF5F), W16(0xFFE1), W16(0xFF92), W16(0xFF57), W16(0xFF7E), W16(0xFFDA), W16(0x0008), + W16(0x00B5), W16(0x0092), W16(0x008C), W16(0x0054), W16(0x0055), W16(0x001D), W16(0xFFC1), W16(0xFF8C), + W16(0xFF63), W16(0xFF6F), W16(0xFFAD), W16(0xFFD6), W16(0xFFEE), W16(0x002A), W16(0x0067), W16(0x009F), + W16(0x0004), W16(0xFFCC), W16(0x0081), W16(0x0020), W16(0x001C), W16(0x005E), W16(0x000E), W16(0x0018), + W16(0xFFEF), W16(0xFFF6), W16(0xFFF2), W16(0xFFEB), W16(0x000F), W16(0xFFEB), W16(0xFFDE), W16(0xFFE6), + W16(0xFFE0), W16(0xFFE4), W16(0xFFE4), W16(0xFFD6), W16(0xFFD6), W16(0xFFD9), W16(0xFFED), W16(0x0007), + W16(0xFFC3), W16(0xFFB7), W16(0xFF6C), W16(0xFFF4), W16(0x0172), W16(0xFFED), W16(0xFF8F), W16(0x021C), + W16(0x00B3), W16(0xFF40), W16(0xFFC8), W16(0xFF96), W16(0xFFD8), W16(0xFF89), W16(0xFF9E), W16(0xFF4E), + W16(0xFF5A), W16(0xFFEC), W16(0x0022), W16(0x0023), W16(0x000D), W16(0x0023), W16(0x000D), W16(0xFFF1), + W16(0xFF96), W16(0x00A1), W16(0x012A), W16(0x0086), W16(0x005C), W16(0x004A), W16(0x0082), W16(0x0000), + W16(0x0052), W16(0x0017), W16(0xFFDD), W16(0xFFD8), W16(0xFFD2), W16(0xFFB4), W16(0xFFA4), W16(0xFFD0), + W16(0xFFC1), W16(0xFFE3), W16(0x001D), W16(0x004F), W16(0x0093), W16(0x00BA), W16(0x00DE), W16(0x00E2), + W16(0x01E5), W16(0x005B), W16(0x0048), W16(0x004D), W16(0x0075), W16(0x0093), W16(0x0050), W16(0x0020), + W16(0x0007), W16(0xFFEE), W16(0xFFE9), W16(0xFFED), W16(0xFFEA), W16(0xFFE8), W16(0xFFC2), W16(0xFF9C), + W16(0xFF8E), W16(0xFF89), W16(0xFF8A), W16(0xFF8B), W16(0xFFA4), W16(0xFFBB), W16(0xFFD3), W16(0xFFF3), + W16(0x00F1), W16(0x009F), W16(0xFF81), W16(0xFFA5), W16(0xFF99), W16(0xFF36), W16(0xFF3B), W16(0xFFA2), + W16(0xFFF9), W16(0x0065), W16(0x005E), W16(0x004D), W16(0x0073), W16(0x0023), W16(0x0047), W16(0x0036), + W16(0x0038), W16(0x0018), W16(0xFFD0), W16(0xFFD4), W16(0xFFC4), W16(0xFFBA), W16(0xFFC4), W16(0xFFBE), + W16(0xFFC3), W16(0x0081), W16(0x005E), W16(0x0044), W16(0xFFFE), W16(0x0004), W16(0x0034), W16(0x0057), + W16(0x005A), W16(0x004B), W16(0x001C), W16(0x0002), W16(0xFFE5), W16(0xFFBE), W16(0xFFA9), W16(0xFFBC), + W16(0xFFAA), W16(0xFFA6), W16(0xFFAD), W16(0xFFA9), W16(0xFFA6), W16(0xFF9A), W16(0xFFAE), W16(0xFFC2), + W16(0x00A3), W16(0x007B), W16(0x0032), W16(0x005C), W16(0x0084), W16(0x001C), W16(0xFFAC), W16(0xFF34), + W16(0xFF86), W16(0xFFC6), W16(0x0020), W16(0x0074), W16(0x0079), W16(0x000F), W16(0xFFEC), W16(0x0014), + W16(0x001A), W16(0x0009), W16(0x0015), W16(0x0077), W16(0x00C2), W16(0x0100), W16(0x011E), W16(0x016A), + W16(0xFFBA), W16(0x0029), W16(0x0017), W16(0xFFE0), W16(0x0015), W16(0x001F), W16(0xFFF4), W16(0xFFB0), + W16(0xFFD2), W16(0xFFBB), W16(0xFFEA), W16(0x0007), W16(0x002A), W16(0x0026), W16(0x0033), W16(0x001C), + W16(0x000B), W16(0x0018), W16(0x0029), W16(0x0034), W16(0x004C), W16(0x0079), W16(0x0090), W16(0x00AC), + W16(0xFFF1), W16(0xFFCA), W16(0x0002), W16(0x0052), W16(0xFFBE), W16(0xFF5B), W16(0xFFDD), W16(0xFFEC), + W16(0xFFDD), W16(0xFFF5), W16(0x003C), W16(0x0050), W16(0x003D), W16(0x0016), W16(0x0027), W16(0x002C), + W16(0x0019), W16(0x0017), W16(0x001F), W16(0x0030), W16(0x0021), W16(0x002C), W16(0x0020), W16(0x002B), + W16(0x000E), W16(0x0099), W16(0x0075), W16(0x0097), W16(0x009F), W16(0x007B), W16(0x003E), W16(0xFFF5), + W16(0xFF9F), W16(0xFFB1), W16(0xFFF0), W16(0xFFF9), W16(0x000F), W16(0x000A), W16(0xFFF9), W16(0xFFC0), + W16(0xFFA6), W16(0xFF93), W16(0xFF97), W16(0xFF93), W16(0xFF9E), W16(0xFFAC), W16(0xFFC2), W16(0xFFEC), + W16(0x002D), W16(0xFF24), W16(0xFEC4), W16(0x0070), W16(0xFF17), W16(0x0191), W16(0x00DD), W16(0xFFF4), + W16(0xFDFE), W16(0x00C4), W16(0xFF19), W16(0x0031), W16(0xFFB2), W16(0xFFED), W16(0xFF78), W16(0x0076), + W16(0x00EC), W16(0x00E1), W16(0x007F), W16(0x005A), W16(0x00C6), W16(0x0028), W16(0x00F2), W16(0x01B2), + W16(0x0127), W16(0x0076), W16(0x007F), W16(0x007A), W16(0x0041), W16(0x0078), W16(0x003E), W16(0xFFF5), + W16(0xFFB0), W16(0xFF89), W16(0xFFA4), W16(0xFFBC), W16(0xFFF0), W16(0x000C), W16(0x003C), W16(0x001E), + W16(0x0024), W16(0x003B), W16(0x004F), W16(0x007B), W16(0x0090), W16(0x00AB), W16(0x00B5), W16(0x00C7), + W16(0x00B0), W16(0x007D), W16(0x0076), W16(0x0068), W16(0x0056), W16(0x0050), W16(0xFFE6), W16(0x0004), + W16(0x0038), W16(0x0040), W16(0x001E), W16(0x002C), W16(0x0022), W16(0xFFC9), W16(0xFFAA), W16(0xFF9B), + W16(0xFF7D), W16(0xFF7A), W16(0xFF95), W16(0xFFCF), W16(0x0002), W16(0x0046), W16(0x00A9), W16(0x00F5), + W16(0xFF44), W16(0xFFB4), W16(0xFFDB), W16(0xFFD9), W16(0xFF9D), W16(0xFF8B), W16(0xFF71), W16(0xFF5E), + W16(0xFF8E), W16(0xFF94), W16(0xFFA9), W16(0xFFF0), W16(0x006F), W16(0x007A), W16(0x00AA), W16(0x00C5), + W16(0x00F6), W16(0x0145), W16(0x015F), W16(0x013D), W16(0x0111), W16(0x00FF), W16(0x00DC), W16(0x00C7), + W16(0xFEE8), W16(0xFEFE), W16(0xFEDE), W16(0xFF0B), W16(0xFE87), W16(0xFED9), W16(0xFEB8), W16(0xFEF7), + W16(0x0069), W16(0x0072), W16(0x00AE), W16(0x009A), W16(0x00B6), W16(0x004F), W16(0xFF68), W16(0x0035), + W16(0x022C), W16(0x0238), W16(0x020A), W16(0x0284), W16(0x01BA), W16(0xFFD5), W16(0x003F), W16(0xFF8E), + W16(0x00D0), W16(0x000F), W16(0xFFCE), W16(0xFF88), W16(0x0015), W16(0xFFFE), W16(0x003F), W16(0x001A), + W16(0x0023), W16(0x0019), W16(0x0029), W16(0xFFF1), W16(0xFFE7), W16(0xFFDC), W16(0xFFBF), W16(0xFFE4), + W16(0xFFD7), W16(0xFFDF), W16(0x000D), W16(0x0051), W16(0x0090), W16(0x00C6), W16(0x010D), W16(0x0138), + W16(0x00E7), W16(0x00AC), W16(0x0057), W16(0x0021), W16(0x0008), W16(0xFFE6), W16(0xFFE0), W16(0x0021), + W16(0x002C), W16(0xFFE0), W16(0xFFFC), W16(0x0001), W16(0x000F), W16(0xFFE8), W16(0xFFFD), W16(0x0006), + W16(0x000E), W16(0x000F), W16(0x0021), W16(0x001A), W16(0x0013), W16(0x0006), W16(0x0021), W16(0x0044), + W16(0x013C), W16(0x0128), W16(0x00CA), W16(0xFFFD), W16(0xFFC0), W16(0xFFA0), W16(0x0013), W16(0x0077), + W16(0x00E3), W16(0x00B9), W16(0x0066), W16(0xFFF7), W16(0xFFD2), W16(0xFFE0), W16(0xFF99), W16(0xFF5A), + W16(0xFF78), W16(0xFF7A), W16(0xFF80), W16(0xFF73), W16(0xFF90), W16(0xFF88), W16(0xFF86), W16(0xFF8B), + W16(0x0038), W16(0x006D), W16(0x004E), W16(0x0015), W16(0xFFF6), W16(0xFFF0), W16(0x0004), W16(0x000A), + W16(0x000E), W16(0xFFEE), W16(0xFFE1), W16(0xFFF1), W16(0xFFE5), W16(0xFFEE), W16(0xFFFA), W16(0x001B), + W16(0x0056), W16(0x00A5), W16(0x00D9), W16(0x0103), W16(0x0104), W16(0x0118), W16(0x012A), W16(0x0111), + W16(0x0299), W16(0x000F), W16(0xFFE1), W16(0xFFCC), W16(0xFFC8), W16(0xFFC3), W16(0xFFF5), W16(0xFFDB), + W16(0x0000), W16(0x0006), W16(0x0029), W16(0x001B), W16(0x001F), W16(0xFFF5), W16(0x0011), W16(0x0011), + W16(0x0023), W16(0x002A), W16(0x003B), W16(0x0046), W16(0x004F), W16(0x0049), W16(0x0058), W16(0x0053), + W16(0x004B), W16(0x0043), W16(0x0088), W16(0x00CD), W16(0x0037), W16(0xFE8A), W16(0xFEB7), W16(0xFF69), + W16(0x0019), W16(0x0084), W16(0x0058), W16(0xFFF1), W16(0xFF76), W16(0x00C5), W16(0x016A), W16(0x0028), + W16(0x006B), W16(0x004E), W16(0x001C), W16(0xFFD0), W16(0x0032), W16(0xFFB9), W16(0xFF95), W16(0xFFC6), + W16(0xFF8D), W16(0x005A), W16(0x00CB), W16(0x0100), W16(0x0056), W16(0xFFD6), W16(0x001A), W16(0xFFC6), + W16(0xFFBE), W16(0xFFE8), W16(0xFFEF), W16(0x0009), W16(0xFFF5), W16(0xFFDD), W16(0xFFF6), W16(0x003D), + W16(0x0053), W16(0x00B0), W16(0x00D2), W16(0x0092), W16(0x0050), W16(0x0023), W16(0x0014), W16(0xFFFB), + W16(0x0119), W16(0x0057), W16(0x0013), W16(0x0009), W16(0xFFF2), W16(0xFFBD), W16(0xFF9C), W16(0xFF9F), + W16(0xFFB8), W16(0xFFB1), W16(0xFFE9), W16(0xFFDE), W16(0xFFFC), W16(0x0036), W16(0x007D), W16(0x0096), + W16(0x00A1), W16(0x00CB), W16(0x00FC), W16(0x011C), W16(0x00A5), W16(0x003F), W16(0x0010), W16(0xFFE0), + W16(0x007C), W16(0x00BA), W16(0x0029), W16(0xFF86), W16(0xFF34), W16(0xFFD2), W16(0xFFB7), W16(0xFFE5), + W16(0x0033), W16(0x0041), W16(0x0035), W16(0xFFFB), W16(0x0037), W16(0x0040), W16(0x000B), W16(0x000C), + W16(0x0029), W16(0x0038), W16(0x006F), W16(0x00B3), W16(0x00C6), W16(0x00C4), W16(0x00BB), W16(0x009C), + W16(0x00E5), W16(0x00CF), W16(0x0125), W16(0x00BA), W16(0xFFFD), W16(0x0010), W16(0x0007), W16(0xFFA1), + W16(0xFFFB), W16(0xFFFE), W16(0x0005), W16(0x000E), W16(0x0004), W16(0xFFDE), W16(0x0026), W16(0x0020), + W16(0x0017), W16(0xFFE3), W16(0xFFA9), W16(0xFF84), W16(0xFF5A), W16(0xFF1B), W16(0xFEAE), W16(0xFE61), + W16(0xFD6E), W16(0x012D), W16(0x014A), W16(0x01A9), W16(0x02D2), W16(0x02CA), W16(0x01CC), W16(0xFF5B), + W16(0xFF28), W16(0xFEF0), W16(0xFE82), W16(0xFDF4), W16(0xFDFF), W16(0xFFE2), W16(0x00A4), W16(0x0063), + W16(0xFFC7), W16(0xFF44), W16(0xFEE8), W16(0xFEBA), W16(0xFE4F), W16(0xFF09), W16(0xFE6C), W16(0xFDBE), + W16(0xFFD3), W16(0x0007), W16(0x00A0), W16(0x0043), W16(0x0035), W16(0x0060), W16(0x007A), W16(0x0039), + W16(0xFFD4), W16(0xFFEE), W16(0xFFB3), W16(0xFFAD), W16(0xFFE3), W16(0x008D), W16(0x0055), W16(0xFF7B), + W16(0xFF56), W16(0x0096), W16(0x011B), W16(0x00F3), W16(0x009A), W16(0x006B), W16(0xFFBC), W16(0xFEEB), + W16(0x0298), W16(0x01D9), W16(0x0134), W16(0x0082), W16(0x0005), W16(0x002A), W16(0xFFE3), W16(0xFFB3), + W16(0xFFCA), W16(0xFFF4), W16(0x0019), W16(0x0036), W16(0x0023), W16(0x0010), W16(0x0011), W16(0xFFF2), + W16(0xFFF7), W16(0xFFF5), W16(0xFFFF), W16(0x0001), W16(0x0022), W16(0x003E), W16(0x0047), W16(0x0037) +}; + +const Word16 cdk_37bits_3_fx[1536] = +{ + W16(0xFFCD), W16(0xFFFB), W16(0xFFC7), W16(0x0024), W16(0x0000), W16(0xFFAB), W16(0x014C), W16(0xFF9A), + W16(0xFFF0), W16(0xFFF1), W16(0x0002), W16(0x0015), W16(0xFFF3), W16(0xFFDC), W16(0xFFD2), W16(0x000F), + W16(0xFFC6), W16(0xFFF3), W16(0xFFF1), W16(0x0032), W16(0x006F), W16(0x0054), W16(0x008F), W16(0x009B), + W16(0x001C), W16(0x0006), W16(0xFFFE), W16(0xFFF3), W16(0xFFDF), W16(0xFF49), W16(0xFFB0), W16(0xFFC8), + W16(0xFFFB), W16(0xFFC2), W16(0xFFE5), W16(0xFFBF), W16(0xFFFC), W16(0x00B0), W16(0x0129), W16(0x0079), + W16(0xFFB2), W16(0xFF40), W16(0xFF97), W16(0xFF9B), W16(0xFFCB), W16(0xFFB6), W16(0xFFB4), W16(0xFFBD), + W16(0xFEFA), W16(0xFFA2), W16(0xFF63), W16(0xFFB2), W16(0xFFAB), W16(0xFFAF), W16(0x000F), W16(0x0024), + W16(0x0003), W16(0xFFD1), W16(0xFFF4), W16(0xFFB4), W16(0xFFFC), W16(0x001D), W16(0x0041), W16(0x0066), + W16(0x0039), W16(0xFFE5), W16(0xFFE3), W16(0x000D), W16(0x003B), W16(0x0076), W16(0x0069), W16(0x0044), + W16(0xFF95), W16(0xFF75), W16(0xFF97), W16(0xFFE8), W16(0x0022), W16(0xFFBB), W16(0x0009), W16(0x0049), + W16(0x0046), W16(0x0004), W16(0xFFFA), W16(0x0010), W16(0x001C), W16(0xFFDB), W16(0xFFE9), W16(0xFFCA), + W16(0xFFD3), W16(0xFFAE), W16(0xFFAC), W16(0xFFA9), W16(0xFF8C), W16(0xFF7B), W16(0xFF71), W16(0xFF78), + W16(0x002E), W16(0xFF90), W16(0xFF94), W16(0xFFA4), W16(0xFFAF), W16(0xFFEF), W16(0x0000), W16(0x0076), + W16(0x001E), W16(0x0031), W16(0x0044), W16(0x0081), W16(0xFFFE), W16(0xFFA3), W16(0xFF90), W16(0xFFB4), + W16(0xFFF2), W16(0x0053), W16(0x011E), W16(0x0107), W16(0xFF79), W16(0xFFBB), W16(0xFF82), W16(0xFED6), + W16(0xFFD0), W16(0x004A), W16(0x002F), W16(0xFF34), W16(0xFF4E), W16(0x0016), W16(0x0007), W16(0x0047), + W16(0x004D), W16(0x0025), W16(0x000F), W16(0x0018), W16(0xFFF9), W16(0xFFF9), W16(0xFFDC), W16(0xFFE9), + W16(0xFFFF), W16(0xFFCE), W16(0xFFB7), W16(0xFFB8), W16(0xFFB0), W16(0xFFB4), W16(0xFFB1), W16(0xFF9A), + W16(0x006B), W16(0xFFDD), W16(0x0002), W16(0xFFE4), W16(0xFFE1), W16(0xFFE2), W16(0xFFD5), W16(0xFFC3), + W16(0xFFEC), W16(0xFFE6), W16(0x000D), W16(0xFFD7), W16(0xFF99), W16(0xFFBD), W16(0x0001), W16(0x00C4), + W16(0x00D3), W16(0xFF57), W16(0xFF8A), W16(0xFF78), W16(0xFFF6), W16(0xFFEA), W16(0xFFDC), W16(0xFFDC), + W16(0xFFD2), W16(0x001D), W16(0x0017), W16(0x0004), W16(0xFFF0), W16(0x0014), W16(0xFFF6), W16(0xFF21), + W16(0x0020), W16(0x0041), W16(0x0030), W16(0x000C), W16(0xFFCA), W16(0xFFFF), W16(0x0037), W16(0x003D), + W16(0x000A), W16(0xFFEA), W16(0xFFE0), W16(0xFFCC), W16(0xFFD4), W16(0xFFC0), W16(0xFFD0), W16(0xFFCD), + W16(0xFF6A), W16(0xFFEF), W16(0xFFFF), W16(0x002C), W16(0xFFC8), W16(0x0077), W16(0x0059), W16(0x000B), + W16(0xFFF5), W16(0xFFFA), W16(0xFFF6), W16(0xFFF1), W16(0xFFDD), W16(0xFFCF), W16(0xFFEA), W16(0xFFF1), + W16(0x0000), W16(0xFFF9), W16(0xFFE4), W16(0xFFB7), W16(0xFF96), W16(0xFF61), W16(0xFF43), W16(0xFF3C), + W16(0xFFE4), W16(0xFFE7), W16(0xFFA0), W16(0xFFA4), W16(0x003D), W16(0x00B1), W16(0x0085), W16(0xFFFC), + W16(0xFF91), W16(0xFFCD), W16(0x0002), W16(0x0011), W16(0xFFF4), W16(0x002A), W16(0xFFE1), W16(0xFF92), + W16(0xFF8F), W16(0xFF82), W16(0xFF9A), W16(0xFFB1), W16(0xFFBE), W16(0xFFEA), W16(0x0011), W16(0x002A), + W16(0xFFAC), W16(0xFFD1), W16(0xFFC2), W16(0xFF84), W16(0xFFCF), W16(0xFFFD), W16(0xFFB5), W16(0xFFA4), + W16(0xFFE6), W16(0xFFD3), W16(0x001E), W16(0x0061), W16(0x0062), W16(0xFFFA), W16(0x0023), W16(0x0016), + W16(0x000D), W16(0x000E), W16(0x000E), W16(0x0003), W16(0x0009), W16(0x0015), W16(0x000A), W16(0x0002), + W16(0xFFB7), W16(0xFFD9), W16(0xFFE4), W16(0xFFBB), W16(0x00F9), W16(0xFFCC), W16(0xFFC6), W16(0xFFA8), + W16(0x0026), W16(0x0005), W16(0x0014), W16(0x0039), W16(0x0040), W16(0xFFE4), W16(0xFF68), W16(0xFF9A), + W16(0x002F), W16(0x0058), W16(0xFFB2), W16(0x001C), W16(0xFFCC), W16(0xFF92), W16(0xFF7D), W16(0xFF60), + W16(0xFFB4), W16(0xFFA5), W16(0xFFEC), W16(0xFFF2), W16(0xFFDD), W16(0xFFF6), W16(0x0033), W16(0x00A0), + W16(0x0097), W16(0x0028), W16(0xFFB8), W16(0xFF58), W16(0xFFA8), W16(0x0024), W16(0xFFE4), W16(0xFFE0), + W16(0xFFFB), W16(0xFFEB), W16(0xFFE2), W16(0xFFD9), W16(0xFFFC), W16(0xFFF7), W16(0x000F), W16(0x0004), + W16(0x0053), W16(0x0020), W16(0x004C), W16(0xFFFC), W16(0x003C), W16(0x0052), W16(0x0027), W16(0x000E), + W16(0x0050), W16(0x0024), W16(0x001C), W16(0xFFE9), W16(0xFFDE), W16(0xFFDB), W16(0xFFBA), W16(0xFFB3), + W16(0xFF9E), W16(0xFFAD), W16(0xFFA2), W16(0xFFA3), W16(0xFFB2), W16(0xFFAA), W16(0xFFB4), W16(0xFFBC), + W16(0xFFF7), W16(0xFFF0), W16(0xFFE4), W16(0x000B), W16(0xFFDE), W16(0xFFE3), W16(0x0024), W16(0xFFB4), + W16(0x0062), W16(0x0045), W16(0xFFCB), W16(0xFFB0), W16(0x00DD), W16(0x006B), W16(0xFF74), W16(0xFF89), + W16(0x0001), W16(0xFFBB), W16(0xFFCD), W16(0xFF9D), W16(0xFF92), W16(0xFF76), W16(0xFF9F), W16(0xFFCF), + W16(0xFF91), W16(0xFF37), W16(0xFFB4), W16(0x00BC), W16(0x004A), W16(0xFFB2), W16(0x001B), W16(0xFF97), + W16(0xFF7D), W16(0x0039), W16(0x003C), W16(0xFFE1), W16(0x0007), W16(0xFFEF), W16(0x0045), W16(0x0031), + W16(0x0014), W16(0x0069), W16(0x005C), W16(0xFFF5), W16(0xFFE8), W16(0xFFD8), W16(0xFFA5), W16(0xFFCB), + W16(0x0024), W16(0x000A), W16(0xFEB4), W16(0x0002), W16(0x0003), W16(0xFFCA), W16(0x002D), W16(0xFFE3), + W16(0xFFF5), W16(0xFFE2), W16(0xFFFE), W16(0x000E), W16(0x0008), W16(0x000F), W16(0x0019), W16(0x0032), + W16(0xFFDD), W16(0xFFFB), W16(0xFFCE), W16(0xFFBA), W16(0xFFC9), W16(0xFFDE), W16(0x000E), W16(0x003D), + W16(0xFFC6), W16(0xFFDD), W16(0xFFA6), W16(0xFFB3), W16(0x0105), W16(0xFFDA), W16(0xFFD0), W16(0xFFCD), + W16(0x0000), W16(0xFFB9), W16(0x0018), W16(0xFF8C), W16(0xFFF1), W16(0xFFD9), W16(0x0030), W16(0x002F), + W16(0xFFFF), W16(0xFFF1), W16(0xFFF6), W16(0x0000), W16(0xFFFC), W16(0x0017), W16(0x003C), W16(0x004E), + W16(0xFED7), W16(0x0028), W16(0x0038), W16(0x0015), W16(0x0006), W16(0xFFF7), W16(0xFFF2), W16(0xFFEC), + W16(0xFFD4), W16(0xFFCF), W16(0xFFE3), W16(0x0024), W16(0x0022), W16(0x000D), W16(0x0027), W16(0x0014), + W16(0x0010), W16(0x0015), W16(0x0028), W16(0x001C), W16(0x0007), W16(0xFFD2), W16(0xFFBD), W16(0xFF93), + W16(0x0068), W16(0xFF90), W16(0x002E), W16(0x007D), W16(0x001B), W16(0x004E), W16(0x000D), W16(0x006E), + W16(0x0039), W16(0xFFF7), W16(0xFF97), W16(0x0018), W16(0xFFF1), W16(0xFFC5), W16(0xFF94), W16(0xFFDB), + W16(0x0018), W16(0x0003), W16(0x001A), W16(0xFFE9), W16(0xFFBC), W16(0xFF9E), W16(0xFF96), W16(0xFF88), + W16(0xFFB0), W16(0xFF7C), W16(0xFF95), W16(0x002C), W16(0xFF96), W16(0xFFB9), W16(0x005F), W16(0x0042), + W16(0xFFEA), W16(0xFFBE), W16(0xFFDC), W16(0x0030), W16(0x00AB), W16(0x006D), W16(0xFFC0), W16(0xFFA5), + W16(0xFFE0), W16(0x0098), W16(0x007B), W16(0x0017), W16(0x0040), W16(0x0079), W16(0x005B), W16(0x002E), + W16(0x0021), W16(0x001A), W16(0x0055), W16(0xFFCE), W16(0xFF7A), W16(0x0058), W16(0x001F), W16(0xFFC7), + W16(0xFFCA), W16(0x002E), W16(0x001E), W16(0x0020), W16(0x0004), W16(0x0014), W16(0x000C), W16(0xFFF8), + W16(0xFFF7), W16(0xFFE0), W16(0xFFCF), W16(0xFFEF), W16(0x00B1), W16(0x00C8), W16(0xFF9A), W16(0xFF27), + W16(0x000D), W16(0x0039), W16(0x0036), W16(0x0009), W16(0xFFC7), W16(0xFFBB), W16(0xFFE9), W16(0x0019), + W16(0x0004), W16(0x000D), W16(0x0007), W16(0xFFF6), W16(0xFFF1), W16(0x0018), W16(0x0013), W16(0x003A), + W16(0x0017), W16(0xFFAF), W16(0xFF5F), W16(0xFF23), W16(0xFF3C), W16(0xFF6D), W16(0xFFB3), W16(0x0035), + W16(0xFFAC), W16(0x0041), W16(0xFFE3), W16(0x0054), W16(0xFFCB), W16(0x003E), W16(0xFFFE), W16(0x000E), + W16(0x003A), W16(0x003C), W16(0x0018), W16(0xFFDF), W16(0xFFFB), W16(0x0012), W16(0xFFE9), W16(0xFFC7), + W16(0xFFC1), W16(0xFFE2), W16(0xFFFF), W16(0x0009), W16(0x001F), W16(0x0018), W16(0x0015), W16(0x0009), + W16(0xFFEA), W16(0xFFBD), W16(0xFFEC), W16(0xFFD1), W16(0xFFF5), W16(0x0036), W16(0x005A), W16(0x002D), + W16(0xFFD8), W16(0xFF85), W16(0xFF4D), W16(0xFFA3), W16(0xFFE4), W16(0x0015), W16(0x0097), W16(0x0050), + W16(0x0021), W16(0xFFDA), W16(0xFFB6), W16(0x003A), W16(0xFFF8), W16(0xFFD2), W16(0xFFD6), W16(0xFFD8), + W16(0x0084), W16(0xFF0B), W16(0xFFEF), W16(0xFFD7), W16(0xFFCF), W16(0x0001), W16(0xFFE0), W16(0xFFFE), + W16(0x001C), W16(0x0020), W16(0x0018), W16(0x0005), W16(0xFFF3), W16(0x0009), W16(0xFFFF), W16(0x0007), + W16(0xFFF8), W16(0xFFF2), W16(0xFFF3), W16(0x0001), W16(0x0008), W16(0x000A), W16(0x0014), W16(0x000E), + W16(0xFFD6), W16(0xFFB8), W16(0xFFC6), W16(0xFFF9), W16(0x0008), W16(0xFFFD), W16(0xFFE6), W16(0x0048), + W16(0xFF6D), W16(0x005B), W16(0x0013), W16(0x002F), W16(0xFFD8), W16(0x0003), W16(0x0002), W16(0xFFF8), + W16(0xFFEE), W16(0x0008), W16(0xFFFB), W16(0xFFF6), W16(0xFFFC), W16(0xFFFF), W16(0x0002), W16(0x0002), + W16(0x0059), W16(0x006C), W16(0xFFE7), W16(0x004C), W16(0x0074), W16(0x0086), W16(0x0037), W16(0xFFA6), + W16(0xFFD0), W16(0xFFD6), W16(0xFFC0), W16(0xFFCD), W16(0xFFC3), W16(0xFFD8), W16(0xFFFE), W16(0x0026), + W16(0x0037), W16(0x0027), W16(0x0003), W16(0xFFE9), W16(0xFFC5), W16(0xFFB8), W16(0xFFCD), W16(0xFFCF), + W16(0x0005), W16(0x0037), W16(0x001E), W16(0xFFFC), W16(0x0022), W16(0x0034), W16(0xFF0F), W16(0x002B), + W16(0x0037), W16(0x002D), W16(0x0013), W16(0x0021), W16(0x000C), W16(0x0003), W16(0x000D), W16(0xFFEE), + W16(0xFFCF), W16(0xFFE6), W16(0xFFF6), W16(0xFFEC), W16(0xFFDB), W16(0xFFDB), W16(0xFFDC), W16(0xFFCF), + W16(0xFF53), W16(0x0078), W16(0x00C4), W16(0xFFC3), W16(0x0051), W16(0x0005), W16(0x0002), W16(0x0022), + W16(0x001C), W16(0x0028), W16(0xFFF9), W16(0xFFE4), W16(0xFFF7), W16(0xFFE5), W16(0xFFC9), W16(0xFFE1), + W16(0xFFDF), W16(0xFFE1), W16(0xFFE8), W16(0x0007), W16(0x003C), W16(0x005F), W16(0x0083), W16(0x0089), + W16(0x00EB), W16(0x0009), W16(0xFFB7), W16(0xFF7B), W16(0xFFD0), W16(0x0024), W16(0xFFC8), W16(0xFFBD), + W16(0xFFDF), W16(0xFFE4), W16(0xFFF5), W16(0x002E), W16(0x0023), W16(0x001D), W16(0x002C), W16(0x001B), + W16(0x001A), W16(0xFFF8), W16(0xFFEA), W16(0xFFD5), W16(0xFFE9), W16(0xFFD1), W16(0xFFC9), W16(0xFFC1), + W16(0xFFE3), W16(0xFFB1), W16(0x0009), W16(0x0096), W16(0x0111), W16(0x00E2), W16(0xFFEA), W16(0xFFBB), + W16(0x000E), W16(0xFFF0), W16(0xFFBC), W16(0xFFF9), W16(0xFFC7), W16(0xFF9E), W16(0xFFA3), W16(0xFFBD), + W16(0xFFEE), W16(0x001E), W16(0x0002), W16(0x0020), W16(0x0032), W16(0x0051), W16(0x0052), W16(0x0062), + W16(0x0032), W16(0x0041), W16(0xFFE4), W16(0xFF9B), W16(0x001C), W16(0xFF48), W16(0x0000), W16(0x002F), + W16(0x0015), W16(0x0014), W16(0x003D), W16(0x0026), W16(0xFFF1), W16(0x0015), W16(0xFFF1), W16(0xFFF9), + W16(0xFFF0), W16(0xFFF4), W16(0xFFED), W16(0xFFFA), W16(0x000D), W16(0x001C), W16(0x002B), W16(0x0023), + W16(0xFFEB), W16(0xFFCF), W16(0x0049), W16(0x0037), W16(0x0039), W16(0xFFBA), W16(0xFFF9), W16(0xFFFD), + W16(0x0045), W16(0x0021), W16(0xFF72), W16(0x0033), W16(0x0010), W16(0x0017), W16(0xFFF6), W16(0x0002), + W16(0xFFEC), W16(0xFFDB), W16(0xFFD4), W16(0xFFC8), W16(0xFFE3), W16(0xFFF4), W16(0x0015), W16(0x0019), + W16(0xFFAC), W16(0xFFB9), W16(0x000E), W16(0xFFA3), W16(0xFF88), W16(0xFFB0), W16(0xFFF1), W16(0xFFEA), + W16(0xFFED), W16(0xFFD8), W16(0x0009), W16(0x0004), W16(0xFFEF), W16(0x002C), W16(0x0051), W16(0x004E), + W16(0x0062), W16(0x0074), W16(0x0075), W16(0x0055), W16(0x0027), W16(0x000F), W16(0xFFF2), W16(0xFFDA), + W16(0xFF96), W16(0xFFB4), W16(0x0033), W16(0x001C), W16(0xFF5C), W16(0xFFC5), W16(0xFFC8), W16(0xFFD7), + W16(0x000D), W16(0x0059), W16(0x0077), W16(0x006A), W16(0x002C), W16(0x002D), W16(0x0003), W16(0xFFD2), + W16(0xFFCD), W16(0xFFD8), W16(0xFFD0), W16(0xFFED), W16(0xFFEA), W16(0xFFE8), W16(0xFFF9), W16(0xFFF6), + W16(0x0052), W16(0xFFD4), W16(0xFF5B), W16(0xFF8B), W16(0xFFA9), W16(0x003F), W16(0x007C), W16(0x0028), + W16(0x001B), W16(0x0010), W16(0xFFD1), W16(0xFFCD), W16(0x0004), W16(0xFFCA), W16(0xFFEE), W16(0xFFE7), + W16(0x0008), W16(0x0047), W16(0x0086), W16(0x0087), W16(0x0064), W16(0x0024), W16(0x000C), W16(0xFFD7), + W16(0x00A6), W16(0x008E), W16(0x0077), W16(0xFFD8), W16(0xFF6A), W16(0x003A), W16(0x003B), W16(0x0017), + W16(0x0028), W16(0x0010), W16(0xFFFA), W16(0xFFDE), W16(0xFFFC), W16(0xFFEC), W16(0xFFE0), W16(0x000B), + W16(0x0026), W16(0x003C), W16(0x003F), W16(0x003E), W16(0x0049), W16(0x006F), W16(0x0080), W16(0x0080), + W16(0xFFB8), W16(0xFFC2), W16(0xFFBE), W16(0x0017), W16(0xFFF9), W16(0xFFF0), W16(0xFFE0), W16(0xFFE4), + W16(0x0027), W16(0x0000), W16(0xFFE9), W16(0x00A2), W16(0x002E), W16(0xFF66), W16(0xFF4F), W16(0x0042), + W16(0x007C), W16(0xFFE4), W16(0xFFF6), W16(0x000A), W16(0x0039), W16(0x0054), W16(0x0054), W16(0x0033), + W16(0xFFD9), W16(0x0003), W16(0x0012), W16(0x0010), W16(0x000B), W16(0x0000), W16(0xFF97), W16(0xFF97), + W16(0xFFC8), W16(0x00AF), W16(0x0215), W16(0xFF25), W16(0xFFD7), W16(0xFFF1), W16(0xFF98), W16(0xFFC3), + W16(0xFFF2), W16(0x0005), W16(0xFFDA), W16(0x0052), W16(0x0069), W16(0x0051), W16(0x008A), W16(0x00CA), + W16(0xFFAB), W16(0xFF9D), W16(0x00C3), W16(0x006D), W16(0x002D), W16(0x006D), W16(0x0064), W16(0x0037), + W16(0xFFBA), W16(0xFFA4), W16(0xFFB3), W16(0xFFF0), W16(0xFFFE), W16(0x0045), W16(0x0029), W16(0xFFD6), + W16(0xFF87), W16(0xFFCD), W16(0xFFFF), W16(0xFFCF), W16(0xFFFF), W16(0xFFE4), W16(0x0003), W16(0x0021), + W16(0x0066), W16(0xFF93), W16(0xFFAD), W16(0xFFFA), W16(0xFFC8), W16(0xFFA4), W16(0xFFD9), W16(0x0072), + W16(0x0007), W16(0x000D), W16(0x0011), W16(0x004A), W16(0x002A), W16(0x002B), W16(0x0002), W16(0xFFDF), + W16(0xFFA4), W16(0xFF6C), W16(0xFF66), W16(0xFF97), W16(0x0035), W16(0x0084), W16(0x00B6), W16(0x00EA), + W16(0x0017), W16(0xFFDC), W16(0x005C), W16(0x004A), W16(0xFFF1), W16(0x0038), W16(0xFFE1), W16(0xFF9F), + W16(0xFF3F), W16(0xFF63), W16(0xFFDE), W16(0x0092), W16(0x0082), W16(0x0053), W16(0x0033), W16(0x003F), + W16(0xFFFF), W16(0xFFEB), W16(0xFFD3), W16(0xFFC8), W16(0xFFC0), W16(0xFFD9), W16(0xFFBD), W16(0xFFA6), + W16(0xFFFE), W16(0x0006), W16(0x0045), W16(0xFF02), W16(0x0036), W16(0x008E), W16(0x000B), W16(0xFFE4), + W16(0x001C), W16(0xFFEF), W16(0xFFCF), W16(0xFFD5), W16(0xFFD3), W16(0xFFFA), W16(0xFFE6), W16(0xFFF1), + W16(0xFFFB), W16(0x001D), W16(0x0019), W16(0x001A), W16(0x002E), W16(0x0022), W16(0x0011), W16(0x0005), + W16(0x00D4), W16(0x0039), W16(0x0060), W16(0x0018), W16(0xFFC9), W16(0xFFB3), W16(0xFFDF), W16(0x0057), + W16(0x00B5), W16(0x007C), W16(0x001F), W16(0xFF64), W16(0xFF9B), W16(0xFFF1), W16(0x0011), W16(0xFFD2), + W16(0x002A), W16(0x0029), W16(0x001F), W16(0x0000), W16(0x002A), W16(0x0017), W16(0x0019), W16(0xFFEF), + W16(0x0082), W16(0x0064), W16(0x0002), W16(0x0057), W16(0x0006), W16(0x002D), W16(0x005F), W16(0x006D), + W16(0xFFF1), W16(0x0035), W16(0x0017), W16(0x001B), W16(0xFFB5), W16(0xFF99), W16(0xFFBE), W16(0xFFD3), + W16(0xFFCA), W16(0xFFD1), W16(0xFFDB), W16(0xFFE2), W16(0xFFF8), W16(0xFFF8), W16(0x000B), W16(0x0000), + W16(0x005A), W16(0x0064), W16(0x0024), W16(0x0001), W16(0xFFCF), W16(0xFFA4), W16(0xFF80), W16(0xFFA0), + W16(0xFFE3), W16(0xFFEF), W16(0xFFC4), W16(0x0006), W16(0x0022), W16(0x0093), W16(0x004D), W16(0x006A), + W16(0x0065), W16(0x0030), W16(0x001C), W16(0x001A), W16(0x0029), W16(0x004A), W16(0x0064), W16(0x0061), + W16(0xFFD8), W16(0xFF96), W16(0x000D), W16(0x008E), W16(0xFFDB), W16(0xFFB8), W16(0xFF8A), W16(0x0013), + W16(0x004D), W16(0x0032), W16(0x002E), W16(0xFFBB), W16(0xFFD1), W16(0xFFF1), W16(0x0062), W16(0x001F), + W16(0x0025), W16(0x003D), W16(0x0036), W16(0x0033), W16(0x0091), W16(0x008C), W16(0x0064), W16(0x0041), + W16(0x0053), W16(0x0030), W16(0xFF71), W16(0x005F), W16(0x0086), W16(0xFFCC), W16(0xFF97), W16(0xFFE9), + W16(0xFFF9), W16(0xFFAC), W16(0xFFD8), W16(0x0017), W16(0xFFF9), W16(0x001C), W16(0x000B), W16(0x001F), + W16(0x005A), W16(0x0052), W16(0x0036), W16(0xFFF3), W16(0xFFE2), W16(0xFFCE), W16(0xFFC4), W16(0xFFBA), + W16(0x0019), W16(0x0030), W16(0x0044), W16(0xFFD3), W16(0x000C), W16(0xFFF5), W16(0x0011), W16(0x0030), + W16(0x0029), W16(0xFF5C), W16(0x002B), W16(0x0012), W16(0x0008), W16(0x0004), W16(0x001F), W16(0xFFFA), + W16(0xFFD8), W16(0xFFE9), W16(0xFFE1), W16(0xFFE0), W16(0xFFF7), W16(0xFFF2), W16(0xFFF2), W16(0xFFDC), + W16(0xFFA8), W16(0x00AA), W16(0xFFE6), W16(0x0022), W16(0x000F), W16(0xFFE9), W16(0x0015), W16(0x0043), + W16(0x004C), W16(0xFFE2), W16(0xFFCE), W16(0xFFF5), W16(0xFFEB), W16(0xFFAC), W16(0xFFCE), W16(0x0016), + W16(0x0044), W16(0x005C), W16(0x003F), W16(0x0020), W16(0x0008), W16(0xFFF9), W16(0xFFF1), W16(0xFFE4), + W16(0x0033), W16(0x0005), W16(0x0088), W16(0x0023), W16(0x004C), W16(0xFFBB), W16(0x0015), W16(0x0011), + W16(0x0024), W16(0x002F), W16(0x0019), W16(0x0004), W16(0xFFC8), W16(0xFFB5), W16(0xFFDC), W16(0x0006), + W16(0x0004), W16(0x0011), W16(0x000E), W16(0x0003), W16(0xFFE2), W16(0xFFB2), W16(0xFF99), W16(0xFF7B), + W16(0xFFEE), W16(0xFFF8), W16(0x0017), W16(0x002B), W16(0xFF2C), W16(0xFFA2), W16(0x0086), W16(0x00F1), + W16(0xFFD0), W16(0xFFDD), W16(0xFFD5), W16(0x0032), W16(0x002C), W16(0xFFD5), W16(0xFFFD), W16(0x002B), + W16(0xFFDD), W16(0xFFE7), W16(0xFFF7), W16(0x003C), W16(0x0011), W16(0x002D), W16(0x004D), W16(0x001F), + W16(0xFFCE), W16(0x001A), W16(0x0052), W16(0xFF95), W16(0xFFFC), W16(0xFFEC), W16(0x0007), W16(0x0013), + W16(0x0013), W16(0x000F), W16(0xFFD7), W16(0x0057), W16(0x0028), W16(0x0019), W16(0xFFCD), W16(0xFFD3), + W16(0xFFCC), W16(0xFFF5), W16(0x006F), W16(0x011E), W16(0x00C4), W16(0x0064), W16(0xFFE2), W16(0xFFA3), + W16(0x0053), W16(0xFFE8), W16(0xFFC4), W16(0x0022), W16(0xFF9D), W16(0x0004), W16(0xFFD3), W16(0x001C), + W16(0x0017), W16(0xFFF0), W16(0xFFF1), W16(0x0012), W16(0x0007), W16(0x001D), W16(0x0010), W16(0x0015), + W16(0x001B), W16(0x000B), W16(0xFFE1), W16(0xFFDA), W16(0xFFA6), W16(0xFF79), W16(0x0002), W16(0x020E), + W16(0x003B), W16(0x0003), W16(0xFFFB), W16(0xFFEC), W16(0xFFCA), W16(0xFFD2), W16(0xFFC8), W16(0xFFAB), + W16(0xFFE1), W16(0x0013), W16(0x0005), W16(0x0020), W16(0x0048), W16(0x005D), W16(0x00E1), W16(0xFFA6), + W16(0xFFAC), W16(0x0073), W16(0x008A), W16(0x005B), W16(0xFFDC), W16(0xFFD2), W16(0xFFEF), W16(0x001A), + W16(0x0035), W16(0x0050), W16(0x000C), W16(0x0047), W16(0x0049), W16(0x0038), W16(0x002E), W16(0x0074), + W16(0xFFE5), W16(0xFF9E), W16(0xFF99), W16(0xFFB6), W16(0xFFF1), W16(0x0004), W16(0x0028), W16(0x0004), + W16(0xFFEA), W16(0x0000), W16(0x0000), W16(0x001A), W16(0x0061), W16(0x0079), W16(0x008A), W16(0x00A0), + W16(0x00D0), W16(0xFFF3), W16(0x0055), W16(0x004B), W16(0x005A), W16(0x0016), W16(0xFFE5), W16(0xFFCC), + W16(0xFFC2), W16(0x0004), W16(0x0017), W16(0x0014), W16(0x0007), W16(0x0000), W16(0xFFFB), W16(0xFFF3), + W16(0xFFF9), W16(0xFFFD), W16(0xFFFD), W16(0x0015), W16(0x003F), W16(0x0045), W16(0x0053), W16(0x004B), + W16(0xFFE7), W16(0x005D), W16(0x0018), W16(0xFFE0), W16(0xFFF7), W16(0x0059), W16(0x003D), W16(0xFFEA), + W16(0xFEFA), W16(0xFFDF), W16(0xFFDD), W16(0x0009), W16(0x001F), W16(0x0016), W16(0x0034), W16(0x002E), + W16(0x0033), W16(0x003F), W16(0x004D), W16(0x002D), W16(0x0016), W16(0x0020), W16(0x0023), W16(0x0014), + W16(0xFFC7), W16(0xFFDE), W16(0x0056), W16(0xFFE8), W16(0x003A), W16(0x008F), W16(0xFFEB), W16(0xFFB7), + W16(0x0011), W16(0x0001), W16(0xFFD2), W16(0xFF83), W16(0xFF90), W16(0xFFEE), W16(0x0037), W16(0x0020), + W16(0x0059), W16(0x00BE), W16(0x00A3), W16(0x000F), W16(0xFF91), W16(0xFFB4), W16(0xFF97), W16(0xFF67), + W16(0xFFDF), W16(0x0046), W16(0xFF9A), W16(0xFFB2), W16(0xFFF0), W16(0x000E), W16(0xFF8F), W16(0xFFC7), + W16(0x0017), W16(0x005B), W16(0x0054), W16(0xFFFB), W16(0xFFC4), W16(0xFFD7), W16(0xFFE8), W16(0x0022), + W16(0x0043), W16(0x004C), W16(0x0066), W16(0x0074), W16(0x0092), W16(0x00B9), W16(0x00D5), W16(0x00BB), + W16(0x0071), W16(0x0148), W16(0x00DB), W16(0x00D4), W16(0x005C), W16(0x0031), W16(0x0012), W16(0x0025), + W16(0xFFE7), W16(0xFFEB), W16(0xFFD8), W16(0xFFC1), W16(0xFFE8), W16(0xFFED), W16(0xFFFA), W16(0x0001), + W16(0xFFFF), W16(0xFFF0), W16(0xFFE3), W16(0xFFE7), W16(0x0004), W16(0xFFFF), W16(0xFFF0), W16(0xFFF3), + W16(0x0055), W16(0x0136), W16(0xFFF5), W16(0xFFA3), W16(0xFFE5), W16(0xFFDC), W16(0xFFC6), W16(0xFFDD), + W16(0xFFDF), W16(0x0000), W16(0x0023), W16(0x0040), W16(0x0045), W16(0x0003), W16(0x0007), W16(0x000B), + W16(0x0002), W16(0x0004), W16(0xFFE8), W16(0xFFDF), W16(0xFFAD), W16(0xFFAA), W16(0xFF6E), W16(0xFF35), + W16(0x0017), W16(0x000B), W16(0x002B), W16(0x00DC), W16(0x00B1), W16(0xFFE2), W16(0xFFC0), W16(0x0001), + W16(0x0024), W16(0x0023), W16(0x0029), W16(0x006A), W16(0xFFED), W16(0xFFDF), W16(0xFFCA), W16(0xFF98), + W16(0xFFA4), W16(0xFFEA), W16(0x001A), W16(0x002C), W16(0x0003), W16(0x002A), W16(0x005F), W16(0x0077) +}; + +const Word16 cdk_37bits_4_fx[1536] = +{ + W16(0xFFF5), W16(0xFFA9), W16(0x000E), W16(0xFFC8), W16(0xFFCB), W16(0xFFB9), W16(0xFFD4), W16(0xFFCC), + W16(0xFFCB), W16(0xFFC8), W16(0xFFD3), W16(0x001A), W16(0x0049), W16(0x003A), W16(0x001F), W16(0x0044), + W16(0x0077), W16(0x004D), W16(0xFFEC), W16(0xFF84), W16(0xFFBC), W16(0xFFED), W16(0xFFE0), W16(0xFFE5), + W16(0x0033), W16(0xFFF7), W16(0xFFF9), W16(0x005E), W16(0x00B6), W16(0x003A), W16(0xFFEA), W16(0xFFA0), + W16(0xFFAB), W16(0xFFB9), W16(0xFFD3), W16(0xFFFB), W16(0xFFF2), W16(0xFFFA), W16(0x0010), W16(0x0029), + W16(0x002E), W16(0xFFD6), W16(0xFFCA), W16(0xFFBE), W16(0xFFC9), W16(0xFFCA), W16(0xFFD8), W16(0xFFD2), + W16(0xFF2B), W16(0x0024), W16(0xFFAF), W16(0x0020), W16(0x0068), W16(0x0038), W16(0x0015), W16(0x001B), + W16(0x0006), W16(0x0005), W16(0xFFF4), W16(0xFFCC), W16(0xFFD1), W16(0xFFF3), W16(0xFFDF), W16(0xFFBF), + W16(0x0003), W16(0xFFE3), W16(0x0001), W16(0x0018), W16(0x0021), W16(0x0010), W16(0xFFF4), W16(0xFFD9), + W16(0xFF6C), W16(0xFFD8), W16(0x0011), W16(0xFFB4), W16(0xFFD1), W16(0xFFBD), W16(0x0002), W16(0xFFDA), + W16(0x003A), W16(0x0033), W16(0x0038), W16(0x001D), W16(0x0030), W16(0x002A), W16(0xFFD3), W16(0xFFC7), + W16(0xFFDF), W16(0xFFC0), W16(0xFFDE), W16(0xFFD8), W16(0xFFB9), W16(0xFFCC), W16(0xFFDE), W16(0xFFFF), + W16(0xFFFA), W16(0xFFCE), W16(0xFFB7), W16(0xFFD7), W16(0x0031), W16(0x0017), W16(0xFFB0), W16(0x0018), + W16(0x003E), W16(0x002E), W16(0xFFE7), W16(0x0096), W16(0xFFCB), W16(0xFFC8), W16(0xFFDB), W16(0xFFB8), + W16(0xFFE0), W16(0xFFF6), W16(0xFFE9), W16(0xFFA6), W16(0xFFBD), W16(0xFFC1), W16(0xFFCC), W16(0xFFE0), + W16(0xFFF0), W16(0xFFDA), W16(0xFFD5), W16(0x000E), W16(0xFF85), W16(0x0112), W16(0xFFBB), W16(0xFFDF), + W16(0xFFF1), W16(0xFFF0), W16(0xFFED), W16(0xFFFB), W16(0xFFF6), W16(0x0009), W16(0x0010), W16(0xFFF1), + W16(0x0005), W16(0xFFE2), W16(0xFFDF), W16(0x0003), W16(0xFFBA), W16(0x0003), W16(0xFFFC), W16(0xFFD8), + W16(0xFFBE), W16(0x0070), W16(0xFF97), W16(0xFFC2), W16(0xFFE8), W16(0xFFF4), W16(0x001A), W16(0xFFE6), + W16(0xFFCD), W16(0xFFDA), W16(0xFFB6), W16(0x0020), W16(0x0020), W16(0x0035), W16(0xFFEC), W16(0x0029), + W16(0x003B), W16(0x0012), W16(0x0026), W16(0x002E), W16(0xFFF9), W16(0xFFE0), W16(0xFFD2), W16(0xFFBC), + W16(0x0042), W16(0xFF99), W16(0xFF90), W16(0x0013), W16(0x0007), W16(0xFFBE), W16(0x0007), W16(0x0016), + W16(0x0019), W16(0xFFC5), W16(0xFFF7), W16(0x001A), W16(0xFFC3), W16(0x002E), W16(0x002C), W16(0x0037), + W16(0xFFDC), W16(0xFFE5), W16(0x0001), W16(0x002A), W16(0x0022), W16(0x0042), W16(0x0043), W16(0x003B), + W16(0x002A), W16(0xFF9D), W16(0xFFD0), W16(0xFFFA), W16(0xFFC4), W16(0x000A), W16(0x0005), W16(0xFFD4), + W16(0x0036), W16(0x0036), W16(0xFFFB), W16(0xFFFC), W16(0xFFEE), W16(0xFFC3), W16(0xFF9A), W16(0x004E), + W16(0x005D), W16(0xFFF4), W16(0xFFEB), W16(0x0015), W16(0xFFF1), W16(0xFFD1), W16(0xFF99), W16(0xFF78), + W16(0x004F), W16(0xFFBD), W16(0xFFA8), W16(0x0053), W16(0x0038), W16(0xFFE5), W16(0xFFD2), W16(0x0026), + W16(0xFFE1), W16(0x0003), W16(0xFFD5), W16(0xFFAB), W16(0x0039), W16(0x0045), W16(0x0028), W16(0xFFF6), + W16(0xFFEB), W16(0xFFD6), W16(0xFFD5), W16(0xFFB9), W16(0xFFDA), W16(0xFFEE), W16(0x0000), W16(0x000E), + W16(0xFF7C), W16(0xFF75), W16(0xFFFF), W16(0xFFED), W16(0xFFFF), W16(0x002D), W16(0x001E), W16(0xFFB1), + W16(0x000A), W16(0x0015), W16(0xFFF0), W16(0xFFF8), W16(0xFFE5), W16(0x0015), W16(0x000E), W16(0x0012), + W16(0xFFE4), W16(0x0003), W16(0x000B), W16(0x000D), W16(0x0024), W16(0x003A), W16(0x0039), W16(0x0033), + W16(0xFFBA), W16(0xFFFD), W16(0xFFD0), W16(0xFFC4), W16(0xFFAE), W16(0x0020), W16(0x0024), W16(0x0050), + W16(0xFFFE), W16(0xFFF7), W16(0xFFE7), W16(0x000C), W16(0x0040), W16(0x001F), W16(0x001E), W16(0xFFD4), + W16(0xFF86), W16(0xFF87), W16(0xFF8B), W16(0xFFD1), W16(0x0024), W16(0x0036), W16(0xFFF4), W16(0xFFD6), + W16(0xFFFE), W16(0x001D), W16(0x0010), W16(0xFFDC), W16(0xFFD0), W16(0xFFF2), W16(0xFFE6), W16(0x0003), + W16(0xFFD5), W16(0xFFED), W16(0x006C), W16(0xFF8D), W16(0x000A), W16(0x0022), W16(0x0023), W16(0x001A), + W16(0x0030), W16(0xFFCA), W16(0xFFD4), W16(0xFFF2), W16(0x0004), W16(0xFFE5), W16(0xFFAB), W16(0xFF9B), + W16(0x0058), W16(0xFFD4), W16(0xFFA9), W16(0xFFAF), W16(0xFFDB), W16(0xFFF2), W16(0x003C), W16(0x008E), + W16(0x0007), W16(0xFFEE), W16(0xFFCE), W16(0xFFE0), W16(0xFFF7), W16(0xFFC4), W16(0xFFF3), W16(0xFFF7), + W16(0x0021), W16(0x0016), W16(0x0017), W16(0x000E), W16(0xFFF1), W16(0xFFF4), W16(0x0004), W16(0x0009), + W16(0xFFDA), W16(0xFFC0), W16(0x0048), W16(0x008F), W16(0x0007), W16(0xFF9C), W16(0xFFE3), W16(0xFFEF), + W16(0x0036), W16(0x0023), W16(0xFFF7), W16(0x000E), W16(0xFFEF), W16(0xFFF5), W16(0x0022), W16(0x0004), + W16(0x0022), W16(0xFFE7), W16(0xFFC5), W16(0xFFDC), W16(0xFFCE), W16(0xFFD7), W16(0xFFAE), W16(0xFF8F), + W16(0xFF94), W16(0x0053), W16(0xFFE9), W16(0xFFFD), W16(0x0002), W16(0x000E), W16(0xFFCA), W16(0xFFB0), + W16(0xFF9E), W16(0x0024), W16(0x0040), W16(0x0048), W16(0x0032), W16(0xFFBC), W16(0xFFFE), W16(0x0025), + W16(0x001A), W16(0xFFC6), W16(0xFFD6), W16(0xFFE9), W16(0xFFFB), W16(0x0012), W16(0x000C), W16(0x0005), + W16(0xFFB4), W16(0xFF9D), W16(0x001F), W16(0xFF74), W16(0xFFE3), W16(0xFFF2), W16(0xFFD9), W16(0x005A), + W16(0x0009), W16(0xFFDD), W16(0xFFEB), W16(0x0033), W16(0x0013), W16(0x0003), W16(0xFFD9), W16(0x0000), + W16(0x0004), W16(0x0000), W16(0x0008), W16(0x0045), W16(0x0022), W16(0x0038), W16(0x004F), W16(0x0036), + W16(0xFFC8), W16(0xFFE4), W16(0xFFD6), W16(0x0076), W16(0x0020), W16(0xFFEE), W16(0x004C), W16(0xFFFA), + W16(0xFFB2), W16(0x0008), W16(0x002E), W16(0x001B), W16(0x0002), W16(0xFFEC), W16(0xFFDD), W16(0xFFEF), + W16(0xFFEE), W16(0xFFD1), W16(0xFFC8), W16(0xFFC8), W16(0xFFBB), W16(0xFFE7), W16(0x0008), W16(0x0018), + W16(0xFFF5), W16(0xFFBA), W16(0x000D), W16(0x001B), W16(0x0045), W16(0x0013), W16(0x0001), W16(0x0010), + W16(0x000D), W16(0xFFF9), W16(0x0043), W16(0x000D), W16(0xFFCD), W16(0xFFF2), W16(0x007E), W16(0xFFAA), + W16(0xFF59), W16(0x00A5), W16(0x0018), W16(0xFFEA), W16(0xFFAE), W16(0xFFCB), W16(0xFFD4), W16(0x0013), + W16(0xFFEA), W16(0xFFA6), W16(0xFFB1), W16(0xFFA5), W16(0x0036), W16(0xFFB5), W16(0xFFB5), W16(0xFFD0), + W16(0xFFD2), W16(0x002D), W16(0x002C), W16(0x0013), W16(0xFFF5), W16(0x0013), W16(0x001C), W16(0x001F), + W16(0x000F), W16(0x001F), W16(0x001A), W16(0x002E), W16(0x001C), W16(0xFFF4), W16(0xFFBE), W16(0xFF9E), + W16(0x000C), W16(0x0037), W16(0xFFDB), W16(0x001C), W16(0x003D), W16(0xFF98), W16(0xFF81), W16(0x0097), + W16(0x005A), W16(0x0001), W16(0xFFDE), W16(0xFFCB), W16(0x0024), W16(0xFFFD), W16(0xFFED), W16(0x0011), + W16(0xFFF0), W16(0xFFD4), W16(0xFFCA), W16(0xFFD8), W16(0xFFD8), W16(0xFFE1), W16(0xFFE2), W16(0xFFD1), + W16(0xFFF7), W16(0xFFD4), W16(0xFFF8), W16(0xFFAD), W16(0x002B), W16(0x002B), W16(0xFFC9), W16(0xFFED), + W16(0xFFED), W16(0x0006), W16(0xFFEE), W16(0xFFCF), W16(0xFF8C), W16(0x0007), W16(0x0022), W16(0x0011), + W16(0x007F), W16(0x005A), W16(0x001C), W16(0xFFBB), W16(0xFF8E), W16(0xFFF7), W16(0x00B9), W16(0x00C3), + W16(0xFFDB), W16(0xFFCB), W16(0x0004), W16(0x0024), W16(0x0025), W16(0x0016), W16(0x0019), W16(0xFFEF), + W16(0xFFD2), W16(0xFFCA), W16(0xFFAD), W16(0xFFE6), W16(0xFFCB), W16(0x0005), W16(0x0060), W16(0x0032), + W16(0x002D), W16(0xFFE8), W16(0xFFC9), W16(0xFFF6), W16(0x0177), W16(0xFF8E), W16(0xFF7B), W16(0xFFCF), + W16(0xFFC6), W16(0x000A), W16(0xFFD3), W16(0xFFDB), W16(0xFFF4), W16(0xFFF3), W16(0x0034), W16(0xFFE2), + W16(0x0035), W16(0xFF72), W16(0x0019), W16(0xFFDE), W16(0x0013), W16(0x000A), W16(0x0003), W16(0x0017), + W16(0x002F), W16(0x0006), W16(0x0012), W16(0xFFFB), W16(0xFFF5), W16(0x000D), W16(0x0004), W16(0xFFF9), + W16(0x0026), W16(0x0005), W16(0xFFF2), W16(0xFF8B), W16(0xFFEE), W16(0x0010), W16(0xFFEB), W16(0xFFBC), + W16(0x002C), W16(0x0043), W16(0xFFA2), W16(0x0014), W16(0x002C), W16(0xFFF6), W16(0x0007), W16(0x0000), + W16(0x000F), W16(0xFFF8), W16(0xFFE7), W16(0xFFDB), W16(0xFFC9), W16(0xFFE2), W16(0xFFFB), W16(0x000B), + W16(0x001F), W16(0xFFF4), W16(0xFFFD), W16(0xFFDB), W16(0x0008), W16(0x0052), W16(0xFFBB), W16(0xFFC6), + W16(0x004A), W16(0xFFFB), W16(0x0049), W16(0xFFE0), W16(0x0059), W16(0xFFEA), W16(0xFFD3), W16(0xFFD0), + W16(0xFFD0), W16(0xFFD9), W16(0xFFEB), W16(0xFFD8), W16(0xFFF0), W16(0x0026), W16(0x0084), W16(0x00A7), + W16(0xFFE8), W16(0xFFCB), W16(0x001B), W16(0x0039), W16(0x0009), W16(0x0000), W16(0x0030), W16(0x0048), + W16(0x0046), W16(0x0061), W16(0x000B), W16(0xFFE0), W16(0xFFEB), W16(0xFFC4), W16(0xFFB2), W16(0xFFB2), + W16(0xFFDC), W16(0xFFEC), W16(0x0009), W16(0x0006), W16(0xFFFC), W16(0x0001), W16(0xFFFB), W16(0xFFF4), + W16(0x004E), W16(0x004A), W16(0x003E), W16(0xFFE0), W16(0xFFCC), W16(0x0035), W16(0x0024), W16(0x0024), + W16(0x0017), W16(0xFFB7), W16(0xFFED), W16(0x0048), W16(0xFFF9), W16(0x000B), W16(0xFFCF), W16(0xFFF1), + W16(0xFFF1), W16(0xFFD0), W16(0xFFBC), W16(0xFFAA), W16(0xFF97), W16(0xFFA4), W16(0xFFA7), W16(0xFFAD), + W16(0x001D), W16(0xFFD1), W16(0x0036), W16(0xFFD3), W16(0x0015), W16(0x0016), W16(0x0065), W16(0x000F), + W16(0x0006), W16(0xFFED), W16(0xFFD0), W16(0xFFB1), W16(0xFFDE), W16(0x0022), W16(0x001A), W16(0x0012), + W16(0xFFC0), W16(0xFFBB), W16(0xFFBD), W16(0xFFBB), W16(0xFFD0), W16(0xFFE3), W16(0xFFE2), W16(0xFFE5), + W16(0x001C), W16(0x003A), W16(0x0004), W16(0xFFCD), W16(0x003C), W16(0x004D), W16(0xFFD8), W16(0x0004), + W16(0x0040), W16(0xFFDC), W16(0xFFA3), W16(0xFFB7), W16(0x002F), W16(0x0017), W16(0xFFDC), W16(0xFFFA), + W16(0x0009), W16(0x0033), W16(0x001C), W16(0x0008), W16(0x0004), W16(0xFFE6), W16(0xFFB8), W16(0xFFA5), + W16(0xFFF0), W16(0xFFD4), W16(0x0042), W16(0xFFD4), W16(0xFFE8), W16(0x003F), W16(0x0064), W16(0xFFEB), + W16(0xFFA8), W16(0xFFE1), W16(0x0017), W16(0x000C), W16(0x0020), W16(0xFFB8), W16(0xFFD5), W16(0x000C), + W16(0x0025), W16(0x0051), W16(0x0016), W16(0xFFF3), W16(0xFFCF), W16(0xFFB7), W16(0xFFA6), W16(0xFF84), + W16(0xFFE6), W16(0xFFC8), W16(0x0024), W16(0xFFE1), W16(0x0044), W16(0xFF29), W16(0x0015), W16(0x0029), + W16(0x0004), W16(0x0023), W16(0xFFD5), W16(0xFFEA), W16(0x001B), W16(0x002B), W16(0xFFFB), W16(0x0011), + W16(0x001C), W16(0x0015), W16(0x0017), W16(0x000B), W16(0xFFF6), W16(0x0009), W16(0x0005), W16(0x0007), + W16(0x0060), W16(0xFFE5), W16(0x005F), W16(0xFFCF), W16(0xFFAF), W16(0xFFB2), W16(0xFFD3), W16(0x0002), + W16(0xFFFA), W16(0xFFD1), W16(0x001D), W16(0x001D), W16(0x0019), W16(0x0037), W16(0x002A), W16(0x0025), + W16(0x0027), W16(0x0029), W16(0x003C), W16(0x0049), W16(0x0035), W16(0x0027), W16(0xFFF9), W16(0xFFD0), + W16(0x0067), W16(0xFFDD), W16(0x000F), W16(0x0043), W16(0x0027), W16(0x002A), W16(0x0051), W16(0xFF79), + W16(0xFFDC), W16(0x002B), W16(0x0012), W16(0x0010), W16(0x001B), W16(0xFFFE), W16(0x0000), W16(0xFFCE), + W16(0xFFD6), W16(0x0002), W16(0x0028), W16(0x0030), W16(0xFFE4), W16(0xFFD8), W16(0xFFCD), W16(0xFFC8), + W16(0x003F), W16(0x0064), W16(0x000C), W16(0x0049), W16(0x0034), W16(0x0062), W16(0x006F), W16(0x004F), + W16(0x0004), W16(0xFFB8), W16(0x0006), W16(0xFFDD), W16(0xFFB8), W16(0xFFD3), W16(0xFFE4), W16(0xFFB6), + W16(0xFFE8), W16(0xFFFE), W16(0x0018), W16(0x004A), W16(0x0022), W16(0xFFFA), W16(0xFFF9), W16(0xFFFC), + W16(0xFFD7), W16(0x0066), W16(0xFFFD), W16(0x0013), W16(0x0023), W16(0xFFE5), W16(0xFFB5), W16(0xFFE5), + W16(0xFFFA), W16(0x000D), W16(0x0043), W16(0x0011), W16(0x003E), W16(0x0083), W16(0xFFF8), W16(0xFFC5), + W16(0xFF84), W16(0x000E), W16(0x0013), W16(0xFFBB), W16(0xFFA7), W16(0xFFB8), W16(0xFFDB), W16(0xFFDA), + W16(0xFFFD), W16(0x001C), W16(0xFFE9), W16(0x0005), W16(0x006D), W16(0xFFD2), W16(0x000C), W16(0x0002), + W16(0x003A), W16(0x002A), W16(0x0012), W16(0x0000), W16(0xFF71), W16(0xFFCA), W16(0xFFE6), W16(0x0009), + W16(0x0012), W16(0xFFEF), W16(0xFFFB), W16(0xFFF5), W16(0x000E), W16(0x001C), W16(0x0029), W16(0x0028), + W16(0x0036), W16(0x002B), W16(0xFFE3), W16(0x004D), W16(0xFF48), W16(0x0019), W16(0x0032), W16(0x0003), + W16(0x0066), W16(0x0003), W16(0xFFE0), W16(0xFFFC), W16(0x0004), W16(0xFFFA), W16(0x001A), W16(0x000B), + W16(0x0001), W16(0xFFFE), W16(0xFFFC), W16(0xFFE3), W16(0xFFE8), W16(0x0004), W16(0x0024), W16(0x0032), + W16(0x0021), W16(0x002B), W16(0xFF99), W16(0x000C), W16(0x0008), W16(0x004D), W16(0xFFD5), W16(0xFFC1), + W16(0xFFDE), W16(0xFFD3), W16(0x0001), W16(0xFFE1), W16(0xFFD3), W16(0x0018), W16(0x0044), W16(0x0024), + W16(0x0030), W16(0x0004), W16(0x000F), W16(0x0017), W16(0x002D), W16(0x0042), W16(0x004A), W16(0x0048), + W16(0xFFDF), W16(0x000D), W16(0x000A), W16(0xFFF4), W16(0xFFF0), W16(0xFFCC), W16(0xFFE2), W16(0xFFF4), + W16(0xFFF3), W16(0x0009), W16(0x0024), W16(0x0054), W16(0x0004), W16(0xFFEB), W16(0x0019), W16(0x0092), + W16(0xFF5F), W16(0xFFFD), W16(0x0022), W16(0x001E), W16(0xFFD5), W16(0xFF9D), W16(0xFFB6), W16(0x002E), + W16(0xFFC7), W16(0xFFCB), W16(0xFF9E), W16(0x0036), W16(0xFF8C), W16(0xFFCD), W16(0xFFDC), W16(0xFFF8), + W16(0x0010), W16(0x001B), W16(0x0019), W16(0x0004), W16(0x0035), W16(0x0018), W16(0xFFFD), W16(0x0010), + W16(0x0032), W16(0x004E), W16(0x0035), W16(0x0037), W16(0x000A), W16(0xFFF5), W16(0xFFE6), W16(0xFFE5), + W16(0x002D), W16(0xFFFA), W16(0xFFF7), W16(0xFFF0), W16(0xFFC6), W16(0xFFCA), W16(0xFFEA), W16(0x001E), + W16(0x0041), W16(0x002C), W16(0xFFF9), W16(0xFFEF), W16(0xFFBD), W16(0x00C2), W16(0x0012), W16(0xFF8E), + W16(0xFFF4), W16(0xFFF1), W16(0x004F), W16(0x0026), W16(0xFFF2), W16(0xFFD6), W16(0xFFAE), W16(0xFFA5), + W16(0xFFBD), W16(0xFFEB), W16(0x0056), W16(0xFFA9), W16(0xFF78), W16(0x0020), W16(0x005D), W16(0xFFE9), + W16(0xFFFA), W16(0x0054), W16(0x0026), W16(0xFFFB), W16(0xFFAC), W16(0xFFE8), W16(0xFFF6), W16(0xFFEC), + W16(0x003E), W16(0x0025), W16(0x0045), W16(0x0027), W16(0x0046), W16(0x0031), W16(0x001D), W16(0xFFF3), + W16(0xFFDD), W16(0x0016), W16(0xFFE8), W16(0x003B), W16(0x0004), W16(0x0053), W16(0x0024), W16(0xFFFA), + W16(0xFFDA), W16(0x0014), W16(0xFF6A), W16(0x0062), W16(0x0006), W16(0xFFE2), W16(0x0003), W16(0xFFF4), + W16(0xFFF2), W16(0xFFF7), W16(0xFFFC), W16(0x0012), W16(0x0019), W16(0x0019), W16(0x000D), W16(0x000E), + W16(0x0049), W16(0xFFF4), W16(0x0028), W16(0x000C), W16(0xFFC1), W16(0xFFDF), W16(0x0025), W16(0x003D), + W16(0xFF8A), W16(0x0048), W16(0x001A), W16(0xFFD5), W16(0x003B), W16(0x0055), W16(0x000C), W16(0xFFB4), + W16(0xFFEF), W16(0xFFFF), W16(0x0007), W16(0x0026), W16(0x001D), W16(0x0025), W16(0x0029), W16(0x0030), + W16(0x0059), W16(0x0057), W16(0xFFF3), W16(0xFFE7), W16(0xFFE6), W16(0xFF6D), W16(0x0080), W16(0xFFD4), + W16(0x002A), W16(0x0027), W16(0xFFE6), W16(0xFF9C), W16(0xFFC5), W16(0x0009), W16(0x0023), W16(0x004C), + W16(0x0048), W16(0x004F), W16(0xFFFB), W16(0xFFF3), W16(0x0016), W16(0x0001), W16(0xFFED), W16(0xFFEC), + W16(0xFF76), W16(0x0021), W16(0x009C), W16(0x0018), W16(0xFFD7), W16(0x002C), W16(0xFFD7), W16(0xFFF4), + W16(0x0025), W16(0xFFD1), W16(0xFFC9), W16(0xFFFB), W16(0xFFF5), W16(0x0005), W16(0x001D), W16(0x0035), + W16(0x002A), W16(0xFFEB), W16(0xFFE6), W16(0xFFD3), W16(0xFFDF), W16(0xFFFB), W16(0xFFFB), W16(0xFFEE), + W16(0x000B), W16(0x0024), W16(0x000C), W16(0x0024), W16(0xFFDB), W16(0xFFEC), W16(0xFFF5), W16(0x0009), + W16(0xFFFE), W16(0x0015), W16(0x0034), W16(0x0058), W16(0xFFF7), W16(0xFF52), W16(0x0058), W16(0x0023), + W16(0xFFD8), W16(0xFFD4), W16(0xFFE6), W16(0xFFFB), W16(0x0000), W16(0x0029), W16(0x003E), W16(0x0041), + W16(0xFFF2), W16(0xFFBA), W16(0xFFF7), W16(0x000A), W16(0x002A), W16(0x004C), W16(0xFFC4), W16(0x0042), + W16(0xFFAC), W16(0xFF6C), W16(0x003B), W16(0x0025), W16(0x0005), W16(0xFFE3), W16(0x000B), W16(0x000F), + W16(0x000C), W16(0x0028), W16(0x0021), W16(0x0015), W16(0xFFFF), W16(0xFFFE), W16(0x0006), W16(0x000B), + W16(0x0005), W16(0x006C), W16(0x0018), W16(0x0068), W16(0x0027), W16(0xFFA0), W16(0x0025), W16(0x0003), + W16(0xFFE8), W16(0xFFD7), W16(0xFFE4), W16(0x0026), W16(0x000D), W16(0xFFFF), W16(0x001D), W16(0x001F), + W16(0x0000), W16(0xFFEC), W16(0xFFF5), W16(0x0017), W16(0x0023), W16(0x003C), W16(0x0041), W16(0x0032), + W16(0xFFB5), W16(0x0068), W16(0xFFE8), W16(0x0006), W16(0xFFB3), W16(0x0002), W16(0xFFF4), W16(0x005C), + W16(0xFFE6), W16(0x0011), W16(0xFFE6), W16(0xFFCA), W16(0xFFA2), W16(0x0023), W16(0x004C), W16(0x0038), + W16(0x000B), W16(0x0011), W16(0x0015), W16(0xFFEA), W16(0xFFEC), W16(0xFFFB), W16(0x000A), W16(0x0003), + W16(0xFFFF), W16(0x0040), W16(0xFF79), W16(0xFFC5), W16(0x002C), W16(0xFFCB), W16(0x0007), W16(0xFFF1), + W16(0x0030), W16(0x003E), W16(0x001F), W16(0xFFE1), W16(0x0020), W16(0x0013), W16(0xFFCE), W16(0xFFD6), + W16(0xFFCC), W16(0xFFFF), W16(0x0027), W16(0x004B), W16(0x004B), W16(0x0045), W16(0x0038), W16(0x0036), + W16(0x0008), W16(0xFFF8), W16(0x0026), W16(0xFFFE), W16(0x000F), W16(0xFFD1), W16(0xFFE3), W16(0x0039), + W16(0xFFF3), W16(0xFFCB), W16(0xFFDE), W16(0x000E), W16(0x0102), W16(0xFFC2), W16(0xFF93), W16(0xFFF9), + W16(0x000C), W16(0xFFD7), W16(0xFFF4), W16(0x000F), W16(0xFFFD), W16(0x0022), W16(0x0020), W16(0x0027), + W16(0x002B), W16(0x0034), W16(0x0006), W16(0x0022), W16(0x0018), W16(0x0022), W16(0xFFE0), W16(0xFFFC), + W16(0x0037), W16(0x001E), W16(0x003F), W16(0xFFCC), W16(0xFFE7), W16(0xFFC3), W16(0xFFA8), W16(0xFFE4), + W16(0x0054), W16(0x006D), W16(0x0025), W16(0xFF9E), W16(0xFFBD), W16(0xFFCB), W16(0xFFE6), W16(0x001A), + W16(0xFFD6), W16(0x0080), W16(0x0074), W16(0xFFA3), W16(0x0034), W16(0xFFFA), W16(0x0010), W16(0xFFBF), + W16(0xFFC1), W16(0x0009), W16(0x0006), W16(0xFFE6), W16(0x0000), W16(0x0035), W16(0x003F), W16(0xFFF7), + W16(0xFFE3), W16(0xFFCF), W16(0x0000), W16(0x0019), W16(0x003B), W16(0x0043), W16(0x003F), W16(0x0047), + W16(0x0028), W16(0xFFCD), W16(0x000C), W16(0x0026), W16(0x0052), W16(0xFFF9), W16(0x003A), W16(0xFF99), + W16(0x0071), W16(0xFFAD), W16(0xFFFB), W16(0x001F), W16(0x000C), W16(0xFFF0), W16(0xFFDB), W16(0xFFFF), + W16(0xFFD5), W16(0x0023), W16(0x0022), W16(0x0032), W16(0x0048), W16(0x0025), W16(0xFFFE), W16(0xFFDB), + W16(0x009C), W16(0x0007), W16(0x0022), W16(0x0002), W16(0xFFB7), W16(0xFFAE), W16(0x0011), W16(0xFFE0), + W16(0x0000), W16(0x003B), W16(0x0027), W16(0x004D), W16(0x003A), W16(0xFFE2), W16(0xFFF6), W16(0x0006), + W16(0xFFE3), W16(0xFFCE), W16(0xFFCD), W16(0xFFD5), W16(0xFFFC), W16(0x0000), W16(0xFFF5), W16(0xFFF5), + W16(0x0040), W16(0xFFDE), W16(0x0050), W16(0x0018), W16(0xFFFB), W16(0x0041), W16(0xFF88), W16(0x000F), + W16(0xFFD7), W16(0x006B), W16(0x0038), W16(0xFFFC), W16(0xFFD8), W16(0xFFE9), W16(0xFFEC), W16(0x0007), + W16(0x0002), W16(0x000E), W16(0x0007), W16(0x0035), W16(0x002B), W16(0x0028), W16(0x0018), W16(0xFFFF), + W16(0xFFD6), W16(0x00B3), W16(0x0087), W16(0x001B), W16(0xFFBD), W16(0x001E), W16(0x0073), W16(0x0071), + W16(0x004B), W16(0x0052), W16(0x004D), W16(0xFFCE), W16(0xFFC2), W16(0xFFC6), W16(0xFFCB), W16(0xFF92), + W16(0xFFA3), W16(0xFF9F), W16(0xFFBA), W16(0x0011), W16(0xFFCF), W16(0xFFD7), W16(0x0018), W16(0x0072), + W16(0x0075), W16(0x0016), W16(0xFFD3), W16(0xFFA9), W16(0x0048), W16(0x001E), W16(0x0019), W16(0x000F), + W16(0xFF97), W16(0xFFF0), W16(0x0025), W16(0x003D), W16(0x0003), W16(0xFFE5), W16(0xFFE9), W16(0xFFEB), + W16(0xFFCD), W16(0xFFEA), W16(0xFFF0), W16(0x000E), W16(0x0018), W16(0x002A), W16(0x0030), W16(0x003C), + W16(0x0041), W16(0xFF90), W16(0x0039), W16(0x0015), W16(0x0006), W16(0x0039), W16(0x004B), W16(0x001E), + W16(0xFFFA), W16(0xFFC3), W16(0x0001), W16(0xFFBD), W16(0xFFF5), W16(0xFFC3), W16(0x0001), W16(0xFFFD), + W16(0x0026), W16(0xFFF4), W16(0x0006), W16(0x0069), W16(0x0083), W16(0x0080), W16(0x0077), W16(0x006E), + W16(0x00B3), W16(0x003E), W16(0x0007), W16(0x0037), W16(0x0025), W16(0xFFFD), W16(0xFFA5), W16(0xFFF6), + W16(0x0000), W16(0xFFF8), W16(0xFFED), W16(0x0003), W16(0x001A), W16(0xFFF7), W16(0x001B), W16(0x0030), + W16(0x0001), W16(0x002D), W16(0x0032), W16(0x0016), W16(0x000B), W16(0x0020), W16(0x0017), W16(0x0004), + W16(0xFFED), W16(0x004D), W16(0x0067), W16(0x0053), W16(0xFFD0), W16(0x0003), W16(0xFFC8), W16(0xFFC3), + W16(0xFFF4), W16(0x0001), W16(0x0032), W16(0x005D), W16(0xFFDF), W16(0x0027), W16(0xFFF2), W16(0xFFFB), + W16(0x002B), W16(0x0048), W16(0x002F), W16(0x0019), W16(0x001B), W16(0x0027), W16(0x001B), W16(0xFFFF), + W16(0xFFB9), W16(0xFFFC), W16(0x0003), W16(0x0054), W16(0x006D), W16(0x0003), W16(0xFFCF), W16(0x000B), + W16(0xFFD1), W16(0x000B), W16(0xFFD6), W16(0xFFDC), W16(0x000B), W16(0x0013), W16(0xFFCB), W16(0x0015), + W16(0x0029), W16(0x0046), W16(0x0084), W16(0x0071), W16(0x004F), W16(0x0045), W16(0x0040), W16(0x0038) +}; + +const Word16 cdk_37bits_5_fx[1536] = +{ + W16(0xFFF5), W16(0x0024), W16(0xFFA1), W16(0xFFDD), W16(0x0022), W16(0x004B), W16(0x003F), W16(0x0001), + W16(0x0040), W16(0xFFF4), W16(0xFFEE), W16(0xFFE4), W16(0xFFA4), W16(0xFFD7), W16(0xFFEA), W16(0xFFFD), + W16(0xFFEB), W16(0xFFDF), W16(0xFFDA), W16(0xFFFA), W16(0xFFFC), W16(0xFFF7), W16(0xFFFA), W16(0x0003), + W16(0x0015), W16(0xFFF0), W16(0xFFF2), W16(0xFFC0), W16(0x002F), W16(0x0002), W16(0xFFCA), W16(0xFFCD), + W16(0xFFF3), W16(0xFFFE), W16(0xFFCF), W16(0xFFF4), W16(0x0017), W16(0x0047), W16(0xFFDD), W16(0xFFFD), + W16(0x004D), W16(0xFF98), W16(0xFFBF), W16(0x0005), W16(0x0041), W16(0x0029), W16(0xFFF9), W16(0x0001), + W16(0xFFA6), W16(0xFFB8), W16(0xFFE4), W16(0x0009), W16(0xFFE0), W16(0x0031), W16(0x0005), W16(0xFFFD), + W16(0xFFAC), W16(0xFFF1), W16(0x000B), W16(0xFFFB), W16(0xFFDB), W16(0x000F), W16(0x0062), W16(0x0000), + W16(0xFFFE), W16(0x0018), W16(0x0000), W16(0xFFDB), W16(0xFFE6), W16(0xFFD1), W16(0xFFCF), W16(0xFFE5), + W16(0xFFE6), W16(0x0002), W16(0xFFAF), W16(0x003F), W16(0xFFF2), W16(0xFFD9), W16(0x0036), W16(0xFFF1), + W16(0x0048), W16(0xFFE7), W16(0xFFD8), W16(0x0002), W16(0x003D), W16(0x0002), W16(0x0005), W16(0x0006), + W16(0xFFBD), W16(0xFFCF), W16(0xFFCB), W16(0x0003), W16(0xFFFB), W16(0xFFF2), W16(0xFFD9), W16(0xFFDF), + W16(0xFFF8), W16(0xFFBF), W16(0x0001), W16(0xFFBB), W16(0xFFEA), W16(0xFFE6), W16(0xFFC8), W16(0x0028), + W16(0x0014), W16(0x0041), W16(0x0014), W16(0x0018), W16(0x0006), W16(0x0007), W16(0x0003), W16(0xFFF2), + W16(0xFFBF), W16(0xFFB0), W16(0xFFDA), W16(0xFFCC), W16(0xFFD4), W16(0xFFE4), W16(0xFFCD), W16(0xFFBE), + W16(0xFFA2), W16(0xFFA8), W16(0xFFF8), W16(0x0055), W16(0x002D), W16(0xFFEA), W16(0xFFE6), W16(0x0000), + W16(0x0005), W16(0xFFEF), W16(0x002D), W16(0x002F), W16(0x003D), W16(0xFFE0), W16(0xFFCF), W16(0xFFE2), + W16(0xFFE5), W16(0xFFEB), W16(0xFFEE), W16(0x0018), W16(0x000B), W16(0x0001), W16(0xFFF6), W16(0x0015), + W16(0x001F), W16(0xFFBA), W16(0xFFEA), W16(0x0002), W16(0xFFDC), W16(0xFFFB), W16(0xFFF0), W16(0xFFE6), + W16(0x005A), W16(0x0013), W16(0xFFF6), W16(0xFFCA), W16(0xFFF9), W16(0xFFB6), W16(0x0060), W16(0x0006), + W16(0x0012), W16(0x0046), W16(0x001D), W16(0x000C), W16(0x0022), W16(0x0022), W16(0x001B), W16(0x0012), + W16(0xFFB2), W16(0x0021), W16(0x000B), W16(0xFFDB), W16(0xFFE3), W16(0x0023), W16(0xFFCE), W16(0xFF8C), + W16(0x0058), W16(0xFFF7), W16(0x0026), W16(0xFFFD), W16(0x0016), W16(0x000D), W16(0x0008), W16(0xFFF0), + W16(0x0015), W16(0x001E), W16(0xFFF6), W16(0xFFF0), W16(0xFFD7), W16(0xFFD2), W16(0xFFD7), W16(0xFFEA), + W16(0xFFD8), W16(0x0006), W16(0xFF77), W16(0x0047), W16(0x0021), W16(0xFFEA), W16(0xFFC7), W16(0x0036), + W16(0xFFE1), W16(0x0032), W16(0xFFDD), W16(0xFFF5), W16(0xFFEA), W16(0xFFAD), W16(0x0028), W16(0x0034), + W16(0x001F), W16(0xFFEB), W16(0x0002), W16(0xFFD9), W16(0xFFEC), W16(0xFFE9), W16(0xFFEA), W16(0xFFE7), + W16(0x0021), W16(0xFFFC), W16(0xFFCD), W16(0xFFD7), W16(0x000D), W16(0xFFE4), W16(0x0025), W16(0xFFEC), + W16(0xFFF0), W16(0xFFF2), W16(0x002B), W16(0xFFE5), W16(0x0040), W16(0xFFB0), W16(0x001C), W16(0xFFE5), + W16(0x001C), W16(0xFFF5), W16(0xFFBD), W16(0xFFD3), W16(0xFFB4), W16(0xFFC8), W16(0xFFDC), W16(0x0000), + W16(0x0029), W16(0xFFFC), W16(0xFFE5), W16(0xFFE3), W16(0xFFAB), W16(0xFFDA), W16(0x0017), W16(0xFFD4), + W16(0xFFE6), W16(0xFFFF), W16(0x0032), W16(0xFFF7), W16(0xFFE3), W16(0x002C), W16(0x0042), W16(0x004A), + W16(0xFFE6), W16(0xFFEE), W16(0xFFE5), W16(0x0008), W16(0xFFDC), W16(0xFFEC), W16(0xFFF6), W16(0x000B), + W16(0xFFB6), W16(0x002A), W16(0x0031), W16(0x0011), W16(0x004F), W16(0xFFCA), W16(0xFFEA), W16(0x002A), + W16(0xFFF7), W16(0xFFEF), W16(0x000D), W16(0xFFBB), W16(0x0023), W16(0xFFCC), W16(0x0048), W16(0xFFF2), + W16(0xFFFD), W16(0xFFFD), W16(0xFFFC), W16(0x0001), W16(0x002D), W16(0x0004), W16(0xFFD0), W16(0xFFA2), + W16(0xFFD7), W16(0xFFE2), W16(0x0041), W16(0x000A), W16(0xFFE5), W16(0xFFEB), W16(0x002B), W16(0x001F), + W16(0x0043), W16(0xFFBE), W16(0x0044), W16(0xFFCF), W16(0xFFD9), W16(0x001C), W16(0x001E), W16(0xFFDE), + W16(0xFFE0), W16(0xFFD3), W16(0xFFD0), W16(0xFFE6), W16(0xFFF0), W16(0xFFF7), W16(0xFFED), W16(0x0002), + W16(0xFFD7), W16(0xFFF8), W16(0xFFEB), W16(0x0002), W16(0x0046), W16(0xFFEE), W16(0xFFF7), W16(0xFFD8), + W16(0x001B), W16(0xFFB8), W16(0xFFBA), W16(0xFFCE), W16(0x000B), W16(0x0042), W16(0x000C), W16(0x003A), + W16(0x000F), W16(0xFFFB), W16(0xFFF2), W16(0xFFE0), W16(0xFFBC), W16(0xFFBE), W16(0xFFF1), W16(0x0023), + W16(0xFFE4), W16(0xFFE6), W16(0xFFEA), W16(0xFFA8), W16(0xFFC1), W16(0x0016), W16(0x0054), W16(0x0016), + W16(0x001B), W16(0xFFFD), W16(0xFFE2), W16(0xFFD0), W16(0x0008), W16(0x002A), W16(0xFFE8), W16(0xFFC0), + W16(0x0019), W16(0xFFFE), W16(0x0021), W16(0x0013), W16(0x000B), W16(0xFFF8), W16(0xFFFE), W16(0x000C), + W16(0xFFA9), W16(0x0036), W16(0x0016), W16(0xFFE9), W16(0xFFAB), W16(0x000E), W16(0x0042), W16(0x0006), + W16(0xFFD0), W16(0x0009), W16(0xFFE3), W16(0xFFE0), W16(0x0025), W16(0x0015), W16(0x0011), W16(0x0027), + W16(0xFFF2), W16(0xFFD4), W16(0xFFB1), W16(0xFFC6), W16(0x001F), W16(0x0038), W16(0x002B), W16(0x0029), + W16(0xFFF0), W16(0x0025), W16(0xFFED), W16(0xFF89), W16(0x0014), W16(0x0034), W16(0xFFE5), W16(0xFFF0), + W16(0xFFE6), W16(0x000B), W16(0x0066), W16(0x0016), W16(0xFFF3), W16(0xFFCC), W16(0xFFD6), W16(0xFFEA), + W16(0xFFF8), W16(0x0007), W16(0x0015), W16(0x0013), W16(0x000A), W16(0x0020), W16(0x001A), W16(0x000E), + W16(0xFFD8), W16(0x000C), W16(0xFFF2), W16(0x0001), W16(0xFFD0), W16(0x0006), W16(0x0018), W16(0x0010), + W16(0xFFED), W16(0x0000), W16(0x001A), W16(0xFFFE), W16(0xFFFD), W16(0x003E), W16(0xFF67), W16(0x004E), + W16(0x000B), W16(0x0015), W16(0xFFEC), W16(0xFFE8), W16(0xFFDE), W16(0xFFF3), W16(0xFFFB), W16(0x0033), + W16(0xFFC6), W16(0xFFF1), W16(0xFFDC), W16(0xFFCA), W16(0x0016), W16(0xFFE7), W16(0x0029), W16(0xFFF6), + W16(0xFFF9), W16(0xFFE2), W16(0xFFCD), W16(0x002A), W16(0xFFE5), W16(0xFFC4), W16(0x0006), W16(0x0027), + W16(0x003B), W16(0x0035), W16(0x001C), W16(0x001C), W16(0x0015), W16(0x0025), W16(0x001F), W16(0x0031), + W16(0x0020), W16(0xFFFB), W16(0x0023), W16(0x0015), W16(0xFFF8), W16(0xFFFD), W16(0xFFEE), W16(0x003F), + W16(0x0055), W16(0x0006), W16(0x001B), W16(0xFFF7), W16(0xFFFB), W16(0xFFED), W16(0xFFE4), W16(0xFFEB), + W16(0xFFBA), W16(0x0029), W16(0x005B), W16(0x0063), W16(0xFFA2), W16(0xFFA6), W16(0xFF9D), W16(0xFFBD), + W16(0xFFCC), W16(0xFFB9), W16(0x0034), W16(0x0011), W16(0x000E), W16(0xFFFD), W16(0x0048), W16(0xFFE9), + W16(0xFFD8), W16(0x0071), W16(0xFFAB), W16(0x0013), W16(0xFFEC), W16(0xFFD2), W16(0xFFD3), W16(0xFFF8), + W16(0x0034), W16(0xFFFE), W16(0xFFD9), W16(0xFFCC), W16(0xFFE6), W16(0xFFF1), W16(0xFFF1), W16(0x0004), + W16(0xFFFD), W16(0x0000), W16(0xFFCA), W16(0xFF9C), W16(0xFFE5), W16(0xFFFD), W16(0xFFF9), W16(0x0025), + W16(0x0023), W16(0xFFBA), W16(0xFFDC), W16(0x003F), W16(0x0039), W16(0xFFE2), W16(0x0027), W16(0xFFEA), + W16(0xFFDC), W16(0x0035), W16(0x0008), W16(0xFFF6), W16(0x0012), W16(0xFFE2), W16(0xFFAD), W16(0xFF94), + W16(0x002B), W16(0xFFE5), W16(0x0015), W16(0x001B), W16(0xFF94), W16(0xFFE8), W16(0xFFCE), W16(0x0023), + W16(0x002A), W16(0xFFF6), W16(0x0023), W16(0xFFD7), W16(0x0025), W16(0x0004), W16(0xFFE2), W16(0x0020), + W16(0x004F), W16(0x0026), W16(0xFFC5), W16(0xFFCE), W16(0xFFF7), W16(0x0012), W16(0x0018), W16(0x0019), + W16(0xFFFE), W16(0xFFCA), W16(0xFFFC), W16(0x0002), W16(0x0006), W16(0x002A), W16(0xFF55), W16(0x0006), + W16(0xFFEE), W16(0x0017), W16(0xFFE3), W16(0x0005), W16(0x0036), W16(0x003E), W16(0x000C), W16(0x000A), + W16(0xFFFD), W16(0x0017), W16(0x0022), W16(0x0013), W16(0xFFFF), W16(0xFFF6), W16(0xFFFE), W16(0x001A), + W16(0x0009), W16(0xFFEB), W16(0xFFE5), W16(0x0000), W16(0x0032), W16(0x0058), W16(0x0009), W16(0x0039), + W16(0xFFD0), W16(0xFFF7), W16(0xFFD8), W16(0xFFF0), W16(0x0014), W16(0xFFDC), W16(0xFFE1), W16(0x0009), + W16(0xFFCB), W16(0xFFD9), W16(0x0002), W16(0x000C), W16(0xFFF9), W16(0x000F), W16(0x003F), W16(0x0062), + W16(0x0013), W16(0x002F), W16(0x0028), W16(0xFFE9), W16(0x0030), W16(0x000D), W16(0xFFA7), W16(0x0000), + W16(0x000A), W16(0xFFED), W16(0xFFEB), W16(0x003F), W16(0xFFEE), W16(0xFFEB), W16(0x0014), W16(0x0029), + W16(0xFFE5), W16(0xFFF0), W16(0xFFB0), W16(0xFFCB), W16(0xFFD5), W16(0x0014), W16(0x0034), W16(0x003B), + W16(0xFFE9), W16(0x0059), W16(0xFFBC), W16(0xFFCD), W16(0x000C), W16(0xFFE6), W16(0x001F), W16(0x0013), + W16(0xFFE5), W16(0x0030), W16(0xFFFD), W16(0x0025), W16(0xFFD9), W16(0x0011), W16(0x002C), W16(0xFFAC), + W16(0xFFE2), W16(0x0014), W16(0xFFF0), W16(0xFFDA), W16(0xFFED), W16(0xFFFE), W16(0xFFFC), W16(0x0006), + W16(0xFFDE), W16(0xFFF0), W16(0xFFFB), W16(0x0001), W16(0x001D), W16(0xFFB6), W16(0xFFEF), W16(0x00CD), + W16(0xFF91), W16(0xFFD0), W16(0xFFCD), W16(0x0017), W16(0x0006), W16(0x0026), W16(0x0011), W16(0xFFF3), + W16(0xFFFD), W16(0x0005), W16(0xFFD7), W16(0xFFF7), W16(0xFFE7), W16(0xFFC3), W16(0xFFDB), W16(0xFFD3), + W16(0x0003), W16(0xFFE7), W16(0xFFD9), W16(0x0010), W16(0x0049), W16(0xFFF3), W16(0xFFFD), W16(0xFFB1), + W16(0x000B), W16(0x005E), W16(0x0030), W16(0xFF9D), W16(0xFFE3), W16(0x000F), W16(0xFFFB), W16(0xFFF3), + W16(0x0001), W16(0xFFFC), W16(0xFFF4), W16(0xFFEC), W16(0xFFEE), W16(0xFFF5), W16(0xFFEB), W16(0xFFFE), + W16(0x0049), W16(0x001E), W16(0x0011), W16(0xFFDF), W16(0xFFD5), W16(0x002C), W16(0xFFFD), W16(0xFFF8), + W16(0x0007), W16(0xFFBC), W16(0xFFD4), W16(0x0013), W16(0x0045), W16(0xFFDE), W16(0xFFFE), W16(0x0049), + W16(0xFFF6), W16(0xFFDC), W16(0xFFE6), W16(0x0000), W16(0xFFFA), W16(0xFFEF), W16(0xFFE3), W16(0xFFF1), + W16(0xFFE0), W16(0x000A), W16(0x0019), W16(0x0006), W16(0xFFF3), W16(0xFFFA), W16(0x000B), W16(0x002D), + W16(0x000E), W16(0x002A), W16(0x0015), W16(0xFFFC), W16(0xFFE9), W16(0xFFC0), W16(0x0034), W16(0xFFDF), + W16(0xFFD7), W16(0xFFF3), W16(0x0017), W16(0x000F), W16(0xFFAC), W16(0xFFEF), W16(0x0101), W16(0xFF60), + W16(0xFFE0), W16(0xFFBD), W16(0x0040), W16(0xFFEB), W16(0xFFFF), W16(0xFFE2), W16(0xFFD5), W16(0xFFE1), + W16(0xFFFA), W16(0xFFF7), W16(0xFFF4), W16(0x0003), W16(0xFFFE), W16(0xFFCA), W16(0x0004), W16(0x0097), + W16(0x001E), W16(0xFF9B), W16(0xFFE6), W16(0x0093), W16(0x0033), W16(0x006E), W16(0xFFFB), W16(0xFFBF), + W16(0x0036), W16(0xFFFE), W16(0x002B), W16(0x0004), W16(0x001A), W16(0x005D), W16(0x0027), W16(0xFFF2), + W16(0x0013), W16(0x0013), W16(0x000F), W16(0x0000), W16(0xFFD8), W16(0xFFB8), W16(0xFFD8), W16(0x0002), + W16(0xFFD2), W16(0x0004), W16(0xFFF1), W16(0xFFD9), W16(0x002C), W16(0x006B), W16(0x0016), W16(0xFF7E), + W16(0xFFFE), W16(0xFFFE), W16(0xFFEB), W16(0x000B), W16(0x000F), W16(0x006C), W16(0x000A), W16(0xFF8A), + W16(0xFFBB), W16(0xFFF3), W16(0xFFE8), W16(0xFFDF), W16(0x0055), W16(0x0037), W16(0xFFE0), W16(0xFFE8), + W16(0x0028), W16(0x000A), W16(0x0005), W16(0xFFDF), W16(0x001B), W16(0x0016), W16(0x0015), W16(0x001D), + W16(0xFFFC), W16(0xFFBA), W16(0x0016), W16(0xFFE0), W16(0x001E), W16(0xFFD4), W16(0xFFF6), W16(0xFFE0), + W16(0xFFA2), W16(0xFFF7), W16(0x0018), W16(0x0012), W16(0x0056), W16(0x0032), W16(0x001A), W16(0xFFEB), + W16(0xFFE7), W16(0x0021), W16(0xFFFE), W16(0x001F), W16(0x000E), W16(0x0016), W16(0x0007), W16(0x0011), + W16(0x0008), W16(0xFFF2), W16(0xFFC4), W16(0x0039), W16(0x0003), W16(0xFFFB), W16(0x0008), W16(0xFF8E), + W16(0x0027), W16(0xFFEA), W16(0x0021), W16(0x0041), W16(0xFFF2), W16(0xFFE4), W16(0x0018), W16(0x0005), + W16(0x0006), W16(0x000E), W16(0xFFEB), W16(0xFFDA), W16(0x0009), W16(0x0019), W16(0x002C), W16(0x004F), + W16(0x0077), W16(0xFFEC), W16(0xFFE6), W16(0xFFF4), W16(0xFFF6), W16(0x000D), W16(0x001C), W16(0xFFE2), + W16(0x0030), W16(0x0035), W16(0x0004), W16(0xFFF5), W16(0x001F), W16(0x003C), W16(0xFFD0), W16(0xFFC4), + W16(0xFFB1), W16(0x0000), W16(0xFFF9), W16(0xFFF5), W16(0xFFEB), W16(0xFFF8), W16(0xFFF8), W16(0xFFFB), + W16(0x0023), W16(0xFF64), W16(0x002A), W16(0x0001), W16(0x0004), W16(0x0030), W16(0x0004), W16(0xFFD9), + W16(0x001B), W16(0xFFDF), W16(0xFFF9), W16(0x0022), W16(0x0011), W16(0xFFE4), W16(0xFFE1), W16(0xFFE2), + W16(0x0023), W16(0x0014), W16(0x0025), W16(0xFFF3), W16(0xFFEA), W16(0xFFEB), W16(0xFFED), W16(0xFFF5), + W16(0x004C), W16(0xFFDE), W16(0xFFE9), W16(0x0024), W16(0x0073), W16(0xFFEB), W16(0xFFCA), W16(0x0018), + W16(0x0024), W16(0xFFE8), W16(0x0022), W16(0xFFD7), W16(0xFFD6), W16(0xFFFE), W16(0xFFE4), W16(0xFFFB), + W16(0x0009), W16(0xFFDF), W16(0x000D), W16(0x0008), W16(0x0012), W16(0x000C), W16(0x0012), W16(0x0019), + W16(0xFFC4), W16(0x005D), W16(0x001A), W16(0x004E), W16(0x0030), W16(0x0028), W16(0xFFFA), W16(0xFFE7), + W16(0xFFD3), W16(0xFFE7), W16(0x001A), W16(0x000C), W16(0xFFCB), W16(0xFFD8), W16(0x0013), W16(0x0011), + W16(0x001F), W16(0x003A), W16(0x0019), W16(0x0006), W16(0xFFF2), W16(0xFFFE), W16(0x000C), W16(0x0019), + W16(0xFFFF), W16(0x0027), W16(0xFF96), W16(0x0023), W16(0xFFFA), W16(0x002D), W16(0xFFC5), W16(0x0037), + W16(0x000B), W16(0xFFD5), W16(0x0027), W16(0xFFF7), W16(0x0007), W16(0x001C), W16(0xFFF4), W16(0xFFDB), + W16(0xFFEE), W16(0x0015), W16(0xFFF9), W16(0xFFF6), W16(0xFFE9), W16(0xFFE9), W16(0xFFFF), W16(0x0027), + W16(0x004C), W16(0x0038), W16(0xFFBB), W16(0xFFF4), W16(0x000E), W16(0xFFA5), W16(0xFFD7), W16(0xFFF3), + W16(0xFFE5), W16(0xFFFA), W16(0x0015), W16(0x0046), W16(0x0023), W16(0xFFFA), W16(0xFFED), W16(0x0010), + W16(0x0030), W16(0x0025), W16(0x003E), W16(0x0006), W16(0xFFD6), W16(0xFFDE), W16(0xFFEE), W16(0x0006), + W16(0x0002), W16(0x001D), W16(0xFFC3), W16(0x000D), W16(0xFFFD), W16(0x0008), W16(0x0053), W16(0xFFD9), + W16(0xFFA1), W16(0xFF9C), W16(0x004A), W16(0x0032), W16(0xFFB5), W16(0x0050), W16(0xFFF1), W16(0x000E), + W16(0x0013), W16(0xFFD6), W16(0xFFFA), W16(0xFFF4), W16(0xFFFE), W16(0xFFE9), W16(0xFFCD), W16(0xFFC4), + W16(0x002E), W16(0x001B), W16(0x0026), W16(0xFFC8), W16(0x001D), W16(0xFFA0), W16(0x0026), W16(0x0031), + W16(0x005B), W16(0x0017), W16(0xFFD8), W16(0x0004), W16(0x0003), W16(0xFFD6), W16(0xFFF9), W16(0xFFD2), + W16(0xFFFA), W16(0xFFEF), W16(0xFFF5), W16(0xFFF7), W16(0xFFEF), W16(0x000F), W16(0x0036), W16(0x004E), + W16(0xFFCD), W16(0x0006), W16(0x001E), W16(0x0007), W16(0x0024), W16(0x0000), W16(0x0012), W16(0x000B), + W16(0x0031), W16(0xFFFA), W16(0x0004), W16(0x004F), W16(0xFFB3), W16(0x0017), W16(0xFFCE), W16(0xFFDA), + W16(0xFFD0), W16(0xFFE6), W16(0xFFE6), W16(0x0039), W16(0x0044), W16(0x003F), W16(0x0024), W16(0x0014), + W16(0xFFF4), W16(0xFFE0), W16(0x0002), W16(0x0020), W16(0xFFD5), W16(0xFFE0), W16(0xFFF9), W16(0x0018), + W16(0x004A), W16(0x0032), W16(0xFF9D), W16(0x0010), W16(0xFFBA), W16(0x0019), W16(0x000B), W16(0x001F), + W16(0x0013), W16(0xFFFE), W16(0x0016), W16(0xFFFA), W16(0xFFF2), W16(0xFFED), W16(0xFFEA), W16(0xFFFD), + W16(0x0005), W16(0xFFE1), W16(0x0003), W16(0x0041), W16(0x000E), W16(0xFFF3), W16(0x0050), W16(0x002C), + W16(0xFFDC), W16(0xFFEE), W16(0x0002), W16(0xFF95), W16(0x001E), W16(0x0006), W16(0x0000), W16(0xFFFD), + W16(0x0002), W16(0x000F), W16(0x002E), W16(0x0041), W16(0x0008), W16(0xFFF4), W16(0xFFE4), W16(0xFFEF), + W16(0xFFC3), W16(0x001F), W16(0x0020), W16(0xFFFD), W16(0xFFEA), W16(0x0021), W16(0xFFEA), W16(0xFFEF), + W16(0xFFF4), W16(0x004B), W16(0x000F), W16(0xFFA9), W16(0x0058), W16(0xFFC5), W16(0xFFD5), W16(0x004C), + W16(0xFFE4), W16(0x003A), W16(0x0016), W16(0x000C), W16(0xFFED), W16(0x001D), W16(0x001E), W16(0x0017), + W16(0x0015), W16(0x007A), W16(0x001F), W16(0xFFDC), W16(0xFFEB), W16(0x0025), W16(0x0000), W16(0x000D), + W16(0x0031), W16(0x0001), W16(0xFFF5), W16(0xFFC2), W16(0xFFDF), W16(0xFFF7), W16(0xFFF7), W16(0x0004), + W16(0x002B), W16(0x0029), W16(0x0028), W16(0x0025), W16(0x001B), W16(0x0010), W16(0x000C), W16(0x0011), + W16(0xFFEE), W16(0x0062), W16(0x003D), W16(0x0058), W16(0x0031), W16(0xFFF5), W16(0x000E), W16(0x000D), + W16(0x000D), W16(0x0005), W16(0xFFEC), W16(0xFFF2), W16(0x0020), W16(0x001D), W16(0xFFB1), W16(0xFFEC), + W16(0xFFF4), W16(0xFFEB), W16(0xFFE7), W16(0xFFD8), W16(0xFFF3), W16(0xFFF0), W16(0xFFE2), W16(0xFFDC), + W16(0x0019), W16(0xFFBF), W16(0xFFF8), W16(0x0010), W16(0xFFF3), W16(0xFFE0), W16(0x0028), W16(0x0034), + W16(0xFFE6), W16(0x0016), W16(0x004D), W16(0x0000), W16(0xFFC6), W16(0xFFD8), W16(0xFFC6), W16(0x002E), + W16(0xFFF6), W16(0x0068), W16(0x002D), W16(0xFFE4), W16(0x0009), W16(0x002E), W16(0x0045), W16(0x0059), + W16(0x0013), W16(0x0009), W16(0x0031), W16(0x0012), W16(0x0041), W16(0x0003), W16(0x0009), W16(0xFFF9), + W16(0x0001), W16(0x0005), W16(0x0010), W16(0x0006), W16(0xFFFA), W16(0x0021), W16(0x001A), W16(0xFFE0), + W16(0xFF87), W16(0xFFC2), W16(0x00FF), W16(0xFFF1), W16(0x000C), W16(0x0020), W16(0xFFF1), W16(0x0033), + W16(0x002E), W16(0x0007), W16(0x0048), W16(0xFFA8), W16(0xFFFF), W16(0x003C), W16(0xFFE9), W16(0xFFCA), + W16(0xFFE5), W16(0x0023), W16(0xFFE6), W16(0x0048), W16(0xFFA2), W16(0x002F), W16(0x0011), W16(0xFFF0), + W16(0x0009), W16(0x0016), W16(0x002B), W16(0x002A), W16(0xFFCE), W16(0xFFDF), W16(0xFFC7), W16(0xFFC7), + W16(0xFFE0), W16(0x003A), W16(0x0040), W16(0x0013), W16(0xFF97), W16(0x000B), W16(0x0020), W16(0x001A), + W16(0xFFF6), W16(0xFFD8), W16(0x000C), W16(0x0064), W16(0x0024), W16(0xFFF9), W16(0xFFE1), W16(0xFFE1), + W16(0x0008), W16(0xFFFF), W16(0x0013), W16(0x001C), W16(0x0000), W16(0xFFEA), W16(0xFFEE), W16(0x0007), + W16(0x0042), W16(0xFFE7), W16(0xFFCB), W16(0x0004), W16(0xFFAD), W16(0x0010), W16(0x0001), W16(0x0019), + W16(0xFFD0), W16(0x0052), W16(0x000E), W16(0x000C), W16(0xFFF6), W16(0x0011), W16(0xFFE9), W16(0xFFE9), + W16(0x0013), W16(0xFFE4), W16(0x0014), W16(0x003B), W16(0x0033), W16(0x0034), W16(0x0030), W16(0x0030), + W16(0xFFD0), W16(0x002C), W16(0x0005), W16(0xFFF2), W16(0xFFF0), W16(0xFF90), W16(0xFFB8), W16(0xFFF6), + W16(0x0013), W16(0x001A), W16(0x0026), W16(0xFFFC), W16(0x000E), W16(0x0037), W16(0x0021), W16(0x000E), + W16(0x000E), W16(0x0010), W16(0x0029), W16(0x0020), W16(0x0025), W16(0x0026), W16(0x0033), W16(0x0038), + W16(0x0016), W16(0x000D), W16(0xFFD6), W16(0x002B), W16(0x000D), W16(0x0029), W16(0xFFF8), W16(0x000C), + W16(0x0027), W16(0x0008), W16(0xFFB4), W16(0x0012), W16(0x0016), W16(0xFFCF), W16(0xFFEF), W16(0xFFD4), + W16(0x0029), W16(0x0026), W16(0xFFF5), W16(0x00A4), W16(0x009C), W16(0xFE71), W16(0x003B), W16(0xFF88), + W16(0x0016), W16(0x000A), W16(0x0021), W16(0x0085), W16(0xFFE0), W16(0x0022), W16(0xFFB1), W16(0x000D), + W16(0xFFE9), W16(0x0000), W16(0x0017), W16(0x001A), W16(0x000A), W16(0x000F), W16(0x001A), W16(0xFFF8), + W16(0xFFFA), W16(0xFFCA), W16(0xFFCB), W16(0x0000), W16(0xFFE7), W16(0xFFDF), W16(0xFFD0), W16(0xFFE5), + W16(0x0052), W16(0x0028), W16(0xFFCD), W16(0xFFE0), W16(0x000D), W16(0xFFD1), W16(0x0016), W16(0x001F), + W16(0xFFE1), W16(0xFFDC), W16(0xFFF4), W16(0xFFD9), W16(0xFFE3), W16(0x0048), W16(0x001D), W16(0x0004), + W16(0x0017), W16(0x0009), W16(0xFFAA), W16(0xFFAD), W16(0x0093), W16(0x005D), W16(0x0023), W16(0x008B), + W16(0x0035), W16(0x001A), W16(0x008C), W16(0xFFD3), W16(0x001B), W16(0xFFF8), W16(0x000A), W16(0x001D), + W16(0xFFA4), W16(0xFFFC), W16(0x0037), W16(0xFFFA), W16(0xFFE3), W16(0xFFDA), W16(0x0008), W16(0x0011), + W16(0x0020), W16(0xFFEE), W16(0xFFF0), W16(0xFFD9), W16(0xFFEE), W16(0xFFF2), W16(0xFFE8), W16(0x0010), + W16(0x0043), W16(0x0017), W16(0x0077), W16(0x0038), W16(0xFFF2), W16(0xFFF0), W16(0xFFEC), W16(0xFFC5), + W16(0x0026), W16(0x0007), W16(0x0022), W16(0xFFEB), W16(0xFFFA), W16(0x0012), W16(0x000F), W16(0x0016), + W16(0x0002), W16(0xFFE9), W16(0xFFF4), W16(0x0015), W16(0x0008), W16(0x001D), W16(0x003B), W16(0x0044), + W16(0x0025), W16(0xFFEB), W16(0x0026), W16(0x002A), W16(0xFFDB), W16(0x0000), W16(0x0047), W16(0x0005), + W16(0x000E), W16(0xFFBA), W16(0xFF9B), W16(0x000E), W16(0x0007), W16(0x0052), W16(0x003F), W16(0x0004), + W16(0xFFCE), W16(0x0041), W16(0x002C), W16(0xFFF5), W16(0xFFDC), W16(0x000E), W16(0x0023), W16(0x002A), + W16(0xFFE0), W16(0xFFFA), W16(0x0013), W16(0x000F), W16(0x0001), W16(0xFFF3), W16(0x0019), W16(0x0003), + W16(0xFFDD), W16(0x0010), W16(0x0004), W16(0x0017), W16(0xFFBA), W16(0x002B), W16(0xFFF7), W16(0xFF9E), + W16(0x006E), W16(0xFFF2), W16(0x0013), W16(0xFFAC), W16(0x0037), W16(0x012C), W16(0xFFBB), W16(0xFFB8), + W16(0x002C), W16(0x001F), W16(0x0017), W16(0xFFFE), W16(0xFFCE), W16(0xFFF3), W16(0x001E), W16(0xFFC7), + W16(0xFFE3), W16(0x0038), W16(0xFFD2), W16(0x0010), W16(0x0025), W16(0xFFD2), W16(0x0035), W16(0x0012), + W16(0x001F), W16(0x0028), W16(0x0033), W16(0x003A), W16(0x0021), W16(0xFFE2), W16(0xFFB8), W16(0xFFAF) +}; + +const Word16 cdk_37bits_6_fx[1536] = +{ + W16(0x0003), W16(0xFFDA), W16(0x0007), W16(0x0012), W16(0x0022), W16(0xFFFC), W16(0x001A), W16(0x0047), + W16(0x001D), W16(0x0029), W16(0x0015), W16(0xFFF4), W16(0xFFE2), W16(0xFFC7), W16(0xFFD7), W16(0xFFDC), + W16(0xFFD6), W16(0xFFE8), W16(0xFFE9), W16(0xFFC5), W16(0xFFFA), W16(0x0002), W16(0x0019), W16(0x0032), + W16(0xFF9B), W16(0xFFEF), W16(0xFFDC), W16(0xFFDE), W16(0xFFF3), W16(0x0024), W16(0xFFE6), W16(0xFFCA), + W16(0xFFD9), W16(0x000B), W16(0x0009), W16(0x002B), W16(0xFFFB), W16(0x000A), W16(0xFFE1), W16(0xFFF7), + W16(0x0045), W16(0xFFE3), W16(0x0009), W16(0xFFF9), W16(0xFFD4), W16(0xFFDE), W16(0x001C), W16(0x0027), + W16(0xFFCC), W16(0xFFBD), W16(0xFFF8), W16(0xFFB6), W16(0x0017), W16(0x0015), W16(0x002B), W16(0xFFDC), + W16(0x0026), W16(0x001E), W16(0xFFCC), W16(0xFFF1), W16(0xFFD5), W16(0xFFF5), W16(0x0009), W16(0x000F), + W16(0xFFEA), W16(0xFFD5), W16(0xFFFD), W16(0x0018), W16(0xFFFF), W16(0xFFE9), W16(0xFFEA), W16(0x0000), + W16(0x000C), W16(0x002C), W16(0xFFCF), W16(0x0042), W16(0x001C), W16(0xFFF8), W16(0x0001), W16(0xFFDF), + W16(0xFFEE), W16(0x0014), W16(0x0030), W16(0xFFC4), W16(0x001C), W16(0x0013), W16(0xFFED), W16(0xFFF6), + W16(0x0003), W16(0xFFBD), W16(0xFFC7), W16(0xFFF4), W16(0x000A), W16(0xFFF4), W16(0xFFF5), W16(0xFFE4), + W16(0xFFF2), W16(0xFFD3), W16(0xFFE6), W16(0xFFEF), W16(0x0003), W16(0xFFE0), W16(0xFFCD), W16(0xFFF2), + W16(0x002D), W16(0xFFE1), W16(0x0061), W16(0xFFFF), W16(0xFFD0), W16(0xFFEB), W16(0xFFEA), W16(0x0024), + W16(0x0027), W16(0x000A), W16(0xFFE5), W16(0xFFCA), W16(0xFFE6), W16(0xFFEF), W16(0xFFF9), W16(0xFFE6), + W16(0xFFE1), W16(0x0000), W16(0xFFEB), W16(0x0011), W16(0xFFFA), W16(0xFFF0), W16(0x0024), W16(0x0018), + W16(0x0003), W16(0xFFE4), W16(0xFFF2), W16(0xFFF5), W16(0xFFEF), W16(0xFFE8), W16(0x000D), W16(0x0044), + W16(0xFFE4), W16(0xFFF9), W16(0xFFC7), W16(0xFFF8), W16(0xFF82), W16(0x00CE), W16(0xFFCF), W16(0x0030), + W16(0x0018), W16(0xFFAE), W16(0x0005), W16(0xFFC6), W16(0xFFBA), W16(0x0005), W16(0x0021), W16(0x000B), + W16(0xFFF5), W16(0xFFF4), W16(0x0005), W16(0x002F), W16(0xFFF4), W16(0xFFFB), W16(0xFFFE), W16(0x0004), + W16(0x0007), W16(0x0011), W16(0xFFF5), W16(0xFFE5), W16(0x0003), W16(0x001C), W16(0x003F), W16(0x0042), + W16(0xFFB1), W16(0xFFD1), W16(0x0012), W16(0xFFFB), W16(0x001F), W16(0xFFE4), W16(0x0016), W16(0xFFFF), + W16(0x0001), W16(0xFFFC), W16(0xFFF3), W16(0xFFB8), W16(0x001C), W16(0x0027), W16(0xFFFF), W16(0xFFEF), + W16(0x000F), W16(0x001C), W16(0x001B), W16(0xFFDA), W16(0x0008), W16(0x0003), W16(0x0018), W16(0x002B), + W16(0x0013), W16(0x0000), W16(0x0005), W16(0xFFF6), W16(0xFFF0), W16(0xFF94), W16(0x003D), W16(0x0003), + W16(0x0006), W16(0xFFFE), W16(0xFFFE), W16(0x0023), W16(0x0010), W16(0x000E), W16(0x0022), W16(0xFFDF), + W16(0xFFF7), W16(0xFFD6), W16(0xFFF5), W16(0xFFD2), W16(0xFFCA), W16(0xFFBC), W16(0xFFD7), W16(0xFFF2), + W16(0xFFD3), W16(0xFFF1), W16(0xFFB4), W16(0xFFEE), W16(0xFFCA), W16(0xFFCD), W16(0x000E), W16(0x0046), + W16(0x0001), W16(0xFFEB), W16(0x002D), W16(0x0005), W16(0x0001), W16(0x0011), W16(0xFFFC), W16(0x0007), + W16(0xFFE3), W16(0xFFDE), W16(0xFFF4), W16(0x0022), W16(0x0020), W16(0x000C), W16(0xFFF7), W16(0xFFE6), + W16(0xFFFA), W16(0xFFD0), W16(0x0004), W16(0x0004), W16(0xFFD6), W16(0x0004), W16(0xFFD3), W16(0x0012), + W16(0x001C), W16(0xFFA6), W16(0xFFCE), W16(0x0026), W16(0xFFF3), W16(0x004B), W16(0x002F), W16(0xFFFE), + W16(0x0021), W16(0xFFEE), W16(0xFFE8), W16(0x0008), W16(0x000E), W16(0x0002), W16(0x000C), W16(0xFFFC), + W16(0xFFDF), W16(0x003D), W16(0x0008), W16(0xFFB1), W16(0x0025), W16(0x0009), W16(0x001D), W16(0x0013), + W16(0xFFE9), W16(0xFFC5), W16(0xFFEF), W16(0x0006), W16(0x002C), W16(0x0018), W16(0x0014), W16(0xFFD7), + W16(0xFFD0), W16(0xFFDB), W16(0xFFEB), W16(0x0008), W16(0xFFE9), W16(0xFFF1), W16(0x0009), W16(0x0012), + W16(0x001A), W16(0xFFF4), W16(0xFFD3), W16(0xFFFB), W16(0xFFDF), W16(0x001B), W16(0x0004), W16(0xFFFD), + W16(0x0037), W16(0xFFE2), W16(0xFFF0), W16(0x0014), W16(0xFFF4), W16(0xFFF2), W16(0xFFF5), W16(0x000E), + W16(0xFFFF), W16(0xFFC4), W16(0x00C0), W16(0xFFAA), W16(0xFFBD), W16(0x0002), W16(0x001A), W16(0xFFCE), + W16(0x000E), W16(0xFFDE), W16(0xFF98), W16(0x0022), W16(0x0022), W16(0xFFFA), W16(0x0034), W16(0xFFF5), + W16(0x0013), W16(0xFFDB), W16(0xFFCF), W16(0x0003), W16(0xFFF3), W16(0xFFFB), W16(0x000C), W16(0xFFCE), + W16(0x0034), W16(0x0026), W16(0x0009), W16(0xFFF8), W16(0xFFE9), W16(0xFFE6), W16(0xFFF2), W16(0xFFFA), + W16(0xFFF6), W16(0x0002), W16(0xFFD7), W16(0x001A), W16(0x0007), W16(0x0004), W16(0xFFDC), W16(0xFFF3), + W16(0x0020), W16(0x0017), W16(0xFFD8), W16(0xFFF5), W16(0xFFC0), W16(0x006D), W16(0xFFDC), W16(0x0033), + W16(0xFFE6), W16(0xFFE3), W16(0xFFE1), W16(0xFFE2), W16(0x000C), W16(0x0019), W16(0x0026), W16(0x0023), + W16(0xFFDD), W16(0x0032), W16(0xFFFB), W16(0x0003), W16(0xFFD2), W16(0xFFDB), W16(0x001C), W16(0xFFF2), + W16(0xFFFD), W16(0x003B), W16(0xFFED), W16(0xFFF7), W16(0xFFD6), W16(0xFFB8), W16(0x0027), W16(0x003D), + W16(0x0037), W16(0x0003), W16(0xFFC9), W16(0xFFD7), W16(0x0021), W16(0x0011), W16(0x001E), W16(0xFFEA), + W16(0xFFEF), W16(0x001D), W16(0x0013), W16(0xFFEC), W16(0x0002), W16(0x0021), W16(0x0023), W16(0x003D), + W16(0xFFF4), W16(0xFFF0), W16(0xFFDD), W16(0x0008), W16(0x000F), W16(0xFFBF), W16(0xFFBA), W16(0xFFEF), + W16(0x003F), W16(0xFFE5), W16(0xFFF4), W16(0xFFFC), W16(0x000A), W16(0x000B), W16(0xFFFE), W16(0xFFD7), + W16(0xFFF7), W16(0x0013), W16(0xFFD5), W16(0xFFEA), W16(0xFFD1), W16(0x0025), W16(0xFFF1), W16(0xFFF8), + W16(0x000E), W16(0x004D), W16(0x0028), W16(0x0004), W16(0x001F), W16(0xFFEA), W16(0xFFD0), W16(0xFFCE), + W16(0xFFF1), W16(0xFFFF), W16(0xFFE6), W16(0xFFF1), W16(0xFFC9), W16(0xFFC2), W16(0xFFCC), W16(0xFFD9), + W16(0xFFFB), W16(0xFFC2), W16(0xFFFE), W16(0xFFE4), W16(0x0022), W16(0x0029), W16(0xFFF8), W16(0x0044), + W16(0xFFBD), W16(0xFFEE), W16(0xFFFF), W16(0xFFD1), W16(0xFFFF), W16(0x002C), W16(0xFFF2), W16(0xFFE4), + W16(0xFFFC), W16(0x000C), W16(0xFFE9), W16(0x001B), W16(0x0019), W16(0x0011), W16(0xFFF6), W16(0xFFC8), + W16(0xFFD8), W16(0x0018), W16(0xFFEE), W16(0xFFD1), W16(0x0042), W16(0xFFDE), W16(0x0031), W16(0xFFC4), + W16(0xFFFB), W16(0xFFEC), W16(0x002B), W16(0xFFF6), W16(0x000B), W16(0xFFEE), W16(0xFFCD), W16(0x003C), + W16(0xFFE2), W16(0xFFFE), W16(0x0006), W16(0xFFF5), W16(0xFFF9), W16(0xFFE4), W16(0xFFEA), W16(0xFFE3), + W16(0xFFD6), W16(0x0017), W16(0xFFFC), W16(0xFFEE), W16(0x0024), W16(0xFFF2), W16(0xFFEB), W16(0x0004), + W16(0x000E), W16(0xFFF3), W16(0x0021), W16(0xFFED), W16(0xFFD3), W16(0xFFFE), W16(0x003B), W16(0xFFDD), + W16(0x0006), W16(0x008A), W16(0xFF6E), W16(0x002F), W16(0x002E), W16(0x0020), W16(0x000F), W16(0xFFDB), + W16(0xFFFF), W16(0x0000), W16(0x0045), W16(0xFFF6), W16(0x0008), W16(0x003C), W16(0xFFE5), W16(0xFFF7), + W16(0xFFDD), W16(0xFFFD), W16(0xFFE8), W16(0xFFC4), W16(0xFFEE), W16(0x0000), W16(0x000D), W16(0x0028), + W16(0x0036), W16(0x0020), W16(0xFFDB), W16(0xFFB8), W16(0xFFDC), W16(0xFFEA), W16(0xFFF1), W16(0xFFE2), + W16(0xFFEE), W16(0x0014), W16(0x002C), W16(0xFFCD), W16(0xFFFB), W16(0x0018), W16(0xFFEE), W16(0x001D), + W16(0x0035), W16(0xFFDA), W16(0x0020), W16(0xFFEC), W16(0x0002), W16(0xFFFF), W16(0xFFB9), W16(0x002B), + W16(0xFFE1), W16(0xFFB9), W16(0xFFE5), W16(0x0007), W16(0x0001), W16(0x000A), W16(0x0025), W16(0x0027), + W16(0x0024), W16(0xFFA1), W16(0x0020), W16(0x001A), W16(0x0020), W16(0xFFFD), W16(0x0001), W16(0xFFDD), + W16(0xFFB9), W16(0x0008), W16(0xFFF3), W16(0x003F), W16(0x0004), W16(0x0012), W16(0xFFDE), W16(0x0026), + W16(0xFFF9), W16(0xFFEB), W16(0xFFFD), W16(0xFFFD), W16(0xFFF1), W16(0xFFF0), W16(0xFFEF), W16(0xFFCE), + W16(0x0002), W16(0xFFF6), W16(0xFFD5), W16(0x002D), W16(0x0014), W16(0x000B), W16(0x0050), W16(0xFFFB), + W16(0xFFC8), W16(0xFFF7), W16(0x0000), W16(0xFFF8), W16(0xFFD7), W16(0xFFE9), W16(0x0044), W16(0xFFFF), + W16(0xFFDC), W16(0xFFC0), W16(0x0010), W16(0x0016), W16(0xFFF1), W16(0x0003), W16(0x0011), W16(0x001F), + W16(0xFFD2), W16(0xFFE4), W16(0xFFDE), W16(0x0028), W16(0xFFE1), W16(0x0048), W16(0x001A), W16(0xFFED), + W16(0x0006), W16(0xFFE3), W16(0xFFD1), W16(0x0012), W16(0x002A), W16(0x0001), W16(0xFFF1), W16(0x001A), + W16(0xFFCE), W16(0x0007), W16(0xFFDA), W16(0xFFE4), W16(0x0034), W16(0xFFE1), W16(0xFFD0), W16(0xFFD2), + W16(0xFFD3), W16(0x0000), W16(0xFFF8), W16(0x0023), W16(0x001A), W16(0xFFD7), W16(0xFFC2), W16(0x0007), + W16(0x0027), W16(0x0035), W16(0xFFC3), W16(0x000D), W16(0x001A), W16(0xFFE5), W16(0x0033), W16(0xFFE6), + W16(0x0000), W16(0xFFCF), W16(0xFFFA), W16(0x0016), W16(0x000C), W16(0x0009), W16(0x001D), W16(0x0014), + W16(0x0014), W16(0x0015), W16(0x000F), W16(0xFFF3), W16(0xFFBB), W16(0x002B), W16(0x002F), W16(0xFFE4), + W16(0xFFF4), W16(0xFFEF), W16(0x004E), W16(0xFFCE), W16(0x0009), W16(0x0012), W16(0x0014), W16(0x0008), + W16(0xFFD1), W16(0x001C), W16(0x0010), W16(0xFFE0), W16(0xFFEE), W16(0xFFF1), W16(0x000C), W16(0x0004), + W16(0xFFA0), W16(0x0005), W16(0x0061), W16(0x000D), W16(0xFFE8), W16(0xFFFF), W16(0xFFF5), W16(0x0002), + W16(0xFFF2), W16(0x0003), W16(0x001F), W16(0x0020), W16(0x0006), W16(0x000D), W16(0xFFFF), W16(0xFFF3), + W16(0xFFE8), W16(0xFFFA), W16(0x0011), W16(0x000B), W16(0xFFE7), W16(0xFFDD), W16(0xFFDA), W16(0xFFC3), + W16(0x0013), W16(0x0022), W16(0xFFDA), W16(0x0002), W16(0xFFF1), W16(0x0049), W16(0xFFC8), W16(0x0025), + W16(0xFFBE), W16(0xFFF7), W16(0x001C), W16(0x002B), W16(0xFFC7), W16(0xFFEF), W16(0x0004), W16(0x002C), + W16(0xFFF7), W16(0xFFF3), W16(0xFFFB), W16(0x000B), W16(0x000A), W16(0xFFE8), W16(0xFFDF), W16(0xFFD2), + W16(0x002E), W16(0xFFEE), W16(0xFFFF), W16(0xFFEE), W16(0x003D), W16(0xFFE4), W16(0xFFE8), W16(0x002D), + W16(0x0000), W16(0x0015), W16(0x000C), W16(0xFFD1), W16(0xFFA8), W16(0xFFF7), W16(0x0011), W16(0x0015), + W16(0x0011), W16(0xFFF8), W16(0x0003), W16(0x0022), W16(0xFFD0), W16(0xFFC1), W16(0xFFC2), W16(0xFFD9), + W16(0x0006), W16(0x0016), W16(0xFFFB), W16(0xFF9E), W16(0xFFBD), W16(0xFFDF), W16(0xFFD1), W16(0x0019), + W16(0x000F), W16(0x0021), W16(0xFFE9), W16(0xFFF1), W16(0x0024), W16(0x0010), W16(0x0006), W16(0x0016), + W16(0x0021), W16(0x0014), W16(0x0017), W16(0x0016), W16(0x0002), W16(0xFFE5), W16(0xFFE0), W16(0xFFDD), + W16(0xFFE0), W16(0x0019), W16(0x0009), W16(0x0038), W16(0x0013), W16(0x0005), W16(0x0009), W16(0x0034), + W16(0x0024), W16(0xFFB7), W16(0xFFFD), W16(0x003C), W16(0xFFD1), W16(0xFFED), W16(0xFFFD), W16(0xFFEB), + W16(0xFFF1), W16(0x002C), W16(0x0031), W16(0xFFE2), W16(0xFFFD), W16(0xFFDA), W16(0xFFF5), W16(0x0001), + W16(0x0002), W16(0xFFE6), W16(0xFFDF), W16(0xFFDB), W16(0x0041), W16(0x000A), W16(0xFFD3), W16(0x0000), + W16(0x0021), W16(0x001C), W16(0xFFDC), W16(0x002A), W16(0x0012), W16(0xFFDF), W16(0xFFBD), W16(0x0001), + W16(0xFFF0), W16(0x003B), W16(0x0005), W16(0x0009), W16(0x0031), W16(0x0026), W16(0x001A), W16(0x0007), + W16(0x003C), W16(0xFFE4), W16(0x003E), W16(0xFFF5), W16(0x002C), W16(0xFFFB), W16(0x0024), W16(0xFFD0), + W16(0x001F), W16(0xFFD1), W16(0x0005), W16(0x0012), W16(0x0004), W16(0xFFCC), W16(0x001F), W16(0xFFF1), + W16(0xFFFE), W16(0xFFF4), W16(0xFFE6), W16(0x0020), W16(0xFFFD), W16(0xFFEA), W16(0xFFD6), W16(0xFFB7), + W16(0x0034), W16(0xFFDE), W16(0xFFC8), W16(0xFFBB), W16(0x0018), W16(0xFFFE), W16(0xFFC5), W16(0xFFDE), + W16(0x0010), W16(0xFFFB), W16(0x0013), W16(0xFFD3), W16(0x002C), W16(0x000E), W16(0x0032), W16(0x0002), + W16(0xFFEA), W16(0xFFDE), W16(0xFFD6), W16(0xFFEF), W16(0x0009), W16(0xFFFB), W16(0x0012), W16(0x001C), + W16(0x004A), W16(0xFFD8), W16(0x0012), W16(0x0013), W16(0xFFE1), W16(0xFFF3), W16(0xFFD0), W16(0xFFFB), + W16(0xFFEB), W16(0x001A), W16(0x004F), W16(0xFFF6), W16(0xFFE2), W16(0x001D), W16(0x003B), W16(0xFFBB), + W16(0x0022), W16(0x0016), W16(0x001D), W16(0xFFF7), W16(0xFFF3), W16(0x0000), W16(0x0007), W16(0x0003), + W16(0xFFE8), W16(0xFFFF), W16(0x000B), W16(0x0018), W16(0x0001), W16(0x002D), W16(0xFFE3), W16(0xFFEA), + W16(0xFFDD), W16(0x002D), W16(0x0008), W16(0xFFE3), W16(0x0031), W16(0x0029), W16(0x0000), W16(0xFFD6), + W16(0xFFDF), W16(0xFFE3), W16(0x0001), W16(0x0091), W16(0xFF6B), W16(0x0028), W16(0x0032), W16(0xFFF0), + W16(0x000B), W16(0xFFF6), W16(0x0011), W16(0x000E), W16(0xFFB0), W16(0x003F), W16(0x0007), W16(0x004A), + W16(0x0015), W16(0x0025), W16(0xFFCA), W16(0xFFD4), W16(0xFFE5), W16(0xFFF2), W16(0x0026), W16(0xFFFF), + W16(0xFFED), W16(0xFFFC), W16(0x0006), W16(0x0009), W16(0x000A), W16(0xFFF4), W16(0xFFFF), W16(0xFFFD), + W16(0x004B), W16(0x0013), W16(0xFFF7), W16(0x0009), W16(0x0021), W16(0x0000), W16(0x0015), W16(0x000D), + W16(0xFFD2), W16(0x002C), W16(0xFF9E), W16(0xFFED), W16(0x001E), W16(0x000D), W16(0x000D), W16(0xFFFE), + W16(0xFFFE), W16(0xFFF0), W16(0xFFF3), W16(0xFFF3), W16(0x0006), W16(0x000C), W16(0x0011), W16(0x0003), + W16(0x0026), W16(0x0047), W16(0xFFE0), W16(0xFFF6), W16(0xFFD5), W16(0xFFF6), W16(0xFFF4), W16(0xFFFC), + W16(0x0049), W16(0x001B), W16(0xFFDE), W16(0x0053), W16(0xFFE1), W16(0xFFF3), W16(0xFFF3), W16(0x0004), + W16(0xFFE5), W16(0xFFE4), W16(0xFFFD), W16(0x0013), W16(0xFFE9), W16(0x0005), W16(0xFFF0), W16(0xFFC2), + W16(0xFFFC), W16(0x000D), W16(0x0008), W16(0x0023), W16(0x002A), W16(0xFFCD), W16(0x0034), W16(0x0002), + W16(0xFFE5), W16(0x0032), W16(0x0036), W16(0x0011), W16(0x0006), W16(0xFFC8), W16(0xFFEE), W16(0xFFD7), + W16(0xFFE2), W16(0x0011), W16(0x001D), W16(0x0043), W16(0x002F), W16(0xFFF3), W16(0xFFE0), W16(0xFFD6), + W16(0xFFFC), W16(0x002B), W16(0x0000), W16(0x001E), W16(0x000D), W16(0x002E), W16(0xFFDF), W16(0x0006), + W16(0x000B), W16(0xFFE7), W16(0xFFEA), W16(0xFFF8), W16(0x000B), W16(0xFFDC), W16(0x004B), W16(0xFF7E), + W16(0x005D), W16(0xFFE1), W16(0xFFDF), W16(0xFFF9), W16(0x002E), W16(0xFFF6), W16(0xFFFE), W16(0x0027), + W16(0xFFEB), W16(0x0033), W16(0xFFC8), W16(0x0008), W16(0xFFE0), W16(0xFFEF), W16(0xFFF9), W16(0x0007), + W16(0xFFBB), W16(0x000D), W16(0xFFFF), W16(0x000D), W16(0x003E), W16(0x001F), W16(0x0014), W16(0xFFF6), + W16(0xFFF6), W16(0x003B), W16(0x001A), W16(0xFFD2), W16(0xFFE7), W16(0x0093), W16(0x0065), W16(0xFF85), + W16(0x0028), W16(0xFFCF), W16(0x0031), W16(0x0011), W16(0xFFF6), W16(0xFFE2), W16(0xFFFD), W16(0xFFFA), + W16(0x0003), W16(0x002F), W16(0xFFFB), W16(0xFFCB), W16(0x004A), W16(0x0012), W16(0xFFC6), W16(0xFFED), + W16(0x0029), W16(0xFFA8), W16(0x002F), W16(0x002C), W16(0x0013), W16(0xFFEF), W16(0xFFFD), W16(0x0004), + W16(0x0005), W16(0xFFD9), W16(0xFFD1), W16(0x000C), W16(0x0004), W16(0xFFF4), W16(0x0000), W16(0xFFF0), + W16(0x000F), W16(0xFFEB), W16(0x0029), W16(0x0019), W16(0x001D), W16(0x0022), W16(0xFFF5), W16(0xFFEF), + W16(0xFFBA), W16(0x0018), W16(0x0044), W16(0x002D), W16(0xFFD1), W16(0xFFA7), W16(0x0019), W16(0x0077), + W16(0xFFF4), W16(0x0056), W16(0x0010), W16(0x0017), W16(0x0014), W16(0x0019), W16(0x0015), W16(0xFFBF), + W16(0x001D), W16(0xFFFB), W16(0xFFD8), W16(0xFFEC), W16(0xFFEB), W16(0x000C), W16(0x002E), W16(0x0019), + W16(0xFFE5), W16(0xFFFB), W16(0x0021), W16(0x003B), W16(0x0022), W16(0xFFEE), W16(0xFFF2), W16(0xFFF2), + W16(0xFFFA), W16(0xFFF3), W16(0x000A), W16(0x0006), W16(0xFFF9), W16(0xFFEC), W16(0xFFF5), W16(0x0012), + W16(0xFFDD), W16(0xFFFD), W16(0x001F), W16(0x001A), W16(0x0037), W16(0xFF7C), W16(0x0024), W16(0x001C), + W16(0x000F), W16(0x0024), W16(0x0021), W16(0xFFD4), W16(0x0009), W16(0xFFF3), W16(0x0007), W16(0x0046), + W16(0xFFFF), W16(0x0015), W16(0x0002), W16(0x001C), W16(0xFFCE), W16(0xFFBC), W16(0x0023), W16(0xFFF2), + W16(0xFFF1), W16(0xFFD0), W16(0x001E), W16(0x001F), W16(0x0022), W16(0x0007), W16(0xFFDE), W16(0x001E), + W16(0x003F), W16(0x0009), W16(0x0020), W16(0x003E), W16(0x002F), W16(0x0028), W16(0x0035), W16(0x002D), + W16(0x000E), W16(0x0010), W16(0x002D), W16(0x0004), W16(0xFFDE), W16(0x0002), W16(0x0008), W16(0xFF95), + W16(0x000F), W16(0x002D), W16(0xFFF8), W16(0x003A), W16(0x002D), W16(0x0003), W16(0x0005), W16(0xFFEB), + W16(0xFFF5), W16(0xFFEF), W16(0xFFE0), W16(0x0003), W16(0x001F), W16(0x001B), W16(0x001C), W16(0x0017), + W16(0x0017), W16(0xFFFB), W16(0x0035), W16(0x001A), W16(0x003F), W16(0x0047), W16(0xFFD5), W16(0xFFEC), + W16(0x000E), W16(0x0005), W16(0xFFF6), W16(0x000A), W16(0xFFE4), W16(0x0020), W16(0x0004), W16(0xFFC5), + W16(0xFFD9), W16(0xFFDB), W16(0xFFFE), W16(0xFFE5), W16(0xFFF9), W16(0xFFF1), W16(0x000F), W16(0x001B), + W16(0x0006), W16(0x0052), W16(0x0025), W16(0xFFED), W16(0x001D), W16(0xFFEA), W16(0xFFE0), W16(0x0014), + W16(0xFFBF), W16(0x0042), W16(0x0025), W16(0x0004), W16(0xFFE4), W16(0x000B), W16(0xFFDE), W16(0x000B), + W16(0x0002), W16(0xFFF1), W16(0xFFEF), W16(0x0006), W16(0x0013), W16(0x0013), W16(0x0032), W16(0x0034), + W16(0x0028), W16(0x0016), W16(0x0017), W16(0xFFE7), W16(0x0025), W16(0xFFEF), W16(0x0009), W16(0xFFE8), + W16(0xFFEC), W16(0xFFC2), W16(0x002B), W16(0x0013), W16(0x0009), W16(0x004E), W16(0xFFC9), W16(0xFFC9), + W16(0x0027), W16(0x0040), W16(0xFFE6), W16(0xFFF6), W16(0x0000), W16(0x0007), W16(0xFFFE), W16(0xFFF3), + W16(0x0006), W16(0xFFEE), W16(0xFFF7), W16(0x0038), W16(0xFFFD), W16(0xFFF4), W16(0xFFE9), W16(0x000D), + W16(0xFFDE), W16(0xFFFD), W16(0xFFD1), W16(0x0010), W16(0xFFF1), W16(0x0006), W16(0xFFF2), W16(0x0033), + W16(0x0043), W16(0x000E), W16(0x0018), W16(0x0026), W16(0xFFF0), W16(0xFFA0), W16(0xFFB0), W16(0x00BF), + W16(0xFFF9), W16(0x0002), W16(0xFFFE), W16(0x0033), W16(0x0001), W16(0x0019), W16(0xFFD1), W16(0x000D), + W16(0x0016), W16(0xFFB4), W16(0xFFF4), W16(0xFFCA), W16(0x0046), W16(0x0002), W16(0x002A), W16(0x0010), + W16(0xFFFE), W16(0x0021), W16(0x0018), W16(0x0017), W16(0xFFF1), W16(0xFFE7), W16(0xFFF1), W16(0xFFF4), + W16(0x000D), W16(0xFFE0), W16(0x0019), W16(0x0015), W16(0x0006), W16(0xFFB4), W16(0xFFCB), W16(0x000E), + W16(0x0008), W16(0x0017), W16(0xFFF4), W16(0xFFF1), W16(0x0019), W16(0x000E), W16(0x0010), W16(0x0075), + W16(0xFFBD), W16(0x001F), W16(0x0012), W16(0xFFE7), W16(0x0025), W16(0x000A), W16(0xFFEC), W16(0xFFD9), + W16(0x0002), W16(0xFFF2), W16(0x0032), W16(0x0049), W16(0xFFDA), W16(0x000E), W16(0x0052), W16(0xFFD9), + W16(0x000D), W16(0x0006), W16(0x0006), W16(0xFFEF), W16(0xFFC3), W16(0x0020), W16(0xFFF4), W16(0xFFF0), + W16(0x001E), W16(0xFFFB), W16(0xFFF3), W16(0x000A), W16(0x000C), W16(0x000E), W16(0x0005), W16(0x000B), + W16(0xFFCF), W16(0xFFF1), W16(0xFFE8), W16(0x0019), W16(0xFFF4), W16(0x0043), W16(0xFFEF), W16(0xFFEF), + W16(0x003B), W16(0xFFF5), W16(0x0027), W16(0xFFDD), W16(0xFFE9), W16(0xFFD0), W16(0xFFEB), W16(0xFFF9), + W16(0x001B), W16(0x0003), W16(0x0033), W16(0x002A), W16(0x0049), W16(0x0024), W16(0x000F), W16(0xFFF8), + W16(0x0015), W16(0x0026), W16(0x0010), W16(0x000E), W16(0x0004), W16(0xFFDA), W16(0x0009), W16(0xFFF8), + W16(0x004F), W16(0x003C), W16(0xFFD9), W16(0xFFDE), W16(0xFFF3), W16(0x0012), W16(0xFFE9), W16(0xFFDE), + W16(0x0013), W16(0x0058), W16(0x0010), W16(0xFFF8), W16(0xFFEC), W16(0xFFEB), W16(0x0008), W16(0x001F), + W16(0x005B), W16(0x0043), W16(0xFFFA), W16(0x0028), W16(0xFFEC), W16(0xFFF8), W16(0xFFF9), W16(0x0044), + W16(0x0008), W16(0xFFE6), W16(0x000F), W16(0xFFF1), W16(0x0016), W16(0x0005), W16(0xFFF3), W16(0x0001), + W16(0xFFE4), W16(0xFFF3), W16(0xFFFC), W16(0xFFF7), W16(0x0015), W16(0xFFFC), W16(0xFFE2), W16(0xFFCD), + W16(0x0001), W16(0x0003), W16(0x006E), W16(0xFFEB), W16(0x0011), W16(0xFFC8), W16(0x0023), W16(0x0026), + W16(0xFFF9), W16(0x0000), W16(0xFFD4), W16(0x001A), W16(0x0010), W16(0xFFF0), W16(0xFFE0), W16(0x0029), + W16(0xFFEC), W16(0x0018), W16(0x0027), W16(0x0010), W16(0x0009), W16(0xFFFB), W16(0x0016), W16(0x0034), + W16(0x0041), W16(0x001F), W16(0xFFD6), W16(0xFFBD), W16(0x0011), W16(0x0026), W16(0x003B), W16(0xFFDE), + W16(0xFFD0), W16(0xFFEF), W16(0xFFE6), W16(0xFFF1), W16(0x000B), W16(0xFFF0), W16(0xFFE2), W16(0x001D), + W16(0x001F), W16(0x0038), W16(0x0028), W16(0x0005), W16(0xFFB6), W16(0xFFD4), W16(0x0013), W16(0x0007), + W16(0x0003), W16(0xFFF8), W16(0xFFFF), W16(0xFFDD), W16(0x0002), W16(0x0001), W16(0xFFFD), W16(0xFFD9), + W16(0xFFCE), W16(0x0003), W16(0xFFFE), W16(0x0007), W16(0xFFCF), W16(0x001B), W16(0x0049), W16(0x0026), + W16(0xFFF8), W16(0x0038), W16(0x0046), W16(0x0009), W16(0x006E), W16(0x0044), W16(0x0011), W16(0xFFFF), + W16(0x000F), W16(0x0003), W16(0x002A), W16(0x0001), W16(0xFFE9), W16(0xFFF7), W16(0xFFCF), W16(0x000F), + W16(0x0014), W16(0x0003), W16(0x0028), W16(0x0031), W16(0x0008), W16(0xFFF2), W16(0xFFF2), W16(0xFFE6), + W16(0x0001), W16(0x000E), W16(0xFFA6), W16(0xFFA6), W16(0x0081), W16(0x007A), W16(0xFFA0), W16(0x0023) +}; + +const Word16 * const cdk_37bits[] = { cdk_37bits_1_fx, cdk_37bits_2_fx, cdk_37bits_3_fx, cdk_37bits_4_fx, + cdk_37bits_5_fx, cdk_37bits_6_fx + }; + +const Word16 *lsf_means[2] = { means_wb_31bits_ma_lsf, means_nb_31bits_ma_lsf }; + + +const lsp_unw_triplet p16_gamma0_92to1[16] = /* Q14 */ +{ + { 0, 19622, -9695 }, + { -14938, 29357, -13258 }, + { -8483, 23708, -13414 }, + { -7350, 22410, -12305 }, + { -7397, 21417, -12160 }, + { -7071, 19878, -11229 }, + { -7144, 19877, -11326 }, + { -6423, 17194, -9613 }, + { -7407, 18024, -9695 }, + { -6972, 16339, -8191 }, + { -8220, 17625, -8422 }, + { -8159, 17459, -8289 }, + { -8700, 19066, -9508 }, + { -7986, 17629, -8607 }, + { -8503, 17203, -8109 }, + { -7820, 14903, 0 } +}; + +const lsp_unw_triplet p16_gamma0_94to1[16] = /* Q14 */ +{ + { 0, 12931, -6314 }, + { -9364, 19577, -8870 }, + { -5512, 16236, -9305 }, + { -4892, 15366, -8398 }, + { -4869, 14631, -8275 }, + { -4631, 13358, -7540 }, + { -4575, 13271, -7599 }, + { -4151, 11403, -6385 }, + { -4859, 11947, -6371 }, + { -4504, 10805, -5407 }, + { -5346, 11618, -5515 }, + { -5418, 11578, -5424 }, + { -5806, 12711, -6226 }, + { -5205, 11592, -5606 }, + { -5745, 11498, -5188 }, + { -5473, 10245, 0 } +}; + + +/*Frame size config table*/ +const FrameSizeParams FrameSizeConfig[FRAME_SIZE_NB] = +{ + /* bits, net bits, trans_bits, trans_mode, band_bits, band_mode_min, band_mode_max, reserved_bits */ + { FRAME_0, FRAME_0, 0, {0,0}, 0, 0, 0, 0}, /* 0 kbps ZERO_FRAME*/ + { FRAME_2_4, FRAME_2_4-2, 1, {1,1}, 1, NB, WB, 0}, /* 2.8kbps VBR(SID)*/ + { FRAME_7_2, FRAME_7_2-1, 0, {0,1}, 1, NB, WB, 0}, /* 7.2kbps VBR/CBR*/ + { FRAME_8, FRAME_8-1, 0, {0,1}, 1, NB, WB, 0}, /* 8 kbps VBR/CBR*/ + { FRAME_9_6, FRAME_9_6-2, 0, {0,1}, 2, NB, SWB, 0}, /* 9.6kbps CBR*/ + { FRAME_13_2, FRAME_13_2-2, 0, {0,1}, 2, NB, SWB, 0}, /* 13.2kbps CBR*/ + { FRAME_16_4, FRAME_16_4-3, 0, {0,1}, 2, NB, FB, 1}, /* 16.4kbps CBR*/ + { FRAME_24_4, FRAME_24_4-3, 0, {0,1}, 2, NB, FB, 1}, /* 24.4kbps CBR*/ + { FRAME_32, FRAME_32-3, 0, {0,1}, 2, WB, FB, 1}, /* 32 kbps CBR*/ + { FRAME_48, FRAME_48-3, 0, {0,1}, 2, WB, FB, 1}, /* 48 kbps CBR*/ + { FRAME_64, FRAME_64-3, 0, {0,1}, 2, WB, FB, 1}, /* 64 kbps CBR*/ + { FRAME_96, FRAME_96-3, 0, {0,1}, 2, WB, FB, 1}, /* 96 kbps CBR*/ + { FRAME_128, FRAME_128-3, 0, {0,1}, 2, WB, FB, 1} /*128 kbps CBR*/ +}; + + +/*===OUTER LOOP 0===*/ +/*./genari 64 -1 ../histo/histo_s17_LC_rate_2*/ +/*limit_tns:-1.00*/ +/* +Entropy: +Entropy full mem.: 2.4198 bit (100.00 %) +Entropy no mem. : 3.2222 bit (133.16 %) +Entropy clustered : : 2.4227 bit (100.12 %) +Perf. clustered and mapped : : 2.4321 bit (100.51 %) +*/ +/*Total states: 398*/ +/*Proba models: 64*/ +/*Tables size: 1535.8 of 32 bits words*/ +/*Perf. clustered and mapped : : 2.4318 bit (100.50 %)*/ + +Word8 const ari_lookup_s17_LC[4096] = +{ + 0x01,0x04,0x29,0x13,0x0A,0x0D,0x05,0x10, + 0x10,0x0D,0x00,0x0D,0x2A,0x2A,0x22,0x25, + 0x25,0x28,0x2B,0x2E,0x31,0x34,0x34,0x0E, + 0x21,0x21,0x21,0x36,0x38,0x38,0x36,0x10, + 0x10,0x08,0x09,0x0B,0x0C,0x0E,0x0E,0x21, + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x10, + 0x10,0x1A,0x09,0x1D,0x0C,0x20,0x20,0x21, + 0x36,0x36,0x36,0x36,0x36,0x0A,0x36,0x16, + 0x1A,0x1A,0x2D,0x0C,0x20,0x20,0x21,0x21, + 0x21,0x36,0x38,0x38,0x38,0x38,0x36,0x16, + 0x16,0x1A,0x3F,0x1F,0x20,0x21,0x24,0x06, + 0x36,0x36,0x36,0x38,0x00,0x0A,0x36,0x22, + 0x3E,0x3E,0x3F,0x30,0x20,0x21,0x06,0x06, + 0x06,0x38,0x36,0x36,0x36,0x26,0x36,0x1C, + 0x1C,0x3E,0x3F,0x02,0x20,0x21,0x06,0x36, + 0x36,0x38,0x0A,0x0A,0x0A,0x0A,0x05,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x3F,0x3F,0x0E,0x35,0x14,0x38,0x38, + 0x05,0x05,0x05,0x0D,0x13,0x13,0x1C,0x16, + 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, + 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, + 0x3F,0x3F,0x3F,0x20,0x35,0x14,0x27,0x38, + 0x38,0x0A,0x2A,0x2A,0x2A,0x16,0x05,0x10, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x3F,0x02,0x0E,0x02,0x14,0x13,0x0A, + 0x0D,0x0D,0x0D,0x13,0x00,0x00,0x16,0x19, + 0x19,0x3F,0x3F,0x02,0x02,0x14,0x38,0x36, + 0x0A,0x0A,0x0A,0x0D,0x0D,0x0D,0x1C,0x22, + 0x22,0x3F,0x3F,0x02,0x17,0x26,0x26,0x1C, + 0x1C,0x10,0x16,0x16,0x16,0x19,0x22,0x25, + 0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39, + 0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39, + 0x39,0x39,0x15,0x2C,0x2E,0x2E,0x2E,0x31, + 0x31,0x31,0x31,0x31,0x31,0x31,0x34,0x39, + 0x39,0x39,0x15,0x2C,0x2E,0x2E,0x0C,0x34, + 0x34,0x34,0x36,0x36,0x36,0x36,0x36,0x36, + 0x36,0x39,0x15,0x3C,0x2E,0x31,0x34,0x34, + 0x31,0x31,0x31,0x1F,0x1E,0x1E,0x1E,0x1E, + 0x1E,0x39,0x28,0x2C,0x2E,0x31,0x37,0x34, + 0x01,0x01,0x01,0x01,0x01,0x00,0x39,0x39, + 0x39,0x39,0x39,0x2C,0x2E,0x31,0x1E,0x34, + 0x34,0x35,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x39,0x39,0x3C,0x2E,0x03,0x07,0x34, + 0x34,0x0F,0x39,0x39,0x39,0x39,0x39,0x39, + 0x39,0x39,0x39,0x15,0x2B,0x31,0x1E,0x34, + 0x34,0x01,0x39,0x39,0x39,0x39,0x39,0x39, + 0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39, + 0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39, + 0x39,0x39,0x39,0x2C,0x39,0x2F,0x2E,0x2E, + 0x2E,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E, + 0x2E,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E, + 0x2E,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E, + 0x2E,0x39,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E, + 0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E, + 0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E, + 0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E, + 0x1E,0x1E,0x1E,0x1E,0x1E,0x0F,0x2E,0x2E, + 0x2E,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E,0x2E, + 0x2E,0x2E,0x39,0x15,0x39,0x39,0x39,0x39, + 0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39, + 0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39, + 0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x39, + 0x19,0x1C,0x16,0x22,0x22,0x25,0x25,0x25, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x3E,0x3E,0x2F,0x3D,0x21,0x36,0x38,0x05, + 0x0D,0x0D,0x0D,0x10,0x16,0x16,0x16,0x25, + 0x2D,0x2D,0x37,0x3D,0x33,0x38,0x05,0x0D, + 0x0D,0x10,0x16,0x16,0x16,0x16,0x16,0x25, + 0x2F,0x2F,0x30,0x12,0x06,0x05,0x0A,0x0D, + 0x0D,0x10,0x16,0x16,0x16,0x22,0x22,0x25, + 0x1F,0x1F,0x32,0x3B,0x29,0x0A,0x0A,0x10, + 0x16,0x16,0x16,0x16,0x22,0x22,0x22,0x25, + 0x02,0x02,0x14,0x29,0x05,0x0D,0x2A,0x10, + 0x16,0x16,0x16,0x22,0x22,0x22,0x22,0x25, + 0x35,0x35,0x14,0x29,0x0A,0x2A,0x2A,0x10, + 0x16,0x16,0x16,0x22,0x22,0x22,0x22,0x25, + 0x17,0x17,0x26,0x05,0x0D,0x10,0x10,0x16, + 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x25, + 0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26, + 0x26,0x26,0x26,0x26,0x26,0x26,0x26,0x26, + 0x26,0x26,0x26,0x1C,0x0D,0x16,0x16,0x16, + 0x22,0x22,0x22,0x22,0x22,0x22,0x25,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x26,0x1C,0x1C,0x10,0x16,0x16,0x22, + 0x22,0x22,0x22,0x22,0x22,0x25,0x25,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x1C,0x1C,0x1C,0x16,0x16,0x16,0x22, + 0x22,0x22,0x22,0x25,0x25,0x25,0x25,0x00, + 0x00,0x26,0x1C,0x1C,0x16,0x16,0x16,0x22, + 0x22,0x22,0x22,0x25,0x25,0x25,0x25,0x00, + 0x16,0x16,0x16,0x16,0x16,0x22,0x22,0x22, + 0x25,0x25,0x25,0x25,0x25,0x25,0x25,0x00, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15, + 0x15,0x15,0x3C,0x1E,0x0F,0x06,0x27,0x2A, + 0x2A,0x10,0x16,0x16,0x16,0x16,0x16,0x22, + 0x2C,0x2C,0x0B,0x37,0x23,0x27,0x13,0x2A, + 0x10,0x10,0x10,0x16,0x16,0x16,0x16,0x22, + 0x1B,0x1B,0x1D,0x0F,0x24,0x13,0x13,0x2A, + 0x00,0x10,0x16,0x16,0x16,0x16,0x16,0x22, + 0x1F,0x1F,0x03,0x24,0x07,0x0A,0x0A,0x10, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x22, + 0x22,0x35,0x06,0x27,0x13,0x2A,0x2A,0x10, + 0x16,0x16,0x16,0x16,0x16,0x22,0x22,0x22, + 0x22,0x06,0x27,0x27,0x13,0x2A,0x2A,0x10, + 0x16,0x16,0x16,0x16,0x16,0x16,0x22,0x22, + 0x22,0x05,0x0A,0x2A,0x2A,0x10,0x10,0x16, + 0x16,0x16,0x16,0x16,0x16,0x22,0x22,0x22, + 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, + 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, + 0x22,0x0D,0x2A,0x10,0x10,0x10,0x10,0x16, + 0x16,0x16,0x16,0x16,0x16,0x22,0x22,0x25, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0x16,0x16,0x16, + 0x16,0x16,0x16,0x22,0x22,0x22,0x22,0x25, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0x10,0x10,0x16,0x16,0x16,0x16, + 0x16,0x22,0x22,0x22,0x22,0x22,0x22,0x25, + 0x0D,0x0D,0x10,0x10,0x10,0x16,0x16,0x16, + 0x16,0x22,0x22,0x22,0x22,0x22,0x22,0x25, + 0x0D,0x0D,0x0D,0x0D,0x0D,0x10,0x10,0x16, + 0x16,0x16,0x16,0x22,0x22,0x22,0x22,0x25, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x11,0x11,0x3A,0x11,0x11,0x11,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x3A,0x11, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x11,0x3A,0x3A,0x3A,0x11, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x11,0x11,0x11,0x18, + 0x00,0x11,0x3A,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x11,0x11,0x11,0x18,0x18,0x18,0x18, + 0x18,0x25,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x3A,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x3A,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x18,0x18, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x18,0x18, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x18,0x18,0x18,0x18, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x11,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x11,0x11,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x11,0x11,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x11,0x11,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x11,0x11,0x11,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x18, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x3A,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x11,0x11,0x3A,0x11, + 0x11,0x3A,0x3A,0x3A,0x11,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x11,0x11,0x11,0x3A,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x18,0x3A,0x3A,0x11,0x11,0x11,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x11,0x11,0x11,0x3A,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x11,0x11,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x11,0x11,0x11,0x11,0x11,0x18, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x11,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x2A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x18, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x11,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x11, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A, + 0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A,0x3A + +}; + +UWord16 const ari_pk_s17_LC_ext[64][18] = +{ + { + 16384, 16368,16337,16231,16143,16115,16059,15916,15793,15710,15586,15472,15367,15302,15201,15107,15020, + 0 + }, + { + 16384, 8983, 8540, 8498, 8485, 4319, 3666, 3594, 3579, 2285, 1908, 1851, 1835, 1326, 1120, 1085, 1074, + 0 + }, + { + 16384, 12022,10039, 9520, 9346, 7347, 5335, 4648, 4382, 3815, 3083, 2728, 2562, 2363, 2050, 1869, 1777, + 0 + }, + { + 16384, 13429,11201,10562,10371, 8231, 5713, 4770, 4441, 3798, 2844, 2359, 2152, 1947, 1614, 1406, 1304, + 0 + }, + { + 16384, 13229,11403,10769,10529, 8415, 6431, 5645, 5311, 4448, 3547, 3176, 3001, 2617, 2181, 1984, 1886, + 0 + }, + { + 16384, 15168,13754,13120,12826,11553, 9705, 8723, 8227, 7675, 6762, 6180, 5842, 5585, 5141, 4816, 4607, + 0 + }, + { + 16384, 14625,12743,12034,11772,10059, 7706, 6652, 6223, 5594, 4594, 4023, 3742, 3501, 3089, 2818, 2664, + 0 + }, + { + 16384, 15275,13679,12951,12652,11158, 8852, 7652, 7121, 6406, 5242, 4542, 4196, 3894, 3398, 3063, 2864, + 0 + }, + { + 16384, 4860, 3338, 3214, 3193, 1428, 676, 571, 547, 356, 222, 189, 180, 139, 102, 89, 84, + 0 + }, + { + 16384, 8357, 5798, 5475, 5410, 3093, 1523, 1227, 1152, 849, 560, 470, 441, 370, 294, 261, 248, + 0 + }, + { + 16384, 15550,14350,13710,13387,12297,10541, 9493, 8929, 8354, 7371, 6696, 6299, 6008, 5491, 5107, 4856, + 0 + }, + { + 16384, 10346, 7298, 6933, 6865, 4052, 1863, 1471, 1381, 1055, 673, 536, 491, 429, 339, 293, 273, + 0 + }, + { + 16384, 11652, 8699, 8030, 7839, 5667, 3460, 2766, 2532, 2093, 1542, 1301, 1203, 1070, 893, 802, 759, + 0 + }, + { + 16384, 15639,14601,14037,13729,12847,11421,10520, 9978, 9521, 8720, 8136, 7750, 7493, 7033, 6676, 6426, + 0 + }, + { + 16384, 12427, 9590, 8715, 8386, 6641, 4708, 3886, 3515, 3071, 2490, 2198, 2052, 1886, 1670, 1549, 1478, + 0 + }, + { + 16384, 13605,10996,10363,10183, 7802, 5032, 4124, 3840, 3267, 2403, 1976, 1804, 1633, 1345, 1171, 1086, + 0 + }, + { + 16384, 15936,15224,14759,14464,13808,12678,11866,11331,10910,10150, 9549, 9122, 8853, 8352, 7938, 7626, + 0 + }, + { + 16384, 16383,16382,14829,14138,14137,14136,12895,12272,10935, 9788, 9082, 8674, 8073, 7508, 7118, 6867, + 0 + }, + { + 16384, 13888,11474,10840,10662, 8335, 5585, 4695, 4411, 3801, 2917, 2506, 2337, 2150, 1847, 1672, 1581, + 0 + }, + { + 16384, 15463,14162,13504,13196,11977,10063, 8978, 8429, 7811, 6768, 6088, 5705, 5406, 4882, 4504, 4266, + 0 + }, + { + 16384, 13764,11941,11367,11151, 9312, 7171, 6301, 5943, 5335, 4430, 3942, 3708, 3466, 3074, 2819, 2679, + 0 + }, + { + 16384, 5179, 3300, 3206, 3197, 1220, 374, 303, 293, 171, 81, 63, 59, 44, 29, 24, 22, + 0 + }, + { + 16384, 16026,15468,15096,14842,14329,13447,12790,12322,11985,11367,10860,10477,10248, 9811, 9443, 9148, + 0 + }, + { + 16384, 12809,11291,10848,10649, 8976, 7199, 6506, 6196, 5657, 4887, 4451, 4219, 3974, 3590, 3365, 3218, + 0 + }, + { + 16384, 16383,16382,15744,15348,15347,15346,14714,14288,13688,13097,12652,12328,11967,11584,11278,11045, + 0 + }, + { + 16384, 15415,14987,14866,14806,13751,13046,12818,12709,12187,11720,11527,11427,11096,10759,10601,10510, + 0 + }, + { + 16384, 5926, 4280, 4090, 4053, 2138, 1120, 947, 903, 632, 413, 353, 334, 264, 198, 174, 166, + 0 + }, + { + 16384, 9206, 6640, 6345, 6291, 3683, 1772, 1423, 1342, 1024, 652, 515, 467, 406, 314, 267, 245, + 0 + }, + { + 16384, 15086,13966,13505,13271,12238,10875,10157, 9763, 9331, 8629, 8155, 7845, 7608, 7198, 6892, 6670, + 0 + }, + { + 16384, 11427, 8599, 8132, 8027, 5406, 3012, 2429, 2270, 1823, 1244, 1006, 920, 814, 654, 564, 524, + 0 + }, + { + 16384, 11561, 8220, 7814, 7737, 4780, 2215, 1731, 1621, 1279, 830, 657, 599, 532, 424, 366, 339, + 0 + }, + { + 16384, 11649, 9374, 8867, 8724, 6398, 4154, 3470, 3253, 2718, 2010, 1695, 1570, 1412, 1172, 1042, 980, + 0 + }, + { + 16384, 13021,10503, 9726, 9443, 7520, 5271, 4369, 4016, 3495, 2741, 2365, 2181, 1990, 1719, 1561, 1478, + 0 + }, + { + 16384, 13815,11388,10605,10316, 8467, 6133, 5175, 4782, 4255, 3466, 3063, 2864, 2688, 2408, 2229, 2125, + 0 + }, + { + 16384, 16175,15807,15536,15338,15006,14402,13919,13549,13312,12871,12491,12182,12010,11681,11390,11143, + 0 + }, + { + 16384, 14310,12047,11336,11110, 9065, 6381, 5318, 4938, 4279, 3272, 2732, 2499, 2284, 1920, 1693, 1574, + 0 + }, + { + 16384, 14765,12824,12096,11834,10003, 7429, 6282, 5841, 5145, 4022, 3402, 3123, 2868, 2426, 2150, 2003, + 0 + }, + { + 16384, 16295,16127,15943,15802,15650,15360,15059,14816,14668,14401,14162,13954,13839,13634,13443,13275, + 0 + }, + { + 16384, 14182,12821,12340,12120,10698, 9040, 8284, 7908, 7378, 6549, 6053, 5772, 5520, 5080, 4785, 4597, + 0 + }, + { + 16384, 15164,13583,12892,12600,11161, 8997, 7888, 7386, 6744, 5673, 5015, 4673, 4391, 3898, 3555, 3349, + 0 + }, + { + 16384, 3758, 2571, 2481, 2467, 988, 478, 412, 397, 245, 154, 133, 127, 95, 69, 61, 58, + 0 + }, + { + 16384, 14805,13193,12553,12285,10706, 8596, 7623, 7178, 6542, 5563, 4996, 4703, 4426, 3967, 3662, 3482, + 0 + }, + { + 16384, 15787,14870,14320,14005,13147,11705,10747,10171, 9651, 8735, 8068, 7629, 7332, 6785, 6361, 6061, + 0 + }, + { + 16384, 7111, 4622, 4304, 4233, 2346, 1174, 938, 870, 659, 455, 389, 365, 316, 260, 236, 226, + 0 + }, + { + 16384, 7146, 4703, 4532, 4512, 2078, 740, 583, 556, 371, 201, 153, 141, 118, 87, 72, 66, + 0 + }, + { + 16384, 9593, 7184, 6853, 6790, 4144, 2206, 1832, 1745, 1320, 878, 741, 697, 599, 476, 424, 401, + 0 + }, + { + 16384, 9209, 5969, 5479, 5351, 3346, 1763, 1382, 1261, 1017, 733, 622, 578, 520, 446, 410, 392, + 0 + }, + { + 16384, 11324, 8681, 8252, 8159, 5450, 3114, 2606, 2473, 1987, 1412, 1211, 1142, 1017, 847, 765, 730, + 0 + }, + { + 16384, 12663,10073, 9527, 9392, 6827, 4204, 3489, 3286, 2713, 1966, 1666, 1554, 1400, 1172, 1051, 994, + 0 + }, + { + 16384, 10413, 7096, 6340, 6115, 4393, 2704, 2156, 1947, 1634, 1254, 1091, 1010, 925, 805, 742, 707, + 0 + }, + { + 16384, 13337,11073,10477,10306, 8045, 5534, 4705, 4438, 3804, 2942, 2530, 2360, 2164, 1850, 1668, 1574, + 0 + }, + { + 16384, 14323,12104,11391,11156, 9183, 6649, 5649, 5287, 4676, 3778, 3302, 3089, 2886, 2548, 2341, 2223, + 0 + }, + { + 16384, 11646, 8435, 7504, 7150, 5603, 3882, 3170, 2853, 2487, 2029, 1791, 1666, 1549, 1386, 1288, 1231, + 0 + }, + { + 16384, 13147,11339,10752,10524, 8775, 6682, 5776, 5398, 4813, 3908, 3406, 3154, 2933, 2554, 2310, 2176, + 0 + }, + { + 16384, 14551,12495,11707,11356, 9962, 8005, 7006, 6500, 6034, 5298, 4839, 4575, 4381, 4057, 3825, 3673, + 0 + }, + { + 16384, 12395, 9526, 9032, 8925, 6130, 3448, 2813, 2649, 2144, 1489, 1231, 1142, 1020, 836, 738, 694, + 0 + }, + { + 16384, 14921,13187,12475,12164,10758, 8775, 7752, 7257, 6727, 5864, 5306, 5004, 4777, 4393, 4119, 3942, + 0 + }, + { + 16384, 2151, 1301, 1276, 1274, 315, 84, 70, 68, 32, 14, 11, 10, 7, 4, 3, 2, + 0 + }, + { + 16384, 16383,16382,13774,13091,13090,13089,11287,10713, 7917, 6052, 5265, 4947, 4161, 3534, 3199, 3039, + 0 + }, + { + 16384, 14374,12331,11688,11474, 9505, 6993, 5998, 5634, 4991, 4008, 3498, 3265, 3036, 2658, 2417, 2285, + 0 + }, + { + 16384, 8798, 5867, 5626, 5593, 2841, 1038, 807, 765, 538, 302, 234, 215, 182, 139, 119, 111, + 0 + }, + { + 16384, 13325,10612,10015, 9860, 7343, 4583, 3802, 3571, 3023, 2269, 1945, 1817, 1670, 1440, 1309, 1243, + 0 + }, + { + 16384, 7741, 5790, 5571, 5528, 3110, 1698, 1464, 1409, 1034, 704, 613, 585, 487, 381, 342, 327, + 0 + }, + { + 16384, 9664, 7506, 7059, 6917, 4820, 3136, 2640, 2455, 2000, 1504, 1297, 1217, 1073, 896, 815, 777, + 0 + } +}; + + +const Word16 Tab_esc_nb[4] = { 0 << (NBITS_CONTEXT+NBITS_RATEQ), + 1 << (NBITS_CONTEXT+NBITS_RATEQ), + 2 << (NBITS_CONTEXT+NBITS_RATEQ), + 3 << (NBITS_CONTEXT+NBITS_RATEQ) + }; + +const Word16 qGains[2][1 << kTcxHmNumGainBits] = +{ + /* GC */ { 1536 /*0.75f Q11*/ }, + /* VC */ { 1229 /*0.6f Q11*/, 2867 /*1.4f Q11*/, 9216 /*4.5f Q11*/, 20480 /*10.0f Q11*/ } +}; + +const Word16 NumRatioBits[2][17] = +{ + /* NB */ + { + 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2 + , 2, 2, 2 + }, + + /* WB */ + { + 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4 + , 2, 2, 2 + } +}; + +/* 7Q8 */ +const Word16 Ratios_WB_2[32] = + /* 2 */ { 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632, 6144, 6656, 7168, 7680, 8192, 8704, 9216, 9728, 10240, 15360, 16384, 18432 }; +const Word16 Ratios_WB_3[32] = + /* 3 */ { 256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3584, 4096, 4608, 5120, 5632, 6144, 6656, 7168, 7680, 8192, 8704, 9216, 9728, 10240, 11264, 12288, 13824, 15360, 17408, 19968, 20480 }; +const Word16 Ratios_WB_4[32] = + /* 4 */ { 384, 512, 640, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3584, 4096, 4608, 5120, 5632, 6144, 6656, 7168, 7680, 8192, 8704, 9216, 9728, 10240, 10752, 11264, 12288, 13312, 13824, 17408 }; +const Word16 Ratios_WB_5[32] = + /* 5 */ { 256, 384, 512, 640, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4096, 4608, 5120, 5632, 6144, 6656, 7168, 7680, 8192, 8704, 9216, 10240, 11264, 12288, 13824 }; +const Word16 Ratios_WB_6[32] = + /* 6 */ { 256, 384, 512, 640, 768, 896, 1024, 1152, 1280, 1408, 1536, 1664, 1792, 1920, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4096, 4608, 5120, 5632, 6144, 6656, 7168, 8704, 10240, 10496 }; +const Word16 Ratios_WB_7[32] = + /* 7 */ { 256, 384, 512, 640, 768, 896, 1024, 1152, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4096, 4352, 4608, 4864, 5120, 5376, 5760, 6144, 6400, 6912, 7168, 7680, 8960 }; +const Word16 Ratios_WB_8[16] = + /* 8 */ { 128, 256, 384, 512, 640, 768, 896, 1024, 1152, 1280, 1408, 1536, 1792, 2048, 2304, 2560 }; +const Word16 Ratios_WB_9[16] = + /* 9 */ { 256, 512, 640, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3840, 4096, 4608, 6912 }; +const Word16 Ratios_WB_10[16] = + /* 10 */ { 256, 384, 512, 640, 768, 896, 1024, 1280, 1536, 2048, 2560, 3840, 4608, 5632, 6144, 6656 }; +const Word16 Ratios_WB_11[16] = + /* 11 */ { 256, 384, 512, 640, 768, 896, 1024, 1280, 1536, 2048, 2560, 3072, 3328, 3584, 4608, 5376 }; +const Word16 Ratios_WB_12[16] = + /* 12 */ { 128, 256, 384, 512, 640, 768, 1024, 1280, 1536, 2048, 2304, 2816, 3072, 3456, 4096, 5120 }; +const Word16 Ratios_WB_13[16] = + /* 13 */ { 128, 256, 384, 512, 640, 768, 1024, 1280, 1536, 1792, 2048, 2560, 2816, 3072, 3584, 5120 }; +const Word16 Ratios_WB_14[16] = + /* 14 */ { 128, 256, 384, 512, 640, 768, 1024, 1152, 1536, 1920, 2304, 2560, 3072, 3584, 3840, 4608 }; +const Word16 Ratios_WB_15[16] = + /* 15 */ { 128, 256, 320, 384, 448, 512, 640, 768, 896, 1024, 1152, 1280, 1536, 2048, 2304, 3584 }; +const Word16 Ratios_WB_16[4] = + /* 16 */ { 128, 256, 512, 1024 }; +const Word16 Ratios_WB_17[4] = + /* 17 */ { 256, 384, 512, 1024 }; +const Word16 Ratios_WB_18[4] = + /* 18 */ { 256, 512, 768, 1024 }; + +/******************************************************************************/ + +/* 7Q8 */ +const Word16 Ratios_NB_2[32] = + /* 2 */ { 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, 3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632, 5888, 6144, 6400, 6656, 6912, 7168, 7680, 8192, 8704, 9216, 9728, 10240 }; +const Word16 Ratios_NB_3[16] = + /* 3 */ { 128, 256, 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 4096, 5120, 6144, 7680 }; +const Word16 Ratios_NB_4[16] = + /* 4 */ { 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3584, 4096, 4608, 5120, 6144, 7680 }; +const Word16 Ratios_NB_5[16] = + /* 5 */ { 512, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3584, 4096, 4608, 5120, 6144, 7680 }; +const Word16 Ratios_NB_6[16] = + /* 6 */ { 512, 640, 768, 896, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3584, 4096, 4608, 5120 }; +const Word16 Ratios_NB_7[16] = + /* 7 */ { 256, 512, 640, 768, 1024, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3584, 4096, 4608, 5120 }; +const Word16 Ratios_NB_8[16] = + /* 8 */ { 256, 384, 512, 640, 768, 896, 1024, 1152, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 4096 }; +const Word16 Ratios_NB_9[8] = + /* 9 */ { 256, 512, 768, 1024, 1280, 1536, 2048, 2560 }; +const Word16 Ratios_NB_10[8] = + /* 10 */ { 256, 512, 768, 1024, 1280, 1536, 2048, 2560 }; +const Word16 Ratios_NB_11[8] = + /* 11 */ { 256, 384, 512, 768, 1024, 1280, 1536, 2048 }; +const Word16 Ratios_NB_12[8] = + /* 12 */ { 256, 512, 640, 768, 1024, 1280, 1536, 2048 }; +const Word16 Ratios_NB_13[4] = + /* 13 */ { 256, 512, 768, 1024 }; +const Word16 Ratios_NB_14[4] = + /* 14 */ { 256, 512, 1024, 1536 }; +const Word16 Ratios_NB_15[4] = + /* 15 */ { 256, 512, 768, 1024 }; +const Word16 Ratios_NB_16[4] = + /* 16 */ { 256, 384, 512, 1024 }; +const Word16 Ratios_NB_17[4] = + /* 17 */ { 256, 384, 512, 768 }; +const Word16 Ratios_NB_18[4] = + /* 18 */ { 128, 256, 512, 768 }; + +/******************************************************************************/ + +const Word16 *const Ratios[2][17] = +{ + /* NB */ + { + Ratios_NB_2, + Ratios_NB_3, + Ratios_NB_4, + Ratios_NB_5, + Ratios_NB_6, + Ratios_NB_7, + Ratios_NB_8, + Ratios_NB_9, + Ratios_NB_10, + Ratios_NB_11, + Ratios_NB_12, + Ratios_NB_13, + Ratios_NB_14, + Ratios_NB_15 + , Ratios_NB_16 + , Ratios_NB_17 + , Ratios_NB_18 + }, + + /* WB */ + { + Ratios_WB_2, + Ratios_WB_3, + Ratios_WB_4, + Ratios_WB_5, + Ratios_WB_6, + Ratios_WB_7, + Ratios_WB_8, + Ratios_WB_9, + Ratios_WB_10, + Ratios_WB_11, + Ratios_WB_12, + Ratios_WB_13, + Ratios_WB_14, + Ratios_WB_15 + , Ratios_WB_16 + , Ratios_WB_17 + , Ratios_WB_18 + } +}; + +/*tns_tabels.c*/ + +struct TnsParameters const tnsParametersIGF32kHz_LowBR[1] = +{ + { 600, 3, 237/*1.85f Q7*/, 2458/*0.075f Q15*/ } +}; + +struct TnsParameters const tnsParameters32kHz[2] = +{ + { 4500, 3, 173/*1.35f Q7*/, 983/*0.0300f Q15*/ }, + { 600, 1, 224/*1.75f Q7*/, 2048/*0.0625f Q15*/ } +}; + +struct TnsParameters const tnsParameters32kHz_grouped[2] = +{ + { 8400, 3, 176/*1.375f Q7*/, 1024/*0.03125f Q15*/ }, + { 800, 3, 176/*1.375f Q7*/, 1024/*0.03125f Q15*/ } +}; + + +/* Tuning for Wide Band 16kHz */ +struct TnsParameters const tnsParameters16kHz[1] = +{ + { 600, 3, 192/*1.5f Q7*/, 1638/*0.05f Q15*/ } +}; + +struct TnsParameters const tnsParameters16kHz_grouped[2] = +{ + { 4400, 3, 192/*1.5f Q7*/, 1638/*0.05f Q15*/ }, + { 800, 3, 192/*1.5f Q7*/, 1638/*0.05f Q15*/ } +}; + +struct TnsParameters const tnsParameters48kHz_grouped[2] = +{ + { 10400, 3, 176/*1.375f Q7*/, 1024/*0.03125f Q15*/ }, + { 800, 3, 176/*1.375f Q7*/, 1024/*0.03125f Q15*/ } +}; + +const Word16 tnsAcfWindow[TNS_MAX_FILTER_ORDER] = +{ + 32696/*0.997803f Q15*/, 32480/*0.991211f Q15*/, 32120/*0.980225f Q15*/, 31616/*0.964844f Q15*/, 30968/*0.945068f Q15*/, 30176/*0.920898f Q15*/, 29240/*0.892334f Q15*/, 28160/*0.859375f Q15*/ +}; + +/**********************************************************************/ +/* Definition of the mapping between TNS parameters and a bitstream */ +/**********************************************************************/ + +/* Helper structures for hufmann table coding */ +const Coding codesTnsCoeff0TCX20[] = +{ + { -8+INDEX_SHIFT, 609, 11 }, /* 01001100001 */ + { -7+INDEX_SHIFT, 305, 10 }, /* 0100110001 */ + { -6+INDEX_SHIFT, 77, 8 }, /* 01001101 */ + { -5+INDEX_SHIFT, 39, 7 }, /* 0100111 */ + { -4+INDEX_SHIFT, 8, 5 }, /* 01000 */ + { -3+INDEX_SHIFT, 21, 5 }, /* 10101 */ + { -2+INDEX_SHIFT, 11, 4 }, /* 1011 */ + { -1+INDEX_SHIFT, 3, 3 }, /* 011 */ + { 0+INDEX_SHIFT, 3, 2 }, /* 11 */ + { 1+INDEX_SHIFT, 0, 2 }, /* 00 */ + { 2+INDEX_SHIFT, 4, 3 }, /* 100 */ + { 3+INDEX_SHIFT, 5, 4 }, /* 0101 */ + { 4+INDEX_SHIFT, 20, 5 }, /* 10100 */ + { 5+INDEX_SHIFT, 18, 6 }, /* 010010 */ + { 6+INDEX_SHIFT, 153, 9 }, /* 010011001 */ + { 7+INDEX_SHIFT, 608, 11 } /* 01001100000 */ +}; + +const Coding codesTnsCoeff0TCX10[] = +{ + { -8+INDEX_SHIFT, 441, 9 }, /* 110111001 */ + { -7+INDEX_SHIFT, 111, 7 }, /* 1101111 */ + { -6+INDEX_SHIFT, 8, 4 }, /* 1000 */ + { -5+INDEX_SHIFT, 9, 4 }, /* 1001 */ + { -4+INDEX_SHIFT, 14, 4 }, /* 1110 */ + { -3+INDEX_SHIFT, 15, 4 }, /* 1111 */ + { -2+INDEX_SHIFT, 3, 3 }, /* 011 */ + { -1+INDEX_SHIFT, 5, 3 }, /* 101 */ + { 0+INDEX_SHIFT, 0, 2 }, /* 00 */ + { 1+INDEX_SHIFT, 2, 3 }, /* 010 */ + { 2+INDEX_SHIFT, 12, 4 }, /* 1100 */ + { 3+INDEX_SHIFT, 26, 5 }, /* 11010 */ + { 4+INDEX_SHIFT, 54, 6 }, /* 110110 */ + { 5+INDEX_SHIFT, 221, 8 }, /* 11011101 */ + { 6+INDEX_SHIFT, 881, 10 }, /* 1101110001 */ + { 7+INDEX_SHIFT, 880, 10 } /* 1101110000 */ +}; + +const Coding codesTnsCoeff1TCX20[] = +{ + { -8+INDEX_SHIFT, 30018, 15 }, /* 111010101000010 */ + { -7+INDEX_SHIFT, 30019, 15 }, /* 111010101000011 */ + { -6+INDEX_SHIFT, 7505, 13 }, /* 1110101010001 */ + { -5+INDEX_SHIFT, 3753, 12 }, /* 111010101001 */ + { -4+INDEX_SHIFT, 939, 10 }, /* 1110101011 */ + { -3+INDEX_SHIFT, 235, 8 }, /* 11101011 */ + { -2+INDEX_SHIFT, 28, 5 }, /* 11100 */ + { -1+INDEX_SHIFT, 6, 3 }, /* 110 */ + { 0+INDEX_SHIFT, 0, 1 }, /* 0 */ + { 1+INDEX_SHIFT, 2, 2 }, /* 10 */ + { 2+INDEX_SHIFT, 15, 4 }, /* 1111 */ + { 3+INDEX_SHIFT, 59, 6 }, /* 111011 */ + { 4+INDEX_SHIFT, 116, 7 }, /* 1110100 */ + { 5+INDEX_SHIFT, 468, 9 }, /* 111010100 */ + { 6+INDEX_SHIFT, 1877, 11 }, /* 11101010101 */ + { 7+INDEX_SHIFT, 15008, 14 } /* 11101010100000 */ +}; + +const Coding codesTnsCoeff1TCX10[] = +{ + { -8+INDEX_SHIFT, 2818, 12 }, /* 101100000010 */ + { -7+INDEX_SHIFT, 2819, 12 }, /* 101100000011 */ + { -6+INDEX_SHIFT, 705, 10 }, /* 1011000001 */ + { -5+INDEX_SHIFT, 353, 9 }, /* 101100001 */ + { -4+INDEX_SHIFT, 177, 8 }, /* 10110001 */ + { -3+INDEX_SHIFT, 45, 6 }, /* 101101 */ + { -2+INDEX_SHIFT, 10, 4 }, /* 1010 */ + { -1+INDEX_SHIFT, 3, 3 }, /* 011 */ + { 0+INDEX_SHIFT, 6, 3 }, /* 110 */ + { 1+INDEX_SHIFT, 0, 2 }, /* 00 */ + { 2+INDEX_SHIFT, 7, 3 }, /* 111 */ + { 3+INDEX_SHIFT, 4, 3 }, /* 100 */ + { 4+INDEX_SHIFT, 2, 3 }, /* 010 */ + { 5+INDEX_SHIFT, 23, 5 }, /* 10111 */ + { 6+INDEX_SHIFT, 89, 7 }, /* 1011001 */ + { 7+INDEX_SHIFT, 1408, 11 } /* 10110000000 */ +}; + +const Coding codesTnsCoeff2TCX20[] = +{ + { -8+INDEX_SHIFT, 13312, 14 }, /* 11010000000000 */ + { -7+INDEX_SHIFT, 13313, 14 }, /* 11010000000001 */ + { -6+INDEX_SHIFT, 3329, 12 }, /* 110100000001 */ + { -5+INDEX_SHIFT, 833, 10 }, /* 1101000001 */ + { -4+INDEX_SHIFT, 209, 8 }, /* 11010001 */ + { -3+INDEX_SHIFT, 53, 6 }, /* 110101 */ + { -2+INDEX_SHIFT, 12, 4 }, /* 1100 */ + { -1+INDEX_SHIFT, 2, 2 }, /* 10 */ + { 0+INDEX_SHIFT, 0, 1 }, /* 0 */ + { 1+INDEX_SHIFT, 7, 3 }, /* 111 */ + { 2+INDEX_SHIFT, 27, 5 }, /* 11011 */ + { 3+INDEX_SHIFT, 105, 7 }, /* 1101001 */ + { 4+INDEX_SHIFT, 417, 9 }, /* 110100001 */ + { 5+INDEX_SHIFT, 1665, 11 }, /* 11010000001 */ + { 6+INDEX_SHIFT, 13314, 14 }, /* 11010000000010 */ + { 7+INDEX_SHIFT, 13315, 14 } /* 11010000000011 */ +}; + +const Coding codesTnsCoeff2TCX10[] = +{ + { -8+INDEX_SHIFT, 512, 12 }, /* 001000000000 */ + { -7+INDEX_SHIFT, 513, 12 }, /* 001000000001 */ + { -6+INDEX_SHIFT, 65, 9 }, /* 001000001 */ + { -5+INDEX_SHIFT, 17, 7 }, /* 0010001 */ + { -4+INDEX_SHIFT, 5, 5 }, /* 00101 */ + { -3+INDEX_SHIFT, 0, 3 }, /* 000 */ + { -2+INDEX_SHIFT, 6, 3 }, /* 110 */ + { -1+INDEX_SHIFT, 1, 2 }, /* 01 */ + { 0+INDEX_SHIFT, 2, 2 }, /* 10 */ + { 1+INDEX_SHIFT, 7, 3 }, /* 111 */ + { 2+INDEX_SHIFT, 3, 4 }, /* 0011 */ + { 3+INDEX_SHIFT, 9, 6 }, /* 001001 */ + { 4+INDEX_SHIFT, 33, 8 }, /* 00100001 */ + { 5+INDEX_SHIFT, 129, 10 }, /* 0010000001 */ + { 6+INDEX_SHIFT, 514, 12 }, /* 001000000010 */ + { 7+INDEX_SHIFT, 515, 12 } /* 001000000011 */ +}; + +const Coding codesTnsCoeff3TCX20[] = +{ + { -8+INDEX_SHIFT, 13318, 14 }, /* 11010000000110 */ + { -7+INDEX_SHIFT, 13319, 14 }, /* 11010000000111 */ + { -6+INDEX_SHIFT, 6656, 13 }, /* 1101000000000 */ + { -5+INDEX_SHIFT, 1665, 11 }, /* 11010000001 */ + { -4+INDEX_SHIFT, 417, 9 }, /* 110100001 */ + { -3+INDEX_SHIFT, 105, 7 }, /* 1101001 */ + { -2+INDEX_SHIFT, 27, 5 }, /* 11011 */ + { -1+INDEX_SHIFT, 7, 3 }, /* 111 */ + { 0+INDEX_SHIFT, 0, 1 }, /* 0 */ + { 1+INDEX_SHIFT, 2, 2 }, /* 10 */ + { 2+INDEX_SHIFT, 12, 4 }, /* 1100 */ + { 3+INDEX_SHIFT, 53, 6 }, /* 110101 */ + { 4+INDEX_SHIFT, 209, 8 }, /* 11010001 */ + { 5+INDEX_SHIFT, 833, 10 }, /* 1101000001 */ + { 6+INDEX_SHIFT, 6657, 13 }, /* 1101000000001 */ + { 7+INDEX_SHIFT, 6658, 13 } /* 1101000000010 */ +}; + +const Coding codesTnsCoeff3TCX10[] = +{ + { -8+INDEX_SHIFT, 1284, 12 }, /* 010100000100 */ + { -7+INDEX_SHIFT, 1285, 12 }, /* 010100000101 */ + { -6+INDEX_SHIFT, 1286, 12 }, /* 010100000110 */ + { -5+INDEX_SHIFT, 1287, 12 }, /* 010100000111 */ + { -4+INDEX_SHIFT, 161, 9 }, /* 010100001 */ + { -3+INDEX_SHIFT, 41, 7 }, /* 0101001 */ + { -2+INDEX_SHIFT, 11, 5 }, /* 01011 */ + { -1+INDEX_SHIFT, 0, 2 }, /* 00 */ + { 0+INDEX_SHIFT, 2, 2 }, /* 10 */ + { 1+INDEX_SHIFT, 3, 2 }, /* 11 */ + { 2+INDEX_SHIFT, 3, 3 }, /* 011 */ + { 3+INDEX_SHIFT, 4, 4 }, /* 0100 */ + { 4+INDEX_SHIFT, 21, 6 }, /* 010101 */ + { 5+INDEX_SHIFT, 81, 8 }, /* 01010001 */ + { 6+INDEX_SHIFT, 640, 11 }, /* 01010000000 */ + { 7+INDEX_SHIFT, 641, 11 } /* 01010000001 */ +}; + +const Coding codesTnsCoeff4TCX20[] = +{ + { -8+INDEX_SHIFT, 13318, 14 }, /* 11010000000110 */ + { -7+INDEX_SHIFT, 13319, 14 }, /* 11010000000111 */ + { -6+INDEX_SHIFT, 6656, 13 }, /* 1101000000000 */ + { -5+INDEX_SHIFT, 833, 10 }, /* 1101000001 */ + { -4+INDEX_SHIFT, 209, 8 }, /* 11010001 */ + { -3+INDEX_SHIFT, 53, 6 }, /* 110101 */ + { -2+INDEX_SHIFT, 12, 4 }, /* 1100 */ + { -1+INDEX_SHIFT, 2, 2 }, /* 10 */ + { 0+INDEX_SHIFT, 0, 1 }, /* 0 */ + { 1+INDEX_SHIFT, 7, 3 }, /* 111 */ + { 2+INDEX_SHIFT, 27, 5 }, /* 11011 */ + { 3+INDEX_SHIFT, 105, 7 }, /* 1101001 */ + { 4+INDEX_SHIFT, 417, 9 }, /* 110100001 */ + { 5+INDEX_SHIFT, 1665, 11 }, /* 11010000001 */ + { 6+INDEX_SHIFT, 6657, 13 }, /* 1101000000001 */ + { 7+INDEX_SHIFT, 6658, 13 } /* 1101000000010 */ +}; + +const Coding codesTnsCoeff4TCX10[] = +{ + { -8+INDEX_SHIFT, 20, 12 }, /* 000000010100 */ + { -7+INDEX_SHIFT, 21, 12 }, /* 000000010101 */ + { -6+INDEX_SHIFT, 22, 12 }, /* 000000010110 */ + { -5+INDEX_SHIFT, 3, 9 }, /* 000000011 */ + { -4+INDEX_SHIFT, 1, 7 }, /* 0000001 */ + { -3+INDEX_SHIFT, 1, 5 }, /* 00001 */ + { -2+INDEX_SHIFT, 1, 3 }, /* 001 */ + { -1+INDEX_SHIFT, 2, 2 }, /* 10 */ + { 0+INDEX_SHIFT, 3, 2 }, /* 11 */ + { 1+INDEX_SHIFT, 1, 2 }, /* 01 */ + { 2+INDEX_SHIFT, 1, 4 }, /* 0001 */ + { 3+INDEX_SHIFT, 1, 6 }, /* 000001 */ + { 4+INDEX_SHIFT, 0, 8 }, /* 00000000 */ + { 5+INDEX_SHIFT, 23, 12 }, /* 000000010111 */ + { 6+INDEX_SHIFT, 8, 11 }, /* 00000001000 */ + { 7+INDEX_SHIFT, 9, 11 } /* 00000001001 */ +}; + +const Coding codesTnsCoeff5[] = +{ + { -8+INDEX_SHIFT, 6788, 13 }, /* 1101010000100 */ + { -7+INDEX_SHIFT, 6789, 13 }, /* 1101010000101 */ + { -6+INDEX_SHIFT, 6790, 13 }, /* 1101010000110 */ + { -5+INDEX_SHIFT, 849, 10 }, /* 1101010001 */ + { -4+INDEX_SHIFT, 213, 8 }, /* 11010101 */ + { -3+INDEX_SHIFT, 107, 7 }, /* 1101011 */ + { -2+INDEX_SHIFT, 27, 5 }, /* 11011 */ + { -1+INDEX_SHIFT, 7, 3 }, /* 111 */ + { 0+INDEX_SHIFT, 0, 1 }, /* 0 */ + { 1+INDEX_SHIFT, 2, 2 }, /* 10 */ + { 2+INDEX_SHIFT, 12, 4 }, /* 1100 */ + { 3+INDEX_SHIFT, 52, 6 }, /* 110100 */ + { 4+INDEX_SHIFT, 425, 9 }, /* 110101001 */ + { 5+INDEX_SHIFT, 6791, 13 }, /* 1101010000111 */ + { 6+INDEX_SHIFT, 3392, 12 }, /* 110101000000 */ + { 7+INDEX_SHIFT, 3393, 12 } /* 110101000001 */ +}; + +const Coding codesTnsCoeff6[] = +{ + { -8+INDEX_SHIFT, 4, 12 }, /* 000000000100 */ + { -7+INDEX_SHIFT, 5, 12 }, /* 000000000101 */ + { -6+INDEX_SHIFT, 6, 12 }, /* 000000000110 */ + { -5+INDEX_SHIFT, 1, 9 }, /* 000000001 */ + { -4+INDEX_SHIFT, 1, 7 }, /* 0000001 */ + { -3+INDEX_SHIFT, 1, 5 }, /* 00001 */ + { -2+INDEX_SHIFT, 1, 3 }, /* 001 */ + { -1+INDEX_SHIFT, 2, 2 }, /* 10 */ + { 0+INDEX_SHIFT, 3, 2 }, /* 11 */ + { 1+INDEX_SHIFT, 1, 2 }, /* 01 */ + { 2+INDEX_SHIFT, 1, 4 }, /* 0001 */ + { 3+INDEX_SHIFT, 1, 6 }, /* 000001 */ + { 4+INDEX_SHIFT, 1, 8 }, /* 00000001 */ + { 5+INDEX_SHIFT, 7, 12 }, /* 000000000111 */ + { 6+INDEX_SHIFT, 0, 11 }, /* 00000000000 */ + { 7+INDEX_SHIFT, 1, 11 } /* 00000000001 */ +}; + +const Coding codesTnsCoeff7[] = +{ + { -8+INDEX_SHIFT, 14, 11 }, /* 00000001110 */ + { -7+INDEX_SHIFT, 15, 11 }, /* 00000001111 */ + { -6+INDEX_SHIFT, 0, 10 }, /* 0000000000 */ + { -5+INDEX_SHIFT, 1, 10 }, /* 0000000001 */ + { -4+INDEX_SHIFT, 1, 7 }, /* 0000001 */ + { -3+INDEX_SHIFT, 1, 5 }, /* 00001 */ + { -2+INDEX_SHIFT, 1, 4 }, /* 0001 */ + { -1+INDEX_SHIFT, 1, 2 }, /* 01 */ + { 0+INDEX_SHIFT, 2, 10 }, /* 0000000010 */ + { 1+INDEX_SHIFT, 1, 1 }, /* 1 */ + { 2+INDEX_SHIFT, 1, 3 }, /* 001 */ + { 3+INDEX_SHIFT, 1, 6 }, /* 000001 */ + { 4+INDEX_SHIFT, 3, 10 }, /* 0000000011 */ + { 5+INDEX_SHIFT, 4, 10 }, /* 0000000100 */ + { 6+INDEX_SHIFT, 5, 10 }, /* 0000000101 */ + { 7+INDEX_SHIFT, 6, 10 } /* 0000000110 */ +}; + +const Coding codesTnsCoeff456[] = +{ + { -8+INDEX_SHIFT, 516, 12 }, /* 001000000100 */ + { -7+INDEX_SHIFT, 517, 12 }, /* 001000000101 */ + { -6+INDEX_SHIFT, 518, 12 }, /* 001000000110 */ + { -5+INDEX_SHIFT, 65, 9 }, /* 001000001 */ + { -4+INDEX_SHIFT, 17, 7 }, /* 0010001 */ + { -3+INDEX_SHIFT, 5, 5 }, /* 00101 */ + { -2+INDEX_SHIFT, 3, 4 }, /* 0011 */ + { -1+INDEX_SHIFT, 1, 2 }, /* 01 */ + { 0+INDEX_SHIFT, 3, 2 }, /* 11 */ + { 1+INDEX_SHIFT, 2, 2 }, /* 10 */ + { 2+INDEX_SHIFT, 0, 3 }, /* 000 */ + { 3+INDEX_SHIFT, 9, 6 }, /* 001001 */ + { 4+INDEX_SHIFT, 33, 8 }, /* 00100001 */ + { 5+INDEX_SHIFT, 519, 12 }, /* 001000000111 */ + { 6+INDEX_SHIFT, 256, 11 }, /* 00100000000 */ + { 7+INDEX_SHIFT, 257, 11 } /* 00100000001 */ +}; + +const Coding codesTnsCoeff0WBTCX20[] = +{ + { -8+INDEX_SHIFT, 225, 10 }, /* 0011100001 */ + { -7+INDEX_SHIFT, 113, 9 }, /* 001110001 */ + { -6+INDEX_SHIFT, 29, 7 }, /* 0011101 */ + { -5+INDEX_SHIFT, 15, 6 }, /* 001111 */ + { -4+INDEX_SHIFT, 2, 4 }, /* 0010 */ + { -3+INDEX_SHIFT, 0, 3 }, /* 000 */ + { -2+INDEX_SHIFT, 13, 4 }, /* 1101 */ + { -1+INDEX_SHIFT, 2, 3 }, /* 010 */ + { 0+INDEX_SHIFT, 5, 3 }, /* 101 */ + { 1+INDEX_SHIFT, 3, 3 }, /* 011 */ + { 2+INDEX_SHIFT, 4, 3 }, /* 100 */ + { 3+INDEX_SHIFT, 7, 3 }, /* 111 */ + { 4+INDEX_SHIFT, 12, 4 }, /* 1100 */ + { 5+INDEX_SHIFT, 6, 5 }, /* 00110 */ + { 6+INDEX_SHIFT, 57, 8 }, /* 00111001 */ + { 7+INDEX_SHIFT, 224, 10 } /* 0011100000 */ +}; + +const Coding codesTnsCoeff1WBTCX20[] = +{ + { -8+INDEX_SHIFT, 512, 12 }, /* 001000000000 */ + { -7+INDEX_SHIFT, 513, 12 }, /* 001000000001 */ + { -6+INDEX_SHIFT, 514, 12 }, /* 001000000010 */ + { -5+INDEX_SHIFT, 65, 9 }, /* 001000001 */ + { -4+INDEX_SHIFT, 17, 7 }, /* 0010001 */ + { -3+INDEX_SHIFT, 5, 5 }, /* 00101 */ + { -2+INDEX_SHIFT, 0, 3 }, /* 000 */ + { -1+INDEX_SHIFT, 2, 3 }, /* 010 */ + { 0+INDEX_SHIFT, 3, 2 }, /* 11 */ + { 1+INDEX_SHIFT, 2, 2 }, /* 10 */ + { 2+INDEX_SHIFT, 3, 3 }, /* 011 */ + { 3+INDEX_SHIFT, 3, 4 }, /* 0011 */ + { 4+INDEX_SHIFT, 9, 6 }, /* 001001 */ + { 5+INDEX_SHIFT, 33, 8 }, /* 00100001 */ + { 6+INDEX_SHIFT, 129, 10 }, /* 0010000001 */ + { 7+INDEX_SHIFT, 515, 12 } /* 001000000011 */ +}; + +const Coding codesTnsCoeff2WB[] = +{ + { -8+INDEX_SHIFT, 5632, 13 }, /* 1011000000000 */ + { -7+INDEX_SHIFT, 5633, 13 }, /* 1011000000001 */ + { -6+INDEX_SHIFT, 1409, 11 }, /* 10110000001 */ + { -5+INDEX_SHIFT, 353, 9 }, /* 101100001 */ + { -4+INDEX_SHIFT, 89, 7 }, /* 1011001 */ + { -3+INDEX_SHIFT, 23, 5 }, /* 10111 */ + { -2+INDEX_SHIFT, 4, 3 }, /* 100 */ + { -1+INDEX_SHIFT, 0, 2 }, /* 00 */ + { 0+INDEX_SHIFT, 3, 2 }, /* 11 */ + { 1+INDEX_SHIFT, 1, 2 }, /* 01 */ + { 2+INDEX_SHIFT, 10, 4 }, /* 1010 */ + { 3+INDEX_SHIFT, 45, 6 }, /* 101101 */ + { 4+INDEX_SHIFT, 177, 8 }, /* 10110001 */ + { 5+INDEX_SHIFT, 705, 10 }, /* 1011000001 */ + { 6+INDEX_SHIFT, 5634, 13 }, /* 1011000000010 */ + { 7+INDEX_SHIFT, 5635, 13 } /* 1011000000011 */ +}; + +const Coding codesTnsCoeff3WB[] = +{ + { -8+INDEX_SHIFT, 5638, 13 }, /* 1011000000110 */ + { -7+INDEX_SHIFT, 5639, 13 }, /* 1011000000111 */ + { -6+INDEX_SHIFT, 2816, 12 }, /* 101100000000 */ + { -5+INDEX_SHIFT, 353, 9 }, /* 101100001 */ + { -4+INDEX_SHIFT, 177, 8 }, /* 10110001 */ + { -3+INDEX_SHIFT, 45, 6 }, /* 101101 */ + { -2+INDEX_SHIFT, 10, 4 }, /* 1010 */ + { -1+INDEX_SHIFT, 0, 2 }, /* 00 */ + { 0+INDEX_SHIFT, 3, 2 }, /* 11 */ + { 1+INDEX_SHIFT, 1, 2 }, /* 01 */ + { 2+INDEX_SHIFT, 4, 3 }, /* 100 */ + { 3+INDEX_SHIFT, 23, 5 }, /* 10111 */ + { 4+INDEX_SHIFT, 89, 7 }, /* 1011001 */ + { 5+INDEX_SHIFT, 705, 10 }, /* 1011000001 */ + { 6+INDEX_SHIFT, 2817, 12 }, /* 101100000001 */ + { 7+INDEX_SHIFT, 2818, 12 } /* 101100000010 */ +}; + +Word16 const nTnsCoeffCodes = sizeof(codesTnsCoeff0TCX20)/sizeof(codesTnsCoeff0TCX20[0]); + +const Coding * codesTnsCoeffSWBTCX20[] = { codesTnsCoeff0TCX20, codesTnsCoeff1TCX20, codesTnsCoeff2TCX20, codesTnsCoeff3TCX20, codesTnsCoeff4TCX20, codesTnsCoeff5, codesTnsCoeff6, codesTnsCoeff7 }; +const Coding * codesTnsCoeffSWBTCX10[] = { codesTnsCoeff0TCX10, codesTnsCoeff1TCX10, codesTnsCoeff2TCX10, codesTnsCoeff3TCX10, codesTnsCoeff4TCX10, codesTnsCoeff5, codesTnsCoeff6, codesTnsCoeff7 }; +const Coding * codesTnsCoeffWBTCX20[] = { codesTnsCoeff0WBTCX20, codesTnsCoeff1WBTCX20, codesTnsCoeff2WB, codesTnsCoeff3WB, codesTnsCoeff456, codesTnsCoeff456, codesTnsCoeff456, codesTnsCoeff7 }; + +Word16 const nTnsCoeffTables = sizeof(codesTnsCoeffSWBTCX20)/sizeof(codesTnsCoeffSWBTCX20[0]); + +const Coding codesTnsOrderTCX20[] = +{ + { 1, 0, 2 }, /* 00 */ + { 2, 40, 6 }, /* 101000 */ + { 3, 41, 6 }, /* 101001 */ + { 4, 21, 5 }, /* 10101 */ + { 5, 11, 4 }, /* 1011 */ + { 6, 4, 3 }, /* 100 */ + { 7, 1, 2 }, /* 01 */ + { 8, 3, 2 } /* 11 */ +}; + +const Coding codesTnsOrderTCX10[] = +{ + { 1, 0, 3 }, /* 000 */ + { 2, 16, 5 }, /* 10000 */ + { 3, 17, 5 }, /* 10001 */ + { 4, 9, 4 }, /* 1001 */ + { 5, 1, 3 }, /* 001 */ + { 6, 5, 3 }, /* 101 */ + { 7, 1, 2 }, /* 01 */ + { 8, 3, 2 } /* 11 */ +}; + +const Coding codesTnsOrder[] = +{ + { 1, 96, 7 }, /* 1100000 */ + { 2, 97, 7 }, /* 1100001 */ + { 3, 49, 6 }, /* 110001 */ + { 4, 25, 5 }, /* 11001 */ + { 5, 13, 4 }, /* 1101 */ + { 6, 7, 3 }, /* 111 */ + { 7, 2, 2 }, /* 10 */ + { 8, 0, 1 } /* 0 */ +}; + +Word16 const nTnsOrderCodes = sizeof(codesTnsOrder)/sizeof(codesTnsOrder[0]); + +ParamsBitMap const tnsSWBTCX20FilterCoeffBitMap[1] = +{ + { + 1, + { + { 0, GetSWBTCX20TnsFilterCoeffBits, TRUE, GetTnsFilterCoeff, SetTnsFilterCoeff, EncodeSWBTCX20TnsFilterCoeff, DecodeSWBTCX20TnsFilterCoeff, NULL } /* TNS filter coefficients */ + } + } +}; + +ParamsBitMap const tnsSWBTCX10FilterCoeffBitMap[1] = +{ + { + 1, + { + { 0, GetSWBTCX10TnsFilterCoeffBits, TRUE, GetTnsFilterCoeff, SetTnsFilterCoeff, EncodeSWBTCX10TnsFilterCoeff, DecodeSWBTCX10TnsFilterCoeff, NULL } /* TNS filter coefficients */ + } + } +}; + +ParamsBitMap tnsSWBTCX20FilterBitMap[1] = +{ + { + 1, + { + { 0, GetTnsFilterOrderBitsSWBTCX20, FALSE, GetTnsFilterOrder, SetTnsFilterOrder, EncodeTnsFilterOrderSWBTCX20, DecodeTnsFilterOrderSWBTCX20, tnsSWBTCX20FilterCoeffBitMap } /* TNS filter order */ + } + } +}; + +ParamsBitMap tnsSWBTCX10FilterBitMap[1] = +{ + { + 1, + { + { 0, GetTnsFilterOrderBitsSWBTCX10, FALSE, GetTnsFilterOrder, SetTnsFilterOrder, EncodeTnsFilterOrderSWBTCX10, DecodeTnsFilterOrderSWBTCX10, tnsSWBTCX10FilterCoeffBitMap } /* TNS filter order */ + } + } +}; + +ParamsBitMap const tnsSWBTCX20BitMap[1] = +{ + { + 1, + { + { 1, NULL, FALSE, GetNumOfTnsFilters, SetNumOfTnsFilters, NULL, NULL, tnsSWBTCX20FilterBitMap } /* Number of TNS filters */ + } + } +}; + +/* For storing/reading bits in SWB/FB mode */ +ParamsBitMap const tnsEnabledSWBTCX20BitMap[1] = +{ + { + 1, + { + { 1, NULL, TRUE, GetTnsEnabled, SetTnsEnabled, NULL, NULL, tnsSWBTCX20BitMap } /* TNS Enabled/Disable */ + } + } +}; + +ParamsBitMap const tnsSWBTCX10BitMap[1] = +{ + { + 1, + { + { 1, NULL, FALSE, GetNumOfTnsFilters, SetNumOfTnsFilters, NULL, NULL, tnsSWBTCX10FilterBitMap } /* Number of TNS filters */ + } + } +}; + +/* For storing/reading bits in SWB/FB mode */ +ParamsBitMap const tnsEnabledSWBTCX10BitMap[1] = +{ + { + 1, + { + { 1, NULL, TRUE, GetTnsEnabled, SetTnsEnabled, NULL, NULL, tnsSWBTCX10BitMap } /* TNS Enabled/Disable */ + } + } +}; + +ParamsBitMap const tnsWBTCX20FilterCoeffBitMap[1] = +{ + { + 1, + { + { 0, GetWBTCX20TnsFilterCoeffBits, TRUE, GetTnsFilterCoeff, SetTnsFilterCoeff, EncodeWBTCX20TnsFilterCoeff, DecodeWBTCX20TnsFilterCoeff, NULL } /* TNS filter coefficients */ + } + } +}; + +ParamsBitMap const tnsWBTCX20FilterBitMap[1] = +{ + { + 1, + { + { 0, GetTnsFilterOrderBits, FALSE, GetTnsFilterOrder, SetTnsFilterOrder, EncodeTnsFilterOrder, DecodeTnsFilterOrder, tnsWBTCX20FilterCoeffBitMap } /* TNS filter order */ + } + } +}; + + +/* For storing/reading bits in WB mode */ +ParamsBitMap const tnsEnabledWBTCX20BitMap[1] = +{ + { + 1, + { + { 1, NULL, TRUE, GetTnsEnabledSingleFilter, SetTnsEnabledSingleFilter, NULL, NULL, tnsWBTCX20FilterBitMap } /* TNS Enabled/Disable */ + } + } +}; + + +/** + * 4 bit resolution TNS coefficients. + */ +const Word16 tnsCoeff4[16]= +{ + -32628/*-0.99573418F Q15*/, /* = sin(-8*(PI/2.0)/(8 + 0.5)) */ + -31517/*-0.96182564F Q15*/, /* = sin(-7*(PI/2.0)/(8 + 0.5)) */ + -29333/*-0.89516329F Q15*/, + -26149/*-0.79801723F Q15*/, + -22076/*-0.67369564F Q15*/, + -17250/*-0.52643216F Q15*/, + -11837/*-0.36124167F Q15*/, + -6021/*-0.18374952F Q15*/, /* = sin(-1*(PI/2.0)/(8 + 0.5)) */ + 0/* 0.00000000F Q15*/, /* = sin(0*(PI/2.0)/(8 + 0.5)) */ + 6813/* 0.20791169F Q15*/, /* = sin(1*(PI/2.0)/(8 - 0.5)) */ + 13328/* 0.40673664F Q15*/, + 19261/* 0.58778525F Q15*/, + 24351/* 0.74314483F Q15*/, + 28378/* 0.86602540F Q15*/, + 31164/* 0.95105652F Q15*/, /* = sin(6*(PI/2.0)/(8 - 0.5)) */ + 32588/* 0.99452190F Q15*/ /* = sin(7*(PI/2.0)/(8 - 0.5)) */ +}; + +/*bits_alloc_tables.c*/ + + +/*NRG MODE*/ +/* NRG mode */ +const Word16 ACELP_NRG_MODE[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX] = +{ + {{0,0,1,1,0,0,0,0},{2,2,1,1,0,0,0,0}}, + {{1,1,1,1,0,0,0,0},{1,1,1,1,1,1,1,0}}, +}; + +/* NRG bits : (0/2/3 bits) */ +const Word16 ACELP_NRG_BITS[3] = +{ + 0, + 3, + 4 +}; + +/*LTP MODE*/ +const Word16 ACELP_LTP_MODE[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX] = +{ + {{0,0,1,2,0,0,0,0},{0,0,1,2,0,0,0,0}}, + {{4,4,3,4,0,0,0,0},{4,4,3,4,8,0,9,0}}, +}; + +/*LTP BITS*/ +const Word16 ACELP_LTP_BITS_SFR[8+RF_MODE_MAX][5] = +{ + {0,0,0,0,0}, + {8,4,4,4,4}, + {8,5,8,5,5}, + {9,6,6,6,6}, + {9,6,9,6,6}, + {8,5,5,5,5}, + {8,5,8,5,5}, + {8,0,0,0,0}, + {8,5,5,5,5}, /* All-pred mode in RF, rf_frame_type = 0 */ + {8,4,4,4,0}, /* Gen-pred mode in RF, rf_frame_type = 2 */ +}; + + +/*LTF MODE: 0 no filtering, 1 filtering, 2 adaptive*/ +const Word16 ACELP_LTF_MODE[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX] = +{ + {{1,1,1,0,0,0,0,0},{1,1,1,0,0,0,0,0}}, + {{0,0,2,0,0,0,0,0},{0,0,2,0,1,1,1,0}}, +}; + +/*LTF BITS*/ +const Word16 ACELP_LTF_BITS[4] = +{ + 0, + 0, + 4, + 0 +}; + +/*GAINS ELEMENT*/ +/*5 modes: (ACELP: 5b/suframe), (AMRWB: 7b/subframe),(AMRWB: 6b/subframe),(UC: 5b/subframe)*/ +const Word16 ACELP_GAINS_MODE[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX] = +{ + {{6,6,1,1,0,0,0,0},{7,7,1,1,0,0,0,0}}, + {{2,2,3,3,0,0,0,0},{2,2,3,3,3,2,1,0}}, +}; + +/*GAINS BITS*/ +const Word16 ACELP_GAINS_BITS[10] = +{ + 0, /* skip sub-frame wise gain coding*/ + 5, /* ACELP 5b */ + 6, /* ACELP 6b */ + 7, /* ACELP 7b */ + 6, /* AMR-WB 6b */ + 7, /* AMR-WB 7b */ + 6, /* ACELP_UC 6b */ + 7, /* GUNVOICED UV 7b (5b ICB/2b Gaussian) */ + 4, /* GNELP UV 4b */ + 5 /* GNELP UV 5b */ +}; + +/*ADAPT BPF*/ +/*BPF MODE: 0 no filtering, 1 filtering, 2 adaptive*/ +const Word16 ACELP_BPF_MODE[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX] = +{ + {{1,1,1,1,0,0,0,0},{1,1,1,1,0,0,0,0}}, + {{1,1,2,2,0,0,0,0},{1,1,2,2,1,1,1,1}}, +}; + +/*BPF BITS*/ +const Word16 ACELP_BPF_BITS[3] = {0, 0, 2}; + +const Word16 ACELP_CDK_BITS[ACELP_FIXED_CDK_NB] = +{ + 7, 10, 12, 15, 17, 20, 24, 26, 28, 30, 32, 34, 36, 40, 43, 46, + 47, 49, 50, 53, 55, 56, 58, 59, 61, 62, 65, 68, 70, 73, 75, 78, 80, 83, + 85, 87, 89, 92, 94, 96, 98 +}; + +/* Number of pulses & positions to the number of unique states that can be achieved with those pulses */ +const Word32 pulsestostates[17][9] = +{ + { 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 2, 2, 2, 2, 2, 2, 2, 2, 2}, + { 4, 8, 12, 16, 20, 24, 28, 32, 36}, + { 6, 18, 38, 66, 102, 146, 198, 258, 326}, + { 8, 32, 88, 192, 360, 608, 952, 1408, 1992}, + { 10, 50, 170, 450, 1002, 1970, 3530, 5890, 9290}, + { 12, 72, 292, 912, 2364, 5336, 10836, 20256, 35436}, + { 14, 98, 462, 1666, 4942, 12642, 28814, 59906, 115598}, + { 16, 128, 688, 2816, 9424, 27008, 68464, 157184, 332688}, + { 18, 162, 978, 4482, 16722, 53154, 148626, 374274, 864146}, + { 20, 200, 1340, 6800, 28004, 97880, 299660, 822560, 2060980}, + { 22, 242, 1782, 9922, 44726, 170610, 568150, 1690370, 4573910}, + { 24, 288, 2312, 14016, 68664, 284000, 1022760, 3281280, 9545560}, + { 26, 338, 2938, 19266, 101946, 454610, 1761370, 6065410, 18892250}, + { 28, 392, 3668, 25872, 147084, 703640, 2919620, 10746400, 35704060}, + { 30, 450, 4510, 34050, 207006, 1057730, 4680990, 18347010, 64797470}, + { 32, 512, 5472, 44032, 285088, 1549824, 7288544, 30316544, 113461024}, +}; + + +/*vlpc_1st_cod*/ +const Word16 dico_lsf_abs_8b[256*M] = /*14Q1*1.28*/ +{ + 966, 1761, 2937, 3740, 4574, 5488, 6457, 7398, 8355, 9289, 10254, 11211, 12247, 13202, 14221, 15172, + 1540, 2731, 3544, 4232, 5065, 5917, 6846, 7707, 8602, 9538, 10479, 11445, 12439, 13339, 14332, 15243, + 1414, 2201, 3469, 4160, 4832, 5563, 6504, 7493, 8507, 9423, 10261, 11087, 12014, 12887, 13935, 15041, + 1176, 2031, 3312, 4141, 4915, 5612, 6368, 7097, 7965, 8861, 9900, 10956, 12137, 13161, 14215, 15190, + 840, 1102, 1853, 3913, 4514, 5155, 5976, 6577, 7726, 8469, 9195, 9896, 12016, 13534, 14458, 15327, + 1165, 1552, 2467, 3520, 3933, 4902, 6085, 6607, 7652, 8343, 8922, 9577, 11002, 13331, 14521, 15310, + 1113, 1431, 2280, 3471, 3975, 4853, 5690, 6407, 7275, 8032, 8621, 9884, 12276, 13033, 13880, 15039, + 719, 1036, 1867, 2553, 4352, 5021, 5775, 6505, 7179, 7826, 9601, 11113, 12075, 12807, 14022, 15272, + 953, 1294, 1952, 2553, 3007, 5085, 6062, 6718, 8178, 8712, 9927, 11330, 12351, 13205, 14164, 15087, + 940, 1283, 2111, 2792, 3256, 3911, 6096, 6898, 7589, 9317, 10103, 10891, 11893, 12886, 13757, 15049, + 587, 903, 1795, 3140, 4297, 4853, 5479, 6468, 7886, 8442, 9844, 11336, 12043, 12793, 13911, 15151, + 861, 1323, 2258, 3258, 3853, 4815, 5824, 6684, 8004, 9358, 10709, 11951, 12810, 13582, 14465, 15216, + 758, 1202, 2449, 3134, 3694, 4423, 5673, 6885, 7835, 9014, 10027, 11120, 12196, 13199, 14218, 15199, + 1042, 1478, 2150, 3726, 4263, 4954, 6139, 6790, 7965, 8974, 9643, 10764, 12030, 12725, 13557, 14581, + 719, 926, 2434, 3748, 4185, 5032, 5661, 6815, 7286, 9180, 10365, 11159, 11991, 12918, 13824, 15248, + 715, 1008, 2245, 3846, 4283, 5859, 6516, 7754, 9005, 9791, 10611, 11473, 12342, 13216, 14190, 15177, + 972, 1282, 1856, 2557, 3020, 4536, 7105, 8030, 8649, 9405, 10103, 10712, 11575, 12633, 13608, 14745, + 813, 1132, 1994, 2990, 3472, 4041, 4711, 7349, 8285, 8967, 9924, 10497, 11905, 13402, 14503, 15358, + 897, 1260, 1953, 3238, 3878, 4495, 6373, 7420, 8046, 9326, 10330, 10893, 11883, 13155, 14226, 15156, + 772, 1190, 1952, 2591, 4617, 5613, 6788, 7715, 8323, 9061, 10103, 11442, 12520, 13313, 14105, 15130, + 648, 914, 1614, 2978, 3913, 5180, 6371, 7029, 7510, 8288, 10181, 11303, 12262, 13298, 14629, 15443, + 679, 934, 1510, 2061, 4006, 5506, 6056, 6653, 7326, 8996, 10254, 11800, 12686, 13410, 14130, 15080, + 536, 802, 1288, 2431, 4428, 4896, 5421, 6396, 8409, 9756, 10509, 11135, 12212, 13338, 14298, 15284, + 774, 1064, 1751, 2361, 3813, 5723, 6272, 7170, 7837, 9027, 9999, 10677, 11383, 12564, 14005, 15142, + 678, 938, 1492, 2025, 4146, 5207, 5984, 6738, 7509, 8781, 9766, 10948, 12156, 13220, 14217, 15296, + 639, 927, 1490, 2153, 4243, 5592, 6466, 7219, 7989, 9277, 10369, 11353, 12295, 13240, 14272, 15267, + 743, 1035, 1700, 2248, 3167, 5728, 6394, 7572, 8421, 9284, 10729, 11762, 12753, 13526, 14380, 15202, + 468, 692, 1255, 2740, 4287, 5357, 6462, 7499, 8537, 9503, 10499, 11458, 12457, 13393, 14352, 15260, + 734, 989, 1478, 1957, 2947, 5157, 6144, 7370, 8090, 8834, 9907, 11183, 12331, 13280, 14246, 15263, + 461, 681, 1659, 3534, 4547, 5654, 6632, 7664, 8623, 9608, 10561, 11542, 12490, 13438, 14368, 15271, + 792, 1113, 1855, 2398, 3238, 5817, 6524, 7434, 8483, 9164, 10021, 11002, 12178, 13218, 14316, 15216, + 658, 1008, 1970, 3074, 4543, 5908, 7154, 8105, 8980, 9832, 10606, 11401, 12264, 13165, 14158, 15163, + 1009, 1541, 2392, 3464, 4644, 5562, 6666, 7588, 8538, 9554, 10547, 11489, 12487, 13412, 14326, 15206, + 955, 1704, 3142, 3903, 4985, 6046, 7112, 8024, 8864, 9606, 10417, 11275, 12242, 13171, 14188, 15188, + 1152, 2084, 3441, 4308, 5341, 6367, 7465, 8361, 9258, 10034, 10799, 11569, 12435, 13295, 14269, 15192, + 1361, 2472, 3734, 4540, 5724, 6786, 7934, 8876, 9753, 10482, 11209, 11930, 12704, 13494, 14411, 15293, + 1448, 2793, 3997, 5078, 6382, 7418, 8278, 9062, 9827, 10479, 11193, 11976, 12798, 13632, 14523, 15357, + 1488, 2499, 3704, 4557, 5499, 6512, 7628, 8636, 9720, 10662, 11547, 12425, 13250, 13991, 14754, 15490, + 1099, 2055, 3146, 3872, 4700, 5675, 6721, 7670, 8652, 9638, 10640, 11603, 12561, 13473, 14404, 15285, + 575, 841, 1577, 3091, 3894, 4777, 5587, 6225, 8293, 8937, 9666, 10986, 12135, 13292, 14164, 15178, + 799, 1086, 1834, 2360, 3186, 5166, 5756, 7271, 8036, 8703, 9532, 10239, 11731, 13180, 14418, 15362, + 956, 1297, 2021, 2413, 4341, 5175, 5948, 6783, 7304, 8114, 9024, 9853, 10910, 12746, 14094, 15167, + 1288, 1856, 2407, 3125, 3686, 4421, 5672, 6339, 7288, 8274, 9315, 10205, 11191, 12856, 14483, 15463, + 1020, 1359, 2139, 2709, 3398, 4646, 5412, 6441, 7053, 7923, 9213, 10192, 11791, 13084, 14208, 15242, + 839, 1165, 2114, 2625, 3382, 3972, 5064, 7268, 7966, 8749, 9833, 12022, 13123, 13848, 14622, 15279, + 837, 1104, 1848, 2230, 3860, 4731, 5491, 6377, 6917, 8917, 10029, 10891, 12043, 12753, 13952, 15201, + 1136, 1564, 2097, 2558, 3026, 4824, 5743, 6459, 7664, 8183, 9819, 10837, 11538, 12762, 14193, 15309, + 1013, 1492, 2105, 2593, 3135, 5090, 6278, 6877, 7559, 8026, 9120, 10257, 11268, 12899, 14253, 15324, + 677, 952, 1578, 2156, 3456, 4665, 5545, 6815, 7822, 8967, 10044, 11143, 12218, 13205, 14269, 15290, + 560, 833, 1626, 2825, 4189, 5300, 5822, 6280, 7858, 9256, 10189, 11481, 12413, 13040, 14138, 15123, + 666, 1181, 2686, 3416, 4169, 5158, 6179, 7282, 8275, 9372, 10419, 11434, 12436, 13400, 14358, 15244, + 773, 1040, 1809, 3551, 4049, 5132, 5867, 6525, 7877, 8558, 9275, 10956, 12231, 13016, 14012, 15032, + 881, 1209, 1988, 3725, 4126, 5152, 6189, 6712, 8497, 9495, 10097, 11006, 12228, 13271, 14197, 15140, + 850, 1109, 2540, 3212, 3836, 4671, 5423, 6258, 6873, 7502, 9107, 10990, 12254, 13154, 14378, 15352, + 721, 954, 2751, 3694, 4320, 5071, 5825, 6738, 7291, 7984, 9289, 11579, 12483, 13254, 14338, 15260, + 1055, 1371, 1968, 3743, 4580, 4986, 5695, 6267, 7257, 8890, 9548, 10261, 11586, 12347, 13324, 15091, + 676, 972, 2112, 2850, 3753, 4728, 5494, 6367, 7285, 8675, 9943, 11368, 12460, 13350, 14172, 15122, + 1049, 1494, 2200, 3000, 3527, 5081, 6046, 6884, 8291, 9069, 10097, 11369, 12496, 13375, 14347, 15128, + 814, 1123, 2183, 2717, 3304, 3975, 5256, 6076, 7491, 8840, 10493, 11738, 12716, 13494, 14450, 15263, + 948, 1271, 2388, 3106, 3719, 4616, 5356, 6675, 7383, 7967, 9440, 11584, 12408, 13133, 13866, 14860, + 635, 881, 1924, 3907, 4384, 5217, 5950, 6984, 7695, 8650, 9877, 11108, 12074, 13120, 14245, 15282, + 762, 1028, 2283, 3533, 3943, 4563, 5144, 6692, 7423, 8653, 9739, 10969, 12023, 13103, 14147, 15192, + 579, 854, 1748, 3347, 3979, 4734, 5418, 7056, 8203, 9063, 10246, 11271, 12279, 13293, 14338, 15258, + 503, 768, 1465, 3077, 4620, 5151, 5798, 7143, 8378, 9391, 10401, 11373, 12315, 13200, 14113, 15106, + 717, 1002, 1807, 3675, 4066, 5418, 6034, 6837, 8445, 8980, 10353, 11755, 12753, 13520, 14476, 15232, + 672, 949, 1676, 3274, 4729, 5344, 6538, 7393, 8330, 9755, 10902, 11594, 12475, 13327, 14247, 15152, + 496, 912, 2757, 3804, 4833, 5819, 6853, 7814, 8753, 9709, 10654, 11604, 12540, 13471, 14395, 15300, + 775, 1049, 2302, 3012, 3920, 4950, 5709, 7219, 7761, 9746, 10544, 11297, 12044, 12831, 13700, 15084, + 1078, 1504, 2140, 3195, 3778, 4555, 5966, 6673, 7747, 8995, 9612, 10447, 11613, 12329, 13101, 14856, + 968, 1849, 3399, 4265, 5004, 5732, 6679, 7575, 8554, 9526, 10485, 11412, 12400, 13344, 14309, 15220, + 1199, 2464, 3945, 4913, 6009, 6786, 7495, 8106, 8835, 9620, 10520, 11438, 12438, 13342, 14319, 15235, + 1081, 2165, 3828, 4637, 5448, 6070, 6800, 7534, 8434, 9349, 10320, 11262, 12293, 13218, 14232, 15192, + 1083, 1694, 2537, 3083, 3771, 5128, 6256, 7141, 8587, 9530, 10324, 11062, 11832, 12707, 13900, 15104, + 925, 1244, 2121, 3433, 3834, 5306, 6241, 6848, 8344, 9060, 9700, 10464, 11277, 12214, 14081, 15400, + 773, 1006, 1754, 4566, 5209, 5778, 6451, 7124, 8069, 8706, 9253, 10001, 10837, 12064, 14326, 15356, + 620, 950, 1866, 3048, 4740, 5460, 5977, 6457, 7915, 9271, 9868, 10687, 11496, 12237, 13203, 15016, + 1104, 1439, 2275, 2648, 3695, 5401, 5983, 7243, 7860, 8327, 8987, 11178, 12399, 13141, 14208, 14977, + 1076, 1712, 2332, 3118, 4625, 5250, 6130, 7069, 7734, 8740, 10166, 11116, 12011, 12960, 13959, 14830, + 659, 949, 1548, 2807, 4382, 4952, 5938, 7089, 7729, 8587, 10547, 11148, 11668, 12528, 13953, 15131, + 618, 891, 1593, 3197, 3993, 4733, 5928, 6583, 7372, 9278, 10158, 10852, 12066, 13201, 14256, 15298, + 1226, 1611, 2351, 3438, 3930, 4616, 6358, 6975, 7675, 9306, 10025, 10545, 11077, 12750, 14164, 15269, + 680, 957, 1852, 3036, 3864, 5284, 5883, 6570, 7132, 8763, 9943, 10590, 11425, 12827, 14180, 15184, + 567, 890, 1811, 3039, 4034, 4670, 5067, 5886, 7597, 8889, 10127, 10989, 12275, 13126, 14471, 15240, + 1017, 1306, 1912, 4065, 5098, 5506, 6244, 6943, 7610, 8963, 10029, 10608, 11375, 12363, 14054, 15433, + 718, 949, 1640, 4407, 4989, 5504, 6145, 6846, 8055, 8755, 9764, 11309, 12335, 13157, 13991, 15052, + 833, 1104, 2582, 3256, 3910, 5291, 5740, 7382, 8142, 8582, 9618, 11230, 12436, 13284, 14118, 14993, + 1157, 1491, 2370, 3490, 3848, 5022, 5800, 6591, 7995, 8564, 9304, 10921, 12495, 13372, 14254, 15054, + 1052, 1417, 2072, 2620, 3044, 4572, 5432, 6284, 7546, 8244, 9800, 10798, 12368, 13625, 14662, 15445, + 795, 1132, 1902, 2810, 3433, 4747, 5790, 6745, 8443, 9315, 10050, 10836, 11673, 12528, 13832, 15149, + 967, 1250, 2420, 3159, 3625, 4266, 4948, 7030, 7674, 8235, 9112, 9840, 11161, 12837, 14235, 15341, + 730, 997, 2113, 3171, 3737, 4764, 5577, 6449, 7240, 8394, 9116, 10604, 12009, 13102, 14231, 15244, + 1192, 1617, 2341, 3430, 4000, 4721, 5596, 6358, 7429, 8167, 8895, 9916, 10855, 12188, 13896, 15254, + 872, 1150, 2032, 3553, 3983, 4963, 5636, 6604, 7462, 8064, 9470, 10203, 11089, 12799, 14118, 15282, + 1013, 1444, 1984, 3267, 4408, 4772, 5805, 7143, 7690, 8647, 10029, 10669, 11431, 12636, 13988, 15117, + 830, 1134, 1866, 3581, 4056, 4925, 6011, 6558, 8076, 8830, 9656, 10706, 12639, 13726, 14663, 15367, + 684, 957, 1801, 3005, 3559, 4879, 5574, 6920, 7739, 8471, 9724, 10719, 12040, 13148, 14262, 15275, + 699, 1022, 2042, 3021, 3652, 5369, 6030, 7152, 8031, 8854, 9968, 10869, 11910, 13073, 14255, 15228, + 831, 1105, 1945, 3827, 4272, 5403, 6214, 6843, 8117, 8827, 9516, 10328, 11201, 12905, 14507, 15398, + 785, 1036, 2037, 4291, 4698, 5531, 6223, 7000, 8372, 9181, 9784, 10501, 11195, 12592, 13855, 15023, + 1079, 1556, 2081, 3294, 4678, 5189, 5975, 6991, 7650, 8458, 9624, 10387, 11370, 12518, 13343, 14521, + 1085, 1535, 2122, 2772, 3190, 4157, 6280, 7310, 8119, 8898, 9511, 10169, 11313, 12529, 13732, 15153, + 1130, 1625, 2359, 3044, 3504, 5151, 6102, 6755, 7616, 8099, 8791, 9828, 10718, 12434, 14231, 15302, + 894, 1194, 1854, 2315, 3048, 5073, 5700, 6637, 7336, 8181, 9563, 10924, 12316, 13331, 14349, 15237, + 1274, 1843, 2368, 2935, 3396, 4031, 5905, 6950, 7597, 8704, 9554, 10193, 11657, 13031, 13891, 14934, + 1208, 1660, 2310, 3189, 3644, 4355, 5442, 6162, 7602, 8433, 9505, 10600, 12310, 13625, 14495, 15234, + 884, 1244, 2154, 2652, 3187, 3810, 5991, 6674, 7284, 8251, 9106, 10547, 11947, 13173, 14248, 15300, + 851, 1095, 2125, 2913, 3429, 4068, 4931, 6228, 6911, 8477, 9513, 10932, 12187, 13333, 14385, 15286, + 637, 976, 2370, 3892, 4718, 6063, 7126, 8378, 9405, 10359, 11188, 12001, 12807, 13610, 14465, 15303, + 674, 1156, 3206, 3848, 4574, 5332, 6275, 7180, 7979, 8944, 9945, 11135, 12211, 13166, 14189, 15185, + 648, 874, 1620, 4523, 5335, 5818, 6480, 7079, 8024, 8654, 9320, 10068, 11602, 13428, 14329, 15293, + 602, 831, 3174, 4258, 4758, 5558, 6154, 6862, 7261, 8173, 9894, 11228, 12406, 13185, 14416, 15390, + 728, 1050, 2523, 3324, 4581, 5112, 6274, 7249, 7665, 8228, 9024, 9779, 11962, 13886, 14569, 15310, + 625, 1064, 2658, 3373, 4317, 5328, 6341, 7576, 8230, 9137, 10072, 11030, 12105, 13071, 14050, 15127, + 860, 1199, 2569, 3264, 3928, 5082, 6012, 7023, 7568, 8726, 9899, 10975, 11665, 12602, 13465, 14849, + 994, 1326, 2131, 3392, 3914, 4629, 5507, 6365, 7208, 8086, 9307, 10139, 11960, 13752, 14791, 15505, + 1297, 1723, 2304, 2955, 3528, 4575, 5330, 6141, 7321, 7873, 9079, 11066, 12114, 12781, 13485, 14866, + 1247, 1673, 2480, 3557, 4100, 4892, 5843, 6678, 7764, 8607, 9292, 10007, 11055, 11895, 12912, 14829, + 1108, 1515, 2302, 3815, 4582, 5275, 6233, 7271, 7993, 8890, 9807, 10489, 11145, 11905, 12753, 14036, + 969, 1302, 2055, 2425, 3922, 5219, 6014, 6785, 7331, 9195, 10032, 10897, 11788, 12542, 13408, 14826, + 1042, 1398, 2217, 2813, 3449, 4242, 5032, 6957, 7766, 8985, 9916, 10576, 11237, 12222, 13952, 15302, + 1099, 1456, 2313, 2814, 3532, 5651, 6349, 7119, 8208, 8769, 9427, 10112, 11070, 12005, 12975, 14815, + 952, 1343, 2279, 4277, 5014, 5588, 6550, 7259, 8172, 9304, 10112, 10905, 11848, 12798, 13734, 14852, + 827, 1155, 2015, 2590, 3389, 5575, 6147, 7237, 8788, 9352, 9943, 10452, 11166, 11866, 13017, 14908, + 965, 1342, 1904, 3530, 4756, 5265, 6282, 7430, 8006, 8866, 10189, 10858, 11593, 12497, 13413, 14286, + 791, 1033, 1807, 4669, 5445, 6065, 6777, 7311, 8217, 8955, 9594, 10171, 10891, 11711, 13024, 15079, + 703, 982, 1468, 2926, 5508, 6551, 7045, 7648, 8280, 9027, 10043, 10724, 11477, 12486, 13816, 15160, + 636, 1084, 3228, 4342, 5051, 5884, 6638, 7545, 8362, 9253, 10190, 11160, 12212, 13207, 14220, 15198, + 821, 1100, 1682, 3559, 5618, 6419, 6944, 7630, 8233, 9075, 10130, 10822, 11427, 12149, 13027, 14146, + 629, 1332, 3013, 3722, 4532, 5532, 6531, 7553, 8517, 9499, 10507, 11474, 12457, 13390, 14358, 15272, + 1317, 2450, 3297, 3892, 4613, 5418, 6425, 7337, 8291, 9245, 10282, 11346, 12442, 13393, 14373, 15268, + 1375, 2387, 3533, 4376, 5325, 6263, 7320, 8268, 9276, 10272, 11197, 12094, 13000, 13818, 14648, 15432, + 1158, 2044, 2814, 3372, 4231, 5273, 6326, 7190, 8055, 8945, 9909, 11036, 12230, 13264, 14271, 15192, + 871, 1102, 2233, 4189, 4539, 5309, 5875, 6894, 8135, 8683, 9397, 10814, 12535, 13312, 14286, 15134, + 814, 1062, 2256, 4246, 4741, 5468, 6095, 6832, 7800, 8445, 9019, 9623, 10539, 12957, 14398, 15333, + 958, 1249, 1879, 3625, 4221, 4743, 5374, 6010, 7564, 8370, 9054, 10537, 11472, 12580, 13996, 15129, + 871, 1148, 2666, 3651, 4193, 5040, 5660, 6778, 7459, 8017, 8780, 9530, 10508, 12721, 14270, 15304, + 651, 1057, 2426, 3096, 4328, 5224, 6148, 6984, 7722, 9038, 10150, 11248, 12299, 13281, 14301, 15245, + 617, 889, 2138, 4101, 4573, 5464, 6134, 7293, 8294, 9277, 10316, 11265, 12281, 13301, 14327, 15273, + 792, 1161, 2081, 2883, 3644, 5502, 6438, 7760, 8867, 9704, 10404, 11003, 11913, 13286, 14647, 15445, + 1202, 1869, 2491, 2996, 4025, 5336, 6574, 7586, 8415, 9166, 9940, 11099, 12441, 13461, 14408, 15252, + 1164, 2036, 2762, 3315, 4510, 5722, 6901, 7925, 8892, 9813, 10715, 11594, 12526, 13416, 14359, 15235, + 1442, 2242, 2916, 3528, 4751, 5836, 6787, 7599, 8395, 9235, 10177, 11157, 12208, 13147, 14145, 15115, + 1182, 2189, 3501, 4359, 5481, 6402, 7306, 7997, 8719, 9457, 10314, 11195, 12207, 13152, 14186, 15159, + 1123, 1928, 3249, 4174, 5190, 6018, 6841, 7570, 8320, 9079, 9969, 10880, 11946, 12957, 14056, 15116, + 1391, 2121, 3172, 3766, 4449, 5215, 6232, 7171, 8096, 8981, 9854, 10664, 11746, 12851, 14017, 15116, + 1330, 2144, 2998, 3489, 4141, 5059, 6328, 7427, 8552, 9564, 10505, 11379, 12290, 13173, 14193, 15189, + 1109, 1492, 2303, 2946, 3382, 4987, 6548, 6997, 8296, 9305, 9871, 10389, 11172, 13047, 14487, 15395, + 1088, 1547, 2223, 3092, 3620, 4386, 6452, 7580, 8220, 9176, 10021, 10624, 11535, 12511, 13349, 14330, + 888, 1265, 1930, 3715, 4354, 4929, 6671, 7348, 8125, 9622, 10527, 11265, 12457, 13225, 13909, 14800, + 815, 1189, 2006, 3817, 4374, 5838, 6485, 7386, 8816, 9395, 10242, 10930, 11702, 12358, 13510, 14977, + 990, 1329, 1856, 2513, 2960, 3841, 6200, 7584, 8128, 9084, 9884, 10615, 11927, 13026, 14162, 15236, + 809, 1891, 3000, 3978, 4992, 5938, 6931, 7857, 8818, 9757, 10695, 11637, 12557, 13495, 14394, 15295, + 554, 1531, 2712, 3754, 4813, 5795, 6805, 7758, 8739, 9677, 10642, 11569, 12527, 13426, 14344, 15173, + 961, 1247, 2162, 4030, 4594, 5392, 6191, 6804, 7979, 8852, 9449, 10061, 10905, 11757, 12852, 14951, + 1214, 1854, 2494, 3286, 3894, 4471, 5973, 7358, 7967, 8807, 9608, 10178, 10994, 12344, 13316, 14487, + 1024, 1446, 2069, 2773, 3329, 5327, 6627, 7318, 8209, 8780, 9592, 11114, 12066, 12765, 13662, 14618, + 907, 1229, 2135, 2657, 3456, 4585, 5614, 6412, 7107, 8072, 10517, 11769, 12447, 13038, 14011, 15186, + 608, 888, 1729, 3791, 4395, 4825, 5374, 6977, 7738, 8387, 9316, 10715, 12651, 13548, 14546, 15311, + 941, 1202, 2101, 3123, 3503, 4159, 4619, 6676, 7402, 8223, 9627, 10280, 11822, 13131, 14470, 15468, + 800, 1065, 1726, 2186, 4630, 5715, 6394, 7256, 7782, 8452, 9368, 11407, 12394, 13086, 14086, 15167, + 875, 1208, 1941, 2508, 3296, 4447, 5532, 6821, 7582, 8862, 9556, 10519, 11696, 12896, 14109, 15273, + 900, 1183, 1959, 2423, 3386, 5868, 6409, 7218, 7883, 8442, 9143, 9913, 11104, 13003, 14241, 15213, + 1115, 1573, 2286, 3113, 3574, 4645, 5519, 6311, 8196, 8937, 9864, 11290, 12252, 13043, 13810, 14631, + 754, 1068, 2679, 3694, 4190, 5008, 5606, 7347, 8013, 8864, 9972, 10786, 11627, 12824, 14010, 15316, + 825, 1144, 1765, 3426, 4206, 4874, 6385, 7180, 7946, 9319, 10153, 10682, 11276, 11957, 13415, 15087, + 537, 862, 1866, 3116, 4349, 4842, 5496, 7245, 7958, 8822, 9611, 10099, 11455, 13291, 14370, 15284, + 887, 1205, 1698, 3243, 5173, 5813, 6470, 7237, 7881, 8707, 9739, 10497, 11284, 12115, 13185, 14869, + 726, 1002, 2984, 3728, 4334, 5142, 5946, 7127, 7676, 8367, 9085, 10668, 11889, 13054, 14011, 15180, + 771, 981, 1772, 4221, 4795, 5401, 6003, 6690, 7480, 8115, 8717, 9938, 12232, 13037, 13941, 15157, + 1303, 1922, 2468, 3316, 4185, 4656, 5507, 6631, 7341, 8291, 9593, 10378, 11412, 12616, 13556, 14820, + 1080, 1403, 2477, 2954, 3741, 4642, 5517, 6582, 7111, 7805, 8786, 9547, 11253, 12874, 14045, 15236, + 872, 1141, 2386, 3209, 3896, 5042, 5805, 7002, 7549, 8285, 9036, 9939, 12031, 13030, 13767, 15055, + 728, 1046, 2013, 4276, 5230, 5799, 6889, 7772, 8535, 9890, 10949, 11702, 12791, 13661, 14459, 15218, + 768, 1578, 3171, 4134, 5114, 6061, 7128, 8112, 9139, 10152, 11101, 12005, 12913, 13736, 14586, 15387, + 622, 1221, 3202, 4279, 5529, 6753, 7808, 8631, 9408, 10115, 10830, 11631, 12512, 13365, 14324, 15263, + 621, 848, 1626, 4612, 5335, 5797, 6416, 7167, 8286, 8933, 9880, 11327, 12709, 13565, 14439, 15329, + 650, 861, 3115, 4397, 4828, 5572, 6159, 7071, 7513, 8108, 8667, 9739, 12413, 13532, 14414, 15581, + 756, 1091, 1615, 2958, 4679, 5429, 6304, 7065, 7657, 8329, 10012, 10763, 11425, 12569, 14285, 15324, + 765, 1051, 2074, 3446, 3838, 5659, 6318, 7149, 8407, 8942, 9688, 11058, 12443, 13347, 14361, 15231, + 1121, 1473, 2217, 2827, 3347, 5017, 5872, 6668, 7595, 8264, 9085, 10487, 12210, 13022, 13866, 14985, + 1056, 1457, 2212, 2861, 3453, 5060, 5976, 6759, 7697, 8519, 9461, 10348, 11169, 12000, 13798, 15274, + 1042, 1388, 2220, 3677, 4297, 5120, 6037, 6788, 7788, 8549, 9262, 10069, 10878, 11755, 14085, 15413, + 961, 1331, 1957, 3111, 3796, 4344, 5010, 5553, 7612, 9441, 10155, 10903, 11982, 12664, 13391, 14959, + 1135, 1470, 2082, 3284, 3937, 4423, 5140, 5618, 7055, 8860, 9355, 10318, 11706, 12556, 13826, 15192, + 1084, 1383, 2209, 3550, 4038, 4636, 5240, 5911, 8011, 9044, 9570, 10294, 11155, 11865, 13587, 15219, + 737, 1028, 1858, 2434, 3038, 3815, 5414, 6560, 7753, 9010, 10088, 11109, 12200, 13241, 14292, 15286, + 979, 1377, 2142, 3511, 4042, 4787, 5869, 6505, 7764, 8710, 9567, 10378, 11383, 13445, 14620, 15417, + 802, 1063, 1768, 3997, 4648, 5273, 6005, 6694, 7698, 8427, 9191, 10230, 11176, 12425, 13991, 15244, + 926, 1148, 2359, 3438, 3811, 4446, 4994, 6492, 7088, 7840, 8921, 9955, 11823, 13037, 14140, 15275, + 639, 939, 1753, 3080, 4204, 5022, 5702, 6198, 6811, 8268, 9786, 10836, 12243, 13126, 14260, 15306, + 736, 1079, 1802, 3276, 4001, 5415, 6381, 7119, 8492, 9232, 10308, 11105, 12031, 12793, 13904, 15114, + 1249, 1897, 2616, 3398, 4149, 4840, 5809, 6616, 7453, 8768, 9869, 10767, 12051, 13177, 14339, 15241, + 1026, 1314, 2014, 3249, 3690, 4344, 4892, 5691, 7289, 7970, 9397, 10615, 11663, 13015, 14272, 15328, + 970, 1249, 2342, 2895, 3661, 4685, 5348, 6691, 7176, 8850, 10323, 11025, 11936, 12697, 13429, 14816, + 872, 1155, 1680, 2334, 2880, 4439, 6448, 7088, 8221, 9517, 10060, 10691, 11577, 12830, 14274, 15377, + 874, 1131, 2067, 2714, 3203, 3786, 4480, 6643, 7487, 8708, 9861, 10989, 12079, 13208, 14240, 15290, + 804, 1079, 1708, 2236, 2842, 5275, 6096, 7030, 7886, 8704, 9978, 11354, 12923, 13800, 14706, 15380, + 646, 907, 1724, 3428, 3981, 5158, 5889, 7244, 8226, 8728, 9227, 10055, 11833, 13065, 14232, 15287, + 986, 1315, 1948, 2518, 3010, 5465, 6638, 7224, 8275, 8820, 9602, 10482, 11268, 12169, 14206, 15449, + 565, 805, 1593, 3458, 4571, 5319, 6411, 7828, 8796, 9460, 10121, 10926, 11931, 12989, 14085, 15181, + 532, 795, 1654, 3253, 3949, 5323, 6246, 7279, 8378, 9364, 10397, 11379, 12395, 13375, 14390, 15290, + 835, 1169, 1895, 2461, 3233, 5608, 6358, 7353, 8521, 9756, 10632, 11371, 12291, 12967, 13777, 14575, + 528, 840, 1585, 2511, 4342, 5075, 5825, 7183, 8370, 8938, 9529, 10614, 12398, 13483, 14482, 15340, + 789, 1044, 2065, 2677, 3589, 5397, 5969, 7559, 8126, 8638, 9332, 10989, 12645, 13441, 14355, 15188, + 685, 970, 1644, 2232, 4331, 5344, 6203, 6877, 7736, 9534, 10331, 11186, 11981, 12778, 13629, 14878, + 800, 1120, 1829, 2303, 4180, 4963, 5877, 6722, 7425, 8436, 9106, 10138, 12113, 13163, 14087, 15242, + 851, 1150, 2243, 3088, 3642, 5370, 6027, 6953, 7919, 8562, 9276, 9957, 10896, 12786, 14320, 15324, + 735, 1113, 2000, 3196, 4699, 5471, 6589, 7347, 8003, 8855, 9650, 10594, 12001, 13017, 13918, 15089, + 837, 1098, 1699, 2175, 3008, 6101, 6902, 7529, 8229, 8790, 9674, 10585, 11532, 12971, 14334, 15323, + 626, 1278, 3315, 4325, 5436, 6586, 7790, 8824, 9821, 10690, 11482, 12268, 13043, 13789, 14591, 15381, + 1439, 2612, 3825, 4715, 5881, 7098, 8204, 9129, 10075, 10889, 11673, 12416, 13159, 13897, 14672, 15420, + 1489, 2697, 3785, 4568, 5440, 6284, 7191, 8043, 8936, 9852, 10756, 11696, 12662, 13539, 14458, 15314, + 663, 932, 1850, 4514, 5042, 5800, 6482, 7381, 8674, 9537, 10447, 11239, 12074, 12975, 13958, 14969, + 695, 1028, 1781, 2195, 4548, 5142, 6539, 7282, 7728, 8259, 8915, 9755, 11646, 13482, 14373, 15221, + 846, 1138, 1713, 2239, 2823, 5254, 6237, 6940, 7777, 8443, 9981, 10858, 11793, 13022, 14259, 15331, + 595, 882, 1481, 3108, 4815, 5391, 5979, 6529, 8058, 8939, 9706, 10649, 11884, 13065, 14350, 15334, + 887, 1139, 1829, 2276, 3102, 5552, 6221, 7067, 7712, 8368, 9127, 10682, 12241, 13127, 14112, 15133, + 1019, 1418, 2165, 2865, 3353, 4937, 6019, 6784, 7810, 8440, 9197, 10025, 12092, 13614, 14602, 15352, + 951, 1206, 2295, 3066, 3586, 4125, 4780, 7215, 7687, 8320, 9079, 10918, 12519, 13503, 14488, 15224, + 847, 1149, 2069, 2504, 4231, 5041, 6034, 6862, 7321, 7882, 8765, 10837, 12433, 13022, 13809, 15203, + 829, 1111, 2677, 3505, 3999, 5080, 5694, 7033, 7667, 8302, 8963, 10297, 12410, 13340, 14485, 15373, + 908, 1284, 2182, 2613, 3944, 5116, 5768, 7284, 7825, 8461, 10123, 11755, 12583, 13368, 14195, 15053, + 930, 1215, 2323, 2834, 3500, 4216, 5200, 5956, 6576, 7757, 9998, 10921, 12073, 12844, 14003, 15254, + 973, 1343, 2164, 3265, 3733, 4538, 5294, 6469, 7850, 8468, 9747, 10750, 11398, 12428, 13990, 15226, + 952, 1239, 1992, 3093, 3498, 4156, 4605, 5695, 7946, 8668, 9684, 11027, 12029, 13102, 14093, 15158, + 558, 828, 1638, 2628, 3361, 4827, 6046, 7182, 8226, 9297, 10326, 11331, 12343, 13333, 14312, 15248, + 543, 797, 1292, 2197, 4031, 4954, 6096, 7133, 8292, 9244, 10253, 11267, 12293, 13293, 14303, 15272, + 562, 818, 1546, 2854, 3792, 5212, 5897, 6697, 8329, 9105, 10103, 11572, 13033, 13866, 14716, 15223, + 897, 1320, 1937, 2717, 3205, 4412, 6880, 7773, 8381, 9585, 10492, 11242, 12589, 13425, 14212, 15053, + 798, 1174, 2038, 2482, 3869, 4999, 5820, 7157, 7807, 9160, 10013, 11078, 12122, 13113, 14028, 14997, + 686, 1000, 2269, 3020, 3755, 5347, 5960, 7664, 8406, 9199, 10485, 11521, 12512, 13361, 14217, 15144, + 715, 1058, 1660, 3282, 4591, 4997, 6361, 7315, 7878, 9084, 10356, 11033, 12186, 13333, 14390, 15279, + 784, 1087, 1584, 3299, 5404, 6007, 6611, 7254, 7870, 8870, 10201, 10911, 11780, 12799, 14077, 15156, + 664, 905, 1952, 4880, 5346, 5934, 6519, 7374, 8530, 9311, 10103, 10819, 11525, 12818, 14071, 15168, + 626, 914, 2854, 4227, 4737, 5634, 6361, 7354, 7918, 8636, 9491, 10701, 11785, 13139, 14220, 15292, + 1793, 3491, 4468, 5330, 6092, 6716, 7382, 8023, 8852, 9777, 10729, 11640, 12576, 13418, 14323, 15182, + 688, 949, 1560, 3990, 5022, 5519, 6194, 6798, 8071, 8773, 9515, 10514, 12712, 13784, 14609, 15400, + 783, 1014, 2824, 3542, 4129, 4903, 5606, 6542, 6965, 7778, 10053, 10913, 11995, 12759, 13498, 15320, + 753, 1093, 2085, 2706, 4391, 5134, 5930, 6777, 7408, 8184, 9523, 10719, 12392, 13543, 14552, 15277, + 920, 1325, 2067, 2928, 3400, 4646, 5913, 6704, 8091, 8819, 9941, 10843, 12080, 13740, 14761, 15449, + 618, 961, 2096, 3325, 4242, 5555, 6567, 7721, 8801, 9891, 10891, 11871, 12871, 13717, 14555, 15310, + 826, 1165, 2466, 3876, 4364, 5723, 6461, 7667, 8417, 9095, 9913, 10755, 11704, 12971, 14239, 15196, + 1056, 1577, 2885, 3726, 4232, 5031, 5736, 6842, 8006, 8903, 10198, 11414, 12536, 13409, 14359, 15205, + 876, 1205, 2453, 3059, 3652, 4312, 5617, 6518, 7542, 8743, 9363, 11286, 13049, 13835, 14643, 15303, + 763, 990, 2805, 3723, 4228, 4936, 5628, 6613, 7058, 7705, 8476, 10130, 11974, 13113, 14180, 15342, + 857, 1152, 1913, 3994, 4629, 5137, 6183, 6861, 7722, 9347, 10177, 10777, 11599, 13112, 14298, 15264, + 656, 1269, 3434, 4621, 5637, 6438, 7220, 7942, 8741, 9612, 10517, 11433, 12435, 13354, 14316, 15237, + 1359, 2605, 3748, 4758, 6042, 7092, 7952, 8651, 9338, 9974, 10723, 11579, 12528, 13418, 14397, 15297, + 1529, 3067, 4410, 5449, 6449, 7233, 7901, 8525, 9237, 10002, 10859, 11784, 12730, 13589, 14467, 15300, + 1790, 3311, 4192, 4897, 5538, 6210, 6922, 7697, 8597, 9590, 10560, 11494, 12426, 13283, 14229, 15138, + 1252, 2359, 3404, 4211, 5155, 6055, 7030, 7899, 8850, 9793, 10761, 11714, 12674, 13565, 14489, 15352, + 590, 998, 2402, 3314, 4528, 5604, 6649, 7644, 8508, 9487, 10408, 11383, 12335, 13276, 14293, 15243, + 727, 1025, 1614, 3818, 5876, 6391, 6980, 7606, 8211, 9304, 10696, 11324, 12381, 13241, 13988, 14791, + 621, 899, 2068, 4152, 5232, 6483, 7323, 8193, 8960, 9627, 10417, 11291, 12234, 13192, 14216, 15187, + 582, 828, 1926, 4025, 4942, 6029, 6957, 7599, 8278, 9093, 10032, 11126, 12233, 13209, 14256, 15311, + 788, 1126, 1690, 3183, 3923, 4599, 6240, 6890, 7758, 9022, 9656, 10453, 11779, 12706, 13913, 15214 +}; + + +const Word16 lsf_cdk_nb_gc_stg1[] = /* 14Q1*1.28 */ +{ + -2046, -827, -3490, -8984, -9331, -8562, -2854, 112, 2194, 13294, 11592, 7952, + -294, 2271, 1647, -1260, -2029, -3649, -4081, -3432, -3649, 333, 5042, 4720, + -1209, 984, -241, -3413, -4476, -4817, -2910, -2016, -2016, 2900, 6868, 5408, + -1900, 896, 688, -197, -33, -993, -1470, -1283, -2145, -665, 2161, 4064, + -1998, -351, -1985, -4742, -4879, -5329, -3500, -2023, -1264, 8507, 9766, 6640, + 245, 3962, 3664, 1935, 1601, 144, -1054, -1236, -2225, -2647, -3746, 1695, + -3051, -1382, -1825, 828, 2537, 1872, 957, 689, -592, 1675, 5507, 5216, + -2178, -281, 2097, 5417, 4372, 1648, -802, -1304, -2817, -754, 3345, 4224, + -3400, -2402, -4098, -3148, -2066, -1985, -558, 466, 705, 11042, 11096, 7424, + 776, 4355, 3200, -1139, -2922, -3985, -2990, -2405, -2881, -661, 2897, 4176, + -1818, 394, -385, -1504, -1545, -2913, -3062, -2451, -2609, 2093, 6387, 5248, + -1081, 2069, 1952, 1345, 1649, 64, -1394, -1526, -2577, -2051, -1025, 2863, + 276, 2780, 1567, -3228, -4881, -5970, -4363, -3523, -3089, 3447, 7300, 5456, + 1917, 6445, 5552, 2069, 684, -1233, -2371, -2377, -3409, -1635, 1616, 3648, + -2734, -1049, -2001, -1927, -1908, -2273, -1294, -652, -944, 4451, 7893, 5888, + -1193, 2108, 5153, 7875, 8214, 6145, 2891, 2001, 208, -1312, -2273, 1599, + -3697, -3538, -6739, -7238, -4524, -2464, 2424, 4591, 6098, 15691, 13066, 8912, + -352, 2108, 847, -247, 1179, -769, -2757, -2873, -3713, 203, 4994, 4688, + -1185, 1565, 703, -1788, -2372, -2721, -1951, -1554, -2129, -374, 2529, 4192, + -2094, 401, 352, 1118, 2376, 1632, 582, 351, -1009, -1389, -784, 3056, + -367, 1637, -145, -5132, -6888, -8178, -5371, -3397, -1776, 9469, 9894, 6752, + 953, 5894, 6785, 5196, 4663, 2400, 31, -598, -2065, -2581, -2786, 1743, + -2637, -1222, -560, 5363, 6867, 5329, 2192, 1264, -544, -508, 1345, 3664, + -1112, 1918, 2976, 3989, 4508, 3104, 1245, 606, -897, -2381, -4258, 1119, + -1983, -328, -2930, -6112, -1802, 144, 486, 194, -960, 4066, 7797, 5872, + 648, 3526, 3104, 562, -200, -2177, -3380, -3162, -3857, -1516, 2433, 3920, + -2908, -722, -417, -181, 290, -352, -352, -175, -1088, 1689, 5603, 5184, + -536, 2771, 2064, 10, -643, -1793, -1733, -1523, -2193, -1813, -1585, 2831, + 2239, 5541, 4400, -637, -2370, -4802, -5148, -3901, -2912, 7328, 9222, 6320, + 8159, 12344, 9921, 5311, 4611, 2480, -1461, -1819, -2032, 5438, 7396, 5968, + -3908, -2998, -3105, 1031, 2171, 1952, 2012, 1982, 1280, 8825, 10343, 7056, + -80, 5935, 10546, 12414, 12351, 9601, 4823, 3380, 1152, -840, -2161, 1967 +}; +const Word16 lsf_cdk_nb_gc_stg2[] = /* 14Q1*1.28 */ +{ + -476, -1387, -3185, 464, 1104, 0, + -1029, -675, 63, -1664, -1168, 0, + -691, -1002, -1697, -1968, -704, 0, + -957, -724, -945, 816, 928, 0, + -1131, -2087, -1296, 2704, 1376, 0, + -1167, -1003, 512, 592, 192, 0, + 492, 517, -721, -3600, -1888, 0, + 489, -147, -1153, -688, -864, 0, + 865, 179, -608, 2000, 1008, 0, + -1286, -1953, -1633, -304, -368, 0, + 2033, 1593, -369, -576, 272, 0, + -718, 685, 751, -192, 192, 0, + 1394, 1172, 1520, -480, -576, 0, + -1455, -466, 2896, 2176, 896, 0, + -1171, 324, 2512, -272, -496, 0, + 4950, 5112, 3536, 1040, 80, 0 +}; +const Word16 lsf_cdk_nb_gc_stg3[] = /* 14Q1*1.28 */ +{ + 1, 6, -801, -3701, -3408, -1712, 2661, 2257, 768, + 4, 11, -481, -1886, -2409, -2353, -652, 1216, 256, + 14, 6, -1713, -1706, -1012, -817, -1158, -369, -97, + 8, 15, 127, -780, -1241, -1617, -2819, -1474, -577, + 13, 6, 2320, 103, -1175, -1681, 297, 1536, 384, + 4, 14, -529, -319, -161, -129, -2113, -4131, -1281, + 0, 5, -2001, -1650, -185, 1040, 2146, 1713, 736, + 12, 4, 320, 1615, 1634, 1376, -1700, -4675, -1697, + 15, 13, -401, -348, -511, -320, 2570, 2865, 944, + 7, 14, 335, -1107, -768, -112, -338, -65, 15, + 13, 15, -1025, 563, -38, -865, -1105, 383, 31, + 4, 6, 1056, 1034, 443, -289, -2357, -1986, -689, + 7, 6, 1008, 1608, 1329, 816, 730, 1312, 432, + 4, 12, -1281, 789, 1794, 1328, -517, -561, -113, + 12, 4, 704, 1656, 2289, 3153, 5215, 3682, 1680, + 11, 15, 2528, 4255, 3539, 2320, -669, -1585, -641 +}; +const Word16 lsf_cdk_nb_vc_stg1[] = /* 14Q1*1.28 */ +{ + -1950, -1358, -4562, -8912, -8626, -8050, -2211, 1051, 4226, 15749, 13194, 8800, + 224, 2532, 175, -5316, -6930, -5601, 381, 515, -416, 3224, 6964, 5584, + -2481, -1570, -3746, -3444, -3066, -3665, -2328, -929, -256, 10781, 10903, 7280, + -164, 2676, 1952, 1170, 1362, 32, -809, -978, -1793, -2288, -3137, 2287, + -1649, -589, -3746, -9056, -6586, -2160, 1693, 1869, 1072, 8982, 10375, 7056, + -1442, 731, -465, -352, 881, 0, -1397, -1476, -2273, -792, 2209, 4048, + -570, 1125, -577, -4067, -5011, -6130, -4457, -3228, -2464, 7796, 9414, 6432, + 314, 2780, 1599, -2442, -4050, -5762, -4680, -3747, -3169, 3706, 7556, 5568, + -3306, -3212, -6178, -5257, -2978, -2209, 33, 2038, 3490, 15396, 13130, 8704, + -303, 2334, 927, -1025, -1877, -2753, -1964, -1602, -2145, -943, 1457, 3872, + -1437, 228, -1633, -3020, -3188, -2833, -1579, -942, -1184, 2482, 6532, 5408, + 2622, 6487, 4448, 511, -1383, -2769, -2495, -2230, -2977, -107, 4082, 4480, + -1897, -706, -2994, -2432, 566, 704, 220, 99, -608, 3533, 7300, 5744, + -2605, -1419, -1376, 1700, 1217, 112, -957, -849, -1633, 1902, 6131, 5296, + 2177, 3621, 751, -6700, -10534, -11698, -2205, 713, 3954, 15329, 12986, 8656, + 7156, 9030, 4704, 653, -2345, -6178, -4996, -1616, 1762, 14213, 12329, 8272, + -997, 238, -2066, -5868, -6868, -7474, -4302, -2171, -623, 12371, 11336, 7600, + 2585, 4011, 959, -298, 477, -353, -2457, -2786, -3233, 5865, 8693, 6064, + -2145, -680, -1553, -1961, -2011, -3249, -3184, -2317, -1968, 5674, 8613, 6080, + 675, 4202, 4128, 2060, 1483, -865, -2647, -2552, -3377, -2094, 64, 3184, + -3084, -2915, -5698, -905, 1626, 2176, 1517, 1566, 1024, 9339, 10663, 7232, + -741, 1377, 1168, 206, 185, -1601, -3079, -2936, -3553, -265, 4402, 4528, + 872, 3048, 799, -4039, -5660, -7890, -7222, -4564, -1792, 10306, 10311, 6992, + 2766, 6132, 4848, -1357, -2881, -4914, -4864, -3528, -2608, 9503, 10134, 6832, + -1649, -1598, -6691, -10943, -5664, -3632, 2663, 6788, 11044, 19895, 15933, 10416, + 530, 3138, 2560, -401, -1453, -3425, -4047, -3463, -3713, 252, 4914, 4672, + -879, 1210, 47, -2253, -2732, -3777, -3689, -2947, -2833, 2110, 6499, 5232, + 5749, 8736, 6865, 3519, 2447, 383, -1446, -1459, -2385, 970, 4146, 4560, + -2556, -1914, -3969, 3390, 7938, 6305, 1777, 560, -928, 1091, 4563, 4928, + -1808, -411, 1313, 6469, 6395, 3680, 398, -149, -1713, -1588, 832, 3360, + 3630, 5517, 2479, -2938, -6552, -10675, -4951, -545, 1441, 13744, 12041, 8080, + 10956, 13776, 9201, 4285, 3873, -801, -5835, -2466, 1233, 13746, 12105, 8192 +}; +const Word16 lsf_cdk_nb_vc_stg2[] = /* 14Q1*1.28 */ +{ + -377, -729, -1793, 400, 1312, 0, + -1197, -1432, -2033, -1936, -1520, 0, + -403, -100, 127, -3232, -3456, 0, + 555, 364, -865, -592, -1264, 0, + -1136, -1968, -2640, 4448, 3824, 0, + -1539, 94, 591, 1600, 1376, 0, + -1564, -393, 2528, -304, -688, 0, + 1075, 823, 1648, -96, -704, 0, + -770, -404, 527, -1648, 64, 0, + -1320, -1678, -1072, 48, -688, 0, + 145, 83, -1089, -3632, -448, 0, + 1994, 1756, 159, 1120, 1504, 0, + 282, -236, -800, 2080, 624, 0, + -1357, -1537, 1008, 2624, 1360, 0, + 2002, 2046, 1215, -2336, -1808, 0, + 3757, 3480, 2592, 1472, 512, 0 +}; +const Word16 lsf_cdk_nb_vc_stg3[] = /* 14Q1*1.28 */ +{ + 3, 5, -657, -4633, -3805, -736, 1304, 1024, 368, + 6, 12, -305, -1836, -2507, -2625, -1818, -241, -305, + 6, 4, -2577, -1854, -1236, -1073, -594, 207, -1, + 2, 2, -80, 643, 38, -993, -3719, -1602, -769, + 13, 10, -625, -1825, -2422, -2449, 2887, 2625, 784, + 6, 0, -336, 315, 466, 560, -2183, -4867, -1345, + 10, 7, -2625, 1255, 2305, 1296, 181, 544, 208, + 0, 7, 912, 1998, 1662, 623, -416, 256, 32, + 10, 6, -1713, -1720, -311, 1408, 2066, 1585, 672, + 7, 11, 15, -1217, -99, -33, -851, -33, -81, + 12, 0, -1680, 556, -499, -897, 454, 896, 256, + 2, 8, 2608, 425, -938, -1937, -1205, 15, -177, + 6, 2, 1504, -796, -939, 80, 2179, 1777, 672, + 3, 13, 1984, 3517, 3171, 2320, -2605, -5651, -1857, + 14, 2, -160, 1660, 2380, 2832, 2924, 2097, 992, + 10, 0, 3857, 3623, 2853, 1728, 1554, 1441, 656 +}; +const Word16 lsf_cdk_wb_gc_stg1[] = /* 14Q1*1.28 */ +{ + -854, -266, -3202, -8408, -10604, -11763, -10826, -9448, -7970, -4784, -3493, -2593, + -2727, -1241, -1489, -1469, -1977, -2529, -2344, -2279, -2273, -1750, -1365, -1505, + -728, 1001, -113, -1594, -2256, -3553, -4619, -4591, -4497, -3300, -2327, -2129, + -590, 1699, 1264, 1187, 300, -865, -1554, -1669, -1649, -1202, -837, -1169, + -1612, -578, -2546, -5013, -6155, -6834, -6779, -6002, -5506, -3988, -2968, -2625, + -1725, 1072, 1280, 74, 277, 672, 1385, 2172, 2688, 2643, 2065, 848, + -86, 3639, 3824, 1931, 2115, 1120, 338, 500, 496, 751, 718, -65, + -1024, 1647, 5377, 9202, 8763, 7665, 5376, 4447, 3824, 2803, 2000, 608, + -2585, -2600, -6211, -11489, -11790, -10322, -5788, -3684, -2289, -465, -33, -289, + -3165, -2478, -3521, -1181, 298, 1632, 2160, 2107, 2272, 2075, 1407, 319, + 1275, 3587, 2848, 570, -26, -1489, -4034, -4818, -5202, -3732, -2550, -2049, + -2614, -1530, -848, 4992, 6996, 8002, 9185, 9172, 9106, 7739, 5862, 3408, + 440, 2263, 751, -3627, -4674, -4978, -4938, -5078, -5554, -5428, -4266, -3361, + -2308, -80, 176, 2603, 3871, 3792, 3219, 2667, 2480, 2189, 1405, 95, + 2569, 6546, 6257, 3885, 2438, 1504, 1431, 1319, 1392, 1337, 942, -65, + -712, 3328, 6290, 10673, 12635, 13827, 14544, 13939, 13619, 10691, 8026, 4768, + 842, 2338, 159, -5945, -8498, -9619, -8197, -7076, -6066, -4502, -3722, -3409, + -1628, 617, -129, -1907, -2194, -1505, -95, 486, 928, 1268, 1071, 175, + 538, 3277, 2111, -1606, -3194, -3553, -2105, -1604, -1393, -974, -740, -1009, + -1279, 456, 2593, 6823, 5435, 3536, 1502, 544, -96, -521, -548, -1105, + -983, 675, -865, -4388, -5936, -5697, -3245, -2211, -1633, -519, -276, -849, + -102, 3506, 2480, 332, -670, -448, 859, 1384, 1776, 1846, 1568, 448, + 270, 5022, 5136, 4435, 4546, 4305, 4185, 4385, 4337, 3659, 2785, 1152, + 216, 5449, 10098, 11459, 11060, 9922, 8139, 7175, 6289, 4794, 3394, 1600, + -3137, -3309, -5826, -6310, -5500, -4385, -2187, -1054, -288, 502, 527, -129, + -2997, -2031, -1344, 2452, 2535, 1856, 912, 451, 272, -124, -515, -993, + 3808, 7001, 5536, 908, -807, -1665, -2041, -2232, -2449, -2206, -1782, -1905, + -1117, 2493, 3616, 4843, 5755, 6273, 6815, 6906, 6769, 5801, 4580, 2528, + 2509, 4911, 3439, -2294, -4945, -7203, -9006, -7957, -6818, -4297, -3321, -3009, + -1110, 1877, 1776, 2112, 2398, 2704, 3465, 3938, 4257, 4039, 3202, 1568, + 7131, 11568, 10626, 7755, 6467, 5073, 4839, 4543, 4128, 3206, 2160, 912, + 2457, 10049, 15204, 18687, 18433, 17364, 14947, 13353, 11682, 8277, 6182, 3232 +}; +const Word16 lsf_cdk_wb_gc_stg2[] = /* 14Q1*1.28 */ +{ + -1224, -2316, -3425, -928, 128, 0, + -1874, -2354, -1025, -624, -448, 0, + -1026, -888, -481, -2352, -1024, 0, + 838, 174, -2306, -4048, -960, 0, + -1336, -2679, -1776, 2464, 1200, 0, + 497, 2649, 3536, 1344, 320, 0, + -1099, 4, 2448, -544, -752, 0, + 993, 486, 592, 64, -480, 0, + 288, -551, -2385, 1824, 2016, 0, + -1090, -815, 128, 1008, 704, 0, + 279, -579, -1729, -560, -832, 0, + 60, 1211, 543, -288, 272, 0, + 480, 1062, 560, 3152, 1680, 0, + -1276, -672, 2961, 2704, 1200, 0, + 1357, 1787, 767, -3424, -2768, 0, + 4229, 3682, 1696, 192, -256, 0 +}; +const Word16 lsf_cdk_wb_gc_stg3[] = /* 14Q1*1.28 */ +{ + 15, 1, -1665, -4778, -4630, -3105, -554, -304, -112, + 13, 10, -753, -1579, -1817, -1953, -2415, -2148, -1697, + 8, 15, 1135, -1716, -3415, -5154, -4958, -3443, -1905, + 4, 1, -32, 570, 443, -65, -2187, -2759, -2561, + 4, 14, 399, -979, -269, 816, 385, -194, -673, + 2, 5, -2161, -1600, -401, -97, -412, -433, -321, + 0, 15, 2128, 3449, 1993, 175, -2815, -2580, -1729, + 3, 2, 400, 714, 1209, 1904, 2711, 2436, 1840, + 9, 13, 143, -1925, -2694, -2545, 358, 930, 960, + 10, 0, -960, 868, 173, -513, -97, 577, 896, + 0, 5, 1824, 11, -1080, -1761, -1565, -1058, -705, + 7, 1, -880, 2304, 2790, 2384, 573, -18, -273, + 5, 8, 1840, 1467, 978, 768, 598, 351, -17, + 6, 7, -1473, -2052, -711, 992, 3166, 2788, 2080, + 7, 12, 1856, 3557, 3483, 3184, 2417, 1923, 1408, + 3, 13, -1649, 1850, 4068, 5073, 4907, 4086, 2976 +}; +const Word16 lsf_cdk_wb_vc_stg1[] = /* 14Q1*1.28 */ +{ + -1159, -1161, -5395, -12785, -14024, -12291, -8572, -6523, -4593, -1979, -1169, -897, + -1903, -921, -2065, -1931, -2752, -3825, -4238, -4174, -4145, -3108, -2167, -2081, + 522, 1696, -513, -6103, -8611, -9571, -9024, -8617, -7826, -5631, -4489, -3761, + -1839, -544, -1280, 1080, 564, 752, 844, 1110, 1344, 1185, 1039, 63, + -2685, -2538, -5074, -6161, -6745, -6738, -5709, -4457, -3377, -1830, -1188, -1185, + -3059, -3565, -6706, -3405, -1183, -272, -112, 33, 160, -5, 13, -721, + 4464, 5425, 1535, -8151, -13242, -15171, -5882, -2159, -288, 176, 739, 1440, + 1431, 2210, -769, -2539, -889, -721, -4378, -6019, -8099, -8147, -6215, -3873, + -1779, -2663, -8548, -12911, -8955, -5265, -1796, -700, 240, 746, 528, -160, + -847, 1228, 735, -1117, -1191, -1857, -2236, -2407, -2321, -1779, -1542, -1665, + -11, 1561, 591, -2764, -3940, -4994, -5679, -5652, -5586, -4852, -3930, -3297, + -783, 2500, 2912, 1480, 864, -64, -492, -833, -769, -353, -452, -1009, + -1207, 305, -1169, -3978, -4167, -3249, -1227, -606, -48, 233, -51, -545, + -2442, -2531, -3873, 5622, 7990, 7025, 4210, 3337, 2576, 1042, 237, -673, + 7644, 9215, 4703, -2206, -6625, -10676, -11281, -8039, -4321, -386, 15, -113, + 5397, 7494, 5296, -39, -1846, -2017, -1875, -1846, -1697, -2156, -2072, -1969, + -279, 230, -3010, -8280, -10317, -11859, -10729, -9576, -7922, -4867, -3862, -2865, + -899, -234, -2897, 3569, 4566, 799, -5740, -7153, -6546, -3276, -2048, -960, + 954, 3319, 1295, -3334, -5133, -5137, -2866, -2245, -1793, -1073, -934, -1281, + -1098, 1538, 1024, 1919, 2978, 3729, 4709, 5431, 5521, 4962, 3843, 1920, + -772, 429, -1810, -5319, -6411, -7074, -6828, -6001, -5266, -3901, -3160, -2833, + -140, 1442, -1153, -2496, -631, 1264, 2033, 3167, 3840, 3225, 2577, 1232, + 2263, 4102, 1167, -4671, -6812, -9651, -10507, -2400, 272, 1823, 1124, -2641, + 3904, 5709, 4800, 1435, -1797, -3682, -7176, -9009, -11812, -10666, -5157, -2353, + 122, 738, -2898, -9698, -11180, -8161, -1527, -926, -352, 476, -116, -705, + 1615, 3938, 3296, -117, -1405, -2593, -4075, -4383, -4273, -3528, -3017, -2881, + 3319, 4999, 2191, -4352, -6684, -7394, -7503, -7494, -6914, -5038, -4138, -3841, + 1933, 5658, 4544, 2619, 2149, 1456, 812, 401, 240, 207, 12, -673, + 1747, 3791, 1295, -236, -1712, -1232, 632, 903, 1488, 1527, 1184, 368, + -1030, 922, 4017, 7665, 6754, 5073, 3236, 1989, 1056, 426, 45, -609, + 12487, 14522, 8896, 2687, 1057, -3810, -10425, -9171, -6482, -2948, -2321, -1169, + 7344, 9906, 7921, 4454, 3289, 2320, 1483, 513, 192, 491, 493, 79 +}; +const Word16 lsf_cdk_wb_vc_stg2[] = /* 14Q1*1.28 */ +{ + -182, -1035, -2593, -176, 528, 0, + -2110, -2904, -2881, -1696, -864, 0, + -160, -876, -1777, -4160, -2112, 0, + 1601, 651, -1393, 208, -896, 0, + -1109, -1806, -2112, 2592, 1360, 0, + -1723, -1575, 1104, 912, 288, 0, + -700, 1343, 687, 1408, 144, 0, + 863, 454, 864, 464, -160, 0, + -1234, -1141, -289, -832, 832, 0, + -230, -608, -480, -1520, -2352, 0, + 1268, 2126, 1919, -3440, -3072, 0, + 1298, 1365, -65, -2832, 672, 0, + 1095, 493, -849, 3184, 3056, 0, + -469, -479, 1617, 3728, 2112, 0, + -675, 1400, 3984, 240, -592, 0, + 2580, 2697, 2432, 1920, 1040, 0 +}; +const Word16 lsf_cdk_wb_vc_stg3[] = /* 14Q1*1.28 */ +{ + 7, 3, -1329, -4391, -3913, -3041, -859, -255, 176, + 13, 7, -2257, -960, -1287, -1649, -1313, -770, -433, + 3, 13, -33, -1650, -2302, -2721, -4039, -3798, -2609, + 10, 4, 0, 1123, 279, -1057, -2271, -1039, 160, + 7, 12, 15, -748, 384, 848, -1029, -1992, -2385, + 4, 1, -2417, -2753, -316, 912, 1240, 993, 704, + 0, 0, 2497, 3043, 1347, -849, -5667, -5913, -4193, + 5, 2, 848, 519, 1737, 2560, 1763, 1506, 912, + 12, 12, 271, -2734, -3306, -736, 1294, 383, -209, + 10, 14, -577, -71, -129, -449, 1561, 2068, 1920, + 14, 1, 1408, -1285, -2943, -4177, -1355, 306, 752, + 15, 8, -2529, 2194, 2953, 2368, 1761, 1377, 816, + 14, 10, 3024, 1322, 224, -304, 514, 511, -81, + 1, 12, -849, -709, 112, 2417, 5221, 4664, 3648, + 1, 9, 160, 3607, 3314, 2016, -333, -884, -1233, + 13, 12, 1888, 3621, 3935, 4000, 3607, 2932, 2128 +}; + +const Word16 *const lsf_codebook[2][2][TCXLPC_NUMSTAGES] = +{ + { + { lsf_cdk_wb_gc_stg1, lsf_cdk_wb_gc_stg2, lsf_cdk_wb_gc_stg3 }, + { lsf_cdk_wb_vc_stg1, lsf_cdk_wb_vc_stg2, lsf_cdk_wb_vc_stg3 } + }, + { + { lsf_cdk_nb_gc_stg1, lsf_cdk_nb_gc_stg2, lsf_cdk_nb_gc_stg3 }, + { lsf_cdk_nb_vc_stg1, lsf_cdk_nb_vc_stg2, lsf_cdk_nb_vc_stg3 } + } +}; + +const Word16 lsf_numbits[TCXLPC_NUMSTAGES] = { 5, 4, 4 }; + +const Word16 lsf_dims[TCXLPC_NUMSTAGES] = { 16, 8, 12 }; +const Word16 lsf_offs[TCXLPC_NUMSTAGES] = { 0, 0, 4 }; + +const Word16 lsf_ind_cdk_nb_gc_stg4[] = /* 14Q1*1.28 */ +{ + -1360, -704, 0, + 80, 256, 0, + -896, 1008, 0, + 960, 2016, 0 +}; +const Word16 lsf_ind_cdk_nb_vc_stg4[] = /* 14Q1*1.28 */ +{ + -1360, -944, 0, + 624, 1408, 0, + -368, 240, 0, + 2480, 3216, 0 +}; +const Word16 lsf_ind_cdk_wb_gc_stg4[] = /* 14Q1*1.28 */ +{ + -1280, -816, 0, + 368, 272, 0, + -704, 1136, 0, + 1296, 2448, 0 +}; +const Word16 lsf_ind_cdk_wb_vc_stg4[] = /* 14Q1*1.28 */ +{ + -1040, -848, 0, + 688, 400, 0, + -560, 1520, 0, + 2256, 2704, 0 +}; + +const Word16 *const lsf_ind_codebook[2][2][TCXLPC_IND_NUMSTAGES] = +{ + { { lsf_ind_cdk_wb_gc_stg4 }, { lsf_ind_cdk_wb_vc_stg4 } }, + { { lsf_ind_cdk_nb_gc_stg4 }, { lsf_ind_cdk_nb_vc_stg4 } } +}; + +const Word16 lsf_ind_numbits[TCXLPC_IND_NUMSTAGES] = { 2 }; + +const Word16 lsf_ind_dims[TCXLPC_IND_NUMSTAGES] = { 4 }; +const Word16 lsf_ind_offs[TCXLPC_IND_NUMSTAGES] = { 0 }; + +const Word16 min_distance_thr[2][2] = /* 14Q1*1.28 */ +{ + /* GC, VC */ + /* WB */ { 580, 580 }, + /* NB */ {1000, 580 } +}; + + +/*14Q1*1.28*/ +const Word16 means_nb_31bits_ma_lsf[16] = {861 /*336.3281f*1.28f Q1*/, 1360 /*531.2500f*1.28f Q1*/, 2270 /*886.7188f*1.28f Q1*/, 3243 /*1266.7969f*1.28f Q1*/, 4171 /*1629.2969f*1.28f Q1*/, 5052 /*1973.4375f*1.28f Q1*/, 6012 /*2348.4375f*1.28f Q1*/, 6776 /*2646.8750f*1.28f Q1*/, 7676 /*2998.4375f*1.28f Q1*/, 8428 /*3292.1875f*1.28f Q1*/, 9194 /*3591.4062f*1.28f Q1*/, 9744 /*3806.2500f*1.28f Q1*/, 10580 /*4132.8125f*1.28f Q1*/, 11911 /*4652.7344f*1.28f Q1*/, 13440 /*5250.0000f*1.28f Q1*/, 15061 /*5883.2031f*1.28f Q1*/}; +const Word16 means_wb_31bits_ma_lsf[16] = {818 /*319.5312f*1.28f Q1*/, 1403 /*548.0469f*1.28f Q1*/, 2392 /*934.3750f*1.28f Q1*/, 3465 /*1353.5156f*1.28f Q1*/, 4429 /*1730.0781f*1.28f Q1*/, 5428 /*2120.3125f*1.28f Q1*/, 6414 /*2505.4688f*1.28f Q1*/, 7323 /*2860.5469f*1.28f Q1*/, 8304 /*3243.7500f*1.28f Q1*/, 9221 /*3601.9531f*1.28f Q1*/, 10162 /*3969.5312f*1.28f Q1*/, 11091 /*4332.4219f*1.28f Q1*/, 12125 /*4736.3281f*1.28f Q1*/, 13153 /*5137.8906f*1.28f Q1*/, 14241 /*5562.8906f*1.28f Q1*/, 15266 /*5963.2812f*1.28f Q1*/}; + + +/*! + * \brief CLDFB prototype filter + * + * cldfb bands: 10 + * delay[ms]: 1.00 + * abs. max Val: 1.04 + * scale: 0.50 + */ +const Word16 CLDFB80_10[] = +{ + W16(0x0000), W16(0xfffc), W16(0xffdf), W16(0x0132), W16(0x23b5), + W16(0x0000), W16(0xffff), W16(0xfff3), W16(0x018d), W16(0x2a98), + W16(0x0000), W16(0x0000), W16(0x0006), W16(0x020d), W16(0x3116), + W16(0x0000), W16(0x0000), W16(0x001a), W16(0x02bd), W16(0x36e2), + W16(0x0000), W16(0x0000), W16(0x001c), W16(0x039f), W16(0x3bb5), + W16(0x0000), W16(0xffff), W16(0x001a), W16(0x04b1), W16(0x3f51), + W16(0x0000), W16(0x0000), W16(0x0024), W16(0x05da), W16(0x419a), + W16(0x0000), W16(0x0000), W16(0x002e), W16(0x06ee), W16(0x428c), + W16(0x0000), W16(0x0000), W16(0x0032), W16(0x07bd), W16(0x4267), + W16(0x0000), W16(0xfffc), W16(0x001b), W16(0x0820), W16(0x410b), + W16(0x0000), W16(0xfff0), W16(0xffe9), W16(0x0806), W16(0x3d82), + W16(0x0000), W16(0xfffe), W16(0xffe6), W16(0x0746), W16(0x37fe), + W16(0x0000), W16(0x0000), W16(0x000d), W16(0x05ae), W16(0x31d1), + W16(0x0000), W16(0x0000), W16(0x002a), W16(0x032f), W16(0x2b60), + W16(0x0000), W16(0xfffd), W16(0x0025), W16(0xffcd), W16(0x24a3), + W16(0x0000), W16(0x0003), W16(0x0004), W16(0xfb88), W16(0x1dc0), + W16(0x0000), W16(0x0000), W16(0xffca), W16(0xf66f), W16(0x16c9), + W16(0x0000), W16(0x0000), W16(0xff95), W16(0xf09a), W16(0x0fe8), + W16(0x0000), W16(0xffff), W16(0xff64), W16(0xea2a), W16(0x08e0), + W16(0x0000), W16(0x0012), W16(0xff21), W16(0xe34c), W16(0x02aa) +}; + +/*! + * \brief CLDFB prototype filter + * + * cldfb bands: 16 + * delay[ms]: 1.00 + * abs. max Val: 1.04 + * scale: 0.50 + */ +const Word16 CLDFB80_16[] = +{ + W16(0x0000), W16(0xfffb), W16(0xffdd), W16(0x0123), W16(0x2266), + W16(0x0000), W16(0xfffe), W16(0xffe7), W16(0x0157), W16(0x26c0), + W16(0x0000), W16(0xffff), W16(0xfff4), W16(0x0194), W16(0x2b04), + W16(0x0000), W16(0xffff), W16(0xfffe), W16(0x01e0), W16(0x2f1f), + W16(0x0000), W16(0x0000), W16(0x000c), W16(0x023f), W16(0x32fc), + W16(0x0000), W16(0x0000), W16(0x0019), W16(0x02b0), W16(0x368c), + W16(0x0000), W16(0x0000), W16(0x001d), W16(0x0336), W16(0x39bc), + W16(0x0000), W16(0x0001), W16(0x0013), W16(0x03cf), W16(0x3c7b), + W16(0x0000), W16(0x0001), W16(0x001a), W16(0x047b), W16(0x3ebd), + W16(0x0000), W16(0x0000), W16(0x001e), W16(0x0532), W16(0x407c), + W16(0x0000), W16(0x0000), W16(0x0025), W16(0x05ec), W16(0x41b3), + W16(0x0000), W16(0xffff), W16(0x002d), W16(0x069d), W16(0x4262), + W16(0x0000), W16(0x0000), W16(0x0031), W16(0x0738), W16(0x429c), + W16(0x0000), W16(0x0000), W16(0x0032), W16(0x07b3), W16(0x4271), + W16(0x0000), W16(0xffff), W16(0x002a), W16(0x0804), W16(0x41d1), + W16(0x0000), W16(0xfff9), W16(0x0015), W16(0x0824), W16(0x40a3), + W16(0x0000), W16(0xffec), W16(0xffee), W16(0x0815), W16(0x3e6c), + W16(0x0000), W16(0xfff7), W16(0xffe0), W16(0x07ca), W16(0x3b3b), + W16(0x0000), W16(0xfffd), W16(0xffe8), W16(0x0734), W16(0x379e), + W16(0x0000), W16(0xfffe), W16(0x0000), W16(0x0647), W16(0x33c7), + W16(0x0000), W16(0xffff), W16(0x0018), W16(0x04ff), W16(0x2fd6), + W16(0x0000), W16(0x0000), W16(0x0029), W16(0x035e), W16(0x2bca), + W16(0x0000), W16(0xffff), W16(0x002b), W16(0x0164), W16(0x279c), + W16(0x0000), W16(0x0001), W16(0x0022), W16(0xff11), W16(0x235b), + W16(0x0000), W16(0xfffc), W16(0x000f), W16(0xfc66), W16(0x1f0d), + W16(0x0000), W16(0x0001), W16(0xffec), W16(0xf966), W16(0x1ab4), + W16(0x0000), W16(0x0000), W16(0xffc6), W16(0xf617), W16(0x165a), + W16(0x0000), W16(0x0001), W16(0xffa5), W16(0xf27f), W16(0x120e), + W16(0x0000), W16(0x0001), W16(0xff86), W16(0xeea6), W16(0x0dbd), + W16(0x0000), W16(0x0001), W16(0xff67), W16(0xea95), W16(0x0950), + W16(0x0000), W16(0x0005), W16(0xff40), W16(0xe657), W16(0x051a), + W16(0x0000), W16(0x001b), W16(0xff12), W16(0xe1fc), W16(0x01c8) +}; + +/*! + * \brief CLDFB prototype filter + * + * cldfb bands: 20 + * delay[ms]: 1.00 + * abs. max Val: 1.04 + * scale: 0.50 + */ +const Word16 CLDFB80_20[] = +{ + W16(0x0000), W16(0xfffb), W16(0xffdf), W16(0x011e), W16(0x21f7), + W16(0x0000), W16(0xfffd), W16(0xffe1), W16(0x0146), W16(0x2573), + W16(0x0000), W16(0xffff), W16(0xfff2), W16(0x0173), W16(0x28e6), + W16(0x0000), W16(0xffff), W16(0xfff6), W16(0x01a9), W16(0x2c45), + W16(0x0000), W16(0xffff), W16(0xffff), W16(0x01e9), W16(0x2f84), + W16(0x0000), W16(0x0000), W16(0x000a), W16(0x0235), W16(0x329c), + W16(0x0000), W16(0x0000), W16(0x0014), W16(0x028c), W16(0x3583), + W16(0x0000), W16(0x0000), W16(0x001b), W16(0x02f1), W16(0x3831), + W16(0x0000), W16(0x0000), W16(0x001e), W16(0x0362), W16(0x3a9c), + W16(0x0000), W16(0x0001), W16(0x000d), W16(0x03df), W16(0x3cbb), + W16(0x0000), W16(0x0000), W16(0x001b), W16(0x0469), W16(0x3e89), + W16(0x0000), W16(0x0000), W16(0x001c), W16(0x04fb), W16(0x4004), + W16(0x0000), W16(0x0000), W16(0x0020), W16(0x0590), W16(0x4129), + W16(0x0000), W16(0x0000), W16(0x0027), W16(0x0622), W16(0x41f5), + W16(0x0000), W16(0x0000), W16(0x002e), W16(0x06ad), W16(0x426d), + W16(0x0000), W16(0x0000), W16(0x0030), W16(0x072a), W16(0x429b), + W16(0x0000), W16(0x0000), W16(0x0032), W16(0x0792), W16(0x4288), + W16(0x0000), W16(0x0001), W16(0x002e), W16(0x07e1), W16(0x4232), + W16(0x0000), W16(0xfffe), W16(0x0024), W16(0x0813), W16(0x4186), + W16(0x0000), W16(0xfff8), W16(0x0011), W16(0x0825), W16(0x407d), + W16(0x0000), W16(0xffed), W16(0xfff1), W16(0x0818), W16(0x3eb8), + W16(0x0000), W16(0xfff5), W16(0xffe3), W16(0x07e8), W16(0x3c3c), + W16(0x0000), W16(0xfffe), W16(0xffe1), W16(0x0789), W16(0x3977), + W16(0x0000), W16(0xfffd), W16(0xffee), W16(0x06f6), W16(0x367b), + W16(0x0000), W16(0xfffe), W16(0x0002), W16(0x062a), W16(0x3363), + W16(0x0000), W16(0xffff), W16(0x0016), W16(0x0524), W16(0x303c), + W16(0x0000), W16(0x0000), W16(0x0026), W16(0x03e4), W16(0x2d04), + W16(0x0000), W16(0x0000), W16(0x002d), W16(0x026c), W16(0x29b7), + W16(0x0000), W16(0xfffe), W16(0x0029), W16(0x00bb), W16(0x2657), + W16(0x0000), W16(0x0005), W16(0x0021), W16(0xfed0), W16(0x22ed), + W16(0x0000), W16(0xfff8), W16(0x0014), W16(0xfcae), W16(0x1f7c), + W16(0x0000), W16(0x0002), W16(0xfff7), W16(0xfa55), W16(0x1c03), + W16(0x0000), W16(0x0000), W16(0xffd8), W16(0xf7c8), W16(0x1886), + W16(0x0000), W16(0x0001), W16(0xffbc), W16(0xf50a), W16(0x150f), + W16(0x0000), W16(0x0001), W16(0xffa2), W16(0xf21f), W16(0x11a0), + W16(0x0000), W16(0x0001), W16(0xff89), W16(0xef0b), W16(0x0e2c), + W16(0x0000), W16(0x0001), W16(0xff71), W16(0xebd2), W16(0x0aa5), + W16(0x0000), W16(0xfffe), W16(0xff55), W16(0xe87a), W16(0x0724), + W16(0x0000), W16(0x0006), W16(0xff33), W16(0xe50a), W16(0x03fd), + W16(0x0000), W16(0x001e), W16(0xff0d), W16(0xe18b), W16(0x017f) +}; + +/*! + * \brief CLDFB prototype filter + * + * cldfb bands: 32 + * delay[ms]: 1.00 + * abs. max Val: 1.04 + * scale: 0.50 + */ +const Word16 CLDFB80_32[] = +{ + W16(0x0000), W16(0xfffb), W16(0xffe2), W16(0x0115), W16(0x214f), + W16(0x0000), W16(0xfffc), W16(0xffde), W16(0x012f), W16(0x237e), + W16(0x0000), W16(0xfffd), W16(0xffe2), W16(0x0149), W16(0x25ab), + W16(0x0000), W16(0xfffe), W16(0xffec), W16(0x0165), W16(0x27d4), + W16(0x0000), W16(0xffff), W16(0xfff4), W16(0x0183), W16(0x29f6), + W16(0x0000), W16(0xffff), W16(0xfff6), W16(0x01a6), W16(0x2c10), + W16(0x0000), W16(0xffff), W16(0xfffb), W16(0x01cc), W16(0x2e1d), + W16(0x0000), W16(0xffff), W16(0x0001), W16(0x01f6), W16(0x301c), + W16(0x0000), W16(0x0000), W16(0x0009), W16(0x0226), W16(0x320b), + W16(0x0000), W16(0x0000), W16(0x000f), W16(0x025a), W16(0x33e7), + W16(0x0000), W16(0x0000), W16(0x0015), W16(0x0292), W16(0x35b0), + W16(0x0000), W16(0x0000), W16(0x001b), W16(0x02d0), W16(0x3761), + W16(0x0000), W16(0x0000), W16(0x001d), W16(0x0313), W16(0x38fa), + W16(0x0000), W16(0x0000), W16(0x001e), W16(0x035a), W16(0x3a77), + W16(0x0000), W16(0x0000), W16(0x001b), W16(0x03a7), W16(0x3bd7), + W16(0x0000), W16(0x0000), W16(0x0004), W16(0x03f7), W16(0x3d18), + W16(0x0000), W16(0xffff), W16(0x001b), W16(0x044e), W16(0x3e38), + W16(0x0000), W16(0xffff), W16(0x001a), W16(0x04a8), W16(0x3f39), + W16(0x0000), W16(0x0000), W16(0x001c), W16(0x0504), W16(0x4018), + W16(0x0000), W16(0x0001), W16(0x001f), W16(0x0561), W16(0x40d6), + W16(0x0000), W16(0x0000), W16(0x0022), W16(0x05be), W16(0x4172), + W16(0x0000), W16(0x0000), W16(0x0027), W16(0x0619), W16(0x41eb), + W16(0x0000), W16(0xffff), W16(0x002c), W16(0x0672), W16(0x4242), + W16(0x0000), W16(0x0000), W16(0x002e), W16(0x06c6), W16(0x427b), + W16(0x0000), W16(0x0000), W16(0x002f), W16(0x0714), W16(0x4297), + W16(0x0000), W16(0x0000), W16(0x0031), W16(0x075a), W16(0x429a), + W16(0x0000), W16(0x0000), W16(0x0032), W16(0x0798), W16(0x4285), + W16(0x0000), W16(0x0001), W16(0x0031), W16(0x07cb), W16(0x4255), + W16(0x0000), W16(0xffff), W16(0x002c), W16(0x07f4), W16(0x4206), + W16(0x0000), W16(0xfffe), W16(0x0025), W16(0x0811), W16(0x4193), + W16(0x0000), W16(0xfffb), W16(0x001a), W16(0x0821), W16(0x40fa), + W16(0x0000), W16(0xfff5), W16(0x000b), W16(0x0823), W16(0x404a), + W16(0x0000), W16(0xfff0), W16(0xfff6), W16(0x081b), W16(0x3f2f), + W16(0x0000), W16(0xffef), W16(0xffe9), W16(0x0809), W16(0x3daa), + W16(0x0000), W16(0xfff5), W16(0xffe2), W16(0x07e4), W16(0x3c12), + W16(0x0000), W16(0xfffa), W16(0xffe0), W16(0x07ac), W16(0x3a5c), + W16(0x0000), W16(0xffff), W16(0xffe4), W16(0x0761), W16(0x388d), + W16(0x0000), W16(0xfffd), W16(0xffed), W16(0x0701), W16(0x36ac), + W16(0x0000), W16(0xfffe), W16(0xfff9), W16(0x068a), W16(0x34c0), + W16(0x0000), W16(0xffff), W16(0x0006), W16(0x05fd), W16(0x32cd), + W16(0x0000), W16(0x0000), W16(0x0013), W16(0x0559), W16(0x30d4), + W16(0x0000), W16(0x0000), W16(0x001d), W16(0x049f), W16(0x2ed6), + W16(0x0000), W16(0x0000), W16(0x0026), W16(0x03cf), W16(0x2cd0), + W16(0x0000), W16(0x0000), W16(0x002c), W16(0x02e8), W16(0x2ac1), + W16(0x0000), W16(0x0000), W16(0x002c), W16(0x01eb), W16(0x28aa), + W16(0x0000), W16(0xfffe), W16(0x0029), W16(0x00d7), W16(0x268d), + W16(0x0000), W16(0xfffd), W16(0x0024), W16(0xffae), W16(0x246c), + W16(0x0000), W16(0x000a), W16(0x0021), W16(0xfe6e), W16(0x2248), + W16(0x0000), W16(0xfff3), W16(0x001a), W16(0xfd19), W16(0x2022), + W16(0x0000), W16(0x0003), W16(0x0006), W16(0xfbad), W16(0x1df8), + W16(0x0000), W16(0x0002), W16(0xfff5), W16(0xfa2d), W16(0x1bcb), + W16(0x0000), W16(0xffff), W16(0xffe2), W16(0xf899), W16(0x199d), + W16(0x0000), W16(0x0001), W16(0xffcf), W16(0xf6f2), W16(0x1770), + W16(0x0000), W16(0x0001), W16(0xffbd), W16(0xf537), W16(0x1546), + W16(0x0000), W16(0x0001), W16(0xffad), W16(0xf36b), W16(0x1320), + W16(0x0000), W16(0x0000), W16(0xff9d), W16(0xf18e), W16(0x10fc), + W16(0x0000), W16(0x0001), W16(0xff8e), W16(0xefa2), W16(0x0ed3), + W16(0x0000), W16(0x0001), W16(0xff7f), W16(0xeda7), W16(0x0ca3), + W16(0x0000), W16(0x0001), W16(0xff6f), W16(0xeb9e), W16(0x0a6c), + W16(0x0000), W16(0xfffd), W16(0xff5e), W16(0xe989), W16(0x0837), + W16(0x0000), W16(0x0003), W16(0xff4b), W16(0xe769), W16(0x0618), + W16(0x0000), W16(0x0006), W16(0xff35), W16(0xe542), W16(0x042a), + W16(0x0000), W16(0x0013), W16(0xff1e), W16(0xe314), W16(0x0284), + W16(0x0000), W16(0x0020), W16(0xff06), W16(0xe0e2), W16(0x010c) +}; + +/*! + * \brief CLDFB prototype filter + * + * cldfb bands: 40 + * delay[ms]: 1.00 + * abs. max Val: 1.04 + * scale: 0.50 + */ +const Word16 CLDFB80_40[] = +{ + W16(0x0000), W16(0xfffa), W16(0xffe2), W16(0x0112), W16(0x2117), + W16(0x0000), W16(0xfffb), W16(0xffdc), W16(0x0128), W16(0x22d6), + W16(0x0000), W16(0xfffc), W16(0xffe0), W16(0x013c), W16(0x2494), + W16(0x0000), W16(0xfffe), W16(0xffe5), W16(0x0151), W16(0x2651), + W16(0x0000), W16(0xffff), W16(0xffed), W16(0x0167), W16(0x280b), + W16(0x0000), W16(0xffff), W16(0xfff4), W16(0x0180), W16(0x29c0), + W16(0x0000), W16(0xffff), W16(0xfff4), W16(0x019b), W16(0x2b6f), + W16(0x0000), W16(0xffff), W16(0xfff8), W16(0x01b8), W16(0x2d18), + W16(0x0000), W16(0xffff), W16(0xfffd), W16(0x01d8), W16(0x2eb8), + W16(0x0000), W16(0xffff), W16(0x0002), W16(0x01fb), W16(0x304e), + W16(0x0000), W16(0x0000), W16(0x0008), W16(0x0221), W16(0x31da), + W16(0x0000), W16(0x0000), W16(0x000d), W16(0x0249), W16(0x335a), + W16(0x0000), W16(0x0000), W16(0x0013), W16(0x0275), W16(0x34ce), + W16(0x0000), W16(0x0000), W16(0x0017), W16(0x02a4), W16(0x3634), + W16(0x0000), W16(0x0000), W16(0x001b), W16(0x02d6), W16(0x378b), + W16(0x0000), W16(0x0000), W16(0x001d), W16(0x030c), W16(0x38d3), + W16(0x0000), W16(0x0000), W16(0x001e), W16(0x0344), W16(0x3a08), + W16(0x0000), W16(0x0000), W16(0x001e), W16(0x0380), W16(0x3b2b), + W16(0x0000), W16(0x0000), W16(0x0017), W16(0x03bf), W16(0x3c3b), + W16(0x0000), W16(0xffff), W16(0x0002), W16(0x03ff), W16(0x3d36), + W16(0x0000), W16(0xffff), W16(0x001a), W16(0x0445), W16(0x3e1d), + W16(0x0000), W16(0x0000), W16(0x001a), W16(0x048d), W16(0x3eef), + W16(0x0000), W16(0x0000), W16(0x001b), W16(0x04d6), W16(0x3fad), + W16(0x0000), W16(0x0000), W16(0x001d), W16(0x0520), W16(0x4055), + W16(0x0000), W16(0x0001), W16(0x001f), W16(0x056a), W16(0x40e8), + W16(0x0000), W16(0xffff), W16(0x0021), W16(0x05b5), W16(0x4164), + W16(0x0000), W16(0x0000), W16(0x0026), W16(0x05fe), W16(0x41ca), + W16(0x0000), W16(0x0000), W16(0x0029), W16(0x0646), W16(0x421b), + W16(0x0000), W16(0xffff), W16(0x002d), W16(0x068c), W16(0x4256), + W16(0x0000), W16(0x0000), W16(0x002e), W16(0x06ce), W16(0x427f), + W16(0x0000), W16(0x0000), W16(0x002f), W16(0x070c), W16(0x4295), + W16(0x0000), W16(0x0000), W16(0x0031), W16(0x0746), W16(0x429c), + W16(0x0000), W16(0x0000), W16(0x0032), W16(0x077a), W16(0x4293), + W16(0x0000), W16(0x0000), W16(0x0032), W16(0x07a8), W16(0x427a), + W16(0x0000), W16(0x0001), W16(0x0030), W16(0x07d0), W16(0x424f), + W16(0x0000), W16(0xffff), W16(0x002d), W16(0x07f0), W16(0x4210), + W16(0x0000), W16(0xffff), W16(0x0028), W16(0x080a), W16(0x41ba), + W16(0x0000), W16(0xfffd), W16(0x001f), W16(0x081b), W16(0x414b), + W16(0x0000), W16(0xfffa), W16(0x0018), W16(0x0824), W16(0x40c6), + W16(0x0000), W16(0xfff4), W16(0x0009), W16(0x0822), W16(0x403a), + W16(0xffff), W16(0xfff1), W16(0xfff9), W16(0x081c), W16(0x3f57), + W16(0x0000), W16(0xffed), W16(0xffec), W16(0x0810), W16(0x3e1f), + W16(0x0000), W16(0xfff3), W16(0xffe6), W16(0x07f9), W16(0x3ce2), + W16(0x0000), W16(0xfff6), W16(0xffe1), W16(0x07d5), W16(0x3b92), + W16(0x0000), W16(0xfffb), W16(0xffe0), W16(0x07a6), W16(0x3a2f), + W16(0x0000), W16(0xffff), W16(0xffe3), W16(0x076a), W16(0x38bc), + W16(0x0000), W16(0xfffd), W16(0xffea), W16(0x0720), W16(0x373e), + W16(0x0000), W16(0xfffd), W16(0xfff3), W16(0x06c8), W16(0x35b7), + W16(0x0000), W16(0xfffe), W16(0xfffd), W16(0x0662), W16(0x342a), + W16(0x0000), W16(0xffff), W16(0x0008), W16(0x05ee), W16(0x329a), + W16(0x0000), W16(0x0000), W16(0x0011), W16(0x056b), W16(0x3107), + W16(0x0000), W16(0xffff), W16(0x001a), W16(0x04d9), W16(0x2f70), + W16(0x0000), W16(0x0000), W16(0x0022), W16(0x043a), W16(0x2dd4), + W16(0x0000), W16(0x0000), W16(0x0028), W16(0x038c), W16(0x2c33), + W16(0x0000), W16(0x0000), W16(0x002c), W16(0x02cf), W16(0x2a8c), + W16(0x0000), W16(0x0001), W16(0x002d), W16(0x0205), W16(0x28e0), + W16(0x0000), W16(0xffff), W16(0x002b), W16(0x012c), W16(0x2730), + W16(0x0000), W16(0xfffd), W16(0x0027), W16(0x0045), W16(0x257d), + W16(0x0000), W16(0xffff), W16(0x0023), W16(0xff50), W16(0x23c8), + W16(0x0000), W16(0x000a), W16(0x0021), W16(0xfe4d), W16(0x2211), + W16(0x0000), W16(0xfff3), W16(0x001c), W16(0xfd3c), W16(0x2059), + W16(0x0000), W16(0x0000), W16(0x000b), W16(0xfc1c), W16(0x1e9e), + W16(0x0000), W16(0x0003), W16(0xfffd), W16(0xfaf0), W16(0x1ce2), + W16(0x0000), W16(0x0001), W16(0xffef), W16(0xf9b6), W16(0x1b24), + W16(0x0000), W16(0xfffe), W16(0xffe0), W16(0xf870), W16(0x1965), + W16(0x0000), W16(0x0001), W16(0xffd1), W16(0xf71d), W16(0x17a7), + W16(0x0000), W16(0x0000), W16(0xffc3), W16(0xf5be), W16(0x15ec), + W16(0x0000), W16(0x0001), W16(0xffb5), W16(0xf453), W16(0x1433), + W16(0x0000), W16(0x0001), W16(0xffa8), W16(0xf2de), W16(0x127c), + W16(0x0000), W16(0x0000), W16(0xff9b), W16(0xf15e), W16(0x10c5), + W16(0x0000), W16(0x0001), W16(0xff8f), W16(0xefd4), W16(0x0f0b), + W16(0x0000), W16(0x0001), W16(0xff83), W16(0xee40), W16(0x0d4c), + W16(0x0000), W16(0x0001), W16(0xff77), W16(0xeca4), W16(0x0b88), + W16(0x0000), W16(0x0001), W16(0xff6a), W16(0xeaff), W16(0x09c2), + W16(0x0000), W16(0xfffd), W16(0xff5d), W16(0xe953), W16(0x0800), + W16(0x0000), W16(0x0002), W16(0xff4d), W16(0xe7a0), W16(0x064d), + W16(0x0000), W16(0x0006), W16(0xff3c), W16(0xe5e8), W16(0x04b8), + W16(0x0000), W16(0x0009), W16(0xff2a), W16(0xe42c), W16(0x034d), + W16(0x0000), W16(0x0018), W16(0xff17), W16(0xe26c), W16(0x0212), + W16(0x0001), W16(0x0020), W16(0xff03), W16(0xe0aa), W16(0x00e3) +}; + +/*! + * \brief CLDFB prototype filter + * + * cldfb bands: 60 + * delay[ms]: 1.00 + * abs. max Val: 1.04 + * scale: 0.50 + */ +const Word16 CLDFB80_60[] = +{ + W16(0x0000), W16(0xfffa), W16(0xffe2), W16(0x010f), W16(0x20cd), + W16(0x0000), W16(0xfffb), W16(0xffdf), W16(0x011e), W16(0x21f7), + W16(0x0000), W16(0xfffb), W16(0xffdd), W16(0x012b), W16(0x2320), + W16(0x0000), W16(0xfffd), W16(0xffe0), W16(0x0138), W16(0x244a), + W16(0x0000), W16(0xfffd), W16(0xffe1), W16(0x0146), W16(0x2573), + W16(0x0000), W16(0xfffe), W16(0xffe6), W16(0x0155), W16(0x269b), + W16(0x0000), W16(0xfffe), W16(0xffec), W16(0x0164), W16(0x27c1), + W16(0x0000), W16(0xffff), W16(0xfff2), W16(0x0173), W16(0x28e6), + W16(0x0000), W16(0xffff), W16(0xfff4), W16(0x0184), W16(0x2a08), + W16(0x0000), W16(0xffff), W16(0xfff4), W16(0x0196), W16(0x2b28), + W16(0x0000), W16(0xffff), W16(0xfff6), W16(0x01a9), W16(0x2c45), + W16(0x0000), W16(0xffff), W16(0xfff9), W16(0x01bd), W16(0x2d5e), + W16(0x0000), W16(0xffff), W16(0xfffc), W16(0x01d2), W16(0x2e73), + W16(0x0000), W16(0xffff), W16(0xffff), W16(0x01e9), W16(0x2f84), + W16(0x0000), W16(0x0000), W16(0x0003), W16(0x0201), W16(0x3091), + W16(0x0000), W16(0x0000), W16(0x0008), W16(0x021a), W16(0x3199), + W16(0x0000), W16(0x0000), W16(0x000a), W16(0x0235), W16(0x329c), + W16(0x0000), W16(0x0000), W16(0x000e), W16(0x0251), W16(0x3399), + W16(0x0000), W16(0x0000), W16(0x0012), W16(0x026e), W16(0x3491), + W16(0x0000), W16(0x0000), W16(0x0014), W16(0x028c), W16(0x3583), + W16(0x0000), W16(0x0000), W16(0x0018), W16(0x02ac), W16(0x366f), + W16(0x0000), W16(0x0000), W16(0x001b), W16(0x02ce), W16(0x3753), + W16(0x0000), W16(0x0000), W16(0x001b), W16(0x02f1), W16(0x3831), + W16(0x0000), W16(0x0000), W16(0x001d), W16(0x0315), W16(0x3907), + W16(0x0000), W16(0x0000), W16(0x001e), W16(0x033b), W16(0x39d6), + W16(0x0000), W16(0x0000), W16(0x001e), W16(0x0362), W16(0x3a9c), + W16(0x0000), W16(0x0000), W16(0x001d), W16(0x038a), W16(0x3b5a), + W16(0x0000), W16(0x0000), W16(0x0019), W16(0x03b4), W16(0x3c0f), + W16(0x0000), W16(0x0001), W16(0x000d), W16(0x03df), W16(0x3cbb), + W16(0x0000), W16(0xffff), W16(0x0001), W16(0x040a), W16(0x3d5e), + W16(0x0000), W16(0xfffe), W16(0x0017), W16(0x0439), W16(0x3df8), + W16(0x0000), W16(0x0000), W16(0x001b), W16(0x0469), W16(0x3e89), + W16(0x0000), W16(0x0000), W16(0x001a), W16(0x0499), W16(0x3f10), + W16(0x0000), W16(0x0000), W16(0x001a), W16(0x04c9), W16(0x3f8f), + W16(0x0000), W16(0x0000), W16(0x001c), W16(0x04fb), W16(0x4004), + W16(0x0000), W16(0x0000), W16(0x001e), W16(0x052c), W16(0x406f), + W16(0x0000), W16(0x0001), W16(0x001f), W16(0x055e), W16(0x40d1), + W16(0x0000), W16(0x0000), W16(0x0020), W16(0x0590), W16(0x4129), + W16(0x0000), W16(0x0000), W16(0x0022), W16(0x05c1), W16(0x4177), + W16(0x0000), W16(0x0000), W16(0x0025), W16(0x05f2), W16(0x41bb), + W16(0x0000), W16(0x0000), W16(0x0027), W16(0x0622), W16(0x41f5), + W16(0x0000), W16(0xffff), W16(0x002a), W16(0x0652), W16(0x4226), + W16(0x0000), W16(0xffff), W16(0x002c), W16(0x0680), W16(0x424e), + W16(0x0000), W16(0x0000), W16(0x002e), W16(0x06ad), W16(0x426d), + W16(0x0000), W16(0x0000), W16(0x002e), W16(0x06d9), W16(0x4284), + W16(0x0000), W16(0x0000), W16(0x002f), W16(0x0702), W16(0x4293), + W16(0x0000), W16(0x0000), W16(0x0030), W16(0x072a), W16(0x429b), + W16(0x0000), W16(0x0000), W16(0x0031), W16(0x074f), W16(0x429b), + W16(0x0000), W16(0x0000), W16(0x0032), W16(0x0772), W16(0x4295), + W16(0x0000), W16(0x0000), W16(0x0032), W16(0x0792), W16(0x4288), + W16(0x0000), W16(0x0000), W16(0x0032), W16(0x07af), W16(0x4274), + W16(0x0000), W16(0x0001), W16(0x0031), W16(0x07ca), W16(0x4257), + W16(0x0000), W16(0x0001), W16(0x002e), W16(0x07e1), W16(0x4232), + W16(0x0000), W16(0xffff), W16(0x002c), W16(0x07f5), W16(0x4203), + W16(0x0000), W16(0xfffe), W16(0x0029), W16(0x0806), W16(0x41ca), + W16(0x0000), W16(0xfffe), W16(0x0024), W16(0x0813), W16(0x4186), + W16(0x0000), W16(0xfffd), W16(0x001e), W16(0x081d), W16(0x4137), + W16(0x0000), W16(0xfffa), W16(0x0019), W16(0x0823), W16(0x40de), + W16(0x0000), W16(0xfff8), W16(0x0011), W16(0x0825), W16(0x407d), + W16(0xffff), W16(0xfff3), W16(0x0006), W16(0x0821), W16(0x4023), + W16(0xffff), W16(0xfff2), W16(0xfffb), W16(0x081d), W16(0x3f8c), + W16(0x0000), W16(0xffed), W16(0xfff1), W16(0x0818), W16(0x3eb8), + W16(0x0000), W16(0xffee), W16(0xffeb), W16(0x080d), W16(0x3deb), + W16(0x0000), W16(0xfff2), W16(0xffe7), W16(0x07fd), W16(0x3d18), + W16(0x0000), W16(0xfff5), W16(0xffe3), W16(0x07e8), W16(0x3c3c), + W16(0x0000), W16(0xfff7), W16(0xffe0), W16(0x07ce), W16(0x3b58), + W16(0x0000), W16(0xfffa), W16(0xffe0), W16(0x07ae), W16(0x3a6b), + W16(0x0000), W16(0xfffe), W16(0xffe1), W16(0x0789), W16(0x3977), + W16(0x0000), W16(0xffff), W16(0xffe4), W16(0x075e), W16(0x387d), + W16(0x0000), W16(0xfffd), W16(0xffe8), W16(0x072d), W16(0x377e), + W16(0x0000), W16(0xfffd), W16(0xffee), W16(0x06f6), W16(0x367b), + W16(0x0000), W16(0xfffe), W16(0xfff4), W16(0x06b8), W16(0x3575), + W16(0x0000), W16(0xfffe), W16(0xfffb), W16(0x0674), W16(0x346d), + W16(0x0000), W16(0xfffe), W16(0x0002), W16(0x062a), W16(0x3363), + W16(0x0000), W16(0xffff), W16(0x000a), W16(0x05d9), W16(0x3257), + W16(0x0000), W16(0x0000), W16(0x0010), W16(0x0582), W16(0x314b), + W16(0x0000), W16(0xffff), W16(0x0016), W16(0x0524), W16(0x303c), + W16(0x0000), W16(0xffff), W16(0x001b), W16(0x04c0), W16(0x2f2c), + W16(0x0000), W16(0x0000), W16(0x0021), W16(0x0455), W16(0x2e19), + W16(0x0000), W16(0x0000), W16(0x0026), W16(0x03e4), W16(0x2d04), + W16(0x0000), W16(0x0000), W16(0x0029), W16(0x036d), W16(0x2bed), + W16(0x0000), W16(0x0000), W16(0x002c), W16(0x02f0), W16(0x2ad3), + W16(0x0000), W16(0x0000), W16(0x002d), W16(0x026c), W16(0x29b7), + W16(0x0000), W16(0x0000), W16(0x002c), W16(0x01e2), W16(0x2898), + W16(0x0000), W16(0xffff), W16(0x002b), W16(0x0151), W16(0x2778), + W16(0x0000), W16(0xfffe), W16(0x0029), W16(0x00bb), W16(0x2657), + W16(0x0000), W16(0xfffd), W16(0x0026), W16(0x001d), W16(0x2534), + W16(0x0000), W16(0xfffe), W16(0x0024), W16(0xff7a), W16(0x2411), + W16(0x0000), W16(0x0005), W16(0x0021), W16(0xfed0), W16(0x22ed), + W16(0x0000), W16(0x0009), W16(0x0021), W16(0xfe21), W16(0x21c8), + W16(0x0000), W16(0xfff5), W16(0x001f), W16(0xfd6b), W16(0x20a2), + W16(0x0000), W16(0xfff8), W16(0x0014), W16(0xfcae), W16(0x1f7c), + W16(0x0000), W16(0x0001), W16(0x0009), W16(0xfbeb), W16(0x1e54), + W16(0x0000), W16(0x0003), W16(0x0000), W16(0xfb23), W16(0x1d2c), + W16(0x0000), W16(0x0002), W16(0xfff7), W16(0xfa55), W16(0x1c03), + W16(0x0000), W16(0x0001), W16(0xffed), W16(0xf981), W16(0x1ad9), + W16(0x0000), W16(0xffff), W16(0xffe3), W16(0xf8a7), W16(0x19b0), + W16(0x0000), W16(0x0000), W16(0xffd8), W16(0xf7c8), W16(0x1886), + W16(0x0000), W16(0x0001), W16(0xffcf), W16(0xf6e3), W16(0x175d), + W16(0x0000), W16(0x0000), W16(0xffc5), W16(0xf5f9), W16(0x1636), + W16(0x0000), W16(0x0001), W16(0xffbc), W16(0xf50a), W16(0x150f), + W16(0x0000), W16(0x0001), W16(0xffb3), W16(0xf416), W16(0x13e9), + W16(0x0000), W16(0x0001), W16(0xffaa), W16(0xf31d), W16(0x12c5), + W16(0x0000), W16(0x0001), W16(0xffa2), W16(0xf21f), W16(0x11a0), + W16(0x0000), W16(0x0000), W16(0xff99), W16(0xf11d), W16(0x107b), + W16(0x0000), W16(0x0000), W16(0xff91), W16(0xf016), W16(0x0f55), + W16(0x0000), W16(0x0001), W16(0xff89), W16(0xef0b), W16(0x0e2c), + W16(0x0000), W16(0x0001), W16(0xff81), W16(0xedfc), W16(0x0d01), + W16(0x0000), W16(0x0001), W16(0xff79), W16(0xece9), W16(0x0bd4), + W16(0x0000), W16(0x0001), W16(0xff71), W16(0xebd2), W16(0x0aa5), + W16(0x0000), W16(0x0001), W16(0xff68), W16(0xeab8), W16(0x0976), + W16(0x0000), W16(0xfffd), W16(0xff5f), W16(0xe99b), W16(0x084a), + W16(0x0000), W16(0xfffe), W16(0xff55), W16(0xe87a), W16(0x0724), + W16(0x0000), W16(0x0003), W16(0xff4a), W16(0xe757), W16(0x0607), + W16(0x0000), W16(0x0006), W16(0xff3f), W16(0xe632), W16(0x04f9), + W16(0x0000), W16(0x0006), W16(0xff33), W16(0xe50a), W16(0x03fd), + W16(0x0000), W16(0x000c), W16(0xff27), W16(0xe3e1), W16(0x0315), + W16(0x0000), W16(0x0016), W16(0xff1a), W16(0xe2b7), W16(0x0244), + W16(0x0000), W16(0x001e), W16(0xff0d), W16(0xe18b), W16(0x017f), + W16(0x0002), W16(0x0020), W16(0xff00), W16(0xe05e), W16(0x00a9) +}; + + +/*! + * \brief CLDFB rRotVectr + * + * cldfb bands: 10 + * global gain: 8.00 + * scale: sqrt(1.0/16.00) + */ +const Word16 rRotVectr_10[] = +{ + W16(0x5a71), W16(0x54ea), W16(0x4714), W16(0x3249), W16(0x1891) +}; + +/*! + * \brief CLDFB iRotVectr + * + * cldfb bands: 10 + * global gain: 8.00 + * scale: sqrt(1.0/16.00) + */ +const Word16 iRotVectr_10[] = +{ + W16(0xfc72), W16(0xe0ac), W16(0xc7f7), W16(0xb4be), W16(0xa8e3) +}; + +/*! + * \brief CLDFB rRotVectr + * + * cldfb bands: 16 + * global gain: 5.00 + * scale: sqrt(1.0/8.00) + */ +const Word16 rRotVectr_16[] = +{ + W16(0x652a), W16(0x62bc), W16(0x5c83), W16(0x52bc), W16(0x45c7), + W16(0x3623), W16(0x246b), W16(0x114d) +}; + +/*! + * \brief CLDFB iRotVectr + * + * cldfb bands: 16 + * global gain: 5.00 + * scale: sqrt(1.0/8.00) + */ +const Word16 iRotVectr_16[] = +{ + W16(0xfd84), W16(0xe9d4), W16(0xd6fe), W16(0xc5bb), W16(0xb6b6), + W16(0xaa82), W16(0xa196), W16(0x9c4c) +}; + +/*! + * \brief CLDFB rRotVectr + * + * cldfb bands: 20 + * global gain: 4.00 + * scale: sqrt(1.0/8.00) + */ +const Word16 rRotVectr_20[] = +{ + W16(0x5a7e), W16(0x591a), W16(0x5584), W16(0x4fd3), W16(0x482a), + W16(0x3ebb), W16(0x33c1), W16(0x2780), W16(0x1a46), W16(0x0c67) +}; + +/*! + * \brief CLDFB iRotVectr + * + * cldfb bands: 20 + * global gain: 4.00 + * scale: sqrt(1.0/8.00) + */ +const Word16 iRotVectr_20[] = +{ + W16(0xfe39), W16(0xf017), W16(0xe259), W16(0xd556), W16(0xc95f), + W16(0xbec1), W16(0xb5bf), W16(0xae90), W16(0xa963), W16(0xa658) +}; + +/*! + * \brief CLDFB rRotVectr + * + * cldfb bands: 32 + * global gain: 2.50 + * scale: sqrt(1.0/4.00) + */ +const Word16 rRotVectr_32[] = +{ + W16(0x652f), W16(0x6494), W16(0x6300), W16(0x6078), W16(0x5d02), + W16(0x58a7), W16(0x5371), W16(0x4d6e), W16(0x46ac), W16(0x3f3b), + W16(0x372f), W16(0x2e9a), W16(0x2593), W16(0x1c2f), W16(0x1286), + W16(0x08af) +}; + +/*! + * \brief CLDFB iRotVectr + * + * cldfb bands: 32 + * global gain: 2.50 + * scale: sqrt(1.0/4.00) + */ +const Word16 iRotVectr_32[] = +{ + W16(0xfec2), W16(0xf4d9), W16(0xeb0b), W16(0xe170), W16(0xd821), + W16(0xcf35), W16(0xc6c1), W16(0xbed9), W16(0xb793), W16(0xb0ff), + W16(0xab2d), W16(0xa62d), W16(0xa20b), W16(0x9ed0), W16(0x9c84), + W16(0x9b2e) +}; + +/*! + * \brief CLDFB rRotVectr + * + * cldfb bands: 40 + * global gain: 2.00 + * scale: sqrt(1.0/4.00) + */ +const Word16 rRotVectr_40[] = +{ + W16(0x5a81), W16(0x5a28), W16(0x5941), W16(0x57cc), W16(0x55cd), + W16(0x5347), W16(0x503d), W16(0x4cb4), W16(0x48b3), W16(0x443e), + W16(0x3f5e), W16(0x3a1a), W16(0x347b), W16(0x2e88), W16(0x284c), + W16(0x21d0), W16(0x1b1f), W16(0x1444), W16(0x0d48), W16(0x0637) +}; + +/*! + * \brief CLDFB iRotVectr + * + * cldfb bands: 40 + * global gain: 2.00 + * scale: sqrt(1.0/4.00) + */ +const Word16 iRotVectr_40[] = +{ + W16(0xff1d), W16(0xf803), W16(0xf0f7), W16(0xea02), W16(0xe330), + W16(0xdc8b), W16(0xd61f), W16(0xcff4), W16(0xca15), W16(0xc48c), + W16(0xbf60), W16(0xba9a), W16(0xb642), W16(0xb25e), W16(0xaef5), + W16(0xac0b), W16(0xa9a6), W16(0xa7ca), W16(0xa678), W16(0xa5b4) +}; + +/*! + * \brief CLDFB rRotVectr + * + * cldfb bands: 60 + * global gain: 1.33 + * scale: sqrt(1.0/2.00) + */ +const Word16 rRotVectr_60[] = +{ + W16(0x6882), W16(0x6855), W16(0x67de), W16(0x671e), W16(0x6615), + W16(0x64c5), W16(0x632f), W16(0x6153), W16(0x5f32), W16(0x5ccf), + W16(0x5a2a), W16(0x5747), W16(0x5426), W16(0x50ca), W16(0x4d35), + W16(0x496a), W16(0x456c), W16(0x413d), W16(0x3ce0), W16(0x3859), + W16(0x33aa), W16(0x2ed6), W16(0x29e2), W16(0x24d0), W16(0x1fa5), + W16(0x1a63), W16(0x150f), W16(0x0fac), W16(0x0a3e), W16(0x04c9) +}; + +/*! + * \brief CLDFB iRotVectr + * + * cldfb bands: 60 + * global gain: 1.33 + * scale: sqrt(1.0/2.00) + */ +const Word16 iRotVectr_60[] = +{ + W16(0xff51), W16(0xf9d9), W16(0xf465), W16(0xeefa), W16(0xe99a), + W16(0xe44a), W16(0xdf0e), W16(0xd9e9), W16(0xd4de), W16(0xcff2), + W16(0xcb27), W16(0xc682), W16(0xc204), W16(0xbdb3), W16(0xb990), + W16(0xb59e), W16(0xb1e0), W16(0xae5a), W16(0xab0c), W16(0xa7fb), + W16(0xa526), W16(0xa292), W16(0xa03f), W16(0x9e30), W16(0x9c65), + W16(0x9ae0), W16(0x99a2), W16(0x98ac), W16(0x97fe), W16(0x9799) +}; + +const Word16 cldfb_anaScale[] = +{ + SCALE_CLDFB_ANA_10, SCALE_CLDFB_ANA_16, SCALE_CLDFB_ANA_20, SCALE_CLDFB_ANA_32, SCALE_CLDFB_ANA_40, SCALE_CLDFB_ANA_60 +}; +const Word16 cldfb_synScale[] = +{ + SCALE_CLDFB_SYN_10, SCALE_CLDFB_SYN_16, SCALE_CLDFB_SYN_20, SCALE_CLDFB_SYN_32, SCALE_CLDFB_SYN_40, SCALE_CLDFB_SYN_60 +}; +const Word16 cldfb_synGain[] = +{ + 0x6666, /* 10 bands */ + 0x51EC, /* 16 bands */ + 0x6666, /* 20 bands */ + 0x51EC, /* 32 bands */ + 0x6666, /* 40 bands */ + 0x4CCD /* 60 bands */ +}; +const Word16 *cldfb_protoFilter_2_5ms[] = +{ + CLDFB80_10, CLDFB80_16, CLDFB80_20, CLDFB80_32, CLDFB80_40, CLDFB80_60 +}; +const Word16 cldfb_scale_2_5ms[7] = +{ + 22603/*88.293854 Q8*/, /* 10 bands */ + 22605/*88.299622 Q8*/, /* 16 bands */ + 22605/*88.300926 Q8*/, /* 20 bands */ + 22606/*88.303848 Q8*/, /* 32 bands */ + 22606/*88.304718 Q8*/, /* 40 bands */ + 22535/*88.028412 Q8*/ /* 60 bands */ +}; + + +/**********************************************************************/ /** +igf settings structure for each bitrate mode +**************************************************************************/ +const Word16 swb_offset_LB_new[15][IGF_MAX_SFB] = +{ + /* 0: for 9600 kbs WB */ + { + 4, 164, 186, 242, 320 + }, + /* 1: for 13200 kbs WB RF */ + { + 4, 164, 186, 242, 320 + }, + /* 2: for 9600 kbs SWB */ + { + 4, 200, 322, 444, 566 + }, + /* 3: for 13200 kbs SWB */ + { + 7, 256, 288, 328, 376, 432, 496, 566 + }, + /* 4: for 13200 kbs SWB RF */ + { + 4, 200, 322, 444, 566 + }, + /* 5: for 16400 kbs SWB */ + { + 8, 256, 288, 328, 376, 432, 496, 576, 640 + }, + /* 6: for 24400 kbs SWB */ + { + 9, 256, 284, 318, 358, 402, 450, 508, 576, 640 + }, + /* 7: for 32000 kbs SWB */ + { + 9, 256, 284, 318, 358, 402, 450, 508, 576, 640 + }, + /* 8: for 48000 kbs SWB */ + { + 4, 512, 534, 576, 640 + }, + /* 9: for 16400 kbs FB */ + { + 10, 256, 288, 328, 376, 432, 496, 576, 640, 720, 800 + }, + /* 10: for 24400 kbs FB */ + { + 11, 256, 284, 318, 358, 402, 450, 508, 576, 640, 720, 800 + }, + /* 11: for 32000 kbs FB */ + { + 11, 256, 284, 318, 358, 402, 450, 508, 576, 640, 720, 800 + }, + /* 12: for 48000 kbs FB */ + { + 5, 512, 584, 656, 728, 800 + }, + /* 13: for 96000 kbs FB */ + { + 3, 640, 720, 800 /* old: 640, 760, 880 */ + }, + /* 14: for 128000 kbs FB */ + { + 3, 640, 720, 800 /* old: 640, 760, 880 */ + } +}; + + + +const Word16 igf_whitening_TH[15][2][IGF_MAX_TILES] = +{ + /* 0: for 9600 kbs WB */ + { + /* medium */ { 2949/*0.36f Q13*/, 2949/*0.36f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/}, + /* strong */ { 11551/*1.41f Q13*/, 11551/*1.41f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/} + }, + /* 1: for 13200 kbs WB RF */ + { + /* medium */ { 2949/*0.36f Q13*/, 2949/*0.36f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/}, + /* strong */ { 11551/*1.41f Q13*/, 11551/*1.41f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/} + }, + /* 2: for 9600 kbs SWB */ + { + /* medium */ { 6881/*0.84f Q13*/, 7291/*0.89f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/}, + /* strong */ { 10650/*1.30f Q13*/, 10240/*1.25f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/} + }, + /* 3: for 13200 kbs SWB */ + { + /* medium */ { 6881/*0.84f Q13*/, 7291/*0.89f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/}, + /* strong */ { 10650/*1.30f Q13*/, 10240/*1.25f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/} + }, + /* 4: for 13200 kbs SWB RF */ + { + /* medium */ { 6881/*0.84f Q13*/, 7291/*0.89f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/}, + /* strong */ { 10650/*1.30f Q13*/, 10240/*1.25f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/} + }, + /* 5: for 16400 kbs SWB */ + { + /* medium */ { 6799/*0.83f Q13*/, 7291/*0.89f Q13*/, 7291/*0.89f Q13*/, 0/*0.f Q13*/}, + /* strong */ { 10732/*1.31f Q13*/, 9748/*1.19f Q13*/, 9748/*1.19f Q13*/, 0/*0.f Q13*/} + }, + /* 6: for 24400 kbs SWB*/ + { + /* medium */ { 6636/*0.81f Q13*/, 6963/*0.85f Q13*/, 6963/*0.85f Q13*/, 0/*0.f Q13*/}, + /* strong */ { 11059/*1.35f Q13*/, 10076/*1.23f Q13*/, 10076/*1.23f Q13*/, 0/*0.f Q13*/} + }, + /* 7: for 32000 kbs SWB */ + { + /* medium */ { 7455/*0.91f Q13*/, 6963/*0.85f Q13*/, 6963/*0.85f Q13*/, 0/*0.f Q13*/}, + /* strong */ { 10977/*1.34f Q13*/, 11059/*1.35f Q13*/, 11059/*1.35f Q13*/, 0/*0.f Q13*/} + }, + /* 8: for 48000 kbs SWB */ + { + /* medium */ { 9421/*1.15f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/}, + /* strong */ { 9748/*1.19f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/} + }, + /* 9: for 16400 kbs FB */ + { + /* medium */ { 5161/*0.63f Q13*/, 2212/*0.27f Q13*/, 2949/*0.36f Q13*/, 0/*0.f Q13*/}, + /* strong */ { 12534/*1.53f Q13*/, 10813/*1.32f Q13*/, 5489/*0.67f Q13*/, 0/*0.f Q13*/} + }, + /* 10: for 24400 kbs FB */ + { + /* medium */ { 6390/*0.78f Q13*/, 2540/*0.31f Q13*/, 2785/*0.34f Q13*/, 2785/*0.34f Q13*/}, + /* strong */ { 12206/*1.49f Q13*/, 11305/*1.38f Q13*/, 5325/*0.65f Q13*/, 5325/*0.65f Q13*/} + }, + /* 11: for 32000 kbs FB */ + { + /* medium */ { 6390/*0.78f Q13*/, 2540/*0.31f Q13*/, 2785/*0.34f Q13*/, 2785/*0.34f Q13*/}, + /* strong */ { 12206/*1.49f Q13*/, 11305/*1.38f Q13*/, 5325/*0.65f Q13*/, 5325/*0.65f Q13*/} + }, + /* 12: for 48000 kbs FB */ + { + /* medium */ { 6554/*0.80f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/}, + /* strong */ { 8192/*1.00f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/} + }, + /* 13: for 96000 kbs FB */ + { + /* medium */ { 0/*0.f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/}, + /* strong */ { 23101/*2.82f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/} + }, + /* 14: for 128000 kbs FB */ + { + /* medium */ { 0/*0.f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/}, + /* strong */ { 23101/*2.82f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/, 0/*0.f Q13*/} + } +}; + + +/* IGF SCF arithmetic coder cumulative frequency tables and offsets */ +const Word16 cf_off_se01_tab[9] = +{ + +1, /* 9.6 kbs B*/ + +1, /* 13.2 kbs WB RF B*/ + +1, /* 9.6 kbs SWB B*/ + +1, /* 13.2 kbs A*/ + +1, /* 13.2 kbs SWB RF B*/ + +1, /* 16.4 kbs B*/ + +1, /* 24.4 kbs B*/ + +1, /* 32.0 kbs A*/ + -1 /* 48.0 kbs B*/ +}; + +const Word16 cf_off_se02_tab[9][IGF_CTX_COUNT] = +{ + { +1, +2, +2, +2, +3, +3, +4}, /* 9.6 kbs B*/ + { +1, +2, +2, +2, +3, +3, +4}, /* 13.2 kbs WB RF B*/ + { +0, +2, +3, +3, +2, +2, +4}, /* 9.6 kbs SWB B*/ + { +0, +2, +3, +3, +2, +2, +4}, /* 13.2 kbs A*/ + { +0, +2, +3, +3, +2, +2, +4}, /* 13.2 kbs SWB RF B*/ + { +0, +2, +3, +3, +2, +2, +4}, /* 16.4 kbs B*/ + { -1, +2, +2, +2, +2, +3, +5}, /* 24.4 kbs B*/ + { -1, +2, +2, +2, +2, +3, +5}, /* 32.0 kbs A*/ + { +3, +2, +3, +2, +3, +3, +6} /* 48.0 kbs B*/ +}; + +const Word16 cf_off_se10_tab = -7; + +const Word16 cf_off_se11_tab[IGF_CTX_COUNT][IGF_CTX_COUNT] = +{ + { -5, +0, +0, +0, +0, +0, +0}, + { +0, +0, +0, +0, +0, +0, +0}, + { +0, +0, +0, +0, +0, +0, +0}, + { +0, +0, +0, +0, +0, +0, +0}, + { +0, +0, +0, +0, +0, +0, +0}, + { +0, +0, +0, +0, +0, +0, +1}, + { +0, +1, +0, +0, +3, +0, +3} +}; + +const Word16 cf_se00_tab[IGF_SYMBOLS_IN_TABLE + 1] = +{ + 16384, 16356, 16299, 16185, 15904, 15282, 14669, 13598, 11886, 9541, 6613, 3845, 1799, 606, 153, 32, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 +}; + +const Word16 cf_se01_tab[9][IGF_SYMBOLS_IN_TABLE + 1] = +{ + {16384, 16320, 16285, 16237, 16163, 16049, 15864, 15604, 15187, 14557, 13612, 12308, 10590, 8535, 6346, 4396, 2900, 1917, 1289, 870, 593, 408, 279, 181, 122, 78, 52, 0}, /* 9.6 kbs B*/ + {16384, 16320, 16285, 16237, 16163, 16049, 15864, 15604, 15187, 14557, 13612, 12308, 10590, 8535, 6346, 4396, 2900, 1917, 1289, 870, 593, 408, 279, 181, 122, 78, 52, 0}, /* 13.2 kbs WB RF B*/ + {16384, 16375, 16362, 16339, 16307, 16258, 16180, 16061, 15845, 15463, 14795, 13680, 11828, 9252, 6358, 3769, 2079, 1186, 687, 415, 242, 150, 100, 67, 44, 30, 19, 0}, /* 9.6 kbs SWB B*/ + {16384, 16375, 16362, 16339, 16307, 16258, 16180, 16061, 15845, 15463, 14795, 13680, 11828, 9252, 6358, 3769, 2079, 1186, 687, 415, 242, 150, 100, 67, 44, 30, 19, 0}, /* 13.2 kbs A*/ + {16384, 16375, 16362, 16339, 16307, 16258, 16180, 16061, 15845, 15463, 14795, 13680, 11828, 9252, 6358, 3769, 2079, 1186, 687, 415, 242, 150, 100, 67, 44, 30, 19, 0}, /* 13.2 kbs SWB RF B*/ + {16384, 16375, 16362, 16339, 16307, 16258, 16180, 16061, 15845, 15463, 14795, 13680, 11828, 9252, 6358, 3769, 2079, 1186, 687, 415, 242, 150, 100, 67, 44, 30, 19, 0}, /* 16.4 kbs B*/ + {16384, 16369, 16356, 16337, 16311, 16268, 16197, 16073, 15876, 15544, 14977, 13987, 12327, 9908, 7017, 4393, 2545, 1446, 840, 493, 292, 183, 111, 70, 45, 31, 20, 0}, /* 24.4 kbs B*/ + {16384, 16369, 16356, 16337, 16311, 16268, 16197, 16073, 15876, 15544, 14977, 13987, 12327, 9908, 7017, 4393, 2545, 1446, 840, 493, 292, 183, 111, 70, 45, 31, 20, 0}, /* 32.0 kbs A*/ + {16384, 16368, 16355, 16334, 16291, 16212, 16071, 15816, 15359, 14523, 13014, 10534, 7345, 4272, 2228, 1149, 626, 357, 215, 139, 93, 67, 53, 43, 36, 28, 22, 0} /* 48.0 kbs B*/ +}; + +const Word16 cf_se02_tab[4][IGF_CTX_COUNT][IGF_SYMBOLS_IN_TABLE + 1] = +{ + { /* 9.6 kbs B */ + { 16384, 16369, 16348, 16316, 16256, 16172, 16017, 15735, 15246, 14363, 13036, 11139, 8916, 6724, 4757, 3282, 2221, 1549, 1105, 771, 548, 364, 238, 151, 89, 50, 30, 0 }, +{ 16384, 16371, 16358, 16339, 16290, 16241, 16153, 16040, 15813, 15397, 14601, 13301, 11360, 8916, 6254, 3911, 2220, 1280, 755, 461, 278, 177, 111, 70, 35, 20, 12, 0 }, +{ 16384, 16375, 16359, 16333, 16286, 16243, 16154, 16024, 15771, 15380, 14712, 13537, 11742, 9425, 6872, 4378, 2327, 1197, 671, 412, 259, 145, 93, 52, 26, 13, 5, 0 }, +{ 16384, 16372, 16358, 16326, 16289, 16241, 16147, 16014, 15765, 15321, 14670, 13546, 11912, 9787, 7323, 4824, 2536, 1330, 731, 438, 258, 148, 86, 37, 22, 11, 2, 0 }, +{ 16384, 16376, 16364, 16344, 16315, 16272, 16219, 16119, 15910, 15620, 15100, 14254, 13063, 11489, 9413, 7100, 4738, 2751, 1584, 973, 597, 349, 201, 96, 47, 22, 9, 0 }, +{ 16384, 16364, 16340, 16312, 16288, 16237, 16166, 16026, 15756, 15390, 14833, 13870, 12627, 10998, 8985, 6893, 4720, 3048, 1860, 1131, 725, 449, 215, 111, 56, 34, 14, 0 }, +{ 16384, 16326, 16297, 16246, 16183, 16064, 15884, 15632, 15240, 14763, 14107, 13230, 12185, 10886, 9390, 7781, 6194, 4696, 3350, 2259, 1506, 975, 604, 356, 201, 106, 48, 0 } + }, + + { /* 9.6 kbs SWB B*/ + { 16384, 16359, 16349, 16331, 16300, 16236, 16112, 15894, 15480, 14691, 13257, 10996, 8168, 5357, 3193, 1864, 1098, 676, 426, 265, 173, 117, 81, 59, 45, 35, 26, 0 }, +{ 16384, 16374, 16370, 16367, 16362, 16348, 16325, 16283, 16204, 16058, 15715, 14980, 13521, 11144, 7972, 4702, 2366, 1063, 480, 241, 128, 71, 42, 22, 14, 9, 5, 0 }, +{ 16384, 16380, 16377, 16375, 16372, 16365, 16354, 16334, 16295, 16216, 16056, 15716, 15034, 13690, 11467, 8404, 5150, 2385, 908, 417, 199, 106, 62, 35, 21, 13, 7, 0 }, +{ 16384, 16378, 16376, 16373, 16368, 16360, 16346, 16318, 16267, 16173, 15991, 15644, 14932, 13623, 11575, 8688, 5224, 2309, 891, 393, 202, 103, 57, 34, 20, 11, 8, 0 }, +{ 16384, 16375, 16372, 16365, 16348, 16322, 16279, 16201, 16046, 15728, 15214, 14297, 12811, 10673, 7918, 4530, 2109, 978, 466, 234, 121, 72, 46, 31, 25, 17, 13, 0 }, +{ 16384, 16366, 16357, 16341, 16325, 16289, 16220, 16084, 15768, 15300, 14466, 13206, 11402, 9176, 6633, 4092, 2192, 1171, 592, 315, 179, 111, 74, 46, 31, 26, 18, 0 }, +{ 16384, 16301, 16266, 16211, 16140, 16045, 15889, 15652, 15358, 14883, 14192, 13119, 11753, 10181, 8445, 6708, 5023, 3449, 2226, 1375, 849, 516, 353, 231, 153, 107, 78, 0 } + }, + +{ /* 24.4 kbs B */ + { 16384, 16351, 16333, 16303, 16254, 16163, 15993, 15681, 15080, 13987, 12109, 9465, 6588, 4160, 2488, 1480, 912, 589, 389, 266, 190, 131, 93, 68, 47, 34, 24, 0 }, +{ 16384, 16379, 16375, 16369, 16360, 16345, 16328, 16286, 16211, 16078, 15810, 15233, 14058, 11933, 8881, 5609, 2940, 1290, 558, 274, 150, 80, 47, 29, 17, 11, 6, 0 }, +{ 16384, 16382, 16380, 16377, 16370, 16358, 16337, 16300, 16224, 16088, 15811, 15233, 14112, 12019, 9061, 5723, 2780, 1121, 480, 239, 123, 69, 41, 22, 13, 8, 5, 0 }, +{ 16384, 16377, 16375, 16369, 16363, 16351, 16325, 16268, 16172, 16009, 15686, 15039, 13830, 11799, 8924, 5422, 2444, 960, 441, 220, 111, 63, 37, 22, 11, 6, 3, 0 }, +{ 16384, 16374, 16369, 16363, 16356, 16335, 16290, 16214, 16068, 15826, 15382, 14550, 13126, 10956, 8000, 4622, 2090, 973, 478, 249, 128, 75, 42, 19, 13, 7, 4, 0 }, +{ 16384, 16375, 16370, 16367, 16362, 16340, 16298, 16232, 16097, 15860, 15440, 14718, 13570, 11874, 9557, 6790, 4053, 2166, 1150, 622, 323, 179, 96, 53, 33, 17, 12, 0 }, +{ 16384, 16335, 16304, 16276, 16228, 16166, 16094, 15983, 15775, 15501, 15040, 14417, 13552, 12326, 10847, 9117, 7308, 5373, 3666, 2297, 1336, 807, 495, 313, 216, 152, 114, 0 } +}, + +{ /* 48.0 kbs B */ + { 16384, 16334, 16310, 16285, 16254, 16204, 16128, 16031, 15903, 15697, 15380, 14820, 13857, 12267, 9878, 7099, 4509, 2576, 1478, 871, 531, 349, 230, 163, 111, 80, 62, 0}, + { 16384, 16337, 16327, 16307, 16278, 16239, 16178, 16092, 15947, 15719, 15286, 14428, 12833, 10246, 7123, 4088, 1896, 849, 481, 287, 190, 139, 94, 66, 52, 34, 24, 0 }, + { 16384, 16352, 16341, 16329, 16312, 16295, 16265, 16223, 16151, 16026, 15825, 15437, 14645, 13089, 10612, 7364, 4077, 1783, 779, 444, 281, 192, 138, 93, 65, 43, 30, 0 }, + { 16384, 16354, 16347, 16337, 16314, 16284, 16233, 16165, 16051, 15847, 15450, 14621, 13069, 10623, 7298, 3789, 1569, 727, 445, 302, 207, 143, 96, 59, 36, 18, 9, 0 }, + { 16384, 16352, 16342, 16330, 16314, 16295, 16266, 16215, 16127, 15984, 15709, 15190, 14242, 12540, 9979, 6448, 3160, 1392, 752, 481, 344, 251, 169, 115, 73, 28, 8, 0 }, + { 16384, 16340, 16320, 16302, 16272, 16257, 16220, 16135, 16011, 15784, 15370, 14688, 13423, 11457, 8721, 5529, 2736, 1375, 784, 525, 353, 263, 172, 113, 78, 26, 11, 0 }, + { 16384, 16238, 16170, 16113, 16077, 16030, 16000, 15948, 15873, 15752, 15535, 15157, 14595, 13788, 12569, 10767, 8611, 6186, 4101, 2459, 1478, 881, 607, 385, 243, 168, 116, 0 } +} +}; + +/* only needed for >= 48 kbs */ + +const Word16 cf_se10_tab[IGF_SYMBOLS_IN_TABLE + 1] = +{ + 16384, 15493, 15154, 14810, 14331, 13701, 13086, 12403, 11585, 10923, 10293, 9631, 8943, 8385, 7760, 7182, 6593, 6009, 5540, 5082, 4571, 4133, 3711, 3299, 2887, 2460, 2043, 0 +}; + +const Word16 cf_se11_tab[IGF_CTX_COUNT][IGF_CTX_COUNT][IGF_SYMBOLS_IN_TABLE + 1] = +{ + { + { 16384, 16313, 16312, 16241, 16206, 16099, 15957, 15386, 14601, 12852, 10282, 7534, 4964, 2966, 1824, 896, 504, 255, 113, 112, 41, 40, 39, 38, 37, 36, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16207, 16206, 16205, 16120, 15949, 14663, 12777, 9947, 6860, 3773, 1972, 772, 430, 259, 174, 89, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16115, 15941, 14891, 12965, 11477, 8587, 5347, 3421, 1407, 620, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16254, 16253, 16004, 15005, 13756, 12006, 9256, 5755, 3755, 1755, 756, 132, 131, 130, 129, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 15964, 15550, 14929, 12856, 9954, 6430, 2906, 1456, 1042, 628, 214, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16087, 15503, 14334, 14333, 11994, 10240, 8193, 5268, 2929, 1760, 1176, 299, 298, 297, 296, 295, 294, 293, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 14922, 13467, 10919, 9464, 7280, 6189, 3641, 2914, 2187, 1824, 1823, 1096, 369, 368, 367, 4, 3, 2, 1, 0} + }, + { + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16238, 16237, 15678, 15399, 14840, 13441, 11341, 8681, 6161, 3781, 2522, 702, 283, 144, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16375, 16374, 15693, 14671, 12625, 7507, 4778, 2390, 1368, 1028, 347, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16375, 16374, 15595, 13776, 9877, 6498, 3639, 3120, 1561, 1042, 523, 265, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 15709, 13704, 12702, 11032, 7355, 3010, 1340, 1007, 674, 341, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16375, 16374, 12816, 10683, 7125, 2854, 720, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16375, 12738, 12737, 10920, 9103, 5466, 1828, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 15359, 15358, 14337, 14336, 14335, 14334, 14333, 10240, 7170, 5124, 2054, 1032, 1031, 1030, 1029, 7, 6, 5, 4, 3, 2, 1, 0} + }, + { + { 16384, 16383, 16382, 16107, 16106, 16105, 16104, 16103, 15966, 15965, 15690, 15140, 14315, 12939, 10324, 8122, 4956, 2479, 1654, 966, 691, 416, 141, 140, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16375, 15320, 14265, 12945, 10568, 8984, 6343, 4230, 1853, 797, 270, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16112, 16111, 16110, 15037, 14501, 12622, 11012, 7790, 5374, 3226, 1347, 542, 275, 274, 273, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16375, 15597, 14819, 12090, 7021, 4292, 1953, 1175, 787, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 15935, 14165, 12838, 9297, 6641, 3985, 1772, 1331, 890, 449, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 14740, 13923, 9010, 6555, 4100, 2464, 828, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 13104, 13103, 8192, 4920, 1647, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} + }, + { + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16077, 16076, 16075, 15926, 15176, 14425, 10819, 7664, 5711, 2856, 1354, 754, 454, 154, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16044, 16043, 14373, 12369, 10030, 7023, 5019, 1677, 676, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16077, 16076, 16075, 15470, 14258, 12743, 11531, 6375, 3040, 3039, 917, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16375, 15309, 13531, 11396, 7480, 3564, 1786, 364, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 15833, 15289, 13652, 10377, 6556, 3827, 3283, 1646, 555, 554, 553, 552, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 14146, 13404, 13403, 13402, 10425, 7448, 3727, 2240, 2239, 752, 751, 750, 749, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 15562, 14745, 13928, 10653, 7378, 5742, 2467, 830, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} + }, + { + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16375, 16219, 15590, 14803, 13544, 11339, 9292, 6930, 4568, 2521, 1419, 790, 318, 161, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16014, 15652, 14925, 14198, 12743, 10196, 5464, 3645, 1826, 371, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16050, 15396, 15395, 12447, 10810, 8518, 4915, 2950, 1313, 659, 333, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16375, 14792, 14001, 11096, 8455, 6079, 3174, 2119, 535, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 15796, 15795, 15794, 15793, 11700, 8777, 6439, 4101, 1178, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 15473, 15472, 15471, 14563, 13655, 12746, 10017, 7288, 6379, 6378, 4559, 1830, 1829, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 15723, 15069, 13105, 9174, 7865, 3934, 3280, 1971, 1317, 663, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} + }, + { + { 16384, 16383, 16382, 16381, 16232, 16231, 16230, 16229, 16228, 16227, 16078, 15628, 15329, 13977, 12325, 10222, 5413, 4212, 1959, 908, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16109, 15842, 15841, 13694, 11815, 10205, 5640, 3493, 2151, 1347, 543, 542, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16168, 14699, 13650, 11761, 9452, 6093, 3784, 1685, 636, 427, 426, 425, 424, 423, 422, 421, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16122, 15611, 14332, 13053, 10238, 7423, 4608, 2561, 2050, 1027, 516, 515, 260, 259, 258, 257, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 16376, 16375, 15207, 13649, 10531, 6632, 3514, 1176, 398, 397, 396, 395, 394, 393, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16379, 16378, 16377, 15749, 15120, 12601, 10082, 8823, 6304, 3785, 3156, 1267, 638, 637, 636, 7, 6, 5, 4, 3, 2, 1, 0}, + { 16384, 16383, 15729, 15728, 15727, 15726, 15725, 15071, 14417, 12453, 10489, 8525, 5905, 1975, 1321, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0} + }, + { + { 16384, 16383, 16372, 16340, 16339, 16328, 16285, 16253, 16136, 15923, 15614, 14931, 13833, 12201, 10175, 7615, 5269, 3243, 2123, 1142, 673, 342, 182, 150, 86, 54, 11, 0}, + { 16384, 16383, 16366, 16349, 16332, 16331, 16314, 16245, 16244, 16141, 15813, 15451, 14105, 12672, 9910, 7113, 4472, 2590, 1071, 484, 294, 156, 53, 36, 19, 18, 1, 0}, + { 16384, 16383, 16382, 16369, 16355, 16341, 16271, 16117, 15921, 15627, 14772, 13089, 10929, 8334, 5487, 3299, 1644, 999, 424, 228, 88, 46, 18, 17, 16, 15, 14, 0}, + { 16384, 16367, 16366, 16365, 16364, 16363, 16259, 16173, 15809, 15028, 13951, 12214, 9278, 6203, 3719, 2052, 1079, 402, 194, 125, 56, 22, 21, 20, 3, 2, 1, 0}, + { 16384, 16383, 16360, 16359, 16358, 16357, 16356, 16333, 16332, 16143, 15954, 15434, 14227, 12262, 9540, 6652, 3882, 1988, 1207, 829, 427, 191, 73, 50, 49, 2, 1, 0}, + { 16384, 16383, 16382, 16381, 16380, 16296, 16254, 15748, 14862, 13427, 11189, 8487, 5278, 3252, 2028, 1099, 551, 340, 298, 214, 172, 88, 46, 45, 3, 2, 1, 0}, + { 16384, 16383, 16307, 16269, 16231, 16230, 16077, 15886, 15464, 14620, 13546, 11896, 9671, 7024, 4338, 2382, 1423, 809, 541, 311, 158, 43, 5, 4, 3, 2, 1, 0} + } +}; + + +/**********************************************************************/ /** +igf settings table for each bitrate mode +**************************************************************************/ +const IGF_MODE igfMode[15] = +{ + /* sampleRate, frameLength, bitRate, igfMinFq, transFac, maxHopsize */ + { 16000, 320, 9600, 774, 20480/*1.25f Q14*/, 4 }, /* 9.6kbs WB 0 */ + { 16000, 320, 13200, 774, 20480/*1.25f Q14*/, 4 }, /* 13.2kbs WB RF 1 */ + { 32000, 640, 9600, 800, 20480/*1.25f Q14*/, 2 }, /* 9.6kbs SWB 2 */ + { 32000, 640, 13200, 800, 20480/*1.25f Q14*/, 4 }, /* 13.2kbs SWB 3 */ + { 32000, 640, 13200, 800, 20480/*1.25f Q14*/, 2 }, /* 13.2kbs SWB RF 4 */ + { 32000, 640, 16400, 800, 20480/*1.25f Q14*/, 4 }, /* 16.4kbs SWB 5 */ + { 32000, 640, 24400, 800, 20480/*1.25f Q14*/, 4 }, /* 24.4kbs SWB 6 */ + { 32000, 640, 32000, 800, 20480/*1.25f Q14*/, 4 }, /* 32.0kbs SWB 7 */ + { 32000, 640, 48000, 1600, 20480/*1.25f Q14*/, 4 }, /* 48.0kbs SWB 8 */ + { 48000, 960, 16400, 800, 20480/*1.25f Q14*/, 4 }, /* 16.4kbs FB 9 */ + { 48000, 960, 24400, 800, 20480/*1.25f Q14*/, 2 }, /* 24.4kbs FB 10 */ + { 48000, 960, 32000, 800, 20480/*1.25f Q14*/, 2 }, /* 32.0kbs FB 11 */ + { 48000, 960, 48000, 1600, 20480/*1.25f Q14*/, 2 }, /* 48.0kbs FB 12 */ + { 48000, 960, 96000, 1600, 8192/*0.50f Q14*/, 1 }, /* 96.0kbs FB 13 */ + { 48000, 960, 128000, 1600, 8192/*0.50f Q14*/, 1 } /*128.0kbs FB 14 */ +}; + +const Word32 bwMode2fs[4] = { 8000, 16000, 32000, 48000 }; + +const PWord16 w1N8[15] = +{ + {{ 32729/*0.998795 Q15*/, -1608/*-0.049068 Q15*/}}, + {{ 32610/*0.995185 Q15*/, -3212/*-0.098017 Q15*/}}, + {{ 32413/*0.989177 Q15*/, -4808/*-0.146730 Q15*/}}, + {{ 32138/*0.980785 Q15*/, -6393/*-0.195090 Q15*/}}, + {{ 31786/*0.970031 Q15*/, -7962/*-0.242980 Q15*/}}, + {{ 31357/*0.956940 Q15*/, -9512/*-0.290285 Q15*/}}, + {{ 30853/*0.941544 Q15*/, -11039/*-0.336890 Q15*/}}, + {{ 30274/*0.923880 Q15*/, -12540/*-0.382683 Q15*/}}, + {{ 29622/*0.903989 Q15*/, -14010/*-0.427555 Q15*/}}, + {{ 28899/*0.881921 Q15*/, -15447/*-0.471397 Q15*/}}, + {{ 28106/*0.857729 Q15*/, -16846/*-0.514103 Q15*/}}, + {{ 27246/*0.831470 Q15*/, -18205/*-0.555570 Q15*/}}, + {{ 26320/*0.803208 Q15*/, -19520/*-0.595699 Q15*/}}, + {{ 25330/*0.773010 Q15*/, -20788/*-0.634393 Q15*/}}, + {{ 24279/*0.740951 Q15*/, -22006/*-0.671559 Q15*/}} +}; + +const PWord16 w2N8[15] = +{ + {{ 32610/*0.995185 Q15*/, -3212/*-0.098017 Q15*/}}, + {{ 32138/*0.980785 Q15*/, -6393/*-0.195090 Q15*/}}, + {{ 31357/*0.956940 Q15*/, -9512/*-0.290285 Q15*/}}, + {{ 30274/*0.923880 Q15*/, -12540/*-0.382683 Q15*/}}, + {{ 28899/*0.881921 Q15*/, -15447/*-0.471397 Q15*/}}, + {{ 27246/*0.831470 Q15*/, -18205/*-0.555570 Q15*/}}, + {{ 25330/*0.773010 Q15*/, -20788/*-0.634393 Q15*/}}, + {{ 23170/*0.707107 Q15*/, -23170/*-0.707107 Q15*/}}, + {{ 20788/*0.634393 Q15*/, -25330/*-0.773010 Q15*/}}, + {{ 18205/*0.555570 Q15*/, -27246/*-0.831470 Q15*/}}, + {{ 15447/*0.471397 Q15*/, -28899/*-0.881921 Q15*/}}, + {{ 12540/*0.382683 Q15*/, -30274/*-0.923880 Q15*/}}, + {{ 9512/*0.290285 Q15*/, -31357/*-0.956940 Q15*/}}, + {{ 6393/*0.195090 Q15*/, -32138/*-0.980785 Q15*/}}, + {{ 3212/*0.098017 Q15*/, -32610/*-0.995185 Q15*/}} +}; + +const PWord16 w3N8[15] = +{ + {{ 32413/*0.989177 Q15*/, -4808/*-0.146730 Q15*/}}, + {{ 31357/*0.956940 Q15*/, -9512/*-0.290285 Q15*/}}, + {{ 29622/*0.903989 Q15*/, -14010/*-0.427555 Q15*/}}, + {{ 27246/*0.831470 Q15*/, -18205/*-0.555570 Q15*/}}, + {{ 24279/*0.740951 Q15*/, -22006/*-0.671559 Q15*/}}, + {{ 20788/*0.634393 Q15*/, -25330/*-0.773010 Q15*/}}, + {{ 16846/*0.514103 Q15*/, -28106/*-0.857729 Q15*/}}, + {{ 12540/*0.382683 Q15*/, -30274/*-0.923880 Q15*/}}, + {{ 7962/*0.242980 Q15*/, -31786/*-0.970031 Q15*/}}, + {{ 3212/*0.098017 Q15*/, -32610/*-0.995185 Q15*/}}, + {{ -1608/*-0.049068 Q15*/, -32729/*-0.998795 Q15*/}}, + {{ -6393/*-0.195090 Q15*/, -32138/*-0.980785 Q15*/}}, + {{-11039/*-0.336890 Q15*/, -30853/*-0.941544 Q15*/}}, + {{-15447/*-0.471397 Q15*/, -28899/*-0.881921 Q15*/}}, + {{-19520/*-0.595699 Q15*/, -26320/*-0.803208 Q15*/}} +}; + +const PWord16 w4N8[15] = +{ + {{ 32138/*0.980785 Q15*/, -6393/*-0.195090 Q15*/}}, + {{ 30274/*0.923880 Q15*/, -12540/*-0.382683 Q15*/}}, + {{ 27246/*0.831470 Q15*/, -18205/*-0.555570 Q15*/}}, + {{ 23170/*0.707107 Q15*/, -23170/*-0.707107 Q15*/}}, + {{ 18205/*0.555570 Q15*/, -27246/*-0.831470 Q15*/}}, + {{ 12540/*0.382683 Q15*/, -30274/*-0.923880 Q15*/}}, + {{ 6393/*0.195090 Q15*/, -32138/*-0.980785 Q15*/}}, + {{ 0/*0.000000 Q15*/, -32768/*-1.000000 Q15*/}}, + {{ -6393/*-0.195090 Q15*/, -32138/*-0.980785 Q15*/}}, + {{-12540/*-0.382683 Q15*/, -30274/*-0.923880 Q15*/}}, + {{-18205/*-0.555570 Q15*/, -27246/*-0.831470 Q15*/}}, + {{-23170/*-0.707107 Q15*/, -23170/*-0.707107 Q15*/}}, + {{-27246/*-0.831470 Q15*/, -18205/*-0.555570 Q15*/}}, + {{-30274/*-0.923880 Q15*/, -12540/*-0.382683 Q15*/}}, + {{-32138/*-0.980785 Q15*/, -6393/*-0.195090 Q15*/}} +}; + +const PWord16 w5N8[15] = +{ + {{ 31786/*0.970031 Q15*/, -7962/*-0.242980 Q15*/}}, + {{ 28899/*0.881921 Q15*/, -15447/*-0.471397 Q15*/}}, + {{ 24279/*0.740951 Q15*/, -22006/*-0.671559 Q15*/}}, + {{ 18205/*0.555570 Q15*/, -27246/*-0.831470 Q15*/}}, + {{ 11039/*0.336890 Q15*/, -30853/*-0.941544 Q15*/}}, + {{ 3212/*0.098017 Q15*/, -32610/*-0.995185 Q15*/}}, + {{ -4808/*-0.146730 Q15*/, -32413/*-0.989177 Q15*/}}, + {{-12540/*-0.382683 Q15*/, -30274/*-0.923880 Q15*/}}, + {{-19520/*-0.595699 Q15*/, -26320/*-0.803208 Q15*/}}, + {{-25330/*-0.773010 Q15*/, -20788/*-0.634393 Q15*/}}, + {{-29622/*-0.903989 Q15*/, -14010/*-0.427555 Q15*/}}, + {{-32138/*-0.980785 Q15*/, -6393/*-0.195090 Q15*/}}, + {{-32729/*-0.998795 Q15*/, 1608/*0.049068 Q15*/}}, + {{-31357/*-0.956940 Q15*/, 9512/*0.290285 Q15*/}}, + {{-28106/*-0.857729 Q15*/, 16846/*0.514103 Q15*/}} +}; + +const PWord16 w6N8[15] = +{ + {{ 31357/*0.956940 Q15*/, -9512/*-0.290285 Q15*/}}, + {{ 27246/*0.831470 Q15*/, -18205/*-0.555570 Q15*/}}, + {{ 20788/*0.634393 Q15*/, -25330/*-0.773010 Q15*/}}, + {{ 12540/*0.382683 Q15*/, -30274/*-0.923880 Q15*/}}, + {{ 3212/*0.098017 Q15*/, -32610/*-0.995185 Q15*/}}, + {{ -6393/*-0.195090 Q15*/, -32138/*-0.980785 Q15*/}}, + {{-15447/*-0.471397 Q15*/, -28899/*-0.881921 Q15*/}}, + {{-23170/*-0.707107 Q15*/, -23170/*-0.707107 Q15*/}}, + {{-28899/*-0.881921 Q15*/, -15447/*-0.471397 Q15*/}}, + {{-32138/*-0.980785 Q15*/, -6393/*-0.195090 Q15*/}}, + {{-32610/*-0.995185 Q15*/, 3212/*0.098017 Q15*/}}, + {{-30274/*-0.923880 Q15*/, 12540/*0.382683 Q15*/}}, + {{-25330/*-0.773010 Q15*/, 20788/*0.634393 Q15*/}}, + {{-18205/*-0.555570 Q15*/, 27246/*0.831470 Q15*/}}, + {{ -9512/*-0.290285 Q15*/, 31357/*0.956940 Q15*/}} +}; + +const PWord16 w7N8[15] = +{ + {{ 30853/*0.941544 Q15*/, -11039/*-0.336890 Q15*/}}, + {{ 25330/*0.773010 Q15*/, -20788/*-0.634393 Q15*/}}, + {{ 16846/*0.514103 Q15*/, -28106/*-0.857729 Q15*/}}, + {{ 6393/*0.195090 Q15*/, -32138/*-0.980785 Q15*/}}, + {{ -4808/*-0.146730 Q15*/, -32413/*-0.989177 Q15*/}}, + {{-15447/*-0.471397 Q15*/, -28899/*-0.881921 Q15*/}}, + {{-24279/*-0.740951 Q15*/, -22006/*-0.671559 Q15*/}}, + {{-30274/*-0.923880 Q15*/, -12540/*-0.382683 Q15*/}}, + {{-32729/*-0.998795 Q15*/, -1608/*-0.049068 Q15*/}}, + {{-31357/*-0.956940 Q15*/, 9512/*0.290285 Q15*/}}, + {{-26320/*-0.803208 Q15*/, 19520/*0.595699 Q15*/}}, + {{-18205/*-0.555570 Q15*/, 27246/*0.831470 Q15*/}}, + {{ -7962/*-0.242980 Q15*/, 31786/*0.970031 Q15*/}}, + {{ 3212/*0.098017 Q15*/, 32610/*0.995185 Q15*/}}, + {{ 14010/*0.427555 Q15*/, 29622/*0.903989 Q15*/}} +}; + +const PWord16 *w_a[7] = {w1N8, w2N8, w3N8, w4N8, w5N8, w6N8, w7N8}; + +const PWord16 w19N[127] = +{ + {{ 31881/*0.972940 Q15*/, 7571/*0.231058 Q15*/}}, + {{ 29269/*0.893224 Q15*/, 14733/*0.449611 Q15*/}}, + {{ 25073/*0.765167 Q15*/, 21097/*0.643832 Q15*/}}, + {{ 19520/*0.595699 Q15*/, 26320/*0.803208 Q15*/}}, + {{ 12910/*0.393992 Q15*/, 30118/*0.919114 Q15*/}}, + {{ 5602/*0.170962 Q15*/, 32286/*0.985278 Q15*/}}, + {{ -2009/*-0.061321 Q15*/, 32706/*0.998118 Q15*/}}, + {{ -9512/*-0.290285 Q15*/, 31357/*0.956940 Q15*/}}, + {{-16500/*-0.503538 Q15*/, 28311/*0.863973 Q15*/}}, + {{-22595/*-0.689541 Q15*/, 23732/*0.724247 Q15*/}}, + {{-27467/*-0.838225 Q15*/, 17869/*0.545325 Q15*/}}, + {{-30853/*-0.941544 Q15*/, 11039/*0.336890 Q15*/}}, + {{-32568/*-0.993907 Q15*/, 3612/*0.110222 Q15*/}}, + {{-32522/*-0.992480 Q15*/, -4011/*-0.122411 Q15*/}}, + {{-30715/*-0.937339 Q15*/, -11417/*-0.348419 Q15*/}}, + {{-27246/*-0.831470 Q15*/, -18205/*-0.555570 Q15*/}}, + {{-22302/*-0.680601 Q15*/, -24008/*-0.732654 Q15*/}}, + {{-16151/*-0.492898 Q15*/, -28511/*-0.870087 Q15*/}}, + {{ -9127/*-0.278520 Q15*/, -31471/*-0.960431 Q15*/}}, + {{ -1608/*-0.049068 Q15*/, -32729/*-0.998795 Q15*/}}, + {{ 5998/*0.183040 Q15*/, -32214/*-0.983105 Q15*/}}, + {{ 13279/*0.405241 Q15*/, -29957/*-0.914210 Q15*/}}, + {{ 19841/*0.605511 Q15*/, -26078/*-0.795837 Q15*/}}, + {{ 25330/*0.773010 Q15*/, -20788/*-0.634393 Q15*/}}, + {{ 29448/*0.898674 Q15*/, -14373/*-0.438616 Q15*/}}, + {{ 31972/*0.975702 Q15*/, -7180/*-0.219101 Q15*/}}, + {{ 32766/*0.999925 Q15*/, 402/*0.012272 Q15*/}}, + {{ 31786/*0.970031 Q15*/, 7962/*0.242980 Q15*/}}, + {{ 29086/*0.887640 Q15*/, 15091/*0.460539 Q15*/}}, + {{ 24812/*0.757209 Q15*/, 21403/*0.653173 Q15*/}}, + {{ 19195/*0.585798 Q15*/, 26557/*0.810457 Q15*/}}, + {{ 12540/*0.382683 Q15*/, 30274/*0.923880 Q15*/}}, + {{ 5205/*0.158858 Q15*/, 32352/*0.987301 Q15*/}}, + {{ -2411/*-0.073565 Q15*/, 32679/*0.997290 Q15*/}}, + {{ -9896/*-0.302006 Q15*/, 31238/*0.953306 Q15*/}}, + {{-16846/*-0.514103 Q15*/, 28106/*0.857729 Q15*/}}, + {{-22884/*-0.698376 Q15*/, 23453/*0.715731 Q15*/}}, + {{-27684/*-0.844854 Q15*/, 17531/*0.534998 Q15*/}}, + {{-30986/*-0.945607 Q15*/, 10660/*0.325310 Q15*/}}, + {{-32610/*-0.995185 Q15*/, 3212/*0.098017 Q15*/}}, + {{-32470/*-0.990903 Q15*/, -4410/*-0.134581 Q15*/}}, + {{-30572/*-0.932993 Q15*/, -11793/*-0.359895 Q15*/}}, + {{-27020/*-0.824589 Q15*/, -18538/*-0.565732 Q15*/}}, + {{-22006/*-0.671559 Q15*/, -24279/*-0.740951 Q15*/}}, + {{-15800/*-0.482184 Q15*/, -28707/*-0.876070 Q15*/}}, + {{ -8740/*-0.266713 Q15*/, -31581/*-0.963776 Q15*/}}, + {{ -1206/*-0.036807 Q15*/, -32746/*-0.999322 Q15*/}}, + {{ 6393/*0.195090 Q15*/, -32138/*-0.980785 Q15*/}}, + {{ 13646/*0.416430 Q15*/, -29792/*-0.909168 Q15*/}}, + {{ 20160/*0.615232 Q15*/, -25833/*-0.788346 Q15*/}}, + {{ 25583/*0.780737 Q15*/, -20475/*-0.624859 Q15*/}}, + {{ 29622/*0.903989 Q15*/, -14010/*-0.427555 Q15*/}}, + {{ 32057/*0.978317 Q15*/, -6787/*-0.207111 Q15*/}}, + {{ 32758/*0.999699 Q15*/, 804/*0.024541 Q15*/}}, + {{ 31686/*0.966976 Q15*/, 8351/*0.254866 Q15*/}}, + {{ 28899/*0.881921 Q15*/, 15447/*0.471397 Q15*/}}, + {{ 24548/*0.749136 Q15*/, 21706/*0.662416 Q15*/}}, + {{ 18868/*0.575808 Q15*/, 26791/*0.817585 Q15*/}}, + {{ 12167/*0.371317 Q15*/, 30425/*0.928506 Q15*/}}, + {{ 4808/*0.146730 Q15*/, 32413/*0.989177 Q15*/}}, + {{ -2811/*-0.085797 Q15*/, 32647/*0.996313 Q15*/}}, + {{-10279/*-0.313682 Q15*/, 31114/*0.949528 Q15*/}}, + {{-17190/*-0.524590 Q15*/, 27897/*0.851355 Q15*/}}, + {{-23170/*-0.707107 Q15*/, 23170/*0.707107 Q15*/}}, + {{-27897/*-0.851355 Q15*/, 17190/*0.524590 Q15*/}}, + {{-31114/*-0.949528 Q15*/, 10279/*0.313682 Q15*/}}, + {{-32647/*-0.996313 Q15*/, 2811/*0.085797 Q15*/}}, + {{-32413/*-0.989177 Q15*/, -4808/*-0.146730 Q15*/}}, + {{-30425/*-0.928506 Q15*/, -12167/*-0.371317 Q15*/}}, + {{-26791/*-0.817585 Q15*/, -18868/*-0.575808 Q15*/}}, + {{-21706/*-0.662416 Q15*/, -24548/*-0.749136 Q15*/}}, + {{-15447/*-0.471397 Q15*/, -28899/*-0.881921 Q15*/}}, + {{ -8351/*-0.254866 Q15*/, -31686/*-0.966976 Q15*/}}, + {{ -804/*-0.024541 Q15*/, -32758/*-0.999699 Q15*/}}, + {{ 6787/*0.207111 Q15*/, -32057/*-0.978317 Q15*/}}, + {{ 14010/*0.427555 Q15*/, -29622/*-0.903989 Q15*/}}, + {{ 20475/*0.624859 Q15*/, -25583/*-0.780737 Q15*/}}, + {{ 25833/*0.788346 Q15*/, -20160/*-0.615232 Q15*/}}, + {{ 29792/*0.909168 Q15*/, -13646/*-0.416430 Q15*/}}, + {{ 32138/*0.980785 Q15*/, -6393/*-0.195090 Q15*/}}, + {{ 32746/*0.999322 Q15*/, 1206/*0.036807 Q15*/}}, + {{ 31581/*0.963776 Q15*/, 8740/*0.266713 Q15*/}}, + {{ 28707/*0.876070 Q15*/, 15800/*0.482184 Q15*/}}, + {{ 24279/*0.740951 Q15*/, 22006/*0.671559 Q15*/}}, + {{ 18538/*0.565732 Q15*/, 27020/*0.824589 Q15*/}}, + {{ 11793/*0.359895 Q15*/, 30572/*0.932993 Q15*/}}, + {{ 4410/*0.134581 Q15*/, 32470/*0.990903 Q15*/}}, + {{ -3212/*-0.098017 Q15*/, 32610/*0.995185 Q15*/}}, + {{-10660/*-0.325310 Q15*/, 30986/*0.945607 Q15*/}}, + {{-17531/*-0.534998 Q15*/, 27684/*0.844854 Q15*/}}, + {{-23453/*-0.715731 Q15*/, 22884/*0.698376 Q15*/}}, + {{-28106/*-0.857729 Q15*/, 16846/*0.514103 Q15*/}}, + {{-31238/*-0.953306 Q15*/, 9896/*0.302006 Q15*/}}, + {{-32679/*-0.997290 Q15*/, 2411/*0.073565 Q15*/}}, + {{-32352/*-0.987301 Q15*/, -5205/*-0.158858 Q15*/}}, + {{-30274/*-0.923880 Q15*/, -12540/*-0.382683 Q15*/}}, + {{-26557/*-0.810457 Q15*/, -19195/*-0.585798 Q15*/}}, + {{-21403/*-0.653173 Q15*/, -24812/*-0.757209 Q15*/}}, + {{-15091/*-0.460539 Q15*/, -29086/*-0.887640 Q15*/}}, + {{ -7962/*-0.242980 Q15*/, -31786/*-0.970031 Q15*/}}, + {{ -402/*-0.012272 Q15*/, -32766/*-0.999925 Q15*/}}, + {{ 7180/*0.219101 Q15*/, -31972/*-0.975702 Q15*/}}, + {{ 14373/*0.438616 Q15*/, -29448/*-0.898674 Q15*/}}, + {{ 20788/*0.634393 Q15*/, -25330/*-0.773010 Q15*/}}, + {{ 26078/*0.795837 Q15*/, -19841/*-0.605511 Q15*/}}, + {{ 29957/*0.914210 Q15*/, -13279/*-0.405241 Q15*/}}, + {{ 32214/*0.983105 Q15*/, -5998/*-0.183040 Q15*/}}, + {{ 32729/*0.998795 Q15*/, 1608/*0.049068 Q15*/}}, + {{ 31471/*0.960431 Q15*/, 9127/*0.278520 Q15*/}}, + {{ 28511/*0.870087 Q15*/, 16151/*0.492898 Q15*/}}, + {{ 24008/*0.732654 Q15*/, 22302/*0.680601 Q15*/}}, + {{ 18205/*0.555570 Q15*/, 27246/*0.831470 Q15*/}}, + {{ 11417/*0.348419 Q15*/, 30715/*0.937339 Q15*/}}, + {{ 4011/*0.122411 Q15*/, 32522/*0.992480 Q15*/}}, + {{ -3612/*-0.110222 Q15*/, 32568/*0.993907 Q15*/}}, + {{-11039/*-0.336890 Q15*/, 30853/*0.941544 Q15*/}}, + {{-17869/*-0.545325 Q15*/, 27467/*0.838225 Q15*/}}, + {{-23732/*-0.724247 Q15*/, 22595/*0.689541 Q15*/}}, + {{-28311/*-0.863973 Q15*/, 16500/*0.503538 Q15*/}}, + {{-31357/*-0.956940 Q15*/, 9512/*0.290285 Q15*/}}, + {{-32706/*-0.998118 Q15*/, 2009/*0.061321 Q15*/}}, + {{-32286/*-0.985278 Q15*/, -5602/*-0.170962 Q15*/}}, + {{-30118/*-0.919114 Q15*/, -12910/*-0.393992 Q15*/}}, + {{-26320/*-0.803208 Q15*/, -19520/*-0.595699 Q15*/}}, + {{-21097/*-0.643832 Q15*/, -25073/*-0.765167 Q15*/}}, + {{-14733/*-0.449611 Q15*/, -29269/*-0.893224 Q15*/}}, + {{ -7571/*-0.231058 Q15*/, -31881/*-0.972940 Q15*/}} +}; + +const PWord16 w18N[127] = +{ + {{ 31972/*0.975702 Q15*/, 7180/*0.219101 Q15*/}}, + {{ 29622/*0.903989 Q15*/, 14010/*0.427555 Q15*/}}, + {{ 25833/*0.788346 Q15*/, 20160/*0.615232 Q15*/}}, + {{ 20788/*0.634393 Q15*/, 25330/*0.773010 Q15*/}}, + {{ 14733/*0.449611 Q15*/, 29269/*0.893224 Q15*/}}, + {{ 7962/*0.242980 Q15*/, 31786/*0.970031 Q15*/}}, + {{ 804/*0.024541 Q15*/, 32758/*0.999699 Q15*/}}, + {{ -6393/*-0.195090 Q15*/, 32138/*0.980785 Q15*/}}, + {{-13279/*-0.405241 Q15*/, 29957/*0.914210 Q15*/}}, + {{-19520/*-0.595699 Q15*/, 26320/*0.803208 Q15*/}}, + {{-24812/*-0.757209 Q15*/, 21403/*0.653173 Q15*/}}, + {{-28899/*-0.881921 Q15*/, 15447/*0.471397 Q15*/}}, + {{-31581/*-0.963776 Q15*/, 8740/*0.266713 Q15*/}}, + {{-32729/*-0.998795 Q15*/, 1608/*0.049068 Q15*/}}, + {{-32286/*-0.985278 Q15*/, -5602/*-0.170962 Q15*/}}, + {{-30274/*-0.923880 Q15*/, -12540/*-0.382683 Q15*/}}, + {{-26791/*-0.817585 Q15*/, -18868/*-0.575808 Q15*/}}, + {{-22006/*-0.671559 Q15*/, -24279/*-0.740951 Q15*/}}, + {{-16151/*-0.492898 Q15*/, -28511/*-0.870087 Q15*/}}, + {{ -9512/*-0.290285 Q15*/, -31357/*-0.956940 Q15*/}}, + {{ -2411/*-0.073565 Q15*/, -32679/*-0.997290 Q15*/}}, + {{ 4808/*0.146730 Q15*/, -32413/*-0.989177 Q15*/}}, + {{ 11793/*0.359895 Q15*/, -30572/*-0.932993 Q15*/}}, + {{ 18205/*0.555570 Q15*/, -27246/*-0.831470 Q15*/}}, + {{ 23732/*0.724247 Q15*/, -22595/*-0.689541 Q15*/}}, + {{ 28106/*0.857729 Q15*/, -16846/*-0.514103 Q15*/}}, + {{ 31114/*0.949528 Q15*/, -10279/*-0.313682 Q15*/}}, + {{ 32610/*0.995185 Q15*/, -3212/*-0.098017 Q15*/}}, + {{ 32522/*0.992480 Q15*/, 4011/*0.122411 Q15*/}}, + {{ 30853/*0.941544 Q15*/, 11039/*0.336890 Q15*/}}, + {{ 27684/*0.844854 Q15*/, 17531/*0.534998 Q15*/}}, + {{ 23170/*0.707107 Q15*/, 23170/*0.707107 Q15*/}}, + {{ 17531/*0.534998 Q15*/, 27684/*0.844854 Q15*/}}, + {{ 11039/*0.336890 Q15*/, 30853/*0.941544 Q15*/}}, + {{ 4011/*0.122411 Q15*/, 32522/*0.992480 Q15*/}}, + {{ -3212/*-0.098017 Q15*/, 32610/*0.995185 Q15*/}}, + {{-10279/*-0.313682 Q15*/, 31114/*0.949528 Q15*/}}, + {{-16846/*-0.514103 Q15*/, 28106/*0.857729 Q15*/}}, + {{-22595/*-0.689541 Q15*/, 23732/*0.724247 Q15*/}}, + {{-27246/*-0.831470 Q15*/, 18205/*0.555570 Q15*/}}, + {{-30572/*-0.932993 Q15*/, 11793/*0.359895 Q15*/}}, + {{-32413/*-0.989177 Q15*/, 4808/*0.146730 Q15*/}}, + {{-32679/*-0.997290 Q15*/, -2411/*-0.073565 Q15*/}}, + {{-31357/*-0.956940 Q15*/, -9512/*-0.290285 Q15*/}}, + {{-28511/*-0.870087 Q15*/, -16151/*-0.492898 Q15*/}}, + {{-24279/*-0.740951 Q15*/, -22006/*-0.671559 Q15*/}}, + {{-18868/*-0.575808 Q15*/, -26791/*-0.817585 Q15*/}}, + {{-12540/*-0.382683 Q15*/, -30274/*-0.923880 Q15*/}}, + {{ -5602/*-0.170962 Q15*/, -32286/*-0.985278 Q15*/}}, + {{ 1608/*0.049068 Q15*/, -32729/*-0.998795 Q15*/}}, + {{ 8740/*0.266713 Q15*/, -31581/*-0.963776 Q15*/}}, + {{ 15447/*0.471397 Q15*/, -28899/*-0.881921 Q15*/}}, + {{ 21403/*0.653173 Q15*/, -24812/*-0.757209 Q15*/}}, + {{ 26320/*0.803208 Q15*/, -19520/*-0.595699 Q15*/}}, + {{ 29957/*0.914210 Q15*/, -13279/*-0.405241 Q15*/}}, + {{ 32138/*0.980785 Q15*/, -6393/*-0.195090 Q15*/}}, + {{ 32758/*0.999699 Q15*/, 804/*0.024541 Q15*/}}, + {{ 31786/*0.970031 Q15*/, 7962/*0.242980 Q15*/}}, + {{ 29269/*0.893224 Q15*/, 14733/*0.449611 Q15*/}}, + {{ 25330/*0.773010 Q15*/, 20788/*0.634393 Q15*/}}, + {{ 20160/*0.615232 Q15*/, 25833/*0.788346 Q15*/}}, + {{ 14010/*0.427555 Q15*/, 29622/*0.903989 Q15*/}}, + {{ 7180/*0.219101 Q15*/, 31972/*0.975702 Q15*/}}, + {{ 0/*0.000000 Q15*/, 32767/*1.000000 Q15*/}}, + {{ -7180/*-0.219101 Q15*/, 31972/*0.975702 Q15*/}}, + {{-14010/*-0.427555 Q15*/, 29622/*0.903989 Q15*/}}, + {{-20160/*-0.615232 Q15*/, 25833/*0.788346 Q15*/}}, + {{-25330/*-0.773010 Q15*/, 20788/*0.634393 Q15*/}}, + {{-29269/*-0.893224 Q15*/, 14733/*0.449611 Q15*/}}, + {{-31786/*-0.970031 Q15*/, 7962/*0.242980 Q15*/}}, + {{-32758/*-0.999699 Q15*/, 804/*0.024541 Q15*/}}, + {{-32138/*-0.980785 Q15*/, -6393/*-0.195090 Q15*/}}, + {{-29957/*-0.914210 Q15*/, -13279/*-0.405241 Q15*/}}, + {{-26320/*-0.803208 Q15*/, -19520/*-0.595699 Q15*/}}, + {{-21403/*-0.653173 Q15*/, -24812/*-0.757209 Q15*/}}, + {{-15447/*-0.471397 Q15*/, -28899/*-0.881921 Q15*/}}, + {{ -8740/*-0.266713 Q15*/, -31581/*-0.963776 Q15*/}}, + {{ -1608/*-0.049068 Q15*/, -32729/*-0.998795 Q15*/}}, + {{ 5602/*0.170962 Q15*/, -32286/*-0.985278 Q15*/}}, + {{ 12540/*0.382683 Q15*/, -30274/*-0.923880 Q15*/}}, + {{ 18868/*0.575808 Q15*/, -26791/*-0.817585 Q15*/}}, + {{ 24279/*0.740951 Q15*/, -22006/*-0.671559 Q15*/}}, + {{ 28511/*0.870087 Q15*/, -16151/*-0.492898 Q15*/}}, + {{ 31357/*0.956940 Q15*/, -9512/*-0.290285 Q15*/}}, + {{ 32679/*0.997290 Q15*/, -2411/*-0.073565 Q15*/}}, + {{ 32413/*0.989177 Q15*/, 4808/*0.146730 Q15*/}}, + {{ 30572/*0.932993 Q15*/, 11793/*0.359895 Q15*/}}, + {{ 27246/*0.831470 Q15*/, 18205/*0.555570 Q15*/}}, + {{ 22595/*0.689541 Q15*/, 23732/*0.724247 Q15*/}}, + {{ 16846/*0.514103 Q15*/, 28106/*0.857729 Q15*/}}, + {{ 10279/*0.313682 Q15*/, 31114/*0.949528 Q15*/}}, + {{ 3212/*0.098017 Q15*/, 32610/*0.995185 Q15*/}}, + {{ -4011/*-0.122411 Q15*/, 32522/*0.992480 Q15*/}}, + {{-11039/*-0.336890 Q15*/, 30853/*0.941544 Q15*/}}, + {{-17531/*-0.534998 Q15*/, 27684/*0.844854 Q15*/}}, + {{-23170/*-0.707107 Q15*/, 23170/*0.707107 Q15*/}}, + {{-27684/*-0.844854 Q15*/, 17531/*0.534998 Q15*/}}, + {{-30853/*-0.941544 Q15*/, 11039/*0.336890 Q15*/}}, + {{-32522/*-0.992480 Q15*/, 4011/*0.122411 Q15*/}}, + {{-32610/*-0.995185 Q15*/, -3212/*-0.098017 Q15*/}}, + {{-31114/*-0.949528 Q15*/, -10279/*-0.313682 Q15*/}}, + {{-28106/*-0.857729 Q15*/, -16846/*-0.514103 Q15*/}}, + {{-23732/*-0.724247 Q15*/, -22595/*-0.689541 Q15*/}}, + {{-18205/*-0.555570 Q15*/, -27246/*-0.831470 Q15*/}}, + {{-11793/*-0.359895 Q15*/, -30572/*-0.932993 Q15*/}}, + {{ -4808/*-0.146730 Q15*/, -32413/*-0.989177 Q15*/}}, + {{ 2411/*0.073565 Q15*/, -32679/*-0.997290 Q15*/}}, + {{ 9512/*0.290285 Q15*/, -31357/*-0.956940 Q15*/}}, + {{ 16151/*0.492898 Q15*/, -28511/*-0.870087 Q15*/}}, + {{ 22006/*0.671559 Q15*/, -24279/*-0.740951 Q15*/}}, + {{ 26791/*0.817585 Q15*/, -18868/*-0.575808 Q15*/}}, + {{ 30274/*0.923880 Q15*/, -12540/*-0.382683 Q15*/}}, + {{ 32286/*0.985278 Q15*/, -5602/*-0.170962 Q15*/}}, + {{ 32729/*0.998795 Q15*/, 1608/*0.049068 Q15*/}}, + {{ 31581/*0.963776 Q15*/, 8740/*0.266713 Q15*/}}, + {{ 28899/*0.881921 Q15*/, 15447/*0.471397 Q15*/}}, + {{ 24812/*0.757209 Q15*/, 21403/*0.653173 Q15*/}}, + {{ 19520/*0.595699 Q15*/, 26320/*0.803208 Q15*/}}, + {{ 13279/*0.405241 Q15*/, 29957/*0.914210 Q15*/}}, + {{ 6393/*0.195090 Q15*/, 32138/*0.980785 Q15*/}}, + {{ -804/*-0.024541 Q15*/, 32758/*0.999699 Q15*/}}, + {{ -7962/*-0.242980 Q15*/, 31786/*0.970031 Q15*/}}, + {{-14733/*-0.449611 Q15*/, 29269/*0.893224 Q15*/}}, + {{-20788/*-0.634393 Q15*/, 25330/*0.773010 Q15*/}}, + {{-25833/*-0.788346 Q15*/, 20160/*0.615232 Q15*/}}, + {{-29622/*-0.903989 Q15*/, 14010/*0.427555 Q15*/}}, + {{-31972/*-0.975702 Q15*/, 7180/*0.219101 Q15*/}} +}; + +const Word16 kLog2TableFrac_x[256] = +{ + 0, 1, 3, 4, 6, 7, 9, 10, + 11, 13, 14, 16, 17, 18, 20, 21, + 22, 24, 25, 26, 28, 29, 30, 32, + 33, 34, 36, 37, 38, 40, 41, 42, + 44, 45, 46, 47, 49, 50, 51, 52, + 54, 55, 56, 57, 59, 60, 61, 62, + 63, 65, 66, 67, 68, 69, 71, 72, + 73, 74, 75, 77, 78, 79, 80, 81, + 82, 84, 85, 86, 87, 88, 89, 90, + 92, 93, 94, 95, 96, 97, 98, 99, + 100, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 111, 112, 113, 114, 116, 117, + 118, 119, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 155, 156, + 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 169, 170, 171, + 172, 173, 174, 175, 176, 177, 178, 178, + 179, 180, 181, 182, 183, 184, 185, 185, + 186, 187, 188, 189, 190, 191, 192, 192, + 193, 194, 195, 196, 197, 198, 198, 199, + 200, 201, 202, 203, 203, 204, 205, 206, + 207, 208, 208, 209, 210, 211, 212, 212, + 213, 214, 215, 216, 216, 217, 218, 219, + 220, 220, 221, 222, 223, 224, 224, 225, + 226, 227, 228, 228, 229, 230, 231, 231, + 232, 233, 234, 234, 235, 236, 237, 238, + 238, 239, 240, 241, 241, 242, 243, 244, + 244, 245, 246, 247, 247, 248, 249, 249, + 250, 251, 252, 252, 253, 254, 255, 255 +}; + +const Word16 kExp2TableFrac_x[256] = /* Q15 */ +{ + 32767, 32678, 32590, 32502, 32414, 32326, 32239, 32152, + 32065, 31978, 31892, 31805, 31719, 31634, 31548, 31463, + 31378, 31293, 31208, 31124, 31040, 30956, 30872, 30789, + 30705, 30622, 30540, 30457, 30375, 30293, 30211, 30129, + 30047, 29966, 29885, 29804, 29724, 29643, 29563, 29483, + 29404, 29324, 29245, 29166, 29087, 29008, 28930, 28852, + 28774, 28696, 28618, 28541, 28464, 28387, 28310, 28233, + 28157, 28081, 28005, 27929, 27854, 27778, 27703, 27628, + 27554, 27479, 27405, 27331, 27257, 27183, 27110, 27036, + 26963, 26890, 26818, 26745, 26673, 26601, 26529, 26457, + 26385, 26314, 26243, 26172, 26101, 26031, 25960, 25890, + 25820, 25750, 25681, 25611, 25542, 25473, 25404, 25335, + 25267, 25198, 25130, 25062, 24995, 24927, 24860, 24792, + 24725, 24659, 24592, 24525, 24459, 24393, 24327, 24261, + 24196, 24130, 24065, 24000, 23935, 23870, 23806, 23741, + 23677, 23613, 23549, 23486, 23422, 23359, 23296, 23233, + 23170, 23107, 23045, 22982, 22920, 22858, 22796, 22735, + 22673, 22612, 22551, 22490, 22429, 22368, 22308, 22248, + 22187, 22127, 22068, 22008, 21948, 21889, 21830, 21771, + 21712, 21653, 21595, 21536, 21478, 21420, 21362, 21304, + 21247, 21189, 21132, 21075, 21018, 20961, 20904, 20848, + 20791, 20735, 20679, 20623, 20568, 20512, 20456, 20401, + 20346, 20291, 20236, 20181, 20127, 20072, 20018, 19964, + 19910, 19856, 19802, 19749, 19696, 19642, 19589, 19536, + 19483, 19431, 19378, 19326, 19274, 19221, 19169, 19118, + 19066, 19014, 18963, 18912, 18861, 18810, 18759, 18708, + 18657, 18607, 18557, 18506, 18456, 18406, 18357, 18307, + 18258, 18208, 18159, 18110, 18061, 18012, 17963, 17915, + 17866, 17818, 17770, 17722, 17674, 17626, 17578, 17531, + 17483, 17436, 17389, 17342, 17295, 17248, 17202, 17155, + 17109, 17063, 17016, 16970, 16925, 16879, 16833, 16788, + 16742, 16697, 16652, 16607, 16562, 16517, 16472, 16428 +}; + +const Word16 sqrt_table_pitch_search[256+1] = /* Q11 */ +{ + 0, 2048, 2896, 3547, 4096, 4579, 5017, 5418, + 5793, 6144, 6476, 6792, 7094, 7384, 7663, 7932, + 8192, 8444, 8689, 8927, 9159, 9385, 9606, 9822, + 10033, 10240, 10443, 10642, 10837, 11029, 11217, 11403, + 11585, 11765, 11942, 12116, 12288, 12457, 12625, 12790, + 12953, 13114, 13273, 13430, 13585, 13738, 13890, 14040, + 14189, 14336, 14482, 14626, 14768, 14910, 15050, 15188, + 15326, 15462, 15597, 15731, 15864, 15995, 16126, 16255, + 16384, 16512, 16638, 16764, 16888, 17012, 17135, 17257, + 17378, 17498, 17618, 17736, 17854, 17971, 18087, 18203, + 18318, 18432, 18545, 18658, 18770, 18882, 18992, 19102, + 19212, 19321, 19429, 19537, 19644, 19750, 19856, 19961, + 20066, 20170, 20274, 20377, 20480, 20582, 20684, 20785, + 20886, 20986, 21085, 21185, 21283, 21382, 21480, 21577, + 21674, 21771, 21867, 21962, 22058, 22153, 22247, 22341, + 22435, 22528, 22621, 22713, 22806, 22897, 22989, 23080, + 23170, 23261, 23351, 23440, 23530, 23619, 23707, 23796, + 23884, 23971, 24059, 24146, 24232, 24319, 24405, 24491, + 24576, 24661, 24746, 24831, 24915, 24999, 25083, 25166, + 25249, 25332, 25415, 25497, 25580, 25661, 25743, 25824, + 25905, 25986, 26067, 26147, 26227, 26307, 26387, 26466, + 26545, 26624, 26703, 26781, 26859, 26937, 27015, 27092, + 27170, 27247, 27324, 27400, 27477, 27553, 27629, 27705, + 27780, 27856, 27931, 28006, 28081, 28155, 28230, 28304, + 28378, 28452, 28525, 28599, 28672, 28745, 28818, 28891, + 28963, 29035, 29108, 29180, 29251, 29323, 29394, 29466, + 29537, 29608, 29678, 29749, 29819, 29890, 29960, 30030, + 30099, 30169, 30238, 30308, 30377, 30446, 30515, 30583, + 30652, 30720, 30788, 30856, 30924, 30992, 31059, 31127, + 31194, 31261, 31328, 31395, 31462, 31529, 31595, 31661, + 31727, 31794, 31859, 31925, 31991, 32056, 32122, 32187, + 32252, 32317, 32382, 32446, 32511, 32575, 32640, 32704, + 32766 +}; + + +/******************** moved over from tables_plus.c ************************/ + +/* For bass post filter */ +const Word16 filt_lp[1+L_FILT] = +{ + 2892/*0.088250f Q15*/, 2831/*0.086410f Q15*/, 2657/*0.081074f Q15*/, 2384/*0.072768f Q15*/, + 2041/*0.062294f Q15*/, 1659/*0.050623f Q15*/, 1271/*0.038774f Q15*/, 907/*0.027692f Q15*/, + 594/*0.018130f Q15*/, 347/*0.010578f Q15*/, 171/*0.005221f Q15*/, 64/*0.001946f Q15*/, + 13/*0.000385f Q15*/ +}; +const Word16 filt_lp_16kHz[1+L_FILT16k] = +{ + 2340/*0.071410f Q15*/, 2308/*0.070433f Q15*/, 2214/*0.067568f Q15*/, 2064/*0.062999f Q15*/, + 1868/*0.057020f Q15*/, 1639/*0.050005f Q15*/, 1389/*0.042378f Q15*/, 1133/*0.034577f Q15*/, + 885/*0.027022f Q15*/, 658/*0.020078f Q15*/, 460/*0.014031f Q15*/, 297/*0.009070f Q15*/, + 173/*0.005276f Q15*/, 86/*0.002625f Q15*/, 33/*0.000999f Q15*/, 7/*0.000205f Q15*/ +}; + +/* 1/4 resolution interpolation filter (-3 dB at 0.856*fs/2) */ +const Word16 pitch_inter4_2[PIT_FIR_SIZE2] = +{ + /* cut-off frequency at 0.94*fs/2 */ + 30802/*0.940000f Q15*/, + 28062/*0.856390f Q15*/, 20718/*0.632268f Q15*/, 11061/*0.337560f Q15*/, 1936/*0.059072f Q15*/, + -4295/*-0.131059f Q15*/, -6534/*-0.199393f Q15*/, -5196/*-0.158569f Q15*/, -1847/*-0.056359f Q15*/, + 1560/*0.047606f Q15*/, 3498/*0.106749f Q15*/, 3398/*0.1037059f Q15*/, 1706/*0.052062f Q15*/, + -497/*-0.015182f Q15*/, -2087/*-0.063705f Q15*/, -2414/*-0.073660f Q15*/, -1524/*-0.046497f Q15*/, + -32/*-0.000983f Q15*/, 1253/*0.038227f Q15*/, 1741/*0.053143f Q15*/, 1313/*0.040059f Q15*/, + 305/*0.009308f Q15*/, -710/*-0.021674f Q15*/, -1238/*-0.037767f Q15*/, -1087/*-0.033186f Q15*/, + -427/*-0.013028f Q15*/, 351/*0.010702f Q15*/, 849/*0.025901f Q15*/, 862/*0.026318f Q15*/, + 453/*0.013821f Q15*/, -119/*-0.003645f Q15*/, -551/*-0.016813f Q15*/, -651/*-0.019855f Q15*/, + -418/*-0.012766f Q15*/, -17/*-0.000530f Q15*/, 330/*0.010080f Q15*/, 463/*0.014122f Q15*/, + 349/*0.010657f Q15*/, 85/*0.002594f Q15*/, -176/*-0.005363f Q15*/, -306/*-0.009344f Q15*/, + -265/*-0.008101f Q15*/, -104/*-0.003182f Q15*/, 76/*0.002330f Q15*/, 185/*0.005635f Q15*/, + 182/*0.005562f Q15*/, 93/*0.002844f Q15*/, -21/*-0.000627f Q15*/, -98/*-0.002993f Q15*/, + -110/*-0.003362f Q15*/, -67/*-0.002044f Q15*/, -4/*-0.000116f Q15*/, 43/*0.001315f Q15*/, + 55/*0.001692f Q15*/, 38/*0.001151f Q15*/, 8/*0.000259f Q15*/, -14/*-0.000417f Q15*/, + -20/*-0.000618f Q15*/, -14/*-0.000434f Q15*/, -4/*-0.000133f Q15*/, 2/*0.000063f Q15*/, + 3/*0.000098f Q15*/, 2/*0.000048f Q15*/, 0/*0.000007f Q15*/, 0/*0.000000f Q15*/ +}; +/* 1/4 resolution interpolation filter (-3 dB at 0.791*fs/2) */ +const Word16 pitch_inter4_1[UP_SAMP * L_INTERPOL1 + 1] = +{ + 29491/*0.900000F Q15*/, + 26836/*0.818959F Q15*/, 19820/* 0.604850F Q15*/, 10859/* 0.331379F Q15*/, 2751/* 0.083958F Q15*/, + -2484/*-0.075795F Q15*/, -4283/* -0.130717F Q15*/, -3463/*-0.105685F Q15*/, -1533/*-0.046774F Q15*/, + 146/*0.004467F Q15*/, 911/* 0.027789F Q15*/, 840/* 0.025642F Q15*/, 412/* 0.012571F Q15*/, + 63/*0.001927F Q15*/, -51/* -0.001571F Q15*/, -25/*-0.000753F Q15*/, 0/* 0.000000f Q15*/ +}; +/* 1/6 resolution interpolation filter (-3 dB at 0.95*fs/2) */ +const Word16 pitch_inter6_2[PIT_FIR_SIZE6_2] = +{ + 31129/*0.949986374119862f Q15*/, + 29854/*0.911081104469830f Q15*/, + 26218/*0.800115099292852f Q15*/, + 20753/*0.633320673120883f Q15*/, + 14240/*0.434558462154083f Q15*/, + 7575/*0.231177017786780f Q15*/, + 1618/*0.049378173063717f Q15*/, + -2950/*-0.090039611811170f Q15*/, + -5727/*-0.174782560924477f Q15*/, + -6635/*-0.202477516286360f Q15*/, + -5905/*-0.180218293244902f Q15*/, + -4012/*-0.122429229978978f Q15*/, + -1558/*-0.047552067127379f Q15*/, + 843/*0.025733669494145f Q15*/, + 2687/*0.081995376731897f Q15*/, + 3656/*0.111581381838187f Q15*/, + 3663/*0.111781798292302f Q15*/, + 2834/*0.086499988914996f Q15*/, + 1462/*0.044629684447068f Q15*/, + -79/*-0.002416435594242f Q15*/, + -1423/*-0.043440027386915f Q15*/, + -2289/*-0.069857782812169f Q15*/, + -2533/*-0.077293683967992f Q15*/, + -2166/*-0.066098268486336f Q15*/, + -1336/*-0.040782649068098f Q15*/, + -282/*-0.008590773415008f Q15*/, + 734/*0.022397654632128f Q15*/, + 1480/*0.045171360007974f Q15*/, + 1811/*0.055274128677739f Q15*/, + 1690/*0.051578034020076f Q15*/, + 1187/*0.036232016917169f Q15*/, + 454/*0.013869500422767f Q15*/, + -317/*-0.009680698856947f Q15*/, + -945/*-0.028843394410080f Q15*/, + -1296/*-0.039560663181280f Q15*/, + -1314/*-0.040095747151623f Q15*/, + -1023/*-0.031231107680685f Q15*/, + -520/*-0.015866154815425f Q15*/, + 60/*0.001841532922707f Q15*/, + 575/*0.017553701334759f Q15*/, + 910/*0.027778555138199f Q15*/, + 1003/*0.030612329573745f Q15*/, + 853/*0.026046143652186f Q15*/, + 518/*0.015803012695681f Q15*/, + 91/*0.002782973481834f Q15*/, + -319/*-0.009720124055079f Q15*/, + -617/*-0.018826488463900f Q15*/, + -744/*-0.022710487805852f Q15*/, + -686/*-0.020936374578238f Q15*/, + -473/*-0.014436620433404f Q15*/, + -169/*-0.005169079181373f Q15*/, + 145/*0.004437651243491f Q15*/, + 397/*0.012100372954920f Q15*/, + 531/*0.016207075406240f Q15*/, + 529/*0.016135389123271f Q15*/, + 403/*0.012306629559665f Q15*/, + 196/*0.005986734945567f Q15*/, + -36/*-0.001094950878591f Q15*/, + -236/*-0.007200842219958f Q15*/, + -360/*-0.010998212848124f Q15*/, + -388/*-0.011835179448280f Q15*/, + -322/*-0.009826566540474f Q15*/, + -188/*-0.005747665080695f Q15*/, + -26/*-0.000780600030751f Q15*/, + 125/*0.003810613287985f Q15*/, + 229/*0.006990479233404f Q15*/, + 268/*0.008174249796791f Q15*/, + 240/*0.007317375965949f Q15*/, + 159/*0.004864690818765f Q15*/, + 52/*0.001587005259212f Q15*/, + -54/*-0.001642504305841f Q15*/, + -133/*-0.004070609517416f Q15*/, + -171/*-0.005230670504649f Q15*/, + -164/*-0.005019147682711f Q15*/, + -120/*-0.003673879223241f Q15*/, + -55/*-0.001671460853812f Q15*/, + 14/*0.000420750005150f Q15*/, + 69/*0.002095384947391f Q15*/, + 99/*0.003020513665060f Q15*/, + 101/*0.003095468528243f Q15*/, + 80/*0.002441025550729f Q15*/, + 44/*0.001335514431569f Q15*/, + 4/*0.000120805384516f Q15*/, + -29/*-0.000893340757369f Q15*/, + -49/*-0.001501610712267f Q15*/, + -54/*-0.001636887611783f Q15*/, + -45/*-0.001362571776250f Q15*/, + -27/*-0.000832126175863f Q15*/, + -8/*-0.000232033375863f Q15*/, + 9/*0.000273627139471f Q15*/, + 19/*0.000582092683087f Q15*/, + 22/*0.000666445711949f Q15*/, + 19/*0.000566088888178f Q15*/, + 12/*0.000360374058147f Q15*/, + 4/*0.000136306914913f Q15*/, + -1/*-0.000038864994777f Q15*/, + -4/*-0.000132755824518f Q15*/, + -5/*-0.000148377158880f Q15*/, + -4/*-0.000112937171810f Q15*/, + -2/*-0.000061132514471f Q15*/, + -1/*-0.000019974224468f Q15*/, + 0/*-0.000000460344975f Q15*/, + 0/*0.000001976848453f Q15*/ +}; + +const Word16 grid50_fx[(GRID50_POINTS-1)/2 - 1] = +{ + 32703, 32510, 32188, 31739, 31164, 30467, + 29649, 28715, 27667, 26510, 25248, 23887, + 22431, 20887, 19261, 17558, 15786, 13952, + 12063, 10126, 8149, 6140, 4107, 2058 +}; + + +const Word16 grid40_fx[(GRID40_POINTS-1)/2 - 1] = +{ + 32667, 32365, 31863, 31164, 30274, 29197, + 27939, 26510, 24917, 23170, 21281, 19261, + 17121, 14876, 12540, 10126, 7650, 5126, + 2571 +}; + +const Word16 bit_rates_div50[] = /* bit rate values / 50 to Fit in a Word16 */ +{ + ACELP_7k20/50, ACELP_8k00/50, ACELP_11k60/50, ACELP_12k15/50, + ACELP_12k85/50, ACELP_13k20/50, ACELP_14k80/50, ACELP_16k40/50, ACELP_22k60/50, + ACELP_24k40/50, ACELP_29k00/50, ACELP_29k20/50, ACELP_30k20/50, ACELP_30k40/50, + ACELP_32k /50, ACELP_48k /50, ACELP_64k /50, HQ_96k /50, HQ_128k /50 +}; + +const Word16 bit_rates_16k_div50[] = /* bit rate values / 50 to Fit in a Word16 */ +{ + ACELP_8k00 /50, ACELP_14k80/50, ACELP_22k60/50, ACELP_24k40/50, ACELP_29k00/50, + ACELP_29k20/50, ACELP_30k20/50, ACELP_30k40/50, ACELP_32k /50, ACELP_48k /50, ACELP_64k /50 +}; + +const Word16 L_frame_inv[8] = { 0x4000, 0x369D, 0x3333, 0x2D83, 0x2AAB, 0x28F6, 0, 0x2222 }; + +const Word16 TecLowBandTable[] = {0, 2, 4, 6}; +const Word16 TecSC_Fx[] = +{ + 23999/*0.3662f*2.0f Q15*/, 7065/*0.1078f*2.0f Q15*/, 7825/*0.1194f*2.0f Q15*/, + 8448/*0.1289f*2.0f Q15*/, 8946/*0.1365f*2.0f Q15*/, 9254/*0.1412f*2.0f Q15*/ +}; + +const Word16 uniform_model_fx[] = { MAX_AR_FREQ, MAX_AR_FREQ / 2, 0 }; + +const Word16 RotVector_32[2*20] = +{ + /** + * \brief Twiddle factors are unscaled + */ + SHC(0x7d8a), SHC(0xe707), SHC(0x7642), SHC(0xcf04), SHC(0x6a6e), SHC(0xb8e3), SHC(0x5a82), SHC(0xa57e), + SHC(0x471d), SHC(0x9592), SHC(0x30fc), SHC(0x89be), SHC(0x18f9), SHC(0x8276), SHC(0x7642), SHC(0xcf04), + SHC(0x5a82), SHC(0xa57e), SHC(0x30fc), SHC(0x89be), SHC(0xcf04), SHC(0x89be), SHC(0xa57e), SHC(0xa57e), + SHC(0x89be), SHC(0xcf04), SHC(0x6a6e), SHC(0xb8e3), SHC(0x30fc), SHC(0x89be), SHC(0xe707), SHC(0x8276), + SHC(0xa57e), SHC(0xa57e), SHC(0x8276), SHC(0xe707), SHC(0x89be), SHC(0x30fc), SHC(0xb8e3), SHC(0x6a6e) +}; + +/** + * \brief Twiddle factors are unscaled + */ +const Word16 RotVector_480[2*(480-30)] = +{ + SHC(0x7fff), SHC(0x0000), SHC(0x7ff5), SHC(0xfca6), + SHC(0x7fd3), SHC(0xf94d), SHC(0x7f9b), SHC(0xf5f5), SHC(0x7f4c), SHC(0xf29f), SHC(0x7ee8), SHC(0xef4b), + SHC(0x7e6d), SHC(0xebfa), SHC(0x7ddb), SHC(0xe8ad), SHC(0x7d34), SHC(0xe563), SHC(0x7c77), SHC(0xe21e), + SHC(0x7ba3), SHC(0xdedf), SHC(0x7abb), SHC(0xdba5), SHC(0x79bc), SHC(0xd872), SHC(0x78a8), SHC(0xd546), + SHC(0x7780), SHC(0xd221), SHC(0x7642), SHC(0xcf04), SHC(0x74ef), SHC(0xcbf0), SHC(0x7388), SHC(0xc8e5), + SHC(0x720d), SHC(0xc5e4), SHC(0x707d), SHC(0xc2ec), SHC(0x6eda), SHC(0xc000), SHC(0x6d23), SHC(0xbd1f), + SHC(0x6b5a), SHC(0xba49), SHC(0x697d), SHC(0xb780), SHC(0x678e), SHC(0xb4c3), SHC(0x658d), SHC(0xb214), + SHC(0x637a), SHC(0xaf72), SHC(0x6155), SHC(0xacdf), SHC(0x5f1f), SHC(0xaa5a), SHC(0x5cd9), SHC(0xa7e4), + SHC(0x7fff), SHC(0x0000), SHC(0x7fd3), SHC(0xf94d), SHC(0x7f4c), SHC(0xf29f), SHC(0x7e6d), SHC(0xebfa), + SHC(0x7d34), SHC(0xe563), SHC(0x7ba3), SHC(0xdedf), SHC(0x79bc), SHC(0xd872), SHC(0x7780), SHC(0xd221), + SHC(0x74ef), SHC(0xcbf0), SHC(0x720d), SHC(0xc5e4), SHC(0x6eda), SHC(0xc000), SHC(0x6b5a), SHC(0xba49), + SHC(0x678e), SHC(0xb4c3), SHC(0x637a), SHC(0xaf72), SHC(0x5f1f), SHC(0xaa5a), SHC(0x5a82), SHC(0xa57e), + SHC(0x55a6), SHC(0xa0e1), SHC(0x508e), SHC(0x9c86), SHC(0x4b3d), SHC(0x9872), SHC(0x45b7), SHC(0x94a6), + SHC(0x4000), SHC(0x9126), SHC(0x3a1c), SHC(0x8df3), SHC(0x3410), SHC(0x8b11), SHC(0x2ddf), SHC(0x8880), + SHC(0x278e), SHC(0x8644), SHC(0x2121), SHC(0x845d), SHC(0x1a9d), SHC(0x82cc), SHC(0x1406), SHC(0x8193), + SHC(0x0d61), SHC(0x80b4), SHC(0x06b3), SHC(0x802d), SHC(0x7fff), SHC(0x0000), SHC(0x7f9b), SHC(0xf5f5), + SHC(0x7e6d), SHC(0xebfa), SHC(0x7c77), SHC(0xe21e), SHC(0x79bc), SHC(0xd872), SHC(0x7642), SHC(0xcf04), + SHC(0x720d), SHC(0xc5e4), SHC(0x6d23), SHC(0xbd1f), SHC(0x678e), SHC(0xb4c3), SHC(0x6155), SHC(0xacdf), + SHC(0x5a82), SHC(0xa57e), SHC(0x5321), SHC(0x9eab), SHC(0x4b3d), SHC(0x9872), SHC(0x42e1), SHC(0x92dd), + SHC(0x3a1c), SHC(0x8df3), SHC(0x30fc), SHC(0x89be), SHC(0x278e), SHC(0x8644), SHC(0x1de2), SHC(0x8389), + SHC(0x1406), SHC(0x8193), SHC(0x0a0b), SHC(0x8065), SHC(0x0000), SHC(0x8000), SHC(0xf5f5), SHC(0x8065), + SHC(0xebfa), SHC(0x8193), SHC(0xe21e), SHC(0x8389), SHC(0xd872), SHC(0x8644), SHC(0xcf04), SHC(0x89be), + SHC(0xc5e4), SHC(0x8df3), SHC(0xbd1f), SHC(0x92dd), SHC(0xb4c3), SHC(0x9872), SHC(0xacdf), SHC(0x9eab), + SHC(0x7fff), SHC(0x0000), SHC(0x7f4c), SHC(0xf29f), SHC(0x7d34), SHC(0xe563), SHC(0x79bc), SHC(0xd872), + SHC(0x74ef), SHC(0xcbf0), SHC(0x6eda), SHC(0xc000), SHC(0x678e), SHC(0xb4c3), SHC(0x5f1f), SHC(0xaa5a), + SHC(0x55a6), SHC(0xa0e1), SHC(0x4b3d), SHC(0x9872), SHC(0x4000), SHC(0x9126), SHC(0x3410), SHC(0x8b11), + SHC(0x278e), SHC(0x8644), SHC(0x1a9d), SHC(0x82cc), SHC(0x0d61), SHC(0x80b4), SHC(0x0000), SHC(0x8000), + SHC(0xf29f), SHC(0x80b4), SHC(0xe563), SHC(0x82cc), SHC(0xd872), SHC(0x8644), SHC(0xcbf0), SHC(0x8b11), + SHC(0xc000), SHC(0x9126), SHC(0xb4c3), SHC(0x9872), SHC(0xaa5a), SHC(0xa0e1), SHC(0xa0e1), SHC(0xaa5a), + SHC(0x9872), SHC(0xb4c3), SHC(0x9126), SHC(0xc000), SHC(0x8b11), SHC(0xcbf0), SHC(0x8644), SHC(0xd872), + SHC(0x82cc), SHC(0xe563), SHC(0x80b4), SHC(0xf29f), SHC(0x7fff), SHC(0x0000), SHC(0x7ee8), SHC(0xef4b), + SHC(0x7ba3), SHC(0xdedf), SHC(0x7642), SHC(0xcf04), SHC(0x6eda), SHC(0xc000), SHC(0x658d), SHC(0xb214), + SHC(0x5a82), SHC(0xa57e), SHC(0x4dec), SHC(0x9a73), SHC(0x4000), SHC(0x9126), SHC(0x30fc), SHC(0x89be), + SHC(0x2121), SHC(0x845d), SHC(0x10b5), SHC(0x8118), SHC(0x0000), SHC(0x8000), SHC(0xef4b), SHC(0x8118), + SHC(0xdedf), SHC(0x845d), SHC(0xcf04), SHC(0x89be), SHC(0xc000), SHC(0x9126), SHC(0xb214), SHC(0x9a73), + SHC(0xa57e), SHC(0xa57e), SHC(0x9a73), SHC(0xb214), SHC(0x9126), SHC(0xc000), SHC(0x89be), SHC(0xcf04), + SHC(0x845d), SHC(0xdedf), SHC(0x8118), SHC(0xef4b), SHC(0x8000), SHC(0x0000), SHC(0x8118), SHC(0x10b5), + SHC(0x845d), SHC(0x2121), SHC(0x89be), SHC(0x30fc), SHC(0x9126), SHC(0x4000), SHC(0x9a73), SHC(0x4dec), + SHC(0x7fff), SHC(0x0000), SHC(0x7e6d), SHC(0xebfa), SHC(0x79bc), SHC(0xd872), SHC(0x720d), SHC(0xc5e4), + SHC(0x678e), SHC(0xb4c3), SHC(0x5a82), SHC(0xa57e), SHC(0x4b3d), SHC(0x9872), SHC(0x3a1c), SHC(0x8df3), + SHC(0x278e), SHC(0x8644), SHC(0x1406), SHC(0x8193), SHC(0x0000), SHC(0x8000), SHC(0xebfa), SHC(0x8193), + SHC(0xd872), SHC(0x8644), SHC(0xc5e4), SHC(0x8df3), SHC(0xb4c3), SHC(0x9872), SHC(0xa57e), SHC(0xa57e), + SHC(0x9872), SHC(0xb4c3), SHC(0x8df3), SHC(0xc5e4), SHC(0x8644), SHC(0xd872), SHC(0x8193), SHC(0xebfa), + SHC(0x8000), SHC(0x0000), SHC(0x8193), SHC(0x1406), SHC(0x8644), SHC(0x278e), SHC(0x8df3), SHC(0x3a1c), + SHC(0x9872), SHC(0x4b3d), SHC(0xa57e), SHC(0x5a82), SHC(0xb4c3), SHC(0x678e), SHC(0xc5e4), SHC(0x720d), + SHC(0xd872), SHC(0x79bc), SHC(0xebfa), SHC(0x7e6d), SHC(0x7fff), SHC(0x0000), SHC(0x7ddb), SHC(0xe8ad), + SHC(0x7780), SHC(0xd221), SHC(0x6d23), SHC(0xbd1f), SHC(0x5f1f), SHC(0xaa5a), SHC(0x4dec), SHC(0x9a73), + SHC(0x3a1c), SHC(0x8df3), SHC(0x245b), SHC(0x8545), SHC(0x0d61), SHC(0x80b4), SHC(0xf5f5), SHC(0x8065), + SHC(0xdedf), SHC(0x845d), SHC(0xc8e5), SHC(0x8c78), SHC(0xb4c3), SHC(0x9872), SHC(0xa327), SHC(0xa7e4), + SHC(0x94a6), SHC(0xba49), SHC(0x89be), SHC(0xcf04), SHC(0x82cc), SHC(0xe563), SHC(0x800b), SHC(0xfca6), + SHC(0x8193), SHC(0x1406), SHC(0x8758), SHC(0x2aba), SHC(0x9126), SHC(0x4000), SHC(0x9eab), SHC(0x5321), + SHC(0xaf72), SHC(0x637a), SHC(0xc2ec), SHC(0x707d), SHC(0xd872), SHC(0x79bc), SHC(0xef4b), SHC(0x7ee8), + SHC(0x06b3), SHC(0x7fd3), SHC(0x1de2), SHC(0x7c77), SHC(0x3410), SHC(0x74ef), SHC(0x4880), SHC(0x697d), + SHC(0x7fff), SHC(0x0000), SHC(0x7ffd), SHC(0xfe53), SHC(0x7ff5), SHC(0xfca6), SHC(0x7fe7), SHC(0xfafa), + SHC(0x7fd3), SHC(0xf94d), SHC(0x7fba), SHC(0xf7a1), SHC(0x7f9b), SHC(0xf5f5), SHC(0x7f77), SHC(0xf44a), + SHC(0x7f4c), SHC(0xf29f), SHC(0x7f1d), SHC(0xf0f5), SHC(0x7ee8), SHC(0xef4b), SHC(0x7ead), SHC(0xeda2), + SHC(0x7e6d), SHC(0xebfa), SHC(0x7e27), SHC(0xea53), SHC(0x7ddb), SHC(0xe8ad), SHC(0x7d8a), SHC(0xe707), + SHC(0x7d34), SHC(0xe563), SHC(0x7cd8), SHC(0xe3c0), SHC(0x7c77), SHC(0xe21e), SHC(0x7c10), SHC(0xe07e), + SHC(0x7ba3), SHC(0xdedf), SHC(0x7b32), SHC(0xdd41), SHC(0x7abb), SHC(0xdba5), SHC(0x7a3e), SHC(0xda0b), + SHC(0x79bc), SHC(0xd872), SHC(0x7935), SHC(0xd6db), SHC(0x78a8), SHC(0xd546), SHC(0x7817), SHC(0xd3b2), + SHC(0x7780), SHC(0xd221), SHC(0x76e3), SHC(0xd092), SHC(0x7fff), SHC(0x0000), SHC(0x7fe7), SHC(0xfafa), + SHC(0x7f9b), SHC(0xf5f5), SHC(0x7f1d), SHC(0xf0f5), SHC(0x7e6d), SHC(0xebfa), SHC(0x7d8a), SHC(0xe707), + SHC(0x7c77), SHC(0xe21e), SHC(0x7b32), SHC(0xdd41), SHC(0x79bc), SHC(0xd872), SHC(0x7817), SHC(0xd3b2), + SHC(0x7642), SHC(0xcf04), SHC(0x743e), SHC(0xca69), SHC(0x720d), SHC(0xc5e4), SHC(0x6fae), SHC(0xc175), + SHC(0x6d23), SHC(0xbd1f), SHC(0x6a6e), SHC(0xb8e3), SHC(0x678e), SHC(0xb4c3), SHC(0x6485), SHC(0xb0c2), + SHC(0x6155), SHC(0xacdf), SHC(0x5dfe), SHC(0xa91d), SHC(0x5a82), SHC(0xa57e), SHC(0x56e3), SHC(0xa202), + SHC(0x5321), SHC(0x9eab), SHC(0x4f3e), SHC(0x9b7b), SHC(0x4b3d), SHC(0x9872), SHC(0x471d), SHC(0x9592), + SHC(0x42e1), SHC(0x92dd), SHC(0x3e8b), SHC(0x9052), SHC(0x3a1c), SHC(0x8df3), SHC(0x3597), SHC(0x8bc2), + SHC(0x7fff), SHC(0x0000), SHC(0x7fba), SHC(0xf7a1), SHC(0x7ee8), SHC(0xef4b), SHC(0x7d8a), SHC(0xe707), + SHC(0x7ba3), SHC(0xdedf), SHC(0x7935), SHC(0xd6db), SHC(0x7642), SHC(0xcf04), SHC(0x72cd), SHC(0xc763), + SHC(0x6eda), SHC(0xc000), SHC(0x6a6e), SHC(0xb8e3), SHC(0x658d), SHC(0xb214), SHC(0x603c), SHC(0xab9b), + SHC(0x5a82), SHC(0xa57e), SHC(0x5465), SHC(0x9fc4), SHC(0x4dec), SHC(0x9a73), SHC(0x471d), SHC(0x9592), + SHC(0x4000), SHC(0x9126), SHC(0x389d), SHC(0x8d33), SHC(0x30fc), SHC(0x89be), SHC(0x2925), SHC(0x86cb), + SHC(0x2121), SHC(0x845d), SHC(0x18f9), SHC(0x8276), SHC(0x10b5), SHC(0x8118), SHC(0x085f), SHC(0x8046), + SHC(0x0000), SHC(0x8000), SHC(0xf7a1), SHC(0x8046), SHC(0xef4b), SHC(0x8118), SHC(0xe707), SHC(0x8276), + SHC(0xdedf), SHC(0x845d), SHC(0xd6db), SHC(0x86cb), SHC(0x7fff), SHC(0x0000), SHC(0x7f77), SHC(0xf44a), + SHC(0x7ddb), SHC(0xe8ad), SHC(0x7b32), SHC(0xdd41), SHC(0x7780), SHC(0xd221), SHC(0x72cd), SHC(0xc763), + SHC(0x6d23), SHC(0xbd1f), SHC(0x668f), SHC(0xb36a), SHC(0x5f1f), SHC(0xaa5a), SHC(0x56e3), SHC(0xa202), + SHC(0x4dec), SHC(0x9a73), SHC(0x444d), SHC(0x93bf), SHC(0x3a1c), SHC(0x8df3), SHC(0x2f6e), SHC(0x891d), + SHC(0x245b), SHC(0x8545), SHC(0x18f9), SHC(0x8276), SHC(0x0d61), SHC(0x80b4), SHC(0x01ad), SHC(0x8003), + SHC(0xf5f5), SHC(0x8065), SHC(0xea53), SHC(0x81d9), SHC(0xdedf), SHC(0x845d), SHC(0xd3b2), SHC(0x87e9), + SHC(0xc8e5), SHC(0x8c78), SHC(0xbe8e), SHC(0x91ff), SHC(0xb4c3), SHC(0x9872), SHC(0xab9b), SHC(0x9fc4), + SHC(0xa327), SHC(0xa7e4), SHC(0x9b7b), SHC(0xb0c2), SHC(0x94a6), SHC(0xba49), SHC(0x8eb9), SHC(0xc467), + SHC(0x7fff), SHC(0x0000), SHC(0x7f1d), SHC(0xf0f5), SHC(0x7c77), SHC(0xe21e), SHC(0x7817), SHC(0xd3b2), + SHC(0x720d), SHC(0xc5e4), SHC(0x6a6e), SHC(0xb8e3), SHC(0x6155), SHC(0xacdf), SHC(0x56e3), SHC(0xa202), + SHC(0x4b3d), SHC(0x9872), SHC(0x3e8b), SHC(0x9052), SHC(0x30fc), SHC(0x89be), SHC(0x22bf), SHC(0x84ce), + SHC(0x1406), SHC(0x8193), SHC(0x0506), SHC(0x8019), SHC(0xf5f5), SHC(0x8065), SHC(0xe707), SHC(0x8276), + SHC(0xd872), SHC(0x8644), SHC(0xca69), SHC(0x8bc2), SHC(0xbd1f), SHC(0x92dd), SHC(0xb0c2), SHC(0x9b7b), + SHC(0xa57e), SHC(0xa57e), SHC(0x9b7b), SHC(0xb0c2), SHC(0x92dd), SHC(0xbd1f), SHC(0x8bc2), SHC(0xca69), + SHC(0x8644), SHC(0xd872), SHC(0x8276), SHC(0xe707), SHC(0x8065), SHC(0xf5f5), SHC(0x8019), SHC(0x0506), + SHC(0x8193), SHC(0x1406), SHC(0x84ce), SHC(0x22bf), SHC(0x7fff), SHC(0x0000), SHC(0x7ead), SHC(0xeda2), + SHC(0x7abb), SHC(0xdba5), SHC(0x743e), SHC(0xca69), SHC(0x6b5a), SHC(0xba49), SHC(0x603c), SHC(0xab9b), + SHC(0x5321), SHC(0x9eab), SHC(0x444d), SHC(0x93bf), SHC(0x3410), SHC(0x8b11), SHC(0x22bf), SHC(0x84ce), + SHC(0x10b5), SHC(0x8118), SHC(0xfe53), SHC(0x8003), SHC(0xebfa), SHC(0x8193), SHC(0xda0b), SHC(0x85c2), + SHC(0xc8e5), SHC(0x8c78), SHC(0xb8e3), SHC(0x9592), SHC(0xaa5a), SHC(0xa0e1), SHC(0x9d97), SHC(0xae27), + SHC(0x92dd), SHC(0xbd1f), SHC(0x8a65), SHC(0xcd79), SHC(0x845d), SHC(0xdedf), SHC(0x80e3), SHC(0xf0f5), + SHC(0x800b), SHC(0x035a), SHC(0x81d9), SHC(0x15ad), SHC(0x8644), SHC(0x278e), SHC(0x8d33), SHC(0x389d), + SHC(0x9683), SHC(0x4880), SHC(0xa202), SHC(0x56e3), SHC(0xaf72), SHC(0x637a), SHC(0xbe8e), SHC(0x6e01), + SHC(0x7fff), SHC(0x0000), SHC(0x7e27), SHC(0xea53), SHC(0x78a8), SHC(0xd546), SHC(0x6fae), SHC(0xc175), + SHC(0x637a), SHC(0xaf72), SHC(0x5465), SHC(0x9fc4), SHC(0x42e1), SHC(0x92dd), SHC(0x2f6e), SHC(0x891d), + SHC(0x1a9d), SHC(0x82cc), SHC(0x0506), SHC(0x8019), SHC(0xef4b), SHC(0x8118), SHC(0xda0b), SHC(0x85c2), + SHC(0xc5e4), SHC(0x8df3), SHC(0xb36a), SHC(0x9971), SHC(0xa327), SHC(0xa7e4), SHC(0x9592), SHC(0xb8e3), + SHC(0x8b11), SHC(0xcbf0), SHC(0x83f0), SHC(0xe07e), SHC(0x8065), SHC(0xf5f5), SHC(0x8089), SHC(0x0bb6), + SHC(0x845d), SHC(0x2121), SHC(0x8bc2), SHC(0x3597), SHC(0x9683), SHC(0x4880), SHC(0xa450), SHC(0x5951), + SHC(0xb4c3), SHC(0x678e), SHC(0xc763), SHC(0x72cd), SHC(0xdba5), SHC(0x7abb), SHC(0xf0f5), SHC(0x7f1d), + SHC(0x06b3), SHC(0x7fd3), SHC(0x1c40), SHC(0x7cd8), SHC(0x7fff), SHC(0x0000), SHC(0x7d8a), SHC(0xe707), + SHC(0x7642), SHC(0xcf04), SHC(0x6a6e), SHC(0xb8e3), SHC(0x5a82), SHC(0xa57e), SHC(0x471d), SHC(0x9592), + SHC(0x30fc), SHC(0x89be), SHC(0x18f9), SHC(0x8276), SHC(0x0000), SHC(0x8000), SHC(0xe707), SHC(0x8276), + SHC(0xcf04), SHC(0x89be), SHC(0xb8e3), SHC(0x9592), SHC(0xa57e), SHC(0xa57e), SHC(0x9592), SHC(0xb8e3), + SHC(0x89be), SHC(0xcf04), SHC(0x8276), SHC(0xe707), SHC(0x8000), SHC(0x0000), SHC(0x8276), SHC(0x18f9), + SHC(0x89be), SHC(0x30fc), SHC(0x9592), SHC(0x471d), SHC(0xa57e), SHC(0x5a82), SHC(0xb8e3), SHC(0x6a6e), + SHC(0xcf04), SHC(0x7642), SHC(0xe707), SHC(0x7d8a), SHC(0x0000), SHC(0x7fff), SHC(0x18f9), SHC(0x7d8a), + SHC(0x30fc), SHC(0x7642), SHC(0x471d), SHC(0x6a6e), SHC(0x5a82), SHC(0x5a82), SHC(0x6a6e), SHC(0x471d) +}; + +const Word16 RotVector_600[2*(600-30)] = +{ + SHC(0x7fff), SHC(0x0000), SHC(0x7ff9), SHC(0xfd52), + SHC(0x7fe3), SHC(0xfaa4), SHC(0x7fbf), SHC(0xf7f6), SHC(0x7f8d), SHC(0xf54a), SHC(0x7f4c), SHC(0xf29f), + SHC(0x7efe), SHC(0xeff5), SHC(0x7ea0), SHC(0xed4d), SHC(0x7e35), SHC(0xeaa7), SHC(0x7dbc), SHC(0xe804), + SHC(0x7d34), SHC(0xe563), SHC(0x7c9e), SHC(0xe2c5), SHC(0x7bfb), SHC(0xe02b), SHC(0x7b49), SHC(0xdd94), + SHC(0x7a89), SHC(0xdb01), SHC(0x79bc), SHC(0xd872), SHC(0x78e1), SHC(0xd5e8), SHC(0x77f9), SHC(0xd362), + SHC(0x7703), SHC(0xd0e1), SHC(0x7600), SHC(0xce66), SHC(0x74ef), SHC(0xcbf0), SHC(0x73d1), SHC(0xc980), + SHC(0x72a7), SHC(0xc716), SHC(0x716f), SHC(0xc4b3), SHC(0x702b), SHC(0xc256), SHC(0x6eda), SHC(0xc000), + SHC(0x6d7d), SHC(0xbdb1), SHC(0x6c13), SHC(0xbb6a), SHC(0x6a9d), SHC(0xb92a), SHC(0x691b), SHC(0xb6f3), + SHC(0x7fff), SHC(0x0000), SHC(0x7fe3), SHC(0xfaa4), SHC(0x7f8d), SHC(0xf54a), SHC(0x7efe), SHC(0xeff5), + SHC(0x7e35), SHC(0xeaa7), SHC(0x7d34), SHC(0xe563), SHC(0x7bfb), SHC(0xe02b), SHC(0x7a89), SHC(0xdb01), + SHC(0x78e1), SHC(0xd5e8), SHC(0x7703), SHC(0xd0e1), SHC(0x74ef), SHC(0xcbf0), SHC(0x72a7), SHC(0xc716), + SHC(0x702b), SHC(0xc256), SHC(0x6d7d), SHC(0xbdb1), SHC(0x6a9d), SHC(0xb92a), SHC(0x678e), SHC(0xb4c3), + SHC(0x6450), SHC(0xb07e), SHC(0x60e5), SHC(0xac5d), SHC(0x5d4f), SHC(0xa861), SHC(0x598f), SHC(0xa48c), + SHC(0x55a6), SHC(0xa0e1), SHC(0x5197), SHC(0x9d60), SHC(0x4d64), SHC(0x9a0b), SHC(0x490d), SHC(0x96e5), + SHC(0x4496), SHC(0x93ed), SHC(0x4000), SHC(0x9126), SHC(0x3b4d), SHC(0x8e91), SHC(0x3680), SHC(0x8c2f), + SHC(0x319a), SHC(0x8a00), SHC(0x2c9e), SHC(0x8807), SHC(0x7fff), SHC(0x0000), SHC(0x7fbf), SHC(0xf7f6), + SHC(0x7efe), SHC(0xeff5), SHC(0x7dbc), SHC(0xe804), SHC(0x7bfb), SHC(0xe02b), SHC(0x79bc), SHC(0xd872), + SHC(0x7703), SHC(0xd0e1), SHC(0x73d1), SHC(0xc980), SHC(0x702b), SHC(0xc256), SHC(0x6c13), SHC(0xbb6a), + SHC(0x678e), SHC(0xb4c3), SHC(0x62a0), SHC(0xae69), SHC(0x5d4f), SHC(0xa861), SHC(0x579f), SHC(0xa2b1), + SHC(0x5197), SHC(0x9d60), SHC(0x4b3d), SHC(0x9872), SHC(0x4496), SHC(0x93ed), SHC(0x3daa), SHC(0x8fd5), + SHC(0x3680), SHC(0x8c2f), SHC(0x2f1f), SHC(0x88fd), SHC(0x278e), SHC(0x8644), SHC(0x1fd5), SHC(0x8405), + SHC(0x17fc), SHC(0x8244), SHC(0x100b), SHC(0x8102), SHC(0x080a), SHC(0x8041), SHC(0x0000), SHC(0x8000), + SHC(0xf7f6), SHC(0x8041), SHC(0xeff5), SHC(0x8102), SHC(0xe804), SHC(0x8244), SHC(0xe02b), SHC(0x8405), + SHC(0x7fff), SHC(0x0000), SHC(0x7f8d), SHC(0xf54a), SHC(0x7e35), SHC(0xeaa7), SHC(0x7bfb), SHC(0xe02b), + SHC(0x78e1), SHC(0xd5e8), SHC(0x74ef), SHC(0xcbf0), SHC(0x702b), SHC(0xc256), SHC(0x6a9d), SHC(0xb92a), + SHC(0x6450), SHC(0xb07e), SHC(0x5d4f), SHC(0xa861), SHC(0x55a6), SHC(0xa0e1), SHC(0x4d64), SHC(0x9a0b), + SHC(0x4496), SHC(0x93ed), SHC(0x3b4d), SHC(0x8e91), SHC(0x319a), SHC(0x8a00), SHC(0x278e), SHC(0x8644), + SHC(0x1d3b), SHC(0x8362), SHC(0x12b3), SHC(0x8160), SHC(0x080a), SHC(0x8041), SHC(0xfd52), SHC(0x8007), + SHC(0xf29f), SHC(0x80b4), SHC(0xe804), SHC(0x8244), SHC(0xdd94), SHC(0x84b7), SHC(0xd362), SHC(0x8807), + SHC(0xc980), SHC(0x8c2f), SHC(0xc000), SHC(0x9126), SHC(0xb6f3), SHC(0x96e5), SHC(0xae69), SHC(0x9d60), + SHC(0xa671), SHC(0xa48c), SHC(0x9f1b), SHC(0xac5d), SHC(0x7fff), SHC(0x0000), SHC(0x7f4c), SHC(0xf29f), + SHC(0x7d34), SHC(0xe563), SHC(0x79bc), SHC(0xd872), SHC(0x74ef), SHC(0xcbf0), SHC(0x6eda), SHC(0xc000), + SHC(0x678e), SHC(0xb4c3), SHC(0x5f1f), SHC(0xaa5a), SHC(0x55a6), SHC(0xa0e1), SHC(0x4b3d), SHC(0x9872), + SHC(0x4000), SHC(0x9126), SHC(0x3410), SHC(0x8b11), SHC(0x278e), SHC(0x8644), SHC(0x1a9d), SHC(0x82cc), + SHC(0x0d61), SHC(0x80b4), SHC(0x0000), SHC(0x8000), SHC(0xf29f), SHC(0x80b4), SHC(0xe563), SHC(0x82cc), + SHC(0xd872), SHC(0x8644), SHC(0xcbf0), SHC(0x8b11), SHC(0xc000), SHC(0x9126), SHC(0xb4c3), SHC(0x9872), + SHC(0xaa5a), SHC(0xa0e1), SHC(0xa0e1), SHC(0xaa5a), SHC(0x9872), SHC(0xb4c3), SHC(0x9126), SHC(0xc000), + SHC(0x8b11), SHC(0xcbf0), SHC(0x8644), SHC(0xd872), SHC(0x82cc), SHC(0xe563), SHC(0x80b4), SHC(0xf29f), + SHC(0x7fff), SHC(0x0000), SHC(0x7efe), SHC(0xeff5), SHC(0x7bfb), SHC(0xe02b), SHC(0x7703), SHC(0xd0e1), + SHC(0x702b), SHC(0xc256), SHC(0x678e), SHC(0xb4c3), SHC(0x5d4f), SHC(0xa861), SHC(0x5197), SHC(0x9d60), + SHC(0x4496), SHC(0x93ed), SHC(0x3680), SHC(0x8c2f), SHC(0x278e), SHC(0x8644), SHC(0x17fc), SHC(0x8244), + SHC(0x080a), SHC(0x8041), SHC(0xf7f6), SHC(0x8041), SHC(0xe804), SHC(0x8244), SHC(0xd872), SHC(0x8644), + SHC(0xc980), SHC(0x8c2f), SHC(0xbb6a), SHC(0x93ed), SHC(0xae69), SHC(0x9d60), SHC(0xa2b1), SHC(0xa861), + SHC(0x9872), SHC(0xb4c3), SHC(0x8fd5), SHC(0xc256), SHC(0x88fd), SHC(0xd0e1), SHC(0x8405), SHC(0xe02b), + SHC(0x8102), SHC(0xeff5), SHC(0x8000), SHC(0x0000), SHC(0x8102), SHC(0x100b), SHC(0x8405), SHC(0x1fd5), + SHC(0x88fd), SHC(0x2f1f), SHC(0x8fd5), SHC(0x3daa), SHC(0x7fff), SHC(0x0000), SHC(0x7ea0), SHC(0xed4d), + SHC(0x7a89), SHC(0xdb01), SHC(0x73d1), SHC(0xc980), SHC(0x6a9d), SHC(0xb92a), SHC(0x5f1f), SHC(0xaa5a), + SHC(0x5197), SHC(0x9d60), SHC(0x424f), SHC(0x9283), SHC(0x319a), SHC(0x8a00), SHC(0x1fd5), SHC(0x8405), + SHC(0x0d61), SHC(0x80b4), SHC(0xfaa4), SHC(0x801d), SHC(0xe804), SHC(0x8244), SHC(0xd5e8), SHC(0x871f), + SHC(0xc4b3), SHC(0x8e91), SHC(0xb4c3), SHC(0x9872), SHC(0xa671), SHC(0xa48c), SHC(0x9a0b), SHC(0xb29c), + SHC(0x8fd5), SHC(0xc256), SHC(0x8807), SHC(0xd362), SHC(0x82cc), SHC(0xe563), SHC(0x8041), SHC(0xf7f6), + SHC(0x8073), SHC(0x0ab6), SHC(0x8362), SHC(0x1d3b), SHC(0x88fd), SHC(0x2f1f), SHC(0x9126), SHC(0x4000), + SHC(0x9bb0), SHC(0x4f82), SHC(0xa861), SHC(0x5d4f), SHC(0xb6f3), SHC(0x691b), SHC(0xc716), SHC(0x72a7), + SHC(0x7fff), SHC(0x0000), SHC(0x7e35), SHC(0xeaa7), SHC(0x78e1), SHC(0xd5e8), SHC(0x702b), SHC(0xc256), + SHC(0x6450), SHC(0xb07e), SHC(0x55a6), SHC(0xa0e1), SHC(0x4496), SHC(0x93ed), SHC(0x319a), SHC(0x8a00), + SHC(0x1d3b), SHC(0x8362), SHC(0x080a), SHC(0x8041), SHC(0xf29f), SHC(0x80b4), SHC(0xdd94), SHC(0x84b7), + SHC(0xc980), SHC(0x8c2f), SHC(0xb6f3), SHC(0x96e5), SHC(0xa671), SHC(0xa48c), SHC(0x9872), SHC(0xb4c3), + SHC(0x8d59), SHC(0xc716), SHC(0x8577), SHC(0xdb01), SHC(0x8102), SHC(0xeff5), SHC(0x801d), SHC(0x055c), + SHC(0x82cc), SHC(0x1a9d), SHC(0x88fd), SHC(0x2f1f), SHC(0x9283), SHC(0x424f), SHC(0x9f1b), SHC(0x53a3), + SHC(0xae69), SHC(0x62a0), SHC(0xc000), SHC(0x6eda), SHC(0xd362), SHC(0x77f9), SHC(0xe804), SHC(0x7dbc), + SHC(0xfd52), SHC(0x7ff9), SHC(0x12b3), SHC(0x7ea0), SHC(0x7fff), SHC(0x0000), SHC(0x7dbc), SHC(0xe804), + SHC(0x7703), SHC(0xd0e1), SHC(0x6c13), SHC(0xbb6a), SHC(0x5d4f), SHC(0xa861), SHC(0x4b3d), SHC(0x9872), + SHC(0x3680), SHC(0x8c2f), SHC(0x1fd5), SHC(0x8405), SHC(0x080a), SHC(0x8041), SHC(0xeff5), SHC(0x8102), + SHC(0xd872), SHC(0x8644), SHC(0xc256), SHC(0x8fd5), SHC(0xae69), SHC(0x9d60), SHC(0x9d60), SHC(0xae69), + SHC(0x8fd5), SHC(0xc256), SHC(0x8644), SHC(0xd872), SHC(0x8102), SHC(0xeff5), SHC(0x8041), SHC(0x080a), + SHC(0x8405), SHC(0x1fd5), SHC(0x8c2f), SHC(0x3680), SHC(0x9872), SHC(0x4b3d), SHC(0xa861), SHC(0x5d4f), + SHC(0xbb6a), SHC(0x6c13), SHC(0xd0e1), SHC(0x7703), SHC(0xe804), SHC(0x7dbc), SHC(0x0000), SHC(0x7fff), + SHC(0x17fc), SHC(0x7dbc), SHC(0x2f1f), SHC(0x7703), SHC(0x4496), SHC(0x6c13), SHC(0x579f), SHC(0x5d4f), + SHC(0x7fff), SHC(0x0000), SHC(0x7ffe), SHC(0xfea9), SHC(0x7ff9), SHC(0xfd52), SHC(0x7ff0), SHC(0xfbfb), + SHC(0x7fe3), SHC(0xfaa4), SHC(0x7fd3), SHC(0xf94d), SHC(0x7fbf), SHC(0xf7f6), SHC(0x7fa8), SHC(0xf6a0), + SHC(0x7f8d), SHC(0xf54a), SHC(0x7f6f), SHC(0xf3f4), SHC(0x7f4c), SHC(0xf29f), SHC(0x7f27), SHC(0xf14a), + SHC(0x7efe), SHC(0xeff5), SHC(0x7ed1), SHC(0xeea1), SHC(0x7ea0), SHC(0xed4d), SHC(0x7e6d), SHC(0xebfa), + SHC(0x7e35), SHC(0xeaa7), SHC(0x7dfa), SHC(0xe955), SHC(0x7dbc), SHC(0xe804), SHC(0x7d7a), SHC(0xe6b3), + SHC(0x7d34), SHC(0xe563), SHC(0x7ceb), SHC(0xe414), SHC(0x7c9e), SHC(0xe2c5), SHC(0x7c4e), SHC(0xe178), + SHC(0x7bfb), SHC(0xe02b), SHC(0x7ba3), SHC(0xdedf), SHC(0x7b49), SHC(0xdd94), SHC(0x7aeb), SHC(0xdc4a), + SHC(0x7a89), SHC(0xdb01), SHC(0x7a25), SHC(0xd9b9), SHC(0x7fff), SHC(0x0000), SHC(0x7ff0), SHC(0xfbfb), + SHC(0x7fbf), SHC(0xf7f6), SHC(0x7f6f), SHC(0xf3f4), SHC(0x7efe), SHC(0xeff5), SHC(0x7e6d), SHC(0xebfa), + SHC(0x7dbc), SHC(0xe804), SHC(0x7ceb), SHC(0xe414), SHC(0x7bfb), SHC(0xe02b), SHC(0x7aeb), SHC(0xdc4a), + SHC(0x79bc), SHC(0xd872), SHC(0x786f), SHC(0xd4a4), SHC(0x7703), SHC(0xd0e1), SHC(0x7579), SHC(0xcd2a), + SHC(0x73d1), SHC(0xc980), SHC(0x720d), SHC(0xc5e4), SHC(0x702b), SHC(0xc256), SHC(0x6e2d), SHC(0xbed8), + SHC(0x6c13), SHC(0xbb6a), SHC(0x69de), SHC(0xb80e), SHC(0x678e), SHC(0xb4c3), SHC(0x6524), SHC(0xb18c), + SHC(0x62a0), SHC(0xae69), SHC(0x6004), SHC(0xab5a), SHC(0x5d4f), SHC(0xa861), SHC(0x5a82), SHC(0xa57e), + SHC(0x579f), SHC(0xa2b1), SHC(0x54a6), SHC(0x9ffc), SHC(0x5197), SHC(0x9d60), SHC(0x4e74), SHC(0x9adc), + SHC(0x7fff), SHC(0x0000), SHC(0x7fd3), SHC(0xf94d), SHC(0x7f4c), SHC(0xf29f), SHC(0x7e6d), SHC(0xebfa), + SHC(0x7d34), SHC(0xe563), SHC(0x7ba3), SHC(0xdedf), SHC(0x79bc), SHC(0xd872), SHC(0x7780), SHC(0xd221), + SHC(0x74ef), SHC(0xcbf0), SHC(0x720d), SHC(0xc5e4), SHC(0x6eda), SHC(0xc000), SHC(0x6b5a), SHC(0xba49), + SHC(0x678e), SHC(0xb4c3), SHC(0x637a), SHC(0xaf72), SHC(0x5f1f), SHC(0xaa5a), SHC(0x5a82), SHC(0xa57e), + SHC(0x55a6), SHC(0xa0e1), SHC(0x508e), SHC(0x9c86), SHC(0x4b3d), SHC(0x9872), SHC(0x45b7), SHC(0x94a6), + SHC(0x4000), SHC(0x9126), SHC(0x3a1c), SHC(0x8df3), SHC(0x3410), SHC(0x8b11), SHC(0x2ddf), SHC(0x8880), + SHC(0x278e), SHC(0x8644), SHC(0x2121), SHC(0x845d), SHC(0x1a9d), SHC(0x82cc), SHC(0x1406), SHC(0x8193), + SHC(0x0d61), SHC(0x80b4), SHC(0x06b3), SHC(0x802d), SHC(0x7fff), SHC(0x0000), SHC(0x7fa8), SHC(0xf6a0), + SHC(0x7ea0), SHC(0xed4d), SHC(0x7ceb), SHC(0xe414), SHC(0x7a89), SHC(0xdb01), SHC(0x7780), SHC(0xd221), + SHC(0x73d1), SHC(0xc980), SHC(0x6f84), SHC(0xc12a), SHC(0x6a9d), SHC(0xb92a), SHC(0x6524), SHC(0xb18c), + SHC(0x5f1f), SHC(0xaa5a), SHC(0x5898), SHC(0xa39d), SHC(0x5197), SHC(0x9d60), SHC(0x4a26), SHC(0x97aa), + SHC(0x424f), SHC(0x9283), SHC(0x3a1c), SHC(0x8df3), SHC(0x319a), SHC(0x8a00), SHC(0x28d4), SHC(0x86b0), + SHC(0x1fd5), SHC(0x8405), SHC(0x16ab), SHC(0x8206), SHC(0x0d61), SHC(0x80b4), SHC(0x0405), SHC(0x8010), + SHC(0xfaa4), SHC(0x801d), SHC(0xf14a), SHC(0x80d9), SHC(0xe804), SHC(0x8244), SHC(0xdedf), SHC(0x845d), + SHC(0xd5e8), SHC(0x871f), SHC(0xcd2a), SHC(0x8a87), SHC(0xc4b3), SHC(0x8e91), SHC(0xbc8d), SHC(0x9337), + SHC(0x7fff), SHC(0x0000), SHC(0x7f6f), SHC(0xf3f4), SHC(0x7dbc), SHC(0xe804), SHC(0x7aeb), SHC(0xdc4a), + SHC(0x7703), SHC(0xd0e1), SHC(0x720d), SHC(0xc5e4), SHC(0x6c13), SHC(0xbb6a), SHC(0x6524), SHC(0xb18c), + SHC(0x5d4f), SHC(0xa861), SHC(0x54a6), SHC(0x9ffc), SHC(0x4b3d), SHC(0x9872), SHC(0x4128), SHC(0x91d3), + SHC(0x3680), SHC(0x8c2f), SHC(0x2b5c), SHC(0x8791), SHC(0x1fd5), SHC(0x8405), SHC(0x1406), SHC(0x8193), + SHC(0x080a), SHC(0x8041), SHC(0xfbfb), SHC(0x8010), SHC(0xeff5), SHC(0x8102), SHC(0xe414), SHC(0x8315), + SHC(0xd872), SHC(0x8644), SHC(0xcd2a), SHC(0x8a87), SHC(0xc256), SHC(0x8fd5), SHC(0xb80e), SHC(0x9622), + SHC(0xae69), SHC(0x9d60), SHC(0xa57e), SHC(0xa57e), SHC(0x9d60), SHC(0xae69), SHC(0x9622), SHC(0xb80e), + SHC(0x8fd5), SHC(0xc256), SHC(0x8a87), SHC(0xcd2a), SHC(0x7fff), SHC(0x0000), SHC(0x7f27), SHC(0xf14a), + SHC(0x7c9e), SHC(0xe2c5), SHC(0x786f), SHC(0xd4a4), SHC(0x72a7), SHC(0xc716), SHC(0x6b5a), SHC(0xba49), + SHC(0x62a0), SHC(0xae69), SHC(0x5898), SHC(0xa39d), SHC(0x4d64), SHC(0x9a0b), SHC(0x4128), SHC(0x91d3), + SHC(0x3410), SHC(0x8b11), SHC(0x2647), SHC(0x85db), SHC(0x17fc), SHC(0x8244), SHC(0x0960), SHC(0x8058), + SHC(0xfaa4), SHC(0x801d), SHC(0xebfa), SHC(0x8193), SHC(0xdd94), SHC(0x84b7), SHC(0xcfa3), SHC(0x897d), + SHC(0xc256), SHC(0x8fd5), SHC(0xb5da), SHC(0x97aa), SHC(0xaa5a), SHC(0xa0e1), SHC(0x9ffc), SHC(0xab5a), + SHC(0x96e5), SHC(0xb6f3), SHC(0x8f31), SHC(0xc383), SHC(0x88fd), SHC(0xd0e1), SHC(0x845d), SHC(0xdedf), + SHC(0x8160), SHC(0xed4d), SHC(0x8010), SHC(0xfbfb), SHC(0x8073), SHC(0x0ab6), SHC(0x8286), SHC(0x194d), + SHC(0x7fff), SHC(0x0000), SHC(0x7ed1), SHC(0xeea1), SHC(0x7b49), SHC(0xdd94), SHC(0x7579), SHC(0xcd2a), + SHC(0x6d7d), SHC(0xbdb1), SHC(0x637a), SHC(0xaf72), SHC(0x579f), SHC(0xa2b1), SHC(0x4a26), SHC(0x97aa), + SHC(0x3b4d), SHC(0x8e91), SHC(0x2b5c), SHC(0x8791), SHC(0x1a9d), SHC(0x82cc), SHC(0x0960), SHC(0x8058), + SHC(0xf7f6), SHC(0x8041), SHC(0xe6b3), SHC(0x8286), SHC(0xd5e8), SHC(0x871f), SHC(0xc5e4), SHC(0x8df3), + SHC(0xb6f3), SHC(0x96e5), SHC(0xa95c), SHC(0xa1c8), SHC(0x9d60), SHC(0xae69), SHC(0x9337), SHC(0xbc8d), + SHC(0x8b11), SHC(0xcbf0), SHC(0x8515), SHC(0xdc4a), SHC(0x8160), SHC(0xed4d), SHC(0x8002), SHC(0xfea9), + SHC(0x8102), SHC(0x100b), SHC(0x845d), SHC(0x2121), SHC(0x8a00), SHC(0x319a), SHC(0x91d3), SHC(0x4128), + SHC(0x9bb0), SHC(0x4f82), SHC(0xa768), SHC(0x5c63), SHC(0x7fff), SHC(0x0000), SHC(0x7e6d), SHC(0xebfa), + SHC(0x79bc), SHC(0xd872), SHC(0x720d), SHC(0xc5e4), SHC(0x678e), SHC(0xb4c3), SHC(0x5a82), SHC(0xa57e), + SHC(0x4b3d), SHC(0x9872), SHC(0x3a1c), SHC(0x8df3), SHC(0x278e), SHC(0x8644), SHC(0x1406), SHC(0x8193), + SHC(0x0000), SHC(0x8000), SHC(0xebfa), SHC(0x8193), SHC(0xd872), SHC(0x8644), SHC(0xc5e4), SHC(0x8df3), + SHC(0xb4c3), SHC(0x9872), SHC(0xa57e), SHC(0xa57e), SHC(0x9872), SHC(0xb4c3), SHC(0x8df3), SHC(0xc5e4), + SHC(0x8644), SHC(0xd872), SHC(0x8193), SHC(0xebfa), SHC(0x8000), SHC(0x0000), SHC(0x8193), SHC(0x1406), + SHC(0x8644), SHC(0x278e), SHC(0x8df3), SHC(0x3a1c), SHC(0x9872), SHC(0x4b3d), SHC(0xa57e), SHC(0x5a82), + SHC(0xb4c3), SHC(0x678e), SHC(0xc5e4), SHC(0x720d), SHC(0xd872), SHC(0x79bc), SHC(0xebfa), SHC(0x7e6d), + SHC(0x7fff), SHC(0x0000), SHC(0x7dfa), SHC(0xe955), SHC(0x77f9), SHC(0xd362), SHC(0x6e2d), SHC(0xbed8), + SHC(0x60e5), SHC(0xac5d), SHC(0x508e), SHC(0x9c86), SHC(0x3daa), SHC(0x8fd5), SHC(0x28d4), SHC(0x86b0), + SHC(0x12b3), SHC(0x8160), SHC(0xfbfb), SHC(0x8010), SHC(0xe563), SHC(0x82cc), SHC(0xcfa3), SHC(0x897d), + SHC(0xbb6a), SHC(0x93ed), SHC(0xa95c), SHC(0xa1c8), SHC(0x9a0b), SHC(0xb29c), SHC(0x8df3), SHC(0xc5e4), + SHC(0x8577), SHC(0xdb01), SHC(0x80d9), SHC(0xf14a), SHC(0x8041), SHC(0x080a), SHC(0x83b2), SHC(0x1e88), + SHC(0x8b11), SHC(0x3410), SHC(0x9622), SHC(0x47f2), SHC(0xa48c), SHC(0x598f), SHC(0xb5da), SHC(0x6856), + SHC(0xc980), SHC(0x73d1), SHC(0xdedf), SHC(0x7ba3), SHC(0xf54a), SHC(0x7f8d), SHC(0x0c0c), SHC(0x7f6f), + SHC(0x226c), SHC(0x7b49), SHC(0x37b6), SHC(0x733e), SHC(0x7fff), SHC(0x0000), SHC(0x7d7a), SHC(0xe6b3), + SHC(0x7600), SHC(0xce66), SHC(0x69de), SHC(0xb80e), SHC(0x598f), SHC(0xa48c), SHC(0x45b7), SHC(0x94a6), + SHC(0x2f1f), SHC(0x88fd), SHC(0x16ab), SHC(0x8206), SHC(0xfd52), SHC(0x8007), SHC(0xe414), SHC(0x8315), + SHC(0xcbf0), SHC(0x8b11), SHC(0xb5da), SHC(0x97aa), SHC(0xa2b1), SHC(0xa861), SHC(0x9337), SHC(0xbc8d), + SHC(0x8807), SHC(0xd362), SHC(0x8193), SHC(0xebfa), SHC(0x801d), SHC(0x055c), SHC(0x83b2), SHC(0x1e88), + SHC(0x8c2f), SHC(0x3680), SHC(0x993d), SHC(0x4c51), SHC(0xaa5a), SHC(0x5f1f), SHC(0xbed8), SHC(0x6e2d), + SHC(0xd5e8), SHC(0x78e1), SHC(0xeea1), SHC(0x7ed1), SHC(0x080a), SHC(0x7fbf), SHC(0x2121), SHC(0x7ba3), + SHC(0x38ea), SHC(0x72a7), SHC(0x4e74), SHC(0x6524), SHC(0x60e5), SHC(0x53a3), SHC(0x6f84), SHC(0x3ed6) +}; + + + +/** + * \brief Twiddle factors are unscaled + */ +const Word16 RotVector_256[2*(256-32)] = +{ + SHC(0x7fff), SHC(0x0000), SHC(0x7ff6), SHC(0xfcdc), SHC(0x7fd9), SHC(0xf9b8), SHC(0x7fa7), SHC(0xf695), + SHC(0x7f62), SHC(0xf374), SHC(0x7f0a), SHC(0xf055), SHC(0x7e9d), SHC(0xed38), SHC(0x7e1e), SHC(0xea1e), + SHC(0x7d8a), SHC(0xe707), SHC(0x7ce4), SHC(0xe3f4), SHC(0x7c2a), SHC(0xe0e6), SHC(0x7b5d), SHC(0xdddc), + SHC(0x7a7d), SHC(0xdad8), SHC(0x798a), SHC(0xd7d9), SHC(0x7885), SHC(0xd4e1), SHC(0x776c), SHC(0xd1ef), + SHC(0x7642), SHC(0xcf04), SHC(0x7505), SHC(0xcc21), SHC(0x73b6), SHC(0xc946), SHC(0x7255), SHC(0xc673), + SHC(0x70e3), SHC(0xc3a9), SHC(0x6f5f), SHC(0xc0e9), SHC(0x6dca), SHC(0xbe32), SHC(0x6c24), SHC(0xbb85), + SHC(0x6a6e), SHC(0xb8e3), SHC(0x68a7), SHC(0xb64c), SHC(0x66d0), SHC(0xb3c0), SHC(0x64e9), SHC(0xb140), + SHC(0x62f2), SHC(0xaecc), SHC(0x60ec), SHC(0xac65), SHC(0x5ed7), SHC(0xaa0a), SHC(0x5cb4), SHC(0xa7bd), + SHC(0x7fff), SHC(0x0000), SHC(0x7fd9), SHC(0xf9b8), SHC(0x7f62), SHC(0xf374), SHC(0x7e9d), SHC(0xed38), + SHC(0x7d8a), SHC(0xe707), SHC(0x7c2a), SHC(0xe0e6), SHC(0x7a7d), SHC(0xdad8), SHC(0x7885), SHC(0xd4e1), + SHC(0x7642), SHC(0xcf04), SHC(0x73b6), SHC(0xc946), SHC(0x70e3), SHC(0xc3a9), SHC(0x6dca), SHC(0xbe32), + SHC(0x6a6e), SHC(0xb8e3), SHC(0x66d0), SHC(0xb3c0), SHC(0x62f2), SHC(0xaecc), SHC(0x5ed7), SHC(0xaa0a), + SHC(0x5a82), SHC(0xa57e), SHC(0x55f6), SHC(0xa129), SHC(0x5134), SHC(0x9d0e), SHC(0x4c40), SHC(0x9930), + SHC(0x471d), SHC(0x9592), SHC(0x41ce), SHC(0x9236), SHC(0x3c57), SHC(0x8f1d), SHC(0x36ba), SHC(0x8c4a), + SHC(0x30fc), SHC(0x89be), SHC(0x2b1f), SHC(0x877b), SHC(0x2528), SHC(0x8583), SHC(0x1f1a), SHC(0x83d6), + SHC(0x18f9), SHC(0x8276), SHC(0x12c8), SHC(0x8163), SHC(0x0c8c), SHC(0x809e), SHC(0x0648), SHC(0x8027), + SHC(0x7fff), SHC(0x0000), SHC(0x7fa7), SHC(0xf695), SHC(0x7e9d), SHC(0xed38), SHC(0x7ce4), SHC(0xe3f4), + SHC(0x7a7d), SHC(0xdad8), SHC(0x776c), SHC(0xd1ef), SHC(0x73b6), SHC(0xc946), SHC(0x6f5f), SHC(0xc0e9), + SHC(0x6a6e), SHC(0xb8e3), SHC(0x64e9), SHC(0xb140), SHC(0x5ed7), SHC(0xaa0a), SHC(0x5843), SHC(0xa34c), + SHC(0x5134), SHC(0x9d0e), SHC(0x49b4), SHC(0x9759), SHC(0x41ce), SHC(0x9236), SHC(0x398d), SHC(0x8dab), + SHC(0x30fc), SHC(0x89be), SHC(0x2827), SHC(0x8676), SHC(0x1f1a), SHC(0x83d6), SHC(0x15e2), SHC(0x81e2), + SHC(0x0c8c), SHC(0x809e), SHC(0x0324), SHC(0x800a), SHC(0xf9b8), SHC(0x8027), SHC(0xf055), SHC(0x80f6), + SHC(0xe707), SHC(0x8276), SHC(0xdddc), SHC(0x84a3), SHC(0xd4e1), SHC(0x877b), SHC(0xcc21), SHC(0x8afb), + SHC(0xc3a9), SHC(0x8f1d), SHC(0xbb85), SHC(0x93dc), SHC(0xb3c0), SHC(0x9930), SHC(0xac65), SHC(0x9f14), + SHC(0x7fff), SHC(0x0000), SHC(0x7f62), SHC(0xf374), SHC(0x7d8a), SHC(0xe707), SHC(0x7a7d), SHC(0xdad8), + SHC(0x7642), SHC(0xcf04), SHC(0x70e3), SHC(0xc3a9), SHC(0x6a6e), SHC(0xb8e3), SHC(0x62f2), SHC(0xaecc), + SHC(0x5a82), SHC(0xa57e), SHC(0x5134), SHC(0x9d0e), SHC(0x471d), SHC(0x9592), SHC(0x3c57), SHC(0x8f1d), + SHC(0x30fc), SHC(0x89be), SHC(0x2528), SHC(0x8583), SHC(0x18f9), SHC(0x8276), SHC(0x0c8c), SHC(0x809e), + SHC(0x0000), SHC(0x8000), SHC(0xf374), SHC(0x809e), SHC(0xe707), SHC(0x8276), SHC(0xdad8), SHC(0x8583), + SHC(0xcf04), SHC(0x89be), SHC(0xc3a9), SHC(0x8f1d), SHC(0xb8e3), SHC(0x9592), SHC(0xaecc), SHC(0x9d0e), + SHC(0xa57e), SHC(0xa57e), SHC(0x9d0e), SHC(0xaecc), SHC(0x9592), SHC(0xb8e3), SHC(0x8f1d), SHC(0xc3a9), + SHC(0x89be), SHC(0xcf04), SHC(0x8583), SHC(0xdad8), SHC(0x8276), SHC(0xe707), SHC(0x809e), SHC(0xf374), + SHC(0x7fff), SHC(0x0000), SHC(0x7f0a), SHC(0xf055), SHC(0x7c2a), SHC(0xe0e6), SHC(0x776c), SHC(0xd1ef), + SHC(0x70e3), SHC(0xc3a9), SHC(0x68a7), SHC(0xb64c), SHC(0x5ed7), SHC(0xaa0a), SHC(0x539b), SHC(0x9f14), + SHC(0x471d), SHC(0x9592), SHC(0x398d), SHC(0x8dab), SHC(0x2b1f), SHC(0x877b), SHC(0x1c0c), SHC(0x831c), + SHC(0x0c8c), SHC(0x809e), SHC(0xfcdc), SHC(0x800a), SHC(0xed38), SHC(0x8163), SHC(0xdddc), SHC(0x84a3), + SHC(0xcf04), SHC(0x89be), SHC(0xc0e9), SHC(0x90a1), SHC(0xb3c0), SHC(0x9930), SHC(0xa7bd), SHC(0xa34c), + SHC(0x9d0e), SHC(0xaecc), SHC(0x93dc), SHC(0xbb85), SHC(0x8c4a), SHC(0xc946), SHC(0x8676), SHC(0xd7d9), + SHC(0x8276), SHC(0xe707), SHC(0x8059), SHC(0xf695), SHC(0x8027), SHC(0x0648), SHC(0x81e2), SHC(0x15e2), + SHC(0x8583), SHC(0x2528), SHC(0x8afb), SHC(0x33df), SHC(0x9236), SHC(0x41ce), SHC(0x9b17), SHC(0x4ec0), + SHC(0x7fff), SHC(0x0000), SHC(0x7e9d), SHC(0xed38), SHC(0x7a7d), SHC(0xdad8), SHC(0x73b6), SHC(0xc946), + SHC(0x6a6e), SHC(0xb8e3), SHC(0x5ed7), SHC(0xaa0a), SHC(0x5134), SHC(0x9d0e), SHC(0x41ce), SHC(0x9236), + SHC(0x30fc), SHC(0x89be), SHC(0x1f1a), SHC(0x83d6), SHC(0x0c8c), SHC(0x809e), SHC(0xf9b8), SHC(0x8027), + SHC(0xe707), SHC(0x8276), SHC(0xd4e1), SHC(0x877b), SHC(0xc3a9), SHC(0x8f1d), SHC(0xb3c0), SHC(0x9930), + SHC(0xa57e), SHC(0xa57e), SHC(0x9930), SHC(0xb3c0), SHC(0x8f1d), SHC(0xc3a9), SHC(0x877b), SHC(0xd4e1), + SHC(0x8276), SHC(0xe707), SHC(0x8027), SHC(0xf9b8), SHC(0x809e), SHC(0x0c8c), SHC(0x83d6), SHC(0x1f1a), + SHC(0x89be), SHC(0x30fc), SHC(0x9236), SHC(0x41ce), SHC(0x9d0e), SHC(0x5134), SHC(0xaa0a), SHC(0x5ed7), + SHC(0xb8e3), SHC(0x6a6e), SHC(0xc946), SHC(0x73b6), SHC(0xdad8), SHC(0x7a7d), SHC(0xed38), SHC(0x7e9d), + SHC(0x7fff), SHC(0x0000), SHC(0x7e1e), SHC(0xea1e), SHC(0x7885), SHC(0xd4e1), SHC(0x6f5f), SHC(0xc0e9), + SHC(0x62f2), SHC(0xaecc), SHC(0x539b), SHC(0x9f14), SHC(0x41ce), SHC(0x9236), SHC(0x2e11), SHC(0x8894), + SHC(0x18f9), SHC(0x8276), SHC(0x0324), SHC(0x800a), SHC(0xed38), SHC(0x8163), SHC(0xd7d9), SHC(0x8676), + SHC(0xc3a9), SHC(0x8f1d), SHC(0xb140), SHC(0x9b17), SHC(0xa129), SHC(0xaa0a), SHC(0x93dc), SHC(0xbb85), + SHC(0x89be), SHC(0xcf04), SHC(0x831c), SHC(0xe3f4), SHC(0x8027), SHC(0xf9b8), SHC(0x80f6), SHC(0x0fab), + SHC(0x8583), SHC(0x2528), SHC(0x8dab), SHC(0x398d), SHC(0x9930), SHC(0x4c40), SHC(0xa7bd), SHC(0x5cb4), + SHC(0xb8e3), SHC(0x6a6e), SHC(0xcc21), SHC(0x7505), SHC(0xe0e6), SHC(0x7c2a), SHC(0xf695), SHC(0x7fa7), + SHC(0x0c8c), SHC(0x7f62), SHC(0x2224), SHC(0x7b5d), SHC(0x36ba), SHC(0x73b6), SHC(0x49b4), SHC(0x68a7) +}; + +/** + * \brief Twiddle factors are unscaled + */ +const Word16 RotVector_320[2*(320-20)] = +{ + SHC(0x7fff), SHC(0x0000), SHC(0x7fe7), SHC(0xfafa), SHC(0x7f9b), SHC(0xf5f5), SHC(0x7f1d), SHC(0xf0f5), + SHC(0x7e6d), SHC(0xebfa), SHC(0x7d8a), SHC(0xe707), SHC(0x7c77), SHC(0xe21e), SHC(0x7b32), SHC(0xdd41), + SHC(0x79bc), SHC(0xd872), SHC(0x7817), SHC(0xd3b2), SHC(0x7642), SHC(0xcf04), SHC(0x743e), SHC(0xca69), + SHC(0x720d), SHC(0xc5e4), SHC(0x6fae), SHC(0xc175), SHC(0x6d23), SHC(0xbd1f), SHC(0x6a6e), SHC(0xb8e3), + SHC(0x678e), SHC(0xb4c3), SHC(0x6485), SHC(0xb0c2), SHC(0x6155), SHC(0xacdf), SHC(0x5dfe), SHC(0xa91d), + SHC(0x7fff), SHC(0x0000), SHC(0x7f9b), SHC(0xf5f5), SHC(0x7e6d), SHC(0xebfa), SHC(0x7c77), SHC(0xe21e), + SHC(0x79bc), SHC(0xd872), SHC(0x7642), SHC(0xcf04), SHC(0x720d), SHC(0xc5e4), SHC(0x6d23), SHC(0xbd1f), + SHC(0x678e), SHC(0xb4c3), SHC(0x6155), SHC(0xacdf), SHC(0x5a82), SHC(0xa57e), SHC(0x5321), SHC(0x9eab), + SHC(0x4b3d), SHC(0x9872), SHC(0x42e1), SHC(0x92dd), SHC(0x3a1c), SHC(0x8df3), SHC(0x30fc), SHC(0x89be), + SHC(0x278e), SHC(0x8644), SHC(0x1de2), SHC(0x8389), SHC(0x1406), SHC(0x8193), SHC(0x0a0b), SHC(0x8065), + SHC(0x7fff), SHC(0x0000), SHC(0x7f1d), SHC(0xf0f5), SHC(0x7c77), SHC(0xe21e), SHC(0x7817), SHC(0xd3b2), + SHC(0x720d), SHC(0xc5e4), SHC(0x6a6e), SHC(0xb8e3), SHC(0x6155), SHC(0xacdf), SHC(0x56e3), SHC(0xa202), + SHC(0x4b3d), SHC(0x9872), SHC(0x3e8b), SHC(0x9052), SHC(0x30fc), SHC(0x89be), SHC(0x22bf), SHC(0x84ce), + SHC(0x1406), SHC(0x8193), SHC(0x0506), SHC(0x8019), SHC(0xf5f5), SHC(0x8065), SHC(0xe707), SHC(0x8276), + SHC(0xd872), SHC(0x8644), SHC(0xca69), SHC(0x8bc2), SHC(0xbd1f), SHC(0x92dd), SHC(0xb0c2), SHC(0x9b7b), + SHC(0x7fff), SHC(0x0000), SHC(0x7e6d), SHC(0xebfa), SHC(0x79bc), SHC(0xd872), SHC(0x720d), SHC(0xc5e4), + SHC(0x678e), SHC(0xb4c3), SHC(0x5a82), SHC(0xa57e), SHC(0x4b3d), SHC(0x9872), SHC(0x3a1c), SHC(0x8df3), + SHC(0x278e), SHC(0x8644), SHC(0x1406), SHC(0x8193), SHC(0x0000), SHC(0x8000), SHC(0xebfa), SHC(0x8193), + SHC(0xd872), SHC(0x8644), SHC(0xc5e4), SHC(0x8df3), SHC(0xb4c3), SHC(0x9872), SHC(0xa57e), SHC(0xa57e), + SHC(0x9872), SHC(0xb4c3), SHC(0x8df3), SHC(0xc5e4), SHC(0x8644), SHC(0xd872), SHC(0x8193), SHC(0xebfa), + SHC(0x7fff), SHC(0x0000), SHC(0x7d8a), SHC(0xe707), SHC(0x7642), SHC(0xcf04), SHC(0x6a6e), SHC(0xb8e3), + SHC(0x5a82), SHC(0xa57e), SHC(0x471d), SHC(0x9592), SHC(0x30fc), SHC(0x89be), SHC(0x18f9), SHC(0x8276), + SHC(0x0000), SHC(0x8000), SHC(0xe707), SHC(0x8276), SHC(0xcf04), SHC(0x89be), SHC(0xb8e3), SHC(0x9592), + SHC(0xa57e), SHC(0xa57e), SHC(0x9592), SHC(0xb8e3), SHC(0x89be), SHC(0xcf04), SHC(0x8276), SHC(0xe707), + SHC(0x8000), SHC(0x0000), SHC(0x8276), SHC(0x18f9), SHC(0x89be), SHC(0x30fc), SHC(0x9592), SHC(0x471d), + SHC(0x7fff), SHC(0x0000), SHC(0x7c77), SHC(0xe21e), SHC(0x720d), SHC(0xc5e4), SHC(0x6155), SHC(0xacdf), + SHC(0x4b3d), SHC(0x9872), SHC(0x30fc), SHC(0x89be), SHC(0x1406), SHC(0x8193), SHC(0xf5f5), SHC(0x8065), + SHC(0xd872), SHC(0x8644), SHC(0xbd1f), SHC(0x92dd), SHC(0xa57e), SHC(0xa57e), SHC(0x92dd), SHC(0xbd1f), + SHC(0x8644), SHC(0xd872), SHC(0x8065), SHC(0xf5f5), SHC(0x8193), SHC(0x1406), SHC(0x89be), SHC(0x30fc), + SHC(0x9872), SHC(0x4b3d), SHC(0xacdf), SHC(0x6155), SHC(0xc5e4), SHC(0x720d), SHC(0xe21e), SHC(0x7c77), + SHC(0x7fff), SHC(0x0000), SHC(0x7b32), SHC(0xdd41), SHC(0x6d23), SHC(0xbd1f), SHC(0x56e3), SHC(0xa202), + SHC(0x3a1c), SHC(0x8df3), SHC(0x18f9), SHC(0x8276), SHC(0xf5f5), SHC(0x8065), SHC(0xd3b2), SHC(0x87e9), + SHC(0xb4c3), SHC(0x9872), SHC(0x9b7b), SHC(0xb0c2), SHC(0x89be), SHC(0xcf04), SHC(0x80e3), SHC(0xf0f5), + SHC(0x8193), SHC(0x1406), SHC(0x8bc2), SHC(0x3597), SHC(0x9eab), SHC(0x5321), SHC(0xb8e3), SHC(0x6a6e), + SHC(0xd872), SHC(0x79bc), SHC(0xfafa), SHC(0x7fe7), SHC(0x1de2), SHC(0x7c77), SHC(0x3e8b), SHC(0x6fae), + SHC(0x7fff), SHC(0x0000), SHC(0x7ffa), SHC(0xfd7d), SHC(0x7fe7), SHC(0xfafa), SHC(0x7fc7), SHC(0xf877), + SHC(0x7f9b), SHC(0xf5f5), SHC(0x7f62), SHC(0xf374), SHC(0x7f1d), SHC(0xf0f5), SHC(0x7ecb), SHC(0xee76), + SHC(0x7e6d), SHC(0xebfa), SHC(0x7e02), SHC(0xe980), SHC(0x7d8a), SHC(0xe707), SHC(0x7d07), SHC(0xe492), + SHC(0x7c77), SHC(0xe21e), SHC(0x7bda), SHC(0xdfae), SHC(0x7b32), SHC(0xdd41), SHC(0x7a7d), SHC(0xdad8), + SHC(0x79bc), SHC(0xd872), SHC(0x78ef), SHC(0xd610), SHC(0x7817), SHC(0xd3b2), SHC(0x7732), SHC(0xd159), + SHC(0x7fff), SHC(0x0000), SHC(0x7fc7), SHC(0xf877), SHC(0x7f1d), SHC(0xf0f5), SHC(0x7e02), SHC(0xe980), + SHC(0x7c77), SHC(0xe21e), SHC(0x7a7d), SHC(0xdad8), SHC(0x7817), SHC(0xd3b2), SHC(0x7546), SHC(0xccb4), + SHC(0x720d), SHC(0xc5e4), SHC(0x6e6e), SHC(0xbf47), SHC(0x6a6e), SHC(0xb8e3), SHC(0x660f), SHC(0xb2bf), + SHC(0x6155), SHC(0xacdf), SHC(0x5c45), SHC(0xa749), SHC(0x56e3), SHC(0xa202), SHC(0x5134), SHC(0x9d0e), + SHC(0x4b3d), SHC(0x9872), SHC(0x4502), SHC(0x9432), SHC(0x3e8b), SHC(0x9052), SHC(0x37dc), SHC(0x8cd5), + SHC(0x7fff), SHC(0x0000), SHC(0x7f62), SHC(0xf374), SHC(0x7d8a), SHC(0xe707), SHC(0x7a7d), SHC(0xdad8), + SHC(0x7642), SHC(0xcf04), SHC(0x70e3), SHC(0xc3a9), SHC(0x6a6e), SHC(0xb8e3), SHC(0x62f2), SHC(0xaecc), + SHC(0x5a82), SHC(0xa57e), SHC(0x5134), SHC(0x9d0e), SHC(0x471d), SHC(0x9592), SHC(0x3c57), SHC(0x8f1d), + SHC(0x30fc), SHC(0x89be), SHC(0x2528), SHC(0x8583), SHC(0x18f9), SHC(0x8276), SHC(0x0c8c), SHC(0x809e), + SHC(0x0000), SHC(0x8000), SHC(0xf374), SHC(0x809e), SHC(0xe707), SHC(0x8276), SHC(0xdad8), SHC(0x8583), + SHC(0x7fff), SHC(0x0000), SHC(0x7ecb), SHC(0xee76), SHC(0x7b32), SHC(0xdd41), SHC(0x7546), SHC(0xccb4), + SHC(0x6d23), SHC(0xbd1f), SHC(0x62f2), SHC(0xaecc), SHC(0x56e3), SHC(0xa202), SHC(0x4930), SHC(0x96fd), + SHC(0x3a1c), SHC(0x8df3), SHC(0x29f0), SHC(0x8711), SHC(0x18f9), SHC(0x8276), SHC(0x0789), SHC(0x8039), + SHC(0xf5f5), SHC(0x8065), SHC(0xe492), SHC(0x82f9), SHC(0xd3b2), SHC(0x87e9), SHC(0xc3a9), SHC(0x8f1d), + SHC(0xb4c3), SHC(0x9872), SHC(0xa749), SHC(0xa3bb), SHC(0x9b7b), SHC(0xb0c2), SHC(0x9192), SHC(0xbf47), + SHC(0x7fff), SHC(0x0000), SHC(0x7e02), SHC(0xe980), SHC(0x7817), SHC(0xd3b2), SHC(0x6e6e), SHC(0xbf47), + SHC(0x6155), SHC(0xacdf), SHC(0x5134), SHC(0x9d0e), SHC(0x3e8b), SHC(0x9052), SHC(0x29f0), SHC(0x8711), + SHC(0x1406), SHC(0x8193), SHC(0xfd7d), SHC(0x8006), SHC(0xe707), SHC(0x8276), SHC(0xd159), SHC(0x88ce), + SHC(0xbd1f), SHC(0x92dd), SHC(0xaafa), SHC(0xa052), SHC(0x9b7b), SHC(0xb0c2), SHC(0x8f1d), SHC(0xc3a9), + SHC(0x8644), SHC(0xd872), SHC(0x8135), SHC(0xee76), SHC(0x8019), SHC(0x0506), SHC(0x82f9), SHC(0x1b6e), + SHC(0x7fff), SHC(0x0000), SHC(0x7d07), SHC(0xe492), SHC(0x743e), SHC(0xca69), SHC(0x660f), SHC(0xb2bf), + SHC(0x5321), SHC(0x9eab), SHC(0x3c57), SHC(0x8f1d), SHC(0x22bf), SHC(0x84ce), SHC(0x0789), SHC(0x8039), + SHC(0xebfa), SHC(0x8193), SHC(0xd159), SHC(0x88ce), SHC(0xb8e3), SHC(0x9592), SHC(0xa3bb), SHC(0xa749), + SHC(0x92dd), SHC(0xbd1f), SHC(0x8711), SHC(0xd610), SHC(0x80e3), SHC(0xf0f5), SHC(0x809e), SHC(0x0c8c), + SHC(0x8644), SHC(0x278e), SHC(0x9192), SHC(0x40b9), SHC(0xa202), SHC(0x56e3), SHC(0xb6d0), SHC(0x6903), + SHC(0x7fff), SHC(0x0000), SHC(0x7bda), SHC(0xdfae), SHC(0x6fae), SHC(0xc175), SHC(0x5c45), SHC(0xa749), + SHC(0x42e1), SHC(0x92dd), SHC(0x2528), SHC(0x8583), SHC(0x0506), SHC(0x8019), SHC(0xe492), SHC(0x82f9), + SHC(0xc5e4), SHC(0x8df3), SHC(0xaafa), SHC(0xa052), SHC(0x9592), SHC(0xb8e3), SHC(0x8711), SHC(0xd610), + SHC(0x8065), SHC(0xf5f5), SHC(0x81fe), SHC(0x1680), SHC(0x8bc2), SHC(0x3597), SHC(0x9d0e), SHC(0x5134), + SHC(0xb4c3), SHC(0x678e), SHC(0xd159), SHC(0x7732), SHC(0xf0f5), SHC(0x7f1d), SHC(0x118a), SHC(0x7ecb), + SHC(0x7fff), SHC(0x0000), SHC(0x7a7d), SHC(0xdad8), SHC(0x6a6e), SHC(0xb8e3), SHC(0x5134), SHC(0x9d0e), + SHC(0x30fc), SHC(0x89be), SHC(0x0c8c), SHC(0x809e), SHC(0xe707), SHC(0x8276), SHC(0xc3a9), SHC(0x8f1d), + SHC(0xa57e), SHC(0xa57e), SHC(0x8f1d), SHC(0xc3a9), SHC(0x8276), SHC(0xe707), SHC(0x809e), SHC(0x0c8c), + SHC(0x89be), SHC(0x30fc), SHC(0x9d0e), SHC(0x5134), SHC(0xb8e3), SHC(0x6a6e), SHC(0xdad8), SHC(0x7a7d), + SHC(0x0000), SHC(0x7fff), SHC(0x2528), SHC(0x7a7d), SHC(0x471d), SHC(0x6a6e), SHC(0x62f2), SHC(0x5134) +}; + + +/** + * \brief Twiddle factors are unscaled + * Rotation factor table, real and imaginary part interleaved, for dim1=20,dim2=20 + */ + +const Word16 RotVector_400[2*(400-20)] = +{ + SHC(0x7fff), SHC(0x0000), SHC(0x7ff0), SHC(0xfbfb), SHC(0x7fbf), SHC(0xf7f6), SHC(0x7f6f), SHC(0xf3f4), + SHC(0x7efe), SHC(0xeff5), SHC(0x7e6d), SHC(0xebfa), SHC(0x7dbc), SHC(0xe804), SHC(0x7ceb), SHC(0xe414), + SHC(0x7bfb), SHC(0xe02b), SHC(0x7aeb), SHC(0xdc4a), SHC(0x79bc), SHC(0xd872), SHC(0x786f), SHC(0xd4a4), + SHC(0x7703), SHC(0xd0e1), SHC(0x7579), SHC(0xcd2a), SHC(0x73d1), SHC(0xc980), SHC(0x720d), SHC(0xc5e4), + SHC(0x702b), SHC(0xc256), SHC(0x6e2d), SHC(0xbed8), SHC(0x6c13), SHC(0xbb6a), SHC(0x69de), SHC(0xb80e), + SHC(0x7fff), SHC(0x0000), SHC(0x7fbf), SHC(0xf7f6), SHC(0x7efe), SHC(0xeff5), SHC(0x7dbc), SHC(0xe804), + SHC(0x7bfb), SHC(0xe02b), SHC(0x79bc), SHC(0xd872), SHC(0x7703), SHC(0xd0e1), SHC(0x73d1), SHC(0xc980), + SHC(0x702b), SHC(0xc256), SHC(0x6c13), SHC(0xbb6a), SHC(0x678e), SHC(0xb4c3), SHC(0x62a0), SHC(0xae69), + SHC(0x5d4f), SHC(0xa861), SHC(0x579f), SHC(0xa2b1), SHC(0x5197), SHC(0x9d60), SHC(0x4b3d), SHC(0x9872), + SHC(0x4496), SHC(0x93ed), SHC(0x3daa), SHC(0x8fd5), SHC(0x3680), SHC(0x8c2f), SHC(0x2f1f), SHC(0x88fd), + SHC(0x7fff), SHC(0x0000), SHC(0x7f6f), SHC(0xf3f4), SHC(0x7dbc), SHC(0xe804), SHC(0x7aeb), SHC(0xdc4a), + SHC(0x7703), SHC(0xd0e1), SHC(0x720d), SHC(0xc5e4), SHC(0x6c13), SHC(0xbb6a), SHC(0x6524), SHC(0xb18c), + SHC(0x5d4f), SHC(0xa861), SHC(0x54a6), SHC(0x9ffc), SHC(0x4b3d), SHC(0x9872), SHC(0x4128), SHC(0x91d3), + SHC(0x3680), SHC(0x8c2f), SHC(0x2b5c), SHC(0x8791), SHC(0x1fd5), SHC(0x8405), SHC(0x1406), SHC(0x8193), + SHC(0x080a), SHC(0x8041), SHC(0xfbfb), SHC(0x8010), SHC(0xeff5), SHC(0x8102), SHC(0xe414), SHC(0x8315), + SHC(0x7fff), SHC(0x0000), SHC(0x7efe), SHC(0xeff5), SHC(0x7bfb), SHC(0xe02b), SHC(0x7703), SHC(0xd0e1), + SHC(0x702b), SHC(0xc256), SHC(0x678e), SHC(0xb4c3), SHC(0x5d4f), SHC(0xa861), SHC(0x5197), SHC(0x9d60), + SHC(0x4496), SHC(0x93ed), SHC(0x3680), SHC(0x8c2f), SHC(0x278e), SHC(0x8644), SHC(0x17fc), SHC(0x8244), + SHC(0x080a), SHC(0x8041), SHC(0xf7f6), SHC(0x8041), SHC(0xe804), SHC(0x8244), SHC(0xd872), SHC(0x8644), + SHC(0xc980), SHC(0x8c2f), SHC(0xbb6a), SHC(0x93ed), SHC(0xae69), SHC(0x9d60), SHC(0xa2b1), SHC(0xa861), + SHC(0x7fff), SHC(0x0000), SHC(0x7e6d), SHC(0xebfa), SHC(0x79bc), SHC(0xd872), SHC(0x720d), SHC(0xc5e4), + SHC(0x678e), SHC(0xb4c3), SHC(0x5a82), SHC(0xa57e), SHC(0x4b3d), SHC(0x9872), SHC(0x3a1c), SHC(0x8df3), + SHC(0x278e), SHC(0x8644), SHC(0x1406), SHC(0x8193), SHC(0x0000), SHC(0x8000), SHC(0xebfa), SHC(0x8193), + SHC(0xd872), SHC(0x8644), SHC(0xc5e4), SHC(0x8df3), SHC(0xb4c3), SHC(0x9872), SHC(0xa57e), SHC(0xa57e), + SHC(0x9872), SHC(0xb4c3), SHC(0x8df3), SHC(0xc5e4), SHC(0x8644), SHC(0xd872), SHC(0x8193), SHC(0xebfa), + SHC(0x7fff), SHC(0x0000), SHC(0x7dbc), SHC(0xe804), SHC(0x7703), SHC(0xd0e1), SHC(0x6c13), SHC(0xbb6a), + SHC(0x5d4f), SHC(0xa861), SHC(0x4b3d), SHC(0x9872), SHC(0x3680), SHC(0x8c2f), SHC(0x1fd5), SHC(0x8405), + SHC(0x080a), SHC(0x8041), SHC(0xeff5), SHC(0x8102), SHC(0xd872), SHC(0x8644), SHC(0xc256), SHC(0x8fd5), + SHC(0xae69), SHC(0x9d60), SHC(0x9d60), SHC(0xae69), SHC(0x8fd5), SHC(0xc256), SHC(0x8644), SHC(0xd872), + SHC(0x8102), SHC(0xeff5), SHC(0x8041), SHC(0x080a), SHC(0x8405), SHC(0x1fd5), SHC(0x8c2f), SHC(0x3680), + SHC(0x7fff), SHC(0x0000), SHC(0x7ceb), SHC(0xe414), SHC(0x73d1), SHC(0xc980), SHC(0x6524), SHC(0xb18c), + SHC(0x5197), SHC(0x9d60), SHC(0x3a1c), SHC(0x8df3), SHC(0x1fd5), SHC(0x8405), SHC(0x0405), SHC(0x8010), + SHC(0xe804), SHC(0x8244), SHC(0xcd2a), SHC(0x8a87), SHC(0xb4c3), SHC(0x9872), SHC(0x9ffc), SHC(0xab5a), + SHC(0x8fd5), SHC(0xc256), SHC(0x8515), SHC(0xdc4a), SHC(0x8041), SHC(0xf7f6), SHC(0x8193), SHC(0x1406), + SHC(0x88fd), SHC(0x2f1f), SHC(0x9622), SHC(0x47f2), SHC(0xa861), SHC(0x5d4f), SHC(0xbed8), SHC(0x6e2d), + SHC(0x7fff), SHC(0x0000), SHC(0x7bfb), SHC(0xe02b), SHC(0x702b), SHC(0xc256), SHC(0x5d4f), SHC(0xa861), + SHC(0x4496), SHC(0x93ed), SHC(0x278e), SHC(0x8644), SHC(0x080a), SHC(0x8041), SHC(0xe804), SHC(0x8244), + SHC(0xc980), SHC(0x8c2f), SHC(0xae69), SHC(0x9d60), SHC(0x9872), SHC(0xb4c3), SHC(0x88fd), SHC(0xd0e1), + SHC(0x8102), SHC(0xeff5), SHC(0x8102), SHC(0x100b), SHC(0x88fd), SHC(0x2f1f), SHC(0x9872), SHC(0x4b3d), + SHC(0xae69), SHC(0x62a0), SHC(0xc980), SHC(0x73d1), SHC(0xe804), SHC(0x7dbc), SHC(0x080a), SHC(0x7fbf), + SHC(0x7fff), SHC(0x0000), SHC(0x7aeb), SHC(0xdc4a), SHC(0x6c13), SHC(0xbb6a), SHC(0x54a6), SHC(0x9ffc), + SHC(0x3680), SHC(0x8c2f), SHC(0x1406), SHC(0x8193), SHC(0xeff5), SHC(0x8102), SHC(0xcd2a), SHC(0x8a87), + SHC(0xae69), SHC(0x9d60), SHC(0x9622), SHC(0xb80e), SHC(0x8644), SHC(0xd872), SHC(0x8010), SHC(0xfbfb), + SHC(0x8405), SHC(0x1fd5), SHC(0x91d3), SHC(0x4128), SHC(0xa861), SHC(0x5d4f), SHC(0xc5e4), SHC(0x720d), + SHC(0xe804), SHC(0x7dbc), SHC(0x0c0c), SHC(0x7f6f), SHC(0x2f1f), SHC(0x7703), SHC(0x4e74), SHC(0x6524), + SHC(0x7fff), SHC(0x0000), SHC(0x7ffc), SHC(0xfdfd), SHC(0x7ff0), SHC(0xfbfb), SHC(0x7fdc), SHC(0xf9f8), + SHC(0x7fbf), SHC(0xf7f6), SHC(0x7f9b), SHC(0xf5f5), SHC(0x7f6f), SHC(0xf3f4), SHC(0x7f3a), SHC(0xf1f4), + SHC(0x7efe), SHC(0xeff5), SHC(0x7eb9), SHC(0xedf7), SHC(0x7e6d), SHC(0xebfa), SHC(0x7e18), SHC(0xe9fe), + SHC(0x7dbc), SHC(0xe804), SHC(0x7d57), SHC(0xe60b), SHC(0x7ceb), SHC(0xe414), SHC(0x7c77), SHC(0xe21e), + SHC(0x7bfb), SHC(0xe02b), SHC(0x7b77), SHC(0xde39), SHC(0x7aeb), SHC(0xdc4a), SHC(0x7a57), SHC(0xda5d), + SHC(0x7fff), SHC(0x0000), SHC(0x7fdc), SHC(0xf9f8), SHC(0x7f6f), SHC(0xf3f4), SHC(0x7eb9), SHC(0xedf7), + SHC(0x7dbc), SHC(0xe804), SHC(0x7c77), SHC(0xe21e), SHC(0x7aeb), SHC(0xdc4a), SHC(0x7919), SHC(0xd68a), + SHC(0x7703), SHC(0xd0e1), SHC(0x74a9), SHC(0xcb53), SHC(0x720d), SHC(0xc5e4), SHC(0x6f2f), SHC(0xc095), + SHC(0x6c13), SHC(0xbb6a), SHC(0x68b9), SHC(0xb666), SHC(0x6524), SHC(0xb18c), SHC(0x6155), SHC(0xacdf), + SHC(0x5d4f), SHC(0xa861), SHC(0x5914), SHC(0xa414), SHC(0x54a6), SHC(0x9ffc), SHC(0x5008), SHC(0x9c1b), + SHC(0x7fff), SHC(0x0000), SHC(0x7f9b), SHC(0xf5f5), SHC(0x7e6d), SHC(0xebfa), SHC(0x7c77), SHC(0xe21e), + SHC(0x79bc), SHC(0xd872), SHC(0x7642), SHC(0xcf04), SHC(0x720d), SHC(0xc5e4), SHC(0x6d23), SHC(0xbd1f), + SHC(0x678e), SHC(0xb4c3), SHC(0x6155), SHC(0xacdf), SHC(0x5a82), SHC(0xa57e), SHC(0x5321), SHC(0x9eab), + SHC(0x4b3d), SHC(0x9872), SHC(0x42e1), SHC(0x92dd), SHC(0x3a1c), SHC(0x8df3), SHC(0x30fc), SHC(0x89be), + SHC(0x278e), SHC(0x8644), SHC(0x1de2), SHC(0x8389), SHC(0x1406), SHC(0x8193), SHC(0x0a0b), SHC(0x8065), + SHC(0x7fff), SHC(0x0000), SHC(0x7f3a), SHC(0xf1f4), SHC(0x7ceb), SHC(0xe414), SHC(0x7919), SHC(0xd68a), + SHC(0x73d1), SHC(0xc980), SHC(0x6d23), SHC(0xbd1f), SHC(0x6524), SHC(0xb18c), SHC(0x5bec), SHC(0xa6ec), + SHC(0x5197), SHC(0x9d60), SHC(0x4646), SHC(0x9504), SHC(0x3a1c), SHC(0x8df3), SHC(0x2d3f), SHC(0x8843), + SHC(0x1fd5), SHC(0x8405), SHC(0x1209), SHC(0x8147), SHC(0x0405), SHC(0x8010), SHC(0xf5f5), SHC(0x8065), + SHC(0xe804), SHC(0x8244), SHC(0xda5d), SHC(0x85a9), SHC(0xcd2a), SHC(0x8a87), SHC(0xc095), SHC(0x90d1), + SHC(0x7fff), SHC(0x0000), SHC(0x7eb9), SHC(0xedf7), SHC(0x7aeb), SHC(0xdc4a), SHC(0x74a9), SHC(0xcb53), + SHC(0x6c13), SHC(0xbb6a), SHC(0x6155), SHC(0xacdf), SHC(0x54a6), SHC(0x9ffc), SHC(0x4646), SHC(0x9504), + SHC(0x3680), SHC(0x8c2f), SHC(0x25a3), SHC(0x85a9), SHC(0x1406), SHC(0x8193), SHC(0x0203), SHC(0x8004), + SHC(0xeff5), SHC(0x8102), SHC(0xde39), SHC(0x8489), SHC(0xcd2a), SHC(0x8a87), SHC(0xbd1f), SHC(0x92dd), + SHC(0xae69), SHC(0x9d60), SHC(0xa154), SHC(0xa9db), SHC(0x9622), SHC(0xb80e), SHC(0x8d0d), SHC(0xc7b0), + SHC(0x7fff), SHC(0x0000), SHC(0x7e18), SHC(0xe9fe), SHC(0x786f), SHC(0xd4a4), SHC(0x6f2f), SHC(0xc095), + SHC(0x62a0), SHC(0xae69), SHC(0x5321), SHC(0x9eab), SHC(0x4128), SHC(0x91d3), SHC(0x2d3f), SHC(0x8843), + SHC(0x17fc), SHC(0x8244), SHC(0x0203), SHC(0x8004), SHC(0xebfa), SHC(0x8193), SHC(0xd68a), SHC(0x86e7), + SHC(0xc256), SHC(0x8fd5), SHC(0xaff8), SHC(0x9c1b), SHC(0x9ffc), SHC(0xab5a), SHC(0x92dd), SHC(0xbd1f), + SHC(0x88fd), SHC(0xd0e1), SHC(0x82a9), SHC(0xe60b), SHC(0x8010), SHC(0xfbfb), SHC(0x8147), SHC(0x1209), + SHC(0x7fff), SHC(0x0000), SHC(0x7d57), SHC(0xe60b), SHC(0x7579), SHC(0xcd2a), SHC(0x68b9), SHC(0xb666), + SHC(0x579f), SHC(0xa2b1), SHC(0x42e1), SHC(0x92dd), SHC(0x2b5c), SHC(0x8791), SHC(0x1209), SHC(0x8147), + SHC(0xf7f6), SHC(0x8041), SHC(0xde39), SHC(0x8489), SHC(0xc5e4), SHC(0x8df3), SHC(0xaff8), SHC(0x9c1b), + SHC(0x9d60), SHC(0xae69), SHC(0x8ee1), SHC(0xc41b), SHC(0x8515), SHC(0xdc4a), SHC(0x8065), SHC(0xf5f5), + SHC(0x8102), SHC(0x100b), SHC(0x86e7), SHC(0x2976), SHC(0x91d3), SHC(0x4128), SHC(0xa154), SHC(0x5625), + SHC(0x7fff), SHC(0x0000), SHC(0x7c77), SHC(0xe21e), SHC(0x720d), SHC(0xc5e4), SHC(0x6155), SHC(0xacdf), + SHC(0x4b3d), SHC(0x9872), SHC(0x30fc), SHC(0x89be), SHC(0x1406), SHC(0x8193), SHC(0xf5f5), SHC(0x8065), + SHC(0xd872), SHC(0x8644), SHC(0xbd1f), SHC(0x92dd), SHC(0xa57e), SHC(0xa57e), SHC(0x92dd), SHC(0xbd1f), + SHC(0x8644), SHC(0xd872), SHC(0x8065), SHC(0xf5f5), SHC(0x8193), SHC(0x1406), SHC(0x89be), SHC(0x30fc), + SHC(0x9872), SHC(0x4b3d), SHC(0xacdf), SHC(0x6155), SHC(0xc5e4), SHC(0x720d), SHC(0xe21e), SHC(0x7c77), + SHC(0x7fff), SHC(0x0000), SHC(0x7b77), SHC(0xde39), SHC(0x6e2d), SHC(0xbed8), SHC(0x5914), SHC(0xa414), + SHC(0x3daa), SHC(0x8fd5), SHC(0x1de2), SHC(0x8389), SHC(0xfbfb), SHC(0x8010), SHC(0xda5d), SHC(0x85a9), + SHC(0xbb6a), SHC(0x93ed), SHC(0xa154), SHC(0xa9db), SHC(0x8df3), SHC(0xc5e4), SHC(0x82a9), SHC(0xe60b), + SHC(0x8041), SHC(0x080a), SHC(0x86e7), SHC(0x2976), SHC(0x9622), SHC(0x47f2), SHC(0xacdf), SHC(0x6155), + SHC(0xc980), SHC(0x73d1), SHC(0xe9fe), SHC(0x7e18), SHC(0x0c0c), SHC(0x7f6f), SHC(0x2d3f), SHC(0x77bd), + SHC(0x7fff), SHC(0x0000), SHC(0x7a57), SHC(0xda5d), SHC(0x69de), SHC(0xb80e), SHC(0x5008), SHC(0x9c1b), + SHC(0x2f1f), SHC(0x88fd), SHC(0x0a0b), SHC(0x8065), SHC(0xe414), SHC(0x8315), SHC(0xc095), SHC(0x90d1), + SHC(0xa2b1), SHC(0xa861), SHC(0x8d0d), SHC(0xc7b0), SHC(0x8193), SHC(0xebfa), SHC(0x8147), SHC(0x1209), + SHC(0x8c2f), SHC(0x3680), SHC(0xa154), SHC(0x5625), SHC(0xbed8), SHC(0x6e2d), SHC(0xe21e), SHC(0x7c77), + SHC(0x080a), SHC(0x7fbf), SHC(0x2d3f), SHC(0x77bd), SHC(0x4e74), SHC(0x6524), SHC(0x68b9), SHC(0x499a) +}; + +/* These words are subtracted from high/low/value with a shift left by 1. */ +/* The value 0x0CCC should never be referenced, low is less/equal high */ +/* The value 0x0BBB should never be referenced, loop must break instead. */ +/* Refer to this table with indices: tab_ari_qnew[msb_high][msb_low] */ +const +Word16 tab_ari_qnew[4][4] = { { 0x0000, 0x0CCC, 0x0CCC, 0x0CCC }, + { 0x0000, 0x0000, 0x0CCC, 0x0CCC }, + { 0x0BBB, 0x2000, 0x4000, 0x0CCC }, + { 0x0BBB, 0x0BBB, 0x4000, 0x4000 } +}; + +/* order 8 LPF for nelp frames when non-native sampling freq inputs used with -max_band NB */ +/* used to suppress frequencies above 4kHz present at the output of filters in pre_proc() */ + +const Word16 num_nelp_lp_fx[NELP_LP_ORDER+1] = /*Q13*/ +{ + 727, + 3506, + 8988, + 15029, + 17732, + 15022, + 8979, + 3501, + 726 +}; + +const Word16 den_nelp_lp_fx[NELP_LP_ORDER+1] = +{ + 8192, + 8819, + 21618, + 12167, + 15902, + 3553, + 3998, + -120, + 353 +}; + +/* ACELP pulse coding */ +const Word16 hi_to_low_tmpl[10] = { 0, 0, 0, 3, 9, 5, 3, 1, 8, 8}; +const Word16 low_len[10] = { 0, 0, 8, 5, 7, 11, 13, 15, 16, 16}; +const Word32 low_mask[10] = { 0, 0, 255, 31,127, 2047, 8191, 32767, 65535, 65535}; +const Word16 indx_fact[10] = { 0, 0, 2, 172, 345, 140, 190, 223, 463, 1732}; +const Word16 index_len[3] = {0, 5, 9}; +const UWord32 index_mask_ACELP[3] = {0, 31, 511}; + +/* HQ pre-echo reduction */ +const Word16 inv_jp2[64] = +{ + 16384, 10923, 8192, 6554, 5461, 4681, 4096, 3641, 3277, 2979, 2731, 2521, 2341, 2185, 2048, 1928, + 1820, 1725, 1638, 1560, 1489, 1425, 1365, 1311, 1260, 1214, 1170, 1130, 1092, 1057, 1024, 993, + 964, 936, 910, 886, 862, 840, 819, 799, 780, 762, 745, 728, 712, 697, 683, 669, + 655, 643, 630, 618, 607, 596, 585, 575, 565, 555, 546, 537, 529, 520, 512, 504 +}; + diff --git a/lib_com/rom_com_fx.h b/lib_com/rom_com_fx.h new file mode 100644 index 0000000..530d2df --- /dev/null +++ b/lib_com/rom_com_fx.h @@ -0,0 +1,1240 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#ifndef ROM_COM_FX_H +#define ROM_COM_FX_H + +#include +#include "stat_com.h" +#include "stat_enc_fx.h" /* Encoder static structure */ +#include "stat_dec_fx.h" /* Decoder static structure */ + + +typedef struct +{ + Word32 fin_fx; /* input frequency Q0 */ + Word32 fout_fx; /* output frequency Q0 */ + Word16 fac_num_fx; /* numerator of resampling factor Q0 */ + Word16 fac_den_fx; /* denominator of resampling factor Q0 */ + Word16 lg_out; /* denominator of resampling factor Q15 */ + const Word16 *filter_fx; /* resampling filter coefficients Q14 */ + Word16 filt_len_fx; /* number of filter coeff. Q0 */ + UNS_Word16 flags_fx; /* flags from config. table Q0 */ +} Resampling_cfg_fx; + +/*-----------------------------------------------------------------* + * Tables with bit-allocations + *-----------------------------------------------------------------*/ + +extern const Word16 LSF_bits_tbl[]; /* Bit allocation table for end-frame ISF quantizer */ +extern const Word16 mid_LSF_bits_tbl[]; /* Bit allocation table for mid-frame ISF quantizer */ +extern const Word16 Es_pred_bits_tbl[]; /* Bit allocation table for scaled innovation energy prediction */ +extern const Word16 gain_bits_tbl[]; /* Bit allocation table for gain quantizer */ +extern const Word16 ACB_bits_tbl[]; /* Bit allocation table for adaptive codebook (pitch) */ +extern const Word16 FCB_bits_tbl[]; /* Bit allocation table for algebraic (fixed) codebook (innovation) */ +extern const Word16 reserved_bits_tbl[]; /* Bit allocation table for reserved bits */ + +extern const Word16 ACB_bits_16kHz_tbl[]; /* Bit allocation table for adaptive codebook (pitch) @16kHz */ +extern const Word16 FCB_bits_16kHz_tbl[]; /* Bit allocation table for algebraic (fixed) codebook (innovation) @16kHz */ +extern const Word16 gain_bits_16kHz_tbl[]; /* Bit allocation table for gain quantizer @16kHz */ +extern const Word16 AVQ_bits_16kHz_tbl[]; /* Bit allocation table for AVQ bits @16kHz ACELP, active segments */ +extern const Word32 pow2[]; /* Table with power of 2 values */ + +extern const Word16 crit_bins[]; /* (used only in AMR-WB IO mode) */ +extern const Word16 mfreq_bindiv_loc[]; +extern const Word16 mfreq_bindiv_LD[]; +extern const Word16 mfreq_loc_LD[]; /* LD music post-filter */ +extern const Word16 crit_bins_corr_fx[]; +/*-----------------------------------------------------------------* + * Table of bitrates + *-----------------------------------------------------------------*/ + +extern const Word32 brate_tbl[SIZE_BRATE_TBL]; +extern const Word32 acelp_sig_tbl[MAX_ACELP_SIG]; + + +extern const Word16 Nb[NB_SFM]; +extern const Word16 LNb[ NB_SFM]; + +/*-----------------------------------------------------------------* + * BC-TCQ frame-end quantization tables + *-----------------------------------------------------------------*/ + +extern const Word16 wind_sss_fx[LEN_WIN_SSS]; /*window for modify_sf ana*/ +extern const Word16 filter5_39s320_120_fx[]; /* LP FIR filter for 8kHz signal resampling */ +extern const Word16 stable_LSF_fx_16k[]; +extern const Word16 UVWB_Ave_fx[]; +extern const Word16 UVNB_Ave_fx[]; +extern const Word16 SVWB_Ave_fx[]; +extern const Word16 SVNB_Ave_fx[]; +extern const Word16 IANB_Ave_fx[]; +extern const Word16 IAWB_Ave_fx[]; +extern const Word16 IAWB2_Ave_fx[]; +extern const Word16 GENB_Ave_fx[]; +extern const Word16 GEWB_Ave_fx[]; +extern const Word16 GEWB2_Ave_fx[]; +extern const Word16 TRWB_Ave_fx[]; +extern const Word16 TRWB2_Ave_fx[]; +extern const Word16 means_wb_cleanspeech_lsf16k0[]; +extern const Word16 means_swb_cleanspeech_lsf25k6[]; +extern const Word16 means_swb_cleanspeech_lsf32k0[]; + +extern const Word16 stable_ISP_fx[]; +extern const Word16 stable_ISF_fx[]; +extern const Word16 stable_LSP_fx[]; +extern const Word16 lsp_shb_prev_tbl_fx[]; +extern const Word16 sin_table256_fx[]; +extern const Word16 b_hp400_fx[]; /* Q12 (/4) */ +extern const Word16 a_hp400_fx[]; +extern const Word16 fir_6k_7k_fx[]; +extern const Word16 no_lead_fx[][MAX_NO_SCALES*2]; +extern const Word16 no_lead_p_fx[][MAX_NO_SCALES*2]; +extern const Word16 change_pl_order_fx[]; +extern const Word16 cng_sort_fx[]; +extern const Word8 Ind_Guess[256]; +extern const Word16 acos_slope[128]; +extern const Word16 cos_table_129[129]; +extern const Word16 Es_pred_qua_5b_fx[32]; +extern const Word16 Es_pred_qua_4b_fx[16]; +extern const Word16 Es_pred_qua_3b_fx[8]; +extern const Word16 Es_pred_qua_4b_no_ltp_fx[16]; +extern const Word16 tbl_gain_code_tc_quant_mean[N_GAIN_CODE_TC-1]; +extern const Word16 tbl_gain_code_tc_fx[N_GAIN_CODE_TC]; +extern const Word16 gain_qua_mless_7b_fx[]; +extern const Word16 gain_qua_mless_6b_fx[]; +extern const Word16 gain_qua_mless_5b_fx[]; +extern const Word16 gp_gamma_1sfr_8b_fx[]; +extern const Word16 gp_gamma_1sfr_7b_fx[]; +extern const Word16 gp_gamma_1sfr_6b_fx[]; +extern const Word16 gp_gamma_2sfr_7b_fx[]; +extern const Word16 gp_gamma_2sfr_6b_fx[]; +extern const Word16 gp_gamma_3sfr_6b_fx[]; +extern const Word16 gp_gamma_4sfr_6b_fx[]; + +extern const Word16 pred_gain_fx[GAIN_PRED_ORDER]; +extern const Word16 t_qua_gain6b_fx[64*2]; +extern const Word16 t_qua_gain7b_fx[128*2]; + +extern const Word16 b_1sfr_fx[]; +extern const Word16 b_2sfr_fx[]; +extern const Word16 b_3sfr_fx[]; +extern const Word16 b_4sfr_fx[]; + +extern const Word16 inter4_2_fx[]; + +extern const Word16 Gamma_19661_Tbl_fx[]; +extern const Word16 Gamma_29491_Tbl[]; +extern const Word16 pwf_fx[17]; + + +extern const Word16 * const ModeMeans_fx[]; +extern const Word16 * const Predictors_fx[]; + +extern const Word16 tbl_mid_voi_wb_1b_fx[]; +extern const Word16 tbl_mid_voi_wb_4b_fx[]; +extern const Word16 tbl_mid_voi_wb_5b_fx[]; + +extern const Word16 tbl_mid_unv_wb_4b_fx[]; +extern const Word16 tbl_mid_unv_wb_5b_fx[]; + +extern const Word16 tbl_mid_gen_wb_2b_fx[]; +extern const Word16 tbl_mid_gen_wb_5b_fx[]; + +extern const Word16 CBsizes_fx[]; +extern const Word16 CBbits_fx[]; +extern const Word16 CBbits_p_fx[]; +extern const Word16 BitsVQ_fx[]; +extern const Word16 BitsVQ_p_fx[]; + + +extern const Word16 Predictor0_fx[]; +extern const Word16 Predictor1_fx[]; +extern const Word16 Predictor2_fx[]; +extern const Word16 Predictor3_fx[]; +extern const Word16 Predictor4_fx[]; +extern const Word16 Predictor5_fx[]; +extern const Word16 Predictor6_fx[]; +extern const Word16 Predictor7_fx[]; +extern const Word16 Predictor8_fx[]; + +extern const Word16 interpol_frac_mid_16k_fx[NB_SUBFR16k*3]; +extern const Word16 interpol_frac_mid_fx[NB_SUBFR*3]; + +extern const Word16 * const Quantizers_p_fx[]; +extern const Word16 * const Quantizers_fx[]; +extern const Word16 CNG_SN1_fx[]; + +extern const Word16 CB_lsf_fx[]; +extern const Word16 CB_p_lsf_fx[]; + +extern const Word16 sigma_p_fx[][16]; +extern const Word16 sigma_MSLVQ_fx[][16]; + +extern const Word16 pi0_fx[]; +extern const Word32 table_no_cv_fx[]; +extern const Word16 pl_par_fx[]; /* 1 if even number of signs */ +extern const Word16 C_VQ_fx[LATTICE_DIM+1][LATTICE_DIM+1]; +extern const Word16 no_vals_ind_fx[NO_LEADERS][MAX_NO_VALS]; +extern const Word16 no_vals_fx[NO_LEADERS]; + +extern const Word16 vals_fx[NO_LEADERS][MAX_NO_VALS]; +extern const Word16 scales_fx[][MAX_NO_SCALES*2]; +extern const Word16 scales_p_fx[][MAX_NO_SCALES*2]; +extern const Word16 predmode_tab[][6]; +extern const Word16 min_lat_bits_SN_fx[]; +extern const Word16 min_lat_bits_pred_fx[]; +extern const Word16 offset_in_lvq_mode_SN_fx[][21]; + +extern const Word16 offset_in_lvq_mode_pred_fx[][32]; + +extern const Word16 offset_lvq_modes_SN_fx[]; +extern const Word16 offset_lvq_modes_pred_fx[]; +extern const Word16 inv_sigma_p_fx[][16]; +extern const Word16 inv_sigma_MSLVQ_fx[][16]; +extern const Word16 perm_MSLVQ_fx[][4]; +extern const Word16 pl_HQ_fx[]; + +/*----------------------------------------------------------------------------------* + * ISF quantization (AMR-WB IO mode) + *----------------------------------------------------------------------------------*/ +extern const Word16 Indirect_dico1[SIZE_BK1]; + +extern const Word16 mean_isf_amr_wb_fx[M]; /* Mean ISF vector (only in AMR-WB IO mode) */ +extern const Word16 mean_isf_noise_amr_wb_fx[]; /* Mean ISF vector for SID frame (only in AMR-WB IO mode) */ + +extern const Word16 dico1_isf_fx[]; /* ISF codebook - common 1st stage, 1st split (only in AMR-WB IO mode) */ +extern const Word16 dico2_isf_fx[]; /* ISF codebook - common 1st stage, 2nd split (only in AMR-WB IO mode) */ + +extern const Word16 dico21_isf_46b_fx[]; /* ISF codebook - 46b, 2nd stage, 1st split (only in AMR-WB IO mode) */ +extern const Word16 dico22_isf_46b_fx[]; /* ISF codebook - 46b, 2nd stage, 2st split (only in AMR-WB IO mode) */ +extern const Word16 dico23_isf_46b_fx[]; /* ISF codebook - 46b, 2nd stage, 3rd split (only in AMR-WB IO mode) */ +extern const Word16 dico24_isf_46b_fx[]; /* ISF codebook - 46b, 2nd stage, 4th split (only in AMR-WB IO mode) */ +extern const Word16 dico25_isf_46b_fx[]; /* ISF codebook - 46b, 2nd stage, 5th split (only in AMR-WB IO mode) */ + +extern const Word16 dico21_isf_36b_fx[]; /* ISF codebook - 36b, 2nd stage, 1st split (only in AMR-WB IO mode) */ +extern const Word16 dico22_isf_36b_fx[]; /* ISF codebook - 36b, 2nd stage, 2nd split (only in AMR-WB IO mode) */ +extern const Word16 dico23_isf_36b_fx[]; /* ISF codebook - 36b, 2nd stage, 3rd split (only in AMR-WB IO mode) */ + +extern const Word16 dico1_ns_28b_fx[]; /* ISF codebook for SID frames - 28b, 1st split */ +extern const Word16 dico2_ns_28b_fx[]; /* ISF codebook for SID frames - 28b, 2nd spilt */ +extern const Word16 dico3_ns_28b_fx[]; /* ISF codebook for SID frames - 28b, 3rd spilt */ +extern const Word16 dico4_ns_28b_fx[]; /* ISF codebook for SID frames - 28b, 4th spilt */ +extern const Word16 dico5_ns_28b_fx[]; /* ISF codebook for SID frames - 28b, 5th spilt */ + +/*-----------------------------------------------------------------* + * BC-TCVQ frame-end quantization tables (BC-TCVQ is used in Voiced mode for 16kHz isf) + *-----------------------------------------------------------------*/ +extern const Word16 NTRANS[4][NUM_STATE]; +extern const Word16 NTRANS2[4][NUM_STATE]; + +extern const Word16 BC_TCVQ_BIT_ALLOC_40B[]; +extern const Word16 FixBranch_tbl[4][4][N_STAGE_VQ - 4]; + +extern const Word16 AR_IntraCoeff_fx[N_STAGE_VQ-1][2][2]; +extern const Word16 SN_IntraCoeff_fx[N_STAGE_VQ-1][2][2]; + +extern const Word16 scale_ARSN_fx[]; +extern const Word16 scale_inv_ARSN_fx[]; + +extern const Word16 AR_TCVQ_CB_SUB1_fx[2][128][2]; +extern const Word16 AR_TCVQ_CB_SUB2_fx[2][64][2]; +extern const Word16 AR_TCVQ_CB_SUB3_fx[4][32][2]; + +extern const Word16 SN_TCVQ_CB_SUB1_fx[2][128][2]; +extern const Word16 SN_TCVQ_CB_SUB2_fx[2][64][2]; +extern const Word16 SN_TCVQ_CB_SUB3_fx[4][32][2]; + +extern const Word16 AR_SVQ_CB1_fx[32][8]; +extern const Word16 AR_SVQ_CB2_fx[16][8]; + + +extern const Word16 interpol_frac_mid_relaxprev_12k8_fx[NB_SUBFR*3]; +extern const Word16 interpol_frac_mid_FEC_fx[NB_SUBFR*3]; +extern const Word16 interpol_frac_mid_relaxprev_pred_12k8_fx[NB_SUBFR*3]; +extern const Word16 interpol_frac_mid_relaxprev_16k_fx[NB_SUBFR16k*3]; +extern const Word16 interpol_frac_mid_16k_FEC_fx[NB_SUBFR16k*3]; +extern const Word16 interpol_frac_mid_relaxprev_pred_16k_fx[NB_SUBFR16k*3]; +extern const Resampling_cfg_fx resampling_cfg_tbl_fx[]; + +extern const Word16 filter_LP15_180H_fx[]; /* Sincfilt.m: N=180*2+1, Fmin=0, Fmax=1/15, hann( N )' */ +extern const Word16 filter_LP3_90H_fx[]; /* Sincfilt.m: N=90*2+1, Fmin=0, Fmax=1/3, hann( N )' */ +extern const Word16 filter_LP12_180H_13b_fx[]; /* Sincfilt.m: N=180*2+1, Fmin=0, Fmax=1/12, hann( N )' */ +extern const Word16 filter_LP15_180H_13b_fx[]; /* Sincfilt.m: N=180*2+1, Fmin=0, Fmax=1/15, hann( N )' */ +extern const Word16 filter_LP15_360H_13b_fx[]; /* Sincfilt.m: N=360*2+1, Fmin=0, Fmax=1/15, hann( N )' */ +extern const Word16 filter_LP24_90H_13b_fx[]; +extern const Word16 filter_LP24_90H_fx[]; + +extern const Word16 inter4_1_fx[]; + +extern const Word16 Low_H_phasedisp[L_SUBFR]; +extern const Word16 Mid_H_phasedisp[L_SUBFR]; +extern const Word16 phs_tbl_dec[]; + +extern const Word16 tbl_gain_trans_tc_fx[]; +extern const Word16 Glottal_cdbk_fx[]; + +extern const Word16 gaus_dico_fx[]; + + +extern const Word16 edct_table_80_fx[]; /* EDCT */ +extern const Word16 edct_table_120_fx[]; /* EDCT */ +extern const Word16 edct_table_100_fx[]; /* EDCT */ +extern const Word16 edct_table_320_fx[]; /* EDCT */ +extern const Word16 edct_table_480_fx[]; /* EDCT */ +extern const Word16 edct_table_600_fx[]; /* EDCT */ +extern const Word16 edct_table_128_fx[]; /* EDCT */ +extern const Word16 edct_table_160_fx[]; /* EDCT */ +extern const Word16 edct_table_40_fx[]; /* EDCT */ +extern const Word16 edct_table_20_fx[]; /* EDCT */ +extern const Word16 edct_table_64_fx[]; +extern const Word16 edct_table_200_fx[]; +extern const Word16 edct_table_240_fx[]; +extern const Word16 edct_table_256_fx[]; +extern const Word16 edct_table_400_fx[]; + +/*------------------------------------------------------------------------------* + * FFT transform + *------------------------------------------------------------------------------*/ +extern const Word16 FFT_REORDER_1024[]; +extern const Word16 FFT_W64[]; +extern const Word16 FFT_W128[]; +extern const Word16 FFT_W256[]; +extern const Word16 FFT_W512[]; +extern const Word16 sincos_t_rad3_fx[]; +extern const Word16 sincos_t_ext_fx[]; + +extern const Word16 Ip_fft16_fx[6]; +extern const Word16 w_fft16_fx[8]; + +extern const Word16 Ip_fft8_fx[6]; +extern const Word16 w_fft8_fx[4]; + +extern const Word16 Ip_fft32_fx[6]; + +extern const Word16 Ip_fft64_fx[6]; + +extern const Word16 Ip_fft4_fx[6]; +extern const Word16 w_fft4_fx[2]; + +extern const Word16 Ip_fft128_fx[10]; + +extern const Word16 ip_edct2_64_fx[6]; +extern const Word16 w_edct2_64_fx[80]; +extern const Word16 Odx_fft64_16fx[64]; +extern const Word16 Ip_fft64_16fx[6]; +extern const Word16 Ip_fft32_16fx[6]; +extern const Word32 w_fft128_16fx[64]; +extern const Word16 Ip_fft128_16fx[10]; +extern const Word16 Idx_dortft320_16fx[320]; +extern const Word16 Ip_fft32_16fx[6]; +extern const Word32 w_fft32_16fx[16]; +extern const Word16 edct_table_160_16fx[160]; +extern const Word16 edct_table_128_16fx[128]; +extern const Word16 edct_table_320_16fx[320]; +extern const Word16 mean_m_fx[]; + +extern const Word16 YG_dicMR_4_fx[]; +extern const Word16 YG_dicMR_2_fx[]; +extern const Word16 YG_dicMR_3_fx[]; +extern const Word16 YG_dicMR_1_fx[]; +extern const Word16 YG_mean16_fx[]; +extern const Word16 YG_dic1_2_fx[]; +extern const Word16 YG_dic1_1_fx[]; +extern const Word16 YG_mean14_fx[]; +extern const Word16 YGain_dic3_LR_fx[];/*Q13 */ +extern const Word16 YGain_dic2_LR_fx[];/*Q13 */ + +extern const Word16 YGain_mean_LR_fx[]; +extern const Word16 Gain_mean_dicHR_fx[]; +extern const Word16 Gain_mean_dic_fx[]; +extern const Word16 mean_gain_dic_fx[]; +extern const Word16 Gain_mean_fx[]; +extern const Word16 Gain_dic3_NBHR_fx[]; +extern const Word16 Gain_dic2_NBHR_fx[]; +extern const Word16 Gain_dic2_NB_fx[]; +extern const Word16 Gain_dic3_NB_fx[]; +extern const Word16 Mean_dic_NB_fx[]; +extern const Word16 Gain_mean_dicNB_fx[]; +extern const Word16 Gain_meanNB_fx[]; +/*extern const Word16 dic_gp_13_fx[]; */ +extern const Word16 dic_gp_fx[]; +extern const Word16 mean_gp_fx[]; +extern const Word16 Gain_dic1_NB_fx[]; +extern const Word16 YGain_dic1_LR_fx[]; + +extern const Word16 mfreq_loc_Q2fx[]; +extern const Word16 mfreq_loc_div_25[]; +extern const Word16 mfreq_bindiv_loc_fx[]; +extern const Word16 sm_table_fx[]; +extern const Word16 GSC_freq_bits[]; + +extern const Word16 gsc_sfm_start[]; +extern const Word16 gsc_sfm_end[]; +extern const Word16 gsc_sfm_size[]; + +extern const Word16 sincos_t_fx[161]; +extern const Word32 GSC_freq_bits_fx[]; + +extern const Word16 *scalar_tbls_fx[4]; +extern const Word16 scalar_4bit_fx[16]; +extern const Word16 scalar_3bit_fx[8]; +extern const Word16 scalar_2bit_fx[4]; +extern const Word16 scalar_1bit_fx[2]; +extern const Word16 Mean_isf_wb[]; +extern const Word16 interpol_isp_amr_wb_fx[]; +extern const Word16 interpol_frac_16k_fx[NB_SUBFR16k]; +extern const Word16 interpol_frac_fx[NB_SUBFR]; +extern const Word16 CNG_burst_att_fx[6][8]; +extern const Word32 pow2_fx[]; +extern const Word16 CNG_details_codebook_fx[64][NUM_ENV_CNG]; + +extern const Word16 deem_tab_fx[]; /* HF BWE - de-emphasis coefficients */ +extern const Word16 filt_hp_fx[]; /* HF BWE - HP filter coefficients in freq. domain */ +extern const Word16 HP_gain_fx[]; /* HF BWE - quantization table for 23.85 */ +extern const Word16 fir_6k_8k_fx[]; /* HF BWE - band-pass filter coefficients */ +extern const Word16 exp_tab_q_fx[]; +extern const Word16 exp_tab_p_fx[]; +extern const Word16 swb_bwe_trans_subband_width_fx[]; +extern const Word16 sqrt_swb_bwe_trans_subband_width_fx[]; +extern const Word16 sqrt_swb_bwe_subband_fx_L1[]; +extern const Word16 sqrt_swb_bwe_subband_fx_L2[]; +extern const Word16 smooth_factor_fx[]; +extern const Word16 swb_bwe_sm_subband_fx[]; + +extern const Word16 swb_bwe_trans_subband_fx[]; +extern const Word16 swb_bwe_subband_fx[]; +extern const Word16 F_2_5_fx[64]; + +extern const Word16 swb_inv_bwe_subband_width_fx[]; +extern const Word16 w_NOR_fx[]; +extern const Word16 sin_switch_8[15]; +extern const Word16 sin_switch_16[30]; +extern const Word16 sin_switch_32[60]; +extern const Word16 sin_switch_48[90]; +/* sinus table for overlapadd */ +/*extern const Word16 sin_switch_96_16_fx[156]; */ +/*extern const Word16 sin_switch_96_12_fx[108]; */ +extern const Word16 one_on_win_48k_fx[210]; /*Q14 */ +extern const Word16 one_on_win_8k_16k_48k_fx[70]; /*Q14 */ +extern const Word16 TRWB2_Ave_fx[16]; +extern const Word16 TRWB_Ave_fx[16]; +/*------------------------------------------------------------------------------* + * ACEPL/HQ core switching tables + *------------------------------------------------------------------------------*/ +extern const Word16 hp12800_32000_fx[]; +extern const Word16 hp16000_32000_fx[]; +extern const Word16 hp12800_48000_fx[]; +extern const Word16 hp16000_48000_fx[]; +extern const Word16 hp12800_16000_fx[]; +extern const Word16 inner_frame_tbl_fx[]; + + +extern const Word16 EnvCdbk11_fx []; +extern const Word16 EnvCdbk1st_fx []; +extern const Word16 EnvCdbk2nd_fx []; +extern const Word16 EnvCdbk3rd_fx []; +extern const Word16 EnvCdbk4th_fx []; +extern const Word16 Env_TR_Cdbk1_fx []; +extern const Word16 Env_TR_Cdbk2_fx []; +extern const Word16 EnvCdbkFB_fx []; +extern const Word16 Mean_env_fx[]; +extern const Word16 Mean_env_tr_fx[]; +extern const Word16 Mean_env_fb_fx[]; + +extern const Word32 PI_select_table_fx[23][8]; /* selection table for Pulse indexing */ +extern const Word32 PI_offset_fx[8][8]; /* offset table for Pulse indexing */ +extern const Word16 PI_factor_fx[]; /* PI factor table for Pulse indexing */ + +extern const short Num_bands_NB[]; + + +extern const Word16 hvq_cb_search_overlap24k[17]; +extern const Word16 hvq_cb_search_overlap32k[21]; + +extern const Word16 hvq_pg_huff_offset[NUM_PG_HUFFLEN]; +extern const Word16 hvq_pg_huff_thres[NUM_PG_HUFFLEN]; +extern const Word16 hvq_pg_huff_tab[32]; + +extern const Word16 hvq_cp_huff_len[52]; +extern const Word16 hvq_cp_huff_val[52]; +extern const Word16 hvq_cp_layer1_map5[HVQ_CP_MAP_LEN]; + +extern const Word16 hvq_cp_huff_thres[HVQ_CP_HUFF_NUM_LEN]; +extern const Word16 hvq_cp_huff_offset[HVQ_CP_HUFF_NUM_LEN]; +extern const Word16 hvq_cp_huff_tab[52]; + +extern const Word16 pgain_huffnorm[32]; +extern const Word16 pgain_huffsizn[32]; + +extern const Word16 huffnorm_tran[32]; +extern const Word16 huffsizn_tran[32]; + +extern const Word16 resize_huffnorm[32]; +extern const Word16 resize_huffsizn[32]; + +extern const Word16 huffsizn[32]; + +extern const Word16 lsf_q_num_bits[]; /* Size of each element of the above, in bits */ + +/*------------------------------------------------------------------------------* + * AVQ - RE8 tables + *------------------------------------------------------------------------------*/ + +extern const Word16 select_table22_fx[][9]; +extern const Word16 vals_a_fx[][4]; /* value of leader element */ +extern const Word16 vals_q_fx[][4]; /* code parameter for every leader */ +extern const UWord16 Is_fx[]; /* codebook start address for every leader */ +extern const Word16 A3_fx[]; /* A3 - Number of the absolute leaders in codebook Q3 */ +extern const Word16 A4_fx[]; /* A4 - Number of the absolute leaders in codebook Q4 */ +extern const UWord16 I3_fx[]; /* I3 - Cardinality offsets for absolute leaders in Q3 */ +extern const UWord16 I4_fx[]; /* I4 - Cardinality offset for absolute leaders in Q4 */ + +extern const Word16 Da_nq_fx[]; +extern const Word16 Da_pos_fx[], Da_nb_fx[]; +extern const Word16 Da_id_fx[]; + +extern const Word16 Assym_window_W16fx[]; +extern const Word16 assym_window_16k_fx[]; +extern const Word16 Hamcos_Window[]; + +extern const Word16 overlap_coefs_fx[NSV_OVERLAP*WIDTH_BAND]; /* in Q15 */ +extern const Word16 overlap_coefs_48kHz_fx[NSV_OVERLAP*WIDTH_BAND]; /* in Q15 */ + +extern const Word16 swb_hr_env_code1_fx[]; /* HR SWB BWE - envelope Q table - first two subabnds in non-transient frames */ +extern const Word16 swb_hr_env_code2_fx[]; /* HR SWB BWE - envelope Q table - second two subabnds in non-transient frames*/ +extern const Word16 swb_hr_env_code3_fx[]; /* HR SWB BWE - envelope Q table - two subands in transient frames */ + +extern const Word16 short_window_48kHz_fx[L_FRAME48k/2/2]; +extern const Word16 short_window_32kHz_fx[L_FRAME32k/2/2]; +extern const Word16 short_window_16kHz_fx[L_FRAME16k/2/2]; +extern const Word16 short_window_8kHz_fx[L_FRAME8k/2/2]; + + +extern const Word16 Hilbert_coeffs_fx[4*NUM_HILBERTS][HILBERT_ORDER1+1]; +extern const Word16 win_flatten_4k_fx[]; /* Window for calculating whitening filter for WB excitation */ + +extern const Word32 no_lead[][MAX_NO_SCALES*2]; +extern const Word32 no_lead_p[][MAX_NO_SCALES*2]; + +extern const Word16 min_lat_bits_SN_fx[]; +extern const Word16 min_lat_bits_pred_fx[]; + +extern const Word16 fb_bwe_sm_subband[]; +extern const Word16 fb_bwe_subband[]; + +extern const Word16 sfm_width[20]; +extern const Word16 a_table_fx[20]; + +/* HQ inner_frame signallisation table */ +extern const Word16 inner_frame_tbl[]; + + +/*------------------------------------------------------------------------------* + * SWB TBE tables + *------------------------------------------------------------------------------*/ + +extern const Word16 skip_bands_SWB_TBE[]; /* bands for SWB TBE quantisation */ +extern const Word16 skip_bands_WB_TBE[]; /* bands for WB TBE quantisation */ + +extern const Word16 swb_lsp_prev_interp_init[]; + +extern const Word16 allpass_poles_3_ov_2[]; /* All pass 3 over 2 filter coefficients */ +extern const Word16 decimate_3_ov_2_lowpass_num[]; +extern const Word16 decimate_3_ov_2_lowpass_den[]; + +/* Band structure */ +extern const Word16 band_len_HQ[]; +extern const Word16 band_start_HQ[]; +extern const Word16 band_end_HQ[]; +extern const Word16 band_len_wb[]; +extern const Word16 band_start_wb[]; +extern const Word16 band_end_wb[]; +extern const Word16 band_len_harm[]; +extern const Word16 band_start_harm[]; +extern const Word16 band_end_harm[]; +extern const Word16 dicnlg2[40]; + +extern const Word16 intl_bw_16[N_INTL_GRP_16]; +extern const Word16 intl_bw_32[N_INTL_GRP_32]; +extern const Word16 intl_bw_48[N_INTL_GRP_48]; +extern const Word16 intl_cnt_16[N_INTL_GRP_16]; +extern const Word16 intl_cnt_32[N_INTL_GRP_32]; +extern const Word16 intl_cnt_48[N_INTL_GRP_48]; +extern const Word16 norm_order_48[NB_SFM]; +extern const Word16 norm_order_32[SFM_N_SWB]; +extern const Word16 norm_order_16[SFM_N_WB]; + +extern const Word16 gaus_dico_swb_fx[]; /* Gaussian codebook for SWB TBE */ +extern const Word16 win_flatten_fx[]; /* Window for calculating whitening filter for SHB excitation */ +extern const Word16 AP1_STEEP_FX[]; /* All pass filter coeffs for interpolation and decimation by a factor of 2 */ +extern const Word16 AP2_STEEP_FX[]; /* All pass filter coeffs for interpolation and decimation by a factor of 2 */ +extern const Word16 cos_fb_exc_fx[32]; +extern const Word16 window_wb_fx[]; +extern const Word16 subwin_wb_fx[]; /* Short overlap add window for SHB excitation used in anal and synth */ +extern const Word16 window_shb_fx[]; /* Overlap add window for SHB excitation used in anal and synth */ +extern const Word16 window_shb_32k_fx[]; +extern const Word16 subwin_shb_fx[]; /* Short overlap add window for SHB excitation used in anal and synth */ +extern const Word16 * const lsf_q_cb_fx[]; /* Codebook array for each LSF */ +extern const Word16 lsf_q_cb_size_fx[]; /* Size of each element of the above */ +extern const Word16 grid_smoothing_fx[]; /* LSF mirroring smoothing table */ +extern const Word16 mirror_point_q_cb_fx[]; /* LSF mirroring point codebook */ +extern const Word16 lbr_wb_bwe_lsfvq_cbook_2bit_fx[]; +extern const Word16 swb_tbe_lsfvq_cbook_8b[]; +extern const Word32 SHBCB_FrameGain16_fx[]; +extern const Word16 SHBCB_SubGain5bit_fx[]; /* 5 bit Quantizer table for SHB gain shapes */ +extern const Word16 SHBCB_SubGain5bit_12_fx[]; /* 5 bit Quantizer table for SHB gain shapes */ +extern const Word16 HBCB_SubGain5bit_fx[]; /* 5-bit TD WB BWE temporal shaping codebook */ +extern const Word32 SHBCB_FrameGain64_fx[]; /* 6 bit Quantizer table for SHB overall gain */ +extern const Word32 SHBCB_FrameGain16_fx[]; +extern const Word16 full_band_bpf_1_fx[][5]; +extern const Word16 full_band_bpf_2_fx[][5]; +extern const Word16 full_band_bpf_3_fx[][5]; +extern const Word16 lsf_q_cb_4b_fx[]; /* 4 bit differential scalar quantizer table for TD SWB BWE LSFs 1 and 2*/ +extern const Word16 lsf_q_cb_3b_fx[]; /* 3 bit differential scalar quantizer table for TD SWB BWE LSFs 3, 4 and 5*/ + +extern const Word16 cos_coef_new[4]; +extern const Word16 pwAlpha[10]; + +extern const Word16 interpol_frac_shb[NB_SUBFR*2]; + +extern const Word16 wb_bwe_lsfvq_cbook_8bit_fx[]; +extern const Word16 lsf_grid_fx[4][5]; /* LSF mirroring adjustment grid */ +extern const Word16 ola_win_shb_switch_fold_fx[]; +extern const Word16 win_lpc_hb_wb_fx[]; +extern const Word16 wac_h[]; +extern const Word16 wac_l[]; +extern const Word16 wac_swb_h[LPC_SHB_ORDER]; +extern const Word16 wac_swb_l[LPC_SHB_ORDER]; +extern const Word16 lpc_weights_fx[]; +extern const Word16 win_lpc_shb_fx[]; /* Window for calculating SHB LPC coeffs */ +extern const Word16 cos_table[512]; +extern const Word16 cos_diff_table[512]; +extern const Word16 Ip_fft256_fx[10]; +extern const Word16 Ip_fft512_fx[18]; +extern const Word16 w_fft512_fx[256]; +extern const Word16 sinq_16k[]; +extern const Word16 sinq_32k[]; +extern const Word16 sinq_48k[]; +extern const Word16 Asr_LP32_fx[41]; +extern const Word16 Asr_LP16_fx[21]; +extern const Word16 Asr_LP48_fx[61]; +extern const Word16 window_8_16_32kHz_fx[]; +extern const Word16 window_48kHz_fx[]; +extern const Word16 window_256kHz[]; +extern const Word16 half_overlap_25[]; +extern const Word16 half_overlap_48[]; +extern const Word16 half_overlap_int[]; +extern const Word16 small_overlap_25[]; +extern const Word16 small_overlap_48[]; +extern const Word16 small_overlap_int[]; + +/* SC-VBR: NELP filter coefficients */ + +extern const Word16 txlpf1_num_coef_fx[11]; +extern const Word16 txlpf1_den_coef_fx[11]; +extern const Word16 txhpf1_num_coef_fx[11]; +extern const Word16 txhpf1_den_coef_fx[11]; + + +extern const Word16 shape1_num_coef_fx[11]; +extern const Word16 shape1_den_coef_fx[11]; +extern const Word16 shape2_num_coef_fx[11]; +extern const Word16 shape2_den_coef_fx[11]; +extern const Word16 shape3_num_coef_fx[11]; +extern const Word16 shape3_den_coef_fx[11]; +extern const Word16 bp1_num_coef_wb_fx[5]; +extern const Word16 bp1_den_coef_wb_fx[5]; +extern const Word16 bp1_num_coef_nb_fx[13]; +extern const Word16 bp1_den_coef_nb_fx[13]; + +extern const Word16 bp1_num_coef_nb_fx_order7[8]; +extern const Word16 bp1_den_coef_nb_fx_order7[8]; + +extern const Word16 UVG1CB_WB_FX[UVG1_CBSIZE][2]; +extern const Word16 UVG2CB1_WB_FX[UVG2_CBSIZE][5]; +extern const Word16 UVG2CB2_WB_FX[UVG2_CBSIZE][5]; + +extern const Word16 UVG1CB_NB_FX[UVG1_CBSIZE][2]; +extern const Word16 UVG2CB1_NB_FX[UVG2_CBSIZE][5]; +extern const Word16 UVG2CB2_NB_FX[UVG2_CBSIZE][5]; + +extern const Word16 frac_4sf_fx[NB_SUBFR +2]; + +extern const Word16 erb_WB_fx[NUM_ERB_WB + 1]; +extern const Word16 erb_NB_fx[NUM_ERB_NB + 1]; + +extern const Word16 AmpCB1_WB_fx[640]; +extern const Word16 pwf78_fx[17]; + +extern const Word16 AmpCB2_WB_fx[64*(NUM_ERB_WB-13)]; + +extern const Word16 AmpCB1_NB_fx[640]; + +extern const Word16 AmpCB2_NB_fx[64*(NUM_ERB_NB-13)]; + +extern const Word16 PowerCB_WB_fx[128]; +extern const Word16 PowerCB_NB_fx[128]; +extern const Word16 sinc_fx[8][12]; +extern const Word16 hvq_cb_search_overlap24k[17]; +extern const Word16 hvq_cb_search_overlap32k[21]; + +extern const Word32 inverse_table[]; + +extern const Word16 post_dct_wind_fx[]; +extern const Word16 mfreq_loc_LD_fx[]; +extern const Word16 inv_mfreq_bindiv_LD_fx[]; +extern const Word16 inv_mfreq_bindiv_LD_M1_fx[]; +/*extern const Word16 inv_mfreq_M1_SC_FACT_fx[]; */ +extern const Word16 sc_qnoise_fx[]; +extern const Word16 MAX_SNR_SNR1_tab_FX[MBANDS_GN_LD]; +extern const Word16 INV_MAX_SNR_tab_FX[MBANDS_GN_LD]; + +extern const Word16 W_DTX_HO_FX[HO_HIST_SIZE]; +extern const Word16 HO_ATT_FX[5]; + + +/*----------------------------------------------------------------------------------* + * SWB HR BWE + *----------------------------------------------------------------------------------*/ + +extern const Word16 wscw16q15_fx[]; +extern const Word16 wscw16q15_8_fx[]; +extern const Word16 wscw16q15_16_fx[]; +extern const Word16 wscw16q15_32_fx[]; + +extern const Word16 crit_bands_loc_fx[]; +extern const Word16 lag_h[]; +extern const Word16 lag_l[]; + +extern const Word16 hvq_class_c_fx[]; +extern const Word32 dicn_fx[40]; +extern const Word16 sqac_headroom_fx[146]; +extern const Word16 inv_N_fx[32]; +extern const Word16 hvq_bwe_fac_fx[16]; +extern const Word16 att_step_fx[4]; +extern const Word16 gain_att_fx[40]; +extern const Word16 stab_trans_fx[]; +extern const Word16 env_stab_tp_fx[2][2]; +extern const Word16 subf_norm_groups_fx[4][11]; +extern const Word32 dicn_pg_fx[]; +extern const Word16 hvq_peak_cb_fx[]; +extern const Word16 rat_fx[SFM_N_WB]; +extern const Word16 fb_inv_bwe_subband_width_fx[]; +extern const Word16 fb_smooth_factor_fx[]; +extern const Word16 hvq_thr_adj_fx[]; +extern const Word16 hvq_index_mapping_fx[4]; +extern const Word16 hq_nominal_scaling_inv[]; +extern const Word16 hq_nominal_scaling[]; +extern const Word16 band_len_idx[]; +extern const Word16 band_len_ener_shift[]; +extern const Word16 fine_gain_pred_sqrt_bw[]; +extern const Word16* finegain_fx[5]; +extern const Word32 SQRT_DIM_fx[]; +extern const Word16 gain_cb_size[]; + +/* PVQ tables */ +extern const UWord32 exactdivodd_fx[ODD_DIV_SIZE_FX]; + + + +extern const Word32 thren_fx[39]; + +typedef struct +{ + Word16 bands; + Word16 bw; + const Word16 *band_width; + Word32 L_qint; + Word16 eref; + Word16 bit_alloc_weight; + Word16 gqlevs; + Word16 Ngq; + Word16 p2a_bands; + Word16 p2a_th; + Word16 pd_thresh; + Word16 ld_slope; + Word16 ni_coef; +} Xcore_Config_fx; + +/* LR-MDCT configuration tables */ +extern const Xcore_Config_fx xcore_config_8kHz_007200bps_long_fx; +extern const Xcore_Config_fx xcore_config_8kHz_008000bps_long_fx; +extern const Xcore_Config_fx xcore_config_8kHz_013200bps_long_fx; +extern const Xcore_Config_fx xcore_config_8kHz_016400bps_long_fx; + +extern const Xcore_Config_fx xcore_config_8kHz_007200bps_short_fx; +extern const Xcore_Config_fx xcore_config_8kHz_008000bps_short_fx; +extern const Xcore_Config_fx xcore_config_8kHz_013200bps_short_fx; +extern const Xcore_Config_fx xcore_config_8kHz_016400bps_short_fx; + +extern const Xcore_Config_fx xcore_config_16kHz_013200bps_long_fx; +extern const Xcore_Config_fx xcore_config_16kHz_016400bps_long_fx; + +extern const Xcore_Config_fx xcore_config_16kHz_013200bps_short_fx; +extern const Xcore_Config_fx xcore_config_16kHz_016400bps_short_fx; + +extern const Xcore_Config_fx xcore_config_32kHz_013200bps_long_fx; +extern const Xcore_Config_fx xcore_config_32kHz_016400bps_long_fx; + +extern const Xcore_Config_fx xcore_config_32kHz_013200bps_short_fx; +extern const Xcore_Config_fx xcore_config_32kHz_016400bps_short_fx; + +extern const Word16 Odx_fft32_5[32]; +extern const Word16 Idx_dortft160[160]; + + +extern const Word16 nextstate[STATES][2]; + +extern const Word16 fine_gain_bits[]; + +/*----------------------------------------------------------------------------------* + * SWB BWE for LR MDCT core + *----------------------------------------------------------------------------------*/ +/* HQ_NORMAL mode */ +extern const Word16 subband_offsets_12KBPS[NB_SWB_SUBBANDS]; +extern const Word16 subband_offsets_16KBPS[NB_SWB_SUBBANDS]; +extern const Word16 bits_lagIndices_modeNormal_fx[NB_SWB_SUBBANDS]; +extern const Word16 subband_search_offsets_fx[NB_SWB_SUBBANDS]; +extern const Word16 bw_SPT_tbl[2][SPT_SHORTEN_SBNUM]; + +/* HQ_HARMONIC mode */ +extern const Word16 bits_lagIndices_mode0_Har_fx[NB_SWB_SUBBANDS_HAR_SEARCH_SB]; +extern const Word16 subband_offsets_sub5_13p2kbps_Har_fx[NB_SWB_SUBBANDS_HAR]; +extern const Word16 subband_search_offsets_13p2kbps_Har_fx[NB_SWB_SUBBANDS_HAR_SEARCH_SB]; +extern const Word16 subband_offsets_sub5_16p4kbps_Har_fx[NB_SWB_SUBBANDS_HAR]; +extern const Word16 subband_search_offsets_16p4kbps_Har_fx[NB_SWB_SUBBANDS_HAR_SEARCH_SB] ; +extern const Word16 gain_table_SWB_BWE_fx[NB_SWB_SUBBANDS]; + + +extern const Word16 inv_tbl_fx[]; +extern const Word32 table_logcum_fx[563]; +extern const Word32 pow_getbitsfrompulses_fx[16]; +extern const Word16 DDP_fx[4]; +extern const Word16 step_tcq_fx[8][STATES]; +extern const Word16 denc_fx[8][STATES]; /* enc trellis */ +extern const Word16 ddec_fx[8][STATES]; /* dec trellis */ +extern const Word16 step_LSB_fx[STATES_LSB][2]; +extern const Word16 denc_LSB_fx[STATES_LSB][2]; +extern const Word16 dqnt_LSB_fx[STATES_LSB][4]; + +extern const Word16 dstep_LSB_fx[4][2]; +extern const Word16 ddec_LSB_fx[4][2]; + +extern const Word16 SmoothingWin_NB875_fx[]; +extern const Word16 SmoothingWin_NB2_fx[]; + +extern const Word16 ENR_ATT_fx[5]; + + +extern const Word16 cu15_fx[28][3]; +extern const Word16 cu4_fx[6][3]; +extern const Word16 ct2_fx[7][14]; + +extern const unsigned char* const hBitsN[65]; +extern const short dsDiracsTab[65]; +extern const unsigned int intLimCDivInvDQ31[68]; +extern const unsigned char obtainEnergyQuantizerDensity_f[57]; + +extern const Word16 lim_neg_inv_tbl_fx[11]; + + +extern const Word16 One_div_fx[]; + + +/*---------------------------------------------------------------------* + * TABLE ROM, defined in lib_com\rom_com.c + *---------------------------------------------------------------------*/ +extern const Word16 inter4_2tcx2[4][4]; +extern const Word16 inter6_2tcx2[6][4]; +typedef struct TCX_LTP_FILTER +{ + const Word16 *filt; + Word16 length; +} TCX_LTP_FILTER; +extern const TCX_LTP_FILTER tcxLtpFilters[12]; + +extern const Word16 Grid[]; +extern const Word16 low_H[64]; +extern const Word16 low_H16k[80]; +extern const Word16 mid_H[64]; +extern const Word16 mid_H16k[80]; + +extern const Word16 E_ROM_inter4_1[PIT_UP_SAMP * L_INTERPOL1 + 1]; +extern const Word16 E_ROM_inter6_1[PIT_UP_SAMP6 * L_INTERPOL1 + 1]; +extern const Word16 E_ROM_qua_gain5b_const[NB_QUA_GAIN5B * 2]; +extern const Word16 E_ROM_qua_gain6b_const[NB_QUA_GAIN6B * 2] ; +extern const Word16 E_ROM_qua_gain7b_const[NB_QUA_GAIN7B * 2] ; +extern const Word16 Es_pred_qua[8]; +extern const Word16 Es_pred_qua_2[16]; + +extern const SCALE_TCX_SETUP scaleTcxTable[13]; + +extern const FrameSizeParams FrameSizeConfig[FRAME_SIZE_NB]; +extern const Word16 amrwb_frame_sizes[9]; + +/*fd_cng_commom.h*/ +extern const Word16 d_array[18]; +extern const Word16 m_array[18]; +#define msQeqInvAv_thres_EXP (-4) +extern const Word16 msQeqInvAv_thresh[3]; +extern const Word16 msNoiseSlopeMax[4]; +extern const Word16 preemphCompensation[NB_BANDS]; +#define msNoiseSlopeMax_EXP 3 + +extern const SCALE_SETUP scaleTable[20]; +extern const SCALE_SETUP scaleTable_cn_only[18]; +extern const Word16 scaleTable_cn_only_amrwbio[3][2]; + +extern const Word16 sidparts_encoder_noise_est[24]; + + +extern const FD_CNG_SETUP FdCngSetup_nb; +extern const FD_CNG_SETUP FdCngSetup_wb1; +extern const FD_CNG_SETUP FdCngSetup_wb2; +extern const FD_CNG_SETUP FdCngSetup_wb3; +extern const FD_CNG_SETUP FdCngSetup_swb1; +extern const FD_CNG_SETUP FdCngSetup_swb2; + +extern const Word16 maxN_37bits; +extern const Word16 maxC_37bits; +extern const Word16 stages_37bits; +extern const Word16 levels_37bits[6]; +extern const Word16 bits_37bits[6]; +extern Word16 const * const cdk_37bits[]; + +/* tcx_utils.c */ +extern const Word16 gain_corr_fac[]; /*pow(10,2^(-n-2)/28)*/ +extern const Word16 gain_corr_inv_fac[];/*pow(10,-2^(-n-2)/28)*/ + +/* ari_stat.h */ +extern const Word8 ari_lookup_s17_LC[4096]; +extern const UWord16 ari_pk_s17_LC_ext[64][18]; +extern const Word16 Tab_esc_nb[4]; + +/* ari_hm.c */ +extern const Word16 NumRatioBits[2][17]; +extern const Word16 Ratios_WB_2[32]; +extern const Word16 Ratios_WB_3[32]; +extern const Word16 Ratios_WB_4[32]; +extern const Word16 Ratios_WB_5[32]; +extern const Word16 Ratios_WB_6[32]; +extern const Word16 Ratios_WB_7[32]; +extern const Word16 Ratios_WB_8[16]; +extern const Word16 Ratios_WB_9[16]; +extern const Word16 Ratios_WB_10[16]; +extern const Word16 Ratios_WB_11[16]; +extern const Word16 Ratios_WB_12[16]; +extern const Word16 Ratios_WB_13[16]; +extern const Word16 Ratios_WB_14[16]; +extern const Word16 Ratios_WB_15[16]; +extern const Word16 Ratios_WB_16[4]; +extern const Word16 Ratios_WB_17[4]; +extern const Word16 Ratios_WB_18[4]; +extern const Word16 Ratios_NB_2[32]; +extern const Word16 Ratios_NB_3[16]; +extern const Word16 Ratios_NB_4[16]; +extern const Word16 Ratios_NB_5[16]; +extern const Word16 Ratios_NB_6[16]; +extern const Word16 Ratios_NB_7[16]; +extern const Word16 Ratios_NB_8[16]; +extern const Word16 Ratios_NB_9[8]; +extern const Word16 Ratios_NB_10[8]; +extern const Word16 Ratios_NB_11[8]; +extern const Word16 Ratios_NB_12[8]; +extern const Word16 Ratios_NB_13[4]; +extern const Word16 Ratios_NB_14[4]; +extern const Word16 Ratios_NB_15[4]; +extern const Word16 Ratios_NB_16[4]; +extern const Word16 Ratios_NB_17[4]; +extern const Word16 Ratios_NB_18[4]; +extern const Word16 *const Ratios[2][17]; + +extern const Word16 qGains[2][1 << kTcxHmNumGainBits]; + +/*tns_tables.h*/ + +extern struct TnsParameters const tnsParametersIGF32kHz_LowBR[1]; + +extern struct TnsParameters const tnsParameters32kHz[2]; + +extern struct TnsParameters const tnsParameters32kHz_grouped[2]; + +extern struct TnsParameters const tnsParameters16kHz[1]; + +extern struct TnsParameters const tnsParameters16kHz_grouped[2]; +extern struct TnsParameters const tnsParameters48kHz_grouped[2]; + +extern const Word16 tnsAcfWindow[TNS_MAX_FILTER_ORDER]; + +/**********************************************************************/ +/* Definition of the mapping between TNS parameters and a bitstream */ +/**********************************************************************/ + +extern ParamsBitMap const tnsEnabledSWBTCX20BitMap[1]; +extern ParamsBitMap const tnsEnabledSWBTCX10BitMap[1]; +extern ParamsBitMap const tnsEnabledWBTCX20BitMap[1]; + +/**********************************************/ +/* Helper structures for hufmann table coding */ +/**********************************************/ + +extern const Coding codesTnsAllCoeffs[]; + +extern const Coding codesTnsCoeff5[]; +extern const Coding codesTnsCoeff6[]; + +extern const Coding codesTnsCoeff0WBTCX20[]; +extern const Coding codesTnsCoeff1WBTCX20[]; +extern const Coding codesTnsCoeff2WBTCX20[]; +extern const Coding codesTnsCoeff3WB[]; + +extern const Coding codesTnsCoeff456[]; +extern const Coding codesTnsCoeff7[]; + +extern Word16 const nTnsCoeffCodes; + +extern const Coding * codesTnsCoeffSWBTCX20[]; +extern const Coding * codesTnsCoeffSWBTCX10[]; +extern const Coding * codesTnsCoeffWBTCX20[]; +extern Word16 const nTnsCoeffTables; + +extern const Coding codesTnsOrderTCX20[]; +extern const Coding codesTnsOrderTCX10[]; +extern const Coding codesTnsOrder[]; +extern Word16 const nTnsOrderCodes; + + +/*******************************/ +/* Quantized TNS coefficients. */ +/*******************************/ + +/* 4 bit resolution TNS coefficients. */ +extern const Word16 tnsCoeff4[16]; + +/*bits_alloc.h*/ + +/*bits_alloc_tables.h*/ +/*RATE MODE CONFIGURATION TABLE*/ +extern const Word16 RATE_MODE_MAPPING[FRAME_SIZE_NB]; + + +/*ACELP INNOVATIVE CDBK*/ +#define ACELP_FIXED_CDK_BITS(n) ACELP_CDK_BITS[n] + +/* Number of states for any combination pulses in any combination of vector length */ +extern const Word32 pulsestostates[17][9]; + + + +/*ACELP NRG ELEMENT*/ +extern const Word16 ACELP_NRG_MODE[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX]; +extern const Word16 ACELP_NRG_BITS[3]; + +/*ACELP LTP ELEMENT*/ +extern const Word16 ACELP_LTP_MODE[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX]; +extern const Word16 ACELP_LTP_BITS_SFR[8+RF_MODE_MAX][5]; + +/*ACELP LTF ELEMENT*/ +extern const Word16 ACELP_LTF_MODE[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX]; +extern const Word16 ACELP_LTF_BITS[4]; + +/*ACELP GAINS ELEMENT*/ +extern const Word16 ACELP_GAINS_MODE[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX]; +extern const Word16 ACELP_GAINS_BITS[10]; + +/*ACELP BPF ADAPT ELEMENT*/ +extern const Word16 ACELP_BPF_MODE[RATE_MODE_MAX][BANDWIDTH_MODE_MAX][ACELP_MODE_MAX+RF_MODE_MAX]; +extern const Word16 ACELP_BPF_BITS[3]; + +extern const Word8 gTcxLpcLsf[3][2]; +extern const Word16 *lsf_means[2]; +typedef Word16 lsp_unw_triplet[3]; +extern const lsp_unw_triplet p16_gamma0_92to1[16]; +extern const lsp_unw_triplet p16_gamma0_94to1[16]; + +extern const Word16 *const lsf_codebook[2][2][TCXLPC_NUMSTAGES]; +extern const Word16 lsf_numbits[TCXLPC_NUMSTAGES]; +extern const Word16 lsf_dims[TCXLPC_NUMSTAGES]; +extern const Word16 lsf_offs[TCXLPC_NUMSTAGES]; +extern const Word16 lsf_q_diff_cb_8b_rf[]; +extern const Word16 lsf_cdk_nb_gc_stg1[]; +extern const Word16 lsf_cdk_nb_gc_stg2[]; +extern const Word16 lsf_cdk_nb_gc_stg3[]; +extern const Word16 lsf_ind_cdk_nb_gc_stg4[]; +extern const Word16 lsf_cdk_nb_vc_stg1[]; +extern const Word16 lsf_cdk_nb_vc_stg2[]; +extern const Word16 lsf_cdk_nb_vc_stg3[]; +extern const Word16 lsf_ind_cdk_nb_vc_stg4[]; +extern const Word16 lsf_cdk_wb_gc_stg1[]; +extern const Word16 lsf_cdk_wb_gc_stg2[]; +extern const Word16 lsf_cdk_wb_gc_stg3[]; +extern const Word16 lsf_ind_cdk_wb_gc_stg4[]; +extern const Word16 lsf_cdk_wb_vc_stg1[]; +extern const Word16 lsf_cdk_wb_vc_stg2[]; +extern const Word16 lsf_cdk_wb_vc_stg3[]; +extern const Word16 lsf_ind_cdk_wb_vc_stg4[]; + +extern const Word16 *const lsf_ind_codebook[2][2][TCXLPC_IND_NUMSTAGES]; +extern const Word16 lsf_ind_numbits[TCXLPC_IND_NUMSTAGES]; +extern const Word16 lsf_ind_dims[TCXLPC_IND_NUMSTAGES]; +extern const Word16 lsf_ind_offs[TCXLPC_IND_NUMSTAGES]; +extern const Word16 min_distance_thr[2][2]; + +extern const Word16 mean_isf_wb [16]; + +extern const Word16 means_nb_31bits_ma_lsf[16]; +extern const Word16 means_wb_31bits_ma_lsf[16]; + +extern const Word16 maxC_wbhb_31bits_ma_lsf; +extern const Word16 stages_wbhb_31bits_ma_lsf; +extern const Word16 levels_wbhb_31bits_ma_lsf[5]; +extern const Word16 bits_wbhb_31bits_ma_lsf[5]; + +extern const Word16 lsf_fit_model[5][16]; + + +extern const Word16 cdk_wbhb_31bits_ma_lsf_10_p12[1536]; + +extern const Word16 cdk_wbhb_31bits_ma_lsf_20_p12[768]; + +extern const Word16 cdk_wbhb_31bits_ma_lsf_30_p12[768]; + +extern const Word16 cdk_wbhb_31bits_ma_lsf_40_p12[768]; + +extern const Word16 cdk_wbhb_31bits_ma_lsf_50_p12[768]; + +extern const Word16 cdk_wbhb_31bits_ma_lsf_11_p12[1536]; + +extern const Word16 cdk_wbhb_31bits_ma_lsf_21_p12[768]; + +extern const Word16 cdk_wbhb_31bits_ma_lsf_31_p12[768]; + +extern const Word16 cdk_wbhb_31bits_ma_lsf_41_p12[768]; + +extern const Word16 cdk_wbhb_31bits_ma_lsf_51_p12[768]; + +extern const Word16 * const cdk_wbhb_31bits_ma_lsf0[]; +extern const Word16 * const cdk_wbhb_31bits_ma_lsf1[]; + + +extern const Word16 CLDFB80_10[100]; +extern const Word16 CLDFB80_16[160]; +extern const Word16 CLDFB80_20[200]; +extern const Word16 CLDFB80_32[320]; +extern const Word16 CLDFB80_40[400]; +extern const Word16 CLDFB80_60[600]; + +extern const Word16 rRotVectr_10[]; +extern const Word16 iRotVectr_10[]; +extern const Word16 rRotVectr_16[]; +extern const Word16 iRotVectr_16[]; +extern const Word16 rRotVectr_20[]; +extern const Word16 iRotVectr_20[]; +extern const Word16 rRotVectr_32[]; +extern const Word16 iRotVectr_32[]; +extern const Word16 rRotVectr_40[]; +extern const Word16 iRotVectr_40[]; +extern const Word16 rRotVectr_60[]; +extern const Word16 iRotVectr_60[]; + +extern const Word16 cldfb_anaScale[]; +extern const Word16 cldfb_synScale[]; +extern const Word16 cldfb_synGain[]; +extern const Word16 *cldfb_protoFilter_2_5ms[]; +extern const Word16 cldfb_scale_2_5ms[7]; + + +extern const Word16 lag_window_8k[2][16]; +extern const Word16 lag_window_12k8[NUM_LAGW_STRENGTHS][2][16]; +extern const Word16 lag_window_16k[NUM_LAGW_STRENGTHS][2][16]; +extern const Word16 lag_window_25k6[NUM_LAGW_STRENGTHS][2][16]; +extern const Word16 lag_window_32k[NUM_LAGW_STRENGTHS][2][16]; +extern const Word16 lag_window_48k[2][16]; + +/**********************************************************************/ /** +igf settings structure for each bitrate mode +**************************************************************************/ +typedef struct igf_mode_type +{ + Word32 sampleRate; + Word16 frameLength; + Word32 bitRate; + Word16 igfMinFq; + Word16 transFac; + Word16 maxHopsize; +} IGF_MODE,*H_IGF_MODE; + + +extern const IGF_MODE igfMode[15]; +extern const Word16 swb_offset_LB_new[15][IGF_MAX_SFB]; +extern const Word16 igf_whitening_TH[15][2][IGF_MAX_TILES]; + +extern const Word16 cf_off_se01_tab[9]; + +extern const Word16 cf_off_se10_tab; + +extern const Word16 cf_off_se02_tab[9][IGF_CTX_COUNT]; + +extern const Word16 cf_off_se11_tab[IGF_CTX_COUNT][IGF_CTX_COUNT]; +extern const Word16 cf_se00_tab[IGF_SYMBOLS_IN_TABLE + 1]; + +extern const Word16 cf_se01_tab[9][IGF_SYMBOLS_IN_TABLE + 1]; +extern const Word16 cf_se02_tab[4][IGF_CTX_COUNT][IGF_SYMBOLS_IN_TABLE + 1]; + +extern const Word16 cf_se10_tab[IGF_SYMBOLS_IN_TABLE + 1]; +extern const Word16 cf_se11_tab[IGF_CTX_COUNT][IGF_CTX_COUNT][IGF_SYMBOLS_IN_TABLE + 1]; + +extern const Word32 bwMode2fs[4]; + +extern const Word16 kLog2TableFrac_x[256]; +extern const Word16 kExp2TableFrac_x[256]; +extern const Word16 sqrt_table_pitch_search[256+1]; + +extern const Word16 grid50_fx[(GRID50_POINTS-1)/2 - 1]; +extern const Word16 grid40_fx[(GRID40_POINTS-1)/2 - 1]; +/******************** moved over from table_decl.h ************************/ + +/* For pitch predictor */ +#define INTERP_EXP 0 +extern const Word16 pitch_inter4_1[UP_SAMP * L_INTERPOL1 + 1]; /*1Q14*/ +extern const Word16 pitch_inter4_2[PIT_FIR_SIZE2]; /*1Q14*/ +extern const Word16 pitch_inter6_2[PIT_FIR_SIZE6_2]; /*1Q14*/ + +/* For bass postfilter */ +extern const Word16 filt_lp[1 + L_FILT]; +extern const Word16 filt_lp_16kHz[1+L_FILT16k]; + +extern const Word16 L_frame_inv[8]; + +extern const Word16 TecLowBandTable[]; +extern const Word16 TecSC_Fx[]; + +extern const Word16 uniform_model_fx[]; + +/* fft.c */ +extern const Word16 RotVector_32[2*20]; +extern const Word16 RotVector_256[2*(256-32)]; +extern const Word16 RotVector_320[2*(320-20)]; +extern const Word16 RotVector_400[2*(400-20)]; +extern const Word16 RotVector_480[2*(480-30)]; +extern const Word16 RotVector_600[2*(600-30)]; + +extern const Word16 tab_ari_qnew[4][4]; + + +extern const Word16 num_nelp_lp_fx[NELP_LP_ORDER+1]; +extern const Word16 den_nelp_lp_fx[NELP_LP_ORDER+1]; + +/* ACELP pulse coding */ +extern const Word16 hi_to_low_tmpl[10]; +extern const Word16 low_len[10]; +extern const Word32 low_mask[10]; +extern const Word16 indx_fact[10]; +extern const Word16 index_len[3]; +extern const UWord32 index_mask_ACELP[3]; + +extern const Word16 inv_jp2[]; + +#endif /*ROM_COM_H */ + diff --git a/lib_com/scale_mem_fx.c b/lib_com/scale_mem_fx.c new file mode 100644 index 0000000..3f24bef --- /dev/null +++ b/lib_com/scale_mem_fx.c @@ -0,0 +1,346 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Common prototypes */ +#include "prot_fx.h" /* Common prototypes */ +#include "cnst_fx.h" +#include "stl.h" + +/*-------------------------------------------------------------------* + * Rescale_exc: + * + * Find absolute maximum of excitation + * Fin scaling factor to apply the excitation and its related memory + * Scale excitation and total excitation (exc2) + *-------------------------------------------------------------------*/ +Word16 Rescale_exc( + Word16 dct_post_old_exc_fx[], /* i/o: Music post processing memory */ + Word16 exc[], /* i/o: excitation to rescale Q_exc */ + Word16 bwe_exc[], + Word16 *last_exc_dct_in, + Word16 lg, /* i : frame size */ + Word16 lg32, + Word32 L_gain_code, /* i : decoded codebook gain Q16 */ + Word16 *sQ_exc, /* i/o: Excitation scaling factor */ + Word16 *sQsubfr, /* i/o: Past excitation scaling factors */ + Word16 exc2[], /* o : local excitation vector */ + Word16 i_subfr, /* i : subframe number */ + const Word16 coder_type +) +{ + Word16 i, tmp, max, new_Q; + + /*------------------------------------------- + * find maximum of absolute excitation + *-------------------------------------------*/ + max = s_max(abs_s(exc[0]), 1); + FOR (i = 1; i < lg; i++) + { + tmp = abs_s(exc[i]); + max = s_max(max, tmp); + } + + /*---------------------------------------------- + * find scaling (tmp) to set max = [2048..4096[ + *----------------------------------------------*/ + tmp = sub(add(norm_s(max), *sQ_exc), 3); + tmp = s_min(tmp, 12); + + /*---------------------------------------------- + * find scaling (new_Q) to keep gain_code < 2048 + *----------------------------------------------*/ + + new_Q = add(tmp, 1); + tmp = sub(norm_l(L_or(L_gain_code, 1)), 3); /* to get to 0x08000000L (L_or with 1 to avoid norm_l(0)) */ + tmp = s_min(tmp, new_Q); + tmp = s_max(tmp, 0); + tmp = sub(tmp, 1); + + /*#define REMOVE_EXCITATION_PER_FRAME_SCALING */ + + /*---------------------------------------------- + * new_Q = smallest Q since 4 subframes (20ms) + *----------------------------------------------*/ + IF( EQ_16( coder_type, TRANSITION )) + { + tmp = s_min(tmp, 7); + } + ELSE IF (EQ_16(coder_type,INACTIVE)) + { + tmp = s_min(tmp, 13); + } + ELSE IF( GT_16(lg,L_SUBFR))/* --> can only happen in AUDIO mode */ + { + tmp = s_min(tmp, 4); /* Limitation of the scaling gain because the frequency domain will add much more energy to the excitation*/ + if( GE_32(L_abs(L_gain_code), 3276800)) /*(1-gain_pit)*past gain code*4 > 50 */ + { + tmp = s_min(tmp, 2); /* Limitation of the scaling gain because the frequency domain might add much more energy to the excitation*/ + } + } + + new_Q = s_min(tmp, sQsubfr[0]); + IF(EQ_16(lg, L_SUBFR)) + { + FOR(i = L_Q_MEM-1; i >= 1; i--) + { + new_Q = s_min(new_Q, sQsubfr[i]); + sQsubfr[i] = sQsubfr[i-1]; + move16(); + } + } + ELSE + { + IF(EQ_16(lg, 2*L_SUBFR)) + { + new_Q = s_min(new_Q, sQsubfr[L_Q_MEM-1]); + FOR(i = L_Q_MEM-1; i >= 2; i--) + { + sQsubfr[i] = sQsubfr[1]; + move16(); + } + sQsubfr[1] = tmp; + move16(); + sQsubfr[0] = tmp; + move16(); + } + ELSE + { + set16_fx(sQsubfr, tmp, L_Q_MEM); + } + } + sQsubfr[0] = tmp; + move16(); + + /*---------------------------------------------- + * rescale excitation and associated memories + *----------------------------------------------*/ + + tmp = sub(new_Q, *sQ_exc); + + IF (tmp != 0) + { + + Scale_sig(exc-L_EXC_MEM_DEC, add(L_EXC_MEM_DEC, lg), tmp); + IF(last_exc_dct_in != NULL) + { + Scale_sig(last_exc_dct_in, L_FRAME, tmp); + } + IF(bwe_exc != NULL) + { + Scale_sig(bwe_exc-PIT16k_MAX*2, add(PIT16k_MAX*2, lg32), tmp); + } + IF(exc2 != NULL) + { + Scale_sig(exc2, i_subfr, tmp); + } + IF(dct_post_old_exc_fx != NULL) + { + Scale_sig(dct_post_old_exc_fx, DCT_L_POST-OFFSET2, tmp); + } + } + + /* scaling factor of excitation (-1..12) */ + *sQ_exc = new_Q; + move16(); + + return tmp; +} + +/*-------------------------------------------------------------------* + * Rescale_mem: + * + * this function should be called after excitation update (4 subfr) and before frame synthesis + * Rescale excitation related memories + *-------------------------------------------------------------------*/ +void Rescale_mem( + const Word16 Q_exc, /* i : current excitation scaling (>=0) */ + Word16 *prev_Q_syn, /* i/o : scaling factor of previous frame */ + Word16 *Q_syn, /* i/o : scaling factor of frame */ + Word16 *mem_syn2, /* i/o : modified synthesis memory */ + Word16 *mem_syn_clas_estim_fx, /* i/o : old 12k8 core memory for classification */ + const Word16 MaxScaling, /* i: Minimal difference between excitation scaling and synthesis scaling */ + Word16 *mem_deemph, /* i/o: speech deemph filter memory */ + Word16 *pst_old_syn, /* i/o: psfiler */ + Word16 *pst_mem_deemp_err, /* i/o: psfiler */ + Word16 *mem_agc, + PFSTAT *pf_stat, /* i/o: All memories related to NB post filter */ + const Word16 Vad_flag, + const Word16 Cna_flag, + const Word16 *tmp_buffer /* tmp_buffer in Q-1 */ +) +{ + Word16 exp_scale, new_Q, tmp, i; + + /*-------------------------------------------------------------------* + * find scaling of synthesis (based on min of current frame and last frame) + * scaling factor of synthesis (-1..6) + *-------------------------------------------------------------------*/ + new_Q = sub(Q_exc, MaxScaling); + tmp = 1; + move16(); + IF(tmp_buffer != NULL) + { + /* use the temporary synthesis in Q-1 to estimate the scaling */ + FOR (i = 0; i < L_FRAME; i++) + { + tmp = s_max(abs_s(tmp_buffer[i]), tmp); + } + /* we add Q_syn which represents the actual scaling of the memories prev_Q_syn represents the last potential scaling */ + tmp = sub(add(norm_s(tmp), -1), 3); /* -2 ... 12 */ + } + ELSE + { + FOR (i = 0; i < M; i++) + { + tmp = s_max(abs_s(mem_syn2[i]), tmp); + tmp = s_max(abs_s(pst_old_syn[i]), tmp); + tmp = s_max(abs_s(mem_syn_clas_estim_fx[i]), tmp); + } + FOR (; i < L_SUBFR; i++) + { + tmp = s_max(abs_s(pst_old_syn[i]), tmp); + tmp = s_max(abs_s(mem_syn_clas_estim_fx[i]), tmp); + } + FOR (; i < L_SYN_MEM_CLAS_ESTIM; i++) + { + tmp = s_max(abs_s(mem_syn_clas_estim_fx[i]), tmp); + tmp = s_max(abs_s(pst_old_syn[i]), tmp); + } + FOR (; i < NBPSF_PIT_MAX; i++) + { + tmp = s_max(abs_s(pst_old_syn[i]), tmp); + } + /* we add Q_syn which represents the actual scaling of the memories prev_Q_syn represents the last potential scaling */ + tmp = sub(add(norm_s(tmp), *Q_syn), 2); /* -2 ... 12 */ + } + + + IF(Vad_flag != 0) + { + new_Q = s_min(sub(Q_exc,2), tmp); + } + ELSE IF(Cna_flag != 0) + { + new_Q = s_min(Q_exc, sub(tmp, 2)); + } + ELSE + { + new_Q = s_min(Q_exc, tmp); + } + new_Q = s_min(new_Q, 12); /* */ + new_Q = s_max(new_Q, -1); /* */ + + /*#define REMOVE_SYNTHESIS_PER_FRAME_SCALING */ + tmp = s_min(new_Q, *prev_Q_syn); + *prev_Q_syn = new_Q; + move16(); + + exp_scale = sub(tmp, *Q_syn); + *Q_syn = tmp; + move16(); + + /* rescale synthesis memory (mem_syn2) */ + Scale_sig(mem_syn2, M, exp_scale); + Scale_sig(mem_syn_clas_estim_fx, L_SYN_MEM_CLAS_ESTIM, exp_scale); + /*Scale_sig(core_old_syn, L_SYN_MEM, exp_scale);*/ + Scale_sig(mem_deemph, 1, exp_scale); + Scale_sig(pst_old_syn, NBPSF_PIT_MAX, exp_scale); + Scale_sig(pst_mem_deemp_err, 1, exp_scale); + Scale_sig(pf_stat->mem_pf_in, L_SUBFR, exp_scale); /* NB post_filter mem */ + Scale_sig(pf_stat->mem_res2, DECMEM_RES2, exp_scale); /* NB post_filter mem */ + Scale_sig(pf_stat->mem_stp, L_SUBFR, exp_scale); /* NB post_filter mem */ + Scale_sig(mem_agc, 1, exp_scale); /* NB post_filter mem */ + return; +} + +/*-------------------------------------------------------------------* + * Scale_sig32 + * Note: In order to save complexity, call function only, if exp0 != 0 + * Up/down scale a 32 bits vector + *-------------------------------------------------------------------*/ +void scale_sig32( + Word32 x[], /* i/o: signal to scale Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx exp */ +) +{ + Word16 i; + + FOR (i = 0; i < lg; i++) + { + /* saturation can occur here */ + x[i] = L_shl(x[i], exp0); + move32(); + } +} + + +/*-------------------------------------------------------------------* + * Rescale_mem: + * + * this function should be called after excitation update (4 subfr) and before frame synthesis + * Rescale excitation related memories + *-------------------------------------------------------------------*/ +Word16 rescale_mem( + const Word16 *Q_exc, /* i : current excitation scaling (>=0) */ + Word16 *prev_Q_syn, /* i/o : scaling factor of previous frame */ + Word16 *Q_syn, /* i/o : scaling factor of frame */ + Word16 *mem_syn2, /* i/o : modified synthesis memory */ + Word16 *syn, /* i/o : synthesis to rescale Q_syn */ + Word16 mem_len, /* i : lenght of modified synthesis memory */ + Word16 i_subfr /* i : subframe number */ +) +{ + Word16 exp_scale, new_Q, tmp; + Word16 i, max16, max_scale; + + max16 = 0; + move16(); + FOR (i = 0; i < mem_len; i++ ) + { + max16 = s_max(max16, abs_s(mem_syn2[i])); + } + IF( syn != NULL ) + { + FOR (i = 0; i < i_subfr; i++ ) + { + max16 = s_max(max16, abs_s(syn[i])); + } + } + max_scale = 15; + move16(); + IF(max16 > 0) + { + max_scale = add(norm_s(max16), -3); + } + + /*-------------------------------------------------------------------* + * find scaling of synthesis (based on min of current frame and last frame) + * scaling factor of synthesis (-1..6) + *-------------------------------------------------------------------*/ + new_Q = sub(*Q_exc, 3); + new_Q = s_max(new_Q, -1); + + tmp = add(max_scale, *Q_syn); + if( GT_16(s_min(new_Q, *prev_Q_syn), tmp)) + { + new_Q = s_max(tmp, -1); + } + + tmp = s_min(new_Q, *prev_Q_syn); + *prev_Q_syn = new_Q; + move16(); + + exp_scale = sub(tmp, *Q_syn); + *Q_syn = tmp; + move16(); + /* rescale synthesis memory (mem_syn2) */ + Scale_sig(mem_syn2, mem_len, exp_scale); + IF(syn != NULL) + { + Scale_sig(syn, i_subfr, exp_scale); + } + + return exp_scale; +} diff --git a/lib_com/stab_est_fx.c b/lib_com/stab_est_fx.c new file mode 100644 index 0000000..d85fe5b --- /dev/null +++ b/lib_com/stab_est_fx.c @@ -0,0 +1,245 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required for wmc_tool */ +#include "basop_mpy.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define BIN_4000 80 /* The frequency bin corresponding to 4kHz */ +#define MAX_BANDEXC 20 + +#define NB_TH3_MIN 30 +#define NB_TH1_MIN 30 + +#define TH_0_MAX_FX 9600 /* Q11 -> 1.5*3.125 */ +#define TH_1_MAX_FX 8640 /* Q11 -> 1.5*2.8125 */ +#define TH_2_MAX_FX 6720 /* Q11 -> 1.5*2.1875 */ +#define TH_3_MAX_FX 5760 /* Q11 -> 1.5*1.875 */ + +#define TH_UP_FX 320 /* Q11 -> 0.15625 */ +#define TH_DW_FX 320 /* Q11 -> 0.15625 */ + +/*------------------------------------------------------------------------* + * stab_est() + * + * Signal stability estimation based on energy variation + *------------------------------------------------------------------------*/ + +Word16 stab_est_fx( + Word16 etot, /* i : Total energy of the current frame */ + Word16 *lt_diff_etot, /* i/o : Long term total energy variation */ + Word16 *mem_etot, /* i/o : Total energy memory */ + Word16 *nb_thr_3, /* i/o : Number of consecutives frames of level 3 */ + Word16 *nb_thr_1, /* i/o : Number of consecutives frames of level 1 */ + Word16 *thresh, /* i/o : Detection thresold */ + Word16 *last_music_flag,/* i/o : Previous music detection ouptut */ + Word16 vad_flag +) +{ + Word16 i, music_flag2, tmp16, exp1, exp2; + Word16 mean_diff; + Word16 dev; + Word32 L_tmp; + + /*------------------------------------------------------------------------* + * Find mean of the past MAX_LT frames energy variation + *------------------------------------------------------------------------*/ + + L_tmp = L_deposit_l(0); + FOR (i = 1; i 1/25 (1/(MAX_LT-15))*/ + + exp1 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, exp1); + tmp16 = round_fx(L_tmp); + + exp2 = sub(31, exp1); + L_tmp = Isqrt_lc(L_tmp, &exp2); + L_tmp = Mpy_32_16_1(L_tmp, tmp16); /* we now have sqrt(L_corr) Q24 (8+16)*/ + exp2 = sub(31-15, sub(exp1, exp2)); /* for Q8 (because of -8^2 from Etot)*/ + + L_tmp = L_shl(L_tmp, exp2); /* Q8 + Q16*/ + dev = extract_h(L_shl(L_tmp, 3)); /* Q(24+3-16) -> Q11 */ + + /*------------------------------------------------------------------------* + * State machine to decide level of inter-harmonic noise reduction and + * (only if this frame is GOOD or if we are already far from NB_BFI_THR) + * (if music_flag2 is 0, the spectral modification is deactivated, otherwise, it is activated) + *------------------------------------------------------------------------*/ + + music_flag2 = 0; + move16();/* deactivate spectral modification (if music_flag2 != 0 is activated) */ + test(); + /*--------------------------------------------------------------------* + * statistical deviation < thresh3 and last signal category type >= 3 + * (last category was "tonal" and the new one is "very tonal") + *--------------------------------------------------------------------*/ + test(); + test(); + test(); + IF ((LT_16(dev, thresh[3]))&&(GE_16(*last_music_flag,3))) + { + music_flag2 = 4; + move16(); + *nb_thr_3 += 1; + move16(); + *nb_thr_1 = 0; + move16(); + } + + /*--------------------------------------------------------------------* + * statistical deviation < thresh2 and last signal category type >= 2 + * (last category was "moderatly tonal" and the new one is a "tonal" ) + *--------------------------------------------------------------------*/ + ELSE IF ((LT_16(dev, thresh[2]))&&(GE_16(*last_music_flag,2))) + { + music_flag2 = 3; + move16(); + *nb_thr_3 += 1; + move16(); + *nb_thr_1 = 0; + move16(); + } + + /*--------------------------------------------------------------------* + * statistical deviation < thresh1 and last signal category type >= 1 + * (last category was "slightly tonal" and the new one is a "moderatly tonal") + *--------------------------------------------------------------------*/ + ELSE IF ((LT_16(dev, thresh[1]))&&(GE_16(*last_music_flag,1))) + { + music_flag2 = 2; + move16(); + } + + /*--------------------------------------------------------------------* + * statistical deviation < thresh0 + * (last category was "not tonal" and the new one is "slightly tonal") + *--------------------------------------------------------------------*/ + ELSE IF ((LT_16(dev, thresh[0]))) + { + music_flag2 = 1; + move16();/* [2000, 4000] Hz */ + } + + /*--------------------------------------------------------------------* + * statistical deviation > thresh0 + * (Statistical deviation is high: the new tonal category is not tonal) + *--------------------------------------------------------------------*/ + ELSE + { + *nb_thr_1 = add(*nb_thr_1,1); + *nb_thr_3 = 0; + move16(); + + } + + /*------------------------------------------------------------------------* + * Update the thresholds + *------------------------------------------------------------------------*/ + IF (GT_16(*nb_thr_3,NB_TH3_MIN)) + { + + /* the number of consecutive categories type 3 or 4 (most tonal and tonal) */ + /* is greater than 30 frames ->increase the deviations thresholds to allow more variation */ + thresh[0] = add(thresh[0], TH_UP_FX); + move16(); /*Q11 */ + thresh[1] = add(thresh[1], TH_UP_FX); + move16(); + thresh[2] = add(thresh[2], TH_UP_FX); + move16(); + thresh[3] = add(thresh[3], TH_UP_FX); + move16(); + + } + ELSE IF (GT_16(*nb_thr_1,NB_TH1_MIN)) + { + /* the number of consecutive categories type 0 (non tonal frames) */ + /* is greater than 30 frames -> decrease the deviations thresholds to allow less variation */ + thresh[0] = sub(thresh[0], TH_DW_FX); + move16(); /*Q11 */ + thresh[1] = sub(thresh[1], TH_DW_FX); + move16(); + thresh[2] = sub(thresh[2], TH_DW_FX); + move16(); + thresh[3] = sub(thresh[3], TH_DW_FX); + move16(); + } + + /* limitation of the threshold (this local macro stores the highest of the two and it also + counts the # of operations) */ + + move16(); + move16(); + move16(); + thresh[0] = s_max(thresh[0], TH_0_MIN2_FX); + thresh[1] = s_max(thresh[1], TH_1_MIN2_FX); + thresh[2] = s_max(thresh[2], TH_2_MIN2_FX); + + move16(); + move16(); + move16(); + thresh[0] = s_min(thresh[0], TH_0_MAX_FX); + thresh[1] = s_min(thresh[1], TH_1_MAX_FX); + thresh[2] = s_min(thresh[2], TH_2_MAX_FX); + move16(); + move16(); + thresh[3] = s_max(thresh[3], TH_3_MIN2_FX); + thresh[3] = s_min(thresh[3], TH_3_MAX_FX); + /*------------------------------------------------------------------------* + * Final update + *------------------------------------------------------------------------*/ + + *last_music_flag = music_flag2; + move16(); + if (vad_flag == 0) + { + + music_flag2 = 0; + move16(); + } + + return music_flag2; +} diff --git a/lib_com/stat_com.h b/lib_com/stat_com.h new file mode 100644 index 0000000..640bde1 --- /dev/null +++ b/lib_com/stat_com.h @@ -0,0 +1,676 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#ifndef STAT_COM_H +#define STAT_COM_H + +#include "options.h" +#include "basop_util.h" +#include "cnst_fx.h" + +/*----------------------------------------------------------------------------------* + * Declaration of structures + *----------------------------------------------------------------------------------*/ + +/* Forward declaration of Decoder_State_fx */ +struct Decoder_State_fx; + +/*-----------------------------------------------------------* + * EV-VBR NB postfilter static variables + *-----------------------------------------------------------*/ +typedef struct +{ + Word16 on; /* On/off flag */ + Word16 reset; /* reset flag */ + Word16 mem_pf_in[L_SUBFR]; /* Input memory */ + Word16 mem_stp[L_SUBFR]; /* 1/A(gamma1) memory */ + Word16 mem_res2[DECMEM_RES2]; /* A(gamma2) residual */ + Word16 mem_zero[M]; /* null memory to compute i.r. of A(gamma2)/A(gamma1) */ + Word16 gain_prec; /* for gain adjustment */ +} PFSTAT; + +typedef struct +{ + Word16 a_fx[MAXLAG_WI]; + Word16 b_fx[MAXLAG_WI]; + Word16 lag_fx; + Word16 nH_fx; + Word16 nH_4kHz_fx; + Word16 upper_cut_off_freq_of_interest_fx; + Word16 upper_cut_off_freq_fx; + Word16 Fs_fx; + Word16 Q; +} DTFS_STRUCTURE_FX; + +typedef struct +{ + Word16 lead_sign_ind; + UWord32 index, size; + Word16 dim, k_val; +} PvqEntry_fx; + +typedef struct +{ + UWord8 buf[MAX_SIZEBUF_PBITSTREAM]; + Word16 curPos; + Word32 numByte; + Word32 numbits; + Word32 maxBytes; +} BITSTREAM_FX, *PBITSTREAM_FX; + +typedef struct +{ + PBITSTREAM_FX bsInst; + + Word32 low; + Word32 high; + + Word32 value; + Word16 bits_to_follow; + + Word32 num_bits; + Word32 max_bits; + +} ARCODEC_FX, *PARCODEC_FX; + +/*---------------------------------------------------------------* + * Encoder/Decoder Static RAM * + *---------------------------------------------------------------*/ +typedef struct +{ + /*Coding mode info*/ + Word16 mode_index; + + /*LPC info*/ + Word8 midLpc; /*Flag for using or not mid LPC for the current frame*/ + Word8 midLpc_enable; /*Flag enabling or not the mid LPC for the current mode_index*/ + + /*ICB flags*/ + Word8 pre_emphasis; + Word8 pitch_sharpening; /*Flag for triggering pitch sharpening*/ + Word8 phase_scrambling; /*Flag for triggering phase scrambling*/ + Word16 formant_enh; /*Flag for triggering formant enhancement: Q15 representing 0...1.0f */ + Word8 formant_tilt; + + Word8 voice_tilt; /*Flag for triggering new voice factor tilt*/ + + Word16 formant_enh_num; + Word16 formant_enh_den; + + Word16 bpf_mode; + + Word16 nrg_mode; + Word16 nrg_bits; + + Word16 ltp_mode; + Word16 ltp_bits; + + Word16 ltf_mode; + Word16 ltf_bits; + + Word16 gains_mode[NB_SUBFR16k]; + + Word16 fixed_cdk_index[NB_SUBFR16k]; + +} ACELP_config; + +/*tns_base.h*/ +/** TNS configuration. + * Use InitTnsConfiguration to initialize it. + */ +typedef struct +{ + Word16 maxOrder; + + /** Maximum number of filters. */ + Word16 nMaxFilters; + + /** Parameters for each TNS filter */ + struct TnsParameters const * pTnsParameters; + + /** Lower borders for each filter. + * Upper border for the first filter is nsbBorders-1. + * Upper borders for other filters is the lower border of previous filter. + */ + Word16 iFilterBorders[TNS_MAX_NUM_OF_FILTERS+1]; + +} STnsConfig; + +/** TNS filter. + * Parameters that define a TNS filter. + */ +typedef struct +{ + /** Number of subbands covered by the filter. */ + Word16 spectrumLength; + /** Filter order. */ + Word16 order; + /** Quantized filter coefficients. */ + Word16 coefIndex[TNS_MAX_FILTER_ORDER]; + /** Prediction gain. The ratio of a signal and TNS residual energy. */ + Word16 predictionGain; /* exponent = PRED_GAIN_E */ + /** Average squared filter coefficient. */ + Word16 avgSqrCoef; /* exponent = 0 */ +} STnsFilter; + +/** TNS data. + * TNS data describing all active filters. + */ +typedef struct +{ + /** Number of active filters. */ + Word16 nFilters; + /** Active filters. */ + STnsFilter filter[TNS_MAX_NUM_OF_FILTERS]; +} STnsData; + +typedef enum +{ + TNS_NO_ERROR = 0, + TNS_FATAL_ERROR +} TNS_ERROR; + +typedef struct +{ + /* TCX mdct window */ + const PWord16 *tcx_mdct_window; + const PWord16 *tcx_mdct_window_half; + const PWord16 *tcx_mdct_window_minimum; + const PWord16 *tcx_mdct_window_trans; + Word16 tcx_aldo_window_1[L_FRAME32k*9/32]; + PWord16 tcx_aldo_window_1_trunc[L_FRAME32k*7/32]; + PWord16 tcx_aldo_window_2[L_FRAME32k*7/32]; + Word16 last_aldo; + + Word16 tcx5Size; /* Size of the TCX5 spectrum. Always 5ms. */ + + Word16 tcx_mdct_window_length; + Word16 tcx_mdct_window_half_length; /*length of the "half" overlap window*/ + Word16 tcx_mdct_window_min_length; /* length of the "minimum" overlap */ + Word16 tcx_mdct_window_trans_length; /* length of the ACELP->TCX overlap */ + + Word16 tcx_mdct_window_delay; /*length of window delay*/ + + Word16 tcx_offset; + Word16 tcx_mdct_window_length_old; /*for keeping old value for sample rate switching */ + + /* TCX mdct window */ + const PWord16 *tcx_mdct_windowFB; + const PWord16 *tcx_mdct_window_halfFB; + const PWord16 *tcx_mdct_window_minimumFB; + const PWord16 *tcx_mdct_window_transFB; + Word16 tcx_aldo_window_1_FB[L_FRAME_MAX*9/32]; + PWord16 tcx_aldo_window_1_FB_trunc[L_FRAME_MAX*7/32]; + PWord16 tcx_aldo_window_2_FB[L_FRAME_MAX*7/32]; + + Word16 tcx5SizeFB; /* Size of the TCX5 spectrum. Always 5ms. */ + + Word16 tcx_mdct_window_lengthFB; + Word16 tcx_mdct_window_half_lengthFB; /*length of the "half" overlap window*/ + Word16 tcx_mdct_window_min_lengthFB; /* length of the "minimum" overlap */ + Word16 tcx_mdct_window_trans_lengthFB; /* length of the ACELP->TCX overlap */ + + Word16 tcx_mdct_window_delayFB; /*length of window delay*/ + Word16 tcx_offsetFB; + + Word16 tcx_coded_lines; /* max number of coded lines, depending on bandwidth mode */ + + Word16 tcx_curr_overlap_mode; /* window overlap of current frame (0: full, 2: none, or 3: half) */ + Word16 tcx_last_overlap_mode; /* previous window overlap, i.e. left-side overlap of current frame */ + + /* FAC window */ + Word16 lfacNext; + Word16 lfacNextFB; + + /* TNS */ + Word8 fIsTNSAllowed; + STnsConfig tnsConfig[2][2]; + STnsConfig const * pCurrentTnsConfig; + + /*Quantization*/ + Word16 sq_rounding; /*set the sq deadzone (no deadzone=0.5f)*/ + Word8 tcxRateLoopOpt; + + /*Bandwidth*/ + Word16 preemph_fac; /*preemphasis factor*/ + Word16 bandwidth; + + /* Context HM - Residual Quantization*/ + Word8 ctx_hm; /*Flag for enabling Context HM*/ + Word8 resq; /*Flag for enabling Residual Quantization*/ + Word16 coder_type; /*INACTIVE, UNVOICED,VOICED,GENERIC*/ + + Word16 na_scale; + + Word32 SFM2; +} TCX_config; + +/* prot.h */ +typedef struct +{ + Word16 bits; /* bits per subframe */ + Word16 nbiter; /* number of iterations */ + Word16 alp; /* initial energy of all fixed pulses, exponent = ALP_E */ + Word8 nb_pulse; /* number of pulses */ + Word8 fixedpulses; /* number of pulses whose position is determined from correlation and not by iteration */ + Word8 nbpos[13]; /* number of positions tried in the pair-wise search */ + Word8 codetrackpos; /* ordering of tracks -mode */ +} PulseConfig; + +/* fd_cng_common.h */ +/* CLDFB-based CNG setup */ +typedef struct +{ + Word16 fftlen; /* FFT length */ + Word16 stopFFTbin; /* Number of FFT bins to be actually processed */ + Word16 numPartitions; /* Number of partitions */ + const Word16* sidPartitions; /* Upper boundaries for grouping the (sub)bands into partitions when transmitting SID frames (define as NULL pointer to avoid grouping) */ + + Word16 numShapingPartitions; /* Number of partitions */ + const Word16* shapingPartitions; /* Upper boundaries for grouping the (sub)bands into partitions for shaping at the decoder (define as NULL pointer to avoid grouping) */ +} FD_CNG_SETUP; + +/* Scale setup */ +typedef struct +{ + Word32 bitrateFrom; + Word32 bitrateTo; + + Word16 scale; + + Word8 bwmode; + +} SCALE_SETUP; + +/* Arrays and variables common to encoder and decoder */ +typedef struct +{ + FD_CNG_SETUP FdCngSetup; + + Word16 numSlots; /* Number of time slots in CLDFB matrix */ + Word16 regularStopBand;/* Number of CLDFB bands to be considered */ + + Word16 numCoreBands; /* Number of core bands to be decomposed into FFT subbands */ + Word16 stopBand; /* Total number of (sub)bands to be considered */ + Word16 startBand; /* First (sub)band to be considered */ + Word16 stopFFTbin; /* Total number of FFT subbands */ + Word16 frameSize; /* Frame size in samples */ + Word16 fftlen; /* FFT length used for the decomposition */ + Word16 fftlenShift; + Word16 fftlenFac; + + Word16 timeDomainBuffer[L_FRAME16k]; + + Word32 fftBuffer[FFTLEN]; + Word16 *olapBufferAna; /* points to FD_CNG_DEC->olapBufferAna[320] in case of decoder */ + Word16 olapBufferSynth[FFTLEN]; + Word16 *olapBufferSynth2; /* points to FD_CNG_DEC->olapBufferSynth2[FFTLEN] in case of decoder */ + const PWord16 * olapWinAna; + const PWord16 * olapWinSyn; + + Word16 msM_win; + Word16 msM_subwin; + Word16 msFrCnt_init_counter; /* Frame counter at initialization */ + Word16 init_old; + + Word16 msFrCnt_init_thresh; + + Word16 msFrCnt; /* Frame counter */ + Word32 msAlphaCor[2]; /* Correction factor (smoothed) */ + Word16 msSlope[2]; + Word32 msQeqInvAv[2]; + Word16 msQeqInvAv_exp[2]; + Word16 msMinBufferPtr; + + Word32 msPsdSum[2]; + Word32 msPeriodogSum[2]; + Word16 msPeriodogSum_exp[2]; + + Word16 offsetflag; + + Word32 periodog[PERIODOGLEN]; /* Periodogram */ + Word16 periodog_exp; + Word16 exp_cldfb_periodog; + + Word32 cngNoiseLevel[FFTCLDFBLEN]; /* Noise level applied for the CNG in each (sub)band */ + Word16 cngNoiseLevelExp; + Word16 seed; /* Seed memory (for random function) */ + + Word16 npart; /* Number of partitions */ + Word16 midband[NPART]; /* Central band of each partition */ + Word16 nFFTpart; /* Number of hybrid spectral partitions */ + Word16 part[NPART]; /* Partition upper boundaries (band indices starting from 0) */ + Word16 psize[NPART]; /* Partition sizes */ + Word16 psize_norm[NPART]; /* Partition sizes, fractional variable */ + Word16 psize_norm_exp; /* Partition sizes exponent for fractional variable */ + Word16 psize_inv[NPART]; /* Inverse of partition sizes */ + Word16 FFTscalingFactor; /* Squared ratio between core signal analysis FFT and noise estimator FFT */ + Word16 scalingFactor; + Word16 invScalingFactor; + Word16 nCLDFBpart; /* Number of CLDFB spectral partitions */ + Word16 CLDFBpart[NPARTCLDFB]; /* CLDFB Partition upper boundaries (band indices starting from 0 above the core coder bands) */ + Word16 CLDFBpsize_inv[NPARTCLDFB];/* Inverse of CLDFB partition sizes */ + + Word16 inactive_frame_counter; + Word16 sid_frame_counter; + Word16 active_frame_counter; + + Word32 sidNoiseEst[NPART]; /* Transmitted noise level */ + Word16 sidNoiseEstExp; + + Word16 frame_type_previous; + + Word16 A_cng[M+1]; + Word16 exc_cng[L_FRAME16k]; + + Word32 CngBitrate; + Word16 CngBandwidth; + + Word16 flag_noisy_speech; + Word16 likelihood_noisy_speech; +} +FD_CNG_COM; +typedef FD_CNG_COM *HANDLE_FD_CNG_COM; + +/*parameter_bitmaping.h*/ +/** Function that gets specific value from p. + * @param p Pointer to a variable that can also be structure or array. + * @param index Index of a variable when p is an array, otherwise 0. + * @param pValue Pointer to the value. + * @return Substructure associated with this value or NULL if there is none. + */ +typedef void const * (* TGetParamValue)(void const * p, Word16 index, Word16 * pValue); + +/** Function that puts specific value to p. + * @param p Pointer to a variable that can also be structure or array. + * @param index Index of a variable when p is an array, otherwise 0. + * @param value The value. + * @return Substructure associated with this value or NULL if there is none. + */ +typedef void * (* TSetParamValue)(void * p, Word16 index, Word16 value); + +/** Function that return required number of bits for a value when it is coded. + * @param value The value. + * @param index Index of a variable when it is an element of an array, otherwise 0. + * @return Number of bits required to code the value. + */ +typedef Word16 (* TGetNumberOfBits)(Word16 value, Word16 index); + +/** Function that encodes a value. + * @param value The value. + * @param index Index of a variable when it is an element of an array, otherwise 0. + * @return Coded value. + */ +typedef Word16 (* TEncodeValue)(Word16 value, Word16 index); + +/** Function that decodes a value. + * @param st Decoder state. + * @param index Index of a variable when it is an element of an array, otherwise 0. + * @param pValue A pointer where the decoded value should be stored. + * @return Number of bits read from the bitstream. + */ +typedef Word16 (* TDecodeValue)(struct Decoder_State_fx *st, Word16 index, Word16 * pValue); + +/** Structure that defines mapping between a parameter and a bistream. */ +typedef struct ParamBitMap +{ + /** Number of bits in a bitstream required for the parameter. + * If nBits is equal to 0 then GetNumberOfBits is used. + */ + Word16 nBits; + /** Function to get the number of bits required for a value of this parameter. + * If nBits != 0 it is not used and can be set to NULL. + * If fZeroAllowed == 0 then GetNumberOfBits must take care of this. + */ + TGetNumberOfBits GetNumberOfBits; + /** If fZeroAllowed is 0 then the value can be zero. + * If the value can't be zero then value-1 is stored in a bitstream. + * If EncodeValue is not equal to NULL, then the encode/decode function + * must take care of this flag - there is no additional processing in parameter bitmapping. + * If EncodeValue is equal to NULL, then the encode/decode function takes care of this. + */ + Word8 fZeroAllowed; + /** Function to get the value of this parameter. + * The function returns a pointer to be used in functions in pSubParamBitMap. + * If the function returns NULL then the same pointer as for the current + * parameter is to be used. + * The function should not do any additional processing if fZeroAllowed == 0, + * but just set the value as it is. + */ + TGetParamValue GetParamValue; + /** Function to set the value of this parameter. + * The function returns a pointer to be used in functions in pSubParamBitMap. + * If the function returns NULL then the same pointer as for the current + * parameter is to be used. + * The function should not do any additional processing if fZeroAllowed == 0, + * but just set the value as it is. + */ + TSetParamValue SetParamValue; + + /** Function to encode a value of this parameter. + * When it is equal to NULL, fixed-width coding is used. + * If fZeroAllowed == 0 then EncodeValue must take care of this. + */ + TEncodeValue EncodeValue; + + /** Function to decode a value of this parameter. + * When it is equal to NULL, fixed-width coding is used. + * If fZeroAllowed == 0 then DecodeValue must take care of this. + */ + TDecodeValue DecodeValue; + + /** Pointer to the map for substructure. + * The number of structures is determined by this parameter's value. + * NULL means that there is no substructure. + */ + struct ParamsBitMap const * pSubParamBitMap; +} ParamBitMap; + +/** Structure that defines mapping between parameters and a bistream. */ +typedef struct ParamsBitMap +{ + /** Number of parameters in params. */ + Word16 nParams; + /** Definition of the mapping for each parameter. */ + ParamBitMap params[NPARAMS_MAX]; +} ParamsBitMap; + +/*tns_tables.h*/ +struct TnsParameters +{ + /* Parameters for each TNS filter */ + Word16 startLineFrequency; /* Starting lower frequency of the TNS filter [20..16000] */ + Word16 nSubdivisions; /* Number of spectrum subdivisions in which the filter operates [1..8) */ + Word16 minPredictionGain; /* Minimum prediction gain required to turn on the TNS filter. Exponent = PRED_GAIN_E */ + Word16 minAvgSqrCoef; /* Minimum average square of coefficients required to turn on the TNS filter. Exponent = 0 */ +}; + +/**********************************************/ +/* Helper structures for hufmann table coding */ +/**********************************************/ + +typedef struct +{ + Word8 value; + Word16 code; + Word8 nBits; +} Coding; + + +/* Scale TCX setup */ +typedef struct +{ + Word16 bwmode; + + Word32 bitrateFrom; + Word32 bitrateTo; + + Word16 scale; + +} SCALE_TCX_SETUP; + + +/* glob_con.h */ +typedef struct +{ + Word16 frame_bits; /*Bits per frame*/ + Word16 frame_net_bits; /*Net Bits per frame*/ + Word8 transmission_bits; /*max=1*/ + Word8 transmission_mode[2]; /*SID,VBR/CBR*/ + Word8 bandwidth_bits; /*max=2*/ + Word8 bandwidth_min; /*first valid bandwidth (NB,WB,SWB,FB)*/ + Word8 bandwidth_max; /*last valid bandwidth (NB,WB,SWB,FB)*/ + Word8 reserved_bits; /*max=1*/ +} FrameSizeParams; + +typedef struct +{ + Word16 lb_scale; /*!< Scale of low band area */ + Word16 lb_scale16; /*!< Scale of low band area */ + Word16 ov_lb_scale; /*!< Scale of adjusted overlap low band area */ + Word16 hb_scale; /*!< Scale of high band area */ + Word16 ov_hb_scale; /*!< Scale of adjusted overlap high band area */ +} CLDFB_SCALE_FACTOR; + +struct CLDFB_FILTER_BANK +{ + const Word16 *p_filter; /*!< Pointer to filter coefficients */ + + Word16 *FilterStates; /*!< Pointer to buffer of filter states */ + Word16 FilterStates_e[CLDFB_NO_COL_MAX+9]; /*!< Filter states time slot exponents */ + Word16 FilterStates_eg; /*!< Filter states current exponent */ + + Word16 p_filter_length; /*!< Size of prototype filter. */ + const Word16 *rRotVctr; /*!< Modulation tables. */ + const Word16 *iRotVctr; + Word16 filterScale; /*!< filter scale */ + + Word16 synGain; /*!< gain for synthesis filterbank */ + + Word16 no_channels; /*!< Total number of channels (subbands) */ + Word16 no_col; /*!< Number of time slots */ + Word16 lsb; /*!< Top of low subbands */ + Word16 usb; /*!< Top of high subbands */ + Word16 zeros; /*!< number of zeros in filter coefficients */ + + Word16 anaScalefactor; /*!< Scale factor of analysis cldfb */ + Word16 synScalefactor; /*!< Scale factor of synthesis cldfb */ + Word16 outScalefactor; /*!< Scale factor of output data (syn only) */ + + Word16 synFilterHeadroom; /*!< Headroom for states in synthesis cldfb filterbank */ + + UWord16 flags; /*!< flags */ + + Word16 bandsToZero; /*!< additional bands which are zeroed in inverse modulation */ + + Word16 filtermode; + + Word16 type; + Word16 *memory; + Word16 memory_length; + Word16 scale; +}; + +typedef struct CLDFB_FILTER_BANK *HANDLE_CLDFB_FILTER_BANK; + +typedef struct +{ + Word16 pGainTemp_m[CLDFB_NO_COL_MAX]; + Word16 pGainTemp_e[CLDFB_NO_COL_MAX]; + Word16 loBuffer[CLDFB_NO_COL_MAX + MAX_TEC_SMOOTHING_DEG]; + + Word16 cldfbExp; + Word16 lastCldfbExp; +} TEMPORAL_ENVELOPE_CODING_DECODER_FX; +typedef TEMPORAL_ENVELOPE_CODING_DECODER_FX* HANDLE_TEC_DEC_FX; + +typedef struct +{ + Word16 loBuffer[CLDFB_NO_COL_MAX + MAX_TEC_SMOOTHING_DEG + DELAY_TEMP_ENV_BUFF_TEC]; + Word16 loTempEnv[CLDFB_NO_COL_MAX]; + Word16 loTempEnv_ns[CLDFB_NO_COL_MAX]; + Word16 hiTempEnv[CLDFB_NO_COL_MAX + DELAY_TEMP_ENV_BUFF_TEC + EXT_DELAY_HI_TEMP_ENV]; + Word16 tranFlag; + Word16 corrFlag; +} TEMPORAL_ENVELOPE_CODING_ENCODER_FX; +typedef TEMPORAL_ENVELOPE_CODING_ENCODER_FX* HANDLE_TEC_ENC_FX; + +typedef enum +{ + FRAME_0 = 0, + FRAME_2 = 40, + FRAME_2_4 = 48, + FRAME_4 = 80, + FRAME_5_6 = 112, + FRAME_7_2 = 144, + FRAME_8 = 160, + FRAME_9_6 = 192, + FRAME_13_2 = 264, + FRAME_16_4 = 328, + FRAME_24_4 = 488, + FRAME_32 = 640, + FRAME_48 = 960, + FRAME_64 = 1280, + FRAME_96 = 1920, + FRAME_128 = 2560 +} FRAME_SIZE; + +/*---------------------------------------------------------------* + * IGF * + *---------------------------------------------------------------*/ +typedef struct igf_grid_struct +{ + Word16 swb_offset[IGF_MAX_SFB]; + Word16 swb_offset_len; + Word16 startFrequency; + Word16 stopFrequency; + Word16 startLine; + Word16 stopLine; + Word16 startSfb; /* 15Q0, startSfb = [0, 11], IGF start sfb */ + Word16 stopSfb; /* 15Q0, stopSfb = [0, 22], IGF stop sfb */ + Word16 sfbWrap[IGF_MAX_TILES+1]; + Word16 sbWrap[IGF_MAX_TILES]; + Word16 nTiles; /* 15Q0, nTiles = [1, 4], number of tiles */ + Word16 minSrcSubband; + Word16 minSrcFrequency; + Word16 tile[IGF_MAX_TILES]; + Word16 infoIsRefined; + Word16 infoGranuleLen; /* 15Q0, infoGranuleLen = [0, 1200], core coder granule length */ + Word16 infoTransFac; /* 1Q14 */ + Word16 whiteningThreshold[2][IGF_MAX_TILES]; /* 2Q13 */ + Word16 gFactor; /* 1Q14 */ + Word16 fFactor; /* 1Q14 */ + Word16 lFactor; /* 1Q14 */ +} IGF_GRID, *H_IGF_GRID; + +typedef struct IGF_INFO_struct +{ + Word16 nfSeed; + Word32 sampleRate; + Word16 frameLength; + Word16 maxHopsize; + IGF_GRID grid[IGF_NOF_GRIDS]; + Word16 bitRateIndex; +} IGF_INFO, *H_IGF_INFO; + + +typedef struct +{ + Word16 *indexBuffer; + Word16 *peakIndices, *holeIndices; + Word16 numPeakIndices, numHoleIndices; +} CONTEXT_HM_CONFIG; + +/* Returns: index of next coefficient */ +typedef Word16 (*get_next_coeff_function)( + Word16 ii[2], /* i/o: coefficient indexes */ + Word16 *pp, /* o : peak(1)/hole(0) indicator */ + Word16 *idx, /* o : index in unmapped domain */ + CONTEXT_HM_CONFIG *hm_cfg /* i : HM configuration */ +); + +/*CLDFB-VAD*/ + + +#endif diff --git a/lib_com/stat_noise_uv_mod_fx.c b/lib_com/stat_noise_uv_mod_fx.c new file mode 100644 index 0000000..da16a0c --- /dev/null +++ b/lib_com/stat_noise_uv_mod_fx.c @@ -0,0 +1,420 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "cnst_fx.h" /* Function prototypes */ +#include "stl.h" + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define TILT_COMP_LIM_FX 24576 /* 0.75 in Q15 */ +#define GE_SHIFT 6 +#define P1 (32768-ISP_SMOOTHING_QUANT_A1_FX-1) +#define P9 (32767-P1) + +/*---------------------------------------------------------* + * Local functions + *---------------------------------------------------------*/ + +static Word16 calc_tilt_fx(const Word16 *x, const Word16 Q_shift, const Word16 len); +Word32 L_Sqrt_Q0(const Word32 x); +/*--------------------------------------------------------------------* + * stat_noise_uv_mod() + * + * Modifies excitation signal in stationary noise segments + *--------------------------------------------------------------------*/ + +void stat_noise_uv_mod_fx( + const Word16 coder_type, /* i : Coder type */ + Word16 noisiness, /* i : noisiness parameter */ + const Word16 *lsp_old, /* i : old LSP vector at 4th sfr */ + const Word16 *lsp_new, /* i : LSP vector at 4th sfr */ + const Word16 *lsp_mid, /* i : LSP vector at 2nd sfr */ + Word16 *Aq, /* o : A(z) quantized for the 4 subframes */ + Word16 *exc2, /* i/o: excitation buffer */ + Word16 Q_exc, /* i : Q of exc2 excitation buffer [11..-1] expected */ + const Word16 bfi , /* i : Bad frame indicator */ + Word32 *ge_sm, /* i/o: smoothed excitation gain */ + Word16 *uv_count, /* i/o: unvoiced counter */ + Word16 *act_count, /* i/o: activation counter */ + Word16 lspold_s[], /* i/o: old LSP */ + Word16 *noimix_seed, /* i/o: mixture seed */ + Word16 *st_min_alpha, /* i/o: minimum alpha */ + Word16 *exc_pe, /* i/o: scale Q_stat_noise */ + const Word32 bitrate, /* i : core bitrate */ + const Word16 bwidth_fx, /* i : input bandwidth */ + Word16 *Q_stat_noise, /* i/o: noise scaling */ + Word16 *Q_stat_noise_ge /* i/o: noise scaling */ +) +{ + Word16 exctilt; /* Q15 */ + Word32 vare; /* Q31 */ + Word16 randval; /* Q?? */ + Word16 alpha; /* Q15 */ + Word16 alpha_m1; /* (1-alpha) Q15 */ + Word16 min_alpha; /* Q15 */ + Word16 lspnew_s[M]; /* Same for all LSP (Q15) */ + Word16 oldlsp_mix[M]; + Word16 midlsp_mix[M]; + Word16 newlsp_mix[M]; + Word16 beta; /* Q15 */ + Word16 Noimix_fract; /* (noimix_fac - 1.0) in Q15 */ + /* noimix_fax * x <-> x + Noimix_fract * x */ + Word16 i_subfr; + Word16 i, k; + + /* Work variables for div and sqrt */ + Word16 tmp_nom,tmp_den,tmp_shift,tmp_res; + Word16 Qdiff,Q_local; /* new Q to be used for states Exc_pe and Ge_sm, and Exc2_local */ + Word32 L_tmp_res,L_tmp, L_tmp3,L_Ge; + + Word16 En_shift,Tmp; + Word16 Exc2_local[L_FRAME]; /* local_copy in scaled Q_local*/ + + /*---------------------------------------------------------* + * Init local variables + *---------------------------------------------------------*/ + alpha = 32767; + move16(); + min_alpha = 16384; + move16(); + + test(); + test(); + test(); + IF (EQ_16(coder_type,INACTIVE)&&(EQ_32(bitrate,ACELP_9k60)||(LT_32(bitrate,ACELP_9k60)&>_16(bwidth_fx,NB)))) + { + min_alpha = *st_min_alpha; + move16(); + /*---------------------------------------------------------* + * decode noisiness parameter + *---------------------------------------------------------*/ + IF (bfi == 0) + { + tmp_den = 31; + move16(); + tmp_shift = norm_s(tmp_den); + move16(); + L_tmp_res = L_deposit_h(noisiness); + L_tmp_res = L_shl(L_tmp_res,sub(tmp_shift,1)); + tmp_den = shl(tmp_den,tmp_shift); + move16(); + tmp_res = div_l(L_tmp_res,tmp_den); + move16(); + min_alpha = add(tmp_res, 16384); + move16(); + + /**st_min_alpha = sub(*st_min_alpha, 1638); move16();*/ + min_alpha = s_max(min_alpha, sub(*st_min_alpha, 1638)); + + *st_min_alpha = min_alpha; + move16(); + } + } + + /*---------------------------------------------------------* + * Mix excitation signal with random noise + *---------------------------------------------------------*/ + test(); + test(); + test(); + IF ( EQ_16(coder_type,INACTIVE)&&(EQ_32(bitrate,ACELP_9k60)||(LT_32(bitrate,ACELP_9k60)&>_16(bwidth_fx,NB)))) + { + /* use a local working copy for scaling and filtering, not needed if input Q-range is fixed */ + Copy(exc2, Exc2_local, L_FRAME); + + /* bound Q for internal use, optimization possible */ + Q_local = s_min(11, s_max(-1, Q_exc)); + /* local excitation Q and incoming excitation Q*/ + Qdiff = sub(Q_local, Q_exc); + /* only shift if incoming Q is outside [11..-1] shift is done in energy calculations aswell */ + Scale_sig(Exc2_local, L_FRAME, Qdiff); + /* current excitation Q and previous stat_noise states Q */ + Qdiff = sub(Q_local, *Q_stat_noise); + + *Q_stat_noise_ge = GE_SHIFT; + move16(); /* assign the fixed Q for Ge_sm */ + + IF (Qdiff != 0) + { + Scale_sig(exc_pe, 1, Qdiff); + } + + En_shift = 0; + move16(); + if (GT_16(Q_local, 3)) + { + /* increase margin for energy accumulation in calc_tilt and vare accumulation */ + En_shift = sub(Q_local, 3); + } + + IF (LT_16(min_alpha, TILT_COMP_LIM_FX)) + { + FOR (i_subfr=0; i_subfrge_sm = ISP_SMOOTHING_QUANT_A1 * st->ge_sm + (1.0f-ISP_SMOOTHING_QUANT_A1) * ge */ + + IF ( EQ_16(*uv_count,1)) + { + *ge_sm = L_shr(L_Ge,Q_local); + } + ELSE + { + L_tmp = Mult_32_16(L_Ge,P1); /* 0.1*ge still in Q local */ + L_tmp3 = Mult_32_16(*ge_sm,P9); /* 0.9*ge_sm still in Q_ge */ + + *ge_sm = L_add(L_shr(L_tmp,Q_local),L_tmp3); + move32(); /* addition in Q_ge domain*/ + } + + /*--------------------------------------------------------------------* + * generate mixture of excitation and noise + * float: + * noimix_fac = 1.0f/(float)sqrt(alpha*alpha + (1-alpha)*(1-alpha)) + *--------------------------------------------------------------------*/ + + beta = shl(sub(alpha, 16384), 1); + alpha_m1 = sub(32767, alpha); + L_tmp_res = L_mac(0, alpha, alpha); + L_tmp_res = L_mac(L_tmp_res, alpha_m1, alpha_m1); + tmp_den = round_fx(L_Frac_sqrtQ31(L_tmp_res)); + + tmp_nom = sub(32767, tmp_den); + tmp_shift = norm_s(tmp_den); + tmp_den = shl(tmp_den, tmp_shift); + tmp_res = div_s(tmp_nom, tmp_den); + + Noimix_fract = shr(tmp_res, tmp_shift); /* float value is in range 0.0 to 0.42 */ + + /* L_Ge might be 0 in unvoiced WB */ + L_Ge = L_max(L_Ge, 1); + tmp_shift = norm_l(L_Ge); + tmp_den = extract_h(L_shl(L_Ge, tmp_shift)); /* Q_local+Q_ge+tmp_shift-16 */ + tmp_res = div_s(1<<14, tmp_den); /* 15+14-Q_local-tmp_shift-Q_ge+16 */ + L_tmp_res = Mult_32_16(*ge_sm, tmp_res); /* Q_stat_noise_ge+45-Q_local-Q_ge-tmp_shift-15 */ + L_tmp_res = Mult_32_16(L_tmp_res, sub(32767, beta)); /*30-Q_local-tmp_shift+15-15 */ + L_tmp_res = L_add(L_shl(L_tmp_res, sub(add(Q_local, tmp_shift), 15)), beta); /* Q15 */ + tmp_res = extract_h(L_shl(L_tmp_res, 15)); /* 15+15-16=14 */ + + Noimix_fract = extract_l(Mult_32_16(L_tmp_res, Noimix_fract)); /*15+15-15 */ + + FOR (i=0; ige_sm*Rnd*((1.0f)-alpha) + * flt: exc2[i] = (noimix_fract*exc2[i]+exc2 )* alpha + st->ge_sm*Rnd*((1.0f)-alpha) + * NB: currently uses 32bit accumulation for best low level performance, + * possibly overkill if input is always up-scaled + *--------------------------------------------------------------------*/ + + /* (1-alpha)*(float)sqrt(12.0f) * ((float)own_random(&(st->noimix_seed))/65536.0f) */ + randval = Random(noimix_seed); /* +/-32767 */ + randval = mult_r(28378, randval); /* Q downscaled by 2 bits ends up in Q14 */ /*sqrt(12.0f) in Q13*/ + randval = extract_l(L_shl(Mult_32_16(L_Ge, randval), 1-*Q_stat_noise_ge)); /*Q_local+Q_ge+14-15+1-Q_ge=Q_local */ + + L_tmp = L_mult(Exc2_local[i], alpha); /* Q_local + 16 */ + L_tmp = L_mac(L_tmp, randval, alpha_m1); /* Q_local + 16 */ + L_tmp3 = Mult_32_16(L_tmp, Noimix_fract); /* Q_local+16+15-15 */ + L_tmp = L_add(L_tmp3, L_shl(Mult_32_16(L_tmp, tmp_res), 1)); /* Q_local+16+14-15+1 */ + + Exc2_local[i] = extract_h(L_tmp); /*Q_local */ + } + *Q_stat_noise = Q_local; /* update for next call, routine can only be called once every frame */ + Qdiff = sub(Q_exc, Q_local); /* local excitation and incoming excitation */ + Scale_sig(Exc2_local, L_FRAME, Qdiff); + Copy(Exc2_local, exc2, L_FRAME); + + /*--------------------------------------------------------------------* + * Generate low-pass filtered version of ISP coefficients + *--------------------------------------------------------------------*/ + FOR (k=0; k correlation loop can be optimized */ + r0 = L_mac(r0,xi,xi); + + xi_p1 = shr(x[i+1], Q_shift); + r1 = L_mac(r1, xi, xi_p1); + + xi = xi_p1; + move16(); + } + + if (r0 == 0) + { + r0 = L_shl(327, 16); + } + + tmp_shift = norm_l(r0); + move16(); + r0 = L_shl(r0,tmp_shift); + tmp_sign = 1; + move16(); + if (r1 >= 0) + { + tmp_sign = 0; + move16(); + } + r1 = L_abs(r1); + + L_tmp_res = Div_32(r1,extract_h(r0), extract_l(r0)); + L_tmp_res = L_shl(L_tmp_res, tmp_shift); /*Q31 */ + + if (tmp_sign != 0) + { + L_tmp_res = L_negate(L_tmp_res); /*Q31 */ + } + + return extract_h(L_tmp_res); /*Q15 */ +} + +/*---------------------------------------------------------------------------* + * L_Sqrt_Q0 + * + * Calculate square root from fractional values (Q0 -> Q0) + * Uses 32 bit internal representation for precision + *---------------------------------------------------------------------------*/ +Word32 L_Sqrt_Q0( /* o : Square root of input */ + const Word32 x /* i : Input */ +) +{ + Word32 log2_work; + + Word16 log2_int; + Word16 log2_frac; + + IF (x > 0) + { + log2_int = norm_l(x); + log2_frac = Log2_norm_lc(L_shl(x, log2_int)); + + log2_work = L_mac0(30*32768L, log2_frac, 1); + log2_work = L_msu(log2_work, log2_int, 16384); + log2_frac = L_Extract_lc(log2_work, &log2_int); + + return Pow2(log2_int, log2_frac); + } + return 0; +} + diff --git a/lib_com/swb_bwe_com_fx.c b/lib_com/swb_bwe_com_fx.c new file mode 100644 index 0000000..d953245 --- /dev/null +++ b/lib_com/swb_bwe_com_fx.c @@ -0,0 +1,2803 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "rom_com_fx.h" +#include "stl.h" + + +/*==========================================================================*/ +/* FUNCTION : Word16 WB_BWE_gain_pred_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : predict WB frequency envelopes for 0b WB BWE */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _Word16 *core_dec_freq i : Frequency domain core decoded signal */ +/* _Word16 coder_type i : coding type */ +/* _Word16 prev_coder_type i : coding type of last frame */ +/* _Word16 prev_WB_fenv i : envelope for last frame */ +/* _Word16 *voice_factors i : voicing factors //Q15 */ +/* _Word16 pitch_buf[] i : pitch buffer //Q6 */ +/* _Word16 last_core_brate i : previous frame core bitrate */ +/* _Word16 last_wb_bwe_ener i : previous frame wb bwe signal energy */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _Word16 *WB_fenv, o : WB frequency envelopes Q3 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _Word16 mode */ +/*--------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*==========================================================================*/ + +Word16 WB_BWE_gain_pred_fx( + Word16 *WB_fenv, /* o : WB frequency envelopes */ + const Word16 *core_dec_freq, /* i : Frequency domain core decoded signal */ + const Word16 coder_type, /* i : coding type */ + Word16 prev_coder_type, /* i : coding type of last frame */ + Word16 prev_WB_fenv, /* i : envelope for last frame */ + Word16 *voice_factors, /* i : voicing factors //Q15 */ + const Word16 pitch_buf[], /* i : pitch buffer //Q6 */ + Word32 last_core_brate, /* i : previous frame core bitrate */ + Word16 last_wb_bwe_ener , /* i : previous frame wb bwe signal energy */ + Word16 Q_syn + ,Word16 last_extl_fx, + Word16 tilt_wb_fx +) +{ + Word32 enerL; + Word16 n_freq, mode,pitch; + Word16 ener_var_flag = 0; + Word16 voice_factor, enerL_16, enerL_40, enerL_64; + Word16 env_var_flag = 0; + Word16 exp; + Word16 tmp, tmp1; + Word32 L_tmp; + Word32 L_WB_fenv0, L_WB_fenv1; + Word16 pitch_buf_tmp[4]; + Word16 alfa = 32767; + move16(); + + mode = NORMAL; + move16(); + + enerL = L_deposit_l(0); + FOR (n_freq = 128; n_freq<192; n_freq++) + { + enerL = L_mac0( enerL, core_dec_freq[n_freq], core_dec_freq[n_freq] ); /*2(Q_syn) */ + } + + L_WB_fenv0 = L_deposit_l(0); + FOR (n_freq = 192; n_freq<224; n_freq++) + { + L_WB_fenv0 = L_mac0(L_WB_fenv0, core_dec_freq[n_freq],core_dec_freq[n_freq]);/*2*Q_syn */ + } + + L_WB_fenv1 = L_deposit_l(0); + FOR (n_freq = 224; n_freq<256; n_freq++) + { + L_WB_fenv1= L_mac0(L_WB_fenv1, core_dec_freq[n_freq],core_dec_freq[n_freq]);/*2*Q_syn */ + } + + L_tmp = sum16_32_fx( voice_factors, 4); + voice_factor = extract_l(L_shr(L_tmp, 2));/*Q13 */ + Copy_Scale_sig(pitch_buf, pitch_buf_tmp, 4, -1); + pitch = sum16_fx(pitch_buf_tmp, 4) ; + move16(); /*Q5 */ + + L_tmp = L_shr(enerL, 4); + test(); + IF(GT_32(L_max(L_WB_fenv1, L_WB_fenv0), L_tmp)&>_16(9856,pitch)) + { + ener_var_flag = 1; + move16(); + } + + test(); + IF(GT_32(L_WB_fenv0, L_shl(L_WB_fenv1,1))) + { + exp = norm_l(L_WB_fenv0); + tmp = extract_h(L_shl(L_WB_fenv0, exp)); + tmp = div_s(16384, tmp); /*Q(15+14-2*Q_syn-exp) */ + L_tmp = L_shr(Mult_32_16(L_shl(L_WB_fenv1, 1), tmp), sub(15, exp));/*2*Q_syn+15+exp-15->2*Q_syn+exp */ + /*L_tmp Q15 */ + tmp = extract_l(L_tmp); + alfa = s_max(tmp, 3277);/*Q15 */ + L_WB_fenv0 = Mult_32_16(L_WB_fenv0, alfa);/*2*Q_syn+15-15->2*Q_syn */ + } + ELSE IF (GT_32(L_WB_fenv1, L_shl(L_WB_fenv0, 1))&&NE_16(coder_type,UNVOICED)) + { + exp = norm_l(L_WB_fenv1); + tmp = extract_h(L_shl(L_WB_fenv1, exp)); + tmp = div_s(16384, tmp); /*Q(15+14-2*Q_syn-exp) */ + L_tmp = L_shr(Mult_32_16(L_shl(L_WB_fenv0, 1), tmp), sub(15, exp));/*2*Q_syn+15+exp-15->2*Q_syn+exp */ + /*L_tmp Q15 */ + tmp = extract_l(L_tmp); + alfa = s_max(tmp, 3277);/*Q15 */ + L_WB_fenv1 = Mult_32_16(L_WB_fenv1, alfa);/*2*Q_syn+15-15->2*Q_syn */ + } + + if(L_WB_fenv0 == 0) + { + L_WB_fenv0 = L_deposit_l(1); + } + + if(L_WB_fenv1 == 0) + { + L_WB_fenv1 = L_deposit_l(1); + } + + if(enerL == 0) + { + enerL = L_deposit_l(1); + } + + L_tmp = L_add(L_WB_fenv0, L_WB_fenv1); /* In 2*Q_syn */ + exp = norm_l(L_tmp); + tmp = extract_h(L_shl(L_tmp, exp)); + /*exp = sub(exp, 30-(2*Q_syn+6)); //+6(/64) */ + exp = sub(exp, sub(30,add(shl(Q_syn,1),6))); /*+6(/64) */ + + tmp = div_s(16384, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp); + + WB_fenv[0] = round_fx(L_shl(L_tmp, sub(exp, 12))); /* Q3 */ + + test(); + test(); + IF(NE_16(coder_type,AUDIO)&&NE_16(coder_type,UNVOICED)&&ener_var_flag==0) + { + WB_fenv[0]= add(WB_fenv[0], mult_r(WB_fenv[0], 16384)); + move16(); + } + + exp = norm_l(enerL); + tmp = extract_h(L_shl(enerL, exp)); + exp = sub(exp, sub(30,shl(Q_syn,1))); + + tmp = div_s(16384, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp); + enerL_16 = round_fx(L_shl(L_tmp, sub(exp, 15))); /* Q0 */ + enerL_40 = mult_r(6554, enerL_16); /*1/40 in Q18 ->Q3 */ + + test(); + test(); + test(); + test(); + test(); + test(); + IF( NE_16(coder_type,TRANSITION)&&NE_16(coder_type,AUDIO)&&NE_16(coder_type,UNVOICED)&& + GT_16(enerL_40, WB_fenv[0]) && GT_16(alfa,29491) && !(EQ_16(coder_type, prev_coder_type) && + GT_16(WB_fenv[0],prev_WB_fenv) ) ) + { + IF(WB_fenv[0] != 0) + { + exp = norm_s(WB_fenv[0]); + tmp = div_s(shl(1,sub(14,exp)), WB_fenv[0]); /*Q(29-exp-3) */ + L_tmp = L_mult(enerL_40, tmp); /*Q(30-exp) */ + tmp = round_fx(L_shl(L_tmp, sub(exp,2))); /*Q12 */ + tmp = s_min(tmp, 16384); + L_tmp = L_shr( L_mult0(tmp, WB_fenv[0]), 12);/*Q15 */ + WB_fenv[0] = extract_l(L_tmp);/*Q3 */ + } + + IF( GT_16(WB_fenv[0],prev_WB_fenv )) + { + /*WB_fenv[0]= add(mult_r(9830, WB_fenv[0]), mult_r(22938, prev_WB_fenv)); move16();//Q3 */ + WB_fenv[0] = round_fx(L_mac(L_mult(9830, WB_fenv[0]), 22938, prev_WB_fenv));/*Q3 */ + } + } + + L_tmp = L_mult0(voice_factor, 77); + tmp1 = extract_l(L_shr(L_tmp, 13)); + + exp = norm_s(pitch); + tmp = div_s(shl(1,sub(14,exp)), pitch); /*Q(29-exp-5) */ + L_tmp = L_mult0(tmp1, tmp); /*29-exp-5->24-exp */ + tmp = round_fx(L_shl(L_tmp, add(exp,6))); /*14 */ + + tmp1= s_max(tmp, 8192); + alfa = s_min(24576, tmp1);/*Q14 */ + + L_tmp = L_mult0(alfa, WB_fenv[0]);/*Q14+Q3->Q17 */ + L_tmp = L_shr(L_tmp, 14);/*Q3 */ + tmp = extract_l(L_tmp); + + enerL = L_deposit_l(enerL_16); + enerL = L_shl(enerL, 6); /*Q6 */ + tmp1 = i_mult(3, WB_fenv[0]);/*Q3 */ + L_tmp = L_mult0(tmp1, WB_fenv[0]); /*Q6 */ + + test(); + test(); + test(); + IF( GT_16(shr(enerL_16, 3), tmp)&>_32(enerL,L_tmp)&&NE_16(prev_coder_type,UNVOICED)&&WB_fenv[0]!=0) + { + env_var_flag = 1; + move16(); + enerL_64 = mult_r(4096, enerL_16);/* 1/64 in Q18 ->Q3 */ + + exp = norm_s(WB_fenv[0]); + tmp = div_s(shl(1,sub(14,exp)), WB_fenv[0]); /*Q(29-exp-3) */ + L_tmp = L_mult(enerL_64 ,tmp); /*Q(30-exp) */ + tmp = round_fx(L_shl(L_tmp, sub(exp,2))); /*Q12 */ + tmp = s_min(tmp, 16384); + L_tmp = L_shr( L_mult0(tmp, WB_fenv[0]), 12);/*Q3 */ + WB_fenv[0] = extract_l(L_tmp);/*Q3 */ + + IF( GT_16(WB_fenv[0],prev_WB_fenv)) + { + /*WB_fenv[0] = add(mult_r(9830, WB_fenv[0]), mult_r(22938, prev_WB_fenv));//Q3 */ + WB_fenv[0] = round_fx(L_mac(L_mult(9830, WB_fenv[0]), 22938, prev_WB_fenv));/*Q3 */ + } + } + + test(); + IF(EQ_16(coder_type,UNVOICED)||EQ_16(prev_coder_type,UNVOICED)) + { + WB_fenv[0] = shr(WB_fenv[0], 1); + move16();/*Q3 */ + } + + IF(NE_16(coder_type,AUDIO)) + { + tmp = mult_r(voice_factor, 19661); /*Q12 */ + tmp = s_max(tmp, 4096); + exp = norm_s(tmp); + tmp = div_s(shl(1,sub(14,exp)), tmp); /*Q(29-exp-12) */ + L_tmp = L_mult(WB_fenv[0], tmp); /*Q(21-exp) */ + + WB_fenv[0] = round_fx(L_shl(L_tmp, sub(exp,2))); /*Q3 */ + tmp1 = mult_r(328, pitch);/*Q7 */ + tmp = s_min(s_max(tmp1, 16), 256);/*Q7 */ + L_tmp = L_shr( L_mult0(WB_fenv[0], tmp),7);/*Q3 */ + /*WB_fenv[0] = saturate(L_tmp); //Q3 */ + WB_fenv[0] = round_fx(L_shl(L_tmp,16)); /*Q3 */ + } + test(); + IF( GT_32(last_core_brate,ACELP_8k00)&>_16(WB_fenv[0],last_wb_bwe_ener)) + { + /*WB_fenv[0]= add(mult_r(29491, last_wb_bwe_ener), mult_r(3277, WB_fenv[0]));//Q3 */ + WB_fenv[0] = round_fx(L_mac(L_mult(29491, last_wb_bwe_ener), 3277, WB_fenv[0]));/*Q3 */ + } + + IF( NE_16(last_extl_fx, WB_BWE)&<_16(tilt_wb_fx,128)) + { + WB_fenv[0] = mult_r(s_min(16384, shl(tilt_wb_fx, 8)), WB_fenv[0]); + } + + IF(env_var_flag == 1) + { + WB_fenv[1] = add(WB_fenv[0], mult_r(WB_fenv[0], 16384)); + move16(); + WB_fenv[0] = mult_r(24576, WB_fenv[0]); + move16();/*Q3 */ + } + ELSE + { + WB_fenv[1] = WB_fenv[0]; + move16(); + } + + test(); + IF(EQ_16(coder_type,UNVOICED)||EQ_16(prev_coder_type,UNVOICED)) + { + WB_fenv[1] = shr(WB_fenv[1], 1); + move16();/*Q3 */ + } + + return (mode); +} + +/*-------------------------------------------------------------------* +* calc_norm_envelop_lf_fx() +* +* calc_envelope of low frequency spectrum +*-------------------------------------------------------------------*/ +static +void calc_norm_envelop_lf_fx( + const Word32 SWB_signal[], /* i : SWB spectrum */ /* Q12 */ + Word32 *envelope, /* o : normalized envelope */ /* Q12 */ + Word16 *L_swb_norm, /* i/o : length of envelope */ + const Word16 HQ_mode, /* i : HQ mode */ /* Q0 */ + const Word16 hq_generic_offset, /* i : frequency offset for representing hq generic */ /* Q0 */ + Word16 *sfreq, /* i : starting frequency index */ + Word16 *efreq /* i : ending frequency index */ +) +{ + Word16 lookback, env_index, n_freq, n_lag_now, n_lag; + + *sfreq = 2; + move16(); + IF ( EQ_16(hq_generic_offset, HQ_GENERIC_FOFFSET_24K4)) + { + *efreq = 146; + move16(); + if ( EQ_16(HQ_mode, HQ_GEN_FB)) + { + *efreq = 306; + move16(); + } + IF ( LT_16(add(shl(sub(328,*efreq),1),1),*L_swb_norm)) + { + *L_swb_norm = add(shl(sub(328,*efreq),1),1); + } + } + ELSE + { + *efreq = 130; + move16(); + if ( EQ_16(HQ_mode, HQ_GEN_FB)) + { + *efreq = 290; + move16(); + } + IF ( LT_16(add(shl(sub(400,*efreq),1),1),*L_swb_norm)) + { + *L_swb_norm = add(shl(sub(400,*efreq),1),1); + } + } + lookback = shr(*L_swb_norm,1); + env_index = 0; + move16(); + n_lag_now = *L_swb_norm; + move16(); + + FOR (n_freq = 0; n_freq < lookback; n_freq++) + { + Word16 tmp; + Word32 L_tmp; + + L_tmp = L_deposit_l(1); + tmp = add(lookback,n_freq); + FOR (n_lag=0; n_lag 0; j--) + { + tmp1 = mult_r(*ptr++, 8192); /* Divide by 4 */ + L_ener = L_mult0(tmp1, tmp1); + /* With the shift by 4 and the L_mult0, no overflow possible for 32 samples */ + FOR (i = 1; i < 32; i++) + { + tmp1 = mult_r(*ptr++, 8192); /* Divide by 4 */ + L_ener = L_mac0(L_ener, tmp1, tmp1); + } + L_ener = L_shr(L_ener, exp2); + L_temp = L_add(L_ener_tot, L_ener); + IF (Overflow != 0) + { + L_ener_tot = L_shr(L_ener_tot, 1); + L_ener = L_shr(L_ener, 1); + exp2 = add(exp2, 1); + /* this is required, do not remove */ + Overflow = 0; + move16(); + } + L_ener_tot = L_add(L_ener_tot, L_ener); + } + L_ener = L_deposit_l(abs_s(sub(sp[1], sp[0]))); + FOR (i = 2; i < N; i++) + { + /* Eq to (sp[i] - sp[i-1]) * (sp[i-1] - sp[i-2]) < 0 */ + tmp1 = sub(sp[i], sp[i-1]); + tmp2 = sub(sp[i-1], sp[i-2]); + tmp2 = mult(tmp1, tmp2); + tmp1 = abs_s(tmp1); + /* to Get either 0 or -1 in 'tmp2' */ + tmp2 = shr(tmp2, 15); + /* this allows this code */ + L_ener = L_msu0(L_ener, tmp2, tmp1); + /* instead of this one */ + /* test(); */ + /* if (tmp2 < 0) */ + /* { */ + /* L_ener = L_mac0(L_ener, 1, tmp1); */ + /* } */ + /* it saves one op */ + } + + tmp1 = norm_l(L_ener_tot); + L_temp = L_shl(L_ener_tot, tmp1); + tmp1 = sub(add(31+4, exp2), add(tmp1, shl(exp_sp, 1))); + L_temp = Isqrt_lc(L_temp, &tmp1); + + /* *tilt_flt = (float)(r1/sqrt(r0)); */ + exp2 = norm_l(L_ener); + L_temp = Mult_32_16(L_temp, round_fx(L_shl(L_ener, exp2))); + exp2 = sub(exp2, tmp1); + exp2 = add(exp2, exp_sp); + + /* Put in Q24 */ + L_temp = L_shr(L_temp, sub(exp2, 24)); + + BASOP_SATURATE_WARNING_ON + + return L_temp; +} +void calc_norm_envelop_fx( + const Word16 SWB_signal[], /* i : SWB spectrum Q_syn*/ + Word32 *envelope, /* o : normalized envelope Q_syn*/ + const Word16 L_swb_norm, /* i : length of envelope Q0 */ + const Word16 SWB_flength, /* i : Length of input/output */ + const Word16 st_offset /* i : offset */ +) +{ + Word16 i, lookback, env_index, n_freq, n_lag_now, n_lag, tmp; + + lookback = shr(L_swb_norm, 1); + move16(); + env_index = add(swb_bwe_subband_fx[0], st_offset); + n_lag_now = L_swb_norm; + move16(); + tmp = sub(add(SWB_flength, st_offset), L_swb_norm); + FOR (n_freq = sub(add(swb_bwe_trans_subband_fx[0], st_offset), lookback); n_freq 0) + { + tmp = sub(18022, weight); /* Q15 */ + WB_signal[n_freq] = extract_l(Mult_32_16(L_tmp,tmp)); /* Q_syn */ + } + + IF(NE_16(signum[n_freq],1)) + { + WB_signal[n_freq] = negate(WB_signal[n_freq]); + move16(); + } + } + } + + /* Normalize with envelope */ + FOR (n_freq = swb_bwe_subband_fx[0]; n_freqQ(25) */ + + exp = norm_l(energy); + L_tmp1 = L_shl(energy, exp); + exp = 31-exp-(25); + move16(); + L_tmp1 = Isqrt_lc(L_tmp1, &exp); /*Q(31-exp) */ + + FOR (n_freq = swb_bwe_subband_fx[n_band]; n_freqQ_syn */ + prev_ener_beta = L_shl( Mult_32_16( *prev_Energy ,beta),2); /*Q_syn+13-15+2 ->Q_syn */ + + test(); + test(); + IF( (EQ_16(mode,HARMONIC)&>_16(shr(WB_fenv[0],2),WB_fenv[1]))||EQ_16(mode,NORMAL)) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_16(last_extl,WB_BWE)&& + ( (EQ_16(prev_coder_type,AUDIO) && NE_16(coder_type,AUDIO) ) || + (NE_16(prev_coder_type,AUDIO) && EQ_16(coder_type,AUDIO) )) && LE_32(total_brate,ACELP_8k00) ) + { + IF( GT_16(WB_fenv[0],prev_WB_fenv[0])) + { + /*wfenv[0]= add(mult_r(9830, WB_fenv[0]), mult_r(22938, prev_WB_fenv[0]));//Q3 */ + wfenv[0]= round_fx(L_mac(L_mult(9830, WB_fenv[0]), 22938, prev_WB_fenv[0]));/*Q3 */ + /*wfenv[1]= add(mult_r(9830, WB_fenv[1]), mult_r(22938, prev_WB_fenv[1]));//Q3 */ + wfenv[1]= round_fx(L_mac(L_mult(9830, WB_fenv[1]), 22938, prev_WB_fenv[1]));/*Q3 */ + } + ELSE + { + /*wfenv[0]= add(mult_r(16384,WB_fenv[0]),mult_r(16384,prev_WB_fenv[0]));//Q3 */ + wfenv[0]= round_fx(L_mac(L_mult(16384,WB_fenv[0]),16384,prev_WB_fenv[0]));/*Q3 */ + /*wfenv[1]= add(mult_r(13108,WB_fenv[1]),mult_r(13108,prev_WB_fenv[1]));//Q3 */ + wfenv[1]= round_fx(L_mac(L_mult(13108,WB_fenv[1]),13108,prev_WB_fenv[1]));/*Q3 */ + } + } + ELSE IF ( EQ_16(last_extl,WB_BWE)&<_32(L_tmp1,L_tmp2)&>_16(WB_fenv[0],prev_WB_fenv[0])&& + NE_16(coder_type,AUDIO) && NE_16(coder_type,UNVOICED) && LE_32(total_brate,ACELP_8k00)) + { + /*wfenv[0]= add(mult_r(9830,WB_fenv[0]),mult_r(22938,prev_WB_fenv[0]));//Q3 */ + wfenv[0]= round_fx(L_mac(L_mult(9830,WB_fenv[0]),22938,prev_WB_fenv[0]));/*Q3 */ + /*wfenv[1]= add(mult_r(9830,WB_fenv[1]),mult_r(22938,prev_WB_fenv[1]));//Q3 */ + wfenv[1]= round_fx(L_mac(L_mult(9830,WB_fenv[1]),22938,prev_WB_fenv[1]));/*Q3 */ + } + ELSE IF ( EQ_16(last_extl,WB_BWE)&>_32(EnergyL,prev_ener_alpha)&>_32(prev_ener_beta,EnergyL)&& + NE_16(prev_coder_type,UNVOICED) ) + { + /*wfenv[0] = add(shr(WB_fenv[0],1), shr(prev_WB_fenv[0],1));//Q3 */ + wfenv[0] = round_fx(L_mac(L_mult(WB_fenv[0],16384), prev_WB_fenv[0],16384));/*Q3 */ + /*wfenv[1] = add(shr(WB_fenv[1],1), shr(prev_WB_fenv[1],1));//Q3 */ + wfenv[1] = round_fx(L_mac(L_mult(WB_fenv[1],16384), prev_WB_fenv[1],16384));/*Q3 */ + } + ELSE + { + wfenv[0] = WB_fenv[0]; + move16(); + wfenv[1] = WB_fenv[1]; + move16(); + } + FOR (n_freq = swb_bwe_subband_fx[0]; n_freqQ3 */ + } + exp = norm_s(SWB_FENV_TRANS); + tmp = div_s(shl(1,sub(14,exp)), SWB_FENV_TRANS); /*Q(29-exp) */ + L_tmp = Mult_32_16(Energy, tmp); /*Q(3+29-exp+1-16)->Q(17-exp) */ + Energy_16 = round_fx(L_shl(L_tmp, add(exp,2))); /*Q3 */ + + /* Reconstruct excitation from LF signal */ + Copy(&core_dec_freq[112], &SWB_signal[240+st_offset], 128); + Copy(&core_dec_freq[112], &SWB_signal[368+st_offset], 128); + Copy(&core_dec_freq[176], &SWB_signal[496+st_offset], 64); + + /* calculate envelope */ + calc_norm_envelop_fx(SWB_signal, envelope, L_swb_norm, SWB_flength, st_offset); + + /* Normalize with envelope */ + tmp_exp = sub(15, Q_syn); + FOR (n_freq = swb_bwe_trans_subband_fx[0]+st_offset; n_freqQ(-exp1+39) */ + + exp = norm_l(energy); + L_tmp = L_shl(energy,exp); + /*exp = 31-exp-(-exp1+39); */ + exp = sub(sub(exp1,exp),8); + L_tmp = Isqrt_lc(L_tmp, &exp); /*Q(31-exp) */ + + Ltmp_ener = Mult_32_16(L_tmp,SWB_fenv[n_band]);/*Q(31-exp+1+1-16)->Q(17-exp) */ + tmp = add(swb_bwe_trans_subband_fx[n_band+1],st_offset); + tmp_exp = add(Q_syn,sub(exp,2)); + FOR (n_freq = add(swb_bwe_trans_subband_fx[n_band],st_offset); n_freqQ(15-exp) */ + Energy_16 = round_fx(L_shl(L_tmp,add(exp,4))); /*Q3 */ + + IF(NE_16(last_extl, SWB_BWE)&&NE_16(last_extl,FB_BWE)) + { + IF(Energy_16 < shr(EnergyL_16, 4) && EQ_16(extl, FB_BWE)) + { + FOR(n_band=0; n_band 4096; tmp3 -= 2048) + { + *pit1 = round_fx(L_shl(L_mult(*pit1,tmp3),3)); /*Q_syn */ + pit1--; + } + } + + tmp1 = add(abs_s(SWB_signal[496+st_offset]),abs_s(SWB_signal[497+st_offset])); /*Q_syn */ + tmp2 = add(add(abs_s(SWB_signal[492+st_offset]),abs_s(SWB_signal[493+st_offset])),add(abs_s(SWB_signal[494+st_offset]),abs_s(SWB_signal[495+st_offset]))); + pit1 = &SWB_signal[496+st_offset]; + move16(); + + test(); + IF((tmp2 == 0) || (LT_16(tmp2,mult_r(tmp1,9830)))) + { + tmp3 = 9830; + move16(); /*0.3 in Q15 */ + WHILE(LT_16(tmp3,32767)) + { + *pit1 = mult_r(*pit1,tmp3); + move16(); /*Q_syn */ + pit1++; + tmp3 = add(tmp3,3277); /*Q15 */ + } + } + ELSE IF(LT_16(tmp2,tmp1)) + { + exp = norm_s(tmp1); + tmp = div_s(shl(1,sub(14,exp)),tmp1); /*Q(29-exp) */ + tmp3 = round_fx(L_shl(L_mult(tmp2,tmp),add(exp,2))); /*Q15 */ + WHILE(LT_16(tmp3,32767)) + { + *pit1 = mult_r(*pit1,tmp3); + move16();/*Q_syn */ + pit1++; + tmp3 = add(tmp3,3277); /*Q15 */ + } + } + pit1 = &SWB_signal[495+st_offset]; + + L_tmp3 = L_deposit_h(tmp1); /*Q17 */ + L_tmp4 = Mult_32_16(L_tmp3,1638); /*Q17 */ + exp = 14; + move16(); + IF(tmp2 != 0) + { + exp = norm_s(tmp2); + tmp = div_s(shl(1,sub(14,exp)),tmp2); /*Q(29-exp) */ + L_tmp3 = L_shr(L_mult(tmp1,tmp),1); /*Q(30-exp+1)->Q(30-exp) (+1) due to *0.5 */ + L_tmp4 = Mult_32_16(L_tmp3,1638); /*Q(30-exp) */ + } + + L_tmp1 = L_shl(1L,sub(30,exp)); + WHILE( GT_32(L_tmp3,L_tmp1)) + { + L_tmp = Mult_32_16(L_tmp3,*pit1); /*Q(16-exp) */ + *pit1-- = round_fx(L_shl(L_tmp,exp)); /*Q_syn */ + L_tmp3 = L_sub(L_tmp3,L_tmp4); + } + + /* calculate envelope */ + calc_norm_envelop_fx(SWB_signal, envelope, L_swb_norm, SWB_flength, st_offset); + } + } + + /* Normalize with envelope */ + test(); + IF( *frica_flag == 0 && NE_16(mode, NOISE)) + { + L = add(swb_bwe_subband_fx[0],st_offset); + exp = norm_s(L_swb_norm); + inv_L_swb_norm = shl(div_s(shl(1,sub(14,exp)),L_swb_norm),sub(exp,14)); /* Q15 */ + + IF(NE_16(mode,HARMONIC)) + { + tmp = add(shl(inv_L_swb_norm,1), inv_L_swb_norm) ; + weight = s_max(s_min(tmp,16384), 6554); + } + ELSE + { + weight = 6554; + move16(); + } + + weight = mac_r(L_mult(13107,weight) , 19661,(*prev_weight)); + + FOR (n_freq = L; n_freq 0) + { + tmp = shr(weight,1); /* Q14 */ + tmp = sub(19661,tmp); /* Q14 */ + SWB_signal[n_freq] = extract_l(L_shl(Mult_32_16(L_tmp,tmp),1)); /* Q_syn */ + } + ELSE + { + SWB_signal[n_freq] = extract_l(L_tmp); /* Q_syn */ + } + + IF(NE_16(signum[n_freq],1)) + { + SWB_signal[n_freq] = negate(SWB_signal[n_freq]); + move16(); + } + } + + tmp_exp = sub(15,Q_syn); + FOR (n_freq = L; n_freqQ(-exp1+39) */ + + exp = norm_l(energy); + L_tmp = L_shl(energy, exp); + /*exp = 31-exp-(-exp1+39);move16(); */ + exp = sub(sub(exp1,exp),8); + Ltmp_ener = Isqrt_lc(L_tmp, &exp); /*Q(31-exp) */ + + tmp = add(swb_bwe_subband_fx[n_band+L],st_offset); + tmp_exp = add(Q_syn,sub(exp,15)); + FOR(n_freq = add(swb_bwe_subband_fx[n_band],st_offset); n_freq0) + { + weight = shr(div_s(Energy_16,*prev_Energy),1); /*Q15 */ + } + ELSE + { + weight = 16384; + move16();/*Q15 */ + } + L_tmp = L_mult(weight, prev_SWB_fenv[0]); /*Q17 */ + L_tmp = L_mac(L_tmp, sub(32767, weight), SWB_fenv[0]);/*Q17 */ + wfenv = round_fx(L_tmp); /*Q1 */ + + tmp = norm_s(wfenv); + IF ( GT_16(tmp,4)) + { + tmp = 12; + move16(); + factor = fenvL_16; + move16();/*Q3 */ + factor1 = mult_r(sub(shl(wfenv,2),fenvL_16),4096); /*Q3 */ + } + ELSE + { + tmp = 14; + move16(); + factor = shr(fenvL_16,2);/*Q1 */ + factor1 = mult_r(sub(wfenv,factor), 4096); /*Q1 */ + } + + tmp2 = add(add(swb_bwe_subband_fx[0],8),st_offset); + FOR (n_freq = add(swb_bwe_subband_fx[0],st_offset); n_freq < tmp2; n_freq++) + { + L_tmp1 = Mult_32_16(SWB_signal_32[n_freq], factor); + SWB_signal_32[n_freq] = L_shl(L_tmp1, tmp-1); + move32();/*15+Qsyn */ + factor = add(factor, factor1); /*Q3 */ + } + + FOR(n_band = 0; n_band < 12; n_band++) + { + L_tmp = L_mult(weight, prev_SWB_fenv[n_band+1]); /*Q17 */ + L_tmp = L_mac(L_tmp, sub(32767,weight), SWB_fenv[n_band+1]);/*Q17 */ + wfenv = round_fx(L_tmp); /*Q1 */ + factor = SWB_fenv[n_band]; + move16(); /*Q1 */ + factor1 = mult_r(sub(wfenv,SWB_fenv[n_band]), smooth_factor_fx[n_band]); /*Q1 */ + tmp = norm_s(factor); + IF ( GT_16(tmp,4)) + { + tmp = 12; + move16(); + factor = shl(factor, 2); + factor1 = shl(factor1, 2); + } + ELSE + { + tmp = 14; + move16(); + } + + tmp2 = add(swb_bwe_sm_subband_fx[n_band+1],st_offset); + FOR (; n_freq < tmp2; n_freq++) + { + L_tmp1 = Mult_32_16(SWB_signal_32[n_freq], factor); + SWB_signal_32[n_freq] = L_shl(L_tmp1, tmp-1); + move32(); /*15+Qsyn */ + factor = add(factor, factor1); /*Q1 */ + } + } + L_tmp = L_mult(weight, prev_SWB_fenv[13]); /*Q17 */ + L_tmp = L_mac(L_tmp,sub(32767,weight), SWB_fenv[13]);/*Q17 */ + wfenv = round_fx(L_tmp); /*Q1 */ + factor = SWB_fenv[12]; + move16();/*Q1 */ + factor1 = mult_r(sub(wfenv, SWB_fenv[12]), smooth_factor_fx[12]); /*Q1 */ + tmp2 = add(swb_bwe_sm_subband_fx[13],st_offset); + FOR ( ; n_freq < tmp2; n_freq++) + { + L_tmp1 = Mult_32_16(SWB_signal_32[n_freq], factor); + SWB_signal_32[n_freq] = L_shl(L_tmp1,13); + move32();/*15+Qsyn */ + factor = add(factor,factor1); /*Q1 */ + } + + FOR(n_band=13; n_band Q(-exp_L+14+2*Q_synth) */ + Energy_16 = 0; + move16(); + /*exp = 31-(-exp_L+14 +(2*(*Q_synth))); */ + exp = sub(17,sub(shl((*Q_synth),1),exp_L)); + + IF(Energy != 0) + { + exp = norm_l(Energy); + frac = extract_h(L_shl(Energy, exp)); + /*exp = sub(exp, 30-(-exp_L+14-2+(2*(*Q_synth)))); */ + exp = sub(exp,sub(30,add(sub(shl((*Q_synth),1),exp_L),14-2))); + + tmp = div_s(16384, frac); + L_tmp = L_deposit_h(tmp); + Energy = Isqrt_lc(L_tmp, &exp); /*Q(31-exp) */ + Energy_16 = round_fx(L_shl(Energy, sub(exp,15))); /*Q0 */ + } + + test(); + IF(LT_32(SWB_tenv[i], 65536)&<_32(Energy,L_shl(SWB_tenv[i],sub(16,exp)))) + { + *Q_synth = add(*Q_synth, 3); + move16(); + } + ELSE + { + pit -= L/4; + move16(); + tmp_ener = 0; + move16(); + exp = 0; + move16(); + + IF(Energy_16 != 0) + { + exp = norm_s(Energy_16); + tmp_ener = div_s(shl(1,sub(14,exp)), Energy_16); /*Q(29-exp) */ + } + + L_tmp = Mult_32_16(SWB_tenv[i], tmp_ener); /*Q(29-exp) */ + tmp = round_fx(L_tmp); /*Q(13-exp) */ + + FOR (j = 0; j < L/4; j++) + { + *pit = round_fx(L_shl(L_mult(tmp, *pit), sub(exp,1))); /*Q(13-exp+1)->Q(14-exp)->Qsyn-3 */ + pit++; + } + } + } + + return; +} + +/*==========================================================================*/ +/* FUNCTION : void time_reduce_pre_echo_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Windowing and time-domain aliasing */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS */ +/* _(Word16*) synth :ACELP core synthesis Q_syn */ +/* _(Word16) L :subframe length */ +/* _(Word16) Q_syn :Q format */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16*)error : SHB BWE synthesis Q_syn */ +/* _(Word16)prev_td_energy : last td energy Q_syn */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +void time_reduce_pre_echo_fx( + const Word16 *synth, /* i : ACELP core synthesis Q_syn*/ + Word16 *error, /* i/o: SHB BWE synthesis Q0*/ + Word16 prev_td_energy, /* o : last td energy Q0*/ + const Word16 L, /* i : subframe length */ + Word16 Q_syn, + Word16 Q_synth +) +{ + Word16 i, j, pos = 0, Len; + Word32 energy; + Word16 energy_16; + Word32 energyL[4]; + Word16 tmp_ener; + Word16 *pit; + Word16 tmpi, tmp_exp; + Word16 exp_L, exp, frac, inv_L, exp_j, tmp; + Word32 L_tmp, L_tmp1, Ltmp_ener; + + exp_L = norm_s(L); + inv_L = div_s(shl(1,sub(14,exp_L)), L); /*Q(29-exp_L) */ + FOR(i=0; i<4; i++) + { + Len = i_mult(L, i); + + L_tmp = L_deposit_l(0); + FOR(j=0; j Q(2*Q_syn) */ + + IF(energyL[i] != 0) + { + exp = norm_l(energyL[i]); + frac = extract_h(L_shl(energyL[i], exp)); + exp = sub(exp, sub(30, shl(Q_syn,1))); + + tmp = div_s(16384, frac); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp); + energyL[i] = L_shl(L_tmp, sub(exp, 16)); + move32();/* Q15 */ + } + } + + FOR(i=0; i<3; i++) + { + L_tmp = Mult_32_16(energyL[i], 29491); /*Q14 */ + test(); + IF(GT_32(L_shr(energyL[i+1], 1), L_tmp)&>_32(energyL[i+1],1638400)) + { + pos = add(i, 1); + move16(); + BREAK; + } + } + + IF (pos > 0) + { + if(LT_16(pos, 3)) + { + pos = add(pos, 1); + } + energy = L_deposit_l(0); + j = i_mult(L, pos); + move16(); + FOR(i=0; i Q(-exp_j+14 +2*Q_synth) */ + energy_16 = 0; + move16(); + + IF(energy != 0) + { + exp = norm_l(energy); + frac = extract_h(L_shl(energy, exp)); + /*exp = sub(exp, 30-(-exp_j+14 +2*Q_synth)); */ + exp = sub(exp, sub(14, sub(shl(Q_synth, 1), exp_j))); + tmp = div_s(16384, frac); + L_tmp = L_deposit_h(tmp); + energy = Isqrt_lc(L_tmp, &exp); /*Q(31-exp) */ + energy_16 = round_fx(L_shl(energy, sub(exp,15))); /*Q0 */ + } + + tmp = mult_r(energy_16, 6554); /*Q0 */ + if(LT_16(prev_td_energy, tmp)) + { + prev_td_energy = tmp; + move16(); + } + + tmp_ener = 0; + move16(); + exp = 0; + move16(); + IF(energy_16 != 0) + { + exp = norm_s(energy_16); + tmp_ener = div_s(shl(1,sub(14,exp)), energy_16); /*Q(29-exp) */ + } + L_tmp = L_mult(prev_td_energy, tmp_ener); /*Q(30-exp) */ + tmp_exp = add(1, exp); + FOR (i = 0; i < j; i++) + { + error[i] = round_fx(L_shl(Mult_32_16(L_tmp, error[i]), tmp_exp)); /*Q(30-exp+1-16)->Q(15-exp)->Q_synth */ + } + + energy = L_deposit_l(0); + FOR(i=j; i<(j+L); i++) + { + energy = L_mac0(energy, error[i], error[i]); /*(2*Q_synth) */ + } + + energy = Mult_32_16(energy, inv_L); /*Q(29-exp_L+1-16) -> Q(-exp_L+14) */ + energy_16 = 0; + move16(); + IF(energy != 0) + { + exp = norm_l(energy); + frac = extract_h(L_shl(energy, exp)); + /*exp = sub(exp, 30-(-exp_L+14+2*Q_synth)); */ + exp = sub(exp, sub(14, sub(shl(Q_synth, 1), exp_L))); + + tmp = div_s(16384, frac); + L_tmp = L_deposit_h(tmp); + energy = Isqrt_lc(L_tmp, &exp); /*Q(31-exp) */ + energy_16 = round_fx(L_shl(energy, sub(exp,15))); /*Q0 */ + } + + tmp_ener = 0; + move16(); + exp = 0; + move16(); + IF(energy_16 != 0) + { + exp = norm_s(energy_16); + tmp_ener = div_s(shl(1,sub(14,exp)), energy_16); /*Q(29-exp) */ + } + Ltmp_ener = L_mult(prev_td_energy, tmp_ener); /*Q(30-exp) */ + L_tmp1 = L_shl(1, sub(30, exp)); + + pit = &error[j]; + move16(); + FOR (i = 0; i < L; i++) + { + tmpi = round_fx(L_shl(L_mult(i, inv_L), add(1, exp_L))); /*Q15 */ + L_tmp = L_sub(L_tmp1, Ltmp_ener); /*Q(30-exp) */ + L_tmp = Mult_32_16(L_tmp, tmpi); /*Q(30-exp) */ + L_tmp = L_add(Ltmp_ener, L_tmp); /*Q(30-exp) */ + tmp = round_fx(L_shl(Mult_32_16(L_tmp, *pit), add(1, exp))); /*Q0 */ + *pit++ = tmp; + } + } + + return; +} + +/*-------------------------------------------------------------------* + * calc_normal_length_fx_32() + * + *-------------------------------------------------------------------*/ +void calc_normal_length_fx_32( + const Word16 core, /* i : core : Q0 */ + const Word32 *sp, /* i : input signal : Q12 */ + const Word16 mode, /* i : input mode : Q0 */ + const Word16 extl, /* i : extension layer : Q0 */ + Word16 *L_swb_norm, /* o : normalize length : Q0 */ + Word16 *prev_L_swb_norm /*i/o : last normalize length : Q0 */ +) +{ + Word16 i, n_freq, n_band, THRES; + Word16 L_swb_norm_trans, L_swb_norm_norm, L_swb_norm_harm, L_swb_norm_cur; + Word16 N; + + const Word32 *pit; + Word32 peak, mean, mag; + Word32 L_tmp1, L_tmp2; + + THRES = 4; + move16(); + test(); + test(); + if( EQ_16(core,HQ_CORE)||EQ_16(extl,SWB_BWE)||EQ_16(extl,FB_BWE)) + { + THRES = 8; + move16(); + } + + N = 16; + move16(); + test(); + test(); + if( EQ_16(core,HQ_CORE)&&(EQ_16(mode,HQ_HARMONIC)||EQ_16(mode,HQ_HVQ))) + { + N = 13; + move16(); + } + + n_band = 0; + move16(); + pit = sp; + move16(); + FOR (i = 0; i < N; i ++) + { + peak = 0; + move16(); + mean = 0; + move16(); + + FOR (n_freq = 0; n_freq < 16; n_freq ++) + { + mag = L_abs(*pit); + if (GT_32(mag , peak)) + { + peak = mag; + move16(); + } + mean = L_add(mean, mag); + pit++; + } + + L_tmp1 = Mult_32_16(peak, shl(15+THRES, 10)); + L_tmp2 = Mult_32_16(mean, shl(THRES, 10)); + test(); + if (GT_32(L_tmp1,L_tmp2)&>_32(peak,40960)) + { + n_band = add(n_band, 1); + } + } + + IF( EQ_16(core,ACELP_CORE)) + { + L_swb_norm_trans = add(4, shr(n_band, 2)); + L_swb_norm_norm = add(8, shr(n_band, 1)); + L_swb_norm_harm = s_max(add(32, shl(n_band, 1)), 24); + + IF( mode == HARMONIC ) + { + L_swb_norm_cur = L_swb_norm_harm ; + move16(); + } + ELSE IF ( mode == NORMAL ) + { + L_swb_norm_cur = L_swb_norm_norm; + move16(); + } + ELSE + { + L_swb_norm_cur = L_swb_norm_trans; + move16(); + } + + *L_swb_norm = shr(add(L_swb_norm_cur, *prev_L_swb_norm), 1); + move16(); + *prev_L_swb_norm = L_swb_norm_cur; + move16(); + } + ELSE + { + test(); + IF( mode == HQ_HARMONIC || mode == HQ_HVQ ) + { + L_swb_norm_cur = add(32, add(shl(n_band, 1), shr(n_band, 1))); + } + ELSE + { + L_swb_norm_cur = add(8, shr(n_band, 1)); + } + + *L_swb_norm = extract_h(L_add(L_mac(L_mult(L_swb_norm_cur, 3276), *prev_L_swb_norm, 29491),32768)); + *prev_L_swb_norm = L_swb_norm_cur; + move16(); + } + + return; +} + + +/*-------------------------------------------------------------------* + * calc_norm_envelop_fx_32() + * + *-------------------------------------------------------------------*/ +void calc_norm_envelop_fx_32( + const Word32 SWB_signal_fx[], /* i : SWB spectrum : Q12 */ + Word32 *envelope_fx, /* o : normalized envelope : Q16 */ + const Word16 L_swb_norm, /* i : length of envelope : Q0 */ + const Word16 SWB_flength, /* i : Length of input/output : Q0 */ + const Word16 st_offset /* i : offset : Q0 */ +) +{ + Word16 i, lookback, env_index, n_freq, n_lag_now, n_lag, tmp; + + lookback = L_swb_norm/2; + move16(); + env_index = swb_bwe_subband_fx[0]+st_offset; + move16(); + n_lag_now = L_swb_norm; + move16(); + tmp = sub(add(SWB_flength,st_offset),L_swb_norm); + FOR (n_freq = sub(add(swb_bwe_trans_subband_fx[0],st_offset),lookback); n_freqQ20*/ + } + + /* mean vector generation for controlling dynamic range */ + FOR( k =0 ; k < nband_lf; ++k ) + { + energy_fx = 1; + move16(); + + tmp = add(i_mult2(add(k,1),blen),sfidx); + FOR ( i = add(i_mult2(k,blen),sfidx); i < tmp; ++i ) + { + energy_fx = L_add(energy_fx,coeff_out1_fx[i]); + } + exp = sub(norm_l(energy_fx),1); + L_tmp = L_shl(energy_fx,exp); + exp1 = norm_l( L_and(blen, 0x00007fff ) ); + L_tmp1 = L_shl( blen, exp1 ); + logic16(); + mean_vector_fx[k] = Div_32(L_tmp, extract_h(L_tmp1), extract_l(L_shr(L_tmp1,1)) & 0x00007fff); + move32();/*31 + 20 + exp1 - exp2*/ + exp = add(51,sub(exp,exp1)); + mean_vector_fx[k] = L_shl(mean_vector_fx[k], sub(20,exp)); + move32();/*Q12->Q20*/ + } + + /* dynamics control */ + FOR( k =0 ; k < nband_lf; ++k ) + { + tmp = add( i_mult2(add(k,1),blen), sfidx); + FOR ( i = add(i_mult2(k,blen),sfidx); i < tmp; ++i ) + { + L_tmp = L_sub(coeff_out1_fx[i],mean_vector_fx[k]); + exp = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, exp); /* exp+12*/ + exp1 = norm_l(rn_weight0_fx); + L_tmp1 = L_shl(rn_weight0_fx, exp1); /* exp1+10*/ + L_tmp = L_mult( extract_h(L_tmp), extract_h(L_tmp1) ); + L_tmp = L_shr(L_tmp, add(exp,sub(exp1,21) )); /* Q20*/ + coeff_out1_fx[i] = L_sub(coeff_out1_fx[i], L_tmp); + move32(); + } + } + + IF ( EQ_16(hq_generic_exc_clas, HQ_GENERIC_EXC0)) + { + bwe_seed = add(add(shl(R[0],3),shl(R[1],2)),add(shl(R[2],1),R[3])); + + FOR ( n_freq = sfidx; n_freq < efidx; n_freq++ ) + { + IF ( signum[n_freq] < 0 ) + { + coeff_out1_fx[n_freq] = L_negate(coeff_out1_fx[n_freq]); + move32(); + } + + IF ( Random(&bwe_seed) < 0 ) + { + coeff_out1_fx[n_freq] = L_negate(coeff_out1_fx[n_freq]); + move32(); + } + } + } + ELSE + { + FOR ( n_freq = sfidx; n_freq < efidx; n_freq++ ) + { + IF ( signum[n_freq] < 0 ) + { + coeff_out1_fx[n_freq] = L_negate(coeff_out1_fx[n_freq]); + move32(); + } + } + } + + /* normalizing modified low frequency spectrum */ + FOR( k =0 ; k < nband_lf; ++k ) + { + energy_fx = 1; + move16(); + tmp = add(i_mult2(add(k,1),blen),sfidx); + FOR ( i = add((i_mult2(k,blen)),sfidx); i < tmp; ++i ) + { + exp = norm_l(coeff_out1_fx[i]); + L_tmp1 = L_shl(coeff_out1_fx[i],exp);/* exp + 12*/ + + L_tmp = Mult_32_32( L_tmp1, L_tmp1); + L_tmp = L_shr( L_tmp, sub(i_mult2(2,exp),11) );/*Q20 */ + energy_fx = L_add( energy_fx, L_tmp ); + } + + exp = norm_l(energy_fx); + L_tmp = L_shl(energy_fx,sub(exp,1)); + exp1 = norm_s(blen); + L_tmp1 = L_shl((Word32)blen,add(exp1,16)); + + L_tmp = Div_32( L_tmp, extract_h(L_tmp1), extract_l( L_shr(L_tmp1,1) ) & 0x00007fff ); + exp = sub( add( 34 , exp ), exp1 ); + L_tmp = L_shr( L_tmp, sub(exp,31) ); + exp = 31; + move16(); + + exp = sub( 31 , exp ); + IF (exp & 0x1) + { + L_tmp = L_shr( L_tmp , 1 ); + exp = add(exp,1); + } + L_tmp = Sqrt_l(L_tmp, &exp1); + exp = add( 31 , sub( shr(exp1,1) , shr(exp,1) ) ); + energy_fx = L_shl(L_tmp, sub(31,exp)); /*Q31*/ + + tmp = add(i_mult2(add(k,1),blen),sfidx); + FOR ( i = add((i_mult2(k,blen)),sfidx); i < tmp; ++i ) + { + IF ( NE_32( L_abs( coeff_out1_fx[i] ), coeff_out1_fx[i] )) + { + s = -1; + move16(); + coeff_out1_fx[i] = L_abs(coeff_out1_fx[i]); + move32(); + } + ELSE + { + s = 0; + move16(); + } + exp = norm_l(coeff_out1_fx[i]); + L_tmp = L_shl(coeff_out1_fx[i],sub(exp,1)); + exp1 = norm_l(energy_fx); + L_tmp1 = L_shl((Word32)energy_fx,exp1); + logic16(); + L_tmp = Div_32( L_tmp, extract_h(L_tmp1), extract_l(L_shr(L_tmp1,1)) & 0x00007fff ); + exp = add ( sub( 19 , exp1 ), exp ); + coeff_out1_fx[i] = L_shl(L_tmp,add(sub(12,exp),15)); + move32(); /* Q12 -> Q27 */ + IF( s ) + { + coeff_out1_fx[i] = L_negate( coeff_out1_fx[i] ); + move32(); + } + } + } + + Copy32(&coeff_out1_fx[HQ_GENERIC_OFFSET], &coeff_out_fx[add(HQ_GENERIC_HIGH0,hq_generic_offset)], HQ_GENERIC_LEN0); + Copy32(&coeff_out1_fx[HQ_GENERIC_OFFSET], &coeff_out_fx[add(HQ_GENERIC_HIGH1,hq_generic_offset)], HQ_GENERIC_LEN0); + + IF ( LE_16(hq_generic_offset , HQ_GENERIC_FOFFSET_24K4)) + { + Copy32( &coeff_out1_fx[HQ_GENERIC_LOW0], &coeff_out_fx[add(HQ_GENERIC_HIGH2,hq_generic_offset)], sub(HQ_GENERIC_END_FREQ , HQ_GENERIC_HIGH2) ); + } + + IF ( EQ_16(HQ_mode , HQ_GEN_FB)) + { + IF ( LE_16(hq_generic_offset, HQ_GENERIC_FOFFSET_24K4)) + { + Copy32(&coeff_out1_fx[sub(add(HQ_GENERIC_LOW0 , HQ_GENERIC_END_FREQ),HQ_GENERIC_HIGH2)], &coeff_out_fx[fb_bwe_subband[0]], 160); + } + ELSE + { + Copy32(&coeff_out1_fx[add(HQ_GENERIC_OFFSET , HQ_GENERIC_LEN0)], &coeff_out_fx[fb_bwe_subband[0]], 160); + } + } + + + L_tmp1 = L_deposit_l(0); + L_tmp2 = L_deposit_l(0); + FOR(i=0; i<5; ++i) + { + L_tmp1 = L_add(L_tmp1, L_abs(coeff_out_fx[add(add(HQ_GENERIC_HIGH1,hq_generic_offset),i)])); + L_tmp2 = L_add(L_tmp2, L_abs(coeff_out_fx[sub(add(sub(HQ_GENERIC_HIGH1,2),hq_generic_offset),i)])); + } + + pit1_fx = &coeff_out_fx[add(HQ_GENERIC_HIGH1,hq_generic_offset)]; + L_tmp1 = L_max(L_tmp1,1); + L_tmp2 = L_max(L_tmp2,1); + exp1 = norm_l(L_tmp1); + exp2 = sub(norm_l(L_tmp2), 1); + tmp1_fx = extract_h(L_shl(L_tmp1, exp1)); + tmp2_fx = extract_h(L_shl(L_tmp2, exp2)); + tmp3_fx = div_s(tmp2_fx, tmp1_fx);/*15 + exp2 + 15 - (exp1 + 15) */ + tmp3_fx = shr(tmp3_fx, add(5, sub(exp2, exp1)));/*10 */ + + if (LT_16(tmp3_fx , 307)) + { + tmp3_fx = 307; + move16(); + } + FOR ( ; tmp3_fx < 1024; tmp3_fx += 102) + { + *pit1_fx = Mult_32_16(*pit1_fx, shl(tmp3_fx, 5)); + move32();/*15 + 5 + 10 -15 */ + pit1_fx++; + } + + pit1_fx = &coeff_out_fx[add(sub(HQ_GENERIC_HIGH1,1),hq_generic_offset)]; + + exp1 = sub(norm_l(L_tmp1), 1); + exp2 = norm_l(L_tmp2); + tmp1_fx = extract_h(L_shl(L_tmp1, exp1)); + tmp2_fx = extract_h(L_shl(L_tmp2, exp2)); + tmp3_fx = div_s(tmp1_fx, tmp2_fx);/*15 + exp2 + 15 - (exp1 + 15) */ + tmp3_fx = shr(tmp3_fx, add(5, sub(exp1, exp2)));/*10 */ + + IF (GT_16(tmp3_fx , 5120)) + { + FOR ( tmp3_fx = 5120; tmp3_fx > 1024; tmp3_fx -= 512) + { + L_tmp1 = Mult_32_16(L_shl(*pit1_fx, 5), tmp3_fx); /*15 + 5 + 10 -15 */ + *pit1_fx-- = L_tmp1; + move32(); + } + } + + IF ( LE_16(hq_generic_offset , HQ_GENERIC_FOFFSET_24K4)) + { + L_tmp1 = L_add(L_abs(coeff_out_fx[add(HQ_GENERIC_HIGH2 , hq_generic_offset)]), L_abs(coeff_out_fx[add(add(HQ_GENERIC_HIGH2,1),hq_generic_offset)])); + L_tmp2 = L_add(L_abs(coeff_out_fx[add(sub(HQ_GENERIC_HIGH2,4),hq_generic_offset)]), L_add(L_abs(coeff_out_fx[add(sub(HQ_GENERIC_HIGH2,3),hq_generic_offset)]), + L_add( L_abs(coeff_out_fx[add(sub(HQ_GENERIC_HIGH2,2),hq_generic_offset)]), L_abs(coeff_out_fx[add(sub(HQ_GENERIC_HIGH2,1),hq_generic_offset)])))); + + pit1_fx = &coeff_out_fx[add(HQ_GENERIC_HIGH2,hq_generic_offset)]; + + L_tmp1 = L_max(L_tmp1,1); + L_tmp2 = L_max(L_tmp2,1); + exp1 = norm_l(L_tmp1); + exp2 = sub(norm_l(L_tmp2), 1); + tmp1_fx = extract_h(L_shl(L_tmp1, exp1)); + tmp2_fx = extract_h(L_shl(L_tmp2, exp2)); + tmp3_fx = div_s(tmp2_fx, tmp1_fx);/*15 + exp2 + 15 - (exp1 + 15) */ + tmp3_fx = shr(tmp3_fx, add(5, sub(exp2, exp1)));/*10 */ + + if (LT_16(tmp3_fx, 307)) + { + tmp3_fx = 307; + move16(); + } + FOR ( ; tmp3_fx < 1024; tmp3_fx += 102) + { + L_tmp = L_shl(Mult_32_16(*pit1_fx, tmp3_fx), 5); /*15 + 5 + 10 -15 */ + *pit1_fx++ = L_tmp; + move32(); + } + + pit1_fx = &coeff_out_fx[add(sub(HQ_GENERIC_HIGH2,1),hq_generic_offset)]; + + exp1 = sub(norm_l(L_tmp1), 1); + exp2 = norm_l(L_tmp2); + tmp1_fx = extract_h(L_shl(L_tmp1, exp1)); + tmp2_fx = extract_h(L_shl(L_tmp2, exp2)); + tmp3_fx = div_s(tmp1_fx, tmp2_fx);/*15 + exp2 + 15 - (exp1 + 15) */ + tmp3_fx = shr(tmp3_fx, add(5, sub(exp1, exp2)));/*10 */ + tmp3_fx = shr(tmp3_fx, 1); + tmp4_fx = mult_r(tmp3_fx, 1638); + WHILE (tmp3_fx > 1024) + { + L_tmp1 = Mult_32_16(L_shl(*pit1_fx, 5), tmp3_fx); /*15 + 5 + 10 -15 */ + *pit1_fx-- = L_tmp1; + move32(); + tmp3_fx = sub(tmp3_fx, tmp4_fx); + } + } + + + wfenv_fx = hq_generic_fenv_fx[0]; + move16();/*1 */ + i = 0; + move16(); + tmp2 = add(add(swb_bwe_subband_fx[0],hq_generic_offset),8); + FOR (n_freq = add(swb_bwe_subband_fx[0],hq_generic_offset); n_freq 30 || hq_generic_fenv_fx[nenv] < 10) + { + wfenv_fx = hq_generic_fenv_fx[sub(nenv,1)]; + move16();/*1 */ + FOR ( i=0; n_freq 0 ) + { + min_bwe_fx = s_min(tmpF_fx, min_bwe_fx); + } + } + + test(); + if( EQ_16(max_bwe_fx, min_bwe_fx)&>_16(min_bwe_fx,shl(1,Q_audio))) + { + min_bwe_fx = mult_r(min_bwe_fx, 16384); + } + + ptr_fx = &t_audio_fx[tmp]; + FOR( j=0; jQ15 */ + } + } + + i = 0; + move16(); + IF( nq[i] == 0 ) + { + i = 1; + move16(); + test(); + WHILE( LT_16(i, Nsv)&&nq[i]==0) + { + i++; + move16(); + test(); + } + + pos_start = i; + move16(); + test(); + WHILE( LT_16(i, Nsv)&&nq[i]!=0) + { + i++; + move16(); + test(); + } + + pos_end = sub(i, 1); + move16(); + + IF( GT_16(pos_end, shl(pos_start, 1))) + { + pos_end = sub(shl(pos_start, 1), 1); + move16(); + } + + incr = pos_end; + move16(); + + FOR( j = sub(pos_start, 1); j >= 0; j-- ) + { + tmp = shl(j, 3); + tmp1 = shl(incr, 3); + FOR( k=0; k= pos_start; j-- ) + { + tmp = shl(j, 3); + tmp1 = shl(incr, 3); + FOR( k=0; k +#include "options.h" +#include "cnst_fx.h" + +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "stl.h" /* required for wmc_tool */ +#include "basop_mpy.h" + +#include + +/*-------------------------------------------------------------------* + * GetPredictedSignal() + * + * Routine for calculating the predicted signal + *-------------------------------------------------------------------*/ +void GetPredictedSignal_fx( + const Word16 *predBuf_fx, /* i: Q8 */ + Word32 *L_outBuf, /* o: Q9 */ + const Word16 lag_fx, /* i: Q0 */ + const Word16 fLen_fx, /* i: Q0 */ + const Word16 lagGains_fx, /* i: Qgain */ + const Word16 Qgain /* i: Q0 */ +) +{ + Word16 i; + const Word16 *p_predBuf; + Word32 *p_L_outBuf; + + p_predBuf = predBuf_fx + lag_fx; + p_L_outBuf = L_outBuf; + + FOR (i=0; i Q9, 9+7-16=Q0 */ + *p_L_outBuf++ = L_shr(L_mult(*p_predBuf++, lagGains_fx), Qgain); + move32(); + } +} + +/*-------------------------------------------------------------------* + * est_freq_har_decis_fx() + * + * Harmonic frequency decision matrix + *-------------------------------------------------------------------*/ +static +void est_freq_har_decis_fx( + Word16 *har_freq_est1, /* o: harmonic analysis 1 */ + Word16 *har_freq_est2, /* o: harmonic analysis 2 */ + Word16 sharp, /* i: pka-avg for group 1 */ + Word16 sharp1, /* i: pka-avg for group 2 */ + Word16 hfe_est_countk1, /* i: group pks count 1 */ + Word16 hfe_est_countk2, /* i: group pks count 2 */ + Word16 k, /* i: group count */ + Word16 k1, /* i: */ + Word16 k2, /* i: */ + Word16 *prev_frm_hfe2 /* i: harmonic estimation */ +) +{ + Word16 temp_hfe2 = 0; + Word16 har_freq_est2_2; + Word16 prev_frm_hfe2_2; + + IF( k != 0 ) + { + *har_freq_est1 = div_s_ss(sharp, k); + } + + test(); + test(); + IF( GT_16(k1, 1)) + { + *har_freq_est2 = div_s_ss(sharp1, k1); + } + ELSE IF( LT_16(k1, 2)&&(k2!=0||GT_16(k,1))) + { + *har_freq_est2 = *har_freq_est1; + move16(); + } + ELSE + { + test(); + test(); + test(); + IF((hfe_est_countk1 != 0 || hfe_est_countk2 != 0) && (k1 == 0 && k2 == 0)) + { + *har_freq_est2 = (*har_freq_est1); + move16(); + } + ELSE + { + *har_freq_est2 = shl(*har_freq_est1, 1); + move16(); + } + } + + /* Consider Estimation Error upto 200Hz */ + test(); + test(); + test(); + har_freq_est2_2 = shl(*har_freq_est2, 1); + prev_frm_hfe2_2 = shl(*prev_frm_hfe2, 1); + IF( *prev_frm_hfe2 != 0 && ( LT_16(abs_s(sub(*prev_frm_hfe2, *har_freq_est2)), 10)||LT_16(abs_s(sub(*prev_frm_hfe2,har_freq_est2_2)),10))) + { + *har_freq_est2 = *prev_frm_hfe2; + move16(); + } + ELSE IF(*prev_frm_hfe2 != 0 && LT_16(abs_s(sub(*har_freq_est2, prev_frm_hfe2_2)), 10)) + { + *har_freq_est2 = prev_frm_hfe2_2; + move16(); + } + ELSE + { + temp_hfe2 = shr(add(*prev_frm_hfe2, *har_freq_est2), 1); + move16(); + + IF( LT_16(abs_s(sub(temp_hfe2, *prev_frm_hfe2)), 2)) + { + temp_hfe2 =*prev_frm_hfe2; + move16(); + *har_freq_est2 = temp_hfe2; + move16(); + } + } + + test(); + test(); + if( LT_16(*har_freq_est2, *har_freq_est1)&&(GT_16(k,1)&<_16(k1,2))) + { + *har_freq_est2 = *har_freq_est1; + move16(); + } + + return; +} + +/*--------------------------------------------------------------------------* + * har_est_fx() + * + * Harmonic Structure analysis using LF spectrum + *--------------------------------------------------------------------------*/ + +Word16 har_est_fx( + Word32 L_spectra[], /* i : coded spectrum */ + Word16 N, /* i : length of the desired spectrum */ + Word16 *har_freq_est1, /* i/o: Estimation harmonics 1 */ + Word16 *har_freq_est2, /* o : Estimation harmonics 2 */ + Word16 *flag_dis, /* i/o: flag for BWE reconstruction */ + Word16 *prev_frm_hfe2, /* i/o: Estimated harmonic update */ + const Word16 subband_search_offset[], /* i : Subband Search range */ + const Word16 sbWidth[], /* i : Subband Search range */ + Word16 *prev_stab_hfe2 /* i/o: Estimated harmonic position */ +) +{ + Word32 L_peak; + Word32 L_input_abs[L_FRAME32k], L_blk_peak[30]; + Word32 L_blk_peak_te[30]; + Word32 L_blk_peak_max; + Word32 *p_L_blk_peak, *pm1_L_blk_peak; + + Word16 i, j, q, k , k1, k2; + Word16 blk_end,blk_st; + Word16 peak_pos,blk_peak_pos[30], diff_peak_pos[30], sharp, sharp1, sharp2; + Word16 min_har_pos; + Word16 blk_peak_pos_te[30]; + Word16 temp; + Word16 hfe_est_countk,hfe_est_countk1,hfe_est_countk2; + Word16 r1, r2, r3; + Word16 start_pos; + Word16 blk_peak_pos_max; + + Word16 nlags, nlags_half, ct_hfsb2,sum_diff; + Word16 blk_peak_pos_hfsb2[30],diff_peak_pos_hfsb2[30]; + Word16 rem_hfe2 ,q_diffpos_hfe2, diff_posmax_hfe2, q_diffpos_prevhfe2; + + Word16 blk_end_LEN; + + Word16 *p_blk_peak_pos, *pm1_blk_peak_pos; + Word16 *p_diff_peak_pos,*pm1_diff_peak_pos; + Word16 blk_peak_max_idx, blk_peak_pos_max_diff, diff_peak_pos_te[30]; + Word16 thr1, thr2; + + set32_fx(L_input_abs, 0x0L, L_FRAME32k); + set32_fx(L_blk_peak, 0x0L, 30); + set16_fx(blk_peak_pos, 0, 30); + set16_fx(blk_peak_pos_te, 0, 30); + + rem_hfe2 = 0; + move16(); + q_diffpos_hfe2 = 0; + move16(); + diff_posmax_hfe2 = 0; + move16(); + q_diffpos_prevhfe2 = 0; + move16(); + + set16_fx(diff_peak_pos,0,30); + + r1 = SWB_HAR_RAN1; + move16(); + r2 = SWB_HAR_RAN2; + move16(); + r3 = SWB_HAR_RAN3; + move16(); + start_pos = r1; + move16(); + + /* Copy the abs values of LF spectrum*/ + FOR ( i = start_pos; i < N; i++) + { + L_input_abs[i] = L_abs(L_spectra[i]); + move32(); + } + + blk_end = div_s_ss(N, LR_BLK_LEN); + blk_st = div_s_ss(start_pos, LR_BLK_LEN); + + /*if( N/(LR_BLK_LEN) - blk_end > 0.0f) */ + blk_end_LEN = i_mult(blk_end, LR_BLK_LEN); + if( GT_16(N, blk_end_LEN)) + { + blk_end = add(blk_end, 1); + } + + /* initialization of over buffer for fractional point */ + temp = i_mult(blk_end, LR_BLK_LEN); + FOR(i=N; i0) + { + sharp = add(sharp, diff_peak_pos[i]); + k = add(k, 1); + } + ELSE IF( LE_16(diff_peak_pos[i], thr2)&&diff_peak_pos[i]>0) + { + sharp1 = add(sharp1, diff_peak_pos[i]); + k1 = add(k1, 1); + } + ELSE IF ( diff_peak_pos[i] > 0 ) + { + sharp2 = add(sharp2, diff_peak_pos[i]); + k2 = add(k2, 1); + } + q = add(q, 1); + } + + est_freq_har_decis_fx(har_freq_est1,har_freq_est2,sharp,sharp1,hfe_est_countk1,hfe_est_countk2,k,k1,k2,prev_frm_hfe2); + + blk_peak_pos_max = blk_peak_pos_te[sub(temp,1)]; + move16(); + + test(); + test(); + IF((*prev_stab_hfe2) > 0 && (*prev_frm_hfe2) > 0 && *prev_stab_hfe2 < N) + { + rem_hfe2 = sub(*har_freq_est2, extract_h(L_shl(L_mult(div_s_ss(*har_freq_est2, *prev_frm_hfe2), *prev_frm_hfe2), 15))); + diff_posmax_hfe2 = abs_s(sub(blk_peak_pos_max, *prev_stab_hfe2)); + IF( rem_hfe2 == 0 ) + { + test(); + IF( LT_16(diff_posmax_hfe2, 9)||*har_freq_est2==0) + { + blk_peak_pos_max = *prev_stab_hfe2; + move16(); + } + ELSE + { + q_diffpos_hfe2 = div_s_ss(diff_posmax_hfe2, *har_freq_est2); + q_diffpos_prevhfe2 = div_s_ss(diff_posmax_hfe2, *prev_frm_hfe2); + test(); + IF( LT_16(q_diffpos_hfe2, 10)||LT_16(q_diffpos_prevhfe2,10)) + { + blk_peak_pos_max = *prev_stab_hfe2; + move16(); + } + ELSE + { + *prev_stab_hfe2 = blk_peak_pos_max; + move16(); + } + } + } + ELSE + { + *prev_stab_hfe2 = blk_peak_pos_max; + move16(); + } + } + ELSE + { + *prev_stab_hfe2 = blk_peak_pos_max; + move16(); + } + + test(); + if( *har_freq_est1 == 0 || *har_freq_est2 == 0 ) + { + *flag_dis = 0; + move16(); + } + } + + IF( *flag_dis == 0 ) + { + IF( *prev_frm_hfe2 != 0 ) + { + *har_freq_est2 = *prev_frm_hfe2; + move16(); + } + ELSE + { + nlags = shl(1, bits_lagIndices_mode0_Har_fx[0]); + nlags_half = shr(nlags, 1); + ct_hfsb2 = 0; + move16(); + FOR(i = 0; i < j; i++) + { + test(); + IF( GE_16(blk_peak_pos_te[i], sub(subband_search_offset[0], nlags_half)) + && + LT_16(blk_peak_pos_te[i], add(add(subband_search_offset[0], sbWidth[0]), nlags_half))) + { + blk_peak_pos_hfsb2[ct_hfsb2] = blk_peak_pos_te[i]; + move16(); + ct_hfsb2 = add(ct_hfsb2, 1); + move16(); + } + } + + IF( GT_16(ct_hfsb2, 1)) + { + sum_diff = 0; + move16(); + FOR(i=1; i(dst_pos); j--) + { + IF (GE_16(ii, add(sbWidth[k],sbWidth[k-1]))) + { + BREAK; + } + + /*xSynth_har[ii] = noise_flr[j];*/ + L_xSynth_har[ii] = L_shl(L_deposit_l(noise_flr_fx[j]), sub(QsL, Qss)); + L_tmpbuf[ii] = L_xSynth_har[ii]; + move32(); + IF( predBuf_fx[j] != 0x0 ) + { + hf_pulse_peaks_fx[l] = predBuf_fx[j]; + move16(); + l = add(l, 1); + } + ii = add(ii, 1); + } + } + pos = 0; + move16(); + FOR(j = 0; j< l; j++) + { + st_last_peakpos = add(st_last_peakpos, har_freq_est2); + IF( LT_16(st_last_peakpos, hfband_end[k])) + { + pk_sf_fx[k*8+pos].nmrValue_fx = hf_pulse_peaks_fx[j]; + move16(); /* Qss */ + pk_sf_fx[k*8+pos].gainIndex_fx = sub(st_last_peakpos, fLenLow); + move16(); + pul_res[k] = add(pul_res[k], 1); + move16(); + pulse_peak_sb_fx[i] = hf_pulse_peaks_fx[j]; + move16(); /* Qss */ + i = add(i, 1); + pos = add(pos, 1); + } + } + st_last_peakpos = temp_last_peakpos; + move16(); + } + res = sub(i, 1); + l = 1; + move16(); + ii = sub(sub(hfband_end[k-1], fLenLow), 1); + tmp_fx = sub(bands, harmonic_band); + FOR(; k inItems = 1/3 = 0.33f, 85(Q8) */ + /* 1/3 = 0.3333f -> 0x2AAA Q15 */ + inItems = 0x2AAA; + move16(); + FOR(i = 1; i < span1; i++) + { + L_sum = L_mac0(L_sum, 0x0001, *newPtr++); + + lo = L_Extract_lc(L_sum, &hi); + *outBuf++ = round_fx( L_shl(Mpy_32_16(hi, lo, inItems), 16) ); /* Q(8+15+1-16)=Q8 -> Q(8+16-16)=Q8 */ + + L_sum = L_mac0(L_sum, 0x0001, *newPtr++); + /* nItems += 2, + * only used value is 5 --> + * inItems = 1/5 = 0.2f, 51(Q8) + */ + /* 1/5 = 0.2f -> 0x1999 Q15 */ + inItems = 0x1999; + move16(); + inBuf++; + } + + inBuf++; + L_sum = L_mac0(L_sum, 0x0001, *newPtr++); + + lo = L_Extract_lc(L_sum, &hi); + /* 4681 (in Q15) = 0.1428 = 1/7 */ + *outBuf++ = round_fx(L_shl(Mpy_32_16(hi, lo, 4681), 16)); /* Q(8+15+1-16)=Q8 -> Q(8+16-16)=Q8 */ + i = add(i, 1); + + /*-- Moving average. --*/ + tmp = sub(num_subband, span1); + FOR( ; i < tmp; i++) + { + L_sum = L_mac0(L_sum, 0x0001, *newPtr++); + L_sum = L_msu0(L_sum, 0x0001, *oldPtr++); + + lo = L_Extract_lc(L_sum, &hi); + /* 4681 (in Q15) = 0.1428 = 1/7 */ + *outBuf++ = round_fx(L_shl(Mpy_32_16(hi, lo, 4681), 16)); /* Q(8+15+1-16)=Q8 -> Q(8+16-16)=Q8 */ + inBuf++; + } + + /*-- Handle end. --*/ + /* nItems = span - 2; (nItems = 5, so we can maintain inItems = 1/5 = 0.2f from above) */ + nItems = sub(MA_LEN, 2); + L_sum = L_msu0(L_sum, 0x0001, *oldPtr++); + + tmp = sub(num_subband, 1); + FOR( ; i < tmp; i++) + { + L_sum = L_msu0(L_sum, 0x0001, *oldPtr++); + + lo = L_Extract_lc(L_sum, &hi); + *outBuf++ = round_fx( L_shl(Mpy_32_16(hi, lo, inItems), 16)); /* Q(8+15+1-16)=Q8 -> Q(8+16-16)=Q8 */ + + /* nItems -= 2; */ + nItems = sub(nItems, 2); + + /* 1.0f -> 0x7fff Q15 */ + inItems = 0x7fff; + move16(); + if(EQ_16(nItems, 3)) + { + /* 1/3 = 0.333f -> 0x2AAA Q15 */ + inItems = 0x2AAA; + move16(); + } + L_sum = L_msu0(L_sum, 0x0001, *oldPtr++); + + inBuf++; + } + + /*-- Last sample. --*/ + *outBuf = *inBuf; + move16(); +} + +/*-------------------------------------------------------------------* + * SpectrumSmoothing() + * + * Smoothing of the low-frequency envelope + *-------------------------------------------------------------------*/ + +void SpectrumSmoothing_fx( + const Word32 *L_inBuf, /* i : Qs Low band MDCT */ + Word16 *outBuf_fx, /* o : Qss output */ + Word16 *Qss, /* o : Q0 Q value of output vector */ + const Word16 fLen, /* i : Q0 length */ + const Word16 th_cut_fx /* i : Qss threshold of cut */ +) +{ + /* internal variable */ + Word16 i,j,k; + + Word16 num_subband_smooth_fx; + Word16 num_subband_smooth_pre_fx; + + Word16 exp_normd; + Word16 exp_shift; + + Word16 max_val_norm_fx; + + Word16 Qmax_val_norm[L_FRAME32k/L_SB]; + + Word32 L_inBuf_abs; + Word32 L_inBuf_pss[L_FRAME32k]; + Word32 L_max_val[L_FRAME32k/L_SB]; + Word16 outBuf_pss_fx[L_FRAME32k]; + + Word16 m, n; + Word16 cnt_zero_cont; + Word16 n_list[BANDS_MAX]; + Word16 reset_flag; + Word16 pp, pk; + Word16 exp_norm; + + *Qss = 10; + + num_subband_smooth_pre_fx = mult(fLen, 21845); /* 1/L_SB = 1/12 = 21845(Q18) Q = exp_normn-18 */ + num_subband_smooth_fx = shr(num_subband_smooth_pre_fx, 18-15); + IF( NE_16(num_subband_smooth_pre_fx, shl(num_subband_smooth_fx, 18-15))) + { + num_subband_smooth_fx++; + } + + FOR( i=0; i= 0 ) + { + outBuf_pss_fx[j] = round_fx(L_shl(Mpy_32_16_r(L_shl(L_inBuf_pss[j], exp_norm), max_val_norm_fx), sub(exp_shift, exp_norm))); + move32(); + } + ELSE + { + outBuf_pss_fx[j] = negate(round_fx(L_shl(Mpy_32_16_r(L_shl(L_abs(L_inBuf_pss[j]), exp_norm), max_val_norm_fx), sub(exp_shift, exp_norm)))); + } + } + ELSE + { + /* CLIP, for avoiding computational difference */ + outBuf_pss_fx[j] = 0x2800; + move16(); + if ( L_inBuf_pss[j] < 0x0L ) + { + outBuf_pss_fx[j] = -0x2800; + move16(); + } + } + j++; + } + } + + k = 0; + move16(); + m = 0; + move16(); + n = 0; + move16(); + reset_flag = 0; + move16(); + n_list[0] = 0; + move16(); + FOR( j=0; j 3*L_SB/4 */ + { + pp = round_fx(L_shl(L_mult(n_list[m], L_SB), 15)); + FOR( i=0; i=0, so L_abs is omitted. */ + Word16 *outBuf_fx, /* o : output Q7 */ + const Word16 fLen, /* i : loop length */ + const Word16 Q_inBuf /* i : Qvalue of L_inBuf */ +) +{ + Word16 i; + Word16 exp, frac; + + Word32 L_tmp; + + Word32 L_lamda; + Word16 Q_inBuf_1; + + Q_inBuf_1 = sub(Q_inBuf, 1); + L_lamda = L_shl(1L, Q_inBuf_1); /* +1 : Q_inBuf -> Q_inBuf-1 for overflow problem */ + + FOR( i = 0; i < fLen; i++) + { + /*outBuf++ = (float) (20.0f * log10(fabs(*inBuf + 1.0))); */ + L_tmp = L_add(L_shr(*L_inBuf++, 1), L_lamda); + exp = 31; + move16(); + if (L_tmp != 0x0L) + { + exp = norm_l(L_tmp); + } + frac = Log2_norm_lc(L_shl(L_tmp, exp)); + exp = sub(30, exp); + exp = sub(exp, Q_inBuf_1); + L_tmp = L_Comp(exp, frac); + + L_tmp = Mpy_32_16_1(L_tmp, 24660); /* 6.0206 in Q12 */ + L_tmp = L_shl(L_tmp, 2+8); /* Q7 */ + *outBuf_fx++ = round_fx(L_tmp); + } + + return; +} + +void convert_lagIndices_pls2smp_fx( + Word16 lagIndices_in_fx[], + Word16 nBands_search_fx, + Word16 lagIndices_out_fx[], + const Word16 sspectra_fx[], + const Word16 sbWidth_fx[], + const Word16 fLenLow_fx +) +{ + Word16 sb; + Word16 i, cnt; + + FOR( sb = 0; sb < nBands_search_fx; sb++ ) + { + cnt = 0; + move16(); + i = 0; + move16(); + + WHILE( LE_16(cnt, lagIndices_in_fx[sb])) + { + if( sspectra_fx[subband_search_offsets_fx[sb]+i] != 0 ) + { + cnt = add(cnt, 1); + } + + i = add(i, 1); + + IF( GE_16(add(subband_search_offsets_fx[sb], add(i, sbWidth_fx[sb])) , fLenLow_fx)) + { + BREAK; + } + } + + lagIndices_out_fx[sb] = add(sub(i, 1), subband_search_offsets_fx[sb]); + move16(); + } + + return; +} + +Word16 get_usebit_npswb_fx( + Word16 hqswb_clas_fx +) +{ + Word16 i; + Word16 bits; + Word16 up_lmt; + const Word16 *bits_req; + + up_lmt = 0; + move16(); + bits_req = bits_lagIndices_modeNormal_fx; + move16(); + bits = 0; + move16(); + + IF( EQ_16(hqswb_clas_fx, HQ_NORMAL)) + { + up_lmt = NB_SWB_SUBBANDS; + move16(); + bits_req = bits_lagIndices_modeNormal_fx; + move16(); + } + ELSE IF ( EQ_16(hqswb_clas_fx, HQ_HARMONIC)) + { + up_lmt = NB_SWB_SUBBANDS_HAR_SEARCH_SB; + move16(); + bits_req =bits_lagIndices_mode0_Har_fx; + move16(); + bits = 2; + move16(); /*noise gain*/ + } + + FOR( i = 0; i < up_lmt; i++ ) + { + bits = add(bits, bits_req[i]); + move16(); + } + + return bits; +} + +void SpectrumSmoothing_nss_fx( + const Word32 *L_inBuf, /* i : lowband MDCT */ + Word16 *outBuf_fx, /* o : output */ + Word16 *Qss, /* o : Q value of output vector */ + const Word16 fLen /* i : length */ +) +{ + /* internal variable */ + Word16 i,k; + + Word16 inBuf_fx[L_FRAME32k]; + Word16 Qm; + Word32 L_tmp[L_FRAME32k]; + + Word16 num_subband_smooth_fx; + Word16 exp_tmp; + + Word16 inBufw_fx[L_FRAME32k+L_SB_NSS]; + Word16 outBufw_fx[L_FRAME32k+L_SB_NSS]; + Word32 L_outBufw[L_FRAME32k+L_SB_NSS]; + Word16 Qo[NUM_SUBBAND_SMOOTH_MAX]; + + Word16 avg_val_fx; + Word32 L_avg_val; + Word16 r0_fx; + Word32 L_r0; + Word32 L_temp; + Word16 temp_fx; + + Word16 max_peak_fx; + + Word16 smr_fx; + Word32 L_smr; + + Word32 L_temp_sum_1[NUM_SUBBAND_SMOOTH_MAX]; + Word32 L_temp_sum_2[NUM_SUBBAND_SMOOTH_MAX]; + Word32 L_temp_sum_3[NUM_SUBBAND_SMOOTH_MAX]; + + + Word16 temp_sum_smooth_fx[NUM_SUBBAND_SMOOTH_MAX]; + Word16 temp_sum_div_fx[NUM_SUBBAND_SMOOTH_MAX]; + Word16 Qsumdiv[NUM_SUBBAND_SMOOTH_MAX]; + Word32 L_temp1; + Word16 temp_hi; + Word16 temp_lo; + + + Word16 avg_val2_fx; + Word32 L_avg_val2; + Word16 Qavg_val; + Word16 Qsmr; + Word16 exp, frac; + + Word16 clip_cof_fx; + + Word16 thre_fx, thre_fx_neg; + Word16 thre_min_fx; + + Word16 temp_sum_log_fx[NUM_SUBBAND_SMOOTH_MAX]; + Word16 exp_norm; + Word16 exp_normn; + Word16 exp_normd; + Word16 exp_shift; + + L_tmp[0] = L_deposit_l(0); + FOR(i=0; i Q(exp_normn-exp_normd+15+16) */ + Qsmr=add(sub(add(Qm,exp_tmp), Qavg_val), 31); + + L_temp = L_add(L_shr(L_smr, 1), 0x1L); /* add minimum value */ + exp = norm_l(L_temp); + frac = Log2_norm_lc(L_shl(L_temp, exp)); + exp = sub(30, exp); + exp = sub(exp, sub(Qsmr, 1)); + L_temp = L_Comp(exp, frac); + + L_temp = Mpy_32_16_1(L_temp, 12330); /* 3.0103 in Q12 */ + L_temp = L_shl(L_temp, 2+8); /* Q7 */ + smr_fx = round_fx(L_temp); + + FOR( i = 0; i < num_subband_smooth_fx; i++ ) + { + L_temp_sum_1[i] = L_deposit_l(0); + L_temp_sum_2[i] = L_deposit_l(0); + + FOR( k = 0; k < L_SB_NSS_HALF; k++ ) + { + L_temp_sum_1[i] = L_add( L_temp_sum_1[i], extract_l(abs_s( inBufw_fx[k+L_SB_NSS*i])) ); /* Qm */ move32(); + } + + FOR( k = L_SB_NSS_HALF; k < L_SB_NSS; k++ ) + { + L_temp_sum_2[i] = L_add( L_temp_sum_2[i], extract_l(abs_s( inBufw_fx[k+L_SB_NSS*i])) ); /* Qm */ move32(); + } + + L_temp_sum_1[i] = L_shr(L_temp_sum_1[i], 2); /* *0.25 guarantee low-side 16bit for L_temp_sum_* */ move32(); + L_temp_sum_2[i] = L_shr(L_temp_sum_2[i], 2); /* *0.25 */ move32(); + L_temp_sum_3[i] = L_mult(extract_l(L_temp_sum_1[i]), extract_l(L_temp_sum_2[i])); /* Qm*2+1 */ move32(); + + IF( L_temp_sum_3[i] == 0 ) + { + L_temp_sum_3[i] = L_shl(L_add(L_temp_sum_1[i], L_temp_sum_2[i]), add(Qm, 1)); /*Q(Qm+Qm+1) */ move32(); + } + } + + exp_norm = add(shl(Qm, 1), 1); + Get20Log10Spec_fx(L_temp_sum_3, temp_sum_log_fx, num_subband_smooth_fx, exp_norm); + + /* temp_sum_log_fx // *0.5 Q7 -> Q8 (not change) */ + SmoothSpec_fx(temp_sum_log_fx, temp_sum_smooth_fx, num_subband_smooth_fx); + + FOR (i = 0; i < num_subband_smooth_fx; i++) + { + L_temp1 = L_mult(temp_sum_smooth_fx[i], 1360); /* Q8+Q13+1=Q22, 1360(Q13) = 0.1660 = 3.321928(log2^10) * 0.05 */ + L_temp1 = L_shr(L_temp1, 6); /* Q22 -> Q16 */ + L_temp1 = L_negate(L_temp1); + temp_lo = L_Extract_lc(L_temp1, &temp_hi); + Qsumdiv[i] = sub(14, temp_hi); + temp_sum_div_fx[i] = extract_l(Pow2(14, temp_lo)); /* Qsumdiv[i] */ + exp_norm = norm_s(temp_sum_div_fx[i]); + temp_sum_div_fx[i] = shl(temp_sum_div_fx[i], exp_norm); + move16(); + Qsumdiv[i] = add(Qsumdiv[i], exp_norm); + move16(); + } + + *Qss = 31; + move16(); + FOR (i = 0; i < num_subband_smooth_fx; i++) + { + Qo[i] = add(add(Qm, Qsumdiv[i]), 1); + L_temp1 = 0x0L; + FOR (k = 0; k < L_SB_NSS; k++) + { + L_outBufw[k + L_SB_NSS * i] = L_mult(inBufw_fx[k + L_SB_NSS * i], temp_sum_div_fx[i]); + move32(); + L_temp1 = L_or(L_temp1, L_abs(L_outBufw[k + L_SB_NSS * i])); + } + exp_norm = 31; + if (L_temp1 != 0x0L ) + { + exp_norm = norm_l(L_temp1); + } + FOR (k = 0; k < L_SB_NSS; k++) + { + L_outBufw[k + L_SB_NSS * i] = L_shl(L_outBufw[k + L_SB_NSS * i], exp_norm); + move32(); + } + Qo[i] = add(Qo[i], exp_norm); + move16(); + *Qss = s_min(*Qss, Qo[i]); + move16(); + } + + FOR (i = 0; i < num_subband_smooth_fx; i++) + { + exp_shift = sub(*Qss, Qo[i]); + exp_shift = s_max(-31, exp_shift); + FOR (k = 0; k < L_SB_NSS; k++) + { + L_outBufw[k + L_SB_NSS * i] = L_shl(L_outBufw[k + L_SB_NSS * i], exp_shift); + move16(); + outBufw_fx[k + L_SB_NSS * i] = round_fx(L_outBufw[k + L_SB_NSS * i]); + } + } + *Qss = sub(*Qss, 16); + + L_avg_val2 = L_deposit_l(0); + FOR( i = 0; i < fLen; i++ ) + { + L_r0 = L_abs(L_deposit_l(outBufw_fx[i])); + L_avg_val2 = L_add(L_avg_val2, L_r0); /* Qss */ + } + + exp_normn = norm_l(L_avg_val2); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_s(fLen); + temp_fx = div_l(L_shl(L_avg_val2, exp_normn), shl(fLen, exp_normd)); /* Q(obw+exp_normn - exp_normd) - 1 */ + avg_val2_fx = shr(temp_fx, sub(sub(exp_normn, exp_normd), 1)); /* Qss */ + + /*clip_cof = smr - 16.0f; */ + clip_cof_fx = sub(smr_fx, 2048); /* 2048: 16.0f (Q7) */ + if( clip_cof_fx < 0 ) + { + clip_cof_fx = 0; + move16(); + } + /*clip_cof += 2.5f; */ + clip_cof_fx = add(clip_cof_fx, 320); /* 320: 2.5f (Q7) */ + + thre_fx = round_fx(L_shl(L_mult(avg_val2_fx, clip_cof_fx), 8)); /* Q(Qss+7+1) -> Qss */ + thre_fx_neg = negate(thre_fx); + thre_min_fx = shr(avg_val2_fx, 2); /* *0.25f // Qss */ + + FOR(i = 0; i < fLen; i++) + { + IF( GT_16(abs_s(outBufw_fx[i]), thre_fx)) + { + temp_fx = thre_fx; + move16(); + if(outBufw_fx[i] < 0) + { + temp_fx = thre_fx_neg; + move16(); + } + outBufw_fx[i] = temp_fx; + move16(); + } + + if( LT_16(abs_s(outBufw_fx[i]), thre_min_fx)) + { + outBufw_fx[i] = 0; + move16(); + } + } + + FOR(i = 0; i < fLen; i++) + { + outBuf_fx[i] = outBufw_fx[i]; + move16(); /* Qss */ + } + + return; +} + +/*-------------------------------------------------------------------* + * return_bits_normal2 + * + * arrange bit_budget when HQ_NORMAL + *-------------------------------------------------------------------*/ + +void return_bits_normal2_fx( + Word16 *bit_budget_fx, /* i/o : bit budget */ + const Word16 p2a_flags_fx[], /* i : HF tonal indicator */ + const Word16 bands_fx, /* i : Total number of Subbands in a frame */ + const Word16 bits_lagIndices_fx[] /* i : bits for lagIndices */ +) +{ + Word16 i; + const Word16 *p_p2a_flags_fx; + + p_p2a_flags_fx = &p2a_flags_fx[sub(bands_fx, NB_SWB_SUBBANDS)]; + FOR( i=0 ; i < NB_SWB_SUBBANDS; i++ ) + { + if( EQ_16(*p_p2a_flags_fx++, 1)) + { + *bit_budget_fx = add(*bit_budget_fx, bits_lagIndices_fx[i]); + move16(); + } + } + + return; +} + +/*-------------------------------------------------------------------* + * preset_hq2_swb + * + * preset before swb_bwe_{enc,dec}_lr + *-------------------------------------------------------------------*/ + +void preset_hq2_swb_fx +( + const Word16 hqswb_clas_fx, /* i : HQ2 class information */ + const Word16 band_end_fx[], /* i : band end of each SB */ + Word16 *har_bands_fx, /* i/o : Number of LF harmonic bands */ + Word16 p2a_bands_fx, /* i : flag for peakness */ + const Word16 length_fx, /* i : processed band length */ + const Word16 bands_fx, /* i : Total number of Subbands in a frame */ + Word16 *lowlength_fx, /* o : lowband length */ + Word16 *highlength_fx, /* o : highband length */ + Word32 L_m[] /* o : MDCT */ +) +{ + IF( EQ_16(hqswb_clas_fx, HQ_HARMONIC)) + { + *har_bands_fx = add(sub(bands_fx, p2a_bands_fx), 1); + move16(); + *lowlength_fx = add(band_end_fx[*har_bands_fx-1], 1); + move16(); + } + ELSE + { + *lowlength_fx = add(band_end_fx[bands_fx-NB_SWB_SUBBANDS-1], 1); + move16(); + } + + *highlength_fx = sub(length_fx, *lowlength_fx); + move16(); + + set32_fx( L_m, 0, length_fx ); + + return; +} + +/*-------------------------------------------------------------------* + * preset_hq2_swb + * + * post process after swb_bwe_{enc,dec}_lr + *-------------------------------------------------------------------*/ + +void post_hq2_swb_fx +( + const Word32 L_m[], /* i : input_signal */ + const Word16 lowlength_fx, /* i : lowband length */ + const Word16 highlength_fx, /* i : highband length */ + const Word16 hqswb_clas_fx, /* i : HQ2 class information */ + const Word16 har_bands_fx, /* i : Number of LF harmonic bands */ + const Word16 bands_fx, /* i : Total number of Subbands in a frame */ + const Word16 p2a_flags_fx[], /* i : HF tonal indicator */ + const Word16 band_start_fx[], /* i : band start of each SB */ + const Word16 band_end_fx[], /* i : band end of each SB */ + Word32 L_y2[], /* o : output signal */ + Word16 npulses_fx[] /* i/o : Number of coded spectrum */ +) +{ + Word16 i, k; + + /* copy the scratch buffer to the output */ + Copy32( &L_m[lowlength_fx], &L_y2[lowlength_fx], highlength_fx ); + + IF( EQ_16(hqswb_clas_fx, HQ_HARMONIC)) + { + k = har_bands_fx; + move16(); + } + ELSE + { + k = sub(bands_fx, NB_SWB_SUBBANDS); + move16(); + } + + FOR( ; k= 0x0L ) + { + *ptr_L_outBuf++ = L_shr(L_mult(*ptr_predBuf_fx++, lagGains_fx[sb]), exp_shift); + move32(); /* Qss+QlagGains+1 -> QsL */ + } + ELSE + { + *ptr_L_outBuf++ = L_negate(L_shr(L_mult(abs_s(*ptr_predBuf_fx++), lagGains_fx[sb]), exp_shift)); + move32(); /* Qss+QlagGains+1 -> QsL */ + } + } + } + + ptr_L_outBuf = ptr_L_in_outBuf; + + return; +} + +/*--------------------------------------------------------------------------* + * div_s_ss + * + * compute division with Word16 Q0. ex. 10/2 -> 5 + *--------------------------------------------------------------------------*/ + +Word16 div_s_ss( /* o: result of division (Word16 Q0) */ + const Word16 n, /* i: numerator (Word16 Q0 */ + const Word16 d /* i: denominator (Word16 Q0) */ +) +{ + Word16 norm_n, norm_d; + Word16 ns, ds; + Word16 res; + + test(); + IF ( n == 0 || d == 0 ) + { + return 0; + } + + norm_n = norm_s(n); + norm_n = sub(norm_n, 1); + ns = shl(n, norm_n); + + norm_d = norm_s(d); + ds = shl(d, norm_d); + + res = shr(div_s(ns, ds), add(sub(norm_n, norm_d), 15)); + + return res; +} + +void hf_parinitiz_fx( + const Word32 L_total_brate, + const Word16 hqswb_clas_fx, + Word16 lowlength_fx, + Word16 highlength_fx, + Word16 wBands_fx[], + const Word16 **subband_search_offset_fx, + const Word16 **subband_offsets_fx, + Word16 *nBands_fx, + Word16 *nBands_search_fx, + Word16 *swb_lowband_fx, + Word16 *swb_highband_fx +) +{ + *swb_lowband_fx = lowlength_fx; + move16(); + *swb_highband_fx = highlength_fx; + move16(); + + IF( EQ_16(hqswb_clas_fx, HQ_HARMONIC)) + { + /* Mode dependent initializations (performed every frame in case mode-switching implemented) */ + *nBands_fx = NB_SWB_SUBBANDS_HAR; + move16(); + *nBands_search_fx = NB_SWB_SUBBANDS_HAR_SEARCH_SB; + move16(); + + IF ( EQ_32(L_total_brate, HQ_13k20)) + { + wBands_fx[0] = SWB_SB_BW_LEN0_12KBPS_HAR; + move16(); + wBands_fx[1] = SWB_SB_BW_LEN1_12KBPS_HAR; + move16(); + wBands_fx[2] = SWB_SB_BW_LEN2_12KBPS_HAR; + move16(); + wBands_fx[3] = SWB_SB_BW_LEN3_12KBPS_HAR; + move16(); + *subband_offsets_fx = subband_offsets_sub5_13p2kbps_Har_fx; + move16(); + *subband_search_offset_fx = subband_search_offsets_13p2kbps_Har_fx; + move16(); + } + ELSE + { + wBands_fx[0] = SWB_SB_BW_LEN0_16KBPS_HAR; + move16(); + wBands_fx[1] = SWB_SB_BW_LEN1_16KBPS_HAR; + move16(); + wBands_fx[2] = SWB_SB_BW_LEN2_16KBPS_HAR; + move16(); + wBands_fx[3] = SWB_SB_BW_LEN3_16KBPS_HAR; + move16(); + *subband_offsets_fx = subband_offsets_sub5_16p4kbps_Har_fx; + move16(); + *subband_search_offset_fx = subband_search_offsets_16p4kbps_Har_fx; + move16(); + } + } + ELSE + { + /* Mode-dependent initializations (performed every frame in case mode-switching implemented) */ + *nBands_fx = NB_SWB_SUBBANDS; + move16(); + *nBands_search_fx = NB_SWB_SUBBANDS; + move16(); + + IF ( EQ_32(L_total_brate, HQ_13k20)) + { + wBands_fx[0] = SWB_SB_LEN0_12KBPS; + move16(); + wBands_fx[1] = SWB_SB_LEN1_12KBPS; + move16(); + wBands_fx[2] = SWB_SB_LEN2_12KBPS; + move16(); + wBands_fx[3] = SWB_SB_LEN3_12KBPS; + move16(); + *subband_offsets_fx = subband_offsets_12KBPS; + move16(); + } + ELSE + { + wBands_fx[0] = SWB_SB_LEN0_16KBPS; + move16(); + wBands_fx[1] = SWB_SB_LEN1_16KBPS; + move16(); + wBands_fx[2] = SWB_SB_LEN2_16KBPS; + move16(); + wBands_fx[3] = SWB_SB_LEN3_16KBPS; + move16(); + *subband_offsets_fx = subband_offsets_16KBPS; + move16(); + } + } + + return; +} + +void GetlagGains_fx( + const Word16 *predBuf_fx, /* i: Qss Low freq. Smoothed Spectrum */ + const Word16 Qss, /* i: Q0 Q value of predBuf */ + const Word32 *L_band_energy, /* i: Qbe Band Energy */ + const Word16 Qbe, /* i: Q0 Q value of band energy */ + const Word16 nBands, /* i: Q0 number of SWB subbands */ + const Word16 *sbWidth, /* i: Q0 width of SWB subbands */ + const Word16 *lagIndices, /* i: Q0 lagIndices */ + const Word16 predBufLen, /* i: Q0 length of predBuf */ + Word16 *lagGains_fx, /* o: QlagGains lagGains */ + Word16 *QlagGains /* o: Q0 Q value of lagGains */ +) +{ + Word16 i; + Word16 sb, fLen, lag; + + Word32 L_outBuf[L_FRAME32k]; + + Word16 *ptr_ssBuf_fx; + Word32 L_lagEnergy; + Word16 Qene; + + Word16 temp_lo_fx, temp_hi_fx; + Word16 pow_fx; + Word16 Qpow; + Word16 exp_normd, exp_normn; + Word16 Qdiv; + Word16 exp_norm; + + Word16 temp_fx; + Word32 L_temp; + + Word16 ssBuf_fx[L_FRAME32k]; + Word16 exp_norm_ss; + + exp_norm_ss = 2; + move16(); + FOR (i=0; i Q16 */ + temp_lo_fx = L_Extract_lc(L_temp, &temp_hi_fx); + Qpow = sub(14, temp_hi_fx); + pow_fx = extract_l(Pow2(14, temp_lo_fx)); /* Qpow */ + + /* Div part ( pow (2.0f, band_energy[i])/lagEenegy ) */ + exp_normn = norm_s(pow_fx); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_l(L_lagEnergy); + temp_fx = div_s( shl( pow_fx, exp_normn), extract_h(L_shl(L_lagEnergy, exp_normd))); + Qdiv = add(sub(add(Qpow, exp_normn) , add(Qene, exp_normd)), 31); + + exp_norm = norm_s(temp_fx); + temp_fx = shl(temp_fx, exp_norm); + Qdiv = add(Qdiv, exp_norm); + + /* Sqrt part sqrt(pow (2.0f, band_energy[i])/lagEnergy) */ + QlagGains[sb] = add(Qdiv, 16); + IF ( s_and(Qdiv, 1) == 0 ) /* Qdiv % 2 == 0 */ + { + L_temp = Sqrt_l(L_shr(L_deposit_h(temp_fx),1), &exp_norm); + L_temp = L_shr(L_temp, exp_norm); + QlagGains[sb] = sub(shr(QlagGains[sb], 1), 1); + move16(); + lagGains_fx[sb] = round_fx(L_temp); + } + ELSE + { + L_temp = Sqrt_l(L_deposit_h(temp_fx), &exp_norm); + L_temp = L_shr(L_temp, exp_norm); + QlagGains[sb] = shr(QlagGains[sb], 1); + move16(); + lagGains_fx[sb] = round_fx(L_temp); + } + } + ELSE + { + /* lagGains[sb] = 0.0f; */ + lagGains_fx[sb] = 0; + move16(); + QlagGains[sb] = 15; + move16(); + } + } + + return; +} + +/*--------------------------------------------------------------------------* + * noise_extr_corcod() + * Spectrum normalization for the core coder + *--------------------------------------------------------------------------*/ + +void noise_extr_corcod_fx( + Word32 L_spectra[], /* i : QsL core coder */ + const Word32 L_spectra_ni[], /* i : QsL core coder with sparse filling */ + Word16 sspectra_fx[], /* o : Qss Smoothed tonal information from core coder */ + Word16 sspectra_diff_fx[], /* o : Qss non tonal infomration for gap filling */ + Word16 sspectra_ni_fx[], /* o : Qss smoothed core coder */ + const Word16 fLenLow_fx, /* i : Q0 low frequency bands width */ + Word16 prev_hqswb_clas_fx, /* i : Q0 classification information */ + Word16 *prev_ni_ratio_fx, /* i : Q15 noise parameter */ + Word16 *Qss /* o : Q0 Q value for sspectra_*_fx */ +) +{ + Word16 i,pulse_num_fx; + Word32 L_spectra_diff[L_FRAME32k]; /* QsL */ + Word16 Qss_s, Qss_d; + Word16 ni_ratio_fx, ni_ratio_cur_fx, br_adj_fx; /* Q15 */ + Word16 tmp_fx; + Word16 exp_normn, exp_normd, exp_shift; + Word16 exp_norm; + + /*Spectrum Smoothing for tonal signals*/ + SpectrumSmoothing_nss_fx( L_spectra, sspectra_fx, &Qss_s, fLenLow_fx ); + Copy(sspectra_fx, sspectra_ni_fx, fLenLow_fx); + tmp_fx = 0; + FOR(i=0; inmrValue */ + Word16 *pul_res /* i : Q0 tonal resolution */ +) +{ + Word16 i, j, k; + Word16 exp_norm; + Word16 Inv_band_width_fx[BANDS_MAX]; + Word16 QInvBW[BANDS_MAX]; + + Word16 xSynth_har_fx[L_FRAME32k]; + Word16 QxSynth; /* Q value for xSynth_har_fx */ + Word16 QxSynth_sft; /* Q value for xSynth_har_fx */ + + Word16 sb_ton_loc_fx[SWB_HAR_RAN1]; /* Q0 */ + Word16 sb_ton_fx[SWB_HAR_RAN1]; /* Qss */ + Word16 ni_gain_fx[NB_SWB_SUBBANDS]; + Word16 Qni_gain; + Word16 avg_pe_fx[NB_SWB_SUBBANDS]; + Word16 Qavg_pe[NB_SWB_SUBBANDS]; + Word16 QsN; /* Q value for xSynth_har after multipy ni_lvl */ + Word16 exp_safe; /* overflow prevent shift */ + + Word16 pos,count_pos_st,count_pos_end; + Word16 pul_res_bnd[NB_SWB_SUBBANDS]; + Word16 peak_fx[NB_SWB_SUBBANDS]; /* Qss */ + + Word32 L_E; + Word16 QE; + Word16 temp_lo_fx, temp_hi_fx; + Word32 L_temp; + Word16 exp_pow; + Word32 L_band_energy_Linear[BANDS_MAX]; + + Word16 exp_normd, exp_normn; + + Word16 E_r_fx; + Word16 QE_r; /* Q value for E_r_fx */ + + Word16 exp_shift; + + Word16 E_r_shift_fx; + Word16 fac_fx; + Word16 Qtemp; + Word16 temp2_fx, Qtemp2; + Word16 temp_fx; + + *QbeL = 3; + move16(); + Qni_gain = 8; + move16(); + + FOR(k=0; k=0 ) + { + pos = add(pos, 1); + } + count_pos_end = pos; + move16(); + pul_res_bnd[k] = sub(count_pos_end, count_pos_st); + move16(); + if(pul_res_bnd[k] > 0) + { + peak_fx[k] = abs_s(sb_ton_fx[count_pos_st]); + move16(); + } + k = add(k, 1); + } WHILE( LT_16(k, NB_SWB_SUBBANDS)); + + k = 0; + move16(); + /*energy calculation for tonal components*/ + FOR(i=har_bands; i E * pow(2.0f, -band_energy) */ + /* Pow Part */ + L_temp = L_shr(L_band_energy[i], sub(Qbe, 16)); + temp_lo_fx = L_Extract_lc(L_temp, &temp_hi_fx); + + exp_pow = sub(14, temp_hi_fx); + L_band_energy_Linear[i] = Pow2(14, temp_lo_fx); + move32(); /* Qexp_pow */ + L_band_energy_Linear[i] = L_shl(L_band_energy_Linear[i], sub(*QbeL, exp_pow)); + + /* Div Part */ + E_r_fx = 0x7fff; + move16(); + QE_r = 0; + move16(); + IF(L_band_energy_Linear[i] != 0x0L) + { + exp_normd = norm_l(L_E); + exp_normd = sub(exp_normd, 1); + exp_normn = norm_l(L_band_energy_Linear[i]); + + E_r_fx = div_s( extract_h(L_shl(L_E, exp_normd)), extract_h(L_shl(L_band_energy_Linear[i], exp_normn))); + /* QE_r = (QE-16) - (QbeL+exp_normn-16) + 15; */ + QE_r = add(sub(add(QE, exp_normd) , add(*QbeL, exp_normn)), 15); + } + + L_E = L_shl(L_E, sub(*QbeL, QE)); + QE = *QbeL; + + /* 0.06=15729(Q18) */ + exp_shift = sub(18, QE_r); + E_r_shift_fx = shl(E_r_fx, exp_shift); + + IF ( LT_16(E_r_shift_fx, 15729)) /* E_r < 0.06 */ + { + /* avg_pe[k] = (float) sqrt(pow(2.0f,band_energy[i])/band_width[i]); */ + /* Pre SQRT part */ + /*L_temp = Mpy_32_16_1(L_band_energy_Linear[i], Inv_band_width_fx[i]);*/ /* QbeL + QInvBW -15 */ + L_temp = Mult_32_16(L_band_energy_Linear[i], Inv_band_width_fx[i]); /* QbeL + QInvBW -15 */ + Qtemp = sub(add(*QbeL, QInvBW[i]), 15); + + sqrt_32n_16_fx(L_temp, Qtemp, &avg_pe_fx[k], &Qavg_pe[k]); + + fac_fx = 19661; /* 0.6(Q15) */ + IF(pul_res_bnd[k] != 0) + { + /* Div Part */ + L_temp = Mult_32_16(L_E, Inv_band_width_fx[i]); /* QE+exp_norm+QInvBW[i]+1 */ + Qtemp = sub(add(QE, QInvBW[i]), 15); + + /* SQRT Part */ + sqrt_32n_16_fx(L_temp, Qtemp, &temp2_fx, &Qtemp2); + + /* Div Part */ + exp_normd = norm_s(temp2_fx); + exp_normd = sub(exp_normd, 1); + exp_normn = norm_s(peak_fx[k]); + + fac_fx = div_s(shl(temp2_fx, exp_normd), shl(peak_fx[k], exp_normn)); + fac_fx = shl(fac_fx, sub(add(Qss, exp_normn), add(Qtemp2, exp_normd))); /* Qtemp2+exp_normd-(Qss+exp_normn)+15 -> 15*/ + + } + + ni_gain_fx[k] = mult_r(avg_pe_fx[k], fac_fx); /* Qavg_pe[k] */ move16(); + + L_temp = L_mult(ni_gain_fx[k], ni_gain_fx[k]); + L_temp = Mult_32_16(L_temp, E_r_fx); + + /* 0.12f: 257698038 (Q31) */ + if( GE_32(L_shl(L_temp,sub(31, add(add(shl(Qavg_pe[k], 1), QE_r), 1-15))), 257698038)) + { + ni_gain_fx[k] = mult_r(1638, ni_gain_fx[k]); /* 0.05 : 1638(Q15) */ move16(); + } + Overflow = 0; + move16(); + ni_gain_fx[k] = shl(ni_gain_fx[k], sub(Qni_gain, Qavg_pe[k])); + assert(Qni_gain==8); /* 358 is '(short)(1.4*pow(2,Qni_gain))' */ + ni_gain_fx[k] = s_max(ni_gain_fx[k], 358); /* 1.4 -> 22938(Q14) */ + + exp_shift = QsL-(QxSynth+Qni_gain+1); /* QsL - (QxSynth+Qni_gain+1) */ + FOR(j=band_start[i]; j<=band_end[i]; j++) + { + L_xSynth_har[j-fLenLow] = L_shl(L_mult(xSynth_har_fx[j-fLenLow], ni_gain_fx[k]), exp_shift); /* QsL - (QxSynth+Qni_gain+1) */ move32(); + } + + exp_safe = 4; /* move16(); */ + norm_vec_32_16_scale_fx(&L_xSynth_har[band_start[i]-fLenLow], QsL, band_width[i], &xSynth_har_fx[band_start[i]-fLenLow], &QxSynth_sft, exp_safe); + + L_E = sum2_fx(&xSynth_har_fx[sub(band_start[i], fLenLow)], band_width[i]); + QE = add(shl(QxSynth_sft, 1),1); + + L_E = L_shl(L_E, sub(*QbeL, QE)); + QE = *QbeL; + } + ELSE + { + /* Q8 -> Q12 */ + FOR(j=band_start[i]; j<=band_end[i]; j++) + { + L_xSynth_har[j-fLenLow] = L_shl(L_xSynth_har[j-fLenLow], 4); /* Q8(12+11-15) -> Q12 */ move32(); + } + } + + k = add(k, 1); + + L_be_tonal[i] = L_sub(L_band_energy_Linear[i], L_E); + + IF ( L_be_tonal[i] < 0x0L ) + { + L_E = L_deposit_l(0); + FOR(j=(band_start[i]-fLenLow); j<=(band_end[i]-fLenLow); j++) + { + temp_fx = round_fx(L_shl(L_xSynth_har[j], (*QbeL+7)/2)); /* (12+x-16)*2+1 => QbeL */ + L_xSynth_har[j] = L_shr(L_xSynth_har[j], 2); /* 1/4 */ move32(); + L_E = L_mac( L_E, temp_fx, temp_fx); + } + + L_E = L_shr(L_E, 4); /* 1/4 */ + L_be_tonal[i] = L_sub(L_band_energy_Linear[i], L_E); + move32(); + } + } + + return; +} + + +/*--------------------------------------------------------------------------* + * Gettonl_scalfact() + * Gap filling for the core coder + *--------------------------------------------------------------------------*/ +void Gettonl_scalfact_fx +( + Word32 *L_outBuf, /* i/o: QsL synthesized spectrum */ + Word16 QsL, /* i : Q0 Q value for outBuf */ + const Word32 *L_codbuf, /* i : QsL core coder */ + const Word16 fLenLow, /* i : Q0 lowband length */ + const Word16 fLenHigh, /* i : Q0 highband length */ + const Word16 harmonic_band, /* i : Q0 total number of Low frequency bands */ + const Word16 bands, /* i : Q0 total number of subbands in a frame */ + Word32 *L_band_energy, /* i : Qbe band energy of each subband */ + Word16 Qbe, /* i : Q0 Q value for band_energy */ + const Word16 *band_start, /* i : Q0 subband start indices */ + const Word16 *band_end, /* i : Q0 subband end indices */ + const Word16 p2aflags[], /* i : Q0 missing bands in the core coder */ + Word32 L_be_tonal[], /* i : QbeL tonal energy */ + Word16 QbeL, /* i : Q0 Q value for be_tonal */ + GainItem_fx *pk_sf_fx, /* i : toanl information for Sparse filling */ + Word16 Qss, /* i : Q0 Q value for pk_sf.nmrValue */ + Word16 *pul_res_pk /* i : Q0 pulse resolution information */ +) +{ + Word16 i, j, tmp; + Word16 sb_ton_fx[SWB_HAR_RAN1]; /* Qss */ + Word16 sb_ton_loc_fx[SWB_HAR_RAN1]; /* Q0 */ + Word32 L_est_ton_ene[NB_SWB_SUBBANDS]; /* QetEne */ + Word16 QetEne; + Word16 band_sf_fx[SWB_HAR_RAN1]; /* Qton_sf */ + Word16 pos_fx, k_fx, pos_tmp_fx; /* Q0 */ + Word16 exp_safe; + Word16 temp_fx; + Word16 Qtemp; + + Word16 band_pos_fx; + Word16 count_pos_st_fx, count_pos_end_fx; + + Word16 exp_normd, exp_normn; + + Word16 ton_sf_fx; /* Qton_sf */ + Word16 Qton_sf; + + Word16 step_fx; /* Q15 */ + Word32 L_temp; + + Word16 enrd_r_fx; /* Q15 */ + + Word32 L_band_energy_Linear[BANDS_MAX]; /* QbeL */ + Word16 temp_hi_fx, temp_lo_fx; + Word16 exp_pow; + Word16 exp_shift; + + Word16 Qbsf2[SWB_HAR_RAN1]; + + Qton_sf = sub(sub(QsL, Qss), 1); + + enrd_r_fx = 29491; + move16(); /* 0.9: 29491.2(Q15) */ + + set32_fx(L_est_ton_ene, 0x0L, NB_SWB_SUBBANDS); + set16_fx(sb_ton_loc_fx, -1,SWB_HAR_RAN1); + + /* Get the tonal information for sparse filling */ + pos_fx = 0; + move16(); + FOR(k_fx=0; k_fx=0) + { + test(); + pos_fx = add(pos_fx, 1); + } + count_pos_end_fx = pos_fx; + move16(); + + exp_safe = 2; /* move16(); */ + QetEne = add(shl(sub(Qss, exp_safe), 1), 1); + L_temp = L_add(L_est_ton_ene[k_fx], 0); + FOR(i=count_pos_st_fx; i 0x0L ) + { + ton_sf_fx = div_l(L_shl(L_be_tonal[band_pos_fx], exp_normd), extract_h(L_shl(L_est_ton_ene[k_fx], exp_normn))); /* QbeL+exp_normd - (QetEne+exp_normn-16) - 1 */ + } + + /* Sqrt Part */ + /*sqrt_32n_16_fx(L_deposit_h(ton_sf_fx), (QbeL+exp_normd)-(QetEne+exp_normn-16)-1+16, &ton_sf_fx, &Qton_sf);*/ + sqrt_32n_16_fx(L_deposit_h(ton_sf_fx), add(sub(add(QbeL, exp_normd), add(QetEne, exp_normn)), 31), &ton_sf_fx, &Qton_sf); + + FOR(i=count_pos_st_fx; i 0x0L ) + { + /* enrd_r *=(float)sqrt(be_tonal[band_pos]/pow(2.0f,band_energy[band_pos])); */ + /* Pow Part */ + L_temp = L_shr(L_band_energy[band_pos_fx], sub(Qbe, 16)); + temp_lo_fx = L_Extract_lc(L_temp, &temp_hi_fx); + exp_pow = sub(14, temp_hi_fx); + L_band_energy_Linear[band_pos_fx] = Pow2(14, temp_lo_fx); + move32(); /* Qexp_pow */ + L_band_energy_Linear[band_pos_fx] = L_shl(L_band_energy_Linear[band_pos_fx], sub(QbeL, exp_pow)); + + /* Div Part */ + exp_normd = norm_l(L_be_tonal[band_pos_fx]); + exp_normd = sub(exp_normd, 1); + exp_normn = norm_l(L_band_energy_Linear[band_pos_fx]); + temp_fx = div_l(L_shl(L_be_tonal[band_pos_fx], exp_normd), extract_h(L_shl(L_band_energy_Linear[band_pos_fx], exp_normn))); /* QbeL+exp_normd-(QbeL+exp_normn-16)-1 */ + sqrt_32n_16_fx(L_deposit_h(temp_fx), add(sub(exp_normd, exp_normn), 31), &temp_fx, &Qtemp); + enrd_r_fx = extract_h(L_shl(L_mult(enrd_r_fx, temp_fx), sub(15, Qtemp))); + + enrd_r_fx = sub(enrd_r_fx, step_fx); + } + ELSE + { + enrd_r_fx = 0x0; + move16(); + } + + IF(EQ_16(p2aflags[band_pos_fx], 1)) + { + FOR(i= band_start[band_pos_fx]; i<=band_end[band_pos_fx]; i++) + { + L_outBuf[i-fLenLow] = L_codbuf[i]; + move32(); + } + } + ELSE + { + pos_fx = 0; + move16(); + pos_fx = add(pos_fx, pos_tmp_fx); + exp_shift = sub(sub(QsL, Qss), 1); + FOR(j=0; j 4+4=8 */ + + L_tmp = L_deposit_l(0); + FOR( i=0; i 15 */ /* 0.7(22937.6:Q15)*/ + L_thr = Mult_32_16(L_thr, temp_fx); + + IF( LT_16(peak_cnt_fx, n_nbiggestsearch)) + { + FOR (j = 0; j < nIdx_fx; j++) + { + IF( GT_32(L_abs_in[j], L_thr)) + { + pk_sf_fx[peak_cnt_fx].nmrValue_fx = round_fx(L_abs_in[j]); /* Qabs_in-16 */ + pk_sf_fx[peak_cnt_fx].gainIndex_fx = j; + move16(); + L_abs_in[j] = L_deposit_l(0); + peak_cnt_fx = add(peak_cnt_fx, 1); + move16(); + } + + IF( EQ_16(peak_cnt_fx, n_nbiggestsearch)) + { + BREAK; + } + } + } + + /* thr *= (0.6f / n_nbiggestsearch) * peak_cnt + 0.3f; */ + /* 0.6=19661(Q15) */ + temp_fx = div_s_ss(19661, n_nbiggestsearch); + L_temp = L_mult(temp_fx, peak_cnt_fx); /* 15+0+1 */ + temp_fx = add(round_fx(L_shl(L_temp, 15)), 9830); /* shift: 16+15-16 -> 15 */ /* 0.3(9830.4:Q15)*/ + + L_thr = Mult_32_16(L_thr, temp_fx); + IF( LT_16(peak_cnt_fx, n_nbiggestsearch)) + { + FOR (j = 0; j < nIdx_fx; j++) + { + IF( GT_32(L_abs_in[j], L_thr)) + { + pk_sf_fx[peak_cnt_fx].nmrValue_fx = round_fx(L_abs_in[j]); /* Qabs_in-16 */ + pk_sf_fx[peak_cnt_fx].gainIndex_fx = j; + move16(); + L_abs_in[j] = L_deposit_l(0); + peak_cnt_fx = add(peak_cnt_fx, 1); + move16(); + } + + IF( EQ_16(peak_cnt_fx, n_nbiggestsearch)) + { + BREAK; + } + } + } + + *n_fx = peak_cnt_fx; + move16(); +} + +/*--------------------------------------------------------------------------* + * spectrumsmooth_noiseton() + * Spectrum normalization for the the core coder + *--------------------------------------------------------------------------*/ +Word16 spectrumsmooth_noiseton_fx( /* o : Qss ss_min */ + Word32 L_spectra[], /* i : Qs core coder */ + /*Word16 Qs,*/ /* i : Q0 Q value for spectra, spectra_ni */ + const Word32 L_spectra_ni[], /* i : Qs core coder with sparse filling */ + Word16 sspectra_fx[], /* o : Qss Smoothed tonal information from core coder */ + Word16 sspectra_diff_fx[], /* o : Qss non tonal infomration for gap filling */ + Word16 sspectra_ni_fx[], /* o : Qss smoothed core coder */ + Word16 *Qss, /* o : Q0 Q value for sspectra* */ + const Word16 fLenLow_fx, /* i : Q0 low frequency boundaries */ + Word16 *ni_seed_fx /* io : Q0 random seed */ +) +{ + Word16 i; + Word32 L_spectra_diff[L_FRAME32k]; + Word16 ni_ratio_fx; /* Q15 */ + Word16 ss_min_fx; /* Q10 */ + Word16 cut_sig_th_fx; /* Q10 */ + Word16 cut_ni_th_fx; /* Q10 */ + Word16 pcnt_fx, sign_fx; + Word16 exp_normn, exp_normd; + + Word16 ratio_fx; + Word32 L_temp; + Word32 L_spectra_rm[L_FRAME32k]; + Word32 L_cut_input=410; + Word16 rand_a_fx[L_FRAME32k]; + + /* pre-prepare random array for float-fix interoperability */ + FOR(i=0; i Q2 */ move16(); + } + p_L_En++; + p_sqrt_En_fx++; + } + + p_sqrt_En_fx = sqrt_En_fx; + p_Enn_sm_sb_fx = Enn_sm_sb_fx; + p_prev_En_sb_fx = prev_En_sb_fx; + FOR(k=BANDS_fx-NB_SWB_SUBBANDS; k Q14 */ + FOR(i=band_start_fx[k]; i<=band_end_fx[k]; i++) + { + IF( LE_32(L_abs(L_xSynth_har[i-fLenLow_fx]), L_th_g[k-(BANDS_fx-NB_SWB_SUBBANDS)])) + { + IF(map_pulse_fx[i] == 0) + { + L_xSynth_har[i-fLenLow_fx] = L_shl(Mult_32_16(L_xSynth_har[i-fLenLow_fx], ni_scale_fx), 1); /* Q12+Q14-15-1 = Q12 */ move32(); + } + } + } + *p_prev_En_sb_fx = *p_Enn_sm_sb_fx; + move16(); + } + p_Enn_sm_sb_fx++; + p_sqrt_En_fx++; + p_prev_En_sb_fx++; + } + + return; +} + +/*--------------------------------------------------------------------------* + * updat_prev_frm() + * + * + *--------------------------------------------------------------------------*/ +void updat_prev_frm_fx( + Word32 L_y2[], /* i/o: core coder buffer */ + Word32 L_t_audio[], /* o: core coder buffer */ + Word32 L_bwe_br, /* i: core bitrate */ + Word16 length_fx, /* i: frame length coded bw */ + const Word16 inner_frame_fx, /* i: input frame length */ + Word16 bands_fx, /* i: sub band resolution */ + Word16 bwidth_fx, /* i: NB/WB/SWB indicator */ + const Word16 is_transient_fx, /* i: signal class information */ + Word16 hqswb_clas_fx, /* i: signal class information */ + Word16 *prev_hqswb_clas_fx, /* o: update signal class information */ + Word16 prev_SWB_peak_pos_fx[], /* o: update core coder last coded peaks*/ + Word16 prev_SWB_peak_pos_tmp_fx[], /* o: update core coder last coded peaks*/ + Word16 *prev_frm_hfe2_fx, /* o: update harmonics */ + Word16 *prev_stab_hfe2_fx, /* o: update harmonics */ + Word16 bws_cnt_fx /* i: band width detector */ +) +{ + Word16 i, j, k; + Word16 k1_fx, k2_fx; + Word16 length1_fx, length2_fx, length3_fx; + + /* Copy the coded MDCT coefficient to the output buffer */ + IF ( !is_transient_fx ) + { + /* Copy the scratch buffer to the output */ + Copy32( L_y2, L_t_audio, length_fx ); + + /* If the input frame is larger than coded bandwidth, zero out uncoded MDCT coefficients */ + IF ( GT_16(inner_frame_fx, length_fx)) + { + set32_fx( L_t_audio + length_fx, 0x0L, sub(inner_frame_fx, length_fx) ); + } + } + ELSE /* transient frame */ + { + test(); + IF( EQ_16(inner_frame_fx, length_fx)||bws_cnt_fx>0) + { + /* Copy the scratch buffer to the output */ + Copy32( L_y2, L_t_audio, length_fx ); + } + ELSE + { + /* length/NUM_TIME_SWITCHING_BLOCKS */ + /*length1_fx = div_s_ss(length_fx, NUM_TIME_SWITCHING_BLOCKS); */ + length1_fx = shr(length_fx, 2); /* length1 = length/NUM_TIME_SWITCHING_BLOCKS */ + /* inner_frame/NUM_TIME_SWITCHING_BLOCKS */ + /*length2_fx = div_s_ss(inner_frame_fx, NUM_TIME_SWITCHING_BLOCKS); */ + length2_fx = shr(inner_frame_fx, 2); /* length2 = inner_frame/NUM_TIME_SWITCHING_BLOCKS */ + /* (inner_frame-length)/NUM_TIME_SWITCHING_BLOCKS */ + /*length3_fx = div_s_ss(sub(inner_frame_fx, length_fx), NUM_TIME_SWITCHING_BLOCKS); */ + length3_fx = shr(sub(inner_frame_fx, length_fx) ,2); /* (inner_frame-length)/NUM_TIME_SWITCHING_BLOCKS */ + + k1_fx = 0; + move16(); + k2_fx = 0; + move16(); + + /* un-collapse transient frame and interleave zeros */ + FOR( i = 0; i < NUM_TIME_SWITCHING_BLOCKS; i++ ) + { + /*k1 = i*length/NUM_TIME_SWITCHING_BLOCKS; */ + /*k2 = i*inner_frame/NUM_TIME_SWITCHING_BLOCKS; */ + + Copy32( L_y2 + k1_fx, L_t_audio + k2_fx, length1_fx ); + set32_fx( L_t_audio + k2_fx + length1_fx, 0x0L, length3_fx); + + k1_fx = add(k1_fx, length1_fx); + k2_fx = add(k2_fx, length2_fx); + + } + } + } + + IF( (EQ_32(L_bwe_br, HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))&&EQ_16(bwidth_fx,SWB)) + { + *prev_hqswb_clas_fx = hqswb_clas_fx; + move16(); + IF ( NE_16(hqswb_clas_fx, HQ_HARMONIC)) + { + *prev_frm_hfe2_fx = 0; + move16(); + *prev_stab_hfe2_fx = 0; + move16(); + } + } + ELSE + { + *prev_hqswb_clas_fx = is_transient_fx; + move16(); + } + + test(); + test(); + test(); + IF( (EQ_32(L_bwe_br, HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))&&EQ_16(bwidth_fx,SWB)&&EQ_16(hqswb_clas_fx,HQ_NORMAL)) + { + j = 0; + move16(); + FOR(k=sub(bands_fx, SPT_SHORTEN_SBNUM); k +#include "options.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "stl.h" +#include "basop_util.h" + +/*-----------------------------------------------------------------* +* Local functions +*-----------------------------------------------------------------*/ + +static void create_random_vector_fx( Word16 output[], const Word16 length, Word16 seed[] ); + +static void flip_spectrum_fx( const Word16 input[], Word16 output[], const Word16 length ); + +static void Calc_st_filt_tbe(Word16 * apond2,Word16 * apond1,Word16 * parcor0,Word16 * sig_ltp_ptr,Word16 * mem_zero ); + +static void Hilbert_transform_fx( Word32 tmp_R[], Word32 tmp_I[], Word32 *tmpi_R, Word32 *tmpi_I, const Word16 length, const Word16 HB_stage_id ); + +static void Hilbert_transform_sp_fx( Word16 tmp_R[], Word16 tmp_I[], Word32 *tmpi_R, Word32 *tmpi_I, const Word16 length, const Word16 HB_stage_id ); + +void Estimate_mix_factors_fx( const Word16 *shb_res, const Word16 Q_shb, const Word16 *exc16kWhtnd, const Word16 Q_bwe_exc, const Word16 *White_exc16k_frac, + const Word16 Q_frac, const Word32 pow1, const Word16 Q_pow1, const Word32 pow22, const Word16 Q_pow22, Word16 *vf_modified, Word16 *vf_ind ); + +/*-------------------------------------------------------------------* +* swb_tbe_reset() +* +* Reset the SWB TBE encoder +*-------------------------------------------------------------------*/ + + +void swb_tbe_reset_fx( + Word32 mem_csfilt[], + Word16 mem_genSHBexc_filt_down_shb[], + Word16 state_lpc_syn[], + Word16 syn_overlap[], + Word16 state_syn_shbexc[], + Word16* tbe_demph, + Word16* tbe_premph, + Word16 mem_stp_swb[], + Word16* gain_prec_swb +) +{ + set32_fx( mem_csfilt, 0, 2 ); + set16_fx( mem_genSHBexc_filt_down_shb, 0, (2*ALLPASSSECTIONS_STEEP+1)); + set16_fx( state_lpc_syn, 0, LPC_SHB_ORDER ); + + set16_fx( syn_overlap, 0, L_SHB_LAHEAD ); + set16_fx( state_syn_shbexc, 0, L_SHB_LAHEAD ); + + *tbe_demph = 0; + move16(); + *tbe_premph = 0; + move16(); + + set16_fx(mem_stp_swb, 0, LPC_SHB_ORDER); + *gain_prec_swb = 16384; + move16();/*Q14 = 1 */ + + return; +} + + +/*-------------------------------------------------------------------* +* swb_tbe_reset_synth() +* +* Reset the extra parameters needed for synthesis of the SWB TBE output +*-------------------------------------------------------------------*/ + + +void swb_tbe_reset_synth_fx( + Word32 genSHBsynth_Hilbert_Mem[], + Word16 genSHBsynth_state_lsyn_filt_shb_local_fx[] ) +{ + + set32_fx( genSHBsynth_Hilbert_Mem, 0, HILBERT_MEM_SIZE ); + set16_fx( genSHBsynth_state_lsyn_filt_shb_local_fx, 0, 2*ALLPASSSECTIONS_STEEP ); + + return; +} + + +/*-------------------------------------------------------------------* + * fb_tbe_reset_synth_fx() + * + * reset of FB TBE memories + *-------------------------------------------------------------------*/ + +void fb_tbe_reset_synth_fx( + Word32 fbbwe_hpf_mem_fx[][4], + Word16 fbbwe_hpf_mem_fx_Q[], + Word16 *prev_fbbwe_ratio_fx +) +{ + set32_fx( fbbwe_hpf_mem_fx[0], 0, 4 ); + set32_fx( fbbwe_hpf_mem_fx[1], 0, 4 ); + set32_fx( fbbwe_hpf_mem_fx[2], 0, 4 ); + set32_fx( fbbwe_hpf_mem_fx[3], 0, 4 ); + set16_fx( fbbwe_hpf_mem_fx_Q, 0, 4 ); + *prev_fbbwe_ratio_fx = 1; + move16(); /*should be set to 1.0f, scaling unknown */ + + return; +} + + +/*-------------------------------------------------------------------* + * tbe_celp_exc_offset() + * + * Compute tbe bwe celp excitation offset + *-------------------------------------------------------------------*/ + +Word16 tbe_celp_exc_offset( + const Word16 T0_fx, /* i : Integer pitch */ + const Word16 T0_frac_fx, /* i : Fractional part of the pitch */ + const Word16 L_frame /* i : frame lenght */ +) +{ + Word16 offset_fx, tmp_fx, tmp1_fx, tmp2_fx, tmp_fac; + tmp_fac = 320; + move16(); /*2.5 in Q7*/ + if(EQ_16(L_frame, L_FRAME16k)) + { + tmp_fac = 256; + move16(); /*2.0 in Q7*/ + } + tmp_fx = extract_l(L_mult(T0_frac_fx,32));/*Q8, 0.25 in Q7*/ + tmp_fx = add(512,tmp_fx);/*Q8; 2 in Q8*/ + tmp_fx = mult_r(tmp_fx,tmp_fac);/*Q16->Q0; 2.5 in Q7 or 2.0 in Q7 */ + + tmp1_fx = sub(T0_fx,2);/*Q0*/ + + tmp2_fx = shl(tmp1_fx,1);/*Q0 */ + + IF(EQ_16(L_frame, L_FRAME)) + { + tmp2_fx = add(shl(tmp1_fx,1),shr(tmp1_fx,1));/*Q0; (5/2 = 2 + 1/2)*/ + } + + offset_fx = add(tmp_fx,tmp2_fx);/*Q0*/ + + return offset_fx; +} + +/*-------------------------------------------------------------------* +* swb_tbe_celp_exc() +* +* Compute tbe bwe celp excitation +*-------------------------------------------------------------------*/ +void tbe_celp_exc( + const Word16 L_frame_fx, /* i : Frame lenght */ + const Word16 i_subfr_fx, /* i : sub frame */ + const Word16 T0_fx, /* i : Integer pitch */ + const Word16 T0_frac_fx, /* i : Fractional part of the pitch */ + Word16 *error_fx, /* i/o: Error */ + Word16 *bwe_exc_fx /* i/o: bandwitdh extension signal */ +) +{ + Word16 offset_fx, tmp_fx, i; + IF( EQ_16(L_frame_fx,L_FRAME)) + { + /*offset = T0 * HIBND_ACB_L_FAC + (int) ((float) T0_frac * 0.25f * HIBND_ACB_L_FAC + 2 * HIBND_ACB_L_FAC + 0.5f) - 2 * HIBND_ACB_L_FAC; + for (i=0; i0) + { + tmp_fx = shr(*error_fx,5);/*Q0*/ + } + ELSE + { + tmp_fx = negate(shr(abs_s(*error_fx),5));/*Q0*/ + } + + FOR (i=0; i0) + { + tmp_fx = shr(*error_fx,5);/*Q0*/ + } + ELSE + { + tmp_fx = negate(shr(abs_s(*error_fx),5));/*Q0*/ + } + + FOR (i=0; i= period ) + { + *phase_state = 0; + move16(); + } + + i = 0; + move16(); + j = *phase_state; + move16(); + + WHILE ( i < length ) + { + WHILE ( ( j < period ) && ( i < length ) ) + { + L_tmp = Mult_32_16( tmp_R[i + 4], local_cos_table[j] ); /*//Qx+16 */ + L_tmp = Madd_32_16( L_tmp, tmp_I[i + 4], local_negsin_table[j] ); /*Qx+16 */ + output[i] = round_fx( L_tmp ); /*Qx */ + i++ ; + j++ ; + } + + if ( j >= period ) + { + j = 0; + move16(); + } + } + + *phase_state = j; + move16(); + return; +} + + +/*---------------------------------------------- + * Hilbert transform - Double precision + *------------------------------------------------*/ +static void Hilbert_transform_fx( Word32 tmp_R[], /* i: Real component of HB */ + Word32 tmp_I[], /* i: Real component of HB */ + Word32 tmpi_R[], /* o: Real component of HB */ + Word32 tmpi_I[], /* o: Imag. component of HB */ + const Word16 length, /* i: input length */ + const Word16 HB_stage_id /* i: HB transform stage */ + ) +{ + Word16 i, hb_filter_stage, offset; + Word32 L_tmp; + + hb_filter_stage = 2*HB_stage_id; + offset = 0; + move16(); + if( HB_stage_id == 0 ) + { + offset = 1; + move16(); + } + + test(); + test(); + IF (HB_stage_id == 0 || HB_stage_id == 2) + { + FOR ( i = 0; i < length; i++ ) + { + L_tmp = Mult_32_16( tmp_R[i + 4], Hilbert_coeffs_fx[hb_filter_stage][0 + offset] ); /*Qx+15 */ + L_tmp = Madd_32_16( L_tmp, tmp_R[i + 2], Hilbert_coeffs_fx[hb_filter_stage][2 + offset] ); /*Qx+15 */ + L_tmp = Madd_32_16( L_tmp, tmp_R[i] , Hilbert_coeffs_fx[hb_filter_stage][4 + offset] );/*Qx+15 */ + tmpi_R[i] = L_shl( L_tmp, 1 ); + move32(); /*Qx+16 */ + + L_tmp = Mult_32_16( tmp_I[i + 4 + offset], Hilbert_coeffs_fx[hb_filter_stage+1][0] ); /*Qx+15 */ + L_tmp = Madd_32_16( L_tmp, tmp_I[i + 2 + offset], Hilbert_coeffs_fx[hb_filter_stage+1][2] ); /*Qx+15 */ + L_tmp = Madd_32_16( L_tmp, tmp_I[i + offset] , Hilbert_coeffs_fx[hb_filter_stage+1][4] ); /*Qx+15 */ + tmpi_I[i] = L_shl( L_tmp, 1 ); + move32(); /*Qx+16 */ + } + } + ELSE IF (HB_stage_id == 1 || HB_stage_id == 3) + { + FOR ( i = 0; i < length; i++ ) + { + + L_tmp = Mult_32_16( tmpi_R[i + 2], Hilbert_coeffs_fx[hb_filter_stage][2] ); /*Qx+15 */ + L_tmp = Madd_32_16( L_tmp, tmpi_R[i] , Hilbert_coeffs_fx[hb_filter_stage][4] ); /*Qx+15 */ + tmpi_R[i + 4] = L_sub( tmp_R[i], L_shl( L_tmp, 1 ) ); + move32();/*Qx+16 */ + + L_tmp = Mult_32_16( tmpi_I[i + 2], Hilbert_coeffs_fx[hb_filter_stage+1][2] ); /*Qx+15 */ + L_tmp = Madd_32_16( L_tmp, tmpi_I[i] , Hilbert_coeffs_fx[hb_filter_stage+1][4] ); /*Qx+15 */ + tmpi_I[i + 4] = L_sub( tmp_I[i], L_shl( L_tmp, 1 ) ); + move32(); /*Qx+16 */ + } + } +} + + +/*---------------------------------------------- +* Hilbert transform - Single precision Stage 0 +*------------------------------------------------*/ +static void Hilbert_transform_sp_fx( Word16 tmp_R[], /* i: Real component of HB */ + Word16 tmp_I[], /* i: Real component of HB */ + Word32 tmpi_R[], /* o: Real component of HB */ + Word32 tmpi_I[], /* o: Imag. component of HB */ + const Word16 length, /* i: input length */ + const Word16 HB_stage_id /* i: HB transform stage */ + ) +{ + Word16 i, hb_filter_stage, offset; + Word32 L_tmp; + + hb_filter_stage = shl(HB_stage_id,1); + offset = 0; + move16(); + if( HB_stage_id == 0 ) + { + offset = 1; + move16(); + } + + /* Hilbert single precision stage 0 */ + FOR ( i = 0; i < length; i++ ) + { + L_tmp = L_mult( tmp_R[i + 4], Hilbert_coeffs_fx[hb_filter_stage][0 + offset] ); /*Qx */ + L_tmp = L_mac ( L_tmp, tmp_R[i + 2], Hilbert_coeffs_fx[hb_filter_stage][2 + offset] ); /*Qx */ + L_tmp = L_mac ( L_tmp, tmp_R[i] , Hilbert_coeffs_fx[hb_filter_stage][4 + offset] ); /*Qx */ + tmpi_R[i] = L_shl ( L_tmp, 1 ); + move32(); /*Qx+16 */ + + L_tmp = L_mult( tmp_I[i + 4 + offset], Hilbert_coeffs_fx[hb_filter_stage+1][0] ); /*Qx */ + L_tmp = L_mac ( L_tmp, tmp_I[i + 2 + offset], Hilbert_coeffs_fx[hb_filter_stage+1][2] ); /*Qx */ + L_tmp = L_mac ( L_tmp, tmp_I[i + offset] , Hilbert_coeffs_fx[hb_filter_stage+1][4] ); /*Qx */ + tmpi_I[i] = L_shl ( L_tmp, 1 ); + move32(); /*Qx+16 */ + } + + return; +} + + +/*---------------------------------------------- + * flip_spectrum_fx + *----------------------------------------------*/ +void flip_spectrum_fx( + const Word16 input[], /* i : input spectrum */ + Word16 output[], /* o : output spectrum */ + const Word16 length /* i : vector length */ +) +{ + Word16 i; + + FOR ( i = 0; i < length; i = i + 2 ) + { + output[i] = negate( input[i] ); + move16(); + output[i + 1] = input[i + 1]; + move16(); + } + + return; +} + + +/*---------------------------------------------------------------------------- + * calc_rc0_h + * + * computes 1st parcor from composed filter impulse response + *---------------------------------------------------------------------------*/ +void Calc_rc0_h( + Word16 * h, /* i : impulse response of composed filter */ + Word16 * rc0 /* o : 1st parcor */ +) +{ + Word32 L_acc; + Word16 *ptrs; + Word16 acf0, acf1; + Word16 temp, sh_acf; + Word16 i; + + /* computation of the autocorrelation function acf */ + L_acc = L_mult(h[0], h[0]); + FOR(i = 1; i < LONG_H_ST; i++) + { + L_acc = L_mac(L_acc, h[i], h[i]); + } + sh_acf = norm_l(L_acc); + L_acc = L_shl(L_acc, sh_acf); + acf0 = extract_h(L_acc); + + ptrs = h; + + temp = *ptrs++; + move16(); + L_acc = L_mult(temp, *ptrs); + FOR(i = 1; i < LONG_H_ST - 1; i++) + { + temp = *ptrs++; + move16(); + L_acc = L_mac(L_acc, temp, *ptrs); + } + L_acc = L_shl(L_acc, sh_acf); + acf1 = extract_h(L_acc); + + /* Compute 1st parcor */ + if (acf0 == 0) + { + *rc0 = 0; + move16(); + return; + } + + IF (LT_16(acf0, abs_s(acf1))) + { + *rc0 = 0; + move16(); + return; + } + *rc0 = div_s(abs_s(acf1), acf0); + move16(); + if (acf1 > 0) + { + *rc0 = negate(*rc0); + move16(); + } +} + +static void Calc_st_filt_tbe( + Word16 * apond2, /* i : coefficients of numerator */ + Word16 * apond1, /* i : coefficients of denominator */ + Word16 * parcor0, /* o : 1st parcor calcul. on composed filter */ + Word16 * sig_ltp_ptr, /* i/o: i of 1/A(gamma1) : scaled by 1/g0 */ + Word16 * mem_zero /* i : All zero memory */ +) +{ + Word32 L_g0; + + Word16 h[LONG_H_ST]; + + Word16 g0, temp; + Word16 i; + temp = sub( 2, norm_s( apond2[0] ) ); + /* compute i.r. of composed filter apond2 / apond1 */ + Syn_filt_s(temp, apond1, LPC_SHB_ORDER, apond2, h, LONG_H_ST, mem_zero, 0); + /* compute 1st parcor */ + Calc_rc0_h(h, parcor0); + + /* compute g0 */ + L_g0 = L_mult0(1, abs_s(h[0])); + FOR (i = 1; i < LONG_H_ST; i++) + { + L_g0 = L_mac0(L_g0, 1, abs_s(h[i])); + } + g0 = extract_h(L_shl(L_g0, 14)); + + /* Scale signal i of 1/A(gamma1) */ + IF (GT_16(g0, 1024)) + { + temp = div_s(1024, g0); /* temp = 2**15 / gain0 */ + FOR (i = 0; i < L_SUBFR16k; i++) + { + sig_ltp_ptr[i] = mult_r(sig_ltp_ptr[i], temp); + move16(); + } + } +} + +static void filt_mu_fx( + const Word16 *sig_in, /* i : signal (beginning at sample -1) */ + Word16 *sig_out, /* o : output signal */ + const Word16 parcor0, /* i : parcor0 (mu = parcor0 * gamma3) */ + Word16 SubFrameLength /* i : the length of subframe */ +) +{ + Word16 n; + Word16 mu, ga, temp; + const Word16 *ptrs; + Word16 tmp,exp; + + + IF ( EQ_16(SubFrameLength ,L_SUBFR )) + { + IF (parcor0 > 0) + { + mu = mult_r(parcor0 , GAMMA3_PLUS_FX); + } + ELSE + { + mu = mult_r(parcor0 , GAMMA3_MINUS_FX); + } + } + ELSE + { + IF(parcor0 > 0) + { + mu = mult_r( parcor0 , GAMMA3_PLUS_WB_FX); + } + ELSE + { + mu = mult_r( parcor0 , GAMMA3_MINUS_WB_FX); + } + } + + tmp = abs_s(mu); + tmp = sub(32767 , tmp); + exp = norm_s(tmp); + tmp = div_s(shl(1,sub(14,exp)),tmp);/*(14 - exp) */ + ga = shl(tmp ,exp);/*Q14 */ + + + /* ga = (float) 1. / ((float) 1. - (float) fabs (mu)); */ + + ptrs = sig_in; /* points on sig_in(-1) */ + + FOR (n = 0; n < SubFrameLength; n++) + { + temp = mult_r(mu , (*ptrs++)); + temp = add (temp ,*ptrs );/*Q12 */ + sig_out[n] = shl(mult_r( ga , temp),1); + move16();/*Q12 */ + } + + return; +} + +static void scale_st_swb( + const Word16 * sig_in_fx, /* i : postfilter i signal */ + Word16 * sig_out_fx, /* i/o: postfilter o signal */ + Word16 * gain_prec_fx, /* i/o: last value of gain for subframe */ + Word16 SubFrameLength +) +{ + Word16 i; + Word16 agc_fac1_para_fx; + Word16 agc_fac_para_fx; + Word32 L_acc,L_temp; + Word16 g0_fx, gain_fx; + Word16 scal_in, scal_out; + Word16 s_g_in, s_g_out,sh_g0,temp; + + + IF ( EQ_16(SubFrameLength ,L_SUBFR )) + { + agc_fac1_para_fx = AGC_FAC1_FX; + move16(); + agc_fac_para_fx = AGC_FAC_FX; + move16(); + } + ELSE /*IF( SubFrameLength == L_SUBFR16k ) */ + { + agc_fac1_para_fx = AGC_FAC1_WB_FX; + move16(); + agc_fac_para_fx = AGC_FAC_WB_FX; + move16(); + } + + /* compute input gain */ + L_acc = L_mult0(1, abs_s(sig_in_fx[0]));/*0 +Q_bwe_exc-1 */ + FOR (i = 1; i < SubFrameLength; i++) + { + L_acc = L_mac0(L_acc, 1, abs_s(sig_in_fx[i])); /*Q_bwe_exc-1 */ + } + + g0_fx = 0; + move16(); + IF (L_acc != 0L) + { + scal_in = norm_l(L_acc); + L_acc = L_shl(L_acc, scal_in); + s_g_in = extract_h(L_acc); /* normalized */ + + /* Compute o gain */ + L_acc = L_mult0(1, abs_s(sig_out_fx[0])); + FOR (i = 1; i < SubFrameLength; i++) + { + L_acc = L_mac0(L_acc, 1, abs_s(sig_out_fx[i])); + } + IF (L_acc == 0L) + { + *gain_prec_fx = 0; + move16(); + + return; + } + + scal_out = norm_l(L_acc); + L_acc = L_shl(L_acc, scal_out); + s_g_out = extract_h(L_acc); /* normalized */ + + + sh_g0 = add(scal_in, 1); + sh_g0 = sub(sh_g0, scal_out); /* scal_in - scal_out + 1 */ + IF (LT_16(s_g_in, s_g_out)) + { + g0_fx = div_s(s_g_in, s_g_out); /* s_g_in/s_g_out in Q15 */ + } + ELSE + { + temp = sub(s_g_in, s_g_out); /* sufficient since normalized */ + g0_fx = shr(div_s(temp, s_g_out), 1); + g0_fx = add(g0_fx, (Word16) 0x4000); /* s_g_in/s_g_out in Q14 */ + sh_g0 = sub(sh_g0, 1); + } + /* L_gain_in/L_gain_out in Q14 */ + /* overflows if L_gain_in > 2 * L_gain_out */ + g0_fx = shr(g0_fx, sh_g0); /* sh_g0 may be >0, <0, or =0 */ + + g0_fx = mult_r(g0_fx, agc_fac1_para_fx); /* L_gain_in/L_gain_out * AGC_FAC1_FX */ + } + /* compute gain(n) = AGC_FAC gain(n-1) + (1-AGC_FAC)gain_in/gain_out */ + /* sig_out(n) = gain(n) sig_out(n) */ + gain_fx = *gain_prec_fx; + move16(); /*14 */ + FOR (i = 0; i < SubFrameLength; i++) + { + temp = mult_r(agc_fac_para_fx, gain_fx);/*15 +14 -15 =14 */ + gain_fx = add(temp, g0_fx); /* in Q14 */ + L_temp = L_mult(gain_fx, sig_out_fx[i]);/*14 + Q_bwe_exc-1 +1 = 14 + Q_bwe_exc */ + L_temp = L_shl(L_temp, 1); /*14 + Q_bwe_exc +1 */ + sig_out_fx[i] = round_fx(L_temp); /*Q_bwe_exc +15 -16 = Q_bwe_exc-1 */ + } + *gain_prec_fx =gain_fx; + move16(); + + return; +} + +void PostShortTerm_fx( + Word16 *sig_in, /* i : input signal (pointer to current subframe */ + Word16 *lpccoeff, /* i : LPC coefficients for current subframe */ + Word16 *sig_out, /* o : postfiltered output */ + Word16 *mem_stp, /* i/o: postfilter memory*/ + Word16 *ptr_mem_stp, /* i/o: pointer to postfilter memory*/ + Word16 *ptr_gain_prec, /* i/o: for gain adjustment*/ + Word16 *mem_zero, /* i/o: null memory to compute h_st*/ + Word16 formant_fac_fx /* i : Strength of post-filter*/ +) +{ + Word16 apond1_fx[LPC_SHB_ORDER+1]; /* denominator coeff.*/ + Word16 apond2_fx[LONG_H_ST]; /* numerator coeff. */ + Word16 sig_ltp_fx[L_SUBFR16k +1]; /* residual signal */ + /*Word16 lpccoeff_fx[LPC_SHB_ORDER+1];//Q12 */ + Word16 g1_fx,g2_fx,parcor0_fx; /*Q15 */ + Word16 tmp; + + parcor0_fx = 0; + move16(); + set16_fx( apond1_fx, 0, LPC_SHB_ORDER+1 ); + set16_fx( apond2_fx, 0, LONG_H_ST ); + set16_fx( sig_ltp_fx, 0, L_SUBFR16k+1 ); + + /* Obtain post-filter weights */ + tmp = extract_h(L_mult(GAMMA_SHARP_FX,formant_fac_fx));/*Q15 */ + g1_fx = add(GAMMA0_FX,tmp);/*Q15 */ + g2_fx = sub(GAMMA0_FX,tmp);/*Q15 */ + + /* Compute weighted LPC coefficients */ + weight_a_fx(lpccoeff, apond1_fx, g1_fx, LPC_SHB_ORDER); + weight_a_fx(lpccoeff, apond2_fx, g2_fx, LPC_SHB_ORDER); + /* o: apond1_fx, apond2_fx in Q12 */ + + /* Compute A(gamma2) residual */ + Residu3_10_fx( apond2_fx, sig_in, sig_ltp_fx+1, L_SUBFR16k, 0 ); + /* o: sig_ltp_fx in Q_bwe_exc */ + + /* Save last output of 1/A(gamma1) */ + sig_ltp_fx[0] = *ptr_mem_stp; + move16(); + + /* Control short term pst filter gain and compute parcor0 */ + Calc_st_filt_tbe(apond2_fx, apond1_fx, &parcor0_fx, sig_ltp_fx+1, mem_zero); + /* o: parcor0 in Q15 */ + /* i/o: sig_ltp_fx in Q_bwe_exc */ + + /* 1/A(gamma1) filtering, mem_stp is updated */ + Syn_filt_s(0,apond1_fx,LPC_SHB_ORDER,sig_ltp_fx+1,sig_ltp_fx+1,L_SUBFR16k,mem_stp,1); + + /* (1 + mu z-1) tilt filtering */ + filt_mu_fx(sig_ltp_fx, sig_out, parcor0_fx, L_SUBFR16k); + /* o: sig_out in Q_bwe_exc */ + + /* gain control */ + scale_st_swb(sig_in, sig_out, ptr_gain_prec, L_SUBFR16k ); + + return; +} + +void flip_spectrum_and_decimby4_fx( + const Word16 input[], /* i : input spectrum Q_inp */ + Word16 output[], /* o : output spectrum Q_inp */ + const Word16 length, /* i : vector length */ + Word16 mem1[], /* i/o : memory Q_inp */ + Word16 mem2[], /* i/o : memory Q_inp */ + const Word16 + ramp_flag /*i: flag to trigger slow ramp-up of output following change of core (HQ to ACELP or 12k8 to 16k ACELP) */ ) +{ + Word16 i; + Word16 factor, tmp[L_FRAME16k/2]; + Word16 tmp1, tmp2; + Word16 input_change[L_FRAME16k]; + + IF ( ramp_flag ) + { + factor = div_s( 4, length ); /* Q15 */ + FOR ( i = 0; i < length / 4; i += 2) + { + tmp1 = extract_l( L_mult0( i, factor ) ); /* Q15 */ + tmp2 = extract_l( L_mult0( add( i, 1 ), factor ) ); /*Q15 */ + input_change[i] = negate( mult_r( input[i], tmp1 ) ); + move16(); + input_change[i + 1] = mult_r( input[i + 1], tmp2 ); + move16(); + } + } + ELSE + { + i = 0; + move16(); + } + + FOR (; i < length; i = i + 2 ) + { + input_change[i] = negate( input[i] ); + move16(); + input_change[i + 1] = input[i + 1]; + move16(); + } + + Decimate_allpass_steep_fx( input_change, mem1, L_FRAME16k, tmp ); + Decimate_allpass_steep_fx( tmp, mem2, L_FRAME16k / 2, output ); + + return; +} + + +/*==========================================================================*/ +/* FUNCTION : void GenShapedWBExcitation_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Synthesize spectrally shaped highband excitation signal for the wideband */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _Word16 *lpc_shb i : lpc coefficients Q12 */ +/* _Word16 coder_type i : coding type */ +/* _Word16 *bwe_exc_extended i : bandwidth extended exciatation Q_bwe_exc*/ +/* _Word16 Q_bwe_exc i : Q format */ +/* _Word16 voice_factors[] i : voicing factor Q15 */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _Word16 *excSHB o : synthesized shaped shb exctiation Q_bwe_exc*/ +/* _Word16 *exc4kWhtnd o : whitened synthesized shb excitation Q_bwe_exc*/ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _Word32 *mem_csfilt i/o : memory Q_bwe_exc+16*/ +/* _Word16 *mem_genSHBexc_filt_down1 i/o : memory Q_bwe_exc */ +/* _Word16 *mem_genSHBexc_filt_down2 i/o : memory Q_bwe_exc */ +/* _Word16 *mem_genSHBexc_filt_down3 i/o : memory Q_bwe_exc */ +/* _Word16 *state_lpc_syn i/o : memory Q_bwe_exc */ +/* _Word16 bwe_seed[] i/o : random number generator seed */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*==========================================================================*/ +void GenShapedWBExcitation_fx( Word16* excSHB, /* o : synthesized shaped shb exctiation Q_bwe_exc*/ + const Word16* lpc_shb, /* i : lpc coefficients Q12*/ + Word16* exc4kWhtnd, /* o : whitened synthesized shb excitation Q_bwe_exc*/ + Word32* mem_csfilt, /* i/o : memory Q_bwe_exc+16*/ + Word16* mem_genSHBexc_filt_down1, /* i/o : memory Q_bwe_exc*/ + Word16* mem_genSHBexc_filt_down2, /* i/o : memory Q_bwe_exc*/ + Word16* mem_genSHBexc_filt_down3, /* i/o : memory Q_bwe_exc*/ + Word16* state_lpc_syn, /* i/o : memory Q_bwe_exc*/ + const Word16 coder_type, /* i : coding type */ + const Word16* bwe_exc_extended, /* i : bandwidth extended exciatation Q_bwe_exc*/ + const Word16 Q_bwe_exc, Word16 bwe_seed[], /* i/o : random number generator seed */ + const Word16 voice_factors[], /* i : voicing factor Q15*/ + const Word16 uv_flag /* i : unvoiced flag */ + , const Word16 igf_flag + ) +{ + Word16 i, j, k; + Word16 wht_fil_mem [ LPC_WHTN_ORDER_WB ]; + Word16 lpc_whtn[ LPC_WHTN_ORDER_WB + 1]; + Word16 R_h[LPC_WHTN_ORDER_WB + 2], R_l[LPC_WHTN_ORDER_WB + 2]; + Word16 Q_R; + Word16 excTmp[ L_FRAME16k]; + Word16 excTmp2[ L_FRAME16k / 4]; + Word16 excTmp2_frac[ L_FRAME16k / 4]; + Word16 exc4k[ L_FRAME16k / 4]; + Word16 exc4k_frac[ L_FRAME16k / 4]; + Word32 exc4k_32[ L_FRAME16k / 4]; + Word32 pow1, pow22; + Word16 scale; + Word32 excNoisyEnv[ L_FRAME16k / 4]; + Word16 csfilt_num2[1] = {1638}; /* Q15*/ + Word16 neg_csfilt_den2[2] = {-32768, 31457}; /* Q15 */ + Word32 L_tmp, Ltemp1, Ltemp2; + Word16 temp1, temp2, exp; + Word32 Lmax; + Word16 max, n1, n2, sc; + Word32 LepsP[LPC_WHTN_ORDER_WB+1]; + Word16 tmp_vfac; + Word16 avg_voice_fac; + + /*0.25f*sum_f(voice_factors, NB_SUBFR)*/ + L_tmp = L_mult(voice_factors[0], 8192); + FOR (i=1; i 0.35f*/ + { + csfilt_num2[0] = 6554; + move16(); /*Q15 -> 0.2f*/ + neg_csfilt_den2[1] = 26214; + move16(); /*Q15 -> 0.8f*/ + } + ELSE IF( igf_flag != 0 && ( EQ_16(coder_type, UNVOICED)||LT_16(avg_voice_fac,6654))) /*Q15 -> 0.2f*/ + { + csfilt_num2[0] = 328; + move16(); /*Q15 -> 0.01f*/ + neg_csfilt_den2[1] = 32440; + move16(); /*Q15 -> 0.99f*/ + } + set16_fx( wht_fil_mem, 0, LPC_WHTN_ORDER_WB ); + Decimate_allpass_steep_fx( bwe_exc_extended, mem_genSHBexc_filt_down1, L_FRAME32k, excTmp ); + flip_spectrum_and_decimby4_fx( excTmp, exc4k, L_FRAME16k, mem_genSHBexc_filt_down2, mem_genSHBexc_filt_down3, 0 ); + + IF ( uv_flag ) + { + create_random_vector_fx( exc4kWhtnd, L_FRAME16k / 4, bwe_seed ); + IF ( LT_16( Q_bwe_exc, 5 )) + { + + FOR ( i = 0; i < L_FRAME16k / 4; i++ ) + { + exc4kWhtnd[i] = shl_r( exc4kWhtnd[i], sub( Q_bwe_exc, 5 ) );/*Q(Q_bwe_exc)/Q5(if Q_bwe_exc > 5) */ + } + } + } + ELSE + { + autocorr_fx( exc4k, LPC_WHTN_ORDER_WB + 1, R_h, R_l, &Q_R, + L_FRAME16k / 4, win_flatten_4k_fx, 0, 1 ); + + /* Ensure R[0] isn't zero when entering Levinson Durbin */ + R_l[0] = s_max( R_l[0], 1 ); + move16(); + FOR ( i = 1; i <= LPC_WHTN_ORDER_WB; i++ ) + { + L_tmp = Mpy_32( R_h[i], R_l[i], wac_h[i - 1], wac_l[i - 1] ); + L_Extract( L_tmp, &R_h[i], &R_l[i] ); + } + + E_LPC_lev_dur(R_h, R_l, lpc_whtn, LepsP, LPC_WHTN_ORDER_WB, NULL); + + Copy_Scale_sig( lpc_whtn, lpc_whtn, LPC_WHTN_ORDER_WB+1, sub(norm_s(lpc_whtn[0]),2) ); + + fir_fx( exc4k, lpc_whtn, exc4kWhtnd, wht_fil_mem, L_FRAME16k / 4, + LPC_WHTN_ORDER_WB, 0, 3 ); + + /* Ensure pow1 is greater than zero when computing normalization */ + max = 0; + FOR ( i = 0; i < L_FRAME16k / 4; i++ ) + { + excTmp2[i] = abs_s( exc4kWhtnd[i] ); + move16(); /* Q_bwe_exc */ + max = s_max( max, excTmp2[i] ); + move16(); + } + + IF ( max == 0 ) + { + pow1 = 1; + move16(); + n1 = 0; + move16(); + } + ELSE + { + n1 = norm_s( max ); + FOR ( i = 0; i < L_FRAME16k / 4; i++ ) + { + excTmp2_frac[i] = shl( excTmp2[i], n1 ); + move16(); /* Q14 */ + } + n1 = sub( sub( 14, n1 ), Q_bwe_exc ); + pow1 = 1; + FOR ( i = 0; i < L_FRAME16k / 4; i++ ) + { + L_tmp = L_mult( excTmp2_frac[i], excTmp2_frac[i] ); /* Q29 */ + pow1 = L_add( pow1, L_shr( L_tmp, 7 ) ); /* Q22 */ + } + } + + FOR ( i = 0; i < L_FRAME16k / 4; i++ ) + { + excNoisyEnv[i] = L_add( *mem_csfilt, L_mult( csfilt_num2[0], excTmp2[i] ) ); + move32(); /* Q_bwe_exc+16 */ + *mem_csfilt = Mult_32_16( excNoisyEnv[i], neg_csfilt_den2[1] ); + move32(); /* Q_bwe_exc+16 */ + } + + create_random_vector_fx( exc4k, L_FRAME16k / 4, bwe_seed ); + + /* Ensure pow22 is greater than zero when computing normalization */ + Lmax = 0; + FOR ( i = 0; i < L_FRAME16k / 4; i++ ) + { + exc4k_32[i] = Mult_32_16( excNoisyEnv[i], exc4k[i] ); + move32();/* Q_bwe_exc+6 */ + Lmax = L_max( Lmax, L_abs( exc4k_32[i] ) ); + } + + IF ( Lmax == 0 ) + { + pow22 = 1; + move16(); + n2 = 0; + move16(); + set16_fx( exc4k_frac, 0, L_FRAME16k / 4 ); + } + ELSE + { + n2 = norm_l( Lmax ); + FOR ( i = 0; i < L_FRAME16k / 4; i++ ) + { + exc4k_frac[i] = extract_h( L_shl( exc4k_32[i], n2 ) ); /* Q(14-n2) */ + } + n2 = 30 - n2 - ( Q_bwe_exc + 6 ); + pow22 = 1; + FOR ( i = 0; i < L_FRAME16k / 4; i++ ) + { + L_tmp = L_mult( exc4k_frac[i], exc4k_frac[i] ); /* Q29 */ + pow22 = L_add( pow22, L_shr( L_tmp, 7 ) ); /* Q22 */ + } + } + + test(); + test(); + IF( EQ_16(coder_type, UNVOICED)||(igf_flag!=0&<_16(avg_voice_fac,6654))) + { + L_tmp = root_a_over_b_fx( pow1, sub( 22, shl( n1, 1 ) ), pow22, sub( 22, shl( n2, 1 ) ), &exp ); + scale = round_fx( L_shl( L_tmp, exp ) ); /*Q15 */ + + sc = sub( add( n2, Q_bwe_exc ), 14 ); + FOR ( i = 0; i < L_FRAME16k / 4; i++ ) + { + exc4kWhtnd[i] = round_fx( L_shl( L_mult( exc4k_frac[i], scale ), sc ) ); /* Q_bwe_exc+n2-10+16+ Q_bwe_exc + n2 -14 -16 = //Q_bwe_exc */ + } + } + ELSE + { + sc = sub( add( n2, Q_bwe_exc ), 14 ); /* Q_bwe_exc+n2-14*/ + + k = 0; + FOR ( i = 0; i < 4; i++ ) + { + test(); + IF( igf_flag != 0 && EQ_16(coder_type, VOICED)) + { + /*tmp_vfac = 2*voice_factors[i]; + tmp_vfac = min(1, tmp_vfac);*/ + BASOP_SATURATE_WARNING_OFF + tmp_vfac = shl(voice_factors[i], 1); + BASOP_SATURATE_WARNING_ON + } + ELSE + { + tmp_vfac = voice_factors[i]; + move16(); + } + + Ltemp1 = root_a_fx( L_deposit_h( tmp_vfac ), 31, &exp ); + temp1 = round_fx( L_shl( Ltemp1, exp ) ); /* Q15 */ + + L_tmp = Mult_32_16( pow1, sub( 32767, tmp_vfac ) ); /* Q22*/ + Ltemp2 = root_a_over_b_fx( L_tmp, sub( 22, shl( n1, 1 ) ), pow22, sub( 22, shl( n2, 1 ) ), &exp ); + temp2 = round_fx( L_shl( Ltemp2, exp ) ); /* Q15 */ + + FOR ( j = 0; j < L_FRAME16k / 16; j++ ) + { + L_tmp = L_mult( temp1, exc4kWhtnd[k] );/* Q(16+Q_bwe_exc) */ + L_tmp = L_add( L_tmp, L_shl( L_mult( temp2, exc4k_frac[k] ), sc ) ); /* Q(16+Q_bwe_exc) */ + exc4kWhtnd[k] = round_fx( L_tmp ); /* Q_bwe_exc */ + k++; + } + } + } + } + + Syn_filt_s( 0, lpc_shb, LPC_SHB_ORDER_WB, exc4kWhtnd, excSHB, L_FRAME16k / 4, state_lpc_syn, 1 ); + + + + return; +} + + +/*-------------------------------------------------------------------* +* GenWBSynth() +* +* Generate 16 KHz sampled highband component from synthesized highband +*-------------------------------------------------------------------*/ + +void GenWBSynth_fx( + const Word16* input_synspeech, /* i : input synthesized speech Qx*/ + Word16* shb_syn_speech_16k, /* o : output highband compnent Qx*/ + Word16* state_lsyn_filt_shb1, /* i/o: memory Qx*/ + Word16* state_lsyn_filt_shb2 /* i/o: memory Qx*/ ) +{ + Word16 speech_buf_16k1[L_FRAME16k], speech_buf_16k2[L_FRAME16k]; + Word16 i, maxm, nor; + Word16 input_synspeech_temp[L_FRAME16k / 4]; + + maxm = 0; + move16(); + FOR(i = 0; i low freq), -ve or neutral Q12 */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _(Word16*)mem_csfilt :memory */ +/* _(Word16*)mem_genSHBexc_filt_down_shb :memory */ +/* _(Word16*)state_lpc_syn :memory */ +/* _(Word16[]) bwe_seed :random number generator seed */ +/* _(Word16[]) lpf_14k_mem :memory */ +/* _(Word32[])Hilbert_Mem :memory */ +/*--------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------------------*/ +/* CALLED FROM : RX */ +/*======================================================================================*/ +void GenShapedSHBExcitation_fx( + Word16 *excSHB, /* o : synthesized shaped shb excitation Q_bwe_exc*/ + const Word16 *lpc_shb, /* i : lpc coefficients Q12*/ + Word16 *White_exc16k_FB, /* o : white excitation for the Fullband extension Q_bwe_exc */ + Word32 *mem_csfilt, /* i/o: memory */ + Word16 *mem_genSHBexc_filt_down_shb, /* i/o: memory */ + Word16 *state_lpc_syn, /* i/o: memory */ + const Word16 coder_type, /* i : coding type */ + const Word16 *bwe_exc_extended, /* i : bandwidth extended excitation */ + Word16 bwe_seed[], /* i/o: random number generator seed */ + Word16 voice_factors[], /* i : voicing factor*/ + const Word16 extl, /* i : extension layer */ + Word16 *tbe_demph, /* i/o: de-emphasis memory */ + Word16 *tbe_premph, /* i/o: pre-emphasis memory */ + Word16 *lpc_shb_sf, /* i: LP coefficients */ + const Word32 shb_ener_sf_32, /* i: input shb ener, Q31 */ + Word16 *shb_res_gshape, /* i: input res gain shape, Q14 */ + Word16 *shb_res, + Word16 *vf_ind, + const Word16 formant_fac, /* i : Formant sharpening factor [0..1] */ + Word16 fb_state_lpc_syn[], /* i/o: memory */ + Word16 *fb_tbe_demph, /* i/o: fb de-emphasis memory */ + Word16 *Q_bwe_exc, + Word16 *Q_bwe_exc_fb, + const Word16 Q_shb, + Word16 n_mem2, /* i : n_mem2 scale factor to adjust 24.4/32kbps memories */ + Word16 prev_Q_bwe_syn, /* i : st_fx->prev_Q_bwe_syn */ + const Word32 bitrate, + const Word16 prev_bfi +) +{ + Word16 i, j, k; + Word16 wht_fil_mem[LPC_WHTN_ORDER]; + Word16 lpc_whtn[LPC_WHTN_ORDER + 1]; + Word16 R_h[LPC_WHTN_ORDER+ 2]; /* Autocorrelations of windowed speech MSB */ + Word16 R_l[LPC_WHTN_ORDER+ 2]; /* Autocorrelations of windowed speech LSB */ + Word16 Q_R; + Word32 LepsP[LPC_WHTN_ORDER+1]; + Word16 exc32k[L_FRAME32k], exc16k[L_FRAME16k]; + Word32 pow1, pow22; + Word16 scale, temp1, temp2; + + Word16 excTmp2[L_FRAME16k]; + Word16 *White_exc16k; + Word16 excNoisyEnv[L_FRAME16k]; + Word16 csfilt_num2[1] = {6554}; /*0.2 in Q15 */ + Word16 neg_csfilt_den2[2] = {-32767, 26214}; /* {1.0f, -0.8f} */ + Word16 varEnvShape; + Word16 fb_deemph_fac = 15729; /*0.48f in Q15 */ + Word16 exc16kWhtnd[L_FRAME16k]; + + Word32 L_tmp; + Word16 vf_tmp; + Word16 tmp, exp, tmp2; + Word16 voiceFacEst[NB_SUBFR16k]; + Word16 zero_mem[LPC_SHB_ORDER]; + Word32 syn_shb_ener_sf[4]; + Word16 tempSHB[80]; + Word16 Q_pow1, Q_pow22; + + Word32 L_tmp2, L_tmp3, L_tmp4; + Word16 temp; + + Word16 White_exc16k_FB_temp[L_FRAME16k]; + Word32 White_exc16k_32[L_FRAME16k]; + Word16 Q_temp; + Word16 prev_Q_bwe_exc_fb; + + set16_fx( zero_mem, 0, LPC_SHB_ORDER ); + set16_fx( wht_fil_mem, 0, LPC_WHTN_ORDER ); + + FOR(i = 0; i < L_FRAME32k; i=i+2) + { + exc32k[i] = negate(bwe_exc_extended[i]); + move16(); + exc32k[i+1] = bwe_exc_extended[i+1]; + move16(); + } + + /* Decimate by 2 */ + Decimate_allpass_steep_fx( exc32k, mem_genSHBexc_filt_down_shb, 2*L_FRAME16k, exc16k ); + /* i: exc32k in Q_bwe_exc */ + /* o: exc16k in Q_bwe_exc */ + + autocorr_fx( exc16k, LPC_WHTN_ORDER + 1, R_h, R_l, &Q_R, L_FRAME16k, win_flatten_fx, 0, 1 ); + /* Ensure R[0] isn't zero when entering Levinson Durbin */ + R_l[0] = s_max( R_l[0], 1 ); + move16(); + FOR ( i = 1; i <= LPC_WHTN_ORDER; i++ ) + { + L_tmp = Mpy_32( R_h[i], R_l[i], wac_h[i - 1], wac_l[i - 1] ); + L_Extract( L_tmp, &R_h[i], &R_l[i] ); + } + E_LPC_lev_dur(R_h, R_l, lpc_whtn, LepsP, LPC_WHTN_ORDER, NULL); + Copy_Scale_sig( lpc_whtn, lpc_whtn, LPC_WHTN_ORDER+1, sub(norm_s(lpc_whtn[0]),2) ); + fir_fx( exc16k, lpc_whtn, exc16kWhtnd, wht_fil_mem, L_FRAME16k, LPC_WHTN_ORDER, 0, 3 ); + + /* i: exc16k in Q_bwe_exc */ + /* o: exc16kWhtnd in Q_bwe_exc */ + + IF( GE_32(bitrate, ACELP_24k40)) + { + temp2 = 0; + move16(); + FOR(j = 0; j < 4; j++) + { + temp1 = shb_res_gshape[j]; + move16(); + FOR(i = 0; i < 80; i++) + { + exc16kWhtnd[temp2 + i] = round_fx(L_shl(L_mult( exc16kWhtnd[temp2 + i], temp1 ), 1)); + /* exc16kWhtnd in Q_bwe_exc, shb_res_gshape in Q14 */ + } + temp2 = add(temp2, 80); + } + } + + /* Estimate pow1 associated with Low band nonlinear extended excitation */ + /* pow1=0.00001f */ + tmp = sub(shl(*Q_bwe_exc, 1), 31); + pow1 = L_shl(21475l/*0.00001f Q31*/, tmp); /* 0.00001f in 2*(Q_bwe_exc) */ + FOR( k = 0; k < L_FRAME16k; k++) + { + /*excTmp2[k ] = (float)(fabs(exc16kWhtnd[k]));*/ + excTmp2[k] = abs_s( exc16kWhtnd[k] ); + move16(); + + /* pow1 += exc16kWhtnd[k] * exc16kWhtnd[k]; */ + pow1 = L_mac0( pow1, exc16kWhtnd[k], exc16kWhtnd[k] ); /* 2*Q_bwe_exc */ + } + Q_pow1 = shl(*Q_bwe_exc,1); + + test(); + IF( (LE_32( bitrate, ACELP_13k20 ))&&(GE_32(bitrate,ACELP_7k20))) + { + /* varEnvShape = mean_fx(voice_factors, 4); */ + /* unroll the loop */ + L_tmp = L_mult(voice_factors[0], 8192); + L_tmp = L_mac(L_tmp, voice_factors[1], 8192 ); + L_tmp = L_mac(L_tmp, voice_factors[2], 8192 ); + varEnvShape = mac_r(L_tmp, voice_factors[3], 8192 ); /* varEnvShape in Q15 */ + } + ELSE /* 16k core */ + { + /* varEnvShape = mean_fx(voice_factors, 5); */ + /* unroll the loop */ + L_tmp = L_mult(voice_factors[0], 6554); + L_tmp = L_mac(L_tmp, voice_factors[1], 6554 ); + L_tmp = L_mac(L_tmp, voice_factors[2], 6554 ); + L_tmp = L_mac(L_tmp, voice_factors[3], 6554 ); + varEnvShape = mac_r(L_tmp, voice_factors[4], 6554 ); /* varEnvShape in Q15 */ + } + + IF ( EQ_16(extl, FB_TBE)) + { + /*pow(varEnvShape,3) */ + tmp = mult_r(varEnvShape, varEnvShape); + tmp = mult_r(tmp, varEnvShape); + + /* max((0.68f - (float)pow(varEnvShape, 3)), 0.48f); */ + fb_deemph_fac = sub(22282/*0.68f Q15*/, tmp); + fb_deemph_fac = s_max(fb_deemph_fac, 15729/*0.48f Q15*/); + } + + /*varEnvShape = 1.09875f - 0.49875f * varEnvShape; */ + varEnvShape = msu_r(1179773824l/*0.549375f Q31*/, 8172/*0.249375f Q15*/, varEnvShape); + + /*varEnvShape = min( max(varEnvShape, 0.6f), 0.999f); */ + varEnvShape = s_max(varEnvShape, 9830/*0.3f Q15*/); + varEnvShape = s_min(varEnvShape, 16368/*0.4995f Q15*/); + varEnvShape = shl(varEnvShape, 1); + csfilt_num2[0] = sub(MAX_16, varEnvShape); + move16(); + neg_csfilt_den2[1] = varEnvShape; + move16(); + + test(); + test(); + test(); + IF ( *mem_csfilt == 0 && ( (EQ_32( bitrate, ACELP_9k60 ))||(EQ_32(bitrate,ACELP_16k40))||(EQ_32(bitrate,ACELP_24k40)))) + { + /* pre-init smoothing filter to avoid energy drop outs */ + L_tmp = L_mult(excTmp2[0], 1638); + FOR (i = 1; i < L_SUBFR16k/4; i++) + { + L_tmp = L_mac(L_tmp, excTmp2[i], 1638); /*1638 = 1/20 in Q15*/ + } + /*L_tmp = sum(excTmp2, L_SUBFR16k/4)*(1/20) where L_SUBFR16k/4 =20 */ + + /* don't apply for FB in case the FB start-frame was potentially lost - White_exc16k is very sensitive to enery mismatch between enc - dec */ + /* rather stick to the more conservative approach, to avoid potential clippings */ + test(); + IF( !(prev_bfi && EQ_16(extl, FB_TBE))) + { + /* use weak smoothing for 1st frame after switching to make filter recover more quickly */ + varEnvShape = 26214/*0.8f Q15*/; + move16(); + csfilt_num2[0] = sub(MAX_16, varEnvShape); + move16(); + neg_csfilt_den2[1] = varEnvShape; + move16(); + } + + *mem_csfilt = Mult_32_16( L_tmp, varEnvShape ); + move32(); + } + + /* Track the low band envelope */ + L_tmp = *mem_csfilt; + move32(); + FOR ( i = 0; i < L_FRAME16k; i++ ) + { + excNoisyEnv[i] = mac_r( L_tmp, csfilt_num2[0], excTmp2[i] ); + move16(); + /* excNoisyEnv : Q_bwe_exc, + *mem_csfilt: Q_bwe_exc+16, excTmp2: Q_bwe_exc, csfilt_num2[0] Q15 */ + L_tmp = L_mult( excNoisyEnv[i], neg_csfilt_den2[1] ); /* Q_bwe_exc+16 */ + } + *mem_csfilt = L_tmp; + move32(); + + /* create a random excitation - Reuse exc16k memory */ + White_exc16k = exc16k; + create_random_vector_fx( White_exc16k, 256, bwe_seed ); + create_random_vector_fx( White_exc16k + 256, L_FRAME16k - 256, bwe_seed ); + + L_tmp = L_deposit_l(0); + tmp = add(*Q_bwe_exc, 1); + FOR ( k = 0; k < L_FRAME16k; k++ ) + { + L_tmp4 = L_shl(L_deposit_l(White_exc16k[k]), tmp); + if(excNoisyEnv[k] != 0) + { + L_tmp4 = L_mult(excNoisyEnv[k], White_exc16k[k]);/* (Q_bwe_exc) +5 +1*/ + } + White_exc16k_32[k] = L_tmp4; + move32(); + L_tmp = L_max(L_tmp, L_abs(White_exc16k_32[k])); + } + Q_temp = norm_l( L_tmp ); + if(L_tmp == 0) + { + Q_temp = 31; + } + /*Copy_Scale_sig( White_exc16k, White_exc16k, L_FRAME16k, sub(NOISE_QFAC, 5) );)*/ + /* White_exc16k in Q6 */ + + /* calculate pow22 */ + /* pow22=0.00001f */ + tmp = sub(shl(sub(*Q_bwe_exc, NOISE_QADJ), 1), 31); + pow22 = L_shl(21475l/*0.00001f Q31*/, tmp); /* 0.00001f in 2*(Q_bwe_exc-NOISE_QADJ) */ + tmp = sub(NOISE_QFAC, 5); + FOR ( k = 0; k < L_FRAME16k; k++ ) + { + /* White_exc16k[k] *= excNoisyEnv[k]; */ + White_exc16k[k] = mult_r( excNoisyEnv[k], shl(White_exc16k[k], tmp) ); + move16(); + /* i: excNoisyEnv in (Q_bwe_exc) */ + /* i: White_exc16k in Q6 */ + /* o: White_exc16k in (Q_bwe_exc-NOISE_QADJ) */ + /* pow22 += White_exc16k[k] * White_exc16k[k]; */ + pow22 = L_mac0( pow22, White_exc16k[k], White_exc16k[k] ); /* 2*(Q_bwe_exc-NOISE_QADJ)*/ + } + /*Q_pow22 = sub( shl(*Q_bwe_exc,1), 18 );*/ + Q_pow22 = shl( sub( *Q_bwe_exc, NOISE_QADJ ), 1); + + + IF( GE_32(bitrate, ACELP_24k40)) + { + IF( EQ_16(*vf_ind,20)) /* encoder side */ + { + Estimate_mix_factors_fx(shb_res, Q_shb, exc16kWhtnd, *Q_bwe_exc, + White_exc16k, (*Q_bwe_exc-NOISE_QADJ), pow1, Q_pow1, + pow22, Q_pow22, voiceFacEst, vf_ind); + tmp = voiceFacEst[0]; + } + ELSE /* decoder side */ + { + /* *vf_ind is an integer scale by 0.125f*/ + tmp = shl( *vf_ind, (15-3) ); + } + tmp2 = MAX_16; + if( LE_16(tmp, 22938/*0.7f Q15*/)) + { + tmp2 = 26214/*0.8f Q15*/; + } + voice_factors[0] = mult_r(voice_factors[0], tmp2); + move16(); + voice_factors[1] = mult_r(voice_factors[1], tmp2); + move16(); + voice_factors[2] = mult_r(voice_factors[2], tmp2); + move16(); + voice_factors[3] = mult_r(voice_factors[3], tmp2); + move16(); + voice_factors[4] = mult_r(voice_factors[4], tmp2); + move16(); + } + + { + tmp = sub(Q_temp, 3); + } + FOR ( k = 0; k < L_FRAME16k; k++ ) + { + White_exc16k_FB[k] = round_fx(L_shl(White_exc16k_32[k], tmp)); /* Q_bwe_exc +5 +1 +Q_temp -16 -3 */ + } + prev_Q_bwe_exc_fb = *Q_bwe_exc_fb; + *Q_bwe_exc_fb = sub(add(*Q_bwe_exc, Q_temp), 13); + + deemph_fx( White_exc16k, PREEMPH_FAC, L_FRAME16k, tbe_demph ); + /* i/o: White_exc16k (Q_bwe_exc-NOISE_QADJ) */ + /* i: tbe_demph (Q_bwe_exc-NOISE_QADJ) */ + + IF ( EQ_16(coder_type, UNVOICED)) + { + L_tmp = root_a_over_b_fx( pow1, Q_pow1, pow22, Q_pow22, &exp ); + scale = round_fx( L_shl( L_tmp, exp ) ); /*Q15 */ + + FOR ( k = 0; k < L_FRAME16k; k++ ) + { + /* White_exc16k: (Q_bwe_exc-NOISE_QADJ), scale: Q15 */ + L_tmp = L_mult( White_exc16k[k], scale ); + /* L_tmp: (Q_bwe_exc-NOISE_QADJ) + 15 + 1 */ + exc16kWhtnd[k] = round_fx( L_shl(L_tmp, NOISE_QADJ) ); + /* exc16kWhtnd: Q_bwe_exc */ + } + preemph_fx( exc16kWhtnd, PREEMPH_FAC, L_FRAME16k, tbe_premph ); + /* i/o: exc16kWhtnd (Q_bwe_exc) */ + /* i/o: tbe_premph (Q_bwe_exc) */ + } + ELSE + { + Word16 nbSubFr, lSubFr; + Word16 tempQ15; + Word32 tempQ31; + /*nbSubFr = ( bitrate < ACELP_24k40 )? NB_SUBFR : NB_SUBFR16k;*/ + nbSubFr = NB_SUBFR16k; + lSubFr = (L_FRAME16k/NB_SUBFR16k); + IF(LT_32(bitrate, ACELP_24k40)) + { + nbSubFr = NB_SUBFR; + move16(); + lSubFr = (L_FRAME16k/NB_SUBFR); + move16(); + } + k = 0; + FOR( i = 0; i < nbSubFr; i++ ) + { + test(); + IF( EQ_16(coder_type, VOICED)&&(LT_32(bitrate,ACELP_24k40))) + { + exp = 0; + tempQ15 = Sqrt16(voice_factors[i], &exp); /* Q15 */ + temp = shl(tempQ15, exp); /* Q15 exc16kWhtnd scale factor */ + exp = 0; + tempQ15 = Sqrt16(temp, &exp); /* Q15 */ + temp1 = shl(tempQ15, exp); /* Q15 exc16kWhtnd scale factor */ + + /*temp2 = root_a_over_b_fx( pow1 * (1.0f - temp), pow22 ); */ + temp = sub(MAX_16, temp); + tempQ31 = Mult_32_16(pow1, temp); + L_tmp = root_a_over_b_fx( tempQ31, Q_pow1, pow22, Q_pow22, &exp ); + temp2 = round_fx(L_shl(L_tmp, exp)); /* Q15 whiteEnvShapedExc scale factor */ + } + ELSE + { + /* Adjust noise mixing for formant sharpening filter */ + tempQ15 = mult_r(SWB_NOISE_MIX_FAC_FX, formant_fac); + /* vf_tmp = voice_factors[i] * (1.0f - vf_tmp); */ + vf_tmp = sub(MAX_16, tempQ15); + vf_tmp = mult_r(voice_factors[i], vf_tmp); + + exp = 0; + tempQ15 = Sqrt16(vf_tmp, &exp); /* Q15 */ + temp1 = shl(tempQ15, exp); /* Q15 exc16kWhtnd scale factor */ + + /*temp2 = root_a_over_b(pow1 * (1.0f - vf_tmp), pow22); */ + temp = sub(MAX_16, vf_tmp); + tempQ31 = Mult_32_16(pow1, temp); + L_tmp = root_a_over_b_fx( tempQ31, Q_pow1, pow22, Q_pow22, &exp ); + temp2 = round_fx(L_shl(L_tmp, exp)); /* Q15 whiteEnvShapedExc scale factor */ + } + + FOR( j = 0; j < lSubFr; j++) + { + /*exc16kWhtnd[k+j] = temp1 * exc16kWhtnd[k+j] + temp2 * White_exc16k[k+j]; */ + L_tmp = L_mult(temp2, White_exc16k[k+j]); /* 16+(Q_bwe_exc-NOISE_QADJ)*/ + L_tmp = L_shl(L_tmp, NOISE_QADJ); /* 16+(Q_bwe_exc) */ + exc16kWhtnd[k+j] = mac_r(L_tmp, temp1, exc16kWhtnd[k+j]); + move16(); + /* Q_bwe_exc */ + } + k = add(k, lSubFr); + + /* estimate the pre-emph factor */ + tempQ15 = sub(MAX_16, voice_factors[i]); + exp = 0; + temp = Sqrt16(tempQ15, &exp); + temp = shl(temp, exp-1); + + temp2 = add( temp, shl(temp1, -1) ); /* shift right by 1 to avoid overflow */ + temp = div_s( temp, temp2 ); /* Q15 */ + temp = mult_r( PREEMPH_FAC, temp ); + + preemph_fx( &exc16kWhtnd[i*lSubFr], temp, lSubFr, tbe_premph ); + /* exc16kWhtnd: Q_bwe_exc; + tbe_premph: Q_bwe_exc*/ + } + } + + + IF ( LT_32(bitrate, ACELP_24k40)) + { + Syn_filt_s(0, lpc_shb, LPC_SHB_ORDER, exc16kWhtnd, excSHB, L_FRAME16k, state_lpc_syn, 1 ); + /* i: exc16kWhtnd in Q_bwe_exc */ + /* o: excSHB in Q_bwe_exc */ + } + ELSE + { + set16_fx( zero_mem, 0, LPC_SHB_ORDER); + + Syn_filt_s(0, lpc_shb_sf, LPC_SHB_ORDER, exc16kWhtnd, tempSHB, 80, zero_mem, 1); + syn_shb_ener_sf[0] = L_shr(sum2_fx(tempSHB, 80),3); + move32(); + + Syn_filt_s(0, lpc_shb_sf+(LPC_SHB_ORDER+1), LPC_SHB_ORDER, exc16kWhtnd+ 80, tempSHB, 80, zero_mem, 1 ); + syn_shb_ener_sf[1] = L_shr(sum2_fx(tempSHB, 80),3); + move32(); + + Syn_filt_s(0, lpc_shb_sf+2*(LPC_SHB_ORDER+1), LPC_SHB_ORDER, exc16kWhtnd+160, tempSHB, 80, zero_mem, 1 ); + syn_shb_ener_sf[2] = L_shr(sum2_fx(tempSHB, 80),3); + move32(); + + Syn_filt_s(0, lpc_shb_sf+3*(LPC_SHB_ORDER+1), LPC_SHB_ORDER, exc16kWhtnd+240, tempSHB, 80, zero_mem, 1 ); + syn_shb_ener_sf[3] = L_shr(sum2_fx(tempSHB, 80),3); + move32(); + + /* i: exc16kWhtnd in Q_bwe_exc */ + /* o: tempSHB in Q_bwe_exc */ + /* o: syn_shb_ener_sf in (2*Q_bwe_exc+1) */ + IF(LE_32(bitrate,ACELP_32k)) + { + L_tmp = sum32_fx(syn_shb_ener_sf, 4); + + /* find root_a(tempSHB[0]) = root_a_over_b(shb_ener_sf[0]), L_tmp) */ + tmp = shl(Q_shb, 1); + tmp2 = add(shl(*Q_bwe_exc, 1), 1); + L_tmp2 = root_a_over_b_fx(shb_ener_sf_32, tmp, L_tmp, tmp2, &exp); /* L_tmp2 in (Q31-exp) */ + + *Q_bwe_exc = sub(*Q_bwe_exc, exp); + move16(); /* compensate for the exp shift */ + tmp2 = add( prev_Q_bwe_syn, n_mem2 ); + IF( GT_16( *Q_bwe_exc, tmp2)) + { + L_tmp2 = L_shl(L_tmp2, sub(tmp2, *Q_bwe_exc)); + *Q_bwe_exc = tmp2; + move16(); + } + FOR(i = 0; i < L_FRAME16k; i++) + { + L_tmp3 = Mult_32_16(L_tmp2, exc16kWhtnd[i]); /* *Q_bwe_exc + (31-exp) - 15 */ + exc16kWhtnd[i] = round_fx(L_tmp3); /* *Q_bwe_exc - exp */ + } + } + /* i: L_tmp2 in (Q31-exp) */ + /* i: exc16kWhtnd in Q_bwe_exc */ + /* o: exc16kWhtnd in Q_bwe_exc: (Q_bwe_exc-exp) */ + + /* Rescale the past memories: LP synth and SHB look ahead buffers */ + tmp = sub(*Q_bwe_exc, prev_Q_bwe_syn); + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + state_lpc_syn[i] = shl( state_lpc_syn[i], tmp ); + move16(); + } + FOR( i = -L_SHB_LAHEAD; i < 0; i++ ) + { + excSHB[i] = shl(excSHB[i], tmp); + move16(); + } + /* Do mem_stp_swb_fx scaling before PostShortTerm_fx */ + + Syn_filt_s(0, lpc_shb_sf, LPC_SHB_ORDER, exc16kWhtnd, excSHB, 80, state_lpc_syn, 1 ); + Syn_filt_s(0, lpc_shb_sf+(LPC_SHB_ORDER+1), LPC_SHB_ORDER, exc16kWhtnd+ 80, excSHB+ 80, 80, state_lpc_syn, 1 ); + Syn_filt_s(0, lpc_shb_sf+2*(LPC_SHB_ORDER+1), LPC_SHB_ORDER, exc16kWhtnd+160, excSHB+160, 80, state_lpc_syn, 1 ); + Syn_filt_s(0, lpc_shb_sf+3*(LPC_SHB_ORDER+1), LPC_SHB_ORDER, exc16kWhtnd+240, excSHB+240, 80, state_lpc_syn, 1 ); + /* i: exc16kWhtnd in (Q_bwe_exc) */ + /* o: excSHB in (Q_bwe_exc) */ + } + + IF ( EQ_16(extl, FB_TBE)) + { + tmp = sub( add(*Q_bwe_exc_fb, 20), prev_Q_bwe_exc_fb ); + Scale_sig( fb_state_lpc_syn, LPC_SHB_ORDER, tmp ); + Scale_sig( fb_tbe_demph, 1, tmp ); + Syn_filt_s(0, lpc_shb, LPC_SHB_ORDER, White_exc16k_FB, White_exc16k_FB_temp, L_FRAME16k, fb_state_lpc_syn, 1 ); + /* i: White_exc16k_FB in (14-n2) */ + /* o: White_exc16k_FB_temp in (14-n2) */ + + FOR( i=0; i<10; i++ ) + { + FOR( j=0; j<32; ++j ) + { + White_exc16k_FB_temp[i*32+j] = mult_r(White_exc16k_FB_temp[i*32+j], cos_fb_exc_fx[j]); + move16(); + } + } + + *Q_bwe_exc_fb = add(*Q_bwe_exc_fb, 20); + move16(); /**Q_bwe_exc_fb +35 +1 -16*/ + flip_spectrum_fx( White_exc16k_FB_temp, White_exc16k_FB, L_FRAME16k ); + + deemph_fx( White_exc16k_FB, fb_deemph_fac, L_FRAME16k, fb_tbe_demph ); + + } + ELSE + { + set16_fx( White_exc16k_FB, 0, L_FRAME16k); + } + + return; +} + + +/*====================================================================================*/ +/* FUNCTION : void GenSHBSynth_fx() */ +/*------------------------------------------------------------------------------------*/ +/* PURPOSE :Generate 32 KHz sampled highband component from synthesized highband*/ +/*------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS */ +/* _(Word16*)input_synspeech :input synthesized speech */ +/* _(Word16) L_frame :ACELP frame length */ +/*------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16*)shb_syn_speech_32k : output highband component */ +/*------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _(Word16[]) allpass_mem : memory */ +/* _(Word32[]) Hilbert_Mem : memory */ +/*------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------------------------------*/ + +void GenSHBSynth_fx( + const Word16* input_synspeech, /* i : input synthesized speech */ + Word16* shb_syn_speech_32k, /* o : output highband component */ + Word32 Hilbert_Mem[], /* i/o: memory */ + Word16 allpass_mem[], /* i/o: memory */ + const Word16 L_frame, /* i : ACELP frame length */ + Word16* syn_dm_phase +) +{ + Word16 i, speech_buf_32k[L_FRAME32k]; + Word16 maxm, nor, nor32, shift; + Word16 input_synspeech_temp[L_FRAME16k]; + Word32 maxm32; + + + maxm = 0; + move16(); + maxm32 = L_deposit_l(0); + FOR(i = 0; i (Q_bwe_exc + Q_gFr_norm - 13) */ + + /* check for headroom of previous buff memories: overlap, Hilbert, and interp all-pass mem */ + tmpQ15 = add( prev_Q_bwe_syn2, n_mem3 ); + if( GT_16( *Q_bwe_exc, tmpQ15)) + { + *Q_bwe_exc = tmpQ15; + move16(); + } + + *Qx = *Q_bwe_exc; + + /* rescale the overlap memory */ + FOR( i = 0; i < L_SHB_LAHEAD; i++ ) + { + temp2 = 1; + if( overlap[i] < 0 ) + { + temp2 = -1; + } + temp1 = abs_s(overlap[i]); + temp1 = shl( temp1, (*Q_bwe_exc - prev_Q_bwe_syn2) ); + move16(); /* Q_bwe_exc + Q_gFr_norm - 13 */ + overlap[i] = i_mult(temp1, temp2); + } + + FOR ( i = 0; i < l_shb_lahead; i++ ) + { + L_tmp = Mult_32_16(mod_syn[i], gain_frame_Q16); /* Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15 */ + L_tmp2 = Mult_32_16(L_tmp, win[i]); /* (Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15) + 15 + (1-16) */ + synSHB[i] = mac_r(L_tmp2, overlap[i], MAX_16); + move16(); /* Q_bwe_exc + Q_gFr_norm - 13 */ + synSHB[i+l_shb_lahead] = round_fx(L_tmp); /* Q_bwe_exc + Q_gFr_norm - 13 */ + } + + FOR ( ; i < l_frame; i++ ) + { + L_tmp = Mult_32_16( mod_syn[i], gain_frame_Q16); /* Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15 */ + synSHB[i] = round_fx( L_tmp ); /* Q_bwe_exc + Q_gFr_norm - 13 */ + } + + l_frame_tmp = add(l_frame, l_shb_lahead); + FOR ( ; i < l_frame_tmp; i++ ) + { + L_tmp = Mult_32_16( mod_syn[i], gain_frame_Q16); /* Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15 */ + L_tmp = Mult_32_16(L_tmp, win[l_frame + l_shb_lahead - 1 - i]); /* (Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15) + 15 + (1-16) */ + overlap[i - l_frame] = round_fx( L_tmp ); /* Q_bwe_exc + Q_gFr_norm - 13 */ + } + + return; +} + + +void ScaleShapedWB_fx( + const Word16 length, /* i : SHB overlap length */ + Word16* synSHB, /* i/o : synthesized shb signal Q_bwe_exc/Qx */ + Word16* overlap, /* i/o : buffer for overlap-add Q_bwe_exc/Qx */ + const Word16* subgain, /* i : subframe gain Q15*/ + const Word32 frame_gain, /* i : frame gain Q18 */ + const Word16* win, /* i : window Q15*/ + const Word16* subwin, /* i : subframes window Q15*/ + const Word16 Q_bwe_exc + ,Word16 L_frame /* i : Frame length - determines whether 12.8 or 16kHz core in-use */ + ,Word16 dynQ /* i : indicate whether output is dynamic Q, or Q0 */ + ,Word16* Qx /* o : newly computed Q factor for synSHB */ + ,Word16 prev_Qx /* i : prev_Qx for memory scaling */ + ,Word32* Hilbert_Mem /* i : Hilbert memory used for computing Qx */ +) +{ + const Word16* skip; + Word16 i, j, k, l_shb_lahead, l_frame, l_frame_tmp; + Word16 join_length, num_join; + Word32 mod_syn[L_FRAME16k+L_SHB_LAHEAD]; + Word16 sum_gain; + Word32 L_tmp; + Word16 max, abs_sig, sc1, sc2, shift, max_headroom, min_shift, max_shift, max_shift2; + /* Init */ + set32_fx( mod_syn, 0, L_FRAME16k+L_SHB_LAHEAD ); + + /* apply gain for each subframe, and store noise output signal using overlap-add */ + IF ( EQ_16(length,SHB_OVERLAP_LEN / 2 )) + { + /* WB Gain shape and gain frame application with overlap */ + skip = skip_bands_WB_TBE; + move16(); + l_frame = L_FRAME16k / 4; + move16(); + l_shb_lahead = L_SHB_LAHEAD / 4; + move16(); + + sum_gain = 0; + move16(); + FOR ( k = 0; k < length / 2; k++ ) + { + sum_gain = mult_r( subwin[2 * k + 2], subgain[0] ); /* Q15 */ + mod_syn[skip[0] + k] = L_mult( sum_gain, synSHB[skip[0] + k] ); + move32();/* Q_bwe_exc + 16 */ + mod_syn[skip[0] + k + length / 2] = L_mult( subgain[0], synSHB[skip[0] + k + length / 2] ); + move32();/* Q_bwe_exc + 16 */ + } + FOR ( i = 1; i < NUM_SHB_SUBFR / 2; i++ ) + { + FOR ( k = 0; k < length; k++ ) + { + L_tmp = L_mult0( subwin[k + 1], subgain[i] ); /* Q30 */ + sum_gain = round_fx( L_mac0( L_tmp, subwin[length - k - 1], subgain[i - 1] ) ); /* Q14 */ + mod_syn[skip[i] + k] = L_shl( L_mult( sum_gain, synSHB[skip[i] + k] ), 1 ); + move32(); /* Q_bwe_exc + 16 */ + } + } + FOR ( k = 0; k < length / 2; k++ ) + { + sum_gain = mult_r( subwin[length - 2 * k - 2], subgain[i - 1] ); /* Q15 */ + mod_syn[skip[i] + k] = L_mult( sum_gain, synSHB[skip[i] + k] ); + move32();/* Q_bwe_exc + 16 */ + } + } + ELSE + { + /* SWB Gain shape and gain frame application with overlap */ + l_frame = L_FRAME16k; + move16(); + l_shb_lahead = L_SHB_LAHEAD; + move16(); + skip = skip_bands_SWB_TBE; + move16(); + + num_join = NUM_SHB_SUBFR / NUM_SHB_SUBGAINS; + move16(); + join_length = i_mult2( num_join, length ); + j = 0; /* ptr*/ + FOR ( k = 0; k < length; k++ ) + { + sum_gain = mult_r( subwin[k + 1], subgain[0] ); /* Q15 */ + mod_syn[j] = L_mult( synSHB[j], sum_gain ); + move32(); /* Q_bwe_exc + 16 */ + j++; + } + + FOR ( i = 0; i < NUM_SHB_SUBGAINS - 1; i++ ) + { + FOR ( k = 0; k < join_length - length; k++ ) + { + mod_syn[j] = L_mult( synSHB[j], subgain[i * num_join] ); + move32(); /* Q_bwe_exc + 16 */ + j++; + } + + FOR ( k = 0; k < length; k++ ) + { + L_tmp = L_mult0( subwin[k + 1], subgain[i_mult2(( i + 1 ), num_join)] ); /* Q30 */ + sum_gain = round_fx( L_mac0( L_tmp, subwin[length - k - 1], subgain[i_mult2(i, num_join)] ) );/*Q14 */ + mod_syn[j] = L_shl( L_mult( sum_gain, synSHB[j] ), 1 ); + move32(); /* Q_bwe_exc + 16 */ + j++; + } + } + FOR ( k = 0; k < join_length - length; k++ ) + { + mod_syn[j] = L_mult( synSHB[j], subgain[( NUM_SHB_SUBGAINS - 1 ) * num_join] ); + move32(); /* Q_bwe_exc + 16 */ + j++; + } + FOR ( k = 0; k < length; k++ ) + { + sum_gain = mult_r( subwin[length - k - 1], subgain[( NUM_SHB_SUBGAINS - 1 ) *num_join] ); /* Q15 */ + mod_syn[j] = L_mult( synSHB[j], sum_gain ); + move32(); /* Q_bwe_exc + 16 */ + j++; + } + } + + + + max = 0; + move16(); + FOR( i = 0; i < l_frame + l_shb_lahead; i++ ) + { + abs_sig = abs_s( round_fx(mod_syn[i]) ); + if(GT_16(abs_sig,max)) + { + max = abs_sig; + move16(); + } + } + + FOR( i = 0; i < HILBERT_MEM_SIZE; i++ ) + { + abs_sig = abs_s( round_fx(Hilbert_Mem[i]) ); + if(GT_16(abs_sig,max)) + { + max = abs_sig; + move16(); + } + } + + sc1 = norm_s( max ); /* max headroom in mod_syn[] */ + sc2 = norm_s( round_fx(frame_gain));/* headroom in GainFrame */ + + IF(dynQ == 0 ) + { + shift = sub(13, Q_bwe_exc); /* earlier = (10 - Q_bwe_exc) but we changed GainFrame Q21 to Q18 */ + *Qx = 0; + } + ELSE IF (EQ_16(L_frame,L_FRAME)) /* 12.8k core */ + { + max_headroom = sub(add(sc1,sc2),4); /* Max headroom after multiplying = sc1 + sc2 -3 (keep 3 bit extra headroom) */ + /* 12.8k core needs extra headroom than 16k core */ + /* otherwise Hilbert transform inside flip_and_downmix have saturation, causes ringing in output */ + + /* Qx = (Q_bwe_exc+3) + shift - 16 */ + /* make sure 14 > Qx > 2 */ + min_shift = 2-(Q_bwe_exc+3-16); + max_shift = 13-(Q_bwe_exc+3-16); + max_shift2 = s_min(max_shift,max_headroom); /* avoid shifting more than the available max headroom to avoid overflow */ + + shift = s_min(min_shift,max_shift2); + *Qx = (Q_bwe_exc+3) + shift - 16; + } + ELSE /* 16k core */ + { + max_headroom = sub(add(sc1,sc2),1); /* Max headroom after multiplying = sc1 + sc2 -1 (keep 1 bit extra headroom) */ + + /* Qx = (Q_bwe_exc+3) + shift - 16 */ + /* make sure 14 > Qx > 3 */ + min_shift = 3-(Q_bwe_exc+3-16); + max_shift = 13-(Q_bwe_exc+3-16); + max_shift2 = s_min(max_shift,max_headroom); /* avoid shifting more than the available max headroom to avoid overflow */ + + shift = s_min(min_shift,max_shift2); + *Qx = (Q_bwe_exc+3) + shift - 16; + } + + /* bring memory st_fx->syn_overlap_fx[] = overlap[i] to new Q = Qx to prepare for addition */ + FOR ( i = 0; i < l_shb_lahead; i++ ) + { + overlap[i] = shl(overlap[i], (*Qx - prev_Qx)); + } + + FOR ( i = 0; i < l_shb_lahead; i++ ) + { + /* mod_syn in (16+Q_bwe_exc), frame_gain in Q18 */ + L_tmp = Mult_32_32( mod_syn[i], frame_gain ); /* L_tmp in (Q_bwe_exc+3) */ + synSHB[i] = round_fx( L_shl( Mult_32_16( L_tmp, win[i] ), shift) ); /* Qx */ + synSHB[i] = add( synSHB[i], overlap[i] ); + move16(); /* Qx */ + synSHB[i + l_shb_lahead] = round_fx( L_shl( L_tmp, shift) ); /* Qx */ + } + + FOR ( ; i < l_frame; i++ ) + { + L_tmp = Mult_32_32( mod_syn[i], frame_gain); /* L_tmp in (Q_bwe_exc+3) */ + synSHB[i] = round_fx( L_shl(L_tmp, shift) ); /* Qx; */ + } + + l_frame_tmp = add(l_frame, l_shb_lahead); + FOR ( ; i < l_frame_tmp; i++ ) + { + L_tmp = Mult_32_32( mod_syn[i], frame_gain ); /* (Q_bwe_exc+3) */ + overlap[i - l_frame] = round_fx( L_shl( Mult_32_16( L_tmp, win[l_frame + l_shb_lahead - 1 - i] ), shift ) ); /* Qx */ + } + + return; +} + +static Word32 non_linearity_scaled_copy( + const Word16 input[], + Word16 j, + Word16 length, + Word32 output[], + Word32 prev_scale, + Word16 scale_step, + Word16 en_abs +) +{ + Word16 i; + Word32 L_tmp; + + IF (en_abs) + { + FOR ( i = 0; i < j; i++ ) + { + L_tmp = L_mult( input[i], input[i] ); /* 2*Q_inp+1 */ + L_tmp = Mult_32_32( L_tmp, prev_scale ); /* 2*Q_inp */ + output[i] = L_tmp; + move32(); + + L_tmp = Mult_32_16( prev_scale, scale_step ); /* Q29 */ + prev_scale = L_shl( L_tmp, 1 ); /* Q30 */ + } + FOR ( ; i < length; i++ ) + { + L_tmp = L_mult( input[i], input[i] ); /* 2*Q_inp+1 */ + L_tmp = Mult_32_32( L_tmp, prev_scale ); /* 2*Q_inp */ + output[i] = L_tmp; + move32(); + } + } + ELSE + { + FOR ( i = 0; i < j; i++ ) + { + L_tmp = L_mult( input[i], input[i] ); /* 2*Q_inp+1 */ + L_tmp = Mult_32_32( L_tmp, prev_scale ); /* 2*Q_inp */ + + if ( input[i] < 0 ) + { + L_tmp = L_negate(L_tmp); + } + output[i] = L_tmp; + move32(); + + L_tmp = Mult_32_16( prev_scale, scale_step ); /* Q29 */ + prev_scale = L_shl( L_tmp, 1 ); /* Q30 */ + } + + FOR ( ; i < length; i++ ) + { + L_tmp = L_mult( input[i], input[i] ); /* 2*Q_inp+1 */ + L_tmp = Mult_32_32( L_tmp, prev_scale ); /* 2*Q_inp */ + + if ( input[i] < 0 ) + { + L_tmp = L_negate(L_tmp); + } + output[i] = L_tmp; + move32(); + } + } + return prev_scale; +} + +/*==========================================================================*/ +/* FUNCTION : void non_linearity() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Apply a non linearity to the SHB excitation */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 input[] i : input signal Q_inp */ +/* Word16 length i : input length */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* Word32 output[] o : output signal 2*Q_inp */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Word32 *prev_scale i/o: memory Q30 */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*==========================================================================*/ + +void non_linearity_fx( + const Word16 input[], /* i : input signal Q_inp */ + Word32 output[], /* o : output signal 2*Q_inp */ + const Word16 length, /* i : input length */ + Word32* pPrevScale, /* i/o: memory Q30 */ + Word16 Q_inp + ,Word16 coder_type, /* i : Coder Type */ + Word16 *voice_factors, /* i : Voice Factors */ + const Word16 L_frame /* i : ACELP frame length */ + +) +{ + Word16 i, j; + Word16 max=0; + Word32 scale; + Word16 scale_step; + Word16 exp, tmp; + Word16 e_tmp, f_tmp; + Word16 frac; + Word32 L_tmp; + Word32 L_tmp1; + + Word16 en_abs = 0; + Word16 v_fac = 0; + Word16 ths; + Word16 nframes; + Word32 prev_scale; + Word16 length_half; + + + IF ( EQ_16(L_frame, L_FRAME16k )) + { + nframes = 5; + move16(); + ths = 17817; + move16(); /* 0.87*5 in Q12 */ + } + ELSE + { + nframes = 4; + move16(); + ths = 15400; + move16(); /* 0.94*4 in Q12 */ + } + + + FOR ( i = 0; i < nframes; i++ ) + { + v_fac = add( v_fac, shr( voice_factors[i], 3 ) ); /* Q12 */ + } + + test(); + if ( EQ_16( coder_type, VOICED )&>_16(v_fac,ths)) + { + en_abs = 1; + move16(); + } + + length_half = shr(length, 1); + prev_scale = *pPrevScale; + move32(); + + + + /* Delay Alignment in FX is done inside swb_tbe_enc_fx() */ + + FOR ( i = j = 0; i < length_half; i++ ) + { + tmp = abs_s(input[i]); + if(GT_16(tmp,max)) + { + j = i; + move16(); + } + max = s_max(max, tmp); + + } + + + IF ( GT_16(max, shl(1,Q_inp))) + { + exp = norm_s( max ); + tmp = div_s( shl(1, sub( 14, exp)), max ); /* Q(29-exp-Q_inp) */ + scale = L_shl( L_mult( 21955, tmp ), add(exp, sub(Q_inp,14)) ); /* Q31 */ + } + ELSE + { + scale = 1438814044; + move32(); /* Q31; 0.67 in Q31 */ + } + + test(); + IF ( prev_scale <= 0 || GT_32( Mult_32_16( prev_scale, 32 ), scale )) + { + scale_step = 16384; + move16(); /* Q14 */ + prev_scale = L_shr( scale, 1 ); /* Q30 */ + } + ELSE + { + + /* Computing log2(scale) */ + IF ( j == 0 ) + { + scale_step = 32767; + move16(); + } + ELSE + { + e_tmp = norm_l( scale ); + f_tmp = Log2_norm_lc( L_shl( scale, e_tmp ) ); + e_tmp = sub(-1, e_tmp); + L_tmp = Mpy_32_16( e_tmp, f_tmp, 32767 ); /* Q16 */ + + /* Computing log2(prev_scale) */ + e_tmp = norm_l( prev_scale ); + f_tmp = Log2_norm_lc( L_shl( prev_scale, e_tmp ) ); + e_tmp = negate(e_tmp); + L_tmp1 = Mpy_32_16( e_tmp, f_tmp, 32767 ); /* Q16 */ + + /* log2(scale / prev_scale) = log2(scale) - log2(prev_scale) */ + L_tmp = L_sub( L_tmp, L_tmp1 ); /* Q16 */ + + /* Computing 1/j */ + exp = norm_s( j ); + tmp = div_s( shl(1, sub( 14, exp)), j ); /* Q(29-exp) */ + + /* (log2(scale / prev_scale))/length */ + L_tmp = L_shl( Mult_32_16( L_tmp, tmp ), sub(exp, 14) ); /* Q(16+29-exp+1-16+exp-14)->Q16 */ + + frac = L_Extract_lc( L_tmp, &exp ); /* Extract exponent of L_tmp */ + + tmp = extract_l( Pow2( 14, frac ) ); + scale_step = shl( tmp, exp ); /* Q14 */ + } + } + + prev_scale = non_linearity_scaled_copy( input, j, length_half, output, prev_scale, scale_step, en_abs ); + + max = 0; + move16(); + j = shr(length, 1); + FOR ( i = length_half; i < length; i++ ) + { + tmp = abs_s(input[i]); + if(GT_16(tmp,max)) + { + j = i; + move16(); + } + max = s_max(max, tmp); + } + + IF ( GT_16( max, shl( 1, Q_inp ) )) + { + exp = norm_s( max ); + tmp = div_s( shl(1, sub( 14, exp)), max ); /* Q(29-exp-Q_inp) */ + scale = L_shl( L_mult( 21955, tmp ), add(exp, sub(Q_inp, 14)) ); /* Q31 */ + } + ELSE + { + scale = 1438814044; + move32(); /* Q31; 0.67 in Q31 */ + } + + test(); + IF ( prev_scale <= 0 || GT_32( Mult_32_16( prev_scale, 32 ), scale )) + { + scale_step = 16384; + move16(); /*Q14 */ + prev_scale = L_shr( scale, 1 ); /*Q30 */ + } + ELSE + { + /*scale_step = (float) exp(1.0f / (float) (j - length/2) * (float) log(scale / prev_scale)); */ + /* Computing log2(scale) */ + IF ( EQ_16(j,length_half)) + { + scale_step = 32767; + move16();/*Q14 */ + } + ELSE + { + e_tmp = norm_l( scale ); + f_tmp = Log2_norm_lc( L_shl( scale, e_tmp ) ); + e_tmp = sub(-e_tmp, 1); + L_tmp = Mpy_32_16( e_tmp, f_tmp, 32767 ); /* Q16 */ + + /* Computing log2(prev_scale) */ + e_tmp = norm_l( prev_scale ); + f_tmp = Log2_norm_lc( L_shl( prev_scale, e_tmp ) ); + e_tmp = negate(e_tmp); + L_tmp1 = Mpy_32_16( e_tmp, f_tmp, 32767 ); /* Q16 */ + + /* log2(scale / prev_scale) = log2(scale) - log2(prev_scale) */ + L_tmp = L_sub( L_tmp, L_tmp1 ); /* Q16 */ + + /* Computing 1/(j - length/2) */ + + tmp = sub( j, length_half ); + exp = norm_s( tmp ); + + + tmp = div_s( shl(1, sub( 14, exp)), tmp ); /* Q(29-exp) */ + + /* (log2(scale / prev_scale))/length */ + L_tmp = L_shl( Mult_32_16( L_tmp, tmp ), sub(exp,14) ); /*Q(16+29-exp+1-16+exp-14)->Q16 */ + + frac = L_Extract_lc( L_tmp, &exp ); /* Extract exponent of L_tmp */ + + tmp = extract_l( Pow2( 14, frac ) ); + scale_step = shl( tmp, exp ); /*Q14 */ + } + } + + prev_scale = non_linearity_scaled_copy( input+length_half, sub(j, length_half), sub(length, length_half), output+length_half, prev_scale, scale_step, en_abs ); + + *pPrevScale = prev_scale; + move32(); + + /* Delay Alignment in FX is done inside swb_tbe_enc_fx() */ + + return; +} + + + + +/*-------------------------------------------------------------------* +* create_random_vector() +* +* creates random number vector +* Note: the abs(max) value coming out of create_random_vector should +* fit into the precision of Q6. +* -------------------------------------------------------------------*/ + +void create_random_vector_fx( + Word16 output[], /* o : output random vector Q5*/ + const Word16 length, /* i : length of random vector */ + Word16 seed[] /* i/o: start seed */ +) +{ + Word16 i, j, k; + Word16 scale1, scale2; + Word32 L_tmp; + + L_tmp = L_abs( Mult_32_16( 2144047674, Random( &seed[0] ) ) );/*Q23 */ + j = extract_l( L_shr( L_tmp, 23 ) ); + j = s_and( j, 0xff ); + + L_tmp = L_abs( Mult_32_16( 2144047674, Random( &seed[1] ) ) );/*Q23 */ + k = extract_l( L_shr( L_tmp, 23 ) ); + k = s_and( k, 0xff ); + + WHILE ( EQ_16(k,j)) + { + L_tmp = L_abs( Mult_32_16( 2144047674, Random( &seed[1] ) ) );/*Q23 */ + k = extract_l( L_shr( L_tmp, 23 ) ); + k = s_and( k, 0xff ); + } + + scale1 = 18021; + move16(); /* 200.00f * 0.35f/0.1243f; */ + if ( Random( &seed[0] ) < 0 ) + { + scale1 = -18021; + move16(); /*Q5 */ /* -200.00f * 0.35f/0.1243f; */ + } + + scale2 = 7208; + move16(); /* 80.00f * 0.35f/0.1243f; */ + if ( Random( &seed[1] ) < 0 ) + { + scale2 = -7208; + move16(); /*Q5 */ /* -80.00f * 0.35f/0.1243f; */ + } + + FOR ( i = 0; i < length; i++ ) + { + j = s_and( j, 0xff ); + k = s_and( k, 0xff ); + output[i] = round_fx( L_add( L_mult( scale1, gaus_dico_swb_fx[j] ), L_mult( scale2, gaus_dico_swb_fx[k] ) ) ); /*Q5 */ + j++; + k++; + } + + return; +} + + +/*======================================================================================*/ +/* FUNCTION : interp_code_5over2_fx() */ +/*--------------------------------------------------------------------------------------*/ +/* PURPOSE : Used to interpolate the excitation from the core sample rate */ +/* of 12.8 kHz to 32 kHz. */ +/* Simple linear interpolator - No need FOR precision here. */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16[]) inp_code_fx : input vector (Q12) */ +/* _ (Word16) inp_length : length of input vector */ +/*--------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) interp_code_fx : output vector (Q12) */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------------------*/ + +/* _ None */ +/*--------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*======================================================================================*/ + +void interp_code_5over2_fx( + const Word16 inp_code_fx[], /* i : input vector Qx*/ + Word16 interp_code_fx[], /* o : output vector Qx*/ + const Word16 inp_length /* i : length of input vector */ +) +{ + Word16 i, kk, kkp1, i_len2; + Word32 Ltemp; + Word16 factor_i_fx[5] = {6554, 19661, 32767, 19661, 6554}; + Word16 factor_j_fx[5] = {26214, 13107, 0, 13107, 26214}; + + interp_code_fx[0] = inp_code_fx[0]; + move16();/* Qx */ + + Ltemp = L_mult( inp_code_fx[0], factor_i_fx[3] );/* Q(16+x) */ + Ltemp = L_mac( Ltemp, inp_code_fx[1], factor_j_fx[3] );/* Q(16+x) */ + interp_code_fx[1] = round_fx( Ltemp );/*Qx */ + + Ltemp = L_mult( inp_code_fx[0], factor_i_fx[4] );/*Q(16+x) */ + Ltemp = L_mac( Ltemp, inp_code_fx[1], factor_j_fx[4] );/*Q(16+x) */ + interp_code_fx[2] = round_fx( Ltemp ); /* Qx */ + + kk = 1; + move16(); + kkp1 = 2; + move16(); + i = 3; + move16(); + /*i_len2 = ( inp_length - 2 ) * HIBND_ACB_L_FAC; */ /*HIBND_ACB_L_FAC == 5/2 */ + i_len2 = sub(inp_length, 2); + i_len2 = shr(add(shl(i_len2, 2),i_len2),1); /* rounding below during shr makes it non BE*/ + + FOR ( ; i < i_len2; i += 5 ) + { + Ltemp = L_mult( inp_code_fx[kk], factor_j_fx[0] );/*Q(16+x) */ + Ltemp = L_mac( Ltemp, inp_code_fx[kkp1], factor_i_fx[0] );/*Q(16+x) */ + interp_code_fx[i] = round_fx( Ltemp );/*Qx */ + + Ltemp = L_mult( inp_code_fx[kk], factor_j_fx[1] );/*Q(16+x) */ + Ltemp = L_mac( Ltemp, inp_code_fx[kkp1], factor_i_fx[1] );/*Q(16+x) */ + interp_code_fx[i + 1] = round_fx( Ltemp );/*Qx */ + + Ltemp = L_mult( inp_code_fx[kkp1], factor_i_fx[2] );/*Q(16+x) */ + interp_code_fx[i + 2] = round_fx( Ltemp );/*Qx */ + + kk++; + kkp1++; + + Ltemp = L_mult( inp_code_fx[kk], factor_i_fx[3] );/*Q(16+x) */ + Ltemp = L_mac( Ltemp, inp_code_fx[kkp1], factor_j_fx[3] );/*Q(16+x) */ + interp_code_fx[i + 3] = round_fx( Ltemp ); /*Qx */ + + Ltemp = L_mult( inp_code_fx[kk], factor_i_fx[4] );/*Q(16+x) */ + Ltemp = L_mac( Ltemp, inp_code_fx[kkp1], factor_j_fx[4] );/*Q(16+x) */ + interp_code_fx[i + 4] = round_fx( Ltemp ); /*Qx */ + + kk++; + kkp1++; + } + + Ltemp = L_mult( inp_code_fx[kk], factor_j_fx[0] );/*Q(16+x) */ + interp_code_fx[i] = round_fx( Ltemp ); /*Qx */ + + Ltemp = L_mult( inp_code_fx[kk], factor_j_fx[1] );/*Q(16+x) */ + interp_code_fx[i + 1] = round_fx( Ltemp ); /*Qx */ + + return; +} + + + +/*======================================================================================*/ +/* FUNCTION : interp_code_4over2_fx() */ +/*--------------------------------------------------------------------------------------*/ +/* PURPOSE : Used to interpolate the excitation from the core sample rate */ +/* of 16 kHz to 32 kHz. */ +/* Simple linear interpolator - No need for precision here. */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16[]) inp_code_fx : input vector (Qx) */ +/* _ (Word16) inp_length : length of input vector */ +/*--------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) interp_code_fx : output vector (Qx) */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------------------*/ + +/* _ None */ +/*--------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*======================================================================================*/ + +void interp_code_4over2_fx( + const Word16 inp_code_fx[], /* i : input vector Qx*/ + Word16 interp_code_fx[], /* o : output vector Qx*/ + const Word16 inp_length /* i : length of input vector */ +) +{ + Word16 i, j; + j = 0; + move16(); + FOR ( i = 0; i < inp_length - 1; i++ ) + { + interp_code_fx[j] = inp_code_fx[i]; + move16();/*Qx */ + interp_code_fx[j + 1] = add( shr( inp_code_fx[i], 1 ), shr( inp_code_fx[i + 1], 1 ) ); + move16(); + move16();/*Qx */ + j = add( j, 2 ); + } + + interp_code_fx[j] = inp_code_fx[i]; + move16(); + interp_code_fx[j + 1] = shr( inp_code_fx[i], 1 ); + move16();/*Qx */ + + return; +} + + +/*-------------------------------------------------------------------* +* wb_tbe_extras_reset_synth() +* +* Reset the extra parameters only required for WB TBE synthesis +*-------------------------------------------------------------------*/ + +void wb_tbe_extras_reset_synth_fx( Word16 state_lsyn_filt_shb[], Word16 state_lsyn_filt_dwn_shb[], + Word16 state_32and48k_WB_upsample[] + ,Word16 state_resamp_HB[] + ) +{ + set16_fx( state_lsyn_filt_shb, 0, 2 * ALLPASSSECTIONS_STEEP ); + set16_fx( state_lsyn_filt_dwn_shb, 0, 2 * ALLPASSSECTIONS_STEEP ); + set16_fx( state_32and48k_WB_upsample, 0, 2 * ALLPASSSECTIONS_STEEP ); + set16_fx( state_resamp_HB, 0, INTERP_3_1_MEM_LEN ); + + return; +} + +/*-------------------------------------------------------------------* + * elliptic_bpf_48k_generic() + * + * 18th-order elliptic bandpass filter at 14.0 to 20 kHz sampled at 48 kHz + * Implemented as 3 fourth order sections cascaded. + *-------------------------------------------------------------------*/ + +void elliptic_bpf_48k_generic_fx( + const Word16 input_fx[], /* i : input signal */ + Word16 *Q_input_fx, + Word16 output_fx[], /* o : output signal */ + Word32 memory_fx2[][4], /* i/o: 4 arrays of 4 for memory */ + Word16 memory_fx_Q[], + const Word16 full_band_bpf_fx[][5] /* i : filter coefficients b0,b1,b2,a0,a1,a2 Q13 */ +) +{ + Word16 i,j; + Word16 memory_fx0[4][4], memory_fx[4][4], Q_temp, Q_temp2; + Word32 L_tmp[L_FRAME48k], L_tmp2[L_FRAME48k], L_output[L_FRAME48k], L_tmpX, memory2_fx[4][4], L_tmpMax; + Word32 memory2_fx_2[4], memory2_fx_3[4]; + + FOR( i=0; i<4; i++ ) + { + memory_fx0[0][i] = extract_l(memory_fx2[0][i]); + memory_fx[0][i] =shl(memory_fx0[0][i],sub(*Q_input_fx,memory_fx_Q[0])); + memory2_fx[1][i] =L_shl(memory_fx2[1][i],sub(add(*Q_input_fx,11),memory_fx_Q[1])); + memory2_fx[2][i] =L_shl(memory_fx2[2][i],sub(add(*Q_input_fx,6),memory_fx_Q[2])); + memory2_fx[3][i] =L_shl(memory_fx2[3][i],sub(add(*Q_input_fx,1),memory_fx_Q[3])); + } + + L_tmpX = L_shr(L_mult(memory_fx[0][0],full_band_bpf_fx[0][4]),3);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(memory_fx[0][1],full_band_bpf_fx[0][3]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(memory_fx[0][2],full_band_bpf_fx[0][2]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(memory_fx[0][3],full_band_bpf_fx[0][1]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(input_fx[0],full_band_bpf_fx[0][0]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_sub(L_tmpX,L_shl(Mult_32_16(memory2_fx[1][3],full_band_bpf_fx[3][1]),2));/*Q_input_fx + 11 + 13 -15 +2*/ + L_tmpX = L_sub(L_tmpX,L_shl(Mult_32_16(memory2_fx[1][2],full_band_bpf_fx[3][2]),2));/*Q_input_fx + 11 + 13 -15 +2*/ + L_tmpX = L_sub(L_tmpX,L_shl(Mult_32_16(memory2_fx[1][1],full_band_bpf_fx[3][3]),2));/*Q_input_fx + 11 + 13 -15 +2*/ + L_tmp[0] = L_sub(L_tmpX,L_shl(Mult_32_16(memory2_fx[1][0],full_band_bpf_fx[3][4]),2));/*Q_input_fx + 11 + 13 -15 +2*/ move32(); + + L_tmpX = L_shr(L_mult(memory_fx[0][1],full_band_bpf_fx[0][4]),3);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(memory_fx[0][2],full_band_bpf_fx[0][3]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(memory_fx[0][3],full_band_bpf_fx[0][2]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(input_fx[0],full_band_bpf_fx[0][1]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(input_fx[1],full_band_bpf_fx[0][0]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_sub(L_tmpX,L_shl(Mult_32_16(L_tmp[0],full_band_bpf_fx[3][1]),2));/*Q_input_fx + 11 + 13 -15 +2*/ + L_tmpX = L_sub(L_tmpX,L_shl(Mult_32_16(memory2_fx[1][3],full_band_bpf_fx[3][2]),2));/*Q_input_fx + 11 + 13 -15 +2*/ + L_tmpX = L_sub(L_tmpX,L_shl(Mult_32_16(memory2_fx[1][2],full_band_bpf_fx[3][3]),2));/*Q_input_fx + 11 + 13 -15 +2*/ + L_tmp[1] = L_sub(L_tmpX,L_shl(Mult_32_16(memory2_fx[1][1],full_band_bpf_fx[3][4]),2));/*Q_input_fx + 11 + 13 -15 +2*/ move32(); + + L_tmpX = L_shr(L_mult(memory_fx[0][2],full_band_bpf_fx[0][4]),3);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(memory_fx[0][3],full_band_bpf_fx[0][3]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(input_fx[0],full_band_bpf_fx[0][2]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(input_fx[1],full_band_bpf_fx[0][1]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(input_fx[2],full_band_bpf_fx[0][0]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_sub(L_tmpX,L_shl(Mult_32_16(L_tmp[1],full_band_bpf_fx[3][1]),2));/*Q_input_fx + 11 + 13 -15 +2*/ + L_tmpX = L_sub(L_tmpX,L_shl(Mult_32_16(L_tmp[0],full_band_bpf_fx[3][2]),2));/*Q_input_fx + 11 + 13 -15 +2*/ + L_tmpX = L_sub(L_tmpX,L_shl(Mult_32_16(memory2_fx[1][3],full_band_bpf_fx[3][3]),2));/*Q_input_fx + 11 + 13 -15 +2*/ + L_tmp[2] = L_sub(L_tmpX,L_shl(Mult_32_16(memory2_fx[1][2],full_band_bpf_fx[3][4]),2));/*Q_input_fx + 11 + 13 -15 +2*/ move32(); + + L_tmpX = L_shr(L_mult(memory_fx[0][3],full_band_bpf_fx[0][4]),3);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(input_fx[0],full_band_bpf_fx[0][3]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(input_fx[1],full_band_bpf_fx[0][2]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(input_fx[2],full_band_bpf_fx[0][1]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_add(L_shr(L_mult(input_fx[3],full_band_bpf_fx[0][0]),3),L_tmpX);/*Q_input_fx + 13 + 1 - 3*/ + L_tmpX = L_sub(L_tmpX,L_shl(Mult_32_16(L_tmp[2],full_band_bpf_fx[3][1]),2));/*Q_input_fx + 11 + 13 -15 +2*/ + L_tmpX = L_sub(L_tmpX,L_shl(Mult_32_16(L_tmp[1],full_band_bpf_fx[3][2]),2));/*Q_input_fx + 11 + 13 -15 +2*/ + L_tmpX = L_sub(L_tmpX,L_shl(Mult_32_16(L_tmp[0],full_band_bpf_fx[3][3]),2));/*Q_input_fx + 11 + 13 -15 +2*/ + L_tmp[3] = L_sub(L_tmpX,L_shl(Mult_32_16(memory2_fx[1][3],full_band_bpf_fx[3][4]),2));/*Q_input_fx + 11 + 13 -15 +2*/ move32(); + + FOR( i=4; i0) + { + expa = norm_l(temp_p1_p3); + fraca = extract_h(L_shl(temp_p1_p3,expa)); + expa = sub(30,expa); + + expb = norm_l(temp_p1_p2); + fracb = round_fx(L_shl(temp_p1_p2,expb)); + expb = sub(30,expb); + + num_flag = 0; + move16(); + IF(fraca<0) + { + num_flag = 1; + move16(); + fraca = negate(fraca); + } + + den_flag = 0; + move16(); + IF(fracb<0) + { + den_flag = 1; + move16(); + fracb = negate(fracb); + } + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); + exp1 = sub(expb,expa); + tmp = shl(tmp,exp1); + + if(NE_16(num_flag,den_flag)) + { + tmp = negate(tmp); + } + } + ELSE + { + tmp = 0; + } + + vf_modified[0] = s_min(s_max(tmp, 3277 /* 0.1f in Q15*/), 32440 /* 0.99f in Q15 */); + move16(); + + *vf_ind = usquant_fx(vf_modified[0], &tmp1, 4096 /* 0.125 in Q15 */, 2048 /* 0.125 in Q14 */, shl(1,NUM_BITS_SHB_VF)); + move16(); + + vf_modified[0] = tmp1; + move16(); + vf_modified[1] = tmp1; + move16(); + vf_modified[2] = tmp1; + move16(); + vf_modified[3] = tmp1; + move16(); + vf_modified[4] = tmp1; + move16(); + + /* vf_modified in Q15 */ + + return; +} + +/*======================================================================================*/ +/* FUNCTION : prep_tbe_exc_fx() */ +/*--------------------------------------------------------------------------------------*/ +/* PURPOSE : Prepare TBE excitation */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) L_frame_fx : length of the frame */ +/* _ (Word16) i_subfr_fx : subframe index */ +/* _ (Word16) gain_pit_fx : Pitch gain (14) */ +/* _ (Word32) gain_code_fx : algebraic codebook gain (Q(16+Q_exc)) */ +/* _ (Word16*[]) code_fx : algebraic excitation (Q9) */ +/* _ (Word16) voice_fac_fx : voicing factor (Q15) */ +/* _ (Word16) gain_preQ_fx : prequantizer excitation gain */ +/* _ (Word16[]) code_preQ_fx : prequantizer excitation */ +/*--------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*[]) voice_factors_fx : TBE voicing factor (Q15) */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16[]) bwe_exc_fx : excitation for TBE (Q_exc) */ +/*--------------------------------------------------------------------------------------*/ + +/* _ None */ +/*--------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*======================================================================================*/ + +void prep_tbe_exc_fx( + const Word16 L_frame_fx, /* i : length of the frame */ + const Word16 i_subfr_fx, /* i : subframe index */ + const Word16 gain_pit_fx, /* i : Pitch gain Q14*/ + const Word32 gain_code_fx, /* i : algebraic codebook gain 16+Q_exc*/ + const Word16 code_fx[], /* i : algebraic excitation Q9*/ + const Word16 voice_fac_fx, /* i : voicing factor Q15*/ + Word16 *voice_factors_fx, /* o : TBE voicing factor Q15*/ + Word16 bwe_exc_fx[], /* i/o: excitation for TBE Q_exc*/ + const Word16 gain_preQ_fx, /* i : prequantizer excitation gain */ + const Word16 code_preQ_fx[], /* i : prequantizer excitation */ + const Word16 Q_exc, /* i : Excitation, bwe_exc Q-factor */ + Word16 T0, /* i : integer pitch variables Q0 */ + Word16 T0_frac, /* i : Fractional pitch variables Q0*/ + const Word16 coder_type, /* i : coding type */ + Word32 core_brate /* i :core bitrate */ +) +{ + Word16 i; + Word16 tmp_code_fx[L_SUBFR * HIBND_ACB_L_FAC]; + Word16 tmp_code_preInt_fx[L_SUBFR]; + Word16 gain_code16 = 0; + Word16 tmp /*, tmp1, tmp2*/; + /*Word16 random_code[L_SUBFR * HIBND_ACB_L_FAC];*/ + Word16 pitch; + + Word32 L_tmp, Ltemp1, Ltemp2; + Word32 tempQ31; + Word16 tempQ15; + + /**voice_factors = VF_0th_PARAM + VF_1st_PARAM * voice_fac + VF_2nd_PARAM * voice_fac * voice_fac; + = VF_0th_PARAM + voice_fac * (VF_1st_PARAM + VF_2nd_PARAM * voice_fac ) + *voice_factors = min( max(0.0f, *voice_factors), 1.0f); */ + tempQ31 = L_deposit_h( VF_1st_PARAM_FX ); + tempQ15 = mac_r(tempQ31, VF_2nd_PARAM_FX, voice_fac_fx); + tempQ31 = L_deposit_h( VF_0th_PARAM_FX ); + *voice_factors_fx = mac_r(tempQ31, voice_fac_fx, tempQ15); + + tmp = 32767; + move16(); + + pitch = shl( add( shl( T0, 2 ), T0_frac ), 5 ); /* Q7 */ + + test(); + test(); + IF ( ( ( EQ_16(coder_type,VOICED))||(GT_16(pitch,14784)))&&(GT_32(core_brate,ACELP_8k00))) + { + tmp = MAX_16; + move16(); + *voice_factors_fx = mult_r( *voice_factors_fx, tmp ); + } + + *voice_factors_fx = s_min(s_max(*voice_factors_fx, 0), MAX_16); + move16(); + + IF ( EQ_16(L_frame_fx,L_FRAME)) + { + interp_code_5over2_fx( code_fx, tmp_code_fx, L_SUBFR ); /* code: Q9, tmp_code: Q9 */ + gain_code16 = round_fx( L_shl( gain_code_fx, Q_exc ) ); /*Q_exc */ + FOR ( i = 0; i < L_SUBFR * HIBND_ACB_L_FAC; i++ ) + { + L_tmp = L_mult( gain_code16, tmp_code_fx[i] ); /* Q9 + Q_exc + 1*/ + L_tmp = L_shl( L_tmp, 5 ); /* Q9 + Q_exc + Q6*/ + L_tmp = L_mac( L_tmp, gain_pit_fx, bwe_exc_fx[i + i_subfr_fx * HIBND_ACB_L_FAC] ); /*Q15+Q_exc */ + L_tmp = L_shl( L_tmp, 1 ); /*16+Q_exc */ /* saturation can occur here */ + bwe_exc_fx[i + i_subfr_fx * HIBND_ACB_L_FAC] = round_fx( L_tmp ); /*Q_exc */ + } + } + ELSE + { + IF( gain_preQ_fx != 0 ) + { + FOR( i = 0; i < L_SUBFR; i++ ) + { + /*code in the encoder is Q9 and there is no <<1 with Mult_32_16 Q16 * Q9 -> Q9 */ + Ltemp1 = Mult_32_16(gain_code_fx, code_fx[i]); /* Q16 + Q9 + 1 - 16 = Q10 */ + Ltemp2 = L_mult(gain_preQ_fx, code_preQ_fx[i]); /*Q2 * Q10 -> Q12 */ + + Ltemp1 = L_shl( Ltemp1, Q_exc+6 /*Q_exc+16-19*/) ; /*Q_exc+16 */ + Ltemp2 = L_shl( Ltemp2, Q_exc+4 /*Q_exc+16-13*/ ) ; /*Q_exc+16 */ + + tmp_code_preInt_fx[i] = round_fx(L_add(Ltemp1, Ltemp2)); /* Q_exc */ + } + } + ELSE + { + FOR( i = 0; i < L_SUBFR; i++ ) + { + /*code in the encoder is Q9 and there is no <<1 with Mult_32_16 Q16 * Q9 -> Q9 */ + Ltemp1 = Mult_32_16(gain_code_fx, code_fx[i]); /* Q16 + Q9 + 1 - 16 = Q10 */ + Ltemp1 = L_shl( Ltemp1, Q_exc+6 /*Q_exc+16-19*/) ; /*Q_exc+16 */ + tmp_code_preInt_fx[i] = round_fx(Ltemp1); /* Q_exc */ + } + } + + interp_code_4over2_fx( tmp_code_preInt_fx, tmp_code_fx, L_SUBFR ); /* o: tmp_code in Q_exc */ + FOR ( i = 0; i < L_SUBFR * 2; i++ ) + { + L_tmp = L_mult(gain_pit_fx, bwe_exc_fx[i + i_subfr_fx*2]); /*Q14+Q_exc+1 */ + tmp = round_fx(L_shl(L_tmp, 1 /* (Q_exc+16)-(14+Q_exc+1)*/ )); /* tmp in Q_exc */ + bwe_exc_fx[i + i_subfr_fx * 2] = add(tmp, tmp_code_fx[i]); /*Q_exc */ move16(); + } + } + + return; +} + + +/*=============================================================================*/ +/* FUNCTION : void swb_formant_fac_fx ( ) */ +/*------------------------------------------------------------------------------*/ +/* PURPOSE : * Find strength of adaptive formant postfilter using tilt */ +/* of the high band. The 2nd lpc coefficient is used as a tilt approximation. */ +/*------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* const Word16 lpc_shb2 : 2nd HB LPC coefficient Q12 */ +/*------------------------------------------------------------------------------*/ +/*INPUT/OUTPUT ARGUMENTS : */ +/* Word16 *tilt_mem Q12 */ +/* OUTPUT ARGUMENTS : */ +/*------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* formant_fac :Formant filter strength [0,1] Q15 */ +/*------------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*==============================================================================*/ + +Word16 swb_formant_fac_fx( /* o : Formant filter strength [0,1] */ + const Word16 lpc_shb2, /* Q12 i : 2nd HB LPC coefficient */ + Word16* tilt_mem /* i/o: Tilt smoothing memory (Q12) */ +) +{ + Word16 formant_fac; + Word16 tmp; + + /* Smoothen tilt value */ + /* tmp = 0.5f * (float)fabs(lpc_shb2) + 0.5f * *tilt_mem; */ + tmp = mult_r( 16384, abs_s( lpc_shb2 ) ); + tmp = add( tmp, mult_r( 16384, *tilt_mem ) ); /* Q12 */ + *tilt_mem = tmp; + move16();/*Q12 */ + /* Map to PF strength */ + /* formant_fac = (tmp - SWB_TILT_LOW)*SWB_TILT_DELTA; */ + tmp = sub( tmp, SWB_TILT_LOW_FX ); /* Q12 */ + formant_fac = mult_r( tmp, SWB_TILT_DELTA_FX ); /* Q12 */ + + + IF ( GT_16( formant_fac, 4096 )) + { + formant_fac = 4096; + move16(); + } + ELSE if ( formant_fac < 0 ) + { + formant_fac = 0; + move16(); + } + /* now formant_fac in Q12 */ + + /* formant_fac = 1.0f - 0.5f*formant_fac */ + tmp = mult_r(16384, formant_fac); /* 0.5 in Q12 */ + formant_fac = shl(sub(4096,tmp),3); + + return formant_fac; /*Q15 */ +} + + +void wb_tbe_extras_reset_fx( + Word16 mem_genSHBexc_filt_down_wb2[], + Word16 mem_genSHBexc_filt_down_wb3[] ) +{ + set16_fx( mem_genSHBexc_filt_down_wb2, 0, 2*ALLPASSSECTIONS_STEEP+1 ); + set16_fx( mem_genSHBexc_filt_down_wb3, 0, 2*ALLPASSSECTIONS_STEEP+1 ); + + return; +} + + + +Word16 get_tbe_bits_fx( + Word32 bitrate, + Word16 bandwidth + ,Word16 rf_mode +) +{ + Word16 i, bits = 0; + + IF( EQ_16(rf_mode,1)) + { + /* TBE bits for core, primary frame */ + test(); + test(); + IF( (EQ_16(bandwidth, WB ))&&(EQ_32(bitrate,ACELP_13k20))) + { + /* Gain frame: 4, Gain shapes: 0, and LSFs: 2 */ + bits = NUM_BITS_SHB_FrameGain_LBR_WB + NUM_BITS_LBR_WB_LSF; + move16(); + } + ELSE IF( (EQ_16(bandwidth, SWB ))&&(EQ_32(bitrate,ACELP_13k20))) + { + /* Gain frame: 5, Gain shapes: 5, and lowrate LSFs: 8 */ + bits = NUM_BITS_SHB_FRAMEGAIN + NUM_BITS_SHB_SUBGAINS + 8; + move16(); + } + } + ELSE + { + test(); + test(); + IF( (EQ_16(bandwidth, WB ))&&(EQ_32(bitrate,ACELP_9k60))) + { + bits = NUM_BITS_LBR_WB_LSF + NUM_BITS_SHB_FrameGain_LBR_WB; + move16(); + } + ELSE IF( (EQ_16( bandwidth, SWB ))||(EQ_16(bandwidth,FB))) + { + test(); + IF( EQ_32(bitrate, ACELP_9k60)) + { + bits = NUM_BITS_SHB_FRAMEGAIN + NUM_BITS_SHB_SUBGAINS + 8; + move16(); + } + ELSE IF( (GE_32( bitrate, ACELP_13k20 ))&&(LE_32(bitrate,ACELP_32k))) + { + bits = NUM_BITS_SHB_SUBGAINS + NUM_BITS_SHB_FRAMEGAIN + NUM_LSF_GRID_BITS + MIRROR_POINT_BITS; + move16(); + + FOR ( i=0; iL_frame :length of the frame */ +/* _ (Word16[]) Aq : LP filter coefficients Q12 */ +/* _ (Word16) exc : input signal Q_exc */ +/* _ (Word16) update_m : update memory flag: 0-->no memory update */ +/* 1 --> update of memory */ +/* _ (Word16) Q_exc : Excitation scaling */ +/* _ (Word16) Q_syn : Synthesis scaling */ +/*---------------------------------------------------------------------------*/ +/* INPUT OUTPUT ARGUMENTS : */ +/*---------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) synth : initial filter states Q_syn */ +/*---------------------------------------------------------------------------*/ + +/* _ (Word16[]) st_fx->mem_syn2_fx: initial filter states Q_syn */ +/*---------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*===========================================================================*/ +void syn_12k8_fx( + Word16 L_frame, + const Word16 *Aq, /* i : LP filter coefficients Q12 */ + const Word16 *exc, /* i : input signal Q_exc */ + Word16 *synth, /* o : output signal Q_syn */ + Word16 *mem, /* i/o: initial filter states Q_syn */ + const Word16 update_m, /* i : update memory flag: 0 --> no memory update Q0 */ + /* 1 --> update of memory */ + const Word16 Q_exc, /* i : Excitation scaling Q0 */ + const Word16 Q_syn /* i : Synthesis scaling Q0 */ +) +{ + const Word16 *p_Aq; + Word16 i_subfr; + Word16 shift; + + shift = sub(Q_exc, Q_syn); + p_Aq = Aq; + move16(); + FOR (i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR) + { + Syn_filt_s(shift, p_Aq, M, &exc[i_subfr], &synth[i_subfr], L_SUBFR, mem, update_m); + p_Aq += (M+1); + move16(); /* interpolated LPC parameters for next subframe */ + } + return; +} diff --git a/lib_com/syn_filt_fx.c b/lib_com/syn_filt_fx.c new file mode 100644 index 0000000..05e1577 --- /dev/null +++ b/lib_com/syn_filt_fx.c @@ -0,0 +1,275 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "basop_util.h" +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" + +static Word32 syn_kern_2(Word32 L_tmp, const Word16 a[], const Word16 y[]) +{ + L_tmp = L_msu(L_tmp, y[-1], a[1]); + return L_msu(L_tmp, y[-2], a[2]); +} + +static Word32 syn_kern_4(Word32 L_tmp, const Word16 a[], const Word16 y[]) +{ + L_tmp = syn_kern_2(L_tmp, a, y); + return syn_kern_2(L_tmp, a+2, y-2); +} + +static Word32 syn_kern_6(Word32 L_tmp, const Word16 a[], const Word16 y[]) +{ + L_tmp = syn_kern_4(L_tmp, a, y); + return syn_kern_2(L_tmp, a+4, y-4); +} + +static Word32 syn_kern_8(Word32 L_tmp, const Word16 a[], const Word16 y[]) +{ + L_tmp = syn_kern_4(L_tmp, a, y); + return syn_kern_4(L_tmp, a+4, y-4); +} + +static Word32 syn_kern_10(Word32 L_tmp, const Word16 a[], const Word16 y[]) +{ + L_tmp = syn_kern_8(L_tmp, a, y); + return syn_kern_2(L_tmp, a+8, y-8); +} + +Word32 syn_kern_16(Word32 L_tmp, const Word16 a[], const Word16 y[]) +{ + L_tmp = syn_kern_8(L_tmp, a, y); + return syn_kern_8(L_tmp, a+8, y-8); +} + +static Word32 syn_kern_24(Word32 L_tmp, const Word16 a[], const Word16 y[]) +{ + L_tmp = syn_kern_16(L_tmp, a, y); + return syn_kern_8(L_tmp, a+16, y-16); +} + +/*------------------------------------------------------------------* + * Syn_filt_s_lc: + * + * perform the synthesis filtering 1/A(z). + * Optimized Version when No Memory, Past is Set to 0 + *------------------------------------------------------------------*/ +void syn_filt_s_lc_fx( + const Word16 shift, /* i : scaling to apply Q0 */ + const Word16 a[], /* i : LP filter coefficients Q12 */ + const Word16 x[], /* i : input signal Qx */ + Word16 y[], /* o : output signal Qx-s */ + const Word16 lg /* i : size of filtering Q0 */ +) +{ + Word16 i, j; + Word32 L_tmp; + Word16 a0; + Word16 q; + + + q = add( norm_s(a[0]), 1 ); + a0 = shr(a[0], shift); /* input / 2^shift */ + + /*-----------------------------------------------------------------------* + * Do the filtering + *-----------------------------------------------------------------------*/ + FOR (i = 0; i < M; i++) + { + L_tmp = L_mult(*x++, a0); + /* Stop at i to Avoid Mults with Zeros */ + FOR (j = 1; j <= i; j++) + { + L_tmp = L_msu(L_tmp, y[-j], a[j]); + } + + L_tmp = L_shl(L_tmp, q); + *y++ = round_fx(L_tmp); + } + + FOR (; i < lg; i++) + { + L_tmp = syn_kern_16(L_mult(*x++, a0), a, y); + L_tmp = L_shl(L_tmp, q); + *y++ = round_fx(L_tmp); + } +} + +/*------------------------------------------------------------------* + * Syn_filt_s: + * + * perform the synthesis filtering 1/A(z). + *------------------------------------------------------------------*/ +void Syn_filt_s( + const Word16 shift, /* i : scaling to apply Q0 */ + const Word16 a[], /* i : LP filter coefficients Q12 */ + const Word16 m, /* i : order of LP filter Q0 */ + const Word16 x[], /* i : input signal Qx */ + Word16 y[], /* o : output signal Qx-s */ + const Word16 lg, /* i : size of filtering Q0 */ + Word16 mem[], /* i/o: memory associated with this filtering. Qx-s */ + const Word16 update /* i : 0=no update, 1=update of memory. Q0 */ +) +{ + E_UTIL_synthesis(shift, a, x, y, lg, mem, update, m); +} + + +/* + * E_UTIL_synthesis + * + * Parameters: + * shift i : scaling to apply for a[0] Q0 + * a[] i : LP filter coefficients Qx + * x[] i : input signal Qx + * y[] o : output signal Qx-s + * lg i : size of filtering Q0 + * mem[] i/o: memory associated with this filtering. Qx-s + * update i : 0=no update, 1=update of memory. Q0 + * m i : order of LP filter Q0 + * + * Function: + * Perform the synthesis filtering 1/A(z). + * Memory size is always M. + * + * Returns: + * void + */ +void E_UTIL_synthesis(const Word16 shift, const Word16 a[], const Word16 x[], Word16 y[], + const Word16 lg, Word16 mem[], const Word16 update, const Word16 m + ) +{ + Word16 i, j, a0; + Word32 L_tmp; + Word16 q; + Word32 (*syn_kern)(Word32 L_tmp, const Word16 a[], const Word16 y[]) = NULL; + + if (EQ_16(m, 6)) + { + syn_kern = syn_kern_6; + } + if (EQ_16(m, 10)) + { + syn_kern = syn_kern_10; + } + if (EQ_16(m, 16)) + { + syn_kern = syn_kern_16; + } + if (EQ_16(m, 24)) + { + syn_kern = syn_kern_24; + } + assert(syn_kern != NULL); + q = add( norm_s(a[0]), 1 ); + + + + /*-----------------------------------------------------------------------* + * Set Memory Pointer at End for Backward Access + *-----------------------------------------------------------------------*/ + mem += m; /*move16();*/ + + a0 = shr(a[0], shift); /* input / 2^shift */ + + /*-----------------------------------------------------------------------* + * Do the filtering + *-----------------------------------------------------------------------*/ + /* Filtering Only from Input + Memory */ + L_tmp = syn_kern(L_mult(a0, *x++), a, mem); + L_tmp = L_shl(L_tmp, q); + *y++ = round_fx(L_tmp); + + /* Filtering from Input + Mix of Memory & Output Signal Past */ + FOR (i = 1; i < m; i++) + { + L_tmp = L_mult(a0, *x++); + /* Process Output Signal Past */ + FOR (j = 1; j <= i; j++) + { + L_tmp = L_msu(L_tmp, a[j], y[-j]); + } + /* Process Memory */ + FOR (; j <= m; j++) + { + L_tmp = L_msu(L_tmp, a[j], mem[i-j]); + } + L_tmp = L_shl(L_tmp, q); + *y++ = round_fx(L_tmp); + } + + /* Filtering from Input + Output Signal Past */ + FOR (; i < lg; i++) + { + L_tmp = syn_kern(L_mult(a0, *x++), a, y); + L_tmp = L_shl(L_tmp, q); + *y++ = round_fx(L_tmp); + } + + /*-----------------------------------------------------------------------* + * Update memory if required + *-----------------------------------------------------------------------*/ + IF (update != 0) + { + FOR (i = 0; i < m; i++) + { + *--mem = *--y; + move16(); + } + } + + return; +} + + + +/*-------------------------------------------------------------------* + * synth_mem_updt2() + * + * Update of synthesis filter memories in case of ACELP@12k8 <-> ACELP@16k switching + *--------------------------------------------------------------------*/ + +void synth_mem_updt2( + const Word16 L_frame, /* i : frame length */ + const Word16 last_L_frame, /* i : frame length */ + Word16 old_exc[], /* i/o: excitation buffer */ + Word16 mem_syn_r[], /* i/o: synthesis filter memory */ + Word16 mem_syn2[], /* o : synthesis filter memory for find_target */ + Word16 mem_syn[], /* o : synthesis filter memory for find_target */ + const Word16 dec /* i : flag for decoder indication */ +) +{ + Word16 mem_syn_r_size_old, mem_syn_r_size_new; + + /* Residual and update old_exc */ + IF( EQ_16(dec, DEC)) + { + lerp( old_exc+L_EXC_MEM_DEC-(last_L_frame+last_L_frame/2), old_exc+L_EXC_MEM_DEC-(L_frame+L_frame/2), L_frame+L_frame/2, last_L_frame+last_L_frame/2 ); + } + ELSE + { + lerp( old_exc+L_EXC_MEM-last_L_frame, old_exc+L_EXC_MEM-L_frame, L_frame, last_L_frame ); + } + + /*Resamp memory*/ + /*Size of LPC syn memory*/ + /* 1.25/20.0 = 1.0/16.0 -> shift 4 to the right. */ + mem_syn_r_size_old = shr(last_L_frame, 4); + mem_syn_r_size_new = shr(L_frame, 4); + + lerp( mem_syn_r + L_SYN_MEM - mem_syn_r_size_old, mem_syn_r + L_SYN_MEM - mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old ); + + Copy( mem_syn_r+L_SYN_MEM-M, mem_syn2, M ); + + IF( mem_syn != NULL ) + { + Copy( mem_syn2, mem_syn, M ); + } + +} + + diff --git a/lib_com/tcq_position_arith_fx.c b/lib_com/tcq_position_arith_fx.c new file mode 100644 index 0000000..48dc303 --- /dev/null +++ b/lib_com/tcq_position_arith_fx.c @@ -0,0 +1,2566 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include +#include "options.h" /* Compilation switches */ +#include "stl.h" + +#include "rom_com_fx.h" +#include "prot_fx.h" + +Word32 ar_div(Word32 num, Word32 denum) +{ + Word16 exp1, exp2, exp, i; + Word32 varout; + Word32 sign; + + sign = L_and(L_xor(num, denum), 0x80000000); + + num = L_abs(num); + denum = L_abs(denum); + + test(); + IF (LT_32(num, denum)||denum==0) + { + return 0; + } + ELSE IF (EQ_32(num, denum)) + { + return 1; + } + ELSE + { + exp1 = norm_l(num); + exp2 = norm_l(denum); + exp = sub(exp2, exp1); + denum = L_shl(denum, exp); + exp = add(exp, 1); + varout = L_deposit_l(0); + FOR (i = 0; i < exp; i++) + { + num = L_sub(num, denum); + varout = L_shl(varout, 1); + IF (num >= 0) + { + num = L_shl(num, 1); + varout = L_add(varout, 1); + } + ELSE + { + num = L_add(num, denum); + num = L_shl(num, 1); + } + } + } + + if(sign != 0) + { + varout = L_negate(varout); + } + + return varout; +} + +static void bitstream_save_bit(PBITSTREAM_FX pBS, Word32 bit) +{ + UWord8 cur; + + cur = pBS->buf[pBS->numByte]; + move16(); + + + cur = (UWord8)(cur | L_shl(bit,pBS->curPos)); + move16(); + pBS->curPos = sub(pBS->curPos,1); + pBS->buf[pBS->numByte] = cur; + move16(); + pBS->numbits = L_add(pBS->numbits, 1); + + IF (pBS->curPos < 0) + { + pBS->curPos = 7; + move16(); + pBS->numByte = L_add(pBS->numByte, 1); + } + + return; +} + +static UWord32 bitstream_load_bit(PBITSTREAM_FX pBS) +{ + UWord32 bit; + Word16 *curPos; + + /* safety check in case of bit errors */ + IF( GE_32(pBS->numByte, pBS->maxBytes)) + { + return 0; + } + + curPos = &pBS->curPos; + move16(); + bit = (( pBS->buf[pBS->numByte] >> (*curPos)--) & 0x00000001); + move16(); + move16(); + move16(); + + IF (*curPos < 0) + { + pBS->numByte = L_add(pBS->numByte, 1); + *curPos = 7; + move16(); + } + + return bit; +} + +static void bitstream_rollback(PBITSTREAM_FX pBS, Word32 numBits) +{ + + FOR ( ; numBits > 0; numBits--) + { + pBS->curPos++; + move16(); + pBS->numbits = L_sub(pBS->numbits, 1); + IF (EQ_16(pBS->curPos, 8)) + { + pBS->curPos = 0; + move16(); + pBS->numByte = L_sub(pBS->numByte, 1); + } + } + + return; +} +static void transmission_bits( PARCODEC_FX arInst, Word32 bit ) +{ + bitstream_save_bit( arInst->bsInst, bit ); + arInst->num_bits = L_add(arInst->num_bits, 1); + bit = !bit; + move32(); + + FOR ( ; arInst->bits_to_follow > 0 && arInst->num_bits < arInst->max_bits; arInst->bits_to_follow --) + { + bitstream_save_bit( arInst->bsInst, bit ); + arInst->num_bits = L_add(arInst->num_bits, 1); + } + + return; +} + +static Word32 ar_make_model_fx( const Word16 *freq, Word16 *model, Word16 len ) +{ + Word16 dist; + Word32 sum = 0; + Word32 cum = 0; + Word16 i, tmp; + + FOR ( i = 0 ; i < len ; i ++ ) + { + sum = L_add(sum, freq[i]); + } + + IF ( sum == 0 ) + { + return 0; + } + + FOR ( i = len ; i >= 0; i -- ) + { + /*model[i] = (short)( ( cum * MAX_AR_FREQ ) / sum ); */ + model[i] = extract_l(ar_div(cum * MAX_AR_FREQ, sum)); + + if (i) cum = L_add(cum, freq[i - 1]); + } + + tmp = sub(len, 1); + FOR ( i = 0 ; i < tmp ; i ++ ) + { + dist = sub(model[i], model[i + 1]); + + IF ( dist <= 0 ) + { + model[i + 1] = add(model[i + 1], sub(dist, 1)); + move16(); + } + } + + FOR ( i = len ; i > 0 ; i -- ) + { + dist = sub(model[i - 1], model[i]); + + IF ( dist <= 0 ) + { + model[i - 1] = sub(model[i - 1], sub(dist, 1)); + move16(); + } + } + + return (model[0] > model[1]); +} + +void ar_encoder_start_fx( PARCODEC_FX arInst, PBITSTREAM_FX bsInst, Word32 max_bits ) +{ + arInst->bsInst = bsInst; + move32(); + + arInst->low = L_deposit_l(0); + arInst->high = AR_TOP; + move32(); + arInst->bits_to_follow = 0; + move16(); + + arInst->num_bits = L_deposit_l(0); + arInst->max_bits = max_bits; + move32(); +} + +static void ar_encode_fx( PARCODEC_FX arInst, Word16 const *model, Word32 symbol ) +{ + Word32 range, high, low; + + high = L_add(arInst->high, 0); + low = L_add(arInst->low, 0); + + symbol = L_add(symbol, 1); + range = L_add(L_sub(high, low), 1); + + high = L_sub(L_add(low, ar_div(range * model[symbol - 1], model[0])), 1); + low = L_add(low, ar_div(range * model[symbol], model[0])); + + FOR( ; ; ) + { + IF ( LT_32(high, AR_HALF)) + { + transmission_bits( arInst, 0 ); + } + ELSE + { + IF (GE_32(low, AR_HALF)) + { + transmission_bits( arInst, 1 ); + + low = L_sub(low, AR_HALF); + high = L_sub(high, AR_HALF); + } + ELSE + { + test(); + IF (GE_32(low, AR_FIRST)&<_32(high,AR_THIRD)) + { + arInst->bits_to_follow ++; + move16(); + + low = L_sub(low, AR_FIRST); + high = L_sub(high, AR_FIRST); + } + ELSE + { + BREAK; + } + } + } + + low = L_shl(low, 1); + high = L_add(L_shl(high, 1 ), 1); + } + + arInst->high = high; + move32(); + arInst->low = low; + move32(); + + return; +} + +static void ar_encode_uniform_fx( PARCODEC_FX arInst, UWord32 data, Word32 bits ) +{ + Word32 i; + + FOR ( i = 0 ; i < bits ; i ++ ) + { + ar_encode_fx( arInst, uniform_model_fx, data & 0x1 ); + data = L_lshr(data, 1); + } + + return; +} + +void ar_encoder_done_fx( PARCODEC_FX arInst ) +{ + arInst->bits_to_follow ++; + move16(); + transmission_bits( arInst, arInst->low >= AR_FIRST ); + + return; +} + +void ar_decoder_start_fx( PARCODEC_FX arInst, PBITSTREAM_FX bsInst ) +{ + Word16 i; + + arInst->bsInst = bsInst; + move32(); + + arInst->low = L_deposit_l(0); + arInst->high = AR_TOP; + move32(); + arInst->value = L_deposit_l(0); + + FOR ( i = 0; i < AR_BITS ; i ++ ) + { + arInst->value = L_add(L_shl( arInst->value, 1), bitstream_load_bit( arInst->bsInst )); + } + + return; +} + +static Word16 ar_decode_fx( PARCODEC_FX arInst, Word16 const *model ) +{ + Word32 range, high, low, value, i; + Word16 cum; + Word16 symbol; + + high = L_add(arInst->high, 0); + low = L_add(arInst->low, 0); + value = L_add(arInst->value, 0); + + range = L_add(L_sub( high, low ), 1); + /*cum = (short)( ( ( (unsigned int)( arInst->value - arInst->low ) + 1 ) * model[0] - 1 ) / range ); */ + cum = extract_l(ar_div(L_sub(L_add(L_sub( value, low ), 1 ) * model[0], 1), range)); + + symbol = 1; + move16(); + WHILE ( GT_16(model[symbol], cum)) + { + symbol = add(symbol, 1); + } + + high = L_sub(L_add(low, ar_div(range * model[symbol - 1], model[0])), 1); + low = L_add(low, ar_div(range * model[symbol], model[0])); + + FOR (i = 0; i < 0x7FFF; i++) + { + Word32 L_msb_diff, L_msb_low, L_msb_high; + + L_msb_high = L_shr(high,14); + L_msb_low = L_shr(low,14); + L_msb_diff = L_sub(L_msb_high, L_msb_low); + IF (GE_32(L_msb_diff,2)) + { + BREAK; + } + assert (tab_ari_qnew[L_msb_high][L_msb_low] != 0x0CCC); + assert (tab_ari_qnew[L_msb_high][L_msb_low] != 0x0BBB); + low = L_msu(low,1,tab_ari_qnew[L_msb_high][L_msb_low]); + low = L_shl(low,1); + high = L_msu(high,1,tab_ari_qnew[L_msb_high][L_msb_low]); + high = L_add(L_shl(high, 1), 1); + value = L_msu(value,1,tab_ari_qnew[L_msb_high][L_msb_low]); + value = L_add(L_shl(value, 1), bitstream_load_bit( arInst->bsInst )); + } + + arInst->low = low; + move32(); + arInst->high = high; + move32(); + arInst->value = value; + move32(); + + return (symbol - 1); +} + +void ar_decoder_done_fx( PARCODEC_FX arInst ) +{ + bitstream_rollback( arInst->bsInst, AR_BITS - 2 ); + + return; +} + +static Word16 quantize_fx( Word16 val, Word16 D) +{ + Word16 qval4_fx; + Word16 retval_fx; + + val = s_min(val, 32255); /* limit input by (2^15 - 1)-2^9 */ + qval4_fx = shr(abs_s(add(val, 512)), 12); + retval_fx = add(shl(qval4_fx, 2), DDP_fx[D]); + /* 2nd zero check */ + IF (D == 0) + { + if (GT_16(abs_s(sub(shl(abs_s(retval_fx), 10), abs_s(val))), abs_s(val))) + { + retval_fx = 0; + move16(); + } + } + /*return retval; */ + return retval_fx; +} + +static Word32 GetBitsFromPulses_fx(Word16 m, Word16 n) +{ + Word16 i, tmp, integer_fx, temp_fx1, temp_fx2, exp1, exp2; + Word32 temp32; + Word32 frac_fx32; + Word32 logCoeff_fx; + Word16 exp = 0; + Word32 mantissa_fx = 0; + move16(); + move32(); + + IF (m == 0) + { + return 0; + } + + tmp = s_min(m, n); + FOR (i = 0; i < tmp; i++) + { + logCoeff_fx = L_add(L_shl(i + 1, 16), L_sub(table_logcum_fx[n+1], L_add(table_logcum_fx[i + 2], table_logcum_fx[n - i]))); + logCoeff_fx = L_add(logCoeff_fx, L_sub(table_logcum_fx[m], L_add(table_logcum_fx[i + 1], table_logcum_fx[m - i])));/*Q16 */ + integer_fx = extract_h(logCoeff_fx);/*Q0 */ + frac_fx32 = L_sub(logCoeff_fx, L_shl(integer_fx, 16));/*Q16 */ + + /*ln2, 0.987, ln2 * ln2, 0.977 */ + /*temp1 = (int) (frac / 0.0625); */ + /*temp2 = frac - (float)temp1 * 0.0625f; */ + + /* frac = pow(2.0, temp1 * 0.0625) * (1 + 0.693 * temp2 + 0.480 * temp2 * temp2 * 0.5);*/ + /*frac = pow_getbitsfrompulses[temp1] * (1 + 0.693f * temp2 + 0.480f * temp2 * temp2 * 0.5f); */ + + temp_fx1 = extract_h(L_shl(frac_fx32, 4)); + temp_fx2 = extract_l(L_and(frac_fx32, 0xfff));/*Q16 */ + + frac_fx32 =L_mac(Mult_32_16(L_mult0(temp_fx2, temp_fx2), 7864), temp_fx2, 22708);/*Q32 */ + frac_fx32 = L_add(0x40000000, L_shr(frac_fx32, 2));/*30 */ + + exp1 = norm_l(pow_getbitsfrompulses_fx[temp_fx1]); + exp2 = norm_l(frac_fx32); + frac_fx32 = Mult_32_32(L_shl(pow_getbitsfrompulses_fx[temp_fx1], exp1), L_shl(frac_fx32, exp2));/*21 + exp1 + 30 + exp2 - 31 */ + frac_fx32 = L_shr(frac_fx32, exp1 + exp2) + 1;/*20 */ + + IF (LT_16(exp, integer_fx)) + { + mantissa_fx = L_shr(mantissa_fx, sub(integer_fx, exp)); + mantissa_fx = L_add(mantissa_fx, frac_fx32); + + exp = integer_fx; + move16(); + } + ELSE + { + mantissa_fx = L_add(mantissa_fx, L_shr(frac_fx32, sub(exp, integer_fx))); + } + IF (GE_32(mantissa_fx, 0x200000)) + { + exp++; + move16(); + + mantissa_fx = L_shr(mantissa_fx, 1); + } + } + + mantissa_fx = L_shl(mantissa_fx, 2);/*22 */ + temp_fx1 = extract_h(mantissa_fx); + /*temp_fx2 = extract_h(L_shl(L_sub(mantissa_fx, L_deposit_h(temp_fx1)), 15)); // 15 */ + temp32 = L_shl(L_sub(mantissa_fx, L_deposit_h(temp_fx1)), 15);/*31 */ + exp1 = sub(norm_l(temp32), 1); + temp32 = ar_div(L_shl(temp32, exp1), temp_fx1); /*31 + exp1 */ + temp32 = L_shr(temp32, exp1 + 1);/*30 */ + + frac_fx32 = L_sub(0x40000000, L_shr(temp32, 1));/*30 */ + frac_fx32 = Mult_32_32(frac_fx32, temp32);/*29 */ + frac_fx32 = L_shr(frac_fx32, 13);/*16 */ + exp1 = norm_l(temp_fx1); + temp_fx1 = Log2_norm_lc(L_shl(temp_fx1, exp1));/*15 */ + frac_fx32 = frac_fx32 + Mult_32_32(frac_fx32, 950680361); /* frac_fx32 *= 1/ln(2) */ + return L_add(L_deposit_h(exp), L_add(L_shl(temp_fx1, 1), frac_fx32)); + /*return exp + (float)temp_fx1 / pow(2.0, 15) + (float)frac_fx32 / pow(2.0, 16); */ +} + +static +void TCQnew_fx( Word32 *v_fx, Word32 scale_fx, Word16 Qscale, + Word16 length, Word16 *vout_fx, Word16 pulses, Word16 *pulsesout, Word16* nzposout, Word32 *savedstates, Word32 * lasttrellislevel, Word32 terminate) +{ + Word16 i, st, dminpos, position; + Word16 pulsesnum, nzpos = 0; + + Word32 metric_fx[STATES][TCQ_MAX_BAND_SIZE]; + Word16 path_fx[STATES][TCQ_MAX_BAND_SIZE]; + Word16 quant_fx[STATES][TCQ_MAX_BAND_SIZE]; + Word16 pused_fx[STATES][TCQ_MAX_BAND_SIZE]; + Word16 quantum1_fx, quantum2_fx, newdist1_fx, newdist2_fx/*, signq_fx*/; + Word32 /*scale_fx, */tmp32, dmin_fx, curdist1_fx, curdist2_fx; + Word16 value_fx, exp; + Word16 exp1, exp2; + + set32_fx(*metric_fx, 0, STATES * TCQ_MAX_BAND_SIZE); + set16_fx( *path_fx, 0, STATES*TCQ_MAX_BAND_SIZE ); + set16_fx( *quant_fx, 0, STATES*TCQ_MAX_BAND_SIZE ); + set16_fx( *pused_fx, 0, STATES*TCQ_MAX_BAND_SIZE ); + + /* Initialize metric */ + FOR ( st = 1; st < STATES; st++) + { + metric_fx[st][0] = MAX_32>>1; + move32(); + } + FOR ( st = 2; st < STATES; st++) + { + metric_fx[st][1] = MAX_32>>1; + move32(); + } + FOR ( st = 4; st < STATES; st++) + { + metric_fx[st][2] = MAX_32>>1; + move32(); + } + /* Viterbi for input sequence */ + FOR ( i = 0; i < length; i++) /* cycle over symbols */ + { + FOR ( st = 0; st < STATES; st++) /* cycle over conditions */ + { + curdist1_fx = L_add(metric_fx[ step_tcq_fx[st][0]][i], 0); + curdist2_fx = L_add(metric_fx[ step_tcq_fx[st][1]][i], 0); + + exp = norm_l(scale_fx); + tmp32 = L_shl(scale_fx, exp); + tmp32 = Mult_32_16(v_fx[i], extract_h(tmp32));/*12 + 20 + exp - 16 - 15 + Qscale */ + exp1 = 26-(exp-19+Qscale); + exp2 = norm_l(tmp32); + IF( GE_16(exp2, exp1)) + { + value_fx = extract_h(L_shl(tmp32, sub(26, add(sub(exp, 19), Qscale))));/*exp -19 + Qscale*/ /*10*/ + } + ELSE + { + value_fx = extract_h(L_shl(tmp32, exp2));/*exp -19 + Qscale*/ /*10*/ + } + /* step 1 */ + quantum1_fx = quantize_fx(value_fx, denc_fx[st][0]); + newdist1_fx = sub(shl(quantum1_fx, 10), abs_s(value_fx));/*10*/ + newdist1_fx = mult(newdist1_fx, newdist1_fx); /* 5 */ + + test(); + if (GT_16(add(quantum1_fx , pused_fx[step_tcq_fx[st][0]][i]), pulses)&&terminate) + { + newdist1_fx = MAX_16; + move16(); + } + /* step 2 */ + quantum2_fx = quantize_fx(value_fx, denc_fx[st][1]); + newdist2_fx = sub(shl(quantum2_fx, 10), abs_s(value_fx));/*10*/ + newdist2_fx = mult(newdist2_fx, newdist2_fx);/*5*/ + + test(); + if (GT_16(add(quantum2_fx , pused_fx[step_tcq_fx[st][1]][i]), pulses)&&terminate) + { + newdist2_fx = MAX_16; + move16(); + } + + /* decision */ + IF (LT_32(L_add(curdist1_fx, newdist1_fx), L_add(curdist2_fx, newdist2_fx))) + { + path_fx[st][i+1] = step_tcq_fx[st][0]; + move16(); + metric_fx[st][i+1] = L_add(curdist1_fx, newdist1_fx); + move32(); + quant_fx[st][i+1] = quantize_fx(value_fx, denc_fx[st][0]); + move16(); + pused_fx[st][i+1] = add(pused_fx[ step_tcq_fx[st][0]][i], abs_s( quant_fx[st][i+1] )); + move16(); + } + ELSE + { + path_fx[st][i+1] = step_tcq_fx[st][1]; + move16(); + metric_fx[st][i+1] = L_add(curdist2_fx, newdist2_fx); + move32(); + quant_fx[st][i+1] = quantize_fx(value_fx, denc_fx[st][1]); + move16(); + pused_fx[st][i+1] = add(pused_fx[ step_tcq_fx[st][1]][i], abs_s( quant_fx[st][i+1] )); + move16(); + } + } + } + + /* Find path with minimal metric */ + dminpos = 0; + move16(); + dmin_fx = L_add(metric_fx[dminpos][ length], 0); + FOR ( i = 1; i < STATES; i++) + { + test(); + test(); + test(); + IF ( (GT_32(dmin_fx, metric_fx[ i][ length])&&EQ_16(pused_fx[i][length],pulses))|| + (NE_16(pused_fx[dminpos][ length], pulses) && EQ_16(pused_fx[i][ length], pulses)) ) + { + dmin_fx = L_add(metric_fx[ i][ length], 0); + dminpos = i; + move16(); + } + } + /* Trace back to get output */ + nzpos = 0; + move16(); + pulsesnum = 0; + move16(); + position = dminpos; + move16(); + FOR ( i = length; i > 0; i--) + { + vout_fx[i-1] = quant_fx[position][i]; + move16(); + if (v_fx[i-1] <= 0) + { + vout_fx[i-1] = - quant_fx[position][i]; + move16(); + } + position = path_fx[position][i]; + move16(); + savedstates[i-1] = position; + move32(); + + /* calculate output pulses number & nz */ + pulsesnum = add(pulsesnum, abs_s(vout_fx[i-1]));/*quant[position][i]; */ + IF ( abs_s(vout_fx[i-1]) > 0 ) + { + if ( nzpos == 0 ) + { + *lasttrellislevel = i; + move32(); + } + + nzpos = add(nzpos, 1); + } + } + + if ( pulsesout != 0 ) + { + *pulsesout = pulsesnum; + move16(); + } + if ( nzposout != 0 ) + { + *nzposout = nzpos; + move16(); + } + + return; +} + +Word32 GetISCScale_fx( Word32 *quants_fx, Word16 size, Word32 bits_fx, Word16 *magn_fx, Word32 *qscale_fx, Word32 *surplus_fx, Word16 *pulses, Word32* savedstates, Word32 noTCQ, + Word16 *nzpout, Word16 *bcount, Word32 *abuffer, Word16 *mbuffer, Word32 *sbuffer) +{ + Word32 pos, terminate, trellislevel, st; + Word32 lasttrellislevel; + Word16 i, j, m_int, leftp, leftnz, nzpos, direction, pulsesnum, diff, pulsescurr, nzposcurr; + Word16 sign; + Word16 flag_g1; + Word32 t32; + Word16 SafeExp; + + Word32 magnbits_fx = 0, tcqmagnbits_fx/*, surplus_fx, bits_fx*/; + Word16 prob0_fx, prob1_fx, num, denum, quantum1_fx, quantum2_fx; + Word32 dmin_fx, scale_fx32; + Word32 actualt_fx; + Word32 pt_fx, sxy_fx = 0, sy2_fx = 0; + Word16 pn_fx, g_fx, scale_fx; + Word16 tmp16, exp, exp1, exp2, Q_temp, hi, lo; + Word32 m_fx, tmp32; + Word32 /*quants_fx[TCQ_MAX_BAND_SIZE], */aquants_fx[TCQ_MAX_BAND_SIZE], dist_fx[TCQ_MAX_BAND_SIZE]; + Word16 exp_dist[TCQ_MAX_BAND_SIZE]; + Word16 /*magn_fx[TCQ_MAX_BAND_SIZE], */t_fx; + Word16 Qscale; + Word16 Qsxy=4; + + exp = 0; /* to avoid compilation warnings */ + Qscale = 0; /* to avoid compilation warnings */ + + set32_fx( dist_fx, 0, size ); + set16_fx(exp_dist, 31, size ); + set32_fx( aquants_fx, 0, size ); + + IF( bits_fx < 0 ) + { + pulsesnum = 0; + move16(); + + IF( surplus_fx != 0 ) + { + /* *surplus_fx += bits_fx; */ + *surplus_fx = L_add(*surplus_fx, bits_fx); + move32(); + } + } + ELSE + { + pulsesnum = GetScale_fx(size, bits_fx, surplus_fx); + } + *nzpout = 0; + move16(); + + if ( pulses != 0 ) + { + *pulses = pulsesnum; + move16(); + } + + IF ( pulsesnum > 0 ) + { + /* Initial quantization */ + m_fx = L_deposit_l(0); + FOR (i = 0; i < size; i++) + { + aquants_fx[i] = L_abs(quants_fx[i]);/*Q12 */ move32(); + m_fx = L_add(m_fx, L_shr( aquants_fx[i], 2) );/*Q12 - 2*/ + } + + IF (m_fx == 0) + { + scale_fx = 0; + move16(); + FOR (i = 0; i < size; i++) + { + magn_fx[i] = 0; + move16(); + } + t_fx = 0; + move16(); + } + ELSE + { + exp1 = sub(norm_s(pulsesnum), 1); + exp2 = norm_l(m_fx); + scale_fx = div_s(shl(pulsesnum, exp1), extract_h(L_shl(m_fx, exp2)));/*15 + exp1 - (exp2 + 12 - 16) */ + + exp = 15 + exp1 - (exp2 + 12 - 16) + 2; + move16(); + t_fx = 0; + move16(); + FOR (i = 0; i < size; i++) + { + tmp32 = Mult_32_16(aquants_fx[i], scale_fx);/*12 + exp - 15 */ + tmp32 = L_shl(tmp32, sub(16, 12 + exp - 15));/*16 */ + magn_fx[i] = extract_h(L_add(32768, tmp32)); + t_fx = add(t_fx, magn_fx[i]); + } + } + + /* Pulses redistribution */ + WHILE (NE_16(t_fx, pulsesnum)) + { + pn_fx = 0; + move16(); + pt_fx = L_deposit_l(0); + + nzpos = 0; + move16(); + FOR (i = 0; i < size; i++) + { + IF (magn_fx[i] > 0) + { + pn_fx = add(pn_fx, magn_fx[i]);/*0 */ + pt_fx = L_add(pt_fx, L_shr( aquants_fx[i], 2) );/*12 */ + } + } + + direction = -1; + move16(); + if ( GT_16(pulsesnum, t_fx)) + { + direction = 1; + move16(); + } + + /* new alg */ + { + FOR ( i = 0; i < size; i++) + { + sxy_fx = L_add(sxy_fx, L_shl(Mult_32_16(aquants_fx[i], magn_fx[i]), Qsxy+3)); /* 12+0-15 +9 -> 6 */ + sy2_fx = L_add(sy2_fx, L_mult0(magn_fx[i], magn_fx[i]));/*0 */ + } + Q_temp = 32; + move16(); + FOR ( i = 0; i < size; i++) + { + IF (magn_fx[i] > 0) + { + tmp16 = add(pn_fx, direction); + tmp32 = L_add(pt_fx, 0); + } + ELSE + { + tmp16 = add(pn_fx, direction); + tmp32 = L_add(pt_fx, L_shr( aquants_fx[i], 2) ); + } + + IF (tmp32 == 0) + { + g_fx = 0; + move16(); + } + ELSE + { + exp1 = sub(norm_l(tmp32), 1); + exp2 = norm_s(tmp16); + tmp32 = L_shl(tmp32, exp1); + IF (tmp16 == 0) + { + tmp16 = 1; + move16(); + exp2 = 16; + move16(); + } + ELSE + { + tmp16 = shl(tmp16, exp2); + } + g_fx = div_s(extract_h(tmp32), tmp16);/*15 + 12 + exp1 - 16 - exp2; */ + exp = 15 + 12 + exp1 - 16 - exp2 - 2; + move16(); + } + + IF (g_fx == 0) + { + dist_fx[i] = L_deposit_l(0); + } + ELSE + { + IF (direction > 0) + { + tmp32 = L_add(sxy_fx, L_shr(aquants_fx[i], 12-Qsxy));/*Qsxy */ + t32 = L_add( sy2_fx, L_add( 1, L_deposit_l( shl(magn_fx[i], 1) ) ) ); + + IF( LT_16(norm_l(t32), 15)) + { + SafeExp = sub(16, norm_l(t32)); + tmp16 = extract_l( L_shr( t32, SafeExp) ); + } + ELSE + { + SafeExp = 0; + move16(); + tmp16 = extract_l( t32 ); + } + } + ELSE + { + tmp32 = L_sub(sxy_fx, L_shr(aquants_fx[i], 12-Qsxy));/*Qsxy */ + t32 = L_add( sy2_fx, L_sub( 1, L_deposit_l( shl(magn_fx[i], 1) ) ) ); + SafeExp = norm_l(t32); + + IF( LE_16(norm_l(t32), 15)) + { + SafeExp = sub(16, norm_l(t32)); + tmp16 = extract_l( L_shr( t32, SafeExp) ); + } + ELSE + { + SafeExp = 0; + move16(); + tmp16 = extract_l( t32 ); + } + } + tmp32 = L_shl(tmp32, 1-SafeExp); /* *2 */ + tmp32 = L_sub(L_shl(L_mult0(g_fx, tmp16), sub(Qsxy, exp)), tmp32);/*Qsxy */ + dist_fx[i] = Mult_32_16(tmp32, g_fx);/*Qsxy + exp - 15 */ move32(); + exp_dist[i] = add(Qsxy-15, exp); + move16(); + if (LT_16(exp_dist[i], Q_temp)) + { + Q_temp = exp_dist[i]; + move16(); + } + } + + } + FOR (i = 0; i < size; i++) + { + dist_fx[i] = L_shr(dist_fx[i], s_min(sub(exp_dist[i], Q_temp), 31)); + move32(); + } + } + + { + /* find min */ + pos = L_deposit_l(0); + dmin_fx = L_add(dist_fx[0], 0); + FOR (i = 1; i < size; i++) + { + IF (GT_32(dmin_fx, dist_fx[i])) + { + pos = L_deposit_l(i); + dmin_fx = L_add(dist_fx[i], 0); + } + } + /*IF (magn_fx[i] == 0 && direction < 0) */ + test(); + IF (magn_fx[pos] == 0 && direction < 0) + { + pos = L_deposit_l(0); + FOR (i = 0; i < size; i++) + { + IF (magn_fx[i] != 0) + { + pos = L_deposit_l(i); + BREAK; + } + } + dmin_fx = L_add(dist_fx[i], 0); + FOR (; i < size; i++) + { + test(); + IF (magn_fx[i] != 0 && LT_32(dmin_fx, dist_fx[i])) + { + pos = L_deposit_l(i); + dmin_fx = L_add(dist_fx[i], 0); + } + } + } + + magn_fx[pos] = add(magn_fx[pos], direction); + move16(); + t_fx = add(t_fx, direction); + } + } + + /* calculate actual nz positions */ + actualt_fx = L_deposit_l(0); + nzpos = 0; + move16(); + FOR (i = 0; i < size; i++) + { + IF (magn_fx[i] > 0) + { + if (quants_fx[i] < 0) + { + magn_fx[i] = negate(magn_fx[i]); + move16(); + } + actualt_fx = L_add(actualt_fx, L_shr( aquants_fx[i], 2) );/*12 */ + nzpos++; + } + /*magn[i] = (float)magn_fx[i]; */ + } + + /* calculate scale */ + IF (actualt_fx == 0) + { + scale_fx32 = L_add(MAX_32, 0); + } + ELSE + { + exp1 = norm_l(actualt_fx); + exp2 = sub(norm_l(pulsesnum), 1); + lo = L_Extract_lc(L_shl(actualt_fx, exp1), &hi); + scale_fx32 = Div_32(L_shl(pulsesnum, exp2), hi, lo);/*31 + exp2 - exp1 - 12 */ + Qscale = 31 + exp2 - exp1 - 12 + 2; + move16(); + } + + *qscale_fx = scale_fx32; + move32(); + *nzpout = nzpos; + move16(); + + + test(); + test(); + IF ( (NE_16(nzpos, pulsesnum)&>_16(nzpos,1))&&noTCQ==0) + { + terminate = L_deposit_l(1); + /*TCQnew( quants, scale, size, magn, pulsesnum, &pulsescurr, &nzposcurr, savedstates, &lasttrellislevel, terminate); */ + TCQnew_fx(quants_fx, scale_fx32, Qscale, + size, magn_fx, pulsesnum, &pulsescurr, &nzposcurr, savedstates, &lasttrellislevel, terminate); + IF (GT_16(pulsesnum, pulsescurr)) + { + Word32 L_tmp; + IF( GT_32( 1952247030, scale_fx32)) + { + scale_fx32 = L_add(scale_fx32, Mult_32_16(scale_fx32, 3277)); + } + ELSE + { + L_tmp = L_shr(scale_fx32, 1); + scale_fx32 = L_add(L_tmp, Mult_32_16(L_tmp, 3277)); + Qscale = sub(Qscale, 1); + } + } + + if(LT_16(pulsesnum, pulsescurr)) + { + scale_fx32 = Mult_32_16(scale_fx32, 29491); + } + IF (GT_16(pulsesnum, pulsescurr)) + { + diff = sub(pulsesnum, pulsescurr); + + FOR ( i = size-1; i >=0; i--) + { + IF ( abs_s(magn_fx[i]) > 0 ) + { + sign = -1; + move16(); + if( magn_fx[i] > 0 ) + { + sign = 1; + move16(); + } + /*magn_fx[i] = sign * abs_s(add(magn_fx[i], diff)); move32(); */ + IF (sign > 0) + { + magn_fx[i] = abs_s(add(magn_fx[i], diff)); + move16(); + } + ELSE + { + magn_fx[i] = -abs_s(add(magn_fx[i], diff)); + move16(); + } + + BREAK; + } + } + } + ELSE IF(LT_16(pulsesnum, pulsescurr)) + { + diff = sub(pulsescurr, pulsesnum); + + FOR ( i = size-1; i >=0; i--) + { + IF (diff <= 0) + { + BREAK; + } + + IF ( abs_s(magn_fx[i]) > 0 ) + { + sign = -1; + move16(); + if( magn_fx[i] > 0 ) + { + sign = 1; + move16(); + } + m_int = abs_s(magn_fx[i]); + + IF (LT_16(diff, m_int)) + { + /*magn_fx[i] = sign * sub(abs_s(magn_fx[i]), diff); move16(); */ + IF (sign > 0) + { + magn_fx[i] = sub(abs_s(magn_fx[i]), diff); + move16(); + } + ELSE + { + magn_fx[i] = - sub(abs_s(magn_fx[i]), diff); + move16(); + } + BREAK; + } + ELSE + { + diff = sub(diff, m_int); + magn_fx[i] = 0; + move16(); + nzposcurr = sub(nzposcurr, 1); + } + } + } + } + + pulsescurr = pulsesnum; + move16(); + + /* Magnitudes coding */ + { + leftp = pulsescurr; + move16();/*pulsesnum; */ + leftnz = nzposcurr; + move16(); /*nzpos; */ + trellislevel = L_deposit_l(0); + + FOR ( i = 0; i < size; i++) + { + IF (LE_16(leftnz, 1)) + { + BREAK; + } + + IF ( magn_fx[i] != 0 ) + { + FOR ( j = 0; j < leftp; j++) + { + num = sub(leftnz, 1); + denum = sub(leftp, add(j, 1)); + IF (GE_16(num, denum)) + { + prob1_fx = MAX_16; + move16(); + prob0_fx = 0; + move16(); + } + ELSE + { + exp1 = sub(norm_s(num), 1); + exp2 = norm_s(denum); + prob1_fx = div_s(shl(num, exp1), shl(denum, exp2));/*15 + exp1 - exp2 */ + exp = 15 + exp1 - exp2; + move16(); + prob1_fx = shl(prob1_fx, sub(15, exp)); + prob0_fx = sub(MAX_16, prob1_fx); + } + + st = L_add(savedstates[ trellislevel ], 0); + quantum1_fx = quantize_fx(shl(add(j, 1), 10), ddec_fx[st][0]); + quantum2_fx = quantize_fx(shl(add(j, 1), 10), ddec_fx[st][1]); + + test(); + IF(NE_16(quantum1_fx, add(j, 1))&&NE_16(quantum2_fx,add(j,1))) + { + /* this magnitude is not possible so set probabilities */ + prob0_fx = MAX_16; + move16(); + prob1_fx = 0; + move16(); + } + + IF (LT_16(j, sub(abs_s(magn_fx[i]), 1))) + { + exp1 = norm_s(prob0_fx); + tmp32 = L_deposit_h(shl(prob0_fx, exp1));/*exp1 + 15 + 16 */ + tmp16 = Log2_norm_lc(tmp32);/*15 */ + magnbits_fx = L_sub(magnbits_fx, L_sub(tmp16, L_shl(add(exp1, 1), 15)));/*15 */ + } + ELSE + { + exp1 = norm_s(prob1_fx); + tmp32 = L_deposit_h(shl(prob1_fx, exp1));/*exp1 + 15 + 16 */ + tmp16 = Log2_norm_lc(tmp32);/*15 */ + magnbits_fx = L_sub(magnbits_fx, L_sub(tmp16, L_shl(add(exp1, 1), 15)));/*15 */ + BREAK; + } + } + + leftnz--; + move16(); + leftp = sub(leftp, abs_s(magn_fx[i])); + } + + trellislevel = L_add(trellislevel, 1); + } + + /* Update actual occurred surplus */ + tcqmagnbits_fx = L_sub(L_sub(table_logcum_fx[pulsescurr], table_logcum_fx[nzposcurr]), table_logcum_fx[pulsescurr - (nzposcurr - 1)]); + *surplus_fx = L_add(*surplus_fx, L_sub(tcqmagnbits_fx, L_shl(magnbits_fx, 1))); + + *nzpout = nzposcurr; + move16(); + }/*magnitude coding */ + }/*TCQ */ + + IF (actualt_fx == 0) + { + scale_fx32 = L_add(MAX_32, 0); + } + ELSE + { + exp1 = norm_l(actualt_fx); + exp2 = sub(norm_l(pulsesnum), 1); + lo = L_Extract_lc(L_shl(actualt_fx, exp1), &hi); + scale_fx32 = Div_32(L_shl(pulsesnum, exp2), hi, lo);/*31 + exp2 - exp1 - 12 */ + Qscale = 31 + exp2 - exp1 - 12; + move16(); + } + test(); + IF ( *nzpout > 1 && bcount != 0 ) + { + flag_g1 = 0; + move16(); + + FOR ( i = 0; i < size; i++) + { + if( abs_s(magn_fx[i]) > 1 ) + { + flag_g1 = 1; + move16(); + } + } + /* prepare vector for TCQ */ + FOR ( i = 0; i < size; i++) + { + test(); + IF (flag_g1 == 0 || GE_16(*bcount, 2*TCQ_AMP)) + { + BREAK; + } + + IF ( abs_s(magn_fx[i]) > 0 ) + { + abuffer[*bcount] = quants_fx[i]; + move32(); + mbuffer[*bcount] = magn_fx[i]; + move16(); + /*sbuffer[*bcount] = scale_fx32;*/ + exp = norm_s(pulsesnum); + tmp16 = div_l( actualt_fx, shl( pulsesnum, exp-1) ); + tmp32 = L_shl( L_deposit_l(tmp16), exp); + /*sbuffer[*bcount] = 1/((float)tmp32/pow(2.0, 12));*/ + sbuffer[*bcount] = tmp32;/*Q12*/ move32(); + /*sbuffer[*bcount] = (float)scale_fx32 / pow(2.0, Qscale);*/ + + (*bcount)++; + + } + } + } + *qscale_fx = scale_fx32; + move32(); + } + + return L_shl(magnbits_fx, 1); +} + +void TCQLSB_fx(Word16 bcount, Word32 *abuffer_fx, Word16 *mbuffer_fx, Word32 *sbuffer_fx, Word16 *dpath) +{ + Word16 i, st, dminpos, position; + Word16 q_fx = 6554;/*Q15*/ + Word32 dmin_fx, curdist1_fx, curdist2_fx, newdist1_fx, newdist2_fx; + Word16 path[STATES_LSB][TCQ_LSB_SIZE]; + Word16 quant[STATES_LSB][TCQ_LSB_SIZE]; + Word16 dquant[STATES_LSB][TCQ_LSB_SIZE]; + Word16 qout[TCQ_LSB_SIZE]; + Word32 s1_fx, s2_fx, a1_fx, a2_fx; + Word16 s1_fx16, s2_fx16; + Word16 q1_fx, q2_fx, sign1_fx, sign2_fx; + Word16 dbuffer_fx[MAX_PULSES]; + + Word32 tmp1, tmp2; + Word16 exp1, exp2; + Word32 metric_fx[STATES_LSB][TCQ_LSB_SIZE]; + Word32 MaxPath; + + set32_fx(*metric_fx, 0, STATES_LSB*TCQ_LSB_SIZE); + set16_fx( *path, 0, STATES_LSB*TCQ_LSB_SIZE ); + set16_fx( *quant, 0, STATES_LSB*TCQ_LSB_SIZE ); + set16_fx( *dquant, 0, STATES_LSB*TCQ_LSB_SIZE ); + set16_fx( qout, 0, TCQ_LSB_SIZE ); + + metric_fx[1][0] = MAX_32>>8; + move32(); + metric_fx[2][0] = MAX_32>>8; + move32(); + metric_fx[3][0] = MAX_32>>8; + move32(); + + FOR( i = 0; i < 2*TCQ_AMP; i+=2 ) + { + q1_fx = mbuffer_fx[i]; + move16(); + q2_fx = mbuffer_fx[i + 1]; + move16(); + + s1_fx= L_add(sbuffer_fx[i], 0); /*12*/ + s2_fx = L_add(sbuffer_fx[i + 1], 0); /*12*/ + exp1 = norm_l(s1_fx); + exp2 = norm_l(s2_fx); + s1_fx16 = extract_h(L_shl(s1_fx, exp1));/*12 + exp1 - 16*/ + s2_fx16 = extract_h(L_shl(s2_fx, exp2));/*12 + exp2 - 16*/ + exp1 = 12 + exp1 - 16; + move16(); + exp2 = 12 + exp2 - 16; + move16(); + + a1_fx = L_add(abuffer_fx[i], 0); + a2_fx = L_add(abuffer_fx[i + 1], 0); + + MaxPath = L_add(MAX_32, 0); + + /* cycle over conditions */ + FOR ( st = 0; st < 4; st++) + { + curdist1_fx = L_add(metric_fx[ step_LSB_fx[st][0] ][i/2], 0); + curdist2_fx = L_add(metric_fx[ step_LSB_fx[st][1] ][i/2], 0); + + /* step 1 */ + /*sign1_fx = (denc_LSB[st][0] & 0x1)?(q_fx):(-q_fx);*/ + IF (s_and(denc_LSB_fx[st][0], 0x1)) + { + sign1_fx = q_fx; + move16(); + } + ELSE + { + sign1_fx = negate(q_fx); + } + /*sign2_fx = (denc_LSB[st][0] & 0x2)?(q_fx):(-q_fx);*/ + IF (s_and(denc_LSB_fx[st][0], 0x2)) + { + sign2_fx = q_fx; + move16(); + } + ELSE + { + sign2_fx = negate(q_fx); + } + tmp1 = L_sub(a1_fx, L_shl(Mult_32_16(L_add(L_shl(q1_fx, 15), sign1_fx), s1_fx16), sub(12+2, exp1)));/*12*/ + tmp2 = L_sub(a2_fx, L_shl(Mult_32_16(L_add(L_shl(q2_fx, 15), sign2_fx), s2_fx16), sub(12+2, exp2)));/*12*/ + newdist1_fx = L_add(Mult_32_32(tmp1, tmp1), Mult_32_32(tmp2, tmp2)); /* -7 */ + + /* step 2 */ + /*sign1_fx = (denc_LSB[st][1] & 0x1)?(q_fx):(-q_fx);*/ + IF (s_and(denc_LSB_fx[st][1], 0x1)) + { + sign1_fx = q_fx; + move16(); + } + ELSE + { + sign1_fx = negate(q_fx); + } + /*sign2_fx = (denc_LSB[st][1] & 0x2)?(q_fx):(-q_fx);*/ + IF (s_and(denc_LSB_fx[st][1], 0x2)) + { + sign2_fx = q_fx; + move16(); + } + ELSE + { + sign2_fx = negate(q_fx); + } + tmp1 = L_sub(a1_fx, L_shl(Mult_32_16(L_add(L_shl(q1_fx, 15), sign1_fx), s1_fx16), sub(12+2, exp1)));/*12*/ + tmp2 = L_sub(a2_fx, L_shl(Mult_32_16(L_add(L_shl(q2_fx, 15), sign2_fx), s2_fx16), sub(12+2, exp2)));/*12*/ + newdist2_fx = L_add(Mult_32_32(tmp1, tmp1), Mult_32_32(tmp2, tmp2));/*-7*/ + + /* decision */ + IF ( LT_32(L_add(curdist1_fx, newdist1_fx), L_add(curdist2_fx, newdist2_fx))) + { + path[st][i/2+1] = step_LSB_fx[st][0]; + move16(); + metric_fx[st][i/2+1] = L_add(curdist1_fx, newdist1_fx); + move32(); + quant[st][i/2+1] = 0; + move16(); + dquant[st][i/2+1] = dqnt_LSB_fx[ step_LSB_fx[st][0] ][st]; + move16(); + } + ELSE + { + path[st][i/2+1] = step_LSB_fx[st][1]; + move16(); + metric_fx[st][i/2+1] = L_add(curdist2_fx, newdist2_fx); + move32(); + quant[st][i/2+1] = 1; + move16(); + dquant[st][i/2+1] = dqnt_LSB_fx[ step_LSB_fx[st][0] ][st]; + move16(); + } + + if( GT_32( MaxPath, metric_fx[st][i/2+1])) + { + MaxPath = L_add(metric_fx[st][i/2+1], 0); + } + } + /* Metric renormalization to prevent overflow */ + FOR ( st = 0; st < 4; st++) + { + metric_fx[st][i/2+1] = L_sub( metric_fx[st][i/2+1], MaxPath ); + move32(); + } + } + + /* Find path with minimal metric */ + dminpos = 0; + move16(); + dmin_fx = L_add(metric_fx[ dminpos][ i/2], 0); + FOR ( st = 1; st < 4; st++) + { + IF ( GT_32(dmin_fx, metric_fx[ st][ i/2])) + { + dmin_fx = L_add(metric_fx[ st][ i/2], 0); + dminpos = st; + move16(); + } + } + + /* Trace back to get output */ + position = dminpos; + move16(); + + FOR ( ; i >= 0; i-=2) + { + qout[i/2] = quant[position][ i/2+1 ]; + move16(); + dpath[i/2] = dquant[position][ i/2+1 ]; + move16(); + + IF (s_and(denc_LSB_fx[position][qout[i/2]], 0x1)) + { + dbuffer_fx[i] = 1; + move16(); + } + ELSE + { + dbuffer_fx[i] = -1; + move16(); + } + IF (s_and(denc_LSB_fx[position][qout[i/2]], 0x2)) + { + dbuffer_fx[i + 1] = 1; + move16(); + } + ELSE + { + dbuffer_fx[i + 1] = -1; + move16(); + } + + position = path[position][i/2+1]; + move16(); + } + + /* add decoded sequence to quanta */ + FOR ( i = 0; i < bcount; i++ ) + { + mbuffer_fx[i] = add(add(mbuffer_fx[i], shl(mbuffer_fx[i], 2)), dbuffer_fx[i]); + } + + return; +} +void TCQLSBdec_fx( Word16 *dpath, Word16 *mbuffer, Word16 bcount ) +{ + /*float q = QTCQ;*/ + Word16 q = 1;/*x5*/ + Word16 i, tmp, state = 0; + + tmp = shr(bcount, 1); + FOR ( i = 0; i < tmp; i++) + { + IF (s_and(ddec_LSB_fx[state][dpath[i]], 0x1)) + { + mbuffer[2*i] = q; + move16(); + } + ELSE + { + mbuffer[2*i] = negate(q); + } + + IF (s_and(ddec_LSB_fx[state][dpath[i]], 0x2)) + { + mbuffer[2*i + 1] = q; + move16(); + } + ELSE + { + mbuffer[2*i + 1] = negate(q); + } + + state = dstep_LSB_fx[state][dpath[i]]; + move16(); + } + + return; +} +void RestoreTCQ_fx( Word16 * magn, Word16 size, Word16 *bcount, Word16 *mbuffer) +{ + Word16 i, nzpos = 0, flag_g1 = 0; + + /* calculate actual nz positions */ + nzpos = 0; + move16(); + FOR ( i = 0; i < size; i++) + { + IF ( magn[i] != 0 ) + { + nzpos = add(nzpos, 1); + if ( GT_16(abs_s(magn[i]), 5)) + { + flag_g1 = 1; + move16(); + } + } + } + + IF ( GT_16(nzpos, 1)) + { + FOR( i = 0; i < size; i++) + { + test(); + IF (flag_g1 == 0 || GE_16(*bcount, 2*TCQ_AMP)) + { + BREAK; + } + + IF( abs_s(magn[i]) > 0 ) + { + magn[i] = mbuffer[*bcount]; + move16(); + *bcount = add(*bcount, 1); + } + } + } + + return; +} +void RestoreTCQdec_fx( Word16 * magn, Word16 size, Word16 *bcount, Word16 *mbuffer) +{ + Word16 i, nzpos = 0, flag_g1 = 0; + + /* calculate actual nz positions */ + nzpos = 0; + move16(); + FOR ( i = 0; i < size; i++) + { + IF( magn[i] != 0 ) + { + nzpos = add(nzpos, 1); + if ( GT_16(abs_s(magn[i]), 1)) + { + flag_g1 = 1; + move16(); + } + magn[i] = extract_l(L_mult0(magn[i], 5)); + } + } + + IF( GT_16(nzpos, 1)) + { + FOR ( i = 0; i < size; i++) + { + test(); + IF (!(flag_g1 && LT_16(*bcount, 2*TCQ_AMP))) + { + BREAK; + } + + IF ( magn[i] != 0 ) + { + mbuffer[*bcount] = add(magn[i], mbuffer[*bcount]); + move16(); + magn[i] = mbuffer[*bcount]; + move16(); + *bcount = add(*bcount, 1); + } + } + } + + return; +} + +void InitLSBTCQ_fx(Word16 *bcount) +{ + *bcount = 0; + move16(); + + return; +} +void SaveTCQdata_fx( PARCODEC_FX arInst, Word16 *dpath, Word16 bcount) +{ + Word16 i; + FOR ( i = 0; i < bcount; i++) + { + ar_encode_uniform_fx( arInst, dpath[i], 1); + } + + return; +} +void LoadTCQdata_fx( PARCODEC_FX arInst, Word16 *dpath, Word16 bcount) +{ + Word32 i; + FOR ( i = 0; i < bcount; i++) + { + dpath[i] = ar_decode_fx( arInst, uniform_model_fx ); + } + + return; +} + + +Word32 encode_position_ari_fx(PARCODEC_FX parenc, Word16* quants, Word16 size, Word32* est_bits_frame_fx) +{ + Word16 i, tmp; + Word16 nz = 0, pulses = 0; + Word16 prob[TCQ_MAX_BAND_SIZE]; + Word16 model_num_nz[TCQ_MAX_BAND_SIZE]; + Word16 *cur_quants = quants; + Word16 integer, frac; + Word32 /*est_bits_frame_fx, */btcq_fx = 0, bits_fx = 0, pnzp_fx; + + Word32 cp, scp, fxone, fxp1; + Word16 pos; + + fxone = 32768; + move32(); + fxp1 = 512*32768; + move32(); + + + + set16_fx( prob, 0, TCQ_MAX_BAND_SIZE ); + set16_fx( model_num_nz, 0, TCQ_MAX_BAND_SIZE ); + + FOR (i = 0; i < size; i ++) + { + pulses = add(pulses, abs_s(cur_quants[i])); + if (cur_quants[i] != 0) + { + nz = add(nz, 1); + } + } + + btcq_fx = GetBitsFromPulses_fx(pulses, size); + /* Estimate TCQ bits */ + bits_fx = L_sub(table_logcum_fx[size + 1], L_add(table_logcum_fx[nz + 1], table_logcum_fx[size - nz + 1])); + bits_fx = L_add(bits_fx, L_sub(btcq_fx, L_sub(table_logcum_fx[size + 1], L_add(table_logcum_fx[nz + 1], table_logcum_fx[size - nz + 1])))); + bits_fx = L_sub(bits_fx, L_sub(table_logcum_fx[pulses], L_add(table_logcum_fx[nz], table_logcum_fx[pulses - (nz - 1)]))); + bits_fx = L_sub(bits_fx, nz); + *est_bits_frame_fx = L_add(*est_bits_frame_fx, bits_fx); + + /*caculate the #nz probability */ + tmp = s_min(pulses, size); + FOR (i = 0; i < tmp; i++) + { + pnzp_fx = L_sub(L_deposit_h(add(i, 1)), btcq_fx); + pnzp_fx = L_add(pnzp_fx, L_add(L_sub(table_logcum_fx[size + 1], L_add(table_logcum_fx[i + 2], table_logcum_fx[size - i])), + L_sub(table_logcum_fx[pulses], L_add(table_logcum_fx[i + 1], table_logcum_fx[pulses - i])))); + pnzp_fx = L_add(pnzp_fx, 917498);/*16 */ + IF( GT_32( pnzp_fx, 0)) + { + integer = extract_h(pnzp_fx); + frac = extract_l(L_shr(L_sub(pnzp_fx, L_deposit_h(integer)), 1));/*15 */ + prob[i] = extract_h(L_shl(Pow2(integer, frac), 16));/*0 */ + + /*zero probability will incur problems in ar_make_model() */ + if (prob[i] == 0) + { + prob[i] = 1; + move16(); + } + } + ELSE + { + prob[i] = 1; + move16(); + } + } + + ar_make_model_fx(prob, model_num_nz, s_min(pulses, size)); + + IF (GT_16(nz, 1)) + { + ar_encode_fx(parenc, model_num_nz, nz - 1);/*encode #nz */ + scp = L_add(fxp1, 0); + pos = 0; + move16(); + FOR( i = 0; i < size; i++) + { + IF (nz <= 0) + { + BREAK; + } + + IF( nz == (size - i) ) + { + cp = L_deposit_l(0); + } + ELSE + { + cp = L_sub( fxone, div_l( L_deposit_h(nz), (size - i)) ); + } + scp = Mult_32_16( scp, extract_l(cp) ); + model_num_nz[pos+1] = round_fx( L_shl( scp, 6) ); + + test(); + test(); + IF( (model_num_nz[pos+1] == 0 && scp > 0) || model_num_nz[pos] == model_num_nz[pos+1] ) + { + model_num_nz[pos+1] = 0; + move16(); + ar_encode_fx( parenc, model_num_nz, pos ); + i--; + move16(); + scp = L_add(fxp1, 0); + pos = 0; + move16(); + CONTINUE; + } + + IF( cur_quants[i] != 0 ) + { + ar_encode_fx( parenc, model_num_nz, pos ); + pos = 0; + move16(); + scp = L_add(fxp1, 0); + nz--; + move16(); + } + ELSE + { + pos++; + move16(); + } + } + } + ELSE IF (EQ_16(nz, 1)) + { + IF (GT_16(pulses, 1)) + { + /*temp -= log2_f((float)(model_num_nz[nz-1] - model_num_nz[nz]) / MAX_AR_FREQ); */ + ar_encode_fx(parenc, model_num_nz, 0);/*encode #nz */ + } + pos = 0; + move16(); + FOR( i = 0; i < size; i++) + { + model_num_nz[i+1] = round_fx( L_shr( L_deposit_h( div_l( L_deposit_h(size - i - 1), size)), 1) ); + + if( cur_quants[i] != 0 ) + { + pos = i; + move16(); + } + } + ar_encode_fx( parenc, model_num_nz, pos ); /* encode pos */ + } + return bits_fx; +} +Word32 encode_magnitude_usq_fx(ARCODEC_FX* parenc, Word16* magn_fx, Word16 size, Word16 npulses, Word16 nzpos, Word32* est_frame_bits_fx) +{ + Word16 i, j, k, tmp, magnp, magnzp; + Word16 magn_position[MAX_PULSES]; + Word32 /*est_frame_bits_fx, */bits_fx; + Word16 pos, model_m[MAX_PULSES + 2]; + Word32 fxone, fxp1, cp, scp; + + fxone = 32768; + move32(); + fxp1 = 512*32768; + move32(); + + + /*estimate fac bits */ + bits_fx = L_sub(table_logcum_fx[npulses], L_add(table_logcum_fx[nzpos], table_logcum_fx[npulses - nzpos + 1])); + *est_frame_bits_fx = L_add(*est_frame_bits_fx, bits_fx); + + test(); + IF (EQ_16(npulses, nzpos)||EQ_16(nzpos,1)) + { + return bits_fx; + } + magnp = sub(npulses, 1); + magnzp = sub(nzpos, 1); + + /*generate the binary sequences of magnitudes */ + k = 0; + move16(); + FOR (i = 0; i < size; i++) + { + IF (magn_fx[i] != 0) + { + tmp = sub(abs_s(magn_fx[i]), 1); + FOR (j = 0; j < tmp; j++) + { + magn_position[k++] = 0; + move16(); + } + magn_position[k++] = 1; + move16(); + } + } + + set16_fx( model_m, 0, MAX_PULSES + 2); + scp = L_add(fxp1, 0); + model_m[0] = MAX_AR_FREQ; + move16(); + pos = 0; + move16(); + tmp = sub(npulses, 1); + FOR( i = 0; i < tmp; i++ ) + { + IF (magnzp <= 0) + { + BREAK; + } + + IF( magnzp == magnp ) + { + cp = L_deposit_l(0); + } + ELSE + { + cp = L_sub( fxone, div_l( L_deposit_h(magnzp), magnp) ); + } + scp = Mult_32_16( scp, extract_l(cp) ); + model_m[pos+1] = round_fx( L_shl( scp, 6) ); + + test(); + test(); + IF( (model_m[pos+1] == 0 && scp > 0) || model_m[pos] == model_m[pos+1] ) + { + model_m[pos+1] = 0; + move16(); + + ar_encode_fx( parenc, model_m, pos ); + pos = 0; + move16(); + i--; + move16(); + scp = L_add(fxp1, 0); + CONTINUE; + } + + IF( magn_position[i] != 0 ) + { + ar_encode_fx( parenc, model_m, pos ); + pos = 0; + move16(); + magnzp--; + move16(); + scp = L_add(fxp1, 0); + } + ELSE + { + pos++; + move16(); + } + + magnp--; + move16(); + } + return bits_fx; +} +Word32 encode_magnitude_tcq_fx(ARCODEC_FX* parenc, Word16* magn_fx, Word16 size, Word16 npulses, Word16 nzpos, Word32* savedstates, Word32* est_frame_bits_fx) +{ + Word32 tcq_bits_fx, bits_fx/*, est_frame_bits_fx*/; + Word16 prob0_fx, prob1_fx, num, denum, quantum1_fx, quantum2_fx; + Word16 exp, exp1, exp2; + + Word16 i, j; + Word32 st; + Word16 magn_mode[3] = {MAX_AR_FREQ, 0, 0}; + + Word16 leftp = npulses;/*pulsesnum; */ + Word16 leftnz = nzpos;/*nzpos; */ + move16(); + move16(); + + bits_fx = L_deposit_l(0); + tcq_bits_fx = L_sub(table_logcum_fx[npulses], L_add(table_logcum_fx[nzpos], table_logcum_fx[npulses - (nzpos - 1)])); + *est_frame_bits_fx = L_add(*est_frame_bits_fx, tcq_bits_fx); + + test(); + IF (EQ_16(nzpos, npulses)||EQ_16(nzpos,1)) + { + return bits_fx; + } + + st = L_deposit_l(0); + FOR ( i = 0; i < size; i++) + { + IF (LE_16(leftnz, 1)) + { + BREAK; + } + + st = L_add(savedstates[i], 0); + IF (magn_fx[i] != 0) + { + FOR ( j = 0; j < leftp; j++) + { + /*calculate the two path probs point to next two states */ + num = sub(leftnz, 1); + denum = sub(leftp, add(j, 0x1)); + IF (GE_16(num, denum)) + { + prob1_fx = MAX_16; + move16(); + prob0_fx = 0; + move16(); + } + ELSE + { + exp1 = sub(norm_s(num), 1); + exp2 = norm_s(denum); + prob1_fx = div_s(shl(num, exp1), shl(denum, exp2));/*15 + exp1 - exp2 */ + exp = 15 + exp1 - exp2; + move16(); + prob1_fx = shl(prob1_fx, sub(15, exp)); + prob0_fx = sub(MAX_16, prob1_fx); + } + + quantum1_fx = quantize_fx(shl(add(j, 1), 10), ddec_fx[st][0]); + quantum2_fx = quantize_fx(shl(add(j, 1), 10), ddec_fx[st][1]); + + test(); + IF (NE_16(quantum1_fx, add(j, 1))&&NE_16(quantum2_fx,add(j,1))) + { + prob0_fx = MAX_16; + move16(); + prob1_fx = 0; + move16(); + } + + test(); + IF (EQ_16(prob0_fx, MAX_16)||EQ_16(prob1_fx,MAX_16)) + { + CONTINUE; + } + + magn_mode[1] = mult(prob1_fx, MAX_AR_FREQ); + IF (LT_16(j, sub(abs_s(magn_fx[i]), 1))) + { + ar_encode_fx(parenc, magn_mode, 0); + } + ELSE + { + IF (sub(leftp, j) > leftnz) + { + ar_encode_fx(parenc, magn_mode, 1); + } + BREAK; + } + } + + leftnz--; + move16(); + leftp = sub(leftp, abs_s( magn_fx[i] )); + } + } + + return bits_fx; +} +Word32 encode_signs_fx(ARCODEC_FX* parenc, Word16* magn, Word16 size, Word16 npos, Word32* est_frame_bits_fx) +{ + Word32 i, sign; + + *est_frame_bits_fx = L_add(*est_frame_bits_fx, L_deposit_h(npos)); + FOR (i = 0; i < size; i++) + { + IF (magn[i] != 0) + { + sign = L_deposit_l(0); + if (magn[i] > 0) + { + sign = L_deposit_l(1); + } + ar_encode_uniform_fx(parenc, sign, 1); + } + } + + return L_deposit_h(npos); +} +void decode_position_ari_fx(PARCODEC_FX pardec, Word16 size, Word16 npulses, Word16* nz, Word16* position) +{ + Word16 i, tmp, nzp; + Word16 mode_num_nz[TCQ_MAX_BAND_SIZE]; + Word16 prob[TCQ_MAX_BAND_SIZE]; + + Word32 btcq_fx, pnzp_fx; + Word16 integer, frac; + Word32 cp, scp, fxone, fxp1; + Word16 stpos = 0, pos, ovrflag = 0, temppos, storepos; + + fxone = 32768; + move32(); + fxp1 = 512*32768; + move32(); + temppos = 0; + move16(); + storepos = 0; + move16(); + + set16_fx( mode_num_nz, 0, TCQ_MAX_BAND_SIZE ); + set16_fx( prob, 0, TCQ_MAX_BAND_SIZE ); + + FOR (i = 0; i < size; i++) + { + position[i] = 0; + move16(); + } + + IF (GT_32(npulses, 1)) + { + btcq_fx = GetBitsFromPulses_fx(npulses, size); + tmp = s_min(npulses, size); + FOR (i = 0; i < tmp; i++) + { + /*calculate the probability of #nz */ + + pnzp_fx = L_sub(L_deposit_h(add(i, 1)), btcq_fx); + pnzp_fx = L_add(pnzp_fx, L_add(L_sub(table_logcum_fx[size + 1], L_add(table_logcum_fx[i + 2], table_logcum_fx[size - i])), + L_sub(table_logcum_fx[npulses], L_add(table_logcum_fx[i + 1], table_logcum_fx[npulses - i])))); + pnzp_fx = L_add(pnzp_fx, 917498);/*16 */ + IF( GT_32( pnzp_fx, 0)) + { + integer = extract_h(pnzp_fx); + frac = extract_l(L_shr(L_sub(pnzp_fx, L_deposit_h(integer)), 1));/*15 */ + prob[i] = extract_h(L_shl(Pow2(integer, frac), 16));/*0 */ + if (prob[i] == 0) + { + prob[i] = 1; + move16(); + } + } + ELSE + { + prob[i] = 1; + move16(); + } + } + + ar_make_model_fx(prob, mode_num_nz, s_min(npulses, size)); + *nz = add(1, ar_decode_fx(pardec, mode_num_nz));/*get #nz */ + nzp = *nz; + move16(); + IF( nzp == 1 ) + { + mode_num_nz[0] = MAX_AR_FREQ; + move16(); + FOR (i = 0; i < size; i ++) + { + mode_num_nz[i+1] = round_fx( L_shr( L_deposit_h( div_l( L_deposit_h(size - i - 1), size)), 1) ); + } + + position[ ar_decode_fx(pardec, mode_num_nz) ] = 1; + move16(); + } + ELSE + { + mode_num_nz[0] = MAX_AR_FREQ; + move16(); + + FOR( ; nzp > 0; nzp-- ) + { + scp = L_add(fxp1, 0); + temppos = 0; + move16(); + storepos = 0; + move16(); + + FOR( i = stpos; i < size; i++) + { + ovrflag = 0; + move16(); + + IF( nzp == (size - i) ) + { + cp = L_deposit_l(0); + } + ELSE + { + cp = L_sub( fxone, div_l( L_deposit_h(nzp), (size - i)) ); + } + scp = Mult_32_16( scp, extract_l(cp) ); + mode_num_nz[i+1-storepos-stpos] = round_fx( L_shl( scp, 6) ); + + test(); + test(); + IF( (mode_num_nz[i+1-storepos-stpos] == 0 && scp > 0) || mode_num_nz[i-storepos-stpos] == mode_num_nz[i+1-storepos-stpos] ) + { + mode_num_nz[i+1-storepos-stpos] = 0; + move16(); + ovrflag = 1; + move16(); + temppos = ar_decode_fx(pardec, mode_num_nz); + move16(); + storepos += temppos; + move16(); + scp = L_add(fxp1, 0); + + IF( temppos == i-stpos) /* esc transmitted */ + { + i--; + move16(); + } + ELSE + { + BREAK; + } + } + } + IF( !ovrflag ) + { + pos = ar_decode_fx(pardec, mode_num_nz) + storepos; + move16(); + } + ELSE + { + pos = storepos; + move16(); + } + + position[ stpos + pos] = 1; + move16(); + stpos += pos + 1; + move16(); + } + } + } + ELSE IF (EQ_32(npulses, 1)) + { + *nz = npulses; + move16(); + nzp = *nz; + move16(); + mode_num_nz[0] = MAX_AR_FREQ; + move16(); + FOR (i = 0; i < size; i ++) + { + mode_num_nz[i+1] = round_fx( L_shr( L_deposit_h( div_l( L_deposit_h(size - i - 1), size)), 1) ); + } + + position[ ar_decode_fx(pardec, mode_num_nz) ] = 1; + move16(); + } + ELSE + { + *nz = 0; + move16(); + } + + return; +} +void decode_magnitude_usq_fx(ARCODEC_FX* pardec, Word16 size, Word16 npulses, Word16 nzpos, Word16* positions, Word16* out) +{ + Word16 i, magnp, magnzp; + Word16 magns[TCQ_MAX_BAND_SIZE], magncout = 0; + Word16 storemagn, ovrflag = 0, pos, tempmagn = 0, mmodel[MAX_PULSES+2]; + Word32 cp, scp, fxone, fxp1; + + fxone = 32768; + move32(); + fxp1 = 512*32768; + move32(); + + set16_fx( magns, 1, TCQ_MAX_BAND_SIZE ); + IF (EQ_16(nzpos, npulses)) + { + FOR (i = 0; i < size; i++) + { + out[i] = positions[i]; + move16(); + } + return; + } + ELSE IF (EQ_16(nzpos, 1)) + { + FOR (i = 0; i < size; i++) + { + IF ( positions[i] != 0 ) + { + out[i] = npulses; + move16(); + return; + } + } + } + + magnzp = sub(nzpos, 1); + magnp = sub(npulses, 1); + + magncout = 0; + move16(); + + set16_fx( out, 0, size ); + set16_fx( mmodel, 0, MAX_PULSES+2 ); + + mmodel[0] = MAX_AR_FREQ; + move16(); + magncout = 0; + move16(); + FOR( pos = 0; pos < size; pos++) + { + scp = L_add(fxp1, 0); + IF( positions[pos] != 0) + { + storemagn = 0; + move16(); + + FOR( i = 0; i < magnp; i++) + { + ovrflag = 0; + move16(); + + IF( magnzp == (magnp-i) ) + { + cp = L_deposit_l(0); + } + ELSE + { + cp = L_sub( fxone, div_l( L_deposit_h(magnzp), magnp-i) ); + } + + IF( cp == fxone ) + { + BREAK; + } + + scp = Mult_32_16( scp, extract_l(cp) ); + mmodel[i+1-storemagn] = round_fx( L_shl( scp, 6) ); + + test(); + test(); + IF( (mmodel[i+1- storemagn] == 0 && scp > 0) || mmodel[i- storemagn] == mmodel[i+1- storemagn] ) + { + mmodel[i+1-storemagn] = 0; + move16(); + /* read data */ + tempmagn = ar_decode_fx( pardec, mmodel ); + storemagn += tempmagn; + move16(); + + IF( tempmagn < i ) + { + /* just magnitude */ + ovrflag = 1; + move16(); + BREAK; + } + ELSE + { + /* esc code */ + scp = L_add(fxp1, 0); + i--; + move16(); + } + } + } + + IF( ovrflag ) + { + out[magncout] = storemagn + 1; + move16(); + } + ELSE + { + out[magncout] = ar_decode_fx( pardec, mmodel ) + storemagn + 1; + move16(); + } + magnp -= out[magncout]; + move16(); + magnzp--; + move16(); + magncout++; + move16(); + + IF (magnzp == 0) /* last magnitude generation */ + { + FOR( pos = add(pos,1); pos < size; pos++) + { + IF( positions[pos] != 0) + { + out[magncout] = magnp + 1; + move16(); + return; + } + ELSE + { + out[magncout] = 0; + move16(); + magncout++; + move16(); + } + } + } + ELSE IF(magnzp == magnp) /* rest magnitudes generation */ + { + FOR( pos = add(pos,1); pos < size; pos++) + { + out[magncout] = positions[pos]; + move16(); + magncout++; + move16(); + } + return; + } + } + ELSE + { + out[magncout] = 0; + move16(); + magncout++; + move16(); + } + } + + return; +} +void decode_mangitude_tcq_fx(ARCODEC_FX* pardec, Word16 size, Word16 npulses, Word16 nzpos, Word16* positions, Word16* out, Word32* surplus_fx) +{ + Word32 tcq_bits_fx, bits_fx/*, surplus_fx*/; + Word16 prob0_fx, prob1_fx, num, denum, quantum1_fx, quantum2_fx; + Word16 exp, exp1, exp2, tmp16; + Word32 tmp32; + + Word16 i, j, symbol, st; + Word16 leftp = npulses;/*pulsesnum; */ + Word16 leftnz = nzpos; /*nzpos; */ + Word16 magn_mode[3] = {MAX_AR_FREQ, 0, 0}; + + bits_fx = L_deposit_l(0); + tcq_bits_fx = L_sub(table_logcum_fx[npulses], L_add(table_logcum_fx[nzpos], table_logcum_fx[npulses - (nzpos - 1)])); + + IF (EQ_16(nzpos, npulses)) + { + FOR (i = 0; i < size; i++) + { + out[i] = positions[i]; + move16(); + } + + return; + } + ELSE IF (EQ_16(nzpos, 1)) + { + FOR (i = 0; i < size; i++) + { + IF ( positions[i] != 0 ) + { + out[i] = npulses; + move16(); + return; + } + } + } + st = 0; + move16(); + FOR (i = 0; i < size; i++) + { + IF (LE_16(leftnz, 1)) + { + BREAK; + } + + out[i] = positions[i]; + IF (positions[i] != 0) + { + /*generate the trellis path */ + symbol = 0; + move16(); + FOR (j = 0; j < leftp; j++) + { + num = sub(leftnz, 1); + denum = sub(leftp, add(j, 1)); + IF (GE_16(num, denum)) + { + prob1_fx = MAX_16; + move16(); + prob0_fx = 0; + move16(); + } + ELSE + { + exp1 = sub(norm_s(num), 1); + exp2 = norm_s(denum); + prob1_fx = div_s(shl(num, exp1), shl(denum, exp2));/*15 + exp1 - exp2 */ + exp = 15 + exp1 - exp2; + prob1_fx = shl(prob1_fx, sub(15, exp)); + prob0_fx = sub(MAX_16, prob1_fx); + } + IF (EQ_32(sub(leftp, j), leftnz)) + { + symbol = add(j, 1); + BREAK; + } + + quantum1_fx = quantize_fx(shl(add(j, 1), 10), ddec_fx[st][0]); + quantum2_fx = quantize_fx(shl(add(j, 1), 10), ddec_fx[st][1]); + + test(); + IF (NE_16(quantum1_fx, add(j, 1))&&NE_16(quantum2_fx,add(j,1))) + { + prob0_fx = MAX_16; + move16(); + prob1_fx = 0; + move16(); + } + + test(); + IF (EQ_16(prob0_fx, MAX_16)||EQ_16(prob1_fx,MAX_16)) + { + symbol = add(j, 1); + CONTINUE; + } + + /*magn_mode[1] = (short)(prob1 * MAX_AR_FREQ); */ + magn_mode[1] = mult(prob1_fx, MAX_AR_FREQ); + + IF (ar_decode_fx(pardec, magn_mode)) + { + exp1 = norm_s(prob1_fx); + tmp32 = L_deposit_h(shl(prob1_fx, exp1));/*exp1 + 15 + 16 */ + tmp16 = Log2_norm_lc(tmp32);/*15 */ + bits_fx = L_sub(bits_fx, L_sub(tmp16, L_shl(add(exp1, 1), 15)));/*15 */ + + symbol = add(j, 1); + BREAK; + } + ELSE + { + exp1 = norm_s(prob0_fx); + tmp32 = L_deposit_h(shl(prob0_fx, exp1));/*exp1 + 15 + 16 */ + tmp16 = Log2_norm_lc(tmp32);/*15 */ + bits_fx = L_sub(bits_fx, L_sub(tmp16, L_shl(add(exp1, 1), 15)));/*15 */ + } + } + out[i] = symbol; + move16(); + /*leftp -= symbol; */ + leftp = sub(leftp, symbol); + leftnz = sub(leftnz, 1); + } + + quantum1_fx = quantize_fx(out[i], ddec_fx[st][0]); + quantum2_fx = quantize_fx(out[i], ddec_fx[st][1]); + + /*generate the next state */ + IF (EQ_16(quantum1_fx, out[i])) + { + st = nextstate[st][0]; + move16(); + } + ELSE + { + st = nextstate[st][1]; + move16(); + } + } + + /*generate the magnitudes */ + FOR (; i < size; i++) + { + out[i] = 0; + move16(); + IF (positions[i] != 0) + { + out[i] = add(sub(leftp, leftnz), 1); + } + + } + + test(); + IF (NE_16(nzpos, npulses)&>_16(nzpos,1)) + { + /*update the surplus */ + *surplus_fx = L_add(*surplus_fx, L_sub(tcq_bits_fx, L_shl(bits_fx, 1))); + } + + return; +} + +void decode_signs_fx(ARCODEC_FX* pardec, Word16 size, Word16* out) +{ + Word16 i; + + FOR ( i = 0; i < size; i++) + { + IF ( out[i] != 0 ) + { + Word16 tmp; + tmp = ar_decode_fx( pardec, uniform_model_fx ); + + if( tmp <= 0 ) + { + out[i] = negate(out[i]); + } + } + } + + return; +} + +Word16 GetScale_fx( Word16 blen, Word32 bits_fx/*Q16*/, Word32 *surplus_fx/*Q16*/) +{ + Word16 pulses = MAX_PULSES, p_est, exp, exp1, exp2, magicnum; + Word32 t, a, b, ab, estbits_fx = 0; + + magicnum = 24773; + move16(); /*Q17: 0.188992013101951f; */ + + t = L_shr( L_mult( magicnum, blen), 2); + exp = norm_l(t); + a = L_shl( 14 - exp, 15) + Log2_norm_lc( L_shl( t, exp ) ); + + exp1 = sub( norm_l(bits_fx), 1); + exp2 = norm_s( blen - 1 ); + b = L_shr( L_deposit_l( div_l( L_shl( bits_fx, exp1), shl( blen - 1, exp2) ) ), exp1-exp2 ); + + ab = L_add( a, b); + + p_est = extract_h(L_shl(Pow2( extract_l( L_shr(ab,15) ), ab&0x7FFF ),16)); /* enable saturationof pow2 result */ + + pulses = s_min( p_est, MAX_PULSES ); + + FOR( ; pulses >= 0; pulses--) + { + estbits_fx = GetBitsFromPulses_fx( pulses, blen); + IF( GE_32( bits_fx, estbits_fx)) + { + BREAK; + } + } + + IF ( surplus_fx != 0 ) + { + *surplus_fx = L_add(*surplus_fx, L_sub(bits_fx, estbits_fx)); + } + + return pulses; +} + +void srt_vec_ind_fx ( + const Word32 *linear, /* linear input */ + Word32 *srt, /* sorted output*/ + Word16 *I, /* index for sorted output */ + Word16 length +) +{ + Word16 pos,npos,tmp; + Word16 idxMem; + Word32 valMem; + + /*initilize */ + FOR (pos = 0; pos < length; pos++) + { + I[pos] = pos; + move16(); + } + + Copy32(linear, srt, length); + + /* now iterate */ + tmp = sub(length, 1); + FOR (pos = 0; pos < tmp; pos++) + { + FOR (npos = add(pos, 1); npos < length; npos++) + { + IF (LT_32(srt[npos], srt[pos])) + { + idxMem = I[pos]; + move16(); + I[pos] = I[npos]; + move16(); + I[npos] = idxMem; + move16(); + + valMem = L_add(srt[pos], 0); + srt[pos] = srt[npos]; + move32(); + srt[npos] = valMem; + move32(); + } + } + } + + return; +} diff --git a/lib_com/tcx_ltp.c b/lib_com/tcx_ltp.c new file mode 100644 index 0000000..b23037e --- /dev/null +++ b/lib_com/tcx_ltp.c @@ -0,0 +1,732 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "prot_fx.h" +#include "stl.h" +#include "cnst_fx.h" +#include "basop_util.h" +#include "rom_com_fx.h" + +#define ALPHA 27853/*0.85f Q15*/ + + +void tcx_ltp_get_lpc(Word16 *x, Word16 L, Word16 *A, Word16 order) +{ + Word16 i, j, s, s2, tmp; + Word32 r, L_tmp; + + Word16 tmpbuf[L_FRAME_MAX], *p = x; + Word16 r_l[TCXLTP_LTP_ORDER+1], r_h[TCXLTP_LTP_ORDER+1]; + + + assert(L <= L_FRAME_MAX); + + /* calc r[0], determine shift */ + s = 0; + move16(); + r = L_deposit_l(0); + FOR (j = 0; j < L; j++) + { + L_tmp = L_sub(r, 0x40000000); + if (L_tmp > 0) s = sub(s, 1); + if (L_tmp > 0) r = L_shr(r, 2); + + tmp = shl(x[j], s); + r = L_mac0(r, tmp, tmp); + } + r = L_max(r, L_shl(100, shl(s, 1))); + r = Mpy_32_16_1(r, 16386/*1.0001f Q14*/); + s2 = norm_l(r); + r = L_shl(r, s2); + s2 = sub(s2, 1); + r_l[0] = L_Extract_lc(r, &r_h[0]); + move16(); + move16(); + + IF (s < 0) + { + /* shift buffer by s, recompute r[0] to reduce risk of instable LPC */ + r = L_deposit_l(0); + tmp = lshl((Word16)0x8000, s); /* factor corresponding to right shift by -s */ + + { + Word64 r64 = 0; + move64(); + FOR (j = 0; j < L; j++) + { + tmpbuf[j] = mult_r(x[j], tmp); + move16(); + r64 = W_mac0_16_16(r64, tmpbuf[j], tmpbuf[j]); + } + r = W_sat_l(r64); + } + r = L_max(r, L_shl(100, shl(s, 1))); + r = Mpy_32_16_1(r, 16386/*1.0001f Q14*/); + s2 = norm_l(r); + r = L_shl(r, s2); + s2 = sub(s2, 1); + r_l[0] = L_Extract_lc(r, &r_h[0]); + move16(); + move16(); + + p = tmpbuf; + } + + /* calc r[1...] */ + FOR (i = 1; i <= order; i++) + { + r = L_deposit_l(0); + + tmp = sub(L, i); + { + Word64 r64 = 0; + move64(); + FOR (j = 0; j < tmp; j++) + { + r64 = W_mac0_16_16(r64, p[j], p[j+i]); + } + r = W_sat_l(r64); + } + r = L_shl(r, s2); + r_l[i] = L_Extract_lc(r, &r_h[i]); + move16(); + move16(); + } + + E_LPC_lev_dur(r_h, r_l, A, NULL, order, NULL); + +} + +static void tcx_ltp_get_zir( Word16 *zir, Word16 length, Word16 *synth_ltp, Word16 *synth, Word16 *A, Word16 lpcorder, Word16 gain, Word16 pitch_int, Word16 pitch_fr, Word16 pitres, Word16 filtIdx ) +{ + Word16 buf[TCXLTP_LTP_ORDER], alpha, step; + Word16 *x0, *x1; + Word16 *y0, *y1; + Word32 s, s2; + const Word16 *w0, *w1, *v0, *v1; + Word16 i, j, k, L; + + x0 = &synth_ltp[-pitch_int]; + x1 = x0 - 1; + y0 = synth; + y1 = y0 - 1; + + assert(filtIdx >= 0); + + w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr]; + w1 = &tcxLtpFilters[filtIdx].filt[sub(pitres, pitch_fr)]; + v0 = &tcxLtpFilters[filtIdx].filt[0]; + v1 = &tcxLtpFilters[filtIdx].filt[pitres]; + L = tcxLtpFilters[filtIdx].length; + move16(); + + FOR (j = 0; j < lpcorder; j++) + { + s = L_deposit_l(0); + s2 = L_deposit_l(0); + k = 0; + move16(); + FOR (i = 0; i < L; i++) + { + s = L_mac(L_mac(s, w0[k], x0[i]), w1[k], x1[-i]); + s2 = L_mac(L_mac(s2, v0[k], y0[i]), v1[k], y1[-i]); + k = add(k, pitres); + } + + /* s2 *= ALPHA; + buf[j] = ( synth[j] - gain * s2 ) - ( synth_ltp[j] - gain * s ); */ + i = sub(round_fx(s), mult_r(round_fx(s2), ALPHA)); + buf[j] = add(sub(synth[j], synth_ltp[j]), mult_r(gain, i)); + move16(); + + x0++; + x1++; + y0++; + y1++; + } + + set16_fx(zir, 0, length); + + E_UTIL_synthesis(0, A, zir, zir, length, buf, 0, lpcorder); + + alpha = 0x7FFF; + move16(); + /* step = 1.f/(float)(length/2); */ + step = shl(4, norm_s(length)); + if (s_and(length, sub(length, 1)) != 0) + { + step = mult_r(step, 26214/*64.f/80.f Q15*/); + } + if (EQ_16(length, 240)) + { + step = 273/*1.f/120.f Q15*/; + move16(); + } + + FOR (j = shr(length, 1); j < length; j++) + { + zir[j] = mult_r(zir[j], alpha); + move16(); + alpha = sub(alpha, step); + } +} + +void predict_signal( + const Word16 excI[], /* i : input excitation buffer */ + Word16 excO[], /* o : output excitation buffer */ + const Word16 T0, /* i : integer pitch lag */ + Word16 frac, /* i : fraction of lag */ + const Word16 frac_max,/* i : max fraction */ + const Word16 L_subfr /* i : subframe size */ +) +{ + Word16 j; + Word32 s; + const Word16 *x0, *win; + + + + + x0 = &excI[-T0-1]; + frac = negate(frac); + + IF (frac < 0) + { + frac = add(frac, frac_max); + x0--; + } + + win = &inter4_2tcx2[frac][0]; + if (EQ_16(frac_max, 6))win=&inter6_2tcx2[frac][0]; + + FOR (j = 0; j < L_subfr; j++) + { + s = L_mult(win[0], x0[0]); + s = L_mac(s, win[1], x0[1]); + s = L_mac(s, win[2], x0[2]); + excO[j] = mac_r(s, win[3], x0[3]); + move16(); + + x0++; + } + +} + +static void tcx_ltp_synth_filter( Word16 *synth_ltp, + Word16 *synth, + Word16 length, + Word16 pitch_int, + Word16 pitch_fr, + Word16 gain, + Word16 pitch_res + ,Word16 *zir /* can be NULL */ + ,Word16 fade /* 0=normal, +1=fade-in, -1=fade-out */ + ,Word16 filtIdx + ) +{ + Word16 *x0, *x1; + Word16 *y0, *y1; + Word32 s, s2; + const Word16 *v0, *v1; + const Word16 *w0, *w1; + Word16 alpha, step = 0; /* initialize just to avoid compiler warning */ + Word16 i, j, k, L; + + IF (gain > 0) + { + x0 = &synth_ltp[-pitch_int]; + x1 = x0 - 1; + y0 = synth; + y1 = y0 - 1; + + assert(filtIdx >= 0); + + w0 = &tcxLtpFilters[filtIdx].filt[pitch_fr]; + w1 = &tcxLtpFilters[filtIdx].filt[sub(pitch_res, pitch_fr)]; + v0 = &tcxLtpFilters[filtIdx].filt[0]; + v1 = &tcxLtpFilters[filtIdx].filt[pitch_res]; + + L = tcxLtpFilters[filtIdx].length; + move16(); + + alpha = 0; + move16(); + IF (fade != 0) + { + if (fade < 0) + { + alpha = 0x7FFF; + move16(); + } + + /* step = 1.f/(float)(length); */ + step = shl(2, norm_s(length)); + if (s_and(length, sub(length, 1)) != 0) + { + step = mult_r(step, 26214/*64.f/80.f Q15*/); + } + if (EQ_16(length, 240)) + { + step = 137/*1.f/240.f Q15*/; + move16(); + } + + if (fade < 0) step = negate(step); + } + + FOR (j = 0; j < length; j++) + { + s = L_deposit_l(0); + s2 = L_deposit_l(0); + k = 0; + move16(); + FOR (i = 0; i < L; i++) + { + s = L_mac(L_mac(s, w0[k], x0[i]), w1[k], x1[-i]); + s2 = L_mac(L_mac(s2, v0[k], y0[i]), v1[k], y1[-i]); + k = add(k, pitch_res); + } + + /* s2 *= ALPHA; + normal: synth_ltp[j] = synth[j] - gain * s2 + gain * s; + zir: synth_ltp[j] = synth[j] - gain * s2 + gain * s - zir[j]; + fade-in/out: synth_ltp[j] = synth[j] - alpha * gain * s2 + alpha * gain * s; */ + i = sub(round_fx(s), mult_r(round_fx(s2), ALPHA)); + k = mult_r(gain, i); + if (fade != 0) k = mult_r(k, alpha); + k = add(synth[j], k); + if (zir != NULL) k = sub(k, zir[j]); + + synth_ltp[j] = k; + move16(); + + BASOP_SATURATE_WARNING_OFF; + if (fade != 0) alpha = add(alpha, step); + BASOP_SATURATE_WARNING_ON; + + x0++; + x1++; + y0++; + y1++; + } + } + ELSE + { + Copy( synth, synth_ltp, length ); + } +} + +Word16 tcx_ltp_decode_params( Word16 *ltp_param, + Word16 *pitch_int, + Word16 *pitch_fr, + Word16 *gain, + Word16 pitmin, + Word16 pitfr1, + Word16 pitfr2, + Word16 pitmax, + Word16 pitres + ) +{ + Word16 tmp, tmp2; + + + + /* Decode Pitch and Gain */ + test(); + IF (ltp_param != 0 && ltp_param[0] != 0) + { + tmp = imult1616(sub(pitfr2, pitmin), pitres); + + IF ( LT_16(ltp_param[1], tmp)) + { + tmp2 = idiv1616U(ltp_param[1], pitres); + + *pitch_int = add(pitmin, tmp2); + move16(); + *pitch_fr = sub(ltp_param[1], imult1616(tmp2, pitres)); + move16(); + } + ELSE + { + pitres = shr(pitres, 1); + tmp2 = imult1616(sub(pitfr1, pitfr2), pitres); + + IF ( LT_16(ltp_param[1], add(tmp, tmp2))) + { + tmp2 = idiv1616U(sub(ltp_param[1], tmp), pitres); + + *pitch_int = add(pitfr2, tmp2); + move16(); + *pitch_fr = shl( sub(sub(ltp_param[1], tmp), imult1616(tmp2, pitres)), 1 ); + move16(); + } + ELSE + { + *pitch_int = sub(add(ltp_param[1], pitfr1), add(tmp, tmp2)); + move16(); + *pitch_fr = 0; + move16(); + } + } + + *gain = imult1616(add(ltp_param[2], 1), 0x1400); + move16(); + + IF( LT_16(*pitch_int,PIT_MIN_SHORTER)) + { + /*pitch out of range due to bit error */ + *pitch_int = PIT_MIN_SHORTER; + move16(); + return 1; + } + + IF( GT_16(*pitch_int,PIT_MAX_MAX)) + { + /*pitch out of range due to bit error */ + *pitch_int = PIT_MAX_MAX; + move16(); + return 1; + } + } + ELSE + { + *pitch_int = pitmax; + move16(); + *pitch_fr = 0; + move16(); + *gain = 0; + move16(); + } + + return 0; +} + +void tcx_ltp_post( Word8 tcxltp_on, + Word16 core, + Word16 L_frame, + Word16 L_frame_core, + Word16 delay, + Word16 *sig, + Word16 *tcx_buf, + Word16 tcx_buf_len, + Word16 bfi, + Word16 pitch_int, + Word16 pitch_fr, + Word16 gain, + Word16 *pitch_int_past, + Word16 *pitch_fr_past, + Word16 *gain_past, + Word16 *filtIdx_past, + Word16 pitres, + Word16 *pitres_past, + Word16 damping, + Word16 SideInfoOnly, + Word16 *mem_in, + Word16 *mem_out, + Word32 bitrate + ) +{ + Word16 tmp, L_transition, lpcorder, filtIdx; + Word16 gain2; + Word32 tmp32; + Word16 zir[L_FRAME_PLUS/4], A[TCXLTP_LTP_ORDER+1]; + Word16 buf_in[TCXLTP_MAX_DELAY+L_FRAME48k+TCXLTP_MAX_DELAY], buf_out[2*L_FRAME48k]; + Word16 *sig_in, *sig_out; + + filtIdx = 0; /* just to avoid comilation warnings */ + + /******** Init ********/ + + + /* Parameters */ + L_transition = shr(L_frame, 2); + lpcorder = TCXLTP_LTP_ORDER; + move16(); + + /* Input buffer */ + sig_in = buf_in + tcx_buf_len; + Copy( mem_in, buf_in, tcx_buf_len ); + Copy( sig, buf_in+tcx_buf_len, L_frame ); + IF ( core > ACELP_CORE ) + { + Copy( tcx_buf, sig_in+L_frame, tcx_buf_len ); + } + Copy( sig+L_frame-tcx_buf_len, mem_in, tcx_buf_len ); + + /* Output buffer */ + sig_out = buf_out + L_frame; + Copy( mem_out, buf_out, L_frame ); + + /* TCX-LTP parameters: integer pitch, fractional pitch, gain */ + test(); + test(); + IF ( !(SideInfoOnly != 0 || tcxltp_on != 0) || EQ_16(core, ACELP_CORE)) + { + /* No LTP */ + pitch_int = 0; + move16(); + pitch_fr = 0; + move16(); + gain = 0; + move16(); + } + ELSE IF (bfi == 0) + { + /* LTP and good frame */ + IF (NE_16(L_frame, L_frame_core)) + { + tmp = div_s(L_frame, shl(L_frame_core, 2)); /* Q13 */ + tmp32 = L_mult0(add(imult1616(pitch_int, pitres), pitch_fr), tmp); /* Q13 */ + tmp = round_fx(L_shl(tmp32, 3)); /* Q0 */ + pitch_int = idiv1616U(tmp, pitres); + pitch_fr = sub(tmp, imult1616(pitch_int, pitres)); + } + test(); + test(); + IF ( EQ_32(bitrate, 48000)&&EQ_16(L_frame_core,L_FRAME16k)) + { + gain = mult_r(gain, 10486/*0.32f Q15*/); + } + ELSE IF ( EQ_32(bitrate, 48000)&&EQ_16(L_frame_core,512)) + { + gain = mult_r(gain, 13107/*0.40f Q15*/); + } + ELSE + { + gain = mult_r(gain, 20972/*0.64f Q15*/); + } + } + ELSE + { + /* PLC: [TCX: Fade-out] + * PLC: LTP and bad frame (concealment) */ + IF (pitres == *pitres_past) /* ensure consistent core SR to previous frame; otherwise, set gain to 0 */ + { + pitch_int = *pitch_int_past; + move16(); + pitch_fr = *pitch_fr_past; + move16(); + gain = shl(mult_r(*gain_past, damping), 1); + } + ELSE + { + gain = 0; + move16(); + } + } + + + IF ( SideInfoOnly != 0 ) + { + gain = 0; + move16(); + if ( bfi != 0 ) + { + *gain_past = 0; + move16(); + } + } + gain2 = gain; + move16(); + + IF (EQ_16(L_frame_core, L_FRAME)) + { + SWITCH ( L_frame ) + { + case L_FRAME8k: + filtIdx = 0; + move16(); + BREAK; + case L_FRAME16k: + filtIdx = 1; + move16(); + BREAK; + case L_FRAME32k: + filtIdx = 2; + move16(); + BREAK; + case L_FRAME48k: + filtIdx = 3; + move16(); + BREAK; + default: + assert(0); + } + } + ELSE IF (EQ_16(L_frame_core, L_FRAME16k)) + { + SWITCH ( L_frame ) + { + case L_FRAME8k: + filtIdx = 4; + move16(); + BREAK; + case L_FRAME16k: + filtIdx = 5; + move16(); + BREAK; + case L_FRAME32k: + filtIdx = 6; + move16(); + BREAK; + case L_FRAME48k: + filtIdx = 7; + move16(); + BREAK; + default: + assert(0); + } + } + ELSE IF (EQ_16(L_frame_core, 512)) + { + SWITCH ( L_frame ) + { + case L_FRAME8k: + filtIdx = 8; + move16(); + BREAK; + case L_FRAME16k: + filtIdx = 9; + move16(); + BREAK; + case L_FRAME32k: + filtIdx = 10; + move16(); + BREAK; + case L_FRAME48k: + filtIdx = 11; + move16(); + BREAK; + default: + assert(0); + } + } + ELSE + { + filtIdx = -1; + move16(); + } + + + /******** Previous-frame part ********/ + + tcx_ltp_synth_filter( sig_out, + sig_in, + delay, + *pitch_int_past, + *pitch_fr_past, + *gain_past, + *pitres_past, + NULL, + 0, + *filtIdx_past + ); + + /******** Transition part ********/ + + test(); + test(); + test(); + IF ( gain==0 && *gain_past==0 ) + { + Copy( sig_in+delay, sig_out+delay, L_transition ); + } + ELSE IF ( *gain_past==0 ) + { + tcx_ltp_synth_filter( sig_out+delay, + sig_in+delay, + L_transition, + pitch_int, + pitch_fr, + gain, + pitres, + NULL, + 1, + filtIdx + ); + } + ELSE IF ( gain==0 ) + { + tcx_ltp_synth_filter( sig_out+delay, + sig_in+delay, + L_transition, + *pitch_int_past, + *pitch_fr_past, + *gain_past, + *pitres_past, + NULL, + -1, + *filtIdx_past + ); + } + ELSE IF ( EQ_16(gain, *gain_past)&&EQ_16(pitch_int,*pitch_int_past)&&EQ_16(pitch_fr,*pitch_fr_past)) + { + tcx_ltp_synth_filter( sig_out+delay, + sig_in+delay, + L_transition, + pitch_int, + pitch_fr, + gain, + pitres, + NULL, + 0, + filtIdx + ); + } + ELSE + { + tcx_ltp_get_lpc( sig_out+delay-L_frame, L_frame, A, lpcorder ); + + tcx_ltp_get_zir( zir, L_transition, sig_out+delay-lpcorder, sig_in+delay-lpcorder, A, lpcorder, gain, pitch_int, pitch_fr, pitres, filtIdx ); + + tcx_ltp_synth_filter( sig_out+delay, + sig_in+delay, + L_transition, + pitch_int, + pitch_fr, + gain, + pitres, + zir, + 0, + filtIdx + ); + } + + /******** Current-frame part ********/ + + tcx_ltp_synth_filter( sig_out+(delay+L_transition), + sig_in+(delay+L_transition), + L_frame-(delay+L_transition), + pitch_int, + pitch_fr, + gain, + pitres, + NULL, + 0, + filtIdx + ); + + + /******** Output ********/ + + + /* copy to output */ + + Copy( sig_out, sig, L_frame ); + + /* Update */ + *pitch_int_past = pitch_int; + move16(); + *pitch_fr_past = pitch_fr; + move16(); + *gain_past = gain2; + move16(); + *filtIdx_past = filtIdx; + move16(); + *pitres_past = pitres; + Copy( sig_out, mem_out, L_frame ); + +} diff --git a/lib_com/tcx_mdct.c b/lib_com/tcx_mdct.c new file mode 100644 index 0000000..698b2b3 --- /dev/null +++ b/lib_com/tcx_mdct.c @@ -0,0 +1,219 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "cnst_fx.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "stl.h" + +static Word16 TCX_MDCT_GetScaleFactor(Word16 L, Word16 *factor_e) +{ + + Word16 factor; + + IF(EQ_16(L, NORM_MDCT_FACTOR)) + { + factor = 32767; + move16(); + *factor_e = 0; + move16(); + } + ELSE IF(EQ_16(L, 2*NORM_MDCT_FACTOR)) + { + factor = 23170; + move16(); + *factor_e = 0; + move16(); + } + ELSE IF(EQ_16(L, 4*NORM_MDCT_FACTOR)) + { + factor = 16384; + move16(); + *factor_e = 0; + move16(); + } + ELSE + { + + factor = mult_r(shl(L, 4), 26214 /*128.f / NORM_MDCT_FACTOR*/); /* 4Q11 */ + *factor_e = 4; + move16(); + + factor = ISqrt16(factor, factor_e); + } + + return factor; +} + +static Word16 TCX_MDCT_Inverse_GetScaleFactor(Word16 L, Word16 *factor_e) +{ + + Word16 factor; + + IF(EQ_16(L, NORM_MDCT_FACTOR)) + { + factor = 32767; + move16(); + *factor_e = 0; + move16(); + } + ELSE IF(EQ_16(L, 2*NORM_MDCT_FACTOR)) + { + factor = 23170; + move16(); + *factor_e = 1; + move16(); + } + ELSE IF(EQ_16(L, 4*NORM_MDCT_FACTOR)) + { + factor = 32767; + move16(); + *factor_e = 1; + move16(); + } + ELSE + { + factor = mult_r(shl(L, 4), 26214 /*128.f / NORM_MDCT_FACTOR*/); /* 4Q11 */ + *factor_e = 4; + move16(); + + factor = Sqrt16(factor, factor_e); + } + + return factor; +} + + +void TCX_MDCT(const Word16 *x, Word32 *y, Word16* y_e, Word16 l, Word16 m, Word16 r) +{ + + Word16 i; + Word16 factor, neg_factor; + Word16 factor_e; + + factor = TCX_MDCT_GetScaleFactor(add(add(shr(l, 1), m), shr(r, 1)), &factor_e); + *y_e = add(*y_e, factor_e); + + neg_factor = negate(factor); + + + /* Init */ + FOR(i=0; i +#include "options.h" +#include "cnst_fx.h" +#include "basop_util.h" +#include "rom_basop_util.h" +#include "prot_fx.h" +#include "stl.h" + +void mdct_window_sine(const PWord16 **window, const Word16 n) +{ + *window = getSineWindowTable(n); +} + + +extern const Word16 window_48kHz_fx[]; +extern const Word16 window_256kHz[]; +extern const Word16 window_8_16_32kHz_fx[]; + +void mdct_window_aldo( + Word16 *window1, + PWord16 *window1_trunc, + PWord16 *window2, + Word16 n +) +{ + Word16 i, n0, n1, n2, d, tmp; + const Word16 *p1, *p2; + + /* set table pointers and decimation factor */ + SWITCH (n) + { + case 320/2: + p1 = window_48kHz_fx + 2; + p2 = window_48kHz_fx + 1110 - 3; + d = 6; + BREAK; + case 512/2: + p1 = window_256kHz; + p2 = window_256kHz + 592 - 1; + d = 2; + BREAK; + case 640/2: + p1 = window_48kHz_fx + 1; + p2 = window_48kHz_fx + 1110 - 2; + d = 3; + BREAK; + case 1024/2: + p1 = window_256kHz; + p2 = window_256kHz + 592 - 1; + d = 1; + BREAK; + case 1280/2: + p1 = window_48kHz_fx + 1; + p2 = window_48kHz_fx + 1110 - 2; + d = 3; + BREAK; + case 1920/2: + p1 = window_48kHz_fx; + p2 = window_48kHz_fx + 1110 - 1; + d = 1; + BREAK; + default: + assert(0); + return; + } + + /* set lengths */ + n0 = shr(imult1616(n, 9), 5); + n1 = shr(imult1616(n, 23), 5); /* left slope length */ + n2 = shr(imult1616(n, 14), 5); /* right slope length */ + + /* first part (long slope) */ + IF (NE_16(n, 1280/2)) + { + FOR (i = 0; i < n0; i++) + { + *window1 = *p1; + move16(); + window1++; + p1 += d; + } + + tmp = shr(n, 1); + FOR ( ; i < tmp; i++) + { + window1_trunc->v.im = *p1; + move16(); + window1_trunc++; + p1 += d; + } + + test(); + if (EQ_16(n, 512/2)||EQ_16(n,320/2))p1++; + + FOR ( ; i < n1; i++) + { + window1_trunc--; + window1_trunc->v.re = *p1; + move16(); + p1 += d; + } + } + ELSE + { + const Word16 *pi = window_8_16_32kHz_fx; + + FOR (i = 0; i < n0; i+=2) + { + *window1 = *p1; + move16(); + window1++; + p1 += d; + + *window1 = *pi; + move16(); + window1++; + pi++; + } + + tmp = shr(n, 1); + FOR ( ; i < tmp; i+=2) + { + window1_trunc->v.im = *p1; + move16(); + window1_trunc++; + p1 += d; + + window1_trunc->v.im = *pi; + move16(); + window1_trunc++; + pi++; + } + + FOR ( ; i < n1; i+=2) + { + window1_trunc--; + window1_trunc->v.re = *pi; + move16(); + pi++; + + window1_trunc--; + window1_trunc->v.re = *p1; + move16(); + p1 += d; + } + } + + /* second part (short slope) */ + IF (NE_16(n, 1280/2)) + { + tmp = shr(n2, 1); + FOR (i = 0; i < tmp; i++) + { + window2->v.im = *p2; + move16(); + window2++; + p2 -= d; + } + + test(); + if (EQ_16(n, 512/2)||EQ_16(n,320/2))p2--; + + FOR ( ; i < n2; i++) + { + window2--; + window2->v.re = *p2; + move16(); + p2 -= d; + } + } + ELSE + { + const Word16 *pi = window_8_16_32kHz_fx + 370 - 1; + + tmp = shr(n2, 1); + FOR (i = 0; i < tmp; i+=2) + { + window2->v.im = *p2; + move16(); + window2++; + p2 -= d; + + window2->v.im = *pi; + move16(); + window2++; + pi--; + } + + FOR ( ; i < n2; i+=2) + { + window2--; + window2->v.re = *pi; + move16(); + pi--; + + window2--; + window2->v.re = *p2; + move16(); + p2 -= d; + } + } +} + diff --git a/lib_com/tcx_utils.c b/lib_com/tcx_utils.c new file mode 100644 index 0000000..e11be3b --- /dev/null +++ b/lib_com/tcx_utils.c @@ -0,0 +1,1593 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "stl.h" +#include "options.h" +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "rom_basop_util.h" +#include "basop_util.h" + +#define inv_int InvIntTable + + +Word16 getInvFrameLen(Word16 L_frame) /* returns 1/L_frame in Q21 format */ +{ + Word16 idx, s; + + s = norm_s(L_frame); + idx = shl(L_frame, s); + + assert((idx == 0x4000) || (idx == 0x4B00) || (idx == 0x5000) || (idx == 0x5A00) || (idx == 0x6000) || (idx == 0x6400) || (idx == 0x7800)); + + idx = mult_r(idx, 0x10); /* idx = shr(add(idx, 0x0400), 11); */ + idx = s_and(idx, 7); + + + return shl(L_frame_inv[idx], sub(s, 7)); +} + +static void tcx_get_windows( + TCX_config const * tcx_cfg, /* i: TCX configuration */ + Word16 left_mode, /* i: overlap mode of left window half */ + Word16 right_mode, /* i: overlap mode of right window half */ + Word16 *left_overlap, /* o: left overlap length */ + PWord16 const **left_win, /* o: left overlap window */ + Word16 *right_overlap, /* o: right overlap length */ + PWord16 const **right_win, /* o: right overlap window */ + Word8 fullband /* i: fullband flag */ +) +{ + IF (fullband == 0) + { + /* Left part */ + SWITCH (left_mode) + { + case TRANSITION_OVERLAP: /* ACELP->TCX transition */ + *left_overlap = tcx_cfg->tcx_mdct_window_trans_length; + move16(); + *left_win = tcx_cfg->tcx_mdct_window_trans; + BREAK; + case MIN_OVERLAP: + *left_overlap = tcx_cfg->tcx_mdct_window_min_length; + move16(); + *left_win = tcx_cfg->tcx_mdct_window_minimum; + BREAK; + case HALF_OVERLAP: + *left_overlap = tcx_cfg->tcx_mdct_window_half_length; + move16(); + *left_win = tcx_cfg->tcx_mdct_window_half; + BREAK; + case FULL_OVERLAP: + *left_overlap = tcx_cfg->tcx_mdct_window_length; + move16(); + *left_win = tcx_cfg->tcx_aldo_window_1_trunc; + BREAK; + default: + assert(!"Not supported overlap"); + } + + /* Right part */ + SWITCH (right_mode) + { + case MIN_OVERLAP: + *right_overlap = tcx_cfg->tcx_mdct_window_min_length; + move16(); + *right_win = tcx_cfg->tcx_mdct_window_minimum; + BREAK; + case HALF_OVERLAP: + *right_overlap = tcx_cfg->tcx_mdct_window_half_length; + move16(); + *right_win = tcx_cfg->tcx_mdct_window_half; + BREAK; + case FULL_OVERLAP: + *right_overlap = tcx_cfg->tcx_mdct_window_delay; + move16(); + *right_win = tcx_cfg->tcx_aldo_window_2; + BREAK; + default: + assert(!"Not supported overlap"); + } + } + ELSE + { + /* Left part */ + SWITCH (left_mode) + { + case TRANSITION_OVERLAP: /* ACELP->TCX transition */ + *left_overlap = tcx_cfg->tcx_mdct_window_trans_lengthFB; + move16(); + *left_win = tcx_cfg->tcx_mdct_window_transFB; + BREAK; + case MIN_OVERLAP: + *left_overlap = tcx_cfg->tcx_mdct_window_min_lengthFB; + move16(); + *left_win = tcx_cfg->tcx_mdct_window_minimumFB; + BREAK; + case HALF_OVERLAP: + *left_overlap = tcx_cfg->tcx_mdct_window_half_lengthFB; + move16(); + *left_win = tcx_cfg->tcx_mdct_window_halfFB; + BREAK; + case RECTANGULAR_OVERLAP: + *left_overlap = 0; + move16(); + *left_win = NULL; + BREAK; + case FULL_OVERLAP: + *left_overlap = tcx_cfg->tcx_mdct_window_lengthFB; + move16(); + *left_win = tcx_cfg->tcx_aldo_window_1_FB_trunc; + BREAK; + default: + assert(!"Not supported overlap"); + } + + /* Right part */ + SWITCH (right_mode) + { + case MIN_OVERLAP: + *right_overlap = tcx_cfg->tcx_mdct_window_min_lengthFB; + move16(); + *right_win = tcx_cfg->tcx_mdct_window_minimumFB; + BREAK; + case HALF_OVERLAP: + *right_overlap = tcx_cfg->tcx_mdct_window_half_lengthFB; + move16(); + *right_win = tcx_cfg->tcx_mdct_window_halfFB; + BREAK; + case RECTANGULAR_OVERLAP: + *right_overlap = 0; + move16(); + *right_win = NULL; + BREAK; + case FULL_OVERLAP: + *right_overlap = tcx_cfg->tcx_mdct_window_delayFB; + move16(); + *right_win = tcx_cfg->tcx_aldo_window_2_FB; + BREAK; + default: + assert(!"Not supported overlap"); + } + } +} + +static void tcx_windowing_analysis( + Word16 const *signal, /* i: signal vector */ + Word16 L_frame, /* i: frame length */ + Word16 left_overlap, /* i: left overlap length */ + PWord16 const *left_win, /* i: left overlap window */ + Word16 right_overlap, /* i: right overlap length */ + PWord16 const *right_win, /* i: right overlap window */ + Word16 *output /* o: windowed signal vector */ +) +{ + Word16 w, n; + + /* Left overlap */ + n = shr(left_overlap, 1); + FOR (w = 0; w < n; w++) + { + *output++ = mult_r(*signal++, left_win[w].v.im); + move16(); + } + FOR (w = 0; w < n; w++) + { + *output++ = mult_r(*signal++, left_win[n-1-w].v.re); + move16(); + } + + /* Non overlapping region */ + n = sub(L_frame, shr(add(left_overlap, right_overlap), 1)); + FOR (w = 0; w < n; w++) + { + *output++ = *signal++; + move16(); + } + + /* Right overlap */ + n = shr(right_overlap, 1); + FOR (w = 0; w < n; w++) + { + *output++ = mult_r(*signal++, right_win[w].v.re); + move16(); + } + FOR (w = 0; w < n; w++) + { + *output++ = mult_r(*signal++, right_win[n-1-w].v.im); + move16(); + } +} + +void WindowSignal( + TCX_config const *tcx_cfg, /* input: configuration of TCX */ + Word16 offset, /* input: left folding point offset relative to the input signal pointer */ + Word16 left_overlap_mode, /* input: overlap mode of left window half */ + Word16 right_overlap_mode, /* input: overlap mode of right window half */ + Word16 * left_overlap_length, /* output: TCX window left overlap length */ + Word16 * right_overlap_length, /* output: TCX window right overlap length */ + Word16 const in[], /* input: input signal */ + Word16 * L_frame, /* input/output: frame length */ + Word16 out[] /* output: output windowed signal */ + ,Word8 fullband /* input: fullband flag */ +) +{ + Word16 l, r; + PWord16 const * left_win; + PWord16 const * right_win; + + + /*-----------------------------------------------------------* + * Init * + *-----------------------------------------------------------*/ + + tcx_get_windows(tcx_cfg, left_overlap_mode, right_overlap_mode, &l, &left_win, &r, &right_win, fullband); + + /* Init lengths */ + + /* if past frame is ACELP */ + IF (EQ_16(left_overlap_mode, TRANSITION_OVERLAP)) + { + /* Increase frame size for 5ms */ + IF (fullband == 0) + { + *L_frame = add(*L_frame, tcx_cfg->tcx5Size); + move16(); + offset = negate(shr(tcx_cfg->tcx_mdct_window_trans_length, 1)); + } + ELSE + { + *L_frame = add(*L_frame, tcx_cfg->tcx5SizeFB); + move16(); + offset = negate(shr(tcx_cfg->tcx_mdct_window_trans_lengthFB, 1)); + } + } + + /*-----------------------------------------------------------* + * Windowing * + *-----------------------------------------------------------*/ + + tcx_windowing_analysis(in-shr(l,1)+offset, *L_frame, l, left_win, r, right_win, out); + + IF (EQ_16(left_overlap_mode, FULL_OVERLAP)) + { + /* fade truncated ALDO window to avoid discontinuities */ + Word16 i, tmp; + const PWord16 *p; + + p = tcx_cfg->tcx_mdct_window_minimum; + tmp = shr(tcx_cfg->tcx_mdct_window_min_length, 1); + IF (fullband != 0) + { + p = tcx_cfg->tcx_mdct_window_minimumFB; + tmp = shr(tcx_cfg->tcx_mdct_window_min_lengthFB, 1); + } + + FOR (i = 0; i < tmp; i++) + { + out[i] = mult_r(out[i], p[i].v.im); + move16(); + } + FOR (i = 0; i < tmp; i++) + { + out[i+tmp] = mult_r(out[i+tmp], p[tmp-1-i].v.re); + move16(); + } + } + + *left_overlap_length = l; + move16(); + *right_overlap_length = r; + move16(); + +} + +void tcx_windowing_synthesis_current_frame( + Word16 *signal, /* i/o: signal vector */ + const PWord16 *window, /* i: TCX window vector */ + const PWord16 *window_half, /* i: TCX window vector for half-overlap window */ + const PWord16 *window_min, /* i: TCX minimum overlap window */ + Word16 window_length, /* i: TCX window length */ + Word16 window_half_length, /* i: TCX half window length */ + Word16 window_min_length, /* i: TCX minimum overlap length */ + Word16 left_rect, /* i: left part is rectangular */ + Word16 left_mode, /* i: overlap mode of left window half */ + Word16 *acelp_zir, /* i: acelp ZIR */ + Word16 *old_syn, + Word16 *syn_overl, + Word16 *A_zir, + const PWord16 *window_trans, + Word16 acelp_zir_len, + Word16 acelp_mem_len, + Word16 last_core_bfi, /* i : last core */ + Word8 last_is_cng + ,Word16 fullbandScale +) +{ + + Word16 i, overlap, n, tmp, tmp2; + Word16 tmp_buf[L_FRAME_MAX/2]; + Word32 L_tmp; + + /* Init */ + + overlap = shr(window_length, 1); + + /* Past-frame is TCX concealed as CNG and current-frame is TCX */ + test(); + test(); + test(); + test(); + IF ( EQ_16(last_is_cng, 1)&&left_rect==0) + { + IF (!fullbandScale) + { + set16_fx(acelp_zir, 0, acelp_zir_len); + E_UTIL_synthesis(0, A_zir, acelp_zir, acelp_zir, acelp_zir_len, signal+overlap+acelp_mem_len-M, 0, M); + } + ELSE + { + lerp(acelp_zir, tmp_buf, acelp_zir_len, idiv1616U(shl(acelp_zir_len, LD_FSCALE_DENOM), fullbandScale)); + acelp_zir = tmp_buf; + } + + FOR (i = 0; i < acelp_zir_len; i++) + { + /*signal[i] *= (float)(i)/(float)(acelp_zir_len); + signal[i] += acelp_zir[i]*(float)(acelp_zir_len-i)/(float)(acelp_zir_len);*/ + move16(); + signal[i] = add(mult_r(signal[i], div_s(i, acelp_zir_len)), mult_r(acelp_zir[i], div_s(sub(acelp_zir_len, i), acelp_zir_len))); + } + } + /* Rectangular window (past-frame is ACELP) */ + ELSE IF ( EQ_16(left_rect, 1)&&last_core_bfi==ACELP_CORE) + { + tmp = sub(overlap,acelp_mem_len); + FOR (i=0; i< tmp ; i++) + { + move16(); + signal[i] = 0; + } + + IF (fullbandScale == 0) + { + + tmp = shl(acelp_mem_len, 1); + + /*OLA with ACELP*/ + FOR (i = 0; i < acelp_mem_len; i++) + { + + /*window decoded TCX with aliasing*/ + tmp2 = mult_r(signal[i+overlap-acelp_mem_len], window_trans[i].v.im); + + /*Time TDAC: 1)forward part of ACELP*/ + tmp2 = add(tmp2, mult_r(old_syn[acelp_zir_len-tmp+i], mult_r(window_trans[i].v.re, window_trans[i].v.re))); + + /*Time TDAC: 1)reward part of ACELP*/ + tmp2 = add(tmp2, mult_r(old_syn[acelp_zir_len-i-1], mult_r(window_trans[i].v.im, window_trans[i].v.re))); + + move16(); + signal[i+overlap-acelp_mem_len] = tmp2; + } + FOR ( ; i < tmp; i++) + { + + /*window decoded TCX with aliasing*/ + tmp2 = mult_r(signal[i+overlap-acelp_mem_len], window_trans[tmp-1-i].v.re); + + /*Time TDAC: 1)forward part of ACELP*/ + tmp2 = add(tmp2, mult_r(old_syn[acelp_zir_len-tmp+i], mult_r(window_trans[tmp-1-i].v.im, window_trans[tmp-1-i].v.im))); + + /*Time TDAC: 1)reward part of ACELP*/ + tmp2 = add(tmp2, mult_r(old_syn[acelp_zir_len-i-1], mult_r(window_trans[tmp-1-i].v.re, window_trans[tmp-1-i].v.im))); + + move16(); + signal[i+overlap-acelp_mem_len] = tmp2; + } + + FOR (i=0; i=0; i--) + { + L_tmp = L_mult(acelp_zir[i], 13107); + L_tmp = L_mac(L_tmp, acelp_zir[i+1], 11469); + acelp_zir[i] = mac_r(L_tmp, acelp_zir[i+2], 8192); + move16(); + } + } + } + + FOR (i = 0; i < acelp_zir_len; i++) + { + /*remove reconstructed ZIR and add ACELP ZIR*/ + move16(); + signal[i+overlap+acelp_mem_len] = sub(signal[i+overlap+acelp_mem_len], mult_r(acelp_zir[i], div_s(sub(acelp_zir_len, i), acelp_zir_len))); + } + } + /* Rectangular window (past-frame is TCX) */ + ELSE IF ( left_rect==1 && last_core_bfi!=ACELP_CORE ) + { + n = add(overlap, acelp_mem_len); + FOR (i=0; ican be skipped*/ + +} + +void tcx_windowing_synthesis_past_frame( + Word16 *signal, /* i/o: signal vector */ + const PWord16 *window, /* i: TCX window vector */ + const PWord16 *window_half, /* i: TCX window vector for half-overlap window */ + const PWord16 *window_min, /* i: TCX minimum overlap window */ + Word16 window_length, /* i: TCX window length */ + Word16 window_half_length, /* i: TCX half window length */ + Word16 window_min_length, /* i: TCX minimum overlap length */ + Word16 right_mode /* i: overlap mode (left_mode of current frame) */ +) +{ + + Word16 i, n; + + + IF ( EQ_16(right_mode, 2)) /* min. overlap */ + { + signal += shr(sub(window_length, window_min_length), 1); + + n = shr(window_min_length, 1); + FOR (i = 0; i < n; i++) + { + *signal = mult_r(*signal, window_min[i].v.re); + move16(); + signal++; + } + FOR (i = 0; i < n; i++) + { + *signal = mult_r(*signal, window_min[n-1-i].v.im); + move16(); + signal++; + } + + n = shr(sub(window_length, window_min_length), 1); + FOR (i = 0; i < n; i++) + { + *signal = 0; + move16(); + signal++; + } + } + ELSE IF ( EQ_16(right_mode,3)) /* half OL */ + { + Word16 w; + + i = shr(sub(window_length, window_half_length),1); + n = shr(window_half_length,1); + FOR (w=0 ; w < n; w++) + { + signal[i] = mult_r(signal[i], window_half[w].v.re); + move16(); + i = add(i,1); + } + FOR (w=0 ; w < n; w++) + { + signal[i] = mult_r(signal[i], window_half[window_half_length/2-1-w].v.im); + move16(); + i = add(i,1); + } + FOR (; i < window_length; i++) + { + move16(); + signal[i] = 0; + } + } + ELSE /* normal full/maximum overlap */ + { + + n = shr(window_length,1); + FOR (i = 0; i < n; i++) + { + move16(); + signal[i] = mult_r(signal[i], window[i].v.re); + move16(); + signal[window_length-1-i] = mult_r(signal[window_length-1-i], window[i].v.im); + } + } + +} + +void lpc2mdct(Word16 *lpcCoeffs, Word16 lpcOrder, + Word16 *mdct_gains, Word16 *mdct_gains_exp, + Word16 *mdct_inv_gains, Word16 *mdct_inv_gains_exp) +{ + Word32 ComplexData[2*FDNS_NPTS]; + Word16 i, j, k, sizeN, step, scale, s, tmp16; + Word16 g, g_e, ig, ig_e; + Word32 tmp32; + const PWord16 *ptwiddle; + Word32 workBuffer[2*BASOP_CFFT_MAX_LENGTH]; + sizeN = shl(FDNS_NPTS, 1); + BASOP_getTables(NULL, &ptwiddle, &step, sizeN); + /*ODFT*/ + assert(lpcOrder < FDNS_NPTS); + /* pre-twiddle */ + FOR (i=0; i<=lpcOrder; i++) + { + ComplexData[2*i] = L_mult(lpcCoeffs[i], ptwiddle->v.re); + move32(); + ComplexData[2*i+1] = L_negate(L_mult(lpcCoeffs[i], ptwiddle->v.im)); + move32(); + ptwiddle += step; + } + /* zero padding */ + FOR ( ; i 0) pg = shr(pg, tmp); + if (tmp < 0) g = shl(g, tmp); + e = s_max(gains_exp[j], gains_exp[jp]); + + tmp = mac_r(L_mult(pg, 12288/*0.375f Q15*/), g, 20480/*0.625f Q15*/); + x[i] = L_shl(Mpy_32_16_1(x[i], tmp), e); + move32(); + + tmp = mac_r(L_mult(pg, 4096/*0.125f Q15*/), g, 28672/*0.875f Q15*/); + x[i+1] = L_shl(Mpy_32_16_1(x[i+1], tmp), e); + move32(); + + /* common exponent for g and ng */ + g = gains[j]; + move16(); + tmp = sub(gains_exp[j], gains_exp[jn]); + if (tmp > 0) ng = shr(ng, tmp); + if (tmp < 0) g = shl(g, tmp); + e = s_max(gains_exp[j], gains_exp[jn]); + + tmp = mac_r(L_mult(g, 28672/*0.875f Q15*/), ng, 4096/*0.125f Q15*/); + x[i+2] = L_shl(Mpy_32_16_1(x[i+2], tmp), e); + move32(); + + tmp = mac_r(L_mult(g, 20480/*0.625f Q15*/), ng, 12288/*0.375f Q15*/); + x[i+3] = L_shl(Mpy_32_16_1(x[i+3], tmp), e); + move32(); + + jp = j; + move16(); + j = jn; + move16(); + jn = s_min(add(jn, 1), FDNS_NPTS-1); + } + } + ELSE IF (EQ_16(k, 5)) + { + jp = 0; + move16(); + j = 0; + move16(); + jn = 1; + move16(); + + FOR (i = 0; i < lg; i += 5) + { + pg = gains[jp]; + move16(); + g = gains[j]; + move16(); + ng = gains[jn]; + move16(); + + /* common exponent for pg and g */ + tmp = sub(gains_exp[j], gains_exp[jp]); + if (tmp > 0) pg = shr(pg, tmp); + if (tmp < 0) g = shl(g, tmp); + e = s_max(gains_exp[j], gains_exp[jp]); + + tmp = mac_r(L_mult(pg, 13107/*0.40f Q15*/), g, 19661/*0.60f Q15*/); + x[i] = L_shl(Mpy_32_16_1(x[i], tmp), e); + move32(); + + tmp = mac_r(L_mult(pg, 6554/*0.20f Q15*/), g, 26214/*0.80f Q15*/); + x[i+1] = L_shl(Mpy_32_16_1(x[i+1], tmp), e); + move32(); + + + x[i+2] = L_shl(Mpy_32_16_1(x[i+2], gains[j]), gains_exp[j]); + move32(); + + /* common exponent for g and ng */ + g = gains[j]; + move16(); + tmp = sub(gains_exp[j], gains_exp[jn]); + if (tmp > 0) ng = shr(ng, tmp); + if (tmp < 0) g = shl(g, tmp); + e = s_max(gains_exp[j], gains_exp[jn]); + + tmp = mac_r(L_mult(g, 26214/*0.80f Q15*/), ng, 6554/*0.20f Q15*/); + x[i+3] = L_shl(Mpy_32_16_1(x[i+3], tmp), e); + move32(); + + tmp = mac_r(L_mult(g, 19661/*0.60f Q15*/), ng, 13107/*0.40f Q15*/); + x[i+4] = L_shl(Mpy_32_16_1(x[i+4], tmp), e); + move32(); + + jp = j; + move16(); + j = jn; + move16(); + jn = s_min(add(jn, 1), FDNS_NPTS-1); + } + } + ELSE /* no interpolation */ + { + FOR (i = 0; i < FDNS_NPTS; i++) + { + FOR (l = 0; l < k; l++) + { + *x = L_shl(Mpy_32_16_1(*x, *gains), *gains_exp); + move32(); + x++; + } + + gains++; + gains_exp++; + } + } + } + +} + +void PsychAdaptLowFreqDeemph(Word32 x[], + const Word16 lpcGains[], const Word16 lpcGains_e[], + Word16 lf_deemph_factors[] + ) +{ + Word16 i; + Word16 max, max_e, fac, min, min_e, tmp, tmp_e; + Word32 L_tmp; + + + + assert(lpcGains[0] >= 0x4000); + + max = lpcGains[0]; + move16(); + max_e = lpcGains_e[0]; + move16(); + min = lpcGains[0]; + move16(); + min_e = lpcGains_e[0]; + move16(); + + /* find minimum (min) and maximum (max) of LPC gains in low frequencies */ + FOR (i = 1; i < 9; i++) + { + IF (compMantExp16Unorm(lpcGains[i], lpcGains_e[i], min, min_e) < 0) + { + min = lpcGains[i]; + move16(); + min_e = lpcGains_e[i]; + move16(); + } + + IF (compMantExp16Unorm(lpcGains[i], lpcGains_e[i], max, max_e) > 0) + { + max = lpcGains[i]; + move16(); + max_e = lpcGains_e[i]; + move16(); + } + } + + min_e = add(min_e, 5); /* min *= 32.0f; */ + + test(); + IF ((compMantExp16Unorm(max, max_e, min, min_e) < 0) && (min > 0)) + { + /* fac = tmp = (float)pow(max / min, 0.0078125f); */ + tmp_e = min_e; + move16(); + tmp = Inv16(min, &tmp_e); + L_tmp = L_shl(L_mult(tmp, max), add(tmp_e, max_e)); /* Q31 */ + L_tmp = BASOP_Util_Log2(L_tmp); /* Q25 */ + L_tmp = L_shr(L_tmp, 7); /* 0.0078125f = 1.f/(1<<7) */ + L_tmp = BASOP_Util_InvLog2(L_tmp); /* Q31 */ + tmp = round_fx(L_tmp); /* Q15 */ + fac = tmp; /* Q15 */ move16(); + + /* gradual lowering of lowest 32 bins; DC is lowered by (max/tmp)^1/4 */ + FOR (i = 31; i >= 0; i--) + { + x[i] = Mpy_32_16_1(x[i], fac); + move32(); + if (lf_deemph_factors != NULL) + { + lf_deemph_factors[i] = mult_r(lf_deemph_factors[i], fac); + move16(); + } + fac = mult_r(fac, tmp); + } + } + +} + +void AdaptLowFreqDeemph(Word32 x[], Word16 x_e, + Word16 tcx_lpc_shaped_ari, + Word16 lpcGains[], Word16 lpcGains_e[], + const Word16 lg, + Word16 lf_deemph_factors[] + ) +{ + + Word16 i, i_max, i_max_old, lg_4; + Word32 v2, v4, tmp32; + + tmp32 = 0; /* to avoid compilation warnings */ + + + IF (tcx_lpc_shaped_ari == 0) + { + v2 = L_shl(2, sub(31, x_e)); /* 2.0 */ + v4 = L_shl(v2, 1); /* 4.0 */ + lg_4 = shr(lg, 2); /* lg/4 */ + + /* 1. find first magnitude maximum in lower quarter of spectrum */ + i_max = -1; + move16(); + + FOR (i = 0; i < lg_4; i++) + { + IF (GE_32(L_abs(x[i]), v4)) + { + + /* Debug initialization to catch illegal x[i] values. */ + tmp32 = 0; + + if (x[i] < 0) tmp32 = L_add(x[i], v2); + if (x[i] > 0) tmp32 = L_sub(x[i], v2); + + assert(tmp32 != 0); + + x[i] = tmp32; + move32(); + i_max = i; + move16(); + BREAK; + } + } + + /* 2. expand value range of all xi up to i_max: two extra steps */ + FOR (i = 0; i < i_max; i++) + { + x[i] = L_shr(x[i], 1); + move32(); + lf_deemph_factors[i] = shr(lf_deemph_factors[i], 1); + move16(); + } + + /* 3. find first magnitude maximum in lower quarter of spectrum */ + i_max_old = i_max; + move16(); + + IF (i_max_old >= 0) + { + i_max = -1; + move16(); + + FOR (i = 0; i < lg_4; i++) + { + IF (GE_32(L_abs(x[i]), v4)) + { + assert(x[i] != 0); + if (x[i] < 0) tmp32 = L_add(x[i], v2); + if (x[i] >= 0) tmp32 = L_sub(x[i], v2); + x[i] = tmp32; + move32(); + i_max = i; + move16(); + BREAK; + } + } + } + + /* 4. expand value range of all xi up to i_max: two extra steps */ + FOR (i = 0; i < i_max; i++) + { + x[i] = L_shr(x[i], 1); + move32(); + lf_deemph_factors[i] = shr(lf_deemph_factors[i], 1); + move16(); + } + + /* 5. always expand two lines; lines could be at index 0 and 1! */ + i_max = s_max(i_max, i_max_old); + i = add(i_max, 1); + + IF (x[i] < 0) + { + tmp32 = L_sub(x[i], L_negate(v4)); + + if (tmp32 > 0) + { + lf_deemph_factors[i] = shr(lf_deemph_factors[i], 1); + move16(); + } + if (tmp32 <= 0) + { + x[i] = L_add(x[i], v2); + move32(); + } + if (tmp32 > 0) + { + x[i] = L_shr(x[i], 1); + move32(); + } + } + ELSE + { + tmp32 = L_sub(x[i], v4); + + if (tmp32 < 0) + { + lf_deemph_factors[i] = shr(lf_deemph_factors[i], 1); + move16(); + } + if (tmp32 >= 0) + { + x[i] = L_sub(x[i], v2); + move32(); + } + if (tmp32 < 0) + { + x[i] = L_shr(x[i], 1); + move32(); + } + } + i = add(i, 1); + + IF (x[i] < 0) + { + tmp32 = L_sub(x[i], L_negate(v4)); + + if (tmp32 > 0) + { + lf_deemph_factors[i] = shr(lf_deemph_factors[i], 1); + move16(); + } + if (tmp32 <= 0) + { + x[i] = L_add(x[i], v2); + move32(); + } + if (tmp32 > 0) + { + x[i] = L_shr(x[i], 1); + move32(); + } + } + ELSE + { + tmp32 = L_sub(x[i], v4); + + if (tmp32 < 0) + { + lf_deemph_factors[i] = shr(lf_deemph_factors[i], 1); + move16(); + } + if (tmp32 >= 0) + { + x[i] = L_sub(x[i], v2); + move32(); + } + if (tmp32 < 0) + { + x[i] = L_shr(x[i], 1); + move32(); + } + } + } + ELSE /*if(!tcx_lpc_shaped_ari)*/ + { + PsychAdaptLowFreqDeemph(x, lpcGains, lpcGains_e, lf_deemph_factors); + }/*if(!tcx_lpc_shaped_ari)*/ + +} + +void tcx_noise_filling( + Word32 *Q, + Word16 Q_e, + Word16 seed, + Word16 iFirstLine, + Word16 lowpassLine, + Word16 nTransWidth, + Word16 L_frame, + Word16 tiltCompFactor, + Word16 fac_ns, + Word16 *infoTCXNoise +) +{ + Word16 i, m, segmentOffset; + Word16 win; /* window coefficient */ + Word16 tilt_factor; + Word32 nrg; + Word16 tmp1, tmp2, s; + Word32 tmp32; + + + /* get inverse frame length */ + tmp1 = getInvFrameLen(L_frame); + + /* tilt_factor = (float)pow(max(0.375f, tiltCompFactor), 1.0f/(float)L_frame); */ + tmp32 = BASOP_Util_Log2(L_deposit_h(s_max(0x3000, tiltCompFactor))); /* 6Q25 */ + tmp32 = L_shr(Mpy_32_16_1(tmp32, tmp1), 6); + BASOP_SATURATE_WARNING_OFF; + tilt_factor = round_fx(BASOP_Util_InvLog2(tmp32)); + BASOP_SATURATE_WARNING_ON; + + /* find last nonzero line below iFirstLine, use it as start offset */ + tmp1 = shr(iFirstLine, 1); + FOR (i = iFirstLine; i > tmp1; i--) + { + IF (Q[i] != 0) + { + BREAK; + } + } + /* fac_ns *= (float)pow(tilt_factor, (float)i); */ + FOR (m = 0; m < i; m++) + { + fac_ns = mult_r(fac_ns, tilt_factor); + } + + nrg = L_deposit_l(1); + win = 0; + move16(); + i = add(i, 1); + segmentOffset = i; + move16(); + + FOR (; i < lowpassLine; i++) + { + fac_ns = mult_r(fac_ns, tilt_factor); + + IF (Q[i] != 0) + { + IF (win > 0) + { + /* RMS-normalize current noise-filled segment */ + tmp1 = BASOP_Util_Divide3216_Scale(nrg, sub(i, segmentOffset), &s); /* mean */ + s = add(s, 9-15); /* scaling */ + tmp1 = ISqrt16(tmp1, &s); /* 1/RMS */ + tmp1 = mult_r(tmp1, inv_int[nTransWidth]); /* compensate win */ + s = add(s, sub(16, Q_e)); /* scaling */ + + tmp2 = sub(i, win); + IF (LT_16(segmentOffset, tmp2)) + { + FOR (m = segmentOffset; m < tmp2; m++) + { + Q[m] = L_shl(Mpy_32_16_1(Q[m], tmp1), s); + move32(); + } + } + + tmp2 = mult(tmp1, inv_int[nTransWidth]); + tmp1 = extract_l(L_mult0(tmp2, win)); + FOR (m = sub(i, win); m < i; m++) + { + Q[m] = L_shl(Mpy_32_16_1(Q[m], tmp1), s); + move32(); + win = sub(win, 1); + tmp1 = sub(tmp1, tmp2); + } + + nrg = L_deposit_l(1); /* start new segment: reset noise segment energy */ + } + segmentOffset = add(i, 1); + } + ELSE /* line is zero, so fill line and update window and energy */ + { + if (LT_16(win, nTransWidth)) + { + win = add(win, 1); + } + + seed = own_random2_fx(seed); + Q[i] = L_mult0(mult(seed, fac_ns), win); + move32(); + + tmp1 = shr(seed, 4); + nrg = L_mac0(nrg, tmp1, tmp1); /* sum up energy of current noise segment */ + + if(infoTCXNoise) /* set noiseflags for IGF */ + { + infoTCXNoise[i] = 1; + move16(); + } + } + } + + IF (win > 0) + { + /* RMS-normalize uppermost noise-filled segment */ + tmp1 = BASOP_Util_Divide3216_Scale(nrg, sub(lowpassLine, segmentOffset), &s); /* mean */ + s = add(s, 9-15); /* compensate energy scaling */ + tmp1 = ISqrt16(tmp1, &s); /* 1/RMS */ + tmp1 = mult_r(tmp1, inv_int[nTransWidth]); /* compensate win */ + s = add(s, sub(16, Q_e)); /* compensate noise scaling */ + + FOR (m = segmentOffset; m < lowpassLine; m++) + { + Q[m] = L_shl(Mpy_32_16_1(Q[m], tmp1), s); + move32(); + } + } + +} + + + +/*--------------------------------------------------------------- + * Residual Quantization + *--------------------------------------------------------------*/ + + +void InitTnsConfigs(Word32 nSampleRate, Word16 L_frame, + STnsConfig tnsConfig[2][2] + ,Word16 igfStopFreq + ,Word32 bitrate + ) +{ + IF (GT_32(bitrate,ACELP_32k)) + { + InitTnsConfiguration(nSampleRate, shr(L_frame,1), &tnsConfig[0][0], igfStopFreq, bitrate); + } + InitTnsConfiguration(nSampleRate, L_frame, &tnsConfig[1][0], igfStopFreq, bitrate); + InitTnsConfiguration(nSampleRate, add(L_frame, shr(L_frame,2)), &tnsConfig[1][1], igfStopFreq, bitrate); +} + + +void SetTnsConfig(TCX_config * tcx_cfg, Word8 isTCX20, Word8 isAfterACELP) +{ + move16(); + tcx_cfg->pCurrentTnsConfig = &tcx_cfg->tnsConfig[isTCX20][isAfterACELP]; + assert(tcx_cfg->pCurrentTnsConfig != NULL); +} + + +void tcx_get_gain(Word32 *x, /* i: spectrum 1 */ + Word16 x_e, /* i: spectrum 1 exponent */ + Word32 *y, /* i: spectrum 2 */ + Word16 y_e, /* i: spectrum 2 exponent */ + Word16 n, /* i: length */ + Word16 *gain, /* o: gain */ + Word16 *gain_e, /* o: gain exponent */ + Word32 *en_y, /* o: energy of y (optional) */ + Word16 *en_y_e /* o: energy of y exponent (optional) */ + ) +{ + Word32 maxX, minX, maxY, minY; + Word32 corr, ener; + Word16 sx, sy, corr_e, ener_e; + Word16 i, tmp; + + + maxX = L_deposit_l(1); + maxY = L_deposit_l(1); + minX = L_deposit_l(-1); + minY = L_deposit_l(-1); + FOR (i = 0; i < n; i++) + { + if (x[i] > 0) maxX = L_max(maxX, x[i]); + if (x[i] < 0) minX = L_min(minX, x[i]); + + if (y[i] > 0) maxY = L_max(maxY, y[i]); + if (y[i] < 0) minY = L_min(minY, y[i]); + } + sx = s_min(norm_l(maxX), norm_l(minX)); + sy = s_min(norm_l(maxY), norm_l(minY)); + sx = sub(sx, 4); + sy = sub(sy, 4); + + ener = L_deposit_l(0); + corr = L_deposit_l(0); + FOR (i = 0; i < n; i++) + { + tmp = round_fx(L_shl(y[i], sy)); + ener = L_mac0(ener, tmp, tmp); + corr = L_mac0(corr, tmp, round_fx(L_shl(x[i], sx))); + } + + if (ener == 0) ener = L_deposit_l(1); + + ener_e = add(shl(sub(y_e, sy), 1), 1); + corr_e = add(sub(add(x_e, y_e), add(sx, sy)), 1); + + tmp = sub(norm_l(corr), 1); + corr = L_shl(corr, tmp); + corr_e = sub(corr_e, tmp); + + tmp = norm_l(ener); + ener = L_shl(ener, tmp); + ener_e = sub(ener_e, tmp); + + tmp = div_s(abs_s(round_fx(corr)), round_fx(ener)); + if (corr < 0) tmp = negate(tmp); + + *gain = tmp; + move16(); + *gain_e = sub(corr_e, ener_e); + move16(); + + if (en_y != NULL) + { + *en_y = ener; + move32(); + } + if (en_y_e != NULL) + { + *en_y_e = ener_e; + move16(); + } + +} + +void init_TCX_config(TCX_config *tcx_cfg, + Word16 L_frame, + Word16 fscale + ,Word16 L_frameTCX + ,Word16 fscaleFB + ) +{ + /* Initialize the TCX MDCT windows */ + tcx_cfg->tcx_mdct_window_length = extract_l(L_shr(L_mult0(L_LOOK_12k8, fscale), LD_FSCALE_DENOM)); + tcx_cfg->tcx_mdct_window_delay = tcx_cfg->tcx_mdct_window_length; + move16(); + + tcx_cfg->tcx_mdct_window_half_length = extract_l(L_shr(L_mult0(L_LOOK_12k8 - NS2SA(12800, 5000000L), fscale), LD_FSCALE_DENOM)); + + tcx_cfg->tcx_mdct_window_min_length = shr(L_frame, 4); /* 1.25ms */ + tcx_cfg->tcx_mdct_window_trans_length = shr(L_frame, 4); /* 1.25ms */ + + tcx_cfg->tcx5Size = shr(L_frame, 2); /* 5ms */ + + tcx_cfg->tcx_mdct_window_lengthFB = extract_l(L_shr(L_mult0(L_LOOK_12k8, fscaleFB), LD_FSCALE_DENOM)); + tcx_cfg->tcx_mdct_window_delayFB = tcx_cfg->tcx_mdct_window_lengthFB; + move16(); + + tcx_cfg->tcx_mdct_window_half_lengthFB = extract_l(L_shr(L_mult0(L_LOOK_12k8 - NS2SA(12800, 5000000L), fscaleFB), LD_FSCALE_DENOM)); + + tcx_cfg->tcx_mdct_window_min_lengthFB = shr(L_frameTCX, 4); /* 1.25ms */ + tcx_cfg->tcx_mdct_window_trans_lengthFB = shr(L_frameTCX, 4); /* 1.25ms */ + + tcx_cfg->tcx5SizeFB = shr(L_frameTCX, 2); /* 5ms */ + + mdct_window_sine( &tcx_cfg->tcx_mdct_window, tcx_cfg->tcx_mdct_window_length ); + mdct_window_sine( &tcx_cfg->tcx_mdct_window_half, tcx_cfg->tcx_mdct_window_half_length ); + mdct_window_sine( &tcx_cfg->tcx_mdct_window_minimum, tcx_cfg->tcx_mdct_window_min_length ); + mdct_window_sine( &tcx_cfg->tcx_mdct_window_trans, tcx_cfg->tcx_mdct_window_trans_length ); + + mdct_window_sine( &tcx_cfg->tcx_mdct_windowFB, tcx_cfg->tcx_mdct_window_lengthFB ); + mdct_window_sine( &tcx_cfg->tcx_mdct_window_halfFB, tcx_cfg->tcx_mdct_window_half_lengthFB ); + mdct_window_sine( &tcx_cfg->tcx_mdct_window_minimumFB, tcx_cfg->tcx_mdct_window_min_lengthFB ); + mdct_window_sine( &tcx_cfg->tcx_mdct_window_transFB, tcx_cfg->tcx_mdct_window_trans_lengthFB ); + + /*ALDO windows for MODE2*/ + mdct_window_aldo(tcx_cfg->tcx_aldo_window_1, tcx_cfg->tcx_aldo_window_1_trunc, tcx_cfg->tcx_aldo_window_2, L_frame); + mdct_window_aldo(tcx_cfg->tcx_aldo_window_1_FB, tcx_cfg->tcx_aldo_window_1_FB_trunc, tcx_cfg->tcx_aldo_window_2_FB, L_frameTCX); +} + diff --git a/lib_com/tec_com.c b/lib_com/tec_com.c new file mode 100644 index 0000000..6611489 --- /dev/null +++ b/lib_com/tec_com.c @@ -0,0 +1,1511 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "stl.h" +#include "basop_util.h" +#include "prot_fx.h" +#include "cnst_fx.h" + + +#ifndef EPS +#define EPS ( 1e-12f) +#endif + +#define ENV_SCALE_OFFSET_1_FX 1515133568l/*90.309f/128.0 Q31*/ /* 10*log10(2^30) */ /* scaled by 1/128.0 */ +#define MAX_TEC_BW_LO (12) +#define MAX_NB_TEC_LOW_BAND ( 3) + +static const Word16 TecSmoothingDeg = 5; +static const Word16 NbTecLowBand = 3; + +#define LOBUF_NO_SMOOTHING_MODE 1 + +void +resetTecDec_Fx( + HANDLE_TEC_DEC_FX hTecDec +) +{ + + set16_fx(hTecDec->pGainTemp_m, 0, CLDFB_NO_COL_MAX); + set16_fx(hTecDec->pGainTemp_e, 0, CLDFB_NO_COL_MAX); + + set16_fx(hTecDec->loBuffer, 0, CLDFB_NO_COL_MAX + MAX_TEC_SMOOTHING_DEG); + + return; +} + + +void +resetTecEnc_Fx(HANDLE_TEC_ENC_FX hTecEnc, Word16 flag) +{ + IF (flag == 0) + { + set16_fx(hTecEnc->loBuffer, 0, CLDFB_NO_COL_MAX + MAX_TEC_SMOOTHING_DEG + DELAY_TEMP_ENV_BUFF_TEC); + set16_fx(hTecEnc->loTempEnv, 0, CLDFB_NO_COL_MAX); + set16_fx(hTecEnc->loTempEnv_ns, 0, CLDFB_NO_COL_MAX); + set16_fx(hTecEnc->hiTempEnv, 0, CLDFB_NO_COL_MAX + DELAY_TEMP_ENV_BUFF_TEC + EXT_DELAY_HI_TEMP_ENV); + } + ELSE + { + set16_fx(hTecEnc->loBuffer, 0, MAX_TEC_SMOOTHING_DEG); + } + return; +} + + +static Word32 calcVar_Fix(const Word32 in[], Word32 len, Word32* x) +{ + Word32 xx; + Word32 i; + Word16 exp1; + Word32 ans; + Word16 r_sft; + Word32 tmpX; + + xx = L_deposit_l(0); + *x = L_deposit_l(0); + FOR(i=0; i 0 ) + { + IF ( GE_32(tmp32,1006632960l/*0.46875 Q31*/)) + { + s = add(s,sub(WORD32_BITS,norm_l(BASOP_Util_InvLog2(L_sub(tmp32,1006632960l/*0.46875 Q31*/))))); + s = add(s,30); + } + ELSE + { + s = add(s,sub(WORD32_BITS,norm_l(BASOP_Util_InvLog2(tmp32)))); + } + + /* scalefactor for logarithmic domain */ + logScaleFactor = L_shl(L_mult0(512/*1.0/(1<= BW_LO); + + calcLoBufferDec_Fx( + pCldfbRealSrc_Fx, + pCldfbImagSrc_Fx, + loBuffer_Fx+MAX_TEC_SMOOTHING_DEG, + startPos, + stopPos, + bandOffset, + 15 - cldfb_exp + ); + + IF (code > 0) + { + IF (NE_16(code, 2)) + { + calcLoTempEnv_TBE_Fx(loBuffer_Fx + MAX_TEC_SMOOTHING_DEG, noCols, + loTempEnv_Fx, 19531/*0.5f * ratioHiLoFacDec Q15*/); + } + ELSE + { + calcLoTempEnv_ns_TBE_Fx(loBuffer_Fx + MAX_TEC_SMOOTHING_DEG, noCols, loTempEnv_Fx); + } + + calcGainLinear_TBE_Fx(loTempEnv_Fx, startPos, stopPos, + pGainTemp_m, pGainTemp_e); + } + + FOR (slot = 0; slot < MAX_TEC_SMOOTHING_DEG; slot++) + { + loBuffer_Fx[slot] = loBuffer_Fx[slot + stopPos]; + move16(); + } +} + +static void setSubfrConfig_Fix(Word16 i_offset, Word16* k_offset, Word16* n_subfr + , Word16 l_subfr + ) +{ + *n_subfr = sub((Word16)N_TEC_TFA_SUBFR,i_offset); + *k_offset = i_mult(i_offset,l_subfr); +} + +static Word16 calcSum_Fx(Word16* vec_m, /*Q0*/ + Word16* vec_e, /*Q0*/ + const Word16 len, + Word16* sum16_m /*Q0*/) +{ + Word16 slot; + Word16 sum16_e; /* Q0 */ + + *sum16_m = 0; + sum16_e = 0; + FOR (slot=0; slot 0) + { + Word16 tmp; + s = norm_l(nrg32); + tmp = extract_h(L_shl(nrg32, s)); + enr_m[i] = tmp; + move16(); + enr_e[i] = - s; + move16(); + } + ELSE + { + enr_m[i] = 0; + move16(); + enr_e[i] = - 15; + move16(); + } + } + + sum16_e = enr_e[i_offset]; + *sum16_m = enr_m[i_offset]; + FOR (i=i_offset+1; i 0) + { + BASOP_Util_Divide_MantExp(enr_ave_m, enr_ave_e, + enr_m[i], enr_e[i], + &inv_curr_enr_m[i], &inv_curr_enr_e[i]); + } + ELSE + { + /* 1.0e+12 */ + inv_curr_enr_m[i] = 28282/*0.8631 Q15*/; + move16(); + inv_curr_enr_e[i] = 39; + move16(); + } + + s = norm_s(inv_curr_enr_m[i]); + inv_curr_enr_m[i] = shl(inv_curr_enr_m[i], s); + move16(); + inv_curr_enr_e[i] = sub(inv_curr_enr_e[i], s); + move16(); + + IF (gain_m[i] > 0) + { + BASOP_Util_Divide_MantExp(gain_m[i], gain_e[i], + gain_ave_m, gain_ave_e, + &gain_m[i], &gain_e[i]); + } + ELSE + { + return exp_syn; + } + } + + /* find the maximum of inv_curr_enr */ + max_inv_curr_enr_e = inv_curr_enr_e[i_offset]; + move16(); + max_inv_curr_enr_m = inv_curr_enr_m[i_offset]; + move16(); + + FOR (i=i_offset+1; i 15) + { + exp_syn = 15; + move16(); + } + + if (exp_syn < 0) + { + exp_syn = 0; + move16(); + } + + min_shift = sub(s, exp_syn); /* exp_syn(old) - exp_syn(new) */ + + k = k_offset; + FOR (i=i_offset; i 0) + { + hb_synth_Fx[k] = shr(hb_synth_Fx[k], s); + move16(); + } + k = add(k, 1); + } + } + + return exp_syn; +} + +static Word16 procTfa_Fx(Word16* hb_synth_Fx, + Word16 exp_syn, + Word16 i_offset, + Word16 l_subfr + ) +{ + Word16 i,j,k; + Word16 k_offset, n_subfr; + + Word16 enr_m[N_TEC_TFA_SUBFR]; + Word16 enr_e[N_TEC_TFA_SUBFR]; + + Word16 enr_ave_m; + Word16 enr_ave_e; + + Word16 inv_n_subfr; + + Word16 s; + Word16 shift[L_FRAME_MAX]; + Word16 min_shift; + + Word16 gain_m[N_TEC_TFA_SUBFR]; + Word16 gain_e[N_TEC_TFA_SUBFR]; + + setSubfrConfig_Fix(i_offset, &k_offset, &n_subfr, l_subfr); + + assert(8 /* = 2^3 */ < n_subfr); + inv_n_subfr = getNormReciprocalWord16Scale(n_subfr, 3); + + enr_ave_e = calcSubfrNrg_Fx(hb_synth_Fx, + exp_syn, + i_offset, + enr_m, + enr_e, + k_offset, + &enr_ave_m + ,l_subfr + ); + + enr_ave_m = mult_r(enr_ave_m, inv_n_subfr); + enr_ave_e = sub(enr_ave_e, 3); + + min_shift = 15; /* min_shift <= 15 */ move16(); + + k = k_offset; + move16(); + FOR (i=i_offset; i 0) + { + BASOP_Util_Divide_MantExp(enr_ave_m, enr_ave_e, + enr_m[i], enr_e[i], + &gain_m[i], &gain_e[i]); + } + ELSE + { + /* gain = 1 */ + gain_m[i] = 32767; + move16(); + gain_e[i] = 0; + move16(); + } + + gain_m[i] = Sqrt16(gain_m[i], &gain_e[i]); + move16(); + + s = norm_s(gain_m[i]); + gain_m[i] = shl(gain_m[i], s); + move16(); + gain_e[i] = sub(gain_e[i], s); + move16(); + + FOR (j=0; j 15) + { + exp_syn = 15; + move16(); + } + + if (exp_syn < 0) + { + exp_syn = 0; + move16(); + } + + min_shift = sub(s, exp_syn); /* exp_syn(old) - exp_syn(new) */ + + k = k_offset; + move16(); + FOR (i=i_offset; i 0) + { + hb_synth_Fx[k] = shr(hb_synth_Fx[k], s); + move16(); + } + k = add(k, 1); + } + } + + return exp_syn; +} + + +Word16 procTecTfa_TBE_Fx(Word16 *hb_synth_Fx, + Word16 hb_synth_fx_exp, + Word16 *gain_m, + Word16 *gain_e, + Word16 flat_flag, + Word16 last_core + , Word16 l_subfr + , Word16 code + ) +{ + Word16 i_offset = 0; + Word16 exp_syn_frame = sub(15, hb_synth_fx_exp); + + + IF (flat_flag) + { + exp_syn_frame = procTfa_Fx(hb_synth_Fx, + exp_syn_frame, + i_offset, + l_subfr + ); + } + ELSE + { + if (NE_16(last_core, ACELP_CORE)) + { + i_offset = 1; + move16(); + } + + + exp_syn_frame = procTec_Fx(hb_synth_Fx, + exp_syn_frame, + gain_m, + gain_e, + i_offset, + l_subfr + , code + ); + + } + + hb_synth_fx_exp = sub(15, exp_syn_frame); + + return hb_synth_fx_exp; +} + + +void +calcHiEnvLoBuff_Fix( + Word16 noCols, + Word16* pFreqBandTable, /*!< freqbandTable. */ + Word16 nSfb, /*!< Number of scalefactors. */ + Word32** pCldfbPow_Fix /*float** pCldfbPow*/, + Word16* loBuffer_Fix /*float* loBuffer Q8*/, + Word16* hiTempEnvOrig_Fix /*float* hiTempEnvOrig*/, + Word16 pCldfbPow_FixScale +) +{ + const Word16 BW_LO = TecLowBandTable[NbTecLowBand]; + const Word16 lowSubband = pFreqBandTable[0]; + const Word16 highSubband = pFreqBandTable[nSfb]; + + Word16 bandOffsetBottom; + + Word16* hiTempEnv = hiTempEnvOrig_Fix + EXT_DELAY_HI_TEMP_ENV; + + move16(); + move16(); + move16(); + bandOffsetBottom = sub(lowSubband, BW_LO); + + assert(bandOffsetBottom > 0); + assert(noCols <= CLDFB_NO_COL_MAX); + + /* ============================================================ */ + /* = calc hiTempEnv = */ + + calcHiTempEnv_Fx(pCldfbPow_Fix,sub(pCldfbPow_FixScale,30),0,noCols,lowSubband,highSubband,hiTempEnv + DELAY_TEMP_ENV_BUFF_TEC); + + /* = = */ + /* ============================================================ */ + + /* ============================================================ */ + /* = calc loBuffer = */ + + calcLoBufferEnc_Fx(pCldfbPow_Fix,sub(pCldfbPow_FixScale,30),0, noCols,bandOffsetBottom,loBuffer_Fix + MAX_TEC_SMOOTHING_DEG + DELAY_TEMP_ENV_BUFF_TEC); + + /* = = */ + /* ============================================================ */ +} + +void +calcLoEnvCheckCorrHiLo_Fix( + Word16 noCols, + Word16* pFreqBandTable, /*!< freqbandTable. */ + Word16* loBuffer_Fix /*float* loBuffer Q8*/, + Word16* loTempEnv_Fix /*float* loTempEnv Q7*/, + Word16* loTempEnv_ns_Fix /* float* loTempEnv_ns*/, + Word16* hiTempEnvOrig_Fix /*float* hiTempEnvOrig*/, + Word16* corrFlag /*int* corrFlag*/ +) +{ + const Word16 BW_LO = TecLowBandTable[NbTecLowBand]; + const Word16 lowSubband = pFreqBandTable[0]; + Word16 i; + + Word16 bandOffsetBottom; + + Word32 hiVar_Fix, loVar_Fix; + Word32 hiSum_Fix, loSum_Fix; + Word32 hiTempEnv32_Fix[CLDFB_NO_COL_MAX + DELAY_TEMP_ENV_BUFF_TEC]; + Word32 loTempEnv32_Fix[CLDFB_NO_COL_MAX + DELAY_TEMP_ENV_BUFF_TEC]; + Word32 loTempEnv32_ns_Fix[CLDFB_NO_COL_MAX + DELAY_TEMP_ENV_BUFF_TEC]; + + Word32 corrCoef_Fix; + + Word32 EQ1, EQ2, EQ3; + Word32 EQ4,EQ5,EQ6; + + Word16 code = 0; /* SET TENTATIVELY */ + Word32 loVar_ns_Fix; + Word32 diff_hi_lo_sum_Fix; + Word32 loSum_ns_Fix; + Word16* hiTempEnv = hiTempEnvOrig_Fix + EXT_DELAY_HI_TEMP_ENV; + + + move16(); + move16(); + move16(); + bandOffsetBottom = sub(lowSubband, BW_LO); + + assert(bandOffsetBottom > 0); + assert(noCols <= CLDFB_NO_COL_MAX); + + + FOR( i = 0; i < noCols+ DELAY_TEMP_ENV_BUFF_TEC; i++) + { + hiTempEnv32_Fix[i] = L_deposit_l(hiTempEnv[i]); + } + hiVar_Fix = calcVar_Fix(hiTempEnv32_Fix, (Word32)noCols, &hiSum_Fix); + + + /* ============================================================ */ + /* = calc loTempEnv = */ + + + + calcLoTempEnv_Fx(loBuffer_Fix+MAX_TEC_SMOOTHING_DEG,noCols,loTempEnv_Fix,26041/*0.5 * ratioHiLoFac Q15*/); + + + calcLoTempEnv_ns_Fx(loBuffer_Fix+MAX_TEC_SMOOTHING_DEG,noCols,loTempEnv_ns_Fix); + + /* = = */ + /* ============================================================ */ + + + FOR( i = 0; i < noCols; i++) + { + loTempEnv32_ns_Fix[i] = L_deposit_l(loTempEnv_ns_Fix[i]); + } + loVar_ns_Fix = calcVar_Fix(loTempEnv32_ns_Fix, noCols, &loSum_ns_Fix); + + diff_hi_lo_sum_Fix = L_sub(loSum_ns_Fix,hiSum_Fix); + + EQ4 = L_sub(L_shr(hiVar_Fix,7),800); + EQ5 = L_sub(L_shr(loVar_ns_Fix,7),720);; + EQ6 = L_sub(L_shr(diff_hi_lo_sum_Fix,7),100); ; + test(); + test(); + if (EQ4 > 0 && EQ5 > 0 && EQ6 < 0) + { + code = 1; + move16(); + } + + + + *corrFlag = 0; + move16(); + + assert(code == 0 || code == 1); + + IF (code) + { + /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + /* ++++ code == 1 +++++*/ + /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + Word16 maxPosHi, maxPosLo; + Word16 maxHiFix, maxLoFix; + + maxHiFix = hiTempEnv[0]; + move16(); + maxLoFix = loTempEnv_ns_Fix[0]; + move16(); + maxPosHi = maxPosLo = 0; + move16(); + FOR (i = 1; i < noCols; i++) + { + if ( LT_16(maxHiFix , hiTempEnv[i])) + { + maxPosHi = i; + move16(); + } + maxHiFix = s_max(maxHiFix, hiTempEnv[i]); + + if ( LT_16(maxLoFix , loTempEnv_ns_Fix[i])) + { + maxPosLo = i; + move16(); + } + maxLoFix = s_max(maxLoFix, loTempEnv_ns_Fix[i]); + } + + if (LT_16(abs_s( sub(maxPosHi , maxPosLo)), 2)) + { + *corrFlag = 2; + move16(); + } + + { + + Word16 feature_max_Fix = 0; + Word16 pos_feature_max = 0; + Word16 feature_Fix[16]; + Word16 min_local_Fix, max_local_Fix; + Word16 j; + Word16 len_window = EXT_DELAY_HI_TEMP_ENV + 1; + + Word16* curr_pos_Fix = hiTempEnv; + + move16(); + move16(); + move16(); + move16(); + + feature_max_Fix = 0; + move16(); + pos_feature_max = 0; + move16(); + + FOR (i = 0; i < 16; i++) + { + max_local_Fix = min_local_Fix = curr_pos_Fix[0]; + move16(); + move16(); + + FOR (j = 1; j < len_window; j++) + { + if ( LT_16( max_local_Fix , curr_pos_Fix[-j])) + { + max_local_Fix = curr_pos_Fix[-j]; + move16(); + } + + if ( GT_16(min_local_Fix, curr_pos_Fix[-j] )) + { + min_local_Fix = curr_pos_Fix[-j]; + move16(); + } + } + feature_Fix[i] = sub(max_local_Fix , min_local_Fix); + + if ( LT_16(feature_max_Fix , feature_Fix[i])) + { + pos_feature_max = i; + move16(); + } + feature_max_Fix = s_max(feature_max_Fix, feature_Fix[i]); + curr_pos_Fix += 1; + } + + IF (*corrFlag > 0) + { + test(); + if ((LE_16(feature_max_Fix, shl(20, 7))||GE_16(abs_s(sub(pos_feature_max,maxPosHi)),3))) + { + *corrFlag = 0; + move16(); + } + } + } + + } + ELSE + { + /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + /* ++++ code == 0 ++++*/ + /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + + /* ============================================================ */ + /* = calc the variance of loTempEnv = */ + + FOR( i = 0; i < noCols; i++) + { + loTempEnv32_Fix[i] = L_deposit_l(loTempEnv_Fix[i]); + } + loVar_Fix = calcVar_Fix(loTempEnv32_Fix, noCols, &loSum_Fix); + /* = = */ + /* ============================================================ */ + + /* ============================================================ */ + /* = calc correlation coefficient between = */ + /* = loTempEnv and hiTempEnv = */ + corrCoef_Fix = calcCorrelationCoefficient2_Fix( + hiTempEnv32_Fix, loTempEnv32_Fix, + noCols, hiVar_Fix, loVar_Fix, hiSum_Fix, loSum_Fix); + /* = = */ + /* ============================================================ */ + + + + + EQ1 = L_sub(L_shl(corrCoef_Fix, 8),28819/*thCorrCoef Q15*/); + EQ2 = L_sub(L_shl(hiVar_Fix,0),Mpy_32_16_1(loVar_Fix,11957/*thRatio Q15*/)); + EQ3 = L_sub(L_shr(hiVar_Fix,2),Mpy_32_16_1(loVar_Fix,16620/*thRatio2 Q13*/)); + + test(); + test(); + if (EQ1 >= 0 && EQ2 > 0 /*ratio > thRatio*/ && EQ3 < 0) + { + *corrFlag = 1; + move16(); + } + + } + + FOR (i = 0; i < MAX_TEC_SMOOTHING_DEG + DELAY_TEMP_ENV_BUFF_TEC; i++) + { + loBuffer_Fix[i] = loBuffer_Fix[noCols + i]; + move16(); + } + + FOR (i = 0; i < DELAY_TEMP_ENV_BUFF_TEC + EXT_DELAY_HI_TEMP_ENV; i++) + { + hiTempEnvOrig_Fix[i] = hiTempEnvOrig_Fix[noCols + i]; + move16(); + } + +} + +void tecEnc_TBE_fx(Word16* corrFlag, const Word16* voicing, Word16 coder_type) +{ + Word16 voice_sum; + Word16 voice_diff; + + /*-----------------------------------------------------------------* + * TEC updates + *-----------------------------------------------------------------*/ + + voice_sum = add(shr(voicing[0], 1), shr(voicing[1], 1)); /*voice_sum = voicing[0] + voicing[1];*/ + voice_diff = sub(voicing[0], voicing[1]); /*voice_diff = voicing[0] - voicing[1];*/ + + if( voice_diff < 0 ) + { + voice_diff = negate(voice_diff);/*voice_diff *= -1.0f;*/ + } + + IF( EQ_16(*corrFlag, 1)) + { + test(); + test(); + test(); + /*if( ((voice_sum > 0.35 * 2 && voice_sum < 0.55 * 2) && (voice_diff < 0.2)) )*/ + if( EQ_16(coder_type,INACTIVE)||((GT_16(voice_sum,11469/*0.35 Q15*/)&<_16(voice_sum,18022/*0.55 Q15*/))&&(sub(voice_diff,6554/*0.2 Q15*/)<0))) + { + *corrFlag = 0; + move16(); + } + } + if( GT_16(voice_sum, 19661/*0.6 Q15*/)) /*if( voice_sum > 0.6 * 2 )*/ + { + *corrFlag = 0; + move16(); + } +} + +void set_TEC_TFA_code_fx(const Word16 corrFlag, Word16* tec_flag, Word16* tfa_flag) +{ + *tec_flag = 0; + move16(); + IF (*tfa_flag == 0) + { + test(); + if (EQ_16(corrFlag, 1)||EQ_16(corrFlag,2)) + { + *tec_flag = 1; + move16(); + } + + if (EQ_16(corrFlag, 2)) + { + *tfa_flag = 1; + move16(); + } + } +} + diff --git a/lib_com/tns_base.c b/lib_com/tns_base.c new file mode 100644 index 0000000..a39813b --- /dev/null +++ b/lib_com/tns_base.c @@ -0,0 +1,980 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include "stl.h" +#include "stat_com.h" +#include "stl.h" +#include +#include +#include "rom_com_fx.h" +#include "prot_fx.h" +#include "basop_util.h" + +#define HLM_MIN_NRG 32768.0f + +/** Linear prediction analysis/synthesis filter definition. + * @param order filter order. + * @param parCoeff filter (PARCOR) coefficients. + * @param state state of the filter. Must be at least of 'order' size. + * @param x the current input value. + * @return the output of the filter. + */ +typedef Word32 (* TLinearPredictionFilter)(Word16 order, Word16 const parCoeff[], Word32 * state, Word32 x); + +/** Inverse quantization for reflection coefficients. + * + * @param index input quantized values. + * @param parCoeff output reflection coefficients. + * @param order number of coefficients/values. + */ +static void Index2Parcor(Word16 const index[], Word16 parCoeff[], Word16 order); + +/** Linear prediction analysis filter. + * See TLinearPredictionFilter for details. + */ +static Word32 FIRLattice(Word16 order, const Word16 *parCoeff, Word32 *state, Word32 x); + +/** Linear prediction synthesis filter. + * See TLinearPredictionFilter for details. + */ +static Word32 IIRLattice(Word16 order, const Word16 *parCoeff, Word32 *state, Word32 x); + +/** TNS analysis/synthesis filter. + * @param spectrum input spectrum values. + * @param numOfLines number of lines in the spectrum. + * @param parCoeff filter (PARCOR) coefficients. + * @param order filter order. + * @param filter function that implements filtering. + By this function it is defined whether analysis or synthesis is performed. + * @param output filtered output spectrum values. + Inplace operation is supported, so it can be equal to spectrum. + */ +static void TnsFilter(Word32 const spectrum[], Word16 numOfLines, + Word16 const parCoeff[], Word16 order, + TLinearPredictionFilter filter, Word32 * state, + Word32 output[]); + +static void ITF_TnsFilter_fx( Word32 const spectrum[], + const Word16 numOfLines, + const Word16 A[], /* Q14 */ + const Word16 Q_A, + const Word16 order, + Word32 output[]); + +static void ITF_GetFilterParameters_fx(Word32 rxx[], + Word16 maxOrder, + Word16* A, /* Q14 */ + Word16* Q_A, + Word16* predictionGain); + +/********************************/ +/* Interface functions */ +/********************************/ + +#define MAX_SUBDIVISIONS 3 + +Word16 InitTnsConfiguration( + Word32 nSampleRate, + Word16 frameLength, + STnsConfig * pTnsConfig, + Word16 igfStopFreq, + Word32 bitrate +) +{ + Word16 iFilter = 0; + Word16 * startLineFilter; + Word32 L_tmp; + Word16 s1; + Word16 s2; + + + move16(); + startLineFilter = &pTnsConfig->iFilterBorders[1]; + + /* Sanity checks */ + assert((nSampleRate > 0) && (frameLength > 0) && (pTnsConfig != NULL)); + if ((nSampleRate <= 0) || (frameLength <= 0) || (pTnsConfig == NULL)) + { + return TNS_FATAL_ERROR; + } + + + /* Initialize TNS filter flag and maximum order */ + move16(); + pTnsConfig->maxOrder = TNS_MAX_FILTER_ORDER; + + IF (LE_32(bitrate, ACELP_32k)) + { + move16(); + move16(); + pTnsConfig->nMaxFilters = sizeof(tnsParametersIGF32kHz_LowBR)/sizeof(tnsParametersIGF32kHz_LowBR[0]); + pTnsConfig->pTnsParameters = tnsParametersIGF32kHz_LowBR; + } + ELSE + { + test(); + IF (GT_32(nSampleRate,32000)&&EQ_32(nSampleRate,L_mult0(100,frameLength))) + { + move16(); + pTnsConfig->nMaxFilters = sizeof(tnsParameters48kHz_grouped)/sizeof(tnsParameters48kHz_grouped[0]); + move16(); + pTnsConfig->pTnsParameters = tnsParameters48kHz_grouped; + } + ELSE + IF ( GT_32(nSampleRate,16000)) + { + move16(); + pTnsConfig->nMaxFilters = sizeof(tnsParameters32kHz)/sizeof(tnsParameters32kHz[0]); + + move16(); + pTnsConfig->pTnsParameters = tnsParameters32kHz; + + if ( EQ_32(nSampleRate, L_mult0(100, frameLength))) /* sub-frame length is <= 10 ms */ + { + move16(); + pTnsConfig->pTnsParameters = tnsParameters32kHz_grouped; + } + } + ELSE + { + IF ( EQ_32(nSampleRate, L_mult0(100, frameLength))) /* sub-frame length is <= 10 ms */ + { + move16(); + move16(); + pTnsConfig->nMaxFilters = sizeof(tnsParameters16kHz_grouped)/sizeof(tnsParameters16kHz_grouped[0]); + pTnsConfig->pTnsParameters = tnsParameters16kHz_grouped; + } + ELSE + { + move16(); + move16(); + pTnsConfig->nMaxFilters = sizeof(tnsParameters16kHz)/sizeof(tnsParameters16kHz[0]); + pTnsConfig->pTnsParameters = tnsParameters16kHz; + } + } + } + + assert(pTnsConfig->nMaxFilters <= TNS_MAX_NUM_OF_FILTERS); + + /* Set starting MDCT line for each filter based on the starting frequencies from the TNS table */ + + FOR (iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++) + { + assert(pTnsConfig->pTnsParameters[iFilter].startLineFrequency < 0.5f*nSampleRate); + assert(nSampleRate <= 96000); + move16(); + startLineFilter[iFilter] = divide3232(L_mult0(frameLength, pTnsConfig->pTnsParameters[iFilter].startLineFrequency), L_shl(nSampleRate,14)); + } + + IF (igfStopFreq > 0) + { + L_tmp = L_mult(frameLength, igfStopFreq); + s1 = sub(norm_l(L_tmp), 1); + s2 = norm_l(nSampleRate); + + move16(); + pTnsConfig->iFilterBorders[0] = shr( div_l( L_shl(L_tmp, s1), extract_h(L_shl(nSampleRate, s2)) ) , sub(WORD16_BITS-1, sub(s2, s1))); + + } + ELSE + { + move16(); + pTnsConfig->iFilterBorders[0] = frameLength; + } + + return TNS_NO_ERROR; +} + + +Word16 ApplyTnsFilter( + STnsConfig const * pTnsConfig, + STnsData const * pTnsData, + Word32 spectrum[], + Word8 fIsAnalysis) +{ + Word16 result; + TLinearPredictionFilter filter; + Word32 state[TNS_MAX_FILTER_ORDER]; + Word16 iFilter; + Word16 stopLine, startLine; + Word16 const * pBorders; + + + move16(); + filter = IIRLattice; + if (fIsAnalysis) + { + move16(); + filter = FIRLattice; + } + set32_fx(state, 0, TNS_MAX_FILTER_ORDER); + move16(); + pBorders = pTnsConfig->iFilterBorders; + + FOR (iFilter = pTnsConfig->nMaxFilters-1; iFilter >= 0; iFilter--) + { + Word16 parCoeff[TNS_MAX_FILTER_ORDER]; + STnsFilter const * pFilter; + + + move16(); + move16(); + move16(); + pFilter = &pTnsData->filter[iFilter]; + stopLine = pBorders[iFilter]; + startLine = pBorders[iFilter+1]; + + Index2Parcor(pFilter->coefIndex, parCoeff, pFilter->order); + + TnsFilter(&spectrum[startLine], stopLine-startLine, + parCoeff, pFilter->order, + filter, state, + &spectrum[startLine]); + + } + + move16(); + result = TNS_NO_ERROR; + if (pTnsData->nFilters < 0) + { + move16(); + result = TNS_FATAL_ERROR; + } + + return result; +} + +TNS_ERROR ITF_Apply_fx(Word32 spectrum[], + Word16 startLine, + Word16 stopLine, + const Word16* A, + Word16 Q_A, + Word16 order + ) +{ + + ITF_TnsFilter_fx(&spectrum[startLine], + (Word16)(stopLine-startLine), + A, + Q_A, + (Word16)order, + &spectrum[startLine]); + + return TNS_NO_ERROR; +} + +Word16 ITF_Detect_fx(Word32 const pSpectrum[], + Word16 startLine, + Word16 stopLine, + Word16 maxOrder, + Word16* A, + Word16* Q_A, + Word16* predictionGain, + Word16* curr_order, + Word16 Q ) +{ + Word16 const idx0 = startLine; + Word16 const idx1 = stopLine; + Word16 spectrumLength; + Word16 const nSubdivisions = MAX_SUBDIVISIONS; + Word16 iSubdivisions; + Word16 iStartLine; + Word16 iEndLine; + Word16 facs[MAX_SUBDIVISIONS]; + Word16 facs_e[MAX_SUBDIVISIONS]; /* exponents of facs[][] */ + Word16 shifts[MAX_SUBDIVISIONS]; + Word16 tmp, headroom, shift; + Word32 rxx[ITF_MAX_FILTER_ORDER+1]; + Word16 lag; + Word32 L_tmp, tmp32; + Word16 tmpbuf[325]; + Word16 n, i; + + move16(); + move16(); + move16(); + + if (maxOrder <= 0) + { + return 0; + } + + /* Calculate norms for each spectrum part */ + FOR (iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++) + { + assert((nSubdivisions == 1) || (nSubdivisions == 3)); + + tmp = sub(idx1, idx0); + iStartLine = imult1616(tmp, iSubdivisions); + iEndLine = add(iStartLine, tmp); + + if (EQ_16(nSubdivisions, 3))iStartLine=mult(iStartLine,0x2AAB); + iStartLine = add(iStartLine, idx0); + + if (EQ_16(nSubdivisions, 3))iEndLine=mult(iEndLine,0x2AAB); + iEndLine = add(iEndLine, idx0); + headroom = getScaleFactor32(pSpectrum+iStartLine-IGF_START_MN, sub(iEndLine, iStartLine)); + /* Calculate norm of spectrum band */ + L_tmp = Norm32Norm(pSpectrum+iStartLine-IGF_START_MN, headroom, sub(iEndLine, iStartLine), &shift); + + /* Check threshold HLM_MIN_NRG */ + BASOP_SATURATE_WARNING_OFF; + tmp32 = L_sub(L_shl(L_tmp, sub(shift, 24-Q)), 4194304l/*HLM_MIN_NRG Q7*/); + BASOP_SATURATE_WARNING_ON; + + /* get pre-shift for autocorrelation */ + tmp = sub(shift, norm_l(L_tmp)); /* exponent for normalized L_tmp */ + tmp = shr(sub(1, tmp), 1); /* pre-shift to apply before autocorrelation */ + shifts[iSubdivisions] = s_min(tmp, headroom); + move16(); + + /* calc normalization factor */ + facs[iSubdivisions] = 0; + move16(); + facs_e[iSubdivisions] = 0; + move16(); + + if (tmp32 > 0) + { + facs[iSubdivisions] = 0x7FFF; + move16(); /* normalization not needed for one subdivision */ + } + + test(); + IF ((tmp32 > 0) && (GT_16(nSubdivisions, 1))) + { + move16(); + facs_e[iSubdivisions] = shl(sub(tmp, shifts[iSubdivisions]), 1); + + tmp = sub(1, shl(tmp, 1)); /* exponent of autocorrelation */ + L_tmp = L_shl(L_tmp, sub(shift, tmp)); /* shift L_tmp to that exponent */ + + /* calc factor (with 2 bits headroom for sum of 3 subdivisions) */ + facs[iSubdivisions] = div_s(0x2000, round_fx(L_tmp)); /* L_tmp is >= 0x2000000 */ move16(); + } + + } + + /* Calculate normalized autocorrelation for spectrum subdivision and get filter parameters based on it */ +#define RXX_E (3) + { + set32_fx(rxx, 0, ITF_MAX_FILTER_ORDER+1); + + spectrumLength = sub(idx1, idx0); + + FOR (iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++) + { + IF ( facs[iSubdivisions] == 0 ) + { + BREAK; + } + + + assert((nSubdivisions == 1) || (nSubdivisions == 3)); + + iStartLine = imult1616(spectrumLength, iSubdivisions); + iEndLine = add(iStartLine, spectrumLength); + + if (EQ_16(nSubdivisions, 3))iStartLine=mult(iStartLine,0x2AAB); + iStartLine = add(iStartLine, idx0); + + if (EQ_16(nSubdivisions, 3))iEndLine=mult(iEndLine,0x2AAB); + iEndLine = add(iEndLine, idx0); + + + move16(); + shift = shifts[iSubdivisions]; + + n = sub(iEndLine, iStartLine); + assert(n < (Word16)(sizeof(tmpbuf)/sizeof(Word16))); + FOR (i = 0; i < n; i++) + { + tmpbuf[i] = round_fx(L_shl(pSpectrum[iStartLine+i-IGF_START_MN], shift)); + } + + FOR (lag = 0; lag <= maxOrder; lag++) + { + n = sub(sub(iEndLine,lag), iStartLine); + + { + Word64 tmp64 = 0; + FOR (i = 0; i < n; i++) + { + tmp64 = W_mac0_16_16(tmp64, tmpbuf[i], tmpbuf[i+lag]); + } + L_tmp = W_sat_l(tmp64); + } + + L_tmp = Mpy_32_16_1(L_tmp, facs[iSubdivisions]); + L_tmp = L_shl(L_tmp, facs_e[iSubdivisions]); + + rxx[lag] = L_add(rxx[lag], L_tmp); + move32(); + } + + } + + IF ( EQ_16(iSubdivisions,nSubdivisions)) /* meaning there is no subdivision with low energy */ + { + /* Limit the maximum order to spectrum length/4 */ + ITF_GetFilterParameters_fx(rxx, s_min (maxOrder, shr(spectrumLength,2)), A, Q_A, predictionGain); + + *curr_order = maxOrder; + } + + } + + return 1; +} + + +/* Helper functions for Hufmann table coding */ + + +/** Get number of bits from a Huffman table. + * The table must be sorted by values. + */ +static Word16 GetBitsFromTable(const Word16 value, const Coding codes[], const Word16 nSize) +{ + (void)nSize; + assert((value >= 0) && (value < nSize) && (nSize >= 0) && (nSize <= 256)); + + move16(); + cast16(); + return (Word16)codes[value].nBits; +} + +/** Get the code for a value from a Huffman table. + * The table must be sorted by values. + */ +static Word16 EncodeUsingTable(const Word16 value, const Coding codes[], const Word16 nSize) +{ + (void)nSize; + assert((value >= 0) && (value < nSize) && (nSize >= 0) && (nSize <= 256)); + + move16(); + return codes[value].code; +} + + +/** Decode a value from a bitstream using a Huffman table. */ +static Word16 DecodeUsingTable(Decoder_State_fx *st, Word16 * pValue, const Coding codes[], const Word16 nSize) +{ + Word16 code = 0; + Word16 nBits = 0; + Word16 valueIndex; + + assert((nSize >= 0) && (nSize <= 256)); + + + move16(); + valueIndex = nSize; + + + WHILE (valueIndex == nSize) + { + code = add(shl(code,1), get_next_indice_fx(st, 1)); + nBits = add(nBits,1); + if (nBits > nSize || nBits > 16) + { + st->BER_detect = 1; + *pValue = 0; + + return -1; + } + + FOR (valueIndex = 0; valueIndex < nSize; valueIndex++) + { + + IF ( s_and((Word16)EQ_16(codes[valueIndex].nBits,nBits),(Word16)EQ_16(codes[valueIndex].code,code))) + { + BREAK; + } + } + + } + if (valueIndex < nSize) + { + *pValue = (Word16)codes[valueIndex].value; + } + else + { + st->BER_detect = 1; + *pValue = 0; + + return -1; + } + + return nBits; +} + + +/* TNS filter coefficients */ + +void const * GetTnsFilterCoeff(void const * p, Word16 index, Word16 * pValue) +{ + *pValue = ((Word16 const *)p)[index] + INDEX_SHIFT; + return NULL; +} + +void * SetTnsFilterCoeff(void * p, Word16 index, Word16 value) +{ + ((Word16 *)p)[index] = sub(value, INDEX_SHIFT); + return NULL; +} + + +Word16 GetSWBTCX20TnsFilterCoeffBits(Word16 value, Word16 index) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + + return GetBitsFromTable(value, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes); +} + +Word16 EncodeSWBTCX20TnsFilterCoeff(Word16 value, Word16 index) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + + return EncodeUsingTable(value, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes); +} + +Word16 DecodeSWBTCX20TnsFilterCoeff(Decoder_State_fx *st, Word16 index, Word16 * pValue) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + + return DecodeUsingTable(st, pValue, codesTnsCoeffSWBTCX20[index], nTnsCoeffCodes); +} + +Word16 GetSWBTCX10TnsFilterCoeffBits(Word16 value, Word16 index) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + + return GetBitsFromTable(value, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes); +} + +Word16 EncodeSWBTCX10TnsFilterCoeff(Word16 value, Word16 index) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + + return EncodeUsingTable(value, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes); +} + +Word16 DecodeSWBTCX10TnsFilterCoeff(Decoder_State_fx *st, Word16 index, Word16 * pValue) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + + return DecodeUsingTable(st, pValue, codesTnsCoeffSWBTCX10[index], nTnsCoeffCodes); +} + +Word16 GetWBTCX20TnsFilterCoeffBits(Word16 value, Word16 index) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + + return GetBitsFromTable(value, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes); +} + +Word16 EncodeWBTCX20TnsFilterCoeff(Word16 value, Word16 index) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + + return EncodeUsingTable(value, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes); +} + +Word16 DecodeWBTCX20TnsFilterCoeff(Decoder_State_fx *st, Word16 index, Word16 * pValue) +{ + assert((index >= 0) && (index < nTnsCoeffTables)); + + return DecodeUsingTable(st, pValue, codesTnsCoeffWBTCX20[index], nTnsCoeffCodes); +} + + + +/* TNS filter order */ + +void const * GetTnsFilterOrder(void const * p, Word16 index, Word16 * pValue) +{ + move16(); + *pValue = ((STnsFilter const *)p)[index].order; + + move16(); + return ((STnsFilter const *)p)[index].coefIndex; +} + +void * SetTnsFilterOrder(void * p, Word16 index, Word16 value) +{ + move16(); + ((STnsFilter *)p)[index].order = value; + + move16(); + return ((STnsFilter *)p)[index].coefIndex; +} + +Word16 GetTnsFilterOrderBitsSWBTCX20(Word16 value, Word16 index) +{ + (void)index; + + return GetBitsFromTable(value-1, codesTnsOrderTCX20, nTnsOrderCodes); +} + +Word16 EncodeTnsFilterOrderSWBTCX20(Word16 value, Word16 index) +{ + (void)index; + + return EncodeUsingTable(value-1, codesTnsOrderTCX20, nTnsOrderCodes); +} + +Word16 DecodeTnsFilterOrderSWBTCX20(Decoder_State_fx *st, Word16 index, Word16 * pValue) +{ + (void)index; + + return DecodeUsingTable(st, pValue, codesTnsOrderTCX20, nTnsOrderCodes); +} + +Word16 GetTnsFilterOrderBitsSWBTCX10(Word16 value, Word16 index) +{ + (void)index; + + return GetBitsFromTable(value-1, codesTnsOrderTCX10, nTnsOrderCodes); +} + +Word16 EncodeTnsFilterOrderSWBTCX10(Word16 value, Word16 index) +{ + (void)index; + + return EncodeUsingTable(value-1, codesTnsOrderTCX10, nTnsOrderCodes); +} + +Word16 DecodeTnsFilterOrderSWBTCX10(Decoder_State_fx *st, Word16 index, Word16 * pValue) +{ + (void)index; + + return DecodeUsingTable(st, pValue, codesTnsOrderTCX10, nTnsOrderCodes); +} + +Word16 GetTnsFilterOrderBits(Word16 value, Word16 index) +{ + (void)index; + + return GetBitsFromTable(value-1, codesTnsOrder, nTnsOrderCodes); +} + +Word16 EncodeTnsFilterOrder(Word16 value, Word16 index) +{ + (void)index; + + return EncodeUsingTable(value-1, codesTnsOrder, nTnsOrderCodes); +} + +Word16 DecodeTnsFilterOrder(Decoder_State_fx *st, Word16 index, Word16 * pValue) +{ + (void)index; + + return DecodeUsingTable(st, pValue, codesTnsOrder, nTnsOrderCodes); +} + +/* Number of TNS filters */ + +void const * GetNumOfTnsFilters(void const * p, Word16 index, Word16 * pValue) +{ + *pValue = ((STnsData const *)p)[index].nFilters; + + return ((STnsData const *)p)[index].filter; +} + +void * SetNumOfTnsFilters(void * p, Word16 index, Word16 value) +{ + ((STnsData *)p)[index].nFilters = value; + + return ((STnsData *)p)[index].filter; +} + +/* TNS enabled/disabled flag */ + +void const * GetTnsEnabled(void const * p, Word16 index, Word16 * pValue) +{ + move16(); + *pValue = 0; + if (((STnsData const *)p)[index].nFilters > 0) + { + move16(); + *pValue = 1; + } + return NULL; +} + +void * SetTnsEnabled(void * p, Word16 index, Word16 value) +{ + (void)p,(void)index,(void)value; + return NULL; +} + +void const * GetTnsEnabledSingleFilter(void const * p, Word16 index, Word16 * pValue) +{ + move16(); + *pValue = 0; + if (((STnsData const *)p)[index].nFilters > 0) + { + move16(); + *pValue = 1; + } + return ((STnsData const *)p)[index].filter; +} + +void * SetTnsEnabledSingleFilter(void * p, Word16 index, Word16 value) +{ + ((STnsData *)p)[index].nFilters = value; + return ((STnsData *)p)[index].filter; +} + +/********************************/ +/* Private functions */ +/********************************/ + +void ResetTnsData(STnsData * pTnsData) +{ + Word16 iFilter; + + + pTnsData->nFilters = 0; + + FOR (iFilter = 0; iFilter < (Word16) (sizeof(pTnsData->filter)/sizeof(pTnsData->filter[0])); iFilter++) + { + STnsFilter * const pTnsFilter = &pTnsData->filter[iFilter]; + pTnsFilter->spectrumLength = 0; + pTnsFilter->predictionGain = 128/*1.0f Q7*/; + pTnsFilter->avgSqrCoef = 0; + ClearTnsFilterCoefficients(pTnsFilter); + } + +} + +void ClearTnsFilterCoefficients(STnsFilter * pTnsFilter) +{ + move16(); + pTnsFilter->order = 0; + assert(TNS_MAX_FILTER_ORDER == 8); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + pTnsFilter->coefIndex[0] = 0; + pTnsFilter->coefIndex[1] = 0; + pTnsFilter->coefIndex[2] = 0; + pTnsFilter->coefIndex[3] = 0; + pTnsFilter->coefIndex[4] = 0; + pTnsFilter->coefIndex[5] = 0; + pTnsFilter->coefIndex[6] = 0; + pTnsFilter->coefIndex[7] = 0; +} + +static void Index2Parcor(const Word16 index[], Word16 parCoeff[], Word16 order) +{ + Word16 const * values; + Word16 i; + + move16(); + values = tnsCoeff4; + + FOR (i = 0; i < order; i++) + { + move16(); + parCoeff[i] = values[add(index[i], INDEX_SHIFT)]; + } + +} + + + +static Word32 FIRLattice(Word16 order, const Word16 *parCoeff /*Q15*/, Word32 *state, Word32 x /* Q0 */) +{ + Word16 i; + Word32 tmpSave, tmp; + + + tmpSave = x; + move32(); + FOR (i = 0; i < order-1; i++) + { + tmp = L_add(state[i], Mpy_32_16_1(x, parCoeff[i])); + x = L_add(x, Mpy_32_16_1(state[i], parCoeff[i])); /* exponent: 31+0 */ + state[i] = tmpSave; + move32(); + tmpSave = tmp; + move32(); + } + + /* last stage: only need half operations */ + x = L_add(x, Mpy_32_16_1(state[order-1], parCoeff[order-1])); + state[order-1] = tmpSave; + move32(); + + return x; +} + +static Word32 IIRLattice(Word16 order, const Word16 *parCoeff, Word32 *state, Word32 x) +{ + Word16 i; + + + /* first stage: no need to calculate state[order-1] */ + x = L_sub(x, Mpy_32_16_1(state[order-1], parCoeff[order-1])); + + FOR (i = order-2; i >= 0; i--) + { + x = L_sub(x, Mpy_32_16_1(state[i], parCoeff[i])); + state[i+1] = L_add(state[i], Mpy_32_16_1(x, parCoeff[i])); + move32(); + } + + move32(); + state[0] = x; + return x; +} + +static void TnsFilter(Word32 const spectrum[], Word16 numOfLines, + Word16 const parCoeff[], Word16 order, + TLinearPredictionFilter filter, Word32 * state, + Word32 output[]) +{ + Word16 j; + + + assert((order >= 0) && (order <= TNS_MAX_FILTER_ORDER)); + assert((numOfLines > 0) || ((numOfLines == 0) && (order == 0))); + + IF (order == 0) + { + + test(); + IF ( s_and((spectrum != output), numOfLines > 0) ) + { + Copy32(spectrum, output, numOfLines); + } + } + ELSE + { + { + + FOR (j = 0; j < numOfLines; j++) + { + move32(); + output[j] = filter(order, parCoeff, state, spectrum[j]); + } + } + } +} + +static void ITF_TnsFilter_fx( Word32 const spectrum[], + const Word16 numOfLines, + const Word16 A[], /* ifdef FIX_ITF_OVERFLOW Q_A else Q14 */ + const Word16 Q_A, + const Word16 order, + Word32 output[]) +{ + Word16 i, j; + Word32 buf[ITF_MAX_FILTER_ORDER + N_MAX]; + Word32* p; + Word16 shift; + assert((order >= 0) && (order <= ITF_MAX_FILTER_ORDER)); + assert((numOfLines > 0) || ((numOfLines == 0) && (order == 0))); + + IF (order == 0) + { + + test(); + IF ( s_and((spectrum != output), numOfLines > 0) ) + { + Copy32(spectrum, output, numOfLines); + } + } + ELSE + { + shift = sub(15, Q_A); + + p = buf + ITF_MAX_FILTER_ORDER; + set32_fx(buf, 0, ITF_MAX_FILTER_ORDER); + Copy32(spectrum, p, numOfLines); + FOR (j = 0; j < numOfLines; j++) + { + Word32 L_tmp; + + L_tmp = L_add(p[0], 0); + FOR (i = 1; i < order; i++) + { + L_tmp = L_add(L_tmp, L_shl(Mpy_32_16_1(p[-i], A[i]), shift)); + } + output[j] = L_tmp; + move32(); + ++p; + } + } + +} + +static void ITF_GetFilterParameters_fx(Word32 rxx[], + Word16 maxOrder, + Word16* A, /* ifdef FIX_ITF_OVERFLOW Q_A else Q14 */ + Word16* Q_A, + Word16* predictionGain) +{ + Word16 i, j, i_2, tmp; + Word16 parCoeff[ITF_MAX_FILTER_ORDER]; + Word32 epsP[ITF_MAX_FILTER_ORDER+1], L_tmp; + + /* compute filter in ParCor form with LeRoux-Gueguen algorithm */ + L_tmp = E_LPC_schur(rxx, parCoeff, epsP, maxOrder); + BASOP_SATURATE_WARNING_OFF /* Allow saturation, this value is compared against a threshold. */ + *predictionGain = divide3232(L_shr(epsP[0], PRED_GAIN_E), L_tmp); + BASOP_SATURATE_WARNING_ON + + { + Word32 A32[ITF_MAX_FILTER_ORDER]; + Word16 tmp1_l, tmp1_h, tmp2_l, tmp2_h; + + /* Convert ParCor / reflection coefficients to LPC */ + A32[0] = 134217728l/*1.0 Q27*/; + move16(); /* Q11+16 */ + A32[1] = L_shr(L_deposit_h(parCoeff[0]), 4); /* Q11+16 */ + + FOR (i=1; i Q14 */ + FOR (i=0; i +#include +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "basop_util.h" +#include "rom_com_fx.h" /* Function prototypes */ +#include "cnst_fx.h" /* Function prototypes */ +#include "stl.h" + +#define INV_BANDS10 3277 /* 1/10 in Q15 */ +#define INV_BANDS9 3641 /* 1/9 in Q15 */ +#define INV_BANDS3 10923 /* 1/9 in Q15 */ + +/*-------------------------------------------------------------------* + * usdequant_fx() + * + * Uniform scalar de-quantizer routine + * + * Applies de-quantization based on scale and round operations. + *-------------------------------------------------------------------*/ +Word16 usdequant_fx( /* Qx*/ + const Word16 idx, /* i: quantizer index Q0*/ + const Word16 qlow, /* i: lowest codebook entry (index 0) Qx*/ + const Word16 delta /* i: quantization step Qx-1*/ +) +{ + Word16 g; + Word32 L_tmp; + + /*g = idx * delta + qlow;*/ + L_tmp = L_deposit_l(qlow);/*Qx */ + L_tmp = L_mac(L_tmp,idx,delta);/*Qx */ + g = round_fx(L_shl(L_tmp,16)); /*Qx */ + + return( g ); +} + +/*-------------------------------------------------------------------* + * usquant() + * + * Uniform scalar quantizer according to MMSE criterion + * (nearest neighbour in Euclidean space) + * + * Applies quantization based on scale and round operations. + * Index of the winning codeword and the winning codeword itself are returned. + *-------------------------------------------------------------------*/ +Word16 usquant_fx( /* o: index of the winning codeword */ + const Word16 x, /* i: scalar value to quantize Qx*/ + Word16 *xq, /* o: quantized value Qx*/ + const Word16 qlow, /* i: lowest codebook entry (index 0) Qx*/ + const Word16 delta, /* i: quantization step Qx-1*/ + const Word16 cbsize /* i: codebook size */ +) +{ + Word16 idx; + Word16 tmp, exp; + Word32 L_tmp; + + /* idx = (short)( (x - qlow)/delta + 0.5f); */ + exp = norm_s(delta); + tmp = div_s(shl(1,sub(14,exp)),delta); /*Q(29-exp-(Qx-1))->Q(30-exp-Qx) */ + L_tmp = L_mult(sub(x,qlow),tmp); /*Q(31-exp) */ + idx = extract_l(L_shr_r(L_add(L_tmp,shl(1,sub(30,exp))),sub(31,exp))); /*Q0 */ + + idx = s_min(idx,sub(cbsize,1)); + idx = s_max( idx, 0); + + /* *xq = idx*delta + qlow; */ + L_tmp = L_deposit_l(qlow);/*Qx */ + L_tmp = L_mac(L_tmp,idx,delta);/*Qx */ + *xq = round_fx(L_shl(L_tmp,16));/*Qx */ + + return idx; +} +/*-------------------------------------------------------------------* +* Dot_product: +* +* Compute scalar product of using accumulator. +* Performs no normalization, as opposed to Dot_product12() +*-------------------------------------------------------------------*/ +Word32 Dot_product( /* o : Sum */ + const Word16 x[], /* i : 12bits: x vector */ + const Word16 y[], /* i : 12bits: y vector */ + const Word16 lg /* i : vector length */ +) +{ + Word16 i; + Word32 L_sum; + Word64 L64_sum; + + L64_sum = 1; + FOR (i = 0; i < lg; i++) + { + L64_sum = W_mac_16_16(L64_sum, x[i], y[i]); + } + L_sum = W_sat_l(L64_sum); + return L_sum; +} +/*---------------------------------------------------------------------* + * dotp_fx() + * + * Dot product of vector x[] and vector y[] + *---------------------------------------------------------------------*/ + +Word32 dotp_fx( /* o : dot product of x[] and y[] */ + const Word16 x[], /* i : vector x[] */ + const Word16 y[], /* i : vector y[] */ + const Word16 n, /* i : vector length */ + Word16 *exp /* (o) : exponent of result (0..+30) */ +) +{ + Word16 sft; + Word32 L_sum; + + assert(*exp == 0); + + L_sum = L_add(L_shr(Dot_product(x, y, n), 1), 1); + + /* Normalize acc in Q31 */ + + sft = norm_l(L_sum); + L_sum = L_shl(L_sum, sft); + + *exp = sub(30, sft); + move16(); /* exponent = 0..30 */ + + return L_sum; +} + +Word32 sum2_fx( /* o : sum of all squared vector elements Q(2x+1)*/ + const Word16 *vec, /* i : input vector Qx*/ + const Word16 lvec /* i : length of input vector */ +) +{ + Word16 i; + Word32 L_tmp; + L_tmp = L_deposit_l(0); + FOR( i=0; i= 0; i--) + { + y[i] = x[i]; + move16(); + } + } +} + +/*-------------------------------------------------------------------* + * Copy32: + * + * Copy vector x[] to y[] (32 bits) + *-------------------------------------------------------------------*/ +void Copy32( + const Word32 x[], /* i : input vector */ + Word32 y[], /* o : output vector */ + const Word16 L /* i : vector length */ +) +{ + Word16 i; + IF(y < x) + { + FOR (i = 0; i < L; i++) + { + y[i] = x[i]; + move32(); + } + } + ELSE + { + FOR (i = L-1; i >= 0; i--) + { + y[i] = x[i]; + move32(); + } + } +} +/*-------------------------------------------------------------------* + * set16_fx() + * set32_fx() + * + * Set the vector elements to a value + *-------------------------------------------------------------------*/ +void set16_fx( + Word16 y[], /* i/o: Vector to set */ + const Word16 a, /* i : Value to set the vector to */ + const Word16 N /* i : Lenght of the vector */ +) +{ + Word16 i; + + FOR (i=0 ; i 0) + { + FOR (i = 0; i < lg; i++) + { + x[i] = shl(x[i], exp0); + move16(); /* saturation can occur here */ + } + return; + } + IF (exp0 < 0) + { + BASOP_SATURATE_WARNING_OFF + tmp = shl(-32768, exp0); /* we use negative to correctly represent 1.0 */ + BASOP_SATURATE_WARNING_ON + FOR (i = 0; i < lg; i++) + { + x[i] = msu_r(0, x[i], tmp); + move16(); /* msu instead of mac because factor is negative */ + } + return; + } +} + +/*---------------------------------------------------------------------* + * mean() + * + *---------------------------------------------------------------------*/ +Word16 mean_fx( /* o : mean of vector */ + const Word16 *vec_fx, /* i : input vector */ + const Word16 lvec_fx /* i : length of input vector */ +) +{ + Word16 tmp; + tmp = sum16_fx(vec_fx,lvec_fx); + tmp = mult_r(tmp,div_s(1,lvec_fx)); + + return tmp; +} +/*-------------------------------------------------------------------* + * Vr_add + * + * Add two Word16 vectors together integer by integer + *-------------------------------------------------------------------*/ +void Vr_add( + const Word16 *in1, /* i : Input vector 1 */ + const Word16 *in2, /* i : Input vector 2 */ + Word16 *out, /* o : Output vector that contains vector 1 + vector 2 */ + Word16 Len /* i : Vector lenght */ +) +{ + Word16 i; + + FOR (i=0; i=lo; i--) + { + i1 = add(i, 1); + tempr = r[i]; + move16(); + move16(); /*supplementary move for the j-1 PTR initialization*/ + FOR (j=i1; j<=up; j++) + { + IF (LE_16(tempr, r[j])) + { + BREAK; + } + + r[j-1] = r[j]; + move16(); + } + r[j-1] = tempr; + move16(); + } +} + +void sort_32_fx( + Word32 *r, /* i/o: Vector to be sorted in place */ + const Word16 lo, /* i : Low limit of sorting range */ + const Word16 up /* I : High limit of sorting range */ +) +{ + Word16 i, j; + Word32 tempr; + FOR ( i=sub(up, 1); i>=lo; i-- ) + { + tempr = r[i]; + move32(); + FOR ( j=add(i, 1); j<=up; j++ ) + { + IF (LE_32(tempr,r[j])) + { + BREAK; + } + r[j-1] = r[j]; + move32(); + } + + r[j-1] = tempr; + move32(); + } + + return; +} + +Word16 minimum_fx( /* o : index of the minimum value in the input vector */ + const Word16 *vec_fx, /* i : input vector */ + const Word16 lvec_fx, /* i : length of input vector */ + Word16 *min_fx /* o : minimum value in the input vector */ +) +{ + Word16 j, ind; + Word16 tmp; + ind = 0; + move16(); + tmp = vec_fx[0]; + move16(); + + FOR ( j=1 ; j 0) + { + ind = j; + move16(); + } + emax = L_max(emax, L_tmp); + } + + *ener_max = L_shr(emax, add(Qvec, Qvec)); + move32(); + + return ind; +} +/*-------------------------------------------------------------------* + * mean32: + * + * Find the mean of a 32 bits vector + *-------------------------------------------------------------------*/ +Word32 Mean32( /* o : mean of the elements of the vector */ + const Word32 in[], /* i : input vector */ + const Word16 L /* i : length of input vector */ +) +{ + Word32 Ltmp; + Word16 inv_L; + + inv_L = INV_BANDS9; + move16(); + if (EQ_16(L, 10)) + { + inv_L = INV_BANDS10; + move16(); + } + + Ltmp = sum32_fx(in, L); + + Ltmp = Mult_32_16(Ltmp, inv_L); + + return Ltmp; +} +Word32 sum32_fx( /* o : sum of all vector elements Qx*/ + const Word32 *vec, /* i : input vector Qx*/ + const Word16 lvec /* i : length of input vector */ +) +{ + Word16 i; + Word32 tmp; + tmp = L_deposit_l(0); + FOR( i=0; i= 0) + { + expA = sub(expA, 1); + } + N = L_shl(Numer, expA); + + /* Perform Approximation of the Division + * Since 'lo' part is '0' AND 'denom' is supposed to be constant in the targeted usage + * one could import the Div32 code and pre-calc the div_s and eliminate all calcs + * with 'lo' to save some complexity */ + + Quotient = Div_32_optmz(N, D); /* takes 36 clocks */ + /* Bring Back to Q0 (minus 2 because we removed the left shift by 2 in the Div32_optmz) */ + IF(rshift) + { + Quotient = L_shr(Quotient, add(15-2, sub(expA, sub(expB,1)))); + } + ELSE + { + Quotient = L_shr(Quotient, add(15-2, sub(expA, expB))); + } + + /* Cross Check (do Quotient x Divisor) + * The Quotient is unsigned but we cannot just use extract_h because + * extract_l on the low part will get the sign of the bit #15. + * In a 32 bits value, what is in bits 0-15 is un unsigned 16 bits value. + * So, we shift left by 1, extract the hi part and mult it by 32768 (hence the L_shl by 16-1. + * Then we take 15 bits left (mask the others) and multiply by Denom. + * Technically this could overflow. But since we are mutiplying to get + * back to the Numer value that fitted in a 32 bits, doing Divisor x Quotient + * must necessarily fit in a 32 bits + * It is assumed that all are positive values. If not, one could + * check the sign of the numer and denom, turn them into abs values + * and restore the sign after*/ + TEMP = L_shl(L_mult0(extract_h(L_shl(Quotient, 1)), Denom), 16-1); + TEMP = L_mac0(TEMP, extract_l(L_and(0x7FFF, Quotient)), Denom); + + + + /* Here we test to see if the previous "Quotient x Divisor" (or TEMP) is too small + * that is the "Numer" minus TEMP is bigger or Equal to the Divisor. + * If it is then the quotient is too small. We need to increase it by 1. + * That is caused by our Div32 fractionnal division that can be off by 1 + * sometimes. + * In some cases, when the divisor is very small (like 10 or something) + * the quotient could be off by more than 1 and we would need a loop + * to check again. That is not the case here with the current divisor */ + IF(rshift) + { + TEMP = L_shl(TEMP, 1); + WHILE (L_msu0(L_sub(Numer, TEMP), 2, Denom) >= 0) + { + Quotient = L_add(Quotient, 1); + TEMP = L_shl(L_mult0(extract_h(L_shl(Quotient, 1)), Denom), 16-1); + TEMP = L_mac0(TEMP, extract_l(L_and(0x7FFF, Quotient)), Denom); + TEMP = L_shl(TEMP, 1); + } + } + ELSE + { + WHILE (L_msu0(L_sub(Numer, TEMP), 1, Denom) >= 0) + { + Quotient = L_add(Quotient, 1); + TEMP = L_shl(L_mult0(extract_h(L_shl(Quotient, 1)), Denom), 16-1); + TEMP = L_mac0(TEMP, extract_l(L_and(0x7FFF, Quotient)), Denom); + } + } + *Int_quotient = Quotient; + move32(); + IF(L_msu0(L_sub(Numer, TEMP), 1, Denom) == 0) + { + *Int_mod = 0L; + move32(); + } + ELSE + { + *Int_mod = L_sub(Numer, TEMP); + move32(); + } + + +} + +/*===================================================================*/ +/* FUNCTION : pz_filter_sp_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Generic pole-zero filter routine, with single */ +/* precision memory */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) b : zero filter coefficients (Qc). */ +/* _ (Word16 []) a : pole filter coefficients (Qc), a(0)=1 in Qc */ +/* _ (Word16 []) x : input signal (Qn). */ +/* _ (Word16) PNR : NR filter order */ +/* _ (Word16) PDR : DR filter order */ +/* _ (Word16) N : number of input samples. */ +/* _ (Word16) Qa : Q factor compensation (Qa=16-Qc) */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) y : output signal (Qn) */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) buf : filter memory (Qn-Qa). */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*===================================================================*/ + +void pz_filter_sp_fx ( + const Word16 b [], + const Word16 a [], + Word16 x [], + Word16 y [], + Word16 buf [], + Word16 PNR, + Word16 PDR, + Word16 N, + Word16 Qa +) +{ + Word16 i, j; + Word16 s; + Word16 s_mem; + Word32 Ltemp1; + Word32 Lacc; + + s = negate( Qa ); + s = add( s, s ); /* s=-2Qa*/ + s = add( s, 1 ); + FOR ( i = 0; i < N; i++ ) + { + Lacc = L_deposit_h( x[i] ); /* Lacc in Q(16+Qn)*/ + Lacc = L_shl( Lacc, s ); /* Lacc=x[i] in Q(16+Qn-2Qa+1)*/ + FOR ( j = PDR - 1; j >= 0; j-- ) + Lacc = L_msu( Lacc, buf[j], a[j + 1] ); /*Q(16+Qn-2Qa+1)*/ + + + + Lacc = L_shr( Lacc, 1 ); + Ltemp1 = L_add( L_shl( Lacc, Qa ), 0x08000 ); + s_mem = extract_h( Ltemp1 ); + + Lacc = L_deposit_l(0); + FOR ( j = PNR - 1; j >= 0; j-- ) + Lacc = L_mac( Lacc, buf[j], b[j + 1] ); + Lacc = L_mac( Lacc, s_mem, b[0] ); + /* Lacc in Q(1+Qc+Qn-Qa)*/ + + FOR ( j = s_max(PDR, PNR ) - 1; j > 0; j-- ) + { + /* Update filter memory */ + buf[j] = buf[j - 1]; + move16(); + } + buf[0] = s_mem; + move16(); + + Ltemp1 = L_add( L_shr( Lacc, s ), 0x08000 ); /* Ltemp1 in Qc+Qa+Qn=Q(Qn) */ + y[i] = extract_h( Ltemp1 ); /* y[i] in Qn */ + } +} + + + +Word32 root_a_fx( + Word32 a, + Word16 Q_a, + Word16* exp_out +) +{ + Word16 exp, tmp; + Word32 L_tmp; + + if ( a <= 0 ) + { + *exp_out = 0; + return 0; + } + + exp = norm_l( a ); + tmp = extract_h( L_shl( a, exp ) ); + exp = sub( exp, sub(30, Q_a) ); + tmp = div_s( 16384, tmp ); + L_tmp = L_deposit_h( tmp ); + L_tmp = Isqrt_lc( L_tmp, &exp ); + + *exp_out = exp; + move16(); + + return L_tmp; +} + + +Word32 root_a_over_b_fx( + Word32 a, + Word16 Q_a, + Word32 b, + Word16 Q_b, + Word16* exp_out +) +{ + Word16 tmp, num, den, scale; + Word16 exp, exp_num, exp_den; + Word32 L_tmp; + test(); + if ( ( a <= 0 ) || ( b <= 0 ) ) + { + *exp_out = 0; + move16(); + return 0; + } + + exp_num = norm_l( b ); + num = round_fx( L_shl( b, exp_num ) ); + exp_num = sub( sub( 30, exp_num ), Q_b ); + + exp_den = norm_l( a ); + den = round_fx( L_shl( a, exp_den ) ); + exp_den = sub( sub( 30, exp_den ), Q_a ); + + scale = shr( sub( den, num ), 15 ); + num = shl( num, scale ); + exp_num = sub( exp_num, scale ); + + tmp = div_s( num, den ); + exp = sub( exp_num, exp_den ); + + L_tmp = L_deposit_h( tmp ); + L_tmp = Isqrt_lc( L_tmp, &exp ); + + *exp_out = exp; + move16(); + + return L_tmp; +} + +/*===================================================================*/ +/* FUNCTION : fir_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Generic FIR filter routine */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) b : filter coefficients (Qc). */ +/* _ (Word16 []) x : input signal (Qn). */ +/* _ (Word16) P : filter order. */ +/* _ (Word16) N : number of input samples. */ +/* _ (Word16) Qa : Q factor compensation (Qa=16-Qc) */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) y : output signal (Qn) */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* */ +/* _ : None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*===================================================================*/ +void fir_fx( const Word16 x[], /* i : input vector Qx*/ + const Word16 h[], /* i : impulse response of the FIR filter Q12*/ + Word16 y[], /* o : output vector (result of filtering) Qx*/ + Word16 mem[], /* i/o: memory of the input signal (L samples) Qx*/ + const Word16 L, /* i : input vector size */ + const Word16 K, /* i : order of the FIR filter (K+1 coefs.) */ + const Word16 upd /* i : 1 = update the memory, 0 = not */ + , Word16 shift /* i : difference between Q15 and scaling of h[] */ + ) +{ + + Word16 buf_in[L_FRAME32k+L_FILT_MAX]; + Word16 i, j; + Word32 s; + + /* prepare the input buffer (copy and update memory) */ + Copy( mem, buf_in, K ); + Copy( x, buf_in + K, L ); + IF ( upd ) + { + Copy( buf_in + L, mem, K ); + } + + /* do the filtering */ + FOR ( i = 0; i < L; i++ ) + { + s = L_mult( buf_in[K + i], h[0] ); + + FOR ( j = 1; j <= K; j++ ) + { + s = L_mac( s, h[j], buf_in[K + i - j] ); + } + s = L_shl( s, shift ); + y[i] = round_fx( s ); /*Qx */ + } +} + + +/*--------------------------------------------------------------------------------*/ +/* squant_fx() */ +/*--------------------------------------------------------------------------------*/ +Word16 squant_fx( /* o: index of the winning codeword */ + const Word16 x, /* i: scalar value to quantize */ + Word16* xq, /* o: quantized value */ + const Word16 cb[], /* i: codebook */ + const Word16 cbsize /* i: codebook size */ +) +{ + Word16 tmp; + Word16 c, idx; + Word32 L_mindist, L_dist; + + idx = 0; + move16(); + L_mindist = MAX_32; + move32(); + + FOR ( c = 0; c < cbsize; c++ ) + { + L_dist = L_deposit_l(0); + tmp = sub( x, cb[c] ); + + /*dist += tmp*tmp; */ + L_dist = L_mac( L_dist, tmp, tmp ); + + if ( LT_32( L_dist, L_mindist )) + { + idx = c; + move16(); + } + L_mindist = L_min(L_mindist, L_dist); + } + + *xq = cb[idx]; + move16(); + + return idx; +} + + +/*===================================================================*/ +/* FUNCTION : pz_filter_dp_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Generic pole-zero filter routine, with double */ +/* precision memory, transposed direct form II */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) b : zero filter coefficients (Qc). */ +/* _ (Word16 []) a : pole filter coefficients (Qc), a(0)=1 */ +/* _ (Word16 []) x : input signal (Qx). */ +/* _ (Word16) P : filter order. */ +/* _ (Word16) N : number of input samples. */ +/* _ (Word16) Qa : Q factor compensation (Qa=16-Qc) */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) y : output signal (Qx) */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* */ +/* _ (Word32 []) buf : filter memory (Qx+Qc) */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*===================================================================*/ + +void pz_filter_dp_fx ( + const Word16 b [], + const Word16 a [], + Word16 x [], + Word16 y [], + Word32 buf [], + Word16 PNR, + Word16 PDR, + Word16 N, + Word16 Qa +) +{ + Word16 i, j; + Word16 s; + Word32 s_mem; + Word32 Ltemp1; + Word32 Lacc; + + s = negate( Qa ); + s = add( s, s ); /* s=-2Qa */ + s = add( s, 1 ); + FOR ( i = 0; i < N; i++ ) + { + Lacc = L_deposit_h( x[i] ); /* Lacc in Q(16+Qn)*/ + Lacc = L_shl( Lacc, s ); /* Lacc=x[i] in Q(16+Qn-2Qa+1)*/ + FOR ( j = PDR - 1; j >= 0; j-- ) + Lacc = Msub_32_16( Lacc, buf[j], a[j + 1] ); /*Q(16+Qn-2Qa+1)*/ + + s_mem = L_shl( Lacc, sub( Qa, 1 ) ); /*Qn-Qa+16=Qn+Qc*/ + + Lacc = L_deposit_l(0); + FOR ( j = PNR - 1; j >= 0; j-- ) + Lacc = Madd_32_16( Lacc, buf[j], b[j + 1] ); + Lacc = Madd_32_16( Lacc, s_mem, b[0] ); + /* Lacc in Q(1+Qc+Qn-Qa) */ + + FOR ( j = s_max( PDR, PNR ) - 1; j > 0; j-- ) + { + /* Update filter memory */ + buf[j] = buf[j - 1]; + move16(); + } + buf[0] = s_mem; + move16(); + + Ltemp1 = L_shr( Lacc, s ); /* Ltemp1 in Qc+Qa+Qn=Q(16+Qn) */ + y[i] = extract_h( Ltemp1 ); /* y[i] in Qn */ + } +} + +/*-------------------------------------------------------------------* + * Copy_Scale_sig32_16 + * + * Up/down scale a 32 bits vector and round to 16 bits vector + *-------------------------------------------------------------------*/ +void Copy_Scale_sig32_16( + const Word32 *src, /* i : signal to scale Qx */ + Word16 *dst, /* o : scaled signal Qx */ + Word16 len, /* i : size of x[] Q0 */ + Word16 exp0) /* i : exponent: x = round(x << exp) Qx ?exp */ +{ + Word16 i; + Word32 L_temp; + + IF (exp0 == 0) + { + FOR (i = 0; i < len; i++ ) + { + *dst++ = round_fx(*src++); + } + return; + } + + FOR (i = 0; i < len; i++ ) + { + L_temp = L_shl(*src++, exp0); + + *dst++ = round_fx(L_temp); + } +} + +/*-------------------------------------------------------------------* + * add_vec() + * + * Addition of two vectors sample by sample + *-------------------------------------------------------------------*/ + +void add_vec_fx( + const Word16 x1[], /* i : Input vector 1 */ + const Word16 Qx1, /* i : SCaling of input 1 */ + const Word16 x2[], /* i : Input vector 2 */ + const Word16 Qx2, /* i : SCaling of input 1 */ + Word16 y[], /* o : Output vector that contains vector 1 + vector 2 */ + const Word16 Qy, /* i : SCaling of output 1 */ + const Word16 N /* i : Vector lenght */ +) +{ + Word16 i, Qyx1, Qyx2; + Qyx1 = sub(Qx1,Qy); + Qyx2 = sub(Qx2,Qy); + IF (Qyx1 == 0) + { + FOR (i=0 ; i0: Val was Left Shifted, <0:Right Shifted) */ + Word32 L_val2, /* i: Mantisa of Val2 */ + Word16 exp2, /* i: Exp of Val2 (same as exp1) */ + Word16 *exp /* o: Exp of Result (# of 'L_shl' Req to get to Final Value) */ +) +{ + Word16 temp; + + /* Normalize Energy #1 */ + temp = norm_l(L_val1); + L_val1 = L_shl(L_val1, temp); + /* Adjust Exponent of Energy #1 */ + exp1 = add(exp1, temp); + + /* Normalize Energy #2 */ + temp = norm_l(L_val2); + L_val2 = L_shl(L_val2, temp); + /* Adjust Exponent of Energy #1 */ + exp2 = add(exp2, temp); + + /* Prepare for Inverse */ + temp = round_fx(L_val1); + temp = div_s(16384, temp); + /* Mult Now */ + L_val2 = Mult_32_16(L_val2, temp); + exp1 = add(sub(exp2, exp1), 15*2); + + /* Here Result of ('L_val2' / 2^'exp2') / ('L_val1' / 2^'exp1') is */ + /* 'L_val2' / 2^'exp1' */ + /* Which is val2/val1 instead of val1/val2 because we will use Inverted Square Root */ + /* Normalize before Square Root */ + temp = norm_l(L_val2); + L_val2 = L_shl(L_val2, temp); + exp1 = add(temp, exp1); + /* Do Sqrt */ + temp = sub(31, exp1); + L_val1 = Isqrt_lc(L_val2, &temp); + + *exp = temp; + move16(); + + return L_val1; +} + +Word16 Invert16( /* result in Q'15 + 'exp' */ + Word16 val, + Word16 *exp) +{ + Word16 temp; + + /* prevent 0 input */ + val = s_max(val,1); + /* Normalize Value */ + temp = norm_s(val); + val = shl(val, temp); + + *exp = sub(sub(15-1, *exp), temp); + move16();/* -1 because of 0x4000 is 1.0 in Q14 (and not Q15) */ + + temp = div_s(0x4000, val); + + return temp; +} + +Word16 find_rem(Word16 n, Word16 m, Word16 *r) +{ + Word16 i, q1, q2, qd; + Word32 Ltemp2; + Word32 Lacc; + + test(); + test(); + IF (n<=0 || m<=0 || n=0) + { + Lacc=L_add(L_shl(Lacc,1),1); + } + ELSE + { + Lacc=L_add(Lacc,Ltemp2); + Lacc=L_shl(Lacc,1); + } + } + q1=extract_l(Lacc); + Ltemp2=L_shr(Lacc,q2); + *r=extract_h(Ltemp2); + return(q1); +} + + +Word32 find_remd(Word32 n, Word32 m, Word32 *r) +{ + Word16 i, q1, q2, qd; + Word32 Ltemp2, qo; + Word32 Lacc; + + test(); + test(); + IF (n<=0 || m<=0 || n=0) + { + Lacc=L_shl(Lacc,1); + qo=L_add(qo,1); + } + ELSE + { + Lacc=L_add(Lacc,Ltemp2); + Lacc=L_shl(Lacc,1); + } + } + *r=L_shr(Lacc,q2); + return(qo); +} + +Word16 rint_new_fx ( + Word32 x /*Q16 */ +) +{ + Word16 a; + Word32 L_tmp; + Word16 frac, tmp; + + /* middle value point test */ + frac = lshr(extract_l(x),1); /*Q15 */ + tmp = sub(frac,0x4000); + + IF (!tmp) + { + a = add(extract_h(x),1); + + if (s_and(a,1) == 0) + { + return a; + } + if (s_and(a,1) != 0) + { + return extract_h(x); + } + return extract_h(x); + } + ELSE + { + L_tmp = L_add(x,32768); /*Q16 */ + return extract_h(L_tmp); + } +} + + +/*===================================================================*/ +/* FUNCTION : erb_diff_search_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : erb amplitude VQ search for QPPP */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16 []) prev_erb : Previous erb amplitude, Q13 */ +/* _ (Word16 []) curr_erb : Current erb amplitude, Q13 */ +/* _ (Word16 []) dif_erb: erb differential, Q13 */ +/* _ (Word16 []) pow_spec : LPC power spectrum, Q7 */ +/* _ (Word16 [][]) cb_fx : differential erb codebook, Q13 */ +/* _ (Word16) cb_size : codebook size */ +/* _ (Word16) cb_dim : codebook dimension */ +/* _ (Word16) offset : index to current segment of erb array */ +/* for quantization */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word16) index: best codebook index */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*===================================================================*/ + +Word16 erb_diff_search_fx(Word16 *prev_erb, const Word16 *curr_erb, Word16 *dif_erb, + Word16 *pow_spec, const Word16 *cb_fx, + Word16 cb_size, Word16 cb_dim, Word16 offset) +{ + Word16 i, j, mmseindex ; + Word16 dh, dl; + Word32 mmse; + Word32 Ltemp1; + Word32 Lacc; + + mmse = EVS_LW_MAX; + move32(); + mmseindex = -1; + move16(); + FOR (j=0; j b[3] = {0.893554687, -1.787109375, 0.893554687}; * + * a[3] = {1.000000000, 1.787109375, -0.864257812}; * + *-----------------------------------------------------------------------*/ +void hp400_12k8_fx( + Word16 signal[], /* i/o: input signal / output is divided by 16 */ + const Word16 lg, /* i : lenght of signal */ + Word16 mem[] /* i/o: filter memory [6] */ +) +{ + Word16 i; + Word16 y1_hi, y1_lo; + Word32 L_tmp, L_tmp2, L_tmp3; + + y1_hi = mem[2]; + move16(); + y1_lo = mem[3]; + move16(); + + L_tmp3 = L_mac(16384L, mem[1], a_hp400_fx[2]); /* rounding to maximize precision */ + L_tmp3 = L_mac(L_tmp3, y1_lo, a_hp400_fx[1]); + L_tmp3 = L_shr(L_tmp3, 15); + L_tmp2 = L_mac(L_tmp3, mem[0], a_hp400_fx[2]); + L_tmp2 = L_mac(L_tmp2, mem[5], b_hp400_fx[2]); + L_tmp2 = L_mac(L_tmp2, mem[4], b_hp400_fx[1]); + L_tmp3 = L_mult(mem[4], b_hp400_fx[2]); + + mem[5] = signal[lg-2]; + + FOR (i = 1; i < lg; i++) + { + /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] */ + /* + a[1]*y[i-1] + a[2] * y[i-2] */ + + L_tmp = L_mac(L_tmp2, y1_hi, a_hp400_fx[1]); + L_tmp = L_mac(L_tmp, *signal, b_hp400_fx[0]); + + L_tmp = L_shl(L_tmp, 1); /* coeff Q12 --> Q13 */ + + L_tmp2 = L_mac(L_tmp3, y1_hi, a_hp400_fx[2]); + L_tmp2 = L_mac(L_tmp2, *signal, b_hp400_fx[1]); + L_tmp3 = L_mac(16384L, y1_lo, a_hp400_fx[2]); /* rounding to maximize precision */ + + y1_lo = L_Extract_lc(L_tmp, &y1_hi); + + L_tmp3 = L_mac(L_tmp3, y1_lo, a_hp400_fx[1]); + L_tmp3 = L_shr(L_tmp3, 15); + + L_tmp2 = L_add(L_tmp3, L_tmp2); + + L_tmp3 = L_mult(*signal, b_hp400_fx[2]); + + /* signal is divided by 16 to avoid overflow in energy computation */ + *signal++ = round_fx(L_tmp); + } + + /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] */ + /* + a[1]*y[i-1] + a[2] * y[i-2] */ + + L_tmp = L_mac(L_tmp2, y1_hi, a_hp400_fx[1]); + + mem[4] = *signal; + move16(); + L_tmp = L_mac(L_tmp, mem[4], b_hp400_fx[0]); + + L_tmp = L_shl(L_tmp, 1); /* coeff Q12 --> Q13 */ + + mem[0] = y1_hi; + move16(); + mem[1] = y1_lo; + move16(); + L_Extract(L_tmp, &mem[2], &mem[3]); + + /* signal is divided by 16 to avoid overflow in energy computation */ + *signal++ = round_fx(L_tmp); + + return; +} + + +Word16 dot_prod_satcontr(const Word16 *x, const Word16 *y, Word16 qx, Word16 qy, Word16 *qo, Word16 len) +{ + Word16 tmp_tab_x[L_FRAME16k]; + Word16 tmp_tab_y[L_FRAME16k]; + Word16 shift, q, ener, i; + Word32 L_tmp; + Word16 *pt1, *pt2; + + + Copy( x, tmp_tab_x, len ); /* OPTIMIZE !!!!! the copy into local table is not necessary */ + Copy( y, tmp_tab_y, len ); /* could be reworked to do a 1st iteration with the original x[] and y[] */ + /* then check if there is an overflow and do a more complex 2nd, 3rd, ... processing */ + shift = 0; + move16(); + BASOP_SATURATE_WARNING_OFF + DO + { + Overflow = 0; + move16(); + L_tmp = L_shl(1, s_max(sub(add(add(qx, qy), 7), shift), 0)); + pt1 = tmp_tab_x; + pt2 = tmp_tab_y; + FOR ( i = 0; i < len; i++ ) + { + L_tmp = L_mac0(L_tmp, *pt1++, *pt2++); /*Q(qx+qy-shift) */ + } + + IF(Overflow != 0) + { + Scale_sig(tmp_tab_x, len, -2); + Scale_sig(tmp_tab_y, len, -2); + shift = add(shift, 4); + } + } + WHILE(Overflow != 0); + BASOP_SATURATE_WARNING_ON + + q = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, q); /*Q(qx+qy-shift+q) */ + ener = extract_h(L_tmp); /*Q(qx+qy-shift+q-16) */ + q = add(q, add(qx, qy)); + *qo = sub(q, add(shift, 16)); + + return ener; +} + + +/* + * E_UTIL_f_convolve + * + * Parameters: + * x I: input vector <14bits + * h I: impulse response (or second input vector) (1Q14) + * y O: output vetor (result of convolution) + * + * Function: + * Perform the convolution between two vectors x[] and h[] and + * write the result in the vector y[]. All vectors are of length L. + * Only the first L samples of the convolution are considered. + * Vector size = L_SUBFR + * + * Returns: + * void + */ +void E_UTIL_f_convolve(const Word16 x[], const Word16 h[], Word16 y[], const Word16 size) +{ + Word16 i, n; + Word32 L_sum; + Word64 L64_sum; + + FOR (n = 0; n < size; n++) + { + L64_sum = 0; + FOR (i = 0; i < n; i++) + { + L64_sum = W_mac_16_16(L64_sum, x[i], h[n - i]); + } + L_sum = W_sat_l(L64_sum); + y[n] = mac_r(L_sum, x[i], h[0]); + } + return; +} + +/*----------------------------------------------------------------------------- + * floating_point_add: + * + * Add two floating point numbers: x <- x + y. + *----------------------------------------------------------------------------*/ +void floating_point_add( + Word32 *mx, /* io: mantissa of the addend Q31 */ + Word16 *ex, /* io: exponent of the addend Q0 */ + const Word32 my, /* i: mantissa of the adder Q31 */ + const Word16 ey /* i: exponent of the adder Q0 */ +) +{ + Word32 accX, accY; + Word16 align, expo; + /* NB: This function will not work properly if the mantissa is zero and the exponent is not 32. + It is up to the caller function to avoid this condition. */ + /* Ensure 1 bit headroom before addition. */ + accX = L_shr(*mx, 1); + accY = L_shr(my, 1); + /* First, align the Q-points of the two operands. Then, add. */ + align = sub(*ex, ey); + test(); + IF (align < 0) + { + accX = L_add(accX, L_shl(accY, align)); + } + ELSE + { + accX = L_add(accY, L_shr(accX, align)); + *ex = ey; + move16(); + } + /* Normalize the result and update the mantissa and exponent. */ + expo = norm_l(accX); + *mx = L_shl(accX, expo); + *ex = sub(add(*ex, expo), 1); /* Subtract 1 due to 1-bit down-shift above ensuring 1 bit headroom before addition. */ + return; +} + diff --git a/lib_com/trans_direct_fx.c b/lib_com/trans_direct_fx.c new file mode 100644 index 0000000..88d9495 --- /dev/null +++ b/lib_com/trans_direct_fx.c @@ -0,0 +1,204 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "stl.h" +#include "cnst_fx.h" /* Common FX constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Function prototypes */ + + + +void direct_transform_fx( + const Word32 in32_fx[], + Word32 out32_fx[], + const Word16 is_transient, + const Word16 L, + Word16 *Q +) +{ + + Word16 i, k; + Word16 seg; + Word16 segment_length, segment_length2, segment_length4; + + const Word16 *wh_fx; + const Word16 *wl_fx; + const Word32 *sh_fx; + const Word32 *sl_fx2; + Word32 *sl_fx; + Word32 *iseg_fx; + Word32 *oseg_fx; + Word32 dctin32_fx[L_FRAME48k]; + Word32 in32_r16_fx[L_FRAME48k]; + + const Word16 *win_fx; + Word16 shift, Qmin = 31; + Word32 L_tmp; + Word16 Qs[NUM_TIME_SWITCHING_BLOCKS]; + + + segment_length = shr(L, 1); + segment_length2 = shr(segment_length, 1); + segment_length4 = shr(segment_length2, 1); + + IF (is_transient) + { + IF (EQ_16(L, L_FRAME48k)) + { + win_fx = wscw16q15_fx; + } + ELSE IF (EQ_16(L, L_FRAME32k)) + { + win_fx = wscw16q15_32_fx; + } + ELSE IF (EQ_16(L, L_FRAME8k)) + { + win_fx = wscw16q15_8_fx; + } + ELSE + { + win_fx = wscw16q15_16_fx; + } + + sh_fx = &in32_fx[L-1]; + add(0,0); + sl_fx = &in32_r16_fx[L-1]; + add(0,0); + FOR (i = 0; i < segment_length; i++) + { + in32_r16_fx[i] = (*sh_fx--); + move32(); + (*sl_fx--) = in32_fx[i]; + move32(); + } + + iseg_fx = &in32_r16_fx[-segment_length4]; + add(0,0); + oseg_fx = out32_fx; + + wh_fx = &win_fx[segment_length4]; + add(0,0); + wl_fx = wh_fx - 1; + + shift = extract_l(L_mult0(3, segment_length4)); + sh_fx = &iseg_fx[shift]; + add(0,0); + sl_fx2 = sh_fx - 1; + + + FOR (i = 0; i < segment_length4; i++) + { + L_tmp = L_negate(Mult_32_16( (*sh_fx++), (*wh_fx++) )); /*Q+15-15=Q */ + dctin32_fx[i] = Madd_32_16(L_tmp, *sl_fx2--, *wl_fx-- ); + move32();/*Q */ + } + + sl_fx2 = &iseg_fx[segment_length2 - 1]; + add(0,0); + + FOR (i = segment_length4; i < segment_length2; i++) + { + dctin32_fx[i] = L_negate(*sl_fx2--); + move32(); + } + + Qs[0] = *Q; + move16(); + edct_fx(dctin32_fx, oseg_fx, segment_length2, &Qs[0]); + Qmin = s_min(Qs[0], Qmin); + + iseg_fx += segment_length2; + add(0,0); + oseg_fx += segment_length2; + add(0,0); + + FOR (seg = 1 ; seg < NUM_TIME_SWITCHING_BLOCKS-1; seg++) + { + wh_fx = &win_fx[segment_length4]; + add(0,0); + wl_fx = wh_fx - 1; + sh_fx = &iseg_fx[shift]; + add(0,0); + sl_fx2 = sh_fx - 1; + FOR (i = 0; i < segment_length4; i++) + { + L_tmp = L_negate(Mult_32_16( (*sh_fx++), (*wh_fx++) )); /*Q+15-15=Q */ + dctin32_fx[i] = Madd_32_16(L_tmp, *sl_fx2--, *wl_fx-- ); + move32(); /*Q */ + } + + sh_fx = iseg_fx; + sl_fx2 = &iseg_fx[segment_length2 - 1]; + add(0,0); + wh_fx = &win_fx[segment_length2 - 1]; + add(0,0); + wl_fx = win_fx ; + + FOR (i = segment_length4; i < segment_length2; i++) + { + L_tmp = Mult_32_16( (*sh_fx++), (*wh_fx--) ); /*Q+15-15=Q */ + dctin32_fx[i] = Madd_32_16(L_tmp, *sl_fx2--, *wl_fx++ ); + move32(); /*Q */ + } + + Qs[seg] = *Q; + move16(); + edct_fx(dctin32_fx, oseg_fx, segment_length2, &Qs[seg]); + Qmin = s_min(Qs[seg], Qmin); + + iseg_fx += segment_length2; + add(0,0); + oseg_fx += segment_length2; + add(0,0); + } + + sh_fx = &iseg_fx[shift - 1]; + add(0,0); + FOR (i = 0; i < segment_length4; i++) + { + dctin32_fx[i] = L_negate(*sh_fx--); + move32(); + } + + + sh_fx = iseg_fx; + sl_fx2 = &iseg_fx[segment_length2 - 1]; + add(0,0); + wh_fx = &win_fx[segment_length2 - 1]; + add(0,0); + wl_fx = win_fx; + + FOR (i = segment_length4; i < segment_length2; i++) + { + L_tmp = Mult_32_16( (*sl_fx2--), (*wl_fx++) ); /*Q+15-15=Q */ + dctin32_fx[i] = Madd_32_16(L_tmp, *sh_fx++, *wh_fx-- ); + move32(); /*Q */ + } + Qs[NUM_TIME_SWITCHING_BLOCKS-1] = *Q; + move16(); + edct_fx(dctin32_fx, oseg_fx, segment_length2, &Qs[NUM_TIME_SWITCHING_BLOCKS-1]); + Qmin = s_min(Qs[NUM_TIME_SWITCHING_BLOCKS-1], Qmin); + + *Q = Qmin; + move16(); + oseg_fx = out32_fx; + FOR ( k=0; k 0) && (GT_16(cntnzcr, maxnzcr[tmp_fx2]))) + { + maxnzcr[tmp_fx2] = cntnzcr; + move16(); + } + + firstnzcr = 0; + move16(); + cntnzcr = -1; + move16(); + } + fxptr2++; + fxptr3++; + } + if(LT_16(j, NUMSF_M1)) + { + cntnzcr = add(cntnzcr, 1); + } + sptr2_loc = s_max(sptr2_loc, cntnzcr); + *fx32ptr4 = tmp_fxL2; + move32(); + fx32ptr4++; + *sptr1 = sptr1_loc; + move16(); + *sptr2 = sptr2_loc; + move16(); + sptr1++; + sptr2++; + + test(); + if( (firstnzcr > 0) && (GT_16(cntnzcr, maxnzcr[tmp_fx2]))) + { + maxnzcr[tmp_fx2] = cntnzcr; + move16(); + } + + sptr1_loc = 0; + move16(); + test(); + firstnzcr = 1; + move16(); + IF((LT_16(j, NUMSF_M1))&&(L_mult0(*fxptr2,*(fxptr2-1))<=0)) /* zcr between 2 subframes */ + { + sptr1_loc = add(sptr1_loc, 1); /* counts for the nexte subframe */ + cntnzcr = -1; + move16(); + firstnzcr = 0; + move16(); + } + + *fx32ptr1 = tmp_fxL1; + move32(); + if( LT_32(*fx32ptr5, L_shr(*fx32ptr1, 1))) + { + tmp_fxL1 = L_shl(L_sub(*fx32ptr1, *fx32ptr5),1); + } + *fx32ptr5 = tmp_fxL1; + move32(); + + fx32ptr1++; + fx32ptr5++; + fx32ptr6++; + } + + fxptr2 = imdct_mem_fx; /* q_sig16 or q-1*/ + j = NUMSF; + move16(); /* one future subframe but 96 samples (not 80) (enough with ALDO window) */ + tmp_fx1 = shr(*fxptr2, qmemp1); /* q-1 shr to avoid overflow in es_mdct_fx*/ + tmp_fxL1 = L_mac0(25, tmp_fx1, tmp_fx1); + + sptr1_loc = 0; + move16(); + fxptr2++; + tmp_fx3 = sub(len3xLp20,1); + FOR (i = 1; i < len3xLp20; i++) + { + tmp_fx1 = shr(*fxptr2, qmemp1); /*q-1 to avoisd saturation in energy*/ + tmp_fxL1 = L_mac0(tmp_fxL1, tmp_fx1, tmp_fx1); + + if(*fxptr2 **(fxptr2-1) <= 0) + { + sptr1_loc = add(sptr1_loc,1); + } + + fxptr2++; + } + *fx32ptr1 = tmp_fxL1; + move32(); + *sptr1 = sptr1_loc; + fxptr2 = imdct_mem_fx; + fxptr3 = imdct_mem_fx + 1; + fxptr4 = imdct_mem_fx + 2; + tmp_fxL1 = L_mult(rec_sig_fx[framelength_m1], -8192); + tmp_fxL1 = L_mac(tmp_fxL1, *fxptr3, -8192); + tmp_fx1 = mac_r(tmp_fxL1, *fxptr2, 16384); + + tmp_fxL2 = L_deposit_l(100); + tmp_fxL2 = L_mac0(tmp_fxL2, tmp_fx1, tmp_fx1); + + FOR(j = 1; j < tmp_fx3; j++) /* tmp_fx3 still contains subframelength*1.2-1 */ + { + tmp_fxL1 = L_mult(*fxptr2, -8192); + tmp_fxL1 = L_mac(tmp_fxL1, *fxptr4, -8192); + tmp_fx1 = mac_r(tmp_fxL1, *fxptr3, 16384); + + tmp_fxL2 = L_mac0(tmp_fxL2, tmp_fx1, tmp_fx1); + fxptr2++; + fxptr3++; + fxptr4++; + } + + tmp_fxL1 = L_mult(*fxptr2, -8192); + tmp_fx1 = mac_r(tmp_fxL1, *fxptr3, 16384); + es_mdct_hb_fx[NUMSF] = L_mac0(tmp_fxL2, tmp_fx1, tmp_fx1); + move32(); + + max_es_hb_fx = L_add(es_mdct_hb_fx[0], 0); /* for memorising the max energy */ + max_es_fx = L_add(es_mdct_fx[0], 0); /* for memorising the max energy */ + maxind = 0; + move16(); + FOR (i = 1; i <= NUMSF; i++) + { + IF (GE_32(es_mdct_hb_fx[i], max_es_hb_fx)) /* '=' to handle the first window*/ + { + max_es_hb_fx = L_add(es_mdct_hb_fx[i], 0); /* max energy low band, 8 present and 1 future subframes */ + } + + IF (GE_32(es_mdct_fx[i], max_es_fx)) /* '=' to handle the first window*/ + { + max_es_fx = L_add(es_mdct_fx[i], 0); /* max energy low band, 8 present and 1 future subframes */ + maxind = i; + move16(); + } + } + + cnt2 = cnt5 = 0; + move16(); + move16(); + test(); + if( *prevflag != 0 || LT_32(max_es_fx, L_mult0(subframelength, 2500))) + { + maxind = 0; + move16(); + } + + if( LT_32(max_es_fx, L_shl(mean_prev_fx_loc, 2)))/*OK if saturated*/ + { + maxind = 0; + move16(); + } + *prevflag = 0; + move16(); + + FOR (i = 0; i < maxind; i++) /* only subbands before max energy subband are handled */ + { + g_fx = 32767; + move16(); /* default gain */ + min_g_fx[i] = 32767; + move16(); + min_g_hb_fx[i] = 32767; + move16(); + + Mpy_32_16_ss(es_mdct_half_fx[i], 328, &tmp_fxL1, &tmp_u16); /* 328 for 1/100*/ + Mpy_32_16_ss(es_mdct_half_fx[i], 3277, &tmp_fxL2, &tmp_u16); /* 3277 for 1/10*/ + Mpy_32_16_ss(es_mdct_fx[i], 5461, &tmp_fxL3, &tmp_u16); /* 5461 for 1/6*/ + test(); + test(); + test(); + IF( ( GT_32(tmp_fxL1, L_add(mean_prev_nc_fx_loc,125000)))||/* less then 20% energy in 3/4 of the subframe -> starting onset in the last quarter */ + (( GT_32(tmp_fxL2, L_add(mean_prev_nc_fx_loc,125000))) && + ((LT_16(zcr[i], limzcr))||(LT_32(es_mdct_quart_fx[i],tmp_fxL3))))) /* already an offset, plosif, do not touch */ + { + maxind = i; + move16(); /* no preecho reduction after the first subframe with gain 1 */ + *prevflag = 1; + move16(); + FOR(j = sub(i,1); j >= 0; j--) + { + if (GT_32(es_mdct_fx[j], L_shr(es_mdct_fx[i],1))) + { + maxind = j; + move16(); + } + } + } + ELSE + { + IF (LT_32(es_mdct_fx[i], L_shr(max_es_fx, 4))) + { + g_fx = lim16_fx; + move16(); + cnt5 = add(cnt5,1); + + IF (LT_32(es_mdct_fx[i], L_shr(max_es_fx, 5))) + { + g_fx = lim32_fx; + move16(); + cnt2 = add(cnt2, 1); + } + + IF(LT_32(mean_prev_fx_loc, es_mdct_fx[i])) + { + tmp_fx1 = norm_l(es_mdct_fx[i]); + tmp_fxL1 = L_shl(es_mdct_fx[i], tmp_fx1); + tmp_fxL2 = L_shl(mean_prev_fx_loc, tmp_fx1); + tmp_fx1 = round_fx(tmp_fxL1); + tmp_fx2 = round_fx(tmp_fxL2); + tmp_fx3 = div_s(tmp_fx2, tmp_fx1); + min_g_fx[i] = Frac_sqrt(tmp_fx3); + move16(); + } + + IF(LT_32(mean_prev_hb_fx_loc, es_mdct_hb_fx[i])) + { + tmp_fx1 = norm_l(es_mdct_hb_fx[i]); + tmp_fxL1 = L_shl(es_mdct_hb_fx[i], tmp_fx1); + tmp_fxL2 = L_shl(mean_prev_hb_fx_loc, tmp_fx1); + tmp_fx1 = round_fx(tmp_fxL1); + tmp_fx2 = round_fx(tmp_fxL2); + tmp_fx3 = div_s(tmp_fx2, tmp_fx1); + min_g_hb_fx[i] = Frac_sqrt(tmp_fx3); + move16(); + } + test(); + IF( (LT_16(zcr[i], limzcr/2))||(GT_16(maxnzcr[i],limmaxnzcr))) + { + if(LT_16(min_g_fx[i], 32767)) /* *mean_prev < es_mdct[i]) */ + { + mean_prev_fx_loc = L_add(es_mdct_fx[i], 0); + } + min_g_fx[i] = 32767; + move16(); /* not noise-like, do not touch the amplitude, but may do in HB*/ + } + } + ELSE + { + test(); + if( i > 0 && LT_16(maxind, NUMSF)) + { + *prevflag = 1; + move16(); + } + maxind = i; + move16(); /* no preecho reduction after the first subframe with gain 1*/ + } + } + gt_fx[i] = g_fx; + move16(); + gt_hb_fx[i] = g_fx; + move16(); + } + + FOR ( i = maxind; i <= NUMSF; i++ ) /* also for the first memory subframe */ + { + gt_fx[i] = 32767; + move16(); + min_g_fx[i] = 32767; + move16(); + gt_hb_fx[i] = 32767; + move16(); + min_g_hb_fx[i] = 32767; + move16(); + + } + + ind2 = 0; + move16(); + FOR( i = 0; i < NUMSF; i++ ) + { + if( LT_16(gt_fx[i], 32767)) /*gt not yet limited by min_g*/ + { + ind2 = add(i, 1); /* first subframe with gain = 1 after last gain < 1 --> frame with the attack*/ + } + } + + test(); + if( (GT_16(wmold_fx, 16384))&&(LT_16(add(cnt2,cnt5),2))) /* mini either 1 cnt2 (and so also cnt5) or 2 cnt5 */ + { + /* maxind = 0; false alarm, no echo reduction */ + ind2 = 0; + move16(); + } + ind2_m1 = sub(ind2, 1); + ind2_sfl = i_mult(subframelength,ind2); + numsf_ind2 = sub(NUMSF, ind2); + fxptr3 = gt_fx; + fxptr4 = gt_hb_fx; + fxptr5 = min_g_fx; + fxptr6 = min_g_hb_fx; + + fxptr1 = preechogain_fx + smooth_len; + pre_g_ch_tab[0] = smooth_len; + move16(); /*1st after smoothmem*/ + fxptr2 = preechogain_hb_fx; + FOR (i = 0; i < ind2; i++) /* only subbands before max energy subband are handled*/ + { + *fxptr3 = s_max(*fxptr3, *fxptr5); + move16(); + + *fxptr4 = s_max(*fxptr4, *fxptr6); + move16(); + + FOR(j = 0; j < subframelength; j++) + { + *fxptr1 = *fxptr3; + move16(); + *fxptr2 = *fxptr4; + move16(); + fxptr1++; + fxptr2++; + } + pre_g_ch_tab[add(i, 1)] = add(pre_g_ch_tab[i], subframelength); + fxptr3++; + fxptr4++; + fxptr5++; + fxptr6++; + } + + max_plus_es_mdct_fx = L_deposit_l(0); + adv = smooth_len; + move16(); /* samples needed to have near 1 gain after smoothing at the beggining of the attack subframe*/ + advmem = adv; + move16(); + + test(); + test(); + IF( ind2 > 0 || LT_16(wmold_fx, 32767)||LT_16(*wmold_hb_fx,32767)) + { + ptr_fx = imdct_mem_fx; + qtmp = qmemp1; + pluslim = num_subsubframes; + move16(); /* if ind2 == NUMSF */ + IF( numsf_ind2 > 0 ) + { + ptr_fx = rec_sig_fx + ind2_sfl; + qtmp = q16p1; + pluslim = i_mult(numsf_ind2, num_subsubframes); + } + + maxcrit_fx = L_add(mean_prev_nc_fx_loc, 0); + IF( ind2 == 0 ) + { + sum_plus_es_fx = L_add(mean_prev_nc_fx_loc, 0); /* 8 times mean sususb enenrgy (=maxcrit)*/ + pluslim = num_subsubframes; + move16(); + oldgain_fx = wmold_fx; + move16(); + oldgain_hb_fx = *wmold_hb_fx; + move16(); + } + ELSE /* ind2 > 0*/ + { + sum_plus_es_fx = es_mdct_fx[ind2_m1]; + move32(); /* 8 times mean sususb enenrgy (=maxcrit)*/ + oldgain_fx = gt_fx[ind2_m1]; + move16(); + oldgain_hb_fx = gt_hb_fx[ind2_m1]; + move16(); + + tmp_fx1 = mult_r(gt_fx[ind2_m1], gt_fx[ind2_m1]); + Mpy_32_16_ss(es_mdct_fx[ind2_m1], tmp_fx1, &maxcrit_fx, &tmp_u16); + Mpy_32_16_ss(max_es_fx, 410, &tmp_fxL1, &tmp_u16); /* 410 for 1/80*/ + + test(); + if( (GT_32(tmp_fxL1, maxcrit_fx))&&(GT_16(zcr[ind2],limzcr))) + { + maxcrit_fx = L_add(tmp_fxL1, 0); /* still 10 times smaller then mean max_es*/ + } + } + fx32ptr1 = plus_es_mdct_fx; + fx32ptr4 = mean_plus_es_fx + 1; + FOR (j = 0; j < pluslim; j++) /* 8 sub-subframes */ + { + tmp_fxL1 = 100; + move16(); + FOR (i = 0; i < subsubframelength; i++) + { + + tmp_fx1 = shr(*ptr_fx, qtmp); /* q-1, to have same shift as es_mdct_.. */ + tmp_fxL1 = L_mac0(tmp_fxL1, tmp_fx1, tmp_fx1); + ptr_fx++; + } + if( GT_32(tmp_fxL1, max_plus_es_mdct_fx)) + { + max_plus_es_mdct_fx = L_add(tmp_fxL1, 0); + } + + sum_plus_es_fx = L_add(sum_plus_es_fx, L_shl(tmp_fxL1, 2)); + *fx32ptr1 = tmp_fxL1; + fx32ptr1++; + Mpy_32_16_ss(sum_plus_es_fx, inv_jp2[j], fx32ptr4, &tmp_u16); /* 410 for 1/80*/ + if( LT_32(*fx32ptr4, maxcrit_fx)) + { + *fx32ptr4 = maxcrit_fx; + move32(); + } + fx32ptr4++; + } + *fx32ptr4 = -1; + move32(); /*mean_plus_es_fx[pluslim] = -1; */ + *mean_plus_es_fx = *plus_es_mdct_fx; + move32(); /* index [0] */ + if( LT_32(*mean_plus_es_fx, maxcrit_fx)) + { + *mean_plus_es_fx = maxcrit_fx; + move32(); + } + + j = 0; + move16(); + WHILE((LT_32(plus_es_mdct_fx[j], mean_plus_es_fx[j]))&&(LT_32(plus_es_mdct_fx[j],max_plus_es_mdct_fx/8))) + { + test(); + j = add(j,1); + } + tmp_fx3 = i_mult(j,subsubframelength); + adv = sub(adv, tmp_fx3); + IF( numsf_ind2 > 0 ) /* onset not in future frame */ + { + fxptr1 = preechogain_fx + ind2_sfl+smooth_len; + fxptr2 = preechogain_hb_fx + ind2_sfl; + + FOR (i = 0; i < tmp_fx3; i++) + { + *fxptr1 = oldgain_fx; + move16(); /*keep the gain of the previous subframe*/ + *fxptr2 = oldgain_hb_fx; + move16(); /*keep the gain of the previous subframe*/ + fxptr1++; + fxptr2++; + } + } + } + + IF(ind2>0) + { + /* check increasing energy of preecho by regression last 3 subframes (if possible) */ + ind3 = add(ind2, shr(j, log2_num_subsubframes)); /* return (with rounding) to subframe basis */ + ind4 = sub(ind3, 1); + ind5 = sub(ind3, 2); + ind6 = sub(ind3, 3); + IF( ind4 > 0 ) + { + /* case of 3 points is simply */ + eshbmean2_fx = L_add(es_mdct_hb_fx[ind4], es_mdct_hb_fx[ind5]); + + sxyhb2_fx = L_sub(es_mdct_hb_fx[ind4], es_mdct_hb_fx[ind5]); /* / eshbmean2 * 2; 04042013: division not needed, only sign of sxyhb2 is used*/ + + IF( GT_16(ind3, 2)) + { + tmp_fxL1 = L_add(eshbmean2_fx, es_mdct_hb_fx[ind6]); + Mpy_32_16_ss(tmp_fxL1, 4369, &eshbmean3_fx, &tmp_u16); /*10922 : 1/3*/ + sxylb3_fx = L_sub(es_mdct_fx[ind4], es_mdct_fx[ind6]); /* /eslbmean3 / 2; /2 for 3 points regression calc; 04042013: division not needed, only sign of sxylb3 is used*/ + tmp_fxL1 = L_sub(es_mdct_hb_fx[ind4], es_mdct_hb_fx[ind6]); + test(); + IF ((LT_32(tmp_fxL1, eshbmean3_fx))||(sxylb3_fx<0)) + { + ind2 = 0; + move16(); + ind2_sfl = 0; + move16(); + adv = advmem; + move16(); + } + } + ELSE + { + IF (sxyhb2_fx < 0) + { + ind2 = 0; + move16(); + ind2_sfl = 0; + move16(); + adv = advmem; + move16();/* 04042013: small bug corection*/ + } + } + + tmp_fxL1 = L_add(eshbmean2_fx, es_mdct_hb_fx[ind3]); + Mpy_32_16_ss(tmp_fxL1, 4369, &eshbmean3_fx, &tmp_u16); /*10922 : 1/3*/ + + tmp_fxL1 = L_sub(es_mdct_hb_fx[ind3], es_mdct_hb_fx[ind5]); + IF (LT_32(tmp_fxL1, eshbmean3_fx)) + { + ind2 = 0; + move16(); + ind2_sfl = 0; + move16(); + adv = advmem; + move16(); + } + } + } + + ind2_m1 = sub(ind2, 1);/*ind2_m1 needs to be recomputed as ind2 could have changed since*/ + + stind = sub(ind2_sfl, adv); + stind_hb = add(stind, advmem); + if( stind < 0 ) + { + stind = 0; + move16(); + } + + if( stind_hb < 0 ) + { + stind_hb = 0; + move16(); + } + + tmp_fx1 = add(stind, smooth_len); + fxptr1 = preechogain_fx + tmp_fx1; + fxptr2 = preechogain_hb_fx + stind_hb; + + FOR (i = tmp_fx1; i < framelength; i++) /* rest of the gains, without 4 (PREECHO_SMOOTH_LEN) 1 for fadeout */ + { + *(fxptr1++) = 32767; + move16(); + } + pre_g_ch_tab[ind2] = s_min(tmp_fx1, framelength); + move16(); + + FOR (i = stind_hb; i < framelength; i++) /* rest of the gains*/ + { + *(fxptr2++) = 32767; + move16(); + } + + fxptr1 = preechogain_fx; + FOR (i = 0; i < smooth_len; i++) + { + *(fxptr1++) = *smoothmem_fx; + move16(); + } + + fattnext_fx = 32767; + move16(); + if( GT_16(stind, framelength)) + { + fattnext_fx = gt_fx[ind2_m1]; + move16(); + } + + fxptr1 = preechogain_fx + framelength; + FOR (i = 0; i < smooth_len; i++) + { + *(fxptr1++) = fattnext_fx; + move16(); + } + + FOR (i = 0; i <= ind2; i++) + { + tmp_fx1 = pre_g_ch_tab[i]; + move16(); + tmp_fx2 = sub(tmp_fx1, smooth_len); /* any index in the previous subframe*/ + tmp_fx3 = mult_r(sub(preechogain_fx[tmp_fx1], preechogain_fx[tmp_fx2]), invsmoothlenp1_fx);/*step*/ + tmp_fx1 = tmp_fx3; + move16(); /*cumulated step*/ + fxptr1 = preechogain_fx + tmp_fx2; + FOR(j = 0; j < smooth_len; j++) + { + *fxptr1 = add(*fxptr1, tmp_fx1); + move16(); + tmp_fx1 = add(tmp_fx1, tmp_fx3); + fxptr1++; + } + } + + *smoothmem_fx = fattnext_fx; + move16(); + *wmold_hb_fx = preechogain_hb_fx[framelength_m1]; + move16(); + + /* apply gain */ + fxptr1 = preechogain_fx; + fxptr2 = preechogain_hb_fx; + fxptr3 = rec_sig_fx; + fxptr4 = rec_sig_lb_fx; + fxptr5 = rec_sig_hb_fx; + FOR (i = 0; i < framelength; i++) + { + tmp_fxL1 = L_mult(*fxptr4, *fxptr1); + *fxptr3 = mac_r(tmp_fxL1, *fxptr5, *fxptr2); + move16(); + fxptr1++; + fxptr2++; + fxptr3++; + fxptr4++; + fxptr5++; + } + + mean_prev_nc_fx_loc = L_add(es_mdct_fx[0], 0); /* compute mean not corrected by the actual gains*/ + + FOR (i = 1; i < NUMSF; i++) /* all present subbands */ + { + if( EQ_16(i, NUMSF_S2)) + { + savehalfe_fx = L_add(mean_prev_nc_fx_loc, 0); + } + mean_prev_nc_fx_loc = L_add(mean_prev_nc_fx_loc, es_mdct_fx[i]); + } + + if( LT_32(savehalfe_fx, L_shr(mean_prev_nc_fx_loc,1) )) + { + mean_prev_nc_fx_loc = L_shl(L_sub(mean_prev_nc_fx_loc, savehalfe_fx), 1); + } + mean_prev_nc_fx_loc = L_shr(mean_prev_nc_fx_loc, 3); /* >> LOG2_NUMSF in fixpoint */ + + FOR( i = 0; i < ind2; i++ ) /* only subbands before max energy subband are handled*/ + { + tmp_fx1 = mult_r(gt_fx[i], gt_fx[i]); + Mpy_32_16_ss(es_mdct_fx[i], tmp_fx1, &es_mdct_fx[i], &tmp_u16); + + tmp_fx1 = mult_r(gt_hb_fx[i], gt_hb_fx[i]); + Mpy_32_16_ss(es_mdct_hb_fx[i], tmp_fx1, &es_mdct_hb_fx[i], &tmp_u16); + + } + + mean_prev_fx_loc = L_shr(es_mdct_fx[0],3); /* compute mean used in next frame to limit gain*/ + mean_prev_hb_fx_loc = L_shr(es_mdct_hb_fx[0],3); /* compute mean used in next frame to limit gain*/ + + FOR (i = 1; i < NUMSF; i++) /* all present subbands */ + { + IF(EQ_16(i, NUMSF_S2)) + { + savehalfe_fx = L_add(mean_prev_fx_loc, 0); + savehalfe_hb_fx = L_add(mean_prev_hb_fx_loc, 0); + } + + mean_prev_fx_loc = L_add(mean_prev_fx_loc, L_shr(es_mdct_fx[i], 3)); + mean_prev_hb_fx_loc = L_add(mean_prev_hb_fx_loc, L_shr(es_mdct_hb_fx[i], 3)); + } + + tmp_fxL1 = L_sub(mean_prev_fx_loc, savehalfe_fx); + if( LT_32(savehalfe_fx, L_shr(mean_prev_fx_loc, 1) )) + { + mean_prev_fx_loc = L_shl(tmp_fxL1, 1); + } + + tmp_fxL1 = L_sub(mean_prev_hb_fx_loc, savehalfe_hb_fx); + if( LT_32(savehalfe_hb_fx, L_shr(mean_prev_hb_fx_loc, 1) )) + { + mean_prev_hb_fx_loc = L_shl(tmp_fxL1, 1); + } + + last2_fx = L_shr(L_add(es_mdct_fx[NUMSF_M1], es_mdct_fx[NUMSF_M2]), 1); + last2_hb_fx = L_shr(L_add(es_mdct_hb_fx[NUMSF_M1], es_mdct_hb_fx[NUMSF_M2]), 1); + + if( GT_32(last2_fx, mean_prev_fx_loc)) + { + mean_prev_fx_loc = L_add(last2_fx, 0); + } + + if( GT_32(last2_hb_fx, mean_prev_hb_fx_loc)) + { + mean_prev_hb_fx_loc = L_add(last2_hb_fx, 0); + } + *mean_prev_fx = mean_prev_fx_loc; + move32(); + *mean_prev_hb_fx = L_shr(mean_prev_hb_fx_loc, shl(q_sig16,1)); + move32(); /*save in Q0*/ + *mean_prev_nc_fx = mean_prev_nc_fx_loc; + move32(); + } + + return; +} + +/*--------------------------------------------------------------------------* + * Inverse_Transform() + * + * Inverse transform from the DCT domain to time domain + *--------------------------------------------------------------------------*/ + +void Inverse_Transform( + const Word32 *in_mdct, /* i : input MDCT vector */ + Word16 *Q, /* i/o: Q value of input */ + Word32 *out, /* o : output vector */ + const Word16 is_transient, /* i : transient flag */ + const Word16 L, /* i : output frame length */ + const Word16 L_inner /* i : length of the transform */ +) +{ + Word16 ta, seg, tmp16; + Word16 segment_length; + const Word16 *win, *win2; + Word32 out_alias[L_FRAME48k]; + Word32 alias[MAX_SEGMENT_LENGTH]; + Word32 in_mdct_modif[L_FRAME48k]; + Word32 *in_segment_modif; + const Word32 *in_segment; + Word32 *out_segment; + Word16 segment_length_div2, segment_length_div4; + Word16 tmp, q_out; + Word32 L_temp; + /* This value is used to right shift all vectors returned by 'iedct_short_fx()' */ + /* to bring them to a scaling that is equal to the 1st 'Q' returned by the 1st */ + /* call to 'iedct_short_fx()' minus these guard bits. */ +#define N_GUARD_BITS (9+1) /* 9 is enough but we put one extra bit */ + + IF (is_transient) + { + segment_length = shr(L, 1); + segment_length_div2 = shr(L, 2); + segment_length_div4 = shr(L, 3); + + IF (EQ_16(L, L_FRAME48k)) + { + win = short_window_48kHz_fx; + } + ELSE IF (EQ_16(L, L_FRAME32k)) + { + win = short_window_32kHz_fx; + } + ELSE IF( EQ_16(L, L_FRAME16k)) + { + win = short_window_16kHz_fx; + } + ELSE /* L == L_FRAME8k */ + { + win = short_window_8kHz_fx; + } + + set32_fx(out_alias, 0, L); + + in_segment = in_mdct; + in_segment_modif = in_mdct_modif; + + tmp16 = sub(L, L_inner); + IF( tmp16 == 0 ) + { + Copy32(in_mdct, in_mdct_modif, L); + } + ELSE IF( tmp16 > 0 ) + { + FOR( seg = 0; seg < NUM_TIME_SWITCHING_BLOCKS; seg++ ) + { + FOR( ta = 0; ta < L_inner; ta += NUM_TIME_SWITCHING_BLOCKS ) + { + *in_segment_modif++ = *in_segment++; + move32(); + } + + FOR( ta = 0; ta < tmp16; ta += NUM_TIME_SWITCHING_BLOCKS ) + { + *in_segment_modif++ = 0L; + move32(); + } + } + } + ELSE /* L < L_inner */ + { + FOR( seg = 0; seg < NUM_TIME_SWITCHING_BLOCKS; seg++ ) + { + FOR( ta = 0; ta < segment_length_div2; ta++ ) + { + *in_segment_modif++ = *in_segment++; + move32(); + } + in_segment += shr(sub(L_inner, L), 2); + move32(); + } + } + + out_segment = out_alias - segment_length_div4; + in_segment = in_mdct_modif; + + tmp = *Q; + /* output of 'iedct_short_fx' has up to 'output frame length'/2 # of Elements */ + iedct_short_fx( in_segment, &tmp, alias, segment_length ); + IF (GT_16(tmp, N_GUARD_BITS)) + { + q_out = sub(tmp, N_GUARD_BITS); + tmp = sub(tmp, q_out); + } + ELSE + { + q_out = 0; + move16(); + } + + FOR( ta = segment_length_div4; ta < segment_length_div2; ta++ ) + { + out_segment[ta] = L_shr(alias[ta], tmp); + move32(); + } + /* This previous loop fills the output buffer from [0..seg_len_div4-1] */ + + win2 = &win[segment_length_div2]; + FOR( ta = segment_length_div2; ta < segment_length; ta++ ) + { + out_segment[ta] = L_shr(Mult_32_16(alias[ta], *--win2), tmp); + move32(); + } + /* This previous loop fills the output buffer from [seg_len_div4..seg_len-seg_len_div4-1] */ + + out_segment += segment_length_div2; + in_segment += segment_length_div2; + + FOR( seg = 1; seg < NUM_TIME_SWITCHING_BLOCKS-1; seg++ ) + { + tmp = *Q; + move16(); + /* output of 'iedct_short_fx' has up to 'output frame length'/2 # of Elements */ + iedct_short_fx( in_segment, &tmp, alias, segment_length ); + tmp = sub(tmp, q_out); + + FOR( ta = 0; ta < segment_length_div2; ta++ ) + { + out_segment[ta] = L_add(out_segment[ta], L_shr(Mult_32_16(alias[ta], *win2++), tmp)); + move32(); + } + FOR( ; ta < segment_length; ta++ ) + { + out_segment[ta] = L_add(out_segment[ta], L_shr(Mult_32_16(alias[ta], *--win2), tmp)); + move32(); + } + + in_segment += segment_length_div2; + out_segment += segment_length_div2; + } + + tmp = *Q; + move16(); + iedct_short_fx( in_segment, &tmp, alias, segment_length ); + tmp = sub(tmp, q_out); + + FOR (ta = 0; ta < segment_length_div2; ta++) + { + out_segment[ta] = L_add(out_segment[ta], L_shr(Mult_32_16(alias[ta], *win2++), tmp)); + move32(); + } + + seg = add(segment_length_div2, shr(segment_length_div2, 1)); /* seg = 3*segment_length/4 */ + FOR (ta = segment_length_div2; ta < seg; ta++) + { + out_segment[ta] = L_shr(alias[ta], tmp); + move32(); + } + + FOR (ta = 0; ta < segment_length; ta++) + { + L_temp = L_add(out_alias[ta], 0); + out[ta] = out_alias[L-1-ta]; + move32(); + out[L-1-ta] = L_temp; + move32(); + } + + *Q = q_out; + move16(); + } + ELSE + { + edct_fx(in_mdct, out, L, Q); + } +} diff --git a/lib_com/vlpc_2st_com.c b/lib_com/vlpc_2st_com.c new file mode 100644 index 0000000..ac54149 --- /dev/null +++ b/lib_com/vlpc_2st_com.c @@ -0,0 +1,61 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "cnst_fx.h" +#include "prot_fx.h" +#include "stl.h" +#include "control.h" +#include "basop_util.h" + + +void lsf_weight_2st( + const Word16 *lsfq, /* input: quantized lsf coefficients (14Q1*1.28) */ + Word16 *w, /* output: weighting function (0Q15*1.28) */ + const Word16 mode /* input: operational mode */ +) +{ + Word16 i; + Word16 d[M+1], weight; + + /* compute lsf distance */ + d[0] = lsfq[0]; + move16(); /*14Q1*1.28*/ + FOR (i=1; i0); */ + + /*w[i] = (weight * sqrt(d[i]*d[i+1])));*/ + + w[i] = mult_r(weight,getSqrtWord32(L_shl(L_mult0(d[i],d[i+1]),6))); + move16(); + } + + + return; +} diff --git a/lib_com/weight_a_fx.c b/lib_com/weight_a_fx.c new file mode 100644 index 0000000..49622fc --- /dev/null +++ b/lib_com/weight_a_fx.c @@ -0,0 +1,208 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "stl.h" +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Function prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include + +/*------------------------------------------------------------------ + * weight_a_subfr() + * + * Weighting of LP filter coefficients for multiple subframes, + * ap[i] = a[i] * (gamma^i) + *------------------------------------------------------------------*/ + +void weight_a_subfr_fx( + const Word16 nb_subfr, /* i : number of subframes */ + const Word16 *A, /* i : LP filter coefficients Q12 */ + Word16 *Aw, /* o : weighted LP filter coefficients Q12 */ + const Word16 gamma, /* i : weighting factor */ + const Word16 order /* i : order of LP filter */ +) +{ + Word16 k, orderp1; + + /* Smoothing aka spreading aka masking envelope generation */ + orderp1 = add(order,1); + FOR (k=0; k= 0 ; sfm--) + { + tmp16 = sub(spe2q[sfm+1],8); + spe2q[sfm] = s_max(spe2q[sfm], tmp16); + move16(); + } + + FOR (sfm = 0; sfm < num_map_bands ; sfm++) + { + spe2q[sfm] = s_max(spe2q[sfm], a_table_fx[sfm]); + move16(); + } + + /* Saturate by the Absolute Threshold of Hearing */ + spe2q_max = -32768; + move16(); + spe2q_min = MAX_16; + move16(); + + FOR (sfm = 0; sfm < num_map_bands ; sfm++) + { + spe2q[sfm] = sub(sfm_width[sfm], spe2q[sfm]); + move16(); + spe2q_max = s_max(spe2q[sfm], spe2q_max); + spe2q_min = s_min(spe2q[sfm], spe2q_min); + } + + FOR (sfm = 0; sfm < num_map_bands ; sfm++) + { + spe2q[sfm] = sub(spe2q[sfm], spe2q_min); + move16(); + } + + spe2q_max = sub(spe2q_max, spe2q_min); + + norm_max = norm_s(spe2q_max); + + shift = sub(norm_max,13); + + FOR (sfm = 0; sfm < num_map_bands ; sfm++) + { + spe2q[sfm] = shl(spe2q[sfm],shift); + move16(); + } + + mqb2sfm_fx(spe2q,spe,lnb_sfm); + + IF (is_transient != 0) + { + FOR (sfm = 0; sfm < lnb_sfm; sfm+=4) + { + sum = 0; + move16(); + FOR (k=0; k < 4; k++) + { + sum = add(sum , spe[sfm+k]); + } + sum = shr(sum,2); + FOR (k=0; k < 4; k++) + { + spe[sfm +k] = sum; + move16(); + } + } + } + + /* modify the norms for bit-allocation */ + FOR (sfm = 0; sfm < lnb_sfm ; sfm++) + { + wnorm[sfm] = add(spe[sfm], normqlg2[sfm]); + move16(); + } + + return; +} + + diff --git a/lib_com/wi_fx.c b/lib_com/wi_fx.c new file mode 100644 index 0000000..ddd4fa7 --- /dev/null +++ b/lib_com/wi_fx.c @@ -0,0 +1,5354 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include + +#include "options.h" +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "log2.h" +#include "stl.h" + +#define WARP_OS_RATE 8 +#define LL 256 +#define LL_OS (WARP_OS_RATE*LL) +#define OSLENGTH 12 +#define CUTFREE_ABS_RANGE 6 +#define CUTFREE_REL_RANGE 0.25 +#define CUTFREE_ABS_RANGE_Q3 48 +#define CUTFREE_REL_RANGE_Q2 1 +#define WI_THRESHLD 0.8 +#define WI_SAMPLE_THLD 20 +#define ERB_CBSIZE1 64 +#define ERB_CBSIZE2 64 +#define P_CBSIZE 64 + +/*#define _POLY1(x, c) ((c)[0] * (x) + (c)[1]) */ +/*#define _POLY2(x, c) (_POLY1((x), (c)) * (x) + (c)[2]) */ +/*#define _POLY3(x, c) (_POLY2((x), (c)) * (x) + (c)[3]) */ + +/*-------------------------------------------------------------------* +* DTFS_new_fx() +* +* DTFS structure initialization. +*-------------------------------------------------------------------*/ +DTFS_STRUCTURE_FX* DTFS_new_fx(void) +{ + + Word16 i ; + + DTFS_STRUCTURE_FX* dtfs_fx = NULL; + dtfs_fx = (DTFS_STRUCTURE_FX *) calloc(1,sizeof(DTFS_STRUCTURE_FX)); + dtfs_fx->lag_fx = 0 ; + move16(); + dtfs_fx->nH_fx=0; + move16(); + dtfs_fx->nH_4kHz_fx=0; + move16(); + dtfs_fx->upper_cut_off_freq_of_interest_fx=3300; + move16(); + dtfs_fx->upper_cut_off_freq_fx=4000; + move16(); + dtfs_fx->Q = 0; + move16(); + + FOR(i=0; ia_fx[i] = 0; + move16(); + dtfs_fx->b_fx[i] = 0; + move16(); + } + + return dtfs_fx; /* o: DTFS structure_fx */ + +} +/*-------------------------------------------------------------------* +* DTFS_copy_fx() +* +* Copy from one DTFS STRUCTURE to another. +*-------------------------------------------------------------------*/ + +void DTFS_copy_fx( + DTFS_STRUCTURE_FX *Xout_fx, /* o: DTFS structure */ + DTFS_STRUCTURE_FX Xinp_fx /* i: DTFS structure */ +) + +{ + + Word16 k; + FOR(k=0; ka_fx[k]=Xinp_fx.a_fx[k]; + move16(); + } + + FOR(k=0; kb_fx[k]=Xinp_fx.b_fx[k]; + move16(); + } + + Xout_fx->lag_fx=Xinp_fx.lag_fx; + move16(); + Xout_fx->nH_fx=Xinp_fx.nH_fx; + move16(); + Xout_fx->nH_4kHz_fx=Xinp_fx.nH_4kHz_fx; + move16(); + Xout_fx->upper_cut_off_freq_of_interest_fx=Xinp_fx.upper_cut_off_freq_of_interest_fx; + move16(); + Xout_fx->upper_cut_off_freq_fx=Xinp_fx.upper_cut_off_freq_fx; + move16(); + Xout_fx->Q = Xinp_fx.Q; + move16(); +} + + +/*-------------------------------------------------------------------* +* DTFS_sub_fx() +* +* Subtract one DTFS STRUCTURE from another. +*-------------------------------------------------------------------*/ +DTFS_STRUCTURE_FX DTFS_sub_fx( + + DTFS_STRUCTURE_FX X1, /* i: DTFS input 1 */ + DTFS_STRUCTURE_FX X2 /* i: DTFS input 2 */ +) +{ + DTFS_STRUCTURE_FX tmp ; + Word16 i ,sft, tmp_loop; + sft = sub(X1.Q,X2.Q); + + IF(sft>0) + { + tmp_loop = shr(X1.lag_fx,1); + FOR(i=0; i<=tmp_loop; i++) + { + + tmp.a_fx[i] = sub(shr(X1.a_fx[i],sft),X2.a_fx[i]); + move16(); + tmp.b_fx[i] = sub(shr(X1.b_fx[i],sft),X2.b_fx[i]); + move16(); + } + tmp.Q = X2.Q; + move16(); + } + ELSE + { + tmp_loop = shr(X1.lag_fx,1); + FOR(i=0; i<=tmp_loop; i++) + { + + tmp.a_fx[i] = sub(X1.a_fx[i],shl(X2.a_fx[i],sft)); + move16(); + tmp.b_fx[i] = sub(X1.b_fx[i],shl(X2.b_fx[i],sft)); + move16(); + } + tmp.Q = X1.Q; + move16(); + } + tmp.lag_fx = s_max(X1.lag_fx, X2.lag_fx) ; + tmp.nH_fx=s_max(X1.nH_fx,X2.nH_fx); + tmp.nH_4kHz_fx=s_max(X1.nH_4kHz_fx,X2.nH_4kHz_fx); + tmp.upper_cut_off_freq_of_interest_fx=X1.upper_cut_off_freq_of_interest_fx; + move16(); + tmp.upper_cut_off_freq_fx=X1.upper_cut_off_freq_fx; + move16(); + return tmp ; +} + +void DTFS_fast_fs_inv_fx( DTFS_STRUCTURE_FX *X_fx,Word16 *out_fx, Word16 N_fx, Word16 LOG2N) +{ + Word16 i, M_2, N_2, s; + Word16 dbuf_fx[256+1]; + + M_2=s_min(shr(X_fx->lag_fx,1),X_fx->nH_fx); + move16(); + N_2=shr(N_fx,1); + s=negate(X_fx->Q); + + dbuf_fx[0]=X_fx->a_fx[0]; + move16(); + dbuf_fx[1]=0; + move16(); + + FOR (i=1; i<=M_2; i++) + { + dbuf_fx[2*i]=shl_r(X_fx->a_fx[i],s); + move16(); + dbuf_fx[2*i+1]=shl_r(X_fx->b_fx[i],s); + move16(); + } + + FOR ( ; i0) + { + Result = L_add(L_tmp, 0); + } + ELSE + { + Result = L_negate(L_tmp); + } + *Qout = sub(30,exp); + + } + return Result; +} + +/*===================================================================*/ +/* FUNCTION : DTFS_alignment_weight_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : search for alignment */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) X1_fx : a/b in X1.Q */ +/* _ (struct DTFS_STRUCTURE_FX) X2_fx : a/b in X2.Q */ +/* _ (Word16) Eshift: Q7 */ +/* _ (Word16 *) LPC1: lpc coefficients. Q12 */ +/* _ (Word16 *) LPC2: lpc coefficients. Q12 */ +/* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */ +/* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16) fshift_fx : Q7 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ + +Word16 DTFS_alignment_weight_fx( DTFS_STRUCTURE_FX *X_fx, DTFS_STRUCTURE_FX X2, Word16 Eshift, const Word16 *LPC1, const Word16 *LPC2, Word16 *S_fx, Word16 *C_fx, Word16 *pf_temp1,Word16 *pf_temp2, Word16 *pf_temp, Word16 *pf_n2) +{ + /* Eshift is w.r.t X2 */ + Word16 k, HalfLag, start, end, ab1[MAXLAG_WI], ab2[MAXLAG_WI] ; + Word32 corr_fx; + Word32 maxcorr_fx, wcorr_fx, diff_corr; + DTFS_STRUCTURE_FX X1 ; + Word16 temp, temp1, Qcorr, Qmaxcorr, inv_lag, n_fx, diff_fx, fshift_fx, Adiff_fx; + Word16 tmplpc_fx[M+1]; + Word16 exp,tmp; + Word32 L_tmp; + + diff_fx = 0; /* to avoid compilation warnings */ + + + DTFS_copy_fx(&X1,*X_fx);/* X1 = *X_fx ; */ + DTFS_adjustLag_fx(&X1,X2.lag_fx) ; + + /* PORTING: Handling the functions with variable no. of arguments */ + poleFilter_setup_fx(LPC1, add(M,1), X1,S_fx,C_fx,pf_temp1,pf_temp2,pf_temp,pf_n2); + DTFS_poleFilter_fx_9(&X1, pf_temp1, pf_temp2, pf_temp, pf_n2); + FOR (k=0; k 0 ) + { + fshift_fx = n_fx ; + move16(); + maxcorr_fx = L_add(wcorr_fx, 0); + Qmaxcorr = Qcorr; + move16(); + } + } + + return fshift_fx ; +} +/*===================================================================*/ +/* FUNCTION : DTFS_alignment_extract_td_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : search for alignment in time domain */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16 *) x1: Q? */ +/* _ (Word16 *) x2: Q? */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16) lag : Q0 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ (Word16 *) idx: Q0 */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*===================================================================*/ + +Word16 DTFS_alignment_extract_td_fx(Word16 *x1, Word16 *x2, Word16 lag) +{ + Word16 j, k, idx, Adiff_fx ; + Word32 maxcorr, corr; + + maxcorr = L_add(MIN_32, 0); + Adiff_fx = (Word16)(s_max(4, shr(lag, 3))); + + idx=0; + move16(); + FOR ( j=negate(Adiff_fx); j<=Adiff_fx; j++) + { + corr=L_deposit_l(0); + FOR (k=0; k 0 ) + { + fshift_fx = n ; + move16(); + maxcorr_fx = (Word32)L_shl(corr_fx, Qcorr) ; /* Qcorr */ + Qmaxcorr = Qcorr; + move16(); + } + } + + return fshift_fx ; +} +/*===========================================================================*/ +/* FUNCTION : DTFS_alignment_full_fx () */ +/*---------------------------------------------------------------------------*/ +/* PURPOSE : search for alignment */ +/*---------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) X1_DTFS_fx : a_fx/b_fx in X1_DTFS_fx.Q */ +/* _ (struct DTFS_STRUCTURE_FX) X2_DTFS_fx : a_fx/b_fx in X2_DTFS_fx.Q */ +/* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */ +/* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */ +/*---------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16) fshift_fx : Q1 */ +/*---------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*---------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*---------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*===========================================================================*/ + +Word16 DTFS_alignment_full_fx( DTFS_STRUCTURE_FX X1_DTFS_fx, DTFS_STRUCTURE_FX X2_DTFS_fx, Word16 ph_offset_fx,Word16 *S_fx, Word16 *C_fx + , Word16 FR_flag + ) +{ + Word16 temp, temp1, k, start, end, HalfLag, ab1[MAXLAG_WI], ab2[MAXLAG_WI] ; + Word16 n, fshift_fx; + Word32 corr_fx, maxcorr_fx; + Word16 Eshift, Adiff_fx; + + + /* Calculating the expected alignment shift */ + Eshift = mult_r(ph_offset_fx, shl(X2_DTFS_fx.lag_fx, 7)); /* confirmed I<2 by smv12.org, Q7 */ + find_rem((Word16)L_FRAME, shr(add(X2_DTFS_fx.lag_fx, X1_DTFS_fx.lag_fx), 1), &temp); + temp = add(shl(temp, 7), Eshift); /* Q7 */ + + IF (temp<0) + { + temp = add(temp, shl(X1_DTFS_fx.lag_fx, 7)); /* Q7 */ + } + find_rem(temp, shl(X1_DTFS_fx.lag_fx, 7), &Eshift); /* Q7 */ + Eshift=shl(shr(Eshift,7),1); /* Q1 but integer */ + + IF (GT_16(X2_DTFS_fx.lag_fx,60)) + { + Adiff_fx = shl(X2_DTFS_fx.lag_fx,1-3); /* lag_fx/8 in Q1 */ + } + ELSE + { + Adiff_fx = shl(X2_DTFS_fx.lag_fx,1-2); /* lag_fx/4 in Q1 */ + } + + + IF (X1_DTFS_fx.lag_fx < X2_DTFS_fx.lag_fx) + { + DTFS_zeroPadd_fx(X2_DTFS_fx.lag_fx,&X1_DTFS_fx) ; + } + + maxcorr_fx = L_add(MIN_32, 0); + HalfLag = s_min(shr(X2_DTFS_fx.lag_fx, 1),X2_DTFS_fx.nH_4kHz_fx); + + FOR (k=0; k<=HalfLag; k++) + { + ab1[k] = round_fx(L_mac(L_mult(X1_DTFS_fx.a_fx[k], X2_DTFS_fx.a_fx[k]), X1_DTFS_fx.b_fx[k], X2_DTFS_fx.b_fx[k])); /* Q(-15); */ + ab2[k] = round_fx(L_msu(L_mult(X1_DTFS_fx.b_fx[k], X2_DTFS_fx.a_fx[k]), X1_DTFS_fx.a_fx[k], X2_DTFS_fx.b_fx[k])); /* Q(-15); */ + } + IF (FR_flag == 0) + { + start=sub(Eshift, Adiff_fx); /*Q1*/ + end=add(Eshift, Adiff_fx); /*Q1*/ + } + ELSE + { + /* + in FR mode, we cannot save and cary forward ph_offset as in VBR mode encoder "ph_offset_E_fx", + so we set ph_offset_fx = 0, as a result we cannot accurately estimate the expected alignment shift Eshift to limit the search, + so we search the full range [0 to X2_DTFS_fx.lag_fx] similar to FL + */ + start=0; /*Q1*/ + end=shl(X2_DTFS_fx.lag_fx,1); /*Q1*/ + } + + fshift_fx=start; + move16(); /*Q1*/ + + FOR (n=start; n<=end; n++) /*n in Q1*/ + { + /* Q1 */ + corr_fx = L_deposit_l(0); + temp = 0; + move16(); + temp1 = add(n,shl(X2_DTFS_fx.lag_fx,1)); /* add lag_fx in Q1to make positive */ + FOR (k=0; k<=HalfLag; k++) + { + corr_fx = L_mac(corr_fx, ab1[k], C_fx[(2*temp)%(4*X2_DTFS_fx.lag_fx)]); + corr_fx = L_mac(corr_fx, ab2[k], S_fx[(2*temp)%(4*X2_DTFS_fx.lag_fx)]); + temp = add(temp, temp1); + } + + if (GT_32(corr_fx, maxcorr_fx)) + { + fshift_fx = n ; /* Q1 */ move16(); + maxcorr_fx = L_add(corr_fx, 0); + } + } + + return fshift_fx ; /*Q1*/ +} +/*===================================================================*/ +/* FUNCTION : DTFS_phaseShift_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Phase is shifted by 2pi*ph/Lag */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) ph: shift index, Q7 */ +/* _ (Word16) Lag: Pitch Lag value as for shift */ +/* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */ +/* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None. */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (struct DTFS_fx) X1 : a/b in X1.Q */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ + +void DTFS_phaseShift_fx( DTFS_STRUCTURE_FX *X_fx,Word16 ph, Word16 Lag, Word16 *S_fx, Word16 *C_fx) +{ + Word16 k ; + Word16 temp, HalfLag; + Word32 L_temp, L_temp2; + + L_temp2 = L_deposit_l(0); + HalfLag = s_min(shr(X_fx->lag_fx, 1),X_fx->nH_fx); + + IF (ph>0) + { + FOR (k=0; k<=HalfLag; k++) + { + temp = X_fx->a_fx[k]; + L_temp = L_shr(L_temp2, 5); /* Q2 */ + X_fx->a_fx[k] = round_fx(L_msu(L_mult(temp, C_fx[L_temp%(4*Lag)]), X_fx->b_fx[k], S_fx[L_temp%(4*Lag)])) ; /* X.Q */ + X_fx->b_fx[k] = round_fx(L_mac(L_mult(X_fx->b_fx[k], C_fx[L_temp%(4*Lag)]), temp, S_fx[L_temp%(4*Lag)])) ; + L_temp2 = L_add(L_temp2, ph); + } + } + + IF (ph<0) + { + FOR (k=0; k<=HalfLag; k++) + { + temp = X_fx->a_fx[k]; + L_temp = L_shr(L_negate(L_temp2), 5); /* Q2 */ + X_fx->a_fx[k] = round_fx(L_mac(L_mult(temp, C_fx[L_temp%(4*Lag)]), X_fx->b_fx[k], S_fx[L_temp%(4*Lag)])) ; /* X.Q */ + X_fx->b_fx[k] = round_fx(L_msu(L_mult(X_fx->b_fx[k], C_fx[L_temp%(4*Lag)]), temp, S_fx[L_temp%(4*Lag)])) ; + L_temp2 = L_add(L_temp2, ph); + } + } +} + +/*===================================================================*/ +/* FUNCTION : Q2phaseShift_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Phase is shifted by 2pi*ph/Lag */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) ph: shift index, Q2 */ +/* _ (Word16) Lag: Pitch Lag value as for shift */ +/* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */ +/* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None. */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) X_fx : a/b in X_fx->Q */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ + +void Q2phaseShift_fx( DTFS_STRUCTURE_FX *X_fx,Word16 ph, Word16 Lag, Word16 *S_fx, Word16 *C_fx) +{ + Word16 k ; + Word16 temp, HalfLag; + Word32 temp2; + + temp2 = L_deposit_l(0); + + HalfLag = s_min(shr(X_fx->lag_fx, 1),X_fx->nH_fx); + + + IF (ph>0) + { + FOR (k=0; k<=HalfLag; k++) + { + temp = X_fx->a_fx[k]; + X_fx->a_fx[k] = round_fx(L_msu(L_mult(temp, C_fx[temp2%(4*Lag)]), X_fx->b_fx[k], S_fx[temp2%(4*Lag)])) ; /* X.Q */ + X_fx->b_fx[k] = round_fx(L_mac(L_mult(X_fx->b_fx[k], C_fx[temp2%(4*Lag)]), temp, S_fx[temp2%(4*Lag)])) ; + temp2 = L_add(temp2, (Word32)ph); + } + } + + + + IF (ph<0) + { + FOR (k=0; k<=HalfLag; k++) + { + temp = X_fx->a_fx[k]; + X_fx->a_fx[k] = round_fx(L_mac(L_mult(temp, C_fx[temp2%(4*Lag)]), X_fx->b_fx[k], S_fx[temp2%(4*Lag)])) ; /* X.Q */ + X_fx->b_fx[k] = round_fx(L_msu(L_mult(X_fx->b_fx[k], C_fx[temp2%(4*Lag)]), temp, S_fx[temp2%(4*Lag)])) ; + temp2 = add((Word16)temp2, negate(ph)); + } + } +} +/*===================================================================*/ +/* FUNCTION : DTFS_zeroPadd_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : zeroPadding */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) N_fx: length , Q0 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None. */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) X_fx : a/b in X_fx.Q i.e Q6 */ +/* _ (Word16) lag: pitch lag of *X_fx, Q0 */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ + +void DTFS_zeroPadd_fx(Word16 N_fx,DTFS_STRUCTURE_FX *X_fx) +{ + Word16 i, start, end ,diff_fx,rem_fx; + + if (EQ_16(N_fx,X_fx->lag_fx)) + { + return ; + } + start = add(shr(X_fx->lag_fx,1), 1); + end = shr(N_fx, 1); + + move16(); + FOR (i=start; i<=end; i++) + { + X_fx->a_fx[i]=0; + move16(); + X_fx->b_fx[i]=0; + move16(); + } + + X_fx->lag_fx = N_fx ; + move16(); + + /* recompute nH for new lag */ + diff_fx = find_rem(12800,X_fx->lag_fx,&rem_fx); + X_fx->nH_fx = find_rem(X_fx->upper_cut_off_freq_fx,diff_fx,&rem_fx); + + if(GE_16(sub(X_fx->upper_cut_off_freq_fx,shr((Word16)L_mult(diff_fx,X_fx->nH_fx),1)),diff_fx)) + { + X_fx->nH_fx = add(X_fx->nH_fx,1); + } +} +/*===================================================================*/ +/* FUNCTION : to_fs_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16 *) x: input time domain series. Q0 */ +/* _ (Word16) N: Lag */ +/* _ (struct DTFS_STRUCTURE_FX) PREVCW_FX: a/b in PREVCW_FX.Q */ +/* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */ +/* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) (Word16 a[]) : in Q */ +/* _ (struct DTFS_STRUCTURE_FX) (Word16 b[]) : in Q */ +/* _ (struct DTFS_STRUCTURE_FX) (Word16 lag) : Q0 */ +/* _ (struct DTFS_STRUCTURE_FX) (Word16 Q ) : Q value of a/b */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None. */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ +void DTFS_to_fs_fx( + const Word16 *x, /* i : time domain signal */ + Word16 N, /* i : Length of input vector */ + DTFS_STRUCTURE_FX *X_fx, /* o : DTFS structure with a, b, lag */ + Word16 Fs, /* i : sampling rate */ + Word16 FR_flag, /* i : FR flag */ + Word16 *S_fx, + Word16 *C_fx +) + +{ + Word16 n,temp,temp_neg,inv_lag,sum,diff_fx; + Word16 nH, k, nH_band, nH_4kHz; + Word32 L_temp, Lx0; + Word32 L_a, L_b,L_tmp; + Word32 La[MAXLAG_WI], Lb[MAXLAG_WI], Labmax; + Word16 exp,tmp; + Word32 L_tmp1; + + + IF (!FR_flag) + { + IF (EQ_16(Fs,16000)) + { + X_fx->upper_cut_off_freq_of_interest_fx=4000; + move16(); + X_fx->upper_cut_off_freq_fx=6400; + move16(); + X_fx->Fs_fx=INT_FS_FX; + move16(); + } + ELSE IF (EQ_16(Fs,8000)) + { + X_fx->upper_cut_off_freq_of_interest_fx=3300; + move16(); + X_fx->upper_cut_off_freq_fx=4000; + move16(); + X_fx->Fs_fx=INT_FS_FX; + move16(); + } + } + ELSE + { + X_fx->upper_cut_off_freq_of_interest_fx=8000; + move16(); + X_fx->upper_cut_off_freq_fx=8000; + move16(); + X_fx->Fs_fx=16000; + move16(); + } + X_fx->lag_fx = N ; + move16(); + + exp = norm_s(X_fx->lag_fx); + tmp = div_s(shl(1,sub(14,exp)),X_fx->lag_fx); /* Q29-exp */ + L_tmp1 = L_mult(12800,tmp); /* Q(30-exp) */ + diff_fx = extract_h(L_shl(L_tmp1,sub(exp,14))); /* Q0 */ + + exp = norm_s(diff_fx); + tmp = div_s(shl(1,sub(14,exp)),diff_fx); /* Q29-exp */ + L_tmp1 = L_mult(X_fx->upper_cut_off_freq_fx,tmp); /* Q(30-exp) */ + nH_band = extract_h(L_shl(L_tmp1,sub(exp,14))); /* Q0 */ + + nH_4kHz = mult(10240,(X_fx->lag_fx)); /* 4000/12800 in Q15 */ + + if(GE_16(sub(X_fx->upper_cut_off_freq_fx,shr((Word16)L_mult(diff_fx,nH_band),1)),diff_fx)) + { + nH_band = add(nH_band,1); + } + + if(GE_16(sub(4000,shr((Word16)L_mult(diff_fx,nH_4kHz),1)),diff_fx)) + { + nH_4kHz = add(nH_4kHz,1); + } + + /* Number of harmonics excluding the ones at 0 and at pi */ + nH = shr(sub(N,1),1); + + /* The DC component */ + X_fx->a_fx[0] = 0 ; + move16(); + X_fx->b_fx[0] = 0 ; + move16(); + + exp = norm_s(N); + tmp = div_s(shl(1,(sub(14,exp))),N); + L_tmp = L_shl(tmp,add(exp,6)); + inv_lag = round_fx(L_tmp); + + Lx0 = L_deposit_h(x[0]); + Labmax = L_deposit_l(0); + FOR ( k=1; k<=nH; k++ ) + { + L_a = L_shr(Lx0,1) ; /* Q16 */ + + L_b = L_deposit_l(0); + sum = k; + move16(); + temp = k; + move16(); + FOR ( n=1; nb_fx[k] = 0 ; + move16(); + } + + temp = norm_l(Labmax); + if (Labmax==0) + { + temp = 31; + move16(); + } + + FOR ( k=1; k<=nH; k++ ) + { + X_fx->a_fx[k]=round_fx(L_shl(La[k], temp)); /* Q(8+temp-16)=Q(temp-8) */ + X_fx->a_fx[k]=mult_r(X_fx->a_fx[k], inv_lag); + move16(); /* Q(temp-8+19+1-16)=Q(temp-4) of a[k]*2.0/N */ + X_fx->b_fx[k]=round_fx(L_shl(Lb[k], temp)); /* Q(8+temp-16)=Q(temp-8) */ + X_fx->b_fx[k]=mult_r(X_fx->b_fx[k], inv_lag); + move16(); /* Q(temp-8+19+1-16)=Q(temp-4) of b[k]*2.0/N */ + } + + /* IF ( N%2 == 0 ) */ + IF ( s_and(N,1) == 0 ) + { + X_fx->a_fx[k]=round_fx(L_shl(La[k], temp)); /* Q(8+temp-16)=Q(temp-8) */ + X_fx->a_fx[k]=mult_r(X_fx->a_fx[k], inv_lag); + move16(); /* Q(temp-8+19+1-16)=Q(temp-4) of a[k]*1.0/N */ + X_fx->b_fx[k]=0; + move16(); + } + + X_fx->Q=sub(temp, 4); + + tmp = s_min(shr(X_fx->lag_fx,1),sub(MAXLAG_WI,1)); + FOR(k=add(nH_band,1); k<=tmp; k++) + { + X_fx->a_fx[k]=0; + move16(); + X_fx->b_fx[k]=0; + move16(); + } + X_fx->nH_fx=nH_band; + move16(); + X_fx->nH_4kHz_fx=nH_4kHz; + move16(); + +} + + +/*===================================================================*/ +/* FUNCTION : DTFS_transform_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) X_fx: a/b in X1.Q, lag in Q0 */ +/* _ (struct DTFS_STRUCTURE_FX) X2_fx. a/b in X2.Q, lag in Q0 */ +/* _ (Word16 *) phase_fx: 2pi normalized, Q12 */ +/* _ (Word16) N: length of series. */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 *) out_fx: output transformed series. Q0. */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None. */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ +void DTFS_transform_fx( + DTFS_STRUCTURE_FX X_fx, /* i : Starting DTFS to use in WI */ + DTFS_STRUCTURE_FX X2_fx, /* i : Ending DTFS to use in WI */ + const Word32 *phase_fx, /* i : Phase contour */ + Word16 *out_fx, /* o : Output time domain waveform */ + Word16 N, /* i : Number of samples to generate */ + Word16 FR_flag /* i : Flag to indicate called in FR context */ +) +{ + + Word16 i, j ; + Word32 L_temp_fx; + Word16 w_fx; + Word16 inv1_fx, inv2_fx, inv_fx, q1, q2; + Word32 Lw_fx,temp32_fx; + Word16 x2_256_fx[256], x1_256_fx[256]; + Word16 k, m, l1; + Word32 x_r_fx[256] = { 0 }; + Word32 tmptmp3_40_fx; + Word16 temp_w; + Word16 N1; + Word16 nrg_flag = 0; + Word32 L_tmp; + Word16 tmp, tmp1, tmp2, frac, exp1, exp2; + Word16 expa, expb, fraca, fracb, scale; + + DTFS_STRUCTURE_FX *tmp2_dtfs_fx = DTFS_new_fx(); + DTFS_STRUCTURE_FX *tmp1_dtfs_fx = DTFS_new_fx(); + DTFS_STRUCTURE_FX *tmp3_dtfs_fx = DTFS_new_fx(); + DTFS_copy_fx(tmp1_dtfs_fx,X_fx); + DTFS_copy_fx(tmp2_dtfs_fx,X2_fx); + + tmp2 = 0; /* to avoid compilation warnings */ + + + DTFS_fast_fs_inv_fx(tmp1_dtfs_fx,x1_256_fx,256,8); + DTFS_fast_fs_inv_fx(tmp2_dtfs_fx,x2_256_fx,256,8); + + + + /* L_temp_fx=invert_dp((Word40)N,4,&n,1); = 1/M, Q(61-n) */ + /* inv1_fx=round_fx(L_temp_fx); = 1/M in Q(45-n) */ + /* q1=sub(n,15); */ + exp1 = norm_s(N); + inv1_fx = div_s(shl(1,sub(14,exp1)),N); /* 29-exp1 */ + q1=add(exp1,1); + + tmp1 = sub(X_fx.lag_fx,N); + exp2 = norm_s(tmp1); + + if(tmp1<0) + { + tmp2 = negate(tmp1); + } + tmp = div_s(shl(1,(14- exp2)),tmp2); /* 29-exp2 */ + L_tmp = L_shl(tmp,16); + + if(tmp1<0) + { + L_tmp = L_negate(L_tmp); + } + + q2=sub(exp2,3); + + + + /*L_temp_fx=(Word32) Mpy_32_16(extract_h(L_tmp),extract_l(L_tmp),22904); move32(); */ /* L_temp=log(0.2)*log10(e)/(lag-M), Q(61-n) */ + L_temp_fx= Mult_32_16(L_tmp,22904); /* L_temp=log(0.2)*log10(e)/(lag-M), Q(61-n) */ + inv2_fx=round_fx(L_temp_fx); /* log(0.2)*log10(e)/(lag-M), Q(45-n) */ + /* q2=sub(n,19); */ /* adjust Q factor to Q26 */ + + + IF (GT_16(sub(N, WI_SAMPLE_THLD), X_fx.lag_fx)) + { + inv_fx = inv2_fx; + move16(); + } + ELSE + { + inv_fx = inv1_fx; + move16(); + exp2 = exp1; + move16(); + } + + Lw_fx = L_deposit_l(inv_fx); + + FOR (i=0; i 16+13+1 */ /*27-exp2 */ + L_tmp = L_shl(L_tmp, sub(exp2,add(q2,11))); + frac = L_Extract_lc(L_tmp, &exp1); /* Extract exponent */ + L_temp_fx =Pow2(14, frac); + exp1 = sub(exp1,14); + L_temp_fx = L_shl(L_temp_fx,add(exp1,15)); /* Q15 */ + + w_fx=sub(16384,extract_h(L_shl(L_temp_fx,15))); /* w_fx in Q14 1- exp(- (i+1) * log(.2)/(lag-M)) */ + } + ELSE + { + w_fx=round_fx(L_shl(Lw_fx,q1)); /* Q14 */ + } + } + ELSE + { + IF (nrg_flag) + { + w_fx=round_fx(L_shl(Lw_fx,q1)); /* Q14 */ + } + ELSE + { + + N1 = sub(N , tmp2_dtfs_fx->lag_fx); + + IF (LT_16(i,N1)) + /* w = (i+1)/N1; */ + { + + /* w = (i+1)/N1; */ + IF(N1) + { + expa = norm_s(N1); + fraca = shl(N1,expa); + expa = sub(14,expa); + + tmp = add(i,1); + expb = norm_s(tmp); + fracb = shl(tmp,expb); + expb = sub(14,expb); + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + w_fx = div_s(fracb,fraca); + exp1 = sub(expb,expa); + w_fx = shl(w_fx,exp1-1); /*Q14*/ + } + ELSE + { + w_fx = 0; + } + + Lw_fx=L_deposit_h(w_fx); + + + } + ELSE + { + w_fx = 16384; + move16(); + } + } + } + + Lw_fx=L_add(Lw_fx,inv_fx); /* (i+1)*inv */ + /* mapping phase to 8x256 length signal */ + temp32_fx = phase_fx[i]; /* Q(27-11)=Q16 due to multiplication by pow(2.0,11) */ + j = rint_new_fx(temp32_fx); + j = s_and(j,0x07ff); + + /* k=j%8; */ + k=s_and(j,7); + l1=shr(j,3); /* reminder and quotient */ + + temp_w = sub( 16384, w_fx ); + tmptmp3_40_fx = L_deposit_l(0); + + FOR (j=0; j<12; j++) + { + m=(1000*LL+l1-OSLENGTH/2+j)%LL; /* use circular addressing */ + x_r_fx[m] = L_mac( L_mult( x1_256_fx[m], temp_w), x2_256_fx[m], w_fx); + } + tmptmp3_40_fx = L_deposit_l(0); + + + FOR (j=0; j<12; j++) + { + m=(1000*LL+l1-OSLENGTH/2+j)%LL; /* use circular addressing */ + tmptmp3_40_fx=L_add(tmptmp3_40_fx, Mult_32_16(x_r_fx[m],sinc_fx[k][j])); + + } + out_fx[i] = round_fx(L_shl(tmptmp3_40_fx,2)); + } + + + free(tmp1_dtfs_fx); + free(tmp2_dtfs_fx); + free(tmp3_dtfs_fx); +} +/*===================================================================*/ +/* FUNCTION : zeroFilter_fx() */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : zero filtering */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) lpc[] : lpc coefficients in Q12 */ +/* _ (Word16) N : lpc order */ +/* _ (Word16) this->lag: in Q0 */ +/* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */ +/* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None. */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16) this->a[] : in Q(this->Q) */ +/* _ (Word16) this->b[] : in Q(this->Q) */ +/* _ (Word16) this->Q: in Q0 */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ + +void DTFS_zeroFilter_fx( DTFS_STRUCTURE_FX *X_fx,Word16 *LPC, Word16 N, Word16 *S_fx, Word16 *C_fx) +{ + Word32 sum1_fx, sum2_fx ; + Word16 k, n, HalfLag ; + Word16 temp, temp1, temp2; + Word32 L_temp1, L_temp2; + Word16 Qmin, Qab[MAXLAG_WI], na, nb; + + Qmin = 32767; + move16(); + HalfLag = s_min(shr(X_fx->lag_fx, 1),X_fx->nH_fx); + FOR ( k=0 ; k<=HalfLag ; k++ ) + { + temp = k; + move16(); + temp2 = k; + move16(); + + /* Calculate sum1 and sum2 */ + sum1_fx = L_deposit_h(4096); /* 1: Q(12+15+1) */ + sum2_fx = L_deposit_l(0); + + FOR ( n=0 ; nlag_fx)]) ; /* Q(12+15+1) */ + sum2_fx = L_mac(sum2_fx, LPC[n], S_fx[(4*temp2)%(4*X_fx->lag_fx)]) ; + temp2 = add(temp2, temp); + } + + temp1 = round_fx(sum1_fx); /* Q(12+15+1-16)=Q(12) */ + temp2 = round_fx(sum2_fx); /* Q(12) */ + + /* Calculate the circular convolution */ + L_temp1 = L_mult(temp1, X_fx->a_fx[k]); + L_temp1 = L_msu(L_temp1, temp2, X_fx->b_fx[k]); /* Q(12+Q+1) */ + L_temp2 = L_mult(temp1, X_fx->b_fx[k]); + L_temp2 = L_mac(L_temp2, temp2, X_fx->a_fx[k]); /* Q(12+Q+1) */ + + /* normalization */ + na = norm_l(L_temp1); + if (L_temp1==0) + { + na=31; + move16(); + } + nb = norm_l(L_temp2); + if (L_temp2==0) + { + nb=31; + move16(); + } + + if (LT_16(na, nb)) + { + nb=na; + move16(); + } + X_fx->a_fx[k] = round_fx((Word32)L_shl(L_temp1, nb)); /* Q(13+Q+nb-16)=Q(Q+nb-3) */ + X_fx->b_fx[k] = round_fx((Word32)L_shl(L_temp2, nb)); /* Q(Q+nb-3) */ + + Qab[k] = sub(nb, 3); + + if (LT_16(Qab[k], Qmin)) + { + Qmin = Qab[k]; + move16(); + } + } + /* bring to the same Q */ + FOR ( k=0 ; k<=HalfLag ; k++ ) + { + X_fx->a_fx[k] = shl(X_fx->a_fx[k], sub(Qmin, Qab[k])); + move16(); /* Q(Q+Qab[k]+Qmin-Qab[k]=Q(Q+Qmin) */ + X_fx->b_fx[k] = shl(X_fx->b_fx[k], sub(Qmin, Qab[k])); + move16(); /* Q(Q+Qmin) */ + } + + X_fx->Q = add(X_fx->Q, Qmin); + move16(); +} +/*===================================================================*/ +/* FUNCTION : DTFS_poleFilter_fx() */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : pole filtering */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) lpc[] : lpc coefficients in Q12 */ +/* _ (Word16) N : lpc order */ +/* _ (Word16) lag: in Q0 */ +/* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */ +/* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */ +/* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16) this->a[] : in Q(this->Q) */ +/* _ (Word16) this->b[] : in Q(this->Q) */ +/* _ (Word16) this->Q: in Q0 */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ + +/* PORTING: Handling the functions with variable no. of arguments */ + +void DTFS_poleFilter_fx_9( DTFS_STRUCTURE_FX *X_fx, Word16 *pf_temp1, Word16 *pf_temp2, Word16 *pf_temp, Word16 *pf_n2_temp1) +{ + Word16 temp, temp1, temp2, HalfLag ; + Word32 sum1_fx, sum2_fx; + Word32 L_temp1, L_temp2; + Word16 k,n2_temp1, na, nb; + Word16 Qmin, Qab[MAXLAG_WI]; + + Qmin = 32767; + move16(); + HalfLag = s_min(shr(X_fx->lag_fx, 1),X_fx->nH_fx); + FOR ( k=0; k<=HalfLag; k++ ) + { + temp = temp2 = k; + move16(); + move16(); + /* Calculate sum1 and sum2 */ + + n2_temp1 = pf_n2_temp1[k]; + move16(); + + temp1 = pf_temp1[k]; + move16();/* Q(12+15+1+n2-16)=Q(12+n2) */ + temp2 = pf_temp2[k]; + move16();/* Q(12+n2) */ + + /* Calculate the circular convolution */ + + L_temp1 = L_mac(L_mult(temp1, X_fx->a_fx[k]), temp2, X_fx->b_fx[k]); /* Q(12+n2+Q+1)=Q(13+n2+Q) */ + L_temp2 = L_msu(L_mult(temp1, X_fx->b_fx[k]), temp2, X_fx->a_fx[k]); /* Q(12+n2+Q+1)=Q(13+n2+Q) */ + + temp = pf_temp[k]; + move16(); /* Q(61-25-2*n2-temp1-16)=Q(20-2*n2-temp1) */ + + sum1_fx = Mult_32_16(L_temp1, temp); /* Q(13+n2+Q+15+exp-15) = Q(13+n2+Q+exp) */ + sum2_fx = Mult_32_16(L_temp2, temp); + /* normalization */ + na = norm_l(sum1_fx); + if(sum1_fx==0) + { + na = 31; + move16(); + } + nb = norm_l(sum2_fx); + if(sum2_fx==0) + { + nb = 31; + move16(); + } + + if (LT_16(na, nb)) + { + nb=na; + move16(); + } + nb=sub(nb,1); /* leave one more sign bit */ + X_fx->a_fx[k] = round_fx((Word32)L_shl(sum1_fx, nb)); /* Q(-3+n2+Q+exp+nb ) */ + X_fx->b_fx[k] = round_fx((Word32)L_shl(sum2_fx, nb)); + + Qab[k] = add(sub(nb, 3), n2_temp1); + + if (LT_16(Qab[k], Qmin)) + { + Qmin = Qab[k]; + move16(); + } + } + /* bring to the same Q */ + move16(); + FOR ( k=0; k<=HalfLag; k++ ) + { + X_fx->a_fx[k] = shl(X_fx->a_fx[k], sub(Qmin, Qab[k])); + move16(); /* Q(Q+Qab[k]+Qmin-Qab[k])=Q(Q+Qmin) */ + X_fx->b_fx[k] = shl(X_fx->b_fx[k], sub(Qmin, Qab[k])); + move16(); /* Q(Q+Qab[k]+Qmin-Qab[k])=Q(Q+Qmin) */ + } + + X_fx->Q = add(X_fx->Q, Qmin); +} +/*===================================================================*/ +/* FUNCTION : DTFS_adjustLag_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) N_fx: lag value, Q0 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (struct DTFS_fx) : a/b in X1.Q */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (struct DTFS_fx) X1 : lag in Q0 */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ + +void DTFS_adjustLag_fx( + DTFS_STRUCTURE_FX *X_DTFS_FX, /* i/o : DTFS to adjust lag for */ + Word16 N_fx /* i : Target lag */ +) +{ + Word32 en_fx; + Word32 temp32_fx,tempnH_fx,mul1_fx,mul2_fx; + Word16 k,diff_fx; + Word16 exp,tmp; + Word32 L_tmp; + + if (EQ_16(N_fx,X_DTFS_FX->lag_fx)) + { + return ; + } + + IF(GT_16(N_fx,X_DTFS_FX->lag_fx)) + { + DTFS_zeroPadd_fx(N_fx,X_DTFS_FX); + } + ELSE + { + en_fx = DTFS_getEngy_fx(X_DTFS_FX); /* Q = 2*(X_DTFS_FX->Q) */ + + tmp = s_min(shr(X_DTFS_FX->lag_fx,1),X_DTFS_FX->nH_fx); + FOR( k = add(shr(N_fx,1),1) ; k<= tmp ; k++) + { + X_DTFS_FX->a_fx[k] = 0; + move16(); + X_DTFS_FX->b_fx[k] = 0; + move16(); + } + DTFS_setEngy_fx(X_DTFS_FX,en_fx); + X_DTFS_FX->lag_fx = N_fx ; + move16(); + + + /* recompute nH for new lag */ + exp = norm_s(X_DTFS_FX->lag_fx); + tmp = div_s(shl(1,sub(14,exp)),X_DTFS_FX->lag_fx);/* 29 - exp */ + L_tmp = L_mult0(12800,tmp); + temp32_fx = L_shl(L_tmp,sub(exp,23)); + diff_fx = (Word16) L_shl(L_tmp,sub(exp,29)); + + + exp = norm_s(diff_fx); + tmp = div_s(shl(1,sub(14,exp)),diff_fx);/* 29 - exp */ + L_tmp = L_mult0(X_DTFS_FX->upper_cut_off_freq_fx,tmp); + X_DTFS_FX->nH_fx = (Word16) L_shl(L_tmp,sub(exp,29)); + + L_tmp = L_mult0(4000,tmp); + tempnH_fx = L_shl(L_tmp,sub(exp,23)); + X_DTFS_FX->nH_4kHz_fx = extract_l(L_shl(L_tmp, sub(exp,29))); + + + if(GE_16(sub(X_DTFS_FX->upper_cut_off_freq_fx, shr((Word16)L_mult(diff_fx,X_DTFS_FX->nH_fx),1)), diff_fx)) + { + X_DTFS_FX->nH_fx = add(X_DTFS_FX->nH_fx,1); + move16(); + } + + mul1_fx = L_shl(temp32_fx,13);/* Q19 */ + mul2_fx = L_shl((Word32)X_DTFS_FX->nH_4kHz_fx,18);/* Q18 */ + tempnH_fx = Mult_32_32(mul1_fx,mul2_fx);/* Q6 */ + tempnH_fx = L_sub((Word32)256000,tempnH_fx);/* Q6 */ + + if(GE_32(tempnH_fx,temp32_fx)) + { + X_DTFS_FX->nH_4kHz_fx = add(X_DTFS_FX->nH_4kHz_fx,1); + move16(); + } + } +} +/*===================================================================*/ +/* FUNCTION : DTFS_getEngy_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) : a/b in X_fx.Q i.e Q6, lag in Q0*/ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : _ None */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word40) en_fx: output energy, 2*X1.Q */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ + + +Word32 DTFS_getEngy_fx( DTFS_STRUCTURE_FX *X_fx) +{ + Word16 k, HalfLag_fx; + Word32 en_fx=0; + Word16 temp_a_fx,temp_b_fx; + + HalfLag_fx = shr(sub(X_fx->lag_fx, 1), 1); + HalfLag_fx = s_min(HalfLag_fx,X_fx->nH_fx); + FOR (k=1; k<=HalfLag_fx; k++) + { + temp_a_fx = X_fx->a_fx[k]; + move16(); + temp_b_fx = X_fx->b_fx[k]; + move16(); + + en_fx = L_mac0(en_fx, temp_a_fx, temp_a_fx); + en_fx = L_mac0(en_fx, temp_b_fx, temp_b_fx); + } + + en_fx = L_shr(en_fx, 1); + temp_a_fx = X_fx->a_fx[0]; + en_fx = L_mac0(en_fx,temp_a_fx, temp_a_fx); + + /* IF (X_fx->lag_fx%2 == 0) */ + IF (s_and(X_fx->lag_fx,1) == 0) + { + temp_a_fx = X_fx->a_fx[k]; + move16(); + temp_b_fx = X_fx->b_fx[k]; + move16(); + + en_fx = L_mac0(en_fx, temp_a_fx, temp_a_fx); + en_fx = L_mac0(en_fx, temp_b_fx, temp_b_fx); + } + + return en_fx ; /* 2*X1.Q+1=Q13 */ +} + + + +/*===================================================================*/ +/* FUNCTION : DTFS_getEngy_P2A_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) : a/b in X_fx.Q, lag in Q0 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : _ None */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word40) en_fx: output energy, 2*X1.Q */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ + +Word32 DTFS_getEngy_P2A_fx( DTFS_STRUCTURE_FX *X_fx) +{ + Word16 k, HalfLag_fx; + Word32 en_fx=0; + + HalfLag_fx = shr(sub(X_fx->lag_fx, 1), 1); + HalfLag_fx = s_min(HalfLag_fx,X_fx->nH_fx); + FOR (k=1; k<=HalfLag_fx; k++) + { + en_fx = L_mac0(en_fx, X_fx->a_fx[k], X_fx->a_fx[k]); + en_fx = L_mac0(en_fx, X_fx->b_fx[k], X_fx->b_fx[k]); + } + en_fx = L_shr(en_fx, 1); + en_fx = L_mac0(en_fx,X_fx->a_fx[0], X_fx->a_fx[0]); + /* IF (X_fx->lag_fx%2 == 0) */ + IF (s_and(X_fx->lag_fx,1) == 0) + { + en_fx = L_mac0(en_fx, X_fx->a_fx[k], X_fx->a_fx[k]); + en_fx = L_mac0(en_fx, X_fx->b_fx[k], X_fx->b_fx[k]); + } + + return en_fx ; /* 2*X1.Q */ +} + + +/*=================================================================================*/ +/* FUNCTION : DTFS_getEngy_band_fx (Word16 lband, Word16 hband) */ +/*---------------------------------------------------------------------------------*/ +/* PURPOSE : compute the energy of X1.a[k] and X2.b[k] */ +/*---------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) X_fx : a_fx/b_fx in X_fx.Q, lag in Q0 */ +/* _ (Word16) lband: Q0 */ +/* _ (Word16) hband: Q0 */ +/*---------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word40) en_fx : 2*X1.Q */ +/*---------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*---------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*---------------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*=================================================================================*/ + +/* PORTING: Handling the functions with variable no. of arguments */ + +Word32 DTFS_getEngy_band_fx(DTFS_STRUCTURE_FX X_fx,Word16 lband, Word16 hband) +{ + Word16 k, lk, hk, HalfLag ; + Word32 freq_fx, L_lband, L_hband; + Word32 en_fx=0; + + L_lband = L_mult(lband, X_fx.lag_fx); + L_hband = L_mult(hband, X_fx.lag_fx); + HalfLag = s_min(shr(sub(X_fx.lag_fx, 1), 1),X_fx.nH_4kHz_fx); + /* get lband and hband */ + FOR (k=1; k<=HalfLag; k++) + { + freq_fx = L_mult(k, 12800); + IF (GE_32(freq_fx, L_lband)) + { + BREAK; + } + } + lk = k; + move16(); + FOR (k=1; k<=HalfLag; k++) + { + freq_fx = L_mult(k, 12800); + IF (GE_32(freq_fx, L_hband)) + { + BREAK; + } + } + hk = k; + move16(); + + FOR (k=lk; klag_fx, 1),X_DTFS_FX->nH_fx); + move16(); + en1_fx = DTFS_getEngy_fx(X_DTFS_FX); + move16(); + + if (en1_fx == 0) + { + return 0; + } + + IF (en2_fx==0) + { + factor_fx=0; + } + ELSE + { + expa = norm_l(en2_fx); + fraca = extract_h(L_shl(en2_fx,expa)); + expa = sub(30, add(expa,shl(X_DTFS_FX->Q, 1))); + + + expb = norm_l(en1_fx); + fracb = round_fx(L_shl(en1_fx,expb)); + expb = sub(30, add(expb, shl(X_DTFS_FX->Q, 1))); + + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); + exp = sub(expb,expa); + + L_tmp = Isqrt_lc(L_deposit_h(tmp),&exp); /* Q(31-exp) */ + factor_fx = L_shr(L_tmp,1); + + } + + FOR (k=0; k<=HalfLag_fx; k++) + { + L_temp_fx = Mult_32_16(factor_fx, X_DTFS_FX->a_fx[k]); /* Q(temp+X1.Q-15) */ + X_DTFS_FX->a_fx[k] = round_fx(L_temp_fx); /* Q(temp+X1.Q-15-16)=Q(temp+X1.Q-31); */ + + L_temp_fx =Mult_32_16(factor_fx, X_DTFS_FX->b_fx[k]); /* Q(temp+X1.Q-15) */ + X_DTFS_FX->b_fx[k] = round_fx(L_temp_fx); /* Q(temp+X1.Q-15-16)=Q(temp+X1.Q-31); */ + + } + + + return en1_fx ;/* 2*X1.Q+1 = Q13 */ +} + +/*===================================================================*/ +/* FUNCTION : struct DTFS_car2pol_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Cartesian to polar representation */ +/* returning amplitudes and 0 phases */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) X_fx : prototype in Cartesian domain*/ +/* (Word16) lag: length of prototype in time domain */ +/* (Word16 []) a,b: re/im of harmonics, normalized */ +/* (Word16) Q: norm factor of a/b */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) X_fx : prototype in polar domain */ +/* (Word16) lag: length of prototype in time domain */ +/* (Word16 []) a: amplitude of harmonics, normalized */ +/* (Word16 []) b: phase of harmonics,cleared to 0 */ +/* (Word16) Q: norm factor of a */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ +/* NOTE: output X.b (angle) is not computed and should be ignored */ +/* When phases are needed, such as in QPPP, instead uses the */ +/* Cartesian representation to avoid computing phases by arctan*/ +/*===================================================================*/ +void DTFS_car2pol_fx( + DTFS_STRUCTURE_FX *X_fx /* i/o : DTFS structure a, b, lag */ +) + +{ + Word16 k, HalfLag_fx ; + Word32 Ltemp_fx; + Word32 Lacc_fx; + Word16 exp,tmp,frac; + + HalfLag_fx = s_min(shr(sub(X_fx->lag_fx,1),1),X_fx->nH_fx); + FOR ( k=1 ; k<=HalfLag_fx; k++ ) + { + + Lacc_fx=L_mult(X_fx->a_fx[k],X_fx->a_fx[k]); /* a[k]^2, 2Q+1 */ + Lacc_fx=L_mac(Lacc_fx,X_fx->b_fx[k],X_fx->b_fx[k]); /* a[k]^2+b[k]^2, 2Q+1 */ + Lacc_fx=L_shr(Lacc_fx,3); /* Lacc=(a[k]^2+b[k]^2)/4, 2Q */ + + IF(Lacc_fx) + { + exp = norm_l(Lacc_fx); + frac = extract_h(L_shl(Lacc_fx,exp)); /* Q14 */ + exp = sub(exp, sub(30,(2*X_fx->Q))); + + tmp = div_s(16384,frac); /* Q15 */ + Ltemp_fx = Isqrt_lc(L_deposit_h(tmp),&exp); /* Q(31-exp) */ + + X_fx->a_fx[k]=extract_h(L_shl(Ltemp_fx, sub(add(X_fx->Q, exp), 15))); /* Q */ + } + ELSE + { + X_fx->a_fx[k] = 0; + move16(); + } + + X_fx->b_fx[k]= 0; + move16(); /* clear b[k] */ + } + + + IF (s_and(X_fx->lag_fx,1) == 0) + { + IF(X_fx->a_fx[k]) + { + Lacc_fx=L_mult0(X_fx->a_fx[k],X_fx->a_fx[k]); /* a[k]^2, 2Q+1 */ + Lacc_fx=L_mac0(Lacc_fx,X_fx->b_fx[k],X_fx->b_fx[k]); /* a[k]^2+b[k]^2, 2Q+1 */ + + exp = norm_l(Lacc_fx); + frac = extract_h(L_shl(Lacc_fx,exp)); /* Q14 */ + exp = sub(exp,sub(30,shl(X_fx->Q,1))); + + tmp = div_s(16384,frac); /* Q15 */ + Ltemp_fx = Isqrt_lc(L_deposit_h(tmp),&exp); /* Q(31-exp) */ + + X_fx->a_fx[k]=extract_h(L_shl(Ltemp_fx, sub(add(X_fx->Q, exp), 15))); /* Q */ + } + ELSE + { + X_fx->a_fx[k] = 0; + move16(); + } + + X_fx->b_fx[k]= 0; + move16(); /* clear b[k]; */ + } +} + + +/*==============================================================================*/ +/* FUNCTION : DTFS_setEngyHarm_fx ( ) */ +/*------------------------------------------------------------------------------*/ +/* PURPOSE : Set a band of harmonics to specified energy */ +/*----------------------------------------------------------------------- ------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_fx) : lag in Q0 */ +/* _ (Word16) f1_fx: lower bound of input, normalized by 12800, Q15 */ +/* _ (Word16) f2_fx: upper bound of input, normalized by 12800, Q15 */ +/* _ (Word16) g1_fx: lower bound of output, normalized by 12800, Q15 */ +/* _ (Word16) g2_fx: upper bound of output, normalized by 12800, Q15 */ +/* _ (Word32) en2_fx: in Q(Qen2) */ +/* _ (Word16) Qen2_fx: Q value of en2 */ +/*---------------------------------------------------------------------------- --*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16) Qa_fx: Q value of output a[]. */ +/*----------------------------------------------------------------------------- -*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _(struct DTFS_STRUCTURE_FX) : a_fx[] in X1_fx.Q at start, then changed to */ +/* *Qa later. */ +/*---------------------------------------------------------------------------- --*/ +/* RETURN ARGUMENTS : _ None. */ +/* _ (Word32) en1_fx: Q(2*X1.Q) */ +/*----------------------------------------------------------------------------- -*/ +/* CALLED FROM : TX/RX */ +/*============================================================================== */ +/* NOTE: This function cannot change Q because it works on a band */ +/* of harmonics, instead of the whole DTFS */ +/*============================================================================== */ +Word32 DTFS_setEngyHarm_fx( + Word16 f1_fx, /* i : lower band freq of input to control energy */ + Word16 f2_fx, /* i : upper band freq of input to control energy */ + Word16 g1_fx, /* i : lower band freq of output to control energy */ + Word16 g2_fx, /* i : upper band freq of output to control energy */ + Word32 en2_fx, /* i : Target Energy to set the DTFS to */ + Word16 Qen2_fx, /* i : Input Q format for en2 */ + Word16 *Qa_fx, /* i : Output Q format for x->a */ + DTFS_STRUCTURE_FX *X_fx /* i/o: DTFS to adjust the energy of */ +) +{ + + Word16 k, count=0, HalfLag_fx; + Word16 f_low_fx, f_high_fx, g_low_fx, g_high_fx; + Word32 L_temp_fx, factor_fx; + Word32 en1_fx; + Word32 Lacc; + Word16 exp,tmp,expa,expb,fraca,fracb,scale; + Word32 L_tmp; + Word32 Lacc_max = 0; + Word16 expp=0; + + + + f_low_fx=mult(f1_fx,X_fx->lag_fx); /* Q0 */ + f_high_fx=mult(f2_fx,X_fx->lag_fx); /* Q0 */ + g_low_fx=mult(g1_fx,X_fx->lag_fx); /* Q0 */ + g_high_fx=mult(g2_fx,X_fx->lag_fx); /* Q0 */ + HalfLag_fx = s_min(f_high_fx,shl(X_fx->nH_fx,1)); + + Lacc = L_deposit_l(0); + FOR (k=f_low_fx+1 ; k<=HalfLag_fx; k++) + { + Lacc = L_mac0(Lacc, X_fx->a_fx[k], X_fx->a_fx[k]); /* 2*X1.Q */ + Lacc_max = L_max( Lacc_max, Lacc); + + count=add(count,1); + } + + IF( GE_32( Lacc_max, 2147483647 )) + { + tmp = sub(HalfLag_fx, f_low_fx); + exp = norm_s(tmp); + expp = sub(15,exp); + + Lacc = L_deposit_l(0); + FOR( k=f_low_fx+1; k<=HalfLag_fx; k++ ) + { + L_tmp = L_mult( X_fx->a_fx[k], X_fx->a_fx[k] ); + Lacc = L_add(Lacc, L_shr(L_tmp,expp)); /* 2*X1.Q-expp */ + count=add(count,1); + } + } + + if (count <= 0) + { + count = 1; + move16(); + } + + exp = norm_s(count); + tmp = div_s(shl(1,sub(14,exp)),count);/* 29 - exp */ + en1_fx = L_shl( Mult_32_16(Lacc , tmp), sub(exp,14)); + + test(); + IF (en1_fx>0 && en2_fx > 0) + { + /* factor_fx = sqrt_divide_dp((Word40)en2_fx, en1_fx, sub(Qen2_fx, shl(X_fx->Q, 1)), &temp_fx,1); : Q(temp) */ + expa = norm_l(en2_fx); + fraca = extract_h(L_shl(en2_fx,expa)); + expa = sub(30,add(expa,Qen2_fx)); + + + expb = norm_l(en1_fx); + fracb = round_fx(L_shl(en1_fx,expb)); + + IF( GE_32( Lacc_max, 2147483647 )) + { + expb = sub( 30, add( expb, sub(shl(X_fx->Q, 1),expp) ) ); + } + ELSE + { + expb = sub(30, add(expb, shl(X_fx->Q, 1))); + } + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); + exp = sub(expb,expa); + + L_tmp = Isqrt_lc(L_deposit_h(tmp),&exp); /* Q(31-exp) */ + + IF( GE_32( Lacc_max, 2147483647 )) + { + factor_fx = L_shr(L_tmp,add(1,s_min(2,expp))); + } + ELSE + { + factor_fx = L_shr(L_tmp,1); + } + + + } + ELSE + { + factor_fx = L_deposit_l(0); + } + + HalfLag_fx = s_min(g_high_fx,shl(X_fx->nH_fx,1)); + FOR (k=g_low_fx+1; k<=HalfLag_fx; k++) + { + /*L_temp_fx =(Word32)Mpy_32_16(extract_h(factor_fx),extract_l(factor_fx), X_fx->a_fx[k]); move32(); */ /* Q(temp+X1.Q-15) */ + L_temp_fx = Mult_32_16(factor_fx, X_fx->a_fx[k]); /* Q(temp+X1.Q-15) */ + X_fx->a_fx[k] = round_fx(L_temp_fx); /* Q(temp+X1.Q-15-16)=Q(temp+X1.Q-31); */ + } + + if ( GE_32( Lacc_max, 2147483647 )) + { + *Qa_fx = sub( sub(X_fx->Q,add(1,s_min(2,expp))) , exp); + } + else + { + *Qa_fx = sub( sub(X_fx->Q,1) , exp); + } + + return en1_fx; /* Q(2*X1.Q) */ + + +} +/*===================================================================*/ +/* FUNCTION : cubicPhase_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Compute cubic phase track for WI synthesis */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) ph1_fx : initial phase, Q15 (normalized by 2pi) */ +/* _ (Word16) ph2_fx : final phase, Q15 (normalized by 2pi) */ +/* _ (Word16) L1 : previous pitch lag, Q0 */ +/* _ (Word16) L2 : current pitch lag, Q0 */ +/* _ (Word16) N : length of phase track, Q0 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word32 []) phOut_fx : phase track, Q27 (normalized by 2pi) */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ +/* NOTE: This function outputs phase in (-1,1) */ +/*===================================================================*/ +static +void cubicPhase_fx( + Word16 ph1_fx, Word16 ph2_fx, Word16 L1, Word16 L2, + Word16 N, Word32 *phOut_fx +) +{ + Word16 n; + Word16 n2; + Word16 f1, f2; /* invert of L1, L2, Q19 */ + Word16 factor, temp; + Word16 c0, c1, c2, c3; /* cubic polynomial coefficients */ + /* Q33, Q27, Q19, Q15 respectively */ + Word32 Ltemp1, Ltemp2, Ltemp3,Ltemp4,Ltemp; + Word16 tmp,exp; + Word32 Lacc; + Word16 expa,expb,fraca,fracb,scale; + Word32 L_tmp,L_tmp1; + Word16 num_flag,den_flag; + Word32 N2; + Word16 dbgshft; + num_flag = 0; + den_flag = 0; + + N=sub(N,L2); + + exp = norm_s(L1); + tmp = div_s(shl(1,sub(14,exp)),L1); + L_tmp = L_shl(tmp,exp+6); + f1 = round_fx(L_tmp); + + exp = norm_s(L2); + tmp = div_s(shl(1,sub(14,exp)),L2); + L_tmp = L_shl(tmp,exp+6); + Ltemp4 = inverse_table[L2]; + f2 = round_fx(L_tmp); + + c3 = ph1_fx; + move16(); /* c3 in Q15 */ + c2 = f1; + move16();/* c2 in Q19 */ + + Ltemp1 = L_sub(ph1_fx,ph2_fx); /* Ltemp1=ph1_fx-ph2_fx, Q15 */ + Ltemp2 = L_add(f1,f2); /* Ltemp2=0.5*(f1+f2), Q20 */ + temp = extract_l(Ltemp2);/* Q20 */ + + IF(temp<0) + { + L_tmp1 = L_shl(L_add(65536,temp),14); /* Q30 */ + L_tmp = Mult_32_16(L_tmp1,N); /* 30-15=15 */ + Ltemp2 = L_shl(L_tmp,1); + } + ELSE + { + Ltemp2 = (Word32)L_mult0(N,temp); /* Ltemp2=0.5*N*(f1+f2), Q20 */ + } + + Ltemp1 = L_add(L_shl(Ltemp1,5),Ltemp2); /* Ltemp1=ph1_fx - ph2_fx + 0.5*N*(f2+f1), Q16, Q20 */ + + factor = round_fx(L_shr(Ltemp1,4)); /* factor in Q0 */ + + c1 = sub(f2,f1); /* c1=f2-f1, Q19 */ + Ltemp1 = L_sub(ph2_fx,ph1_fx); /* Q15 */ + Ltemp2 = L_mult(N,f1); /* Ltemp2=N*f1, Q20 */ + Ltemp2 = L_sub(L_shl(L_deposit_h(factor),4),Ltemp2); /* Ltemp2=factor-N*f1, Q20 */ + Ltemp1 = L_add(Ltemp2,L_shl(Ltemp1,5)); /* Ltemp1 in Q20 */ + + IF(GT_16(N,180)) + { + Ltemp2 = L_shl(L_mult0(N,N),14); + Ltemp2 = L_shl(Mult_32_16(Ltemp2,N),1); + + /* IF(N%2) */ + if(s_and(N,1) == 1) + { + Ltemp2 = L_add(Ltemp2,1); + } + } + ELSE + { + Ltemp2=L_shr(L_mult(N,N),1); + Ltemp2 = L_mult0(N,extract_l(Ltemp2)); /* Ltemp2=N^3 */ + } + Ltemp3 = L_mult(N,c1); /* Q20 */ + Ltemp3 = L_sub(Ltemp3,L_shl(Ltemp1,1)); /* Ltemp3=N*c1-2*Ltemp1, Q20 */ + + + IF (GE_32(L_abs(Ltemp3),L_shl(Ltemp2,8))) + { + Lacc = L_add(MIN_32, 0); + if (Ltemp3 > 0) + { + Lacc = L_add(MAX_32, 0); + } + + c0 = extract_h(Lacc); /* c0 in Q33 */ + } + ELSE + { + expa = norm_l(Ltemp3); + fraca = extract_h(L_shl(Ltemp3,expa)); + expa = sub(30,add(expa, 20)); + if(fraca<0) + { + num_flag = 1; + move16(); + } + + expb = norm_l(Ltemp2); + fracb = extract_h(L_shl(Ltemp2,expb)); + expb = sub(30,expb); + if(fracb<0) + { + den_flag = 1; + move16(); + } + + if(num_flag) + { + fraca = negate(fraca); + } + if(den_flag) + { + fracb = negate(fracb); + } + scale = shr(sub(fracb,fraca),15); + fraca = shl(fraca,scale); + expa = sub(expa,scale); + + tmp = div_s(fraca,fracb); /* 15-exp */ + exp = sub(expa,expb); + test(); + if(num_flag && !den_flag) + { + tmp = negate(tmp); + } + test(); + if(den_flag && !num_flag) + { + tmp = negate(tmp); + } + + Lacc = L_shl(tmp,add(exp,34)); + Lacc = L_add(Lacc,0x08000); + c0 = extract_h(Lacc); /* c0 in Q33 */ + } + + Ltemp1 = L_mult(N,N); /* Ltemp1=2*N*N */ + Ltemp1 = L_add(Ltemp1,L_shr(Ltemp1,1)); /* Ltemp1=3*N*N, max is 3*140*140 */ + + /* patch added for time warping support, where N can be more than 140 */ + dbgshft= norm_l(Ltemp1); + Ltemp1= L_shl(Ltemp1,dbgshft); + temp = extract_h(Ltemp1); + Ltemp1 = (Word32)L_shl((Word32)L_mult0(c0,temp), sub(16,dbgshft)); /* Ltemp1=3*N*N*c0, Q33 */ + /* Patch end */ + + num_flag = den_flag = 0; + move16(); + move16(); + Ltemp1 = L_sub(L_shr(L_deposit_h(c1),2),Ltemp1); /* Ltemp1=c1-3*N*N*c0, Q33 */ + + expa = norm_l(Ltemp1); + fraca = extract_h(L_shl(Ltemp1,expa)); + expa = sub(30,add(expa, 33)); + if(fraca<0) + { + num_flag = 1; + move16(); + } + + expb = norm_l(N); + fracb = extract_h(L_shl(N,expb)); + expb = sub(30,expb); + if(fracb<0) + { + den_flag = 1; + move16(); + } + + if(num_flag) + { + fraca = negate(fraca); + } + if(den_flag) + { + fracb = negate(fracb); + } + scale = shr(sub(fracb,fraca),15); + fraca = shl(fraca,scale); + expa = sub(expa,scale); + + tmp = div_s(fraca,fracb); /* 15-exp */ + exp = sub(expa,expb); + test(); + if(num_flag && !den_flag) + { + tmp = negate(tmp); + } + test(); + if(den_flag && !num_flag) + { + tmp = negate(tmp); + } + + Lacc = L_shl(tmp,exp+27); + Lacc = L_add(Lacc,0x08000); + c1 = extract_h(Lacc); /* c1 in Q27 */ + + + /* Computation of the phase value at each sample point */ + /* ph[n]= c0*n^3+c1*n^2+c2*n+c3, Q15 */ + phOut_fx[0] = L_shl(ph1_fx,11);/* Q27 */ + + IF(LT_16(N,181)) + { + FOR (n=1; n=diff_fx)/* Q0 compare */ + { + nH_band_fx = add(nH_band_fx,1);/* Q0 */ + } + + n=s_min(shr(lag_fx,1),nH_band_fx); + exp = norm_s(lag_fx); + tmp = div_s(shl(1,sub(14,exp)),lag_fx); /* Q29-exp */ + L_tmp = L_shl(tmp, add(exp,6)); + diff_fx =round_fx(L_tmp); + + j=0; + move16(); + FOR (i=0; i<=n; i++) + { + Ltemp_fx=L_mult(diff_fx,i); /* Ltemp=i*diff, Q20 */ + /* freq=round32_16(L_shl(Ltemp,11)); : freq=i*diff, Q15 */ + + IF (EQ_16(num_erb_fx,NUM_ERB_NB)) + { + Ltemp_fx=L_min(Ltemp_fx,0x050000); /* 0x50000=0.3125 in Q20 (4000Hz) */ + } + ELSE IF (EQ_16(num_erb_fx,NUM_ERB_WB)) + { + Ltemp_fx=L_min(Ltemp_fx,0x080000); /* 0x80000=0.5 in Q20 (6400Hz) */ + } + + FOR ( ; jlag_fx); + tmp = div_s(shl(1,sub(14,exp)),X_fx->lag_fx);/* 29-exp */ + diff_fx= shl(tmp,exp-10); /* Q19 */ + + min_q = EVS_SW_MAX; + move16(); + X_fx->a_fx[0]=0; + move16(); + + HalfLag_fx=s_min(shr(X_fx->lag_fx,1),X_fx->nH_fx); + + j=1; + move16(); + FOR (i=1 ; i<=HalfLag_fx; i++) + { + Ltemp_fx=L_mult(diff_fx,i); /* Ltemp=i*diff, Q20 */ + freq_fx=round_fx(L_shl(Ltemp_fx,11)); /* Q15 */ + + freq_fx=s_min(freq_fx,upper_cut_off_freq_fx); /* 0x4000 is 0.5 in Q15 */ + + FOR ( ; j=0) + { + d2=sub(freq_fx,f_fx[j-1]); + Ltemp_fx=L_mac(L_mult(amp_fx[j],d2),amp_fx[j-1],d1); /* Q29 */ + d2=sub(f_fx[j],f_fx[j-1]); /* Q15 */ + /* Ltemp2_fx=invert_dp((Word40)d2, 4, &n,1); : Ltemp2=1/d2, Q(61-15-n) */ + exp = norm_s(d2); + tmp = div_s(shl(1,sub(14,exp)),d2);/* 29-exp */ + /* L_tmp = L_shr(tmp,8); */ + Ltemp2_fx = L_shl(tmp,16); + n = add(exp,16); + + d1h=extract_h(Ltemp_fx); + d1l=extract_l(Ltemp_fx); + d2h=extract_h(Ltemp2_fx); + d2l=extract_l(Ltemp2_fx); + Ltemp_fx=(Word32)L_mult0(d1h,d2l); + Lacc_fx=L_mac0((Word32)Ltemp_fx,d2h,d1l); + Ltemp_fx=L_add((Word32)L_shr(Lacc_fx,15),L_mult(d1h,d2h)); /* 46-n+29-31 */ + d2h=norm_l(Ltemp_fx); /* d2h is 0 IF Ltemp=0 */ + if( Ltemp_fx == 0 ) + { + d2h = 31; + move16(); + } + X_fx->a_fx[i]=round_fx(L_shl(Ltemp_fx,d2h)); /* Q(28-n+d2h) */ + q[i]=add(sub(28,n),d2h); + min_q=s_min(min_q,q[i]); + + BREAK ; + } + } + } + /* block normalize a[i] */ + FOR (i=1; i<=HalfLag_fx; i++) + { + X_fx->a_fx[i]=shl(X_fx->a_fx[i],sub(min_q,q[i])); + move16(); + } + + X_fx->Q=min_q; +} + +/*===================================================================*/ +/* FUNCTION : LPCPowSpect_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Compute LPC power spectrum */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16 []) freq : ERB frequency bounds, Q15 */ +/* _ (Word16 []) LPC : LPC coefficients, Q12 */ +/* _ (Word16) Nf: number of ERB bins, Q0 */ +/* _ (Word16) Np : order of LPC, Q0 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 []) out : LPC power spectrum, Q7 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*===================================================================*/ +/* NOTE: Frequency is normalized by 12800, i.e. 1=12800Hz */ +/*===================================================================*/ +void LPCPowSpect_fx(Word16 *freq, Word16 Nf, Word16 *LPC, Word16 Np, + Word16 *out) +{ + Word16 i, k; + Word16 w; /* Q9 */ + Word16 t1, dt; + /*Word16 t2; */ + Word16 dh, dl; + Word32 Re, Im; /* Q27 */ + Word32 Ltemp, Lw; + Word32 Lacc; + Word16 tmp,exp; + + FOR (k=0; k 0) + { + tmp = div_s(16384, tmp); /* 15+exp1 */ + } + ELSE + { + tmp = 0; + move16(); + } + Ltemp = L_deposit_h(tmp); + out[k] = round_fx(L_shl(Ltemp,negate(add(exp,8)))); + + /* out[k] = shl(tmp,-exp-8); in Q7 */ + + } +} +/*===================================================================*/ +/* FUNCTION : erb_diff_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Quantize erb amplitude for QPPP */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) pl : previous pitch lag, Q0 */ +/* _ (Word16) l : current pitch lag, Q0 */ +/* _ (Word16 []) prev_erb : Previous erb amplitude, Q13 */ +/* _ (Word16 []) curr_erb : Current erb amplitude, Q13 */ +/* _ (Word16 []) curr_lsp : LSP coefficients, Q12 */ +/* _ (Word16 []) num_erb : Number of ERBs , Q0 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 []) index: quantized differential erb index */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*===================================================================*/ +static +void erb_diff_fx( + const Word16 *prev_erb, /* i : previous ERB */ + Word16 pl, /* i : previous lag */ + const Word16 *curr_erb, /* i : current ERB */ + Word16 l, /* i : current lag */ + const Word16 *curr_lsp, /* i : current LSP coefficients */ + Word16 *index, /* 0 : ERB index */ + Word16 num_erb /* i : Number of ERBs */ +) +{ + Word16 i; + Word16 pslot[NUM_ERB_WB], cslot[NUM_ERB_WB]; + Word16 tmp, t_prev_erb[NUM_ERB_WB], LPC[M+1], mfreq[NUM_ERB_WB], PowSpect[NUM_ERB_WB], dif_erb[NUM_ERB_WB] ; + const Word16 *AmpCB1_fx = NULL; + + IF (EQ_16(num_erb,NUM_ERB_NB)) + { + AmpCB1_fx=AmpCB1_NB_fx; + move16(); + } + ELSE IF (EQ_16(num_erb,NUM_ERB_WB)) + { + AmpCB1_fx=AmpCB1_WB_fx; + move16(); + + } + erb_slot_fx (l,cslot,mfreq,num_erb);/* cslot in Qo and mfreq in Q15 */ + erb_slot_fx (pl,pslot,t_prev_erb,num_erb); + + FOR (i=0; i=0; i--) + { + IF (pslot[i]!=0) + { + tmp = t_prev_erb[i]; + move16(); + } + ELSE + { + t_prev_erb[i] = tmp ; + move16(); + } + } + } + FOR(i=0; i=0; i--) + { + + IF (pslot_fx[i] != 0) + { + tmp_fx = t_prev_erb_fx[i]; + move16(); /* Q13 */ + } + ELSE + { + t_prev_erb_fx[i] = tmp_fx; + move16(); /* Q13 */ + } + } + } + + tmp_fx = add(shl(index_fx[0],3),shl(index_fx[0],1)); /* tmp_fx=10*index_fx[0] */ + FOR (i=1; i<11; i++) + { + + IF (cslot_fx[i]!=0) + { + curr_erb_fx[i] = add(AmpCB1_fx[sub(add(tmp_fx,i),1)],t_prev_erb_fx[i]); + move16();/* Q13+Q13=Q13 */ + curr_erb_fx[i] = s_max(0, curr_erb_fx[i]); + move16(); + } + ELSE + curr_erb_fx[i] = 0; + move16(); + } + + tmp_fx = add(shl(index_fx[1],3),index_fx[1]); /* tmp=9*index[1] */ + tmp2_fx = mult(shl(index_fx[1],6),5632);/* temp=11*index_fx[1] */ + tmp_loop = sub(num_erb_fx,2); + FOR (i=11; iupper_cut_off_freq_fx,0x2800))/* 4000 hz normalized to 12800 in Q15 */ + { + num_erb=NUM_ERB_NB; + move16(); + PowerCB_fx=PowerCB_NB_fx; + move16(); + } + ELSE IF (EQ_16(X_fx->upper_cut_off_freq_fx,0x4000))/* 6400 hz normalized to 12800 in Q15 */ + { + num_erb=NUM_ERB_WB; + move16(); + PowerCB_fx=PowerCB_WB_fx; + move16(); + } + + /* Get weighting and target */ + quant_target_fx(X_fx,curr_lpc_fx, w, target, sin_tab, cos_tab); + + /* Power Quantization in log domain */ + target[0]=sub(target[0],*lastLgainE_fx); + move16(); + target[1]=sub(target[1],*lastHgainE_fx); + move16(); + + minerror = L_add(EVS_LW_MAX, 0); + *POWER_IDX = 0; + move16(); + + j=0; + move16(); + FOR (n=0; n=0 && d2>=0) + { + Ltemp= Mult_32_16(Ltemp,0x6666); /* *=0.8 */ + } + IF (LT_32(Ltemp, minerror)) + { + minerror = L_add(Ltemp, 0); + *POWER_IDX = j ; + move16(); + } + j = add(j,1); + } + DTFS_to_erb_fx (*X_fx,curr_erb_fx) ; + + FOR(j=0; jlag_fx, slot, mfreq,num_erb) ; + /* Amplitude Quantization */ + + + erb_diff_fx(lasterbE_fx,pl,curr_erb_fx,X_fx->lag_fx,curr_lpc_fx,AMP_IDX,num_erb); + + + /* Dequantization of prototype */ + /* PORTING: Removing the references */ + /* DTFS_dequant_cw_fx(pl, *POWER_IDX, AMP_IDX,lastLgainE_fx,lastHgainE_fx, lasterbE_fx,X_fx,num_erb,curr_erb_fx); */ + + /* Determine IF the amplitude quantization is good enough */ + erb_add_fx(curr_erb_fx,X_fx->lag_fx,lasterbE_fx,pl,AMP_IDX,num_erb); + + curr_erb_fx[0] = mult_r(curr_erb_fx[1],9830); + move16(); /* 0.3 inQ15 leaves curr_erb in Q13 */ + curr_erb_fx[sub(num_erb,2)] = mult_r(curr_erb_fx[sub(num_erb,3)],9830);/* Q13 */ + + curr_erb_fx[sub(num_erb,1)] = 0; + move16(); + flag=1; + move16(); + + Ltemp = L_deposit_l(0); + n=0; + move16(); + FOR (j=1; j<10; j++) + { + IF (slot[j]!=0) + { + Ltemp=L_add(Ltemp,abs_s(sub(erb_uq[j],curr_erb_fx[j]))); /* Q13 */ + n=add(n,1); /* n++ */ + } + } + + exp = norm_s(n); + tmp = div_s(shl(1,sub(14,exp)),n);/* 29 - exp */ + Lacc = L_shl( Mult_32_16(Ltemp , tmp), exp +4); + + tmp=round_fx(Lacc); /* tmp in Q15 */ + + test(); + if (GT_16(tmp,0x3C29)&>_16(target[0],-819)) + { + flag = 0 ; /* Bumping up */ move16(); + } + + /* mfreq normalized (2.56) in Q15 */ + DTFS_erb_inv_fx(curr_erb_fx, slot, mfreq, X_fx,num_erb) ; + + + /* Back up the lasterbD memory after power normalization */ + DTFS_setEngyHarm_fx(236,2828,0,2828,1,0,&Ql,X_fx); + DTFS_setEngyHarm_fx(2828,X_fx->upper_cut_off_freq_of_interest_fx,2828,X_fx->upper_cut_off_freq_fx,1,0,&Qh,X_fx); + + /* Need to unify the Q factors of both bands */ + X_fx->Q=s_min(Ql,Qh); /* set Q factor to be the smaller one */ + n=sub(Ql,Qh); /* compare band Q factors */ + + + /* This logic adjusts difference between Q formats of both bands */ + + IF (n<0) + rshiftHarmBand_fx(X_fx,2828, X_fx->upper_cut_off_freq_fx,n); + ELSE IF (n>0) + rshiftHarmBand_fx(X_fx,0, 2828, sub(Qh,Ql)); + + tmp=shl(*POWER_IDX,1); /* tmp=2*POWER_IDX */ + *lastLgainE_fx =add(*lastLgainE_fx, PowerCB_fx[tmp]) ; /* Q11 */ + *lastHgainE_fx =add(*lastHgainE_fx, PowerCB_fx[tmp+1]); /* Q11 */ + + Ltemp=log10_fx(X_fx->lag_fx); /* Ltemp=10*log10(lag), Q23 */ + logLag_fx= Mult_32_16(Ltemp,0x6666); /* logLag=log10(lag), Q26 */ + + Ltemp=L_sub(L_shr(L_deposit_h(*lastLgainE_fx),1),logLag_fx); /* Ltemp=Lgain-log10(lag), Q26 */ + + L_tmp=pow_10(Ltemp,&Q); /* Lacc=10^Lgain/lag, Q15 */ + n=norm_l(L_tmp); + Ltemp=(Word32)L_shl(L_tmp,n); /* Ltemp in Q(15+n) */ + + + DTFS_setEngyHarm_fx(236,2828,0,2828,Ltemp, add(Q,n),&Ql,X_fx); + + Ltemp=L_sub(L_shr(L_deposit_h(*lastHgainE_fx),1),logLag_fx); /* Ltemp=Hgain-log10(lag), Q26 */ + + /* Ltemp = L_shr(Ltemp,1); */ + L_tmp = pow_10(Ltemp,&Q); /* Lacc=10^Lgain/lag, Q15 */ + n=norm_l(L_tmp); + Ltemp=(Word32)L_shl(L_tmp,n); /* Ltemp in Q(15+n) */ + + DTFS_setEngyHarm_fx(2828,X_fx->upper_cut_off_freq_of_interest_fx,2828,X_fx->upper_cut_off_freq_fx,Ltemp,add(Q,n),&Qh,X_fx); + /* Need to unify the Q factors of both bands */ + X_fx->Q=s_min(Ql,Qh); /* set Q factor to be the smaller one */ + n=sub(Ql,Qh); /* compare band Q factors */ + + IF (n<0) + rshiftHarmBand_fx(X_fx,2828, X_fx->upper_cut_off_freq_fx,n); + ELSE IF (n>0) + rshiftHarmBand_fx(X_fx,0, 2828, sub(Qh,Ql)); + + return flag; +} +/*===================================================================*/ +/* FUNCTION : struct quant_target_fx() */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Get weighting and target for power quantization */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16 []) curr_lpc: LPC coefficients, Q12 */ +/* _ (Word16 []) sin_tab: sine table based on lag, Q15 */ +/* _ (Word16 []) cos_tab: cosine table based on lag, Q15 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) w: Weighting for power quantization, Q15 */ +/* _ (Word16[]) target: Power of 2 bands for quantization, Q11 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (struct DTFS_fx) X : prototype in polar domain */ +/* (Word16) lag: length of prototype in time domain */ +/* (Word16 []) a: amplitude of harmonics, normalized */ +/* (Word16) Q: norm factor of a */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*===================================================================*/ +/* NOTE: This function is used by quant_cw_fx and quant_cw_memless_fx*/ +/*===================================================================*/ +void quant_target_fx( DTFS_STRUCTURE_FX *X_fx,const Word16 *curr_lpc, Word16 *w, Word16 *target, + Word16 *sin_tab, Word16 *cos_tab) +{ + Word16 tmp, n,exp; + Word16 Ql, Qh; + Word32 Ltemp1, Ltemp, Ltemp2, logLag, Ltemp3,Lacc; + + tmp=sub(shl(X_fx->Q,1),13); /* tmp=2Q-13, Q factor of getSpEngy... output */ + Ltemp3=L_shl(L_mult(tmp,24660),9); /* Ltemp3=(2Q-13)*10log10(2), Q23, 24660=10log10(2) in Q13 */ + + Ltemp1 = getSpEngyFromResAmp_fx(X_fx,0, 2828,curr_lpc, sin_tab, cos_tab); + Ltemp1=log10_fx(Ltemp1); + + /* subtract 10log10(2)*(2Q-13), Q23 */ + Ltemp1=L_sub(Ltemp1,Ltemp3); + Ltemp1=L_max(0,Ltemp1); + Ltemp2 = getSpEngyFromResAmp_fx(X_fx,2828,X_fx->upper_cut_off_freq_fx,curr_lpc, sin_tab, cos_tab); + Ltemp2=log10_fx(Ltemp2 ); /* Ltemp1=10log10(eng_hb), Q23, need to adjust for Q factor of energy (2Q-13) */ + Ltemp2=L_sub(Ltemp2,Ltemp3); /* Ltemp2 in Q23 */ + + Ltemp2=L_max(0,Ltemp2); + + /* Getting the Speech Domain Energy LOG Ratio */ + + Lacc = L_add(Ltemp1,Ltemp2); + exp = norm_l(Lacc); + tmp = round_fx(L_shl(Lacc,exp)); + exp = sub(sub(30,exp),23); + IF(tmp) + tmp = div_s(16384,tmp); /* 15+exp1 */ + ELSE + tmp = 0; + Ltemp = L_deposit_h(tmp); + + tmp=round_fx(Ltemp); /* tmp in Q(22-n) */ + Ltemp1= Mult_32_16(Ltemp1,tmp); /* Q(30-n) */ + n=sub(8,exp); + w[0]=round_fx(L_shl(Ltemp1,n)); /* w[0] in Q15 */ + Ltemp2= Mult_32_16(Ltemp2,tmp); + w[1]=round_fx(L_shl(Ltemp2,n)); /* w[1] in Q15 */ + + logLag=log10_fx(X_fx->lag_fx); /* logLag=10*log10(lag), Q23 */ + Ltemp3=L_shl(L_mult(shl(X_fx->Q,1),24660),9); /* Ltemp3=2Q*10log10(2), Q23 */ + /* Process low band */ + Ltemp=DTFS_setEngyHarm_fx(236, 2828, 0, 2828, 1, 0, &Ql,X_fx); /* Ql is norm factor of low band a[], Ltemp is energy in 2Q */ + /* Compensate for Q factor of energy to get log10(lag*eng) */ + Ltemp=log10_fx(Ltemp); /* Ltemp=10log10(eng), Q23 */ + Ltemp=L_add(L_sub(Ltemp,Ltemp3),logLag); /* Ltemp=10*log10(lag*eng), Q23 */ + + target[0]=round_fx(L_shl(Mult_32_16(Ltemp,0x6666),1)); /* Q11 */ + + /* Process high band */ + Ltemp=DTFS_setEngyHarm_fx(2828, X_fx->upper_cut_off_freq_of_interest_fx, 2828, X_fx->upper_cut_off_freq_fx, 1, 0, &Qh,X_fx); + Ltemp=log10_fx(Ltemp); + Ltemp=L_add(L_sub(Ltemp,Ltemp3),logLag); /* Ltemp=10*log10(lag*eng), Q23 */ + target[1]=round_fx(L_shl(Mult_32_16(Ltemp,0x6666),1)); /* Q11 */ + + /* Need to unify the Q factors of both bands */ + X_fx->Q=s_min(Ql,Qh); /* set Q factor to be the smaller one */ + n=sub(Ql,Qh); /* compare band Q factors */ + + IF (n<0) rshiftHarmBand_fx(X_fx,2828, X_fx->upper_cut_off_freq_fx,n); + ELSE IF (n>0) rshiftHarmBand_fx(X_fx,0, 2828, sub(Qh,Ql)); +} +/*===================================================================*/ +/* FUNCTION : struct DTFS_fx::dequant_cw_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Dequantize QPPP prototype */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) pl: previous lag */ +/* _ (Word16) p_idx: Power index */ +/* _ (Word16[]) a_idx: Amplitude indices, 2 words */ +/* _ (struct DTFS_fx) X : prototype in polar domain */ +/* (Word16) lag: length of prototype */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (struct DTFS_fx) X : prototype in polar domain */ +/* (Word16) lag: length of prototype in time domain */ +/* (Word16 []) a: amplitude of harmonics, normalized */ +/* (Word16) Q: norm factor of a */ +/* _ (Word16[]) curr_erb: Quantized current ERB, Q13 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16[]) lasterb: ERB history for differential */ +/* quantization, Q13 */ +/* _ (Word16) Lgain: low band power history, log domain, Q11 */ +/* _ (Word16) Hgain: high band power history, log domain, Q11 */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ + +void DTFS_dequant_cw_fx( + Word16 pl_fx, /* i : Previous lag */ + Word16 POWER_IDX_fx, /* i : POWER index */ + const Word16 *AMP_IDX_fx, /* i : Amp Shape index */ + Word16 *lastLgainD_fx, /* i/o: low band last gain */ + Word16 *lastHgainD_fx, /* i/o: high band last gain */ + Word16 *lasterbD_fx, /* i/o: last frame ERB vector */ + DTFS_STRUCTURE_FX *X_fx, /* o : DTFS structure dequantized */ + Word16 num_erb_fx +) + +{ + Word16 tmp_fx, mfreq_fx[NUM_ERB_WB], curr_erb_fx[NUM_ERB_WB]; + const Word16 *PowerCB_fx=NULL; + Word16 slot_fx[NUM_ERB_WB]; + Word16 Ql, Qh, n; + Word32 Ltemp_fx,logLag_fx; + Word16 exp,frac,exp1; + Word32 L_tmp,L_temp; + Word32 L_tmp2; + + IF (num_erb_fx==NUM_ERB_NB) + { + PowerCB_fx=PowerCB_NB_fx; + move16(); + } + ELSE IF (num_erb_fx==NUM_ERB_WB) + { + PowerCB_fx=PowerCB_WB_fx; + move16(); + } + + /* Amplitude Dequantization */ + + erb_add_fx(curr_erb_fx,X_fx->lag_fx,lasterbD_fx,pl_fx,AMP_IDX_fx,num_erb_fx); + + curr_erb_fx[0] = mult_r(curr_erb_fx[1],9830);/* 0.3 inQ15 leaves curr_erb in Q13 */ + curr_erb_fx[sub(num_erb_fx,2)] = mult_r(curr_erb_fx[sub(num_erb_fx,3)],9830);/* Q13 */ + + move16(); + + curr_erb_fx[sub(num_erb_fx,1)] = 0; + + erb_slot_fx(X_fx->lag_fx,slot_fx,mfreq_fx,num_erb_fx); + + /* mfreq normalized (2.56) in Q15 */ + DTFS_erb_inv_fx(curr_erb_fx, slot_fx, mfreq_fx, X_fx,num_erb_fx) ; + + + /* Back up the lasterbD memory after power normalization */ + + DTFS_setEngyHarm_fx(236,2828,0,2828,1,0,&Ql,X_fx); + DTFS_setEngyHarm_fx(2828,X_fx->upper_cut_off_freq_of_interest_fx,2828,X_fx->upper_cut_off_freq_fx,1,0,&Qh,X_fx); + + /* Need to unify the Q factors of both bands */ + X_fx->Q=s_min(Ql,Qh); /* set Q factor to be the smaller one */ + n=sub(Ql,Qh); /* compare band Q factors */ + + + + + /* This logic adjusts difference between Q formats of both bands */ + IF (n<0) + rshiftHarmBand_fx(X_fx,2828, X_fx->upper_cut_off_freq_fx,n); + ELSE IF (n>0) + rshiftHarmBand_fx(X_fx,0, 2828, sub(Qh,Ql)); + + DTFS_to_erb_fx(*X_fx,lasterbD_fx); + + + /* Power Dequantization */ + + tmp_fx=shl(POWER_IDX_fx,1); /* tmp=2*POWER_IDX */ + *lastLgainD_fx =add(*lastLgainD_fx, PowerCB_fx[tmp_fx]) ; /* Q11 */ + *lastHgainD_fx =add(*lastHgainD_fx, PowerCB_fx[tmp_fx+1]); /* Q11 */ + + L_tmp = L_deposit_h(X_fx->lag_fx); /* Q16 */ + exp = norm_l(L_tmp); + L_tmp = L_shl(L_tmp,exp); + frac = Log2_norm_lc(L_tmp); + exp = sub(30,add(exp,16)); + L_tmp = Mpy_32_16(exp,frac,12330);/* Q13 */ /* 10*log10(2) in Q12*/ + Ltemp_fx = L_shl(L_tmp, 10);/* Q23 */ + + + logLag_fx= Mult_32_16(Ltemp_fx,0x6666); /* logLag=log10(lag), Q26 */ + + Ltemp_fx=L_sub(L_shr(L_deposit_h(*lastLgainD_fx),1),logLag_fx); /* Ltemp=Lgain-log10(lag), Q26 */ + + /* Lacc_fx=dsp_pow10(Ltemp_fx); : Lacc=10^Lgain/lag, Q15 */ + + L_tmp = Mult_32_16(Ltemp_fx, 27213); /* 3.321928 in Q13 */ + L_tmp = L_shr(L_tmp,8); /* Q16 */ + frac = L_Extract_lc(L_tmp, &exp1); /* Extract exponent */ + L_tmp =Pow2(14, frac); + exp1 = sub(exp1,14); + L_temp = L_shl(L_tmp, add(exp1,15) ); /* Q15 */ + + L_tmp2 = L_temp; + if( GE_32( L_temp, 2147483647 )) + { + L_temp = L_shl(L_tmp, 15 ); /*Q(15-exp1) */ + } + + n=norm_l(L_temp); + Ltemp_fx=L_shl(L_temp,n); /* Ltemp in Q(15+n) or Q(15 - exp1 +n) */ + + IF( GE_32( L_tmp2, 2147483647 )) + { + DTFS_setEngyHarm_fx( 236, 2828, 0, 2828, Ltemp_fx, add(15,sub(n,exp1)), &Ql, X_fx ); + } + ELSE + { + DTFS_setEngyHarm_fx( 236, 2828, 0, 2828, Ltemp_fx, add(15,n), &Ql, X_fx ); + } + + Ltemp_fx=L_sub(L_shr(L_deposit_h(*lastHgainD_fx),1),logLag_fx); /* Ltemp=Hgain-log10(lag), Q26 */ + /* Lacc_fx=dsp_pow10(Ltemp_fx); : Lacc=10^Hgain/lag, Q15 */ + L_tmp = Mult_32_16(Ltemp_fx, 27213); /* 3.321928 in Q13 */ /* Q24 */ + L_tmp = L_shr(L_tmp,8); /* Q16 */ + frac = L_Extract_lc(L_tmp, &exp1); /* Extract exponent */ + L_tmp =Pow2(14, frac); + exp1 = sub(exp1,14); + L_temp = L_shl(L_tmp,exp1 +15 ); /* Q15 */ + + L_tmp2 = L_temp; + if( GE_32( L_temp, 2147483647 )) + { + L_temp = L_shl(L_tmp, 15 ); /*Q(15-exp1) */ + } + + + n=norm_l(L_temp); + Ltemp_fx=L_shl(L_temp,n); /* Ltemp in Q(15+n) or Q(15 - exp1 +n) */ + + IF( GE_32( L_tmp2, 2147483647 )) + { + DTFS_setEngyHarm_fx( 2828, X_fx->upper_cut_off_freq_of_interest_fx,2828, X_fx->upper_cut_off_freq_fx, Ltemp_fx,add( 15, sub( n, exp1 )),&Qh, X_fx ); + } + ELSE + { + DTFS_setEngyHarm_fx( 2828, X_fx->upper_cut_off_freq_of_interest_fx,2828, X_fx->upper_cut_off_freq_fx, Ltemp_fx, add( 15, n ), &Qh, X_fx ); + } + + + /* Need to unify the Q factors of both bands */ + X_fx->Q=s_min(Ql,Qh); /* set Q factor to be the smaller one */ + n=sub(Ql,Qh); /* compare band Q factors */ + + + + IF (n<0) + rshiftHarmBand_fx(X_fx,2828, X_fx->upper_cut_off_freq_fx,n); + ELSE IF (n>0) + rshiftHarmBand_fx(X_fx,0, 2828, sub(Qh,Ql)); +} +/*==========================================================================*/ +/* FUNCTION : WIsyn_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) PREVCW_FX: a/b in PREVCW_FX.Q */ +/* _ (struct DTFS_fx *) CURR_CW_DTFS_FX: a/b in CURR_CW_DTFS_FX->Q */ +/* _ (Word16 *) curr_lpc_fx: lpc coefficients in Q12 */ +/* _ (Word16 *) ph_offset_fx: in Q15, normalized by 2pi */ +/* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */ +/* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */ +/* _ (Word16 *) N: length, Q0 */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 *) out_fx: Q0 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX *) CURR_CW_DTFS_FX: a/b in CURR_CW_DTFS_FX->Q*/ +/* _ (Word16 *) ph_offset_fx: in Q15, normalized by 2pi */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*==========================================================================*/ + +void WIsyn_fx( + DTFS_STRUCTURE_FX PREVCW_FX, + DTFS_STRUCTURE_FX *CURR_CW_DTFS_FX, + const Word16 *curr_lpc_fx, + Word16 *ph_offset_fx, + Word16 *out_fx, + Word16 N, + Word16 FR_flag, /* i : called for post-smoothing in FR */ + Word16 * S_fx, + Word16* C_fx, + Word16 *pf_temp1, + Word16 *pf_temp2, + Word16 *pf_temp, + Word16 *pf_n2 +) +{ + Word16 i; + UWord16 I=1, flag=0; + /* Word16 *phase_fx = (Word16*)malloc(sizeof(Word16) * (2*N)); new operator used size 2*N */ + Word32 phase_fx[WI_FX_phase_fx]; + Word16 alignment_fx; + Word16 tmp_fx, temp; + Word32 L_temp; + Word16 exp,tmp; + Word32 L_tmp; + /* prev_lsp_fx; */ + + + DTFS_STRUCTURE_FX *CURRCW_DTFS_FX=DTFS_new_fx(); + + + IF (LT_16(PREVCW_FX.Q,CURR_CW_DTFS_FX->Q)) + { + temp = sub(CURR_CW_DTFS_FX->Q, PREVCW_FX.Q); + tmp = s_min(shr(CURR_CW_DTFS_FX->lag_fx,1),CURR_CW_DTFS_FX->nH_fx); + FOR (i=0; i<=tmp; i++) + { + CURR_CW_DTFS_FX->a_fx[i] = shr(CURR_CW_DTFS_FX->a_fx[i], temp); + move16(); + CURR_CW_DTFS_FX->b_fx[i] = shr(CURR_CW_DTFS_FX->b_fx[i], temp); + move16(); + } + CURR_CW_DTFS_FX->Q=PREVCW_FX.Q; + move16(); + } + + + IF (LT_16(CURR_CW_DTFS_FX->Q,PREVCW_FX.Q)) + { + temp = sub(PREVCW_FX.Q, CURR_CW_DTFS_FX->Q); + tmp = s_min(shr(PREVCW_FX.lag_fx, 1),PREVCW_FX.nH_fx); + FOR (i=0; i<=tmp; i++) + { + PREVCW_FX.a_fx[i] = shr(PREVCW_FX.a_fx[i], temp); + move16(); + PREVCW_FX.b_fx[i] = shr(PREVCW_FX.b_fx[i], temp); + move16(); + } + PREVCW_FX.Q=CURR_CW_DTFS_FX->Q; + move16(); + } + + DTFS_copy_fx( CURRCW_DTFS_FX, *CURR_CW_DTFS_FX); + /* Calculating the expected alignment shift */ + alignment_fx = mult_r(*ph_offset_fx, shl(PREVCW_FX.lag_fx, 7)); /* confirmed I<2 by smv12.org, Q7 */ + + + IF (EQ_16(flag,1)) + alignment_fx = extract_l(L_shr(L_mult(alignment_fx, I), 1)) ; /* Q7 */ + + /* Calculating the expected alignment shift */ + find_rem((Word16)N, shr(add(PREVCW_FX.lag_fx, CURRCW_DTFS_FX->lag_fx), 1), &temp); + temp = add(shl(temp, 7), alignment_fx); /* Q7 */ + + + IF (temp<0) + temp = add(temp,shl(CURRCW_DTFS_FX->lag_fx,7)); /* Q7 */ + + find_rem(temp,shl(CURRCW_DTFS_FX->lag_fx, 7),&tmp_fx); /* Q7 */ + IF (FR_flag==0) + { + alignment_fx = DTFS_alignment_weight_fx(&PREVCW_FX, *CURRCW_DTFS_FX,tmp_fx, curr_lpc_fx, curr_lpc_fx, S_fx, + C_fx, pf_temp1, pf_temp2, pf_temp, pf_n2); + move16();/* Q7 */ + } + ELSE + { + alignment_fx = DTFS_alignment_full_fx(PREVCW_FX, *CURRCW_DTFS_FX, *ph_offset_fx, S_fx, C_fx + ,FR_flag + ); + + /*alignment_fx is in Q1, we make it Q7*/ + alignment_fx = shl(alignment_fx,6); + } + + + IF (GE_16(alignment_fx,shl(CURRCW_DTFS_FX->lag_fx, 7))) + { + temp=sub(alignment_fx, shl(CURRCW_DTFS_FX->lag_fx, 7)); + tmp = shl(CURRCW_DTFS_FX->lag_fx, 7); + exp = norm_s(tmp); + tmp = div_s(shl(1,sub(14,exp)),tmp);/* 22-exp */ + L_tmp =L_shl(L_mult(temp,tmp),exp+1); + tmp_fx = round_fx(L_tmp); + } + ELSE IF (alignment_fx<0) + { + temp=negate(alignment_fx); + tmp = shl(CURRCW_DTFS_FX->lag_fx, 7); + exp = norm_s(tmp); + tmp = div_s(shl(1,sub(14,exp)),tmp);/* 22-exp */ + L_tmp =L_shl(L_mult(temp,tmp),exp+1); + tmp_fx = negate( round_fx(L_tmp)); + } + ELSE + { + temp=alignment_fx; + move16(); + tmp = shl(CURRCW_DTFS_FX->lag_fx, 7); + exp = norm_s(tmp); + tmp = div_s(shl(1,sub(14,exp)),tmp);/* 22-exp */ + L_tmp =L_shl(L_mult(temp,tmp),exp+1); + tmp_fx = round_fx(L_tmp); + } + + DTFS_phaseShift_fx(CURRCW_DTFS_FX, alignment_fx, CURRCW_DTFS_FX->lag_fx, S_fx, C_fx) ; /* Qmin */ + DTFS_phaseShift_fx(CURR_CW_DTFS_FX, alignment_fx, CURR_CW_DTFS_FX->lag_fx, S_fx, C_fx);/* Qmin */ + + /* Compute the cubic phase track and transform to 1-D signal */ + cubicPhase_fx(*ph_offset_fx, tmp_fx, PREVCW_FX.lag_fx , CURRCW_DTFS_FX->lag_fx, N, phase_fx) ; + + temp = shr(add(PREVCW_FX.lag_fx,CURRCW_DTFS_FX->lag_fx),1); /* Q0 */ + + IF (FR_flag==0) + { + DTFS_transform_fx(PREVCW_FX,*CURRCW_DTFS_FX, phase_fx, out_fx, N, 0) ; + } + ELSE + { + DTFS_transform_fx (PREVCW_FX, *CURRCW_DTFS_FX, phase_fx, out_fx, N, 1) ; + } + + + /* Adjust the phase offset and wrap it between 0 and 2pi */ + + + + + IF (EQ_16(flag,2)) + { + L_temp = L_shr(L_mult(tmp_fx, I), 1); /* Q15 */ + } + ELSE + { + L_temp = L_deposit_l(tmp_fx); /* Q15 */ + } + + + FOR ( ; L_temp < 0; L_temp += 0x8000L) + { + /* empty loop */ + } + L_temp = L_temp&0x7fff; + move16(); /* fraction part */ + *ph_offset_fx = extract_l(L_temp); + + /* free(phase_fx) ; */ + free(CURRCW_DTFS_FX); +} + + + +/*===================================================================*/ +/* FUNCTION : ppp_extract_pitch_period_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Update background noise estimate, signal energy */ +/* estimate, and band snrs */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16 []) in : residual input, Q0 */ +/* _ (Word16) l : pitch lag, Q0 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 []) out : pitch period prototype, Q0 */ +/* _ (Word16*) out_of_bound : pitch lag, Q0 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word16) spike_near_edge : Q0 */ +/*===================================================================*/ +Word16 ppp_extract_pitch_period_fx( + const Word16 *in, /* i : input residual */ + Word16 *out, /* o : output residual */ + Word16 l, /* i : lag */ + Word16 *out_of_bound, /* o : out of bound flag */ + Word16 Qres + +) +{ + Word16 i,j,k; + Word16 spike=0,range; + Word16 max=0; + const Word16 *ptr=in+L_FRAME-l; + Word32 en1 = 0,Lacc,L_tmp; + Word16 spike_near_edge=0,scale; + Word16 pos_max,neg_max; + Word16 spike_pos=0,spike_neg=0; + Word16 x,tmp,expa,fraca,expb,fracb,scale1,exp; + + pos_max = -0x8000L; + move16(); + neg_max = 0; + move16(); + *out_of_bound=0; + move16(); + + en1 = L_deposit_l(0); + FOR (i=0 ; i0) + { + spike_pos=spike; + move16(); + /* search for neg spike around the pos spike */ + FOR(j=spike-10; j0) + tmp = add(tmp,4);/* Q3 */ + ELSE + tmp = sub(tmp,4);/* Q3 */ + range = shr(tmp,3);/* Q0 */ + + test(); + IF((LT_16(spike,range))||(GE_16(add(spike,range),l))) + { + /* need to grab from one lag before + ensure that there is no array bound read */ + + IF(LT_16(sub(L_FRAME,l),l)) + { + *out_of_bound=1; + move16(); + return spike_near_edge; + } + spike_near_edge=1; + move16(); + } + + IF(LT_16(spike,range)) + { + tmp = add(l,sub(spike,range)); + FOR(i=0; i=in) + { + FOR(ptr-=l; i= 0) + { + if (GT_32(L_temp,maxPosEn_fx)) + { + maxPosEn_fx = L_temp ; /* Q(1) */ + } + } + ELSE + { + if (GT_32(L_temp,maxNegEn_fx)) + { + maxNegEn_fx = L_temp ; /* Q(1) */ + } + } + } + + + IF (L_sum==0) + { + *pos_fx=*neg_fx=0; + move16(); + move16(); + } + ELSE + { + IF (maxPosEn_fx==0) + { + *pos_fx=0; + *Qpos=31; + } + ELSE + { + expa = norm_l(maxPosEn_fx); + fraca = extract_h(L_shl(maxPosEn_fx,expa)); + expa = sub(30,add(expa,1)); + + + expb = norm_l(L_sum); + fracb = round_fx(L_shl(L_sum,expb)); + expb = sub(30,add(expb,shl(X_fx.Q,1))); + + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); + exp = sub(expb,expa); + + L_tmp = Isqrt_lc(L_deposit_h(tmp),&exp); /* Q(31-exp) */ + *pos_fx = L_tmp; + *Qpos = sub(31, exp); + + } + + IF (maxNegEn_fx==0) + { + *neg_fx=0; + *Qneg=31; + } + ELSE + { + + expa = norm_l(maxNegEn_fx); + fraca = extract_h(L_shl(maxNegEn_fx,expa)); + expa = 30-expa- 1; + + + expb = norm_l(L_sum); + fracb = round_fx(L_shl(L_sum,expb)); + expb = 30-expb - (2*X_fx.Q); + + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); + exp = sub(expb,expa); + + L_tmp = Isqrt_lc(L_deposit_h(tmp),&exp); /* Q(31-exp) */ + *neg_fx = L_tmp; + *Qneg = 31 - exp; + + } + + } +} + +/*===================================================================*/ +/* FUNCTION : struct DTFS_fx:: rshiftHarmBand_fx() */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Right-shift harmonics in band to align Q factor */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) lband: lower band boundary, Q15 */ +/* _ (Word16) hband: upper band boundary, Q15 */ +/* _ (Word16) shift: right shift value, Q0 (must be <0) */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (struct DTFS_fx) X : prototype in polar domain */ +/* (Word16) lag: length of prototype in time domain */ +/* (Word16 []) a: amplitude of harmonics, normalized */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ +/* NOTE: This function should be called after two consecutive calls */ +/* to setEngyHarm_fx, because the norm factor outputs from */ +/* the two previous calls might be different */ +/*===================================================================*/ +void rshiftHarmBand_fx( DTFS_STRUCTURE_FX *X_fx,Word16 lband_fx, Word16 hband_fx, Word16 shift_fx) +{ + Word16 k_fx, HalfLag_fx; + Word16 low_fx, high_fx; + + low_fx=mult(lband_fx,X_fx->lag_fx); /* low=lband*lag, Q0 */ + high_fx=mult(hband_fx,X_fx->lag_fx); /* high=hband*lag, Q0 */ + HalfLag_fx = s_min(high_fx,shl(X_fx->nH_fx,1)); + + FOR (k_fx=low_fx+1; k_fx<=HalfLag_fx; k_fx++) + { + X_fx->a_fx[k_fx]=shl_r(X_fx->a_fx[k_fx],shift_fx); + move16(); /* right shift and round */ + } +} + +/*===================================================================*/ +/* FUNCTION : GetSinCosTab_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Compute sine & cosine table given pitch lag, */ +/* by interpolating the 512-entry cosine table. */ +/* sin(2pi/4L*n) & cos(2pi/4L*n) for n=0,1,... 4L-1 */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) L : Pitch lag, Q0 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 []) sinTab, Q15 : sin(2pi/4L*n), n=0,1,...,4L-1 */ +/* _ (Word16 []) cosTab, Q15 : cos(2pi/4L*n), n=0,1,...,4L-1 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ +/* NOTE: This function interpolates cos_table for better accuracy */ +/*===================================================================*/ +void GetSinCosTab_fx(Word16 L, Word16 *sinTab, Word16 *cosTab) +{ + Word16 i, L4; + Word16 dl, t1, w, dt; + /* Word16 t2; */ + Word32 invL; /* 1/4L in Q25 */ + Word32 Ltemp, Lw; + Word32 L_tmp; + + invL = L_shr(inverse_table[L],4); + + L4=shl(L,2); + Lw = L_deposit_l(0); + FOR (i=0 ; i 0; k -= size) + { + K=add(K,1); /* K=512/size */ + } + n_2=shr(size,1); + FOR (i=1; i<=stage; i++) ii_table[i-1]=shr(size,i); + + /* Rearrange the input array in bit reversed order */ + j = 0; + move16(); + FOR (i = 0 ; i < size - 2; i = i + 2) + { + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + + IF (GT_16(j,i)) + { + ftmp_fx = *(farray_ptr_fx + i); + *(farray_ptr_fx + i) = *(farray_ptr_fx + j); + *(farray_ptr_fx + j) = (Word16) ftmp_fx; + + ftmp_fx = *(farray_ptr_fx + i + 1); + *(farray_ptr_fx + i + 1) = *(farray_ptr_fx + j + 1); + *(farray_ptr_fx + j + 1) = (Word16)ftmp_fx; + } + + k = n_2; + move16(); + WHILE (j >= k) + { + j = sub(j, k); + k = shr(k, 1); + } + j += k; + } + + /* The FFT part */ + + + + IF (isign == 1) + { + FOR (i = 0; i < stage; i++) /* i is stage counter */ + { + jj = shl(2, i); /* FFT size */ + kk = shl(jj, 1); /* 2 * FFT size */ + + move16(); + + ii = ii_table[i]; /* 2 * number of FFT's */ + + FOR (j = 0; j < jj; j = j + 2) /* j is sample counter */ + { + ji = j * ii; /* ji is phase table index */ + + FOR (k = j; k < size; k = k + kk) /* k is butterfly top */ + { + kj = add(k, jj); /* kj is butterfly bottom */ + temp_sand = s_and((ji*K+384),511); + /* Butterfly computations */ + /* ftmp_real_fx = L_sub(L_mult(*(farray_ptr_fx + kj), cos_table[ji*K]), */ + /* L_mult(*(farray_ptr_fx + kj + 1), cos_table[(ji*K+384)%512])); */ + ftmp_real_fx = L_msu(L_mult(*(farray_ptr_fx + kj), cos_table[ji*K]), + *(farray_ptr_fx + kj + 1), cos_table[temp_sand]); + + /* ftmp_imag_fx = L_add(L_mult(*(farray_ptr_fx + kj + 1), cos_table[ji*K]), */ + /* L_mult(*(farray_ptr_fx + kj), cos_table[(ji*K+384)%512])); */ + ftmp_imag_fx = L_mac(L_mult(*(farray_ptr_fx + kj + 1), cos_table[ji*K]), + *(farray_ptr_fx + kj), cos_table[temp_sand]); + + tmp1 = round_fx(ftmp_real_fx); + tmp2 = round_fx(ftmp_imag_fx); + + tmp = sub(*(farray_ptr_fx + k), tmp1); + *(farray_ptr_fx + kj) = shr(tmp, 1); + move16(); + + tmp = sub(*(farray_ptr_fx + k + 1), tmp2); + *(farray_ptr_fx + kj + 1) = shr(tmp, 1); + move16(); + + tmp = add(*(farray_ptr_fx + k), tmp1); + *(farray_ptr_fx + k) = shr(tmp, 1); + move16(); + + tmp = add(*(farray_ptr_fx + k + 1), tmp2); + *(farray_ptr_fx + k + 1) = shr(tmp, 1); + move16(); + } + } + } + + /* The IFFT part */ + } + ELSE + { + FOR (i = 0; i < stage; i++) /* i is stage counter */ + { + jj = shl(2, i); /* FFT size */ + kk = shl(jj, 1); /* 2 * FFT size */ + ii = ii_table[i]; /* 2 * number of FFT's */ + + FOR (j = 0; j < jj; j = j + 2) /* j is sample counter */ + { + ji = j * ii; /* ji is phase table index */ + + FOR (k = j; k < size; k = k + kk) /* k is butterfly top */ + { + kj = add(k, jj); /* kj is butterfly bottom */ + temp_sand = s_and((ji*K+384),511); + /* Butterfly computations */ + /* ftmp_real_fx = L_add(L_mult(*(farray_ptr_fx + kj), cos_table[ji*K]), */ + /* L_mult(*(farray_ptr_fx + kj + 1), cos_table[(ji*K+384)%512])); */ + ftmp_real_fx = L_mac(L_mult(*(farray_ptr_fx + kj), cos_table[ji*K]), + *(farray_ptr_fx + kj + 1), cos_table[temp_sand]); + + /* ftmp_imag_fx = L_sub(L_mult(*(farray_ptr_fx + kj + 1), cos_table[ji*K]), */ + /* L_mult(*(farray_ptr_fx + kj), cos_table[(ji*K+384)%512])); */ + ftmp_imag_fx = L_msu(L_mult(*(farray_ptr_fx + kj + 1), cos_table[ji*K]), + *(farray_ptr_fx + kj), cos_table[temp_sand]); + + tmp1 = round_fx(ftmp_real_fx); + tmp2 = round_fx(ftmp_imag_fx); + + *(farray_ptr_fx + kj) = sub(*(farray_ptr_fx + k), tmp1); + move16(); + *(farray_ptr_fx + kj + 1) = sub(*(farray_ptr_fx + k + 1), tmp2); + move16(); + *(farray_ptr_fx + k) = add(*(farray_ptr_fx + k), tmp1); + move16(); + *(farray_ptr_fx + k + 1) = add(*(farray_ptr_fx + k + 1), tmp2); + move16(); + } + } + } + } + +} /* end of c_fft () */ + + +void r_fft_4_fx(Word16 * farray_ptr_fx, Word16 size, Word16 stage, Word16 isign) +{ + + Word16 ftmp1_real_fx, ftmp1_imag_fx, ftmp2_real_fx, ftmp2_imag_fx; + Word32 Lftmp1_real_fx, Lftmp1_imag_fx; + Word16 i, j,temp_sand; + Word32 Ltmp1_fx, Ltmp2_fx; + Word16 n_2, k, K; + + n_2 = shr(size,1); + K=0; + move16(); + + FOR (k = 256; k > 0; k -= size) + { + K = add(K,1); /* K=512/size */ + } + + /* The FFT part */ + IF (isign == 1) + { + /* Perform the complex FFT */ + c_fft_wi_fx(farray_ptr_fx, size, stage, isign); + + /* First, handle the DC and foldover frequencies */ + ftmp1_real_fx = *farray_ptr_fx; + ftmp2_real_fx = *(farray_ptr_fx + 1); + *farray_ptr_fx = add(ftmp1_real_fx, ftmp2_real_fx); + *(farray_ptr_fx + 1) = sub(ftmp1_real_fx, ftmp2_real_fx); + + /* Now, handle the remaining positive frequencies */ + j = size - 2; + FOR (i = 2; i <= n_2; i = i + 2 ) + { + ftmp1_real_fx = add(*(farray_ptr_fx + i), *(farray_ptr_fx + j)); + ftmp1_imag_fx = sub(*(farray_ptr_fx + i + 1), *(farray_ptr_fx + j + 1)); + ftmp2_real_fx = add(*(farray_ptr_fx + i + 1), *(farray_ptr_fx + j + 1)); + ftmp2_imag_fx = sub(*(farray_ptr_fx + j), *(farray_ptr_fx + i)); + + Lftmp1_real_fx = L_deposit_h(ftmp1_real_fx); + Lftmp1_imag_fx = L_deposit_h(ftmp1_imag_fx); + temp_sand = s_and((i*K+384),511); + /* Ltmp1_fx = L_sub(L_mult(ftmp2_real_fx, cos_table[i*K]), L_mult(ftmp2_imag_fx, cos_table[(i*K+384)%512])); */ + Ltmp1_fx = L_msu(L_mult(ftmp2_real_fx, cos_table[i*K]), ftmp2_imag_fx, cos_table[temp_sand]); + *(farray_ptr_fx + i) = round_fx(L_shr(L_add(Lftmp1_real_fx, Ltmp1_fx), 1)); + + /* Ltmp1_fx = L_add(L_mult(ftmp2_imag_fx, cos_table[i*K]), L_mult(ftmp2_real_fx, cos_table[(i*K+384)%512])); */ + Ltmp1_fx = L_mac(L_mult(ftmp2_imag_fx, cos_table[i*K]), ftmp2_real_fx, cos_table[temp_sand]); + *(farray_ptr_fx + i + 1) = round_fx(L_shr(L_add(Lftmp1_imag_fx, Ltmp1_fx), 1)); + + /* Ltmp1_fx = L_add(L_mult(ftmp2_real_fx, cos_table[j*K]), L_mult(ftmp2_imag_fx, cos_table[(j*K+384)%512])); */ + Ltmp1_fx = L_mac(L_mult(ftmp2_real_fx, cos_table[j*K]), ftmp2_imag_fx, cos_table[temp_sand]); + *(farray_ptr_fx + j) = round_fx(L_shr(L_add(Lftmp1_real_fx, Ltmp1_fx), 1)); + + /* Ltmp1_fx = L_add(L_negate(L_mult(ftmp2_imag_fx, cos_table[j*K])), L_mult(ftmp2_real_fx, cos_table[(j*K+384)%512])); */ + Ltmp1_fx = L_msu(L_mult(ftmp2_real_fx, cos_table[temp_sand]), ftmp2_imag_fx, cos_table[j*K]); + Ltmp2_fx = L_sub(Ltmp1_fx, Lftmp1_imag_fx); + *(farray_ptr_fx + j + 1) = round_fx(L_shr(Ltmp2_fx, 1)); + j = size - i; + } + + } + ELSE + { + + /* First, handle the DC and foldover frequencies */ + + move16(); + move16(); + + ftmp1_real_fx = *farray_ptr_fx; + ftmp2_real_fx = *(farray_ptr_fx + 1); + *farray_ptr_fx = shr(add(ftmp1_real_fx, ftmp2_real_fx), 1); + move16(); + *(farray_ptr_fx + 1) = shr(sub(ftmp1_real_fx, ftmp2_real_fx), 1); + move16(); + + /* Now, handle the remaining positive frequencies */ + FOR (i = 2; i <= n_2; i += 2) + { + j = sub(size, i); + + ftmp1_real_fx = add(*(farray_ptr_fx + i), *(farray_ptr_fx + j)); + ftmp1_imag_fx = sub(*(farray_ptr_fx + i + 1), *(farray_ptr_fx + j + 1)); + ftmp2_real_fx = negate(add(*(farray_ptr_fx + j + 1), *(farray_ptr_fx + i + 1))); + ftmp2_imag_fx = negate(sub(*(farray_ptr_fx + j), *(farray_ptr_fx + i))); + + Lftmp1_real_fx = L_deposit_h(ftmp1_real_fx); + Lftmp1_imag_fx = L_deposit_h(ftmp1_imag_fx); + temp_sand = s_and((i*K+384),511); + /* Ltmp1_fx = L_add(L_mult(ftmp2_real_fx, cos_table[i*K]), L_mult(ftmp2_imag_fx, cos_table[(i*K+384)%512])); */ + Ltmp1_fx = L_mac(L_mult(ftmp2_real_fx, cos_table[i*K]), ftmp2_imag_fx, cos_table[ temp_sand]); + *(farray_ptr_fx + i) = round_fx(L_shr(L_add(Lftmp1_real_fx, Ltmp1_fx), 1)); + + /* Ltmp1_fx = L_sub(L_mult(ftmp2_imag_fx, cos_table[i*K]), L_mult(ftmp2_real_fx, cos_table[(i*K+384)%512])); */ + Ltmp1_fx = L_msu(L_mult(ftmp2_imag_fx, cos_table[i*K]), ftmp2_real_fx, cos_table[ temp_sand]); + *(farray_ptr_fx + i + 1) = round_fx(L_shr(L_add(Lftmp1_imag_fx, Ltmp1_fx), 1)); + + /* Ltmp1_fx = L_sub(L_mult(ftmp2_real_fx, cos_table[j*K]), L_mult(ftmp2_imag_fx, cos_table[(j*K+384)%512])); */ + Ltmp1_fx = L_msu(L_mult(ftmp2_real_fx, cos_table[j*K]), ftmp2_imag_fx, cos_table[temp_sand]); + *(farray_ptr_fx + j) = round_fx(L_shr(L_add(Lftmp1_real_fx, Ltmp1_fx), 1)); + + /* Ltmp1_fx = L_negate(L_add(L_mult(ftmp2_imag_fx, cos_table[j*K]), L_mult(ftmp2_real_fx, cos_table[(j*K+384)%512]))); */ + Ltmp1_fx = L_negate(L_mac(L_mult(ftmp2_imag_fx, cos_table[j*K]), ftmp2_real_fx, cos_table[temp_sand])); + Ltmp2_fx = L_sub(Ltmp1_fx, Lftmp1_imag_fx); + *(farray_ptr_fx + j + 1) = round_fx(L_shr(Ltmp2_fx, 1)); + } + + /* Perform the complex IFFT */ + c_fft_wi_fx(farray_ptr_fx, size, stage, isign); + + } + +} + + +/*===================================================================*/ +/* FUNCTION : struct DTFS_fx::copy_phase_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Retain the amplitudes of a prototype X2, but copy*/ +/* the phases of another prototype X1 of same length*/ +/* over to make a new prototype */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_fx) X1 : prototype in Cartesian domain */ +/* (Word16) X1.lag: length of prototype in time domain*/ +/* (Word16 []) X1.a,b: re/im of harmonics, normalized */ +/* (Word16) X1.Q: norm factor of X2.a/b */ +/* _ (struct DTFS_fx) X2 : prototype in polar domain */ +/* (Word16) X2.lag: should be same as X1.lag */ +/* (Word16 []) X2.a:amplitude of harmonics, normalized*/ +/* (Word16 []) X2.b: phase of harmonics, don't care */ +/* (Word16) X2.Q: norm factor of X2.a */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (struct DTFS_fx) X : prototype in Cartesian domain */ +/* The amplitudes of this prototype are from X2 */ +/* and the phases are from X1 */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ +/* X.a[k]=2*X2.a[k]/sqrt(X1.a[k]^2+X1.b[k]^2)*X1.a[k] */ +/* X.b[k]=2*X2.a[k]/sqrt(X1.a[k]^2+X1.b[k]^2)*X1.b[k] */ +/*===================================================================*/ +void copy_phase_fx( DTFS_STRUCTURE_FX *X1_fx, DTFS_STRUCTURE_FX X2_fx, DTFS_STRUCTURE_FX *retX_fx) +{ + /* DTFS_fx X; */ + Word16 k, q, sn, cn, HalfLag; + Word16 d1h, d1l; + Word32 Ltemp_fx,L_tmp; + Word32 Lacc_fx; + Word16 exp,tmp,exp1; + + move16(); + + retX_fx->lag_fx=X1_fx->lag_fx; + retX_fx->Q = sub(X2_fx.Q,1); /* equivalent to 2x MIN_FX(shr(sub(X_fx->lag_fx,1),1),X_fx->nH_fx) */ + HalfLag = s_min(shr(X1_fx->lag_fx,1),X1_fx->nH_fx); + move16(); + FOR ( k=1; k<=HalfLag; k++ ) + { + Lacc_fx=L_mult(X1_fx->a_fx[k],X1_fx->a_fx[k]); + Lacc_fx = L_mac(Lacc_fx,X1_fx->b_fx[k],X1_fx->b_fx[k]); /* 2*Q+1 */ + + exp = norm_l(Lacc_fx); + tmp = extract_h(L_shl(Lacc_fx,exp)); + exp1 = sub(sub(30,exp),2*X1_fx->Q+1); + + IF(tmp) + tmp = div_s(16384,tmp); /* 15+exp1 */ + ELSE + tmp = 0; + tmp = shr(tmp,1); + q = 15+exp1+16-1; + + IF(tmp) + { + exp = norm_s(tmp); + tmp = shl(tmp, exp); + tmp = div_s(16384, tmp); + L_tmp = L_deposit_h(tmp); + Ltemp_fx = Isqrt_lc(L_tmp,&exp); /* Q(31-exp) */ + } + ELSE + Ltemp_fx = 0; + + if (s_and(q, 1)) + Ltemp_fx = Mult_32_16(Ltemp_fx, 23170); /* 23170 is 1/sqrt(2) in Q15 */ + + q = shr(q,1); /* Ltemp_fx in Q(q+16) */ + + d1h=extract_h(Ltemp_fx); + d1l=extract_l(Ltemp_fx); + Ltemp_fx = L_mult0(X1_fx->b_fx[k],d1l); + Ltemp_fx = L_add(L_shr(Ltemp_fx,15),L_mult(X1_fx->b_fx[k],d1h)); /* sin(w) in Q(q+16+Q-15) */ + sn = round_fx(L_shl(Ltemp_fx,sub(30,add(q,X1_fx->Q)))); /* Q15 */ + retX_fx->b_fx[k] = mult_r(X2_fx.a_fx[k],sn); /* X2_fx.Q */ + + Ltemp_fx = L_mult0(X1_fx->a_fx[k],d1l); + Ltemp_fx = L_add(L_shr(Ltemp_fx,15),L_mult(X1_fx->a_fx[k],d1h)); /* cos(w) in Q(q+Q+1) */ + cn = round_fx(L_shl(Ltemp_fx,sub(30,add(q,X1_fx->Q)))); /* Q15 */ + retX_fx->a_fx[k] = mult_r(X2_fx.a_fx[k],cn); /* X2_fx.Q */ + + } + k=sub(k,1); + + + IF (s_and(X1_fx->lag_fx,1)==0) + { + retX_fx->a_fx[k] = shr(retX_fx->a_fx[k],1); + move16(); + retX_fx->b_fx[k] = shr(retX_fx->b_fx[k],1); + move16(); + } +} + + + +/*===================================================================*/ +/* FUNCTION : getSpEngyFromResAmp_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Get band energy */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) X_fx : prototype in polar domain */ +/* (Word16) lag: length of prototype in time domain */ +/* (Word16 []) a: amplitude of harmonics, normalized */ +/* (Word16) Q: norm factor of a */ +/* _ (Word16 []) curr_lpc: LPC coefficients, Q12 */ +/* _ (Word16) lband: lower frequency bound, Q15 */ +/* _ (Word16) hband: upper frequency bound, Q15 */ +/* _ (Word16 []) sin_tab: sine table based on lag, Q15 */ +/* _ (Word16 []) cos_tab: cosine table based on lag, Q15 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word32) en: energy of the specified frequency band, */ +/* Q factor is 2Q-13 */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*===================================================================*/ +Word32 getSpEngyFromResAmp_fx( DTFS_STRUCTURE_FX *X_fx,Word16 lband, Word16 hband, + const Word16 *curr_lpc, Word16 *sin_tab, + Word16 *cos_tab) +{ + Word16 i, k, k4, n, M_fx, HalfLag; + Word16 fdiff, freq; + Word32 Ltemp; + Word32 Lacc; + Word32 Re, Im; /* Q27 */ + Word32 en; + Word16 exp,tmp,expa,fraca,expb,fracb,scale; + Word32 L_tmp; + + en = L_deposit_l(0); + + if (EQ_16(hband,X_fx->upper_cut_off_freq_fx)) + { + hband = 0x2803; + move16(); /* 4001.0/12800 in Q15 */ + } + M_fx=shl(X_fx->lag_fx,2); /* M_fx=4*lag */ + + /* Ltemp=invert_dp(X_fx->lag_fx, 4, &n,1); : Ltemp=1/lag, Q(61-n) */ + /* fdiff=round_fx(L_shl(Ltemp,sub(n,26))); : fdiff=1/lag, Q19 */ + + exp = norm_s(X_fx->lag_fx); + tmp = div_s(shl(1,sub(14,exp)),X_fx->lag_fx); + L_tmp = L_shl(tmp ,add(exp,6)); + fdiff = round_fx(L_tmp); + + HalfLag = s_min(shr(X_fx->lag_fx,1),X_fx->nH_4kHz_fx); + FOR (k=0; k<=HalfLag; k++) + { + Ltemp=L_mult(fdiff,k); /* Ltemp=k*fdiff, Q20 */ + freq=extract_h(L_shl(Ltemp,11)); /* k*fdiff in Q15 */ + + test(); + IF (LT_16(freq,hband)&&GE_16(freq,lband)) + { + Lacc = L_add(0x10000000, 0); /* Re=1.0, Q28 */ + k4=shl(k,2); /* k4=4*k */ + + n=k4; + move16(); + FOR (i=0; ia_fx[k],X_fx->a_fx[k]); /* 2*a[k]^2 in 2Q */ + /* Ltemp=(Word32)L_sat32_40(divide_dp(Ltemp,Lacc,-19,1)); : Ltemp in Q(2Q-13) */ + + if(Lacc<0) + { + Lacc = L_negate(Lacc); + } + + IF(Lacc) + { + + expa = norm_l(Lacc); + fraca = extract_h(L_shl(Lacc,expa)); + expa = sub(30,add(expa,23)); + + + expb = norm_l(Ltemp); + fracb = round_fx(L_shl(Ltemp,expb)); + expb = sub(30,add(expb, shl(X_fx->Q,1))); + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); /* 15-exp */ + exp = sub(expb,expa); + Ltemp = L_shl(tmp, sub(add(shl(X_fx->Q,1),exp), 27)) ; + + } + ELSE + { + Ltemp = L_deposit_l(0); + } + + test(); + IF (X_fx->lag_fx%2==0 && EQ_16(k,shr(X_fx->lag_fx,1))) + en=L_add(en,L_shr(Ltemp,1)); + ELSE + en=L_add(en,Ltemp); /* en in 2Q-13 */ + } + + } + return(en); /* en in 2Q-13 */ +} +/*===================================================================*/ +/* FUNCTION : DTFS_poleFilter_fx() */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : pole filtering */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) lpc[] : lpc coefficients in Q12 */ +/* _ (Word16) N : lpc order */ +/* _ (Word16) X_fx->lag_fx: in Q0 */ +/* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */ +/* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16) X_fx->a_fx[] : in Q(X_fx->Q) */ +/* _ (Word16) X_fx->b_fx[] : in Q(X_fx->Q) */ +/* _ (Word16) X_fx->Q: in Q0 */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ + +void DTFS_poleFilter_fx( DTFS_STRUCTURE_FX *X_fx,Word16 *LPC, Word16 N, Word16 *S_fx, Word16 *C_fx) +{ + Word16 temp, temp1, temp2, HalfLag ; + Word32 sum1_fx, sum2_fx; + Word32 sum, L_temp1, L_temp2; + Word16 k, n, na, nb; + Word16 Qmin, Qab[MAXLAG_WI]; + Word16 exp,tmp; + + Qmin = 32767; + move16(); + HalfLag = s_min(shr(X_fx->lag_fx, 1),X_fx->nH_fx); + FOR ( k=0; k<=HalfLag; k++ ) + { + temp2 = k; + move16(); + /* Calculate sum1 and sum2 */ + sum1_fx = L_deposit_h(4096); /* 1: Q(12+15+1) */ + + sum2_fx = L_deposit_l(0); + FOR ( n=0 ; nlag_fx)]) ; /* Q(12+15+1) */ + sum2_fx = L_mac(sum2_fx, LPC[n], S_fx[(4*temp2)%(4*X_fx->lag_fx)]) ; /* Q(12+15+1) */ + temp2 = add(temp2, k); + } + + temp1 = round_fx(sum1_fx); /* Q(12+15+1-16)=Q(12) */ + temp2 = round_fx(sum2_fx); /* Q(12) */ + + /* Calculate the circular convolution */ + sum = L_mac(L_mult(temp1, temp1), temp2, temp2); /* Q(12+12+1)=Q(25) */ + + L_temp1 = L_mult(temp1, X_fx->a_fx[k]); + L_temp1 = L_mac(L_temp1, temp2, X_fx->b_fx[k]); /* Q(12+Q+1)=Q(13+Q) */ + L_temp2 = L_mult(temp1, X_fx->b_fx[k]); + L_temp2 = L_msu(L_temp2, temp2, X_fx->a_fx[k]); /* Q(12+Q+1)=Q(13+Q) */ + + IF(sum) + { + exp = norm_l(sum); + temp1 = exp; + tmp = extract_h(L_shl(sum,exp)); + exp = sub(sub(30,exp),25); + tmp = div_s(16384,tmp); /* Q(15+exp) */ + sum = L_shl(tmp ,16 ); + temp = round_fx(sum); + } + ELSE + { + sum =0; + move16(); + temp =0; + move16(); + temp1 =0; + move16(); + + } + sum1_fx = Mult_32_16(L_temp1, temp); /* Q(13+Q+20-temp1-15)=Q(Q-temp1+18) */ + sum2_fx = Mult_32_16(L_temp2, temp); /* Q(Q-temp1+18) */ + + /* normalization */ + na = norm_l(sum1_fx); + if (sum1_fx==0) + { + na = 31; + move16(); + } + nb = norm_l(sum2_fx); + if (sum2_fx==0) + { + nb = 31; + move16(); + } + + if (LT_16(na, nb)) + { + nb=na; + move16(); + } + nb=sub(nb,1); /* leave one more sign bit */ + X_fx->a_fx[k] = round_fx(L_shl(sum1_fx, nb)); /* Q(Q-temp1+22+nb-16)=Q(Q-temp1+nb+2) */ + X_fx->b_fx[k] = round_fx(L_shl(sum2_fx, nb)); /* Q(Q-temp1+nb+2) */ + + Qab[k] = add(sub(add(nb, 2), temp1),X_fx->Q); + + if (LT_16(Qab[k], Qmin)) + { + Qmin = Qab[k]; + move16(); + } + } + /* bring to the same Q */ + FOR ( k=0; k<=HalfLag; k++ ) + { + X_fx->a_fx[k] = shl(X_fx->a_fx[k], sub(Qmin, Qab[k])); + move16(); /* Q(Q+Qab[k]+Qmin-Qab[k])=Q(Q+Qmin) */ + X_fx->b_fx[k] = shl(X_fx->b_fx[k], sub(Qmin, Qab[k])); + move16(); /* Q(Q+Qab[k]+Qmin-Qab[k])=Q(Q+Qmin) */ + } + + X_fx->Q = Qmin; +} +/*===================================================================*/ +/* FUNCTION : poleFilter_setup_fx() */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Sets up pole filtering LPC dependent intermediate*/ +/* values to be used by poleFilter */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) lpc[] : lpc coefficients in Q12 */ +/* _ (Word16) N : lpc order */ +/* _ (Word16) lag : in Q0 */ +/* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */ +/* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*===================================================================*/ + +void poleFilter_setup_fx(const Word16 *LPC, Word16 N, DTFS_STRUCTURE_FX X_fx, Word16 *S_fx, Word16 *C_fx, Word16 *pf_temp1, Word16 *pf_temp2, Word16 *pf_temp, Word16 *pf_n2_temp1) +{ + Word16 temp1, temp2, HalfLag ; + Word32 sum1_fx, sum2_fx; + Word32 sum; + Word16 k, n, n1, n2; + Word16 exp,tmp; + + HalfLag = s_min(shr(X_fx.lag_fx, 1),X_fx.nH_fx); + + FOR ( k=0; k<=HalfLag; k++ ) + { + temp2 = k; + move16(); + /* Calculate sum1 and sum2 */ + sum1_fx = L_deposit_h(4096); /* 1: Q(12+15+1) */ + + sum2_fx = L_deposit_l(0); + FOR ( n=0 ; n +#include "basop_util.h" +#include "prot_fx.h" +#include "stl.h" + +#define PI_HALF_0Q15 51472 /* ~=round(pi/2*2^15) */ +#define PI2_15Q16 0x0006487F /* ~=round(2*PI*2^16) */ +#define PI2_10Q21 13176795 /* ~=round(2*PI*2^21) */ +#define PI2_11Q20 6588397 /* ~=round(2*PI*2^20) */ +#define P54_1Q14 8847 /* ~=round(0.54*2^14) */ +#define P54_0Q15 17695 /* ~=round(0.54*2^15) */ +#define P46_0Q15 15073 /* ~=round(0.46*2^15) */ +#define P92_0Q15 30147 /* ~=round(0.92*2^15) */ +#include "options.h" +#include "rom_basop_util.h" + + +void ham_cos_window(Word16 *fh, /* o: 0Q15 */ + const Word16 n1, /* i: */ + const Word16 n2 /* i: */ + ) +{ + Word16 i; + Word32 cte, cc; + + + + assert( n1>=102 ); /* if n1 is too low -> overflow in div_l */ + /* cte = PI2/(Float32)(2*n1 - 1); */ + BASOP_SATURATE_WARNING_OFF + move16(); + cte = L_deposit_l(div_l(PI2_10Q21,sub(shl(n1,1),1))); /*0Q15*/ + BASOP_SATURATE_WARNING_ON + cc = 0; + FOR (i = 0; i < n1; i++) + { + /* fh_f[i] = 0.54f - 0.46f * (Float32)cos(cc); */ + BASOP_SATURATE_WARNING_OFF + fh[i] = sub(P54_0Q15, mult_r(getCosWord16(round_fx(L_shl(cc,9))),P92_0Q15)); /*0Q15*/ move16(); + BASOP_SATURATE_WARNING_ON + cc = L_add(cc, cte); /*0Q15*/ + } + + assert( n2>=26 ); /* if n2 is too low -> overflow in div_l */ + /* cte = PI2/(Float32)(4*n2 - 1); */ + cte = L_deposit_l(div_l(PI2_11Q20,sub(shl(n2,2),1))); /*0Q15*/ + cc = 0; + move16(); + + add(n1,n2); + BASOP_SATURATE_WARNING_OFF + FOR (i = n1; i < n1+n2; i++) + { + /* fh_f[i] = (Float32)cos(cc); */ + fh[i] = shl(getCosWord16(round_fx(L_shl(cc,10))),1); /*0Q15*/ move16(); + cc = L_add(cc, cte); + } + BASOP_SATURATE_WARNING_ON + + + return; +} + diff --git a/lib_com/window_ola_fx.c b/lib_com/window_ola_fx.c new file mode 100644 index 0000000..163ce54 --- /dev/null +++ b/lib_com/window_ola_fx.c @@ -0,0 +1,778 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Function prototypes */ +#include "stl.h" + +void sinq_fx( + const Word16 tmp, /* i : sinus factor cos(tmp*i+phi) Q15*/ + const Word16 phi, /* i : sinus phase cos(tmp*i+phi) Q15*/ + const Word16 N, /* i : size of output */ + Word16 x[] /* o : output vector Q15*/ +) +{ + Word16 i; + Word16 tmp1, tmp2; + Word32 L_tmp, A32,tmp_old,tmp_old_old; + + x[0]= phi; + move16(); /*sin(x) approximated by x; Q15 */ + tmp1 = add(tmp, phi); /*Q15 */ + L_tmp = L_mult(tmp1, tmp1); /*Q31 */ + L_tmp = Mult_32_16(L_tmp, tmp1); /*Q31 */ + L_tmp = Mult_32_16(L_tmp, 5461); /*Q31; division by 6 */ + tmp2 = round_fx(L_tmp); /*Q15 */ + x[1] = sub(tmp1, tmp2); + move16(); /* sin(x) approximated by (x-x^3/3!); Q15 */ + tmp1 = add(shl(tmp,1), phi); /*Q15 */ + L_tmp = L_mult(tmp1, tmp1); /*Q31 */ + L_tmp = Mult_32_16(L_tmp, tmp1); /*Q31 */ + L_tmp = Mult_32_16(L_tmp, 5461); /*Q31; division by 6 */ + tmp2 = round_fx(L_tmp); /*Q15 */ + x[2] = sub(tmp1, tmp2); + move16(); /* sin(x) approximated by (x-x^3/3!); Q15 */ + + + IF ( GT_16(abs_s(tmp),3)) + { + /*A=(x[2]+x[0])/x[1]=2*cos(tmp); here approximated by 2*(1-tmp^2/2!) */ + A32 = L_mult0(tmp,tmp); /*Q30 */ + A32 = L_add(L_sub(1073741824, A32), 1073741824); /*Q30 */ + } + ELSE + { + A32 = L_deposit_l(0); + } + + tmp_old=L_deposit_h(x[2]); /*Q31 */ + tmp_old_old=L_deposit_h(x[1]); /*Q31 */ + + FOR ( i=3; i Q15 */ + *pt2 = shl( mult_r(*pt2,*pt4),1); + move16();/*/= win[(3*L_FRAME16k/2-1-i/2)*decimate+decay-L_FRAME48k*14/20]; */ + pt+=2; + pt2+=2; + pt5-=3; + pt4--; + + } + } + ELSE + { + + pt=synth+tmp; + pt5=on_win+210-1; + temp_len = i_mult2(shr(R2_16,2),delta); + FOR( i=0 ; i< temp_len; i++ ) + { + *pt=shl( mult_r(*pt,*pt5),1); + move16();/* /= win[(3*output_frame/2-1-i)*decimate+decay-L_FRAME48k*14/20]; */ + pt++; + pt5-=decimate; + move16(); + } + } + + + pt=synth+tmp; + move16();/*Q15 */ + pt2=synth_subfr_bwe+tmp-NS2SA(output_Fs, DELAY_CLDFB_NS); + move16(); /*Q15 */ + pt3=tmp_buf_switch+tmp; + move16(); /*Q15 */ + + FOR( i=0; i +#include +#include +#include +#include "options.h" +#include "stl.h" +#include "rom_com_fx.h" +#include "rom_dec_fx.h" +#include "basop_util.h" +#include "stl.h" +#include "cnst_fx.h" +#include "prot_fx.h" + +/** + * \brief Arithmetic decoder + * \param[i/o] st + * \param[o] x + * \param[i] nt + * \param[i] nbbits + * \param[i] resQMaxBits + * \return resQBits + */ +Word16 ACcontextMapping_decode2_no_mem_s17_LC( + Decoder_State_fx *st,/* i/o: decoder state */ + Word16 *x, /* o: decoded spectrum */ + Word16 nt, /* i: size of spectrum */ + Word16 nbbits, /* i: bit budget */ + Word16 resQMaxBits, /* i: residual coding maximum bits*/ + CONTEXT_HM_CONFIG *hm_cfg /* i: context-based harmonic model configuration */ +) +{ + TastatDec as; + Word16 start_bit_pos, lsbs_bit_pos, overflow_bit_pos; + Word16 a, b, t, a1, b1, a1_i, b1_i, k, L; + Word16 lev, pki, esc_nb; + Word16 rateFlag; + Word16 r, lastnz, n; + Word16 resQBits; + Word16 rest_bits, rest_bits_overflow; + Word16 tmp=0; /* initialize just to avoid compiler warning */ + Word16 nt_half; + Word16 c[2], *ctx; + Word16 p1, p2; + Word16 ii[2], idx1, idx2, idx; + Word16 numPeakIndicesOrig, numHoleIndices; + get_next_coeff_function get_next_coeff; + Word16 nbbits_m2; + Word32 La, Lb; + + r = 0; /* to avoid compilation warnings */ move16(); + esc_nb = 0; /* to avoid compilation warnings */ move16(); + + set16_fx(x, 0, nt); + + /* Rate flag */ + rateFlag = 0; + move16(); + if (GT_16(nbbits, 400)) + { + rateFlag = 2 << NBITS_CONTEXT; + move16(); + } + + /*Decode number of ntuples*/ + start_bit_pos = st->next_bit_pos_fx; + move16(); + lsbs_bit_pos = add(start_bit_pos, sub(nbbits, 1)); + + n = 0; + move16(); + + L = sub(14, norm_s(negate(nt))); + n = add(get_next_indice_fx(st, L), 1); + + /* Init */ + nt_half = shr(nt, 1); + c[0] = c[1] = 0; + move16(); + move16(); + + t = 0; + move16(); + + lastnz = shl(n, 1); + + IF (GT_16(lastnz, nt) || st->BER_detect) + { + st->BER_detect = 1; + move16(); + return 0; + } + + IF (hm_cfg) /* mapped domain */ + { + numPeakIndicesOrig = hm_cfg->numPeakIndices; + move16(); + hm_cfg->numPeakIndices = s_min(hm_cfg->numPeakIndices, lastnz); + move16(); + numHoleIndices = sub(lastnz, hm_cfg->numPeakIndices); + + /* Mark hole indices beyond lastnz as pruned */ + FOR (k=numHoleIndices; knumHoleIndices; ++k) + { + hm_cfg->holeIndices[k] = add(hm_cfg->holeIndices[k], nt); + move16(); + } + + ii[0] = numPeakIndicesOrig; + move16(); + ii[1] = 0; + move16(); + + get_next_coeff = get_next_coeff_mapped; + move16(); + } + ELSE /* unmapped domain */ + { + ii[0] = 0; + move16(); + + p1 = p2 = 0; + move16(); + move16(); + + get_next_coeff = get_next_coeff_unmapped; + move16(); + } + + /* Start Decoding */ + ari_start_decoding_14bits(st, &as); + + overflow_bit_pos = st->next_bit_pos_fx; + move16(); + nbbits_m2 = add(nbbits, cbitsnew - 2); + rest_bits_overflow = rest_bits = negate(nbbits_m2); + move16(); + + /*Main Loop through the 2-tuples*/ + FOR (k = 0; k < lastnz; k += 2) + { + /* First coefficient */ + a1_i = get_next_coeff(ii, &p1, &idx1, hm_cfg); + + /* Second coefficient */ + b1_i = get_next_coeff(ii, &p2, &idx2, hm_cfg); + + idx = s_min(idx1, idx2); + + /* Get context */ + ctx = &c[s_or(p1, p2)]; + move16(); + + t = add(*ctx, rateFlag); + if (GT_16(idx, nt_half)) + { + t = add(t, 1 << NBITS_CONTEXT); + } + + test(); + IF (t < 0 || lsbs_bit_pos <= 0) + { + st->BER_detect = 1; + move16(); + return 0; + } + + La = L_deposit_l(0); + Lb = L_deposit_l(0); + /* MSBs decoding */ + test(); + FOR (lev = 0; lev < 15 && lsbs_bit_pos > 0; lev++) + { + test(); + esc_nb = s_min(lev, 3); + tmp = add(t, Tab_esc_nb[esc_nb]); + assert(tmp >= 0 && tmp < 4096); + pki = ari_lookup_s17_LC[tmp]; + move16(); + r = ari_decode_14bits_s17_ext(st, &as, ari_pk_s17_LC_ext[pki]); + + IF (LT_16(r, VAL_ESC)) + { + BREAK; + } + + /*LSBs decoding*/ + La = L_mac0(La, pow2tab[lev], get_indice_1_fx(st, lsbs_bit_pos--)); + Lb = L_mac0(Lb, pow2tab[lev], get_indice_1_fx(st, lsbs_bit_pos--)); + } + + test(); + test(); + IF ( ((LT_16(lsbs_bit_pos, -1)&&GE_16(r,VAL_ESC)))||(GT_16(lev,14))) + { + x[a1_i] = 0; + move16(); + x[b1_i] = 0; + move16(); + st->BER_detect = 1; + move16(); + return 0; + } + + /*MSBs contributions*/ + b1 = shr(r, 2); + a1 = s_and(r, 0x3); + a = extract_l(L_mac0(La, pow2tab[lev], a1)); + b = extract_l(L_mac0(Lb, pow2tab[lev], b1)); + + /*lsbs bits sign bits*/ + rest_bits = add(rest_bits, shl(lev, 1)); + + if (a > 0) + { + rest_bits = add(rest_bits, 1); + } + if (b > 0) + { + rest_bits = add(rest_bits, 1); + } + + /*Dectect overflow*/ + IF (add(sub(st->next_bit_pos_fx, start_bit_pos), rest_bits) > 0) + { + /* Roll back bit-stream position to overflow_bit_pos */ + get_next_indice_tmp_fx(st, sub(overflow_bit_pos, st->next_bit_pos_fx)); + rest_bits = rest_bits_overflow; + move16(); + x[a1_i] = 0; + move16(); + x[b1_i] = 0; + move16(); + BREAK; + } + + overflow_bit_pos = st->next_bit_pos_fx; + move16(); + rest_bits_overflow = rest_bits; + move16(); + + /* Store decoded data */ + x[a1_i] = a; + move16(); + x[b1_i] = b; + move16(); + + /* Update context for next 2-tuple */ + IF (EQ_16(p1, p2)) /* peak-peak or hole-hole context */ + { + lev = sub(esc_nb, 1); + if (lev > 0) t = add(12, lev); + if (lev <= 0) t = add(a1, b1); + if (lev == 0) t = add(t, t); + + *ctx = add(shl(s_and(*ctx, 0xf), 4), add(t, 1)); + move16(); + } + ELSE /* mixed context */ + { + IF (s_and(idx1, 1)) /* update first context */ + { + c[p1] = update_mixed_context(c[p1], a); + move16(); + } + + IF (s_and(idx2, 1)) /* update second context */ + { + c[p2] = update_mixed_context(c[p2], b); + move16(); + } + } + } + + /* Total number of decoded AC bits */ + get_next_indice_tmp_fx(st, -(cbitsnew - 2)); + + /*detect overflow*/ + IF (NE_16(k, lastnz)) + { + rest_bits = add(rest_bits, nbbits_m2); + /* Set bit-stream position to (start_bit_pos+nbbits-rest_bits) */ + get_next_indice_tmp_fx(st, sub((sub(add(start_bit_pos, nbbits), rest_bits)), st->next_bit_pos_fx)); + } + + /*Decode signs*/ + if (hm_cfg) + { + tmp = nt; + move16(); + } + if (!hm_cfg) + { + tmp = lastnz; + move16(); + } + FOR (k = 0; k < tmp; k++) + { + IF (x[k] > 0) + { + if (get_next_indice_1_fx(st) != 0) + { + x[k] = negate(x[k]); + move16(); + } + } + } + + /*Decode Residual Q*/ + resQBits = s_min(resQMaxBits, sub(add(lsbs_bit_pos,1), st->next_bit_pos_fx)); + FOR (k=0; knext_bit_pos_fx)); + + + return resQBits; +} + diff --git a/lib_dec/EvsRXlib.c b/lib_dec/EvsRXlib.c new file mode 100644 index 0000000..4de16cc --- /dev/null +++ b/lib_dec/EvsRXlib.c @@ -0,0 +1,569 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "options.h" +#include "prot_fx.h" +#include "EvsRXlib.h" +#include "jbm_jb4sb.h" +#include "jbm_pcmdsp_apa.h" +#include "jbm_pcmdsp_fifo.h" + +#include "stl.h" +#include "basop_util.h" +#include "basop_util_jbm.h" + + + +struct EVS_RX +{ + Decoder_State_fx *st; + JB4_HANDLE hJBM; + Word16 lastDecodedWasActive; + Word16 samplesPerMs; /* sampleRate / 1000 */ + PCMDSP_APA_HANDLE hTimeScaler; + PCMDSP_FIFO_HANDLE hFifoAfterTimeScaler; +#ifdef SUPPORT_JBM_TRACEFILE + FILE *jbmTraceFile; +#endif +}; + +/* function to check if a frame contains a SID */ +static Word16 isSidFrame( Word16 size ); + + +/* Opens the EVS Receiver instance. */ +EVS_RX_ERROR EVS_RX_Open(EVS_RX_HANDLE* phEvsRX, + Decoder_State_fx *st, + Word16 jbmSafetyMargin) +{ + EVS_RX_HANDLE hEvsRX; + Word16 divScaleFac, wss, css; + + *phEvsRX = NULL; + move16(); + + /* Create EVS Receiver handle */ + *phEvsRX = (EVS_RX_HANDLE) calloc(1, sizeof(struct EVS_RX) ); + move16(); + IF( *phEvsRX == NULL ) + { + return EVS_RX_MEMORY_ERROR; + } + hEvsRX = *phEvsRX; + move16(); + + hEvsRX->st = st; + move16(); + /* do not use codec for time stretching (PLC) before initialization with first received frame */ + st->codec_mode = 0; + move16(); + + /* open JBM */ + hEvsRX->hJBM = 0; + move16(); + IF( JB4_Create(&(hEvsRX->hJBM)) != 0) + { + EVS_RX_Close(phEvsRX); + return EVS_RX_INIT_ERROR; + } + + /* init JBM */ + IF(JB4_Init(hEvsRX->hJBM, jbmSafetyMargin) != 0) + { + EVS_RX_Close(phEvsRX); + return EVS_RX_INIT_ERROR; + } + + + hEvsRX->lastDecodedWasActive = 0; + move16(); + hEvsRX->samplesPerMs = BASOP_Util_Divide3216_Scale(st->output_Fs_fx, 1000, &divScaleFac); + hEvsRX->samplesPerMs = shl(hEvsRX->samplesPerMs, add(divScaleFac, 1)); + assert(hEvsRX->samplesPerMs == st->output_Fs_fx / 1000); + + IF(EQ_32(st->output_Fs_fx, 8000)) + { + wss = 1; + move16(); + css = 1; + move16(); + } + ELSE IF(EQ_32(st->output_Fs_fx, 16000)) + { + wss = 2; + move16(); + css = 1; + move16(); + } + ELSE IF(EQ_32(st->output_Fs_fx, 32000)) + { + wss = 4; + move16(); + css = 2; + move16(); + } + ELSE IF(EQ_32(st->output_Fs_fx, 48000)) + { + wss = 6; + move16(); + css = 3; + move16(); + } + ELSE + { + assert(0 || "unknown sample rate!"); + wss = css = 1; /* just to avoid compiler warning */ + } + + /* initialize time scaler and FIFO after time scaler */ test(); + test(); + test(); + test(); + test(); + IF( apa_init( &hEvsRX->hTimeScaler ) != 0 || + apa_set_rate( hEvsRX->hTimeScaler, st->output_Fs_fx, 1 ) != 0 || + apa_set_complexity_options( hEvsRX->hTimeScaler, wss, css ) != 0 || + apa_set_quality( hEvsRX->hTimeScaler, L_deposit_h(1), 4, 4 ) != 0 || + pcmdsp_fifo_create( &hEvsRX->hFifoAfterTimeScaler ) != 0 || + pcmdsp_fifo_init( hEvsRX->hFifoAfterTimeScaler, i_mult2(4, st->output_frame_fx) /* 4 frames */, 1, 2 /* Word16 */ ) != 0 ) + { + EVS_RX_Close(phEvsRX); + return EVS_RX_TIMESCALER_ERROR; + } + + return EVS_RX_NO_ERROR; +} + +#ifdef SUPPORT_JBM_TRACEFILE +/* Sets the name of the JBM trace file which will be created. */ +EVS_RX_ERROR +EVS_RX_SetJbmTraceFileName(EVS_RX_HANDLE hEvsRX, + const char *jbmTraceFileName) +{ + /* JBM trace file writing is only done for EVS testing and is not instrumented. */ + if( hEvsRX->jbmTraceFile ) + fclose( hEvsRX->jbmTraceFile ); + if( jbmTraceFileName != NULL ) + { + hEvsRX->jbmTraceFile = fopen( jbmTraceFileName, "w" ); + if( !hEvsRX->jbmTraceFile ) + { + return EVS_RX_WRONG_PARAMS; + } + fprintf( hEvsRX->jbmTraceFile, "#rtpSeqNo;rtpTs;rcvTime;playTime;active\n" ); + } + return EVS_RX_NO_ERROR; +} +#endif + +/* Feeds one frame into the receiver. */ +EVS_RX_ERROR +EVS_RX_FeedFrame(EVS_RX_HANDLE hEvsRX, + UWord8 *au, + Word16 auSize, + Word16 rtpSequenceNumber, + Word32 rtpTimeStamp, + Word32 rcvTime_ms + , Word16 isAMRWB_IOmode, + Word16 frameTypeIndex, + Word16 qBit +) +{ + JB4_DATAUNIT_HANDLE dataUnit; + Word16 partialCopyFrameType, partialCopyOffset; + Word16 result; + + if (auSize == 0) { + return EVS_RX_NO_ERROR; /* ignore empty/NO_DATA frame - shouldn't be transmitted in RTP */ + } + if ((auSize + 7) / 8 > MAX_AU_SIZE) { + return EVS_RX_RECEIVER_ERROR; + } + + /* check if frame contains a partial copy and get its offset */ + evs_dec_previewFrame(au, auSize, &partialCopyFrameType, &partialCopyOffset); + + /* create data unit for primary copy in the frame */ + dataUnit = JB4_AllocDataUnit(hEvsRX->hJBM); + copyWord8((Word8*)au, (Word8*)dataUnit->data, shr(add(auSize, 7), 3) ); + dataUnit->dataSize = auSize; + move16(); + dataUnit->duration = 20; + move32(); + dataUnit->sequenceNumber = rtpSequenceNumber; + move16(); + dataUnit->silenceIndicator = isSidFrame( dataUnit->dataSize ); + dataUnit->timeScale = 1000; + move32(); + dataUnit->rcvTime = rcvTime_ms; + move32(); + dataUnit->timeStamp = rtpTimeStamp; + move32(); + dataUnit->partial_frame = 0; + move16(); + dataUnit->partialCopyOffset = partialCopyOffset; + move16(); + dataUnit->isAMRWB_IOmode = isAMRWB_IOmode; + dataUnit->frameTypeIndex = frameTypeIndex; + dataUnit->qBit = qBit; + /* add the frame to the JBM */ + result = JB4_PushDataUnit(hEvsRX->hJBM, dataUnit, rcvTime_ms); + IF(result != 0) + { + return EVS_RX_JBM_ERROR; + } + test(); + IF(NE_16(partialCopyFrameType, RF_NO_DATA)&&partialCopyOffset!=0) + { + /* create data unit for partial copy in the frame */ + dataUnit = JB4_AllocDataUnit(hEvsRX->hJBM); + copyWord8((Word8*)au, (Word8*)dataUnit->data, shr(add(auSize, 7), 3) ); + dataUnit->dataSize = auSize; + move16(); + dataUnit->duration = 20; + move32(); + dataUnit->sequenceNumber = rtpSequenceNumber; + move16(); + dataUnit->silenceIndicator = 0; /* there are no partial copies for SID frames */ move16(); + dataUnit->timeScale = 1000; + move32(); + dataUnit->rcvTime = rcvTime_ms; + move32(); + dataUnit->timeStamp = rtpTs_sub(rtpTimeStamp, L_mult0(partialCopyOffset, 20)); + assert(dataUnit->timeStamp == rtpTimeStamp - partialCopyOffset * dataUnit->duration); + dataUnit->partial_frame = 1; + move16(); + dataUnit->partialCopyOffset = partialCopyOffset; + move16(); + dataUnit->isAMRWB_IOmode = isAMRWB_IOmode; + dataUnit->frameTypeIndex = frameTypeIndex; + dataUnit->qBit = qBit; + /* add the frame to the JBM */ + result = JB4_PushDataUnit(hEvsRX->hJBM, dataUnit, rcvTime_ms); + IF(result != 0) + { + return EVS_RX_JBM_ERROR; + } + } + return EVS_RX_NO_ERROR; +} + +/* Retrieves one frame of output PCM data. */ +EVS_RX_ERROR +EVS_RX_GetSamples(EVS_RX_HANDLE hEvsRX, + Word16 *nOutSamples, + Word16 *pcmBuf, + Word16 pcmBufSize, + Word32 systemTimestamp_ms) +{ + Decoder_State_fx *st; + Word16 soundCardFrameSize, extBufferedSamples; + Word32 extBufferedTime_ms; + Word16 scale, maxScaling, nTimeScalerOutSamples; + Word16 timeScalingDone, result; + JB4_DATAUNIT_HANDLE dataUnit; + Word16 tmp; + + assert(hEvsRX->st->output_frame_fx <= pcmBufSize); + assert(hEvsRX->st->output_frame_fx <= APA_BUF); + + st = hEvsRX->st; + move16(); + soundCardFrameSize = st->output_frame_fx; + move16(); + timeScalingDone = 0; + move16(); + + /* make sure that the FIFO after decoder/scaler contains at least one sound card frame (i.e. 20ms) */ + WHILE(LT_16(pcmdsp_fifo_nReadableSamples(hEvsRX->hFifoAfterTimeScaler), soundCardFrameSize)) + { + extBufferedSamples = pcmdsp_fifo_nReadableSamples( hEvsRX->hFifoAfterTimeScaler ); + extBufferedTime_ms = L_deposit_l(idiv1616U(extBufferedSamples, hEvsRX->samplesPerMs)); + dataUnit = NULL; + move16(); + /* pop one access unit from the jitter buffer */ + result = JB4_PopDataUnit(hEvsRX->hJBM, systemTimestamp_ms, extBufferedTime_ms, &dataUnit, &scale, &maxScaling); + IF(result != 0) + { + return EVS_RX_JBM_ERROR; + } + if(GT_16(maxScaling, 20)) + { + maxScaling = 20; + move16(); + } + maxScaling = i_mult2(maxScaling, hEvsRX->samplesPerMs); + assert(maxScaling >= 0); + /* avoid time scaling multiple times in one sound card slot */ + IF(NE_16(scale, 100)) + { + if( timeScalingDone != 0 ) + { + scale = 100; + move16(); + } + timeScalingDone = 1; + move16(); + } + + /* copy bitstream into decoder state */ + IF(dataUnit) + { + IF( NE_16(st->codec_mode,0)) + { + tmp = 0; + if (EQ_16(dataUnit->partial_frame,1)) + { + tmp = 1; + } + read_indices_from_djb_fx( st, dataUnit->data, dataUnit->dataSize, + dataUnit->isAMRWB_IOmode, dataUnit->frameTypeIndex, dataUnit->qBit, + tmp, dataUnit->nextCoderType ); + + IF(dataUnit->partial_frame != 0) + { + st->codec_mode = MODE2; + st->use_partial_copy = 1; + } + } + ELSE /* initialize decoder with first received frame */ + { + /* initialize, since this is needed within read_indices_from_djb_fx, to correctly set st->last_codec_mode */ + st->ini_frame_fx = 0; + st->prev_use_partial_copy = 0; + init_decoder_fx( st ); + + /* parse frame again because init_decoder() overwrites st->total_brate_fx */ + read_indices_from_djb_fx( st, dataUnit->data, dataUnit->dataSize, + dataUnit->isAMRWB_IOmode, dataUnit->frameTypeIndex, dataUnit->qBit, + 0, 0 ); + } + + } + ELSE IF( st->codec_mode != 0 ) + { + read_indices_from_djb_fx( st, NULL, 0, + 0, 0, 0, + 0, 0 ); + } + + /* run the main decoding routine */ + SUB_WMOPS_INIT("evs_dec"); + IF( EQ_16(st->codec_mode, MODE1)) + { + IF( st->Opt_AMR_WB_fx ) + { + amr_wb_dec_fx( pcmBuf, st ); + } + ELSE + { + evs_dec_fx( st, pcmBuf, FRAMEMODE_NORMAL ); + } + } + ELSE IF( EQ_16(st->codec_mode, MODE2)) + { + IF(st->bfi_fx == 0) + { + evs_dec_fx(st, pcmBuf, FRAMEMODE_NORMAL); + } + ELSE IF ( EQ_16(st->bfi_fx,2)) + { + evs_dec_fx(st, pcmBuf, FRAMEMODE_FUTURE); /* FRAMEMODE_FUTURE */ + } + ELSE /* conceal */ + { + evs_dec_fx(st, pcmBuf, FRAMEMODE_MISSING); + } + } + END_SUB_WMOPS; + test(); + IF( EQ_16(st->codec_mode, MODE1)||EQ_16(st->codec_mode,MODE2)) + { + /* increase the counter of initialization frames */ + if( LT_16(st->ini_frame_fx, MAX_FRAME_COUNTER)) + { + st->ini_frame_fx = add(st->ini_frame_fx, 1); + } + } + ELSE /* codec mode to use not known yet */ + { + set16_fx( pcmBuf, 0, st->output_frame_fx ); + } + + IF(dataUnit != NULL) + { + IF(dataUnit->partial_frame != 0) + { + hEvsRX->lastDecodedWasActive = 1; + move16(); + } + ELSE + { + hEvsRX->lastDecodedWasActive = s_xor(dataUnit->silenceIndicator, 1); + } + /* data unit memory is no longer used */ + JB4_FreeDataUnit(hEvsRX->hJBM, dataUnit); + } + + /* limit scale to range supported by time scaler */ + if(LT_16(scale, APA_MIN_SCALE)) + scale = APA_MIN_SCALE; + move16(); + if(GT_16(scale, APA_MAX_SCALE)) + scale = APA_MAX_SCALE; + move16(); + /* apply time scaling on decoded/concealed samples */ + IF( apa_set_scale( hEvsRX->hTimeScaler, scale ) != 0 ) + { + return EVS_RX_TIMESCALER_ERROR; + } + result = apa_exec( hEvsRX->hTimeScaler, pcmBuf, st->output_frame_fx, + maxScaling, pcmBuf, &nTimeScalerOutSamples ); + IF( result != 0 ) + { + return EVS_RX_TIMESCALER_ERROR; + } + assert(nTimeScalerOutSamples <= pcmBufSize); + assert(nTimeScalerOutSamples <= APA_BUF); + (void)pcmBufSize; + /* append scaled samples to FIFO */ + IF( pcmdsp_fifo_write( hEvsRX->hFifoAfterTimeScaler, + (UWord8*)pcmBuf, nTimeScalerOutSamples ) != 0 ) + { + return EVS_RX_TIMESCALER_ERROR; + } +#ifdef SUPPORT_JBM_TRACEFILE + /* write JBM trace file entry */ + /* JBM trace file writing is only done for EVS testing and is not instrumented. */ + if( hEvsRX->jbmTraceFile ) + { + /* the first sample of the decoded/concealed frame will be played after the samples in the ring buffer */ + double playTime = systemTimestamp_ms + extBufferedSamples * 1000.0 / st->output_Fs_fx; + /* rtpSeqNo;rtpTs;rcvTime;playTime;active\n */ + if( dataUnit ) + { + if(dataUnit->partial_frame == 1) + { + fprintf( hEvsRX->jbmTraceFile, "%d;%d;%d;%f;%d;%d\n", + -1, -1, -1, playTime, (int)hEvsRX->lastDecodedWasActive, dataUnit->partialCopyOffset ); + } + else + { + fprintf( hEvsRX->jbmTraceFile, "%u;%u;%u;%f;%d\n", + dataUnit->sequenceNumber, dataUnit->timeStamp, dataUnit->rcvTime, + playTime, (int)hEvsRX->lastDecodedWasActive ); + } + + } + else + { + fprintf( hEvsRX->jbmTraceFile, "%d;%d;%d;%f;%d\n", + -1, -1, -1, + playTime, (int)hEvsRX->lastDecodedWasActive ); + } + } +#endif + } + + /* fetch one frame for the sound card from FIFO */ + *nOutSamples = soundCardFrameSize; + move16(); + IF( pcmdsp_fifo_read( hEvsRX->hFifoAfterTimeScaler, *nOutSamples, (UWord8*)pcmBuf ) != 0 ) + { + return EVS_RX_TIMESCALER_ERROR; + } + return EVS_RX_NO_ERROR; +} + +Word16 +EVS_RX_Get_FEC_offset( EVS_RX_HANDLE hEvsRX, Word16 *offset, Word16 *FEC_hi) +{ + *offset = (Word16)JB4_getFECoffset(hEvsRX->hJBM); + move16(); + *FEC_hi = (Word16)JB4_FECoffset(hEvsRX->hJBM); + move16(); + + return 0; +} + + +/* Returns 1 if the jitter buffer is empty, otherwise 0. */ +Word8 +EVS_RX_IsEmpty(EVS_RX_HANDLE hEvsRX ) +{ + Word8 isEmpty; + + isEmpty = 0; + move16(); + if(JB4_bufferedDataUnits(hEvsRX->hJBM) == 0 ) + { + isEmpty = 1; + move16(); + } + return isEmpty; +} + +/* Closes the receiver instance. */ +EVS_RX_ERROR +EVS_RX_Close(EVS_RX_HANDLE* phRX ) +{ + /* Free all memory */ + test(); + IF( phRX == NULL || *phRX == NULL ) + { + return EVS_RX_NO_ERROR; + } + + destroy_decoder( (*phRX)->st ); + + IF( (*phRX)->hJBM ) + { + JB4_Destroy( &(*phRX)->hJBM ); + } + + + IF( (*phRX)->hTimeScaler ) + { + apa_exit( &(*phRX)->hTimeScaler ); + } + + IF( (*phRX)->hFifoAfterTimeScaler ) + { + pcmdsp_fifo_destroy( &(*phRX)->hFifoAfterTimeScaler ); + } + +#ifdef SUPPORT_JBM_TRACEFILE + if( (*phRX)->jbmTraceFile ) + fclose( (*phRX)->jbmTraceFile ); +#endif + + free( *phRX ); + *phRX = NULL; + move16(); + phRX = NULL; + move16(); + return EVS_RX_NO_ERROR; +} + +/* function to check if a frame contains a SID */ +static Word16 isSidFrame( Word16 size ) +{ + Word16 ret; + + ret = 0; + move16(); + if(EQ_16(size, SID_1k75 / 50)) + { + ret = 1; /* AMR-WB SID */ move16(); + } + if(EQ_16(size, SID_2k40 / 50)) + { + ret = 1; /* EVS SID */ move16(); + } + return ret; +} + diff --git a/lib_dec/EvsRXlib.h b/lib_dec/EvsRXlib.h new file mode 100644 index 0000000..a26f538 --- /dev/null +++ b/lib_dec/EvsRXlib.h @@ -0,0 +1,85 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#ifndef EvsRXLIB_H +#define EvsRXLIB_H + +/* local headers */ +#include "stat_dec_fx.h" + +/* + * ENUMS + */ + +/* Receiver error enums */ +typedef enum _EVS_RX_ERROR +{ + EVS_RX_NO_ERROR = 0x0000, + EVS_RX_MEMORY_ERROR = 0x0001, + EVS_RX_WRONG_PARAMS = 0x0002, + EVS_RX_INIT_ERROR = 0x0003, + EVS_RX_RECEIVER_ERROR = 0x0004, + EVS_RX_DECODER_ERROR = 0x0005, + EVS_RX_JBM_ERROR = 0x0006, + EVS_RX_TIMESCALER_ERROR = 0x0007, + EVS_RX_NOT_IMPLEMENTED = 0x0010 + +} EVS_RX_ERROR; + + +/* + * Structures + */ + +typedef struct EVS_RX* EVS_RX_HANDLE; + +/* + * Functions + */ + +/*! Opens the EVS Receiver instance. */ +EVS_RX_ERROR +EVS_RX_Open(EVS_RX_HANDLE* phEvsRX, + Decoder_State_fx *st, + Word16 jbmSafetyMargin); + +/*! Sets the name of the JBM trace file which will be created. */ +EVS_RX_ERROR +EVS_RX_SetJbmTraceFileName(EVS_RX_HANDLE hEvsRX, + const char *jbmTraceFileName); + +/*! Feeds one frame into the receiver. */ +EVS_RX_ERROR +EVS_RX_FeedFrame(EVS_RX_HANDLE hEvsRX, + UWord8 *au, + Word16 auSize, + Word16 rtpSequenceNumber, + Word32 rtpTimeStamp, + Word32 rcvTime_ms + , Word16 isAMRWB_IOmode, + Word16 frameTypeIndex, + Word16 qBit + ); + +/*! Retrieves one frame of output PCM data. */ +EVS_RX_ERROR +EVS_RX_GetSamples(EVS_RX_HANDLE hEvsRX, + Word16 *nOutSamples, + Word16 *pcmBuf, + Word16 pcmBufSize, + Word32 systemTimestamp_ms) ; + +Word16 +EVS_RX_Get_FEC_offset( EVS_RX_HANDLE hEvsRX, Word16 *offset, Word16 *FEC_hi); + +/*! Returns 1 if the jitter buffer is empty, otherwise 0. */ +/* Intended for flushing at the end of the main loop but not during normal operation! */ +Word8 +EVS_RX_IsEmpty(EVS_RX_HANDLE hEvsRX ); + +/*! Closes the receiver instance. */ +EVS_RX_ERROR +EVS_RX_Close(EVS_RX_HANDLE* phEvsRX ); + +#endif diff --git a/lib_dec/FEC_HQ_core_fx.c b/lib_dec/FEC_HQ_core_fx.c new file mode 100644 index 0000000..0645cc7 --- /dev/null +++ b/lib_dec/FEC_HQ_core_fx.c @@ -0,0 +1,1590 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +#include "prot_fx.h" +#include "rom_com_fx.h" + + + + +/*--------------------------------------------------------------------------* + * Regression_Anal() + * + * + *--------------------------------------------------------------------------*/ +static void Regression_Anal_fx( + const Word32 *values_fx, /* i : Previous values */ + Word32 *r_p_fx, /* o : Output r[a b] array : y=ax+b */ + const Word16 num_pgf /* i : Number of previous good frame */ +) +{ + Word16 i; + Word16 tmp; + Word32 L_tmp1, L_tmp2; + Word16 aindex_fx[MAX_PGF+1]; + Word32 b_p_fx[MAX_PGF+1]; + + /* Initialize */ + FOR (i=0; ienergy_MA_Curr_fx[1], st_fx->energy_MA_Curr_fx[0])); + exp1 = sub(norm_s(tmp_fx), 1); + st_fx->energy_MA_Curr_fx[0] = s_max(st_fx->energy_MA_Curr_fx[0],1); + move16(); + exp2 = norm_s(st_fx->energy_MA_Curr_fx[0]); + tmp_fx = div_s(shl(tmp_fx, exp1), shl(st_fx->energy_MA_Curr_fx[0], exp2));/*15 + exp1 - exp2*/ + energy_diff_fx = shl(tmp_fx, sub(sub(exp2, exp1), 5));/*10*/ + test(); + IF ((LT_16(energy_diff_fx, 1024))&&(is_transient==0)) /* First erasure frame */ + { + mute_start = 5; + move16(); + } + ELSE + { + mute_start = 2; + move16(); + } + test(); + test(); + if( EQ_16(st_fx->prev_old_bfi_fx, 1)&&EQ_16(st_fx->nbLostCmpt,1)&&EQ_16(output_frame,L_FRAME8k)) + { + st_fx->nbLostCmpt = add(st_fx->nbLostCmpt, 1); + } + + /* Frequency-domain FEC */ + IF ( EQ_16(st_fx->nbLostCmpt, 1)) /* First erasure frame */ + { + IF ( is_transient == 0 ) + { + IF (LT_16(energy_diff_fx, 1024)) + { + FOR (i=0; i < output_frame; i++) + { + t_audio_q_fx[i] = st_fx->old_coeffs_fx[i]; + move32(); + } + } + ELSE + { + FOR (i=0; i < output_frame; i++) + { + st_fx->old_coeffs_fx[i] = Mult_32_16(st_fx->old_coeffs_fx[i], 23170);/*23170, 3dB, Q15*/ + t_audio_q_fx[i] = st_fx->old_coeffs_fx[i]; + move32(); + } + } + + /* Sign prediction in 4-dim bands up to 1.6 kHz*/ + IF (st_fx->old_is_transient_fx[1] == 0) + { + IF (st_fx->old_is_transient_fx[2] == 0) + { + FOR (sfm = 0; sfm < HQ_FEC_SIGN_SFM; sfm++) + { + IF (GE_16(st_fx->prev_sign_switch_fx[sfm], HQ_FEC_SIGN_THRES)) + { + FOR (i = 0; i < HQ_FEC_BAND_SIZE; i++) + { + t_audio_q_fx[i+sfm*HQ_FEC_BAND_SIZE] = L_negate(t_audio_q_fx[i+sfm*HQ_FEC_BAND_SIZE]); + move32(); + } + } + } + } + ELSE + { + FOR (sfm = 0; sfm < HQ_FEC_SIGN_SFM; sfm++) + { + IF (GE_16(st_fx->prev_sign_switch_fx[sfm], HQ_FEC_SIGN_THRES_TRANS)) + { + FOR (i = 0; i < HQ_FEC_BAND_SIZE; i++) + { + t_audio_q_fx[i+sfm*HQ_FEC_BAND_SIZE] = L_negate(t_audio_q_fx[i+sfm*HQ_FEC_BAND_SIZE]); + move32(); + } + } + } + } + } + ELSE + { + FOR (i = RANDOM_START*8; i < output_frame; i++) + { + IF(Random(&st_fx->HQ_FEC_seed_fx) < 0) + { + t_audio_q_fx[i] = L_negate(t_audio_q_fx[i]); + move32(); + } + } + } + } + ELSE + { + IF( st_fx->old_is_transient_fx[1] ) /* hangover */ + { + FOR (i=0; i < output_frame; i++) + { + st_fx->old_coeffs_fx[i] = Mult_32_16(st_fx->old_coeffs_fx[i], 23170); + t_audio_q_fx[i] = st_fx->old_coeffs_fx[i]; + move32(); + } + } + ELSE + { + FOR (i = 0; i < RANDOM_START*8; i++) + { + st_fx->old_coeffs_fx[i] = Mult_32_16(st_fx->old_coeffs_fx[i], 23170); + t_audio_q_fx[i] = st_fx->old_coeffs_fx[i]; + move32(); + } + + FOR (i = RANDOM_START*8; i < output_frame; i++) + { + st_fx->old_coeffs_fx[i] = Mult_32_16(st_fx->old_coeffs_fx[i], 23170); + IF (Random(&st_fx->HQ_FEC_seed_fx) < 0) + { + t_audio_q_fx[i] = L_negate(st_fx->old_coeffs_fx[i]); + move32(); + } + ELSE + { + t_audio_q_fx[i] = st_fx->old_coeffs_fx[i]; + move32(); + } + } + } + } + } + ELSE /* st_fx->nbLostCmpt > 1 */ + { + test(); + IF( LT_16(energy_diff_fx, 1024)&&is_transient==0) + { + num_pgf = 4; + move16(); + } + ELSE + { + num_pgf = 2; + move16(); + } + + Num_sb_bwe = num_Sb; + move16(); + IF ( EQ_16(st_fx->nbLostCmpt, 2)) + { + + FOR ( i=0; inbLostCmpt, mute_start)) + { + /* Scaling */ + FOR ( i=0; i < output_frame; i++ ) + { + st_fx->old_coeffs_fx[i] = Mult_32_16(st_fx->old_coeffs_fx[i], 23170); + move32(); + } + } + + k = 0; + move16(); + FOR ( i=0; i 0 ) + { + r_p_fx[1] = L_deposit_l(0); + norm_p_fx[i] = L_shr(norm_values_fx[0], 7);/*5*/ move32(); + } + ELSE + { + norm_p_fx[i] = L_add(r_p_fx[0], L_mult0(extract_l(r_p_fx[1]), sub(add(st_fx->nbLostCmpt, num_pgf), 1))); + } + + test(); + IF ( norm_values_fx[0] != 0 && norm_p_fx[i] > 0 ) /* Avoid negative value of the predicted energy */ + { + exp1 = sub(norm_l(norm_p_fx[i]), 1); + exp2 = norm_l(norm_values_fx[0]); + tmp_fx = div_s(extract_h(L_shl(norm_p_fx[i], exp1)), + extract_h(L_shl(norm_values_fx[0], exp2)));/*15 + (5 + exp1 - 16) - (12 + exp2 - 16)*/ + tmp_fx = shl(tmp_fx, add(6, sub(exp2, exp1)));/*14*/ + + if (GT_16(tmp_fx, 16384)) + { + tmp_fx = 16384; + move16(); + } + + FOR ( j=0; jNorm_gain_fx[k++] = shl(tmp_fx, 1); + move16(); + } + } + ELSE + { + /* Scale down the last gain with the fixed gain(-3dB) */ + FOR (j=0; jNorm_gain_fx[k] = mult_r(st_fx->Norm_gain_fx[k], 23170); + move16(); + k++; + } + } + } + + /* Scaling for core band */ + FEC_scaling_fx( st_fx->old_coeffs_fx, t_audio_q_fx, st_fx->Norm_gain_fx, &st_fx->HQ_FEC_seed_fx, nb_sfm, sfm_start, sfm_end ); + + } + + + return; +} + +void HQ_FEC_Mem_update_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word32 *t_audio_q_fx, /*Q12*/ + Word32 *normq_fx, /*Q14*/ + Word16 *ynrm, + Word16 *Num_bands_p, + Word16 is_transient, + Word16 hqswb_clas, + Word16 c_switching_flag, + Word16 nb_sfm, + Word16 num_Sb, + Word16 *mean_en_high_fx, /*Q5*/ + Word16 hq_core_type, /* i : normal or low-rate MDCT(HQ) core */ + Word16 output_frame +) +{ + Word16 Min_ind; + Word32 Min_value; + Word16 Max_ind; + Word16 stat_mode_curr; + + Word16 i, j, k; + Word16 offset; + Word16 exp, exp1, exp2, tmp_fx; + Word32* norm_values_fx; + Word32 L_tmp, tmp_energy_fx = 0, Max_coeff_fx; + Word32 en_high_fx[MAX_SB_NB]; + + + IF (is_transient) + { + set16_fx(st_fx->prev_sign_switch_2_fx, 0, HQ_FEC_SIGN_SFM); + set16_fx(st_fx->prev_sign_switch_fx, 0, HQ_FEC_SIGN_SFM); + } + ELSE + { + FOR (j = 0; j < HQ_FEC_SIGN_SFM; j++) + { + st_fx->prev_sign_switch_fx[j] = st_fx->prev_sign_switch_2_fx[j]; + move16(); + st_fx->prev_sign_switch_2_fx[j] = 0; + move16(); + + FOR (i = 0; i < HQ_FEC_BAND_SIZE; i++) + { + test(); + test(); + test(); + IF ((st_fx->old_coeffs_fx[i+j*HQ_FEC_BAND_SIZE]>0 && t_audio_q_fx[i+j*HQ_FEC_BAND_SIZE]<0) + || (st_fx->old_coeffs_fx[i+j*HQ_FEC_BAND_SIZE]<0 && t_audio_q_fx[i+j*HQ_FEC_BAND_SIZE]>0)) + { + st_fx->prev_sign_switch_fx[j] = add(st_fx->prev_sign_switch_fx[j], 1); + move16(); + st_fx->prev_sign_switch_2_fx[j] = add(st_fx->prev_sign_switch_2_fx[j], 1); + move16(); + } + } + } + } + + IF(EQ_16(output_frame, L_FRAME8k)) + { + /* if LR MDCT core is used, recalculate norms from decoded MDCT spectrum (using code from hq_hr_enc_fx()) */ + test(); + IF ( ( EQ_16(hqswb_clas, HQ_HVQ))||(EQ_16(hq_core_type,LOW_RATE_HQ_CORE))) + { + /* First group */ + logqnorm_fx(t_audio_q_fx, 12, ynrm, 32, WID_G1, (hqswb_clas == HQ_HVQ)); + j = ynrm[0]; + move16(); + offset = WID_G1; + move16(); + + FOR ( i=1; iynrm_values_fx[i][0]; + Copy32(norm_values_fx, &norm_values_fx[1], MAX_PGF-1); + + L_tmp = L_deposit_l(0); + FOR (j=0; jlast_core_fx, ACELP_CORE))&&(EQ_16(st_fx->core_fx,HQ_CORE)))) + { + FOR (i=0; iynrm_values_fx[i][j]=st_fx->ynrm_values_fx[i][0]; + move32(); + } + } + } + set16_fx(st_fx->Norm_gain_fx, 32767, SFM_N_NB);/*15*/ + /* st->energy_MA_Curr[1]=Energy of the current frame */ + tmp_fx = inv_tbl_fx[nb_sfm]; + move16();/*15*/ + L_tmp = Mult_32_16(tmp_energy_fx, tmp_fx);/*8 + 15 - 15*/ + + st_fx->energy_MA_Curr_fx[1] = extract_h(L_shl(L_tmp, 16-8)); + /* Moving Average */ + st_fx->energy_MA_Curr_fx[0] = s_max(1,add(mult_r(26214, st_fx->energy_MA_Curr_fx[0]), mult_r(6554, st_fx->energy_MA_Curr_fx[1]))); + + /*st->diff_energy = (float)fabs((st->energy_MA_Curr[1] - st->energy_MA_Curr[0])/st->energy_MA_Curr[0]); */ + st_fx->diff_energy_fx = abs_s(sub(st_fx->energy_MA_Curr_fx[1], st_fx->energy_MA_Curr_fx[0])); + exp1 = sub(norm_l(st_fx->diff_energy_fx), 1); + exp2 = norm_l(st_fx->energy_MA_Curr_fx[0]); + st_fx->diff_energy_fx = div_s(extract_h(L_shl(st_fx->diff_energy_fx, exp1)), extract_h(L_shl(st_fx->energy_MA_Curr_fx[0], exp2))); + exp = add(15, sub(exp1, exp2)); + st_fx->diff_energy_fx = shl(st_fx->diff_energy_fx, sub(11, exp));/*11*/ + + /* Classify the stationary mode : 12% */ + IF (LT_16(st_fx->diff_energy_fx, ED_THRES_12P_fx)) + { + stat_mode_curr = 1; + move16(); + } + ELSE + { + stat_mode_curr = 0; + move16(); + } + + /* Apply Hysteresis to prevent frequent mode changing */ + IF(EQ_16(st_fx->stat_mode_old_fx, stat_mode_curr)) + { + st_fx->stat_mode_out_fx = stat_mode_curr; + move16(); + } + + st_fx->stat_mode_old_fx = stat_mode_curr; + move16(); + + /* Find max. band index (Minimum value means maximum energy) */ + Min_ind=0; + move16(); + Min_value = L_deposit_l(100); + FOR (i=0; iynrm_values[i][j+1];*/ + en_high_fx[i] = L_add(en_high_fx[i], L_shr(st_fx->ynrm_values_fx[i][j+1], 1));/*Q12*/ move32(); + } + } + + *mean_en_high_fx = 0; + move16(); + FOR (i=k; iynrm_values[i][0]);*/ + exp1 = sub(norm_l(en_high_fx[i]), 1); + exp2 = norm_l(st_fx->ynrm_values_fx[i][0]); + tmp_fx = div_s(extract_h(L_shl(en_high_fx[i], exp1)), extract_h(L_shl(st_fx->ynrm_values_fx[i][0], exp2))); + exp = add(15, sub(exp1, exp2)); + *mean_en_high_fx = add(*mean_en_high_fx, shr(tmp_fx, sub(exp, 5))); + } + *mean_en_high_fx = mult(*mean_en_high_fx, inv_tbl_fx[num_Sb-k]); + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF ((LT_16(Min_ind, 5))&&(LT_16(abs_s(sub(Min_ind,st_fx->old_Min_ind_fx)),2))&&(LT_16(st_fx->diff_energy_fx,ED_THRES_90P_fx))&&(!st_fx->bfi_fx)&&(!st_fx->prev_bfi_fx)&&(!st_fx->prev_old_bfi_fx) + &&(!is_transient)&&(!st_fx->old_is_transient_fx[1]) && (st_fx->prev_last_core_fx==HQ_CORE) && (st_fx->last_core_fx==HQ_CORE)) + { + st_fx->phase_mat_flag_fx = 1; + move16(); + test(); + if ((Min_ind == 0)&&(LT_16(Max_ind, 3))) + { + st_fx->phase_mat_flag_fx = 0; + move16(); + } + } + ELSE + { + st_fx->phase_mat_flag_fx = 0; + move16(); + } + + st_fx->old_Min_ind_fx = Min_ind; + move16(); + } + + FOR (i=0; i < L_FRAME8k; i++) + { + st_fx->old_coeffs_fx[i] = t_audio_q_fx[i]; + move32(); + } + + st_fx->old_is_transient_fx[2] = st_fx->old_is_transient_fx[1]; + move16(); + st_fx->old_is_transient_fx[1] = st_fx->old_is_transient_fx[0]; + move16(); + st_fx->old_is_transient_fx[0] = is_transient; + move16(); + + return; +} + + +static Word16 find_best_delay_fx( + Word16 *mu_o_fx, + Word16 *in_fx, + Word16 mind1, + Word16 maxd1, + Word16 lin, + Word16 delta, + Word16 *false_flag +) +{ + Word16 i, d1, k; + Word16 d1m = 0; + + Word16 tmp, exp1, exp2; + Word32 L_tmp1, L_tmp2; + + Word32 min_sq_cross_fx, min_corr_fx; + Word32 accA_fx, accB_fx; + Word32 Rxy_fx[MAXDELAY_FEC], Ryy_fx[MAXDELAY_FEC]; + + d1 = mind1; + move16(); + FOR ( k = 0; k < (maxd1-mind1)/delta; k++ ) + { + accA_fx = L_deposit_l(0); + accB_fx = L_deposit_l(0); + FOR ( i = 0; i < lin; i += delta ) + { + accA_fx = L_add(accA_fx, L_shr(L_mult(mu_o_fx[d1+i], mu_o_fx[d1+i]),2)); + accB_fx = L_add(accB_fx, L_shr(L_mult(mu_o_fx[d1+i], in_fx[i]),2)); + } + + Rxy_fx[k] = accB_fx; + move32(); + Ryy_fx[k] = accA_fx; + move32(); + + d1 = add(d1, delta); + } + + /* Obtain the best delay values */ + min_sq_cross_fx = 0x80000000; + move32(); + min_corr_fx = L_deposit_l(0); + exp2 = 0; + move16(); + FOR ( d1 = 0; d1 < (maxd1-mind1)/delta; d1++ ) + { + IF (L_abs(Rxy_fx[d1]) > L_abs(Ryy_fx[d1])) + exp1 = norm_l(Rxy_fx[d1]); + ELSE + exp1 = norm_l(Ryy_fx[d1]); + + L_tmp1 = Mult_32_32(L_shl(Rxy_fx[d1], exp1), L_shl(min_corr_fx, exp2)); + L_tmp2 = Mult_32_32(L_shl(Ryy_fx[d1], exp1), L_shl(min_sq_cross_fx, exp2)); + IF ( GE_32(L_tmp1, L_tmp2)) + { + d1m = d1; + move16(); + min_corr_fx = L_add(Ryy_fx[d1], 0); /*12 + 12 - 31 */ + min_sq_cross_fx = L_add(Rxy_fx[d1], 0); /*12 + 12 - 31 */ + exp2 = exp1; + move16(); + } + } + + test(); + IF((min_sq_cross_fx<=0) || (min_corr_fx<=0)) + { + tmp = 0; + move16(); /* If cross correlation is negative, the division per the energy will always be negative --> tmp will be < 8192, no need to do the division per say */ + } + ELSE + { + /*d1m *= delta; */ + d1m = extract_l(L_mult0(d1m, delta)); + + exp1 = sub(norm_l(min_sq_cross_fx), 1); + exp2 = norm_l(min_corr_fx); + L_tmp1 = L_shl(min_sq_cross_fx, exp1); + L_tmp2 = L_shl(min_corr_fx, exp2); + tmp = div_s(extract_h(L_tmp1), extract_h(L_tmp2));/*15 + exp1 - exp2 */ + tmp = shl(tmp, sub(exp2, add(exp1, 1)));/*14 */ + } + + *false_flag = 0; + move16(); + test(); + if (LT_16(tmp, 8192)||GT_16(tmp,24576)) + { + *false_flag = 1; + move16(); + } + + return d1m; + +} + +static Word16 Search_Max_Corr_fx( + Word16 *mu_o_fx, /* i : *old_auOut_2fr, */ + Word16 old_Min_ind, /* i : *old_auOut_2fr, */ + const Word16 L /* i : L/2 */ +) +{ + Word16 pos; + Word16 pos2,delta2; + Word16 lin, delta; + Word16 mind1,maxd1; + Word16 false_flag; + Word16 min_d1, max_d1; + Word16 tmp1, tmp2; + Word16 *in_fx; + + IF (old_Min_ind == 0) + { + /*lin = 8*L/20; */ /* Basic size of the block for phase matching */ + lin = mult_r(L, 13107); /* Basic size of the block for phase matching */ + /*min_dist = -1e35f; */ + mind1 = 0; + move16(); /* min value of delay d1 to search for */ + /*maxd1 = 12*L/20; */ /* max value of delay d1 to search for */ + maxd1 = mult_r(L, 19661); /* max value of delay d1 to search for */ + + /*in = mu_o + 2*L -lin; */ + in_fx = mu_o_fx + 2*L - lin; + move16(); + + /* generate correlation */ + delta = 2; + move16(); + delta2 = 1; + move16(); + + pos = find_best_delay_fx(mu_o_fx, in_fx, mind1, maxd1, lin, delta, &false_flag); + + IF (false_flag) + { + return 0; + } + + tmp1 = add(mind1, sub(add(pos, 1), delta)); + tmp2 = add(mind1, add(pos, delta)); + min_d1 = s_max(mind1, tmp1); + max_d1 = s_min(maxd1, tmp2); + pos2 = find_best_delay_fx(mu_o_fx, in_fx, min_d1, max_d1, lin, delta2, &false_flag); + IF (GT_16(mind1, tmp1)) + { + pos = pos2; + move16(); + } + ELSE + { + pos = add(pos, add(sub(pos2, delta), 1)); + } + + pos = add(pos, add(lin, mind1)); + } + ELSE + { + lin = mult_r(L, 9830); + mind1 = mult_r(L, 14746); /* min value of delay d1 to search for */ + maxd1 = mult_r(L, 22938); /* max value of delay d1 to search for */ + in_fx = mu_o_fx + 2*L - lin; + move16(); + + /* generate correlation */ + delta = 2; + move16(); + delta2 = 1; + move16(); + + pos = find_best_delay_fx(mu_o_fx, in_fx, mind1, maxd1, lin, delta, &false_flag); + + IF (false_flag) + { + return 0; + } + + tmp1 = add(mind1, add(sub(pos, delta), 1)); + tmp2 = add(mind1, add(pos, delta)); + min_d1 = s_max(mind1, tmp1); + max_d1 = s_min(maxd1, tmp2); + pos2 = find_best_delay_fx(mu_o_fx, in_fx, min_d1, max_d1, lin, delta2, &false_flag); + + IF (GT_16(mind1, tmp1)) + { + pos = pos2; + move16(); + } + ELSE + { + pos = add(pos, add(sub(pos2, delta), 1)); + } + pos = add(pos, add(lin, mind1)); + } + + return pos; +} + +Word16 FEC_phase_matching_fx( + Decoder_State_fx *st_fx, /* i : Decoder State */ + Word32 *ImdctOut_fx, /* i : input */ + Word16 *auOut_fx, /* o : output audio */ + Word16 *OldauOut_fx, + Word16 OldauOut_pha_fx[2][N_LEAD_NB] +) +{ + Word16 i; + Word16 pos, remain; + Word16 ol_size; + Word16 L_overlap, L; + Word16 ImdctOutWin_fx[2*L_FRAME8k]; + Word16 OldauOutnoWin_fx[L_FRAME8k]; + Word16 OldauOut2_fx[L_FRAME8k]; + Word16 win_NB_fx[L_FRAME8k + 25]; + Word16 exp1, exp2, tmp; + Word32 pow1_fx, pow22_fx; + Word16 SmoothingWin_NB3_fx[24]; + + L = L_FRAME8k; + move16(); + ol_size = 2*L/20; + move16(); + L_overlap = 3*L/20; + move16(); + + FOR (i=0; iold_auOut_2fr_fx, st_fx->old_Min_ind_fx, L); + + IF (pos == 0) + { + return 1; + } + + /* Repetition */ + remain = L+N_Z_L_NB - ((2*L)-pos); + move16(); + Copy(&st_fx->old_auOut_2fr_fx[pos], &ImdctOutWin_fx[N_ZERO_NB], (2*L)-pos); + + /* OldauOut without windowing */ + FOR (i = N_ZERO_NB; i < L/2; i++) + { + OldauOutnoWin_fx[i-N_ZERO_NB] = extract_l( L_shr( L_negate(st_fx->oldIMDCTout_fx[L/2 - 1 - i]), 6 ) ); + } + FOR(i = 0; i < L/2; i++) + { + OldauOutnoWin_fx[i+N_ZERO_O_NB] = extract_l( L_shr( L_negate(st_fx->oldIMDCTout_fx[i]), 6 ) ); + } + + Copy(OldauOutnoWin_fx, &ImdctOutWin_fx[N_ZERO_NB+(2*L)-pos], remain); + + pow1_fx = L_deposit_l(0); + pow22_fx = L_deposit_l(0); + FOR (i = 0; i < L; i++) + { + pow1_fx = L_add(pow1_fx, shr(abs_s(st_fx->old_auOut_2fr_fx[L+i]), 1)); + pow22_fx = L_add(pow22_fx, shr(abs_s(ImdctOutWin_fx[N_ZERO_NB+i]), 1)); + } + IF(pow22_fx != 0) + { + exp1 = sub(norm_l(pow1_fx), 1); + exp2 = norm_l(pow22_fx); + tmp = div_s(extract_h(L_shl(pow1_fx, exp1)), extract_h(L_shl(pow22_fx, exp2)));/*15 + exp1 - exp2*/ + tmp = shl(tmp, sub(sub(exp2, exp1), 1));/*14*/ + FOR (i = N_ZERO_NB; i < 2*L; i++) + { + ImdctOutWin_fx[i] = shl(mult(ImdctOutWin_fx[i], tmp), 1); + } + } + Smoothing_vector_NB_fx(OldauOutnoWin_fx, &ImdctOutWin_fx[N_ZERO_NB], SmoothingWin_NB2_fx, auOut_fx, ol_size); + + FOR (i = 0; i < L/2; i++) + { + /*ImdctOutWin[3*L/2 + i] *= win_NB[L/2-i-1];*/ + ImdctOutWin_fx[3*L/2 + i] = mult(ImdctOutWin_fx[3*L/2 + i], win_NB_fx[L/2-i-1]); + move16(); + } + + FOR (i = N_ZERO_NB; i < L/2; i++) + { + /*ImdctOutWin_fx[L + i] *= win_NB_fx[(L-1-i)];*/ + ImdctOutWin_fx[L + i] = mult(ImdctOutWin_fx[L + i], win_NB_fx[(L-1-i)]); + move16(); + } + + Copy(&ImdctOutWin_fx[N_Z_L_O_NB], &OldauOut_pha_fx[0][0], N_LEAD_NB); + Copy(&ImdctOutWin_fx[ol_size+N_ZERO_NB], &auOut_fx[ol_size], N_Z_L_NB-ol_size); + Copy(&ImdctOutWin_fx[L], &auOut_fx[N_Z_L_NB], N_ZERO_NB); + Copy(&ImdctOutWin_fx[L], OldauOut_fx, L); + + FOR (i = 0; i < L/2; i++) + { + OldauOut2_fx[i] = extract_l( L_shr( L_negate(ImdctOut_fx[L/2 - 1 - i]), 6 ) ); + OldauOut2_fx[L/2+i] = extract_l( L_shr( L_negate(ImdctOut_fx[i]), 6 ) ); + } + + Smoothing_vector_NB_fx(&ImdctOutWin_fx[N_Z_L_O_NB], &OldauOut2_fx[N_ZERO_NB], SmoothingWin_NB3_fx, &OldauOut_pha_fx[1][0], L_overlap); + + FOR (i=L_overlap; i Q0 */ + } + FOR (i = 0; i < L/2; i++) + { + /*OldauOut[i+N_ZERO_O_NB] = -OldImdctOut[i];*/ + OldauOut_fx[i+N_ZERO_O_NB] = extract_l( L_shr( L_negate(OldImdctOut_fx[i]), 6 )); /* Q6 -> Q0 */ + } + + /* Overlapping with next good frame : Overlapping to remove the discontinuity */ + IF (cur_data_use_flag) + { + ol_size = N_LEAD_NB; + move16(); + + FOR (i = N_ZERO_NB; i < L/2; i++) + { + /* ImdctOutWin[i+L] = -ImdctOut[L/2 - 1 - i]; */ + ImdctOutWin_fx[i+L] = extract_l( L_shr( L_negate(ImdctOut_fx[L/2 - 1 - i]), 6 ) ); + } + FOR (i = 0; i < L/2; i++) + { + ImdctOutWin_fx[i+3*L/2] = extract_l( L_shr( L_negate(ImdctOut_fx[i]), 6 ) ); + } + + /*a = (float)(1./(float)(ol_size)); y = ax */ + Smoothing_vector_scaledown_NB_fx(OldauOut_fx, &ImdctOutWin_fx[N_Z_L_O_NB], SmoothingWin_NB875_fx, OldauOut_fx, ol_size); + + /* Scale down the overlapped signal */ + Scaledown_fx(&ImdctOutWin_fx[ol_size+N_Z_L_O_NB], &OldauOut_fx[ol_size], 23170, N_Z_L_NB-ol_size); + } + + L_overlap = overlap_time; + move16(); + FOR (i = 0; i < L_overlap; i++) + { + /*OldauOut[i] *= SmoothingWin_NB875[L_overlap-i-1];*/ + OldauOut_fx[i] = mult(OldauOut_fx[i], SmoothingWin_NB875_fx[L_overlap-i-1]); + move16(); + } + FOR (i=L_overlap; i < L; i++) + { + OldauOut_fx[i] = 0; + move16(); + } + + /* Windowing */ + /*Windowing_1st_NB(ImdctOutWin, ImdctOut, win_NB, SmoothingWin_NB875, 1);*/ + /*Windowing_2nd_NB(ImdctOutWin, ImdctOut, win_NB);*/ + Windowing_1st_NB_fx(ImdctOutWin_fx, ImdctOut_fx, win_NB_fx, SmoothingWin_NB875_fx, 1); + Windowing_2nd_NB_fx(ImdctOutWin_fx, ImdctOut_fx, win_NB_fx); + + /*v_add(&ImdctOutWin[N_ZERO_NB], OldauOut, auOut, L);*/ + /*mvr2r(&ImdctOutWin[L], OldauOut, L);*/ + FOR (i = 0; i < L; i++) + { + auOut_fx[i] = add(ImdctOutWin_fx[N_ZERO_NB + i], OldauOut_fx[i]); + move16(); + } + Copy(&ImdctOutWin_fx[L], OldauOut_fx, L); + + return; +} + +Word16 Repetition_smoothing_fx( + const Word32 *ImdctOut_fx, /* i : input */ + Word16 *auOut_fx, /* o : output audio */ + Word32 *OldImdctOut_fx, /* i : input */ + Word16 *OldauOut_fx, /* i/o: audio from previous frame */ + const Word16 L, /* i : length */ + Word16 *prev_oldauOut_fx, /* i : OldauOut from previous frame */ + Word16 overlap_time /* i : overlap time */ +) +{ + Word16 i; + Word32 pow1_fx; + Word32 pow22_fx; + Word16 ImdctOutWin_fx[2*L_FRAME8k]; + Word16 OldauOutnoWin_fx[L_FRAME8k]; + Word16 win_NB_fx[L_FRAME8k + 25]; + + FOR (i=0; i L_add(pow1_fx, L_shl(pow1_fx, 1))) + { + return 1; + } + + /* Update the OldauOut array for next overlapping */ + Copy(&ImdctOutWin_fx[L], OldauOut_fx, L); + Scaledown_fx(prev_oldauOut_fx, prev_oldauOut_fx, 23170, L); + + return 0; +} + +void common_overlapping_fx( + Word16 *auOut_fx, /* i : Input */ + Word16 *ImdctOutWin_fx, /* o : Output */ + Word16 *OldauOut_fx, /* i : Window */ + Word16 end1, /* i : Decay */ + Word16 offset1, + Word16 start2, + Word16 end2, + Word16 offset_i2, + Word16 offset2 +) +{ + Word16 i; + + /* Common Overlapping */ + FOR (i=0 ; i < end1; i++) + { + /*auOut_fx[i] = L_add(ImdctOutWin_fx[i+7*L/20], OldauOut_fx[i+offset1]);*/ + auOut_fx[i] = add(ImdctOutWin_fx[i+N_ZERO_NB], OldauOut_fx[i+offset1]); + move16(); + } + FOR (i=start2 ; i < end2; i++) + { + /*auOut_fx[i+offset2] = ImdctOutWin_fx[i+offset_i2]; move32();*/ + auOut_fx[i+offset2] = ImdctOutWin_fx[i+offset_i2]; + move16(); + } + + return; +} + + +void Smoothing_vector_NB_fx( + const Word16 OldauOutnoWin_fx[], /* i : Input vector 1 */ + const Word16 ImdctOutWin_fx[], /* i : Input vector 2 */ + const Word16 SmoothingWin_fx[], /* i : Smoothing window */ + Word16 auOut_fx[], /* o : Output vector that contains vector 1 .* vector 2 */ + const Word16 ol_size /* i : Overlap size */ +) +{ + Word16 i; + Word16 weight_fx; + + FOR (i=0 ; i < ol_size; i++) + { + weight_fx = SmoothingWin_fx[i]; + move16(); + auOut_fx[i] = add(mult(OldauOutnoWin_fx[i], sub(32767, weight_fx)), mult(ImdctOutWin_fx[i], weight_fx)); + move16(); + } + + return; +} + + +void Windowing_1st_NB_fx( + Word16 *ImdctOutWin_fx, /* o : Output */ + const Word32 *ImdctOut_fx, /* i : Input */ + const Word16 *win_fx, /* i : Window */ + const Word16 *smoothingWin_fx, /* i : Smoothing Window */ + Word16 smoothing_flag /* i : 1=Smoothing window, 0=Original window */ +) +{ + Word16 i; + Word16 L; + + L = L_FRAME8k; + move16(); + IF ( smoothing_flag == 0 ) + { + FOR (i = N_ZERO_NB; i < L/2; i++) + { + /*ImdctOutWin[i] = ImdctOut[L/2 + i] * win[(2*L-1-i)-N_LEAD_O_NB];*/ + ImdctOutWin_fx[i] = extract_l( L_shr( Mult_32_16(ImdctOut_fx[L/2 + i], win_fx[(2*L-1-i)-N_LEAD_O_NB]), 6 )); + } + + FOR (i = 0; i < N_ZERO_O_NB; i++) + { + /*ImdctOutWin[L/2 + i] = -ImdctOut[L - 1 - i] * win[(3*L/2-1-i)-N_LEAD_O_NB];*/ + /*ImdctOutWin[3*L/2 + i] = -ImdctOut[i] * win[(L/2-i-1)];*/ + ImdctOutWin_fx[L/2 + i] = extract_l( L_shr( Mult_32_16(L_negate(ImdctOut_fx[L - 1 - i]), win_fx[(3*L/2-1-i)-N_LEAD_O_NB]), 6 )); + ImdctOutWin_fx[3*L/2 + i] = extract_l( L_shr( Mult_32_16(L_negate(ImdctOut_fx[i]), win_fx[(L/2-i-1)]), 6 )); + } + } + ELSE + { + FOR (i = N_ZERO_NB; i < L/2; i++) + { + /*ImdctOutWin[i] = ImdctOut[L/2 + i] * smoothingWin[(i-N_ZERO_NB)];*/ /*win[(2*L-i)*decimate-1-decay-14*L_FRAME48k/20];*/ + ImdctOutWin_fx[i] = extract_l( L_shr( Mult_32_16(ImdctOut_fx[L/2 + i], smoothingWin_fx[(i-N_ZERO_NB)]), 6 )); /*win[(2*L-i)*decimate-1-decay-14*L_FRAME48k/20];*/ + } + + FOR (i = 0; i < N_ZERO_O_NB; i++) + { + /*ImdctOutWin[L/2 + i] = -ImdctOut[L - 1 - i] * smoothingWin[(i+N_ZERO_O_NB)];*/ /*win[(3*L/2-1-i)*decimate+decay-L_FRAME48k*14/20];*/ + /*ImdctOutWin[3*L/2 + i] = -ImdctOut[i] * win[(L/2-i-1)];*/ + ImdctOutWin_fx[L/2 + i] = extract_l( L_shr( Mult_32_16(L_negate(ImdctOut_fx[L - 1 - i]), smoothingWin_fx[(i+N_ZERO_O_NB)]), 6 )); /*win[(3*L/2-1-i)*decimate+decay-L_FRAME48k*14/20];*/ + ImdctOutWin_fx[3*L/2 + i] = extract_l( L_shr( Mult_32_16(L_negate(ImdctOut_fx[i]), win_fx[(L/2-i-1)]), 6 )); + } + } + + return; +} +void Windowing_2nd_NB_fx( + Word16 *ImdctOutWin_fx, /* o : Output */ + const Word32 *ImdctOut_fx, /* i : Input */ + const Word16 *win_fx /* i : Window */ +) +{ + Word16 i; + Word16 L; + + L = L_FRAME8k; + move16(); + FOR (i = N_ZERO_O_NB; i < L/2; i++) + { + /*ImdctOutWin[L/2 + i] = -ImdctOut[L - 1 - i];*/ + /*ImdctOutWin[3*L/2 + i] = -ImdctOut[i] * win[L/2-i-1];*/ + ImdctOutWin_fx[L/2 + i] = extract_l( L_shr( L_negate(ImdctOut_fx[L - 1 - i]), 6 )); + ImdctOutWin_fx[3*L/2 + i] = extract_l( L_shr( Mult_32_16(L_negate(ImdctOut_fx[i]), win_fx[L/2-i-1]), 6 )); + } + + FOR (i = 0; i < N_ZERO_NB; i++) + { + /*ImdctOutWin[L + i] = -ImdctOut[L/2 - 1 - i];*/ + ImdctOutWin_fx[L + i] = extract_l( L_shr( L_negate(ImdctOut_fx[L/2 - 1 - i]), 6 )); + } + + FOR (i = N_ZERO_NB; i < L/2; i++) + { + /*ImdctOutWin[L + i] = -ImdctOut[L/2 - 1 - i] * win[L - 1 - i];*/ + ImdctOutWin_fx[L + i] = extract_l( L_shr( Mult_32_16(L_negate(ImdctOut_fx[L/2 - 1 - i]), win_fx[L - 1 - i]), 6 )); + } + + return; +} + +void Smoothing_vector_scaledown_NB_fx( + const Word16 OldauOutnoWin_fx[], /* i : Input vector 1 */ + const Word16 ImdctOutWin_fx[], /* i : Input vector 2 */ + const Word16 SmoothingWin_fx[], /* i : Smoothing window */ + Word16 auOut_fx[], /* o : Output vector that contains vector 1 .* vector 2 */ + const Word16 ol_size /* i : Overlap size */ + +) +{ + Word16 i; + Word16 weight_fx; + + FOR (i=0 ; i < ol_size; i++) + { + weight_fx = SmoothingWin_fx[i]; + move16(); + auOut_fx[i] = add(mult(OldauOutnoWin_fx[i], sub(32767, weight_fx)), + mult(ImdctOutWin_fx[i], mult_r(23170, weight_fx))); + move16(); + } + + return; +} + + +void Scaledown_fx( + Word16 x[], /* i : Input vector */ + Word16 y[], /* o : Output vector that contains vector 1 .* vector 2 */ + Word16 scale_v, /*Q15 */ + const Word16 N /* i : Overlap size */ +) +{ + Word16 i; + + FOR (i=0; iQ_old_wtda != 0) + { + Scale_sig(st_fx->old_out_fx, output_frame, negate(st_fx->Q_old_wtda)); + st_fx->Q_old_wtda = 0; + move16(); + } + + test(); + test(); + test(); + test(); + test(); + test(); + IF( (EQ_16(st_fx->nbLostCmpt, 1))&&(EQ_16(st_fx->phase_mat_flag_fx,1))&&(EQ_16(st_fx->phase_mat_next_fx,0))) + { + IF (FEC_phase_matching_fx(st_fx, wtda_audio_fx, out_fx, st_fx->old_out_fx, st_fx->old_out_pha_fx) ) + { + /* window_ola( wtda_audio, out, st->old_out, output_frame, 0, 0, 0 ); */ + window_ola_fx(wtda_audio_fx, out_fx, Q_synth, st_fx->old_out_fx, &st_fx->Q_old_wtda, output_frame, ALDO_WINDOW, ALDO_WINDOW, 0, 0, 0 ); + st_fx->phase_mat_next_fx = 0; + move16(); + } + ELSE + { + st_fx->phase_mat_next_fx = 1; + move16(); + *Q_synth = 0; + move16(); + } + } + ELSE IF((EQ_16(st_fx->prev_bfi_fx, 1))&&(st_fx->bfi_fx==0)&&(EQ_16(st_fx->phase_mat_next_fx,1))) + { + FEC_phase_matching_nextgood_fx( wtda_audio_fx, out_fx, st_fx->old_out_fx, st_fx->old_out_pha_fx, mean_en_high_fx); + + st_fx->phase_mat_next_fx = 0; + move16(); + *Q_synth = 0; + move16(); + } + ELSE IF((EQ_16(st_fx->prev_bfi_fx, 1))&&(EQ_16(st_fx->bfi_fx,1))&&(EQ_16(st_fx->phase_mat_next_fx,1))) + { + FEC_phase_matching_burst_fx( wtda_audio_fx, out_fx, st_fx->old_out_fx, st_fx->old_out_pha_fx, st_fx->prev_oldauOut_fx); + st_fx->phase_mat_next_fx = 1; + move16(); + *Q_synth = 0; + move16(); + } + ELSE + { + /*n4 = (short)(N_LEAD_MDCT*(float)(output_frame/20));*/ + test(); + IF (st_fx->bfi_fx == 0 && EQ_16(st_fx->prev_bfi_fx, 1)) + { + test(); + IF((EQ_16(st_fx->stat_mode_out_fx, 1))||(LT_16(st_fx->diff_energy_fx,ED_THRES_50P_fx)))/* Q11 */ + { + Word16 tmp; + + tmp = 0; + if( GT_16(st_fx->old_bfi_cnt_fx,1)) + { + tmp = 1; + } + Repetition_smoothing_nextgood_fx( wtda_audio_fx, out_fx, st_fx->oldIMDCTout_fx, st_fx->old_out_fx, tmp, N_LEAD_NB); + *Q_synth = 0; + move16(); + } + ELSE IF(GT_16(st_fx->old_bfi_cnt_fx, 1)) + { + Next_good_after_burst_erasures_fx( wtda_audio_fx, out_fx, st_fx->old_out_fx, N_LEAD_NB ); + *Q_synth = 0; + move16(); + } + ELSE + { + /*window_ola( wtda_audio, out, st->old_out, output_frame, 0, 0, 0); */ + window_ola_fx( wtda_audio_fx, out_fx, Q_synth, st_fx->old_out_fx, &st_fx->Q_old_wtda, output_frame, + st_fx->tcx_cfg.tcx_last_overlap_mode, st_fx->tcx_cfg.tcx_curr_overlap_mode, st_fx->prev_bfi_fx, st_fx->oldHqVoicing_fx , st_fx->oldgapsynth_fx ); + } + } + ELSE /* if(st->bfi_fx == 1) */ + { + test(); + IF( (EQ_16(st_fx->stat_mode_out_fx, 1))||(LT_16(st_fx->diff_energy_fx,ED_THRES_50P_fx))) + { + /* if( window_ola_bfi( wtda_audio, out, st->oldIMDCTout, st->old_out, output_frame, st->prev_oldauOut, N_LEAD_NB) ) */ + IF( Repetition_smoothing_fx( wtda_audio_fx, out_fx, st_fx->oldIMDCTout_fx, st_fx->old_out_fx, output_frame, st_fx->prev_oldauOut_fx, N_LEAD_NB) ) + { + /*window_ola( wtda_audio, out, st->old_out, output_frame, 0, 0, 0);*/ + window_ola_fx( wtda_audio_fx, out_fx, Q_synth, st_fx->old_out_fx, &st_fx->Q_old_wtda, output_frame, + st_fx->tcx_cfg.tcx_last_overlap_mode, st_fx->tcx_cfg.tcx_curr_overlap_mode, st_fx->prev_bfi_fx, st_fx->oldHqVoicing_fx , st_fx->oldgapsynth_fx ); + } + ELSE + { + *Q_synth = 0; + move16(); + } + } + ELSE + { + /*window_ola( wtda_audio, out, st->old_out, output_frame, 0, 0, 0 );*/ + window_ola_fx( wtda_audio_fx, out_fx, Q_synth, st_fx->old_out_fx, &st_fx->Q_old_wtda, output_frame, + st_fx->tcx_cfg.tcx_last_overlap_mode, st_fx->tcx_cfg.tcx_curr_overlap_mode, st_fx->prev_bfi_fx, st_fx->oldHqVoicing_fx , st_fx->oldgapsynth_fx ); + } + } + st_fx->phase_mat_next_fx = 0; + move16(); + } + + return; +} + +void Next_good_after_burst_erasures_fx( + const Word32 *ImdctOut_fx, + Word16 *auOut_fx, + Word16 *OldauOut_fx, + const Word16 ol_size +) +{ + Word16 i, L; + Word16 ImdctOutWin_fx[2*L_FRAME48k]; + Word16 win_NB_fx[L_FRAME8k + 25]; + + L = L_FRAME8k; + move16(); + FOR (i=0; ienv_stab based threshold for hq-ecu technology decision */ + +#define PHASE_DITH_fx 25736 /* 2*pi in Q12 */ +#define DELTA_CORR 6 /* Tuning parameter - defining range for phase correction around peak */ +#define THRESH_TR_DB_FX 10 +#define THRESH_TR_LIN_BY2_FX (10/2) /* 10.0^(THRESH_TR_DB_FX/10.0)/2. Divided by 2 to facilitate fixed-point implementation. */ +#define MAX_INCREASE_GRPPOW_FX 0 /* max. amplification in case of transients (in dB scale) */ +#define MAX_INCREASE_GRPPOW_LIN_FX 32767 /* in Q15-- 10.0^(MAX_INCREASE_GRPPOW_FX/10.0) (in linear scale) */ + +#define PHASE_DITH_SCALE_SHIFT 16 /* The number of bit shift equivalent to multiply by PHASE_DITH_SCALE */ + +#define BURST_PHDITH_THRESH (4-1) /* speech start phase dither with losses in a row */ +#define BURST_PHDITH_RAMPUP_LEN 2 /* speech ramp up degree of phase dither over a length of frames */ +#define BURST_ATT_THRESH (3-1) /* speech start attenuate with losses in a row */ +#define ATT_PER_FRAME 4 /* speech attenuation in dB */ +#define BETA_MUTE_THR 10 /* time threshold to start beta-noise attenuation */ + +#define LGW32K 7 +#define LGW16K 6 +#define LGW48K LGW32K+1 /* Use the same frequency groups as for SWB + 1 */ + +#define LTRANALOG32K 8 +#define LTRANALOG16K 7 +#define PFIND_SENS_FX 31785 /* 0.97 in Q15 */ +#define CMPLMNT_PFIND_SENS_FX 983 /* (1.0 - pfind_sen) in Q15 */ + +#define FEC_HQ_ECU_POINT5 (0x4000) /* 0.5 in Q15. Prefix with FEC_HQ namespace to avoid naming conflict. */ +#define FEC_HQ_ECU_ROOT2 (0x5a83) /* sqrt(2) in Q14 */ +#define FEC_HQ_HAMM_A0 17695 /* 0.54 in Q15 */ +#define FEC_HQ_HAMM_A1 15073 /* 0.46 in Q15 */ +#define FEC_HQ_WIN_A0 FEC_HQ_HAMM_A0 +#define FEC_HQ_WIN_A1 FEC_HQ_HAMM_A1 + + +static Word16 sqrt2ndOrder(const Word16); + +static void windowing(const Word16*, Word16*, const Word16*, const Word16, const Word16); +static void windowing_ROM_optimized(const Word16*, Word16*, const Word16, const Word16, const Word16); +static void fft_spec2_fx(const Word16 [], Word32 [], const Word16); +static void trans_ana_fx(const Word16*, Word16*, Word16*, Word16*, const Word16, const Word16, const Word16 + ,const Word16 + ,Word16*, Word16*, Word16*, Word16* + + ); +static void peakfinder_fx(const Word16*, const Word16, Word16*, Word16*, const Word16); +static Word16 imax_fx( const Word16 *, const Word16); +static void spec_ana_fx(const Word16*, Word16*, Word32*, Word16*, Word16*, const Word16, const Word16, Word16*); +static 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*, Word16, const Word16* + ); +Word16 rand_phase_fx(const Word16 seed, Word16 *sin_F, Word16 *cos_F); + + +/*------------------------------------------------------------------* + * rand_phase() + * + * randomized phase in form of sin and cos components + *------------------------------------------------------------------*/ +Word16 rand_phase_fx(const Word16 seed, Word16 *sin_F, Word16 *cos_F) +{ + const Word16 *sincos = sincos_t_ext_fx + 128; + Word16 seed2 = own_random2_fx(seed); + Word16 seed2_shift = shr(seed2, 8); + + *sin_F = negate(*(sincos + seed2_shift)); + move16(); + if (s_and(seed2, 0x40) != 0) + { + *sin_F = *(sincos + seed2_shift); + move16(); + } + + *cos_F = negate(*(sincos - seed2_shift)); + move16(); + if (s_and(seed2, 0x80) != 0) + { + *cos_F = *(sincos - seed2_shift); + move16(); + } + + return seed2; +} + +/*----------------------------------------------------------------------------- + * fft_spec2_fx() + * + * Square magnitude of fft spectrum + *----------------------------------------------------------------------------*/ +static void fft_spec2_fx( + const Word16 x[], /* i : Input vector: complex spectrum */ + Word32 xMagSq[], /* o : Magnitude square spectrum */ + const Word16 N /* i : Input vector length */ +) +{ + Word16 i, l; + const Word16 *pRe, *pIm; + Word32 *pMagSq, acc; + + /* Magnitude at 0. */ + pMagSq = &xMagSq[0]; + pRe = &x[0]; + *pMagSq++ = L_mult0(*pRe, *pRe); + pRe++; /* Non-fractional multiply gives subsequent group power accumulation a bit headroom. */ + + /* From 1 to (N/2 - 1). */ + l = sub(shr(N, 1), 1); /* N/2 - 1. */ + pIm = &x[N]; + pIm--; + FOR (i = 0; i < l; i++) + { + acc = L_mult0(*pRe, *pRe); + pRe++; /* Non-fractional mode multiply. */ + *pMagSq++ = L_mac0(acc, *pIm, *pIm); + pIm--; + move32(); + } + + /* The magnitude square at N/2 */ + *pMagSq = L_mult0(*pRe, *pRe); + move32(); + return; +} + +/*----------------------------------------------------------------------------- + * trans_ana_fx() + * + * Transient analysis + *----------------------------------------------------------------------------*/ +static void trans_ana_fx( + const Word16 *xfp, /* i : Input signal Q0 */ + Word16 *mag_chg, /* o : Magnitude modification Q15 */ + Word16 *ph_dith, /* o : Phase dither, 2*PI is not included (Q15, i.e., between 0.0 and 1.0) */ + Word16 *mag_chg_1st, /* i/o: per band magnitude modifier for transients Q15 */ + const Word16 output_frame, /* i : Frame length */ + const Word16 time_offs, /* i : Time offset (integral multiple of output_frame) */ + const Word16 est_mus_content, /* i : 0.0=speech_like ... 1.0=Music (==st->env_stab ) */ + const Word16 last_fec, /* i : signal that previous frame was concealed with fec_alg */ + Word16 *alpha, /* o : Magnitude modification factors for fade to average */ + Word16 *beta, /* o : Magnitude modification factors for fade to average */ + Word16 *beta_mute, /* o : Factor for long-term mute */ + Word16 *Xavg /* o : Frequency group average gain to fade to */ +) +{ + const Word16 *w_hamm, *pFftTbl; + Word16 att_val, attDegreeFrames; + Word16 xfp_left[Ltrana48k], xfp_right[Ltrana48k]; + Word32 magSqLeft[Ltrana48k/2+1], magSqRight[Ltrana48k/2+1]; + Word32 *pLeft, *pRight, *pGrPowLeft, *pGrPowRight; + Word32 gr_pow_left[Lgw_max], gr_pow_right[Lgw_max]; + const Word16 *pXfp, *pGw; + Word16 Ltrana, Ltrana_2, Lprot, three4thLength, LtranaLogMinus1, Lgw, i, k, l, burst_len; + Word16 man, expo; + Word16 att_always = 0; /* fixed attenuation per frequency group if set to 1 */ + Word16 oneOverFrame, roundEstMusContent, tmp16, headroom, lowerEdge; + Word16 burst_phdith_thresh = BURST_PHDITH_THRESH; /*speech settings */ + Word16 burst_att_thresh = BURST_ATT_THRESH ; + Word16 att_per_frame = ATT_PER_FRAME; + Word16 burst_phdith_rampup_len = BURST_PHDITH_RAMPUP_LEN; + Word16 tr_dec[Lgw_max]; + UWord16 lsb; + Word32 acc; + + Lgw = 0; + LtranaLogMinus1 = 0; + pFftTbl = NULL; + + /* Initialisation to prevent warnings */ + oneOverFrame = 102; /* 1/320 in Q15 */ move16(); + w_hamm = w_hamm16k_2_fx; + move16(); + Lprot = 512; + move16(); + + /* check burst error */ + IF (EQ_16(output_frame, L_FRAME48k)) /* output_frame = (sampling frequency)/50 */ + { + oneOverFrame = 34; /* 1/960 in Q15 */ move16(); + w_hamm = w_hamm48k_2_fx; + move16(); + Lgw = LGW48K; + move16(); + Lprot = 1536; /* (2*output_frame)*1024/1280; */ move16(); + } + ELSE IF (EQ_16(output_frame, L_FRAME32k)) + { + oneOverFrame = 51; /* 1/640 in Q15 */ move16(); + w_hamm = w_hamm32k_2_fx; + move16(); + Lgw = LGW32K; + move16(); + Lprot = 1024; + move16(); + pFftTbl = FFT_W128; /* Table for 256 real input radix-2 FFT */ move16(); + LtranaLogMinus1 = LTRANALOG32K - 1; + move16(); + } + ELSE + { + oneOverFrame = 102; /* 1/320 in Q15 */ move16(); + w_hamm = w_hamm16k_2_fx; + move16(); + Lgw = LGW16K; + move16(); + Lprot = 512; + move16(); + pFftTbl = FFT_W64; /* Table for 128 real input radix-2 FFT */ move16(); + LtranaLogMinus1 = LTRANALOG16K - 1; + move16(); + } + burst_len = add(mult_r(time_offs, oneOverFrame), 1); + + *ph_dith = 0; + move16(); /* typical pattern is 2*pi*[0 0 .25 .50 .75 1.0 1.0 1.0 ..] */ + + IF (GE_16(output_frame, L_FRAME32k)) /*currently est_mus_content only calculated for SWB and FB */ + { + roundEstMusContent = 0; + move16(); + if (GE_16(est_mus_content, FEC_HQ_ECU_POINT5)) /* est_mus_content is in [0.0, 1.0]. */ + { + roundEstMusContent = 1; + move16(); + } + + /* softly shift attenuation just a bit later for estimated "stable" music_content */ + burst_phdith_thresh = add(BURST_PHDITH_THRESH, roundEstMusContent); + burst_att_thresh = add(BURST_ATT_THRESH, roundEstMusContent); + att_per_frame = sub(ATT_PER_FRAME, roundEstMusContent); /* only slighty less att for music */ + } + ELSE + { + /* lock to music-like stable envelope setting for now */ + burst_phdith_thresh = add(BURST_PHDITH_THRESH, 1); /* in Q0 */ + burst_att_thresh = add(BURST_ATT_THRESH, 1); /* in Q0 */ + att_per_frame = sub(ATT_PER_FRAME, 1); /* in Q0 */ + } + + IF (GT_16(burst_len, burst_phdith_thresh)) + { + /* increase degree of dither */ +#if BURST_PHDITH_RAMPUP_LEN != 2 +#error The implementation of phase_dith=min(1.0, (burst_len - burst_phdith_thresh)/burst_phdith_rampup_len)) is incorrect +#endif + *ph_dith = 32767; /* 1.0 in Q15. N.B. 2*PI is not included. */ move16(); + tmp16 = sub(burst_len, burst_phdith_thresh); + if (LT_16(tmp16, burst_phdith_rampup_len)) + { + *ph_dith = 16384; /* 0.5 in Q15. N.B. 2*PI is not included. */ move16(); + } + } + + attDegreeFrames = 0; + move16(); + IF (GT_16(burst_len, burst_att_thresh)) + { + att_always = 1; + move16(); + /* increase degree of attenuation */ + + /* N.B. To facilitate the subsequent 10^(-att_degree/20) implementation + * so as to use direct table-lookup, + * (burstLen - burst_att_thresh) is NOT multiplied by "att_per_frame". */ + attDegreeFrames = sub(burst_len, burst_att_thresh); /* Not multiplied by att_per_frqme! */ + /* Furthermore, in order to minimize the size of the lookup-table required to + * implement 10^(-att_degree/10), hard limit attDegreeFrames to (30% of 50)=15. + * If attDegreeFrames is greater than 15, it means there are more than 15 successive + * bad frames. In this case, no matter what to do, the sound quality will be bad. + */ + if (GT_16(attDegreeFrames, OFF_FRAMES_LIMIT)) + { + attDegreeFrames = OFF_FRAMES_LIMIT; /* Hard limit the no. of frames */ move16(); + } + } + + Ltrana = shr(Lprot, 2); + Ltrana_2 = shr(Ltrana, 1); + + test(); + test(); + IF (LE_16(burst_len, 1)||(EQ_16(burst_len,2)&&last_fec!=0)) + { + + set16_fx(alpha, 32767, Lgw_max); + set16_fx(beta, 0, Lgw_max); + *beta_mute = BETA_MUTE_FAC_INI; + move16(); + + /* Apply Hamming window */ + windowing(xfp, xfp_left, w_hamm, 0, Ltrana_2); /* 1st quarter */ + three4thLength = sub(Lprot, Ltrana); + pXfp = xfp + three4thLength; + windowing(pXfp, xfp_right, w_hamm, 0, Ltrana_2); /* 4th quarter */ + + /* spectrum */ + IF (EQ_16(output_frame, L_FRAME48k)) + { + fft3_fx(xfp_left, xfp_left, Ltrana); + fft3_fx(xfp_right, xfp_right, Ltrana); + } + ELSE + { + r_fft_fx_lc(pFftTbl, Ltrana, Ltrana_2, LtranaLogMinus1, xfp_left, xfp_left, 1); + r_fft_fx_lc(pFftTbl, Ltrana, Ltrana_2, LtranaLogMinus1, xfp_right, xfp_right, 1); + } + + /* square representation */ + fft_spec2_fx(xfp_left, magSqLeft, Ltrana); + fft_spec2_fx(xfp_right, magSqRight, Ltrana); + + /* band powers in frequency groups + * exclude bin at PI from calculation */ + magSqLeft[Ltrana_2] = L_deposit_l(0); + magSqRight[Ltrana_2] = L_deposit_l(0); + } + + pGrPowLeft = &gr_pow_left[0]; + pGrPowRight = &gr_pow_right[0]; + pGw = gw_fx; + FOR ( k = 0; k < Lgw; k++ ) + { + test(); + test(); + IF (LE_16(burst_len, 1)||(EQ_16(burst_len,2)&&last_fec!=0)) + { + lowerEdge = *pGw++; + move16(); + l = sub(*pGw, lowerEdge); + headroom = GR_POW_HEADROOM[k]; /* Number of bits to scale down preventing from saturation in accumulation.*/ move16(); + pLeft = magSqLeft + lowerEdge; + pRight = magSqRight + lowerEdge; + *pGrPowLeft = L_deposit_l(0); + *pGrPowRight = L_deposit_l(0); + FOR (i = 0; i < l; i++) + { + acc = L_shr(*pLeft++, headroom); /* Scale down to prevent from saturation. */ + *pGrPowLeft = L_add(*pGrPowLeft, acc); + move32(); + acc = L_shr(*pRight++, headroom); + *pGrPowRight = L_add(*pGrPowRight, acc); + move32(); + } + + /*Xavg[k] = sqrt(0.5f*(gr_pow_left[k]+gr_pow_right[k])/(float)(gw[k+1]-gw[k]));*/ + acc = L_shr(L_add(*pGrPowLeft, *pGrPowRight), 1); + acc = Mult_32_16(acc, gw_len_inv_fx[k]); /* -headroom */ + + acc = Sqrt_l(acc, &expo); /* -headroom+31+expo */ + + expo = sub(add(expo, 31), headroom); + if ( EQ_16(s_and(expo, 1), 1)) + { + acc = Mult_32_16(acc, 23170); /* 1/sqrt(2) in Q15 */ + } + expo = shr(expo, 1); + Xavg[k] = round_fx(L_shl(acc, sub(sub(16, expo), 2))); /* Q0, additional right shift by 2 to account for that Xavg is + calculated using lenght N/4 fft but is applied on a fft of length N */ + + /*dither phase in case of transient */ + /* separate transition detection and application of forced burst dithering */ + tr_dec[k] = 0; + move16(); + Mpy_32_16_ss(*pGrPowLeft, THRESH_TR_LIN_BY2_FX, &acc, &lsb); /* To facilitate fixed-point implementation, divide threshold by 2. */ + acc = L_or(L_shl(acc,16), L_and(0xffffL,lsb)); /* Equivalent to concatenate acc and lsb, and then down shift by 16 bits. */ + if (GT_32(*pGrPowRight, acc)) /* gr_pow_right > thres_tr_lin*gr_pow_left */ + { + tr_dec[k] = 1; + move16(); + } + Mpy_32_16_ss(*pGrPowRight, THRESH_TR_LIN_BY2_FX, &acc, &lsb); + acc = L_or(L_shl(acc,16), L_and(0xffffL,lsb)); /* Equivalent to concatenate acc and lsb, and then down shift by 16 bits. */ + if (GT_32(*pGrPowLeft, acc)) /* gr_pow_left > thres_tr_lin*gr_pow_right */ + { + tr_dec[k] = 1; + move16(); + } + + /* magnitude modification */ + IF ( add(tr_dec[k], att_always) != 0) + { + +#if MAX_INCREASE_GRPPOW_FX != 0 +#error trans_ana_fx-- The following implementation is incorrect +#endif + att_val = 32767; + move16(); + IF (GT_32(*pGrPowRight, 0)) + { + IF (LT_32(*pGrPowRight, *pGrPowLeft)) /* i.e., (gr_pow_right/gr_pow_left) < 1.0 */ + { + /* Compute sqrt(grp_pow_chg), where grp_pow_chg = gr_pow_right/gr_pow_left. */ + tmp16 = ratio(*pGrPowRight, *pGrPowLeft, &expo); /* tmp16 in Q14 */ + expo = sub(expo, (15-14)); /* Now, tmp16 is considered in Q15 */ + i = norm_s(tmp16); + man = shl(tmp16, i); /* Mandatory normalization before sqrtNthOrder(). */ + expo = add(expo, i); + man = sqrt2ndOrder(man); + if (s_and(expo,1) != 0) /* Check even or odd. */ + { + man = mult_r(man,FEC_HQ_ECU_ROOT2); + } + expo = shr(expo, 1); /* Divided by 2-- square root operation. */ + att_val = shr(man, expo); /* Denormalize the mantissa back to Q15. */ + } + /* ELSE do nothing because (gr_pow_right/gr_pow_left) >= 1.0 (i.e., + * max_increase_grppow_lin) */ + } + + mag_chg_1st[k] = att_val; + move16(); + mag_chg[k] = att_val; + move16(); + } + ELSE + { + mag_chg_1st[k] = 32767; + move16(); + mag_chg[k] = 32767; + move16(); /* Set to 1.0 in Q15 */ + } + } + ELSE + { + /* Since attDegreeFrames is discrete (integer) and hard limited to OFF_FRAMES_LIMIT, + * it is much easier to implement 10^(-att_degree/20.0) by a simply direct + * table-lookup. Also, att_per_frame is discrete as well and can be + * either ATT_PER_FRAME-1 or ATT_PER_FRAME and nothing else. This + * means only 2 tables of size=(OFF_FRAMES_LIMIT+1) each are required. + * To take square root into account, it is divided by 20 instead of 10. */ + IF (EQ_16(att_per_frame, ATT_PER_FRAME)) /* Select the corresponding lookup-table. */ + { + att_val = POW_ATT_TABLE0[attDegreeFrames]; /* 10^(-attDegreeFrames*(ATT_PER_FRAME)/20) */ move16(); + } + ELSE + { + att_val = POW_ATT_TABLE1[attDegreeFrames]; /* 10^(-attDegreeFrames*(ATT_PER_FRAME - 1)/20) */ move16(); + } + mag_chg[k] = mult_r(mag_chg_1st[k], att_val); /* Q15 */ + + if (GT_16(burst_len, BETA_MUTE_THR)) + { + *beta_mute = shr(*beta_mute, 1); + } + alpha[k] = mag_chg[k]; + move16(); + /*beta[k] = sqrt(1.0f - SQR(alpha[k])) * *beta_mute;*/ + acc = L_sub(1073741824, L_mult0(alpha[k], alpha[k])); + acc = Sqrt_l(acc, &expo); + expo = add(30, add(31, expo)); + if (EQ_16(s_and(expo, 1), 1)) + { + acc = Mult_32_16(acc, 23170); /* 1/sqrt(2) in Q15 */ + } + expo = shr(expo, 1); + beta[k] = mult_r(*beta_mute, round_fx(L_shl(acc, sub(31, expo)))); + move16(); + + IF (GE_16(k, LGW32K-1)) + { + beta[k] = mult_r(beta[k], 3277); /* 0.1 in Q15 */ + } + ELSE IF (GE_16(k, LGW16K-1)) + { + beta[k] = mult_r(beta[k], 16384); /* 0.5 in Q15 */ + } + } + pGrPowLeft++; + pGrPowRight++; + } + + return; +} + +/*----------------------------------------------------------------------------- + * peakfinder_fx() + * + * Peak-picking algorithm + *----------------------------------------------------------------------------*/ +static void peakfinder_fx( + const Word16 *x0, /* i : vector from which the maxima will be found */ + const Word16 len0, /* i : length of input vector */ + Word16 *plocs, /* o : the indices of the identified peaks in x0 Q0 */ + Word16 *cInd, /* o : number of identified peaks Q0 */ + const Word16 sel /* i : The amount above surrounding data for a peak to be identified */ +) +{ + const Word16 *pX0; + Word16 minMag, tempMag, leftMin; + Word16 dx0[Lprot48k_2], x[Lprot48k_2+1], peakMag[MAX_PLOCS]; + Word16 *pDx0, *pDx01, *pX; + Word16 i, len, tempLoc, foundPeak, ii, xInd, tmp16, threshold, xAt0, xAt1, xAt2; + Word16 len0Minus1, len0Minus2, lenMinus1; + Word16 indarr[Lprot48k_2+1], peakLoc[MAX_PLOCS]; + Word16 *pInd; + + tempLoc = 0; + + /* Find derivative */ + len0Minus1 = sub(len0, 1); + pX0 = x0 + 1; + Vr_subt(pX0, x0, dx0, len0Minus1); + + FOR (i=0; i overwrite with x[0] */ + { + *pX = xAt0; /* x[1] = x[0] */ move16(); + tmp16 = *pInd++; + move16(); + *pInd++ = tmp16; /* ind[1] = ind[0] */ move16(); + len = sub(len, 1); + } + pX--; /* After decrement, pX points to x[0]. */ + } + ELSE /* First point is smaller than the second */ + { + ii = 0; + IF (LT_16(xAt1, xAt2)) /* x[1] is not extremum -> overwrite with x[0] */ + { + *pX = xAt0; /* x[1] = x[0] */ move16(); + tmp16 = *pInd++; + move16(); + *pInd++ = tmp16; /* ind[1] = ind[0] */ move16(); + len = sub(len, 1); + } + } + pX--; /* After decrement, pX points to either x[-1] or x[0]. */ + + *cInd = 0; + move16(); + /*Loop through extrema which should be peaks and then valleys*/ + lenMinus1 = sub(len, 1); + FOR (;;) + { + ii = add(ii, 1); /* This is a peak */ + + /* Make sure we don't iterate past the length of our vector */ + IF (GE_16(ii, lenMinus1)) + { + BREAK; + } + + /*Reset peak finding if we had a peak and the next peak is bigger + than the last or the left min was small enough to reset.*/ + IF (GT_16(foundPeak,0)) + { + tempMag = minMag; + move16(); + foundPeak = 0; + move16(); + } + + /* Found new peak that was larger than temp mag and selectivity larger + than the minimum to its left. */ + IF (GT_16(*(++pX), tempMag)) + { + IF ( GT_16(*pX, threshold)) /* threshold = leftMin + sel */ + { + tempLoc = ii; + move16(); + tempMag = *pX; + move16(); + } + } + + ii = add(ii, 1); /* Move onto the valley */ + pX++; + + /* Come down at least sel from peak */ + IF (foundPeak == 0) + { + IF (GT_16(tempMag, add(sel, *pX))) + { + foundPeak = 1; /* We have found a peak */ move16(); + leftMin = *pX; + move16(); + threshold = add(leftMin, sel); + peakLoc[*cInd] = tempLoc; /* Add peak to index */ move16(); + peakMag[*cInd] = tempMag; + move16(); + *cInd = add(*cInd, 1); + } + } + IF (foundPeak == 0) /* The above IF-block has not found the peak yet. */ + { + IF (LT_16(*pX, leftMin))/* New left minimum */ + { + leftMin = *pX; + move16(); + threshold = add(leftMin, sel); + } + } + } + + /* Check end point */ + IF (GT_16(x[lenMinus1], tempMag)) + { + IF (GT_16(x[lenMinus1], threshold)) /* threshold = leftMin + sel */ + { + peakLoc[*cInd] = lenMinus1; + move16(); + peakMag[*cInd] = x[lenMinus1]; + move16(); + *cInd = add(*cInd, 1); + foundPeak = 1; + move16(); + } + } + IF (foundPeak == 0) /* Check if we still need to add the last point */ + { + IF (GT_16(tempMag, minMag)) + { + peakLoc[*cInd] = tempLoc; + move16(); + peakMag[*cInd] = tempMag; + move16(); + *cInd = add(*cInd, 1); + } + } + + /* Create output */ + FOR (i = 0; i < *cInd; i++) + { + plocs[i] = *(indarr + peakLoc[i]); + move16(); + move16(); + } + } + ELSE /* This is a monotone function where an endpoint is the only peak */ + { + xInd = 1; + move16(); + if (GT_16(x[0], x[1])) + { + xInd = 0; + move16(); + } + + peakMag[0] = x[xInd]; + move16(); + IF (GT_16(peakMag[0], add(minMag, sel))) + { + plocs[0] = *(indarr + xInd); + move16(); + *cInd = 1; + move16(); + } + ELSE + { + *cInd = 0; + move16(); + } + } +} + +/*----------------------------------------------------------------------------- +* imax_fx() +* +* Get interpolated maximum position +*-----------------------------------------------------------------------------*/ +static Word16 imax_fx( /* o: The location, relative to the middle of the 3 given data point, of the maximum. (Q15) */ + const Word16 *y, /* i: The 3 given data points. */ + const Word16 special /* i: -1 = left edge special case, 0 = normal, +1 = right edge special case */ +) +{ + Word16 posi; + Word16 y1, y2, y3, man, expo, edge; + const Word16 *pY; + Word32 numer, denom, sign, acc, y3_y1; + + /* Seek the extremum of the parabola P(x) defined by 3 consecutive points + so that P([-1 0 1]) = [y1 y2 y3] */ + pY = y; + y1 = *pY++, y2 = *pY++, y3 = *pY; + move16(); + move16(); + move16(); + + /* The extremum value: + * y2i = -0.125f * SQR(y3_y1) / (y1+y3-2*y2)+y2 + * is not computed. Alternatively, the derivative of the parabola evaluated at y=0, + * dP/dy|y=0, is used to determine whether the extremum is maximum or not. + */ + + /* Compute the extremum location: posi = (y3 - y1)/(4*y2 - 2*y1 - 2*y3). */ + y3_y1 = L_sub(y3, y1); + acc = L_shl(y2,1); /* N.B. y2 is multiplied by 2 not 4. */ + acc = L_sub(acc, y1); /* N.B. Y1 is not multiplied by 2. */ + denom = L_sub(acc, y3); /* N.B. Y3 is not multiplied by 2. */ + sign = L_xor(y3_y1, denom); /* Preserve the sign since div_s() only takes positive arguments. */ + numer = L_abs(y3_y1); + denom = L_abs(denom); + IF (numer == 0) + { + return 0; + } + IF (denom == 0) + { + return 0; + } + /* Although the output of ratio() is in Q14, adding the missing factor of 2 (See above) + * in the denominator, the output is now considered to be in Q15. */ + man = ratio(numer, denom, &expo); /* The mantissa is considered in Q15 */ + posi = shr(man, expo); /* in Q15 (Due to saturation, it is automatically bound inside [-1.0,1.0].) */ + + if (sign < 0) /* Restore the sign. */ + { + posi = negate(posi); + } + + /* For both edges (left and right), the extremum found above may be minimum. + * It needs to reject the minimum. */ + IF (NE_16(special,0)) /* Either edge specical case. */ + { + edge = 0x7fff; /* 1 in Q15 for the right edge special case */ move16(); + if (LT_16(special,0)) + { + edge = 0; /* Left edge special case */ move16(); + } + + /* The derivative (slope) of the interpolating parabola = 2*A*y + B, + * where A = (y3 + y1)/2 - y2 + * and B = (y3 - y1)/2. + * Therefore, the slope at y=0 is simply B. Use this slope to determine + * if the parabola is concave upward or downward. + */ + IF (GT_16(posi,0)) /* The extremum is in between the middle and the right given data points. */ + { + IF (LE_16(y3, y1)) /* Check the slope at y=0, i.e., at the middle given data point. */ + { + posi = edge; /* minimum case */ move16(); + } + ELSE + { + posi = sub(0x7fff, posi); /* maximum case */ + } + } + ELSE /* The extremum is in between the left and the middle given data points. */ + { + IF (GE_16(y3, y1)) + { + posi = edge; /* minimum case */ move16(); + } + ELSE + { + posi = add(0x7fff, posi); /* maximum case */ + } + } + } + return posi; /* Q15. The position either left or right relative to the index of the middle of the 3 given data points. */ +} + +/*----------------------------------------------------------------------------- +* spec_ana_fx() +* +* Spectral analysis +*-----------------------------------------------------------------------------*/ +static void spec_ana_fx( + const Word16 *prevsynth, /* i : Input signal */ + Word16 *plocs, /* o : The indicies of the identified peaks Q0 */ + Word32 *plocsi, /* o : Interpolated positions of the identified peaks Q16 */ + Word16 *num_plocs, /* o : Number of identified peaks Q0 */ + Word16 *X_sav, /* o : Stored fft spectrum */ + const Word16 output_frame, /* i : Frame length Q0 */ + const Word16 bwidth_fx, /* i : Encoded bandwidth index Q0 */ + Word16 *Q /* o : Q value of the fft spectrum */ +) +{ + Word16 Lprot, LprotLog2Minus1=0, hamm_len2=0, Lprot2, Lprot2_1, m, n; + const Word16 *pFftTbl = NULL; + Word16 xfp[Lprot48k]; + Word32 magSq[Lprot48k/2+1], *pMagSq; + Word16 *pXfp, *pXfp1, *pXsav, *pPlocs; + Word16 Xmax, Xmin, sel, man, expo, expoBy2; + Word16 sinTblOffset, rectLength, fraction, special; + Word32 *pPlocsi; + Word32 acc; + Word16 stop_band_start; + Word16 stop_band_length; + + Lprot = 512; /* 1536=(2*output_frame)*1024/1280; */ move16(); + + sinTblOffset = 0; + + IF (EQ_16(output_frame, L_FRAME48k)) + { + Lprot = Lprot48k; /* 1536=(2*output_frame)*1024/1280; */ move16(); + hamm_len2 = Lprot_hamm_len2_48k; /* half Hamming window = 288 */ move16(); + } + ELSE IF (EQ_16(output_frame, L_FRAME32k)) + { + Lprot = Lprot32k; /* 1024 */ move16(); + sinTblOffset = 4; + move16(); + hamm_len2 = Lprot_hamm_len2_32k; /* half Hamming window = 192 */ move16(); + pFftTbl = FFT_W512; /* Table for 1024-point real input FFT */ + LprotLog2Minus1 = 9; /* FFT stages for complex input FFT */ move16(); + } + ELSE + { + Lprot = 512; + move16(); + sinTblOffset = 8; + move16(); + hamm_len2 = Lprot_hamm_len2_16k; /* half Hamming window = 96 */ move16(); + pFftTbl = FFT_W256; /* Table for 512-point real input FFT */ + LprotLog2Minus1 = 8; /* FFT stages for complex input FFT */ move16(); + } + + Lprot2 = shr(Lprot, 1); + Lprot2_1 = add(Lprot2, 1); + rectLength = sub(Lprot, shl(hamm_len2,1)); /* The length of the rectangular portion of the Hamming-Rectangular window. */ + + *Q = s_max(0, sub(Exp16Array(Lprot, prevsynth), 1)); + move16(); + Copy_Scale_sig(prevsynth, xfp, Lprot, *Q); + + IF (EQ_16(output_frame, L_FRAME48k)) + { + /* Apply hamming-rect window */ + windowing(xfp, xfp, w_hamm_sana48k_2_fx, rectLength, hamm_len2); + /* Spectrum */ + fft3_fx(xfp, xfp, Lprot); + } + ELSE + { + /* Apply hamming-rect window */ + windowing_ROM_optimized(xfp, xfp, sinTblOffset, rectLength, hamm_len2); + /* Spectrum */ + r_fft_fx_lc(pFftTbl, Lprot, Lprot2, LprotLog2Minus1, xfp, xfp, 1); + } + + /* Apply zeroing of non-coded FFT spectrum */ + IF (GT_16(output_frame, inner_frame_tbl_fx[bwidth_fx])) + { + stop_band_start = shl(128, bwidth_fx); + stop_band_length = sub(Lprot, shl(stop_band_start,1)); + stop_band_start = add(stop_band_start, 1); + set16_fx( xfp + stop_band_start, 0, stop_band_length ); + } + + pXfp = xfp; + pXsav = X_sav; + FOR (m = 0; m < Lprot; m++) + { + *pXsav++ = *pXfp++; + move16(); + } + + /* Magnitude representation */ + fft_spec2_fx(xfp, magSq, Lprot); + + /* Compute xfp[m] = sqrt(magSq[m]) */ + pXfp = xfp; + pMagSq = magSq; + FOR (m = 0; m < Lprot2_1; m++) + { + IF (*pMagSq == 0) + { + *pXfp++ = extract_l(*pMagSq++); /* magSq[] is zero */ + } + ELSE + { + expo = norm_l(*pMagSq); /* exponent */ + man = extract_h(L_shl(*pMagSq++, expo)); /* mantissa */ + man = sqrt2ndOrder(man); + expoBy2 = shr(expo, 1); /* Divided by 2-- square root operation. */ + IF (s_and(expo,1) == 0) /* Check even or odd. */ + { + man = mult_r(man,FEC_HQ_ECU_ROOT2); /* FEC_HQ_ECU_ROOT2 is sqrt(2) in Q14 */ + expoBy2 = sub(expoBy2, 1); + } + *pXfp++ = shr(man, expoBy2); + move16();/* Denormalize the mantissa back to Q0. */ + } + } + + /* Find maximum and minimum. */ + maximum_fx(xfp, Lprot2_1, &Xmax); + minimum_fx(xfp, Lprot2_1, &Xmin); + sel = mult_r(sub(Xmax, Xmin), CMPLMNT_PFIND_SENS_FX); + peakfinder_fx(xfp, Lprot2_1, plocs, num_plocs, sel); + + /* Refine peaks */ + pPlocsi = plocsi; + pPlocs = plocs; + n = sub(*num_plocs, 1); /* -1 so as to exclude the very last peak. */ + /* Special case-- The very 1st peak if it is at 0 index position */ + IF (EQ_16(*pPlocs, 0)) /* Only the very 1st peak is possible the peak at 0 index position. */ + { + fraction = imax_fx(xfp, -1); /* -1 signifies special left edge case. */ + acc = L_deposit_h(*pPlocs++); /* N.B., (*pPlocs) must be zero here. */ + *pPlocsi++ = L_mac(acc, fraction, 1); + move32();/* in Q16 */ + n = sub(n, 1); /* This special case is taken care of-- one less to go */ + } + /* All peaks except the very last peak but including the very 1st one if it has not been taken care of. */ + pXfp1 = xfp - 1; + FOR (m = 0; m < n; m++) /* Loop through up to the last but one peak. (The last one is excluded.) */ + { + pXfp = pXfp1 + *pPlocs; + fraction = imax_fx(pXfp, 0); /* in Q15 */ + acc = L_deposit_h(*pPlocs++); + *pPlocsi++ = L_mac(acc, fraction, 1); + move32();/* in Q16. Append the fractional part to the integral part. */ + } + IF ( n >= 0 ) + { + /* Special case-- The very last peak */ + pXfp = pXfp1 + *pPlocs; + IF (EQ_16(*pPlocs, Lprot2)) /* Only the very last peak is possible the peak at Lprot2 index position. */ + { + pXfp--; /* Special case needs extra decrement */ + special = 1; /* Signify special right edge case. */ move16(); + } + ELSE + { + special = 0; + move16(); + } + fraction = imax_fx(pXfp, special); /* in Q15 */ + acc = L_deposit_h(*pPlocs); + *pPlocsi = L_mac(acc, fraction, 1); + move32();/* in Q16. Append the fractional part to the integral part. */ + } +} + +/*-------------------------------------------------------------------* +* subst_spec_fx() +* +* Substitution spectrum calculation +*-------------------------------------------------------------------*/ + +static void subst_spec_fx( + const Word16 *plocs, /* i : The indices of the identified peaks Q0 */ + const Word32 *plocsi, /* i : Interpolated positions of the identified peaks Q16 */ + Word16 *num_plocs, /* i/o : Number of identified peaks Q0 */ + const Word16 time_offs, /* i : Time offset Q0 */ + Word16 *X, /* i/o : FFT spectrum */ + const Word16 *mag_chg, /* i : Magnitude modification Q15 */ + const Word16 ph_dith, /* i : Phase dither, 2*PI is not included. (Q15, i.e., between 0.0 and 1.0) */ + const Word16 *is_trans, /* i : Transient flags (either 0 or 1) */ + const Word16 output_frame, /* i : Frame length Q0 */ + Word16 *seed, /* i/o : Random seed */ + const Word16 *alpha, /* i : Magnitude modification factors for fade to average Q15 */ + const Word16 *beta, /* i : Magnitude modification factors for fade to average Q15 */ + Word16 beta_mute, /* i : Factor for long-term mute Q15 */ + const Word16 *Xavg /* i : Frequency group averages to fade to Q0 */ +) +{ + Word16 Xph_short; + Word32 corr_phase[MAX_PLOCS], Xph; + Word32 *pCorrPhase; + Word16 cos_F, sin_F, tmp; + Word16 Lprot, m, i, e, im_ind, delta_corr_up, delta_corr_dn, delta_tmp; + UWord16 lsb; + Word16 j, re, im, *pReX, *pImX, lastPeak, lprotBy2Minus1, segmentLen; + Word16 pkLocation_1, pkLocation, pkLocation1; + const Word16 *pPlocs; + const Word32 *pPlocsi; + Word32 acc; + Word16 Lecu; + Word16 Lprot_inv; + Word16 k; + Word16 tmp2; + Word16 alpha_local; + Word16 beta_local; + Word16 expo; + + Word16 mag_chg_local; /*for peak attenuation in burst */ + + Lprot = 512; + move16(); + Lprot_inv = 8192; + move16(); + Lecu = shl(output_frame, 1); + + IF (EQ_16(output_frame, L_FRAME48k)) + { + Lprot = Lprot48k; /* 1536=(2*output_frame)*1024/1280; */ move16(); + Lprot_inv = 2731; /* Q22 */ move16(); + } + ELSE IF (EQ_16(output_frame, L_FRAME32k)) + { + Lprot = Lprot32k; /* 1024 */ move16(); + Lprot_inv = 4096; /* Q22 */ move16(); + } + ELSE + { + Lprot = 512; + move16(); + Lprot_inv = 8192; /* Q22 */ move16(); + } + + /* Correction phase of the identified peaks */ + IF (s_or(is_trans[0], is_trans[1]) != 0) + { + *num_plocs = 0; + move16(); + } + ELSE + { + tmp = NS2SA(output_frame*50,PH_ECU_ALDO_OLP2_NS-PH_ECU_LOOKAHEAD_NS); + tmp = add(tmp, sub(Lecu, shr(sub(Lecu, Lprot), 1))); + tmp = sub(tmp, shr(output_frame, 1)); + tmp = add(tmp, time_offs); + tmp = round_fx(L_shl(L_mult0(tmp, Lprot_inv), 4)); /* 0+22+4-16=10 */ + + pPlocsi = plocsi; + pCorrPhase = corr_phase; + FOR (m = 0; m < *num_plocs; m++) + { + Mpy_32_16_ss(*pPlocsi++, tmp, &acc, &lsb); /* plocsi[] in Q16, tmp in Q10 and tmp does not include 2*PI. */ + acc = L_add(L_shl(acc, 5), lshr(lsb, 11)); + *pCorrPhase++ = acc; /* in Q16. 2*PI is not included. */ move32(); + } + } + + lprotBy2Minus1 = sub(shr(Lprot, 1), 1); + i = 1; + move16(); + k = 0; + move16(); + im_ind = sub(Lprot, 1); + move16(); + pReX = X + i; + pImX = X + im_ind; + pPlocs = plocs; + pCorrPhase = corr_phase; + pkLocation = *pPlocs; /* N.B. No post-increment */ move16(); + pkLocation1 = *pPlocs++; + move16(); + lastPeak = sub(*num_plocs, 1); + FOR (m = 0; m < *num_plocs; m++) + { + delta_corr_dn = DELTA_CORR; + move16(); + delta_corr_up = DELTA_CORR; + move16(); + + pkLocation_1 = pkLocation; /* plocs[m - 1] */ move16(); + pkLocation = pkLocation1; /* plocs[m] */ move16(); + pkLocation1 = *pPlocs++; /* plocs[m + 1] */ move16(); + IF (m > 0) + { + delta_tmp = shr(sub(sub(pkLocation, pkLocation_1), 1), 1); + if (LT_16(delta_tmp, DELTA_CORR)) + { + delta_corr_dn = delta_tmp; + move16(); + } + } + + IF (LT_16(m, lastPeak)) + { + delta_tmp = shr(sub(sub(pkLocation1, pkLocation), 1), 1); + if (LT_16(delta_tmp, DELTA_CORR )) + { + delta_corr_up = delta_tmp; + move16(); + } + } + + /* Input Xph */ + segmentLen = sub(sub(pkLocation, delta_corr_dn), i); + /* i = add(i, segmentLen); */ + FOR (j = 0; j < segmentLen; j++) + { + *seed = rand_phase_fx(*seed, &sin_F, &cos_F); + + re = *pReX; + move16(); + im = *pImX; + move16(); + tmp = sub(mult_r(re, cos_F), mult_r(im, sin_F)); + im = add(mult_r(re, sin_F), mult_r(im, cos_F)); + IF (LT_16(alpha[k], 32766)) + { + *seed = rand_phase_fx(*seed, &sin_F, &cos_F); + tmp2 = mult_r(beta[k], Xavg[k]); + *pReX++ = add( mult_r(alpha[k], tmp), mult_r(tmp2, cos_F) ); + move16(); + *pImX-- = add( mult_r(alpha[k], im), mult_r(tmp2, sin_F) ); + move16(); + } + ELSE + { + *pReX++ = mult_r(mag_chg[k], tmp); + move16(); + *pImX-- = mult_r(mag_chg[k], im); + move16(); + } + i = add(i, 1); + if (GE_16(i, gwlpr_fx[k+1])) + { + k = add(k, 1); + } + } + + e = add(pkLocation, delta_corr_up); + if (GT_16(e, lprotBy2Minus1)) + { + e = lprotBy2Minus1; + move16(); + } + + Xph = *pCorrPhase; + Xph_short = s_and(extract_l(L_shr(Xph, 16 - 10)), 0x3ff); /* 10 bits precision after radix point */ + IF (GE_16(Xph_short, 512)) + { + sin_F = negate(sincos_t_ext_fx[Xph_short - 512]); + IF (LT_16(Xph_short, 768)) + { + cos_F = negate(sincos_t_ext_fx[Xph_short - (512 - 256)]); + } + ELSE + { + cos_F = sincos_t_ext_fx[-Xph_short + (1024 + 256)]; + move16(); + } + } + ELSE + { + sin_F = sincos_t_ext_fx[Xph_short]; + move16(); + IF (LT_16(Xph_short, 256)) + { + cos_F = sincos_t_ext_fx[Xph_short + 256]; + move16(); + } + ELSE + { + cos_F = negate(sincos_t_ext_fx[-Xph_short + (256 + 512)]); + } + } + + segmentLen = add(sub(e, i), 1); + /* i = add(i, segmentLen); */ + FOR (j = 0; j < segmentLen; j++ ) + { + mag_chg_local = mag_chg[k]; + move16(); + IF (ph_dith != 0 ) + { + Xph = *pCorrPhase; /* in Q16. 2*PI is not included. */ + *seed = own_random2_fx(*seed); /* in Q0 */ + acc = L_mult(*seed, ph_dith); /* N.B. ph_dith[i] is in Q15, i.e., in between 0 and 1.0 (2*PI not included) */ + acc = L_shr(acc, PHASE_DITH_SCALE_SHIFT); + Xph = L_add(Xph, acc); /* in Q16. */ + + IF (ph_dith > 0 ) /* up to 6 dB additional att of peaks in non_transient longer bursts, (when peak phase is randomized ) */ + { + /* mag_chg_local *= 0.5 + (1.0 - ph_dith[i])/2 where 0.5~= sqrt((float)pow(10.0,-6/10.0)) and ph_dith=0..1.0--> scale=1.0 ...5 */ + mag_chg_local = mult_r(mag_chg_local, sub(32767, shr(ph_dith, 1))); + } + Xph_short = s_and(extract_l(L_shr(Xph, 16 - 10)), 0x3ff); + IF (GE_16(Xph_short, 512)) + { + sin_F = negate(sincos_t_ext_fx[Xph_short - 512]); + IF (LT_16(Xph_short, 768)) + { + cos_F = negate(sincos_t_ext_fx[Xph_short - (512 - 256)]); + } + ELSE + { + cos_F = sincos_t_ext_fx[-Xph_short + (1024 + 256)]; + move16(); + } + } + ELSE + { + sin_F = sincos_t_ext_fx[Xph_short]; + move16(); + IF (LT_16(Xph_short, 256)) + { + cos_F = sincos_t_ext_fx[Xph_short + 256]; + move16(); + } + ELSE + { + cos_F = negate(sincos_t_ext_fx[-Xph_short + (256 + 512)]); + } + } + } + + re = *pReX; + move16(); + im = *pImX; + move16(); + tmp = sub(mult_r(re, cos_F), mult_r(im, sin_F)); + im = add(mult_r(re, sin_F), mult_r(im, cos_F)); + IF (LT_16(alpha[k], 32766)) + { + alpha_local = mag_chg_local; + move16(); + + acc = L_sub(1073741824L, L_mult0(alpha_local, alpha_local)); + acc = Sqrt_l(acc, &expo); + expo = add(30, add(31, expo)); + if (EQ_16(s_and(expo, 1), 1)) + { + acc = Mult_32_16(acc, 23170); /* 1/sqrt(2) in Q15 */ + } + expo = shr(expo, 1); + beta_local = mult_r(beta_mute, round_fx(L_shl(acc, sub(31, expo)))); + + IF (GE_16(k, LGW32K-1)) + { + beta_local = mult_r(beta_local, 3277); /* 0.1 in Q15 */ + } + ELSE if (GE_16(k, LGW16K-1)) + { + beta_local = mult_r(beta_local, 16384); /* 0.5 in Q15 */ + } + + *seed = rand_phase_fx(*seed, &sin_F, &cos_F); + tmp2 = mult_r(beta_local, Xavg[k]); + *pReX++ = add( mult_r(alpha_local, tmp), mult_r(tmp2, cos_F) ); + move16(); + *pImX-- = add( mult_r(alpha_local, im), mult_r(tmp2, sin_F) ); + move16(); + } + ELSE + { + *pReX++ = mult_r(mag_chg_local, tmp); + move16(); + *pImX-- = mult_r(mag_chg_local, im); + move16(); + } + + i = add(i, 1); + if (GE_16(i, gwlpr_fx[k+1])) + { + k = add(k, 1); + } + } + pCorrPhase++; + } + + segmentLen = sub(shr(Lprot,1), i); + FOR (j = 0; j < segmentLen; j++) + { + *seed = rand_phase_fx(*seed, &sin_F, &cos_F); + + re = *pReX; + move16(); + im = *pImX; + move16(); + tmp = sub(mult_r(re, cos_F), mult_r(im, sin_F)); + im = add(mult_r(re, sin_F), mult_r(im, cos_F)); + IF (LT_16(alpha[k], 32766)) + { + *seed = rand_phase_fx(*seed, &sin_F, &cos_F); + tmp2 = mult_r(beta[k], Xavg[k]); + *pReX++ = add( mult_r(alpha[k], tmp), mult_r(tmp2, cos_F) ); + move16(); + *pImX-- = add( mult_r(alpha[k], im), mult_r(tmp2, sin_F) ); + move16(); + } + ELSE + { + *pReX++ = mult_r(mag_chg[k], tmp); + move16(); + *pImX-- = mult_r(mag_chg[k], im); + move16(); + } + + i = add(i, 1); + if (GE_16(i, gwlpr_fx[k+1])) + { + k = add(k, 1); + } + } +} + +/*-------------------------------------------------------------------------- + * rec_wtda() + * + * Windowing and TDA of reconstructed frame + *--------------------------------------------------------------------------*/ + +static void rec_wtda_fx( + Word16 *X, /* i : FFT spectrum */ + Word32 *ecu_rec, /* o : Reconstructed frame in tda domain */ + const Word16 output_frame, /* i : Frame length */ + const Word16 Lprot, /* i : Prototype frame length */ + const Word32 fs +) +{ + Word16 l, Lprot2, timesh; + Word16 rec_buf[3*L_FRAME48k]; + Word16 *xsubst_,*out_ptr; + Word16 Qin; + Word16 xf_len; + Word16 i, idx; + Word16 *p_ecu; + Word16 g; + Word16 tbl_delta; + + xsubst_ = rec_buf + output_frame; + Lprot2 = shr(Lprot, 1); + + /* Initialize to WB constants */ + xf_len = 26; + move16(); + tbl_delta = 10082; /* Q12 */ move16(); + IF (EQ_16(output_frame, L_FRAME48k)) + { + xf_len = 78; + move16(); + tbl_delta = 3361; /* Q12 */ move16(); + } + ELSE IF (EQ_16(output_frame, L_FRAME32k)) + { + xf_len = 52; + move16(); + tbl_delta = 5041; /* Q12 */ move16(); + } + + /* extract reconstructed frame with aldo window */ + l = sub(output_frame, Lprot2); + set16_fx(xsubst_,0 , l); + Copy(X, xsubst_ + l, Lprot); + set16_fx(xsubst_ + add(output_frame, Lprot2), 0, l); + + /* Smoothen onset of ECU frame */ + p_ecu = xsubst_ + (output_frame - Lprot2); + FOR ( i = 0; i < xf_len; i++) + { + idx = extract_l(L_shr(L_mult0(i, tbl_delta), 12)); + g = sincos_t_fx[idx]; + g = mult(g, g); + *p_ecu = mult(g, (*p_ecu)); + move16(); + p_ecu++; + } + + timesh = NS2SA_fx2(fs, 10000000L - PH_ECU_ALDO_OLP2_NS); + + set16_fx(rec_buf, 0, output_frame); + Qin = 0; + out_ptr = rec_buf + sub(shl(output_frame,1), timesh); + wtda_fx(out_ptr, &Qin, ecu_rec, NULL, 0, ALDO_WINDOW, ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */ + output_frame); + + return; +} + +/*-------------------------------------------------------------------------- + * rec_frame_fx() + * + * Frame reconstruction + *--------------------------------------------------------------------------*/ +static void rec_frame_fx( + Word16 *X, /* i : FFT spectrum */ + Word32 *ecu_rec, /* o : Reconstructed frame in tda domain */ + const Word16 output_frame, /* i : Frame length */ + const Word16 Q +) +{ + const Word16 *pFftTbl; + Word16 Lprot, lprotLog2Minus1; + Word32 fs; + + fs = L_mult0(output_frame, 50); + + /* Initialize to WB constants */ + Lprot = 512; + move16(); + lprotLog2Minus1 = 9 - 1; + move16(); + pFftTbl = FFT_W256; /* Table for 512-point real input FFT */ + IF (EQ_16(output_frame, L_FRAME48k)) + { + Lprot = Lprot48k; /* 1536 = (2*output_frame)*1024/1280 */ move16(); + } + ELSE IF (EQ_16(output_frame, L_FRAME32k)) + { + Lprot = Lprot32k; /* 1024 */ move16(); + lprotLog2Minus1 = 10 - 1; + move16(); + pFftTbl = FFT_W512; /* Table for 1024-point real input FFT */ + } + + /* extend spectrum and IDFT */ + IF (EQ_16(output_frame, L_FRAME48k)) + { + ifft3_fx(X, X, Lprot); + } + ELSE + { + r_fft_fx_lc(pFftTbl, Lprot, shr(Lprot, 1), lprotLog2Minus1, X, X, 0); /* Inverse FFT */ + } + Scale_sig(X, Lprot, -Q); + + rec_wtda_fx(X, ecu_rec, output_frame, Lprot, fs); + + return; +} + +static +Word32 mult_32_32_q(const Word32 a, const Word32 b, const Word16 q) +{ + Word32 hi; + UWord32 lo; + Mpy_32_32_ss(a, b, &hi, &lo); + + return L_or(L_shl(hi, 32 - q - 1), L_lshr(lo, q + 1)); +} + +static +void fir_dwn_fx( + const Word16 x[], /* i : input vector Q(x_Q) */ + const Word16 h[], /* i : impulse response of the FIR filter Q(h_Q) */ + const Word16 h_Q, /* H's Q */ + Word16 y[], /* o : output vector (result of filtering) Q~ */ + const Word16 L, /* i : input vector size */ + const Word16 K, /* i : order of the FIR filter (K+1 coefs.) */ + const Word16 decimation /* i : decimation */ +) +{ + Word32 s; + Word16 i, j; + const Word16 *ptr_h, *ptr_x; + Word16 *ptr_y; + Word16 Kdiv2; + Word16 centering; + Word16 tmp; + + centering = sub(16, h_Q); + Kdiv2 = shr(K,1); + + ptr_y = y; + /* do the filtering */ + FOR (i = Kdiv2; i < K; i+=decimation) + { + s = L_deposit_l(0); + ptr_h = h + 1; + ptr_x = x + i - 1; + move16(); + + FOR (j = 1; j <= i; j++) + { + s = L_mac0(s, *ptr_h++, *ptr_x--); + } + + *ptr_y++ = extract_h(L_shl(s, centering)); + } + FOR (i = K; i < L; i+=decimation) + { + s = L_deposit_l(0); + ptr_h = h + 1; + ptr_x = x + i - 1; + move16(); + + FOR (j = 1; j <= K; j++) + { + s = L_mac0(s, *ptr_h++, *ptr_x--); + } + + *ptr_y++ = extract_h(L_shl(s, centering)); + + } + tmp = add(L,Kdiv2); + FOR (i = i; i < tmp; i+=decimation) + { + s = L_deposit_l(0); + ptr_h = h + i - L + 1; + move16(); + ptr_x = x + L - 1; + move16(); + + FOR (j = add(sub(i,L),1); j <= K; j++) + { + s = L_mac0(s, *ptr_h++, *ptr_x--); + } + + *ptr_y++ = extract_h(L_shl(s, centering)); + } + + return; +} + +static +void fec_ecu_pitch_fx( + const Word16 *prevsynth_fx, /*Q15 16 */ + Word16 *prevsynth_LP_fx, /* Q15 16 */ + const Word16 L, + Word16 *N, + Word16 *min_corr_fx, /* Q15 16 */ + Word16 *decimatefator, + const Word16 HqVoicing +) +{ + + Word16 i,filt_size; + Word16 QAsr,Ryy,cb_start, tmpQLP; + Word32 Ryytmp; + Word32 accA,accB, accBisqrt,accC, accCisqrt; + Word16 delay_ind,k; + const Word16 *Asr_LP_fx; + Word16 *ptr_LP, *ptr_LP2, *ptr_LP3, *ptr_LP4; + Word16 cb_end; + Word16 Lmul2, Lon20mul6, Lon20mul28, Lon20mul33, Lon20mul34; + + + SWITCH(L) + { + case L_FRAME48k: + *decimatefator=6; + move16(); + filt_size=60; + move16(); + Asr_LP_fx = Asr_LP48_fx; + QAsr = 17; + move16(); + Lon20mul6 = 48; + move16(); + Lon20mul28 = 224; + move16(); + Lon20mul33 = 264; + move16(); + Lon20mul34 = 272; + move16(); + Lmul2 = 1920; + move16(); + BREAK; + + case L_FRAME32k: + *decimatefator=4; + move16(); + filt_size=40; + move16(); + Asr_LP_fx = Asr_LP32_fx; + QAsr = 15; + move16(); + Lon20mul6 = 48; + move16(); + Lon20mul28 = 224; + move16(); + Lon20mul33 = 264; + move16(); + Lon20mul34 = 272; + move16(); + Lmul2 = 1280; + move16(); + BREAK; + + case L_FRAME16k: + *decimatefator=2; + move16(); + filt_size=20; + move16(); + Asr_LP_fx = Asr_LP16_fx; + QAsr = 15; + move16(); + Lon20mul6 = 48; + move16(); + Lon20mul28 = 224; + move16(); + Lon20mul33 = 264; + move16(); + Lon20mul34 = 272; + move16(); + Lmul2 = 640; + move16(); + BREAK; + + default: + *decimatefator=2; + move16(); + filt_size=40; + move16(); + Asr_LP_fx = Asr_LP16_fx; + QAsr = 15; + move16(); + Lon20mul6 = 48; + move16(); + Lon20mul28 = 224; + move16(); + Lon20mul33 = 264; + move16(); + Lon20mul34 = 272; + move16(); + Lmul2 = 320; + move16(); + BREAK; + } + + + /* Resampling to work at 8Khz */ + fir_dwn_fx(prevsynth_fx, Asr_LP_fx, QAsr, prevsynth_LP_fx, Lmul2, filt_size, *decimatefator); /* resampling without delay */ + + + tmpQLP = Find_Max_Norm16(prevsynth_LP_fx,320); + Scale_sig(prevsynth_LP_fx,320,sub(tmpQLP,3)); /* to avoid over scaling */ + + + + /* Correlation analysis */ + *min_corr_fx = 0; + move16(); + accC = L_deposit_l(0); + + ptr_LP = prevsynth_LP_fx + Lon20mul34; + FOR (k = 0; k < Lon20mul6; k++) + { + accC = L_mac0 (accC, *ptr_LP, *ptr_LP); + ptr_LP++; + + } + + + + IF (HqVoicing==1) + { + cb_start=0; + cb_end=Lon20mul33; + } + ELSE + { + cb_start=0; + cb_end=Lon20mul28; + } + + accB=0; + delay_ind=cb_start; + + FOR (i=cb_start; i *min_corr_fx ) + { + *min_corr_fx = Ryy; + delay_ind = i; + } + + test(); + IF ( HqVoicing == 0 && *min_corr_fx > 31130) + { + BREAK; + } + } + + *N= sub(Lon20mul34, delay_ind); + + + Scale_sig(prevsynth_LP_fx,320,negate(sub(tmpQLP,3))); + return; +} + +static +void sin_cos_est_fx(Word32 phi, Word16 *cosfreq, Word16 *sinfreq) +{ + + + /* i phi : normalized frequency beteween 0 and Pi (nyquist) in Q30 */ + /* o cosfreq & sinfreq : cos(phi) and sin (phi) in Q15 */ + + Word16 i; + Word32 delta; + Word32 imin; + Word16 sinb, cosb; + Word32 sinv, cosv, tmp; + + i=0; + move16(); + FOR (imin=0; imin0 || HqVoicing */ + } + + + + + pt4 = pulses; + nb_pulses=0; + move16(); + PL=0; + move16(); + cpt=0; + move16(); + old=0; + move16(); + glued=1; + move16(); + new_s=Tf_abs[1]; + move16(); + if (flag ) + { + PL=1; + move16(); + } + tmp=sub(shr(N,1),3); + WHILE(LE_16(cpt,tmp)) + { + test(); + IF(GT_16(Tf_abs[cpt],old)&>_16(Tf_abs[cpt],new_s)) + { + Word16 tmp2; + + glued=cpt; + move16(); + + tmp2 = add(add(cpt,PL),1); + FOR (i=glued; i scaling of a_re is Qin+sN */ + *pt2++ = Tfi[indmax]; + move16(); /*L_shr(Tfi[indmax], sN); //instead shr -> scaling of a_im is Qin+sN */ + *pt3++ = indmax; + move16(); + Tf_abs[indmax] = -1; + move16(); + } + + } + ELSE + { + DO + { + mmax = 0; + move16(); + pt4 = pulses; + FOR ( k=0; k scaling of a_re is Qin+sN */ + *pt2++ = Tfi[indmax]; + move16(); /*L_shr(Tfi[indmax], sN); //instead shr -> scaling of a_im is Qin+sN */ + *pt3++ = indmax; + move16(); + Tf_abs[indmax] = -1; + move16(); + + maxi=sub(maxi,1); + } WHILE( maxi>0 && LT_32(cumsum, L_tmp)); + + nb_pulses_final = sub(nb_pulses_final,maxi); + move16(); + } + + + /* sinusoidal synthesis */ + + + set32_fx(synthesis_fx,0,Len); + + exp = add(exp,sN); + + + pt1 = a_re; + pt2 = a_im; + pt3 = freqi; + q = shr_r(N,2); + if (GT_16(N,shl(q,2))) + { + q = add(q,1); + } + + inv_den = i_mult2(N,decimate_factor); /*Q0 */ + + /*tmp = div_s(12868,inv_den);*/ /*Q15 */ + + + FOR ( i=0; i 0 ) + { + tmp_fx = Random(ni_seed_forfec); + + L_tmp = L_mac(1503264768, tmp_fx ,9830); + if ( kk == 0 ) + { + L_tmp = L_mac(1073741824, tmp_fx ,6554); + } + + kk = sub(1,kk) ; + tmp_fx = round_fx(L_tmp); + Rnd_N_noise = extract_h(L_mult(N_noise, tmp_fx)); /*Q0 */ + + + tmp_fx = div_s(1, Rnd_N_noise); /*Q15 */ + tmp_fx = round_fx(L_shl(L_mult(tmp_fx, 25736),2)); /*Q15 */ + + sinq_fx( shr(tmp_fx,1), shr(tmp_fx,2), Rnd_N_noise, SS_fx); + + pt2 = &noisevect_fx[N_noise]; + pt1 = pt2 - Rnd_N_noise; + pt3 = SS_fx; + pt4 = pt3 + sub(Rnd_N_noise,1); + tmp_fx = s_min(Rnd_N_noise, flag); + FOR ( i=0 ; i 0) + { + seed = add(seed, plocs[*num_p-1]); + } + + subst_spec_fx(plocs, plocsi, num_p, *time_offs, X, mag_chg, ph_dith, old_is_transient, output_frame, &seed, + alpha, beta, *beta_mute, Xavg); + + /* reconstructed frame in tda domain */ + rec_frame_fx(X, ecu_rec, output_frame, *Q_spec); + + *last_fec = 0; + *ph_ecu_active = 1; + move16(); +} + + +/*-------------------------------------------------------------------------- + * hq_ecu() + * + * Main routine for HQ ECU + *--------------------------------------------------------------------------*/ +void hq_ecu_fx( + const Word16 *prevsynth, /* i : buffer of previously synthesized signal */ + Word32 *ecu_rec, /* o : reconstructed frame in tda domain */ + Word16 *time_offs, /* i/o: Sample offset for consecutive frame losses */ + Word16 *X_sav, /* i/o: Stored spectrum of prototype frame */ + Word16 *Q_spec, /* i/o: Q value of stored spectrum */ + Word16 *num_p, /* i/o: Number of identified peaks */ + Word16 *plocs, /* i/o: Peak locations */ + Word32 *plocsi, /* i/o: Interpolated peak locations Q16 */ + const Word16 env_stab, /* i : Envelope stability parameter */ + Word16 *last_fec, /* i/o: Flag for usage of pitch dependent ECU */ + const Word16 ph_ecu_HqVoicing, /* i : HQ Voicing flag */ + Word16 *ph_ecu_active, /* i : Phase ECU active flag */ + Word16 *gapsynth, /* o : Gap synthesis */ + const Word16 prev_bfi, /* i : indicating burst frame error */ + const Word16 old_is_transient[2], /* i : flags indicating previous transient frames */ + Word16 *mag_chg_1st, /* i/o: per band magnitude modifier for transients */ + Word16 *Xavg, /* i/o: Frequency group average gain to fade to */ + Word16 *beta_mute, /* o : Factor for long-term mute */ + const Word16 output_frame, /* i : frame length */ + Decoder_State_fx *st_fx /* i/o: decoder state structure */ +) +{ + Word16 N; + Word16 decimatefactor; + Word16 corr; /*Q15 */ + Word16 prevsynth_LP[2*L_FRAME8k]; + + /* init (values ar changed after) */ + decimatefactor=4; + N=shr(output_frame,2); + + + /* find pitch and R value */ + + IF (!(LT_16(output_frame,L_FRAME16k))) + { + fec_ecu_pitch_fx( prevsynth+NS2SA(output_frame*50,ACELP_LOOK_NS/2-PH_ECU_LOOKAHEAD_NS), prevsynth_LP, output_frame, &N, &corr, &decimatefactor, ph_ecu_HqVoicing); + } + ELSE + { + corr = 0; + move16(); /* just to avoid using uninitialized value in if statement below */ + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF ( (GE_32(st_fx->total_brate_fx,48000)&& + ( GE_16(output_frame, L_FRAME16k) && !prev_bfi && (!old_is_transient[0] || old_is_transient[1] ) && (NE_16(ph_ecu_HqVoicing,0) || ( ((NE_16(st_fx->env_stab_plc_fx ,0)) && (LT_16(corr,19661))) || (!(NE_16(st_fx->env_stab_plc_fx ,0)) && (GT_16(corr, 27853)) ))))) || + (LT_32(st_fx->total_brate_fx,48000) && ( ( ph_ecu_HqVoicing || GT_16(corr, 27853)) && !prev_bfi && (!old_is_transient[0] || old_is_transient[1]) )) ) + { + fec_alg_fx( prevsynth+NS2SA(output_frame*50,ACELP_LOOK_NS/2-PH_ECU_LOOKAHEAD_NS), prevsynth_LP, &st_fx->ni_seed_forfec, ecu_rec, output_frame, N, decimatefactor, ph_ecu_HqVoicing, gapsynth); + + *last_fec = 1; + *ph_ecu_active = 0; + move16(); + *time_offs = output_frame; + move16(); + } + ELSE + { + hq_phase_ecu_fx( prevsynth, ecu_rec, time_offs, X_sav, Q_spec, num_p, plocs, plocsi, + env_stab, last_fec, ph_ecu_active, prev_bfi, old_is_transient, + mag_chg_1st, Xavg, beta_mute, st_fx->bwidth_fx, output_frame ); + } + + return; +} + +/******************************************************************************* + * The square root of x which MUST be 0.5 <= x < 1, i.e., x must be normalized. + * sqrt(x) is approximated by a polynomial of degree n. + * + * sqrt(x) = a0 x^n + a1 x^(n-1) + a2 x^(n-2) + ... + an + * = (...((a0 x + a1) x + a2) x + ...) x + an + * + * The coefficients can be readily obtained by the following open source Octave + * (or commercial Matlab) script: + * order = 2; + * N = 400; + * x = linspace(0.5, 1.0, N); + * y = sqrt(x); + * p = polyfit(x, y, order) + * z = polyval(p, x); + * err = y - z; + * plot(err); + ******************************************************************************/ + +static Word16 sqrt2ndOrder( /* o: in Q15 (2nd order least square approx.) */ + const Word16 x /* i: x must be in between 0.5 and 1.0 (Q15). */ +) +{ + Word32 acc; + Word16 z; + + acc = 1890205600L; /* 0.880195572812922 in Q31 */ move32(); + z = mac_r(acc, x, -6506); /* -0.198537395405340 in Q15 */ + acc = 682030261L; /* 0.317595089462249 in Q31 */ move32(); + z = mac_r(acc, z, x); /* in Q15 */ + return z; +} + +/*----------------------------------------------------------------------------- + * windowing() + * + * Apply a symmetric Hamming or Hamming-Rectangular window to the signal. + * If the "rectLength" parameter is zero, it is Hamming window; otherwise, the + * rectLength signifies the length of the rectangular part of the Hamming-Rectangular + * window. + *--------------------------------------------------------------------------- */ +static void windowing( + const Word16 *x, /* i: Input signal */ + Word16 *y, /* o: Windowed output */ + const Word16 *win, /* i: Window coefficients */ + const Word16 rectLength, /* i: Offset in between the 1st and 2nd symmetric halves of the Hamming window */ + const Word16 halfLength /* i: Half of the total length of a complete Hamming window. */ +) +{ + Word16 i; + Word16 *pY; + const Word16 *pX, *pW; + pX = x; + pW = win; + pY = y; + FOR (i = 0; i < halfLength; i++) /* 1st symmetric half of the Hamming window */ + { + *pY++ = mult_r(*pX++, *pW++); + move16(); + } + FOR (i = 0; i < rectLength; i++) /* If rectLength is zero, it's a pure Hamming window; otherwise Hamming-Rectangular. */ + { + *pY++ = *pX++; + move16(); + } + FOR (i = 0; i < halfLength; i++) /* 2nd symmetric half of the Hamming window. */ + { + *pY++ = mult_r(*pX++, *(--pW)); + move16(); + } +} + +/*----------------------------------------------------------------------------- + * windowing_ROM_optimized() + * + * The coefficients of the Hamming window are derived from the sine table + * shared with fft3_fx(). + * The entire Hamming-Rectangular window is decomposed into 5 segments: + * 1. 1st half of the left half of the Hamming window + * 2. 2nd half of the left half of the Hamming window + * 3. The flat part of the rectangular region + * 4. 1st half of the right half of the Hamming window + * 5. 2nd half of the right half of the Hamming window + *----------------------------------------------------------------------------*/ +static void windowing_ROM_optimized( + const Word16 *x, /* i: Input signal */ + Word16 *y, /* o: Windowed output */ + const Word16 downSamples,/* i: Offset in accessing the sine table. */ + const Word16 rectLength, /* i: Length of the rectangular portion (excluding the Hamming window part) */ + const Word16 halfLength /* i: Half of the total length of the Hamming (excluding rectangular part) window */ +) +{ + Word16 i, hamm, quarterLen, initOffset; + Word16 *pY; + const Word16 *pX, *pSine; + Word32 acc; + + quarterLen = shr(halfLength, 1); /* 1/4 length of the entire Hamming (excluding the rectangular part) window. */ + initOffset = add(T_SIN_PI_2, shr(downSamples,1)); + pSine = sincos_t_rad3_fx + initOffset; + pX = x; + pY = y; + + /* 1st half of the left half of the Hamming window. */ + FOR (i = 0; i < quarterLen; i++) + { + pSine -= downSamples; /* Decrement address counter */ + acc = L_deposit_h(FEC_HQ_WIN_A0); /* Derive the Hamming window coefficient from the sine table. */ + hamm = msu_r(acc, *pSine, FEC_HQ_WIN_A1); + *pY++ = mult_r(hamm, *pX++); + move16(); + } + + /* 2nd half of the left half of the Hamming window. */ + FOR (i = 0; i < quarterLen; i++) + { + acc = L_deposit_h(FEC_HQ_WIN_A0); + hamm = mac_r(acc, *pSine, FEC_HQ_WIN_A1); + *pY++ = mult_r(hamm, *pX++); + move16(); + pSine += downSamples; /* Increment address counter */ + } + + /* The rectangular flat region */ + FOR (i = 0; i < rectLength; i++) + { + *pY++ = *pX++; + move16(); + } + + /* 1st half of the right half of the Hamming window. */ + FOR (i = 0; i < quarterLen; i++) + { + pSine -= downSamples; /* Decrement address counter */ + acc = L_deposit_h(FEC_HQ_WIN_A0); + hamm = mac_r(acc, *pSine, FEC_HQ_WIN_A1); + *pY++ = mult_r(hamm, *pX++); + move16(); + } + + /* 2nd half of the right half of the Hamming window. */ + FOR (i = 0; i < quarterLen; i++) + { + acc = L_deposit_h(FEC_HQ_WIN_A0); + hamm = msu_r(acc, *pSine, FEC_HQ_WIN_A1); + *pY++ = mult_r(hamm, *pX++); + move16(); + pSine += downSamples; /* Increment address counter */ + } +} diff --git a/lib_dec/FEC_adapt_codebook_fx.c b/lib_dec/FEC_adapt_codebook_fx.c new file mode 100644 index 0000000..772d7f2 --- /dev/null +++ b/lib_dec/FEC_adapt_codebook_fx.c @@ -0,0 +1,536 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_dec_fx.h" /* Decoder static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + + +/*---------------------------------------------------------------------* + * FEC_SinOnset() + * + * Create an artificial onset when it is lost + *---------------------------------------------------------------------*/ +Word16 FEC_SinOnset_fx ( + Word16 *exc, /* i/o : exc vector to modify */ + Word16 puls_pos, /* i : last pulse position desired */ + const Word16 T0, /* i : Pitch information of the 1 subfr */ + Word32 enr_q, /* i : energy provide by the encoder */ + Word16 *Aq, /* i : A(z) filter Q12 */ + const Word16 L_frame /* i : frame length */ + ,const Word16 Qold +) +{ + Word16 P0, onset_len, sign, i, len, L_subfr, L_subfr2; + Word16 h1[L_SUBFR16k], mem[M], exc_tmp[L_FRAME16k+ MODE1_L_FIR_FER]; + Word16 *pt_end, *pt_exc, enr_LP, gain, H_low_s[5], exp_gain, exp2, tmp; + Word32 L_tmp; + Word16 Q_exc; + + sign = 0; + move16(); + Q_exc = Qold; + move16(); + L_subfr = L_SUBFR; + move16(); + if( EQ_16(L_frame,L_FRAME16k)) + { + L_subfr = L_SUBFR16k; + move16(); + } + + L_subfr2 = shl(L_subfr,1); + onset_len = s_max(T0, L_subfr2); + + P0 = puls_pos; + move16(); + + IF (P0 < 0) + { + sign = 1; + move16(); + P0 = negate(P0); + } + + test(); + test(); + IF ( GT_16(P0,PIT_MAX)&&EQ_16(L_frame,L_FRAME)) + { + P0 = PIT_MAX; + move16();/* Should never be the case, however... */ + } + ELSE if ( GT_16(P0,PIT16k_MAX)&&EQ_16(L_frame,L_FRAME16k)) + { + P0 = PIT16k_MAX; + move16(); /* Should never be the case, however... */ + } + set16_fx( exc_tmp, 0, add(L_frame, MODE1_L_FIR_FER)); /* Reset excitation vector */ + + /*-------------------------------------------------------------------------------* + * Find LP filter impulse response energy and Generate the scaled pulse prototype + *-------------------------------------------------------------------------------*/ + + set16_fx(h1, 0, L_subfr); /* Find the impulse response */ + set16_fx(mem, 0, M); + h1[0] = 1024; + move16(); + Syn_filt_s(1, Aq, M, h1, h1, L_subfr, mem, 0); + + + enr_LP = extract_h(Dot_product12(h1, h1, L_subfr, &exp_gain)); + exp_gain = sub(exp_gain, 10 + 10); /* h1 in Q10 */ + + /* divide by LP filter E, scaled by transmitted E */ + /* gain = (float)sqrt( enr_q / enr_LP ); */ + + enr_q = L_max(enr_q,1); + + exp2 = norm_l(enr_q); + tmp = extract_h(L_shl(enr_q, exp2)); + tmp = mult(tmp, 24576); /* multpiply by 1.5 */ + + IF(LT_16(tmp, 16384)) + { + exp2 = add(exp2, 1); + tmp = shl(tmp, 1); + } + exp2 = sub(30, exp2); /* in Q15 */ + + + IF(GT_16(enr_LP, tmp)) + { + enr_LP = shr(enr_LP, 1); + exp_gain = add(exp_gain, 1); + } + + tmp = div_s(enr_LP, tmp); + exp2 = sub(exp_gain, exp2); + + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp2); + gain = round_fx(L_tmp); + + gain = mult_r(gain, 31457); /* multiply by .96 like floating point */ + exp2 = add(sub(exp2, 15), Q_exc); /* from Q15 to Q_exc */ + + /* Find if rescaling needed */ + tmp = extract_h(L_mult(H_low[2], gain)); + exp_gain = norm_s(tmp); + tmp = sub(exp_gain, exp2); /* difference */ + + IF(tmp < 0)/* Need to correct scaling */ + { + Q_exc = add(Q_exc, tmp); + exp2 = add(exp2, tmp); + } + /* Scale pulse "prototype" energy */ + /* Generate the scaled pulse */ + FOR(i = 0; i < MODE1_L_FIR_FER; i++) + { + L_tmp = L_mult(gain, H_low[i]); /* Q_exc*Q15 -> Q_exc */ + H_low_s[i] = round_fx(L_shl(L_tmp, exp2)); + } + /*------------------------------------------------------------------------------------------* + * Construct the harmonic part as a train of low-pass filtered pulses + *------------------------------------------------------------------------------------------*/ + move16(); + move16(); + move16(); + pt_exc = exc_tmp + sub(L_frame, add(add(1, MODE1_L_FIR_FER/2), P0)); /* beginning of the 1st pulse */ + pt_end = exc_tmp + onset_len; + len = (Word16) (pt_exc - pt_end); + + len = s_min(len, MODE1_L_FIR_FER); + IF(!sign) + { + + FOR(i = 0; i < len; i++) + { + /* The filter response would have E=1 in full band. */ + pt_exc[i] = add(pt_exc[i], H_low_s[i]); + move16(); + } + } + ELSE + { + FOR(i = 0; i < len; i++) + { + /* The filter response would have E=1 in full band. */ + pt_exc[i] = sub(pt_exc[i], H_low_s[i]); + move16(); + } + } + Copy(&exc_tmp[L_frame - L_EXC_MEM], exc, L_EXC_MEM); + return Q_exc; +} + +Word16 FEC_enhACB_fx( + const Word16 L_frame, /* i : frame length */ + const Word16 last_L_frame, /* i : frame length of previous frame */ + Word16 *exc_io, /* i/o : adaptive codebook memory */ + const Word16 new_pit, /* i : decoded first frame pitch */ + const Word16 puls_pos, /* i : decoder position of the last glottal pulses decoded in the previous frame */ + const Word16 bfi_pitch /* i : Q6 pitch used for concealment */ +) +{ + Word16 Tc, P0, sign, pit_search; + Word16 Tlist[10], Terr, diff_pit, dist_Plast; + Word16 tmp2; + Word16 exc[L_FRAME16k + L_SUBFR]; + Word16 Do_WI = 1; + move16(); + + + set16_fx(exc, 0, L_FRAME16k - L_EXC_MEM); + set16_fx(exc+L_FRAME16k, 0, L_SUBFR); + Copy(exc_io, exc + L_FRAME16k - L_EXC_MEM, L_EXC_MEM); + + Tc = shr(bfi_pitch,6); + Copy(exc + L_FRAME16k - Tc, exc + L_FRAME16k, L_SUBFR); + + /*------------------------------------------------------------ + * Decode phase information transmitted in the bitstream + * (The position of the absolute maximum glottal pulse from + * the end of the frame and its sign) + *------------------------------------------------------------*/ + + P0 = puls_pos; + move16(); + sign = 0; + move16(); + IF (P0 < 0) + { + sign = 1; + move16(); + P0 = negate(P0); + } + + IF( EQ_16(L_frame,L_FRAME)) + { + P0 = s_min(PIT_MAX, P0); + } + ELSE /* L_frame == L_FRAME16k */ + { + P0 = s_min(PIT16k_MAX, P0); + } + + /*---------------------------------------------------------------------------------- + * Find the position of the first the maximum(minimum) lp_filtered pulse + * <----- Mem --->|<--------------------- L_frame ------------>|<----- L_SUBFR --->| + * |<-------pit_search----> | | + *----------------------------------------------------------------------------------*/ + + pit_search = Tc; + move16(); + + Tlist[0] = findpulse_fx( L_frame, exc+sub(L_frame,pit_search) , pit_search,DEC, &sign); + + /*Terr = (short) abs(pit_search-Tlist[0]-P0);*/ + Terr = abs_s(sub(pit_search,add(Tlist[0],P0))); + + dist_Plast = sub(Tc,Tlist[0]); + + Tlist[1] = findpulse_fx( L_frame, exc+sub(L_frame,pit_search) , add(pit_search,L_SUBFR),DEC, &sign); + + + /*if(Terr > abs(Tlist[1]-Tc + P0))*/ + IF(GT_16(Terr,abs_s(add(sub(Tlist[1],Tc), P0)))) + { + dist_Plast = sub(Tc,Tlist[1]); + Terr = abs_s(add(sub(Tlist[1],Tc), P0)); + } + + diff_pit = abs_s(sub(new_pit, Tc)); + /*ftmp = (float) (int)((float)L_frame/(float)Tc+0.5);*/ + tmp2 = mult_r(div_s(16, Tc), shr(L_frame,4)); + test(); + test(); + IF (LE_16(Terr, i_mult(tmp2, diff_pit))&& + Terr != 0 && /* If Terr = 0, no resynchronization required */ + sub(Terr, L_SUBFR) < 0 )/* prevent catastrophy search */ + { + /* performe excitation resynchronization here */ + Do_WI = FEC_synchro_exc_fx( L_frame, exc, P0, dist_Plast, Tc ); + move16(); + Copy(exc + L_FRAME16k - L_EXC_MEM, exc_io, L_EXC_MEM); + } + ELSE + { + Do_WI = 0; + move16(); + } + + if( NE_16(last_L_frame, L_FRAME16k)) + { + Do_WI = 0; + move16(); + } + + return Do_WI; +} + +Word16 FEC_synchro_exc_fx( /* o : do_WI flag */ + const Word16 L_frame, /* i : length of the frame */ + Word16 *exc, /* i/o: exc vector to modify */ + const Word16 desire_puls_pos, /* i : Pulse position send by the encoder */ + const Word16 true_puls_pos, /* i : Present pulse location */ + const Word16 Old_pitch /* i : Pitch use to create temporary adaptive codebook */ +) +{ + Word16 exc_tmp[L_FRAME16k+L_SUBFR]; + Word16 fact; + Word32 L_min_energy, L_tmp; + Word16 *pt_exc, *pt_exc1; + Word16 i, j, point_to_remove, point_to_add, nb_min; + Word16 min_pos[L_FRAME16k/PIT_MIN_DOUBLEEXTEND], points_by_pos[L_FRAME16k/PIT_MIN_DOUBLEEXTEND]; + Word16 total_point, tmp_len; + Word16 *pt_pos, pos, start_search, tmp16; + Word16 remaining_len; + + point_to_add = -1; + move16(); + + /* Init */ + FOR (i = 0; i < L_FRAME16k/PIT_MIN_DOUBLEEXTEND; i++) + { + min_pos[i] = 10000; + move16(); + points_by_pos[i] = 0; + move16(); + } + + /* Find number of point to remove and number of minimum */ + point_to_remove = sub(true_puls_pos, desire_puls_pos); /* if it is negative it means remove point else it means add point */ + + pos = sub(L_frame, true_puls_pos); + + /* Find number of minimum energy region */ + /* nb_min = (L_FRAME - true_puls_pos)/Old_pitch */ + tmp16 = shl(Old_pitch, 5); + tmp16 = div_s(pos, tmp16); + nb_min = shr(tmp16, 10); + /* if Old pitch < 128, must have at least 2 min */ + if (LE_16(Old_pitch, 128)) + { + nb_min = s_max(nb_min, 2); + } + /* Must have at least 1 min */ + nb_min = s_max(nb_min, 1); + + pt_exc = exc + pos; + move16(); + + /* Find starting point for minimum energy search */ + start_search = mult_r(Old_pitch, -24576); + if(EQ_16(s_and(Old_pitch,3),1)) + { + /* Only be align with integer operation -3*Old_pitch/4 */ + start_search = add(start_search,1); + } + IF (add(start_search, pos) < 0) + { + start_search = negate(pos); + IF (LT_16(abs_s(start_search), shr(Old_pitch, 3))) + { + /* it's not safe to remove/add point inside 1/8 of the pulse position */ + return 0; + } + } + + /* Find min energy in the first pitch section */ + /* -------------------------------------------------------------------- + * The minimum energy regions are determined by the computing the energy + * using a sliding 5-sample window. The minimum energy position is set + * at the middle of the window at which the energy is at minimum + * --------------------------------------------------------------------*/ + L_min_energy = L_add(MAX_32, 0); + L_tmp = L_mult(pt_exc[start_search], pt_exc[start_search]); + L_tmp = L_mac(L_tmp, pt_exc[start_search + 1], pt_exc[start_search + 1]); + L_tmp = L_mac(L_tmp, pt_exc[start_search + 2], pt_exc[start_search + 2]); + L_tmp = L_mac(L_tmp, pt_exc[start_search + 3], pt_exc[start_search + 3]); + L_tmp = L_mac(L_tmp, pt_exc[start_search + 4], pt_exc[start_search + 4]); + + IF (LT_32(L_tmp, L_min_energy)) + { + L_min_energy = L_add(L_tmp, 0); + min_pos[0] = add(add(pos, start_search), 2); + } + + FOR (i = start_search; i < -5; i++) + { + L_tmp = L_msu(L_tmp, pt_exc[i], pt_exc[i]); + L_tmp = L_mac(L_tmp, pt_exc[i + 5], pt_exc[i + 5]); + + IF (LT_32(L_tmp, L_min_energy)) + { + L_min_energy = L_tmp; /* sets to 'L_tmp' in 1 clock */ + move32(); + min_pos[0] = add(add(pos, i), 2); + } + } + + FOR (j = 1; j < nb_min; j++) + { + min_pos[j] = sub(min_pos[j-1], Old_pitch); + /* If the first minimum is in the past, forget this minimum */ + IF (min_pos[j] < 0) + { + min_pos[j] = -10000; + move16(); + nb_min = sub(nb_min, 1); + } + } + + /* safety-measure against not properly initialized min_pos[] */ + IF( GE_32(L_min_energy, MAX_32)) + { + return 0; + } + + IF(GT_16(nb_min,16)) /* inv_sqi & sqi are built for a maximum of nb_min-2 = 14 values*/ + { + return 0; + } + /*-------------------------------------------------------------------- + * Determine the number of samples to be added or removed at each pitch + * cycle whereby less samples are added/removed at the beginning and + * more towards the end of the frame + * --------------------------------------------------------------------*/ + test(); + IF (EQ_16(nb_min, 1)||EQ_16(abs_s(point_to_remove),1)) + { + nb_min = 1; + move16(); + points_by_pos[0] = abs_s(point_to_remove); + } + ELSE + { + /* First position */ + /* fact = (float)fabs(point_to_remove) / sqi[nb_min-2]; (nb_min*nb_min) */ + fact = mult_r(shl(abs_s(point_to_remove), 7), inv_sqi[nb_min - 2]); /*Q7 */ + points_by_pos[0] = mult_r(fact, 256); /*Q7 */ + total_point = points_by_pos[0]; + move16(); + + FOR (i = 2; i <= nb_min; i++) + { + /* points_by_pos[i-1] = (Word16)(fact*(sqi[i-2]) - total_point+0.5) */ + points_by_pos[i - 1] = sub(shr(extract_l(L_mac0(64L, fact, sqi[i - 2])), 7), total_point); + total_point = add(total_point, points_by_pos[i-1]); + + /* ensure a constant increase */ + IF (LT_16(points_by_pos[i-1], points_by_pos[i-2])) + { + tmp16 = points_by_pos[i-2]; + move16(); + points_by_pos[i-2] = points_by_pos[i-1]; + move16(); + points_by_pos[i-1] = tmp16; + move16(); + } + } + } + /* -------------------------------------------------------------------- + * Sample deletion or insertion is performed in minimum energy regions. + * At the end of this section the last maximum pulse in the concealed + * excitation is forced to align to the actual maximum pulse position + * at the end of the frame which is transmitted in the future frame. + * --------------------------------------------------------------------*/ + if (point_to_remove > 0) + { + point_to_add = point_to_remove; + move16(); + } + + pt_exc = exc_tmp; + move16(); + pt_exc1 = exc; + move16(); + + i = 0; + move16(); + pt_pos = min_pos + sub(nb_min, 1); + + IF (point_to_add > 0)/* Samples insertion */ + { + remaining_len = L_frame; + move16(); + FOR (i = 0; i < nb_min; i++) + { + /* Copy section */ + /* Compute len to copy */ + tmp_len = *pt_pos; + move16(); + IF (i != 0) + { + /* Compute len to copy */ + tmp_len = sub(sub(*pt_pos, *(pt_pos+1)), points_by_pos[i-1]); + } + /*Copy section */ + Copy(pt_exc1, pt_exc, tmp_len); + remaining_len = sub(remaining_len, tmp_len); + pt_exc1 += tmp_len; + move16(); + pt_exc += tmp_len; + move16(); + + /* Find point to add and Add points */ + tmp16 = mult_r(*pt_exc1, -1638); + FOR (j = 0; j < points_by_pos[i]; j++) + { + *pt_exc++ = tmp16; + move16();/* repeat last point */ + tmp16 = negate(tmp16); + } + + remaining_len = sub(remaining_len, points_by_pos[i]); + pt_pos--; + } + /* Copy remaining data */ + remaining_len = s_max(0, remaining_len); + Copy(pt_exc1, pt_exc, remaining_len); + /* Update true excitation vector */ + Copy(exc_tmp, exc, L_frame); + } + ELSE /* Samples deletion */ + { + remaining_len = L_frame; + move16(); + + FOR (i = 0; i < nb_min; i++) + { + /* Compute len to copy */ + tmp_len = *pt_pos; + move16(); + IF (i != 0) + { + /* Compute len to copy */ + tmp_len = sub(sub(*pt_pos, *(pt_pos+1)), points_by_pos[i-1]); + } + Copy(pt_exc1, pt_exc, tmp_len); + remaining_len = sub(remaining_len, tmp_len); + pt_exc1 += tmp_len; + move16(); + pt_exc += tmp_len; + move16(); + /* Remove points */ + FOR (j = 0; j < points_by_pos[i]; j++) + { + pt_exc1++; + } + pt_pos--; + } + /* Copy remaining data */ + remaining_len = s_max(0, remaining_len); + Copy(pt_exc1, pt_exc, remaining_len); + /* Update true excitation vector */ + Copy(exc_tmp, exc, L_frame); + } + + return 1; + +} diff --git a/lib_dec/FEC_clas_estim_fx.c b/lib_dec/FEC_clas_estim_fx.c new file mode 100644 index 0000000..6c29507 --- /dev/null +++ b/lib_dec/FEC_clas_estim_fx.c @@ -0,0 +1,937 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "basop_util.h" + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static Word16 FEC_dec_class_fx( Decoder_State_fx *st_fx, const Word32 bitrate, const Word16 coder_type, Word32 *enr_q, const Word16 last_good); + +static void Corre(const Word16 *x,const Word16 *y,const Word16 l,Word16 *gain); + +/*---------------------------------------------------------------------* + * Local Constants + *---------------------------------------------------------------------*/ +#define UNS6 10923/2 +#define UNS5 13107/2 + +#define K_COR_FX 14004 /* Q14 0.8547f <-0.29, 0.88> */ +#define C_COR_FX 266180599 /* Q14+16 0.2479f */ + +#define K_TILT_FX 13653 /*Q14 0.8333f <-0.35, 0.85> */ +#define C_TILT_FX 313210491 /*Q14+16 0.2917f */ + +#define K_ZC_FX -1310 /*Q15 -0.04f <63, 38> */ +#define C_ZC_FX 2642416 /*11Q20 2.52 */ + +#define K_ENR_FX 1311 /*Q15 0.04 <-14, 11> */ +#define C_ENR_FX 9395241 /*Q8+16 0.56f */ + +#define K_PC_FX -1169 /*Q15 -0.0357f <45, 17> */ +#define C_PC_FX 105323 /*Q0+16 1.6071f */ + + + +/*======================================================================*/ +/* FUNCTION : FEC_clas_estim() */ +/*----------------------------------------------------------------------*/ +/* PURPOSE : Estimation of classification */ +/* information, if not available in the bitsream */ +/* */ +/*======================================================================*/ + +void FEC_clas_estim_fx( + Decoder_State_fx *st_fx , /* i/o: decoder state handle */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ /*A*/ + const Word16 L_frame, /* i : length of the frame */ + Word16 *clas, /* i/o: frame classification */ + const Word16 coder_type, /* i : coder type */ + const Word16 *pitch, /* i : pitch values for each subframe (Q6)*/ + Word16 *syn, /* i : synthesis buffer */ + Word16 *lp_speech, /* i/o: long term active speech energy average Q8 */ + Word16 *decision_hyst, /* i/o: hysteresis of the music/speech decision */ /*A*/ + Word16 *UV_cnt, /* i/o: number of consecutives frames classified as UV */ /*A*/ + Word16 *LT_UV_cnt, /* i/o: long term consecutives frames classified as UV */ /*A*/ + Word16 *Last_ener, /* i/o: last_energy frame */ /*A*/ + Word16 *locattack, /* i/o: detection of attack (mainly to localized speech burst) */ /*A*/ + Word16 *lt_diff_etot, /* i/o: long-term total energy variation */ /*A*/ + Word16 *amr_io_class, /* i/o: classification for AMR-WB IO mode */ /*A*/ + const Word32 bitrate, /* i : Decoded bitrate */ /*A*/ + Word16 Q_syn, /* i : Synthesis scaling */ + Word16 *class_para, /* o : classification para. fmerit1 */ /*A*/ + Word16 *mem_syn_clas_estim, /* i/o: memory of the synthesis signal for frame class estimation */ + Word16 *Q_mem_syn, /* i/o: exponent for memory of synthesis signal for frame class estimation */ /*B*/ + Word16 LTP_Gain, /* i : LTP gain is 0..0.6 or -1 Q15 *//*B*/ + Word16 mode, /* i : signal classifier mode *//*B*/ + Word16 bfi, /* i : bad frame indicator *//*B*/ + Word32 last_core_brate /* i : bitrate of previous frame */ +) +{ + Word16 i, j, pos; + Word16 *pt1, *pt2, zc_frame, frame_ener =1 ,tmp_scale=0, tmp_scale_syn, tmp_scale_mem; + Word16 tiltn, corn, zcn, pcn, fmerit1, enern, ener = 0/*not necessary, just to quiet a warning so not cmplxty counted*/, tilt, diff_ener; + Word16 voicing, cor_max[4], *synth, tmp16, exp1, exp2; + Word32 Ltmp, Ltmp1; + Word16 tmpS, T0, pc, /*max,*/ tmp_x, tmp_y; + Word16 old_synth[L_SYN_MEM_CLAS_ESTIM + L_FRAME16k]; + Word16 nb_subfr; + Word16 pos_limit; + Word16 codec_mode, narrowBand, tcxonly,preemph_fac; + Word16 memmax; + + nb_subfr = shr(L_frame,6); + memmax = 0; + move16(); + tmp_scale_syn = 0; + move16(); + + codec_mode = st_fx->codec_mode; + tcxonly = st_fx->tcxonly; /* i : tcxonly flag *//*B*/ + narrowBand = st_fx->narrowBand; /* i : narrowband flag *//*B*/ + preemph_fac = st_fx->preemph_fac; /* i : preemphasis factor *//*B*/ + /*------------------------------------------------------------------------* + * Copy synthesized into local buffer + *------------------------------------------------------------------------*/ + + /* After Rate Switching st->last_core is reset to 0. Check for last_core_brate is needed */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF((EQ_32(last_core_brate, SID_1k75)||EQ_32(last_core_brate,ACELP_6k60)||EQ_32(last_core_brate,ACELP_8k85) + || EQ_32(last_core_brate, ACELP_12k65) || EQ_32(last_core_brate, ACELP_14k25) || EQ_32(last_core_brate, ACELP_15k85) + || EQ_32(last_core_brate, ACELP_18k25) || EQ_32(last_core_brate, ACELP_19k85) || EQ_32(last_core_brate, ACELP_23k05) + || EQ_32(last_core_brate, ACELP_23k85)) && !Opt_AMR_WB && EQ_16(codec_mode, MODE2) + && GT_16(L_frame,L_FRAME) ) + { + Word16 oldLenClasBuff, newLenClasBuff; + oldLenClasBuff = extract_l(L_shr(Mpy_32_16_1(L_mult0(st_fx->last_L_frame_fx,getInvFrameLen(st_fx->L_frame_fx)/*Q21*/)/*Q21*/,L_SYN_MEM_CLAS_ESTIM/*Q0*/)/*Q6*/,6)/*Q0*/); + newLenClasBuff = L_SYN_MEM_CLAS_ESTIM; + move16(); + lerp( &mem_syn_clas_estim[L_SYN_MEM_CLAS_ESTIM-oldLenClasBuff], &mem_syn_clas_estim[L_SYN_MEM_CLAS_ESTIM-newLenClasBuff], newLenClasBuff, oldLenClasBuff ); + } + synth = old_synth + L_SYN_MEM_CLAS_ESTIM; + + /*Rescale synthesis mem buffer or synthesis buffer, if necessary - + allign them to the same scaling in case of switching MODE2->MODE1*/ + IF(EQ_16(codec_mode, MODE2)) + { + memmax=1; + move16(); + /*find maximum of mem syn*/ + FOR(i=0; i0) /*mem syn is bigger, scale it down*/ + { + tmp_scale_mem = negate(tmp_scale); + Scale_sig(mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM, tmp_scale_mem); + } + ELSE /*synthesis is bigger, scale it down*/ + { + /*check for upscaling mem syn, first*/ + tmp_scale_mem = norm_s(sub(memmax,1)); + if (EQ_16(memmax,1)) + { + tmp_scale_mem = 14; + move16(); + } + tmp_scale_syn = sub(add(*Q_mem_syn, tmp_scale_mem), Q_syn); /*if this is negative, syn can be scaled down*/ + test(); + IF(tmp_scale_syn > 0 || EQ_16(mode , 1/*CLASSIFIER_TCX*/)) /*dont scale up syn, but scale mem_syn, adequately*/ + { + tmp_scale_mem = sub(tmp_scale_mem,tmp_scale_syn); + tmp_scale_syn = 0; + move16(); + } + + Scale_sig( mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM, tmp_scale_mem ); + *Q_mem_syn = add(*Q_mem_syn, tmp_scale_mem); + } + + } + + tmp_scale = -1; + move16(); + + Copy_Scale_sig( mem_syn_clas_estim, old_synth, L_SYN_MEM_CLAS_ESTIM, tmp_scale ); + Copy_Scale_sig( syn, synth, L_frame, add(tmp_scale_syn, tmp_scale) ); + + /*Tell MODE2 decoder the scaling of the buffer*/ + *Q_mem_syn = add(add(Q_syn, tmp_scale_syn), tmp_scale); + + /**Q_mem_syn = *Q_syn; move16();*/ + + test(); + IF(EQ_16(codec_mode,MODE2)&&EQ_16(mode,1/*CLASSIFIER_TCX*/)) + { + /* TCX outputs non-pe-speech */ + move16(); + tmp16 = shl(syn[-1],tmp_scale); /*dont forget to scale the mem*/ + preemph_copy_fx(synth, synth, preemph_fac, L_frame, &tmp16); + } + + /*------------------------------------------------------------------------* + * GC, TC and AC frames + *------------------------------------------------------------------------*/ + /* Do the classification only + - MODE1: when the class is not transmitted in the bitstream + - MODE2: on good frames (classifier is also called for bfi=1) */ + test(); + test(); + test(); + test(); + test(); + test(); + IF (( EQ_16(codec_mode , MODE1)&&(LT_32(bitrate,ACELP_11k60) + || LE_16(coder_type , UNVOICED) || Opt_AMR_WB)) || + (EQ_16(codec_mode , MODE2) && NE_16(bfi,1) && !tcxonly )) + + { + /*------------------------------------------------------------------------* + * Overwrite classification decision using coder_type information + *------------------------------------------------------------------------*/ + test(); + IF( EQ_16(coder_type,VOICED)) + { + *clas = VOICED_CLAS; + move16(); + } + ELSE IF( EQ_16(coder_type,UNVOICED)) + { + *clas = UNVOICED_CLAS; + move16(); + } + ELSE IF( EQ_16(coder_type,INACTIVE)&&!Opt_AMR_WB) + { + *clas = INACTIVE_CLAS; + move16(); + } + ELSE + { + /*------------------------------------------------------------------------* + * Compute the zero crossing rate for all subframes + *------------------------------------------------------------------------*/ + + pt1 = (Word16 *)synth - 1; + move16(); + tmpS = shr(*pt1, 15); /* sets 'tmpS to -1 if *pt1 < 0 */ + Ltmp = L_deposit_l(0); + FOR (j = 0; j < L_SUBFR*nb_subfr; j++) + { + tmp16 = add(1, tmpS); + pt1++; + if(*pt1 != 0) /* Do only count zero crossing, no zero touchings */ + { + tmpS = shr(*pt1, 15); /* 1Clk: >=0 ---> 0 OTHERWISE -1 */ + } + Ltmp = L_msu0(Ltmp, tmpS, tmp16); + } + + zc_frame = shl(extract_l(Ltmp),4); /* Q4 */ + + if( EQ_16(L_frame,L_FRAME16k)) + { + /*zc_frame *= 0.8f;*/ /* Renormalization for 12.8kHz core*/ + zc_frame = mult_r(zc_frame, 26214); + } + + + /*------------------------------------------------------------------------* + * Compute the normalized correlation pitch-synch. at the end of the frame + *------------------------------------------------------------------------*/ + T0 = shr(pitch[3], 6); + Ltmp1 = L_mult(pitch[3], 256); + + if (GT_16(T0, L_SUBFR*3/2)) + { + T0 = mac_r(Ltmp1, pitch[2], 256); + } + + + pt1 = synth; + move16(); + pos = sub(L_frame, T0); /* T0 [34 231] */ + + + Corre(&pt1[pos], &pt1[pos-T0], T0, &cor_max[0]); + T0 = mult_r(add(pitch[2], pitch[3]), 256); + pos_limit = sub(L_frame, L_SUBFR); + j = s_min(1, s_max(0, sub(pos, pos_limit))); + Ltmp = L_deposit_l(cor_max[0]); + IF (j > 0) + { + j = 16384; + move16(); + pos = sub(pos, T0); /* T0 [34 231] */ + Corre(&pt1[pos], &pt1[pos-T0], T0, &cor_max[1]); + Ltmp = L_add(Ltmp, cor_max[1]); + IF (GT_16(pos, pos_limit)) + { + j = 10923; + move16(); + pos = sub(pos, T0); /* T0 [34 231] */ + Corre(&pt1[pos], &pt1[pos-T0], T0, &cor_max[2]); + Ltmp = L_add(Ltmp, cor_max[2]); + } + IF (GT_16(pos, pos_limit)) + { + j = 8192; + move16(); + pos = sub(pos, T0); /* T0 [34 231] */ + Corre(&pt1[pos], &pt1[pos-T0], T0, &cor_max[3]); + Ltmp = L_add(Ltmp, cor_max[3]); + } + } + + voicing = cor_max[0]; + move16(); + IF(j > 0) + { + voicing = extract_l(Mult_32_16(Ltmp, j)); + } + /*------------------------------------------------------------------------* + * Compute pitch coherence + *------------------------------------------------------------------------*/ + + pc = 0; + move16(); + test(); + test(); + IF (EQ_16(codec_mode , MODE1)||!(NE_16(LTP_Gain,-32768/*-1.f Q15*/)&&EQ_16(mode,CLASSIFIER_TCX))) + { + pc = shr(abs_s(sub(add(pitch[3], sub(pitch[2], pitch[1])), pitch[0])), 6); + + if(EQ_16(L_frame,L_FRAME16k)) + { + pc = mult_r(pc, 26214); /* Renormalization for 12.8kHz core*/ + } + } + + /*------------------------------------------------------------------------* + * Compute spectral tilt + *------------------------------------------------------------------------*/ + pt1 = (Word16 *)synth + L_SUBFR; + move16(); + pt2 = (Word16 *)synth + L_SUBFR - 1; + move16(); + Ltmp = L_mult0(*pt1, *pt1); + Ltmp1 = L_mult0(*pt1, *pt2); + FOR(j = 1; j < L_SUBFR*(nb_subfr-1); j++) + { + pt1++; + pt2++; + Ltmp = L_mac0(Ltmp, *pt1, *pt1); + Ltmp1 = L_mac0(Ltmp1, *pt1, *pt2); + } + tilt = 0; + move16(); + + IF (Ltmp != 0) + { + BASOP_SATURATE_WARNING_OFF + tmp16 = extract_l(L_or(L_shr(Ltmp1, 32), 1)); /* sets a flag -1 or 1 for sign of Ltmp1 */ + BASOP_SATURATE_WARNING_ON + Ltmp1 = L_abs(Ltmp1); + exp1 = norm_l(Ltmp1); + tmp_y = extract_h(L_shl(Ltmp1, exp1)); + exp1 = sub(31-1+3, exp1); + exp2 = norm_l(Ltmp); + tmp_x = extract_h(L_shl(Ltmp, exp2)); + exp2 = sub(31-1+3, exp2); + BASOP_SATURATE_WARNING_OFF + tmpS = shr(sub(tmp_x, tmp_y), 16); /* if tmp_x >= tmp_y tmpS = 0, -1 otherwise */ + BASOP_SATURATE_WARNING_ON + tmp_y = shl(tmp_y, tmpS); + exp1 = sub(exp1, tmpS); + + tilt = div_s(tmp_y, tmp_x); + tilt = shl(tilt, sub(exp1, exp2)); /* saturate to 1.0 */ + + tilt = i_mult2(tilt, tmp16); + } + + /*------------------------------------------------------------------------* + * Compute pitch-synchronous energy at the frame end + *------------------------------------------------------------------------*/ + ener = frame_energy_fx(L_frame, pitch, synth, *lp_speech, &frame_ener, *Q_mem_syn); + + /*------------------------------------------------------------------------* + * transform parameters between 0 & 1 + * find unique merit function + *------------------------------------------------------------------------*/ + enern = mac_r(C_ENR_FX, K_ENR_FX, ener); /*Q8*/ + + tiltn = extract_h(L_shr(L_mac(C_TILT_FX, K_TILT_FX, tilt), 6)); /*Q14 -> Q8*/ + + corn = extract_h(L_shr(L_mac(C_COR_FX, K_COR_FX, voicing), 6)); /*Q14 -> Q8*/ + + zcn = extract_h(L_shl(L_mac(C_ZC_FX, K_ZC_FX, zc_frame), 4)); /* Q4 -> Q8*/ + + BASOP_SATURATE_WARNING_OFF + tmp16 = sub(LTP_Gain , -32768/*-1.f Q15*/); + BASOP_SATURATE_WARNING_ON + test(); + test(); + IF ( EQ_16(codec_mode , MODE2)&&tmp16!=0&&EQ_16(mode,CLASSIFIER_TCX)) + { + pcn = round_fx(L_shl(Mpy_32_16_1(C_PC_FX/*Q16*/, LTP_Gain/*Q15*/),8)); /*Q16*/ + } + ELSE + { + pcn = extract_h(L_shl(L_mac(C_PC_FX, K_PC_FX, pc),8)); /* Q0 -> Q8*/ + } + + pcn = s_min(256, pcn); + pcn = s_max( 0, pcn); + /* fmerit1 = (1.0f/6.0f) * (tiltn + 2.0f*corn + zcn + pcn + enern) */ + Ltmp = L_mult(tiltn, UNS6); + Ltmp = L_mac(Ltmp, corn, 2*UNS6); + Ltmp = L_mac(Ltmp, zcn, UNS6); + Ltmp = L_mac(Ltmp, pcn, UNS6); + Ltmp = L_mac(Ltmp, enern, UNS6); + BASOP_SATURATE_WARNING_OFF + fmerit1 = round_fx(L_shl(Ltmp, 15-8)); /*Q15 can saturate to 1.0 */ + BASOP_SATURATE_WARNING_ON + test(); + if ( EQ_16(codec_mode,MODE2)&&narrowBand!=0) + { + fmerit1 = mult_r(fmerit1, 29491/*0.9f Q15*/); /* 0.90 */ + } + IF(EQ_16(codec_mode, MODE1)) + { + *class_para = round_fx(L_shl(Ltmp, 14-8)); /*Q14 - cannot be saturated, degrades HF synthesis */ + } + + /*------------------------------------------------------------------------* + * frame classification + *------------------------------------------------------------------------*/ + test(); + test(); + if ( (NE_16(coder_type,VOICED)&<_32(bitrate,ACELP_11k60))||Opt_AMR_WB) + { + Word16 result = UNVOICED_CLAS; + move16(); + SWITCH( *clas ) + { + case VOICED_CLAS: + case ONSET: + case SIN_ONSET: + case VOICED_TRANSITION: + IF(LT_16(fmerit1, 12780/*0.39f Q15*/)) + { + result = UNVOICED_CLAS; + move16(); + } + ELSE IF(LT_16(fmerit1, 20644/*0.63f Q15*/) + && (LT_16(ener,-3840) || EQ_16(codec_mode,MODE2))) + { + result = VOICED_TRANSITION; + move16(); + } + ELSE + { + result = VOICED_CLAS; + move16(); + } + + BREAK; + + case UNVOICED_CLAS: + case UNVOICED_TRANSITION: + case INACTIVE_CLAS: + IF( GT_16(fmerit1, 18350/*0.56f Q15*/)) + { + result = ONSET; + move16(); + } + ELSE IF( GT_16(fmerit1, 14746/*0.45f Q15*/)) + { + result = UNVOICED_TRANSITION; + move16(); + } + ELSE + { + result = UNVOICED_CLAS; + move16(); + } + BREAK; + + } + *clas = result; + move16(); + } + } + + + + IF(EQ_16(codec_mode,MODE1)) + { + /*------------------------------------------------------------------------* + * Overwrite classification decision in case of music + *------------------------------------------------------------------------*/ + IF( EQ_16(coder_type,AUDIO)) + { + (*decision_hyst) = add(*decision_hyst,4); + move16(); + } + ELSE + { + (*decision_hyst) = sub(*decision_hyst,1); + move16(); + } + + if( EQ_16(coder_type,INACTIVE)) + { + *decision_hyst = sub(*decision_hyst,10); + move16(); + } + IF( GT_16(*decision_hyst,200)) + { + *decision_hyst = 200; + move16(); + } + ELSE if( *decision_hyst < 0 ) + { + *decision_hyst = 0; + move16(); + } + + test(); + test(); + if( GT_16(*decision_hyst,16)&<_16(*clas,VOICED_CLAS)&&EQ_16(coder_type,AUDIO)) + { + *clas = VOICED_CLAS; + move16(); + } + } /*MODE1*/ + + /*---------------------------------------------------------------------------------* + * Measure energy on active voice frames (to improve FEC performance) + *---------------------------------------------------------------------------------*/ + IF( EQ_16(*clas,VOICED_CLAS)) + { + test(); + test(); + test(); + test(); + test(); + IF( (EQ_16(codec_mode,MODE2)&&EQ_16(coder_type,VOICED)) + || (EQ_16(codec_mode,MODE1) && (Opt_AMR_WB || (NE_16(coder_type,GENERIC) && NE_16(coder_type,TRANSITION) ) ) ) + ) + { + /* pitch-synchronous energy at the frame end */ + enern = frame_energy_fx(L_frame,pitch, synth, *lp_speech, &frame_ener, *Q_mem_syn); + } + /* update of long-term active speech energy */ + Ltmp = L_mult0(655, frame_ener); /* 0.01 */ + *lp_speech = mac_r(Ltmp, 32440, *lp_speech); + move16(); /* lp_speech update */ + } + + IF(EQ_16(codec_mode, MODE1)) + { + + /*---------------------------------------------------------------------------------* + * Overwrite classification decision to UNVOICED_CLAS in case of INACTIVE frame + *---------------------------------------------------------------------------------*/ + test(); + if( EQ_16(coder_type, INACTIVE)&&NE_16(*clas,INACTIVE_CLAS)) + { + *clas = UNVOICED_CLAS; + move16(); + } + + /*---------------------------------------------------------------------------------* + * Classification refinement to improve noise coding (only in AMR-WB IO mode) + *---------------------------------------------------------------------------------*/ + IF( Opt_AMR_WB ) + { + *locattack = 0; + move16(); + + /*-----------------------------------------------------------------------------* + * Unvoiced signal but not silence + *-----------------------------------------------------------------------------*/ + + test(); + IF( EQ_16(*clas, UNVOICED_CLAS)&&NE_16(coder_type,INACTIVE)) + { + IF ( LE_16(*lp_speech, 40*256/*Q8*/)) + { + *UV_cnt = 16; + move16(); + } + ELSE + { + move16(); + *UV_cnt = sub(*UV_cnt, 8); + } + } + + /*-----------------------------------------------------------------------------* + * Neither unvoiced nor clean silence + * Number of frames between UV is increased + *-----------------------------------------------------------------------------*/ + + ELSE IF ( NE_16(coder_type, INACTIVE)) + { + move16(); + *UV_cnt = add(*UV_cnt, 1); + } + + /*-----------------------------------------------------------------------------* + * Maximum/minimum number of frames between UV reached + *-----------------------------------------------------------------------------*/ + + /* Range 0..300 */ move16(); + *UV_cnt = s_max(s_min(300, *UV_cnt), 0); + + /*-----------------------------------------------------------------------------* + * IF VAD = 0 (no voice activity) + * long-term average updated towards to speech + * maximum number of frames between UV is limited to 125 + * Else + * update long-term average + *-----------------------------------------------------------------------------*/ + + IF ( EQ_16(coder_type, INACTIVE)) + { + move16(); + *LT_UV_cnt = mult_r(31130/*0.95f*/, *LT_UV_cnt); /* tend to speech if no activity */ + *UV_cnt = s_min(125, *UV_cnt); + move16(); + } + ELSE + { + /* *LT_UV_cnt = 0.9f * *LT_UV_cnt + 0.1f * *UV_cnt */ + + Ltmp = L_mult(3277/*0.1f*/, *UV_cnt); + /* Bring to Q22 */ + Ltmp = L_shl(Ltmp, 6); + /* Add to 0.9 x *LT_UV_cnt (Already in Q6) */ + Ltmp = L_mac(Ltmp, 29491/*0.9f*/, *LT_UV_cnt); /* Q22*/ + /* Store */ + *LT_UV_cnt = round_fx(Ltmp); + } + + /*-----------------------------------------------------------------------------* + * Compute frame energy difference + * IF long-term average is high and energy difference is relatively low + * classification is overwritten to AUDIO + * IF energy difference > 6.0dB + * consider an attack + *-----------------------------------------------------------------------------*/ + + diff_ener = sub(ener, *Last_ener); + *Last_ener = ener; + move16(); + *amr_io_class = *clas; + move16(); + test(); + if ( GT_16(*LT_UV_cnt, LT_UV_THR_FX)&<_16(diff_ener,12*256/*Q8*/)) + { + move16(); + *amr_io_class = AUDIO_CLAS; + } + test(); + test(); + if ( (GT_16(diff_ener, 6*256/*Q8*/)&&EQ_16(*clas,AUDIO_CLAS))||GT_16(diff_ener,9*256/*Q8*/)) + { + *locattack = 1; + move16(); + } + + /*------------------------------------------------------------------------* + * Find mean of the past 40 frames energy variation + *------------------------------------------------------------------------*/ + + IF( NE_16(coder_type, INACTIVE)) + { + Ltmp = L_deposit_l(0); + FOR (i = 1; iQ8 */ + L_tmp = L_mult(tmpS, 10885); /* 0.332192 in Q15 */ + L_tmp = L_shr(L_tmp, 8); /* From Q24 to Q16 */ + sfrac = L_Extract_lc(L_tmp, &tmpS); + *enr_q = Pow2(tmpS, sfrac); + move32(); + } + + return clas; +} + +Word16 FEC_pos_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 coder_type, /* i : coder type */ + const Word16 last_good, /* i : last good classfication */ + Word16 *last_pulse_pos, /* o : last glotal pulse position in the lost ACB */ + Word16 *clas, /* o : decoded classification */ + Word32 *enr_q, /* o : decoded energy in Q0 */ + const Word32 core_brate /* i : decoded bitrate */ +) +{ + Word16 pitch_index, T0, T0_frac, T0_min, T0_max; + Word16 bit_pos_pitch_index, nBits; + + T0 = 0; + move16(); + IF( GT_16(coder_type,UNVOICED)) + { + /* decode the clas and energy information */ + IF( LT_16(coder_type,AUDIO)) + { + *clas = FEC_dec_class_fx( st_fx, core_brate, coder_type, enr_q, last_good); + move16(); + + test(); + test(); + test(); + IF( EQ_16(coder_type,GENERIC)&&EQ_16(*clas,VOICED_CLAS)&&(LE_16(last_good,UNVOICED_CLAS)||EQ_16(last_good,INACTIVE_CLAS))) + { + *clas = SIN_ONSET; + move16(); + } + } + + test(); + IF( EQ_16(coder_type,GENERIC)&>_32(core_brate,ACELP_24k40)) + { + nBits = 0; + move16(); + IF( NE_16(coder_type,AUDIO)) + { + nBits = ACB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(core_brate, coder_type, 0, 0)]; + move16(); + } + + /* use the absolute position of pitch index in the bitstream (this value is hard-coded and must be udpated when it changes in the encoder) */ + bit_pos_pitch_index = 71; + move16(); /* 64 kbps WB,SWB and FB*/ + if( LE_32(core_brate,ACELP_32k)) + { + bit_pos_pitch_index = 72; + move16(); /* 32 kbp, WB*/ + if(GT_16(st_fx->bwidth_fx,WB)) + { + bit_pos_pitch_index = 73; + move16(); /* 32 kbp, SWB, FB*/ + } + } + + /* retrieve the pitch index */ + pitch_index = (Word16)get_indice_fx( st_fx, bit_pos_pitch_index, nBits ); + + /* decode pitch period */ + T0_min = PIT_MIN; + move16(); + T0_max = PIT_MAX; + move16(); + pit16k_Q_dec_fx( pitch_index, 10, 1, &T0, &T0_frac, &T0_min, &T0_max, &st_fx->BER_detect ); + + /* decode last pulse position */ + *last_pulse_pos = (Word16)get_next_indice_fx( st_fx, FEC_BITS_POS ); + + /* respect the sign */ + IF (GE_16(*last_pulse_pos,128)) + { + *last_pulse_pos = negate(s_and(*last_pulse_pos , 0x7F)); + move16(); + } + if ( GE_16(T0,128)) + { + *last_pulse_pos = add(*last_pulse_pos,*last_pulse_pos); + move16(); + } + + if( st_fx->BER_detect ) + { + *last_pulse_pos = 0; + move16(); + } + } + } + + return T0; +} +/*----------------------------------------------------------------------* + * Corre: + * + * Correlation function. Signal x is compared to target signal y + * Information about the similarity between vectors is returned in *gain + *----------------------------------------------------------------------*/ +static void Corre( + const Word16 *x, /* i : vector 1 Q12 */ + const Word16 *y, /* i : vector 2 Q12 */ + const Word16 l, /* i : length of vectors */ + Word16 *gain /* o : normalized correlation gain Q15 */ +) +{ + Word16 cor, cor_exp; + Word16 den, den_exp; + Word16 den2, den2_exp; + Word32 tmp; + Word16 tmp_exp; + + /* keep Q15 normalized result */ + cor = extract_h(Dot_product12(x, y, l, &cor_exp)); + den = add(extract_h(Dot_product12(y, y, l, &den_exp)), 1); + den2 = extract_h(Dot_product12(x, x, l, &den2_exp)); + + /* keep Q31 normalized result */ + tmp = L_mult(den, den2); + tmp_exp = norm_l(tmp); + tmp = L_shl(tmp, tmp_exp); + tmp_exp = sub(add(den_exp, den2_exp), tmp_exp); + + tmp = Isqrt_lc(tmp, &tmp_exp); + /* keep Q15 result */ + gain[0] = shl(mult_r(cor, extract_h(tmp)), add(cor_exp, tmp_exp)); + move16(); +} + diff --git a/lib_dec/FEC_fx.c b/lib_dec/FEC_fx.c new file mode 100644 index 0000000..2ea49e5 --- /dev/null +++ b/lib_dec/FEC_fx.c @@ -0,0 +1,803 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Common static table prototypes */ +#include "rom_dec_fx.h" /* Decoder static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "basop_util.h" + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ +static void pulseRes_preCalc(Word16* cond1, Word16* cond2, Word32* cond3 ,Word16 new_pit, Word16 Tc, Word16 L_frame); +void gain_dec_bfi_fx(Word16 *past_qua_en); +/*======================================================================*/ +/* FUNCTION : FEC_exc_estim_fx() */ +/*----------------------------------------------------------------------*/ +/* PURPOSE : Calculation of excitation signal */ +/* */ +/*----------------------------------------------------------------------*/ +/* GLOBAL INPUT ARGUMENTS : */ +/* _ (Struct) st_fx : decoder static memory */ +/* _ (Word16) L_frame_fx : length of the frame Q0 */ +/* _ (Word16) st_fx->lp_ener_fx : FEC - low-pass filtered energy Q6 */ +/* _ (Word16) st_fx->lp_gainc_fx : FEC - low-pass filtered code gain Q3 */ +/* _ (Word16) st_fx->old_pitch_buf : FEC buffer of old subframe pitch valuesQ6*/ +/* _ (Word16) st_fx->last_good : FEC - clas of last good received */ +/* _ (Word16) st_fx->bfi_pitch_fx : LP filter coefficient */ +/* _ (Word16) st_fx->upd_cnt_fx : FEC counter of frames since last update*/ +/* _ (Word16) st_fx->last_coder_type_fx: previous coder type */ +/* _ (Word16) st_fx->Last_GSC_pit_band_idx_fx: AC mode (GSC)Last pitch band index*/ +/* _ (Word16) st_fx->stab_fac_fx : LSF stability factor Q15 */ +/* _ (Word16) st_fx->tilt_code : tilt of code Q15 */ +/* _ (Word16) st_fx->last_voice_factor : coding type Q12 */ +/* _ (Word16) st_fx->opt_AMR_WB_fx : coding type Q12 */ +/* _ (Word16) st_fx->lp_gainp_fx : FEC -low-pass filtered pitch gain Q14 */ +/* _ (Word16) st_fx->seed :FEC-seed for random generator for excitation*/ +/* _ (Word16) st_fx->opt_OMR_WB:flag indicating AMR-WB IO mode */ +/*-----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Q_exc) */ +/* _ (Word16[]) exc2_fx : adapt. excitation/total exc (Q_exc) */ +/* _ (Word16[]) bwe_exc_fx : excitation for SWB TBE (Q_exc) */ +/* _ (Word16[]) pitch_buf_fx : floating pitch values for each subframe Q6*/ +/* _ (Word16[]) voice_factors_fx : frame error rate Q15 */ +/* _ (Word16[]) FEC_pitch_fx(tmp_tc): FEC pitch Q6 */ +/*-----------------------------------------------------------------------*/ + +/* _ (Word16) st_fx->lp_gainp_fx : FEC -low-pass filtered pitch gain Q14 */ +/* _ (Word16) st_fx->seed :FEC-seed for random generator for excitation*/ +/* _ (Word16) st_fx->bfi_pitch_fx : LP filter coefficient */ +/* _ (Word16) st_fx->lp_gainc_fx : FEC - low-pass filtered code gain Q3 */ +/*-----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*=======================================================================*/ + + +void FEC_exc_estim_fx( + Decoder_State_fx *st_fx, /* i/o: Decoder static memory */ + const Word16 L_frame, /* i : length of the frame */ + Word16 *exc, /* o : pointer to excitation buffer (with past) */ + Word16 *exc2, /* o : total excitation (for synthesis) */ + Word16 exc_dct_in[], /* o : GSC excitation in DCT domain */ + Word16 *pitch_buf, /* o : Floating pitch for each subframe */ + Word16 *voice_factors, /* o : voicing factors */ + Word16 *tmp_tc, /* o : FEC pitch Q6 */ + Word16 *bwe_exc, /* o : excitation for SWB TBE */ + Word16 *lsf_new, /* i : ISFs at the end of the frame */ + Word16 *Q_exc, + Word16 *tmp_noise /* o : long-term noise energy Q0 */ +) +{ + + Word16 exc2_buf[L_FRAME16k + MODE1_L_FIR_FER-1]; + Word16 gainCNG,new_pit /*Q0*/; /* Q3*/ + Word16 exp; + Word32 L_tmp,L_tmp2; + Word16 tmp,tmp1,tmp16; + Word16 delta; + Word16 i,j; + Word16 alpha; + Word16 gain,gain_inov; + Word16 Tc; + Word16 *pt_exc,*pt1_exc; + Word16 step; + Word32 L_step; + Word16 hp_filt[5]; + Word16 Diff_len,max_len,Len; + Word16 last_bin_fx, nb_subfr; + Word16 extrapolationFailed; + Word16 cond1, cond2; + Word32 cond3; + Word32 predPitchLag; + + /* nb_subfr = L_frame/L_SUBFR */ + nb_subfr = shr(L_frame, 6); + Diff_len = 0; /* to avoid compilation flags */ + set16_fx( exc_dct_in, 0, L_FRAME16k ); + + extrapolationFailed = 1; + move16(); + + gainCNG = 0; + move16(); + IF(st_fx->lp_ener_fx != 0) + { + exp = norm_l(st_fx->lp_ener_fx); /*lp_ener in Q6*/ + tmp = extract_h(L_shl(st_fx->lp_ener_fx,exp)); + exp = sub(exp, 30-6); + + tmp = div_s(16384, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp); + + gainCNG = round_fx(L_shl(L_tmp, sub(exp, 12))); /* In Q3 */ + + } + tmp1 = shl(st_fx->lp_gainc_fx,1); + gainCNG = s_min(gainCNG , tmp1); + set16_fx( exc_dct_in, 0, L_FRAME16k ); + + /*-----------------------------------------------------------------* + * pitch extrapolation + *-----------------------------------------------------------------*/ + + { + Word32 *tmp_old_pitch /*15Q16*/; + Word16 tmp_pitmin, tmp_pitmax; + + /*tmp_old_pitch = L_frame == L_FRAME ? &st_fx->old_pitch_buf_fx[2*NB_SUBFR-1] : &st_fx->old_pitch_buf_fx[2*NB_SUBFR16k-1];*/ + /*tmp_pitmin = L_frame == L_FRAME?PIT_MIN_DOUBLEEXTEND:PIT16k_MIN_EXTEND;*/ + /*tmp_pitmax = L_frame == L_FRAME?PIT_MAX:PIT16k_MAX;*/ + + tmp_old_pitch = &st_fx->old_pitch_buf_fx[2*NB_SUBFR16k-1]; + tmp_pitmin = PIT16k_MIN_EXTEND; + tmp_pitmax = PIT16k_MAX; + IF(EQ_16(L_frame, L_FRAME)) + { + tmp_old_pitch = &st_fx->old_pitch_buf_fx[2*NB_SUBFR-1]; + tmp_pitmin = PIT_MIN_DOUBLEEXTEND; + move16(); + tmp_pitmax = PIT_MAX; + move16(); + } + + + pitch_pred_linear_fit( + st_fx->nbLostCmpt, + st_fx->last_good_fx, + st_fx->old_pitch_buf_fx, + tmp_old_pitch, + &predPitchLag, + tmp_pitmin, + tmp_pitmax, + st_fx->mem_pitch_gain, + 0, + 0, + &extrapolationFailed, + nb_subfr); + + new_pit/*Q0 int*/ = shl(round_fx(predPitchLag),0); + } + + + + /*-----------------------------------------------------------------* + * estimate subframe pitch values for the FEC frame + *-----------------------------------------------------------------*/ + + /* initialize pitch to the long-term pitch */ + + *tmp_tc = st_fx->bfi_pitch_fx; + move16(); /*Q6*/ + IF( EQ_16(L_frame,L_FRAME)) + { + test(); + test(); + IF ( (LT_16(round_fx(L_shl(st_fx->old_pitch_buf_fx[2*NB_SUBFR-1], 6)), shl(mult(29491, st_fx->bfi_pitch_fx), 1))&& + GT_16(round_fx(L_shl(st_fx->old_pitch_buf_fx[2*NB_SUBFR-1], 6)), mult(19661, st_fx->bfi_pitch_fx)) ) || /* last pitch coherent with the past */ + GE_16(st_fx->upd_cnt_fx, MAX_UPD_CNT) ) /* or last update too far in the past */ + { + /* take the pitch value of last subframe of the previous frame */ + *tmp_tc = round_fx(L_shl(st_fx->old_pitch_buf_fx[2*NB_SUBFR-1], 6)); + } + } + ELSE /* L_frame == L_FRAME16k */ + { + test(); + test(); + IF ( (LT_16(round_fx(L_shl(st_fx->old_pitch_buf_fx[2*NB_SUBFR16k-1], 6)), shl(mult(29491, st_fx->bfi_pitch_fx), 1))&& + GT_16(round_fx(L_shl(st_fx->old_pitch_buf_fx[2*NB_SUBFR16k-1], 6)), mult(19661, st_fx->bfi_pitch_fx))) || /* last pitch coherent with the past */ + GE_16(st_fx->upd_cnt_fx, MAX_UPD_CNT)) /* or last update too far in the past */ + { + /* take the pitch value of last subframe of the previous frame */ + *tmp_tc = round_fx(L_shl(st_fx->old_pitch_buf_fx[2*NB_SUBFR16k-1], 6)); + } + } + + /* convert pitch period */ + /* Tc = (short)(tmp_tc + 0.5f) */ + Tc = shr_r(*tmp_tc,6); + + /* estimate pitch values for all subframes */ + /*calculate conditions for Pulse resynchronization to take place*/ + pulseRes_preCalc( &cond1, &cond2, &cond3 , new_pit, Tc, L_frame); + + test(); + test(); + test(); + test(); + IF ((cond1 < 0 ) + && (new_pit > 0) && (cond2 != 0) + && (cond3 > 0) + && extrapolationFailed == 0 + ) + { + tmp16 = *tmp_tc; /*Q6*/ move16(); + IF(EQ_16(nb_subfr,4)) + { + delta = shr(sub(shl(new_pit,6), *tmp_tc),2 ); /* 4 sub-frames */ + } + ELSE + { + delta = mult_r(sub(shl(new_pit,6), *tmp_tc),6554); /* 5 sub-frames */ + } + FOR (i = 0; i < nb_subfr; i++) /* subframe pitch values */ + { + /* fT0 += delta */ + tmp16 = add(tmp16, delta); + /* ptch_buf[i] = (short)(fT0 + 0.5) */ + pitch_buf[i] = shl(mult_r(tmp16, 512), 6); + move16(); + } + } + ELSE + { + FOR (i = 0; i < nb_subfr; i++) /* subframe pitch values for bass postfilter */ + { + pitch_buf[i] = *tmp_tc; + move16(); + } + } + + /*-----------------------------------------------------------------* + * estimate damping factor + *-----------------------------------------------------------------*/ + + /* rapid convergence to 0 */ + alpha = _ALPHA_VT_FX; + move16(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( st_fx->last_coder_type_fx == UNVOICED && LE_16(st_fx->nbLostCmpt, 3)) + { + /* last good frame was clearly unvoiced */ + alpha = _ALPHA_UU_FX; + move16(); + } + ELSE IF( EQ_16(st_fx->last_coder_type_fx,AUDIO)||EQ_16(st_fx->last_good_fx,INACTIVE_CLAS)) + { + test(); + IF( st_fx->Last_GSC_pit_band_idx_fx > 0 && GT_16(st_fx->nbLostCmpt,1)) + { + alpha = 26214; + move16(); + } + ELSE IF( LE_16(st_fx->nbLostCmpt,5)) + { + alpha = 32604; + move16(); + } + ELSE + { + alpha = 31130; + move16(); + } + } + ELSE IF( EQ_16(st_fx->last_good_fx,UNVOICED_CLAS)) + { + IF( LE_16(st_fx->nbLostCmpt,1)) + { + /* if stable, do not decrease the energy, pitch_gain = 0 */ + alpha = mac_r((1L<<16)*2*_ALPHA_U_FX, st_fx->stab_fac_fx, 32768-2*_ALPHA_U_FX); /*st_fx->stab_fac_fx in Q15*/ + } + ELSE IF ( EQ_16(st_fx->nbLostCmpt,2)) + { + alpha =_ALPHA_S_FX; + move16(); /* ALPHA_U*1.5f = 0.6 */ + } + ELSE + { + alpha = _ALPHA_U_FX; + move16(); /* 0.4 go rapidly to CNG gain, pitch gain = 0 */ + } + } + ELSE IF( EQ_16(st_fx->last_good_fx,UNVOICED_TRANSITION)) + { + alpha = _ALPHA_UT_FX; + move16(); + } + ELSE IF( EQ_16(st_fx->last_good_fx,ONSET)&&LE_16(st_fx->nbLostCmpt,3)&&(EQ_16(st_fx->last_coder_type_fx,GENERIC)||EQ_16(st_fx->last_coder_type_fx,TRANSITION))) + { + alpha = 26214; + move16(); /* mild convergence to 0 for the first 3 erased frames 0.8 in Q15 */ + } + ELSE IF( ( EQ_16(st_fx->last_good_fx,VOICED_CLAS)||EQ_16(st_fx->last_good_fx,ONSET))&&LE_16(st_fx->nbLostCmpt,3)) + { + alpha = _ALPHA_V_FX; + move16(); /* constant for the first 3 erased frames */ + } + ELSE IF( EQ_16(st_fx->last_good_fx,SIN_ONSET)) + { + alpha = _ALPHA_S_FX; + move16(); + } + test(); + test(); + IF( GE_16(st_fx->last_good_fx,VOICED_CLAS)&<_16(st_fx->last_good_fx,INACTIVE_CLAS)&&NE_16(st_fx->last_coder_type_fx,AUDIO)) + { + IF( EQ_16(st_fx->nbLostCmpt,1)) /* if first erased frame in a block, reset harmonic gain */ + { + /* move pitch gain towards 1 for voiced to remove energy fluctuations */ + /*gain = (float)sqrt( st_fx->lp_gainp );*/ + st_fx->lp_gainp_fx = s_max(st_fx->lp_gainp_fx, 1); + exp = norm_s(st_fx->lp_gainp_fx); + tmp = shl(st_fx->lp_gainp_fx, exp); + tmp = div_s(16384, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp); + + gain = extract_h(L_shl(L_tmp, exp)); + + gain = s_min(gain, 32113); /*0.98 */ + gain = s_max(gain, 27853); /*0.85 */ + + alpha = mult_r(alpha, gain); + } + ELSE + { + /* st_fx->lp_gainp_fx is in Q14 when bfi_cnt > 1 to follow floating point because lp_gainp could be > than 1 */ + alpha = st_fx->lp_gainp_fx; + move16(); + } + } + + /*-----------------------------------------------------------------* + * construct the harmonic part of excitation + *-----------------------------------------------------------------*/ + test(); + test(); + test(); + test(); + IF( (GE_16(st_fx->last_good_fx,UNVOICED_TRANSITION)&<_16(st_fx->last_good_fx,INACTIVE_CLAS))|| + ( (EQ_16(st_fx->last_coder_type_fx,AUDIO) || EQ_16(st_fx->last_good_fx,INACTIVE_CLAS) ) && st_fx->Last_GSC_pit_band_idx_fx > 0) ) + { + + pt_exc = exc; + move16(); + pt1_exc = pt_exc - Tc; + move16(); + + IF (EQ_16(st_fx->nbLostCmpt,1)) + { + /* first pitch cycle is low-pass filtered */ + + FOR (i = 0; i < Tc; i++) /* pitch cycle is first low-pass filtered */ + { + /* *pt_exc++ = (0.18f * pt1_exc[-1] + 0.64f * pt1_exc[0] + 0.18f * pt1_exc[1]) */ + L_tmp = L_mult(5898, pt1_exc[-1]); + L_tmp = L_mac(L_tmp, 20972, pt1_exc[0]); + *pt_exc++ = mac_r(L_tmp, 5898, pt1_exc[1]); + move16(); + pt1_exc++; + } + } + + /* last pitch cycle of the previous frame is repeatedly copied up to an extra subframe */ + + tmp = (Word16)((exc + L_frame + L_SUBFR) - pt_exc); + FOR (i = 0; i < tmp; i++) + { + *pt_exc++ = *pt1_exc++; + move16(); + } + + IF (new_pit > 0 ) + { + /*calculate conditions for Pulse resynchronization to take place*/ + pulseRes_preCalc( &cond1, &cond2, &cond3 , new_pit, Tc, L_frame); + + test(); + test(); + test(); + test(); + IF ((cond1 < 0 ) + && (new_pit > 0) && (cond2 != 0) + && (cond3 > 0) + && extrapolationFailed == 0 + ) + { + Copy(exc,exc-L_frame-L_SUBFR,L_frame+L_SUBFR); + PulseResynchronization(exc-L_frame-L_SUBFR, exc, L_frame, nb_subfr, L_deposit_h(Tc/*Q0*/)/*15Q16*/, L_deposit_h(new_pit/*Q0*/)/*15Q16*/); + } + } + test(); + test(); + IF( EQ_16(st_fx->last_good_fx,UNVOICED_TRANSITION)&&(EQ_16(st_fx->last_coder_type_fx,GENERIC)||EQ_16(st_fx->last_coder_type_fx,TRANSITION))) + { + /* start of the frame gain */ + gain = 0; + move16(); + + /* end of the frame gain */ + st_fx->lp_gainp_fx = 0; + move16(); + step = 0; + move16(); + } + ELSE + { + + /* start of the frame gain */ + gain = 16384; + move16(); + + /* end of the frame gain */ + test(); + + IF(!(GE_16(st_fx->last_good_fx,VOICED_CLAS)&<_16(st_fx->last_good_fx,INACTIVE_CLAS)&&NE_16(st_fx->last_coder_type_fx,AUDIO)&>_16(st_fx->nbLostCmpt,1))) + { + st_fx->lp_gainp_fx = shr(alpha,1); /* alpha in Q15 */ + } + ELSE + { + st_fx->lp_gainp_fx = alpha; + move16(); /* alpha in Q14 */ + } + + IF(EQ_16(L_frame, L_FRAME)) + { + step = shr(sub(gain,st_fx->lp_gainp_fx),8); + } + ELSE /*L_frame == L_FRAME16k*/ + { + /*step = (1.0f/L_frame) * (gain - st_fx->lp_gainp);*/ + + step = shr(mult_r(26214,sub(gain,st_fx->lp_gainp_fx)),8); /*Q14*/ + } + } + + FOR( i=0 ; i< L_frame; i++ ) + { + /* exc[i] *= gain */ + exc[i] = round_fx(L_shl(L_mult(exc[i], gain), 1)); /* in Q_exc */ + /* gain -= step */ + gain = sub(gain, step); + } + test(); + test(); + IF( (EQ_16(st_fx->last_coder_type_fx,AUDIO)||EQ_16(st_fx->last_good_fx,INACTIVE_CLAS))&&st_fx->Last_GSC_pit_band_idx_fx>0) + { + Diff_len = mfreq_loc_div_25[st_fx->Last_GSC_pit_band_idx_fx]; + move16(); + + /* Transform to frequency domain */ + edct_16fx( exc, exc_dct_in, st_fx->L_frame_fx, 5 ); + + /* Reset unvaluable part of the adaptive (pitch) excitation contribution */ + max_len = sub(st_fx->L_frame_fx,Diff_len); + Len = s_min( max_len, 80 ); + + move16(); /*ptr init*/ + FOR( i=0; ilast_good >= VOICED_TRANSITION" */ + + /*-----------------------------------------------------------------* + * Replicate the last spectrum in case the last good frame was coded by GSC + *-----------------------------------------------------------------*/ + test(); + test(); + test(); + IF( EQ_16(st_fx->last_coder_type_fx,AUDIO)||(EQ_16(st_fx->last_good_fx,INACTIVE_CLAS)&&LE_32(st_fx->total_brate_fx,ACELP_24k40)&&!st_fx->Opt_AMR_WB_fx)) + { + st_fx->GSC_noisy_speech_fx = st_fx->Last_GSC_noisy_speech_flag_fx; + move16(); + /* Replication of the last spectrum, with a slight downscaling of its dynamic */ + gsc_dec_fx( st_fx, exc_dct_in, st_fx->Last_GSC_pit_band_idx_fx, Diff_len, 0, st_fx->L_frame_fx/L_SUBFR, st_fx->last_coder_type_fx, &last_bin_fx, lsf_new, NULL, st_fx->Q_exc ); + *tmp_noise = shr_r(st_fx->lp_gainc_fx,3); /*Q0*/ + /* Transform back to time domain */ + edct_16fx( exc_dct_in, exc, st_fx->L_frame_fx, 5 ); + } + ELSE + { + /*-----------------------------------------------------------------* + * Construct the random part of excitation + *-----------------------------------------------------------------*/ + + /* generate the random part of the excitation */ + FOR (i=0; iseed_fx ),3); + move16(); + } + + /* start of the frame gain */ + gain = st_fx->lp_gainc_fx; + move16(); + + test(); + test(); + test(); + IF(!(GE_16(st_fx->last_good_fx,VOICED_CLAS)&<_16(st_fx->last_good_fx,INACTIVE_CLAS)&&NE_16(st_fx->last_coder_type_fx,AUDIO)&>_16(st_fx->nbLostCmpt,1))) + { + /* Here alpha is in Q15 and lp_gainc_fx in Q3 */ + /* st_fx->lp_gainc = alpha * st_fx->lp_gainc + (1.0f - alpha) * gainCNG; */ + L_tmp = L_mult(alpha, st_fx->lp_gainc_fx); + + st_fx->lp_gainc_fx = msu_r(L_tmp, add(alpha, -32768), gainCNG); + } + ELSE + { /* Here alpha is in Q14, but lp_gainc still in Q3 */ + /* st_fx->lp_gainc = alpha * st_fx->lp_gainc + (1.0f - alpha) * gainCNG; */ + L_tmp = L_mult(alpha, st_fx->lp_gainc_fx); /* Q14*Q3->Q18 */ + + st_fx->lp_gainc_fx = round_fx(L_shl(L_msu(L_tmp, add(alpha, -16384), gainCNG),1));/* (Q14*Q3<<1)>>16 ->Q3 */ + } + + test(); + test(); + test(); + if( EQ_16(st_fx->last_good_fx,UNVOICED_TRANSITION)&&(EQ_16(st_fx->last_coder_type_fx,GENERIC)||EQ_16(st_fx->last_coder_type_fx,TRANSITION))&&gainCNG>0) + { + st_fx->lp_gainc_fx = gainCNG; + move16(); + } + + /* linearly attenuate the gain throughout the frame */ + /* step = (1.0f/L_FRAME) * (gain - *lp_gainc); */ + step = sub(gain,st_fx->lp_gainc_fx); /* divide by L_FRAME done later */ + test(); + if(EQ_16(L_frame,L_FRAME16k)) + { + step = mult_r(step,26214); /* L_frame16k-> L_frame and division by L_frame done later*/ + } + + /* calculate gain to normalize energy */ + pt_exc = exc2_buf + MODE1_L_FIR_FER/2; + move16(); + + /* To avoid saturation split the L_frame dot product into (L_frame/L_SUBFR) dot products + and scale down before adding */ + /* gain_inov = 1.0f / (float)sqrt( dotp( pt_exc, pt_exc, L_frame ) / L_frame + 0.01f ); */ + + L_tmp = L_deposit_l(0); + FOR (i = 0; i < 2; i++) + { + L_tmp2 = L_mult0(*pt_exc, *pt_exc); + pt_exc++; + FOR (j = 1; j < shr(L_frame,1); j++) + { + L_tmp2 = L_mac0(L_tmp2, *pt_exc, *pt_exc); /* Q-5 */ + pt_exc++; + } + L_tmp = L_add(L_tmp, L_shr(L_tmp2, 1)); /* Q-7 */ + } + test(); + if(EQ_16(L_frame,L_FRAME16k)) + { + L_tmp = Mult_32_16(L_tmp, 26214); /* x0.8 to normalize to 256 samples */ + } + exp = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, exp); /* Normalize */ + exp = add(exp, 8-7); /* Q0, 8 ->divide by 256 */ + exp = sub(31, exp); /* For Denormalization in Q31 */ + L_tmp = Isqrt_lc(L_tmp, &exp);/* in Q(31-exp) */ + gain_inov = round_fx(L_tmp); + + /* attenuate somewhat on unstable unvoiced */ + test(); + test(); + if( (EQ_16(st_fx->last_good_fx,UNVOICED_CLAS)||EQ_16(st_fx->last_good_fx,INACTIVE_CLAS))&&NE_16(st_fx->last_coder_type_fx,UNVOICED)) + { + gain_inov = mult_r(gain_inov, 26214); + } + + /* scaling of the random part of excitation */ + pt_exc = exc2_buf; + move16(); + L_step = L_shr(L_mult(gain_inov, step), 8); /* here is the divide by L_FRAME */ + L_tmp2 = L_mult(gain_inov, gain); /* Q15 * Q3 -> Q3 */ + tmp = round_fx(L_tmp2); + exp = add(add(exp, *Q_exc), 15); /* 3+Q_exc+15 -> Q_exc+18 */ + + FOR( i=0; i< MODE1_L_FIR_FER/2; i++ ) + { + /* non-causal ringing of the FIR filter */ + /**pt_exc++ *= (gain_inov * gain);*/ + L_tmp = L_mult(tmp, *pt_exc); /* Q_exc+18 * Q-3 -> Q_exc+16 */ + *pt_exc++ = round_fx(L_shl(L_tmp, exp)); + } + + FOR( i=0; i< L_frame; i++ ) + { + /* the inner part of the FIR filter */ + /* *pt_exc++ *= (gain_inov * gain); */ + L_tmp = L_mult(tmp, *pt_exc); + *pt_exc++ = round_fx(L_shl(L_tmp, exp)); + /* gain -= step; */ + L_tmp2 = L_sub(L_tmp2, L_step); + tmp = round_fx(L_tmp2); + + } + + FOR (i = 0 ; i < MODE1_L_FIR_FER/2; i++) /* causal ringing of the FIR filter */ + { + /* *pt_exc++ *= (gain_inov * gain) */ + L_tmp = L_mult(tmp, *pt_exc); + *pt_exc++ = round_fx(L_shl(L_tmp, exp)); + } + } + + /*-----------------------------------------------------------------* + * Total excitation + *-----------------------------------------------------------------*/ + test(); + test(); + test(); + test(); + IF( (EQ_16(st_fx->last_coder_type_fx,AUDIO)||EQ_16(st_fx->last_good_fx,INACTIVE_CLAS))&&LE_32(st_fx->total_brate_fx,ACELP_24k40)&&!st_fx->Opt_AMR_WB_fx) + { + /* For GSC - the excitation is already computed */ + Copy( exc, exc2, st_fx->L_frame_fx ); + } + ELSE IF( GE_16(st_fx->last_good_fx,UNVOICED_TRANSITION)&<_16(st_fx->last_good_fx,INACTIVE_CLAS)) + { + /* For voiced and generic signals - prepare a HP filter for the random part of excitation */ + /* tmp = -(1-tilt_code) to correctly represent 1.0000 */ + tmp = add(st_fx->tilt_code_fx, -32768); + move16(); + FOR (i = 0; i < MODE1_L_FIR_FER; i++) + { + hp_filt[i] = msu_r(0, tmp, h_high_fx[i]); + move16(); + } + + /* HP filter the random part of the excitation and add the adaptive part */ + pt_exc = exc2_buf; + move16(); + FOR( i=0; i< L_frame; i++ ) + { + /* exc2[i] = exc[i] + dotp( &exc2_buf[i], hp_filt, MODE1_L_FIR_FER );*/ + L_tmp = L_mult(hp_filt[0], pt_exc[0]); + FOR (j = 1; j < MODE1_L_FIR_FER; j++) + { + L_tmp = L_mac(L_tmp, hp_filt[j], pt_exc[j]); + } + exc2[i] = msu_r(L_tmp, -32768, exc[i]); + move16(); + pt_exc++; + } + } + ELSE + { + /* For purely unvoiced signals - just copy the unfiltered random part of the excitation */ + Copy( exc2_buf + MODE1_L_FIR_FER/2, exc, L_frame ); + Copy( exc2_buf + MODE1_L_FIR_FER/2, exc2, L_frame ); + } + + IF( EQ_16(L_frame,L_FRAME)) + { + + interp_code_5over2_fx( exc, bwe_exc, L_frame ); + } + ELSE + { + interp_code_4over2_fx( exc, bwe_exc, L_frame ); + } + test(); + IF( EQ_16(st_fx->last_coder_type_fx,AUDIO)||EQ_16(st_fx->last_good_fx,INACTIVE_CLAS)) + { + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + set16_fx( voice_factors, 32767, NB_SUBFR ); + } + ELSE + { + set16_fx( voice_factors, 32767, NB_SUBFR16k ); + } + } + ELSE + { + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + set16_fx( voice_factors, st_fx->last_voice_factor_fx, NB_SUBFR); /* The factor of the last subframe is propagated forward */ + } + ELSE + { + set16_fx( voice_factors, st_fx->last_voice_factor_fx, NB_SUBFR16k ); /* The factor of the last subframe is propagated forward */ + } + } + IF( st_fx->Opt_AMR_WB_fx ) + { + gain_dec_bfi_fx(st_fx->past_qua_en_fx); + } + st_fx->bfi_pitch_fx = pitch_buf[(L_frame/L_SUBFR)-1]; + move16(); + st_fx->bfi_pitch_frame_fx = st_fx->L_frame_fx; + move16(); + return; +} + + +/*calculates some conditions for Pulse resynchronization to take place*/ +static void pulseRes_preCalc(Word16* cond1, Word16* cond2, Word32* cond3 ,Word16 new_pit, Word16 Tc, Word16 L_frame) +{ + Word16 tmp_pit, tmp_pit_e, tmp_frame, tmp_frame_e; + Word32 tmp_pit2; + + tmp_pit = BASOP_Util_Divide1616_Scale(new_pit/*Q0*/,Tc/*Q0*/,&tmp_pit_e)/*Q15*/; + tmp_frame = add( extract_l(L_mult0(L_frame , 64/*1.f/L_SUBFR Q12*/)/*Q12*/) , 4096/*1.f Q12*/ );/*Q12*/ + tmp_frame = BASOP_Util_Divide1616_Scale(4096/*1.f Q12*/,tmp_frame, &tmp_frame_e);/*Q15*/ + tmp_frame = shl(tmp_frame,add(tmp_frame_e,1)); + tmp_frame = sub(32767/*1.f Q15*/, tmp_frame);/*Q15*/ + BASOP_SATURATE_WARNING_OFF + /*To calc Q15 threshold, overflow may happen - do negation and compare with negated value to check also highest possible value*/ + tmp_pit = shl(negate(tmp_pit),tmp_pit_e); + BASOP_SATURATE_WARNING_ON + *cond1 = sub(tmp_pit, negate(tmp_frame)); + + *cond2 = sub(Tc, new_pit); + + tmp_pit_e = BASOP_Util_Add_MantExp(new_pit,15-0,negate(Tc),15-0,&tmp_pit);/*Q15*/ + tmp_pit = abs_s(tmp_pit); + tmp_pit2 = L_mult(Tc,4915/*0.15f Q15*/);/*Q16*/ + BASOP_SATURATE_WARNING_OFF + /*To calc Q15 threshold, overflow may happen - do negation and compare with negated value to check also highest possible value*/ + tmp_pit2 = L_shl(L_negate(tmp_pit2),sub(15-16,tmp_pit_e)); + BASOP_SATURATE_WARNING_ON + *cond3 = L_sub(L_mult0(-1, tmp_pit),tmp_pit2); +} + +/*-------------------------------------------------------------------* + * gain_dec_bfi() + * + * Estimate past quantized gain prediction residual to be used in + * next frame + *-------------------------------------------------------------------*/ + +void gain_dec_bfi_fx( + Word16 *past_qua_en /* i/o: gain quantization memory (4 words) */ +) +{ + Word16 i; + Word16 av_pred_en; + Word32 Lav_pred_en; + + Lav_pred_en = L_mult(past_qua_en[0], 8192); + FOR (i = 1; i < GAIN_PRED_ORDER; i++) + { + Lav_pred_en = L_mac(Lav_pred_en, past_qua_en[i], 8192); + } + + /*av_pred_en = (float)(av_pred_en*(1.0f/(float)GAIN_PRED_ORDER)-3.0f);*/ + av_pred_en = sub(round_fx(Lav_pred_en),3<<10); + + /*if (av_pred_en < -14.0f)av_pred_en = -14.0f;*/ + av_pred_en = s_max(av_pred_en, -14 * (1 << 10)); + + + FOR (i=GAIN_PRED_ORDER-1; i>0; i--) + { + past_qua_en[i] = past_qua_en[i-1]; + move16(); + } + + past_qua_en[0] = av_pred_en; + move16(); + + return; +} diff --git a/lib_dec/FEC_lsf_estim_fx.c b/lib_dec/FEC_lsf_estim_fx.c new file mode 100644 index 0000000..63ecfe9 --- /dev/null +++ b/lib_dec/FEC_lsf_estim_fx.c @@ -0,0 +1,59 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * FEC_lsf_estim() + * + * - LSP calculation + * - A(z) calculation + *-------------------------------------------------------------------*/ + +void FEC_lsf2lsp_interp( + Decoder_State_fx *st, /* i/o: Decoder static memory */ + const Word16 L_frame, /* i : length of the frame */ + Word16 *Aq, /* o : calculated A(z) for 4 subframes */ + Word16 *lsf, /* o : estimated LSF vector */ + Word16 *lsp /* o : estimated LSP vector */ +) +{ + + /* convert LSFs to LSPs */ + IF ( st->Opt_AMR_WB_fx ) + { + E_LPC_isf_isp_conversion( lsf, lsp, M); + } + ELSE + { + IF( EQ_16(L_frame,L_FRAME)) + { + lsf2lsp_fx( lsf, lsp, M, INT_FS_FX ); + } + ELSE /* L_frame == L_FRAME16k */ + { + lsf2lsp_fx( lsf, lsp, M, INT_FS_16k_FX); + } + } + + /*----------------------------------------------------------------------* + * Interpolate LSP vector and find A(z) + *----------------------------------------------------------------------*/ + + IF ( st->Opt_AMR_WB_fx ) + { + int_lsp_fx( L_frame, st->lsp_old_fx, lsp, Aq, M, interpol_isp_amr_wb_fx, 1 ); + } + ELSE + { + int_lsp_fx( L_frame, st->lsp_old_fx, lsp, Aq, M, interpol_frac_fx, 0 ); + } + + return; +} diff --git a/lib_dec/FEC_pitch_estim_fx.c b/lib_dec/FEC_pitch_estim_fx.c new file mode 100644 index 0000000..0d8c948 --- /dev/null +++ b/lib_dec/FEC_pitch_estim_fx.c @@ -0,0 +1,104 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "basop_mpy.h" + +/*========================================================================*/ +/* FUNCTION : FEC_pitch_estim_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : Estimation of pitch for FEC */ +/* */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) st_fx->Opt_AMR_WB: flag indicating AMR-WB IO mode */ +/* _ (Word16) st_fx->L_frame_fx: length of the frame */ +/* _ (Word16) st_fx->clas_dec: frame classification */ +/* _ (Word16) st_fx->last_good_fx: last good clas information */ +/* _ (Word16[]) pitch : pitch values for each subframe Q6 */ +/* _ (Word16[]) old_pitch_buf:pitch values for each subframe Q6 */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*------------------------------------------------------------------------*/ + +/* _ (Word16[]) st_fx->bfi_pitch : initial synthesis filter states */ +/* _ (Word16) st_fx->bfi_pitch_frame: LP filter E of last */ +/* _ (Word16) st_fx->upd_cnt_fx: update counter */ +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ +void FEC_pitch_estim_fx( + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 last_core, /* i : last core */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 clas, /* i : current frame classification */ + const Word16 last_good, /* i : last good clas information */ + const Word16 pitch_buf[], /* i : Floating pitch for each subframe */ + const Word32 old_pitch_buf[], /* i : buffer of old subframe pitch values 15Q16 */ + Word16 *bfi_pitch, /* i/o: update of the estimated pitch for FEC */ + Word16 *bfi_pitch_frame, /* o : frame length when pitch was updated */ + Word16 *upd_cnt /* i/o: update counter */ + ,const Word16 coder_type /* i : coder_type */ +) +{ + Word16 tmp,tmp1,tmp2,tmp3; + Word16 tmp16k1,tmp16k2; + + tmp = mult_r(pitch_buf[1],22938); /*Q6( 0.7f * pitch_buf[1] 0.7 in Q15)*/ + tmp1 = shl(tmp,1); /*Q6 (1.4f * pitch_buf[1])*/ + tmp2 = round_fx(L_shl(Mpy_32_16_1(old_pitch_buf[2*NB_SUBFR-1],22938), 6)); /*Q6 (0.7f * old_pitch_buf[2*NB_SUBFR-1])*/ + tmp3 = shl(tmp2,1); /*Q6 (1.4f * old_pitch_buf[2*NB_SUBFR-1])*/ + + tmp16k1 = round_fx(L_shl(Mpy_32_16_1(old_pitch_buf[2*NB_SUBFR16k-1],22938), 6)); /*Q6 0.7f * old_pitch_buf[2*NB_SUBFR16k-1]*/ + tmp16k2 = shl(tmp16k1,1); /*Q6 1.4f * old_pitch_buf[2*NB_SUBFR16k-1]*/ + + IF( EQ_16(last_core,HQ_CORE)) + { + *bfi_pitch = pitch_buf[shr(L_frame,6)-1]; + move16(); + *bfi_pitch_frame = L_frame; + move16(); + *upd_cnt = MAX_UPD_CNT; + move16(); + } + + test(); + test(); + test(); + IF( (EQ_16(clas,VOICED_CLAS)&&GE_16(last_good,VOICED_TRANSITION))||(Opt_AMR_WB&&EQ_16(clas,VOICED_CLAS))) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( (LT_16(pitch_buf[3],tmp1))&&(GT_16(pitch_buf[3],tmp))&& + (LT_16(pitch_buf[1],tmp3) ) && (GT_16(pitch_buf[1],tmp2) ) && + (EQ_16(L_frame,L_FRAME) ) ) || + ( (LT_16(pitch_buf[3],tmp1) ) && (GT_16(pitch_buf[3],tmp) ) && + (LT_16(pitch_buf[1],tmp16k2) ) && (GT_16(pitch_buf[1],tmp16k1) ) && + (EQ_16(L_frame,L_FRAME16k) ) ) + || (EQ_16(coder_type, TRANSITION) ) ) + { + *bfi_pitch = pitch_buf[shr(L_frame,6)-1]; + move16(); + *bfi_pitch_frame = L_frame; + move16(); + *upd_cnt = 0; + move16(); + } + } +} + diff --git a/lib_dec/FEC_scale_syn_fx.c b/lib_dec/FEC_scale_syn_fx.c new file mode 100644 index 0000000..05ddbac --- /dev/null +++ b/lib_dec/FEC_scale_syn_fx.c @@ -0,0 +1,616 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "basop_mpy.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ +#define AGC_FX 32113 /* 0.98f */ +#define SCLSYN_LAMBDA (9830/*0.3f Q15*/) + +/*========================================================================*/ +/* FUNCTION : FEC_scale_syn_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : Smooth the speech energy evolution when */ +/* recovering after a BAD frame */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) L_frame : length of the frame */ +/* _ (Word16) *update_flg : indication about resynthesis */ +/* _ (Word16) st_fx->clas_dec: frame classification */ +/* _ (Word16) last_good : last good frame classification */ +/* _ (Word16[]) synth : synthesized speech at Fs = 12k8 Hz Q_syn */ +/* _ (Word16[]) pitch : pitch values for each subframe Q0 */ +/* _ (Word32) L_enr_old :energy at the end of previous frame Q0 */ +/* _ (Word16) L_enr_q : transmitted energy for current frame Q0 */ +/* _ (Word16) coder_type : coder type */ +/* _ (Word16) st_fx->prev_bfi_fx: previous frame BFI */ +/* _ (Word16) st_fx->last_core_brate_fx: previous frame core bitrate */ +/* _ (Word16[]) mem_tmp : temp. initial synthesis filter states Q_syn */ +/* _ (Word16) Q_exc : quantized LSPs from frame end */ +/* _ (Word16) Q_syn : quantized LSPs from frame end */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc : excitation signal without enhancement Q_exc */ +/* _ (Word16[]) exc2 : excitation signal with enhancement Q_exc */ +/* _ (Word16[]) Aq : LP filter coefs (can be modified if BR) Q12 */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*------------------------------------------------------------------------*/ + +/* _ (Word16[]) st_fx->mem_syn2 : initial synthesis filter states Q_syn */ +/* _ (Word16) st_fx->old_enr_LP : LP filter E of last Q5 */ +/* good voiced frame */ +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ + + +void FEC_scale_syn_fx( + const Word16 L_frame, /* i : length of the frame */ + Word16 *update_flg, /* o: flag indicating re-synthesis after scaling*/ + Word16 clas, /* i/o: frame classification */ + const Word16 last_good, /* i: last good frame classification */ + Word16 *synth, /* i/o: synthesized speech at Fs = 12k8 Hz */ + const Word16 *pitch, /* i: pitch values for each subframe */ + Word32 L_enr_old, /* i: energy at the end of previous frame */ + Word32 L_enr_q, /* i: transmitted energy for current frame */ + const Word16 coder_type, /* i: coder type */ + const Word16 LSF_Q_prediction, /* i : LSF prediction mode */ + Word16 *scaling_flag, /* i/o: flag to indicate energy control of syn */ + Word32 *lp_ener_FEC_av, /* i/o: averaged voiced signal energy */ + Word32 *lp_ener_FEC_max, /* i/o: averaged voiced signal energy */ + const Word16 bfi, /* i: current frame BFI */ + const Word32 total_brate, /* i: total bitrate */ + const Word16 prev_bfi, /* i: previous frame BFI */ + const Word32 last_core_brate, /* i: previous frame core bitrate */ + Word16 *exc, /* i/o: excitation signal without enhancement */ + Word16 *exc2, /* i/o: excitation signal with enhancement */ + Word16 Aq[], /* i/o: LP filter coefs (can be modified if BR) */ + Word16 *old_enr_LP, /* i/o: LP filter E of last good voiced frame */ + const Word16 *mem_tmp, /* i: temp. initial synthesis filter states */ + Word16 *mem_syn, /* o: initial synthesis filter states */ + Word16 Q_exc, + Word16 Q_syn + , Word16 avoid_lpc_burst_on_recovery /* i : if true the excitation energy is limited if LP has big gain */ + , Word16 force_scaling /* i: force scaling */ +) +{ + Word16 i; + Word32 L_enr1, L_enr2; + Word16 gain1, gain2, enr_LP; + Word16 tmp, tmp2, exp, exp2; + Word16 tmp3; + Word32 L_tmp; + Word16 scaling; + Word32 ener_max, L_enr2_av, L_ener2_max; + Word16 h1[L_FRAME/2], tilt, pitch_dist, mean_pitch; + Word16 k; + Word32 L_mean_pitch; + enr_LP = 0; + move16(); + gain2 = 0; + move16(); + gain1 = 0; + move16(); + *update_flg = 0; + move16(); + L_enr_old = L_max(1, L_enr_old); /* to avoid division by zero (*L_enr_old is always >= 0) */ + scaling = 16384; + move16(); /* Q14*/ + + /*-----------------------------------------------------------------* + * Find the synthesis filter impulse response on voiced + *-----------------------------------------------------------------*/ + test(); + IF( GE_16(clas,VOICED_TRANSITION)&<_16(clas,INACTIVE_CLAS)) + { + IF( EQ_16(L_frame,L_FRAME)) + { + enr_LP = Enr_1_Az_fx(Aq+(NB_SUBFR-1)*(M+1), L_SUBFR ); + } + ELSE /* L_frame == L_FRAME16k */ + { + enr_LP = Enr_1_Az_fx( Aq+(NB_SUBFR16k-1)*(M+1), L_SUBFR ); /*Q3*/ + } + } + + /*-----------------------------------------------------------------* + * Define when to scale the synthesis + *-----------------------------------------------------------------*/ + + IF( bfi ) + { + *scaling_flag = 1; + move16(); /* Always check synthesis on bad frames */ + } + ELSE IF( prev_bfi ) + { + test(); + IF( ( EQ_16(LSF_Q_prediction,AUTO_REGRESSIVE))||(EQ_16(LSF_Q_prediction,MOVING_AVERAGE))) + { + *scaling_flag = 2; + move16(); /* Decoded LSFs affected */ + } + ELSE IF( NE_16(coder_type,TRANSITION)) + { + *scaling_flag = 1; + move16(); /* SN, but not TC mode - LSF still affected by the interpolation */ + } + ELSE + { + *scaling_flag = 0; + move16(); /* LSF still possibly affected due to interpolation */ + } + scaling = 24576; /*1.5 Q14*/ move16(); + } + ELSE + { + test(); + IF( (EQ_16(LSF_Q_prediction,AUTO_REGRESSIVE))&&(EQ_16(*scaling_flag,2))) + { + *scaling_flag = 2; + move16(); /* Continue with energy control till the end of AR prediction */ + } + ELSE IF( *scaling_flag > 0 ) + { + (*scaling_flag) = sub(*scaling_flag,1); /* If scaling flag was equal to 2, add one control frame to account for the LSF interpolation */ + } + scaling = 32767; /*2.0 Q14*/ move16(); + } + + /*-----------------------------------------------------------------* + * Find the energy/gain at the end of the frame + *-----------------------------------------------------------------*/ + + /*fer_energy( L_frame, clas, synth, pitch[(L_frame>>6)-1], &enr2, L_frame );*/ + frame_ener_fx(L_frame,clas, synth, pitch[sub(shr(L_frame,6),1)], &L_enr2/*Q0*/, 1, Q_syn, 3, 0); + + if( bfi || (EQ_32(total_brate,ACELP_7k20))||(EQ_32(total_brate,ACELP_8k00))) + { + /* previous frame erased and no TC frame */ + IF( *scaling_flag > 0 ) + { + /*enr2 += 0.01f;*/ + L_enr2 = L_max(L_enr2, 1); /* L_enr2 is in Q0 */ + + IF( bfi ) /* In all bad frames, limit the gain to 1 */ + { + /* gain2 = (float)sqrt( enr_old / enr2 );*/ + L_tmp = Sqrt_Ratio32(L_enr_old, 0, L_enr2, 0, &exp2); + gain2 = round_fx(L_shl(L_tmp, sub(exp2, 1))); /* in Q14 */ + + /*if( gain2 > 1.0f )gain2 = 1.0f;*/ + gain2 = s_min(gain2, 16384); + + /* find the energy/gain at the beginning of the frame */ + frame_ener_fx(L_frame,clas, synth, pitch[0], &L_enr1/*Q0*/, 1, Q_syn, 3, 0); + + /*enr1 += 0.1f;*/ + L_enr1 = L_max(L_enr1, 1); /* L_enr2 is in Q0 */ + + /*gain1 = (float)sqrt( enr_old / enr1 );*/ + L_tmp = Sqrt_Ratio32(L_enr_old, 0, L_enr1, 0, &exp2); + gain1 = round_fx(L_shl(L_tmp, sub(exp2, 1))); /* in Q14 */ + + /*if( gain1 > 1.0f )gain1 = 1.0f;*/ + gain1 = s_min(gain1, 16384); + } + ELSE /* good frame */ + { + IF( L_enr_q == 0 ) /* If E info (FEC protection bits) is not available in the bitstream */ + { + L_enr_q = L_enr2; + set16_fx( h1, 0, L_FRAME/2 ); + h1[0] = 1024; + move16(); + /*syn_filt( Aq+(3*(M+1)), M, h1, h1, L_FRAME/2, h1+(M+1), 0 );*/ + E_UTIL_synthesis(1, Aq+(3*(M+1)), h1, h1, L_FRAME/2, h1+(M+1), 0, M); + + /*Compute tilt */ + /*rr0 = dotp( h1, h1, L_FRAME/2-1 ) + 0.1f;*/ + /*rr1 = dotp( h1, h1+1, L_FRAME/2-1 );*/ + /*tilt = rr1 / rr0;*/ + tilt = extract_h(L_shl(get_gain(h1+1, h1, L_FRAME/2-1),15)); + + pitch_dist = 0; + move16(); + L_mean_pitch = L_mult(pitch[0], 8192); + move32(); + FOR( k=0; k<(NB_SUBFR - 1); k++ ) + { + pitch_dist = add(pitch_dist, abs_s(sub(pitch[k+1],pitch[k]))); + L_mean_pitch = L_mac(L_mean_pitch, pitch[k+1], 8192); + } + /*pitch_dist /= (float)(NB_SUBFR-1); */ + pitch_dist = mult_r(shl(pitch_dist,4),10923); + /*mean_pitch /= (float)(NB_SUBFR);*/ + mean_pitch = extract_h(L_shl(L_mean_pitch,4)); + + + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( GT_16(tilt,22938))&& /* HF resonnant filter */ + ( (GT_16(pitch_dist, 8<<4) ) || (LT_16(mean_pitch,PIT_MIN<<4) ) ) && /* pitch unstable or very short */ + ( (prev_bfi) || ( (EQ_16(coder_type,GENERIC) ) && (EQ_16(LSF_Q_prediction,AUTO_REGRESSIVE) ) ) ) ) + { + /*if( enr_q > scaling * enr_old ){enr_q = scaling * enr_old;}*/ + L_enr_q = L_min(L_enr_q, L_shl(Mult_32_16(L_enr_old, scaling),1)); /* scaling in Q14*/ + } + ELSE + { + ener_max = *lp_ener_FEC_max; + move32(); + test(); + if( EQ_16(clas,VOICED_TRANSITION)||(GE_16(clas,INACTIVE_CLAS))) + { + ener_max = *lp_ener_FEC_av; + move32(); + } + /*if( enr_old > ener_max )ener_max = enr_old;*/ + ener_max = L_max(ener_max, L_enr_old); + + /*if( enr_q > scaling * ener_max ){enr_q = scaling * ener_max;}*/ + L_enr_q = L_min(L_enr_q, L_shl(Mult_32_16(ener_max, scaling),1)); /* scaling in Q14*/ + } + } + /*gain2 = (float)sqrt( enr_q / enr2 );*/ + L_enr_q = L_max(L_enr_q, 1); /* L_enr2 is in Q0 */ + L_tmp = Sqrt_Ratio32(L_enr_q, 0, L_enr2, 0, &exp2); + gain2 = round_fx(L_shl(L_tmp, sub(exp2, 1))); /* in Q14 */ + + /*-----------------------------------------------------------------* + * Find the energy/gain at the beginning of the frame to ensure smooth transition after erasure(s) + *-----------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( (GE_16(last_good,VOICED_TRANSITION)&<_16(last_good,INACTIVE_CLAS)&&(EQ_16(clas,UNVOICED_CLAS)||EQ_16(clas,INACTIVE_CLAS)))|| + EQ_32(last_core_brate,SID_1k75) || EQ_32(last_core_brate,SID_2k40) || EQ_32(last_core_brate,FRAME_NO_DATA) ) && prev_bfi ) + { + /* voiced -> unvoiced signal transition */ + /* CNG -> active signal transition */ + gain1 = gain2; + move16(); + } + ELSE + { + /* find the energy at the beginning of the frame */ + frame_ener_fx(L_frame,clas, synth, pitch[0], &L_enr1/*Q0*/, 1, Q_syn, 3, 0); + + /*enr1 += 0.1f;*/ + L_enr1 = L_max(L_enr1, 1); /* L_enr1 is in Q0 */ + + /*gain1 = (float)sqrt( enr_old / enr1 );*/ + L_tmp = Sqrt_Ratio32(L_enr_old, 0, L_enr1, 0, &exp2); + gain1 = round_fx(L_shl(L_tmp, sub(exp2, 1))); /* in Q14 */ + + /*if( gain1 > 1.2f )gain1 = 1.2f;*/ + /* prevent clipping */ + gain1 = s_min(gain1, 19661); + + /* prevent amplifying the unvoiced or inactive part of the frame in case an offset is followed by an onset */ + test(); + test(); + if( EQ_16(clas,ONSET)&>_16(gain1,gain2)&&prev_bfi) + { + gain1 = gain2; + move16(); + } + } + + L_enr2 = L_enr_q; + move32(); /* Set the end frame energy to the scaled energy, to be used in the lp_ener_FEC */ + } + + /*------------------------------------------------------------------------------* + * Smooth the energy evolution by exponentially evolving from gain1 to gain2 + *------------------------------------------------------------------------------*/ + + /*gain2 *= ( 1.0f - AGC );*/ + L_tmp = L_mult(gain2, (Word16)(32768 - AGC_FX)); + FOR( i=0; i scaling * enr_old )enr_q = scaling * enr_old;*/ + L_enr_q = L_min(L_enr_q, L_shl(Mult_32_16(L_enr_old, scaling),1)); /* scaling in Q14*/ + } + ELSE IF( GE_16(last_good,VOICED_TRANSITION)&<_16(last_good,INACTIVE_CLAS)&&GE_16(clas,VOICED_TRANSITION)&<_16(clas,INACTIVE_CLAS)) + { + /* Voiced-voiced recovery */ + test(); + IF( *old_enr_LP != 0 && GT_16(enr_LP, shl(*old_enr_LP, 1))) + { + /* enr_q /= enr_LP */ + exp = norm_l(L_enr_q); + tmp = extract_h(L_shl(L_enr_q, exp)); + + exp2 = norm_s(enr_LP); + tmp2 = shl(enr_LP, exp2); + + exp = sub(exp2, exp); + + tmp3 = sub(tmp, tmp2); + IF (tmp3 > 0) + { + tmp = shr(tmp, 1); + exp = add(exp, 1); + } + tmp = div_s(tmp, tmp2); + + /* L_enr_q *= 2 * *old_enr_LP */ + L_enr_q = L_shl(L_mult(tmp, shl(*old_enr_LP, 1)), exp); + } + + ELSE + { + test(); + IF( avoid_lpc_burst_on_recovery && GT_16(enr_LP, 160)) + { + exp = norm_s(enr_LP); + tmp = shl(enr_LP, exp); + + exp2 = 7; + move16(); + tmp2 = 160 << 7; /* 160 = 20.0f in Q3 */ + exp = sub(exp2, exp); + + IF (GT_16(tmp, tmp2)) + { + tmp = shr(tmp, 1); + exp = add(exp, 1); + } + tmp = div_s(tmp, tmp2); /* tmp*2^exp = enr_LP/20.0 */ + L_tmp = Isqrt_lc(L_deposit_h(tmp), &exp); /* L_tmp*2^exp = sqrt(20.0/enr_LP) */ + L_enr_q = L_shl(Mpy_32_32(L_enr_q, L_tmp), exp); + } + } + + } + + test(); + test(); + test(); + IF( (GE_16(last_good,VOICED_TRANSITION)&<_16(last_good,INACTIVE_CLAS)&&GE_16(clas,VOICED_TRANSITION)&<_16(clas,INACTIVE_CLAS)) + || force_scaling ) + { + + IF( GT_32(L_enr_q, L_enr_old)) /* Prevent energy to increase on voiced */ + { + L_enr_q = L_add(Mpy_32_16_1(L_enr_old, 32767 - SCLSYN_LAMBDA), Mpy_32_16_1(L_enr_q, SCLSYN_LAMBDA)); + } + } + } + + L_enr_q = L_max(1, L_enr_q); + + /* gain2 = (float)sqrt( enr_q / enr2 );*/ + exp = norm_l(L_enr_q); + tmp = extract_h(L_shl(L_enr_q, exp)); + + exp2 = norm_l(L_enr2); + tmp2 = extract_h(L_shl(L_enr2, exp2)); + + exp2 = sub(exp, exp2); /* Denormalize and substract */ + + tmp3 = sub(tmp2, tmp); + IF (tmp3 > 0) + { + tmp2 = shr(tmp2, 1); + exp2 = add(exp2, 1); + } + + tmp = div_s(tmp2, tmp); + + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp2); + gain2 = round_fx(L_shl(L_tmp, sub(exp2, 1))); /* in Q14 */ + + /*-----------------------------------------------------------------* + * Clipping of the smoothing gain at the frame end + *-----------------------------------------------------------------*/ + + gain2 = s_min(gain2, 19661); /* Gain modification clipping */ + if (LT_32(L_enr_q, 2)) + { + gain2 = s_min(gain2, 16384); /* Gain modification clipping */ + } + + /*-----------------------------------------------------------------* + * Find the energy/gain at the beginning of the frame to ensure smooth transition after erasure(s) + *-----------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_16(clas,SIN_ONSET)) /* slow increase */ + { + gain1 = shr(gain2, 1); + } + /*------------------------------------------------------------* + * voiced->unvoiced transition recovery + *------------------------------------------------------------*/ + ELSE IF( (GE_16(last_good,VOICED_TRANSITION)&<_16(last_good,INACTIVE_CLAS)&&(EQ_16(clas,UNVOICED_CLAS)||EQ_16(clas,INACTIVE_CLAS)))|| /* voiced->unvoiced transition recovery */ + EQ_32(last_core_brate,SID_1k75) || EQ_32(last_core_brate,SID_2k40) || EQ_32(last_core_brate,FRAME_NO_DATA)) /* CNG -> active signal transition */ + { + gain1 = gain2; + move16(); + } + ELSE + { + /*--------------------------------------------------------* + * Find the energy at the beginning of the frame + *--------------------------------------------------------*/ + tmp = frame_ener_fx(L_frame,clas, synth, pitch[0], &L_enr1, 0, Q_syn, 3, 0); + + /*gain1 = (float)sqrt( enr_old / enr1 );*/ + exp = norm_l(L_enr_old); + tmp = extract_h(L_shl(L_enr_old, exp)); + exp2 = norm_l(L_enr1); + tmp2 = extract_h(L_shl(L_enr1, exp2)); + + exp2 = sub(exp, exp2); /* Denormalize and substract */ + + tmp3 = sub(tmp2, tmp); + + IF (tmp3 > 0) + { + tmp2 = shr(tmp2, 1); + exp2 = add(exp2, 1); + } + + tmp = div_s(tmp2, tmp); + + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp2); + gain1 = round_fx(L_shl(L_tmp, sub(exp2, 1))); /* in Q14 */ + /* exp2 is always <= 1 */ + + gain1 = s_min(gain1, 19661); + + test(); + test(); + if( avoid_lpc_burst_on_recovery && (GT_16(enr_LP, 160))&&(LE_16(enr_LP,shl(*old_enr_LP,1)))) + { + gain1 = s_min(gain1, 16384); + } + + /*--------------------------------------------------------* + * Prevent a catastrophy in case of offset followed by onset + *--------------------------------------------------------*/ + test(); + if( ( EQ_16(clas,ONSET))&&(GT_16(gain1,gain2))) + { + gain1 = gain2; + move16(); + } + } + /*-----------------------------------------------------------------* + * Smooth the energy evolution by exponentially evolving from + * gain1 to gain2 + *-----------------------------------------------------------------*/ + + L_tmp = L_mult(gain2, (Word16)(32768 - AGC_FX)); + + FOR( i=0; i0.25119f;*/ move16(); + } + ELSE IF( EQ_16(music_flag2,3)) + { + min_band = 3; + move16(); + local_min_gain = 8231; /*Q15->0.25119f; */ move16(); + } + ELSE IF( EQ_16(music_flag2,2)) + { + min_band = 4; + move16(); + local_min_gain = 11626; /*Q15->0.35481f; */ move16(); + } + ELSE IF( EQ_16(music_flag2,1)) + { + min_band = 4; + move16(); + local_min_gain = 16423; /*Q15->0.50119f;*/ move16(); + } + + min_band = add(min_band, 4); + + MAX_GN = 1638; /*Q14*/ move16(); + if( GT_32(core_brate,ACELP_9k60)) + { + /* overshoot not allowed, since GSC already matches the energy */ + MAX_GN = 0; + move16(); + } + + if( EQ_16(coder_type,AUDIO)) + { + /* with GSC we know for sure that we are in music */ + min_band = s_min( min_band, 3 ); + } + + /*------------------------------------------------------------------------* + * Approximation of the inter-harmonic noise level + * - sort the bin energy + * - compupte the average energy per band excluding the maximum energy bin + *------------------------------------------------------------------------*/ + + j = 0; + move16(); + Ltmp_max = L_deposit_l(0); + FOR (i = 0; i < MBANDS_GN_LD; i++) + { + Ltmp = L_deposit_l(0); + max_val = L_deposit_l(0); + + FOR( k=j; k < mfreq_bindiv_LD[i]+j; k++ ) + { + /*m_ave += lf_E[k];*/ + Ltmp = L_add(lf_E[k], Ltmp); + max_val = L_max(max_val, lf_E[k]); + } + Ltmp_max = L_max(Ltmp_max, max_val); + /*m_ave -= max_val;*/ + Ltmp = L_sub(Ltmp, max_val); + /*m_ave /=(mfreq_bindiv_LD[i]-1);*/ + m_ave = Mult_32_16(Ltmp,inv_mfreq_bindiv_LD_M1_fx[i]); + + /*bckr[i] = m_ave*sc_qnoise[i];*/ + bckr[i] = Mult_32_16(m_ave,sc_qnoise_fx[i]); + move32(); + + j+=mfreq_bindiv_LD[i]; + } + + /* This is computed inside the loop i = maximum(lf_E, DCT_L_POST, &m_ave);*/ + /*------------------------------------------------------------------------* + * - Normalisation of the energy vector between [0.72, 5], with the form of pow(x,4) + * - Simple LP filtering along the frequency domain + * - LT averaging with the past and in function of the stability factor + *------------------------------------------------------------------------*/ + /*m_ave = ALPH/lf_E[i];*/ + exp1 = norm_l(Ltmp_max); + mant = extract_h(L_shl(Ltmp_max, exp1)); + /*exp1 = sub(16,exp1);*/ + + s_ave = div_s(16384, mant); + exp1 = sub(14/*+15*/+16, exp1); /*s_ave in Q15 + exp1*/ + old_tmp16 = norm_lfe(lf_E[0], s_ave, exp1); + old_tmp16 = s_min(old_tmp16, MAXX_Q12_FX); + tmp16 = norm_lfe(lf_E[1], s_ave, exp1); + tmp16 = s_min(tmp16, MAXX_Q12_FX); + old_tmp16_1 = tmp16; + move16(); + tmp_lfE[0] = round_fx(L_mac(L_mult(16384, old_tmp16), 16384, tmp16)); + + FOR(i = 1; i < DCT_L_POST-1; i++) + { + /*tmp_lfE[i] = 0.333f*old_ftmp + 0.333f*ftmp; */ + Ltmp = L_mac(L_mult(10813, old_tmp16), 10813, old_tmp16_1); + + old_tmp16 = old_tmp16_1; + move16(); + tmp16 = norm_lfe(lf_E[i+1], s_ave, exp1); + /*ftmp = min(ftmp, MAXX); + tmp_lfE[i] += 0.333f*ftmp; */ + old_tmp16_1 = s_min(tmp16, MAXX_Q12_FX); + Ltmp = L_mac(Ltmp, 10813, old_tmp16_1); + tmp_lfE[i] = round_fx(Ltmp); + } + + tmp16 = norm_lfe(lf_E[i], s_ave, exp1); + /*ftmp = min(ftmp, MAXX); + tmp_lfE[i] = 0.5f*old_ftmp + 0.5f*ftmp;*/ + tmp16 = s_min(tmp16, MAXX_Q12_FX); + tmp_lfE[i] = round_fx(L_mac(L_mult(16384, old_tmp16), 16384, tmp16)); + + FOR(i = 0; i < BIN_4KHZ; i++) + { + /*filt_lfE[i] = tmp_lfE[i]*.05f + .95f*filt_lfE[i] ;*/ + filt_lfE[i] = round_fx(L_mac(L_mult(tmp_lfE[i],1638), 31130, filt_lfE[i])) ; + } + + FOR(; i < DCT_L_POST; i++) + { + /*filt_lfE[i] = tmp_lfE[i]*(.15f) + .85f*filt_lfE[i] ;*/ + filt_lfE[i] = round_fx(L_mac(L_mult(tmp_lfE[i],4915), 27853, filt_lfE[i])) ; + } + /*------------------------------------------------------------------------* + * - Reduce inter-harmonic noise with SNR based method + * - Second stage of spectral shaping modification based + * on the pow(x,4) energy spectrum + *------------------------------------------------------------------------*/ + + if( EQ_16(coder_type,AUDIO)) + { + MAX_band = 16; + move16(); + } + + Copy(dtc_in, dtc_out, DCT_L_POST); + + spectrum_mod_dct_fx( Qdct, dtc_out, lf_E, lf_EO, bckr, local_min_gain, lp_gbin, music_flag2, min_band, MAX_GN, MAX_band ); + + i = 0; + move16(); + IF( GE_16(music_flag2,1)) + { + FOR(i = 0; i < BIN_1KHZ; i++) + { + tmp16 = s_min(4096, filt_lfE[i]); + dtc_out[i] = round_fx(L_shl(L_mult(dtc_out[i], tmp16),3)); + } + } + { + IF( GT_16(*last_nonfull_music,40)) + { + max_ovf_2k = 5120; /*1.25 Q12*/ move16(); + max_ovf_4k = 6144; /*1.5 Q12*/ move16(); + max_ovf_6k = 6144; /*1.5 Q12*/ move16(); + + min_g_2k = 0; + move16(); + min_g_4k = 0; + move16(); + min_g_6k = 0; + move16(); + + IF( EQ_16(coder_type,AUDIO )) + { + max_ovf_2k = 4096; /*1.0 Q12*/ move16(); + max_ovf_4k = 4506; /*1.1 Q12*/ move16(); + max_ovf_6k = 5120; /*1.25 Q12*/ move16(); + + min_g_2k = 3072; /*0.75 Q12*/ move16(); + min_g_4k = 2048; /*0.5 Q12*/ move16(); + min_g_6k = 2048; /*0.5 Q12*/ move16(); + + IF( GT_32(core_brate,ACELP_9k60)) + { + max_ovf_4k = 4096; /*1.0 Q12*/ move16(); + max_ovf_6k = 4710; /*1.15 Q12*/ move16(); + + min_g_2k = 3789; /*0.925 Q12*/ move16(); + min_g_4k = 3379; /*0.825 Q12*/ move16(); + min_g_6k = 3072; /*0.75 Q12*/ move16(); + } + } + ELSE IF( GE_32(core_brate,ACELP_12k65)) + { + max_ovf_2k = 4096; /*1.0 Q12*/ move16(); + max_ovf_4k = 5120; /*1.25 Q12*/ move16(); + + IF( GT_32(core_brate,ACELP_15k85)) + { + max_ovf_4k = 4096; /*1.0 Q12*/ move16(); + max_ovf_6k = 5120; /*1.25 Q12*/ move16(); + + min_g_2k = 3072; /*0.75 Q12*/ move16(); + min_g_4k = 2048; /*0.5 Q12*/ move16(); + min_g_6k = 2048; /*0.5 Q12*/ move16(); + } + } + + FOR(; i < BIN_2KHZ; i++) + { + tmp16 = s_min(max_ovf_2k, filt_lfE[i]); + tmp16 = s_max(min_g_2k, tmp16); + /*DCT_buf[i] *= ftmp;*/ + dtc_out[i] = round_fx(L_shl(L_mult(dtc_out[i], tmp16),3)); + + } + + FOR(; i < BIN_4KHZ; i++) + { + tmp16 = s_min(max_ovf_4k, filt_lfE[i]); + tmp16 = s_max(min_g_4k, tmp16); + /*DCT_buf[i] *= ftmp;*/ + dtc_out[i] = round_fx(L_shl(L_mult(dtc_out[i], tmp16),3)); + } + + test(); + IF( NE_16(coder_type,AUDIO)||GT_32(core_brate,ACELP_8k85)) + { + /* Do not modify HF when coded with GSC at LR, because the spectrum is just noise */ + FOR(; i < DCT_L_POST; i++) + { + tmp16 = s_min(max_ovf_6k, filt_lfE[i]); + tmp16 = s_max(min_g_6k, tmp16); + /*DCT_buf[i] *= ftmp;*/ + dtc_out[i] = round_fx(L_shl(L_mult(dtc_out[i], tmp16),3)); + } + } + } + ELSE IF( GT_16(*last_nonfull_music,25)) + { + /* When unsure on content type only slight clean-up allowed, no overshoot allowed */ + FOR(; i < DCT_L_POST; i++) + { + tmp16 = s_min(4096,filt_lfE[i]); + /*DCT_buf[i] *= ftmp;*/ + dtc_out[i] = round_fx(L_shl(L_mult(dtc_out[i], tmp16),3)); + } + } + } +} + +/*---------------------------------------------------------------------------* + * spectrum_mod_dct() + * + * spectrum enhancement according to the output of signal_type_clas() + *---------------------------------------------------------------------------*/ + +static void spectrum_mod_dct_fx( + const Word16 Qdct, /* i : scaling factor Q0 */ + Word16 data[], /* i/o: dct spectrum */ + const Word32 lf_E[], /* i: per bin E for first 46 bins (without DC) 2*Qdct+10 */ + Word32 lf_EO[], /* i/o: old per bin E for previous half frame 2*Qdct+10 */ + const Word32 noiseE[], /* i: per band background noise energy estimate 2*Qdct+10 */ + const Word16 minGain, /* i: minimum suppression gain Q15 */ + Word16 lp_gbin[], /* i/o: Smoothed suppression gain, per FFT bin Q14*/ + const Word16 music_flag, /* i: music ? 1:0 */ + Word16 min_band, /* i : minimum band */ + const Word16 MAX_GN, /* i : Maximum gain overshoot */ + const Word16 MAX_band /* i : minimum band */ +) +{ + Word32 maxNoise; + Word32 binE[VOIC_BINS_HR], Lgain; + Word16 gain = 0, minE; + Word16 freq, slope, m_invno[MBANDS_GN_LD],e_invno[MBANDS_GN_LD]; + Word16 *pt_gbin, alpha, tmpN; + Word16 i; + Word32 Ltmp; + Word16 scaling; + Word16 tmp_snr; + Word16 *pt; + Word16 wtmp; + Word16 e_tmp; + Word16 m_binE, e_binE; + Word16 e_gain; + Word16 sqrt_gain; + Word32 Lshift; + Word32 dot5_scaled; + const Word32 *Lpt2; + + gain = 0; + move16(); + + /*-----------------------------------------------------------------* + * Compute the inverse of noise + *-----------------------------------------------------------------*/ + + scaling = add(shl(Qdct,1),10); + dot5_scaled = L_shl(1, sub(scaling,1)); + FOR ( i=0; i<=MBANDS_GN_LD-1; i++) + { + /*inv_noise[i] = 1.0f / noiseE[i];*/ + IF (noiseE[i] != 0) + { + e_invno[i] = norm_l(noiseE[i]); + move16(); + m_invno[i] = extract_h(L_shl(noiseE[i],e_invno[i])); + e_invno[i] = sub(14, e_invno[i]); + move16(); + m_invno[i] = div_s(16384, m_invno[i]); + move16(); + } + ELSE + { + /* noiseE[i] == 0 only if Q_new <0*/ + e_invno[i] = add(-16,Qdct); + move16(); + m_invno[i] = MAX_16; + move16(); + } + } + /*----------------------------------------------------------------------* + * Perform noise reduction for 1 frames + *----------------------------------------------------------------------*/ + FOR (i=0 ; i < VOIC_BINS_HR ; i++) + { + /*binE[i] = (float)(0.3 * lf_EO[i] + 0.7 * lf_E[i]);*/ + Ltmp = Mult_32_16(lf_EO[i], 9830); + binE[i] = Madd_32_16(Ltmp, lf_E[i], 22938); + move32(); + } + Copy32( lf_E, lf_EO, VOIC_BINS_HR ); /* update */ + /*----------------------------------------------------------------------* + * Find the maximum noise in a critical band + *----------------------------------------------------------------------*/ + + maxNoise = L_max(noiseE[0], noiseE[1]); + FOR (i=2; i<=MBANDS_GN_LD-1; i++) + { + maxNoise = L_max(maxNoise, noiseE[i]); + } + + /* pointer initialization */ + pt = &data[0]; + + /*-----------------------------------------------------------------* + * Initialization for active speech frames or VAD hangover frames, + * (exclude Clean speech) + *-----------------------------------------------------------------*/ + + IF ( music_flag != 0 ) /* prevent subtraction on clean speech */ + { + IF( LE_32(maxNoise, L_shl(10, scaling))) + { + minE = 18432/2; /*Q14*/ move16(); + } + ELSE + { + minE = shr(mult_r(minGain, minGain),1); /*Q14*/ + } + + Lpt2 = binE; + freq = 0; + move16(); + + pt_gbin = lp_gbin; + FOR (i=0; i < min_band; i++) + { + + FOR (; freq <= mfreq_loc_LD_fx[i]; freq += BIN_16kdct_fx) + { + Lpt2++; + /* Lgain is already saturate if it's > 1*/ + pt++; + *pt_gbin = 16384; + move16(); + pt_gbin++; + } + } + /*-----------------------------------------------------------------* + * Per Frequency BIN processing + * For highly voiced and highly pitched speech, use per bin + * subtraction in low frequencies (maximum up to 3700 Hz, + * first 17 critical bands) + *-----------------------------------------------------------------*/ + + FOR (; i < MAX_band; i++) + { + + /*tmp = INV_MAX_SNR_tab[i]; + slope = tmp - tmp * minE; + shift = MAX_SNR_SNR1_tab[i] * minE - tmp;*/ + + /*tmp = 1.0f/ (MAX_SNR1 - 1.0f);*/ + tmp_snr = INV_MAX_SNR_tab_FX[i]; + move16(); + /*slope = -tmp * minE + tmp;*/ + Ltmp = L_mult(tmp_snr, 16384); + slope = msu_r(Ltmp,tmp_snr, minE); /*Q14*/ + + /*shift = MAX_SNR1 * tmp * minE - tmp;*/ + Ltmp = L_mult(MAX_SNR_SNR1_tab_FX[i], minE); /*Q14*Q14*/ + Lshift = L_msu(Ltmp, tmp_snr,8192); /*Q15*Q13+Q29*/ + Lshift = L_shl(Lshift,1); /*Q29 -> Q30*/ + + /*tmpN = slope * inv_noise[i];*/ + tmpN = mult(slope, m_invno[i]); + e_tmp = e_invno[i]; + move16(); + + /*while (freq <= mfreq_loc_LD[i])*/ + FOR (; freq <= mfreq_loc_LD_fx[i]; freq += BIN_16kdct_fx) + { + /*gain = 1.0f;*/ + Lgain = L_deposit_h(16384); + /*if (noiseE[i] >= 0.5f)*/ + IF (GT_32(noiseE[i], dot5_scaled))/* Do not alter if noise E very low */ + { + /*gain = tmpN * *pt2 + shift;*/ /* limits: [x,y] = {[1, minE], [MAX_SNR1, 1]}, */ + e_binE = norm_l(*Lpt2); + m_binE = extract_h(L_shl(*Lpt2, e_binE)); + + e_binE = sub(e_binE,0); /* lf_e divided by 4 in anal_sp*/ + + Ltmp = L_mult(tmpN, m_binE); + e_binE = sub(add(e_tmp, e_binE),15); + Ltmp = L_shr(Ltmp, e_binE); + Lgain = L_add(Ltmp, Lshift); /*Saturation can occure here result in Q30*/ + } + + Lpt2++; + gain = round_fx(Lgain); /*gain in Q30-16 = Q14*/ + /*if (gain < minE)gain = minE;*/ + gain = s_max(gain,minE); + /*if (gain > 1.0f+MAX_GN)gain = 1.0f+MAX_GN;*/ + gain = s_min(gain,add(16384, MAX_GN)); + + /* prepare gain to find sqrt */ + e_gain = norm_s(gain); + Ltmp = L_shl(gain, add(16,e_gain)); + e_gain = negate(sub(e_gain,1)); + + Ltmp = Isqrt_lc(Ltmp, &e_gain); + wtmp = extract_h(Ltmp); + sqrt_gain = div_s(16384,wtmp); + + + /* the gain smoothing control: stronger lp filtering for lower gains */ + /*alpha = 1.0f - (float)sqrt(gain);*/ + /* keep gain in Q14*/ + sqrt_gain = shr(sqrt_gain, e_gain); + /*alpha = 1.0f - gain;*/ /* the gain smoothing control: stronger LP filtering for lower gains */ + alpha = shl(sub(16384, sqrt_gain),1); + + /**pt_gbin = gain + alpha * *pt_gbin;*/ + Ltmp = L_mult(gain, 32767); + *pt_gbin = round_fx(L_mac(Ltmp, alpha, *pt_gbin)); /*Q14*/ + /**pt++ *= *pt_gbin;*/ + *pt = round_fx(L_shl(L_mult(*pt, *pt_gbin),1)); + pt++; + pt_gbin++; + } + } + } + ELSE + { + freq = BIN_16kdct_fx; + move16(); + pt_gbin = lp_gbin; + move16(); + FOR (i=0; i < MBANDS_GN_LD; i++) + { + FOR (; freq <= mfreq_loc_LD[i]; freq += BIN_16kdct_fx) + { + /**pt_gbin = 0.9f* *pt_gbin + 0.1f;*/ + *pt_gbin = round_fx(L_mac(L_mult(29491, *pt_gbin), 32767, 1638)); + pt_gbin++; + } + } + } + + return; + +} + + +/*----------------------------------------------------------------------------------* + * analy_sp_dct() + * + * Spectral analysis of the current synthesized frame + *----------------------------------------------------------------------------------*/ + +static void analy_sp_dct_fx( + const Word16 *dct_buf, /* i input dct spectrum */ + Word32 *fr_bands, /* o: energy in critical frequency bands 2*Qdct+10 */ + Word32 *lf_E, /* o: per bin E for first... 2*Qdct+10 */ + Word16 *etot, /* o: total input energy Q8 */ + const Word16 Qdct /* i: Scaling of dct */ +) +{ + Word32 Letot = 0; + Word16 exp_etot, frac_etot; + + Letot = L_deposit_l(0); + /*-----------------------------------------------------------------* + * find energy per critical frequency band and total energy in dB + *-----------------------------------------------------------------*/ + find_enr_dct_fx(dct_buf, fr_bands, lf_E, &Letot, 0, MBANDS_GN_LD, Qdct, BIN_16kdct_fx ); + + /* find average log total energy over both half-frames */ + /**etot = 10.0f * (float)log10(*etot) - 3.0103f;*/ + exp_etot = norm_l(Letot); + frac_etot = Log2_norm_lc(L_shl(Letot, exp_etot)); + exp_etot = sub(30, exp_etot); + exp_etot = sub(exp_etot, add(shl(Qdct,1),10+1)); /* +(1) */ + Letot = Mpy_32_16(exp_etot, frac_etot, LG10); + /* Q8 Averaged the total energy over both half-frames in log10 */ + *etot = extract_l(L_shr(Letot, 14-8)); + + return; +} + +/*------------------------------------------------------------------------* + * find_enr_dct) + * + * find input signal energy for each critical band and first 74 LF bins + * The energy is normalized by the number of frequency bins in a channel + *------------------------------------------------------------------------*/ + +static void find_enr_dct_fx( + const Word16 data[], /* i : dct result, for the format Qdct*/ + Word32 band[], /* o : per band energy 2*Qdct+10*/ + Word32 *ptE, /* o : per bin energy for low frequencies 2*Qdct+10*/ + Word32 *Etot, /* o : total energy 2*Qdct+10*/ + const Word16 min_band, /* i : minimum critical band Q0 */ + const Word16 max_band, /* i : maximum critical band Q0 */ + const Word16 Q_dct, /* i : scaling factor Q0 */ + const Word16 bin_freq /* i : Number of frequency bins Q0 */ +) +{ + Word16 i; + Word16 freq; + const Word16 *ptR; + Word32 LE_min, Ltmp, Ltmp1; + + LE_min = L_max(L_shl(E_MIN_Q15, sub(shl(Q_dct,1)+10,22)),1); + + ptR = &data[0]; /* pointer to first real coefficient */ + freq = 0; + move16(); + FOR( i=0; i < max_band; i++ ) + { + band[i] = 0; + move16(); + Ltmp1 = L_deposit_l(0); + FOR(; freq <= mfreq_loc_LD_fx[i]; freq += bin_freq) + { + /* energy */ + /**ptE = *ptR * *ptR; */ + Ltmp = L_mult(*ptR, *ptR); + + /* normalization */ + /**ptE *= 1.0f / (DCT_L_POST);*/ + Ltmp = Mult_32_16(Ltmp, 26214); /*26214 = 1.0/640 ->Q15+9 --> 2*Q_dct + 9*/ + Ltmp = L_max(Ltmp, LE_min); + *ptE = Ltmp; + move32(); + + /*band[i] += *ptE++;*/ + Ltmp1 = L_add(Ltmp, Ltmp1); + + ptE++; + ptR++; + } + + /* normalization per frequency bin */ + /*band[i] /= cnt;*/ + band[i] = L_max(Mult_32_16(Ltmp1, inv_mfreq_bindiv_LD_fx[i]), LE_min); + move32(); /* 2*Q_dct + 9*/ + + } + + /*-----------------------------------------------------------------* + * Find the total energy over the input bandwidth + *-----------------------------------------------------------------*/ + + Ltmp = 0; + move16(); + FOR( i = min_band; i <= NB_LIMIT_BAND; i++ ) + { + /* total channel energy */ + Ltmp = L_add(band[i],Ltmp); + } + + *Etot = Ltmp; + move32(); + + return; +} + +/*------------------------------------------------------------------------* + * Prep_music_postP() + * + * Performs the steps needed to do the music post processing + *------------------------------------------------------------------------*/ + +void Prep_music_postP_fx( + Word16 exc_buffer_in[], /* i/o: excitation buffer Q_exc*/ + Word16 dct_buffer_out[], /* o : DCT output buffer (qdct)*/ + Word16 filt_lfE[], /* i/o: long term spectrum energy Q15?*/ + const Word16 last_core, /* i : last core */ + const Word16 *pitch_buf, /* i : current frame pitch information Q6*/ + Word16 *LDm_enh_lp_gbin, /* o : smoothed suppression gain, per dct bin Q14*/ + const Word16 Q_exc, /* i : excitation scaling */ + Word16 *qdct /* o : Scaling factor of dct coefficient */ +) +{ + Word16 i; + Word16 *pt1; + const Word16 *pt2; + Word16 s_pit, fr_pit; + + Word16 exc16[DCT_L_POST]; + Word16 *pt1_out; + + s_pit = shr(pitch_buf[3],6); + fr_pit = shr(sub(pitch_buf[3], shl(s_pit,6)),4); /* Find fractional part */ + + /*------------------------------------------------------------* + * Resetting some memories in case of switching + *------------------------------------------------------------*/ + + IF( EQ_16(last_core,HQ_CORE)) + { + set16_fx( filt_lfE, 4096, DCT_L_POST ); + set16_fx( LDm_enh_lp_gbin, 16384, VOIC_BINS_HR ); + pt1 = exc_buffer_in + OFFSET2 - 1; + pt2 = pt1 + shr_r(pitch_buf[0],6); + FOR( i = 0; i < OFFSET2; i++ ) + { + *pt1 = *pt2; + move16(); + pt1--; + pt2--; + } + } + + /*------------------------------------------------------------* + * Extrapolation of the last future part and windowing + *------------------------------------------------------------*/ + pt1 = exc_buffer_in + DCT_L_POST - OFFSET2; + pred_lt4(pt1, pt1, s_pit, fr_pit, OFFSET2, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP); + /*------------------------------------------------------------* + * windowing right side + *------------------------------------------------------------*/ + pt2 = post_dct_wind_fx; + pt1_out = exc16 + DCT_L_POST - OFFSET2; + FOR( i = 0; i < OFFSET2; i++ ) + { + *pt1_out = mult_r(*pt1,*pt2); + move16(); + pt1++; + pt2++; + pt1_out++; + } + /*------------------------------------------------------------* + * windowing left side + *------------------------------------------------------------*/ + pt1 = exc_buffer_in; + pt1_out = exc16; + pt2--; + FOR( i = 0; i < OFFSET2; i++ ) + { + *pt1_out = mult_r(*pt1,*pt2); + move16(); + pt1++; + pt1_out++; + pt2--; + } + /*------------------------------------------------------------* + * Copy remaining data (Flat part) + *------------------------------------------------------------*/ + + FOR(; i < L_FRAME+OFFSET2; i++ ) + { + *pt1_out = *pt1; + move16(); + pt1++; + pt1_out++; + } + /*------------------------------------------------------------* + * EDCT and back to 16 bits + *------------------------------------------------------------*/ + + edct_16fx(exc16, dct_buffer_out, DCT_L_POST, 6); + *qdct = Q_exc; + move16(); + + return; +} +/*------------------------------------------------------------------------* + * norm_lfe() + * + * Energy bins normalisation + *------------------------------------------------------------------------*/ +static Word16 norm_lfe( + const Word32 Lfe, /* i: energy bin to normalize 2*Qdct+10 */ + const Word16 m_norm, /* i: Normalisation factor Q e_norm */ + const Word16 e_norm /* i: Exponent of the normalisation factor */ +) +{ + Word32 Ltmp; + Word16 exp2, tmp16, exp3 ; + + Ltmp = Mult_32_16(Lfe, m_norm); + Ltmp = L_add(Ltmp, L_shl(BET_Q15_FX, sub(e_norm,15))); /* Ltmp -> e_norm*/ + exp2 = norm_l(Ltmp); + tmp16 = extract_h(L_shl(Ltmp,exp2)); /* exp2 -= 16 */ + exp2 = add(e_norm,exp2); + + tmp16 = mult_r(tmp16,tmp16); /* tmp16 in Q exp2 */ + tmp16 = mult_r(tmp16,tmp16); + tmp16 = mult_r(tmp16,tmp16); + + exp3 = sub(12+16, exp2); /* tmp16 in Q exp2 */ + if(NE_16(exp2,31)) + { + exp3 = sub(exp2, 12+16-3); /* if exp2 < 31, means that tmp >= 1.0 */ + /* Need to shl by 3 to take into account the 3 multiplications */ + } + tmp16 = shl(tmp16, exp3); /* Result in Q12 */ + + return tmp16; +} + +/*------------------------------------------------------------------------* + * Post_music_postP() + * + * Going back from frequency to time domain from the enhanced spectrum. + * Retreive the aligned excitation and redo the synthesis + *------------------------------------------------------------------------*/ + +void Post_music_postP_fx( + Word16 dct_buffer_in[], /* i/o: excitation buffer */ + Word16 *exc2, /* i/o: Current excitation to be overwriten */ + const Word16 *mem_tmp, /* i : previous frame synthesis memory */ + Word16 *st_mem_syn2, /* i/o: current frame synthesis memory */ + const Word16 *Aq, /* i : LPC filter coefficients */ + Word16 *syn, /* i/o: 12k8 synthesis */ + Word16 *Q_exc, /* i : excitation scaling */ + Word16 *prev_Q_syn, /* i : previsous frame synthesis scaling */ + Word16 *Q_syn, /* i : Current frame synthesis scaling */ + Word16 *mem_syn_clas_estim_fx, /* i : old 12k8 synthesis used for frame classification*/ + const Word16 IsIO, /* i: Flag to indicate IO mode */ + Word16 *mem_deemph, /* i/o: speech deemph filter memory */ + Word16 *st_pst_old_syn_fx, /* i/o: psfiler */ + Word16 *st_pst_mem_deemp_err_fx, /* i/o: psfiler */ + Word16 *mem_agc, + PFSTAT *pf_stat, /* i/o: All memories related to NB post filter */ + const Word16 *tmp_buffer /* tmp_buffer in Q-1 */ + ,Word16 *mem_tmp2 /* Temporary memory used with scale_syn */ +) +{ + Word16 exc16[DCT_L_POST]; + + /*------------------------------------------------------------------------* + * Go back to time domain + *------------------------------------------------------------------------*/ + + edct_16fx( dct_buffer_in, exc16, DCT_L_POST, 6); + + Copy( exc16 + OFFSET2, exc2, L_FRAME); + + Copy( mem_tmp, st_mem_syn2, M ); + + /*------------------------------------------------------------------------* + * Perform the synthesis filtering using the enhanced excitation + *------------------------------------------------------------------------*/ + IF(IsIO == 0) /* Rescaling already done in IO mode */ + { + Rescale_mem(*Q_exc, prev_Q_syn, Q_syn, st_mem_syn2,mem_syn_clas_estim_fx, 4, + mem_deemph, st_pst_old_syn_fx, st_pst_mem_deemp_err_fx, mem_agc, + pf_stat, 1, 0, tmp_buffer); + Copy( st_mem_syn2, mem_tmp2, M ); + } + + syn_12k8_fx( L_FRAME, Aq, exc2, syn, st_mem_syn2, 1 , *Q_exc, *Q_syn); + + return; +} + + diff --git a/lib_dec/TonalComponentDetection.c b/lib_dec/TonalComponentDetection.c new file mode 100644 index 0000000..ebdd9f8 --- /dev/null +++ b/lib_dec/TonalComponentDetection.c @@ -0,0 +1,1013 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#define _USE_MATH_DEFINES + +#include +#include "stl.h" + +#include "options.h" +#include "prot_fx.h" +#include "cnst_fx.h" +#include "rom_basop_util.h" +#include "basop_util.h" + + +/***********************************************************************************/ +/* forward declaration for local functions, see implementation at end of this file */ +/***********************************************************************************/ +static void calcPseudoSpec(Word32 * mdctSpec, Word16 mdctSpec_exp, Word16 nSamples, Word16 floorPowerSpectrum, Word32 * powerSpec, Word16 * powerSpec_exp); +static void getEnvelope(Word16 nSamples, Word32 const * powerSpec, Word16 F0, Word32 * envelope, Word32 * smoothedSpectrum); +static void GetF0(Word16 const nSamples, + Word16 const nSamplesCore, + Word32 const * const powerSpectrum, Word32 const pitchLag, Word16 * const pOrigF0, Word16 * const pF0); +static void findStrongestHarmonics(Word16 nSamples, Word32 const * powerSpectrum, Word16 F0, Word16 nTotalHarmonics, Word16 * pHarmonicIndexes, Word16 * pnHarmonics); +static void CorrectF0(Word16 const * pHarmonicIndexes, Word16 const nHarmonics, Word16 * pF0); +static void findCandidates(Word16 nSamples, + Word32 * MDCTSpectrum, /* i: MDCT spectrum */ + Word16 MDCTSpectrum_exp, Word16 * thresholdModificationNew + ,Word16 floorPowerSpectrum /* i: lower limit for power spectrum bins */ + ); +static void modifyThreshold(Word16 i, Word16 F0, Word16 threshold, Word16 * thresholdModification); +static void modifyThresholds(Word16 F0, Word16 origF0, Word16 * thresholdModification); +static void RefineThresholdsUsingPitch(Word16 nSamples, + Word16 nSamplesCore, + Word32 const powerSpectrum[], + Word32 lastPitchLag, + Word32 currentPitchLag, + Word16 * pF0, + Word16 * thresholdModification); + +static void findTonalComponents(Word16 * indexOfTonalPeak, Word16 * lowerIndex, Word16 * upperIndex, Word16 *numIndexes, Word16 nSamples, const Word32 * powerSpectrum, Word16 F0, Word16 * thresholdModification); + +/*******************************************************/ +/*-------------- public functions -------------------- */ +/*******************************************************/ + +/* Detect tonal components in the lastMDCTSpectrum, use + * secondLastPowerSpectrum for the precise location of the peaks and + * store them in indexOfTonalPeak. Updates lowerIndex, upperIndex, + * pNumIndexes accordingly. */ +void DetectTonalComponents(Word16 indexOfTonalPeak[], + Word16 lowerIndex[], + Word16 upperIndex[], + Word16 * pNumIndexes, + Word32 lastPitchLag, Word32 currentPitchLag, + Word16 const lastMDCTSpectrum[], + Word16 lastMDCTSpectrum_exp, + Word16 const scaleFactors[], + Word16 const scaleFactors_exp[], + Word16 const scaleFactors_max_e, + Word32 const secondLastPowerSpectrum[], + Word16 nSamples + ,Word16 nSamplesCore + ,Word16 floorPowerSpectrum /* i: lower limit for power spectrum bins */ + ) +{ + Word16 F0; + Word16 thresholdModification[L_FRAME_MAX]; + Word32 pScaledMdctSpectrum[L_FRAME_MAX]; + + mdct_shaping_16(lastMDCTSpectrum, nSamplesCore, nSamples, + scaleFactors, scaleFactors_exp, + scaleFactors_max_e, pScaledMdctSpectrum); + lastMDCTSpectrum_exp = add(lastMDCTSpectrum_exp, scaleFactors_max_e); + + /* Find peak candidates in the last frame. */ + findCandidates(nSamples, pScaledMdctSpectrum, lastMDCTSpectrum_exp, thresholdModification + , floorPowerSpectrum + ); + + /* Refine peak candidates using the pitch information */ + RefineThresholdsUsingPitch(nSamples, nSamplesCore, secondLastPowerSpectrum, lastPitchLag, currentPitchLag, &F0, thresholdModification); + + /* Find peaks in the second last frame */ + findTonalComponents(indexOfTonalPeak, lowerIndex, upperIndex, pNumIndexes, nSamples, secondLastPowerSpectrum, F0, thresholdModification); +} + +/* When called, the tonal components are already stored in + * indexOfTonalPeak. Detect tonal components in the lastMDCTSpectrum, + * use secondLastPowerSpectrum for the precise location of the peaks and + * then keep in indexOfTonalPeak only the tonal components that are + * again detected Updates indexOfTonalPeak, lowerIndex, upperIndex, + * phaseDiff, phases, pNumIndexes accordingly. */ +void RefineTonalComponents(Word16 indexOfTonalPeak[], + Word16 lowerIndex[], + Word16 upperIndex[], + Word16 phaseDiff[], + Word16 phases[], Word16 * pNumIndexes, + Word32 lastPitchLag, Word32 currentPitchLag, + Word16 const lastMDCTSpectrum[], + Word16 const lastMDCTSpectrum_exp, + Word16 const scaleFactors[], + Word16 const scaleFactors_exp[], + Word16 const scaleFactors_max_e, + Word32 const secondLastPowerSpectrum[], + Word16 nSamples + ,Word16 nSamplesCore + ,Word16 floorPowerSpectrum /* i: lower limit for power spectrum bins */ + ) +{ + Word16 newIndexOfTonalPeak[MAX_NUMBER_OF_IDX]; + Word16 newLowerIndex[MAX_NUMBER_OF_IDX]; + Word16 newUpperIndex[MAX_NUMBER_OF_IDX]; + Word16 newNumIndexes, nPreservedPeaks; + Word16 iNew, iOld, j; + Word16 * pOldPhase, * pNewPhase; + + + DetectTonalComponents(newIndexOfTonalPeak, + newLowerIndex, + newUpperIndex, + &newNumIndexes, + lastPitchLag, + currentPitchLag, + lastMDCTSpectrum, + lastMDCTSpectrum_exp, + scaleFactors, + scaleFactors_exp, + scaleFactors_max_e, + secondLastPowerSpectrum, + nSamples, + nSamplesCore, + floorPowerSpectrum); + + nPreservedPeaks = 0; + move16(); + iNew = 0; + move16(); + pOldPhase = phases; + pNewPhase = phases; + + FOR (iOld = 0; iOld < *pNumIndexes; iOld++) + { + /* We don't want that the old peak index is at the border of the new peak region, that is why >= newUpperIndex and > newLowerIndex */ + test(); + WHILE (LT_16(iNew,newNumIndexes)&&GE_16(indexOfTonalPeak[iOld],newUpperIndex[iNew])) + { + iNew = add(iNew,1); + } + + test(); + IF (LT_16(iNew,newNumIndexes)&>_16(indexOfTonalPeak[iOld],newLowerIndex[iNew])) + { + newIndexOfTonalPeak[nPreservedPeaks] = indexOfTonalPeak[iOld]; + move16(); + newLowerIndex[nPreservedPeaks] = lowerIndex[iOld]; + move16(); + newUpperIndex[nPreservedPeaks] = upperIndex[iOld]; + move16(); + phaseDiff[nPreservedPeaks] = phaseDiff[iOld]; + move16(); + + FOR (j = lowerIndex[iOld]; j <= upperIndex[iOld]; j++) + { + *pNewPhase++ = *pOldPhase++; + move16(); + } + nPreservedPeaks = add(nPreservedPeaks,1); + } + ELSE + { + pOldPhase += sub(upperIndex[iOld],add(lowerIndex[iOld],1)); + } + } + + FOR (iNew = 0; iNew < nPreservedPeaks; iNew++) + { + indexOfTonalPeak[iNew] = newIndexOfTonalPeak[iNew]; + move16(); + lowerIndex[iNew] = newLowerIndex[iNew]; + move16(); + upperIndex[iNew] = newUpperIndex[iNew]; + move16(); + } + *pNumIndexes = nPreservedPeaks; + move16(); + +} + +/***************************************************** +---------------- private functions ------------------- +******************************************************/ +static void calcPseudoSpec(Word32 * mdctSpec, /* i: MDCT spectrum */ + Word16 mdctSpec_exp, /* i: exponent of MDCT spectrum */ + Word16 nSamples, /* i: frame size */ + Word16 floorPowerSpectrum, /* i: lower limit for power spectrum bins */ + Word32 * powerSpec, /* o: estimated power spectrum */ + Word16 * powerSpec_exp) /* o: exponent of estimated power spectrum */ +{ + Word16 k; + Word32 x, L_tmp, L_tmp_floor; + Word16 tmp_loop; + + + + *powerSpec_exp = add(add(mdctSpec_exp, mdctSpec_exp), 5); + move16(); + + k = sub(31, *powerSpec_exp); + /* If the signal is bellow floor, special care is needed for *powerSpec_exp */ + IF (LT_16(add(16-3, norm_s(floorPowerSpectrum)), k)) /*extra 3 bits of headroom for MA filter in getEnvelope*/ + { + k = add(16-3, norm_s(floorPowerSpectrum)); /*extra 3 bits of headroom for MA filter in getEnvelope*/ + L_tmp_floor = L_shl(L_deposit_l(floorPowerSpectrum), k); + set32_fx(powerSpec, L_tmp_floor, nSamples); + *powerSpec_exp = sub(31, k); + } + ELSE + { + L_tmp_floor = L_shl(L_deposit_l(floorPowerSpectrum), k); + + tmp_loop = sub(nSamples, 2); + FOR (k = 1; k <= tmp_loop; k++) + { + x = L_sub(L_shr(mdctSpec[k+1], 1),L_shr(mdctSpec[k-1], 1)); /* An MDST estimate */ + + x = L_shr(Mpy_32_32(x, x), 3); + + L_tmp = Mpy_32_32(mdctSpec[k], mdctSpec[k]); + L_tmp = L_shr(L_tmp, 5); + + powerSpec[k] = L_max(L_tmp_floor, L_add(L_tmp, x)); + move32(); + } + } + + powerSpec[0] = L_shr(powerSpec[1], 1); + move32(); + powerSpec[nSamples-1] = L_shr(powerSpec[nSamples-2], 1); + move32(); + +} + +#define LEVEL_EXP 3/*+4*/ +static void getEnvelope(Word16 nSamples, /*i: Q0 */ + Word32 const * powerSpec, /*i: powerSpec_exp */ + Word16 F0, /*i: 5Q10*/ + Word32 * envelope, /*o: powerSpec_exp + LEVEL_EXP*/ + Word32 * smoothedSpectrum /*o: powerSpec_exp + LEVEL_EXP*/ + ) +{ + Word16 nFilterLength, nHalfFilterLength, nSecondHalfFilterLength, n1, n2; + Word16 level, inv_len; + Word16 i; + Word32 sum, tmp; + + IF (F0 == 0) + { + nFilterLength = 15; + move16(); + } + ELSE IF (F0 <= 10240/*10.0f Q10*/) + { + nFilterLength = 11; + move16(); + } + ELSE IF (F0 >= 22528/*22.0f Q10*/) + { + /* For F0 >= 22 peak is isolated well enough with the filter length of 23. + This case is however not triggered due to the limit of pit_min, + but the line is left for security reasons. */ + nFilterLength = 23; + move16(); + } + ELSE + { + nFilterLength = s_or(1, shr(F0,10)); /*1+2*(int)(F0/2); F0->Q10*/ move16(); + } + + nHalfFilterLength = shr(nFilterLength,1); + + n1 = add(nHalfFilterLength,1); + + nSecondHalfFilterLength = sub(nFilterLength,nHalfFilterLength); + + n2 = sub(nSecondHalfFilterLength,1); + + assert((nFilterLength >= 7) && (nFilterLength <= 23) && (nFilterLength %2 == 1)); + + + sum = L_deposit_l(0); + level = 31089/*LEVEL_ABOVE_ENVELOPE Q12*/; /*Q12*/ + + FOR (i = 0; i < n2; i++) + { + sum = L_add(sum, powerSpec[i]); + } + /* No need for PTR_INIT for powerSpec[i+n2] as we continue from the previous loop */ + FOR (i = 0; i < n1; i++) + { + sum = L_add(sum, powerSpec[i+n2]); + tmp = Mpy_32_16_1(sum/*Q31,powerSpec_exp*/,level/*Q12*/); /*Q28,powerSpec_exp*/ + envelope[i]/*Q28,powerSpec_exp*/ = Mpy_32_16_1(tmp/*Q28,powerSpec_exp*/, InvIntTable[i+nSecondHalfFilterLength]/*Q15*/); + move32(); + } + + inv_len = mult_r(level, InvIntTable[nFilterLength]); + FOR (i = n1; i < nSamples-n2; i++) + { + sum = L_add(sum, L_sub(powerSpec[i+n2],powerSpec[i-n1])); + envelope[i] = Mpy_32_16_1(sum, inv_len); + move32(); + } + + FOR (i = nSamples-n2; i < nSamples; i++) + { + sum = L_sub(sum, powerSpec[i-n1]); + tmp = Mpy_32_16_1(sum,level); + envelope[i] = Mpy_32_16_1(tmp, InvIntTable[nSamples-(i-nHalfFilterLength)]); + move32(); + } + + FOR (i = 1; i < nSamples-1; i++) + { + smoothedSpectrum[i] = L_add(L_add(Mpy_32_16_1(powerSpec[i-1],3072/*0.75f Q12*/),L_shr(powerSpec[i],LEVEL_EXP)), Mpy_32_16_1(powerSpec[i+1],3072/*0.75f Q12*/)); + } + + move32(); + move32(); + smoothedSpectrum[0] = L_add(Mpy_32_16_1(powerSpec[1],3072/*0.75f Q12*/),L_shr(powerSpec[0],LEVEL_EXP)); + smoothedSpectrum[nSamples-1] = L_add(Mpy_32_16_1(powerSpec[nSamples-2],3072/*0.75f Q12*/),L_shr(powerSpec[nSamples-1],LEVEL_EXP)); + + +} + +static void GetF0(Word16 /*int*/ const nSamples, /*i - Q0 */ + Word16 /*int*/ const nSamplesCore, /*i - Q0 */ + Word32 /*float*/ const * const powerSpectrum, /*i - Qx */ /*is justed handed over and given back*/ + Word32 /*float*/ const pitchLag, /*i - Q16*/ + Word16 /*float*/ * const pOrigF0, /*o - Q10*/ + Word16 /*float*/ * const pF0) /*o - Q10*/ +{ + Word16 /*float*/ tmpPitchLag; + Word16 /*int*/ rgiStrongHarmonics[MAX_PEAKS_FROM_PITCH]; + Word16 /*int*/ nTotalHarmonics, nStrongHarmonics; + Word16 tmp; + + + assert(LAST_HARMONIC_POS_TO_CHECK <= nSamplesCore); + + /* Use only F0 >= 100 Hz */ + test(); + IF ((pitchLag > 0) && (LE_16(round_fx(pitchLag) , shr(nSamplesCore,1)))) + { + + tmpPitchLag /*"halfPitchLag" in FLC - read as Q5 for comparison to halfpitchlag */ + = round_fx(L_shl(pitchLag,4)); /*no division by 2, will be done in following division - + furthermore, do a leftshift before rounding, to preserve more accuracy - + will be accommodated also in following division*/ + + /**pF0 = nSamplesCore/tmpPitchLag;*/ + BASOP_Util_Divide_MantExp(nSamplesCore,0,tmpPitchLag,-(1/*division by 2*/+4/*accommodate accuracy-prevention-leftshift*/),pF0,&tmp); /*pF0 is Q15*/ + move16(); + *pF0 = shr(*pF0,sub(5,tmp)); /*Q10 without scalingfactor*/ + move16(); + *pOrigF0 = *pF0; /*Q10*/ + move16(); + tmp = 2*LAST_HARMONIC_POS_TO_CHECK; + if (LT_16(nSamples , 2*LAST_HARMONIC_POS_TO_CHECK)) + { + move16(); + tmp = nSamples; + } + BASOP_Util_Divide_MantExp(tmp,15,*pF0,5,&nTotalHarmonics,&tmp); + nTotalHarmonics =shl(nTotalHarmonics,sub(tmp,15)); + + + /* Get in rgiStrongHarmonics all i for which i*F0 are the strongest harmonics */ + findStrongestHarmonics(nSamples, powerSpectrum, *pF0, nTotalHarmonics, rgiStrongHarmonics, &nStrongHarmonics); + + CorrectF0(rgiStrongHarmonics, nStrongHarmonics, pF0); + } + ELSE + { + move16(); + move16(); + *pF0 = 0; + *pOrigF0 = 0; + } + +} + + +static void findStrongestHarmonics(Word16 nSamples, + Word32 const * powerSpectrum, + Word16 F0/*5Q10*/, + Word16 nTotalHarmonics, + Word16 * pHarmonicIndexes, + Word16 * pnHarmonics) +{ + Word32 peaks[MAX_PEAKS_FROM_PITCH], smallestPeak; + Word16 nPeaksToCheck, nPeaks, iSmallestPeak; + Word16 i, l, k; + (void)nSamples; + + + nPeaks = 0; + move16(); + + iSmallestPeak = 0; + move16(); + smallestPeak = 0x7fffffff; + move32(); + + nPeaksToCheck = s_min(nTotalHarmonics, MAX_PEAKS_FROM_PITCH+1); + + FOR (i = 1; i < nPeaksToCheck; i++) + { + Word32 newPeak; + + k = extract_h(L_shl(L_mult(i,F0),5)); /*k = (int)(i*F0);*/ + assert(k > 0 && k < 2*LAST_HARMONIC_POS_TO_CHECK && k < nSamples); + + newPeak = L_add(powerSpectrum[k], 0); + + peaks[nPeaks] = newPeak; + move32(); + pHarmonicIndexes[nPeaks] = i; + move16(); + + IF (LE_32(newPeak,smallestPeak)) + { + iSmallestPeak = nPeaks; + move16(); + smallestPeak = L_add(newPeak, 0); + } + + nPeaks = add(nPeaks,1); + } + + FOR (; i < nTotalHarmonics; i++) + { + Word32 newPeak; + + k = extract_h(L_shl(L_mult(i,F0),5)); + assert(k > 0 && k < 2*LAST_HARMONIC_POS_TO_CHECK && k < nSamples); + + newPeak = L_add(powerSpectrum[k], 0); + + IF (GT_32(newPeak,smallestPeak)) + { + peaks[iSmallestPeak] = newPeak; + move32(); + pHarmonicIndexes[iSmallestPeak] = i; + move16(); + smallestPeak = L_add(newPeak, 0); + + FOR (l = 0; l < MAX_PEAKS_FROM_PITCH; l++) + { + IF (peaks[l] <= smallestPeak) + { + iSmallestPeak = l; + move16(); + smallestPeak = L_add(peaks[l], 0); + } + } + } + } + + sort_fx(pHarmonicIndexes, 0, sub(nPeaks,1)); + + *pnHarmonics = nPeaks; + move16(); + +} + +/* Use new F0, for which harmonics are most common in pHarmonicIndexes */ +static void CorrectF0(Word16 /*int*/ const * pHarmonicIndexes, /*I - Q0 */ + Word16 /*int*/ const nHarmonics, /*I - Q0 */ + Word16 /*float*/ * pF0) /*I/O - Q10 range: {0}, [4..18) */ +{ + Word16 /*int*/ i; + Word16 /*float*/ F0; + Word16 /*int*/ diff[MAX_PEAKS_FROM_PITCH-1], sortedDiff[MAX_PEAKS_FROM_PITCH-1]; + Word16 /*int*/ iMostCommonDiff, nMostCommonDiff, nSameDiff, iMult; + + Word16 tmp; + + + F0 = *pF0; + + test(); + IF (F0 > 0 && nHarmonics != 0) + { + tmp = sub(nHarmonics, 1); + FOR (i = 0; i < tmp; i++) + { + diff[i] = sub(pHarmonicIndexes[i+1], pHarmonicIndexes[i]); + move16(); + sortedDiff[i] = diff[i]; + move16(); + } + sort_fx(sortedDiff, 0,sub(nHarmonics, 1+1)); + iMostCommonDiff = sortedDiff[0]; + move16(); + nSameDiff = 1; + move16(); + i = 1; + move16(); + IF (EQ_16(imult1616(sortedDiff[0],pHarmonicIndexes[0]),1)) + { + /* Find how many distances between peaks have length 1 */ + FOR (; i < tmp; i++) + { + if (EQ_16(sortedDiff[i],1)) + { + nSameDiff=add(nSameDiff,1); + } + } + } + nMostCommonDiff = nSameDiff; + move16(); + + /* If there are at least 3 distances between peaks with length 1 and if the 1st harmonic is in pHarmonicIndexes then keep the original F0 */ + /* Otherwise find the most common distance between peaks */ + IF (LT_16(nSameDiff,3)) + { + /* Find the most common difference */ + FOR (i = nSameDiff; i < tmp; i++) + { + IF (EQ_16(sortedDiff[i], sortedDiff[i-1])) + { + nSameDiff=add(nSameDiff,1); + } + ELSE + { + IF (GT_16(nSameDiff, nMostCommonDiff)) + { + nMostCommonDiff = nSameDiff; + move16(); + iMostCommonDiff = sortedDiff[i-1]; + move16(); + } + ELSE { + test(); + IF (EQ_16(nSameDiff, nMostCommonDiff)&&(abs_s(sub(iMostCommonDiff,pHarmonicIndexes[0]))>abs_s(sub(sortedDiff[i-1],pHarmonicIndexes[0])))) + { + nMostCommonDiff = nSameDiff; + move16(); + iMostCommonDiff = sortedDiff[i-1]; + move16(); + } + } + nSameDiff = 1; + move16(); + } + } + IF (GT_16(nSameDiff,nMostCommonDiff)) + { + nMostCommonDiff = nSameDiff; + move16(); + iMostCommonDiff = sortedDiff[nHarmonics-2]; + move16(); + } + } + + /* If there are enough peaks at the same distance */ + IF (GE_16(nMostCommonDiff, MAX_PEAKS_FROM_PITCH/2)) + { + iMult = 1; + move16(); + FOR (i = 0; i < tmp; i++) + { + IF (EQ_16(diff[i], iMostCommonDiff)) + { + iMult = pHarmonicIndexes[i]; + move16(); + BREAK; + } + /* for rare cases of octave mismatch or missing harmonics */ + test(); + test(); + IF (GT_16(sub(nHarmonics,2),i)&&(EQ_16(diff[i],diff[i+1]))&&(EQ_16(add(diff[i],diff[i+1]),iMostCommonDiff))) + { + iMult = pHarmonicIndexes[i]; + move16(); + BREAK; + } + } + + /* If the real F0 is much higher than the original F0 from the pitch */ + + IF (LE_16(iMult, 3)) + { + /* Use iMostCommonDiff, because the lowest pHarmonicIndexes[i] (which is equal to iMult) may not correspond to the new F0, but to it's multiple */ + F0 = round_fx(L_shl(L_mult(iMostCommonDiff /*Q0*/,F0 /*Q10*/),15)); + } + ELSE + { + F0 = 0; + } + } + /* Otherwise if there are at least 3 distances between peaks with length 1 and if the 1st harmonic is in pHarmonicIndexes then keep the original F0 */ + /* Otherwise don't use F0 */ + ELSE + { + test(); + if ((GT_16(iMostCommonDiff,1))||(LT_16(nMostCommonDiff,3))) + { + /* Not enough peaks at the same distance => don't use the pitch. */ + F0 = 0; + move16(); + } + } + *pF0 = F0; + move16(); + } + +} + +static void modifyThreshold(Word16 /*int*/ i, /*I - Q0 */ + Word16 /*float*/ F0, /*I - Q10*/ + Word16 /*float*/ threshold, /*I - Q10*/ + Word16* /*float*/ thresholdModification) /*I/O - Q10*/ +{ + Word32 harmonic; + Word16 fractional /*Q15*/; + Word16 k /*Q0*/; + Word16 twoTimesFract /*Q10*/; + + + + harmonic = L_mult(shl(i,5),F0); /*Q0 * Q10 = 15Q16*/ + k = extract_h(harmonic); /*Q0*/ + fractional = lshr(extract_l(harmonic),1); /* Fractional part of the i*F0 */ /*Q15*/ + twoTimesFract = mult(2048/*2 in Q10*/,fractional/*Q15*/); /*Q10*/ /* threshold if the center of the peek is between k-1 and k, threshold+2 if the center of the peek is between k and k+1 */ + + move16(); + thresholdModification[k] = threshold; + move16(); + thresholdModification[k-1] = add(threshold/*Q10*/, twoTimesFract/*Q10*/); /*Q10*/ + move16(); + thresholdModification[k+1] = add(threshold/*Q10*/, sub(2048/*2 in Q10*/, twoTimesFract/*Q10*/)/*Q10*/); /*Q10*/ + +} + +static void modifyThresholds(Word16 /*float*/ F0, /*I - Q10*/ + Word16 /*float*/ origF0, /*I - Q10*/ + Word16* /*float*/ thresholdModification) /*I/O - Q10*/ +{ + Word16 /*int*/ i, /*int*/ nHarmonics; + Word16 tmp, tmpM, tmpE; + + + + + IF (origF0 > 0) + { + IF (F0 == 0) + { + nHarmonics /*Q0*/ = s_min(MAX_PEAKS_FROM_PITCH /*Q0*/, shl((div_s(LAST_HARMONIC_POS_TO_CHECK /*Q0*/, origF0/*Q10*/) /*Q15*2^10*/),-5 /*Q0*2^-5*/) /*Q0*/); + + FOR (i = 1; i <= nHarmonics; i++) + { + modifyThreshold(i, origF0, 717/*0.7f Q10*/ /*0.7f in Q10*/, thresholdModification); + } + } + IF (F0 > 0) + { + nHarmonics /*Q0*/ = s_min(MAX_PEAKS_FROM_PITCH /*Q0*/, shl((div_s(LAST_HARMONIC_POS_TO_CHECK /*Q0*/, F0/*Q10*/) /*Q15*2^10*/),-5 /*Q0*2^-5*/) /*Q0*/); + + /*(int)(F0/origF0+0.5f)*/ + BASOP_Util_Divide_MantExp(F0,0,origF0,0,&tmpM,&tmpE); + tmp=round_fx(L_shl(L_deposit_l(tmpM),add(tmpE,1))); + + FOR (i = tmp; i > 0; i--) + { + modifyThreshold(i, origF0, 358/*0.35f Q10*/, thresholdModification); + } + FOR (i = 1; i <= nHarmonics; i++) + { + modifyThreshold(i, F0, 358/*0.35f Q10*/, thresholdModification); + } + } + } + +} + +static void findCandidates(Word16 nSamples, /* i: frame size */ + Word32 * MDCTSpectrum, /* i: MDCT spectrum */ + Word16 MDCTSpectrum_exp, /* i: exponent of MDCT spectrum */ + Word16 * thresholdModificationNew /* o: threshold modification Q10 */ + ,Word16 floorPowerSpectrum /* i: lower limit for power spectrum bins */ + ) +{ + Word32 powerSpectrum[L_FRAME_MAX]; + Word16 powerSpectrum_exp; + Word32 envelope[L_FRAME_MAX]; + Word32 smoothedSpectrum[L_FRAME_MAX]; + Word16 upperIdx, lowerIdx; + Word16 k, j; + Word32 biggerNeighbor; + Word16 tmp_loop1, tmp_loop2, tmp_loop3; + + + + calcPseudoSpec(MDCTSpectrum, MDCTSpectrum_exp, nSamples, floorPowerSpectrum, powerSpectrum, &powerSpectrum_exp); + + getEnvelope(nSamples, powerSpectrum, 0, envelope, smoothedSpectrum); + + set16_fx(thresholdModificationNew, UNREACHABLE_THRESHOLD, nSamples); + + k = GROUP_LENGTH/2; + move16(); + tmp_loop1 = sub(nSamples, (GROUP_LENGTH-GROUP_LENGTH/2)); + tmp_loop2 = sub(nSamples,1); + WHILE ( LE_16(k, tmp_loop1)) + { + IF (GT_32(smoothedSpectrum[k],envelope[k])) + { + /* The check that bin at k is bigger than bins at k-1 and k+1 is needed to avoid deadlocks when the thresholds are low. */ + /* It removes some true peaks, especially if non weighted sum is used for the smoothed spectrum. */ + biggerNeighbor = L_max(powerSpectrum[k-1], powerSpectrum[k+1]); + + IF (GE_32(powerSpectrum[k], biggerNeighbor)) + { + /* Find the right foot */ + upperIdx = add(k, 1); + WHILE ( LT_16(upperIdx,tmp_loop2)) + { + + IF (LT_32(powerSpectrum[upperIdx],powerSpectrum[upperIdx+1])) + { + /* Side lobes may increase for certain amount */ + IF (LT_32( L_shl(Mpy_32_16_1(powerSpectrum[upperIdx], ALLOWED_SIDE_LOBE_FLUCTUATION), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP), powerSpectrum[upperIdx+1] )) + { + BREAK; + } + /* Check for further decrease after a side lobe increase */ + FOR (j = add(upperIdx,1); j < tmp_loop2; j++) + { + IF (LT_32( powerSpectrum[j], L_shl(Mpy_32_16_1(powerSpectrum[j+1], ALLOWED_SIDE_LOBE_FLUCTUATION), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP) )) + { + BREAK; + } + } + /* Side lobe increase must be 2 times smaller than the decrease to the foot */ + /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */ + IF ( GT_32( Mpy_32_32(L_shl(powerSpectrum[upperIdx+1],1),powerSpectrum[j]), Mpy_32_32(powerSpectrum[upperIdx], powerSpectrum[upperIdx]) )) + { + BREAK; + } + upperIdx = sub(j,1); + } + upperIdx = add(upperIdx, 1); + } + /* left foot */ + lowerIdx = sub(k,1); + WHILE ( lowerIdx > 0 ) + { + + IF (LT_32(powerSpectrum[lowerIdx], powerSpectrum[lowerIdx-1])) + { + /* Side lobes may increase for certain amount */ + IF (LT_32( L_shl(Mpy_32_16_1(powerSpectrum[lowerIdx], ALLOWED_SIDE_LOBE_FLUCTUATION), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP), powerSpectrum[lowerIdx-1])) + { + BREAK; + } + /* Check for further decrease after a side lobe increase */ + FOR (j = sub(lowerIdx,1); j > 0; j--) + { + IF (LT_32(powerSpectrum[j], L_shl(Mpy_32_16_1(powerSpectrum[j-1], ALLOWED_SIDE_LOBE_FLUCTUATION), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP) ) ) + { + BREAK; + } + } + /* Side lobe increase must be 2 times smaller than the decrease to the foot */ + /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */ + IF (GT_32 ( Mpy_32_32(L_shl(powerSpectrum[lowerIdx-1],1), powerSpectrum[j]), Mpy_32_32(powerSpectrum[lowerIdx], powerSpectrum[lowerIdx])) ) + { + BREAK; + } + lowerIdx = add(j,1); + } + lowerIdx = sub(lowerIdx, 1); + } + + /* Check if there is a bigger peak up to the next peak foot */ + tmp_loop3 = s_min(upperIdx, tmp_loop1); + FOR (j = s_max(GROUP_LENGTH/2, lowerIdx); j <= tmp_loop3; j++) + { + if (GT_32(powerSpectrum[j], powerSpectrum[k])) + { + k = j; + move16(); + } + } + + /* Modify thresholds for the following frame */ + tmp_loop3 = add(k,2); + FOR (j = sub(k,1); j < tmp_loop3; j++) + { + thresholdModificationNew[j] = BIG_THRESHOLD; + move16(); + + if (GT_32(smoothedSpectrum[j], envelope[j])) + { + thresholdModificationNew[j] = SMALL_THRESHOLD; + move16(); + } + + } + /* Jump to the next foot of the peak. */ + k = upperIdx; + move16(); + } + } + k = add(k, 1); + } + +} + +static void RefineThresholdsUsingPitch(Word16 nSamples, + Word16 nSamplesCore, + Word32 const powerSpectrum[], + Word32 lastPitchLag, + Word32 currentPitchLag, + Word16 * pF0, + Word16 * thresholdModification) +{ + Word16 pitchIsStable; + Word16 origF0; + Word32 L_tmp; + + /*pitchIsStable = (fabs(lastPitchLag-currentPitchLag) < 0.25f);*/ + pitchIsStable = 0; + move16(); + L_tmp = L_abs(L_sub(lastPitchLag, currentPitchLag)); + if (LT_32(L_tmp, 16384l/*0.25f Q16*/)) + { + pitchIsStable = 1; + move16(); + } + + IF (pitchIsStable) + { + GetF0(nSamples, + nSamplesCore, + powerSpectrum, lastPitchLag, &origF0, pF0); + + modifyThresholds(*pF0, origF0, thresholdModification); + } + ELSE + { + *pF0 = 0; + move16(); + } + +} + +static void findTonalComponents(Word16 * indexOfTonalPeak, /* OUT */ + Word16 * lowerIndex, /* OUT */ + Word16 * upperIndex, /* OUT */ + Word16 *numIndexes, /* OUT */ + Word16 nSamples, /* IN */ + const Word32 * powerSpectrum, /* IN */ + Word16 F0, /* IN */ + Word16 * thresholdModification) /* IN */ +{ + Word32 envelope[L_FRAME_MAX]; + Word32 smoothedSpectrum[L_FRAME_MAX]; + Word16 nrOfFIS; + Word16 upperIdx, lowerIdx, lowerBound; + Word16 k, j, m; + Word32 biggerNeighbor; + Word16 tmp_loop1, tmp_loop2, tmp_loop3; + + getEnvelope(nSamples, powerSpectrum, F0, envelope, smoothedSpectrum); + + + nrOfFIS = 0; + move16(); + lowerBound = 0; + move16(); + + k = GROUP_LENGTH/2; + move16(); + tmp_loop1 = sub(nSamples, (GROUP_LENGTH-GROUP_LENGTH/2)); + tmp_loop2 = sub(nSamples,1); + WHILE ( LE_16(k, tmp_loop1)) + { + /* There is 3 bits headroom in envelope and max of thresholdModification is 16384, so shifting left for 4 would produce overflow only when the result is anyhow close to 1 */ + IF (GT_32(L_shr(smoothedSpectrum[k], 1), L_shl(Mpy_32_16_1(envelope[k]/*Q28,powerSpec_exp*/, thresholdModification[k]/*Q10*/), 4))) + { + /* The check that bin at k is bigger than bins at k-1 and k+1 is needed to avoid deadlocks when the thresholds are low. */ + /* It removes some true peaks, especially if non weighted sum is used for the smoothed spectrum. */ + biggerNeighbor = L_max(powerSpectrum[k-1], powerSpectrum[k+1]); + + IF (GE_32(powerSpectrum[k], biggerNeighbor)) + { + /* Find the right foot */ + upperIdx = add(k, 1); + WHILE (LT_16(upperIdx, tmp_loop2)) + { + IF (LT_32(powerSpectrum[upperIdx], powerSpectrum[upperIdx+1])) + { + /* Side lobes may increase for certain amount */ + IF (LT_32( L_shl(Mpy_32_16_1(powerSpectrum[upperIdx], ALLOWED_SIDE_LOBE_FLUCTUATION), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP), powerSpectrum[upperIdx+1])) + { + BREAK; + } + /* Check for further decrease after a side lobe increase */ + FOR (j = add(upperIdx, 1); j < tmp_loop2; j++) + { + IF (LT_32( powerSpectrum[j], L_shl(Mpy_32_16_1(powerSpectrum[j+1], ALLOWED_SIDE_LOBE_FLUCTUATION), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP))) + { + BREAK; + } + } + /* Side lobe increase must be 2 times smaller than the decrease to the foot */ + /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */ + IF (GT_32( Mpy_32_32(L_shl(powerSpectrum[upperIdx+1], 1), powerSpectrum[j]), Mpy_32_32(powerSpectrum[upperIdx], powerSpectrum[upperIdx]))) + { + BREAK; + } + upperIdx = sub(j, 1); + } + upperIdx = add(upperIdx, 1); + } + /* left foot */ + lowerIdx = sub(k, 1); + WHILE (GT_16(lowerIdx, lowerBound)) + { + IF (LT_32(powerSpectrum[lowerIdx], powerSpectrum[lowerIdx-1])) + { + /* Side lobes may increase for certain amount */ + IF ( LT_32(L_shl(Mpy_32_16_1(powerSpectrum[lowerIdx], ALLOWED_SIDE_LOBE_FLUCTUATION), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP), powerSpectrum[lowerIdx-1])) + { + BREAK; + } + /* Check for further decrease after a side lobe increase */ + FOR (j = sub(lowerIdx, 1); j > 0; j--) + { + IF (LT_32(powerSpectrum[j], L_shl(Mpy_32_16_1(powerSpectrum[j-1], ALLOWED_SIDE_LOBE_FLUCTUATION), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP))) + { + BREAK; + } + } + /* Side lobe increase must be 2 times smaller than the decrease to the foot */ + /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */ + IF ( GT_32( Mpy_32_32(L_shl(powerSpectrum[lowerIdx-1], 1), powerSpectrum[j]), Mpy_32_32(powerSpectrum[lowerIdx], powerSpectrum[lowerIdx]))) + { + BREAK; + } + lowerIdx = add(j, 1); + } + lowerIdx = sub(lowerIdx, 1); + } + + lowerBound = upperIdx; + move16(); + + /* Check if there is a bigger peak up to the next peak foot */ + tmp_loop3 = s_min(upperIdx, tmp_loop1); + FOR (j = s_max(GROUP_LENGTH/2, lowerIdx); j <= tmp_loop3; j++) + { + if (GT_32(powerSpectrum[j],powerSpectrum[k])) + { + + k = j; + move16(); + } + } + + assert((nrOfFIS == 0) || (indexOfTonalPeak[nrOfFIS-1] < k)); + + lowerIndex[nrOfFIS] = sub(k, GROUP_LENGTH/2); + move16(); + + upperIndex[nrOfFIS] = add(k,(GROUP_LENGTH-GROUP_LENGTH/2-1)); + move16(); + + test(); + IF ((nrOfFIS > 0) && (LE_16(lowerIndex[nrOfFIS], upperIndex[nrOfFIS-1]))) + { + m = shr(add(k, indexOfTonalPeak[nrOfFIS-1]), 1); + upperIndex[nrOfFIS-1] = m; + move16(); + lowerIndex[nrOfFIS] = add(m, 1); + move16(); + } + + indexOfTonalPeak[nrOfFIS++] = k; + move16(); + + IF (EQ_16(nrOfFIS, MAX_NUMBER_OF_IDX)) + { + BREAK; + } + /* Jump to the next foot of the peak. */ + k = upperIdx; + move16(); + } + } + k = add(k, 1); + } + + *numIndexes = nrOfFIS; + move16(); + +} + diff --git a/lib_dec/acelp_core_dec_fx.c b/lib_dec/acelp_core_dec_fx.c new file mode 100644 index 0000000..3087b3d --- /dev/null +++ b/lib_dec/acelp_core_dec_fx.c @@ -0,0 +1,1247 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "basop_mpy.h" + +/*==========================================================================*/ +/* FUNCTION : void acelp_core_dec_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : ACELP core decoder */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ Word16 coder_type_fx i : coder type */ + +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ Word16 *voice_factors o : voicing factors Q15 */ +/* _ Word16 old_syn_12k8_16k[] o : intermediate ACELP Q_syn2-1 */ +/* synthesis at 12.8kHz or 16kHz to be used by SWB BWE */ +/* _ Word16 synth_out[] o : synthesis Q_syn2-1 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ Decoder_State_fx *st_fx: */ +/* _ Word16 bwe_exc_extended[] i/o: bandwidth extended excitation Q0*/ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* CALLED FROM : RX */ +/*==========================================================================*/ + +void acelp_core_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 synth_out[], /* o : synthesis */ + Word32 bwe_exc_extended[], /* i/o: bandwidth extended excitation */ + Word16 *voice_factors, /* o : voicing factors */ + Word16 old_syn_12k8_16k[], /* o : intermediate ACELP synthesis for SWB BWE */ + Word16 coder_type_fx, /* i : coder type */ + Word16 sharpFlag, + Word16 pitch_buf_fx[NB_SUBFR16k], /* o : floating pitch for each subframe */ + Word16 *unbits, /* o : number of unused bits */ + Word16 *sid_bw /* o : 0-NB/WB, 1-SWB SID */ +) +{ + Word16 old_exc_fx[L_EXC_DEC] = {0}, *exc_fx; /* excitation signal buffer (Q0) */ + Word16 syn_fx_tmp[L_FRAME_16k+L_SUBFR], *syn_fx; /* synthesis signal buffer */ + Word16 temp_buf[L_FRAME16k + L_SYN_MEM]; + Word16 output_frame; /* frame length at output sampling freq. */ + Word16 mem_tmp_fx[M]; /* temporary synthesis filter memory */ + Word32 enr_q_fx; /* E information for FER protection */ + Word16 tmp_noise_fx; /* Long term temporary noise energy */ + Word16 i, int_fs; + Word16 tc_subfr_fx; + Word16 allow_cn_step_fx; + Word16 temp_buf_fx[L_FRAME16k + L_SYN_MEM]; + + Word16 Aq_fx[NB_SUBFR16k*(M+1)]= {0}; /*Q12*/ + Word16 Es_pred_fx; /*Q8*/ + Word16 old_bwe_exc_fx[((PIT16k_MAX + (L_FRAME16k+1) + L_SUBFR16k) * 2)] = {0}; /* excitation buffer */ + Word16 old_exc2_fx[L_FRAME16k + L_EXC_MEM], *exc2_fx; /* total excitation buffer */ + Word16 *bwe_exc_fx; + Word16 lsf_new_fx[M]; /* LSFs at the end of the frame */ + Word16 lsp_new_fx[M]; /* LSPs at the end of the frame */ + Word16 lsp_mid_fx[M]; /* LSPs in the middle of the frame */ + Word16 FEC_pitch_fx; /*Q6*/ + Word16 last_pulse_pos; + Word16 T0_tmp; + Word16 do_WI_fx; + Word16 dct_buffer_fx[DCT_L_POST]; + Word16 exc_buffer_fx[DCT_L_POST]; + Word16 dct_exc_tmp[L_FRAME16k]; + Word16 qdct; + Word16 delta_mem_scale; + Word16 bpf_error_signal[L_FRAME16k]; + CLDFB_SCALE_FACTOR scaleFactor; + Word32 workBuffer[128*3]; + Word32 q_env[20]; + Word16 exc3_fx[L_FRAME16k]; + Word16 syn1_fx_tmp[L_FRAME16k+2], *syn1_fx; + Word32 *realBuffer[CLDFB_NO_COL_MAX], *imagBuffer[CLDFB_NO_COL_MAX]; + Word16 gain_buf[NB_SUBFR16k]; /*Q14*/ + Word16 syn_fx_tmp2[L_FRAME_16k]; + Word16 pitch_buf_tmp[NB_SUBFR16k]; + Word16 k; + Word16 update_flg; + Word32 realBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 imagBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word16 LSF_Q_prediction; /* o : LSF prediction mode */ + Word16 avoid_lpc_burst_on_recovery; + + FOR( i=0; ioutput_Fs_fx / 50); move16();*/ + output_frame = st_fx->output_frame_fx; + move16(); + st_fx->bpf_off_fx = 0; + move16(); + if( EQ_16(st_fx->last_core_fx,HQ_CORE)) + { + /* in case of HQ->ACELP switching, do not apply BPF */ + st_fx->bpf_off_fx = 1; + move16(); + /* in case of core switching, reset post-filter memories */ + st_fx->pfstat.on = 0; + move16(); + /* reset the GSC pre echo energy threshold in case of switching */ + st_fx->Last_frame_ener_fx = MAX_32; + move32(); + } + if(st_fx->prev_bfi_fx > 0) + { + /* reset the GSC pre echo energy threshold in case of FEC */ + st_fx->Last_frame_ener_fx = MAX_32; + move32(); + } + st_fx->clas_dec = st_fx->last_good_fx; + move16(); + enr_q_fx = 0; + move16(); + Es_pred_fx = 0; + move16(); + tmp_noise_fx = 0; + + Copy( st_fx->old_exc_fx, old_exc_fx, L_EXC_MEM_DEC ); + exc_fx = old_exc_fx + L_EXC_MEM_DEC; + move16(); + Copy( st_fx->old_exc2_fx, old_exc2_fx, L_EXC_MEM ); + exc2_fx = old_exc2_fx + L_EXC_MEM; + Copy( st_fx->old_bwe_exc_fx, old_bwe_exc_fx, PIT16k_MAX * 2); + bwe_exc_fx = old_bwe_exc_fx + PIT16k_MAX * 2; + move16(); + last_pulse_pos = 0; + move16(); + do_WI_fx = 0; + move16(); + st_fx->GSC_noisy_speech_fx = 0; + move16(); + st_fx->relax_prev_lsf_interp_fx = 0; + move16(); + + set16_fx( gain_buf, 0, NB_SUBFR16k ); + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + st_fx->gamma = GAMMA1; + move16(); + st_fx->preemph_fac = PREEMPH_FAC; + move16(); + int_fs = INT_FS_FX; + move16(); + } + ELSE + { + st_fx->gamma = GAMMA16k; + move16(); + st_fx->preemph_fac = PREEMPH_FAC_16k; + move16(); + int_fs = INT_FS_16k; + move16(); + } + + /* reset post-filter in case post-filtering was off in previous frame */ + if( st_fx->pfstat.on == 0 ) + { + st_fx->pfstat.reset = 1; + move16(); + } + + avoid_lpc_burst_on_recovery = 0; + move16(); + test(); + test(); + if( st_fx->last_con_tcx && NE_16(st_fx->L_frameTCX_past, st_fx->L_frame_fx)&&st_fx->last_core_fx!=0) + { + avoid_lpc_burst_on_recovery = 1; + move16(); + } + + /*----------------------------------------------------------------* + * Updates in case of internal sampling rate switching + *----------------------------------------------------------------*/ + test(); + IF( NE_16(st_fx->last_L_frame_fx,st_fx->L_frame_fx)&&NE_16(st_fx->last_core_fx,HQ_CORE)) + { + if( st_fx->pfstat.on != 0 ) + { + Word16 mem_syn_r_size_old, mem_syn_r_size_new; + + mem_syn_r_size_old = shr(st_fx->last_L_frame_fx, 4); + mem_syn_r_size_new = shr(st_fx->L_frame_fx, 4); + lerp( st_fx->pfstat.mem_stp+L_SYN_MEM-mem_syn_r_size_old, st_fx->pfstat.mem_stp+L_SYN_MEM-mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old ); + lerp( st_fx->pfstat.mem_pf_in+L_SYN_MEM-mem_syn_r_size_old, st_fx->pfstat.mem_pf_in+L_SYN_MEM-mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old ); + } + + /* convert quantized LSP vector */ + st_fx->rate_switching_reset=lsp_convert_poly_fx( st_fx->lsp_old_fx, st_fx->L_frame_fx, 0); + /* convert old quantized LSF vector */ + lsp2lsf_fx( st_fx->lsp_old_fx, st_fx->lsf_old_fx, M, int_fs ); + + /* FEC - update adaptive LSF mean vector */ + Copy( st_fx->lsf_old_fx, st_fx->lsfoldbfi1_fx, M ); + Copy( st_fx->lsf_old_fx, st_fx->lsfoldbfi0_fx, M ); + Copy( st_fx->lsf_old_fx, st_fx->lsf_adaptive_mean_fx, M ); + + /* Reset LPC mem */ + IF( EQ_32(st_fx->sr_core,16000)) + { + Copy( GEWB2_Ave_fx, st_fx->mem_AR_fx, M ); + } + ELSE + { + Copy( GEWB_Ave_fx, st_fx->mem_AR_fx, M ); + } + set16_fx( st_fx->mem_MA_fx,0, M ); + + /* update synthesis filter memories */ + synth_mem_updt2( st_fx->L_frame_fx, st_fx->last_L_frame_fx, st_fx->old_exc_fx, st_fx->mem_syn_r, st_fx->mem_syn2_fx, NULL, DEC ); + Copy( st_fx->old_exc_fx, old_exc_fx, L_EXC_MEM_DEC ); + Copy_Scale_sig(st_fx->mem_syn2_fx, st_fx->mem_syn1_fx, M, sub(-1,st_fx->Q_syn)); /*Q-1*/ + + Copy( st_fx->mem_syn2_fx, st_fx->mem_syn3_fx, M ); + + } + + IF( NE_16(st_fx->last_L_frame_fx,st_fx->L_frame_fx)) + { + /* update buffer of old subframe pitch values */ + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + move16(); + IF( EQ_16(st_fx->last_L_frame_fx,L_FRAME32k)) + { + /* (float)12800/(float)32000; */ + k = 13107; + } + ELSE IF( EQ_16(st_fx->last_L_frame_fx,512)) + { + /* (float)12800/(float)25600; */ + k = 16384; + } + ELSE /* st->last_L_frame == L_FRAME16k */ + { + /* (float)12800/(float)16000; */ + k = 26214; + } + + FOR( i=NB_SUBFR16k-NB_SUBFR; iold_pitch_buf_fx[i-1] = Mpy_32_16_1(st_fx->old_pitch_buf_fx[i], k); + move32(); + } + + FOR( i=2*NB_SUBFR16k-NB_SUBFR; i<2*NB_SUBFR16k; i++ ) + { + st_fx->old_pitch_buf_fx[i-2] = Mpy_32_16_1(st_fx->old_pitch_buf_fx[i], k); + move32(); + } + } + ELSE + { + move16(); + IF( EQ_16(st_fx->last_L_frame_fx,L_FRAME32k)) + { + /* (float)16000/(float)32000; */ + k = -16384; + } + ELSE IF( EQ_16(st_fx->last_L_frame_fx,512)) + { + /* tmpF = (float)16000/(float)25600; */ + k = -12288; + } + ELSE /* st->last_L_frame == L_FRAME12k8 */ + { + /* tmpF = (float)16000/(float)12800; */ + k = 8192; + } + + FOR( i=2*NB_SUBFR-1; i>=NB_SUBFR; i-- ) + { + st_fx->old_pitch_buf_fx[i+2] = L_add(st_fx->old_pitch_buf_fx[i], Mpy_32_16_1(st_fx->old_pitch_buf_fx[i], k)); + move32(); + } + st_fx->old_pitch_buf_fx[NB_SUBFR+1] = st_fx->old_pitch_buf_fx[NB_SUBFR+2]; + move32(); + + FOR( i=NB_SUBFR-1; i>=0; i-- ) + { + st_fx->old_pitch_buf_fx[i+1] = L_add(st_fx->old_pitch_buf_fx[i], Mpy_32_16_1(st_fx->old_pitch_buf_fx[i], k)); + move32(); + } + st_fx->old_pitch_buf_fx[0] = st_fx->old_pitch_buf_fx[1]; + move32(); + } + } + + IF( NE_16(st_fx->bfi_pitch_frame_fx, st_fx->L_frame_fx)) + { + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + move16(); + IF( EQ_16(st_fx->bfi_pitch_frame_fx,L_FRAME32k)) + { + /* (float)12800/(float)32000; */ + k = 13107; + } + ELSE IF( EQ_16(st_fx->bfi_pitch_frame_fx,512)) + { + /* (float)12800/(float)25600; */ + k = 16384; + } + ELSE /* st->bfi_pitch_frame_fx == L_FRAME16k */ + { + /* (float)12800/(float)16000; */ + k = 26214; + } + st_fx->bfi_pitch_fx = mult_r(k, st_fx->bfi_pitch_fx); + st_fx->bfi_pitch_frame_fx = L_FRAME; + move16(); + } + ELSE + { + move16(); + IF( EQ_16(st_fx->bfi_pitch_frame_fx,L_FRAME32k)) + { + /* (float)16000/(float)32000; */ + k = -16384; + } + ELSE IF( EQ_16(st_fx->bfi_pitch_frame_fx,512)) + { + /* tmpF = (float)16000/(float)25600; */ + k = -12288; + } + ELSE /* st->bfi_pitch_frame_fx == L_FRAME12k8 */ + { + /* tmpF = (float)16000/(float)12800; */ + k = 8192; + } + st_fx->bfi_pitch_fx = add(st_fx->bfi_pitch_fx, mult_r(st_fx->bfi_pitch_fx,k)); + st_fx->bfi_pitch_frame_fx = L_FRAME16k; + move16(); + } + } + + test(); + test(); + if( EQ_16(st_fx->last_bwidth_fx,NB)&&NE_16(st_fx->bwidth_fx,NB)&&st_fx->ini_frame_fx!=0) + { + st_fx->rate_switching_reset=1; + move16(); + } + + /*----------------------------------------------------------------------* + * GOOD frame + *----------------------------------------------------------------------*/ + + IF( !st_fx->bfi_fx ) + { + + /*----------------------------------------------------------------* + * Decoding of TC subframe clasification + *----------------------------------------------------------------*/ + + tc_subfr_fx = -1; + move16(); + if( EQ_16(coder_type_fx,TRANSITION)) + { + tc_subfr_fx = tc_classif_fx( st_fx, st_fx->L_frame_fx ); + move16(); + } + + /*----------------------------------------------------------------* + * Decoding of inactive CNG frames + *----------------------------------------------------------------*/ + test(); + IF ( st_fx->core_brate_fx == FRAME_NO_DATA || EQ_32(st_fx->core_brate_fx,SID_2k40)) + { + /* decode CNG parameters */ + IF ( EQ_16(st_fx->cng_type_fx,LP_CNG)) + { + + CNG_dec_fx( st_fx, st_fx->L_frame_fx, Aq_fx, st_fx->core_brate_fx, lsp_new_fx, lsf_new_fx, &allow_cn_step_fx, sid_bw, q_env ); + + /* comfort noise generation */ + CNG_exc_fx( st_fx->core_brate_fx, st_fx->L_frame_fx, &st_fx->Enew_fx, &st_fx->cng_seed_fx, exc_fx, exc2_fx, &st_fx->lp_ener_fx, st_fx->last_core_brate_fx, + &st_fx->first_CNG_fx, &(st_fx->cng_ener_seed_fx), bwe_exc_fx, allow_cn_step_fx, &st_fx->last_allow_cn_step_fx, st_fx->prev_Q_exc, st_fx->Q_exc, st_fx->num_ho_fx, + q_env, st_fx->lp_env_fx, st_fx->old_env_fx, st_fx->exc_mem_fx, st_fx->exc_mem1_fx, sid_bw, &st_fx->cng_ener_seed1_fx, exc3_fx ,st_fx->Opt_AMR_WB_fx ); + } + ELSE + { + IF( EQ_32(st_fx->core_brate_fx,SID_2k40)) + { + FdCng_decodeSID(st_fx->hFdCngDec_fx->hFdCngCom, st_fx); + *sid_bw=0; + move16(); + } + + generate_comfort_noise_dec( NULL, NULL, NULL, st_fx, &(st_fx->Q_exc), 2 ); + + FdCng_exc(st_fx->hFdCngDec_fx->hFdCngCom, &st_fx->CNG_mode_fx, st_fx->L_frame_fx, st_fx->lsp_old_fx, st_fx->first_CNG_fx, st_fx->lspCNG_fx, Aq_fx, lsp_new_fx, lsf_new_fx, exc_fx, exc2_fx, bwe_exc_fx); + + Copy( exc2_fx, exc3_fx, st_fx->L_frame_fx ); + } + + delta_mem_scale = 3; + move16(); + test(); + if( LT_32(st_fx->lp_ener_fx,40)&&EQ_16(st_fx->cng_type_fx,LP_CNG)) /* very low energy frames, less than 0.3125 */ + { + delta_mem_scale = 0; + move16(); + } + i = st_fx->Q_exc; + Rescale_exc( st_fx->dct_post_old_exc_fx, exc_fx, bwe_exc_fx, st_fx->last_exc_dct_in_fx, st_fx->L_frame_fx, + st_fx->L_frame_fx* HIBND_ACB_L_FAC, 0, &(st_fx->Q_exc), st_fx->Q_subfr, NULL, 0, INACTIVE); + + Rescale_mem( st_fx->Q_exc, &st_fx->prev_Q_syn, &st_fx->Q_syn, st_fx->mem_syn2_fx, st_fx->mem_syn_clas_estim_fx, delta_mem_scale, + &st_fx->mem_deemph_fx, st_fx->pst_old_syn_fx,&st_fx->pst_mem_deemp_err_fx, &st_fx->agc_mem_fx[1], &st_fx->pfstat, 0, 0, NULL ); + Copy_Scale_sig(exc2_fx, exc2_fx, st_fx->L_frame_fx, sub(st_fx->Q_exc, i)); + + /* update past excitation signals for LD music post-filter */ + Copy( st_fx->dct_post_old_exc_fx + L_FRAME, st_fx->dct_post_old_exc_fx, DCT_L_POST-L_FRAME-OFFSET2 ); + Copy( exc2_fx, st_fx->dct_post_old_exc_fx + (DCT_L_POST-L_FRAME-OFFSET2), L_FRAME ); + + /* synthesis at 12.8kHz sampling rate */ + syn_12k8_fx( st_fx->L_frame_fx, Aq_fx, exc2_fx, syn_fx, st_fx->mem_syn2_fx, 1, st_fx->Q_exc, st_fx->Q_syn ); + syn_12k8_fx( st_fx->L_frame_fx, Aq_fx, exc3_fx, syn1_fx, st_fx->mem_syn3_fx, 1, st_fx->Q_exc, st_fx->Q_syn ); + + /* reset the decoder */ + CNG_reset_dec_fx( st_fx, pitch_buf_fx, voice_factors ); + + /* update st_fx->mem_syn1 for ACELP core switching */ + Copy( st_fx->mem_syn3_fx, st_fx->mem_syn1_fx, M ); + + /* update old synthesis for classification */ + Copy( syn1_fx + st_fx->L_frame_fx - L_SYN_MEM_CLAS_ESTIM, st_fx->mem_syn_clas_estim_fx, L_SYN_MEM_CLAS_ESTIM ); + + /* Update music post processing values */ + /* Filter energies update */ + FOR( i = 0; i < DCT_L_POST; i++ ) + { + /*st_fx->filt_lfE_fx[i] = 0.3f + 0.7f * st_fx->filt_lfE_fx[i];*/ + st_fx->filt_lfE_fx[i] = round_fx(L_mac((1228<<(16)), 22938, st_fx->filt_lfE_fx[i])); + } + + /* save and delay synthesis to be used by SWB BWE */ + Copy_Scale_sig( syn1_fx, temp_buf_fx, st_fx->L_frame_fx, sub(-1,st_fx->Q_syn)); + save_old_syn_fx( st_fx->L_frame_fx, temp_buf_fx, old_syn_12k8_16k, st_fx->old_syn_12k8_16k_fx, st_fx->preemph_fac, &st_fx->mem_deemph_old_syn_fx); + } + + /*----------------------------------------------------------------* + * Decoding of all other frames + *----------------------------------------------------------------*/ + + ELSE + { + /*-----------------------------------------------------------------* + * After CNG period, use the most up-to-date LSPs + *-----------------------------------------------------------------*/ + + test(); + IF ( st_fx->last_core_brate_fx == FRAME_NO_DATA || EQ_32(st_fx->last_core_brate_fx,SID_2k40)) + { + Copy( st_fx->lspCNG_fx, st_fx->lsp_old_fx, M ); + + lsp2lsf_fx( st_fx->lspCNG_fx, st_fx->lsf_old_fx, M, int_fs ); + } + + /*-----------------------------------------------------------------* + * Reset higher ACELP pre-quantizer in case of switching + *-----------------------------------------------------------------*/ + + IF( !st_fx->use_acelp_preq ) + { + st_fx->mem_preemp_preQ_fx = 0; + move16(); + st_fx->last_nq_preQ_fx = 0; + move16(); + } + + st_fx->use_acelp_preq = 0; + move16(); + + /*-----------------------------------------------------------------* + * LSF de-quantization and interpolation + *-----------------------------------------------------------------*/ + + lsf_dec_fx( st_fx, tc_subfr_fx, st_fx->L_frame_fx, coder_type_fx, st_fx->bwidth_fx, Aq_fx, + &LSF_Q_prediction, lsf_new_fx, lsp_new_fx, lsp_mid_fx ); + + /*-----------------------------------------------------------------* + * FEC - first good frame after lost frame(s) (possibility to correct the ACB) + *-----------------------------------------------------------------*/ + + IF( GE_32(st_fx->core_brate_fx,ACELP_11k60)) + { + last_pulse_pos = 0; + move16(); + + /* decode the last glottal pulse position */ + T0_tmp = FEC_pos_dec_fx( st_fx, coder_type_fx, st_fx->last_good_fx, &last_pulse_pos, &st_fx->clas_dec, &enr_q_fx, st_fx->core_brate_fx ); + move16(); + + test(); + test(); + IF( NE_16(st_fx->last_core_fx,HQ_CORE)||(EQ_16(st_fx->last_core_fx,HQ_CORE)&&st_fx->last_con_tcx)) + { + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_16(st_fx->clas_dec,SIN_ONSET)&&last_pulse_pos!=0&&EQ_16(st_fx->prev_bfi_fx,1)) + { + st_fx->Q_exc = + FEC_SinOnset_fx( old_exc_fx+L_EXC_MEM_DEC-L_EXC_MEM, last_pulse_pos, T0_tmp, enr_q_fx, Aq_fx, st_fx->L_frame_fx, st_fx->Q_exc ); + } + ELSE IF( (EQ_16(coder_type_fx,GENERIC)||EQ_16(coder_type_fx,VOICED))&&last_pulse_pos!=0&&EQ_16(st_fx->old_bfi_cnt_fx,1)&&EQ_16(output_frame,L_FRAME16k)) + { + do_WI_fx = FEC_enhACB_fx( st_fx->L_frame_fx, st_fx->last_L_frame_fx, old_exc_fx+L_EXC_MEM_DEC-L_EXC_MEM , T0_tmp, last_pulse_pos, st_fx->bfi_pitch_fx ); + } + } + } + + /*------------------------------------------------------------* + * In case of first frame after an erasure and transition from voiced to unvoiced or inactive + * redo the LPC interpolation + *------------------------------------------------------------*/ + test(); + test(); + test(); + test(); + IF( st_fx->stab_fac_fx == 0 && st_fx->old_bfi_cnt_fx > 0 && NE_16(st_fx->clas_dec,VOICED_CLAS)&&NE_16(st_fx->clas_dec,ONSET)&&st_fx->relax_prev_lsf_interp_fx==0) + { + int_lsp4_fx(st_fx->L_frame_fx, st_fx->lsp_old_fx, lsp_mid_fx, lsp_new_fx, Aq_fx, M, 2 ); + } + + /*---------------------------------------------------------------* + * Decoding of the scaled predicted innovation energy + *---------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( NE_16(coder_type_fx,UNVOICED)&& + NE_16(coder_type_fx,AUDIO) && + NE_16(coder_type_fx,INACTIVE) && + !(LE_32(st_fx->core_brate_fx,ACELP_8k00) && NE_16(coder_type_fx,TRANSITION) ) ) || + (EQ_16(coder_type_fx,INACTIVE) && GE_32(st_fx->total_brate_fx,ACELP_32k) ) + ) + { + Es_pred_dec_fx( st_fx, &Es_pred_fx, coder_type_fx, st_fx->core_brate_fx ); + } + + /*------------------------------------------------------------* + * Decode excitation according to coding type + *------------------------------------------------------------*/ + + test(); + test(); + IF( EQ_16(st_fx->nelp_mode_dec_fx,1)) + { + /* SC-VBR - NELP frames */ + Scale_sig(exc_fx-L_EXC_MEM, L_EXC_MEM, -st_fx->Q_exc); + st_fx->Q_exc = 0; + move16(); + + decod_nelp_fx( st_fx, coder_type_fx, &tmp_noise_fx, pitch_buf_fx, exc_fx, exc2_fx, + voice_factors, bwe_exc_fx, &st_fx->Q_exc, st_fx->bfi_fx, gain_buf ); + + Rescale_exc(st_fx->dct_post_old_exc_fx, exc_fx, NULL, st_fx->last_exc_dct_in_fx, L_FRAME, 0, (Word32)0, &(st_fx->Q_exc), st_fx->Q_subfr, exc2_fx, L_FRAME, coder_type_fx); + } + ELSE IF( EQ_16(coder_type_fx,UNVOICED)) + { + /* UNVOICED frames */ + decod_unvoiced_fx( st_fx, Aq_fx, coder_type_fx, &tmp_noise_fx, pitch_buf_fx, voice_factors, exc_fx, exc2_fx, bwe_exc_fx, gain_buf ); + } + ELSE IF ( EQ_16(st_fx->ppp_mode_dec_fx,1)) + { + Scale_sig(exc_fx-L_EXC_MEM, L_EXC_MEM, -st_fx->Q_exc); + st_fx->Q_exc = 0; + /* SC-VBR - PPP frames */ + decod_ppp_fx( st_fx, Aq_fx, pitch_buf_fx, exc_fx, exc2_fx, st_fx->bfi_fx, gain_buf, voice_factors, bwe_exc_fx ); + + Rescale_exc( st_fx->dct_post_old_exc_fx, exc_fx, NULL, st_fx->last_exc_dct_in_fx, L_FRAME, 0, (Word32)0, &(st_fx->Q_exc), st_fx->Q_subfr, exc2_fx, L_FRAME, coder_type_fx ); + } + ELSE IF( EQ_16(coder_type_fx,TRANSITION )) + { + decod_tran_fx( st_fx, st_fx->L_frame_fx, tc_subfr_fx, Aq_fx, coder_type_fx, Es_pred_fx, pitch_buf_fx, voice_factors, exc_fx, exc2_fx, bwe_exc_fx, unbits, sharpFlag, gain_buf ); + } + ELSE IF( EQ_16(coder_type_fx,AUDIO)||(EQ_16(coder_type_fx,INACTIVE)&&LE_32(st_fx->core_brate_fx,ACELP_24k40))) + { + decod_audio_fx( st_fx, dct_exc_tmp, Aq_fx, coder_type_fx, pitch_buf_fx, voice_factors, exc_fx, exc2_fx, bwe_exc_fx, lsf_new_fx, gain_buf ); + tmp_noise_fx = shr_r(st_fx->lp_gainc_fx,3); /*Q0*/ + } + ELSE + { + decod_gen_voic_fx( st_fx, st_fx->L_frame_fx, sharpFlag, Aq_fx, coder_type_fx, Es_pred_fx, do_WI_fx, pitch_buf_fx, voice_factors, exc_fx, exc2_fx, bwe_exc_fx, unbits, gain_buf ); + } + + /* synthesis for ACELP core switching and SWB BWE */ + syn_12k8_fx( st_fx->L_frame_fx, Aq_fx, exc_fx, temp_buf_fx, st_fx->mem_syn1_fx, 1, st_fx->Q_exc, -1 ); + /* save and delay synthesis to be used by SWB BWE */ + save_old_syn_fx( st_fx->L_frame_fx, temp_buf_fx, old_syn_12k8_16k, st_fx->old_syn_12k8_16k_fx, st_fx->preemph_fac, &st_fx->mem_deemph_old_syn_fx ); + + + /*-----------------------------------------------------------------* + * Apply energy matching when switching to inactive frames + *-----------------------------------------------------------------*/ + + Inac_swtch_ematch_fx( exc2_fx, dct_exc_tmp, st_fx->lt_ener_per_band_fx, coder_type_fx, st_fx->L_frame_fx, st_fx->core_brate_fx, st_fx->Q_exc, st_fx->bfi_fx, st_fx->last_core_fx, st_fx->last_codec_mode ); + + /*------------------------------------------------------------* + * Decode information and modify the excitation signal of stationary unvoiced frames + *------------------------------------------------------------*/ + + IF ( NE_16(st_fx->nelp_mode_dec_fx,1)) + { + stat_noise_uv_dec_fx( st_fx, coder_type_fx, lsp_new_fx, lsp_mid_fx, Aq_fx, exc2_fx ); + } + + /*------------------------------------------------------------* + * Save filter memory in case the synthesis is redone after scaling + * Synthesis at 12k8 Hz sampling rate + *------------------------------------------------------------*/ + + /* update past excitation signals for LD music post-filter */ + Copy( st_fx->dct_post_old_exc_fx + L_FRAME, st_fx->dct_post_old_exc_fx, DCT_L_POST-L_FRAME-OFFSET2 ); + Copy( exc2_fx, st_fx->dct_post_old_exc_fx + (DCT_L_POST-L_FRAME-OFFSET2), L_FRAME ); + Copy( st_fx->dct_post_old_exc_fx, exc_buffer_fx, DCT_L_POST-OFFSET2 ); + + test(); + IF( EQ_16(coder_type_fx, AUDIO )&&st_fx->GSC_noisy_speech_fx==0) + { + + /* Extrapolation of the last future part, windowing and high resolution DCT transform */ + qdct = 0; + Prep_music_postP_fx( exc_buffer_fx, dct_buffer_fx, st_fx->filt_lfE_fx, st_fx->last_coder_type_fx, pitch_buf_fx, + st_fx->LDm_enh_lp_gbin_fx, st_fx->Q_exc, &qdct ); + + /* LD music post-filter */ + LD_music_post_filter_fx( dct_buffer_fx, dct_buffer_fx, st_fx->core_brate_fx, &st_fx->LDm_last_music_flag_fx, + st_fx->LDm_thres_fx, &st_fx->LDm_nb_thr_1_fx, &st_fx->LDm_nb_thr_3_fx, st_fx->LDm_lt_diff_etot_fx, + &st_fx->LDm_mem_etot_fx, st_fx->LDm_enh_min_ns_gain_fx, st_fx->LDm_bckr_noise_fx, + st_fx->LDm_enh_lf_EO_fx, st_fx->LDm_enh_lp_gbin_fx, st_fx->filt_lfE_fx, &st_fx->last_nonfull_music_fx, + &st_fx->Old_ener_Q, AUDIO, st_fx->last_coder_type_fx, qdct ); + + /* Inverse DCT transform, retrieval of the aligned excitation, re-synthesis */ + Post_music_postP_fx( dct_buffer_fx, exc2_fx, st_fx->mem_syn2_fx, st_fx->mem_syn2_fx, Aq_fx, syn_fx, &st_fx->Q_exc, &st_fx->prev_Q_syn, + &st_fx->Q_syn, st_fx->mem_syn_clas_estim_fx,0, &st_fx->mem_deemph_fx, st_fx->pst_old_syn_fx, + &st_fx->pst_mem_deemp_err_fx, &st_fx->agc_mem_fx[1], &st_fx->pfstat, temp_buf_fx, mem_tmp_fx ); + } + ELSE + { + /* Core synthesis at 12.8kHz or 16kHz */ + i = 1; + move16(); + if( EQ_16(coder_type_fx,INACTIVE)) + { + i = 0; + move16(); + } + /* add extra headroom in case a CNA addition is likely (i.e. st_fx->psf_lp_noise_fx is close to the threshold) */ + k = 0; + move16(); + test(); + test(); + if( EQ_16(coder_type_fx, INACTIVE)&&st_fx->flag_cna&&GE_16(round_fx(L_shl(st_fx->lp_noise,1)),15<<7)) + { + k = 1; + move16(); + } + + Rescale_mem( st_fx->Q_exc, &st_fx->prev_Q_syn, &st_fx->Q_syn, st_fx->mem_syn2_fx, st_fx->mem_syn_clas_estim_fx, 4, &st_fx->mem_deemph_fx, + st_fx->pst_old_syn_fx, &st_fx->pst_mem_deemp_err_fx, &st_fx->agc_mem_fx[1], &st_fx->pfstat, i, k, temp_buf_fx ); + + Copy( st_fx->mem_syn2_fx, mem_tmp_fx, M ); + + syn_12k8_fx( st_fx->L_frame_fx, Aq_fx, exc2_fx, syn_fx, st_fx->mem_syn2_fx, 1 , st_fx->Q_exc, st_fx->Q_syn); + + FOR( i = 0; i < DCT_L_POST; i++ ) + { + /*st_fx->filt_lfE_fx[i] = 0.3f + 0.7f * st_fx->filt_lfE_fx[i];*/ + st_fx->filt_lfE_fx[i] = round_fx(L_mac((1228<<(16)), 22938, st_fx->filt_lfE_fx[i])); + } + } + + /*------------------------------------------------------------* + * FEC - Estimate the classification information + *------------------------------------------------------------*/ + + FEC_clas_estim_fx( st_fx, st_fx->Opt_AMR_WB_fx, st_fx->L_frame_fx, &st_fx->clas_dec, coder_type_fx, pitch_buf_fx, + syn_fx, &st_fx->lp_ener_FER_fx, &st_fx->decision_hyst_fx, + NULL, NULL, NULL, NULL, 0, NULL, st_fx->core_brate_fx, st_fx->Q_syn, temp_buf_fx, + st_fx->mem_syn_clas_estim_fx, &st_fx->classifier_Q_mem_syn, + 0, 0, 0, st_fx->last_core_brate_fx ); + + /*------------------------------------------------------------* + * FEC - Estimate pitch + *------------------------------------------------------------*/ + + FEC_pitch_estim_fx( st_fx->Opt_AMR_WB_fx, st_fx->last_core_fx, st_fx->L_frame_fx, st_fx->clas_dec, st_fx->last_good_fx, pitch_buf_fx, st_fx->old_pitch_buf_fx, + &st_fx->bfi_pitch_fx, &st_fx->bfi_pitch_frame_fx, &st_fx->upd_cnt_fx, coder_type_fx ); + + /*------------------------------------------------------------* + * FEC - Smooth the speech energy evolution when recovering after a BAD frame + * (smoothing is performed in the excitation domain and signal is resynthesized after) + *------------------------------------------------------------*/ + + k = 0; + move16(); + FOR (i = 0; i < st_fx->L_frame_fx; i += L_SUBFR) + { + pitch_buf_tmp[k] = mult_r(pitch_buf_fx[k], 512); + move16(); + k++; + } + + FEC_scale_syn_fx( st_fx->L_frame_fx, &update_flg, st_fx->clas_dec, st_fx->last_good_fx, syn_fx, pitch_buf_tmp, st_fx->enr_old_fx, enr_q_fx, coder_type_fx, LSF_Q_prediction, + &st_fx->scaling_flag, &st_fx->lp_ener_FEC_av, &st_fx->lp_ener_FEC_max, st_fx->bfi_fx, st_fx->total_brate_fx, st_fx->prev_bfi_fx, st_fx->last_core_brate_fx, + exc_fx, exc2_fx, Aq_fx, &st_fx->old_enr_LP, mem_tmp_fx, st_fx->mem_syn2_fx, st_fx->Q_exc, st_fx->Q_syn , avoid_lpc_burst_on_recovery, 0 ); + + test(); + if( (EQ_32(st_fx->total_brate_fx,ACELP_7k20))||(EQ_32(st_fx->total_brate_fx,ACELP_8k00))) + { + frame_ener_fx( st_fx->L_frame_fx, st_fx->clas_dec, syn_fx, pitch_buf_tmp[sub(shr(st_fx->L_frame_fx,6),1)], &st_fx->enr_old_fx, st_fx->L_frame_fx, st_fx->Q_syn, 3, 0 ); + } + } + + } /* End of GOOD FRAME */ + + /*----------------------------------------------------------------* + * BAD frame + *----------------------------------------------------------------*/ + ELSE + { + /* SC-VBR */ + if ( EQ_16(st_fx->last_nelp_mode_dec_fx,1)) + { + st_fx->nelp_mode_dec_fx = 1; + move16(); + } + + /* long burst frame erasures */ + test(); + test(); + if( GT_16(st_fx->nbLostCmpt,5)&&GE_16(st_fx->clas_dec,VOICED_CLAS)&<_16(st_fx->clas_dec,INACTIVE_CLAS)) + { + st_fx->last_good_fx = VOICED_TRANSITION; + move16(); + } + + /* LSF estimation and A(z) calculation */ + lsf_dec_bfi( MODE1, lsf_new_fx, st_fx->lsf_old_fx, st_fx->lsf_adaptive_mean_fx, NULL, st_fx->mem_MA_fx, st_fx->mem_AR_fx, + st_fx->stab_fac_fx, st_fx->last_coder_type_fx, st_fx->L_frame_fx, st_fx->last_good_fx, + st_fx->nbLostCmpt, 0, NULL, NULL, NULL, st_fx->Last_GSC_pit_band_idx_fx, st_fx->Opt_AMR_WB_fx, 0, st_fx->bwidth_fx); + + FEC_lsf2lsp_interp( st_fx, st_fx->L_frame_fx, Aq_fx, lsf_new_fx, lsp_new_fx ); + + IF ( st_fx->nelp_mode_dec_fx == 1 ) + { + /* SC-VBR */ + Scale_sig(exc_fx-L_EXC_MEM, L_EXC_MEM, -st_fx->Q_exc); + st_fx->Q_exc = 0; + move16(); + + decod_nelp_fx( st_fx, coder_type_fx, &tmp_noise_fx, pitch_buf_fx, exc_fx, exc2_fx, + voice_factors, bwe_exc_fx, &st_fx->Q_exc, st_fx->bfi_fx, gain_buf ); + + FEC_pitch_fx = pitch_buf_fx[3]; + move16(); + + Rescale_exc( st_fx->dct_post_old_exc_fx, exc_fx, NULL, st_fx->last_exc_dct_in_fx, L_FRAME, 0, (Word32)0, &(st_fx->Q_exc), st_fx->Q_subfr, exc2_fx, L_FRAME, coder_type_fx ); + } + ELSE + { + /* calculation of excitation signal */ + + FEC_exc_estim_fx( st_fx, st_fx->L_frame_fx, exc_fx, exc2_fx, dct_exc_tmp, pitch_buf_fx, voice_factors, &FEC_pitch_fx, bwe_exc_fx, lsf_new_fx, &st_fx->Q_exc, &tmp_noise_fx ); + + Rescale_exc( NULL, exc_fx, bwe_exc_fx, st_fx->last_exc_dct_in_fx, st_fx->L_frame_fx, L_FRAME32k, (Word32)0, + &(st_fx->Q_exc), st_fx->Q_subfr, exc2_fx, st_fx->L_frame_fx, st_fx->last_coder_type_fx ); + + tmp_noise_fx = shr_r(st_fx->lp_gainc_fx,3); /*Q0*/ + + /* SC-VBR */ + st_fx->prev_gain_pit_dec_fx = st_fx->lp_gainp_fx; + move16(); /*Q14*/ + } + + /* synthesis for ACELP core switching and SWB BWE */ + syn_12k8_fx( st_fx->L_frame_fx, Aq_fx, exc_fx, temp_buf_fx, st_fx->mem_syn1_fx, 1, st_fx->Q_exc, -1 ); /*old_syn_12k8_16k directly in q-1*/ + + /* save and delay synthesis to be used by SWB BWE */ + save_old_syn_fx( st_fx->L_frame_fx, temp_buf_fx, old_syn_12k8_16k, st_fx->old_syn_12k8_16k_fx, st_fx->preemph_fac, &st_fx->mem_deemph_old_syn_fx ); + + /* Apply energy matching when switching to inactive frames */ + Inac_swtch_ematch_fx( exc2_fx, dct_exc_tmp, st_fx->lt_ener_per_band_fx, coder_type_fx, st_fx->L_frame_fx, st_fx->core_brate_fx, st_fx->Q_exc, st_fx->bfi_fx, st_fx->last_core_fx, st_fx->last_codec_mode ); + + /* udate past excitation signals for LD music post-filter */ + Copy( st_fx->dct_post_old_exc_fx + L_FRAME, st_fx->dct_post_old_exc_fx, DCT_L_POST-L_FRAME-OFFSET2 ); + Copy( exc2_fx, st_fx->dct_post_old_exc_fx + (DCT_L_POST-L_FRAME-OFFSET2), L_FRAME ); + + /* synthesis at 12k8 Hz sampling rate */ + /* add extra headroom in case a CNA addition is likely (i.e. st_fx->psf_lp_noise_fx is close to the threshold) */ + k = 0; + move16(); + test(); + test(); + if( EQ_16(coder_type_fx, INACTIVE)&&st_fx->flag_cna&&GE_16(round_fx(L_shl(st_fx->lp_noise,1)),15<<7)) + { + k = 1; + move16(); + } + + Rescale_mem( st_fx->Q_exc, &st_fx->prev_Q_syn, &st_fx->Q_syn, st_fx->mem_syn2_fx, st_fx->mem_syn_clas_estim_fx, 4, &st_fx->mem_deemph_fx, + st_fx->pst_old_syn_fx, &st_fx->pst_mem_deemp_err_fx, &st_fx->agc_mem_fx[1], &st_fx->pfstat, 1, k, temp_buf_fx ); + + if( (EQ_32(st_fx->total_brate_fx,ACELP_7k20))||(EQ_32(st_fx->total_brate_fx,ACELP_8k00))) + { + Copy( st_fx->mem_syn2_fx, mem_tmp_fx, M ); + } + syn_12k8_fx( st_fx->L_frame_fx, Aq_fx, exc2_fx, syn_fx, st_fx->mem_syn2_fx, 1, st_fx->Q_exc, st_fx->Q_syn); + + /* update buffer for classifier */ + Copy( exc2_fx + st_fx->L_frame_fx - L_EXC_MEM, st_fx->old_exc2_fx, L_EXC_MEM ); + Copy( syn_fx + st_fx->L_frame_fx - L_EXC_MEM, st_fx->old_syn2_fx, L_EXC_MEM ); + st_fx->prev_Q_exc_fr = st_fx->Q_exc; + st_fx->prev_Q_syn_fr = st_fx->Q_syn; + + Copy( syn_fx + st_fx->L_frame_fx - L_SYN_MEM_CLAS_ESTIM, st_fx->mem_syn_clas_estim_fx, L_SYN_MEM_CLAS_ESTIM ); + + /* Update music post processing values */ + /* Filter energies update */ + FOR( i = 0; i < DCT_L_POST; i++ ) + { + /*st_fx->filt_lfE_fx[i] = 0.3f + 0.7f * st_fx->filt_lfE_fx[i];*/ + st_fx->filt_lfE_fx[i] = round_fx(L_mac((1228<<(16)), 22938, st_fx->filt_lfE_fx[i])); + } + /* Update circular buffer, keep last energy difference unchanged */ + FOR( i = 1; iLDm_lt_diff_etot_fx[i-1] = st_fx->LDm_lt_diff_etot_fx[i]; + move16(); + } + + if( (EQ_32(st_fx->total_brate_fx,ACELP_7k20))||(EQ_32(st_fx->total_brate_fx,ACELP_8k00))) + { + k = 0; + move16(); + FOR (i = 0; i < st_fx->L_frame_fx; i += L_SUBFR) + { + pitch_buf_tmp[k] = mult_r(pitch_buf_fx[k], 512); + move16(); + k++; + } + + /*------------------------------------------------------------* + * FEC - Smooth the speech energy evolution when recovering after a BAD frame + * (smoothing is performed in the excitation domain and signal is resynthesized after) + *------------------------------------------------------------*/ + + FEC_scale_syn_fx( st_fx->L_frame_fx, &update_flg, st_fx->clas_dec, st_fx->last_good_fx, syn_fx, pitch_buf_tmp, st_fx->enr_old_fx, enr_q_fx, coder_type_fx, LSF_Q_prediction, + &st_fx->scaling_flag, &st_fx->lp_ener_FEC_av, &st_fx->lp_ener_FEC_max, st_fx->bfi_fx, st_fx->total_brate_fx, st_fx->prev_bfi_fx, st_fx->last_core_brate_fx, + exc_fx, exc2_fx, Aq_fx, &st_fx->old_enr_LP, mem_tmp_fx, st_fx->mem_syn2_fx, st_fx->Q_exc, st_fx->Q_syn, avoid_lpc_burst_on_recovery, 0 ); + } + + /* estimate the pitch-synchronous speech energy per sample to be used when normal operation recovers */ + /* fer_energy( st_fx->L_frame_fx, st_fx->last_good_fx, syn_fx, FEC_pitch_fx, &st_fx->enr_old_fx, st_fx->L_frame_fx ); */ + frame_ener_fx( st_fx->L_frame_fx, st_fx->last_good_fx, syn_fx, shr(add(FEC_pitch_fx,32),6), &st_fx->enr_old_fx, st_fx->L_frame_fx, st_fx->Q_syn, 3, 0 ); + + IF ( st_fx->nelp_mode_dec_fx !=1 ) + { + /* modify the excitation signal of stationary unvoiced frames */ + stat_noise_uv_mod_fx( coder_type_fx, 0, st_fx->lsp_old_fx, lsp_new_fx, lsp_new_fx, Aq_fx, exc2_fx, st_fx->Q_exc, 1, &st_fx->ge_sm_fx, + &st_fx->uv_count_fx, &st_fx->act_count_fx, st_fx->lspold_s_fx, &st_fx->noimix_seed_fx, &st_fx->min_alpha_fx, + &st_fx->exc_pe_fx, st_fx->core_brate_fx,st_fx->bwidth_fx, &st_fx->Q_stat_noise, &st_fx->Q_stat_noise_ge ); + } + + /* SC-VBR */ + st_fx->FadeScale_fx = mult(st_fx->FadeScale_fx,24576); /*24576 in Q15*/ + } + + IF (EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + Copy( Aq_fx+2*(M+1), st_fx->cur_sub_Aq_fx, (M+1) ); + } + ELSE + { + Copy( Aq_fx+3*(M+1), st_fx->cur_sub_Aq_fx, (M+1) ); + } + + /*--------------------------------------------------------* + * Apply NB postfilter in case of 8kHz output + *--------------------------------------------------------*/ + + IF( EQ_16(st_fx->last_bwidth_fx,NB)) + { + k = 0; + move16(); + FOR (i = 0; i < st_fx->L_frame_fx; i += L_SUBFR) + { + pitch_buf_tmp[k] = mult_r(pitch_buf_fx[k], 512); + move16(); + k++; + } + + IF(EQ_16(st_fx->bwidth_fx,NB)) + { + st_fx->pfstat.on = 1; + move16(); + nb_post_filt( st_fx->L_frame_fx, &(st_fx->pfstat), &st_fx->psf_lp_noise_fx, tmp_noise_fx, syn_fx, Aq_fx, pitch_buf_tmp, coder_type_fx, st_fx->BER_detect, 0 ); + } + ELSE + { + st_fx->pfstat.on = 0; + move16(); + nb_post_filt( st_fx->L_frame_fx, &(st_fx->pfstat), &st_fx->psf_lp_noise_fx, tmp_noise_fx, syn_fx, Aq_fx, pitch_buf_tmp, AUDIO, st_fx->BER_detect, 0 ); + } + } + ELSE + { + st_fx->psf_lp_noise_fx = round_fx(L_shl(st_fx->lp_noise,1)); + } + + /*------------------------------------------------------------------* + * Perform fixed deemphasis through 1/(1 - g*z^-1) + *-----------------------------------------------------------------*/ + + /* Update old synthesis buffer - needed for ACELP internal sampling rate switching */ + Copy( syn_fx + st_fx->L_frame_fx - L_SYN_MEM, st_fx->mem_syn_r, L_SYN_MEM ); + deemph_fx( syn_fx, st_fx->preemph_fac, st_fx->L_frame_fx, &(st_fx->mem_deemph_fx) ); + + unscale_AGC( syn_fx, st_fx->Q_syn, syn_fx_tmp2, st_fx->agc_mem_fx, st_fx->L_frame_fx ); + Copy(syn_fx_tmp2, syn_fx, st_fx->L_frame_fx); + + /* Update MODE2 memories*/ + Copy_Scale_sig( syn_fx + st_fx->L_frame_fx/2, st_fx->old_syn_Overl, st_fx->L_frame_fx/2, sub(-1,st_fx->Q_syn)); /*Q-1*/ + Copy_Scale_sig( syn_fx + st_fx->L_frame_fx-M-1, st_fx->syn, M+1, sub(0,st_fx->Q_syn)); /*Q0*/ + + /*------------------------------------------------------------------* + * Formant post-filter + *-----------------------------------------------------------------*/ + + test(); + test(); + IF( GE_16(st_fx->last_bwidth_fx,WB)&>_32(st_fx->core_brate_fx,ACELP_24k40)&&LE_32(st_fx->core_brate_fx,ACELP_32k)) + { + Copy( syn_fx, temp_buf + L_SYN_MEM, L_FRAME16k ); + st_fx->pfstat.on = 1; + move16(); + formant_post_filt( &(st_fx->pfstat), temp_buf + L_SYN_MEM, Aq_fx, syn_fx, L_FRAME16k, st_fx->lp_noise, st_fx->total_brate_fx, 0); + } + ELSE IF( GE_16(st_fx->last_bwidth_fx,WB)) + { + if( st_fx->pfstat.on ) + { + Copy( st_fx->pfstat.mem_pf_in+L_SYN_MEM-M, temp_buf, M ); + Copy( syn_fx, temp_buf + M, L_SUBFR ); + Residu3_fx ( Aq_fx, temp_buf + M, temp_buf+M+L_SUBFR, L_SUBFR, 1 ); + E_UTIL_synthesis ( 1, Aq_fx, temp_buf+M+L_SUBFR, temp_buf, L_SUBFR, st_fx->pfstat.mem_stp+L_SYN_MEM-M, 0, M ); + scale_st ( syn_fx, temp_buf, &st_fx->pfstat.gain_prec, L_SUBFR ); + Copy( temp_buf, syn_fx, L_SUBFR/2 ); + blend_subfr2( temp_buf + L_SUBFR/2, syn_fx + L_SUBFR/2, syn_fx + L_SUBFR/2 ); + } + st_fx->pfstat.on = 0; + move16(); + } + + /*----------------------------------------------------------------* + * Comfort noise addition + *----------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + IF( st_fx->flag_cna || (EQ_16(st_fx->cng_type_fx,FD_CNG)&&LE_32(st_fx->total_brate_fx,ACELP_32k))||(EQ_16(st_fx->cng_type_fx,LP_CNG)&&LE_32(st_fx->total_brate_fx,SID_2k40))) + { + /*VAD only for non inactive frame*/ + test(); + st_fx->VAD = st_fx->VAD && (coder_type_fx != INACTIVE); + + /*Noisy speech detector*/ + noisy_speech_detection( st_fx->VAD, syn_fx, st_fx->L_frame_fx, st_fx->Q_syn, st_fx->hFdCngDec_fx->msNoiseEst, st_fx->hFdCngDec_fx->msNoiseEst_exp, + st_fx->hFdCngDec_fx->psize_shaping_norm, st_fx->hFdCngDec_fx->psize_shaping_norm_exp, st_fx->hFdCngDec_fx->nFFTpart_shaping, + &(st_fx->hFdCngDec_fx->lp_noise), &(st_fx->hFdCngDec_fx->lp_speech), &(st_fx->hFdCngDec_fx->hFdCngCom->flag_noisy_speech) ); + + st_fx->hFdCngDec_fx->hFdCngCom->likelihood_noisy_speech = mult_r(st_fx->hFdCngDec_fx->hFdCngCom->likelihood_noisy_speech, 32440/*0.99 Q15*/); + IF ( st_fx->hFdCngDec_fx->hFdCngCom->flag_noisy_speech != 0 ) + { + st_fx->hFdCngDec_fx->hFdCngCom->likelihood_noisy_speech = add(st_fx->hFdCngDec_fx->hFdCngCom->likelihood_noisy_speech, 328/*0.01 Q15*/); + move16(); + } + st_fx->lp_noise = st_fx->hFdCngDec_fx->lp_noise; + move32(); + + /*Noise estimate*/ + test(); + test(); + ApplyFdCng( syn_fx, st_fx->Q_syn, realBuffer, imagBuffer, 0, st_fx->hFdCngDec_fx, st_fx->m_frame_type, st_fx, 0, + (EQ_16(coder_type_fx, AUDIO ) && st_fx->GSC_noisy_speech_fx == 0) ); + + /* CNA: Generate additional comfort noise to mask potential coding artefacts */ + test(); + test(); + test(); + test(); + IF( st_fx->flag_cna && NE_16(coder_type_fx,AUDIO)) + { + generate_masking_noise( syn_fx, st_fx->Q_syn, st_fx->hFdCngDec_fx->hFdCngCom, st_fx->hFdCngDec_fx->hFdCngCom->frameSize, 0 ); + } + ELSE IF( st_fx->flag_cna && coder_type_fx == AUDIO && st_fx->last_core_fx == ACELP_CORE && st_fx->last_coder_type_fx != AUDIO ) + { + FOR (i=0; i < st_fx->hFdCngDec_fx->hFdCngCom->frameSize/2; i++) + { + syn_fx[i] = add( syn_fx[i], shr_r( mult_r( st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth2[i+5*st_fx->hFdCngDec_fx->hFdCngCom->frameSize/4], st_fx->hFdCngDec_fx->hFdCngCom->fftlenFac ), -st_fx->Q_syn ) ); + move16(); + } + } + } + + IF( st_fx->flag_cna == 0 && EQ_16(st_fx->L_frame_fx,L_FRAME16k)&&st_fx->last_flag_cna==1&&((st_fx->last_core_fx==ACELP_CORE&&st_fx->last_coder_type_fx!=AUDIO)||st_fx->last_core_fx==AMR_WB_CORE)) + { + FOR (i=0; i < st_fx->L_frame_fx/2; i++) + { + syn_fx[i] = add( syn_fx[i], shr_r( st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth2[i+5*st_fx->L_frame_fx/4], -st_fx->Q_syn ) ); + move16(); + } + } + + test(); + IF( st_fx->flag_cna == 0 || EQ_16(coder_type_fx,AUDIO)) + { + set16_fx( st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth2, 0, st_fx->hFdCngDec_fx->hFdCngCom->fftlen ); + } + + /*----------------------------------------------------------------* + * Resample to the output sampling rate (8/16/32/48 kHz) + * Bass post-filter + *----------------------------------------------------------------*/ + + /* check if the CLDFB works on the right sample rate */ + IF( (st_fx->cldfbAna_fx->usb * st_fx->cldfbAna_fx->no_col) != st_fx->L_frame_fx ) + { + /* resample to ACELP internal sampling rate */ + Word16 newCldfbBands = CLDFB_getNumChannels(L_mult0(st_fx->L_frame_fx,50)); + resampleCldfb( st_fx->cldfbAna_fx, newCldfbBands, st_fx->L_frame_fx, 0 ); + resampleCldfb( st_fx->cldfbBPF_fx, newCldfbBands, st_fx->L_frame_fx, 0 ); + + if( st_fx->ini_frame_fx > 0 ) + { + st_fx->cldfbSyn_fx->bandsToZero = sub(st_fx->cldfbSyn_fx->no_channels,st_fx->cldfbAna_fx->no_channels); + } + } + + test(); + IF( NE_16(st_fx->L_frame_fx,st_fx->last_L_frame_fx)&&NE_16(st_fx->last_codec_mode,MODE2)) + { + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + retro_interp5_4_fx( st_fx->pst_old_syn_fx ); + } + ELSE IF( EQ_16(st_fx->L_frame_fx,L_FRAME16k)) + { + retro_interp4_5_fx( syn_fx, st_fx->pst_old_syn_fx ); + } + } + + bass_psfilter_fx( st_fx->Opt_AMR_WB_fx, syn_fx, st_fx->L_frame_fx, pitch_buf_fx, st_fx->pst_old_syn_fx, + &st_fx->pst_mem_deemp_err_fx, &st_fx->pst_lp_ener_fx, st_fx->bpf_off_fx, st_fx->stab_fac_fx, &st_fx->stab_fac_smooth_fx, + st_fx->mem_mean_pit_fx, st_fx->Track_on_hist_fx, st_fx->vibrato_hist_fx, &st_fx->psf_att_fx, coder_type_fx, st_fx->Q_syn, bpf_error_signal ); + + /* analysis of the synthesis at internal sampling rate */ + cldfbAnalysisFiltering( st_fx->cldfbAna_fx, realBuffer, imagBuffer, &scaleFactor, syn_fx, negate(st_fx->Q_syn), CLDFB_NO_COL_MAX, workBuffer); + + scaleFactor.hb_scale = scaleFactor.lb_scale; + move16(); + + /* analysis and add the BPF error signal */ + i = 0; + move16(); + if( st_fx->bpf_off_fx == 0 ) + { + i = CLDFB_NO_COL_MAX; + move16(); + } + addBassPostFilterFx( bpf_error_signal, realBuffer, imagBuffer, st_fx->cldfbBPF_fx, workBuffer, negate(st_fx->Q_syn), + i, st_fx->cldfbAna_fx->no_col, st_fx->cldfbAna_fx->no_channels, &scaleFactor ); + + /* set output mask for upsampling */ + IF( EQ_16(st_fx->bwidth_fx,NB)) + { + /* set NB mask for upsampling */ + st_fx->cldfbSyn_fx->bandsToZero = sub(st_fx->cldfbSyn_fx->no_channels,10); + } + ELSE if( NE_16(st_fx->cldfbSyn_fx->bandsToZero,sub(st_fx->cldfbSyn_fx->no_channels,st_fx->cldfbAna_fx->no_channels))) + { + /* in case of BW switching, re-init to default */ + st_fx->cldfbSyn_fx->bandsToZero = sub(st_fx->cldfbSyn_fx->no_channels, st_fx->cldfbAna_fx->no_channels); + } + + /*WB/SWB-FD_CNG*/ + scaleFactor.hb_scale = scaleFactor.lb_scale; + move16(); + + test(); + test(); + test(); + IF( ( EQ_32(st_fx->core_brate_fx,FRAME_NO_DATA)||EQ_32(st_fx->core_brate_fx,SID_2k40))&&(EQ_16(st_fx->cng_type_fx,FD_CNG))&&(LT_16(st_fx->hFdCngDec_fx->hFdCngCom->numCoreBands,st_fx->cldfbSyn_fx->no_channels))) + { + generate_comfort_noise_dec_hf( realBuffer, imagBuffer, &scaleFactor.hb_scale, st_fx ); + + st_fx->cldfbSyn_fx->bandsToZero = 0; + move16(); + if( LT_16(st_fx->hFdCngDec_fx->hFdCngCom->regularStopBand, st_fx->cldfbSyn_fx->no_channels)) + { + st_fx->cldfbSyn_fx->bandsToZero = sub(st_fx->cldfbSyn_fx->no_channels, st_fx->hFdCngDec_fx->hFdCngCom->regularStopBand); + } + st_fx->cldfbSyn_fx->lsb = st_fx->cldfbAna_fx->no_channels; + move16(); + } + + /* synthesis of the combined signal */ + st_fx->Q_syn2 = st_fx->Q_syn; + move16(); + cldfbSynthesisFiltering(st_fx->cldfbSyn_fx, realBuffer, imagBuffer, &scaleFactor, synth_out, negate(st_fx->Q_syn2), CLDFB_NO_COL_MAX, workBuffer); + + /* Bring CLDFB output to Q0 */ + Scale_sig(synth_out, output_frame, negate(st_fx->Q_syn2)); + st_fx->Q_syn2 = 0; + move16(); + + /* save synthesis - needed in case of core switching */ + Copy( synth_out, st_fx->previoussynth_fx, output_frame ); + + /*-----------------------------------------------------------------* + * Bandwidth extension 6kHz-7kHz (only for 16kHz input signals) + *-----------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( (EQ_16(st_fx->L_frame_fx,L_FRAME)&&NE_16(st_fx->bwidth_fx,NB)&&GE_16(output_frame,L_FRAME16k)&& + ( EQ_16(st_fx->extl_fx,-1) || EQ_16(st_fx->extl_fx,SWB_CNG) || (EQ_16(st_fx->extl_fx,WB_BWE) && st_fx->extl_brate_fx == 0 && NE_16(coder_type_fx,AUDIO) )) ) ) + { + hf_synth_fx( st_fx->core_brate_fx, output_frame, Aq_fx, exc2_fx, syn_fx, synth_out, &st_fx->seed2_fx, + st_fx->mem_hp400_fx, st_fx->mem_syn_hf_fx, st_fx->mem_hf_fx, st_fx->Q_exc, + st_fx->Q_syn2, st_fx->delay_syn_hf_fx, &st_fx->memExp1, st_fx->mem_hp_interp_fx, st_fx->extl_fx, st_fx->CNG_mode_fx ); + } + ELSE + { + hf_synth_reset_fx( &st_fx->seed2_fx, st_fx->mem_hf_fx, st_fx->mem_syn_hf_fx, st_fx->mem_hp400_fx, st_fx->mem_hp_interp_fx, st_fx->delay_syn_hf_fx ); + } + + /*-----------------------------------------------------------------* + * Populate parameters for SWB TBE + *-----------------------------------------------------------------*/ + + /* Apply a non linearity to the SHB excitation */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( !st_fx->bfi_fx && ( st_fx->prev_bfi_fx )) || ((EQ_16(st_fx->last_vbr_hw_BWE_disable_dec_fx,1))&&(st_fx->vbr_hw_BWE_disable_dec_fx==0))||((EQ_16(st_fx->extl_fx,SWB_TBE)||EQ_16(st_fx->extl_fx,WB_TBE)||EQ_16(st_fx->extl_fx,FB_TBE))&&NE_16(st_fx->last_extl_fx,SWB_TBE)&&NE_16(st_fx->last_extl_fx,WB_TBE)&&NE_16(st_fx->last_extl_fx,FB_TBE))) + { + st_fx->bwe_non_lin_prev_scale_fx = L_deposit_l(0); + set16_fx( st_fx->old_bwe_exc_extended_fx, 0, NL_BUFF_OFFSET ); + } + + + IF( !st_fx->ppp_mode_dec_fx ) + { + non_linearity_fx( bwe_exc_fx, bwe_exc_extended, L_FRAME32k, &st_fx->bwe_non_lin_prev_scale_fx, st_fx->Q_exc , + coder_type_fx, voice_factors, st_fx->L_frame_fx ); + } + + test(); + if( EQ_32(st_fx->core_brate_fx,FRAME_NO_DATA)||EQ_32(st_fx->core_brate_fx,SID_2k40)) + { + st_fx->bwe_non_lin_prev_scale_fx = L_deposit_l(0); + } + + /*----------------------------------------------------------------------* + * Updates + *----------------------------------------------------------------------*/ + + updt_dec_fx( st_fx, st_fx->L_frame_fx, coder_type_fx, old_exc_fx, pitch_buf_fx, Es_pred_fx, Aq_fx, lsf_new_fx, lsp_new_fx, voice_factors, old_bwe_exc_fx, gain_buf ); + + IF( GT_32(st_fx->core_brate_fx,SID_2k40)) + { + /* update CNG parameters in active frames */ + cng_params_upd_fx( lsp_new_fx, exc_fx, st_fx->L_frame_fx, &st_fx->ho_circ_ptr_fx, st_fx->ho_ener_circ_fx, &st_fx->ho_circ_size_fx, st_fx->ho_lsp_circ_fx, + st_fx->Q_exc, DEC, st_fx->ho_env_circ_fx, NULL, NULL, NULL, NULL, st_fx->last_active_brate_fx ); + + /* Set 16k LSP flag for CNG buffer */ + st_fx->ho_16k_lsp_fx[st_fx->ho_circ_ptr_fx] = 0; + move16(); + if( NE_16(st_fx->L_frame_fx, L_FRAME)) + { + st_fx->ho_16k_lsp_fx[st_fx->ho_circ_ptr_fx] = 1; + move16(); + } + } + + return; +} diff --git a/lib_dec/acelp_core_switch_dec_fx.c b/lib_dec/acelp_core_switch_dec_fx.c new file mode 100644 index 0000000..8a0e2dc --- /dev/null +++ b/lib_dec/acelp_core_switch_dec_fx.c @@ -0,0 +1,677 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required for wmc_tool */ + +/*---------------------------------------------------------------------* +* Local functions +*---------------------------------------------------------------------*/ + +static void decod_gen_voic_core_switch_fx( Decoder_State_fx *st_fx, const Word16 L_frame, const Word16 sharpFlag, const Word16 *Aq, const Word16 coder_type, + Word16 *exc, const Word32 core_brate, Word16 *Q_exc ); + +/*-------------------------------------------------------------------* +* acelp_core_switch_dec() +* +* ACELP core decoder in the first ACELP->HQ switching frame +*-------------------------------------------------------------------*/ + +void acelp_core_switch_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *synth_subfr_out, /* o : synthesized ACELP subframe Q_syn*/ + Word16 *tmp_synth_bwe, /* o : synthesized ACELP subframe BWE Q_syn*/ + const Word16 output_frame, /* i : input frame length */ + const Word16 core_switching_flag, /* i : core switching flag */ + Word16 *mem_synth, /* o : synthesis to overlap */ + Word16 *Q_syn +) +{ + Word16 i, delta, L_frame_for_cs, decode_bwe, tmp; + Word16 d1m, ind1, fdelay, gapsize; + Word32 cbrate; + Word16 synth_intFreq[2*L_SUBFR]; + CLDFB_SCALE_FACTOR scaleFactor; + Word32 workBuffer[128*3]; + Word16 old_exc[L_EXC_DEC], *exc; + Word16 tmp_mem2[2*L_FILT48k], gain; + Word16 hb_synth_tmp[NS2SA(48000,10000000)]; + const Word16 *hp_filter; + Word16 Aq[2*(M+1)]; + Word16 bpf_error_signal[2*L_SUBFR]; + Word16 *pt1, *pt2; + Word16 syn_fx_tmp[L_FRAME_16k]; + Word32 *realBuffer[CLDFB_NO_COL_MAX_SWITCH], *imagBuffer[CLDFB_NO_COL_MAX_SWITCH]; + Word32 realBufferTmp[CLDFB_NO_COL_MAX_SWITCH][CLDFB_NO_CHANNELS_MAX], imagBufferTmp[CLDFB_NO_COL_MAX_SWITCH][CLDFB_NO_CHANNELS_MAX]; + + FOR( i=0; iold_Aq_12_8_fx, Aq, M+1 ); + Copy( st_fx->old_Aq_12_8_fx, Aq + (M+1), M+1 ); + + set16_fx( mem_synth, 0, NS2SA(16000, DELAY_CLDFB_NS)+2 ); + set16_fx( synth_subfr_out, 0, SWITCH_MAX_GAP ); /* avoid valgrind complaining about uninitialized memory in core_switching_OLA_fx() */ + + /* set multiplication factor according to the sampling rate */ + delta = 1; + if( GT_16(output_frame, L_FRAME16k)) + { + delta = shr(output_frame,8); + } + + /*----------------------------------------------------------------* + * set switching frame bit-rate + *----------------------------------------------------------------*/ + + test(); + test(); + test(); + IF( core_switching_flag && EQ_16(st_fx->last_L_frame_fx, st_fx->last_L_frame_ori_fx)&&((EQ_16(st_fx->last_core_fx,ACELP_CORE))||(EQ_16(st_fx->last_core_fx,AMR_WB_CORE)))) + { + exc = old_exc + L_EXC_MEM_DEC; + Copy( st_fx->old_exc_fx, old_exc, L_EXC_MEM_DEC ); /*scaling of exc from previous frame*/ + + IF( EQ_16(st_fx->last_L_frame_fx, L_FRAME)) + { + cbrate = L_add(st_fx->core_brate_fx, 0); + if( GT_32(cbrate, ACELP_24k40)) + { + cbrate = L_add(ACELP_24k40, 0); + } + + L_frame_for_cs = L_FRAME; + move16(); + } + ELSE + { + IF( LE_32(st_fx->core_brate_fx, ACELP_8k00)) + { + cbrate = L_add(ACELP_8k00, 0); + } + ELSE IF( LE_32(st_fx->core_brate_fx, ACELP_14k80)) + { + cbrate = L_add(ACELP_14k80, 0); + } + ELSE + { + cbrate = L_min(st_fx->core_brate_fx, ACELP_22k60 ); + } + + L_frame_for_cs = L_FRAME16k; + move16(); + } + + /*----------------------------------------------------------------* + * Excitation decoding + *----------------------------------------------------------------*/ + + decod_gen_voic_core_switch_fx( st_fx, L_frame_for_cs, 0, Aq, GENERIC, exc, cbrate, &st_fx->Q_exc ); + + /*----------------------------------------------------------------* + * synthesis, deemphasis, postprocessing and resampling + *----------------------------------------------------------------*/ + + /* Core synthesis at 12.8kHz or 16kHz */ + Rescale_mem( st_fx->Q_exc, &st_fx->prev_Q_syn, &st_fx->Q_syn, st_fx->mem_syn2_fx, st_fx->mem_syn_clas_estim_fx, + 4, &st_fx->mem_deemph_fx, st_fx->pst_old_syn_fx, &st_fx->pst_mem_deemp_err_fx,&st_fx->agc_mem_fx[1], &st_fx->pfstat , 1, 0, NULL ); + + syn_12k8_fx( 2*L_SUBFR, Aq, exc, synth_intFreq, st_fx->mem_syn2_fx, 1, st_fx->Q_exc, st_fx->Q_syn ); + + IF(st_fx->pfstat.on && (EQ_16(st_fx->last_bwidth_fx,NB))) + { + Word16 tmp_noise, pitch_buf_tmp[2]; + tmp_noise = 0; + FOR( i=0; i<2; i++ ) + { + pitch_buf_tmp[i] = L_SUBFR; + move16(); + } + nb_post_filt( 2*L_SUBFR, &(st_fx->pfstat), &tmp_noise, 0, synth_intFreq, Aq, pitch_buf_tmp, AUDIO, st_fx->BER_detect, 0 ); + } + + IF( EQ_16(L_frame_for_cs,L_FRAME)) + { + deemph_fx( synth_intFreq, PREEMPH_FAC, 2*L_SUBFR, &(st_fx->mem_deemph_fx) ); + } + ELSE + { + deemph_fx( synth_intFreq, PREEMPH_FAC_16k, 2*L_SUBFR, &(st_fx->mem_deemph_fx) ); + } + + unscale_AGC( synth_intFreq, st_fx->Q_syn, syn_fx_tmp+M, st_fx->agc_mem_fx, 2*L_SUBFR ); + Copy( syn_fx_tmp+M, synth_intFreq, 2*L_SUBFR ); + + test(); + IF( st_fx->pfstat.on && (NE_16(st_fx->last_bwidth_fx,NB))) + { + Copy( st_fx->pfstat.mem_pf_in+L_SYN_MEM-M, bpf_error_signal, M ); + Copy( synth_intFreq, bpf_error_signal + M, L_SUBFR ); + Residu3_fx ( Aq, bpf_error_signal + M, exc, L_SUBFR, 1 ); + E_UTIL_synthesis ( 1, Aq, exc, bpf_error_signal, L_SUBFR, st_fx->pfstat.mem_stp+L_SYN_MEM-M, 0, M ); + scale_st ( synth_intFreq, bpf_error_signal, &st_fx->pfstat.gain_prec, L_SUBFR ); + Copy( bpf_error_signal, synth_intFreq, L_SUBFR/2 ); + blend_subfr2( bpf_error_signal + L_SUBFR/2, synth_intFreq + L_SUBFR/2, synth_intFreq + L_SUBFR/2 ); + } + st_fx->pfstat.on = 0; + move16(); + + IF ( st_fx->flag_cna != 0 ) + { + generate_masking_noise( synth_intFreq, st_fx->Q_syn, st_fx->hFdCngDec_fx->hFdCngCom, 2*L_SUBFR, 0); + } + + /*----------------------------------------------------------------* + * Resample to the output sampling rate (8/16/32/48 kHz) + * Bass post-filter + *----------------------------------------------------------------*/ + + bass_psfilter_fx( st_fx->Opt_AMR_WB_fx, synth_intFreq, 2*L_SUBFR, NULL, st_fx->pst_old_syn_fx, + &st_fx->pst_mem_deemp_err_fx, &st_fx->pst_lp_ener_fx, st_fx->bpf_off_fx, st_fx->stab_fac_fx, &st_fx->stab_fac_smooth_fx, + st_fx->mem_mean_pit_fx, st_fx->Track_on_hist_fx, st_fx->vibrato_hist_fx, &st_fx->psf_att_fx, GENERIC, + st_fx->Q_syn, bpf_error_signal ); + + cldfb_save_memory( st_fx->cldfbAna_fx ); + cldfbAnalysisFiltering( st_fx->cldfbAna_fx, realBuffer, imagBuffer, &scaleFactor, synth_intFreq, + negate(st_fx->Q_syn), CLDFB_NO_COL_MAX_SWITCH, workBuffer); + cldfb_restore_memory( st_fx->cldfbAna_fx ); + + /* CLDFB synthesis of the combined signal */ + scaleFactor.hb_scale = scaleFactor.lb_scale; + move16(); + + /* CLDFB analysis and add the BPF error signal */ + cldfb_save_memory( st_fx->cldfbBPF_fx ); + i = 0; + move16(); + if( st_fx->bpf_off_fx == 0 ) + { + i = CLDFB_NO_COL_MAX_SWITCH; + move16(); + } + addBassPostFilterFx( bpf_error_signal, realBuffer, imagBuffer, st_fx->cldfbBPF_fx, workBuffer, negate(st_fx->Q_syn), + i, CLDFB_NO_COL_MAX_SWITCH, st_fx->cldfbAna_fx->no_channels, &scaleFactor ); + cldfb_restore_memory( st_fx->cldfbBPF_fx ); + + /* CLDFB synthesis of the combined signal */ + scaleFactor.hb_scale = scaleFactor.lb_scale; + + cldfb_save_memory( st_fx->cldfbSyn_fx ); + cldfbSynthesisFiltering(st_fx->cldfbSyn_fx, realBuffer, imagBuffer, &scaleFactor, synth_subfr_out, 0, CLDFB_NO_COL_MAX_SWITCH, workBuffer); + cldfb_restore_memory( st_fx->cldfbSyn_fx ); + *Q_syn = 0; + move16(); + + Copy_Scale_sig( synth_intFreq+ NS2SA(L_frame_for_cs * 50, SWITCH_GAP_LENGTH_NS-DELAY_CLDFB_NS)-2, mem_synth, NS2SA(L_frame_for_cs * 50, DELAY_CLDFB_NS)+2, negate(st_fx->Q_syn) ); /* Copy mem with Q0 */ + + /*----------------------------------------------------------------* + * BWE decoding + *----------------------------------------------------------------*/ + + decode_bwe = 0; + move16(); + test(); + test(); + IF( !(( EQ_16(inner_frame_tbl[st_fx->bwidth_fx], L_FRAME16k)&&EQ_16(st_fx->last_L_frame_fx,L_FRAME16k))||EQ_16(inner_frame_tbl[st_fx->bwidth_fx],L_FRAME8k))) + { + /* Decoding of BWE */ + d1m = (Word16)get_next_indice_fx(st_fx, AUDIODELAYBITS); + ind1 = (Word16)get_next_indice_fx(st_fx, NOOFGAINBITS1); + gain = usdequant_fx( ind1, MINVALUEOFFIRSTGAIN_FX, shr(DELTAOFFIRSTGAIN_FX,3) ); /*Q13*/ + decode_bwe = 1; + move16(); + } + + test(); + test(); + test(); + IF( decode_bwe && !(( EQ_16(output_frame, L_FRAME16k)&&EQ_16(st_fx->last_L_frame_fx,L_FRAME16k))||EQ_16(output_frame,L_FRAME8k))) + { + set16_fx( tmp_mem2, 0, 2*L_FILT48k ); + + hp_filter = hp16000_48000_fx; + fdelay = 48; + move16(); + IF ( EQ_32(st_fx->output_Fs_fx, 16000)) + { + IF( EQ_16(st_fx->last_L_frame_fx, L_FRAME)) + { + hp_filter = hp12800_16000_fx; + fdelay = 20; + move16(); + } + } + ELSE IF( EQ_32(st_fx->output_Fs_fx, 32000)) + { + IF( EQ_16(st_fx->last_L_frame_fx, L_FRAME)) + { + hp_filter = hp12800_32000_fx; + fdelay = 40; + move16(); + } + ELSE + { + hp_filter = hp16000_32000_fx; + fdelay = 32; + move16(); + } + } + ELSE IF( EQ_16(st_fx->last_L_frame_fx, L_FRAME)) + { + hp_filter = hp12800_48000_fx; + fdelay = 60; + move16(); + } + + /* safety check in case of bit errors */ + i = MAX_D1M_16k; + move16(); + if( EQ_16(st_fx->last_L_frame_fx,L_FRAME)) + { + i = MAX_D1M_12k8; + move16(); + } + + IF( GE_16(d1m,i)) + { + d1m = sub(i,1); + gain = 0; /* force muting */ move16(); + st_fx->BER_detect = 1; + move16(); + } + + i = NS2SA_fx2(st_fx->output_Fs_fx, FRAME_SIZE_NS-ACELP_LOOK_NS-DELAY_BWE_TOTAL_NS); + move16(); + Copy( st_fx->old_synth_sw_fx, hb_synth_tmp, i ); + set16_fx( hb_synth_tmp + i, 0, NS2SA_fx2(st_fx->output_Fs_fx, 10000000L) - i ); + fir_fx( hb_synth_tmp, hp_filter, hb_synth_tmp, tmp_mem2, shr(output_frame,1), fdelay, 1, 0 ); + + set16_fx( tmp_synth_bwe, 0, SWITCH_MAX_GAP ); + + gapsize = i_mult2(delta, (NS2SA(16000,SWITCH_GAP_LENGTH_NS))); + + pt1 = tmp_synth_bwe; + tmp = add(i_mult(d1m,delta),fdelay); + pt2 = &hb_synth_tmp[tmp]; + FOR( i=0; iHQ switching frame in case of BAD frame +*-------------------------------------------------------------------*/ + +void acelp_core_switch_dec_bfi_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 synth_out[], /* o : synthesis Q_syn */ + const Word16 coder_type /* i : coder type */ +) +{ + Word16 old_exc[L_EXC_DEC], *exc; /* excitation signal buffer */ + Word16 syn[L_FRAME16k]; /* synthesis signal buffer */ + Word16 lsf_new[M]; /* LSFs at the end of the frame */ + Word16 lsp_new[M]; /* LSPs at the end of the frame */ + Word16 Aq[NB_SUBFR16k*(M+1)]; /* A(q) quantized for the 4 subframes */ + Word16 old_exc2[L_FRAME16k + L_EXC_MEM], *exc2; /* total excitation buffer */ + Word16 tmp_noise; /* Long term temporary noise energy */ + Word16 FEC_pitch; /* FEC pitch */ + Word16 old_bwe_exc[((PIT16k_MAX + (L_FRAME16k+1) + L_SUBFR16k) * 2)]; /* excitation buffer */ + Word16 *bwe_exc; /* Excitation for SWB TBE */ + Word16 tmp_float[NBPSF_PIT_MAX]; + Word16 tmp_float2[M]; + Word16 tmp_float3; + Word16 tmp_float4[L_TRACK_HIST]; + Word16 tmp_float5[L_TRACK_HIST]; + Word16 tmp_float6[L_TRACK_HIST]; + Word16 tmp_float7; + Word32 tmp_float32; + Word16 voice_factors[NB_SUBFR16k]; + Word16 pitch_buf[NB_SUBFR16k]; + Word16 Q_exc; + Word32 *realBuffer[CLDFB_NO_COL_MAX_SWITCH_BFI], *imagBuffer[CLDFB_NO_COL_MAX_SWITCH_BFI]; + Word32 realBufferTmp[CLDFB_NO_COL_MAX_SWITCH_BFI][CLDFB_NO_CHANNELS_MAX], imagBufferTmp[CLDFB_NO_COL_MAX_SWITCH_BFI][CLDFB_NO_CHANNELS_MAX]; + Word16 i; + CLDFB_SCALE_FACTOR scaleFactor; + Word32 workBuffer[128*3]; + + FOR( i=0; iQ_exc; + move16(); + st_fx->bpf_off_fx = 1; + move16(); + st_fx->clas_dec = st_fx->last_good_fx; + move16(); + tmp_noise = 0; + move16(); + + Copy( st_fx->old_exc_fx, old_exc, L_EXC_MEM_DEC ); + exc = old_exc + L_EXC_MEM_DEC; + Copy( st_fx->old_exc2_fx, old_exc2, L_EXC_MEM ); + exc2 = old_exc2 + L_EXC_MEM; + Copy( st_fx->old_bwe_exc_fx, old_bwe_exc, PIT16k_MAX * 2); + bwe_exc = old_bwe_exc + PIT16k_MAX * 2; + st_fx->GSC_noisy_speech_fx = 0; + move16(); + st_fx->relax_prev_lsf_interp_fx = 0; + move16(); + + /* SC-VBR */ + if( EQ_16(st_fx->last_nelp_mode_dec_fx, 1)) + { + st_fx->nelp_mode_dec_fx = 1; + move16(); + } + + Copy(st_fx->mem_AR_fx,tmp_float,M); + Copy(st_fx->mem_MA_fx,tmp_float2,M); + + /* LSF estimation and A(z) calculation */ + lsf_dec_bfi( MODE1, lsf_new, st_fx->lsf_old_fx, st_fx->lsf_adaptive_mean_fx, NULL, st_fx->mem_MA_fx, st_fx->mem_AR_fx, + st_fx->stab_fac_fx, st_fx->last_coder_type_fx, st_fx->L_frame_fx, st_fx->last_good_fx, + st_fx->nbLostCmpt, 0, NULL, NULL, NULL, st_fx->Last_GSC_pit_band_idx_fx, st_fx->Opt_AMR_WB_fx, 0, st_fx->bwidth_fx); + + FEC_lsf2lsp_interp( st_fx, st_fx->L_frame_fx, Aq, lsf_new, lsp_new); + + Copy( tmp_float, st_fx->mem_AR_fx, M ); + Copy( tmp_float2, st_fx->mem_MA_fx, M ); + + /*----------------------------------------------------------------* + * Excitation decoding + *----------------------------------------------------------------*/ + + IF( EQ_16(st_fx->nelp_mode_dec_fx, 1)) + { + Word16 gain_buf[NB_SUBFR16k]; + Scale_sig(exc-L_EXC_MEM, L_EXC_MEM, -st_fx->Q_exc); + st_fx->Q_exc = 0; + /* SC-VBR */ + decod_nelp_fx( st_fx, coder_type, &tmp_noise, pitch_buf, exc, exc2, voice_factors, bwe_exc, &Q_exc, st_fx->bfi_fx, gain_buf ); + FEC_pitch = pitch_buf[3]; + move16(); + Rescale_exc( st_fx->dct_post_old_exc_fx, exc, NULL, st_fx->last_exc_dct_in_fx, L_FRAME, 0, (Word32)0, &Q_exc, st_fx->Q_subfr, exc2, L_FRAME, coder_type); + st_fx->Q_exc = Q_exc; + } + ELSE + { + tmp_float[0] = st_fx->bfi_pitch_fx; + move16(); + tmp_float[1] = st_fx->bfi_pitch_frame_fx; + move16(); + tmp_float[2] = st_fx->lp_gainp_fx; + move16(); + tmp_float[3] = st_fx->lp_gainc_fx; + move16(); + tmp_float[4] = st_fx->upd_cnt_fx; + move16(); + tmp_float[5] = st_fx->seed_fx; + move16(); + + /* calculation of excitation signal */ + FEC_exc_estim_fx( st_fx, st_fx->L_frame_fx, exc, exc2, syn /* dummy buffer */, pitch_buf, voice_factors, &FEC_pitch, bwe_exc, lsf_new, &Q_exc, &tmp_noise ); + Rescale_exc( NULL, exc, bwe_exc, st_fx->last_exc_dct_in_fx, st_fx->L_frame_fx, L_FRAME32k, (Word32)0, + &Q_exc, st_fx->Q_subfr, exc2, st_fx->L_frame_fx, st_fx->last_coder_type_fx); + st_fx->seed_fx = tmp_float[5]; + move16(); + st_fx->bfi_pitch_fx = tmp_float[0]; + move16(); + st_fx->bfi_pitch_frame_fx = tmp_float[1]; + move16(); + st_fx->lp_gainp_fx = tmp_float[2]; + move16(); + st_fx->lp_gainc_fx = tmp_float[3]; + move16(); + st_fx->upd_cnt_fx = tmp_float[4]; + move16(); + } + + /*------------------------------------------------------------------* + * Synthesis + *-----------------------------------------------------------------*/ + + Rescale_mem( Q_exc, &st_fx->prev_Q_syn, &st_fx->Q_syn, st_fx->mem_syn2_fx, st_fx->mem_syn_clas_estim_fx, 4, &st_fx->mem_deemph_fx, + st_fx->pst_old_syn_fx, &st_fx->pst_mem_deemp_err_fx, &st_fx->agc_mem_fx[1], &st_fx->pfstat, 1, 0, NULL ); + Copy( st_fx->mem_syn2_fx,tmp_float,M); + syn_12k8_fx( st_fx->L_frame_fx, Aq, exc2, syn, tmp_float, 1, Q_exc, st_fx->Q_syn ); + + tmp_float32 = st_fx->enr_old_fx; + frame_ener_fx( st_fx->L_frame_fx, st_fx->last_good_fx, syn, shr(add(FEC_pitch,32),6), &tmp_float32, st_fx->L_frame_fx, st_fx->Q_syn, 3, 0 ); + + /*------------------------------------------------------------------* + * Perform fixed deemphasis through 1/(1 - g*z^-1) + *-----------------------------------------------------------------*/ + tmp_float[0] = st_fx->mem_deemph_fx; + move16(); /*if in acelp_core_dec_fx deemph_fx is used*/ + /*tmp_float = shr(st_fx->mem_deemph_fx, sub(st_fx->Q_syn,1)); if in acelp_core_dec_fx Deemph2 is used*/ + + IF(EQ_16(st_fx->L_frame_fx,L_FRAME )) + { + deemph_fx( syn, PREEMPH_FAC, L_FRAME, &tmp_float[0] ); /*Q0*/ + } + ELSE + { + deemph_fx( syn, PREEMPH_FAC_16k, L_FRAME16k, &tmp_float[0] ); /*Q0*/ + } + + /*----------------------------------------------------------------* + * Bass post-filter + *----------------------------------------------------------------*/ + + st_fx->bpf_off_fx=1; + move16(); + Copy( st_fx->pst_old_syn_fx,tmp_float,NBPSF_PIT_MAX); + + tmp_float3 = st_fx->stab_fac_smooth_fx; + move16(); + Copy( st_fx->mem_mean_pit_fx,tmp_float4, L_TRACK_HIST); + Copy( st_fx->Track_on_hist_fx,tmp_float5, L_TRACK_HIST); + Copy( st_fx->vibrato_hist_fx,tmp_float6, L_TRACK_HIST); + tmp_float7 = st_fx->psf_att_fx; + move16(); + + bass_psfilter_fx( st_fx->Opt_AMR_WB_fx, syn, st_fx->L_frame_fx, pitch_buf, tmp_float, + &st_fx->pst_mem_deemp_err_fx, &st_fx->pst_lp_ener_fx, st_fx->bpf_off_fx, st_fx->stab_fac_fx, &tmp_float3, + tmp_float4, tmp_float5, tmp_float6, &tmp_float7, coder_type, st_fx->Q_syn, old_exc /* tmp buffer*/); + + /*----------------------------------------------------------------* + * Resamping to the output sampling frequency + *----------------------------------------------------------------*/ + /* CLDFB analysis of the synthesis at internal sampling rate */ + cldfb_save_memory( st_fx->cldfbAna_fx ); + cldfbAnalysisFiltering( st_fx->cldfbAna_fx, realBuffer, imagBuffer, &scaleFactor, syn, + negate(st_fx->Q_syn), CLDFB_NO_COL_MAX_SWITCH_BFI, workBuffer); + cldfb_restore_memory( st_fx->cldfbAna_fx ); + + scaleFactor.hb_scale = scaleFactor.lb_scale; + + /* CLDFB synthesis of the combined signal */ + cldfb_save_memory( st_fx->cldfbSyn_fx ); + cldfbSynthesisFiltering( st_fx->cldfbSyn_fx, realBuffer, imagBuffer, &scaleFactor, synth_out, + negate(st_fx->Q_syn), CLDFB_NO_COL_MAX_SWITCH_BFI, workBuffer ); + + /* output to Q0 */ + Scale_sig(synth_out,L_FRAME48k, negate(st_fx->Q_syn)); + + cldfb_restore_memory( st_fx->cldfbSyn_fx ); + + return; +} + + +/*-------------------------------------------------------------------* +* decod_gen_voic_core_switch() +* +* Decode excitation signal in teh first ACELP->HQ switching frame +*-------------------------------------------------------------------*/ + +static void decod_gen_voic_core_switch_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 sharpFlag, /* i : flag for formant sharpening */ + const Word16 *Aq, /* i : LP filter coefficient */ + const Word16 coder_type, /* i : coding type */ + Word16 *exc, /* i/o: adapt. excitation exc */ + const Word32 core_brate, /* i : switching frame bit-rate */ + Word16 *Q_exc +) +{ + Word16 T0, T0_frac, T0_min, T0_max;/* integer pitch variables */ + Word16 gain_pit,gain_code16; /* pitch gain */ + Word32 gain_code,L_tmp; /* gain/normalized gain of the algebraic excitation */ + Word32 norm_gain_code; /* normalized gain of the algebraic excitation */ + Word16 gain_inov; /* Innovation gain */ + Word16 voice_fac; /* voicing factor */ + Word16 code[L_SUBFR]; /* algebraic codevector */ + Word16 pitch; /* pointer to floating pitch */ + Word16 i; /* tmp variables */ + Word16 pitch_limit_flag; + Word16 *pt1; + + /*----------------------------------------------------------------------* + * initializations + *----------------------------------------------------------------------*/ + + IF( EQ_16(L_frame, L_FRAME)) + { + T0_max = PIT_MAX; + move16(); + T0_min = PIT_MIN; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + T0_max = PIT16k_MAX; + move16(); + T0_min = PIT16k_MIN; + move16(); + } + + /*----------------------------------------------------------------------* + * Decode pitch lag + *----------------------------------------------------------------------*/ + + pitch = pit_decode_fx( st_fx, core_brate, 0, L_frame, 0, coder_type, &pitch_limit_flag, &T0, &T0_frac, &T0_min, &T0_max, L_SUBFR ); /*Q6*/ + + /*--------------------------------------------------------------* + * Find the adaptive codebook vector. + *--------------------------------------------------------------*/ + + pred_lt4( &exc[0], &exc[0], T0, T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + /*--------------------------------------------------------------* + * LP filtering of the adaptive excitation + *--------------------------------------------------------------*/ + + lp_filt_exc_dec_fx( st_fx, MODE1, core_brate,0, coder_type, 0, L_SUBFR, L_frame, 0, exc); /*Scaling of exc doesn't change*/ + + /*--------------------------------------------------------------* + * Innovation decoding + *--------------------------------------------------------------*/ + + inov_decode_fx( st_fx, core_brate, 0, L_frame, coder_type, sharpFlag, 0, -1, Aq, st_fx->tilt_code_fx, pitch, code); /*code in Q9*/ + + /*--------------------------------------------------------------* + * Gain decoding + * Estimate spectrum tilt and voicing + *--------------------------------------------------------------*/ + + IF( EQ_16(L_frame, L_FRAME)) + { + gain_dec_mless_fx( st_fx, core_brate, L_frame, TRANSITION, 0, -1, code, st_fx->old_Es_pred_fx, &gain_pit, &gain_code, &gain_inov, &norm_gain_code ); + } + ELSE + { + gain_dec_mless_fx( st_fx, core_brate, L_frame, coder_type, 0, -1, code, st_fx->old_Es_pred_fx, &gain_pit, &gain_code, &gain_inov, &norm_gain_code ); + } + + /* _ (Word16*) gain_pit : quantized pitch gain (Q14) */ + /* _ (Word32*) gain_code : quantized codebook gain (Q16) */ + /* _ (Word16*) gain_inov : gain of the innovation (used for normalization) (Q12) */ + /* _ (Word32*) norm_gain_code : norm. gain of the codebook excitation (Q16) */ + st_fx->tilt_code_fx = est_tilt_fx( exc, gain_pit, code, gain_code, &voice_fac, *Q_exc ); /*Q15*/ + + /*----------------------------------------------------------------------* + * Find the total excitation + *----------------------------------------------------------------------*/ + + /* Rescaling for 12.8k core */ + IF ( EQ_16(L_frame,L_FRAME)) + { + Rescale_exc( NULL, &exc[0], NULL, st_fx->last_exc_dct_in_fx, L_SUBFR, L_SUBFR * HIBND_ACB_L_FAC, gain_code, &(st_fx->Q_exc), st_fx->Q_subfr, NULL, 0, GENERIC ); + } + /* Rescaling for 16k core */ + ELSE + { + Rescale_exc(NULL, &exc[0], NULL, st_fx->last_exc_dct_in_fx, L_SUBFR, L_SUBFR * 2, gain_code, &(st_fx->Q_exc), st_fx->Q_subfr, NULL, 0, GENERIC); + } + + gain_code16 = round_fx(L_shl(gain_code,st_fx->Q_exc)); /*Q_exc*/ + IF( st_fx->prev_bfi_fx ) + { + /*gain_code = min(gain_code, 0.5f*gain_code+0.5f*st->lp_gainc);*/ + gain_code16 = s_min(gain_code16, mac_r(L_mult(16384,gain_code16),shl(16384>>3, st_fx->Q_exc), st_fx->lp_gainc_fx)); /* st_fx->lp_gainc_fx in Q3 >>3 to bring it to Q0 as gain_code16 */ + } + + FOR (i = 0; i < L_SUBFR; i++) + { + L_tmp = L_shl(L_mult(gain_pit, exc[i]), 1); /*Q16+Q_exc*/ + /*exc2_fx[i+i_subfr] = round_fx(L_tmp);*/ /*Q_exc*/ + L_tmp = L_add(L_tmp, L_shl(L_mult(gain_code16, code[i]), 6)); /*Q16+Q_exc*/ + exc[i] = round_fx(L_tmp); /*Q_exc*/ + } + + /*-----------------------------------------------------------------* + * long term prediction on the 2nd sub frame + *-----------------------------------------------------------------*/ + + pred_lt4(&exc[L_SUBFR], &exc[L_SUBFR], T0, T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP); + pt1 = exc+L_SUBFR; + + FOR( i = 0; i < L_SUBFR; i++ ) + { + (*pt1) = round_fx(L_shl(L_mult(*pt1, gain_pit),1)); /*Q_exc + Q14 +1 +1 -16*/ + pt1++; + } + + return; +} diff --git a/lib_dec/amr_wb_dec_fx.c b/lib_dec/amr_wb_dec_fx.c new file mode 100644 index 0000000..41a14b1 --- /dev/null +++ b/lib_dec/amr_wb_dec_fx.c @@ -0,0 +1,1135 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "cnst_fx.h" +#include "rom_com_fx.h" +#include "prot_fx.h" +#include "stl.h" +#include "basop_mpy.h" +#include "basop_util.h" /* Function prototypes */ + +/*-------------------------------------------------------------------* + * amr_wb_dec() + * + * AMR-WB decoder + *-------------------------------------------------------------------*/ + +void amr_wb_dec_fx( + Word16 output_sp[], /* o : synthesis output */ + Decoder_State_fx *st_fx /* o : Decoder static variables structure */ +) +{ + Word16 i; + Word16 vad_flag; + Word16 coder_type; + Word16 output_frame; /* frame length at output sampling freq. */ + Word16 allow_cn_step; + Word16 locattack, amr_io_class; + Word16 tmps; + Word16 synth_out_fx[L_FRAME48k]; + + Word16 class_para_fx, hf_gain_fx[NB_SUBFR], voice_factors_fx[NB_SUBFR]; + Word16 delay_comp; + Word16 last_core_ori; + Word16 tmp_buffer_fx[L_FRAME48k]; + Word16 dct_buffer_fx[DCT_L_POST]; + Word16 frame_e_fx; + Word16 exc_buffer_fx[DCT_L_POST]; + Word16 lsp_new_fx[M]; /* LSPs at the end of the frame */ + Word16 lsf_new_fx[M]; /* LSFs at the end of the frame */ + Word16 xsp_tmp[M]; + Word16 Aq_fx[NB_SUBFR*(M+1)]; /* A(q) quantized for the 4 subframes */ + Word16 exc2_fx[L_FRAME]; /* total excitation buffer */ + Word16 mem_tmp_fx[M]; /* temporary synthesis filter memory */ + Word32 L_enr_q_fx; /* E information for FER protection */ + Word16 tmp_noise_fx; /* Long term temporary noise energy */ + Word16 FEC_pitch_fx; /* FEC pitch */ + Word16 dummy_buf_fx[L_FRAME32k]; /* dummy buffer - no usage */ + Word16 old_exc_fx[L_EXC_DEC], *exc_fx; /* excitation signal buffer */ + Word16 syn_tmp_fx[L_FRAME+2], *syn_fx; /* synthesis signal buffer */ + Word32 L_tmp, L_tmp1; + Word16 pitch_buf_fx[NB_SUBFR], Qdct, tmp_coder_type; /* floating pitch for each subframe (Q6) */ + Word16 tmp16; + Word16 sid_bw = 0; + Word32 L_Ng_ener; + Word16 exp2, ng_ener; + + Word16 bpf_error_signal[L_FRAME]; + CLDFB_SCALE_FACTOR scaleFactor; + Word32 workBuffer[128*3]; + Word32 q_env[20]; + Word16 exc3[L_FRAME]; + Word16 gain_buf[NB_SUBFR16k]; + + Word32 *realBuffer[CLDFB_NO_COL_MAX], *imagBuffer[CLDFB_NO_COL_MAX]; + Word32 realBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], imagBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word16 syn_fx_tmp2[L_FRAME]; + + Word16 pitch_buf_tmp[NB_SUBFR]; + Word16 update_flg; + Word8 flag_cna; + + Word8 waveadj_rec = 0; + + Word16 avoid_lpc_burst_on_recovery; + Word16 delta_mem_scale; + + /*------------------------------------------------------------------* + * Initialization + *------------------------------------------------------------------*/ + + syn_tmp_fx[0] = 0; + move16(); + syn_tmp_fx[1] = 0; + move16(); + syn_fx = syn_tmp_fx+2; + + FOR( i=0; iuse_partial_copy = 0; + move16(); + st_fx->rf_flag = 0; + move16(); + st_fx->rf_flag_last = 0; + move16(); + + st_fx->L_frame_fx = L_FRAME; + move16(); + st_fx->nb_subfr = NB_SUBFR; + move16(); + st_fx->core_fx = AMR_WB_CORE; + move16(); + st_fx->core_brate_fx = st_fx->total_brate_fx; + move16(); + st_fx->extl_fx = -1; + move16(); + st_fx->bwidth_fx = WB; + move16(); + coder_type = GENERIC; + move16(); + output_frame = st_fx->output_frame_fx; + move16(); /* frame length of the input signal */ + + st_fx->bpf_off_fx = 0; + move16(); + if( EQ_16(st_fx->last_core_fx,HQ_CORE)) + { + st_fx->bpf_off_fx = 1; + move16(); + st_fx->pfstat.on = 0; + move16(); + } + st_fx->igf = 0; + move16(); + + st_fx->sr_core = i_mult(st_fx->L_frame_fx,50); + st_fx->fscale_old = st_fx->fscale; + st_fx->fscale = sr2fscale(st_fx->sr_core); + + /* Initialization in case that the first frame is the good received AMR-WB (IO) frame */ + IF( st_fx->ini_frame_fx == 0 ) + { + st_fx->last_core_fx = AMR_WB_CORE; + move16(); + Copy( mean_isf_amr_wb_fx, st_fx->lsf_old_fx, M ); + E_LPC_isf_isp_conversion( st_fx->lsf_old_fx, st_fx->lsp_old_fx, M ); + } + + /* Updates in case of EVS primary mode -> AMR-WB IO mode switching */ + IF( NE_16(st_fx->last_core_fx,AMR_WB_CORE)) + { + updt_IO_switch_dec_fx( output_frame, st_fx ); + } + + /* Updates in case of EVS -> AMR-WB IO switching */ + core_switching_pre_dec_fx( st_fx, output_frame ); + + last_core_ori = st_fx->last_core_fx; + move16(); + set16_fx( hf_gain_fx, 0, NB_SUBFR); + + amr_io_class = UNVOICED_CLAS; + move16(); + L_enr_q_fx = L_deposit_l(0); + tmp_noise_fx = 0; + move16(); + + Copy( st_fx->old_exc_fx, old_exc_fx, L_EXC_MEM_DEC ); + exc_fx = old_exc_fx + L_EXC_MEM_DEC; + /* reset post-filter in case of switching */ + if( st_fx->pfstat.on == 0 ) + { + st_fx->pfstat.reset = 1; + move16(); + } + IF( st_fx->bfi_fx > 0 ) + { + st_fx->nbLostCmpt = add(st_fx->nbLostCmpt,1); + } + ELSE + { + st_fx->nbLostCmpt = 0; + move16(); + } + + /* PLC: [TCX: Fade-out-recovery] + * PLC: overlapping part needs to be attenuated for first good frame */ test(); + test(); + test(); + test(); + IF (!st_fx->bfi_fx + && st_fx->prev_bfi_fx + && (EQ_16(st_fx->last_codec_mode, MODE2) ) + && (EQ_16(st_fx->last_core_bfi, TCX_20_CORE) + || EQ_16(st_fx->last_core_bfi, TCX_10_CORE) )) + { + /* v_multc(st_fx->old_out_fx, st_fx->plcInfo.recovery_gain, */ + /* st_fx->old_out_fx, st_fx->L_frameTCX); */ + FOR( i = 0; i < st_fx->L_frameTCX; i++ ) + { + st_fx->old_out_fx[i] = shl(mult_r(st_fx->old_out_fx[i], st_fx->plcInfo.recovery_gain), 1); + } + } + + avoid_lpc_burst_on_recovery = 0; + move16(); + test(); + test(); + if (st_fx->last_con_tcx && (NE_16(st_fx->L_frameTCX_past, st_fx->L_frame_fx))&&(st_fx->last_core_fx!=0)) + { + avoid_lpc_burst_on_recovery = 1; + move16(); + } + + /*-----------------------------------------------------------------* + * switching from ACELP@16k core to AMR-WB IO mode + *-----------------------------------------------------------------*/ + st_fx->rate_switching_reset=0; + move16(); + test(); + test(); + IF( NE_16(st_fx->last_core_fx,AMR_WB_CORE)&&EQ_16(st_fx->last_L_frame_fx,L_FRAME16k)&&NE_16(st_fx->last_core_fx,HQ_CORE)) + { + /* in case of switching, do not apply BPF */ + st_fx->bpf_off_fx = 1; + move16(); + + if(st_fx->pfstat.on!=0) + { + Word16 mem_syn_r_size_old, mem_syn_r_size_new; + + mem_syn_r_size_old = shr(st_fx->last_L_frame_fx, 4); + mem_syn_r_size_new = shr(st_fx->L_frame_fx, 4); + lerp( st_fx->pfstat.mem_stp+L_SYN_MEM-mem_syn_r_size_old, st_fx->pfstat.mem_stp+L_SYN_MEM-mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old ); + lerp( st_fx->pfstat.mem_pf_in+L_SYN_MEM-mem_syn_r_size_old, st_fx->pfstat.mem_pf_in+L_SYN_MEM-mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old ); + } + + st_fx->rate_switching_reset=lsp_convert_poly_fx( st_fx->lsp_old_fx, L_FRAME, 1 ); + /* convert old quantized LSF vector */ + lsp2lsf_fx( st_fx->lsp_old_fx, st_fx->lsf_old_fx, M, INT_FS_FX ); + + /* FEC - update adaptive LSF mean vector */ + Copy( st_fx->lsf_old_fx, st_fx->lsfoldbfi1_fx, M ); + Copy( st_fx->lsf_old_fx, st_fx->lsfoldbfi0_fx, M ); + Copy( st_fx->lsf_old_fx, st_fx->lsf_adaptive_mean_fx, M ); + + /* Reset LPC mem */ + Copy( GEWB_Ave_fx, st_fx->mem_AR_fx, M ); + set16_fx( st_fx->mem_MA_fx,0, M ); + + /* update synthesis filter memories */ + synth_mem_updt2( L_FRAME, st_fx->last_L_frame_fx, st_fx->old_exc_fx, st_fx->mem_syn_r, st_fx->mem_syn2_fx, NULL, DEC ); + Copy( st_fx->old_exc_fx, old_exc_fx, L_EXC_MEM_DEC ); + Copy_Scale_sig(st_fx->mem_syn2_fx, st_fx->mem_syn1_fx, M, sub(-1,st_fx->Q_syn)); /*Q-1*/ + Copy( st_fx->mem_syn2_fx, st_fx->mem_syn3_fx, M ); + + /* LSP -> ISP */ + Copy( stable_ISP_fx, xsp_tmp, M ); + lsp2isp_fx( st_fx->lsp_old_fx, st_fx->lsp_old_fx, xsp_tmp, M ); + + } + + /* update buffer of old subframe pitch values */ + IF( NE_16(st_fx->last_L_frame_fx,L_FRAME)) + { + move16(); + IF( EQ_16(st_fx->last_L_frame_fx,L_FRAME32k)) + { + /* (float)12800/(float)32000; */ + tmp16 = 13107; + } + ELSE IF( EQ_16(st_fx->last_L_frame_fx,512)) + { + /* (float)12800/(float)25600; */ + tmp16 = 16384; + } + ELSE /* st->last_L_frame == L_FRAME16k */ + { + /* (float)12800/(float)16000; */ + tmp16 = 26214; + } + + FOR( i=NB_SUBFR16k-NB_SUBFR; iold_pitch_buf_fx[i-1] = Mpy_32_16_1(st_fx->old_pitch_buf_fx[i], tmp16); + move32(); + } + + FOR( i=2*NB_SUBFR16k-NB_SUBFR; i<2*NB_SUBFR16k; i++ ) + { + st_fx->old_pitch_buf_fx[i-2] = Mpy_32_16_1(st_fx->old_pitch_buf_fx[i], tmp16); + move32(); + } + } + + IF( NE_16(st_fx->bfi_pitch_frame_fx, L_FRAME)) + { + move16(); + IF( EQ_16(st_fx->bfi_pitch_frame_fx,L_FRAME32k)) + { + /* (float)12800/(float)32000; */ + tmp16 = 13107; + } + ELSE IF( EQ_16(st_fx->bfi_pitch_frame_fx,512)) + { + /* (float)12800/(float)25600; */ + tmp16 = 16384; + } + ELSE /* st->bfi_pitch_frame_fx == L_FRAME16k */ + { + /* (float)12800/(float)16000; */ + tmp16 = 26214; + } + st_fx->bfi_pitch_fx = mult_r(tmp16, st_fx->bfi_pitch_fx); + st_fx->bfi_pitch_frame_fx = L_FRAME; + move16(); + } + + IF( NE_16(st_fx->last_core_fx,AMR_WB_CORE)) + { + /* reset the unvoiced/audio signal improvement memories */ + E_LPC_f_isp_a_conversion( st_fx->lsp_old_fx, st_fx->old_Aq_fx, M ); + Copy( st_fx->old_Aq_fx, st_fx->old_Aq_fx + (M+1), M+1 ); + Copy( st_fx->old_Aq_fx, st_fx->old_Aq_fx + 2*(M+1), M+1 ); + Copy( st_fx->old_Aq_fx, st_fx->old_Aq_fx + 3*(M+1), M+1 ); + } + + test(); + if( EQ_16(st_fx->last_bwidth_fx,NB)&&st_fx->ini_frame_fx!=0) + { + st_fx->rate_switching_reset=1; + move16(); + } + + /*----------------------------------------------------------------------* + * GOOD frame + *----------------------------------------------------------------------*/ + + IF( !st_fx->bfi_fx ) + { + /*----------------------------------------------------------------* + * Processing of FRAME_NO_DATA frames + * Decoding of SID frames + *----------------------------------------------------------------*/ + + test(); + IF ( EQ_32(st_fx->core_brate_fx,FRAME_NO_DATA)||EQ_32(st_fx->core_brate_fx,SID_1k75)) + { + /* decode CNG parameters */ + CNG_dec_fx( st_fx, L_FRAME, Aq_fx, st_fx->core_brate_fx, lsp_new_fx, lsf_new_fx, &allow_cn_step, &sid_bw, q_env ); + + /* comfort noise generation */ + CNG_exc_fx( st_fx->core_brate_fx, L_FRAME, &st_fx->Enew_fx, &st_fx->cng_seed_fx, exc_fx, exc2_fx, &st_fx->lp_ener_fx, st_fx->last_core_brate_fx, + &st_fx->first_CNG_fx, &st_fx->cng_ener_seed_fx, dummy_buf_fx, allow_cn_step, &st_fx->last_allow_cn_step_fx, st_fx->prev_Q_exc, st_fx->Q_exc , st_fx->num_ho_fx, + q_env, st_fx->lp_env_fx, st_fx->old_env_fx, st_fx->exc_mem_fx, st_fx->exc_mem1_fx, &sid_bw, &st_fx->cng_ener_seed1_fx, exc3, st_fx->Opt_AMR_WB_fx ); + + set16_fx( voice_factors_fx, 32767, NB_SUBFR ); + class_para_fx = 0; + move16(); + + if( st_fx->first_CNG_fx == 0 ) + { + st_fx->first_CNG_fx = 1; + move16(); + } + + + delta_mem_scale = 3; + move16(); + test(); + if( LT_32(st_fx->lp_ener_fx,40)) /* very low energy frames, less than 0.3125 */ + { + delta_mem_scale = 0; + move16(); + } + + i = st_fx->Q_exc; + Rescale_exc( st_fx->dct_post_old_exc_fx, exc_fx, NULL, st_fx->last_exc_dct_in_fx, st_fx->L_frame_fx, + st_fx->L_frame_fx* HIBND_ACB_L_FAC, 0, &(st_fx->Q_exc), st_fx->Q_subfr, NULL, 0, INACTIVE); + + Rescale_mem( st_fx->Q_exc, &st_fx->prev_Q_syn, &st_fx->Q_syn, st_fx->mem_syn2_fx, st_fx->mem_syn_clas_estim_fx, delta_mem_scale, + &st_fx->mem_deemph_fx, st_fx->pst_old_syn_fx,&st_fx->pst_mem_deemp_err_fx, &st_fx->agc_mem_fx[1], &st_fx->pfstat, 0, 0, NULL ); + Copy_Scale_sig(exc2_fx, exc2_fx, st_fx->L_frame_fx, sub(st_fx->Q_exc, i)); + + /* update past excitation signals for LD music post-filter */ + Copy( st_fx->dct_post_old_exc_fx + L_FRAME, st_fx->dct_post_old_exc_fx, DCT_L_POST-L_FRAME-OFFSET2 ); + Copy( exc2_fx, st_fx->dct_post_old_exc_fx + (DCT_L_POST-L_FRAME-OFFSET2), L_FRAME ); + + /* synthesis at 12k8 Hz sampling rate */ + syn_12k8_fx( L_FRAME, Aq_fx, exc2_fx, syn_fx, st_fx->mem_syn2_fx, 1, st_fx->Q_exc, st_fx->Q_syn ); + syn_12k8_fx( L_FRAME, Aq_fx, exc2_fx, dummy_buf_fx, st_fx->mem_syn3_fx, 1, st_fx->Q_exc, st_fx->Q_syn ); + + /* reset the decoder */ + CNG_reset_dec_fx( st_fx, pitch_buf_fx, dummy_buf_fx+L_FRAME ); + + /* update st_fx->mem_syn1 for ACELP core switching */ + Copy_Scale_sig( st_fx->mem_syn3_fx, st_fx->mem_syn1_fx, M, sub(-1,st_fx->Q_syn) ); /*Q-1*/ + IF( NE_16(output_frame,L_FRAME8k)) + { + Word16 pitch_temp[4]; + pitch_temp[2] = shl(L_FRAME, 6); + move16(); + pitch_temp[3] = shl(L_FRAME, 6); + move16(); + frame_energy_fx( L_FRAME, pitch_temp, syn_fx, 0, &frame_e_fx, st_fx->Q_syn ); + /*st->psf_lp_noise = 0.99f * st->psf_lp_noise + 0.01f * frame_e; */ + st_fx->psf_lp_noise_fx = round_fx(L_mac(L_mult(32440, st_fx->psf_lp_noise_fx), 328, frame_e_fx)); /*Q8*/ + } + /* update old synthesis for classification */ + Copy( syn_fx + L_FRAME - L_SYN_MEM_CLAS_ESTIM, st_fx->mem_syn_clas_estim_fx, L_SYN_MEM_CLAS_ESTIM ); + + /* Update music post processing values */ + /* Filter energies update */ + FOR( i = 0; i < DCT_L_POST; i++ ) + { + /*st->filt_lfE[i] = 0.3f + 0.7f * st->filt_lfE[i];*/ + st_fx->filt_lfE_fx[i] = round_fx(L_mac(L_deposit_h(1229), 22938, st_fx->filt_lfE_fx[i])); + } + + vad_flag = 0; + move16(); + } + + /*----------------------------------------------------------------* + * Decoding of all other frames + *----------------------------------------------------------------*/ + + ELSE + { + /*-----------------------------------------------------------------* + * After CNG period, use the most up-to-date ISPs + *-----------------------------------------------------------------*/ + + test(); + IF ( EQ_32(st_fx->last_core_brate_fx,FRAME_NO_DATA)||EQ_32(st_fx->last_core_brate_fx,SID_1k75)) + { + Copy( st_fx->lspCNG_fx, st_fx->lsp_old_fx, M ); + E_LPC_isp_isf_conversion( st_fx->lspCNG_fx, st_fx->lsf_old_fx, M ); + set16_fx( old_exc_fx, 0, L_EXC_MEM_DEC ); + } + + /*------------------------------------------------------------* + * Extracts VAD information from the bitstream in AMR-WB IO mode + *------------------------------------------------------------*/ + + vad_flag = (Word16)get_next_indice_fx( st_fx, 1 ); + + coder_type = GENERIC; + move16(); + if ( vad_flag == 0 ) + { + coder_type = INACTIVE; + move16(); + } + + /*-----------------------------------------------------------------* + * ISF de-quantization and interpolation + *-----------------------------------------------------------------*/ + + isf_dec_amr_wb_fx( st_fx, Aq_fx, lsf_new_fx, lsp_new_fx ); + + /*------------------------------------------------------------* + * Decode excitation + *------------------------------------------------------------*/ + + decod_amr_wb_fx( st_fx, Aq_fx, pitch_buf_fx, exc_fx, exc2_fx, hf_gain_fx, voice_factors_fx, gain_buf ); + + /* synthesis for ACELP core switching and SWB BWE */ + syn_12k8_fx( L_FRAME, Aq_fx, exc_fx, tmp_buffer_fx, st_fx->mem_syn1_fx, 1, st_fx->Q_exc, -1 ); + + /*------------------------------------------------------------* + * Update long-term energies for FEC + * Update ISP vector for CNG + *------------------------------------------------------------*/ + + IF( EQ_16(coder_type,INACTIVE)) + { + IF( GT_16(st_fx->unv_cnt_fx,20)) + { + /*ftmp = st->lp_gainc * st->lp_gainc;*/ + L_tmp1 = L_mult0(st_fx->lp_gainc_fx, st_fx->lp_gainc_fx); /* Q3*Q3 -> Q6*/ + /*st->lp_ener = 0.7f * st->lp_ener + 0.3f * ftmp;*/ + L_tmp = Mult_32_16(st_fx->lp_ener_fx, 22938); + st_fx->lp_ener_fx = L_add(L_tmp, Mult_32_16(L_tmp1, 9830)); /*Q6 + Q6*/ + FOR( i=0; ilspCNG_fx[i] = round_fx(L_mac(L_tmp, 29491, st_fx->lspCNG_fx[i])); + } + } + ELSE + { + st_fx->unv_cnt_fx = add(st_fx->unv_cnt_fx,1); + } + } + ELSE + { + st_fx->unv_cnt_fx = 0; + move16(); + } + + /*------------------------------------------------------------* + * Save filter memory in case the synthesis is redone after scaling + * Core synthesis at 12k8 Hz + *------------------------------------------------------------*/ + + /* add extra headroom in case a CNA addition is likely (i.e. st_fx->psf_lp_noise_fx is close to the threshold) */ + tmp16 = 0; + move16(); + test(); + test(); + if(EQ_16(coder_type,INACTIVE)&&st_fx->flag_cna&&GE_16(st_fx->psf_lp_noise_fx,15<<7)) + { + tmp16 = 1; + move16(); + } + Rescale_mem( st_fx->Q_exc, &st_fx->prev_Q_syn, &st_fx->Q_syn, st_fx->mem_syn2_fx, st_fx->mem_syn_clas_estim_fx, 5, &st_fx->mem_deemph_fx, + st_fx->pst_old_syn_fx, &st_fx->pst_mem_deemp_err_fx, &st_fx->agc_mem_fx[1], &st_fx->pfstat, vad_flag, tmp16, tmp_buffer_fx ); + Copy( st_fx->mem_syn2_fx, mem_tmp_fx, M ); + syn_12k8_fx( L_FRAME, Aq_fx, exc2_fx, syn_fx, st_fx->mem_syn2_fx, 1, st_fx->Q_exc, st_fx->Q_syn ); + + /*------------------------------------------------------------* + * FEC - Estimate the classification information + *------------------------------------------------------------*/ + + FEC_clas_estim_fx( st_fx, 1, L_FRAME, &st_fx->clas_dec, coder_type, pitch_buf_fx, + syn_fx, &st_fx->lp_ener_FER_fx, + &st_fx->decision_hyst_fx, &st_fx->UV_cnt_fx, &st_fx->LT_UV_cnt_fx, &st_fx->Last_ener_fx, &locattack, st_fx->lt_diff_etot_fx, + &amr_io_class, st_fx->core_brate_fx, st_fx->Q_syn, &class_para_fx, st_fx->mem_syn_clas_estim_fx, &st_fx->classifier_Q_mem_syn, + 0, 0, 0, st_fx->last_core_brate_fx ); + + /* update past excitation signals for LD music post-filter */ + Copy( st_fx->dct_post_old_exc_fx + L_FRAME, st_fx->dct_post_old_exc_fx, DCT_L_POST-L_FRAME-OFFSET2 ); + Copy( exc2_fx, st_fx->dct_post_old_exc_fx + (DCT_L_POST-L_FRAME-OFFSET2), L_FRAME ); + Copy( st_fx->dct_post_old_exc_fx, exc_buffer_fx, DCT_L_POST-OFFSET2 ); + + IF( NE_16(output_frame,L_FRAME8k)) + { + IF ( EQ_16(coder_type,INACTIVE)) + { + frame_energy_fx( L_FRAME, pitch_buf_fx, syn_fx, 0, &frame_e_fx, st_fx->Q_syn ); + /*st->psf_lp_noise = 0.99f * st->psf_lp_noise + 0.01f * frame_e; */ + st_fx->psf_lp_noise_fx = round_fx(L_mac(L_mult(32440, st_fx->psf_lp_noise_fx), 328, frame_e_fx)); /*Q8*/ + } + } + + test(); + test(); + IF( NE_16(amr_io_class,UNVOICED_CLAS)&&NE_16(coder_type,INACTIVE)&<_16(st_fx->psf_lp_noise_fx,15<<8)) + { + tmp_coder_type = AUDIO; + move16(); + test(); + if (EQ_16(st_fx->last_coder_type_fx,INACTIVE)||EQ_16(st_fx->last_coder_type_fx,UNVOICED)) + { + tmp_coder_type = INACTIVE; + move16(); + } + /* Extrapolation of the last future part, windowing and high resolution DCT transform */ + Prep_music_postP_fx( exc_buffer_fx, dct_buffer_fx, st_fx->filt_lfE_fx, st_fx->last_core_fx, pitch_buf_fx, st_fx->LDm_enh_lp_gbin_fx, st_fx->Q_exc, &Qdct ); + + /* LD music post-filter */ + LD_music_post_filter_fx( dct_buffer_fx, dct_buffer_fx, st_fx->core_brate_fx, &st_fx->LDm_last_music_flag_fx, + st_fx->LDm_thres_fx, &st_fx->LDm_nb_thr_1_fx, &st_fx->LDm_nb_thr_3_fx, st_fx->LDm_lt_diff_etot_fx, + &st_fx->LDm_mem_etot_fx, st_fx->LDm_enh_min_ns_gain_fx, st_fx->LDm_bckr_noise_fx, + st_fx->LDm_enh_lf_EO_fx, st_fx->LDm_enh_lp_gbin_fx, st_fx->filt_lfE_fx, &st_fx->last_nonfull_music_fx, + &st_fx->Old_ener_Q, -1, tmp_coder_type, Qdct ); + + /* Inverse DCT transform, retrieval of the aligned excitation, re-synthesis */ + Post_music_postP_fx( dct_buffer_fx, exc2_fx, mem_tmp_fx, st_fx->mem_syn2_fx, Aq_fx, syn_fx, &st_fx->Q_exc, &st_fx->prev_Q_syn, + &st_fx->Q_syn, st_fx->mem_syn_clas_estim_fx, 1, &st_fx->mem_deemph_fx, st_fx->pst_old_syn_fx, + &st_fx->pst_mem_deemp_err_fx, &st_fx->agc_mem_fx[1], &st_fx->pfstat, NULL, NULL ); + } + ELSE + { + /*------------------------------------------------------------* + * Improvement for unvoiced and audio signals + *------------------------------------------------------------*/ + + improv_amr_wb_gs_fx( amr_io_class, coder_type, st_fx->core_brate_fx, &st_fx->seed_tcx_fx, st_fx->old_Aq_fx, st_fx->mem_syn2_fx, st_fx->lt_voice_fac_fx, + locattack, Aq_fx, exc2_fx, st_fx->Q_exc, mem_tmp_fx, syn_fx, st_fx->Q_syn, pitch_buf_fx, st_fx->Last_ener_fx, st_fx->rate_switching_reset, st_fx->last_coder_type_fx ); + + FOR( i = 0; i < DCT_L_POST; i++ ) + { + /*st->filt_lfE[i] = 0.3f + 0.7f * st->filt_lfE[i] ;*/ + st_fx->filt_lfE_fx[i] = round_fx(L_mac(L_deposit_h(1229), 22938, st_fx->filt_lfE_fx[i])); + } + } + + /*------------------------------------------------------------* + * FEC - Estimate pitch + *------------------------------------------------------------*/ + + FEC_pitch_estim_fx( 1, st_fx->last_core_fx, L_FRAME, st_fx->clas_dec, st_fx->last_good_fx, pitch_buf_fx, st_fx->old_pitch_buf_fx, &st_fx->bfi_pitch_fx, + &st_fx->bfi_pitch_frame_fx, &st_fx->upd_cnt_fx, GENERIC ); + + /*------------------------------------------------------------* + * FEC - Smooth the speech energy evolution when recovering after a BAD frame + * (smoothing is performed in the excitation domain and signal is resynthesized after) + *------------------------------------------------------------*/ + + FOR( i=0; iclas_dec, st_fx->last_good_fx, syn_fx, pitch_buf_tmp, st_fx->enr_old_fx, L_enr_q_fx, -1, MOVING_AVERAGE, + &st_fx->scaling_flag, &st_fx->lp_ener_FEC_av, &st_fx->lp_ener_FEC_max, st_fx->bfi_fx, st_fx->total_brate_fx, st_fx->prev_bfi_fx, st_fx->last_core_brate_fx, + exc_fx, exc2_fx, Aq_fx, &st_fx->old_enr_LP, mem_tmp_fx, st_fx->mem_syn2_fx, st_fx->Q_exc, st_fx->Q_syn, avoid_lpc_burst_on_recovery, 0 ); + + frame_ener_fx( L_FRAME, st_fx->clas_dec, syn_fx, pitch_buf_tmp[3], &st_fx->enr_old_fx, L_FRAME, st_fx->Q_syn, 3, 0 ); + } + + } /* End of GOOD FRAME */ + + /*----------------------------------------------------------------* + * BAD frame + *----------------------------------------------------------------*/ + ELSE + { + /* long burst frame erasures */ + test(); + if( GT_16(st_fx->nbLostCmpt,5)&&GE_16(st_fx->clas_dec,VOICED_CLAS)) + { + st_fx->last_good_fx = VOICED_TRANSITION; + move16(); + } + vad_flag = st_fx->last_vad_fx; + move16(); + amr_io_class = st_fx->last_good_fx; + move16(); + class_para_fx = 0; + move16(); + + /* LSF estimation and A(z) calculation */ + lsf_dec_bfi( MODE1, lsf_new_fx, st_fx->lsf_old_fx, st_fx->lsf_adaptive_mean_fx, NULL, st_fx->mem_MA_fx, st_fx->mem_AR_fx, + st_fx->stab_fac_fx, st_fx->last_coder_type_fx, st_fx->L_frame_fx, st_fx->last_good_fx, + st_fx->nbLostCmpt, 0, NULL, NULL, NULL, st_fx->Last_GSC_pit_band_idx_fx, st_fx->Opt_AMR_WB_fx, 0, st_fx->bwidth_fx); + + FEC_lsf2lsp_interp( st_fx, st_fx->L_frame_fx, Aq_fx, lsf_new_fx, lsp_new_fx ); + /* calculation of excitation signal */ + FEC_exc_estim_fx( st_fx, L_FRAME, exc_fx, exc2_fx, tmp_buffer_fx, pitch_buf_fx, voice_factors_fx, + &FEC_pitch_fx, dummy_buf_fx, lsf_new_fx, &st_fx->Q_exc, &tmp_noise_fx); + + /* synthesis for ACELP core switching and SWB BWE */ + syn_12k8_fx( L_FRAME, Aq_fx, exc_fx, tmp_buffer_fx, st_fx->mem_syn1_fx, 1, st_fx->Q_exc, -1 ); + + /* update past excitation signals */ + Copy( st_fx->dct_post_old_exc_fx + L_FRAME, st_fx->dct_post_old_exc_fx, DCT_L_POST-L_FRAME-OFFSET2 ); + Copy( exc2_fx, st_fx->dct_post_old_exc_fx + (DCT_L_POST-L_FRAME-OFFSET2), L_FRAME ); + + /* Update music post processing values */ + /* Update circular buffer, keep last energy difference unchanged */ + FOR( i = 1; iLDm_lt_diff_etot_fx[i-1] = st_fx->LDm_lt_diff_etot_fx[i]; + move16(); + } + /* Filter energies update */ + FOR( i = 0; i < DCT_L_POST; i++ ) + { + /*st->filt_lfE[i] = 0.3f + 0.7f * st->filt_lfE[i];*/ + st_fx->filt_lfE_fx[i] = round_fx(L_mac(L_deposit_h(1229), 22938, st_fx->filt_lfE_fx[i])); + } + + Rescale_mem( st_fx->Q_exc, &st_fx->prev_Q_syn, &st_fx->Q_syn, st_fx->mem_syn2_fx, st_fx->mem_syn_clas_estim_fx, 4, &st_fx->mem_deemph_fx, + st_fx->pst_old_syn_fx, &st_fx->pst_mem_deemp_err_fx, &st_fx->agc_mem_fx[1], &st_fx->pfstat, 1, 0, tmp_buffer_fx ); + + Copy( st_fx->mem_syn2_fx, mem_tmp_fx, M ); + /* synthesis at 12k8 Hz sampling rate */ + syn_12k8_fx( L_FRAME, Aq_fx, exc2_fx, syn_fx, st_fx->mem_syn2_fx, 1 , st_fx->Q_exc, st_fx->Q_syn ); + + /* update old synthesis for classification */ + Copy( syn_fx + L_FRAME - L_SYN_MEM_CLAS_ESTIM, st_fx->mem_syn_clas_estim_fx, L_SYN_MEM_CLAS_ESTIM ); + + + FOR( i=0; iclas_dec, st_fx->last_good_fx, syn_fx, pitch_buf_tmp, st_fx->enr_old_fx, L_enr_q_fx, -1, + MOVING_AVERAGE, &st_fx->scaling_flag, &st_fx->lp_ener_FEC_av, &st_fx->lp_ener_FEC_max, st_fx->bfi_fx, st_fx->total_brate_fx, + st_fx->prev_bfi_fx, st_fx->last_core_brate_fx, exc_fx, exc2_fx, Aq_fx, &st_fx->old_enr_LP, mem_tmp_fx, st_fx->mem_syn2_fx, + st_fx->Q_exc, st_fx->Q_syn, 0, 0 ); + + /* estimate the pitch-synchronous speech energy per sample to be used when normal operation recovers */ + frame_ener_fx( L_FRAME, st_fx->last_good_fx, syn_fx, shr(FEC_pitch_fx, 6), &st_fx->enr_old_fx, L_FRAME, st_fx->Q_syn, 3, 0 ); + } + + /*--------------------------------------------------------* + * NB post-filter + *--------------------------------------------------------*/ + test(); + IF( EQ_16(output_frame,L_FRAME8k)||EQ_16(st_fx->last_bwidth_fx,NB)) + { + FOR( i=0; ipfstat.on = 1; + move16(); + nb_post_filt( L_FRAME, &(st_fx->pfstat), &st_fx->psf_lp_noise_fx, tmp_noise_fx, syn_fx, Aq_fx, pitch_buf_tmp, coder_type, st_fx->BER_detect, 0 ); + } + ELSE + { + st_fx->pfstat.on = 0; + move16(); + nb_post_filt( L_FRAME, &(st_fx->pfstat), &st_fx->psf_lp_noise_fx, tmp_noise_fx, syn_fx, Aq_fx, pitch_buf_tmp, AUDIO, st_fx->BER_detect, 0 ); + } + } + + /*------------------------------------------------------------------* + * Perform fixed deemphasis through 1/(1 - g*z^-1) + *-----------------------------------------------------------------*/ + + /* update old synthesis buffer - needed for ACELP internal sampling rate switching */ + Copy( syn_fx + L_FRAME - L_SYN_MEM, st_fx->mem_syn_r, L_SYN_MEM ); + + deemph_fx( syn_fx, PREEMPH_FAC, L_FRAME, &(st_fx->mem_deemph_fx) ); + + unscale_AGC( syn_fx, st_fx->Q_syn, syn_fx_tmp2, st_fx->agc_mem_fx, L_FRAME ); + Copy( syn_fx_tmp2, syn_fx, L_FRAME ); + + /* TCX=Q-1, ACELP2 Q0 */ + Copy_Scale_sig( syn_fx + L_FRAME/2, st_fx->old_syn_Overl, L_FRAME/2, sub(-1,st_fx->Q_syn)); /*Q_syn*/ + Copy_Scale_sig( syn_fx + L_FRAME-M-1, st_fx->syn, M+1, sub(0,st_fx->Q_syn)); /*Q0*/ + + /*------------------------------------------------------------------* + * Formant post-filter + *-----------------------------------------------------------------*/ + + Copy( syn_fx, tmp_buffer_fx + L_SYN_MEM, L_FRAME ); + IF( NE_16(output_frame,L_FRAME8k)&&NE_16(st_fx->last_bwidth_fx,NB)) + { + st_fx->pfstat.on = 1; + move16(); + test(); + formant_post_filt( &(st_fx->pfstat), tmp_buffer_fx + L_SYN_MEM, Aq_fx, syn_fx, L_FRAME, L_shl(st_fx->psf_lp_noise_fx,15), st_fx->total_brate_fx, sub(amr_io_class,AUDIO_CLAS) == 0); + } + + /*----------------------------------------------------------------* + * Comfort Noise Addition + *----------------------------------------------------------------*/ + + flag_cna = 0; + move16(); + test(); + IF( (GE_16(st_fx->psf_lp_noise_fx,15<<8))||(coder_type==INACTIVE)) + { + /*VAD only for non inactive frame*/ + test(); + IF( EQ_16(st_fx->VAD, 1)&&NE_16(coder_type,INACTIVE)) + { + st_fx->VAD = 1; + move16(); + } + ELSE + { + st_fx->VAD = 0; + move16(); + } + ApplyFdCng( syn_fx, st_fx->Q_syn, NULL, NULL, 0, st_fx->hFdCngDec_fx, st_fx->m_frame_type, st_fx, 0, 0 ); + + st_fx->hFdCngDec_fx->hFdCngCom->frame_type_previous = st_fx->m_frame_type; + + /*Noisy speech detector*/ + noisy_speech_detection( st_fx->VAD, syn_fx, L_FRAME, st_fx->Q_syn, st_fx->hFdCngDec_fx->msNoiseEst, st_fx->hFdCngDec_fx->msNoiseEst_exp, + st_fx->hFdCngDec_fx->psize_shaping_norm, st_fx->hFdCngDec_fx->psize_shaping_norm_exp, st_fx->hFdCngDec_fx->nFFTpart_shaping, + &(st_fx->hFdCngDec_fx->lp_noise), &(st_fx->hFdCngDec_fx->lp_speech), &(st_fx->hFdCngDec_fx->hFdCngCom->flag_noisy_speech) ); + + st_fx->hFdCngDec_fx->hFdCngCom->likelihood_noisy_speech = mult_r(st_fx->hFdCngDec_fx->hFdCngCom->likelihood_noisy_speech, 32440/*0.99 Q15*/); + IF ( st_fx->hFdCngDec_fx->hFdCngCom->flag_noisy_speech != 0 ) + { + st_fx->hFdCngDec_fx->hFdCngCom->likelihood_noisy_speech = add(st_fx->hFdCngDec_fx->hFdCngCom->likelihood_noisy_speech, 328/*0.01 Q15*/); + move16(); + } + st_fx->lp_noise = st_fx->hFdCngDec_fx->lp_noise; + move16(); + + test(); + IF( st_fx->flag_cna && GE_16(st_fx->psf_lp_noise_fx,15<<8)) + { + flag_cna = 1; + move16(); + generate_masking_noise( syn_fx, st_fx->Q_syn, st_fx->hFdCngDec_fx->hFdCngCom, st_fx->hFdCngDec_fx->hFdCngCom->frameSize, AMR_WB_CORE ); + } + ELSE IF ( st_fx->flag_cna ) + { + generate_masking_noise_update_seed( st_fx->hFdCngDec_fx->hFdCngCom ); + } + + /*Copy(syn+L_FRAME-M-1, st_fx->syn, M+1);*/ + } + ELSE IF ( st_fx->flag_cna ) + { + generate_masking_noise_update_seed( st_fx->hFdCngDec_fx->hFdCngCom ); + } + + + IF( flag_cna == 0 ) + { + test(); + test(); + test(); + IF( EQ_16(st_fx->last_flag_cna,1)&&((EQ_16(st_fx->last_core_fx,ACELP_CORE)&&NE_16(st_fx->last_coder_type_fx,AUDIO))||EQ_16(st_fx->last_core_fx,AMR_WB_CORE))) + { + FOR (i=0; i < L_FRAME/2; i++) + { + syn_fx[i] = add( syn_fx[i], shr_r( st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth2[i+5*L_FRAME/4], -st_fx->Q_syn ) ); + move16(); + } + } + set16_fx( st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth2, 0, shl(L_FRAME,1) ); + } + + /*----------------------------------------------------------------* + * Change the sampling frequency to 8/16/32 kHz + * Bass post-filter + *----------------------------------------------------------------*/ + + /* check if the CLDFB works on the right sample rate */ + IF( (st_fx->cldfbAna_fx->usb * st_fx->cldfbAna_fx->no_col) != L_FRAME ) + { + /* resample to ACELP internal sampling rate */ + Word16 newCldfbBands = CLDFB_getNumChannels(INT_FS_FX); + + resampleCldfb( st_fx->cldfbAna_fx, newCldfbBands, L_FRAME, 0 ); + resampleCldfb( st_fx->cldfbBPF_fx, newCldfbBands, L_FRAME, 0 ); + + if( st_fx->ini_frame_fx > 0 ) + { + st_fx->cldfbSyn_fx->bandsToZero = sub(st_fx->cldfbSyn_fx->no_channels,st_fx->cldfbAna_fx->no_channels); + } + } + + bass_psfilter_fx( st_fx->Opt_AMR_WB_fx, syn_fx, L_FRAME, pitch_buf_fx, st_fx->pst_old_syn_fx, + &st_fx->pst_mem_deemp_err_fx, &st_fx->pst_lp_ener_fx, st_fx->bpf_off_fx, st_fx->stab_fac_fx, &st_fx->stab_fac_smooth_fx, + st_fx->mem_mean_pit_fx, st_fx->Track_on_hist_fx, st_fx->vibrato_hist_fx, &st_fx->psf_att_fx, GENERIC, st_fx->Q_syn, bpf_error_signal); + + cldfbAnalysisFiltering( st_fx->cldfbAna_fx, realBuffer, imagBuffer, &scaleFactor, syn_fx, + negate(st_fx->Q_syn), CLDFB_NO_COL_MAX, workBuffer ); + + scaleFactor.hb_scale = scaleFactor.lb_scale; + move16(); + + /* CLDFB analysis and add the BPF error signal */ + i = 0; + move16(); + if( st_fx->bpf_off_fx == 0 ) + { + i = CLDFB_NO_COL_MAX; + move16(); + } + addBassPostFilterFx( bpf_error_signal, realBuffer, imagBuffer, st_fx->cldfbBPF_fx, workBuffer, negate(st_fx->Q_syn), + i, st_fx->cldfbAna_fx->no_col, st_fx->cldfbAna_fx->no_channels, &scaleFactor ); + st_fx->Q_syn2 = st_fx->Q_syn; + move16(); + + if( NE_16(st_fx->cldfbSyn_fx->bandsToZero,sub(st_fx->cldfbSyn_fx->no_channels,st_fx->cldfbAna_fx->no_channels))) + { + /* in case of BW switching, re-init to default */ + st_fx->cldfbSyn_fx->bandsToZero = sub(st_fx->cldfbSyn_fx->no_channels, st_fx->cldfbAna_fx->no_channels); + } + cldfb_synth_set_bandsToZero( st_fx, realBuffer, imagBuffer, CLDFB_NO_COL_MAX, scaleFactor ); + /* CLDFB synthesis of the combined signal */ + cldfbSynthesisFiltering( st_fx->cldfbSyn_fx, realBuffer, imagBuffer, &scaleFactor, synth_out_fx, negate(st_fx->Q_syn2), CLDFB_NO_COL_MAX, workBuffer ); + + /* Bring CLDFB output to Q-1 */ + Scale_sig( synth_out_fx, output_frame, negate(st_fx->Q_syn2) ); + st_fx->Q_syn2 = 0; + move16(); + + /* save synthesis - needed in case of core switching */ + Copy( synth_out_fx, st_fx->previoussynth_fx, output_frame ); + st_fx->Q_syn2 = 0; + move16(); + + /*--------------------------------------------------------* + * calculate the average frame energy + *--------------------------------------------------------*/ + frame_ener_fx( L_FRAME, st_fx->clas_dec, syn_fx, mult_r(pitch_buf_fx[3],512), &L_Ng_ener, L_FRAME, st_fx->Q_syn, 3, 0 ); + /*--------------------------------------------------------* + * optimized for NO_S@-26dBov with street noise @ SNR=25dB + *--------------------------------------------------------*/ + + /* ng_ener = 10.0f * (float)log10(ng_ener + 0.01f) - 90.3087f + 15; */ + L_Ng_ener = L_max(1, L_Ng_ener); + tmp16 = norm_l(L_Ng_ener); + exp2 = Log2_norm_lc(L_shl(L_Ng_ener, tmp16)); + tmp16 = sub(30, tmp16); + ng_ener = mac_r(L_shl(L_mac(-1233858L, tmp16, 24660), 8+2), exp2, 771); + /* st_fx->ng_ener_ST = 0.7f * st_fx->ng_ener_ST + 0.3f * ng_ener; */ + st_fx->Ng_ener_ST_fx = mac_r(L_mult(st_fx->Ng_ener_ST_fx, 22938), ng_ener, 9830); + move16(); + + /*-----------------------------------------------------------------* + * Bandwidth extension 6kHz-8kHz + *-----------------------------------------------------------------*/ + + test(); + test(); + IF( GE_16(output_frame,L_FRAME16k)&&(NE_16(st_fx->cldfbSyn_fx->bandsToZero,sub(st_fx->cldfbSyn_fx->no_channels,10))||NE_16(st_fx->last_flag_filter_NB,1))) + { + hf_synth_amr_wb_fx( st_fx->core_brate_fx, output_frame, Aq_fx, exc2_fx, syn_fx, st_fx->mem_syn_hf_fx, + st_fx->delay_syn_hf_fx, &st_fx->prev_r_fx, &st_fx->fmerit_w_sm_fx, &amr_io_class, st_fx->mem_hp_interp_fx, synth_out_fx, + class_para_fx, hf_gain_fx, voice_factors_fx, pitch_buf_fx, st_fx->Ng_ener_ST_fx, lsf_new_fx, + &st_fx->frame_count_fx, &st_fx->ne_min_fx, &st_fx->fmerit_m_sm_fx, &st_fx->voice_fac_amr_wb_hf, &st_fx->unvoicing_fx, &st_fx->unvoicing_sm_fx, + &st_fx->unvoicing_flag_fx, &st_fx->voicing_flag_fx, &st_fx->start_band_old_fx, &st_fx->OptCrit_old_fx, st_fx->Q_exc, st_fx->Q_syn2 ); + } + ELSE + { + hf_synth_amr_wb_reset_fx( &st_fx->seed2_fx, st_fx->mem_syn_hf_fx, st_fx->mem_hp_interp_fx, + &st_fx->prev_r_fx, &st_fx->fmerit_w_sm_fx, st_fx->delay_syn_hf_fx, &st_fx->frame_count_fx, + &st_fx->ne_min_fx, &st_fx->fmerit_m_sm_fx, &st_fx->voice_fac_amr_wb_hf, + &st_fx->unvoicing_fx, &st_fx->unvoicing_sm_fx, &st_fx->unvoicing_flag_fx, + &st_fx->voicing_flag_fx, &st_fx->start_band_old_fx, &st_fx->OptCrit_old_fx ); + } + + /*----------------------------------------------------------------------* + * Updates + *----------------------------------------------------------------------*/ + + updt_dec_fx( st_fx, L_FRAME, coder_type, old_exc_fx, pitch_buf_fx, 0, Aq_fx , lsf_new_fx, lsp_new_fx, voice_factors_fx, dummy_buf_fx, gain_buf ); + + /* update old_Aq[] - needed in improv_amr_wb_gs_fx() */ + Copy( Aq_fx, st_fx->old_Aq_fx, NB_SUBFR * (M+1) ); + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + if (!st_fx->bfi_fx + && st_fx->prev_bfi_fx + && GE_32(st_fx->last_total_brate_fx, HQ_48k) + && EQ_16(st_fx->last_codec_mode, MODE2) + && (EQ_16(st_fx->last_core_bfi, TCX_20_CORE) || EQ_16(st_fx->last_core_bfi, TCX_10_CORE) ) + && st_fx->plcInfo.concealment_method == TCX_NONTONAL + && LT_32(st_fx->plcInfo.nbLostCmpt, 4) ) + { + waveadj_rec = 1; + move16(); + } + + /* update main codec parameters */ + st_fx->last_core_fx = st_fx->core_fx; + move16(); + st_fx->last_extl_fx = -1; + move16(); + st_fx->last_codec_mode = st_fx->codec_mode; + move16(); + st_fx->last_L_frame_fx = L_FRAME; + move16(); + st_fx->last_core_brate_fx = st_fx->core_brate_fx; + move16(); + st_fx->last_codec_mode = st_fx->codec_mode; + move16(); + st_fx->last_bwidth_fx = WB; + move16(); + st_fx->last_total_brate_ber_fx = st_fx->total_brate_fx; + move32(); + st_fx->prev_Q_exc = st_fx->Q_exc; + move16(); + if ( !st_fx->bfi_fx ) + { + st_fx->last_total_brate_fx = st_fx->total_brate_fx; + move32(); + st_fx->last_good_fx = st_fx->clas_dec; + move16(); + } + st_fx->last_vad_fx = vad_flag; + move16(); + st_fx->last_flag_cna = flag_cna; + move16(); + + /*----------------------------------------------------------------* + * Overlap of ACELP synthesis with old MDCT memory + *----------------------------------------------------------------*/ + + if( st_fx->bfi_fx ) + { + /* calculate another loss frame to fill gap in case of switching frame loss */ + acelp_core_switch_dec_bfi_fx( st_fx, st_fx->fer_samples_fx, coder_type ); + } + + delay_comp = NS2SA_fx2(st_fx->output_Fs_fx, DELAY_CLDFB_NS); + Scale_sig(st_fx->delay_buf_out_fx, delay_comp, sub(st_fx->Q_syn2,st_fx->Q_old_postdec)); + st_fx->Q_old_postdec=st_fx->Q_syn2; + move16(); + IF( EQ_16(last_core_ori,HQ_CORE)) + { + Word16 step, alpha,nz; + + Scale_sig(st_fx->old_out_fx, L_FRAME48k, sub(st_fx->Q_syn2,st_fx->Q_old_wtda)); + st_fx->Q_old_wtda=st_fx->Q_syn2; + move16(); + + Copy( st_fx->delay_buf_out_fx,synth_out_fx, delay_comp ); /* copy the HQ/ACELP delay synchroniation buffer at the beginning of ACELP frame */ + + i = 15; + move16(); + tmps = NS2SA_fx2(st_fx->output_Fs_fx, 6000000L); + nz = NS2SA_fx2(st_fx->output_Fs_fx, N_ZERO_MDCT_NS); + step = Inv16(tmps, &i); + step = shl(step, i); + alpha = 0; + move16(); + + test(); + IF( st_fx->prev_bfi_fx && st_fx->HqVoicing_fx ) + { + Copy_Scale_sig( st_fx->fer_samples_fx, &st_fx->old_out_fx[nz], tmps,negate(st_fx->Q_syn2)); + } + + FOR (i = 0; i < tmps; i++) + { + synth_out_fx[i+delay_comp] = msu_r(L_mult(synth_out_fx[i+delay_comp], alpha), st_fx->old_out_fx[i+nz], add(alpha, -32768)); + move16(); + alpha = add(alpha, step); + } + } + + st_fx->prev_bfi_fx = st_fx->bfi_fx; + st_fx->last_con_tcx = st_fx->con_tcx; + + if( GT_32(st_fx->core_brate_fx,SID_1k75)) + { + st_fx->last_active_brate_fx = st_fx->total_brate_fx; + move32(); + } + + test(); + IF( GT_32(st_fx->core_brate_fx,SID_1k75)&&st_fx->first_CNG_fx) + { + if( GE_16(st_fx->act_cnt_fx,BUF_DEC_RATE)) + { + st_fx->act_cnt_fx = 0; + move16(); + } + + st_fx->act_cnt_fx = add(st_fx->act_cnt_fx,1); + + test(); + if( EQ_16(st_fx->act_cnt_fx,BUF_DEC_RATE)&&st_fx->ho_hist_size_fx>0) + { + st_fx->ho_hist_size_fx = sub(st_fx->ho_hist_size_fx,1); + } + + st_fx->act_cnt2_fx = add(st_fx->act_cnt2_fx,1); + st_fx->act_cnt2_fx = s_min(st_fx->act_cnt2_fx,MIN_ACT_CNG_UPD); + } + st_fx->prev_bws_cnt_fx = 0; + st_fx->bws_cnt_fx = 0; + st_fx->bws_cnt1_fx = 0; + /*----------------------------------------------------------------* + * HP filtering + * Final synthesis output + *----------------------------------------------------------------*/ + + /* Delay ACELP synthesis by DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS delay */ + IF ( GE_16(output_frame,L_FRAME16k)) + { + tmps = NS2SA_fx2(st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS); + Scale_sig( st_fx->prev_synth_buffer_fx, tmps, sub(st_fx->Q_syn2, st_fx->Qprev_synth_buffer_fx) ); + + Copy( synth_out_fx, tmp_buffer_fx, output_frame ); + Copy( st_fx->prev_synth_buffer_fx, synth_out_fx, tmps ); + Copy( tmp_buffer_fx, synth_out_fx + tmps, output_frame - tmps ); + Copy( tmp_buffer_fx + output_frame - tmps, st_fx->prev_synth_buffer_fx, tmps ); + } + + if (waveadj_rec) + { + tmps = 0; + IF( GE_16(output_frame,L_FRAME16k)) + { + tmps = NS2SA_fx2(st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS); + } + + waveform_adj2_fix(st_fx->tonalMDCTconceal.secondLastPcmOut, + synth_out_fx+tmps, + st_fx->plcInfo.data_noise, + &st_fx->plcInfo.outx_new_n1_fx, + &st_fx->plcInfo.nsapp_gain_fx, + &st_fx->plcInfo.nsapp_gain_n_fx, + &st_fx->plcInfo.recovery_gain, + st_fx->plcInfo.step_concealgain_fx, + st_fx->plcInfo.Pitch_fx, + st_fx->plcInfo.FrameSize, + tmps, + add(extract_l(st_fx->plcInfo.nbLostCmpt), 1), + st_fx->bfi_fx); + } + + /* HP filter */ + Scale_sig32( st_fx->L_mem_hp_out_fx, 4, sub(st_fx->Q_syn2, st_fx->Qprev_synth_buffer_fx) ); + st_fx->Qprev_synth_buffer_fx = st_fx->Q_syn2; + hp20( synth_out_fx, 1/*stride*/, output_frame, st_fx->L_mem_hp_out_fx, L_mult0(output_frame, 50) ); + + /* save synthesis for core switching */ + Copy_Scale_sig( synth_out_fx+NS2SA_fx2( st_fx->output_Fs_fx,ACELP_LOOK_NS+DELAY_BWE_TOTAL_NS), st_fx->old_synth_sw_fx, NS2SA_fx2(st_fx->output_Fs_fx,FRAME_SIZE_NS-ACELP_LOOK_NS-DELAY_BWE_TOTAL_NS), sub(st_fx->Q_old_postdec, st_fx->Q_syn2) ); + + { + /* TCX-LTP Postfilter: used in AMR-WB IO to update memories and to avoid discontinuities when the past frame was TCX */ + Word16 delta = NS2SA_fx2( st_fx->output_Fs_fx, TCXLTP_DELAY_NS ); + Scale_sig(st_fx->tcxltp_mem_in, delta, sub(st_fx->Q_syn2, st_fx->Qprev_synth_buffer_fx)); + Scale_sig(st_fx->tcxltp_mem_out, output_frame, sub(st_fx->Q_syn2, st_fx->Qprev_synth_buffer_fx)); + tcx_ltp_post( st_fx->tcxltp, ACELP_CORE, output_frame, st_fx->L_frame_past, 0, synth_out_fx, NULL, + delta, 0, 0, 0, 0, &st_fx->tcxltp_pitch_int_post_prev, + &st_fx->tcxltp_pitch_fr_post_prev, &st_fx->tcxltp_gain_post_prev, + &st_fx->tcxltp_filt_idx_prev, st_fx->pit_res_max, + &st_fx->pit_res_max_past, + 0, 0, st_fx->tcxltp_mem_in, + st_fx->tcxltp_mem_out, st_fx->total_brate_fx ); + } + + /* final output of synthesis signal */ + syn_output_fx( st_fx->codec_mode, synth_out_fx, output_frame, output_sp, st_fx->Q_syn2 ); + + + return; +} diff --git a/lib_dec/ari_dec.c b/lib_dec/ari_dec.c new file mode 100644 index 0000000..c2c8259 --- /dev/null +++ b/lib_dec/ari_dec.c @@ -0,0 +1,533 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "assert.h" +#include "stl.h" +#include "basop_mpy.h" +#include "cnst_fx.h" +#include "rom_com_fx.h" +#include "prot_fx.h" + +/*--------------------------------------------------------------- + * Ari decode 14 bits routines + -------------------------------------------------------------*/ + +Word16 ari_decode_overflow(TastatDec *s) +{ + return L_sub(L_sub(s->high, 1), s->low) <= 0; +} + +/** + * \brief Start ArCo decoding + * + * \param[i/o] st + * \param[o] s + */ +void ari_start_decoding_14bits(Decoder_State_fx *st, TastatDec *s) +{ + Word32 val; + + val = L_and(L_deposit_l(get_next_indice_fx(st, cbitsnew)), 0xffffL); + + s->low = L_deposit_l(0); + s->high = ari_q4new+1; + move32(); + s->vobf = val; + move32(); +} + +Word16 ari_start_decoding_14bits_prm(const Word16 *ptr, Word16 bp, TastatDec *s) +{ + Word32 val; + Word16 i; + const Word16 *p; + + val = L_deposit_l(0); + + p = ptr+bp; + + FOR (i=0; ilow = L_deposit_l(0); + s->high = ari_q4new+1; + move32(); + s->vobf = val; + move32(); + + return add(bp,i); +} + +static Word16 ari_lookup_s17(Word32 cum, Word32 range, UWord16 const *cum_freq) +{ + Word32 tmp; + const UWord16 *p; + Word16 range_l, range_h; + + p = cum_freq; + + /* Note: For each indirect addressing p[i], we assume a tmp pointer init followed by a costfree reading the value */ + /* If the value multiplied by range is greater than cum, the pointer p is set to the tmp pointer */ + /* tmp_p = p+8; if (tmp_p[0]*range>cum) p = tmp_p; */ + + /* max value in p[x] is 16384 => 14 bits */ + range_l = extract_l(L_and(range,0x7FFF)); + range_h = extract_l(L_shr(range,15)); + + tmp = L_multi31x16_X2(range_h, range_l,p[8]); + if (GT_32(tmp,cum)) + { + p = p + 8; + } + + tmp = L_multi31x16_X2(range_h, range_l,p[4]); + if (GT_32(tmp,cum)) + { + p = p + 4; + } + + + tmp = L_multi31x16_X2(range_h, range_l,p[2]); + if (GT_32(tmp,cum)) + { + p = p + 2; + } + + tmp = L_multi31x16_X2(range_h, range_l,p[1]); + IF (GT_32(tmp,cum)) + { + p = p + 1; + + tmp = L_multi31x16_X2(range_h, range_l,p[1]); + test(); + if ( ((Word32)(&cum_freq[15] - p) == 0) && (GT_32(tmp,cum))) + { + p = p + 1; + } + } + + /* return extract_l(L_shr(L_sub((Word32)p,(Word32)cum_freq),1)); */ + L_sub(0,0); + L_shr(0,0); /* pointer subtraction */ + return extract_l(p - cum_freq); +} + +static Word16 ari_lookup_s27(Word32 cum, Word32 range, UWord16 const *cum_freq) +{ + Word32 tmp; + Word16 range_l, range_h; + Word16 il, ih, im; + + /* Note: For each indirect addressing p[i], we assume a tmp pointer init followed by a costfree reading the value */ + /* If the value multiplied by range is greater than cum, the pointer p is set to the tmp pointer */ + /* tmp_p = p+8; if (tmp_p[0]*range>cum) p = tmp_p; */ + + /* max value in p[x] is 16384 => 14 bits */ + range_l = extract_l(L_and(range,0x7FFF)); + range_h = extract_l(L_shr(range,15)); + + /* begin change when compared with ari_decode_14bits_s17_ext, + starting with line: tmp = L_multi31x16_X2(range_h, range_l, p[8]); */ + il = 0; + move16(); + ih = 27; + move16(); + + /* do a five step binary search, using the interval [il, ih) */ + im = 13; + move16(); /* (il + ih) >> 1 */ + tmp = L_multi31x16_X2(range_h, range_l, cum_freq[im]); + tmp = L_sub(tmp, cum); + if (tmp > 0) + { + il = im; + move16(); + } + if (tmp <= 0) + { + ih = im; + move16(); + } + + im = shr(add(il, ih), 1); + tmp = L_multi31x16_X2(range_h, range_l, cum_freq[im]); + tmp = L_sub(tmp, cum); + if (tmp > 0) + { + il = im; + move16(); + } + if (tmp <= 0) + { + ih = im; + move16(); + } + + im = shr(add(il, ih), 1); + tmp = L_multi31x16_X2(range_h, range_l, cum_freq[im]); + tmp = L_sub(tmp, cum); + if (tmp > 0) + { + il = im; + move16(); + } + if (tmp <= 0) + { + ih = im; + move16(); + } + + im = shr(add(il, ih), 1); + tmp = L_multi31x16_X2(range_h, range_l, cum_freq[im]); + tmp = L_sub(tmp, cum); + if (tmp > 0) + { + il = im; + move16(); + } + if (tmp <= 0) + { + ih = im; + move16(); + } + + IF (GT_16(sub(ih, il), 1)) /* if the interval has more than one symbol */ + { + /* here, only ih == il + 2 is possible, which means two symbols in the interval */ + im = add(il, 1); /* (il + ih) >> 1 */ + tmp = L_multi31x16_X2(range_h, range_l, cum_freq[im]); + tmp = L_sub(tmp, cum); + if (tmp > 0) + { + il = im; + move16(); + } + } + + return il; +} + +static Word16 ari_lookup_bit(Word32 cum, Word32 range, UWord16 const *cum_freq) +{ + Word16 symbol = 0; /* initialize just to avoid compiler warning */ + + (void)cum_freq; + + range = L_shl(range, 13); /* L_multi31x16_X2(range_h, range_l, 8192) */ + cum = L_sub(range, cum); + + if (cum > 0) + { + symbol = 1; + move16(); + } + if (cum <= 0) + { + symbol = 0; + move16(); + } + + return symbol; +} + +static Word16 ari_decode_14bits_ext( + Decoder_State_fx *st, + TastatDec *s, + UWord16 const *cum_freq, + Word16 (*lookup_fn)(Word32 cum, Word32 range, UWord16 const *cum_freq) +) +{ + Word32 cum; + Word16 symbol; + Word32 low; + Word32 high; + Word32 range; + Word32 value; + Word16 i; + + low = s->low; + move32(); + high = s->high; + move32(); + value = s->vobf; + move32(); + + range = L_sub(high, low); + + cum = L_add(L_shl(L_sub(value, low), stat_bitsnew), sub(shl(1,stat_bitsnew),1)); + if (cum < 0) + { + cum = 0x7fffffff; + } + + symbol = lookup_fn(cum, range, cum_freq); + + high = L_add(low,mul_sbc_14bits(range,cum_freq[symbol])); + low = L_add(low,mul_sbc_14bits(range,cum_freq[symbol+1])); + + FOR (i = 0; i < 0x7FFF; i++) + { + Word32 L_msb_diff, L_msb_low, L_msb_high; + + L_msb_high = L_shr(L_sub(high,1),14); + L_msb_low = L_shr(low,14); + L_msb_diff = L_sub(L_msb_high, L_msb_low); + IF (GE_32(L_msb_diff,2)) + { + BREAK; + } + assert (tab_ari_qnew[L_msb_high][L_msb_low] != 0x0CCC); + assert (tab_ari_qnew[L_msb_high][L_msb_low] != 0x0BBB); + low = L_msu(low,1,tab_ari_qnew[L_msb_high][L_msb_low]); + low = L_shl(low,1); + high = L_msu(high,1,tab_ari_qnew[L_msb_high][L_msb_low]); + high = L_shl(high,1); + value = L_msu(value,1,tab_ari_qnew[L_msb_high][L_msb_low]); + value = L_mac0(L_shl(value,1),1,get_next_indice_1_fx(st)); + } + + s->low = low; + move32(); + s->high = high; + move32(); + s->vobf = value; + move32(); + + return symbol; +} + + +/** + * \brief Only for 17 symbols with new extended Tables + */ +Word16 ari_decode_14bits_s17_ext(Decoder_State_fx *st, TastatDec *s, UWord16 const *cum_freq) +{ + return ari_decode_14bits_ext(st, s, cum_freq, ari_lookup_s17); +} + +/** + * \brief Only for 27 symbols with new extended Tables + */ +Word16 ari_decode_14bits_s27_ext(Decoder_State_fx *st, TastatDec *s, UWord16 const *cum_freq) +{ + return ari_decode_14bits_ext(st, s, cum_freq, ari_lookup_s27); +} + +/** + * \brief Only for decoding one bit with uniform probability: + * the equivalent cum_freq table used is {16384, 8192, 0} + */ +Word16 ari_decode_14bits_bit_ext(Decoder_State_fx *st, TastatDec *s) +{ + static const UWord16 cum_freq[3] = {16384, 8192, 0}; + return ari_decode_14bits_ext(st, s, cum_freq, ari_lookup_bit); +} + +static Word16 ari_lookup_pow(TastatDec *s, Word16 base) +{ + Word32 cum, range; + Word16 symbol; + Word16 range_h, range_l; + Word16 pows[12]; /* "base" to the power of 2, 4, 8,... 2^12 */ + Word16 lowlim, highlim, testval; + Word16 k; + + range = L_sub(s->high, s->low); + cum = L_add(L_shl(L_sub(s->vobf, s->low), stat_bitsnew), sub(shl(1,stat_bitsnew),1)); + + range_h = extract_l(L_shr(range,15)); + range_l = extract_l(L_and(range,0x7FFF)); + + symbol = 0; + move16(); + lowlim = shr(base, 1); + highlim = 16384; + move16(); + + /* search for the interval where "cum" fits */ + IF (GT_32(L_multi31x16_X2(range_h, range_l, lowlim), cum)) /* below pow-1 */ + { + pows[0] = base; + move16(); + testval = base; + move16(); + /* increase exponent until it is smaller than "cum" */ + FOR (k = 1; k < 12; k++) + { + highlim = testval; + move16(); + pows[k] = mult_r(pows[k-1], pows[k-1]); + move16(); + testval = mult_r(pows[k], base); + + IF (LE_32(L_multi31x16_X2(range_h, range_l, shr(testval, 1)), cum)) /* found! big range is [lowlim,testval], (now narrow it down) */ + { + lowlim = testval; + move16(); + k = sub(k, 1); + symbol = shl(1, k); + BREAK; + } + } + assert(k < 12); /* maximum 2^10-1*/ + + /* narrow the range down */ + FOR (k = sub(k, 2); k >= 0; k--) + { + testval = mult_r(highlim, pows[k+1]); + + IF (LE_32(L_multi31x16_X2(range_h, range_l, shr(testval, 1)), cum)) + { + lowlim = testval; + move16(); + symbol = sub(symbol, shl(1, k)); + } + ELSE + { + highlim = testval; + move16(); + } + } + + highlim = shr(highlim, 1); + lowlim = shr(lowlim, 1); + } + + s->high = L_add(s->low, mul_sbc_14bits(range, highlim)); + move32(); + s->low = L_add(s->low, mul_sbc_14bits(range, lowlim)); + move32(); + + return symbol; +} + +static Word16 ari_lookup_sign(TastatDec *s, Word16 base) +{ + Word32 cum, range; + Word16 symbol; + + (void)base; + + range = L_sub(s->high, s->low); + cum = L_sub(s->vobf, s->low); + range = L_shr(range, 1); + + IF (GT_32(range, cum)) + { + symbol = 1; + move16(); + s->high = L_add(s->low, range); + move32(); + } + ELSE + { + symbol = 0; + move16(); + s->low = L_add(s->low, range); + move32(); + } + + return symbol; +} + +static Word16 ari_decode_14bits_notbl( + Word16 *ptr, + Word16 bp, + Word16 bits, + Word16 *res, + TastatDec *s, + Word16 base, + Word16 (*lookup_fn)(TastatDec *s, Word16 base) +) +{ + Word16 symbol; + Word32 low, high, value; + + symbol = lookup_fn(s, base); + + low = L_add(s->low, 0); + high = L_add(s->high, 0); + value = L_add(s->vobf, 0); + + FOR (; bplow,low))&&(EQ_32(s->high,L_sub(high,1)))&&(EQ_32(s->vobf,value))))) + { + /* This should not happen except of bit errors. */ + s->high = 0; + move32(); + s->low = 0; + move32(); + *res = 0; + move16(); + return -1; + } + + s->low = low; + move32(); + s->high = high; + move32(); + s->vobf = value; + move32(); + + *res = symbol; + move16(); + + return bp; +} + +/*------------------------------------------------------------------------ + * Function: ari_decode_14bits_pow + * + * Decode a symbol which follows the exponential distribution. That is, + * symbols are in the following intervals + * + * p(x = 0) = 1 - exp(- 0.5 * base * 2) + * p(x = q>0) = exp(- (q-0.5)*base* 2) - exp(- (q+0.5)*base*2 ) + * + *-------------------------------------------------------------------------*/ +Word16 ari_decode_14bits_pow(Word16 *ptr, Word16 bp, Word16 bits, Word16 *res, TastatDec *s, Word16 base) +{ + return ari_decode_14bits_notbl(ptr, bp, bits, res, s, base, ari_lookup_pow); +} + +/*------------------------------------------------------------------------ + * Function: ari_decode_14bits_sign + * + * Decode a sign with equal probabilities. + *-------------------------------------------------------------------------*/ +Word16 ari_decode_14bits_sign(Word16 *ptr, Word16 bp, Word16 bits, Word16 *res, TastatDec *s) +{ + return ari_decode_14bits_notbl(ptr, bp, bits, res, s, 0, ari_lookup_sign); +} + diff --git a/lib_dec/ari_hm_dec.c b/lib_dec/ari_hm_dec.c new file mode 100644 index 0000000..e8889ba --- /dev/null +++ b/lib_dec/ari_hm_dec.c @@ -0,0 +1,152 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include +#include +#include "stl.h" +#include "cnst_fx.h" +#include "basop_util.h" +#include "rom_com_fx.h" +#include "prot_fx.h" + +Word16 +DecodeIndex( + Decoder_State_fx *st, + Word16 Bandwidth, + Word16 *PeriodicityIndex) +{ + test(); + IF ( (st->tcx_hm_LtpPitchLag > 0) && GT_16(st->tcxltp_gain, kLtpHmGainThr)) + { + Word16 LtpPitchIndex = sub(mult_r(st->tcx_hm_LtpPitchLag, 1 << (15-kLtpHmFractionalResolution)), 2); + + *PeriodicityIndex = kLtpHmFlag; + move16(); + *PeriodicityIndex = s_or(*PeriodicityIndex, get_next_indice_fx(st, NumRatioBits[Bandwidth][LtpPitchIndex])); + *PeriodicityIndex = add(*PeriodicityIndex, 1); + move16(); + *PeriodicityIndex = s_or(*PeriodicityIndex, shl(LtpPitchIndex, 9)); + move16(); + + return NumRatioBits[Bandwidth][LtpPitchIndex]; + } + ELSE + { + *PeriodicityIndex = get_next_indice_fx(st, 8); + move16(); + return 8; + } +} + +static Word16 tcx_hm_dequantize_gain( + Word16 coder_type, /* i : coder type Q0 */ + Word16 gain_idx, /* i: quantization index Q0 */ + Word16 *gain /* o: dequantized gain Q11 */ +) +{ + + assert(0 <= coder_type && coder_type <= 1); + + /* safety check in case of bit errors */ + test(); + IF(!(0 <= gain_idx && LT_16(gain_idx,(1 << kTcxHmNumGainBits)))) + { + *gain = 0; + return 1; + } + + *gain = qGains[coder_type][gain_idx]; + move16(); + + return 0; +} + +void tcx_hm_decode( + Word16 L_frame, /* i: number of spectral lines Q0 */ + Word32 env[], /* i/o: envelope shape Q16 */ + Word16 targetBits, /* i: target bit budget Q0 */ + Word16 coder_type, /* i: coder_type Q0 */ + Word16 prm_hm[], /* i: HM parameters Q0 */ + Word16 LtpPitchLag, /* i: LTP pitch lag or -1 if none Q0 */ + Word16 *hm_bits /* o: bit consumption Q0 */ +) +{ + Word16 NumTargetBits; + Word16 fract_res; + Word32 lag; + Word16 gain; + Word16 L_frame_m_256; + Word16 p[2*kTcxHmParabolaHalfWidth+1]; + + + + *hm_bits = 0; + move16(); + + L_frame_m_256 = sub(L_frame,256); + + test(); + IF( !(EQ_16(coder_type,VOICED)||EQ_16(coder_type,GENERIC))) + { + /* A bit error was encountered */ + *hm_bits = -1; + move16(); + return; + } + + NumTargetBits = CountIndexBits( (L_frame_m_256 >= 0), prm_hm[1] ); + + NumTargetBits = add(NumTargetBits,targetBits); + + if ( EQ_16(coder_type,VOICED)) + { + NumTargetBits = add(NumTargetBits,kTcxHmNumGainBits); + } + + *hm_bits = add(sub(NumTargetBits, targetBits), 1); + move16(); + + /* Convert the index to lag */ + UnmapIndex( + prm_hm[1], + (L_frame_m_256 >= 0), + LtpPitchLag, + (( LE_16(NumTargetBits,kSmallerLagsTargetBitsThreshold) ) || ( L_frame_m_256 < 0 )), + &fract_res, + &lag + ); + test(); + test(); + + /* Render the harmonic model */ + IF( tcx_hm_render( lag, fract_res, p ) ) + { + /* A bit error was encountered */ + *hm_bits = -1; + move16(); + return; + } + + /* Dequantize gain */ + IF( tcx_hm_dequantize_gain((Word16)EQ_16(coder_type,VOICED),prm_hm[2],&gain)) + { + /* A bit error was encountered */ + *hm_bits = -1; + return; + } + + tcx_hm_modify_envelope( + gain, + lag, + fract_res, + p, + env, + L_frame + ); + +} + diff --git a/lib_dec/arith_coder_dec.c b/lib_dec/arith_coder_dec.c new file mode 100644 index 0000000..ade2b83 --- /dev/null +++ b/lib_dec/arith_coder_dec.c @@ -0,0 +1,232 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include + +#include "options.h" +#include "cnst_fx.h" +#include "rom_com_fx.h" +#include "stl.h" +#include "prot_fx.h" + +/* Returns: number of bits consumed */ +static Word16 tcx_arith_decode( + Word16 L_frame, /* i: number of spectral lines Q0 */ + const Word16 envelope[], /* i: scaled envelope Q15-e */ + Word16 envelope_e, /* i: scaled envelope exponent Q0 */ + Word16 target_bits, /* i: target bit budget Q0 */ + Word16 prm[], /* i: bit-stream Q0 */ + Word32 q_spectrum[], /* o: scalar quantized spectrum Q31-e */ + Word16 *q_spectrum_e, /* o: spectrum exponent Q0 */ + Word16 *nf_seed /* o: noise filling seed Q0 */ +) +{ + Word16 bp, k, q, s; + TastatDec as; + Word16 exp_k; + Word16 tmp; + Word32 L_tmp, Q; + + bp = ari_start_decoding_14bits_prm(prm, 0, &as); + + tmp = sub(envelope_e, 1+15); + L_tmp = L_deposit_l(0); + FOR (k = 0; k < L_frame; k++) + { + IF( envelope[k] == 0 ) /* safety check in case of bit errors */ + { + set32_fx(q_spectrum, 0, L_frame); + return -1; + } + ELSE + { + exp_k = round_fx(expfp(envelope[k], tmp)); + } + /* decode line magnitude */ + bp = ari_decode_14bits_pow(prm, bp, target_bits, &q, &as, exp_k); + + if (q == 0) + { + q_spectrum[k] = L_deposit_l(0); + } + IF (q != 0) /* line is non-zero, decode sign */ + { + bp = ari_decode_14bits_sign(prm, bp, target_bits, &s, &as); + + L_tmp = L_macNs(L_tmp, q, k); + + Q = L_mult(q, -(1<<(30 - SPEC_EXP_DEC))); + if (s == 0) Q = L_mult(q, 1 << (30 - SPEC_EXP_DEC)); + q_spectrum[k] = Q; + move32(); + } + + IF (ari_decode_overflow(&as)) + { + if( LT_16(bp, target_bits)) /* safety check in case of bit errors */ + { + bp = -1; + move16(); + } + BREAK; /* no bits left, so exit loop */ + } + } + *q_spectrum_e = SPEC_EXP_DEC; + move16(); + + set32_fx(q_spectrum+k, 0, sub(L_frame, k)); + + /* noise filling seed */ + *nf_seed = extract_l(L_tmp); + + + return bp; +} + +void tcx_arith_decode_envelope( + Word32 q_spectrum[], /* o: quantised MDCT coefficients Q31-e */ + Word16 *q_spectrum_e, /* o: MDCT exponent Q0 */ + Word16 L_frame, /* i: frame or MDCT length Q0 */ + Word16 L_spec, /* i: length w/o BW limitation Q0 */ + Decoder_State_fx *st, + const Word16 A_ind[], /* i: quantised LPC coefficients Q12 */ + Word16 target_bits, /* i: number of available bits Q0 */ + Word16 prm[], /* i: bitstream parameters Q0 */ + Word8 use_hm, /* i: use HM in current frame? */ + Word16 prm_hm[], /* i: HM parameter area Q0 */ + Word16 tcxltp_pitch, /* i: TCX LTP pitch in FD, -1 if n/a Q0*/ + Word16 *arith_bits, /* o: bits used for ari. coding Q0 */ + Word16 *signaling_bits, /* o: bits used for signaling Q0 */ + Word16 *nf_seed /* o: noise filling seed Q0 */ + ,Word16 low_complexity /* i: low-complexity flag Q0 */ +) +{ + Word32 env[N_MAX_ARI]; /* unscaled envelope */ + Word16 *envelope; /* scaled envelope */ + Word16 envelope_e; + Word16 L_spec_core; + TCX_config *tcx_cfg; + Word16 gamma_w, gamma_uw; + Word16 hm_bits; + + test(); + test(); + IF( GT_16(L_spec,N_MAX_ARI)||GT_16(target_bits,(ACELP_13k20/50))||(target_bits<=0)) + { + /* this could happen in case of bit errors */ + st->BER_detect = 1; + move16(); + L_spec = N_MAX_ARI; + move16(); + *signaling_bits = 0; + move16(); + *arith_bits = 0; + move16(); + set32_fx( q_spectrum, 0, L_frame ); + + return; + } + + + tcx_cfg = &st->tcx_cfg; + *signaling_bits = 0; + move16(); + assert(st->enableTcxLpc); + gamma_w = 32767/*1.0f Q15*/; + move16(); + gamma_uw = st->inv_gamma; + move16(); + + tcx_arith_render_envelope( + A_ind, + L_frame, + L_spec, + tcx_cfg->preemph_fac, + gamma_w, + gamma_uw, + env + ); + + IF (use_hm != 0) + { + IF (prm_hm[0] != 0) + { + tcx_hm_decode( + L_spec, + env, + target_bits, + tcx_cfg->coder_type, + prm_hm, + tcxltp_pitch, + &hm_bits + ); + + IF (hm_bits < 0) + { + st->BER_detect = 1; + move16(); + *signaling_bits = 0; + move16(); + *arith_bits = 0; + move16(); + set32_fx( q_spectrum, 0, L_frame ); + return; + } + } + ELSE + { + hm_bits = 1; + move16(); + } + *signaling_bits = add(*signaling_bits, hm_bits); + move16(); + } + ELSE + { + prm_hm[0] = 0; /* just to be sure */ move16(); + } + + L_spec_core = L_spec; + move16(); + if (st->igf) + { + L_spec_core = s_min(L_spec_core, st->hIGFDec.infoIGFStartLine); + } + envelope = (Word16*)env; + + tcx_arith_scale_envelope( + L_spec, + L_spec_core, + env, + target_bits, + low_complexity, + envelope, + &envelope_e + ); + + *arith_bits = tcx_arith_decode( + L_spec, + envelope, + envelope_e, + target_bits, + prm, + q_spectrum, + q_spectrum_e, + nf_seed + ); + move16(); + + /* safety check in case of bit errors */ + IF( *arith_bits < 0 ) + { + st->BER_detect = 1; + move16(); + set32_fx(q_spectrum, 0, L_frame); + } + + set32_fx(q_spectrum + L_spec, 0, sub(L_frame, L_spec)); +} diff --git a/lib_dec/avq_dec_fx.c b/lib_dec/avq_dec_fx.c new file mode 100644 index 0000000..cfa14a7 --- /dev/null +++ b/lib_dec/avq_dec_fx.c @@ -0,0 +1,241 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-----------------------------------------------------------------* + * Function AVQ_Demuxdec_Bstr * + * ~~~~~~~~~~~~~~~~~~ * + * Read indexes from one bitstream and decode subvectors. * + *-----------------------------------------------------------------*/ + +void AVQ_demuxdec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 xriq[], /* o: decoded subvectors [0..8*Nsv-1] */ + Word16 *nb_bits, /* i/o: number of allocated bits */ + const Word16 Nsv, /* i: number of subvectors */ + Word16 nq_out[] /* i/o: AVQ nq index */ +) +{ + Word16 i,j, bits, order_v; + UWord16 I[NSV_MAX]; + Word16 nq[NSV_MAX], *kv, code[8]; + Word16 tmp16; + + set16_fx( (Word16*)I, 0, NSV_MAX ); + set16_fx( code, 0, 8 ); + + kv = xriq; /* reuse vector to save memory */ + bits = *nb_bits; + move16(); + + FOR( i=0; iBER_detect = 1; + move16(); + set16_fx( xriq, 0, shl(Nsv,3) ); + set16_fx( nq_out, 0, Nsv ); + *nb_bits = 0; + move16(); + + return; + } + + bits = sub(bits,nq[i]); + bits = sub(bits,1); /* count the stop bit */ + + if( nq[i] > 0 ) + { + nq[i] = add(nq[i],1); + move16(); + } + + /* read codebook indices (rank I and event. Voronoi index kv) */ + IF( nq[i] != 0 ) /* for Q0 nothing to read */ + { + IF( LT_16(nq[i], 5)) /* Q2, Q3, Q4 */ + { + tmp16 = shl(nq[i], 2); + order_v = 0; + move16(); + } + ELSE /* for Q3/Q4 + Voronoi extensions r=1,2 */ + { + j = 1; + move16(); + if( s_and(nq[i], 1) == 0 ) + { + j = add(j,1); + } + order_v = sub(shr(nq[i], 1), j); /* Voronoi order determination */ + tmp16 = shl(add(j, 2), 2); + } + + I[i] = get_next_indice_fx(st_fx, tmp16 ); + move16(); + bits = sub(bits, tmp16); + + IF( order_v > 0 ) + { + tmp16 = shl(i, 3); + FOR( j=0; j<8; j++ ) + { + kv[tmp16+j] = (Word16)get_next_indice_fx(st_fx, order_v ); + move16(); + } + bits = sub(bits, shl(order_v, 3)); + } + } + } + } + + /* decode all subvectors */ + FOR( i=0; i=0; l--) + { + nq = indx[l]; /* quantizer number (0,2,3..n) */ move16(); + + nk = 0; + move16(); + n = nq; + move16(); + + IF (GT_16(nq, 4)) + { + nk = shr(sub(nq, 3), 1); + n = sub(nq, shl(nk, 1)); + } + + /* read n groups of 4-bit for Voronoi index (k[]) */ + + FOR (i=0; i<8; i++) + { + kv[i] = 0; + move16(); + } + + FOR ( ; nk > 0; nk--) + { + ival = s_and(indx[pos--], 0x0F); + ival = shl(ival, 4); + ival = add(ival, s_and(indx[pos--], 0x0F)); + + FOR (i=7; i>=0; i--) + { + kv[i] = shl(kv[i], 1); + kv[i] = add(kv[i], s_and(ival, 0x01)); + move16(); + ival = shr(ival, 1); + } + } + + /* read n groups of 4-bit for base codebook index (I) */ + I = L_deposit_l(0); + FOR (; n > 0; n--) + { + I = L_shl(I, 4); + I = L_add(I, (Word32) s_and(indx[pos--], 0x0F)); + } + + /* multi-rate RE8 decoder */ + I16 = (UWord16)extract_l(I); + cast16(); + re8_dec_fx(nq, I16, kv, c); + + /* write decoded RE8 vector */ + FOR (i=0; i<8; i++) + { + nvecq[(l*8)+i] = c[i]; + move16(); + } + } + + return; +} diff --git a/lib_dec/basop_util_jbm.c b/lib_dec/basop_util_jbm.c new file mode 100644 index 0000000..f0dc733 --- /dev/null +++ b/lib_dec/basop_util_jbm.c @@ -0,0 +1,38 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*! @file basop_util_jbm.c basop utility functions for JBM. */ + +#include "basop_util.h" +#include "basop_util_jbm.h" +#include "options.h" +#include "stl.h" + +/* Adds two uint32_t values with overflow like plain C. */ +Word32 rtpTs_add( Word32 ts1, Word32 ts2 ) +{ + Word32 ret; + + Carry = 0; + ret = L_add_c(ts1, ts2); + Carry = 0; + Overflow = 0; + + return ret; +} + +/* Subtracts two uint32_t values with overflow like plain C. */ +Word32 rtpTs_sub( Word32 ts1, Word32 ts2 ) +{ + Word32 ret; + + BASOP_SATURATE_WARNING_OFF + Carry = 1; + ret = L_sub_c(ts1, ts2); + BASOP_SATURATE_WARNING_ON + Carry = 0; + Overflow = 0; + + return ret; +} diff --git a/lib_dec/basop_util_jbm.h b/lib_dec/basop_util_jbm.h new file mode 100644 index 0000000..5472096 --- /dev/null +++ b/lib_dec/basop_util_jbm.h @@ -0,0 +1,18 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*! @file basop_util_jbm.h basop utility functions for JBM. */ + +#ifndef BASOP_UTIL_JBM_H +#define BASOP_UTIL_JBM_H + +#include "typedef.h" + +/*! Adds two uint32_t values with overflow like plain C. */ +Word32 rtpTs_add( Word32 ts1, Word32 ts2 ); + +/*! Subtracts two uint32_t values with overflow like plain C. */ +Word32 rtpTs_sub( Word32 ts1, Word32 ts2 ); + +#endif diff --git a/lib_dec/bass_psfilter_fx.c b/lib_dec/bass_psfilter_fx.c new file mode 100644 index 0000000..4aa3e7d --- /dev/null +++ b/lib_dec/bass_psfilter_fx.c @@ -0,0 +1,868 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "rom_dec_fx.h" /* Static table prototypes */ + +#include "stl.h" +#include "basop_mpy.h" +#include "basop_util.h" + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define NBPSF_L_EXTRA 120 +#define BPF_STOP_STOPBAND_16 16 + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ +static Word16 Pit_track_fx(Word16 syn[], Word16 T); + +/*---------------------------------------------------------------------* + * bass_psfilter_init() + * + * Initialisation of postfiltering variables + *---------------------------------------------------------------------*/ +void bass_psfilter_init_fx( + Word16 old_syn[], /* o : Old synthesis buffer 1 */ + Word16 *mem_deemph_err, /* o : Error deemphasis memory */ + Word16 *lp_ener /* o : long_term error signal energy */ +) +{ + /* post-filter memories */ + *mem_deemph_err = 0; + move16(); + *lp_ener = 0; + move16();/*0 in Q8 */ + set16_fx(old_syn, 0, NBPSF_PIT_MAX); + + return; +} + +/*=========================================================================*/ +/* FUNCTION : void bass_psfilter_fx () */ +/*-------------------------------------------------------------------------*/ +/* PURPOSE : */ +/*-------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ Word16 synth_in_fx[], Q_syn2-1 i :input synthesis (at 16kHz) */ +/* _ const Word16 L_frame, i : length of the last frame */ +/* _ Word16 pitch_buf_fx[],Q6 i : pitch for every subfr [0,1,2,3] */ +/* _ const Word16 bpf_off, i : do not use BPF when set to 1 */ +/* _ Word16 v_stab_fx, Q15 i : stability factor */ +/* _ Word16 Q_syn i : Q format of synth_in_fx */ +/*-------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ Word16 *mem_deemph_err, Q_syn2-1 */ +/* o : Error deemphasis memory */ +/* _ Word16 *lp_ener, Q8 o : long_term error signal energy */ +/*-------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ Word16 old_syn_fx[], Q_syn2-1 i/o: NBPSF_PIT_MAX */ +/* _ Word16 *v_stab_smooth_fx,Q15 i/o: smoothed stability factor */ +/*-------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*=========================================================================*/ + +void bass_psfilter_fx( + const Word16 Opt_AMR_WB, /* i : AMR-WB IO flag */ + Word16 synth_in_fx[], /* i : input synthesis (at 16kHz) */ + const Word16 L_frame, /* i : length of the last frame */ + Word16 pitch_buf_fx[], /* i : pitch for every subfr [0,1,2,3] */ + Word16 old_syn_fx[], /* i/o: NBPSF_PIT_MAX */ + Word16 *mem_deemph_err, /* o : Error deemphasis memory */ + Word16 *lp_ener, /* o : long_term error signal energy */ + const Word16 bpf_off, /* i : do not use BPF when set to 1 */ + Word16 v_stab_fx, /* i : stability factor */ + Word16 *v_stab_smooth_fx, /* i/o: smoothed stability factor */ + Word16 *mem_mean_pit, /* i/o: average pitch memory */ + Word16 *Track_on_hist, /* i/o: History of half frame usage */ + Word16 *vibrato_hist, /* i/o: History of frames declared as vibrato*/ + Word16 *psf_att, /* i/o: Post filter attenuation factor */ + const Word16 coder_type, /* i : coder_type */ + Word16 Q_syn, + Word16 bpf_noise_buf[] /* o : BPF error signal (at int_fs) */ +) +{ + Word16 i, j, i_subfr, T, exp, exp2; + Word16 tmp, gain, alpha, tmp2; + Word32 Lcorr, Lener; + Word32 Lcorr0,Lener0,Ltmp; + Word16 syn_buf_fx[NBPSF_PIT_MAX+L_FRAME16k+NBPSF_PIT_MAX], *syn_fx; + Word16 syn2_buf_fx[L_FRAME16k], *syn2_fx; + Word16 err[L_HALFR16k], *sigPtr, *sigPtr1; + Word16 T_sf[NB_SUBFR16k]; + Word16 subfr_pos; + Word16 nb_subfr; + Word16 delta_v_stab; + Word16 T_update = 0; + Word16 dist_pit_diff, idx_pit_min, idx_pit_max, vibrato, Track_on; + Word16 loc_pit_max, loc_pit_min, diff_pit; + Word16 TrackOnR, vibratR, alp_tmp; + Word16 Q_syn2x; + + + Track_on = 0; + move16(); + vibrato = 0; + move16(); + + nb_subfr = shr(L_frame,6); + move16(); + + /*------------------------------------------------------- + * Initialize pointers to various synthesis buffers + * + * |--------------------syn_buf--------------------------------| + * |-----old_syn-----|-------synth_in--------|----extrapol---- | + * |--NBPSF_PIT_MAX--| sf1 | sf2 | sf3 | sf4 |--NBPSF_PIT_MAX--| + * |------syn2_buf---------| + * |------L_frame----------| + * |----bpf_noise_buf------| + * + *-------------------------------------------------------*/ + Q_syn2x = shl(Q_syn, 1); + move16(); + + Copy(old_syn_fx, syn_buf_fx, NBPSF_PIT_MAX); + Copy(synth_in_fx, syn_buf_fx+NBPSF_PIT_MAX, L_frame); + + test(); + IF( !(pitch_buf_fx == NULL || bpf_off) ) + { + FOR(i = L_TRACK_HIST-1; i > 0; i--) + { + mem_mean_pit[i] = mem_mean_pit[i-1]; + move16(); /*Q6 */ + } + Ltmp = L_deposit_l(0); + FOR(j=0; j Q4*/ + if(EQ_16(nb_subfr,5)) + { + tmp = mult_r(tmp, 26214); /* multiply by 0.8 for case where L_frame == L_FRAME16k*/ + } + mem_mean_pit[i] = tmp; /*Q4 */ move16(); + } + idx_pit_min = minimum_fx(mem_mean_pit, L_TRACK_HIST, &loc_pit_min); + idx_pit_max = maximum_fx(mem_mean_pit, L_TRACK_HIST, &loc_pit_max); + + dist_pit_diff = abs_s(sub(idx_pit_max,idx_pit_min)); + diff_pit = sub(loc_pit_max,loc_pit_min); /*Q4 */ + + if( EQ_16(L_frame,L_FRAME16k)) + { + diff_pit = mult_r(diff_pit,26214); /*Q4 */ + } + + test(); + test(); + test(); + if( coder_type != INACTIVE && GE_16(diff_pit,2<<4)&<_16(diff_pit,10<<4)&&GE_16(dist_pit_diff,3)) + { + vibrato = 1; + move16(); + } + + tmp = sum16_fx(Track_on_hist,L_TRACK_HIST); + TrackOnR = round_fx(L_shl(L_mult0(tmp,3277),16)); /*Q15 */ + + vibratR = sum16_fx(vibrato_hist,L_TRACK_HIST); /*Q0 */ + + alp_tmp = sub(32767,TrackOnR); /*Q15 */ + + IF( vibrato ) + { + /* vibratR = vibratR * vibratR * -0.009f + 1.0f;move16(); */ + tmp = round_fx(L_shl(L_mult0(vibratR,vibratR),16)); /*Q0 */ + tmp = round_fx(L_shl(L_mult(tmp,18874),9)); /*Q15 */ + vibratR = sub(32767,tmp); /*Q15 */ + alp_tmp = mult_r(alp_tmp,vibratR); /*Q15 */ + } + + alp_tmp = s_max( 3277, alp_tmp ); + + IF( GT_16(alp_tmp,*psf_att)) + { + /**psf_att = add(mult_r(1638,alp_tmp),mult_r(31130,*psf_att)); //Q15 */ + *psf_att = round_fx(L_mac(L_mult(1638,alp_tmp),31130,*psf_att)); /*Q15 */ + } + ELSE + { + /**psf_att = add(mult_r(13107,alp_tmp),mult_r(19661,*psf_att)); //Q15 */ + *psf_att = round_fx(L_mac(L_mult(13107,alp_tmp),19661,*psf_att)); /*Q15 */ + } + test(); + IF( pitch_buf_fx == NULL || bpf_off ) + { + /* do not use BPF for HQ core */ + T_update = 80; + move16(); + set16_fx( T_sf, 0, 5 ); + syn_fx = &syn_buf_fx[NBPSF_PIT_MAX+L_frame]; + sigPtr = syn_fx-T_update; + FOR (i=0; i 0; i-- ) + { + Track_on_hist[i] = Track_on_hist[i-1]; + move16(); + vibrato_hist[i] = vibrato_hist[i-1]; + move16(); + } + + Track_on_hist[i] = Track_on; + move16(); + vibrato_hist[i] = vibrato; + move16(); + + Copy( syn_buf_fx+L_frame, old_syn_fx, NBPSF_PIT_MAX ); + + + return; +} + +/*==============================================================================*/ +/* FUNCTION : Word16 Pit_track_fx ( ) */ +/*------------------------------------------------------------------------------*/ +/* PURPOSE : */ +/*------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 syn[], st_fx->Q_syn2 i : synthesis [-PIT_MAX..L_SUBFR] */ +/* Word16 T Q0 i : pitch period (>= PIT_MIN) */ +/*------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* Word16 T Q0 */ +/*------------------------------------------------------------------------------*/ +/* CALLED FROM : TX/RX */ +/*==============================================================================*/ + +static Word16 Pit_track_fx( /* o : Pitch */ + Word16 syn[], /* i : synthesis [-PIT_MAX..L_SUBFR] */ + Word16 T /* i : pitch period (>= PIT_MIN) */ +) +{ + Word16 T2; + Word16 i, j; + Word32 Ltmp, Lcorr, Lener; + Word32 Ltmp0, Lcorr0, Lener0; + Word16 *v1, *v2; + Word16 exp1, exp2; + + /*----------------------------------------------------------------* + * Test pitch/2 to avoid continuous pitch doubling + * (short pitch is limited to PIT_MIN (34 = 376Hz) by the encoder + *----------------------------------------------------------------*/ + + T2 = shr(T, 1); + + v1 = &syn[-NBPSF_L_EXTRA]; + v2 = &syn[add(-T2, -NBPSF_L_EXTRA)]; + + Lener = L_deposit_h(-32768); + Ltmp = L_deposit_h(-32768); + Lcorr = L_deposit_l(2); + /* by using the maximum negative value + it is possible to gain another bit + of range for the 'Lener' sum. + It cannot be done for Lcorr + because it is a signed sum. */ + FOR (j = 0; j < 14; j++) + { + BASOP_SATURATE_WARNING_OFF + Lener0 = L_mult0(*v1, *v1); + Ltmp0 = L_mult0(*v2, *v2); + Lcorr0 = L_mult0(*v1++, *v2++); + FOR (i = 1; i < (L_HALFR16k+NBPSF_L_EXTRA)/14; i++) + { + Lener0 = L_mac0(Lener0, *v1, *v1); + Ltmp0 = L_mac0(Ltmp0, *v2, *v2); + Lcorr0 = L_mac0(Lcorr0, *v1++, *v2++); + } + BASOP_SATURATE_WARNING_ON + test(); + test(); + test(); + IF (EQ_32(Lener0, 2147483647L)|| + EQ_32(Ltmp0, 2147483647L) || + EQ_32(Lcorr0, 2147483647L) || EQ_32(Lcorr0, -2147483647-1L)) + { + v1 -= i; + move16(); + v2 -= i; + move16(); + FOR (i = 0; i < (L_HALFR16k+NBPSF_L_EXTRA)/14; i++) + { + Lener = L_add(Lener, L_shr(L_mult0(*v1, *v1), 6)); + Ltmp = L_add(Ltmp, L_shr(L_mult0(*v2, *v2), 6)); + Lcorr = L_add(Lcorr, L_shr(L_mult0(*v1++, *v2++), 6)); + } + } + ELSE + { + Lener = L_add(Lener, L_shr(Lener0, 6)); + Ltmp = L_add(Ltmp, L_shr(Ltmp0, 6)); + Lcorr = L_add(Lcorr, L_shr(Lcorr0, 6)); + } + } + + Lener = L_shr(Lener, 1); + Lener = L_add(Lener, 0x40000001L); + Ltmp = L_shr(Ltmp, 1); + Ltmp = L_add(Ltmp, 0x40000001L); + Lcorr = L_shr(Lcorr, 1); + /* 'Lener', 'Ltmp' & 'Lcorr' are divided by 2 */ + + /* cn = corr / (float)sqrt(ener*tmp) */ + exp1 = norm_l(Lener); + exp2 = norm_l(Ltmp); + /* Multiply the Most Significant 16 bits */ + Ltmp = L_mult0(round_fx(L_shl(Lener, exp1)), round_fx(L_shl(Ltmp, exp2))); + exp1 = add(exp1, exp2); + /* Correct if Odd # of Shifts */ + exp2 = s_and(exp1, 1); + exp1 = sub(exp1, exp2); + Ltmp = L_shr(Ltmp, exp2); + /* Call the Integer Square Root (it will normalize again if req.) */ + Ltmp = Isqrt(Ltmp); + /* We now do corr * 1 / sqrt(1/product) with high part of ratio only */ + exp1 = mac_r((16-1)*65536L-0x8000L, exp1, 16384); + exp2 = norm_l(Ltmp); + Ltmp = L_shl(Ltmp, exp2); + exp1 = sub(exp1, exp2); + exp2 = norm_l(Lcorr); + Lcorr= L_shl(Lcorr, exp2); + exp1 = sub(exp1, exp2); + Ltmp = Mpy_32_16_1(Lcorr, round_fx(Ltmp)); + /* Go to Q31 */ + Ltmp = L_shl(Ltmp, exp1); + + /* cn = normalized correlation of pitch/2 */ + if (GT_32(Ltmp, 2040109466L)) /* 0.95f in Q31 */ + { + T = T2; + move16(); + } + + return T; +} + +/*---------------------------------------------------------------------* + * addBassPostFilter() + * + * Add BPF component in cldfb domain + *---------------------------------------------------------------------*/ + +void addBassPostFilterFx (const Word16 *harm_timeIn_Fx, + Word32 **rAnalysis_Fx, + Word32 **iAnalysis_Fx, + HANDLE_CLDFB_FILTER_BANK cldfbBank_bpf_Fx, + Word32 *workBuffer, + const Word16 timeIn_e, + const Word16 nTimeSlots, + const Word16 nTimeSlotsTotal, + const Word16 nBandsTotal, + CLDFB_SCALE_FACTOR *cldfb_scale + ) +{ + Word16 i, scale1, scale2; + Word16 b; + Word16 maxBand; + Word16 nChan; + CLDFB_SCALE_FACTOR scale; + const Word16 *weights_Fx; + Word32 *tmp_R_Fx[CLDFB_NO_COL_MAX]; + Word32 *tmp_I_Fx[CLDFB_NO_COL_MAX]; + Word32 cldfbBufferReal[CLDFB_NO_COL_MAX][20]; + Word32 cldfbBufferImag[CLDFB_NO_COL_MAX][20]; + + nChan = cldfbBank_bpf_Fx->no_channels; + scale1 = scale2 = 0; + move16(); + move16(); + + weights_Fx = bpf_weights_16_Fx; + maxBand = s_min(nChan, BPF_STOP_STOPBAND_16); + + assert(nChan <= 20); + + FOR (i=0; i < nTimeSlots; i++) + { + tmp_R_Fx[i] = cldfbBufferReal[i]; + tmp_I_Fx[i] = cldfbBufferImag[i]; + } + + /* do the CLDFB anlysis of filtered signal */ + cldfbAnalysisFiltering( cldfbBank_bpf_Fx, + tmp_R_Fx, + tmp_I_Fx, + &scale, + harm_timeIn_Fx, + timeIn_e, + nTimeSlots, + workBuffer + ); + + /* now do the subtraction */ + + IF (nTimeSlots > 0) + { + /* Find common scale. */ + b = s_max(cldfb_scale->lb_scale, scale.lb_scale); + scale1 = limitScale32(sub(cldfb_scale->lb_scale, b)); + scale2 = limitScale32(sub(scale.lb_scale, b)); + cldfb_scale->lb_scale = b; + move16(); + /* Rescale time slots which do not have BPF contribution. */ + FOR (i=nTimeSlots; i < nTimeSlotsTotal; i++) + { + Scale_sig32(rAnalysis_Fx[i], nBandsTotal, scale1); + Scale_sig32(iAnalysis_Fx[i], nBandsTotal, scale1); + } + } + + FOR (i=0; i < nTimeSlots; i++) + { + /* Compensate first bpf_weights coefficient which is scaled by 0.5 */ + rAnalysis_Fx[i][0] = L_sub(L_shl(rAnalysis_Fx[i][0],scale1),L_shl(Mpy_32_16_1(tmp_R_Fx[i][0],weights_Fx[0]),add(1, scale2))); + move32(); + iAnalysis_Fx[i][0] = L_sub(L_shl(iAnalysis_Fx[i][0],scale1),L_shl(Mpy_32_16_1(tmp_I_Fx[i][0],weights_Fx[0]),add(1, scale2))); + move32(); + + /* loop over remaining low frequency bands */ + FOR (b=1; b < maxBand; b++) + { + rAnalysis_Fx[i][b] = L_sub(L_shl(rAnalysis_Fx[i][b],scale1),L_shr(Mpy_32_16_1(tmp_R_Fx[i][b],weights_Fx[b]), scale2)); + move32(); + iAnalysis_Fx[i][b] = L_sub(L_shl(iAnalysis_Fx[i][b],scale1),L_shr(Mpy_32_16_1(tmp_I_Fx[i][b],weights_Fx[b]), scale2)); + move32(); + } + + /* Rescale Bands with no BPF contribution. */ + Scale_sig32(rAnalysis_Fx[i]+maxBand, sub(nBandsTotal, maxBand), scale1); + Scale_sig32(iAnalysis_Fx[i]+maxBand, sub(nBandsTotal, maxBand), scale1); + } + + return; +} diff --git a/lib_dec/cng_dec_fx.c b/lib_dec/cng_dec_fx.c new file mode 100644 index 0000000..f048c79 --- /dev/null +++ b/lib_dec/cng_dec_fx.c @@ -0,0 +1,982 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ + +#include "stl.h" +#include "prot_fx.h" +#include "cnst_fx.h" +#include "rom_com_fx.h" +#include "basop_mpy.h" +#include + +/*Temporary location to be move in prot* when merge is done*/ +void E_LPC_f_isp_a_conversion(const Word16 *isp, Word16 *a, const Word16 m); +void E_LPC_f_lsp_a_conversion(const Word16 *isp, Word16 *a, const Word16 m); + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + +static void shb_CNG_decod_fx( Decoder_State_fx *st_fx, const Word16 *synth_fx, Word16 *shb_synth_fx, const Word16 sid_bw + ,const Word16 Qsyn + ); + +/*-----------------------------------------------------------------* + * Decode residual signal energy + *-----------------------------------------------------------------*/ + +void CNG_dec_fx( + Decoder_State_fx *st_fx, /* i/o: State structure */ + const Word16 L_frame, /* i : length of the frame Q0 */ + Word16 Aq[], /* o : LP coefficients Q12 */ + const Word32 core_brate, /* i : core bitrate Q0 */ + Word16 *lsp_new, /* i/o: current frame LSPs Q15 */ + Word16 *lsf_new, /* i/o: current frame LSFs Qlog2(2.56) */ + Word16 *allow_cn_step, /* o : allow CN step Q0 */ + Word16 *sid_bw /* i : 0-NB/WB, 1-SWB SID */ + ,Word32 *q_env +) +{ + Word16 istep; + Word16 i, L_enr_index; + Word32 L_ener; + Word16 ener_fra,ener_int; + Word16 num_bits; + Word16 weights, ptr, j, k; + Word16 m1; + Word16 m = 0; + Word16 tmp[HO_HIST_SIZE*M]; + Word16 burst_ho_cnt = 0; + Word16 ll,s_ptr; + Word32 L_enr,L_tmp1; + Word16 tmp1,exp; + Word16 lsf_tmp[M]; + Word32 C[M]; + Word32 max[2]; + Word16 max_idx[2]; + Word16 ftmp_fx; + Word16 lsp_tmp[M]; + Word16 dev; + Word16 max_dev; + Word16 dist; + Word16 tmpv; + Word16 env_idx[2]; + Word32 enr1; + Word32 env[NUM_ENV_CNG]; + Word32 tmp_env[HO_HIST_SIZE*NUM_ENV_CNG]; + Word32 L_tmp; + Word16 fra; + Word16 temp_lo_fx, temp_hi_fx; + Word16 exp_pow; + Word16 tmp_loop; + Word16 LSF_Q_prediction; /* o : LSF prediction mode - just temporary variable in CNG */ + + m = 0; + move16(); + /*-----------------------------------------------------------------* + * Decode CNG spectral envelope (only in SID frame) + *-----------------------------------------------------------------*/ + test(); + IF ( EQ_32(core_brate,SID_1k75)||EQ_32(core_brate,SID_2k40)) + { + /* de-quantize the LSF vector */ + IF ( st_fx->Opt_AMR_WB_fx != 0 ) + { + /* Flt function */ + isf_dec_amr_wb_fx( st_fx, Aq, lsf_new, lsp_new); + { + Word16 enr_new, Aq_tmp[M + 1]; + /* check if ISPs may trigger too much synthesis energy */ + + E_LPC_f_isp_a_conversion(lsp_new, Aq_tmp, M); + enr_new = Enr_1_Az_fx(Aq_tmp, 2 * L_SUBFR); + + IF ((shr(enr_new, 14) > 0)) + { + /* Use old LSP vector */ + Copy(st_fx->lsp_old_fx, lsp_new, M); + Copy(st_fx->lsf_old_fx, lsf_new, M); + } + } + } + ELSE + { + lsf_dec_fx( st_fx, 0, L_frame, INACTIVE, -1, Aq, &LSF_Q_prediction, lsf_new, lsp_new, 0 ); + { + Word16 enr_new, Aq_tmp[M + 1]; + /* check if LSPs may trigger too much synthesis energy */ + + E_LPC_f_lsp_a_conversion(lsp_new, Aq_tmp, M); + enr_new = Enr_1_Az_fx(Aq_tmp, 2 * L_SUBFR); + + IF(shr(enr_new, 14) > 0) + { + /* Use old LSP vector */ + Copy(st_fx->lsp_old_fx, lsp_new, M); + Copy(st_fx->lsf_old_fx, lsf_new, M); + } + } + } + } + ELSE + { + /* Use old LSP vector */ + Copy( st_fx->lsp_old_fx, lsp_new, M ); + Copy( st_fx->lsf_old_fx, lsf_new, M ); + } + + /* Initialize the CNG spectral envelope in case of the very first CNG frame */ + IF( st_fx->first_CNG_fx == 0 ) + { + Copy( st_fx->lsp_old_fx, st_fx->lspCNG_fx, M ); + } + + /*-----------------------------------------------------------------* + * Decode residual signal energy + *-----------------------------------------------------------------*/ + + *allow_cn_step = 0; + move16(); + test(); + IF( EQ_32(core_brate,SID_1k75)||EQ_32(core_brate,SID_2k40)) + { + istep = ISTEP_AMR_WB_SID_FX; + move16(); + if( EQ_32(core_brate,SID_2k40)) + { + istep = ISTEP_SID_FX; + move16(); + } + + /* intialize the energy quantization parameters */ + num_bits = 6; + move16(); + if( st_fx->Opt_AMR_WB_fx == 0 ) + { + num_bits = 7; + move16(); + } + + /* decode the energy index */ + L_enr_index = get_next_indice_fx( st_fx, num_bits ); + + IF( LE_32(st_fx->last_core_brate_fx, SID_2k40) || EQ_16(st_fx->prev_bfi_fx, 1) ) + { + tmp1 = add(st_fx->old_enr_index_fx, 20); + } + ELSE + { + tmp1 = add(st_fx->old_enr_index_fx, 40); + } + IF( GT_16(L_enr_index, tmp1) && st_fx->old_enr_index_fx >= 0 ) /* Likely bit error and not startup */ + { + L_enr_index = tmp1; move16(); + L_enr_index = s_min(L_enr_index, 127); + if (st_fx->Opt_AMR_WB_fx != 0) + { + L_enr_index = s_min(L_enr_index, 63); + } + } + + test(); + test(); + test(); + if (GT_32(st_fx->last_core_brate_fx,SID_1k75)&& + st_fx->first_CNG_fx != 0 && + st_fx->old_enr_index_fx >= 0 && + GT_16(L_enr_index, add(st_fx->old_enr_index_fx,1))) + { + *allow_cn_step = 1; + move16(); + } + + st_fx->old_enr_index_fx = L_enr_index; + move16(); + if ( L_enr_index == 0 ) + { + L_enr_index = -5; + move16(); + } + /* st_fx->Enew = L_enr_index / step - 2.0f;*/ + L_ener = L_mult(L_enr_index, istep); /* Q16 (0+15) */ + /* substract by 2 not done to leave Energy in Q2 */ + + /* extract integral and fractional parts */ + ener_fra = L_Extract_lc(L_ener, &ener_int); + ener_int = add(ener_int, 4); /* Q2 to Q6 */ + + /* find the new energy value */ + st_fx->Enew_fx = Pow2(ener_int, ener_fra); + + IF( EQ_32(core_brate,SID_2k40)) + { + burst_ho_cnt = get_next_indice_fx( st_fx, 3 ); /* 3bit */ + + *sid_bw = get_next_indice_fx( st_fx, 1 ); + IF ( *sid_bw == 0 ) + { + env_idx[0] = get_next_indice_fx( st_fx, 6 ); + move16(); + + /* get quantized res_env_details */ + FOR ( i=0; ibwidth_fx,WB)&&st_fx->first_CNG_fx!=0&&NE_16(st_fx->L_frame_fx,st_fx->last_CNG_L_frame_fx)) + { + st_fx->ho_hist_size_fx = 0; + move16(); + } + } + + /*---------------------------------------------------------------------* + * CNG spectral envelope update + * Find A(z) coefficients + *---------------------------------------------------------------------*/ + test(); + test(); + test(); + IF( st_fx->last_core_brate_fx <= SID_2k40 ) + { + /* Reset hangover counter if not first SID period */ + if( GT_32(st_fx->core_brate_fx,FRAME_NO_DATA)) + { + st_fx->num_ho_fx = 0; + move16(); + } + /* Update LSPs if last SID energy not outlier or insufficient number of hangover frames */ + test(); + IF( LT_16(st_fx->num_ho_fx,3)||LT_32(Mult_32_16(st_fx->Enew_fx,21845/*1/1.5f, Q15*/),st_fx->lp_ener_fx)) + { + FOR( i=0; ilspCNG_fx[i] = mac_r(L_mult(CNG_ISF_FACT_FX, st_fx->lspCNG_fx[i]), 32768-CNG_ISF_FACT_FX, lsp_new[i]); + move16(); /* Q15 (15+15+1-16) */ + } + } + } + ELSE + { + /* Update CNG_mode if allowed */ + test(); + test(); + test(); + IF( ( st_fx->Opt_AMR_WB_fx || EQ_16(st_fx->bwidth_fx,WB)) + && ( !st_fx->first_CNG_fx || GE_16(st_fx->act_cnt2_fx,MIN_ACT_CNG_UPD) ) ) + { + IF( GT_32(st_fx->last_active_brate_fx,ACELP_16k40)) + { + st_fx->CNG_mode_fx = -1; + move16(); + } + ELSE IF( GT_32(st_fx->last_active_brate_fx,ACELP_13k20)) + { + st_fx->CNG_mode_fx = 4; + move16(); + } + ELSE IF( GT_32(st_fx->last_active_brate_fx,ACELP_9k60)) + { + st_fx->CNG_mode_fx = 3; + move16(); + } + ELSE IF( GT_32(st_fx->last_active_brate_fx,ACELP_8k00)) + { + st_fx->CNG_mode_fx = 2; + move16(); + } + ELSE IF( GT_32(st_fx->last_active_brate_fx,ACELP_7k20)) + { + st_fx->CNG_mode_fx = 1; + move16(); + } + ELSE + { + st_fx->CNG_mode_fx = 0; + move16(); + } + } + + /* If first sid after active burst update LSF history from circ buffer */ + burst_ho_cnt = s_min(burst_ho_cnt, st_fx->ho_circ_size_fx); /* MODE1_DTX_IN_CODEC_B_FIX */ + st_fx->act_cnt_fx = 0; + move16(); + s_ptr = add(sub(st_fx->ho_circ_ptr_fx, burst_ho_cnt),1); + move16(); + if( s_ptr < 0 ) + { + s_ptr = add(s_ptr,st_fx->ho_circ_size_fx); + } + + FOR( ll = burst_ho_cnt; ll > 0; ll-- ) + { + st_fx->ho_hist_ptr_fx = add(st_fx->ho_hist_ptr_fx,1); + if( EQ_16(st_fx->ho_hist_ptr_fx, HO_HIST_SIZE)) + { + st_fx->ho_hist_ptr_fx = 0; + move16(); + } + + /* Conversion between 12.8k and 16k LSPs */ + test(); + test(); + test(); + IF( ( EQ_16(L_frame,L_FRAME16k)&&st_fx->ho_16k_lsp_fx[s_ptr]==0)||(EQ_16(L_frame,L_FRAME)&&EQ_16(st_fx->ho_16k_lsp_fx[s_ptr],1))) + { + /* Conversion from 16k LPSs to 12k8 */ + lsp_convert_poly_fx( &(st_fx->ho_lsp_circ_fx[s_ptr*M]), L_frame, 0 ); + } + /* update the circular buffers */ + Copy(&(st_fx->ho_lsp_circ_fx[s_ptr*M]), &(st_fx->ho_lsp_hist_fx[st_fx->ho_hist_ptr_fx*M]), M ); + Copy32(&(st_fx->ho_ener_circ_fx[s_ptr]), &(st_fx->ho_ener_hist_fx[st_fx->ho_hist_ptr_fx]), 1 ); + st_fx->ho_sid_bw_fx = L_shl(L_and(st_fx->ho_sid_bw_fx, (Word32) 0x3fffffffL ), 1); + Copy32(&(st_fx->ho_env_circ_fx[s_ptr*NUM_ENV_CNG]), &(st_fx->ho_env_hist_fx[st_fx->ho_hist_ptr_fx*NUM_ENV_CNG]), NUM_ENV_CNG ); + + st_fx->ho_hist_size_fx = add(st_fx->ho_hist_size_fx,1); + + if (GT_16(st_fx->ho_hist_size_fx, HO_HIST_SIZE)) + { + st_fx->ho_hist_size_fx = HO_HIST_SIZE; + move16(); + } + + s_ptr = add(s_ptr,1); + if( EQ_16(s_ptr, st_fx->ho_circ_size_fx)) + { + s_ptr = 0; + move16(); + } + } + + IF( st_fx->ho_hist_size_fx > 0 ) /* can be -1 at init MODE1_DTX_IN_CODEC_B_FIX */ + { + /* *allow_cn_step |= ( st_fx->ho_ener_hist[st_fx->ho_hist_ptr] > 4.0f * st_fx->lp_ener );*/ + L_tmp1 = L_shr(st_fx->ho_ener_hist_fx[st_fx->ho_hist_ptr_fx], 2); + L_tmp1 = L_sub(L_tmp1, st_fx->lp_ener_fx); + + if(L_tmp1 > 0) + { + *allow_cn_step = s_or(*allow_cn_step,1); + } + } + test(); + IF ( *allow_cn_step == 0 && st_fx->ho_hist_size_fx > 0 ) + { + /* Use average of energies below last energy */ + ptr = st_fx->ho_hist_ptr_fx; + move16(); + Copy( &(st_fx->ho_lsp_hist_fx[ptr*M]), tmp, M ); + m1 = 0; + move16(); + IF( L_and(st_fx->ho_sid_bw_fx, (Word32) 0x1) == 0 ) + { + Copy32( &st_fx->ho_env_hist_fx[ptr*NUM_ENV_CNG], tmp_env, NUM_ENV_CNG ); + m1 = 1; + move16(); + } + L_enr = Mult_32_16(st_fx->ho_ener_hist_fx[ptr],W_DTX_HO_FX[0]) ;/* Q6+15-15->Q6 */ + + weights = W_DTX_HO_FX[0]; /* Q15 */ + + m = 1; + move16(); + FOR( k=1; kho_hist_size_fx; k++ ) + { + ptr = sub(ptr,1); + if( ptr < 0 ) + { + ptr = HO_HIST_SIZE - 1; + move16(); + } + + test(); + IF ( LT_32(Mult_32_16(st_fx->ho_ener_hist_fx[ptr],ONE_OVER_BUF_H_NRG_FX),st_fx->ho_ener_hist_fx[st_fx->ho_hist_ptr_fx])&& + GT_32(st_fx->ho_ener_hist_fx[ptr],Mult_32_16(st_fx->ho_ener_hist_fx[st_fx->ho_hist_ptr_fx], BUF_L_NRG_FX))) + { + /*enr += W_DTX_HO[k] * st_fx->ho_ener_hist[ptr];*/ + L_tmp1 = Mult_32_16(st_fx->ho_ener_hist_fx[ptr],W_DTX_HO_FX[k]) ; /* Q6+15-15->Q6 */ + L_enr = L_add(L_enr,L_tmp1); /* Q6 */ + + /*weights += W_DTX_HO[k];*/ + weights = add( weights, W_DTX_HO_FX[k]); /* Q15 */ + + Copy( &st_fx->ho_lsp_hist_fx[ptr*M], &tmp[m*M], M ); + IF( L_and(st_fx->ho_sid_bw_fx, L_shl((Word32)0x1,k)) == 0 ) + { + Copy32( &st_fx->ho_env_hist_fx[ptr*NUM_ENV_CNG], &tmp_env[m1*NUM_ENV_CNG], NUM_ENV_CNG ); + m1 = add(m1,1); + } + m = add(m,1); + } + } + + /*enr /= weights;*/ + exp = norm_s(weights); + tmp1 = div_s(shl(1,sub(14,exp)),weights); /* Q(15+14-exp-15) */ + L_tmp1 = Mult_32_16(L_enr,tmp1); /* Q(14-exp+6-15)->Q(5-exp) */ + L_enr = L_shl(L_tmp1,exp+1); /* Q6 */ + + st_fx->lp_ener_fx = L_enr; /* Q6 */ + + set32_fx( max, 0, 2 ); + set16_fx( max_idx, 0, 2 ); + + FOR( i=0; iL_frame_fx,L_FRAME)) + { + lsp2lsf_fx( &tmp[i*M], lsf_tmp, M, INT_FS_FX ); + ftmp_fx = 964; + move16();/*X2.56 */ + tmpv = sub(16384,add(lsf_tmp[M-1],ftmp_fx)); /*QX2.56*/ + L_tmp = L_mult0(tmpv,tmpv); /*QX6.5536*/ + } + ELSE + { + lsp2lsf_fx( &tmp[i*M], lsf_tmp, M, INT_FS_16k_FX ); + ftmp_fx = 1205; + move16();/*QX2.56*/ + tmpv = sub(20480,add(lsf_tmp[M-1],ftmp_fx)); /*QX2.56*/ + L_tmp = L_mult0(tmpv,tmpv); /*QX6.5536*/ + } + + tmpv = sub(lsf_tmp[0],ftmp_fx); /*QX2.56*/ + L_tmp = L_mac0(L_tmp,tmpv,tmpv); /*QX6.5536*/ + FOR ( j=0; jlspCNG_fx[i] = lsp_tmp[i]; + move16(); /*Q15*/ + } + } + ELSE + { + FOR( i=0; ilspCNG_fx[i] = add(mult_r(26214,lsp_tmp[i]),mult_r(6554,lsp_new[i])); + } + } + IF( m1 > 0 ) + { + FOR ( i=0; ilp_ener_fx; */ + IF(EQ_16(m1,1)) + { + L_tmp = L_sub(L_tmp,L_add(st_fx->lp_ener_fx,st_fx->lp_ener_fx)); + } + ELSE + { + tmp1 = div_s(1,m1); + L_tmp = Mult_32_16(L_tmp,tmp1); + L_tmp = L_sub(L_tmp,L_add(st_fx->lp_ener_fx,st_fx->lp_ener_fx)); + } + env[i] = L_tmp; + move32(); + } + + Copy32(env, st_fx->lp_env_fx, NUM_ENV_CNG); + } + } + ELSE + { + Copy( lsp_new, st_fx->lspCNG_fx, M ); /* use newly analyzed ISFs */ + } + } + + test(); + IF( EQ_32(st_fx->core_brate_fx, SID_1k75)||EQ_32(st_fx->core_brate_fx,SID_2k40)) + { + /* Update hangover memory during CNG */ + test(); + IF ( *allow_cn_step == 0 && LT_32(st_fx->Enew_fx,L_add(st_fx->lp_ener_fx,L_shr(st_fx->lp_ener_fx,1)))) + { + /* update the pointer to circular buffer of old LSP vectors */ + st_fx->ho_hist_ptr_fx = add(st_fx->ho_hist_ptr_fx, 1); + if( EQ_16(st_fx->ho_hist_ptr_fx,HO_HIST_SIZE)) + { + st_fx->ho_hist_ptr_fx = 0; + move16(); + } + + /* update the circular buffer of old LSP vectors with the new LSP vector */ + Copy( lsp_new, &(st_fx->ho_lsp_hist_fx[(st_fx->ho_hist_ptr_fx)*M]), M ); + + /* update the hangover energy buffer */ + st_fx->ho_ener_hist_fx[st_fx->ho_hist_ptr_fx] = st_fx->Enew_fx; + move32(); + test(); + IF ( EQ_32(core_brate,SID_2k40)&&*sid_bw==0) + { + /* enr1 = (float)log10( st->Enew*L_frame + 0.1f ) / (float)log10( 2.0f );*/ + exp = norm_l(st_fx->Enew_fx); + L_tmp = L_shl(st_fx->Enew_fx,exp);/*Q(exp+6)*/ + L_tmp = Mult_32_16(L_tmp,shl(L_frame,5));/*Q(exp+6+5-15=exp-4)*/ + L_tmp = L_shr(L_tmp,sub(exp,10));/*Q6*/ + + exp = norm_l(L_tmp); + fra = Log2_norm_lc(L_shl(L_tmp,exp)); + exp = sub(sub(30,exp),6); + L_tmp = L_Comp(exp,fra); + enr1 = L_shr(L_tmp,10);/* Q6 */ + + FOR ( i=0; iEnew;*/ + L_tmp = L_sub(enr1,q_env[i]);/* Q6 */ + L_tmp = L_shl(L_tmp, 10);/* 16 */ + temp_lo_fx = L_Extract_lc(L_tmp, &temp_hi_fx); + + exp_pow = sub(14, temp_hi_fx); + L_tmp = Pow2(14, temp_lo_fx); /* Qexp_pow */ + env[i] = L_shl(L_tmp, sub(6, exp_pow)); /* Q6 */ + L_tmp = L_add(st_fx->Enew_fx,st_fx->Enew_fx); + env[i] = L_add(env[i],L_tmp); /* Q6 */ move32(); + } + st_fx->ho_sid_bw_fx = L_shl(L_and(st_fx->ho_sid_bw_fx, (Word32) 0x3fffffffL ), 1); + Copy32( env, &(st_fx->ho_env_hist_fx[(st_fx->ho_hist_ptr_fx)*NUM_ENV_CNG]), NUM_ENV_CNG ); + } + ELSE IF( *sid_bw != 0 ) + { + st_fx->ho_sid_bw_fx = L_shl(L_and(st_fx->ho_sid_bw_fx, (Word32) 0x3fffffffL ), 1); + st_fx->ho_sid_bw_fx = L_or(st_fx->ho_sid_bw_fx, 0x1L); + } + + st_fx->ho_hist_size_fx = add(st_fx->ho_hist_size_fx,1); + if( GT_16(st_fx->ho_hist_size_fx,HO_HIST_SIZE)) + { + st_fx->ho_hist_size_fx = HO_HIST_SIZE; + move16(); + } + } + /* Update the frame length memory */ + st_fx->last_CNG_L_frame_fx = st_fx->L_frame_fx; + move16(); + + if( NE_32(core_brate,SID_1k75)) + { + st_fx->num_ho_fx = m; + move16(); + } + } + + /* Update the frame length memory */ + st_fx->last_CNG_L_frame_fx = st_fx->L_frame_fx; + + if( NE_32(core_brate,SID_1k75)) + { + st_fx->num_ho_fx = m; + move16(); + } + + IF ( st_fx->Opt_AMR_WB_fx ) + { + E_LPC_f_isp_a_conversion( st_fx->lspCNG_fx, Aq, M ); + } + ELSE + { + E_LPC_f_lsp_a_conversion( st_fx->lspCNG_fx, Aq, M ); + } + + tmp_loop = shr(L_frame,6); + FOR( i=1; icore_brate_fx == FRAME_NO_DATA || EQ_32(st_fx->core_brate_fx, SID_2k40)) + { + /* SHB SID decoding and CNG */ + test(); + IF (st_fx->cng_type_fx == LP_CNG && EQ_16(st_fx->extl_fx, SWB_CNG)) + { + shb_CNG_decod_fx( st_fx, synth_fx, shb_synth_fx, sid_bw, Qsyn ); + } + st_fx->last_vad_fx = 0; + move16(); + st_fx->burst_cnt_fx = 0; + move16(); + } + ELSE + { + st_fx->last_vad_fx = 1; + move16(); + st_fx->burst_cnt_fx = add(st_fx->burst_cnt_fx, 1); + if ( GT_16(st_fx->burst_cnt_fx, 10)) + { + st_fx->burst_cnt_fx = 0; + move16(); + } + } + + return; +} + +/*---------------------------------------------------------------------* + * shb_CNG_decod() + * + * Main routine of SHB SID decoding and CNG + *---------------------------------------------------------------------*/ +static void shb_CNG_decod_fx( + Decoder_State_fx *st_fx, /* i/o: State structure */ + const Word16 *synth_fx, /* i : ACELP core synthesis at 32kHz */ + Word16 *shb_synth_fx, /* o : high-band CNG synthesis */ + const Word16 sid_bw /* i : 0-NB/WB, 1-SWB SID */ + ,const Word16 Qsyn /* i : Q value of ACELP core synthesis */ +) +{ + Word16 i; + Word16 idx_ener_fx; + Word16 shb_lpcCNG_fx[LPC_SHB_ORDER+1]; + Word16 shb_lspCNG_fx[LPC_SHB_ORDER]; + Word16 excTmp_fx[L_FRAME16k]; + Word16 excSHB_fx[L_FRAME16k]; + Word16 tmp_lsp[LPC_SHB_ORDER]; + Word16 ener_excSHB_fx; + Word32 wb_ener_fx; + Word16 wb_ener16_fx; + Word32 L_gain_fx; + Word16 gain_fx; + Word16 shb_syn16k_fx[L_FRAME16k]; + Word16 tmp; + Word16 step_fx; + Word16 interp_fx; + Word16 ener_fx; + Word16 exp,exp1; + Word16 fra; + Word32 L_tmp; + Word16 tmp2; + Word16 allow_cn_step_fx=0; + Word16 q; + + + IF ( st_fx->bfi_fx == 0 ) + { + test(); + IF ( EQ_32(st_fx->core_brate_fx, SID_2k40)&&EQ_16(sid_bw,1)) + { + idx_ener_fx = get_next_indice_fx(st_fx, 4); + + if ( idx_ener_fx == 0 ) + { + idx_ener_fx = -15; + move16(); + } + + /* de-quantization of SHB CNG parameters */ + L_tmp = L_mult(idx_ener_fx, 27400); /*Q14*/ + st_fx->last_shb_cng_ener_fx = extract_l(L_shr(L_sub(L_tmp, 295924), 6)); /*Q8 */ + } + } + + /* SHB spectrum estimation */ + + + interp_fx = s_min(st_fx->shb_dtx_count_fx,32); + interp_fx = shl(interp_fx, 10); /*Q15*/ + + FOR ( i=0; ilsp_shb_prev_fx[i]); /*Q14*/ + tmp = mult(sub(32767, interp_fx), st_fx->lsp_shb_prev_prev_fx[i]); /*Q14*/ + shb_lspCNG_fx[i] = add(tmp2, tmp); + move16(); /*Q14*/ + } + + if ( LT_16(st_fx->shb_dtx_count_fx, 1000)) + { + st_fx->shb_dtx_count_fx = add(st_fx->shb_dtx_count_fx, 1); + } + + E_LPC_lsf_lsp_conversion(shb_lspCNG_fx, tmp_lsp, LPC_SHB_ORDER); /*Q14*/ + E_LPC_f_lsp_a_conversion(tmp_lsp, shb_lpcCNG_fx, LPC_SHB_ORDER); + + Copy_Scale_sig( shb_lpcCNG_fx, shb_lpcCNG_fx, LPC_SHB_ORDER+1, sub(norm_s(shb_lpcCNG_fx[0]),2) ); /* Q12 */ + + + + /* SHB energy estimation */ + wb_ener_fx = L_deposit_l(1);/*Q1 */ + FOR ( i=0; ifirst_CNG_fx == 0 ) + { + st_fx->wb_cng_ener_fx = wb_ener16_fx; + move16();/*Q8 */ + } + if ( GT_16(abs_s(sub(wb_ener16_fx,st_fx->wb_cng_ener_fx)),3072)) + { + allow_cn_step_fx = 1; + move16(); + } + + IF ( EQ_16(allow_cn_step_fx, 1)) + { + st_fx->wb_cng_ener_fx = wb_ener16_fx; + move16(); /*Q8 */ + } + ELSE + { + tmp = sub(wb_ener16_fx, st_fx->wb_cng_ener_fx); /*Q8 */ + tmp = mult_r(tmp, 29491); /*Q8 */ + st_fx->wb_cng_ener_fx = add(st_fx->wb_cng_ener_fx, tmp); /*Q8 */ + } + test(); + test(); + IF ( EQ_32(st_fx->core_brate_fx, SID_2k40)&&EQ_16(sid_bw,1)&&st_fx->bfi_fx==0) + { + st_fx->last_wb_cng_ener_fx = st_fx->wb_cng_ener_fx; + move16(); + + if ( st_fx->first_CNG_fx == 0 ) + { + st_fx->shb_cng_ener_fx = st_fx->last_shb_cng_ener_fx; + move16(); + } + } + + gain_fx = sub(st_fx->wb_cng_ener_fx, st_fx->last_wb_cng_ener_fx); /*8 */ + if (GT_16(gain_fx, 15)) + { + gain_fx = 15; + move16(); + } + step_fx = sub(add(gain_fx, st_fx->last_shb_cng_ener_fx), st_fx->shb_cng_ener_fx); /*Q8 */ + test(); + IF ( EQ_16(allow_cn_step_fx,1)||GT_32(st_fx->last_core_brate_fx,SID_2k40)) + { + st_fx->shb_cng_ener_fx = add(st_fx->shb_cng_ener_fx, step_fx); + } + ELSE + { + st_fx->shb_cng_ener_fx = add(st_fx->shb_cng_ener_fx, mult(8192, step_fx)); /*Q8 */ + } + /* generate white noise excitation */ + FOR ( i=0; iswb_cng_seed_fx), 8); + move16();/*Q-8*/ + } + + /* synthesis filtering */ + Syn_filt_s( 0, shb_lpcCNG_fx, LPC_SHB_ORDER, excTmp_fx, excSHB_fx, L_FRAME16k, st_fx->state_lpc_syn_fx, 1 ); + + + /* synthesis signal gain shaping */ + L_tmp = 0; + FOR ( i=0; ilast_vad_fx, 1)) + { + st_fx->trans_cnt_fx = 0; + move16(); + test(); + if ( GT_16(st_fx->burst_cnt_fx, 3)&&NE_16(st_fx->last_core_fx,HQ_CORE)) + { + st_fx->trans_cnt_fx = 5; + move16(); + } + } + + ener_fx = st_fx->shb_cng_ener_fx; + move16();/*Q8 */ + IF ( st_fx->trans_cnt_fx > 0 ) + { + i = extract_l(L_mult0(st_fx->trans_cnt_fx, 17)); /*Q0 */ + ener_fx = add(st_fx->shb_cng_ener_fx, mult(sin_table256_fx[i], sub(st_fx->last_shb_ener_fx, st_fx->shb_cng_ener_fx))); /*Q8 */ + st_fx->trans_cnt_fx = sub(st_fx->trans_cnt_fx, 1); + } + + tmp = mult(3277, ener_fx); /*Q8 */ + L_tmp = L_mult(27213, tmp); /*Q22, 27213=3.321928 in Q13 */ + L_tmp = L_shr(L_tmp, 6); /*Q16 */ + L_tmp = L_add(L_tmp, 10<<16); + if( L_tmp < 0 ) + { + L_tmp = 0; + move32(); + } + fra = L_Extract_lc(L_tmp, &exp); + L_tmp = L_shl(Pow2(exp, fra), 5); /*Q5 */ + L_tmp = L_shr(L_tmp, 10); + if( L_tmp == 0 ) + { + L_tmp = 1; /*Q5 */ + } + exp = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, exp); /*Q31*/ + tmp = extract_h(L_tmp); /*Q15*/ + exp = sub(exp, 16); + exp1 = norm_s(ener_excSHB_fx); + fra = shl(ener_excSHB_fx, exp1); /*Q15*/ + + IF ( GT_16(fra,tmp)) + { + fra = shr(fra, 1); /*Q15*/ + exp1 = sub(exp1, 1); + } + tmp = div_s(fra, tmp); /*Q15*/ + + L_tmp = L_deposit_h(tmp); /*Q31 */ + tmp = -(q+exp1)+(5+exp); + L_gain_fx = Isqrt_lc(L_tmp, &tmp); /*Q31-Qtmp */ + FOR ( i=0; ilast_extl_fx, SWB_TBE)||EQ_16(st_fx->last_extl_fx,FB_TBE)) + { + /* rescale the Hilbert memories to Q0 */ + FOR(i = 0; i < HILBERT_MEM_SIZE ; i++) + { + st_fx->genSHBsynth_Hilbert_Mem_fx[i] = L_shr(st_fx->genSHBsynth_Hilbert_Mem_fx[i], st_fx->prev_Q_bwe_syn2); + move32(); + } + + FOR(i = 0; i < 2*ALLPASSSECTIONS_STEEP; i++ ) + { + st_fx->genSHBsynth_state_lsyn_filt_shb_local_fx[i] = shr(st_fx->genSHBsynth_state_lsyn_filt_shb_local_fx[i], st_fx->prev_Q_bwe_syn2); + } + + } + GenSHBSynth_fx( shb_syn16k_fx, shb_synth_fx, st_fx->genSHBsynth_Hilbert_Mem_fx, st_fx->genSHBsynth_state_lsyn_filt_shb_local_fx, st_fx->L_frame_fx, &(st_fx->syn_dm_phase_fx) ); + + IF ( EQ_32(st_fx->output_Fs_fx,48000)) + { + interpolate_3_over_2_allpass_fx( shb_synth_fx, L_FRAME32k, shb_synth_fx, st_fx->interpol_3_2_cng_dec_fx, allpass_poles_3_ov_2 ); + } + ResetSHBbuffer_Dec_fx( st_fx ); + + return; +} + + + diff --git a/lib_dec/core_dec_init.c b/lib_dec/core_dec_init.c new file mode 100644 index 0000000..62c9bd9 --- /dev/null +++ b/lib_dec/core_dec_init.c @@ -0,0 +1,786 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include +#include "prot_fx.h" +#include "basop_util.h" +#include "rom_com_fx.h" +#include "options.h" +#include "stl.h" +#include "cnst_fx.h" /* for MIN_CNG_LEV */ + +/*-----------------------------------------------------------------------* + * open_decoder_LPD() + * + * Initialization of state variables + *-----------------------------------------------------------------------*/ + +void open_decoder_LPD( Decoder_State_fx *st, Word32 bit_rate, Word16 bandwidth_mode ) +{ + Word16 i; + Word16 mem_syn_r_size_new; + Word16 mem_syn_r_size_old; + Word16 fscaleFB; + + + + st->total_brate_fx = bit_rate; + st->fscale_old = st->fscale; + st->sr_core = getCoreSamplerateMode2(st->total_brate_fx, bandwidth_mode, st->rf_flag); + st->fscale = sr2fscale(st->sr_core); + fscaleFB = sr2fscale(st->output_Fs_fx); + + /* initializing variables for frame lengths etc. right in the beginning */ + st->L_frame_fx = extract_l(Mult_32_16(st->sr_core , 0x0290)); + st->L_frameTCX = extract_l(Mult_32_16(st->output_Fs_fx , 0x0290)); + + IF (st->ini_frame_fx == 0) + { + st->last_L_frame_fx = st->L_frame_past = st->L_frame_fx; + move16(); + move16(); + st->L_frameTCX_past = st->L_frameTCX; + move16(); + } + + st->tcxonly = getTcxonly(st->total_brate_fx); + move16(); + + /* the TD TCX PLC in MODE1 still runs with 80ms subframes */ + st->nb_subfr = NB_SUBFR; + move16(); + test(); + test(); + test(); + test(); + if ( (EQ_16(st->L_frame_fx,L_FRAME16k)&&LE_32(st->total_brate_fx,32000))|| + (st->tcxonly != 0 && (EQ_32(st->sr_core,32000) || EQ_32(st->sr_core,16000)) ) + ) + { + st->nb_subfr = NB_SUBFR16k; + move16(); + } + + /* (float)st->L_frame/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->total_brate_fx */ + st->bits_frame = extract_l(L_shr(Mpy_32_16_1( L_shl(st->total_brate_fx, 1) , 20972), 6)); /* 20972 = 0.01 * 64 * 32768 */ + + assert(FSCALE_DENOM == 512); + assert(st->fscale == 2 * st->L_frame_fx); /* this assumption is true if operated in 20ms frames with FSCALE_DENOM == 512, which is the current default */ + assert(st->bits_frame == (int)( (float)st->L_frame_fx/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->total_brate_fx/100.0f + 0.49f )); + + st->TcxBandwidth = getTcxBandwidth(bandwidth_mode); + st->narrowBand = 0; + move16(); + if (EQ_16(bandwidth_mode, NB)) + { + st->narrowBand = 1; + move16(); + } + + st->pit_res_max = initPitchLagParameters(st->sr_core, &st->pit_min, &st->pit_fr1, &st->pit_fr1b, &st->pit_fr2, &st->pit_max); + IF ( st->ini_frame_fx == 0) + { + st->pit_res_max_past = st->pit_res_max; + } + i = mult_r(st->L_frameTCX, getInvFrameLen(st->L_frame_fx)); + st->pit_max_TCX = extract_l(L_shr(L_mult(st->pit_max, i), 7)); + st->pit_min_TCX = extract_l(L_shr(L_mult(st->pit_min, i), 7)); + + /*Preemphasis param*/ + st->preemph_fac = PREEMPH_FAC_SWB; /*SWB*/ move16(); + IF ( LT_16(st->fscale, (16000*FSCALE_DENOM)/12800)) + { + st->preemph_fac = PREEMPH_FAC; /*WB*/ move16(); + } + ELSE if ( LT_16(st->fscale, (24000*FSCALE_DENOM)/12800)) + { + st->preemph_fac = PREEMPH_FAC_16k; /*WB*/ move16(); + } + + st->gamma = GAMMA1; + move16(); + st->inv_gamma = GAMMA1_INV; + move16(); + IF ( EQ_32(st->sr_core, 16000)) + { + st->gamma = GAMMA16k; + move16(); + st->inv_gamma = GAMMA16k_INV; + move16(); + } + + /* LPC quantization */ + st-> lpcQuantization = 0; + move16(); + test(); + if( st->tcxonly == 0 && LE_32(st->sr_core, 16000)) + { + st->lpcQuantization = 1; + } + + st->numlpc = 2; + move16(); + if ( st->tcxonly==0 ) + { + st->numlpc = 1; + move16(); + } + + /* Initialize TBE */ + st->prev_coder_type_fx = GENERIC; + set16_fx( st->prev_lsf_diff_fx,16384,LPC_SHB_ORDER-2 ); + st->prev_tilt_para_fx = 0; + set16_fx( st->cur_sub_Aq_fx, 0, M+1 ); + + /*TCX config*/ + st->tcx_cfg.preemph_fac = st->preemph_fac; + move16(); + st->tcx_cfg.tcx_mdct_window_length_old = st->tcx_cfg.tcx_mdct_window_length; + move16(); + + init_TCX_config( &st->tcx_cfg, st->L_frame_fx, st->fscale, st->L_frameTCX, fscaleFB ); + + IF (st->ini_frame_fx == 0) + { + st->tcx_cfg.tcx_last_overlap_mode = st->tcx_cfg.tcx_curr_overlap_mode = ALDO_WINDOW; + move16(); + move16(); + } + + /* TCX Offset */ + st->tcx_cfg.tcx_offset = shr(st->tcx_cfg.tcx_mdct_window_delay, 1); + st->tcx_cfg.tcx_offsetFB = shr(st->tcx_cfg.tcx_mdct_window_delayFB, 1); + + /* Initialize FAC */ + st->tcx_cfg.lfacNext = sub(st->tcx_cfg.tcx_offset,shr(st->L_frame_fx,2)); + st->tcx_cfg.lfacNextFB = sub(st->tcx_cfg.tcx_offsetFB,shr(st->L_frameTCX,2)); + + /* set number of coded lines */ + st->tcx_cfg.tcx_coded_lines = getNumTcxCodedLines(st->bwidth_fx); + + /* TNS in TCX */ + st->tcx_cfg.pCurrentTnsConfig = NULL; + st->tcx_cfg.fIsTNSAllowed = getTnsAllowed(st->total_brate_fx, st->igf); + + IF (st->tcx_cfg.fIsTNSAllowed != 0) + { + InitTnsConfigs(bwMode2fs[st->bwidth_fx], st->tcx_cfg.tcx_coded_lines, st->tcx_cfg.tnsConfig, st->hIGFDec.infoIGFStopFreq, st->total_brate_fx); + } + + resetTecDec_Fx( &(st->tecDec_fx) ); + + /* Initialize decoder delay */ + /*Constraint for adaptive BPF, otherwise parameter estimation and post-processing not time aligned*/ + if ( st->tcxonly==0 ) + { + assert(0 == (st->tcx_cfg.lfacNext>0 ? st->tcx_cfg.lfacNext : 0) ); + } + + + st->flag_cna = 0; + move16(); + IF( st->ini_frame_fx == 0 ) + { + st->last_flag_cna = 0; + move16(); + } + + /* Static vectors to zero */ + IF (st->ini_frame_fx == 0) + { + + st->last_is_cng = 0; + move16(); + + st->rate_switching_reset = 0; + move16(); + set16_fx(st->old_syn_Overl, 0, L_FRAME32k/2); + + set16_fx(st->syn_Overl_TDAC, 0, L_FRAME32k/2); + set16_fx(st->syn_OverlFB, 0, L_FRAME_MAX/2); + set16_fx(st->syn_Overl_TDACFB, 0, L_FRAME_MAX/2); + + set16_fx(st->syn_Overl, 0, L_FRAME32k/2); + + set16_fx(st->old_synth, 0, OLD_SYNTH_INTERNAL_DEC); + set16_fx( st->synth_history_fx, 0, Lprot48k + L_FRAME_MAX); + + set16_fx(st->syn, 0, M+1); + + set16_fx(st->mem_syn_r, 0, L_SYN_MEM); + + mem_syn_r_size_old = 0; /* just to avoid MSVC warnings */ + mem_syn_r_size_new = 0; /* just to avoid MSVC warnings */ + + st->con_tcx = 0; + } + ELSE + { + /* Reset old_synth in case of core sampling rate switching and codec switching*/ + test(); + IF( (NE_16(st->L_frame_fx, st->last_L_frame_fx))||(EQ_16(st->last_codec_mode,MODE1))) + { + set16_fx(st->old_synth, 0, OLD_SYNTH_INTERNAL_DEC); + } + + /*Size of LPC syn memory*/ + /* 1.25/20.0 = 1.0/16.0 -> shift 4 to the right. */ + mem_syn_r_size_old = shr(st->last_L_frame_fx, 4); + mem_syn_r_size_new = shr(st->L_frame_fx, 4); + + /*Reset LPC mem*/ + test(); + test(); + IF( (NE_16(st->L_frame_fx,st->last_L_frame_fx))||(EQ_16(st->last_core_fx,AMR_WB_CORE)) + || EQ_16(st->last_core_fx,HQ_CORE) ) + { + /*LPC quant. mem*/ + set16_fx(st->mem_MA_fx, 0, M); + IF( EQ_32(st->sr_core,16000)) + { + Copy( GEWB2_Ave_fx, st->mem_AR_fx, M ); + } + ELSE + { + Copy( GEWB_Ave_fx, st->mem_AR_fx, M ); + } + } + + /*Codec switching*/ + IF( EQ_16(st->last_codec_mode,MODE1)) + { + Copy( st->lsp_old_fx, st->lspold_uw, M ); + Copy( st->lsf_old_fx, st->lsfold_uw, M ); + set16_fx( st->syn, 0, M ); + } + IF( EQ_16(st->last_core_fx,AMR_WB_CORE)) + { + st->last_core_fx = ACELP_CORE; + move16(); + st->last_core_bfi = ACELP_CORE; + move16(); + } + + /*Codec switching from ACELP-A */ + test(); + IF( EQ_16(st->last_codec_mode, MODE1)&&EQ_16(st->last_core_fx,ACELP_CORE)) + { + st->last_core_bfi = ACELP_CORE; + move16(); + + /*PLC*/ + IF(st->prev_bfi_fx!=0) + { + PWord16 const *w; + Word16 W1,W2,nz,delay_comp; + + W1 = st->tcx_cfg.tcx_mdct_window_lengthFB; + move16(); + W2 = shr(st->tcx_cfg.tcx_mdct_window_lengthFB,1); + w = st->tcx_cfg.tcx_mdct_windowFB; /*pointer - no need to instrument*/ + + nz = NS2SA_fx2(st->output_Fs_fx, N_ZERO_MDCT_NS); + delay_comp = NS2SA_fx2(st->output_Fs_fx, DELAY_CLDFB_NS); /*CLDFB delay*/ + + Copy(st->fer_samples_fx+delay_comp, st->syn_OverlFB, shr(st->L_frameTCX,1)); + + lerp(st->fer_samples_fx+delay_comp, st->syn_Overl , shr(st->L_frame_fx,1), shr(st->L_frameTCX,1)); /*Q0: ACELP(bfi)->TCX(rect)*/ + + /*old_out needed for MODE1 routine and syn_Overl_TDAC for MODE2 routine*/ + st->Q_old_wtda=-1; + set16_fx(st->old_out_fx, 0, nz); + Copy_Scale_sig(st->fer_samples_fx+delay_comp, st->old_out_fx+nz,W1, st->Q_old_wtda); /*Q-1*/ + + FOR (i=0; i < W2; i++) + { + st->old_out_fx[i+nz] = round_fx(Mpy_32_16_1(L_mult(w[i].v.re,w[i].v.re),st->old_out_fx[i+nz])); + } + FOR ( ; i < W1; i++) + { + st->old_out_fx[i+nz] = round_fx(Mpy_32_16_1(L_mult(w[W2-1-(i-W2)].v.im,w[W2-1-(i-W2)].v.im),st->old_out_fx[i+nz])); + } + set16_fx(&st->old_out_fx[W1+nz], 0, nz); + + lerp(st->old_out_fx , st->old_out_LB_fx , st->L_frame_fx , st->L_frameTCX); + + Copy(st->old_out_fx +nz, st->syn_Overl_TDACFB, shr(st->L_frameTCX,1)); + nz = NS2SA_fx2(st->sr_core, N_ZERO_MDCT_NS); + Copy(st->old_out_LB_fx+nz, st->syn_Overl_TDAC , shr(st->L_frame_fx,1)); + st->Q_old_wtda_LB = st->Q_old_wtda; + } + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_16(st->last_codec_mode,MODE2)&& + NE_16(st->L_frame_fx, st->last_L_frame_fx) && + ( ( EQ_16(st->m_frame_type, SID_FRAME) && GT_16(st->last_core_fx, ACELP_CORE) ) || + ( GT_16(st->last_core_fx, ACELP_CORE) && GT_16(st->core_fx, ACELP_CORE) ) || + st->prev_bfi_fx ) ) + { + lerp(st->old_out_LB_fx, st->old_out_LB_fx, st->L_frame_fx, st->last_L_frame_fx); + } + + /* Rate switching */ + test(); + test(); + test(); + IF( EQ_16(st->last_codec_mode,MODE1)&&EQ_16(st->last_core_fx,HQ_CORE)) + { + /*Codec switching from MDCT */ + + /*Reset of ACELP memories*/ + move16(); + move16(); + st->rate_switching_reset=1; + st->tilt_code_fx = TILT_CODE; + set16_fx(st->old_exc_fx, 0, L_EXC_MEM_DEC); + set16_fx(st->syn, 0, 1+M); + set16_fx(st->mem_syn2_fx, 0, M); + + /*OLA -> zero */ + set16_fx(st->old_syn_Overl, 0, L_FRAME32k/2); /*HQ-CORE(bfi)->TCX don't need it*/ + set16_fx(st->syn_Overl_TDAC, 0, L_FRAME32k/2); /*HQ-CORE(bfi)->TCX don't need it*/ + set16_fx(st->syn_Overl_TDACFB, 0, L_FRAME_MAX/2); /*HQ-CORE(bfi)->TCX don't need it*/ + set16_fx(st->syn_Overl, 0, L_FRAME32k/2); /*HQ-CORE(bfi)->TCX don't need it*/ + + Copy_Scale_sig(st->old_out_fx+NS2SA(st->output_Fs_fx, N_ZERO_MDCT_NS), st->syn_OverlFB, st->tcx_cfg.tcx_mdct_window_lengthFB, negate(add(st->Q_old_wtda, TCX_IMDCT_HEADROOM))); + + move16(); + move16(); + st->tcx_cfg.last_aldo=1; /*It was previously ALDO*/ + st->tcx_cfg.tcx_curr_overlap_mode = ALDO_WINDOW; + /*OLA for MDCT-LB always reset in codec switching cases*/ + set16_fx( st->old_out_LB_fx, 0, st->L_frame_fx ); + move16(); + st->last_core_bfi = TCX_20_CORE; + + st->pfstat.on=0; + move16(); + /* reset CLDFB memories */ + cldfb_reset_memory( st->cldfbAna_fx ); + cldfb_reset_memory( st->cldfbBPF_fx ); + cldfb_reset_memory( st->cldfbSyn_fx ); + } + ELSE IF( (NE_16(st->L_frame_fx,st->last_L_frame_fx))&&(LE_16(st->L_frame_fx,L_FRAME16k))&&(LE_16(st->last_L_frame_fx,L_FRAME16k))) /* Rate switching between 12.8 and 16 kHz*/ + { + /*Interpolation of ACELP memories*/ + + /* convert quantized LSP vector */ + st->rate_switching_reset=lsp_convert_poly_fx( st->lsp_old_fx, st->L_frame_fx, 0 ); + IF( st->tcxonly == 0 ) + { + lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, st->sr_core ); + } + ELSE + { + E_LPC_lsp_lsf_conversion( st->lsp_old_fx, st->lsf_old_fx, M ); + } + E_LPC_f_lsp_a_conversion(st->lsp_old_fx, st->old_Aq_12_8_fx, M); + + + Copy( st->lsp_old_fx, st->lspold_uw, M ); + Copy( st->lsf_old_fx, st->lsfold_uw, M ); + + IF( !st->last_con_tcx ) + { + synth_mem_updt2( st->L_frame_fx, st->last_L_frame_fx, st->old_exc_fx, st->mem_syn_r, st->mem_syn2_fx, NULL, DEC ); + } + + /*mem of deemphasis stayed unchanged.*/ + } + ELSE IF( NE_16(st->L_frame_fx,st->last_L_frame_fx)) /* Rate switching involving TCX only modes */ + { + /*Partial reset of ACELP memories*/ + st->rate_switching_reset = 1; + + /*reset partly some memories*/ + st->tilt_code_fx = TILT_CODE; + IF( !st->last_con_tcx ) + { + set16_fx( st->old_exc_fx, 0, L_EXC_MEM_DEC ); + } + set16_fx( st->old_Aq_12_8_fx, 0, M+1 ); + + /*Resamp others memories*/ + /*Size of LPC syn memory*/ + lerp( st->mem_syn_r+L_SYN_MEM-mem_syn_r_size_old, st->mem_syn_r+L_SYN_MEM-mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old ); + Copy( st->mem_syn_r+L_SYN_MEM-M, st->mem_syn2_fx, M ); + + /*Untouched memories : st->syn */ + } + ELSE IF( !st->tcxonly && EQ_16(st->L_frame_fx,L_FRAME16k)&>_32(st->last_total_brate_fx,ACELP_32k)) + { + lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, st->sr_core ); + } + } + + test(); + test(); + if(EQ_16(st->last_bwidth_fx,NB)&&NE_16(st->bwidth_fx,NB)&&st->ini_frame_fx!=0) + { + st->rate_switching_reset=1; + move16(); + } + + st->old_synth_len = shl(st->L_frame_fx, 1); + st->old_synth_lenFB = shl(st->L_frameTCX, 1); + + /* bass pf reset */ + st->bpf_gain_param = 0; + move16(); + set16_fx( st->pst_old_syn_fx, 0, NBPSF_PIT_MAX ); + + /* Formant postfilter */ + IF ( st->ini_frame_fx==0 ) + { + /*do nothing*/ + } + ELSE IF( EQ_16(st->last_codec_mode,MODE2)) + { + IF (st->tcxonly==0) + { + IF ( st->pfstat.on!=0 ) + { + lerp( st->pfstat.mem_stp+L_SYN_MEM-mem_syn_r_size_old, st->pfstat.mem_stp+L_SYN_MEM-mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old ); + lerp( st->pfstat.mem_pf_in+L_SYN_MEM-mem_syn_r_size_old, st->pfstat.mem_pf_in+L_SYN_MEM-mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old ); + } + ELSE + { + set16_fx( st->pfstat.mem_stp, 0,L_SYN_MEM ); + set16_fx( st->pfstat.mem_pf_in, 0,L_SYN_MEM ); + st->pfstat.reset = 1; + st->pfstat.gain_prec = 16384; + move16(); + } + } + ELSE IF ( st->pfstat.on!=0 ) + { + lerp( st->pfstat.mem_stp+L_SYN_MEM-mem_syn_r_size_old, st->pfstat.mem_stp+L_SYN_MEM-mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old ); + lerp( st->pfstat.mem_pf_in+L_SYN_MEM-mem_syn_r_size_old, st->pfstat.mem_pf_in+L_SYN_MEM-mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old ); + } + } + ELSE + { + /*codec switching*/ + /*reset post-filter except for Narrowband*/ + IF ( NE_32(st->output_Fs_fx,8000)) + { + st->pfstat.reset = 1; + if(st->pfstat.on!=0) + { + st->pfstat.reset = 0; + Scale_sig(st->pfstat.mem_pf_in, L_SUBFR, negate(st->Q_syn)); /* WB post_filter mem */ + Scale_sig(st->pfstat.mem_stp, L_SUBFR, negate(st->Q_syn)); /* WB post_filter mem */ + lerp( st->pfstat.mem_stp+L_SYN_MEM-mem_syn_r_size_old, st->pfstat.mem_stp+L_SYN_MEM-mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old ); + lerp( st->pfstat.mem_pf_in+L_SYN_MEM-mem_syn_r_size_old, st->pfstat.mem_pf_in+L_SYN_MEM-mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old ); + } + } + ELSE{ + Scale_sig(st->pfstat.mem_pf_in, L_SUBFR, negate(st->Q_syn)); /* NB post_filter mem */ + Scale_sig(st->pfstat.mem_res2, DECMEM_RES2, negate(st->Q_syn)); /* NB post_filter mem */ + Scale_sig(st->pfstat.mem_stp, L_SUBFR, negate(st->Q_syn)); /* NB post_filter mem */ + /*feed last value old_synth as it is used for pre-emphasis mem*/ + st->old_synth[st->old_synth_len-1]=st->syn[M]; + move16(); + st->pst_old_syn_fx[NBPSF_PIT_MAX-1]=st->syn[M]; + move16(); + } + } + + /* lsf and lsp initialization */ + IF ( st->ini_frame_fx == 0 ) + { + Copy(st->lsp_old_fx, st->lspold_uw, M); + Copy(st->lsf_old_fx, st->lsfold_uw, M); + + set16_fx(st->lsf_cng, 0, M); + } + + st->seed_tcx_plc = 21845; + move16(); + st->past_gpit = 0; + move16(); + st->past_gcode = L_deposit_l(0); + st->gc_threshold_fx = L_deposit_l(0); + + E_LPC_lsf_lsp_conversion(st->lsf_cng, st->lspold_cng, M); + E_LPC_f_lsp_a_conversion(st->lspold_cng, st->Aq_cng, M); + st->plcBackgroundNoiseUpdated = 0; + move16(); + Copy(st->lsf_old_fx, st->lsf_q_cng, M); + Copy(st->lsf_old_fx, st->old_lsf_q_cng, M); + Copy(st->lsp_old_fx, st->lsp_q_cng, M); + Copy(st->lsp_old_fx, st->old_lsp_q_cng, M); + set16_fx(st->mem_syn_unv_back, 0, M); + + st->last_gain_syn_deemph = 32768/2; + move16(); + st->last_gain_syn_deemph_e = 1; + move16(); + test(); + IF( EQ_16(st->last_codec_mode,MODE1)||st->ini_frame_fx==0) + { + /* this assumes that MODE1 fades out in the frequency domain - + otherwise some data from MODE1 would be needed here */ + st->last_concealed_gain_syn_deemph = 32768/2; + move16(); + st->last_concealed_gain_syn_deemph_e = 1; + move16(); + st->conceal_eof_gain = 32768/2;/*Q14*/ move16(); + + } + + /* Post processing */ + set16_fx(st->mem_Aq,0,NB_SUBFR16k*(M+1)); + st->lp_ener_FER_fx = 15360; + move16(); /*60 in Q8*/ + IF (st->ini_frame_fx == 0) + { + st->prev_bfi_fx = 0; + move16(); + st->last_core_bfi = -1; + move16(); + } + st->prev_old_bfi_fx = 0; + move16(); + + /*st->noise_filling_index = 0;*/ /* not in BASOP */ + + Copy(st->lsf_old_fx, st->lsf_adaptive_mean_fx, M); + Copy(st->lsf_old_fx, st->lsfoldbfi0_fx, M); + Copy(st->lsf_old_fx, st->lsfoldbfi1_fx, M); + + st->clas_dec = UNVOICED_CLAS; + move16(); + move16(); + IF (!st->last_con_tcx) + { + move16(); + st->old_enr_LP = 0; /* LP filter E of last good voiced frame or local LP filter E in TD TCX PLC */ + } + + IF (st->prev_bfi_fx) + { + /* calculate energy at the end of the previous frame */ + test(); + IF( EQ_16(st->core_fx,ACELP_CORE)&&EQ_16(st->last_core_fx,HQ_CORE)) + { + frame_ener_fx( st->output_frame_fx, UNVOICED_CLAS, st->previoussynth_fx, -1, &st->enr_old_fx, 1, 0, 0, 0 ); + } + } + ELSE + { + st->last_good_fx = UNVOICED_CLAS; /* last good received frame for concealment */ move16(); + st->enr_old_fx = L_deposit_l(0); /* energy at the end of the previous frame */ + } + st->Mode2_lp_gainc = L_deposit_l(0); + st->Mode2_lp_gainp = L_deposit_l(0); + + st->prev_widow_left_rect = 0; + move16(); + + st->conCngLevelBackgroundTrace = PLC_MIN_CNG_LEV; /*Q15*/ move16(); + st->conNoiseLevelIndex = PLC_MIN_STAT_BUFF_SIZE-1; + move16(); + st->conCurrLevelIndex = 0; + move16(); + st->conLastFrameLevel = PLC_MIN_CNG_LEV; /*Q15*/ move16(); + set16_fx(st->conNoiseLevelMemory, PLC_MIN_CNG_LEV, PLC_MIN_STAT_BUFF_SIZE); /*Q15*/ + set16_fx(st->conNoiseLevelMemory_e, 0, PLC_MIN_STAT_BUFF_SIZE); + st->conLastFrameLevel_e = 0; + st->conCngLevelBackgroundTrace_e = 0; + + st->cummulative_damping_tcx = 32767/*1.0f Q15*/; + move16(); + st->cummulative_damping = 32767/*1.0f Q15*/; + move16(); + + FOR ( i=0; i<2*NB_SUBFR16k+2; i++ ) + { + st->old_pitch_buf_fx[i] = L_deposit_h(st->pit_min); + } + + FOR ( i=0; i<2*NB_SUBFR16k+2; i++ ) + { + st->mem_pitch_gain[i] = 16384/*1.f Q14*/;/*Q14*/ + } + + + st->old_fpitch = L_deposit_h(st->pit_min); + st->old_fpitchFB = L_deposit_h(st->pit_min_TCX); + + st->rate_switching_init = 1; + move16(); + + st->reset_mem_AR = 0; + move16(); + + /* For phase dispersion */ + st->dm_fx.prev_gain_code = L_deposit_l(0); + set16_fx(st->dm_fx.prev_gain_pit, 0, 6); + st->dm_fx.prev_state = 0; + move16(); + + st->voice_fac = -1; /* purely unvoiced */ move16(); + + /* TCX-LTP */ + st->tcxltp = getTcxLtp(st->sr_core); + move16(); + + test(); + IF ( st->ini_frame_fx == 0 || EQ_16(st->last_codec_mode,MODE1)) + { + st->tcxltp_pitch_int = st->pit_max; + move16(); + st->tcxltp_pitch_fr = 0; + move16(); + st->tcxltp_last_gain_unmodified = 0; + move16(); + IF ( st->ini_frame_fx == 0) + { + set16_fx( st->tcxltp_mem_in, 0, TCXLTP_MAX_DELAY ); + set16_fx( st->tcxltp_mem_out, 0, L_FRAME48k ); + st->tcxltp_pitch_int_post_prev = 0; + move16(); + st->tcxltp_pitch_fr_post_prev = 0; + move16(); + st->tcxltp_gain_post_prev = 0; + move16(); + st->tcxltp_filt_idx_prev = -1; + move16(); + } + } + + /* in floating point implementation, different buffers are used: lp_error_ener <-> pst_lp_ener, mem_error <-> pst_mem_deemp_err */ + st->lp_error_ener = Mpy_32_16_1(L_shl(st->pst_lp_ener_fx, 8), 0x2a86); /* convert from 7Q8 10*log10 -> 15Q16, log2 */ + st->mem_error = L_deposit_l(0); + st->tcx_cfg.ctx_hm = getCtxHm (st->total_brate_fx, st->rf_flag); + st->last_ctx_hm_enabled = 0; + move16(); + + st->tcx_cfg.resq = getResq(st->total_brate_fx); + move16(); + + st->tcx_cfg.sq_rounding = 12288/*0.375f Q15*/; /*deadzone of 1.25->rounding=1-1.25/2 (No deadzone=0.5)*/ move16(); + + st->tcx_lpc_shaped_ari = getTcxLpcShapedAri( + st->total_brate_fx, + bandwidth_mode + ,st->rf_flag + ); + + st->envWeighted = 0; + move16(); + + st->p_bpf_noise_buf = NULL; + if (st->tcxonly == 0) + { + st->p_bpf_noise_buf = st->bpf_noise_buf; + } + + st->tec_tfa = 0; + move16(); + test(); + test(); + if ( EQ_16(bandwidth_mode, SWB)&& + (EQ_32(st->total_brate_fx, ACELP_16k40) || EQ_32(st->total_brate_fx, ACELP_24k40)) ) + { + st->tec_tfa = 1; + move16(); + } + + st->tec_flag = 0; + move16(); + st->tfa_flag = 0; + move16(); + + st->enableGplc = 0; + move16(); + + st->flagGuidedAcelp = 0; + move16(); + st->T0_4th = L_SUBFR; + move16(); + st->guidedT0 = st->T0_4th; + move16(); + test(); + test(); + test(); + + st->enablePlcWaveadjust = 0; + move16(); + IF(GE_32(st->total_brate_fx, 48000)) + { + st->enablePlcWaveadjust = 1; + move16(); + test(); + test(); + test(); + IF (st->ini_frame_fx == 0 || LT_32(st->last_total_brate_fx, HQ_48k)||EQ_16(st->last_codec_mode,MODE1)||st->force_lpd_reset) + { + concealment_init_x( st->L_frameTCX, &st->plcInfo ); + } + } + + /* PLC: [TCX: Tonal Concealment] */ + st->tonalMDCTconceal.nScaleFactors = 0; + move16(); + st->tonalMDCTconceal.nSamples = 0; + move16(); + st->tonalMDCTconceal.lastPcmOut = 0x0; + move16(); + st->tonalMDCTconceal.lastBlockData.tonalConcealmentActive = 0; + move16(); + st->tonalMDCTconceal.lastBlockData.nSamples = 0; + move16(); + + TonalMDCTConceal_Init(&st->tonalMDCTconceal, + st->L_frameTCX, + st->L_frame_fx, + FDNS_NPTS, + &(st->tcx_cfg) + ); + + st->last_tns_active = 0; + st->second_last_tns_active = 0; + st->second_last_core = -1; + st->tcxltp_second_last_pitch = st->old_fpitch; + move16(); + st->tcxltp_third_last_pitch = st->old_fpitch; + move16(); + + move16(); + st->dec_glr = 0; + test(); + test(); + test(); + if( (EQ_32(st->total_brate_fx, 9600))||(EQ_32(st->total_brate_fx,16400))|| + (EQ_32(st->total_brate_fx, 24400))) + { + move16(); + st->dec_glr = 1; + } + move16(); + st->dec_glr_idx = 0; + + st->enableTcxLpc = 1; + st->VAD = 0; + st->old_gaintcx_bfi = 0; + st->old_gaintcx_bfi_e = 0 ; + st->tcx_cfg.na_scale = 32767/*1.0f Q15*/; + st->tcx_hm_LtpPitchLag = -1; + st->tcxltp_gain = 0; + + return; +} + diff --git a/lib_dec/core_dec_reconf.c b/lib_dec/core_dec_reconf.c new file mode 100644 index 0000000..979b5d5 --- /dev/null +++ b/lib_dec/core_dec_reconf.c @@ -0,0 +1,169 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "basop_util.h" +#include "prot_fx.h" +#include "options.h" +#include "stl.h" +#include "rom_com_fx.h" + + +void reconfig_decoder_LPD( Decoder_State_fx *st, Word16 bits_frame, Word16 bandwidth_mode, Word32 bitrate, Word16 L_frame_old) +{ + + + move16(); + st->bits_frame=bits_frame; + + IF (bandwidth_mode==0) + { + move16(); + st->narrowBand = 1; + } + ELSE if (bandwidth_mode>0) + { + move16(); + st->narrowBand = 0; + } + + BITS_ALLOC_init_config_acelp(bitrate, st->narrowBand, st->nb_subfr, &(st->acelp_cfg)); + + /*Configuration of partial copy*/ + st->acelp_cfg_rf.mode_index = 1; + st->acelp_cfg_rf.midLpc = 0; + st->acelp_cfg_rf.midLpc_enable = 0; + st->acelp_cfg_rf.pre_emphasis = 0; + st->acelp_cfg_rf.formant_enh = 1; + st->acelp_cfg_rf.formant_tilt = 1; + st->acelp_cfg_rf.voice_tilt = 1; + st->acelp_cfg_rf.formant_enh_num = FORMANT_SHARPENING_G1; + st->acelp_cfg_rf.formant_enh_den = FORMANT_SHARPENING_G2; + + + st->flag_cna = getCnaPresent(bitrate, bandwidth_mode); + move16(); + + /* TCX-LTP */ + st->tcxltp = getTcxLtp(st->sr_core); + move16(); + + { + Word16 i; + + /*Scale TCX for non-active frames to adjust loudness with ACELP*/ + st->tcx_cfg.na_scale=32767/*1.0f Q15*/; + + test(); + IF ((LT_16(bandwidth_mode,SWB))&&!(st->tcxonly)) + { + Word16 scaleTableSize = sizeof (scaleTcxTable) / sizeof (scaleTcxTable[0]); /* is a constant */ + + FOR (i = 0 ; i < scaleTableSize ; i++) + { + test(); + test(); + IF ( (EQ_16(bandwidth_mode,scaleTcxTable[i].bwmode)) && + (GE_32 (bitrate,scaleTcxTable[i].bitrateFrom) ) && + (LT_32 (bitrate,scaleTcxTable[i].bitrateTo) ) + ) + { + if( st->rf_flag ) + { + i--; + } + st->tcx_cfg.na_scale=scaleTcxTable[i].scale; + BREAK; + } + } + } + } + + /*if its not the first frame resample overlap buffer to new sampling rate */ + IF ( st->ini_frame_fx != 0 ) + { + test(); + test(); + test(); + IF( NE_16 (st->fscale,st->fscale_old) + && ! (st->last_codec_mode == MODE1 + && st->last_core_fx == ACELP_CORE + && st->prev_bfi_fx != 0)) + /* no resempling is needed here when recovering from mode 1 + acelp plc, since the buffers are already sampled with the + correct sampling rate in open_decoder_LPD() */ + { + Word16 newLen; + Word16 oldLen; + + newLen = st->tcx_cfg.tcx_mdct_window_length; + move16(); + oldLen = st->tcx_cfg.tcx_mdct_window_length_old; + move16(); + + test(); + test(); + IF( (st->prev_bfi_fx && EQ_16(st->last_core_bfi,ACELP_CORE))||EQ_16(st->last_core_fx,ACELP_CORE)) + { + newLen = shr(st->L_frame_fx,1); + oldLen = shr(L_frame_old,1); + } + + lerp( st->old_syn_Overl, st->old_syn_Overl, newLen, oldLen ); + lerp( st->syn_Overl, st->syn_Overl, newLen, oldLen ); + + test(); + IF( st->prev_bfi_fx && EQ_16(st->last_core_bfi,ACELP_CORE)) + { + lerp( st->syn_Overl_TDAC, st->syn_Overl_TDAC, newLen, oldLen ); + } + } + + + IF (LE_16(st->L_frame_fx,L_FRAME16k)) + { + IF (LE_16(st->last_L_frame_fx,L_FRAME16k)) + { + IF (NE_16(st->L_frame_fx,st->last_L_frame_fx)) + { + Word16 oldLenClasBuff; + Word16 newLenClasBuff; + IF (GT_16(st->L_frame_fx,st->last_L_frame_fx)) + { + oldLenClasBuff = extract_l(L_shr(Mpy_32_16_1(L_mult0(st->last_L_frame_fx,getInvFrameLen(st->L_frame_fx)/*Q21*/)/*Q21*/,L_SYN_MEM_CLAS_ESTIM/*Q0*/)/*Q6*/,6)/*Q0*/); + + newLenClasBuff = L_SYN_MEM_CLAS_ESTIM; + move16(); + + } + ELSE + { + oldLenClasBuff = L_SYN_MEM_CLAS_ESTIM; + newLenClasBuff = extract_l(L_shr(Mpy_32_16_1(L_mult0(st->L_frame_fx,getInvFrameLen(st->last_L_frame_fx)/*Q21*/)/*Q21*/,L_SYN_MEM_CLAS_ESTIM/*Q0*/)/*Q6*/,6)/*Q0*/); + } + lerp( &st->mem_syn_clas_estim_fx[L_SYN_MEM_CLAS_ESTIM-oldLenClasBuff], &st->mem_syn_clas_estim_fx[L_SYN_MEM_CLAS_ESTIM-newLenClasBuff], newLenClasBuff, oldLenClasBuff ); + } + } + ELSE + { + set16_fx(st->mem_syn_clas_estim_fx, 0, L_SYN_MEM_CLAS_ESTIM); + st->classifier_Q_mem_syn = 0; + move16(); + } + } + } + test(); + test(); + st->enableTcxLpc = (st->numlpc == 1) && (st->lpcQuantization == 1) && (bitrate <= LOWRATE_TCXLPC_MAX_BR || st->rf_flag); + + if (st->ini_frame_fx == 0) + { + st->envWeighted = 0; + } + + + return; +} diff --git a/lib_dec/core_dec_switch.c b/lib_dec/core_dec_switch.c new file mode 100644 index 0000000..97c8e7b --- /dev/null +++ b/lib_dec/core_dec_switch.c @@ -0,0 +1,227 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "basop_util.h" +#include "prot_fx.h" +#include "stl.h" +#include "options.h" +#include "rom_com_fx.h" + + +void mode_switch_decoder_LPD( Decoder_State_fx *st, Word16 bandwidth, Word32 bitrate, Word16 frame_size_index + ) +{ + Word16 fscale, switchWB; + Word32 sr_core; + Word8 bSwitchFromAmrwbIO; + Word16 frame_size; + + + switchWB = 0; + move16(); + bSwitchFromAmrwbIO = 0; + move16(); + + if (EQ_16(st->last_core_fx,AMR_WB_CORE)) + { + bSwitchFromAmrwbIO = 1; + move16(); + } + + sr_core = getCoreSamplerateMode2(bitrate, bandwidth, st->rf_flag); + + fscale = sr2fscale(sr_core); + move16(); + + /* set number of coded lines */ + st->tcx_cfg.tcx_coded_lines = getNumTcxCodedLines(bandwidth); + + test(); + test(); + IF (( (GE_16(bandwidth, WB))&&(EQ_16(fscale,(FSCALE_DENOM*16000)/12800))&&(EQ_16(fscale,st->fscale)))) + { + test(); + test(); + test(); + if ( ((GT_32(bitrate, 32000))&&(st->tcxonly==0))||((LE_32(bitrate,32000))&&(st->tcxonly!=0))) + { + switchWB = 1; + move16(); + } + } + + test(); + if( GT_16(st->last_L_frame_fx,L_FRAME16k)&&LE_32(st->total_brate_fx,ACELP_32k)) + { + switchWB = 1; + move16(); + } + + + st->igf = getIgfPresent(bitrate, bandwidth, st->rf_flag); + + st->hIGFDec.infoIGFStopFreq = -1; + move16(); + IF( st->igf ) + { + /* switch IGF configuration */ + IGFDecSetMode( &st->hIGFDec, st->total_brate_fx, bandwidth, -1, -1, st->rf_flag); + + } + + test(); + test(); + test(); + test(); + IF ( NE_16(fscale, st->fscale)||switchWB!=0||bSwitchFromAmrwbIO!=0||EQ_16(st->last_codec_mode,MODE1)||st->force_lpd_reset) + { + open_decoder_LPD( st, bitrate, bandwidth ); + } + ELSE + { + assert(fscale > (FSCALE_DENOM/2)); + + st->fscale_old = st->fscale; + move16(); + st->fscale = fscale; + move16(); + st->L_frame_fx = extract_l(Mult_32_16(st->sr_core , 0x0290)); + st->L_frameTCX = extract_l(Mult_32_16(st->output_Fs_fx , 0x0290)); + + st->tcx_cfg.ctx_hm = getCtxHm(bitrate, st->rf_flag); + st->tcx_cfg.resq = getResq(bitrate); + move16(); + + st->tcx_lpc_shaped_ari = getTcxLpcShapedAri( + bitrate, + bandwidth + ,st->rf_flag + ); + + st->narrowBand = 0; + move16(); + if ( EQ_16(bandwidth, NB)) + { + st->narrowBand = 1; + move16(); + } + st->TcxBandwidth = getTcxBandwidth(bandwidth); + + st->tcx_cfg.pCurrentTnsConfig = NULL; + st->tcx_cfg.fIsTNSAllowed = getTnsAllowed(bitrate, st->igf ); + move16(); + + IF (st->tcx_cfg.fIsTNSAllowed != 0) + { + InitTnsConfigs(bwMode2fs[bandwidth], st->tcx_cfg.tcx_coded_lines, st->tcx_cfg.tnsConfig, st->hIGFDec.infoIGFStopFreq, st->total_brate_fx); + } + } + + frame_size = FrameSizeConfig[frame_size_index].frame_net_bits; + move16(); + + reconfig_decoder_LPD( st, frame_size, bandwidth, bitrate, st->last_L_frame_fx ); + + test(); + IF (st->envWeighted != 0 && st->enableTcxLpc == 0) + { + Copy(st->lspold_uw, st->lsp_old_fx, M); + Copy(st->lsfold_uw, st->lsf_old_fx, M); + st->envWeighted = 0; + move16(); + } + + /* update PLC LSF memories */ + IF( st->tcxonly == 0 ) + { + lsp2lsf_fx( st->lsp_old_fx, st->lsfoldbfi1_fx, M, extract_l(st->sr_core) ); + } + ELSE + { + E_LPC_lsp_lsf_conversion( st->lsp_old_fx, st->lsfoldbfi1_fx, M ); + } + mvr2r_Word16(st->lsfoldbfi1_fx, st->lsfoldbfi0_fx,M); + mvr2r_Word16(st->lsfoldbfi1_fx, st->lsf_adaptive_mean_fx,M); + + IF( st->igf != 0 ) + { + test(); + test(); + test(); + test(); + test(); + IF( (EQ_16(st->bwidth_fx, WB)&&NE_16(st->last_extl_fx,WB_TBE))|| + (EQ_16(st->bwidth_fx, SWB) && NE_16(st->last_extl_fx, SWB_TBE)) || + (EQ_16(st->bwidth_fx, FB) && NE_16(st->last_extl_fx,FB_TBE)) ) + { + TBEreset_dec_fx(st, st->bwidth_fx); + } + ELSE + { + set16_fx( st->state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + set16_fx( st->state_syn_shbexc_fx, 0, L_SHB_LAHEAD ); + set16_fx( st->mem_stp_swb_fx, 0, LPC_SHB_ORDER ); + set16_fx( st->mem_zero_swb_fx, 0, LPC_SHB_ORDER ); + st->gain_prec_swb_fx = 16384; + move16(); /*Q14 = 1 */ + } + } + + test(); + test(); + IF( (EQ_16(bandwidth, SWB))&& + (EQ_32(st->total_brate_fx, ACELP_16k40) || EQ_32(st->total_brate_fx, ACELP_24k40)) + ) + { + IF (st->tec_tfa == 0) + { + set16_fx(st->tecDec_fx.loBuffer, 0, MAX_TEC_SMOOTHING_DEG); + } + st->tec_tfa = 1; + move16(); + } + ELSE + { + st->tec_tfa = 0; + move16(); + } + + st->tec_flag = 0; + move16(); + st->tfa_flag = 0; + move16(); + + /* needed in decoder to read the bitstream */ + st->enableGplc = 0; + move16(); + test(); + test(); + test(); + test(); + test(); + if( (EQ_16(bandwidth, WB )&&EQ_32(bitrate,24400))|| + (sub(bandwidth, SWB) == 0 && L_sub(bitrate, 24400) == 0 )|| + (sub(bandwidth, FB) == 0 && L_sub(bitrate, 24400) == 0 ) ) + { + st->enableGplc = 1; + move16(); + } + move16(); + st->dec_glr = 0; + test(); + test(); + if( (EQ_32(st->total_brate_fx, 9600))||(EQ_32(st->total_brate_fx,16400))|| + (EQ_32(st->total_brate_fx, 24400))) + { + st->dec_glr = 1; + move16(); + } + move16(); + st->dec_glr_idx = 0; + +} + diff --git a/lib_dec/core_switching_dec_fx.c b/lib_dec/core_switching_dec_fx.c new file mode 100644 index 0000000..cee2189 --- /dev/null +++ b/lib_dec/core_switching_dec_fx.c @@ -0,0 +1,1181 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required for wmc_tool */ +#include "basop_mpy.h" /*required for CodeB_Mpy_32_16()*/ +#include "basop_util.h" /* Function prototypes */ + + +/*---------------------------------------------------------------------* + * bandwidth_switching_detect_fx() + * + * + *---------------------------------------------------------------------*/ + +void bandwidth_switching_detect_fx( + Decoder_State_fx *st_fx /* i/o: encoder state structure */ +) +{ + /* update band-width switching counter */ + test(); + test(); + test(); + IF( GE_16(st_fx->bws_cnt1_fx, N_NS2W_FRAMES)) + { + st_fx->bws_cnt1_fx = 0; + move16(); + } + ELSE IF( GT_32(st_fx->total_brate_fx, ACELP_9k60)&<_32(st_fx->last_core_brate_fx,ACELP_9k60) + && EQ_16(st_fx->bwidth_fx, SWB) && EQ_16(st_fx->last_bwidth_fx, WB) ) + { + st_fx->bws_cnt1_fx = add(st_fx->bws_cnt1_fx,1); + move16(); + } + ELSE IF( st_fx->bws_cnt1_fx > 0 ) + { + IF( LT_16(st_fx->bwidth_fx, st_fx->last_bwidth_fx)) + { + st_fx->bws_cnt_fx = sub( shl(sub(N_NS2W_FRAMES, st_fx->bws_cnt1_fx), 1), 1 ); + move16(); + } + ELSE + { + st_fx->bws_cnt_fx = 0; + move16(); + } + + IF( LT_16(st_fx->bwidth_fx, st_fx->last_bwidth_fx)) + { + st_fx->bws_cnt1_fx = 0; + move16(); + } + ELSE + { + IF(EQ_16(st_fx->bwidth_fx, SWB)) + { + st_fx->bws_cnt1_fx = add(st_fx->bws_cnt1_fx,1); + move16(); + } + ELSE + { + st_fx->bws_cnt1_fx = 0; + move16(); + } + } + } + + /* update band-width switching counter */ + test(); + test(); + test(); + IF( GE_16(st_fx->bws_cnt_fx, N_WS2N_FRAMES)) + { + st_fx->bws_cnt_fx = 0; + move16(); + } + ELSE IF( LT_32(st_fx->total_brate_fx, ACELP_9k60)&>_32(st_fx->last_core_brate_fx,ACELP_9k60) + && LT_16(st_fx->bwidth_fx, st_fx->last_bwidth_fx) && EQ_16(st_fx->bwidth_fx, WB) ) + { + st_fx->bws_cnt_fx = add(st_fx->bws_cnt_fx,1); + move16(); + } + ELSE IF( st_fx->bws_cnt_fx > 0 ) + { + IF( GT_16(st_fx->bwidth_fx, st_fx->last_bwidth_fx)) + { + st_fx->bws_cnt1_fx = shr(sub(N_WS2N_FRAMES, st_fx->bws_cnt_fx), 1); + move16(); + } + ELSE + { + st_fx->bws_cnt1_fx = 0; + move16(); + } + + IF( GT_16(st_fx->bwidth_fx, st_fx->last_bwidth_fx)) + { + st_fx->bws_cnt_fx = 0; + move16(); + } + ELSE + { + IF( EQ_16(st_fx->bwidth_fx, WB)) + { + st_fx->bws_cnt_fx = add(st_fx->bws_cnt_fx,1); + move16(); + } + ELSE + { + st_fx->bws_cnt_fx = 0; + move16(); + } + } + } + + return; +} + +/*---------------------------------------------------------------------* + * Calc_freq_ener() + * + * + *---------------------------------------------------------------------*/ + +static Word32 Calc_freq_ener(Word32 L_tmp, const Word16 Q_syn2) +{ + Word32 enerLL_fx; + Word16 exp, tmp; + IF(L_tmp == 0) + { + enerLL_fx = L_deposit_l(0); + } + ELSE + { + exp = norm_l(L_tmp); + tmp = extract_h(L_shl(L_tmp, exp)); + exp = sub(exp, sub(30,shl(Q_syn2,1))); + + tmp = div_s(16384, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp); /*31-exp*/ + + enerLL_fx = L_shr(L_tmp, sub(sub(31, exp), Q_syn2)); /*st_fx->Q_syn2-1*/ + } + return enerLL_fx; +} + +/*---------------------------------------------------------------------* + * bw_switching_pre_proc_fx() + * + * + *---------------------------------------------------------------------*/ + +void bw_switching_pre_proc_fx( + const Word16 *old_syn_12k8_16k_fx, /* i : ACELP core synthesis at 12.8kHz or 16kHz */ + Decoder_State_fx *st_fx /* i/o: decoder state structure */ +) +{ + Word16 i; + Word16 syn_dct_fx[L_FRAME]; + Word32 L_tmp; + IF( EQ_16(st_fx->core_fx, ACELP_CORE)) + { + /*----------------------------------------------------------------------* + * Calculate tilt of the ACELP core synthesis + *----------------------------------------------------------------------*/ + + st_fx->tilt_wb_fx = round_fx(L_shl(calc_tilt_bwe_fx(old_syn_12k8_16k_fx, -1, st_fx->L_frame_fx), 3)); + + /*-------------------------------------------------------------------------------* + * Calculate frequency energy of 0~3.2kHz and 3.2~6.4kHz the ACELP core synthesis + *-------------------------------------------------------------------------------*/ + + edct_16fx(old_syn_12k8_16k_fx, syn_dct_fx, L_FRAME, 6); + + L_tmp = L_deposit_l(0); + FOR ( i=0; i < L_FRAME/2; i++ ) + { + L_tmp = L_mac0(L_tmp, syn_dct_fx[i], syn_dct_fx[i]); + } + L_tmp = L_shr(L_tmp, 7); /*2*(st_fx->Q_syn2-1)*/ + st_fx->enerLL_fx = Calc_freq_ener(L_tmp, shl(st_fx->Q_syn2,1)); + L_tmp = L_deposit_l(0); + FOR (; iQ_syn2-1)*/ + st_fx->enerLH_fx = Calc_freq_ener(L_tmp, shl(st_fx->Q_syn2,1)); + } + ELSE + { + IF( st_fx->old_is_transient_fx[0] ) + { + L_tmp = L_deposit_l(0); + FOR ( i=0; i<32; i++ ) + { + L_tmp = L_mac0(L_tmp, st_fx->t_audio_q_fx[i], st_fx->t_audio_q_fx[i]); + } + L_tmp = L_shr(L_tmp, 5); /*st_fx->Q_syn2-1*/ + st_fx->enerLL_fx = Calc_freq_ener(L_tmp, shl(st_fx->Q_syn2,1)); + L_tmp = L_deposit_l(0); + FOR (; i<64; i++ ) + { + L_tmp = L_mac0(L_tmp, st_fx->t_audio_q_fx[i], st_fx->t_audio_q_fx[i]); + } + L_tmp = L_shr(L_tmp, 5); /*st_fx->Q_syn2-1*/ + st_fx->enerLH_fx = Calc_freq_ener(L_tmp, shl(st_fx->Q_syn2,1)); + } + ELSE + { + L_tmp = L_deposit_l(0); + FOR ( i=0; i < L_FRAME/2; i++ ) + { + L_tmp = L_mac0(L_tmp, st_fx->t_audio_q_fx[i], st_fx->t_audio_q_fx[i]); + } + L_tmp = L_shr(L_tmp, 7); /*st_fx->Q_syn2-1*/ + st_fx->enerLL_fx = Calc_freq_ener(L_tmp, shl(st_fx->Q_syn2,1)); + L_tmp = L_deposit_l(0); + FOR (; it_audio_q_fx[i], st_fx->t_audio_q_fx[i]); + } + L_tmp = L_shr(L_tmp, 7); /*st_fx->Q_syn2-1*/ + st_fx->enerLH_fx = Calc_freq_ener(L_tmp, shl(st_fx->Q_syn2,1)); + + } + } + + + test(); + test(); + test(); + test(); + test(); + IF( st_fx->last_bwidth_fx == 0 && LE_16(st_fx->extl_fx, SWB_CNG)) + { + st_fx->prev_ener_shb_fx = 0; + move16(); + set16_fx(st_fx->prev_SWB_fenv_fx, 0, SWB_FENV); + } + ELSE if(((EQ_16(st_fx->core_fx, ACELP_CORE)&&EQ_16(st_fx->last_core_fx,HQ_CORE))||(EQ_16(st_fx->core_fx,st_fx->last_core_fx)&&NE_16(st_fx->extl_fx,st_fx->last_extl_fx)))&&GE_16(st_fx->last_bwidth_fx,SWB)) + { + st_fx->attenu_fx = 3277; + move16(); + } + + test(); + test(); + test(); + test(); + IF(EQ_16(st_fx->last_core_fx, HQ_CORE) + || ( EQ_16(st_fx->last_core_fx, ACELP_CORE) + && !(EQ_16(st_fx->last_extl_fx, WB_TBE) || EQ_16(st_fx->last_extl_fx, SWB_TBE) || EQ_16(st_fx->last_extl_fx, FB_TBE) ) && GT_32(st_fx->core_brate_fx, ACELP_8k00) )) + { + st_fx->prev_fractive_fx = 0; + move16(); + } + return; +} + + +/*---------------------------------------------------------------------* +* core_switching_pre_dec_fx() +* +* Preprocessing/preparation for ACELP/HQ core switching +*---------------------------------------------------------------------*/ + +void core_switching_pre_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 output_frame /* i : frame length */ +) +{ + Word16 oldLenClasBuff, newLenClasBuff; + + /* Codec switching */ + IF( EQ_16(st_fx->last_codec_mode,MODE2)) + { + st_fx->mem_deemph_fx = st_fx->syn[M]; + move16(); + set16_fx( st_fx->agc_mem_fx, 0, 2 ); + Scale_sig(&(st_fx->mem_deemph_fx), 1, st_fx->Q_syn); /* Brings mem_deemph to Qsyn */ + + Copy_Scale_sig(st_fx->mem_syn2_fx, st_fx->mem_syn1_fx, M, sub(-1,st_fx->Q_syn)); /*Q-1*/ + + st_fx->bpf_off_fx = 1; + move16(); + Scale_sig(st_fx->pfstat.mem_pf_in, L_SUBFR, st_fx->Q_syn); /* Post_filter mem */ + Scale_sig(st_fx->pfstat.mem_res2, DECMEM_RES2, st_fx->Q_syn); /* NB post_filter mem */ + Scale_sig(st_fx->pfstat.mem_stp, L_SUBFR, st_fx->Q_syn); /* Post_filter mem */ + set16_fx( st_fx->pst_old_syn_fx, 0, NBPSF_PIT_MAX ); /* BPF mem*/ + st_fx->pst_lp_ener_fx = round_fx(L_shl(Mpy_32_16_1(st_fx->lp_error_ener, 0x6054), 2+8)); /* convert from 15Q16, log2 -> 7Q8 10*log10 */ + st_fx->pst_mem_deemp_err_fx = 0; + move16(); + st_fx->psf_lp_noise_fx = round_fx(L_shl(st_fx->lp_noise,1)); + + /* reset old HB synthesis buffer */ + IF( EQ_16(st_fx->last_L_frame_fx,L_FRAME)) + { + st_fx->old_bwe_delay_fx = NS2SA_fx2( st_fx->output_Fs_fx, MAX_DELAY_TBE_NS - DELAY_SWB_TBE_12k8_NS ); + } + ELSE + { + st_fx->old_bwe_delay_fx = NS2SA_fx2( st_fx->output_Fs_fx, MAX_DELAY_TBE_NS - DELAY_SWB_TBE_16k_NS ); + } + set16_fx( st_fx->hb_prev_synth_buffer_fx, 0, NS2SA(48000, DELAY_BWE_TOTAL_NS) ); + st_fx->prev_hb_synth_fx_exp = 31; + move16(); + + /* reset upd_cnt */ + st_fx->upd_cnt_fx = MAX_UPD_CNT; + move16(); + st_fx->igf = 0; + move16(); + + IF( NE_16(st_fx->last_core_fx,ACELP_CORE)) + { + /* reset BWE memories */ + set16_fx( st_fx->old_bwe_exc_fx, 0, PIT16k_MAX*2 ); + st_fx->bwe_non_lin_prev_scale_fx = L_deposit_l(0); + } + + IF( GE_32(st_fx->output_Fs_fx,16000)) + { + hf_synth_reset_fx( &st_fx->seed2_fx, st_fx->mem_hf_fx, st_fx->mem_syn_hf_fx, st_fx->mem_hp400_fx, st_fx->mem_hp_interp_fx, st_fx->delay_syn_hf_fx ); + } + set16_fx( st_fx->old_syn_12k8_16k_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) ); + + set32_fx( st_fx->prev_env_fx, 0, SFM_N_WB ); + set32_fx( st_fx->prev_normq_fx, 0, SFM_N_WB ); + + set32_fx( st_fx->last_ni_gain_fx, 0, BANDS_MAX ); + set16_fx( st_fx->last_env_fx, 0, BANDS_MAX ); + st_fx->last_max_pos_pulse_fx = 0; + move16(); + + IF( GT_32(st_fx->output_Fs_fx,16000)) + { + set32_fx( st_fx->prev_coeff_out_fx, 0, L_HQ_WB_BWE ); + } + + /* pre-echo */ + st_fx->pastpre_fx = 0; + move16(); + /* reset the GSC pre echo energy threshold in case of switching */ + st_fx->Last_frame_ener_fx = MAX_32; + move32(); + + test(); + IF( EQ_16(st_fx->last_core_fx,TCX_20_CORE)||EQ_16(st_fx->last_core_fx,TCX_10_CORE)) + { + st_fx->last_core_fx = HQ_CORE; + move16(); + Copy( st_fx->FBTCXdelayBuf, st_fx->prev_synth_buffer_fx, NS2SA(st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS)); + set32_fx( st_fx->last_ni_gain_fx, 0, BANDS_MAX ); + set16_fx( st_fx->last_env_fx, 0, BANDS_MAX ); + st_fx->last_max_pos_pulse_fx = 0; + move16(); + + set16_fx( st_fx->prev_SWB_peak_pos_fx, 0, SPT_SHORTEN_SBNUM ); + st_fx->prev_frm_hfe2_fx = 0; + move16(); + st_fx->prev_stab_hfe2_fx = 0; + move16(); + } + + IF(st_fx->prev_bfi_fx!=0) + { + Word16 delay_comp; + + /*switch off Hq Voicing as it was not uodated in MODE2*/ + st_fx->oldHqVoicing_fx=0; + st_fx->HqVoicing_fx=0; + move16(); + + delay_comp = NS2SA_fx2(st_fx->output_Fs_fx, DELAY_CLDFB_NS); + + IF( !st_fx->last_con_tcx && st_fx->last_core_bfi == ACELP_CORE && EQ_16(st_fx->core_fx,HQ_CORE)) + { + + Word16 i, no_col; + Word32 *realBuffer[CLDFB_NO_COL_MAX], *imagBuffer[CLDFB_NO_COL_MAX]; + Word32 realBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], imagBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + CLDFB_SCALE_FACTOR scaleFactor; + Word32 workBuffer[128*3]; + + FOR( i=0; icldfbAna_fx->no_col, idiv1616(sub(add(delay_comp, st_fx->cldfbAna_fx->no_channels),1) , st_fx->cldfbAna_fx->no_channels)); + + /* CLDFB analysis of the synthesis at internal sampling rate */ + cldfb_save_memory( st_fx->cldfbAna_fx ); + cldfbAnalysisFiltering( st_fx->cldfbAna_fx, realBuffer, imagBuffer, &scaleFactor, st_fx->syn_Overl, 0, no_col, workBuffer); + cldfb_restore_memory( st_fx->cldfbAna_fx ); + + scaleFactor.hb_scale = scaleFactor.lb_scale; + move16(); + + /* CLDFB synthesis of the combined signal */ + cldfb_save_memory( st_fx->cldfbSyn_fx ); + cldfbSynthesisFiltering(st_fx->cldfbSyn_fx, realBuffer, imagBuffer, &scaleFactor, st_fx->fer_samples_fx, 0, no_col, workBuffer); + cldfb_restore_memory( st_fx->cldfbSyn_fx ); + } + + IF( !st_fx->last_con_tcx && st_fx->last_core_bfi == ACELP_CORE && EQ_16(st_fx->core_fx,HQ_CORE)) + { + lerp(st_fx->syn_Overl, st_fx->fer_samples_fx+delay_comp,shr(st_fx->output_frame_fx,1), shr(st_fx->last_L_frame_fx,1)); + /*Set to zero the remaining part*/ + set16_fx( st_fx->fer_samples_fx+delay_comp+shr(st_fx->output_frame_fx,1), 0, shr(st_fx->output_frame_fx,1)-delay_comp); + } + } + + st_fx->use_acelp_preq = 0; + move16(); + st_fx->reset_mem_AR=0; + move16(); + + } + + /*FEC*/ + IF( LE_16(st_fx->L_frame_fx,L_FRAME16k)) + { + test(); + IF( LE_16(st_fx->last_L_frame_fx,L_FRAME16k)&&NE_16(st_fx->core_fx,HQ_CORE)) + { + IF( NE_16(st_fx->L_frame_fx,st_fx->last_L_frame_fx)) + { + IF (GT_16(st_fx->L_frame_fx,st_fx->last_L_frame_fx)) + { + oldLenClasBuff = extract_l(L_shr(Mpy_32_16_1(L_mult0(st_fx->last_L_frame_fx,getInvFrameLen(st_fx->L_frame_fx)/*Q21*/)/*Q21*/,L_SYN_MEM_CLAS_ESTIM/*Q0*/)/*Q6*/,6)/*Q0*/); + newLenClasBuff = L_SYN_MEM_CLAS_ESTIM; + move16(); + } + ELSE + { + oldLenClasBuff = L_SYN_MEM_CLAS_ESTIM; + move16(); + newLenClasBuff = extract_l(L_shr(Mpy_32_16_1(L_mult0(st_fx->L_frame_fx,getInvFrameLen(st_fx->last_L_frame_fx)/*Q21*/)/*Q21*/,L_SYN_MEM_CLAS_ESTIM/*Q0*/)/*Q6*/,6)/*Q0*/); + } + lerp( &st_fx->mem_syn_clas_estim_fx[L_SYN_MEM_CLAS_ESTIM-oldLenClasBuff], &st_fx->mem_syn_clas_estim_fx[L_SYN_MEM_CLAS_ESTIM-newLenClasBuff], newLenClasBuff, oldLenClasBuff ); + } + } + ELSE + { + set16_fx( st_fx->mem_syn_clas_estim_fx, 0,L_SYN_MEM_CLAS_ESTIM ); + st_fx->classifier_Q_mem_syn = 0; + move16(); + } + } + + /* Here we only handle cases where last_ppp and last_nelp not updated when coming from CodecB or other cores + within ACELP_CORE if switching from another bitarate to vbr, last_ppp and last_nelp is always updated in the previous frame */ + test(); + test(); + IF( EQ_16(st_fx->core_fx, ACELP_CORE)&&(NE_16(st_fx->last_core_fx,ACELP_CORE)||EQ_16(st_fx->last_codec_mode,MODE2))) + { + st_fx->last_ppp_mode_dec_fx = 0; + move16(); + st_fx->last_nelp_mode_dec_fx =0; + move16(); + } + + test(); + test(); + test(); + IF( EQ_16(st_fx->core_fx, ACELP_CORE)&&(NE_16(st_fx->last_core_fx,ACELP_CORE)||EQ_16(st_fx->last_codec_mode,MODE2)||LE_32(st_fx->last_total_brate_fx,PPP_NELP_2k80))) + { + st_fx->act_count_fx = 3; + move16(); + st_fx->uv_count_fx = 0; + move16(); + } + + test(); + test(); + IF( (EQ_16(st_fx->core_fx,ACELP_CORE)||EQ_16(st_fx->core_fx,AMR_WB_CORE))&&EQ_16(st_fx->last_core_fx,HQ_CORE)) + { + IF(EQ_16(st_fx->L_frame_fx, L_FRAME16k)) + { + Copy( TRWB2_Ave_fx, st_fx->lsf_old_fx, M ); + Copy( TRWB2_Ave_fx, st_fx->lsfoldbfi1_fx, M ); + Copy( TRWB2_Ave_fx, st_fx->lsfoldbfi0_fx, M ); + Copy( TRWB2_Ave_fx, st_fx->lsf_adaptive_mean_fx, M ); + lsf2lsp_fx( st_fx->lsf_old_fx, st_fx->lsp_old_fx, M, INT_FS_16k ); + } + ELSE + { + Copy( TRWB_Ave_fx, st_fx->lsf_old_fx, M ); /* init of LSP */ + Copy( TRWB_Ave_fx, st_fx->lsfoldbfi1_fx, M ); + Copy( TRWB_Ave_fx, st_fx->lsfoldbfi0_fx, M ); + Copy( TRWB_Ave_fx, st_fx->lsf_adaptive_mean_fx, M ); + lsf2lsp_fx( st_fx->lsf_old_fx, st_fx->lsp_old_fx, M, INT_FS_FX ); + } + + set16_fx( st_fx->agc_mem_fx, 0, 2 ); + st_fx->mem_deemph_fx = 0; + move16(); + IF( !st_fx->last_con_tcx ) + { + set16_fx( st_fx->mem_syn2_fx, 0, M ); + } + set16_fx( st_fx->mem_syn1_fx, 0, M ); + st_fx->bwe_non_lin_prev_scale_fx = 0; + move16(); + + /* Reset ACELP parameters */ + set16_fx( st_fx->mem_MA_fx,0, M ); + IF( EQ_32(st_fx->sr_core,16000)) + { + Copy( GEWB2_Ave_fx, st_fx->mem_AR_fx, M ); + } + ELSE + { + Copy( GEWB_Ave_fx, st_fx->mem_AR_fx, M ); + } + st_fx->tilt_code_fx = 0; + move16(); + st_fx->gc_threshold_fx = 0; + move16(); + st_fx->dm_fx.prev_gain_code = L_deposit_l(0); + set16_fx(st_fx->dm_fx.prev_gain_pit, 0, 6); + st_fx->dm_fx.prev_state = 0; + move16(); + + st_fx->last_coder_type_fx = GENERIC; + move16(); + + frame_ener_fx( output_frame, UNVOICED_CLAS, st_fx->previoussynth_fx, -1, &st_fx->enr_old_fx, 1, 0, 0, 0 ); + st_fx->lp_gainp_fx = 0; + move16(); + + /* the sqrt below needs to be changed to use basop Sqrt16 */ + /*st_fx->lp_gainc_fx = (float)sqrt( st_fx->lp_ener_fx ); */ + IF( st_fx->lp_ener_fx != 0 ) + { + Word32 L_tmp; + Word16 tmp, exp; + exp = norm_l(st_fx->lp_ener_fx); /* In Q6 */ + tmp = extract_h(L_shl(st_fx->lp_ener_fx, exp)); + exp = sub(exp, 30-6); + + tmp = div_s(16384, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp); + + st_fx->lp_gainc_fx = round_fx(L_shl(L_tmp, sub(exp, 12))); /* In Q3 */ + } + + + st_fx->last_voice_factor_fx = 0; + move16(); + st_fx->Last_GSC_noisy_speech_flag_fx = 0; + move16(); + + /* reset CLDFB memories */ + cldfb_reset_memory( st_fx->cldfbAna_fx ); + cldfb_reset_memory( st_fx->cldfbBPF_fx ); + cldfb_reset_memory( st_fx->cldfbSyn_fx ); + + /* reset TBE memories */ + test(); + IF (!st_fx->last_con_tcx) + { + set16_fx(st_fx->old_exc_fx,0, L_EXC_MEM_DEC ); + } + ELSE IF (LT_16(st_fx->L_frame_fx,L_FRAME16k)) + { + /* resample from 16kHz to 12.8kHZ */ + synth_mem_updt2( st_fx->L_frame_fx, L_FRAME16k, st_fx->old_exc_fx, st_fx->mem_syn_r, st_fx->mem_syn2_fx, NULL, DEC ); + } + + set16_fx( st_fx->old_bwe_exc_fx, 0, PIT16k_MAX*2 ); + + IF( GE_32(st_fx->output_Fs_fx, 16000L)) + { + hf_synth_reset_fx( &st_fx->seed2_fx, st_fx->mem_hf_fx, st_fx->mem_syn_hf_fx, st_fx->mem_hp400_fx, st_fx->mem_hp_interp_fx, st_fx->delay_syn_hf_fx ); + } + set16_fx( st_fx->old_syn_12k8_16k_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) ); + } + + test(); + test(); + IF( EQ_16(st_fx->core_fx,HQ_CORE)&&(EQ_16(st_fx->last_core_fx,ACELP_CORE)||st_fx->last_core_fx==AMR_WB_CORE)) + { + set32_fx( st_fx->prev_env_fx, 0, SFM_N_WB ); + set32_fx( st_fx->prev_normq_fx, 0, SFM_N_WB ); + + set32_fx( st_fx->last_ni_gain_fx, 0, BANDS_MAX ); + set16_fx( st_fx->last_env_fx, 0, BANDS_MAX ); + st_fx->last_max_pos_pulse_fx = 0; + + set16_fx( st_fx->prev_SWB_peak_pos_fx, 0, SPT_SHORTEN_SBNUM ); + st_fx->prev_frm_hfe2_fx = 0; + st_fx->prev_stab_hfe2_fx = 0; + + IF( GT_32(st_fx->output_Fs_fx,16000)) + { + set32_fx( st_fx->prev_coeff_out_fx, 0, L_HQ_WB_BWE ); + } + + set16_fx( st_fx->old_out_fx, 0, output_frame ); + st_fx->Q_old_wtda_LB = 15; + st_fx->Q_old_wtda = 15; + } + + /* handle switching cases where preecho_sb was not called in the last frame (memory not up to date) */ + st_fx->pastpre_fx--; + IF( st_fx->pastpre_fx <= 0 ) + { + reset_preecho_dec_fx( st_fx ); + } + + IF( EQ_32(st_fx->core_brate_fx,FRAME_NO_DATA)) + { + st_fx->VAD = 0; + move16(); + st_fx->m_frame_type = ZERO_FRAME; + move16(); + } + ELSE IF( LE_32(st_fx->core_brate_fx,SID_2k40)) + { + st_fx->VAD = 0; + move16(); + st_fx->m_frame_type = SID_FRAME; + move16(); + } + ELSE + { + st_fx->VAD = 1; + move16(); + st_fx->m_frame_type = ACTIVE_FRAME; + move16(); + } + + /*switch on CNA on active frames*/ + test(); + test(); + test(); + test(); + IF( NE_16(st_fx->core_fx,AMR_WB_CORE)&&st_fx->VAD&&LE_32(st_fx->total_brate_fx,CNA_MAX_BRATE)) + { + st_fx->flag_cna = 1; + move16(); + } + ELSE IF( EQ_16(st_fx->core_fx,AMR_WB_CORE)&&st_fx->VAD&&LE_32(st_fx->total_brate_fx,ACELP_8k85)) + { + st_fx->flag_cna = 1; + move16(); + } + ELSE IF( st_fx->VAD || ( EQ_16(st_fx->cng_type_fx,FD_CNG)&&EQ_16(st_fx->L_frame_fx,L_FRAME16k))) + { + st_fx->flag_cna = 0; + move16(); + } + + if( EQ_16(st_fx->core_fx,AMR_WB_CORE)) + { + st_fx->cng_type_fx = LP_CNG; + move16(); + } + + test(); + test(); + test(); + test(); + IF( st_fx->hFdCngDec_fx && ((NE_16(st_fx->last_L_frame_fx,st_fx->L_frame_fx))|| + (NE_16(st_fx->hFdCngDec_fx->hFdCngCom->frameSize,st_fx->L_frame_fx)) || + st_fx->ini_frame_fx == 0 || NE_16(st_fx->bwidth_fx, st_fx->last_bwidth_fx) )) + { + + IF( NE_16(st_fx->core_fx,AMR_WB_CORE)) + { + Word32 tmp; + + tmp = st_fx->total_brate_fx; + move32(); + test(); + if( EQ_16(st_fx->rf_flag,1)&&EQ_32(st_fx->total_brate_fx,ACELP_13k20)) + { + tmp = ACELP_9k60; + move32(); + } + configureFdCngDec(st_fx->hFdCngDec_fx, st_fx->bwidth_fx, tmp, st_fx->L_frame_fx ); + } + ELSE + { + configureFdCngDec(st_fx->hFdCngDec_fx, 1, ACELP_8k00, st_fx->L_frame_fx ); + + if( st_fx->VAD ) + { + st_fx->hFdCngDec_fx->hFdCngCom->CngBitrate = st_fx->total_brate_fx; + move32(); + } + } + + test(); + test(); + IF ( NE_16(st_fx->last_L_frame_fx,st_fx->L_frame_fx)&&LE_16(st_fx->L_frame_fx,L_FRAME16k)&&LE_16(st_fx->last_L_frame_fx,L_FRAME16k)) + { + lerp( st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth2, st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth2, st_fx->L_frame_fx*2, st_fx->last_L_frame_fx*2 ); + test(); + IF( LE_32(st_fx->total_brate_fx,SID_2k40)&&LE_32(st_fx->last_total_brate_fx,SID_2k40)) + { + lerp( st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth, st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth, st_fx->L_frame_fx*2, st_fx->last_L_frame_fx*2 ); + IF( EQ_16(st_fx->L_frame_fx, L_FRAME)) + { + Word16 n; + FOR( n=0; n < st_fx->L_frame_fx*2; n++ ) + { + st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth[n] = mult_r( st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth[n], 20480 ); + } + } + ELSE + { + Word16 n; + FOR( n=0; n < st_fx->L_frame_fx*2; n++ ) + { + st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth[n] = mult_r( shl(st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth[n],1), 26214 ); + } + } + } + } + } + + return; +} + +/*---------------------------------------------------------------------* + * core_switching_post_dec() + * + * Postprocessing for ACELP/HQ core switching + *---------------------------------------------------------------------*/ + +void core_switching_post_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *synth, /* i/o: output synthesis Qsynth */ + const Word16 output_frame, /* i : frame length */ + const Word16 core_switching_flag, /* i : ACELP->HQ switching flag */ + const Word16 coder_type, /* i : ACELP coder type */ + Word16 *Qsynth /* i/o: Scaling of ACELP exit (Q_syn2-1) or HQ exit (Qsynth); changes after this function */ +) +{ + Word16 i, delay_comp, delta; + Word16 tmpF, tmp, Fs_kHz, shift, *ptmp1, *ptmp2; + Word32 L_tmp; + Word16 synth_subfr_out[SWITCH_MAX_GAP], synth_subfr_bwe[SWITCH_MAX_GAP]; + Word16 mem_synth[NS2SA(16000, DELAY_CLDFB_NS)+2]; + Word16 Qtmp; + Word16 Qsubfr; + + /* Rescale synthesis in Q0 to avoid multiple rescaling after */ + tmp = Find_Max_Norm16(synth,output_frame); + Scale_sig(synth,output_frame,tmp); + *Qsynth=add(*Qsynth,tmp); + + test(); + IF( EQ_16(st_fx->core_fx, ACELP_CORE)&&st_fx->bfi_fx) + { + acelp_core_switch_dec_bfi_fx( st_fx, st_fx->fer_samples_fx, coder_type ); /*the output at Q0*/ + } + + /* set multiplication factor according to the sampling rate */ + tmp = extract_l(L_shr(st_fx->output_Fs_fx,13)); + Fs_kHz = shl(add(tmp,1),3); + + delta = 1; + move16(); + if ( GE_16(output_frame, L_FRAME16k)) + { + delta = shr(Fs_kHz, 3); + } + + /* set delay compensation between HQ synthesis and ACELP synthesis */ + delay_comp = i_mult2(delta, HQ_DELAY_COMP); + + IF( EQ_16(st_fx->core_fx, HQ_CORE)) + { + st_fx->use_acelp_preq = 0; + move16(); + /* rescaling to the min exp of the 2 */ + /* Qtmp=s_min(*Qsynth,st_fx->Q_old_postdec); + Scale_sig(synth, output_frame, sub(Qtmp,*Qsynth)); + Scale_sig(st_fx->delay_buf_out_fx, delay_comp, sub(Qtmp,st_fx->Q_old_postdec));*/ + + st_fx->mem_deemph_old_syn_fx = 0; + move16(); + + test(); + test(); + test(); + IF ( core_switching_flag && EQ_16(st_fx->last_L_frame_fx, st_fx->last_L_frame_ori_fx)&&(EQ_16(st_fx->last_core_fx,ACELP_CORE)||EQ_16(st_fx->last_core_fx,AMR_WB_CORE))) + { + acelp_core_switch_dec_fx( st_fx, synth_subfr_out, synth_subfr_bwe, output_frame, core_switching_flag, mem_synth, &Qsubfr ); + } + test(); + test(); + IF( core_switching_flag && EQ_16(st_fx->last_core_fx, HQ_CORE)&&st_fx->prev_bfi_fx) + { + Copy( st_fx->delay_buf_out_fx, synth_subfr_out, delay_comp ); + Qsubfr=st_fx->Q_old_postdec; + } + + /* delay HQ synthesis to synchronize with ACELP synthesis */ + /* rescaling to the min exp of the 2 */ + Qtmp=s_min(*Qsynth,st_fx->Q_old_postdec); + Scale_sig(synth, output_frame, sub(Qtmp,*Qsynth)); + *Qsynth=Qtmp; + move16(); + Scale_sig(st_fx->delay_buf_out_fx, delay_comp, sub(Qtmp,st_fx->Q_old_postdec)); + st_fx->Q_old_postdec=Qtmp; + move16(); + + Copy( synth, &synth[delay_comp], output_frame); + Copy( st_fx->delay_buf_out_fx, synth, delay_comp ); + Copy( &synth[output_frame], st_fx->delay_buf_out_fx, delay_comp ); + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF ( core_switching_flag && EQ_16(st_fx->last_L_frame_fx, st_fx->last_L_frame_ori_fx)&&(EQ_16(st_fx->last_core_fx,ACELP_CORE)||EQ_16(st_fx->last_core_fx,AMR_WB_CORE))) + { + /* mem_over_hp_fx : Qsubfr */ + core_switching_OLA_fx( mem_synth, st_fx->last_L_frame_fx, st_fx->output_Fs_fx, synth, synth_subfr_out, synth_subfr_bwe, output_frame, st_fx->bwidth_fx, Qsynth, &Qsubfr ); + } + ELSE IF ( core_switching_flag && EQ_16(st_fx->last_core_fx, HQ_CORE)&&st_fx->prev_bfi_fx) /* HQ | ACELP | TRANSITION with ACELP frame lost */ + { + /* Overlapp between old->out (stocked in st_fx->fer_samples)and good HQ frame on L/2 */ + ptmp1 = &synth[delay_comp]; + shift = i_mult2(Fs_kHz, 10); + tmp = i_mult2(delta,shr(N16_CORE_SW,1)); + + Scale_sig(st_fx->fer_samples_fx, output_frame, *Qsynth); + ptmp2 = &st_fx->fer_samples_fx[tmp]; + tmp = div_s(1, shift); /*Q15*/ + tmpF = 0; + move16(); + + FOR( i=0; icore_fx, HQ_CORE)&&(EQ_16(st_fx->last_core_fx,ACELP_CORE)||EQ_16(st_fx->last_core_fx,AMR_WB_CORE))) /* ACELP | TRANSITION | HQ with TRANSITION lost */ + || (core_switching_flag && st_fx->prev_bfi_fx && NE_16(st_fx->last_L_frame_fx, st_fx->last_L_frame_ori_fx) ) ) + { + /* Overlapp between CELP estimation (BFI) and good HQ frame on L/2 */ + shift = i_mult2(Fs_kHz, 10); + tmp = div_s(1, shift); /*Q15*/ + tmpF = 0; + move16(); + ptmp1 = synth; + Scale_sig(st_fx->fer_samples_fx, output_frame, *Qsynth); + ptmp2 = st_fx->fer_samples_fx; + FOR( i=0; ibwe_non_lin_prev_scale_fx = L_deposit_l(0); + IF ( !(EQ_16(inner_frame_tbl[st_fx->bwidth_fx], L_FRAME16k)&&EQ_32(st_fx->core_brate_fx,HQ_32k))) + { + set32_fx( st_fx->prev_env_fx, 0, SFM_N_WB ); + set32_fx( st_fx->prev_normq_fx, 0, SFM_N_WB ); + } + Copy_Scale_sig( synth, st_fx->previoussynth_fx, output_frame, negate(*Qsynth) ); /*scaling of st_fx->previoussynth_fx set at Q0*/ + + /*Set post-filtering flag to zero*/ + st_fx->pfstat.on = 0; + move16(); + } + ELSE + { + IF ( EQ_16(st_fx->last_core_fx, HQ_CORE)) /* MDCT to ACELP transition */ + { + Qtmp = s_min(s_min(*Qsynth, st_fx->Q_old_postdec), st_fx->Q_old_wtda); + + Scale_sig(synth, output_frame, sub(Qtmp,*Qsynth)); + Scale_sig(st_fx->delay_buf_out_fx, delay_comp, sub(Qtmp,st_fx->Q_old_postdec)); + Scale_sig(st_fx->old_out_fx, L_FRAME48k, sub(Qtmp, st_fx->Q_old_wtda)); + *Qsynth = Qtmp; + move16(); + st_fx->Q_old_postdec=Qtmp; + move16(); + st_fx->Q_old_wtda=Qtmp; + move16(); + + Copy( st_fx->delay_buf_out_fx, synth, delay_comp ); /* copy the HQ/ACELP delay synchroniation buffer at the beginning of ACELP frame */ + + tmp = i_mult2(delta, N_ZERO_8); + shift = i_mult2(Fs_kHz, 3); + test(); + IF( st_fx->prev_bfi_fx && st_fx->HqVoicing_fx ) + { + Copy_Scale_sig( st_fx->fer_samples_fx, &st_fx->old_out_fx[tmp], shift, *Qsynth ); + } + + ptmp2 = &st_fx->old_out_fx[tmp]; + tmp = div_s(1, shift); + ptmp1 = &synth[delay_comp]; + tmpF = 0; + move16(); + FOR( i=0; idelay_buf_out_fx, 0, HQ_DELTA_MAX*HQ_DELAY_COMP ); + st_fx->oldHqVoicing_fx = 0; + move16(); + + set16_fx(st_fx->prev_SWB_peak_pos_fx, 0, SPT_SHORTEN_SBNUM); + st_fx->prev_frm_hfe2_fx = 0; + move16(); + st_fx->prev_stab_hfe2_fx = 0; + move16(); + } + + /* reset SWB BWE buffers */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF(st_fx->bws_cnt_fx == 0 || (st_fx->bws_cnt_fx > 0 && NE_16(coder_type, INACTIVE)&&NE_16(coder_type,AUDIO))) + { + st_fx->attenu_fx = 3277; + move16(); + } + + IF( ( NE_16(st_fx->last_extl_fx, SWB_BWE)&&EQ_16(st_fx->extl_fx,SWB_BWE))||(NE_16(st_fx->last_extl_fx,FB_BWE)&&EQ_16(st_fx->extl_fx,FB_BWE))|| + ((EQ_16(st_fx->last_core_fx, HQ_CORE) || EQ_16(st_fx->last_extl_fx, SWB_TBE) ) && st_fx->extl_fx < 0 && NE_16(st_fx->core_fx, HQ_CORE) ) + || (EQ_16(st_fx->last_core_fx,ACELP_CORE) && EQ_16(st_fx->core_fx,ACELP_CORE) + && ((NE_16(st_fx->prev_coder_type_fx,INACTIVE) && EQ_16(coder_type,INACTIVE) ) || (NE_16(st_fx->prev_coder_type_fx,AUDIO) && EQ_16(coder_type,AUDIO) )) + && st_fx->bws_cnt_fx > 0) + ) + { + set16_fx( st_fx->L_old_wtda_swb_fx, 0, output_frame ); + st_fx->old_wtda_swb_fx_exp = 0; + move16(); + if( NE_16(st_fx->last_extl_fx, WB_BWE)) + { + st_fx->prev_mode_fx = NORMAL; + move16(); + } + + st_fx->prev_Energy_fx = 0; + move16(); + st_fx->prev_L_swb_norm_fx = 8; + move16(); + st_fx->prev_frica_flag_fx = 0; + move16(); + set16_fx( st_fx->mem_imdct_fx, 0, L_FRAME48k ); + st_fx->prev_td_energy_fx = 0; + move16(); + st_fx->prev_weight_fx = 6554; + move16(); /*0.2 in Q15*/ + st_fx->prev_fb_ener_adjust_fx = 0; + move16(); + } + + /* reset WB BWE buffers */ + test(); + IF( NE_16(st_fx->last_extl_fx, WB_BWE)&&EQ_16(st_fx->extl_fx,WB_BWE)) + { + set16_fx(st_fx->L_old_wtda_swb_fx, 0, output_frame); + + test(); + if ( NE_16(st_fx->last_extl_fx, SWB_BWE)&&NE_16(st_fx->last_extl_fx,FB_BWE)) + { + st_fx->prev_mode_fx = NORMAL; + move16(); + } + st_fx->prev_Energy_wb_fx = 0; + move16(); + st_fx->prev_L_swb_norm_fx = 8; + move16(); + set16_fx( st_fx->mem_imdct_fx, 0, L_FRAME48k ); + st_fx->prev_flag_fx = 0; + move16(); + } + + /* reset SWB TBE buffers */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( (( EQ_16(st_fx->extl_fx, SWB_TBE)||EQ_16(st_fx->extl_fx,FB_TBE)||EQ_16(st_fx->extl_fx,SWB_CNG))&& + ( NE_16(st_fx->L_frame_fx, st_fx->last_L_frame_fx) || ( NE_16(st_fx->last_extl_fx, SWB_TBE) && NE_16(st_fx->last_extl_fx, FB_TBE) ) || EQ_16(st_fx->last_core_fx, HQ_CORE) )) || + ( LT_16(st_fx->bwidth_fx, st_fx->last_bwidth_fx) && NE_16(st_fx->last_extl_fx, SWB_TBE) ) || st_fx->old_ppp_mode_fx + || ((EQ_16(st_fx->prev_coder_type_fx, AUDIO) || EQ_16(st_fx->prev_coder_type_fx, INACTIVE) ) && st_fx->bws_cnt_fx > 0) + || (st_fx->bws_cnt_fx == 0 && EQ_16(st_fx->prev_bws_cnt_fx, N_WS2N_FRAMES)) ) + { + swb_tbe_reset_fx( st_fx->mem_csfilt_fx, st_fx->mem_genSHBexc_filt_down_shb_fx, st_fx->state_lpc_syn_fx, + st_fx->syn_overlap_fx, st_fx->state_syn_shbexc_fx, &(st_fx->tbe_demph_fx), &(st_fx->tbe_premph_fx) + ,st_fx->mem_stp_swb_fx, &(st_fx->gain_prec_swb_fx) ); + + set16_fx( st_fx->GainShape_Delay, 0, NUM_SHB_SUBFR/2 ); + swb_tbe_reset_synth_fx( st_fx->genSHBsynth_Hilbert_Mem_fx, st_fx->genSHBsynth_state_lsyn_filt_shb_local_fx ); + + IF( EQ_16(output_frame, L_FRAME16k)) + { + /* reset in case that SWB TBE layer is transmitted, but the output is 16kHz sampled */ + set16_fx( st_fx->mem_resamp_HB_32k_fx, 0, 2*ALLPASSSECTIONS_STEEP+1 ); + } + set16_fx(st_fx->int_3_over_2_tbemem_dec_fx, 0, INTERP_3_2_MEM_LEN); + } + ELSE IF( ( EQ_16(st_fx->extl_fx, SWB_TBE)||EQ_16(st_fx->extl_fx,FB_TBE))&& + ( NE_32(st_fx->last_total_brate_fx, st_fx->total_brate_fx) || NE_16(st_fx->last_bwidth_fx, st_fx->bwidth_fx) || + NE_16(st_fx->last_codec_mode, MODE1) || NE_16(st_fx->rf_flag, st_fx->rf_flag_last) ) ) + { + set16_fx( st_fx->state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + set16_fx( st_fx->state_syn_shbexc_fx, 0, L_SHB_LAHEAD ); + set16_fx( st_fx->mem_stp_swb_fx, 0, LPC_SHB_ORDER ); + set16_fx( st_fx->mem_zero_swb_fx, 0, LPC_SHB_ORDER ); + st_fx->gain_prec_swb_fx = 16384; + move16(); /*Q14 = 1 */ + } + + /* Interp_3_2 CNG buffers reset */ + test(); + test(); + test(); + IF(EQ_32(st_fx->output_Fs_fx,48000)&&((GT_32(st_fx->last_core_brate_fx,SID_2k40))&&(EQ_32(st_fx->core_brate_fx,FRAME_NO_DATA)||EQ_32(st_fx->core_brate_fx,SID_2k40)))) + { + set16_fx( st_fx->interpol_3_2_cng_dec_fx, 0, INTERP_3_2_MEM_LEN ); + } + + /* reset FB TBE buffers */ + test(); + test(); + IF( EQ_16(st_fx->extl_fx, FB_TBE)&&(NE_16(st_fx->last_extl_fx,FB_TBE)||NE_16(st_fx->L_frame_fx,st_fx->last_L_frame_fx))) + { + set16_fx( st_fx->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + st_fx->fb_tbe_demph_fx = 0; + fb_tbe_reset_synth_fx( st_fx->fbbwe_hpf_mem_fx, st_fx->fbbwe_hpf_mem_fx_Q,&st_fx->prev_fbbwe_ratio_fx ); + } + + /* reset WB TBE buffers */ + test(); + IF( NE_16(st_fx->last_extl_fx, WB_TBE)&&EQ_16(st_fx->extl_fx,WB_TBE)) + { + wb_tbe_extras_reset_fx( st_fx->mem_genSHBexc_filt_down_wb2_fx, st_fx->mem_genSHBexc_filt_down_wb3_fx ); + wb_tbe_extras_reset_synth_fx( st_fx->state_lsyn_filt_shb_fx, st_fx->state_lsyn_filt_dwn_shb_fx, st_fx->state_32and48k_WB_upsample_fx, st_fx->mem_resamp_HB_fx ); + + set16_fx( st_fx->state_syn_shbexc_fx, 0, L_SHB_LAHEAD / 4 ); + set16_fx( st_fx->syn_overlap_fx, 0, L_SHB_LAHEAD ); + set32_fx( st_fx->mem_csfilt_fx, 0, 2 ); + } + + return; +} + +/*---------------------------------------------------------------------* +* core_switching_hq_prepare_dec() +* +* Preprocessing in the first HQ frame after ACELP frame +* - modify bit allocation for HQ core by removing CELP subframe budget +*---------------------------------------------------------------------*/ + +void core_switching_hq_prepare_dec_fx( + Decoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *num_bits, /* i/o: bit budget update */ + const Word16 output_frame /* i : output frame length */ +) +{ + Word32 cbrate; + + test(); + IF( EQ_16(st_fx->last_core_fx, HQ_CORE)&&st_fx->prev_bfi_fx) + { + Copy_Scale_sig( st_fx->old_out_fx, st_fx->fer_samples_fx, output_frame, negate(st_fx->Q_old_wtda) ); /*Q0*/ + } + + /* set switching frame bit-rate */ + IF( EQ_16(st_fx->last_L_frame_fx, L_FRAME)) + { + cbrate = L_add(st_fx->core_brate_fx, 0); + if( GT_32(st_fx->core_brate_fx, ACELP_24k40)) + { + cbrate = L_add(ACELP_24k40, 0); + } + + /* subtract ACELP switching frame bits */ + if( GE_32(st_fx->core_brate_fx, ACELP_11k60)) + { + (*num_bits) = sub((*num_bits), 1); /* LP_FLAG bit */ + } + *num_bits = sub( (*num_bits), ACB_bits_tbl[BIT_ALLOC_IDX_fx(cbrate, GENERIC, 0, 0)] ); /* pitch bits*/ + *num_bits = sub( (*num_bits), gain_bits_tbl[BIT_ALLOC_IDX_fx(cbrate, TRANSITION, 0, 0)] ); /* gain bits */ + *num_bits = sub( (*num_bits), FCB_bits_tbl[BIT_ALLOC_IDX_fx(cbrate, GENERIC, 0, 0)] ); /* FCB bits */ + } + ELSE /* L_frame_fx == L_FRAME16k */ + { + IF( LE_32(st_fx->core_brate_fx, ACELP_8k00)) + { + cbrate = L_add(ACELP_8k00, 0); + } + ELSE IF( LE_32(st_fx->core_brate_fx, ACELP_14k80)) + { + cbrate = L_add(ACELP_14k80, 0); + } + ELSE + { + cbrate = L_min(st_fx->core_brate_fx, ACELP_22k60); + } + + /* subtract ACELP switching frame bits */ + if( GE_32(st_fx->core_brate_fx, ACELP_11k60)) + { + (*num_bits) = sub((*num_bits), 1); /* LP_FLAG bit */ + } + *num_bits = sub((*num_bits), ACB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(cbrate, GENERIC, 0, 0)]); /* pitch bits*/ + *num_bits = sub((*num_bits), gain_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(cbrate, GENERIC, 0, 0)]); /* gain bits */ + *num_bits = sub((*num_bits), FCB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(cbrate, GENERIC, 0, 0)]); /* FCB bits */ + } + + /* subtract BWE bits */ + test(); + test(); + IF( !( ( EQ_16(inner_frame_tbl_fx[st_fx->bwidth_fx], L_FRAME16k)&&EQ_16(st_fx->last_L_frame_fx,L_FRAME16k))||EQ_16(inner_frame_tbl_fx[st_fx->bwidth_fx],L_FRAME8k))) + { + *num_bits = sub((*num_bits), (NOOFGAINBITS1 + AUDIODELAYBITS)); + } + + /* reset state of old_out if switching */ + set16_fx( st_fx->old_out_fx, 0, output_frame ); + + return; + +} diff --git a/lib_dec/d_gain2p.c b/lib_dec/d_gain2p.c new file mode 100644 index 0000000..b0b0ab4 --- /dev/null +++ b/lib_dec/d_gain2p.c @@ -0,0 +1,406 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*-------------------------------------------------------------------* + * Decoding of pitch and codebook gains (see q_gain2_plus.c) * + *-------------------------------------------------------------------*/ +#include +#include +#include "prot_fx.h" +#include "basop_util.h" +#include "stl.h" +#include "rom_com_fx.h" + + +/********************* + * private functions * + *********************/ +static Word32 calc_gcode0( + Word16 *gcode0, + Word16 *exp_gcode0 +) +{ + Word32 L_tmp; + + /*gcode0 = (float)pow(10.0,(gcode0)*0.05);*/ /* predicted gain */ + + L_tmp = L_mult(*gcode0, 5443/*0.166096f Q15*/); + *exp_gcode0 = add(1,extract_l(L_shr(L_tmp, 24))); + L_tmp = L_lshl(L_tmp, 7); + L_tmp = L_and(0x7FFFFFFF, L_tmp); + + L_tmp = Pow2(30,round_fx(L_tmp)); + *gcode0 = round_fx(L_tmp); + + return L_tmp; +} + +static Word32 calc_gain_code(Word16 g_code, Word16 gcode0, Word16 exp_gcode0) +{ + Word32 L_tmp; + + L_tmp = L_mult(g_code, gcode0); /* Q11*Q15 -> Q27 */ + exp_gcode0 = add(exp_gcode0,-11); + L_tmp = L_shl(L_tmp, exp_gcode0); /* Q27 -> Q16 */ + + + return L_tmp; +} + +/*--------------------------------------------------------------------------* +* Mode2_gain_dec_mless +* +* Decoding of pitch and codebook gains without updating long term energies +*-------------------------------------------------------------------------*/ + +static void Mode2_gain_dec_mless( + Word16 index, /* i : Quantization index vector Q0 */ + Word16 *code, /* i : algebraic code excitation Q9 */ + Word16 lcode, /* i : Subframe size Q0 */ + Word16 *gain_pit, /* o : Quantized pitch gain 1Q14 */ + Word32 *gain_code, /* o : Quantized codebook gain Q16 */ + Word16 mean_ener, /* i : mean_ener defined in open-loop Q8 */ + Word16 *past_gpit, /* i/o: past gain of pitch 1Q14 */ + Word32 *past_gcode, /* i/o: past energy of code Q16 */ + Word16 *gain_inov, /* o : unscaled innovation gain 3Q12 */ + Word16 coder_type /* i : coder type for number of bits */ +) +{ + + Word16 ener_code; + const Word16 *t_qua_gain; + Word16 exp_L_tmp1; + Word16 gcode0, exp_gcode0; + Word32 L_tmp, L_tmp1; + + + + /**gain_inov = 1.0f / (float)sqrt( ( dot_product( code, code, lcode ) + 0.01f ) / lcode);*/ + L_tmp = calc_gain_inov(code, lcode, &L_tmp1, &exp_L_tmp1); + move16(); + *gain_inov = round_fx(L_shl(L_tmp, 15-3)); /* gain_inov in Q12 */ + + /*-----------------------------------------------------------------* + * Select the gains quantization table + *-----------------------------------------------------------------*/ + t_qua_gain = E_ROM_qua_gain7b_const; + + if( coder_type == 0 ) + { + t_qua_gain = E_ROM_qua_gain5b_const; + } + + if(EQ_16(coder_type,1)) + { + t_qua_gain = E_ROM_qua_gain6b_const; + } + + /*-----------------------------------------------------------------* + * decode pitch gain + *-----------------------------------------------------------------*/ + *gain_pit = t_qua_gain[index*2]; + + /*-----------------------------------------------------------------* + * calculate the predicted gain code + *-----------------------------------------------------------------*/ + /*ener_code = 10 * log10((dot_product(code, code, lcode) + 0.01) / lcode) */ + L_tmp = BASOP_Util_Log2(L_tmp1); + L_tmp = L_add(L_tmp,L_shl(L_deposit_l(exp_L_tmp1),31-LD_DATA_SCALE)); + + L_tmp = Mpy_32_16_1(L_tmp, 24660/*(10.0f/3.3219280948873623478703194294894f)/4.0f Q15*/); + /* exponent of L_tmp = 6+2 */ + ener_code = round_fx(L_shl(L_tmp, 6+2-7)); /* Q8 */ + + /* predicted codebook gain */ + gcode0 = sub(mean_ener, ener_code); /* Q8 */ + + /*gcode0 = (float)pow(10.0,(gcode0)*0.05);*/ /* predicted gain */ + + calc_gcode0(&gcode0, &exp_gcode0); + + /*-----------------------------------------------------------------* + * decode normalized codebook gain + *-----------------------------------------------------------------*/ + /* *gain_code = t_qua_gain[index*2+1] * gcode0;*/ + + L_tmp = calc_gain_code(t_qua_gain[index*2+1], gcode0, exp_gcode0); + + *gain_code = L_tmp; + *past_gpit = *gain_pit; + /**past_gcode = *gain_code / *gain_inov; */ + /* Q16/Q12 => Q5 */ + L_tmp1 = L_deposit_h(BASOP_Util_Divide3216_Scale(L_tmp,*gain_inov,&exp_L_tmp1)); + *past_gcode = L_shl(L_tmp1,sub(exp_L_tmp1,15-12)); + + + + return; +} + +/*---------------------------------------------------------------------* + * gain_dec_uv + * + * Decoding of pitch and codebook gains for Unvoiced mode + *---------------------------------------------------------------------*/ + +static void gain_dec_uv( + Word16 index, /* i : Quantization index vector Q0 */ + Word16 *code, /* i : algebraic code excitation Q9 */ + Word16 lcode, /* i : Subframe size Q0 */ + Word16 *gain_pit, /* o : Quantized pitch gain 1Q14 */ + Word32 *gain_code, /* o : Quantized codebook gain Q16 */ + Word16 *past_gpit, /* i/o: past gain of pitch 1Q14 */ + Word32 *past_gcode, /* i/o: past energy of code Q16 */ + Word16 *gain_inov /* o : unscaled innovation gain 3Q12 */ +) +{ + Word16 i, exp_L_tmp1; + Word32 L_tmp, L_tmp1; + + + /*-----------------------------------------------------------------* + * Innovation energy (without gain) + *-----------------------------------------------------------------*/ + /* *gain_inov = 1.0f / (float)sqrt( ( dot_product( code, code, lcode ) + 0.01f ) / lcode );*/ + L_tmp = calc_gain_inov(code, lcode, &L_tmp1, &exp_L_tmp1); + move16(); + *gain_inov = round_fx(L_shl(L_tmp, 15-3)); /* gain_inov in Q12 */ + + /*-----------------------------------------------------------------* + * Decode pitch gain + *-----------------------------------------------------------------*/ + *gain_pit = 0; + move16(); + + /*-----------------------------------------------------------------* + * Decode codebook gain + *-----------------------------------------------------------------*/ + /* *gain_code= (float)pow(10.f,(((index*1.9f)-30.f)/20.f));*/ + L_tmp = L_mac(-167197708l/*-0.166096*30.0f Q25*/,shl(index, 16-7), 10341/*0.166096f*1.9f Q15*/); + i = add(1,extract_l(L_shr(L_tmp, 25))); + L_tmp = L_lshl(L_tmp, 6); + L_tmp = L_and(0x7FFFFFFF, L_tmp); + + L_tmp = Pow2(30,round_fx(L_tmp)); + L_tmp = L_shl(L_tmp, i-(31-16)); /* Q16 */ + + + /*-----------------------------------------------------------------* + * past gains for error concealment + *-----------------------------------------------------------------*/ + *past_gpit = *gain_pit; + *past_gcode = L_tmp; + L_tmp = L_shl(Mpy_32_16_1(L_tmp, *gain_inov), 3); /* Q16*Q12 -> Q13 -> Q16 */ + *gain_code = L_tmp; + move32(); + + + return; +} + +/*---------------------------------------------------------------------* + * gain_dec_gacelp_uv + * + * Decoding of pitch and codebook gains for Unvoiced mode + *---------------------------------------------------------------------*/ + +static void gain_dec_gacelp_uv( + Word16 index, /* i : Quantization index vector Q0 */ + Word16 *code, /* i : algebraic code excitation Q9 */ + Word16 *code2, /* i : algebraic code excitation Q9 */ + Word16 mean_ener, /* i : Q8 */ + Word16 lcode, /* i : Subframe size Q0 */ + Word16 *gain_pit, /* o : Quantized pitch gain 1Q14 */ + Word32 *gain_code, /* o : Quantized codebook gain Q16 */ + Word32 *gain_code2, /* o : Quantized codebook gain Q16 */ + Word16 *past_gpit, /* i/o: past gain of pitch 1Q14 */ + Word32 *past_gcode, /* i/o: past energy of code Q16 */ + Word16 *gain_inov /* o : unscaled innovation gain 3Q12 */ +) +{ + Word16 i, exp_L_tmp1; + Word16 exp_gcode; + Word16 g_code; + Word32 L_tmp, L_tmp1; + Word32 pred_nrg_frame; + Word16 exp_gcode2, g_code2, norm_code2; + Word16 index2, s; + + + + + /* pred_nrg_frame = (float)pow(10.0,mean_ener/20.0); */ + L_tmp = L_mult(mean_ener, 10885/*0.166096f * 2 Q15*/); /* 6Q25 */ + pred_nrg_frame = BASOP_Util_InvLog2(L_sub(L_tmp, 503316480l/*15.f Q25*/)); /* 15Q16 */ + + /*-----------------------------------------------------------------* + * Prediction gains + *-----------------------------------------------------------------*/ + /* gain_inov = 1.0f / sqrt((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */ + L_tmp = calc_gain_inov(code, lcode, NULL, NULL); + *gain_inov = round_fx(L_shl(L_tmp, 15-3)); /* gain_inov in Q12 */ + + /* gcode = pred_nrg_frame * (*gain_inov); */ + L_tmp = Mpy_32_16_1(pred_nrg_frame, *gain_inov); /* 18Q13 */ + i = norm_l(L_tmp); + g_code = round_fx(L_shl(L_tmp, i)); + exp_gcode = sub(18, i); + + /* norm_code2 = 1.0f / sqrt((dot_product(code2, code2, lcode) + 0.01f) / lcode); */ + L_tmp = calc_gain_inov(code2, lcode, NULL, NULL); + norm_code2 = round_fx(L_shl(L_tmp, 15-3)); /* Q12 */ + + /* g_code2 = pred_nrg_frame * norm_code2; */ + L_tmp = Mpy_32_16_1(pred_nrg_frame, norm_code2); /* 18Q13 */ + i = norm_l(L_tmp); + g_code2 = round_fx(L_shl(L_tmp, i)); + exp_gcode2 = sub(18, i); + + /*-----------------------------------------------------------------* + * Decode pitch gain + *-----------------------------------------------------------------*/ + *gain_pit = 0; + move16(); + *past_gpit = *gain_pit; + move16(); + + /*-----------------------------------------------------------------* + * past gains for error concealment + *-----------------------------------------------------------------*/ + index2=shr(index,5); + index=s_and(index,0x1F); + + /**gain_code= (float)pow(10.f,(((index*1.25f)-20.f)/20.f))*gcode;*/ + + L_tmp = L_mac(-111465139l/*-0.166096*20.0f Q25*/,shl(index, 16-7), 6803/*0.166096f*1.25f Q15*/); + + i = add(1,extract_l(L_shr(L_tmp, 25))); + L_tmp = L_lshl(L_tmp, 6); + L_tmp = L_and(0x7FFFFFFF, L_tmp); + + L_tmp = Pow2(30,round_fx(L_tmp)); + L_tmp = L_shl(L_tmp, i-(31-16)); /* Q16 */ + + /* *past_gcode = L_tmp * pred_nrg_frame; */ + i = norm_l(L_tmp); + L_tmp1 = L_shl(L_tmp, i); + exp_L_tmp1 = sub(15, i); + + i = norm_l(pred_nrg_frame); + L_tmp1 = Mpy_32_32(L_tmp1, L_shl(pred_nrg_frame, i)); + exp_L_tmp1 = add(exp_L_tmp1, sub(15, i)); + + *past_gcode = L_shl(L_tmp1, sub(exp_L_tmp1, 15)); /* Q16 */ move32(); + + *gain_code = L_shl(Mpy_32_16_1(*past_gcode, *gain_inov), 3); + move32(); + + + L_tmp = Mpy_32_16_1(*gain_code, BASOP_Util_Divide1616_Scale(g_code2, g_code, &s)); + L_tmp = L_shl(L_tmp, sub(sub(add(s, exp_gcode2), exp_gcode), 2)); /* Q16 */ + L_tmp1 = L_add(L_tmp, 0); + FOR (i = 0; i < index2; i++) + { + L_tmp1 = L_add(L_tmp1, L_tmp); + } + *gain_code2 = L_tmp1; + + + return; +} + +/********************* + * public functions * + *********************/ + +void decode_acelp_gains( + Word16 *code, /* i : algebraic code excitation Q9 */ + Word16 gains_mode, + Word16 mean_ener_code, /* i : mean_ener defined in open-loop Q8 */ + Word16 *gain_pit, /* o : Quantized pitch gain 1Q14 */ + Word32 *gain_code, /* o : Quantized codebook gain Q16 */ + Word16 **pt_indice, + Word16 *past_gpit, /* i/o: past gain of pitch 1Q14 */ + Word32 *past_gcode, /* i/o: past energy of code Q16 */ + Word16 *gain_inov, /* o : unscaled innovation gain 3Q12 */ + Word16 L_subfr, /* i : Subframe size Q0 */ + Word16 *code2, /* i : algebraic code excitation Q9 */ + Word32 *gain_code2 /* o : Quantized codebook gain Q16 */ +) +{ + Word16 index = 0; + + + index = **pt_indice; + (*pt_indice)++; + + IF ( s_and(gains_mode > 0,(Word16) LT_16(gains_mode, 4))) + { + /* ACELP gains quantizer (5bits/subfr) */ + Mode2_gain_dec_mless(index, code, L_subfr, gain_pit, gain_code, mean_ener_code, past_gpit, past_gcode, gain_inov, gains_mode-1 ); + } + ELSE IF (s_or((Word16)EQ_16(gains_mode,4),(Word16)EQ_16(gains_mode,5))) + { + /* AMR-WB gains quantizer (6bits/subfr (mode 2) or 7bits/subfr (mode 3)) */ + assert(0); + } + ELSE IF ( EQ_16(gains_mode,6)) + { + /* UV gains quantizer (6bits/subfr) */ + gain_dec_uv( index, code, L_subfr, gain_pit, gain_code, past_gpit, past_gcode, gain_inov ); + } + ELSE IF (EQ_16(gains_mode,7)) + { + /* GACELP_UV gains quantizer (7=5-2bits/subfr) */ + gain_dec_gacelp_uv( index, code, code2, mean_ener_code, L_subfr, gain_pit, gain_code, gain_code2, past_gpit, past_gcode, gain_inov ); + } + ELSE + { + fprintf(stderr, "invalid gains coding for acelp!\n"); + assert(0); + } + +} + + +/*---------------------------------------------------------------------* + * d_gain_pred : + * + * decode the predicted value for the scaled + * innovation energy in all subframes + *---------------------------------------------------------------------*/ +void d_gain_pred( + Word16 nrg_mode, /* i : NRG moe */ + Word16 *Es_pred, /* o : predicted scaled innovation energy Q8 */ + Word16 **pt_indice /* i/o: pointer to the buffer of indices */ +) +{ + Word16 indice; + + indice = (Word16)**pt_indice; + (*pt_indice)++; + + *Es_pred = 0; + move16(); + + if( EQ_16(nrg_mode,1)) + { + *Es_pred = Es_pred_qua[indice]; + move16(); + } + + if( EQ_16(nrg_mode,2)) + { + *Es_pred = Es_pred_qua_2[indice]; + move16(); + } + + IF( GT_16(nrg_mode,2)) + { + move16(); + *Es_pred= extract_l(L_mac(-335544320l/* -20.f Q24*/, indice, 224/* 1.75f Q7*/)); /*(Q8 - ((Q0*Q7)=Q8))*/ + } + + return; +} diff --git a/lib_dec/dec2t32_fx.c b/lib_dec/dec2t32_fx.c new file mode 100644 index 0000000..80d3966 --- /dev/null +++ b/lib_dec/dec2t32_fx.c @@ -0,0 +1,125 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + + +/*==========================================================================*/ +/* FUNCTION : void dec_acelp_2t32_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : */ +/* * 12 bits algebraic codebook decoder. */ +/* * 2 track x 32 positions per track = 64 samples. */ +/* * 12 bits --> 2 pulses in a frame of 64 samples. */ +/* * All pulses can have two (2) possible amplitudes: +1 or -1. */ +/* * Each pulse can have 32 possible positions. */ +/* * See cod2t32.c for more details of the algebraic code. */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _Word16 i_subfr, i : subframe index */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _Word16 code[] o : algebraic (fixed) codebook excitation Q12 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*==========================================================================*/ + + +void dec_acelp_2t32_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 code[] /* o: algebraic (fixed) codebook excitation */ +) +{ + + Word16 index, i0, i1; + + index = (Word16) get_next_indice_fx( st_fx, 12 ); + move16(); + + set16_fx( code, 0, L_SUBFR ); + + /*------------------------------------------------------------------------------------------* + * decode the positions and signs of pulses and build the codeword + *------------------------------------------------------------------------------------------*/ + + i0 = shl(s_and(shr(index, 6), NB_POS_FCB_2T-1), 1); + + i1 = add(shl(s_and(index, NB_POS_FCB_2T-1), 1), 1); + + + code[i0] = -512; + move16(); + if (s_and(index, 0x800) == 0) + { + code[i0] = 512; + move16(); + } + + code[i1] = -512; + move16(); + if (s_and(index, 0x20) == 0) + { + code[i1] = 512; + move16(); + } + +} + + +/*==========================================================================*/ +/* FUNCTION : void dec_acelp_1t64_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : * 7 bits algebraic codebook. */ +/* * 1 track x 64 positions per track = 64 samples. */ +/* * The pulse can have 64 possible positions and two (2) possible amplitudes: +1 or -1.*/ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _Word16 i_subfr, i : subframe index */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _Word16 code[] o : algebraic (fixed) codebook excitation Q12 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*==========================================================================*/ +void dec_acelp_1t64_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 code[] /* o: algebraic (fixed) codebook excitation Q12*/ +) +{ + Word16 pos,sgn; + + /*-----------------------------------------------------------------* + * decode the positions and signs of pulses and build the codeword + *-----------------------------------------------------------------*/ + pos = (Word16)get_next_indice_fx( st_fx, 7 ); + move16(); + + sgn = -512; + move16(); + IF( GE_16(pos,L_SUBFR)) + { + pos = sub(pos, L_SUBFR); + move16(); + sgn = 512; + move16(); + } + set16_fx(code, 0, L_SUBFR); + code[pos] = sgn; + move16(); + return; + +} diff --git a/lib_dec/dec4t64_fx.c b/lib_dec/dec4t64_fx.c new file mode 100644 index 0000000..40a905a --- /dev/null +++ b/lib_dec/dec4t64_fx.c @@ -0,0 +1,800 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "assert.h" /* Static table prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ +static void add_pulses_fx(const Word16 pos[],const Word16 nb_pulse, const Word16 track,Word16 code[]); +static void dec_1p_N1_fx(const Word32 index, const Word16 N, const Word16 offset, Word16 pos[] ); +static void dec_2p_2N1_fx(const Word32 index, const Word16 N, const Word16 offset, Word16 pos[] ); +static void dec_3p_3N1_fx(const Word32 index, const Word16 N, const Word16 offset, Word16 pos[] ); +static void dec_4p_4N1_fx(const Word32 index, const Word16 N, const Word16 offset, Word16 pos[] ); +static void dec_4p_4N_fx(const Word32 index, const Word16 N, const Word16 offset, Word16 pos[]); +static void dec_5p_5N_fx(const Word32 index,const Word16 N,const Word16 offset,Word16 pos[]); +static void dec_6p_6N2_fx(const Word32 index,const Word16 N,const Word16 offset,Word16 pos[]); +static Word32 fcb_decode_PI_fx(Word32 code_index,Word16 sector_6p[],Word16 pulse_num); + + +/*==========================================================================*/ +/* FUNCTION : void dec_acelp_4t64_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : */ +/* * 20, 36 bits algebraic codebook decoder. */ +/* * 4 tracks x 16 positions per track = 64 samples. */ +/* * 20 bits --> 4 pulses in a frame of 64 samples. */ +/* * 36 bits --> 8 pulses in a frame of 64 samples. */ +/* * All pulses can have two (2) possible amplitudes: +1 or -1. */ +/* * Each pulse can have sixteen (16) possible positions. */ +/* * See cod4t64.c for more details of the algebraic code. */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _Word16 i_subfr i : subframe index */ +/* _Word16 nbbits i : number of bits per codebook */ +/* _Word16 FCB_5Sx4T_fla i : 5Sx4Track flag for PI */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _Word16 code[] o : algebraic (fixed) codebook excitation Q12 */ +/* _Word16 index_buf_4T[] o : 5Sx4Track buffer for PI */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*==========================================================================*/ +void dec_acelp_4t64_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 nbbits, /* i : number of bits per codebook */ + Word16 code[], /* o : algebraic (fixed) codebook excitation Q9*/ + const Word16 Opt_AMR_WB +) +{ + Word16 i, k, pos[7]; + Word32 L_index; + Word32 ind1[NB_TRACK_FCB_4T]; + PulseConfig config; + Word16 indexing_indices[6], wordcnt, bitcnt, index2; + + IF ( !Opt_AMR_WB ) + { + SWITCH (nbbits) + { + case 20: + config.nb_pulse = 4; + move16(); + BREAK; + + case 28: + config.nb_pulse = 6; + move16(); + BREAK; + + case 36: + config.nb_pulse = 8; + move16(); + BREAK; + + case 43: + config.nb_pulse = 10; + move16(); + BREAK; + + case 50: + config.nb_pulse = 12; + move16(); + BREAK; + + case 62: + config.nb_pulse = 16; + move16(); + BREAK; + + case 87: + config.nb_pulse = 26; + move16(); + BREAK; + } + + config.bits = nbbits; + move16(); + config.codetrackpos = TRACKPOS_FIXED_FIRST; + move16(); + + + wordcnt = shr(nbbits, 4); + bitcnt = s_and(nbbits, 15); + FOR ( i = 0; i < wordcnt; i++ ) + { + indexing_indices[i] = get_next_indice_fx( st_fx, 16 ); + move16(); + } + IF ( bitcnt ) + { + indexing_indices[i] = get_next_indice_fx( st_fx, bitcnt ); + move16(); + } + + D_ACELP_indexing( code, config, NB_TRACK_FCB_4T, indexing_indices, &st_fx->BER_detect ); + } + ELSE + { + FOR (i=0; i> N) & 1); */ + i = L_shr(index, N) & 1L; + + if (i != 0) + { + pos1 = add(pos1, NB_POS_FCB_4T); + } + pos[0] = pos1; + move16(); +} +/*-------------------------------------------------------* + * dec_2p_2N1() + * + * Decode 2 pulses with 2*N+1 bits: + *-------------------------------------------------------*/ + +void dec_2p_2N1_fx( + const Word32 index, /* i: quantization index */ + const Word16 N, /* i: nb. of bits */ + const Word16 offset, /* i: pulse position offset */ + Word16 pos[] /* o: pulse position */ +) +{ + + Word16 pos1, pos2, tmp; + Word32 mask, i; + + mask = L_deposit_l(sub(shl(1, N), 1)); /* mask = ((1<> N) & mask) + offset); */ + logic16(); + pos1 = extract_l(L_add((L_shr(index, N) & mask), L_deposit_l(offset))); + + /* i = (index >> (2*N)) & 1; */ + tmp = shl(N, 1); + i = L_and(L_shr(index, tmp), 1L); + + /* pos2 = ((index & mask) + offset); */ + pos2 = add(extract_l(index & mask), offset); + logic16(); + + + IF (LT_16(pos2, pos1)) + { + IF (i != 0) + { + pos1 = add(pos1, NB_POS_FCB_4T); + } + ELSE + { + pos2 = add(pos2, NB_POS_FCB_4T); + } + } + ELSE + { + IF (i != 0) + { + pos1 = add(pos1, NB_POS_FCB_4T); + pos2 = add(pos2, NB_POS_FCB_4T); + } + } + + pos[0] = pos1; + move16(); + pos[1] = pos2; + move16(); + + return; + +} +/*-------------------------------------------------------* +* Dec_3p_3N1 +* +* Decode 3 pulses with 3*N+1 bits: +*-------------------------------------------------------*/ +static void dec_3p_3N1_fx( + const Word32 index, /* i : quantization index */ + const Word16 N, /* i : nb. of bits */ + const Word16 offset, /* i : pulse position offset */ + Word16 pos[] /* o : pulse position */ +) +{ + Word16 j, tmp; + Word32 mask, idx; + + tmp = sub(shl(N, 1), 1); /* mask = ((1<<((2*N)-1))-1); */ + mask = L_sub(L_shl(1L, tmp), 1L); + + idx = L_and(index, mask); + j = offset; + move16(); + tmp = sub(shl(N, 1), 1); + + logic16(); + IF ((L_shr(index, tmp) & 1L) != 0) + { + /* IF (((index >> ((2*N)-1)) & 1) == 1){ */ + j = add(j, shl(1, sub(N, 1))); /* j += (1<<(N-1)); */ + } + dec_2p_2N1_fx(idx, sub(N, 1), j, pos); + + mask = sub(shl(1, add(N, 1)), 1); /* mask = ((1<<(N+1))-1); */ + tmp = shl(N, 1); /* idx = (index >> (2*N)) & mask; */ + idx = L_shr(index, tmp) & mask; + logic16(); + + dec_1p_N1_fx(idx, N, offset, pos + 2); +} + +/*-------------------------------------------------------* + * Dec_4p_4N1 + * + * Decode 4 pulses with 4*N+1 bits: + *-------------------------------------------------------*/ +static void dec_4p_4N1_fx( + const Word32 index, /* i : quantization index */ + const Word16 N, /* i : nb. of bits */ + const Word16 offset, /* i : pulse position offset */ + Word16 pos[] /* o : pulse position */ +) +{ + Word16 j, tmp; + Word32 mask, idx; + + tmp = sub(shl(N, 1), 1); /* mask = ((1<<((2*N)-1))-1); */ + mask = L_sub(L_shl(1L, tmp), 1L); + idx = L_and(index, mask); + j = offset; + move16(); + tmp = sub(shl(N, 1), 1); + + logic16(); + IF((L_shr(index, tmp) & 1L) != 0L) + { + /* (((index >> ((2*N)-1)) & 1) == 1) */ + j = add(j, shl(1, sub(N, 1))); /* j += (1<<(N-1)); */ + } + dec_2p_2N1_fx(idx, sub(N, 1), j, pos); + + + tmp = add(shl(N, 1), 1); /* mask = ((1<<((2*N)+1))-1); */ + mask = L_sub(L_shl(1L, tmp), 1L); + idx = L_shr(index, shl(N, 1)) & mask; + logic16();/* idx = (index >> (2*N)) & mask; */ + dec_2p_2N1_fx(idx, N, offset, pos + 2); /* Dec_2p_2N1(idx, N, offset, pos+2); */ +} + + +/*-------------------------------------------------------* +* Dec_4p_4N +* +* Decode 4 pulses with 4*N bits: +*-------------------------------------------------------*/ +static void dec_4p_4N_fx( + const Word32 index, /* i : quantization index */ + const Word16 N, /* i : nb. of bits */ + const Word16 offset, /* i : pulse position offset */ + Word16 pos[] /* o : pulse position */ +) +{ + Word16 j, n_1, tmp; + + n_1 = sub(N, 1); + j = add(offset, shl(1, n_1)); /* j = offset + (1 << n_1) */ + + tmp = sub(shl(N, 2), 2); + logic16(); + SWITCH (L_shr(index, tmp) & 3) + { + /* ((index >> ((4*N)-2)) & 3) */ + case 0: + tmp = add(shl(n_1, 2), 1); + + logic16(); + IF((L_shr(index, tmp) & 1) == 0) + { + /* (((index >> ((4*n_1)+1)) & 1) == 0) */ + dec_4p_4N1_fx(index, n_1, offset, pos); + } + ELSE + { + dec_4p_4N1_fx(index, n_1, j, pos); + } + BREAK; + case 1: + tmp = add(extract_l(L_shr(L_mult(3, n_1), 1)), 1); /* Dec_1p_N1((index>>((3*n_1)+1)), n_1, offset, pos) */ + dec_1p_N1_fx(L_shr(index, tmp), n_1, offset, pos); + dec_3p_3N1_fx(index, n_1, j, pos + 1); + move16(); + BREAK; + case 2: + tmp = add(shl(n_1, 1), 1); /* Dec_2p_2N1((index>>((2*n_1)+1)), n_1, offset, pos) */ + dec_2p_2N1_fx(L_shr(index, tmp), n_1, offset, pos); + dec_2p_2N1_fx(index, n_1, j, pos + 2); + move16(); + BREAK; + case 3: + tmp = add(n_1, 1); /* Dec_3p_3N1((index>>(n_1+1)), n_1, offset, pos) */ + dec_3p_3N1_fx(L_shr(index, tmp), n_1, offset, pos); + dec_1p_N1_fx(index, n_1, j, pos + 3); + move16(); + BREAK; + } +} + + +/*-------------------------------------------------------* + * Dec_5p_5N + * + * Decode 5 pulses with 5*N bits: + *-------------------------------------------------------*/ +static void dec_5p_5N_fx( + const Word32 index, /* i : quantization index */ + const Word16 N, /* i : nb. of bits */ + const Word16 offset, /* i : pulse position offset */ + Word16 pos[] /* o : pulse position */ +) +{ + Word16 j, n_1, tmp; + Word32 idx; + + n_1 = sub(N, 1); + j = add(offset, shl(1, n_1)); /* j = offset + (1 << n_1); */ + tmp = add(shl(N, 1), 1); /* idx = (index >> ((2*N)+1)); */ + idx = L_shr(index, tmp); + tmp = sub(extract_l(L_shr(L_mult(5, N), 1)), 1); /* ((5*N)-1)) */ + + logic16(); + IF ((L_shr(index, tmp) & 1) == 0) /* ((index >> ((5*N)-1)) & 1) */ + { + dec_3p_3N1_fx(idx, n_1, offset, pos); + dec_2p_2N1_fx(index, N, offset, pos + 3); + move16(); + } + ELSE + { + dec_3p_3N1_fx(idx, n_1, j, pos); + dec_2p_2N1_fx(index, N, offset, pos + 3); + move16(); + } +} + +/*-------------------------------------------------------* + * Dec_6p_6N_2 + * + * Decode 6 pulses with 6*N+2 bits: + *-------------------------------------------------------*/ +static void dec_6p_6N2_fx( + const Word32 index, /* i : quantization index */ + const Word16 N, /* i : nb. of bits */ + const Word16 offset, /* i : pulse position offset */ + Word16 pos[] /* o : pulse position */ +) +{ + Word16 j, n_1, offsetA, offsetB, n_6; + + n_1 = sub(N, 1); + j = add(offset, shl(1, n_1)); /* j = offset + (1 << n_1); */ + n_6 = extract_l(L_mult0(N, 6)); + + /* !! N and n_1 are constants -> it doesn't need to be operated by Basic Operators */ + + offsetA = offsetB = j; + move16(); + logic16(); + IF ((L_shr(index, sub(n_6, 5)) & 1L) == 0) + { + /* IF (((index >> ((6*N)-5)) & 1) == 0) */ + offsetA = offset; + move16(); + } + ELSE + { + offsetB = offset; + move16(); + } + + + logic16(); + SWITCH (L_shr(index, sub(n_6, 4)) & 3) + { + /* (index >> ((6*N)-4)) & 3 */ + case 0: + dec_5p_5N_fx(L_shr(index, N), n_1, offsetA, pos); /* Dec_5p_5N(index>>N, n_1, offsetA, pos); */ + dec_1p_N1_fx(index, n_1, offsetA, pos + 5); + move16(); + BREAK; + case 1: + dec_5p_5N_fx(L_shr(index, N), n_1, offsetA, pos); /* Dec_5p_5N(index>>N, n_1, offsetA, pos); */ + dec_1p_N1_fx(index, n_1, offsetB, pos + 5); + move16(); + BREAK; + case 2: + dec_4p_4N_fx(L_shr(index, add(shl(n_1,1),1)), n_1, offsetA, pos); /* Dec_4p_4N(index>>((2*n_1)+1 ), n_1, offsetA, pos); */ + dec_2p_2N1_fx(index, n_1, offsetB, pos + 4); + move16(); + BREAK; + case 3: + dec_3p_3N1_fx(L_shr(index, add(add(shl(n_1, 1),n_1), 1)), n_1, offset, pos); /* Dec_3p_3N1(index>>((3*n_1)+ 1), n_1, offset, pos); */ + dec_3p_3N1_fx(index, n_1, j, pos + 3); + move16(); + BREAK; + } +} + +static Word32 fcb_decode_class_all_p_fx( /* o: The index of pulse positions */ + Word32 *code_index, /* i: fcb index information */ + Word16 sector_6p_num[], /* o: Number of pulses for each position */ + Word16 pulse_num, /* i: Number of pulses on a track. */ + Word16 *pos_num /* o: Number of positions which have pulses on the track.*/ +) +{ + Word16 i; + Word32 mn9,j,k; + Word16 pulse_pos_num; + Word32 L_tmp, L_tmp1; + FOR (i=1; i<=pulse_num; i++) + { + IF (LT_32((*code_index),PI_offset_fx[pulse_num][i])) + { + BREAK; + } + } + + /* (*code_index) -= PI_offset_fx[pulse_num][i-1];*/ + (*code_index) = L_sub((*code_index),PI_offset_fx[pulse_num][i-1]); + + /*pulse_pos_num = pulse_num - i + 2;*/ + pulse_pos_num = add(sub(pulse_num , i) , 2); + + /* j = (*code_index)>>pulse_pos_num;*/ + j = L_shr((*code_index) , pulse_pos_num); + IF(LT_32(j,PI_select_table_fx[16][pulse_pos_num])) + { + k = L_deposit_l(0); + mn9 = L_add(j, 0); + } + ELSE + { + L_tmp = L_deposit_l(0); + L_tmp1 = L_add(j, 0); + WHILE(GE_32(L_tmp1,PI_select_table_fx[16][pulse_pos_num])) + { + L_tmp = L_add(L_tmp,1); + L_tmp1 = L_sub(L_tmp1,PI_select_table_fx[16][pulse_pos_num]); + } + k = L_add(L_tmp, 0); + mn9 = L_add(L_tmp1, 0); + } + /* mn9 = Mult_32_32(sub(j , k) , PI_select_table_fx[16][pulse_pos_num]);*/ + + test(); + IF ( (LT_16( pulse_pos_num,pulse_num))&&(GT_16(pulse_pos_num,1))) + { + FOR (i=0; i= k; l+=2); + + if (GT_32(k,PI_select_table_fx[L_sub(17,l)][temp])) + { + l = L_sub(l,1); + } + + /* k = PI_select_table_fx[17-l][temp--] - k ;*/ + k = L_sub(PI_select_table_fx[L_sub(17,l)][temp--] , k); + pos_vector[i] = extract_l(L_sub(l,1)); + } + pos_vector[i] = extract_l(L_add(l,k)); + + return; +} + +static Word32 fcb_decode_PI_fx( /* o: return pulse position number */ + Word32 code_index, /* i: fcb index information */ + Word16 sector_6p[], /* o: decoded pulse position */ + Word16 pulse_num /* i: pulse number for the track */ +) +{ + Word16 i,l, j; + Word32 mn9; + Word16 pulse_pos_num; + Word16 sector_6p_temp[7], sector_6p_num_temp[7]; + Word16 *sector_6p_ptr0; + Word16 *sector_6p_ptr1; + + /*get the position number and the pulse number on every position */ + mn9 = fcb_decode_class_all_p_fx(&code_index, sector_6p_num_temp, pulse_num, &pulse_pos_num); + + /* rebuild the vector*/ + /* decode the pulse position not same to the others*/ + fcb_decode_position_fx(mn9, sector_6p_temp, pulse_pos_num); + FOR (i=pulse_pos_num-1; i>=0; i--) + { + /*sector_6p_temp[i] += ((code_index&0x1)<<4) ;*/ + sector_6p_temp[i] = add(sector_6p_temp[i],extract_l(L_shl((code_index&0x1),4))) ; + move16(); + /*code_index = code_index>>1;*/ + code_index = L_shr(code_index , 1); + + } + + /* decode the pulse position maybe some pulse position same to other pulse */ + sector_6p_ptr0 = §or_6p[pulse_num]; + sector_6p_ptr1 = §or_6p_temp[pulse_pos_num]; + FOR (i=0; i +#include +#include +#include "prot_fx.h" +#include "basop_util.h" +#include "rom_com_fx.h" +#include "options.h" +#include "stl.h" + +/* #if defined(_WIN32) && (_MSC_VER <= 1200) /\* disable global optimizations to overcome an internal compiler error *\/ */ +#if defined(_MSC_VER) && (_MSC_VER <= 1200) /* disable global optimizations to overcome an internal compiler error */ +#pragma optimize("g", off) +#endif + +/*-------------------------------------------------------------------* +* decoder_LPD() +* +* Core decoder +*--------------------------------------------------------------------*/ + +void decoder_LPD( + Word16 signal_out[], /* output: signal with LPD delay (7 subfrs) */ + Word16 signal_outFB[], + Word16 *total_nbbits, /* i/o: number of bits / decoded bits */ + Decoder_State_fx *st, + Word16 * bpf_noise_buf, + Word16 bfi, + Word16 *bitsRead, + Word16 *coder_type, + Word16 param[], + Word16 *pitch_buf, + Word16 *voice_factors, + Word16 *ptr_bwe_exc +) +{ + Word16 *param_lpc; + Word16 synth_buf[OLD_SYNTH_SIZE_DEC+L_FRAME_PLUS+M]; + Word16 *synth; + Word16 synth_bufFB[OLD_SYNTH_SIZE_DEC+L_FRAME_PLUS+M]; + Word16 *synthFB; + Word16 lsf[(NB_DIV+1)*M],lsp[(NB_DIV+1)*M],lspmid[M],lsfmid[M]; + Word16 Aq[(NB_SUBFR16k+1)*(M+1)]; /* Dyn RAM: it can be reduced by M+1 if insert branch for nb_subfr==5*/ + Word16 pitch[NB_SUBFR16k]; + Word16 pit_gain[NB_SUBFR16k]; + Word16 i, k, *prm; + Word16 L_frame,nb_subfr; + Word16 L_frameTCX; + Word16 Aind[M+1], lspind[M]; + Word16 tmp_old[M+1], tmp_new[M+1], enr_old, enr_new; + Word16 xspnew_uw[NB_DIV*M], xsfnew_uw[NB_DIV*M]; + Word16 const* xsfBase; /* base for differential XSF coding */ + Word16 past_core_mode; + + Word16 lsf_q_1st_rf[M], lsf_q_rf[M], lsp_q_rf[M]; + Word32 lsp_diff; + Word16 LSF_Q_prediction; + Word16 tcx_last_overlap_mode, tcx_current_overlap_mode; + + st->core_fx = 0; /* to avoid compilation warnings */ + prm = NULL; /* to avoid compilation warnings */ + + /*--------------------------------------------------------------------------------* + * INIT + *--------------------------------------------------------------------------------*/ + + enr_old = 0; + move16(); + enr_new = 0; + move16(); + + LSF_Q_prediction= -1; + move16(); + + param_lpc = param+DEC_NPRM_DIV*NB_DIV; + + past_core_mode = st->last_core_bfi; + move16(); + + test(); + test(); + if(st->use_partial_copy && GE_16(st->rf_frame_type, RF_TCXFD)&&LE_16(st->rf_frame_type,RF_TCXTD2)) + { + bfi = st->bfi_fx; + move16(); + } + + /*Adjust bit per frame*/ + if (bfi == 0) + { + st->bits_frame_core = sub(st->bits_frame, bitsRead[0]); + } + + /* Framing parameters */ + L_frame = st->L_frame_fx; + move16(); + L_frameTCX = st->L_frameTCX; + move16(); + nb_subfr = st->nb_subfr; + move16(); + + + /* Initialize pointers */ + synth = synth_buf + st->old_synth_len; + /*st->old_synth: Q_0*/ + Copy(st->old_synth, synth_buf, st->old_synth_len); + set16_fx(synth, 0, L_FRAME_PLUS + M); + + synthFB = synth_bufFB + st->old_synth_lenFB; + Copy(st->old_synthFB_fx, synth_bufFB, st->old_synth_lenFB); + set16_fx(synthFB, 0, L_FRAME_PLUS + M); + + /*For post-processing (post-filtering+blind BWE)*/ + IF (st->tcxonly==0) + { + /* for bass postfilter */ + set16_fx(pitch, L_SUBFR, nb_subfr); + + set16_fx(pit_gain, 0, nb_subfr); + } + + /* PLC: [Common: Memory update] + * PLC: Update the number of lost frames */ + IF ( bfi != 0) + { + move16(); + st->nbLostCmpt = add(st->nbLostCmpt, 1); + } + + + /*--------------------------------------------------------------------------------* + * BITSTREAM DECODING + *--------------------------------------------------------------------------------*/ + + IF (bfi == 0) + { + /* PLC: [TCX: Tonal Concealment] */ + st->second_last_core = st->last_core_fx; + move16(); + tcx_last_overlap_mode = st->tcx_cfg.tcx_last_overlap_mode; + move16(); + tcx_current_overlap_mode = st->tcx_cfg.tcx_curr_overlap_mode; + move16(); + dec_prm(coder_type, param, param_lpc, total_nbbits, st, L_frame, bitsRead); + IF(!st->rate_switching_init && EQ_16((st->last_codec_mode), MODE2)&&st->BER_detect) + { + *coder_type = st->last_coder_type_fx; + move16(); + st->last_core_fx = st->second_last_core; + move16(); + st->tcx_cfg.tcx_last_overlap_mode = tcx_last_overlap_mode; + move16(); + st->tcx_cfg.tcx_curr_overlap_mode = tcx_current_overlap_mode; + move16(); + st->bfi_fx = 1; + move16(); + bfi = 1; + move16(); + st->flagGuidedAcelp = 0; + move16(); + st->nbLostCmpt++; + move16(); + st->core_brate_fx = st->last_core_brate_fx; + move16(); + st->core_fx = GetPLCModeDecision( st ); + } + } + ELSE + { + + test(); + test(); + IF( st->use_partial_copy && GE_16(st->rf_frame_type, RF_TCXFD)&&LE_16(st->rf_frame_type,RF_TCXTD2)) + { + dec_prm( coder_type, param, param_lpc, total_nbbits, st, L_frame, bitsRead ); + } + + if (GT_16(st->nbLostCmpt, 1)) + { + st->flagGuidedAcelp = 0; + move16(); + } + } + + /* PLC: [Common: mode decision] + * PLC: Decide which Concealment to use. Update pitch lags if needed */ + IF ( bfi!=0 ) + { + st->core_fx = GetPLCModeDecision(st); + } + + IF ( bfi == 0 ) + { + IF( EQ_16(st->prev_bfi_fx, 1)) + { + st->prev_nbLostCmpt = st->nbLostCmpt; + move16(); + } + ELSE + { + st->prev_nbLostCmpt = 0; + move16(); + } + move16(); + st->nbLostCmpt = 0; + } + + /*--------------------------------------------------------------------------------* + * LPC PARAMETERS + *--------------------------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + IF( (bfi == 0 ) || ( bfi != 0 && st->use_partial_copy != 0 && EQ_16(st->rf_frame_type,RF_TCXFD))) + { + test(); + test(); + test(); + test(); + test(); + IF(EQ_16(st->use_partial_copy,1)&&(LT_16(st->rf_frame_type,RF_TCXFD)||GT_16(st->rf_frame_type,RF_TCXTD2))) + { + IF( EQ_16((Word16)st->envWeighted,1)) + { + Copy( st->lspold_uw, st->lsp_old_fx, M ); + Copy( st->lsfold_uw, st->lsf_old_fx, M ); + st->envWeighted = 0; + move16(); + } + + /* first stage VQ, 8 bits; reuse TCX high rate codebook */ + set16_fx(lsf_q_1st_rf, 0, M); + vlpc_1st_dec(param_lpc[0], lsf_q_1st_rf ); + + /* second stage vq */ + /* quantized lsf from two stages */ + /*v_add(lsf_q_1st_rf, lsf_q_diff_cb_8b_rf + M * param_lpc[1], lsf_q_rf, M);*/ + FOR (i=0; isr_core ); + + /* current n-th ACELP frame and its corresponding partial copy */ + /*lsf2lsp( lsf_q_rf, lsp_q_rf, M, st->sr_core );*/ + E_LPC_lsf_lsp_conversion( lsf_q_rf, lsp_q_rf, M ); + + /* copy the old and current lsfs and lsps into the lsf[] and lsp[] buffer for interpolation */ + Copy(st->lsf_old_fx, &lsf[0], M); + Copy(st->lsp_old_fx, &lsp[0], M); + Copy(lsf_q_rf, &lsf[M], M); + Copy(lsp_q_rf, &lsp[M], M); + lsp_diff = 0; + FOR( i=0; i < M; i++ ) + { + lsp_diff = L_add(lsp_diff,(Word32)abs_s(sub(lsp[i+M],lsp[i]))); + } + + IF( EQ_16(st->core_fx,ACELP_CORE)&&EQ_16(st->last_core_fx,ACELP_CORE) + && LT_32(lsp_diff, 52428 )&>_32(lsp_diff,3932)&&EQ_16(st->next_coder_type,GENERIC) + && !st->prev_use_partial_copy && EQ_16(st->last_coder_type_fx,UNVOICED) && GE_16(st->rf_frame_type,RF_GENPRED) ) + { + Copy( &lsp[0], &lsp[M], M ); + } + + /* update mem_MA and mem_AR memories */ + lsf_update_memory( (Word16)st->narrowBand, &lsf[M], st->mem_MA_fx, st->mem_MA_fx, M ); + Copy(&lsf[M], st->mem_AR_fx, M); + + FOR( k=0; knumlpc; ++k ) + { + Copy( &lsp[(k+1)*M], &xspnew_uw[k*M], M ); + Copy( &lsf[(k+1)*M], &xsfnew_uw[k*M], M ); + } + } + ELSE + IF ((st->enableTcxLpc !=0 && NE_16(st->core_fx , ACELP_CORE))||(bfi&&st->use_partial_copy&&st->rf_frame_type==RF_TCXFD)) + { + Word16 tcx_lpc_cdk; + IF(bfi && st->use_partial_copy && EQ_16(st->rf_frame_type, RF_TCXFD)) + { + tcx_lpc_cdk = tcxlpc_get_cdk(GENERIC); + } + ELSE + { + tcx_lpc_cdk = tcxlpc_get_cdk(*coder_type); /* inlined */ + } + + Copy(st->lsf_old_fx, &lsf[0], M); + Copy(st->lsp_old_fx, &lsp[0], M); + + D_lsf_tcxlpc( param_lpc, &lsf[M], lspind, st->narrowBand, tcx_lpc_cdk, st->mem_MA_fx ); + + E_LPC_lsf_lsp_conversion( &lsf[M], &lsp[M], M ); + + lsf_update_memory( (Word16)st->narrowBand, &lsf[M], st->mem_MA_fx, st->mem_MA_fx, M ); + Copy(&lsf[M], st->mem_AR_fx, M); + + st->envWeighted = 1; + move16(); + + E_LPC_lsp_unweight( &lsp[M], xspnew_uw, xsfnew_uw, st->inv_gamma, M ); + } + ELSE + { + + IF (st->envWeighted) + { + Copy(st->lspold_uw, st->lsp_old_fx, M); + Copy(st->lsfold_uw, st->lsf_old_fx, M); + st->envWeighted = 0; + move16(); + } + IF (EQ_16(st->core_fx, TCX_20_CORE)) + { + lpc_unquantize( st, st->lsf_old_fx, st->lsp_old_fx, lsf, lsp, M, st->lpcQuantization, param_lpc, st->numlpc, st->core_fx, + st->mem_MA_fx, st->mem_AR_fx, lspmid, lsfmid, AUDIO, st->acelp_cfg.midLpc, st->narrowBand, &(st->seed_acelp), + st->sr_core, &st->mid_lsf_int_fx, st->prev_bfi_fx, &LSF_Q_prediction, &st->safety_net_fx ); + } + ELSE + { + lpc_unquantize( st, st->lsf_old_fx, st->lsp_old_fx, lsf, lsp, M, st->lpcQuantization, param_lpc, st->numlpc, st->core_fx, + st->mem_MA_fx, st->mem_AR_fx, lspmid, lsfmid, *coder_type, st->acelp_cfg.midLpc, st->narrowBand, &(st->seed_acelp), + st->sr_core, &st->mid_lsf_int_fx, st->prev_bfi_fx, &LSF_Q_prediction, &st->safety_net_fx ); + IF(EQ_16(st->prev_use_partial_copy,1)&&EQ_16(st->last_core_fx,ACELP_CORE)&&EQ_16(st->core_fx,ACELP_CORE) + && GE_16(st->prev_rf_frame_type, RF_GENPRED) && EQ_16(*coder_type,UNVOICED) ) + { + IF ( st->lpcQuantization && st->acelp_cfg.midLpc ) + { + Copy(lspmid, &lsp[0], M ); + Copy(&lsp[M], lspmid, M ); + } + } + } + + FOR(k=0; knumlpc; ++k) + { + Copy(&lsp[(k+1)*M], &xspnew_uw[k*M], M); + Copy(&lsf[(k+1)*M], &xsfnew_uw[k*M], M); + } + } + + /* PLC: [LPD: LPC concealment] + * built the moving average for the LPC concealment */ + + FOR (k=0; knumlpc; k++) + { + FOR (i=0; ilsf_adaptive_mean_fx[i] = add(add(mult_r(st->lsfoldbfi1_fx[i], 10923/*1.0f/3.0f Q15*/), mult_r(st->lsfoldbfi0_fx[i], 10923/*1.0f/3.0f Q15*/)), mult_r(xsfnew_uw[k*M+i], 10923/*1.0f/3.0f Q15*/)); + move16(); + st->lsfoldbfi1_fx[i] = st->lsfoldbfi0_fx[i]; + move16(); + st->lsfoldbfi0_fx[i] = xsfnew_uw[k*M+i]; + } + } + } + ELSE + { + /* PLC: [LPD: LPC concealment] + * Conceal the LPC from the lost frame */ + st->numlpc = 2; + move16(); + test(); + if ( st->tcxonly == 0 || LT_16(st->core_fx, TCX_10_CORE)) + { + move16(); + st->numlpc = 1; + } + IF(EQ_16(st->nbLostCmpt,1)) + { + Copy(st->lsf_old_fx, st->old_lsf_q_cng, M); + Copy(st->lsp_old_fx, st->old_lsp_q_cng, M); + } + move16(); + xsfBase = PlcGetLsfBase (st->lpcQuantization, + (Word16)st->narrowBand, + st->sr_core); + + dlpc_bfi( st->L_frame_fx, + xsfnew_uw, + st->lsfold_uw, + st->last_good_fx, + st->nbLostCmpt, + st->mem_MA_fx, + st->mem_AR_fx, + &(st->stab_fac_fx), + st->lsf_adaptive_mean_fx, + st->numlpc, + st->lsf_cng, + st->plcBackgroundNoiseUpdated, + st->lsf_q_cng, + st->old_lsf_q_cng, + xsfBase, + st->tcxonly + ); + + st->envWeighted = 0; + move16(); + + Copy( st->lspold_uw, lsp, M ); + Copy( st->lsfold_uw, lsf, M ); + + FOR ( k = 0; k < st->numlpc; k++ ) + { + Copy( &xsfnew_uw[k*M], &lsf[(k+1)*M], M ); + + IF ( st->tcxonly ) + { + E_LPC_lsf_lsp_conversion(&lsf[(k+1)*M], &lsp[(k+1)*M], M); + E_LPC_lsf_lsp_conversion(st->lsf_q_cng, st->lsp_q_cng, M); + } + ELSE + { + lsf2lsp_fx( &lsf[(k+1)*M], &lsp[(k+1)*M], M, st->sr_core ); + lsf2lsp_fx( st->lsf_q_cng, st->lsp_q_cng, M, st->sr_core ); + } + + Copy( &lsp[(k+1)*M], &xspnew_uw[k*M], M ); + } + } + + /*--------------------------------------------------------------* + * Rate switching + *---------------------------------------------------------------*/ + IF( st->rate_switching_reset!=0 ) + { + Copy( &(lsf[M]),&(lsf[0]), M ); + Copy( &(lsp[M]),&(lsp[0]), M ); + Copy( &(lsf[M]),st->lsf_old_fx, M ); + Copy( &(lsp[M]),st->lsp_old_fx, M ); + Copy( &(lsf[M]),lsfmid, M ); + Copy( &(lsp[M]),lspmid, M ); + E_LPC_f_lsp_a_conversion(st->lsp_old_fx, st->old_Aq_12_8_fx, M); + } + + + IF(st->enablePlcWaveadjust) + { + if(EQ_16(st->core_fx, ACELP_CORE)) + { + st->tonality_flag = 0; + move16(); + } + if(bfi) + { + st->plcInfo.nbLostCmpt++; + move16(); + } + } + + /*--------------------------------------------------------------------------------* + * ACELP + *--------------------------------------------------------------------------------*/ + test(); + test(); + test(); + IF( (st->prev_bfi_fx!=0) && (bfi==0) && (EQ_16(*coder_type,VOICED))&>_16(st->prev_nbLostCmpt,4)) + { + st->dec_glr_idx = 1; + move16(); + st->reset_mem_AR = 1; + move16(); + } + + IF ( st->core_fx == ACELP_CORE ) + { + IF (st->tcxonly==0) + { + /* Set pointer to parameters */ + prm = param; + + /* Stability Factor */ + IF ( bfi == 0 ) + { + st->stab_fac_fx = lsf_stab_fx(&lsf[M], &lsf[0], 0, st->L_frame_fx); + } + + test(); + IF( bfi==0 && st->prev_bfi_fx != 0 ) + { + /* check if LSP interpolation can be relaxed or if LPC power can be diffused*/ + E_LPC_f_lsp_a_conversion(&lsp[0], tmp_old, M); + enr_old = Enr_1_Az_fx(tmp_old, 2*L_SUBFR); + + E_LPC_f_lsp_a_conversion(&lsp[M], tmp_new, M); + enr_new = Enr_1_Az_fx(tmp_new, 2*L_SUBFR); + } + + test(); + test(); + test(); + test(); + IF( (bfi == 0) && ((EQ_16(st->dec_glr_idx, 1))||((st->safety_net_fx==0)&&(shr(enr_new,11)>0)&&(GT_16(shr(enr_new,1),enr_old))))&&(st->prev_bfi_fx!=0)) + { + Word16 reset_q = 0; + if( EQ_16(st->dec_glr_idx, 1)) + { + reset_q = 1; + move16(); + } + RecLpcSpecPowDiffuseLc( &lsp[M], &lsp[0], &lsf[M], st, reset_q); + + int_lsp_fx( L_frame, &lsp[0], &lsp[M], Aq, M, interpol_frac_fx, 0 ); + + Copy(&lsf[M], xsfnew_uw, M); + } + ELSE + { + /* LPC Interpolation for ACELP */ + test(); + IF ( bfi==0 && st->acelp_cfg.midLpc ) + { + st->relax_prev_lsf_interp_fx = 0; + move16(); + IF (st->prev_bfi_fx) + { + /* check if LSP interpolation can be relaxed */ + IF ( LT_16(enr_new, shr(enr_old, 2))) + { + st->relax_prev_lsf_interp_fx = -1; + move16(); + test(); + test(); + test(); + test(); + if ( EQ_16(st->clas_dec, UNVOICED_CLAS)||EQ_16(st->clas_dec,SIN_ONSET)||EQ_16(st->clas_dec,INACTIVE_CLAS)||EQ_16(*coder_type,GENERIC)||EQ_16(*coder_type,TRANSITION)) + { + st->relax_prev_lsf_interp_fx = 1; + move16(); + } + } + } + + test(); + test(); + test(); + test(); + if (st->stab_fac_fx == 0 && st->old_bfi_cnt_fx > 0 && NE_16(st->clas_dec, VOICED_CLAS)&&NE_16(st->clas_dec,ONSET)&&st->relax_prev_lsf_interp_fx==0) + { + st->relax_prev_lsf_interp_fx = 2; + move16(); + } + int_lsp4_fx( L_frame, &lsp[0], lspmid, &lsp[M], Aq, M, st->relax_prev_lsf_interp_fx ); + } + ELSE + { + int_lsp_fx( L_frame, &lsp[0], &lsp[M], Aq, M, interpol_frac_fx, 0 ); + int_lsp_fx( L_frame, st->old_lsp_q_cng, st->lsp_q_cng, st->Aq_cng, M, interpol_frac_fx, 0 ); + } + } + } + + test(); + IF (bfi!=0 && st->last_core_fx != ACELP_CORE) + { + /* PLC: [TCX: TD PLC] */ + con_tcx( st, &synthFB[0] ); + lerp( synthFB, synth, st->L_frame_fx, st->L_frameTCX ); + st->con_tcx = 1; + move16(); + set16_fx (st->mem_pitch_gain+2,round_fx(L_shl(st->Mode2_lp_gainp , 1)), st->nb_subfr); + } + ELSE + { + /* ACELP decoder */ + IF (EQ_16(st->L_frame_fx,L_FRAME)) + { + Copy(Aq+2*(M+1), st->cur_sub_Aq_fx, (M+1)); + } + ELSE + { + Copy(Aq+3*(M+1), st->cur_sub_Aq_fx, (M+1)); + } + IF ( bfi != 0 ) + { + /* PLC: [ACELP: general] + * PLC: Use the ACELP like concealment */ + con_acelp(Aq, + st->core_ext_mode, + &synth[0], + pitch, + pit_gain, + st->stab_fac_fx, + st, + &st->Q_exc, + &st->Q_syn, /*Q format of st->mem_syn*/ + pitch_buf, + voice_factors, + ptr_bwe_exc + ); + + Copy(&st->mem_pitch_gain[2], &st->mem_pitch_gain[st->nb_subfr+2], st->nb_subfr); + set16_fx(&st->mem_pitch_gain[2],0,st->nb_subfr); + } + ELSE + { + decoder_acelp(st, *coder_type, prm, Aq, st->acelp_cfg, &synth[0], + pitch, pit_gain, st->stab_fac_fx, pitch_buf, voice_factors, LSF_Q_prediction, ptr_bwe_exc); + IF(st->flagGuidedAcelp > 0) + { + st->guidedT0 = s_max(s_min(add(st->T0_4th, st->guidedT0), NBPSF_PIT_MAX), PIT_MIN_16k); + } + + FOR (i=0; inb_subfr; i++) + { + move16(); + move16(); + st->mem_pitch_gain[2+(2*st->nb_subfr-1)-i] = st->mem_pitch_gain[2+ (st->nb_subfr-1) -i]; + st->mem_pitch_gain[2+(st->nb_subfr-1)-i] = pit_gain[i]; + } + } + } + + + /* LPC for ACELP/BBWE */ + test(); + test(); + IF( st->narrowBand || (EQ_32(st->sr_core, 12800))||(EQ_32(st->sr_core,16000))) + { + Copy(Aq, st->mem_Aq, nb_subfr*(M+1)); + } + + /* PLC: [TCX: Tonal Concealment] */ + /* Signal that this frame is not TCX */ + TonalMDCTConceal_UpdateState(&st->tonalMDCTconceal, 0, 0, 0, 0); + + IF (bfi==0) + { + st->second_last_tns_active = st->last_tns_active; + st->last_tns_active = 0; + st->tcxltp_last_gain_unmodified = 0; + move16(); + } + + } + + + + /*--------------------------------------------------------------------------------* + * TCX20 + *--------------------------------------------------------------------------------*/ + + IF ( EQ_16(st->core_fx, TCX_20_CORE)) + { + /* Set pointer to parameters */ + prm = param; + + /* Stability Factor */ + IF ( bfi == 0 ) + { + IF ( st->tcxonly != 0 ) + { + st->stab_fac_fx = lsf_stab_fx(&lsf[M], &lsf[0],0, L_FRAME); + } + ELSE + { + st->stab_fac_fx = lsf_stab_fx(&lsf[M], &lsf[0],0, st->L_frame_fx); + } + } + + IF (st->enableTcxLpc) + { + /* Convert quantized xSP to A */ + E_LPC_f_lsp_a_conversion(&lsp[M], Aq, M); + } + ELSE + { + IF (st->tcxonly == 0) + { + test(); + test(); + test(); + IF( (bfi == 0) && (st->prev_bfi_fx != 0 ) && (st->safety_net_fx==0) && (st->rate_switching_reset != 0) ) + { + /* diffuse LPC power on rate switching*/ + RecLpcSpecPowDiffuseLc( &lsp[M], &lsp[0], &lsf[M], st, 0 ); + int_lsp_fx( L_frame, &lsp[0], &lsp[M], Aq, M, interpol_frac_fx, 0 ); + Copy(&lsf[M], xsfnew_uw, M); + } + ELSE + { + /* LPC Interpolation for TCX */ + E_LPC_int_lpc_tcx(&lsp[0], &lsp[M], Aq); + } + } + ELSE + { + E_LPC_f_lsp_a_conversion(&lsp[M], Aq, M); + } + } + + test(); + IF ( bfi == 0 && st->tcx_lpc_shaped_ari != 0 ) + { + E_LPC_f_lsp_a_conversion(lspind, Aind, M); + } + + /* TCX decoder */ + decoder_tcx(&st->tcx_cfg, + prm, + Aq, + Aind, + L_frame, + L_frameTCX, + st->tcx_cfg.tcx_coded_lines, + &synth[0], + &synthFB[0], + st, + *coder_type, + bfi, + 0, + st->stab_fac_fx + ); + + } + + /*--------------------------------------------------------------------------------* + * TCX10 + *--------------------------------------------------------------------------------*/ + + IF ( EQ_16(st->core_fx, TCX_10_CORE)) + { + FOR (k=0; k<2; k++) + { + + /* Set pointer to parameters */ + prm = param + (k*DEC_NPRM_DIV); + + /* Stability Factor */ + IF ( bfi==0 ) + { + st->stab_fac_fx = lsf_stab_fx(&lsf[(k+1)*M], &lsf[k*M],0, L_FRAME); + } + + E_LPC_f_lsp_a_conversion(&lsp[(k+1)*M], Aq, M); + + /* TCX decoder */ + + IGFDecRestoreTCX10SubFrameData( &st->hIGFDec, k ); + decoder_tcx(&st->tcx_cfg, + prm, + Aq, + Aind, + shr(L_frame, 1), + shr(L_frameTCX, 1), + shr(st->tcx_cfg.tcx_coded_lines, 1), + &synth[k*L_frame/2], + &synthFB[k*L_frameTCX/2], + st, + *coder_type, + bfi, + k, + st->stab_fac_fx + ); + } + + } + + + test(); + IF (EQ_16(st->core_fx, TCX_10_CORE)||EQ_16(st->core_fx,TCX_20_CORE)) + { + test(); + test(); + IF(st->enablePlcWaveadjust || /* bfi */ + (GE_32(st->last_total_brate_fx, HQ_48k) && /* recovery */ + EQ_16(st->last_codec_mode, MODE2) ) ) + { + /* waveform adjustment */ + concealment_signal_tuning_fx( bfi, st->core_fx, + synthFB, &st->plcInfo, st->nbLostCmpt, st->prev_bfi_fx, + st->tonalMDCTconceal.secondLastPcmOut, + past_core_mode,st->tonalMDCTconceal.lastPcmOut, st ); + test(); + test(); + test(); + IF ((bfi || st->prev_bfi_fx) && st->plcInfo.Pitch_fx && (EQ_16(st->plcInfo.concealment_method, TCX_NONTONAL))) + { + lerp( synthFB, synth, L_frame, L_frameTCX ); + test(); + if( !bfi && st->prev_bfi_fx ) + { + st->plcInfo.Pitch_fx = 0; + move16(); + } + } + } + + IF (!bfi) + { + TonalMDCTConceal_SaveTimeSignal( &st->tonalMDCTconceal, synthFB, L_frameTCX ); + } + decoder_tcx_post( st, synth, synthFB, Aq, bfi ); + + IF (EQ_16(st->core_fx, TCX_20_CORE)) + { + /* LPC Interpolation for BBWE/post-processing */ + test(); + test(); + IF( st->narrowBand || (EQ_32(st->sr_core, 12800))||(EQ_32(st->sr_core,16000))) + { + int_lsp_fx( L_frame, st->lspold_uw, xspnew_uw, Aq, M, interpol_frac_fx, 0 ); + Copy(Aq, st->mem_Aq, nb_subfr*(M+1)); + } + } + } + + /* PLC: [Common: Classification] */ + + IF( LE_32( st->sr_core, 16000)) + { + test(); + test(); + test(); + IF ( EQ_16(st->core_fx, TCX_20_CORE)||EQ_16(st->core_fx,TCX_10_CORE)||(st->tcxonly&&st->bfi_fx)) + { + Word16 pitch_C[NB_SUBFR16k]; + Word16 core_ext_mode, LTP_Gain; + + set16_fx(pitch_C, shl(round_fx(st->old_fpitch), 6), NB_SUBFR16k); + + core_ext_mode = GENERIC; + move16(); + if(st->tcxonly == 0) + { + core_ext_mode = st->core_ext_mode; + move16(); + } + + LTP_Gain = -32768/*-1.0f Q15*/; + if(st->tcxltp) + { + LTP_Gain = st->tcxltp_last_gain_unmodified; + move16(); + } + + + FEC_clas_estim_fx( + st, + /*Opt_AMR_WB*/0, /*A*/ + st->L_frame_fx, + &(st->clas_dec), + core_ext_mode, + pitch_C, + synth, + &st->lp_ener_FER_fx, + /**decision_hyst*/NULL, /* i/o: hysteresis of the music/speech decision */ + /**UV_cnt*/ NULL, /* i/o: number of consecutive frames classified as */ + /**LT_UV_cnt*/ NULL, /* i/o: long term consecutive frames classified as UV */ + /**Last_ener*/ NULL, /* i/o: last_energy frame */ + /**locattack*/ NULL, /* i/o: detection of attack (mainly to localized speech burst) */ + /**lt_diff_etot*/NULL, /* i/o: long-term total energy variation */ + /**amr_io_class*/ NULL, /* i/o: classification for AMR-WB IO mode */ + /*bitrate*/ 0 , /* i : Decoded bitrate */ + 0, /* i : Synthesis scaling */ + /**class_para*/ NULL, /* o : classification para. fmerit1 */ + st->mem_syn_clas_estim_fx, /* i/o: memory of the synthesis signal for frame class estimation */ + &st->classifier_Q_mem_syn, /* i/o: exponent for memory of synthesis signal for frame class estimation */ + LTP_Gain, /* i : means LTP Gain */ + 1 /*CLASSIFIER_TCX*/, /* i : signal classifier mode */ + bfi, /* i : bad frame indicator */ + st->last_core_brate_fx /* i : bitrate of previous frame */ + ); + + } + } + + /*--------------------------------------------------------------------------------* + * END + *--------------------------------------------------------------------------------*/ + + test(); + IF( bfi && NE_16(st->last_core_bfi , ACELP_CORE)) + { + /* Update FEC_scale_syn parameters */ + IF(st->tcxltp_gain == 0) + { + frame_ener_fx( L_frame, UNVOICED_CLAS, synth, shr(L_frame,1), &st->enr_old_fx, L_frame, 0, 0, 0 ); + } + ELSE + { + Word16 pitch_Q0; + pitch_Q0 = round_fx(st->old_fpitch); + frame_ener_fx( L_frame, st->clas_dec, synth, pitch_Q0, &st->enr_old_fx, L_frame, 0, 0, 0 ); + } + } + + + test(); + test(); + IF(!bfi && GE_16(st->clas_dec, VOICED_TRANSITION)&<_16(st->clas_dec,INACTIVE_CLAS)) + { + Word16 offset; + + IF(EQ_16(st->core_fx, ACELP_CORE)) + { + offset = sub(st->nb_subfr,1); + offset = imult1616(offset,add(M,1)); + } + ELSE + { + offset = 0; + move16(); + } + /* use latest LPC set */ + st->old_enr_LP = Enr_1_Az_fx(Aq+offset, L_SUBFR); /*Q3*/ + } + + + /* Update */ + Copy(synth_buf+L_frame, st->old_synth, st->old_synth_len); + + Copy( st->old_synthFB_fx + L_frameTCX - NS2SA_fx2(st->output_Fs_fx, PH_ECU_MEM_NS), st->synth_history_fx, NS2SA_fx2(st->output_Fs_fx, PH_ECU_MEM_NS) ); + Copy(synth_bufFB+L_frameTCX, st->old_synthFB_fx, st->old_synth_lenFB); + Copy_Scale_sig( st->old_out_fx+NS2SA_fx2(st->output_Fs_fx, N_ZERO_MDCT_NS), st->old_synthFB_fx+st->old_synth_lenFB, NS2SA_fx2(st->output_Fs_fx, PH_ECU_LOOKAHEAD_NS), negate(st->Q_old_wtda)); + + + Copy(&xspnew_uw[(st->numlpc-1)*M], st->lspold_uw, M); + Copy(&xsfnew_uw[(st->numlpc-1)*M], st->lsfold_uw, M); + + IF (bfi) + { + Copy(st->lspold_uw, st->lsp_old_fx, M); /* for recovery */ + Copy(st->lsfold_uw, st->lsf_old_fx, M); /* for recovery */ + } + ELSE + { + Copy(&lsp[st->numlpc*M], st->lsp_old_fx, M); + Copy(&lsf[st->numlpc*M], st->lsf_old_fx, M); + } + Copy(st->lsp_q_cng, st->old_lsp_q_cng, M); + Copy(st->lsf_q_cng, st->old_lsf_q_cng, M); + + /* Update LP_CNG parameters */ + IF( st->tcxonly == 0 ) + { + /* update CNG parameters in active frames */ + IF (EQ_16(st->bwidth_fx,NB)&&st->enableTcxLpc!=0&&NE_16(st->core_fx,ACELP_CORE)) + { + Word16 buf[L_LP], res[L_FRAME], A[M+1], Qexc, r_l[M+1], r_h[M+1], lsptmp[M], Q_r, tmp; + + assert(st->L_frame_fx==L_FRAME); + Copy(synth+L_FRAME-L_LP, buf, L_LP); + tmp = synth[L_FRAME-L_LP-1]; + Qexc = E_UTIL_f_preemph3(buf, st->preemph_fac, L_LP, &tmp, 1); + autocorr_fx( buf, M, r_h, r_l, &Q_r, L_LP, Assym_window_W16fx, 0, 0 ); + lag_wind(r_h, r_l, M, INT_FS_FX, LAGW_WEAK); + E_LPC_lev_dur(r_h, r_l, A, NULL, M, NULL); + E_LPC_a_lsp_conversion(A, lsptmp, &xspnew_uw[0], M); + Residu3_fx(A, buf+L_LP-L_FRAME, res, L_FRAME, 1); + cng_params_upd_fx( lsptmp, res, st->L_frame_fx, &st->ho_circ_ptr_fx, + st->ho_ener_circ_fx, &st->ho_circ_size_fx, st->ho_lsp_circ_fx, + Qexc, DEC, st->ho_env_circ_fx, NULL, NULL, NULL, NULL, st->last_active_brate_fx ); + } + ELSE + { + cng_params_upd_fx( &lsp[M], st->old_exc_fx+L_EXC_MEM_DEC-st->L_frame_fx, + st->L_frame_fx, &st->ho_circ_ptr_fx, st->ho_ener_circ_fx, + &st->ho_circ_size_fx, st->ho_lsp_circ_fx, st->Q_exc, DEC, + st->ho_env_circ_fx, NULL, NULL, NULL, NULL, st->last_active_brate_fx ); + } + + /* Set 16k LSP flag for CNG buffer */ + st->ho_16k_lsp_fx[st->ho_circ_ptr_fx] = 1; + move16(); + if ( EQ_16(st->L_frame_fx,L_FRAME)) + { + st->ho_16k_lsp_fx[st->ho_circ_ptr_fx] = 0; + move16(); + } + } + + move16(); + st->last_is_cng = 0; + + /* Postfiltering */ + post_decoder( st, + *coder_type, + synth_buf, + pit_gain, + pitch, + signal_out, + bpf_noise_buf + ); + + IF( signal_outFB ) + { + Copy( synthFB, signal_outFB, L_frameTCX ); + } + + IF( st->enablePlcWaveadjust) + { + if(!bfi) + { + st->plcInfo.nbLostCmpt = L_deposit_l(0); + } + + IF (st->core_fx == 0) + { + set_state(st->plcInfo.Transient, st->core_fx, MAX_POST_LEN); + } + } + + + return; +} + + diff --git a/lib_dec/dec_ace.c b/lib_dec/dec_ace.c new file mode 100644 index 0000000..5ae1ee7 --- /dev/null +++ b/lib_dec/dec_ace.c @@ -0,0 +1,772 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*BASOp version info: This file is up to date with trunk rev. 39929 */ + +#include +#include +#include +#include "options.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "stl.h" + +/*-------------------------------------------------------------------* + * decoder_acelp() + * + * Decode ACELP frame + *-------------------------------------------------------------------*/ + +void decoder_acelp( + Decoder_State_fx *st, + Word16 coder_type, /* i : coder type */ + Word16 prm[], /* i : parameters */ + Word16 A[], /* i : coefficients NxAz[M+1] */ + ACELP_config acelp_cfg, /* i : ACELP config */ + Word16 synth[], /* i/o: synth[-2*LFAC..L_DIV] Q0 */ + Word16 *pT, /* o : pitch for all subframe Q0 */ + Word16 *pgainT, /* o : pitch gain for all subfr 1Q14 */ + Word16 stab_fac, /* i : stability of isf */ + Word16 *pitch_buffer, /* o : pitch values for each subfr. */ + Word16 *voice_factors, /* o : voicing factors */ + const Word16 LSF_Q_prediction, /* i : LSF prediction mode */ + Word16 *bwe_exc /* o : excitation for SWB TBE */ +) +{ + Word16 i, j, i_subfr; + Word16 T0, T0_frac, T0_min, T0_min_frac, T0_max, T0_max_frac, T0_res; + Word16 tmp, tmp2, gain_pit/*Q14*/, Es_pred, tmp_deemph; + Word32 Ltmp, Ltmp2, gain_code; + Word16 code[L_SUBFR]; + Word16 mem_syn[M]; + Word16 *syn, syn_buf[M+L_DIV_MAX+L_DIV_MAX/2]; + Word16 *exc, exc_buf[L_EXC_MEM_DEC+L_DIV_MAX+1]; + Word16 exc2[L_FRAME_16k]; + Word16 *p_A; + Word32 pitch_buf[NB_SUBFR16k]; + Word16 dummy_pitch_buf[NB_SUBFR16k]; + Word16 gain_inov; + Word16 mem_back[M]; + Word16 update_flg; + Word16 Q_mem_back; /*Q format of mem_back*/ + Word16 h1[L_FRAME_16k/4+1]; + Word16 mem[M]; + Word16 *pA; + PulseConfig config; + Word16 weights[5]; /* Q15 */ + + Word16 reScaleLen_fx; /* rescaling length for the BWE buffers */ + Word16 reSampLen; + + /*Q formats of buffers */ + Word16 prev_Q_syn; + Word32 gain_code2=0; + Word16 code2[L_SUBFR]; + Word16 error = 0; + Word16 gain_preQ = 0; /* Gain of prequantizer excitation */ + Word16 code_preQ[L_SUBFR]; /* Prequantizer excitation */ + Word16 lp_flag; + + + Word16 prev_gain_pit; + Word16 tmp_noise; /* Long term temporary noise energy */ + Word32 gain_code_tmp; + Word16 gain_pit_tmp; + Word32 gain_code_pre; + Word16 avoid_lpc_burst_on_recovery; + Word16 force_scale_syn; + + + gain_code_pre = 0; + move16(); + + + set16_fx(code_preQ, 0, L_SUBFR); + + gain_inov = 0; /* to avoid compilation warnings */ + T0 = 0; /* to avoid compilation warnings */ + T0_frac = 0; /* to avoid compilation warnings */ + T0_res = 0; /* to avoid compilation warnings */ + prev_Q_syn = st->prev_Q_syn = st->Q_syn; + move16(); + move16(); + move16(); + move16(); + gain_pit = 0; + gain_code = 0; + move16(); + move16(); + move16(); + update_flg = 0; + move16(); + gain_code2=0; + + prev_gain_pit = 0; + tmp_noise = 0; + + IF(EQ_16(st->nb_subfr,4)) + { + move16(); + move16(); + move16(); + move16(); + weights[0] = 3277/*0.1f Q15*/; + weights[1] = 6554/*0.2f Q15*/; + weights[2] = 9830/*0.3f Q15*/; + weights[3] = 13107/*0.4f Q15*/; + } + ELSE /*nb_subfr == 5*/ + { + move16(); + move16(); + move16(); + move16(); + move16(); + weights[0] = 2185/*(float)1/15 Q15*/; + weights[1] = 4369/*(float)2/15 Q15*/; + weights[2] = 6554/*(float)3/15 Q15*/; + weights[3] = 8738/*(float)4/15 Q15*/; + weights[4] = 10923/*(float)5/15 Q15*/; + } + st->Mode2_lp_gainp = L_deposit_l(0); + st->Mode2_lp_gainc = L_deposit_l(0); + + avoid_lpc_burst_on_recovery = 0; + move16(); + test(); + test(); + if (st->last_con_tcx && (NE_16(st->L_frameTCX_past, st->L_frame_fx))&&(st->last_core_fx!=0)) + { + avoid_lpc_burst_on_recovery = 1; + move16(); + } + + + /*------------------------------------------------------------------------* + * Previous frame is TCX * + *------------------------------------------------------------------------*/ + + + /* Reset phase dispersion */ + IF ( st->last_core_bfi > ACELP_CORE ) + { + st->dm_fx.prev_gain_code = L_deposit_l(0); + set16_fx(st->dm_fx.prev_gain_pit, 0, 6); + st->dm_fx.prev_state = 0; + move16(); + } + + /* Update of synthesis filter memories in case of 12k8 core */ + test(); + test(); + IF ( st->prev_bfi_fx && st->last_con_tcx && LT_16(st->L_frame_fx, L_FRAME16k)) + { + synth_mem_updt2( st->L_frame_fx, L_FRAME16k, st->old_exc_fx, st->mem_syn_r, st->mem_syn2_fx, NULL, DEC ); + } + + IF( st->last_con_tcx && st->old_enr_LP ) + { + Word16 enr_LP, ratio; + + /* rescale excitation buffer if LPC energies differs too much */ + enr_LP = Enr_1_Az_fx( A, L_SUBFR ); + + IF(LT_16(st->old_enr_LP, enr_LP)) + { + ratio = div_s(st->old_enr_LP,enr_LP); /* Q15 */ + IF (LT_16(ratio, 26215)) + { + FOR (i = 0; i < L_EXC_MEM_DEC; i++) + { + st->old_exc_fx[i] = mult_r(st->old_exc_fx[i], ratio); + } + } + } + } + + /*------------------------------------------------------------------------* + * Initialize buffers * + *------------------------------------------------------------------------*/ + Copy( st->mem_syn2_fx, mem_back, M); + move16(); + Q_mem_back = st->Q_syn; + /* set ACELP synthesis memory */ + Copy( st->mem_syn2_fx, mem_syn, M ); + + /* set excitation memory*/ + exc=exc_buf+L_EXC_MEM_DEC; + Copy( st->old_exc_fx, exc_buf, L_EXC_MEM_DEC); + *(exc+st->L_frame_fx) = 0; + + /* Init syn buffer */ + syn = syn_buf + M; + Copy( st->mem_syn2_fx, syn_buf, M ); + + /*------------------------------------------------------------------------* + * Fast recovery flag + *------------------------------------------------------------------------*/ + test(); + if(st->prev_bfi_fx && EQ_16(coder_type,VOICED)) + { + /*Force BPF to be applied fully*/ + st->bpf_gain_param=3; + move16(); + } + + /*------------------------------------------------------------------------* + * - decode mean_ener_code for gain decoder (d_gain2.c) * + *------------------------------------------------------------------------*/ + Es_pred = 0; + move16(); + IF ( acelp_cfg.nrg_mode>0 ) + { + d_gain_pred(acelp_cfg.nrg_mode, &Es_pred, &prm ); + } + + /*------------------------------------------------------------------------* + * Loop for every subframe in the analysis frame * + *------------------------------------------------------------------------* + * To find the pitch and innovation parameters. The subframe size is * + * L_subfr and the loop is repeated L_ACELP/L_subfr times. * + * - compute impulse response of weighted synthesis filter (h1[]) * + * - compute the target signal for pitch search * + * - find the closed-loop pitch parameters * + * - encode the pitch delay * + * - update the impulse response h1[] by including fixed-gain pitch * + * - find target vector for codebook search * + * - correlation between target vector and impulse response * + * - codebook search * + * - encode codebook address * + * - VQ of pitch and codebook gains * + * - find synthesis speech * + * - update states of weighting filter * + *------------------------------------------------------------------------*/ + + p_A = A; + + FOR (i_subfr = 0; i_subfr < st->L_frame_fx; i_subfr += L_SUBFR) + { + + test(); + IF( EQ_16(st->use_partial_copy,1)&&EQ_16(st->rf_frame_type,RF_NELP)) + { + IF( i_subfr == 0 ) + { + decod_nelp_fx( st, UNVOICED, &tmp_noise, dummy_pitch_buf, exc, exc2, voice_factors, bwe_exc, &st->Q_exc, st->bfi_fx, pgainT ); + + set32_fx(pitch_buf, L_SUBFR_Q16, NB_SUBFR); + set16_fx(pitch_buffer, 4096, NB_SUBFR); /* L_SUBFR_Q16 in Q6 */ + } + } + ELSE + { + + /*-------------------------------------------------------* + * - Decode adaptive codebook. * + *-------------------------------------------------------*/ + + test(); + IF( EQ_16(st->use_partial_copy,1)&&st->acelp_cfg.gains_mode[i_subfr/L_SUBFR]==0) + { + gain_pit = prev_gain_pit; + } + + IF ( acelp_cfg.ltp_bits != 0 ) + { + /*if( st->use_partial_copy + && st->rf_frame_type == RF_GENPRED + && ( i_subfr == L_SUBFR || i_subfr == 3*L_SUBFR ) ) + { + *pt_pitch = (float)T0 + (float)T0_frac/(float)T0_res; + } + else*/ + { + /* pitch lag decoding */ + pitch_buf[i_subfr/L_SUBFR] = Mode2_pit_decode( acelp_cfg.ltp_mode, + i_subfr, + L_SUBFR, + &prm, + &T0, + &T0_frac, + &T0_res, + &T0_min, + &T0_min_frac, + &T0_max, + &T0_max_frac, + st->pit_min, + st->pit_fr1, + st->pit_fr1b, + st->pit_fr2, + st->pit_max, + st->pit_res_max); + } + /* find pitch excitation */ + test(); + IF( EQ_16(st->pit_res_max,6)&&!(st->use_partial_copy)) + { + IF ( EQ_16(T0_res, shr(st->pit_res_max, 1))) + { + pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, shl(T0_frac,1), L_SUBFR+1, pitch_inter6_2, PIT_L_INTERPOL6_2, PIT_UP_SAMP6 ); + } + ELSE + { + pred_lt4( &exc[i_subfr],&exc[i_subfr], T0, T0_frac, L_SUBFR+1, pitch_inter6_2, PIT_L_INTERPOL6_2, PIT_UP_SAMP6 ); + } + } + ELSE + { + IF ( EQ_16(T0_res, shr(st->pit_res_max, 1))) + { + pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, shl(T0_frac,1), L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + } + ELSE + { + pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + } + } + + /* LP filtering of the adaptive excitation*/ + lp_flag = acelp_cfg.ltf_mode; + move16(); + + IF( EQ_16(acelp_cfg.ltf_mode, NORMAL_OPERATION)) + { + lp_flag = *prm; + move16(); + prm++; + } + + lp_filt_exc_dec_fx( st, MODE2, st->core_brate_fx, 0, coder_type, i_subfr, L_SUBFR, st->L_frame_fx, lp_flag, exc ); + + } + ELSE + { + /* No adaptive codebook (UC) */ + set16_fx(&exc[i_subfr], 0, L_SUBFR); + + T0 = L_SUBFR; + T0_frac = 0; + T0_res = 1; + pitch_buf[i_subfr/L_SUBFR] = L_deposit_h(L_SUBFR); + } + + IF( st->igf != 0 ) + { + tbe_celp_exc(st->L_frame_fx, i_subfr, T0, T0_frac, &error, bwe_exc); + } + + pitch_buffer[i_subfr/L_SUBFR] = shl(add(shl(T0,2),T0_frac), 4); + + /*-------------------------------------------------------* + * - Decode innovative codebook. * + *-------------------------------------------------------*/ + test(); + test(); + test(); + test(); + IF( EQ_16(st->use_partial_copy,1)&& + ( EQ_16(st->rf_frame_type,RF_ALLPRED) || + ( EQ_16(st->rf_frame_type,RF_GENPRED) && + ( EQ_16(i_subfr,L_SUBFR) || EQ_16(i_subfr,3*L_SUBFR) )) ) ) + { + set16_fx(code, 0, L_SUBFR); + } + ELSE + { + config = PulseConfTable[acelp_cfg.fixed_cdk_index[i_subfr/L_SUBFR]]; + D_ACELP_indexing( code, config, NB_TRACK_FCB_4T, prm, &st->BER_detect ); + (prm) += 8; + /*-------------------------------------------------------* + * - Add the fixed-gain pitch contribution to code[]. * + *-------------------------------------------------------*/ + + cb_shape_fx( acelp_cfg.pre_emphasis, acelp_cfg.pitch_sharpening, acelp_cfg.phase_scrambling, acelp_cfg.formant_enh, acelp_cfg.formant_tilt, + acelp_cfg.formant_enh_num, acelp_cfg.formant_enh_den, p_A, code, st->tilt_code_fx, extract_h(L_add(pitch_buf[i_subfr/L_SUBFR],26216)), 1 ); + } + /*-------------------------------------------------------* + * - Generate Gaussian excitation * + *-------------------------------------------------------*/ + test(); + IF( EQ_16(acelp_cfg.gains_mode[i_subfr/L_SUBFR],7)&&!st->use_partial_copy) + { + gaus_L2_dec( code2, st->tilt_code_fx, p_A, acelp_cfg.formant_enh_num, &(st->seed_acelp) ); + } + ELSE + { + gain_code2 = L_deposit_l(0); + set16_fx(code2,0,L_SUBFR); + } + + /*-------------------------------------------------* + * - Decode codebooks gains. * + *-------------------------------------------------*/ + IF( st->acelp_cfg.gains_mode[i_subfr/L_SUBFR] != 0 ) + { + decode_acelp_gains( code, + acelp_cfg.gains_mode[i_subfr/L_SUBFR], + Es_pred, + &gain_pit, + &gain_code, + &prm, + &(st->past_gpit), + &(st->past_gcode), + &gain_inov, + L_SUBFR, + code2, + &gain_code2 + ); + } + IF(st->use_partial_copy && st->rf_frame_type == RF_ALLPRED) st->past_gcode = 0; + IF(st->use_partial_copy && st->rf_frame_type == RF_NOPRED ) st->past_gpit = 67; + IF( st->igf != 0 ) + { + /* Rescaling for 12.8k and 16k cores related to BWE */ + IF ( EQ_16(st->L_frame_fx, L_FRAME)) + { + /* 5/2 times resampled past memories*/ + reScaleLen_fx = add(shl(i_subfr, 1), shr(i_subfr, 1)); + reSampLen = (L_SUBFR * HIBND_ACB_L_FAC); + } + ELSE + { + /* 2 times resampled past memories*/ + reScaleLen_fx = shl(i_subfr, 1); + reSampLen = (L_SUBFR * 2); + } + + Rescale_exc(NULL, &exc[i_subfr], &bwe_exc[reScaleLen_fx], + NULL, L_SUBFR, reSampLen, gain_code, &(st->Q_exc), st->Q_subfr, + exc2, i_subfr, GENERIC); + } + ELSE + { + Rescale_exc(NULL, &exc[i_subfr], NULL, NULL, L_SUBFR, 0, + gain_code, &(st->Q_exc), st->Q_subfr, exc2, i_subfr, GENERIC); + } + + /*----------------------------------------------------------* + * Update parameters for the next subframe. * + * - tilt of code: 0.0 (unvoiced) to 0.5 (voiced) * + *----------------------------------------------------------*/ + E_UTIL_voice_factor( exc, + i_subfr, + code, + gain_pit, + gain_code, + &(st->voice_fac), + &(st->tilt_code_fx), + L_SUBFR, + acelp_cfg.voice_tilt, + st->Q_exc, + 0 + ); + + pgainT[i_subfr/L_SUBFR] = gain_pit; + move16(); + + /*-------------------------------------------------------* + * - Find the total excitation. * + *-------------------------------------------------------*/ + gain_code_tmp = gain_code; + gain_pit_tmp = gain_pit; + IF( i_subfr == 0 ) + { + gain_code_pre = 0; + } + IF ( EQ_16(st->core_fx,ACELP_CORE)&&EQ_16(st->last_core_fx,ACELP_CORE)&&(EQ_16(st->use_partial_copy,1)||EQ_16(st->prev_use_partial_copy,1))) + { + IF( i_subfr > 0 && GT_16(gain_pit,20152)&>_16(st->prev_tilt_code_dec_fx,6553)&&EQ_16(st->next_coder_type,VOICED) + &&( EQ_16(st->use_partial_copy,1) || EQ_16(st->prev_use_partial_copy, 1) ) ) + { + gain_pit = mult(gain_pit,sub(26214, mult(i_subfr,51))); + } + ELSE IF( !st->prev_use_partial_copy && EQ_16(st->last_coder_type_fx,UNVOICED)&&NE_16(st->next_coder_type,UNVOICED)&<_32(gain_code,gain_code_pre)) + + { + gain_code = 0; + } + } + gain_code_pre = gain_code; + st->tilt_code_dec_fx[i_subfr/L_SUBFR] = st->tilt_code_fx; + + + tmp2 = shr(L_SUBFR, 1); + FOR (j = 0; j < 2; j++) + { + FOR (i = sub(tmp2, shr(L_SUBFR, 1)); i < tmp2; i++) + { + /* code in Q9, gain_pit in Q14, gain_code in Q16; exc Q_new */ + Ltmp = Mpy_32_16_1(gain_code2, code2[i]); + Ltmp = L_shl(Ltmp, add(5,st->Q_exc)); + Ltmp = L_mac(Ltmp, gain_pit, exc[i+i_subfr]); + exc2[i + i_subfr] = round_fx(L_shl(Ltmp, 1)); + + Ltmp2 = Mpy_32_16_1(gain_code, code[i]); + Ltmp2 = L_shl(Ltmp2, add(5,st->Q_exc)); + Ltmp = L_add(Ltmp, Ltmp2); + BASOP_SATURATE_WARNING_OFF + Ltmp = L_shl(Ltmp, 1); /* saturation can occur here */ + BASOP_SATURATE_WARNING_ON + exc[i + i_subfr] = round_fx(Ltmp); + } + tmp2 = L_SUBFR; + move16(); + } + + /*-----------------------------------------------------------------* + * Prepare TBE excitation + *-----------------------------------------------------------------*/ + gain_code = gain_code_tmp; + gain_pit = gain_pit_tmp; + IF( st->igf != 0 ) + { + prep_tbe_exc_fx( st->L_frame_fx, + i_subfr, + gain_pit, + gain_code, + code, + st->voice_fac, + &voice_factors[i_subfr/L_SUBFR], + bwe_exc, + gain_preQ, + code_preQ, + st->Q_exc, + T0, + T0_frac, + coder_type, + st->core_brate_fx); + } + + /*---------------------------------------------------------* + * Enhance the excitation * + *---------------------------------------------------------*/ + E_UTIL_enhancer( st->voice_fac, + stab_fac, + st->past_gcode, + gain_inov, + &(st->gc_threshold_fx), + code, + &exc2[i_subfr], + gain_pit, + &st->dm_fx.prev_gain_code, + st->dm_fx.prev_gain_pit, + &st->dm_fx.prev_state, + coder_type, + acelp_cfg.fixed_cdk_index[i_subfr/L_SUBFR], + L_SUBFR, + st->L_frame_fx, + st->Q_exc + ); + + } /* !RF_NELP frame partial copy */ + /*----------------------------------------------------------* + * - compute the synthesis speech * + *----------------------------------------------------------*/ + rescale_mem(&st->Q_exc, &prev_Q_syn, &st->Q_syn, mem_syn, syn, M, i_subfr); + + E_UTIL_synthesis(sub(st->Q_exc,st->Q_syn), p_A, &exc2[i_subfr], &syn[i_subfr], L_SUBFR, mem_syn, 1, M); + + /*-----------------------------------------------------------------* + * update lp_filtered gains for the case of frame erasure + *-----------------------------------------------------------------*/ + + st->Mode2_lp_gainp = L_add(st->Mode2_lp_gainp, L_mult0(st->past_gpit, weights[i_subfr/L_SUBFR])); /* 2Q29=1Q14*Q15 */ move32(); + st->Mode2_lp_gainc = L_add(st->Mode2_lp_gainc, Mpy_32_16_1(st->past_gcode, weights[i_subfr/L_SUBFR])); /* 15Q16=15Q16*Q15 */ move32(); + + /*----------------------------------------------------------* + * - update pitch lag for guided ACELP * + *----------------------------------------------------------*/ + test(); + if( st->enableGplc && EQ_16( shr(i_subfr,6), sub(st->nb_subfr,1) )) + { + st->T0_4th = T0; + move16(); + } + + /*----------------------------------------------------------* + * - Update LPC coeffs * + *----------------------------------------------------------*/ + p_A += (M+1); + + /* copy current gain for next subframe use, in case there is no explicit encoding */ + prev_gain_pit = gain_pit; + } /* end of subframe loop */ + + IF(st->BER_detect) + { + FOR (i=0; iL_frame_fx; i++) + { + exc[i] = 0; + move16(); + } + + int_lsp_fx( st->L_frame_fx, st->old_lsp_q_cng, st->lsp_q_cng, st->Aq_cng, M, interpol_frac_fx, 0 ); + + p_A = st->Aq_cng; + IF(st->last_good_fx < UNVOICED_TRANSITION ) + { + Copy(st->mem_syn2_fx, mem_syn, M ); + } + ELSE + { + set16_fx( mem_syn, 0, M ); + } + + FOR (i_subfr = 0; i_subfr < st->L_frame_fx; i_subfr += L_SUBFR) + { + E_UTIL_synthesis(sub(st->Q_exc,st->Q_syn), p_A, &exc[i_subfr], &syn[i_subfr], L_SUBFR, mem_syn, 1, M); + p_A += (M+1); + } + } + + tmp = 0; + move16(); + pA = A+(st->nb_subfr-1)*(M+1); + set16_fx(h1, 0, add(L_SUBFR,1)); + set16_fx(mem, 0, M); + h1[0] = 32768/32; + move16(); + E_UTIL_synthesis(0, pA, h1, h1, L_SUBFR, mem, 0, M); /* impulse response of LPC */ + deemph_fx(h1, st->preemph_fac, L_SUBFR, &tmp); /* impulse response of deemph */ + /* impulse response level = gain introduced by synthesis+deemphasis */ + Ltmp = Dot_productSq16HQ( 0, h1, L_SUBFR, &st->last_gain_syn_deemph_e); + st->last_gain_syn_deemph_e= add(st->last_gain_syn_deemph_e,10/*scaling of h1[0] and E_UTIL_synthesis * 2*/); + st->last_gain_syn_deemph = round_fx(Sqrt32(Ltmp,&st->last_gain_syn_deemph_e)); + + /* Do the classification */ + { + Word16 pit16[NB_SUBFR16k]; + Word16 k; + FOR(k = 0 ; k < st->nb_subfr ; k++) + { + pit16[k] = shl(extract_h(pitch_buf[k]),6);/*Q6*/ + } + + FEC_clas_estim_fx( + st, + /*Opt_AMR_WB*/0, /*A*/ + st->L_frame_fx, + &(st->clas_dec), + st->core_ext_mode, + pit16, + syn, + &st->lp_ener_FER_fx, + /**decision_hyst*/NULL, /* i/o: hysteresis of the music/speech decision */ + /**UV_cnt*/ NULL, /* i/o: number of consecutives frames classified as UV */ + /**LT_UV_cnt*/ NULL, /* i/o: long term consecutives frames classified as UV */ + /**Last_ener*/ NULL, /* i/o: last_energy frame */ + /**locattack*/ NULL, /* i/o: detection of attack (mainly to localized speech burst) */ + /**lt_diff_etot*/NULL, /* i/o: long-term total energy variation */ + /**amr_io_class*/ NULL, /* i/o: classification for AMR-WB IO mode */ + /*bitrate*/ 0 , /* i : Decoded bitrate */ + st->Q_syn, /* i : Synthesis scaling */ + /**class_para*/ NULL, /* o : classification para. fmerit1 */ + st->mem_syn_clas_estim_fx, /* i/o: memory of the synthesis signal for frame class estimation */ + &st->classifier_Q_mem_syn, /* i/o: exponent for memory of synthesis signal for frame class estimation */ + -32768/*-1.f Q15*/, /* i : LTP Gain */ + 0/*CLASSIFIER_ACELP*/, /* i : signal classifier mode */ + 0/*bfi*/, /* i : bad frame indicator */ + st->last_core_brate_fx /* i : bitrate of previous frame */ + ); + } + + /* Update Pitch Lag memory */ + + Copy32(&st->old_pitch_buf_fx[st->nb_subfr], st->old_pitch_buf_fx, st->nb_subfr); + Copy32(pitch_buf, &st->old_pitch_buf_fx[st->nb_subfr], st->nb_subfr); + + + { + Word16 pBuf_scaleSyn[NB_SUBFR16k]; + + FOR(i=0; i<(st->L_frame_fx/L_SUBFR); i++) + { + pBuf_scaleSyn[i] = round_fx(pitch_buf[i]); + } + + Scale_sig(mem_back, M, sub(st->Q_syn,Q_mem_back)); + + force_scale_syn = 0; + move16(); + test(); + test(); + test(); + IF ( (EQ_16(st->clas_dec,ONSET))||((GE_16(st->last_good_fx,VOICED_TRANSITION))&&(LT_16(st->last_good_fx,INACTIVE_CLAS)))) + { + force_scale_syn = 1; + move16(); + } + + FEC_scale_syn_fx( st->L_frame_fx, + &update_flg, + st->clas_dec, + st->last_good_fx, + syn, + pBuf_scaleSyn, + st->enr_old_fx, + 0, + coder_type, + LSF_Q_prediction, + &st->scaling_flag, + &st->lp_ener_FEC_av, + &st->lp_ener_FEC_max, + st->bfi_fx, + st->total_brate_fx, + st->prev_bfi_fx, + st->last_core_brate_fx, + exc, + exc2, + A, + &(st->old_enr_LP), + mem_back, + mem_syn, + st->Q_exc, + st->Q_syn + , avoid_lpc_burst_on_recovery + , force_scale_syn + ); + } + /* update ACELP synthesis memory */ + Copy( mem_syn, st->mem_syn2_fx, M ); + Copy( syn+st->L_frame_fx-L_SYN_MEM, st->mem_syn_r, L_SYN_MEM ); + + /* Deemphasis and output synth and ZIR */ + tmp_deemph = st->syn[M]; + move16(); + E_UTIL_deemph2(st->Q_syn, syn, st->preemph_fac, st->L_frame_fx, &tmp_deemph); /* tmp_deemph and syn in Q0 starting from here*/ + + bufferCopyFx(syn+st->L_frame_fx- st->L_frame_fx/2, st->old_syn_Overl, shr(st->L_frame_fx, 1),0 /*Qf_syn*/, -1 /*Qf_old_xnq*/, 0 , 0 /*Q_old_xnq*/); + + Copy(syn+st->L_frame_fx-M-1, st->syn, 1+M); /*Q0*/ + + Copy(syn, synth, st->L_frame_fx); + + Copy( syn, st->old_core_synth_fx, st->L_frame_fx ); + + + /* update old_Aq */ + Copy(exc_buf+st->L_frame_fx, st->old_exc_fx, L_EXC_MEM_DEC); + + /* Output pitch parameters for bass post-filter */ + FOR (i_subfr = 0; i_subfr < st->L_frame_fx; i_subfr += L_SUBFR) + { + *pT++ = round_fx(pitch_buf[i_subfr/L_SUBFR]); + } + + + st->tcxltp_last_gain_unmodified = 0; + + /*Update MODE1*/ + Copy( p_A-(M+1), st->old_Aq_12_8_fx, M+1 ); + st->old_Es_pred_fx = Es_pred; + + st->tcxltp_third_last_pitch = st->tcxltp_second_last_pitch; + st->tcxltp_second_last_pitch = st->old_fpitch; + st->old_fpitch = pitch_buf[(st->L_frame_fx/L_SUBFR) - 1]; + move32(); + + + return; +} + diff --git a/lib_dec/dec_acelp.c b/lib_dec/dec_acelp.c new file mode 100644 index 0000000..ef015c7 --- /dev/null +++ b/lib_dec/dec_acelp.c @@ -0,0 +1,372 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "stl.h" +#include "basop_util.h" +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "prot_fx.h" +#include "rom_basop_util.h" + +#define _1_CODE 0x200 /*codebook excitation Q9 */ + +static void D_ACELP_decode_arithtrack(Word16 v[], Word32 s, Word16 p, Word16 trackstep, Word16 tracklen); + +/*---------------------------------------------------------------------* +* Function D_ACELP_indexing() +* +*---------------------------------------------------------------------*/ + +void D_ACELP_indexing( + Word16 code[], + PulseConfig config, + Word16 num_tracks, + Word16 index[] + ,Word16 *BER_detect +) +{ + Word16 track, pulses, k, pulsestrack[NB_TRACK_FCB_4T]; + Word32 s; + Word16 trackpos; + UWord16 *idxs; + UWord32 idxs32[4], index_n[NB_TRACK_FCB_4T]; + Word16 restpulses, wordcnt, wordcnt32; + + assert(num_tracks == NB_TRACK_FCB_4T); + + wordcnt = shr(add(config.bits,15),4); /* ceil(bits/16) */ + + /* check if some tracks have more pulses */ + restpulses = s_and((Word16)config.nb_pulse, sub(num_tracks, 1)); + + /* cast to short */ + idxs= (UWord16 *)idxs32; + FOR (k=0; k=1; track--) + { + pulses = pulsestrack[track]; + move16(); + + IF (pulses) + { + /* divide by number of possible states: rest is actual state and + * the integer part goes to next track */ + s = index_n[track]; + /* decode state to actual pulse positions on track */ + D_ACELP_decode_arithtrack(code+track, s, pulses, num_tracks, 16); + } + ELSE /* track is empty */ + { + FOR (k=track; k < 16*num_tracks; k+=num_tracks) + { + code[k] = 0; + move16(); + } + } + } + + s = L_add(index_n[0], 0); + pulses = pulsestrack[0]; + move16(); + + /* safety check in case of bit errors */ + IF( GE_32(s,pulsestostates[16][pulses-1])) + { + set16_fx( code, 0, L_SUBFR ); + *BER_detect = 1; + move16(); + return; + } + + IF (pulses) + { + D_ACELP_decode_arithtrack(code, s, pulses, num_tracks, 16); + } + ELSE {/* track is empty */ + FOR (k=0; k < 16*num_tracks; k+=num_tracks) + { + code[k] = 0; + move16(); + } + } + } +} + +static void D_ACELP_decode_arithtrack(Word16 v[], Word32 s, Word16 p, Word16 trackstep, Word16 tracklen) +{ + Word16 k, idx; + + /*initialy s was UWords32 but it seems that s is never greater then 0x80000000*/ + /*this assumption reduces complexity but if it is not true than exit*/ + assert(s >= 0); + + FOR (k=(tracklen)-1; k>= 0; k--) + { + idx = imult1616(k,trackstep); + v[idx] = 0; /* default: there is no pulse here */ move16(); + + FOR(; p; p--) /* one pulse placed, so one less left */ + { + IF (LT_32(s, pulsestostates[k][p-1])) + { + BREAK; + } + + s = L_sub(s, pulsestostates[k][p-1]); + + IF (v[idx] != 0) /* there is a pulse here already = sign is known */ + { + if (v[idx] > 0) + { + v[idx] = add(v[idx],_1_CODE); /* place one more pulse here */ move16(); + } + if (v[idx] <= 0) + { + v[idx] = sub(v[idx],_1_CODE); /* place one more pulse here */ move16(); + } + } + ELSE /* this is the first pulse here -> determine sign */ + { + v[idx] = +_1_CODE; /* place a negative pulse here */ move16(); + if (L_and(s, 0x1) != 0) + { + v[idx] = -_1_CODE; /* place a negative pulse here */ move16(); + } + s = L_lshr(s,1); + } + } + } +} + +void fcb_pulse_track_joint_decode(UWord16 *idxs, Word16 wordcnt, UWord32 *index_n, Word16 *pulse_num, Word16 track_num) +{ + Word16 hi_to_low[10] = { 0, 0, 0, 3, 9, 5, 3, 1, 8, 8}; + + UWord32 index; + Word32 indx_tmp; + Word16 indx_flag, indx_flag_1; + Word16 track, track_num1, pulse_num0, pulse_num1; + Word32 div_tmp; + Word16 indx_flag_2; + + indx_flag = 0; + move16(); + indx_flag_1 = 0; + move16(); + indx_flag_2 = 0; + move16(); + + FOR (track = 0; track < track_num; track++) + { + indx_flag = add(indx_flag, shr(pulse_num[track], 2)); + indx_flag_1 = add(indx_flag_1, shr(pulse_num[track], 1)); + indx_flag_2 = add(indx_flag_2, shr(pulse_num[track], 3)); + } + + hi_to_low[4] = 1; + move16(); + if (GE_16(indx_flag, track_num)) + { + hi_to_low[4] = 9; + move16(); + } + + hi_to_low[7] = 1; + move16(); + if (GE_16(indx_flag_2, 1)) + { + hi_to_low[7] = 9; + move16(); + } + + IF (GE_16(indx_flag_1, track_num)) + { + IF (GE_16(indx_flag, track_num)) + { + index = L_deposit_l(0); + IF (GE_16(indx_flag_2, 1)) + { + FOR (track = sub(wordcnt, 1); track >= 6; track--) + { + index = L_add(L_lshl(index, 16), (UWord32) idxs[track]); + } + index_n[3] = L_add(L_lshl(idxs[5], 8), L_and(L_lshr(idxs[4], 8), 0xFF)); + move32(); + index_n[2] = L_and(L_add(L_lshl(idxs[4], 16), idxs[3]), 0xFFFFFF); + move32(); + index_n[1] = L_add(L_lshl(idxs[2], 8), L_and(L_lshr(idxs[1], 8), 0xFF)); + move32(); + index_n[0] = L_and(L_add(L_lshl(idxs[1], 16), idxs[0]), 0xFFFFFF); + move32(); + } + ELSE + { + FOR (track = (wordcnt-1); track >= track_num; track--) + { + index = L_add(L_lshl(index, 16), (UWord32) idxs[track]); + } + FOR (track = 0; track < track_num; track++) + { + index_n[track] = (UWord32) idxs[track]; + move32(); + } + } + } + ELSE + { + index = L_deposit_l(0); + FOR (track = (wordcnt-1); track >= 2; track--) + { + index = L_add(L_lshl(index, 16), (UWord32) idxs[track]); + } + + index_n[3] = L_and((Word32) idxs[1], 0xFF); + move32(); + index_n[2] = L_lshr((Word32) idxs[1], 8); + move32(); + index_n[1] = L_and((Word32) idxs[0], 0xFF); + move32(); + index_n[0] = L_lshr((Word32) idxs[0], 8); + move32(); + } + + track_num1 = sub(track_num, 1); + pulse_num1 = pulse_num[track_num1]; + move16(); + index = L_add(L_lshl(index, hi_to_low[pulse_num1]), L_lshr(index_n[track_num1], low_len[pulse_num1])); + FOR (track = (track_num-1); track > 0; track--) + { + track_num1 = sub(track, 1); + pulse_num0 = pulse_num[track_num1]; + move16(); + pulse_num1 = pulse_num[track]; + move16(); + index = L_add(L_lshl(index, hi_to_low[pulse_num0]), L_lshr(index_n[track_num1], low_len[pulse_num0])); + + iDiv_and_mod_32(index, indx_fact[pulse_num1], &div_tmp, &indx_tmp, 0); + index_n[track] = L_add(L_and(index_n[track], low_mask[pulse_num1]), L_lshl(indx_tmp, low_len[pulse_num1])); + index = L_add(div_tmp, 0); + } + pulse_num1 = pulse_num[0]; + move16(); + index_n[0] = L_add(L_and(index_n[0], low_mask[pulse_num1]), L_lshl(index, low_len[pulse_num1])); + move32(); + } + ELSE + { + index = L_deposit_l(0); + FOR (track = (wordcnt-1); track >= 0; track--) + { + index = L_add(L_lshl(index, 16), (UWord32) idxs[track]); + } + FOR (track = 3; track > 0; track--) + { + pulse_num1 = pulse_num[track]; + move16(); + index_n[track] = L_and(index, index_mask_ACELP[pulse_num1]); + move32(); + index = L_lshr(index, index_len[pulse_num1]); + } + index_n[0] = index; + move32(); + } + + return; +} + diff --git a/lib_dec/dec_acelp_tcx_main.c b/lib_dec/dec_acelp_tcx_main.c new file mode 100644 index 0000000..dcdfe80 --- /dev/null +++ b/lib_dec/dec_acelp_tcx_main.c @@ -0,0 +1,536 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include "rom_com_fx.h" +#include "stat_com.h" +#include "options.h" +#include "stl.h" +#include "prot_fx.h" +#include "basop_util.h" + +static +void decode_frame_type(Decoder_State_fx *st) +{ + Word32 L_tmp; + Word16 num_bits; + UWord16 lsb; + Word16 frame_size_index; + Word16 n; + Word32 total_brate; + Word16 frame_len_indicator; + + frame_size_index = 0; + move16(); + total_brate = st->total_brate_fx; + move16(); + + Mpy_32_16_ss(st->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + num_bits = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + + + /* Get Frame Type (NULL,SID,ACTIVE) and Frame Mode (2kbps, 4kbps,...) */ + + IF (EQ_16(st->mdct_sw, MODE1)) + { + st->m_frame_type = ACTIVE_FRAME; + move16(); + + FOR (n=0; ntotal_brate_fx, FRAME_NO_DATA)) + { + st->bwidth_fx = st->last_bwidth_fx; + move16(); + st->m_frame_type = ZERO_FRAME; + move16(); + } + + /* SID frame */ + ELSE IF ( EQ_32(st->total_brate_fx, SID_2k40)) + { + st->cng_type_fx = get_next_indice_fx(st, 1); + if( NE_16(st->cng_type_fx, FD_CNG)) + { + st->BER_detect = 1; + } + st->m_frame_type = SID_FRAME; + move16(); + frame_size_index = 1; + move16(); + st->bwidth_fx = get_next_indice_fx(st, 2); + move16(); + + frame_len_indicator = get_next_indice_fx(st, 1); + IF ( EQ_16(st->bwidth_fx, NB)) + { + if( frame_len_indicator ) + { + st->BER_detect = 1; + move16(); + } + frame_len_indicator = 0; + move16(); + } + IF ( frame_len_indicator == 0 ) + { + st->L_frame_fx = L_FRAME; + st->total_brate_fx = 9600; + } + ELSE + { + st->L_frame_fx = L_FRAME16k; + IF ( st->last_total_brate_fx==16400 || st->last_total_brate_fx==24400 ) + { + st->total_brate_fx = st->last_total_brate_fx; + } + ELSE + { + st->total_brate_fx = 16400; + } + } + + Mpy_32_16_ss(st->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + num_bits = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + FOR (n=0; nm_frame_type = ACTIVE_FRAME; + move16(); + + FOR (n=0; nrf_flag == 0) + { + + /* Get bandwidth mode */ + st->bwidth_fx = get_next_indice_fx(st, FrameSizeConfig[frame_size_index].bandwidth_bits); + + st->bwidth_fx = add(st->bwidth_fx, FrameSizeConfig[frame_size_index].bandwidth_min); + + } + ELSE + { + st->bwidth_fx += FrameSizeConfig[frame_size_index].bandwidth_min; + } + + IF (GT_16(st->bwidth_fx, FB)) + { + st->bwidth_fx = FB; + move16(); + st->BER_detect = 1; + move16(); + } + + test(); + IF ( GT_16(st->bwidth_fx, SWB)&<_32(st->total_brate_fx,ACELP_16k40)) + { + st->bwidth_fx = SWB; + move16(); + st->BER_detect = 1; + move16(); + } + + /* Get reserved bits */ + IF (FrameSizeConfig[frame_size_index].reserved_bits && st->rf_flag == 0) + { + Word16 dummyBit; + dummyBit = (Word8)get_next_indice_fx(st, 1); + move16(); + if (dummyBit != 0) + { + st->BER_detect = 1; + move16(); + } + assert( FrameSizeConfig[frame_size_index].reserved_bits == 1); + } + } + } + + st->rate_switching_init = 0; + move16(); + + if( st->last_codec_mode != MODE2 || !st->BER_detect ) + { + /* Mode or Rate Change */ + test(); + test(); + test(); + IF ( (EQ_16(st->m_frame_type, ACTIVE_FRAME)||EQ_16(st->m_frame_type,SID_FRAME))&&(s_or(s_or(s_or(s_or((Word16)NE_32(st->total_brate_fx,st->last_total_brate_fx),(Word16)NE_16(st->bwidth_fx,st->last_bwidth_fx)),(Word16)EQ_16(st->last_codec_mode,MODE1)),(Word16)NE_16(st->rf_flag,st->rf_flag_last)),st->force_lpd_reset))) + { + st->rate_switching_init = 1; + move16(); + + /* Reconf Core */ + mode_switch_decoder_LPD( st, st->bwidth_fx, st->total_brate_fx, frame_size_index ); + + /* Reconf CLDFB */ + IF( NE_16 (i_mult(st->cldfbAna_fx->no_channels,st->cldfbAna_fx->no_col), st->L_frame_fx) ) + { + Word16 newCldfbBands = CLDFB_getNumChannels(L_mult0(st->L_frame_fx,50)); + + resampleCldfb( st->cldfbAna_fx, newCldfbBands, st->L_frame_fx, 0 ); + IF ( LE_16(st->L_frame_fx,L_FRAME16k) ) + { + resampleCldfb( st->cldfbBPF_fx, newCldfbBands, st->L_frame_fx, 0 ); + } + } + IF ( EQ_16(st->bwidth_fx,NB)) + { + st->cldfbSyn_fx->bandsToZero = sub (st->cldfbSyn_fx->no_channels,10); + } + ELSE + { + st->cldfbSyn_fx->bandsToZero = 0; + } + + /* Reconf FD-CNG */ + L_tmp = st->total_brate_fx; + move32(); + test(); + if( EQ_16(st->rf_flag,1)&&EQ_32(st->total_brate_fx,ACELP_13k20)) + { + L_tmp = ACELP_9k60; + move32(); + } + configureFdCngDec( st->hFdCngDec_fx, st->bwidth_fx, L_tmp, st->L_frame_fx ); + test(); + test(); + IF ( (NE_16(st->last_L_frame_fx,st->L_frame_fx))&&(LE_16(st->L_frame_fx,320))&&(LE_16(st->last_L_frame_fx,320))) + { + lerp( st->hFdCngDec_fx->hFdCngCom->olapBufferSynth2, st->hFdCngDec_fx->hFdCngCom->olapBufferSynth2, st->L_frame_fx*2, st->last_L_frame_fx*2 ); + test(); + IF ( EQ_16(st->m_frame_type, SID_FRAME)&&NE_16(st->hFdCngDec_fx->hFdCngCom->frame_type_previous,ACTIVE_FRAME)) + { + lerp( st->hFdCngDec_fx->hFdCngCom->olapBufferSynth, st->hFdCngDec_fx->hFdCngCom->olapBufferSynth, st->L_frame_fx*2, st->last_L_frame_fx*2 ); + + IF( EQ_16(st->L_frame_fx, L_FRAME)) + { + FOR( n=0; n < st->L_frame_fx*2; n++ ) + { + st->hFdCngDec_fx->hFdCngCom->olapBufferSynth[n] = mult_r( st->hFdCngDec_fx->hFdCngCom->olapBufferSynth[n], 20480 ); + } + } + ELSE + { + FOR( n=0; n < st->L_frame_fx*2; n++ ) + { + st->hFdCngDec_fx->hFdCngCom->olapBufferSynth[n] = mult_r( shl(st->hFdCngDec_fx->hFdCngCom->olapBufferSynth[n],1), 26214 ); + } + } + } + } + IF ( NE_16(st->bwidth_fx,st->last_bwidth_fx)) + { + st->hFdCngDec_fx->hFdCngCom->msFrCnt_init_counter = 0; + st->hFdCngDec_fx->hFdCngCom->init_old = 32767; + } + + /* Reconf BPF */ + st->p_bpf_noise_buf=NULL; + IF (st->tcxonly == 0) + { + st->p_bpf_noise_buf = st->bpf_noise_buf; + } + } + } + + st->total_brate_fx = total_brate; + +} + + +Word16 dec_acelp_tcx_frame(Decoder_State_fx *st, + Word16 *coder_type, + Word16 *concealWholeFrame, + Word16 *pcmBuf, + Word16 * bpf_noise_buf, + Word16 * pcmbufFB, + Word32 bwe_exc_extended[], /* i/o: bandwidth extended excitation */ + Word16 *voice_factors, /* o : voicing factors */ + Word16 pitch_buf[] /* o : floating pitch for each subframe */ + ) +{ + Word16 num_bits; + Word32 L_tmp; + UWord16 lsb; + Word16 bitsRead; + Word16 tmp; + Word16 i; + Word16 start_bit_pos; + Word16 param[DEC_NPRM_DIV*NB_DIV+NPRM_LPC_NEW]; + Word16 old_bwe_exc[(PIT16k_MAX + (L_FRAME16k + 1) + L_SUBFR16k) * 2]; /* excitation buffer */ + Word16 *ptr_bwe_exc; /* pointer to BWE excitation signal in the current frame */ + + Mpy_32_16_ss(st->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + num_bits = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + + /* -------------------------------------------------------------- */ + /* Set the bit-stream */ + /* -------------------------------------------------------------- */ + + + start_bit_pos = st->next_bit_pos_fx; + move16(); + + if( EQ_16(st->rf_flag,1)) + { + start_bit_pos = sub(start_bit_pos,2); + } + /* -------------------------------------------------------------- */ + /* IDENTIFY FRAME TYPE */ + /* -------------------------------------------------------------- */ + + st->m_old_frame_type = st->m_frame_type; + move16(); + + IF ( *concealWholeFrame == 0) + { + + Word16 m_frame_type = st->m_frame_type; + Word16 bwidth = st->bwidth_fx; + Word16 cng_type = st->cng_type_fx; + Word16 L_frame = st->L_frame_fx; + Word32 total_brate = st->last_total_brate_fx; + + decode_frame_type( st ); + + st->force_lpd_reset = 0; + + test(); + test(); + test(); + test(); + IF( (EQ_16(st->last_codec_mode, MODE2))&&(st->BER_detect||(st->prev_bfi_fx&&(EQ_16(st->m_frame_type,ZERO_FRAME))&&(EQ_16(st->m_old_frame_type,ACTIVE_FRAME))))) + { + /* Copy back parameters from previous frame, because there is a high risk they are corrupt + * DO concealment with configuration used in previous frame */ + st->m_frame_type = m_frame_type; + move16(); + st->bwidth_fx = bwidth; + move16(); + st->cng_type_fx = cng_type; + move16(); + st->L_frame_fx = L_frame; + move16(); + if( st->ini_frame_fx != 0 ) + { + st->total_brate_fx = total_brate; + move32(); + } + + *concealWholeFrame = 1; + move16(); + st->m_decodeMode = DEC_CONCEALMENT_EXT; + move16(); + st->BER_detect = 0; + move16(); + + test(); + test(); + IF( (NE_16(st->bwidth_fx, st->last_bwidth_fx))||(NE_16(st->rf_flag,st->rf_flag_last))||(NE_32(st->total_brate_fx,st->last_total_brate_fx))) + { + st->force_lpd_reset = 1; + move16(); + } + + st->core_brate_fx = st->last_core_brate_fx; + move32(); + st->bfi_fx = 1; + move16(); + IF(st->ini_frame_fx == 0 ) + { + st->tcx_cfg.tcx_coded_lines = getNumTcxCodedLines(SWB); + } + } + ELSE + { + st->core_brate_fx = st->total_brate_fx; + move32(); + bpf_noise_buf = st->p_bpf_noise_buf; + move16(); + } + } + + IF( *concealWholeFrame != 0 ) + { + /* add two zero bytes for arithmetic coder flush */ + FOR( i=0; i<8*2; i++ ) + { + st->bit_stream_fx[i] = 0; + } + } + + + IF ( s_and((Word16)NE_16(st->m_frame_type,SID_FRAME),(Word16)NE_16(st->m_frame_type,ZERO_FRAME))) /* test */ + { + + /* -------------------------------------------------------------- */ + /* DECODE CORE */ + /* -------------------------------------------------------------- */ + + tmp = sub(num_bits, sub(st->next_bit_pos_fx, start_bit_pos)); + bitsRead = 0; + move16(); + + set16_fx( old_bwe_exc + PIT16k_MAX * 2, 0, ((L_FRAME16k + 1) + L_SUBFR16k) * 2 ); + ptr_bwe_exc = old_bwe_exc + PIT16k_MAX * 2; + Copy( st->old_bwe_exc_fx, old_bwe_exc, PIT16k_MAX * 2 ); + + IF ( EQ_16(st->m_decodeMode, DEC_NO_FRAM_LOSS)) + { + decoder_LPD(pcmBuf, + pcmbufFB, + &tmp, + st, + bpf_noise_buf, + 0, + &bitsRead, + coder_type, + param, + pitch_buf, + voice_factors, + ptr_bwe_exc + ); + + test(); + test(); + test(); + test(); + test(); + IF( st->rate_switching_init == 0 && EQ_16((st->last_codec_mode), MODE2)&&!(st->use_partial_copy&&GE_16(st->rf_frame_type,RF_TCXFD)&&LE_16(st->rf_frame_type,RF_TCXTD2))&&EQ_16(st->bfi_fx,1)) + { + *concealWholeFrame = 1; + move16(); + st->m_decodeMode = DEC_CONCEALMENT_EXT; + move16(); + st->BER_detect = 0; + move16(); + } + + } + ELSE IF (EQ_16(st->m_decodeMode, DEC_CONCEALMENT_EXT)) + { + /* Decode the LPD data */ + decoder_LPD( pcmBuf, + pcmbufFB, + NULL, + st, + bpf_noise_buf, + 1, + &bitsRead, + coder_type, + NULL, + pitch_buf, + voice_factors, + ptr_bwe_exc + ); + } + + test(); + test(); + test(); + test(); + IF( ( st->bfi_fx == 0 && (EQ_16(st->prev_bfi_fx, 1)||EQ_16(st->prev_use_partial_copy,1)))||((EQ_16(st->last_vbr_hw_BWE_disable_dec_fx,1))&&(st->vbr_hw_BWE_disable_dec_fx==0))) + { + st->bwe_non_lin_prev_scale_fx = 0; + set16_fx( st->old_bwe_exc_extended_fx, 0, NL_BUFF_OFFSET ); + } + + test(); + test(); + IF( st->core_fx == ACELP_CORE && st->igf != 0 && st->con_tcx == 0) + { + non_linearity_fx( ptr_bwe_exc, bwe_exc_extended, L_FRAME32k, &st->bwe_non_lin_prev_scale_fx, st->Q_exc, + *coder_type, voice_factors, st->L_frame_fx + ); + + /* update the old BWE exe memory */ + Copy( &old_bwe_exc[L_FRAME32k], st->old_bwe_exc_fx, PIT16k_MAX * 2 ); + } + ELSE + { + set16_fx( st->old_bwe_exc_extended_fx, 0, NL_BUFF_OFFSET ); + set16_fx( st->old_bwe_exc_fx, 0, PIT16k_MAX * 2 ); + st->bwe_non_lin_prev_scale_fx = 0; + move32(); + } + + /* for ACELP mode, skip core data to read TD-BWE side info */ + test(); + test(); + IF( (!st->bfi_fx) && EQ_16(st->core_fx,ACELP_CORE)&&st->total_brate_fx>0) + { + /* target bs-position "-3": -2 as earlier "start_bit_pos -= 2;" are included in st->rf_target_bits + -1 as flag-bit not considered in rf_target_bits */ + IF (EQ_16(st->rf_flag, 1)) + { + get_next_indice_tmp_fx(st, start_bit_pos + num_bits - st->rf_target_bits - 3 - get_tbe_bits_fx(st->total_brate_fx, st->bwidth_fx, st->rf_flag) - st->next_bit_pos_fx); + } + ELSE + { + get_next_indice_tmp_fx(st, start_bit_pos + num_bits - st->rf_target_bits - get_tbe_bits_fx(st->total_brate_fx, st->bwidth_fx, st->rf_flag) - st->next_bit_pos_fx); + } + tbe_read_bitstream_fx(st); + } + + /* updates */ + st->last_voice_factor_fx = voice_factors[st->nb_subfr-1];; + move16(); + st->last_coder_type_fx = *coder_type; + + } + ELSE + { + + IF ( EQ_16(st->m_frame_type,SID_FRAME)) + { + FdCng_decodeSID(st->hFdCngDec_fx->hFdCngCom, st); + } + + /* updates */ + st->last_voice_factor_fx = 0; + move16(); + st->last_coder_type_fx = INACTIVE; + move16(); + } + + return 0; +} diff --git a/lib_dec/dec_amr_wb_fx.c b/lib_dec/dec_amr_wb_fx.c new file mode 100644 index 0000000..60e4078 --- /dev/null +++ b/lib_dec/dec_amr_wb_fx.c @@ -0,0 +1,139 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + + +/*---------------------------------------------------------------------* + * decod_amr_wb() + * + * Decode excitation signal in AMR-WB IO mode + *---------------------------------------------------------------------*/ + +void decod_amr_wb_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + const Word16 *Aq_fx, /* i : LP filter coefficients */ + Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe */ + Word16 *exc_fx, /* i/o: adapt. excitation exc */ + Word16 *exc2_fx, /* i/o: adapt. excitation/total exc */ + Word16 hf_gain_fx[NB_SUBFR], /* o : decoded HF gain */ + Word16 *voice_factors_fx, /* o : voicing factors */ + Word16 *gain_buf /* o : Q14 */ +) +{ + Word16 T0, T0_frac, T0_min, T0_max; /* integer pitch variables */ + Word16 gain_pit_fx, gain_code16; /* pitch gain */ + Word32 L_gain_code_fx; /* gain/normalized gain of the algebraic excitation */ + Word32 L_norm_gain_code_fx; /* normalized gain of the algebraic excitation */ + Word16 gain_inov_fx; /* Innovation gain */ + Word16 voice_fac_fx; /* voicing factor */ + Word16 code_fx[L_SUBFR]; /* algebraic codevector */ + const Word16 *p_Aq_fx; /* Pointer to frame LP coefficient */ + Word16 *pt_pitch_fx; /* pointer to floating pitch */ + Word16 i_subfr; /* tmp variables */ + Word16 pitch_limit_flag; + Word32 L_Voice_fac_ave, L_tmp; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + p_Aq_fx = Aq_fx; /* pointer to interpolated LPC parameters */ + pt_pitch_fx = pitch_buf_fx; /* pointer to the pitch buffer */ + L_Voice_fac_ave = L_deposit_l(0); + pitch_limit_flag = 0; + move16(); /* always restrained pitch Q range in IO mode */ + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + + FOR( i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR ) + { + /*----------------------------------------------------------------------* + * Decode pitch lag + *----------------------------------------------------------------------*/ + + *pt_pitch_fx = pit_decode_fx( st_fx, st_fx->core_brate_fx, 1, L_FRAME, i_subfr, -1, &pitch_limit_flag, &T0, &T0_frac, &T0_min, &T0_max, L_SUBFR ); + + /*--------------------------------------------------------------* + * Find the adaptive codebook vector + *--------------------------------------------------------------*/ + + pred_lt4(&exc_fx[i_subfr],&exc_fx[i_subfr], T0, T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP); + + /*--------------------------------------------------------------* + * LP filtering of the adaptive excitation + *--------------------------------------------------------------*/ + + lp_filt_exc_dec_fx( st_fx, MODE1, st_fx->core_brate_fx, 1, -1, i_subfr, L_SUBFR, L_FRAME, 0, exc_fx ); + + /*--------------------------------------------------------------* + * Innovation decoding + *--------------------------------------------------------------*/ + + inov_decode_fx( st_fx, st_fx->core_brate_fx, 1, L_FRAME, -1, 0, i_subfr, -1, p_Aq_fx, st_fx->tilt_code_fx, *pt_pitch_fx, code_fx); + + /*--------------------------------------------------------------* + * Gain decoding + * Estimate spectrum tilt and voicing + *--------------------------------------------------------------*/ + + gain_dec_amr_wb_fx( st_fx, st_fx->core_brate_fx, &gain_pit_fx, &L_gain_code_fx, st_fx->past_qua_en_fx, &gain_inov_fx, code_fx, &L_norm_gain_code_fx ); + + /* update LP filtered gains for the case of frame erasures */ + lp_gain_updt_fx( i_subfr, gain_pit_fx, L_norm_gain_code_fx, &st_fx->lp_gainp_fx, &st_fx->lp_gainc_fx, L_FRAME ); + + st_fx->tilt_code_fx = est_tilt_fx( exc_fx+i_subfr, gain_pit_fx, code_fx, L_gain_code_fx, &voice_fac_fx, st_fx->Q_exc ); + + Rescale_exc( st_fx->dct_post_old_exc_fx, &exc_fx[i_subfr], NULL, st_fx->last_exc_dct_in_fx, L_SUBFR, 0, + L_gain_code_fx, &(st_fx->Q_exc), st_fx->Q_subfr, exc2_fx, i_subfr, -1 ); + + gain_code16 = round_fx(L_shl(L_gain_code_fx,st_fx->Q_exc)); /*Q_exc*/ + + /*----------------------------------------------------------------------* + * Find the total excitation + *----------------------------------------------------------------------*/ + + Acelp_dec_total_exc( exc_fx, exc2_fx, gain_code16, gain_pit_fx, i_subfr, code_fx ); + + /*----------------------------------------------------------------* + * Excitation enhancements + *----------------------------------------------------------------*/ + + enhancer_fx( st_fx->core_brate_fx, 1, -1, i_subfr, L_FRAME, voice_fac_fx, st_fx->stab_fac_fx, + L_norm_gain_code_fx, gain_inov_fx, &st_fx->gc_threshold_fx, code_fx, exc2_fx, gain_pit_fx, &(st_fx->dm_fx),st_fx->Q_exc ); + + /*-----------------------------------------------------------------* + * HF gain modification factors at 23.85 kbps + *-----------------------------------------------------------------*/ + + IF ( EQ_32(st_fx->core_brate_fx,ACELP_23k85)) + { + hf_gain_fx[shr(i_subfr,6)] = (Word16)get_next_indice_fx(st_fx, 4); + } + + /*voice_fac = VF_0th_PARAM + VF_1st_PARAM * voice_fac + VF_2nd_PARAM * voice_fac * voice_fac;*/ + L_tmp = L_mult(VF_2nd_PARAM_FX, mult_r(voice_fac_fx, voice_fac_fx)); + L_tmp = L_mac(L_tmp, VF_1st_PARAM_FX, voice_fac_fx); + voice_fac_fx = mac_r(L_tmp, VF_0th_PARAM_FX, 32767); + + /*voice_factors[i_subfr/L_SUBFR] = min( max(0.0f, voice_fac), 1.0f);*/ + voice_factors_fx[i_subfr/L_SUBFR] = s_min(s_max(0, voice_fac_fx),32767); + move16(); + p_Aq_fx += (M+1); + pt_pitch_fx++; + + L_Voice_fac_ave = L_mac(L_Voice_fac_ave, 8192, voice_fac_fx); + gain_buf[i_subfr/L_SUBFR] = gain_pit_fx; + } + + st_fx->lt_voice_fac_fx = round_fx(L_Voice_fac_ave); + + return; +} diff --git a/lib_dec/dec_gen_voic_fx.c b/lib_dec/dec_gen_voic_fx.c new file mode 100644 index 0000000..99aeced --- /dev/null +++ b/lib_dec/dec_gen_voic_fx.c @@ -0,0 +1,443 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "basop_util.h" + + +/*======================================================================*/ +/* FUNCTION : decod_gen_voic_fx() */ +/*----------------------------------------------------------------------*/ +/* PURPOSE : Decode generic (GC), voiced (VC) and AMR-WB IO frames */ +/* */ +/*----------------------------------------------------------------------*/ +/* GLOBAL INPUT ARGUMENTS : */ +/* _ (Struct) st_fx : decoder static memory */ +/* _ (Word16) L_frame_fx : length of the frame */ + +/* _ (Word16[]) Aq_fx : LP filter coefficient Q12 */ +/* _ (Word16) coder_type_fx : coding type Q12 */ +/* _ (Word16) Es_pred_fx : predicted scaled innov. energy Q8 */ +/* _ (Word16[]) pitch_buf_fx : floating pitch values for each subframe Q6*/ +/* _ (Word16[]) voice_factors_fx: frame error rate Q15 */ +/*----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Q_exc) */ +/* _ (Word16[]) exc2_fx : adapt. excitation/total exc (Q_exc) */ +/*----------------------------------------------------------------------*/ + + +/*----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*======================================================================*/ + +void decod_gen_voic_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + const Word16 L_frame_fx, /* i : length of the frame */ + const Word16 sharpFlag_fx, /* i : formant sharpening flag */ + const Word16 *Aq_fx, /* i : LP filter coefficient */ + const Word16 coder_type_fx, /* i : coding type */ + const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */ + const Word16 do_WI_fx, /* i : do interpolation after a FER */ + Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe */ + Word16 *voice_factors_fx, /* o : voicing factors */ + Word16 *exc_fx, /* i/o: adapt. excitation exc */ + Word16 *exc2_fx, /* i/o: adapt. excitation/total exc */ + Word16 *bwe_exc_fx, /* o : excitation for SWB TBE */ + Word16 *unbits, /* number of unused bits */ + Word16 *gain_buf +) +{ + + + Word16 T0_fx, T0_frac_fx, T0_min_fx, T0_max_fx;/* integer pitch variables */ + Word16 gain_pit_fx = 0; /* pitch gain Q14 */ + Word32 gain_code_fx=0; /* gain/normalized gain of the algebraic excitation Q16 */ + Word32 norm_gain_code_fx=0; /* normalized gain of the algebraic excitation Q16 */ + Word16 gain_inov_fx=0; /* Innovation gain Q12 */ + Word32 gc_mem[NB_SUBFR-1]; /* gain_code from previous subframes */ + Word16 gp_mem[NB_SUBFR-1]; /* gain_pitch from previous subframes */ + Word16 voice_fac_fx; /* voicing factor Q15 */ + Word16 code_fx[L_SUBFR]; /* algebraic codevector Q12 */ + + const Word16 *p_Aq_fx; /* Pointer to frame LP coefficient Q12 */ + Word16 *pt_pitch_fx; /* pointer to floating pitch Q6 */ + Word16 i_subfr_fx, i; /* tmp variables */ + Word16 error_fx = 0; + Word16 gain_preQ_fx = 0; /* Gain of prequantizer excitation */ + Word16 code_preQ_fx[L_SUBFR]; /* Prequantizer excitation */ + Word32 norm_gain_preQ_fx; + Word16 pitch_limit_flag_fx; + + Word16 tmp1_fx,gain_code16; + Word32 L_tmp_GC; + Word32 L_tmp; + + Word16 harm_flag_acelp; + + Word16 shft_prev, ph_offset_fx; + Word32 prev_res_nrg; + Word32 prev_spch_nrg; + Word32 curr_res_nrg; + Word32 curr_spch_nrg; + Word16 rint_bfi_pitch, rint_pitch; + Word16 fraca, fracb, expa, expb, scale, exp1; + Word16 *p_exc; + Word16 mem_tmp_fx[M]; + Word16 syn_tmp_fx[L_FRAME16k]; + Word16 shft_curr; + Word16 *p_syn; + Word16 sp_enratio, Qsp_enratio; + Word16 enratio, Qenratio; + DTFS_STRUCTURE_FX *PREVP, *CURRP; + Word16 S_fx[PIT_MAX*4+1], C_fx[PIT_MAX*4+1]; + Word16 dummy2[2]; + Word16 out_fx[L_FRAME16k]; + + Word16 pf_temp1[MAXLAG_WI]; /*may not need more than MAXLAG_WI/2+1 */ + Word16 pf_temp2[MAXLAG_WI]; + Word16 pf_temp[MAXLAG_WI]; + Word16 pf_n2[MAXLAG_WI]; + + + + T0_fx = PIT_MIN; + move16(); + T0_frac_fx = 0; + move16(); + + /* read harmonicity flag */ + harm_flag_acelp = 0; + move16(); + test(); + test(); + IF( (GT_32(st_fx->core_brate_fx,ACELP_24k40)&&LE_32(st_fx->core_brate_fx,ACELP_32k))&&EQ_16(coder_type_fx,GENERIC)) + { + harm_flag_acelp = (Word16)get_next_indice_fx( st_fx, 1 ); + } + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + + p_Aq_fx = Aq_fx; + move16(); /* pointer to interpolated LPC parameters */ + pt_pitch_fx = pitch_buf_fx; + move16(); /* pointer to the pitch buffer */ + norm_gain_preQ_fx = 0; + move16(); + gain_preQ_fx = 0; + move16(); + set16_fx( code_preQ_fx, 0, L_SUBFR ); + + FOR( i_subfr_fx = 0; i_subfr_fx < L_frame_fx; i_subfr_fx += L_SUBFR ) + { + /*----------------------------------------------------------------------* + * Decode pitch lag + *----------------------------------------------------------------------*/ + + *pt_pitch_fx = pit_decode_fx( st_fx, st_fx->core_brate_fx, 0, L_frame_fx, i_subfr_fx, coder_type_fx, &pitch_limit_flag_fx, + &T0_fx, &T0_frac_fx, &T0_min_fx, &T0_max_fx, L_SUBFR ); + move16(); /*Q6*/ + + /*--------------------------------------------------------------* + * Find the adaptive codebook vector + *--------------------------------------------------------------*/ + + pred_lt4( &exc_fx[i_subfr_fx], &exc_fx[i_subfr_fx], T0_fx, T0_frac_fx, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + tbe_celp_exc( L_frame_fx,i_subfr_fx,T0_fx, T0_frac_fx, &error_fx, bwe_exc_fx ); + + /*--------------------------------------------------------------* + * LP filtering of the adaptive excitation + *--------------------------------------------------------------*/ + + lp_filt_exc_dec_fx( st_fx, MODE1, st_fx->core_brate_fx, 0, coder_type_fx, i_subfr_fx, L_SUBFR, L_frame_fx, 0, exc_fx ); + + /*-----------------------------------------------------------------* + * Transform-domain contribution decoding (active frames) + *-----------------------------------------------------------------*/ + + test(); + IF( GT_32(st_fx->core_brate_fx,ACELP_24k40)&&NE_16(coder_type_fx,INACTIVE)) + { + gain_code_fx = 0; + move16(); + transf_cdbk_dec_fx( st_fx, st_fx->core_brate_fx, coder_type_fx, harm_flag_acelp, i_subfr_fx, -1, Es_pred_fx, gain_code_fx, &st_fx->mem_preemp_preQ_fx, + &gain_preQ_fx, &norm_gain_preQ_fx, code_preQ_fx, unbits ); + } + + /*--------------------------------------------------------------* + * Innovation decoding + *--------------------------------------------------------------*/ + + inov_decode_fx( st_fx, st_fx->core_brate_fx, 0, L_frame_fx, coder_type_fx, + sharpFlag_fx, i_subfr_fx, -1, p_Aq_fx, st_fx->tilt_code_fx, *pt_pitch_fx, code_fx ); + + /*--------------------------------------------------------------* + * Gain decoding + * Estimate spectrum tilt and voicing + *--------------------------------------------------------------*/ + + IF( LE_32(st_fx->core_brate_fx,ACELP_8k00)) + { + gain_dec_lbr_fx( st_fx, st_fx->core_brate_fx, coder_type_fx, i_subfr_fx, code_fx, &gain_pit_fx, &gain_code_fx, &gain_inov_fx, &norm_gain_code_fx, gc_mem, gp_mem ); + } + ELSE IF( GT_32(st_fx->core_brate_fx,ACELP_32k)) + { + gain_dec_SQ_fx( st_fx, st_fx->core_brate_fx, coder_type_fx, i_subfr_fx, -1, code_fx, Es_pred_fx, &gain_pit_fx, &gain_code_fx, &gain_inov_fx, &norm_gain_code_fx ); + } + ELSE + { + gain_dec_mless_fx( st_fx, st_fx->core_brate_fx, L_frame_fx, coder_type_fx, i_subfr_fx, -1, code_fx, Es_pred_fx, &gain_pit_fx, &gain_code_fx, &gain_inov_fx, &norm_gain_code_fx ); + } + st_fx->tilt_code_fx = est_tilt_fx( exc_fx+i_subfr_fx, gain_pit_fx, code_fx, gain_code_fx, &voice_fac_fx, st_fx->Q_exc ); + + /*-----------------------------------------------------------------* + * Transform domain contribution decoding + *-----------------------------------------------------------------*/ + test(); + IF( GT_32( st_fx->core_brate_fx,ACELP_24k40)&&EQ_16(coder_type_fx,INACTIVE)) + { + transf_cdbk_dec_fx( st_fx, st_fx->core_brate_fx, coder_type_fx, harm_flag_acelp, i_subfr_fx, -1, Es_pred_fx, gain_code_fx, &st_fx->mem_preemp_preQ_fx, + &gain_preQ_fx, &norm_gain_preQ_fx, code_preQ_fx, unbits ); + } + + /* update LP filtered gains for the case of frame erasures */ + lp_gain_updt_fx( i_subfr_fx, gain_pit_fx, L_add(norm_gain_code_fx,norm_gain_preQ_fx), &st_fx->lp_gainp_fx, &st_fx->lp_gainc_fx, L_frame_fx ); + + /*----------------------------------------------------------------------* + * Find the total excitation + *----------------------------------------------------------------------*/ + + IF ( EQ_16(L_frame_fx,L_FRAME)) /* Rescaling for 12.8k core */ + { + Rescale_exc( st_fx->dct_post_old_exc_fx, &exc_fx[i_subfr_fx], &bwe_exc_fx[i_subfr_fx * HIBND_ACB_L_FAC], st_fx->last_exc_dct_in_fx, + L_SUBFR, L_SUBFR * HIBND_ACB_L_FAC, gain_code_fx, &(st_fx->Q_exc), st_fx->Q_subfr, exc2_fx, i_subfr_fx, coder_type_fx ); + + } + ELSE /* Rescaling for 16k core */ + { + L_tmp_GC = L_max(gain_code_fx, L_shl(gain_preQ_fx,16)); /* Chose the maximum of gain_code or the prequantizer excitation x4 to keep some room*/ + Rescale_exc( st_fx->dct_post_old_exc_fx, &exc_fx[i_subfr_fx], &bwe_exc_fx[i_subfr_fx * 2], st_fx->last_exc_dct_in_fx, + L_SUBFR, L_SUBFR * 2, L_tmp_GC, &(st_fx->Q_exc), st_fx->Q_subfr, exc2_fx, i_subfr_fx, coder_type_fx ); + } + + gain_code16 = round_fx(L_shl(gain_code_fx,st_fx->Q_exc)); /*Q_exc*/ + + /*-----------------------------------------------------------------* + * Add the ACELP pre-quantizer contribution + *-----------------------------------------------------------------*/ + + IF( GT_32(st_fx->core_brate_fx,ACELP_24k40)) + { + tmp1_fx = add(15-Q_AVQ_OUT_DEC-2,st_fx->Q_exc); + FOR( i = 0; i < L_SUBFR; i++ ) + { + Word32 Ltmp1; + /* Contribution from AVQ layer */ + Ltmp1 = L_mult(gain_preQ_fx, code_preQ_fx[i]); /* Q2 + Q6 -> Q9*/ + Ltmp1 = L_shl(Ltmp1,tmp1_fx); /* Q16 + Q_exc */ + + /* Compute exc2 */ + L_tmp = L_shl(L_mult(gain_pit_fx,exc_fx[i+i_subfr_fx]),1); + exc2_fx[i+i_subfr_fx] = round_fx(L_add(L_tmp, Ltmp1)); + + /* code in Q9, gain_pit in Q14 */ + L_tmp = L_mult(gain_code16, code_fx[i]); + L_tmp = L_shl(L_tmp, 5); + L_tmp = L_mac(L_tmp, exc_fx[i + i_subfr_fx], gain_pit_fx); + L_tmp = L_shl(L_tmp, 1); /* saturation can occur here */ + + exc_fx[i+i_subfr_fx] = round_fx(L_add(L_tmp, Ltmp1)); + } + } + ELSE + { + Acelp_dec_total_exc( exc_fx, exc2_fx, gain_code16, gain_pit_fx, i_subfr_fx, code_fx ); + } + + /*-----------------------------------------------------------------* + * Prepare TBE excitation + *-----------------------------------------------------------------*/ + + prep_tbe_exc_fx( L_frame_fx, i_subfr_fx, gain_pit_fx, gain_code_fx, code_fx, voice_fac_fx, + &voice_factors_fx[i_subfr_fx/L_SUBFR], bwe_exc_fx, gain_preQ_fx, code_preQ_fx, + st_fx->Q_exc, T0_fx, T0_frac_fx, coder_type_fx, st_fx->core_brate_fx ); + + + /*----------------------------------------------------------------* + * Excitation enhancements (update of total excitation signal) + *----------------------------------------------------------------*/ + + test(); + IF( GT_32(st_fx->core_brate_fx,ACELP_32k)||EQ_16(coder_type_fx,INACTIVE)) + { + Copy( exc_fx+i_subfr_fx, exc2_fx+i_subfr_fx, L_SUBFR ); + } + ELSE + { + enhancer_fx( st_fx->core_brate_fx, 0, coder_type_fx, i_subfr_fx, L_frame_fx, voice_fac_fx, st_fx->stab_fac_fx, + norm_gain_code_fx, gain_inov_fx, &st_fx->gc_threshold_fx, code_fx, exc2_fx, gain_pit_fx, &(st_fx->dm_fx), st_fx->Q_exc ); + } + + p_Aq_fx += (M+1); + move16(); + pt_pitch_fx++; + gain_buf[i_subfr_fx/L_SUBFR] = gain_pit_fx; + move16(); + } + + /* FEC fast recovery */ + + IF( do_WI_fx ) + { + /* shft_prev = L_EXC_MEM - rint_new_fx(st_fx->bfi_pitch_fx);*/ + L_tmp = L_shl(L_deposit_l(st_fx->bfi_pitch_fx),10); /*Q16*/ + rint_bfi_pitch = rint_new_fx(L_tmp); /*Q0*/ + shft_prev = sub( L_EXC_MEM, rint_bfi_pitch ); /*Q0*/ + + p_exc = st_fx->old_exc2_fx + shft_prev; + move16(); + p_syn = st_fx->old_syn2_fx + shft_prev; + move16(); + + prev_res_nrg = L_deposit_l(1); + prev_spch_nrg = L_deposit_l(1); + FOR( i=0; iprev_Q_exc_fr */ + prev_spch_nrg = L_mac0(prev_spch_nrg, *p_syn, *p_syn); /* 2*st_fx->prev_Q_syn_fr */ + p_exc++; + p_syn++; + } + + Copy( st_fx->mem_syn2_fx, mem_tmp_fx, M ); + + syn_12k8_fx( st_fx->L_frame_fx, Aq_fx, exc2_fx, syn_tmp_fx, mem_tmp_fx, 1, st_fx->Q_exc, st_fx->Q_syn ); + + L_tmp = L_shl(L_deposit_l(pitch_buf_fx[NB_SUBFR16k-1]),10); /*Q16*/ + rint_pitch = rint_new_fx(L_tmp); /*Q0*/ + shft_curr = sub( st_fx->L_frame_fx, rint_pitch ); /*Q0*/ + + p_exc = exc2_fx + shft_curr; + move16(); + p_syn = syn_tmp_fx + shft_curr; + move16(); + + curr_res_nrg = L_deposit_l(1); + curr_spch_nrg = L_deposit_l(1); + FOR( i=0; iQ_exc */ + curr_spch_nrg = L_mac0(curr_spch_nrg, *p_syn, *p_syn); /* 2*st_fx->Q_syn */ + p_exc++; + p_syn++; + } + + /* enratio = (curr_res_nrg / prev_res_nrg); */ + IF(prev_res_nrg>0) + { + expa = norm_l(prev_res_nrg); + fraca = extract_h(L_shl(prev_res_nrg,expa)); + expa = sub(30,expa+(2*st_fx->prev_Q_exc_fr)); + + expb = norm_l(curr_res_nrg); + fracb = round_fx(L_shl(curr_res_nrg,expb)); + expb = sub(30,expb+(2*st_fx->Q_exc)); + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + enratio = div_s(fracb,fraca); + exp1 = sub(expb,expa); + Qenratio = 15-exp1; + } + ELSE + { + enratio = 0; + Qenratio = 0; + } + + /* sp_enratio = curr_spch_nrg/prev_spch_nrg */ + IF(prev_spch_nrg>0) + { + expa = norm_l(prev_spch_nrg); + fraca = extract_h(L_shl(prev_spch_nrg,expa)); + expa = sub(30,expa+(2*st_fx->prev_Q_syn_fr)); + + expb = norm_l(curr_spch_nrg); + fracb = round_fx(L_shl(curr_spch_nrg,expb)); + expb = sub(30,expb+(2*st_fx->Q_syn)); + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + sp_enratio = div_s(fracb,fraca); + exp1 = sub(expb,expa); + Qsp_enratio = 15-exp1; + } + ELSE + { + sp_enratio = 0; + Qsp_enratio = 0; + } + + test(); + test(); + test(); + test(); + IF ( GT_16(shl_r(enratio,15-Qenratio), 8192)&& /*compare with 0.25 in Q15*/ + LT_16(shl_r(enratio,10-Qenratio), 15360) && /*compare with 15.0 in Q10*/ + GT_16(shl_r(sp_enratio,15-Qsp_enratio), 4915) &&/*compare with 0.15 in Q15*/ + st_fx->bfi_pitch_fx < 9600 && /*Q6*/ + pitch_buf_fx[ sub( NB_SUBFR16k, 1 ) ] < 9600 ) /*Q6*/ + { + PREVP = DTFS_new_fx(); + CURRP = DTFS_new_fx(); + + GetSinCosTab_fx(rint_bfi_pitch,S_fx,C_fx); + DTFS_to_fs_fx( st_fx->old_exc2_fx + shft_prev, rint_bfi_pitch, PREVP, (Word16)st_fx->output_Fs_fx, do_WI_fx, S_fx, C_fx); + PREVP->Q = add(PREVP->Q, st_fx->prev_Q_exc_fr); + + GetSinCosTab_fx(rint_pitch,S_fx,C_fx); + DTFS_to_fs_fx( exc2_fx + shft_curr, rint_pitch, CURRP, (Word16)st_fx->output_Fs_fx, do_WI_fx, S_fx, C_fx); + CURRP->Q = add(CURRP->Q, st_fx->Q_exc); + + ph_offset_fx = 0; + move16(); + WIsyn_fx(*PREVP, CURRP, dummy2, &(ph_offset_fx), out_fx, (Word16)st_fx->L_frame_fx, 1, S_fx, C_fx, pf_temp1, pf_temp2, pf_temp, pf_n2); + + + Copy_Scale_sig( out_fx, exc2_fx, st_fx->L_frame_fx, st_fx->Q_exc ); + Copy_Scale_sig( out_fx, exc_fx, st_fx->L_frame_fx, st_fx->Q_exc ); + + /* update bwe_exc for SWB-TBE */ + FOR (i_subfr_fx = 0; i_subfr_fx < L_frame_fx; i_subfr_fx += L_SUBFR) + { + interp_code_4over2_fx( exc_fx + i_subfr_fx, bwe_exc_fx + (i_subfr_fx*2), L_SUBFR ); + } + + free(PREVP); + free(CURRP); + } + + } + + /* SC-VBR */ + st_fx->prev_gain_pit_dec_fx = gain_pit_fx; + move16(); /*Q14*/ + st_fx->prev_tilt_code_dec_fx = st_fx->tilt_code_fx; + move16(); /*Q15*/ + + return; +} diff --git a/lib_dec/dec_higher_acelp_fx.c b/lib_dec/dec_higher_acelp_fx.c new file mode 100644 index 0000000..983a7d1 --- /dev/null +++ b/lib_dec/dec_higher_acelp_fx.c @@ -0,0 +1,266 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" + +/*-----------------------------------------------------------------* + * Transform domain contribution decoding + *-----------------------------------------------------------------*/ +void transf_cdbk_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 coder_type, /* i : coding type */ + const Word16 harm_flag_acelp,/* i : harmonic flag for higher rates ACELP */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 Es_pred, /* i : predicited scaled innovation energy (Q8) */ + const Word32 gain_code, /* i : innovative excitation gain (Q16) */ + Word16 *mem_preemp, /* i/o: dequantizer preemhasis memory */ + Word16 *gain_preQ, /* o : prequantizer excitation gain (Q2) */ + Word32 *norm_gain_preQ,/* o : normalized prequantizer excitation gain (Q16) */ + Word16 code_preQ[], /* o : prequantizer excitation (Q8) */ + Word16 *unbits /* o : number of AVQ unused bits */ +) +{ + Word16 i, index, nBits; + Word16 nq[L_SUBFR/WIDTH_BAND]; + Word16 gain16, exp16, tmp16; + Word32 L_tmp; + Word32 dct_code32[L_SUBFR]; + Word16 qdct; + + /*--------------------------------------------------------------* + * Set bit-allocation + *--------------------------------------------------------------*/ + + nBits = AVQ_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx( core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ_fx(tc_subfr))]; + move16(); + + /* increase # of AVQ allocated bits by unused bits from the previous subframe */ + nBits = add(nBits,*unbits); + + /*--------------------------------------------------------------* + * Dequantize prequantizer excitation gain + *--------------------------------------------------------------*/ + + index = (Word16)get_next_indice_fx(st_fx, G_AVQ_BITS ); + + IF( EQ_16(coder_type,INACTIVE)) + { + IF( EQ_32(core_brate,ACELP_64k)) + { + gain16 = usdequant_fx( index, G_AVQ_MIN_INACT_64k_Q12, G_AVQ_DELTA_INACT_64k_Q12>>1 ); + } + ELSE IF( EQ_32(core_brate,ACELP_48k)) + { + gain16 = usdequant_fx( index, G_AVQ_MIN_INACT_48k_Q12, G_AVQ_DELTA_INACT_48k_Q12>>1 ); + } + ELSE + { + gain16 = usdequant_fx( index, G_AVQ_MIN_INACT_Q12, G_AVQ_DELTA_INACT_Q12>>1 ); + } + + L_tmp = Mult_32_16(gain_code,gain16); /* Q16 * Q12 - 15 -> Q13*/ + L_tmp = L_shl(L_tmp,5); /* Q13 -> Q18*/ + *gain_preQ = round_fx(L_tmp); /* Q2*/ + } + ELSE + { + IF( LE_32(core_brate,ACELP_32k)) + { + gain16 = gain_dequant_fx( index, G_AVQ_MIN_32kbps_Q15, G_AVQ_MAX_Q0, G_AVQ_BITS, &exp16 ); + } + ELSE + { + gain16 = gain_dequant_fx( index, G_AVQ_MIN_Q15, G_AVQ_MAX_Q0, G_AVQ_BITS, &exp16 ); + } + + IF( Es_pred < 0 ) + { + tmp16 = shr(negate(Es_pred),2); + L_tmp = L_mult(gain16,tmp16); /* Q0*Q8 -> Q9*/ + } + ELSE + { + L_tmp = L_mult(gain16,Es_pred); /* Q0*Q8 -> Q9*/ + } + L_tmp = L_shl(L_tmp,add(exp16,9)); /* Q18*/ + *gain_preQ = round_fx(L_tmp); /* Q2*/ + } + + /*--------------------------------------------------------------* + * Demultiplex and decode subvectors from bit-stream + *--------------------------------------------------------------*/ + + AVQ_demuxdec_fx(st_fx, code_preQ, &nBits, 8, nq ); + + FOR( i=0; ilast_nq_preQ_fx, nq[0]), 7))) + { + /* *mem_preemp /= 16; */ + *mem_preemp = shr(*mem_preemp,4); + move16(); + } + st_fx->last_nq_preQ_fx = nq[7]; + move16(); + + preemph_fx( code_preQ, FAC_PRE_AVQ_FX, L_SUBFR, mem_preemp ); + + /*--------------------------------------------------------------* + * Compute normalized prequantizer excitation gain for FEC + * + * somewhat attenuate pre-quantizer normalized gain for FEC + *--------------------------------------------------------------*/ + + /*Ecode = (sum2_f( code_preQ, L_SUBFR ) + 0.01f) / L_SUBFR;*/ + /*norm_gain_preQ = 0.8f * (*gain_preQ) * (float)sqrt( Ecode );*/ + + L_tmp = Dot_product12(code_preQ, code_preQ, L_SUBFR, &exp16); + + IF( EQ_32(L_tmp,L_shl(1,sub(30,exp16)))) + { + /* pre-quantizer contribution is zero */ + *norm_gain_preQ = 1; + move16(); + } + ELSE + { + exp16 = sub(exp16, Q_AVQ_OUT_DEC*2 + 6); /* exp: (code_preQ in Q_AVQ_OUT_DEC), -6 (/L_SUBFR) */ + L_tmp = Isqrt_lc(L_tmp, &exp16); + tmp16 = extract_h(L_tmp); + exp16 = 15 - 10 - exp16; /* tmp16 in Q10+exp16*/ + tmp16 = div_s(16384,tmp16); /* Q15+Q14-(Q10+Qexp16) = Q19-exp16*/ + + L_tmp = L_mult(*gain_preQ,tmp16); /* Q2+Q19-exp16+1 -> Q22-exp16 */ + L_tmp = Mult_32_16(L_tmp, 26214 ); /* Q22-Qexp16+Q15+1-16 -> Q22-exp16*/ + *norm_gain_preQ = L_shr(L_tmp,6-exp16); + move32(); /* Q22-exp16 -> Q16*/ + } + + + st_fx->use_acelp_preq = 1; + move16(); + + return; + +} + +/*==========================================================================*/ +/* FUNCTION : Word16 gain_dequant_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : */ +/* * Returns decoded gain quantized between the specified */ +/* * range using the specified number of levels. */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 index i: quantization index */ +/* Word16 min i : value of lower limit */ +/* Word16 max i : value of upper limit */ +/* Word16 bits i : number of bits to dequantize */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _Word16 *expg o : */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* Word16 gain Q0 */ +/*--------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*==========================================================================*/ +Word16 gain_dequant_fx( /* o: decoded gain */ + Word16 index, /* i: quantization index */ + const Word16 min, /* i: value of lower limit */ + const Word16 max, /* i: value of upper limit */ + const Word16 bits, /* i: number of bits to dequantize */ + Word16 *expg +) +{ + Word16 gain, c_min, c_max; + Word16 levels; + Word16 e_tmp, f_tmp; + Word16 tmp, frac; + Word32 L_tmp; + levels = 1<Q16*/ + + frac = L_Extract_lc(L_tmp, expg); /* Extract exponent of gcode0 */ + + gain = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + *expg = sub(*expg, 14); + + return( gain ); +} diff --git a/lib_dec/dec_nelp_fx.c b/lib_dec/dec_nelp_fx.c new file mode 100644 index 0000000..c5bdc84 --- /dev/null +++ b/lib_dec/dec_nelp_fx.c @@ -0,0 +1,92 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*======================================================================*/ +/* FUNCTION : decod_nelp_fx() */ +/*-----------------------------------------------------------------------*/ +/* PURPOSE : Decode unvoiced NELP */ +/* */ +/*-----------------------------------------------------------------------*/ +/* GLOBAL INPUT ARGUMENTS : */ +/* _ (Struct) st_fx : decoder static memory */ +/* _ (Word16) coder_type : coding type */ +/* _ (Word16[]) tmp_noise_fx : long term temporary noise energy */ +/* _ (Word16[]) pitch_buf_fx : floating pitch values for each + subframe(Q6) */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Q_exc) */ +/* _ (Word16[]) exc2_fx : adapt. excitation/total exc (Q_exc) */ +/* _ (Word16) bfi : frame error rate */ +/*-----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Q_exc) */ +/* _ (Word16[]) exc2_fx : adapt. excitation/total exc (Q_exc) */ +/*-----------------------------------------------------------------------*/ + +/* _ (Word16[]) tmp_noise_fx : long term temporary noise energy + (Q0) */ +/* _ (Word16[]) pitch_buf_fx : floating pitch values for each + subframe (Q6) */ +/* _ (Word16[]) st_fx->dispMem : Noise enhancer - phase dispersion + algorithm memory (Q14) */ +/* _ (Word16) st_fx->tilt_code : tilt of code (Q15) */ +/* _ (Word16) st_fx->prev_gain_pit_dec */ +/*-----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*=======================================================================*/ + +void decod_nelp_fx( + Decoder_State_fx *st_fx, + const Word16 coder_type, + Word16 *tmp_noise_fx, + Word16 *pitch_buf_fx, + Word16 *exc_fx, + Word16 *exc2_fx, + Word16 *voice_factors, + Word16 *bwe_exc_fx, + Word16 *Q_exc, Word16 bfi + , Word16 *gain_buf +) +{ + Word16 i; + Word16 exc_nelp_fx[L_FRAME]; + + *tmp_noise_fx = 0; + move16(); + + nelp_decoder_fx(st_fx, exc_nelp_fx, exc_fx, Q_exc, bfi, coder_type + , gain_buf + + ); + + Copy(exc_nelp_fx, exc_fx, L_FRAME); + Copy(exc_nelp_fx, exc2_fx, L_FRAME); + + st_fx->tilt_code_fx = 0; + move16();/* purely unvoiced */ /* Q15 */ + set16_fx(st_fx->tilt_code_dec_fx, 0, NB_SUBFR16k); + + st_fx->dm_fx.prev_state = 0; + move16();/* Q0 */ + st_fx->prev_gain_pit_dec_fx = 0; + move16(); /* Q14 */ + st_fx->dm_fx.prev_gain_pit[0]= st_fx->prev_gain_pit_dec_fx; + move16(); /* Q16 */ + + FOR(i=1; i<5; i++) + { + st_fx->dm_fx.prev_gain_pit[i] = st_fx->dm_fx.prev_gain_pit[i-1]; + move16(); /* Q14 */ + } + + set16_fx(pitch_buf_fx, L_SUBFR_Q6, NB_SUBFR); /* L_SUBFR = 64, Q6 */ + set16_fx(voice_factors, 0, NB_SUBFR16k); + interp_code_5over2_fx( exc2_fx, bwe_exc_fx, L_FRAME ); + return; +} diff --git a/lib_dec/dec_pit_exc_fx.c b/lib_dec/dec_pit_exc_fx.c new file mode 100644 index 0000000..508735c --- /dev/null +++ b/lib_dec/dec_pit_exc_fx.c @@ -0,0 +1,260 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + + +/*==========================================================================*/ +/* FUNCTION : void dec_pit_exc_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Decode pitch only contribution */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16*) Aq_fx : LP filter coefficient Q12 */ +/* _ (Word16) coder_type_fx : coding type Q0 */ +/* _ (Word16) nb_subfr_fx :Number of subframe considered */ +/* _ (Word16) Es_pred_fx :predicted scaled innov. energy */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) pitch_buf_fx : floating pitch values for each subframe Q6 */ +/* _ (Word16*) code_fx : innovation */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Decoder_State_fx *st_fx : decoder state structure */ +/* _ (Word16*) exc_fx : adapt. excitation exc */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*==========================================================================*/ +void dec_pit_exc_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + const Word16 *Aq_fx, /* i : LP filter coefficient */ + const Word16 coder_type_fx, /* i : coding type */ + const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */ + Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe */ + Word16 *code_fx, /* o : innovation */ + Word16 *exc_fx, /* i/o: adapt. excitation exc */ + Word16 *bwe_exc_fx, /* o : excitation for SWB TBE */ + const Word16 nb_subfr_fx /* i : Number of subframe considered */ + , Word16 *gain_buf /*Q14*/ +) +{ + Word16 T0_fx, T0_frac_fx, T0_min_fx, T0_max_fx;/* integer pitch variables */ + Word16 gain_pit_fx = 0; /* pitch gain Q14 */ + Word32 gain_code_fx; /* gain/normalized gain of the algebraic excitation Q16 */ + Word32 norm_gain_code_fx; /* normalized gain of the algebraic excitation Q16 */ + Word16 gain_inov_fx; /* Innovation gain Q12 */ + Word16 voice_fac_fx; /* voicing factor Q15 */ + Word16 L_subfr_fx,pit_idx_fx; + const Word16 *p_Aq_fx; /* Pointer to frame LP coefficient Q12 */ + Word16 *pt_pitch_fx; /* pointer to floating pitch Q6 */ + Word16 i_subfr_fx, i; /* tmp variables */ + Word16 Local_BR_fx, Pitch_BR_fx, Pitch_CT_fx; + Word16 pitch_limit_flag; + Word16 exc2_bidon[L_SUBFR]; + Word16 *pt_gain; /* Pointer to floating gain values for each subframe */ + + Word16 gain_code16,gain_pitx2; + Word32 L_tmp; + Word16 nbits; + + IF( EQ_16(st_fx->GSC_noisy_speech_fx,1)) + { + Local_BR_fx = ACELP_7k20; + move16(); + Pitch_CT_fx = GENERIC; + move16(); + Pitch_BR_fx = ACELP_7k20; + move16(); + } + ELSE + { + Local_BR_fx = ACELP_7k20; + move16(); + Pitch_CT_fx = AUDIO; + move16(); + Pitch_BR_fx = extract_l(st_fx->core_brate_fx); + } + gain_code_fx = 0; + move16(); + pitch_limit_flag = 1; + move16();/* always extended pitch Q range */ + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + L_subfr_fx = mult_r(L_FRAME,div_s(1,nb_subfr_fx)); + p_Aq_fx = Aq_fx; /* pointer to interpolated LPC parameters */ + pt_pitch_fx = pitch_buf_fx; /* pointer to the pitch buffer */ + pt_gain = gain_buf; /* pointer to the gain buffer */ + FOR ( i_subfr_fx = 0; i_subfr_fx < L_FRAME; i_subfr_fx += L_subfr_fx ) + { + /*----------------------------------------------------------------------* + * Decode pitch lag + *----------------------------------------------------------------------*/ + + *pt_pitch_fx = pit_decode_fx( st_fx, Pitch_BR_fx, 0, L_FRAME, i_subfr_fx, Pitch_CT_fx, &pitch_limit_flag, &T0_fx, &T0_frac_fx, &T0_min_fx, &T0_max_fx, L_subfr_fx ); + move16(); + + /*--------------------------------------------------------------* + * Find the adaptive codebook vector. + *--------------------------------------------------------------*/ + + pred_lt4( &exc_fx[i_subfr_fx], &exc_fx[i_subfr_fx], T0_fx, T0_frac_fx, L_subfr_fx+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + /*--------------------------------------------------------------* + * Innovation decoding + *--------------------------------------------------------------*/ + + IF( EQ_16(st_fx->GSC_noisy_speech_fx,1)) + { + inov_decode_fx( st_fx, Local_BR_fx, 0, L_FRAME, LOCAL_CT, 1, i_subfr_fx, -1, p_Aq_fx, st_fx->tilt_code_fx, *pt_pitch_fx, code_fx ); + /*--------------------------------------------------------------* + * Gain decoding + * Estimate spectrum tilt and voicing + *--------------------------------------------------------------*/ + + gain_dec_mless_fx( st_fx, Local_BR_fx, L_FRAME, LOCAL_CT, i_subfr_fx, -1, code_fx, Es_pred_fx, &gain_pit_fx, &gain_code_fx, &gain_inov_fx, &norm_gain_code_fx ); + + st_fx->tilt_code_fx = est_tilt_fx( exc_fx+i_subfr_fx, gain_pit_fx, code_fx, gain_code_fx, &voice_fac_fx,0 ); + } + ELSE + { + nbits = 4; + move16(); + + set16_fx(code_fx, 0, L_SUBFR); + gain_code_fx = L_deposit_l(0); + st_fx->tilt_code_fx = 0; + move16(); + pit_idx_fx = (Word16)get_next_indice_fx( st_fx, nbits ); + move16(); + + gain_pit_fx = add(9590,dic_gp_fx[pit_idx_fx]); + move16(); /*Q14 0.5853 in Q14 9590*/ + + if( st_fx->BER_detect ) /* Bitstream is corrupted, use the past pitch gain */ + { + gain_pit_fx = st_fx->lp_gainp_fx; + move16(); + } + gain_code_fx = L_mult0(s_max(sub(32767, shl(gain_pit_fx,1)), 16384), st_fx->lp_gainc_fx); /* Use gain pitch and past gain code as an indicator to help finding the best scaling value. gain_code_fx used a temp var*/ + } + + /*----------------------------------------------------------------------* + * Find the total excitation + *----------------------------------------------------------------------*/ + + Rescale_exc( st_fx->dct_post_old_exc_fx, &exc_fx[i_subfr_fx], &bwe_exc_fx[i_subfr_fx * HIBND_ACB_L_FAC], st_fx->last_exc_dct_in_fx, + L_subfr_fx, L_subfr_fx * HIBND_ACB_L_FAC, gain_code_fx, &(st_fx->Q_exc), st_fx->Q_subfr, NULL, i_subfr_fx, coder_type_fx); + + gain_code16 = round_fx(L_shl(gain_code_fx,st_fx->Q_exc)); /*Q_exc*/ + + IF( EQ_16(st_fx->GSC_noisy_speech_fx,1)) + { + Acelp_dec_total_exc( exc_fx, exc2_bidon-i_subfr_fx, gain_code16, gain_pit_fx, i_subfr_fx, code_fx ); + } + ELSE + { + IF (norm_s(s_or(gain_pit_fx, 1)) == 0) + { + FOR (i = 0; i < L_subfr_fx; i++) + { + L_tmp = L_shl(L_mult(gain_pit_fx, exc_fx[i+i_subfr_fx]), 1); /*Q16+Q_exc*/ + exc_fx[i+i_subfr_fx] = round_fx(L_tmp); /*Q_exc*/ + } + } + ELSE + { + gain_pitx2 = shl(gain_pit_fx, 1); /*Q15*/ + + FOR (i = 0; i < L_subfr_fx; i++) + { + L_tmp = L_mult(gain_pitx2, exc_fx[i+i_subfr_fx]); /*Q16+Q_exc*/ + exc_fx[i+i_subfr_fx] = round_fx(L_tmp); /*Q_exc*/ + } + } + } + IF( EQ_16(L_subfr_fx,128)) /*2*L_SUBFR*/ + { + p_Aq_fx += 2*(M+1); + move16(); + pt_pitch_fx++; + *pt_pitch_fx = *(pt_pitch_fx-1); + move16(); + pt_pitch_fx++; + *pt_gain = gain_pit_fx; + move16(); + pt_gain++; + *pt_gain = *(pt_gain-1); + move16(); + pt_gain++; + IF( i_subfr_fx == 0 ) + { + /* update gains for FEC - equivalent to lp_gain_updt() */ + st_fx->lp_gainp_fx = extract_h(L_mult(9830,gain_pit_fx)); /*Q14 (3/10 in Q15 9830)*/ + st_fx->lp_gainc_fx = 0; + move16(); + } + ELSE + { + /* update gains for FEC - equivalent to lp_gain_updt() */ + st_fx->lp_gainp_fx = extract_h(L_mult(22938,gain_pit_fx)); /*Q14 (7/10 in Q15 22938)*/ + st_fx->lp_gainc_fx = 0; + move16(); + } + } + ELSE IF( EQ_16(L_subfr_fx,256)) /*4*L_SUBFR*/ + { + pt_pitch_fx++; + *pt_pitch_fx = *(pt_pitch_fx-1); + move16(); + pt_pitch_fx++; + *pt_pitch_fx = *(pt_pitch_fx-1); + move16(); + pt_pitch_fx++; + *pt_pitch_fx = *(pt_pitch_fx-1); + move16(); + pt_pitch_fx++; + *pt_gain = gain_pit_fx; + move16(); + pt_gain++; + *pt_gain = *(pt_gain-1); + move16(); + pt_gain++; + *pt_gain = *(pt_gain-1); + move16(); + pt_gain++; + *pt_gain = *(pt_gain-1); + move16(); + pt_gain++; + p_Aq_fx += 4*(M+1); + move16(); + + /* update gains for FEC - equivalent to lp_gain_updt() */ + st_fx->lp_gainp_fx = gain_pit_fx; + move16(); + st_fx->lp_gainc_fx = 0; + move16(); + } + ELSE + { + p_Aq_fx += (M+1); + move16(); + pt_pitch_fx++; + move16(); + *pt_gain = gain_pit_fx; + move16(); + pt_gain++; + + lp_gain_updt_fx( i_subfr_fx, gain_pit_fx, 0, &st_fx->lp_gainp_fx, &st_fx->lp_gainc_fx, L_FRAME ); + } + } + + return; +} diff --git a/lib_dec/dec_post.c b/lib_dec/dec_post.c new file mode 100644 index 0000000..23687b3 --- /dev/null +++ b/lib_dec/dec_post.c @@ -0,0 +1,1540 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "stl.h" /* Weighted mops computation related code */ +#include "rom_dec_fx.h" +#include "cnst_fx.h" + +#define FORMAT_POST_FILT_G1 24576/*0.75f Q15*/ /*0.75f*/ /*denominator 0.9,0.75,0.15,0.9*/ +#define FORMAT_POST_FILT_G2 22938/*0.7f Q15*/ /*0.7f*/ /*numerator 0.75,0.7,0.1,0.7*/ +#define FORMAT_POST_FILT_G1_MAX 26214/*0.8f Q15*/ /*for low bit-rates on clean speech*/ +#define FORMAT_POST_FILT_G1_MIN 24576/*0.75f Q15*/ /*for high bit-rates on clean speech and noisy speech*/ + +/*-------------------------------------------------------------------------- + * Local functions + *--------------------------------------------------------------------------*/ + +static void Dec_postfilt( PFSTAT * pfstat, const Word16 t0, const Word16 *signal_ptr, const Word16 *coeff, + Word16 *sig_out, const Word16 gamma1, const Word16 gamma2, const Word16 Gain_factor, const Word16 disable_hpf ); + +static void pst_ltp( Word16 t0, Word16 * ptr_sig_in, Word16 * ptr_sig_pst0, Word16 gain_factor ); + +static void search_del( Word16 t0, Word16 * ptr_sig_in, Word16 * ltpdel, Word16 * phase, Word16 * num_gltp, Word16 * den_gltp, + Word16 * sh_num_gltp, Word16 * sh_den_gltp, Word16 * y_up, Word16 * off_yup ); + +static void filt_plt( Word16 * s_in, Word16 * s_ltp, Word16 * s_out, Word16 gain_plt ); + +static void compute_ltp_l( Word16 * s_in, Word16 ltpdel, Word16 phase, Word16 * y_up, Word16 * num, Word16 * den, Word16 * sh_num, Word16 * sh_den ); + +static Word16 select_ltp( Word16 num1, Word16 den1, Word16 sh_num1, Word16 sh_den1, Word16 num2, Word16 den2, Word16 sh_num2, Word16 sh_den2 ); + +static void calc_st_filt( Word16 * apond2, Word16 * apond1, Word16 * parcor0, Word16 * sig_ltp_ptr, Word16 * mem_zero ); + +static void modify_pst_param( const Word16 lp_noise, Word16 *g1, Word16 *g2, const Word16 coder_type, Word16 *gain_factor ); + +static void Dec_formant_postfilt( PFSTAT *pfstat, Word16 *signal_ptr, Word16 *coeff, Word16 *sig_out, Word16 gamma1, Word16 gamma2 ); + + +/*-------------------------------------------------------------------------- + * Init_post_filter + * + * post filter initialization + *--------------------------------------------------------------------------*/ +void Init_post_filter( + PFSTAT * pfstat /* i : core decoder parameters */ +) +{ + /* It is off by default */ + pfstat->on = 0; + + /* Reset */ + pfstat->reset = 0; + + /* Initialize arrays and pointers */ + set16_fx(pfstat->mem_pf_in, 0, L_SUBFR); + + /* res2 = A(gamma2) residual */ + set16_fx(pfstat->mem_res2, 0, DECMEM_RES2); + + /* 1/A(gamma1) memory */ + set16_fx(pfstat->mem_stp, 0, L_SUBFR); + + /* null memory to compute i.r. of A(gamma2)/A(gamma1) */ + set16_fx(pfstat->mem_zero, 0, M); + + /* for gain adjustment */ + pfstat->gain_prec = 16384; /*Q14*/ move16(); + + return; +} + +/*-------------------------------------------------------------------------- + * NB_post_filt: + * + * Main routine to perform post filtering on NB synthesis + *--------------------------------------------------------------------------*/ +void nb_post_filt( + const Word16 L_frame, /* i : frame length */ + PFSTAT *Pfstat, /* i/o: Post filter related memories */ + Word16 *psf_lp_noise, /* i : Long term noise Q8 */ + const Word16 tmp_noise, /* i : noise energy Q0 */ + Word16 *Synth, /* i : 12k8 synthesis Qsyn */ + const Word16 *Aq, /* i : LP filter coefficient Q12 */ + const Word16 *Pitch_buf, /* i : Fractionnal subframe pitch buffer Q6 */ + const Word16 coder_type, /* i : coder_type */ + const Word16 BER_detect, /* i : BER detect flag */ + const Word16 disable_hpf /* i : flag to diabled HPF */ +) +{ + Word16 i, j, Post_G1, Post_G2, Gain_factor; + Word16 T0_first, *Pf_in; + const Word16 *p_Aq; + Word16 pf_in_buffer[M+L_FRAME16k]; + + IF( BER_detect == 0 ) + { + /* update long-term background noise energy during inactive frames */ + IF( EQ_16(coder_type,INACTIVE)) + { + *psf_lp_noise = round_fx(L_mac(L_mult(31130, *psf_lp_noise), 26214 /*0.05 Q19*/, shl(tmp_noise,4))); /*Q8*Q15 + Q19*Q4 -> Q8 */ + } + } + + modify_pst_param( *psf_lp_noise, &Post_G1, &Post_G2, coder_type, &Gain_factor ); + + if(Pfstat->reset) + { + set16_fx(Pfstat->mem_res2, 0, DECMEM_RES2); + Copy( &Synth[L_frame-L_SYN_MEM], Pfstat->mem_pf_in, L_SYN_MEM); + Copy( &Synth[L_frame-L_SYN_MEM], Pfstat->mem_stp, L_SYN_MEM ); + Pfstat->gain_prec = 16384; + move16(); + Pfstat->reset = 0; + move16(); + return; + } + Pf_in = &pf_in_buffer[M]; + Copy( Pfstat->mem_pf_in+L_SYN_MEM-M, &Pf_in[-M], M ); + Copy( Synth, Pf_in, L_frame ); + Copy( &Synth[L_frame - L_SYN_MEM], Pfstat->mem_pf_in, L_SYN_MEM ); + /* deactivation of the post filter in case of AUDIO because it causes problems to singing sequences */ + if( EQ_16(coder_type,AUDIO)) + { + Post_G1 = 32767; + move16(); + Post_G2 = 32767; + move16(); + Gain_factor = 32767; + move16(); + } + + + /* run the post filter */ + p_Aq = Aq; + move16(); + j = 0; + move16(); + FOR (i = 0; i < L_frame; i += L_SUBFR) + { + T0_first = Pitch_buf[j]; + + Dec_postfilt( Pfstat, T0_first, &Pf_in[i], p_Aq, &Synth[i], Post_G1, Post_G2, Gain_factor, disable_hpf ); + + p_Aq += (M+1); + j = add(j,1); + } + + + return; +} + +/*---------------------------------------------------------------------------- + * Dec_postfilt() + * + * Post - adaptive postfilter main function + * Short term postfilter : + * Hst(z) = Hst0(z) Hst1(z) + * Hst0(z) = 1/g0 A(gamma2)(z) / A(gamma1)(z) + * if {hi} = i.r. filter A(gamma2)/A(gamma1) (truncated) + * g0 = SUM(|hi|) if > 1 + * g0 = 1. else + * Hst1(z) = 1/(1 - |mu|) (1 + mu z-1) + * with mu = k1 * gamma3 + * k1 = 1st parcor calculated on {hi} + * gamma3 = gamma3_minus if k1<0, gamma3_plus if k1>0 + * Long term postfilter : + * harmonic postfilter : H0(z) = gl * (1 + b * z-p) + * b = gamma_g * gain_ltp + * gl = 1 / 1 + b + * computation of delay p on A(gamma2)(z) s(z) + * sub optimal search + * 1. search around 1st subframe delay (3 integer values) + * 2. search around best integer with fract. delays (1/8) + *----------------------------------------------------------------------------*/ +static void Dec_postfilt( + PFSTAT * pfstat, /* i/o: states strucure */ + const Word16 t0, /* i : pitch delay given by coder */ + const Word16 * signal_ptr, /* i : input signal (pointer to current subframe */ + const Word16 * coeff, /* i : LPC coefficients for current subframe */ + Word16 * sig_out, /* o : postfiltered output */ + const Word16 gamma1, /* i : short term postfilt. den. weighting factor */ + const Word16 gamma2, /* i : short term postfilt. num. weighting factor */ + const Word16 Gain_factor, /* i : Gain Factor (Q15) */ + const Word16 disable_hpf +) +{ + /* Local variables and arrays */ + Word16 apond1[M+1]; /* s.t. denominator coeff. */ + Word16 apond2[LONG_H_ST]; + Word16 sig_ltp[L_SUBFR+1]; /* H0 output signal */ + Word16 res2[SIZ_RES2]; + + Word16 *sig_ltp_ptr; + Word16 *res2_ptr; + Word16 *ptr_mem_stp; + + Word16 parcor0; + + + /* Init pointers and restore memories */ + res2_ptr = res2 + DECMEM_RES2; + ptr_mem_stp = pfstat->mem_stp + L_SYN_MEM - 1; + Copy(pfstat->mem_res2, res2, DECMEM_RES2); + + /* Compute weighted LPC coefficients */ + weight_a_fx(coeff, apond1, gamma1, M); + weight_a_fx(coeff, apond2, gamma2, M); + set16_fx(&apond2[M+1], 0, LONG_H_ST-(M+1)); + + /* Compute A(gamma2) residual */ + Residu3_fx(apond2, signal_ptr, res2_ptr, L_SUBFR, 1); + + /* Harmonic filtering */ + sig_ltp_ptr = sig_ltp + 1; + + IF (disable_hpf == 0) + { + pst_ltp( t0, res2_ptr, sig_ltp_ptr, Gain_factor ); + } + ELSE + { + Copy(res2_ptr, sig_ltp_ptr, L_SUBFR); + } + + /* Save last output of 1/A(gamma1) */ + /* (from preceding subframe) */ + sig_ltp[0] = *ptr_mem_stp; + move16(); + + /* Controls short term pst filter gain and compute parcor0 */ + calc_st_filt(apond2, apond1, &parcor0, sig_ltp_ptr, pfstat->mem_zero ); + + E_UTIL_synthesis(1, apond1, sig_ltp_ptr, sig_ltp_ptr, L_SUBFR, pfstat->mem_stp+L_SYN_MEM-M, 0, M); + Copy( sig_ltp_ptr+L_SUBFR-L_SYN_MEM, pfstat->mem_stp, L_SYN_MEM ); + + /* Tilt filtering */ + Filt_mu(sig_ltp, sig_out, parcor0, L_SUBFR); + + /* Gain control */ + scale_st(signal_ptr, sig_out, &pfstat->gain_prec, L_SUBFR); + + /* Update for next subframe */ + Copy(&res2[L_SUBFR], pfstat->mem_res2, DECMEM_RES2); + + + return; +} + +/*-------------------------------------------------------------------------- + * formant_post_filt: + * + * Main routine to perform formant post filtering + *--------------------------------------------------------------------------*/ +void formant_post_filt( + PFSTAT *pfstat, /* i/o: Post filter related memories */ + Word16 *synth_in, /* i : 12k8 synthesis */ + Word16 *Aq, /* i : LP filter coefficient */ + Word16 *synth_out, /* i/o: input signal */ + Word16 L_frame, + Word32 lp_noise, /* (i) : background noise energy (15Q16) */ + Word32 rate, /* (i) : bit-rate */ + const Word16 off_flag /* i : off flag */ +) +{ + Word16 i_subfr; + Word16 *p_Aq; + Word16 post_G1, post_G2; + + + /*default parameter for noisy speech and high bit-rates*/ + IF (EQ_16(L_frame, L_FRAME)) + { + post_G2 = 22938/*0.7f Q15*/; + move16(); + IF (LT_32(lp_noise, LP_NOISE_THRESH)) + { + /*Clean speech*/ + IF (LT_32(rate, ACELP_13k20)) + { + /*Low rates*/ + + post_G1 = 26214/*0.8f Q15*/; + move16(); + } + ELSE IF (LT_32(rate, ACELP_24k40)) + { + /*Low rates*/ + + post_G1 = 24576/*0.75f Q15*/; + move16(); + } + ELSE + { + post_G1 = 23593/*0.72f Q15*/; + move16(); + } + } + ELSE /*Noisy speech*/ + { + post_G1 = 22938/*0.7f Q15*/; + move16(); + if (LT_32(rate, ACELP_15k85)) + { + /*Low rates*/ + post_G1 = 24576/*0.75f Q15*/; + move16(); + } + } + } + ELSE + { + post_G2 = 24904/*0.76f Q15*/; + move16(); + test(); + IF (GE_32(lp_noise, LP_NOISE_THRESH)) + { + post_G1 = 24904/*0.76f Q15*/; + } + ELSE IF (EQ_32(rate, ACELP_13k20)) + { + post_G1 = 26870/*0.82f Q15*/; + move16(); + } + ELSE IF (EQ_32(rate, ACELP_16k40)) + { + post_G1 = 26214/*0.80f Q15*/; + move16(); + } + ELSE IF (EQ_32(rate, ACELP_24k40)||EQ_32(rate,ACELP_32k)) + { + post_G1 = 25559/*0.78f Q15*/; + move16(); + } + ELSE + { + post_G1 = 24904/*0.76f Q15*/; + move16(); + } + } + + /* Switch off post-filter */ + if( off_flag != 0 ) + { + post_G1 = post_G2; + move16(); + } + + /* Reset post filter */ + if( pfstat->reset != 0 ) + { + post_G1 = MAX16B; + move16(); + post_G2 = MAX16B; + move16(); + pfstat->reset = 0; + move16(); + Copy( &synth_in[L_frame-L_SYN_MEM], pfstat->mem_pf_in, L_SYN_MEM); + Copy( &synth_in[L_frame-L_SYN_MEM], pfstat->mem_stp, L_SYN_MEM ); + pfstat->gain_prec = 16384; + move16(); + Copy( synth_in,synth_out, L_frame ); + + return; + } + + /* input memory*/ + Copy( pfstat->mem_pf_in, synth_in-L_SYN_MEM, L_SYN_MEM); + Copy( &synth_in[L_frame-L_SYN_MEM], pfstat->mem_pf_in, L_SYN_MEM); + + move16(); + p_Aq = Aq; + FOR (i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR ) + { + Dec_formant_postfilt( pfstat, &synth_in[i_subfr], p_Aq, &synth_out[i_subfr], post_G1, post_G2 ); + p_Aq += (M+1); + } + +} + +/*---------------------------------------------------------------------------- + * Dec_postfilt + * + * Post - adaptive postfilter main function + * Short term postfilter : + * Hst(z) = Hst0(z) Hst1(z) + * Hst0(z) = 1/g0 A(gamma2)(z) / A(gamma1)(z) + * if {hi} = i.r. filter A(gamma2)/A(gamma1) (truncated) + * g0 = SUM(|hi|) if > 1 + * g0 = 1. else + * Hst1(z) = 1/(1 - |mu|) (1 + mu z-1) + * with mu = k1 * gamma3 + * k1 = 1st parcor calculated on {hi} + * gamma3 = gamma3_minus if k1<0, gamma3_plus if k1>0 + *----------------------------------------------------------------------------*/ +static void Dec_formant_postfilt( + PFSTAT *pfstat, /* i/o: states strucure */ + Word16 *signal_ptr, /* i : input signal (pointer to current subframe */ + Word16 *coeff, /* i : LPC coefficients for current subframe */ + Word16 *sig_out, /* o : postfiltered output */ + Word16 gamma1, /* i : short term postfilt. den. weighting factor*/ + Word16 gamma2 /* i : short term postfilt. num. weighting factor*/ +) +{ + /* Local variables and arrays */ + Word16 apond1[M+1]; /* s.t. denominator coeff. */ + Word16 apond2[LONG_H_ST]; + Word16 res2[L_SUBFR]; + Word16 resynth[L_SUBFR+1]; + Word16 parcor0; + Word16 i, max; + Word16 scale_down; + + /* Compute weighted LPC coefficients */ + weight_a_fx(coeff, apond1, gamma1, M); + weight_a_fx(coeff, apond2, gamma2, M); + set16_fx(&apond2[M+1], 0, LONG_H_ST-(M+1)); + + max = abs_s(signal_ptr[0]); + FOR (i = 1; i < L_SUBFR; i++) + { + max = s_max(max, abs_s(signal_ptr[i])); + } + scale_down = 0; + move16(); + if (GT_16(max, 16384)) + { + scale_down = 1; + move16(); + } + + /* Compute A(gamma2) residual */ + IF (!scale_down) + { + Residu3_fx(apond2, signal_ptr, res2, L_SUBFR, 1); + } + ELSE + { + Residu3_fx(apond2, signal_ptr, res2, L_SUBFR, 0); + Scale_sig(pfstat->mem_stp, L_SYN_MEM, -1); + } + + /* Controls short term pst filter gain and compute parcor0 */ + calc_st_filt(apond2, apond1, &parcor0, res2, pfstat->mem_zero ); + + /* 1/A(gamma1) filtering, mem_stp is updated */ + resynth[0] = *(pfstat->mem_stp + sub(L_SYN_MEM, 1)); + move16(); + + E_UTIL_synthesis(1, apond1, res2, &(resynth[1]), L_SUBFR, pfstat->mem_stp+L_SYN_MEM-M, 0, M); + + IF (!scale_down) + { + Copy( &(resynth[1])+L_SUBFR-L_SYN_MEM, pfstat->mem_stp, L_SYN_MEM ); + } + ELSE + { + Copy_Scale_sig( &(resynth[1])+L_SUBFR-L_SYN_MEM, pfstat->mem_stp, L_SYN_MEM, 1 ); + } + + /* Tilt filtering */ + Filt_mu(resynth, sig_out, parcor0, L_SUBFR); + IF (scale_down) + { + Scale_sig(sig_out, L_SUBFR, 1); + } + + /* Gain control */ + scale_st(signal_ptr, sig_out, &pfstat->gain_prec, L_SUBFR); + + + return; +} + + +/*------------------------------------------------------------------------------------ + * modify_pst_param() + * + * Modify gamma1 and gamma2 values in function of the long term noise level + *-----------------------------------------------------------------------------------*/ + +static void modify_pst_param( + const Word16 lp_noise, /* i : Long term noise energy Q8 */ + Word16 *g1, /* o : Gamma1 used in post filter Q15 */ + Word16 *g2, /* o : Gamma1 used in post filter Q15 */ + const Word16 coder_type, /* i : Vad information decoded in UV frame */ + Word16 *gain_factor /* o : Gain factor applied in post filtering */ +) +{ + Word16 tmp; + Word16 lp_noiseQ12; + Word32 L_tmp; + + + test(); + IF( NE_16(coder_type,INACTIVE)&<_16(lp_noise,LP_NOISE_THR_FX)) + { + lp_noiseQ12 = shl(lp_noise, 4); /* to go from Q8 to Q12 */ + + /* ftmp = lp_noise*BG1_FX + CG1_FX */ + tmp = mac_r(CG1_FX*65536L, lp_noiseQ12, BG1_FX*8); /* x8 to go from Q12 to Q15 */ + tmp = s_min(tmp, POST_G1_FX ); + tmp = s_max(tmp, GAMMA1_PST12K_MIN_FX ); + + *g1 = tmp; + move16(); + + /* ftmp = lp_noise*BG2_FX + CG2_FX */ + L_tmp = L_mac0(CG2_FX/2*65536L, lp_noiseQ12, BG2_FX*8);/* L_mac0 and /2 to go from Q12 to Q14 */ + /* we go to Q30 to avoid overflow CG2_FX*/ + + L_tmp = L_min(L_tmp, POST_G2_FX*65536L/2); /* /2 because L_tmp is Q30 */ + L_tmp = L_max(L_tmp, GAMMA2_PST12K_MIN_FX*65536L/2); + + *g2 = extract_h(L_shl(L_tmp, 1)); /* Q30=>Q31=>Q15 */ + } + ELSE + { + *g1 = GAMMA1_PST12K_NOIS_FX; + move16(); + *g2 = GAMMA2_PST12K_NOIS_FX; + move16(); + } + + /* Set gain_factor of the harmonic filtering*/ + /* ftmp = (lp_noise - K_LP_NOISE)*C_LP_NOISE_FX */ + L_tmp = L_mac(-CK_LP_NOISE_FX, lp_noise, C_LP_NOISE_FX); /* tmp is in Q24 (from Q8) */ + + L_tmp = L_min(L_tmp, 64*65536L); /* 0.25 in Q24 */ + L_tmp = L_max(L_tmp, 0); + + *gain_factor = extract_h(L_shl(L_tmp, 7)); /* Q24=>Q31=>Q15 */ + + + return; +} + +/*---------------------------------------------------------------------------- + * pst_ltp + * + * Perform harmonic postfilter + *----------------------------------------------------------------------------*/ +static void pst_ltp( + Word16 t0, /* i : pitch delay given by coder */ + Word16 * ptr_sig_in, /* i : postfilter i filter (residu2) */ + Word16 * ptr_sig_pst0, /* o : harmonic postfilter o */ + Word16 gain_factor /* i : Gain Factor (Q15) */ +) +{ + Word32 L_temp; + + Word16 y_up[SIZ_Y_UP]; + Word16 sig_cadr[SIZ_RES2]; + + Word16 *ptr_y_up; + Word16 *ptr_sig; + Word16 *ptr_sig_cadr; + + Word16 i; + Word16 temp; + Word16 ltpdel, phase; + Word16 num_gltp, den_gltp; + Word16 num2_gltp, den2_gltp; + Word16 sh_num, sh_den; + Word16 sh_num2, sh_den2; + Word16 gain_plt; + Word16 off_yup; + Word16 nb_sh_sig; + + + + /* i signal justified on 13 bits */ + ptr_sig = ptr_sig_in - DECMEM_RES2; + nb_sh_sig = getScaleFactor16(ptr_sig, add(DECMEM_RES2, L_SUBFR)); + nb_sh_sig = sub(3, nb_sh_sig); + + FOR (i = 0; i < DECMEM_RES2+L_SUBFR; i++) + { + /* nb_sh_sig may be >0, <0 or =0 */ + sig_cadr[i] = shr(ptr_sig[i], nb_sh_sig); + move16(); + } + ptr_sig_cadr = sig_cadr + DECMEM_RES2; + + /* Sub optimal delay search */ + search_del(t0, ptr_sig_cadr, <pdel, &phase, &num_gltp, &den_gltp, &sh_num, &sh_den, y_up, &off_yup); + + + IF (num_gltp == 0) + { + Copy(ptr_sig_in, ptr_sig_pst0, L_SUBFR); + } + ELSE + { + IF (phase == 0) + { + ptr_y_up = ptr_sig_in - ltpdel; + } + ELSE + { + /* Filtering with long filter */ + compute_ltp_l(ptr_sig_cadr, ltpdel, phase, ptr_sig_pst0, &num2_gltp, &den2_gltp, &sh_num2, &sh_den2); + + + IF (EQ_16(select_ltp(num_gltp, den_gltp, sh_num, sh_den, num2_gltp, den2_gltp, sh_num2, sh_den2), 1)) + { + /* select short filter */ + temp = sub(phase, 1); + L_temp = L_mult0(temp, L_SUBFR + 1); + temp = extract_l(L_temp); + temp = add(temp, off_yup); + + /* ptr_y_up = y_up + (phase-1) * (L_SUBFR+1) + off_yup */ + ptr_y_up = y_up + temp; + } + ELSE + { + /* select long filter */ + num_gltp = num2_gltp; + move16(); + den_gltp = den2_gltp; + move16(); + sh_num = sh_num2; + move16(); + sh_den = sh_den2; + move16(); + ptr_y_up = ptr_sig_pst0; + } + + /* rescale y_up */ + FOR (i = 0; i < L_SUBFR; i++) + { + /* nb_sh_sig may be >0, <0 or =0 */ + ptr_y_up[i] = shl(ptr_y_up[i], nb_sh_sig); + move16(); + } + } + + temp = sub(sh_num, sh_den); + IF (temp >= 0) + { + den_gltp = shr(den_gltp, temp); + } + ELSE + { + num_gltp = shl(num_gltp, temp); /* >> (-temp) */ + } + IF (GE_16(num_gltp, den_gltp)) + { + /* beta bounded to 1 */ + gain_plt = MIN_GPLT_FX; + move16(); + } + ELSE + { + /* GAMMA_G = 0.5 */ + /* gain_plt = den_gltp x 2**15 / (den_gltp + 0.5 num_gltp) */ + /* shift 1 bit to avoid overflows in add */ + num_gltp = shr(num_gltp, 2); + den_gltp = shr(den_gltp, 1); + temp = add(den_gltp, num_gltp); + gain_plt = div_s(den_gltp, temp); /* Q15 */ + } + + /* decrease gain in noisy condition */ + /* gain_plt += (1.0f-gain_plt) * gain_factor */ + /* gain_plt = gain_plt + gain_factor - gain_plt*gain_factor */ + gain_plt = msu_r(L_msu(L_deposit_h(gain_plt), gain_plt, gain_factor), -32768, gain_factor); + + /** filtering by H0(z) = harmonic filter **/ + filt_plt(ptr_sig_in, ptr_y_up, ptr_sig_pst0, gain_plt); + } + +} + +/*---------------------------------------------------------------------------- + * search_del: + * + * Computes best (shortest) integer LTP delay + fine search + *---------------------------------------------------------------------------*/ +static void search_del( + Word16 t0, /* i : pitch delay given by coder */ + Word16 * ptr_sig_in, /* i : i signal (with delay line) */ + Word16 * ltpdel, /* o : delay = *ltpdel - *phase / f_up */ + Word16 * phase, /* o : phase */ + Word16 * num_gltp, /* o : 16 bits numerator of LTP gain */ + Word16 * den_gltp, /* o : 16 bits denominator of LTP gain */ + Word16 * sh_num_gltp, /* o : justification for num_gltp */ + Word16 * sh_den_gltp, /* o : justification for den_gltp */ + Word16 * y_up, /* o : LT delayed signal if fract. delay */ + Word16 * off_yup /* o : offset in y_up */ +) +{ + Word32 L_den0[F_UP_PST - 1]; + Word32 L_den1[F_UP_PST - 1]; + + Word32 *ptr_L_den0, *ptr_L_den1; + + Word32 L_num_int, L_den_int, L_den_max; + Word32 L_temp0, L_temp1; + Word32 L_acc; + Word32 L_temp; + + const Word16 *ptr_h; + Word16 *ptr_sig_past, *ptr_sig_past0; + Word16 *ptr1, *ptr_y_up; + + Word16 i, n; + Word16 num, den0, den1; + Word16 den_max, num_max; + Word32 L_numsq_max; + Word16 ener; + Word16 sh_num, sh_den, sh_ener; + Word16 i_max, lambda, phi, phi_max, ioff; + Word16 temp; + + + /*------------------------------------- + * Computes energy of current signal + *-------------------------------------*/ + + L_acc = L_mult(ptr_sig_in[0], ptr_sig_in[0]); + FOR(i = 1; i < L_SUBFR; i++) + { + L_acc = L_mac(L_acc, ptr_sig_in[i], ptr_sig_in[i]); + } + IF (L_acc == 0) + { + *num_gltp = 0; + move16(); + *den_gltp = 1; + move16(); + *ltpdel = 0; + move16(); + *phase = 0; + move16(); + + return; + } + sh_ener = sub(16, norm_l(L_acc)); + /* save energy for final decision */ + sh_ener = s_max(0, sh_ener); + ener = extract_l(L_shr(L_acc, sh_ener)); + + /*------------------------------------- + * Selects best of 3 integer delays + * Maximum of 3 numerators around t0 + *-------------------------------------*/ + lambda = sub(t0, 1); + ptr_sig_past = ptr_sig_in - lambda; + L_num_int = L_deposit_l(-1); + + /* initialization used only to suppress Microsoft Visual C++ warnings */ + i_max = (Word16) 0; + move16(); + + FOR (i = 0; i < 3; i++) + { + L_acc = L_mult(ptr_sig_in[0], ptr_sig_past[0]); + FOR (n = 1; n < L_SUBFR; n++) + { + L_acc = L_mac(L_acc, ptr_sig_in[n], ptr_sig_past[n]); + } + + + L_acc = L_max(L_acc, 0); + L_temp = L_sub(L_acc, L_num_int); + if (L_temp > 0L) + { + i_max = (Word16) i; + move16(); + } + L_num_int = L_max(L_num_int, L_acc); + ptr_sig_past--; + } + + IF (L_num_int == 0) + { + *num_gltp = 0; + move16(); + *den_gltp = 1; + move16(); + *ltpdel = 0; + move16(); + *phase = 0; + move16(); + + return; + } + + /* Compute den for i_max */ + lambda = add(lambda, (Word16) i_max); + ptr_sig_past = ptr_sig_in - lambda; + temp = *ptr_sig_past++; + move16(); + L_acc = L_mult(temp, temp); + FOR (i = 1; i < L_SUBFR; i++) + { + temp = *ptr_sig_past++; + move16(); + L_acc = L_mac(L_acc, temp, temp); + } + IF (L_acc == 0L) + { + *num_gltp = 0; + move16(); + *den_gltp = 1; + move16(); + *ltpdel = 0; + move16(); + *phase = 0; + move16(); + + return; + } + L_den_int = L_acc; /* sets to 'L_acc' in 1 clock */ + move32(); + + /*---------------------------------- + * Select best phase around lambda + *---------------------------------- + * Compute y_up & denominators + *----------------------------------*/ + + ptr_y_up = y_up; + L_den_max = L_den_int; /* sets to 'L_acc' in 1 clock */ + move32(); + ptr_L_den0 = L_den0; + ptr_L_den1 = L_den1; + ptr_h = Tab_hup_s; + temp = sub(lambda, LH_UP_S - 1); + ptr_sig_past0 = ptr_sig_in - temp; + + /* Loop on phase */ + FOR (phi = 1; phi < F_UP_PST; phi++) + { + /* Compute y_up for lambda+1 - phi/F_UP_PST */ + /* and lambda - phi/F_UP_PST */ + + ptr_sig_past = ptr_sig_past0; + FOR (n = 0; n <= L_SUBFR; n++) + { + ptr1 = ptr_sig_past++; + + L_acc = L_mult(ptr_h[0], ptr1[0]); + FOR (i = 1; i < LH2_S; i++) + { + L_acc = L_mac(L_acc, ptr_h[i], ptr1[-i]); + } + ptr_y_up[n] = round_fx(L_acc); + } + + /* compute den0 (lambda+1) and den1 (lambda) */ + + /* part common to den0 and den1 */ + L_acc = L_mult(ptr_y_up[1], ptr_y_up[1]); + FOR (n = 2; n < L_SUBFR; n++) + { + L_acc = L_mac(L_acc, ptr_y_up[n], ptr_y_up[n]); + } + L_temp0 = L_acc; /* sets to 'L_acc' in 1 clock (saved for den1) */ + move32(); + + /* den0 */ + L_acc = L_mac(L_acc, ptr_y_up[0], ptr_y_up[0]); + *ptr_L_den0 = L_acc; + move32(); + + /* den1 */ + L_acc = L_mac(L_temp0, ptr_y_up[L_SUBFR], ptr_y_up[L_SUBFR]); + *ptr_L_den1 = L_acc; + move32(); + + IF (GT_16(abs_s(ptr_y_up[0]), abs_s(ptr_y_up[L_SUBFR]))) + { + L_den_max = L_max(*ptr_L_den0, L_den_max); + } + ELSE + { + L_den_max = L_max(*ptr_L_den1, L_den_max); + } + ptr_L_den0++; + ptr_L_den1++; + ptr_y_up += (L_SUBFR+1); + ptr_h += LH2_S; + } + + IF (L_den_max == 0) + { + *num_gltp = 0; + move16(); + *den_gltp = 1; + move16(); + *ltpdel = 0; + move16(); + *phase = 0; + move16(); + + return; + } + + sh_den = sub(16, norm_l(L_den_max)); + /* if sh_den <= 0 : dynamic between current frame */ + /* and delay line too high */ + IF (sh_den <= 0) + { + *num_gltp = 0; + move16(); + *den_gltp = 1; + move16(); + *ltpdel = 0; + move16(); + *phase = 0; + move16(); + + return; + } + + /* search sh_num to justify correlations */ + /* sh_num = Max(sh_den, sh_ener) */ + sh_num = sh_ener; + move16(); + if (GE_16(sh_den, sh_ener)) + { + sh_num = sh_den; + move16(); + } + + /* Computation of the numerators */ + /* and selection of best num*num/den */ + /* for non null phases */ + + /* Initialize with null phase */ + L_acc = L_shr(L_den_int, sh_den); /* sh_den > 0 */ + den_max = extract_l(L_acc); + L_acc = L_shr(L_num_int, sh_num); /* sh_num > 0 */ + num_max = extract_l(L_acc); + L_numsq_max = L_mult(num_max, num_max); + + phi_max = 0; + move16(); + ioff = 1; + move16(); + + ptr_L_den0 = L_den0; + ptr_L_den1 = L_den1; + ptr_y_up = y_up; + + + /* if den_max = 0 : will be selected and declared unvoiced */ + /* if num!=0 & den=0 : will be selected and declared unvoiced */ + /* degenerated seldom cases, switch off LT is OK */ + + /* Loop on phase */ + FOR (phi = 1; phi < F_UP_PST; phi++) + { + /* compute num for lambda+1 - phi/F_UP_PST */ + L_acc = L_mult(ptr_sig_in[0], ptr_y_up[0]); + FOR (n = 1; n < L_SUBFR; n++) + { + L_acc = L_mac(L_acc, ptr_sig_in[n], ptr_y_up[n]); + } + L_acc = L_shr(L_acc, sh_num); /* sh_num > 0 */ + L_acc = L_max(0, L_acc); + num = extract_l(L_acc); + + /* selection if num**2/den0 max */ + L_temp1 = L_mult(num, num); + L_temp0 = Mpy_32_16_1(L_temp1, den_max); + L_acc = L_add(*ptr_L_den0++, 0); + L_acc = L_shr(L_acc, sh_den); /* sh_den > 0 */ + den0 = extract_l(L_acc); + L_temp = Msub_32_16(L_temp0, L_numsq_max, den0); + IF (L_temp > 0L) + { + num_max = num; + move16(); + L_numsq_max = L_temp1; /* sets to 'L_temp1' in 1 clock */ + move32(); + den_max = den0; + move16(); + ioff = 0; + move16(); + phi_max = phi; + move16(); + } + + /* compute num for lambda - phi/F_UP_PST */ + ptr_y_up++; + + L_acc = L_mult(ptr_sig_in[0], ptr_y_up[0]); + FOR (n = 1; n < L_SUBFR; n++) + { + L_acc = L_mac(L_acc, ptr_sig_in[n], ptr_y_up[n]); + } + L_acc = L_shr(L_acc, sh_num); /* sh_num > 0 */ + L_acc = L_max(0, L_acc); + num = extract_l(L_acc); + + /* selection if num**2/den1 max */ + L_temp1 = L_mult(num, num); + L_temp0 = Mpy_32_16_1(L_temp1, den_max); + L_acc = L_add(*ptr_L_den1++, 0); + L_acc = L_shr(L_acc, sh_den); /* sh_den > 0 */ + den1 = extract_l(L_acc); + L_temp = Msub_32_16(L_temp0, L_numsq_max, den1); + IF (L_temp > 0L) + { + num_max = num; + move16(); + L_numsq_max = L_temp1; /* sets to 'L_temp1' in 1 clock */ + move32(); + den_max = den1; + move16(); + ioff = 1; + move16(); + phi_max = phi; + move16(); + } + + ptr_y_up += L_SUBFR; + } + + /*--------------------------------------------------- + * test if normalized crit0[iopt] > THRESHCRIT + *--------------------------------------------------*/ + test(); + IF (num_max == 0 || LE_16(den_max, 1)) + { + *num_gltp = 0; + move16(); + *den_gltp = 1; + move16(); + *ltpdel = 0; + move16(); + *phase = 0; + move16(); + + return; + } + + /* compare num**2 */ + /* to ener * den * 0.5 */ + /* (THRESHCRIT = 0.5) */ + L_temp1 = L_mult(den_max, ener); + + /* temp = 2 * sh_num - sh_den - sh_ener + 1 */ + /* 16 bits with no overflows */ + temp = shl(sh_num, 1); + temp = sub(temp, sh_den); + temp = sub(temp, sh_ener); + temp = add(temp, 1); + IF (temp < 0) + { + temp = negate(temp); /* no overflow */ + L_numsq_max = L_shr(L_numsq_max, temp); + } + ELSE + { + if (temp > 0) + { + L_temp1 = L_shr(L_temp1, temp); + } + } + L_temp = L_sub(L_numsq_max, L_temp1); + IF (L_temp >= 0L) + { + temp = add(lambda, 1); + *ltpdel = sub(temp, ioff); + *off_yup = ioff; + move16(); + *phase = phi_max; + move16(); + *num_gltp = num_max; + move16(); + *den_gltp = den_max; + move16(); + *sh_den_gltp = sh_den; + move16(); + *sh_num_gltp = sh_num; + move16(); + } + ELSE + { + *num_gltp = 0; + move16(); + *den_gltp = 1; + move16(); + *ltpdel = 0; + move16(); + *phase = 0; + move16(); + } + + + return; +} + +/*---------------------------------------------------------------------------- + * filt_plt: + * + * Perform long term postfilter + *----------------------------------------------------------------------------*/ +static void filt_plt( + Word16 * s_in, /* i : i signal with past */ + Word16 * s_ltp, /* i : filtered signal with gain 1 */ + Word16 * s_out, /* o : signal */ + Word16 gain_plt /* i : filter gain */ +) +{ + + /* Local variables */ + Word32 L_acc; + + Word16 n; + Word16 gain_plt_1; + + + gain_plt_1 = sub(32767, gain_plt); + gain_plt_1 = add(gain_plt_1, 1); /* 2**15 (1 - g) */ + + FOR (n = 0; n < L_SUBFR; n++) + { + /* s_out(n) = gain_plt x s_in(n) + gain_plt_1 x s_ltp(n) */ + L_acc = L_mult(gain_plt, s_in[n]); + s_out[n] = mac_r(L_acc, gain_plt_1, s_ltp[n]); + move16(); /* no overflow */ + } + + + return; +} + + +/*---------------------------------------------------------------------------- + * compute_ltp_l : + * + * compute delayed signal, num & den of gain for fractional delay + * with long interpolation filter + *----------------------------------------------------------------------------*/ +static void compute_ltp_l( + Word16 * s_in, /* i/o: signal with past */ + Word16 ltpdel, /* i : delay factor */ + Word16 phase, /* i : phase factor */ + Word16 * y_up, /* i : delayed signal */ + Word16 * num, /* i : numerator of LTP gain */ + Word16 * den, /* i : denominator of LTP gain */ + Word16 * sh_num, /* i : justification factor of num */ + Word16 * sh_den /* i : justification factor of den */ +) +{ + Word32 L_acc; + Word16 *ptr2; + const Word16 *ptr_h; + Word16 n, i; + Word16 temp; + + temp = sub(phase, 1); + temp = shl(temp, L2_LH2_L); + ptr_h = Tab_hup_l + temp; /* Tab_hup_l + LH2_L * (phase-1) */ + + temp = sub(LH_UP_L, ltpdel); + ptr2 = s_in + temp; + + /* Compute y_up */ + FOR (n = 0; n < L_SUBFR; n++) + { + L_acc = L_mult(ptr_h[0], *ptr2--); + + FOR (i = 1; i < LH2_L; i++) + { + L_acc = L_mac(L_acc, ptr_h[i], *ptr2--); + } + y_up[n] = round_fx(L_acc); + ptr2 += LH2_L_P1; + } + + /* Compute num */ + L_acc = L_mult(y_up[0], s_in[0]); + FOR (n = 1; n < L_SUBFR; n++) + { + L_acc = L_mac(L_acc, y_up[n], s_in[n]); + } + IF (L_acc < 0L) + { + *num = 0; + move16(); + *sh_num = 0; + move16(); + } + ELSE + { + temp = sub(16, norm_l(L_acc)); + temp = s_max(temp, 0); + L_acc = L_shr(L_acc, temp); /* with temp >= 0 */ + *num = extract_l(L_acc); + *sh_num = temp; + move16(); + } + + /* Compute den */ + L_acc = L_mult(y_up[0], y_up[0]); + FOR (n = 1; n < L_SUBFR; n++) + { + L_acc = L_mac(L_acc, y_up[n], y_up[n]); + } + temp = sub(16, norm_l(L_acc)); + temp = s_max(temp, 0); + L_acc = L_shr(L_acc, temp); /* with temp >= 0 */ + *den = extract_l(L_acc); + *sh_den = temp; + move16(); + + + return; +} + +/*---------------------------------------------------------------------------- + * select_ltp: + * + * selects best of (gain1, gain2) + * with gain1 = num1 * 2** sh_num1 / den1 * 2** sh_den1 + * and gain2 = num2 * 2** sh_num2 / den2 * 2** sh_den2 + *----------------------------------------------------------------------------*/ +static Word16 select_ltp( /* o : 1 = 1st gain, 2 = 2nd gain */ + Word16 num1, /* i : numerator of gain1 */ + Word16 den1, /* i : denominator of gain1 */ + Word16 sh_num1, /* i : just. factor for num1 */ + Word16 sh_den1, /* i : just. factor for den1 */ + Word16 num2, /* i : numerator of gain2 */ + Word16 den2, /* i : denominator of gain2 */ + Word16 sh_num2, /* i : just. factor for num2 */ + Word16 sh_den2 /* i : just. factor for den2 */ +) +{ + Word32 L_temp1, L_temp2; + Word32 L_temp; + + Word16 temp1, temp2; + + + IF (den2 == 0) + { + return 1; + } + + /* compares criteria = num**2/den */ + L_temp1 = L_mult(num1, num1); + L_temp1 = Mpy_32_16_1(L_temp1, den2); + + L_temp2 = L_mult(num2, num2); + L_temp2 = Mpy_32_16_1(L_temp2, den1); + + /* temp1 = sh_den2 + 2 * sh_num1 */ + temp1 = shl(sh_num1, 1); + temp1 = add(temp1, sh_den2); + /* temp2 = sh_den1 + 2 * sh_num2; */ + temp2 = shl(sh_num2, 1); + temp2 = add(temp2, sh_den1); + + temp2 = sub(temp2, temp1); + if (temp2 > 0) + { + L_temp1 = L_shr(L_temp1, temp2); /* temp2 > 0 */ + } + if (temp2 < 0) + { + L_temp2 = L_shl(L_temp2, temp2); /* temp2 < 0 */ + } + + L_temp = L_sub(L_temp2, L_temp1); + temp1 = 1; + move16(); + if (L_temp > 0L) + { + temp1 = 2; + move16(); + } + + return temp1; +} + +/*---------------------------------------------------------------------------- + * calc_st_filt + * + * computes impulse response of A(gamma2) / A(gamma1) + * controls gain : computation of energy impulse response as + * SUMn (abs (h[n])) and computes parcor0 + *---------------------------------------------------------------------------- */ +static void calc_st_filt( + Word16 * apond2, /* i : coefficients of numerator */ + Word16 * apond1, /* i : coefficients of denominator */ + Word16 * parcor0, /* o : 1st parcor calcul. on composed filter */ + Word16 * sig_ltp_ptr, /* i/o: i of 1/A(gamma1) : scaled by 1/g0 */ + Word16 * mem_zero /* i : All zero memory */ +) +{ + Word32 L_g0; + + Word16 h[LONG_H_ST]; + + Word16 g0, temp; + Word16 i; + + + temp = sub( 2, norm_s( apond2[0] ) ); + + /* compute i.r. of composed filter apond2 / apond1 */ + E_UTIL_synthesis(temp, apond1, apond2, h, LONG_H_ST, mem_zero, 0, M); + + /* compute 1st parcor */ + Calc_rc0_h(h, parcor0); + + /* compute g0 */ + L_g0 = L_mult0(1, abs_s(h[0])); + FOR (i = 1; i < LONG_H_ST; i++) + { + L_g0 = L_mac0(L_g0, 1, abs_s(h[i])); + } + g0 = extract_h(L_shl(L_g0, 14)); + + /* Scale signal i of 1/A(gamma1) */ + IF (GT_16(g0, 1024)) + { + temp = div_s(1024, g0); /* temp = 2**15 / gain0 */ + FOR (i = 0; i < L_SUBFR; i++) + { + sig_ltp_ptr[i] = mult_r(sig_ltp_ptr[i], temp); + move16(); + } + } + + + return; +} + +/*---------------------------------------------------------------------------- + * filt_mu + * + * tilt filtering with : (1 + mu z-1) * (1/1-|mu|) + * computes y[n] = (1/1-|mu|) (x[n]+mu*x[n-1]) + *---------------------------------------------------------------------------*/ +void Filt_mu( + Word16 * sig_in, /* i : signal (beginning at sample -1) */ + Word16 * sig_out, /* o : signal with tilt */ + Word16 parcor0, /* i : parcor0 (mu = parcor0 * gamma3) */ + Word16 L_subfr /* i : the length of subframe */ +) +{ + Word32 L_acc, L_temp, L_fact; + + Word16 *ptrs; + + Word16 n; + Word16 mu, mu2, ga, temp; + Word16 fact, sh_fact; + + + IF (parcor0 > 0) + { + mu = mult_r(parcor0, GAMMA3_PLUS_FX); + /* GAMMA3_PLUS_FX < 0.5 */ + sh_fact = 14; + move16(); /* sh_fact */ + fact = (Word16) 0x4000; + move16(); /* 2**sh_fact */ + L_fact = (Word32) L_deposit_l(0x2000); /* fact >> 1 */ + } + ELSE + { + mu = mult_r(parcor0, GAMMA3_MINUS_FX); + /* GAMMA3_MINUS_FX < 0.9375 */ + sh_fact = 11; + move16(); /* sh_fact */ + fact = (Word16) 0x0800; + move16(); /* 2**sh_fact */ + L_fact = (Word32) L_deposit_l(0x0400); /* fact >> 1 */ + } + + temp = sub(1, abs_s(mu)); + BASOP_SATURATE_WARNING_OFF; + mu2 = add(32767, temp); /* 2**15 (1 - |mu|) */ + BASOP_SATURATE_WARNING_ON; + ga = div_s(fact, mu2); /* 2**sh_fact / (1 - |mu|) */ + + ptrs = sig_in; /* points on sig_in(-1) */ + + sh_fact = sub(sh_fact,16); /* to remove the saturate(), should shl by 16 before rounding */ + + FOR (n = 0; n < L_subfr; n++) + { + L_acc = L_mult0(mu, *ptrs++); + L_temp = L_mac(L_acc, 16384, *ptrs); /* sig_in(n) * 2**15 */ + + L_temp = Madd_32_16(L_fact, L_temp, ga); + L_temp = L_shr(L_temp, sh_fact); /* mult. temp x ga */ + + BASOP_SATURATE_WARNING_OFF; + /*sig_out[n] = saturate(L_temp); move16();*/ + sig_out[n] = round_fx(L_temp); + BASOP_SATURATE_WARNING_ON; + } + + + return; +} + + +/*---------------------------------------------------------------------------- + * scale_st() + * + * control of the subframe gain + * gain[n] = AGC_FAC_FX * gain[n-1] + (1 - AGC_FAC_FX) g_in/g_out + *---------------------------------------------------------------------------*/ +void scale_st( + const Word16 * sig_in, /* i : postfilter i signal */ + Word16 * sig_out, /* i/o: postfilter o signal */ + Word16 * gain_prec, /* i/o: last value of gain for subframe */ + Word16 L_subfr +) +{ + Word32 L_acc, L_temp; + + Word16 i; + Word16 scal_in, scal_out; + Word16 s_g_in, s_g_out, temp, sh_g0, g0; + Word16 gain = 0; + + + /* compute i gain */ + L_acc = L_deposit_l(0); + FOR (i = 0; i < L_subfr; i++) + { + if(sig_in[i] > 0) + { + L_acc = L_mac0(L_acc, 1, sig_in[i]); + } + if(sig_in[i] < 0) + { + L_acc = L_msu0(L_acc, 1, sig_in[i]); + } + } + + g0 = 0; + move16(); + IF (L_acc != 0L) + { + scal_in = norm_l(L_acc); + L_acc = L_shl(L_acc, scal_in); + s_g_in = extract_h(L_acc); /* normalized */ + + /* Compute o gain */ + { + Word64 acc64 = 0; + FOR (i = 0; i < L_subfr; i++) + { + acc64 = W_mac0_16_16(acc64, 1, abs_s(sig_out[i])); + } + L_acc = W_sat_l(acc64); + } + IF (L_acc == 0L) + { + *gain_prec = 0; + move16(); + + return; + } + scal_out = norm_l(L_acc); + L_acc = L_shl(L_acc, scal_out); + s_g_out = extract_h(L_acc); /* normalized */ + + sh_g0 = add(scal_in, 1); + sh_g0 = sub(sh_g0, scal_out); /* scal_in - scal_out + 1 */ + IF (LT_16(s_g_in, s_g_out)) + { + g0 = div_s(s_g_in, s_g_out); /* s_g_in/s_g_out in Q15 */ + } + ELSE + { + temp = sub(s_g_in, s_g_out); /* sufficient since normalized */ + g0 = shr(div_s(temp, s_g_out), 1); + g0 = add(g0, (Word16) 0x4000); /* s_g_in/s_g_out in Q14 */ + sh_g0 = sub(sh_g0, 1); + } + /* L_gain_in/L_gain_out in Q14 */ + /* overflows if L_gain_in > 2 * L_gain_out */ + g0 = shr(g0, sh_g0); /* sh_g0 may be >0, <0, or =0 */ + + g0 = mult_r(g0, AGC_FAC1_FX); /* L_gain_in/L_gain_out * AGC_FAC1_FX */ + } + + /* gain(n) = AGC_FAC gain(n-1) + AGC_FAC1 gain_in/gain_out */ + /* sig_out(n) = gain(n) sig_out(n) */ + gain = *gain_prec; + move16(); + FOR (i = 0; i < L_subfr; i++) + { + temp = mult_r(AGC_FAC_FX, gain); + gain = add(temp, g0); /* in Q14 */ + L_temp = L_mult(gain, sig_out[i]); + L_temp = L_shl(L_temp, 1); + sig_out[i] = round_fx(L_temp); + } + *gain_prec = gain; + move16(); + + + return; +} + +/*---------------------------------------------------------------------------- + * blend_subfr2() + * + * + *---------------------------------------------------------------------------*/ + +void blend_subfr2( + Word16 *sigIn1, + Word16 *sigIn2, + Word16 *sigOut +) +{ + Word16 fac1 = 32768 - 512; + Word16 fac2 = 0 + 512; + Word16 step = 1024; + Word16 i; + + FOR( i=0; i +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*===================================================================*/ +/* FUNCTION : void decod_ppp_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : decode highly voiced frames using PPP */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ const Word16 Aq_fx[] - Q12 12k8 Lp coefficient */ +/* _ Word16 bfi_fx - Q0 bad frame indicator */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ Decoder_State_fx *st_fx: */ +/* _ lastLgainD_fx - Q11 */ +/* _ lastHgainD_fx - Q11 */ +/* _ lasterbD_fx - Q13 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ Decoder_State_fx *st_fx: */ +/* _ lsp_old_fx - Q15 */ +/* _ st_fx->dtfs_dec_xxxx */ +/* _ a nd b in st_fx->dtfs_dec_Q */ +/* rest all in Q0 */ +/* _ gainp_ppp Q14 */ +/* _ FadeScale_fx - Q15 */ +/* _ tilt_code_fx - Q15 */ +/* _ prev_tilt_code_dec_fx - Q15 */ +/* _ prev_gain_pit_dec_fx - Q14 */ +/* _ dm_fx.prev_state - Q0 */ +/* _ dm_fx.prev_gain_code - Q16 */ +/* _ .dm_fx.prev_gain_pit - Q14 */ +/* _ prev_gain_pit_dec - Q14 */ +/* _ Word16 *pitch_buf_fx - Q6 fixed pitch values for each subframe */ +/* _ Word16 *exc_fx - Q_exc current non-enhanced excitation */ +/* _ Word16 *exc2_fx - Q_exc current enhanced excitation */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : RX */ +/*===================================================================*/ + +void decod_ppp_fx( + Decoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */ + Word16 *pitch_buf_fx, /* i/o: fixed pitch values for each subframe */ + Word16 *exc_fx, /* i/o: current non-enhanced excitation */ + Word16 *exc2_fx, /* i/o: current enhanced excitation */ + Word16 bfi /* i : bad frame indicator */ + , Word16 *gain_buf + ,Word16 *voice_factors, /* o : voicing factors */ + Word16 *bwe_exc_fx /* o : excitation for SWB TBE */ +) +{ + Word16 k; + + Word16 LPC_de_curr_fx[M+1], p_Aq_curr_fx[M], p_Aq_old_fx[M+1]; + Word16 excQ_ppp_fx[L_FRAME], pitch_fx[NB_SUBFR], LPC_de_old_fx[M+1]; + + /* call voiced decoder at this point */ + FOR( k=0; ktilt_code_fx = st_fx->tilt_code_dec_fx[3]; + move16(); + + Copy(excQ_ppp_fx, exc_fx, L_FRAME); + Copy(exc_fx, exc2_fx, L_FRAME); + + st_fx->dm_fx.prev_state = 2; + move16(); + + st_fx->dm_fx.prev_gain_pit[0] = st_fx->prev_gain_pit_dec_fx; + move16();/*Q14 */ + + FOR(k=3; k<7; k++) + { + st_fx->dm_fx.prev_gain_pit[k-2] = st_fx->dm_fx.prev_gain_pit[k-3]; + move16();/*Q14 */ + } + + Copy(pitch_fx, pitch_buf_fx, NB_SUBFR);/*Q6 */ + + interp_code_5over2_fx( exc2_fx, bwe_exc_fx, L_FRAME ); + set16_fx( voice_factors, 0, NB_SUBFR16k ); + + + + set16_fx(gain_buf,0,NB_SUBFR16k); + return; +} diff --git a/lib_dec/dec_prm.c b/lib_dec/dec_prm.c new file mode 100644 index 0000000..93af7f6 --- /dev/null +++ b/lib_dec/dec_prm.c @@ -0,0 +1,1199 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + + +#include +#include +#include +#include +#include "rom_com_fx.h" +#include "stl.h" +#include "prot_fx.h" +#include "basop_util.h" + +static void dec_prm_hm( + Decoder_State_fx *st, + Word16 *prm_hm, + Word16 L_frame +) +{ + Word16 tmp; + + /* Disable HM for non-GC,VC modes */ + test(); + IF (NE_16(st->tcx_cfg.coder_type, VOICED)&&NE_16(st->tcx_cfg.coder_type,GENERIC)) + { + prm_hm[0] = 0; + move16(); + + return; + } + + prm_hm[1] = -1; + move16(); + prm_hm[2] = 0; + move16(); + + /* Flag */ + prm_hm[0] = get_next_indice_fx(st, 1); + move16(); + + IF (prm_hm[0] != 0) + { + tmp = 0; + move16(); + if (GE_16(L_frame, 256)) + { + tmp = 1; + move16(); + } + /* Periodicity index */ + DecodeIndex(st, tmp, &prm_hm[1]); + + /* Gain index */ + IF (EQ_16(st->tcx_cfg.coder_type, VOICED)) + { + prm_hm[2] = get_next_indice_fx(st, kTcxHmNumGainBits); + move16(); + } + } +} + +/*-----------------------------------------------------------------* + * Funtion dec_prm() * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * + * + * SQ is used for TCX modes + * + * decode parameters according to selected mode * + *-----------------------------------------------------------------*/ +void dec_prm( + Word16 *coder_type, + Word16 param[], /* (o) : decoded parameters */ + Word16 param_lpc[], /* (o) : LPC parameters */ + Word16 *total_nbbits, /* i/o : number of bits / decoded bits */ + Decoder_State_fx *st, + Word16 L_frame, + Word16 *bitsRead +) +{ + Word16 j, k, n, sfr, *prm; + Word16 lg; + Word16 lgFB; + Word16 start_bit_pos; + Word16 acelp_target_bits=-1; + Word16 tmp; + Word16 nTnsParams; + Word16 nTnsBits; + Word16 nb_subfr; + Word16 nbits_tcx; + Word16 ix, j_old, wordcnt, bitcnt; + Word16 hm_size; + Word16 *prms; + CONTEXT_HM_CONFIG hm_cfg; + CONTEXT_HM_CONFIG * phm_cfg; + Word16 indexBuffer[N_MAX+1]; + Word8 flag_ctx_hm; + Word32 L_tmp; + Word16 num_bits; + UWord16 lsb; + Word16 ltp_mode, gains_mode; + Word16 ind; + Word16 prm_ltp[LTPSIZE]; + + /*--------------------------------------------------------------------------------* + * INIT + *--------------------------------------------------------------------------------*/ + + hm_cfg.indexBuffer = indexBuffer; + move16(); + + IF (EQ_16(st->mdct_sw, MODE1)) + { + start_bit_pos = 0; /* count from frame start */ move16(); + + /* Adjust st->bits_frame_core not to subtract MODE2 bandwidth signaling */ + FOR (n=0; ntotal_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + num_bits = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + assert(num_bits == st->total_brate_fx/50); + IF (EQ_16(FrameSizeConfig[n].frame_bits, num_bits)) + { + st->bits_frame_core = add(st->bits_frame_core, FrameSizeConfig[n].bandwidth_bits); + BREAK; + } + } + } + ELSE + { + IF( EQ_16(st->rf_flag,1)) + { + /*Inherent adjustment to accommodate the compact packing used in the RF mode*/ + start_bit_pos = sub(st->next_bit_pos_fx,2); + } + ELSE + { + start_bit_pos = st->next_bit_pos_fx; + } + } + + /* Framing parameters */ + nb_subfr = st->nb_subfr; + move16(); + + /* Initialize pointers */ + prm = param; + + /* Init counters */ + j = 0; + move16(); + + /* Init LTP data */ + st->tcx_hm_LtpPitchLag = -1; + move16(); + st->tcxltp_gain = 0; + move16(); + + /*--------------------------------------------------------------------------------* + * HEADER + *--------------------------------------------------------------------------------*/ + + /* Modes (ACE_GC, ACE_UC, TCX20, TCX10...) */ + IF ( st->tcxonly ) + { + st->core_fx = add(get_next_indice_fx(st, 1), 1); + move16(); + ind = get_next_indice_fx(st, 2); + st->clas_dec = ONSET; + move16(); + IF( ind == 0 ) + { + st->clas_dec = UNVOICED_CLAS; + move16(); + } + ELSE IF( EQ_16(ind, 1)) + { + st->clas_dec = UNVOICED_TRANSITION; + move16(); + if( GE_16(st->last_good_fx, VOICED_TRANSITION)) + { + st->clas_dec = VOICED_TRANSITION; + move16(); + } + } + ELSE if( EQ_16(ind, 2)) + { + st->clas_dec = VOICED_CLAS; + move16(); + } + *coder_type = INACTIVE; + st->VAD = 0; + move16(); + } + ELSE + { + IF (EQ_16(st->mdct_sw, MODE1)) + { + /* 2 bits instead of 3 as TCX is already signaled */ + st->core_fx = TCX_20_CORE; + move16(); + st->tcx_cfg.coder_type = get_next_indice_fx(st, 2); + move16(); + *coder_type = st->tcx_cfg.coder_type; + move16(); + } + ELSE + { + IF (EQ_16(st->mdct_sw_enable, MODE2)) + { + IF (get_next_indice_1_fx(st) != 0) /* TCX */ + { + tmp = get_next_indice_fx(st, 3); + assert(!(tmp & 4) || !"HQ_CORE encountered in dec_prm"); + st->core_fx = TCX_20_CORE; + move16(); + st->tcx_cfg.coder_type = tmp; + move16(); + *coder_type = st->tcx_cfg.coder_type; + move16(); + } + ELSE /* ACELP */ + { + st->core_fx = ACELP_CORE; + move16(); + *coder_type = get_next_indice_fx(st, 2); + move16(); + } + } + ELSE + { + IF(EQ_16(st->rf_flag,1)) + { + IF( !( st->use_partial_copy ) ) + { + tmp = get_next_indice_fx(st, 1); + IF(tmp == 0) + { + st->core_fx = ACELP_CORE; + move16(); + } + ELSE + { + st->core_fx = TCX_20_CORE; + move16(); + st->tcx_cfg.coder_type = *coder_type; + move16(); + } + } + } + ELSE + { + st->core_fx = ACELP_CORE; + move16(); + *coder_type = get_next_indice_fx(st, 3); + move16(); + IF ( GE_16(*coder_type, ACELP_MODE_MAX)) + { + st->core_fx = TCX_20_CORE; + move16(); + *coder_type=sub(*coder_type,ACELP_MODE_MAX); + st->tcx_cfg.coder_type = *coder_type; + move16(); + } + } + } + } + + test(); + IF ( st->igf != 0 && EQ_16(st->core_fx, ACELP_CORE) ) + { + st->bits_frame_core = sub( st->bits_frame_core, get_tbe_bits_fx(st->total_brate_fx, st->bwidth_fx, st->rf_flag) ); + } + + IF( EQ_16(st->rf_flag,1)) + { + st->bits_frame_core = sub(st->bits_frame_core, add(st->rf_target_bits, 1)); /* +1 as flag-bit not considered in rf_target_bits */ + } + + /* Inactive frame detection on non-DTX mode */ + st->VAD = 1; + move16(); + if( EQ_16(*coder_type, INACTIVE)) + { + st->VAD = 0; + move16(); + } + } + + /*Core extended mode mapping for correct PLC classification*/ + st->core_ext_mode = *coder_type; + move16(); + + if( EQ_16(*coder_type, INACTIVE)) + { + st->core_ext_mode = UNVOICED; + move16(); + } + + /* Decode previous mode for error concealment */ + tmp = 0; + move16(); + test(); + test(); + IF( ( NE_16(st->core_fx, ACELP_CORE) || st->tcx_cfg.lfacNext > 0 ) && st->use_partial_copy == 0 ) + { + st->last_core_bs_fx = get_next_indice_fx(st, 1); + move16(); + + /* + need to introduce special error handling for lost transition frames from CNG: + in such cases, the bitstream reader continues with CNG, setting bfi = 0, total_brate = 0 + this might result in a not matching last_core transmitted in the BS - we should use this + only for interpreting the bitstream and re-use the internal state for the proper + transition handling; still, for voiced onsets rather stick to wrong windowing... + */ + if( (!((st->last_total_brate_fx == 0) && (sub(st->clas_dec, VOICED_CLAS) != 0))) && (sub(st->last_core_bs_fx, st->last_core_fx) != 0) ) + { + st->last_core_fx = st->last_core_bs_fx; + } + /*for TCX 10 force last_core to be TCX since ACELP as previous core is forbidden*/ + IF( EQ_16(st->core_fx, TCX_10_CORE)) + { + st->last_core_fx = TCX_20_CORE; + st->last_core_bs_fx = TCX_20_CORE; + move16(); + move16(); + } + } + + test(); + test(); + IF(EQ_16(st->rf_flag,1)&&EQ_16(st->use_partial_copy,1)&&!st->tcxonly) + { + st->bits_frame_core = st->rf_target_bits; + + /* offset the indices to read the acelp partial copy */ + Mpy_32_16_ss(st->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + num_bits = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + + get_next_indice_tmp_fx(st, start_bit_pos + num_bits - st->rf_target_bits - 3 - st->next_bit_pos_fx); + } + + IF( st->use_partial_copy == 0 ) + { + /* Set the last overlap mode based on the previous and current frame type and coded overlap mode */ + test(); + IF ((EQ_16(st->last_core_fx, ACELP_CORE))||(EQ_16(st->last_core_fx,AMR_WB_CORE))) + { + st->tcx_cfg.tcx_last_overlap_mode = TRANSITION_OVERLAP; + move16(); + } + ELSE + { + test(); + IF ((EQ_16(st->core_fx, TCX_10_CORE))&&(EQ_16(st->tcx_cfg.tcx_curr_overlap_mode,ALDO_WINDOW))) + { + st->tcx_cfg.tcx_last_overlap_mode = FULL_OVERLAP; + move16(); + } + ELSE + { + st->tcx_cfg.tcx_last_overlap_mode = st->tcx_cfg.tcx_curr_overlap_mode; + move16(); + test(); + if ((NE_16(st->core_fx, TCX_10_CORE))&&(EQ_16(st->tcx_cfg.tcx_curr_overlap_mode,FULL_OVERLAP))) + { + st->tcx_cfg.tcx_last_overlap_mode = ALDO_WINDOW; + move16(); + } + } + } + /* Set the current overlap mode based on the current frame type and coded overlap mode */ + st->tcx_cfg.tcx_curr_overlap_mode = ALDO_WINDOW; + move16(); + + IF (NE_16(st->core_fx, ACELP_CORE)) + { + tmp = 0; + move16(); + /* if current TCX mode is not 0 (full overlap), read another bit */ + IF (get_next_indice_fx(st, 1)) + { + tmp = add(2, get_next_indice_fx(st, 1)); + } + st->tcx_cfg.tcx_curr_overlap_mode = tmp; + move16(); + + /* TCX10 : always symmetric windows */ + test(); + test(); + test(); + if ((EQ_16(st->core_fx, TCX_20_CORE))&&(tmp==0)&&(NE_16(st->last_core_fx,ACELP_CORE))&&(NE_16(st->last_core_fx,AMR_WB_CORE))) + { + st->tcx_cfg.tcx_curr_overlap_mode = ALDO_WINDOW; + move16(); + } + } + + /* SIDE INFO. DECODING */ + IF(st->enableGplc) + { + Word16 pitchDiff; + Word16 bits_per_subfr, search_range; + bits_per_subfr = 4; + move16(); + search_range = 8; + move16(); + + st->flagGuidedAcelp = get_next_indice_fx(st, 1); + move16(); + + pitchDiff = 0; + move16(); + IF(st->flagGuidedAcelp) + { + pitchDiff = get_next_indice_fx(st, bits_per_subfr); + move16(); + st->guidedT0 = sub(pitchDiff, search_range); + move16(); + } + test(); + if( (pitchDiff == 0) && st->flagGuidedAcelp) + { + st->flagGuidedAcelp = 0; + move16(); + } + } + ELSE + { + st->flagGuidedAcelp = 0; + move16(); + } + + IF( st->dec_glr ) + { + move16(); + st->dec_glr_idx = -1; + IF( EQ_16(st->core_fx, ACELP_CORE) ) + { + st->dec_glr_idx = get_next_indice_fx(st, G_LPC_RECOVERY_BITS); + } + } + } + /*--------------------------------------------------------------------------------* + * LPC PARAMETERS + *--------------------------------------------------------------------------------*/ + + /*Initialization of LPC Mid flag*/ + st->acelp_cfg.midLpc = st->acelp_cfg.midLpc_enable; + move16(); + test(); + test(); + IF( (EQ_16(st->lpcQuantization, 1)&&(EQ_16(*coder_type,VOICED)))||(st->use_partial_copy)) + { + st->acelp_cfg.midLpc = 0; + move16(); + } + + IF( st->use_partial_copy == 0 ) + { + /* Number of sets of LPC parameters (does not include mid-lpc) */ + st->numlpc = 2; + move16(); + test(); + if ( st->tcxonly==0 || LT_16(st->core_fx, TCX_10_CORE)) + { + st->numlpc = 1; + move16(); + } + + /* Decode LPC parameters */ + test(); + IF (st->enableTcxLpc && NE_16(st->core_fx, ACELP_CORE)) + { + Word16 tcx_lpc_cdk; + tcx_lpc_cdk = tcxlpc_get_cdk(*coder_type); + dec_lsf_tcxlpc(st, ¶m_lpc, st->narrowBand, tcx_lpc_cdk); + } + ELSE + { + IF (st->lpcQuantization==0) + { + decode_lpc_avq( st, st->numlpc, param_lpc ); + move16(); + } + ELSE IF (EQ_16(st->lpcQuantization, 1)) + { + test(); + test(); + IF(EQ_32(st->sr_core, 16000)&&EQ_16(*coder_type,VOICED)&&EQ_16(st->core_fx,ACELP_CORE)) + { + lsf_bctcvq_decprm(st, param_lpc); + } + ELSE + { + lsf_msvq_ma_decprm( st, param_lpc, st->core_fx, *coder_type, st->acelp_cfg.midLpc, st->narrowBand, st->sr_core ); + } + + } + ELSE + { + assert(0 && "LPC quant not supported!"); + } + } + } + ELSE + { + st->numlpc = 1; + move16(); + + test(); + IF( EQ_16(st->rf_frame_type, RF_TCXFD)) + { + param_lpc[0] = 0; + move16(); + param_lpc[1] = get_next_indice_fx(st, lsf_numbits[0]); /* VQ 1 */ + param_lpc[2] = get_next_indice_fx(st, lsf_numbits[1]); /* VQ 2 */ + param_lpc[3] = get_next_indice_fx(st, lsf_numbits[2]); /* VQ 3 */ + } + ELSE IF( GE_16(st->rf_frame_type, RF_ALLPRED)&&LE_16(st->rf_frame_type,RF_NELP)) + { + /* LSF indices */ + param_lpc[0] = get_next_indice_fx(st, 8); /* VQ 1 */ + param_lpc[1] = get_next_indice_fx(st, 8); /* VQ 2 */ + } + } + + st->bits_common = sub(st->next_bit_pos_fx, start_bit_pos); + move16(); + + + /*--------------------------------------------------------------------------------* + * ACELP + *--------------------------------------------------------------------------------*/ + test(); + test(); + IF( EQ_16(st->core_fx,ACELP_CORE)&&st->use_partial_copy==0) + { + /* Target Bits */ + acelp_target_bits = sub(st->bits_frame_core, st->bits_common); + + { + Word16 acelp_bits; + move16(); + acelp_bits = BITS_ALLOC_config_acelp( acelp_target_bits, *coder_type, &(st->acelp_cfg), st->narrowBand, st->nb_subfr ); + + if ( acelp_bits < 0 ) + { + st->BER_detect = 1; + move16(); + } + } + + /* Adaptive BPF (2 bits)*/ + n=ACELP_BPF_BITS[st->acelp_cfg.bpf_mode]; + move16(); + + st->bpf_gain_param = shl(st->acelp_cfg.bpf_mode, 1); + IF( n != 0) + { + st->bpf_gain_param = get_next_indice_fx(st, n); + move16(); + } + + /* Mean energy (2 or 3 bits) */ + n = ACELP_NRG_BITS[st->acelp_cfg.nrg_mode]; + move16(); + IF( n != 0 ) + { + prm[j++] = get_next_indice_fx(st, n); + move16(); + } + + /* Subframe parameters */ + FOR (sfr=0; sfracelp_cfg.ltp_mode][sfr]; + move16(); + + IF(n!=0) + { + prm[j++] = get_next_indice_fx(st, n); + move16(); + } + + /* Adaptive codebook filtering (1 bit) */ + IF ( EQ_16(st->acelp_cfg.ltf_mode, 2)) + { + prm[j++] = get_next_indice_fx(st, 1); + move16(); + } + + /* Innovative codebook */ + { + /* Decode pulse positions. */ + j_old = j; + move16(); + wordcnt = shr(ACELP_FIXED_CDK_BITS(st->acelp_cfg.fixed_cdk_index[sfr]), 4); + bitcnt = s_and(ACELP_FIXED_CDK_BITS(st->acelp_cfg.fixed_cdk_index[sfr]), 0xF); + + /* sanity check for testing - not instrumented */ + test(); + if ( GE_16(st->acelp_cfg.fixed_cdk_index[sfr], ACELP_FIXED_CDK_NB)||(st->acelp_cfg.fixed_cdk_index[sfr]<0)) + { + st->acelp_cfg.fixed_cdk_index[sfr] = 0; + move16(); + st->BER_detect = 1; + move16(); + } + + FOR (ix = 0; ix < wordcnt; ix++) + { + prm[j++] = get_next_indice_fx(st, 16); + move16(); + } + IF (bitcnt) + { + prm[j] = get_next_indice_fx(st, bitcnt); + move16(); + } + + j = add(j_old, 8); + + } + + /* Gains (5b, 6b or 7b / subfr) */ + n = ACELP_GAINS_BITS[st->acelp_cfg.gains_mode[sfr]]; + move16(); + + prm[j++] = get_next_indice_fx(st, n); + move16(); + }/*end of subfr loop*/ + } + + ELSE IF( GE_16(st->rf_frame_type,RF_ALLPRED)&&st->use_partial_copy) + { + Word16 acelp_bits = + BITS_ALLOC_config_acelp( st->rf_target_bits, /* target bits ranges from 56 to 72 depending on rf_type */ + st->rf_frame_type, /* already offset by 4 to parse the config elements for partial copy */ + &(st->acelp_cfg), /* acelp_cfg_rf*/ + 0, /* is narrowBand */ + st->nb_subfr ); + + if ( acelp_bits < 0 ) + { + st->BER_detect = 1; + move16(); + } + + /* rf_frame_type NELP: 7 */ + IF(EQ_16(st->rf_frame_type,RF_NELP)) + { + /* NELP gain indices */ + st->rf_indx_nelp_iG1 = get_next_indice_fx( st, 5 ); + st->rf_indx_nelp_iG2[0] = get_next_indice_fx( st, 6 ); + st->rf_indx_nelp_iG2[1] = get_next_indice_fx( st, 6 ); + + /* NELP filter selection index */ + st->rf_indx_nelp_fid = get_next_indice_fx( st, 2 ); + + /* tbe gainFr */ + st->rf_indx_tbeGainFr = get_next_indice_fx( st, 5 ); + } + ELSE + { + /* rf_frame_type ALL_PRED: 4, NO_PRED: 5, GEN_PRED: 6*/ + /* ES pred */ + prm[j++] = get_next_indice_fx(st, 3); + + ltp_mode = ACELP_LTP_MODE[1][1][st->rf_frame_type]; + gains_mode = ACELP_GAINS_MODE[1][1][st->rf_frame_type]; + + /* Subframe parameters */ + FOR( sfr = 0; sfr < nb_subfr; sfr++ ) + { + /* Pitch lag (5, or 8 bits) */ + n = ACELP_LTP_BITS_SFR[ltp_mode][sfr]; + IF (n != 0) + { + prm[j++] = get_next_indice_fx(st, n); + } + + /*Innovative codebook*/ + test(); + test(); + test(); + IF( EQ_16(st->rf_frame_type,RF_NOPRED) + || ( EQ_16(st->rf_frame_type,RF_GENPRED) && (sfr == 0 || EQ_16(sfr,2) )) ) + { + /* NOTE: FCB actual bits need to be backed up as well */ + /*n = ACELP_FIXED_CDK_BITS(st->rf_indx_fcb[fec_offset][sfr]) & 15;*/ + prm[j] = get_next_indice_fx(st, 7); + j = add(j,8); + } + + /* Gains (5b, 6b or 7b / subfr) */ + test(); + IF( sfr == 0 || EQ_16(sfr,2)) + { + n = ACELP_GAINS_BITS[gains_mode]; + prm[j++] = get_next_indice_fx(st, n); + } + } + + st->rf_indx_tbeGainFr = get_next_indice_fx( st, 2 ); + } + } + + /*--------------------------------------------------------------------------------* + * TCX20 + *--------------------------------------------------------------------------------*/ + test(); + IF( EQ_16(st->core_fx, TCX_20_CORE)&&st->use_partial_copy==0) + { + flag_ctx_hm = 0; + move16(); + + IF (st->enablePlcWaveadjust) + { + st->tonality_flag = get_next_indice_fx(st, 1); + move16(); + } + + /* TCX Gain = 7 bits */ + prm[j++] = get_next_indice_fx(st, 7); + move16(); + + /* TCX Noise Filling = NBITS_NOISE_FILL_LEVEL bits */ + prm[j++] = get_next_indice_fx(st, NBITS_NOISE_FILL_LEVEL); + move16(); + + /* LTP data */ + /* PLC pitch info for HB */ + test(); + IF (st->tcxltp != 0 || GT_32(st->sr_core, 25600)) + { + + prm[j] = get_next_indice_fx(st, 1); + move16(); + + IF ( prm[j] ) + { + prm[j+1] = get_next_indice_fx(st, 9); + move16(); + prm[j+2] = get_next_indice_fx(st, 2); + move16(); + } + + st->BER_detect = st->BER_detect | + tcx_ltp_decode_params(&prm[j], + &(st->tcxltp_pitch_int), + &(st->tcxltp_pitch_fr), + &(st->tcxltp_gain), + st->pit_min, + st->pit_fr1, + st->pit_fr2, + st->pit_max, + st->pit_res_max); + + st->tcx_hm_LtpPitchLag = -1; + move16(); + st->tcxltp_last_gain_unmodified = st->tcxltp_gain; + move16(); + + test(); + IF ((st->tcxonly == 0) && (LT_16(st->tcxltp_pitch_int, L_frame))) + { + Word32 tmp32 = L_shl(L_mult0(st->L_frame_fx, st->pit_res_max), 1+kLtpHmFractionalResolution+1); + Word16 tmp1 = add(imult1616(st->tcxltp_pitch_int, st->pit_res_max), st->tcxltp_pitch_fr); + st->tcx_hm_LtpPitchLag = div_l(tmp32, tmp1); + } + } + + j = add(j, 3); + + /* TCX spectral data */ + lg = L_frame; + move16(); + lgFB = st->tcx_cfg.tcx_coded_lines; + move16(); + + IF (st->last_core_bs_fx == ACELP_CORE ) + { + /* ACE->TCX transition */ + lg = add(lg, st->tcx_cfg.tcx_offset); + if(st->tcx_cfg.lfacNext < 0) + { + lg = sub(lg,st->tcx_cfg.lfacNext); + } + + lgFB = add(lgFB, shr(lgFB, 2)); + } + + /* TNS data */ + nTnsParams = 0; + move16(); + nTnsBits = 0; + move16(); + + IF (st->tcx_cfg.fIsTNSAllowed) + { + SetTnsConfig(&st->tcx_cfg, 1, st->last_core_bs_fx == ACELP_CORE); + ReadTnsData(st->tcx_cfg.pCurrentTnsConfig, st, &nTnsBits, prm+j, &nTnsParams); + + j = add(j, nTnsParams); + } + hm_size = shl(mult(st->TcxBandwidth, lg), 1); + + test(); + IF (st->tcx_lpc_shaped_ari != 0 && NE_16(st->last_core_bs_fx, ACELP_CORE)) + { + dec_prm_hm(st, &prm[j], hm_size); + } + + nbits_tcx = sub(st->bits_frame_core, sub(st->next_bit_pos_fx, start_bit_pos)); + if (st->enableGplc != 0) + { + nbits_tcx = sub(nbits_tcx, 7); + } + + /*Context HM flag*/ + test(); + IF ( st->tcx_cfg.ctx_hm && NE_16(st->last_core_bs_fx, ACELP_CORE)) + { + prm[j] = get_next_indice_fx(st, 1); + move16(); + nbits_tcx = sub(nbits_tcx, 1); + + IF (prm[j]) + { + Word16 NumIndexBits; + + tmp = 0; + move16(); + if(GE_16(hm_size, 256)) + { + tmp = 1; + move16(); + } + + NumIndexBits = DecodeIndex(st, + tmp, + prm+j+1); + + flag_ctx_hm = 1; + move16(); + + ConfigureContextHm( + lgFB, + nbits_tcx, + *(prm+j+1), + st->tcx_hm_LtpPitchLag, + &hm_cfg); + + nbits_tcx = sub(nbits_tcx, NumIndexBits); + } + } + j = add(j, NPRM_CTX_HM); + + /* read IGF payload */ + IF (st->igf) + { + + n = st->next_bit_pos_fx; + move16(); + IF (EQ_16(st->last_core_bs_fx, ACELP_CORE)) + { + IGFDecReadLevel( &st->hIGFDec, st, IGF_GRID_LB_TRAN, 1 ); + IGFDecReadData( &st->hIGFDec, st, IGF_GRID_LB_TRAN, 1 ); + + } + ELSE + { + IGFDecReadLevel( &st->hIGFDec, st, IGF_GRID_LB_NORM, 1 ); + IGFDecReadData( &st->hIGFDec, st, IGF_GRID_LB_NORM, 1 ); + } + + nbits_tcx = sub(nbits_tcx, sub(st->next_bit_pos_fx, n)); + + } + nbits_tcx = sub(st->bits_frame_core, sub(st->next_bit_pos_fx, start_bit_pos)); + IF (st->tcx_lpc_shaped_ari != 0) + { + prm[j++] = nbits_tcx; /* store length of buffer */ move16(); + prms = &prm[j]; + FOR (ix = 0; ix < nbits_tcx; ix++) + { + prms[ix] = get_next_indice_1_fx(st); + move16(); + } + set16_fx(prms+nbits_tcx, 1, 32); + j = add(j, nbits_tcx); + } + ELSE + { + phm_cfg = NULL; + move16(); + if (flag_ctx_hm) + { + phm_cfg = &hm_cfg; + move16(); + } + st->resQBits[0] = ACcontextMapping_decode2_no_mem_s17_LC(st, + prm+j, + lgFB, + nbits_tcx, + NPRM_RESQ*st->tcx_cfg.resq, + phm_cfg); + move16(); + j = add(j, lg); + } + } + + test(); + test(); + IF( GE_16(st->rf_frame_type,RF_TCXFD)&&LE_16(st->rf_frame_type,RF_TCXTD2)&&EQ_16(st->use_partial_copy,1)) + { + /* classification */ + ind = get_next_indice_fx(st, 2); + st->clas_dec = ONSET; + move16(); + + IF( ind == 0 ) + { + st->clas_dec = UNVOICED_CLAS; + move16(); + } + ELSE IF( EQ_16(ind, 1)) + { + IF( GE_16(st->last_good_fx, VOICED_TRANSITION)) + { + st->clas_dec = VOICED_TRANSITION; + move16(); + } + ELSE + { + st->clas_dec = UNVOICED_TRANSITION; + move16(); + } + } + ELSE IF( EQ_16(ind, 2)) + { + st->clas_dec = VOICED_CLAS; + move16(); + } + + IF( EQ_16(st->rf_frame_type, RF_TCXFD)) + { + /* TCX Gain = 7 bits */ + st->old_gaintcx_bfi = get_next_indice_fx(st, 7); + } + ELSE + { + /* LTP data */ + IF( st->tcxltp != 0 ) + { + IF( EQ_16(st->rf_frame_type, RF_TCXTD2)||EQ_16(st->rf_frame_type,RF_TCXTD1)) + { + prm_ltp[0] = 1; + move16(); /* LTP active*/ + prm_ltp[1] = get_next_indice_fx(st, 9); + prm_ltp[2] = 3; + move16(); /* max ampl. quantizer output (2bits), anyway not used later*/ + + IF( st->prev_bfi_fx == 0 ) + { + st->BER_detect = st->BER_detect | + tcx_ltp_decode_params(&prm_ltp[0], &(st->tcxltp_pitch_int), &(st->tcxltp_pitch_fr), &(st->tcxltp_gain), + st->pit_min, st->pit_fr1, st->pit_fr2, st->pit_max, st->pit_res_max ); + + st->tcxltp_last_gain_unmodified = st->tcxltp_gain; + move16(); + } + } + } + } + } + + + /*--------------------------------------------------------------------------------* + * TCX10 + *--------------------------------------------------------------------------------*/ + IF ( EQ_16(st->core_fx, TCX_10_CORE)) + { + Word16 tcxltp_prm_0 = 0; + Word16 tcxltp_prm_1 = 0; + Word16 tcxltp_prm_2 = 0; + Word16 nbits_igf = 0; + move16(); + move16(); + move16(); + move16(); + move16(); + /* read IGF payload */ + IF (st->igf) + { + + n = st->next_bit_pos_fx; + move16(); + + IGFDecReadLevel( &st->hIGFDec, st, IGF_GRID_LB_SHORT, 1); + IGFDecReadData( &st->hIGFDec, st, IGF_GRID_LB_SHORT, 1); + IGFDecStoreTCX10SubFrameData( &st->hIGFDec, 0 ); + + IGFDecReadLevel( &st->hIGFDec, st, IGF_GRID_LB_SHORT, 0); + IGFDecReadData( &st->hIGFDec, st, IGF_GRID_LB_SHORT, 0); + IGFDecStoreTCX10SubFrameData( &st->hIGFDec, 1 ); + + nbits_igf = sub(st->next_bit_pos_fx, n); + + } + FOR (k = 0; k < 2; k++) + { + flag_ctx_hm = 0; + move16(); + + prm = param + (k*DEC_NPRM_DIV); + j = 0; + move16(); + + nbits_tcx = sub(st->next_bit_pos_fx, start_bit_pos); + + test(); + IF (st->enablePlcWaveadjust && k) + { + st->tonality_flag = get_next_indice_fx(st, 1); + move16(); + } + /* TCX Gain = 7 bits */ + prm[j++] = get_next_indice_fx(st, 7); + move16(); + + /* TCX Noise Filling = NBITS_NOISE_FILL_LEVEL bits */ + prm[j++] = get_next_indice_fx(st, NBITS_NOISE_FILL_LEVEL); + move16(); + + /* LTP data */ + test(); + test(); + IF ( (k == 0) && ((st->tcxltp != 0) || (GT_32(st->sr_core, 25600)))) + { + prm[j] = get_next_indice_fx(st, 1); + move16(); + + IF ( prm[j] ) + { + + prm[j+1] = get_next_indice_fx(st, 9); + move16(); + prm[j+2] = get_next_indice_fx(st, 2); + move16(); + + tcxltp_prm_0 = prm[j]; + move16(); + tcxltp_prm_1 = prm[j+1]; + move16(); + tcxltp_prm_2 = prm[j+2]; + move16(); + } + + st->BER_detect = st->BER_detect | + tcx_ltp_decode_params(&prm[j], + &(st->tcxltp_pitch_int), + &(st->tcxltp_pitch_fr), + &(st->tcxltp_gain), + st->pit_min, + st->pit_fr1, + st->pit_fr2, + st->pit_max, + st->pit_res_max); + + st->tcxltp_last_gain_unmodified = st->tcxltp_gain; + move16(); + st->tcx_hm_LtpPitchLag = -1; + move16(); + + j = add(j, 3); + } + ELSE + { + prm[j++] = tcxltp_prm_0; + move16(); + prm[j++] = tcxltp_prm_1; + move16(); + prm[j++] = tcxltp_prm_2; + move16(); + } + + /* TCX spectral data */ + lg = shr(L_frame, 1); + lgFB = shr(st->tcx_cfg.tcx_coded_lines, 1); + + test(); + IF ( k == 0 && st->last_core_bs_fx == ACELP_CORE ) + { + /* ACE->TCX transition */ + lg = add(lg, st->tcx_cfg.tcx_offset); + if(st->tcx_cfg.lfacNext<0) + { + lg = sub(lg,st->tcx_cfg.lfacNext); + } + + lgFB = add(lgFB, shr(lgFB, 1)); + } + + /* TNS data */ + nTnsParams = 0; + move16(); + nTnsBits = 0; + move16(); + + IF (st->tcx_cfg.fIsTNSAllowed) + { + IF( EQ_16(st->last_core_bs_fx, ACELP_CORE)&&(k==0)) + { + st->BER_detect = 1; + st->last_core_fx = TCX_20_CORE; move16(); + st->last_core_bs_fx = TCX_20_CORE; move16(); + } + test(); + test(); + SetTnsConfig(&st->tcx_cfg, 0, (st->last_core_bs_fx == ACELP_CORE) && (k == 0)); + + ReadTnsData(st->tcx_cfg.pCurrentTnsConfig, st, &nTnsBits, prm+j, &nTnsParams); + + j = add(j, nTnsParams); + } + + hm_size = shl(mult(st->TcxBandwidth, lgFB), 1); + + /*compute target bits*/ + nbits_tcx = sub(shr(sub(add(sub(sub(st->bits_frame_core, st->bits_common), nbits_igf), 1), k), 1), sub(sub(st->next_bit_pos_fx, start_bit_pos), nbits_tcx)); + + /*Context HM flag*/ + test(); + test(); + IF ( st->tcx_cfg.ctx_hm && !(st->last_core_bs_fx == ACELP_CORE && k == 0) ) + { + prm[j] = get_next_indice_fx(st, 1); + move16(); + nbits_tcx = sub(nbits_tcx, 1); + move16(); + + IF (prm[j]) /* Read PeriodicityIndex */ + { + Word16 NumIndexBits = DecodeIndex(st, + hm_size >= 256, + prm+j+1); + + flag_ctx_hm = 1; + move16(); + + ConfigureContextHm( + lgFB, + nbits_tcx, + *(prm+j+1), + -1, + &hm_cfg); + + nbits_tcx = sub(nbits_tcx, NumIndexBits); + } + } + j = add(j, NPRM_CTX_HM); + phm_cfg = NULL; + move16(); + if (flag_ctx_hm) + { + phm_cfg = &hm_cfg; + move16(); + } + st->resQBits[k] = ACcontextMapping_decode2_no_mem_s17_LC(st, prm+j, + lgFB, + nbits_tcx, + NPRM_RESQ*st->tcx_cfg.resq, + phm_cfg); + move16(); + j = add(j, lgFB); + + } /* k, window index */ + } + + IF(!st->use_partial_copy) + { + IF (LT_16(sub(*total_nbbits, bitsRead[0]), sub(st->next_bit_pos_fx, start_bit_pos))) + { + st->BER_detect = 1; + move16(); + st->next_bit_pos_fx = add(start_bit_pos, sub(*total_nbbits, bitsRead[0])); + } + bitsRead[0] = sub(st->next_bit_pos_fx, start_bit_pos); + move16(); + } + + return; +} + diff --git a/lib_dec/dec_tcx.c b/lib_dec/dec_tcx.c new file mode 100644 index 0000000..efbb2b0 --- /dev/null +++ b/lib_dec/dec_tcx.c @@ -0,0 +1,2404 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "prot_fx.h" +#include "basop_util.h" +#include "stl.h" +#include "options.h" +#include "prot_fx.h" + +extern const Word16 T_DIV_L_Frame[];/*0Q15 * 2^-7 */ + +static Word32 CalculateAbsEnergy( /* o : normalized result Q31 */ + const Word32 L_off, /* i : initial sum value Qn */ + const Word16 x[], /* i : x vector Qn */ + const Word16 lg, /* i : vector length, range [0..7FFF] Q0 */ + Word16 * exp /* o : exponent of result in [-32,31] Q0 */ +); + +static void IMDCT(Word32 *x, Word16 x_e, + Word16 *old_syn_overl, + Word16 *syn_Overl_TDAC, + Word16 *xn_buf, + const Word16 *tcx_aldo_window_1, + const PWord16 *tcx_aldo_window_1_trunc, + const PWord16 *tcx_aldo_window_2, + const PWord16 *tcx_mdct_window_half, + const PWord16 *tcx_mdct_window_minimum, + const PWord16 *tcx_mdct_window_trans, + Word16 tcx_mdct_window_half_length, + Word16 tcx_mdct_window_min_length, + Word16 index, + Word16 left_rect, + Word16 tcx_offset, + Word16 overlap, + Word16 L_frame, + Word16 L_frameTCX, + Word16 L_spec_TCX5, + Word16 L_frame_glob, + Word16 frame_cnt, + Word16 bfi, + Word16 *old_out, + Word16 *Q_old_wtda, + Decoder_State_fx *st + ,Word16 fullbandScale + ,Word16 *acelp_zir + ); + + +void decoder_tcx( + TCX_config *tcx_cfg, /* input: configuration of TCX */ + Word16 prm[], /* input: parameters */ + Word16 A[], /* input: coefficients NxAz[M+1] */ + Word16 Aind[], /* input: frame-independent coefficients Az[M+1] */ + Word16 L_frame_glob, /* input: frame length */ + Word16 L_frameTCX_glob, + Word16 L_spec, + Word16 synth[], /* in/out: synth[-M-LFAC..L_frame] */ + Word16 synthFB[], + Decoder_State_fx *st, + Word16 coder_type, /* input : coder type */ + Word16 bfi, /* input: Bad frame indicator */ + Word16 frame_cnt, /* input: frame counter in the super frame */ + Word16 stab_fac /* input: stability of isf (1Q14) */ +) +{ + Word16 i, index, L_frame, tcx_offset; + Word16 L_frameTCX, tcx_offsetFB; + Word16 firstLine; + Word16 gain_tcx, gain_tcx_e, fac_ns; + Word16 Ap[M+2]; + Word32 x[N_MAX]; + Word16 x_e; + Word16 *xn_buf; + Word16 xn_bufFB[L_MDCT_OVLP_MAX+L_FRAME_PLUS+L_MDCT_OVLP_MAX]; + Word32 xn_buf32[N_MAX]; + Word16 overlap; + Word16 overlapFB; + Word16 noiseFillingSize; + Word16 noiseTransWidth; + Word16 tnsSize; /* number of tns parameters put into prm */ + Word8 fUseTns; /* flag that is set if TNS data is present */ + STnsData tnsData; + Word16 left_rect; + Word16 gainlpc2[FDNS_NPTS]; + Word16 gainlpc2_e[FDNS_NPTS]; + Word16 noiseTiltFactor; + Word16 nf_seed; + Word16 tmp1, tmp2, s, *tmpP16; + Word8 tmp8; + Word32 tmp32; + Word16 gamma1; + Word16 gamma; + Word16 gainCompensate, gainCompensate_e; + Word16 h1[L_FRAME_MAX/4+1]; + Word16 mem[M]; + Word16 temp_concealment_method = 0; + Word16 arith_bits, signaling_bits; + Word16 *prm_ltp, *prm_tns, *prm_hm, *prm_sqQ, *prm_target; + Word16*pInfoTCXNoise; + Word16 acelp_zir[L_FRAME_MAX/2]; + Word16 noise_filling_index; + Word16 infoIGFStartLine; + Word16 L_spec_con; + + prm_target = NULL; /* just to suppress MSVC warnigs */ + + + x_e = 0; /* to avoid compilation warnings */ + nf_seed = 0; /* to avoid compilation warnings */ + + + + /* Overlay xn_buf32 with xn_buf */ + xn_buf = (Word16 *) xn_buf32; + + noiseTransWidth = MIN_NOISE_FILLING_HOLE; + move16(); + tnsSize = 0; + move16(); + fUseTns = 0; + move16(); + gainCompensate = 32768/2; + move16(); + gainCompensate_e = 1; + move16(); + FOR (i=0 ; i < (L_MDCT_OVLP_MAX+L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2; i++) + { + xn_buf32[i] = L_deposit_l(0); + } + + + /* Init lengths */ + + overlap = tcx_cfg->tcx_mdct_window_length; + move16(); + overlapFB = tcx_cfg->tcx_mdct_window_lengthFB; + move16(); + /* Modified the overlap to the delay in case of short blocks*/ + tcx_offset = tcx_cfg->tcx_offset; + move16(); + tcx_offsetFB = tcx_cfg->tcx_offsetFB; + move16(); + L_spec_con = L_spec; + move16(); + gamma1 = st->gamma; + move16(); + + if (st->enableTcxLpc != 0) + { + gamma1 = 0x7FFF; + move16(); + } + + IF (bfi != 0) + { + /* PLC: [TCX: Memory update] + * PLC: Init buffers */ + + assert(st->L_frame_past > 0); + L_frame = st->L_frame_past; + move16(); + L_frameTCX = st->L_frameTCX_past; + move16(); + + left_rect = st->prev_widow_left_rect; + move16(); + + IF (left_rect != 0) + { + tcx_offset = tcx_cfg->lfacNext; + move16(); + tcx_offsetFB = tcx_cfg->lfacNextFB; + move16(); + L_spec = add(L_spec, shr(st->tcx_cfg.tcx_coded_lines, 2)); + L_spec_con = add(L_spec_con, shr(st->tcx_cfg.tcx_coded_lines, 2)); + } + } + ELSE + { + test(); + IF ( frame_cnt == 0 && st->last_core_fx == ACELP_CORE ) + { + if (st->prev_bfi_fx == 0) + { + tcx_cfg->last_aldo = 0; + move16(); + } + + /* if past frame is ACELP */ + L_frame = add(L_frame_glob, tcx_offset); + L_frameTCX = add(L_frameTCX_glob, tcx_offsetFB); + L_spec_con = add(L_spec_con, shr(st->tcx_cfg.tcx_coded_lines, 2)); + assert(tcx_cfg->lfacNext<=0); + L_frame = sub(L_frame , tcx_cfg->lfacNext); + L_frameTCX = sub(L_frameTCX, tcx_cfg->lfacNextFB); + tcx_offset = tcx_cfg->lfacNext; + move16(); + tcx_offsetFB = tcx_cfg->lfacNextFB; + move16(); + left_rect = 1; + move16(); + st->prev_widow_left_rect = 1; + move16(); + } + ELSE + { + + L_frame = L_frame_glob; + move16(); + L_frameTCX = L_frameTCX_glob; + move16(); + left_rect = 0; + move16(); + st->prev_widow_left_rect = 0; + move16(); + } + + IF ( frame_cnt == 0 && EQ_16(st->last_core_bs_fx, ACELP_CORE) ) + { + L_spec += st->tcx_cfg.tcx_coded_lines >> 2; + } + + st->L_frame_past = L_frame; + move16(); + st->L_frameTCX_past = L_frameTCX; + move16(); + } + + test(); + IF ( (EQ_16(L_frame, shr(st->L_frame_fx, 1)))&&(st->tcxonly)) + { + IGFDecUpdateInfo( + &st->hIGFDec, + IGF_GRID_LB_SHORT + ); + } + ELSE + { + test(); + test(); + IF ((EQ_16(st->last_core_fx, ACELP_CORE))||(left_rect&&st->bfi_fx)) + { + IGFDecUpdateInfo( + &st->hIGFDec, + IGF_GRID_LB_TRAN + ); + } + ELSE + { + IGFDecUpdateInfo( + &st->hIGFDec, + IGF_GRID_LB_NORM + ); + } + } + + IF (0 == st->igf) + { + IF (st->narrowBand == 0) + { + /* minimum needed for output with sampling rates lower then the + nominal sampling rate */ + infoIGFStartLine = s_min(L_frameTCX, L_frame); + move16(); + } + ELSE + { + infoIGFStartLine = L_frameTCX; + move16(); + } + } + ELSE + { + infoIGFStartLine = s_min(st->hIGFDec.infoIGFStartLine,L_frameTCX); + move16(); + } + + noiseFillingSize = L_spec; + move16(); + if (st->igf != 0) + { + noiseFillingSize = st->hIGFDec.infoIGFStartLine; + move16(); + } + + + prm_ltp = &prm[1+NOISE_FILL_RANGES]; + move16(); + prm_tns = prm_ltp + LTPSIZE; + move16(); + + /*-----------------------------------------------------------* + * Read TCX parameters * + *-----------------------------------------------------------*/ + + index = 0; + move16(); + + IF (bfi == 0) + { + + index = prm[0]; + move16(); + + /* read noise level (fac_ns) */ + + noise_filling_index = prm[1]; + move16(); + + fac_ns = extract_l(L_shr(L_mult0(noise_filling_index, 0x6000), NBITS_NOISE_FILL_LEVEL)); + } + ELSE + { + fac_ns = 0; + move16(); + } + + /* read TNS data */ + test(); + IF ((bfi == 0) && (tcx_cfg->fIsTNSAllowed != 0)) + { + cast16(); + fUseTns = (Word8)DecodeTnsData(tcx_cfg->pCurrentTnsConfig, + prm_tns, + &tnsSize, + &tnsData); + } + ELSE + { + fUseTns = 0; + move16(); + } + + prm_hm = prm_tns + tnsSize; + move16(); + prm_sqQ = prm_hm + NPRM_CTX_HM; + move16(); + + /*-----------------------------------------------------------* + * Spectrum data * + *-----------------------------------------------------------*/ + + IF (bfi == 0) + { + + /*-----------------------------------------------------------* + * Context HM * + *-----------------------------------------------------------*/ + test(); + test(); + IF(tcx_cfg->ctx_hm != 0 && ( (st->last_core_bs_fx != ACELP_CORE) || (frame_cnt > 0) ) ) + { + st->last_ctx_hm_enabled = prm_hm[0]; + move16(); + { + FOR (i = 0; i < L_spec; i++) /* no context harmonic model, copy MDCT coefficients to x */ + { + + x[i] = L_mult(prm_sqQ[i], + 1 << (30 - SPEC_EXP_DEC)); + move32(); + } + } + x_e = SPEC_EXP_DEC; + move16(); + } + ELSE /* tcx_cfg->ctx_hm == 0 */ + { + + IF (st->tcx_lpc_shaped_ari != 0) /* low rates: new arithmetic coder */ + { + prm_target = prm_sqQ; + move16(); + prm_sqQ = prm_target + 1; + move16(); + + tmp8 = 1; + move16(); + if (EQ_16(st->last_core_bs_fx, ACELP_CORE)) + { + tmp8 = 0; + move16(); + } + + tcx_arith_decode_envelope( + x, &x_e, + L_frame, + L_spec, + st, + Aind, + *prm_target, + prm_sqQ, + tmp8, + prm_hm, /* HM parameter area */ + st->tcx_hm_LtpPitchLag, + &arith_bits, + &signaling_bits, + &nf_seed, + shr(st->bwidth_fx, 1) /* equivalent to: (st->bwidth_fx > WB)?1:0 */ + ); + + st->resQBits[frame_cnt] = sub(*prm_target, arith_bits); + move16(); + } + ELSE /* TCX-only: old arithmetic coder */ + { + FOR (i = 0; i < L_spec; i++) + { + + x[i] = L_mult(prm_sqQ[i], + 1 << (30 - SPEC_EXP_DEC)); + move32(); + } + + set32_fx(x+L_spec, 0, sub(L_frameTCX, L_spec)); + + x_e = SPEC_EXP_DEC; + move16(); + } + + } /* else of if tcx_cfg->ctx_hm */ + tmp1 = s_max(L_frame, L_frameTCX); + tmp1 = s_max(tmp1, L_spec_con); + set32_fx(x+L_spec, 0, sub(tmp1, L_spec)); + + + /*-----------------------------------------------------------* + * adaptive low frequency deemphasis. * + *-----------------------------------------------------------*/ + + weight_a_fx(A, Ap, gamma1, M); + + lpc2mdct(Ap, M, NULL, NULL, gainlpc2, gainlpc2_e); + + + /* initialize LF deemphasis factors in xn_buf */ + tmp1 = s_max(L_spec, L_frameTCX); + set16_fx(xn_buf, 0x4000, tmp1); + + IF (st->tcxonly == 0) + { + AdaptLowFreqDeemph( x, x_e, st->tcx_lpc_shaped_ari, gainlpc2, gainlpc2_e, + L_frame, xn_buf /* LF deemphasis factors */ ); + } + } + + /* Global Gain */ + st->damping = 0; + + IF(bfi==0) + { + /*-----------------------------------------------------------* + * Compute global gain * + *-----------------------------------------------------------*/ + + tmp32 = L_shl(L_mult0(index, 0x797D), 7); /* 6Q25; 0x797D -> log2(10)/28 (Q18) */ + gain_tcx_e = add(extract_l(L_shr(tmp32, 25)), 1); /* get exponent */ + gain_tcx = round_fx(BASOP_Util_InvLog2(L_or(tmp32, 0xFE000000))); + + tmp1 = mult_r(shl(L_spec, 5), 26214/*128.f/NORM_MDCT_FACTOR Q15*/); + s = 15-5-7; + if(L_spec>=1024) /*reduce precision for avoiding overflow*/ + { + tmp1 = mult_r(shl(L_spec, 4), 26214/*128.f/NORM_MDCT_FACTOR Q15*/); + s = 15-4-7; + } + tmp1 = ISqrt16(tmp1, &s); + + gain_tcx = mult(gain_tcx, tmp1); + gain_tcx_e = add(gain_tcx_e, s); + + st->old_gaintcx_bfi = gain_tcx; + move16(); + st->old_gaintcx_bfi_e = gain_tcx_e; + move16(); + + st->cummulative_damping_tcx = 32767/*1.0f Q15*/; + move16(); + } + ELSE /* bfi = 1 */ + { + /* PLC: [TCX: Fade-out] + * derivation of damping factor */ + + + IF( st->use_partial_copy != 0 ) + { + IF( EQ_16(st->rf_frame_type, RF_TCXFD)) + { + tmp32 = L_shl(L_mult0(st->old_gaintcx_bfi, 0x797D), 7); /* 6Q25; 0x797D -> log2(10)/28 (Q18) */ + gain_tcx_e = add(extract_l(L_shr(tmp32, 25)), 1); /* get exponent */ + gain_tcx = round_fx(BASOP_Util_InvLog2(L_or(tmp32, 0xFE000000))); + + tmp1 = mult_r(shl(L_spec, 5), 26214/*128.f/NORM_MDCT_FACTOR Q15*/); + s = 15-5-7; + tmp1 = ISqrt16(tmp1, &s); + + gain_tcx = mult(gain_tcx, tmp1); + gain_tcx_e = add(gain_tcx_e, s); + + st->old_gaintcx_bfi = gain_tcx; + move16(); + st->old_gaintcx_bfi_e = gain_tcx_e; + move16(); + } + ELSE + { + gain_tcx = st->old_gaintcx_bfi; + move16(); + gain_tcx_e = st->old_gaintcx_bfi_e; + move16(); + } + + st->damping = 16384/*1.f Q14*/; /*Q14*/ move16(); + } + ELSE + { + st->damping = Damping_fact(coder_type, st->nbLostCmpt, st->last_good_fx, stab_fac, &(st->Mode2_lp_gainp), st->last_core_fx); + gain_tcx = st->old_gaintcx_bfi; + move16(); + gain_tcx_e = st->old_gaintcx_bfi_e; + move16(); + } + + st->cummulative_damping_tcx = shl(mult(st->cummulative_damping_tcx,st->damping),1);/*shl(Q15*Q14,1)=shl(Q14,1) = Q15*/ + + } + { + + IF(bfi) + { + gamma = gamma1; + move16(); + if (st->envWeighted) + { + gamma = st->gamma; + move16(); + } + + /* PLC: [TCX: Fade-out] + * PLC: invert LPC weighting in case of PLC */ + IF (st->enableTcxLpc != 0) + { + gamma = add(mult_r(st->cummulative_damping_tcx,sub(st->gamma, 32767/*1.0f Q15*/)), 32767/*1.0f Q15*/); + } + ELSE + { + gamma = add(mult_r(st->cummulative_damping_tcx,sub(gamma1, 32767/*1.0f Q15*/)), 32767/*1.0f Q15*/); + } + weight_a_fx(A, Ap, gamma, M); + + lpc2mdct(Ap, M, NULL, NULL, gainlpc2, gainlpc2_e); + + } + tmp2 = 0; + move16(); + + set16_fx(h1, 0, add(L_SUBFR,1)); + set16_fx(mem, 0, M); + h1[0] = 32768/32; + move16(); + E_UTIL_synthesis(0,Ap, h1, h1, L_SUBFR, mem, 0, M ); + deemph_fx(h1, st->preemph_fac, L_SUBFR, &tmp2); + /* impulse response level = gain introduced by synthesis+deemphasis */ + test(); + IF (bfi==0) + { + /* st->last_gain_syn_deemph = (float)sqrt(dot_product( h1, h1, L_SUBFR)); */ + tmp32 = Dot_productSq16HQ( 0, h1, L_SUBFR, &st->last_gain_syn_deemph_e)/*Q15, st->last_gain_syn_deemph_e*/; + st->last_gain_syn_deemph_e = add(st->last_gain_syn_deemph_e,10/*scaling of h1[0] and E_UTIL_synthesis * 2*/); + tmp32 = Sqrt32(tmp32,&st->last_gain_syn_deemph_e); + st->last_gain_syn_deemph = round_fx(tmp32); + /*for avoiding compiler warnings*/ + st->gainHelper = 32768/2; + move16(); + st->gainHelper_e = 1; + move16(); + st->stepCompensate = 0; + move16(); + st->stepCompensate_e = 0; + move16(); + } + /* not instrumenting the additional test() here seems to be common practice */ + ELSE IF (EQ_16(TCX_20_CORE, st->core_fx)||EQ_16(frame_cnt,1)) + { + /* gainCompensate = st->last_gain_syn_deemph/(float)sqrt(dot_product( h1, h1, L_SUBFR)); */ + tmp32 = Dot_productSq16HQ( 0, h1, L_SUBFR, &gainCompensate_e)/*Q15, gainCompensate_e*/; + gainCompensate_e = add(gainCompensate_e,10/*scaling of h1[0] and E_UTIL:synthesis*/); + gainCompensate = round_fx(Sqrt32(tmp32,&gainCompensate_e))/*Q15, gainCompensate_e*/; + BASOP_Util_Divide_MantExp ( st->last_gain_syn_deemph, + st->last_gain_syn_deemph_e, + gainCompensate, + gainCompensate_e, + &gainCompensate, + &gainCompensate_e); + + tmp1 = T_DIV_L_Frame[L_shl(L_mac(-28000,st->L_frame_fx,95),1-15)]; + + IF (EQ_16(st->nbLostCmpt,1)) + { + /* stepCompensate = (1.f - gainCompensate)/st->L_frame_fx; */ + st->stepCompensate_e = BASOP_Util_Add_MantExp( + tmp1, + -7, + negate(mult(gainCompensate,tmp1)), + add(-7,gainCompensate_e), + &st->stepCompensate); + + st->gainHelper = 32768/2; + move16(); + st->gainHelper_e = 1; + move16(); + } + ELSE + { + /* stepCompensate = (st->last_concealed_gain_syn_deemph - gainCompensate)/st->L_frame_fx; */ + st->stepCompensate_e = BASOP_Util_Add_MantExp( + mult(tmp1,st->last_concealed_gain_syn_deemph), + add(-7, st->last_concealed_gain_syn_deemph_e), + negate(mult(tmp1,gainCompensate)), + add(-7, gainCompensate_e), + &st->stepCompensate); + move16(); + move16(); + st->gainHelper = st->last_concealed_gain_syn_deemph; + st->gainHelper_e = st->last_concealed_gain_syn_deemph_e; + } + move16(); + move16(); + st->last_concealed_gain_syn_deemph = gainCompensate; + st->last_concealed_gain_syn_deemph_e = gainCompensate_e; + } + + } + + + /*-----------------------------------------------------------* + * Residual inv. Q. * + *-----------------------------------------------------------*/ + test(); + IF ((bfi == 0) && (tcx_cfg->resq != 0)) + { + + IF (st->tcx_lpc_shaped_ari != 0) /* new arithmetic coder */ + { + + Word16 *prm_resq; + + prm_resq = prm_sqQ + + *prm_target /* = targetBits */ + - st->resQBits[frame_cnt]; + + i = tcx_ari_res_invQ_spec(x, x_e, L_spec, + prm_resq, + st->resQBits[frame_cnt], + 0, + tcx_cfg->sq_rounding, + xn_buf /* LF deemphasis factors */ ); + } + ELSE /* old arithmetic coder */ + { + i = tcx_res_invQ_gain(&gain_tcx, &gain_tcx_e, + &prm_sqQ[L_spec], + st->resQBits[frame_cnt]); + + tmpP16 = xn_buf; + if (st->tcxonly != 0) tmpP16 = NULL; + + tcx_res_invQ_spec(x, x_e, L_spec, + &prm_sqQ[L_spec], + st->resQBits[frame_cnt], + i, + tcx_cfg->sq_rounding, + tmpP16 /* LF deemphasis factors */ ); + } + } + test(); + IF (bfi == 0 && st->tcxonly != 0) + { + test(); + test(); + IF (st->tcxltp && (st->tcxltp_gain > 0) && !fUseTns) + { + + PsychAdaptLowFreqDeemph(x, gainlpc2, gainlpc2_e, NULL); + } + } + + /* for FAC */ + + test(); + IF (bfi == 0 && st->tcxonly == 0) + { + + + /* Replication of ACELP formant enhancement for low rates */ + IF (LT_32(st->total_brate_fx, ACELP_13k20)||st->rf_flag!=0) + { + tcxFormantEnhancement(xn_buf, gainlpc2, gainlpc2_e, x, &x_e, L_frame, L_frameTCX); + } + } + + /*-----------------------------------------------------------* + * Add gain to the lpc gains * + *-----------------------------------------------------------*/ + + if(st->VAD==0 ) + { + gain_tcx = mult_r(gain_tcx, tcx_cfg->na_scale); + } + + i = norm_s(gain_tcx); + gain_tcx = shl(gain_tcx, i); + gain_tcx_e = sub(gain_tcx_e, i); + FOR (i = 0; i < FDNS_NPTS; i++) + { + gainlpc2[i] = mult_r(gainlpc2[i], gain_tcx); + move16(); + } + + + /*-----------------------------------------------------------* + * Noise filling. * + *-----------------------------------------------------------*/ + + test(); + IF (bfi==0 && (fac_ns > 0)) + { + + tmp1 = 0; + move16(); + test(); + if ( GE_16(st->bits_frame, 256)&&st->rf_flag==0) + { + tmp1 = 1; + move16(); + } + + firstLine = tcxGetNoiseFillingTilt( A, M, L_frame, tmp1, &noiseTiltFactor ); + + IF (st->tcxonly != 0) + { + tmp1 = 0; + move16(); + test(); + test(); + if ((tcx_cfg->ctx_hm != 0) && (st->last_core_fx != ACELP_CORE) && (st->last_ctx_hm_enabled != 0)) + { + tmp1 = 10240/*0.3125f Q15*/; + move16(); + } + noiseTransWidth = HOLE_SIZE_FROM_LTP(s_max(st->tcxltp_gain, tmp1)); + + if (EQ_16(L_frame, shr(st->L_frame_fx, 1))) + { + noiseTransWidth = 3; /* minimum transition fading for noise filling in TCX-10 */ move16(); + } + } + + + IF (st->tcx_lpc_shaped_ari == 0) /* old arithmetic coder */ + { + /* noise filling seed */ + tmp32 = L_deposit_l(0); + FOR (i = 0; i < L_spec; i++) + { + tmp32 = L_macNs(tmp32, abs_s(prm_sqQ[i]), i); + } + nf_seed = extract_l(tmp32); + } + + tmp1 = nf_seed; + move16(); + + pInfoTCXNoise = NULL; + if (st->igf) + { + pInfoTCXNoise = st->hIGFDec.infoTCXNoise; + move16(); + } + tcx_noise_filling(x, x_e, + tmp1 /* seed */, + firstLine, + noiseFillingSize, + noiseTransWidth, + L_frame, + noiseTiltFactor, + fac_ns, + pInfoTCXNoise + ); + st->seed_tcx_plc = tmp1; + move16(); + } + + IF (st->enablePlcWaveadjust) + { + IF (bfi) + { + IF (EQ_16(st->nbLostCmpt, 1)) + { + st->plcInfo.concealment_method = TCX_NONTONAL; + move16(); + /* tonal/non-tonal decision */ + test(); + test(); + IF (EQ_16(st->plcInfo.Transient[0],1) + && EQ_16(st->plcInfo.Transient[1], 1) + && EQ_16(st->plcInfo.Transient[2], 1)) + { + Word16 sum_word16 = 0; + move16(); + + FOR (i = 9; i >= 0; i--) + { + sum_word16 = add(sum_word16, st->plcInfo.TCX_Tonality[i]); + } + + if(GE_16(sum_word16, 6)) + { + st->plcInfo.concealment_method = TCX_TONAL; + move16(); + } + } + + if(st->tonal_mdct_plc_active) + { + st->plcInfo.concealment_method = TCX_TONAL; + move16(); + } + } + + if (GT_16(L_frameTCX, st->L_frameTCX)) + { + st->plcInfo.concealment_method = TCX_TONAL; + move16(); + } + + temp_concealment_method = st->plcInfo.concealment_method; + move16(); + + if (EQ_16(st->core_fx, TCX_10_CORE)) + { + temp_concealment_method = TCX_TONAL; + move16(); + } + } + /* get the starting location of the subframe in the frame */ + IF (EQ_16(st->core_fx, TCX_10_CORE)) + { + st->plcInfo.subframe_fx =extract_l( L_mult0(frame_cnt,L_frameTCX_glob)); + } + } + + /* PLC: [TCX: Tonal Concealment] */ + /* PLC: [TCX: Fade-out] + * PLC: Fade out to white noise */ + + IF (bfi == 0) + { + TonalMDCTConceal_SaveFreqSignal(&st->tonalMDCTconceal, + x, x_e, + L_frameTCX, + L_frame, + gainlpc2, gainlpc2_e, + gain_tcx_e); + } + ELSE + { + test(); + IF( !st->enablePlcWaveadjust || EQ_16(temp_concealment_method, TCX_TONAL)) + { + Word16 f, tmp; + + /* set f to 1 to not fade out */ + /* set f to 0 to immediately switch to white noise */ + f = st->cummulative_damping_tcx; + move16(); + if (0 != st->tcxonly) + { + f = 32767/*1.0f Q15*/; + move16(); + } + + test(); + test(); + IF ( (frame_cnt == 0) && (EQ_16(L_frameTCX, shr(st->L_frameTCX, 1))) + && (st->tcxonly) && (!st->tonal_mdct_plc_active) && (EQ_16(st->nbLostCmpt, 1)) + && (tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) + && (tcx_cfg->tcx_curr_overlap_mode != FULL_OVERLAP) ) + { + Word16 exp1, exp2; + Word32 E_2ndlast, E_last; + + E_2ndlast = CalculateAbsEnergy(1, &(st->tonalMDCTconceal.lastBlockData.spectralData[0]), infoIGFStartLine, &exp2); + E_last = CalculateAbsEnergy(1, &(st->tonalMDCTconceal.lastBlockData.spectralData[1]), infoIGFStartLine, &exp1); + + BASOP_Util_Divide_MantExp(extract_h(E_2ndlast), exp2, extract_h(E_last), exp1, &tmp1, &tmp2); + + tmp1 = shr(tmp1,2); /*Q13*/ + tmp1 = shl(tmp1,tmp2); + test(); + test(); + /* replace higher energy TCX5 frame by lower one to avoid energy fluctuation */ + IF(GT_16(tmp1,16384 /*2 in Q13*/)) + { + FOR(i=0; itonalMDCTconceal.lastBlockData.spectralData[i] = st->tonalMDCTconceal.lastBlockData.spectralData[i+1]; + } + } + ELSE IF(LT_16(tmp1,4096/*0.5 in Q13*/)) + { + FOR(i=0; itonalMDCTconceal.lastBlockData.spectralData[i+1] = st->tonalMDCTconceal.lastBlockData.spectralData[i]; + } + } + } + + noiseTiltFactor = 32767/*1.0f Q15*/; + move16(); + + tmp = 0; + move16(); + test(); + IF( GE_16(st->bits_frame, 256)&&st->rf_flag==0) + { + tmp = 1; + move16(); + } + + tcxGetNoiseFillingTilt( A, M, L_frame, tmp, &noiseTiltFactor ); + + TonalMDCTConceal_InsertNoise(&st->tonalMDCTconceal, + x, + &x_e, + st->tonal_mdct_plc_active, + &st->seed_tcx_plc, + noiseTiltFactor, + f, + infoIGFStartLine + ); + + } + } + + + IF (LT_16(L_spec, L_frame)) + { + set32_fx(x+L_spec, 0, sub(L_frame,L_spec)); + } + ELSE IF (GT_16(L_spec, L_frameTCX)) + { + set32_fx(x+L_frameTCX, 0, sub(L_spec,L_frameTCX)); + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF ( bfi && (!st->enablePlcWaveadjust || EQ_16(temp_concealment_method, TCX_TONAL)) + && st->igf && (frame_cnt == 0) && (EQ_16(L_frameTCX, shr(st->L_frameTCX, 1))) + && (st->tcxonly) && (!st->tonal_mdct_plc_active) && (EQ_16(st->nbLostCmpt, 1)) + && (tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) + && (tcx_cfg->tcx_curr_overlap_mode != FULL_OVERLAP) ) + { + IGFDecCopyLPCFlatSpectrum( + &st->hIGFDec, + x, + x_e, + IGF_GRID_LB_SHORT + ); + Copy(st->hIGFDec.igfData.igf_curr_subframe[0][0], st->hIGFDec.igfData.igf_curr_subframe[1][0], IGF_MAX_SFB); + } + + /*-----------------------------------------------------------* + * Noise shaping in frequency domain (1/Wz) * + *-----------------------------------------------------------*/ + test(); + IF(st->igf && ! bfi) + { + test(); + IF ( (EQ_16(L_frame, shr(st->L_frame_fx, 1)))&&(st->tcxonly)) + { + IGFDecCopyLPCFlatSpectrum( + &st->hIGFDec, + x, + x_e, + IGF_GRID_LB_SHORT + ); + } + ELSE + { + IF (EQ_16(st->last_core_fx, ACELP_CORE)) + { + IGFDecCopyLPCFlatSpectrum( + &st->hIGFDec, + x, + x_e, + IGF_GRID_LB_TRAN + ); + } + ELSE + { + IGFDecCopyLPCFlatSpectrum( + &st->hIGFDec, + x, + x_e, + IGF_GRID_LB_NORM + ); + + } + } + } + + /* LPC gains already available */ + test(); + test(); + IF(!st->enablePlcWaveadjust || !bfi || (EQ_16(temp_concealment_method, TCX_TONAL))) + { + x_e = add(x_e, gain_tcx_e); + mdct_shaping(x, L_frame, gainlpc2, gainlpc2_e); + IF ( bfi == 0 ) + { + FOR (i = L_frame; i < L_spec; i++) + { + x[i] = L_shl(Mpy_32_16_1(x[i], gainlpc2[FDNS_NPTS-1]), gainlpc2_e[FDNS_NPTS-1]); + move32(); + } + } + + set32_fx(x+L_spec, 0, sub(L_frameTCX, L_spec)); + test(); + test(); + IF (( bfi != 0) && ( !st->enablePlcWaveadjust || EQ_16(temp_concealment_method, TCX_TONAL))) + { + scale_sig32(x+infoIGFStartLine, sub(L_spec, infoIGFStartLine), negate(gain_tcx_e)); + } + } + + /* PLC: [TCX: Tonal Concealment] */ + IF( bfi && st->tonal_mdct_plc_active ) + { + TonalMDCTConceal_Apply(&st->tonalMDCTconceal, x, &x_e); + } + + tmp32 = L_deposit_h(0); + if(st->tcxltp_last_gain_unmodified > 0) + { + tmp32 = L_add(st->old_fpitch, 0); + } + tmp8 = 0; + move16(); + test(); + if(bfi && st->tonal_mdct_plc_active) + { + tmp8 = 1; + move16(); + } + TonalMDCTConceal_UpdateState(&st->tonalMDCTconceal, + L_frameTCX, + tmp32, + bfi, + tmp8); + + IF (st->enablePlcWaveadjust) + { + Word16 core; + core = st->core_fx; + move16(); + /* spectrum concealment */ + IF (bfi && (EQ_16(temp_concealment_method, TCX_NONTONAL))) + { + /* x_e =31-x_scale; */ + concealment_decode_fix(core, x, &x_e, &st->plcInfo); + } + /* update spectrum buffer, tonality flag, etc. */ + concealment_update_x(bfi, core, st->tonality_flag, x, &x_e, &st->plcInfo); + } + + /*-----------------------------------------------------------* + * IGF * + *-----------------------------------------------------------*/ + test(); + test(); + IF (st->igf && !((EQ_16(L_frame, shr(st->L_frame_fx, 1)))&&(st->tcxonly))) + { + Word16 igfGridIdx; + + test(); + test(); + IF ((EQ_16(st->last_core_fx, ACELP_CORE))||(left_rect&&bfi)) + { + /* packet loss after first TCX must be handled like transition frame */ + igfGridIdx = IGF_GRID_LB_TRAN; + } + ELSE + { + igfGridIdx = IGF_GRID_LB_NORM; + } + + st->hIGFDec.igfData.igfInfo.nfSeed = extract_l(L_mac0(13849L, nf_seed, 31821)); + + IGFDecApplyMono( + &st->hIGFDec, + x, + &x_e, + igfGridIdx, + bfi + ); + } + test(); + test(); + IF (st->igf && ((EQ_16(L_frame, shr(st->L_frame_fx, 1)))&&(st->tcxonly))) + { + st->hIGFDec.igfData.igfInfo.nfSeed = extract_l(L_mac0(13849L, nf_seed, 31821)); + IGFDecApplyMono( + &st->hIGFDec, + x, + &x_e, + IGF_GRID_LB_SHORT, + bfi + ); + } + + index = tcx_cfg->tcx_last_overlap_mode; /* backup last TCX overlap mode */ move16(); + + /* normalize spectrum to minimize IMDCT noise */ + tmp1 = s_max(s_max(L_frame,L_frameTCX), L_spec); + s = s_max(0, sub(getScaleFactor32(x, tmp1), 4)); /* Keep 4 bits headroom for TNS */ + Scale_sig32(x, tmp1, s); + x_e = sub(x_e, s); + + IF(st->igf) + { + test(); + IF(st->hIGFDec.flatteningTrigger != 0 && fUseTns == 0) + { + Word16 startLine = st->hIGFDec.infoIGFStartLine; + Word16 endLine = st->hIGFDec.infoIGFStopLine; + Word32 x_itf[N_MAX_TCX-IGF_START_MN]; + Word16 j; + + const Word16* chk_sparse = st->hIGFDec.flag_sparse; + const Word32* virtualSpec = st->hIGFDec.virtualSpec; + + const Word16 maxOrder = 8; + Word16 curr_order = 0; /* not counted */ + Word16 A_itf[ITF_MAX_FILTER_ORDER+1]; + Word16 Q_A_itf; + Word16 predictionGain = 0; /* not counted */ + + move16(); + move16(); + + move16(); + + FOR (j = startLine; j < endLine; j++) + { + IF (EQ_16(chk_sparse[j-IGF_START_MN], 2)) + { + x_itf[j-IGF_START_MN] = x[j]; + move32(); + x[j] = virtualSpec[j-IGF_START_MN]; + move32(); + } + } + ITF_Detect_fx(x+IGF_START_MN, startLine, endLine, maxOrder, A_itf, &Q_A_itf, &predictionGain, &curr_order, shl(x_e, 1)); + s = getScaleFactor32(&x[startLine], sub(endLine, startLine)); + s = sub(s, 2); + FOR(j = startLine; j < endLine; j++) + { + x[j] = L_shl(x[j], s); + move32(); + } + + ITF_Apply_fx(x, startLine, endLine, A_itf, Q_A_itf, curr_order); + + FOR(j = startLine; j < endLine; j++) + { + x[j] = L_shr(x[j], s); + move32(); + } + + FOR (j = startLine; j < endLine; j++) + { + if (EQ_16(chk_sparse[j-IGF_START_MN],2)) + { + x[j] = x_itf[j-IGF_START_MN]; + move32(); + } + } + } + } + + test(); + IF ((EQ_16(L_frame, shr(st->L_frame_fx, 1)))&&(st->tcxonly!=0)) + { + Word16 L = L_frameTCX; + move16(); + + test(); + test(); + test(); + if ((tcx_cfg->fIsTNSAllowed != 0 && fUseTns != 0 && bfi == 0) || (GT_16(L_spec, L_frameTCX))) + { + L = L_spec; + move16(); + } + + tcxInvertWindowGrouping(tcx_cfg, + xn_buf32, + x, + L, + fUseTns, + st->last_core_fx, + index, + frame_cnt, + bfi + ); + } + + + /*-----------------------------------------------------------* + * Temporal Noise Shaping Synthesis * + *-----------------------------------------------------------*/ + + test(); + test(); + IF ((tcx_cfg->fIsTNSAllowed != 0) && (fUseTns != 0) && bfi == 0 ) + { + /* Apply TNS to get the reconstructed signal */ + test(); + test(); + SetTnsConfig(tcx_cfg, L_frame_glob == st->L_frame_fx, (st->last_core_fx == ACELP_CORE) && (frame_cnt == 0)); + + ApplyTnsFilter(tcx_cfg->pCurrentTnsConfig, &tnsData, x, 0); + + test(); + IF ((EQ_16(L_frame, shr(st->L_frame_fx, 1)))&&(st->tcxonly!=0)) + { + + test(); + test(); + test(); + IF ((tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) || + ((tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP) && (frame_cnt == 0) && (index == 0)) + ) + { + tmp1 = shr(tcx_cfg->tnsConfig[0][0].iFilterBorders[0], 1); + /* undo rearrangement of LF sub-window lines for TNS synthesis filtering */ + IF (s_max(L_frameTCX, L_spec) > tcx_cfg->tnsConfig[0][0].iFilterBorders[0]) + { + tmp2 = shr(s_max(L_frameTCX, L_spec), 1); + Copy32(x+tmp1+8, x+tmp2+8, sub(tmp1, 8)); + Copy32(x+8, x+tmp2, 8); + Copy32(x+16, x+8, sub(tmp1, 8)); + set32_fx(x+tmp1, 0, sub(tmp2, tmp1)); + set32_fx(x+tmp2+tmp1, 0, sub(tmp2, tmp1)); + } + ELSE + { + Copy32(x+8, xn_buf32, 8); + Copy32(x+16, x+8, sub(tmp1,8)); + Copy32(xn_buf32, x+tmp1, 8); + } + + } + } + } + + + /*-----------------------------------------------------------* + * Compute inverse MDCT of x[]. * + *-----------------------------------------------------------*/ + + + Copy32(x, xn_buf32, s_max(s_max(L_frame,L_frameTCX), L_spec)); + + IF(st->igf != 0) + { + set32_fx( xn_buf32+st->hIGFDec.infoIGFStartLine, 0, sub(L_frameTCX, st->hIGFDec.infoIGFStartLine) ); + } + IMDCT(xn_buf32, x_e, + st->syn_Overl, + st->syn_Overl_TDAC, + xn_buf, + tcx_cfg->tcx_aldo_window_1, + tcx_cfg->tcx_aldo_window_1_trunc, + tcx_cfg->tcx_aldo_window_2, + st->tcx_cfg.tcx_mdct_window_half, + tcx_cfg->tcx_mdct_window_minimum, + st->tcx_cfg.tcx_mdct_window_trans, + st->tcx_cfg.tcx_mdct_window_half_length, + tcx_cfg->tcx_mdct_window_min_length, + index, + left_rect, + tcx_offset, + overlap, + L_frame, + L_frameTCX, + shr(s_max(L_frameTCX, L_spec), 1), + L_frame_glob, + frame_cnt, + bfi, + st->old_out_LB_fx, + &st->Q_old_wtda_LB, + st, + 0, + acelp_zir); + + /* Generate additional comfort noise to mask potential coding artefacts */ + IF ( st->flag_cna != 0 ) + { + generate_masking_noise_mdct (x, + &x_e, + st->hFdCngDec_fx->hFdCngCom, + s_max(s_max(L_frame,L_frameTCX), L_spec) + ); + } + + IMDCT(x, x_e, + st->syn_OverlFB, + st->syn_Overl_TDACFB, + xn_bufFB, + tcx_cfg->tcx_aldo_window_1_FB, + tcx_cfg->tcx_aldo_window_1_FB_trunc, + tcx_cfg->tcx_aldo_window_2_FB, + tcx_cfg->tcx_mdct_window_halfFB, + tcx_cfg->tcx_mdct_window_minimumFB, + tcx_cfg->tcx_mdct_window_transFB, + tcx_cfg->tcx_mdct_window_half_lengthFB, + tcx_cfg->tcx_mdct_window_min_lengthFB, + index, + left_rect, + tcx_offsetFB, + overlapFB, + L_frameTCX, + L_frameTCX, + shr(s_max(L_frameTCX, L_spec), 1), + L_frameTCX_glob, + frame_cnt, + bfi, + st->old_out_fx, + &st->Q_old_wtda, + st, + div_l(L_mult(FSCALE_DENOM, L_frameTCX_glob), L_frame_glob), + acelp_zir + ); + + + + + + /* PLC: [TCX: Tonal Concealment] */ + + IF (!bfi) + { + st->second_last_tns_active = st->last_tns_active; + st->last_tns_active = 0; + move16(); + test(); + if ( tcx_cfg->fIsTNSAllowed && fUseTns) + { + st->last_tns_active = 1; + move16(); + } + + st->tcxltp_third_last_pitch = st->tcxltp_second_last_pitch; + move32(); + st->tcxltp_second_last_pitch = st->old_fpitch; + move32(); + st->old_fpitch = L_add(L_deposit_h(st->tcxltp_pitch_int), L_mult( st->tcxltp_pitch_fr, div_s(1,st->pit_res_max) /*Q16*/)); + st->old_fpitchFB = Mpy_32_16_1(st->old_fpitch/*Q16*/, mult_r(L_frameTCX/*Q0*/,getInvFrameLen(L_frame)/*Q21*/)/*Q6*/)/*Q7*/; + st->old_fpitchFB = L_shr(st->old_fpitchFB,7-16);/*->Q16*/ + } + + + /* Update old_syn_overl */ + IF (st->tcx_cfg.last_aldo == 0) + { + Copy(xn_buf+L_frame, st->syn_Overl, overlap); + Copy(xn_bufFB+L_frameTCX, st->syn_OverlFB, overlapFB); + } + + /* Output */ + Copy(xn_buf+shr(overlap,1)-tcx_offset, synth, L_frame_glob); + Copy(xn_bufFB+shr(overlapFB,1)-tcx_offsetFB, synthFB, L_frameTCX_glob); + +} + + + +void decoder_tcx_post(Decoder_State_fx *st_fx, + Word16 *synth, + Word16 *synthFB, + Word16 *A, + Word16 bfi + ) +{ + Word16 i; + Word16 level_syn; + Word16 level_syn_e; + Word32 step; + Word16 gainCNG,gainCNG_e; + Word16 xn_buf[L_FRAME_MAX]; + Word16 tmp1, tmp2, s; + Word32 tmp32; + Word32 tmp32_1, tmp32_2; + + /* TCX output */ + Copy( synth, xn_buf, st_fx->L_frame_fx ); + + /* first TCX frame after ACELP; overwrite ltp initialization done during acelp PLC */ + test(); + test(); + if (!st_fx->bfi_fx && st_fx->prev_bfi_fx && EQ_16(st_fx->last_core_fx,ACELP_CORE)) + { + st_fx->tcxltp_last_gain_unmodified = 0; + move16(); + } + IF (bfi != 0 && st_fx->use_partial_copy == 0) + { + test(); + /* run lpc gain compensation not for waveform adjustment */ + IF ( 0 == st_fx->enablePlcWaveadjust || EQ_16(st_fx->plcInfo.concealment_method,TCX_TONAL)) + { + UWord32 dmy; + tmp32_1 /*gainHelperFB*/ = L_shl_r(L_deposit_h(st_fx->gainHelper) ,sub(st_fx->gainHelper_e, 31-28));/*Q28*/ + tmp32_2 /*stepCompensateFB*/= L_shl_r(L_deposit_h(st_fx->stepCompensate),sub(st_fx->stepCompensate_e,31-28));/*Q28*/ + + Mpy_32_32_ss(tmp32_2/*Q28*/, + L_shl(L_mult0(st_fx->L_frame_fx, + getInvFrameLen(st_fx->L_frameTCX)/*Q21*/)/*Q21*/, + 8)/*Q29*/, + &tmp32_2, + &dmy ); /*Q26*/ + + tmp32_2 = L_shl(tmp32_2,3-1); /*Q28*/ + + FOR( i=0; i < st_fx->L_frameTCX; i++ ) + { + tmp32 = L_shl(tmp32_1/*Q28*/,-(28-15)); /*16Q15*/ + synthFB[i] = round_fx(L_shl(Mpy_32_16_1(tmp32,synthFB[i]), 16)); + move16(); + tmp32_1 = L_sub(tmp32_1 , tmp32_2); + } + } + tmp32_1 /*gainHelper*/ = L_shl_r(L_deposit_h(st_fx->gainHelper) ,sub(st_fx->gainHelper_e, 31-28));/*Q28*/ + tmp32_2 /*stepCompensate*/= L_shl_r(L_deposit_h(st_fx->stepCompensate),sub(st_fx->stepCompensate_e,31-28));/*Q28*/ + FOR( i=0; i < st_fx->L_frame_fx; i++ ) + { + tmp32 = L_shl(tmp32_1/*Q28*/,-(28-15)); /*16Q15*/ + xn_buf[i] = extract_l(Mpy_32_16_1(tmp32,xn_buf[i])); + move16(); + tmp32_1 = L_sub(tmp32_1 , tmp32_2); + } + } + + /* PLC: [TCX: Fade-out] + * PLC: estimate and update CNG energy */ + + /* level_syn = (float)sqrt(( dot_product(synthFB, synthFB, L_frame)) / L_frame ); */ + s = sub(getScaleFactor16(synthFB, st_fx->L_frameTCX), 4); + { + Word64 tmp64 = 0; + move64(); + FOR (i = 0; i < st_fx->L_frameTCX; i++) + { + tmp1 = shl(synthFB[i], s); + tmp64 = W_mac0_16_16(tmp64, tmp1, tmp1); + } + tmp32 = W_sat_l(tmp64); + } + tmp32 = Mpy_32_16_1(tmp32, getInvFrameLen(st_fx->L_frameTCX)); + tmp2 = norm_l(tmp32); + tmp1 = round_fx(L_shl(tmp32, tmp2)); + s = sub(sub(sub(1, shl(s, 1)), 6/*table lookup for inverse framelength*/), tmp2); + tmp1 = Sqrt16(tmp1, &s); + move16(); + level_syn = tmp1; /*Q0*/ + + /* PLC: [TCX: Fade-out] + * PLC: estimate and update CNG energy */ + + level_syn_e = add(s,15); + test(); + test(); + IF (bfi == 0 && st_fx->tcxonly != 0 && EQ_16(st_fx->clas_dec , UNVOICED_CLAS)) + { + + Word16 Qnew_levelBackgroundTrace; + Qnew_levelBackgroundTrace = 0; + move16(); + minimumStatistics(st_fx->conNoiseLevelMemory, /*Q15*/ + &st_fx->conNoiseLevelIndex, /*Q0 */ + &st_fx->conCurrLevelIndex, /*Q0 */ + &st_fx->conCngLevelBackgroundTrace, /*Q15*/ + &st_fx->conLastFrameLevel, /*Q15*/ + level_syn, /*Q15*/ + st_fx->conNoiseLevelMemory_e, + st_fx->conCngLevelBackgroundTrace_e, + &Qnew_levelBackgroundTrace, + &st_fx->conLastFrameLevel_e, + level_syn_e /*scaling of level_syn*/ + ); + + /*note: All parameters being different from Q0 have to have the same Q-format*/ + + st_fx->conCngLevelBackgroundTrace_e = Qnew_levelBackgroundTrace; + move16(); + } + + /* PLC: [TCX: Fade-out] + * PLC: fade-out in time domain */ + IF (bfi != 0) + { + Word32 conceal_eof_gain32; + Word32 conceal_eof_gainFB; + move16(); + move16(); + gainCNG = 1; + gainCNG_e = 14+15+6; /*gainCNG is 2`097`152 - should be enough in case tracinglevel =~0 */ + IF (st_fx->tcxonly != 0) + { + /*gainCNG = st_fx->conCngLevelBackgroundTrace/(tracingLevel+0.01f);*/ + + IF(level_syn != 0) + { + BASOP_Util_Divide_MantExp ( + st_fx->conCngLevelBackgroundTrace, + st_fx->conCngLevelBackgroundTrace_e, + level_syn, + level_syn_e, + &gainCNG, + &gainCNG_e); + } + } + ELSE + { + /*gainCNG = st_fx->cngTDLevel/(tracingLevel+0.01f);*/ + IF(level_syn != 0) + { + BASOP_Util_Divide_MantExp ( + st_fx->cngTDLevel, + st_fx->cngTDLevel_e, + level_syn, + level_syn_e, + &gainCNG, + &gainCNG_e); + } + } + + if ((EQ_16(st_fx->nbLostCmpt, 1))) + { + st_fx->conceal_eof_gain = 16384/*1.0f Q14*/; /*Q14*/ move16(); + } + + /* step = (st_fx->conceal_eof_gain - ( st_fx->conceal_eof_gain * st_fx->damping + gainCNG * (1 - st_fx->damping) )) / st_fx->L_frame_fx; */ + tmp2 = BASOP_Util_Add_MantExp( + mult_r(st_fx->conceal_eof_gain /*Q14*/, + st_fx->damping /*Q14*/), + 15-13/*->Q15*/, + mult_r(gainCNG/*Q15*/,sub(0x4000,st_fx->damping/*Q14*/)) /*Q14*/, + add(gainCNG_e,15-14)/*->Q15*/, + &tmp1); + tmp2 = BASOP_Util_Add_MantExp(st_fx->conceal_eof_gain, 15-14, negate(tmp1), tmp2, &tmp1); + + step = L_shl(L_mult(tmp1, getInvFrameLen(st_fx->L_frame_fx)), sub(tmp2,6/*scaling from table lookup*/ +1/*go to Q30*/)); /*Q30*/ + { + Word32 stepFB; + UWord32 dmy; + conceal_eof_gainFB = L_deposit_h(st_fx->conceal_eof_gain); /*Q30*/ + Mpy_32_32_ss(step,L_shl(L_mult0(st_fx->L_frame_fx, getInvFrameLen(st_fx->L_frameTCX)),8),&stepFB ,&dmy ); + stepFB = L_shl(stepFB,3-1); /*Q30*/ + + FOR( i=0; i < st_fx->L_frameTCX; i++ ) + { + synthFB[i] = round_fx(L_shl(Mpy_32_16_1(conceal_eof_gainFB, synthFB[i]),1)); + move16(); + conceal_eof_gainFB = L_sub(conceal_eof_gainFB, stepFB); + } + } + conceal_eof_gain32 = L_deposit_h(st_fx->conceal_eof_gain); /*Q30*/ + FOR( i=0; i < st_fx->L_frame_fx; i++ ) + { + xn_buf[i] = round_fx(L_shl(Mpy_32_16_1(conceal_eof_gain32 /*Q30*/, xn_buf[i]),1)); + move16(); + conceal_eof_gain32 = L_sub(conceal_eof_gain32,step); + } + st_fx->conceal_eof_gain = round_fx(conceal_eof_gain32); /*Q14*/ move16(); + /* run lpc gain compensation not for waveform adjustment */ test(); + IF ( 0 == st_fx->enablePlcWaveadjust || EQ_16(st_fx->plcInfo.concealment_method,TCX_TONAL)) + { + st_fx->plcInfo.recovery_gain = extract_h(L_shl(Mpy_32_16_1(conceal_eof_gainFB, + st_fx->last_concealed_gain_syn_deemph), + st_fx->last_concealed_gain_syn_deemph_e + ));/*Q30->Q14*/ + } + ELSE + { + st_fx->plcInfo.recovery_gain = extract_h(conceal_eof_gainFB); /*Q14*/ + } + st_fx->plcInfo.step_concealgain_fx = + round_fx(L_shl(L_mult0( + round_fx(step), + round_fx(L_shl(L_mult0(st_fx->L_frame_fx, getInvFrameLen(st_fx->L_frameTCX)),8))),3)); /*Q15*/ + } + + /*-----------------------------------------------------------* + * Memory update * + *-----------------------------------------------------------*/ + + /* Update synth, exc and old_Aq */ + tcx_decoder_memory_update(xn_buf, /*Q0*/ + synth, /*Q0*/ + st_fx->L_frame_fx, + A, + st_fx, + st_fx->syn, /*Q0*/ + 0 + ); + + + /* PLC: [TCX: Memory update] */ + + st_fx->old_pitch_buf_fx[0] = st_fx->old_pitch_buf_fx[st_fx->nb_subfr]; + move32(); + st_fx->old_pitch_buf_fx[1] = st_fx->old_pitch_buf_fx[st_fx->nb_subfr+1]; + move32(); + Copy32(&st_fx->old_pitch_buf_fx[st_fx->nb_subfr+2], &st_fx->old_pitch_buf_fx[2], st_fx->nb_subfr); + set32_fx(&st_fx->old_pitch_buf_fx[st_fx->nb_subfr+2], st_fx->old_fpitch, st_fx->nb_subfr); + st_fx->bfi_pitch_fx = shl(round_fx(st_fx->old_fpitch),6); + st_fx->bfi_pitch_frame_fx = st_fx->L_frame_fx; + move16(); + + st_fx->mem_pitch_gain[2*st_fx->nb_subfr+1] = st_fx->mem_pitch_gain[st_fx->nb_subfr+1]; + move16(); + st_fx->mem_pitch_gain[2*st_fx->nb_subfr] = st_fx->mem_pitch_gain[st_fx->nb_subfr]; + move16(); + + FOR (i = 0; i < st_fx->nb_subfr; i++) + { + st_fx->mem_pitch_gain[2*st_fx->nb_subfr-1 - i] = st_fx->mem_pitch_gain[st_fx->nb_subfr-1 - i]; + move16(); + st_fx->mem_pitch_gain[st_fx->nb_subfr-1 - i] = st_fx->tcxltp_last_gain_unmodified; + move16(); + } +} + + +static Word32 CalculateAbsEnergy( /* o : normalized result Q31 */ + const Word32 L_off, /* i : initial sum value Qn */ + const Word16 x[], /* i : x vector Qn */ + const Word16 lg, /* i : vector length, range [0..7FFF] Q0 */ + Word16 * exp /* o : exponent of result in [-32,31] Q0 */ +) +{ + Word16 i; + Word32 L_sum, L_c; + /* Clear carry flag and init sum */ + Carry = 0; + L_c = 0; + move32(); + L_sum = L_macNs(L_off,0,0); + if (L_sum > 0) + L_c = L_macNs(L_c,0,0); + if (L_sum < 0) + L_c = L_msuNs(L_c,0,0); + + FOR (i=0; i < lg; i+=2) + { + Carry = 0; + BASOP_SATURATE_WARNING_OFF /*multiplication of -32768 * -32768 throws an overflow, but is not critical*/ + L_sum = L_macNs(L_sum, x[i], x[i]); + BASOP_SATURATE_WARNING_ON + Overflow = 0; /* to avoid useless warning in L_macNs calling L_mult */ + L_c = L_macNs(L_c,0,0); + } + L_sum = norm_llQ31(L_c,L_sum,exp); + return L_sum; +} + + +static void IMDCT(Word32 *x, Word16 x_e, + Word16 *old_syn_overl, + Word16 *syn_Overl_TDAC, + Word16 *xn_buf, + const Word16 *tcx_aldo_window_1, + const PWord16 *tcx_aldo_window_1_trunc, + const PWord16 *tcx_aldo_window_2, + const PWord16 *tcx_mdct_window_half, + const PWord16 *tcx_mdct_window_minimum, + const PWord16 *tcx_mdct_window_trans, + Word16 tcx_mdct_window_half_length, + Word16 tcx_mdct_window_min_length, + Word16 index, + Word16 left_rect, + Word16 tcx_offset, + Word16 overlap, + Word16 L_frame, + Word16 L_frameTCX, + Word16 L_spec_TCX5, + Word16 L_frame_glob, + Word16 frame_cnt, + Word16 bfi, + Word16 *old_out, + Word16 *Q_old_wtda, + Decoder_State_fx *st, + Word16 fullbandScale, + Word16 *acelp_zir) +{ + const TCX_config *tcx_cfg = &st->tcx_cfg; + Word16 tmp_offset; + Word16 tmp1, tmp2, tmp3, *tmpP16; + Word32 tmp32; + Word8 tmp8; + Word16 i; + Word16 nz; + Word16 aldo=0; + + /* number of zero for ALDO windows*/ + tmp32 = L_add(st->sr_core, 0); + if (fullbandScale != 0) + { + tmp32 = L_add(st->output_Fs_fx, 0); + } + nz = NS2SA_fx2(tmp32, N_ZERO_MDCT_NS); + + tmp_offset = 0; + move16(); + if (tcx_offset < 0) + { + tmp_offset = negate(tcx_offset); + } + + test(); + IF ((EQ_16(L_frameTCX, shr(st->L_frameTCX, 1)))&&(st->tcxonly!=0)) + { + /* Mode decision in PLC + + last OL curr OL left TCX-10 right TCX-10 + ------------------------------------------------------------- + 0 0 2x TCX-5* 1x TCX-10 + 0 2 1x TCX-10 1x TCX-10 + 0 3 1x TCX-10 1x TCX-10 + 2 0 2x TCX-5 1x TCX-10 + 2 2 2x TCX-5 2x TCX-5 + 2 3 2x TCX-5 2x TCX-5 + 3 0 2x TCX-5 1x TCX-10 + 3 2 2x TCX-5 2x TCX-5 + 3 3 2x TCX-5 2x TCX-5 + */ + test(); + test(); + test(); + test(); + test(); + test(); + IF ((bfi == 0 && tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) || (bfi!=0 && (tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) && (tcx_cfg->tcx_curr_overlap_mode != FULL_OVERLAP))) + { + /* minimum or half overlap, two transforms, grouping into one window */ + Word16 win[(L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2]; + Word16 w; + Word16 L_win, L_ola; + + L_win = shr(L_frame, 1); + L_ola = tcx_mdct_window_half_length; + move16(); + if (EQ_16(tcx_cfg->tcx_last_overlap_mode, MIN_OVERLAP)) + { + L_ola = tcx_mdct_window_min_length; + move16(); + } + + set16_fx(xn_buf, 0, add(tcx_offset,shr(L_ola,1))); /* zero left end of buffer */ + set16_fx(win, 0, (L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2); + + FOR (w = 0; w < 2 ; w++) + { + + TCX_MDCT_Inverse(x+L_mult0(w,L_spec_TCX5), sub(x_e,TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM),win, L_ola, sub(L_win,L_ola), L_ola); + + tmp1 = left_rect; + move16(); + tmp2 = tcx_cfg->tcx_last_overlap_mode; + move16(); + tmp3 = st->last_core_bfi; + move16(); + tmp8 = st->last_is_cng; + move16(); + IF (w > 0) + { + tmp1 = 0; + move16(); + tmp2 = MIN_OVERLAP; + move16(); + tmp3 = 1; + move16(); + tmp8 = (Word8)0; + move16(); + } + test(); + if(w == 0 && EQ_16(index,2)) + { + tmp2 = MIN_OVERLAP; + move16(); + } + IF (frame_cnt>0) + { + tmp3 = 1; + move16(); + tmp8 = (Word8)0; + move16(); + } + + tcx_windowing_synthesis_current_frame(win, + tcx_aldo_window_2, + tcx_mdct_window_half, + tcx_mdct_window_minimum, + L_ola, + tcx_mdct_window_half_length, + tcx_mdct_window_min_length, + tmp1, + tmp2, + acelp_zir, + st->old_syn_Overl, + syn_Overl_TDAC, + st->old_Aq_12_8_fx, + tcx_mdct_window_trans, + L_win, + tmp_offset, + tmp3, + tmp8, + fullbandScale + ); + + IF (w > 0) + { + tcx_windowing_synthesis_past_frame(xn_buf+tcx_offset-shr(L_ola , 1)+ imult1616(w,L_win), + tcx_aldo_window_1_trunc, + tcx_mdct_window_half, + tcx_mdct_window_minimum, + L_ola, + tcx_mdct_window_half_length, + tcx_mdct_window_min_length, + MIN_OVERLAP + ); + } + /* add part of current sub-window overlapping with previous window */ + Vr_add(win, + xn_buf+tcx_offset-shr(L_ola,1)+w*L_win, /*instrumented only shr because in fact, its only L_win+L_win+L_win...*/ + xn_buf+tcx_offset-shr(L_ola,1)+w*L_win, + L_ola); + /* copy new sub-window region not overlapping with previous window */ + Copy( + win+L_ola, + xn_buf+tcx_offset+shr(L_ola,1)+w*L_win, + L_win); + } + + /* To assure that no garbage values are passed to overlap */ + set16_fx(xn_buf+L_frame+tcx_offset+shr(L_ola,1), 0, overlap-tcx_offset-shr(L_ola,1)); + } + ELSE IF ( bfi == 0 && (frame_cnt == 0) && (tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP)) + { + Word16 win[(L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2]; + Word16 L_win, L_ola, w; + + /* special overlap attempt, two transforms, grouping into one window */ + L_win = shr(L_frame, 1); + L_ola = tcx_mdct_window_min_length; + move16(); + + set16_fx(win, 0, (L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2); + + /* 1st TCX-5 window, special MDCT with minimum overlap on right side */ + + TCX_MDCT_Inverse(x, sub(x_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM), + win + L_win, + 0, sub(L_win, shr(L_ola, 1)), L_ola); + + set16_fx(xn_buf, 0, shr(overlap,1)); + /* copy new sub-window region not overlapping with previous window */ + Copy(win+L_win, xn_buf+shr(overlap,1), add(L_win,shr(L_ola,1)) ); + + /* 2nd TCX-5 window, regular MDCT with minimum overlap on both sides */ + TCX_MDCT_Inverse(x + L_spec_TCX5, sub(x_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM), + win, + L_ola, sub(L_win, L_ola), L_ola); + + tcx_windowing_synthesis_current_frame(win, + tcx_aldo_window_2, + tcx_mdct_window_half, + tcx_mdct_window_minimum, + L_ola, + tcx_mdct_window_half_length, + tcx_mdct_window_min_length, + 0, /* left_rect */ + MIN_OVERLAP, /* left_mode */ + acelp_zir, + st->old_syn_Overl, + syn_Overl_TDAC, + st->old_Aq_12_8_fx, + tcx_mdct_window_trans, + L_win, + tmp_offset, + 1, /* st->last_core_bfi */ + 0, /* st->last_is_cng */ + fullbandScale + ); + + tmpP16 = xn_buf + add(sub(L_win, shr(L_ola, 1)), shr(overlap,1)); + + tcx_windowing_synthesis_past_frame(tmpP16, + tcx_aldo_window_1_trunc, + tcx_mdct_window_half, + tcx_mdct_window_minimum, + L_ola, + tcx_mdct_window_half_length, + tcx_mdct_window_min_length, + MIN_OVERLAP + ); + + /* add part of current sub-window overlapping with previous window */ + FOR (i = 0; i < L_ola; i++) + { + tmpP16[i] = add(tmpP16[i], win[i]); + move16(); + } + + /* copy new sub-window region not overlapping with previous window */ + Copy(win + L_ola, + xn_buf + add(add(shr(overlap,1), shr(L_ola, 1)), L_win), + L_win); + + /* extra folding-out on left side of win, for perfect reconstruction */ + FOR (w = shr(overlap,1); w < overlap; w++) + { + xn_buf[overlap-1-w] = negate(xn_buf[w]); + move16(); + } + + tcx_windowing_synthesis_current_frame(xn_buf, + tcx_aldo_window_2, + tcx_mdct_window_half, + tcx_mdct_window_minimum, + overlap, + tcx_mdct_window_half_length, + tcx_mdct_window_min_length, + left_rect, + 0, /* left_mode */ + acelp_zir, + st->old_syn_Overl, + syn_Overl_TDAC, + st->old_Aq_12_8_fx, + tcx_mdct_window_trans, + shl(L_win,1), + tmp_offset, + st->last_core_bfi, + st->last_is_cng, + fullbandScale + ); + + } + ELSE /* default i.e. maximum overlap, single transform, no grouping */ + { + + TCX_MDCT_Inverse(x, sub(x_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM), + xn_buf, + overlap, sub(L_frame, overlap), overlap); + + tmp1 = index; + move16(); + test(); + test(); + test(); + if ( bfi==0 && (frame_cnt > 0) && (index == 0) && (st->last_core_fx != ACELP_CORE)) + { + tmp1 = MIN_OVERLAP; + move16(); + } + + tmp3 = st->last_core_bfi; + move16(); + if (frame_cnt > 0) + { + tmp3 = 1; + move16(); + } + + tmp8 = st->last_is_cng; + move16(); + if (frame_cnt > 0) + { + tmp8 = 0; + move16(); + } + + tcx_windowing_synthesis_current_frame(xn_buf, + tcx_aldo_window_2, + tcx_mdct_window_half, + tcx_mdct_window_minimum, + overlap, + tcx_mdct_window_half_length, + tcx_mdct_window_min_length, + left_rect, + tmp1, + acelp_zir, + st->old_syn_Overl, + syn_Overl_TDAC, + st->old_Aq_12_8_fx, + tcx_mdct_window_trans, + shr(L_frame_glob, 1), + tmp_offset, + tmp3, + tmp8, + fullbandScale + ); + } + } + ELSE /* frame is TCX-20 or not TCX-only */ + { + assert(frame_cnt == 0); + + IF (NE_16(st->tcx_cfg.tcx_last_overlap_mode, TRANSITION_OVERLAP)) + { + Word32 tmp_buf[L_FRAME_PLUS]; + Word16 Q; + + /* DCT */ + Q = sub(31, x_e); + edct_fx(x, tmp_buf, L_frame, &Q); + + /* scale by sqrt(L / NORM_MDCT_FACTOR) */ + tmp1 = mult_r(shl(L_frame, 4), 26214/*128.f / NORM_MDCT_FACTOR Q15*/); /* 4Q11 */ + tmp2 = 4; + move16(); + tmp1 = Sqrt16(tmp1, &tmp2); + + FOR (i = 0; i < L_frame; i++) + { + tmp_buf[i] = Mpy_32_16_1(tmp_buf[i], tmp1); + move32(); + } + Q = sub(Q, tmp2); + + + window_ola_fx(tmp_buf, + xn_buf, + &Q, + old_out, + Q_old_wtda, + L_frame, + tcx_cfg->tcx_last_overlap_mode, + tcx_cfg->tcx_curr_overlap_mode, + 0, + 0, + NULL); + + /* scale output */ + IF (Q <= 0) + { + FOR (i = 0; i < L_frame; i++) + { + xn_buf[i] = shr(xn_buf[i], Q); + move16(); + } + } + ELSE + { + tmp1 = shr(0x4000, sub(Q,1)); + + FOR (i = 0; i < L_frame; i++) + { + xn_buf[i] = mult_r(xn_buf[i], tmp1); + move16(); + } + } + + aldo = 1; + move16(); + } + ELSE + { + + TCX_MDCT_Inverse(x, sub(x_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM), + xn_buf, overlap, sub(L_frame, overlap), overlap); + + + /*-----------------------------------------------------------* + * Windowing, overlap and add * + *-----------------------------------------------------------*/ + + + /* Window current frame */ + tmp3 = st->last_core_bfi; + move16(); + + tmp8 = st->last_is_cng; + move16(); + tcx_windowing_synthesis_current_frame( xn_buf, + tcx_aldo_window_2, + tcx_mdct_window_half, + tcx_mdct_window_minimum, + overlap, + tcx_mdct_window_half_length, + tcx_mdct_window_min_length, + left_rect, + tcx_cfg->tcx_last_overlap_mode, + acelp_zir, + st->old_syn_Overl, + syn_Overl_TDAC, + st->old_Aq_12_8_fx, + tcx_mdct_window_trans, + shr(L_frame_glob, 1), + tmp_offset, + tmp3, + tmp8, + fullbandScale + ); + } /* TRANSITION_OVERLAP */ + } /* TCX-20 and TCX-only */ + + /* Window and overlap-add past frame if past frame is TCX */ + test(); + IF ((frame_cnt != 0) || (st->last_core_bfi > ACELP_CORE)) + { + test(); + test(); + IF (((EQ_16(L_frameTCX, shr(st->L_frameTCX, 1)))&&(st->tcxonly!=0))||(EQ_16(st->tcx_cfg.tcx_last_overlap_mode,TRANSITION_OVERLAP))) + { + test(); + test(); + test(); + test(); + if ((bfi == 0) && (frame_cnt > 0) && (index == 0) && + (tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP) && (st->last_core_fx != ACELP_CORE)) + { + index = MIN_OVERLAP; /* use minimum overlap between the two TCX-10 windows */ move16(); + } + + IF (tcx_cfg->last_aldo != 0) + { + Word16 tmp4; + + tmp2 = add(*Q_old_wtda, TCX_IMDCT_HEADROOM); + tmp4 = sub(shr(overlap, 1), tcx_offset); + + FOR (i = 0; i < tmp4; i++) + { + xn_buf[i] = shl(xn_buf[i], TCX_IMDCT_HEADROOM); + move16(); + } + + tmp1 = sub(overlap, tcx_mdct_window_min_length); + FOR (i=0; i < tmp1; i++) + { + xn_buf[i+tmp4] = shl(add(xn_buf[i+tmp4], shr(old_out[i+nz], tmp2)), TCX_IMDCT_HEADROOM); + move16(); + } + + /* fade truncated ALDO window */ + tmp1 = sub(overlap, shr(tcx_mdct_window_min_length, 1)); + FOR ( ; i < tmp1; i++) + { + tmp3 = mult_r(shr(old_out[i+nz], tmp2), tcx_mdct_window_minimum[i-overlap+tcx_mdct_window_min_length].v.re); + xn_buf[i+tmp4] = shl(add(xn_buf[i+tmp4], tmp3), TCX_IMDCT_HEADROOM); + move16(); + } + FOR ( ; i < overlap; i++) + { + tmp3 = mult_r(shr(old_out[i+nz], tmp2), tcx_mdct_window_minimum[overlap-1-i].v.im); + xn_buf[i+tmp4] = shl(add(xn_buf[i+tmp4], tmp3), TCX_IMDCT_HEADROOM); + move16(); + } + + FOR (i = add(i, tmp4) ; i < L_frame; i++) + { + xn_buf[i] = shl(xn_buf[i], TCX_IMDCT_HEADROOM); + move16(); + } + } + ELSE + { + tmp1 = index; + move16(); + test(); + if ((index == 0) || (EQ_16(tcx_cfg->tcx_last_overlap_mode, MIN_OVERLAP))) + { + tmp1 = tcx_cfg->tcx_last_overlap_mode; + move16(); + } + + tcx_windowing_synthesis_past_frame( old_syn_overl + , + tcx_aldo_window_1_trunc, + tcx_mdct_window_half, + tcx_mdct_window_minimum, + overlap, + tcx_mdct_window_half_length, + tcx_mdct_window_min_length, + tmp1 + ); + + BASOP_SATURATE_WARNING_OFF; + IF ( bfi ) + { + tmp1 = sub(shr(overlap, 1), tcx_offset); + tmp3 = shr(tcx_mdct_window_half_length, 1); + FOR (i=0; i < tmp1; i++) + { + xn_buf[i] = shl(xn_buf[i], TCX_IMDCT_HEADROOM); + move16(); + } + FOR (i = 0; i < tmp3; i++) + { + tmp2 = add(xn_buf[i+tmp1], mult_r(old_syn_overl[i], tcx_mdct_window_half[i].v.re)); + xn_buf[i+tmp1] = shl(tmp2, TCX_IMDCT_HEADROOM); + move16(); + } + FOR ( ; i < tcx_mdct_window_half_length; i++) + { + tmp2 = add(xn_buf[i+tmp1], mult_r(old_syn_overl[i], tcx_mdct_window_half[tcx_mdct_window_half_length-1-i].v.im)); + xn_buf[i+tmp1] = shl(tmp2, TCX_IMDCT_HEADROOM); + move16(); + } + IF (LT_16(add(i, tmp1), L_frame)) + { + FOR (i = add(i, tmp1); i < L_frame; i++) + { + xn_buf[i] = shl(xn_buf[i], TCX_IMDCT_HEADROOM); + move16(); + } + } + } + ELSE IF (left_rect == 0) + { + FOR (i=0; iL_frameTCX >> 1 && st->tcxonly) || + st->tcx_cfg.tcx_last_overlap_mode == TRANSITION_OVERLAP); + } + ELSE + { + IF (aldo == 0) + { + BASOP_SATURATE_WARNING_OFF; + FOR (i = 0; i < L_frame; i++) + { + xn_buf[i] = shl(xn_buf[i], TCX_IMDCT_HEADROOM); + move16(); + } + BASOP_SATURATE_WARNING_ON; + } + } + + test(); + test(); + test(); + IF ( (aldo == 0) && + ((EQ_16(L_frameTCX, shr(st->L_frameTCX, 1)) && frame_cnt > 0) || + NE_16(L_frameTCX, shr(st->L_frameTCX, 1)) ) ) + { + /*Compute windowed synthesis in case of switching to ALDO windows in next frame*/ + FOR (i = 0; i < nz; i++) + { + old_out[i] = shr(xn_buf[L_frame-nz+i], TCX_IMDCT_HEADROOM); + move16(); + } + Copy(xn_buf+L_frame, old_out+nz, overlap); + set16_fx(old_out+nz+overlap, 0, nz); + + tcx_windowing_synthesis_past_frame( old_out+nz, + tcx_aldo_window_1_trunc, + tcx_mdct_window_half, + tcx_mdct_window_minimum, + overlap, + tcx_mdct_window_half_length, + tcx_mdct_window_min_length, + tcx_cfg->tcx_curr_overlap_mode + ); + + /* If current overlap mode = FULL_OVERLAP -> ALDO_WINDOW */ + IF (EQ_16(tcx_cfg->tcx_curr_overlap_mode, FULL_OVERLAP)) + { + FOR (i=0; itcx_cfg.last_aldo = aldo; + move16(); + } + + /* Smoothing between the ACELP PLC and TCX Transition frame. Using the shape of the half overlap window for the crossfading. */ + test(); + test(); + test(); + IF (left_rect && (frame_cnt == 0) && (st->last_core_bfi == ACELP_CORE) + && st->prev_bfi_fx) + { + + IF (fullbandScale) + { + tmp1 = sub(shr(overlap, 1), tcx_offset); + tmp3 = shr(tcx_mdct_window_half_length, 1); + FOR (i = 0; i < tmp3; i++) + { + xn_buf[i+tmp1] = mult_r( xn_buf[i+tmp1], tcx_mdct_window_half[i].v.im ); + xn_buf[i+tmp1] = add( xn_buf[i+tmp1], mult_r( st->syn_OverlFB[i], mult_r( tcx_mdct_window_half[i].v.re, tcx_mdct_window_half[i].v.re ) ) ); + move16(); + } + FOR ( ; i < tcx_mdct_window_half_length; i++) + { + xn_buf[i+tmp1] = mult_r( xn_buf[i+tmp1], tcx_mdct_window_half[tcx_mdct_window_half_length-1-i].v.re ); + xn_buf[i+tmp1] = add( xn_buf[i+tmp1], mult_r( st->syn_OverlFB[i], mult_r( tcx_mdct_window_half[tcx_mdct_window_half_length-1-i].v.im, tcx_mdct_window_half[tcx_mdct_window_half_length-1-i].v.im ) ) ); + move16(); + } + } + ELSE + { + tmp1 = sub(shr(overlap, 1), tcx_offset); + tmp3 = shr(tcx_mdct_window_half_length, 1); + FOR (i = 0; i < tmp3; i++) + { + xn_buf[i+tmp1] = mult_r( xn_buf[i+tmp1], tcx_mdct_window_half[i].v.im ); + xn_buf[i+tmp1] = add( xn_buf[i+tmp1], mult_r( st->syn_Overl[i], mult_r( tcx_mdct_window_half[i].v.re, tcx_mdct_window_half[i].v.re ) ) ); + move16(); + } + FOR ( ; i < tcx_mdct_window_half_length; i++) + { + xn_buf[i+tmp1] = mult_r( xn_buf[i+tmp1], tcx_mdct_window_half[tcx_mdct_window_half_length-1-i].v.re ); + xn_buf[i+tmp1] = add( xn_buf[i+tmp1], mult_r( st->syn_Overl[i], mult_r( tcx_mdct_window_half[tcx_mdct_window_half_length-1-i].v.im, tcx_mdct_window_half[tcx_mdct_window_half_length-1-i].v.im ) ) ); + move16(); + } + } + } +} + diff --git a/lib_dec/dec_tran_fx.c b/lib_dec/dec_tran_fx.c new file mode 100644 index 0000000..c7f6c68 --- /dev/null +++ b/lib_dec/dec_tran_fx.c @@ -0,0 +1,230 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*======================================================================*/ +/* FUNCTION : decod_tran_fx() */ +/*----------------------------------------------------------------------*/ +/* PURPOSE : Decode transition (TC) frames */ +/* */ +/*----------------------------------------------------------------------*/ +/* GLOBAL INPUT ARGUMENTS : */ +/* _ (Struct) st_fx : decoder static memory */ +/* _ (Word16) L_frame_fx : length of the frame Q0 */ +/* _ (Word16[]) Aq_fx : LP filter coefficient Q12 */ +/* _ (Word16) coder_type_fx : coding type Q12 */ +/* _ (Word16) Es_pred_fx : predicted scaled innov. energy Q8 */ +/* _ (Word16[]) pitch_buf_fx : floating pitch values for each subframe Q6*/ +/* _ (Word16[]) voice_factors_fx: frame error rate Q15 */ +/*-----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Q_exc) */ +/* _ (Word16[]) exc2_fx : adapt. excitation/total exc (Q_exc) */ +/*-----------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*=======================================================================*/ + +void decod_tran_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + const Word16 L_frame_fx, /* i : length of the frame */ + const Word16 tc_subfr_fx, /* i : TC subframe index */ + const Word16 *Aq_fx, /* i : LP filter coefficient */ + const Word16 coder_type_fx, /* i : coding type */ + const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */ + Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe*/ + Word16 *voice_factors_fx, /* o : voicing factors */ + Word16 *exc_fx, /* i/o: adapt. excitation exc */ + Word16 *exc2_fx, /* i/o: adapt. excitation/total exc */ + Word16 *bwe_exc_fx, /* i/o: excitation for SWB TBE */ + Word16 *unbits, /* i/o: number of unused bits */ + const Word16 sharpFlag, /* i : formant sharpening flag */ + Word16 *gain_buf +) +{ + Word16 T0, T0_frac, T0_min, T0_max; /* integer pitch variables */ + Word32 gain_code_fx=0; /* Quantized algebraic codeebook gain */ + Word32 norm_gain_code_fx=0; /* normalized algebraic codeebook gain */ + Word16 gain_pit_fx = 0; /* Quantized pitch gain */ + Word16 voice_fac_fx; /* Voicing factor */ + Word16 gain_inov_fx=0; /* inovation gain */ + Word16 code_fx[L_SUBFR]; /* algebraic codevector */ + const Word16 *p_Aq_fx; /* pointer to lp filter coefficient */ + Word16 *pt_pitch_fx; /* pointer to floating pitch */ + Word16 i_subfr, i; /* tmp variables */ + Word16 position; /* TC related flag */ + Word16 gain_preQ_fx = 0; /* Gain of prequantizer excitation */ + Word16 code_preQ_fx[L_SUBFR]; /* Prequantizer excitation */ + Word16 Jopt_flag; /* flag indicating zero adaptive contribtuion */ + Word32 norm_gain_preQ_fx; + Word16 gain_code16; + Word32 L_tmp; + Word16 tmp16, tmp1_fx, tmp_fx; + gain_preQ_fx = 0; + move16(); + set16_fx( code_preQ_fx, 0, L_SUBFR ); + /*----------------------------------------------------------------* + * ACELP subframe loop + *----------------------------------------------------------------*/ + + p_Aq_fx = Aq_fx; + move16(); + pt_pitch_fx = pitch_buf_fx; + move16(); + Jopt_flag = 0; + move16(); + norm_gain_preQ_fx = 0; + move16(); + + FOR( i_subfr = 0; i_subfr < L_frame_fx; i_subfr += L_SUBFR ) + { + /*------------------------------------------------------------* + * TC : subframe determination & + * adaptive/glottal part of excitation construction + *------------------------------------------------------------*/ + + test(); + IF( i_subfr == 0 && GT_16(st_fx->Q_exc,2)) + { + tmp16 = sub(2, st_fx->Q_exc); + Scale_sig(exc_fx-L_EXC_MEM, L_EXC_MEM, tmp16); + Scale_sig(bwe_exc_fx-PIT16k_MAX*2, PIT16k_MAX*2, tmp16); + Scale_sig(st_fx->last_exc_dct_in_fx, L_FRAME, tmp16); + st_fx->Q_exc = add(st_fx->Q_exc,tmp16); + } + + transition_dec_fx( st_fx, st_fx->core_brate_fx, 0, L_frame_fx, i_subfr, coder_type_fx, tc_subfr_fx, &Jopt_flag, exc_fx, + &T0, &T0_frac, &T0_min, &T0_max, &pt_pitch_fx, &position, bwe_exc_fx, &st_fx->Q_exc ); + + /*-----------------------------------------------------------------* + * Transform domain contribution decoding - active frames + *-----------------------------------------------------------------*/ + + IF( GT_32(st_fx->core_brate_fx,ACELP_24k40)) + { + gain_code_fx = 0; + move16(); + transf_cdbk_dec_fx( st_fx, st_fx->core_brate_fx, coder_type_fx, 0, i_subfr, tc_subfr_fx, + Es_pred_fx, gain_code_fx, &st_fx->mem_preemp_preQ_fx, &gain_preQ_fx, &norm_gain_preQ_fx, code_preQ_fx, unbits); + } + + /*-----------------------------------------------------------------* + * ACELP codebook search + pitch sharpening + *-----------------------------------------------------------------*/ + + inov_decode_fx( st_fx, st_fx->core_brate_fx, 0, L_frame_fx, coder_type_fx, + sharpFlag, i_subfr, tc_subfr_fx, p_Aq_fx, st_fx->tilt_code_fx, *pt_pitch_fx, code_fx ); + + /*-----------------------------------------------------------------* + * De-quantize the gains + * Update tilt of code: 0.0 (unvoiced) to 0.5 (voiced) + *-----------------------------------------------------------------*/ + + IF( Jopt_flag == 0 ) + { + /* 2/3-bit decoding */ + gain_dec_tc_fx( st_fx, st_fx->core_brate_fx, code_fx, L_frame_fx, i_subfr, tc_subfr_fx, Es_pred_fx, &gain_pit_fx, &gain_code_fx, &gain_inov_fx, &norm_gain_code_fx ); + } + ELSE + { + /* 5-bit decoding */ + IF( GT_32(st_fx->core_brate_fx,ACELP_32k)) + { + gain_dec_SQ_fx( st_fx, st_fx->core_brate_fx, coder_type_fx, i_subfr, tc_subfr_fx, code_fx, Es_pred_fx, &gain_pit_fx, &gain_code_fx, &gain_inov_fx, &norm_gain_code_fx ); + } + ELSE + { + gain_dec_mless_fx( st_fx, st_fx->core_brate_fx, L_frame_fx, coder_type_fx, i_subfr, tc_subfr_fx , code_fx, + Es_pred_fx, &gain_pit_fx, &gain_code_fx, &gain_inov_fx, &norm_gain_code_fx ); + + } + } + + /* update LP filtered gains for the case of frame erasures */ + lp_gain_updt_fx( i_subfr, gain_pit_fx, L_add(norm_gain_code_fx,norm_gain_preQ_fx), &st_fx->lp_gainp_fx, &st_fx->lp_gainc_fx, L_frame_fx ); + + st_fx->tilt_code_fx = est_tilt_fx( exc_fx+i_subfr, gain_pit_fx, code_fx, gain_code_fx,&voice_fac_fx,st_fx->Q_exc); + + /*----------------------------------------------------------------------* + * Find the total excitation + *----------------------------------------------------------------------*/ + + IF ( EQ_16(L_frame_fx,L_FRAME)) /* Rescaling for 12.8k core */ + { + Rescale_exc( st_fx->dct_post_old_exc_fx, &exc_fx[i_subfr], &bwe_exc_fx[i_subfr * HIBND_ACB_L_FAC], st_fx->last_exc_dct_in_fx, + L_SUBFR, L_SUBFR * HIBND_ACB_L_FAC, gain_code_fx, &(st_fx->Q_exc), st_fx->Q_subfr, exc2_fx, i_subfr, coder_type_fx ); + } + ELSE /* Rescaling for 16k core */ + { + Rescale_exc( st_fx->dct_post_old_exc_fx, &exc_fx[i_subfr], &bwe_exc_fx[i_subfr * 2], st_fx->last_exc_dct_in_fx, + L_SUBFR, L_SUBFR * 2, gain_code_fx, &(st_fx->Q_exc), st_fx->Q_subfr, exc2_fx, i_subfr, coder_type_fx ); + } + + gain_code16 = round_fx(L_shl(gain_code_fx,st_fx->Q_exc)); /*Q_exc*/ + Acelp_dec_total_exc( exc_fx, exc2_fx, gain_code16, gain_pit_fx, i_subfr, code_fx ); + + /*-----------------------------------------------------------------* + * Add the ACELP pre-quantizer contribution + *-----------------------------------------------------------------*/ + + IF( GT_32(st_fx->core_brate_fx,ACELP_24k40)) + { + tmp1_fx = add(15-Q_AVQ_OUT_DEC-2,st_fx->Q_exc); + FOR( i = 0; i < L_SUBFR; i++ ) + { + L_tmp = L_mult(gain_preQ_fx, code_preQ_fx[i]); /* Q2 + Q10 -> Q13*/ + L_tmp = L_shl(L_tmp,tmp1_fx); /* Q16 + Q_exc */ + tmp_fx = round_fx(L_tmp); + + exc2_fx[i+i_subfr] = add(exc2_fx[i+i_subfr],tmp_fx); + move16(); + exc_fx[i+i_subfr] = add(exc_fx[i+i_subfr],tmp_fx); + move16(); + } + } + + /*-----------------------------------------------------------------* + * Prepare TBE excitation + *-----------------------------------------------------------------*/ + + prep_tbe_exc_fx( L_frame_fx, i_subfr, gain_pit_fx, gain_code_fx, code_fx, voice_fac_fx, + &voice_factors_fx[i_subfr/L_SUBFR], bwe_exc_fx, gain_preQ_fx, code_preQ_fx, + st_fx->Q_exc, T0, T0_frac, coder_type_fx, st_fx->core_brate_fx ); + + /*----------------------------------------------------------------* + * Excitation enhancements (update of total excitation signal) + *----------------------------------------------------------------*/ + + IF( GT_32(st_fx->core_brate_fx,ACELP_32k)) + { + Copy( exc_fx+i_subfr, exc2_fx+i_subfr, L_SUBFR ); + } + ELSE + { + enhancer_fx( st_fx->core_brate_fx, 0, coder_type_fx, i_subfr, L_frame_fx, voice_fac_fx, st_fx->stab_fac_fx, + norm_gain_code_fx, gain_inov_fx, &st_fx->gc_threshold_fx, code_fx, exc2_fx, gain_pit_fx, &(st_fx->dm_fx), st_fx->Q_exc ); + } + + p_Aq_fx += (M+1); + move16(); + pt_pitch_fx++; + st_fx->tilt_code_dec_fx[i_subfr/L_SUBFR] = st_fx->tilt_code_fx; + move16(); + gain_buf[i_subfr/L_SUBFR] = gain_pit_fx; + move16(); + } + + /* SC-VBR */ + st_fx->prev_gain_pit_dec_fx = gain_pit_fx; + move16(); /*Q14*/ + + return; +} diff --git a/lib_dec/dec_uv.c b/lib_dec/dec_uv.c new file mode 100644 index 0000000..2ab1995 --- /dev/null +++ b/lib_dec/dec_uv.c @@ -0,0 +1,89 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * decod_unvoiced() + * + * Decode unvoiced (UC) frames + *-------------------------------------------------------------------*/ + +void decod_unvoiced_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + const Word16 *Aq_fx, /* Q12 i : LP filter coefficient */ + const Word16 coder_type_fx, /* Q0 i : coding type */ + Word16 *tmp_noise_fx, /* Q0 o : long term temporary noise energy */ + Word16 *pitch_buf_fx, /* Q6 o : floating pitch values for each subframe*/ + Word16 *voice_factors_fx, /* Q15 o : voicing factors */ + Word16 *exc_fx, /* Q_X o : adapt. excitation exc */ + Word16 *exc2_fx, /* Q_X o : adapt. excitation/total exc */ + Word16 *bwe_exc_fx /* Q_X i/o: excitation for SWB TBE */ + ,Word16 *gain_buf +) +{ + Word16 gain_pit_fx = 0; /* Quantized pitch gain */ + Word32 gain_code_fx; /* Quantized algebraic codeebook gain */ + Word16 gain_inov_fx; /* inovation gain */ + Word32 norm_gain_code_fx; /* normalized algebraic codeebook gain */ + Word16 voice_fac_fx; /* Voicing factor */ + Word16 code_fx[L_SUBFR]; /* algebraic codevector */ + Word16 i_subfr_fx; + const Word16 *p_Aq_fx; + Word16 *pt_pitch_fx; + + test(); + IF ( EQ_16(st_fx->last_ppp_mode_dec_fx,1)||EQ_16(st_fx->last_nelp_mode_dec_fx,1)) + { + /* SC_VBR - reset the decoder, to avoid memory not updated issue for this unrealistic case */ + CNG_reset_dec_fx( st_fx, pitch_buf_fx, voice_factors_fx ); + } + + p_Aq_fx = Aq_fx; + move16(); /*Q12*/ /* pointer to interpolated LPC parameters */ + pt_pitch_fx = pitch_buf_fx; + move16(); /* pointer to the pitch buffer */ + + FOR( i_subfr_fx=0; i_subfr_fxcore_brate_fx, i_subfr_fx, code_fx, &norm_gain_code_fx, + &st_fx->lp_gainp_fx, &st_fx->lp_gainc_fx, &gain_inov_fx, &st_fx->tilt_code_fx, + &voice_fac_fx, &gain_pit_fx, pt_pitch_fx, exc_fx, &gain_code_fx, exc2_fx, bwe_exc_fx,&(st_fx->Q_exc),st_fx->Q_subfr ); + + *tmp_noise_fx = extract_h(norm_gain_code_fx); /*Q16*/ + + /*----------------------------------------------------------------* + * Excitation enhancements (update of total excitation signal) + *----------------------------------------------------------------*/ + + enhancer_fx( st_fx->core_brate_fx, 0, coder_type_fx, i_subfr_fx, L_FRAME, voice_fac_fx, st_fx->stab_fac_fx, + norm_gain_code_fx, gain_inov_fx, &st_fx->gc_threshold_fx, code_fx, exc2_fx, gain_pit_fx, &(st_fx->dm_fx), st_fx->Q_exc ); + + voice_factors_fx[i_subfr_fx/L_SUBFR] = 0; + move16(); + + interp_code_5over2_fx( &exc_fx[i_subfr_fx], &bwe_exc_fx[i_subfr_fx * HIBND_ACB_L_FAC], L_SUBFR ); + + p_Aq_fx += (M+1); + move16(); + pt_pitch_fx++; + st_fx->tilt_code_dec_fx[i_subfr_fx/L_SUBFR] = st_fx->tilt_code_fx; + move16(); + } + + /* SC-VBR */ + st_fx->prev_gain_pit_dec_fx = gain_pit_fx; + move16(); + + set16_fx( gain_buf, 0, NB_SUBFR ); + + return; +} diff --git a/lib_dec/decision_matrix_dec_fx.c b/lib_dec/decision_matrix_dec_fx.c new file mode 100644 index 0000000..916ec42 --- /dev/null +++ b/lib_dec/decision_matrix_dec_fx.c @@ -0,0 +1,709 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" +#include "prot_fx.h" +#include "stat_dec_fx.h" +#include "rom_com_fx.h" +#include "stl.h" + + +/*-----------------------------------------------------------------* + * decision_matrix_dec() + * + * ACELP/HQ core selection + * Read ACELP signalling bits from the bitstream + * Set extension layers + *-----------------------------------------------------------------*/ + +void decision_matrix_dec_fx( + Decoder_State_fx *st, /* i/o: decoder state structure */ + Word16 *coder_type, /* o : coder type */ + Word16 *sharpFlag, /* o : formant sharpening flag */ + Word16 *hq_core_type, /* o : HQ core type */ + Word16 *core_switching_flag/* o : ACELP->HQ switching frame flag */ +) +{ + Word16 start_idx; + Word16 ppp_nelp_mode; + Word32 ind; + Word16 nBits; + Word16 tmp16, temp_core; + + st->core_fx = -1; + move16(); + st->core_brate_fx = L_deposit_l(0); + st->extl_fx = -1; + move16(); + st->extl_brate_fx = 0; + move16(); + st->ppp_mode_dec_fx = 0; + move16(); + st->nelp_mode_dec_fx = 0; + move16(); + st->igf = 0; + move16(); + + if( GT_32(st->total_brate_fx,ACELP_8k00)) + { + st->vbr_hw_BWE_disable_dec_fx = 0; + move16(); + } + + IF (EQ_16(st->mdct_sw, MODE2)) + { + st->core_fx = HQ_CORE; + move16(); + } + ELSE + { + test(); + IF( EQ_32(st->total_brate_fx,FRAME_NO_DATA)||EQ_32(st->total_brate_fx,SID_2k40)) + { + st->core_fx = ACELP_CORE; + move16(); + st->core_brate_fx = st->total_brate_fx; + move32(); + + IF( NE_32(st->total_brate_fx,FRAME_NO_DATA)) + { + st->cng_type_fx = get_next_indice_fx( st, 1 ); + + IF( EQ_16(st->cng_type_fx,LP_CNG)) + { + st->L_frame_fx = L_FRAME; + move16(); + + tmp16 = get_next_indice_fx( st, 1 ); + if( EQ_16(tmp16,1)) + { + st->L_frame_fx = L_FRAME16k; + move16(); + } + } + ELSE + { + st->bwidth_fx = get_next_indice_fx(st, 2); + + tmp16 = get_next_indice_fx(st, 1); + move16(); + + st->L_frame_fx = L_FRAME16k; + move16(); + if( tmp16 == 0 ) + { + st->L_frame_fx = L_FRAME; + move16(); + } + } + } + + test(); + if( GE_32(st->output_Fs_fx,32000)&&GE_16(st->bwidth_fx,SWB)) + { + st->extl_fx = SWB_CNG; + move16(); + } + + test(); + test(); + test(); + if( EQ_32(st->total_brate_fx,FRAME_NO_DATA)&&st->prev_bfi_fx&&!st->bfi_fx&>_16(st->L_frame_fx,L_FRAME16k)) + { + st->L_frame_fx = st->last_CNG_L_frame_fx; + move16(); + } + + return; + } + + /* SC-VBR */ + ELSE IF( EQ_32(st->total_brate_fx,PPP_NELP_2k80)) + { + st->core_fx = ACELP_CORE; + move16(); + st->core_brate_fx = PPP_NELP_2k80; + move32(); + st->L_frame_fx = L_FRAME; + move16(); + st->fscale = sr2fscale(INT_FS_FX); + move16(); + + IF ( st->ini_frame_fx == 0 ) + { + /* avoid switching of internal ACELP Fs in the very first frame */ + st->last_L_frame_fx = st->L_frame_fx; + st->last_core_fx = st->core_fx; + st->last_core_brate_fx = st->core_brate_fx; + st->last_extl_fx = st->extl_fx; + } + + st->vbr_hw_BWE_disable_dec_fx = 1; + move16(); + get_next_indice_fx( st, 1 ); + + ppp_nelp_mode = get_next_indice_fx( st, 2 ); + + /* 0 - PPP_NB, 1 - PPP_WB, 2 - NELP_NB, 3 - NELP_WB */ + IF( ppp_nelp_mode == 0 ) + { + st->ppp_mode_dec_fx = 1; + move16(); + *coder_type = VOICED; + move16(); + st->bwidth_fx = NB; + move16(); + } + ELSE IF( EQ_16(ppp_nelp_mode,1)) + { + st->ppp_mode_dec_fx = 1; + move16(); + *coder_type = VOICED; + move16(); + st->bwidth_fx = WB; + move16(); + } + ELSE IF( EQ_16(ppp_nelp_mode,2)) + { + st->nelp_mode_dec_fx = 1; + move16(); + *coder_type = UNVOICED; + move16(); + st->bwidth_fx = NB; + move16(); + } + ELSE IF( EQ_16(ppp_nelp_mode,3)) + { + st->nelp_mode_dec_fx = 1; + move16(); + *coder_type = UNVOICED; + move16(); + st->bwidth_fx = WB; + move16(); + } + + + return; + } + + /*---------------------------------------------------------------------* + * ACELP/HQ core selection + *---------------------------------------------------------------------*/ + + test(); + IF( LT_32(st->total_brate_fx,ACELP_24k40)) + { + st->core_fx = ACELP_CORE; + move16(); + } + ELSE IF( GE_32(st->total_brate_fx,ACELP_24k40)&&LE_32(st->total_brate_fx,ACELP_64k)) + { + /* read the ACELP/HQ core selection bit */ + temp_core = get_next_indice_fx( st, 1 ); + + st->core_fx = HQ_CORE; + move16(); + if( temp_core == 0 ) + { + st->core_fx = ACELP_CORE; + move16(); + } + } + } + + /*-----------------------------------------------------------------* + * Read ACELP signalling bits from the bitstream + *-----------------------------------------------------------------*/ + + IF( EQ_16(st->core_fx,ACELP_CORE)) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + start_idx = 0; + move16(); + WHILE( NE_32(acelp_sig_tbl[start_idx],st->total_brate_fx)) + { + start_idx = add(start_idx,1); + IF( GE_16(start_idx,MAX_ACELP_SIG)) + { + st->BER_detect = 1; + move16(); + start_idx = 0; + move16(); + break; + } + } + + /* skip the bitrate */ + start_idx = add(start_idx,1); + + /* retrieve the number of bits */ + nBits = extract_l(acelp_sig_tbl[start_idx]); + start_idx = add(start_idx,1); + + start_idx = add(start_idx,get_next_indice_fx( st, nBits )); + IF( start_idx >= MAX_ACELP_SIG ) + { + ind = 0; + move16(); + st->BER_detect = 1; + move16(); + } + ELSE + { + /* retrieve the signalling indice */ + ind = acelp_sig_tbl[start_idx]; + + /* convert signalling indice into signalling information */ + *coder_type = extract_l(L_and(ind,0x7L)); + + IF( EQ_16(*coder_type,LR_MDCT)) + { + st->core_fx = HQ_CORE; + move16(); + st->bwidth_fx = extract_l(L_shr(ind,3) & 0x7L); + } + ELSE + { + st->bwidth_fx = extract_l(L_and(L_shr(ind,3),0x7L)); + *sharpFlag = extract_l(L_and(L_shr(ind,6),0x1L)); + + } + } + + /* detect corrupted signalling (due to bit errors) */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( st->BER_detect ) || + ( GE_32(ind,1<<7) ) || + ( LE_32(st->total_brate_fx,ACELP_13k20) && EQ_16(st->bwidth_fx,FB) ) || + ( GE_32(st->total_brate_fx,ACELP_32k) && EQ_16(st->bwidth_fx,NB) ) || + ( GE_32(st->total_brate_fx,ACELP_32k) && !(EQ_16(*coder_type,GENERIC) || EQ_16(*coder_type,TRANSITION) || EQ_16(*coder_type,INACTIVE) ) ) || + ( LT_32(st->total_brate_fx,ACELP_13k20) && NE_16(st->bwidth_fx,NB) && EQ_16(*coder_type,LR_MDCT) ) || + ( GE_32(st->total_brate_fx,ACELP_13k20) && EQ_16(*coder_type,UNVOICED) ) || + ( GE_32(st->total_brate_fx,ACELP_13k20) && EQ_16(*coder_type,AUDIO) && EQ_16(st->bwidth_fx,NB) ) + ) + { + st->BER_detect = 0; + move16(); + st->bfi_fx = 1; + move16(); + + IF( st->ini_frame_fx == 0 ) + { + st->core_fx = ACELP_CORE; + move16(); + st->L_frame_fx = L_FRAME; + move16(); + st->last_core_fx = st->core_fx; + move16(); + st->last_core_brate_fx = st->core_brate_fx; + move32(); + } + ELSE IF( EQ_32(st->last_total_brate_fx, -1)) /* can happen in case of BER when no good frame was received before */ + { + *coder_type = st->last_coder_type_fx; + move16(); + st->bwidth_fx = st->last_bwidth_fx; + move16(); + st->total_brate_fx = st->last_total_brate_ber_fx; + move32(); + test(); + IF( EQ_16(st->last_core_fx, AMR_WB_CORE)) + { + st->core_fx = ACELP_CORE; + move16(); + st->codec_mode = MODE1; + move16(); + } + ELSE IF( EQ_16(st->last_core_bfi, TCX_20_CORE)||EQ_16(st->last_core_bfi,TCX_10_CORE)) + { + st->core_fx = st->last_core_bfi; + move16(); + st->codec_mode = MODE2; + move16(); + } + ELSE + { + st->core_fx = st->last_core_fx; + move16(); + st->codec_mode = MODE1; + move16(); + } + st->core_brate_fx = st->last_core_brate_fx; + move32(); + st->extl_fx = st->last_extl_fx; + move16(); + st->extl_brate_fx = L_sub(st->total_brate_fx, st->core_brate_fx); + move32(); + } + ELSE + { + *coder_type = st->last_coder_type_fx; + move16(); + st->bwidth_fx = st->last_bwidth_fx; + move16(); + st->total_brate_fx = st->last_total_brate_fx; + move16(); + + test(); + IF( EQ_16(st->last_core_fx,AMR_WB_CORE)) + { + st->core_fx = ACELP_CORE; + move16(); + st->codec_mode = MODE1; + move16(); + } + ELSE IF( EQ_16(st->last_core_fx,TCX_20_CORE)||EQ_16(st->last_core_fx,TCX_10_CORE)) + { + st->core_fx = st->last_core_fx; + move16(); + st->codec_mode = MODE2; + move16(); + } + ELSE + { + st->core_fx = st->last_core_fx; + move16(); + st->codec_mode = MODE1; + move16(); + } + st->core_brate_fx = st->last_core_brate_fx; + move32(); + st->extl_fx = st->last_extl_fx; + move16(); + st->extl_brate_fx = L_sub(st->total_brate_fx,st->core_brate_fx); + } + + return; + } + } + + /*-----------------------------------------------------------------* + * Set extension layers + *-----------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_16(st->core_fx,ACELP_CORE)&&EQ_16(st->bwidth_fx,WB)&<_32(st->total_brate_fx,ACELP_9k60)) + { + if( st->vbr_hw_BWE_disable_dec_fx == 0 ) + { + st->extl_fx = WB_BWE; + move16(); + } + } + ELSE IF( EQ_16(st->core_fx,ACELP_CORE)&&EQ_16(st->bwidth_fx,WB)&&GE_32(st->total_brate_fx,ACELP_9k60)&&LE_32(st->total_brate_fx,ACELP_16k40)) + { + /* read the WB TBE/BWE selection bit */ + tmp16 = get_next_indice_fx( st, 1 ); + IF( EQ_16(tmp16,1)) + { + st->extl_fx = WB_BWE; + move16(); + st->extl_brate_fx = WB_BWE_0k35; + move32(); + } + ELSE + { + st->extl_fx = WB_TBE; + move16(); + st->extl_brate_fx = WB_TBE_1k05; + move32(); + } + } + ELSE IF( EQ_16(st->core_fx,ACELP_CORE)&&(EQ_16(st->bwidth_fx,SWB)||EQ_16(st->bwidth_fx,FB))&&GE_32(st->total_brate_fx,ACELP_13k20)) + { + IF( GE_32(st->total_brate_fx,ACELP_48k)) + { + st->extl_fx = SWB_BWE_HIGHRATE; + move16(); + if( EQ_16(st->bwidth_fx,FB)) + { + st->extl_fx = FB_BWE_HIGHRATE; + move16(); + } + + st->extl_brate_fx = SWB_BWE_16k; + move32(); + } + + /* read the SWB TBE/BWE selection bit */ + ELSE + { + tmp16 = get_next_indice_fx( st, 1 ); + IF( tmp16 ) + { + st->extl_fx = SWB_BWE; + move16(); + st->extl_brate_fx = SWB_BWE_1k6; + move32(); + } + ELSE + { + st->extl_fx = SWB_TBE; + move16(); + st->extl_brate_fx = SWB_TBE_1k6; + move32(); + if( GE_32(st->total_brate_fx,ACELP_24k40)) + { + st->extl_brate_fx = SWB_TBE_2k8; + move32(); + } + } + } + + /* set FB TBE and FB BWE extension layers */ + test(); + IF( EQ_16(st->bwidth_fx,FB)&&GE_32(st->total_brate_fx,ACELP_24k40)) + { + IF( EQ_16(st->extl_fx,SWB_BWE)) + { + st->extl_fx = FB_BWE; + move16(); + st->extl_brate_fx = FB_BWE_1k8; + move32(); + } + ELSE IF( EQ_16(st->extl_fx,SWB_TBE)) + { + st->extl_fx = FB_TBE; + move16(); + { + st->extl_brate_fx = FB_TBE_3k0; + move32(); + } + } + } + } + + /* set core bitrate */ + st->core_brate_fx = L_sub(st->total_brate_fx,st->extl_brate_fx); + + /*-----------------------------------------------------------------* + * Read HQ signalling bits from the bitstream + * Set HQ core type + *-----------------------------------------------------------------*/ + + + IF( EQ_16(st->core_fx,HQ_CORE)) + { + IF( NE_16(st->mdct_sw, MODE2)) + { + /* skip the HQ/TCX core switching flag */ + get_next_indice_tmp_fx( st, 1 ); + } + + /* read ACELP->HQ core switching flag */ + *core_switching_flag = get_next_indice_fx( st, 1 ); + + IF( EQ_16(*core_switching_flag,1)) + { + st->last_L_frame_ori_fx = st->last_L_frame_fx; + move16(); + + /* read ACELP L_frame info */ + st->last_L_frame_fx = L_FRAME16k; + move16(); + tmp16 = get_next_indice_fx( st, 1 ); + if( tmp16 == 0 ) + { + st->last_L_frame_fx = L_FRAME; + move16(); + } + } + + IF( NE_16(st->mdct_sw, MODE2)) + { + + /* read/set band-width (needed for different I/O sampling rate support) */ + IF( GT_32(st->total_brate_fx,ACELP_16k40)) + { + tmp16 = get_next_indice_fx( st, 2 ); + + IF( tmp16 == 0 ) + { + st->bwidth_fx = NB; + move16(); + } + ELSE IF( EQ_16(tmp16,1)) + { + st->bwidth_fx = WB; + move16(); + } + ELSE IF( EQ_16(tmp16,2)) + { + st->bwidth_fx = SWB; + move16(); + } + ELSE + { + st->bwidth_fx = FB; + move16(); + } + } + } + + /* detect bit errors in signalling */ + test(); + test(); + test(); + test(); + IF( ( GE_32(st->total_brate_fx,ACELP_24k40)&&EQ_16(st->bwidth_fx,NB))|| + ( EQ_16(st->core_fx,HQ_CORE) && LE_32(st->total_brate_fx,LRMDCT_CROSSOVER_POINT) && EQ_16(st->bwidth_fx,FB) ) + ) + { + st->bfi_fx = 1; + move16(); + + st->core_brate_fx = st->total_brate_fx; + move32(); + st->extl_fx = -1; + move16(); + st->extl_brate_fx = 0; + move32(); + IF( EQ_16(st->last_core_fx,AMR_WB_CORE)) + { + st->core_fx = ACELP_CORE; + move16(); + st->L_frame_fx = L_FRAME; + move16(); + st->codec_mode = MODE1; + move16(); + st->last_L_frame_fx = L_FRAME; + move16(); + + IF( GE_32(st->total_brate_fx,ACELP_16k40)) + { + st->total_brate_fx = ACELP_13k20; + move32(); + st->core_brate_fx = st->total_brate_fx; + move32(); + } + } + ELSE + { + /* make sure, we are in a valid configuration wrt to bandwidth */ + st->bwidth_fx = WB; + move16(); + } + } + + /* set HQ core type */ + *hq_core_type = NORMAL_HQ_CORE; + move16(); + + test(); + test(); + IF( (EQ_16(st->bwidth_fx,SWB)||EQ_16(st->bwidth_fx,WB))&&LE_32(st->total_brate_fx,LRMDCT_CROSSOVER_POINT)) + { + *hq_core_type = LOW_RATE_HQ_CORE; + move16(); + } + ELSE IF( EQ_16(st->bwidth_fx,NB)) + { + *hq_core_type = LOW_RATE_HQ_CORE; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Set ACELP frame lnegth + *-----------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_32(st->core_brate_fx,FRAME_NO_DATA)) + { + /* prevent "L_frame" changes in CNG segments */ + st->L_frame_fx = st->last_L_frame_fx; + move16(); + } + ELSE IF( EQ_32(st->core_brate_fx,SID_2k40)&&EQ_16(st->bwidth_fx,WB)&&st->first_CNG_fx&<_16(st->act_cnt2_fx,MIN_ACT_CNG_UPD)) + { + /* prevent "L_frame" changes in SID frame after short segment of active frames */ + st->L_frame_fx = st->last_CNG_L_frame_fx; + move16(); + } + ELSE IF( ( EQ_32(st->core_brate_fx,SID_2k40)&&GE_32(st->total_brate_fx,ACELP_9k60)&&EQ_16(st->bwidth_fx,WB))|| + ( GT_32(st->total_brate_fx,ACELP_24k40) && LT_32(st->total_brate_fx,HQ_96k) ) || ( EQ_32(st->total_brate_fx,ACELP_24k40) && GE_16(st->bwidth_fx,WB) ) ) + { + st->L_frame_fx = L_FRAME16k; + move16(); + } + ELSE + { + st->L_frame_fx = L_FRAME; + move16(); + } + + st->nb_subfr = NB_SUBFR; + move16(); + if ( EQ_16(st->L_frame_fx,L_FRAME16k)) + { + st->nb_subfr = NB_SUBFR16k; + move16(); + } + + test(); + IF( EQ_32(st->output_Fs_fx,8000)) + { + st->extl_fx = -1; + move16(); + } + ELSE IF( EQ_32(st->output_Fs_fx,16000)&&EQ_16(st->L_frame_fx,L_FRAME16k)) + { + st->extl_fx = -1; + move16(); + st->extl_brate_fx = L_deposit_l(0); + } + + IF( st->ini_frame_fx == 0 ) + { + /* avoid switching of internal ACELP Fs in the very first frame */ + st->last_L_frame_fx = st->L_frame_fx; + move16(); + st->last_core_fx = st->core_fx; + move16(); + st->last_core_brate_fx = st->core_brate_fx; + move32(); + st->last_extl_fx = st->extl_fx; + move16(); + } + + return; +} diff --git a/lib_dec/decoder.c b/lib_dec/decoder.c new file mode 100644 index 0000000..46949df --- /dev/null +++ b/lib_dec/decoder.c @@ -0,0 +1,258 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include +#include +#include "options.h" +#include "stl.h" +#include "stat_dec_fx.h" +#include "prot_fx.h" +#include "g192.h" +#include "disclaimer.h" + +#include "EvsRXlib.h" + +/*------------------------------------------------------------------------------------------* + * Global variables + *------------------------------------------------------------------------------------------*/ +long frame = 0; /* Counter of frames */ + + +int main(int argc, char *argv[]) +{ + Decoder_State_fx *st_fx; /* decoder state structure */ + Word16 zero_pad, dec_delay,output_frame; + FILE *f_stream; /* input bitstream file */ + FILE *f_synth; /* output synthesis file */ + UWord16 bit_stream[MAX_BITS_PER_FRAME+16]; + Word16 output[L_FRAME48k]; /* buffer for output synthesis */ +#ifdef SUPPORT_JBM_TRACEFILE + char *jbmTraceFileName = NULL; /* VOIP tracefile name */ +#endif + Word16 quietMode = 0; + Word16 noDelayCmp = 0; + char *jbmFECoffsetFileName = NULL; /* FEC offset file name */ + + + BASOP_init + + + + + /*------------------------------------------------------------------------------------------* + * Allocation of memory for static variables + * - I/O initializations + * - Decoder variables initialization + * - Find frame length + *------------------------------------------------------------------------------------------*/ + + if ( (st_fx = (Decoder_State_fx *) calloc(1, sizeof(Decoder_State_fx) ) ) == NULL ) + { + } + + /*------------------------------------------------------------------------------------------* + * I/O initializations + * Decoder variables initialization + *------------------------------------------------------------------------------------------*/ + + st_fx->bit_stream_fx = bit_stream; + + io_ini_dec_fx( argc, argv, &f_stream, &f_synth, + &quietMode, + &noDelayCmp, + st_fx, +#ifdef SUPPORT_JBM_TRACEFILE + &jbmTraceFileName, +#endif + &jbmFECoffsetFileName + ); + + /*output_frame = (short)(st_fx->output_Fs / 50);*/ + st_fx->output_frame_fx = extract_l(Mult_32_16(st_fx->output_Fs_fx , 0x0290)); + + srand((unsigned int)time(0)); + + reset_indices_dec_fx(st_fx); + + IF(st_fx->Opt_VOIP_fx) + { +#ifdef SUPPORT_JBM_TRACEFILE + IF( decodeVoip(st_fx, f_stream, f_synth, jbmTraceFileName, jbmFECoffsetFileName, quietMode ) != 0 ) +#else + IF( decodeVoip(st_fx, f_stream, f_synth, jbmFECoffsetFileName, quietMode ) != 0 ) +#endif + { + free( st_fx ); + fclose( f_synth ); + fclose( f_stream ); + return -1; + } + } + ELSE + { + /*------------------------------------------------------------------------------------------* + * Regular EVS decoder with ITU-T G.192 bitstream + *------------------------------------------------------------------------------------------*/ + + init_decoder_fx(st_fx); + + /* output frame length */ + output_frame = st_fx->output_frame_fx; + + if( noDelayCmp == 0) + { + /* calculate the compensation (decoded signal aligned with original signal) */ + /* the number of first output samples will be reduced by this amount */ + dec_delay = NS2SA_fx2(st_fx->output_Fs_fx, get_delay_fx(DEC, st_fx->output_Fs_fx)); + } + else + { + dec_delay = 0; + } + + zero_pad = dec_delay; + + /*------------------------------------------------------------------------------------------* + * Loop for every packet (frame) of bitstream data + * - Read the bitstream packet + * - Run the decoder + * - Write the synthesized signal into output file + *------------------------------------------------------------------------------------------*/ + if (quietMode == 0) + { + fprintf( stdout, "\n------ Running the decoder ------\n\n" ); + fprintf( stdout, "Frames processed: " ); + } + else { + fprintf( stdout, "\n-- Start the decoder (quiet mode) --\n\n" ); + } + BASOP_end_noprint; + BASOP_init; +#if (WMOPS) + Init_WMOPS_counter(); + Reset_WMOPS_counter(); + setFrameRate(48000, 960); +#endif + + /*----- loop: decode-a-frame -----*/ + WHILE( st_fx->bitstreamformat==G192 ? read_indices_fx( st_fx, f_stream, 0 ) : read_indices_mime( st_fx, f_stream, 0) ) + { +#if (WMOPS) + fwc(); + Reset_WMOPS_counter(); +#endif + + + SUB_WMOPS_INIT("evs_dec"); + + /* run the main encoding routine */ + IF(EQ_16(st_fx->codec_mode, MODE1)) + { + IF ( st_fx->Opt_AMR_WB_fx ) + { + amr_wb_dec_fx( output,st_fx); + } + ELSE + { + evs_dec_fx( st_fx, output, FRAMEMODE_NORMAL); + } + } + ELSE + { + IF(st_fx->bfi_fx == 0) + { + evs_dec_fx( st_fx, output, FRAMEMODE_NORMAL); + } + ELSE /* conceal */ + { + evs_dec_fx( st_fx, output, FRAMEMODE_MISSING); + } + } + + END_SUB_WMOPS; + + + + /* increase the counter of initialization frames */ + + if( LT_16(st_fx->ini_frame_fx,MAX_FRAME_COUNTER)) + { + st_fx->ini_frame_fx = add(st_fx->ini_frame_fx,1); + } + + /* write the synthesized signal into output file */ + /* do final delay compensation */ + IF ( dec_delay == 0 ) + { + fwrite( output, sizeof(Word16), output_frame, f_synth ); + } + ELSE + { + IF ( LE_16(dec_delay , output_frame)) + { + fwrite( output +dec_delay, sizeof(Word16), sub(output_frame , dec_delay), f_synth ); + dec_delay = 0; + move16(); + } + ELSE + { + dec_delay = sub(dec_delay, output_frame); + } + } + + + frame++; + if (quietMode == 0) + { + fprintf( stdout, "%-8ld\b\b\b\b\b\b\b\b", frame); + } + } + + /*----- decode-a-frame-loop end -----*/ + + fflush( stderr ); + if (quietMode == 0) + { + fprintf( stdout, "\n\n" ); + printf("Decoding finished\n\n"); + } + else + { + printf("Decoding of %ld frames finished\n\n", frame); + } + fprintf( stdout, "\n\n" ); + fflush(stdout); + + + + fflush(stdout); + fflush(stderr); + + /* end of WMOPS counting */ +#if (WMOPS) + fwc(); + printf("\nDecoder complexity\n"); + WMOPS_output(0); + printf("\n"); +#endif + + /* add zeros at the end to have equal length of synthesized signals */ + set16_fx( output, 0, zero_pad ); + fwrite( output, sizeof(Word16), zero_pad, f_synth ); + BASOP_init + destroy_decoder( st_fx ); + BASOP_end_noprint + } + + /* free memory etc. */ + free( st_fx ); + fclose( f_synth ); + fclose( f_stream ); + + + return 0; +} diff --git a/lib_dec/dlpc_avq.c b/lib_dec/dlpc_avq.c new file mode 100644 index 0000000..a836f4e --- /dev/null +++ b/lib_dec/dlpc_avq.c @@ -0,0 +1,274 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +/* Header files */ +#include +#include +#include +#include "stl.h" +#include "prot_fx.h" +/* Constants */ + +#define M 16 /* length of LPC */ + +#define BFI_FAC 29491/*0.9f Q15*/ + +/***********************************************/ +/* Variable bit-rate multiple LPC un-quantizer */ +/***********************************************/ + +Word16 dlpc_avq( + Word16 *index, /* (i) Quantization indices */ + Word16 *LSF_Q, /* (o) Quantized LSF vectors */ + Word16 numlpc, /* (i) Number of sets of lpc */ + Word32 sr_core +) +{ + Word16 i, nbi, last; + Word16 *p_index, q_type; + + + /* Last LPC index */ + + move16(); + last = 0; + if ( NE_16(numlpc,1)) + { + move16(); + last = M; + } + + move16(); + p_index = index; + + /* Decode last LPC */ + + FOR (i=0; inext_bit_pos_fx; + + /* Index bits */ + + move16(); + *ind = 0; + WHILE ((get_next_indice_1_fx(st) != 0) && !st->BER_detect) + { + move16(); + *ind = add(*ind,1); + } + + if (*ind != 0) + { + move16(); + *ind = add(*ind, 1); + } + + return sub(st->next_bit_pos_fx, start_bit_pos); + +} + +static Word16 pack4bits(Word16 nbits, Decoder_State_fx *st, Word16 *prm) +{ + Word16 i; + + + move16(); + i=0; + + FOR ( ; nbits > 4; nbits -= 4 ) + { + move16(); + prm[i] = get_next_indice_fx(st, 4); + i = add(i,1); + + + } + prm[i] = get_next_indice_fx(st, nbits); + move16(); + i = add(i,1); + + return(i); +} + +Word16 decode_lpc_avq( Decoder_State_fx *st, Word16 numlpc, Word16 *param_lpc ) +{ + Word16 k,j; + Word16 nb, qn1, qn2, avqBits, q_type; + Word16 start_bit_pos; + + move16(); + move16(); + j = 0; + start_bit_pos = st->next_bit_pos_fx; + + FOR (k=0; kBER_detect = 1; + move16(); + } + + move16(); + param_lpc[j] = qn1; + j = add(j, 1); + move16(); + param_lpc[j] = qn2; + j = add(j, 1); + + /* Decode Split-by-2 algebraic VQ */ + avqBits = shl(qn1,2); + + pack4bits(avqBits, st, ¶m_lpc[j]); + j = add(j, qn1); + + avqBits = shl(qn2,2); + pack4bits(avqBits, st, ¶m_lpc[j]); + j = add(j, qn2); + } + + return sub(st->next_bit_pos_fx, start_bit_pos); +} diff --git a/lib_dec/dlpc_stoch.c b/lib_dec/dlpc_stoch.c new file mode 100644 index 0000000..f42f519 --- /dev/null +++ b/lib_dec/dlpc_stoch.c @@ -0,0 +1,121 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +/* Header files */ +#include +#include +#include +#include "stl.h" +#include "basop_util.h" +#include "prot_fx.h" + +/* Constants */ +#define M 16 + +#define BFI_FAC 0.9f + + +void lpc_unquantize( + Decoder_State_fx * st, + Word16 *lsfold, + Word16 *lspold, + Word16 *lsf, + Word16 *lsp, + const Word16 m, + const Word16 lpcQuantization, + Word16 *param_lpc, + const Word16 numlpc, + const Word16 core, + Word16 *mem_MA, + Word16 * mem_AR, + Word16 *lspmid, + Word16 *lsfmid, + Word16 coder_type, + Word16 acelp_midLpc, + Word8 narrow_band, + Word16 *seed_acelp, + Word32 sr_core, + Word16 *mid_lsf_int, + Word16 prev_bfi, + Word16 *LSF_Q_prediction, /* o : LSF prediction mode */ + Word16 *safety_net +) +{ + Word16 nb_indices, k; + Word16 i; + + nb_indices = 0; /* to avoid compilation warnings */ + + + Copy(lsfold, &lsf[0], m); + Copy(lspold, &lsp[0], m); + + IF( lpcQuantization == 0 ) + { + nb_indices = dlpc_avq(param_lpc, &lsf[m], numlpc, st->sr_core); + FOR ( k=0; kbwidth */ , 31, &lsf[m], mem_AR, mem_MA, sr_core, st->core_brate_fx, + &st->offset_scale1_fx[0][0], &st->offset_scale2_fx[0][0], &st->offset_scale1_p_fx[0][0], &st->offset_scale2_p_fx[0][0], + &st->no_scales_fx[0][0], &st->no_scales_p_fx[0][0], &st->safety_net_fx, param_lpc, LSF_Q_prediction, &nb_indices ); + } + ELSE + { + IF (EQ_16(st->core_fx, TCX_20_CORE)) + { + lsf_end_dec_fx( st, 1, AUDIO, sub(1, narrow_band) /* st->bwidth */ , 31, &lsf[m], mem_AR, mem_MA, sr_core, st->core_brate_fx, + &st->offset_scale1_fx[0][0], &st->offset_scale2_fx[0][0], &st->offset_scale1_p_fx[0][0], &st->offset_scale2_p_fx[0][0], + &st->no_scales_fx[0][0], &st->no_scales_p_fx[0][0], &st->safety_net_fx, param_lpc, LSF_Q_prediction, &nb_indices); + } + ELSE + { + lsf_end_dec_fx( st, 1, coder_type, sub(1, narrow_band) /* st->bwidth */ , 31, &lsf[m], mem_AR, mem_MA, sr_core, st->core_brate_fx, + &st->offset_scale1_fx[0][0], &st->offset_scale2_fx[0][0], &st->offset_scale1_p_fx[0][0], &st->offset_scale2_p_fx[0][0], + &st->no_scales_fx[0][0], &st->no_scales_p_fx[0][0], &st->safety_net_fx, param_lpc, LSF_Q_prediction, &nb_indices); + } + } + + lsf2lsp_fx(&lsf[m], &lsp[m], M, sr_core); + } + ELSE + { + assert(0); + } + + *seed_acelp=0; + move16(); + FOR(i=nb_indices-1; i>=0; i--) + { + *seed_acelp = extract_l(L_mac0(L_mac0(13849, shr(*seed_acelp, 1), 31821), param_lpc[i], 31821)); + } + + /* Decoded mid-frame isf */ + test(); + test(); + test(); + IF ( lpcQuantization && acelp_midLpc && core==ACELP_CORE && st->rate_switching_reset==0) + { + midlsf_dec ( &lsf[0], &lsf[m], param_lpc[nb_indices], lsfmid + ,coder_type + ,mid_lsf_int, + prev_bfi, + *safety_net + ); + reorder_lsf_fx( lsfmid, LSF_GAP_MID_FX, M, sr_core ); + lsf2lsp_fx(lsfmid, lspmid, M, sr_core); + } + + + return; +} + diff --git a/lib_dec/er_dec_acelp.c b/lib_dec/er_dec_acelp.c new file mode 100644 index 0000000..6632f93 --- /dev/null +++ b/lib_dec/er_dec_acelp.c @@ -0,0 +1,1126 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*VERSIONINFO: File up to date with trunk rev. 39929*/ + + +#include +#include +#include +#include "prot_fx.h" +#include "basop_util.h" +#include "rom_dec_fx.h" +#include "options.h" +#include "stl.h" + +extern const Word16 T_DIV_L_Frame[];/*0Q15 * 2^-7 */ + +/*Table 2^7 * 1/L_frame */ + +#define L_SYN_BUF M+L_DIV_MAX+L_DIV_MAX +#define L_EXC_BUF OLD_EXC_SIZE_DEC_16k+L_DIV_MAX+L_SUBFR+1+L_DIV_MAX/2 + +/*LOCAL FUNCTIONS*/ +static void memsynPrecission(Word16 nbLostCmpt,Word16* mem_syn, Word16* exc, Word16 len, Word16*s_16); + + + +/*************************************************************** + * \brief Main concealment function for ACELP + * + * +****************************************************************/ + +void con_acelp( + const Word16 A[], /*mem_syn >rescaling done */ + Word16 *pitch_buffer, + Word16 *voice_factors, + Word16 *bwe_exc +) +{ + + Word16 i_subfr, i, T0; /*Q0*/ + Word16 tmp, tmp2, tmp_deemph; + Word16 mem_syn[M], mem_syn2[M], *syn; + Word16 *noise_buf; + Word16 *exc, *harmonic_exc_buf, buf[L_EXC_MEM_DEC+M+L_FRAME_16k+L_FRAME_16k/2]; /*Qf_exc*/ + const Word16 *p_A; + Word32 pitch_buf[NB_SUBFR16k] /*15Q16*/; + Word16 alpha; /*Q14*/ + Word16 step, gain, gainCNG,ftmp; + Word16 *pt_exc; + Word16 gain_inov; + Word16 gainCNG_e ; /*scaling Factor (exponent) of gainCNG*/ + Word16 Qf_syn; /*Q format and exponent of new synthesis*/ + Word16 *pt1_exc; + Word32 tmp_tc; /*15Q16*/ + Word16 extrapolationFailed; + Word32 predPitchLag; /*15Q16*/ + Word32 pc; /*float 15Q16*/ + Word16 fUseExtrapolatedPitch;/*int*/ + Word16 tmpSeed, Tc; /*Q0*/ + Word16 s_32; + Word16 synthScaling; + PWord16 const *w = st->tcx_cfg.tcx_mdct_window; + Word16 W1, W2; + Word16 nSubframes; + Word16 s_16, s_gain_inov, s2; + Word16 tmp_16, gain_16; + Word32 tmp_32, gain_32, step_32; + Word16 l_fir_fer; + Word16 lpFiltAdapt[3]; + Word16 hp_filt[3]; + Word16 Qf_syn_new; + Word16 exc_unv[L_FRAME_16k+L_FRAME_16k/2]; + Word16 syn_unv[L_FRAME_16k+L_FRAME_16k/2]; + Word16 mem_syn_unv[M]; + Word16 gain_lpc[NB_SUBFR16k]; + Word16 gain_lpc_e[NB_SUBFR16k]; + Word16 mem[M]; + Word16 h1[L_FRAME_16k/4+1]; + Word16 gainSynthDeemph; + Word16 gainSynthDeemph_e; + Word16 l; + Word16 g, g_e; + Word16 n; + const Word16 scale_h1 = 5; + + /*Inits*/ + move16(); + l_fir_fer = L_FIR_FER; + + fUseExtrapolatedPitch = 0; + move16(); + extrapolationFailed = 1; + move16(); + + move16(); + move16(); + move16(); + alpha = 0; + /*st->Mode2_lp_gainc = L_shl(st->Mode2_lp_gainc,7);*/ /*rudiment, could be changed in the whole file but should work also*/ + pc=L_deposit_l(0); + + /*------------------------------------------------------------------------* + * Initialize buffers * + *------------------------------------------------------------------------*/ + + /* set ACELP synthesis memory */ + Copy( st->mem_syn2_fx, mem_syn, M); + + /* set excitation memory*/ + harmonic_exc_buf = buf+M; + exc = harmonic_exc_buf+L_EXC_MEM_DEC; + Copy( st->old_exc_fx, harmonic_exc_buf, L_EXC_MEM_DEC); + exc[st->L_frame_fx] = 0; + move16(); + + /*------------------------------------------------------------------------* + * PLC: [ACELP:Extrapolate Pitch Lag] + *------------------------------------------------------------------------*/ + + if (EQ_16(st->flagGuidedAcelp, 1)) + { + T0 = st->guidedT0; + move16(); + } + + pitch_pred_linear_fit(st->nbLostCmpt, st->last_good_fx, + st->old_pitch_buf_fx, + &st->old_fpitch, + &predPitchLag, st->pit_min, st->pit_max, st->mem_pitch_gain, 0, + st->plc_use_future_lag, &extrapolationFailed, st->nb_subfr); + T0 = round_fx(predPitchLag); + + IF (extrapolationFailed != 0) + { + /*------------------------------------------------------------------------* + * - Construct adaptive codebook from side information * + *------------------------------------------------------------------------*/ + + IF (st->flagGuidedAcelp == 0) + { + nSubframes = 0; + move16(); + } + ELSE + { + nSubframes = 2; + move16(); + /* Construct adaptive codebook with T0, T0_frac, T0_res, gain_pit for 2 sub-frames */ + l = shl(L_SUBFR,1); + FOR (i = 0; i < l; i++) + { + exc[i] = exc[sub(i,st->guidedT0)]; + move16(); + } + } + } + ELSE + { + nSubframes = 0; + move16(); + } + + tmp_tc = st->old_fpitch; + move16(); /* take the previous frame last pitch*/ + if( nSubframes > 0 ) + { + tmp_tc = L_deposit_h(st->guidedT0); /* take the transmit pitch*/ + } + + /* PLC: [ACELP: Fade-out] + * PLC: calculate damping factor */ + alpha = Damping_fact(coder_type, st->nbLostCmpt, st->last_good_fx, stab_fac, &(st->Mode2_lp_gainp), 0); /*Q14*/ + st->cummulative_damping = shl(mult(st->cummulative_damping,alpha),1);/*shl(Q15*Q14,1)=shl(Q14,1) = Q15*/ + if (EQ_16(st->nbLostCmpt,1)) + { + st->cummulative_damping = 32767/*1.f Q15*/; /*Q15*/ + } + + /*-----------------------------------------------------------------* + * PLC: [ACELP: adaptive codebook] + * PLC: Construct the harmonic part of excitation + *-----------------------------------------------------------------*/ + + IF( GE_16(st->last_good_fx , UNVOICED_TRANSITION )) + { + + /*---------------------------------------------------------------* + * Last pitch cycle of the previous frame is repeatedly copied. * + *---------------------------------------------------------------*/ + + Tc = round_fx(tmp_tc); + BASOP_SATURATE_WARNING_OFF /*if this ever saturates, it doesn't matter*/ + tmp = sub(shl(abs_s(sub(T0,Tc)),6) , mult(19661/*0.15f Q17*/,shl(Tc,4)) /*Q6*/); + BASOP_SATURATE_WARNING_ON + test(); + test(); + test(); + if ((T0 > 0) && (NE_16(T0 , Tc)) + && ( tmp < 0 ) + && extrapolationFailed == 0 ) + { + fUseExtrapolatedPitch = 1; + move16(); + } + + pt_exc = exc; + if (st->enableGplc != 0) + { + pt_exc = &exc[nSubframes*L_SUBFR]; + } + pt1_exc = pt_exc - Tc; + + IF (fUseExtrapolatedPitch != 0) + { + /* Required because later pt1_exc[1] used in filtering points to exc[0]. To make it safe also for GPL pt_exc is used instead of exc */ + pt_exc[0] = 0; + move16(); + pt_exc = harmonic_exc_buf; + assert(pt_exc < pt1_exc-1); + } + + IF (EQ_16(st->nbLostCmpt, 1)) + { + /* pitch cycle is first low-pass filtered */ + + /*get filter coefficients*/ + genPlcFiltBWAdap( + st->sr_core, /*W32 Q0*/ + &lpFiltAdapt[0] /*Q15*/, + 0, + st->cummulative_damping /*Q15*/ + ); + FOR( i=0 ; i< Tc; i++ ) + { + + /* *pt_exc++ = ( lpFiltAdapt[0] * pt1_exc[-1] + lpFiltAdapt[1] * pt1_exc[0] + lpFiltAdapt[2] * pt1_exc[1]);*/ + tmp_32 = L_mult( lpFiltAdapt[0] , pt1_exc[-1]) ; + tmp_32 = L_mac(tmp_32, lpFiltAdapt[1] , pt1_exc[0]) ; + tmp_16 = mac_r(tmp_32, lpFiltAdapt[2] , pt1_exc[1]); + move16(); + *pt_exc = tmp_16; + pt_exc++; + pt1_exc++; + } + } + ELSE + { + /* copy the first pitch cycle without low-pass filtering */ + FOR( i=0 ; i< Tc; i++ ) + { + move16(); + *pt_exc++ = *pt1_exc++; + } + } + + if (fUseExtrapolatedPitch != 0) + { + pt1_exc = harmonic_exc_buf; + } + + l = add(st->L_frame_fx,sub(imult1616(L_SUBFR,sub(1,nSubframes)),Tc)); + FOR( i= 0; i < l; i++ ) + { + move16(); + *pt_exc++ = *pt1_exc++; + } + + /*-------------------------------------------------------* + * PLC: [ACELP: adaptive codebook] + * PLC: Resync pulse positions. + *-------------------------------------------------------*/ + + IF( nSubframes > 0 ) + { + move16(); + move16(); + pitch_buf[0] = L_deposit_h(st->guidedT0); + pitch_buf[1] = L_deposit_h(st->guidedT0); + } + + IF (nSubframes>0) + { + move16(); + move16(); + pitch_buf[3] = pitch_buf[2] = pitch_buf[1]; /* do not resync on second half of frame */ + if (EQ_16(st->nb_subfr, 5)) + { + /* for guided acelp cases and nSubframes=2, set pitch_buf[4] to avoid memory_access issues in post_decoder() */ + pitch_buf[4] = pitch_buf[3]; + move16(); + } + } + ELSE + { + IF (fUseExtrapolatedPitch != 0) + { + + get_subframe_pitch(st->nb_subfr, st->old_fpitch, predPitchLag, pitch_buf); + PulseResynchronization(harmonic_exc_buf, exc, st->L_frame_fx, st->nb_subfr, st->old_fpitch, predPitchLag); + } + ELSE { + set32_fx(pitch_buf, st->old_fpitch, st->nb_subfr); + } + } + + /*------------------------------------------------------------* + * PLC: [ACELP: adaptive codebook] + * PLC: Create the harmonic part needed for the overlap-add. + *------------------------------------------------------------*/ + pt_exc = exc+st->L_frame_fx; + pt1_exc = pt_exc - T0; + if (T0 == 0) + { + pt1_exc = pt_exc - Tc; + } + l = shr(st->L_frame_fx, 1); + FOR (i = 0; i < l; i++) + { + *pt_exc++ = *pt1_exc++; + move16(); + } + + /*-------------------------------------------------------* + * PLC: [ACELP: adaptive codebook] + * PLC: update the floating point pitch for consecutive loss + *-------------------------------------------------------*/ + + IF (fUseExtrapolatedPitch != 0) + { + move32(); + st->old_fpitch = predPitchLag; + if (EQ_16(st->flagGuidedAcelp ,1)) + { + st->old_fpitch = L_deposit_h(T0); + } + } + + /*-------------------------------------------------------* + * PLC: [ACELP: adaptive BPF] + * PLC: Accommodate the BPF + *-------------------------------------------------------*/ + + st->bpf_gain_param = 3 ; /*full BPF*/ move16(); + + /*-------------------------------------------------------* + * PLC: [ACELP: adaptive codebook] + * PLC: Calculate the initial gain and fade out step. + *-------------------------------------------------------*/ + + /* Compute pitch coherence (copied from decoder classifier)*/ + + pc = L_abs(L_sub(L_add(pitch_buf[3], L_sub(pitch_buf[2], pitch_buf[1])), pitch_buf[0])); /*9Q6*/ /*> 15Q16*/ + + /* mapping: floor(( 0.824[15Q15]-x[15Q0]*0.0733[0Q15] )*4) */ + + pc = Mpy_32_16_1( L_shl(pc,1)/*precompensate Q14 from table*/, /*15Q16*/ + T_256DIV_L_Frame[L_shr(L_msu0(54000,shr(st->L_frame_fx,5),2402),15-2)]); + + test(); + test();/*test();*/ + IF (LE_16(st->last_good_fx , UNVOICED_TRANSITION) + && (EQ_16(coder_type , GENERIC ) ) + && GT_32(pc , 6*2*32768/*6(15Q16)*/ ) /*&& (stab_fac <= 0.5f)*/ + ) + { + gain = 0; + move16(); + st->Mode2_lp_gainp = L_deposit_l(0); + } + ELSE + { + gain = 0x4000 /*1 (1Q14)*/; /* start-of-the-frame gain */ + st->Mode2_lp_gainp = L_shl(L_deposit_l(alpha),15); /*1Q14->2Q29*/ + } + + tmp_16 = extract_l(L_shl(L_mac(-28000,st->L_frame_fx,95),1-15)); + tmp_16 = T_DIV_L_Frame[tmp_16]; + tmp_32 = L_mult0(tmp_16 , sub(gain , alpha));/* 0Q15 * 2^-7 * 1Q14 -> 2Q29 * 2^-7*/ + tmp_32 = L_shr(tmp_32,6); /*-> 1Q30*/ + step = round_fx(tmp_32); /*->1Q14*/ + + /*FLC: step: 6.25e-5 .. 0.0045*/ /*-> s_step = -7*/ + /*lp_gainp : 0..0.2856..0.98*/ + + /*-------------------------------------------------------* + * PLC: [ACELP: Fade-out] + * Apply fade out + *-------------------------------------------------------*/ + + tmp_16 = 0; + move16(); + l = 0; + move16(); + FOR (i_subfr = 0; i_subfr < st->nb_subfr; i_subfr++) + { + pgainT[i_subfr] = gain; /*Q14*/ move16(); + i = l; + move16(); + l = add(l, L_SUBFR); + FOR (; i < l; i++) + { + move16(); + BASOP_SATURATE_WARNING_OFF + exc[i] = mult_r(exc[i] , shl(gain,1)); /*overflow is first iteration because gain may be 1 after shift*/ + BASOP_SATURATE_WARNING_ON + gain = sub(gain , step); + } + } + + l = add(st->L_frame_fx,shr(st->L_frame_fx,1)); + FOR (; i < l; i++ ) + { + move16(); + BASOP_SATURATE_WARNING_OFF + exc[i] = mult_r(exc[i] , shl(gain,1)); /*overflow is first iteration because gain may become 1 due to shift*/ + BASOP_SATURATE_WARNING_ON + gain = sub(gain , step); + } + + FOR (i = 0; i < st->nb_subfr; i ++) + { + pT[i] = round_fx(pitch_buf[i]); /*Q0*/ + pitch_buffer[i] = round_fx(pitch_buf[i]); + } + + /* update old exc without random part*/ + Copy(harmonic_exc_buf+st->L_frame_fx, st->old_exc_fx, L_EXC_MEM_DEC); + } + ELSE + { + /* No harmonic part */ + assert( (int)(sizeof(buf)/sizeof(buf[0])) - M - L_EXC_MEM_DEC >= st->L_frame_fx + st->L_frame_fx/2); + set16_fx(&exc[0], 0, add(st->L_frame_fx, shr(st->L_frame_fx,1))); + + FOR (i = 0; i < st->nb_subfr; i ++) + { + pitch_buf[i] = L_deposit_h(st->pit_max); /*15Q16*/ + pgainT[i] = 0; + move16(); + pT[i] = L_SUBFR; + move16(); + pitch_buffer[i] = L_SUBFR; + move16(); + } + + st->bpf_gain_param = 0; /*no BPF*/ move16(); + } + + /*-----------------------------------------------------------------* + * Construct the random part of excitation (5/2 st->L_frame_fx + 2L_FIR_FER - 2) + * + * This is done in Q0 and will be corrected to current Q format of excitation + * when doing "non-causal ringing of the FIR filter" + * + * search for "Scale from randomized buffer to excitation buffer" + *-----------------------------------------------------------------*/ + noise_buf = buf; + move16(); + tmpSeed = st->seed_acelp; + move16(); + l = add(st->L_frame_fx,sub(l_fir_fer,1)); + FOR (i = 0; i < l; i++) + { + tmpSeed = own_random2_fx(tmpSeed); + noise_buf[i] = tmpSeed; /*Q0*/ move16(); + } + + st->seed_acelp = tmpSeed; + move16(); + l = add(add(st->L_frame_fx,shr(st->L_frame_fx,1)),sub(l_fir_fer,1)); + FOR ( ; i < l; i++) + { + tmpSeed = own_random2_fx(tmpSeed); + noise_buf[i] = tmpSeed; /*Q0*/ move16(); + } + + /*get filter coefficients*/ + genPlcFiltBWAdap(st->sr_core, /*W32 Q0*/ + &hp_filt[0], /*Q15*/ + 1, + st->cummulative_damping); /*Q15*/ + + /* PLC: [ACELP: Fade-out] + * PLC: retrieve background level */ + + tmp2 = shl(div_s(st->L_frame_fx,shl(L_SUBFR,3)),3-15); + + + tmp = 32767/*1.0f Q15*/; + gainSynthDeemph=getLevelSynDeemph(&(tmp), + A, + M, + L_SUBFR, + st->preemph_fac, + tmp2, + &gainSynthDeemph_e); + + + + /*gainCNG=st->cngTDLevel/gainSynthDeemph;*/ + BASOP_Util_Divide_MantExp(st->cngTDLevel, st->cngTDLevel_e, gainSynthDeemph, gainSynthDeemph_e,&gainCNG, &gainCNG_e); + gainCNG_e=sub(gainCNG_e,15-5);/*Q15->Q5*/ + if(gainCNG==0) + { + gainCNG_e = 0; + move16(); + } + + gain_32 = st->Mode2_lp_gainc; /*15Q16 *//* start-of-the-frame gain */ move16(); + + ftmp = round_fx(L_shl(gain_32,1));/*Q0*/ + + BASOP_SATURATE_WARNING_OFF + tmp_16 = sub(shl(gainCNG,sub(gainCNG_e,5/*Q5*/)),ftmp); + /*in case of overflow:*/ + test(); + if ((EQ_16(shl(ftmp,sub(gainCNG_e,1)),MAXVAL_WORD16))&&(gainCNG==MAXVAL_WORD16)) + { + move16(); + tmp_16 = 1; + } + BASOP_SATURATE_WARNING_ON + + IF (tmp_16 > 0 ) + { + gainCNG = ftmp/*Q0*/; + gainCNG_e = 5; /*-> Q5*/ + s_16 = norm_s(gainCNG); + gainCNG = shl(gainCNG,s_16); + gainCNG_e = sub(gainCNG_e,s_16); + } + + /* end-of-the-frame gain */ + /* st->Mode2_lp_gainc = alpha * st->Mode2_lp_gainc + (1.0f - alpha) * gainCNG;*/ + tmp_32 = Mpy_32_16_1(st->Mode2_lp_gainc /*Q16*/,alpha/*Q14*/);/*Q31-16 = Q15*/ + s_32 = norm_l(tmp_32); + tmp_32 = L_shl(tmp_32,s_32); + tmp_16 = round_fx(tmp_32); + s_16 = negate(s_32); + s_16 = sub(s_16,-1-15); /*->Q15*/ + + tmp2 = sub(16384/*1 in Q14*/,alpha); /*Q14*/ + tmp2 = mult(tmp2,gainCNG); /*Q14+Q5 +1 -16 = Q4*/ + s2 = norm_s(tmp2); + tmp2 = shl(tmp2,s2); + s2 = add(negate(s2),gainCNG_e); + s2 = sub(s2,4-15);/*->Q15*/ + + s_16 = BASOP_Util_Add_MantExp(tmp_16,s_16,tmp2,s2,&tmp_16); + st->Mode2_lp_gainc = L_shl(L_deposit_l(tmp_16),add(s_16,1)); + test(); + IF( (EQ_16(st->last_good_fx, UNVOICED_TRANSITION))&&(EQ_16(coder_type,GENERIC))) + { + st->Mode2_lp_gainc = L_deposit_h(gainCNG);/*Q21*/ + st->Mode2_lp_gainc = L_shr(st->Mode2_lp_gainc,sub(5,gainCNG_e)); /*15Q16, no scaling*/ + } + + highPassFiltering(st->last_good_fx, add(st->L_frame_fx,shr(l_fir_fer,1)), noise_buf, hp_filt, l_fir_fer); + + pt_exc = noise_buf + l_fir_fer/2; + + /*** Find energy normalization factor ***/ + /*gain_inov = 1.0f / (float)sqrt( dot_product( pt_exc, pt_exc, st->L_frame_fx ) / st->L_frame_fx );*//* normalize energy */ /*<--- FLC*/ + + BASOP_SATURATE_WARNING_OFF /*norm_llQ31 at the end of Dot_productSq16HQ may throw an overflow, but result is okay*/ + tmp_32 = Dot_productSq16HQ(0,pt_exc,st->L_frame_fx,&s_32); + BASOP_SATURATE_WARNING_ON + s_32 = add(s_32, 31-1); + /*scalingfactor is twice the headroom (at noise insertion onto the buffer), -1 (because of mult) +31 (Result is Q31) +s_32 (output scalingfactor of dot_product)*/ + + tmp_16 = T_DIV_L_Frame[L_shl(L_mac(-28000,st->L_frame_fx,95),1-15)]; + tmp_32 = Mpy_32_16_1(tmp_32,tmp_16 ); /* Q31 * 2^s_32 * 0Q15 * 2^-7 */ + + s_32 = sub(s_32,7); /*tmp_32 is Q31 * 2^s_32 */ + + /*assure doing Isqrt not for 0*/ + IF (tmp_32 != 0) + { + s_gain_inov = s_32; + tmp_32 = ISqrt32(tmp_32, &s_gain_inov); + } + ELSE + { + s_gain_inov = 0; + tmp_32 = 0; + } + + + gain_inov = round_fx(tmp_32);/*Inverse sqrt*/ /* Q15 * 2^s_gain_inov */ + + /* PLC: [ACELP: Fade-out] + * PLC: Linearly attenuate the gain through the frame */ + + step_32 = L_sub(gain_32, st->Mode2_lp_gainc); /* 15Q16 */ + tmp_16 = extract_l(L_shl(L_mac(-28000,st->L_frame_fx,95),1-15)); + step_32 = Mpy_32_16_1(step_32, T_DIV_L_Frame[tmp_16]); /* 15Q16 * 2^-7 = 15Q16 * Q15 * 2^-7 */ + step_32 = L_shr(step_32, 7); /* 15Q16 */ + + test(); + if ((EQ_16(st->last_good_fx ,UNVOICED_CLAS))&&(NE_16(coder_type,UNVOICED))) /* Attenuate somewhat on unstable unvoiced */ + { + gain_inov = mult_r(gain_inov, 26214/*0.8f Q15*/); /*Q15 * 2^s_gain_inov*/ + } + + IF ( GE_16(st->last_good_fx , UNVOICED_TRANSITION)) + { + Word16 tilt_code; + + /*tilt_code = (float)(0.10f*(1.0f + st->voice_fac));*/ + tilt_code = mac_r(214748368l/*0.1f Q31*/, 3277/*0.1f Q15*/ , st->voice_fac); + + gain_inov = mult_r(gain_inov, sub(32767/*1.0f Q15*/, tilt_code)); /* Q15 * 2^s_gain_inov */ + } + + pt_exc = noise_buf; + + /* non-causal ringing of the FIR filter */ + + /* gain_16 = gain_32 = gain_inov * gain */ + gain_32 = Mpy_32_16_1(gain_32, gain_inov); /* 15Q16 * Q15 * 2^s_gain_inov */ + gain_32 = L_shl(gain_32, add(15, s_gain_inov)); /* Q31 */ + gain_16 = round_fx(gain_32); /* Q15 */ + + /* step_32 = gain_inov * step */ + step_32 = Mpy_32_16_1(step_32, gain_inov); /* 15Q16 * Q15 * 2^s_gain_inov */ + step_32 = L_shl(step_32, add(15, s_gain_inov)); /* Q31 */ + + g_e = norm_s(round_fx(L_shl(Mpy_32_16_1(st->Mode2_lp_gainc, gain_inov), add(15, s_gain_inov)))); /* norm_s for gain*gain_inov at the end of the following loops */ + g_e = s_min(norm_s(gain_16), g_e); + gain_16 = shl(gain_16, g_e); + gain_32 = L_shl(gain_32, g_e); + step_32 = L_shl(step_32, g_e); + l = shr(l_fir_fer,1); + FOR( i=0 ; i < l; i++ ) + { + /* *pt_exc++ *= (gain_inov * gain); <=> *pt_exc++ *= gain_16; */ /*<-- FLC*/ + *pt_exc = mult_r(*pt_exc , gain_16); /* Q0 = Q0 * Q15 */ move16(); + pt_exc++; + } + + /* gain -= step; gain is updated after the loop and inside the loop gain_16 = gain_inov * gain is modified using gain_inov * (gain-step) = gain_inov * gain - gain_inov * step */ /*<-- FLC*/ + FOR( i=0 ; i < st->L_frame_fx; i++ ) + { + /* *pt_exc++ *= (gain_inov * gain); <=> *pt_exc++ *= gain_16; */ /*<-- FLC*/ + *pt_exc = mult_r(*pt_exc , gain_16); /* Q0 = Q0 * Q15 */ move16(); + pt_exc++; + + gain_32 = L_sub(gain_32, step_32); + gain_16 = round_fx(gain_32); + } + + l = add(shr(st->L_frame_fx,1),l_fir_fer/2); + FOR( i=0 ; i < l; i++ ) + { + /* *pt_exc++ *= (gain_inov * gain); <=> *pt_exc++ *= gain_16; */ /*<-- FLC*/ + *pt_exc = mult_r(*pt_exc , gain_16); /* Q0 = Q0 * Q15 */ move16(); + pt_exc++; + } + + /*store st->past_gcode*/ + /* at this point gain is equal to st->Mode2_lp_gainc, so we don't need to calculate gain at all */ + st->past_gcode = st->Mode2_lp_gainc; /*15Q16 */ move16(); + + /*-----------------------------------------------------------------* + * PLC: [ACELP: general] + * PLC: Construct the total excitation + *-----------------------------------------------------------------*/ + + IF( st->last_good_fx < UNVOICED_TRANSITION ) + { + bufferCopyFx(noise_buf+l_fir_fer/2, exc, add(st->L_frame_fx,shr(st->L_frame_fx,1)), 0, *Qf_exc, negate(g_e), 0); /*copy between different formats*/ + Copy(harmonic_exc_buf+st->L_frame_fx, st->old_exc_fx, L_EXC_MEM_DEC); + Copy(exc, exc_unv, add(st->L_frame_fx, shr(st->L_frame_fx,1))); /* Update exc_unv */ + } + ELSE + { + /* Update exc_unv */ + bufferCopyFx(noise_buf+l_fir_fer/2, exc_unv, add(st->L_frame_fx,shr(st->L_frame_fx,1)), 0, *Qf_exc, negate(g_e), 0); /*copy between different formats*/ + } + + /* Compute total excitation in noisebuffer to save memories */ + IF( GE_16( st->last_good_fx, UNVOICED_TRANSITION )) + { + Vr_add(exc, exc_unv, noise_buf, add(st->L_frame_fx, 1)); + } + ELSE + { + noise_buf = exc_unv; + } + + IF( EQ_16( st->L_frame_fx, L_FRAME )) + { + interp_code_5over2_fx(noise_buf, bwe_exc, st->L_frame_fx); + set16_fx(voice_factors, st->last_voice_factor_fx, NB_SUBFR); + } + ELSE + { + interp_code_4over2_fx(noise_buf, bwe_exc, st->L_frame_fx); + set16_fx(voice_factors, st->last_voice_factor_fx, NB_SUBFR16k); + } + + /*----------------------------------------------------------* + * - compute the synthesis speech * + *----------------------------------------------------------*/ + + /* Init syn buffer */ + syn = buf + M; + Copy(st->mem_syn2_fx, buf, M ); + + IF (EQ_16(st->nbLostCmpt,1)) + { + IF( st->last_good_fx < UNVOICED_TRANSITION ) + { + Copy(st->mem_syn2_fx, mem_syn_unv, M ); + } + ELSE + { + set16_fx( mem_syn_unv, 0, M ); + } + } + ELSE + { + Copy( st->mem_syn_unv_back, mem_syn_unv, M ); + } + + /* voiced synth */ + IF(st->last_good_fx >= UNVOICED_TRANSITION) + { + p_A = A; + FOR (i_subfr = 0; i_subfr < st->L_frame_fx; i_subfr += L_SUBFR) + { + tmp = 0; + move16(); + set16_fx(h1, 0, L_SUBFR+1); + set16_fx(mem, 0, M); + h1[0] = 1024/*1.0f/((float)(1 << scale_h1)) Q15*/; + move16(); + E_UTIL_synthesis(0, p_A, h1, h1, L_SUBFR, mem, 0, M); /* impulse response of LPC */ + deemph_fx(h1, st->preemph_fac, L_SUBFR, &tmp); /* impulse response of deemph */ + + /* impulse response level = gain introduced by synthesis+deemphasis */ + /* gain_lpc[i_subfr/L_SUBFR] = 1.f/(float)sqrt(dotp( h1, h1, L_SUBFR)); */ + tmp_32 = Dot_productSq16HQ(0, h1, L_SUBFR, &gain_lpc_e[i_subfr/L_SUBFR]); + tmp_32 = L_max(tmp_32, 1); + gain_lpc_e[i_subfr/L_SUBFR] = add(gain_lpc_e[i_subfr/L_SUBFR], 2*scale_h1); + move16(); + gain_lpc[i_subfr/L_SUBFR] = round_fx(ISqrt32(tmp_32, &gain_lpc_e[i_subfr/L_SUBFR])); + + p_A += (M+1); /* Pointer move */ + } + + g = 0; + move16(); + FOR (i_subfr = 0; i_subfr < st->L_frame_fx; i_subfr += L_SUBFR) + { + + g = mult_r(st->last_gain_syn_deemph, gain_lpc[i_subfr/L_SUBFR]); + g_e = add(st->last_gain_syn_deemph_e, gain_lpc_e[i_subfr/L_SUBFR]); + g = shl(g, g_e); + FOR (i=0; i < L_SUBFR; i++) + { + /* exc[i_subfr + i] *= st->last_gain_syn_deemph*gain_lpc[j]; */ + exc[i_subfr + i] = mult_r(exc[i_subfr + i], g); + move16(); + } + } + l = add(st->L_frame_fx, shr(st->L_frame_fx, 1)); + FOR (i = st->L_frame_fx; i < l; i++) + { + exc[i] = mult_r(exc[i], g); + move16(); + } + + /*Rescale the synthesis memory*/ + Qf_syn_new = *Qf_mem_syn; + move16(); + Qf_syn = *Qf_mem_syn; + move16(); + rescale_mem(Qf_exc, &Qf_syn_new, &Qf_syn, mem_syn, NULL, M, st->L_frame_fx); + synthScaling = sub(*Qf_exc,Qf_syn); + + p_A = A; + + /*in case of more than 5 consecutive concealed frames, improve precision of synthesis*/ + memsynPrecission(st->nbLostCmpt,mem_syn, exc, st->L_frame_fx, &s_16); + FOR (i_subfr = 0; i_subfr < st->L_frame_fx; i_subfr += L_SUBFR) + { + + + E_UTIL_synthesis(synthScaling, p_A, &exc[i_subfr], &syn[i_subfr], L_SUBFR, mem_syn, 1, M); + p_A += (M+1); + } + Copy( mem_syn, mem_syn2, M ); + /* synthesize ola*/ + E_UTIL_synthesis(synthScaling, p_A-(M+1), &exc[i_subfr], &syn[i_subfr], (st->L_frame_fx/2), mem_syn2, 0, M); + } + + test(); + IF(GT_16(st->nbLostCmpt,5)&&(s_16>0)) + { + /*scale back mem_syn, exc and synthesis*/ + Scale_sig(mem_syn,M,negate(s_16)); + Scale_sig(syn, add(shr(st->L_frame_fx,1),st->L_frame_fx) ,negate(s_16)); + /*Scale_sig(exc, add(shr(st->L_frame_fx,1),st->L_frame_fx) ,negate(s_16));*/ + } + + + /* unvoiced synth */ + + tmp = 0; + move16(); + p_A = st->Aq_cng; + + FOR (i_subfr = 0; i_subfr < st->L_frame_fx; i_subfr += L_SUBFR) + { + set16_fx(h1, 0, L_SUBFR+1); + set16_fx(mem, 0, M); + h1[0] = 1024/*1.0f/((float)(1 << scale_h1)) Q15*/; + move16(); + E_UTIL_synthesis(0, p_A, h1, h1, L_SUBFR, mem, 0, M); /* impulse response of LPC */ + deemph_fx(h1, st->preemph_fac, L_SUBFR, &tmp); /* impulse response of deemph */ + + /* impulse response level = gain introduced by synthesis+deemphasis */ + /* gain_lpc[i_subfr/L_SUBFR] = 1.f/(float)sqrt(dotp( h1, h1, L_SUBFR)); */ + tmp_32 = Dot_productSq16HQ(0, h1, L_SUBFR, &gain_lpc_e[i_subfr/L_SUBFR]); + tmp_32 = L_max(tmp_32, 1); + gain_lpc_e[i_subfr/L_SUBFR] = add(gain_lpc_e[i_subfr/L_SUBFR], 2*scale_h1); + move16(); + gain_lpc[i_subfr/L_SUBFR] = round_fx(ISqrt32(tmp_32, &gain_lpc_e[i_subfr/L_SUBFR])); + + p_A += (M+1); /* Pointer move */ + } + + g = 0; + move16(); + FOR (i_subfr = 0; i_subfr < st->L_frame_fx; i_subfr += L_SUBFR) + { + g = mult_r(st->last_gain_syn_deemph, gain_lpc[i_subfr/L_SUBFR]); + g_e = add(st->last_gain_syn_deemph_e, gain_lpc_e[i_subfr/L_SUBFR]); + g = shl(g, g_e); + FOR (i=0; i < L_SUBFR; i++) + { + /* exc[i_subfr + i] *= st->last_gain_syn_deemph*gain_lpc[j]; */ + exc_unv[i_subfr + i] = mult_r(exc_unv[i_subfr + i], g); + move16(); + } + } + l = add(st->L_frame_fx, shr(st->L_frame_fx, 1)); + FOR (i = st->L_frame_fx; i < l; i++) + { + exc_unv[i] = mult_r(exc_unv[i], g); + move16(); + } + + /* Update Qf_syn */ + Qf_syn_new = *Qf_mem_syn; + move16(); + Qf_syn = *Qf_mem_syn; + move16(); + rescale_mem(Qf_exc, &Qf_syn_new, &Qf_syn, mem_syn_unv, NULL, M, st->L_frame_fx); + synthScaling = sub(*Qf_exc,Qf_syn); + *Qf_mem_syn = Qf_syn; + + p_A = st->Aq_cng; + + /*in case of more than 5 consecutive concealed frames, improve precision of synthesis*/ + memsynPrecission(st->nbLostCmpt,mem_syn_unv, exc_unv, st->L_frame_fx, &s_16); + + FOR (i_subfr = 0; i_subfr < st->L_frame_fx; i_subfr += L_SUBFR) + { + E_UTIL_synthesis(synthScaling, p_A, &exc_unv[i_subfr], &syn_unv[i_subfr], L_SUBFR, mem_syn_unv, 1, M); + p_A += (M+1); + } + Copy(mem_syn_unv,st->mem_syn_unv_back,M); + + IF(LT_16(st->last_good_fx,UNVOICED_TRANSITION)) + { + Copy(mem_syn_unv,mem_syn,M); + /* unvoiced for ola */ + E_UTIL_synthesis(synthScaling, p_A-(M+1), &exc_unv[i_subfr], &syn_unv[i_subfr], shr(st->L_frame_fx,1), mem_syn_unv, 0, M); + } + + test(); + IF(GT_16(st->nbLostCmpt,5)&&(s_16>0)) + { + /*scale back mem_syn_unv, exc_unv and synthesis*/ + Scale_sig(mem_syn_unv,M,negate(s_16)); + IF(LT_16(st->last_good_fx,UNVOICED_TRANSITION)) + { + Scale_sig(mem_syn,M,negate(s_16)); + Scale_sig(syn_unv, add(shr(st->L_frame_fx,1),st->L_frame_fx) ,negate(s_16)); + } + ELSE + { + Scale_sig(syn_unv, st->L_frame_fx ,negate(s_16)); + } + + Scale_sig(st->mem_syn_unv_back,M,negate(s_16)); + + /*Scale_sig(exc_unv, add(shr(st->L_frame_fx,1),st->L_frame_fx) ,negate(s_16));*/ + } + + /* add separate synthesis buffers */ + IF (GE_16(st->last_good_fx,UNVOICED_TRANSITION)) + { + FOR( i=0 ; i < st->L_frame_fx; i++ ) + { + syn[i] = add(syn[i], syn_unv[i]); + move16(); + } + } + ELSE + { + Copy(syn_unv,syn,add(st->L_frame_fx, shr(st->L_frame_fx,1))); + } + + + /* update buffer for the classification */ + { + Word16 pit16[NB_SUBFR16k]; + Word16 k; + FOR(k = 0 ; k < st->nb_subfr; k++) + { + pit16[k] = shl(extract_h(pitch_buf[k]),6);/*Q6*/ + } + + FEC_clas_estim_fx( + st, + /*Opt_AMR_WB*/0, /*A*/ + st->L_frame_fx, + &(st->clas_dec), + coder_type, + pit16, + syn, + &st->lp_ener_FER_fx, + /**decision_hyst*/NULL, /* i/o: hysteresis of the music/speech decision */ + /**UV_cnt*/ NULL, /* i/o: number of consecutives frames classified as UV */ + /**LT_UV_cnt*/ NULL, /* i/o: long term consecutives frames classified as UV */ + /**Last_ener*/ NULL, /* i/o: last_energy frame */ + /**locattack*/ NULL, /* i/o: detection of attack (mainly to localized speech burst) */ + /**lt_diff_etot*/NULL, /* i/o: long-term total energy variation */ + /**amr_io_class*/ NULL, /* i/o: classification for AMR-WB IO mode */ + /*bitrate*/ 0 , /* i : Decoded bitrate */ + Qf_syn, /* i : Synthesis scaling */ + /**class_para*/ NULL, /* o : classification para. fmerit1 */ + st->mem_syn_clas_estim_fx, /* i/o: memory of the synthesis signal for frame class estimation */ + &st->classifier_Q_mem_syn, /*i/o : exponent for memory of synthesis signal for frame class estimation */ + -32768/*-1.f Q15*/, /* i : LTP Gain */ + 0/*CLASSIFIER_ACELP*/, /* i : signal classifier mode */ + 1/*bfi*/, /* i : bad frame indicator */ + st->last_core_brate_fx /* i : bitrate of previous frame */ + ); + } + + /* Update Pitch Lag memory */ + Copy32(&st->old_pitch_buf_fx[st->nb_subfr], st->old_pitch_buf_fx, st->nb_subfr); + Copy32(pitch_buf, &st->old_pitch_buf_fx[st->nb_subfr], st->nb_subfr); + + /*updating enr_old parameters*/ + frame_ener_fx( st->L_frame_fx, st->last_good_fx, syn, round_fx(tmp_tc), &(st->enr_old_fx), 1, 0, 0, 0 ); + + st->enr_old_fx = L_shl(st->enr_old_fx,shl(negate(Qf_syn),1)); + + /* update ACELP synthesis memory */ + Copy(mem_syn, st->mem_syn2_fx , M); + Copy(syn+st->L_frame_fx-L_SYN_MEM, st->mem_syn_r , L_SYN_MEM); + + /*Q_mem_syn_new = Q_mem_syn;*//*NOT "+synthScaling", cause mem_syn format is not changed*/ + /* Deemphasis and output synth */ + tmp_deemph = st->syn[M]; + + E_UTIL_deemph2(*Qf_mem_syn, syn, st->preemph_fac, add(st->L_frame_fx,shr(st->L_frame_fx,1)), &tmp_deemph); + + Copy(syn, synth, st->L_frame_fx); + + bufferCopyFx(syn+st->L_frame_fx-st->L_frame_fx/2, st->old_syn_Overl, shr(st->L_frame_fx,1),0 /*Qf_syn*/, -1 /*Qf_old_xnq*/, 0 , 0 /*Q_old_xnq*/); + + /* save last half frame if next frame is TCX */ + bufferCopyFx(syn+st->L_frame_fx, st->syn_Overl_TDAC, shr(st->L_frame_fx,1),0 /*Qf_syn*/, -1 /*Qf_old_xnq*/, 0 , 0 /*Q_old_xnq*/ ); + Copy(syn+st->L_frame_fx-M-1, st->syn, add(1,M)); + + /* update old_Aq */ + Copy(p_A-(M+1), st->old_Aq_12_8_fx, add(M,1)); + + + Copy(syn+st->L_frame_fx, st->syn_Overl, shr(st->L_frame_fx,1)); + + /* create aliasing and windowing */ + + W1 = st->tcx_cfg.tcx_mdct_window_length; + move16(); + W2 = shr(W1,1); + + st->tcx_cfg.tcx_curr_overlap_mode = FULL_OVERLAP; + move16(); + + n = extract_h(L_mult(st->L_frame_fx,9216/*(float)N_ZERO_MDCT_NS/(float)FRAME_SIZE_NS Q15*/)); + + st->Q_old_wtda_LB = getScaleFactor16(syn+st->L_frame_fx-n, + sub(st->L_frame_fx,n)); + move16(); + + bufferCopyFx(syn+st->L_frame_fx-n, st->old_out_LB_fx, sub(st->L_frame_fx, n), 0, 0, st->Q_old_wtda_LB, 0); + FOR (i=0; i < W2; i++) + { + st->old_out_LB_fx[i+n] = round_fx(Mpy_32_16_1(L_mult(w[i].v.re,w[i].v.re),st->old_out_LB_fx[i+n])); + } + FOR ( ; i < W1; i++) + { + st->old_out_LB_fx[i+n] = round_fx(Mpy_32_16_1(L_mult(w[W2-1-(i-W2)].v.im,w[W2-1-(i-W2)].v.im),st->old_out_LB_fx[i+n])); + } + set16_fx(&st->old_out_LB_fx[W1+n], 0, n); + + st->Q_old_wtda = st->Q_old_wtda_LB; + + + + FOR (i=0; isyn_Overl_TDAC[i],w[i].v.re); + + } + FOR(; isyn_Overl_TDAC[i],w[W1-1-i].v.im); + } + + + FOR (i=0; isyn_Overl_TDAC[i] = add(buf[i],buf[W1-1-i]); /* A-D */ + } + /*-2*/ + FOR (i=0; isyn_Overl_TDAC[W2+i] = add(buf[W2+i],buf[W1-1-W2-i]);/* B-C */ + } + + + FOR (i=0; isyn_Overl_TDAC[i] = mult_r(st->syn_Overl_TDAC[i],w[i].v.re); + } + + FOR(; isyn_Overl_TDAC[i] = mult_r(st->syn_Overl_TDAC[i],w[W1-1-i].v.im); + } + + /* update memory for full band */ + lerp(st->syn_Overl_TDAC, st->syn_Overl_TDACFB, shr(st->L_frameTCX, 1), shr(st->L_frame_fx, 1)); + lerp(st->syn_Overl, st->syn_OverlFB, shr(st->L_frameTCX, 1), shr(st->L_frame_fx, 1)); + lerp(st->old_out_LB_fx, st->old_out_fx, st->L_frameTCX, st->L_frame_fx); + + /* copy total excitation exc2 as 16kHz for acelp mode1 decoding */ + lerp(exc, st->old_exc2_fx, L_EXC_MEM, st->L_frame_fx); + lerp(syn, st->old_syn2_fx, L_EXC_MEM, st->L_frame_fx); + st->bfi_pitch_fx = shl(round_fx(pitch_buf[st->nb_subfr-1]),6); + move16(); + st->bfi_pitch_frame_fx = st->L_frame_fx; + move16(); + + return; +} + +static void memsynPrecission(Word16 nbLostCmpt,Word16* mem_syn, Word16* exc, Word16 len, Word16*s_16) +{ + IF(GT_16(nbLostCmpt,5)) + { + Word16 sf_mem_syn, sf_exc,k, tmp_loop, max, tmp, i; + tmp = 0; + move16(); + *s_16 = 0; + move16(); + max = 0; + move16(); + + /*check energy of mem_syn*/ + FOR(i=0; i 0 ) + { + sf_mem_syn = getScaleFactor16(mem_syn,M); + /*sf_exc = getScaleFactor16(exc, add(shr(len,1),len));*/ /*this returns 0 if signal is 0*/ + tmp_loop = add(shr(len,1),len); + FOR(k=0; k +#include +#include +#include "options.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "rom_dec_fx.h" +#include "stl.h" + + +/***************************************************** + calcGainc calculates st->lp_gainc +******************************************************/ +static void calcGainc(Word16* exc, Word16 Q_exc, Word32 old_fpitch, Word16 L_subfr, Word32 lp_gainp, Word32* lp_gainc) +{ + Word32 L_c ; + Word16 tmp16, tmp16_2, tmp16_3, tmp_e, tmp2_e, tmp_loop, i; + Word32 L_acc, L_tmp; + + + L_acc = L_deposit_l(0); + L_c = L_deposit_l(0); + Overflow = 0; + Carry = 0; + + tmp16 = round_fx(old_fpitch);/*Q0*/ + tmp_loop = shl(L_subfr,1); + BASOP_SATURATE_WARNING_OFF + tmp16_2 = round_fx(L_shl(lp_gainp,2)); /*Q31->Q15, no severe saturation, because st->lp_gainp here is [0,1]*/ + BASOP_SATURATE_WARNING_ON + + FOR ( i=0; i< tmp_loop; i++ ) + { + /*st->lp_gainc += ( exc[i-2*L_subfr] - st->Mode2_lp_gainp * exc[i-2*L_subfr-(int)(st->old_fpitch+0.5f)] ) * + ( exc[i-2*L_subfr] - st->Mode2_lp_gainp * exc[i-2*L_subfr-(int)(st->old_fpitch+0.5f)] );*/ + tmp16_3 = sub + ( + exc[i-2*L_subfr] /*Q1*/, + mult_r(tmp16_2 /*Q15*/, exc[i-2*L_subfr-tmp16]/*Q1*/)/*Q1*/ + ); + L_acc = L_macNs(L_acc,tmp16_3,tmp16_3); /*Q3*/ + Overflow = 0; + L_c = L_macNs(L_c,0,0); /*Accumulate Carrys*/ + Carry = 0; + } + L_tmp = norm_llQ31(L_c,L_acc,&tmp_e);/*Q3,norm,tmp_e*/ + tmp_e = add(tmp_e,31-(add(shl(Q_exc,1),1))); /*L_tmp is Q31, now*/ + tmp16 = BASOP_Util_Divide3216_Scale(L_tmp/*Q31,norm,tmp_e*/,shl(L_subfr,1)/*Q15,15*/,&tmp2_e)/*Q15,tmp2_e+tmp_e-15*/; + tmp_e = sub(add(tmp2_e,tmp_e), 15); + + IF (tmp16 != 0) + { + tmp16 = Sqrt16(tmp16,&tmp_e); /*Q15,norm,tmp_e*/ + } + *lp_gainc = L_shl(L_deposit_l(tmp16),add(tmp_e,1)); /*15Q16*/ + +} + +static void calcGainc2(Word16 *exc, Word16 Q_exc, Word16 L_subfr, Word32* lp_gainc) +{ + Word16 i, cnt, tmp16 , tmp_e, tmp2_e; + Word32 L_c, L_acc, L_tmp; + + + Carry = 0; + Overflow = 0; + + L_c = L_deposit_l(0); + L_acc = L_deposit_l(0); + + cnt = shl(L_subfr,1); + + FOR (i=0; i < cnt; i++) + { + /* *gainc += ( exc[i-2*L_subfr] ) * ( exc[i-2*L_subfr]); */ + L_acc = L_macNs(L_acc, exc[i-2*L_subfr] /*Q1*/, exc[i-2*L_subfr] /*Q1*/); /*Q3*/ + Overflow = 0; + L_c = L_macNs(L_c,0,0); /* Accumulate Carrys */ + Carry = 0; + } + + L_tmp = norm_llQ31(L_c,L_acc,&tmp_e); /*Q3,norm,tmp_e*/ + tmp_e = add(tmp_e,31-(add(shl(Q_exc,1),1))); /*L_tmp is Q31, now*/ + tmp16 = BASOP_Util_Divide3216_Scale(L_tmp/*Q31,norm,tmp_e*/,shl(L_subfr,1)/*Q15,15*/,&tmp2_e)/*Q15,tmp2_e+tmp_e-15*/; + tmp_e = sub(add(tmp2_e,tmp_e), 15); + + IF ( tmp16 != 0 ) + { + tmp16 = Sqrt16(tmp16,&tmp_e); /*Q15,norm,tmp_e*/ + } + *lp_gainc = L_shl(L_deposit_l(tmp16),add(tmp_e,1)); /*15Q16*/ move32(); + +} + +/****************************************************** + +con_tcx + +\brief main function in time domain TCX concealment + +*******************************************************/ + +void con_tcx( + Decoder_State_fx *st, /* i/o: coder memory state */ + Word16 synth[] /* i/o: synth[] *//*Q0 */ +) +{ + Word16 i, s, c, L_frame, L_subfr, fLowPassFilter, T0; + Word16 n, mem_syn_r_size_old, mem_syn_r_size_new; + Word16 *noise; + Word16 mem_syn[M], *syn; + Word16 *exc, buf[OLD_EXC_SIZE_DEC+L_FRAME_MAX+L_FRAME_MAX/NB_SUBFR+1+L_FRAME_MAX/2]; + Word16 pre_emph_buf; + Word16 hp_filt[L_FIR_FER2]; + Word16 alpha; + Word16 tmp_deemph, gain, gainCNG, gain_inov; + Word16 *pt_exc, *pt1_exc; + Word16 Tc, tmpSeed; + Word16 fUseExtrapolatedPitch; + Word16 *ana_window; + Word16 r_h[M+1], A_local[M+1], mem, r_l[M+1]; + PWord16 const *w; + Word16 W1, W2, W12; + Word16 Q_r; + Word16 tmp16, tmp16_2, tmp_loop, tmp_e, gain_tmp; + Word16 gainCNG_e, noise_e, gain_inov_e ;/*Exponents for gainCNG, noise, gain_inov*/ + Word16 Q_syn; /*Q format of temporary synthesis buffer syn*/ + Word32 L_tmp, L_tmp2, step32_tmp; + Word32 predPitchLag, pitch_buf[NB_SUBFR16k], step32, gain32; + Word16 extrapolationFailed; + Word16 gainSynthDeemph; + Word16 gainSynthDeemph_e; + Word32 old_pitch_buf[2*NB_SUBFR16k+2]; + Word16 Q_exc, new_Q, exp_scale; + Word16 offset; + + /* inits */ + alpha = 0; + move16(); + fUseExtrapolatedPitch = 0; + move16(); + extrapolationFailed = 1; + move16(); + + noise_e = 0; + move16(); + Q_syn = -1; /*Q format of temporary synthesis buffer syn*/ move16(); + offset = 0; + move16(); + + /* Framing parameters */ + L_frame = st->L_frameTCX; + move16(); + /* L_subfr = st->L_frameTCX/st->nb_subfr */ + L_subfr = mult_r(st->L_frameTCX,div_s(1,st->nb_subfr)); + assert( L_subfr == st->L_frameTCX/st->nb_subfr ); + move32(); + w = st->tcx_cfg.tcx_mdct_windowFB; /*pointer - no need to instrument*/ + W1 = st->tcx_cfg.tcx_mdct_window_lengthFB; + move16(); + W2 = shr(st->tcx_cfg.tcx_mdct_window_lengthFB,1); + W12 = shr(W1,1); + + /* take the previous frame last pitch */ + Tc = round_fx(st->old_fpitchFB); + + set16_fx(buf,0,shr(sizeof(buf),1)); /* initialize buf with 0 */ + + c = BASOP_Util_Divide1616_Scale( + L_frame, + st->L_frame_fx, + &s + ); + + FOR (i=0; i < (2*NB_SUBFR16k+2); i++) + { + old_pitch_buf[i] = L_shl(Mpy_32_16_1(st->old_pitch_buf_fx[i],c),s); + move32(); + } + + /* set excitation memory*/ + exc = buf+OLD_EXC_SIZE_DEC; + tmp_deemph = synth[-1]; + move16(); + pre_emph_buf = synth[-1]; + move16(); + + test(); + IF ( (EQ_16( st->nbLostCmpt, 1 ))||st->tcxConceal_recalc_exc) + { + /* apply pre-emphasis to the signal */ + mem = synth[-((shr(L_frame,1))+st->pit_max_TCX+M+M)-1]; + Q_exc = E_UTIL_f_preemph3(&(synth[-((shr(L_frame,1))+st->pit_max_TCX+2*M)]), st->preemph_fac, add(add(shr(L_frame,1),st->pit_max_TCX),shl(M,1)), &mem,1); + st->Mode2_lp_gainc = L_deposit_l(0); + + st->Mode2_lp_gainp = get_gain2( synth-2*L_subfr, synth-2*L_subfr-Tc, shl(L_subfr,1) ); + move32(); + + st->Mode2_lp_gainp = L_max(st->Mode2_lp_gainp,0); + st->Mode2_lp_gainp = L_min(st->Mode2_lp_gainp,65536l/*1.0f Q16*/); + st->Mode2_lp_gainp = L_shl(st->Mode2_lp_gainp, 13); + + ana_window = buf; + ham_cos_window(ana_window, mult(L_frame,24576/*0.75f Q15*/), shr(L_frame,2)); + + /* Autocorrelation */ + autocorr_fx(&(synth[-L_frame-1]), M, r_h ,r_l , &Q_r , L_frame, ana_window, 0, 0); + + /* Lag windowing */ + lag_wind( r_h,r_l, M, st->output_Fs_fx, LAGW_STRONG ); + + /* Levinson Durbin */ + E_LPC_lev_dur(r_h, r_l, A_local, NULL, M, NULL); + + /* copy for multiple frame loss */ + Copy(A_local, st->old_Aq_12_8_fx, M+1); + + /* Residu */ + assert((2*L_subfr+Tc+1+M) <= st->old_synth_lenFB); + + BASOP_SATURATE_WARNING_OFF /*saturation possible in case of spiky synthesis*/ + Residu3_fx( + A_local, + &(synth[-(2*L_subfr+Tc+1+M)]), /*Qx = Q0*/ + &(exc[-(2*L_subfr+Tc+1+M)]), /*Qx+1 = Q1*/ + add(add(add(shl(L_subfr,1),Tc),1),M), + 1); + BASOP_SATURATE_WARNING_ON + } + ELSE + { + /* apply pre-emphasis to the signal */ + mem = synth[-L_frame-1]; + Q_exc = E_UTIL_f_preemph3(&(synth[-L_frame]), st->preemph_fac, L_frame, &mem, 1); + Copy(st->old_Aq_12_8_fx, A_local, M+1); + + offset = shr(L_frame,1); + IF(GE_16(st->last_good_fx, UNVOICED_TRANSITION)) + { + tmp16 = s_max(Tc - shr(L_frame,1), 0); + Copy_Scale_sig(st->old_excFB_fx, &(exc[-tmp16]), offset+tmp16, Q_exc-st->Q_exc); + } + ELSE { + Copy_Scale_sig(st->old_excFB_fx, &(exc[-2*L_subfr]), 2*L_subfr+offset, Q_exc-st->Q_exc); + } + } + + /*-----------------------------------------------------------------* + * PLC: Construct the harmonic part of excitation + *-----------------------------------------------------------------*/ + + test(); + test(); + IF( GT_16(st->last_good_fx, UNVOICED_CLAS)&&!(EQ_16(st->last_good_fx,UNVOICED_TRANSITION)&&EQ_16(st->core_ext_mode,GENERIC))) + { + + IF ( EQ_16(st->nbLostCmpt,1)||st->tcxConceal_recalc_exc) + { + calcGainc( exc, Q_exc, st->old_fpitchFB, L_subfr, st->Mode2_lp_gainp, &(st->Mode2_lp_gainc)); + } + + tmp16 = 0; + move16(); + if (GT_32(st->output_Fs_fx , 25600)) + { + tmp16 = 1; + move16(); + } + + test(); + test(); + test(); + test(); + IF( ((EQ_16(st->nbLostCmpt,1))||st->tcxConceal_recalc_exc)&&GE_16(st->rf_frame_type,RF_TCXFD)&&LE_16(st->rf_frame_type,RF_TCXTD2)&&st->use_partial_copy) + { + Word32 tcxltp_pitch_tmp = L_add(L_deposit_h(st->tcxltp_pitch_int), L_shl(L_deposit_l(div_s(st->tcxltp_pitch_fr,st->pit_res_max)),1)); /*15Q16*/ + Word16 scale_tmp = mult_r(st->L_frameTCX, getInvFrameLen(st->L_frame_fx)); /*getInvFrameLen()->9Q6*/ + Word16 tmp_shift = norm_s(scale_tmp); + predPitchLag = L_shl(Mpy_32_16_1(tcxltp_pitch_tmp, shl(scale_tmp, tmp_shift)), sub(9, tmp_shift)); + + T0 = round_fx(predPitchLag); + + test(); + test(); + test(); + if ( (T0 > 0) + && (NE_16(T0,Tc) ) + && (LT_32(L_deposit_h(abs_s(sub(T0,Tc)))/*Q16*/ , L_mult(4915/*.15f Q15*//*Q15*/,Tc/*Q0*/) /*Q16*/ ) ) + ) + { + fUseExtrapolatedPitch = 1; + move16(); + } + } + ELSE + { + + pitch_pred_linear_fit( + st->nbLostCmpt, + st->last_good_fx, + old_pitch_buf, + &(st->old_fpitchFB), + &predPitchLag, + st->pit_min_TCX, + st->pit_max_TCX, + st->mem_pitch_gain, + tmp16, + st->plc_use_future_lag, + &extrapolationFailed, + st->nb_subfr + ); + + T0 = round_fx(predPitchLag); + test(); + test(); + test(); + if ( (T0 > 0) + && (NE_16(T0,Tc) ) + && (LT_32(L_deposit_h(abs_s(sub(T0,Tc)))/*Q16*/ , L_mult(4915/*.15f Q15*//*Q15*/,Tc/*Q0*/) /*Q16*/ ) ) + && (extrapolationFailed == 0) + ) + { + fUseExtrapolatedPitch = 1; + move16(); + } + } + + + fLowPassFilter = 0; + move16(); + pt_exc = exc + offset; + pt1_exc = pt_exc - Tc; + + if (fUseExtrapolatedPitch != 0) + { + pt_exc = buf; + } + test(); + IF( LT_16(st->stab_fac_fx ,32767/*1.f Q15*/)&&EQ_16(st->nbLostCmpt,1)) + { + /* pitch cycle is first low-pass filtered */ + + IF (LE_32(st->output_Fs_fx , 16000)) + { + FOR( i=0 ; i< Tc; i++ ) + { + move16(); + *pt_exc++ = mac_r(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac( + L_mult(174/* 0.0053f Q15*/, pt1_exc[-5]), + 0/* 0.0000f Q15*/, pt1_exc[-4]), + -1442/*-0.0440f Q15*/, pt1_exc[-3]), + 0/* 0.0000f Q15*/, pt1_exc[-2]), + 8641/* 0.2637f Q15*/, pt1_exc[-1]), + 18022/* 0.5500f Q15*/, pt1_exc[0] ), + 8641/* 0.2637f Q15*/, pt1_exc[1] ), + 0/* 0.0000f Q15*/, pt1_exc[2] ), + -1442/*-0.0440f Q15*/, pt1_exc[3] ), + 0/* 0.0000f Q15*/, pt1_exc[4] ), + 174/* 0.0053f Q15*/, pt1_exc[5] ); + pt1_exc++; + } + } + ELSE /*(st->output_Fs_fx >= 32000)*/ + { + FOR( i=0 ; i< Tc; i++ ) + { + move16(); + *pt_exc++ = mac_r(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac(L_mac( + L_mult(-174/*-0.0053f Q15*/, pt1_exc[-5]), + -121/*-0.0037f Q15*/, pt1_exc[-4]), + -459/*-0.0140f Q15*/, pt1_exc[-3]), + 590/* 0.0180f Q15*/, pt1_exc[-2]), + 8743/* 0.2668f Q15*/, pt1_exc[-1]), + 16355/* 0.4991f Q15*/, pt1_exc[0] ), + 8743/* 0.2668f Q15*/, pt1_exc[1] ), + 590/* 0.0180f Q15*/, pt1_exc[2] ), + -459/*-0.0140f Q15*/, pt1_exc[3] ), + -121/*-0.0037f Q15*/, pt1_exc[4] ), + -174/*-0.0053f Q15*/, pt1_exc[5] ); + pt1_exc++; + } + } + + fLowPassFilter = 1; + move16(); + } + ELSE + { + /* copy the first pitch cycle without low-pass filtering */ + FOR( i=0 ; i < Tc; i++ ) + { + *pt_exc++ = *pt1_exc++; + move16(); + } + fLowPassFilter = 1; + move16(); + } + + if (fUseExtrapolatedPitch != 0) + { + pt1_exc = buf; + } + tmp16 = add(sub(L_frame,imult1616(fLowPassFilter,Tc)),L_subfr); + FOR (i = 0; i < tmp16; i++) + { + *pt_exc++ = *pt1_exc++; + move16(); + } + + IF (fUseExtrapolatedPitch != 0) + { + get_subframe_pitch(st->nb_subfr, + st->old_fpitch, + /* predPitchLag * L_frame/st->L_frame, */ + L_shr(Mpy_32_16_1(predPitchLag/*Q16*/, + mult_r(st->L_frame_fx/*Q0*/, + getInvFrameLen(L_frame)/*Q21*/ + )/*Q6*/ + )/*Q7*/, + 7-16)/*Q16*/, + pitch_buf); + + PulseResynchronization(buf, exc, L_frame, st->nb_subfr, st->old_fpitchFB, predPitchLag); + } + ELSE + { + set32_fx( pitch_buf, st->old_fpitch, st->nb_subfr); + } + + IF ( EQ_16(st->nbLostCmpt , 1)) + { + pt_exc = exc+L_frame; + IF (T0 == 0) + { + pt1_exc = pt_exc - Tc; + } + ELSE + { + pt1_exc = pt_exc - T0; + } + + tmp_loop = shr(L_frame,1); + FOR (i = 0; i < tmp_loop; i++) + { + *pt_exc++ = *pt1_exc++; + move16(); + } + } + + if (fUseExtrapolatedPitch != 0) + { + st->old_fpitchFB = predPitchLag; + move16(); + } + st->bpf_gain_param = 0; + move16(); + + /* PLC: calculate damping factor */ + alpha = Damping_fact(st->core_ext_mode, st->nbLostCmpt, st->last_good_fx, st->stab_fac_fx, &(st->Mode2_lp_gainp), 0);/*Q14*/ + + IF ( EQ_16(st->nbLostCmpt , 1)) + { + st->cummulative_damping = 32767/*1.f Q15*/; + move16(); + } + ELSE + { + st->cummulative_damping = shl(mult_r(st->cummulative_damping/*Q15*/,alpha/*Q14*/),1)/*Q15*/; + } + + gain32 = L_add(2147483647l/*1.f Q31*/, 0); /*Q31*/ + gain = 32767/*1.f Q15*/; /*Q15*/ move16(); + if( EQ_16(st->rf_frame_type, RF_TCXTD1)&&EQ_16(st->use_partial_copy,1)) + { + gain32 = 1073741824l/*0.5f Q31*/; + gain = 16384/*0.5f Q15*/; + } + + /*step = (1.0f/(L_frame+(L_frame/2))) * (gain - alpha);*/ + tmp16 = shr(imult1616(3,L_frame),1); + tmp_e = norm_s(tmp16); + tmp16 = shl(tmp16,tmp_e); + tmp16 = div_s(16384/*1.f Q14*/,tmp16);/*Q15,1+tmp_e-15*/ + tmp16_2 = sub(shr(gain,1),alpha)/*Q14*/; + step32 = L_shl(L_mult(tmp16,tmp16_2)/*Q30, 1+tmp_e-15*/,add(1-14,tmp_e))/*Q31*/; + + /* PLC: Apply fade out */ + tmp_loop = shr(imult1616(L_frame,3),1); + FOR ( i=offset; i < tmp_loop; i++ ) + { + exc[i] = mult_r(exc[i],round_fx(gain32))/*Q1*/; + move16(); + gain32 = L_sub(gain32 , step32); + } + + /* update old exc without random part */ + offset = s_max(round_fx(st->old_fpitchFB) - shr(L_frame,1), 0); + Copy(exc+L_frame-offset, st->old_excFB_fx, shr(L_frame,1)+offset); + /* copy old_exc as 16kHz for acelp decoding */ + IF ( EQ_16(st->nbLostCmpt, 1)) + { + lerp(exc - shr(L_frame,1), st->old_exc_fx, L_EXC_MEM_DEC, add(L_frame, shr(L_frame,1))); + } + ELSE + { + Copy(st->old_exc_fx+L_FRAME16k, st->old_exc_fx, L_FRAME16k/2); + lerp(exc, st->old_exc_fx+L_FRAME16k/2, L_FRAME16k, L_frame); + } + st->Q_exc = Q_exc; + } + ELSE + { + /* No harmonic part */ + set16_fx(&exc[0], 0, add(L_frame,shr(L_frame,1))); + IF ( EQ_16(st->nbLostCmpt , 1)) + { + calcGainc2(&exc[0], Q_exc, L_subfr, &(st->Mode2_lp_gainc)); + } + set32_fx( pitch_buf, L_deposit_h(L_SUBFR), st->nb_subfr); + /* PLC: calculate damping factor */ + alpha = Damping_fact(st->core_ext_mode, st->nbLostCmpt, st->last_good_fx, st->stab_fac_fx, &(st->Mode2_lp_gainp), 0);/*Q14*/ + } + + /*-----------------------------------------------------------------* + * Construct the random part of excitation + *-----------------------------------------------------------------*/ + tmpSeed = st->seed_acelp; + move16(); + noise = buf; + noise_e = 1;/*set exponent of noise to 1*/ move16(); + + tmp_loop = add(L_frame,L_FIR_FER2-1); + FOR (i = 0; i < tmp_loop; i++) + { + tmpSeed = own_random2_fx(tmpSeed); + noise[i] = shr(tmpSeed,noise_e); + move16(); + } + st->seed_acelp = tmpSeed; + move16(); + + tmp_loop = add(add(L_frame,shr(L_frame,1)) ,shl(L_FIR_FER2,1)); + FOR ( ; i < tmp_loop; i++) + { + tmpSeed = own_random2_fx(tmpSeed); + noise[i] = shr(tmpSeed,noise_e); + move16(); + } + test(); + IF (EQ_16(st->last_good_fx , VOICED_CLAS)||EQ_16(st->last_good_fx,ONSET)) + { + tmp16 = 19661/*0.6f Q15*/; + move16(); + if ( LE_32(st->output_Fs_fx,16000)) + { + tmp16 = 6554/*0.2f Q15*/; + move16(); + } + + mem = noise[0]; + move16(); + preemph_copy_fx(&noise[1], &noise[1], tmp16, L_frame+(L_frame/2)+L_FIR_FER2, &mem); + } + /* high rate filter tuning */ + IF ( LE_32(st->output_Fs_fx,16000)) + { + FOR( i=0; i< L_FIR_FER2; i++ ) + { + hp_filt[i] = h_high3_16[i]; + move16(); + } + } + ELSE /*(st->output_Fs_fx==32000)*/ + { + FOR( i=0; i< L_FIR_FER2; i++ ) + { + hp_filt[i] = h_high3_32[i]; + move16(); + } + } + IF ( EQ_16(st->nbLostCmpt,1)) + { + highPassFiltering(st->last_good_fx, add(add(L_frame, shr(L_frame,1)),L_FIR_FER2), noise, hp_filt, L_FIR_FER2); + } + ELSE + { + IF(GT_16( st->last_good_fx , UNVOICED_TRANSITION)) + { + tmp_loop = add(add(L_frame,shr(L_frame,1)),L_FIR_FER2); + gain_tmp = negate(add(-32768,st->cummulative_damping));/*Q15*/ + FOR( i=0 ; i < tmp_loop; i++ ) + { + Word16 j; + L_tmp2 = 0; move32(); + for (j=11; j>0; j--) + { + L_tmp2 = L_mac(L_tmp2, noise[i+L_FIR_FER2-j], hp_filt[L_FIR_FER2-j]); + } + L_tmp2 = Mpy_32_16_1(L_tmp2, st->cummulative_damping/*Q15*/);/*Q0, noise_e*/ + noise[i] = mac_r(L_tmp2, gain_tmp,noise[i]);/*Q15, noise_e*/ + } + } + } + + /* PLC: [TCX: Fade-out] retrieve background level */ + tmp16 = 32767; + move16(); + gainSynthDeemph = getLevelSynDeemph(&(tmp16), + A_local, + M, + shr(L_frame,2), + st->preemph_fac, + 1, + &gainSynthDeemph_e); + IF (0 != st->tcxonly) + { + /* gainCNG = st->conCngLevelBackgroundTrace/gainSynthDeemph; */ + BASOP_Util_Divide_MantExp(st->conCngLevelBackgroundTrace, + st->conCngLevelBackgroundTrace_e, + gainSynthDeemph, gainSynthDeemph_e, + &gainCNG, &gainCNG_e); + } + ELSE + { + /* gainCNG = st->cngTDLevel/gainSynthDeemph; */ + BASOP_Util_Divide_MantExp(st->cngTDLevel, + st->cngTDLevel_e, + gainSynthDeemph, gainSynthDeemph_e, + &gainCNG, &gainCNG_e); + } + + gain32 = L_add(st->Mode2_lp_gainc, 0); /* start-of-the-frame gain - Q16*/ + if( EQ_16(st->rf_frame_type, RF_TCXTD1)&&EQ_16(st->use_partial_copy,1)) + { + gain32 = Mpy_32_16_1(gain32, 22938/*0.7f Q15*/); + } + L_tmp = L_shl(gain32,1); + + IF (GT_32(L_shl(L_deposit_h(gainCNG),sub(gainCNG_e,31-16)/*Q16*/) , L_tmp)) + { + gainCNG_e = sub(15+1,norm_l(L_tmp)); + gainCNG = extract_l(L_shr(L_tmp,gainCNG_e));/*Q15,gainCNG_e*/ + gainCNG_e = sub(gainCNG_e,1); + } + + /* st->Mode2_lp_gainc = alpha * (st->Mode2_lp_gainc) + (1.0f - alpha) * gainCNG;*/ /* end-of-the-frame gain */ + + L_tmp = Mpy_32_16_1(st->Mode2_lp_gainc,alpha)/*Q15*/; + L_tmp2 = L_mult(sub(16384/*1.f Q14*/,alpha)/*Q14*/,gainCNG/*Q15,gainCNG_e*/);/*Q30,gainCNG_e*/ + st->Mode2_lp_gainc = BASOP_Util_Add_Mant32Exp(L_tmp,31-15,L_tmp2,add(gainCNG_e,31-30),&tmp_e);/*Q31*/ move32(); + st->Mode2_lp_gainc = L_shl(st->Mode2_lp_gainc,sub(tmp_e,31-16)); + move32(); + + /* PLC: [TCX: Fade-out] Linearly attenuate the gain through the frame */ + /*step = (1.0f/L_frame) * (gain - (st->Mode2_lp_gainc));*/ + L_tmp = L_sub(gain32,st->Mode2_lp_gainc);/*Q16*/ + tmp_e = norm_l(L_tmp); + L_tmp = L_shl(L_tmp,tmp_e);/*Q16,-tmp_e*/ + step32 = Mpy_32_16_1(L_tmp/*Q16,-tmp_e*/,getInvFrameLen(L_frame)/*W16Q21*/);/*Q22,-tmp_e*/ + step32 = L_shl(step32,sub((25-22),tmp_e));/*Q25*/ + + pt_exc = noise + L_FIR_FER2/2; + + /*gain_inov = 1.0f / (float)sqrt( dot_product( pt_exc, pt_exc, L_frame ) / L_frame + 0.01f );*//* normalize energy */ + L_tmp = Dot_productSq16HQ(0,pt_exc/*Q0,15+1*/,L_frame,&tmp_e)/*Q31,tmp_e+16+16*/; + L_tmp = Mpy_32_16_1(L_tmp,getInvFrameLen(L_frame)/*W16Q21*/)/*W32Q37,tmp_e+16+16*//*Q5,tmp_e*/; + tmp_e = add(tmp_e,31-5);/*-->Q31*/ + gain_inov = round_fx(ISqrt32(L_tmp,&tmp_e));/*Q15,tmp_e*/ + gain_inov_e = tmp_e; + move16(); + test(); + test(); + IF (EQ_16(st->last_good_fx , UNVOICED_CLAS)&&NE_16(st->core_ext_mode,UNVOICED)) + { + gain_inov = mult_r(gain_inov,26214/*0.8f Q15*/); + } + ELSE IF (!( EQ_16(st->last_good_fx , UNVOICED_CLAS)||EQ_16(st->last_good_fx,UNVOICED_TRANSITION))) + { + /*gain_inov *= (1.1f- 0.75*st->lp_gainp);*/ + L_tmp = Mpy_32_16_1(L_sub(590558016l/*1.1f Q29*/, Mpy_32_16_1(st->Mode2_lp_gainp,24576))/*Q29*/,gain_inov/*Q15,gain_inov_e*/);/*Q29,gain_inov_e*/ + tmp_e = norm_l(L_tmp); + L_tmp = L_shl(L_tmp,tmp_e); + gain_inov_e = add(sub(gain_inov_e,tmp_e),31-29);/*->Q31*/ + gain_inov = round_fx(L_tmp);/*Q15,gain_inov_e*/ + } + + st->Mode2_lp_gainp = L_shr(L_deposit_h(alpha/*Q14*/)/*Q14+16*/,1);/*Q29*/ + pt_exc = noise; /* non-causal ringing of the FIR filter */ + + tmp_e = norm_l(gain32); + tmp_e = sub(tmp_e,5); /*5 Bit additional Headroom for the gain - should be enough*/ + gain32 = L_shl(gain32,tmp_e);/*Q16,-tmp_e*/ + L_tmp = Mpy_32_16_1(gain32/*Q16,-tmp_e*/, gain_inov/*Q15,gain_inov_e*/)/*Q16,gain_inov_e-tmp_e*/; + + gain_tmp = round_fx(L_tmp);/*Q0, gain_inov_e-tmp_e*/ + + FOR( i=0 ; i< L_FIR_FER2/2; i++ ) + { + *pt_exc = mult_r(*pt_exc,gain_tmp);/*Q-15,noise_e+gain_inov_e-tmp_e*/ move16(); + pt_exc++; + } + tmp16 = add(L_frame,L_FIR_FER2/2); + step32_tmp = L_shl(step32/*Q25*/,sub(tmp_e,(25-16)));/*Q16,-tmp_e*/ + FOR( i=0 ; i< tmp16; i++ ) /* Actual filtered random part of excitation */ + { + *pt_exc = mult_r(*pt_exc, gain_tmp); + move16(); + pt_exc++; + gain32 = L_sub(gain32/*Q16,-tmp_e*/,step32_tmp);/*Q16,-tmp_e*/ + gain_tmp = mult_r(round_fx(gain32/*Q16,-tmp_e*/)/*Q0*/, gain_inov/*Q15,gain_inov_e*/)/*Q0,gain_inov_e-tmp_e*/; + } + tmp16 = shr(L_frame,1); + FOR( i=0 ; i< tmp16; i++ ) /* causal ringing of the FIR filter */ + { + *pt_exc = mult_r(*pt_exc , gain_tmp); + move16(); + pt_exc++; + } + noise_e = add(sub(add(noise_e,gain_inov_e),tmp_e),15);/*--> noise is Q0, noise_e*/ + /*buf[0;L_FIR_FER2 + L_Frame + L_Frame/2] Q0, noise_e*/ + + /*-----------------------------------------------------------------* + * Construct the total excitation + *-----------------------------------------------------------------*/ + + IF( GE_16(st->last_good_fx , UNVOICED_TRANSITION)) + { + tmp16 = add(L_frame,shr(L_frame,1)); + FOR( i=0 ; i< tmp16; i++ ) + { + exc[i] = add(exc[i] , shl(noise[i+(L_FIR_FER2/2)],Q_exc+noise_e));/*Q1*/ move16(); + } + } + ELSE + { + bufferCopyFx(noise+L_FIR_FER2/2, exc, add(L_frame , shr(L_frame,1)),0/*Q_noise*/, noise_e, Q_exc, 0/*exc_e*/); + Copy(exc+L_frame-2*L_subfr, st->old_excFB_fx, 2*L_subfr+shr(L_frame,1)); + /* copy old_exc as 16kHz for acelp decoding */ + IF ( EQ_16(st->nbLostCmpt, 1)) + { + lerp(exc, st->old_exc_fx, L_EXC_MEM_DEC, add(L_frame, shr(L_frame,1))); + } + ELSE { + Copy(st->old_exc_fx+L_FRAME16k, st->old_exc_fx, L_FRAME16k/2); + lerp(exc, st->old_exc_fx+L_FRAME16k/2, L_FRAME16k, L_frame); + } + st->Q_exc = Q_exc; + } + /*buf[0;L_FIR_FER2 + L_Frame + L_Frame/2] Q0, noise_e*/ + /*buf[OLD_EXC_SIZE_DEC;3/2 L_frame] Q1*/ + + /* Update Pitch Lag memory */ + Copy32( &st->old_pitch_buf_fx[st->nb_subfr], st->old_pitch_buf_fx, st->nb_subfr ); + Copy32( pitch_buf, &st->old_pitch_buf_fx[st->nb_subfr], st->nb_subfr ); + + /*----------------------------------------------------------* + * - compute the synthesis speech * + *----------------------------------------------------------*/ + + syn = buf + M; + Copy(synth-M, buf, M); + + new_Q = sub(Q_exc, 3); + new_Q = s_max(new_Q, -1); + + tmp16 = s_min(new_Q, st->prev_Q_syn); + st->prev_Q_syn = new_Q; + move16(); + + exp_scale = sub(tmp16, Q_exc-1); + Q_syn = tmp16; + move16(); + + Copy_Scale_sig(buf, mem_syn, M, exp_scale); + + tmp_deemph = shl(tmp_deemph,Q_syn); + st->Q_syn = Q_syn; + + /*buf[OLD_EXC_SIZE_DEC;3/2 L_frame] Q1: exc*/ + /*buf[0;M] Q0: mem_syn*/ + + E_UTIL_synthesis( + sub(Q_exc, Q_syn), + A_local, + &exc[0], + &syn[0], + add(L_frame, shr(L_frame,1)), + mem_syn, + 1, + M); + + /*buf[OLD_EXC_SIZE_DEC;3/2 L_frame-1] Q1: exc*/ + /*buf[0;M-1] Q0: mem_syn*/ + /*buf[M;3/2 L_frame-1] Q-1: syn*/ + + n = extract_h(L_mult(L_frame,9216/*(float)N_ZERO_MDCT_NS/(float)FRAME_SIZE_NS Q15*/)); + + /* update ACELP synthesis memory */ + mem_syn_r_size_old = shr(L_frame,4); /* replace 1.25/20.0 by shr(4) */ + /* copy mem_syn as 16kHz */ + mem_syn_r_size_new = shr(L_FRAME16k,4); /* replace 1.25/20.0 by shr(4) */ + + Copy(syn+L_frame-L_SYN_MEM, st->mem_syn_r, L_SYN_MEM); + lerp(st->mem_syn_r+L_SYN_MEM-mem_syn_r_size_old, st->mem_syn_r+L_SYN_MEM-mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old); + Copy(st->mem_syn_r+L_SYN_MEM-M, st->mem_syn2_fx, M); + + /* Deemphasis and output synth and ZIR */ + deemph_fx(syn, st->preemph_fac, add(L_frame,shr(L_frame,1)), &tmp_deemph); + bufferCopyFx(syn+L_frame-M-1, st->syn, 1+M, Q_syn, 0, 0, 0); + + + lerp( syn+L_frame-shr(L_frame, 1), st->old_syn_Overl, shr(st->L_frame_fx, 1), shr(L_frame, 1) ); + Copy(syn+L_frame-n, st->old_out_fx, sub(L_frame,n)); + + FOR (i=0; i < W12; i++) + { + st->old_out_fx[i+n] = round_fx(Mpy_32_16_1(L_mult(w[i].v.re,w[i].v.re),st->old_out_fx[i+n])); + } + FOR ( ; i < W1; i++) + { + st->old_out_fx[i+n] = round_fx(Mpy_32_16_1(L_mult(w[W12-1-(i-W12)].v.im,w[W12-1-(i-W12)].v.im),st->old_out_fx[i+n])); + } + + set16_fx(&st->old_out_fx[W1+n], 0, n); + + st->Q_old_wtda = Q_syn; + move16(); + + /* As long as there is no synth scaling factor introduced, which + is given to the outside, there might occur overflows here */ + BASOP_SATURATE_WARNING_OFF + bufferCopyFx(syn, synth, L_frame, Q_syn, 0, 0, 0); + BASOP_SATURATE_WARNING_ON + + Copy_Scale_sig(syn+L_frame, st->syn_OverlFB, shr(L_frame,1), negate(Q_syn)); + + /* copy total excitation exc2 as 16kHz for acelp mode1 decoding */ + lerp(exc, st->old_exc2_fx, L_EXC_MEM, L_frame); + lerp(syn, st->old_syn2_fx, L_EXC_MEM, L_frame); + st->bfi_pitch_fx/*Q6*/ = round_fx(L_shl(pitch_buf[st->nb_subfr-1]/*15Q16*/,6/*Q6*/)); + move16(); + st->bfi_pitch_frame_fx = st->L_frame_fx; + move16(); + + /* create aliasing and windowing need for transition to TCX10/5 */ + bufferCopyFx(syn+L_frame, st->syn_Overl_TDACFB, shr(L_frame,1),Q_syn,0,-1,0); + + FOR (i=0 ; i < W12 ; i++) + { + buf[i] = mult_r(st->syn_Overl_TDACFB[i] , w[i].v.re); + move16(); + } + FOR ( ; i syn_Overl_TDACFB[i],w[W12-1-(i-W12)].v.im); + move16(); + } + + + FOR (i=0; isyn_Overl_TDACFB[i] = add(buf[i] , buf[W1-1-i]); + move16(); + } + + FOR (i=0; isyn_Overl_TDACFB[W2+i] = add(buf[W2+i] , buf[W1-1-W2-i]); + move16(); + } + + FOR (i=0 ; i < W12 ; i++) + { + st->syn_Overl_TDACFB[i] = mult_r(st->syn_Overl_TDACFB[i],w[i].v.re); + move16(); + } + FOR ( ; i syn_Overl_TDACFB[i] = mult_r(st->syn_Overl_TDACFB[i],w[W12-1-(i-W12)].v.im); + move16(); + } + + st->tcx_cfg.tcx_curr_overlap_mode = FULL_OVERLAP; + + synth[-1] = pre_emph_buf; + move16(); + + /* update memory for low band */ + Scale_sig(st->old_syn_Overl, shr(st->L_frame_fx, 1), sub(-1, Q_syn)); + lerp( st->syn_OverlFB, st->syn_Overl, shr(st->L_frame_fx, 1), shr(L_frame, 1) ); + lerp( st->syn_Overl_TDACFB, st->syn_Overl_TDAC, shr(st->L_frame_fx, 1), shr(L_frame, 1) ); + lerp( st->old_out_fx, st->old_out_LB_fx, st->L_frame_fx, L_frame ); + + + st->old_enr_LP = Enr_1_Az_fx(A_local, L_SUBFR); /*Q3*/ + + return; +} + diff --git a/lib_dec/er_scale_syn.c b/lib_dec/er_scale_syn.c new file mode 100644 index 0000000..d63dc7b --- /dev/null +++ b/lib_dec/er_scale_syn.c @@ -0,0 +1,129 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*This file is up to date with trunk rev 36531*/ + +#include +#include +#include "prot_fx.h" +#include "basop_util.h" +#include "cnst_fx.h" +#include "stl.h" + + +/*----------------------------------------------------------------------------------* +* Damping_fact() +* +* Estimate damping factor +*----------------------------------------------------------------------------------*/ + +/*This BASOP version was ported based on trunk rev. 27621 and updated based on trunk rev. 29287, re-updated based on trunk rev. 32244 */ +Word16 Damping_fact( /* o : damping factor *//*Q14*/ + const Word16 coder_type, /* i : coding type in last good received frame */ + const Word16 nbLostCmpt, /* i : counter of consecutive bfi frames */ + const Word16 last_good, /* i : last good frame class */ + const Word16 stab_fac, /* i : ISF stability factor *//*Q15*/ + Word32 *lp_gainp, /*i/o: damped pitch gain *//*2Q29 Word32!*/ + const Word16 core /* i : current coding mode */ +) +{ + Word16 alpha; /*Q14*/ + Word16 gain; /*Q14*/ + Word32 lp_tmp; + Word16 s_gainp; + Word32 gain32; + + IF (core == ACELP_CORE) + { + alpha = mult_r(_ALPHA_VT_FX,16384); /* rapid convergence to 0 *//*Q14*/ + test(); + test(); + test();/*ELSEIF*/ + test(); + test();/*ELSEIF*/ + IF( ( EQ_16(coder_type, UNVOICED))&&(LE_16(nbLostCmpt,3))) /* Clear unvoiced last good frame */ + { + alpha = mult_r(_ALPHA_UU_FX,16384); /*Q14*/ + } + ELSE IF( EQ_16(last_good, UNVOICED_CLAS)) + { + IF( EQ_16(nbLostCmpt,1)) + { + /* If stable, do not decrease the energy, pitch gain = 0 */ + /* * (1.0f - 2.0f*_ALPHA_U_FX) + 2.0f*MODE2_ALPHA_U; */ /* [0.8, 1.0] */ + alpha = add(mult_r(stab_fac,sub(16384,_ALPHA_U_FX)),_ALPHA_U_FX); + } + ELSE IF (EQ_16(nbLostCmpt, 2)) + { + /*alpha = _ALPHA_U_FX * 1.5f;*/ /* 0.6 */ + alpha = mult_r(_ALPHA_U_FX, 24576/*1.5f Q14*/); /*Q14*/ + } + ELSE + { + alpha = mult_r(_ALPHA_U_FX,16384); /*Q14*/ /* 0.4 go rapidly to CNG gain, pitch gain = 0 */ + } + } + ELSE IF( EQ_16(last_good, UNVOICED_TRANSITION)) + { + alpha = mult_r(_ALPHA_UT_FX,16384); /*Q14*/ + } + ELSE IF( (EQ_16(last_good, ONSET))&&(LE_16(nbLostCmpt,3))&&(EQ_16(coder_type,GENERIC))) + { + alpha = 13107/*0.8f Q14*/; /*Q14*/ + } + ELSE if( ( (EQ_16(last_good, VOICED_CLAS))||(EQ_16(last_good,ONSET)))&&(LE_16(nbLostCmpt,3))) + { + alpha = mult_r(_ALPHA_V_FX,16384); /* constant for the first 3 erased frames */ + } + + IF (GE_16(last_good, VOICED_CLAS)) + { + move16(); + lp_tmp = *lp_gainp; + + IF( EQ_16(nbLostCmpt, 1)) /* if first erased frame in a block, reset harmonic gain */ + { + /*lp_gainp_E = 1;*/ /*For sqrt, because *lp_gain is Q14 */ + + /*gain = (float)sqrt( *lp_gainp );*/ /* move pitch gain towards 1 for voiced to remove energy fluctuations */ + /*BASOP_Util_Sqrt_MantExp(lp_gainp,&lp_gainp_E);*/ + s_gainp = 31-29; + move16(); + gain32 = Sqrt32(lp_tmp, &s_gainp); + + gain = round_fx(L_shl(gain32,s_gainp)); /* Q15*/ + gain = s_min(gain, 32113/*0.98f Q15*/); /*Q15*/ + gain = s_max(gain, 27853/*0.85f Q15*/); /*Q15*/ + alpha = mult_r(alpha , gain); /*Q14*/ + } + ELSE IF ( EQ_16(nbLostCmpt, 2)) + { + /*0.6 + 0.35*stab_fac*/ + alpha = mult_r(mac_r(1288490240l/*0.6f Q31*/, 11469/*0.35f Q15*/, stab_fac), round_fx(L_shl(lp_tmp,1))); + } + ELSE + { + /*0.7 + 0.2*stab_fac*/ move16(); + lp_tmp = Mpy_32_16_1(lp_tmp, mac_r(1503238528l/*0.7f Q31*/, 6554/*0.2f Q15*/, stab_fac)); /*2Q29*/ + alpha = round_fx(L_shl(lp_tmp,1)); /*1Q14*/ + } + move16(); + *lp_gainp = lp_tmp; /*store*/ + } + } + ELSE + { + alpha = mac_r(375809632l/*0.35f Q30*/,6554/*0.4f Q14*/,stab_fac); /*Q14*/ + if (LT_16(nbLostCmpt,2)) + { + alpha = mac_r(751619264l/*0.70f Q30*/,4915/*0.3f Q14*/,stab_fac); /*Q14*/ + } + if (EQ_16(nbLostCmpt, 2)) + { + alpha = mac_r(483183808l/*0.45f Q30*/,6554/*0.4f Q14*/,stab_fac); /*Q14*/ + } + + } + return alpha; +} diff --git a/lib_dec/er_sync_exc.c b/lib_dec/er_sync_exc.c new file mode 100644 index 0000000..79feced --- /dev/null +++ b/lib_dec/er_sync_exc.c @@ -0,0 +1,542 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*This BASOP port is up to date with trunk rev. 36554*/ + +#include "cnst_fx.h" +#include "stl.h" +#include "prot_fx.h" +#include +#include +#include "basop32.h" +#include "basop_util.h" + +/*------------------------------------------------------------------------- +* +* Perform resynchronisation of the last glottal pulse in voiced lost frame +* +*------------------------------------------------------------------------*/ + + +/** Get the location of the minimum energy in the given signal. + * @returns Index of the position of the minimum energy, that is the position i where filter(x[i-filterLength/2],...,x[i+(filterLength-filterLength/2)-1]) is at maximum. + */ +static Word16 GetMinimumPosition( + Word16 const * x, /* Input signal. Qx*/ + Word16 length, /* The length of the input signal. Q0*/ + Word16 filterLength /* the length of the filter length used for the energy calculation. Q0*/ +) +{ + Word16 iMinEnergyPos, center, i; + Word16 cnt, tmp_e, tmp16; + Word32 energy, energy_old, tmptest; + + + + + filterLength = s_min(filterLength, length); + center = shr(filterLength,1); + iMinEnergyPos = center; + move16(); + + IF (filterLength > 0) + { + center = add(center,1); + energy = L_deposit_l(0); + energy_old = L_deposit_l(0); + + cnt = sub(length,filterLength); + + tmp_e = 0; + move16(); + FOR (i = 0; i < cnt; i++) + { + tmp16 = shr(x[i],tmp_e); + energy = L_msu(energy_old,tmp16,tmp16); + tmp16 = shr(x[i+filterLength],tmp_e); + BASOP_SATURATE_WARNING_OFF /*Saturation will be handled*/ + energy = L_mac(energy,tmp16,tmp16); + BASOP_SATURATE_WARNING_ON + + /*if (energy == MAXVAL_WORD32)*/ + BASOP_SATURATE_WARNING_OFF /*saturates if energy < 0*/ + tmptest = L_sub(energy,MAXVAL_WORD32); + BASOP_SATURATE_WARNING_ON + IF (tmptest == 0) + { + tmp_e = add(tmp_e,1); + energy = L_shr(energy_old,2); + tmp16 = shr(x[i],tmp_e); + energy = L_msu(energy,tmp16,tmp16); + tmp16 = shr(x[i+filterLength],tmp_e); + energy = L_mac(energy,tmp16,tmp16); + } + + IF (energy < 0) + { + iMinEnergyPos = add(i,center); + tmp_e = 0; + move16(); + energy = 0; + move16(); + } + energy_old = L_add(energy, 0); + } + + } + + return iMinEnergyPos; +} + +/*! + * \brief FindMaxPeak - Get the location of the maximum peak in the given signal. + * + * \returns Index of the position of the maximum peak, that is the position i where abs(x[i]) has it's maximum. + */ + +static Word16 FindMaxPeak +( + Word16 /*float*/ const * x, /* 0; j--) + { + *pt_dest++ = *pt_src++; + move16(); + } + /* Add some samples */ + ftmp = negate(mult(*pt_src,1638/*.05f Q15*/)); + + FOR (j = 0; j < points_by_pos[i]; j++) + { + *pt_dest++ = ftmp; + move16(); + ftmp = negate(ftmp); + } + /* Prepare for the next loop iteration */ + last_min_pos = min_pos[i]; + move16(); + } + /* Copy remaining length */ + FOR (j = sub(L_frame , add(n_samples_to_add , last_min_pos)); j > 0; j--) + { + *pt_dest++ = *pt_src++; + move16(); + } + +} + +static void RemoveSamples( + Word16 /*float*/const * const old_exc, /*i : Qx */ + Word16 /*float*/ * const new_exc, /*o : Qx */ + Word16 /*int*/ const L_frame, /*i : Q0 */ + Word16 /*int*/ const n_samples_to_add, /*i : Q0 */ + Word16 /*int*/ const min_pos[], /*i : Q0 */ + Word16 /*int*/ const points_by_pos[], /*i : Q0 */ + Word16 /*int*/ const nb_min /*i : Q0*/ +) +{ + Word16 /*float*/ * pt_dest; + Word16 /*float*/ const * pt_src; + Word16 /*int*/ last_min_pos, i, j; + + + + pt_dest = new_exc+L_frame; + last_min_pos = sub(L_frame,n_samples_to_add); + + FOR(i = sub(nb_min,1); i >= 0; i--) + { + /* Compute len to copy */ + /* Copy section, removing some samples */ + pt_src = old_exc+last_min_pos; + + FOR (j = sub(last_min_pos , add(min_pos[i],points_by_pos[i])); j > 0; j--) + { + *--pt_dest = *--pt_src; + move16(); + } + /* Prepare for the next loop iteration */ + last_min_pos = min_pos[i]; + move16(); + } + /* Copy remaining length */ + pt_src = old_exc+last_min_pos; + + FOR (j = last_min_pos; j > 0; j--) + { + *--pt_dest = *--pt_src; + move16(); + } + +} + +/** Resynchronize glotal pulse positions of the signal in src_exc and store it in dst_exc. + * src_exc holds on call the harmonic part of the signal with the constant pitch, constructed by repeating the last pitch cycle of length pitchStart. + * dst_exc holds on return the harmonic part of the signal with the pitch changing from pitchStart to pitchEnd. + * src_exc and dst_exc can overlap, but src_exc < dst_exc must be fullfiled. + */ +/*This BASOP port is up to date with trunk rev 8779(svnext2)*/ +void PulseResynchronization( + Word16 /*float*/ const * const src_exc, /*= 0)) + { + /* This is error handling and recovery that should never occur. */ + test(); + IF (src_exc != dst_exc && LE_16(nFrameLength, 1200)) + { + Copy(src_exc, dst_exc, nFrameLength); + } + return; + } + + roundedPitchStart = round_fx(pitchStart); /*Q0*/ + + /* freqStart = 1.0f/roundedPitchStart; */ + freqStart_e = 15; + move16(); + freqStart = Inv16(roundedPitchStart, &freqStart_e); /*Q15,freqStart_e*/ + + /* Calculate number of samples to be removed (if negative) or added (if positive) */ + /*samplesDelta = 0.5f*pitchDelta*nFrameLength*(nSubframes+1)*freqStart;*/ + /* pitchDelta*freqStart = ((pitchEnd - pitchStart)/roundedPitchStart)/nSubframes */ + tmp16 = shl(roundedPitchStart, 2); /*Q0*/ + if (EQ_16(nSubframes, 5)) + { + tmp16 = add(tmp16, roundedPitchStart);/*Q0*/ /*tmp16=roundedPitchStart*nSubframes*/ + } + tmp_e = norm_s(tmp16); + tmp16 = shl(tmp16, tmp_e);/*Q0,-tmp_e*/ /*tmp16=roundedPitchStart*nSubframes*/ + tmp_e = sub(15, tmp_e); + tmp16 = Inv16(tmp16, &tmp_e); /*Q15,tmp_e*/ /*tmp16=1.0/(roundedPitchStart*nSubframes)*/ + tmp32 = L_sub(pitchEnd,pitchStart); + tmp2_e = norm_l(tmp32); + tmp32 = L_shl(tmp32, tmp2_e);/*Q16,-tmp2_e*/ + tmp32 = Mpy_32_16_1(tmp32, tmp16);/*Q16,tmp_e-tmp2_e*/ /*tmp32=pitchDelta*freqStart*/ + tmp_e = sub(tmp_e, tmp2_e); /* sum up all the scalings for tmp32 */ + + tmp16 = imult1616(nFrameLength,add(nSubframes,1));/*Q0*//*tmp16=nFrameLength*(nSubframes+1)*/ + tmp2_e = norm_s(tmp16); + tmp16 = shl(tmp16,tmp2_e); + + tmp32 = Mpy_32_16_1(tmp32,tmp16);/*Q1 scaling (tmp_e-tmp2_e-1), -1 because of 0.5f*/ /*tmp32=0.5f*pitchDelta*nFrameLength*(nSubframes+1)*freqStart*/ + tmp_e = sub(sub(tmp_e,tmp2_e),1); /* sum up all the scalings for tmp32 */ + tmp_e = add(tmp_e,31-1); /* tmp32 is now regarded as Q31 with scaling tmp_e */ + + /*samplesDelta -= nFrameLength*(1.0f-pitchStart*freqStart);*/ + tmp2_e = norm_l(pitchStart); + tmp32_a = L_shl(pitchStart,tmp2_e); + tmp32_a = Mpy_32_16_1(tmp32_a/*Q16,-tmp2_e*/,freqStart/*Q15,freqStart_e*/);/*Q16, scaling (freqStart_e-tmp2_e)*/ /*tmp32_a=pitchStart*freqStart*/ + tmp16 = norm_l(tmp32_a); + tmp32_a = L_shl(tmp32_a,tmp16); + tmp2_e = sub(sub(freqStart_e,tmp16),tmp2_e); /* sum up all scalings for tmp32_a */ + tmp2_e = add(tmp2_e,31-16); /* tmp32_a is now regarded as Q31 with scaling tmp2_e */ + + tmp3_e = tmp2_e; + tmp32_a = L_negate(tmp32_a); + tmp32_a = L_add(L_shl(1, sub(31, tmp3_e)), tmp32_a); /*Q31,tmp3_e*//*tmp32_a= 1.0f-pitchStart*freqStart*/ + tmp2_e = norm_s(nFrameLength); + tmp16_a = shl(nFrameLength,tmp2_e); + tmp32_a = Mpy_32_16_1(tmp32_a/*Q31,tmp3_e*/,tmp16_a/*Q0,-tmp2_e*/);/*Q16,tmp3_e-tmp2_e*/ /*tmp32_a= nFrameLength*(1.0f-pitchStart*freqStart)*/ + tmp2_e = add(sub(tmp3_e, tmp2_e), 15); + samplesDelta = BASOP_Util_Add_Mant32Exp(tmp32, tmp_e, L_negate(tmp32_a), tmp2_e, &samplesDelta_e); /*Q31,samplesDelta_e*/ + + /* To have enough samples in the buffer of length nFrameLength*(nSubframes+1)/nSubframes, pitchEnd/pitchEnd must be bigger than (nSubframes-1)/(nSubframes+1)=1-2/(nSubframes+1) */ + /* Thus nSubframes must be bigger than 1 */ + nSamplesDelta = round_fx(L_shl(samplesDelta,sub(samplesDelta_e,31-16))); /*Q0*/ + nSamplesDeltaRemain = abs_s(nSamplesDelta); + /* Find the location of the glottal pulse */ + T0 = FindMaxPeak(src_exc, roundedPitchStart); /*Q0*/ + /* Get the index of the last pulse in the resynchronized frame */ + /*k = (int)ceil((nFrameLength-nSamplesDelta-T0)*freqStart - 1);*/ + tmp32 = BASOP_Util_Add_Mant32Exp(L_mult(sub(nFrameLength,add(nSamplesDelta,T0)),freqStart)/*Q16*/,add(freqStart_e,31-16),0x80000000/*-1.f Q31*/,0,&tmp_e); + tmp32 = L_shl(tmp32,sub(tmp_e,31-16))/*Q16*/; + tmp32 = L_add(tmp32,65536l/*1.f Q16*/); + k=extract_h(tmp32); + test(); + IF ((k >= 0) && LE_16(add(k,1) , NB_PULSES_MAX)) + { + absPitchDiff = L_abs(L_sub(L_deposit_h(roundedPitchStart),pitchEnd));/*Q16*/ + + /* Calculate the delta of the samples to be added/removed between consecutive cycles */ + /*perCycleDeltaDelta = (absPitchDiff*(nFrameLength-samplesDelta) - (float)fabs(samplesDelta)*roundedPitchStart) + / ((k+1)*(T0+0.5f*k*roundedPitchStart));*/ + tmp32 = L_sub(L_deposit_h(nFrameLength),L_shl(samplesDelta,sub(samplesDelta_e,31-16)));/*Q16*/ + tmp_e = 15; /*tmp32 = Q31,tmp_e*/ move16(); + tmp2_e = norm_l(tmp32); + tmp32 = L_shl(tmp32,tmp2_e); + tmp_e = sub(tmp_e,tmp2_e); /*tmp32 = Q31,tmp_e*/ + tmp2_e = norm_l(absPitchDiff); + tmp32_b = L_shl(absPitchDiff,tmp2_e); + tmp_e = sub(tmp_e,tmp2_e); + tmp32 = Mpy_32_16_1(tmp32_b,round_fx(tmp32));/*Q16,tmp_e*/ /*tmp32 = absPitchDiff*(nFrameLength-samplesDelta)*/ + tmp32_a = Mpy_32_16_1(L_abs(samplesDelta)/*Q31,samplesDelta_e*/,roundedPitchStart/*Q0*/);/*Q16,samplesDelta_e*/ /*tmp32_a=fabs(samplesDelta)*roundedPitchStart*/ + tmp32 = BASOP_Util_Add_Mant32Exp(tmp32, add(tmp_e,31-16), L_negate(tmp32_a), add(samplesDelta_e,31-16),&tmp_e);/*Q31,tmp_e*/ /*tmp32=absPitchDiff*(nFrameLength-samplesDelta)-fabs(samplesDelta)*roundedPitchStart*/ + tmp16 = imult1616(add(k,1),add(shl(T0,1),imult1616(k,roundedPitchStart)));/*Q0,-1*/ /*tmp16=(k+1)*(T0+0.5f*k*roundedPitchStart)*/ + perCycleDeltaDelta = BASOP_Util_Divide3216_Scale(tmp32/*Q31,tmp_e*/,tmp16/*Q0,-1*/,&perCycleDeltaDelta_e); /*Q15,perCycleDeltaDelta_e*/ + perCycleDeltaDelta_e = add(perCycleDeltaDelta_e,sub(tmp_e,-1+15)); + tmp_e = norm_s(perCycleDeltaDelta); + perCycleDeltaDelta_e = sub(perCycleDeltaDelta_e,tmp_e); + perCycleDeltaDelta = shl(perCycleDeltaDelta,tmp_e);/*Q15,perCycleDeltaDelta_e*/ + + + /* Calculate the integer number of samples to be added/removed in each pitch cycle */ + /*cycleDelta = max(0, (absPitchDiff-(k+1)*perCycleDeltaDelta)*T0*freqStart); */ + tmp_e = norm_s(k+1); + tmp32 = L_mult(perCycleDeltaDelta/*Q15,perCycleDeltaDelta_e*/,shl(add(k,1),tmp_e)/*Q0, tmp_e*/)/*Q0+16, perCycleDeltaDelta_e-tmp_e*/; + tmp32 = BASOP_Util_Add_Mant32Exp(absPitchDiff/*Q16*/,31-16,L_negate(tmp32),add(sub(perCycleDeltaDelta_e,tmp_e),31-16),&tmp_e);/*Q31,tmp_e*/ + tmp32 = Mpy_32_16_1(tmp32,T0/*Q0*/);/*Q16,tmp_e*/ + tmp32 = Mpy_32_16_1(tmp32/*Q16,tmp_e*/,freqStart/*Q15,freqStart_e*/)/*Q16, tmp_e+(freqStart_e)*/; + tmp32 = L_max(0,tmp32); + cycleDelta_e = add(tmp_e,freqStart_e); + tmp32_a = L_shl(tmp32,cycleDelta_e); + roundedCycleDelta = extract_h(L_abs(tmp32_a)); + if (tmp32<0) + { + roundedCycleDelta = negate(roundedCycleDelta); + } + fractionalLeft = lshr(extract_l(tmp32_a),1);/*Q15*/ + tmp_e = sub(15,norm_l(tmp32)); + cycleDelta_e = add(cycleDelta_e,tmp_e); + tmp32 = L_shr(tmp32,sub(tmp_e,15));/*Q31 frac, cycleDelta_e*/ + cycleDelta = round_fx(tmp32);/*Q15, cycleDelta_e*/ + if (cycleDelta == 0) + { + move16(); + cycleDelta_e = 0; + } + + /*roundedCycleDelta = (int)(cycleDelta); */ /*done above*/ + move16(); + iDeltaSamples[0] = roundedCycleDelta;/*Q0*/ + /*fractionalLeft = cycleDelta-roundedCycleDelta;*/ /*done above*/ + nSamplesDeltaRemain = sub(nSamplesDeltaRemain,roundedCycleDelta);/*Q0*/ + + tmp_e = (s_max(2,k)); + tmp_e = norm_s(tmp_e);/*maximum norming factor for following loop*/ + + + FOR (i = 1; i <= k; i++) + { + /*cycleDelta = (absPitchDiff-(k+1-i)*perCycleDeltaDelta) + fractionalLeft; */ + tmp32 = L_mult(perCycleDeltaDelta/*Q15,perCycleDeltaDelta_e*/,shl(sub(add(k,1),i),tmp_e)/*Q0, tmp_e*/)/*Q0+16, perCycleDeltaDelta_e-tmp_e*/; /*calcultion of base for first iteration*/ + tmp32 = L_shl(tmp32,sub(perCycleDeltaDelta_e,tmp_e));/*Q16*/ + tmp32_a = L_sub(absPitchDiff,tmp32); + tmp32_b = L_lshl(L_deposit_l(fractionalLeft/*Q15*/),1)/*Q16*/; + cycleDelta32 = L_add(tmp32_a,tmp32_b);/*Q16*/ + cycleDelta32 = L_max(0, cycleDelta32); + + /* Make sure that the number of samples increases */ + IF (GT_32(L_deposit_h(roundedCycleDelta), cycleDelta32)) + { + iDeltaSamples[i] = roundedCycleDelta; + move16(); + roundedCycleDelta = extract_h(cycleDelta32); /* cycleDelta32 should never be < 0 here */ + iDeltaSamples[i-1] = roundedCycleDelta; + move16(); + + } + ELSE + { + roundedCycleDelta = extract_h(cycleDelta32); /* cycleDelta32 should never be < 0 here */ + iDeltaSamples[i] = roundedCycleDelta; + move16(); + } + /*fractionalLeft = cycleDelta-roundedCycleDelta = cycleDelta-(int)cycleDelta;*/ + fractionalLeft = lshr(extract_l(cycleDelta32),1); /*Q15*/ /* cycleDelta32 should never be < 0 here */ + nSamplesDeltaRemain = sub(nSamplesDeltaRemain,roundedCycleDelta); + } + iDeltaSamples[k+1] = s_max(0, nSamplesDeltaRemain); + move16(); + maxDeltaSamples = s_max(iDeltaSamples[k], iDeltaSamples[k+1]);/*Q0*/ + + /* Find the location of the minimum energy between the first two pulses */ + + /*iMinPos1 = T0+GetMinimumPosition(src_exc+T0, min(roundedPitchStart, (nSubframes+1)*nFrameLength/nSubframes-T0), maxDeltaSamples);*/ + BASOP_Util_Divide_MantExp(add(nSubframes,1),15,nSubframes,15,&tmp16,&tmp_e); + tmp32 = L_mult(nFrameLength/*Q0*/,tmp16/*Q15,tmp_e*/);/*Q16,tmp_e*/ + tmp16 = round_fx(L_shl(tmp32,tmp_e)); + tmp16 = sub(tmp16,T0); + tmp16 = s_min(roundedPitchStart,tmp16); + + iMinPos1 = GetMinimumPosition( + src_exc+T0, /*Qx*/ + tmp16, /*Q0*/ + maxDeltaSamples /*Q0*/ + ); + iMinPos1 = add(iMinPos1,T0); + + + IF (nSamplesDelta < 0) + { + /* Find the location of the minimum energy before the first pulse */ + + IF (GT_16(iMinPos1 , add(roundedPitchStart , shr(iDeltaSamples[0],1)))) + { + iMinPos[0] = sub(iMinPos1 , sub(roundedPitchStart , shr(iDeltaSamples[0],1))); + move16(); + } + ELSE + { + move16(); + iMinPos[0] = sub(GetMinimumPosition(src_exc, T0, iDeltaSamples[0]) , shr(iDeltaSamples[0],1)); + } + + /* Find the location of the minimum energy between the pulses */ + FOR (i = 1; i <= k; i++) + { + move16(); + iMinPos[i] = add(iMinPos1 , sub(imult1616(sub(i,1),roundedPitchStart) , shr(iDeltaSamples[i],1))); + } + /* Find the location of the minimum energy after the last pulse */ + + IF (LT_16(add(iMinPos1 , add(imult1616(k,roundedPitchStart) , sub(iDeltaSamples[k+1] , shr(iDeltaSamples[k+1],1)))) , sub(nFrameLength,nSamplesDelta) )) + { + move16(); + iMinPos[k+1] = add(iMinPos1 , sub(imult1616(k,roundedPitchStart) , shr(iDeltaSamples[k+1],1))); + } + ELSE + { + /*iMinPos[k+1] = T0+k*roundedPitchStart + + GetMinimumPosition(src_exc+T0+k*roundedPitchStart, nFrameLength-nSamplesDelta-(T0+k*roundedPitchStart), iDeltaSamples[k+1]) + - iDeltaSamples[k+1]/2; */ + tmp16 = GetMinimumPosition(src_exc+T0+k*roundedPitchStart, sub(nFrameLength,add(nSamplesDelta,add(T0,imult1616(k,roundedPitchStart)))), iDeltaSamples[k+1]); + tmp16 = add(add(T0,imult1616(k,roundedPitchStart)),tmp16); + tmp16 = sub(tmp16,shr(iDeltaSamples[k+1],1)); + iMinPos[k+1] = tmp16; + move16(); + } + + IF (GT_16(add(iMinPos[k+1],iDeltaSamples[k+1]) , sub(nFrameLength,nSamplesDelta))) + { + iDeltaSamples[k] += add(iMinPos[k+1] , sub(iDeltaSamples[k+1] , sub(nFrameLength,nSamplesDelta))); + iDeltaSamples[k+1] = sub(nFrameLength , add(nSamplesDelta , iMinPos[k+1])); + } + + /* Remove samples at the given positions */ + RemoveSamples(src_exc, dst_exc, nFrameLength, nSamplesDelta, iMinPos, iDeltaSamples, k+2); + } + ELSE + { + /* Find the location of the minimum energy before the first pulse */ + IF (GT_16(iMinPos1 , roundedPitchStart)) + { + iMinPos[0] = sub(iMinPos1 , roundedPitchStart); + move16(); + } + ELSE + { + iMinPos[0] = GetMinimumPosition(src_exc, T0, iDeltaSamples[0]); + move16(); + } + /* Find the location of the minimum energy between the pulses */ + + FOR (i = 1; i <= k; i++) + { + iMinPos[i] = iMinPos1; + move16(); + iMinPos1 = add(iMinPos1,roundedPitchStart); + } + + /* Find the location of the minimum energy after the last pulse */ + IF (LT_16(iMinPos1 , sub(nFrameLength,nSamplesDelta))) + { + iMinPos[k+1] = iMinPos1; + move16(); + } + ELSE + { + + tmp16 = GetMinimumPosition(src_exc+T0+k*roundedPitchStart, sub(nFrameLength,add(nSamplesDelta,add(T0,imult1616(k,roundedPitchStart)))), iDeltaSamples[k+1]); + tmp16 = add(add(tmp16,T0),imult1616(k,roundedPitchStart)); + iMinPos[k+1] = tmp16; + move16(); + } + + IF (GT_16(add(iMinPos[k+1],iDeltaSamples[k+1]) , sub(nFrameLength,nSamplesDelta))) + { + move16(); + move16(); + iDeltaSamples[k] = add(iDeltaSamples[k] , add(iMinPos[k+1] , sub(iDeltaSamples[k+1] , sub(nFrameLength,nSamplesDelta)))); + iDeltaSamples[k+1] = sub(sub(nFrameLength, nSamplesDelta),iMinPos[k+1]); + } + /* Add samples at the given positions */ + AddSamples(src_exc, dst_exc, nFrameLength, nSamplesDelta, iMinPos, iDeltaSamples, k+2); + } + } + +} + diff --git a/lib_dec/er_util.c b/lib_dec/er_util.c new file mode 100644 index 0000000..3cfa51d --- /dev/null +++ b/lib_dec/er_util.c @@ -0,0 +1,474 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include "options.h" +#include "stl.h" +#include "prot_fx.h" +#include "basop_util.h" +#include + + +#define MODE_DECISION_BASED_ON_PEAK_DETECTION + + +/* static void setnoiseLevelMemory() + * + * Helper function - updates buffer for minimumStatistics function + */ +static void setnoiseLevelMemory(Word16 f, Word16* new_noiseEstimate_e, Word16* noiseLevelMemory_e, Word16* noiseLevelMemory, Word16* currLevelIndex) +{ + noiseLevelMemory[*currLevelIndex] = f; + move16(); + noiseLevelMemory_e[*currLevelIndex] = *new_noiseEstimate_e; + move16(); +} + + +/* PLC: [Common: Fade-out] + * PLC: and for PLC fade out */ + +void minimumStatistics(Word16* noiseLevelMemory, /* Qx, internal state */ + Word16* noiseLevelIndex, /* Q0, internal state */ + Word16* currLevelIndex, /* Q0, internal state (circular buffer) */ + Word16* noiseEstimate, /* Qx, previous estimate of background noise */ + Word16* lastFrameLevel, /* Qx, level of the last frame */ + Word16 currentFrameLevel, /* Qx, level of the current frame */ + Word16* noiseLevelMemory_e, /* scaling factor for noiseLevelMemory */ + Word16 const noiseEstimate_e, /* exponent of noiseEstimate */ + Word16* new_noiseEstimate_e, /* new exponent of noise Estimate*/ + Word16* const lastFrameLevel_e, /* exponent of lastFrameLevel */ + Word16 currentFrameLevel_e) /* exponent of currentFrameLevel */ +{ + Word16 aOpt, aOpt_e; + Word16 f, p, i; + Word16 tmp,tmp2, tmp_e; + Word32 tmp32; + move16(); + aOpt_e = 0; + + + BASOP_SATURATE_WARNING_OFF + IF (LT_16(shl(currentFrameLevel, currentFrameLevel_e),PLC_MIN_CNG_LEV)) + { + BASOP_SATURATE_WARNING_ON + currentFrameLevel = PLC_MIN_CNG_LEV; + move16(); + move16(); + currentFrameLevel_e = 0; + } + BASOP_SATURATE_WARNING_ON + + /* compute optimal factor aOpt for recursive smoothing of frame minima */ + tmp2 = BASOP_Util_Add_MantExp(*lastFrameLevel,*lastFrameLevel_e,negate(*noiseEstimate),noiseEstimate_e,&tmp); + IF (tmp >= 0) + { + /* aOpt = *noiseEstimate / *lastFrameLevel; */ + aOpt = BASOP_Util_Divide1616_Scale(*noiseEstimate, *lastFrameLevel, &aOpt_e); + aOpt_e = add(aOpt_e, sub(noiseEstimate_e, *lastFrameLevel_e)); + } + ELSE + { + /* aOpt = *lastFrameLevel / *noiseEstimate; */ + aOpt = BASOP_Util_Divide1616_Scale(*lastFrameLevel, *noiseEstimate, &aOpt_e); + aOpt_e = add(aOpt_e, sub(*lastFrameLevel_e, noiseEstimate_e)); + } + aOpt = mult_r(aOpt, aOpt); /* Q15 */ + aOpt_e = shl(aOpt_e,1); + if (aOpt == 0) + { + move16(); + aOpt_e = 0; + } + + *lastFrameLevel = currentFrameLevel; + move16(); + move16(); + *lastFrameLevel_e = currentFrameLevel_e; + + /* recursively compute smoothed frame minima using optimal factor aOpt */ + tmp = *currLevelIndex; + move16(); + move16(); + if (tmp == 0) + { + tmp = PLC_MIN_STAT_BUFF_SIZE; + move16(); + + } + /*f = msu_r(L_mult(aOpt, noiseLevelMemory[sub(tmp, 1)]), add(aOpt, 0x8000), currentFrameLevel);*/ + /*f = (aOpt * noiseLevelMemory[tmp-1]) - (currentFrameLevel * (aOpt-1))*/ + /*tmp32*/ /*tmp*/ + + tmp32 = L_mult(aOpt,noiseLevelMemory[tmp-1]); /*Q_tmp32 = aOpt_e + noiseLevelMemory_e[tmp - 1]*/ + move16(); + tmp_e = tmp; + + + tmp2 = BASOP_Util_Add_MantExp(aOpt,aOpt_e,negate(32768/2),1,&tmp); + tmp = mult_r(tmp,currentFrameLevel); /*Q_tmp = tmp2 + currentFrameLevel_e*/ + tmp2 = add(tmp2,currentFrameLevel_e); + + *new_noiseEstimate_e = BASOP_Util_Add_MantExp(round_fx(tmp32),add(aOpt_e,noiseLevelMemory_e[tmp_e - 1]),negate(s_max(tmp,-32767)/*to avoid negate(-32768)*/),tmp2,&f); + + assert(f >= 0); + + /* if current frame min is a new local min, set index to current index */ + p = *noiseLevelIndex; + move16(); + tmp2 = BASOP_Util_Add_MantExp(noiseLevelMemory[p],noiseLevelMemory_e[p],negate(f),*new_noiseEstimate_e,&tmp); + IF (tmp >= 0) + { + + /*rescale noiseLevelMemory*/ + + setnoiseLevelMemory(f,new_noiseEstimate_e,noiseLevelMemory_e, noiseLevelMemory, currLevelIndex); + p = *currLevelIndex; + move16(); + } + ELSE + { + move16(); + + setnoiseLevelMemory(f,new_noiseEstimate_e, noiseLevelMemory_e, noiseLevelMemory, currLevelIndex); + + /* current min is not a new min, so check if min must be re-searched */ + IF (NE_16(p, *currLevelIndex)) + { + f = noiseLevelMemory[p]; /* min is still in memory, so return it */ + move16(); + *new_noiseEstimate_e = noiseLevelMemory_e[p]; + } + ELSE { + /* p == currLevelIndex; min was removed from memory, re-search min */ + FOR (i = 0; i < PLC_MIN_STAT_BUFF_SIZE; i++) + { + tmp2 = BASOP_Util_Add_MantExp(noiseLevelMemory[p],noiseLevelMemory_e[p],negate(noiseLevelMemory[i]),noiseLevelMemory_e[i],&tmp); + if ( tmp > 0) + { + p = i; + move16(); + } + } + f = noiseLevelMemory[p]; + move16(); + *new_noiseEstimate_e = noiseLevelMemory_e[p]; + } + } + + /* update local-minimum-value index and current circular-buffer index */ + *noiseLevelIndex = p; + move16(); + p = add(*currLevelIndex,1); + *currLevelIndex = add(*currLevelIndex, 1); + move16(); + if (EQ_16(*currLevelIndex, PLC_MIN_STAT_BUFF_SIZE)) + { + *currLevelIndex = 0; + move16(); + } + + *noiseEstimate = f; + move16(); +} + +/*----------------------------------------------------------------------* + * PLC: [ACELP: Fade-out] + * PLC: getLevelSynDeemph: derives on frame or subframe basis the level + * of LPC synthesis and deeemphasis based on the given input + *----------------------------------------------------------------------*/ +Word16 getLevelSynDeemph( /*10Q5*/ + Word16 h1Init[], /* i: input value or vector to be processed */ /* Q15 */ + Word16 const A[], /* i: LPC coefficients */ /* Qx */ + Word16 const lpcorder, /* i: LPC order */ /* Q0 */ + Word16 const lenLpcExc, /* i: length of the LPC excitation buffer */ /* Q0 */ + Word16 const preemph_fac, /* i: preemphasis factor */ /* Q15 */ + Word16 const numLoops, /* i: number of loops */ /* Q0 */ + Word16 *Exp /* o: exponent of return value Q15 */ +) +{ + Word32 levelSynDeemphSub; + Word32 levelSynDeemph ; + Word16 h1[L_FRAME_PLUS/4]; /*Q15*/ + Word16 mem[M]; + Word16 tmp; + Word16 loop; + Word16 s16, tmp16, Hr16; + Word16 Q_h1; + + + levelSynDeemphSub = L_deposit_l(0); + levelSynDeemph = L_deposit_l(0); + tmp = 0; + Q_h1 = 9; /*synthesis scaling for */ move16(); + + /*calculate headroom for dotproduct*/ + Hr16 = sub(15,norm_s(lenLpcExc)); + + Q_h1 = s_max(sub(Q_h1,Hr16),0); /*compensate synthesis scaling with Headroom as much as possible to retain as much precision as possible*/ + + /*Factor to be multiplied in order to calculate dotproduct with headroom*/ + tmp16 = shr(32768/2,sub(Hr16,1)); + + /*moved from inside loop, before synthesis*/ + h1Init[0] = mult_r(h1Init[0],tmp16); + move16(); + + FOR (loop = 0; loop < numLoops; loop++) + { + set16_fx(h1, 0, lenLpcExc); + set16_fx(mem, 0, lpcorder); + + Copy(h1Init, h1, 1); + /*h1 will be scaled down, Q_h1 */ + E_UTIL_synthesis(Q_h1, A, h1, h1, lenLpcExc, mem, 0, lpcorder); + deemph_fx(h1, preemph_fac, lenLpcExc, &tmp); + A += (M+1); + + /* gain introduced by synthesis+deemphasis */ + /*levelSynDeemphSub = (float)sqrt(dot_product( h1, h1, lenLpcExc));*/ + levelSynDeemphSub = Dot_product12_offs(h1, h1, lenLpcExc, &s16, 0); + s16 = sub(shl(add(Q_h1,Hr16),1), sub(30, s16)); + + levelSynDeemphSub = Sqrt32(levelSynDeemphSub,&s16); /*Q31*/ + + /* mean of the above across all subframes -- moved outta loop*/ + /*levelSynDeemph += (1.0/(float)numLoops) * levelSynDeemphSub;*/ + tmp16 = 32767/*1.0f Q15*/; + move16(); + + if (GT_16(numLoops , 1)) + { + tmp16 = div_s(1,numLoops); + } + + levelSynDeemph = L_add(levelSynDeemph , L_shl(Mpy_32_16_1(levelSynDeemphSub,tmp16),sub(s16,10))); /*10Q21*/ + + } + s16 = norm_l(levelSynDeemph); + levelSynDeemph = L_shl(levelSynDeemph, s16); + move16(); + *Exp = sub(10,s16); /*Set exponent in order to transform returnvalue to Q15*/ + + return round_fx(levelSynDeemph); /*Q15*/ +} + +/* BASOP version: up to date with rev 7422 */ +void genPlcFiltBWAdap(const Word32 sr_core, Word16 *lpFiltAdapt, const Word16 type, const Word16 alpha + ) +{ + Word16 a, b, exp; + + + assert(type == 0 || type == 1); + + IF ( EQ_32(sr_core, 16000)) + { + IF (type == 0) + { + move16(); + move16(); + move16(); + *lpFiltAdapt++ = 7282/* 0.4000f/(2.f*0.4000f+1.f) Q15*/; + *lpFiltAdapt++ = 18204/* 1.f/(2.f*0.4000f+1.f) Q15*/; + *lpFiltAdapt = 7282/* 0.4000f/(2.f*0.4000f+1.f) Q15*/; + } + ELSE + { + a = mult_r(13107/*0.4000f Q15*/, alpha); + exp = 0; + move16(); + b = Inv16(add(a, 16384/*0.5f Q15*/), &exp); + b = shr(b, sub(1, exp)); + a = negate(mult_r(a, b)); + move16(); + move16(); + move16(); + *lpFiltAdapt++ = a; + *lpFiltAdapt++ = b; + *lpFiltAdapt = a; + } + } + ELSE + { + IF (type == 0) + { + move16(); + move16(); + move16(); + *lpFiltAdapt++ = 5899/* 0.2813f/(2.f*0.2813f+1.f) Q15*/; + *lpFiltAdapt++ = 20970/* 1.f/(2.f*0.2813f+1.f) Q15*/; + *lpFiltAdapt = 5899/* 0.2813f/(2.f*0.2813f+1.f) Q15*/; + } + ELSE { + a = mult_r(9218/*0.2813f Q15*/, alpha); + exp = 0; + move16(); + b = Inv16(add(a, 16384/*0.5f Q15*/), &exp); + b = shr(b, sub(1, exp)); + a = negate(mult_r(a, b)); + move16(); + move16(); + move16(); + *lpFiltAdapt++ = a; + *lpFiltAdapt++ = b; + *lpFiltAdapt = a; + } + } + +} + + +/*-----------------------------------------------------------------* + * PLC: [ACELP: general] + * PLC: high pass filtering + *-----------------------------------------------------------------*/ +/*VERSIONINFO: This port is up to date with trunk rev. 32434*/ +void highPassFiltering( + const Word16 last_good, /* i: short last classification type */ + const Word16 L_buffer, /* i: int buffer length */ + Word16 exc2[], /* i/o: Qx unvoiced excitation before the high pass filtering */ + const Word16 hp_filt[], /* i: Q15 high pass filter coefficients */ + const Word16 l_fir_fer) /* i: high pass filter length */ + +{ + Word16 i; /*int*/ + + IF( GT_16(last_good , UNVOICED_TRANSITION)) + { + + FOR( i=0 ; i< L_buffer; i++ ) + { + exc2[i] = round_fx(L_sub(Dot_product(&exc2[i], hp_filt, l_fir_fer), 1)); + } + } +} + +/*----------------------------------------------------------------------------------* + * PLC: [Common: mode decision] + * PLC: Decide which Concealment to use. Update pitch lags if needed + *----------------------------------------------------------------------------------*/ +Word16 GetPLCModeDecision( + Decoder_State_fx *st /* i/o: decoder memory state pointer */ +) +{ + Word16 /*int*/ core; + Word16 numIndices = 0; + + + IF( EQ_16(st->flagGuidedAcelp,1)) + { + st->old_pitch_buf_fx[2*st->nb_subfr] = L_deposit_h(st->guidedT0); + st->old_pitch_buf_fx[2*st->nb_subfr+1] = L_deposit_h(st->guidedT0); + st->mem_pitch_gain[0] = st->mem_pitch_gain[1] = 16384/*1.f Q14*/;/*Q14*/ + } + st->plc_use_future_lag = 0; + move16(); + test(); + test(); + if(( st->last_core_fx > ACELP_CORE && st->tcxltp_last_gain_unmodified!=0 ) + || ( EQ_16(st->flagGuidedAcelp,1) ) + ) + { + /* no updates needed here, because already updated in last good frame */ + st->plc_use_future_lag = 1; + move16(); + } + + IF (EQ_16(st->last_core_fx,-1)) + { + core = TCX_20_CORE; + move16(); + st->last_core_fx = ACELP_CORE; + move16(); + if(st->Opt_AMR_WB_fx) + { + core = ACELP_CORE; + move16(); + } + st->tonal_mdct_plc_active = 0; + move16(); + } + ELSE + { + core = ACELP_CORE; + move16(); + if (GT_16(st->nbLostCmpt,1)) + { + core = st->last_core_bfi; + move16(); + } + IF (EQ_16(st->nbLostCmpt,1)) + { + st->tonal_mdct_plc_active = 0; + move16(); + test(); + test(); + test(); + IF ( !(st->rf_flag && st->use_partial_copy && (EQ_16(st->rf_frame_type, RF_TCXTD1)||EQ_16(st->rf_frame_type,RF_TCXTD2)))) + { + test(); + test(); + test(); + test(); + test(); + test(); + IF ((EQ_16(st->last_core_fx,TCX_20_CORE))&&(EQ_16(st->second_last_core,TCX_20_CORE)) + && ((LE_32(st->old_fpitch,L_deposit_h(shr(st->L_frame_fx,1)))) + || (LE_16(st->tcxltp_last_gain_unmodified,13107/*0.4f Q15*/))) + /* it is fine to call the detection even if no ltp information + is available, meaning that st->old_fpitch == + st->tcxltp_second_last_pitch == st->L_frame */ + && (EQ_32(st->old_fpitch, st->tcxltp_second_last_pitch)) + && !st->last_tns_active && !st->second_last_tns_active) + { + Word32 pitch; + + + pitch = L_deposit_h(0); + if(st->tcxltp_last_gain_unmodified > 0) + { + pitch = L_add(st->old_fpitch, 0); + } + TonalMDCTConceal_Detect(&st->tonalMDCTconceal, + pitch, + &numIndices); + + test(); + test(); + test(); + test(); + test(); + test(); + IF ((GT_16(numIndices,10)) + || ((GT_16(numIndices,5) ) + && (LT_32(L_abs(L_sub(st->tcxltp_third_last_pitch,st->tcxltp_second_last_pitch)),32768l/*0.5f Q16*/) )) + || ((numIndices > 0) && ((LE_16(st->last_good_fx,UNVOICED_TRANSITION))||(LE_16(st->tcxltp_last_gain_unmodified,13107/*0.4f Q15*/))) + && (LT_32(L_abs(L_sub(st->tcxltp_third_last_pitch,st->tcxltp_second_last_pitch)),32768l/*0.5f Q16*/) ))) + { + core = TCX_20_CORE; + move16(); + st->tonal_mdct_plc_active = 1; + move16(); + } + ELSE IF (LE_16(st->last_good_fx,UNVOICED_TRANSITION)||LE_16(st->tcxltp_last_gain_unmodified,13107/*0.4f Q15*/)) + { + core = TCX_20_CORE; + move16(); + } + } + ELSE IF (st->last_core_fx != ACELP_CORE) + { + test(); + if (LE_16(st->last_good_fx,UNVOICED_TRANSITION)||LE_16(st->tcxltp_last_gain_unmodified,13107/*0.4f Q15*/)) + { + core = st->last_core_fx; + move16(); + } + } + } + } + } + return core; +} diff --git a/lib_dec/evs_dec_fx.c b/lib_dec/evs_dec_fx.c new file mode 100644 index 0000000..414b927 --- /dev/null +++ b/lib_dec/evs_dec_fx.c @@ -0,0 +1,1508 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "basop_util.h" /* Function prototypes */ +#include "stl.h" /* required for wmc_tool */ + +#include /* Debug prototypes */ + +/*--------------------------------------------------------------------------* + * evs_dec() + * + * Principal decoder routine + *--------------------------------------------------------------------------*/ + +void evs_dec_fx( + Decoder_State_fx *st_fx, /* i/o : Decoder state structure */ + Word16 output_sp[], /* o : output synthesis signal */ + frameMode_fx frameMode /* i : Decoder frame mode */ +) +{ + Word16 i, j, output_frame, coder_type; + Word16 sharpFlag; + Word16 tmps, incr; + Word16 core_switching_flag; + Word16 unbits; + Word16 hq_core_type; + Word16 post_hq_delay; + Word32 bwe_exc_extended_fx[L_FRAME32k+NL_BUFF_OFFSET]; + Word16 voice_factors_fx[NB_SUBFR16k]; + Word16 hb_synth_fx[L_FRAME48k]; + Word16 hb_synth_fx_exp; + Word32 L_tmp; + Word16 exp,fra; + Word16 tmp_buffer_fx[L_FRAME48k]; + Word16 tmp16,tmp16_2; + Word16 synth_fx[L_FRAME48k + HQ_DELTA_MAX*HQ_DELAY_COMP]; + Word16 fb_exc_fx[L_FRAME16k]; + Word16 pitch_buf_fx[NB_SUBFR16k]; + Word16 Q_fb_exc; + Word16 old_syn_12k8_16k_fx[L_FRAME16k]; + Word16 sid_bw=-1; + Word16 pcmbufFB[L_FRAME_MAX]; + Word32 workBuffer[128*3]; + Word16 delta; + Word16 nab; + Word16 concealWholeFrame; + Word16 concealWholeFrameTmp = -1; + Word16 delay_comp, delay_tdbwe; + + Word16 Qpostd; + Word16 Q_synth; + Word16 Qpostd_prev; + + Word32 *realBuffer[CLDFB_NO_COL_MAX], *imagBuffer[CLDFB_NO_COL_MAX]; + Word32 realBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], imagBufferTmp[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word16 timeIn_e; + + timeIn_e = 0; + move16(); + + delay_tdbwe = 0; /* for compiler warning*/ + Qpostd = 0; + move16(); /* default and used for MODE2 */ + concealWholeFrame = -1; + move16(); + + /*------------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + FOR( i=0; ibfi_fx == 0 ) + { + st_fx->extl_fx = -1; + move16(); + } + + output_frame = st_fx->output_frame_fx; + move16(); + + core_switching_flag = 0; + move16(); + sharpFlag = 0; + move16(); + unbits = 0; + move16(); + + st_fx->use_partial_copy = 0; + move16(); + st_fx->rf_flag = 0; + move16(); + + Qpostd_prev = st_fx->Qprev_synth_buffer_fx; + move16(); + + IF( EQ_16(st_fx->bfi_fx,1)) + { + hq_core_type = st_fx->last_hq_core_type_fx; + move16(); + coder_type = st_fx->last_coder_type_fx; + move16(); + } + ELSE + { + hq_core_type = -1; + move16(); + coder_type = INACTIVE; + move16(); + } + + + /* PLC: [TCX: Fade-out-recovery] + * PLC: overlapping part needs to be attenuated for first good frame */ test(); + test(); + test(); + test(); + IF (!st_fx->bfi_fx + && st_fx->prev_bfi_fx + && (EQ_16(st_fx->last_codec_mode, MODE2) ) + && (EQ_16(st_fx->last_core_bfi, TCX_20_CORE) + || EQ_16(st_fx->last_core_bfi, TCX_10_CORE) )) + { + /* v_multc(st_fx->old_out_fx, st_fx->plcInfo.recovery_gain, */ + /* st_fx->old_out_fx, st_fx->L_frameTCX); */ + FOR( i = 0; i < st_fx->L_frameTCX; i++ ) + { + st_fx->old_out_fx[i] = shl(mult_r(st_fx->old_out_fx[i] , st_fx->plcInfo.recovery_gain), 1); + } + FOR( i = 0; i < st_fx->L_frame_fx; i++ ) + { + st_fx->old_out_LB_fx[i] = shl(mult_r(st_fx->old_out_LB_fx[i], st_fx->plcInfo.recovery_gain), 1); + } + /* attenuate PLC buffers, if no aldo window + is used and if no sid or zero frame is received */ + IF ( 0 == st_fx->tcx_cfg.last_aldo ) + { + Word32 f; + Word16 s; + Word16 tmp1; + f = L_deposit_l(st_fx->conceal_eof_gain); /*Q14*/ + s = norm_l(f); + s = sub(16,s); + tmp1 = extract_l(L_shr_r(f,s)); + FOR( i=0; i < st_fx->tcx_cfg.tcx_mdct_window_lengthFB; i++ ) + { + + st_fx->syn_OverlFB[i] = shl(mult(tmp1,st_fx->syn_OverlFB[i]), add(s,1)); + move16(); + + } + s = norm_l(f); + s = sub(16,s); + tmp1 = extract_l(L_shr_r(f,s)); + FOR( i=0; i < st_fx->tcx_cfg.tcx_mdct_window_length; i++ ) + { + st_fx->syn_Overl[i] = shl(mult(tmp1,st_fx->syn_Overl[i]),s); + move16(); + } + } + } + + set16_fx( voice_factors_fx, 0, NB_SUBFR16k ); + set16_fx( hb_synth_fx, 0, L_FRAME48k ); + hb_synth_fx_exp = 0; + move16(); + + st_fx->rate_switching_reset = 0; + move16(); + + if(!st_fx->bfi_fx) + { + st_fx->flagGuidedAcelp = 0; + } + + /*----------------------------------------------------------------* + * Updates in case of AMR-WB IO mode -> EVS primary switching + *----------------------------------------------------------------*/ + + IF( EQ_16(st_fx->last_core_fx,AMR_WB_CORE)) + { + updt_IO_switch_dec_fx( output_frame, st_fx ); + } + + IF( NE_16(frameMode,FRAMEMODE_MISSING)) /* frame mode normal or future frame */ + { + getPartialCopyInfo(st_fx, &coder_type, &sharpFlag); + + frameMode = st_fx->bfi_fx; + } + + test(); + IF( EQ_16(st_fx->rf_frame_type,RF_NO_DATA)&&EQ_16(st_fx->use_partial_copy,1)) + { + /* the partial copy is a RF FRAME_NO_DATA frame and should follow the concealment path*/ + st_fx->bfi_fx = 1; + move16(); + st_fx->codec_mode = st_fx->last_codec_mode; + move16(); + frameMode = FRAMEMODE_MISSING; + move16(); + st_fx->use_partial_copy = 0; + move16(); + } + + /* if previous frame was concealed via ACELP, drop TCX partial copy info and continue ACELP concealment */ + test(); + test(); + test(); + IF( EQ_16(st_fx->use_partial_copy,1)&&EQ_16(st_fx->core_fx,TCX_20_CORE)&& + EQ_16(st_fx->prev_bfi_fx,1) && EQ_16(st_fx->last_core_fx,ACELP_CORE) ) + { + st_fx->bfi_fx = 1; + move16(); + st_fx->codec_mode = st_fx->last_codec_mode; + move16(); + frameMode = FRAMEMODE_MISSING; + move16(); + st_fx->use_partial_copy = 0; + move16(); + st_fx->core_fx = ACELP_CORE; + move16(); + } + + /* if previous frame was HQ Core or TCX10, drop partial copy info and continue HQ Core/TCX10 concealment */ + IF( st_fx->use_partial_copy && ((sub(st_fx->last_core_fx, HQ_CORE) == 0) || (sub(st_fx->last_core_fx, TCX_10_CORE) == 0) || ((sub(st_fx->last_core_fx, TCX_20_CORE) == 0) && getTcxonly(st_fx->last_total_brate_fx))) ) + { + st_fx->bfi_fx = 1; + move16(); + st_fx->codec_mode = st_fx->last_codec_mode; + move16(); + frameMode = FRAMEMODE_MISSING; + move16(); + st_fx->use_partial_copy = 0; + move16(); + st_fx->core_fx = st_fx->last_core_fx; + move16(); + } + + /*------------------------------------------------------------------* + * Decoding + *-----------------------------------------------------------------*/ + + IF( EQ_16(st_fx->codec_mode,MODE1)) + { + /*------------------------------------------------------------------* + * Decision matrix (selection of technologies) + *-----------------------------------------------------------------*/ + + IF ( NE_16(st_fx->bfi_fx,1)) + { + decision_matrix_dec_fx( st_fx, &coder_type, &sharpFlag, &hq_core_type, &core_switching_flag ); + + IF( NE_16(st_fx->bfi_fx,1)) + { + st_fx->sr_core = i_mult(st_fx->L_frame_fx,50); + st_fx->fscale_old = st_fx->fscale; + st_fx->fscale = sr2fscale(st_fx->sr_core); + } + ELSE + { + frameMode = FRAMEMODE_MISSING; + move16(); + } + } + } + + IF( EQ_16(st_fx->codec_mode,MODE1)) + { + /*------------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + IF( EQ_16(st_fx->bfi_fx,1)) + { + st_fx->nbLostCmpt = add(st_fx->nbLostCmpt,1); + } + ELSE + { + st_fx->nbLostCmpt = 0; + move16(); + } + st_fx->enablePlcWaveadjust = 0; + move16(); + + /*---------------------------------------------------------------------* + * Detect bandwidth switching + *---------------------------------------------------------------------*/ + + bandwidth_switching_detect_fx(st_fx); + + /*---------------------------------------------------------------------* + * Preprocessing (preparing) for ACELP/HQ core switching + *---------------------------------------------------------------------*/ + + core_switching_pre_dec_fx( st_fx, output_frame ); + + /*---------------------------------------------------------------------* + * ACELP core decoding + * HQ core decoding + *---------------------------------------------------------------------*/ + IF ( EQ_16(st_fx->core_fx,ACELP_CORE)) + { + /* ACELP core decoder */ + acelp_core_dec_fx( st_fx, synth_fx, bwe_exc_extended_fx, voice_factors_fx, old_syn_12k8_16k_fx, coder_type, sharpFlag, pitch_buf_fx, &unbits, &sid_bw ); + Qpostd = st_fx->Q_syn2; + move16(); + } + ELSE + { + hq_core_dec_fx( st_fx, synth_fx, &Q_synth, output_frame, hq_core_type, core_switching_flag ); + Qpostd = Q_synth; + move16(); + } + + /*---------------------------------------------------------------------* + * Postprocessing for ACELP/HQ core switching + *---------------------------------------------------------------------*/ + + core_switching_post_dec_fx( st_fx, synth_fx, output_frame, core_switching_flag, coder_type, &Qpostd ); + + /*---------------------------------------------------------------------* + * Pre-processing for bandwidth switching + *---------------------------------------------------------------------*/ + + bw_switching_pre_proc_fx( old_syn_12k8_16k_fx, st_fx ); + + /*---------------------------------------------------------------------* + * WB TBE decoding + * WB BWE decoding + *---------------------------------------------------------------------*/ + + IF ( EQ_16(st_fx->extl_fx,WB_TBE)) + { + /* WB TBE decoder */ + wb_tbe_dec_fx( st_fx, coder_type, bwe_exc_extended_fx, st_fx->Q_exc, voice_factors_fx, hb_synth_fx, &hb_synth_fx_exp ); + } + ELSE IF ( EQ_16(st_fx->extl_fx,WB_BWE)&&st_fx->bws_cnt_fx==0) + { + /* WB BWE decoder */ + hb_synth_fx_exp = wb_bwe_dec_fx( synth_fx, hb_synth_fx, output_frame, coder_type, voice_factors_fx, pitch_buf_fx, st_fx, &Qpostd ); + } + + /*---------------------------------------------------------------------* + * SWB TBE decoding + * SWB BWE decoding + * FB TBE decoding + *---------------------------------------------------------------------*/ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF ( EQ_16(st_fx->extl_fx,SWB_TBE)||EQ_16(st_fx->extl_fx,FB_TBE) + || (NE_16(coder_type,AUDIO) && NE_16(coder_type,INACTIVE) && GT_32(st_fx->core_brate_fx,SID_2k40) && EQ_16(st_fx->core_fx,ACELP_CORE) + && GE_32(st_fx->output_Fs_fx,32000) && GT_16(st_fx->bwidth_fx,NB) && st_fx->bws_cnt_fx > 0 && !st_fx->ppp_mode_dec_fx + && !( EQ_16( st_fx->nelp_mode_dec_fx, 1) && EQ_16( st_fx->bfi_fx, 1) ) ) ) + + { + swb_tbe_dec_fx( st_fx, coder_type, bwe_exc_extended_fx, st_fx->Q_exc, voice_factors_fx, + old_syn_12k8_16k_fx, fb_exc_fx, &Q_fb_exc, hb_synth_fx, &hb_synth_fx_exp, pitch_buf_fx ); + + /* FB TBE decoder/synthesis */ + test(); + IF ( EQ_16(output_frame,L_FRAME48k)&&EQ_16(st_fx->extl_fx,FB_TBE)) + { + fb_tbe_dec_fx( st_fx, fb_exc_fx, Q_fb_exc, hb_synth_fx, hb_synth_fx_exp); + } + } + ELSE IF( EQ_16(st_fx->extl_fx,SWB_BWE)||EQ_16(st_fx->extl_fx,FB_BWE)|| + (GE_32(st_fx->output_Fs_fx,32000) && EQ_16(st_fx->core_fx,ACELP_CORE) && GT_16(st_fx->bwidth_fx,NB) && st_fx->bws_cnt_fx > 0 && !st_fx->ppp_mode_dec_fx + && !( EQ_16( st_fx->nelp_mode_dec_fx, 1) && EQ_16( st_fx->bfi_fx, 1) ) ) ) + { + /* SWB BWE decoder */ + hb_synth_fx_exp = swb_bwe_dec_fx( st_fx, synth_fx, hb_synth_fx, output_frame, &Qpostd, coder_type ); + } + ELSE IF( EQ_16(st_fx->extl_fx,SWB_BWE_HIGHRATE)||EQ_16(st_fx->extl_fx,FB_BWE_HIGHRATE)) + { + hb_synth_fx_exp = swb_bwe_dec_hr_fx( st_fx, old_syn_12k8_16k_fx, Qpostd, hb_synth_fx, output_frame, unbits, pitch_buf_fx ); + } + + /*---------------------------------------------------------------------* + * FEC - recovery after lost HQ core (smoothing of the BWE component) + *---------------------------------------------------------------------*/ + + test(); + test(); + IF ( st_fx->prev_bfi_fx && EQ_16(st_fx->last_core_fx,HQ_CORE)&&NE_16(st_fx->extl_fx,-1)) + { + /*tmp = FRAC_BWE_SMOOTH/output_frame;*/ + tmp16 = shr(410,shr(output_frame,8)); + if(EQ_16(output_frame, L_FRAME48k)) + { + tmp16 = 68; + move16(); + } + /*output_frame/FRAC_BWE_SMOOTH*/ + j = shr(output_frame,1); + tmp16_2 = 0; + move16(); + FOR (i = 0; i < j; i++) + { + /*hb_synth[i] *= (i*tmp);*/ + hb_synth_fx[i] = mult_r(hb_synth_fx[i], tmp16_2); + move16(); + tmp16_2 = add(tmp16_2, tmp16); + } + } + + /*---------------------------------------------------------------------* + * SWB CNG + *---------------------------------------------------------------------*/ + IF( GE_16(output_frame,L_FRAME32k)) + { + /* SHB CNG decoder */ + swb_CNG_dec_fx( st_fx, synth_fx, hb_synth_fx, sid_bw, Qpostd ); + + test(); + if( LE_32(st_fx->core_brate_fx, SID_2k40)&&st_fx->bws_cnt_fx==0) + { + hb_synth_fx_exp = 3; + move16(); + } + } + + /*----------------------------------------------------------------* + * Delay ACELP core synthesis to be synchronized with the components of bandwidth extension layers + *----------------------------------------------------------------*/ + + IF ( GE_16(output_frame,L_FRAME16k)) + { + tmps = NS2SA_fx2(st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS); + + exp=s_min(Qpostd, st_fx->Qprev_synth_buffer_fx); + Scale_sig(synth_fx, output_frame, sub(exp,Qpostd)); + Qpostd=exp; + move16(); + Scale_sig(st_fx->prev_synth_buffer_fx, tmps, sub(exp, st_fx->Qprev_synth_buffer_fx)); + st_fx->Qprev_synth_buffer_fx=exp; + move16(); + Copy(synth_fx, tmp_buffer_fx, output_frame); + Copy(st_fx->prev_synth_buffer_fx, synth_fx, tmps); + Copy(tmp_buffer_fx, synth_fx + tmps, output_frame - tmps); + Copy(tmp_buffer_fx + output_frame - tmps, st_fx->prev_synth_buffer_fx, tmps); + } + ELSE + { + exp=s_min(Qpostd, st_fx->Qprev_synth_buffer_fx); + Scale_sig(synth_fx, output_frame, sub(exp,Qpostd)); + Qpostd=exp; + move16(); + st_fx->Qprev_synth_buffer_fx=exp; + move16(); + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF (EQ_16(st_fx->core_fx,ACELP_CORE) + && !st_fx->bfi_fx + && st_fx->prev_bfi_fx + && GE_32(st_fx->last_total_brate_fx, HQ_48k) + && EQ_16(st_fx->last_codec_mode, MODE2) + && (EQ_16(st_fx->last_core_bfi, TCX_20_CORE) || EQ_16(st_fx->last_core_bfi, TCX_10_CORE) ) + && st_fx->plcInfo.concealment_method == TCX_NONTONAL + && LT_32(st_fx->plcInfo.nbLostCmpt, 4) ) + { + tmps = 0; + IF( GE_16(output_frame,L_FRAME16k)) + { + tmps = NS2SA_fx2(st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS); + } + + waveform_adj2_fix(st_fx->tonalMDCTconceal.secondLastPcmOut, + synth_fx+tmps, + st_fx->plcInfo.data_noise, + &st_fx->plcInfo.outx_new_n1_fx, + &st_fx->plcInfo.nsapp_gain_fx, + &st_fx->plcInfo.nsapp_gain_n_fx, + &st_fx->plcInfo.recovery_gain, + st_fx->plcInfo.step_concealgain_fx, + st_fx->plcInfo.Pitch_fx, + st_fx->plcInfo.FrameSize, + tmps, + add(extract_l(st_fx->plcInfo.nbLostCmpt), 1), + st_fx->bfi_fx); + st_fx->plcInfo.Pitch_fx = 0; + } + + /*----------------------------------------------------------------* + * Addition of BWE components to the ACELP core synthesis + *----------------------------------------------------------------*/ + + test(); + test(); + IF ( NE_16(st_fx->extl_fx,-1)||(st_fx->bws_cnt_fx>0&&EQ_16(st_fx->core_fx,ACELP_CORE))) + { + /* Calculate an additional delay of extension layer components to be synchronized with ACELP synthesis */ + IF ( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + /* TBE on top of ACELP@12.8kHz */ + tmps = NS2SA_fx2( st_fx->output_Fs_fx, MAX_DELAY_TBE_NS - DELAY_SWB_TBE_12k8_NS ); + } + ELSE + { + test(); + IF( EQ_16(st_fx->extl_fx,SWB_BWE_HIGHRATE)||EQ_16(st_fx->extl_fx,FB_BWE_HIGHRATE)) + { + /* HR SWB BWE on top of ACELP@16kHz */ + tmps = NS2SA_fx2( st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS ); + } + ELSE + { + /* TBE on top of ACELP@16kHz */ + tmps = NS2SA_fx2( st_fx->output_Fs_fx, MAX_DELAY_TBE_NS - DELAY_SWB_TBE_16k_NS ); + } + } + + /* Smooth transitions when switching between different technologies */ + test(); + test(); + test(); + test(); + IF ( (NE_16(st_fx->extl_fx,st_fx->last_extl_fx)||(EQ_16(st_fx->extl_fx,st_fx->last_extl_fx)&&EQ_16((st_fx->core_fx^st_fx->last_core_fx),HQ_CORE))) + && !(EQ_16(st_fx->extl_fx,SWB_CNG) && EQ_16(st_fx->last_extl_fx,SWB_TBE)) ) + { + /*incr = (short) ( L_FRAME / (tmps + 0.5f) );*/ + incr = idiv1616(L_FRAME*2, add(shl(tmps,1),1)); + tmp16 = 0; + move16(); + FOR (i=0; ihb_prev_synth_buffer_fx, 0, tmps ); + } + ELSE IF ( LT_16(tmps,st_fx->old_bwe_delay_fx)) + { + /* the previous frame was TBE on top of ACELP@16kHz and the current frame is TBE on top of ACELP@12.8kHz */ + /*incr = (short) ( L_FRAME / (tmps + 0.5f) );*/ + incr = idiv1616(L_FRAME*2, add(shl(tmps,1),1)); + tmp16 = 0; + move16(); + FOR (i=0; ihb_prev_synth_buffer_fx[i], sin_table256_fx[255 - tmp16]), + st_fx->hb_prev_synth_buffer_fx[st_fx->old_bwe_delay_fx - 1 - i], sin_table256_fx[tmp16])); + tmp16 = add(tmp16, incr); + } + Copy(tmp_buffer_fx, st_fx->hb_prev_synth_buffer_fx, tmps); + } + ELSE IF (GT_16(tmps,st_fx->old_bwe_delay_fx)) + { + /* the previous frame was TBE on top of ACELP@12.8kHz and the current frame is TBE on top of ACELP@16kHz */ + /*incr = (short)( L_FRAME / (st->old_bwe_delay + 0.5f) );*/ + incr = idiv1616(L_FRAME*2, add(shl(st_fx->old_bwe_delay_fx,1),1)); + tmp16 = 0; + move16(); + FOR (i=0; iold_bwe_delay_fx; i++) + { + tmp_buffer_fx[i] = mult_r(st_fx->hb_prev_synth_buffer_fx[i], sin_table256_fx[255 - tmp16]); + move16(); + tmp16 = add(tmp16, incr); + + } + FOR (; iold_bwe_delay_fx; i++) + { + /*tmp_buffer[tmps - 1 - i] += st->hb_prev_synth_buffer[st->old_bwe_delay - 1 - i] * sin_table256[i * incr];*/ + tmp_buffer_fx[tmps - 1 - i] = round_fx(L_mac(L_mult(tmp_buffer_fx[tmps - 1 - i], 32767), st_fx->hb_prev_synth_buffer_fx[st_fx->old_bwe_delay_fx - 1 - i], sin_table256_fx[tmp16/*i * incr*/])); + tmp16 = add(tmp16, incr); + } + + Copy( tmp_buffer_fx, st_fx->hb_prev_synth_buffer_fx, tmps ); + } + /* Delay hb_synth */ + tmp16 = sub(hb_synth_fx_exp, st_fx->prev_hb_synth_fx_exp); + IF ( tmp16 != 0 ) + { + Scale_sig(st_fx->hb_prev_synth_buffer_fx, tmps, tmp16 ); + } + Copy( hb_synth_fx, tmp_buffer_fx, output_frame ); + Copy( st_fx->hb_prev_synth_buffer_fx, hb_synth_fx, tmps ); + Copy( tmp_buffer_fx, hb_synth_fx + tmps, output_frame - tmps ); + Copy( tmp_buffer_fx + output_frame - tmps, st_fx->hb_prev_synth_buffer_fx, tmps ); + + st_fx->old_bwe_delay_fx = tmps; + move16(); + + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( st_fx->ppp_mode_dec_fx || (EQ_16(st_fx->nelp_mode_dec_fx,1)&&EQ_16(st_fx->bfi_fx,1)))&&EQ_16(st_fx->L_frame_fx,st_fx->last_L_frame_fx)&&(st_fx->bws_cnt_fx>1||st_fx->last_extl_fx!=-1)) + + { + Copy( st_fx->old_hb_synth_fx, hb_synth_fx, output_frame ); + IF(LT_16(st_fx->prev_hb_synth_fx_exp, 14)) + { + hb_synth_fx_exp = add(st_fx->prev_hb_synth_fx_exp, 1); + } + ELSE + { + hb_synth_fx_exp = 14; + } + } + ELSE + { + Copy( hb_synth_fx, st_fx->old_hb_synth_fx, output_frame ); + } + + add_vec_fx( synth_fx, Qpostd, hb_synth_fx, hb_synth_fx_exp, synth_fx, Qpostd, output_frame ); + + /* SWB CNG/DTX - calculate SHB energy */ + test(); + IF ( GE_16(output_frame, L_FRAME32k)&>_16(st_fx->extl_fx,SWB_CNG)) + { + SWITCH (output_frame) + { + case L_FRAME8k: + tmp16 = 205; + BREAK; /*Q15*/ + case L_FRAME16k: + tmp16 = 102; + BREAK; /*Q15*/ + case L_FRAME32k: + tmp16 = 51; + BREAK; /*Q15*/ + case L_FRAME48k: + tmp16 = 34; + BREAK; /*Q15*/ + } + + L_tmp = L_deposit_l(1); /*Q2*hb_synth_fx_exp*/ + FOR ( i=0; ilast_shb_ener_fx = round_fx(L_shl(L_tmp, 10)); /*Q8*/ + } + } + st_fx->prev_hb_synth_fx_exp = hb_synth_fx_exp; + move16(); + + /* TCX-LTP Postfilter: used in MODE1 to update memories and to avoid discontinuities when the past frame was TCX */ + delta = NS2SA_fx2( st_fx->output_Fs_fx, TCXLTP_DELAY_NS ); + Scale_sig(st_fx->tcxltp_mem_in, delta, sub(Qpostd, Qpostd_prev)); + Scale_sig(st_fx->tcxltp_mem_out, output_frame, sub(Qpostd, Qpostd_prev)); + tcx_ltp_post( st_fx->tcxltp, ACELP_CORE, output_frame, st_fx->L_frame_past, 0, synth_fx, NULL, + delta, 0, 0, 0, 0, &st_fx->tcxltp_pitch_int_post_prev, + &st_fx->tcxltp_pitch_fr_post_prev, &st_fx->tcxltp_gain_post_prev, + &st_fx->tcxltp_filt_idx_prev, st_fx->pit_res_max, + &st_fx->pit_res_max_past, + 0, 0, st_fx->tcxltp_mem_in, + st_fx->tcxltp_mem_out, st_fx->total_brate_fx ); + + + /* final output of synthesis signal */ + Copy( synth_fx, output_sp, output_frame ); + + + } + ELSE /* MODE2 PART */ + { + + /* -------------------------------------------------------------- */ + /* CONCEALMENT */ + /* -------------------------------------------------------------- */ + + concealWholeFrame = 0; + move16(); + + if( EQ_16(frameMode, FRAMEMODE_NORMAL)) + { + st_fx->m_decodeMode = DEC_NO_FRAM_LOSS; + move16(); + } + + IF( EQ_16(frameMode, FRAMEMODE_MISSING)) + { + test(); + test(); + IF( st_fx->use_partial_copy && GE_16(st_fx->rf_frame_type, RF_TCXFD)&&LE_16(st_fx->rf_frame_type,RF_TCXTD2)) + { + st_fx->m_decodeMode = DEC_NO_FRAM_LOSS; + move16(); + } + ELSE + { + st_fx->m_decodeMode = DEC_CONCEALMENT_EXT; + move16(); + } + } + + SWITCH( st_fx->m_decodeMode ) + { + case DEC_NO_FRAM_LOSS: + BREAK; + case DEC_CONCEALMENT_EXT: + concealWholeFrame = 1; + move16(); + BREAK; + } + + + /* -------------------------------------------------------------- */ + /* DECODE CORE */ + /* -------------------------------------------------------------- */ + + dec_acelp_tcx_frame( st_fx, &coder_type, &concealWholeFrame, output_sp, + st_fx->p_bpf_noise_buf, pcmbufFB, bwe_exc_extended_fx, voice_factors_fx, pitch_buf_fx ); + + concealWholeFrameTmp = concealWholeFrame; + move16(); + if(st_fx->bfi_fx) + { + frameMode = FRAMEMODE_MISSING; + move16(); + } + IF( st_fx->igf ) + { + + /* TBE interface */ + test(); + test(); + IF( (st_fx->bfi_fx == 0 || st_fx->last_core_fx == ACELP_CORE) && st_fx->core_fx == ACELP_CORE ) + { + test(); + test(), test(); + SWITCH (st_fx->bwidth_fx) + { + case WB: + st_fx->extl_fx = WB_TBE; + move16(); + st_fx->extl_brate_fx = WB_TBE_0k35; + move32(); + BREAK; + + case SWB: + st_fx->extl_fx = SWB_TBE; + move16(); + st_fx->extl_brate_fx = SWB_TBE_1k6; + move32(); + BREAK; + + case FB: + st_fx->extl_fx = FB_TBE; + move16(); + st_fx->extl_brate_fx = FB_TBE_1k8; + move32(); + BREAK; + } + } + ELSE + { + st_fx->extl_fx = IGF_BWE; + move16(); + st_fx->extl_brate_fx = L_deposit_l(0); + } + + test(); + test(); + if( EQ_32(st_fx->output_Fs_fx,8000)||(EQ_32(st_fx->output_Fs_fx,16000)&&EQ_16(st_fx->L_frame_fx,L_FRAME16k))) + { + st_fx->extl_fx = -1; + move16(); + } + + st_fx->core_brate_fx = L_sub(st_fx->total_brate_fx, st_fx->extl_brate_fx); + + st_fx->bws_cnt_fx = 0; + move16(); + st_fx->bws_cnt1_fx = 0; + move16(); + st_fx->tilt_wb_fx = 0; + move16(); + + IF( EQ_16(st_fx->m_frame_type, ACTIVE_FRAME)) + { + test(); + test(); + IF( ( st_fx->bfi_fx == 0 || st_fx->last_core_fx == ACELP_CORE ) && st_fx->core_fx == ACELP_CORE ) + { + test(); + IF( EQ_16(st_fx->extl_fx, WB_TBE)) + { + wb_tbe_dec_fx( st_fx, coder_type, bwe_exc_extended_fx, st_fx->Q_exc, voice_factors_fx, hb_synth_fx, &hb_synth_fx_exp ); + } + ELSE IF( EQ_16(st_fx->extl_fx, SWB_TBE)||EQ_16(st_fx->extl_fx,FB_TBE)) + { + /* SWB TBE decoder */ + swb_tbe_dec_fx( st_fx, coder_type, bwe_exc_extended_fx, st_fx->Q_exc, voice_factors_fx, st_fx->old_core_synth_fx, + fb_exc_fx, &Q_fb_exc, hb_synth_fx, &hb_synth_fx_exp, pitch_buf_fx ); + + test(); + IF( EQ_16(st_fx->extl_fx, FB_TBE)&&EQ_16(output_frame,L_FRAME48k)) + { + fb_tbe_dec_fx( st_fx, fb_exc_fx, Q_fb_exc, hb_synth_fx, hb_synth_fx_exp ); + } + } + Copy( hb_synth_fx, st_fx->old_hb_synth_fx, output_frame ); + } + ELSE + { + IF( EQ_16(st_fx->last_core_fx,ACELP_CORE)) + { + test(); + test(); + test(); + test(); + IF( ( EQ_16(st_fx->bwidth_fx, SWB)||EQ_16(st_fx->bwidth_fx,FB))&& + (( EQ_16(st_fx->last_extl_fx, SWB_TBE) || EQ_16(st_fx->last_extl_fx, FB_TBE) ) && EQ_16(st_fx->last_codec_mode, MODE2) ) ) + { + GenTransition_fx( st_fx->syn_overlap_fx, st_fx->old_tbe_synth_fx, 2*NS2SA(st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS), hb_synth_fx, + st_fx->genSHBsynth_Hilbert_Mem_fx, st_fx->genSHBsynth_state_lsyn_filt_shb_local_fx, + st_fx->mem_resamp_HB_32k_fx, + &(st_fx->syn_dm_phase_fx), st_fx->output_Fs_fx, st_fx->int_3_over_2_tbemem_dec_fx, st_fx->rf_flag, st_fx->total_brate_fx ); + + hb_synth_fx_exp = st_fx->prev_Q_bwe_syn2; + move16(); + } + ELSE IF ( st_fx->bwidth_fx == WB && st_fx->last_extl_fx == WB_TBE ) + { + GenTransition_WB_fx( st_fx->syn_overlap_fx, st_fx->old_tbe_synth_fx, st_fx->prev_Qx, 2*NS2SA(st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS), hb_synth_fx, + st_fx->state_lsyn_filt_shb_fx, st_fx->state_lsyn_filt_dwn_shb_fx, st_fx->output_Fs_fx, st_fx->mem_resamp_HB_fx ); + + hb_synth_fx_exp = st_fx->prev_Qx; + move16(); + } + + TBEreset_dec_fx( st_fx, st_fx->bwidth_fx ); + } + ELSE IF ( EQ_16(st_fx->last_codec_mode,MODE1)) + { + swb_tbe_reset_fx( st_fx->mem_csfilt_fx, st_fx->mem_genSHBexc_filt_down_shb_fx, st_fx->state_lpc_syn_fx, + st_fx->syn_overlap_fx, st_fx->state_syn_shbexc_fx, &(st_fx->tbe_demph_fx), &(st_fx->tbe_premph_fx), st_fx->mem_stp_swb_fx, &(st_fx->gain_prec_swb_fx) ); + IF( EQ_16(st_fx->extl_fx, FB_TBE)) + { + set16_fx( st_fx->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + st_fx->fb_tbe_demph_fx = 0; + fb_tbe_reset_synth_fx( st_fx->fbbwe_hpf_mem_fx, st_fx->fbbwe_hpf_mem_fx_Q,&st_fx->prev_fbbwe_ratio_fx ); + } + swb_tbe_reset_synth_fx( st_fx->genSHBsynth_Hilbert_Mem_fx, st_fx->genSHBsynth_state_lsyn_filt_shb_local_fx ); + } + } + } + } + + IF( NE_16(st_fx->m_frame_type,ACTIVE_FRAME)) + { + st_fx->extl_fx = -1; + move16(); + st_fx->extl_brate_fx = L_deposit_l(0); + } + + /* -------------------------------------------------------------- */ + /* APPLY POSTPROC */ + /* -------------------------------------------------------------- */ + + { + nab = s_min( st_fx->cldfbAna_fx->no_channels, st_fx->cldfbSyn_fx->no_channels ); + st_fx->cldfbSyn_fx->lsb = s_min(st_fx->cldfbAna_fx->no_channels, st_fx->cldfbSyn_fx->no_channels); + move16(); + st_fx->cldfbSyn_fx->usb = st_fx->cldfbSyn_fx->no_channels; + move16(); + st_fx->cldfbAna_fx->lsb = st_fx->cldfbAna_fx->no_channels; + move16(); + st_fx->cldfbAna_fx->usb = st_fx->cldfbAna_fx->no_channels; + move16(); + + test(); + test(); + test(); + test(); + IF ( st_fx->hFdCngDec_fx != NULL && (EQ_32(st_fx->sr_core,8000)||EQ_32(st_fx->sr_core,12800)||EQ_32(st_fx->sr_core,16000))&&LE_32(st_fx->total_brate_fx,ACELP_32k)) + { + /*************************************** + In CLDFB domain: + - perform noise estimation during active frames + - do CNG during inactive frames + ****************************************/ + HANDLE_FD_CNG_DEC hFdCngDec = st_fx->hFdCngDec_fx; + move16(); + + noisy_speech_detection( st_fx->VAD && st_fx->m_frame_type==ACTIVE_FRAME, output_sp, st_fx->L_frame_fx, 0, hFdCngDec->msNoiseEst, hFdCngDec->msNoiseEst_exp, + hFdCngDec->psize_shaping_norm, hFdCngDec->psize_shaping_norm_exp, hFdCngDec->nFFTpart_shaping, + &(hFdCngDec->lp_noise), &(hFdCngDec->lp_speech), &(hFdCngDec->hFdCngCom->flag_noisy_speech) ); + + hFdCngDec->hFdCngCom->likelihood_noisy_speech = mult_r(hFdCngDec->hFdCngCom->likelihood_noisy_speech, 32440/*0.99 Q15*/); + IF ( hFdCngDec->hFdCngCom->flag_noisy_speech != 0 ) + { + hFdCngDec->hFdCngCom->likelihood_noisy_speech = add(hFdCngDec->hFdCngCom->likelihood_noisy_speech, 328/*0.01 Q15*/); + move16(); + } + st_fx->lp_noise = hFdCngDec->lp_noise; + move32(); + ApplyFdCng( output_sp, 0, realBuffer, imagBuffer, &st_fx->scaleFactor.hb_scale, hFdCngDec, st_fx->m_frame_type, st_fx, concealWholeFrame, 0); + + /* Generate additional comfort noise to mask potential coding artefacts */ + test(); + IF( EQ_16(st_fx->m_frame_type,ACTIVE_FRAME)&&st_fx->flag_cna) + { + generate_masking_noise( output_sp, 0, hFdCngDec->hFdCngCom, hFdCngDec->hFdCngCom->frameSize, 0 ); + } + + } + + test(); + test(); + test(); + test(); + test(); + test(); + IF( st_fx->flag_cna == 0 && EQ_16(st_fx->L_frame_fx,L_FRAME16k)&&EQ_16(st_fx->last_flag_cna,1) + && ( (st_fx->last_core_fx == ACELP_CORE && NE_16(st_fx->last_coder_type_fx,AUDIO) ) || EQ_16(st_fx->last_core_fx,TCX_20_CORE) || EQ_16(st_fx->last_core_fx,AMR_WB_CORE) ) ) + { + FOR (i=0; i < st_fx->L_frame_fx/2; i++) + { + output_sp[i] = add( output_sp[i], st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth2[i+5*st_fx->L_frame_fx/4] ); + move16(); + } + } + + IF( EQ_16(st_fx->m_frame_type,ACTIVE_FRAME)) + { + timeIn_e = s_max(0, sub(getScaleFactor16( output_sp, st_fx->L_frame_fx ), 3)); + IF( NE_16(st_fx->core_fx,ACELP_CORE)) + { + timeIn_e = s_max(0, s_min(sub(getScaleFactor16( pcmbufFB, st_fx->L_frameTCX ), 3),timeIn_e)); + } + Scale_sig( output_sp, st_fx->L_frame_fx, timeIn_e ); + timeIn_e = negate( timeIn_e ); + cldfbAnalysisFiltering( st_fx->cldfbAna_fx, realBuffer, imagBuffer, &st_fx->scaleFactor, output_sp, timeIn_e, CLDFB_NO_COL_MAX, workBuffer ); + st_fx->scaleFactor.hb_scale = st_fx->scaleFactor.lb_scale; + move16(); + } + ELSE + { + Word16 timeDomainBuffer[L_FRAME16k]; + Word16 A[M+1]; + + Copy( st_fx->hFdCngDec_fx->hFdCngCom->timeDomainBuffer, timeDomainBuffer, st_fx->L_frame_fx ); + Copy( st_fx->hFdCngDec_fx->hFdCngCom->A_cng, A, M+1 ); + + update_decoder_LPD_cng( st_fx, coder_type, timeDomainBuffer, A, st_fx->p_bpf_noise_buf ); + + /* Generate additional comfort noise to mask potential coding artefacts */ + IF( st_fx->flag_cna ) + { + generate_masking_noise( timeDomainBuffer, 0, st_fx->hFdCngDec_fx->hFdCngCom, st_fx->hFdCngDec_fx->hFdCngCom->frameSize, 0 ); + } + ELSE IF( EQ_16(st_fx->L_frame_fx,L_FRAME16k)&&EQ_16(st_fx->last_flag_cna,1)&&((EQ_16(st_fx->last_core_fx,ACELP_CORE)&&NE_16(st_fx->last_coder_type_fx,AUDIO))||EQ_16(st_fx->last_core_fx,TCX_20_CORE)||EQ_16(st_fx->last_core_fx,AMR_WB_CORE))) + { + FOR( i=0; i < st_fx->L_frame_fx/2; i++ ) + { + timeDomainBuffer[i] = add( timeDomainBuffer[i], st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth2[i+5*st_fx->L_frame_fx/4] ); + move16(); + } + } + /* check if the CLDFB works on the right sample rate */ + IF( NE_16((st_fx->cldfbAna_fx->no_channels * st_fx->cldfbAna_fx->no_col),st_fx->L_frame_fx)) + { + Word16 newCldfbBands = CLDFB_getNumChannels(L_mult0(st_fx->L_frame_fx, 50)); + + resampleCldfb( st_fx->cldfbAna_fx, newCldfbBands, st_fx->L_frame_fx, 0 ); + resampleCldfb( st_fx->cldfbBPF_fx, newCldfbBands, st_fx->L_frame_fx, 0 ); + } + + st_fx->cldfbSyn_fx->bandsToZero = 0; + move16(); + test(); + IF ( EQ_16( st_fx->bwidth_fx, NB )&>_16(st_fx->cldfbSyn_fx->no_channels,10)) + { + st_fx->cldfbSyn_fx->bandsToZero = sub( st_fx->cldfbSyn_fx->no_channels, 10 ); + } + ELSE IF ( st_fx->hFdCngDec_fx->hFdCngCom->regularStopBand < st_fx->cldfbSyn_fx->no_channels ) + { + st_fx->cldfbSyn_fx->bandsToZero = st_fx->cldfbSyn_fx->no_channels - st_fx->hFdCngDec_fx->hFdCngCom->regularStopBand; + } + + timeIn_e = 2; + move16(); + Scale_sig(timeDomainBuffer, st_fx->L_frame_fx, timeIn_e); + IF ( st_fx->p_bpf_noise_buf ) + { + Scale_sig(st_fx->p_bpf_noise_buf, st_fx->L_frame_fx, timeIn_e); + } + + timeIn_e = negate(timeIn_e); + cldfbAnalysisFiltering( st_fx->cldfbAna_fx, realBuffer, imagBuffer, &st_fx->scaleFactor, timeDomainBuffer, timeIn_e, CLDFB_NO_COL_MAX, workBuffer) ; + } + + if( st_fx->flag_cna == 0 ) + { + set16_fx( st_fx->hFdCngDec_fx->hFdCngCom->olapBufferSynth2, 0, st_fx->hFdCngDec_fx->hFdCngCom->fftlen ); + } + + IF( st_fx->p_bpf_noise_buf ) + { + Word16 timeInBpf_e = timeIn_e; + move16(); + if( EQ_16(st_fx->m_frame_type,ACTIVE_FRAME)) + { + timeInBpf_e = 0; + move16(); + } + + addBassPostFilterFx( st_fx->p_bpf_noise_buf, realBuffer, imagBuffer, st_fx->cldfbBPF_fx, workBuffer, + timeInBpf_e, CLDFB_NO_COL_MAX, st_fx->cldfbAna_fx->no_col, st_fx->cldfbAna_fx->no_channels, &st_fx->scaleFactor ); + + IF( NE_16(st_fx->m_frame_type,ACTIVE_FRAME)) + { + Scale_sig(st_fx->p_bpf_noise_buf, st_fx->L_frame_fx, timeIn_e); + } + + } + + IF (GT_32(st_fx->output_Fs_fx, 8000)) + { + st_fx->tecDec_fx.cldfbExp = add(15, st_fx->scaleFactor.lb_scale); + + calcGainTemp_TBE_Fx( realBuffer, imagBuffer, st_fx->tecDec_fx.cldfbExp, st_fx->tecDec_fx.loBuffer, + 0, /*startPos,*//*!< Start position of the current envelope. */ + st_fx->cldfbAna_fx->no_col, /*stopPos,*/ /*!< Stop position of the current envelope. */ + st_fx->cldfbAna_fx->no_channels, /*lowSubband*/ + st_fx->tecDec_fx.pGainTemp_m, st_fx->tecDec_fx.pGainTemp_e, st_fx->tec_flag + ); + } + + /* set high band buffers to zero. Covering the current frame and the overlap area. */ + IF( EQ_16(st_fx->m_frame_type,ACTIVE_FRAME)) + { + FOR( i = 0; i < 16; i++ ) + { + set32_fx( &realBuffer[i][nab], 0, sub(st_fx->cldfbSyn_fx->no_channels,nab) ); + set32_fx( &imagBuffer[i][nab], 0, sub(st_fx->cldfbSyn_fx->no_channels,nab) ); + } + } + + timeIn_e = s_min(0, add(timeIn_e, 2)); + cldfbSynthesisFiltering(st_fx->cldfbSyn_fx, realBuffer, imagBuffer, &st_fx->scaleFactor, output_sp, timeIn_e, CLDFB_NO_COL_MAX, workBuffer ); + /*CLDFB output always in timeIn_e*/ + + /* MODE1 MDCT to ACELP 2 transition */ + delay_comp = NS2SA_fx2(st_fx->output_Fs_fx, DELAY_CLDFB_NS); + Scale_sig(st_fx->delay_buf_out_fx, delay_comp, negate(st_fx->Q_old_postdec)); + st_fx->Q_old_postdec = 0; + move16(); + delay_tdbwe= NS2SA_fx2(st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS- DELAY_CLDFB_NS); + IF( GE_16(output_frame,L_FRAME16k)) + { + Scale_sig(st_fx->prev_synth_buffer_fx, delay_tdbwe, sub(Qpostd, st_fx->Qprev_synth_buffer_fx)); + } + + test(); + IF( EQ_16(st_fx->last_codec_mode,MODE1)&>_16(st_fx->last_core_bfi,ACELP_CORE)) + { + Copy_Scale_sig( st_fx->delay_buf_out_fx, output_sp, delay_comp, negate(timeIn_e) ); /* copy the HQ/ACELP delay synchronization buffer at the beginning of ACELP frame */ + IF( EQ_16(st_fx->core_fx,ACELP_CORE)) + { + Word16 step, alpha, nz; + + i = 15; + move16(); + tmps = NS2SA_fx2(st_fx->output_Fs_fx, 3000000L); + nz = NS2SA_fx2(st_fx->output_Fs_fx, N_ZERO_MDCT_NS); + step = Inv16(tmps, &i); + step = shl(step, i); + alpha = 0; + move16(); + + test(); + IF( st_fx->prev_bfi_fx && st_fx->HqVoicing_fx ) + { + Copy( st_fx->fer_samples_fx, &st_fx->old_out_fx[nz], tmps); + } + ELSE + { + Scale_sig(st_fx->old_out_fx, nz+tmps, negate(st_fx->Q_old_wtda)); + } + st_fx->Q_old_wtda = 0; + move16(); + + FOR (i = 0; i < tmps; i++) + { + output_sp[i+delay_comp] = msu_r(L_mult(output_sp[i+delay_comp], alpha), shr(st_fx->old_out_fx[i+nz], timeIn_e), add(alpha, -32768)); + move16(); + alpha = add(alpha, step); + } + } + ELSE + { + IF( EQ_32(st_fx->output_Fs_fx,8000)) + { + Copy(st_fx->delay_buf_out_fx, st_fx->FBTCXdelayBuf, delay_comp); + } + ELSE + { + Copy( st_fx->prev_synth_buffer_fx, st_fx->FBTCXdelayBuf, delay_tdbwe ); + Copy( st_fx->delay_buf_out_fx, st_fx->FBTCXdelayBuf + delay_tdbwe, delay_comp ); + } + } + } + + /* set delay compensation between HQ synthesis and ACELP synthesis */ + test(); + IF( EQ_16(st_fx->core_fx,ACELP_CORE)&&!(st_fx->con_tcx)) + { + set16_fx( st_fx->delay_buf_out_fx, 0, delay_comp ); + Copy_Scale_sig( output_sp, st_fx->previoussynth_fx, output_frame, timeIn_e ); + } + ELSE + { + Copy( st_fx->old_synthFB_fx+st_fx->old_synth_lenFB-delay_comp, st_fx->delay_buf_out_fx, delay_comp ); + IF( EQ_32(st_fx->output_Fs_fx, 8000)) + { + Copy(st_fx->FBTCXdelayBuf, st_fx->previoussynth_fx, delay_comp); + } + ELSE + { + Copy( st_fx->FBTCXdelayBuf + delay_tdbwe, st_fx->previoussynth_fx, delay_comp ); + } + Copy(pcmbufFB, st_fx->previoussynth_fx + delay_comp, sub(output_frame, delay_comp)); + } + } + + /* Delay compensation for TD-BWE*/ + IF( GE_16(output_frame,L_FRAME16k)) + { + Copy( output_sp, tmp_buffer_fx, output_frame ); + Copy_Scale_sig( st_fx->prev_synth_buffer_fx, output_sp, delay_tdbwe, negate(timeIn_e) ); + Copy( tmp_buffer_fx, output_sp + delay_tdbwe, output_frame - delay_tdbwe ); + Copy_Scale_sig( tmp_buffer_fx + output_frame - delay_tdbwe, st_fx->prev_synth_buffer_fx, delay_tdbwe, timeIn_e); + } + + test(); + IF( st_fx->igf != 0 && EQ_16( st_fx->m_frame_type, ACTIVE_FRAME )) + { + test(); + test(); + test(); + test(); + IF( st_fx->bfi_fx == 0 && EQ_16(st_fx->core_fx, ACELP_CORE)&&(st_fx->tec_flag!=0||st_fx->tfa_flag!=0)&>_32(st_fx->output_Fs_fx,8000)) + { + tmp16 = 0; + move16(); + if (EQ_16(st_fx->tec_flag, 2)) + { + tmp16 = 1; + move16(); + } + + hb_synth_fx_exp = procTecTfa_TBE_Fx( hb_synth_fx, hb_synth_fx_exp, st_fx->tecDec_fx.pGainTemp_m, st_fx->tecDec_fx.pGainTemp_e, + st_fx->tfa_flag, st_fx->last_core_fx, shr(output_frame, 4 ), tmp16 ); + } + + test(); + test(); + test(); + test(); + test(); + test(); + IF( (( ( st_fx->bfi_fx == 0 || st_fx->last_core_fx == ACELP_CORE ) && st_fx->core_fx == ACELP_CORE ) || + ( ( EQ_16(st_fx->last_core_fx, ACELP_CORE) ) && (NE_16(st_fx->bwidth_fx, NB) && EQ_16(st_fx->last_codec_mode, MODE2) ) )) + && (GT_32( st_fx->output_Fs_fx, 8000 ) ) ) + { + add_vec_fx( output_sp, negate(timeIn_e), hb_synth_fx, hb_synth_fx_exp, output_sp, negate(timeIn_e), output_frame ); + } + } + + + IF( EQ_32( st_fx->output_Fs_fx, 8000 )) + { + tmps = NS2SA_fx2(st_fx->output_Fs_fx, DELAY_CLDFB_NS ); + } + ELSE + { + tmps = NS2SA_fx2(st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS ); + } + delta = NS2SA_fx2( st_fx->output_Fs_fx, TCXLTP_DELAY_NS ); + + test(); + test(); + test(); + IF ( (st_fx->bfi_fx && GT_16(st_fx->last_core_fx, ACELP_CORE))||GT_16(st_fx->core_fx,ACELP_CORE)) + { + test(); + test(); + test(); + test(); + IF ( GT_16(st_fx->last_core_bfi, ACELP_CORE)||(st_fx->bfi_fx&&st_fx->last_core_fx>ACELP_CORE)||(st_fx->prev_bfi_fx&&st_fx->last_con_tcx)) + { + Copy_Scale_sig(st_fx->FBTCXdelayBuf, output_sp, tmps, negate(timeIn_e)); + Copy_Scale_sig(pcmbufFB, output_sp + tmps, sub(st_fx->L_frameTCX, tmps), negate(timeIn_e)); + } + ELSE + { + Word16 step, alpha; + + i = 15; + move16(); + step = Inv16(tmps, &i); + step = shl(step, i); + alpha = 0; + move16(); + + FOR (i = 0; i < tmps; i++) + { + output_sp[i+tmps] = msu_r(L_mult(shr(pcmbufFB[i], timeIn_e), alpha), output_sp[i+tmps], add(alpha, -32768)); + move16(); + alpha = add(alpha, step); + } + Copy_Scale_sig( pcmbufFB + tmps, output_sp + shl(tmps,1), sub(st_fx->L_frameTCX, shl(tmps,1)), negate(timeIn_e) ); + } + + Copy( pcmbufFB + st_fx->L_frameTCX - tmps, st_fx->FBTCXdelayBuf, tmps ); + + test(); + IF( st_fx->bfi_fx && GT_16(st_fx->last_core_fx, ACELP_CORE)) + { + IF( EQ_32(st_fx->output_Fs_fx, 8000)) + { + Copy(st_fx->FBTCXdelayBuf, st_fx->delay_buf_out_fx, NS2SA(st_fx->output_Fs_fx, DELAY_CLDFB_NS)); + } + ELSE + { + Copy( st_fx->FBTCXdelayBuf, st_fx->prev_synth_buffer_fx, NS2SA(st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS) ); + Copy( st_fx->FBTCXdelayBuf + NS2SA(st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS), st_fx->delay_buf_out_fx, NS2SA(st_fx->output_Fs_fx, DELAY_CLDFB_NS) ); + } + } + } + ELSE IF( (EQ_16(st_fx->last_codec_mode,MODE2))&&(GT_16(st_fx->last_core_fx,ACELP_CORE))) + { + Word16 step, alpha; + + Copy_Scale_sig(st_fx->FBTCXdelayBuf, output_sp, delta, negate(timeIn_e)); + + i = 15; + move16(); + step = Inv16(sub(tmps,delta), &i); + step = shl(step, i); + alpha = 0; + move16(); + + FOR (i = delta; i < tmps; i++) + { + output_sp[i] = msu_r(L_mult(output_sp[i], alpha), shr(st_fx->FBTCXdelayBuf[i], timeIn_e), add(alpha, -32768)); + move16(); + alpha = add(alpha, step); + } + } + + Scale_sig(st_fx->tcxltp_mem_in, delta, sub(Qpostd, Qpostd_prev)); + Scale_sig(st_fx->tcxltp_mem_out, output_frame, sub(Qpostd, Qpostd_prev)); + test(); + + Scale_sig( output_sp, output_frame, timeIn_e ); + + tcx_ltp_post( st_fx->tcxltp, st_fx->core_fx, st_fx->L_frameTCX, st_fx->L_frame_fx, NS2SA_fx2( st_fx->output_Fs_fx, ACELP_LOOK_NS ) + tmps, + output_sp, st_fx->FBTCXdelayBuf, delta, st_fx->bfi_fx, st_fx->tcxltp_pitch_int, st_fx->tcxltp_pitch_fr, st_fx->tcxltp_gain, + &st_fx->tcxltp_pitch_int_post_prev, &st_fx->tcxltp_pitch_fr_post_prev, &st_fx->tcxltp_gain_post_prev, &st_fx->tcxltp_filt_idx_prev, + st_fx->pit_res_max, + &st_fx->pit_res_max_past, + st_fx->damping, L_sub(st_fx->total_brate_fx, 96000) >= 0, st_fx->tcxltp_mem_in, st_fx->tcxltp_mem_out, st_fx->total_brate_fx ); + Copy( output_sp, synth_fx, output_frame ); + + } /* end of MODE2 */ + + + /*----------------------------------------------------------------* + * Save synthesis for HQ FEC + *----------------------------------------------------------------*/ + post_hq_delay = NS2SA_fx2( st_fx->output_Fs_fx, POST_HQ_DELAY_NS ); + IF (EQ_16(st_fx->codec_mode, MODE1)) + { + + Copy( st_fx->synth_history_fx+output_frame, st_fx->synth_history_fx, output_frame-post_hq_delay+NS2SA_fx2( st_fx->output_Fs_fx, PH_ECU_MEM_NS )); + Copy_Scale_sig( synth_fx, st_fx->old_synthFB_fx+output_frame-post_hq_delay, output_frame,negate(Qpostd)); /* output_sp not initialized yet */ + /* reset the remaining buffer, which is read in TCX concealment the necessary samples to fill + this buffer are not available for all cases, the impact on the output is limited */ + set16_fx( st_fx->old_synthFB_fx+2*output_frame-post_hq_delay, 0, post_hq_delay ); + + IF( GE_16(output_frame, L_FRAME16k)) + { + + Copy_Scale_sig( st_fx->prev_synth_buffer_fx, st_fx->old_synthFB_fx+2*output_frame-NS2SA_fx2(st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS), NS2SA_fx2(st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS),negate(st_fx->Qprev_synth_buffer_fx)); + } + IF( NE_16(st_fx->core_fx,ACELP_CORE)) + { + IF( GE_16(output_frame, L_FRAME16k)) + { + + Copy_Scale_sig( synth_fx+output_frame, st_fx->old_synthFB_fx+2*output_frame-NS2SA_fx2(st_fx->output_Fs_fx, DELAY_CLDFB_NS), NS2SA_fx2(st_fx->output_Fs_fx, DELAY_CLDFB_NS),negate(Qpostd)); + Copy_Scale_sig( st_fx->old_out_fx+NS2SA_fx2(st_fx->output_Fs_fx, N_ZERO_MDCT_NS), st_fx->old_synthFB_fx+2*output_frame, NS2SA_fx2(st_fx->output_Fs_fx, PH_ECU_LOOKAHEAD_NS), negate(st_fx->Q_old_wtda)); + } + ELSE + { + + Copy_Scale_sig( synth_fx+output_frame, st_fx->old_synthFB_fx+2*output_frame-NS2SA_fx2(st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS), NS2SA_fx2(st_fx->output_Fs_fx, DELAY_CLDFB_NS),negate(Qpostd)); + Copy_Scale_sig( st_fx->old_out_fx+NS2SA_fx2(st_fx->output_Fs_fx, N_ZERO_MDCT_NS), st_fx->old_synthFB_fx+2*output_frame-NS2SA_fx2(st_fx->output_Fs_fx, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS), NS2SA_fx2(st_fx->output_Fs_fx, PH_ECU_LOOKAHEAD_NS), negate(st_fx->Q_old_wtda)); + } + } + } + + /*----------------------------------------------------------------* + * HP filtering + *----------------------------------------------------------------*/ + + st_fx->Qprev_synth_buffer_fx=Qpostd; + move16(); + Scale_sig32(st_fx->L_mem_hp_out_fx, 4, sub(Qpostd, Qpostd_prev)); + hp20(synth_fx, 1/*stride*/, output_frame, st_fx->L_mem_hp_out_fx, L_mult0(output_frame, 50)); + + /*----------------------------------------------------------------* + * Synthesis output + *----------------------------------------------------------------*/ + + IF( EQ_16(st_fx->codec_mode,MODE1)) + { + /* final output of synthesis signal */ + syn_output_fx( st_fx->codec_mode, synth_fx, output_frame, output_sp, Qpostd ); + } + ELSE + { + Copy( synth_fx, output_sp, output_frame ); + } + + /*--------------------------------------------------------* + * Updates + *--------------------------------------------------------*/ + + test(); + IF( st_fx->last_is_cng == 0 && EQ_16(st_fx->codec_mode,MODE2)) + { + st_fx->bfi_fx = 0; + move16(); + IF( st_fx->use_partial_copy && GE_16(st_fx->rf_frame_type, RF_TCXFD)&&LE_16(st_fx->rf_frame_type,RF_TCXTD2)) + { + if( EQ_16(frameMode, FRAMEMODE_MISSING)) + { + st_fx->bfi_fx = 1; + move16(); + } + } + ELSE IF( EQ_16(st_fx->m_decodeMode, DEC_CONCEALMENT_EXT)) + { + st_fx->bfi_fx = 1; + move16(); + } + updt_dec_common_fx( st_fx, -1, output_sp ); + } + ELSE + { + if( EQ_16(st_fx->codec_mode,MODE2)) + { + st_fx->bfi_fx = 0; + move16(); + } + updt_dec_common_fx( st_fx, hq_core_type, output_sp ); + } + IF( EQ_16(st_fx->codec_mode,MODE2)) + { + test(); + IF(EQ_16(st_fx->use_partial_copy,1)&&EQ_16(st_fx->rf_frame_type,RF_NELP)) + { + st_fx->last_nelp_mode_dec_fx = 1; + } + ELSE + { + st_fx->last_nelp_mode_dec_fx = 0; + } + } + + st_fx->prev_use_partial_copy = st_fx->use_partial_copy; + move16(); + + st_fx->prev_tilt_code_dec_fx = 0; + move16(); + + st_fx->prev_Q_exc = st_fx->Q_exc; + move16(); + + L_tmp = L_mult(st_fx->tilt_code_dec_fx[0], 4096); + FOR( i=1; itilt_code_dec_fx[i], 4096); + } + st_fx->prev_tilt_code_dec_fx = round_fx(L_tmp); + + st_fx->prev_coder_type_fx = coder_type; + move16(); + if( EQ_16(st_fx->core_fx,HQ_CORE)) + { + st_fx->prev_coder_type_fx = GENERIC; + move16(); + } + + test(); + IF ( GT_32(st_fx->core_brate_fx,SID_2k40)&&EQ_16(st_fx->first_CNG_fx,1)) + { + if( GE_16(st_fx->act_cnt_fx,BUF_DEC_RATE)) + { + st_fx->act_cnt_fx = 0; + move16(); + } + + st_fx->act_cnt_fx = add(st_fx->act_cnt_fx, 1); + + test(); + if( (EQ_16(st_fx->act_cnt_fx,BUF_DEC_RATE))&&(st_fx->ho_hist_size_fx>0)) + { + st_fx->ho_hist_size_fx = sub(st_fx->ho_hist_size_fx,1); + } + + st_fx->act_cnt2_fx = add(st_fx->act_cnt2_fx,1); + if( GE_16(st_fx->act_cnt2_fx,MIN_ACT_CNG_UPD)) + { + st_fx->act_cnt2_fx = MIN_ACT_CNG_UPD; + move16(); + } + } + + test(); + test(); + if ( LE_32(st_fx->core_brate_fx,SID_2k40)&&st_fx->first_CNG_fx==0&&EQ_16(st_fx->cng_type_fx,LP_CNG)) + { + st_fx->first_CNG_fx = 1; + move16(); + } + + /* update bandwidth switching parameters */ + IF( EQ_16(st_fx->codec_mode, MODE1)) + { + updt_bw_switching_fx( st_fx, synth_fx, Qpostd ); + } + ELSE + { + st_fx->last_bwidth_fx = st_fx->bwidth_fx; + move32(); + } + + /* synchronisation of CNG seeds*/ + test(); + test(); + IF( st_fx->bfi_fx || (NE_32(st_fx->core_brate_fx,FRAME_NO_DATA)&&NE_32(st_fx->core_brate_fx,SID_2k40))) + { + Random( &(st_fx->cng_seed_fx) ); + Random( &(st_fx->cng_ener_seed_fx) ); + } + + test(); + IF( st_fx->enablePlcWaveadjust && !concealWholeFrameTmp ) + { + /* update the parameters used in waveform adjustment */ + concealment_update2_x( output_sp, &st_fx->plcInfo, st_fx->L_frameTCX ); + } + + st_fx->last_total_brate_ber_fx = st_fx->total_brate_fx; + move32(); + if( st_fx->bfi_fx == 0 ) + { + st_fx->last_total_brate_fx = st_fx->total_brate_fx; + move32(); + } + + st_fx->last_flag_cna = st_fx->flag_cna; + move16(); + st_fx->hFdCngDec_fx->hFdCngCom->frame_type_previous = st_fx->m_frame_type; + move16(); + st_fx->prev_bws_cnt_fx = st_fx->bws_cnt_fx; + + return; +} diff --git a/lib_dec/evs_rtp_payload.c b/lib_dec/evs_rtp_payload.c new file mode 100644 index 0000000..901c34e --- /dev/null +++ b/lib_dec/evs_rtp_payload.c @@ -0,0 +1,238 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "evs_rtp_payload.h" + +static void evsPayload_unpackFrame_compact_amrWbIo(const char *payload, uint16_t payloadSizeBits, uint16_t iProtectedSize, + unsigned char **framePtr, uint16_t *frameSizeInBits) { + uint16_t i, iBit0; + unsigned char d0, *frame = *framePtr; + /* ignore 3 bit CMR and padding bits for EVS AMR-WB IO */ + if (iProtectedSize == 2) { /* EVS AMR-WB IO 6.6 */ + *frameSizeInBits = payloadSizeBits - 4; + } + else if (iProtectedSize == 5) { /* EVS AMR-WB IO 8.85 */ + *frameSizeInBits = payloadSizeBits - 7; + } + else { + *frameSizeInBits = payloadSizeBits - 3; + } + iBit0 = *frameSizeInBits + 3 - 1; + d0 = (((unsigned char)payload[iBit0 / 8]) >> (7 - (iBit0 % 8))) & 0x01; + frame[0] = (d0 << 7) | ((payload[0] & 0x1f) << 2); /* d(1..5) */ + ++payload; + for (i = 1; i != (payloadSizeBits + 7) / 8; ++i) { + *frame++ |= (*payload & 0xc0) >> 6; + *frame = (*payload & 0x3f) << 2; + ++payload; + } + assert(frame == *framePtr + (*frameSizeInBits + 7) / 8 - 1); + /* last payload byte contained d(0), clear it */ + (*framePtr)[*frameSizeInBits / 8] &= ~(0x80 >> (*frameSizeInBits % 8)); +} + +static void evsPayload_unpackFrame_compact_evsPrimary(const char *payload, uint16_t payloadSizeBits, + unsigned char **framePtr, uint16_t *frameSizeInBits) { + *framePtr = (unsigned char*)payload; /* no need to copy frame bytes */ + *frameSizeInBits = payloadSizeBits; +} + + +static void evsPayload_unpackFrame_compact(const char *payload, uint16_t payloadSizeBits, uint16_t iProtectedSize, + bool *isAMRWB_IOmode, uint16_t *frameTypeIndex, + unsigned char **framePtr, uint16_t *frameSizeInBits) { + if (iProtectedSize == 1) { /* A.2.1.3 Special case for 56 bit payload size (EVS Primary or EVS AMR-WB IO SID) */ + assert((payload[0] & 0x80) == 0); /* AMR-WB IO SID has no compact format and therefore is handled outside this function */ + *isAMRWB_IOmode = false; + *frameTypeIndex = 0; /* PRIMARY_2800 */ + } + else { + *isAMRWB_IOmode = evsPayloadProtectedSizes_isAMRWB_IOmode[iProtectedSize]; + *frameTypeIndex = evsPayloadProtectedSizes_frameTypeIndex[iProtectedSize]; + } + if (*isAMRWB_IOmode) { + evsPayload_unpackFrame_compact_amrWbIo(payload, payloadSizeBits, iProtectedSize, framePtr, frameSizeInBits); + } + else { + evsPayload_unpackFrame_compact_evsPrimary(payload, payloadSizeBits, framePtr, frameSizeInBits); + } +} + +bool evsPayload_unpackFrame(bool hf_only, const char *payload, uint16_t payloadSizeBytes, uint16_t frameIndex, + bool *isAMRWB_IOmode, bool *frameFollowing, uint16_t *frameTypeIndex, bool *qBit, + unsigned char **framePtr, uint16_t *frameSizeInBits) { + uint16_t payloadSizeBits = payloadSizeBytes * 8; + bool specialCaseIoSid = payloadSizeBits == 56 && (payload[0] & 0x80); /* A.2.1.3 Special case for 56 bit payload size */ + if (!hf_only && !specialCaseIoSid) { /* A.2.3.1 Default format handling */ + uint16_t i; + for (i = 0; i != sizeof(evsPayloadProtectedSizes) / sizeof(evsPayloadProtectedSizes)[0]; ++i) { + if (payloadSizeBits == evsPayloadProtectedSizes[i]) { + assert(frameIndex == 0); + *frameFollowing = false; + *qBit = true; + evsPayload_unpackFrame_compact(payload, payloadSizeBits, i, isAMRWB_IOmode, frameTypeIndex, framePtr, frameSizeInBits); + return true; + } + } + } /* else: A.2.3.2 Header-Full-only format handling */ + return evsHeaderFullPayload_unpackFrame(payload, payloadSizeBytes, frameIndex, isAMRWB_IOmode, + frameFollowing, frameTypeIndex, qBit, framePtr, frameSizeInBits); +} + +static void evsHeaderFullPayload_parseToc(uint8_t toc, bool *isAMRWB_IOmode, bool *frameFollowing, uint16_t *frameTypeIndex, bool *qBit, int32_t *bitrate) { + bool evsModeBit = (toc & 0x20) != 0; + *isAMRWB_IOmode = evsModeBit; + *frameFollowing = (toc & 0x40) != 0; + *frameTypeIndex = toc & 0x0f; + if (!*isAMRWB_IOmode) { + *qBit = true; /* assume good q_bit for the unused EVS-mode bit */ + *bitrate = PRIMARYmode2rate[*frameTypeIndex]; + } + else { + *qBit = (toc & 0x10) != 0; + *bitrate = AMRWB_IOmode2rate[*frameTypeIndex]; + } +} + +bool evsPayload_getFrameTypeFromSize(int16_t frameSizeBits, bool *isAMRWB_IOmode, uint16_t *frameTypeIndex) { + int16_t i; + int32_t rate = frameSizeBits * 50; + if (rate == 0) { + assert(0); /* VOIP_G192_RTP should not transmit empty frames */ + return false; /* no information available */ + } + for (i = 0; i <= 9; ++i) { + if (rate == AMRWB_IOmode2rate[i]) { + *isAMRWB_IOmode = true; + *frameTypeIndex = i; + return true; + } + } + for (i = 0; i <= 12; ++i) { + if (rate == PRIMARYmode2rate[i]) { + *isAMRWB_IOmode = false; + *frameTypeIndex = i; + return true; + } + } + return false; +} + +bool evsHeaderFullPayload_unpackFrame(const char *payload, uint16_t payloadSizeBytes, uint16_t frameIndex, + bool *isAMRWB_IOmode, bool *frameFollowing, uint16_t *frameTypeIndex, bool *qBit, + unsigned char **frame, uint16_t *frameSizeInBits) { + bool someIsAMRWB_IOmode, someFrameFollowing = true, someQBit; + uint16_t someFrameTypeIndex, someFrameSizeInBits; + int32_t bitrate; + uint16_t iFrame; + if (payloadSizeBytes < 1) { + fprintf(stderr, "Error: payload too small to parse ToC\n"); + return false; + } + /* skip CMR */ + if (*payload & 0x80) { + ++payload; + --payloadSizeBytes; + } + /* parse all ToC entries */ + *frame = (unsigned char *)payload; /* no need to copy frame bytes */ + for (iFrame = 0; someFrameFollowing; ++iFrame) { + if ((int16_t)payloadSizeBytes <= 0) { + fprintf(stderr, "Error: payload too small\n"); + return false; + } + if (*payload & 0x80) { + fprintf(stderr, "Error: expected ToC, found CMR\n"); + return false; + } + evsHeaderFullPayload_parseToc(*payload, &someIsAMRWB_IOmode, &someFrameFollowing, &someFrameTypeIndex, &someQBit, &bitrate); + if (bitrate < 0) { + fprintf(stderr, "Error: unexpected frameTypeIndex in ToC\n"); + return false; + } + ++payload; + ++*frame; + someFrameSizeInBits = (uint16_t)(bitrate / 50); + /* just keep/copy zero padding bits + * in case of AMRWB_IO_SID the STI bit and CMI bits following the SID_1k75 frame are also kept (A.2.2.1.3) */ + payloadSizeBytes -= 1 + (someFrameSizeInBits + 7) / 8; + if (iFrame < frameIndex) { + *frame += (someFrameSizeInBits + 7) / 8; + if (!someFrameFollowing) { + fprintf(stderr, "Error: expected ToC with F bit set\n"); + return false; + } + } + else if (iFrame == frameIndex) { + *isAMRWB_IOmode = someIsAMRWB_IOmode; + *frameFollowing = someFrameFollowing; + *frameTypeIndex = someFrameTypeIndex; + *qBit = someQBit; + *frameSizeInBits = someFrameSizeInBits; + } + if ((int16_t)payloadSizeBytes < 0) { + fprintf(stderr, "Error: payload too small for frame %u data\n", frameIndex); + return false; + } + } + return true; +} + +EVS_RTPDUMP_DEPACKER_ERROR EVS_RTPDUMP_DEPACKER_open(EVS_RTPDUMP_DEPACKER *self, FILE *file, bool hf_only) { + RTPDUMP_ERROR rtpdumpError; + self->hf_only = hf_only; + self->frameFollowing = false; + rtpdumpError = RTPDUMP_OpenWithFileToRead(&self->rtpdump, file); + if (rtpdumpError != RTPDUMP_NO_ERROR) { + return EVS_RTPDUMP_DEPACKER_RTPDUMP_ERROR; + } + return EVS_RTPDUMP_DEPACKER_NO_ERROR; +} + +EVS_RTPDUMP_DEPACKER_ERROR EVS_RTPDUMP_DEPACKER_readNextFrame( + EVS_RTPDUMP_DEPACKER *self, + uint16_t *rtpSequenceNumber, + uint32_t *rtpTimeStamp, + uint32_t *rcvTime_ms, + bool *isAMRWB_IOmode, + uint16_t *frameTypeIndex, + bool *qBit, + unsigned char **frame, + uint16_t *frameSizeBits) +{ + /* read next RTP packet from rtpdump */ + if (!self->frameFollowing) { + RTPDUMP_ERROR rtpdumpError = RTPDUMP_ReadPacket(self->rtpdump, &self->rtpPacket, &self->timeoffset_ms); + if (rtpdumpError == RTPDUMP_READ_ENDOFFILE) { + return EVS_RTPDUMP_DEPACKER_EOF; + } + else if (rtpdumpError != RTPDUMP_NO_ERROR) { + return EVS_RTPDUMP_DEPACKER_RTPDUMP_ERROR; + } + self->frameIndex = 0; + } + /* unpack next frame from RTP packet */ + if (!evsPayload_unpackFrame(self->hf_only, self->rtpPacket.data + self->rtpPacket.headerSize, + self->rtpPacket.payloadSize, self->frameIndex, + isAMRWB_IOmode, &self->frameFollowing, frameTypeIndex, qBit, + frame, frameSizeBits)) + { + return EVS_RTPDUMP_DEPACKER_PAYLOAD_ERROR; + } + /* return frame */ + *rtpSequenceNumber = self->rtpPacket.sequenceNumber; + *rtpTimeStamp = self->rtpPacket.timeStamp + self->frameIndex * 16000 / 50; + *rcvTime_ms = self->timeoffset_ms; + ++self->frameIndex; + return EVS_RTPDUMP_DEPACKER_NO_ERROR; +} + +void EVS_RTPDUMP_DEPACKER_close(EVS_RTPDUMP_DEPACKER *self) { + if (!self) { + return; + } + RTPDUMP_Close(&self->rtpdump, 0); +} diff --git a/lib_dec/evs_rtp_payload.h b/lib_dec/evs_rtp_payload.h new file mode 100644 index 0000000..e3901d5 --- /dev/null +++ b/lib_dec/evs_rtp_payload.h @@ -0,0 +1,173 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#pragma once +#include +#include +#include +#include "rtpdump.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static const int32_t AMRWB_IOmode2rate[16] = +{ + 6600, /* AMRWB_IO_6600 */ + 8850, /* AMRWB_IO_8850 */ + 12650, /* AMRWB_IO_1265 */ + 14250, /* AMRWB_IO_1425 */ + 15850, /* AMRWB_IO_1585 */ + 18250, /* AMRWB_IO_1825 */ + 19850, /* AMRWB_IO_1985 */ + 23050, /* AMRWB_IO_2305 */ + 23850, /* AMRWB_IO_2385 */ + 1750, /* AMRWB_IO_SID: SID_1k75 followed by STI bit and CMI bits (A.2.2.1.3) */ + -1, /* AMRWB_IO_FUT1 */ + -1, /* AMRWB_IO_FUT2 */ + -1, /* AMRWB_IO_FUT3 */ + -1, /* AMRWB_IO_FUT4 */ + 0, /* SPEECH_LOST */ + 0 /* NO_DATA */ +}; + +static const int32_t PRIMARYmode2rate[16] = +{ + 2800, /* PRIMARY_2800 */ + 7200, /* PRIMARY_7200 */ + 8000, /* PRIMARY_8000 */ + 9600, /* PRIMARY_9600 */ + 13200, /* PRIMARY_13200 */ + 16400, /* PRIMARY_16400 */ + 24400, /* PRIMARY_24400 */ + 32000, /* PRIMARY_32000 */ + 48000, /* PRIMARY_48000 */ + 64000, /* PRIMARY_64000 */ + 96000, /* PRIMARY_96000 */ + 128000, /* PRIMARY_128000 */ + 2400, /* PRIMARY_SID */ + -1, /* PRIMARY_FUT1 */ + 0, /* SPEECH_LOST */ + 0 /* NO_DATA */ +}; + +static const uint16_t evsPayloadProtectedSizes[22] = { + 48, + 56, + 136, + 144, + 160, + 184, + 192, + 256, + 264, + 288, + 320, + 328, + 368, + 400, + 464, + 480, + 488, + 640, + 960, + 1280, + 1920, + 2560 +}; + +static const bool evsPayloadProtectedSizes_isAMRWB_IOmode[22] = { + 0, + 0, /* Special case (see clause A.2.1.3) */ + 1, + 0, + 0, + 1, + 0, + 1, + 0, + 1, + 1, + 0, + 1, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0 +}; + +static const uint16_t evsPayloadProtectedSizes_frameTypeIndex[22] = { + 12, /* PRIMARY_SID */ + 0, /* Special case (see clause A.2.1.3) */ + 0, /* AMRWB_IO_6600 */ + 1, /* PRIMARY_7200 */ + 2, /* PRIMARY_8000 */ + 1, /* AMRWB_IO_8850 */ + 3, /* PRIMARY_9600 */ + 2, /* AMRWB_IO_1265 */ + 4, /* PRIMARY_13200 */ + 3, /* AMRWB_IO_1425 */ + 4, /* AMRWB_IO_1585 */ + 5, /* PRIMARY_16400 */ + 5, /* AMRWB_IO_1825 */ + 6, /* AMRWB_IO_1985 */ + 7, /* AMRWB_IO_2305 */ + 8, /* AMRWB_IO_2385 */ + 6, /* PRIMARY_24400 */ + 7, /* PRIMARY_32000 */ + 8, /* PRIMARY_48000 */ + 9, /* PRIMARY_64000 */ + 10, /* PRIMARY_96000 */ + 11 /* PRIMARY_128000 */ +}; + +bool evsPayload_unpackFrame(bool hf_only, const char *payload, uint16_t payloadSizeBytes, uint16_t frameIndex, + bool *isAMRWB_IOmode, bool *frameFollowing, uint16_t *frameTypeIndex, bool *qBit, + unsigned char **framePtr, uint16_t *frameSizeBits); + +bool evsPayload_getFrameTypeFromSize(int16_t frameSizeBits, bool *isAMRWB_IOmode, uint16_t *frameTypeIndex); + +bool evsHeaderFullPayload_unpackFrame(const char *payload, uint16_t payloadSizeBytes, uint16_t frameIndex, + bool *isAMRWB_IOmode, bool *frameFollowing, uint16_t *frameTypeIndex, bool *qBit, + unsigned char **frame, uint16_t *frameSizeBits); + +typedef struct { + RTPDUMP_HANDLE rtpdump; + bool hf_only; + RTPDUMP_RTPPACKET rtpPacket; + uint32_t timeoffset_ms; + uint16_t frameIndex; + bool frameFollowing; +} EVS_RTPDUMP_DEPACKER; + +typedef enum { + EVS_RTPDUMP_DEPACKER_NO_ERROR = 0, + EVS_RTPDUMP_DEPACKER_EOF = -1, + EVS_RTPDUMP_DEPACKER_RTPDUMP_ERROR = 1, + EVS_RTPDUMP_DEPACKER_PAYLOAD_ERROR +} EVS_RTPDUMP_DEPACKER_ERROR; + +EVS_RTPDUMP_DEPACKER_ERROR EVS_RTPDUMP_DEPACKER_open(EVS_RTPDUMP_DEPACKER *self, FILE *file, bool hf_only); + +EVS_RTPDUMP_DEPACKER_ERROR EVS_RTPDUMP_DEPACKER_readNextFrame( + EVS_RTPDUMP_DEPACKER *self, + uint16_t *rtpSequenceNumber, + uint32_t *rtpTimeStamp, + uint32_t *rcvTime_ms, + bool *isAMRWB_IOmode, + uint16_t *frameTypeIndex, + bool *qBit, + unsigned char **frame, + uint16_t *frameSizeBits); + +void EVS_RTPDUMP_DEPACKER_close(EVS_RTPDUMP_DEPACKER *self); + +#ifdef __cplusplus +} +#endif diff --git a/lib_dec/fd_cng_dec.c b/lib_dec/fd_cng_dec.c new file mode 100644 index 0000000..5f94890 --- /dev/null +++ b/lib_dec/fd_cng_dec.c @@ -0,0 +1,2181 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include "rom_com_fx.h" +#include "stat_dec_fx.h" +#include "stl.h" +#include "options.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "rom_basop_util.h" + + + + + + +/******************************** +* External tables * +********************************/ + +extern const Word16 T_DIV_L_Frame[]; /* format: 0Q15 * 2^-7 */ + + +/* + createFdCngDec + + Parameters: + + hFdCngDec i/0 : pointer to cng decoder structure + + Function: + create an instance of type FD_CNG +*/ +void createFdCngDec (HANDLE_FD_CNG_DEC *hFdCngDec) +{ + HANDLE_FD_CNG_DEC hs; + + /* Allocate memory */ + hs = (HANDLE_FD_CNG_DEC) calloc(1, sizeof (FD_CNG_DEC)); + + + createFdCngCom(&(hs->hFdCngCom)); + + *hFdCngDec = hs; +} + +Word16 initFdCngDec (HANDLE_FD_CNG_DEC hs, Word16 scale) +{ + /* Initialize common */ + + initFdCngCom( hs->hFdCngCom, scale ); + set16_fx( hs->olapBufferAna, 0, 320 ); + hs->hFdCngCom->olapBufferAna = hs->olapBufferAna; + move16(); + set16_fx( hs->olapBufferSynth2, 0, FFTLEN ); + hs->hFdCngCom->olapBufferSynth2 = hs->olapBufferSynth2; + move16(); + + /* Set some counters and flags */ + + hs->flag_dtx_mode = 0; + move16(); + hs->lp_noise = -167772160l/*-20.f Q23*/; /* format: Q8.24 */ + hs->lp_speech = 209715200l/* 25.f Q23*/; /* format: Q8.24 */ + + /* Initialization of the noise estimation algorithm */ + + set32_fx( hs->bandNoiseShape, 0, FFTLEN2 ); + set16_fx( &hs->bandNoiseShape_exp, 0, 1); + + set32_fx (hs->partNoiseShape, 0, NPART ); + set16_fx( &hs->partNoiseShape_exp, 0, 1); + + set32_fx( hs->msPeriodog, 0, NPART_SHAPING ); + set16_fx( &hs->msPeriodog_exp, 0, 1); + + set32_fx( hs->msAlpha, 0, NPART_SHAPING ); + + set32_fx( hs->msBminWin, 0, NPART_SHAPING ); + + set32_fx( hs->msBminSubWin, 0, NPART_SHAPING ); + + set16_fx( hs->msPsd, 0, NPART_SHAPING ); + set16_fx( hs->msNoiseFloor, 0, NPART_SHAPING ); + + set32_fx( hs->msNoiseEst, 0, NPART_SHAPING ); + set16_fx( &hs->msNoiseEst_exp, 0, 1); + + set32_fx( hs->msMinBuf, 2147483647l/*1.0 Q31*/, MSNUMSUBFR*NPART_SHAPING ); + + set32_fx( hs->msCurrentMin, 2147483647l/*1.0 Q31*/, NPART_SHAPING ); + + set32_fx( hs->msCurrentMinOut, 2147483647l/*1.0 Q31*/, NPART_SHAPING ); + + set32_fx( hs->msCurrentMinSubWindow, 2147483647l/*1.0 Q31*/, NPART_SHAPING ); + + set16_fx( hs->msLocalMinFlag, 0, NPART_SHAPING ); + set16_fx( hs->msNewMinFlag, 0, NPART_SHAPING ); + + set16_fx( hs->msPsdFirstMoment, 0, NPART_SHAPING ); + + set32_fx( hs->msPsdSecondMoment, 0, NPART_SHAPING ); + set16_fx( hs->msPeriodogBuf, 0, MSBUFLEN*NPART_SHAPING ); + + hs->msPeriodogBufPtr = 0; + move16(); + + set16_fx( hs->msLogPeriodog, 0, NPART_SHAPING ); + set16_fx( hs->msLogNoiseEst, 0, NPART_SHAPING ); + + set16_fx( hs->psize_shaping, 0, NPART_SHAPING ); + move16(); + hs->nFFTpart_shaping = 0; + + + return 0; +} + +/* + configureFdCngDec + + Parameters: + + hs i/o: Contains the variables related to the FD-based CNG process + numSlots i : Number of time slots in CLDFB matrix + numCoreBands i : Number of core bands + regularStopBand i : Number of CLDFB bands to be considered + CLDFBscale i : cldfb scale factor + + Function: + configure FD_CNG + + Returns: + void +*/ +void configureFdCngDec (HANDLE_FD_CNG_DEC hsDec, /* i/o: Contains the variables related to the CLDFB-based CNG process */ + Word16 bandwidth, + Word32 bitrate, + Word16 L_frame + ) +{ + Word16 j, stopBandFR; + HANDLE_FD_CNG_COM hsCom = hsDec->hFdCngCom; + + + hsCom->CngBandwidth = bandwidth; + IF ( EQ_16( hsCom->CngBandwidth, FB )) + { + hsCom->CngBandwidth = SWB; + } + test(); + if ( bitrate != FRAME_NO_DATA && NE_32(bitrate, SID_2k40)) + { + hsCom->CngBitrate = L_add(bitrate, 0); + } + hsCom->numSlots = 16; + move16(); + + /* NB configuration */ + IF ( bandwidth == NB ) + { + hsCom->FdCngSetup = FdCngSetup_nb; + hsCom->numCoreBands = 16; + move16(); + hsCom->regularStopBand = 16; + move16(); + } + + /* WB configuration */ + ELSE IF ( EQ_16(bandwidth, WB)) + { + /* FFT 6.4kHz, no CLDFB */ + test(); + test(); + IF ( LE_32(hsCom->CngBitrate, ACELP_8k00) + && EQ_16(L_frame,L_FRAME) + ) + { + hsCom->FdCngSetup = FdCngSetup_wb1; + hsCom->numCoreBands = 16; + move16(); + hsCom->regularStopBand = 16; + move16(); + } + /* FFT 6.4kHz, CLDFB 8.0kHz */ + ELSE IF ( LE_32(hsCom->CngBitrate, ACELP_13k20) + || EQ_16(L_frame,L_FRAME) + ) + { + hsCom->FdCngSetup = FdCngSetup_wb2; + hsCom->numCoreBands = 16; + move16(); + hsCom->regularStopBand = 20; + move16(); + IF ( + EQ_16(L_frame,L_FRAME16k) + ) + { + hsCom->FdCngSetup = FdCngSetup_wb2; + hsCom->numCoreBands = 20; + move16(); + hsCom->regularStopBand = 20; + move16(); + hsCom->FdCngSetup.fftlen = 640; + move16(); + hsCom->FdCngSetup.stopFFTbin = 256; + move16(); + } + } + /* FFT 8.0kHz, no CLDFB */ + ELSE + { + hsCom->FdCngSetup = FdCngSetup_wb3; + hsCom->numCoreBands = 20; + move16(); + hsCom->regularStopBand = 20; + move16(); + } + } + + /* SWB/FB configuration */ + ELSE + { + /* FFT 6.4kHz, CLDFB 14kHz */ + IF ( + EQ_16(L_frame,L_FRAME) + ) + { + hsCom->FdCngSetup = FdCngSetup_swb1; + hsCom->numCoreBands = 16; + move16(); + hsCom->regularStopBand = 35; + move16(); + } + /* FFT 8.0kHz, CLDFB 16kHz */ + ELSE + { + hsCom->FdCngSetup = FdCngSetup_swb2; + hsCom->numCoreBands = 20; + move16(); + hsCom->regularStopBand = 40; + move16(); + } + } + hsCom->fftlen = hsCom->FdCngSetup.fftlen; + move16(); + hsCom->stopFFTbin = hsCom->FdCngSetup.stopFFTbin; + move16(); + + /* Configure the SID quantizer and the Confort Noise Generator */ + + hsCom->startBand = 2; + move16(); + hsCom->stopBand = add( hsCom->FdCngSetup.sidPartitions[hsCom->FdCngSetup.numPartitions-1], 1 ); + initPartitions(hsCom->FdCngSetup.sidPartitions, hsCom->FdCngSetup.numPartitions, hsCom->startBand, hsCom->stopBand, hsCom->part, &hsCom->npart, hsCom->midband, hsCom->psize, hsCom->psize_norm, &hsCom->psize_norm_exp, hsCom->psize_inv, 0); + + hsCom->nFFTpart = 21; + move16(); + if ( EQ_16(hsCom->stopFFTbin, 256)) + { + hsCom->nFFTpart = 20; + move16(); + } + if ( EQ_16(hsCom->stopFFTbin, 160)) + { + hsCom->nFFTpart = 17; + move16(); + } + + hsCom->nCLDFBpart = sub( hsCom->npart, hsCom->nFFTpart ); + FOR(j=0; jnCLDFBpart; j++) + { + hsCom->CLDFBpart[j] = sub( hsCom->part[j+hsCom->nFFTpart], (hsCom->stopFFTbin-hsCom->startBand) ); + move16(); + hsCom->CLDFBpsize_inv[j] = hsCom->psize_inv[j+hsCom->nFFTpart]; + move16(); + } + + stopBandFR = 1000/25; + if ( GT_16(stopBandFR, hsCom->stopFFTbin)) + { + stopBandFR = hsCom->stopFFTbin; + move16(); + } + initPartitions(hsCom->FdCngSetup.shapingPartitions, hsCom->FdCngSetup.numShapingPartitions, + hsCom->startBand, hsCom->stopFFTbin, hsDec->part_shaping, &hsDec->npart_shaping, hsDec->midband_shaping, + hsDec->psize_shaping, hsDec->psize_shaping_norm, &hsDec->psize_shaping_norm_exp, hsDec->psize_inv_shaping, + stopBandFR ); + hsDec->nFFTpart_shaping = hsDec->npart_shaping; + move16(); + + SWITCH (hsCom->fftlen) + { + case 512: + hsCom->fftlenShift = 8; + move16(); + hsCom->fftlenFac = 32767/*1.0 Q15*/; + move16(); + BREAK; + case 640: + hsCom->fftlenShift = 9; + move16(); + hsCom->fftlenFac = 20480/*0.625 Q15*/; + move16(); + BREAK; + default: + assert(!"Unsupported FFT length for FD-based CNG"); + BREAK; + } + BASOP_getTables( &hsCom->olapWinAna, NULL, NULL, shr(hsCom->fftlen, 1)); + BASOP_getTables( &hsCom->olapWinSyn, NULL, NULL, shr(hsCom->fftlen, 2)); + hsCom->frameSize = shr(hsCom->fftlen,1); + +} + + +/* + deleteFdCngDec + + Parameters: + + hFdCngDec i/0 : pointer to cng decoder structure + + Function: + delete the instance of type FD_CNG + + Returns: + void +*/ +void deleteFdCngDec (HANDLE_FD_CNG_DEC *hFdCngDec) +{ + HANDLE_FD_CNG_DEC hsDec = *hFdCngDec; + + IF ( hsDec != NULL ) + { + deleteFdCngCom (&(hsDec->hFdCngCom)); + free(hsDec); + *hFdCngDec = NULL; + } +} + + +/* + ApplyFdCng + + Parameters: + + timeDomainInput, i : pointer to time domain input + cldfbBufferReal i/o: real part of the CLDFB buffer + cldfbBufferImag i/o: imaginary part of the CLDFB buffer + cldfbBufferScale o : pointer to the scalefactor for real and imaginary part of the CLDFB buffer + st i/o: pointer to FD_CNG structure containing all buffers and variables + m_frame_type i : type of frame at the decoder side + stcod i : pointer to Coder_State structure + stdec i : pointer to Decoder_State structure + bitrate i : bitrate + concealWholeFrame i : binary flag indicating frame loss + + Function: + apply the CLDFB-based CNG at the decoder + + Returns: + error +*/ +Word16 ApplyFdCng (Word16 *timeDomainInput, /* i : pointer to time domain input */ + Word16 Q, + Word32 **cldfbBufferReal, /* i/o: real part of the CLDFB buffer */ + Word32 **cldfbBufferImag, /* i/o: imaginary part of the CLDFB buffer */ + Word16 *cldfbBufferScale, /* o : pointer to the scalefactor for real and imaginary part of the CLDFB buffer */ + HANDLE_FD_CNG_DEC st, /* i/o: pointer to FD_CNG structure containing all buffers and variables */ + Word16 m_frame_type, /* i : type of frame at the decoder side */ + Decoder_State_fx *stdec, + const Word16 concealWholeFrame, /* i : binary flag indicating frame loss */ + Word16 is_music + ) +{ + Word16 j, k, nBins; + Word16 s, s1, s2, num, denom; + Word32 *cngNoiseLevel; + Word16 *cngNoiseLevel_exp; + Word32 L_tmp; + Word16 L_tmp_exp; + Word16 facTab[NPART]; + Word16 facTabExp[NPART]; + Word16 tmp_loop; + Word32 L_c; + Word16 lsp_cng[M]; + + + if(EQ_16(st->hFdCngCom->frame_type_previous,ACTIVE_FRAME)) + { + st->hFdCngCom->inactive_frame_counter = 0; + move16(); + } + + cngNoiseLevel = st->hFdCngCom->cngNoiseLevel; + cngNoiseLevel_exp = &st->hFdCngCom->cngNoiseLevelExp; + + nBins = sub(st->hFdCngCom->stopFFTbin,st->hFdCngCom->startBand); + + SWITCH ( m_frame_type ) + { + case ACTIVE_FRAME: + + /************************** + * ACTIVE_FRAME at DECODER * + **************************/ + + st->hFdCngCom->inactive_frame_counter = 0; + move16(); + st->hFdCngCom->sid_frame_counter = 0; + move16(); + + /* set noise estimation inactive during concealment, as no update with noise generated by concealment should be performed. */ + /* set noise estimation inactive during concealment, no update with noise generated by concealment should be performed. */ + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( + (concealWholeFrame == 0) && + (*timeDomainInput < MAXVAL_WORD16) && (*timeDomainInput > MINVAL_WORD16) && (*(timeDomainInput+st->hFdCngCom->frameSize-1) < MAXVAL_WORD16) && (*(timeDomainInput+st->hFdCngCom->frameSize-1) > MINVAL_WORD16) + && ( ((st->flag_dtx_mode == 0) && (stdec->VAD != 0)) == 0 ) + && ( ((stdec->cng_type_fx == LP_CNG) && (st->flag_dtx_mode != 0)) == 0) + && ( is_music == 0 ) + && (stdec->BER_detect == 0) + ) + { + /* Perform noise estimation at the decoder */ + perform_noise_estimation_dec ( + timeDomainInput, + Q, + st + ); + + + /* Update the shaping parameters */ + scalebands ( + st->msNoiseEst, + st->part_shaping, + st->nFFTpart_shaping, + st->midband_shaping, + st->nFFTpart_shaping, + nBins, + st->bandNoiseShape, + 1 + ); + + st->bandNoiseShape_exp = st->msNoiseEst_exp; + move16(); + + + /* Update CNG levels */ + test(); + IF ( st->flag_dtx_mode != 0 && stdec->cng_type_fx == FD_CNG ) + { + /* This needs to be done only once per inactive phase */ + bandcombinepow ( + st->bandNoiseShape, + st->bandNoiseShape_exp, + nBins, + st->hFdCngCom->part, + st->hFdCngCom->nFFTpart, + st->hFdCngCom->psize_inv, + st->partNoiseShape, + &st->partNoiseShape_exp + ); + + + j = 0; + move16(); + s2 = -(WORD32_BITS-1); + move16(); + FOR (k=0; k < st->hFdCngCom->nFFTpart; k++) + { + assert(st->partNoiseShape[k]>=0); + assert(st->hFdCngCom->sidNoiseEst[k]>=0); + + /* add DELTA as it is done in FLC version, in order to avoid num > denom */ + facTab[k] = 0; + move16(); + IF ( st->partNoiseShape[k] != 0) + { + s1 = norm_l(st->hFdCngCom->sidNoiseEst[k]); + L_tmp = L_shl(st->hFdCngCom->sidNoiseEst[k], s1); + L_tmp_exp = sub(st->hFdCngCom->sidNoiseEstExp, s1); + L_tmp = BASOP_Util_Add_Mant32Exp(L_tmp, L_tmp_exp, DELTA_MANTISSA_W32, DELTA_EXPONENT, &L_tmp_exp); + L_tmp = L_shr(L_tmp, 1); + s = add(L_tmp_exp, 1); + num = extract_h(L_tmp); + + s1 = norm_l(st->partNoiseShape[k]); + L_tmp = L_shl(st->partNoiseShape[k], s1); + L_tmp_exp = sub(st->partNoiseShape_exp, s1); + L_tmp = BASOP_Util_Add_Mant32Exp(L_tmp, L_tmp_exp, DELTA_MANTISSA_W32, DELTA_EXPONENT, &L_tmp_exp); + s = sub(s, L_tmp_exp); + denom = extract_h(L_tmp); + + facTab[k] = div_s(num,denom); + move16(); + facTabExp[k] = s; + move16(); + } + /* Set unique exponent, if mantissa is equal to zero */ + if (facTab[k] == 0) + { + facTabExp[k] = -(WORD32_BITS-1); + move16(); + } + s2 = s_max(s2,facTabExp[k]); + } + + FOR (k=0; k < st->hFdCngCom->nFFTpart; k++) + { + s = sub(facTabExp[k],s2); + s = s_max(s_min(s,WORD32_BITS-1),-(WORD32_BITS-1)); + FOR ( ; j <= st->hFdCngCom->part[k]; j++) + { + cngNoiseLevel[j] = L_shl(Mpy_32_16_1(st->bandNoiseShape[j],facTab[k]),s); + move32(); + } + } + + /* adapt scaling for rest of the buffer */ + IF (NE_16(s2,-(WORD32_BITS-1))) + { + s = sub(*cngNoiseLevel_exp,add(st->bandNoiseShape_exp,s2)); + FOR ( ; k < st->hFdCngCom->npart; k++) + { + FOR( ; j <= st->hFdCngCom->part[k]; j++) + { + cngNoiseLevel[j] = L_shl(cngNoiseLevel[j],s); + move32(); + } + } + + *cngNoiseLevel_exp = add(st->bandNoiseShape_exp,s2); + move16(); + } + } + ELSE + { + /* This sets the new CNG levels until a SID update overwrites it */ + Copy32 ( + st->bandNoiseShape, + cngNoiseLevel, + nBins + ); + + *cngNoiseLevel_exp = st->bandNoiseShape_exp; + move16(); + } + /*stdec->cngTDLevel = (float)sqrt( (sumFLOAT(cngNoiseLevel, st->hFdCngCom->stopFFTbin - st->hFdCngCom->startBand) / 2 * st->hFdCngCom->fftlen) / stdec->Mode2_L_frame);*/ + tmp_loop = sub(st->hFdCngCom->stopFFTbin , st->hFdCngCom->startBand); + L_tmp = L_deposit_h(0); + L_c = L_deposit_h(0); + FOR(j = 0 ; j < tmp_loop; j++) + { + + Carry = 0; + L_tmp = L_add_c(L_tmp,*(cngNoiseLevel+j)); + Overflow = 0; + + if(*(cngNoiseLevel+j) < 0) + { + L_c = L_msuNs(L_c,0,0); + } + if(*(cngNoiseLevel+j) >= 0) + { + L_c = L_macNs(L_c,0,0); + } + } + L_tmp = norm_llQ31(L_c,L_tmp,&L_tmp_exp); + L_tmp_exp = sub(add(L_tmp_exp,*cngNoiseLevel_exp),1); + + L_tmp = Mpy_32_16_1(L_tmp,st->hFdCngCom->fftlen); /*Q16*/ + + L_tmp = Mpy_32_16_1(L_tmp,T_DIV_L_Frame[L_shl(L_mac(-28000,stdec->L_frame_fx,95),1-15)]);/*Q16,exp -7*/ + L_tmp_exp = add(L_tmp_exp,-7); /*->Q16, L_tmp_exp */ + L_tmp_exp = add(L_tmp_exp,31-16); /*->Q31, L_tmp_exp*/ + + stdec->cngTDLevel = round_fx(Sqrt32(L_tmp, &L_tmp_exp)); + stdec->cngTDLevel_e = L_tmp_exp; + move16(); + + + } + test(); + test(); + L_tmp = 0; + FOR( j=st->hFdCngCom->startBand; jhFdCngCom->stopFFTbin; j++ ) + { + L_tmp = L_add(L_tmp,L_shr(cngNoiseLevel[j],16)); + } + L_tmp_exp = add(*cngNoiseLevel_exp,16); + IF (EQ_16(concealWholeFrame,1)&&EQ_16(stdec->nbLostCmpt,1)&&(L_shl(L_tmp,L_tmp_exp)>21474836 /*0.01f Q31*/)) + { + /* update isf cng estimate for concealment. Do that during concealment, in order to avoid addition clean channel complexity*/ + lpc_from_spectrum(cngNoiseLevel, *cngNoiseLevel_exp, st->hFdCngCom->startBand, st->hFdCngCom->stopFFTbin, st->hFdCngCom->fftlen, st->hFdCngCom->A_cng, + M, 0); + E_LPC_a_lsp_conversion( st->hFdCngCom->A_cng, lsp_cng, stdec->lspold_cng, M ); + Copy( lsp_cng, stdec->lspold_cng, M); + + lsp2lsf_fx( lsp_cng, stdec->lsf_cng, M, stdec->sr_core ); + stdec->plcBackgroundNoiseUpdated = 1; + move16(); + } + BREAK; + + case SID_FRAME: + + st->flag_dtx_mode = 1; + move16(); + /* no break */ + + case ZERO_FRAME: + + test(); + IF(stdec!=NULL && stdec->cng_type_fx==LP_CNG) + { + /* Perform noise estimation on inactive phase at the decoder */ + perform_noise_estimation_dec(timeDomainInput, Q, st + ); + + /* Update the shaping parameters */ + scalebands(st->msNoiseEst, st->part_shaping, st->nFFTpart_shaping, st->midband_shaping, st->nFFTpart_shaping, st->hFdCngCom->stopFFTbin-st->hFdCngCom->startBand, st->bandNoiseShape, 1); + st->bandNoiseShape_exp = st->msNoiseEst_exp; + move16(); + /* This sets the new CNG levels until a SID update overwrites it */ + Copy32(st->bandNoiseShape, cngNoiseLevel, st->hFdCngCom->stopFFTbin-st->hFdCngCom->startBand); /* This sets the new CNG levels until a SID update overwrites it */ + *cngNoiseLevel_exp = st->bandNoiseShape_exp; + move16(); + + /*stdec->cngTDLevel = (float)sqrt( (sumFLOAT(cngNoiseLevel, st->hFdCngCom->stopFFTbin - st->hFdCngCom->startBand) / 2 * st->hFdCngCom->fftlen) / stdec->Mode2_L_frame);*/ + tmp_loop = sub(st->hFdCngCom->stopFFTbin , st->hFdCngCom->startBand); + L_tmp = L_deposit_h(0); + L_c = L_deposit_h(0); + FOR(j = 0 ; j < tmp_loop; j++) + { + + Carry = 0; + L_tmp = L_add_c(L_tmp,*(cngNoiseLevel+j)); + Overflow = 0; + + if(*(cngNoiseLevel+j) < 0) + { + L_c = L_msuNs(L_c,0,0); + } + if(*(cngNoiseLevel+j) >= 0) + { + L_c = L_macNs(L_c,0,0); + } + } + L_tmp = norm_llQ31(L_c,L_tmp,&L_tmp_exp); + L_tmp_exp = sub(add(L_tmp_exp,*cngNoiseLevel_exp),1); + + L_tmp = Mpy_32_16_1(L_tmp,st->hFdCngCom->fftlen); /*Q16*/ + + L_tmp = Mpy_32_16_1(L_tmp,T_DIV_L_Frame[L_shl(L_mac(-28000,stdec->L_frame_fx,95),1-15)]);/*Q16,exp -7*/ + L_tmp_exp = add(L_tmp_exp,-7); /*->Q16, L_tmp_exp */ + L_tmp_exp = add(L_tmp_exp,31-16); /*->Q31, L_tmp_exp*/ + + stdec->cngTDLevel = round_fx(Sqrt32(L_tmp, &L_tmp_exp)); + stdec->cngTDLevel_e = L_tmp_exp; + move16(); + + BREAK; + } + st->hFdCngCom->inactive_frame_counter = add(st->hFdCngCom->inactive_frame_counter,1); + move16(); + + /************************************* + * SID_FRAME or ZERO_FRAME at DECODER * + *************************************/ + + /* Detect first non-active frame */ + IF ( EQ_16(st->hFdCngCom->inactive_frame_counter,1)) + { + /* Compute the fine spectral structure of the comfort noise shape using the decoder-side noise estimates */ + bandcombinepow ( + st->bandNoiseShape, + st->bandNoiseShape_exp, + nBins, + st->hFdCngCom->part, + st->hFdCngCom->nFFTpart, + st->hFdCngCom->psize_inv, + st->partNoiseShape, + &st->partNoiseShape_exp + ); + } + + IF ( EQ_16(m_frame_type,SID_FRAME)) + { + IF ( LT_32(st->hFdCngCom->msFrCnt_init_counter,L_deposit_l(st->hFdCngCom->msFrCnt_init_thresh))) + { + /* At initialization, interpolate the bin/band-wise levels from the partition levels */ + scalebands ( + st->hFdCngCom->sidNoiseEst, + st->hFdCngCom->part, + st->hFdCngCom->npart, + st->hFdCngCom->midband, + st->hFdCngCom->nFFTpart, + sub(st->hFdCngCom->stopBand,st->hFdCngCom->startBand), + cngNoiseLevel, + 1 + ); + *cngNoiseLevel_exp = st->hFdCngCom->sidNoiseEstExp; + move16(); + } + ELSE + { + /* Interpolate the CLDFB band levels from the SID (partition) levels */ + IF ( GT_16( st->hFdCngCom->regularStopBand, st->hFdCngCom->numCoreBands )) + { + scalebands ( + st->hFdCngCom->sidNoiseEst, + st->hFdCngCom->part, + st->hFdCngCom->npart, + st->hFdCngCom->midband, + st->hFdCngCom->nFFTpart, + sub(st->hFdCngCom->stopBand,st->hFdCngCom->startBand), + cngNoiseLevel, + 0 + ); + + *cngNoiseLevel_exp = st->hFdCngCom->sidNoiseEstExp; + move16(); + } + + s2 = -(WORD32_BITS-1); + move16(); + /* Shape the SID noise levels in each FFT bin */ + j = 0; + move16(); + FOR (k=0; k < st->hFdCngCom->nFFTpart ; k++) + { + assert(st->partNoiseShape[k]>=0); + + /* add DELTA as it is done in FLC version, in order to avoid num > denom */ + facTab[k] = 0; + move16(); + IF ( st->partNoiseShape[k] != 0) + { + s1 = norm_l(st->hFdCngCom->sidNoiseEst[k]); + L_tmp = L_shl(st->hFdCngCom->sidNoiseEst[k], s1); + L_tmp_exp = sub(st->hFdCngCom->sidNoiseEstExp, s1); + L_tmp = BASOP_Util_Add_Mant32Exp(st->hFdCngCom->sidNoiseEst[k], st->hFdCngCom->sidNoiseEstExp, DELTA_MANTISSA_W32, DELTA_EXPONENT, &L_tmp_exp); + L_tmp = L_shr(L_tmp, 1); + s = add(L_tmp_exp, 1); + num = extract_h(L_tmp); + + s1 = norm_l(st->partNoiseShape[k]); + L_tmp = L_shl(st->partNoiseShape[k], s1); + L_tmp_exp = sub(st->partNoiseShape_exp, s1); + L_tmp = BASOP_Util_Add_Mant32Exp(L_tmp, L_tmp_exp, DELTA_MANTISSA_W32, DELTA_EXPONENT, &L_tmp_exp); + s = sub(s, L_tmp_exp); + denom = extract_h(L_tmp); + + facTab[k] = div_s(num,denom); + move16(); + facTabExp[k] = s; + move16(); + } + /* Set unique exponent, if mantissa is equal to zero */ + if (facTab[k] == 0) + { + facTabExp[k] = -(WORD32_BITS-1); + move16(); + } + s2 = s_max(s2,facTabExp[k]); + } + + FOR (k=0; k < st->hFdCngCom->nFFTpart; k++) + { + s = sub(facTabExp[k],s2); + s = s_max(s_min(s,WORD32_BITS-1),-(WORD32_BITS-1)); + FOR( ; j <= st->hFdCngCom->part[k]; j++) + { + cngNoiseLevel[j] = L_shl(Mpy_32_16_1(st->bandNoiseShape[j],facTab[k]),s); + move32(); + } + } + /* adapt scaling for rest of the buffer */ + s = sub(*cngNoiseLevel_exp,add(st->bandNoiseShape_exp,s2)); + FOR ( ; k < st->hFdCngCom->npart; k++) + { + FOR( ; j <= st->hFdCngCom->part[k]; j++) + { + cngNoiseLevel[j] = L_shl(cngNoiseLevel[j],s); + move32(); + } + } + *cngNoiseLevel_exp = add(st->bandNoiseShape_exp,s2); + move16(); + } + } + + + IF ( EQ_16(stdec->codec_mode, MODE2)) + { + /* Generate comfort noise during SID or zero frames */ + generate_comfort_noise_dec ( + cldfbBufferReal, + cldfbBufferImag, + cldfbBufferScale, + stdec, + &(stdec->Q_exc), + 2 + ); + } + + BREAK; + + default: + return -1; + } + + + return 0; +} + + +/* + perform_noise_estimation_dec + + Parameters: + + timeDomainInput, i: pointer to time domain input + bitrate, i: bitrate + st i/o: FD_CNG structure containing all buffers and variables + + Function: + perform noise estimation + + Returns: + void +*/ +void perform_noise_estimation_dec (const Word16 *timeDomainInput, /* i: pointer to time domain input */ + Word16 Q, + HANDLE_FD_CNG_DEC st /* i/o: FD_CNG structure containing all buffers and variables */ + ) +{ + Word16 i, tmp_r, tmp_i, fac, fftBuffer_exp; + Word16 s, len, npart, nFFTpart; + Word16 startBand, stopFFTbin; + + Word16 *part, *psize_inv, *psize_norm; + Word32 tmp, *fftBuffer, *periodog, *ptr_per, *ptr_r, *ptr_i; + + + + /* pointer initialization */ + periodog = st->hFdCngCom->periodog; + fftBuffer = st->hFdCngCom->fftBuffer; + + part = st->part_shaping; + psize_inv = st->psize_inv_shaping; + psize_norm = st->psize_shaping_norm; + + /* variable initialization */ + startBand = st->hFdCngCom->startBand; + move16(); + stopFFTbin = st->hFdCngCom->stopFFTbin; + move16(); + + npart = st->npart_shaping; + move16(); + nFFTpart = st->nFFTpart_shaping; + move16(); + + /* Perform STFT analysis */ + AnalysisSTFT ( + timeDomainInput, + Q, + fftBuffer, + &fftBuffer_exp, + st->hFdCngCom + ); + + fftBuffer_exp = add(fftBuffer_exp,WORD16_BITS-1); + + + assert(startBand != 0); + + len = sub(stopFFTbin, startBand); + + s = getScaleFactor32 (&fftBuffer[2*startBand], 2*len); + s = sub(s,1); + + ptr_per = periodog; + IF ( startBand == 0 ) + { + /* DC component */ + tmp_r = extract_h(L_shl(fftBuffer[0],s)); + + tmp = L_mult(tmp_r, tmp_r); + *ptr_per = tmp; + + ptr_per++; + ptr_r = fftBuffer + 2; + len = sub(len, 1); + } + ELSE + { + ptr_r = fftBuffer + shl(startBand, 1); + } + + ptr_i = ptr_r+1; + FOR (i=0; i < len; i++) + { + tmp_r = extract_h(L_shl(*ptr_r,s)); + tmp_i = extract_h(L_shl(*ptr_i,s)); + + tmp = L_mac(L_mult(tmp_r, tmp_r),tmp_i, tmp_i); + *ptr_per = tmp; + + ptr_r += 2; + ptr_i += 2; + ptr_per++; + } + + st->hFdCngCom->periodog_exp = shl(sub(fftBuffer_exp,s),1); + + /* Rescale */ + assert( (st->hFdCngCom->fftlen == 640) || (st->hFdCngCom->fftlen == 512) || (st->hFdCngCom->fftlen == 320) ); + + fac = 20972/*0.64 Q15*/; + move16(); + if( EQ_16(st->hFdCngCom->fftlen,512)) + { + fac = 16384/*0.5 Q15*/; + move16(); + } + + if ( EQ_16(st->hFdCngCom->fftlen,640)) + { + s = 18; + move16(); + } + if ( EQ_16(st->hFdCngCom->fftlen,512)) + { + s = 17; + move16(); + } + if ( EQ_16(st->hFdCngCom->fftlen,320)) + { + s = 16; + move16(); + } + + len = sub(stopFFTbin, startBand); + FOR (i=0; i < len; i++) + { + st->hFdCngCom->periodog[i] = Mpy_32_16_1(st->hFdCngCom->periodog[i],fac); + } + st->hFdCngCom->periodog_exp = add(st->hFdCngCom->periodog_exp,sub(2,s)); + + + /* Adjust to the desired frequency resolution by averaging over spectral partitions for SID transmission */ + bandcombinepow(periodog, st->hFdCngCom->periodog_exp, sub(stopFFTbin,startBand), part, npart, psize_inv, st->msPeriodog, &st->msPeriodog_exp); + + + st->msPeriodog_exp_fft = st->msPeriodog_exp; + move16(); + st->msPeriodog_exp_cldfb = st->msPeriodog_exp; + move16(); + + + /* Compress MS inputs */ + compress_range(st->msPeriodog, st->msPeriodog_exp, st->msLogPeriodog, npart); + + /* Call the minimum statistics routine for noise estimation */ + minimum_statistics ( + npart, + nFFTpart, + psize_norm, + st->msLogPeriodog, + st->msNoiseFloor, + st->msLogNoiseEst, + st->msAlpha, + st->msPsd, + st->msPsdFirstMoment, + st->msPsdSecondMoment, + st->msMinBuf, + st->msBminWin, + st->msBminSubWin, + st->msCurrentMin, + st->msCurrentMinOut, + st->msCurrentMinSubWindow, + st->msLocalMinFlag, + st->msNewMinFlag, + st->msPeriodogBuf, + &(st->msPeriodogBufPtr), + st->hFdCngCom + ); + + /* Expand MS outputs */ + expand_range(st->msLogNoiseEst, st->msNoiseEst, &st->msNoiseEst_exp, npart); + +} + + + +/* + FdCng_decodeSID + + Parameters: + + st i/o: FD_CNG structure containing all buffers and variables + bs_word16 i : Bitstream + amrwb_io i : amr wideband mode + preemph_fac i : preemphase factor + + Function: + decode the FD-CNG bitstream + + Returns: + void +*/ +void FdCng_decodeSID (HANDLE_FD_CNG_COM st, Decoder_State_fx *corest) +{ + Word16 i, N, index; + Word32 *sidNoiseEst; + + Word16 indices[32], v16[32]; + Word32 v[32], gain; + + Word32 tmp, maxVal, E_ExpLd64; + Word16 sidNoiseEst_Exp; + + Word16 preemph_fac; + + + sidNoiseEst = st->sidNoiseEst; + move16(); + preemph_fac = corest->preemph_fac; + move16(); + + N = st->npart; + move16(); + + st->sid_frame_counter = add(st->sid_frame_counter,1); + move16(); + + /* Read bitstream */ + FOR (i=0; i= 0; maxVal -= 33554432l/*0.015625 Q31*/) + { + sidNoiseEst_Exp = add(sidNoiseEst_Exp,1); + } + st->sidNoiseEstExp = sidNoiseEst_Exp; + move16(); + E_ExpLd64 = L_shl(sidNoiseEst_Exp, WORD32_BITS-1-LD_DATA_SCALE); + + /* format v: Q9.23, format sidNoiseEst: Q6.26, 0.66438561897 = log10(10)/log10(2.0) / 10.0 * 2.0 */ + FOR (i=0; isidNoiseEst[i] = BASOP_Util_InvLog2(tmp); + move32(); + } + + /* NB last band energy compensation */ + IF ( st->CngBandwidth == NB ) + { + st->sidNoiseEst[N-1] = Mpy_32_16_1(st->sidNoiseEst[N-1], NB_LAST_BAND_SCALE); + move32(); + } + + test(); + if ( st->CngBandwidth == SWB && st->CngBitrate <= ACELP_13k20 ) + { + st->sidNoiseEst[N-1] = Mpy_32_16_1(st->sidNoiseEst[N-1], SWB_13k2_LAST_BAND_SCALE); + } + + + scalebands (sidNoiseEst, st->part, st->npart, st->midband, st->nFFTpart, st->stopBand-st->startBand, st->cngNoiseLevel, 1); + st->cngNoiseLevelExp = st->sidNoiseEstExp; + move16(); + + + lpc_from_spectrum (st->cngNoiseLevel, st->cngNoiseLevelExp, st->startBand, st->stopFFTbin, st->fftlen, st->A_cng, M, preemph_fac); + + +} + + +/* + noisy_speech_detection + + Parameters: + + vad i : VAD decision + Etot i : total channel E + Etot_exp i : exponent for total channel E + totalNoise i : noise estimate over all critical bands + totalNoise_exp i : exponent for noise estimate over all critical bands + lp_noise i/o: pointer to long term total Noise energy average + lp_speech i/o: pointer to long term active speech energy average + + Function: + detector for noisy speech, lp_noise and lp_speech are scaled by LD_DATA_SCALE+2 bits + + Returns: flag, that indicates whether noisy speech has been detected + + void +*/ +void noisy_speech_detection (const Word16 vad, + const Word16 *ftimeInPtr, /* i : input time-domain frame */ + const Word16 frameSize, /* i : frame size */ + const Word16 Q, + const Word32 *msNoiseEst, /* i : noise estimate over all critical bands */ + const Word16 msNoiseEst_exp, /* i : exponent for noise estimate over all critical bands */ + const Word16 *psize_norm, + const Word16 psize_norm_exp, + const Word16 nFFTpart, /* i : Number of partitions taken into account */ + Word32 *lp_noise, /* i/o: pointer to long term total Noise energy average */ + Word32 *lp_speech, /* i/o: pointer to long term active speech energy average */ + Word16 *flag_noisy_speech + ) +{ + Word16 i; + Word32 tmp; + Word32 Etot; + Word16 Etot_exp; + Word32 logEtot; + Word32 logEtotExp; + Word32 totalNoise; + Word16 totalNoise_exp; + Word32 logTotalNoise; + Word32 logTotalNoiseExp; + + + IF ( vad == 0 ) + { + totalNoise = dotWord32_16_Mant32Exp(msNoiseEst, msNoiseEst_exp, psize_norm, psize_norm_exp, nFFTpart, &totalNoise_exp); + + /* + - logTotalNoise is scaled by LD_DATA_SCALE+2 + - logTotalNoise = 10.0 * log10(totalNoise + DELTA); + - constant: -0.78125 = 10.0*log10(DELTA)/(1<<(LD_DATA_SCALE+2)) + - constant: 0.75257498916 = 10.0 * log10(2.0)/log10(10.0)/(1<<2) + */ + IF ( totalNoise == 0 ) + { + logTotalNoise = L_add(-1677721600l/*-0.78125 Q31*/, 0); + } + ELSE + { + logTotalNoise = BASOP_Util_Log2(totalNoise); + logTotalNoiseExp = L_shl(L_deposit_l(totalNoise_exp),WORD32_BITS-1-LD_DATA_SCALE); + logTotalNoise = Mpy_32_16_1(L_add(logTotalNoise,logTotalNoiseExp),24660/*0.75257498916 Q15*/); + } + + *lp_noise = L_add(Mpy_32_16_1(*lp_noise,32604/*0.995 Q15*/),L_shr(Mpy_32_16_1(logTotalNoise,20972/*0.64 Q15*/),7)); + move32(); + } + ELSE + { + Etot = 0; + Etot_exp = 31; + FOR( i = 0; i < frameSize ; i++ ) + { + tmp = L_shr_r( L_mult0( ftimeInPtr[i], ftimeInPtr[i] ), sub( Etot_exp, 31 ) ); + IF( L_sub( maxWord32, tmp ) < Etot ) + { + Etot_exp = add( Etot_exp, 1 ); + Etot = L_shr_r( Etot, 1 ); + tmp = L_shr_r( tmp, 1 ); + } + Etot = L_add( Etot, tmp ); + } + Etot_exp = sub( Etot_exp, shl( Q, 1 ) ); + + /* + - logEtot is scaled by LD_DATA_SCALE+2 + - logEtot = 10.0 * log10(totalNoise + DELTA); + - constant: -0.78125 = 10.0*log10(DELTA)/(1<<(LD_DATA_SCALE+2)) + - constant: 0.75257498916 = 10.0 * log10(2.0)/log10(10.0)/(1<<2) + */ + IF ( Etot == 0 ) + { + logEtot = L_add(-1677721600l/*-0.78125 Q31*/, 0); + } + ELSE + { + logEtot = BASOP_Util_Log2(Etot); + logEtotExp = L_shl(L_deposit_l(Etot_exp),WORD32_BITS-1-LD_DATA_SCALE); + logEtot = Mpy_32_16_1(L_add(logEtot,logEtotExp),24660/*0.75257498916 Q15*/); + IF ( EQ_16( frameSize, L_FRAME16k )) + { + logEtot = L_add( logEtot, -184894985l/*-0.086098436822497 Q31*/ ); + } + ELSE + { + logEtot = L_add( logEtot, -176765584l/*-0.082312889439370 Q31*/ ); + } + } + + *lp_speech = L_add(Mpy_32_16_1(*lp_speech,32604/*0.995 Q15*/),L_shr(Mpy_32_16_1(logEtot,20972/*0.64 Q15*/),7)); + move32(); + } + + tmp = L_sub(*lp_speech,377487360l/*45.0 Q23*/); + + if ( LT_32(*lp_noise,tmp)) + { + *lp_noise = tmp; + move32(); + } + + *flag_noisy_speech = 0; + move16(); + if ( LT_32(L_sub(*lp_speech,*lp_noise),234881024l/*28.0 Q23*/)) + { + *flag_noisy_speech = 1; + move16(); + } + + + return; +} + + +void +generate_comfort_noise_dec (Word32 **bufferReal, /* o : matrix to real part of input bands */ + Word32 **bufferImag, /* o : matrix to imaginary part of input bands */ + Word16 *bufferScale, /* o : pointer to scalefactor for real and imaginary part of input bands */ + Decoder_State_fx *stdec, + Word16 *Q_new, + Word16 gen_exc + ) +{ + Word16 i, j, s, sc, sn, cnt; + Word16 startBand2; + Word16 stopFFTbin2; + Word16 scaleCLDFB; + Word16 preemph_fac; + Word32 sqrtNoiseLevel; + Word16 randGaussExp; + Word16 fftBufferExp; + Word16 cngNoiseLevelExp; + Word16 *seed; + Word16 *timeDomainOutput; + Word32 *ptr_r, *ptr_i; + Word32 *cngNoiseLevel; + Word32 *ptr_level; + Word32 *fftBuffer; + Word16 old_syn_pe_tmp[16]; + Word16 tcx_transition = 0; + HANDLE_FD_CNG_DEC std = stdec->hFdCngDec_fx; + HANDLE_FD_CNG_COM st = std->hFdCngCom; + + + + /* Warning fix */ + s = 0; + + /* pointer initialization */ + + cngNoiseLevel = st->cngNoiseLevel; + cngNoiseLevelExp = st->cngNoiseLevelExp; + ptr_level = cngNoiseLevel; + seed = &(st->seed); + fftBuffer = st->fftBuffer; + timeDomainOutput = st->timeDomainBuffer; + + /* scaleCLDFB: CLDFBinvScalingFactor_EXP + 1 */ + scaleCLDFB = mult(st->invScalingFactor,CLDFB_SCALING); + + /* + Generate Gaussian random noise in real and imaginary parts of the FFT bins + Amplitudes are adjusted to the estimated noise level cngNoiseLevel in each bin + scaling Gaussian random noise: format Q3.29 + */ + sn = 0; + move16(); + IF ( s_and(cngNoiseLevelExp,1) != 0 ) + { + sn = add(sn,1); + cngNoiseLevelExp = add(cngNoiseLevelExp,sn); + move16(); + } + + randGaussExp = CNG_RAND_GAUSS_SHIFT; + move16(); + cnt = sub(st->stopFFTbin, st->startBand); + IF ( st->startBand == 0 ) + { + /* DC component in FFT */ + s = 0; + move16(); + sqrtNoiseLevel = Sqrt32(L_shr(*ptr_level,sn), &s); + + fftBuffer[0] = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),s); + move32(); + + /* Nyquist frequency is discarded */ + fftBuffer[1] = L_deposit_l(0); + + ptr_level = ptr_level + 1; + ptr_r = fftBuffer + 2; + cnt = sub(cnt, 1); + } + ELSE + { + startBand2 = shl(st->startBand,1); + set32_fx(fftBuffer, 0, startBand2); + ptr_r = fftBuffer + startBand2; + } + + sn = add(sn,1); + ptr_i = ptr_r + 1; + FOR (i=0; i < cnt; i++) + { + s = 0; + move16(); + sqrtNoiseLevel = Sqrt32(L_shr(*ptr_level,sn), &s); + + /* Real part in FFT bins */ + *ptr_r = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),s); + move32(); + + /* Imaginary part in FFT bins */ + *ptr_i = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),s); + move32(); + + ptr_r = ptr_r + 2; + ptr_i = ptr_i + 2; + ptr_level = ptr_level + 1; + } + + /* Remaining FFT bins are set to zero */ + stopFFTbin2 = shl(st->stopFFTbin,1); + set32_fx(fftBuffer+stopFFTbin2, 0, sub(st->fftlen,stopFFTbin2)); + + fftBufferExp = add(shr(cngNoiseLevelExp,1),randGaussExp); + + /* If previous frame is active, reset the overlap-add buffer */ + IF ( st->frame_type_previous == ACTIVE_FRAME ) + { + set16_fx(st->olapBufferSynth, 0, st->fftlen); + test(); + test(); + if ( ( stdec->last_core_bfi > ACELP_CORE && stdec->codec_mode == MODE2 ) || stdec->codec_mode == MODE1 ) + { + tcx_transition = 1; + move16(); + } + } + + /* Perform STFT synthesis */ + SynthesisSTFT (fftBuffer, fftBufferExp, timeDomainOutput, st->olapBufferSynth, st->olapWinSyn, + tcx_transition, + st, gen_exc, Q_new); + + { + Word32 Lener, att; + Word16 exp; + /* update CNG excitation energy for LP_CNG */ + + /* calculate the residual signal energy */ + /*enr = dotp( st->exc_cng, st->exc_cng, st->frameSize ) / st->frameSize;*/ + Lener = Dot_productSq16HQ(1,st->exc_cng,stdec->L_frame_fx,&exp); + exp = add(sub(shl(sub(15,*Q_new),1),8),exp); /*8 = log2(256)*/ + + /* convert log2 of residual signal energy */ + /*(float)log10( enr + 0.1f ) / (float)log10( 2.0f );*/ + Lener = BASOP_Util_Log2(Lener); + Lener = L_add(Lener,L_shl(L_deposit_l(exp),WORD32_BITS-1-LD_DATA_SCALE)); /*Q25*/ + if(stdec->L_frame_fx == L_FRAME16k) + { + Lener = L_sub(Lener, 10802114l/*0.3219280949f Q25*/); /*log2(320) = 8.3219280949f*/ + } + /* decrease the energy in case of WB input */ + IF( NE_16(stdec->bwidth_fx, NB)) + { + IF( EQ_16(stdec->bwidth_fx,WB)) + { + IF( stdec->CNG_mode_fx >= 0 ) + { + /* Bitrate adapted attenuation */ + att = L_shl(L_deposit_l(ENR_ATT_fx[stdec->CNG_mode_fx]),17); + } + ELSE + { + /* Use least attenuation for higher bitrates */ + att = L_shl(L_deposit_l(ENR_ATT_fx[4]),17); + } + } + ELSE + { + att = 384<<17; + move16();/*1.5 Q8<<17=Q25*/ + } + Lener = L_sub(Lener, att ); + } + /*stdec->lp_ener = 0.8f * stcod->lp_ener + 0.2f * pow( 2.0f, enr );*/ + Lener = BASOP_util_Pow2(Lener, 6, &exp); + Lener = Mult_32_16(Lener, 6554/*0.2f Q15*/); + exp = sub(25,exp); + Lener = L_shr(Lener, exp); /*Q6*/ + stdec->lp_ener_fx = L_add(Mult_32_16(stdec->lp_ener_fx, 26214/*0.8f Q15*/), Lener); /*Q6*/ + } + + /* + Generate Gaussian random noise in real and imaginary parts of the CLDFB bands + Amplitudes are adjusted to the estimated noise level cngNoiseLevel in each band + */ + test(); + IF ( bufferReal!=NULL && (LT_16(st->numCoreBands,st->regularStopBand))) + { + + sn = sub(sn,1); + sc = add(shr(add(cngNoiseLevelExp,CLDFBinvScalingFactor_EXP+1-1),1),randGaussExp); + move16(); + assert( ((cngNoiseLevelExp+CLDFBinvScalingFactor_EXP+1-1)&1) == 0); + + FOR (j=st->numCoreBands; jregularStopBand; j++) + { + /* scaleCLDFB: CLDFBinvScalingFactor_EXP + 1 */ + s = 0; + move16(); + sqrtNoiseLevel = Sqrt32(L_shr(Mpy_32_16_1(*ptr_level,scaleCLDFB),sn), &s); + + FOR (i=0; inumSlots; i++) + { + /* Real part in CLDFB band */ + bufferReal[i][j] = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),s); + move32(); + /*fprintf(pFile,"%13.10f\n",WORD322FL_SCALE(bufferReal[i][j],sc));*/ + + /* Imaginary part in CLDFB band */ + bufferImag[i][j] = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),s); + move32(); + /*fprintf(pFile,"%13.10f\n",WORD322FL_SCALE(bufferImag[i][j],sc));*/ + } + ptr_level = ptr_level + 1; + } + *bufferScale = sub(sc,15); + move16(); + } + + /* Overlap-add when previous frame is active */ + test(); + IF ( st->frame_type_previous == ACTIVE_FRAME && stdec->codec_mode == MODE2 ) + { + Word32 old_exc_ener, gain, noise32; + Word16 seed_loc, lpcorder, old_syn, tmp, gain16, N, N2, N4, N8; + Word16 old_exc_ener_exp, gain_exp; + Word16 normFacE, normShiftE, normShiftEM1; + Word16 normFacG, normShiftG, normShiftGM1; + Word16 noiseExp, *old_exc, *old_Aq, *old_syn_pe; + Word16 noise[640], normShiftP2; + Word16 Q_exc, Q_syn; + + + assert(st->frameSize <= 640); + + seed_loc = st->seed; + move16(); + N = st->frameSize; + move16(); + N2 = shr(st->frameSize,1); + + IF ( stdec->last_core_bfi > ACELP_CORE ) + { + Word16 left_overlap_mode; + left_overlap_mode = stdec->tcx_cfg.tcx_last_overlap_mode; + move16(); + if (EQ_16(left_overlap_mode, ALDO_WINDOW)) + { + left_overlap_mode = FULL_OVERLAP; + move16(); + } + + tcx_windowing_synthesis_current_frame( timeDomainOutput, + stdec->tcx_cfg.tcx_mdct_window, /*Keep sine windows for limiting Time modulation*/ + stdec->tcx_cfg.tcx_mdct_window_half, + stdec->tcx_cfg.tcx_mdct_window_minimum, + stdec->tcx_cfg.tcx_mdct_window_length, + stdec->tcx_cfg.tcx_mdct_window_half_length, + stdec->tcx_cfg.tcx_mdct_window_min_length, + 0, + left_overlap_mode, + NULL, + NULL, + NULL, + NULL, + NULL, + N/2, + shr(sub(abs_s(stdec->tcx_cfg.tcx_offset), stdec->tcx_cfg.tcx_offset), 1), /* equivalent to: stdec->tcx_cfg.tcx_offset<0?-stdec->tcx_cfg.tcx_offset:0 */ + 1, + 0, + 0 + ); + + IF (stdec->tcx_cfg.last_aldo != 0) + { + FOR (i=0; iframeSize,NS2SA(stdec->sr_core, N_ZERO_MDCT_NS)); i++) + { + timeDomainOutput[i] = add(timeDomainOutput[i], shr_r(stdec->old_out_LB_fx[i+NS2SA(stdec->sr_core, N_ZERO_MDCT_NS)],stdec->Q_old_wtda_LB)); + } + } + ELSE + { + tcx_windowing_synthesis_past_frame( stdec->syn_Overl, + stdec->tcx_cfg.tcx_mdct_window, + stdec->tcx_cfg.tcx_mdct_window_half, + stdec->tcx_cfg.tcx_mdct_window_minimum, + stdec->tcx_cfg.tcx_mdct_window_length, + stdec->tcx_cfg.tcx_mdct_window_half_length, + stdec->tcx_cfg.tcx_mdct_window_min_length, + stdec->tcx_cfg.tcx_last_overlap_mode + ); + + FOR (i=0; itcx_cfg.tcx_mdct_window_length; i++) + { + timeDomainOutput[i] += shl(stdec->syn_Overl[i],TCX_IMDCT_HEADROOM); + } + } + } + ELSE + { + + /* + - the scaling of the LPCs (e.g. old_Aq) is always Q12 (encoder or decoder) + + - the scaling of the deemphasized signals (e.g. old_syn) is always Q0 (encoder or decoder) + + - the scaling of the excitation signals in the encoder (e.g. old_exc) is Q_new + - the scaling of the preemphasized signals in the encoder (e.g. old_syn_pe) is Q_new-1 + + - the scaling of the excitation signals in the decoder (e.g. old_exc) is Q_exc (or stdec->Q_exc) + - the scaling of the preemphasized signals in the decoder (e.g. old_syn_pe) is Q_syn (or stdec->Q_syn) + */ + + lpcorder = M; + move16(); + old_Aq = stdec->old_Aq_12_8_fx; + old_exc = stdec->old_exc_fx+sub(L_EXC_MEM_DEC,N2); + old_syn_pe = stdec->mem_syn2_fx; + old_syn = stdec->syn[lpcorder]; + move16(); + preemph_fac = stdec->preemph_fac; + move16(); + Q_exc = stdec->Q_exc; + move16(); + Q_syn = stdec->Q_syn; + move16(); + + /* shift to be in the range of values supported by getNormReciprocalWord16() */ + N8 = shr(N2, CNG_NORM_RECIPROCAL_RANGE_SHIFT); + + assert( N2 == (N8<olapWinSyn[i].v.re); + timeDomainOutput[i] = add(timeDomainOutput[i],tmp); + move16(); + tmp = mult(noise[i+N4],st->olapWinSyn[N4-1-i].v.im); + timeDomainOutput[i+N4] = add(timeDomainOutput[i+N4],tmp); + move16(); + } + } + } + +} + + +void +generate_comfort_noise_dec_hf (Word32 **bufferReal, /* o : matrix to real part of input bands */ + Word32 **bufferImag, /* o : matrix to imaginary part of input bands */ + Word16 *bufferScale, /* o : pointer to scalefactor for real and imaginary part of input bands */ + Decoder_State_fx *stdec + ) +{ + Word16 i, j, s, sc, sn; + Word16 scaleCLDFB; + Word32 sqrtNoiseLevel; + Word16 randGaussExp; + Word16 cngNoiseLevelExp; + Word16 *seed; + Word32 *cngNoiseLevel; + Word32 *ptr_level; + HANDLE_FD_CNG_COM st = stdec->hFdCngDec_fx->hFdCngCom; + + cngNoiseLevel = st->cngNoiseLevel+st->stopFFTbin-st->startBand; + cngNoiseLevelExp = st->cngNoiseLevelExp; + ptr_level = cngNoiseLevel; + seed = &(st->seed); + + /* scaleCLDFB: CLDFBinvScalingFactor_EXP + 1 */ + scaleCLDFB = mult(st->invScalingFactor,CLDFB_SCALING); + + sn = 0; + move16(); + IF ( s_and(cngNoiseLevelExp,1) != 0 ) + { + sn = add(sn,1); + cngNoiseLevelExp = add(cngNoiseLevelExp,sn); + move16(); + } + + randGaussExp = CNG_RAND_GAUSS_SHIFT; + move16(); + + IF ( LT_16(st->numCoreBands,st->regularStopBand)) + { + + sc = add(shr(add(cngNoiseLevelExp,CLDFBinvScalingFactor_EXP+1-1),1),randGaussExp); + move16(); + assert( ((cngNoiseLevelExp+CLDFBinvScalingFactor_EXP+1-1)&1) == 0); + + FOR (j=st->numCoreBands; jregularStopBand; j++) + { + /* scaleCLDFB: CLDFBinvScalingFactor_EXP + 1 */ + s = 0; + move16(); + sqrtNoiseLevel = Sqrt32(L_shr(Mpy_32_16_1(*ptr_level,scaleCLDFB),sn), &s); + + FOR (i=0; inumSlots; i++) + { + /* Real part in CLDFB band */ + bufferReal[i][j] = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),s); + move32(); + /*fprintf(pFile,"%13.10f\n",WORD322FL_SCALE(bufferReal[i][j],sc));*/ + + /* Imaginary part in CLDFB band */ + bufferImag[i][j] = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),s); + move32(); + /*fprintf(pFile,"%13.10f\n",WORD322FL_SCALE(bufferImag[i][j],sc));*/ + } + ptr_level = ptr_level + 1; + } + *bufferScale = sub(sc,15); + move16(); + } +} + + +/* + generate_masking_noise + + Parameters: + + timeDomainBuffer i/o : pointer to time domain output buffer 15Q0 + st i/o : pointer to FD_CNG_COM structure + bitrate i : bitrate + + Function: + Generate additional comfort noise (kind of noise filling) + + Returns: none + + void +*/ +void generate_masking_noise (Word16 *timeDomainBuffer, /* i/o : pointer to time domain output buffer 15Q0 */ + Word16 Q, + HANDLE_FD_CNG_COM st /* i/o : pointer to FD_CNG_COM structure */ + ,Word16 length + ,Word16 core + ) +{ + Word16 i, s, s1, s2, sq, cnt, startBand2, stopFFTbin2; + Word16 scaleExp,fftBufferExp,cngNoiseLevelExp; + Word16 scale, scaleTableSize; + Word16 maskingNoise[L_FRAME16k]; + Word32 sqrtNoiseLevel; + Word32 *cngNoiseLevel; + Word32 *fftBuffer; + Word16 *seed; + + + + /* pointer initializations */ + cngNoiseLevel = st->cngNoiseLevel; + fftBuffer = st->fftBuffer; + seed = &(st->seed); + + /* Compute additional CN level */ + cngNoiseLevelExp = st->cngNoiseLevelExp; + move16(); + + IF(core!=AMR_WB_CORE) + { + scaleTableSize = 18; + move16(); + assert( scaleTableSize == (sizeof (scaleTable_cn_only) / sizeof (scaleTable_cn_only[0])) ); + + scale = -1; + move16(); + FOR (i=0; i < scaleTableSize; i++) + { + test(); + test(); + IF ( ( EQ_16(st->CngBandwidth,scaleTable_cn_only[i].bwmode)) + && (GE_32(st->CngBitrate,scaleTable_cn_only[i].bitrateFrom) ) + && ( LT_32(st->CngBitrate,scaleTable_cn_only[i].bitrateTo) )) + + { + scale = scaleTable_cn_only[i].scale; + move16(); + BREAK; + } + } + assert(scale >= 0); + } + ELSE + { + scaleTableSize = 3; + move16(); + assert( scaleTableSize == (sizeof (scaleTable_cn_only_amrwbio) / sizeof (scaleTable_cn_only_amrwbio[0])) ); + + scale = 0; + move16(); + FOR (i=0; i < scaleTableSize; i++) + { + IF ( GE_32(st->CngBitrate,scaleTable_cn_only_amrwbio[i][0])) + { + scale = scaleTable_cn_only_amrwbio[i][1]; + move16(); + BREAK; + } + } + } + + /* Exclude clean speech */ + + s1 = norm_s(scale); + s2 = norm_s(st->likelihood_noisy_speech); + + /* scaleTable_cn_only[i].scale is scaled by 1 bit */ + scaleExp = sub(1,add(s1,s2)); + scale = mult_r(shl(scale,s1),shl(st->likelihood_noisy_speech,s2)); + + { + /* add exponent of scale and cngNoiseLevel */ + fftBufferExp = add(scaleExp,cngNoiseLevelExp); + + /* even scalefactor needed for sqrt calculation */ + s = s_and(fftBufferExp,1); + fftBufferExp = add(fftBufferExp,s); + + /* sqrt calculation => shift exponent */ + fftBufferExp = shr(fftBufferExp,1); + + /* consider scaling of random noise */ + fftBufferExp = add(fftBufferExp,CNG_RAND_GAUSS_SHIFT); + + cnt = sub(st->stopFFTbin,st->startBand); + /* + Generate Gaussian random noise in real and imaginary parts of the FFT bins + Amplitudes are adjusted to the estimated noise level cngNoiseLevel in each bin + */ + IF ( st->startBand == 0 ) + { + /* random noise is scaled by CNG_RAND_GAUSS_SHIFT bits */ + + /* DC component in FFT */ + + /* -s => consider scalefactor adaptation for sqrt calculation */ + sq = sub(0,s); + sqrtNoiseLevel = Sqrt32(Mpy_32_16_1(*cngNoiseLevel,scale),&sq); + st->fftBuffer[0] = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),sq); + move32(); + st->fftBuffer[1] = 0; + move32(); + + fftBuffer = st->fftBuffer + 2; + cngNoiseLevel++; + + cnt = sub(cnt,1); + } + ELSE + { + startBand2 = shl(st->startBand,1); + set32_fx(st->fftBuffer,0,startBand2); + fftBuffer = st->fftBuffer + startBand2; + } + + FOR (i=0; i weighting with 0.5, -s => consider scalefactor adaptation for sqrt calculation */ + sq = sub(-1,s); + sqrtNoiseLevel = Sqrt32(Mpy_32_16_1(*cngNoiseLevel,scale),&sq); + + /* real part in FFT bins */ + + /* random noise is scaled by CNG_RAND_GAUSS_SHIFT bits */ + *fftBuffer = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),sq); + move32(); + fftBuffer++; + + /* imaginary part in FFT bins */ + + /* random noise is scaled by CNG_RAND_GAUSS_SHIFT bits */ + *fftBuffer = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),sq); + move32(); + fftBuffer++; + + cngNoiseLevel++; + } + + /* remaining FFT bins are set to zero */ + stopFFTbin2 = shl(st->stopFFTbin,1); + set32_fx(st->fftBuffer+stopFFTbin2, 0, sub(st->fftlen,stopFFTbin2)); + + + /* perform STFT synthesis */ + assert(st->olapBufferSynth2 != NULL); + SynthesisSTFT(st->fftBuffer, fftBufferExp, maskingNoise, st->olapBufferSynth2, st->olapWinSyn, + 0, + st, 0, NULL); + + + /* add some comfort noise on top of decoded signal */ + IF ( st->frameSize > length ) + { + FOR (i=0; iframeSize; i++) + { + timeDomainBuffer[i] = add(timeDomainBuffer[i],shr_r(maskingNoise[i],-Q)); + move16(); + } + } + } + +} + +/*------------------------------------------------------------------- + * generate_masking_noise_update_seed() + * + * Update seed for scenarios where generate_masking_noise() is + * not called based on signal statistics + *-------------------------------------------------------------------*/ + +void generate_masking_noise_update_seed ( + HANDLE_FD_CNG_COM st /* i/o : pointer to FD_CNG_COM structure */ +) +{ + Word16 *seed; + Word16 cnt, i; + + /* pointer initializations */ + seed = &(st->seed); + + cnt = sub(st->stopFFTbin, st->startBand); + + IF ( st->startBand == 0 ) + { + rand_gauss(seed); + cnt = sub(cnt,1); + } + + FOR (i=0; icngNoiseLevel; + seed = &(st->seed); + + /* Compute additional CN level */ + cngNoiseLevelExp = st->cngNoiseLevelExp; + move16(); + + /* Compute additional CN level */ + scaleTableSize = 18; + move16(); + assert( scaleTableSize == (sizeof (scaleTable_cn_only) / sizeof (scaleTable_cn_only[0])) ); + + scale = -1; + move16(); + FOR (i=0; i < scaleTableSize; i++) + { + test(); + test(); + IF ( ( EQ_16(st->CngBandwidth,scaleTable_cn_only[i].bwmode)) + && ( GE_32(st->CngBitrate,scaleTable_cn_only[i].bitrateFrom) ) + && ( LT_32(st->CngBitrate,scaleTable_cn_only[i].bitrateTo) ) + ) + { + scale = scaleTable_cn_only[i].scale; + move16(); + BREAK; + } + } + assert(scale >= 0); + + /* Exclude clean speech */ + s1 = norm_s(scale); + s2 = norm_s(st->likelihood_noisy_speech); + + /* scaleTable_cn_only[i].scale is scaled by 1 bit */ + scaleExp = sub(1,add(s1,s2)); + scale = mult_r(shl(scale,s1),shl(st->likelihood_noisy_speech,s2)); + + /* add exponent of scale and cngNoiseLevel */ + maskingNoiseExp = add(scaleExp,cngNoiseLevelExp); + + /* even scalefactor needed for sqrt calculation */ + s = s_and(maskingNoiseExp,1); + maskingNoiseExp = add(maskingNoiseExp,s); + + /* sqrt calculation => shift exponent */ + maskingNoiseExp = shr(maskingNoiseExp,1); + + /* consider scaling of random noise */ + maskingNoiseExp = add(maskingNoiseExp,CNG_RAND_GAUSS_SHIFT); + + cnt = sub(st->stopFFTbin,st->startBand); + + /* + Generate Gaussian random noise in real and imaginary parts of the FFT bins + Amplitudes are adjusted to the estimated noise level cngNoiseLevel in each bin + */ + IF ( st->startBand == 0 ) + { + /* random noise is scaled by CNG_RAND_GAUSS_SHIFT bits */ + + /* DC component in FFT */ + + /* -1 => weighting with 0.5, -s => consider scalefactor adaptation for sqrt calculation */ + sq = sub(-1,s); + sqrtNoiseLevel = Sqrt32(Mpy_32_16_1(*cngNoiseLevel,scale),&sq); + maskingNoise[0] = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),sq); + move32(); + + pMaskingNoise = &maskingNoise[1]; + cngNoiseLevel++; + + cnt = sub(cnt,1); + } + ELSE + { + set32_fx(maskingNoise,0,st->startBand); + pMaskingNoise = maskingNoise + st->startBand; + } + + FOR (i=0; i weighting with 0.5, -s => consider scalefactor adaptation for sqrt calculation */ + sq = sub(-1,s); + sqrtNoiseLevel = Sqrt32(Mpy_32_16_1(*cngNoiseLevel,scale),&sq); + + /* real part in FFT bins */ + + /* random noise is scaled by CNG_RAND_GAUSS_SHIFT bits */ + *pMaskingNoise = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),sq); + move32(); + pMaskingNoise++; + + cngNoiseLevel++; + } + + /* re-normalization of energy level + 16 * 0.79056941504 = sqrt(NORM_MDCT_FACTOR) + */ + assert( NORM_MDCT_FACTOR == 160 ); + + /* do weighting with factor 0.79056941504 later */ + maskingNoiseExp = add(maskingNoiseExp,4); + + s = s_max(*mdctBuffer_e,maskingNoiseExp); + s1 = sub(s,*mdctBuffer_e); + s2 = sub(s,maskingNoiseExp); + + /* avoid rescaling of mdct samples if no comfort noise is added */ + IF ( scale != 0 ) + { + /* Add some comfort noise on top of decoded signal */ + IF ( s1 == 0 ) + { + FOR (i=0; i < st->stopFFTbin; i++) + { + /* If shifting negative noise values the lowest result is -1 but never 0. + Shift positive noise values to avoid unwanted amplification of these small values later */ + noise = L_shr(Mpy_32_16_1(L_abs(maskingNoise[i]),25905/*0.79056941504 Q15*/),s2); + + if ( maskingNoise[i] < 0 ) + { + noise = L_negate(noise); + } + + mdctBuffer[i] = L_add(mdctBuffer[i], noise); + move32(); + } + } + ELSE + { + FOR (i=0; i < st->stopFFTbin; i++) + { + mdctBuffer[i] = L_add(L_shr(mdctBuffer[i],s1), + Mpy_32_16_1(maskingNoise[i],25905/*0.79056941504 Q15*/)); + move32(); + } + FOR (i=st->stopFFTbin; i < L_frame; i++) + { + mdctBuffer[i] = L_shr(mdctBuffer[i],s1); + move32(); + } + *mdctBuffer_e = s; + move16(); + } + } + +} diff --git a/lib_dec/gain_dec_fx.c b/lib_dec/gain_dec_fx.c new file mode 100644 index 0000000..d679d9d --- /dev/null +++ b/lib_dec/gain_dec_fx.c @@ -0,0 +1,1238 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + + +/*===========================================================================*/ +/* FUNCTION : Es_pred_dec_fx() */ +/*---------------------------------------------------------------------------*/ +/* PURPOSE : Decoding of scaled predicted innovation energy to be */ +/* used in all subframes */ +/*---------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) coder_type : coder type */ +/* _ (Word32) core_brate : core bitrate */ +/* _ (Word16*) Es_pred_qua_nb_fx : Gain quantization - quantization table */ +/* for scaled innovation energy prediciton Q8*/ +/*---------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) Es_pred : predicited scaled innovation energy Q8 */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*===========================================================================*/ +void Es_pred_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *Es_pred, /* o : predicited scaled innovation energy Q8*/ + const Word16 coder_type, /* i : coder type */ + const Word32 core_brate /* i : core bitrate */ +) +{ + Word16 enr_idx, nb_bits; + { + nb_bits = Es_pred_bits_tbl[BIT_ALLOC_IDX_fx(core_brate, coder_type, -1, -1)]; + move16(); + enr_idx = (Word16)get_next_indice_fx( st_fx, nb_bits ); + move16(); + } + SWITCH ( nb_bits ) + { + case 5: + *Es_pred = Es_pred_qua_5b_fx[enr_idx]; + move16(); + BREAK; + case 4: + *Es_pred = Es_pred_qua_4b_fx[enr_idx]; + move16(); + BREAK; + default: + *Es_pred = Es_pred_qua_5b_fx[enr_idx]; + move16(); + BREAK; + } +} +/*======================================================================================*/ +/* FUNCTION : void gain_dec_tc_fx () */ +/*--------------------------------------------------------------------------------------*/ +/* PURPOSE : Decoding of pitch and codebook gains and updating long term energies */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word32 core_brate_fx i : core bitrate */ +/* Word16 *code_fx i : algebraic code excitation */ +/* Word16 L_frame_fx i : length of the frame */ +/* Word16 i_subfr_fx i : subframe number */ +/* Word16 tc_subfr_fx i : TC subframe index */ +/* Word16 Es_pred_fx i : predicted scaled innov. energy Q8 */ +/*--------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* Word16 *gain_pit_fx o : pitch gain Q14 */ +/* Word32 *gain_code_fx o : Quantized codeebook gain Q16 */ +/* Word16 *gain_inov_fx o : unscaled innovation gain Q12 */ +/* Word32 *norm_gain_code_fx o : norm. gain of the codebook excit. Q16 */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*======================================================================================*/ + +void gain_dec_tc_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate_fx, /* i : core bitrate */ + const Word16 *code_fx, /* i : algebraic code excitation */ + const Word16 L_frame_fx, /* i : length of the frame */ + const Word16 i_subfr_fx, /* i : subframe number */ + const Word16 tc_subfr_fx, /* i : TC subframe index */ + const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */ + Word16 *gain_pit_fx, /* o : pitch gain */ + Word32 *gain_code_fx, /* o : Quantized codeebook gain */ + Word16 *gain_inov_fx, /* o : unscaled innovation gain */ + Word32 *norm_gain_code_fx /* o : norm. gain of the codebook excit. */ +) +{ + Word16 index, nBits; + Word16 gcode0_fx; + Word16 Ei_fx; + Word16 expg, expg2, e_tmp, f_tmp, exp_gcode0, tmp_fx, frac; + Word32 L_tmp, L_tmp1; + Word16 wgain_code=0; + move16(); + *gain_pit_fx = 0; + move16(); + + /*----------------------------------------------------------------* + * find number of bits for gain dequantization + *----------------------------------------------------------------*/ + IF( EQ_16(L_frame_fx,L_FRAME)) + { + nBits = gain_bits_tbl[BIT_ALLOC_IDX_fx(core_brate_fx, TRANSITION, i_subfr_fx, TC_SUBFR2IDX_fx(tc_subfr_fx))]; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + nBits = gain_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(core_brate_fx, TRANSITION, i_subfr_fx, TC_SUBFR2IDX_16KHZ_fx(tc_subfr_fx))]; + move16(); + } + + /*-----------------------------------------------------------------* + * calculate the predicted gain code + *-----------------------------------------------------------------*/ + + /*Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR; + *gain_inov = 1.0f / (float)sqrt( Ecode );*/ + L_tmp = Dot_product12(code_fx, code_fx, L_SUBFR, &expg); + expg = sub(expg, 18 + 6); /* exp: -18 (code in Q9), -6 (/L_SUBFR) */ + expg2 = expg; + move16(); + L_tmp1 = L_tmp; /* sets to 'L_tmp' in 1 clock */ + move32(); + L_tmp = Isqrt_lc(L_tmp, &expg); + + *gain_inov_fx = extract_h(L_shl(L_tmp, sub(expg, 3))); + move16(); /* gain_inov in Q12 */ + + + /* Ei = 10 * (float)log10( Ecode );*/ + e_tmp = norm_l(L_tmp1); + f_tmp = Log2_norm_lc(L_shl(L_tmp1, e_tmp)); + e_tmp = sub(expg2,add(1,e_tmp)); + L_tmp1 = Mpy_32_16(e_tmp, f_tmp, 12330); /* Q13 */ /* 10*log10(2) in Q12*/ + Ei_fx = round_fx(L_shl(L_tmp1, 11)); /* Q8 */ + /* gcode0 = (float) pow(10, 0.05 * (Es_pred - Ei));*/ + gcode0_fx = sub(Es_pred_fx, Ei_fx); /* Q8 */ + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *-----------------------------------------------------------------*/ + L_tmp = L_mult(gcode0_fx, 21771); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */ + gcode0_fx = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + /*------------------------------------------------------------------------------------------* + * Select the gain quantization table and dequantize the gain + *------------------------------------------------------------------------------------------*/ + + /* index = (Word16)get_indice( st_fx,"gain_code", i_subfr_fx, ACELP_CORE);move16();*/ + index = (Word16)get_next_indice_fx( st_fx, nBits ); + move16(); + + + IF( GT_16(nBits,3)) + { + wgain_code = gain_dequant_fx( index, G_CODE_MIN_TC_Q15, G_CODE_MAX_TC_Q0, nBits, &expg ); + wgain_code = shl(wgain_code,add(expg,13)); /* wgain_code in Q13*/ + } + ELSE /* nBits == 3 */ + { + wgain_code = tbl_gain_code_tc_fx[index]; + move16(); + } + + /*-----------------------------------------------------------------* + * decode normalized codebook gain + *-----------------------------------------------------------------*/ + + /* *gain_code *= gcode0;*/ + L_tmp = L_mult(wgain_code, gcode0_fx); /* Q13*Q0 -> Q14 */ + *gain_code_fx= L_shl(L_tmp, add(exp_gcode0, 2)); + move32(); /* Q14 -> Q16 */ + + /**norm_gain_code = *gain_code / *gain_inov;*/ + expg = sub(norm_s(*gain_inov_fx),1); + expg = s_max(expg, 0); + + tmp_fx = div_s(shr(8192,expg),*gain_inov_fx); + *norm_gain_code_fx = L_shr(Mult_32_16(*gain_code_fx, tmp_fx),sub(1,expg)); + move32(); + + return; +} +/*======================================================================================*/ +/* FUNCTION : gain_dec_mless_fx() */ +/*--------------------------------------------------------------------------------------*/ +/* PURPOSE : Decoding of pitch and codebook gains without updating long term energies */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word32) core_brate_fx : core bitrate */ +/* _ (Word16) L_frame_fx : length of the frame */ +/* _ (Word16) coder_type_fx : coding type */ +/* _ (Word16) i_subfr_fx : subframe index */ +/* _ (Word16) tc_subfr_fx : TC subframe index */ +/* _ (Word16*[]) code_fx : algebraic code excitation (Q12) */ +/* _ (Word16) Es_pred_fx : predicted scaled innov. energy (Q8) */ +/*--------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) gain_pit_fx : quantized pitch gain (Q14) */ +/* _ (Word32*) gain_code_fx : quantized codebook gain (Q16) */ +/* _ (Word16*) gain_inov_fx : gain of the innovation (used for normalization) (Q12) */ +/* _ (Word32*) norm_gain_code_fx : norm. gain of the codebook excitation (Q16) */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------------------*/ + +/* _ None */ +/*--------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*======================================================================================*/ +void gain_dec_mless_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate_fx, /* i : core bitrate */ + const Word16 L_frame_fx, /* i : length of the frame */ + const Word16 coder_type_fx, /* i : coding type */ + const Word16 i_subfr_fx, /* i : subframe number */ + const Word16 tc_subfr_fx, /* i : TC subframe index */ + const Word16 *code_fx, /* i : algebraic code excitation */ + const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */ + Word16 *gain_pit_fx, /* o : Quantized pitch gain Q14*/ + Word32 *gain_code_fx, /* o : Quantized codeebook gain Q16*/ + Word16 *gain_inov_fx, /* o : unscaled innovation gain Q12*/ + Word32 *norm_gain_code_fx /* o : norm. gain of the codebook excitation Q16*/ +) +{ + Word16 index, nBits; + Word16 gcode0_fx, Ei_fx, gain_code16; + const Word16 *qua_table_fx; + Word16 expg, expg2, e_tmp, f_tmp, exp_gcode0, tmp_fx, frac; + Word32 L_tmp, L_tmp1; + + /*-----------------------------------------------------------------* + * decode pitch gain + *-----------------------------------------------------------------*/ + IF( EQ_16(L_frame_fx,L_FRAME)) + { + nBits = gain_bits_tbl[BIT_ALLOC_IDX_fx(core_brate_fx, coder_type_fx, i_subfr_fx, TC_SUBFR2IDX_fx(tc_subfr_fx))]; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + nBits = gain_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(core_brate_fx, coder_type_fx, i_subfr_fx, TC_SUBFR2IDX_16KHZ_fx(tc_subfr_fx))]; + move16(); + } + test(); + test(); + test(); + test(); + test(); + IF( (EQ_16(tc_subfr_fx,3*L_SUBFR )&&EQ_16(i_subfr_fx,3*L_SUBFR)&&EQ_16(L_frame_fx,L_FRAME))|| + (EQ_16(tc_subfr_fx,4*L_SUBFR ) && EQ_16(i_subfr_fx,4*L_SUBFR) && EQ_16(L_frame_fx,L_FRAME16k)) ) + { + /* decode pitch gain */ + index = (Word16)get_next_indice_fx( st_fx, shr(nBits,1) ); + move16(); + + /*Ei = (G_PITCH_MAX_TC192 - G_PITCH_MIN_TC192) / ((1 << (nBits>>1)) - 1);*/ /* set quantization step */ + tmp_fx = div_s(1,sub(shl(1,shr(nBits,1)),1)); /*Q15*/ + Ei_fx = mult_r(G_PITCH_MAX_MINUS_MIN_TC192_Q13,tmp_fx); /*Q13*/ + + /**gain_pit = usdequant( index, G_PITCH_MIN_TC192, Ei );*/ + *gain_pit_fx = usdequant_fx( index, G_PITCH_MIN_TC192_Q14, Ei_fx ); + move16(); /*Q14*/ + + /* calculate the predicted gain code */ + /*Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR; + *gain_inov = 1.0f / (float)sqrt( Ecode );*/ + L_tmp = Dot_product12(code_fx, code_fx, L_SUBFR, &expg); + expg = sub(expg, 18 + 6); /* exp: -18 (code in Q12), -6 (/L_SUBFR) */ + expg2 = expg; + move16(); + L_tmp1 = L_tmp; /* sets to 'L_tmp' in 1 clock */ + move32(); + L_tmp = Isqrt_lc(L_tmp, &expg); + + *gain_inov_fx = extract_h(L_shl(L_tmp, sub(expg, 3))); /* gain_inov in Q12 */ + + /*Ei = 10 * (float)log10( Ecode );*/ + e_tmp = norm_l(L_tmp1); + f_tmp = Log2_norm_lc(L_shl(L_tmp1, e_tmp)); + e_tmp = sub(expg2,add(1,e_tmp)); + L_tmp1 = Mpy_32_16(e_tmp, f_tmp, 12330); /* Q13 */ /* 10*log10(2) in Q12*/ + Ei_fx = round_fx(L_shl(L_tmp1, 11)); /* Q8 */ + + /*-----------------------------------------------------------------* + * calculate the predicted gain code + *-----------------------------------------------------------------*/ + + /*gcode0 = (float) pow(10, 0.05 * (Es_pred - Ei));*/ + gcode0_fx = sub(Es_pred_fx, Ei_fx); /* Q8 */ + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *-----------------------------------------------------------------*/ + L_tmp = L_mult(gcode0_fx, 21771); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */ + + gcode0_fx = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + + /* decode normalized codebook gain */ + /*index = (short)get_indice( st_fx, "gain_code", i_subfr_fx, ACELP_CORE );move16();*/ + index = (Word16)get_next_indice_fx( st_fx, shr(add(nBits,1),1) ); + move16(); + + /**gain_code = gain_dequant( index, G_CODE_MIN_TC192, G_CODE_MAX_TC192, (nBits+1)>>1 );*/ + gain_code16 = gain_dequant_fx( index, G_CODE_MIN_TC192_Q15, G_CODE_MAX_TC192_Q0, shr(add(nBits,1),1), &expg ); + move16(); + + /**gain_code *= gcode0;*/ + L_tmp = L_mult(gain_code16,gcode0_fx); /*Q0*Q0 -> Q1*/ + *gain_code_fx = L_shl(L_tmp,add(add(expg,exp_gcode0),15)); + move32(); /*Q16*/ + } + ELSE + { + SWITCH ( nBits ) + { + case 7: + { + qua_table_fx = gain_qua_mless_7b_fx; + move16(); + BREAK; + } + case 6: + { + qua_table_fx = gain_qua_mless_6b_fx; + move16(); + BREAK; + } + case 5: + { + qua_table_fx = gain_qua_mless_5b_fx; + move16(); + BREAK; + } + default: + { + qua_table_fx = gain_qua_mless_6b_fx; + move16(); + BREAK; + } + } + + test(); + if( EQ_16(coder_type_fx,INACTIVE)&&EQ_16(nBits,6)) + { + nBits = sub(nBits, 1); + } + + index = (Word16)get_next_indice_fx( st_fx, nBits ); + move16(); + + *gain_pit_fx = qua_table_fx[index * 2]; + move16(); + + /*Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR; + *gain_inov = 1.0f / (float)sqrt( Ecode );*/ + + L_tmp = Dot_product12(code_fx, code_fx, L_SUBFR, &expg); + expg = sub(expg, 18 + 6); /* exp: -18 (code in Q9), -6 (/L_SUBFR) */ + expg2 = expg; + move16(); + L_tmp1 = L_tmp; /* sets to 'L_tmp' in 1 clock */ + move32(); + L_tmp = Isqrt_lc(L_tmp, &expg); + + *gain_inov_fx = extract_h(L_shl(L_tmp, sub(expg, 3))); /* gain_inov in Q12 */ + + /*Ei = 10 * (float)log10( Ecode );*/ + e_tmp = norm_l(L_tmp1); + f_tmp = Log2_norm_lc(L_shl(L_tmp1, e_tmp)); + e_tmp = sub(expg2,add(1,e_tmp)); + L_tmp1 = Mpy_32_16(e_tmp, f_tmp, 12330); /* Q13 */ /* 10*log10(2) in Q12*/ + Ei_fx = round_fx(L_shl(L_tmp1, 11)); /* Q8 */ + + /*-----------------------------------------------------------------* + * calculate the predicted gain code + *-----------------------------------------------------------------*/ + + /*gcode0 = (float) pow(10, 0.05 * (Es_pred - Ei));*/ + gcode0_fx = sub(Es_pred_fx, Ei_fx); /* Q8 */ + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *-----------------------------------------------------------------*/ + L_tmp = L_mult(gcode0_fx, 21771); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */ + + gcode0_fx = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + + /*-----------------------------------------------------------------* + * decode normalized codebook gain + *-----------------------------------------------------------------*/ + + /**gain_code = qua_table[index * 2 + 1] * gcode0;*/ + L_tmp = L_mult(qua_table_fx[add(shl(index,1),1)] , gcode0_fx); /* Q9*Q0 -> Q10 */ + *gain_code_fx = L_shl(L_tmp, add(exp_gcode0, 6)); + move32(); /* Q10 -> Q16*/ + } + + /**norm_gain_code = *gain_code / *gain_inov;*/ + expg = sub(norm_s(*gain_inov_fx),1); + expg = s_max(expg, 0); + + tmp_fx = div_s(shr(8192,expg),*gain_inov_fx); + *norm_gain_code_fx = L_shr(Mult_32_16(*gain_code_fx, tmp_fx),sub(1,expg)); + move32(); + + return; +} + +/*==================================================================================*/ +/* FUNCTION : gain_dec_lbr_fx() */ +/*----------------------------------------------------------------------------------*/ +/* PURPOSE : Decoding of pitch and codebook gains in ACELP at 6.6 and 7.5 kbps */ +/*----------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word32) core_brate : core bitrate */ +/* _ (Word16) coder_type : coding type */ +/* _ (Word16) i_subfr : subframe index */ +/* _ (Word16*[]) code_fx : algebraic excitation (Q12) */ +/*----------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) gain_pit_fx : quantized pitch gain (Q14) */ +/* _ (Word32*) gain_code_fx : quantized codebook gain (Q16) */ +/* _ (Word16*) gain_inov_fx : gain of the innovation (used for normalization) (Q12) */ +/* _ (Word32*) norm_gain_code_fx : norm. gain of the codebook excitation (Q12) */ +/*----------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*----------------------------------------------------------------------------------*/ + +/* _ None */ +/*----------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*==================================================================================*/ +void gain_dec_lbr_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 coder_type, /* i : coding type */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 *code_fx, /* i : algebraic excitation Q9 */ + Word16 *gain_pit_fx, /* o : quantized pitch gain Q14*/ + Word32 *gain_code_fx, /* o : quantized codebook gain Q16*/ + Word16 *gain_inov_fx, /* o : gain of the innovation (used for normalization) Q12*/ + Word32 *norm_gain_code_fx, /* o : norm. gain of the codebook excitation Q16*/ + Word32 gc_mem[], /* i/o: gain_code from previous subframes */ + Word16 gp_mem[] /* i/o: gain_pitch from previous subframes */ +) +{ + Word16 index, nBits, n_pred, ctype; + Word16 gcode0_fx, aux_fx[10]; + Word32 L_tmp, L_tmp1, L_tmp2; + Word16 expg, expg2, e_tmp, exp_gcode0, f_tmp, frac, tmp_fx; + const Word16 *b_fx ,*cdbk_fx = 0; + /* Ecode = ( dotp( code, code, L_SUBFR ) + 0.01f ) / L_SUBFR; + *gain_inov = 1.0f / (float)sqrt(Ecode); */ + + L_tmp = Dot_product12(code_fx, code_fx, L_SUBFR, &expg); + expg = sub(expg, 18 + 6); /* exp: -18 (code in Q9), -6 (/L_SUBFR) */ + expg2 = expg; + move16(); + L_tmp2 = L_tmp; /* sets to 'L_tmp' in 1 clock */ + move32(); + L_tmp = Isqrt_lc(L_tmp, &expg); + + *gain_inov_fx = extract_h(L_shl(L_tmp, sub(expg, 3))); /* gain_inov in Q12 */ + + + /*-----------------------------------------------------------------* + * select the codebook, size and number of bits + * set the gains searching range + *-----------------------------------------------------------------*/ + + nBits = gain_bits_tbl[BIT_ALLOC_IDX_fx(core_brate, coder_type, i_subfr, 0)]; + move16(); + + ctype = shl(sub(coder_type, 1),1); + + /*-----------------------------------------------------------------* + * calculate prediction of gcode + * search for the best codeword + *-----------------------------------------------------------------*/ + IF (i_subfr == 0) + { + b_fx = b_1sfr_fx; + move16(); + n_pred = 2; + move16(); + cdbk_fx = gp_gamma_1sfr_6b_fx; + SWITCH ( nBits ) + { + case 8: + { + cdbk_fx = gp_gamma_1sfr_8b_fx; /* Q14/Q9*/ + move16(); + BREAK; + } + case 7: + { + cdbk_fx = gp_gamma_1sfr_7b_fx; /* Q14/Q9*/ + move16(); + BREAK; + } + case 6: + { + cdbk_fx = gp_gamma_1sfr_6b_fx; /* Q14/Q9*/ + move16(); + BREAK; + } + } + + /* calculate predicted gain */ + aux_fx[0] = 4096; + move16(); + aux_fx[1] = shl(ctype,12); + + /* gcode0 = (float)pow(10, dotp(b, aux, n_pred) - 0.5f * (float)log10(Ecode)); + gcode0 = (float)pow(10, dotp(b, aux, n_pred) - 0.05f * 10 * (float)log10(Ecode)); + gcode0 = (float)pow(10, 0.05(20 * dotp(b, aux, n_pred) - 10 * (float)log10(Ecode))); */ + + e_tmp = norm_l(L_tmp2); + f_tmp = Log2_norm_lc(L_shl(L_tmp2, e_tmp)); + e_tmp = sub(expg2,add(1,e_tmp)); + L_tmp1 = Mpy_32_16(e_tmp, f_tmp, 12330); /* Q13 */ /* 10*log10(2) in Q12*/ + + L_tmp = Dot_product(b_fx, aux_fx, n_pred); /*Q25*/ + L_tmp = Mult_32_16(L_tmp,160);/*Q13, 20 in Q3*/ + L_tmp = L_sub(L_tmp,L_tmp1);/*Q13*/ + + gcode0_fx = round_fx(L_shl(L_tmp, 11)); /* Q8 */ + + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *-----------------------------------------------------------------*/ + + L_tmp = L_mult(gcode0_fx, 21771); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */ + + gcode0_fx = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + + /* retrieve the codebook index and calculate both gains */ + /*index = (Word16)get_indice( st_fx,"gain", i_subfr, ACELP_CORE);move16();*/ + index = (Word16)get_next_indice_fx( st_fx, nBits ); + move16(); + + *gain_pit_fx = cdbk_fx[index * 2]; + move16(); + + L_tmp = L_mult(cdbk_fx[add(shl(index,1),1)] , gcode0_fx); /* Q9*Q0 -> Q10 */ + *gain_code_fx = L_shl(L_tmp, add(exp_gcode0, 6)); + move16(); /* Q10 -> Q16*/ + + gc_mem[0] = *gain_code_fx; + move32(); /*Q16*/ + gp_mem[0] = *gain_pit_fx; + move16(); /*Q14*/ + } + ELSE IF (EQ_16(i_subfr,L_SUBFR)) + { + b_fx = b_2sfr_fx; + move16(); + n_pred = 4; + move16(); + + cdbk_fx = gp_gamma_1sfr_6b_fx; + SWITCH ( nBits ) + { + case 7: + { + cdbk_fx = gp_gamma_2sfr_7b_fx; /* Q14/Q9*/ + move16(); + BREAK; + } + case 6: + { + cdbk_fx = gp_gamma_2sfr_6b_fx; /* Q14/Q9*/ + move16(); + BREAK; + } + } + + /* calculate predicted gain */ + aux_fx[0] = 4096; + move16(); + aux_fx[1] = shl(ctype,12); + + /*aux_fx[2] = (float)log10(gc_mem[0]); + = log2(gc_mem[0])*log10(2);*/ + e_tmp = norm_l(gc_mem[0]); + f_tmp = Log2_norm_lc(L_shl(gc_mem[0], e_tmp)); + e_tmp = sub(sub(30,e_tmp),16); /*Q_format(gc_mem[0])=16*/ + L_tmp1 = Mpy_32_16(e_tmp, f_tmp, 9864); /* Q16 */ + aux_fx[2] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + aux_fx[3] = shr(gp_mem[0],2); /*Q12*/ + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, dotp(b, aux, n_pred) + * = pow(2, 3.321928*dotp(b, aux, n_pred) + *-----------------------------------------------------------------*/ + L_tmp = Dot_product(b_fx, aux_fx, n_pred); /*Q25*/ + L_tmp = Mult_32_16(L_tmp, 27213); /* *3.321928 in Q13 -> Q23 */ + L_tmp = L_shr(L_tmp, 7); /* From Q23 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */ + + gcode0_fx = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + + /* retrieve the codebook index and calculate both gains */ + index = (Word16)get_next_indice_fx( st_fx, nBits ); + move16(); + + *gain_pit_fx = cdbk_fx[index * 2]; + move16(); + + L_tmp = L_mult(cdbk_fx[add(shl(index,1),1)] , gcode0_fx); /* Q9*Q0 -> Q10 */ + *gain_code_fx = L_shl(L_tmp, add(exp_gcode0, 6)); + move16(); /* Q10 -> Q16*/ + + gc_mem[1] = *gain_code_fx; + move32(); + gp_mem[1] = *gain_pit_fx; + move16(); + } + ELSE IF (EQ_16(i_subfr,2*L_SUBFR)) + { + b_fx = b_3sfr_fx; + move16(); + n_pred = 6; + move16(); + + cdbk_fx = gp_gamma_3sfr_6b_fx; + move16(); /* Q14/Q9*/ + + /* calculate predicted gain */ + aux_fx[0] = 4096; + move16(); + aux_fx[1] = shl(ctype,12); + move16(); + + /*aux_fx[2] = (float)log10(gc_mem[0]); + = log2(gc_mem[0])*log10(2);*/ + e_tmp = norm_l(gc_mem[0]); + f_tmp = Log2_norm_lc(L_shl(gc_mem[0], e_tmp)); + e_tmp = sub(sub(30,e_tmp),16); /*Q_format(gc_mem[0])=16*/ + L_tmp1 = Mpy_32_16(e_tmp, f_tmp, 9864); /* Q16 */ + aux_fx[2] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + /*aux[3] = (float)log10(gc_mem[1]); + = log2(gc_mem[1])*log10(2);*/ + e_tmp = norm_l(gc_mem[1]); + f_tmp = Log2_norm_lc(L_shl(gc_mem[1], e_tmp)); + e_tmp = sub(sub(30,e_tmp),16); /*Q_format(gc_mem[1])=16*/ + L_tmp1 = Mpy_32_16(e_tmp, f_tmp, 9864); /* Q16 */ + aux_fx[3] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + aux_fx[4] = shr(gp_mem[0],2); + move16(); + aux_fx[5] = shr(gp_mem[1],2); + move16(); + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, dotp(b, aux, n_pred) + * = pow(2, 3.321928*dotp(b, aux, n_pred) + *-----------------------------------------------------------------*/ + L_tmp = Dot_product(b_fx, aux_fx, n_pred); /*Q25*/ + L_tmp = Mult_32_16(L_tmp, 27213); /* *3.321928 in Q13 -> Q23 */ + L_tmp = L_shr(L_tmp, 7); /* From Q23 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */ + + gcode0_fx = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + + /* retrieve the codebook index and calculate both gains */ + index = (Word16)get_next_indice_fx( st_fx, nBits ); + move16(); + + *gain_pit_fx = cdbk_fx[index * 2]; + move16(); + + L_tmp = L_mult(cdbk_fx[add(shl(index,1),1)] , gcode0_fx); /* Q9*Q0 -> Q10 */ + *gain_code_fx = L_shl(L_tmp, add(exp_gcode0, 6)); /* Q10 -> Q16*/ + + gc_mem[2] = *gain_code_fx; + move32(); + gp_mem[2] = *gain_pit_fx; + move16(); + } + ELSE IF (EQ_16(i_subfr,3*L_SUBFR)) + { + b_fx = b_4sfr_fx; + move16(); + n_pred = 8; + move16(); + + cdbk_fx = gp_gamma_4sfr_6b_fx; + move16(); /* Q14/Q9*/ + + /* calculate predicted gain */ + aux_fx[0] = 4096; + move16(); + aux_fx[1] = shl(ctype,12); + move16(); + + /*aux[2] = (float)log10(gc_mem[0]); + = log2(gc_mem[0])*log10(2);*/ + e_tmp = norm_l(gc_mem[0]); + f_tmp = Log2_norm_lc(L_shl(gc_mem[0], e_tmp)); + e_tmp = sub(sub(30,e_tmp),16); /*Q_format(gc_mem[0])=16*/ + L_tmp1 = Mpy_32_16(e_tmp, f_tmp, 9864); /* Q16 */ + aux_fx[2] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + /*aux[3] = (float)log10(gc_mem[1]); + = log2(gc_mem[1])*log10(2);*/ + e_tmp = norm_l(gc_mem[1]); + f_tmp = Log2_norm_lc(L_shl(gc_mem[1], e_tmp)); + e_tmp = sub(sub(30,e_tmp),16); /*Q_format(gc_mem[1])=16*/ + L_tmp1 = Mpy_32_16(e_tmp, f_tmp, 9864); /* Q16 */ + aux_fx[3] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + /*aux[4] = (float)log10(gc_mem[2]); + = log2(gc_mem[2])*log10(2);*/ + e_tmp = norm_l(gc_mem[2]); + f_tmp = Log2_norm_lc(L_shl(gc_mem[2], e_tmp)); + e_tmp = sub(sub(30,e_tmp),16); /*Q_format(gc_mem[2])=16*/ + L_tmp1 = Mpy_32_16(e_tmp, f_tmp, 9864); /* Q16 */ + aux_fx[4] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + aux_fx[5] = shr(gp_mem[0],2);/*Q12*/ move16(); + aux_fx[6] = shr(gp_mem[1],2);/*Q12*/ move16(); + aux_fx[7] = shr(gp_mem[2],2);/*Q12*/ move16(); + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, dotp(b, aux, n_pred) + * = pow(2, 3.321928*dotp(b, aux, n_pred) + *-----------------------------------------------------------------*/ + L_tmp = Dot_product(b_fx, aux_fx, n_pred); /*Q25*/ + L_tmp = Mult_32_16(L_tmp, 27213); /* *3.321928 in Q13 -> Q23 */ + L_tmp = L_shr(L_tmp, 7); /* From Q23 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */ + + gcode0_fx = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + + /* retrieve the codebook index and calculate both gains */ + index = (Word16)get_next_indice_fx( st_fx, nBits ); + move16(); + *gain_pit_fx = cdbk_fx[index * 2]; + move16(); + + L_tmp = L_mult(cdbk_fx[add(shl(index,1),1)] , gcode0_fx); /* Q9*Q0 -> Q10 */ + *gain_code_fx = L_shl(L_tmp, add(exp_gcode0, 6)); + move32(); /* Q10 -> Q16*/ + } + + /* *norm_gain_code = *gain_code / *gain_inov; */ + expg = sub(norm_s(*gain_inov_fx),1); + expg = s_max(expg, 0); + + tmp_fx = div_s(shr(8192,expg),*gain_inov_fx); + *norm_gain_code_fx = L_shr(Mult_32_16(*gain_code_fx, tmp_fx),sub(1,expg)); + move32(); + + return; +} + +/*====================================================================== */ +/* FUNCTION : lp_gain_updt_fx() */ +/*-----------------------------------------------------------------------*/ +/* PURPOSE : Update of LP pitch and code gains (FEC) */ +/* */ +/*-----------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) i_subfr : subframe number Q0 */ +/* _ (Word16) gain_pit : Decoded gain pitch Q14 */ +/* _ (Word32) norm_gain_code : Normalised gain code Q16 */ +/* _ (Word16) L_frame : length of the frame Q0 */ +/*-----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 *) T0 : close loop integer pitch */ +/* _ (Word16 *) T0_frac : close loop fractional part of the pitch */ +/* _ (Word16 ) pitch : pitch value Q6 */ +/*-----------------------------------------------------------------------*/ +/* INPUT OUTPUT ARGUMENTS */ +/* _ (Word16 *) lp_gainp : LP-filtered pitch gain(FEC) Q14 */ +/* _ (Word16 *) lp_gainc : LP-filtered code gain (FEC) Q3 */ +/*-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*=======================================================================*/ + + +void lp_gain_updt_fx( + const Word16 i_subfr, /* i : subframe number Q0 */ + const Word16 gain_pit, /* i : Decoded gain pitch Q14 */ + const Word32 norm_gain_code, /* i : Normalised gain code Q16 */ + Word16 *lp_gainp, /* i/o: LP-filtered pitch gain(FEC) Q14 */ + Word16 *lp_gainc, /* i/o: LP-filtered code gain (FEC) Q3 */ + const Word16 L_frame /* i : length of the frame */ +) +{ + Word16 tmp; + + tmp = extract_h(L_shl(norm_gain_code,3)); /*(16+3)-16 -> Q3*/ + IF( EQ_16(L_frame,L_FRAME)) + { + IF(i_subfr == 0) + { + *lp_gainp = mult(3277,gain_pit); + move16(); /*0.1 in Q15 = 3277 , (15+14)-15 -> Q14*/ + *lp_gainc = mult_r(3277,tmp); + move16(); /* (15+3)-15 -> Q3*/ + } + ELSE IF( EQ_16(i_subfr,L_SUBFR)) + { + *lp_gainp = add(*lp_gainp, mult(6554, gain_pit)); + move16(); /*Q14 (0.2 in Q15 = 6554)*/ + *lp_gainc = mac_r(L_deposit_h(*lp_gainc), 6554, tmp); + move16(); /*Q3*/ + } + ELSE IF( EQ_16(i_subfr,2*L_SUBFR)) + { + *lp_gainp = add( *lp_gainp, mult(9830, gain_pit)); + move16(); /*Q14 (0.3 in Q15 = 9830)*/ + *lp_gainc = mac_r(L_deposit_h(*lp_gainc), 9830, tmp); + move16(); /*Q3*/ + } + ELSE /* i_subfr == 3*L_SUBFR */ + { + *lp_gainp = add( *lp_gainp, mult(13107, gain_pit)); + move16(); /*Q14 (0.4 in Q15 = 13107)*/ + *lp_gainc = mac_r(L_deposit_h(*lp_gainc), 13107, tmp); + move16(); /*Q3*/ + } + } + ELSE + { + IF( i_subfr == 0 ) + { + *lp_gainp = mult(2185,gain_pit); + move16(); /*(1.0/15.0) in Q15 = 2185 , (15+14)-15 -> Q14*/ + *lp_gainc = mult_r(2185,tmp); + move16(); /* (15+3)-15 -> Q3*/ + } + ELSE IF( EQ_16(i_subfr,L_SUBFR )) + { + *lp_gainp = add(*lp_gainp, mult(4369, gain_pit)); + move16(); /*Q14 (2.0/15.0 in Q15 = 4369)*/ + *lp_gainc = mac_r(L_deposit_h(*lp_gainc), 4369, tmp); + move16(); /*Q3*/ + } + ELSE IF( EQ_16(i_subfr,2*L_SUBFR)) + { + *lp_gainp = add(*lp_gainp, mult(6554, gain_pit)); + move16(); /*Q14 (3.0/15.0 in Q15 = 6554)*/ + *lp_gainc = mac_r(L_deposit_h(*lp_gainc), 6554, tmp); + move16(); /*Q3*/ + } + ELSE IF( EQ_16(i_subfr,3*L_SUBFR)) + { + *lp_gainp = add(*lp_gainp, mult(8738, gain_pit)); + move16(); /*Q14 (4.0/15.0 in Q15 = 8738)*/ + *lp_gainc = mac_r(L_deposit_h(*lp_gainc), 8738, tmp); + move16(); /*Q3*/ + } + ELSE /* i_subfr == 4*L_SUBFR */ + { + *lp_gainp = add(*lp_gainp, mult(10923, gain_pit)); + move16(); /*Q14 (5.0/15.0 in Q15 = 10923)*/ + *lp_gainc = mac_r(L_deposit_h(*lp_gainc), 10923, tmp); + move16(); /*Q3*/ + } + } + return; + +} + +/*-------------------------------------------------* + * Gain_dec_gaus_vbr + * + * Decode gains of purely unvoiced sounds + *-------------------------------------------------*/ +Word32 gain_dec_gaus_fx( /* o : quantized codebook gain Q16 */ + Word16 index, /* i : quantization index */ + const Word16 bits, /* i : number of bits to quantize */ + const Word16 lowBound, /* i : lower bound of quantizer (dB) */ + const Word16 topBound, /* i : upper bound of quantizer (dB) */ + const Word16 inv_gain_inov, /* o : unscaled innovation gain Q12 */ + Word32 *L_norm_gain_code /* o : gain of normalized gaussian excitation Q16 */ +) +{ + Word16 stepSize, gain, expg, frac, expi, tmp_igi; + Word32 L_tmp, L_enr_q, L_gain; + + /*------------------------------------------------------------------------------------------* + * Quantize linearly the log E + *------------------------------------------------------------------------------------------*/ + + stepSize = shl(sub(topBound,lowBound),sub(14, bits)); /* Q14 */ + + /*------------------------------------------------------------------------------------------* + * Gaussian codebook gain + *------------------------------------------------------------------------------------------*/ + + /* enr_q = (float)index*stepSize ,lowBound); */ + L_enr_q = L_mult(index, stepSize); /* Q0 * Q14 -> Q15 */ + L_enr_q = L_shl(L_enr_q, 9); /* Q15 -> Q24 */ + L_enr_q = L_add(L_enr_q, L_shl(L_deposit_h(lowBound),8)); /* Q24 */ + + /*------------------------------------------------------------* + * gain = pow(10.0, enr/20) + * = pow(2, 3.321928*enr/20) + * = pow(2, 0.166096*enr) + *------------------------------------------------------------*/ + + /* gain = (float)pow( 10.0f, enr/20.0f ); quantized codebook gain */ + L_tmp = Mult_32_16(L_enr_q, 21771); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */ + frac = L_Extract_lc(L_tmp, &expg); /* Extract exponent of enr */ + L_gain = Pow2(30, frac); /* Put 30 as exponent so that the */ + expg = add(expg, 16-30); /* output of Pow2() will be */ + /* Normalized, set result in Q16 */ + gain = round_fx(L_gain); + L_gain = L_shl(L_gain, expg); /* In Q16*/ + /* *norm_gain_code = gain / *inv_gain_inov;*/ + expi = norm_s(inv_gain_inov); + tmp_igi = shl(inv_gain_inov, expi); + L_tmp = div_s(shr(gain,1), tmp_igi); + L_tmp = L_shl(L_tmp, add(1,expi)); + *L_norm_gain_code = L_shl(L_tmp, add(expg,13)); /* Q16 */ move32(); + + return L_gain; +} + +/*--------------------------------------------------------------------------* +* gain_dec_SQ() +* +* Decoding of pitch and codebook gains using scalar quantizers +*-------------------------------------------------------------------------*/ + +void gain_dec_SQ_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 coder_type, /* i : coding type */ + const Word16 i_subfr, /* i : subframe number */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 *code, /* i : algebraic code excitation Q9*/ + const Word16 Es_pred, /* i : predicted scaled innov. energy Q8 */ + Word16 *gain_pit, /* o : Quantized pitch gain Q14*/ + Word32 *gain_code, /* o : Quantized codeebook gain Q16*/ + Word16 *gain_inov, /* o : unscaled innovation gain Q12*/ + Word32 *norm_gain_code /* o : norm. gain of the codebook excitation Q16*/ +) +{ + Word16 index, nBits; + Word16 gcode0, Ei; + Word16 tmp16, expg, expg2, e_tmp, f_tmp, exp_gcode0, frac; + Word32 L_tmp, L_tmp1; + + /*-----------------------------------------------------------------* + * get number of bits + *-----------------------------------------------------------------*/ + + nBits = gain_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ_fx(tc_subfr)) ]; + move16(); + + /*-----------------------------------------------------------------* + * decode pitch gain + *-----------------------------------------------------------------*/ + + index = (Word16)get_next_indice_fx(st_fx, shr(nBits,1) ); + + /*Ei = (G_PITCH_MAX - G_PITCH_MIN) / ((1 << (nBits>>1)) - 1); set quantization step */ + tmp16 = div_s(1,sub(shl(1,shr(nBits,1)),1)); /* Q15*/ + Ei = mult_r(G_PITCH_MAX_MINUS_MIN_Q13,tmp16); /* Q13*/ + + /**gain_pit = usdequant( index, G_PITCH_MIN, Ei );*/ + *gain_pit = usdequant_fx( index, G_PITCH_MIN_Q14, Ei ); + move16(); /*Q14 */ + + /*-----------------------------------------------------------------* + * calculate the predicted gain code + *-----------------------------------------------------------------*/ + + /*Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR;*/ + /**gain_inov = 1.0f / (float)sqrt( Ecode );*/ + + L_tmp = Dot_product12(code, code, L_SUBFR, &expg); + expg = sub(expg, 18 + 6); /* exp: -18 (code in Q9), -6 (/L_SUBFR) */ + expg2 = expg; + move16(); + L_tmp1 = L_tmp; /* sets to 'L_tmp' in 1 clock */ + move32(); + L_tmp = Isqrt_lc(L_tmp, &expg); + + *gain_inov = extract_h(L_shl(L_tmp, sub(expg, 3))); /* gain_inov in Q12 */ + + /*Ei = 10 * (float)log10( Ecode );*/ + e_tmp = norm_l(L_tmp1); + f_tmp = Log2_norm_lc(L_shl(L_tmp1, e_tmp)); + e_tmp = sub(expg2,add(1,e_tmp)); + L_tmp1 = Mpy_32_16(e_tmp, f_tmp, 12330); /* Q13 */ /* 10*log10(2) in Q12*/ + Ei = round_fx(L_shl(L_tmp1, 11)); /* Q8 */ + + /*gcode0 = (float) pow(10, 0.05 * (Es_pred - Ei));*/ + gcode0 = sub(Es_pred, Ei); /* Q8 */ + + /* gcode0 = pow(10.0, gcode0/20) = pow(2, 3.321928*gcode0/20) = pow(2, 0.166096*gcode0) */ + L_tmp = L_mult(gcode0, 21771); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */ + + gcode0 = extract_l(Pow2(14, frac));/* Put 14 as exponent so that output of Pow2() will be: 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + + /*-----------------------------------------------------------------* + * decode normalized codebook gain + *-----------------------------------------------------------------*/ + + index = (Word16)get_next_indice_fx(st_fx, shr(add(nBits,1),1) ); + + tmp16 = gain_dequant_fx( index, G_CODE_MIN_TC_Q15, G_CODE_MAX_TC_Q0, shr(add(nBits,1),1), &expg ); + + /**gain_code *= gcode0;*/ + L_tmp = L_mult(tmp16,gcode0); /* Q0*Q0 -> Q1*/ + /**gain_code = L_shl(L_tmp,add(expg,15)); Q16*/ + *gain_code = L_shl(L_tmp,add(add(expg,exp_gcode0),15)); + move32(); /*Q16*/ + + /**norm_gain_code = *gain_code / *gain_inov;*/ + expg = sub(norm_s(*gain_inov),1); + expg = s_max(expg, 0); + + tmp16 = div_s(shr(8192,expg),*gain_inov); + *norm_gain_code = L_shr(Mult_32_16(*gain_code,tmp16),sub(1,expg)); + move32(); + + return; +} + +/*---------------------------------------------------------------------* + * gain_dec_amr_wb() + * + * Decoding of pitch and fixed codebook gains (used also in AMR-WB IO mode) + *---------------------------------------------------------------------*/ + +void gain_dec_amr_wb_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + Word16 *gain_pit, /* o : Quantized pitch gain */ + Word32 *gain_code, /* o : Quantized codeebook gain */ + Word16 *past_qua_en, /* i/o: gain quantization memory (4 words) */ + Word16 *gain_inov, /* o : unscaled innovation gain */ + const Word16 *code, /* i : algebraic code excitation */ + Word32 *norm_gain_code /* o : norm. gain of the codebook excitation */ +) +{ + Word16 i, index, index2; + Word16 nbits; + Word16 gcode0, qua_en; + const Word16 *t_qua_gain; + Word16 tmp; + Word32 L_tmp; + Word16 expg, exp_gcode0, fracg; + + /**gain_inov = 1.0f/ (float)sqrt( ( dotp( code, code, L_SUBFR ) + 0.01f ) / L_SUBFR );*/ + + L_tmp = Dot_product12(code, code, L_SUBFR, &expg); + expg = sub(expg, 18 + 6); /* exp: -18 (code in Q9), -6 (/L_SUBFR) */ + L_tmp = Isqrt_lc(L_tmp, &expg); + + *gain_inov = extract_h(L_shl(L_tmp, sub(expg, 3))); /* gain_inov in Q12 */ + + /*-----------------------------------------------------------------* + * Select the gain quantization table + *-----------------------------------------------------------------*/ + nbits = 7; + move16(); + t_qua_gain = t_qua_gain7b_fx; + + IF( LT_32(core_brate,ACELP_12k65)) + { + nbits = 6; + move16(); + t_qua_gain = t_qua_gain6b_fx; + } + + /*-----------------------------------------------------------------* + * predicted code gain + *-----------------------------------------------------------------*/ + + /* start with predicting code energy in dB */ + /**for (i=0; i Q25 */ + } + + /* predicted codebook gain */ + gcode0 = extract_h(L_tmp); /* From Q25 to Q9 */ + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *-----------------------------------------------------------------*/ + L_tmp = L_mult(gcode0, 21771); /* *0.166096 in Q17 -> Q27 */ + L_tmp = L_shr(L_tmp, 9+2); /* From Q27 to Q16 */ + L_Extract(L_tmp, &exp_gcode0, &fracg); /* Extract exponent of gcode0 */ + + gcode0 = extract_l(Pow2(14, fracg));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + + /*-----------------------------------------------------------------* + * Decode pitch gain + *-----------------------------------------------------------------*/ + + index = (Word16)get_next_indice_fx( st_fx, nbits ); + index2 = shl(index,1); + *gain_pit = t_qua_gain[index2]; + move16(); + + /*-----------------------------------------------------------------* + * Decode code gain + *-----------------------------------------------------------------*/ + qua_en = t_qua_gain[add(index2,1)]; + move16(); + + /* *gain_code = t_qua_gain[indice*2+1] * gcode0; */ + L_tmp = L_mult(qua_en, gcode0); /* Q11*Q0 -> Q12 */ + tmp = round_fx(L_tmp); + move16(); /* Q-4 */ + *gain_code = L_shl(L_tmp, add(exp_gcode0, 4)); + move32(); /* Q12 -> Q16 */ + + /* adjust gain according to energy of code */ + L_tmp = Mult_32_16(*gain_code, *gain_inov); + *gain_code = L_shl(L_tmp, 3); + move32(); /* gcode_inov in Q12*/ + + /*-----------------------------------------------------------------* + * update table of past quantized energies + *-----------------------------------------------------------------*/ + + FOR (i=GAIN_PRED_ORDER-1; i>0; i--) + { + past_qua_en[i] = past_qua_en[i-1]; + move16(); + } + /*past_qua_en[0] = (float)(20.0*log10(qua_en));*/ + /*----------------------------------------------------------* + * past_qua_en[0] = 20*log10(t_qua_gain[indice*2+1]) + * = 6.0206*log2(t_qua_gain[indice*2+1]) + * = 6.0206*(log2(t_qua_gain[indice*2+1]Q11 -11) + *----------------------------------------------------------*/ + tmp = norm_l(qua_en); + fracg = Log2_norm_lc(L_shl(qua_en, tmp)); + expg = sub(30,tmp); + expg = sub(expg, 11); + L_tmp = Mpy_32_16(expg, fracg, 24660); /* x 6.0206 in Q12 */ + qua_en = extract_h(L_shl(L_tmp, 13)); /* result in Q10 */ + + past_qua_en[0] = qua_en; + move16(); /* in Q10 */ + + /*-----------------------------------------------------------------* + * Normalized code gain + *-----------------------------------------------------------------*/ + /**norm_gain_code = *gain_code / *gain_inov;*/ + expg = sub(norm_s(*gain_inov),1); + expg = s_max(expg, 0); + + tmp = div_s(shr(8192,expg),*gain_inov); + *norm_gain_code = L_shr(Mult_32_16(*gain_code,tmp),sub(1,expg)); + move32(); + + return; +} diff --git a/lib_dec/gaus_dec_fx.c b/lib_dec/gaus_dec_fx.c new file mode 100644 index 0000000..4890b2b --- /dev/null +++ b/lib_dec/gaus_dec_fx.c @@ -0,0 +1,284 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +void gaus_dec2v_fx( Decoder_State_fx *st_fx, Word16 *code, const Word16 lg, const Word16 nb_bits); +static void dec_2pos_fx(Word16 index, Word16 *ind1, Word16 *ind2, Word16 *sign1, Word16 *sign2, Word16 log2_n); + +/*---------------------------------------------------------------------* + * gaus_dec() + * + * no adaptive excitation constructed + * - decode the codebook indices, + * - find the excitation + *---------------------------------------------------------------------*/ +void gaus_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 i_subfr, /* i : subframe index */ + Word16 *code, /* o : unvoiced excitation Q12 */ + Word32 *L_norm_gain_code, /* o : gain of normalized gaussian excitation Q16 */ + Word16 *lp_gainp, /* i/o : lp filtered pitch gain(FER) Q14 */ + Word16 *lp_gainc, /* i/o : lp filtered code gain (FER) Q3 */ + Word16 *inv_gain_inov, /* o : unscaled innovation gain Q12 */ + Word16 *tilt_code, /* o : synthesis excitation spectrum tilt Q15 */ + Word16 *voice_fac, /* o : estimated voicing factor Q15 */ + Word16 *gain_pit, /* o : pitch gain Q14 */ + Word16 *pt_pitch_1, /* o : floating pitch buffer Q6 */ + Word16 *exc, /* o : excitation signal frame */ + Word32 *L_gain_code, /* o : gain of the gaussian excitation Q16 */ + Word16 *exc2, /* o : Scaled excitation signal frame */ + Word16 *bwe_exc_fx, + Word16 *sQ_exc, /* i/o : Excitation scaling factor (Decoder state) */ + Word16 *sQsubfr /* i/o : Past excitation scaling factors (Decoder State) */ +) +{ + Word16 i, exp, gain_code; + Word16 idx, nb_bits; + Word32 L_tmp; + + /*------------------------------------------------------------------------------------------* + * Unvoiced : Gaussian codebook + *------------------------------------------------------------------------------------------*/ + + nb_bits = FCB_bits_tbl[BIT_ALLOC_IDX_fx(core_brate, UNVOICED, i_subfr, TC_SUBFR2IDX_fx(-1))]; + move16(); + + gaus_dec2v_fx( st_fx, code, L_SUBFR, shr(nb_bits,1)); + + /*------------------------------------------------------------------------------------------* + * - Gain of Gaussian excitation and normalized Gaussian excitation + *------------------------------------------------------------------------------------------*/ + /* gain_inov = 1.0f / (float)sqrt((dot_product(code, code, L_SUBFR) + 0.01f) / L_SUBFR) */ + L_tmp = Dot_product12(code, code, L_SUBFR, &exp); + exp = sub(exp, 18/*24*/ + 6); /* exp: -18 (code in Q9), -6 (/L_SUBFR) */ + L_tmp = Isqrt_lc(L_tmp, &exp); + *inv_gain_inov = extract_h(L_shl(L_tmp, sub(exp, 3))); /* inv_gain_inov in Q12 */ + + nb_bits = gain_bits_tbl[BIT_ALLOC_IDX_fx(core_brate, UNVOICED, i_subfr, TC_SUBFR2IDX_fx(-1))]; + move16(); + idx = (Word16)get_next_indice_fx( st_fx, nb_bits ); + move16(); + + /* safety check in case of bit errors */ + IF( GT_16(idx,78)) + { + idx = 78; + move16(); + st_fx->BER_detect = 1; + move16(); + } + + *L_gain_code = gain_dec_gaus_fx( idx, nb_bits,-30,190, *inv_gain_inov, L_norm_gain_code ); + + /* update LP filtered gains for the case of frame erasures */ + lp_gain_updt_fx( i_subfr, 0, *L_norm_gain_code, lp_gainp, lp_gainc, L_FRAME ); /* supposes that gain_dec_gaus() is used for ACELP@12k8 only */ + + /*------------------------------------------------------------------------------------------* + * Updates + *------------------------------------------------------------------------------------------*/ + + *tilt_code = 0; + move16(); + *voice_fac = -32768; /* only unvoiced */ move16(); + *gain_pit = 0; /* needed for BASS postfitler */ move16(); + *pt_pitch_1 = 4096; /* floating pitch buffer Q6 */ move16(); + + /*------------------------------------------------------------------------------------------* + * Construct scaled excitation + *------------------------------------------------------------------------------------------*/ + + set16_fx(&exc[i_subfr],0, L_SUBFR); + set16_fx(&exc2[i_subfr],0, L_SUBFR); + + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + Rescale_exc( st_fx->dct_post_old_exc_fx, &exc[i_subfr], &bwe_exc_fx[i_subfr * HIBND_ACB_L_FAC], st_fx->last_exc_dct_in_fx, + L_SUBFR, L_SUBFR* HIBND_ACB_L_FAC, *L_gain_code, sQ_exc, sQsubfr, exc2, i_subfr, UNVOICED ); + } + ELSE + { + Rescale_exc( st_fx->dct_post_old_exc_fx, &exc[i_subfr], &bwe_exc_fx[i_subfr * 2], st_fx->last_exc_dct_in_fx, + L_SUBFR, L_SUBFR* 2, *L_gain_code, sQ_exc, sQsubfr, exc2, i_subfr, UNVOICED ); + } + + gain_code = round_fx(L_shl(*L_gain_code, *sQ_exc)); + FOR (i = 0; i < L_SUBFR; i++) + { + L_tmp = L_shl(L_mult(gain_code, code[i]), 6/*3*/); + exc[i+i_subfr] = round_fx(L_tmp); + } + + return; +} + + + +/*-----------------------------------------------------* + * gaus_dec2v() + * + * decoder of Gaussian Codebook for unvoiced + * consisting of addition of 2 Gaussian vectors + * + * One Gaussian vector of 190 values + *-----------------------------------------------------*/ + +void gaus_dec2v_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *code, /* o : decoded gaussian vector Q12-exp */ + const Word16 lg, /* i : codevector length Q0 */ + const Word16 nb_bits /* i : nb ob bits per track (max 6) */ +) +{ + Word16 i, ind1, ind2,idx; + Word16 step; + Word16 sign1, sign2; + Word16 delta, delta2, inv_delta; + Word16 gaus_dico2_fx[190]; + Word16 tmp16; + const Word16 *pt1, *pt2; + Word16 index_delta; + + step = shr(0x80, nb_bits); + + idx = (Word16)get_next_indice_fx( st_fx, add(shl(nb_bits,1),1) ); + index_delta = (Word16)get_next_indice_fx( st_fx, 3 ); + + dec_2pos_fx( idx, &ind1, &ind2, &sign1, &sign2, nb_bits ); + + delta = shl(index_delta, STEP_DELTA_FX); + delta2 = mac_r(16384*65536, shr(delta,1), delta); + inv_delta = div_s(16384, delta2); + + IF (delta > 0) + { + gaus_dico2_fx[0] = gaus_dico_fx[0]; + move16(); /*Q12 */ + FOR (i=1; i<190; i++) + { + /* gaus_dico2[i] = (gaus_dico_fx[i] - delta*gaus_dico_fx[i-1])/(1+delta*delta) */ + tmp16 = msu_r(L_deposit_h(gaus_dico_fx[i]), delta, gaus_dico_fx[i-1]); + gaus_dico2_fx[i] = mult_r(tmp16, inv_delta); + } + } + ELSE + { + FOR (i=0; i<190; i++) + { + gaus_dico2_fx[i] = gaus_dico_fx[i]; + move16(); /*Q12 */ + } + } + + pt1 = &gaus_dico2_fx[i_mult2(ind1, step)]; + move16(); + pt2 = &gaus_dico2_fx[i_mult2(ind2, step)]; + move16(); + + FOR (i = 0; i < lg; i++) + { + /* code is Q9, Gaussian codebook is Q12 */ + /* code[i] = pt1[i] * sign1 + pt2[i] * sign2 */ + code[i] = add(mult(pt1[i], sign1), mult(pt2[i], sign2)); + } + + return; +} + + +/*-----------------------------------------------------* + * dec_2pos() + * + * Decode the codevectors positions and signs + *-----------------------------------------------------*/ +static void dec_2pos_fx( + Word16 index, /* i : quantization index Q0 */ + Word16 *ind1, /* o : 1st vector index Q0 */ + Word16 *ind2, /* o : 2nd vector index Q0 */ + Word16 *sign1, /* o : 1st vector sign Q0 */ + Word16 *sign2, /* o : 2nd vector sign Q0 */ + Word16 log2_n /* i : Log2(number of vector) Q0 */ +) +{ + Word16 i; + + i = s_and(index, 1); + *sign1 = (-32768); /* -1 (Q15) */ move16(); + if (i == 0) + { + *sign1 = MAX_16; /* 1 (Q15) */ move16(); + } + *sign1 = shr(*sign1,3); + move16(); /* To have code dec in Q9 instead of Q12 */ + + index = shr(index, 1); + + *ind1 = shr(index, log2_n); + move16(); + *ind2 = sub(index, shl(*ind1, log2_n)); + move16(); + *sign2 = *sign1; + move16(); + if (GT_16(*ind1, *ind2)) + { + *sign2 = negate(*sign1); + move16(); + } + return; +} + + + +/*-----------------------------------------------------* + * gaus_L2_dec : + * + * decoder of Gaussian Codebook for unvoiced as Layer 2 + * + * One Gaussian vector + *-----------------------------------------------------*/ +void gaus_L2_dec( + Word16 *code, /* o : decoded gaussian codevector Q9 */ + Word16 tilt_code, /* i : tilt of code Q15 */ + const Word16 *A, /* i : quantized LPCs Q12 */ + Word16 formant_enh, /* i : formant enhancement factor Q15 */ + Word16 *seed_acelp /*i/o : random seed Q0 */ +) +{ + Word16 i, seed; + Word32 tmp32; + + /*Generate white gaussian noise using central limit theorem method (N only 4 as E_util_random is not purely uniform)*/ + seed = *seed_acelp; + move16(); + FOR (i = 0; i < L_SUBFR; i++) + { + seed = own_random2_fx(seed); + tmp32 = L_mac(0, seed, 1<<9); + + seed = own_random2_fx(seed); + tmp32 = L_mac(tmp32, seed, 1<<9); + + seed = own_random2_fx(seed); + code[i] = mac_r(tmp32, seed, 1<<9); + move16(); + } + *seed_acelp = seed; + move16(); + + /*Shape the gaussian excitation*/ + cb_shape_fx( 1, 0, 0, 1, 0, formant_enh, FORMANT_SHARPENING_G2, A, code, tilt_code, 0, 1 ); + + + return; +} + diff --git a/lib_dec/gs_dec_amr_wb_fx.c b/lib_dec/gs_dec_amr_wb_fx.c new file mode 100644 index 0000000..f3a5e5a --- /dev/null +++ b/lib_dec/gs_dec_amr_wb_fx.c @@ -0,0 +1,454 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define ALP_FX 22938 /* 0.70f */ +#define MALP_FX (Word16)(32768L-ALP_FX) +#define ALPMY_FX 28180 /* 0.86f */ + +#define BAND3k 15 +#define BIN_1k2 48 +#define BAND_2k 12 +#define BAND_0k4 4 + +#define NORMALIZE_SPECS_Q_OUT 6 +#define ENER_FX_Q_GUARD 1 + +/*-------------------------------------------------------------------* + * NoiseFill_fx() + * + * noise fill function for unvoiced/inactive frames (used only in AMR-WB IO mode) + *-------------------------------------------------------------------*/ + +static void NoiseFill_fx( + Word16 *exc_diffQ_fx, /* i/o: Noise per band */ + Word16 *seed_tcx, /* i : Seed for noise */ + const Word16 Mbands_gn, /* i : number of bands */ + const Word16 Q_out /* i : Q of exc_diffQ_fx[] */ +) +{ + Word16 i_band, CurBin, EndBin; + Word32 L_temp; + Word16 fact; + CurBin = 0; + move16(); + fact = shr(24576/*0.75f*/, sub(15, Q_out)); + + FOR( i_band = 0; i_band < Mbands_gn; i_band++ ) + { + EndBin = add(CurBin, crit_bins[i_band]); + FOR( ; CurBin Q9 */ + L_temp = L_mult(exc_diffQ_fx[i],s_max(temp2,512)); /*Q(Qexc_diffQ+10) */ + exc_diffQ_fx[i] = round_fx(L_shl(L_temp,16-10));/*Qexc_diffQ */ + } + + /*--------------------------------------------------------------------------------------* + * Match the energy of the modified excitation vector to the decoded excitation + *--------------------------------------------------------------------------------------*/ + Apply_gain_fx( exc_diffQ_fx, Ener_per_bd_iQ_fx, Ener_per_bd_yQ_fx,sub(NORMALIZE_SPECS_Q_OUT, Q_dct_out) ); + /*--------------------------------------------------------------------------------------* + * Copy to the output vector + *--------------------------------------------------------------------------------------*/ + + Copy(exc_diffQ_fx, dct_out_fx, L_FRAME); + + return; +} + +/*-------------------------------------------------------------------* + * improv_amr_wb_gs_fx() + * + * Modify the decoded excitation to increase quality of + * unvoiced and audio signals (used only in AMR-WB IO mode) + *-------------------------------------------------------------------*/ +void improv_amr_wb_gs_fx( + const Word16 clas, /* i : signal frame class */ + const Word16 coder_type, /* i : coder type */ + const Word32 core_brate, /* i : bitrate allocated to the core */ + Word16 *seed_tcx, /* i/o: Seed used for noise generation */ + Word16 *old_Aq_fx, /* i/o: old LPC filter coefficient */ + Word16 *mem_syn2_fx, /* i/o: synthesis memory */ + const Word16 lt_voice_fac_fx, /* i/o: long term voice factor Q14 */ + const Word16 locattack, /* i : Flag for a detected attack */ + Word16 *Aq_fx, /* i/o: Decoded LP filter coefficient */ + Word16 *exc2_fx, /* i/o: Decoded complete excitation */ + const Word16 Q_exc2, /* i : Exponent of Exc2 */ + Word16 *mem_tmp_fx, /* i/o: synthesis temporary memory */ + Word16 *syn_fx, /* o: Decoded synthesis to be updated */ + const Word16 Q_syn, /* i : Synthesis scaling Q0 */ + const Word16 *pitch_buf_fx, /* i : Decoded pitch buffer Q6 */ + const Word16 Last_ener_fx /* i : Last energy (Q8) */ + ,const Word16 rate_switching_reset /* i : rate switching reset flag */ + ,const Word16 last_coder_type_fx /* i : Last coder_type */ +) +{ + Word16 i, exp_a, exp_b, exp_diff, j; + Word16 dct_exc_in_fx[L_FRAME], dct_exc_out_fx[L_FRAME]; + Word16 Aq_orig[NB_SUBFR*(M+1)], enr_LP_old, enr_LP_new; + + /*------------------------------------------------------------* + * Condition to enter the section on excitation modification + *------------------------------------------------------------*/ + + /* Enter the modification for all inactive frames and also for unvoiced frames if bit rate is below 8k85 */ + + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( locattack == 0 && LE_32(core_brate, ACELP_12k65))&& + ( (LT_32(core_brate, ACELP_8k85) && NE_16(clas, AUDIO_CLAS) && + (EQ_16(clas, UNVOICED_CLAS) || EQ_16(clas, VOICED_TRANSITION) )) || EQ_16(coder_type, INACTIVE) ) ) + { + /*------------------------------------------------------------* + * two differents paths: + * unvoiced or inactive + * generic audio sound + * LP filter smoothing for inactive parts + *------------------------------------------------------------*/ + *seed_tcx = extract_l(L_mult0(pitch_buf_fx[0],pitch_buf_fx[3])); + /* last_coder_type_fx == UNVOICED should be understand as INACTIVE, but it is forced to UNVOICED in update_dec */ + test(); + test(); + test(); + IF( EQ_16(coder_type, INACTIVE)&>_16(Last_ener_fx,-3*256)&&EQ_16(last_coder_type_fx,UNVOICED)&&rate_switching_reset==0) /* 3.0 x 256 to Go to Q8 */ + { + + FOR(i =0; i < NB_SUBFR; i++) + { + Copy( Aq_fx, Aq_orig, NB_SUBFR*(M+1) ); + + exp_a = norm_s(Aq_fx[i*(M+1)]); + exp_b = norm_s(old_Aq_fx[i*(M+1)]); + exp_diff = sub(exp_a, exp_b); + IF(exp_diff>0) + { + Scale_sig(&old_Aq_fx[i*(M+1)], (M+1), negate(exp_diff)); + } + ELSE + { + Scale_sig(&Aq_fx[i*(M+1)], (M+1), exp_diff); + + } + FOR(j = i*(M+1); j < (i+1)*(M+1); j++) + { + + Aq_fx[j] = round_fx(L_mac(L_mult(ALP_FX, old_Aq_fx[j]), MALP_FX, Aq_fx[j])); + } + } + + /* check the smoothed LP filter stability */ + enr_LP_old = Enr_1_Az_fx( old_Aq_fx, L_SUBFR ); + Overflow = 0; + move16(); + + FOR( i=0; i < NB_SUBFR; i++ ) + { + enr_LP_new = Enr_1_Az_fx( Aq_fx+i*(M+1), L_SUBFR ); + + IF( (shr(enr_LP_new,7) > enr_LP_old) || Overflow ) + { + /* filter is unstable, do not modify the excitation */ + Copy( Aq_orig, Aq_fx, NB_SUBFR*(M+1) ); + Overflow = 0; + move16(); + + return; + } + + enr_LP_old = enr_LP_new; + move16(); + } + } + + /*------------------------------------------------------------* + * Find frequency representation of the excitation + * Do the excitation modification according to the content + * Go back to time domain -> Overwrite exctiation + *------------------------------------------------------------*/ + edct_16fx(exc2_fx, dct_exc_in_fx, L_FRAME, 6); + gs_dec_amr_wb_fx( core_brate, seed_tcx, dct_exc_in_fx, Q_exc2, dct_exc_out_fx, Q_exc2, pitch_buf_fx, lt_voice_fac_fx, clas, coder_type ); + + edct_16fx(dct_exc_out_fx, exc2_fx, L_FRAME, 6); + /*------------------------------------------------------------* + * Redo core synthesis at 12k8 Hz with the modified excitation + *------------------------------------------------------------*/ + + Copy( mem_tmp_fx, mem_syn2_fx, M ); + syn_12k8_fx(L_FRAME, Aq_fx, exc2_fx, syn_fx, mem_syn2_fx, 1, Q_exc2, Q_syn ); + } + + return; +} diff --git a/lib_dec/gs_dec_fx.c b/lib_dec/gs_dec_fx.c new file mode 100644 index 0000000..903d5b5 --- /dev/null +++ b/lib_dec/gs_dec_fx.c @@ -0,0 +1,606 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "stl.h" +#include "options.h" +#include "cnst_fx.h" +#include "rom_com_fx.h" +#include "prot_fx.h" + +/*=========================================================================*/ +/* FUNCTION : void decod_audio_fx(); */ +/*-------------------------------------------------------------------------*/ +/* PURPOSE : Decode audio (AC) frames */ +/*-------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16[]) Aq : LP filter coefficient Q12 */ +/* _ (Word16) coder_type : coding type Q0 */ +/* _(Word16) Q_exc :Q format of excitation */ +/*-------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) pitch_buf_fx : floating pitch values for each subframe Q6*/ +/* _ (Word16[]) voice_factors_fx: frame error rate Q15 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Decoder_State_fx *st_fx : decoder memory structure */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Q_exc) */ +/* _ (Word16[]) exc2_fx : adapt. excitation/total exc (Q_exc) */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*==========================================================================*/ +void decod_audio_fx( + Decoder_State_fx *st_fx, /* i/o: decoder static memory */ + Word16 dct_epit[], /* o : GSC excitation in DCT domain */ + const Word16 *Aq, /* i : LP filter coefficient */ + const Word16 coder_type, /* i : coding type */ + Word16 *pitch_buf, /* o : floating pitch values for each subframe */ + Word16 *voice_factors, /* o : voicing factors */ + Word16 *exc, /* i/o: adapt. excitation exc */ + Word16 *exc2, /* i/o: adapt. excitation/total exc */ + Word16 *bwe_exc, /* o : excitation for SWB TBE */ + Word16 *lsf_new /* i : ISFs at the end of the frame */ + , Word16 *gain_buf /*Q14*/ +) +{ + Word16 tmp_nb_bits_tot, pit_band_idx; + Word16 code[L_SUBFR]; + Word16 Diff_len, nb_subfr, i; + Word16 nb_frame_flg; + Word16 Es_pred = 0; + Word16 Len, max_len; + Word16 gsc_attack_flag; + + Word16 low_pit; + Word16 last_bin; + Word16 nbits; + + Word16 exc_wo_nf[L_FRAME]; + + + /*---------------------------------------------------------------* + * Initialization + *---------------------------------------------------------------*/ + Diff_len = 0; + move16(); + + /* decode GSC attack flag (used to reduce possible pre-echo) */ + gsc_attack_flag = (Word16) get_next_indice_fx( st_fx, 1 ); + + /* decode GSC SWB speech flag */ + test(); + IF( NE_16(coder_type,INACTIVE)&&GE_32(st_fx->total_brate_fx,ACELP_13k20)) + { + st_fx->GSC_noisy_speech_fx = (Word16) get_next_indice_fx( st_fx, 1 ); + } + + /* safety check in case of bit errors */ + test(); + IF( st_fx->GSC_noisy_speech_fx && NE_16(st_fx->bwidth_fx,SWB)) + { + st_fx->BER_detect = 1; + move16(); + st_fx->GSC_noisy_speech_fx = 0; + move16(); + } + + /*---------------------------------------------------------------* + * Decode energy dynamics + *---------------------------------------------------------------*/ + IF( EQ_16(st_fx->GSC_noisy_speech_fx,1)) + { + nb_subfr = NB_SUBFR; + move16(); + st_fx->cor_strong_limit_fx = 0; + move16(); + st_fx->noise_lev_fx = NOISE_LEVEL_SP3; + move16(); + } + ELSE + { + IF( LE_32(st_fx->core_brate_fx,ACELP_8k00)) + { + st_fx->noise_lev_fx = add((Word16)get_next_indice_fx( st_fx, 2 ), NOISE_LEVEL_SP2); + } + ELSE + { + st_fx->noise_lev_fx = add((Word16)get_next_indice_fx( st_fx, 3 ), NOISE_LEVEL_SP0); + } + + /*---------------------------------------------------------------* + * Decode number of subframes + *---------------------------------------------------------------*/ + + st_fx->cor_strong_limit_fx = 1; + move16(); + nb_subfr = SWNB_SUBFR; + move16(); + + IF( GE_32(st_fx->core_brate_fx,ACELP_9k60)) + { + nbits = 1; + move16(); + nb_frame_flg = (Word16)get_next_indice_fx( st_fx, nbits ); + + IF( s_and(nb_frame_flg,0x1) == 0) + { + nb_subfr = 2*SWNB_SUBFR; + move16(); + st_fx->cor_strong_limit_fx = 0; + move16(); + } + } + } + + /*---------------------------------------------------------------* + * Decode the last band where the adaptive (pitch) contribution is significant + *---------------------------------------------------------------*/ + + IF( LT_32(st_fx->core_brate_fx,CFREQ_BITRATE)) + { + nbits = 3; + move16(); + test(); + if( LT_32(st_fx->core_brate_fx,ACELP_9k60)&&(EQ_16(coder_type,INACTIVE))) + { + nbits = 1; + move16(); + } + } + ELSE + { + nbits = 4; + move16(); + } + test(); + IF( LT_32(st_fx->core_brate_fx,ACELP_9k60)&&NE_16(coder_type,INACTIVE)) + { + pit_band_idx = 1; + move16(); + } + ELSE + { + pit_band_idx = (Word16)get_next_indice_fx( st_fx, nbits ); + } + + IF( pit_band_idx != 0 ) + { + IF( LT_32(st_fx->core_brate_fx,ACELP_9k60)) + { + pit_band_idx = 7+BAND1k2; + move16(); /* At low rate, if pitch model is chosen, then for to be use on extented and constant frequency range */ + } + ELSE + { + pit_band_idx = add(pit_band_idx, BAND1k2); + } + + /* detect bit errors in the bitstream */ + IF( GT_16(pit_band_idx,13)) /* The maximum decodable index is 10 + BAND1k2 (3) = 13 */ + { + pit_band_idx = 13; + move16(); + st_fx->BER_detect = 1; + move16(); + } + Diff_len = mfreq_loc_div_25[pit_band_idx]; + move16(); + } + st_fx->Last_GSC_pit_band_idx_fx = pit_band_idx; + move16(); + + + /*--------------------------------------------------------------------------------------* + * Decode adaptive (pitch) excitation contribution + * Reset unvaluable part of the adaptive (pitch) excitation contribution + *--------------------------------------------------------------------------------------*/ + IF( GT_16(pit_band_idx,BAND1k2)) + { + /*---------------------------------------------------------------* + * Decode adaptive (pitch) excitation contribution + *---------------------------------------------------------------*/ + test(); + IF( EQ_16(st_fx->GSC_noisy_speech_fx,1)&&EQ_16(nb_subfr,NB_SUBFR)) + { + Es_pred_dec_fx( st_fx, &Es_pred, GENERIC, st_fx->core_brate_fx ); + } + + dec_pit_exc_fx( st_fx, Aq, coder_type, Es_pred, pitch_buf, code, exc, bwe_exc, nb_subfr + , gain_buf + ); + + IF( LT_32(st_fx->core_brate_fx,ACELP_9k60)) + { + minimum_fx( pitch_buf, shr(L_FRAME,6), &low_pit); + low_pit = shr(low_pit, 6); /*Q6 -> Q0 */ + + IF( LT_16(low_pit,64)) + { + pit_band_idx = 9+BAND1k2; + move16(); + if(EQ_16(st_fx->bwidth_fx,NB)) + { + pit_band_idx = 7+BAND1k2; + move16(); + } + } + ELSE IF ( LT_16(low_pit,128)) + { + pit_band_idx = 5+BAND1k2; + move16(); + } + ELSE + { + pit_band_idx = 3+BAND1k2; + move16(); + } + + Diff_len = mfreq_loc_div_25[pit_band_idx]; + move16(); + st_fx->Last_GSC_pit_band_idx_fx = pit_band_idx; + move16(); + } + + /*---------------------------------------------------------------* + * DCT transform + *---------------------------------------------------------------*/ + edct_16fx( exc, dct_epit, L_FRAME, 7 ); + + /*---------------------------------------------------------------* + * Reset unvaluable part of the adaptive (pitch) excitation contribution + *---------------------------------------------------------------*/ + + max_len = sub( L_FRAME, Diff_len ); + + if(EQ_16(st_fx->bwidth_fx,NB)) + { + max_len = sub(160,Diff_len); + } + + Len = 80; + move16(); + if( max_len < 80 ) + { + Len = max_len; + move16(); + } + + test(); + IF(EQ_32(st_fx->core_brate_fx,ACELP_8k00)&&NE_16(st_fx->bwidth_fx,NB)) + { + FOR (i=0; i < max_len; i++) + { + dct_epit[i+Diff_len] = 0; + move16(); + } + } + ELSE + { + FOR (i = 0; i < Len; i++) + { + dct_epit[i + Diff_len] = mult_r(dct_epit[i + Diff_len],sm_table_fx[i]); + move16(); + } + + FOR (; i < max_len; i++) + { + dct_epit[i + Diff_len] = 0; + move16(); + } + } + st_fx->bfi_pitch_fx = mean_fx(pitch_buf, nb_subfr); + move16(); + st_fx->bfi_pitch_frame_fx = L_FRAME; + move16(); + + Diff_len = add(Diff_len,1); + st_fx->bpf_off_fx = 0; + move16(); + } + ELSE + { + /* No adaptive (pitch) excitation contribution */ + st_fx->bpf_off_fx = 1; + move16(); + set16_fx( dct_epit, 0, L_FRAME ); + set16_fx( pitch_buf, shl(L_SUBFR,6), NB_SUBFR ); + + set16_fx( gain_buf, 0, NB_SUBFR16k); + + st_fx->bfi_pitch_fx = shl(L_SUBFR,6); + st_fx->bfi_pitch_frame_fx = L_FRAME; + move16(); + st_fx->lp_gainp_fx = 0; + move16(); + st_fx->lp_gainc_fx = 0; + move16(); + st_fx->tilt_code_fx = 0; + move16(); + pit_band_idx = 0; + move16(); + Diff_len = 0; + move16(); + } + + /*--------------------------------------------------------------------------------------* + * GSC decoder + *--------------------------------------------------------------------------------------*/ + + /* find the current total number of bits used */ + + tmp_nb_bits_tot = st_fx->next_bit_pos_fx; + move16(); + + if( st_fx->extl_brate_fx > 0 ) + { + /* subtract 1 bit for TBE/BWE BWE flag (bit counted in extl_brate) */ + tmp_nb_bits_tot = sub(tmp_nb_bits_tot, 1); + } + + + test(); + if( EQ_16(coder_type,INACTIVE)&&LE_32(st_fx->core_brate_fx,ACELP_9k60)) + { + tmp_nb_bits_tot = add(tmp_nb_bits_tot,5); + } + + gsc_dec_fx(st_fx, dct_epit, pit_band_idx, Diff_len, tmp_nb_bits_tot, nb_subfr, coder_type, &last_bin, lsf_new, exc_wo_nf, st_fx->Q_exc ); + + /*--------------------------------------------------------------------------------------* + * iDCT transform + *--------------------------------------------------------------------------------------*/ + + edct_16fx( dct_epit, exc, L_FRAME, 7 ); + edct_16fx( exc_wo_nf, exc_wo_nf, L_FRAME, 7 ); + /*----------------------------------------------------------------------* + * Remove potential pre-echo in case an onset has been detected + *----------------------------------------------------------------------*/ + + pre_echo_att_fx( &st_fx->Last_frame_ener_fx, exc, gsc_attack_flag + ,st_fx->Q_exc + ,st_fx->last_coder_type_fx + ); + + /*--------------------------------------------------------------------------------------* + * Update BWE excitation + *--------------------------------------------------------------------------------------*/ + + set16_fx( voice_factors, 0, NB_SUBFR16k ); + interp_code_5over2_fx( exc, bwe_exc, L_FRAME ); + + /*--------------------------------------------------------------------------------------* + * Updates + *--------------------------------------------------------------------------------------*/ + + Copy( exc, exc2, L_FRAME ); + Copy( exc_wo_nf, exc, L_FRAME ); + + /*--------------------------------------------------------------------------------------* + * Channel aware mode parameters + *--------------------------------------------------------------------------------------*/ + + set16_fx( st_fx->tilt_code_dec_fx, 0, NB_SUBFR16k ); + + return; +} + +/*==========================================================================*/ +/* FUNCTION : void gsc_dec_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Generic audio signal decoder */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) pit_band_idx : bin position of the cut-off frequency Q0 */ +/* _ (Word16) Diff_len : Lenght of the difference signal Q0 */ +/* _ (Word16) coder_type : coding type Q0 */ +/* _ (Word16) bits_used : Number of bit used before frequency Q Q0 */ +/* _ (Word16) nb_subfr : Number of subframe considered Q0 */ +/* _ (Word16) Qexc : Q format of exc_dct_in */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Decoder_State_fx *st_fx:Decoder State Structure */ +/* _ (Word16[]) exc_dct_in : dctof pitch-only excitation / total excitation Qexc*/ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _None */ +/*==========================================================================*/ +void gsc_dec_fx( + Decoder_State_fx *st_fx, /* i/o: State structure */ + Word16 exc_dct_in[], /* i/o: dct of pitch-only excitation / total excitation */ + const Word16 pit_band_idx, /* i : bin position of the cut-off frequency */ + const Word16 Diff_len, /* i : Lenght of the difference signal (before pure spectral)*/ + const Word16 bits_used, /* i : Number of bit used before frequency Q */ + const Word16 nb_subfr, /* i : Number of subframe considered */ + const Word16 coder_type, /* i : coding type */ + Word16 *last_bin, /* i : last bin of bit allocation */ + Word16 *lsf_new, /* i : ISFs at the end of the frame */ + Word16 *exc_wo_nf, /* o : excitation (in f domain) without noisefill */ + Word16 Q_exc +) +{ + Word16 i, j, bit, nb_subbands, pvq_len; + Word16 bitallocation_band[MBANDS_GN]; + Word16 bitallocation_exc[2]; + Word16 Ener_per_bd_iQ[MBANDS_GN]; + Word16 max_ener_band[MBANDS_GN]; + Word16 exc_diffQ[L_FRAME]; + Word16 bits_per_bands[MBANDS_GN]; + Word16 concat_out[L_FRAME]; + Word16 inpulses_fx[NB_SFM]; + Word16 imaxpulse_fx[NB_SFM]; + Word16 mean_gain; + Word16 Mbands_gn = 16; + Word16 Qexc_diffQ = Q_PVQ_OUT; + Word32 L_tmp; + Word16 Q_tmp; + Word16 seed_init; + + set16_fx(inpulses_fx, 0,NB_SFM); + set16_fx(imaxpulse_fx, 0,NB_SFM); + + /*--------------------------------------------------------------------------------------* + * Initialization + *--------------------------------------------------------------------------------------*/ + bit = bits_used; + move16(); + set16_fx( exc_diffQ, 0, L_FRAME ); + + /*--------------------------------------------------------------------------------------* + * Gain decoding + *--------------------------------------------------------------------------------------*/ + + test(); + IF( st_fx->bfi_fx || st_fx->BER_detect ) + { + /* copy old gain */ + Copy( st_fx->old_y_gain_fx, Ener_per_bd_iQ, Mbands_gn ); + mean_gain = mult_r(st_fx->lp_gainc_fx,3277); /*Q3*/ + FOR( i=0; ilp_gainc_fx = mult_r(st_fx->lp_gainc_fx,32112); /*Q3*/ + } + ELSE + { + mean_gain = gsc_gaindec_fx( st_fx, Ener_per_bd_iQ, st_fx->core_brate_fx, st_fx->old_y_gain_fx, coder_type, st_fx->bwidth_fx ); + + st_fx->lp_gainc_fx = mult_r(640,mean_gain); /*10 in Q6 x Q12 -> lp_gainc in Q3 */ + } + + *last_bin = 0; + move16(); + test(); + IF( EQ_32(st_fx->core_brate_fx,ACELP_8k00)&&NE_16(st_fx->bwidth_fx,NB)) + { + bitallocation_exc[0] = 0; + move16(); + bitallocation_exc[1] = 0; + move16(); + } + + set16_fx( bitallocation_band, 0, MBANDS_GN ); + + test(); + IF( (EQ_16(st_fx->bfi_fx,1))||st_fx->BER_detect) + { + /*--------------------------------------------------------------------------------------* + * Copy old spectrum + * reduce spectral dynamic + * save spectrum + *--------------------------------------------------------------------------------------*/ + test(); + IF( EQ_16(st_fx->last_good_fx,INACTIVE_CLAS)||EQ_16(st_fx->Last_GSC_noisy_speech_flag_fx,1)) + { + FOR( i=0; iseed_tcx_fx),26214),5); /*Q10*/ + L_tmp = L_mac(L_tmp, st_fx->Last_GSC_spectrum_fx[i],6554); + st_fx->Last_GSC_spectrum_fx[i] = round_fx(L_tmp); /*Q10*/ + } + } + + Copy( st_fx->Last_GSC_spectrum_fx, exc_diffQ, L_FRAME ); + + FOR( i=0; iLast_GSC_spectrum_fx[i] = mult_r(st_fx->Last_GSC_spectrum_fx[i],24576); /*Q10*/ move16(); + } + + } + ELSE + { + /*--------------------------------------------------------------------------------------* + * PVQ decoder + *--------------------------------------------------------------------------------------*/ + + bands_and_bit_alloc_fx( st_fx->cor_strong_limit_fx, st_fx->noise_lev_fx, st_fx->core_brate_fx, Diff_len, bit, &bit, Ener_per_bd_iQ, + max_ener_band, bits_per_bands, &nb_subbands, NULL, NULL, &pvq_len, coder_type, st_fx->bwidth_fx, st_fx->GSC_noisy_speech_fx ); + + pvq_core_dec_fx( st_fx, gsc_sfm_start, gsc_sfm_end, gsc_sfm_size, concat_out, &Q_tmp, bit, nb_subbands, bits_per_bands, NULL, inpulses_fx, imaxpulse_fx, ACELP_CORE ); + Scale_sig(concat_out, gsc_sfm_end[nb_subbands-1], sub(Q_PVQ_OUT, Q_tmp)); + + seed_init = 0; + move16(); + + /* Reorder Q bands */ + FOR(j = 0; j < nb_subbands; j++) + { + Copy( concat_out+j*16, exc_diffQ + max_ener_band[j]*16, 16); + + *last_bin = s_max(*last_bin,max_ener_band[j]); + move16(); + + bitallocation_band[max_ener_band[j]] = 1; + move16(); + + seed_init =add(seed_init,inpulses_fx[j]); + } + test(); + IF( NE_16(st_fx->last_coder_type_fx, AUDIO) /* First audio frame */ + && NE_16(st_fx->last_coder_type_fx, UNVOICED) )/* last_coder_type == INACTIVE is overwritten in update_dec to UNVOICED */ + { + FOR( j = 0; j < shl(nb_subbands,4); j++ ) + { + IF( concat_out[j] > 0 ) + { + seed_init = extract_l(L_shl(seed_init,3)); + } + IF( concat_out[j] < 0 ) + { + seed_init = add(seed_init,3); + move16(); + } + } + + st_fx->seed_tcx_fx = seed_init; + move16(); + } + test(); + IF( EQ_32(st_fx->core_brate_fx,ACELP_8k00)&&NE_16(st_fx->bwidth_fx,NB)) + { + if( exc_diffQ[L_FRAME8k - 2] != 0 ) + { + bitallocation_exc[0] = 1; + move16(); + } + + if( exc_diffQ[L_FRAME8k - 1] != 0 ) + { + bitallocation_exc[1] = 1; + move16(); + } + } + + Copy( exc_diffQ, st_fx->Last_GSC_spectrum_fx, L_FRAME ); + + /*--------------------------------------------------------------------------------------* + * Skip adaptive (pitch) contribution frequency band (no noise added over the time contribution) + * Find x pulses between 1.6-3.2kHz to code in the spectrum of the residual signal + * Gain is based on the inter-correlation gain between the pulses found and residual signal + *--------------------------------------------------------------------------------------*/ + freq_dnw_scaling_fx( st_fx->cor_strong_limit_fx, coder_type, st_fx->noise_lev_fx, st_fx->core_brate_fx, exc_diffQ, Qexc_diffQ ); + } + + /*--------------------------------------------------------------------------------------* + * Estimate noise level + *--------------------------------------------------------------------------------------*/ + + highband_exc_dct_in_fx( st_fx->core_brate_fx, mfreq_bindiv_loc, *last_bin, Diff_len, st_fx->noise_lev_fx, pit_band_idx, exc_diffQ, + &st_fx->seed_tcx_fx, Ener_per_bd_iQ, nb_subfr, exc_dct_in, st_fx->last_coder_type_fx, bitallocation_band, lsf_new, + st_fx->last_exc_dct_in_fx, &st_fx->last_ener_fx, st_fx->last_bitallocation_band_fx, bitallocation_exc, st_fx->bfi_fx, coder_type, + st_fx->bwidth_fx, exc_wo_nf, Qexc_diffQ, Q_exc, st_fx->GSC_noisy_speech_fx + ,st_fx->lt_ener_per_band_fx + ); + + exc_dct_in[0] = 0; + move16(); + + return; + +} diff --git a/lib_dec/hdecnrm_fx.c b/lib_dec/hdecnrm_fx.c new file mode 100644 index 0000000..4501f4b --- /dev/null +++ b/lib_dec/hdecnrm_fx.c @@ -0,0 +1,405 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" +#include "rom_dec_fx.h" +#include "stl.h" /* required for wmc_tool */ + +/*--------------------------------------------------------------------------*/ +/* Function hdecnrm_fx */ +/* ~~~~~~~~~~~~~~~~~~~~ */ +/* */ +/* Huffman decoding for indices of quantized norms */ +/*--------------------------------------------------------------------------*/ +void hdecnrm_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 numNorms, /* (i) number of norms */ + Word16 *index) /* (o) indices of quantized norms */ +{ + Word16 i, j, k, n, m; + Word16 temp; + Word16 *pidx; + + + pidx = index; + + m = sub(numNorms, 1); + FOR (i=0; i 0) + { + tmp_h = shr(hufftab[hufftab_idx],4); + tmp_l = sub(hufftab[hufftab_idx],shl(tmp_h,4)); + *rbits = add(*rbits,tmp_l); + hufftab_idx = L_add(hufftab_idx, L_add(L_deposit_l(tmp_h), get_next_indice_fx( st_fx, tmp_l ) )); + } + return negate(hufftab[hufftab_idx]); +} + + +/*--------------------------------------------------------------------------*/ +/* hdecnrm_context_fx() */ +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +/* */ +/* Huffman decoding for indices of quantized norms */ +/*--------------------------------------------------------------------------*/ +/* Word16 N (i) number of norms */ +/* Word16 *index (o) indices of quantized norms */ +/* Word16 *n_length (o) decoded stream length */ +/*--------------------------------------------------------------------------*/ + +void hdecnrm_context_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 N, + Word16 *index, + Word16 *n_length +) +{ + Word16 i, prevj, tmp; + + prevj = add(index[0], OFFSET_NORM); + FOR( i=1; i < N; i++) + { + IF( GT_16(prevj, HTH_NORM)) + { + /* above */ + tmp = decode_huff_context_fx( st_fx, hntable_fx, n_length); + index[i] = sub(31 , tmp); + move16(); + } + ELSE + { + IF( LT_16(prevj, LTH_NORM)) + { + /* less */ + index[i] = decode_huff_context_fx(st_fx, hntable_fx, n_length); + move16(); + } + ELSE + { + /* equal */ + index[i] = decode_huff_context_fx(st_fx, hetable_fx, n_length); + move16(); + } + } + prevj = index[i]; + move16(); + } + return; +} + +void hdecnrm_resize_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 N, /* (i) number of SFMs */ + Word16 *index /* (o) norm quantization index vector */ +) +{ + Word16 i, j, k, m; + Word16 temp; + Word16 *pidx; + + pidx = index; + + m = sub(N, 1); + move16(); + FOR (i=0; inext_bit_pos_fx = sub(st_fx->next_bit_pos_fx, j); + + return; +} + +/*-------------------------------------------------------------------------- + * hdecnrm_trans() + * + * Huffman decoding for indices of quantized norms + *--------------------------------------------------------------------------*/ + +void hdecnrm_tran_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 N, /* i : number of norms */ + Word16 *index /* o : indices of quantized norms */ +) +{ + Word16 i, j, k, n, m; + Word16 temp; + Word16 *pidx; + Word16 l; + + pidx = index; + move16(); + + m = sub(N, 1); + FOR (i=0; i 0.8 ==> - 14 dB (voiced) + * tilt 0.5 ==> - 6 dB (voiced or noise) + * tilt < 0.0 ==> 0 dB (noise) + *-----------------------------------------------------------------------------------*/ + +static void hf_synthesis_fx( + const Word32 core_brate, /* i : core bitrate */ + const Word16 output_subfr, /* i : output sub-frame length */ + const Word16 Aq[], /* i : quantized Az Q12 */ + const Word16 exc[], /* i : excitation at 12.8 kHz Q_exc */ + const Word16 Q_exc, /* i : excitation scaling */ + Word16 synth[], /* i : 12.8kHz synthesis signal Q_syn */ + Word16 synth16k[], /* i/o: 16kHz synthesis signal Q_syn */ + Word16 *seed2, /* i/o: random seed for HF noise gen */ + Word16 *mem_hp400, /* i/o: memory of hp 400 Hz filter */ + Word16 *mem_syn_hf, /* i/o: HF synthesis memory */ + Word16 *mem_hf, /* i/o: HF band-pass filter memory */ + const Word16 Q_syn, /* i : synthesis scaling */ + Word16 *delay_syn_hf, /* i/o: HF synthesis memory Q_syn */ + Word16 *memExp1, /* o : HF excitation scaling exponent */ + Word16 *mem_hp_interp, /* i/o: interpol. memory */ + const Word16 extl, /* i : flag indicating BWE */ + const Word16 CNG_mode /* i : CNG_mode */ +) +{ + Word16 i; + Word16 HF_syn[L_SUBFR16k], upsampled_HF_syn[L_FRAME48k/NB_SUBFR]; + Word16 HF_exc[L_SUBFR16k]; + Word16 temp_buffer[NS2SA(16000,DELAY_CLDFB_NS) - L_FILT16k]; + Word16 tmp, ener, exp1, exp2, scale, delay; + Word32 L_tmp; + Word16 Ap[M16k+1]; + (void)extl; + (void)CNG_mode; + + /*-----------------------------------------------------------------* + * generate white noise vector + *-----------------------------------------------------------------*/ + + Random_Fill(seed2, L_SUBFR16k, HF_exc, 3); /* 3 = Shift Right by 3 */ + /* o: HF_exc in Q-3 */ + + /*-----------------------------------------------------------------* + * calculate energy scaling factor so that white noise would have the + * same energy as exc12k8 + *-----------------------------------------------------------------*/ + + /*ener = sum2_f( exc, L_SUBFR ) + 0.01f*/ + ener = extract_h(Dot_product12(exc, exc, L_SUBFR, &exp2)); + exp2 = sub(exp2, add(Q_exc, Q_exc)); + + /*tmp = round_fx(Dot_product12(HF_exc, HF_exc, output_subfr, &exp1)); */ + L_tmp = Dot_product12(HF_exc, HF_exc, L_SUBFR16k, &exp1); + tmp = round_fx(L_tmp); + /* tmp = (float)(sqrt(ener/tmp)) */ + /* scale is -1 if tmp > ener */ + scale = shr(sub(ener, tmp), 15); + tmp = shl(tmp, scale); + exp1 = sub(exp1, scale); + + tmp = div_s(tmp, ener); + exp1 = sub(exp1, exp2); + + L_tmp = L_deposit_h(tmp); + + L_tmp = Isqrt_lc(L_tmp, &exp1); + scale = round_fx(L_tmp);/* Q18 when Q_exc=-1, HF_exc in Q-3 */ + + exp2 = sub(*memExp1, exp1); + move16(); + *memExp1 = exp1; + move16(); + + /*-----------------------------------------------------------------* + * calculate energy scaling factor to respect tilt of synth12k8 + * (tilt: 1=voiced, -1=unvoiced) + *-----------------------------------------------------------------*/ + + hp400_12k8_fx( synth, L_SUBFR, mem_hp400 ); + /* i: mem_hp400 in Q_syn */ + /* i: synth in Q_syn */ + /* o: synth in Q_syn-3 */ + + L_tmp = L_mac(1L, synth[0], synth[0]); + FOR (i = 1; i < L_SUBFR; i++) + { + L_tmp = L_mac(L_tmp, synth[i], synth[i]); + } + tmp = norm_l(L_tmp); + ener = extract_h(L_shl(L_tmp, tmp)); /* ener = r[0] */ + /*ener in Q = 2*(Q_syn-3)+1 = Q-5 when Q_syn=0*/ + + L_tmp = L_mac(1L, synth[1], synth[0]); + FOR (i = 2; i < L_SUBFR; i++) + { + L_tmp = L_mac(L_tmp, synth[i], synth[i - 1]); + } + tmp = extract_h(L_shl(L_tmp, tmp)); /* tmp = r[1] */ + /*tmp in Q = 2*(Q_syn-3)+1 = Q-5 when Q_syn=0 */ + /*we use the same normalization factor for both ener and tmp, */ + /*if the headroom in "tmp" is less than "ener", tmp can saturate */ + /*but this is ok since below we apply some thresholds to tmp */ + + tmp = s_max(0, tmp); + if (tmp > 0) + { + tmp = div_s(tmp, ener); + } + + /*-----------------------------------------------------------------* + * modify energy of white noise according to synthesis tilt + *-----------------------------------------------------------------*/ + + /* tmp = 1.0 - fac */ + tmp = add(1, sub(32767, tmp)); + + test(); + if( EQ_32(core_brate,FRAME_NO_DATA)||EQ_32(core_brate,SID_2k40)) + { + /* emphasize HF noise in CNG */ + /*fac *= 2.0f;*/ + tmp = add(tmp, tmp); + } + tmp = s_max(tmp, 3277); /* 0.1 in Q15 */ + + /*scale *= fac;*/ + tmp = mult_r(scale, tmp); + /*-----------------------------------------------------------------* + * modify HF excitation according to both calculated scaling factors + * high pass filtering (0.94ms of delay) + *-----------------------------------------------------------------*/ + + filt_6k_7k_scale_fx( HF_exc, L_SUBFR16k, mem_hf,tmp,exp2 ); + /* i: input HF_exc is scaled in float, here scaling is done inside this filter */ + /* i: mem_hf in Q-2 */ + /* o: HF_exc in Q0 */ + + /*-----------------------------------------------------------------* + * synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz + *-----------------------------------------------------------------*/ + + /*weight_a( Aq, Ap, 0.6f, M );*/ + weight_a_lc_fx(Aq, Ap, Gamma_19661_Tbl_fx, M); + /* o: Ap in Q14 */ + + Syn_filt_s( 0, Ap, M, HF_exc, HF_syn, L_SUBFR16k, mem_syn_hf, 1 ); + + /* i: Ap in Q14 */ + /* i: HF_exc in Q0 */ + /* o: HF_syn in Q0 */ + /* i/o: mem_syn_hf in Q0 */ + + Scale_sig(HF_syn, L_SUBFR16k, (add(Q_syn, exp1))); /* bring HF_syn to (Q_syn+exp1) */ + + /*-----------------------------------------------------------------* + * add filtered HF noise to speech synthesis + *-----------------------------------------------------------------*/ + + /* delay by 5 samples @16kHz to compensate CLDFB resampling delay (20samples) and HP filtering delay (roughly 15 samples) */ + delay = NS2SA(16000,DELAY_CLDFB_NS) - 15; + Copy( HF_syn+L_SUBFR16k-delay, temp_buffer, delay ); + Copy( HF_syn, HF_syn+delay, L_SUBFR16k-delay ); + Copy( delay_syn_hf, HF_syn, delay ); + Copy( temp_buffer, delay_syn_hf, delay ); + + /* interpolate the HF synthesis */ + IF( EQ_16(output_subfr,L_SUBFR48k)) /* 48kHz sampled output */ + { + { + Word16 s; + s = s_max(s_min(sub(s_min(Find_Max_Norm16(HF_syn, L_SUBFR16k), Find_Max_Norm16(mem_hp_interp, INTERP_3_1_MEM_LEN - 3)), 3), + sub(Find_Max_Norm16(mem_hp_interp + INTERP_3_1_MEM_LEN - 3, 3), 1)), 0 ); + Scale_sig(HF_syn, L_SUBFR16k, s); + Scale_sig(mem_hp_interp, INTERP_3_1_MEM_LEN, s); + interpolate_3_over_1_allpass_fx( HF_syn, L_SUBFR16k, upsampled_HF_syn, mem_hp_interp, allpass_poles_3_ov_2 ); + Scale_sig(upsampled_HF_syn, 3*L_SUBFR16k, -s); + Scale_sig(mem_hp_interp, INTERP_3_1_MEM_LEN, -s); + Scale_sig(HF_syn, L_SUBFR16k, -s); + } + Scale_sig( upsampled_HF_syn, L_SUBFR48k, -1 ); + } + ELSE IF( EQ_16(output_subfr,L_SUBFR32k)) /* 32kHz sampled output */ + { + { + Word16 s; + s = s_max(sub(s_min(Find_Max_Norm16(HF_syn, L_SUBFR16k), Find_Max_Norm16(mem_hp_interp, 2*ALLPASSSECTIONS_STEEP)),2), 0); + Scale_sig(HF_syn, L_SUBFR16k, s); + Scale_sig(mem_hp_interp, 2*ALLPASSSECTIONS_STEEP, s); + Interpolate_allpass_steep_fx( HF_syn, mem_hp_interp, L_SUBFR16k, upsampled_HF_syn ); + Scale_sig(upsampled_HF_syn, 2*L_SUBFR16k, -s); + Scale_sig(mem_hp_interp, 2*ALLPASSSECTIONS_STEEP, -s); + Scale_sig(HF_syn, L_SUBFR16k, -s); + } + } + ELSE /* 16kHz sampled output */ + { + Copy( HF_syn, upsampled_HF_syn, L_SUBFR16k ); + } + + Vr_add( synth16k, upsampled_HF_syn, synth16k, output_subfr ); + + return; +} + + +/*-------------------------------------------------------------------* + * filt_6k_7k: + * + * 15th order band pass 6kHz to 7kHz FIR filter. + * + * frequency: 4kHz 5kHz 5.5kHz 6kHz 6.5kHz 7kHz 7.5kHz 8kHz + * dB loss: -60dB -45dB -13dB -3dB 0dB -3dB -13dB -45dB + * (gain=4.0) + *-------------------------------------------------------------------*/ +static void filt_6k_7k_scale_fx( + Word16 signal[], /* i/o: signal */ + Word16 lg, /* i : length of input */ + Word16 mem[], /* i/o: memory (size=30) */ + Word16 fact, /* i : multiply factor */ + Word16 exp /* i : Mem Exponent */ +) +{ + Word16 i, x[L_FRAME48k/NB_SUBFR+(L_FIR-1)]; + Word32 L_tmp; + + Copy_Scale_sig(mem, x, L_FIR - 1, exp); + + FOR (i = 0; i < lg; i++) + { + x[i + L_FIR - 1] = shr(mult(signal[i], fact), 2); + move16(); /* gain of filter = 4 */ + } + FOR (i = 0; i < lg; i++) + { + + Word16 j; + L_tmp = 0; move32(); + for (j = 0; j<31; j++) + { + L_tmp = L_mac(L_tmp, x[i+j], fir_6k_7k_fx[j]); + } + + signal[i] = round_fx(L_tmp); + } + Copy(x + lg, mem, L_FIR - 1); +} + +/*-------------------------------------------------------------------* + * hf_synth_amr_wb_init() + * + * hf synthesis filters initialization + * - initialization of 1600 Hz low pass filter + * - initialization of band pass 6kHz to 8kHz FIR filter for noise and line resampled signals + *-------------------------------------------------------------------*/ + +void hf_synth_amr_wb_init_fx( + Word16 *prev_r, /* o : previous sub-frame gain */ + Word16 *fmerit_w_sm, /* o : 1 sample memory fmerit_w param */ + Word16 mem_syn_hf_fx[], /* HF LPC synthesis filter initialization */ + Word16 *frame_count, /* o : frame counter initialization */ + Word16 *ne_min, /* o : minimum Noise gate - short-term energy initialization*/ + Word16 *fmerit_m_sm, /* o : 1 sample memory fmerit_m param */ + Word16 *voice_fac, /* o : voice factor initialization */ + Word16 *unvoicing, /* o : unvoiced parameter */ + Word16 *unvoicing_sm, /* o : smoothed unvoiced parameter */ + Word16 *unvoicing_flag, /* o : unvoiced flag */ + Word16 *voicing_flag, /* o : voiced flag */ + Word16 *start_band_old, /* o : previous start point for copying frequency band */ + Word32 *OptCrit_old /* o : previous criterion value for deciding the start point */ +) +{ + *prev_r = 0; + move16(); + set16_fx( mem_syn_hf_fx, 0, M ); + *fmerit_w_sm = 0; + move16(); + *frame_count = 0; + move16(); + *ne_min = -7680; + move16(); /*Q8*/ + *fmerit_m_sm = 0; + move16(); + *voice_fac = 0; + move16(); + *unvoicing = 0; + move16(); + *unvoicing_sm = 32767; + move16(); /*Q15*/ + *unvoicing_flag = 0; + move16(); + *voicing_flag = 0; + move16(); + *start_band_old = 160; + move16(); + *OptCrit_old = 32768; + move32(); /*Q15*/ ; + return; +} + +/*-------------------------------------------------------------------* + * hf_synth_amr_wb_reset() + * + * reset of HF synthesis filters + * - needed in switching scenarios + *-------------------------------------------------------------------*/ + +void hf_synth_amr_wb_reset_fx( + Word16 *seed2, /* i/o: random seed for HF noise gen */ + Word16 mem_syn_hf[], /* o : HF synthesis memory */ + Word16 mem_hp_interp[], /* o : interpol. memory */ + Word16 *prev_r, /* o : previous sub-frame gain */ + Word16 *fmerit_w_sm, /* o : 1 sample memory fmerit_w param */ + Word16 delay_syn_hf[], /* o : HF synthesis memory */ + Word16 *frame_count, /* o : frame counter memory */ + Word16 *ne_min, /* o : minimum Noise gate - short-term energy memory */ + Word16 *fmerit_m_sm, /* o : 1 sample memory fmerit_m param */ + Word16 *voice_fac, /* o : voice factor memory */ + Word16 *unvoicing, /* o : unvoiced parameter */ + Word16 *unvoicing_sm, /* o : smoothed unvoiced parameter */ + Word16 *unvoicing_flag, /* o : unvoiced flag */ + Word16 *voicing_flag, /* o : voiced flag */ + Word16 *start_band_old, /* o : previous start point for copying frequency band */ + Word32 *OptCrit_old /* o : previous criterion value for deciding the start point */ +) +{ + Word16 i; + + + FOR( i=0; i30-exp */ + *pt3 = round_fx(L_shl(L_tmp, sub(exp,1))); /*13 */ + *pt4++ = *pt3++; + move16(); + + pt1 += L_SUBFR; + pt2 += L_SUBFR; + } + + output_subfr = shr(output_frame , 2); + + if( NE_16(*amr_io_class, 7)) + { + core_type = 0; + move16(); + } + + /* modify LF parameters for excitation weighting or sub-frame gains calculating */ + pitch_var_cur = 0; + move16(); + pt6 = pitch_buf; + pt7 = pitch_buf+1; + FOR( i = 0; i < 3; i++ ) + { + tmp1 = abs_s(sub(*pt6++, *pt7++)); /*Q5 */ + pitch_var_cur = add(pitch_var_cur, shr(tmp1,1)); /*Q6 -> Q5 */ + } + test(); + IF( GT_16(*frame_count, FRAME_COUNT)&&*amr_io_class==UNVOICED_CLAS) + { + *frame_count = 0; + move16(); + *ne_min = -7680; + move16();/*Q8; */ + } + ELSE + { + tmp1 = *frame_count; + move16(); + *frame_count = add(*frame_count ,1); + if(GT_16(tmp1, 2*FRAME_COUNT)) + { + *frame_count = 2*FRAME_COUNT; + move16(); + } + if ( LT_16(ng_ener_ST, *ne_min)) + { + *ne_min = ng_ener_ST; + move16();/*Q8; */ + } + } + + pt6 = voice_factors; + L_tmp = L_mult(*pt6++,4096); + FOR(i = 1; i < 4; i++) + { + L_tmp = L_mac(L_tmp, *pt6++,4096); + } + + voice_fac = round_fx(L_tmp); + + /*fmerit_w = fmerit > 5734 ? 5734 : (fmerit < 2458 ? 2458 : fmerit); //Q14 */ + + fmerit_w = s_min(fmerit,5734); + fmerit_w = s_max(fmerit_w,2458); + + if ( EQ_16(core_type, 1)) + { + fmerit_w = shr(fmerit_w, 1); /*Q14; */ + } + + L_tmp = L_mult(fmerit_w, add(16384, voice_fac)); + fmerit_w = extract_l(L_shr(L_tmp, 15)); /*Q14 */ + /**fmerit_w_sm = add(mult_r(*fmerit_w_sm, 29491), mult_r(fmerit_w, 3277)); //Q14 */ + *fmerit_w_sm = round_fx(L_mac(L_mult(*fmerit_w_sm, 29491), fmerit_w, 3277)); /*Q14 */ + fmerit_w = *fmerit_w_sm; + move16(); + + tmp1 = fmerit; + move16(); + if(LT_16(fmerit, 8192)) + { + tmp1 = 16384; + move16(); + } + fmerit_m = negate(add(-32768, tmp1)); + *fmerit_m_sm = add(shr(*fmerit_m_sm, 1), shr(fmerit_m, 1)); /*Q14 */ + fmerit_m = *fmerit_m_sm; + move16(); + + pt1 = til; + FOR( i = 0; i < NB_SUBFR; i++ ) + { + tmp = sub(pitch_var_cur, 320); + tmp = s_and(tmp, *pt1); + if (tmp < 0 ) + { + *pt1 = 1638; + move16(); + } + + tmp1 = sub(8192, *pt1); + *pt1 = s_max(6554, tmp1); + move16(); + tmp1 = add(*ne_min, 7680); /*Q8 */ + tmp1 = mult_r(tmp1, 7340); /*Q20 - > 0.007 //Q13 */ + *pt1 = add(*pt1, tmp1); + move16();/*Q13 */ + + L_tmp = L_mult0(*pt1, fmerit_m); /*Q13+14 */ + *pt1++ = extract_l(L_shr(L_tmp, 14)); /*Q13 */ + } + /* predict LPC coefficents and calculate sub-frame gains */ + p_Aq = Aq; + p_Ap = Ap; + pt1 = sub_gain; + pt2 = til0; + pt3 = til; + pt6 = voice_factors; + FOR( i = 0; i < NB_SUBFR; i++ ) + { + envelope_fx( core_brate, p_Aq, p_Ap, pt1, *pt2, *pt3, *pt6, prev_r, + voice_facor_sm, unvoicing, unvoicing_sm, unvoicing_flag ); + pt1++; + pt2++; + pt3++; + pt6++; + + p_Aq += (M+1); + p_Ap += (M+1); + } + + AdaptiveStartBand_fx( &start_band, core_brate, lsf_new, voice_fac, *amr_io_class, voicing_flag, start_band_old, OptCrit_old ); + + + q_tmp = Exp16Array(L_FRAME, exc); + qdct = sub(q_tmp, 1); + Copy_Scale_sig_16_32(exc, exc32, L_FRAME, qdct); + + qdct = add(qdct, Q_exc); + edct_fx(exc32, dct_exc32, L_FRAME, &qdct); + q_tmp = Exp32Array(L_FRAME, dct_exc32); + + q_tmp = sub(q_tmp,16); + Copy_Scale_sig_32_16(dct_exc32, dct_exc, L_FRAME, q_tmp); + qdct = add(qdct, q_tmp); + + set16_fx( dct_hb, 0, L_FRAME16k); + pt1 = &dct_hb[200]; + pt2 = &dct_exc[200]; + FOR ( i = 200; i < 240; i++) + { + *pt1++ = *pt2++; + move16();/*qdct */ + } + set16_fx(signum, 1, L_SUBFR16k); + pt1 = dct_hb+240; + pt2 = dct_exc+start_band; + pt3 = signum; + FOR ( i = 240; i < L_FRAME16k; i++ ) + { + if (*pt2<0) + { + *pt3 = -1; + move16(); + } + *pt1++ = abs_s(*pt2++); + move16(); /*qdct */ + pt3++; + } + hb_ener = dot_prod_satcontr(&dct_hb[240], &dct_hb[240], qdct, qdct, &q1, L_SUBFR16k); + + L_tmp = L_shl(L_mult(start_band, 205), 14); /*Q30 */ + tmp = round_fx(L_tmp); /*Q14 */ + tmp = sub(18022, tmp); /*Q14 */ + fmerit_w = round_fx(L_shl(L_mult(fmerit_w, tmp), 1)); /*Q: 14+14+1+1-16 = 14 */ + + + L_tmp = L_deposit_l(fmerit_w); /*Q14 */ + L_tmp = Isqrt(L_tmp); /*Q(31-7) */ + tmp = round_fx(L_tmp); /*Q8 */ + q2 = norm_s(tmp); + alpha = div_s(shl(1, sub(14, q2)), tmp); /*Q(29-q2-8); */ + alpha = shl(alpha, sub(q2, 7));/*Q14 */ + + beta = sub(16384, fmerit_w); /*Q14 */ + + L_tmp = L_mult(alpha, 31130); /*Q30 */ + gamma = round_fx(L_tmp); /*Q14 */ + gamma = sub(17203, gamma); /*Q14 */ + gamma = s_min(16384, gamma); + gamma = s_max(4915, gamma); + + IF ( LT_16(beta, 16384)) + { + L_tmp = 1; /*variable for tonal energy*/ + + pt1 = hb_amb; + pt2 = hb_tonal; + pt3 = &dct_hb[240]; + FOR (i=0; i<8; i++) + { + fn = add(i,8); + tmp1 = div_s(1, fn); /*Q15 */ + tmp = 0; + move16(); + pt4 = &dct_hb[240]; + FOR (j=0; j 0 ) + { + L_tmp = L_mac0(L_tmp, shr(*pt2,1), shr(*pt2,1)); + } + pt1++; + pt2++; + pt3++; + } + FOR (; i < L_SUBFR16k-8; i++) + { + fb = sub(i,7); + fn = add(fb,15); + tmp = 0; + pt4 = &dct_hb[fb+240]; + FOR (j=fb; j 0 ) + { + L_tmp = L_mac0(L_tmp, shr(*pt2,1), shr(*pt2,1)); + } + pt1++; + pt2++; + pt3++; + } + FOR (; i 0 ) + { + L_tmp = L_mac0(L_tmp, shr(*pt2,1), shr(*pt2,1)); /*2*qdct-2 */ + } + pt1++; + pt2++; + pt3++; + } + + /*scaling of hb_ener is q1; tonal_ener0) + { + *pt1 = mult_r(*pt1,g); /*qdct */ move16(); + } + *pt2 = round_fx(L_shl(L_mult(*pt2,inv_g),3)); /*qdct */ + *pt3 = add(*pt1, *pt2); + move16(); + *pt3 = extract_l(L_mult0(*pt3, *pt4)); /*qdct */ + pt1++; + pt2++; + pt3++; + pt4++; + } + + ener = dot_prod_satcontr(&dct_hb[240], &dct_hb[240], qdct, qdct, &q2, L_SUBFR16k); + scale = div_s(shl(1, 14), hb_ener); /*Q(29-q1) */ + L_tmp = L_mult(ener, scale); /*30-q1+q2 */ + q2 = sub(q1, q2); /*30-q2 */ + scale = round_fx(Isqrt(L_shl(L_tmp, sub(q2, 24)))); /*Q12 */ + scale = round_fx(L_shl(L_mult(scale, gamma),4)); /*Q15 */ + } + ELSE + { + scale = 32767; /*~1 in Q15 */ move16(); + } + + IF ( EQ_32(core_brate, ACELP_6k60)) + { + filt_weight_coeff = 60; + move16(); + rev_filt_weight_coeff = 555; + move16(); /* 1/(filt_weight_coeff-1) Q15 */ + } + ELSE IF ( EQ_32(core_brate, ACELP_8k85)) + { + filt_weight_coeff = 40; + move16(); + rev_filt_weight_coeff = 840; + move16(); + } + ELSE + { + filt_weight_coeff = 20; + move16(); + rev_filt_weight_coeff = 1725; + move16(); + } + + pt1 = filt_weight; + FOR ( i = 0; i < filt_weight_coeff; i++) + { + L_tmp = L_mult(-32735, rev_filt_weight_coeff); /*Q31 */ + L_tmp = L_shl(Mult_32_16(L_tmp, i), 14); /*Q16+14 */ + *pt1++ = add(round_fx(L_tmp), 16384); + move16();/*Q14 */ + } + + IF ( EQ_32(core_brate, ACELP_23k85)) + { + pt1 = dct_hb+240; + tmp = sub(filt_weight_coeff, 80); + pt3 = filt_weight+tmp; + FOR( i = 240; i < L_FRAME16k; i++ ) + { + *pt1 = mult_r(*pt1, scale); /*qdct */ move16(); + + IF ( GE_16(i, sub(320, filt_weight_coeff))) + { + *pt1 = round_fx(L_shl(L_mult(*pt3, *pt1), 1)); /*qdct */ + } + pt1++; + pt3++; + } + pt1 = dct_hb+200; + pt6 = filt_hp_fx; + FOR( i = 200; i < 256; i++ ) + { + *pt1 = mult_r(*pt6++, *pt1); + move16(); /*qdct */ + pt1++; + } + pt1 = HF_corr_gain; + pt6 = hf_gain; + FOR ( i = 0; i < NB_SUBFR; i++) + { + tmp = *pt6++; + move16(); + *pt1++ = HP_gain_fx[tmp]; + move16(); + } + } + ELSE + { + pt1 = dct_hb+240; + tmp = sub(filt_weight_coeff, 80); + pt3 = filt_weight+tmp; + FOR( i = 240; i < L_FRAME16k; i++ ) + { + *pt1 = mult_r(*pt1, scale); /*qdct */ + IF ( GT_16(i, 255)) + { + *pt1 = mult_r(19505, *pt1); + move16(); + } + + IF ( GE_16(i, sub(320, filt_weight_coeff))) + { + *pt1 = round_fx(L_shl(L_mult(*pt3, *pt1), 1)); /*qdct */ + } + pt1++; + pt3++; + } + + pt1 = dct_hb+200; + pt6 = filt_hp_fx; + pt7 = deem_tab_fx; + FOR( i = 200; i < 256; i++ ) + { + *pt1 = mult_r(*pt6++, *pt1); + move16();/*qdct */ + *pt1 = mult_r(*pt7++, *pt1); + move16(); + pt1++; + } + } + + q_tmp = Exp16Array(L_FRAME16k, dct_hb); + qhf = sub(q_tmp, 1); + Copy_Scale_sig_16_32(dct_hb, dct_hb32, L_FRAME16k, qhf); + qhf = add(qhf, qdct); + edct_fx(dct_hb32, exc16k32, L_FRAME16k, &qhf); + q_tmp = Exp32Array(L_FRAME16k, exc16k32); + q_tmp = sub(q_tmp,16); + Copy_Scale_sig_32_16(exc16k32, exc16k, L_FRAME16k, q_tmp); + qhf = add(qhf, q_tmp); + + ener = dot_prod_satcontr(exc, exc, Q_exc, Q_exc, &q1, L_FRAME); + tmp = dot_prod_satcontr(exc16k, exc16k, qhf, qhf, &q2, L_FRAME16k); + + pt6 = exc; + pt2 = exc16k; + + FOR ( i = 0; i < NB_SUBFR; i++ ) + { + e_subfr1 = dot_prod_satcontr(pt6, pt6, Q_exc, Q_exc, &q3, L_SUBFR); + e_subfr2 = dot_prod_satcontr(pt2, pt2, qhf, qhf, &q4, L_SUBFR16k); + + L_tmp = L_mult(e_subfr1, tmp); /*Q(q2+q3+1) */ + q3 = add(add(q2, q3), 1); + shift = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, shift); /*Q(q3+shift); */ + q3 = add(q3, shift); + scale = round_fx(L_tmp); /*Q(q3-16); */ + q3 = sub(q3, 16); + scale = div_s(shl(1, 14), scale); /*Q(29-q3) */ + L_tmp = L_mult(scale, ener); /*Q(29-q3+q1+1) */ + shift = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, shift); /*Q(29-q3+q1+1+shift) */ + scale = round_fx(L_tmp); /*Q(29-q3+q1+1+shift-16) */ + L_tmp = L_mult(scale, e_subfr2); /*Q(29-q3+q1+1+shift-16+q4+1)=Q(15+q1-q3+q4+shift) */ + q3 = sub(15, q3); + q3 = add(q3, q1); + q3 = add(q3, shift); + q3 = add(q3, q4); + scale = round_fx(Isqrt(L_shl(L_tmp, sub(6, q3)))); /*Q12 */ + + pt6 += L_SUBFR; + FOR ( j = 0; j < L_SUBFR16k; j++ ) + { + *pt2 = round_fx(L_shl(L_mult(*pt2, scale), 2)); /*qhf-1 */ + pt2++; + } + } + qhf = sub(qhf, 1); + + p_Ap = Ap; + pt1 = exc16k; + pt2 = synth_out; + pt3 = sub_gain; + pt4 = HF_corr_gain; + pt5 = til0; + pt6 = voice_factors; + pt7 = exc; + + FOR( i = 0; i < NB_SUBFR; i++ ) + { + hf_synthesis_amr_wb_fx( core_brate, output_subfr, p_Ap, pt1, pt2, + mem_syn_hf, delay_syn_hf, mem_hp_interp, *pt3, *pt4, *pt5, *pt6, pt7, + Q_exc, Q_out, qhf); + p_Ap += (M+1); + pt1 += L_SUBFR16k; + pt2 += output_subfr; + pt3++; + pt4++; + pt5++; + pt6++; + pt7 += L_SUBFR; + } + + return; +} +static void hf_synthesis_amr_wb_fx( + const Word32 core_brate, /* i : core bitrate : Q0 */ + const Word16 output_subfr, /* i : output sub-frame length : Q0 */ + const Word16 Ap[], /* i : quantized Aq : Q12 */ + Word16 exc16k[], /* i : excitation at 16 kHz : Qhf */ + Word16 synth_out[], /* i/o: synthesis signal at output Fs : Qo */ + Word16 *mem_syn_hf, /* i/o: HF synthesis memory : Qo */ + Word16 *delay_syn_hf, /* i/o: HF synthesis memory : Qo */ + Word16 *mem_hp_interp, /* i/o: interpol. memory : Qo */ + Word16 p_r, /* i : sub-frame gain : Q12 */ + Word16 HF_corr_gain, /* i : HF gain index : Q14 */ + Word16 til, /*Q14*/ + Word16 voice_factors, /*Q14*/ + const Word16 exc[], /* i : excitation at 12.8 kHz : Qi */ + const Word16 Q_exc, /*exc scaling*/ + const Word16 Q_out, /*synth_out scaling*/ + Word16 qhf /*exc16k scaling*/ +) +{ + Word16 i, delay; + Word16 HF_syn[L_SUBFR16k], upsampled_HF_syn[L_SUBFR48k]; + Word16 temp_buffer[NS2SA(16000,DELAY_CLDFB_NS)]; + Word16 ener, tmp, scale, exc2385[L_SUBFR16k]; + Word32 L_tmp; + Word16 q1, q2,q3, shift; + Word16 *pt1, *pt2, flag; + IF ( EQ_32(core_brate, ACELP_23k85)) + { + ener = dot_prod_satcontr(exc, exc, Q_exc, Q_exc, &q1, L_SUBFR); + tmp = dot_prod_satcontr(exc16k, exc16k, qhf, qhf, &q2, L_SUBFR16k); + + L_tmp = L_mult(ener, 6554); /*Q(q1+16) */ + q3 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, q3); /*Q(q1+q3+16) */ + ener = extract_h(L_tmp); /*Q(q1+q3); */ + q1 = add(q1, q3); + + scale = div_s(shl(1, 14), ener); /*Q(29-q1) */ + L_tmp = L_mult(tmp, scale); /*30-q1+q2 */ + q2 = sub(q1, q2); /*30-q2 */ + scale = round_fx(Isqrt(L_shl(L_tmp, sub(q2, 24)))); /*Q12 */ + + pt1 = exc16k; + pt2 = exc2385; + FOR ( i = 0; i < L_SUBFR16k; i++ ) + { + L_tmp = L_mult(*pt1++, HF_corr_gain); /*qhf+15*/ + L_tmp = Mult_32_16(L_tmp, scale); /*qhf-1+12+1*/ + *pt2++ = round_fx(L_shl(L_tmp, 1)); /*qhf-3*/ + } + + pt1 = exc16k; + FOR ( i = 0; i < L_SUBFR16k; i++ ) + { + *pt1 = mult_r(*pt1, p_r); /*qhf-3*/ move16(); + pt1++; + } + + qhf = sub(qhf, 3); + + ener = dot_prod_satcontr(exc16k, exc16k, qhf, qhf, &q1, L_SUBFR16k); + tmp = dot_prod_satcontr(exc2385, exc2385, qhf, qhf, &q2, L_SUBFR16k); + L_tmp = L_mult(ener, 9830); /*Q(q1+16) */ + q3 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, q3); /*Q(q1+q3+16) */ + ener = extract_h(L_tmp); /*Q(q1+q3); */ + q1 = add(q1, q3); + + scale = div_s(shl(1, 14), ener); /*Q(29-q1) */ + L_tmp = L_mult(tmp, scale); /*30-q1+q2 */ + q2 = sub(q1, q2); /*30-q2 */ + scale = round_fx(Isqrt(L_shl(L_tmp, sub(q2, 24)))); /*Q12 */ + + flag = negate(s_and(til,-0x8000)); + if (GT_16(scale, 4096)) + { + flag = 1; + move16(); + } + IF ( flag ) + { + Copy( exc2385, exc16k, L_SUBFR16k ); + } + ELSE + { + pt1 = exc16k; + pt2 = exc2385; + FOR ( i = 0; i < L_SUBFR16k; i++ ) + { + tmp = sub(16348, shl(til, 1));/*Q14 */ + L_tmp = L_mult(tmp, sub(26214, shr(voice_factors, 1))); /*Q29*/ + tmp = round_fx(L_shr(L_tmp, 1)); /*Q12*/ + tmp = s_min(tmp, 4096); + tmp = s_max(tmp, scale); + *pt1++ = round_fx(L_shl(L_mult(*pt2++, tmp), 3))/*qhf*/; + } + } + + } + ELSE + { + pt1 = exc16k; + FOR ( i = 0; i < L_SUBFR16k; i++ ) + { + *pt1 = mult_r(*pt1, p_r); /*qhf-3*/ move16(); + pt1++; + } + + qhf = sub(qhf, 3); + } + + shift = sub(qhf, Q_out); + Syn_filt_s( shift, Ap, M, exc16k, HF_syn, L_SUBFR16k, mem_syn_hf, 1 ); /*Q_out=qhf-shift */ + + /*-----------------------------------------------------------------* + * Resample to output sampling rate + * Synchronize LB and HB components (delay componsation) + * Add synthesised high band to speech synthesis + *-----------------------------------------------------------------*/ + + /* compensate CLDFB resampling delay */ + delay = NS2SA(16000,DELAY_CLDFB_NS); + Copy( HF_syn+L_SUBFR16k-delay, temp_buffer, delay ); + Copy( HF_syn, HF_syn+delay, L_SUBFR16k-delay ); + Copy( delay_syn_hf, HF_syn, delay ); + Copy( temp_buffer, delay_syn_hf, delay ); + + IF( EQ_16(output_subfr, L_SUBFR48k)) /* 48kHz sampled output */ + { + Word16 s; + s = s_max(s_min(sub(s_min(Find_Max_Norm16(HF_syn, L_SUBFR16k), Find_Max_Norm16(mem_hp_interp, INTERP_3_1_MEM_LEN - 3)), 3), + sub(Find_Max_Norm16(mem_hp_interp + INTERP_3_1_MEM_LEN - 3, 3), 1)), 0 ); + Scale_sig( HF_syn, L_SUBFR16k, s ); + Scale_sig( mem_hp_interp, INTERP_3_1_MEM_LEN, s ); + + interpolate_3_over_1_allpass_fx( HF_syn, L_SUBFR16k, upsampled_HF_syn, mem_hp_interp, allpass_poles_3_ov_2 ); + + Scale_sig( upsampled_HF_syn, L_SUBFR48k, add(-s,-1) ); + Scale_sig( mem_hp_interp, INTERP_3_1_MEM_LEN, -s ); + Scale_sig( HF_syn, L_SUBFR16k, -s ); + } + ELSE IF( EQ_16(output_subfr, L_SUBFR32k)) /* 32kHz sampled output */ + { + Word16 s; + s = s_max( sub(s_min(Find_Max_Norm16(HF_syn, L_SUBFR16k), Find_Max_Norm16(mem_hp_interp, 2*ALLPASSSECTIONS_STEEP)),2), 0 ); + Scale_sig( HF_syn, L_SUBFR16k, s ); + Scale_sig( mem_hp_interp, 2*ALLPASSSECTIONS_STEEP, s ); + + Interpolate_allpass_steep_fx( HF_syn, mem_hp_interp, L_SUBFR16k, upsampled_HF_syn ); + + Scale_sig( upsampled_HF_syn, 2*L_SUBFR16k, -s ); + Scale_sig( mem_hp_interp, 2*ALLPASSSECTIONS_STEEP, -s ); + Scale_sig( HF_syn, L_SUBFR16k, -s ); + } + ELSE /* 16kHz sampled output */ + { + Copy( HF_syn, upsampled_HF_syn, L_SUBFR16k ); + } + + Vr_add( synth_out, upsampled_HF_syn, synth_out, output_subfr); + + return; +} + +static Word16 EnhanceClass_fx( + const Word16 qq_fx, + const Word16 pp_fx, + const Word16 tilt0_fx, /* i : spectrum tilt */ + const Word16 tilt_fx, /* i : spectrum tilt */ + const Word16 voice_factor_fx, /* i : voice factor */ + Word16 *voice_fac_fx, /* i/o: smoothed voiced parameter */ + Word16 *unvoicing_fx, /* i/o: unvoiced parameter */ + Word16 *unvoicing_sm_fx, /* i/o: smoothed unvoiced parameter */ + Word16 *unvoicing_flag /* i/o: unvoiced flag */ +) +{ + Word16 unvoicing_tmp_fx; + Word16 tmp, tmp1; + Word32 L_tmp; + + /* Decide (*unvoicing_flag) to allow BWE enhancement when qq>pp */ + /**voice_fac_fx = add(mult_r(*voice_fac_fx, 24576), mult_r(voice_factor_fx, 8192)); //Q15 */ + *voice_fac_fx = round_fx(L_mac(L_mult(*voice_fac_fx, 24576), voice_factor_fx, 8192)); /*Q15 */ + + tmp = mult_r(sub(8192, tilt0_fx), 16384); /*Q13 */ + + L_tmp = L_sub(32768, *voice_fac_fx); /*Q15 */ + + L_tmp = Mult_32_16(L_tmp, tmp); /*Q13 */ + tmp = extract_l(L_tmp); /*Q13 */ + + tmp1 = mult_r(tilt_fx, 21845); /*Q15->1/1.5 ->Q13+15-15->Q13 */ + tmp1 = s_min(tmp1, 8192); + + L_tmp = L_mult(tmp, tmp1); /*Q13+Q13+1 */ + unvoicing_tmp_fx = extract_l(L_shr(L_tmp, 12)); /*Q15 */ + + /**unvoicing_fx = add(mult_r(16384, *unvoicing_fx), mult_r(16384, unvoicing_tmp_fx)); //Q15 */ + *unvoicing_fx = round_fx(L_mac(L_mult(16384, *unvoicing_fx), 16384, unvoicing_tmp_fx)); /*Q15 */ + + IF( GT_16(*unvoicing_sm_fx, *unvoicing_fx)) + { + /**unvoicing_sm_fx = add(mult_r(29491, *unvoicing_sm_fx), mult_r(3277, *unvoicing_fx)); //Q15 */ + *unvoicing_sm_fx = round_fx(L_mac(L_mult(29491, *unvoicing_sm_fx), 3277, *unvoicing_fx)); /*Q15 */ + } + ELSE + { + /**unvoicing_sm_fx = add(mult_r(32440, *unvoicing_sm_fx), mult_r(328, *unvoicing_fx)); //Q15 */ + *unvoicing_sm_fx = round_fx(L_mac(L_mult(32440, *unvoicing_sm_fx), 328, *unvoicing_fx)); /*Q15 */ + } + + if ( GT_16(sub(*unvoicing_fx, *unvoicing_sm_fx),3277)) + { + *unvoicing_flag = 1; + } + + if ( LT_16(sub(*unvoicing_fx, *unvoicing_sm_fx),1638)) + { + *unvoicing_flag = 0; + } + test(); + return ( *unvoicing_flag && GT_16(qq_fx, pp_fx) ); +} + +static void envelope_fx( + const Word32 core_brate, /* i : core bitrate */ + const Word16 Aq_dyn_scal[], /* i : de-quant. LPC coefficents, dynamic scaling */ + Word16 Ap[], /* o : extended LPC coefficents, Q12 */ + Word16 *sub_gain, /* o : sub-frame gain, Q12 */ + Word16 tilt0, /* i : spectrum tilt, Q14 */ + Word16 tilt, /* i : spectrum tilt, Q13 */ + Word16 voice_factor, /* i : voice factor, Q15 */ + Word16 *prev_r, /* i/o: previous sub-frame gain, Q10 */ + Word16 *voice_fac, /* i/o: smoothed voiced parameter, Q15 */ + Word16 *unvoicing, /* i/o: unvoiced parameter, Q15 */ + Word16 *unvoicing_sm, /* i/o: smoothed unvoiced parameter, Q15*/ + Word16 *unvoicing_flag /* i/o: unvoiced flag */ +) +{ + + Word16 px, py, rx, ry, pp, rr, qx, qy, qq; /*Q10*/ + Word16 i, Unvoicing_flag; + Word16 alpha; /*Q14*/ + Word16 est_level1, est_level2; /*Q10*/ + Word32 L_tmp; + Word16 tmp, q1, q2, q3, shift; + Word16 As[3], k1, k2; + Word16 *pt1; + const Word16 *pt2, *pt3; + Word16 Aq[M+1]; + + + /* Aq has dynamic scaling + go back to Q12 to make sure there's no overflow while calculating qx,qy*/ + shift = sub(norm_s(Aq_dyn_scal[0]),2); + Copy_Scale_sig(Aq_dyn_scal, Aq, M+1, shift); + + /* LPC envelope weighting */ + IF( EQ_32(core_brate,ACELP_6k60)) + { + weight_a_lc_fx( Aq, Ap, Gamma_29491_Tbl, M ); + } + ELSE + { + weight_a_lc_fx( Aq, Ap, Gamma_19661_Tbl_fx, M ); + } + /* Ap has dynamic scaling + go back to Q12 to make sure there's no overflow while calculating px,py*/ + shift = sub(norm_s(Ap[0]),2); + IF(shift != 0) + { + Scale_sig(Ap, M+1, shift); + } + + /* LPC envelope level estimate */ + L_tmp = L_deposit_l(0); + pt1 = Ap; + pt2 = exp_tab_p_fx; + FOR ( i = 0; i <= M; i++ ) + { + L_tmp = L_mac(L_tmp, *pt1++, *pt2++); + } + q1 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, q1);/*Q(27+q1)*/ + px = round_fx(L_shr(L_tmp, 1)); /*Q(10+q1)*/ + + L_tmp = L_deposit_l(0); + + pt1 = Ap; + pt2 = exp_tab_p_fx+33; + FOR ( i = 0; i <= M; i++ ) + { + L_tmp = L_mac(L_tmp, *pt1++, *pt2--); + } + q2 = norm_l(L_tmp); + shift = sub(q1, q2); + IF ( shift >= 0 ) + { + px = shr(px, shift); + L_tmp = L_shl(L_tmp, q2);/*Q(27+q2)*/ + q1 = q2; + move16(); + } + ELSE + { + L_tmp = L_shl(L_tmp, q1);/*Q(27+q1)*/ + } + py = round_fx(L_shr(L_tmp, 1)); /*Q(10+q1)*/ + + L_tmp = L_deposit_l(0); + pt2 = Aq; + pt3 = exp_tab_q_fx; + FOR ( i = 0; i <= M; i++ ) + { + L_tmp = L_mac(L_tmp, *pt2++, *pt3++); + } + q2 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, q2);/*Q(27+q2)*/ + rx = round_fx(L_shr(L_tmp, 1)); /*Q(10+q2)*/ + + L_tmp = L_deposit_l(0); + pt2 = Aq; + pt3 = exp_tab_q_fx+33; + FOR ( i = 0; i <= M; i++ ) + { + L_tmp = L_mac(L_tmp, *pt2++, *pt3--); + } + q3 = norm_l(L_tmp); + shift = sub(q2, q3); + IF ( shift >= 0 ) + { + rx = shr(rx, shift); + L_tmp = L_shl(L_tmp, q3);/*Q(27+q3)*/ + q2 = q3; + move16(); + } + ELSE + { + L_tmp = L_shl(L_tmp, q2);/*Q(27+q2)*/ + } + ry = round_fx(L_shr(L_tmp, 1)); /*Q(10+q2)*/ + + L_tmp = L_mult(px, px); + L_tmp = L_mac(L_tmp, py, py); /*Q(21+2*q1)*/ + pp = round_fx(Isqrt(L_shr(L_tmp, add(11, shl(q1, 1))))); /*Q10*/ + + L_tmp = L_mult(rx, rx); + L_tmp = L_mac(L_tmp, ry, ry); /*Q(21+2*q1)*/ + rr = round_fx(Isqrt(L_shr(L_tmp, add(11, shl(q2, 1))))); /*Q10*/ + + Copy(Aq, As, 3); + IF ( EQ_16(shr(As[2],1),-2048) ) + { + k2 = -2458; + move16(); + k1 = 4055; + move16(); + if (As[1]<0) + { + k1 = -k1; + move16(); + } + } + ELSE + { + k1 = add(2048, shr(As[2],1)); /*Q11 */ + q1 = 11; + move16(); + q2 = norm_s(k1); + k1 = (shl(k1, q2)); /*q1+q2 */ + tmp = abs_s(k1); + q1 = add(q1, q2); + tmp = div_s(shl(1, 14), tmp); /*Q(29-q1) */ + if ( k1 < 0 ) + { + tmp = negate(tmp); + move16(); + } + + L_tmp = L_mult(As[1], tmp); /*Q(42-q1) */ + q1 = sub(q1, 14); + k1 = round_fx(L_shl(L_tmp, q1)); /*Q12 */ + k2 = As[2]; + move16(); /*Q12 */ + if ( GT_16(k2, 2458)) + { + k2 = 2458; + move16(); + } + if ( LT_16(k2, -2458) ) + { + k2 = -2458; + move16(); + } + if ( GT_16(k1, 4055)) + { + k1 = 4055; + move16(); + } + if ( LT_16(k1, -4055) ) + { + k1 = -4055; + move16(); + } + } + As[1] = add(4096, k2); + move16(); + L_tmp = L_mult(As[1], k1); /*Q25 */ + As[1] = round_fx(L_shl(L_tmp, 3)); /*Q12 */ + As[2] = k2; + move16(); /*Q12 */ + + L_tmp = L_deposit_l(0); + pt1 = As; + pt2 = exp_tab_q_fx; + FOR ( i = 0; i < 3; i++ ) + { + L_tmp = L_mac(L_tmp, *pt1++, *pt2++); + } + q1 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, q1);/*Q(27+q1)*/ + qx = round_fx(L_shr(L_tmp, 1)); /*Q(10+q1)*/ + + + L_tmp = L_deposit_l(0); + pt1 = As; + pt2 = exp_tab_q_fx+33; + FOR ( i = 0; i < 3; i++ ) + { + L_tmp = L_mac(L_tmp, *pt1++, *pt2--); + } + q2 = norm_l(L_tmp); + shift = sub(q1, q2); + IF ( shift >= 0 ) + { + qx = shr(qx, shift); + L_tmp = L_shl(L_tmp, q2);/*Q(27+q2)*/ + q1 = q2; + move16(); + } + ELSE + { + L_tmp = L_shl(L_tmp, q1);/*Q(27+q1)*/ + } + qy = round_fx(L_shr(L_tmp, 1)); /*Q(10+q1)*/ + + + L_tmp = L_mult(qx, qx); + L_tmp = L_mac(L_tmp, qy, qy); + qq = round_fx(Isqrt(L_shr(L_tmp, add(11, shl(q1, 1))))); /*Q10*/ + + Unvoicing_flag = EnhanceClass_fx( rr, pp, tilt0, tilt, voice_factor, voice_fac, unvoicing, unvoicing_sm, unvoicing_flag ); + + alpha = 0; + move16(); + IF ( Unvoicing_flag ) + { + IF ( GT_16(rr, (*prev_r))) + { + rr = shr(add(rr, (*prev_r)), 1); + } + + *prev_r = rr; + move16(); + + L_tmp = L_mult(tilt, sub(26214, shr(voice_factor, 1))); /*Q28*/ + + L_tmp = L_min(L_tmp, 268435456); + + L_tmp = Mult_32_16(L_tmp, rr); /*Q23*/ + rr = round_fx(L_shl(L_tmp, 3)); /*Q10*/ + L_tmp = L_mult(tilt, sub(26214, shr(voice_factor, 1))); /*Q28*/ + L_tmp = L_max(L_tmp, 268435456); + L_tmp = Mult_32_16(L_tmp, qq); /*Q23*/ + qq = round_fx(L_shl(L_tmp, 3)); /*Q10*/ + rr = s_min(rr, qq); + rr= s_max(rr, pp); + } + ELSE + { + test(); + IF ( LT_16(rr, 1024)&<_16((*prev_r),1024)) + { + L_tmp = L_mult(rr, rr); /*Q21*/ + tmp = round_fx(L_shl(L_tmp, 9)); /*Q14*/ + L_tmp = L_sub(2097152, L_tmp); /*Q21*/ + alpha = round_fx(L_shl(L_tmp, 9)); /*Q14*/ + L_tmp = L_mult(alpha, (*prev_r)); /*Q25*/ + L_tmp = L_mac(L_tmp, tmp, rr); /*Q25*/ + rr = round_fx(L_shl(L_tmp, 1)); /*Q10*/ + } + + *prev_r = rr; + move16(); + + L_tmp = L_mult(tilt, sub(26214, shr(voice_factor, 1))); /*Q28*/ + + L_tmp = L_min(L_tmp, 268435456); + L_tmp = Mult_32_16(L_tmp, qq); /*Q23*/ + est_level1 = round_fx(L_shl(L_tmp, 3)); /*Q10*/ + + tmp = pp; + move16(); + tmp = s_min(tmp, qq); + rr = s_min(tmp, rr); + + L_tmp = L_mult(abs_s(sub(tilt, 8192)), sub(26214, shr(voice_factor, 1))); /*Q28*/ + L_tmp = L_add(L_tmp, 268435456); + L_tmp = Mult_32_16(L_tmp, rr); /*Q23*/ + est_level2 = round_fx(L_shl(L_tmp, 3)); /*Q10*/ + + rr = s_min(est_level1, est_level2); + } + + + q1 = norm_s(pp); + tmp = div_s(shl(1, sub(14, q1)), pp); /*Q(29-q1-10) */ + L_tmp = L_mult(rr, tmp);/*Q(30-q1-10+10) */ + + *sub_gain = s_min(20480,round_fx(L_shl(L_tmp, sub(q1, 2)))); /*Q12 */ + + return; + +} + +/*---------------------------------------------------------------------* + * AdaptiveStartBand_fx() + * + * adaptively select the start band of bandwidth extension + *---------------------------------------------------------------------*/ + +void AdaptiveStartBand_fx( + Word16 *start_band, /* o : start point of copied band */ + const Word32 rate, /* i : core bitrate */ + const Word16 *lsf_fx, /* i : Q2 lsf frequency */ + const Word16 voicing_fac_fx, /* i : Q14 voicing factors */ + const Word16 clas, /* i : signal class (determined by FEC algorithm)*/ + Word16 *voicing_flag, + Word16 *start_band_old, + Word32 *OptCrit_old_fx /*i/o : Q15 */ +) +{ + Word16 i, pos, M2, voicing_flag_old; + Word16 lsf_diff_fx[M]; + Word16 W_fx; + Word16 tmp1, tmp2; + Word32 L_tmp; + Word32 OptCrit_fx = 32768, Crit_fx; + Word16 *pt1, flag; + const Word16 *pt2, *pt3; + + /*voicing switching flag : to avoid switching start band frequently in VOICED or AUDIO area*/ + voicing_flag_old = *voicing_flag; + test(); + test(); + test(); + if( GT_16(voicing_fac_fx, 6554)||(GT_16(voicing_fac_fx,4915)&&GE_16(clas,VOICED_CLAS))||EQ_16(clas,AUDIO_CLAS)) + { + *voicing_flag = 1; + move16(); + } + + test(); + if( LT_16(voicing_fac_fx, 3277)&<_16(clas,VOICED_CLAS)) + { + *voicing_flag = 0; + move16(); + } + + /* rate adaptive start band */ + *start_band = 160; + move16(); + IF( LT_32(rate, ACELP_23k05)) + { + pt1 = lsf_diff_fx+1; + pt2 = lsf_fx+1; + pt3 = lsf_fx; + FOR(i=1; i<(M-1); i++) + { + *pt1++ = sub(*pt2++, *pt3++); + move16();/*Q2 */ + } + tmp1 = extract_l(Mult_32_16(rate, 27046)); /*Q14 */ + L_tmp = L_shr(L_mult0(tmp1, 22370), 15); /*Q27->1/6000 ->Q26 */ + tmp2 = extract_l(L_tmp); /*Q26 */ + W_fx = mult_r(tmp1, tmp2); /*Q25 */ + + if (EQ_16(clas,AUDIO_CLAS)) + { + W_fx = mult_r(W_fx, 24576); /*Q25 */ + } + + pos = 2; + move16(); + M2 = sub(M, 2); + IF( EQ_16(*voicing_flag,1)) + { + IF( LE_32(rate, ACELP_8k85)) + { + M2 = sub(M, 8); + } + ELSE IF( LE_32(rate, ACELP_12k65)) + { + M2 = sub(M, 6); + } + ELSE IF( LE_32(rate, ACELP_15k85)) + { + M2 = sub(M, 4); + } + } + + /*do the procedure for i==2*/ + L_tmp = L_max(L_msu(171798692, lsf_fx[2], W_fx), 171799); /* Q2.56+25+1 */ + Crit_fx = Mult_32_16(L_tmp, lsf_diff_fx[2]); /* Q2.56+25+1+2.56-15 = Q11+2.56+2.56 */ + + OptCrit_fx = L_add(Crit_fx, 0); + pos = 2; + move16(); + /*----------------------------------------------------------------*/ + + pt2 = &lsf_fx[3]; + pt1 = &lsf_diff_fx[3]; + FOR(i=3; i 0 ) ) + { + *OptCrit_old_fx = OptCrit_fx; + move16(); + test(); + test(); + if ( LT_16(abs_s(sub((*start_band),(*start_band_old))), 20)&&EQ_16(*voicing_flag,1)&&EQ_16(voicing_flag_old,1)) + { + *start_band = *start_band_old; + move16(); + } + } + ELSE + { + test(); + if (LT_32(OptCrit_fx, (*OptCrit_old_fx))&&EQ_16((*voicing_flag),1)) + { + *OptCrit_old_fx = OptCrit_fx; + move16(); + } + + *start_band = *start_band_old; + move16(); + } + + if (EQ_16(clas,AUDIO_CLAS)) + { + *start_band = s_min(*start_band, 120); + move16(); + } + + flag = sub(s_and(*start_band, 0x0001),1); + if (flag == 0) + { + *start_band = sub(*start_band, 1); + move16(); + } + } + + *start_band_old = *start_band; + move16(); + + return; +} + diff --git a/lib_dec/hq_classifier_dec_fx.c b/lib_dec/hq_classifier_dec_fx.c new file mode 100644 index 0000000..28813e7 --- /dev/null +++ b/lib_dec/hq_classifier_dec_fx.c @@ -0,0 +1,70 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required for wmc_tool */ + +/*--------------------------------------------------------------------------* + * hq_classifier_dec() + * + * HQ mode selector (decision_matrix) + *--------------------------------------------------------------------------*/ + +Word16 hq_classifier_dec_fx( /* o : Consumed bits Q0 */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : Core bit rate Q0 */ + const Word16 length, /* i : Frame length Q0 */ + Word16 *is_transient, /* o : Transient flag Q0 */ + Word16 *hqswb_clas /* o : HQ class Q0 */ +) +{ + Word16 bits; + + test(); + IF ( GE_16(length, L_FRAME32k)&&LE_32(core_brate,HQ_32k)) + { + *hqswb_clas = get_next_indice_fx( st_fx, 2 ); + move16(); + test(); + if (( EQ_16(length, L_FRAME48k))&&(EQ_16(*hqswb_clas,HQ_NORMAL))) + { + *hqswb_clas = HQ_GEN_FB; + move16(); + } + } + ELSE + { + *hqswb_clas = get_next_indice_fx( st_fx, 1 ); + move16(); + } + + *is_transient = 0; + move16(); + if ( EQ_16(*hqswb_clas, HQ_TRANSIENT)) + { + *is_transient = 1; + move16(); + } + + test(); + test(); + if ( *hqswb_clas == HQ_NORMAL && EQ_16(length, L_FRAME32k)&&LE_32(core_brate,HQ_32k)) + { + *hqswb_clas = HQ_GEN_SWB; + move16(); + } + + bits = 1; + move16(); + test(); + if ( GE_16(length, L_FRAME32k)&&LE_32(core_brate,HQ_32k)) + { + bits = 2; + move16(); + } + + return bits; +} + diff --git a/lib_dec/hq_conf_fec_fx.c b/lib_dec/hq_conf_fec_fx.c new file mode 100644 index 0000000..eb50364 --- /dev/null +++ b/lib_dec/hq_conf_fec_fx.c @@ -0,0 +1,39 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" +#include "cnst_fx.h" +#include "stl.h" /* required for wmc_tool */ + + +/*--------------------------------------------------------------------------* + * hq_configure_bfi_fx() + * + * Initialization of HQ bands and subframes + *--------------------------------------------------------------------------*/ +void hq_configure_bfi_fx( + Word16 *nb_sfm, /* o : Number of sub bands Q0 */ + Word16 *num_Sb, /* o : Number of FEC sub bands ? Q0 */ + Word16 *num_bands_p, /* o : FEC sub bands Q0 */ + Word16 const **sfmsize, /* o : Subband bandwidths */ + Word16 const **sfm_start, /* o : Subband start coefficients */ + Word16 const **sfm_end /* o : Subband end coefficients */ +) +{ + *num_Sb = MAX_SB_NB; + move16(); + *nb_sfm = SFM_N_NB; + move16(); + Copy( Num_bands_NB, num_bands_p, *num_Sb ); + *sfmsize = band_len_wb; + *sfm_start = band_start_wb; + *sfm_end = band_end_wb; + + + + return; +} diff --git a/lib_dec/hq_core_dec_fx.c b/lib_dec/hq_core_dec_fx.c new file mode 100644 index 0000000..8380f04 --- /dev/null +++ b/lib_dec/hq_core_dec_fx.c @@ -0,0 +1,460 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" +/*-------------------------------------------------------------------------- + * hq_core_dec() + * + * HQ core decoder + *--------------------------------------------------------------------------*/ + +void hq_core_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure fx */ + Word16 synth[], /* o : output synthesis */ + Word16 *Q_synth, /* o : Q value of synth */ + const Word16 output_frame, /* i : output frame length */ + const Word16 hq_core_type, /* i : HQ core type */ + const Word16 core_switching_flag /* i : ACELP->HQ switching frame flag */ +) +{ + Word16 num_bits, is_transient, hqswb_clas, inner_frame; + Word16 i, j, flag_uv, num_Sb, nb_sfm; + Word16 ynrm[NB_SFM], num_bands_p[MAX_SB_NB]; + Word16 ener_match; /* Q13 */ + Word32 t_audio_q[L_FRAME48k]; /* Q12 */ + Word16 Q_audio; + Word32 wtda_audio[2*L_FRAME48k]; + Word16 delay_comp; + Word32 normq_fx[NB_SFM]; + Word16 mean_en_high_fx; + Word16 SWB_fenv_fx[SWB_FENV+DIM_FB]; + const Word16 *sfmsize, *sfm_start, *sfm_end; + Word16 gapsynth_fx[L_FRAME48k]; + Word16 tmp, tmp_loop; + Word32 L_tmp; + UWord16 lsb; + + /*-------------------------------------------------------------------------- + * Initializations + *--------------------------------------------------------------------------*/ + + set32_fx( t_audio_q, 0, L_FRAME48k ); + set16_fx( gapsynth_fx, 0, L_FRAME48k ); + set16_fx( num_bands_p, 0, MAX_SB_NB ); + set16_fx( ynrm, 39, NB_SFM ); /* Initialize to the smallest value */ + mean_en_high_fx = 0; + move16(); + Q_audio = 12; + move16(); + sfm_start = sfm_end = NULL; + num_Sb = nb_sfm = 0; + + st_fx->tcx_cfg.tcx_last_overlap_mode = st_fx->tcx_cfg.tcx_curr_overlap_mode; + move16(); + if (EQ_16(st_fx->tcx_cfg.tcx_curr_overlap_mode, FULL_OVERLAP)) + { + st_fx->tcx_cfg.tcx_last_overlap_mode = ALDO_WINDOW; + move16(); + } + st_fx->tcx_cfg.tcx_curr_overlap_mode = ALDO_WINDOW; + move16(); + + /*-------------------------------------------------------------------------- + * Find the number of bits for transform-domain coding + *--------------------------------------------------------------------------*/ + + /* set the total bit-budget */ + /*num_bits = (short)(st->total_brate / 50); */ + Mpy_32_16_ss(st_fx->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + num_bits = extract_l(L_shr(L_tmp, 3)); /*Q0 */ + + IF( !st_fx->bfi_fx ) + { + IF ( EQ_16(core_switching_flag, 1)) + { + core_switching_hq_prepare_dec_fx( st_fx, &num_bits, output_frame ); + + /* During ACELP->HQ core switching, limit the HQ core bitrate to 48kbps */ + if ( GT_16(num_bits, HQ_48k / 50)) + { + num_bits = (Word16)(HQ_48k / 50); + move16(); + } + } + + /* subtract signalling bits */ + num_bits = sub(num_bits, st_fx->next_bit_pos_fx); + + /* set FEC parameters */ + flag_uv = sub(1, st_fx->HqVoicing_fx); + + /* subtract the number of bits for pitch & gain at higher bitrates */ + test(); + IF ( !(core_switching_flag) && GT_32(st_fx->core_brate_fx, MINIMUM_RATE_TO_ENCODE_VOICING_FLAG)) + { + st_fx->HqVoicing_fx = get_next_indice_fx( st_fx, 1 ); + num_bits = sub(num_bits, 1); + } + ELSE + { + st_fx->HqVoicing_fx = 0; + move16(); + if ( GT_32(st_fx->core_brate_fx, MINIMUM_RATE_TO_ENCODE_VOICING_FLAG)) + { + st_fx->HqVoicing_fx = 1; + move16(); + } + } + } + ELSE + { + flag_uv = 0; + move16(); + } + + /* set inner frame (== coded bandwidth) length */ + inner_frame = inner_frame_tbl[st_fx->bwidth_fx]; + move16(); + + IF ( st_fx->bfi_fx == 0) + { + st_fx->ph_ecu_HqVoicing_fx = 0; + move16(); + if ( GE_16(output_frame, L_FRAME16k)) + { + st_fx->ph_ecu_HqVoicing_fx = st_fx->HqVoicing_fx; + move16(); + } + } + + IF ( EQ_16(output_frame, L_FRAME8k)) + { + hq_configure_bfi_fx( &nb_sfm, &num_Sb, num_bands_p, &sfmsize, &sfm_start, &sfm_end ); + } + + /*-------------------------------------------------------------------------- + * transform-domain decoding + *--------------------------------------------------------------------------*/ + + IF( EQ_16(st_fx->bfi_fx, 1)) + { + is_transient = st_fx->old_is_transient_fx[0]; + move16(); + IF ( GE_16(output_frame, L_FRAME16k)) /* Apply phase ecu for WB, SWB and FB */ + { + /* ecu_rec sent to OLA, env_stab passed in ph_ecu_st */ + hq_ecu_fx( st_fx->prev_good_synth_fx, t_audio_q, &st_fx->time_offs_fx, st_fx->X_sav_fx, &st_fx->Q_X_sav, &st_fx->num_p_fx, st_fx->plocs_fx, st_fx->plocsi_fx, st_fx->env_stab_fx, + &st_fx->last_fec_fx, st_fx->ph_ecu_HqVoicing_fx, &st_fx->ph_ecu_active_fx, gapsynth_fx, st_fx->prev_bfi_fx, st_fx->old_is_transient_fx, st_fx->mag_chg_1st_fx, + st_fx->Xavg_fx, &st_fx->beta_mute_fx, output_frame, st_fx ); + } + ELSE + { + HQ_FEC_processing_fx( st_fx, t_audio_q, is_transient, st_fx->ynrm_values_fx, st_fx->r_p_values_fx, num_Sb, nb_sfm, num_bands_p, + output_frame, sfm_start, sfm_end ); + } + + st_fx->old_is_transient_fx[2] = st_fx->old_is_transient_fx[1]; + move16(); + st_fx->old_is_transient_fx[1] = st_fx->old_is_transient_fx[0]; + move16(); + + IF ( GE_16(output_frame, L_FRAME16k)) + { + /* keep st->previoussynth updated as in FEC_HQ_pitch_analysis but no LP analysis */ + delay_comp = NS2SA_fx2(st_fx->output_Fs_fx, DELAY_CLDFB_NS); + + Copy( st_fx->previoussynth_fx + delay_comp, st_fx->previoussynth_fx, sub(output_frame, delay_comp) ); + Copy( st_fx->delay_buf_out_fx, st_fx->previoussynth_fx + output_frame - delay_comp, delay_comp ); + + flag_uv = 1; + move16(); /* disable costly pitch out synthesis in bfi frame */ + st_fx->HqVoicing_fx = sub(1, flag_uv); /* safety setting for HQ->ACELP switch logic */ + set16_fx( st_fx->fer_samples_fx, 0, L_FRAME48k ); /* safety, create a known signal state for HQ->ACELP switch logic */ + } + } + ELSE + { + IF( EQ_16(hq_core_type, LOW_RATE_HQ_CORE)) + { + IF( EQ_16(st_fx->prev_bfi_fx, 1)) + { + set32_fx( st_fx->last_ni_gain_fx, 0, BANDS_MAX ); + set16_fx( st_fx->last_env_fx, 0, BANDS_MAX ); + st_fx->last_max_pos_pulse_fx = 0; + move16(); + } + + /* HQ low rate decoder */ + hq_lr_dec_fx( st_fx, t_audio_q, inner_frame, num_bits, &is_transient ); + + hqswb_clas = is_transient; + move16(); + Q_audio = 12; + move16(); + } + ELSE + { + /* HQ high rate decoder */ + hq_hr_dec_fx(st_fx, t_audio_q, inner_frame, num_bits, ynrm, &is_transient, &hqswb_clas, SWB_fenv_fx); + Q_audio = 12; + move16(); + } + + /* scaling (coefficients are in nominal level) */ + IF( NE_16(output_frame, NORM_MDCT_FACTOR)) + { + IF (EQ_16(output_frame, L_FRAME32k)) + { + Q_audio = sub(Q_audio, 1); /* Multiply by 2 */ + } + ELSE + { + tmp = mult_r(output_frame, 410/2); /* 1/8000 in Q15 */ + ener_match = hq_nominal_scaling_inv[tmp]; + FOR( i=0; i < inner_frame; i++ ) + { + /*t_audio_q[i] *= ener_match;*/ + Mpy_32_16_ss(t_audio_q[i], ener_match, &L_tmp, &lsb); /*12+13-15=10 */ + t_audio_q[i] = L_add(L_shl(L_tmp, 2), lshr(lsb, 14)); + move16(); /* Q12 */ + } + } + } + + HQ_FEC_Mem_update_fx( st_fx, t_audio_q, normq_fx, ynrm, num_bands_p, is_transient, hqswb_clas, + core_switching_flag, nb_sfm, num_Sb, &mean_en_high_fx, hq_core_type, output_frame ); + } + /*-------------------------------------------------------------------------- + * Attenuate HFs in case of band-width switching (from higher BW to lower BW) + *--------------------------------------------------------------------------*/ + /* attenuate HFs in case of band-width switching */ + IF( st_fx->bws_cnt1_fx > 0 ) + { + IF( EQ_16(st_fx->bws_cnt1_fx,N_NS2W_FRAMES)) + { + ener_match = 32767; + move16(); /*Q15*/ + } + ELSE + { + ener_match = div_s(st_fx->bws_cnt1_fx,N_NS2W_FRAMES); /*Q15*/ + } + + IF( is_transient ) + { + FOR( i = 0; i < NUM_TIME_SWITCHING_BLOCKS; i++ ) + { + tmp_loop = mult(inner_frame,8192); + FOR( j=mult(inner_frame_tbl_fx[sub(st_fx->bwidth_fx,1)],8192); jbwidth_fx,1)]; it_audio_q_fx, 80, -13); + } + ELSE + { + Copy_Scale_sig_32_16(t_audio_q, st_fx->t_audio_q_fx, L_FRAME, -13); + } + + + /*-------------------------------------------------------------------------- + * Inverse transform + * Overlap-add + * Pre-echo reduction + *--------------------------------------------------------------------------*/ + + test(); + IF (EQ_16(output_frame, L_FRAME8k)||st_fx->bfi_fx==0) + { + test(); + IF( NE_16(inner_frame, output_frame)&&EQ_16(st_fx->bfi_fx,1)) + { + Inverse_Transform( t_audio_q, &Q_audio, wtda_audio, is_transient, output_frame, output_frame ); + } + ELSE + { + Inverse_Transform( t_audio_q, &Q_audio, wtda_audio, is_transient, output_frame, inner_frame ); + } + *Q_synth = Q_audio; + move16(); + } + + IF ( EQ_16(output_frame, L_FRAME8k)) + { + test(); + IF( st_fx->bfi_fx == 0 && st_fx->prev_bfi_fx == 0) + { + Copy_Scale_sig(st_fx->old_out_fx+N_ZERO_NB, st_fx->prev_oldauOut_fx, output_frame-N_ZERO_NB, negate(st_fx->Q_old_wtda) ); + } + ELSE IF( EQ_16(st_fx->prev_bfi_fx, 1)) + { + set16_fx( st_fx->prev_oldauOut_fx, 0, output_frame ); + } + + test(); + test(); + test(); + test(); + IF( (EQ_16(st_fx->prev_bfi_fx, 1)||EQ_16(st_fx->bfi_fx,1))&&st_fx->old_is_transient_fx[2]==0&&EQ_16(st_fx->last_core_fx,HQ_CORE)&&EQ_16(st_fx->last_codec_mode,MODE1)) + { + time_domain_FEC_HQ_fx( st_fx, wtda_audio, synth, mean_en_high_fx, output_frame, Q_synth ); + } + ELSE + { + window_ola_fx( wtda_audio, synth, Q_synth, st_fx->old_out_fx, &st_fx->Q_old_wtda, output_frame, + st_fx->tcx_cfg.tcx_last_overlap_mode, st_fx->tcx_cfg.tcx_curr_overlap_mode, st_fx->prev_bfi_fx, st_fx->oldHqVoicing_fx , st_fx->oldgapsynth_fx ); + st_fx->phase_mat_next_fx = 0; + move16(); + } + + test(); + test(); + IF ( (st_fx->bfi_fx == 0 && st_fx->prev_bfi_fx == 0) || !(GE_16(output_frame, L_FRAME16k))) + { + preecho_sb_fx( st_fx->core_brate_fx, wtda_audio, Q_audio, synth, *Q_synth, output_frame, &st_fx->memfilt_lb_fx, + &st_fx->mean_prev_hb_fx, &st_fx->smoothmem_fx, &st_fx->mean_prev_fx, &st_fx->mean_prev_nc_fx, &st_fx->wmold_hb_fx, &st_fx->prevflag_fx, &st_fx->pastpre_fx, st_fx->bwidth_fx ); + } + } + ELSE + { + test(); + IF (EQ_16(st_fx->bfi_fx, 1)&&GE_16(output_frame,L_FRAME16k)) + { + /* PHASE_ECU active */ + Q_audio = 15; + move16(); + window_ola_fx( t_audio_q, synth, &Q_audio, st_fx->old_out_fx, &st_fx->Q_old_wtda, output_frame, + ALDO_WINDOW, ALDO_WINDOW, st_fx->prev_bfi_fx && !st_fx->ph_ecu_active_fx, st_fx->oldHqVoicing_fx, st_fx->oldgapsynth_fx ); + *Q_synth = Q_audio; + move16(); + } + ELSE + { + /* no BFI or baseline PLC active */ + window_ola_fx( wtda_audio, synth, Q_synth, st_fx->old_out_fx, &st_fx->Q_old_wtda, output_frame, + st_fx->tcx_cfg.tcx_last_overlap_mode, st_fx->tcx_cfg.tcx_curr_overlap_mode, st_fx->prev_bfi_fx && !st_fx->ph_ecu_active_fx, st_fx->oldHqVoicing_fx, st_fx->oldgapsynth_fx); + } + + test(); + test(); + IF ( (st_fx->bfi_fx == 0 && st_fx->prev_bfi_fx == 0) || !(GE_16(output_frame, L_FRAME16k))) + { + preecho_sb_fx( st_fx->core_brate_fx, wtda_audio, Q_audio, synth,*Q_synth, output_frame, &st_fx->memfilt_lb_fx, + &st_fx->mean_prev_hb_fx, &st_fx->smoothmem_fx, &st_fx->mean_prev_fx, &st_fx->mean_prev_nc_fx, &st_fx->wmold_hb_fx, &st_fx->prevflag_fx, &st_fx->pastpre_fx, st_fx->bwidth_fx ); + } + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF (!st_fx->bfi_fx + && st_fx->prev_bfi_fx + && GE_32(st_fx->last_total_brate_fx, HQ_48k) + && EQ_16(st_fx->last_codec_mode, MODE2) + && (EQ_16(st_fx->last_core_bfi, TCX_20_CORE) || EQ_16(st_fx->last_core_bfi, TCX_10_CORE) ) + && st_fx->plcInfo.concealment_method == TCX_NONTONAL + && LT_32(st_fx->plcInfo.nbLostCmpt, 4) ) + { + st_fx->plcInfo.recovery_gain = shl(st_fx->plcInfo.recovery_gain, *Q_synth); + waveform_adj2_fix(st_fx->tonalMDCTconceal.secondLastPcmOut, + synth, + st_fx->plcInfo.data_noise, + &st_fx->plcInfo.outx_new_n1_fx, + &st_fx->plcInfo.nsapp_gain_fx, + &st_fx->plcInfo.nsapp_gain_n_fx, + &st_fx->plcInfo.recovery_gain, + st_fx->plcInfo.step_concealgain_fx, + st_fx->plcInfo.Pitch_fx, + st_fx->plcInfo.FrameSize, + 0, + add(extract_l(st_fx->plcInfo.nbLostCmpt), 1), + st_fx->bfi_fx); + } + + IF (GE_16(output_frame, L_FRAME16k)) + { + IF (EQ_16(st_fx->ph_ecu_HqVoicing_fx, 1)) + { + st_fx->oldHqVoicing_fx = 1; + move16(); + Copy( gapsynth_fx, st_fx->oldgapsynth_fx, L_FRAME48k ); + } + ELSE + { + st_fx->oldHqVoicing_fx = 0; + move16(); + } + } + ELSE + { + st_fx->oldHqVoicing_fx = 0; + move16(); + } + + if( EQ_16(st_fx->nbLostCmpt, FRAMECTTOSTART_MDCT)) + { + st_fx->HqVoicing_fx = 0; + move16(); + } + + IF( EQ_16(output_frame, L_FRAME8k)) + { + Copy32( wtda_audio, st_fx->oldIMDCTout_fx, L_FRAME8k/2 ); + Copy(&st_fx->old_auOut_2fr_fx[output_frame], st_fx->old_auOut_2fr_fx, output_frame); + Copy_Scale_sig(synth, &st_fx->old_auOut_2fr_fx[output_frame], output_frame, negate(*Q_synth)); + } + + /* prepare synthesis output buffer (as recent as possible) for HQ FEC */ + + { + Word16 nbsubfr; + /*nbsubfr = extract_l(L_mult0(st_fx->L_frame_fx,FL2WORD16(1/L_SUBFR)));*/ + nbsubfr = 4; + if(EQ_16(st_fx->L_frame_fx,320)) + { + nbsubfr = 5; + move16(); + } + + /* update buffer of old subframe pitch values */ + test(); + IF( EQ_16(st_fx->last_core_fx,HQ_CORE)&&NE_16(st_fx->L_frame_fx,st_fx->last_L_frame_fx)) + { + set32_fx( &st_fx->old_pitch_buf_fx[nbsubfr], (L_SUBFR<<16), nbsubfr ); + } + Copy32( &st_fx->old_pitch_buf_fx[nbsubfr], &st_fx->old_pitch_buf_fx[0], nbsubfr ); + set32_fx( &st_fx->old_pitch_buf_fx[nbsubfr], (L_SUBFR<<16), nbsubfr ); + Copy( &st_fx->mem_pitch_gain[2], &st_fx->mem_pitch_gain[nbsubfr+2], nbsubfr ); + set16_fx( &st_fx->mem_pitch_gain[2], 0, nbsubfr ); + } + + return; +} diff --git a/lib_dec/hq_env_dec_fx.c b/lib_dec/hq_env_dec_fx.c new file mode 100644 index 0000000..f9d0f1d --- /dev/null +++ b/lib_dec/hq_env_dec_fx.c @@ -0,0 +1,216 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" /* required for wmc_tool */ + +/*------------------------------------------------------------------------* + * decode_envelope_indices_fx() + * + * Decode envelope indices + *------------------------------------------------------------------------*/ + +Word16 decode_envelope_indices_fx( /* o : Number of bits */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 start_norm, /* i : starting band index */ + const Word16 num_sfm, /* i : Number of subbands */ + const Word16 numnrmibits, /* i : Bitrate of fall-back coding mode */ + Word16 *difidx, /* o : Diff indices/encoded diff indices */ + const Word16 flag_HQ2 /* i : indicator of HQ2 core */ + ,const Word16 is_transient /* i : indicator of HQ_TRANSIENT */ +) +{ + Word16 hcode_l; + Word16 i,j; + Word16 LCmode; + Word16 startNormPlus1,numSfmMinus1,numSfmMinus2,offset; + Word16 *pDifidx,*pDifidx1; + + test(); + IF( EQ_16(flag_HQ2, LOW_RATE_HQ_CORE)||EQ_16(flag_HQ2,LOW_RATE_HQ_CORE_TRAN)) + { + LCmode = (Word16)get_next_indice_fx ( st_fx, BITS_DE_HMODE); + difidx[start_norm] = (Word16)get_next_indice_fx ( st_fx, BITS_DE_FCOMP); + } + ELSE + { + LCmode = (Word16)get_next_indice_fx( st_fx, 2 ); + difidx[start_norm] = (Word16)get_next_indice_fx( st_fx, NORM0_BITS ); + } + + test(); + IF( is_transient && EQ_16(flag_HQ2, LOW_RATE_HQ_CORE_TRAN)) + { + hcode_l = 0; + move16(); + IF( EQ_16(LCmode, 1)) + { + hdecnrm_tran_fx(st_fx, num_sfm, &difidx[start_norm + 1] ); + j = add(start_norm, num_sfm); + FOR( i = start_norm + 1; i < j; i++ ) + { + hcode_l = add(hcode_l, huffsizn_tran[difidx[i]]); + } + } + ELSE + { + hdecnrm_context_fx(st_fx, num_sfm, &difidx[start_norm], &hcode_l); + } + } + ELSE + { + hcode_l = 0; + IF( LCmode == 0 ) + { + hdecnrm_context_fx( st_fx, num_sfm, &difidx[start_norm], &hcode_l); + } + ELSE IF( LCmode == 1 ) + { + startNormPlus1 = add(start_norm, 1); + hdecnrm_resize_fx( st_fx, num_sfm, &difidx[startNormPlus1] ); + + pDifidx = &difidx[startNormPlus1]; + move16(); + numSfmMinus1 = sub(num_sfm, 1); + FOR( i = 0; i < numSfmMinus1; i++ ) + { + j = *pDifidx++; + move16(); + hcode_l = add(hcode_l, resize_huffsizn[j]); + } + + pDifidx1 = &difidx[startNormPlus1]; + move16(); + numSfmMinus2 = sub(num_sfm, 2); + FOR( i = 0; i < numSfmMinus2; i++ ) + { + pDifidx = pDifidx1++; + move16(); + IF( *pDifidx > 17 ) + { + offset = sub(*pDifidx, 17); + offset = s_min(offset, 3); + *pDifidx1 = sub(*pDifidx1, offset); + } + ELSE IF( *pDifidx < 13 ) + { + offset = sub(*pDifidx, 13); + offset = s_max(offset, -3); + *pDifidx1 = sub(*pDifidx1, offset); + } + } + } + ELSE IF( LCmode == 2 ) + { + startNormPlus1 = add(start_norm, 1); + hdecnrm_fx( st_fx, num_sfm, &difidx[start_norm + 1] ); + + pDifidx = &difidx[startNormPlus1]; + move16(); + numSfmMinus1 = sub(num_sfm, 1); + FOR( i = 0; i < numSfmMinus1; i++ ) + { + j = *pDifidx++; + move16(); + hcode_l = add(hcode_l, huffsizn[j]); + } + } + ELSE + { + startNormPlus1 = add(start_norm, 1); + numSfmMinus1 = sub(num_sfm, 1); + pDifidx = &difidx[startNormPlus1]; + FOR( i = 0; i < numSfmMinus1; i++ ) + { + *pDifidx++ = (Word16)get_next_indice_fx( st_fx, NORMI_BITS ); + move16(); + } + hcode_l = numnrmibits; + move16(); + } + } + + return hcode_l; +} + +/*------------------------------------------------------------------------* + * dequantize_norms_fx() + * + * De-quantization of norms + *------------------------------------------------------------------------*/ + +void dequantize_norms_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 start_norm, /* i : First SDE encoded norm */ + const Word16 num_sfm, /* i : Number of norms */ + const Word16 is_transient, /* i : Transient flag */ + Word16 *ynrm, /* o : Decoded norm indices */ + Word16 *normqlg2 /* o : Log2 of decoded norms */ +) +{ + Word16 i,j; + Word16 idxbuf[NB_SFM]; + Word16 *pYnrm, *pNormqlg2; + + /* First sub-frame */ + i = ynrm[start_norm]; + move16(); + normqlg2[start_norm] = dicnlg2[i]; + move16(); + + /* Other sub-frames */ + IF ( is_transient ) + { + /* Recover quantization indices and quantized norms */ + idxbuf[0] = ynrm[0]; + move16(); + FOR ( i = 1; i < num_sfm; i++ ) + { + idxbuf[i] = sub( add(ynrm[i],idxbuf[i-1]), 15 ); + move16(); + /* safety check in case of bit errors */ + test(); + IF ( idxbuf[i] < 0 || GT_16( idxbuf[i], 39 )) + { + idxbuf[i] = 39; + move16(); + st_fx->BER_detect = 1; + move16(); + } + } + + recovernorm_fx( idxbuf, ynrm, normqlg2, num_sfm ); + } + ELSE + { + pYnrm = &ynrm[start_norm]; + move16(); + pNormqlg2 = &normqlg2[start_norm+1]; + move16(); + FOR ( i = 1; i < num_sfm; i++ ) + { + j = sub(*pYnrm++,15); + move16(); + *pYnrm = add(*pYnrm,j); + move16(); + /* safety check in case of bit errors */ + test(); + IF ( *pYnrm < 0 || GT_16( *pYnrm, 39 )) + { + *pYnrm = 39; + move16(); + st_fx->BER_detect = 1; + move16(); + } + *pNormqlg2++ = dicnlg2[*pYnrm]; + move16(); + } + } + + return; +} + diff --git a/lib_dec/hq_hr_dec_fx.c b/lib_dec/hq_hr_dec_fx.c new file mode 100644 index 0000000..a403f1f --- /dev/null +++ b/lib_dec/hq_hr_dec_fx.c @@ -0,0 +1,313 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "stl.h" +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ + + +void hq_pred_hb_bws_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 *ynrm, /* i : norm quantization index vector */ + const Word16 length, /* i : frame length */ + const Word16 hqswb_clas, /* i : HQ SWB class */ + const Word16 *SWB_fenv /* i : SWB frequency envelopes Q1 */ +) +{ + Word16 i; + Word32 L_tmp; + + IF( GE_16(length,L_FRAME32k)) + { + /* calculate the switching parameters */ + test(); + test(); + IF( ( NE_16(hqswb_clas,HQ_GEN_SWB)&&LE_32(st_fx->core_brate_fx,HQ_32k))||GT_32(st_fx->core_brate_fx,HQ_32k)) + { + st_fx->prev_ener_shb_fx = 0; + move16(); + L_tmp = L_deposit_l(0); + FOR(i=25; iprev_ener_shb_fx = extract_l(L_tmp);/*Q1*/ + st_fx->prev_ener_shb_fx = mult(st_fx->prev_ener_shb_fx,5461); /*Q1*/ + } + ELSE + { + st_fx->prev_ener_shb_fx = 0; + move16(); + FOR(i=0; iprev_ener_shb_fx = add(st_fx->prev_ener_shb_fx,SWB_fenv[i]);/*Q1*/ + } + st_fx->prev_ener_shb_fx = mult(st_fx->prev_ener_shb_fx, 2979); /*Q1*/ + } + } + + IF( GE_16(st_fx->last_inner_frame_fx,L_FRAME32k)) + { + set16_fx(st_fx->prev_SWB_fenv_fx, st_fx->prev_ener_shb_fx, SWB_FENV); + } + + return; + +} +/*--------------------------------------------------------------------------* + * hq_hr_dec_fx() + * + * HQ High rate decoding routine + *--------------------------------------------------------------------------*/ +void hq_hr_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure fx */ + Word32 *t_audio_q, /* o : transform-domain coefficients Q12 */ + const Word16 length, /* i : frame length Q0 */ + Word16 num_bits, /* i : number of available bits Q0 */ + Word16 *ynrm, /* o : norm quantization index vector Q0 */ + Word16 *is_transient, /* o : transient flag Q0 */ + Word16 *hqswb_clas, /* o : HQ SWB class Q0 */ + Word16 *SWB_fenv /* o : SWB frequency envelopes Q1 */ +) +{ + Word16 nb_sfm; + Word16 sum, hcode_l; + const Word16 *sfmsize, *sfm_start, *sfm_end; + Word16 num_sfm, numnrmibits; + Word16 nf_idx; + Word16 normqlg2[NB_SFM], R[NB_SFM]; + Word16 pulses[NB_SFM], maxpulse[NB_SFM]; + Word16 env_stab; /*Q15*/ + Word16 Rsubband[NB_SFM]; /*Q3*/ + Word16 start_norm, Npeaks = 0; + Word16 noise_level[HVQ_BWE_NOISE_BANDS]; /*Q15*/ + Word16 peak_idx[HVQ_MAX_PEAKS_32k]; + Word16 hq_generic_offset; + Word16 num_env_bands; + Word16 hq_generic_exc_clas = 0; + Word16 core_sfm; + Word16 har_freq_est1, har_freq_est2; + Word16 flag_dis; + const Word16 *subband_search_offset; + Word16 wBands[2]; + Word16 bits, i; + Word16 t_audio_q_norm[L_FRAME48k]; + Word16 Q_audio; + Word16 b_delta_env; + Word16 tmp,n_band; + Word16 Q_shift; + + Q_audio = 0; /* to avoid compilation warnings */ + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + set16_fx( pulses, 0, NB_SFM ); + set16_fx( maxpulse, 0, NB_SFM ); + flag_dis = 1; + move16(); + har_freq_est1 = 0; + move16(); + har_freq_est2 = 0; + move16(); + set16_fx( peak_idx, 0, HVQ_MAX_PEAKS_32k); + + /*------------------------------------------------------------------* + * Decode classification + *------------------------------------------------------------------*/ + + bits = hq_classifier_dec_fx( st_fx, st_fx->core_brate_fx, length, is_transient, hqswb_clas); + num_bits = sub(num_bits, bits); + + /*------------------------------------------------------------------* + * set quantization parameters + *------------------------------------------------------------------*/ + + hq_configure_fx( length, *hqswb_clas, st_fx->core_brate_fx, &num_sfm, &nb_sfm, &start_norm, + &num_env_bands, &numnrmibits, &hq_generic_offset, &sfmsize, &sfm_start, &sfm_end ); + + /*------------------------------------------------------------------* + * Unpacking bit-stream + *------------------------------------------------------------------*/ + + nf_idx = 0; + move16(); + test(); + test(); + test(); + IF( !*is_transient && NE_16(*hqswb_clas, HQ_HVQ)&&!(EQ_16(length,L_FRAME16k)&&EQ_32(st_fx->core_brate_fx,HQ_32k))) + { + nf_idx = get_next_indice_fx( st_fx, 2 ); + } + + /*------------------------------------------------------------------* + * Decode envelope + *------------------------------------------------------------------*/ + + hcode_l = decode_envelope_indices_fx( st_fx, start_norm, num_env_bands, numnrmibits, ynrm, NORMAL_HQ_CORE, *is_transient ); + num_bits = sub(num_bits, add(hcode_l, NORM0_BITS + FLAGS_BITS)); + + dequantize_norms_fx( st_fx, start_norm, num_env_bands, *is_transient, ynrm, normqlg2 ); + + test(); + IF ( EQ_16(*hqswb_clas, HQ_GEN_SWB)||EQ_16(*hqswb_clas,HQ_GEN_FB)) + { + hq_generic_exc_clas = swb_bwe_gain_deq_fx( st_fx, HQ_CORE, NULL, SWB_fenv, st_fx->core_brate_fx == HQ_32k, *hqswb_clas ); + if ( EQ_16(hq_generic_exc_clas , HQ_GENERIC_SP_EXC)) + { + num_bits = add(num_bits,1); /* conditional 1 bit saving for representing HQ GENERIC excitation class */ + } + map_hq_generic_fenv_norm_fx( *hqswb_clas, SWB_fenv, ynrm, normqlg2, num_env_bands, nb_sfm, hq_generic_offset ); + } + + env_stab = 0; + move16(); + IF( EQ_16(*hqswb_clas, HQ_HVQ)) + { + st_fx->mem_env_delta_fx = 0; + move16(); + } + ELSE IF( EQ_16(length, L_FRAME32k)) + { + env_stab = env_stability_fx( ynrm, SFM_N_ENV_STAB, st_fx->mem_norm_fx, &st_fx->mem_env_delta_fx ); + } + ELSE + { + st_fx->mem_norm_fx[0] = 31; + move16(); + st_fx->mem_env_delta_fx = 0; + move16(); + } + + IF ( EQ_16(*hqswb_clas, HQ_HVQ)) + { + st_fx->env_stab_fx = 32767; + move16(); /* 1 in Q15, stable by definition */ + } + ELSE + { + IF ( EQ_16(length, L_FRAME32k)) + { + st_fx->env_stab_fx = env_stab; + move16(); /* calculated stability */ + } + ELSE + { + st_fx->env_stab_fx = env_stability_fx( ynrm, SFM_N_ENV_STAB_WB, st_fx->mem_norm_hqfec_fx, &st_fx->mem_env_delta_hqfec_fx ); + } + } + st_fx->env_stab_plc_fx = env_stab_smo_fx(s_min(st_fx->env_stab_fx, sub(32767, stab_trans_fx[L_STAB_TBL-1])), st_fx->env_stab_state_p_fx, &st_fx->envstabplc_hocnt_fx); + + /*------------------------------------------------------------------* + * Bit allocation + *------------------------------------------------------------------*/ + + hq_bit_allocation_fx( st_fx->core_brate_fx, length, *hqswb_clas, &num_bits, normqlg2, nb_sfm, sfmsize, noise_level, + R, Rsubband, &sum, &core_sfm, num_env_bands ); + + test(); + test(); + IF( EQ_16(*hqswb_clas, HQ_GEN_SWB)&&st_fx->bws_cnt1_fx>0&&EQ_32(st_fx->core_brate_fx,HQ_24k40)) + { + tmp = i_mult(st_fx->bws_cnt1_fx, 1638); + move16(); + IF( EQ_16(st_fx->L_frame_fx, L_FRAME16k)) + { + FOR (n_band = 0; n_band < 4; n_band++) + { + SWB_fenv[n_band] = mult_r(SWB_fenv[n_band], tmp); + move16(); + } + } + + FOR (n_band = 4; n_band < SWB_FENV; n_band++) + { + SWB_fenv[n_band] = mult_r(SWB_fenv[n_band], tmp); + move16(); + } + } + + test(); + IF ( EQ_16(*hqswb_clas , HQ_GEN_SWB)||EQ_16(*hqswb_clas,HQ_GEN_FB)) + { + b_delta_env = get_nor_delta_hf_fx(st_fx, ynrm, Rsubband, num_env_bands, nb_sfm, core_sfm ); + sum = sub(sum,b_delta_env); + } + + /*------------------------------------------------------------------* + * Decode spectral fine structure using HVQ/PVQ + *------------------------------------------------------------------*/ + + IF( EQ_16(*hqswb_clas, HQ_HVQ)) + { + hvq_dec_fx( st_fx, num_bits, st_fx->core_brate_fx, ynrm, R, noise_level, peak_idx, &Npeaks, t_audio_q, st_fx->core_fx ); + } + ELSE + { + pvq_core_dec_fx(st_fx, sfm_start, sfm_end, sfmsize, t_audio_q_norm, &Q_audio, sum, nb_sfm, Rsubband, R, pulses, maxpulse, HQ_CORE ); + } + + test(); + IF ( EQ_16(*hqswb_clas, HQ_HVQ)||EQ_16(*hqswb_clas,HQ_HARMONIC)) + { + subband_search_offset = subband_search_offsets_13p2kbps_Har_fx; + wBands[0] = SWB_SB_BW_LEN0_16KBPS_HAR; + move16(); + wBands[1] = SWB_SB_BW_LEN1_16KBPS_HAR; + move16(); + + IF (EQ_16(*hqswb_clas, HQ_HARMONIC)) + { + Q_shift = sub(SWB_BWE_LR_Qs, Q_audio); + FOR (i = 0; i < 300; i++) + { + t_audio_q[i] = L_shl(L_deposit_l(t_audio_q_norm[i]), Q_shift); /* Q12 */ + } + } + + har_est_fx( t_audio_q, 300 ,&har_freq_est1, &har_freq_est2, &flag_dis, &st_fx->prev_frm_hfe2_fx, subband_search_offset, wBands, &st_fx->prev_stab_hfe2_fx ); + + st_fx->prev_frm_hfe2_fx = har_freq_est2; + move16(); + } + + test(); + test(); + IF ( NE_16(*hqswb_clas, HQ_HARMONIC)||NE_16(*hqswb_clas,HQ_HVQ)||flag_dis==0) + { + st_fx->prev_frm_hfe2_fx = 0; /*reset*/ move16(); + st_fx->prev_stab_hfe2_fx = 0; /*reset*/ move16(); + } + + /*------------------------------------------------------------------* + * Spectral filling + *------------------------------------------------------------------*/ + fill_spectrum_fx( t_audio_q_norm, t_audio_q, R, *is_transient, ynrm, SWB_fenv, hq_generic_offset, nf_idx, length, env_stab, + &st_fx->no_att_hangover_fx, &st_fx->energy_lt_fx, &st_fx->hq_generic_seed_fx, hq_generic_exc_clas, + core_sfm, *hqswb_clas, noise_level, st_fx->core_brate_fx, st_fx->prev_noise_level_fx, &st_fx->prev_R_fx, st_fx->prev_coeff_out_fx, peak_idx, Npeaks, pulses, st_fx->old_is_transient_fx[0], + st_fx->prev_normq_fx, st_fx->prev_env_fx, st_fx->prev_bfi_fx, sfmsize, sfm_start, sfm_end, &st_fx->prev_L_swb_norm_fx, st_fx->prev_hqswb_clas_fx, num_sfm, + st_fx->prev_env_Q, num_env_bands ); + + enforce_zero_for_min_envelope_fx( *hqswb_clas, ynrm, t_audio_q, nb_sfm, sfm_start, sfm_end ); + + + IF( EQ_16(*is_transient, 1)) + { + de_interleave_spectrum_fx( t_audio_q, length ); + } + + /*------------------------------------------------------------------* + * WB/SWB bandwidth switching + *------------------------------------------------------------------*/ + hq_pred_hb_bws_fx(st_fx, ynrm, length, *hqswb_clas, SWB_fenv ); + + /* update */ + st_fx->prev_hqswb_clas_fx = *hqswb_clas; + move16(); + + return; +} diff --git a/lib_dec/hq_lr_dec_fx.c b/lib_dec/hq_lr_dec_fx.c new file mode 100644 index 0000000..6982abc --- /dev/null +++ b/lib_dec/hq_lr_dec_fx.c @@ -0,0 +1,1332 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "options.h" +#include "cnst_fx.h" +#include "rom_dec_fx.h" +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "stl.h" /* required for wmc_tool */ +#include "basop_mpy.h" + +/*--------------------------------------------------------------------------* + * Local functions + *--------------------------------------------------------------------------*/ + +static Word16 p2a_threshold_dequant_fx( Decoder_State_fx *st_fx, Word16 *p2a_flags, const Word16 bands, const Word16 p2a_bands ); + +static void mdct_spectrum_fine_gain_dec_fx( Decoder_State_fx *st_fx, Word32 L_y2[], const Word16 band_start[], const Word16 band_end[], + const Word16 k_sort[], const Word16 bands, + const Word32 L_qint,const Word16 Ngq, const Word16 gqlevs, const Word16 gqbits ); + +static Word16 band_energy_dequant_fx( Decoder_State_fx *st_fx, Word32 L_band_energy[], const Word16 bands, + const Word32 L_qint,const Word16 eref_fx, const Word16 is_transient_fx ); + +static Word16 Calc_inv(Word32 L_tmp, Word16 *exp) +{ + Word16 exp2, tmp; + + tmp = extract_h(L_tmp); + + IF(tmp != 0) + { + exp2 = norm_s(tmp); + tmp = shl(tmp,exp2);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp=29-exp) */ + *exp = sub(29,exp2); + move16(); + } + ELSE + { + tmp = 0x7fff; + move16(); + *exp = 0; + move16(); + } + return tmp; +} + +/*--------------------------------------------------------------------------* + * spt_shorten_domain_set_dec() + * + * update the shorten band information based on p2a analysis + *--------------------------------------------------------------------------*/ + +static void spt_shorten_domain_set_dec_fx( + Decoder_State_fx *st_fx, /* i: encoder state structure */ + const Word16 p2a_flags[], /* i: p2a anlysis information */ + const Word16 new_band_start[], /* i: new band start position */ + const Word16 new_band_end[], /* i: new band end position */ + const Word16 new_band_width[], /* i: new subband band width */ + const Word16 bands, /* i: total number of subbands */ + Word16 band_start[], /* o: band start position */ + Word16 band_end[], /* o: band end position */ + Word16 band_width[], /* o: sub band band width */ + Word16 *bit_budget /* i/o: bit budget */ +) +{ + Word16 j,k; + Word16 kpos; + Word16 spt_shorten_flag[SPT_SHORTEN_SBNUM]; + + kpos = 0; + move16(); + j = 0; + move16(); + FOR( k = sub(bands,SPT_SHORTEN_SBNUM); k < bands; k++ ) + { + spt_shorten_flag[j] = 0; + move16(); + IF( EQ_16(p2a_flags[k], 1)) + { + spt_shorten_flag[j] = get_next_indice_fx (st_fx, 1 ); + *bit_budget = sub(*bit_budget, 1); + IF( EQ_16(spt_shorten_flag[j], 1)) + { + band_start[k] = new_band_start[j]; + move16(); + band_end[k] = new_band_end[j]; + move16(); + band_width[k] = new_band_width[j]; + move16(); + } + } + + kpos = add(kpos, 1); + j = add(j, 1); + } + + return; +} + +/*-------------------------------------------------------------------* + * hq_lr_dec_fx() + * + * HQ low rate decoding routine + *-------------------------------------------------------------------*/ + +void hq_lr_dec_fx( + Decoder_State_fx *st_fx, /* i/o: : decoder state structure */ + Word32 L_yout[], /* o : Q12 : transform-domain output coefs. */ + const Word16 inner_frame, /* i : Q0 : inner frame length */ + Word16 num_bits, /* i : Q0 : number of available bits */ + Word16 *is_transient_fx /* o : Q0 : transient flag */ +) +{ + Word16 i, j, k; + + Word32 L_y2[L_FRAME48k]; + Word32 L_y2_ni[L_FRAME48k]; + Word32 L_y2_org[L_FRAME48k]; + Word16 inp_vector_fx[L_FRAME48k]; + Word16 flag_spt_fx; + Word32 L_m[L_FRAME48k]; + Word32 L_band_energy[BANDS_MAX]; + Word32 L_band_energy_tmp[BANDS_MAX]; + + Word16 npulses_fx[BANDS_MAX]; + Word16 lowlength_fx, highlength_fx, hqswb_clas_fx, har_bands_fx, bands_fx; + Word16 p2a_flags_fx[BANDS_MAX]; + Word32 L_bwe_br; + Word16 prev_SWB_peak_pos_tmp_fx[SPT_SHORTEN_SBNUM]; + + Word16 band_start[BANDS_MAX], band_end[BANDS_MAX], band_width[BANDS_MAX],trans_bit_fx; + + /* hq2_core_configure */ + Word32 L_qint; + /*Word16 Qqint=29;*/ + + Word16 eref_fx/*, Qeref=10*/; + Word16 bit_alloc_weight_fx/*, Qbaw=13*/; + Word16 ld_slope_fx/*, Qldslope=15*/; + Word16 p2a_th_fx/*, Qp2ath=11*/; + Word16 pd_thresh_fx/*, Qpdth=15*/; + Word16 ni_coef_fx/*, Qnicoef=14*/; + + Word32 L_Rk[BANDS_MAX]; + Word16 bit_budget_fx; + + Word16 ni_seed_fx; + Word16 length_fx; + Word16 pbits_fx; + + Word16 k1_fx; + Word16 gqlevs_fx, gqbits_fx, Ngq_fx, p2a_bands_fx; + Word16 ebits_fx; + Word16 exp_norm; + Word16 org_band_start[SPT_SHORTEN_SBNUM]; + Word16 org_band_end[SPT_SHORTEN_SBNUM]; + Word16 org_band_width[SPT_SHORTEN_SBNUM]; + + Word16 new_band_start[SPT_SHORTEN_SBNUM]; + Word16 new_band_end[SPT_SHORTEN_SBNUM]; + Word16 new_band_width[SPT_SHORTEN_SBNUM]; + + Word16 k_sort_fx[BANDS_MAX]; + Word16 last_bitalloc_max_band[2]; + Word32 L_tmp; + Word16 lowband,highband,p2a_flags_tmp[BANDS_MAX]; + Word32 L_tmp2,L_tmp3; + Word16 exp,exp2,tmp,tmp1,tmp2,tmp3,frac1,alpha_fx,Q_band_energy; + Word32 enerH_fx; + Word32 enerL_fx; + Word32 Ep_fx[BANDS_MAX]; + Word32 Ep_avrg_fx, Ep_vari_fx; + Word32 Ep_avrgL_fx; + Word32 Ep_peak_fx; + Word32 Ep_tmp_fx[BANDS_MAX]; + Word16 gama_fx;/*Q15 0.85f;// */ + Word16 beta_fx;/*Q14 1.05f; */ + Word16 adjustFlag; + Word16 bw_low, bw_high; + + tmp2 = 0; /* to avoid compilation flags */ + + set16_fx(last_bitalloc_max_band, 0, 2); + set32_fx( L_y2, 0x0L, L_FRAME48k ); + set16_fx( inp_vector_fx, 0, inner_frame ); + flag_spt_fx = 0; + move16(); + set16_fx(prev_SWB_peak_pos_tmp_fx, 0, SPT_SHORTEN_SBNUM); + adjustFlag = 0; + move16(); + bw_low = 0; + move16(); + bw_high = 20; + move16(); + enerL_fx = L_deposit_l(0); + enerH_fx = L_deposit_l(0); + + L_bwe_br = L_add(st_fx->core_brate_fx, 0); + hqswb_clas_fx = 0; + move16(); + test(); + test(); + IF( EQ_16(st_fx->bwidth_fx, SWB)&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))) + { + hqswb_clas_fx = get_next_indice_fx(st_fx, 2); + num_bits = sub(num_bits, 2); + + *is_transient_fx = 0; + move16(); + if ( EQ_16(hqswb_clas_fx, HQ_TRANSIENT)) + { + *is_transient_fx = 1; + move16(); + } + } + ELSE + { + /* decode transient flag */ + *is_transient_fx = get_next_indice_fx(st_fx, 1); + num_bits = sub(num_bits, 1); + } + + /* Configure decoder for different bandwidths, bit rates, etc. */ + hq2_core_configure_fx( inner_frame, num_bits, *is_transient_fx, &bands_fx, &length_fx, band_width, band_start, band_end, + &L_qint, &eref_fx, &bit_alloc_weight_fx, &gqlevs_fx, &Ngq_fx, &p2a_bands_fx, &p2a_th_fx, &pd_thresh_fx, &ld_slope_fx, &ni_coef_fx + ,L_bwe_br); + + highlength_fx = band_end[bands_fx-1]; + move16(); + har_bands_fx = bands_fx; + move16(); + + test(); + test(); + test(); + IF( EQ_16(st_fx->bwidth_fx, SWB)&&*is_transient_fx==0&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))) + { + /* reserve bits for HQ_NORMAL2 and HQ_HARMONIC modes */ + test(); + IF( EQ_16(hqswb_clas_fx, HQ_NORMAL)||EQ_16(hqswb_clas_fx,HQ_HARMONIC)) + { + num_bits = sub(num_bits, get_usebit_npswb_fx(hqswb_clas_fx)); + } + if( EQ_16(hqswb_clas_fx, HQ_NORMAL)) + { + flag_spt_fx = 1; + move16(); + } + } + + test(); + test(); + IF(( EQ_32(L_bwe_br, HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))&&EQ_16(st_fx->bwidth_fx,SWB)) + { + IF( NE_16(st_fx->prev_hqswb_clas_fx, HQ_NORMAL)) + { + j = 0; + move16(); + FOR(k=sub(bands_fx,SPT_SHORTEN_SBNUM); kprev_SWB_peak_pos_fx[j] = 0; + move16(); + j = add(j, 1); + } + } + } + + /* Spectral energy calculation/quantization */ + ebits_fx = band_energy_dequant_fx( st_fx, L_band_energy, bands_fx, L_qint, eref_fx, *is_transient_fx ); + + /* simple check: band_energy is too large, Abnormal Situation of bit errors */ + FOR( k=0; kBER_detect = 1; + move16(); + set32_fx( L_yout, 0x0L, inner_frame ); + return; + } + } + + /* First pass bit budget for TCQ of spectral band information */ + exp_norm = norm_s(gqlevs_fx); + gqbits_fx = sub(14, exp_norm); + + bit_budget_fx = sub(sub(num_bits, ebits_fx), round_fx(L_shl(L_mult(Ngq_fx, gqbits_fx), 15))); /* (*num_bits) - (short) ceil (ebits) - Ngq * gqbits; */ + + + pbits_fx = 0; + move16(); + test(); + test(); + IF( EQ_16(st_fx->bwidth_fx, SWB)&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))) + { + IF ( EQ_16(hqswb_clas_fx, HQ_HARMONIC)) + { + set16_fx( p2a_flags_fx, 1, har_bands_fx ); + } + ELSE + { + pbits_fx = p2a_threshold_dequant_fx( st_fx, p2a_flags_fx, bands_fx, p2a_bands_fx ); + bit_budget_fx = sub(bit_budget_fx, pbits_fx); + + IF( EQ_16(hqswb_clas_fx, HQ_NORMAL)) + { + return_bits_normal2_fx( &bit_budget_fx, p2a_flags_fx, bands_fx, bits_lagIndices_modeNormal_fx ); + } + } + } + ELSE + { + pbits_fx = p2a_threshold_dequant_fx( st_fx, p2a_flags_fx, bands_fx, p2a_bands_fx ); + bit_budget_fx = sub(bit_budget_fx, pbits_fx); + } + + IF( EQ_16(flag_spt_fx, 1)) + { + /* initalize the desired parameters for SPT */ + spt_shorten_domain_band_save_fx(bands_fx, band_start, band_end, band_width, org_band_start, org_band_end, org_band_width); + spt_shorten_domain_pre_fx(band_start, band_end, st_fx->prev_SWB_peak_pos_fx, bands_fx, L_bwe_br, new_band_start, new_band_end, new_band_width); + spt_shorten_domain_set_dec_fx(st_fx, p2a_flags_fx, new_band_start, new_band_end, new_band_width, bands_fx, band_start, band_end, band_width, &bit_budget_fx); + } + + /* safety check in case of bit errors */ + IF( LT_16(bit_budget_fx, 2)) + { + st_fx->BER_detect = 1; + move16(); + set32_fx( L_yout, 0x0, inner_frame ); + return; + } + + Q_band_energy = SWB_BWE_LR_Qbe; + FOR(i = 0; i < bands_fx; i++) + { + L_tmp = L_shl(L_band_energy[i],sub(16,Q_band_energy));/*Q16 */ + + frac1 = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */ + L_tmp = Pow2(30, frac1); + exp = sub(exp, 30); + Ep_fx[i] = L_shl(L_tmp , s_max(sub(exp,6), -31)); /* Q -6 */ + } + + FOR( i = 0; i < bands_fx; i++ ) + { + L_tmp2 = Ep_fx[i]; + L_tmp = L_max(1, L_tmp2); + exp = norm_l(L_tmp); + tmp = extract_h(L_shl(L_tmp, exp)); + + L_tmp3 = (Word32)band_width[i]; + exp2 = norm_l(L_tmp3); + tmp2 = extract_h(L_shl(L_tmp3, exp2)); + + exp2 = sub(exp, exp2); /* Denormalize and substract */ + + tmp3 = sub(tmp2, tmp); + if (tmp3 > 0) + { + tmp2 = shr(tmp2, 1); + } + if (tmp3 > 0) + { + exp2 = add(exp2, 1); + } + tmp = div_s(tmp2, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp2);/*Q(31-exp2) */ + Ep_tmp_fx[i] = L_shr(L_tmp,sub(15,exp2));/*Q13 */ move32(); + } + + test(); + test(); + test(); + test(); + test(); + test(); + IF ( *is_transient_fx == 0 && EQ_16(inner_frame, L_FRAME8k)&&LE_32(st_fx->core_brate_fx,ACELP_13k20)) + { + /* decode the last p2a_bands-1 subbands bit-allocation index of the previous frame */ + j = 0; + FOR(i = 0; i < 2; i++) + { + last_bitalloc_max_band[i] = get_next_indice_fx( st_fx, 1 ); + } + lowband = 6; + move16(); + trans_bit_fx = 2; + move16(); + bit_budget_fx = sub(bit_budget_fx,trans_bit_fx); + gama_fx = 27852; + move16(); /*Q15 0.85f; */ + beta_fx = 17203; + move16(); /*Q14 1.05f; */ + + set16_fx(&p2a_flags_tmp[sub(bands_fx,trans_bit_fx)], 0, 2); + + IF( EQ_32(st_fx->core_brate_fx, ACELP_13k20)) + { + beta_fx = 13107; + move16();/*14 1.25f; */ + gama_fx = 31130; + move16();/*0.95f; */ + Copy(&p2a_flags_fx[sub(bands_fx,trans_bit_fx)], &p2a_flags_tmp[sub(bands_fx,trans_bit_fx)], trans_bit_fx); + } + + /* calculate the the low band/high band energy and the variance/avrage of the envelopes */ + Ep_vari_fx = L_deposit_l(0); + Ep_avrg_fx = L_deposit_l(0); + Ep_avrgL_fx = L_deposit_l(0); + Ep_peak_fx = L_deposit_l(0); + FOR( i = 0; i < bands_fx; i++ ) + { + IF( GE_16(i,lowband)) + { + Ep_vari_fx = L_add(Ep_vari_fx,L_abs(L_sub(Ep_tmp_fx[i],Ep_tmp_fx[sub(i,1)])));/*Q15 */ + Ep_avrg_fx = L_add(Ep_avrg_fx,Ep_tmp_fx[i]);/*Q15 */ + + } + ELSE + { + Ep_avrgL_fx = L_add(Ep_avrgL_fx,Ep_tmp_fx[i]);/*Q15 */ + if(GT_32(Ep_tmp_fx[i],Ep_peak_fx)) + { + Ep_peak_fx = L_add(Ep_tmp_fx[i], 0); /*Q15 */ + } + } + + } + /* modify the last p2a_bands subbands band_energies */ + Copy32( L_band_energy,L_band_energy_tmp,bands_fx ); /*Q_band_energy */ + L_tmp = Mult_32_16(Ep_peak_fx,24576);/*Q(13+14-15 = 12) 1.5 lowband = 6; */ + L_tmp2 =Mult_32_16(Ep_peak_fx,shl(sub(bands_fx,lowband),9));/*Q(13+9-15 = 7) */ + L_tmp3 =Mult_32_16(Ep_avrg_fx,1126);/*Q(13+9-15 = 7) */ + + test(); + test(); + test(); + test(); + IF(( (LT_32(L_tmp, L_shr(Ep_avrgL_fx,1))&&EQ_32(st_fx->core_brate_fx,ACELP_13k20))||LT_32(st_fx->core_brate_fx,ACELP_13k20))&& + LT_32(L_tmp2, L_tmp3) && GT_32(L_tmp2, L_shr(Ep_avrg_fx,7)) ) + { + FOR(i = lowband; i < bands_fx; i++) + { + L_tmp = Mult_32_16(Ep_avrg_fx,24576);/*Q(13+14-15 = 12) 1.5 */ + IF(LT_32(L_shr(Ep_tmp_fx[i],1), L_tmp)) + { + L_tmp = Mult_32_16(Ep_peak_fx,sub(bands_fx,lowband));/*Q(13+0-15 = -2) */ + tmp = Calc_inv(L_shl(L_tmp,14), &exp); + L_tmp = L_shl(Mult_32_16(Ep_avrg_fx,tmp),sub(13,exp));/*Q(13+exp-15 +13-exp +4 = 15) */ + L_tmp2 = L_add(L_tmp,13107); /*15 */ + tmp2 = extract_l(L_min(L_max(L_tmp2,16384),gama_fx)); /*15 = 15 */ + L_band_energy_tmp[i] = Mult_32_16(L_band_energy_tmp[i],tmp2);/*Q(Q_band_energy+15-15 = Q_band_energy) */ move32(); + } + } + } + ELSE + { + FOR(i = sub(bands_fx,trans_bit_fx); i < bands_fx; i++) + { + alpha_fx = 16384; + move16();/*Q14 */ + IF( EQ_16(p2a_flags_tmp[i],1)) + { + L_tmp = Mult_32_16(Ep_tmp_fx[i],sub(bands_fx,lowband));/*Q(13+0-15 = -2) */ + tmp = Calc_inv(L_shl(L_tmp,14), &exp); + L_tmp =Mult_32_16(Ep_vari_fx,3277);/*13+15-15=13 */ + L_tmp = L_shl(Mult_32_16(L_tmp,tmp),sub(12,exp));/*Q(13+exp-15 +12-exp +4 = 14) */ + + tmp2 = extract_h(Ep_avrg_fx);/*Q13-16=-3 */ + IF(tmp2 != 0) + { + exp = norm_s(tmp2); + tmp2 = shl(tmp2,exp);/*Q(exp) */ + tmp2 = div_s(16384,tmp2);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + /*when the divisor is zero, happens rarely*/ + tmp2 = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp2 =Mult_32_16(Ep_vari_fx,6554);/*13+15-15=13 */ + L_tmp2 = L_shl(Mult_32_16(L_tmp2,tmp2),sub(13,exp));/*Q(13+exp-15 +13-exp +3 = 14) */ + L_tmp=L_min(L_tmp,L_tmp2);/*14 */ + tmp=extract_l(L_min(L_tmp,13107));/*14 */ + alpha_fx =add(16384,tmp); + + } + IF(EQ_16(last_bitalloc_max_band[j++], 1)) + { + L_tmp = Mult_32_16(Ep_tmp_fx[i],sub(bands_fx,lowband));/*Q(13+0-15 = -2) */ + tmp = Calc_inv(L_shl(L_tmp,14), &exp); + L_tmp = L_shl(Mult_32_16(Ep_avrg_fx,tmp),sub(14,exp));/*Q(13+exp-15 +14-exp+2 = 14) */ + L_tmp =L_max(L_tmp,16384); /*14 */ + tmp=extract_l(L_min(L_tmp,beta_fx)); /*14 */ + alpha_fx=shl(mult(alpha_fx,tmp),1);/*14+14-15 +1=14 */ + } + ELSE + { + tmp2 = extract_h(Ep_avrg_fx);/*13 -16 =-3 */ + IF(tmp2 != 0) + { + exp = norm_s(tmp2); + tmp2 = shl(tmp2,exp);/*Q(exp) */ + tmp2 = div_s(16384,tmp2);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + /*when the divisor is zero, happens rarely*/ + tmp2 = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = L_shl(Mult_32_16(Ep_tmp_fx[i],tmp2),sub(19,exp));/*Q(13+exp-15 +19-exp +3 = 20) */ + L_tmp = Mult_32_16(L_tmp,shl(sub(bands_fx,lowband),9));/*20 +9 -15 =14 */ + L_tmp =L_max(L_tmp,13926); /*14 */ + tmp2 =extract_l(L_min(L_tmp,16384)); /*14 */ + alpha_fx=shl(mult(alpha_fx,tmp2),1);/*14+14-15+1 =14 */ + } + L_band_energy_tmp[i] = L_shl(Mult_32_16(L_band_energy_tmp[i],alpha_fx),1);/*Q(Q_band_energy+14-15 +1= Q_band_energy) */ move32(); + } + } + lowband = 3; + move16(); + Ep_avrg_fx = L_deposit_l(0); + Ep_avrgL_fx = L_deposit_l(0); + Ep_peak_fx = L_deposit_l(0); + FOR(i = 0; i < bands_fx; i++) + { + IF(GE_16(i,lowband)) + { + Ep_avrg_fx = L_add(Ep_avrg_fx,Ep_tmp_fx[i]);/*Q15 */ + } + ELSE + { + Ep_avrgL_fx = L_add(Ep_avrgL_fx,L_shr(Ep_tmp_fx[i],1));/*Q12 */ + if(GT_32(Ep_tmp_fx[i],Ep_peak_fx)) + { + Ep_peak_fx = L_add(Ep_tmp_fx[i], 0); /*Q13 */ + } + } + } + L_tmp = Mult_32_16(Ep_peak_fx,28262);/*Q(13+14-15 = 12) 1.725 lowband = 3; */ + L_tmp2 =Mult_32_16(Ep_avrgL_fx,24576);/*Q(12+14-15 = 11) */ + test(); + test(); + IF( GT_32(L_shr(Ep_avrg_fx,2), L_tmp2)&<_32(L_shr(Ep_avrg_fx,4),L_tmp2)&>_32(L_tmp,Ep_avrgL_fx)) + { + adjustFlag = 1; + move16(); + FOR (i = 0; i < lowband; i++) + { + tmp = Calc_inv(Ep_avrgL_fx, &exp); + L_tmp = Mult_32_16(Ep_peak_fx,tmp);/*Q(13+exp-15+4 = exp+2) */ + L_tmp = Mult_32_16(L_tmp,lowband);/*Q(exp+2+0-15 = exp-13) */ + L_tmp = Mult_32_16(L_tmp,18842);/*Q(exp-13+16-16 = exp-13) */ + L_tmp = L_shl(L_tmp,sub(27,exp));/*Q14 0.5 */ + tmp2=extract_l(L_min(L_tmp,19661));/*14 */ + L_tmp = Mult_32_16(L_band_energy_tmp[i],tmp2);/*Q(Q_band_energy+14-15 = Q_band_energy-1) */ + L_band_energy_tmp[i] = L_shl(L_tmp,1); /*Q_band_energy */ move32(); + } + } + hq2_bit_alloc_fx( + L_band_energy_tmp, bands_fx, L_Rk, &bit_budget_fx, p2a_flags_fx, bit_alloc_weight_fx, band_width, + num_bits, hqswb_clas_fx, st_fx->bwidth_fx, *is_transient_fx ); + } + ELSE IF( *is_transient_fx == 0 && EQ_16(inner_frame, L_FRAME16k)) + { + bit_budget_fx = sub(bit_budget_fx,2);/* bits in high bands to indicate the last 2 subbands is allocated bits or not */ + + FOR(i = 0; i < 2; i++) + { + last_bitalloc_max_band[i] = get_next_indice_fx( st_fx, 1 ); + move16(); + } + FOR( i = 0; i < bands_fx; i++ ) + { + Ep_tmp_fx[i] = L_shl(Ep_tmp_fx[i],2); + move32(); + } + IF( EQ_32( st_fx->core_brate_fx, ACELP_13k20 )) + { + lowband = 8; + move16(); + highband = 15; + move16(); + bw_low = sub(band_start[highband],band_start[lowband]); + bw_high = sub(add(band_end[sub(bands_fx,1)],1),band_start[highband]); + } + ELSE + { + lowband = 8; + move16(); + highband = 16; + move16(); + bw_low = sub(band_start[highband],band_start[lowband]); + bw_high = sub(add(band_end[sub(bands_fx,1)],1),band_start[highband]); + } + /* calculate the the low band/high band energy and the variance/avrage of the envelopes */ + enerL_fx = L_deposit_l(0); + enerH_fx = L_deposit_l(0); + Ep_vari_fx = L_deposit_l(0); + Ep_avrg_fx = L_deposit_l(0); + FOR( i = 0; i < bands_fx; i++ ) + { + test(); + IF( GE_16(i,lowband)&&add(sub(i,bands_fx),p2a_bands_fx)<0) + { + Ep_vari_fx = L_add(Ep_vari_fx,L_abs(L_sub(Ep_tmp_fx[i],Ep_tmp_fx[sub(i,1)])));/*Q15 */ + Ep_avrg_fx = L_add(Ep_avrg_fx,Ep_tmp_fx[i]);/*Q15 */ + } + + IF(GE_16(i,highband)) + { + enerH_fx = L_add(enerH_fx,L_shl(Ep_fx[i],2));/*Q0 */ + } + ELSE IF(GE_16(i,lowband)) + { + enerL_fx = L_add(enerL_fx,L_shl(Ep_fx[i],2));/*Q0 */ + } + } + + /* modify the last p2a_bands subbands band_energies */ + Copy32( L_band_energy,L_band_energy_tmp,bands_fx ); /*Q_band_energy */ + L_tmp = L_max(enerH_fx,enerL_fx); + tmp = s_max(bw_low,bw_high); + i = norm_l(L_tmp); + j = norm_s(tmp); + L_tmp = Mult_32_16(L_shl(enerH_fx,i), shl(bw_low,j)); /* i + j -15 */ + L_tmp2 = Mult_32_16(L_shl(enerL_fx,i), shl(bw_high,j)); /*i + j -15 */ + L_tmp2 = L_sub(L_tmp,L_tmp2); + FOR( i = sub(bands_fx,p2a_bands_fx); i < bands_fx; i++ ) + { + test(); + IF( EQ_16(p2a_flags_fx[i],1)||L_tmp2>0) + { + tmp = sub(bands_fx,p2a_bands_fx); + tmp = sub(tmp,lowband);/*Q0 */ + + tmp1 = extract_h(L_shl(Ep_avrg_fx,1));/*Q0 */ + IF(tmp1 != 0) + { + exp = norm_s(tmp1); + tmp1 = shl(tmp1,exp);/*Q(exp) */ + tmp1 = div_s(16384,tmp1);/*Q(15+14-exp = 29-exp) */ + exp = sub(29,exp); + } + ELSE + { + /*when the divisor is zero, happens rarely*/ + tmp1 = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = Mult_32_16(Ep_tmp_fx[i],tmp1);/*Q(15+exp-15 = exp) */ + L_tmp = Mult_32_16(L_tmp,tmp);/*Q(exp+0-15 = exp-15) */ + L_tmp = Mult_32_16(L_tmp,16384);/*Q(exp-15+13-15 = exp-17) */ + L_tmp = L_shl(L_tmp,sub(32,exp));/*Q15 */ + tmp = extract_l(L_min(L_tmp,6554));/*Q15 */ + L_tmp = Mult_32_16(Ep_vari_fx,tmp1);/*Q(15+exp-15 = exp) */ + L_tmp = Mult_32_16(L_tmp,tmp);/*Q(exp+15-15 = exp) */ + L_tmp = L_shl(L_tmp,sub(15,exp));/*Q15 */ + tmp = extract_l(L_shr(L_min(L_tmp,13107),1));/*Q14 */ + + alpha_fx = add(tmp,16384);/*Q14 */ + } + ELSE + { + alpha_fx = 16384; + move16();/*Q14 */ + } + + IF(add(sub(i,bands_fx),p2a_bands_fx) > 0) + { + tmp = sub(bands_fx, p2a_bands_fx); + IF(EQ_16(last_bitalloc_max_band[sub(i, add(tmp, 1))], 1)) + { + tmp = sub(tmp,lowband); + L_tmp = Mult_32_16(Ep_tmp_fx[i],tmp);/*Q(15+0-15 = 0) */ + tmp = Calc_inv(L_shl(L_tmp,16), &exp); + L_tmp = Mult_32_16(Ep_avrg_fx,tmp);/*Q(15+exp-15 = exp) */ + L_tmp = L_shl(L_tmp,sub(14,exp));/*Q14 */ + tmp = extract_l(L_min(L_max(L_tmp,16384),20480));/*Q14 */ + L_tmp = L_mult(alpha_fx,tmp);/*Q(14+14+1=29) */ + alpha_fx = extract_l(L_shr(L_tmp,15)); /*Q14 */ + } + ELSE + { + tmp = sub(tmp,lowband); + + tmp1 = extract_h(L_shl(Ep_avrg_fx,1));/*Q0 */ + IF(tmp1 != 0) + { + exp = norm_s(tmp1); + tmp1 = shl(tmp1,exp);/*Q(exp) */ + tmp1 = div_s(16384,tmp1);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + /*when the divisor is zero, happens rarely*/ + tmp1 = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = Mult_32_16(Ep_tmp_fx[i],tmp1);/*Q(15+exp-15 = exp) */ + L_tmp = Mult_32_16(L_tmp,tmp);/*Q(exp+0-15 = exp-15) */ + L_tmp = L_shl(L_tmp,sub(29,exp));/*Q14 */ + tmp = extract_l(L_min(L_max(L_tmp,13926),16384));/*Q14 */ + L_tmp = L_mult(alpha_fx,tmp);/*Q(14+14+1=29) */ + alpha_fx = extract_l(L_shr(L_tmp,15)); /*Q14 */ + } + } + L_tmp = Mult_32_16(L_band_energy_tmp[i],alpha_fx);/*Q(Q_band_energy+14-15=Q_band_energy-1) */ + L_band_energy_tmp[i] = L_shl(L_tmp,1);/*Q Q_band_energy */ + } + lowband = 6; + move16(); + Ep_avrg_fx = L_deposit_l(0); + Ep_avrgL_fx = L_deposit_l(0); + Ep_peak_fx = L_deposit_l(0); + FOR(i = 0; i < bands_fx; i++) + { + IF(GE_16(i,lowband)) + { + Ep_avrg_fx = L_add(Ep_avrg_fx,Ep_tmp_fx[i]);/*Q15 */ + } + ELSE + { + Ep_avrgL_fx = L_add(Ep_avrgL_fx,Ep_tmp_fx[i]);/*Q15 */ + if(GT_32(Ep_tmp_fx[i],Ep_peak_fx)) + { + Ep_peak_fx = L_add(Ep_tmp_fx[i], 0); /*Q15 */ + } + } + } + + + L_tmp = Mult_32_16(Ep_peak_fx,24576);/*Q(15+13-15 = 13) lowband = 6; */ + L_tmp2 =Mult_32_16(Ep_peak_fx,19661);/*Q(15+14-15 = 14) */ + L_tmp3 =Mult_32_16(Ep_avrgL_fx,24576);/*Q(15+12-15 = 12) */ + + test(); + test(); + test(); + test(); + test(); + IF( (GT_32(L_shr(Ep_avrgL_fx,1), Ep_avrg_fx)&>_32(L_tmp,L_shr(Ep_avrgL_fx,2))&<_32(L_shr(Ep_avrgL_fx,1),L_tmp2))|| + (GT_32(L_shr(Ep_avrg_fx,1), Ep_avrgL_fx) && LT_32(L_shr(Ep_avrg_fx,3),L_tmp3) && GT_32(L_tmp,L_shr(Ep_avrgL_fx,2)) ) ) + { + adjustFlag = 1; + move16(); + FOR (i = 0; i < lowband; i++) + { + tmp = Calc_inv(L_shl(Ep_avrgL_fx,1), &exp); + L_tmp = Mult_32_16(Ep_peak_fx,tmp);/*Q(15+exp-15 = exp) */ + L_tmp = Mult_32_16(L_tmp,lowband);/*Q(exp+0-15 = exp-15) */ + L_tmp = L_shl(L_tmp,sub(28,exp));/*Q14 0.5 */ + tmp = extract_l(L_min(L_tmp,19661));/*//Q14 */ + L_tmp = Mult_32_16(L_band_energy_tmp[i],tmp);/*Q(Q_band_energy+14-15 = Q_band_energy-1) */ + L_band_energy_tmp[i] = L_shl(L_tmp,1); /*Q_band_energy */ move32(); + } + } + + hq2_bit_alloc_fx( + L_band_energy_tmp, bands_fx, L_Rk, &bit_budget_fx, p2a_flags_fx, bit_alloc_weight_fx, band_width, + num_bits, hqswb_clas_fx, st_fx->bwidth_fx, *is_transient_fx ); + } + ELSE IF( EQ_16(st_fx->bwidth_fx, SWB)&&EQ_16(hqswb_clas_fx,HQ_HARMONIC)&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))) + { + hq2_bit_alloc_har_fx( L_band_energy, bit_budget_fx, bands_fx, L_Rk, p2a_bands_fx, L_bwe_br, p2a_flags_fx, band_width ); + } + ELSE + { + hq2_bit_alloc_fx( + L_band_energy, bands_fx, L_Rk, &bit_budget_fx, p2a_flags_fx, bit_alloc_weight_fx, band_width, + num_bits, hqswb_clas_fx, st_fx->bwidth_fx, *is_transient_fx ); + } + + IF( bit_budget_fx < 0 ) + { + st_fx->BER_detect = 1; + move16(); + bit_budget_fx = 0; + move16(); + } + tcq_core_LR_dec_fx( st_fx, /*inp_vector*/inp_vector_fx, bit_budget_fx, bands_fx, band_start, band_width, /*Rk, */L_Rk, npulses_fx, k_sort_fx, + p2a_flags_fx, p2a_bands_fx, last_bitalloc_max_band, inner_frame, adjustFlag, is_transient_fx ); + + /* Denormalize the coded MDCT spectrum */ + mdct_spectrum_denorm_fx( inp_vector_fx, L_y2, band_start, band_end, band_width, L_band_energy, npulses_fx, bands_fx, ld_slope_fx, pd_thresh_fx ); + + /* Apply fine gain to denormalized coded spectrum */ + mdct_spectrum_fine_gain_dec_fx( st_fx, L_y2, band_start, band_end, k_sort_fx, bands_fx, + L_qint, Ngq_fx, gqlevs_fx, gqbits_fx ); + + test(); + test(); + test(); + /* Restore the band information */ + IF( EQ_16(flag_spt_fx, 1)) + { + spt_shorten_domain_band_restore_fx(bands_fx, band_start, band_end, band_width, org_band_start, org_band_end, org_band_width); + } + + Copy32( L_y2, L_y2_org, L_FRAME32k ); + + /* Inject noise into components having relatively low pulse energy per band */ + ni_seed_fx = add(add(add(npulses_fx[0], npulses_fx[1]), npulses_fx[2]), npulses_fx[3]); + Copy32( L_y2, L_y2_ni, band_end[bands_fx-1]+1 ); + + hq2_noise_inject_fx( L_y2_ni, band_start, band_end, band_width, Ep_fx, L_Rk, npulses_fx, ni_seed_fx, bands_fx, 0, bw_low, bw_high, enerL_fx, enerH_fx, + st_fx->last_ni_gain_fx, st_fx->last_env_fx, &st_fx->last_max_pos_pulse_fx, p2a_flags_fx, p2a_bands_fx, + hqswb_clas_fx, st_fx->bwidth_fx, L_bwe_br ); + + test(); + test(); + IF( EQ_16(st_fx->bwidth_fx, SWB)&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))) + { + test(); + IF( EQ_16(hqswb_clas_fx, HQ_NORMAL)||EQ_16(hqswb_clas_fx,HQ_HARMONIC)) + { + preset_hq2_swb_fx( hqswb_clas_fx, band_end, &har_bands_fx, p2a_bands_fx,length_fx, bands_fx, &lowlength_fx, &highlength_fx, L_m ); + + swb_bwe_dec_lr_fx( + st_fx, + L_y2, SWB_BWE_LR_Qs, L_m, + L_bwe_br, + bands_fx, band_start, band_end, + L_band_energy, SWB_BWE_LR_Qbe, + p2a_flags_fx, hqswb_clas_fx, lowlength_fx, highlength_fx, har_bands_fx, + &st_fx->prev_frm_hfe2_fx, &st_fx->prev_stab_hfe2_fx + , band_width, L_y2_ni, &ni_seed_fx + ); + + post_hq2_swb_fx( L_m, lowlength_fx, highlength_fx, hqswb_clas_fx, har_bands_fx, bands_fx, p2a_flags_fx, band_start, band_end, L_y2, npulses_fx ); + + IF( EQ_16(hqswb_clas_fx, HQ_NORMAL)) + { + spt_swb_peakpos_tmp_save_fx(L_y2, bands_fx, band_start, band_end, prev_SWB_peak_pos_tmp_fx); + FOR( k=0; klast_inner_frame_fx, L_FRAME16k)&&st_fx->bws_cnt_fx>0)) + { + k1_fx = sub(bands_fx,2); + if(NE_16(*is_transient_fx,1)) + { + k1_fx = sub(bands_fx,6); + } + L_tmp = L_deposit_l(0); + FOR(i = k1_fx; i < bands_fx; i++) + { + tmp = div_s(1,sub(bands_fx,k1_fx));/*Q15 */ + L_tmp = L_add(L_tmp,Mult_32_16(Ep_tmp_fx[i],tmp));/*Q15 */ + } + st_fx->prev_ener_shb_fx = extract_l(L_shr(L_tmp, 14)); + } + IF( GE_16(st_fx->last_inner_frame_fx,L_FRAME32k)) + { + set16_fx(st_fx->prev_SWB_fenv_fx, st_fx->prev_ener_shb_fx ,SWB_FENV); + } + + updat_prev_frm_fx( L_y2, L_yout, L_bwe_br, length_fx, inner_frame, bands_fx, st_fx->bwidth_fx, *is_transient_fx, hqswb_clas_fx, &st_fx->prev_hqswb_clas_fx, + st_fx->prev_SWB_peak_pos_fx, prev_SWB_peak_pos_tmp_fx, &st_fx->prev_frm_hfe2_fx, &st_fx->prev_stab_hfe2_fx, st_fx->bws_cnt_fx ); + + return; +} + +/*------------------------------------------------------------------------------------ + * small_symbol_dec_tran_fx() + * + * Huffman decoding of differential energies + *--------------------------------------------------------------------------------------*/ + +static Word16 small_symbol_dec_tran_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *qbidx, /* o : output of dequantized differential energy */ + const Word16 bands, /* i : number of bands */ + const Word16 is_transient /* i : transient flag */ +) +{ + Word16 i, bits; + Word16 difidx[BANDS_MAX]; + + /* Decoding differential energies*/ + bits = decode_envelope_indices_fx(st_fx, 0, bands, 0, difidx, LOW_RATE_HQ_CORE_TRAN ,is_transient); + bits = add(bits, BITS_DE_FCOMP); + + /* counting 1 bit for band_energy_huff_coding_mode */ + bits = add(bits, BITS_DE_HMODE); + + /* converting to original values */ + FOR( i=0; i 0 ) + { + *rbits = add(*rbits, s_and(*hufftab, 0xf)); + bit = get_next_indice_fx( st_fx, s_and(*hufftab, 0xf) ); + hufftab += add(shr(*hufftab, 4), bit); + } + + return negate(*hufftab); +} + +static Word16 large_symbol_dec_fx( /* o : bits */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *qbidx, /* o : output of dequantized differential energy */ + const Word16 bands /* i : number of bands */ +) +{ + Word16 i, bits; + Word16 LSB[BANDS_MAX]; + Word16 basic_shift,cntbits,ns2mode; + Word16 pos_outlyer; + Word16 ns2mode0,ns2mode1; + + cntbits = BITS_DE_8SMODE; + move16(); + ns2mode = get_next_indice_fx (st_fx, BITS_DE_8SMODE); + + IF ( ns2mode == 0 ) + { + ns2mode0 = get_next_indice_fx (st_fx, BITS_DE_8SMODE_N0); + ns2mode1 = get_next_indice_fx (st_fx, BITS_DE_8SMODE_N1); + cntbits = add(cntbits, BITS_DE_8SMODE_N0+BITS_DE_8SMODE_N1); + + IF ( ns2mode0 == 0 ) + { + IF ( EQ_16(ns2mode1, 1)) + { + pos_outlyer = get_next_indice_fx (st_fx, BITS_DE_8SPOS); + cntbits = add(cntbits, BITS_DE_8SPOS); + qbidx[pos_outlyer] = sub(get_next_indice_fx (st_fx, BITS_ABS_ENG), ABS_ENG_OFFSET); + move16(); + cntbits = add(cntbits, BITS_ABS_ENG); + } + ELSE + { + pos_outlyer = -1; + move16(); + } + + FOR( i=0; i Qbe(Q14) */ + } + + IF (is_transient_fx) + { + reverse_transient_frame_energies_fx( L_band_energy, bands_fx ); + } + + return( deng_bits ); +} + + +/*--------------------------------------------------------------------------* + * p2a_threshold_dequant() + * + * + *--------------------------------------------------------------------------*/ + +static Word16 p2a_threshold_dequant_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *p2a_flags, /* o : tonaly indicator */ + const Word16 bands, /* i : number of subbands */ + const Word16 p2a_bands /* i : number of subbnads for computing tonality */ +) +{ + Word16 j, k; + + j = sub(bands, p2a_bands); + FOR( k = 0; k < j; k++ ) + { + p2a_flags[k] = 1; + move16(); + } + + j = 0; + move16(); + FOR( k = sub(bands, p2a_bands); k < bands; k++ ) + { + p2a_flags[k] = get_next_indice_fx( st_fx, 1 ); + move16(); + j = add(j, 1); + } + + return( j ); +} + + +/*--------------------------------------------------------------------------* + * mdct_spectrum_fine_gain_dec() + * + * + *--------------------------------------------------------------------------*/ + +static void mdct_spectrum_fine_gain_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word32 L_y2[], /* i/o: Q12 : decoded spectrum */ + const Word16 band_start[], /* i : Q0 : table of start freq for every subband */ + const Word16 band_end[], /* i : Q0 : table of end freq for every subband */ + const Word16 k_sort[], /* i : Q0 : sort table by band_energy */ + const Word16 bands, /* i : Q0 : nubmber of subbands */ + const Word32 L_qint, /* i : Q0 : */ + const Word16 Ngq, /* i : Q0 : */ + const Word16 gqlevs, /* i : Q0 : quantized level */ + const Word16 gqbits /* i : Q0 : quantized bits */ +) +{ + Word16 i, k, imin_fx; + + Word16 delta_fx, Qdelta; + Word32 L_delta; + Word32 L_q; + + Word16 gain_table_fx[MAX_GQLEVS]; + Word16 Qgt; + Word16 gamma_fx; /* Q14 */ + + Word16 exp_normn, exp_normd; + + Word32 L_temp; + Word16 temp_lo_fx, temp_hi_fx; + + /* Fine gain quantization on only the most significant energy bands */ + + exp_normn = norm_l(L_qint); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_s(gqlevs); + delta_fx = div_l(L_shl(L_qint, exp_normn), shl(gqlevs, exp_normd)); + Qdelta = add(sub(exp_normn, exp_normd), 28); /* 29+exp_normn-(exp_normd)-1; */ + L_delta = L_shl(L_deposit_h(delta_fx), sub(13, Qdelta)); + + L_q = L_shr(L_sub(L_delta, L_qint), 1); + + FOR ( i=0; i Q14 */ move16(); + } + + FOR( k = sub(bands, Ngq); k < bands; k++ ) + { + imin_fx = get_next_indice_fx( st_fx, gqbits ); + + /*gamma = gain_table[imin]; */ + gamma_fx = gain_table_fx[imin_fx]; + move16(); + + FOR (i = band_start[k_sort[k]]; i <= band_end[k_sort[k]]; i++) + { + /* This IF statement for keeping same mantissa evenif y2 is plus or minus */ + IF ( L_y2[i] >= 0x0 ) + { + L_y2[i] = L_shl(Mpy_32_16_1(L_y2[i], gamma_fx), 1); + } + ELSE + { + L_y2[i] = L_negate(L_shl(Mpy_32_16_1(L_abs(L_y2[i]), gamma_fx), 1)); + } + } + } + + return; +} diff --git a/lib_dec/igf_dec.c b/lib_dec/igf_dec.c new file mode 100644 index 0000000..227f979 --- /dev/null +++ b/lib_dec/igf_dec.c @@ -0,0 +1,1735 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include +#include "options.h" +#include "stl.h" +#include "prot_fx.h" +#include "cnst_fx.h" +#include "stat_dec_fx.h" +#include "basop_util.h" + +/**********************************************************************/ /* +get scalefactor of an Word32 array with condition +**************************************************************************/ +static Word16 IGF_getScaleFactor32Cond( /**< out: Q0 | measured headroom in range [0..31], 0 if all x[i] == 0 */ + const Word16 *cond, /**< in: Q0 | array conating the condition */ + const Word32 *x, /**< in: Q31 | array containing 32-bit data */ + const Word16 len_x /**< in: Q0 | length of the array to scan */ +) +{ + Word16 i; + Word16 i_min; + Word16 i_max; + Word32 x_min; + Word32 x_max; + Word32 tmp32; + + + x_max = 0; + move32(); + x_min = 0; + move32(); + FOR (i = 0; i < len_x; i++) + { + tmp32 = L_add(x[i], 0); /*L_and(x[i], cond[i]);*/ + + if (cond[i] == 0) + { + tmp32 = L_deposit_h(0); + } + + + if (tmp32>= 0) + { + x_max = L_max(x_max, tmp32); + } + if (tmp32< 0) + { + x_min = L_min(x_min, tmp32); + } + } + + i_max = 0x20; + move16(); + i_min = 0x20; + move16(); + + if (x_max != 0) + { + i_max = norm_l(x_max); + } + if (x_min != 0) + { + i_min = norm_l(x_min); + } + + i = s_and(s_min(i_max, i_min), 0x1F); + + return i; +} + +/**********************************************************************/ /* +measures TCX noise +**************************************************************************/ +static Word16 IGF_replaceTCXNoise_1( /**< out: Q0 | number of noise bands */ + const Word32 *in, /**< in: Q31 | MDCT spectrum */ + Word16 s_l, /**< in: Q0 | noise headroom */ + const Word16 *TCXNoise, /**< in: | tcx noise indicator vector */ + const Word16 start, /**< in: Q0 | start MDCT subband index */ + const Word16 stop, /**< in: Q0 | stop MDCT subband index */ + Word32 *totalNoiseNrg /**< out: | measured noise energy */ +) +{ + Word16 sb; + Word16 tmp16; + Word16 noise; + Word32 nE; + + + tmp16 = 0; + move16(); + noise = 0; + move16(); + s_l = sub(s_l, 5); + nE = 0; + move32(); + + FOR (sb = start; sb < stop; sb++) + { + if (TCXNoise[sb]) + { + tmp16 = extract_h(L_shl(in[sb], s_l)); + } + if (TCXNoise[sb]) + { + nE = L_mac(nE, tmp16, tmp16); + } + if (TCXNoise[sb]) + { + noise = add(noise, 1); + } + } + + *totalNoiseNrg = nE; + move32(); + + return noise; +} + +/**********************************************************************/ /* +replaces TCX noise +**************************************************************************/ +static void IGF_replaceTCXNoise_2(Word32 *in, /**< in/out: | MDCT spectrum */ + const Word16 *TCXNoise, /**< in: Q0 | tcx noise indicator vector */ + const Word16 start, /**< in: Q0 | start MDCT subband index */ + const Word16 stop, /**< in: Q0 | stop MDCT subband index */ + Word32 totalNoiseNrg, /**< in: | measured noise energy */ + const Word16 s_l, /**< in: Q0 | noise headroom */ + Word16 *nfSeed /**< in: | random generator noise seed */ + ) +{ + Word16 sb; + Word16 g; + Word16 val; + Word32 rE; + Word32 L_tmp; + + + val = 0; + move16(); + rE = 0; + move32(); + + FOR (sb = start; sb < stop; sb++) + { + if (TCXNoise[sb]) + { + val = Random(nfSeed); + } + if (TCXNoise[sb]) + { + in[sb] = L_deposit_l(val); + } + if (TCXNoise[sb]) + { + val = shr(val, 5); + } + if (TCXNoise[sb]) + { + rE = L_mac(rE, val, val); + } + } + + totalNoiseNrg = L_shr(totalNoiseNrg, 1); + + + /* make sure that rE is never 0 */ + if (rE == 0) + { + rE = L_add(totalNoiseNrg, 0); /* save move32() -> use L_add(x, 0) = x; */ + } + + /* if totalNoiseNrg == 0, then rE must be at least 0x00010000, otherwise division by 0 will occur */ + if (totalNoiseNrg == 0) + { + rE = L_max(rE, 0x00010000); + } + + /* make sure that rE is never smaller than totalNoiseNrg */ + L_tmp = L_sub(rE, totalNoiseNrg); + if (L_tmp < 0) + { + rE = totalNoiseNrg; /* save move32() -> use L_add(x, 0) = x; */ + move32(); + } + + + g = getSqrtWord32(L_mult(divide3232(totalNoiseNrg, rE), 8192/*1.0f / 4.0f Q15*/)); + g = shl(g, 1); + + FOR (sb = start; sb < stop; sb++) + { + if (TCXNoise[sb]) + { + in[sb] = L_shr(L_mult(extract_l(in[sb]), g), s_l); + move32(); + } + } + +} + +/**********************************************************************/ /* +reads whitening levels +**************************************************************************/ +static void IGF_decode_whitening_level(Decoder_State_fx *st, /**< in: | decoder state */ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData, /**< in: | instance handle of IGF Deccoder */ + const Word16 p /**< in: Q0 | tile index, p = [0, 3] */ + ) +{ + Word16 tmp; + + + tmp = get_next_indice_fx(st, 1); + + IF (tmp == 0) + { + hPrivateData->currWhiteningLevel[p] = IGF_WHITENING_MID; + move16(); + + return; + } + + tmp = get_next_indice_fx(st, 1); + hPrivateData->currWhiteningLevel[p] = IGF_WHITENING_STRONG; + move16(); + + if (tmp == 0) + { + hPrivateData->currWhiteningLevel[p] = IGF_WHITENING_OFF; + move16(); + } + +} + +/**********************************************************************/ /* +reads flattening trigger +**************************************************************************/ +static void IGF_decode_temp_flattening_trigger(Decoder_State_fx *st, /**< in: | decoder state */ + IGF_DEC_INSTANCE_HANDLE hInstance /**< in: | instance handle of IGF Deccoder */ + ) +{ + hInstance->flatteningTrigger = get_next_indice_fx(st, 1); +} + +/**********************************************************************/ /* +set power spectrum values to zero, needed for energy calculation +**************************************************************************/ +static void IGF_setLinesToZero(const Word16 startLine, /**< in: Q0 | start MDCT subband index */ + const Word16 stopLine, /**< in: Q0 | stop MDCT subband index */ + const Word32 *pSpectralData, /**< in: | original MDCT spectrum */ + Word32 *pPowerSpecIGF /**< in/out: | prepared IGF energy spectrum */ + ) +{ + Word16 i; + + + /* set energy values in the IGF "power spectrum" to 0, + if there is content in the original MDCT spectrum */ + FOR (i = startLine; i < stopLine; i++) + { + if (pSpectralData[i] != 0) + { + pPowerSpecIGF[i] = L_deposit_l(0); + } + } + +} + +/**********************************************************************/ /* +prepare IGF spectrum +**************************************************************************/ +static void IGF_prep(IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData, /**< in: | IGF private data handle */ + const Word16 igfGridIdx, /**< in: Q0 | in case of CELP->TCX switching, use 1.25 framelength */ + const Word16 *TCXNoise, /**< in: Q0 | TCX noise vector */ + Word32 *igf_spec, /**< in: Q31 | prepared IGF spectrum */ + Word16 *igf_spec_e, /**< in: | array exponents of igf_spec, one exponent per tile */ + const Word32 *src_spec, /**< in: | source spectrum */ + const Word16 src_spec_e, /**< in: | exponent of src_spec, whitening off */ + const Word16 specMed_e /**< in: | exponent of medium flattening level */ + ) +{ + H_IGF_GRID hGrid; + H_IGF_INFO hInfo; + Word16 i; + Word16 tb; + Word16 sfb; + Word16 nTiles; + Word16 n_noise_bands; + Word16 n_noise_bands_off; + Word16 strt_cpy; + Word16 startLine; + Word16 minSrcSubband; + Word16 tile_idx; + Word32 totalNoiseNrg; + Word32 totalNoiseNrg_off; + const Word32 *sel_spec; + + + /* initialize variables */ + hInfo = &hPrivateData->igfInfo; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + n_noise_bands = hPrivateData->n_noise_bands; + move16(); + n_noise_bands_off = hPrivateData->n_noise_bands_off; + move16(); + totalNoiseNrg = hPrivateData->totalNoiseNrg; + move32(); + totalNoiseNrg_off = hPrivateData->totalNoiseNrg_off; + move32(); + nTiles = hGrid->nTiles; + move16(); + startLine = hGrid->startLine; + move16(); + minSrcSubband = hGrid->minSrcSubband; + move16(); + tile_idx = 0; + move16(); + + FOR (tile_idx = 0; tile_idx < nTiles; tile_idx++) + { + strt_cpy = hGrid->sbWrap[tile_idx]; + move16(); + + /* strong whitening detected */ + IF (EQ_16(IGF_WHITENING_STRONG, hPrivateData->currWhiteningLevel[tile_idx])) + { + Word32 abs_sum; + abs_sum = 0; + move32(); + + FOR(i = strt_cpy; i < hGrid->startLine; i++) + { + abs_sum = L_add(abs_sum, L_abs(src_spec[i])); + } + + /* fill igf_spec with random noise */ + tb = hGrid->swb_offset[hGrid->sfbWrap[tile_idx]]; + move16(); + + IF (abs_sum != 0) + { + FOR (i = strt_cpy; i < startLine; i++) + { + igf_spec[tb++] = L_deposit_l(Random(&hInfo->nfSeed)); /* 31Q0, fill LSBs */ + } + } + ELSE + { + FOR (i = strt_cpy; i < startLine; i++) + { + igf_spec[tb++] = 0; + move32(); + } + } + + /* set exponent of the current tile, random noise is 31Q0 */ + igf_spec_e[tile_idx] = 31; + move16(); + } + ELSE + { + /* medium whitening detected */ + IF (EQ_16(IGF_WHITENING_MID, hPrivateData->currWhiteningLevel[tile_idx])) + { + IF (n_noise_bands != 0) + { + IGF_replaceTCXNoise_2(igf_spec, + TCXNoise, + + minSrcSubband, + startLine, + totalNoiseNrg, + hPrivateData->headroom_TCX_noise_white, + &hInfo->nfSeed); + } + + /* selected source spectrum is igf_spec, igf_spec contains the whitened signal in the core region */ + sel_spec = igf_spec; + move16(); + + /* set exponent of the current tile */ + igf_spec_e[tile_idx] = specMed_e; + move16(); + } + /* off whitening detectded */ + ELSE + { + IF (n_noise_bands_off != 0) + { + IGF_replaceTCXNoise_2(hPrivateData->pSpecFlat, + TCXNoise, + minSrcSubband, + startLine, + totalNoiseNrg_off, + hPrivateData->headroom_TCX_noise, + &hInfo->nfSeed); + + } + /* selected source spectrum is pSpecFlat, pSpecFlat contains the signal before the LPC reshaping */ + sel_spec = src_spec; + move16(); + + /* set exponent of the current tile */ + igf_spec_e[tile_idx] = src_spec_e; + move16(); + } + /* generate the raw IGF spectrum out if the selected spectrum */ + FOR (sfb = hGrid->sfbWrap[tile_idx]; sfb < hGrid->sfbWrap[tile_idx + 1]; sfb++) + { + FOR (tb = hGrid->swb_offset[sfb]; tb < hGrid->swb_offset[sfb + 1]; tb++) + { + igf_spec[tb] = sel_spec[strt_cpy]; + move32(); + strt_cpy = add(strt_cpy, 1); + } + } + } + } + +} + +/**********************************************************************/ /* +calculates IGF energies +**************************************************************************/ +static void IGF_calc(IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData, /**< in: | IGF private data handle */ + const Word16 igfGridIdx, /**< in: Q0 | in case of CELP->TCX switching, use 1.25 framelength */ + const Word32 *spectrum, /**< in: Q31 | MDCT spectrum */ + const Word16 spectrum_e, /**< in: | exponent of pSpectralData */ + Word32 *igf_spec, /**< in: Q31 | prepared IGF spectrum */ + Word16 *igf_spec_e /**< in: | array exponents of igf_spec, one exponent per tile */ + ) +{ + H_IGF_GRID hGrid; + Word16 i; + Word32 *igf_pN; /* Q31 | processed energy */ + Word16 *igf_pN_e; /* | exponents of igf_pN, one for each entry of igf_pN */ + Word32 *igf_sN; /* Q31 | survived energy */ + Word16 *igf_sN_e; /* | exponents of igf_sN, one for each entry of igf_sN */ + Word32 squaredSpectra[IGF_MAX_GRANULE_LEN]; /* Q31 | MDCT^2 spectra */ + Word16 squaredSpectra_e[IGF_MAX_TILES]; /* | exponents of squaredSpectra, one exponent per tile! */ + + + /* initialize variables */ + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + igf_pN = hPrivateData->igf_pN; + igf_pN_e = hPrivateData->igf_pN_e; + igf_sN = hPrivateData->igf_sN; + igf_sN_e = hPrivateData->igf_sN_e; + + set32_fx(squaredSpectra, 0, IGF_MAX_GRANULE_LEN); + set16_fx(squaredSpectra_e, 0, IGF_MAX_TILES); + + /* square the original spectrum */ + IGFCommonFuncsMDCTSquareSpec(hGrid->startLine, + hGrid->stopLine, + spectrum, + spectrum_e, + squaredSpectra, + squaredSpectra_e, + 0); + + /* calculate the energy per SFB of the survied subbands */ + IGFCommonFuncsCalcSfbEnergyPowerSpec(hGrid->startSfb, + hGrid->stopSfb, + hGrid->swb_offset, + squaredSpectra, + squaredSpectra_e, + igf_sN, + igf_sN_e); + + /* loop over tiles, every tile has his own exponent! */ + FOR (i = 0; i < hGrid->nTiles; i++) + { + /* square the prepared IGF spectrum */ + IGFCommonFuncsMDCTSquareSpec(hGrid->tile[i], + hGrid->tile[i + 1], + igf_spec, + igf_spec_e[i], + squaredSpectra, + &squaredSpectra_e[i], + 0); + + /* set all squared values to 0, if the core contains survied lines */ + IGF_setLinesToZero(hGrid->tile[i], + hGrid->tile[i + 1], + spectrum, + squaredSpectra); + + /* calculate the energy per SFB of the processed subbands */ + IGFCommonFuncsCalcSfbEnergyPowerSpec(hGrid->sfbWrap[i], + hGrid->sfbWrap[i + 1], + hGrid->swb_offset, + squaredSpectra, + &squaredSpectra_e[i], + igf_pN, + igf_pN_e); + } + +} + +/**********************************************************************/ /* +apply IGF +**************************************************************************/ +static void IGF_appl(IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData, /**< in: | IGF private data handle */ + const Word16 igfGridIdx, /**< in: Q0 | in case of CELP->TCX switching, use 1.25 framelength */ + Word32 *spectrum, /**< in: Q31 | MDCT spectrum */ + Word16 *spectrum_e, /**< in: | exponent of pSpectralData */ + const Word32 *igf_spec, /**< in: Q31 | prepared IGF spectrum */ + const Word16 *igf_spec_e, /**< in: | array exponents of igf_spec, one exponent per tile */ + Word32 *virtualSpec, /**< out:Q31 | virtual IGF spectrum, used for temp flattening */ + Word16 *virtualSpec_e, /**< out: | exponent of virtualSpec */ + Word16 *flag_sparse /**< out: Q0 | temp flattening indicator */ + ) +{ + H_IGF_GRID hGrid; + Word16 i; + Word16 tb; + Word16 sfb; + Word16 shift; + Word16 s; + Word16 s_sfb; + Word16 start_sfb; + Word16 stop_sfb; + Word16 sfb_p1; + Word16 sfb_m1; + Word16 hopsize; + Word16 sum; + Word16 tileIdx; + Word16 width; /* Q0 | width of the current sfb */ + Word16 width_e; /* | exponent of widthent sfb, initialized as 15! */ + Word16 gFactor; /* 1Q14 | general SCF adaption */ + Word16 fFactor; /* 1Q14 | first SCF adaption */ + Word16 lFactor; /* 1Q14 | last SCF adaption */ + Word16 w0; /* Q15 | float value: 0.201f */ + Word16 w1; /* Q15 | float value: 0.389f */ + Word16 w2; /* Q15 | float value: 0.410f */ + Word16 dE; /* Q31 | energy below igfBgn */ + Word16 dE_e ; /* | exponent of dE */ + Word16 gn; /* Q0 | gain read from bitstream + processing */ + Word16 gn_e; /* | exponent of gn */ + Word16 maxGain_e; /* | maximal gain exponent over sfbs */ + Word16 tmp; + Word16 tmp_e; + Word16 tmp_loop; + Word32 L_tmp; + Word16 L_tmp_e; + Word32 L_tmp2; + Word32 sNlocal; + Word16 sNlocal_e; + Word32 dNlocal; + Word16 dNlocal_e; + Word32 E; + Word16 E_e; + Word32 *sN; + Word16 *sN_e; + Word32 *pN; + Word16 *pN_e; + Word16 gain[IGF_MAX_SFB]; + Word16 gain_e[IGF_MAX_SFB]; + Word16 dN[IGF_MAX_SFB + 1]; + Word16 dN_e[IGF_MAX_SFB + 1]; + Word16 dS[IGF_MAX_SFB]; + Word16 dS_e[IGF_MAX_SFB]; + Word32 energyTmp[24]; + Word32 L_c; + Word16 Hr; + + + /* initialize variables */ + w0 = 6586; + move16(); + w1 = 12747; + move16(); + w2 = 13435; + move16(); + dE = 0; + move16(); + dE_e = 0; + move16(); + tmp = 0; + move16(); + s = 0; + move16(); + tmp_e = 0; + move16(); + gn = 0; + move16(); + gn_e = 0; + move16(); + maxGain_e = 0; + move16(); + L_tmp_e = 0; + move16(); + dNlocal_e = 0; + move16(); + L_tmp = 0; + move32(); + dNlocal = 0; + move32(); + + set16_fx(gain, 0, IGF_MAX_SFB); + set16_fx(gain_e, 0, IGF_MAX_SFB); + set16_fx(dN, 0, add(IGF_MAX_SFB,1)); + set16_fx(dN_e, 0, add(IGF_MAX_SFB,1)); + set16_fx(dS, 0, IGF_MAX_SFB); + set16_fx(dS_e, 0, IGF_MAX_SFB); + set32_fx(energyTmp, 0, 24); + + /* more inits */ + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + sN = hPrivateData->igf_sN; + sN_e = hPrivateData->igf_sN_e; + pN = hPrivateData->igf_pN; + pN_e = hPrivateData->igf_pN_e; + start_sfb = hGrid->startSfb; + move16(); + stop_sfb = hGrid->stopSfb; + move16(); + gFactor = hGrid->gFactor; + move16(); + fFactor = hGrid->fFactor; + move16(); + lFactor = hGrid->lFactor; + move16(); + + /* reset virtual spec */ + set16_fx(flag_sparse, 0, N_MAX_TCX-IGF_START_MN); + set32_fx(virtualSpec, 0, N_MAX_TCX-IGF_START_MN); + *virtualSpec_e = *spectrum_e; + move16(); + + /* collect energy below hGrid->startLine: */ + tmp = sub(hGrid->startLine, 24); + IGFCommonFuncsMDCTSquareSpec(tmp, + hGrid->startLine, + spectrum, + *spectrum_e, + energyTmp, + &dE_e, + negate(tmp)); + + L_c = 0; + move32(); + FOR (tb = 0; tb < 24; tb++) + { + Carry = 0; + L_tmp = L_add_c(L_tmp, energyTmp[tb]); + Overflow = 0; + L_c = L_macNs(L_c, 0, 0); + } + L_tmp = norm_llQ31(L_c, L_tmp, &shift); + /* float: dE = (float)sqrt(dE / 24.f); basop: */ + shift = add(sub(shift, 4), dE_e); /* x/24 = (x >> 4) * 1/1.5 */ + dE = Sqrt16norm(extract_h(L_tmp), &shift); + dE = mult_r(dE, 26755/*0.81649658092772603273242802490196f Q15*/); /* 0.81649658092772603273242802490196f = sqrt(1/1.5)) */ + dE_e = shift; + move16(); + + /* select correct hopsize for envelope refinement */ + hopsize = 2; + move16(); + if (EQ_16(hPrivateData->currWhiteningLevel[0], IGF_WHITENING_OFF)) + { + hopsize = 4; + move16(); + } + if (EQ_16(hPrivateData->currWhiteningLevel[0], IGF_WHITENING_STRONG)) + { + hopsize = 1; + move16(); + } + hopsize = s_min(hopsize, hPrivateData->igfInfo.maxHopsize); + + IF (hopsize > 1) + { + FOR (sfb = start_sfb; sfb < stop_sfb; sfb += hopsize) + { + tmp_loop = s_min(add(sfb, hopsize), stop_sfb); + FOR (tb = add(sfb, 1); tb < tmp_loop; tb++) + { + sN[sfb] = BASOP_Util_Add_Mant32Exp(sN[sfb], + sN_e[sfb], + sN[tb], + sN_e[tb], + &sN_e[sfb]); + move32(); + pN[sfb] = BASOP_Util_Add_Mant32Exp(pN[sfb], + pN_e[sfb], + pN[tb], + pN_e[tb], + &pN_e[sfb]); + move32(); + sN[tb] = L_deposit_l(0); + pN[tb] = L_deposit_l(0); + } + } + } + + /* IGF_rescale_SCF */ + IF (hGrid->infoIsRefined != 0) + { + FOR (sfb = start_sfb; sfb < stop_sfb; sfb += 2) + { + /* calculate and normalize the width of the current sfb */ + width = sub(hGrid->swb_offset[sfb + 2], hGrid->swb_offset[sfb]); + shift = norm_s(width); + width = shl(width, shift); + width_e = sub(15, shift); /* initial value of width_e is 15, -> width = 15Q0 */ + + /* float: gn = 0.25f * igf_curr - 4.f; basop: */ + gn = hPrivateData->igf_curr[shr(sfb,1)]; + move16(); + move16(); + gn_e = 13; /* set exponent of igf_curr to 13 = 15 - 2; -> igf_curr = igf_curr * 0.25, virtual division by 4 */ + gn = sub(gn, 16); /* 13Q2 | 4 = 16 * 2^(-15 + 13); ("4" has same exponent as igf_curr now) */ + + /* float: tmp = pow(2.f, gn); basop: */ + L_tmp = BASOP_util_Pow2(L_deposit_h(gn), gn_e, &L_tmp_e); + + /* float: tmp = tmp * tmp; basop: */ + tmp = round_fx(L_tmp); + L_tmp = L_mult(tmp, tmp); + L_tmp_e = add(L_tmp_e, L_tmp_e); + + /* get sNlocal | float: sNlocal = sN[ sfb ] + sN[ sfb+ 1 ]; basop: */ + sNlocal = BASOP_Util_Add_Mant32Exp(sN[sfb], + sN_e[sfb], + sN[sfb + 1], + sN_e[sfb + 1], + &sNlocal_e); + + /* float: sNlocal /= width; basop: */ + shift = sub(norm_l(sNlocal), 1); /* leave MSB empty, so in the division sNlocal is always smaller than width */ + sNlocal = L_deposit_h(div_s(extract_h(L_shl(sNlocal, shift)), width)); + sNlocal_e = sub(sub(sNlocal_e, shift), width_e); + + /* float: tmp = max(0.001 * sNlocal, tmp - sNlocal); basop: */ + L_tmp = BASOP_Util_Add_Mant32Exp(L_tmp, + L_tmp_e, + L_negate(sNlocal), + sNlocal_e, + &L_tmp_e); /* float: tmp = tmp - sNlocal */ + + /* max(0.001 * sNlocal, L_tmp) */ + /* Build a threshold and compare with L_tmp. + Build negated threshold and compare with negated L_tmp to cover also fullscale L_tmp case */ + BASOP_SATURATE_WARNING_OFF + L_tmp2 = L_shl(L_negate(Mpy_32_16_1(sNlocal, 33/*0.001f Q15*/)), sub(sNlocal_e, L_tmp_e)); + L_tmp2 = L_sub(L_tmp2, L_negate(L_tmp)); + BASOP_SATURATE_WARNING_ON + + IF (L_tmp2 < 0) + { + L_tmp = Mpy_32_16_1( sNlocal,33/*0.001f Q15*/); + L_tmp_e = sNlocal_e; + move16(); + } + + /* calc square root of L_tmp and store result in dN */ + L_tmp = Sqrt32(L_tmp, &L_tmp_e); + dN[sfb] = round_fx(L_tmp); + dN_e[sfb] = L_tmp_e; + move16(); + dN[sfb+1] = dN[sfb]; + move16(); + dN_e[sfb+1] = dN_e[sfb]; + move16(); + } + } + ELSE + { + FOR (sfb = start_sfb; sfb < stop_sfb; sfb++) + { + /* calculate and normalize the width of the current sfb */ + width = sub(hGrid->swb_offset[sfb + 1], hGrid->swb_offset[sfb]); + shift = norm_s(width); + width = shl(width, shift); + width_e = sub(15, shift); /* initial value of width_e is 15, -> width = 15Q0 */ + + /* float: gn = 0.25f * igf_curr - 4.f; basop: */ + gn = hPrivateData->igf_curr[sfb]; + move16(); + move16(); + gn_e = 13; /* set exponent of igf_curr to 13 = 15 - 2; -> igf_curr = igf_curr * 0.25, virtual division by 4 */ + gn = sub(gn, 16); /* 13Q2 | 4 = 16 * 2^(-15 + 13); ("4" has same exponent as igf_curr now) */ + + /* float: tmp = pow(2.f, gn); basop: */ + L_tmp = BASOP_util_Pow2(L_deposit_h(gn), gn_e, &L_tmp_e); + + /* float: tmp = tmp * tmp; basop: */ + tmp = round_fx(L_tmp); + L_tmp = L_mult(tmp, tmp); + L_tmp_e = add(L_tmp_e, L_tmp_e); + + /* get sNlocal */ + sNlocal = sN[sfb]; + move32(); + sNlocal_e = sN_e[sfb]; + move16(); + + /* float: sNlocal /= width; basop: */ + shift = sub(norm_l(sNlocal), 1); /* leave MSB empty, so in the division sNlocal is always smaller than width */ + sNlocal = L_deposit_h(div_s(extract_h(L_shl(sNlocal, shift)), width)); + sNlocal_e = sub(sub(sNlocal_e, shift), width_e); + + /* float: tmp = max(0.001 * sNlocal, tmp - sNlocal); basop: */ + L_tmp = BASOP_Util_Add_Mant32Exp(L_tmp, + L_tmp_e, + L_negate(sNlocal), + sNlocal_e, + &L_tmp_e); /* float: tmp = tmp - sNlocal */ + + /* max(0.001 * sNlocal, L_tmp) */ + /* Build a threshold and compare with L_tmp. + Build negated threshold and compare with negated L_tmp to cover also fullscale L_tmp case */ + BASOP_SATURATE_WARNING_OFF + L_tmp2 = L_shl(L_negate(Mpy_32_16_1(sNlocal, 33/*0.001f Q15*/)), sub(sNlocal_e,L_tmp_e)); + L_tmp2 = L_sub(L_tmp2, L_negate(L_tmp)); + BASOP_SATURATE_WARNING_ON + + IF (L_tmp2 < 0 ) + { + L_tmp = Mpy_32_16_1(sNlocal,33/*0.001f Q15*/); + L_tmp_e = sNlocal_e; + } + + /* calc square root of L_tmp and store result in dN */ + L_tmp = Sqrt32(L_tmp, &L_tmp_e); + dN[sfb] = round_fx(L_tmp); + dN_e[sfb] = L_tmp_e; + move16(); + } + } + + dS[start_sfb] = dN[start_sfb]; + move16(); + dS_e[start_sfb] = dN_e[start_sfb]; + move16(); + + /* first value with adaption to core energy: */ + tmp_e = BASOP_Util_Add_MantExp(dE, + dE_e, + negate(dN[start_sfb]), + dN_e[start_sfb], + &tmp); /* float: tmp = dE - dN[start_sfb] */ + IF (tmp < 0) + { + /* float: dS[start_sfb] = dN[start_sfb] + fFactor * (dE-dN[start_sfb]); basop: */ + L_tmp = L_mult(fFactor, tmp); + L_tmp_e = add(tmp_e, 1); /* 1Q14 | fFactor is 1Q14 */ + dS_e[start_sfb] = BASOP_Util_Add_MantExp(dN[start_sfb], + dN_e[start_sfb], + round_fx(L_tmp), + L_tmp_e, + &dS[start_sfb]); + move16(); + } + /* last value with less energy: */ + dS[stop_sfb - 1] = mult_r(lFactor, dN[stop_sfb - 1]); + move16(); + move16(); + dS_e[stop_sfb - 1] = add(dN_e[stop_sfb - 1], 1); /* 1Q14 | lFactor is 1Q14 */ + + sfb_p1 = add(start_sfb, 1); + sfb_m1 = sub(stop_sfb, 1); + test(); + IF (hGrid->infoIsRefined != 0 && EQ_16(hopsize, 1)) + { + /* apply filter to absolute energy values: */ + FOR (sfb = sfb_p1; sfb < sfb_m1; sfb++) + { + /* float: dS[sfb] = w0 * dN[sfb-1] + w1 * dN[sfb+0] + w2 * dN[sfb+1]; basop: */ + L_tmp = L_mult(w0, dN[sfb - 1]); + dS[sfb] = round_fx(L_tmp); + move16(); + dS_e[sfb] = dN_e[sfb-1]; /* w0 is Q15, so no need to add an exponent */ + L_tmp = L_mult(w1, dN[sfb]); + dS_e[sfb] = BASOP_Util_Add_MantExp(dS[sfb], + dS_e[sfb], + round_fx(L_tmp), + dN_e[sfb], /* w1 is Q15, so no need to add an exponent */ + &tmp); + move16(); + dS[sfb] = tmp; + move16(); + L_tmp = L_mult(w2, dN[sfb + 1]); + dS_e[sfb] = BASOP_Util_Add_MantExp(dS[sfb], + dS_e[sfb], + round_fx(L_tmp), + dN_e[sfb + 1], /* w2 is Q15, so no need to add an exponent */ + &tmp); + move16(); + dS[sfb] = tmp; + move16(); + } + } + ELSE + { + FOR (sfb = sfb_p1; sfb < sfb_m1; sfb++) + { + dS[sfb] = dN[sfb]; + move16(); + dS_e[sfb] = dN_e[sfb]; + move16(); + } + } + + Hr = 0; + move16(); + tileIdx = -1; + move16(); + FOR (sfb = start_sfb; sfb < stop_sfb; sfb += hopsize) + { + E = 0; + move32(); + E_e = 0; + move16(); + sum = 0; + move16(); + + FOR (tb = 0; tb < hopsize; tb++) + { + /* calculate of the current sfb width */ + width = sub(hGrid->swb_offset[s_min(add(add(sfb, tb), 1), stop_sfb)], /* 15Q0 | width is Q0 */ + hGrid->swb_offset[s_min(add(sfb, tb), stop_sfb)]); + + tmp = dS[s_min(add(sfb, tb), sub(stop_sfb, 1))]; + tmp_e = dS_e[s_min(add(sfb, tb), sub(stop_sfb, 1))]; + + /* square tmp */ + L_tmp = L_mult(tmp, tmp); + L_tmp_e = add(tmp_e, tmp_e); + + /* mult L_tmp times width */ + L_tmp = L_mult(round_fx(L_tmp), width); + L_tmp_e = add(L_tmp_e, 15); /* 15Q0 | width is Q0 */ + + /* calculate resulting energy */ + E = BASOP_Util_Add_Mant32Exp(E, + E_e, + L_tmp, + L_tmp_e, + &E_e); + sum = add(sum, width); /* 15Q0 | sum shares its exponent with width */ + } + + /* normalize sum for the following division */ + shift = norm_s(sum); + sum = shl(sum, shift); /* exponent of sum: sub(15, shift) */ + + /* divide E by sum */ + tmp = div_s(shr(round_fx(E), 1), sum); /* shift E 1 bit to the right in order to make it smaller than sum */ + tmp_e = sub(add(E_e, 1), sub(15, shift)); /* 15Q0 | sum is 15Q0 */ + + /* multiply the result by the hopsize */ + L_tmp = L_mult(tmp, hopsize); + L_tmp_e = add(tmp_e, 15); /* 15Q0 | hopsize is 15Q0 */ + + /* take the square root and store the result in dS */ + L_tmp = Sqrt32(L_tmp, &L_tmp_e); + dS[sfb] = round_fx(L_tmp); + dS_e[sfb] = L_tmp_e; + move16(); + + /* calculate the new dN */ + dN[sfb] = mult_r(gFactor, dS[sfb]); + move16(); + move16(); + dN_e[sfb] = add(dS_e[sfb], 1); /* 1Q14 | gFactor is 1Q14 */ + + /* calculate of the current sfb width */ + width = sub(hGrid->swb_offset[sfb + 1], /* 15Q0 | width is Q0 */ + hGrid->swb_offset[sfb]); + + /* square dN */ + L_tmp = L_mult(dN[sfb], dN[sfb]); + L_tmp_e = add(dN_e[sfb], dN_e[sfb]); + + /* mult L_tmp times width */ + shift = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, shift); + L_tmp = L_mult(round_fx(L_tmp), width); + L_tmp_e = sub(add(L_tmp_e, 15), shift); /* 15Q0 | width is Q0 */ + shift = norm_l(L_tmp); + + /* store normalized result */ + dNlocal = L_shl(L_tmp, shift); + dNlocal_e = sub(L_tmp_e, shift); + + /* gain calculation */ + gain[sfb] = 0; + move16(); + IF (pN[sfb] != 0) + { + tmp = BASOP_Util_Divide3232_Scale(dNlocal, pN[sfb],&s); + s = sub(add(s, dNlocal_e), pN_e[sfb]); + gain[sfb] = Sqrt16(tmp, &s); + move16(); + gain_e[sfb] = s; + move16(); + + + /* get the maximal exponent of the gain array, needed for exponent adjustment of the spectrum */ + maxGain_e = s_max(maxGain_e, gain_e[sfb]); + } + sfb_p1 = add(sfb, 1); + sfb_m1 = s_min(add(sfb, hopsize), stop_sfb); + FOR (s_sfb = sfb_p1; s_sfb < sfb_m1; s_sfb++) + { + gain[s_sfb] = gain[sfb]; + move16(); + gain_e[s_sfb] = gain_e[sfb]; + move16(); + } + + /*--- check gains /spectrum exponents for possible overflows --- */ + /* get tile index */ + if (LE_16(hGrid->sfbWrap[tileIdx + 1], sfb)) + { + tileIdx = add(tileIdx, 1); + } + /*do a test multiplication with the highest possible value*/ + L_tmp = Mpy_32_16_1(0xFFFF8000/*igf_spec occupies only the 16LSBs */, gain[sfb]); + L_tmp_e = add(igf_spec_e[tileIdx], gain_e[sfb]); + /*check whether overflow would occur and calculate Headroom, needed*/ + shift = sub(L_tmp_e, *spectrum_e); + tmp = sub(shift , sub(norm_l(L_tmp), TCX_IMDCT_HEADROOM)); + if (tmp > 0) + { + Hr = s_max(Hr, tmp); + } + + /* disable rescaling if gain is smaler than 1 */ + /* gain < 1, if norm_s(gain[sfb]) >= gain_e[sfb] */ + tmp = sub(norm_s(gain[sfb]), gain_e[sfb]); + if (tmp >= 0) + { + Hr = 0; + move16(); + } + } + + /* Rescale spectrum if overflow may occur */ + tileIdx = -1; + move16(); + IF (Hr > 0) + { + /* rescale virtual Spec, cheap and easy: reset scalingfactor */ + *virtualSpec_e = add(*virtualSpec_e, Hr); + move16(); + + /* rescale spectrum */ + FOR (i = 0; i < hGrid->stopLine; i++) + { + spectrum[i] = L_shr(spectrum[i], Hr); + move16(); + } + *spectrum_e = add(*spectrum_e, Hr); + move16(); + } + + /* tiling */ + tileIdx = -1; + move16(); + FOR (sfb = start_sfb; sfb < stop_sfb; sfb++) + { + /* get tile index */ + if (EQ_16(hGrid->sfbWrap[tileIdx + 1], sfb)) + { + tileIdx = add(tileIdx, 1); + } + + IF (hPrivateData->frameLossCounter > 0) + { + /* normalize gain */ + tmp = norm_s(gain[sfb]); + gain[sfb] = shl(gain[sfb], tmp); + gain_e[sfb] = sub(gain_e[sfb], tmp); + + /* gain[sfb] = min(gain[sfb], 12.f); */ + BASOP_SATURATE_WARNING_OFF /* threshold, may overflow */ + tmp = shl(gain[sfb], sub(gain_e[sfb], 15 - 5)); /* 10Q5 | tmp is in 10Q5 */ + BASOP_SATURATE_WARNING_ON + + IF (tmp > 384) /* 10Q5 | 384 = 12 in 10Q5 */ + { + gain[sfb] = 384; + move16(); + gain_e[sfb] = 10; + move16(); + } + + IF (LT_16(hPrivateData->frameLossCounter, 5)) + { + /* gain[sfb] -= gain[sfb] / 8 * hPrivateData->frameLossCounter; -> multiply with 0Q15 -> adaption of the exponent not needed */ + IF (EQ_16(hPrivateData->frameLossCounter, 1)) + { + /* 0Q15 | >> 3 ^= * 0.125 = 1 / 8 */ + gain[sfb] = sub(gain[sfb], shr_r(gain[sfb], 3)); + move16(); + } + ELSE IF (EQ_16(hPrivateData->frameLossCounter, 2)) + { + /* 0Q15 | >> 2 ^= * 0.25 = 2 / 8 */ + gain[sfb] = sub(gain[sfb], shr_r(gain[sfb], 2)); + move16(); + } + ELSE IF (EQ_16(hPrivateData->frameLossCounter, 3)) + { + /* 0Q15 | * 12288 ^= * 0.3750 = 3 / 8 */ + gain[sfb] = sub(gain[sfb], mult_r(gain[sfb], 12288)); + move16(); + } + ELSE + { + /* 0Q15 | >> 1 ^= * 0.5 = 4 / 8 */ + gain[sfb] = sub(gain[sfb], shr_r(gain[sfb], 1)); + move16(); + } + } + ELSE + { + /* gain[sfb] /= 2; -> reduce exponent by 1 */ + gain_e[sfb] = sub(gain_e[sfb], 1); + move16(); + } + } + + FOR (tb = hGrid->swb_offset[sfb]; tb < hGrid->swb_offset[sfb + 1]; tb++) + { + /* multiply the prepared IGF spectrum with the gain */ + L_tmp2 = 0; /* set L_tmp2 to default value */ + move32(); + L_tmp = Mpy_32_16_1(igf_spec[tb], gain[sfb]); + L_tmp_e = add(igf_spec_e[tileIdx], gain_e[sfb]); + + /* store the finalized IGF spectrum */ + IF (spectrum[tb] == 0) + { + shift = sub(L_tmp_e, *spectrum_e); + tmp = norm_l(L_tmp) - shift - 32; + if (tmp < 0) + { + L_tmp2 = L_shl(L_tmp, shift); + } + spectrum[tb] = L_tmp2; + move32(); + flag_sparse[tb-IGF_START_MN] = 1; + move16(); + } + ELSE + { + shift = sub(L_tmp_e, *virtualSpec_e); + tmp = norm_l(L_tmp) - shift - 32; + if (tmp < 0) + { + L_tmp2 = L_shl(L_tmp, shift); + } + virtualSpec[tb-IGF_START_MN] = L_tmp2; + move32(); + flag_sparse[tb-IGF_START_MN] = 2; + move16(); + } + } + } + +} + +/**********************************************************************/ /* +spectral whitening +**************************************************************************/ +static void IGF_getWhiteSpectralData(const Word32 *in, /**< in: Q31 | MDCT spectrum */ + Word16 s_l, /**< in: Q0 | getScaleFactor32() of in */ + Word32 *out, /**< out: Q31| whitened spectrum */ + const Word16 start, /**< in: Q0 | start MDCT subband index */ + const Word16 stop, /**< in: Q0 | stop MDCT subband index */ + const Word16 level /**< in: Q0 | whitening strength */ + ) +{ + Word16 j; + Word32 ak; /* moving average */ + Word32 ak_norm; + Word16 tmp_16; + Word16 div; + Word16 nrm_i; + Word16 nrm_tab[] = {2341 /* 1/14 */, 2521 /* 1/13 */, 2731 /* 1/12 */, 2979 /* 1/11 */, 3277 /* 1/10 */, 3641 /* 1/9 */, 4096 /* 1/8 */, 4681 /* 1/7 */}; + + + /* inits */ + div = 0; + move16(); + s_l = sub(s_l, 2); + ak = 0; + move32(); + + + FOR (j = start - level; j < start + level; j++) + { + tmp_16 = extract_h(L_shl(in[j], s_l)); + ak = L_mac(ak, tmp_16, tmp_16); + } + FOR (j = start; j < stop - level; j++) + { + tmp_16 = extract_h(L_shl(in[j + level], s_l)); + ak = L_mac(ak, tmp_16, tmp_16); + ak_norm = Mpy_32_16_r(ak, 2185); + tmp_16 = sub(31, norm_l(ak_norm)); + + if (ak == 0) + { + tmp_16 = 0; + move16(); + } + + tmp_16 = s_min(14, sub(15, shr(tmp_16, 1))); + div = shl(1, tmp_16); + out[j] = Mpy_32_16_1(L_shl(in[j], s_l), div); + move32(); + + tmp_16 = extract_h(L_shl(in[j - level], s_l)); + ak = L_msu(ak, tmp_16, tmp_16); + } + + nrm_i = 0; + move16(); + + FOR (; j < stop; j++) + { + ak_norm = Mpy_32_16_r(ak, nrm_tab[nrm_i++]); + tmp_16 = sub(31, norm_l(ak_norm)); + + if (ak == 0) + { + tmp_16 = 0; + move16(); + } + + tmp_16 = s_min(14, sub(15, shr(tmp_16, 1))); + div = shl(1, tmp_16); + + if (LT_32(ak, 16)) + { + div = 1; + move16(); + } + + out[j] = Mpy_32_16_1(L_shl(in[j], s_l), div); + move32(); + tmp_16 = extract_h(L_shl(in[j - level], s_l)); + ak = L_msu(ak, tmp_16, tmp_16); + } + +} + +/**********************************************************************/ /* +refines the IGF grid +**************************************************************************/ +static void IGF_RefineGrid(H_IGF_GRID hGrid /**< in/out: | IGF grid handle */ + ) +{ + Word16 a[IGF_MAX_SFB+1]; + Word16 sfb; + Word16 tmp; + Word16 delta; + + + set16_fx(a, 0, IGF_MAX_SFB+1); + + + hGrid->infoIsRefined = 1; + move16(); + FOR (sfb = 0; sfb < hGrid->swb_offset_len; sfb++) + { + tmp = shl(sfb, 1); + a[tmp] = hGrid->swb_offset[sfb]; + move16(); + tmp = add(tmp, 1); + delta = sub(hGrid->swb_offset[sfb+1], hGrid->swb_offset[sfb]); + delta = mac_r(0x00195000, 29491/*0.45f Q16*/, shl(delta, 5)); + a[tmp] = add(hGrid->swb_offset[sfb], shr(delta, 6)); + move16(); + if (s_and(a[tmp], 1) != 0) + { + a[tmp] = sub(a[tmp], 1); + move16(); + } + } + hGrid->stopSfb = shl(hGrid->stopSfb, 1); + FOR (sfb = 0; sfb <= hGrid->stopSfb; sfb++) + { + hGrid->swb_offset[sfb] = a[sfb]; + move16(); + } + + FOR (sfb = 0; sfb <= hGrid->nTiles; sfb++) + { + hGrid->sfbWrap[sfb] = shl(hGrid->sfbWrap[sfb], 1); + move16(); + } + +} + +/**********************************************************************/ /* +reads whitening information from the bitstream +**************************************************************************/ +void IGFDecReadData(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Deccoder */ + Decoder_State_fx *st, /**< in: | decoder state */ + const Word16 igfGridIdx, /**< in: Q0 | in case of CELP->TCX switching, use 1.25 framelength */ + const Word16 isIndepFrame /**< in: Q0 | if 1: arith dec force reset, if 0: no reset */ + ) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 p; + Word16 nT; + Word16 tmp; + + + IF (hInstance != NULL) + { + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + nT = hGrid->nTiles; + move16(); + tmp = 0; + move16(); + + /* set/reset all values to default = IGF_WHITENING_OFF */ + FOR (p = 0; p < IGF_MAX_TILES; p++) + { + hPrivateData->currWhiteningLevel[p] = IGF_WHITENING_OFF; + move16(); + } + + IF (isIndepFrame == 0) + { + tmp = get_next_indice_fx(st, 1); + } + + IF (tmp == 1) + { + FOR (p = 0; p < nT; p++) + { + hPrivateData->currWhiteningLevel[p] = hPrivateData->prevWhiteningLevel[p]; + move16(); + } + } + ELSE + { + IGF_decode_whitening_level(st, hPrivateData, 0); + tmp = get_next_indice_fx(st, 1); + IF (tmp == 1) + { + FOR (p = 1; p < nT; p++) + { + IGF_decode_whitening_level(st, hPrivateData, p); + } + } + ELSE + { + FOR (p = 1; p < nT; p++) + { + hPrivateData->currWhiteningLevel[p] = hPrivateData->currWhiteningLevel[0]; + move16(); + } + } + } + + /* save current level for concealment */ + FOR (p = 0; p < IGF_MAX_TILES; p++) + { + hPrivateData->prevWhiteningLevel[p] = hPrivateData->currWhiteningLevel[p]; + move16(); + } + + /* read flattening trigger from bitstream */ + IGF_decode_temp_flattening_trigger(st, hInstance); + } + +} + +/**********************************************************************/ /* +read the IGF level information from the bitsream +**************************************************************************/ +void IGFDecReadLevel( /**< out: Q0 | return igfAllZero flag indicating if no envelope is transmitted */ + const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + Decoder_State_fx *st, /**< in: | decoder state */ + const Word16 igfGridIdx, /**< in: Q0 | in case of CELP->TCX switching, use 1.25 framelength */ + const Word16 isIndepFrame /**< in: Q0 | if 1: arith dec force reset, if 0: no reset */ +) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 m_igfSfbStart; + Word16 IGFAllZero; + + IGFAllZero = 1; + move16(); + + IF (hInstance != NULL) + { + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + m_igfSfbStart = hGrid->startSfb; + move16(); + IGFAllZero = get_next_indice_fx(st, 1); + + IF (IGFAllZero == 0) + { + Copy(hPrivateData->igf_curr, hPrivateData->igf_prev, hGrid->stopSfb); + IGFSCFDecoderDecode(&hPrivateData->hArithSCFdec, + st, + &hPrivateData->igf_curr[m_igfSfbStart], /* 0Q15, hPrivateData->igf_curr = [0, 91] */ + isIndepFrame + ); + } + ELSE + { + IGFSCFDecoderReset(&hPrivateData->hArithSCFdec); + set16_fx(&hPrivateData->igf_curr[m_igfSfbStart], 0, sub(hGrid->stopSfb, m_igfSfbStart)); + } + } + + hInstance->infoIGFAllZero = IGFAllZero; + move16(); +} + +/**********************************************************************/ /* +apply the IGF decoder +**************************************************************************/ +void IGFDecApplyMono(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + Word32 *spectrum, /**< in/out: | MDCT spectrum */ + Word16 *spectrum_e, /**< in/out: | exponent of spectrum */ + const Word16 igfGridIdx, /**< in: | in case of CELP->TCX switching, use 1.25 framelength */ + Word16 bfi /**< in: | frame loss == 1, frame good == 0 */ + ) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 i; + Word16 whiteningLevel; + Word16 s_l; /* | headroom of pSpecFlat */ + Word16 specMed_e; /* | exponent of the medium whitened spectrum */ + Word32 igf_spec[IGF_MAX_GRANULE_LEN]; /* Q31 | prepared IGF spectrum */ + Word16 igf_spec_e[IGF_MAX_TILES]; /* | exponents of igf_spec, one exponent per tile */ + + + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + + /* initialize variables */ + whiteningLevel = 7; + move16(); + specMed_e = 0; + move16(); + hPrivateData->n_noise_bands = 0; + move16(); + hPrivateData->n_noise_bands_off = 0; + move16(); + hPrivateData->headroom_TCX_noise_white = 0; + move16(); + hPrivateData->headroom_TCX_noise = 0; + move16(); + hPrivateData->totalNoiseNrg = 0; move32(); + hPrivateData->totalNoiseNrg_off = 0; move32(); + + set32_fx(igf_spec, 0, IGF_MAX_GRANULE_LEN); + set16_fx(igf_spec_e, 0, IGF_MAX_TILES); + + /* concealment counter */ + IF (bfi != 0) + { + hPrivateData->frameLossCounter = add(hPrivateData->frameLossCounter, 1); + } + ELSE + { + hPrivateData->frameLossCounter = 0; + } + + /* skip IGF processing if all IGF levels are zero */ + IF (hInstance->infoIGFAllZero == 0) + { + + + FOR (i = 0; i < hGrid->nTiles; i++) + { + IF (EQ_16(hPrivateData->currWhiteningLevel[i], IGF_WHITENING_MID)) + { + s_l = getScaleFactor32(hPrivateData->pSpecFlat + hGrid->minSrcSubband - whiteningLevel, + add(sub(hGrid->startLine, hGrid->minSrcSubband), whiteningLevel)); + + specMed_e = hPrivateData->pSpecFlat_exp; + move16(); + IGF_getWhiteSpectralData(hPrivateData->pSpecFlat, + s_l, + igf_spec, + hGrid->minSrcSubband, + hGrid->startLine, + whiteningLevel); + + /*14 seems to be precise enough*/ + hPrivateData->headroom_TCX_noise_white = IGF_getScaleFactor32Cond(hInstance->infoTCXNoise + hGrid->minSrcSubband, + igf_spec + hGrid->minSrcSubband, + sub(hGrid->startLine, hGrid->minSrcSubband)); + hPrivateData->n_noise_bands = IGF_replaceTCXNoise_1(igf_spec, + hPrivateData->headroom_TCX_noise_white, + hInstance->infoTCXNoise, + hGrid->minSrcSubband, + hGrid->startLine, + &hPrivateData->totalNoiseNrg); + + BREAK; + } + } + + FOR (i = 0; i < hGrid->nTiles; i++) + { + IF (hPrivateData->currWhiteningLevel[ i ] == IGF_WHITENING_OFF) + { + hPrivateData->headroom_TCX_noise = IGF_getScaleFactor32Cond(hInstance->infoTCXNoise + hGrid->minSrcSubband, + hPrivateData->pSpecFlat + hGrid->minSrcSubband, + sub(hGrid->startLine, hGrid->minSrcSubband)); + + hPrivateData->n_noise_bands_off = IGF_replaceTCXNoise_1(hPrivateData->pSpecFlat, + hPrivateData->headroom_TCX_noise, + hInstance->infoTCXNoise, + hGrid->minSrcSubband, + hGrid->startLine, + &hPrivateData->totalNoiseNrg_off); + BREAK; + } + } + + /* apply IGF in three steps: */ + IGF_prep(hPrivateData, + igfGridIdx, + hInstance->infoTCXNoise, + igf_spec, + igf_spec_e, + hPrivateData->pSpecFlat, + hPrivateData->pSpecFlat_exp, + specMed_e); + IGF_calc(hPrivateData, + igfGridIdx, + spectrum, + *spectrum_e, + igf_spec, + igf_spec_e); + IGF_appl(hPrivateData, + igfGridIdx, + spectrum, + spectrum_e, + igf_spec, + igf_spec_e, + hInstance->virtualSpec, + &hInstance->virtualSpec_e, + hInstance->flag_sparse); + + } + + /* reset TCX noise indicator vector */ + set16_fx(hInstance->infoTCXNoise, 0, IGF_START_MX); + +} + +/**********************************************************************/ /* +set mode is used to init the IGF dec with a new bitrate +**************************************************************************/ +void IGFDecSetMode(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const Word32 bitRate, /**< in: Q0 | bitrate */ + const Word16 mode, /**< in: Q0 | bandwidth mode */ + const Word16 defaultStartLine, /**< in: Q0 | default start subband index */ + const Word16 defaultStopLine /**< in: Q0 | default stop subband index */ + , const Word16 rf_mode /**< in: | flag to signal the RF mode */ + ) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + + + hPrivateData = &hInstance->igfData; + hInstance->isIGFActive = 0; + move16(); + + IF (IGFCommonFuncsIGFConfiguration(bitRate, mode, &hPrivateData->igfInfo, rf_mode) != 0) + { + IGFSCFDecoderOpen(&hPrivateData->hArithSCFdec, + sub(hPrivateData->igfInfo.grid[0].stopSfb, hPrivateData->igfInfo.grid[0].startSfb), + bitRate, + mode + ,rf_mode + ); + + hInstance->infoIGFStopLine = hPrivateData->igfInfo.grid[0].stopLine; + move16(); + hInstance->infoIGFStartLine = hPrivateData->igfInfo.grid[0].startLine; + move16(); + hInstance->infoIGFStopFreq = hPrivateData->igfInfo.grid[0].stopFrequency; + move16(); + hInstance->infoIGFStartFreq = hPrivateData->igfInfo.grid[0].startFrequency; + move16(); + hInstance->infoIGFAllZero = 0; + move16(); + hInstance->isIGFActive = 1; + move16(); + + test(); + IF ((LE_16(hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_SWB_48000))||(LE_16(hPrivateData->igfInfo.bitRateIndex,IGF_BITRATE_FB_48000))) + { + IGF_RefineGrid(&hPrivateData->igfInfo.grid[IGF_GRID_LB_NORM]); + IGF_RefineGrid(&hPrivateData->igfInfo.grid[IGF_GRID_LB_TRAN]); + IGF_RefineGrid(&hPrivateData->igfInfo.grid[IGF_GRID_LB_SHORT]); + } + } + ELSE + { + hInstance->infoIGFStopLine = defaultStopLine; + move16(); + hInstance->infoIGFStartLine = defaultStartLine; + move16(); + hInstance->infoIGFStopFreq = -1; + move16(); + hInstance->infoIGFStartFreq = -1; + move16(); + fprintf(stderr,"IGFDecSetMode: initialization error!\n"); + } + +} + +/**********************************************************************/ /* +updates the start/stop frequency of IGF according to igfGridIdx +**************************************************************************/ +void IGFDecUpdateInfo(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const Word16 igfGridIdx /**< in: | IGF grid index */ + ) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + + + hPrivateData = &hInstance->igfData; + IF (hInstance->isIGFActive != 0) + { + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + hInstance->infoIGFStartFreq = hGrid->startFrequency; + move16(); + hInstance->infoIGFStopFreq = hGrid->stopFrequency; + move16(); + hInstance->infoIGFStartLine = hGrid->startLine; + move16(); + hInstance->infoIGFStopLine = hGrid->stopLine; + move16(); + } +} + +/**********************************************************************/ /* +copy the LPC flat spectrum to IGF buffer +**************************************************************************/ +void IGFDecCopyLPCFlatSpectrum(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const Word32 *pSpectrumFlat, /**< in: Q31 | LPC flattend spectrum from TCX dec */ + const Word16 pSpectrumFlat_exp, /**< in: | exponent of pSpectrumFlat */ + const Word16 igfGridIdx /**< in: Q0 | IGF grid index */ + ) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + + + IF (hInstance) + { + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + + + /* pSpectrumFlat_exp has to be multiplied with 1024 = 2^10 go achive proper gain values */ + hPrivateData->pSpecFlat_exp = add(pSpectrumFlat_exp, 10); + move16(); + + Copy32(pSpectrumFlat, hPrivateData->pSpecFlat, hGrid->startLine); + } + +} + +/**********************************************************************/ /* +store the IGF bitstream information for TCX10 subframes +**************************************************************************/ +void IGFDecStoreTCX10SubFrameData(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const Word16 subFrameIdx /**< in: Q0 | index of subframe */ + ) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + + + hPrivateData = &hInstance->igfData; + + /* store igf energies for subframe*/ + Copy(hPrivateData->igf_curr, hPrivateData->igf_curr_subframe[subFrameIdx][0], IGF_MAX_SFB); + Copy(hPrivateData->igf_prev, hPrivateData->igf_prev_subframe[subFrameIdx], IGF_MAX_SFB); + + /* store spectral whitening information for current subframe */ + Copy(hPrivateData->currWhiteningLevel, hPrivateData->currWhiteningLevel_subframe[subFrameIdx], IGF_MAX_TILES); + Copy(hPrivateData->prevWhiteningLevel, hPrivateData->prevWhiteningLevel_subframe[subFrameIdx], IGF_MAX_TILES); + /* store flattening trigger for current subframe */ + hPrivateData->igf_flatteningTrigger_subframe[subFrameIdx] = hInstance->flatteningTrigger; + move16(); + +} + +/**********************************************************************/ /* +restore the IGF bitstream information for TCX10 subframes +**************************************************************************/ +void IGFDecRestoreTCX10SubFrameData(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Decoder */ + const Word16 subFrameIdx /**< in: Q0 | index of subframe */ + ) +{ + IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData; + + + hPrivateData = &hInstance->igfData; + + /* store igf energies for subframe*/ + Copy(hPrivateData->igf_curr_subframe[subFrameIdx][0], hPrivateData->igf_curr, IGF_MAX_SFB); + Copy(hPrivateData->igf_prev_subframe[subFrameIdx], hPrivateData->igf_prev, IGF_MAX_SFB); + + /* store spectral whitening information for current subframe */ + Copy(hPrivateData->currWhiteningLevel_subframe[subFrameIdx], hPrivateData->currWhiteningLevel, IGF_MAX_TILES); + Copy(hPrivateData->prevWhiteningLevel_subframe[subFrameIdx], hPrivateData->prevWhiteningLevel, IGF_MAX_TILES); + /* restore flattening trigger for current subframe */ + hInstance->flatteningTrigger = hPrivateData->igf_flatteningTrigger_subframe[subFrameIdx]; + move16(); + +} diff --git a/lib_dec/igf_scf_dec.c b/lib_dec/igf_scf_dec.c new file mode 100644 index 0000000..df936fb --- /dev/null +++ b/lib_dec/igf_scf_dec.c @@ -0,0 +1,352 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include +#include "options.h" +#include "stl.h" +#include "prot_fx.h" +#include "stat_dec_fx.h" +#include "basop_util.h" + + +/**********************************************************************/ /** +initialization of an instance of this module +**************************************************************************/ +void IGFSCFDecoderOpen( + IGFSCFDEC_INSTANCE_HANDLE hPublicData, /* i/o: handle to public data */ + Word16 scfCountLongBlock, /* i: number of SCFs for a long block */ + Word32 bitRate, /* i: bitrate in bps */ + Word16 mode /* i: operating mode */ + ,Word16 rf_mode +) +{ + + + hPublicData->scfCountLongBlock = scfCountLongBlock; + move16(); + hPublicData->t = 0; + move16(); /* protect against the invalid request of starting decoding with a dependent block */ + + IGFCommonFuncsIGFGetCFTables( + bitRate, + mode, + rf_mode, + &hPublicData->cf_se00, + &hPublicData->cf_se01, + &hPublicData->cf_off_se01, + &hPublicData->cf_se02, + &hPublicData->cf_off_se02, + &hPublicData->cf_se10, + &hPublicData->cf_off_se10, + &hPublicData->cf_se11, + &hPublicData->cf_off_se11 + ); + +} + + +static Word16 quant_ctx_fx( + Word16 ctx /* i: the context value to be quantized */ +) +{ + /* + ctx ... -5 -4 -3 -2 -1 0 1 2 3 4 5 ... + Q(ctx)... -3 -3 -3 -2 -1 0 1 2 3 3 3 ... + */ + Word16 result; + + + result = s_min(abs_s(ctx), IGF_CTX_OFFSET); /* limit the absolute value to IGF_CTX_OFFSET */ + if (ctx < 0) /* add the sign back, if needed */ + { + result = negate(result); + } + + return result; +} + +static Word16 arith_decode_bits_fx( + IGFSCFDEC_INSTANCE_HANDLE hPrivateData, /* i/o: instance handle */ + Decoder_State_fx *st, /* i/o: pointer to bitstream decoder state */ + Word16 nBits /* i: number of bits to decode */ +) +{ + Word16 i; + Word16 x; + Word16 bit; + + + x = 0; + move16(); + FOR (i = 0; i < nBits; ++i) /* nBits > 0 */ + { + x = lshl(x, 1); + /* decode one bit using the new raw AC function */ + bit = ari_decode_14bits_bit_ext(st, &hPrivateData->acState); + if (bit != 0) + { + x = s_or(x, 1); + } + } + + return x; +} + +static Word16 arith_decode_residual_fx( + IGFSCFDEC_INSTANCE_HANDLE hPrivateData, /* i/o: instance handle */ + Decoder_State_fx *st, /* i/o: pointer to decoder state */ + const Word16 *cumulativeFrequencyTable, /* i: cumulative frequency table to be used */ + Word16 tableOffset /* i: offset used to align the table */ +) +{ + Word16 val; + Word16 x = 0; /* to avoid a compiler warning (potentially uninitialized local variable used) */ + Word16 extra; + + + /* decode one of the IGF_SYMBOLS_IN_TABLE == 27 alphabet symbols using the new raw AC function */ + val = ari_decode_14bits_s27_ext(st, &hPrivateData->acState, (const UWord16*) cumulativeFrequencyTable); + + /* meaning of the values of val: */ + /* esc_{0} IGF_MIN_ENC_SEPARATE ... IGF_MAX_ENC_SEPARATE esc_{IGF_SYMBOLS_IN_TABLE - 1} */ + test(); + IF ((val != 0) && (NE_16(val, IGF_SYMBOLS_IN_TABLE - 1))) + { + x = add(val, - 1 + IGF_MIN_ENC_SEPARATE); /* (val - 1) + IGF_MIN_ENC_SEPARATE */ + + + x = sub(x, tableOffset); + + return x; + } + + /* decode one of the tails of the distribution */ + /* decode extra with 4 bits */ + extra = arith_decode_bits_fx(hPrivateData, st, 4); + IF (EQ_16(extra, 15)) /* escape code 15 to indicate extra >= 15 */ + { + /* decode addtional extra with 6 bits */ + extra = arith_decode_bits_fx(hPrivateData, st, 6); + IF (EQ_16(extra, 63)) /* escape code 63 to indicate extra >= 63 */ + { + /* decode safety extra with 7 bits */ + extra = arith_decode_bits_fx(hPrivateData, st, 7); + extra = add(63, extra); + } + extra = add(15, extra); + } + + if (val == 0) + { + /* escape code 0 to indicate x <= IGF_MIN_ENC_SEPARATE - 1 */ + x = sub(IGF_MIN_ENC_SEPARATE - 1, extra); + } + if (EQ_16(val, IGF_SYMBOLS_IN_TABLE - 1)) + { + /* escape code (IGF_SYMBOLS_IN_TABLE - 1) to indicate x >= IGF_MAX_ENC_SEPARATE + 1 */ + x = add(IGF_MAX_ENC_SEPARATE + 1, extra); + } + + x = sub(x, tableOffset); + + return x; +} + +static void arith_decode_flush_fx( + Decoder_State_fx *st /* i/o: pointer to decoder state */ +) +{ + + get_next_indice_tmp_fx(st, -14); /* return back the least significant 14 bits to the bitstream */ + +} + +static void decode_sfe_vector_fx( + IGFSCFDEC_INSTANCE_HANDLE hPrivateData, /* i/o: instance handle */ + Decoder_State_fx *st, /* i/o: pointer to decoder state */ + Word16 t, /* i: counter reset to 0 at each independent block */ + Word16 *prev_x, /* i: previous vector */ + Word16 *x, /* o: current vector to decode */ + Word16 length /* i: number of elements to decode */ +) +{ + /* + f + ^ + | d a x + | c b + | e --> t + */ + Word16 f; + Word16 pred; + Word16 res; + Word16 ctx; + Word16 ctx_f; + Word16 ctx_t; + Word16 prev_offset; + Word32 index1; + Word32 index2; + + + + FOR (f = 0; f < length; ++f) + { + IF (t == 0) + { + IF (f == 0) + { + /* (t == 0) && (f == 0) */ + /* decode one of the IGF_SYMBOLS_IN_TABLE == 27 alphabet symbols using the new raw AC function */ + res = ari_decode_14bits_s27_ext(st, &hPrivateData->acState, (const UWord16*) hPrivateData->cf_se00); + + pred = arith_decode_bits_fx(hPrivateData, st, 2); /* LSBs as 2 bit raw */ + x[f] = add(shl(res, 2), pred); + move16(); + } + ELSE IF (EQ_16(f, 1)) + { + /* (t == 0) && (f == 1) */ + res = arith_decode_residual_fx(hPrivateData, + st, + hPrivateData->cf_se01, + hPrivateData->cf_off_se01); + x[f] = add(x[0], res); + move16(); /* f - increment is 0, pred = b */ + } + ELSE + { + /* (t == 0) && (f >= 2) */ + prev_offset = sub(f, 1); + ctx = quant_ctx_fx(sub(x[prev_offset], x[sub(prev_offset, 1)])); /* Q(b - e) */ + /* index1 is (IGF_SYMBOLS_IN_TABLE + 1) * (CTX_OFFSET + ctx) */ + index1 = L_mac0((IGF_SYMBOLS_IN_TABLE + 1) * IGF_CTX_OFFSET, (IGF_SYMBOLS_IN_TABLE + 1), ctx); + /* index2 is IGF_CTX_OFFSET + ctx */ + index2 = L_mac0(IGF_CTX_OFFSET, 1, ctx); + res = arith_decode_residual_fx(hPrivateData, + st, + hPrivateData->cf_se02 + index1, + hPrivateData->cf_off_se02[index2]); + x[f] = add(x[prev_offset], res); + move16(); /* pred = b */ + } + } + ELSE + { + /* t == 1 */ + IF (f == 0) + { + /* (t == 1) && (f == 0) */ + res = arith_decode_residual_fx(hPrivateData, + st, + hPrivateData->cf_se10, + hPrivateData->cf_off_se10); + x[f] = add(prev_x[f], res); + move16(); /* pred = a */ + } + ELSE + { + /* (t == 1) && (f >= 1) */ + prev_offset = sub(f, 1); + pred = add(prev_x[f], x[prev_offset]); + pred = sub(pred, prev_x[prev_offset]); /* pred = a + b - c */ + ctx_f = quant_ctx_fx(sub(prev_x[f], prev_x[prev_offset])); /* Q(a - c) */ + ctx_t = quant_ctx_fx(sub(x[prev_offset], prev_x[prev_offset])); /* Q(b - c) */ + /* index1 is (IGF_SYMBOLS_IN_TABLE + 1) * IGF_CTX_COUNT * (IGF_CTX_OFFSET + ctx_t) + + (IGF_SYMBOLS_IN_TABLE + 1) * (IGF_CTX_OFFSET + ctx_f) */ + index1 = L_mac0( + ((IGF_SYMBOLS_IN_TABLE + 1) * IGF_CTX_COUNT + (IGF_SYMBOLS_IN_TABLE + 1)) * IGF_CTX_OFFSET, + (IGF_SYMBOLS_IN_TABLE + 1) * IGF_CTX_COUNT, ctx_t); + index1 = L_mac0(index1, (IGF_SYMBOLS_IN_TABLE + 1), ctx_f); + /* index2 is IGF_CTX_COUNT * (IGF_CTX_OFFSET + ctx_t) + (IGF_CTX_OFFSET + ctx_f) */ + index2 = L_mac0((IGF_CTX_COUNT + 1) * IGF_CTX_OFFSET, IGF_CTX_COUNT, ctx_t); + index2 = L_mac0(index2, 1, ctx_f); + res = arith_decode_residual_fx(hPrivateData, + st, + hPrivateData->cf_se11 + index1, + hPrivateData->cf_off_se11[index2]); + x[f] = add(pred, res); + move16(); + } + } + + IF( x[f] < 0 ) + { + x[f] = 0; + move16(); + st->BER_detect = 1; + move16(); + } + + IF (GT_16(x[f],91)) + { + x[f] = 91; + move16(); + st->BER_detect = 1; + move16(); + } + } + +} + +/**********************************************************************/ /** +resets the internal decoder memory (context memory) +**************************************************************************/ +void IGFSCFDecoderReset( + IGFSCFDEC_INSTANCE_HANDLE hPublicData /* i/o: handle to public data */ +) +{ + + + /* reset of coder */ + hPublicData->t = 0; /* indicate that an independent block follows */ + /* we do not need to fill hPublicData->prev with zeros, because when t = 0 no previous information is used */ + +} + +/**********************************************************************/ /** +main decoder function +**************************************************************************/ +void IGFSCFDecoderDecode( + IGFSCFDEC_INSTANCE_HANDLE hPublicData, /* i/o: handle to public data */ + Decoder_State_fx *st, /* i/o: pointer to decoder state */ + Word16 *sfe, /* o: pointer to an array which will contain the decoded quantized SCFs */ + Word16 indepFlag /* i: 1 if the block is an independent block, 0 otherwise */ +) +{ + + + + /* insert data */ + hPublicData->bitsRead = st->next_bit_pos_fx; + move16(); + ari_start_decoding_14bits(st, &hPublicData->acState); /* start AC decoding */ + + /* check if coder needs a reset and do it if necessary */ + IF (indepFlag != 0) + { + /* reset of coder */ + IGFSCFDecoderReset(hPublicData); + } + + decode_sfe_vector_fx(hPublicData, + st, + hPublicData->t, + hPublicData->prev, + sfe, + hPublicData->scfCountLongBlock + ); + + arith_decode_flush_fx(st); /* finish AC decoding */ + + + /* advance history */ + Copy(sfe, hPublicData->prev, hPublicData->scfCountLongBlock); + hPublicData->t = add(hPublicData->t, 1); + + hPublicData->bitsRead = sub(st->next_bit_pos_fx, hPublicData->bitsRead); + +} diff --git a/lib_dec/init_dec_fx.c b/lib_dec/init_dec_fx.c new file mode 100644 index 0000000..74c6b97 --- /dev/null +++ b/lib_dec/init_dec_fx.c @@ -0,0 +1,967 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" /* required for wmc_tool */ +#include "basop_util.h" + +/*----------------------------------------------------------------------* + * init_decoder() + * + * Initialization of static variables for the decoder + *----------------------------------------------------------------------*/ + +void init_decoder_fx( + Decoder_State_fx *st_fx /* o: Decoder static variables structure */ +) +{ + Word16 i, j; + Word16 f_db, e_db; + Word32 L_tmp; + Word16 newCldfbBands; + + + st_fx->total_num_bits = -1; + move16(); + + /*-----------------------------------------------------------------* + * ACELP core parameters + *-----------------------------------------------------------------*/ + + st_fx->codec_mode = MODE1; + move16(); + st_fx->last_codec_mode = MODE1; + move16(); + st_fx->core_fx = ACELP_CORE; + move16(); + st_fx->L_frame_fx = L_FRAME; + move16(); + st_fx->extl_fx = -1; + move16(); + st_fx->total_brate_fx = 8000; + move16(); + st_fx->last_total_brate_fx = -1; + move16(); + st_fx->last_total_brate_ber_fx = -1; + move32(); + st_fx->core_brate_fx = 8000; + move16(); + st_fx->ini_frame_fx = 0; + move16(); + st_fx->bwidth_fx = NB; + move16(); + st_fx->extl_brate_fx = 0; + move16(); + + + st_fx->last_coder_type_fx = GENERIC; + move16(); + st_fx->last_L_frame_fx = st_fx->L_frame_fx; + move16(); + st_fx->last_core_brate_fx = st_fx->core_brate_fx ; + move16(); + + st_fx->last_core_fx = -1; + move16(); + st_fx->prev_last_core_fx = -1; + st_fx->last_extl_fx = st_fx->extl_fx; + move16(); + st_fx->last_hq_core_type_fx = -1; + move16(); + + /* LSF initilaizations */ + Copy( GEWB_Ave_fx, st_fx->mem_AR_fx, M ); + + init_lvq_fx( st_fx->offset_scale1_fx, st_fx->offset_scale2_fx, st_fx->offset_scale1_p_fx, st_fx->offset_scale2_p_fx, st_fx->no_scales_fx, st_fx->no_scales_p_fx ); + + set16_fx( st_fx->mem_MA_fx, 0, M ); + + st_fx->dm_fx.prev_state = 0; + move16(); /* This corresponds to st_fx->dispMem in FLP */ + st_fx->dm_fx.prev_gain_code = L_deposit_l(0); + FOR(i=2; i<8; i++) + { + st_fx->dm_fx.prev_gain_pit[i-2] = 0; + move16(); + } + + /* HF synth init */ + hf_synth_amr_wb_init_fx( &st_fx->prev_r_fx, &st_fx->fmerit_w_sm_fx, st_fx->mem_syn_hf_fx, + &st_fx->frame_count_fx, &st_fx->ne_min_fx, &st_fx->fmerit_m_sm_fx, &st_fx->voice_fac_amr_wb_hf, + &st_fx->unvoicing_fx, &st_fx->unvoicing_sm_fx, &st_fx->unvoicing_flag_fx, + &st_fx->voicing_flag_fx, &st_fx->start_band_old_fx, &st_fx->OptCrit_old_fx ); + + hf_synth_init_fx( st_fx->mem_hp400_fx, st_fx->mem_hf_fx ); + set16_fx( st_fx->mem_hp_interp_fx, 0, INTERP_3_1_MEM_LEN ); + set16_fx( st_fx->delay_syn_hf_fx, 0, NS2SA_fx2(16000,DELAY_CLDFB_NS) ); + + st_fx->tilt_code_fx = 0; + move16(); + st_fx->gc_threshold_fx = L_deposit_l(0); + st_fx->last_good_fx = UNVOICED_CLAS; + move16(); + st_fx->clas_dec = UNVOICED_CLAS; + move16(); + + st_fx->lp_gainp_fx = 0; + move16(); + st_fx->lp_gainc_fx = 0; + move16(); + + set16_fx( st_fx->old_exc_fx, 0, L_EXC_MEM_DEC ); + + /* AVQ pre-quantizer memory */ + st_fx->mem_preemp_preQ_fx = 0; + move16(); + st_fx->last_nq_preQ_fx = 0; + move16(); + st_fx->use_acelp_preq = 0; + move16(); + + st_fx->mem_deemph_fx = 0; + move16(); + + set16_fx( st_fx->mem_syn1_fx, 0, M ); + st_fx->mem_deemph_old_syn_fx = 0; + move16(); + set16_fx( st_fx->mem_syn2_fx, 0, M ); + st_fx->stab_fac_fx = 0; + move16(); + st_fx->stab_fac_smooth_fx = 0; + move16(); + set16_fx( st_fx->agc_mem_fx, 0, 2 ); + set32_fx( st_fx->L_mem_hp_out_fx, 0, 5 ); + set16_fx( st_fx->mem_syn3_fx, 0, M ); + FOR (i=0; ipast_qua_en_fx[i] = -14336; + move16(); /* Q10; */ /* gain quantization memory (used also in AMR-WB IO mode) */ + } + + Copy( GEWB_Ave_fx, st_fx->lsf_old_fx, M ); + lsf2lsp_fx( st_fx->lsf_old_fx, st_fx->lsp_old_fx, M, INT_FS_FX ); + st_fx->mid_lsf_int_fx = 0; + move16(); + st_fx->safety_net_fx = 0; + move16(); + + /* parameters for AC mode (GSC) */ + st_fx->seed_tcx_fx = 15687; + move16(); /*check if it is Q0*/ + st_fx->GSC_noisy_speech_fx = 0; + move16(); + st_fx->Last_GSC_noisy_speech_flag_fx = 0; + move16(); + st_fx->cor_strong_limit_fx = 1; + move16(); + set16_fx(st_fx->old_y_gain_fx, 0 , MBANDS_GN ); + st_fx->noise_lev_fx = NOISE_LEVEL_SP0; + move16(); + set16_fx( st_fx->Last_GSC_spectrum_fx, 0, L_FRAME ); + st_fx->Last_GSC_pit_band_idx_fx = 0; + move16(); + + set16_fx( st_fx->lt_ener_per_band_fx, 4096, MBANDS_GN );/*Q12*/ + set16_fx( st_fx->last_exc_dct_in_fx, 0, L_FRAME); + st_fx->last_ener_fx = 0; + set16_fx( st_fx->last_bitallocation_band_fx, 0, 6 ); + + /* NB post-filter */ + Init_post_filter( &(st_fx->pfstat) ); + st_fx->psf_lp_noise_fx = 0; + move16(); + + /* FEC */ + st_fx->scaling_flag = 0; + move16(); + st_fx->lp_ener_FEC_av = 500000; + move32(); + st_fx->lp_ener_FEC_max = 500000; + move32(); + st_fx->prev_bfi_fx = 0; + move16(); + st_fx->lp_ener_FER_fx = 15360; + move16(); /*60 in Q8*/ + st_fx->old_enr_LP = 0; + move16(); + st_fx->lp_ener_fx = L_deposit_l(0); + st_fx->enr_old_fx = L_deposit_l(0); + st_fx->bfi_pitch_fx = L_SUBFR_Q6; + move16(); + st_fx->bfi_pitch_frame_fx = L_SUBFR; + move16(); + set16_fx( st_fx->mem_syn_clas_estim_fx, 0, L_SYN_MEM_CLAS_ESTIM ); + st_fx->classifier_Q_mem_syn = 0; + move16(); + st_fx->last_con_tcx = 0; + move16(); + + FOR (i=0; i<2*NB_SUBFR16k; i++) + { + st_fx->old_pitch_buf_fx[i] = L_SUBFR<<16; + move32(); /*15Q16*/ + } + + st_fx->upd_cnt_fx = MAX_UPD_CNT; + move16(); + Copy( GEWB_Ave_fx, st_fx->lsfoldbfi0_fx, M ); + Copy( GEWB_Ave_fx, st_fx->lsfoldbfi1_fx, M ); + Copy( GEWB_Ave_fx, st_fx->lsf_adaptive_mean_fx, M ); + + st_fx->seed_acelp = RANDOM_INITSEED; + move16(); + st_fx->seed_fx = RANDOM_INITSEED; + move16(); + st_fx->nbLostCmpt = 0; + move16(); + st_fx->decision_hyst_fx = 0; + move16(); + + /* fast recovery */ + set16_fx( st_fx->old_exc2_fx, 0, L_EXC_MEM ); + set16_fx( st_fx->old_syn2_fx, 0, L_EXC_MEM ); + + /* Stationary noise UV modification */ + st_fx->unv_cnt_fx = 0; + move16(); + st_fx->ge_sm_fx = L_deposit_l(640); /*Q(GE_SHIFT)*/ + st_fx->uv_count_fx = 0; + move16(); + st_fx->act_count_fx = 3; + move16(); + Copy( st_fx->lsp_old_fx, st_fx->lspold_s_fx, M ); + st_fx->noimix_seed_fx = RANDOM_INITSEED; + move16(); + st_fx->min_alpha_fx = 32767; + move16(); /*1; Q15*/ + st_fx->exc_pe_fx = 0; + move16(); + + st_fx->cng_ener_seed1_fx = RANDOM_INITSEED; + move16(); + set32_fx(st_fx->lp_env_fx, 0, NUM_ENV_CNG); + set16_fx(st_fx->exc_mem_fx, 0, 24); + set16_fx(st_fx->exc_mem1_fx, 0, 30); + set32_fx(st_fx->old_env_fx, 0, NUM_ENV_CNG); + /* LD music post-filter */ + set16_fx(st_fx->dct_post_old_exc_fx, 0, DCT_L_POST-OFFSET2 ); + /*st->LDm_enh_min_ns_gain = (float)pow(10.0f, -12/20.0f);*/ + L_tmp = L_mult(((-12*256)), 5443); /* *0.166096 in Q15 -> Q24 */ + L_tmp = L_shr(L_tmp, 8); /* From Q24 to Q16 */ + f_db = L_Extract_lc(L_tmp, &e_db); /* Extract exponent */ + f_db = extract_l(Pow2(14, f_db)); /* Put 14 as exponent so that */ + e_db = add(e_db, 15-14); + f_db = add(f_db, shr(1,add(e_db,1))); + st_fx->LDm_enh_min_ns_gain_fx = shl(f_db, e_db); + + st_fx->LDm_last_music_flag_fx = 0; + move16(); + set16_fx( st_fx->LDm_lt_diff_etot_fx, 0, MAX_LT ); + + st_fx->LDm_thres_fx[0] = TH_0_MIN_FX; + move16(); + st_fx->LDm_thres_fx[1] = TH_1_MIN_FX; + move16(); + st_fx->LDm_thres_fx[2] = TH_2_MIN_FX; + move16(); + st_fx->LDm_thres_fx[3] = TH_3_MIN_FX; + move16(); + + st_fx->LDm_nb_thr_1_fx = 0; + move16(); + st_fx->LDm_nb_thr_3_fx = 0; + move16(); + st_fx->LDm_mem_etot_fx = 0; + move16(); + + FOR (i = 0; i < VOIC_BINS_HR; i++) + { + st_fx->LDm_enh_lp_gbin_fx[i] = 16384; + move16(); + st_fx->LDm_enh_lf_EO_fx [i] = 328; + move16(); + } + + FOR (i = 0; i < MBANDS_GN_LD; i++) + { + st_fx->LDm_bckr_noise_fx[i] = E_MIN_Q15; + move16(); + } + + set16_fx(st_fx->filt_lfE_fx, 4096, DCT_L_POST); + move16(); + st_fx->last_nonfull_music_fx = 0; + move16(); + st_fx->Old_ener_Q = 0; + move16(); + + /* CNG and DTX */ + st_fx->CNG_fx = 0; + move16(); /* RTXDTX handler CNG=1 nonCNG= 0,*/ + st_fx->prev_ft_speech_fx = 1; + move16(); /* RXDTX handeler previous frametype flag for G.192 format AMRWB SID_FIRST detection */ + st_fx->cng_seed_fx = RANDOM_INITSEED; + move16(); + st_fx->cng_ener_seed_fx = RANDOM_INITSEED; + move16(); + st_fx->old_enr_index_fx = -1; + move16(); + st_fx->Enew_fx = L_deposit_l(0); + st_fx->first_CNG_fx = 0; + move16(); + Copy( st_fx->lsp_old_fx, st_fx->lspCNG_fx, M ); + st_fx->last_allow_cn_step_fx = 0; + move16(); + st_fx->shb_cng_ener_fx = -1541; + move16(); + st_fx->wb_cng_ener_fx = -1541; + move16(); + st_fx->last_wb_cng_ener_fx = -1541; + move16(); + st_fx->last_shb_cng_ener_fx = -1541; + move16(); + st_fx->swb_cng_seed_fx = RANDOM_INITSEED; + move16(); + st_fx->ho_hist_ptr_fx = -1; + move16(); + st_fx->ho_sid_bw_fx = L_deposit_l(0); + set16_fx( st_fx->ho_lsp_hist_fx, 0, HO_HIST_SIZE*M ); + set32_fx( st_fx->ho_ener_hist_fx, 0, HO_HIST_SIZE ); + set32_fx( st_fx->ho_env_hist_fx, 0, HO_HIST_SIZE*NUM_ENV_CNG ); + st_fx->ho_hist_size_fx = 0; + move16(); + st_fx->act_cnt_fx = 0; + move16(); + st_fx->ho_circ_ptr_fx = -1; + move16(); + set16_fx( st_fx->ho_lsp_circ_fx, 0, HO_HIST_SIZE*M ); + set32_fx( st_fx->ho_ener_circ_fx, 0, HO_HIST_SIZE ); + set32_fx( st_fx->ho_env_circ_fx, 0, HO_HIST_SIZE*NUM_ENV_CNG ); + st_fx->ho_circ_size_fx = 0; + move16(); + set16_fx( st_fx->ho_16k_lsp_fx, 0, HO_HIST_SIZE ); + st_fx->CNG_mode_fx = -1; + move16(); + st_fx->last_active_brate_fx = ACELP_7k20; + move32(); + st_fx->last_CNG_L_frame_fx = L_FRAME; + move16(); + st_fx->act_cnt2_fx = 0; + move16(); + st_fx->num_ho_fx = 0; + move16(); + st_fx->cng_type_fx = -1; + move16(); + st_fx->last_cng_type_fx = -1; + move16(); + + FOR ( i=0; ilsp_shb_prev_fx[i] = lsp_shb_prev_tbl_fx[i]; + st_fx->lsp_shb_prev_prev_fx[i] = st_fx->lsp_shb_prev_fx[i]; + } + + st_fx->shb_dtx_count_fx = 0; + move16(); + st_fx->last_vad_fx = 0; + move16(); + st_fx->trans_cnt_fx = 0; + move16(); + st_fx->burst_cnt_fx = 0; + move16(); + st_fx->last_shb_ener_fx = 0; + move16(); + + /* HF (6-7kHz) BWE */ + st_fx->seed2_fx = RANDOM_INITSEED; + move16(); + st_fx->Q_stat_noise_ge = GE_SHIFT; + move16(); + st_fx->cngTDLevel = 0; + move16(); + st_fx->cngTDLevel_e = 0; + move16(); + + /*-----------------------------------------------------------------* + * HR SWB BWE parameters + *-----------------------------------------------------------------*/ + + set16_fx( st_fx->t_audio_prev_fx, 0, 2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_START_FREQ_COEF ); + set16_fx( st_fx->t_audio_prev_fx_exp, 0, NUM_TIME_SWITCHING_BLOCKS ); /* one exp per switching block */ + st_fx->old_is_transient_hr_bwe_fx = 0; + move16(); + st_fx->bwe_highrate_seed_fx = 12345; + move16(); + + st_fx->L_mem_EnergyLT_fx = L_deposit_h(16384); + st_fx->mem_EnergyLT_fx_exp = 40; + move16(); /* set to a high exponent */ + + + /*-----------------------------------------------------------------* + * HQ core parameters + *-----------------------------------------------------------------*/ + + set16_fx( st_fx->old_out_fx, 0, L_FRAME48k ); + set16_fx( st_fx->old_out_LB_fx, 0, L_FRAME32k ); + set32_fx( st_fx->old_coeffs_fx, 0, L_FRAME8k ); + st_fx->Q_old_wtda = 15; + move16(); + st_fx->Q_old_postdec = 0; + move16(); + st_fx->Qprev_synth_buffer_fx = 15; + move16(); + set16_fx( st_fx->old_is_transient_fx, 0, 3 ); + st_fx->old_bfi_cnt_fx = 0; + move16(); + set16_fx(st_fx->old_auOut_2fr_fx, 0, L_FRAME8k*2); + set16_fx(st_fx->old_out_pha_fx[0], 0, N_LEAD_NB); + set16_fx(st_fx->old_out_pha_fx[1], 0, N_LEAD_NB); + st_fx->prev_old_bfi_fx = 0; + move16(); + st_fx->phase_mat_flag_fx = 0; + move16(); + st_fx->phase_mat_next_fx = 0; + move16(); + st_fx->old_Min_ind_fx = 0; + move16(); + st_fx->diff_energy_fx = 0; + move16(); + set32_fx( st_fx->oldIMDCTout_fx, 0, L_FRAME8k/2 ); + set16_fx( st_fx->prev_oldauOut_fx, 0, L_FRAME8k ); + st_fx->stat_mode_out_fx = 0; + move16(); + st_fx->stat_mode_old_fx = 0; + move16(); + st_fx->oldHqVoicing_fx = 0; + move16(); + + FOR( i=0; i ynrm_values_fx[i][j] = 0; + move16(); + } + FOR( j=0; jr_p_values_fx[i][j] = 0; + move16(); + } + } + set16_fx(st_fx->Norm_gain_fx, 1, SFM_N_NB); /*check if it is in Q0 */ + set16_fx(st_fx->energy_MA_Curr_fx, 100, 2);/*check if it is in Q0*/ + st_fx->HQ_FEC_seed_fx = RANDOM_INITSEED; + move16(); + set16_fx( st_fx->delay_buf_out_fx, 0, HQ_DELTA_MAX*HQ_DELAY_COMP ); + set16_fx( st_fx->previoussynth_fx, 0, L_FRAME48k); + set16_fx( st_fx->old_synth_sw_fx, 0, NS2SA(48000,FRAME_SIZE_NS-ACELP_LOOK_NS-DELAY_BWE_TOTAL_NS) ); + set16_fx( st_fx->prev_noise_level_fx, 0, 2 ); + + st_fx->prev_R_fx = 0; + set32_fx( st_fx->prev_coeff_out_fx, 0, L_HQ_WB_BWE ); + set16_fx(st_fx->prev_SWB_peak_pos_fx, 0, SPT_SHORTEN_SBNUM); + + /* HQ GENERIC */ + st_fx->hq_generic_seed_fx = RANDOM_INITSEED; + move16(); + + st_fx->mem_norm_fx[0] = 31; + move16(); + set16_fx(st_fx->mem_norm_fx+1, 39, SFM_N_ENV_STAB-1); + st_fx->mem_env_delta_fx = 0; + move16(); + st_fx->no_att_hangover_fx = 0; + move16(); + st_fx->energy_lt_fx = 2457600; + move16(); /* 300 in Q13 */ + + st_fx->HqVoicing_fx = 0; + move16(); + set16_fx( st_fx->fer_samples_fx, 0, L_FRAME48k ); + set32_fx( st_fx->prev_env_fx, 0, SFM_N_WB ); + set32_fx( st_fx->prev_normq_fx, 0, SFM_N_WB ); + st_fx->prev_hqswb_clas_fx = HQ_NORMAL; + move16(); + + /* LRMDCT_DELTA_NOISE_INJECT_FX */ + set32_fx( st_fx->last_ni_gain_fx, 0x0L, BANDS_MAX ); + set16_fx( st_fx->last_env_fx, 0, BANDS_MAX ); + st_fx->last_max_pos_pulse_fx = 0; + move16(); + st_fx->prev_frm_hfe2_fx = 0; + move16(); + st_fx->prev_stab_hfe2_fx = 0; + move16(); + st_fx->prev_ni_ratio_fx = 16384; + move16(); /* 0.5 */ + set16_fx( st_fx->prev_En_sb_fx, 0, NB_SWB_SUBBANDS ); + + /* pre-echo reduction */ + reset_preecho_dec_fx( st_fx ); + + + /*----------------------------------------------------------------------------------* + * HQ FEC + *----------------------------------------------------------------------------------*/ + st_fx->old_synthFB_fx = st_fx->synth_history_fx + NS2SA_fx2(st_fx->output_Fs_fx, PH_ECU_MEM_NS); + st_fx->prev_good_synth_fx = st_fx->old_synthFB_fx + NS2SA_fx2(st_fx->output_Fs_fx, PH_ECU_LOOKAHEAD_NS); + set16_fx( st_fx->X_sav_fx, 0, PH_ECU_SPEC_SIZE ); + st_fx->Q_X_sav = 0; + move16(); + st_fx->num_p_fx = 0; + move16(); + st_fx->ph_ecu_active_fx = 0; + move16(); + st_fx->ni_seed_forfec = 0; + move16(); + st_fx->last_fec_fx = 0; + move16(); + st_fx->ph_ecu_HqVoicing_fx = 0; + move16(); + set16_fx( st_fx->oldgapsynth_fx, 0, L_FRAME48k ); + st_fx->env_stab_fx = 0x6000; /* 0.75 (Q15) */ move16(); + st_fx->mem_norm_hqfec_fx[0] = 31; + move16(); + set16_fx(st_fx->mem_norm_hqfec_fx+1, 39, SFM_N_ENV_STAB-1); + st_fx->mem_env_delta_hqfec_fx = 0; + move16(); + st_fx->env_stab_plc_fx = 0; + move16(); + set16_fx( st_fx->env_stab_state_p_fx, INV_NUM_ENV_STAB_PLC_STATES, NUM_ENV_STAB_PLC_STATES ); + st_fx->envstabplc_hocnt_fx = 0; + move16(); + set16_fx(st_fx->mag_chg_1st_fx, 32767, Lgw_max); + set16_fx(st_fx->Xavg_fx, 0, Lgw_max); + st_fx->beta_mute_fx = BETA_MUTE_FAC_INI; + move16(); + set16_fx( st_fx->prev_sign_switch_fx, 0, HQ_FEC_SIGN_SFM ); + set16_fx( st_fx->prev_sign_switch_2_fx, 0, HQ_FEC_SIGN_SFM ); + /* st->ni_seed_forfec = 0; */ + st_fx->time_offs_fx = 0; + move16(); + st_fx->ber_occured_in_pvq = 0; + move16(); + + /*-----------------------------------------------------------------* + * SWB BWE parameters + *-----------------------------------------------------------------*/ + st_fx->old_wtda_wb_fx_exp = 0; + move16(); + set16_fx( st_fx->old_syn_12k8_16k_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) ); + set16_fx( st_fx->L_old_wtda_swb_fx, 0, L_FRAME48k ); + st_fx->old_wtda_swb_fx_exp = 0; + move16(); + st_fx->mem_imdct_exp_fx = 0; + move16(); + + st_fx->prev_mode_fx = NORMAL; + move16(); + set16_fx( st_fx->prev_SWB_fenv_fx, 0, SWB_FENV ); + st_fx->prev_Energy_fx = 0; + move16(); + st_fx->prev_L_swb_norm_fx = 8; + move16(); + st_fx->Seed_fx = 21211; + move16(); + st_fx->prev_frica_flag_fx = 0; + move16(); + set16_fx( st_fx->mem_imdct_fx, 0, L_FRAME48k ); + st_fx->prev_td_energy_fx = 0; + move16(); + st_fx->prev_weight_fx = 6554; /*0.2 in Q15*/ move16(); + st_fx->prev_flag_fx = 0; + move16(); + st_fx->prev_coder_type_fx = GENERIC; + move16(); + st_fx->last_wb_bwe_ener_fx = 0; + move16(); + st_fx->prev_hb_synth_fx_exp = 0; + move16(); + st_fx->tilt_wb_fx = 0; + move16(); + + st_fx->prev_Energy_wb_fx = L_deposit_l(0); + + /*-----------------------------------------------------------------* + * TBE parameters + *-----------------------------------------------------------------*/ + + InitSWBdecBuffer_fx( st_fx ); + ResetSHBbuffer_Dec_fx(st_fx); + + IF( EQ_32(st_fx->output_Fs_fx,48000)) + { + set32_fx( st_fx->fbbwe_hpf_mem_fx[0], 0, 4 ); + set32_fx( st_fx->fbbwe_hpf_mem_fx[1], 0, 4 ); + set32_fx( st_fx->fbbwe_hpf_mem_fx[2], 0, 4 ); + set32_fx( st_fx->fbbwe_hpf_mem_fx[3], 0, 4 ); + set16_fx( st_fx->fbbwe_hpf_mem_fx_Q, 0, 4 ); + } + + set16_fx( st_fx->mem_resamp_HB_fx, 0, INTERP_3_1_MEM_LEN ); + set16_fx( st_fx->mem_resamp_HB_32k_fx, 0, 2*ALLPASSSECTIONS_STEEP+1 ); + set16_fx( st_fx->prev_synth_buffer_fx, 0, NS2SA_fx2(48000, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS) ); + set16_fx( st_fx->hb_prev_synth_buffer_fx, 0, NS2SA_fx2(48000, DELAY_BWE_TOTAL_NS) ); + st_fx->old_bwe_delay_fx = -1; /*Q0*/ move16(); + + st_fx->tilt_mem_fx = 0; + move16(); + set16_fx( st_fx->prev_lsf_diff_fx, 16384, LPC_SHB_ORDER-2 ); + st_fx->prev_tilt_para_fx = 0; + move16(); + set16_fx( st_fx->cur_sub_Aq_fx, 0, M+1 ); + set16_fx( st_fx->int_3_over_2_tbemem_dec_fx, 0, INTERP_3_2_MEM_LEN ); + set16_fx( st_fx->interpol_3_2_cng_dec_fx, 0, INTERP_3_2_MEM_LEN ); + + /* TD BWE post-processing */ + st_fx->ptr_mem_stp_swb_fx = st_fx->mem_stp_swb_fx + LPC_SHB_ORDER - 1; + set16_fx(st_fx->mem_zero_swb_fx, 0, LPC_SHB_ORDER); + + FOR ( i=0; iswb_lsp_prev_interp_fx[i] = swb_lsp_prev_interp_init[i]; + move16(); + } + + st_fx->prev1_shb_ener_sf_fx = 32767; /* Q15*/ move16(); + st_fx->prev2_shb_ener_sf_fx = 32767; /* Q15*/ move16(); + st_fx->prev3_shb_ener_sf_fx = 32767; /* Q15*/ move16(); + st_fx->prev_res_shb_gshape_fx = 8192; /* 0.125 in Q14*/ move16(); + st_fx->prev_mixFactors_fx = 16384; /* 0.5 in Q15*/ move16(); + st_fx->prev_GainShape_fx = 0; + move16(); + st_fx->prev_Q_bwe_exc_fb = 51; + move16(); + set16_fx( st_fx->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + st_fx->fb_tbe_demph_fx = 0; + move16(); + + + /*-----------------------------------------------------------------* + * WB/SWB bandwidth switching parameters + *-----------------------------------------------------------------*/ + + st_fx->tilt_swb_fx = 0; + move16(); + st_fx->prev_ener_fx = L_deposit_l(0); + st_fx->prev_ener_shb_fx = 0; + move16(); + st_fx->prev_enerLH_fx = 0; + move16(); + st_fx->enerLH_fx = L_deposit_l(0); + st_fx->enerLL_fx = L_deposit_l(0); + st_fx->prev_enerLL_fx = 0; + move16(); + st_fx->prev_fractive_fx = 0; + move16(); + st_fx->prev_bws_cnt_fx = 0; + move16(); + st_fx->bws_cnt_fx = N_WS2N_FRAMES; + move16(); + st_fx->bws_cnt1_fx = N_NS2W_FRAMES; + move16(); + st_fx->attenu_fx = 3277; + move16(); + st_fx->last_inner_frame_fx = L_FRAME8k; + move16(); + st_fx->last_bwidth_fx = 0; + move16(); + st_fx->prev_weight1_fx = 16384; + move16(); + + /*-----------------------------------------------------------------* + * channel-aware mode parameters + *-----------------------------------------------------------------*/ + + set16_fx( st_fx->tilt_code_dec_fx, 0, NB_SUBFR16k ); + + st_fx->use_partial_copy = 0; + move16(); + st_fx->prev_use_partial_copy = 0; + move16(); + st_fx->rf_flag = 0; + move16(); + st_fx->rf_flag_last = 0; + st_fx->prev_rf_frame_type = 0; + move16(); + st_fx->next_coder_type = 0; + move16(); + + st_fx->rf_target_bits = 0; + move16(); + + st_fx->rf_indx_nelp_fid = 0; + move16(); + st_fx->rf_indx_nelp_iG1 = 0; + move16(); + st_fx->rf_indx_nelp_iG2[0] = 0; + move16(); + st_fx->rf_indx_nelp_iG2[1] = 0; + move16(); + st_fx->rf_indx_tbeGainFr = 0; + move16(); + + /*-----------------------------------------------------------------* + * Improvement of unvoiced and audio signals in AMR-WB IO mode parameters + *-----------------------------------------------------------------*/ + + st_fx->UV_cnt_fx = 30; + move16(); + st_fx->LT_UV_cnt_fx = (60<<6); + move16(); + set16_fx( st_fx->lt_diff_etot_fx, 0, MAX_LT ); + st_fx->Last_ener_fx = 0; + move16(); + set16_fx(st_fx->old_Aq_fx, 0, 4*(M+1)); + st_fx->old_Aq_fx[0] = 16384; + move16(); + st_fx->old_Aq_fx[M+1] = 16384; + move16(); + st_fx->old_Aq_fx[2*(M+1)] = 16384; + move16(); + st_fx->old_Aq_fx[3*(M+1)] = 16384; + move16(); + st_fx->lt_voice_fac_fx = 0; + move16(); + + + /*-----------------------------------------------------------------* + * Postfilters + *-----------------------------------------------------------------*/ + + bass_psfilter_init_fx( st_fx->pst_old_syn_fx, &(st_fx->pst_mem_deemp_err_fx), &(st_fx->pst_lp_ener_fx) ); + st_fx->bpf_off_fx = 0; + move16(); + set16_fx( st_fx->Track_on_hist_fx, 0, L_TRACK_HIST ); + set16_fx( st_fx->vibrato_hist_fx, 0, L_TRACK_HIST ); + set16_fx( st_fx->mem_mean_pit_fx, 80, L_TRACK_HIST ); + st_fx->psf_att_fx = 32767; + move16(); + + /*-----------------------------------------------------------------* + * FD BPF & resampling tools parameters + *-----------------------------------------------------------------*/ + /* open analysis for max. SR 48kHz */ + openCldfb ( &st_fx->cldfbAna_fx, CLDFB_ANALYSIS, CLDFB_getNumChannels(48000), 320 ); + + /* open analysis BPF for max. SR 16kHz */ + openCldfb ( &st_fx->cldfbBPF_fx, CLDFB_ANALYSIS, CLDFB_getNumChannels(16000), 320 ); + + /* open synthesis for output SR */ + openCldfb ( &st_fx->cldfbSyn_fx, CLDFB_SYNTHESIS, CLDFB_getNumChannels(st_fx->output_Fs_fx), st_fx->output_frame_fx); + + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move32(); + st_fx->last_active_bandsToZero_bwdec = 0; + st_fx->flag_NB_bwddec = 0; + st_fx->perc_bwddec = 0; + st_fx->last_flag_filter_NB = 0; + st_fx->active_frame_cnt_bwddec = 0; + st_fx->total_frame_cnt_bwddec = 0; + set16_fx(st_fx->flag_buffer, 0, 20); + st_fx->avg_nrg_LT = 0; + + st_fx->Ng_ener_ST_fx = -13056; + move16(); /*-51 IN Q8*/ + st_fx->Last_frame_ener_fx = MAX_32; + move32(); + st_fx->old_Es_pred_fx = 0; + move16(); + set16_fx(st_fx->old_Aq_12_8_fx + 1, 0, M ); + st_fx->old_Aq_12_8_fx[0] = 4096; + move16(); /*1 in Q12*/ + + /*-----------------------------------------------------------------* + * SC-VBR + *-----------------------------------------------------------------*/ + st_fx->FadeScale_fx = 32767; + move16(); /* Q15*/ + st_fx->last_ppp_mode_dec_fx = 0; + move16(); + st_fx->old_ppp_mode_fx = 0; + move16(); + st_fx->ppp_mode_dec_fx = 0; + move16(); + st_fx->last_nelp_mode_dec_fx = 0; + move16(); + st_fx->nelp_mode_dec_fx = 0; + move16(); + st_fx->nelp_dec_seed_fx = 0; + move16(); + st_fx->firstTime_voiceddec_fx = 1; + move16(); + st_fx->prev_gain_pit_dec_fx = 0; + move16(); + st_fx->prev_tilt_code_dec_fx = 0; + move16(); + st_fx->vbr_hw_BWE_disable_dec_fx = 0; + move16(); + st_fx->last_vbr_hw_BWE_disable_dec_fx = 0; + move16(); + set16_fx( st_fx->old_hb_synth_fx, 0, L_FRAME48k ); + + /* DTFS variables */ + set16_fx( st_fx->dtfs_dec_a_fx, 0, MAXLAG_WI ); + set16_fx( st_fx->dtfs_dec_b_fx, 0, MAXLAG_WI ); + st_fx->dtfs_dec_lag_fx = 0; + move16(); + st_fx->dtfs_dec_nH_fx = 0; + move16(); + st_fx->dtfs_dec_nH_4kHz_fx = 0; + move16(); + st_fx->dtfs_dec_upper_cut_off_freq_of_interest_fx = 0; + move16(); + st_fx->dtfs_dec_upper_cut_off_freq_fx = 0; + move16(); + st_fx->ph_offset_D_fx = 0; + move16(); + st_fx->lastLgainD_fx = 0; + move16(); + st_fx->lastHgainD_fx = 0; + move16(); + set16_fx( st_fx->lasterbD_fx, 0, NUM_ERB_WB ); + st_fx->dtfs_dec_Q = 0; + move16(); + + /* NELP decoder variables */ + set32_fx( st_fx->bp1_filt_mem_nb_dec_fx, 0, 14 ); + set16_fx( st_fx->bp1_filt_mem_wb_dec_fx, 0, 8 ); + set16_fx( st_fx->shape1_filt_mem_dec_fx, 0, 10 ); + set16_fx( st_fx->shape2_filt_mem_dec_fx, 0, 10 ); + set16_fx( st_fx->shape3_filt_mem_dec_fx, 0, 10 ); + /* IGF */ + st_fx->igf = 0; + move16(); + set16_fx( (Word16*)&st_fx->hIGFDec, 0, (sizeof(st_fx->hIGFDec)+1)/sizeof(Word16) ); + st_fx->hIGFDec.igfData.igfInfo.nfSeed = 9733; + move16(); + + st_fx->enablePlcWaveadjust = 0; + move16(); + + /* Init Decoder */ + open_decoder_LPD( st_fx, st_fx->total_brate_fx, st_fx->bwidth_fx); + + st_fx->m_decodeMode = DEC_NO_FRAM_LOSS; + move16(); + st_fx->m_frame_type = ACTIVE_FRAME; + move16(); + st_fx->m_old_frame_type = ACTIVE_FRAME; + move16(); + + + newCldfbBands = CLDFB_getNumChannels(L_mult0(st_fx->L_frame_fx, 50)); + + resampleCldfb( st_fx->cldfbAna_fx, newCldfbBands, st_fx->L_frame_fx, 1 ); + resampleCldfb( st_fx->cldfbBPF_fx, newCldfbBands, st_fx->L_frame_fx, 1 ); + + /* Create FD_CNG instance */ + createFdCngDec(&st_fx->hFdCngDec_fx); + + /* Init FD-CNG */ + initFdCngDec( st_fx->hFdCngDec_fx, st_fx->cldfbSyn_fx->scale ); + + st_fx->lp_noise = -167772160l/*-20.f Q23*/; + st_fx->force_lpd_reset = 0; + move16(); + + /*-----------------------------------------------------------------* + * initialzie Q values + *-----------------------------------------------------------------*/ + + st_fx->memExp1 = 0; + move16(); + st_fx->Q_syn2 = 0; + move16(); + st_fx->Q_exc = 8; + st_fx->prev_Q_exc = 0; + move16(); + st_fx->Q_syn = 0; + move16(); + st_fx->prev_Q_syn = 0; + move16(); + + FOR(i=0; iQ_subfr[i] = 8; + move16(); + } + + /* Previous frame LPC initialization for PPP */ + st_fx->prev_Q_synth = 0; + move16(); + + st_fx->prev_Q_exc_fr = 0; + move16(); + st_fx->prev_Q_syn_fr = 0; + move16(); + + return; + +} + + +/*----------------------------------------------------------------------* + * reset_preecho_dec() + * + * Initialization of static variables for pre-echo + *----------------------------------------------------------------------*/ + +void reset_preecho_dec_fx( + Decoder_State_fx *st_fx /* i/o: Decoder static variables structure */ +) +{ + st_fx->memfilt_lb_fx = 0; + move16(); + st_fx->mean_prev_hb_fx = L_deposit_l(0); + st_fx->smoothmem_fx = 32767; + move16(); + st_fx->mean_prev_fx = L_deposit_l(0); + st_fx->mean_prev_nc_fx = L_deposit_l(0); + st_fx->wmold_hb_fx = 32767; + move16(); + st_fx->prevflag_fx = 0; + move16(); + st_fx->pastpre_fx = 0; + move16(); + + return; +} + + +/*----------------------------------------------------------------------* + * destroy_decoder() + * + * Free memory which was allocated in init_decoder() + *----------------------------------------------------------------------*/ + +void destroy_decoder( + Decoder_State_fx *st_fx /* o: Decoder static variables structure */ +) +{ + + /* CLDFB BPF & resampling tools */ + + /* delete analysis for max. SR 16kHz */ + deleteCldfb(&st_fx->cldfbAna_fx); + + /* delete analysis BPF for max. SR 16kHz */ + deleteCldfb(&st_fx->cldfbBPF_fx); + + /* delete synthesis for output SR */ + deleteCldfb(&st_fx->cldfbSyn_fx); + + deleteFdCngDec( &st_fx->hFdCngDec_fx ); + + return; +} diff --git a/lib_dec/inov_dec_fx.c b/lib_dec/inov_dec_fx.c new file mode 100644 index 0000000..9698229 --- /dev/null +++ b/lib_dec/inov_dec_fx.c @@ -0,0 +1,135 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" + +/*======================================================================*/ +/* FUNCTION : inov_decode_fx() */ +/*-----------------------------------------------------------------------*/ +/* PURPOSE : Decode the algebraic innovation and do pitch sharpening */ +/* */ +/*-----------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word32) core_brate : Core bitrate Q0 */ +/* _ (Word16) Opt_AMR_WB : flag indicating AMR-WB IO mode Q0 */ +/* _ (Word16) L_frame : length of the frame Q0 */ +/* _ (Word16) i_subfr : length of the frame Q0 */ +/* _ (Word16) coder_type : coding type */ +/* _ (Word16) L_subfr : subframe length */ +/* _ (Word16) sharpFlag : formant sharpening flag */ +/* _ (Word16) tc_subfr : TC subframe index */ +/* _ (Word16 *) p_Aq : LP filter coefficients Q12 */ +/* _ (Word16) tilt_code : tilt of the excitation of previous subframe Q15*/ +/* _ (Word16) pt_pitch : current subframe fractional pitch Q6 */ +/*-----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 *[]) code : subframe length Q12 */ +/* _ (Word16 []) index_buf_4T : subframe length */ +/*-----------------------------------------------------------------------*/ +/* INPUT OUTPUT ARGUMENTS */ +/*-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*=======================================================================*/ + +void inov_decode_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + const Word16 sharpFlag, /* i : formant sharpening flag */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 *p_Aq, /* i : LP filter coefficients Q12 */ + const Word16 tilt_code, /* i : tilt of the excitation of previous subframe Q15 */ + const Word16 pt_pitch, /* i : pointer to current subframe fractional pitch Q6*/ + Word16 *code /* o : algebraic excitation */ +) +{ + Word16 nBits; + Word16 g1, g2; + + IF( EQ_16(L_frame,L_FRAME)) + { + g1 = FORMANT_SHARPENING_G1; + g2 = FORMANT_SHARPENING_G2; + } + ELSE + { + g1 = FORMANT_SHARPENING_G1_16k; + g2 = FORMANT_SHARPENING_G2_16k; + } + + IF ( !Opt_AMR_WB ) + { + IF( EQ_16(L_frame, L_FRAME)) + { + nBits = FCB_bits_tbl[BIT_ALLOC_IDX_fx(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_fx(tc_subfr))]; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + nBits = FCB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ_fx(tc_subfr))]; + move16(); + } + IF(EQ_16(nBits,7)) + { + dec_acelp_1t64_fx(st_fx, code); + } + ELSE IF( EQ_16(nBits,12)) + { + dec_acelp_2t32_fx( st_fx, code ); + } + ELSE + { + dec_acelp_4t64_fx( st_fx, nBits, code, Opt_AMR_WB ); + } + } + ELSE + { + IF ( EQ_32(core_brate,ACELP_6k60)) + { + dec_acelp_2t32_fx( st_fx, code ); + } + ELSE IF ( EQ_32(core_brate,ACELP_8k85)) + { + dec_acelp_4t64_fx( st_fx, 20, code, Opt_AMR_WB ); + } + ELSE IF ( EQ_32(core_brate,ACELP_12k65)) + { + dec_acelp_4t64_fx( st_fx, 36, code, Opt_AMR_WB ); + } + ELSE IF ( EQ_32(core_brate,ACELP_14k25)) + { + dec_acelp_4t64_fx( st_fx, 44, code, Opt_AMR_WB ); + } + ELSE IF ( EQ_32(core_brate,ACELP_15k85)) + { + dec_acelp_4t64_fx( st_fx, 52, code, Opt_AMR_WB ); + } + ELSE IF ( EQ_32(core_brate,ACELP_18k25)) + { + dec_acelp_4t64_fx( st_fx, 64, code, Opt_AMR_WB ); + } + ELSE IF ( EQ_32(core_brate,ACELP_19k85)) + { + dec_acelp_4t64_fx( st_fx, 72, code, Opt_AMR_WB ); + } + ELSE + { + dec_acelp_4t64_fx( st_fx, 88, code, Opt_AMR_WB ); + } + } + + cb_shape_fx( 1, 1, 0, sharpFlag, 0, g1, g2, p_Aq, code, tilt_code, shr(add(pt_pitch,26),6), 0 ); + return; + +} diff --git a/lib_dec/io_dec_fx.c b/lib_dec/io_dec_fx.c new file mode 100644 index 0000000..50aaa01 --- /dev/null +++ b/lib_dec/io_dec_fx.c @@ -0,0 +1,497 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "options.h" /* Compilation switches */ +#include "stl.h" +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "disclaimer.h" /*for disclaimer*/ +#include "basop_util.h" +#include "mime.h" +#include +/* WMC_TOOL_SKIP_FILE */ + +/*---------------------------------------------------------------------* +* Local functions +*---------------------------------------------------------------------*/ + +static void usage_dec(void); +static char *to_upper( char *str ); + +static char * bit_rate_to_string(char *string, Word32 bit_rate) +{ + char *src, *dst; + /* NO_DATA is also an allowed bit rate */ + if ( bit_rate <= 0) + { + sprintf(string, "0.00"); + return string; + } + assert(bit_rate >= 100); + src = string + sprintf(string, "%i", bit_rate); + /* Insert a '.' before last two digits and remove last digit */ + /* What we want is to print %.2f of bit_rate/1000.0 */ + dst = src--; + *--dst = *--src; + *--dst = *--src; + *--dst = '.'; + + return string; +} +/*---------------------------------------------------------------------* + * io_ini_dec() + * + * Processing of command line parameters + *---------------------------------------------------------------------*/ + +void io_ini_dec_fx( + const int argc, /* i : command line arguments number */ + char *argv[], /* i : command line arguments */ + FILE **f_stream, /* o : input bitstream file */ + FILE **f_synth, /* o : output synthesis file */ + Word16 *quietMode, /* o : limited printouts */ + Word16 *noDelayCmp, /* o : turn off delay compensation */ + Decoder_State_fx *st_fx, /* o : Decoder static variables structure */ +#ifdef SUPPORT_JBM_TRACEFILE + char **jbmTraceFileName, /* o : VOIP tracefilename */ +#endif + char **jbmFECoffsetFileName /* : Output file for Optimum FEC offset */ +) +{ + short i; + char stmp[50]; + Word16 evs_magic, amrwb_magic; + char bit_rate_string[14]; +#ifdef DEBUGGING + short i_FEC_pattern = 0; +#endif + print_disclaimer(stderr); + + /*-----------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + i = 1; + *f_synth = NULL; + *f_stream = NULL; + st_fx->Opt_AMR_WB_fx = 0; + st_fx->Opt_VOIP_fx = 0; + set_zero_Word8((Word8 *)stmp, sizeof(stmp)); + + st_fx->bitstreamformat = G192; + st_fx->amrwb_rfc4867_flag = -1; + + IF ( argc <= 1 ) + { + usage_dec(); + } + + /*-----------------------------------------------------------------* + * Optional input arguments + *-----------------------------------------------------------------*/ + + WHILE ( i < argc-3 ) + { + /*-----------------------------------------------------------------* + * VOIP mode + *-----------------------------------------------------------------*/ + + IF ( strcmp( to_upper(argv[i]), "-VOIP") == 0) + { + st_fx->Opt_VOIP_fx = 1; + move16(); + st_fx->bitstreamformat = VOIP_G192_RTP; + i += 1; + } + ELSE IF ( strcmp( to_upper(argv[i]), "-VOIP_HF_ONLY=0") == 0) + { + st_fx->Opt_VOIP_fx = 1; + st_fx->bitstreamformat = VOIP_RTPDUMP; + st_fx->sdp_hf_only = 0; + i += 1; + } + ELSE IF ( strcmp( to_upper(argv[i]), "-VOIP_HF_ONLY=1") == 0) + { + st_fx->Opt_VOIP_fx = 1; + st_fx->bitstreamformat = VOIP_RTPDUMP; + st_fx->sdp_hf_only = 1; + i += 1; + } +#ifdef SUPPORT_JBM_TRACEFILE + /*-----------------------------------------------------------------* + * VOIP Tracefile + *-----------------------------------------------------------------*/ + + ELSE IF ( strcmp( to_upper(argv[i]), "-TRACEFILE" ) == 0 ) + { + *jbmTraceFileName = argv[i+1]; + i = i + 2; + } +#endif + /*-----------------------------------------------------------------* + * FEC offset file + *-----------------------------------------------------------------*/ + + ELSE IF ( strcmp( to_upper(argv[i]), "-FEC_CFG_FILE" ) == 0 ) + { + st_fx->writeFECoffset = 1; + *jbmFECoffsetFileName = argv[i+1]; + i = i + 2; + } +#ifdef DEBUGGING + ELSE IF(strcmp(to_upper(argv[i]), "-FEC") == 0) + { + float ftmp = 0.0f; + if (sscanf(argv[i + 1], "%f", &ftmp) != 1) + { + if ((FEC_pattern = fopen(argv[i + 1], "rb")) == NULL) + { + fprintf(stderr, "Error: Missing or incorrect FEC specification\n\n"); + usage_dec(); + } + + i_FEC_pattern = i + 1; + } + else + { + if (ftmp < 0 || ftmp >= 20) + { + fprintf(stderr, "Error: Missing or incorrect FEC specification\n\n"); + usage_dec(); + } + + FEC_random = ftmp; + } + + i += 2; + } +#endif + /*-----------------------------------------------------------------* + * Quiet mode + *-----------------------------------------------------------------*/ + + ELSE IF ( strcmp( to_upper(argv[i]), "-Q" ) == 0 ) + { + *quietMode = 1; + move16(); + i++; + } + + /*-----------------------------------------------------------------* + * deactivate delay compensation + *-----------------------------------------------------------------*/ + + ELSE IF ( strcmp( to_upper(argv[i]), "-NO_DELAY_CMP" ) == 0 ) + { + *noDelayCmp = 1; + i++; + } + + /*-----------------------------------------------------------------* + * MIME input file format + *-----------------------------------------------------------------*/ + ELSE IF( strcmp( to_upper(argv[i]), "-MIME" ) == 0 ) + { + st_fx->bitstreamformat = MIME; + st_fx->amrwb_rfc4867_flag = 0; + i++; + } + + /*-----------------------------------------------------------------* + * Option not recognized + *-----------------------------------------------------------------*/ + + ELSE + { + fprintf(stderr, "Error: Unknown option %s\n\n", argv[i]); + usage_dec(); + } + + } /* end of while */ + + + /*-----------------------------------------------------------------* + * Mandatory input arguments + *-----------------------------------------------------------------*/ + + /*-----------------------------------------------------------------* + * Output sampling frequency + *-----------------------------------------------------------------*/ + + if( i < argc - 2 ) + { + st_fx->output_Fs_fx = (int)atoi( argv[i] ) * 1000; + if( st_fx->output_Fs_fx != 8000 && st_fx->output_Fs_fx != 16000 && st_fx->output_Fs_fx != 32000 && st_fx->output_Fs_fx != 48000 ) + { + fprintf(stderr, "Error: %d kHz is not a supported sampling rate\n\n", atoi( argv[i] ) ); + usage_dec(); + } + + i++; + } + else + { + fprintf (stderr, "Error: Sampling rate is not specified\n\n"); + usage_dec(); + } + /*-----------------------------------------------------------------* + * Input bitstream file + *-----------------------------------------------------------------*/ + + if( i < argc - 1 ) + { + if ( (*f_stream = fopen(argv[i], "rb")) == NULL) + { + fprintf(stderr,"Error: input bitstream file %s cannot be opened\n\n", argv[i]); + usage_dec(); + } + /* If MIME/storage format selected, scan for the magic number at the beginning of the bitstream file */ + if( st_fx->bitstreamformat == MIME ) + { + char buf[13]; + evs_magic = 1 ; + amrwb_magic = 1; + + if(NULL == fgets(buf, 13, *f_stream)) + { + fprintf(stderr,"Error: input bitstream file %s cannot be read\n\n", argv[i]); + usage_dec(); + } + + /* verify AMRWB magic number */ + if ( strncmp(buf, AMRWB_MAGIC_NUMBER, strlen(AMRWB_MAGIC_NUMBER))) + { + amrwb_magic = 0; + } + + if ( strncmp(buf, EVS_MAGIC_NUMBER, strlen(EVS_MAGIC_NUMBER))) /* strncmp safer than strcmp */ + { + evs_magic = 0; + } + + if( evs_magic != 0 ) + { + if ((fread(&buf,sizeof(char), 4, *f_stream) != 4 ) || !((buf[3] == 1) && (buf[2] == 0) && (buf[1] == 0) && (buf[0] == 0)) ) + { + fprintf(stderr, "Error: input bitstream file %s specifies unsupported number of evs audio channels\n\n",argv[i]); + usage_dec(); + } + } + + if( evs_magic == 0 && amrwb_magic == 0 ) + { + /* no valid MIME magic number */ + fprintf(stderr, "Error: input bitstream file %s specifies unsupported MIME magic number (%13s) \n\n",argv[i],buf ); + usage_dec(); + } + + if( evs_magic ) + { + fprintf( stderr, "Found MIME Magic number %s\n", EVS_MAGIC_NUMBER ); + st_fx->amrwb_rfc4867_flag = 0; + } + else + { + fprintf( stderr, "Found MIME Magic number %s\n",AMRWB_MAGIC_NUMBER ); + st_fx->amrwb_rfc4867_flag = 1; + st_fx->Opt_AMR_WB_fx = 1; /* needed in case first initial RFC4867 frames/ToCs are lost */ + } + } + else if( st_fx->Opt_VOIP_fx == 0 ) + { + /* G.192 format .... preread the G.192 sync header */ + UWord16 utmp; + if ( fread( &utmp, sizeof(unsigned short), 1, *f_stream ) != 1 ) + { + /* error during pre-reading */ + if( ferror( *f_stream ) ) + { + fprintf(stderr, "Error: input G.192 bitstream file %s , can not be read \n\n",argv[i] ); + } + else + { + fprintf(stderr, "Error: input G.192 bitstream file %s , has zero size, can not be read \n\n",argv[i] ); + } + usage_dec(); + } + if( (NE_16(utmp, SYNC_GOOD_FRAME))&&(NE_16(utmp,SYNC_BAD_FRAME))) + { + /* check for a valid first G.192 synch word in Sync Header */ + fprintf(stderr, "Error: input bitstream file %s does not have a valid G.192 synch word value \n\n",argv[i]); + usage_dec(); + } + /* now rewind the G.192 bitstream file */ + fseek( *f_stream , 0L, SEEK_SET ); + } + /* JBM format */ + + fprintf( stderr, "Input bitstream file: %s\n", argv[i]); + i++; + + } + else + { + fprintf (stderr, "Error: no input bitstream file specified\n\n"); + usage_dec(); + } + + /*-----------------------------------------------------------------* + * Output synthesis file + *-----------------------------------------------------------------*/ + + if( i < argc ) + { + if ( (*f_synth = fopen(argv[i], "wb")) == NULL ) + { + fprintf( stderr, "Error: ouput synthesis file %s cannot be opened\n\n", argv[i] ); + usage_dec(); + } + + fprintf( stdout, "Output synthesis file: %s\n", argv[i] ); + i++; + } + else + { + fprintf( stderr, "Error: no output synthesis file specified\n\n" ); + usage_dec(); + } + fprintf( stdout, "\n" ); + + if( !st_fx->Opt_VOIP_fx ) + { + /*-----------------------------------------------------------------* + * Read information from bitstream + *-----------------------------------------------------------------*/ + if( st_fx->bitstreamformat == G192 ) + { + read_indices_fx( st_fx, *f_stream, 1 ); /* rew_flag == 1 , reads future frames */ + } + else + { + read_indices_mime( st_fx, *f_stream, 1 ); /* rew_flag == 1 , checks only very first frame */ + if( st_fx->amrwb_rfc4867_flag != 0 ) + { + fseek(*f_stream,strlen(AMRWB_MAGIC_NUMBER),SEEK_SET); /* restart after 9 bytes */ + } + else + { + fseek(*f_stream,strlen(EVS_MAGIC_NUMBER)+4, SEEK_SET); /* restart after 16 bytes */ + } + } + + /*-----------------------------------------------------------------* + * Print info on screen + *-----------------------------------------------------------------*/ +#ifdef DEBUGGING + /*-----------------------------------------------------------------* + * Print information about FEC + *-----------------------------------------------------------------*/ + + if (!st_fx->Opt_VOIP_fx && (FEC_pattern != NULL || FEC_random > 0)) + { + if (FEC_pattern != NULL) + { + fprintf(stdout, "FEC: %s\n", argv[i_FEC_pattern]); + } + else + { + fprintf(stdout, "FEC: %.2f %%\n", FEC_random); + } + } +#endif + /*-----------------------------------------------------------------* + * Print output sampling frequency + *-----------------------------------------------------------------*/ + + fprintf( stdout, "Output sampling rate: %d Hz\n", st_fx->output_Fs_fx ); + + /*-----------------------------------------------------------------* + * Print bitrate + *-----------------------------------------------------------------*/ + + fprintf( stdout, "Bitrate: %s kbps\n", bit_rate_to_string(bit_rate_string, st_fx->total_brate_fx) ); + if ( st_fx->total_brate_fx <= 0 ) + { + if( st_fx->bitstreamformat == G192 ) + { + fprintf( stdout, "Active Bitrate not identified in bitstream file \n" ); + } + else + { + /* MIME */ + fprintf( stdout, "Active Bitrate not identified from first MIME frame \n" ); + } + } + + } + + return; +} + +/*---------------------------------------------------------------------* + * to_upper() + * + * Capitalize all letters of a string. + * (normally to_upper() function would be used but it does not work in Unix) + *---------------------------------------------------------------------*/ + +static char *to_upper( char *str ) +{ + short i; + char *p = str; + + i = 0; + while (str[i] != 0) + { + if (str[i] >= 'a' && str[i] <= 'z') str[i] -= 0x20; + i++; + } + + return p; +} + +static void usage_dec( void ) +{ + fprintf(stdout, "Usage: EVS_dec.exe [Options] Fs bitstream_file output_file\n\n"); + + fprintf(stdout, "Mandatory parameters:\n"); + fprintf(stdout, "---------------------\n"); + fprintf(stdout, "Fs : Output sampling rate in kHz (8, 16, 32 or 48)\n"); + fprintf(stdout, "bitstream_file : Input bitstream filename (*.192) or RTP packet filename (in VOIP mode)\n"); + fprintf(stdout, "output_file : Output audio filename (*.8k, *.16k, *.32k, *.48k)\n\n"); + + fprintf(stdout, "Options:\n"); + fprintf(stdout, "--------\n"); + + fprintf(stdout, "-VOIP : VoIP mode: RTP in G192\n"); + fprintf(stdout, "-VOIP_hf_only=0 : VoIP mode: EVS RTP Payload Format hf_only=0 in rtpdump\n"); + fprintf(stdout, "-VOIP_hf_only=1 : VoIP mode: EVS RTP Payload Format hf_only=1 in rtpdump\n"); + fprintf(stdout, " The decoder may read rtpdump files containing TS26.445 Annex A.2.2\n"); + fprintf(stdout, " EVS RTP Payload Format. The SDP parameter hf_only is required.\n"); + fprintf(stdout, " Reading RFC4867 AMR/AMR-WB RTP payload format is not supported.\n"); +#ifdef SUPPORT_JBM_TRACEFILE + fprintf(stdout, "-Tracefile TF : VoIP mode: Generate trace file named TF\n"); +#endif +#ifdef DEBUGGING + fprintf(stdout, "\n-FEC X : Insert frame erasures, X = 0-10 is the percentage\n\n"); +#endif + fprintf(stdout, "-fec_cfg_file RF : VoIP mode: Optimal channel aware configuration computed by the JBM\n"); + fprintf(stdout, " as described in Section 6.3.1 of TS26.448. The output is\n"); + fprintf(stdout, " written into a file named RF. Each line contains the FER indicator\n"); + fprintf(stdout, " (HI|LO) and optimal FEC offset.\n"); + + fprintf(stdout, "-no_delay_cmp : Turn off delay compensation\n"); + fprintf(stdout, "-mime : Mime bitstream file format\n"); + fprintf(stdout, " The decoder may read both TS26.445 Annex A.2.6 and RFC4867 Mime Storage\n"); + fprintf(stdout, " Format files, the magic word in the mime file is used to determine\n"); + fprintf(stdout, " which of the two supported formats is in use.\n"); + fprintf(stdout, " default bitstream file format is G.192\n"); + fprintf(stdout, "-q : Quiet mode, no frame counter\n"); + fprintf(stdout, " default is deactivated\n"); + fprintf(stdout, "\n"); + exit(-1); +} diff --git a/lib_dec/jbm_jb4_circularbuffer.c b/lib_dec/jbm_jb4_circularbuffer.c new file mode 100644 index 0000000..d76fa35 --- /dev/null +++ b/lib_dec/jbm_jb4_circularbuffer.c @@ -0,0 +1,422 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/** \file jbm_jb4_circularbuffer.c circular buffer (FIFO) with fixed capacity */ + +/* system includes */ +#include +#include +#include +/* local includes */ +#include "jbm_jb4_circularbuffer.h" +/* instrumentation */ +#include "stl.h" +#include "options.h" +#include "basop_util.h" + + +/** Calculates percentile by selecting greatest elements. + * This function partial sorts all given elements in the given buffer. + * @param[in,out] elements ascending sorted buffer of selected greatest elements + * @param[in,out] size size of elements buffer + * @param[in] capacity maximum number of elements to buffer + * @param[in] newElement element to insert in buffer if great enough */ +static void JB4_CIRCULARBUFFER_calcPercentile( JB4_CIRCULARBUFFER_ELEMENT *elements, + Word32 *size, Word32 capacity, JB4_CIRCULARBUFFER_ELEMENT newElement ); + + +/** circular buffer (FIFO) with fixed capacity */ +struct JB4_CIRCULARBUFFER +{ + /** elements of circular buffer */ + JB4_CIRCULARBUFFER_ELEMENT *data; + /** maximum allowed number of elements plus one free element (to decide between full/empty buffer) */ + Word16 capacity; + /** position of next enque operation */ + Word16 writePos; + /** position of next deque operation */ + Word16 readPos; +}; + + +/* Creates a circular buffer (FIFO) */ +Word16 JB4_CIRCULARBUFFER_Create( JB4_CIRCULARBUFFER_HANDLE *ph ) +{ + JB4_CIRCULARBUFFER_HANDLE h = malloc( sizeof( struct JB4_CIRCULARBUFFER ) ); + + h->data = NULL; + move16(); + h->capacity = 0; + move16(); + h->writePos = 0; + move16(); + h->readPos = 0; + move16(); + + *ph = h; + move16(); + return 0; +} + +/* Destroys the circular buffer (FIFO) */ +void JB4_CIRCULARBUFFER_Destroy( JB4_CIRCULARBUFFER_HANDLE *ph ) +{ + JB4_CIRCULARBUFFER_HANDLE h; + + IF( !ph ) + { + return; + } + h = *ph; + move16(); + IF( !h ) + { + return; + } + + if( h->data ) + free( h->data ); + free( h ); + *ph = NULL; + move16(); +} + +/* Initializes a circular buffer (FIFO) with a fixed maximum allowed number of elements */ +Word16 JB4_CIRCULARBUFFER_Init( JB4_CIRCULARBUFFER_HANDLE h, Word16 capacity ) +{ + + /* keep one element free to be able to decide between full/empty buffer */ + capacity = add( capacity, 1 ); + + h->data = malloc( capacity * sizeof( JB4_CIRCULARBUFFER_ELEMENT ) ); + + h->capacity = capacity; + move16(); + h->writePos = 0; + move16(); + h->readPos = 0; + move16(); + + return 0; +} + +Word16 JB4_CIRCULARBUFFER_Enque( JB4_CIRCULARBUFFER_HANDLE h, JB4_CIRCULARBUFFER_ELEMENT element ) +{ + + IF( JB4_CIRCULARBUFFER_IsFull( h ) ) + { + return -1; + } + + h->data[h->writePos] = element; + move32(); + h->writePos = add( h->writePos, 1 ); + + if( EQ_16( h->capacity, h->writePos )) + { + h->writePos = 0; + move16(); + } + return 0; +} + +Word16 JB4_CIRCULARBUFFER_Deque( JB4_CIRCULARBUFFER_HANDLE h, JB4_CIRCULARBUFFER_ELEMENT *pElement ) +{ + + IF( JB4_CIRCULARBUFFER_IsEmpty( h ) ) + { + return -1; + } + + *pElement = h->data[h->readPos]; + move32(); + h->readPos = add( h->readPos, 1 ); + + if( EQ_16( h->capacity, h->readPos )) + { + h->readPos = 0; + move16(); + } + return 0; +} + +/* Returns the first element. */ +JB4_CIRCULARBUFFER_ELEMENT JB4_CIRCULARBUFFER_Front( const JB4_CIRCULARBUFFER_HANDLE h ) +{ + JB4_CIRCULARBUFFER_ELEMENT ret; + + ret = L_add(h->data[h->readPos], 0); + return ret; +} + +/* Returns the last element. */ +JB4_CIRCULARBUFFER_ELEMENT JB4_CIRCULARBUFFER_Back( const JB4_CIRCULARBUFFER_HANDLE h ) +{ + Word16 retPos; + + retPos = sub( h->writePos, 1 ); + if( h->writePos == 0 ) + retPos = sub( h->capacity, 1 ); + + return h->data[ retPos ]; +} + +Word16 JB4_CIRCULARBUFFER_IsEmpty( const JB4_CIRCULARBUFFER_HANDLE h ) +{ + Word16 ret; + + ret = 0; + move16(); + + if( EQ_16( h->readPos, h->writePos )) + ret = 1; + move16(); + return ret; +} + +Word16 JB4_CIRCULARBUFFER_IsFull( const JB4_CIRCULARBUFFER_HANDLE h ) +{ + Word16 ret; + Word16 writePosInc; + + writePosInc = add( h->writePos, 1 ); + /* check if writePos++ should wrap around */ + if( EQ_16( writePosInc, h->capacity )) + writePosInc = 0; + move16(); + + ret = 0; + move16(); + + if( EQ_16( writePosInc, h->readPos )) + ret = 1; + move16(); + return ret; +} + +Word16 JB4_CIRCULARBUFFER_Size( const JB4_CIRCULARBUFFER_HANDLE h ) +{ + Word16 ret; + + ret = sub( h->writePos, h->readPos ); + /* if wrap around */ + if( ret < 0 ) + ret = add( ret, h->capacity ); + return ret; +} + +/* Calculates statistics over all elements: min element */ +void JB4_CIRCULARBUFFER_Min( const JB4_CIRCULARBUFFER_HANDLE h, JB4_CIRCULARBUFFER_ELEMENT *pMin ) +{ + Word16 upperMinElePos, lowerMinElePos; + + IF( JB4_CIRCULARBUFFER_IsEmpty(h) ) + { + *pMin = 0; + move32(); + return; + } + BASOP_SATURATE_WARNING_OFF + IF( GT_16( h->writePos, h->readPos )) + { + /* no wraparound */ + /* calc statistics for [readPos;writePos[ */ + upperMinElePos = findIndexOfMinWord32( &(h->data[h->readPos] ), sub( h->writePos, h->readPos ) ); + *pMin = h->data[ add( h->readPos, upperMinElePos ) ]; + move32(); + } + ELSE + { + /* find min for [readPos;capacity[ */ + upperMinElePos = findIndexOfMinWord32( &(h->data[h->readPos] ), sub( h->capacity, h->readPos ) ); + *pMin = h->data[ add( h->readPos, upperMinElePos ) ]; + move32(); + + /* special case where writePos is pointing to start of buffer then there are actually no values in + * lower region so skip lower region find() (find requires at least two elements in the region) */ + IF( h->writePos == 0 ) + { + BASOP_SATURATE_WARNING_ON + return; + } + + /* otherwise find min for [0;writePos[ */ + lowerMinElePos = findIndexOfMinWord32( h->data, h->writePos ); + + if( GT_32( *pMin, h->data[lowerMinElePos] )) + *pMin = h->data[ lowerMinElePos ]; + move32(); + } + BASOP_SATURATE_WARNING_ON +} + +/* Calculates statistics over all elements: max element */ +void JB4_CIRCULARBUFFER_Max( const JB4_CIRCULARBUFFER_HANDLE h, JB4_CIRCULARBUFFER_ELEMENT *pMax ) +{ + Word16 upperMaxElePos, lowerMaxElePos; + + IF( JB4_CIRCULARBUFFER_IsEmpty(h) ) + { + *pMax = 0; + move32(); + return; + } + BASOP_SATURATE_WARNING_OFF + IF( GT_16( h->writePos, h->readPos )) + { + /* no wraparound */ + /* find max for [readPos;writePos[ */ + upperMaxElePos = findIndexOfMaxWord32( &(h->data[h->readPos] ), sub( h->writePos, h->readPos ) ); + *pMax = h->data[ add( h->readPos, upperMaxElePos ) ]; + move32(); + } + ELSE + { + /* find max for [readPos;capacity[ */ + upperMaxElePos = findIndexOfMaxWord32( &(h->data[h->readPos] ), sub( h->capacity, h->readPos ) ); + *pMax = h->data[ add( h->readPos, upperMaxElePos ) ]; + move32(); + + /* special case where writePos is pointing to start of buffer then there are actually no values in + * lower region so skip lower region find() (find requires at least two elements in the region) */ + IF( h->writePos == 0 ) + { + BASOP_SATURATE_WARNING_ON + return; + } + + /* otherwise find max for [0;writePos[ */ + lowerMaxElePos = findIndexOfMaxWord32( h->data, h->writePos ); + + if( GT_32( h->data[lowerMaxElePos], *pMax )) + *pMax = h->data[ lowerMaxElePos ]; + move32(); + } + BASOP_SATURATE_WARNING_ON +} + +/* Calculates statistics over a considered fraction of all elements: min element and percentile */ +void JB4_CIRCULARBUFFER_MinAndPercentile( const JB4_CIRCULARBUFFER_HANDLE h, Word32 nElementsToIgnore, + JB4_CIRCULARBUFFER_ELEMENT *pMin, JB4_CIRCULARBUFFER_ELEMENT *pPercentile ) +{ + JB4_CIRCULARBUFFER_ELEMENT minEle; + JB4_CIRCULARBUFFER_ELEMENT maxElements[100]; + Word32 maxElementsSize; + Word32 maxElementsCapacity; + Word32 i; + + /* init output variables */ + minEle = L_add(h->data[h->readPos], 0); + + /* To calculate the percentile, a number of elements with the highest values are collected in maxElements in + * ascending sorted order. This array has a size of nElementsToIgnore plus one. This additional element is the + * lowest of all maxElements, and is called the percentile of all elements. */ + + maxElementsSize = L_deposit_l(0); + maxElementsCapacity = L_add( nElementsToIgnore, 1 ); + + + BASOP_SATURATE_WARNING_OFF + IF( LE_32( h->readPos, h->writePos )) + { + /* no wrap around */ + /* calc statistics for [readPos;writePos[ */ + FOR( i = h->readPos; i != h->writePos; ++i ) + { + if( LT_32( h->data[i], minEle )) + { + minEle = L_add(h->data[i], 0); + } + JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] ); + } + } + ELSE + { + /* wrap around */ + /* calc statistics for [readPos;capacity[ */ + FOR( i = h->readPos; i != h->capacity; ++i ) + { + if( LT_32( h->data[i], minEle )) + { + minEle = L_add(h->data[i], 0); + } + JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] ); + } + /* calc statistics for [0;writePos[ */ + FOR( i = 0; i != h->writePos; ++i ) + { + if( LT_32( h->data[i], minEle )) + { + minEle = L_add(h->data[i], 0); + } + JB4_CIRCULARBUFFER_calcPercentile( maxElements, &maxElementsSize, maxElementsCapacity, h->data[i] ); + } + } + BASOP_SATURATE_WARNING_ON + *pPercentile = maxElements[0]; + move32(); + *pMin = minEle; + move32(); +} + +/* Calculates percentile by selecting greatest elements. */ +static void JB4_CIRCULARBUFFER_calcPercentile( JB4_CIRCULARBUFFER_ELEMENT *elements, + Word32 *size, Word32 capacity, JB4_CIRCULARBUFFER_ELEMENT newElement ) +{ + Word32 i,j; + + /* insert newElement if elements buffer is not yet full */ + IF( LT_32( *size, capacity )) + { + FOR( i = 0; i != *size; ++i ) + { + IF( LE_32( newElement, elements[i] )) + { + /* insert newElement at index i (move all elements above insert pos up a place */ + FOR( j = *size; j >= i; --j ) + { + elements[j+1] = elements[j]; + move32(); + } + + elements[i] = newElement; + move32(); + *size = L_add( *size, 1 ); + return; + } + } + /* newElement is maximum, just append it */ + elements[*size] = newElement; + move32(); + *size = L_add( *size, 1 ); + return; + } + + /* check if newElement is too small to be inserted in elements buffer */ + IF( LE_32( newElement, elements[0] )) + { + return; + } + + /* select position to insert newElement to elements */ + FOR( i = *size - 1; i != 0; --i ) + { + IF( GT_32( newElement, elements[i] )) + { + /* insert newElement at index i (move all elements below insert pos down a place)*/ + FOR( j = 0; j < i; j++ ) + { + elements[j] = elements[j+1]; + move32(); + } + elements[i] = newElement; + move32(); + return; + } + } + /* newElement is just greater than first on in elements buffer */ + elements[0] = newElement; + move32(); +} + diff --git a/lib_dec/jbm_jb4_circularbuffer.h b/lib_dec/jbm_jb4_circularbuffer.h new file mode 100644 index 0000000..4267b2e --- /dev/null +++ b/lib_dec/jbm_jb4_circularbuffer.h @@ -0,0 +1,52 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/** \file jbm_jb4_circularbuffer.h circular buffer (FIFO) with fixed capacity */ + +#ifndef JBM_JB4_CIRCULARBUFFER_H +#define JBM_JB4_CIRCULARBUFFER_H JBM_JB4_CIRCULARBUFFER_H +#include "typedef.h" + +/** handle for circular buffer (FIFO) with fixed capacity */ +typedef struct JB4_CIRCULARBUFFER *JB4_CIRCULARBUFFER_HANDLE; +/** type of circular buffer elements */ +typedef Word32 JB4_CIRCULARBUFFER_ELEMENT; + +/** Creates a circular buffer (FIFO) + * @param[out] ph pointer to created handle + * @return 0 if succeeded */ +Word16 JB4_CIRCULARBUFFER_Create( JB4_CIRCULARBUFFER_HANDLE *ph ); +/** Destroys the circular buffer (FIFO) */ +void JB4_CIRCULARBUFFER_Destroy( JB4_CIRCULARBUFFER_HANDLE *ph ); +/** Initializes a circular buffer (FIFO) with a fixed maximum allowed number of elements + * @param[in] capacity maximum allowed number of elements + * @return 0 if succeeded */ +Word16 JB4_CIRCULARBUFFER_Init( JB4_CIRCULARBUFFER_HANDLE h, Word16 capacity ); + +Word16 JB4_CIRCULARBUFFER_Enque( JB4_CIRCULARBUFFER_HANDLE h, JB4_CIRCULARBUFFER_ELEMENT element ); +Word16 JB4_CIRCULARBUFFER_Deque( JB4_CIRCULARBUFFER_HANDLE h, JB4_CIRCULARBUFFER_ELEMENT *pElement ); + +/** Returns the first element. */ +JB4_CIRCULARBUFFER_ELEMENT JB4_CIRCULARBUFFER_Front( const JB4_CIRCULARBUFFER_HANDLE h ); +/** Returns the last element. */ +JB4_CIRCULARBUFFER_ELEMENT JB4_CIRCULARBUFFER_Back( const JB4_CIRCULARBUFFER_HANDLE h ); + +Word16 JB4_CIRCULARBUFFER_IsEmpty( const JB4_CIRCULARBUFFER_HANDLE h ); +Word16 JB4_CIRCULARBUFFER_IsFull( const JB4_CIRCULARBUFFER_HANDLE h ); +Word16 JB4_CIRCULARBUFFER_Size( const JB4_CIRCULARBUFFER_HANDLE h ); + +/** Calculates statistics over all elements: min element + * @param[out] pMin minimum element */ +void JB4_CIRCULARBUFFER_Min( const JB4_CIRCULARBUFFER_HANDLE h, JB4_CIRCULARBUFFER_ELEMENT *pMin ); +/** Calculates statistics over all elements: max element + * @param[out] pMax maximum element */ +void JB4_CIRCULARBUFFER_Max( const JB4_CIRCULARBUFFER_HANDLE h, JB4_CIRCULARBUFFER_ELEMENT *pMax ); +/** Calculates statistics over a considered fraction of all elements: min element and percentile + * @param[in] nElementsToIgnore number of highest elements to ignore for percentile calculation + * @param[out] pMin minimum element + * @param[out] pPercentile consideredFraction percentile of the highest elements */ +void JB4_CIRCULARBUFFER_MinAndPercentile( const JB4_CIRCULARBUFFER_HANDLE h, Word32 nElementsToIgnore, + JB4_CIRCULARBUFFER_ELEMENT *pMin, JB4_CIRCULARBUFFER_ELEMENT *pPercentile ); + +#endif /* JBM_JB4_CIRCULARBUFFER_H */ diff --git a/lib_dec/jbm_jb4_inputbuffer.c b/lib_dec/jbm_jb4_inputbuffer.c new file mode 100644 index 0000000..cfb5ef7 --- /dev/null +++ b/lib_dec/jbm_jb4_inputbuffer.c @@ -0,0 +1,355 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/** \file jbm_jb4_inputbuffer.c RTP input buffer with fixed capacity. */ + +/* system includes */ +#include +#include +#include +/* instrumentation */ +/* local includes */ +#include "options.h" +#include "jbm_jb4_inputbuffer.h" +#include "stl.h" + + +/** input buffer with fixed capacity */ +struct JB4_INPUTBUFFER +{ + /** elements of input buffer */ + JB4_INPUTBUFFER_ELEMENT *data; + /** maximum allowed number of elements plus one free element (to decide between full/empty buffer) */ + Word16 capacity; + /** position of next enque operation */ + Word16 writePos; + /** position of next deque operation */ + Word16 readPos; + /** function to compare two elements */ + Word32 (*compareFunction)( const JB4_INPUTBUFFER_ELEMENT first, const JB4_INPUTBUFFER_ELEMENT second, + Word16 *replaceWithNewElementIfEqual ); +}; + + +/* Creates a input buffer */ +Word16 JB4_INPUTBUFFER_Create( JB4_INPUTBUFFER_HANDLE *ph ) +{ + JB4_INPUTBUFFER_HANDLE h = malloc( sizeof( struct JB4_INPUTBUFFER ) ); + + h->data = NULL; + move16(); + h->capacity = 0; + move16(); + h->writePos = 0; + move16(); + h->readPos = 0; + move16(); + h->compareFunction = NULL; + move16(); + + *ph = h; + move16(); + return 0; +} + +/* Destroys the input buffer */ +void JB4_INPUTBUFFER_Destroy( JB4_INPUTBUFFER_HANDLE *ph ) +{ + JB4_INPUTBUFFER_HANDLE h; + + IF( !ph ) + { + return; + } + h = *ph; + move16(); + + IF( !h ) + { + return; + } + + if( h->data ) + free( h->data ); + free( h ); + *ph = NULL; + move16(); +} + +/* Initializes a input buffer with a fixed maximum allowed number of elements */ +Word16 JB4_INPUTBUFFER_Init( JB4_INPUTBUFFER_HANDLE h, Word16 capacity, + Word32 (*compareFunction)( const JB4_INPUTBUFFER_ELEMENT first, const JB4_INPUTBUFFER_ELEMENT second, + Word16 *replaceWithNewElementIfEqual ) ) +{ + + /* keep one element free to be able to decide between full/empty buffer */ + capacity = add( capacity, 1 ); + h->data = malloc( L_mult0( capacity, sizeof( JB4_INPUTBUFFER_ELEMENT ) ) ); + h->capacity = capacity; + move16(); + h->writePos = 0; + move16(); + h->readPos = 0; + move16(); + h->compareFunction = compareFunction; + move16(); + return 0; +} + +Word16 JB4_INPUTBUFFER_Enque( JB4_INPUTBUFFER_HANDLE h, JB4_INPUTBUFFER_ELEMENT element, + JB4_INPUTBUFFER_ELEMENT *replacedElement ) +{ + Word16 size; + Word16 low, high, middle; + Word32 diff; + Word16 wrapCheck; + Word16 iterDiff; + Word16 insertPos; + Word16 canMoveRight; + Word16 canMoveLeft; + Word16 replace; + Word16 loopIter; + *replacedElement = NULL; + move16(); + + size = JB4_INPUTBUFFER_Size( h ); + + IF(GE_16(size, sub(h->capacity, 1))) + { + return -1; + } + + /* appending the first element is straight forward */ + IF( size == 0 ) + { + h->data[h->writePos] = element; + move16(); + h->writePos = add( h->writePos, 1 ); + + if( EQ_16( h->writePos, h->capacity )) + { + h->writePos = 0; + move16(); + } + return 0; + } + + /* there's a high probability that the new element can be appended at the back */ + IF( h->compareFunction( element, JB4_INPUTBUFFER_Back( h ), &replace ) > 0 ) + { + h->data[h->writePos] = element; + move16(); + h->writePos = add( h->writePos, 1 ); + + if( EQ_16( h->writePos, h->capacity )) + { + h->writePos = 0; + move16(); + } + return 0; + } + + /* out of order: use binary search to get the position to insert */ + low = 0; + move16(); + high = sub( size, 1 ); + + WHILE( ( iterDiff = sub( high, low ) ) >= 0 ) + { + /* equivalent to: middle = low + ( high - low ) / 2; */ + middle = add( low, shr( iterDiff, 1 ) ); + + diff = h->compareFunction( element, JB4_INPUTBUFFER_Element( h, middle ), &replace ); + + IF( diff < 0 ) + high = sub( middle, 1 ); + ELSE IF( diff > 0 ) + low = add( middle, 1 ); + ELSE /* an element with same index is already stored */ + { + IF(replace != 0) + { + insertPos = add( h->readPos, middle ); + /* check for wrap around and overwrite pos if required (previously used modulo divide) */ + wrapCheck = sub( insertPos, h->capacity ); + if( wrapCheck >= 0 ) + { + insertPos = wrapCheck; + move16(); + } + assert(insertPos == ( h->readPos + middle ) % h->capacity); + *replacedElement = h->data[insertPos]; + move16(); + h->data[insertPos] = element; + move16(); + return 0; + } + return 1; + } + } + + /* the following checks are for debugging only - excluded from instrumentation */ + + insertPos = add( h->readPos, low ); + /* check for wrap around and overwrite pos if required (previously used modulo divide) */ + wrapCheck = sub( insertPos, h->capacity ); + if( wrapCheck >= 0 ) + insertPos = wrapCheck; + move16(); + + canMoveRight = 1; + move16(); + canMoveLeft = h->readPos; + move16(); + + IF( GE_16( h->readPos, h->writePos )) + { + canMoveRight = sub( h->writePos, insertPos ); + canMoveLeft = sub( insertPos, h->writePos ); + } + + assert( canMoveRight > 0 || canMoveLeft > 0 ); + (void)canMoveLeft; + + IF( canMoveRight > 0 ) + { + /* move higher elements to the right and insert at insertPos */ + FOR( loopIter = 0; loopIter < h->writePos - insertPos; ++loopIter ) + { + iterDiff = sub( h->writePos, loopIter ); + h->data[ iterDiff ] = h->data[ sub( iterDiff, 1 ) ]; + move16(); + } + h->data[insertPos] = element; + move16(); + h->writePos = add( h->writePos, 1 ); + + if( EQ_16( h->writePos, h->capacity )) + { + h->writePos = 0; + move16(); + } + } + ELSE + { + /* move lower elements to the left and insert before insertPos */ + FOR( loopIter = 0; loopIter < low; ++loopIter ) + { + iterDiff = add( h->readPos, loopIter ); + h->data[ sub( iterDiff, 1 ) ] = h->data[iterDiff]; + move16(); + } + h->data[insertPos-1] = element; + move16(); + h->readPos = sub( h->readPos, 1 ); + assert( h->readPos >= 0 ); + } + return 0; +} + +Word16 JB4_INPUTBUFFER_Deque( JB4_INPUTBUFFER_HANDLE h, JB4_INPUTBUFFER_ELEMENT *pElement ) +{ + + IF( JB4_INPUTBUFFER_IsEmpty( h ) ) + { + return -1; + } + + *pElement = h->data[h->readPos]; + h->readPos = add( h->readPos, 1 ); + + if( EQ_16( h->readPos, h->capacity )) + { + h->readPos = 0; + move16(); + } + return 0; +} + +/* Returns the first element. */ +JB4_INPUTBUFFER_ELEMENT JB4_INPUTBUFFER_Front( const JB4_INPUTBUFFER_HANDLE h ) +{ + JB4_INPUTBUFFER_ELEMENT ret; + + ret = h->data[h->readPos]; + move16(); + return ret; +} + +/* Returns the last element. */ +JB4_INPUTBUFFER_ELEMENT JB4_INPUTBUFFER_Back( const JB4_INPUTBUFFER_HANDLE h ) +{ + JB4_INPUTBUFFER_ELEMENT ret; + + IF( h->writePos != 0 ) + { + ret = h->data[ sub( h->writePos, 1 ) ]; + move16(); + } + ELSE + { + ret = h->data[ sub( h->capacity, 1 ) ]; + move16(); + } + return ret; +} + +/* Returns the element with the given index (0 means front element). */ +JB4_INPUTBUFFER_ELEMENT JB4_INPUTBUFFER_Element( const JB4_INPUTBUFFER_HANDLE h, Word16 index ) +{ + JB4_INPUTBUFFER_ELEMENT ret; + Word16 iter; + Word16 wrapCheck; + + /* return h->data[(h->readPos + index) % h->capacity] without error handling */ + iter = add( h->readPos, index ); + wrapCheck = sub( iter, h->capacity ); + if( wrapCheck >= 0 ) + iter = wrapCheck; + move16(); + ret = h->data[ iter ]; + move16(); + return ret; +} + +Word16 JB4_INPUTBUFFER_IsEmpty( const JB4_INPUTBUFFER_HANDLE h ) +{ + Word16 ret; + + ret = 0; + move16(); + if( EQ_16( h->readPos, h->writePos )) + { + ret = 1; + move16(); + } + return ret; +} + +Word16 JB4_INPUTBUFFER_IsFull( const JB4_INPUTBUFFER_HANDLE h ) +{ + Word16 ret; + + ret = 0; + move16(); + IF( EQ_16( JB4_INPUTBUFFER_Size( h ), sub( h->capacity, 1 ))) + { + ret = 1; + move16(); + } + return ret; +} + +Word16 JB4_INPUTBUFFER_Size( const JB4_INPUTBUFFER_HANDLE h ) +{ + Word16 ret; + + ret = sub( h->writePos, h->readPos ); + + /* wrap around */ + if( GT_16( h->readPos, h->writePos )) + ret = add( ret, h->capacity ); + return ret; +} + diff --git a/lib_dec/jbm_jb4_inputbuffer.h b/lib_dec/jbm_jb4_inputbuffer.h new file mode 100644 index 0000000..a1004fb --- /dev/null +++ b/lib_dec/jbm_jb4_inputbuffer.h @@ -0,0 +1,50 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/** \file jbm_jb4_inputbuffer.h RTP input buffer with fixed capacity. + \note the buffer and corresponding variables have been designed + and tested up to a maximum 512 elements. */ + +#ifndef JBM_JB4_INPUTBUFFER_H +#define JBM_JB4_INPUTBUFFER_H JBM_JB4_INPUTBUFFER_H + +#include "typedef.h" + +/** Handle for RTP input buffer with fixed capacity. */ +/** Implemented as priority queue using an array based sorted circular buffer. */ +typedef struct JB4_INPUTBUFFER *JB4_INPUTBUFFER_HANDLE; +/** type of sorted circular buffer elements */ +typedef void* JB4_INPUTBUFFER_ELEMENT; + +/** Creates a input buffer + * @param[out] ph pointer to created handle + * @return 0 if succeeded */ +Word16 JB4_INPUTBUFFER_Create( JB4_INPUTBUFFER_HANDLE *ph ); +/** Destroys the input buffer */ +void JB4_INPUTBUFFER_Destroy( JB4_INPUTBUFFER_HANDLE *ph ); +/** Initializes a input buffer with a fixed maximum allowed number of elements + * @param[in] capacity maximum allowed number of elements + * @param[in] function to compare two elements: newElement==arrayElement ? 0 : (newElement>arrayElement ? +1 : -1) + * @return 0 if succeeded */ +Word16 JB4_INPUTBUFFER_Init( JB4_INPUTBUFFER_HANDLE h, Word16 capacity, + Word32 (*compareFunction)( const JB4_INPUTBUFFER_ELEMENT newElement, const JB4_INPUTBUFFER_ELEMENT arrayElement, + Word16 *replaceWithNewElementIfEqual ) ); + +/** Add an element to the buffer. + * @return 0 if succeeded, -1 if buffer full, +1 if element with same index already stored. */ +Word16 JB4_INPUTBUFFER_Enque( JB4_INPUTBUFFER_HANDLE h, JB4_INPUTBUFFER_ELEMENT element, JB4_INPUTBUFFER_ELEMENT *replacedElement ); +Word16 JB4_INPUTBUFFER_Deque( JB4_INPUTBUFFER_HANDLE h, JB4_INPUTBUFFER_ELEMENT *pElement ); + +/** Returns the first element. */ +JB4_INPUTBUFFER_ELEMENT JB4_INPUTBUFFER_Front( const JB4_INPUTBUFFER_HANDLE h ); +/** Returns the last element. */ +JB4_INPUTBUFFER_ELEMENT JB4_INPUTBUFFER_Back( const JB4_INPUTBUFFER_HANDLE h ); +/** Returns the element with the given index (0 means front element). */ +JB4_INPUTBUFFER_ELEMENT JB4_INPUTBUFFER_Element( const JB4_INPUTBUFFER_HANDLE h, Word16 index ); + +Word16 JB4_INPUTBUFFER_IsEmpty( const JB4_INPUTBUFFER_HANDLE h ); +Word16 JB4_INPUTBUFFER_IsFull( const JB4_INPUTBUFFER_HANDLE h ); +Word16 JB4_INPUTBUFFER_Size( const JB4_INPUTBUFFER_HANDLE h ); + +#endif /* JBM_JB4_INPUTBUFFER_H */ diff --git a/lib_dec/jbm_jb4_jmf.c b/lib_dec/jbm_jb4_jmf.c new file mode 100644 index 0000000..4eba39a --- /dev/null +++ b/lib_dec/jbm_jb4_jmf.c @@ -0,0 +1,274 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/** \file jbm_jb4_jmf.cpp jitter measure fifo - a fifo used for windowed measure of network status */ + +/* system includes */ +#include +#include +#include +/* instrumentation */ +#include "options.h" +#include "stl.h" +#include "basop_util.h" +/* local includes */ +#include "jbm_jb4_jmf.h" +#include "jbm_jb4_circularbuffer.h" + + +/** jitter measure fifo - a fifo used for windowed measure of network status */ +struct JB4_JMF +{ + /** scale of system time and RTP time stamps */ + Word16 timeScale; + /** the window size of the fifo as time in sysTimeScale */ + Word16 maxWindowDuration; + /** considered fraction in 1/1000 units, e.g. 900 ignores 10% of the highest samples */ + Word16 consideredFraction; + + /** fifo containing the delay entries (ordered by receive time) */ + JB4_CIRCULARBUFFER_HANDLE fifo; + /** fifo containing the offset entries (ordered by receive time) */ + JB4_CIRCULARBUFFER_HANDLE offsetFifo; + /** fifo containing the RTP times of the values in offsetFifo (ordered by receive time) */ + JB4_CIRCULARBUFFER_HANDLE timeStampFifo; + /** flag if the first packet was already pushed */ + Word16 firstPacketPushed; + /** last packets system time in microseconds */ + Word32 lastSysTime; + /** RTP time stamp of the last pushed packet */ + Word32 lastRtpTimeStamp; + /** last packets calculated delay value */ + Word32 lastDelay; + /** number of elements to ignore for percentile calculation - value set within init */ + Word16 nElementsToIgnore; + /** maximum delay to avoid overflow by clock drift - value set within init */ + Word32 maxDelay; +}; + + +/** helper function to add an entry at back of the buffer */ +static void JB4_JMF_pushBack( JB4_JMF_HANDLE h, Word32 delay, Word32 offset, Word32 time ); +/** helper function to remove an entry from the front of the buffer */ +static void JB4_JMF_popFront( JB4_JMF_HANDLE h ); + + +Word16 JB4_JMF_Create( JB4_JMF_HANDLE *ph ) +{ + JB4_JMF_HANDLE h = malloc( sizeof( struct JB4_JMF ) ); + + JB4_CIRCULARBUFFER_Create( &h->fifo ); + JB4_CIRCULARBUFFER_Create( &h->offsetFifo ); + JB4_CIRCULARBUFFER_Create( &h->timeStampFifo ); + + h->timeScale = 1000; + move16(); + h->maxWindowDuration = 10000; + move16(); + h->consideredFraction = 1000; + move16(); + h->firstPacketPushed = 0; + move16(); + h->lastSysTime = L_deposit_l(0); + h->lastRtpTimeStamp = L_deposit_l(0); + h->lastDelay = L_deposit_l(0); + h->nElementsToIgnore = 0; + move16(); + h->maxDelay = L_deposit_l(0); + + *ph = h; + move16(); + return 0; +} + +void JB4_JMF_Destroy( JB4_JMF_HANDLE *ph ) +{ + JB4_JMF_HANDLE h; + + IF( !ph ) + { + return; + } + h = *ph; + move16(); + + IF( !h ) + { + return; + } + + JB4_CIRCULARBUFFER_Destroy( &h->fifo ); + JB4_CIRCULARBUFFER_Destroy( &h->offsetFifo ); + JB4_CIRCULARBUFFER_Destroy( &h->timeStampFifo ); + + free( h ); + *ph = NULL; + move16(); +} + +/* function to set the window size of the fifo and the fraction which will be considered */ +Word16 JB4_JMF_Init( JB4_JMF_HANDLE h, Word16 timeScale, Word16 windowSize, + Word16 windowDuration, Word16 consideredFraction ) +{ + Word16 divScaleFac; + + /* check the following parameters (debug only) */ + assert( windowSize != 0U ); + /* check consideredFraction given is not too low */ + assert( consideredFraction * windowSize / 1000 >= 2 ); + /* check consideredFraction given is not too high */ + assert( consideredFraction <= 1000 ); + + /* store values */ + h->timeScale = timeScale; + move16(); + h->maxWindowDuration = windowDuration; + move16(); + h->consideredFraction = consideredFraction; + move16(); + + JB4_CIRCULARBUFFER_Init( h->fifo, windowSize ); + JB4_CIRCULARBUFFER_Init( h->offsetFifo, windowSize ); + JB4_CIRCULARBUFFER_Init( h->timeStampFifo, windowSize ); + + /* calculate nElementsToIgnore so that the multi & divide occur only once, not every jitter calc. + * to retain accuracy in the division use scaled division and shift back after */ + h->nElementsToIgnore = BASOP_Util_Divide3216_Scale( L_mult0( windowSize, sub( 1000, h->consideredFraction ) ), 1000, &divScaleFac ); + h->nElementsToIgnore = shl( h->nElementsToIgnore, add( divScaleFac,1 ) ); + assert(h->nElementsToIgnore == windowSize * ( 1000 - consideredFraction ) / 1000); + /* calculate maxDelay here as to not calculate every push packet */ + h->maxDelay = L_mult0( h->timeScale, 60 ); + return 0; +} + +/* function to calculate delay for the current packet */ +Word16 JB4_JMF_PushPacket( JB4_JMF_HANDLE h, Word32 sysTime, Word32 rtpTimeStamp ) +{ + Word32 rtpTimeDiff, sysTimeDiff; + Word32 offset, delay; + + /* check if this is the first entry */ + IF( h->firstPacketPushed == 0 ) + { + h->firstPacketPushed = 1; + move16(); + h->lastSysTime = sysTime; + move32(); + h->lastRtpTimeStamp = rtpTimeStamp; + move32(); + return 0; + } + + rtpTimeDiff = L_sub( rtpTimeStamp, h->lastRtpTimeStamp ); + sysTimeDiff = L_sub( sysTime, h->lastSysTime ); + offset = L_sub( sysTime, rtpTimeStamp ); + + /* get the delay (yes, signed!!!!) */ + delay = L_add( L_sub( sysTimeDiff, rtpTimeDiff ), h->lastDelay ); + + /* remember old values */ + h->lastSysTime = sysTime; + move32(); + h->lastRtpTimeStamp = rtpTimeStamp; + move32(); + h->lastDelay = delay; + move32(); + + /* reset delay if absolute value is greater than 60s + * to avoid overflow caused by clockdrift */ test(); + if( GT_32( delay, h->maxDelay )||L_add(delay,h->maxDelay)<0) + { + h->lastDelay = L_deposit_l(0); + } + JB4_JMF_pushBack( h, delay, offset, rtpTimeStamp ); + return 0; +} + +/* function to get the current jitter */ +Word16 JB4_JMF_Jitter( const JB4_JMF_HANDLE h, Word32 *jitter ) +{ + JB4_CIRCULARBUFFER_ELEMENT min, percentile; + + /* sanity check (must not be empty) and return invalid result if there is only one entry */ + IF( LT_16( JB4_CIRCULARBUFFER_Size( h->fifo ), 2 )) + { + return -1; + } + + JB4_CIRCULARBUFFER_MinAndPercentile( h->fifo, h->nElementsToIgnore, &min, &percentile ); + + /* return the difference between the highest considered and the smallest value */ + *jitter = L_sub( percentile, min ); + assert( percentile >= min ); + return 0; +} + +/* function to get the minimum offset between received time and time stamp of all entries in the fifo */ +Word16 JB4_JMF_MinOffset( const JB4_JMF_HANDLE h, Word32 *offset ) +{ + JB4_CIRCULARBUFFER_ELEMENT min; + + IF( JB4_CIRCULARBUFFER_IsEmpty( h->offsetFifo ) ) + { + return -1; + } + + JB4_CIRCULARBUFFER_Min( h->offsetFifo, &min ); + + *offset = min; + move32(); + return 0; +} + + +/***************************************************************************** + **************************** private functions ****************************** + *****************************************************************************/ + +/* helper function to add entry at back of the buffer */ +static void JB4_JMF_pushBack( JB4_JMF_HANDLE h, Word32 delay, Word32 offset, Word32 time ) +{ + Word32 minTime, maxTime, duration; + + /* check for size and discard first entry if too big */ + IF( JB4_CIRCULARBUFFER_IsFull( h->fifo ) ) + { + JB4_JMF_popFront( h ); + } + + /* push back new entry */ + JB4_CIRCULARBUFFER_Enque( h->fifo, delay ); + JB4_CIRCULARBUFFER_Enque( h->offsetFifo, offset ); + JB4_CIRCULARBUFFER_Enque( h->timeStampFifo, time ); + + /* check for duration and discard first entries if too long */ + minTime = JB4_CIRCULARBUFFER_Front( h->timeStampFifo ); + maxTime = JB4_CIRCULARBUFFER_Back( h->timeStampFifo ); + + duration = L_sub( maxTime, minTime ); + test(); + WHILE( duration > 0 && GT_32( duration, h->maxWindowDuration )) + { + test(); + JB4_JMF_popFront( h ); + minTime = JB4_CIRCULARBUFFER_Front( h->timeStampFifo ); + duration = L_sub( maxTime, minTime ); + } +} + +/* helper function to remove an entry from the front of the buffer */ +static void JB4_JMF_popFront( JB4_JMF_HANDLE h ) +{ + JB4_CIRCULARBUFFER_ELEMENT tmpElement; + + /* try to remove one element - fails if empty */ + IF( JB4_CIRCULARBUFFER_Deque( h->fifo, &tmpElement ) != 0 ) + { + return; + } + /* also remove offset entry */ + JB4_CIRCULARBUFFER_Deque( h->offsetFifo, &tmpElement ); + JB4_CIRCULARBUFFER_Deque( h->timeStampFifo, &tmpElement ); +} + diff --git a/lib_dec/jbm_jb4_jmf.h b/lib_dec/jbm_jb4_jmf.h new file mode 100644 index 0000000..48f97d1 --- /dev/null +++ b/lib_dec/jbm_jb4_jmf.h @@ -0,0 +1,42 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/** \file jbm_jb4_jmf.h jitter measure fifo - a fifo used for windowed measure of network status */ + +#ifndef JBM_JB4_JMF_H +#define JBM_JB4_JMF_H JBM_JB4_JMF_H + +#include "typedef.h" + +/** handle for jitter measure fifo - a fifo used for windowed measure of network status */ +typedef struct JB4_JMF *JB4_JMF_HANDLE; + +/**@name functions to manage the fifo */ +/**@{ */ +Word16 JB4_JMF_Create( JB4_JMF_HANDLE *ph ); +void JB4_JMF_Destroy( JB4_JMF_HANDLE *ph ); +/** function to set the window size of the fifo and the fraction which will be considered */ +/** @param timeScale scale of system time and RTP time stamps (designed and tested up to 500 pkts) + * @param windowSize the window size of the fifo in number of packets (designed and tested up to 10000ms (500*20ms)) + * @param windowDuration the window size of the fifo as time in sysTimeScale + * @param consideredFraction the considered fraction in 1/1000 units, e.g. 900 ignores 10% of the highest samples + * @return 0 on success */ +Word16 JB4_JMF_Init( JB4_JMF_HANDLE h, Word16 timeScale, Word16 windowSize, + Word16 windowDuration, Word16 consideredFraction ); +/**@} */ + +/**@name functions to push packets and get the current jitter rate */ +/**@{ */ +/** function to calculate jitter for the current packet */ +Word16 JB4_JMF_PushPacket( JB4_JMF_HANDLE h, Word32 sysTime, Word32 rtpTimeStamp ); +/** function to get the current jitter */ +Word16 JB4_JMF_Jitter( const JB4_JMF_HANDLE h, Word32 *jitter ); +/** function to get the minimum offset between received time and time stamp of all entries in the fifo */ +/*! This value is the offset of the fastest transmitted packet of all packets currently + * contained in the fifo. + * @param[out] offset the minimum offset in microseconds */ +Word16 JB4_JMF_MinOffset( const JB4_JMF_HANDLE h, Word32 *offset ); +/**@} */ + +#endif /* JBM_JB4_JMF_H */ diff --git a/lib_dec/jbm_jb4sb.c b/lib_dec/jbm_jb4sb.c new file mode 100644 index 0000000..a7987b8 --- /dev/null +++ b/lib_dec/jbm_jb4sb.c @@ -0,0 +1,1495 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*! \file jbm_jb4sb.c Jitter Buffer Management Interface */ + +/* system headers */ +#include +#include +/* instrumentation headers */ +#include "stl.h" +#include "options.h" +#include "basop_util.h" +#include "basop_util_jbm.h" +#include "cnst_fx.h" +/* local headers */ +#include "jbm_jb4_circularbuffer.h" +#include "jbm_jb4_inputbuffer.h" +#include "jbm_jb4_jmf.h" +#include "jbm_jb4sb.h" +#include "prot_fx.h" + + +static Word16 idiv3216(Word32 x, Word16 y) +{ + Word16 z, divScaleFac; + + z = BASOP_Util_Divide3216_Scale(x, y, &divScaleFac); + z = shl(z, add(divScaleFac,1)); + return z; +} + +#define MAXOFFSET 10 + +/*! Calculates the difference between two RTP timestamps - the diff is positive, if B 'later', negative otherwise */ +static Word32 JB4_rtpTimeStampDiff( Word32 tsA, Word32 tsB ); +/* function to calculate different options for the target playout delay */ +static void JB4_targetPlayoutDelay( const JB4_HANDLE h, Word32 *targetMin, + Word32 *targetMax, Word32 *targetDtx, Word32 *targetStartUp ); +/*! function to do playout adaptation before playing the next data unit */ +/*! In case of time shrinking, data units will be dropped before the next data unit to play is returned and + * in case of time stretching a empty data unit is returned and the frame should be concealed. + * @param[in] now current system time + * @param[out] dataUnit the next data unit to play + * @param[out] scale the scale in percent used as target for time scaling of the returned data unit + * @param[out] maxScaling the maximum allowed external time scaling */ +static Word16 JB4_adaptPlayout( JB4_HANDLE h, Word32 sysTime, Word32 extBufferedTime, + JB4_DATAUNIT_HANDLE *pDataUnit, Word16 *scale, Word16 *maxScaling ); +/*! function to do playout adaptation before playing the first data unit */ +/*! @param[in] now current system time + * @param[out] prebuffer true, if the data unit should be prebuffered */ +static void JB4_adaptFirstPlayout( JB4_HANDLE h, Word32 sysTime, Word16 *prebuffer ); +/*! function for playout adaptation while active (no DTX) */ +static void JB4_adaptActivePlayout( JB4_HANDLE h, Word32 sysTime, + Word32 extBufferedTime, Word16 *scale, Word16 *maxScaling ); +/*! function for playout adaptation while DTX */ +static void JB4_adaptDtxPlayout( JB4_HANDLE h, Word32 sysTime, Word16 *stretchTime ); +/*! function to look into the buffer and check if it makes sense to drop a data unit */ +/*! @param[out] dropEarly true, if a data unit could be dropped early + * @param[out] buffered the buffered time span in timeScale units + * @return true, if a data unit could be dropped */ +static Word16 JB4_inspectBufferForDropping( const JB4_HANDLE h, Word16 *dropEarly, Word32 *buffered ); +/* function to look into the buffer and check if it makes sense to drop a data unit during DTX */ +static Word16 JB4_checkDtxDropping( const JB4_HANDLE h ); +/*! function to estimate the short term jitter */ +static void JB4_estimateShortTermJitter( JB4_HANDLE h, Word32 rcvTime, Word32 rtpTimeStamp ); +/*! function to pop a data unit from the buffer */ +static void JB4_popFromBuffer( JB4_HANDLE h, Word32 sysTime, JB4_DATAUNIT_HANDLE *pDataUnit ); +/*! function to drop a data unit from the buffer - updates nShrinked */ +static void JB4_dropFromBuffer( JB4_HANDLE h, Word32 sysTime ); +/*! function to calculate the playout delay based on the current jitter */ +/*! @param[in] playTime the system time when the data unit will be played + * @param[in] timeStamp the time stamp of the data unit to played + * @param[out] delay the calculated playout delay */ +static Word16 JB4_playoutDelay( const JB4_HANDLE h, Word32 playTime, + Word32 rtpTimeStamp, Word32 *delay ); +/*! function to update lastPlayoutDelay and lastTargetTime after popFromBuffer() */ +static void JB4_updateLastTimingMembers( JB4_HANDLE h, Word32 playTime, Word32 rtpTimeStamp ); +/*! function to compare the RTP time stamps of two data units: newElement==arrayElement ? 0 : (newElement>arrayElement ? +1 : -1) */ +static Word32 JB4_inputBufferCompareFunction( const JB4_INPUTBUFFER_ELEMENT newElement, + const JB4_INPUTBUFFER_ELEMENT arrayElement, Word16 *replaceWithNewElementIfEqual ); + + +/*! Jitter Buffer Management Interface */ +struct JB4 +{ + /*! @name statistics for user */ + /*@{ */ + /*! the number of late lost data units */ + Word32 nLateLost; + /*! the number of data units that were available (not NULL) at playout time */ + Word32 nAvailablePopped; + /*! the number of data units that were not available (NULL) at playout time */ + Word32 nUnavailablePopped; + /*! the number of unavailable pops since the last available one - used as temp value for nLost and nStretched */ + Word32 nLostOrStretched; + /*! the number of data units that were lost at playout time */ + Word32 nLost; + /*! the number of empty data units inserted for playout adaptation */ + Word32 nStretched; + /*! the number of data units dropped for playout adaptation */ + /*! This function counts all time shrinking events, no matter if a dropped data unit was actually available. */ + Word32 nShrinked; + /*! the number of data units that were returned to create comfort noice (including NULL) */ + Word32 nComfortNoice; + /*! the number of jitter induced concealment operations (as defined in 3GPP TS 26.114) */ + Word32 jitterInducedConcealments; + /*! the target playout delay of the last returned data unit */ + Word32 targetPlayoutDelay; + /*! the target playout time of the last returned data unit */ + Word32 lastTargetTime; + /*@} */ + /*! @name internal configuration values - do not change!!! */ + /*@{ */ + /*! internal time scale for all calculations */ + Word16 timeScale; + /*! internal frame duration in timeScale units */ + Word32 frameDuration; + /*@} */ + /*! @name jitter buffer configuration values */ + /*@{ */ + /*! the allowed delay reserve in addition to network jitter to reduce late-loss [milliseconds] */ + Word32 safetyMargin; + /*@} */ + /*! @name data for short term jitter estimation */ + /*@{ */ + /*! short term jitter measure FIFO */ + JB4_JMF_HANDLE stJmf; + /*! FIFO of short term jitter values */ + JB4_CIRCULARBUFFER_HANDLE stJitterFifo; + /*! FIFO of RTP time stamps for the values stored in stJitterFifo */ + JB4_CIRCULARBUFFER_HANDLE stTimeStampFifo; + /*! short term jitter */ + Word32 stJitter; + /*@} */ + /*! @name jitter buffer data */ + /*@{ */ + /*! true, if a data unit was already popped from the buffer */ + Word16 firstDataUnitPopped; + /*! system time of the previous JB4_PopDataUnit() call */ + Word32 prevPopSysTime; + /*! RTP timestamp of the last played/dropped data unit that was actually available */ + Word32 lastReturnedTs; + /*! true, if the last popped data unit contained no active signal, i.e. silence -> hint for DTX */ + Word16 lastPoppedWasSilence; + /*! the playout time minus the minimum offset of the last played data unit in microseconds */ + Word32 lastPlayoutOffset; + /*! RTP time stamp of the next data unit that is expected to be fetched from the buffer */ + Word32 nextExpectedTs; + Word16 rfOffset2Active; + Word16 rfOffset3Active; + Word16 rfOffset5Active; + Word16 rfOffset7Active; + Word32 rfDelay; + /*! long term jitter measure FIFO */ + JB4_JMF_HANDLE ltJmf; + + Word32 FecOffWinLen; + Word32 FecOffWin[10]; + Word32 optimum_offset; + Word32 totWin; + Word32 netLossRate; + /*! the number of partial copies decoded instead of PLC */ + Word32 nPartialCopiesUsed; + Word32 last_nLost; + Word32 last_ntot; + /*@} */ + + /*! @name members to store the data units */ + /*@{ */ + /*! the data unit buffer */ + JB4_INPUTBUFFER_HANDLE inputBuffer; + Word16 pre_partial_frame; + struct JB4_DATAUNIT memorySlots[MAX_JBM_SLOTS]; + JB4_DATAUNIT_HANDLE freeMemorySlots[MAX_JBM_SLOTS]; + Word16 nFreeMemorySlots; + /*@} */ +}; /* JB4 */ + + +Word16 JB4_Create( JB4_HANDLE *ph ) +{ + JB4_HANDLE h = calloc( 1, sizeof( struct JB4 ) ); + + Word16 iter; + + /* statistics for user */ + h->nLateLost = L_deposit_l(0); + h->nAvailablePopped = L_deposit_l(0); + h->nUnavailablePopped = L_deposit_l(0); + h->nLostOrStretched = L_deposit_l(0); + h->nLost = L_deposit_l(0); + h->nStretched = L_deposit_l(0); + h->nShrinked = L_deposit_l(0); + h->nComfortNoice = L_deposit_l(0); + h->jitterInducedConcealments = L_deposit_l(0); + h->targetPlayoutDelay = L_deposit_l(0); + h->lastTargetTime = L_deposit_l(0); + /* internal configuration values - do not change!!! */ + h->timeScale = 0; + move16(); + h->frameDuration = L_deposit_l(0); + /* jitter buffer configuration values: done in JB4_Init() */ + /* short term jitter evaluation */ + JB4_JMF_Create( &h->stJmf ); + JB4_CIRCULARBUFFER_Create( &h->stJitterFifo ); + JB4_CIRCULARBUFFER_Create( &h->stTimeStampFifo ); + h->stJitter = L_deposit_l(0); + /* jitter buffer data */ + h->firstDataUnitPopped = false; + move16(); + h->prevPopSysTime = L_deposit_l(0); + h->lastReturnedTs = L_deposit_l(0); + h->lastPoppedWasSilence = false; + move16(); + h->lastPlayoutOffset = L_deposit_l(0); + h->nextExpectedTs = L_deposit_l(0); + h->rfOffset2Active = 0; + move16(); + h->rfOffset3Active = 0; + move16(); + h->rfOffset5Active = 0; + move16(); + h->rfOffset7Active = 0; + move16(); + h->rfDelay = L_deposit_l(0); + JB4_JMF_Create( &h->ltJmf ); + h->pre_partial_frame = 0; + + h->FecOffWinLen = 0; + move32(); + FOR (iter = 0; iter < 10; iter++ ) + { + h->FecOffWin[iter] = 0; + move32(); + } + h->optimum_offset = 3; + move32(); + h->totWin = 0; + move32(); + h->netLossRate = 0; + move32(); + h->nPartialCopiesUsed = 0; + move32(); + h->last_nLost = 0; + move32(); + h->last_ntot = 0; + move32(); + + /* members to store the data units */ + JB4_INPUTBUFFER_Create( &h->inputBuffer ); + /* allocate memory for data units */ + FOR(iter = 0; iter < MAX_JBM_SLOTS; ++iter) + { + h->memorySlots[iter].data = malloc(MAX_AU_SIZE); + h->freeMemorySlots[iter] = &h->memorySlots[iter]; + move16(); + } + h->nFreeMemorySlots = MAX_JBM_SLOTS; + *ph = h; + move16(); + return 0; +} + +void JB4_Destroy( JB4_HANDLE *ph ) +{ + JB4_HANDLE h; + Word16 i; + + IF( !ph ) + { + return; + } + h = *ph; + move16(); + + IF( !h ) + { + return; + } + + JB4_JMF_Destroy( &h->stJmf ); + JB4_CIRCULARBUFFER_Destroy( &h->stJitterFifo ); + JB4_CIRCULARBUFFER_Destroy( &h->stTimeStampFifo ); + JB4_JMF_Destroy( &h->ltJmf ); + JB4_INPUTBUFFER_Destroy( &h->inputBuffer ); + + for(i = 0; i < MAX_JBM_SLOTS; ++i) + { + free(h->memorySlots[i].data); + } + + free( h ); + *ph = NULL; + move16(); +} + +Word16 JB4_Init( JB4_HANDLE h, Word16 safetyMargin ) +{ + Word16 ltJmfSize, stFifoSize, stJmfSize, stJmfAllowedLateLoss; + Word16 inputBufferCapacity; + + /* internal timescale is 1000, frame duration is 20ms */ + h->timeScale = 1000; /* ms */ move16(); + h->frameDuration = L_deposit_l(20); /* ms */ + + /* jitter buffer configuration values */ + h->safetyMargin = L_deposit_l(safetyMargin); + + /* long term jitter measure FIFO: 500 frames and 10s */ + ltJmfSize = 10000; + move16(); + JB4_JMF_Init( h->ltJmf, h->timeScale, ltJmfSize / 20, ltJmfSize, 1000 ); + /* short term jitter evaluation */ + stFifoSize = 200; + move16(); + stJmfSize = 50; + move16(); + stJmfAllowedLateLoss = 940; /* (1000 - 60) = 6%, e.g. ignore three packets out of 50 */ move16(); + JB4_CIRCULARBUFFER_Init( h->stJitterFifo, stFifoSize ); + JB4_CIRCULARBUFFER_Init( h->stTimeStampFifo, stFifoSize ); + JB4_JMF_Init( h->stJmf, h->timeScale, stJmfSize, h->timeScale /* 1s */, stJmfAllowedLateLoss ); + + inputBufferCapacity = MAX_JBM_SLOTS - 2; + move16(); + JB4_INPUTBUFFER_Init( h->inputBuffer, inputBufferCapacity, JB4_inputBufferCompareFunction ); + return 0; +} + +/* Returns a memory slot to store a new data unit */ +JB4_DATAUNIT_HANDLE JB4_AllocDataUnit( JB4_HANDLE h ) +{ + JB4_DATAUNIT_HANDLE dataUnit; + + WHILE(h->nFreeMemorySlots == 0) + { + assert(JB4_INPUTBUFFER_IsEmpty(h->inputBuffer) == 0); + JB4_dropFromBuffer(h, 0); + } + + h->nFreeMemorySlots = sub(h->nFreeMemorySlots, 1); + dataUnit = h->freeMemorySlots[h->nFreeMemorySlots]; + move16(); + h->freeMemorySlots[h->nFreeMemorySlots] = NULL; + move16(); + assert(dataUnit != NULL); + return dataUnit; +} + +/* Notifies the JBM that a data unit is no longer used and the memory can be reused */ +void JB4_FreeDataUnit( JB4_HANDLE h, JB4_DATAUNIT_HANDLE dataUnit ) +{ + assert(dataUnit != NULL); + assert(h->nFreeMemorySlots < MAX_JBM_SLOTS); + h->freeMemorySlots[h->nFreeMemorySlots] = dataUnit; + move16(); + h->nFreeMemorySlots = add(h->nFreeMemorySlots, 1); +} + +Word16 JB4_PushDataUnit( JB4_HANDLE h, JB4_DATAUNIT_HANDLE dataUnit, Word32 rcvTime ) +{ + JB4_DATAUNIT_HANDLE droppedDataUnit = NULL; + move16(); + + assert( dataUnit->duration == h->frameDuration ); + assert( dataUnit->timeScale == h->timeScale ); + + /* ignore frames from too far in future (3 seconds) */ test(); + IF( h->firstDataUnitPopped && + GE_32(JB4_rtpTimeStampDiff(h->lastReturnedTs, dataUnit->timeStamp), + L_mult0(50 * 3, extract_l(dataUnit->duration)))) + { + JB4_FreeDataUnit(h, dataUnit); + return 0; + } + + /* reserve space for one element to add: drop oldest if buffer is full */ + WHILE(JB4_INPUTBUFFER_IsFull(h->inputBuffer)) + { + JB4_dropFromBuffer(h, rcvTime); + } + assert(JB4_INPUTBUFFER_IsFull(h->inputBuffer) == 0); + + /* do statistics on partial copy offset using active primary copies to + * avoid unexpected resets because RF_NO_DATA partial copies are dropped before JBM */ + IF(dataUnit->silenceIndicator == 0 && dataUnit->partial_frame == 0) + { + IF(EQ_16(dataUnit->partialCopyOffset, 0)) + { + h->rfOffset2Active = s_max(sub(h->rfOffset2Active, 1), 0); + h->rfOffset3Active = s_max(sub(h->rfOffset3Active, 1), 0); + h->rfOffset5Active = s_max(sub(h->rfOffset5Active, 1), 0); + h->rfOffset7Active = s_max(sub(h->rfOffset7Active, 1), 0); + } + ELSE IF(EQ_16(dataUnit->partialCopyOffset, 2)) + { + h->rfOffset2Active = 100; + move16(); + h->rfOffset3Active = 0; + move16(); + h->rfOffset5Active = 0; + move16(); + h->rfOffset7Active = 0; + move16(); + } + ELSE IF(EQ_16(dataUnit->partialCopyOffset, 3)) + { + h->rfOffset2Active = 0; + move16(); + h->rfOffset3Active = 100; + move16(); + h->rfOffset5Active = 0; + move16(); + h->rfOffset7Active = 0; + move16(); + } + ELSE IF(EQ_16(dataUnit->partialCopyOffset, 5)) + { + h->rfOffset2Active = 0; + move16(); + h->rfOffset3Active = 0; + move16(); + h->rfOffset5Active = 100; + move16(); + h->rfOffset7Active = 0; + move16(); + } + ELSE IF(EQ_16(dataUnit->partialCopyOffset, 7)) + { + h->rfOffset2Active = 0; + move16(); + h->rfOffset3Active = 0; + move16(); + h->rfOffset5Active = 0; + move16(); + h->rfOffset7Active = 100; + move16(); + } + } + + IF(dataUnit->partial_frame != 0) + { + /* check for "real" late loss: a frame with higher/same timestamp was already returned to be fed into decoder */ test(); + IF( h->firstDataUnitPopped && JB4_rtpTimeStampDiff( h->lastReturnedTs, dataUnit->timeStamp ) <= 0 ) + { + JB4_FreeDataUnit(h, dataUnit); + return 0; + } + + /* drop partial copy if the missing frame was already concealed */ + IF( h->firstDataUnitPopped ) + { + IF( LE_16(dataUnit->partialCopyOffset, 3)&&JB4_rtpTimeStampDiff(h->nextExpectedTs,dataUnit->timeStamp)<0) + { + JB4_FreeDataUnit(h, dataUnit); + return 0; + } + ELSE IF( EQ_16(dataUnit->partialCopyOffset, 5)&<_32(JB4_rtpTimeStampDiff(h->nextExpectedTs,dataUnit->timeStamp),-40)) + { + JB4_FreeDataUnit(h, dataUnit); + return 0; + } + ELSE IF( EQ_16(dataUnit->partialCopyOffset, 7)&<_32(JB4_rtpTimeStampDiff(h->nextExpectedTs,dataUnit->timeStamp),-80)) + { + JB4_FreeDataUnit(h, dataUnit); + return 0; + } + } + + /* try to store partial copy - will be dropped if primary copy already available */ + IF(JB4_INPUTBUFFER_Enque( h->inputBuffer, dataUnit, (void**)&droppedDataUnit ) == 0) + { + /* partial copy is useful, consider it in long-term jitter estimation */ + IF( LE_16(dataUnit->partialCopyOffset, 3)) + { + JB4_JMF_PushPacket( h->ltJmf, rcvTime, dataUnit->timeStamp ); + } + } + ELSE + { + JB4_FreeDataUnit(h, dataUnit); + } + IF(droppedDataUnit != NULL) + { + JB4_FreeDataUnit(h, droppedDataUnit); + } + } + ELSE + { + /* calculate jitter */ + JB4_JMF_PushPacket( h->ltJmf, rcvTime, dataUnit->timeStamp ); + JB4_estimateShortTermJitter( h, rcvTime, dataUnit->timeStamp ); + /* check for "real" late loss: a frame with higher/same timestamp was already returned to be fed into decoder */ test(); + IF( h->firstDataUnitPopped && JB4_rtpTimeStampDiff( h->lastReturnedTs, dataUnit->timeStamp ) <= 0 ) + { + IF( !dataUnit->silenceIndicator ) + { + h->nLateLost = L_add(h->nLateLost, 1); + /* deletion of a speech frame because it arrived at the JBM too late */ + h->jitterInducedConcealments = L_add(h->jitterInducedConcealments, 1); + } + JB4_FreeDataUnit(h, dataUnit); + return 0; + } + /* store data unit */ + IF(JB4_INPUTBUFFER_Enque( h->inputBuffer, dataUnit, (void**)&droppedDataUnit ) != 0) + { + JB4_FreeDataUnit(h, dataUnit); + } + IF(droppedDataUnit != NULL) + { + JB4_FreeDataUnit(h, droppedDataUnit); + } + } + return 0; +} + +Word16 JB4_PopDataUnit( JB4_HANDLE h, Word32 sysTime, Word32 extBufferedTime, + JB4_DATAUNIT_HANDLE *pDataUnit, Word16 *scale, Word16 *maxScaling ) +{ + Word16 ret; + + assert( sysTime >= h->prevPopSysTime ); + if( GT_32(sysTime, L_add(h->prevPopSysTime, h->frameDuration))) + { + h->lastPlayoutOffset = rtpTs_add(h->lastPlayoutOffset, h->frameDuration); + } + h->prevPopSysTime = sysTime; + move32(); + + ret = JB4_adaptPlayout( h, sysTime, extBufferedTime, pDataUnit, scale, maxScaling ); + return ret; +} + +/* Calculates the difference between two RTP timestamps - the diff is positive, if B 'later', negative otherwise */ +static Word32 JB4_rtpTimeStampDiff( Word32 tsA, Word32 tsB ) +{ + Word32 ret; + /* no saturation wanted! */ + ret = rtpTs_sub(tsB, tsA); + assert( ret == (Word32)(tsB - tsA) ); + return ret; +} + +/* function to get the number of data units contained in the buffer */ +Word16 JB4_bufferedDataUnits( const JB4_HANDLE h ) +{ + return JB4_INPUTBUFFER_Size( h->inputBuffer ); +} + + +Word16 JB4_getFECoffset(JB4_HANDLE h) +{ + return (Word16)h->optimum_offset; +} + +Word16 JB4_FECoffset(JB4_HANDLE h) +{ + IF ( LT_32( h->netLossRate, 1634)) + { + return (Word16)0; + } + ELSE + { + return (Word16)1; + } +} + + +/***************************************************************************** + **************************** private functions ****************************** + *****************************************************************************/ + + +/* function to calculate different options for the target playout delay */ +static void JB4_targetPlayoutDelay( const JB4_HANDLE h, Word32 *targetMin, + Word32 *targetMax, Word32 *targetDtx, Word32 *targetStartUp ) +{ + Word32 ltJitter, extraDelayReserve; + /* adapt target delay to partial copy offset */ + extraDelayReserve = L_deposit_l(0); + h->rfDelay = L_deposit_l(0); + IF(h->rfOffset7Active != 0) + { + h->rfDelay = L_deposit_l(140); + } + ELSE IF(h->rfOffset5Active != 0) + { + h->rfDelay = L_deposit_l(100); + } + ELSE IF(h->rfOffset2Active == 0 && h->rfOffset3Active == 0) + { + /* keep some delay reserve for RF-off */ + extraDelayReserve = L_deposit_l(15); + } + + /* get estimated long term jitter */ + IF( JB4_JMF_Jitter( h->ltJmf, <Jitter ) == 0 ) + { + /* combine long term and short term jitter to calculate target delay values */ + *targetMax = L_add(h->stJitter, L_add(h->safetyMargin, h->rfDelay)); + *targetMin = L_min(L_add(L_add(L_add(ltJitter, 20), h->rfDelay), extraDelayReserve), *targetMax ); + *targetDtx = L_min(L_add(ltJitter, extraDelayReserve), h->stJitter ); + *targetStartUp = L_shr(L_add(L_add(*targetMin, *targetMax), L_shr(extraDelayReserve, 2)), 1); + } + ELSE + { + /* combine long term and short term jitter to calculate target delay values */ + *targetMax = h->safetyMargin; + move32(); + *targetMin = L_min( 20, *targetMax ); + *targetDtx = 0; + move16(); + *targetStartUp = L_shr(L_add(*targetMin, *targetMax), 1); + } + if(LT_32(*targetStartUp, 60)) + { + *targetStartUp = 60; + move32(); + } +} + +/* function to do playout adaptation before playing the next data unit */ +static Word16 JB4_adaptPlayout( JB4_HANDLE h, Word32 sysTime, Word32 extBufferedTime, + JB4_DATAUNIT_HANDLE *pDataUnit, Word16 *scale, Word16 *maxScaling ) +{ + Word16 stretchTime; + + /* reset scale */ test(); + IF( scale == NULL || maxScaling == NULL ) + { + return -1; + } + *scale = 100; + move16(); + *maxScaling = 0; + move16(); + stretchTime = false; + move16(); + + /* switch type of current playout (first one, active, DTX) */ + IF( !h->firstDataUnitPopped ) + { + JB4_adaptFirstPlayout( h, sysTime, &stretchTime ); + } + ELSE IF( h->lastPoppedWasSilence ) + { + JB4_adaptDtxPlayout( h, sysTime, &stretchTime ); + } + ELSE + { + JB4_adaptActivePlayout( h, sysTime, extBufferedTime, scale, maxScaling ); + } + + /* time shrinking done if needed, now do time stretching or pop data unit to play */ + IF( stretchTime ) + { + /* return empty data unit */ + *pDataUnit = NULL; + move16(); + + IF( h->firstDataUnitPopped ) + { + h->nUnavailablePopped = L_add(h->nUnavailablePopped, 1); + IF( !h->lastPoppedWasSilence ) + { + h->nStretched = L_add(h->nStretched, 1); + /* jitter-induced insertion (e.g. buffer underflow) */ + h->jitterInducedConcealments = L_add(h->jitterInducedConcealments, 1); + } + } + /* add one frame to last playout delay */ + h->lastPlayoutOffset = rtpTs_add(h->lastPlayoutOffset, h->frameDuration); + } + ELSE + { + /* return next data unit from buffer */ + JB4_popFromBuffer( h, sysTime, pDataUnit ); + } + return 0; +} + +/* function for playout adaptation while active (no DTX) */ +static void JB4_adaptActivePlayout( JB4_HANDLE h, Word32 sysTime, + Word32 extBufferedTime, Word16 *scale, Word16 *maxScaling ) +{ + JB4_DATAUNIT_HANDLE nextDataUnit; + Word16 convertToLateLoss, dropEarly = 0; + Word32 targetMin, targetMax, targetDtx, targetStartUp, targetMaxStretch; + Word32 currPlayoutDelay, buffered; + Word16 gap, rate, dropGapMax, dropRateMin, dropRateMax; + Word32 minOffTicks, tsDiffToNextDataUnit; + Word32 delayWithClearedExternalBuffer; + Word32 tmp32; + + JB4_targetPlayoutDelay( h, &targetMin, &targetMax, &targetDtx, &targetStartUp ); + IF( JB4_JMF_MinOffset( h->ltJmf, &minOffTicks ) != 0 ) + { + return; + } + h->targetPlayoutDelay = L_shr(L_add(targetMin, targetMax ), 1); + + convertToLateLoss = false; + move16(); + dropEarly = false; + move16(); + dropGapMax = 200; + move16(); + dropRateMin = 5; + move16(); + dropRateMax = 200; /* 20% */ move16(); + /* calculate current playout delay */ + currPlayoutDelay = rtpTs_add(rtpTs_sub(h->lastPlayoutOffset, minOffTicks), extBufferedTime); + /* adapt it to time stretching due to empty buffer */ + IF( !JB4_INPUTBUFFER_IsEmpty( h->inputBuffer ) ) + { + nextDataUnit = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Front( h->inputBuffer ); + tsDiffToNextDataUnit = JB4_rtpTimeStampDiff( h->nextExpectedTs, nextDataUnit->timeStamp ); + IF( tsDiffToNextDataUnit < 0 ) + { + convertToLateLoss = true; + move16(); + { + /* time stretching is expected -> increase playout delay to allow dropping the late frame */ + currPlayoutDelay = L_sub(currPlayoutDelay, tsDiffToNextDataUnit); + currPlayoutDelay = L_add(currPlayoutDelay, 1); + } + } + } + + /* decided between shrinking/stretching */ + IF( GT_32(currPlayoutDelay, targetMax)) /* time shrinking */ + { + gap = extract_l(L_sub(currPlayoutDelay, h->targetPlayoutDelay)); + /* check if gap is positive and dropping is allowed + * and buffer contains enough time (ignoring one frame) */ test(); + test(); + test(); + IF( gap > 0 && + JB4_inspectBufferForDropping( h, &dropEarly, &buffered ) == 0 && + ( convertToLateLoss || + GT_32(L_add(L_add(buffered, h->frameDuration), extBufferedTime), targetMax) ) ) + { + IF( convertToLateLoss ) + { + JB4_dropFromBuffer( h, sysTime ); + h->nLostOrStretched = L_add(h->nLostOrStretched, 1); + } + ELSE IF( dropEarly ) + { + JB4_dropFromBuffer( h, sysTime ); + } + ELSE + { + /* limit gap to [gapMin,gapMax] and calculate current drop rate from gap */ + tmp32 = L_mult0(s_min(gap, dropGapMax), sub(dropRateMax, dropRateMin)); + assert( tmp32 == s_min(gap, dropGapMax) * ( dropRateMax - dropRateMin )); + rate = idiv3216(tmp32, dropGapMax); + assert( rate == tmp32 / dropGapMax ); + rate = add(rate, dropRateMin); + *scale = idiv1616U(sub(1000, rate), 10); + assert( *scale == (1000 - rate) / 10 ); + *maxScaling = extract_l(L_sub(currPlayoutDelay, targetMax)); + } + } + } + ELSE /* time stretching */ + { + /* Stretching only makes sense if we win one additional frame in the input buffer. + * If too much additional delay would be required to do so, then do not scale. + * Also make sure that the delay doesn't increase too much. */ + delayWithClearedExternalBuffer = L_add(L_sub(currPlayoutDelay, extBufferedTime), h->frameDuration); + targetMaxStretch = L_sub(targetMax, h->frameDuration); + IF( LE_32(L_add(delayWithClearedExternalBuffer, h->frameDuration), targetMaxStretch)&& + LT_32(currPlayoutDelay, targetMaxStretch) && LT_32(currPlayoutDelay, L_add(110, L_shr(h->rfDelay, 2))) ) + { + *scale = 120; + move16(); + *maxScaling = extract_l(L_sub(targetMaxStretch, currPlayoutDelay)); + } + } + +} + +/* function for playout adaptation while DTX */ +static void JB4_adaptDtxPlayout( JB4_HANDLE h, Word32 sysTime, Word16 *stretchTime ) +{ + JB4_DATAUNIT_HANDLE firstDu; + Word32 targetMin, targetMax, targetDtx, targetStartUp; + Word32 currPlayoutDelay, headRoom; + Word32 minOffTicks, tsDiffToNextDataUnit; + + + JB4_targetPlayoutDelay( h, &targetMin, &targetMax, &targetDtx, &targetStartUp ); + IF( JB4_JMF_MinOffset( h->ltJmf, &minOffTicks ) != 0 ) + { + return; + } + + /* calculate current playout delay */ + assert( rtpTs_sub(h->lastPlayoutOffset, minOffTicks) == h->lastPlayoutOffset - minOffTicks ); + currPlayoutDelay = rtpTs_sub(h->lastPlayoutOffset, minOffTicks); + + /* check for startup after DTX */ + IF( !JB4_INPUTBUFFER_IsEmpty( h->inputBuffer ) ) + { + firstDu = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Front( h->inputBuffer ); + + tsDiffToNextDataUnit = JB4_rtpTimeStampDiff( h->nextExpectedTs, firstDu->timeStamp ); + /* check if the next available data unit should already be used (time stamp order) */ + if( tsDiffToNextDataUnit > 0 ) + { + /* time stretching is expected -> increase playout delay */ + currPlayoutDelay = L_add(currPlayoutDelay, tsDiffToNextDataUnit); + } + + IF( !firstDu->silenceIndicator ) + { + /* recalculate playout delay based on first buffered data unit */ + JB4_playoutDelay( h, sysTime, firstDu->timeStamp, &currPlayoutDelay ); + /* check if the next available data unit should already be used (time stamp order) */ + if( tsDiffToNextDataUnit > 0 ) + { + /* time stretching is expected -> increase playout delay */ + currPlayoutDelay = L_add(currPlayoutDelay, tsDiffToNextDataUnit); + } + h->targetPlayoutDelay = targetStartUp; + move32(); + headRoom = L_deposit_l(12); /* 600 * 20 (h->frameDuration) / 1000 */ + /* decided between shrinking/stretching */ + IF( GT_32(currPlayoutDelay, L_add(targetStartUp, headRoom))) /* time shrinking */ + { + IF( JB4_checkDtxDropping( h ) ) + { + JB4_dropFromBuffer( h, sysTime ); + } + } + ELSE IF( LT_32(L_add(currPlayoutDelay, headRoom), targetStartUp)) /* time stretching */ + { + *stretchTime = true; + move16(); + } + return; + } + } + + /* adapt while DTX */ + h->targetPlayoutDelay = targetDtx; + move32(); + + /* decided between shrinking/stretching */ + IF( GE_32(currPlayoutDelay, L_add(targetDtx, h->frameDuration))) /* time shrinking */ + { + IF( JB4_checkDtxDropping( h ) ) + { + JB4_dropFromBuffer( h, sysTime ); + } + } + ELSE IF( LT_32(L_add(currPlayoutDelay, L_shr(h->frameDuration, 1)), targetDtx)) /* time stretching */ + { + *stretchTime = true; + move16(); + } +} + +/* function to do playout adaptation before playing the first data unit */ +static void JB4_adaptFirstPlayout( JB4_HANDLE h, Word32 sysTime, Word16 *prebuffer ) +{ + Word32 currPlayoutDelay; + JB4_DATAUNIT_HANDLE firstDu; + Word32 targetMin, targetMax, targetDtx, targetStartUp; + + /* get target delay */ + IF( JB4_INPUTBUFFER_IsEmpty( h->inputBuffer ) ) + { + *prebuffer = true; + move16(); + return; + } + JB4_targetPlayoutDelay( h, &targetMin, &targetMax, &targetDtx, &targetStartUp ); + + IF(LT_32(targetStartUp, h->frameDuration)) + { + return; + } + /* calculate delay if first data unit would be played now */ + firstDu = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Front( h->inputBuffer ); + + IF( JB4_playoutDelay( h, sysTime, firstDu->timeStamp, &currPlayoutDelay ) != 0 ) + { + *prebuffer = true; + move16(); + return; + } + + IF( LT_32(L_add(currPlayoutDelay, L_shr(h->frameDuration, 1)), targetStartUp)) /* time stretching */ + { + *prebuffer = true; + move16(); + } + ELSE /* no adaptation, start playout */ + { + *prebuffer = false; + move16(); + } +} + +/* function to look into the buffer and check if it makes sense to drop a data unit */ +static Word16 JB4_inspectBufferForDropping( const JB4_HANDLE h, Word16 *dropEarly, Word32 *buffered ) +{ + Word16 inputBufferSize; + Word32 tsDiff, bufferedTs, endTs; + JB4_DATAUNIT_HANDLE firstDu, secondDu, lastDu; + + assert( !h->lastPoppedWasSilence ); + *dropEarly = false; + move16(); + *buffered = L_deposit_l(0); + inputBufferSize = JB4_INPUTBUFFER_Size( h->inputBuffer ); + + IF( inputBufferSize == 0 ) + { + return -1; + } + + firstDu = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Front( h->inputBuffer ); + tsDiff = L_deposit_l(0); + /* check for loss: timestamp diff is exactly 0 in the valid case */ + IF( h->firstDataUnitPopped ) + { + tsDiff = JB4_rtpTimeStampDiff( h->nextExpectedTs, firstDu->timeStamp ); + } + + IF( tsDiff <= 0 ) + { + /* preview data unit to play after dropping */ + IF( LE_16(inputBufferSize, 1)) + { + /* data unit to play missing, avoid drop followed by concealment */ + return -1; + } + secondDu = JB4_INPUTBUFFER_Element( h->inputBuffer, 1 ); + + IF( rtpTs_sub(rtpTs_add(firstDu->timeStamp, h->frameDuration), secondDu->timeStamp) != 0 ) + { + /* data unit to play is not available, avoid drop followed by concealment */ + return -1; + } + /* calculate buffered time span */ + bufferedTs = L_deposit_l(0); + } + ELSE IF( rtpTs_sub(tsDiff, L_mult0(2, extract_l(h->frameDuration))) == 0 ) + { + /* data unit to play is not available, avoid dropping followed by concealment */ + return -1; + } + ELSE /* seqNoDiff == 1 || seqNoDiff > 2 */ + { + /* first data unit is not available -> drop it early to avoid concealment + * This is very aggressive: ignores the maximum drop rate (50% drop and 50% concealment for adjacent lost), + * but on the other hand, dropping sounds better than concealment. */ + *dropEarly = true; + move16(); + /* data unit to drop (first one) is lost */ + bufferedTs = L_deposit_l(0); + } + + /* add time stamp difference of last and first actually buffered data unit */ + IF( EQ_16(inputBufferSize, 1)) + { + bufferedTs = rtpTs_add(bufferedTs, h->frameDuration); + } + ELSE + { + lastDu = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Back( h->inputBuffer ); + endTs = rtpTs_add(lastDu->timeStamp, h->frameDuration); + /* check for RTP time stamp wrap around */ + /* check if sign changes from negative to positive */ test(); + IF( L_and(firstDu->timeStamp, 0x80000000) != 0 && + L_and(endTs, 0x80000000) == 0 ) + { + endTs = rtpTs_add(endTs, 0xFFFFFFFF); + } + bufferedTs = rtpTs_add(bufferedTs, rtpTs_sub(endTs, firstDu->timeStamp)); + } + + /* the result should not be negative */ + IF( bufferedTs < 0 ) + { + return -1; + } + *buffered = bufferedTs; + move32(); + return 0; +} + +/* function to look into the buffer and check if it makes sense to drop a data unit */ +static Word16 JB4_checkDtxDropping( const JB4_HANDLE h ) +{ + Word16 inputBufferSize; + JB4_DATAUNIT_HANDLE firstDu; + Word16 droppingAllowed; + + assert( h->firstDataUnitPopped ); + assert( h->lastPoppedWasSilence ); + droppingAllowed = 1; + move16(); + inputBufferSize = JB4_INPUTBUFFER_Size( h->inputBuffer ); + + IF( inputBufferSize > 0 ) + { + firstDu = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Front( h->inputBuffer ); + /* check for loss */ + if( JB4_rtpTimeStampDiff( h->nextExpectedTs, firstDu->timeStamp ) <= 0 ) + { + /* no not drop first active frame */ + droppingAllowed = 0; + move16(); + } + } + /* else: buffer empty, allow dropping FRAME_NO_DATA */ + return droppingAllowed; +} + +/* function to estimate the short term jitter */ +static void JB4_estimateShortTermJitter( JB4_HANDLE h, Word32 rcvTime, Word32 rtpTimeStamp ) +{ + Word32 stOffset, ltOffset, duration, maxDuration; + Word32 jitter, minTime, maxTime; + JB4_CIRCULARBUFFER_ELEMENT maxElement, dequedElement; + + jitter = L_deposit_l(0); + JB4_JMF_PushPacket( h->stJmf, rcvTime, rtpTimeStamp ); + /* save delta delay */ + IF( JB4_JMF_Jitter( h->stJmf, &jitter ) == 0 ) + { + /* compensate difference between both offsets */ + JB4_JMF_MinOffset( h->stJmf, &stOffset ); + JB4_JMF_MinOffset( h->ltJmf, <Offset ); + jitter = L_add(jitter, L_sub(stOffset, ltOffset)); + assert( jitter >= 0 ); + + IF( JB4_CIRCULARBUFFER_IsFull( h->stJitterFifo ) ) + { + JB4_CIRCULARBUFFER_Deque( h->stJitterFifo, &dequedElement ); + JB4_CIRCULARBUFFER_Deque( h->stTimeStampFifo, &dequedElement ); + } + JB4_CIRCULARBUFFER_Enque( h->stJitterFifo, jitter ); + JB4_CIRCULARBUFFER_Enque( h->stTimeStampFifo, rtpTimeStamp ); + + /* check for duration and discard first entries if too long */ + minTime = JB4_CIRCULARBUFFER_Front( h->stTimeStampFifo ); + maxTime = JB4_CIRCULARBUFFER_Back( h->stTimeStampFifo ); + + duration = rtpTs_sub(maxTime, minTime); + IF( duration > 0 ) + { + maxDuration = L_mult0(4, h->timeScale); + WHILE( rtpTs_sub(duration, maxDuration) > 0 ) + { + JB4_CIRCULARBUFFER_Deque( h->stJitterFifo, &dequedElement ); + JB4_CIRCULARBUFFER_Deque( h->stTimeStampFifo, &dequedElement ); + minTime = JB4_CIRCULARBUFFER_Front( h->stTimeStampFifo ); + duration = rtpTs_sub(maxTime, minTime); + IF( duration <= 0) + { + BREAK; + } + } + } + } + + /* update h->stJitter */ + IF( !JB4_CIRCULARBUFFER_IsEmpty( h->stJitterFifo ) ) + { + JB4_CIRCULARBUFFER_Max( h->stJitterFifo, &maxElement ); + /* round up to full frame duration */ + h->stJitter = L_add(maxElement, L_sub(h->frameDuration, 1)); + h->stJitter = L_mult0(idiv1616(extract_l(h->stJitter), extract_l(h->frameDuration)), extract_l(h->frameDuration)); + } +} + +/* function to pop a data unit from the buffer */ +static void JB4_popFromBuffer( JB4_HANDLE h, Word32 sysTime, JB4_DATAUNIT_HANDLE *pDataUnit ) +{ + JB4_DATAUNIT_HANDLE nextDataUnit; + Word32 nStretched, tsDiff; + + JB4_DATAUNIT_HANDLE tempDataUnit; + Word32 readlen ; + Word16 i; + Word32 frameoffset; + Word32 maxval, lost, total_rec ; + + + + JB4_DATAUNIT_HANDLE partialCopyDu; + Word16 searchpos, endpos; + + /* check if a data unit is available */ + IF( JB4_INPUTBUFFER_IsEmpty( h->inputBuffer ) ) + { + /* no data unit available */ + *pDataUnit = NULL; + move16(); + h->nextExpectedTs = rtpTs_add(h->nextExpectedTs, h->frameDuration); + + IF( h->lastPoppedWasSilence ) + { + h->nComfortNoice = L_add(h->nComfortNoice, 1); + } + ELSE + { + h->nUnavailablePopped = L_add(h->nUnavailablePopped, 1); + h->nLostOrStretched = L_add(h->nLostOrStretched, 1); + } + return; + } + + /* preview next data unit in sequence order */ + nextDataUnit = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Front( h->inputBuffer ); + + /* check if this is the first data unit */ + IF( !h->firstDataUnitPopped ) + { + h->firstDataUnitPopped = true; + move16(); + /* adjust sequence numbers to avoid handling first packet as loss */ + h->nextExpectedTs = nextDataUnit->timeStamp; + move32(); + } + + /* check if the next available data unit should already be used (time stamp order) */ + tsDiff = JB4_rtpTimeStampDiff( nextDataUnit->timeStamp, h->nextExpectedTs ); + + h->totWin += 1; + move16(); + test(); + IF ( ( GT_32(h->totWin , 3000))||(GT_32(h->FecOffWinLen,100))) + { + maxval = h->FecOffWin[1]; + move16(); + h->optimum_offset = 1; + move16(); + FOR( i = 2; i < MAXOFFSET ; i++ ) + { + IF ( GT_32( h->FecOffWin[i], maxval )) + { + maxval = h->FecOffWin[i] ; + move16(); + h->optimum_offset = i ; + move16(); + } + h->FecOffWin[i] = 0; + move16(); + } + h->FecOffWin[0] = 0; + move16(); + h->FecOffWin[1] = 0; + move16(); + h->totWin = 0; + move16(); + h->FecOffWinLen = 0; + move16(); + + lost = L_sub( L_add(h->nLost, h->nPartialCopiesUsed), h->last_nLost ); + total_rec = L_sub( L_add(h->nAvailablePopped , h->nUnavailablePopped), h->last_ntot ); + + IF ( lost != 0 && total_rec != 0 ) + { + h->netLossRate = divide3232( lost , total_rec ); + } + ELSE + { + h->netLossRate = 0; + } + h->last_nLost = L_add(h->nLost, h->nPartialCopiesUsed); + h->last_ntot = L_add(h->nAvailablePopped , h->nUnavailablePopped); + } + + + + IF( tsDiff < 0 ) + { + + + readlen = JB4_INPUTBUFFER_Size( h->inputBuffer ); + move16(); + FOR ( i=0; i < readlen; i++) + { + tempDataUnit = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Element( h->inputBuffer, i ); + + test(); + IF ( tempDataUnit->partial_frame == 0 && h->lastPoppedWasSilence == 0 ) + { + frameoffset = Mult_32_16(JB4_rtpTimeStampDiff( h->nextExpectedTs, tempDataUnit->timeStamp ), 1639 ) ; /* divide by 20 */ + test(); + IF ( frameoffset > 0 && (LT_32( frameoffset, MAXOFFSET))) + { + h->FecOffWin[frameoffset] = L_add(h->FecOffWin[frameoffset], 1); + } + } + } + + h->FecOffWinLen = L_add (h->FecOffWinLen, 1); + + + /* next expected data unit is missing + * -> conceal network loss, do time stretching or create comfort noice */ + *pDataUnit = NULL; + + /* update statistics */ + h->nextExpectedTs = rtpTs_add(h->nextExpectedTs, h->frameDuration); + + IF( h->lastPoppedWasSilence ) + { + h->nComfortNoice = L_add(h->nComfortNoice, 1); + } + ELSE + { + h->nUnavailablePopped = L_add(h->nUnavailablePopped, 1); + h->nLostOrStretched = L_add(h->nLostOrStretched, 1); + } + return; + } + + /* fetch the next data unit from buffer */ + *pDataUnit = nextDataUnit; + move16(); + nextDataUnit->nextCoderType = INACTIVE; + IF( EQ_16(h->pre_partial_frame,1)||EQ_16(nextDataUnit->partial_frame,1)) + { + IF( nextDataUnit->partial_frame ) + { + h->pre_partial_frame = 1; + } + ELSE IF( h->pre_partial_frame ) + { + h->pre_partial_frame = 0; + } + + endpos = JB4_INPUTBUFFER_Size(h->inputBuffer); + FOR(searchpos = 0; searchpos < endpos; searchpos++) + { + partialCopyDu = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Element(h->inputBuffer, searchpos); + IF ( EQ_32(partialCopyDu->timeStamp,L_add(nextDataUnit->timeStamp,partialCopyDu->duration))) + { + get_NextCoderType_fx( partialCopyDu->data, &nextDataUnit->nextCoderType); + break; + } + } + } + JB4_INPUTBUFFER_Deque( h->inputBuffer, (void**)pDataUnit ); + + + IF ( EQ_16(nextDataUnit->partial_frame,1)) + { + + h->nPartialCopiesUsed = L_add(h->nPartialCopiesUsed, 1); + readlen = JB4_INPUTBUFFER_Size( h->inputBuffer ); + move16(); + FOR ( i=0; i < readlen; i++) + { + tempDataUnit = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Element( h->inputBuffer, i ); + test(); + IF ( tempDataUnit->partial_frame == 0 && h->lastPoppedWasSilence == 0 ) + { + frameoffset = Mult_32_16(JB4_rtpTimeStampDiff( h->nextExpectedTs, tempDataUnit->timeStamp ), 1639 ) ; + test(); + IF ( frameoffset > 0 && (LT_32( frameoffset, MAXOFFSET))) + { + h->FecOffWin[frameoffset] = L_add(h->FecOffWin[frameoffset], 1); + } + } + } + + h->FecOffWinLen = L_add (h->FecOffWinLen, 1); + } + + + + + /* update statistics */ + IF( h->nLostOrStretched != 0U ) + { + assert( h->lastPoppedWasSilence == false ); + /* separate concealments since last available pop in lost and stretched */ + nStretched = idiv3216(tsDiff, extract_l(h->frameDuration)); + assert( nStretched == tsDiff / h->frameDuration ); + assert( h->nLostOrStretched >= nStretched ); + h->nLost = L_add(h->nLost, L_sub(h->nLostOrStretched, nStretched)); + /* jitter-induced insertion (e.g. buffer underflow) */ + h->jitterInducedConcealments = L_add(h->jitterInducedConcealments, nStretched); + h->nStretched = L_add(h->nStretched, nStretched); + h->nLostOrStretched = L_deposit_l(0); + } + h->lastReturnedTs = nextDataUnit->timeStamp; + move32(); + JB4_updateLastTimingMembers( h, sysTime, nextDataUnit->timeStamp ); + h->nextExpectedTs = rtpTs_add(nextDataUnit->timeStamp, h->frameDuration); + + if( nextDataUnit->silenceIndicator ) + h->nComfortNoice = L_add(h->nComfortNoice, 1); + if( !nextDataUnit->silenceIndicator ) + h->nAvailablePopped = L_add(h->nAvailablePopped, 1); + h->lastPoppedWasSilence = nextDataUnit->silenceIndicator; + move16(); +} + +/* function to drop a data unit from the buffer - updates nShrinked */ +static void JB4_dropFromBuffer( JB4_HANDLE h, Word32 sysTime ) +{ + JB4_DATAUNIT_HANDLE nextDataUnit, dataUnit; + Word32 tsDiff, nStretched; + (void)sysTime; + + /* check if a data unit is available */ + IF( JB4_INPUTBUFFER_IsEmpty( h->inputBuffer ) ) + { + return; + } + /* preview next data unit in sequence order */ + nextDataUnit = (JB4_DATAUNIT_HANDLE)JB4_INPUTBUFFER_Front( h->inputBuffer ); + + /* check if this is the first data unit */ + IF( !h->firstDataUnitPopped ) + { + h->firstDataUnitPopped = true; + move16(); + /* adjust sequence numbers to avoid handling first packet as loss */ + h->nextExpectedTs = nextDataUnit->timeStamp; + move32(); + } + + /* check if the next available data unit should already be used (time stamp order) */ + tsDiff = JB4_rtpTimeStampDiff( nextDataUnit->timeStamp, h->nextExpectedTs ); + + IF( tsDiff < 0 ) + { + /* next expected data unit is missing, remember this data unit as popped, + * but do not count it as lost, because it will not be concealed */ + h->nextExpectedTs = rtpTs_add(h->nextExpectedTs, h->frameDuration); + /* substract one frame from last playout delay */ + h->lastPlayoutOffset = rtpTs_sub(h->lastPlayoutOffset, h->frameDuration); + + IF( !h->lastPoppedWasSilence ) + { + h->nShrinked = L_add(h->nShrinked, 1); + /* modification of the output timeline due to link loss */ + h->nUnavailablePopped = L_add(h->nUnavailablePopped, 1); + h->nLostOrStretched = L_add(h->nLostOrStretched, 1); + } + + if( h->lastTargetTime != 0 ) + { + h->lastTargetTime = L_add(h->lastTargetTime, h->frameDuration); + } + return; + } + + /* fetch the next data unit from buffer */ + JB4_INPUTBUFFER_Deque( h->inputBuffer, (void *)&dataUnit ); + /* update statistics */ + IF( h->nLostOrStretched != 0U ) + { + assert( h->lastPoppedWasSilence == false ); + /* separate concealments since last available pop in lost and stretched */ + nStretched = idiv3216(tsDiff, extract_l(h->frameDuration)); + assert( nStretched == tsDiff / h->frameDuration ); + assert( h->nLostOrStretched >= nStretched ); + + /* convert stretching followed by shrinking to late-loss */ + IF( nStretched > 0 ) + { + nStretched = L_sub(nStretched, 1); + h->nLateLost = L_add(h->nLateLost, 1); + h->nLost = L_add(h->nLost , L_sub(h->nLostOrStretched, nStretched)); + /* jitter-induced insertion (e.g. buffer underflow) */ + h->jitterInducedConcealments = L_add(h->jitterInducedConcealments, nStretched); + + if( !dataUnit->silenceIndicator ) + { + /* JBM induced removal of a speech frame (intentional frame dropping) */ + h->jitterInducedConcealments = L_add(h->jitterInducedConcealments, 1); + } + h->nStretched = L_add(h->nStretched, nStretched); + } + ELSE + { + h->nLost = L_add(h->nLost, h->nLostOrStretched); + h->nShrinked = L_add(h->nShrinked, 1); + if( !dataUnit->silenceIndicator ) + { + /* JBM induced removal of a speech frame (intentional frame dropping) */ + h->jitterInducedConcealments = L_add(h->jitterInducedConcealments, 1); + } + } + h->nLostOrStretched = L_deposit_l(0); + } + ELSE IF( !dataUnit->silenceIndicator ) + { + h->nShrinked = L_add(h->nShrinked, 1); + /* JBM induced removal of a speech frame (intentional frame dropping) */ + h->jitterInducedConcealments = L_add(h->jitterInducedConcealments, 1); + } + + h->lastReturnedTs = dataUnit->timeStamp; + move32(); + h->lastPoppedWasSilence = dataUnit->silenceIndicator; + move16(); + h->nextExpectedTs = rtpTs_add(dataUnit->timeStamp, h->frameDuration); + + /* substract one frame from last playout delay */ + h->lastPlayoutOffset = rtpTs_sub(h->lastPlayoutOffset, h->frameDuration); + + if( h->lastTargetTime != 0 ) + h->lastTargetTime = L_add(h->lastTargetTime, h->frameDuration); + JB4_FreeDataUnit(h, dataUnit); +} + +/* function to calculate the playout delay based on the current jitter */ +static Word16 JB4_playoutDelay( const JB4_HANDLE h, Word32 playTime, Word32 rtpTimeStamp, Word32 *delay ) +{ + Word32 minOffTicks; + + IF( JB4_JMF_MinOffset( h->ltJmf, &minOffTicks ) != 0 ) + { + return -1; + } + + *delay = rtpTs_sub(rtpTs_sub(playTime, minOffTicks), rtpTimeStamp); + return 0; +} + +/* function to update lastPlayoutDelay and lastTargetTime after popFromBuffer() */ +static void JB4_updateLastTimingMembers( JB4_HANDLE h, Word32 playTime, Word32 rtpTimeStamp ) +{ + Word32 minOffTicks; + + IF( JB4_JMF_MinOffset( h->ltJmf, &minOffTicks ) != 0 ) + { + return; + } + + /* playoutDelay = playTime - minOffset - timeStamp */ + h->lastPlayoutOffset = rtpTs_sub(playTime, rtpTimeStamp); + /* targetTime = minOffset + timeStamp + targetDelay */ + h->lastTargetTime = rtpTs_add(rtpTs_add(minOffTicks, rtpTimeStamp), h->targetPlayoutDelay); +} + +/* function to compare the RTP time stamps of two data units: newElement==arrayElement ? 0 : (newElement>arrayElement ? +1 : -1) */ +static Word32 JB4_inputBufferCompareFunction( const JB4_INPUTBUFFER_ELEMENT newElement, + const JB4_INPUTBUFFER_ELEMENT arrayElement, Word16 *replaceWithNewElementIfEqual ) +{ + JB4_DATAUNIT_HANDLE newDataUnit, arrayDataUnit; + Word32 diff, result; + + *replaceWithNewElementIfEqual = 0; + move16(); + newDataUnit = (JB4_DATAUNIT_HANDLE)newElement; + move16(); + arrayDataUnit = (JB4_DATAUNIT_HANDLE)arrayElement; + move16(); + diff = JB4_rtpTimeStampDiff( arrayDataUnit->timeStamp, newDataUnit->timeStamp ); + + IF( diff > 0 ) + { + result = L_deposit_l(1); + } + ELSE IF( diff < 0 ) + { + result = L_negate(1); + } + ELSE /* equal timestamps */ + { + result = 0; + move32(); + test(); + IF(newDataUnit->partial_frame == 0 && arrayDataUnit->partial_frame != 0) + { + /* replace partial copy with primary copy */ + *replaceWithNewElementIfEqual = 1; + move16(); + } + ELSE IF(EQ_16(newDataUnit->partial_frame, arrayDataUnit->partial_frame)&& + GT_32(newDataUnit->dataSize, arrayDataUnit->dataSize)) + { + /* if both are primary or partial: take the one with higher size (e.g. higher bitrate) */ + *replaceWithNewElementIfEqual = 1; + move16(); + } + } + return result; +} + diff --git a/lib_dec/jbm_jb4sb.h b/lib_dec/jbm_jb4sb.h new file mode 100644 index 0000000..1eba33b --- /dev/null +++ b/lib_dec/jbm_jb4sb.h @@ -0,0 +1,70 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/** \file jbm_jb4sb.h Jitter Buffer Management Interface */ + +#ifndef ACE_JB4SB_H +#define ACE_JB4SB_H ACE_JB4SB_H + +/** handle for jitter buffer */ +typedef struct JB4* JB4_HANDLE; + +/** jitter buffer data units (access unit together with RTP seqNo, timestamp, ...) */ +struct JB4_DATAUNIT +{ + /** the RTP sequence number (16 bits) */ + Word16 sequenceNumber; + /** the RTP time stamp (32 bits) of this chunk in timeScale() units */ + Word32 timeStamp; + /** the duration of this chunk in timeScale() units */ + Word32 duration; + /** the RTP time scale, which is used for timeStamp() and duration() */ + Word32 timeScale; + /** the receive time of the RTP packet in milliseconds */ + Word32 rcvTime; + /** true, if the data unit contains only silence */ + Word16 silenceIndicator; + Word16 isAMRWB_IOmode; + /** for EVS payload */ + Word16 frameTypeIndex; + /** Q bit for AMR-WB IO */ + Word16 qBit; + + /** the binary encoded access unit */ + UWord8 *data; + /** the size of the binary encoded access unit [bits] */ + Word16 dataSize; + + /** identify if the data unit has a partial copy of a previous frame */ + Word16 partial_frame; + /** offset of the partial copy contained in that frame or zero */ + Word16 partialCopyOffset; + Word16 nextCoderType; +}; +/** handle for jitter buffer data units */ +typedef struct JB4_DATAUNIT* JB4_DATAUNIT_HANDLE; + + +Word16 JB4_Create( JB4_HANDLE *ph ); +void JB4_Destroy( JB4_HANDLE *ph ); + +Word16 JB4_Init( JB4_HANDLE h, Word16 safetyMargin ); + +/** Returns a memory slot to store a new data unit */ +JB4_DATAUNIT_HANDLE JB4_AllocDataUnit( JB4_HANDLE h ); +/** Notifies the JBM that a data unit is no longer used and the memory can be reused */ +void JB4_FreeDataUnit( JB4_HANDLE h, JB4_DATAUNIT_HANDLE dataUnit ); + +Word16 JB4_PushDataUnit( JB4_HANDLE h, JB4_DATAUNIT_HANDLE dataUnit, Word32 rcvTime ); +Word16 JB4_PopDataUnit( JB4_HANDLE h, Word32 sysTime, Word32 extBufferedTime, + JB4_DATAUNIT_HANDLE *pDataUnit, Word16 *scale, Word16 *maxScaling ); + +/** function to get the number of data units contained in the buffer */ +Word16 JB4_bufferedDataUnits( const JB4_HANDLE h ); + +Word16 JB4_getFECoffset(JB4_HANDLE h); + +Word16 JB4_FECoffset(JB4_HANDLE h); + +#endif /* ACE_JB4SB_H */ diff --git a/lib_dec/jbm_pcmdsp_apa.c b/lib_dec/jbm_pcmdsp_apa.c new file mode 100644 index 0000000..d098a6f --- /dev/null +++ b/lib_dec/jbm_pcmdsp_apa.c @@ -0,0 +1,1472 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*! @file pcmdsp_apa.c Adaptive Playout for Audio (apa). */ + +/* system headers */ +#include +#include /* malloc(), free() */ +#include +/* flc header */ +#include "stl.h" +/* instrumentation */ +/* local headers */ +#include "jbm_pcmdsp_apa.h" +#include "jbm_pcmdsp_similarityestimation.h" +#include "jbm_pcmdsp_window.h" +#include "options.h" + + +/* +******************************************************************************** +* LOCAL DATA DEFINITIONS AND PROTOTYPES +******************************************************************************** +*/ + +/* maximum number of segments/iterations in extend_frm() */ +#define MAXN 10 + +/* definition of state struct */ +struct apa_state_t +{ + /* number of right shifts to be applied to the signal before correlation functions */ + Word16 signalScaleForCorrelation; + /* scaled input samples for similarity estimation */ + Word16 frmInScaled[2*48000/50]; + /* output buffer */ + Word16 buf_out[APA_BUF]; + Word16 l_buf_out; + + /* Hann window */ + const Word16 *win; + Word16 l_halfwin; + /* subsample factor used for Hann window + * used to step over x values for lower sample rates */ + Word16 win_incrementor; + + /* sampling rate [Hz] */ + Word32 rate; + + /* length of a segment [samples] */ + Word16 l_seg; + + /* length of a frame [samples] */ + Word16 l_frm; + + /* total number of processed input samples since apa_reset() */ + Word32 l_in_total; + + /* sum of inserted/removed samples since last apa_set_scale() */ + Word32 diffSinceSetScale; + /* number of input frames since last apa_set_scale() */ + Word16 nFramesSinceSetScale; + + /* current and previous scaling ratio [%]. */ + Word16 scale; + + /* minimum pitch length [samples] */ + Word16 p_min; + + /* search length [samples] */ + Word16 l_search; + + Word16 wss; /* waveform subsampling */ + Word16 css; /* correlation subsampling */ + + Word32 targetQualityQ16; /* Q15.16 */ + Word16 qualityred; /* quality reduction threshold */ + Word16 qualityrise; /* quality rising for adaptive quality thresholds */ + + Word16 last_pitch; /* last pitch/sync position */ + Word16 bad_frame_count; /* # frames before quality threshold is lowered */ + Word16 good_frame_count; /* # scaled frames */ + + Word16 num_channels; /* number of input/output channels */ +}; + + +/* prototypes for local functions */ + +/** Converts the correlation energy to dB. */ +Word16 apa_corrEnergy2dB(Word32 energy, Word16 energyExp, Word16 corr_len); + +/** Increases the calculated quality of signals with low energy. */ +Word16 apa_getQualityIncreaseForLowEnergy(Word16 energydB); + +static Word8 logarithmic_search(const apa_state_t * ps, + const Word16 * signal, + Word16 s_start, + Word16 inlen, + Word16 offset, + Word16 fixed_pos, + Word16 corr_len, + Word16 wss, + Word16 css, + Word16 * synchpos); + +static Word16 find_synch (apa_state_t * ps, + const Word16 * in, + Word16 l_in, + Word16 s_start, + Word16 s_len, + Word16 fixed_pos, + Word16 corr_len, + Word16 offset, + Word16 * energydBQ8, + Word32 * qualityQ16, + Word16 * synch_pos); + +static Word16 copy_frm (apa_state_t * ps, + const Word16 frm_in[], + Word16 frm_out[], + Word16 * l_frm_out); + +static Word16 shrink_frm (apa_state_t * ps, + const Word16 frm_in[], + Word16 maxScaling, + Word16 frm_out[], + Word16 * l_frm_out); + +static Word16 extend_frm (apa_state_t * ps, + const Word16 frm_in[], + Word16 frm_out[], + Word16 * l_frm_out); + + +/* +******************************************************************************** +* PUBLIC PROGRAM CODE +******************************************************************************** +*/ + +/* Allocates memory for state struct and initializes elements. */ +Word8 apa_init (apa_state_t ** pps) +{ + apa_state_t *ps; + + ps = NULL; + move16(); + + /* make sure pointer is valid */ + IF(!pps) + { + return 1; + } + + /* allocate state struct */ + ps = (apa_state_t *) malloc (sizeof (apa_state_t)); + IF(!ps) + { + return 2; + } + apa_reset (ps); + *pps = ps; + move16(); + return 0; +} + +/* Sets state variables to initial value. */ +void apa_reset (apa_state_t * ps) +{ + /* init state struct */ + ps->signalScaleForCorrelation = 0; + move16(); + ps->l_buf_out = 0; + move16(); + ps->win = NULL; + move16(); + ps->l_halfwin = 0; + move16(); + ps->win_incrementor = 0; + move16(); + ps->rate = L_deposit_l(0); + ps->l_seg = 0; + move16(); + ps->l_frm = 0; + move16(); + ps->l_in_total = L_deposit_l(0); + ps->diffSinceSetScale = L_deposit_l(0); + ps->nFramesSinceSetScale = 0; + move16(); + ps->scale = 100; + move16(); + ps->p_min = 0; + move16(); + ps->l_search = 0; + move16(); + ps->wss = 1; + move16(); + ps->css = 1; + move16(); + ps->targetQualityQ16 = L_deposit_l(0); + ps->qualityred = 0; + move16(); + ps->qualityrise = 0; + move16(); + ps->last_pitch = 0; + move16(); + ps->bad_frame_count = 0; + move16(); + ps->good_frame_count = 0; + move16(); + ps->num_channels = 0; + move16(); +} + +/* Sets the audio configuration. */ +Word8 apa_set_rate( apa_state_t * ps, Word32 rate, Word16 num_channels ) +{ + Word16 divScaleFac; + + /* make sure pointer is valid */ + IF( ps == (apa_state_t *) NULL ) + { + return 1; + } + + /* assert rate is actually matching one of the supported EVS rates otherwise Hann window is wrong */ + assert( rate == 8000 || rate == 16000 || rate == 24000 || rate == 32000 || rate == 48000 ); + + /* reset state struct */ + apa_reset( ps ); + + /* copy rate to state struct */ + ps->rate = rate; + move32(); + + /* set number of channels */ + ps->num_channels = num_channels; + move16(); + + /* + * several other parameters depend on the sampling rate + * and are set below. Some "magic numbers" are used here + * which are based on typical values of a "pitch" in + * human voice. The pitch length is the period of the + * base frequency and is usually assumed to be 40-240 + * samples at 16 kHz. + */ + + /* set frame size */ + /* set to 320 samples at 16 kHz */ + ps->l_frm = BASOP_Util_Divide3216_Scale( L_mult0_3216( ps->rate, ps->num_channels ), 50, &divScaleFac ); + ps->l_frm = shl( ps->l_frm, add( divScaleFac,1 ) ); + + /* set segment size */ + /* in the order of a pitch, set to 160 samples at 16 kHz */ + /* used for windowing and as the correlation length, i.e., */ + /* the size of the template segment. */ + /* before basop port was originally : ps->l_seg = ( ps->rate * ps->num_channels ) / 100 ); + * but whilst frm_size is still hard-coded the seg_size can be taken from half frm_size */ + ps->l_seg = shr( ps->l_frm, 1 ); + + /* init Hann window */ + /* Note: l_win < APA_BUF is required, which is assured */ + /* because APA_MAX_RATE/100 = l_win = 441 < 2048 = APA_BUF */ + /* Length of Hann window is independent of + * number of channels - same window applied to all channels. + * sample rates 24k & 48k lookup a Hann window of length of 48000/50=960, + * where 24k subsamples (skips every second sample) */ + ps->win = pcmdsp_window_hann_640; + move16(); + ps->l_halfwin = 320; + move16(); + ps->win_incrementor = 1; + move16(); + IF(EQ_32(ps->rate, 48000)) + { + ps->win = pcmdsp_window_hann_960; + move16(); + ps->l_halfwin = 480; + move16(); + } + IF(EQ_32(ps->rate, 24000)) + { + ps->win = pcmdsp_window_hann_960; + move16(); + ps->l_halfwin = 480; + move16(); + ps->win_incrementor = 2; + move16(); + } + /* sample rates 8k, 16k & 32k use a Hann window of length of 640, + * where 8k and 16k subsample */ + if(EQ_32(ps->rate, 16000)) + ps->win_incrementor = 2; + move16(); + if(EQ_32(ps->rate, 8000)) + ps->win_incrementor = 4; + move16(); + + /* set minimum pitch */ + /* set to 40 samples at 16 kHz */ + /* (defines min change in number of samples, i.e., abs(l_in-l_out) >= p_min) */ + /* before basop port was originally: ps->p_min = (ps->rate * ps->num_channels) / 400; + * but for simplicity can be taken as l_seg / 4 */ + ps->p_min = shr( ps->l_seg, 2 ); + + /* set search length */ + /* must cover one pitch, set to 200 samples at 16 kHz */ + /* (the resulting maximum pitch is then p_min+l_search = 240 samples at 16 kHz) */ + /* the following is equivalent to: ps->l_search = (ps->rate * ps->num_channels) / 80; */ + ps->l_search = BASOP_Util_Divide3216_Scale( L_mult0_3216( ps->rate, ps->num_channels ), 80, &divScaleFac ); + ps->l_search = shl( ps->l_search, add( divScaleFac,1 ) ); + + ps->signalScaleForCorrelation = getSignalScaleForCorrelation(ps->rate); + + return 0; +} + +/* Set scaling. */ +Word8 apa_set_scale (apa_state_t * ps, Word16 scale) +{ + /* make sure pointer is valid */ + IF( ps == (apa_state_t *) NULL) + { + return 1; + } + + /* check range */ + assert( scale >= APA_MIN_SCALE && scale <= APA_MAX_SCALE ); + + /* do nothing if same scale is set multiple times */ + /* (otherwise scale control is confused) */ + IF( EQ_16(ps->scale, scale)) + { + return 0; + } + + /* copy to state struct */ + ps->scale = scale; + move16(); + + /* reset scaling statistics */ + ps->diffSinceSetScale = L_deposit_l(0); + ps->nFramesSinceSetScale = 0; + move16(); + return 0; +} + +/* +******************************************************************************** +* +* Function : apa_set_quality +* Tables : +* Compile Defines : +* Return : 0 on success, 1 on failure +* Information : Set quality thresholds. +* +* quality is lower limit for minimum quality +* Range is [-2;2] - where positive values allow +* only pasting with same phase information +* Negative values would yield cross phased pasting +* +* qualityred allows dynamic lowering of lower quality +* bound - this gives better results for rhythmic signals +* Range is [0;20], meaning 0.1 lowering*qualityred +* +* undocumented: qualityrise (same as qualityred - other +* direction) +* +******************************************************************************** +*/ +Word8 apa_set_quality( + apa_state_t *ps, + Word32 qualityQ16, + Word16 qualityred, + Word16 qualityrise) +{ + assert(ps != (apa_state_t *) NULL); + assert(LE_32(L_deposit_h(-2), qualityQ16) && LE_32(qualityQ16, L_deposit_h(3)) ); + assert(qualityred > 0 && LE_16( qualityred, 20 )); + assert(qualityrise > 0 && LE_16(qualityrise, 20)); + + ps->targetQualityQ16 = qualityQ16; + move32(); + ps->qualityred = qualityred; + move16(); + ps->qualityrise = qualityrise; + move16(); + ps->bad_frame_count = 0; + move16(); + ps->good_frame_count = 0; + move16(); + return 0; +} + +/* +******************************************************************************** +* +* Function : apa_set_complexity_options +* Tables : +* Compile Defines : +* Return : 0 on success, 1 on failure +* Information : Set complexity options +* Waveform subsampling computes the correlation function +* for certain positions only +* Correlation function subsampling computes the maxima +* for certain positions only +* +******************************************************************************** +*/ +Word8 apa_set_complexity_options (apa_state_t * ps, Word16 wss, Word16 css) +{ + /* make sure pointer is valid */ + assert( ps != NULL ); + assert( wss != 0 && wss <= 1000 ); + assert( css != 0 && css <= 1000 ); + + ps->wss = wss; + move16(); + ps->css = css; + move16(); + return 0; +} + +/* +******************************************************************************** +* +* Function : apa_exit +* Tables : +* Compile Defines : +* Return : 0 on success, 1 on failure +* Information : The memory used for storing the state is freed. +* The state struct pointer is set to NULL. +* +******************************************************************************** +*/ +Word8 apa_exit( apa_state_t ** pps ) +{ + /* ignore NULL pointer input */ + IF( *pps == (apa_state_t *) NULL ) + { + return 0; + } + + /* deallocate state struct */ + free (*pps); + /* set pointer to NULL */ + *pps = NULL; + move16(); + return 0; +} + +/* +******************************************************************************** +* +* Function : apa_exec +* Tables : +* Compile Defines : +* Return : 0 on success, 1 on failure +* Information : Execute adaptive playout for audio, i.e., audio scaling. +* Will take l_in input samples from a_in[] and +* try to extend/shrink the amount of samples according +* to the last scaling set by using apa_set_scale(). +* The actual amount of samples after scaling may vary +* and is given in l_out. The scaled audio samples +* are contained in a_out[]. Note that the scaling is +* achieved only in average. The input buffer must be +* filled with 20ms audio. The output buffer must be +* allocated externally and must be at least of size +* APA_BUF. +* Scaling can only be performed when a sampling rate +* is specified using apa_set_rate(). Otherwise, +* an error is returned. +* +* The amount of scaling is achieved by controlling the +* frequency of scaling. Note that the exact amount of +* scaling is signal dependent and is an integer +* multiple of a pitch. Hence, when we want to achieve +* a scaling of e.g. 110% then the APA module will typically +* forward several frames without any modification and +* then scale one frame by a higher amount, e.g. 143%. +* +******************************************************************************** +*/ +Word8 apa_exec (apa_state_t * ps, /* i/o: state struct */ + const Word16 a_in[], /* i: input samples */ + Word16 l_in, /* i: number of input samples */ + Word16 maxScaling, /* i: allowed number of inserted/removed samples */ + Word16 a_out[], /* o: output samples */ + Word16 *l_out /* o: number of output samples */) +{ + Word16 i; + Word16 frm_in[APA_BUF]; + Word16 l_frm_out; + Word16 l_rem; + Word32 dl_scaled, dl_copied, l_frm_out_target; + Word32 actScaling, expScaling; + Word16 *frm_in_ptr, *buf_out_ptr, *buf_out_ptr1, *buf_out_ptr2; + Word16 statsResetThreshold, statsResetShift; + + statsResetThreshold = 1637; + move16(); + statsResetShift = 2; + move16(); + + /* make sure no invalid output is used */ + *l_out = 0; + move16(); + l_frm_out = 0; + move16(); + + /* make sure pointer is valid */ + IF( ps == (apa_state_t *) NULL ) + { + return 1; + } + /* check available rate */ + IF( ps->rate == 0 ) + { + return 2; + } + /* check size of input */ + IF( NE_32( l_in, ps->l_frm )) + { + return 3; + } + + /* get target length */ + IF(s_or((Word16)EQ_16(ps->l_frm, 480),(Word16)EQ_16(ps->l_frm,960))) + { + /* decomposite ps->l_frm into 15<l_frm)); + /* this only works for 20ms framing */ + assert(ps->l_frm == shl(shr(ps->l_frm, i), i)); + assert(i_mult2(sub(ps->scale, 100), add(ps->nFramesSinceSetScale, 1)) == (ps->scale - 100) * (ps->nFramesSinceSetScale + 1)); + expScaling = L_shr_r(L_mult0(i_mult2(sub(ps->scale, 100), add(ps->nFramesSinceSetScale, 1)), 19661/*15*(1<<2)/100.0 Q15*/), sub(15+2, i)); + } + ELSE + { + /* decomposite ps->l_frm into 5<l_frm)); + /* this only works for 20ms framing */ + assert(ps->l_frm == shl(shr(ps->l_frm, i), i)); + assert(i_mult2(sub(ps->scale, 100), add(ps->nFramesSinceSetScale, 1)) == (ps->scale - 100) * (ps->nFramesSinceSetScale + 1)); + expScaling = L_shr_r(L_mult0(i_mult2(sub(ps->scale, 100), add(ps->nFramesSinceSetScale, 1)), 13107/*5*(1<<3)/100.0 Q15*/), sub(15+3, i)); + } + assert( expScaling >= (ps->l_frm * (ps->scale - 100.0f) / 100.0f) * (ps->nFramesSinceSetScale + 1LL) - 3); + assert( expScaling <= (ps->l_frm * (ps->scale - 100.0f) / 100.0f) * (ps->nFramesSinceSetScale + 1LL) + 3); + actScaling = L_sub(ps->diffSinceSetScale, L_deposit_l(ps->l_frm)); + assert( actScaling == ps->diffSinceSetScale - ps->l_frm ); + /* target number of samples for output frame */ + l_frm_out_target = L_sub(expScaling, actScaling); + assert( l_frm_out_target == expScaling - actScaling ); + + /* Wait until we have l_frm outputs samples */ + /* (required to search for correlation in the past). */ + /* If we don't have enough samples, simply copy input to output */ + IF( LT_16( ps->l_buf_out, ps->l_frm )) + { + FOR( i = 0; i < ps->l_frm; i++ ) + { + a_out[i] = a_in[i]; + move16(); + } + l_frm_out = ps->l_frm; + move16(); + } + ELSE + { + buf_out_ptr = &(ps->buf_out[ sub( ps->l_buf_out, ps->l_frm ) ]); + move16(); + frm_in_ptr = &(frm_in[ps->l_frm]); + move16(); + + /* fill input frame */ + /* 1st input frame: previous output samples */ + FOR( i = 0; i < ps->l_frm; i++ ) + { + frm_in[i] = buf_out_ptr[i]; + move16(); + } + /* 2nd input frame: new input samples */ + FOR( i = 0; i < ps->l_frm; i++ ) + { + frm_in_ptr[i] = a_in[i]; + move16(); + } + /* no scaling */ + IF( EQ_16( ps->scale, 100 )) + { + copy_frm (ps, frm_in, a_out, &l_frm_out); + } + /* shrink */ + ELSE IF( LT_16( ps->scale, 100 )) + { + shrink_frm (ps, frm_in, maxScaling, a_out, &l_frm_out); + } + /* extend */ + ELSE { + extend_frm (ps, frm_in, a_out, &l_frm_out); + } + /* control the amount/frequency of scaling */ + IF( NE_16( l_frm_out, ps->l_frm )) + { + test(); + IF( maxScaling != 0U && + GT_16( abs_s( sub( ps->l_frm, l_frm_out) ), maxScaling )) + { + /* maxScaling exceeded -> discard scaled frame */ + copy_frm (ps, frm_in, a_out, &l_frm_out); + } + ELSE IF( GT_32( L_abs( l_frm_out_target ), L_deposit_l(ps->l_frm) )) /* ignore small difference */ + { + dl_copied = L_sub( l_frm_out_target, L_deposit_l(ps->l_frm) ); + dl_scaled = L_sub( l_frm_out_target, L_deposit_l(l_frm_out) ); + /* discard scaled frame if copied frame is closer to target length */ + IF( LT_32( L_abs( dl_copied ), L_abs( dl_scaled ) )) + { + copy_frm (ps, frm_in, a_out, &l_frm_out); + } + } + } + } + + /* copy output to internal buffer */ + /* avoid buffer overflow: */ + /* discard old samples; always keep at least most recent l_frm samples */ + IF ( GT_16( add( ps->l_buf_out, l_frm_out), APA_BUF )) + { + buf_out_ptr1 = ps->buf_out; + move16(); + + l_rem = sub( ps->l_frm, l_frm_out ); + if( l_rem < 0 ) + { + l_rem = 0; + move16(); + } + buf_out_ptr2 = &(ps->buf_out[ sub( ps->l_buf_out, l_rem )]); + move16(); + + FOR( i = 0; i < l_rem; i++ ) + { + buf_out_ptr1[i] = buf_out_ptr2[i]; + move16(); + } + ps->l_buf_out = l_rem; + move16(); + } + /* append new output samples */ + IF( GT_16( add( ps->l_buf_out, l_frm_out), APA_BUF )) + { + return 5; + } + { + buf_out_ptr = &(ps->buf_out[ps->l_buf_out]); + FOR( i = 0; i < l_frm_out; i++) + { + buf_out_ptr[i] = a_out[i]; + move16(); + } + } + ps->l_buf_out = add( ps->l_buf_out, l_frm_out ); + + /* check variable l_frm_out is non-negative since l_out being returned is unsigned */ + assert( l_frm_out >= 0 ); + *l_out = l_frm_out; + move16(); + /* update statistics */ + ps->l_in_total = L_add( ps->l_in_total, L_deposit_l( ps->l_frm ) ); + test(); + IF( LT_32(L_abs(ps->diffSinceSetScale), + L_sub(0x7FFFFF, L_deposit_l(sub(l_frm_out, ps->l_frm)))) && + LT_16(ps->nFramesSinceSetScale, statsResetThreshold) ) + { + ps->diffSinceSetScale = L_add(ps->diffSinceSetScale, L_deposit_l(sub(l_frm_out, ps->l_frm))); + ps->nFramesSinceSetScale = add(ps->nFramesSinceSetScale, 1); + } + ELSE /* scale statistics down to avoid overflow */ + { + ps->diffSinceSetScale = L_shr(ps->diffSinceSetScale, statsResetShift); + ps->nFramesSinceSetScale = shr(ps->nFramesSinceSetScale, statsResetShift); + } + return 0; +} + + +/* +******************************************************************************** +* LOCAL PROGRAM CODE +******************************************************************************** +*/ + +static void get_scaling_quality(const apa_state_t * ps, + const Word16 * signal, + Word16 s_len, + Word16 offset, + Word16 corr_len, + Word16 pitch, + Word16 * energydBQ8, + Word32 * qualityQ16) +{ + Word32 energy, maxEnergy; + Word32 qualityOfMaxEnergy; /* we measure the quality for all channels and select the one with highest energy */ + Word16 half_pitch_cn; + Word16 pitch_cn; + Word16 three_halves_pitch_cn; + Word16 double_pitch_cn; + Word32 pitch_energy; + Word32 half_pitch_energy; + Word32 three_halves_pitch_energy; + Word32 double_pitch_energy; + Word16 i; + + + maxEnergy = L_deposit_l(0); + qualityOfMaxEnergy = L_deposit_l(0); + + FOR( i=0; i < ps->num_channels; i++ ) + { + offset = 0; + move16(); + + pitch_cn = normalized_cross_correlation_self(signal, add(pitch, offset), offset, corr_len, + shl(ps->num_channels, 1), &pitch_energy); + IF(pitch_cn > 0) + { + /* calculate correlation for double pitch */ + IF(LE_16(add(add(shl(pitch, 1), offset), corr_len), s_len)) + { + double_pitch_cn = normalized_cross_correlation_self(signal, add(shl(pitch, 1), offset), + offset, corr_len, shl(ps->num_channels, 1), &double_pitch_energy); + } + ELSE + { + double_pitch_cn = pitch_cn; + move16(); + double_pitch_energy = L_add(pitch_energy, 0); + } + /* calculate correlation for three/half pitch */ + IF(LE_16(add(add(shr(i_mult2(pitch, 3), 1), offset), corr_len), s_len)) + { + three_halves_pitch_cn = normalized_cross_correlation_self(signal, add(shr(i_mult2(pitch, 3), 1), + offset), offset, corr_len, shl(ps->num_channels, 1), &three_halves_pitch_energy); + } + ELSE + { + three_halves_pitch_cn = pitch_cn; + move16(); + three_halves_pitch_energy = L_add(pitch_energy, 0); + } + /* calculate correlation for half pitch */ + IF(LE_16(add(add(shr(pitch, 1), offset), corr_len), s_len)) + { + half_pitch_cn = normalized_cross_correlation_self(signal, add(shr(pitch, 1), offset), + offset, corr_len, shl(ps->num_channels, 1), &half_pitch_energy); + } + ELSE + { + half_pitch_cn = pitch_cn; + move16(); + half_pitch_energy = L_add(pitch_energy, 0); + } + + /* combine correlation results: Q15.16 */ + *qualityQ16 = L_shr(L_mac0(L_mult0(half_pitch_cn, three_halves_pitch_cn), + pitch_cn, double_pitch_cn), 14); + BASOP_SATURATE_WARNING_OFF + energy = L_add(L_add(L_add(pitch_energy, half_pitch_energy), three_halves_pitch_energy), double_pitch_energy); + BASOP_SATURATE_WARNING_ON + } + ELSE + { + *qualityQ16 = L_shl(L_deposit_l(pitch_cn), 1); /* value is negative, thus pass it */ + energy = L_add(pitch_energy, 0); + } + + /* update the quality by the quality of the signal with the highest energy */ + IF(GT_32(energy, maxEnergy)) + { + qualityOfMaxEnergy = L_add(*qualityQ16, 0); + maxEnergy = L_add(energy, 0); + } + + /* go to next channel */ + ++signal; + } + *qualityQ16 = qualityOfMaxEnergy; + move32(); + + /* increase calculated quality of signals with low energy */ + *energydBQ8 = apa_corrEnergy2dB(maxEnergy, shl(ps->signalScaleForCorrelation, 1), corr_len); + *qualityQ16 = L_add(*qualityQ16, L_shl(L_deposit_l(apa_getQualityIncreaseForLowEnergy(*energydBQ8)), 8)); +} + +/* Converts the correlation energy to dB. */ +Word16 apa_corrEnergy2dB(Word32 energy, Word16 energyExp, Word16 corr_len) +{ + + Word16 result, tmpScale; + + /* normalise before dividing */ + tmpScale = norm_l( energy ); + energy = L_shl( energy, tmpScale ); + energyExp = sub( energyExp, tmpScale ); + + /* divide energy by corr_len */ + result = BASOP_Util_Divide3216_Scale(energy, corr_len, &tmpScale); + energyExp = add(energyExp, tmpScale); + + result = BASOP_Util_lin2dB( L_deposit_l( result ), energyExp, 1 ); + return result; +} + +/* Increases the calculated quality of signals with low energy. */ +Word16 apa_getQualityIncreaseForLowEnergy(Word16 energydBQ8) +{ + Word16 qualIncreaseMinEnergy, qualIncreaseMaxEnergy, qualIncForLowEnergy; /* Q8 */ + + qualIncreaseMinEnergy = -65 * (1 << 8); + move16(); + qualIncreaseMaxEnergy = -40 * (1 << 8); + move16(); + qualIncForLowEnergy = 0; + move16(); + + /* increase calculated quality of signals with low energy */ + IF(LT_16(energydBQ8, qualIncreaseMaxEnergy)) + { + qualIncForLowEnergy = energydBQ8; + move16(); + if(LT_16(qualIncForLowEnergy, qualIncreaseMinEnergy)) + { + qualIncForLowEnergy = qualIncreaseMinEnergy; + move16(); + } + if(GT_16(qualIncForLowEnergy, qualIncreaseMaxEnergy)) + { + qualIncForLowEnergy = qualIncreaseMaxEnergy; + move16(); + } + /* -50: (-50 - -40) / (-65 - -40) * 20 + * = -10 / -25 * 20 + */ + qualIncForLowEnergy = divide1616(sub(qualIncForLowEnergy, qualIncreaseMaxEnergy), + sub(qualIncreaseMinEnergy, qualIncreaseMaxEnergy)); + /* apply factor 2 and scale back to Q8 */ + assert(qualIncForLowEnergy >= 0); + qualIncForLowEnergy = shr(qualIncForLowEnergy, 7-1); + assert(qualIncForLowEnergy >= 0 && qualIncForLowEnergy <= (2 << 8)); + } + return qualIncForLowEnergy; +} + +/* +******************************************************************************** +* +* Function : logarithmic_search +* Tables : +* Compile Defines : +* Return : 0 on success, 1 on failure +* Information : Search for best match of a template segment using +* hierarchical search method: +* Parameter css is used for sampling every css'd correlation +* value. The area around the best match so far is used for +* further correlation value with half css-value until css=1. +* Search area length is always half previous search length. +* Parameter wss is passed to the correlation computation +* If the search area passes the boundaries, the search +* window is reduced so that it's entirely inside the +* boundaries. +* +******************************************************************************** +*/ +static Word8 logarithmic_search(const apa_state_t * ps, + const Word16 * signal, + Word16 s_start, + Word16 inlen, + Word16 offset, + Word16 fixed_pos, + Word16 corr_len, + Word16 wss, + Word16 css, + Word16 * synchpos) +{ + Word16 i; + Word32 coeff; + Word32 coeff_max; + Word16 s_start_old, s_len_old; + + DO + { + coeff_max = 0x80000000; /* will always be overwritten with result of first correlation */ move32(); + + FOR(i = s_start; i < s_start+inlen; i += css) + { + test(); + IF( EQ_16(wss,1)&&EQ_16(ps->num_channels,1)) + { + coeff = cross_correlation_self(signal, add(i, offset), add(fixed_pos, offset), corr_len); + } + ELSE + { + coeff = cross_correlation_subsampled_self(signal, add(i, offset), add(fixed_pos, offset), + corr_len, i_mult2(wss, ps->num_channels)); + } + + /* update max corr */ + IF( LT_16(ps->scale, 100)) + { + /* shrinking: prefer greater synchpos for equal coeff */ + BASOP_SATURATE_WARNING_OFF + IF(GE_32(coeff, coeff_max)) + { + coeff_max = L_add(coeff, 0); + *synchpos = i; + move16(); + } + BASOP_SATURATE_WARNING_ON + } + ELSE + { + /* extending: prefer smaller synchpos for equal coeff */ + BASOP_SATURATE_WARNING_OFF + IF(GT_32(coeff, coeff_max)) + { + coeff_max = L_add(coeff, 0); + *synchpos = i; + move16(); + } + BASOP_SATURATE_WARNING_ON + } + } + /* backup old search range */ + s_start_old = s_start; + move16(); + s_len_old = inlen; + move16(); + + css = shr( css, 1 ); + inlen = shr( inlen, 1 ); + s_start_old = s_start; + move16(); + s_start = sub( *synchpos, shr( inlen, 1 ) ); + + if( LT_16(s_start,s_start_old)) + { + s_start = s_start_old; + move16(); + } + + IF( GT_16( add(s_start,inlen), add(s_start_old,s_len_old) )) + { + inlen = add( sub( s_start_old, s_start), s_len_old ); + } + } WHILE( GT_16( css, 2 )); + return 0; +} + +/* +******************************************************************************** +* +* Function : find_synch +* Tables : +* Compile Defines : +* Return : 0 on success, 1 on failure +* Information : Find the best match of an template segment within +* a search region by similarity measures. +* +******************************************************************************** +*/ +static Word16 find_synch (apa_state_t * ps, + const Word16 * in, + Word16 l_in, + Word16 s_start, + Word16 s_len, + Word16 fixed_pos, + Word16 corr_len, + Word16 offset, + Word16 * energydBQ8, + Word32 * qualityQ16, + Word16 * synch_pos) +{ + assert( (corr_len - 1 + s_start + s_len - 1 + offset) < l_in ); + assert( (corr_len - 1 + fixed_pos + offset) < l_in); + + /* pass last pitch to search function as prediction value */ + *synch_pos = ps->last_pitch; + move16(); + logarithmic_search(ps, + in, + s_start, + s_len, + offset, + fixed_pos, + corr_len, + ps->wss, + i_mult2(ps->css, ps->num_channels), + synch_pos); + /* assert synch_pos is cleanly divisible by number of channels */ + assert( *synch_pos % ps->num_channels == 0 ); + + *qualityQ16 = L_deposit_l(0); + get_scaling_quality(ps, in, l_in, offset, corr_len, + abs_s( sub(*synch_pos, fixed_pos) ), energydBQ8, qualityQ16); + ps->last_pitch = *synch_pos; + move16(); + return 0; +} + + +/* +******************************************************************************** +* +* Function : copy_frm +* Tables : +* Compile Defines : +* Return : 0 on success, 1 on failure +* Information : Copy an audio. +* +* The frame size is fixed to ps->l_frm. The input data +* is stored in frm_in[], where the first ps->l_frm samples +* shall include the previous output frame and the second +* ps->l_frm samples shall contain the current input frame. +* The output frame is stored in frm_out[] and contains +* l_frm_out = ps->l_frm. +* +* The first ps->l_frm input samples are not used by +* this function and are only provided for a consistent +* function call with shrink_frm() and extend_frm(). +* +******************************************************************************** +*/ +static Word16 copy_frm (apa_state_t * ps, + const Word16 frm_in[], Word16 frm_out[], Word16 * l_frm_out) +{ + Word16 i; + + /* only 2nd input frame is used */ + frm_in += ps->l_frm; + + /* copy frame */ + FOR( i = 0; i < ps->l_frm; i++ ) + { + frm_out[i] = frm_in[i]; + move16(); + } + + /* set output length */ + *l_frm_out = ps->l_frm; + move16(); + return 0; +} + +/* +******************************************************************************** +* +* Function : shrink_frm +* Tables : +* Compile Defines : +* Return : 0 on success, 1 on failure +* Information : Shrink the length of an audio frame using the WSOLA +* algorithm. +* +* The frame size is fixed to ps->l_frm. The input data +* is stored in frm_in[], where the first ps->l_frm samples +* shall include the previous output frame and the second +* ps->l_frm samples shall contain the current input frame. +* The output frame is stored in frm_out[] and contains +* l_frm_out samples. The amount of shrinking is signal +* dependent. +* +* The first ps->l_frm input samples are not used by +* this function and are only provided for a consistent +* function call with extend_frm(). +* +******************************************************************************** +*/ +static Word16 shrink_frm (apa_state_t * ps, + const Word16 frm_in[], Word16 maxScaling, Word16 frm_out[], Word16 * l_frm_out) +{ + Word16 findSynchResult; + Word16 xtract, l_rem, s_start, s_end, l_frm, l_seg; + Word16 i; + Word16 over; + Word16 energyQ8; + Word32 qualityQ16; + + findSynchResult = 0; + move16(); + l_frm = ps->l_frm; + move16(); + l_seg = ps->l_seg; + move16(); + + /* only 2nd input frame is used */ + frm_in += l_frm; + + /* set search range */ + s_start = ps->p_min; + move16(); + /* assumption made that number of channels limited to 2 for basop port */ + assert( ps->num_channels <= 2 ); + /* pre-basop conversion was: s_start = (s_start / nChans) * nChans; */ + IF( ps->num_channels == 2 ) + { + s_start = shl( shr( s_start, 1 ), 1 ); + } + s_end = add( s_start, ps->l_search ); + + if( GE_16( add( s_end, l_seg ), l_frm )) + { + s_end = sub( l_frm, l_seg ); + } + + /* calculate overlap position */ + IF( isSilence( frm_in, l_seg, 10 ) ) + { + /* maximum scaling */ + energyQ8 = -65 * (1 << 8); + move16(); + qualityQ16 = L_deposit_h(5); + + /* set to last valid element (i.e. element[len - 1] but note for stereo last element is last pair of samples) */ + xtract = sub( s_end, ps->num_channels ); + test(); + if( maxScaling != 0U && GT_16( s_end, add( maxScaling, 1 ) )) + { + xtract = maxScaling; + move16(); + } + } + ELSE + { + /* find synch */ + assert(sizeof(ps->frmInScaled)/sizeof(ps->frmInScaled[0]) >= (size_t)l_frm); + scaleSignal16( frm_in, ps->frmInScaled, l_frm, ps->signalScaleForCorrelation ); + findSynchResult = find_synch (ps, ps->frmInScaled, l_frm, + s_start, sub(s_end, s_start), 0, l_seg, 0, &energyQ8, &qualityQ16, &xtract); + } + /* assert synch_pos is cleanly divisible by number of channels */ + assert( xtract % ps->num_channels == 0 ); + + /* set frame overlappable - reset if necessary */ + over = 1; + move16(); + + /* test whether frame has sufficient quality */ + /* 6554=0.1 in Q15.16; 13107=0.2 in Q15.16 */ + IF(LT_32(qualityQ16, L_add(L_sub(ps->targetQualityQ16, + L_mult0(ps->bad_frame_count, 6554)), + L_mult0(ps->good_frame_count, 13107)))) + { + /* not sufficient */ + over = 0; + move16(); + + if( LT_16( ps->bad_frame_count, ps->qualityred )) + { + ps->bad_frame_count = add( ps->bad_frame_count, 1 ); + } + if( ps->good_frame_count > 0 ) + { + ps->good_frame_count = sub( ps->good_frame_count, 1 ); + } + } + ELSE + { + /* sufficient quality */ + if( ps->bad_frame_count > 0 ) + { + ps->bad_frame_count = sub( ps->bad_frame_count, 1 ); + } + if( LT_16( ps->good_frame_count, ps->qualityrise )) + { + ps->good_frame_count = add( ps->good_frame_count, 1 ); + } + } + + /* Calculate output data */ test(); + IF( over != 0 && xtract != 0 ) + { + IF( EQ_16( findSynchResult, 1)) + { + return 1; + } + overlapAdd(frm_in, frm_in + xtract, frm_out, l_seg, ps->num_channels, + ps->win + ps->l_halfwin, ps->win, ps->win_incrementor ); + } + ELSE + { + xtract = 0; + move16(); + FOR( i = 0; i < l_seg; i++ ) + { + frm_out[i] = frm_in[i]; + move16(); + } + } + + /* append remaining samples */ + l_rem = sub( sub( l_frm, xtract ), l_seg ); + FOR( i = 0; i < l_rem; i++ ) + { + frm_out[l_seg + i] = frm_in[l_frm - l_rem + i]; + move16(); + } + + /* set output length */ + *l_frm_out = add( l_seg, l_rem ); + return 0; +} + +/* +******************************************************************************** +* +* Function : extend_frm +* Tables : +* Compile Defines : +* Return : 0 on success, 1 on failure +* Information : Extend the length of an audio frame using the WSOLA +* algorithm. +* +* The frame size is fixed to ps->l_frm. The input data +* is stored in frm_in[], where the first ps->l_frm samples +* shall include the previous output frame and the second +* ps->l_frm samples shall contain the current input frame. +* The output frame is stored in frm_out[] and contains +* l_frm_out samples. The amount of extension is signal +* dependent. +* +******************************************************************************** +*/ +static Word16 extend_frm (apa_state_t * ps, + const Word16 frm_in[], Word16 frm_out[], Word16 * l_frm_out) +{ + Word16 findSynchResult; + Word16 l_frm_out_target; + Word16 N, n, i; + Word16 s[MAXN + 2], s_max, s_min; + Word16 xtract[MAXN + 2], sync_start, s_end; + Word16 over[MAXN + 2]; + Word16 l_frm, l_seg; + Word16 s_start, l_rem; + Word16 sn_plus_search, sync_start_sub_pmin; + Word16 divScaleFac; + Word16 energyQ8; + Word32 qualityQ16; + const Word16 *fadeOut, *fadeIn; + Word16 *frmInScaled, *out; + + findSynchResult = 0; + move16(); + s_start = 0; + move16(); + qualityQ16 = L_deposit_l(0); + l_frm = ps->l_frm; + move16(); + l_seg = ps->l_seg; + move16(); + frmInScaled = NULL; + move16(); + + /* number of segments/iterations */ + /* equivalent to l_frm_out_target = l_frm * 1.5; */ + l_frm_out_target = add( l_frm, shr( l_frm, 1 ) ); + /* equivalent to (l_frm_out_target / l_seg) - 1 */ + N = BASOP_Util_Divide3216_Scale( l_frm_out_target, l_seg, &divScaleFac ); + N = sub( shl( N, add(divScaleFac,1) ), 1 ); + + assert( (l_frm_out_target / l_seg) - 1 == N ); + + if( LT_16(N, 1)) + { + N = 1; + move16(); + } + + assert( N <= MAXN ); + + /* calculate equally spaced search regions */ + /* s[n] are given relative to 2nd frame and point to the start of */ + /* the search region. The first segment (n=1) will not be moved. */ + /* Hence, the iterations will start with n=2. */ + s_min = sub( negate(ps->l_search), ps->p_min ); + /* (make sure not to exceed array dimension) */ + if( add( l_frm, s_min ) < 0) + { + s_min = negate( l_frm ); + } + s_max = sub( sub( l_frm, shl( l_seg, 1 ) ), ps->l_search ); + if( LT_16( s_max, s_min )) + { + N = 1; + move16(); + } + /* for just one segment start at s_min */ + s[2] = s_min; + move16(); + /* else, spread linear in between s_min and s_max */ + /* (including s_min and s_max) */ + IF( NE_16( N, 1 )) + { + FOR( n = 2; n <= (N + 1); n++ ) + { + s[n] = BASOP_Util_Divide3216_Scale( L_mult0( sub( s_max, s_min ), sub(n,2) ), sub(N,1), &divScaleFac ); + s[n] = add( shl( s[n], add(divScaleFac,1) ), s_min ); + move16(); + } + } + + /* + * Planning Phase + */ + + xtract[1] = negate(l_seg); /* make sync_start=0 in 1st iteration */ move16(); + n = 2; + move16(); + { + /* define synch segment (to be correlated with search region) */ + sync_start = add( xtract[sub(n,1)], l_seg ); + over[n] = 1; /* will be reset if overlap is not required */ move16(); + + /* added basop port - stored results for repeated calculations */ + sn_plus_search = add( s[n], ps->l_search ); + sync_start_sub_pmin = sub( sync_start, ps->p_min ); + + /* check end of search region: should be at least p_min */ + /* samples on the left of synch_start */ + /* removed basop (overwritten instead): if( sub( sn_plus_search, sub( sync_start, ps->p_min) ) < 0 */ + s_start = s[n]; + move16(); + s_end = add( s_start, ps->l_search ); + + IF( GE_16( sn_plus_search, sync_start_sub_pmin )) + { + /* shrink search region to enforce minimum shift */ + s_end = sync_start_sub_pmin; + move16(); + + IF( LT_16( sn_plus_search, sync_start )) + { + s_start = s[n]; /* just do it with normal start position */ move16(); + } + ELSE IF( EQ_16( n, add(N,1) )) /* move search region left for last segment */ + { + s_start = sub( s_end, sub( ps->l_search, ps->p_min ) ); + } + ELSE + { + over[n] = 0; /* don't search/overlap (just copy down) */ move16(); + } + } + + IF( over[n] != 0 ) + { + /* calculate overlap position */ + IF( isSilence( frm_in, l_seg, 10 ) ) + { + /* maximum scaling */ + energyQ8 = -65 * (1 << 8); + move16(); + qualityQ16 = L_deposit_h(5); + xtract[n] = add( s_start, ps->num_channels ); + move16(); + } + ELSE + { + /* find synch */ + IF( frmInScaled == NULL ) + { + frmInScaled = ps->frmInScaled; + move16(); + assert(sizeof(ps->frmInScaled)/sizeof(ps->frmInScaled[0]) >= 2 * (size_t)l_frm); + scaleSignal16( frm_in, frmInScaled, shl( l_frm, 1 ), ps->signalScaleForCorrelation ); + } + findSynchResult = find_synch( ps, frmInScaled, shl( l_frm, 1 ), + s_start, sub( s_end, s_start ), sync_start, + l_seg, l_frm, &energyQ8, &qualityQ16, &xtract[n] ); + } + /* assert synch_pos is cleanly divisible by number of channels */ + assert( xtract[n] % ps->num_channels == 0 ); + + /* test for sufficient quality */ + /* 6554=0.1 in Q15.16; 13107=0.2 in Q15.16 */ + IF(LT_32(qualityQ16, L_add(L_sub(ps->targetQualityQ16, + L_mult0(ps->bad_frame_count, 6554)), + L_mult0(ps->good_frame_count, 13107)))) + { + /* not sufficient */ + over[n] = 0; + move16(); + xtract[n] = sync_start; + move16(); + + if( LT_16( ps->bad_frame_count, ps->qualityred )) + { + ps->bad_frame_count = add( ps->bad_frame_count, 1 ); + } + if( ps->good_frame_count > 0 ) + { + ps->good_frame_count = sub( ps->good_frame_count, 1 ); + } + } + ELSE + { + /* sufficient quality */ + if( ps->bad_frame_count > 0 ) + { + ps->bad_frame_count = sub( ps->bad_frame_count, 1 ); + } + if(LT_16(ps->good_frame_count, ps->qualityrise)) + { + ps->good_frame_count = add( ps->good_frame_count, 1 ); + } + } + + IF( findSynchResult > 0 ) + { + return 1; + } + } + ELSE + { + xtract[n] = sync_start; + move16(); + } + + } + + /* Calculate output data */ + FOR( n = 2; n <= N; n++ ) + { + test(); + IF( over[n] != 0 && NE_16( add( xtract[sub(n,1)], l_seg ), xtract[n] )) + { + /* mix 2nd half of previous segment with 1st half of current segment */ + fadeOut = frm_in + l_frm + xtract[n - 1] + l_seg; + fadeIn = frm_in + l_frm + xtract[n]; + out = frm_out + i_mult2(sub(n, 2), l_seg); + overlapAdd(fadeOut, fadeIn, out, l_seg, ps->num_channels, + ps->win + ps->l_halfwin, ps->win, ps->win_incrementor ); + } + ELSE + { + /* just copy down 1st half of current segment (= 2nd half of previous segment) */ + Word16 *frm_out_ptr = &(frm_out[ i_mult2( sub(n,2), l_seg ) ]); + const Word16 *frm_in_ptr = &(frm_in[ add( l_frm, xtract[n] ) ]); + FOR(i = 0; i < l_seg; i++) + { + frm_out_ptr[i] = frm_in_ptr[i]; + move16(); + } + } + } + + /* append remaining samples */ + l_rem = sub( l_frm, add( xtract[N], l_seg ) ); + FOR( i = 0; i < l_rem; i++ ) + { + frm_out[ add( i_mult2( sub(N,1), l_seg), i ) ] = + frm_in[ add( sub( shl( l_frm,1 ), l_rem ), i ) ]; + move16(); + } + + /* set output length */ + *l_frm_out = add( i_mult2( sub(N,1), l_seg ), l_rem ); + return 0; +} + diff --git a/lib_dec/jbm_pcmdsp_apa.h b/lib_dec/jbm_pcmdsp_apa.h new file mode 100644 index 0000000..73bb720 --- /dev/null +++ b/lib_dec/jbm_pcmdsp_apa.h @@ -0,0 +1,93 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*! @file pcmdsp_apa.h Adaptive Playout for Audio (apa). */ + +#ifndef PCMDSP_APA_H +#define PCMDSP_APA_H PCMDSP_APA_H + +/* instrumentation */ +#include "typedef.h" + +/* +******************************************************************************** +* DEFINITION OF CONSTANTS +******************************************************************************** +*/ + +/* size of IO buffers (a_in[], a_out[]) for apa_exec() */ +#define APA_BUF (48000/50*3) + +/* min/max scaling [%] */ +#define APA_MIN_SCALE 50 +#define APA_MAX_SCALE 150 + + +/* +******************************************************************************** +* DEFINITION OF DATA TYPES +******************************************************************************** +*/ + +struct apa_state_t; +typedef struct apa_state_t apa_state_t; +/*! handle for APA */ +typedef struct apa_state_t* PCMDSP_APA_HANDLE; + + +/* +******************************************************************************** +* DECLARATION OF PROTOTYPES +******************************************************************************** +*/ + +/*! Allocates memory for state struct and initializes elements. + * @return 0 on success, 1 on failure */ +Word8 apa_init(apa_state_t **s); + +/*! Sets state variables to initial value. */ +void apa_reset(apa_state_t *s); + +/*! Sets the audio configuration. + * Must be called once before processing can start. + * If called again during processing it will reset the state struct! + * Will also set a number of other state variables that depend on the sampling rate. + * @param[in,out] ps state + * @param[in] rate sample rate [Hz] + * @param[in] num_channels number of channels + * @return 0 on success, 1 on failure */ +Word8 apa_set_rate( + apa_state_t *ps, + Word32 rate, + Word16 num_channels); + +/*! Set scaling. + * The scale is given in % and will be valid until changed again. + * Must be in range [APA_MIN_SCALE,APA_MAX_SCALE]. + * @return 0 on success, 1 on failure */ +Word8 apa_set_scale(apa_state_t *s, Word16 scale); + +Word8 apa_set_quality( + apa_state_t *s, + Word32 qualityQ16, + Word16 qualityred, + Word16 qualityrise); + +Word8 apa_set_complexity_options( + apa_state_t *s, + Word16 wss, + Word16 css); + +Word8 apa_exit( + apa_state_t **s); + +Word8 apa_exec( + apa_state_t *s, + const Word16 a_in[], + Word16 l_in, + Word16 maxScaling, + Word16 a_out[], + Word16 *l_out); + +#endif /* PCMDSP_APA_H */ diff --git a/lib_dec/jbm_pcmdsp_fifo.c b/lib_dec/jbm_pcmdsp_fifo.c new file mode 100644 index 0000000..e90b5a5 --- /dev/null +++ b/lib_dec/jbm_pcmdsp_fifo.c @@ -0,0 +1,213 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*! @file pcmdsp_fifo.c Ringbuffer (FIFO) with fixed capacity for audio samples */ + +/* system headers */ +#include +/* instrumentation headers */ +#include "options.h" +#include "stl.h" +#include "basop_util.h" +/* local headers */ +#include "jbm_pcmdsp_fifo.h" + + +/** Ringbuffer (FIFO) with fixed capacity for audio samples. */ +struct PCMDSP_FIFO +{ + /** number of currently stored samples per channel */ + Word16 size; + /** maximum allowed number of samples per channel */ + Word16 capacity; + /** sample size in bytes per channel */ + Word16 nBytesPerSampleSet; + + /** begin of the FIFO data (pointer to bytes) */ + UWord8 *dataBegin; + /** end of the FIFO data (pointer to bytes) */ + UWord8 *dataEnd; + /** position of next write operation (pointer to bytes) */ + UWord8 *dataWriteIterator; + /** position of next read operation (pointer to bytes) */ + UWord8 *dataReadIterator; +}; + + +/* Creates a FIFO. */ +Word16 pcmdsp_fifo_create( PCMDSP_FIFO_HANDLE *ph ) +{ + PCMDSP_FIFO_HANDLE h = malloc( sizeof( struct PCMDSP_FIFO ) ); + + h->size = 0; + move16(); + h->capacity = 0; + move16(); + h->nBytesPerSampleSet = 0; + move16(); + h->dataBegin = NULL; + move16(); + h->dataEnd = NULL; + move16(); + h->dataWriteIterator = NULL; + move16(); + h->dataReadIterator = NULL; + move16(); + + *ph = h; + move16(); + return 0; +} + +/* Destroys the FIFO. */ +void pcmdsp_fifo_destroy( PCMDSP_FIFO_HANDLE *ph ) +{ + PCMDSP_FIFO_HANDLE h; + + IF( !ph ) + { + return; + } + h = *ph; + move16(); + IF( !h ) + { + return; + } + + IF( h->dataBegin ) + { + free( h->dataBegin ); + } + free( h ); + *ph = NULL; + move16(); +} + +/* Initializes the FIFO with a fixed maximum allowed number audio samples. */ +Word16 pcmdsp_fifo_init( PCMDSP_FIFO_HANDLE h, Word16 nSamples, + Word16 nChannels, Word16 nBytesPerSample ) +{ + Word32 nDataBytes; + + h->capacity = nSamples; + move16(); + h->nBytesPerSampleSet = i_mult2( nChannels, nBytesPerSample ); + nDataBytes = L_mult0( nSamples, h->nBytesPerSampleSet); + h->dataBegin = malloc(nDataBytes); + h->dataEnd = h->dataBegin + nDataBytes; + move16(); + h->dataWriteIterator = h->dataBegin; + move16(); + h->dataReadIterator = h->dataBegin; + move16(); + return 0; +} + +/* Writes the given audio data to the FIFO. */ +Word16 pcmdsp_fifo_write( PCMDSP_FIFO_HANDLE h, const UWord8 *samples, Word16 nSamplesPerChannel ) +{ + Word32 nBytesToWrite, writeIter, bytesOfFirstPart, secondSize; + + /* check for empty input buffer */ + IF( nSamplesPerChannel == 0 ) + { + return 0; + } + /* check, if enough space left */ + IF( GT_16( nSamplesPerChannel, sub( h->capacity, h->size ) )) + { + return -1; + } + + nBytesToWrite = L_mult0( nSamplesPerChannel, h->nBytesPerSampleSet ); + + IF( h->dataWriteIterator + nBytesToWrite - h->dataEnd > 0 ) + { + /* wrap around: writing two parts */ + bytesOfFirstPart = h->dataEnd - h->dataWriteIterator; + secondSize = L_sub( nBytesToWrite, bytesOfFirstPart ); + + FOR( writeIter = 0; writeIter < bytesOfFirstPart; ++writeIter ) + { + *h->dataWriteIterator++ = *(samples + writeIter); + move16(); + } + h->dataWriteIterator = h->dataBegin; + move16(); + FOR( writeIter = 0; writeIter < secondSize; ++writeIter ) + { + *h->dataWriteIterator++ = *(samples + bytesOfFirstPart + writeIter ); + move16(); + } + } + ELSE + { + /* no wrap around: simple write */ + FOR( writeIter = 0; writeIter < nBytesToWrite; ++writeIter ) + { + *h->dataWriteIterator++ = *(samples + writeIter); + move16(); + } + } + h->size = add( h->size, nSamplesPerChannel ); + return 0; +} + +/* Reads the given number of audio samples from the FIFO. */ +Word16 pcmdsp_fifo_read( PCMDSP_FIFO_HANDLE h, Word16 nSamplesPerChannel, UWord8 *samples ) +{ + Word32 nBytesToRead, readIter, nBytesOfSecondPart, bytesOfFirstPart; + + /* check for empty output buffer */ + IF( nSamplesPerChannel == 0 ) + { + return 0; + } + /* check, if enough bytes readable */ + IF( GT_32( nSamplesPerChannel, h->size )) + { + return -1; + } + + nBytesToRead = L_mult0( nSamplesPerChannel, h->nBytesPerSampleSet ); + + IF( h->dataReadIterator + nBytesToRead - h->dataEnd > 0 ) + { + /* wrap around: reading two parts */ + bytesOfFirstPart = h->dataEnd - h->dataReadIterator; + nBytesOfSecondPart = L_sub( nBytesToRead, bytesOfFirstPart ); + + FOR( readIter = 0; readIter < bytesOfFirstPart; ++readIter ) + { + *(samples + readIter) = *h->dataReadIterator++; + move16(); + } + h->dataReadIterator = h->dataBegin; + move16(); + FOR( readIter = 0; readIter < nBytesOfSecondPart; ++readIter ) + { + *(samples + bytesOfFirstPart + readIter) = *h->dataReadIterator++; + move16(); + } + } + ELSE + { + /* no wrap around: simple read */ + FOR( readIter = 0; readIter < nBytesToRead; ++readIter ) + { + *(samples + readIter) = *h->dataReadIterator++; + move16(); + } + } + h->size = sub( h->size, nSamplesPerChannel ); + return 0; +} + +/* Returns the number of samples per channel that can be read (number of currently stored samples). */ +Word16 pcmdsp_fifo_nReadableSamples( const PCMDSP_FIFO_HANDLE h ) +{ + return h->size; +} + diff --git a/lib_dec/jbm_pcmdsp_fifo.h b/lib_dec/jbm_pcmdsp_fifo.h new file mode 100644 index 0000000..5fe4f32 --- /dev/null +++ b/lib_dec/jbm_pcmdsp_fifo.h @@ -0,0 +1,44 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*! @file pcmdsp_fifo.h Ringbuffer (FIFO) with fixed capacity for audio samples. */ + +#ifndef PCMDSP_FIFO_H +#define PCMDSP_FIFO_H PCMDSP_FIFO_H + +/* instrumentation headers */ +#include "typedef.h" +/** handle for FIFO with fixed capacity */ +typedef struct PCMDSP_FIFO *PCMDSP_FIFO_HANDLE; + +/** Creates a FIFO. + * @param[out] ph pointer to created handle + * @return 0 if succeeded */ +Word16 pcmdsp_fifo_create( PCMDSP_FIFO_HANDLE *ph ); +/** Destroys the FIFO. */ +void pcmdsp_fifo_destroy( PCMDSP_FIFO_HANDLE *ph ); +/** Initializes the FIFO with a fixed maximum allowed number of audio samples. + * @param[in] nSamples maximum allowed number of samples per channel (capacity) + * @note Word16 gives max capacity of 34 frames @ 48000 Hz + * @param[in] nChannels number of audio channels + * @param[in] nBytesPerSample size in bytes per sample per channel + * @return 0 if succeeded */ +Word16 pcmdsp_fifo_init( PCMDSP_FIFO_HANDLE h, Word16 nSamples, + Word16 nChannels, Word16 nBytesPerSample ); + +/** Writes the given audio data to the FIFO. + * @param[in] samples pointer to audio samples to append + * @param[in] nSamplesPerChannel the number of samples per channel to append + * @return 0 if succeeded */ +Word16 pcmdsp_fifo_write( PCMDSP_FIFO_HANDLE h, const UWord8 *samples, Word16 nSamplesPerChannel ); +/** Reads the given number of audio samples from the FIFO. + * @param[in] nSamplesPerChannel the number of samples per channel to read from the FIFO + * @param[in] samples pointer where the audio samples will be copied to + * @return 0 if succeeded */ +Word16 pcmdsp_fifo_read( PCMDSP_FIFO_HANDLE h, Word16 nSamplesPerChannel, UWord8 *samples ); + +/** Returns the number of samples per channel that can be read (number of currently stored samples). */ +Word16 pcmdsp_fifo_nReadableSamples( const PCMDSP_FIFO_HANDLE h ); + +#endif /* PCMDSP_FIFO_H */ diff --git a/lib_dec/jbm_pcmdsp_similarityestimation.c b/lib_dec/jbm_pcmdsp_similarityestimation.c new file mode 100644 index 0000000..13945ca --- /dev/null +++ b/lib_dec/jbm_pcmdsp_similarityestimation.c @@ -0,0 +1,202 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*! @file pcmdsp_similarityestimation.c Algorithms for correlation and similarity estimation. */ + +/* system headers */ +#include +#include +/* flc header */ +#include "stl.h" +#include "basop_util.h" +/* local headers */ +#include "jbm_pcmdsp_similarityestimation.h" +#include "options.h" + +/* Returns the number of right shifts to be applied to the signal before correlation functions. */ +Word16 getSignalScaleForCorrelation(Word32 sampleRate) +{ + Word16 ret; + + IF( LT_32(sampleRate, 16000)) + { + ret = 2; + move16(); + } + ELSE IF( GE_32(sampleRate, 32000)) + { + ret = 4; + move16(); + } + ELSE + { + ret = 3; + move16(); + } + + return ret; +} + +/* Copies the right shifted signal to another buffer. */ +void scaleSignal16(const Word16 *src, Word16 *dst, Word16 n, Word16 rightShift) +{ + Word16 i; + + FOR(i = 0; i < n; i++) + { + dst[i] = shr_r(src[i], rightShift); + move16(); + } + +} + + +/* Calculates cross correlation coefficient for template segment. */ +Word32 cross_correlation_self(const Word16 * signal, + Word16 x, Word16 y, Word16 corr_len) +{ + Word32 sum; + Word16 i; + + sum = L_deposit_l(0); + FOR(i = 0; i < corr_len; i++) + { + sum = L_mac0(sum, signal[x + i], signal[y + i]); + } + + return sum; +} + +/* Calculates cross correlation coefficient for template segment. */ +Word32 cross_correlation_subsampled_self(const Word16 * signal, + Word16 x, Word16 y, Word16 corr_len, Word16 subsampling) +{ + Word32 sum; + Word16 i; + + sum = L_deposit_l(0); + FOR(i = 0; i < corr_len; i += subsampling) + { + sum = L_mac0(sum, signal[x + i], signal[y + i]); + } + + return sum; +} + +/* Calculates normalized cross correlation coefficient for template segment. */ +Word16 normalized_cross_correlation_self(const Word16 * signal, + Word16 x, Word16 y, Word16 corr_len, + Word16 subsampling, Word32 * energy) +{ + const Word16 *signalX, *signalY; + Word32 sumXY, sumXX, sumYY, product; + Word16 sqrtXY, cc; + Word16 i, normX, normY, normXY, normCC; + + signalX = &signal[x]; + signalY = &signal[y]; + sumXY = L_deposit_l(0); + sumXX = L_deposit_l(0); + sumYY = L_deposit_l(0); + + FOR(i = 0; i < corr_len; i += subsampling) + { + sumXY = L_mac0(sumXY, signalX[i], signalY[i]); + sumXX = L_mac0(sumXX, signalX[i], signalX[i]); + sumYY = L_mac0(sumYY, signalY[i], signalY[i]); + } + + normX = norm_l(sumXX); + sumXX = L_shl(sumXX, normX); + normY = norm_l(sumYY); + sumYY = L_shl(sumYY, normY); + product = L_mult0(extract_h(sumXX), extract_h(sumYY)); + normXY = add(normX, normY); + normXY = sub(normXY, 32); + + /* change norm to factor of 2 */ + IF( s_and(normXY, 0x1) != 0 ) + { + product = L_shr(product, 1); + normXY = sub(normXY, 1); + } + sqrtXY = getSqrtWord32(product); + normXY = shr(normXY, 1); + + IF(sqrtXY != 0) + { + normCC = 0; + move16(); + cc = BASOP_Util_Divide3216_Scale(sumXY, sqrtXY, &normCC); + normCC = add(normCC, 16); + /* scale to Q15 with saturation */ + BASOP_SATURATE_WARNING_OFF + cc = shl_r(cc, add(normXY, normCC)); + BASOP_SATURATE_WARNING_ON + *energy = L_shr_r(L_deposit_l(sqrtXY), normXY); + } + ELSE /* conceal silent frames */ + { + cc = 0; + move16(); + *energy = L_deposit_l(1); + } + + return cc; /* Q15 */ +} + +/* Splits the signal into segments and checks if all of them have very low energy. */ +Word8 isSilence(const Word16 * signal, Word16 len, Word16 segments) +{ + Word16 i, j, samplesPerSegment; + Word32 energy, maxEnergy; + Word8 ret; + + assert(len > 0); + assert(segments > 0); + + /* Every segment is checked using the following formula: + * 10 * log10(sum_i(signal[i]*signal[i]))) > -65 + * For simplification/complexity, this is replaced by: + * 20 * log10(sum_i(abs(signal[i]))) > -65 + */ + + ret = 1; + move16(); + energy = L_deposit_l(0); + samplesPerSegment = idiv1616U(len, segments); + /* calculate maxEnergy with factor 2 to reduce rounding error */ + maxEnergy = L_mult0(samplesPerSegment, 37); /* 37 = 2 * exp10(-65.0 / 20) * 32768 */ + maxEnergy = L_shr(maxEnergy, 1); + j = samplesPerSegment; + move16(); + /* check all but last segment */ + FOR(i = 0; i < len; i++) + { + /* division by 32768 is done later */ + energy = L_add(energy, L_abs(L_deposit_l(signal[i]))); + IF( EQ_16(i, j)) + { + /* check energy of current segment */ + /* 20 * log10(energy / 32768 / samplesPerSegment) > -65 + * => energy > samplesPerSegment * 10 ^ (-65 / 20) * 32768 */ + IF( GT_32(energy, maxEnergy)) + { + ret = 0; + move16(); + BREAK; + } + energy = L_deposit_l(0); + j = add(j, samplesPerSegment); + } + } + /* check last segment */ + if( GT_32(energy, maxEnergy)) + { + ret = 0; + move16(); + } + return ret; +} + diff --git a/lib_dec/jbm_pcmdsp_similarityestimation.h b/lib_dec/jbm_pcmdsp_similarityestimation.h new file mode 100644 index 0000000..63b81a7 --- /dev/null +++ b/lib_dec/jbm_pcmdsp_similarityestimation.h @@ -0,0 +1,114 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*! @file pcmdsp_similarityestimation.h Algorithms for correlation and similarity estimation. */ + +#ifndef PCMDSP_SIMILARITYESTIMATION_H +#define PCMDSP_SIMILARITYESTIMATION_H PCMDSP_SIMILARITYESTIMATION_H + +/* local headers */ +#include "stl.h" + +/*! Returns the number of right shifts to be applied to the signal before correlation functions. */ +Word16 getSignalScaleForCorrelation(Word32 sampleRate); + +/*! Copies the right shifted signal to another buffer. */ +void scaleSignal16(const Word16 *src, Word16 *dst, Word16 n, Word16 rightShift); + +/* +******************************************************************************** +* +* Function : cross_correlation_self +* Tables : +* Compile Defines : +* Return : (float) cross correlation coefficient +* Information : Calculate cross correlation coefficient for template +* segment. +* The returned value is signal-energy dependant. +* +* Used formula: +* +* corr_len-1 +* ---- +* \ +* / (j+x)*(j+y) +* ---- +* j=0 +* +******************************************************************************** +*/ +Word32 cross_correlation_self(const Word16 * signal, + Word16 x, + Word16 y, + Word16 corr_len); + +/* +******************************************************************************** +* +* Function : cross_correlation_subsampled_self +* Tables : +* Compile Defines : +* Return : (float) cross correlation coefficient +* Information : Calculate cross correlation coefficient for template +* segment. +* The returned value is signal-energy dependant. +* +* Used formula: +* +* corr_len-1 +* ---- +* \ +* / (j+x)*(j+y) +* ---- +* j=0 +* +******************************************************************************** +*/ +Word32 cross_correlation_subsampled_self(const Word16 * signal, + Word16 x, + Word16 y, + Word16 corr_len, + Word16 subsampling); + +/* +******************************************************************************** +* +* Function : normalized_cross_correlation_self +* Tables : +* Compile Defines : +* Return : (float) normalized cross correlation coefficient +* Information : Calculate normalized cross correlation coefficient +* for template segment. +* The returned value is signal-energy independant. +* This means, no matter how loud your signal is, equal +* signals will return 1.0, cross-phased signals -1.0. +* +* This function fills parameter energy with the common +* energy of signal x and signal y. This might be useful +* for silence detection. +* +* Used formula: +* +* corr_len-1 +* ---- +* \ (j+x)*(j+y) +* \ __________________ +* / -------------- +* / -/ (j+x)���+(j+y)��� +* ---- +* j=0 +* +******************************************************************************** +*/ +Word16 normalized_cross_correlation_self(const Word16 * signal, + Word16 x, + Word16 y, + Word16 corr_len, + Word16 subsampling, + Word32 * energy); + +/* Splits the signal into segments and checks if all of them have very low energy. */ +Word8 isSilence(const Word16 * signal, Word16 len, Word16 segments); + +#endif /* PCMDSP_SIMILARITYESTIMATION_H */ diff --git a/lib_dec/jbm_pcmdsp_window.c b/lib_dec/jbm_pcmdsp_window.c new file mode 100644 index 0000000..cc7ec0e --- /dev/null +++ b/lib_dec/jbm_pcmdsp_window.c @@ -0,0 +1,41 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*! @file pcmdsp_window.c Window functions. */ + +/* instrumentation headers */ +/* local headers */ +#include "jbm_pcmdsp_window.h" +#include "options.h" +#include "stl.h" + + +/* Overlap/Add of two signal with a given window. */ +void overlapAdd(const Word16 *fadeOut, const Word16 *fadeIn, Word16 *out, + Word16 n, Word16 nChannels, const Word16 *fadeOutWin, const Word16 *fadeInWin, Word16 hannIncrementor ) +{ + Word32 fdOutVal, fdInVal; + Word16 i, j, hannIter, combinedVal; + + + FOR(j = 0; j < nChannels; j++) + { + /* reset Hann window iterator to beginning (both channels use same window) */ + hannIter = 0; + move16(); + FOR( i = j; i < n; i += nChannels ) + { + fdOutVal = L_mult( fadeOut[i], fadeOutWin[hannIter] ); + fdInVal = L_mult( fadeIn[i], fadeInWin[hannIter] ); + /* round to 16bit value and saturate (L_add already applies saturation) */ + combinedVal = round_fx( L_add( fdOutVal, fdInVal ) ); + + out[i] = combinedVal; + move16(); + /* advance the Hann window iterator by incrementor (dependent on sample rate). */ + hannIter = add( hannIter, hannIncrementor ); + } + } +} + diff --git a/lib_dec/jbm_pcmdsp_window.h b/lib_dec/jbm_pcmdsp_window.h new file mode 100644 index 0000000..ef2e4ad --- /dev/null +++ b/lib_dec/jbm_pcmdsp_window.h @@ -0,0 +1,36 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +/*! @file pcmdsp_window.h Window functions. */ + +#ifndef PCMDSP_WINDOW_H +#define PCMDSP_WINDOW_H PCMDSP_WINDOW_H + +/* instrumentation headers */ +#include "basop_util.h" + +/*! Tables contain a Hann window (cos-shaped) of length 960 or 640. + * Roughly: + * + * 1 __ + * / \ + * 0 _/ \_ + * <------> + * n + */ +extern const Word16 pcmdsp_window_hann_960[960]; +extern const Word16 pcmdsp_window_hann_640[640]; + +/** Overlap/Add of two signal with a given window. */ +/** @param[in] fadeOut signal to fade out + * @param[in] fadeIn signal to fade in + * @param[in] out buffer to store the output signal + * @param[in] n number of samples + * @param[in] nChannels number of channels + * @param[in] fadeOutWin window for fade out + * @param[in] fadeInWin window for fade in */ +void overlapAdd(const Word16 *fadeOut, const Word16 *fadeIn, Word16 *out, + Word16 n, Word16 nChannels, const Word16 *fadeOutWin, const Word16 *fadeInWin, Word16 hannIncrementor); + +#endif /* PCMDSP_WINDOW_H */ diff --git a/lib_dec/lead_deindexing_fx.c b/lib_dec/lead_deindexing_fx.c new file mode 100644 index 0000000..6aba3a3 --- /dev/null +++ b/lib_dec/lead_deindexing_fx.c @@ -0,0 +1,279 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ + +#include "cnst_fx.h" +#include "rom_com_fx.h" +#include "rom_dec_fx.h" +#include "prot_fx.h" +#include "stl.h" + +/*-------------------------------------------------------------------* + * Local function prototype + *-------------------------------------------------------------------*/ +static void fcb_decode_pos_fx(Word16 index, Word16 pos_vector[], Word16 pulse_num, Word16 pos_num); + +/*-------------------------------------------------------------------* + * re8_decode_base_index_fx + * + * Decode RE8 base index + *-------------------------------------------------------------------*/ +void re8_decode_base_index_fx( + Word16 n, /* i : codebook number (*n is an integer defined in {0,2,3,4,..,n_max}) */ + UWord16 I, /* i : index of c (pointer to unsigned 16-bit word) */ + Word16 *x /* o : point in RE8 (8-dimensional integer vector) */ +) +{ + Word16 i,j,k1,l,m,m1,m2; + Word16 setor_8p_temp[8],setor_8p_temp_1[8],setor_8p_temp_2[8]= {0}; + Word16 sign_8p; + Word16 code_level; + const Word16 *a1,*a2; + + Word16 ka; + UWord16 offset; + Word16 code_index; + + Word16 element_a10, element_a11 = 0, element_a12 = 0; + + IF (LT_16( n, 2 )) + { + FOR (i=0; i<8; i++) + { + x[i]=0; + move16(); + } + } + ELSE + { + if ( GT_32( I, 65519 )) + { + I = 0; + move16(); + } + + /*-------------------------------------------------------------------* + * search for the identifier ka of the absolute leader (table-lookup) + * Q2 is a subset of Q3 - the two cases are considered in the same branch + *-------------------------------------------------------------------*/ + IF (LE_16(n,3)) + { + FOR (i = 1; i < NB_LDQ3; i++) + { + IF (LT_32(I, I3_fx[i])) + { + BREAK; + } + } + ka = A3_fx[sub(i,1)]; + move16(); + } + ELSE + { + FOR (i = 1; i < NB_LDQ4; i++) + { + IF (LT_32(I, I4_fx[i])) + { + BREAK; + } + } + ka = A4_fx[sub(i,1)]; + move16(); + } + + /*-------------------------------------------------------* + * decode + *-------------------------------------------------------*/ + a1 = vals_a_fx[ka]; + move16(); + a2 = vals_q_fx[ka]; + move16(); + k1 = a2[0]; + move16(); + code_level = a2[1]; + move16(); + + offset = Is_fx[ka]; + move16(); + code_index = extract_l( L_sub( I, offset ) ); + + sign_8p = s_and(code_index, sub( shl(1,k1), 1 )); + + code_index = shr(code_index, k1); + + m = 0; + move16(); + m1 = 0; + move16(); + m2 = 0; + move16(); + + element_a10 = a1[0]; + move16(); + + SWITCH (code_level) + { + case 4: + + m2 = 1; + move16(); + i = s_and(code_index, 1); + setor_8p_temp_2[0] = 0; + move16(); + + if ( i ) + { + setor_8p_temp_2[0] = 1; + move16(); + } + code_index = shr(code_index, 1); + /* no break */ + + case 3: + + m = a2[2]; + move16(); + m1 = a2[3]; + move16(); + + l = select_table22_fx[m1][m]; + move16(); + j = extract_l(L_shr(L_mult0(code_index, mult_avq_tab_fx[l]), shift_avq_tab_fx[l])); + code_index = sub(code_index, extract_l(L_mult0(j, l))); + fcb_decode_pos_fx(code_index,setor_8p_temp_1, m, m1); + + code_index = j; + move16(); + element_a12 = a1[2]; + move16(); + /* no break */ + + case 2: + + m = a2[2]; + move16(); + fcb_decode_pos_fx(code_index,setor_8p_temp,8,m); + element_a11 = a1[1]; + move16(); + } + + FOR (i=0; i<8; i++) + { + x[i] = element_a10; + move16(); + } + + FOR (i=0; i +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------------------* +* dqlsf_CNG_fx() +* +* LSF de-quantizer for SID frames (uses 28 bits, 4 for VQ, 24 for LVQ) +* +* Note: +* LP-CNG LSF decoder does not need to know the sampling rate, +* the sampling rate data is embedded inside the LSF coefficients. +* If the highest order LSF coefficient (lsf_q[M-1]) is smaller than 6350 then Fs=12.8kHz +* If the highest order LSF coefficient (lsf_q[M-1]) is larger than 6350 then Fs=16kHz +----------------------------------------------------------------------------------------*/ + +static void dqlsf_CNG_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *lsf_q, /* o : decoded LSFs */ + Word32 * p_offset_scale1, /* i : offset for 1st LVQ subvector */ + Word32 * p_offset_scale2, /* i : offset for second LVQ subvector */ + Word16 * p_no_scales /* i : number of scales for LVQ struct */ +) +{ + Word16 indice[4]; + Word16 ber_flag; + + indice[0] = (Word16)get_next_indice_fx( st_fx, 4 ); + move16(); + indice[1] = (Word16)get_next_indice_fx( st_fx, LEN_INDICE ); + move16(); + indice[2] = (Word16)get_next_indice_fx( st_fx, LSF_BITS_CNG - 4 - LEN_INDICE ); + move16(); + + /* deindex_lvq_cng decoder does not need to know the sampling rate, the sampling rate data is embedded inside the LSF coefficients */ + ber_flag= + deindex_lvq_cng_fx( &indice[1], lsf_q, indice[0], LSF_BITS_CNG-4, p_offset_scale1, p_offset_scale2, p_no_scales ); + + st_fx->BER_detect = s_or(ber_flag, st_fx->BER_detect); + + /* The sampling frequency of the LP-CNG frame can be determined by checking the value of the highest order LSF coefficient (last coefficient). + If the last decoded LSF coefficient is larger than 6350 the decoded frame is WB2 with sampling rate of 16 kHz + otherwise it is sampled at 12.8kHz and contains either NB or WB LSF data. */ + Vr_add(lsf_q, &CNG_SN1_fx[indice[0] * M], lsf_q, M); + + test(); + test(); + test(); + IF ( ((EQ_16(st_fx->L_frame_fx, L_FRAME16k))&&(LE_16(lsf_q[M-1],WB_LIMIT_LSF_FX)))||((LT_16(st_fx->L_frame_fx,L_FRAME16k))&&(GT_16(lsf_q[M-1],WB_LIMIT_LSF_FX)))) + { + st_fx->BER_detect = 1; + move16(); + } + + return; +} + +/*===========================================================================*/ +/* FUNCTION : lsf_dec_fx() */ +/*---------------------------------------------------------------------------*/ +/* PURPOSE : LSF decoder */ +/*---------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Struct) st_fx : decoder static memory */ +/* _ (Word16) L_frame : length of the frame */ +/* _ (Word16) coder_type : coding type */ +/* _ (Word16) bwidth : input signal bandwidth */ +/*---------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) Aq : LP filter coefficient Q12 */ +/* _ (Word16*) lsf_new : LP filter coefficient Q(x2.56) */ +/* _ (Word16*) lsp_new : LP filter coefficient Q15 */ +/* _ (Word16*) lsp_mid : LP filter coefficient Q15 */ +/*---------------------------------------------------------------------------*/ + +/* _ (Word16[]) st_fx->lsf_adaptive_mean_fx : FEC - adaptive mean LSF */ +/* vector for FEC Q(x2.56) */ +/* _ (Word16[]) st_fx->mem_AR_fx : AR memory of LSF quantizer */ +/* (past quantized LSFs without mean) Q(x2.56) */ +/* _ (Word16) st_fx->stab_fac_fx : LSF stability factor Q15 */ +/*---------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*===========================================================================*/ +void lsf_dec_fx( + Decoder_State_fx *st_fx, /* i/o: State structure */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + const Word16 bwidth, /* i : input signal bandwidth */ + Word16 *Aq, /* o : quantized A(z) for 4 subframes */ + Word16 *LSF_Q_prediction, /* o : LSF prediction mode */ + Word16 *lsf_new, /* o : de-quantized LSF vector */ + Word16 *lsp_new, /* o : de-quantized LSP vector */ + Word16 *lsp_mid /* o : de-quantized mid-frame LSP vector */ +) +{ + Word16 i; + Word16 int_fs; + Word32 L_tmp; + Word16 nBits = 0; + Word16 tmp_old[M+1], tmp_new[M+1]; + Word16 enr_old = 0, enr_new = 0; + Word16 lsf_diff; + /* initialize */ + int_fs = INT_FS_16k_FX; + move16(); + if( EQ_16(L_frame,L_FRAME)) + { + int_fs = INT_FS_FX; + move16(); + } + + /* Find the number of bits for LSF quantization */ + IF ( EQ_32(st_fx->core_brate_fx,SID_2k40)) + { + nBits = LSF_BITS_CNG; + move16(); + } + ELSE + { + test(); + IF ( st_fx->nelp_mode_dec_fx == 0 && st_fx->ppp_mode_dec_fx == 0 ) + { + nBits = LSF_bits_tbl[LSF_BIT_ALLOC_IDX_fx(st_fx->core_brate_fx, coder_type)]; + move16(); + } + ELSE IF ( EQ_16(st_fx->nelp_mode_dec_fx,1)) + { + IF ( EQ_16(coder_type,UNVOICED)) + { + nBits = 30; + move16(); + if ( EQ_16(bwidth,NB)) + { + nBits = 32; + move16(); + } + } + } + ELSE IF ( EQ_16(st_fx->ppp_mode_dec_fx,1)) + { + nBits = 26; + move16(); + } + } + + /* LSF de-quantization */ + lsf_end_dec_fx( st_fx, 0, coder_type, st_fx->bwidth_fx, nBits, lsf_new, st_fx->mem_AR_fx,st_fx->mem_MA_fx, int_fs, st_fx->core_brate_fx, + &st_fx->offset_scale1_fx[0][0], &st_fx->offset_scale2_fx[0][0], &st_fx->offset_scale1_p_fx[0][0], &st_fx->offset_scale2_p_fx[0][0], + &st_fx->no_scales_fx[0][0], &st_fx->no_scales_p_fx[0][0], &st_fx->safety_net_fx, NULL, LSF_Q_prediction, NULL ); + + /* convert quantized LSFs to LSPs */ + + lsf2lsp_fx(lsf_new, lsp_new, M ,int_fs); + IF ( EQ_32(st_fx->core_brate_fx,SID_2k40)) + { + /* return if SID frame (conversion to A(z) done in the calling function) */ + return; + } + + /*-------------------------------------------------------------------------------------* + * FEC - update adaptive LSF mean vector + *-------------------------------------------------------------------------------------*/ + + FOR (i=0; ilsfoldbfi1_fx[i], 10922); /*Q(x2.56+16)*/ + L_tmp = L_mac(L_tmp, st_fx->lsfoldbfi0_fx[i], 10922); /*Q(x2.56+16)*/ + st_fx->lsf_adaptive_mean_fx[i] = round_fx(L_tmp); /*Q(x2.56)*/ + } + + test(); + test(); + IF ( ( st_fx->prev_bfi_fx && (EQ_16(coder_type,TRANSITION))&&(EQ_16(tc_subfr,sub(L_frame,L_SUBFR))))) + { + lsf_diff = 1205; + move16(); /*int_fs / (float)(2*(M+1)); = 470.588 -> 1205 in Q2.56 */ + if( EQ_16(L_frame,L_FRAME)) + { + lsf_diff = 964; + move16(); /*int_fs / (float)(2*(M+1)); = 376.47 -> 964 in Q2.56 */ + } + st_fx->lsf_old_fx[0] = lsf_diff; + move16(); + + FOR ( i=1; ilsf_old_fx[i] = add(st_fx->lsf_old_fx[i-1], lsf_diff); + move16(); + } + lsf2lsp_fx( st_fx->lsf_old_fx, st_fx->lsp_old_fx, M, int_fs ); + } + /*-------------------------------------------------------------------------------------* + * Mid-frame LSF decoding + * LSP interpolation and conversion of LSPs to A(z) + *-------------------------------------------------------------------------------------*/ + if(st_fx->rate_switching_reset) + { + /*extrapolation in case of unstable LSF convert*/ + Copy(lsp_new,st_fx->lsp_old_fx,M); + Copy(lsf_new,st_fx->lsf_old_fx,M); + } + { + /* Mid-frame LSF decoding */ + lsf_mid_dec_fx( st_fx, int_fs, st_fx->lsp_old_fx, lsp_new, coder_type, lsp_mid, st_fx->core_brate_fx, st_fx->ppp_mode_dec_fx, st_fx->nelp_mode_dec_fx + ,st_fx->prev_bfi_fx, &(st_fx->mid_lsf_int_fx), st_fx->safety_net_fx); + } + test(); + test(); + IF ( !( st_fx->prev_bfi_fx && (EQ_16(coder_type,TRANSITION))&&(EQ_16(tc_subfr,sub(L_frame,L_SUBFR))))) + { + IF ( st_fx->prev_bfi_fx) + { + /* check, if LSP interpolation can be relaxed */ + E_LPC_f_lsp_a_conversion( st_fx->lsp_old_fx, tmp_old, M); + enr_old = Enr_1_Az_fx( tmp_old, 2*L_SUBFR ); + + E_LPC_f_lsp_a_conversion( lsp_new, tmp_new, M); + enr_new = Enr_1_Az_fx( tmp_new, 2*L_SUBFR ); + } + IF ( st_fx->prev_bfi_fx ) + { + IF( LT_16(enr_new, mult_r(9830/*0.3 Q15*/,enr_old))) + { + /* OLD CODE : if( st->safety_net == 1), replaced with a decision similar to MODE2 */ + st_fx->relax_prev_lsf_interp_fx = -1; + move16(); + test(); + test(); + test(); + test(); + if ( EQ_16(st_fx->clas_dec, UNVOICED_CLAS)||EQ_16(st_fx->clas_dec,SIN_ONSET)||EQ_16(st_fx->clas_dec,INACTIVE_CLAS)||EQ_16(coder_type,GENERIC)||EQ_16(coder_type,TRANSITION)) + { + st_fx->relax_prev_lsf_interp_fx = 1; + move16(); + } + } + } + } + test(); + IF( EQ_16(st_fx->last_core_fx, HQ_CORE)&&EQ_16(st_fx->core_fx,ACELP_CORE)) + { + /* update old LSPs/LSFs in case of HQ->ACELP core switching */ + Copy( lsp_mid, st_fx->lsp_old_fx, M ); + lsp2lsf_fx( lsp_mid, st_fx->lsf_old_fx, M, int_fs ); + } + + /* LSP interpolation and conversion of LSPs to A(z) */ + int_lsp4_fx( L_frame, st_fx->lsp_old_fx, lsp_mid, lsp_new, Aq, M, st_fx->relax_prev_lsf_interp_fx ); + + /*------------------------------------------------------------------* + * Check LSF stability (distance between old LSFs and current LSFs) + *------------------------------------------------------------------*/ + + st_fx->stab_fac_fx = lsf_stab_fx( lsf_new, st_fx->lsf_old_fx, 0, st_fx->L_frame_fx ); /*Q15*/ + + return; +} +/*========================================================================*/ +/* FUNCTION : lsf_end_dec_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : De-quantize frame end LSF vector */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) coder_type : coding type */ +/* _ (Word16) bwidth : input signal bandwidth */ +/* _ (Word16) nBits : number of bits used for ISF quantization */ +/* _ (Word32*) grid : Table of 100 grid points for evaluating */ +/* Chebyshev polynomials Q31 */ +/* _ (Word16) int_fs : sampling frequency */ +/* _ (Word32) core_brate : Coding Bit Rate */ +/* _ (Word32*) p_offset_scale1 : offsets for LSF LVQ structure 1st */ +/* 8-dim subvector Q0 */ +/* _ (Word32*) p_offset_scale2 : offsets for LSF LVQ structure 2nd */ +/* 8-dim subvector Q0 */ +/* _ (Word32*) p_offset_scale1_p : offsets for LSF LVQ structure, pred .*/ +/* case, 1st 8-dim subvector Q0 */ +/* _ (Word32*) p_offset_scale2_p : offsets for LSF LVQ structure, */ +/* pred. case, 2nd 8-dim subvector Q0 */ +/* _ (Word16*) p_no_scales : LSF LVQ structure Q0 */ +/* _ (Word16*) p_no_scales_p : LSF LVQ structure Q0 */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16*) mem_AR : quantizer memory for AR model Q(x2.56) */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) qlsf : quantized LSFs in the cosine domain Q(x2.56) */ +/*------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ + +void lsf_end_dec_fx( + Decoder_State_fx * st, /* i/o: decoder state structure */ + Word16 mode2_flag, + const Word16 coder_type_org, /* i : coding type */ + const Word16 bwidth, /* i : input signal bandwidth */ + const Word16 nBits_in, /* i : number of bits used for ISF quantization*/ + Word16 *qlsf, /* o : quantized LSFs in the cosine domain */ + Word16 *mem_AR, /* i/o: quantizer memory for AR model */ + Word16 *mem_MA, /* i/o: quantizer memory for MA model */ + const Word32 int_fs, /* i : sampling frequency */ + Word32 core_brate, /* i : Coding Bit Rate */ + Word32 *p_offset_scale1, + Word32 *p_offset_scale2, + Word32 *p_offset_scale1_p, + Word32 *p_offset_scale2_p, + Word16 *p_no_scales, + Word16 *p_no_scales_p, + Word16 *safe_net, + Word16 *lpc_param, + Word16 *LSF_Q_prediction, /* o : LSF prediction mode */ + Word16 * nb_indices +) +{ + Word16 pred0[M]; /* Prediction for the safety-net quantizer (usually mean)*/ + Word16 pred1[M], pred2[M]; /* Prediction for the predictive quantizer*/ + Word16 stages0; /* Amount of stages used by safety-net quantizer*/ + Word16 stages1; /* Amount of stages used by predictive quantizer*/ + Word16 levels0[MAX_VQ_STAGES]; /* Sizes of different codebook stages for safety-net quantizer*/ + Word16 levels1[MAX_VQ_STAGES]; /* Sizes of different codebook stages for predictive quantizer*/ + Word16 i; + Word16 TCQIdx[M/2+4]; + Word16 bits0[MAX_VQ_STAGES], bits1[MAX_VQ_STAGES]; + Word16 cumleft; + Word16 lindice[MAX_VQ_STAGES+3]; /* Predictor selector needs 1 bit and the LVQ indice uses 3 shorts */ + Word16 mode_lvq, mode_lvq_p; + Word16 safety_net, predmode, stages, *levels; + const Word16 *Bit_alloc1 = NULL, *bits; + Word16 num_bits; + Word16 * p_lpc_param; + + Word16 nr_ind; + Word16 nBits; + + Word16 coder_type; + Word16 ber_flag; + nBits = nBits_in; + move16(); + + test(); + test(); + IF((EQ_16(coder_type_org, GENERIC))&&(EQ_32(int_fs,INT_FS_16k))&&(mode2_flag==0)) + { + coder_type = (Word16)get_next_indice_fx( st, 1 ); + coder_type = add(coder_type,2); + if (EQ_16(coder_type, GENERIC)) + { + nBits = sub(nBits,1); + } + } + ELSE + { + coder_type = coder_type_org; + move16(); + } + + /*--------------------------------------------------------------------------------* + * LSF de-quantization of SID frames + *--------------------------------------------------------------------------------*/ + + IF ( core_brate == SID_2k40 ) + { + dqlsf_CNG_fx( st, qlsf, p_offset_scale1, p_offset_scale2, p_no_scales ); + sort_fx( qlsf, 0, M-1); + reorder_lsf_fx( qlsf, MODE1_LSF_GAP_FX, M, int_fs ); + + return; + } + + + predmode = find_pred_mode(coder_type, bwidth, int_fs, &mode_lvq, &mode_lvq_p, st->total_brate_fx); + /*----------------------------------------------------------------* + * Calculate number of stages and levels for each stage based on the allowed bit allocation + * (subtract one bit for LSF predictor selection) + *----------------------------------------------------------------*/ + lsf_allocate_fx( sub(nBits,shr(predmode,1)), mode_lvq, mode_lvq_p, &stages0, &stages1, levels0, levels1, + bits0, bits1); + + + /*--------------------------------------------------------------------------* + * Select safety_net or predictive mode + *--------------------------------------------------------------------------*/ + p_lpc_param = lpc_param; + + nr_ind = 0; + move16(); + IF ( predmode == 0 ) + { + safety_net = 1; + move16(); + } + ELSE IF ( predmode == 1 ) + { + safety_net = 0; + move16(); + } + ELSE + { + IF (EQ_16(mode2_flag, 1)) + { + nr_ind = add(nr_ind,1); + /* read from param_lpc */ + safety_net = p_lpc_param[0]; + move16(); + p_lpc_param++; + } + ELSE + { + safety_net = (Word16)get_next_indice_fx( st, 1 ); + } + } + + *safe_net = safety_net; + move16(); + + /*--------------------------------------------------------------------------* + * Read indices from array + *--------------------------------------------------------------------------*/ + + IF ( safety_net ) + { + stages = stages0; + move16(); + levels = levels0; + move16(); + bits = bits0; + move16(); + } + ELSE + { + stages = stages1; + move16(); + levels = levels1; + move16(); + bits = bits1; + move16(); + } + + IF (EQ_16(mode2_flag, 1)) + { + /* VOICED_WB@16kHz */ + test(); + IF ( EQ_32(int_fs, INT_FS_16k)&&EQ_16(coder_type,VOICED)) + { + *nb_indices = 10; + move16(); + FOR(i=0; i<*nb_indices; i++) + { + TCQIdx[i] = (Word16)lpc_param[i]; + move16(); + } + } + ELSE + { + FOR ( i=0; i 0 ) + { + IF ( GT_16(cumleft, LEN_INDICE)) + { + cumleft = sub(cumleft, LEN_INDICE); + num_bits = LEN_INDICE; + move16(); + } + ELSE + { + num_bits = (Word16)cumleft; + move16(); + cumleft = 0; + move16(); + } + + lindice[i+1] = *p_lpc_param++; + move16(); + nr_ind = add(nr_ind,1); + i = add(i,1); + } + *nb_indices = nr_ind; + move16(); + } + } + ELSE + { + /* VOICED_WB@16kHz */ + test(); + IF ( EQ_32(int_fs, INT_FS_16k)&&EQ_16(coder_type,VOICED)) + { + Bit_alloc1 = &BC_TCVQ_BIT_ALLOC_40B[1]; + TCQIdx[0] = safety_net; + move16(); + FOR ( i=0; i<(M/2)+3; i++ ) + { + TCQIdx[i+1] = (Word16)get_next_indice_fx( st, Bit_alloc1[i] ); + } + } + ELSE + { + FOR ( i=0; i 0 ) + { + IF ( GT_16(cumleft, LEN_INDICE)) + { + cumleft = sub(cumleft, LEN_INDICE); + num_bits = LEN_INDICE; + move16(); + } + ELSE + { + num_bits = (Word16)cumleft; + move16(); + cumleft = 0; + move16(); + } + + lindice[i+1] = (Word16)get_next_indice_fx( st, num_bits ); + i = add(i,1); + } + } + } + + IF(EQ_16(st->reset_mem_AR,1)) + { + FOR( i=0; imem_AR_fx[i] = ModeMeans_fx[mode_lvq][i]; + move16(); + } + st->reset_mem_AR = 0; + } + + /*------------------------------------------------------------------------------------------* + * De-quantize LSF vector + *------------------------------------------------------------------------------------------*/ + + *LSF_Q_prediction = SAFETY_NET; + move16(); + /* VOICED_WB@16kHz */ + test(); + IF ( EQ_32(int_fs, INT_FS_16k)&&EQ_16(coder_type,VOICED)) + { + /* BC-TCVQ decoder */ + safety_net = qlsf_ARSN_tcvq_Dec_16k_fx ( qlsf, TCQIdx, nBits-1 ); + + /* Update mem_MA */ + Copy( qlsf, mem_MA, M ); + + IF (safety_net) + { + Copy(ModeMeans_fx[mode_lvq], pred0, M); + } + ELSE + { + FOR(i = 0; i < M; i++) + { + pred0[i] = add(ModeMeans_fx[mode_lvq][i], mult(Predictors_fx[mode_lvq_p][i],(sub(mem_AR[i], ModeMeans_fx[mode_lvq][i])))); /* Q(x2.56)*/ + } + *LSF_Q_prediction = AUTO_REGRESSIVE; + move16(); + } + Vr_add( qlsf, pred0, qlsf, M ); + } + ELSE + { + + /* Safety-net */ + Copy( ModeMeans_fx[mode_lvq], pred0, M ); + /* for mem_MA update */ + FOR (i=0; iBER_detect = s_or(st->BER_detect, ber_flag); + Vr_add( qlsf, pred0, qlsf, M ); + Vr_subt( qlsf, pred1, mem_MA, M); + } + ELSE + { + ber_flag = + vq_dec_lvq_fx( 0, qlsf, &lindice[1], stages1, M, mode_lvq_p, levels1[stages1-1], + p_offset_scale1, p_offset_scale2, p_offset_scale1_p, p_offset_scale2_p, + p_no_scales, p_no_scales_p ); + + st->BER_detect = s_or(st->BER_detect, ber_flag); + IF (EQ_16(predmode, 1)) /* MA only */ + { + Copy(qlsf, mem_MA, M); + Vr_add( qlsf, pred1, qlsf, M ); + *LSF_Q_prediction = MOVING_AVERAGE; + move16(); + } + ELSE + { + /* AR */ + FOR ( i=0; imode_lvq = mode_lvq; + move16(); + + + return; +} + + +/*========================================================================*/ +/* FUNCTION : lsf_mid_dec_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : Decode mid-frame LSFs */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) coder_type : Coder type */ +/* _ (Word16) int_fs : internal (ACELP) sampling frequency */ +/* _ (Word32) core_brate : core bitrate */ +/* _ (Word32) ppp_mode : PPP mode */ +/* _ (Word32) nelp_mode : NELP mode */ +/* _ (Word16[]) qlsp0 : quantized LSPs from frame beginning Q15 */ +/* _ (Word16[]) qlsp1 : quantized LSPs from frame end Q15 */ +/* _ (Word16) prev_bfi, */ +/* _ (Word16 *)mid_lsf_int, */ +/* _ (Word16) safety_net */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) qlsp : quantized LSPs Q15 */ +/*------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ +void lsf_mid_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 int_fs, /* i : internal (ACELP) sampling frequency */ + Word16 qlsp0[], /* i : quantized LSPs from frame beginning Q15*/ + Word16 qlsp1[], /* i : quantized LSPs from frame endSQ15*/ + Word16 coder_type, /* i : Coder type */ + Word16 qlsp[], /* o : quantized LSPs Q15*/ + const Word32 core_brate, /* i : core bitrate */ + Word16 ppp_mode, + Word16 nelp_mode, + Word16 prev_bfi, + Word16 *mid_lsf_int, + Word16 safety_net +) +{ + Word16 j, idx; + Word16 nb_bits; + Word16 qlsf0[M], qlsf1[M], qlsf[M]; + Word32 L_tmp; + Word16 bad_spacing; + const Word16 *ratio = NULL; + bad_spacing = 0; + move16(); + + + /* Convert LSPs to LSFs */ + lsp2lsf_fx( qlsp0, qlsf0, M, int_fs); + lsp2lsf_fx( qlsp1, qlsf1, M, int_fs); + + /* Codebook selection */ + IF ( EQ_16(ppp_mode,1)) + { + nb_bits = 1; + move16(); + ratio = &tbl_mid_voi_wb_1b_fx[0]; + } + ELSE IF ( EQ_16(nelp_mode,1)) + { + nb_bits = 4; + move16(); + ratio = &tbl_mid_unv_wb_4b_fx[0]; + } + ELSE + { + nb_bits = mid_LSF_bits_tbl[LSF_BIT_ALLOC_IDX_fx(core_brate, coder_type)]; + move16(); + + /* codebook selection */ + + IF ( EQ_16(coder_type,VOICED)) + { + SWITCH ( nb_bits ) + { + case 5: + { + ratio = tbl_mid_voi_wb_5b_fx; + BREAK; + } + case 4: + { + ratio = tbl_mid_voi_wb_4b_fx; + BREAK; + } + } + } + ELSE IF ( coder_type == UNVOICED ) + { + ratio = tbl_mid_unv_wb_5b_fx; + } + ELSE + { + /* GENERIC, TRANSITION, AUDIO and INACTIVE */ + SWITCH ( nb_bits ) + { + case 5: + { + ratio = tbl_mid_gen_wb_5b_fx; + BREAK; + } + case 2: + { + ratio = tbl_mid_gen_wb_2b_fx; + BREAK; + } + } + } + } + + /* Retrieve mid-frame LSF index */ + idx = (Word16)get_next_indice_fx( st_fx, nb_bits ); + + /* Calculation of mid-LSF vector */ + FOR (j=0; jQ(x2.56+14)*/ + L_tmp = L_mac(L_tmp, ratio[idx*M+j], qlsf1[j]); /*Q(x2.56+14)*/ + qlsf[j] = round_fx(L_shl(L_tmp,2)); /*Q(x2.56)*/ + } + + /* check for incorrect LSF ordering */ + IF ( EQ_16(*mid_lsf_int, 1)) + { + FOR (j=1; j 0 && LT_16(j, M)&<_16(qlsf[j],add(qlsf[j-1],LSF_GAP_MID_FX))) + { + qlsf[j] = add(qlsf[j-1], LSF_GAP_MID_FX); + move16(); + } + } + } + ELSE + { + /* otherwise, use regular LSF spacing and ordering as in the encoder */ + FOR (j=0; j 0 && LT_16(j, M)&<_16(qlsf[j],add(qlsf[j-1],LSF_GAP_MID_FX))) + { + qlsf[j] = add(qlsf[j-1], LSF_GAP_MID_FX); + move16(); + } + } + } + + if ( prev_bfi ) + { + /* continue redoing mid-LSF interpolation with 0.4 in order not to propagate the error */ + *mid_lsf_int = 1; + move16(); + } + + if ( safety_net ) + { + /* safety-net encountered -> stop redoing mid-LSF interpolation with 0.4 */ + *mid_lsf_int = 0; + move16(); + } + + reorder_lsf_fx( qlsf, LSF_GAP_MID_FX, M, int_fs ); + + /* convert back to LSPs */ + lsf2lsp_fx( qlsf, qlsp, M, int_fs); + + return; +} diff --git a/lib_dec/lsf_msvq_ma_dec.c b/lib_dec/lsf_msvq_ma_dec.c new file mode 100644 index 0000000..e698cc8 --- /dev/null +++ b/lib_dec/lsf_msvq_ma_dec.c @@ -0,0 +1,294 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "stl.h" +#include "options.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "rom_com_fx.h" + + +#define swap(x,y,type) {type u__p; u__p=x; x=y; y=u__p;} + + +Word16 lsf_msvq_ma_decprm( Decoder_State_fx * st, Word16 *param_lpc, Word16 core, Word16 acelp_mode, Word16 acelp_midLpc, + Word16 narrowBand, Word32 sr_core + ) +{ + Word16 i, nbits_lpc, tmp; + Word16 bits_midlpc; + Word16 bits0[MAX_VQ_STAGES], bits1[MAX_VQ_STAGES], stages0, stages1, stages, + levels0[MAX_VQ_STAGES], levels1[MAX_VQ_STAGES], * bits; + Word16 predmode, mode_lvq, mode_lvq_p, safety_net; + + bits_midlpc=5; + move16(); + + test(); + IF ((EQ_32(sr_core, INT_FS_16k))&&(EQ_16(acelp_mode,UNVOICED))) + { + predmode = find_pred_mode(GENERIC, sub(1, narrowBand) /*st->bwidth*/, sr_core, + &mode_lvq, &mode_lvq_p, st->total_brate_fx); + move16(); + } + ELSE + { + IF (EQ_16(core, TCX_20_CORE)) + { + predmode = find_pred_mode(AUDIO, sub(1,narrowBand)/*st->bwidth*/, sr_core, + &mode_lvq, &mode_lvq_p, st->total_brate_fx ); + move16(); + } + ELSE + { + predmode = find_pred_mode(acelp_mode, sub(1, narrowBand)/*st->bwidth*/, sr_core, + &mode_lvq, &mode_lvq_p, st->total_brate_fx ); + move16(); + } + } + lsf_allocate_fx( sub(31, shr(predmode,1)), mode_lvq, mode_lvq_p, &stages0, &stages1, levels0, levels1, + bits0, bits1); + + + nbits_lpc = 0; + move16(); + + IF (EQ_16(predmode, 2)) + { + /* there is choice between SN and AR prediction */ + safety_net = get_next_indice_fx(st, 1); + + IF (EQ_16(safety_net,1)) + { + stages = stages0; + move16(); + bits = bits0; + move16(); + } + ELSE + { + stages = stages1; + move16(); + bits = bits1; + move16(); + } + *param_lpc = safety_net; + move16(); + param_lpc++; + nbits_lpc++; + + } + ELSE + { + stages = stages1; + move16(); + bits = bits1; + move16(); + } + + + tmp = sub(stages,1); + FOR (i=0; inext_bit_pos_fx; + move16(); + FOR (i=0; inext_bit_pos_fx, start_bit_pos); +} diff --git a/lib_dec/nelp_dec_fx.c b/lib_dec/nelp_dec_fx.c new file mode 100644 index 0000000..ae7d48e --- /dev/null +++ b/lib_dec/nelp_dec_fx.c @@ -0,0 +1,401 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ + +#include "rom_com_fx.h" +#include "stl.h" + +/*===================================================================*/ +/* FUNCTION : normalize_arr() */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Normalize array */ +/* */ +/*-------------------------------------------------------------------*/ +/* GLOBAL INPUT ARGUMENTS : */ +/* _ (Word16*) qf */ +/* _ (Word16*) size */ +/* _ (Word16*) hdr */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) arr : Normalized array */ +/*-------------------------------------------------------------------*/ + +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*===================================================================*/ +static void normalize_arr(Word16 *arr, Word16 *qf, Word16 size, Word16 hdr) +{ + Word16 i; + Word16 max_s = 0; + + FOR(i = 0; i < size; i++) + { + max_s=s_max(max_s, abs_s(arr[i])); + } + + *qf=norm_s((Word16)max_s); + test(); + IF((*qf == 0)&&(((Word16)max_s)==0)) + { + *qf = 15; + move16(); + } + + *qf = *qf-hdr; + + FOR (i = 0; i < size; i++) + { + arr[i] = shl(arr[i], *qf); + move16(); /* saturation can occur here */ + } + + return; +} + +/*===================================================================*/ +/* FUNCTION : nelp_decoder_fx() */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : NELP decoding for the current frame */ +/* */ +/*-------------------------------------------------------------------*/ +/* GLOBAL INPUT ARGUMENTS : */ +/* _ (Struct) st */ +/* _ (Word16[]) exc_nelp : adapt. excitation/total exc (Q0) */ +/* _ (Word16[]) exc : adapt. excitation exc (Q0) */ +/* _ (Word16) bfi : frame error rate */ +/* _ (Word16) coder_type : coding type */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc_nelp : adapt. excitation/total exc (Q0) */ +/*-------------------------------------------------------------------*/ + +/* _ (Word16[]) shape1_filt_mem_dec : filter memory (Q0) */ +/* _ (Word16[]) shape2_filt_mem_dec : filter memory (Q0) */ +/* _ (Word16[]) shape3_filt_mem_dec : filter memory (Q0) */ +/* _ (Word16[]) bp1_filt_mem_wb_dec : filter memory (Q0) */ +/* _ (Word16[]) bp1_filt_mem_nb_dec : filter memory (Q0) */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*===================================================================*/ + +void nelp_decoder_fx( Decoder_State_fx *st_fx, Word16 *exc_nelp, Word16 *exc, Word16 *Q_exc, Word16 bfi, const Word16 coder_type + , Word16 *gain_buf + ) +{ + Word16 i, fid = 0; + Word16 ptr[L_FRAME], filtRes[L_FRAME], gain_fac; /*ptr, filtRes - Q0, gain_fac - Q14 */ + Word16 Gains[10]; /* Q0 */ + Word32 Gain, E3, E2; + Word16 BP1_ORDER = 4; + Word16 ptr_tmp[L_FRAME]; /* Q0 */ + Word16 iG1, iG2[2]; + Word16 exp_E2, exp_E3, frac_E2, frac_E3; + Word16 tmp, scale, exp, frac; + Word32 L_tmp, L_tmp1; + Word32 exc_sqr[L_SUBFR]; + Word32 max_exc_sqr; + Word16 n; + Word16 max_val = 0, norm_val = 0; + Word16 qGain=0; + + if (EQ_16(st_fx->last_nelp_mode_dec_fx,1)&&NE_16(st_fx->bwidth_fx,st_fx->last_bwidth_fx)) + { + st_fx->last_nelp_mode_dec_fx = 0; + } + + test(); + test(); + test(); + IF ( EQ_16(coder_type,UNVOICED)&&EQ_16(st_fx->bwidth_fx,NB)) + { + IF (NE_16(st_fx->last_nelp_mode_dec_fx,1)) + { + BP1_ORDER = 7; + move16(); + + set32_fx(st_fx->bp1_filt_mem_nb_dec_fx, 0, BP1_ORDER*2); + } + } + ELSE IF ( EQ_16(coder_type,UNVOICED)&&(EQ_16(st_fx->bwidth_fx,WB)||EQ_16(st_fx->bwidth_fx,SWB))) + { + BP1_ORDER =4; + move16(); + IF (NE_16(st_fx->last_nelp_mode_dec_fx,1)) + { + set16_fx(st_fx->bp1_filt_mem_wb_dec_fx, 0 , BP1_ORDER*2); + } + } + + IF (NE_16(st_fx->last_nelp_mode_dec_fx,1)) + { + set16_fx(st_fx->shape1_filt_mem_dec_fx, 0, 10); + set16_fx(st_fx->shape2_filt_mem_dec_fx, 0, 10); + set16_fx(st_fx->shape3_filt_mem_dec_fx, 0, 10); + } + + IF (bfi == 0) + { + test(); + IF(EQ_16(st_fx->rf_frame_type,RF_NELP)&&EQ_16(st_fx->use_partial_copy,1)) + { + iG1 = st_fx->rf_indx_nelp_iG1; + iG2[0] = st_fx->rf_indx_nelp_iG2[0]; + iG2[1] = st_fx->rf_indx_nelp_iG2[1]; + } + ELSE + { + /* Do Unvoiced/NELP Decoding */ + iG1 =(Word16) get_next_indice_fx( st_fx, 5 ); + move16(); + iG2[0] =(Word16) get_next_indice_fx( st_fx, 6 ); + move16(); + iG2[1] =(Word16) get_next_indice_fx( st_fx, 6 ); + move16(); + } + + test(); + test(); + IF ( EQ_16(coder_type,UNVOICED)&&(EQ_16(st_fx->bwidth_fx,WB)||EQ_16(st_fx->bwidth_fx,SWB))) + { + test(); + IF(EQ_16(st_fx->rf_frame_type,RF_NELP)&&EQ_16(st_fx->use_partial_copy,1)) + { + fid = st_fx->rf_indx_nelp_fid; + } + ELSE + { + fid = (Word16)get_next_indice_fx( st_fx, 2 ); + move16(); + } + } + + *Q_exc = dequantize_uvg_fx(iG1, iG2, Gains, st_fx->bwidth_fx ,1 ); + move16();/* Gains - Q0/Q3 */ + } + ELSE + { + FOR (i=1; i<=L_SUBFR; i++) + { + exc_sqr[i-1] = L_mult0(exc[-i],exc[-i]); + move32();/*2*Q_exc */ + } + max_exc_sqr = L_deposit_l(0); + FOR (i=0; ibwidth_fx,WB)||EQ_16(st_fx->bwidth_fx,SWB))) + { + gain_fac = 19005; + move16(); /* 1.16f - Q14 */ + } + + IF (EQ_16(st_fx->bwidth_fx,WB)||EQ_16(st_fx->bwidth_fx,SWB)) + { + /* Normalize Gains[10] with headroom 4, qGain is the new Q value os Gains, not Q0*/ + /* This is done to avoid internal overflow observed in the wb bp filter below, similar to encoder */ + normalize_arr(Gains, &qGain, 10, 4); + } + + generate_nelp_excitation_fx(&(st_fx->nelp_dec_seed_fx), Gains, ptr, gain_fac); + /* o: ptr = nelp_exc in Q=qGain, qGain = 0 always for NB */ + + test(); + test(); + IF ( EQ_16(coder_type,UNVOICED )&&(EQ_16(st_fx->bwidth_fx,WB)||EQ_16(st_fx->bwidth_fx,SWB))) + { + BP1_ORDER =4; + move16(); + Scale_sig(st_fx->bp1_filt_mem_wb_dec_fx, 2*BP1_ORDER, qGain); /* bring filter prev memory from Q0 to qGain */ + pz_filter_sp_fx(bp1_num_coef_wb_fx, bp1_den_coef_wb_fx, ptr, ptr_tmp, st_fx->bp1_filt_mem_wb_dec_fx, + BP1_ORDER, BP1_ORDER, L_FRAME, (sub(16,BP1_COEF_WB_QF))); + + Scale_sig(st_fx->bp1_filt_mem_wb_dec_fx, 2*BP1_ORDER, -qGain); /* bring filter prev memory from qGain to Q0 */ + Scale_sig(ptr_tmp, L_FRAME, -qGain); /* bring nelp_exc to Q0 */ + Copy(ptr_tmp,ptr,L_FRAME); + } + + test(); + IF ( EQ_16(coder_type,UNVOICED )&&(EQ_16(st_fx->bwidth_fx,NB))) + { + BP1_ORDER = 7; + move16(); + + FOR (i=0; i < L_FRAME; i++ ) + { + max_val = s_max( ptr[i], max_val ); + } + tmp = shl(BP1_ORDER,1); + FOR (i=0; i < tmp; i++ ) + { + max_val = s_max( round_fx( L_shr( st_fx->bp1_filt_mem_nb_dec_fx[i], 16)), max_val ); + } + norm_val = norm_s(max_val); + + norm_val = s_max (0, sub(norm_val, 4)); /* 4 bit head room */ + + norm_val = s_min ( norm_val,8); /* scale only for very low level signals */ + + IF ( norm_val > 0 ) + { + Scale_sig32(st_fx->bp1_filt_mem_nb_dec_fx, shl(BP1_ORDER,1), norm_val) ; + Scale_sig(ptr, L_FRAME, norm_val); + *Q_exc = add( norm_val, *Q_exc ); + } + + BP1_ORDER = 7; + move16(); + pz_filter_dp_fx(bp1_num_coef_nb_fx_order7, bp1_den_coef_nb_fx_order7, ptr, ptr_tmp, st_fx->bp1_filt_mem_nb_dec_fx, + BP1_ORDER, BP1_ORDER, L_FRAME, (sub(16,BP1_COEF_NB_QF_ORDER7))); + + + IF ( norm_val > 0 ) + { + Scale_sig32(st_fx->bp1_filt_mem_nb_dec_fx, shl(BP1_ORDER,1), -norm_val) ; + + } + + Copy(ptr_tmp,ptr,L_FRAME); /*Q_exc */ + } + + E3 = L_deposit_l(1); + FOR (i=0 ; ibwidth_fx,WB)||EQ_16(st_fx->bwidth_fx,SWB))) + { + pz_filter_sp_fx(shape1_num_coef_fx, shape1_den_coef_fx, ptr, ptr_tmp, st_fx->shape1_filt_mem_dec_fx, + 10, 10, L_FRAME, (sub(16,SHAPE1_COEF_QF))); + Copy(ptr_tmp,ptr,L_FRAME); /*Q_exc */ + + SWITCH(fid) + { + case 1: + /* Update other filter memory */ + pz_filter_sp_fx(shape3_num_coef_fx, shape3_den_coef_fx, ptr, filtRes, st_fx->shape3_filt_mem_dec_fx, + 10, 10, L_FRAME, (sub(16,SHAPE3_COEF_QF))); + + /* filter the residual to desired shape */ + pz_filter_sp_fx(shape2_num_coef_fx, shape2_den_coef_fx, ptr, ptr_tmp, st_fx->shape2_filt_mem_dec_fx, + 10, 10, L_FRAME, (sub(16,SHAPE2_COEF_QF))); + + Copy(ptr_tmp,ptr,L_FRAME); /*Q_exc */ + + BREAK; + case 2: + /* Update other filter memory */ + pz_filter_sp_fx(shape2_num_coef_fx, shape2_den_coef_fx, ptr, filtRes, st_fx->shape2_filt_mem_dec_fx, + 10, 10, L_FRAME, (sub(16,SHAPE2_COEF_QF))); + + /* filter the residual to desired shape */ + pz_filter_sp_fx(shape3_num_coef_fx, shape3_den_coef_fx, ptr, ptr_tmp, st_fx->shape3_filt_mem_dec_fx, + 10, 10, L_FRAME, (sub(16,SHAPE3_COEF_QF))); + + Copy(ptr_tmp,ptr,L_FRAME); /*Q_exc */ + + BREAK; + default: + /* Update other filter memory */ + pz_filter_sp_fx(shape2_num_coef_fx, shape2_den_coef_fx, ptr, filtRes, st_fx->shape2_filt_mem_dec_fx, + 10, 10, L_FRAME, (sub(16,SHAPE2_COEF_QF))); + pz_filter_sp_fx(shape3_num_coef_fx, shape3_den_coef_fx, ptr, filtRes, st_fx->shape3_filt_mem_dec_fx, + 10, 10, L_FRAME, (sub(16,SHAPE3_COEF_QF))); + + BREAK; + } + + E2 = L_deposit_l(1); + FOR (i=0 ; i max noise_level-idx = 3 */ + noise_level[i] = i_mult(noise_level_idx, PK_VQ_NOISE_DELTA); + move16();/* max noise_level=3*0.1 => Q15 is good enough */ + + bits = sub(bits, 2); + } + + peak_vq_dec_fx( st_fx, coefsq_norm, (Word16)core_brate, bits, ynrm, R, peak_idx, + Npeaks, core ); +} + +/*-------------------------------------------------------------------------- + * peak_vq_dec() + * + * Vector de-quantization of MDCT peaks + *--------------------------------------------------------------------------*/ + +void peak_vq_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word32 *coefs_out, /* o : Output coefficient vector Q12 */ + const Word16 brate, /* i : Core bitrate */ + const Word16 num_bits, /* i : Number of bits for HVQ */ + const Word16 *ynrm, /* i : Envelope coefficients */ + Word16 *R, /* i/o: Bit allocation/updated bit allocation */ + Word16 *vq_peak_idx, /* o : Peak position vector */ + Word16 *Npeaks, /* o : Number of peaks */ + const Word16 core +) +{ + Word16 vq_peaks, i, j, k, FlagN, hcode_l, diff; + Word16 bin_th, bin_th2, max_peaks, pvq_bands; + Word16 nf_gains_idx[HVQ_NF_GROUPS], pgain_difidx[HVQ_MAX_PEAKS_32k], pvq_norm[MAX_PVQ_BANDS]; + Word16 gain_bits_array[MAX_PVQ_BANDS]; + Word16 pos_bits; + Word32 nf_gains_fx[HVQ_NF_GROUPS], peak_gains_fx[HVQ_MAX_PEAKS_32k]; + Word16 pvq_vector[HVQ_PVQ_BUF_LEN]; + Word16 res_vec[HVQ_THRES_BIN_32k]; + Word16 k_sort[HVQ_MAX_PVQ_WORDS]; + Word16 pvq_inp_vector[HVQ_PVQ_BUF_LEN], pvq_maxpulse[HVQ_MAX_PVQ_WORDS]; + Word16 npulses[MAX_PVQ_BANDS]; + Word16 pvq_bits, Rk[MAX_PVQ_BANDS]; + Word16 fg_pred[NB_SFM_MAX]; + + Word32 *pCoefsOut; + Word16 whiteNoise; + UWord16 dontCare; + Word32 acc; + Word16 *pPvqVector; + Word32 manE_peak, manPeakGains, manPkEnrg; /* Due to very wide dynamic range, use floating point format, i.e., (man, exp) */ + Word16 expE_peak, expPeakGains, expPkEnrg; + Word16 *pSelBnds; + Word16 sel_bnds[HVQ_NUM_SFM_24k]; + Word16 hvq_band_end[MAX_PVQ_BANDS]; + Word16 hvq_band_start[MAX_PVQ_BANDS]; + Word16 hvq_band_width[MAX_PVQ_BANDS]; + Word16 n_sel_bnds; + Word32 normq; + UWord32 lsb; + Word32 tmp; + Word16 nf_seed = RANDOM_INITSEED; + move16(); + + set16_fx( gain_bits_array, 0, MAX_PVQ_BANDS ); + set16_fx( pvq_vector, 0, HVQ_PVQ_BUF_LEN ); + set16_fx( npulses, 0, MAX_PVQ_BANDS ); + set16_fx( pvq_inp_vector, 0, HVQ_PVQ_BUF_LEN ); + + /* Set bitrate dependent variables */ + IF (EQ_16(brate, HQ_24k40)) + { + max_peaks = HVQ_MAX_PEAKS_24k; + move16(); + bin_th = HVQ_THRES_BIN_24k; + move16(); + bin_th2 = HVQ_THRES_BIN_24k/HVQ_NF_GROUPS; + move16(); + } + ELSE + { + max_peaks = HVQ_MAX_PEAKS_32k; + move16(); + bin_th = HVQ_THRES_BIN_32k; + move16(); + bin_th2 = HVQ_THRES_BIN_32k/HVQ_NF_GROUPS; + move16(); + } + + /* Get number of peaks */ + vq_peaks = get_next_indice_fx( st_fx, 5 ); + vq_peaks = sub(max_peaks, vq_peaks); + *Npeaks = vq_peaks; + move16(); + diff = 5; + move16(); + + /* safety check in case of bit errors */ + IF( LT_16(*Npeaks, HVQ_MIN_PEAKS)) + { + st_fx->BER_detect = 1; + move16(); + vq_peaks = HVQ_MIN_PEAKS; + move16(); + *Npeaks = HVQ_MIN_PEAKS; + move16(); + } + + /* De-quantize peak positions */ + FOR (i = 0; i < bin_th; i++) + { + res_vec[i] = 0; + move16(); + } + + /* Unpack PVQ codewords */ + pos_bits = hvq_dec_pos_fx(st_fx, res_vec, bin_th, vq_peaks); + diff = add(diff, pos_bits); + + j = 0; + move16(); + test(); + FOR (i = 0; i < bin_th && j < vq_peaks; i++) /* safety check in case of bit errors */ + { + IF ( res_vec[i] != 0) + { + vq_peak_idx[j++] = i; + move16(); + } + } + + /* safety check in case of bit errors */ + IF( LT_16(j, vq_peaks)) + { + st_fx->BER_detect = 1; + move16(); + vq_peaks = sub(j, 1); + *Npeaks = sub(j, 1); + } + + /* Huffman or differential coding */ + FlagN = (Word16) get_next_indice_fx( st_fx, 1 ); + + /* De-quantize peak gains */ + pgain_difidx[0] = get_next_indice_fx( st_fx, GAIN0_BITS ); + + /* safety check in case of bit errors */ + IF( GT_16(pgain_difidx[0], 44)) + { + st_fx->BER_detect = 1; + move16(); + pgain_difidx[0] = 44; + move16(); + } + peak_gains_fx[0] = dicn_pg_fx[pgain_difidx[0]]; /* Q12 */ move32(); + if (res_vec[vq_peak_idx[0]] < 0) + { + peak_gains_fx[0] = L_negate(peak_gains_fx[0]); + move16(); + } + + hcode_l = 0; + move16(); + IF (FlagN) + { + huff_dec_fx( st_fx, vq_peaks-1, MAX_PG_HUFFLEN, NUM_PG_HUFFLEN, hvq_pg_huff_thres, hvq_pg_huff_offset, hvq_pg_huff_tab, &pgain_difidx[1] ); + + FOR (i = 1; i < vq_peaks; i++) + { + hcode_l = add(hcode_l, pgain_huffsizn[pgain_difidx[i]]); + move16();/* indirect addressing*/ + } + } + ELSE + { + FOR (i = 1; i < vq_peaks; i++) + { + pgain_difidx[i] = get_next_indice_fx(st_fx, GAINI_BITS ); + move16(); + hcode_l = add(hcode_l, GAINI_BITS); + } + } + + FOR (i = 1; i < vq_peaks; i++) + { + pgain_difidx[i] = add(pgain_difidx[i], sub(pgain_difidx[i - 1],15)); + move16(); + + /* safety check in case of bit errors */ + test(); + IF( GT_16(pgain_difidx[i], 44)||pgain_difidx[i]<0) + { + st_fx->BER_detect = 1; + move16(); + pgain_difidx[i] = 44; + move16(); + } + + peak_gains_fx[i] = dicn_pg_fx[pgain_difidx[i]]; + move32();/* Q12 move16(); */ + if (res_vec[vq_peak_idx[i]] < 0) + { + peak_gains_fx[i] = L_negate(peak_gains_fx[i]); + move32(); + } + } + + /* Scale up peak gains and accumulate peak energy */ + manE_peak = L_deposit_l(0); + expE_peak = 32; + move16(); + FOR (i = 0; i < vq_peaks; i++) + { + peak_gains_fx[i] = L_shl(peak_gains_fx[i], 2); + move32(); /* Q12 */ + /* Use floating point operation to deal with wide dynamic range. + * 32-bit mantissa is used here. It should be even more accurate than + * the floating-point reference code with 24-bit mantissa! */ + tmp = L_shl(dicn_pg_fx[pgain_difidx[i]], 2); + expPeakGains = norm_l(tmp); + manPeakGains = L_shl(tmp, expPeakGains); + Mpy_32_32_ss(manPeakGains, manPeakGains, &manPkEnrg, &lsb); /* peak_gains square */ + expPkEnrg = shl(expPeakGains, 1); /* Multiply by 2 due to squaring. */ + + floating_point_add(&manE_peak, &expE_peak, manPkEnrg, expPkEnrg); + } + /* Number of bits used for peak gain quantization */ + diff = add(diff, add(FLAGN_BITS + GAIN0_BITS, hcode_l)); + + /* De-quantize peaks */ + FOR (i = 0; i < vq_peaks; i++) + { + dequant_peaks_fx( st_fx, &coefs_out[vq_peak_idx[i]-2], &peak_gains_fx[i]); /* coefs_out in Q12, peak_gains_fx in Q14 */ + diff = add(diff, 9); + } + + FOR (i = 0; i < HVQ_NF_GROUPS; i++) + { + nf_gains_idx[i] = get_next_indice_fx( st_fx, 5 ); + move16(); + nf_gains_fx[i] = L_shr(dicn_fx[nf_gains_idx[i]],1); + move32(); /* nf_gains in Q14 */ + diff = add(diff, 5); + } + pvq_bits = sub(num_bits, diff); + + /* Calculate number of PVQ bands to code and assign bits */ + pvq_bands = hvq_pvq_bitalloc_fx(pvq_bits, brate, st_fx->bwidth_fx, ynrm, manE_peak, expE_peak, Rk, R, sel_bnds, + &n_sel_bnds); + + /* safety check in case of bit errors */ + if (pvq_bands == 0) + { + st_fx->BER_detect = 1; + move16(); + } + + pvq_bits = sub(pvq_bits, i_mult2(HVQ_PVQ_GAIN_BITS, pvq_bands)); + /* Get band limits for concatenated PVQ target */ + hvq_concat_bands_fx(pvq_bands, sel_bnds, n_sel_bnds, hvq_band_start, + hvq_band_width, hvq_band_end); + + FOR (k = 0; k < pvq_bands; k++) + { + k_sort[k] = k; + move16(); + } + + pvq_decode_frame_fx(st_fx, pvq_vector, npulses, pvq_inp_vector, hvq_band_start, hvq_band_end, hvq_band_width, pvq_bands, Rk, pvq_bits, core ); + + + fine_gain_pred_fx( hvq_band_start, hvq_band_end, hvq_band_width, k_sort, npulses, pvq_maxpulse, NULL, + pvq_bands, pvq_vector, pvq_inp_vector, fg_pred, core ); + + fine_gain_dec_fx( st_fx, k_sort, pvq_bands, gain_bits_array, fg_pred); + + apply_gain_fx(k_sort, hvq_band_start, hvq_band_end, pvq_bands, fg_pred, pvq_vector); + + pPvqVector = pvq_vector; + pCoefsOut = coefs_out; + pSelBnds = sel_bnds; + move16(); + FOR (k = 0; k < pvq_bands; k++) + { + pvq_norm[k] = get_next_indice_fx( st_fx, HVQ_PVQ_GAIN_BITS ); + pvq_norm[k] = add(pvq_norm[k], 8); + move16(); + + diff = add(diff, HVQ_PVQ_GAIN_BITS); + + j = 0; + move16(); + IF (GE_16(k, sub(pvq_bands, n_sel_bnds))) + { + i = band_start_harm[*pSelBnds++]; + move16(); + move16(); + pCoefsOut = coefs_out + i; + } + normq = L_add(dicn_fx[pvq_norm[k]], 0); + WHILE (LT_16(j, hvq_band_width[k])) + { + IF (EQ_32(*pCoefsOut, 0)) + { + Mpy_32_16_ss(normq, *pPvqVector++, &acc, &dontCare); /* acc(Q11), normq(Q14), pvq_vector(Q12) */ + *pCoefsOut = L_shl(acc, 12 - 11); /* Q12 */ move32(); + j = add(j, 1); + } + pCoefsOut++; + } + } + + /* Noise fill unqantized coeffs with one gain per group */ + pCoefsOut = &coefs_out[-1]; + FOR (i = 0; i < HVQ_NF_GROUPS; i++) + { + FOR (j = 0; j < bin_th2; j++) + { + IF (*(++pCoefsOut) == 0) + { + whiteNoise = Random(&nf_seed); /* Q15 */ + Mpy_32_16_ss(nf_gains_fx[i], whiteNoise, &acc, &dontCare); /* nf_gains_fx[] in Q14 */ + *pCoefsOut = L_shr(acc, 14-12); /* Q12 */ move32(); + } + } + } + + return; +} + +/*-------------------------------------------------------------------------- + * dequant_peaks() + * + * Reads codebook vector and scales peak + *--------------------------------------------------------------------------*/ + +static void dequant_peaks_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word32 *vect_out, /* o : Quantized vector in Q12 */ + const Word32 *peak_gain /* i : Peak gain in Q12 */ +) +{ + Word16 xq[4]; + const Word16 *tmp; + Word16 i, hvq_cb_rev; + Word16 cb_idx, indx; + Word32 absPeakGain1, absPeakGain; + UWord16 dontCare; + + hvq_cb_rev = get_next_indice_fx( st_fx, 1 ); + cb_idx = get_next_indice_fx( st_fx, 8 ); + + indx = shl(cb_idx,2); + IF ( hvq_cb_rev ) + { + indx = add(indx,3); + tmp = &hvq_peak_cb_fx[indx]; + FOR (i = 0; i < 4; i++) + { + xq[i] = *tmp--; /* Q15 */ move16(); + } + } + ELSE + { + tmp = &hvq_peak_cb_fx[indx]; + FOR (i = 0; i < 4; i++) + { + xq[i] = *tmp++; /* Q15 */ move16(); + } + } + + absPeakGain = L_abs(peak_gain[0]); + + IF(vect_out[0] == 0) + { + Mpy_32_16_ss(*peak_gain, xq[0], &vect_out[0], &dontCare); /* vect_out in Q12 */ + Mpy_32_16_ss(*peak_gain, xq[1], &vect_out[1], &dontCare); /* Q12 */ + } + ELSE + { + absPeakGain1 = L_abs(peak_gain[-1]); + IF(LE_32(absPeakGain1, absPeakGain)) + { + Mpy_32_16_ss(*peak_gain, xq[0], &vect_out[0], &dontCare); /* vect_out in Q12 */ + Mpy_32_16_ss(*peak_gain, xq[1], &vect_out[1], &dontCare); /* Q12 */ + } + ELSE + { + IF(vect_out[1] == 0 || (LE_32(absPeakGain1, absPeakGain))) + { + Mpy_32_16_ss(*peak_gain, xq[1], &vect_out[1], &dontCare); + } + } + } + vect_out[2] = *peak_gain; /* vect_out in Q12 */ + Mpy_32_16_ss(*peak_gain, xq[2], &vect_out[3], &dontCare); + Mpy_32_16_ss(*peak_gain, xq[3], &vect_out[4], &dontCare); + + return; +} + + +/*-------------------------------------------------------------------------- + * hvq_dec_pos() + * + * HVQ decode peak positions + *--------------------------------------------------------------------------*/ + +static Word16 hvq_dec_pos_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *pos_vec, + const Word16 length, + const Word16 num_peaks +) +{ + Word16 peak_idx[HVQ_MAX_PEAKS_32k]; + Word16 delta[HVQ_MAX_PEAKS_32k]; + Word16 sign_vec[HVQ_MAX_PEAKS_32k]; + + Word16 mode; + Word16 num_bits, tmp; + Word16 i, j; + + num_bits = 0; + move16(); + set16_fx(pos_vec, 0, length); + + mode = get_next_indice_fx(st_fx, 1); + num_bits = add(num_bits, 1); + + IF (mode == HVQ_CP_DELTA) + { + huff_dec_fx(st_fx, num_peaks, HVQ_CP_HUFF_MAX_CODE, HVQ_CP_HUFF_NUM_LEN, hvq_cp_huff_thres, hvq_cp_huff_offset, hvq_cp_huff_tab, delta); + + FOR (i = 0; i < num_peaks; i++) + { + num_bits = add(num_bits, hvq_cp_huff_len[delta[i]]); + } + + peak_idx[0] = sub(delta[0], HVQ_CP_HUFF_OFFSET); + /* safety check in case of bit errors */ + IF (peak_idx[0] < 2) + { + peak_idx[0] = 2; + move16(); + st_fx->BER_detect = 1; + move16(); + } + FOR (i = 1; i < num_peaks; i++) + { + peak_idx[i] = add(add(delta[i], peak_idx[i-1]), HVQ_CP_HUFF_OFFSET); + move16(); + /* safety check in case of bit errors */ + IF (GE_16(peak_idx[i], HVQ_THRES_BIN_32k)) + { + peak_idx[i] = HVQ_THRES_BIN_32k - 1; + move16(); + st_fx->BER_detect = 1; + move16(); + } + } + + FOR (i = 0; i < num_peaks; i++) + { + pos_vec[peak_idx[i]] = 1; + move16(); + } + } + ELSE + { + tmp = sparse_dec_pos_fx(st_fx, pos_vec, length); + num_bits = add(num_bits, tmp); + } + + FOR (i = 0; i < num_peaks; i++) + { + IF (get_next_indice_1_fx(st_fx) == 0) + { + sign_vec[i] = -1; + move16(); + } + ELSE + { + sign_vec[i] = 1; + move16(); + } + } + num_bits = add(num_bits, num_peaks); + + j = 0; + move16(); + /* safety check in case of bit errors */ + test(); + FOR (i = 0; i < length && j < num_peaks; i++) + { + if (EQ_16(pos_vec[i], 1)) + { + pos_vec[i] = i_mult2(pos_vec[i], sign_vec[j++]); + move16(); + } + } + + return num_bits; +} + +/*-------------------------------------------------------------------------- + * sparse_dec_pos() + * + * Sparse decode positions + *--------------------------------------------------------------------------*/ + +static Word16 sparse_dec_pos_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *out, + const Word16 length +) +{ + Word16 layer2[HVQ_CP_L2_MAX]; + Word16 layer_length; + Word16 i, j, tmp; + Word16 bits; + Word16 idx, val; + + set16_fx(layer2, 0, HVQ_CP_L2_MAX); + set16_fx(out, 0, length); + bits = 0; + move16(); + + /*layer_length = (short)((float)length/HVQ_CP_L1_LEN + 0.5); */ + layer_length = round_fx(L_mult0(length, 13107)); /* 0+16-16, 13107 is 1/5 in Q16 */ + + FOR (i = 0; i < layer_length; i++) + { + layer2[i] = get_next_indice_1_fx(st_fx); + move16(); + } + bits = add(bits, layer_length); + + FOR (j = 0; j < layer_length; j++) + { + IF (EQ_16(layer2[j], 1)) + { + idx = get_next_indice_fx(st_fx, HVQ_CP_MAP_IDX_LEN); + bits = add(bits, HVQ_CP_MAP_IDX_LEN); + + val = hvq_cp_layer1_map5[idx]; + move16(); + test(); /* safety check in case of bit errors */ + IF ( j == 0 && GT_16(val, 4)) /* out[0] and out[1] are invalid positions */ + { + st_fx->BER_detect = 1; + move16(); + val = 4; + move16(); + } + tmp = i_mult2(j, HVQ_CP_L1_LEN); + FOR (i = sub(s_min(i_mult2(add(j,1), HVQ_CP_L1_LEN), length), 1); i >= tmp; i--) + { + out[i] = s_and(val, 1); + move16(); + val = lshr(val, 1); + } + } + } + + return bits; +} diff --git a/lib_dec/pit_dec.c b/lib_dec/pit_dec.c new file mode 100644 index 0000000..7a4e183 --- /dev/null +++ b/lib_dec/pit_dec.c @@ -0,0 +1,948 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "cnst_fx.h" +#include "prot_fx.h" +#include "stl.h" +#include "options.h" + +#include "rom_basop_util.h" +#define inv_T0_res InvIntTable + +/*----------------------------------------------------------* + * Mode2_pit_decode() + * + * Decode pitch lag + *----------------------------------------------------------*/ + +Word32 Mode2_pit_decode( /* o: floating pitch value */ + const Word16 coder_type, /* i: coding model */ + Word16 i_subfr, /* i: subframe index */ + Word16 L_subfr, + Word16 **pt_indice, /* i/o: quantization indices pointer */ + Word16 *T0, /* i/o: close loop integer pitch */ + Word16 *T0_frac, /* o: close loop fractional part of the pitch */ + Word16 *T0_res, /* i/o: pitch resolution */ + Word16 *T0_min, /* i/o: lower limit for close-loop search */ + Word16 *T0_min_frac, /* i/o: lower limit for close-loop search */ + Word16 *T0_max, /* i/o: higher limit for close-loop search */ + Word16 *T0_max_frac, /* i/o: higher limit for close-loop search */ + Word16 pit_min, + Word16 pit_fr1, + Word16 pit_fr1b, + Word16 pit_fr2, + Word16 pit_max, + Word16 pit_res_max +) +{ + Word32 pitch; + + IF(coder_type == 0) + { + *T0 = L_subfr; + move16(); + *T0_frac = 0; + move16(); + *T0_res = 1; + move16(); + } + ELSE IF(EQ_16(coder_type,1)) /* 8/4/4/4 (EVS) */ + { + IF (i_subfr == 0) + { + Mode2_abs_pit_dec( T0, T0_frac, T0_res, pt_indice, pit_min, pit_fr1b, pit_min, pit_res_max); + } + ELSE + { + limit_T0_voiced( 4, shr(pit_res_max,1), *T0, *T0_frac, *T0_res, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + *T0_res = shr(pit_res_max,1); + move16(); + Mode2_delta_pit_dec( T0, T0_frac, *T0_res, T0_min, T0_min_frac, pt_indice); + } + } + ELSE IF(EQ_16(coder_type,2)) /* 8/5/8/5 (EVS) */ + { + test(); + IF ( ( i_subfr == 0 ) || ( EQ_16(i_subfr,shl(L_subfr,1)))) + { + Mode2_abs_pit_dec( T0, T0_frac, T0_res, pt_indice, pit_min, pit_fr1b, pit_min, pit_res_max); + } + ELSE + { + limit_T0_voiced( 5, shr(pit_res_max,1), *T0, *T0_frac, *T0_res, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + *T0_res = shr(pit_res_max,1); + move16(); + Mode2_delta_pit_dec( T0, T0_frac, *T0_res, T0_min, T0_min_frac, pt_indice); + } + } + ELSE IF(EQ_16(coder_type,3)) /* 9/6/6/6 (HRs- VC) */ + { + Word16 pit_res_max2 = pit_res_max; + if ( EQ_16(pit_min,PIT_MIN_16k)) + { + pit_res_max2 = shr(pit_res_max,1); + } + + IF ( ( i_subfr == 0 ) ) + { + Mode2_abs_pit_dec( T0, T0_frac, T0_res, pt_indice, pit_min, pit_fr1, pit_fr2, pit_res_max); + } + ELSE + { + limit_T0_voiced( 6, pit_res_max2, *T0, 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + *T0_res = pit_res_max2; + move16(); + Mode2_delta_pit_dec( T0, T0_frac, *T0_res, T0_min, T0_min_frac, pt_indice); + } + } + ELSE IF(EQ_16(coder_type,4)) /* 9/6/9/6 (AMRWB) */ + { + Word16 pit_res_max2 = pit_res_max; + if ( EQ_16(pit_min,PIT_MIN_16k)) + { + pit_res_max2 = shr(pit_res_max,1); + } + test(); + IF ( ( i_subfr == 0 ) || ( EQ_16(i_subfr,shl(L_subfr,1)))) + { + Mode2_abs_pit_dec( T0, T0_frac, T0_res, pt_indice, pit_min, pit_fr1, pit_fr2, pit_res_max); + } + ELSE + { + limit_T0_voiced( 6, pit_res_max2, *T0, 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + *T0_res = pit_res_max2; + move16(); + Mode2_delta_pit_dec( T0, T0_frac, *T0_res, T0_min, T0_min_frac, pt_indice); + } + } + ELSE IF(EQ_16(coder_type,8)) /* 8/5/5/5 (RF all pred mode) */ + { + IF (i_subfr == 0) + { + Mode2_abs_pit_dec( T0, T0_frac, T0_res, pt_indice, pit_min, pit_fr1b, pit_min, pit_res_max); + } + ELSE + { + limit_T0_voiced( 5, shr(pit_res_max,1), *T0, *T0_frac, *T0_res, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + *T0_res = shr(pit_res_max,1); + Mode2_delta_pit_dec( T0, T0_frac, *T0_res, T0_min, T0_min_frac, pt_indice); + } + } + ELSE IF(EQ_16(coder_type,9)) /* 8/0/8/0 (RF gen pred mode) */ + { + IF (i_subfr == 0) + { + Mode2_abs_pit_dec( T0, T0_frac, T0_res, pt_indice, pit_min, pit_fr1b, pit_min, pit_res_max); + } + ELSE + { + limit_T0_voiced( 4, shr(pit_res_max,1), *T0, *T0_frac, *T0_res, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + *T0_res = shr(pit_res_max,1); + Mode2_delta_pit_dec( T0, T0_frac, *T0_res, T0_min, T0_min_frac, pt_indice); + } + } + ELSE + { + assert(0 && "LTP mode not supported"); + } + + /*-------------------------------------------------------* + * Compute floating pitch output + *-------------------------------------------------------*/ + assert(*T0_res > 0 || *T0_res <= 6); + + /*pitch = (float)(*T0) + (float)(*T0_frac)/(float)(*T0_res);*/ /* save subframe pitch values */ + pitch = L_mac(L_deposit_h(*T0), *T0_frac,inv_T0_res[*T0_res]); + + + return pitch; +} + + + +/*---------------------------------------------------------------------* + * Mode2_abs_pit_dec() + * + * Decode the absolute pitch + *---------------------------------------------------------------------*/ + +void Mode2_abs_pit_dec( + Word16 *T0, /* o: integer pitch lag */ + Word16 *T0_frac, /* o: pitch fraction */ + Word16 *T0_res, /* o: pitch resolution */ + Word16 **pt_indice, /* i/o: pointer to Vector of Q indexes */ + Word16 pit_min, + Word16 pit_fr1, + Word16 pit_fr2, + Word16 pit_res_max +) +{ + Word16 index; + Word16 pit_res_max_half, tmp1, tmp2, res; + + index = **pt_indice; + move16(); + (*pt_indice)++; + pit_res_max_half = shr(pit_res_max,1); + + tmp1 = i_mult(sub(pit_fr2,pit_min),pit_res_max); + tmp2 = i_mult(sub(pit_fr1,pit_fr2),pit_res_max_half); + IF (LT_16(index,tmp1)) + { + assert(pit_res_max > 1 && pit_res_max<=6); + + res = pit_res_max; + move16(); + if(EQ_16(pit_res_max,6)) + { + res =shr(res,1); + } + + *T0 = mult(index,inv_T0_res[res]); + if(EQ_16(pit_res_max,6)) + { + *T0 =shr(*T0,1); + } + + *T0 = add(pit_min,*T0); + move16(); + + *T0_frac = sub(index,i_mult(sub(*T0,pit_min),pit_res_max)); + move16(); + *T0_res = pit_res_max; + move16(); + } + ELSE IF (index < add(tmp1,tmp2) ) + { + assert(pit_res_max > 1); + + index = sub(index,tmp1); + *T0 = add(pit_fr2,mult(index,inv_T0_res[pit_res_max_half])); + move16(); + *T0_frac = sub(index, i_mult(sub(*T0,pit_fr2),pit_res_max_half)); + move16(); + *T0_res = pit_res_max_half; + move16(); + } + ELSE + { + *T0 = add(index,sub(pit_fr1,add(tmp1,tmp2))); + move16(); + *T0_frac = 0; + move16(); + *T0_res = 1; + move16(); + } + + return; +} + + +/*---------------------------------------------------------------------* + * Routine Mode2_delta_pit_dec() + * + * Decode delta pitch + *---------------------------------------------------------------------*/ +void Mode2_delta_pit_dec( + Word16 *T0, /* o: integer pitch lag */ + Word16 *T0_frac, /* o: pitch fraction */ + Word16 T0_res, /* i: pitch resolution */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_min_frac, /* i: delta search min */ + Word16 **pt_indice /* i/o: pointer to Vector of Q indexes */ +) +{ + Word16 index, res; + + assert(T0_res > 1 && T0_res<=6); + + res = T0_res; + move16(); + if(EQ_16(T0_res,6)) + { + res =shr(res,1); + } + + index = **pt_indice; + move16(); + (*pt_indice)++; + + + *T0 = mult(add(index,*T0_min_frac),inv_T0_res[res]); + if(EQ_16(T0_res,6)) + { + *T0 =shr(*T0,1); + } + + *T0 = add(*T0_min,*T0); + move16(); + + *T0_frac = add(index, sub(*T0_min_frac, i_mult(sub(*T0,*T0_min),T0_res))); + + return; +} + + +/*======================================================================*/ +/* FUNCTION : pit_decode_fx() */ +/*-----------------------------------------------------------------------*/ +/* PURPOSE : calculate pitch value */ +/* */ +/*-----------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word32) core_brate : Core bitrate Q0 */ +/* _ (Word16) Opt_AMR_WB : flag indicating AMR-WB IO mode Q0 */ +/* _ (Word16) L_frame : length of the frame Q0 */ +/* _ (Word16) i_subfr : length of the frame Q0 */ +/* _ (Word16) coder_type : coding type Q0 */ +/* _ (Word16) L_subfr : subframe length */ +/*-----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 *) T0 : close loop integer pitch */ +/* _ (Word16 *) T0_frac : close loop fractional part of the pitch */ +/* _ (Word16 ) pitch : pitch value Q6 */ +/*-----------------------------------------------------------------------*/ +/* INPUT OUTPUT ARGUMENTS */ +/* _ (Word16 *) T0_min : delta search min for sf 2 & 4 */ +/* _ (Word16 *) T0_max : delta search max for sf 2 & 4 */ +/*-----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word16 ) pitch : close loop integer pitch Q6 */ +/*=======================================================================*/ + + +Word16 pit_decode_fx( /* o : floating pitch value */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + Word16 i_subfr, /* i : subframe index */ + const Word16 coder_type, /* i : coding type */ + Word16 *limit_flag, /* i/o: restrained(0) or extended(1) Q limits */ + Word16 *T0, /* o : close loop integer pitch */ + Word16 *T0_frac, /* o : close loop fractional part of the pitch */ + Word16 *T0_min, /* i/o: delta search min for sf 2 & 4 */ + Word16 *T0_max, /* i/o: delta search max for sf 2 & 4 */ + const Word16 L_subfr /* i : subframe length */ +) +{ + Word16 pitch; /*Q2*/ + Word16 pitch_index, nBits, pit_flag; + + pitch_index = 0; + + /*----------------------------------------------------------------* + * Set pit_flag = 0 for every subframe with absolute pitch search + *----------------------------------------------------------------*/ + pit_flag = i_subfr; + move16(); + + if (EQ_16(i_subfr,PIT_DECODE_2XL_SUBFR)) + { + pit_flag = 0; + move16(); + } + + /*-------------------------------------------------------* + * Retrieve the pitch index + *-------------------------------------------------------*/ + IF( !Opt_AMR_WB ) + { + /*----------------------------------------------------------------* + * pitch Q: Set limit_flag to 0 for restrained limits, and 1 for extended limits + *----------------------------------------------------------------*/ + test(); + test(); + IF( i_subfr == 0 ) + { + *limit_flag = 1; + move16(); + + if( EQ_16(coder_type,VOICED)) + { + *limit_flag = 2; + move16(); /* double-extended limits */ + } + test(); + if( EQ_16(coder_type,GENERIC )&&EQ_32(core_brate,ACELP_7k20)) + { + *limit_flag = 0; + move16(); + } + } + ELSE IF( EQ_16(i_subfr,2*L_SUBFR)&&EQ_32(coder_type,GENERIC)&&LE_32(core_brate,ACELP_13k20)) + { + if( GT_16(*T0,shr(add(PIT_FR1_EXTEND_8b, PIT_MIN),1) )) + { + *limit_flag = 0; + move16(); + } + } + + /*-------------------------------------------------------* + * Retrieve the number of Q bits + *-------------------------------------------------------*/ + + nBits = 0; + move16(); + IF( NE_16(coder_type, AUDIO)) + { + /* find the number of bits */ + IF( EQ_16(L_frame,L_FRAME)) + { + nBits = ACB_bits_tbl[BIT_ALLOC_IDX_fx(core_brate, coder_type, i_subfr, 0)]; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + nBits = ACB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(core_brate, coder_type, i_subfr, 0)]; + move16(); + } + + pitch_index = (Word16)get_next_indice_fx( st_fx, nBits ); + move16(); + } + + /*-------------------------------------------------------* + * Pitch decoding in AUDIO mode + * (both ACELP@12k8 and ACELP@16k cores) + *-------------------------------------------------------*/ + IF( EQ_16(coder_type, AUDIO)) + { + test(); + if( EQ_16(L_subfr,L_FRAME/2)&&i_subfr!=0) + { + pit_flag = L_SUBFR; + move16(); + } + if( pit_flag == 0 ) + { + nBits = 10; + move16(); + } + if( pit_flag != 0 ) + { + nBits = 6; + move16(); + } + + pitch_index = (Word16)get_next_indice_fx( st_fx, nBits ); + move16(); + + test(); + test(); + IF( EQ_16(L_subfr,L_FRAME/2)&&i_subfr!=0&&GE_16(pitch_index,32)) /* safety check in case of bit errors */ + { + pitch_index = shr(pitch_index,1); + move16(); + st_fx->BER_detect = 1; + move16(); + } + + pit_Q_dec_fx( 0, pitch_index, nBits, 4, pit_flag, *limit_flag, T0, T0_frac, T0_min, T0_max, &st_fx->BER_detect ); + } + ELSE IF( EQ_16(coder_type,VOICED)) + { + /*-------------------------------------------------------* + * Pitch decoding in VOICED mode + * (ACELP@12k8 core only) + *-------------------------------------------------------*/ + if( EQ_16(i_subfr,2*L_SUBFR)) + { + pit_flag = i_subfr; + move16(); + } + + pit_Q_dec_fx( 0, pitch_index, nBits, 4, pit_flag, *limit_flag, T0, T0_frac, T0_min, T0_max, &st_fx->BER_detect ); + } + ELSE + { + /*-------------------------------------------------------* + * Pitch decoding in GENERIC mode + * (both ACELP@12k8 and ACELP@16k cores) + *-------------------------------------------------------*/ + IF( EQ_16(L_frame,L_FRAME)) + { + pit_Q_dec_fx( 0, pitch_index, nBits, 8, pit_flag, *limit_flag, T0, T0_frac, T0_min, T0_max, &st_fx->BER_detect ); + } + ELSE + { + pit16k_Q_dec_fx( pitch_index, nBits, *limit_flag, T0, T0_frac, T0_min, T0_max, &st_fx->BER_detect ); + } + } + } + + /*-------------------------------------------------------* + * Pitch decoding in AMR-WB IO mode + *-------------------------------------------------------*/ + + ELSE + { + *limit_flag = 0; + move16(); + test(); + test(); + IF( i_subfr == 0 || ( EQ_16(i_subfr, 2*L_SUBFR)&&EQ_32(core_brate,ACELP_8k85))) + { + nBits = 8; + move16(); + } + ELSE + { + nBits = 5; + move16(); + } + IF( GT_32(core_brate, ACELP_8k85)) + { + nBits = 6; + move16(); + test(); + if( i_subfr == 0 || EQ_16(i_subfr, 2*L_SUBFR)) + { + nBits = 9; + move16(); + } + } + + pitch_index = (Word16)get_next_indice_fx( st_fx, nBits ); + + pit_Q_dec_fx( 1, pitch_index, nBits, 8, pit_flag, *limit_flag, T0, T0_frac, T0_min, T0_max, &st_fx->BER_detect ); + } + + /*-------------------------------------------------------* + * Compute floating pitch output + *-------------------------------------------------------*/ + + pitch = shl(add(shl(*T0,2),*T0_frac),4); /* save subframe pitch values Q6 */ + + return pitch; +} + + +/*----------------------------------------------------------* + * pit_Q_dec_fx() + * + * Decode pitch lag + *----------------------------------------------------------*/ + +void pit_Q_dec_fx( + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 pitch_index, /* i : pitch index */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 delta, /* i : Half the CL searched interval */ + const Word16 pit_flag, /* i : absolute(0) or delta(1) pitch Q */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) Q limits */ + Word16 *T0, /* o : integer pitch lag */ + Word16 *T0_frac, /* o : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* i/o: delta search max */ + ,Word16 *BER_detect /* o : BER detect flag */ +) +{ + IF( EQ_16(nBits, 10)) /* absolute decoding with 10 bits */ + { + IF( limit_flag == 0 ) + { + *T0 = add(PIT_MIN,shr(pitch_index,2)); + *T0_frac = sub(pitch_index,shl(sub(*T0,PIT_MIN),2)); + } + ELSE IF( EQ_16(limit_flag,1)) + { + *T0 = add(PIT_MIN_EXTEND,shr(pitch_index,2)); + *T0_frac = sub(pitch_index ,shl(sub(*T0,PIT_MIN_EXTEND),2)); + } + ELSE /* limit_flag == 2 */ + { + *T0 = add(PIT_MIN_DOUBLEEXTEND,shr(pitch_index,2)); + *T0_frac = sub(pitch_index ,shl(sub(*T0,PIT_MIN_DOUBLEEXTEND),2)); + } + } + ELSE IF( EQ_16(nBits, 9)) /* absolute decoding with 9 bits */ + { + abs_pit_dec_fx( 4, pitch_index, limit_flag, T0, T0_frac ); + + /* find T0_min and T0_max for delta search */ + IF( Opt_AMR_WB ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, 0, *T0, 0, T0_min, T0_max ); /* T0_frac==0 to keep IO with AMR-WB */ + } + } + ELSE IF( EQ_16(nBits, 8)) /* absolute decoding with 8 bits */ + { + abs_pit_dec_fx( 2, pitch_index, limit_flag, T0, T0_frac ); + + /* find T0_min and T0_max for delta search */ + IF( Opt_AMR_WB ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, 0, *T0, 0, T0_min, T0_max ); /* T0_frac==0 to keep IO with AMR-WB */ + } + } + ELSE IF( EQ_16(nBits, 6)) /* relative decoding with 6 bits */ + { + delta_pit_dec_fx( 4, pitch_index, T0, T0_frac, *T0_min ); + } + ELSE IF( EQ_16(nBits, 5)) /* relative decoding with 5 bits */ + { + IF( EQ_16(delta,8)) + { + delta_pit_dec_fx( 2, pitch_index, T0, T0_frac, *T0_min ); + } + ELSE /* delta == 4 */ + { + delta_pit_dec_fx( 4, pitch_index, T0, T0_frac, *T0_min ); + } + } + ELSE /* nBits == 4 */ /* relative decoding with 4 bits */ + { + IF( EQ_16(delta,8)) + { + delta_pit_dec_fx( 0, pitch_index, T0, T0_frac, *T0_min ); + } + ELSE /* delta == 4 */ + { + delta_pit_dec_fx( 2, pitch_index, T0, T0_frac, *T0_min ); + } + } + + /* biterror detection mechanism */ + test(); + test(); + IF( GT_16(add((*T0<<2),*T0_frac),add((PIT_MAX<<2),2))&&pit_flag==0&&!Opt_AMR_WB) + { + *T0 = L_SUBFR; + move16(); + *T0_frac = 0; + move16(); + *BER_detect = 1; + move16(); + } + + IF( !Opt_AMR_WB ) + { + /* find T0_min and T0_max for delta search */ + limit_T0_fx( L_FRAME, delta, L_SUBFR, limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + + return; +} + +/*-------------------------------------------------* + * pit16k_Q_dec() + * + * pitch decoding @16kHz core + *-------------------------------------------------*/ + +void pit16k_Q_dec_fx( + const Word16 pitch_index, /* i : pitch index */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) limits */ + Word16 *T0, /* o : integer pitch lag */ + Word16 *T0_frac, /* o : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* i/o: delta search max */ + ,Word16 *BER_detect /* o : BER detect flag */ +) +{ + Word16 index; + + IF( EQ_16(nBits,10)) /* absolute decoding with 10 bits */ + { + { + IF( LT_16(pitch_index,shl((PIT16k_FR2_EXTEND_10b-PIT16k_MIN_EXTEND),2))) + { + *T0 = add(PIT16k_MIN_EXTEND, shr(pitch_index,2)); + move16(); + *T0_frac = sub(pitch_index, shl(sub(*T0, PIT16k_MIN_EXTEND),2)); + move16(); + } + ELSE + { + index = sub(pitch_index, shl((PIT16k_FR2_EXTEND_10b-PIT16k_MIN_EXTEND),2)); + *T0 = add(PIT16k_FR2_EXTEND_10b, shr(index,1)); + *T0_frac = sub(index, shl(sub(*T0, PIT16k_FR2_EXTEND_10b),1)); + /*(*T0_frac) *= 2;*/ + (*T0_frac) = shl(*T0_frac,1); + + } + } + + } + ELSE IF ( EQ_16(nBits,9)) /* absolute decoding with 9 bits */ + { + { + IF (LT_16(pitch_index,(PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4)) + { + *T0 = add(PIT16k_MIN_EXTEND, shr(pitch_index,2)); + move16(); + *T0_frac = sub(pitch_index, shl(sub(*T0, PIT16k_MIN_EXTEND),2)); + move16(); + } + ELSE IF (LT_16(pitch_index,( (PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4 + (PIT16k_FR1_EXTEND_9b-PIT16k_FR2_EXTEND_9b)*2))) + { + index = sub(pitch_index, (PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4); + *T0 = add(PIT16k_FR2_EXTEND_9b, shr(index,1)); + move16(); + *T0_frac = sub(index, shl(sub(*T0, PIT16k_FR2_EXTEND_9b),1)); + move16(); + (*T0_frac) *= shl((*T0_frac),1); + } + ELSE + { + *T0 = add(pitch_index, PIT16k_FR1_EXTEND_9b - ((PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4) - ((PIT16k_FR1_EXTEND_9b-PIT16k_FR2_EXTEND_9b)*2)); + move16(); + *T0_frac = 0; + move16(); + } + } + } + ELSE /* nBits == 6 */ /* relative decoding with 6 bits */ + { + delta_pit_dec_fx( 4, pitch_index, T0, T0_frac, *T0_min ); + } + + /* biterror detection mechanism */ + test(); + IF( GT_16(add((*T0<<2),*T0_frac),(PIT16k_MAX<<2))&&GE_16(nBits,9)) + { + *T0 = L_SUBFR; + move16(); + *T0_frac = 0; + move16(); + *BER_detect = 1; + move16(); + } + + /* find T0_min and T0_max for delta search */ + limit_T0_fx( L_FRAME16k, 8, L_SUBFR, limit_flag, *T0, *T0_frac, T0_min, T0_max ); + + return; +} + +/*----------------------------------------------------------* + * abs_pit_dec_fx() + * + * Absolute pitch decoding + *----------------------------------------------------------*/ + +void abs_pit_dec_fx( + const Word16 fr_steps, /* i: fractional resolution steps (0, 2, 4) */ + Word16 pitch_index, /* i: pitch index */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) limits */ + Word16 *T0, /* o: integer pitch lag */ + Word16 *T0_frac /* o: pitch fraction */ +) +{ + Word16 temp; + + IF( limit_flag == 0 ) + { + IF(EQ_16(fr_steps,2)) + { + IF(LT_16(pitch_index,PIT_FR1_8b_MINUS_PIT_MIN_X2)) + { + *T0= add(PIT_MIN,shr(pitch_index,1)); + move16(); + temp = shl(sub(*T0,PIT_MIN),1); + *T0_frac = shl(sub(pitch_index,temp),1); + move16(); + } + ELSE + { + *T0 = add(pitch_index,PIT_FR1_8b_MINUS_PIT_FR1_8b_MINUS_PIT_MIN_X2); + move16(); + *T0_frac = 0; + move16(); + } + } + ELSE IF( EQ_16(fr_steps,4)) + { + IF(LT_16(pitch_index,PIT_FR2_9b_MINUS_PIT_MIN_X4)) + { + *T0= add(PIT_MIN,shr(pitch_index,2)); + move16(); + temp = shl(sub(*T0,PIT_MIN),2); + *T0_frac = sub(pitch_index,temp); + move16(); + } + ELSE IF (LT_16(pitch_index,PIT_DECODE_1)) /*( (PIT_FR2_9b-PIT_MIN)*4 + (PIT_FR1_9b-PIT_FR2_9b)*2) = 440*/ + { + pitch_index = sub(pitch_index,PIT_DECODE_2); /*pitch_index -= (PIT_FR2_9b-PIT_MIN)*4(=376);*/ + *T0 = add(PIT_FR2_9b,shr(pitch_index,1)); + move16(); + temp = shl(sub(*T0,PIT_FR2_9b),1); + *T0_frac = shl(sub(pitch_index,temp),1); + move16(); + } + ELSE + { + *T0 = add(pitch_index,PIT_DECODE_3); + move16(); + *T0_frac = 0; + move16(); + } + } + ELSE /* fr_steps == 0 */ + { + /* not used in the codec */ + } + } + ELSE IF( EQ_16(limit_flag, 1)) /* extended Q range */ + { + IF( EQ_16(fr_steps,2)) + { + IF( LT_16(pitch_index, PIT_FR1_EXT8b_MINUS_PIT_MIN_EXT_X2)) + { + *T0 = add(PIT_MIN_EXTEND, shr(pitch_index,1)); + move16(); + *T0_frac = sub(pitch_index, shl(sub(*T0, PIT_MIN_EXTEND),1)); + *T0_frac = shl(*T0_frac, 1); + move16(); + } + ELSE + { + *T0 = add(pitch_index, sub(PIT_FR1_EXTEND_8b, PIT_FR1_EXT8b_MINUS_PIT_MIN_EXT_X2)); + move16(); + *T0_frac = 0; + move16(); + } + } + ELSE IF( EQ_16(fr_steps,4)) + { + IF( LT_16(pitch_index, PIT_FR2_EXT9b_MINUS_PIT_MIN_EXT_X4)) + { + /**T0 = PIT_MIN_EXTEND + (pitch_index/4);*/ + *T0 = add(PIT_MIN_EXTEND, shr(pitch_index,2)); + move16(); + /**T0_frac = pitch_index - (*T0 - PIT_MIN_EXTEND)*4;*/ + *T0_frac = sub(pitch_index, shl(sub(*T0, PIT_MIN_EXTEND),2)); + move16(); + } + ELSE IF( LT_16(pitch_index,add(PIT_FR2_EXT9b_MINUS_PIT_MIN_EXT_X4, PIT_FR1_EXT9b_MINUS_PIT_FR2_EXT9b_X2))) + { + /*pitch_index -= (PIT_FR2_EXTEND_9b-PIT_MIN_EXTEND)*4;*/ + pitch_index = sub(pitch_index, PIT_FR2_EXT9b_MINUS_PIT_MIN_EXT_X4); + *T0 = add(PIT_FR2_EXTEND_9b, shr(pitch_index,1)); + *T0_frac = sub(pitch_index, shl(sub(*T0, PIT_FR2_EXTEND_9b),1)); + (*T0_frac) = shl(*T0_frac,1); + move16(); + } + ELSE + { + /**T0 = pitch_index + PIT_FR1_EXTEND_9b - ((PIT_FR2_EXTEND_9b-PIT_MIN_EXTEND)*4) - ((PIT_FR1_EXTEND_9b-PIT_FR2_EXTEND_9b)*2);move16();*/ + *T0 = add(pitch_index, PIT_DECODE_7); + move16(); + *T0_frac = 0; + move16(); + } + } + ELSE /* fr_steps == 0 */ + { + /* not used in the codec */ + } + } + ELSE /* limit_flag == 2 */ + { + IF( EQ_16(fr_steps,2)) + { + IF( LT_16(pitch_index,PIT_FR1_DEXT8b_MINUS_PIT_MIN_DEXT_X2)) + { + *T0 = add(PIT_MIN_DOUBLEEXTEND, shr(pitch_index,1)); + move16(); + *T0_frac = sub(pitch_index, shl(sub(*T0, PIT_MIN_DOUBLEEXTEND),1)); + move16(); + *T0_frac = shl(*T0_frac,1); + move16(); + } + ELSE + { + /**T0 = pitch_index + PIT_FR1_DOUBLEEXTEND_8b - ((PIT_FR1_DOUBLEEXTEND_8b-PIT_MIN_DOUBLEEXTEND)*2);move16();*/ + *T0 = add(pitch_index, PIT_DECODE_8); + move16(); + *T0_frac = 0; + move16(); + } + } + ELSE IF( EQ_16(fr_steps,4)) + { + IF( LT_16(pitch_index, PIT_FR2_DEXT9b_MINUS_PIT_MIN_DEXT_X4)) + { + *T0 = add(PIT_MIN_DOUBLEEXTEND, shr(pitch_index,2)); + move16(); + *T0_frac = sub(pitch_index, shl(sub(*T0, PIT_MIN_DOUBLEEXTEND),2)); + move16(); + } + ELSE IF( LT_16(pitch_index,PIT_DECODE_9)) + { + /*pitch_index -= (PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4;move16();*/ + pitch_index = sub(pitch_index , PIT_FR2_DEXT9b_MINUS_PIT_MIN_DEXT_X4); + move16(); + *T0 = add(PIT_FR2_DOUBLEEXTEND_9b, shr(pitch_index,1)); + move16(); + *T0_frac = sub(pitch_index, shl(sub(*T0, PIT_FR2_DOUBLEEXTEND_9b),1)); + move16(); + (*T0_frac) = shl(*T0_frac,1); + move16(); + } + ELSE + { + *T0 = add(pitch_index, PIT_DECODE_10); + move16(); + *T0_frac = 0; + move16(); + } + } + ELSE /* fr_steps == 0 */ + { + /* not used in the codec */ + } + } + + return; +} + +/*----------------------------------------------------------* + * delta_pit_dec_fx() + * + * Delta pitch decoding + *----------------------------------------------------------*/ + +void delta_pit_dec_fx( + const Word16 fr_steps, /* i : fractional resolution steps (0, 2, 4) */ + const Word16 pitch_index, /* i : pitch index */ + Word16 *T0, /* o : integer pitch lag */ + Word16 *T0_frac, /* o : pitch fraction */ + const Word16 T0_min /* i : delta search min */ +) +{ + + Word16 temp; + IF( fr_steps == 0 ) + { + *T0 = add(T0_min,pitch_index); + move16(); + *T0_frac = 0; + move16(); + } + ELSE IF( EQ_16(fr_steps,2)) + { + *T0 = add(T0_min,shr(pitch_index,1)); + move16(); + temp = shl(sub(*T0,T0_min),1); + *T0_frac = shl(sub(pitch_index,temp),1); + move16(); + } + ELSE IF ( EQ_16(fr_steps,4)) + { + *T0 = add(T0_min,shr(pitch_index,2)); + move16(); + temp = shl(sub(*T0,T0_min),2); + *T0_frac = sub(pitch_index,temp); + move16(); + } + + return; +} diff --git a/lib_dec/pitch_extr.c b/lib_dec/pitch_extr.c new file mode 100644 index 0000000..f647f64 --- /dev/null +++ b/lib_dec/pitch_extr.c @@ -0,0 +1,328 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +/*This file is up to date with trunk rev. 36531*/ + +#include +#include +#include +#include "cnst_fx.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "stl.h" +#include "options.h" + + + +/*-------------------------------------------------------------------* + * - num x 32768 + * ------------------- Q15 + * PIT_MAX x Fact + *-------------------------------------------------------------------*/ + +#define PIT_MAX_DIV_8k(num, fact) ( -(num * 32768) / (PIT_MAX_12k8 * fact) ) +#define PIT_MAX_DIV_12k8(num, fact) ( -(num * 32768) / (PIT_MAX_12k8 * fact) ) +#define PIT_MAX_DIV_16k(num, fact) ( -(num * 32768) / (PIT_MAX_16k * fact) ) + + +/*-----------------------------------------------------------------* + * Pitch prediction for frame erasure using linear fitting * + *-----------------------------------------------------------------*/ +/*port is up to date with trunk 38840*/ +void pitch_pred_linear_fit( + const Word16 /*short*/ bfi_cnt, /* i: bfi counter */ /*Q0 */ + const Word16 /*short*/ last_good, /* i: last classification type */ /*Q0 */ + Word32 /*float*/ *old_pitch_buf, /* i: pitch lag buffer */ /*Q16*/ + Word32 /*float*/ *old_fpitch, /* i: */ /*Q16*/ + Word32 /*float*/ *T0_out, /* o: estimated close loop pitch */ /*Q16*/ + Word16 /* int*/ pit_min, /* i: Minimum pitch lag */ /*Q0 */ + Word16 /* int*/ pit_max, /* i: Maximum pitch lag */ /*Q0 */ + Word16 /*float*/ *mem_pitch_gain, /* i: pitch gain [0] is the most recent subfr gain */ /*Q14*/ + Word16 /* int*/ limitation, + Word8 /*short*/ plc_use_future_lag, /* i: */ /*Q0 */ + Word16 /*short*/ *extrapolationFailed,/* o: flag if extrap decides not to change the pitch */ /*Q0 */ + Word16 nb_subfr /* i: number of ACELP subframes*/ +) +{ + Word32 pit, a, b, pita, pitb; + Word16 sum0; + Word32 T0; + Word32 mdy, dy[5]; + Word16 lcor; + Word16 imax, i; + Word16 pg[8]; /* local buffer for pitch gain*/ + Word32 ml[8]; /* local buffer for mem_lag*/ + Word16 const timeWeight[5] = {20480/*1.25f Q14*/, 18432/*1.125f Q14*/, 16384/*1.f Q14*/, 14336/*0.875f Q14*/, 12288/*.75f Q14*/}; /*Q14*/ + Word16 no_subfr_pred; + Word16 a1, a2, a3, a4, a5, tmpa, tmpb, b1, b2, b3, b4, b5; + Word16 a_e, b_e, sum0_q; + Word32 mem_lag[2*NB_SUBFR16k+2]; + + + /* Inverse the order the pitch lag memory */ + IF ( EQ_16(nb_subfr, 4)) + { + FOR (i = 0; i < 2*NB_SUBFR+2; i++) + { + mem_lag[i] = old_pitch_buf[2*NB_SUBFR+1 - i]; + move32(); + } + } + ELSE /* L_frame == L_FRAME16k */ + { + FOR (i = 0; i < 2*NB_SUBFR16k+2; i++) + { + mem_lag[i] = old_pitch_buf[2*NB_SUBFR16k+1 - i]; + move32(); + } + } + move16(); + move16(); + move16(); + move16(); + move16(); /*timeweight*/ + + IF (LT_16(pit_max,extract_h(*old_fpitch)) ) + { + *extrapolationFailed = 1; + *T0_out = pit_max; + return; + } + + move16(); + lcor = 5; + T0 = L_deposit_l(0); + + test(); + test(); + IF (EQ_16(bfi_cnt , 1)&&GE_16(last_good,UNVOICED_TRANSITION)&<_16(last_good,ONSET)) + { + move16(); + no_subfr_pred = 4; + if (plc_use_future_lag!=0) + { + move16(); + no_subfr_pred = 2; + } + + /* copy to local buffers, depending on availability of info about future subframes */ + Copy(mem_pitch_gain+no_subfr_pred-2,pg,8); + Copy32(mem_lag+no_subfr_pred-2,ml,8); + + mdy = L_deposit_l(0); + + FOR (i = (sub(lcor,1)); i >= 0; i--) + { + move32(); + dy[i] = L_sub(ml[i] , ml[i+1]); + mdy = L_add(mdy , dy[i]); + } + + /*---------------------------------------------------* + * remove maximum variation + *---------------------------------------------------*/ + move16(); + imax = 0; + pita = L_abs(dy[0]); + FOR (i = 1; i Q9*/),mult_r(pg[3],16384/*Q12->Q11*/))/*Q5*/; + a4 = mac_r(L_mac(L_mult( mult_r(-12*2048,pg[0])/*Q8*/,pg[3] /*Q12*/)/*Q5+16*/,mult_r(-6*2048,pg[1])/*Q8*/,pg[3]/*Q12*/)/*Q5+16*/,mult_r(-2*2048,pg[2])/*Q8*/,pg[3]/*Q12*/)/*Q5*/; + a3 = mac_r(L_mac(L_mult( mult_r(-8*2048,pg[0]) /*Q8*/,pg[2]),mult_r(-3*2048,pg[1])/*Q8*/,pg[2]),mult_r(pg[2],4096/*Q12->Q9*/),mult_r(pg[3],16384/*12->Q11*/));/*Q5*/ + a2 = mac_r(L_mac(L_mult( mult_r(2*2048,pg[1]) /*Q8*/,pg[2])/*Q5+16*/,mult_r(2*2048,pg[1])/*Q8*/,pg[3])/*Q5+16*/,mult_r(-4*2048,pg[0])/*Q8*/,pg[1]/*Q12*/)/*Q5*/; + a1 = mac_r(L_mac(L_mult( mult_r(3*2048,pg[0]) /*Q8*/,pg[1])/*Q5+16*/,mult_r(4*2048,pg[0])/*Q8*/,pg[2]/*Q12*/)/*Q5+16*/,mult_r(3*2048,pg[0])/*Q8*/,pg[3]/*Q12*/)/*Q5*/; + + a = L_mac(L_mac(L_mac(L_mac(L_mult(a1 + , round_fx(L_shl(ml[0],4)))/*Q4*/ + , round_fx(L_shl(ml[1],4)) /*Q4*/, a2) + , round_fx(L_shl(ml[2],4)) /*Q4*/, a3) + , round_fx(L_shl(ml[3],4)) /*Q4*/, a4) + , round_fx(L_shl(ml[4],4)) /*Q4*/, a5); /*Q-6+16 = Q10*/ + + a_e = norm_l(a); + a = L_shl(a, a_e); + + a1 = BASOP_Util_Divide3216_Scale(L_negate(a), /* Numerator */ /*scalefactor 21*/ + sum0, /* Denominator*/ /*scalefactor 10*/ + &tmpa); /* scalefactor for result */ + + /* Float: + b=(( pg[1]+2*pg[2]+3*pg[3]+4*pg[4])*pg[0] *//*b1*//* + *ml[0] + + (( pg[2]+2*pg[3]+3*pg[4])*pg[1]-pg[1]*pg[0]) *//*b2*//* + *ml[1] + + ( -2*pg[2]*pg[0]-pg[2]*pg[1]+(pg[3]+2*pg[4])*pg[2]) *//*b3*//* + *ml[2] + + ( -3*pg[3]*pg[0]-2*pg[3]*pg[1]-pg[3]*pg[2]+pg[4]*pg[3]) *//*b4*//* + *ml[3] + + ( -4*pg[4]*pg[0]-3*pg[4]*pg[1]-2*pg[4]*pg[2]-pg[4]*pg[3]) *//*b5*//* + *ml[4] )/sum0; MAC(22);MULT(9);DIV(1);*/ + + /*magic numbers in Q13 if not DIRECTLY marked otherwise*/ + b1 = mac_r(L_mac(L_mac(L_mult(mult_r(pg[1],pg[0]),32768/4)/*Q7+16*/,mult_r(2*8192,pg[0])/*Q10*/,pg[2]/*Q12*/)/*Q7+16*/,mult_r(3*8192,pg[0])/*Q10*/,pg[3]/*Q12*/)/*Q7+16*/, /*mult_r(4*8192,pg[0])*/ pg[0]/*Q10*/,pg[4]/*Q12*/)/*Q7*/; + b2 = mac_r(L_mac(L_mac(L_mult(mult_r(pg[2],pg[1]),32768/4)/*Q7+16*/,mult_r(2*8192,pg[1]),pg[3]),mult_r(3*8192,pg[1]),pg[4])/*Q7+16*/,mult_r(pg[1],-32768/2/*Q12->Q12*/),mult_r(pg[0],32768/2/*Q12->Q10*/))/*Q7*/; + b3 = mac_r(L_mac(L_mac(L_mult(mult_r(-2*8192,pg[0]),pg[2])/*Q7+16*/,mult_r(pg[2],-32768/2),mult_r(pg[1],32768/2)),mult_r(pg[3],32768/2),mult_r(pg[2],32768/2))/*Q5+16*/,mult_r(2*8192,pg[2]),pg[4])/*Q7*/; + b4 = mac_r(L_mac(L_mac(L_mult(mult_r(-3*8192,pg[0]),pg[3]),mult_r(-2*8192,pg[1]),pg[3]),mult_r(-32768/2,pg[3]),mult_r(32768/2,pg[2])),mult_r(32768/2,pg[4]),mult_r(32768/2,pg[3]));/*Q7*/ + b5 = mac_r(L_mac(L_mac(L_mult(mult_r(-32768/*(-4*8192)*/,pg[0]),pg[4]),mult_r(-3*8192,pg[1]),pg[4]),mult_r(-2*8192,pg[2]),pg[4]),mult_r(-32768/2,pg[4]),mult_r(32768/2,pg[3]))/*Q7*/; + + b = L_mac(L_mac(L_mac(L_mac(L_mult(b1 + , round_fx(L_shl(ml[0],4)))/*Q4*/ + , round_fx(L_shl(ml[1],4)) /*Q4*/, b2) + , round_fx(L_shl(ml[2],4)) /*Q4*/, b3) + , round_fx(L_shl(ml[3],4)) /*Q4*/, b4) + , round_fx(L_shl(ml[4],4)) /*Q4*/, b5); /*Q-4+16 = Q12*/ + /*predict pitch for 4th future subframe*/ + + b_e = norm_l(b); + b = L_shl(b, b_e); + + b1 = BASOP_Util_Divide3216_Scale(b, /* Numerator */ /*scalefactor 19*/ + sum0, /* Denominator*/ /*scalefactor 10*/ + &tmpb); /* scalefactor for result*/ + + /*pit = a + b * ((float)no_subfr_pred + (float)nb_subfr);*/ + pita = L_shl( L_deposit_l(a1),add(add(sum0_q, 16-10+1),sub(tmpa, a_e)))/*Q16*/; + pitb = L_shl_r(L_mult(b1/*Q15*/,add(no_subfr_pred,nb_subfr)/*Q0*/ ),add(add(sum0_q, 16-12),sub(tmpb, b_e))); + pit = L_add( pita , pitb ); /*Q16*/ + + T0 = L_add(pit, 0); + + /*limit pitch to allowed range*/ + + T0 = L_min(L_deposit_h(pit_max),T0); + T0 = L_max(L_deposit_h(pit_min),T0); + + move16(); + *extrapolationFailed = 0; + } + ELSE + { + T0 = L_deposit_l(0); + *extrapolationFailed = 1; + move16(); + } + } + ELSE + { + + T0 = L_deposit_l(0); + move16(); + *extrapolationFailed = 1; + } + } + ELSE + { + T0 = L_add(*old_fpitch, 0); + move16(); + *extrapolationFailed = 1; + } + move32(); + *T0_out = T0; + + return; +} + +/* up to date with rev 8158*/ +void get_subframe_pitch( + Word16 nSubframes, /* i: number of subframes */ /* Q0 */ + Word32 pitchStart, /* i: starting pitch lag (in subframe -1) */ /*15Q16*/ + Word32 pitchEnd, /* i: ending pitch lag (in subframe nSubframes-1) */ /*15Q16*/ + Word32 *pitchBuf /* o: interpolated pitch lag per subframe */ /*15Q16*/ +) +{ + Word16 i,s; + Word32 pitchDelta; + + assert((nSubframes > 0) && (pitchBuf != NULL) && (pitchStart >= 0) && (pitchEnd > 0)); + + /*pitchDelta = (pitchEnd - pitchStart)/nSubframes;*/ + pitchDelta = L_deposit_l(BASOP_Util_Divide3216_Scale(L_sub(pitchEnd,pitchStart),nSubframes, &s));/*Q15*/ + pitchDelta = L_shl(pitchDelta,add(s,1));/*Q16*/ + pitchBuf[0] = L_add(pitchStart,pitchDelta); + FOR (i = 1; i < nSubframes; i++) + { + pitchBuf[i] = L_add(pitchBuf[i-1] , pitchDelta); + move32(); + } +} + diff --git a/lib_dec/post_dec.c b/lib_dec/post_dec.c new file mode 100644 index 0000000..b92e222 --- /dev/null +++ b/lib_dec/post_dec.c @@ -0,0 +1,619 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + + +#include +#include +#include +#include "options.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "stl.h" + + +/*---------------------------------------------------------------------* + * Function prototypes + *---------------------------------------------------------------------*/ + +static void bass_pf_1sf_delay( Word16 *syn, Word16 *T_sf, Word16 *gainT_sf, Word16 l_frame, + Word16 l_subfr, Word16 *bpf_noise_buf, Word16 *gain_factor_param, + Word8 disable_bpf, Word32 *lp_error_ener, Word32 *mem_error ); + +/*---------------------------------------------------------------------* + * post_decoder() + * + * Perform post-processing + *---------------------------------------------------------------------*/ + +void post_decoder( + Decoder_State_fx *st, + Word16 coder_type, + Word16 synth_buf[], + Word16 pit_gain[], + Word16 pitch[], + Word16 signal_out[], + Word16 *bpf_noise_buf +) +{ + Word16 L_frame, nb_subfr; + Word16 *synth, *synth2; + Word16 pfstat_on_previous; + Word16 pitch_gain_adjust[NB_SUBFR16k]; + Word16 tmp, tmp_noise; + Word16 synth2_pe[L_FRAME_MAX]; + Word16 synth_buf2[PIT_MAX_16k+1+L_FRAME_MAX+M]; + Word32 bitrate; + Word8 tmp8; + + + L_frame = st->L_frame_fx; + move16(); + nb_subfr = st->nb_subfr; + move16(); + pfstat_on_previous = st->pfstat.on; + move16(); + st->pfstat.on = 0; + move16(); + + bitrate = L_add(st->total_brate_fx, 0); + if(st->core_brate_fx <= SID_2k40) + { + bitrate = L_add(st->last_active_brate_fx, 0); + } + + + /*Adapt Bpf: copy old and current adapt bpf parameters*/ + set16_fx(pitch_gain_adjust, st->bpf_gain_param, nb_subfr); + + synth = synth_buf + st->old_synth_len; + synth2 = synth_buf2 + NBPSF_PIT_MAX; + Copy( st->pst_old_syn_fx, synth_buf2, NBPSF_PIT_MAX ); + + IF ( st->tcxonly != 0 ) + { + Copy( synth, synth2, L_frame ); + IF ( pfstat_on_previous ) + { + Copy( st->pfstat.mem_pf_in+L_SYN_MEM-M, synth-M, M ); + Residu3_fx ( st->old_Aq_12_8_fx, synth, synth_buf, L_SUBFR, 1 ); + E_UTIL_synthesis ( 1, st->old_Aq_12_8_fx, synth_buf, synth2, L_SUBFR, st->pfstat.mem_stp+L_SYN_MEM-M, 0, M ); + scale_st ( synth, synth2, &st->pfstat.gain_prec, L_SUBFR ); + blend_subfr2(synth2+L_SUBFR/2, synth+L_SUBFR/2, synth2+L_SUBFR/2); + } + } + ELSE + { + /*Formant enhancement*/ + IF ( EQ_16(st->last_bwidth_fx,NB)) + { + Copy( synth, synth2_pe, L_frame ); + tmp = synth[-1]; + move16(); + + preemph_copy_fx( synth2_pe, synth2_pe, st->preemph_fac, L_frame, &tmp); + + tmp = 0; + move16(); + test(); + test(); + if ((GT_32(st->lp_noise, LP_NOISE_THRESH))|| + (st->core_fx != ACELP_CORE) || + (EQ_16(coder_type, UNVOICED))) + { + tmp = 1; + move16(); + } + + if(pfstat_on_previous==0) + { + st->pfstat.reset = 1; + move16(); + } + IF ( EQ_16(st->bwidth_fx,NB)) + { + st->pfstat.on = 1; + move16(); + tmp_noise = 0; + nb_post_filt( L_frame, &(st->pfstat), &tmp_noise, 0, synth2_pe, st->mem_Aq, pitch, GENERIC, st->BER_detect, tmp ); + } + ELSE + { + st->pfstat.on = 0; + move16(); + tmp_noise = 0; + nb_post_filt( L_frame, &(st->pfstat), &tmp_noise, 0, synth2_pe, st->mem_Aq, pitch, AUDIO, st->BER_detect, tmp ); + } + + Copy(synth2_pe, synth2, L_frame); + + tmp = synth2[-1]; + move16(); + deemph_fx( synth2, st->preemph_fac, L_frame, &tmp ); + } + ELSE + { + if(pfstat_on_previous==0) + { + st->pfstat.reset = 1; + move16(); + } + IF ( GE_16(st->last_bwidth_fx,WB)) + { + st->pfstat.on = 1; + move16(); + formant_post_filt( &(st->pfstat), synth, st->mem_Aq, synth2, L_frame, st->lp_noise, bitrate, 0 ); + } + ELSE + { + st->pfstat.on = 0; + move16(); + formant_post_filt( &(st->pfstat), synth, st->mem_Aq, synth2, L_frame, st->lp_noise, bitrate, 1 ); + } + } + + /*Bass Post-filter */ + tmp8 = 0; + move16(); + test(); + if( GT_32(st->lp_noise,LP_NOISE_THRESH)&&st->narrowBand) + { + tmp8 = 1; + move16(); + } + bass_pf_1sf_delay( synth2, pitch, pit_gain, L_frame, L_SUBFR, bpf_noise_buf, pitch_gain_adjust, + tmp8, &(st->lp_error_ener), &(st->mem_error) ); + } + + /* Output */ + Copy( synth2, signal_out, L_frame ); + + /* Update synth2 memory */ + Copy( synth_buf2 + L_frame, st->pst_old_syn_fx, NBPSF_PIT_MAX ); + + + return; +} + + +/*---------------------------------------------------------------------* + * bass_pf_1sf_delay() + * + * Perform low-frequency postfiltering + *---------------------------------------------------------------------*/ + +static void bass_pf_1sf_delay( + Word16 *syn, /* (i) : 12.8kHz synthesis to postfilter Q0 */ + Word16 *T_sf, /* (i) : Pitch period for all subframes (T_sf[16]) Q0 */ + Word16 *gainT_sf, /* (i) : Pitch gain for all subframes (gainT_sf[16]) Q14 */ + Word16 l_frame, /* (i) : frame length (should be multiple of l_subfr) Q0 */ + Word16 l_subfr, /* (i) : sub-frame length (60/64) Q0 */ + Word16 *bpf_noise_buf, /* (i) : harmoninc filtered signal Q0 */ + Word16 *gain_factor_param, /* (i) : gain factor param 0-> no BPF, 3-> full BPF */ + Word8 disable_bpf, + Word32 *lp_error_ener, + Word32 *mem_error +) +{ + Word16 i, sf, i_subfr, T, lg, s1, st, tmp16; + Word16 gain; + Word32 tmp, nrg, lp_error, tmp32; + Word32 ener2; + + + assert(bpf_noise_buf != NULL); + + sf = 0; + move16(); + lp_error = L_shl(*mem_error, 0); + + FOR (i_subfr = 0; i_subfr < l_frame; i_subfr += l_subfr) + { + T = T_sf[sf]; + move16(); + + lg = sub(sub(l_frame, T), i_subfr); + if (lg < 0) + { + lg = 0; + move16(); + } + if (lg > l_subfr) + { + lg = l_subfr; + move16(); + } + + test(); + IF (disable_bpf == 0 && gainT_sf[sf] > 0) + { + /* get headroom for used part of syn */ + tmp16 = add(l_subfr, T); + if (lg>0) + { + tmp16 = add(lg, shl(T, 1)); + } + s1 = getScaleFactor16(syn + sub(i_subfr, T), tmp16); + s1 = sub(s1, 3); + + tmp = L_deposit_l(1); + nrg = L_deposit_l(1); + + IF (lg > 0) + { + + { + Word64 tmp64 = W_deposit32_l( tmp ); + Word64 nrg64 = W_deposit32_l( nrg ); + FOR (i = 0; i < lg; i++) + { + tmp32 = L_mult(syn[i+i_subfr-T], 0x4000); + tmp32 = L_mac(tmp32, syn[i+i_subfr+T], 0x4000); + tmp16 = round_fx(L_shl(tmp32, s1)); /* Q0+s1 */ + + tmp64 = W_mac0_16_16(tmp64, shl(syn[i+i_subfr], s1), tmp16); /* Q0+2*s1 */ + nrg64 = W_mac0_16_16(nrg64, tmp16, tmp16); /* Q0+2*s1 */ + } + tmp = W_sat_l(tmp64); + nrg = W_sat_l(nrg64); + } + + } + + IF (LT_16(lg, l_subfr)) + { + + { + Word64 tmp64 = W_deposit32_l( tmp ); + Word64 nrg64 = W_deposit32_l( nrg ); + FOR (i = lg; i < l_subfr; i++) + { + tmp16 = shl(syn[i+i_subfr-T], s1); /* Q0+s1 */ + tmp64 = W_mac0_16_16(tmp64, shl(syn[i+i_subfr], s1), tmp16); /* Q0+2*s1 */ + nrg64 = W_mac0_16_16(nrg64, tmp16, tmp16); /* Q0+2*s1 */ + } + tmp = W_sat_l(tmp64); + nrg = W_sat_l(nrg64); + } + + } + + /* gain = tmp/nrg; */ + gain = BASOP_Util_Divide3232_Scale(tmp, nrg, &tmp16); + BASOP_SATURATE_WARNING_OFF; + gain = shl(gain, tmp16); /* Q15 */ + BASOP_SATURATE_WARNING_ON; + + if (gain < 0) + { + gain = 0; + move16(); + } + + st = sub(norm_l(lp_error), 3); + test(); + if ((LT_16(st, s1))&&(lp_error!=0)) + { + s1 = st; + move16(); + } + + ener2 = L_deposit_l(0); + + IF (lg > 0) + { + + { + Word64 ener2_64 = W_deposit32_l( ener2 ); + FOR (i = 0; i < lg; i++) + { + tmp32 = L_msu0(0, gain, syn[i+i_subfr-T]); + tmp32 = L_msu0(tmp32, gain, syn[i+i_subfr+T]); + tmp16 = mac_r(tmp32, gain, syn[i+i_subfr]); /* Q0 */ + + lp_error = Mpy_32_16_1(lp_error, 29491/*0.9f Q15*/); + lp_error = L_mac(lp_error, tmp16, 0x1000); /* Q13 */ + + tmp16 = round_fx(L_shl(lp_error, s1)); /* Q0+s1-3 */ + ener2_64 = W_mac0_16_16(ener2_64, tmp16, tmp16); /* Q0+(s1-3)*2 */ + } + ener2 = W_sat_l(ener2_64); + } + + } + + IF (LT_16(lg, l_subfr)) + { + + { + Word64 ener2_64 = W_deposit32_l( ener2 ); + FOR (i = lg; i < l_subfr; i++) + { + tmp32 = L_mult0(gain, syn[i+i_subfr]); + tmp32 = L_msu0(tmp32, gain, syn[i+i_subfr-T]); /* Q0 */ + tmp16 = round_fx(tmp32); + + lp_error = Mpy_32_16_1(lp_error, 29491/*0.9f Q15*/); + lp_error = L_mac(lp_error, tmp16, 0x1000); /* Q13 */ + + tmp16 = round_fx(L_shl(lp_error, s1)); /* Q0+s1-3 */ + ener2_64 = W_mac0_16_16(ener2_64, tmp16, tmp16); /* Q0+(s1-3)*2 */ + } + ener2 = W_sat_l(ener2_64); + } + + } + + st = shl(sub(s1, 3), 1); + + IF (ener2 > 0) + { + ener2 = L_shr(BASOP_Util_Log2(ener2), 9); /* 15Q16 */ + ener2 = L_add(ener2, L_deposit_h(sub(31, st))); + } + ELSE + { + ener2 = L_add(0xFFF95B2C, 0); /* log2(0.01) (15Q16) */ + } + + *lp_error_ener = L_add(Mpy_32_16_1(L_sub(*lp_error_ener, ener2), 32440/*0.99f Q15*/), ener2); /* 15Q16 */ + + st = add(st, 6); + ener2 = L_sub(*lp_error_ener, L_deposit_h(sub(31, st))); + IF (ener2 >= 0) + { + tmp16 = add(extract_h(ener2), 1); + ener2 = L_sub(ener2, L_deposit_h(tmp16)); + tmp = L_shr(tmp, tmp16); + nrg = L_shr(nrg, tmp16); + } + ener2 = BASOP_Util_InvLog2(L_shl(ener2, 9)); /* Q0+2*s1 */ + + tmp32 = L_add(L_shr(nrg, 1), L_shr(ener2, 1)); + if (tmp32 == 0) tmp32 = L_deposit_l(1); + tmp16 = BASOP_Util_Divide3232_Scale(tmp, tmp32, &st); + BASOP_SATURATE_WARNING_OFF; + tmp16 = shl(tmp16, sub(st, 2)); /* Q15 */ + + if (GT_16(tmp16, 16384/*0.5f Q15*/)) + { + tmp16 = 16384/*0.5f Q15*/; + move16(); + } + if (tmp16 < 0) + { + tmp16 = 0; + move16(); + } + BASOP_SATURATE_WARNING_ON; + + /*Adjust gain*/ + /* full gain = gainLTP*0.5*/ + /* adaptive gain = gainLTP*0.5*max(0.5f*gain_factor_param[sf],0.125f)*/ + tmp16 = round_fx(L_shl(L_mult0(tmp16, s_max(shl(gain_factor_param[sf],2),1)),13)); + + + /* calculate noise based on voiced pitch */ + IF (lg > 0) + { + FOR (i = 0; i < lg; i++) + { + tmp32 = L_msu0(0, tmp16, syn[i+i_subfr-T]); + tmp32 = L_msu0(tmp32, tmp16, syn[i+i_subfr+T]); + tmp32 = L_mac(tmp32, tmp16, syn[i+i_subfr]); + bpf_noise_buf[i+i_subfr] = round_fx(tmp32); /* Q0 */ + } + } + + IF (LT_16(lg, l_subfr)) + { + FOR (i = lg; i < l_subfr; i++) + { + tmp32 = L_mult0(tmp16, syn[i+i_subfr]); + tmp32 = L_msu0(tmp32, tmp16, syn[i+i_subfr-T]); + bpf_noise_buf[i+i_subfr] = round_fx(tmp32); /* Q0 */ + } + } + } + ELSE + { + set16_fx(bpf_noise_buf+i_subfr, 0, l_subfr); + } + + sf = add(sf, 1); + } + + *mem_error = lp_error; + move32(); + + + return; +} + +/*---------------------------------------------------------------------* + * cldfb_synth_set_bandsToZero() + * + * + *---------------------------------------------------------------------*/ + +void cldfb_synth_set_bandsToZero( + Decoder_State_fx *st, + Word32 **rAnalysis, + Word32 **iAnalysis, + const Word16 nTimeSlots, + const CLDFB_SCALE_FACTOR scaleFactor +) +{ + Word32 nrgQ31; + Word32 nrg_band[CLDFB_NO_CHANNELS_MAX], tempQ31, max_nrg; + Word16 realQ1, imagQ1, flag, offset, WBcnt; + Word16 perc_detect, perc_miss; + Word16 i, k, tmp1, tmp2, tmp3, tmp, update_perc; + + realQ1 = 0; + move16(); + imagQ1 = 0; + move16(); + + set32_fx( nrg_band, 0, CLDFB_NO_CHANNELS_MAX ); + max_nrg = 0; + + offset = 250; + WBcnt = 20; + perc_miss = 13107; /*0.80 in Q14*/ + perc_detect = 14746; /*0.90 in Q14*/ + + IF(EQ_16(st->VAD,1)) + { + st->active_frame_cnt_bwddec = add(st->active_frame_cnt_bwddec,1); + st->total_frame_cnt_bwddec = add(st->total_frame_cnt_bwddec,1); + if(GT_16(st->active_frame_cnt_bwddec, 99)) + { + st->active_frame_cnt_bwddec = 100; + move16(); + } + if(GT_16(st->total_frame_cnt_bwddec, 500)) + { + st->total_frame_cnt_bwddec = 500; + move16(); + } + + FOR (i = 0; i < (st->cldfbSyn_fx->no_channels - st->cldfbSyn_fx->bandsToZero); i++) + { + nrgQ31 = 0; + move32(); + FOR (k = 0; k < nTimeSlots; k++) + { + /* use 16-bit precision of real and imag buffers */ + realQ1 = extract_l(L_shr(rAnalysis[k][i], 31-(15+scaleFactor.lb_scale)+3)); + imagQ1 = extract_l(L_shr(iAnalysis[k][i], 31-(15+scaleFactor.lb_scale)+3)); /* Q(-3), headroom */ + nrgQ31 = L_mac0(nrgQ31, realQ1, realQ1); + nrgQ31 = L_mac0(nrgQ31, imagQ1, imagQ1); /* keep in Q(-6) */ + } + nrg_band[i] = (nrgQ31); + move16(); + test(); + if(GT_32(nrg_band[i], max_nrg)&&GE_16(i,11)) + { + max_nrg = nrg_band[i]; + move16(); + } + } + FOR(; i < st->cldfbSyn_fx->no_channels; i++) + { + nrg_band[i] = 0; + move16(); + } + + nrgQ31 = 0; + move16(); + FOR(i = 2; i < 9; i++) + { + nrgQ31 = L_add(nrgQ31, Mult_32_16(nrg_band[i], 4681)); + } + + tempQ31 = L_shr(nrgQ31,9); + + st->avg_nrg_LT = L_add(Mult_32_16(st->avg_nrg_LT, 32440), Mult_32_16(tempQ31, 327)); /*0.99*avg_nrg_LT + 0.01*tempQ31*/ + update_perc = 1; + move16(); + if(st->ini_frame_fx >= 25 && tempQ31 < Mult_32_16(st->avg_nrg_LT, 164)) + { + update_perc = 0; + move16(); + } + + flag = 1; + move16(); + if(max_nrg >= tempQ31) + { + flag = 0; + move16(); + } + + FOR(i = 0; i < WBcnt-1; i++) + { + st->flag_buffer[i] = st->flag_buffer[i+1]; + move16(); + } + st->flag_buffer[WBcnt-1] = flag; + move16(); + + /*long term percentage*/ + IF(EQ_16(update_perc, 1)) + { + IF(flag != 0) + { + tmp1 = sub(16384, st->perc_bwddec); /*Q14*/ + + tmp = norm_s(st->active_frame_cnt_bwddec); + tmp3 = shl(st->active_frame_cnt_bwddec, tmp); /*Qtmp*/ + + tmp2 = div_s(16384,tmp3); /* 1/active_frames in Q15 + Q14 - Qtmp = Q29 - Qtmp */ + tmp2 = mult_r(tmp2, tmp1); /*(1-perc)*(1/active_frames) in Q14 + Q29 - Qtmp - Q15 = Q28 - Qtmp*/ + st->perc_bwddec = add(st->perc_bwddec, shl(tmp2, sub(tmp, 14))); /* Q14 */ + } + ELSE + { + tmp1 = (st->perc_bwddec); /*Q14*/ + + tmp = norm_s(st->active_frame_cnt_bwddec); + tmp3 = shl(st->active_frame_cnt_bwddec, tmp); /*Qtmp*/ + + tmp2 = div_s(16384,tmp3); /* 1/active_frames in Q15 + Q14 - Qtmp = Q29 - Qtmp */ + tmp2 = mult_r(tmp2, tmp1); /*(perc)*(1/active_frames) in Q14 + Q29 - Qtmp - Q15 = Q28 - Qtmp*/ + st->perc_bwddec = sub(st->perc_bwddec, shl(tmp2, sub(tmp, 14))); /* Q14 */ + } + } + test(); + IF(GT_16(st->total_frame_cnt_bwddec, offset)&>_16(st->active_frame_cnt_bwddec,50)) + { + IF( (st->perc_bwddec >= perc_detect || (st->perc_bwddec >= perc_miss && st->last_flag_filter_NB)) && (sum16_fx(st->flag_buffer, WBcnt) != 0)) /*decision hysterysis*/ + { + st->cldfbSyn_fx->bandsToZero = sub( st->cldfbSyn_fx->no_channels, 10 ); + move16(); + st->last_flag_filter_NB = 1; + move16(); /*VAD processing must be dependent on hysterysis, as if hysterysis fails, but threshold passes, we dont want next vad frames to have NB only*/ + } + ELSE + { + st->last_flag_filter_NB = 0; + move16(); + } + } + ELSE + { + st->last_flag_filter_NB = 0; + move16(); + } + IF(sum16_fx(st->flag_buffer, WBcnt) == 0) + { + st->perc_bwddec = 0; + st->active_frame_cnt_bwddec = 0; + move16(); + st->total_frame_cnt_bwddec = 0; + move16(); + st->last_flag_filter_NB = 0; + move16(); + } + } + ELSE + { + IF(st->last_flag_filter_NB == 1) + { + st->cldfbSyn_fx->bandsToZero = st->last_active_bandsToZero_bwdec; + move16(); + } + st->total_frame_cnt_bwddec = add(st->total_frame_cnt_bwddec, 1); + if(GT_16(st->total_frame_cnt_bwddec, 500)) + { + st->total_frame_cnt_bwddec = 500; + move16(); + } + } + + st->last_active_bandsToZero_bwdec = st->cldfbSyn_fx->bandsToZero; + + return; +} diff --git a/lib_dec/ppp_dec_fx.c b/lib_dec/ppp_dec_fx.c new file mode 100644 index 0000000..5031b0e --- /dev/null +++ b/lib_dec/ppp_dec_fx.c @@ -0,0 +1,162 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "stl.h" + + +/*===================================================================*/ +/* FUNCTION : void ppp_quarter_decoder_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ Word16 bfi_fx - Q0 bad frame indicator */ +/* _ const Word16 *curr_lpc_fx - Q12 current frame LPC */ +/* _ Word16 *exc_fx - Q0 previous frame excitation */ +/* _ Word16 prevCW_lag_fx - Q0 Previous lag */ +/* _ (struct DTFS_fx) PREV_CW_D_FX : prototype in polar domain */ +/* (Word16) lag: length of prototype in time domain */ +/* (Word16 []) a: amplitude of harmonics, normalized */ +/* (Word16) Q: norm factor of a */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ Decoder_State_fx *st_fx: */ +/* _ Word16 *pitch - Q6 floating pitch values for each subframe */ +/* _ Word16 *out_fx - Q0 residual signal */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ Decoder_State_fx *st_fx: */ +/* _ lsp_old_fx - Q15 */ +/* _ st_fx->dtfs_dec_xxxx */ +/* _ gainp_ppp Q14 */ +/* _ lastLgainD_fx - Q11 */ +/* _ lastHgainD_fx - Q11 */ +/* _ lasterbD_fx - Q13 */ +/* _ (struct DTFS_fx) CURRCW_Q_DTFS_FX : prototype in polar domain*/ +/* (Word16) lag: length of prototype in time domain */ +/* (Word16 []) a: amplitude of harmonics, normalized */ +/* (Word16) Q: norm factor of a */ +/* _ Word16 *pitch_buf_fx - Q6 fixed pitch values for each subframe */ +/* _ Word16 *exc_fx - Q0 previous frame excitation */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : RX */ +/*===================================================================*/ + +void ppp_quarter_decoder_fx( + DTFS_STRUCTURE_FX *CURRCW_Q_DTFS_FX, /* i/o: Current CW DTFS */ + Word16 prevCW_lag_fx, /* i : Previous lag */ + Word16 *lastLgainD_fx, /* i/o: Last gain lowband Q11 */ + Word16 *lastHgainD_fx, /* i/o: Last gain highwband Q11 */ + Word16 *lasterbD_fx, /* i/o: Last ERB vector Q13 */ + Word16 bfi, /* i : FER flag */ + Word16 *S_fx, /* i : sine table, Q15 */ + Word16 *C_fx, /* i : cosine table, Q15 */ + DTFS_STRUCTURE_FX PREV_CW_D_FX, /* i : Previous DTFS */ + Decoder_State_fx *st_fx +) +{ + DTFS_STRUCTURE_FX *PREVDTFS_FX = DTFS_new_fx(); + Word16 AMP_IDX_fx[2]; + Word16 temp_pl_fx = prevCW_lag_fx, temp_l_fx = CURRCW_Q_DTFS_FX->lag_fx; + Word16 temp_fx; + Word16 l_fx = CURRCW_Q_DTFS_FX->lag_fx; + Word16 POWER_IDX_fx; + Word16 Erot_fx = 0; + Word16 num_erb_fx = 24; + Word32 temp32d_fx,temp32n_fx; + Word32 L_tmp, L_tmp1; + Word16 tmp, exp; + + + IF ( EQ_16(CURRCW_Q_DTFS_FX->upper_cut_off_freq_fx,4000 )) + { + num_erb_fx = 22; + move16(); + } + ELSE IF ( EQ_16(CURRCW_Q_DTFS_FX->upper_cut_off_freq_fx,6400)) + { + num_erb_fx = 24; + move16(); + } + + DTFS_copy_fx(PREVDTFS_FX, PREV_CW_D_FX); + IF (bfi == 0) + { + POWER_IDX_fx =(Word16) get_next_indice_fx( st_fx, 6); + move16(); + AMP_IDX_fx[0] =(Word16) get_next_indice_fx( st_fx, 6); + move16(); + AMP_IDX_fx[1] =(Word16) get_next_indice_fx( st_fx, 6); + move16(); + + /* Amplitude Dequantization */ + /*This normalization and de-normalization is done to avoid division by 12800. And this logic is used only in + dequant_cw. So upper cut-off frequencies need to be multiplied by a factor2.56. + This logic of normalisation is not employed in adjustlag, hence denormalisation is necessury.*/ + /*As the upper cut of freqencies are normalized to 12800, we have to multiply upper cut off freq by + 2.56(1/12800 in Q15) */ + temp32n_fx = L_mult(CURRCW_Q_DTFS_FX->upper_cut_off_freq_fx,10486);/* Q0+Q27 = Q28 */ + CURRCW_Q_DTFS_FX->upper_cut_off_freq_fx = (Word16)L_shr(temp32n_fx,13);/*Q15 */ + temp32n_fx = L_mult(CURRCW_Q_DTFS_FX->upper_cut_off_freq_of_interest_fx,10486);/* Q0+Q27 = Q28 */ + CURRCW_Q_DTFS_FX->upper_cut_off_freq_of_interest_fx = (Word16)L_shr(temp32n_fx,13);/*Q15 */ + + DTFS_dequant_cw_fx(prevCW_lag_fx,POWER_IDX_fx,AMP_IDX_fx,lastLgainD_fx,lastHgainD_fx,lasterbD_fx,CURRCW_Q_DTFS_FX,num_erb_fx); + /*De-normalize cut off frequencies */ + + temp32n_fx = L_shl((Word32)CURRCW_Q_DTFS_FX->upper_cut_off_freq_fx,13);/*Q28 */ + CURRCW_Q_DTFS_FX->upper_cut_off_freq_fx = (Word16)find_remd(temp32n_fx, 20971,&temp32d_fx); + temp32n_fx = L_shl((Word32)CURRCW_Q_DTFS_FX->upper_cut_off_freq_of_interest_fx,13);/*Q28 */ + CURRCW_Q_DTFS_FX->upper_cut_off_freq_of_interest_fx = (Word16)find_remd(temp32n_fx, 20971,&temp32d_fx); + } + + /* Copying phase spectrum over */ + DTFS_adjustLag_fx(PREVDTFS_FX,l_fx); + + temp_fx = sub(L_FRAME,temp_l_fx); /*Q0 */ + + exp = norm_s(temp_pl_fx); + tmp = div_s(shl(1,sub(14,exp)),temp_pl_fx); /*Q(29-exp) */ + L_tmp = L_mult(temp_fx,tmp); /*Q(31-exp); +1 due to /2 */ + L_tmp = L_shl(L_tmp,sub(exp,15)); /*Q16 */ + + exp = norm_s(temp_l_fx); + tmp = div_s(shl(1,sub(14,exp)),temp_l_fx); /*Q(29-exp) */ + L_tmp1 = L_mult(temp_fx,tmp); /*Q(31-exp); +1 due to /2 */ + L_tmp1 = L_shl(L_tmp1,sub(exp,15)); /*Q16 */ + + L_tmp = L_add(L_tmp,L_tmp1); /*Q16 */ + + tmp = lshr(extract_l(L_tmp),1); /*Q15 */ + L_tmp = L_mult(temp_l_fx,tmp); /*Q16 */ + temp_fx = rint_new_fx(L_tmp); + Erot_fx = sub(temp_l_fx,temp_fx); /*Q0 */ + + Q2phaseShift_fx(PREVDTFS_FX,shl(Erot_fx,2),CURRCW_Q_DTFS_FX->lag_fx,S_fx,C_fx); + IF ( EQ_16(bfi,1)) + { + DTFS_car2pol_fx(CURRCW_Q_DTFS_FX); + } + /*Phase copying is done through copy_phase instead of car2pol and pol2car */ + copy_phase_fx(PREVDTFS_FX,*CURRCW_Q_DTFS_FX,CURRCW_Q_DTFS_FX); + + { + temp_fx = (Word16) get_next_indice_fx( st_fx, 3 ); + + temp_fx = sub(temp_fx,3); + temp_fx = shl(temp_fx,2);/*Q2 */ + Q2phaseShift_fx(CURRCW_Q_DTFS_FX,temp_fx,CURRCW_Q_DTFS_FX->lag_fx,S_fx,C_fx); + } + + free(PREVDTFS_FX); + + return; +} + diff --git a/lib_dec/pvq_core_dec_fx.c b/lib_dec/pvq_core_dec_fx.c new file mode 100644 index 0000000..a3e1361 --- /dev/null +++ b/lib_dec/pvq_core_dec_fx.c @@ -0,0 +1,556 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" +#include "basop_util.h" + +static Word16 get_pvq_splits_fx(Decoder_State_fx *st_fx, const Word16 band_bits, const Word16 sfmsize, Word16 *bits); + +static void densitySymbolIndexDecode_fx(Decoder_State_fx *st_fx, const Word16 density, const Word16 opp_sz, const Word16 near_sz, Word16 *index_phi); + +/* Decode band with PVQ */ +static void pvq_decode_band_fx( + Decoder_State_fx *st_fx, + Word16 *pulse_vector, + Word16 *npulses, + Word16 *coefs_quant, + const Word16 sfmsize, + const Word16 band_bits, + Word16 *bits_left, + const Word16 strict_bits +) +{ + + Word16 K_val; + + Word16 j, Np; + Word16 part_start[MAX_SPLITS+1], dim_part[MAX_SPLITS+1], bits_part[MAX_SPLITS+1]; + Word16 pool_tot, pool_part, dim_parts; + Word16 g_part[MAX_SPLITS]; + Word16 g_part_neg[MAX_SPLITS]; + Word16 sg_part[MAX_SPLITS+1]; + Word16 idx_sort[MAX_SPLITS+1]; + Word16 js, band_bits_tot, split_bit; + Np = get_pvq_splits_fx(st_fx, band_bits, sfmsize, &split_bit); + band_bits_tot = sub(band_bits, split_bit); + + dim_parts = extract_h(L_mult(negate(sfmsize),lim_neg_inv_tbl_fx[Np])); + set16_fx(dim_part, dim_parts, sub(Np, 1)); + dim_part[Np-1] = sub(sfmsize, i_mult2(dim_parts, sub(Np, 1))); + move16(); + + part_start[0] = 0; + move16(); + FOR (j = 1; j < Np; j++) + { + part_start[j] = add(part_start[j-1], dim_part[j-1]); + move16(); + } + + /* Encode energies */ + set16_fx( g_part_neg, -32768, Np ); + IF( GT_16(Np, 1)) + { + decode_energies_fx( st_fx, Np, dim_part, bits_part, g_part_neg, band_bits_tot, bits_left, sfmsize, strict_bits ); + } + ELSE + { + bits_part[0] = band_bits_tot; + move16(); + } + + pool_tot = 0; + move16(); + pool_part = 0; + move16(); + BASOP_SATURATE_WARNING_OFF + FOR (j = 0; j < Np; j++) + { + g_part[j] = negate(g_part_neg[j]); + } + BASOP_SATURATE_WARNING_ON + srt_vec_ind16_fx(g_part, sg_part, idx_sort, Np); + FOR(j = 0; j < Np; j++) + { + js = idx_sort[Np-1-j]; + pool_part = shrtCDivSignedApprox(pool_tot, sub(Np, j) ); + bits_part[js] = s_max(0, s_min(add(bits_part[js], pool_part), 256)); + move16(); + + conservativeL1Norm_fx(dim_part[js],bits_part[js], strict_bits, *bits_left, pool_tot , *npulses, /* inputs */ + &K_val, bits_left, &pool_tot, npulses); /* outputs */ + + IF( K_val > 0 ) + { + + pvq_decode_fx(st_fx, coefs_quant + part_start[js], pulse_vector + part_start[js], + K_val, dim_part[js], g_part_neg[js]); + } + ELSE + { + set16_fx(coefs_quant + part_start[js], 0, dim_part[js]); + set16_fx(pulse_vector + part_start[js], 0, dim_part[js]); + } + } + + return; +} + +void pvq_decode_frame_fx( + Decoder_State_fx *st_fx, + Word16 *coefs_quant, /* o : quantized coefficients */ + Word16 *npulses, /* o : number of pulses per band */ + Word16 *pulse_vector, /* o : non-normalized pulse shapes */ + const Word16 *sfm_start, /* i : indices of first coefficients in the bands */ + const Word16 *sfm_end, /* i : indices of last coefficients in the bands */ + const Word16 *sfmsize, /* i : band sizes */ + const Word16 nb_sfm, /* i : total number of bands */ + const Word16 *R, /* i : bitallocation per band */ + const Word16 pvq_bits, /* i : number of bits avaiable */ + const Word16 core /* i : core */ +) +{ + Word16 i, j; + Word16 band_bits, bits_left; + Word16 bit_pool = 0; + Word16 coded_bands, bands_to_code; + Word16 bits; + Word16 R_sort[NB_SFM]; + Word16 is, i_sort[NB_SFM]; + Word16 strict_bits; + + rc_dec_init_fx(st_fx, pvq_bits); + + bits = shl(sub(pvq_bits, RC_BITS_RESERVED), 3); + + bands_to_code = 0; + move16(); + FOR (i = 0; i < nb_sfm; i++) + { + if (R[i] > 0) + { + bands_to_code = add(bands_to_code, 1); + } + } + + IF (core == ACELP_CORE) + { + strict_bits = 1; + move16(); + srt_vec_ind16_fx (R, R_sort, i_sort, nb_sfm); + } + ELSE + { + strict_bits = 0; + move16(); + FOR (i = 0; i < nb_sfm; i++) + { + i_sort[i] = i; + move16(); + } + } + + coded_bands = 0; + move16(); + FOR (i = 0; i < nb_sfm; i++) + { + is = i_sort[i]; + move16(); + IF(R[is] > 0) + { + bandBitsAdjustment_fx(st_fx->rc_num_bits_fx, st_fx->rc_range_fx, bits, bands_to_code, bands_to_code-coded_bands, sfmsize[is] ,R[is], bit_pool, /* inputs */ + &band_bits, &bits_left, &bit_pool); /* outputs */ + + pvq_decode_band_fx( st_fx, &pulse_vector[sfm_start[is]], &npulses[is], + &coefs_quant[sfm_start[is]], sfmsize[is], band_bits, + &bits_left, strict_bits); + + /* Updates */ + coded_bands = add(coded_bands, 1); + } + ELSE + { + FOR (j = sfm_start[is]; j < sfm_end[is]; j++) + { + coefs_quant[j] = 0; + move16(); + pulse_vector[j] = 0; + move16(); + } + } + } + + rc_dec_finish_fx(st_fx); +} + +/*-------------------------------------------------------------------* + * pvq_core_dec() + * + *-------------------------------------------------------------------*/ + +Word16 pvq_core_dec_fx( + Decoder_State_fx *st_fx, + const Word16 *sfm_start, + const Word16 *sfm_end, + const Word16 *sfmsize, + Word16 coefs_quant[], /* o : output MDCT */ + Word16 *Q_coefs, + Word16 bits_tot, + Word16 nb_sfm, + Word16 *R, /* Q3 */ + Word16 *Rs, + Word16 *npulses, + Word16 *maxpulse, + const Word16 core +) +{ + Word16 i; + Word16 R_upd; + Word16 ord[NB_SFM_MAX]; + Word16 pulse_vector[L_FRAME48k]; + Word16 pvq_bits; + Word16 gain_bits_array[NB_SFM]; + Word16 fg_pred[NB_SFM_MAX]; + + st_fx->ber_occured_in_pvq = 0; + move16(); + + R_upd = shl(bits_tot, 3); + assign_gain_bits_fx( core, nb_sfm, sfmsize, R, gain_bits_array, &R_upd ); + + pvq_bits = shr(R_upd, 3); + + pvq_decode_frame_fx(st_fx, coefs_quant, npulses, pulse_vector, sfm_start, + sfm_end, sfmsize, nb_sfm, R, pvq_bits, core ); + + IF( Rs != NULL ) + { + FOR(i = 0; i < nb_sfm; i++) + { + if (npulses[i] <= 0) + { + Rs[i] = 0; + move16(); /* Update Rs in case no pulses were assigned */ + } + } + } + + FOR (i=0; i < nb_sfm; i++) + { + ord[i] = i; + move16(); + if (npulses[i] <= 0) + { + R[i] = 0; + move16(); /* Update in case no pulses were assigned */ + } + } + + get_max_pulses_fx( sfm_start, sfm_end, ord, npulses, nb_sfm, pulse_vector, maxpulse ); + + fine_gain_pred_fx( sfm_start, sfm_end, sfmsize, ord, npulses, maxpulse, R, + nb_sfm, coefs_quant, pulse_vector, fg_pred, core ); + + fine_gain_dec_fx( st_fx, ord, nb_sfm, gain_bits_array, fg_pred); + + IF( st_fx->ber_occured_in_pvq != 0 ) + { + set16_fx( fg_pred, 1, nb_sfm ); /* low complex ECU action in case of detetected BER in PVQ decoding */ + } + apply_gain_fx(ord, sfm_start, sfm_end, nb_sfm, fg_pred, coefs_quant); + *Q_coefs = 12; + + return bits_tot; +} + +void decode_energies_fx( + Decoder_State_fx *st_fx, + Word16 Np, + Word16 *dim_part, + Word16 *bits_part, + Word16 *g_part, /* Q15 */ + short qband, + Word16 *bits_left, + Word16 dim, + const Word16 strict_bits +) +{ + Word16 density; + Word16 i, l_Np, r_Np; + Word16 l_bits, r_bits, l_dim, r_dim; + Word16 il, ir; + Word16 oppRQ3, qzero; + Word16 l_gain, r_gain; + Word16 index_phi=-1; + + l_Np = shr(Np, 1); + r_Np = sub(Np, l_Np); + + l_bits = 0; + move16(); + l_dim = 0; + move16(); + FOR (i = 0; i < l_Np; i++) + { + l_dim = add(l_dim, dim_part[i]); + } + r_dim = sub(dim, l_dim); + + obtainEnergyQuantizerDensity_fx(dim, qband, &density); + rangeCoderFinalizationFBits_fx(st_fx->rc_num_bits_fx, st_fx->rc_range_fx, &qzero); + + densitySymbolIndexDecode_fx( st_fx, density, r_dim, l_dim, &index_phi); + densityAngle2RmsProjDec_fx(density, index_phi, &ir, &il, &oppRQ3); + + + + + l_gain = il; /* Q15 */ move16(); + r_gain = ir; /* Q15 */ move16(); + + FOR (i = 0; i < l_Np; i++) + { + g_part[i] = mult_r(l_gain, g_part[i]); + move16(); + } + + FOR (i = l_Np; i < Np; i++) + { + g_part[i] = mult_r(r_gain, g_part[i]); + move16(); + } + + NearOppSplitAdjustment_fx( qband, qzero, st_fx->rc_num_bits_fx, st_fx->rc_range_fx, *bits_left, + strict_bits, Np, dim_part[0], dim_part[Np-1], + l_dim, r_dim, oppRQ3, + &l_bits, &r_bits, bits_left); + + + IF (GT_16(l_Np, 1)) + { + decode_energies_fx( st_fx, l_Np, dim_part, bits_part, g_part, l_bits, bits_left, l_dim, strict_bits ); + } + ELSE + { + bits_part[0] = l_bits; + move16(); + } + + IF (GT_16(r_Np, 1)) + { + decode_energies_fx( st_fx, r_Np, &dim_part[l_Np], &bits_part[l_Np], &g_part[l_Np], r_bits, bits_left, r_dim, strict_bits ); + } + ELSE + { + bits_part[1] = r_bits; + move16(); + } + + return; +} + +static void densitySymbolIndexDecode_fx(Decoder_State_fx *st_fx, + const Word16 density, + const Word16 opp_sz, + const Word16 near_sz, + Word16 *index_phi + ) +{ + Word16 density1, density2; + Word32 tmp1; + Word16 tmp2; + Word16 c, density_alpha, density_c; + Word32 sym_freq, cum_freq, tot, dec_freq; + Word16 angle, expo, r; + UWord16 lsb; + Word32 acc; + Word16 alpha=0; + + IF( s_and((Word16)0xFFFE, density) == 0 ) + { + /* odd density exit */ + *index_phi = -1; + return; + } + + sym_freq = L_deposit_l(1); + + angle = atan2_fx(SQRT_DIM_fx[opp_sz], SQRT_DIM_fx[near_sz]); + angle = shl(angle, 1); + angle = mult_r(angle, 20861); + c = mult_r(density, angle); + density_c = sub(density, c); + + tot = L_mac0(1L, density, add(density, 1)); + IF (c == 0) + { + dec_freq = rc_decode_fx(st_fx, tot); + + density1 = add(density, 1); + acc = L_mult0(density1, density1); + acc = L_sub(acc, dec_freq); + alpha = add(getSqrtWord32(acc), density1); + sym_freq = L_mac(1L, sub(density, alpha), 1); + cum_freq = L_mac0(L_mult(alpha, density), alpha, 1); + } + ELSE IF (EQ_16(c, density)) + { + dec_freq = rc_decode_fx(st_fx, tot); + + alpha = getSqrtWord32(dec_freq); + sym_freq = L_add(L_shl(alpha, 1), 1); + cum_freq = L_mult0(alpha, alpha); + } + ELSE + { + acc = L_mult0(density, c); + Mpy_32_16_ss(acc, density_c, &acc, &lsb); + acc = L_or(L_shl(acc, 16), L_and(lsb, 0xffffL)); /* Concatenate acc and lsb forming 48 bits; upshift 16 bits; keep 32 MSB. */ + acc = L_shr(acc, 1); /* Compensate fractional mode multiply (Mpy_32_16_ss) */ + tot = L_add(L_add(acc, (Word32)density), 1L); + + dec_freq = rc_decode_fx(st_fx, tot); + + acc = L_mult0(sub(density_c, 1), density_c); + Mpy_32_16_ss(acc, c, &acc, &lsb); + acc = L_or(L_shl(acc, 16), L_and(lsb, 0xffffL)); /* Concatenate acc and lsb forming 48 bits; upshift 16 bits; keep 32 MSB. */ + acc = L_shr(acc, 1); /* Compensate fractional mode multiply (Mpy_32_16_ss) */ + acc = L_add(acc, L_add(density, 1)); + acc = L_sub(acc, L_add(c, 1)); + acc = L_sub(tot, acc); + IF (LT_32(dec_freq, acc )) + { + acc = L_add((Word32)density_c, L_shl(dec_freq, 2)); + acc = L_sub(acc, 2); + Mpy_32_16_ss(acc, density_c, &acc, &lsb); + acc = L_or(L_shl(acc, 16), L_and(lsb, 0xffffL)); /* Concatenate acc and lsb forming 48 bits; upshift 16 bits; keep 32 MSB. */ + acc = L_shr(acc, 1); /* Compensate fractional mode multiply (Mpy_32_16_ss) */ + acc = L_add(acc, 1); + tmp2 = getSqrtWord32(acc); + acc = L_add(density_c, tmp2); + acc = L_sub(acc, 1); + r = ratio(acc, L_shl(density_c,1), &expo); + alpha = shr(r, add(14, expo)); + + acc = L_mult(alpha, density_c); + sym_freq = L_add(acc, 1); + acc = L_mult0(sub(alpha, 1), density_c); + acc = L_add(acc, 1); + cum_freq = L_mult0(alpha, extract_l(acc)); + } + ELSE + { + density1 = add(density, 1); + density2 = add(shl(density, 1), 1); + + acc = L_mult0(density, density1); + Mpy_32_16_ss(acc, c, &acc, &lsb); + acc = L_or(L_shl(acc, 16), L_and(lsb, 0xffffL)); /* Concatenate acc and lsb forming 48-bit; upshift 16 bits; keep 32 MSB. */ + acc = L_shr(acc, 1); /* Compensate fractional mode multiply (Mpy_32_16_ss) */ + acc = L_add(density1, acc); + acc = L_add(dec_freq, acc); + acc = L_sub(tot, acc); + Mpy_32_16_ss(acc, c, &acc, &lsb); + acc = L_or(L_shl(acc, 16), L_and(lsb, 0xffffL)); + acc = L_shr(acc, 1 - 2); + + tmp2 = extract_l(L_mac0(1L, c, density2)); + tmp1 = L_mult0(tmp2, tmp2); + tmp1 = L_add(tmp1, acc); + tmp2 = getSqrtWord32(tmp1); /* floor */ + if (L_msu0(tmp1, tmp2, tmp2) != 0) + { + tmp2 = add(tmp2, 1); /* convert to ceil */ + } + + acc = L_mult0(c, density2); + acc = L_add(acc, 1); + acc = L_sub(acc, tmp2); + r = ratio(acc, L_shl(c, 1), &expo); + alpha = shr(r, add(14, expo)); + + density_alpha = sub(density, alpha); + sym_freq = L_mac(1L, density_alpha, c); + acc = L_mult0(density_alpha, add(density_alpha, 1)); + Mpy_32_16_ss(acc, c, &acc, &lsb); + acc = L_or(L_shl(acc, 16), L_and(lsb, 0xffffL)); /* Concatenate acc and lsb forming 48-bit; upshift 16 bits; keep 32 MSB. */ + acc = L_shr(acc, 1); /* Compensate fractional mode multiply (Mpy_32_16_ss) */ + acc = L_sub(acc, alpha); + acc = L_add(acc, density1); + cum_freq = L_sub(tot, acc); + } + } + + rc_dec_update_fx(st_fx, cum_freq, sym_freq); + *index_phi = alpha; + return; +} + + +/*--------------------------------------------------------------------------* + * get_pvq_splits() + * + * Retrieve the number of segments + *--------------------------------------------------------------------------*/ + +static Word16 get_pvq_splits_fx( /* o : Number of segments */ + Decoder_State_fx *st_fx, /* i/o: Decoder state */ + const Word16 band_bits, /* i : Band bit rate */ + const Word16 sfmsize, /* i : Band width */ + Word16 *bits /* o : Used bits */ +) +{ + Word16 Np, i; + Word32 acc, flag; + + IF (band_bits == 0) + { + Np = 1; + move16(); + } + ELSE + { + acc = L_mult0(band_bits, 0x7a44); + Np = extract_l(L_shr(acc, 23)); /* Get integer part. */ + if (L_and(acc, 0x7fffffL) != 0) /* If fractional part != 0, add 1. */ + { + Np = add(Np, 1); /* ceiling operation */ + } + } + *bits = 0; + move16(); + IF (LT_16(Np, MAX_SPLITS)) + { + acc = L_mult0(8*THR_ADD_SPLIT, sfmsize); + IF (GT_32(band_bits, acc)) + { + flag = rc_dec_bits_fx(st_fx, 1); + *bits = 8; + move16(); + if (flag != 0) + { + Np = add(Np, 1); + } + } + } + /* Check constraints for number of splits */ + /* The following code assumes that PVQ_MAX_BAND_SIZE is 64 */ + i = shr(sfmsize, 6); /* 6 = log2(64) = log2(PVQ_MAX_BAND_SIZE) */ + if (s_and(sfmsize, 0x3f) != 0) + { + i = add(i, 1); /* ceiling operation */ + } + + Np = s_max(i, Np); + Np = s_min(MAX_SPLITS, Np); + Np = s_min(sfmsize, Np); /* The code line assumes that MIN_BAND_SIZE is 1 */ + return Np; +} + + diff --git a/lib_dec/pvq_decode_fx.c b/lib_dec/pvq_decode_fx.c new file mode 100644 index 0000000..189d53d --- /dev/null +++ b/lib_dec/pvq_decode_fx.c @@ -0,0 +1,104 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "stl.h" +#include "prot_fx.h" +#include "rom_com_fx.h" + +/*-------------------------------------------------------------------* +* Function pvq_decode_fx() * +* * +* PVQ subvector decoding algorithm * +*-------------------------------------------------------------------*/ + +void pvq_decode_fx( + Decoder_State_fx *st_fx, + Word16 *xq, /* o: decoded vector (Q15) */ + Word16 *y, /* o: decoded vector (non-scaled int) */ + const Word16 k_val, /* i: number of allocated pulses */ + const Word16 dim, /* i: Length of vector */ + const Word16 neg_gain /* i: Gain (negated to fit 1.0 in Q15 as -1.0) */ +) +{ + Word16 i; + + UWord32 h_mem[1+KMAX_NON_DIRECT_FX+1]; /* allocate max offset memory for dim 6 */ + + PvqEntry_fx entry; + + Word16 neg_gain_norm, shift_num,shift_den,shift_tot; + Word32 L_yy,L_isqrt,L_tmp; + UWord16 u16_tmp; + + entry = get_size_mpvq_calc_offset_fx(dim, k_val, h_mem); /* get size & prepare H(adaptive table for entry.size=N_MPVQ(dim,k_val) */ + + IF( NE_16(dim, 1)) + { + entry.lead_sign_ind = (short)rc_dec_bits_fx(st_fx, 1); + entry.index = rc_dec_uniform_fx(st_fx, entry.size); + + + /* safety check in case of bit errors */ + test(); + IF( GE_32(entry.index, entry.size)||st_fx->ber_occured_in_pvq!=0) + { + st_fx->ber_occured_in_pvq = 1; + move16(); + st_fx->BER_detect = 1; + move16(); + entry.index = 0; + move16(); /* a zero index will essentially disable PVQ index decompostion complexity */ + } + + } + ELSE + { + entry.lead_sign_ind = (short)rc_dec_bits_fx(st_fx, 1); /* always a single sign bit */ + entry.index = L_deposit_l(0); + } + + mpvq_decode_vec_fx(&entry, h_mem, y); + + IF( neg_gain == 0 ) + { + FOR(i=0; i +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ + + +#include "stl.h" + + +static Word16 rc_dec_read_fx(Decoder_State_fx *st_fx); + +/*-------------------------------------------------------------------* + * rc_dec_init() + * + * Initialize range coder + *-------------------------------------------------------------------*/ + +void rc_dec_init_fx( + Decoder_State_fx *st_fx, /* i/o: Decoder State */ + Word16 tot_bits /* i : Total bit budget */ +) +{ + Word16 i; + + st_fx->rc_low_fx = L_deposit_l(0); + st_fx->rc_range_fx = 0xffffffff; + move32(); + st_fx->rc_num_bits_fx = 0; + move16(); + st_fx->rc_offset_fx = add(tot_bits, st_fx->next_bit_pos_fx); + st_fx->rc_end_fx = st_fx->rc_offset_fx; + move16(); + + FOR (i = 0; i < 4; i++) + { + st_fx->rc_low_fx = UL_addNsD(UL_lshl(st_fx->rc_low_fx, 8), UL_deposit_l(rc_dec_read_fx(st_fx))); + } +} + +/*-------------------------------------------------------------------* + * rc_decode() + * + * Decode symbol + *-------------------------------------------------------------------*/ + +UWord32 rc_decode_fx( /* o : Decoded cumulative frequency */ + Decoder_State_fx *st_fx, /* i/o: Decoder State */ + UWord32 tot /* i : Total cumulative frequency */ +) +{ + UWord32 inv, lsb, val, UL_tmp1, UL_tmp2; + Word16 exp_num, exp_den, exp; + UWord16 sgn; + + inv = UL_inverse(tot, &exp); + Mpy_32_32_uu(st_fx->rc_range_fx, inv, &(st_fx->rc_help_fx), &lsb);/*0+exp-32*/ + st_fx->rc_help_fx = UL_lshr(st_fx->rc_help_fx, sub(exp, 32)); + + exp_den = norm_ul(st_fx->rc_help_fx); + UL_tmp2 = UL_lshl(st_fx->rc_help_fx, exp_den); + exp_num = sub(norm_ul(st_fx->rc_low_fx), 1); + UL_tmp1 = UL_lshl(st_fx->rc_low_fx, exp_num); + exp = add(32, sub(exp_num, exp_den)); + + val = UL_div(UL_tmp1, UL_tmp2); + val = UL_lshr(val, exp); + + UL_tmp1 = UL_Mpy_32_32(val, st_fx->rc_help_fx); + UL_tmp2 = UL_Mpy_32_32(UL_addNsD(val, 1), st_fx->rc_help_fx); + UL_tmp1 = UL_subNsD(st_fx->rc_low_fx, UL_tmp1); + UL_tmp2 = UL_subNsD(st_fx->rc_low_fx, UL_tmp2); + if (UL_tmp2 < UL_tmp1) + { + val = UL_addNsD(val, 1); + } + + /* safety check in case of bit errors */ + UL_tmp1 = UL_subNs(tot,val,&sgn); + IF ( sgn != 0) + { + st_fx->BER_detect = 1; + move16(); + return 0; + } + + return val; +} + +/*-------------------------------------------------------------------* + * rc_dec_update() + * + * Update range coder + *-------------------------------------------------------------------*/ + +void rc_dec_update_fx( + Decoder_State_fx *st_fx, /* i/o: Decoder State */ + UWord32 cum_freq, /* i : Cumulative frequency */ + UWord32 sym_freq /* i : Symbol frequency */ +) +{ + st_fx->rc_low_fx = UL_subNsD(st_fx->rc_low_fx, UL_Mpy_32_32(cum_freq, st_fx->rc_help_fx)); /*0+0*/ + st_fx->rc_range_fx = UL_Mpy_32_32(st_fx->rc_help_fx, sym_freq); + + WHILE (st_fx->rc_range_fx < 1<<24) + { + L_sub(0, 0); /* For comparision in while*/ + st_fx->rc_num_bits_fx = add(st_fx->rc_num_bits_fx, 8); + st_fx->rc_low_fx = UL_addNsD(UL_lshl(st_fx->rc_low_fx, 8), UL_deposit_l(rc_dec_read_fx(st_fx))); + st_fx->rc_range_fx = UL_lshl(st_fx->rc_range_fx, 8); + } +} + +/*-------------------------------------------------------------------* + * rc_dec_bits() + * + * Encode bits + *-------------------------------------------------------------------*/ + +Word32 rc_dec_bits_fx( /* i : Decoded value */ + Decoder_State_fx *st_fx, /* i/o: Decoder State */ + Word16 bits /* i : Number of bits */ +) +{ + Word32 value; + + st_fx->rc_num_bits_fx = add(st_fx->rc_num_bits_fx, bits); + + IF (GT_16(bits, 16)) + { + st_fx->rc_offset_fx = sub(st_fx->rc_offset_fx, sub(bits, 16)); + value = UL_lshl(UL_deposit_l(get_indice_fx(st_fx, st_fx->rc_offset_fx, sub(bits, 16))), 16); + st_fx->rc_offset_fx = sub(st_fx->rc_offset_fx, 16); + value = UL_or(value, UL_deposit_l(get_indice_fx(st_fx, st_fx->rc_offset_fx, 16))); + } + ELSE + { + st_fx->rc_offset_fx = sub(st_fx->rc_offset_fx, bits); + value = UL_deposit_l(get_indice_fx(st_fx, st_fx->rc_offset_fx, bits)); + } + + return value; +} + +/*-------------------------------------------------------------------* + * rc_dec_uniform() + * + * Encode with uniform distribution + *-------------------------------------------------------------------*/ + +UWord32 rc_dec_uniform_fx( /* i : Decoded value */ + Decoder_State_fx *st_fx, /* i/o: Decoder State */ + UWord32 tot /* i : Maximum value */ +) +{ + UWord32 value; + Word16 n; + n = sub(32, norm_ul(tot - 1)); + + IF (LE_16(n, 8)) + { + value = rc_decode_fx(st_fx, tot); + rc_dec_update_fx(st_fx, value, 1); + } + ELSE + { + n = sub(n, 8); + value = rc_decode_fx(st_fx, UL_addNsD(UL_lshr(tot, n), 1)); + rc_dec_update_fx(st_fx, value, 1); + value = UL_lshl(value, n); + value = UL_or(value, rc_dec_bits_fx(st_fx, n)); + } + + return value; +} + +/*-------------------------------------------------------------------* + * rc_dec_finish() + * + * Finalize range decoder + *-------------------------------------------------------------------*/ + +void rc_dec_finish_fx(Decoder_State_fx *st_fx) +{ + st_fx->next_bit_pos_fx = st_fx->rc_end_fx; +} + +/*-------------------------------------------------------------------* + * rc_dec_read() + * + * Read a byte from bit stream + *-------------------------------------------------------------------*/ + + +static Word16 rc_dec_read_fx(Decoder_State_fx *st_fx) +{ + Word16 bits; + + bits = sub( st_fx->rc_end_fx, st_fx->next_bit_pos_fx ); + + /* If the end of the buffer has been reached, pad the last byte with zeros */ + IF(sub(bits, 8) < 0) + { + return shl(get_next_indice_fx(st_fx, bits), sub(8, bits)); + } + ELSE + { + return get_next_indice_fx(st_fx, 8); + } +} + diff --git a/lib_dec/re8_dec_fx.c b/lib_dec/re8_dec_fx.c new file mode 100644 index 0000000..14a590c --- /dev/null +++ b/lib_dec/re8_dec_fx.c @@ -0,0 +1,72 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------------- +* re8_dec_fx() +* +* MULTI-RATE INDEXING OF A POINT y in THE LATTICE RE8 (INDEX DECODING) +* note: the index I is defined as a 32-bit word, but only +* 16 bits are required (long can be replaced by unsigned integer) +*--------------------------------------------------------------------------*/ + +void re8_dec_fx( + Word16 n, /* i : codebook number (*n is an integer defined in {0,2,3,4,..,n_max}) */ + const UWord16 I, /* i : index of c (pointer to unsigned 16-bit word) */ + const Word16 k[], /* i : index of v (8-dimensional vector of binary indices) = Voronoi index */ + Word16 y[] /* o : point in RE8 (8-dimensional integer vector) */ +) +{ + Word16 i, m, v[8]; + + /*------------------------------------------------------------------------* + * decode the sub-indices I and kv[] according to the codebook number n: + * if n=0,2,3,4, decode I (no Voronoi extension) + * if n>4, Voronoi extension is used, decode I and kv[] + *------------------------------------------------------------------------*/ + IF( LE_16(n, 4)) + { + re8_decode_base_index_fx( n, I, y ); + } + ELSE + { + /*--------------------------------------------------------------------* + * compute the Voronoi modulo m = 2^r where r is extension order + *--------------------------------------------------------------------*/ + m = 0; + move16(); + + FOR (; n > 4; n -= 2) + { + m = add(m, 1); + } + + /*--------------------------------------------------------------------* + * decode base codebook index I into c (c is an element of Q3 or Q4) + * [here c is stored in y to save memory] + *--------------------------------------------------------------------*/ + + re8_decode_base_index_fx( n, I, y ); + + /*--------------------------------------------------------------------* + * decode Voronoi index k[] into v + *--------------------------------------------------------------------*/ + re8_k2y_fx( k, m, v ); + + /*--------------------------------------------------------------------* + * reconstruct y as y = m c + v (with m=2^r, r integer >=1) + *--------------------------------------------------------------------*/ + FOR( i=0; i<8; i++ ) + { + /* y[i] = m*y[i] + v[i] */ + y[i] = add(shl(y[i], m), v[i]); + move16(); + } + } + + return; +} diff --git a/lib_dec/rom_dec_fx.c b/lib_dec/rom_dec_fx.c new file mode 100644 index 0000000..561b1b8 --- /dev/null +++ b/lib_dec/rom_dec_fx.c @@ -0,0 +1,456 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "stl.h" +#include "cnst_fx.h" /* Common constants */ +#include "basop_util.h" + +/* 125 375 750 1250 2000 4000 8000 16000 24000 */ +const Word16 gw_fx[Lgw_max] = { 1, 3, 6, 10, 16, 32, 64, 128, 192 }; /* frequency group start bins for transient analysis */ + +const Word16 gw_len_inv_fx[Lgw_max-1] = /* Q15 */ +{ + 16384, 10923, 8192, 5461, + 2048, 1024, 512, 512, +}; + +/* 31.25 343.75 718.75 1218.75 1968.75 4000 8000 16000 24000 */ +const Word16 gwlpr_fx[Lgw_max] = { 1, 3*Quot_Lpr_Ltr-1, 6*Quot_Lpr_Ltr-1, 10*Quot_Lpr_Ltr-1, 16*Quot_Lpr_Ltr-1, 32*Quot_Lpr_Ltr, 64*Quot_Lpr_Ltr, 128*Quot_Lpr_Ltr, 192*Quot_Lpr_Ltr }; /* frequency group start bins for transient analysis */ + + +const Word16 hestable_fx[15]= +{ + 0X11, 0X21, -0X04, 0X21, -0X03, 0X21, -0X02, -0X05, 0X11, 0X21, -0X01, -0X06, + 0X11, -0X07, -0X00 +}; +/*-------------------------------------------------------------------* + * num x 32768 + 0.5 + * ------------------- + * PIT_MAX x Fact + * Tables fill at compiled time + *-------------------------------------------------------------------*/ + +#define PIT_MAX_DIV(num, fact) ((num*32768L+(fact)*PIT_MAX/2) / ((fact)*PIT_MAX)) +#define PIT_MAX_DIV16k(num, fact) ((num*32768L+(fact)*PIT16k_MAX/2) / ((fact)*PIT16k_MAX)) + +/*----------------------------------------------------------------------------------* + * hp filter for filtering random part of excitation in frame error concealment + * Used in lib_dec\syn_bfi.c + *----------------------------------------------------------------------------------*/ + +const Word16 h_high_fx[5] = { -410, -3572, 25602, -3572, -410 }; +const Word16 inv_sqi[15] = +{ + 8192, /* 1/4 */ + 3641, /* 1/9 */ + 2048, /* 1/16 */ + 1311, /* 1/25 */ + 910, /* 1/36 */ + 669, /* 1/49 */ + 512, /* 1/64 */ + 405, /* 1/81 */ + 328, /* 1/100 */ + 271, /* 1/121 */ + 228, /* 1/144 */ + 194, /* 1/169 */ + 167, /* 1/196 */ + 146, /* 1/225 */ + 128 /* 1/256 */ +}; +/*-------------------------------------------------------------------* + * index square used in fec_adapt_codebook + *-------------------------------------------------------------------*/ +const Word16 sqi[15] = +{ + 4, /* 2 */ + 9, /* 3 */ + 16, /* 4 */ + 25, /* 5 */ + 36, /* 6 */ + 49, /* 7 */ + 64, /* 8 */ + 81, /* 9 */ + 100, /* 10 */ + 121, /* 11 */ + 144, /* 12 */ + 169, /* 13 */ + 196, /* 14 */ + 225, /* 15 */ + 256 /* 16 */ +}; +/*------------------------------------------------------------------------------* + * RE8 related tables rom + *------------------------------------------------------------------------------*/ + +/* NOTE: Many values here could fit in shorts instead of ints */ + +const Word16 mult_avq_tab_fx[7] = {1,1,1,342,1,1,171}; +const Word16 shift_avq_tab_fx[7] = {0,0,1, 10,2,0, 10}; + +/*----------------------------------------------------------------------------------* + * HR SWB BWE parameters + *----------------------------------------------------------------------------------*/ +const Word16 swb_hr_inv_frm_len[4] = /* in Q19 */ +{ + 26214, /* 1/(160/8) */ + 13107, /* 1/(320/8) */ + 6554, /* 1/(640/8) */ + 4369 /* 1/(960/8) */ +}; +const Word16 inv_tbl_2n_minus1[] = { -1, -1, /* Bits = 0 and 1 are not used */ + 21845/*Q16*/, + 18725/*Q17*/, + 17476/*Q18*/, + 16913/*Q19*/, + 16644/*Q20*/, + 16513/*Q21*/ + }; /* in Qx */ + + +const Word16 hntable_fx[55]= +{ + 0X13, -0X10, -0X0F, -0X11, 0X51, 0X61, -0X0E, -0X12, 0X51, 0X61, + -0X13, -0X0D, 0X51, 0X62, -0X14, 0X81, -0X0C, 0X81, -0X15, -0X17, + 0X71, 0X81, -0X18, -0X16, 0X71, -0X0B, 0X71, -0X1A, 0X71, -0X09, + -0X1B, -0X0A, -0X19, 0X41, -0X1C, -0X08, 0X31, 0X41, -0X1D, -0X06, + 0X31, 0X41, -0X07, 0X41, -0X05, -0X1E, -0X04, -0X1F, 0X11, -0X03, + 0X11, -0X02, 0X11, -0X01, 0X00 +}; + +const Word16 hetable_fx[57]= +{ + 0X12, 0X41, -0X0F, 0X41, -0X10, -0X0E, 0X31, -0X11, 0X31, 0X41, + -0X0D, 0X41, -0X12, 0X42, -0x0C, 0X61, -0X13, 0X61, 0X71, -0X0A, + 0X71, -0X0B, -0X14, -0X15, 0X51, 0X61, -0X16, -0X09, 0X51, 0X61, + -0X17, 0X62, -0X08, 0X81, -0X07, 0X81, -0X18, -0X05, -0X04, -0X03, + 0X51, -0X06, 0X51, -0X19, 0X51, -0X01, -0X1C, -0X02, -0X1B, -0X1A, + 0X11, 0X00, 0X11, -0X1D, 0X11, -0X1E, -0X1F +}; + +const Word16 lsf_tab_fx[LPC_SHB_ORDER] = +{ + 2315, 3920, 5546, 6759, 7978, + 10254, 11336, 12476, 13437, 14590 +}; + + +/*-----------------------------------------------------------------------------* + * lp filter for filtering periodic part of excitation in artificial onset + * construction after frame error concealment + * Used in lib_dec\onset_fx.c + *-----------------------------------------------------------------------------*/ + +const Word16 H_low[5] = +{ + -410, 3572, 25602, 3572, -410 +}; + +const Word16 w_hamm48k_2_fx[Ltrana48k/2] = +{ + 2621, 2623, 2630, 2640, 2654, 2672, 2694, 2721, + 2751, 2785, 2824, 2866, 2913, 2963, 3017, 3076, + 3138, 3204, 3274, 3348, 3426, 3507, 3593, 3682, + 3775, 3871, 3972, 4076, 4184, 4295, 4410, 4529, + 4651, 4777, 4906, 5039, 5175, 5314, 5457, 5603, + 5752, 5904, 6060, 6219, 6381, 6546, 6714, 6884, + 7058, 7235, 7414, 7596, 7781, 7969, 8159, 8352, + 8547, 8745, 8945, 9148, 9353, 9560, 9769, 9980, + 10194, 10409, 10627, 10846, 11067, 11290, 11515, 11741, + 11969, 12199, 12430, 12662, 12896, 13131, 13367, 13605, + 13843, 14083, 14323, 14565, 14807, 15050, 15294, 15538, + 15783, 16029, 16275, 16521, 16768, 17015, 17262, 17509, + 17757, 18004, 18251, 18498, 18745, 18991, 19238, 19483, + 19729, 19973, 20217, 20461, 20704, 20945, 21186, 21427, + 21666, 21904, 22140, 22376, 22611, 22844, 23075, 23306, + 23534, 23762, 23987, 24211, 24433, 24653, 24872, 25088, + 25303, 25515, 25725, 25934, 26140, 26343, 26545, 26744, + 26940, 27134, 27326, 27515, 27701, 27884, 28065, 28243, + 28419, 28591, 28760, 28927, 29090, 29250, 29408, 29562, + 29712, 29860, 30004, 30146, 30283, 30418, 30548, 30676, + 30800, 30920, 31037, 31150, 31260, 31366, 31468, 31567, + 31662, 31753, 31840, 31924, 32003, 32079, 32151, 32219, + 32283, 32344, 32400, 32452, 32501, 32545, 32585, 32622, + 32654, 32682, 32707, 32727, 32743, 32755, 32763, 32767 +}; + +const Word16 w_hamm32k_2_fx[Ltrana32k/2]= +{ + 2621, 2626, 2640, 2663, 2695, 2736, 2786, 2845, + 2913, 2991, 3077, 3172, 3276, 3388, 3509, 3639, + 3778, 3925, 4080, 4243, 4415, 4595, 4782, 4978, + 5181, 5392, 5610, 5836, 6069, 6309, 6555, 6809, + 7069, 7336, 7609, 7888, 8173, 8464, 8760, 9062, + 9369, 9681, 9998, 10319, 10646, 10976, 11310, 11649, + 11991, 12336, 12685, 13037, 13391, 13749, 14108, 14470, + 14834, 15199, 15566, 15935, 16304, 16674, 17045, 17416, + 17788, 18159, 18530, 18900, 19270, 19639, 20007, 20373, + 20738, 21101, 21461, 21820, 22176, 22529, 22879, 23226, + 23570, 23910, 24247, 24579, 24907, 25231, 25551, 25865, + 26175, 26479, 26778, 27072, 27360, 27642, 27918, 28188, + 28451, 28708, 28958, 29202, 29438, 29667, 29889, 30104, + 30311, 30510, 30702, 30886, 31061, 31229, 31388, 31539, + 31682, 31816, 31942, 32059, 32167, 32266, 32357, 32439, + 32511, 32575, 32630, 32675, 32712, 32739, 32758, 32767 +}; + +const Word16 w_hamm16k_2_fx[Ltrana16k/2] = +{ + 2621, 2640, 2695, 2787, 2916, 3080, 3281, 3516, + 3787, 4091, 4429, 4799, 5201, 5633, 6095, 6585, + 7102, 7646, 8214, 8805, 9418, 10051, 10703, 11371, + 12056, 12754, 13464, 14185, 14914, 15650, 16391, 17136, + 17881, 18626, 19369, 20108, 20841, 21566, 22282, 22986, + 23678, 24354, 25015, 25658, 26281, 26883, 27463, 28019, + 28549, 29053, 29529, 29976, 30393, 30780, 31134, 31455, + 31742, 31995, 32213, 32396, 32543, 32653, 32727, 32763 +}; + + +const Word16 w_hamm_sana48k_2_fx[288] = +{ + 2621, 2622, 2625, 2630, 2636, 2644, 2654, 2666, + 2679, 2694, 2711, 2730, 2751, 2773, 2797, 2823, + 2851, 2881, 2912, 2945, 2980, 3017, 3055, 3095, + 3137, 3180, 3226, 3273, 3321, 3372, 3424, 3478, + 3534, 3591, 3650, 3710, 3773, 3837, 3902, 3970, + 4039, 4109, 4181, 4255, 4330, 4407, 4486, 4566, + 4648, 4731, 4816, 4902, 4990, 5079, 5170, 5263, + 5357, 5452, 5549, 5647, 5747, 5848, 5950, 6054, + 6160, 6266, 6374, 6484, 6595, 6707, 6820, 6935, + 7051, 7168, 7287, 7406, 7527, 7650, 7773, 7898, + 8023, 8150, 8278, 8407, 8538, 8669, 8802, 8935, + 9070, 9205, 9342, 9479, 9618, 9758, 9898, 10040, + 10182, 10325, 10469, 10614, 10760, 10907, 11054, 11202, + 11351, 11501, 11652, 11803, 11955, 12108, 12261, 12415, + 12569, 12725, 12880, 13037, 13194, 13351, 13509, 13668, + 13827, 13986, 14146, 14306, 14467, 14628, 14789, 14951, + 15113, 15276, 15438, 15601, 15765, 15928, 16092, 16256, + 16420, 16584, 16748, 16913, 17077, 17242, 17406, 17571, + 17736, 17901, 18065, 18230, 18394, 18559, 18723, 18888, + 19052, 19216, 19379, 19543, 19706, 19870, 20032, 20195, + 20357, 20519, 20681, 20842, 21003, 21163, 21324, 21483, + 21642, 21801, 21959, 22117, 22274, 22431, 22587, 22742, + 22897, 23052, 23205, 23358, 23511, 23662, 23813, 23963, + 24113, 24261, 24409, 24556, 24702, 24848, 24992, 25136, + 25279, 25421, 25562, 25702, 25841, 25979, 26116, 26252, + 26387, 26521, 26654, 26786, 26917, 27047, 27175, 27303, + 27429, 27554, 27678, 27801, 27923, 28043, 28162, 28280, + 28397, 28512, 28626, 28739, 28850, 28960, 29069, 29177, + 29283, 29387, 29490, 29592, 29693, 29792, 29889, 29985, + 30080, 30173, 30265, 30355, 30444, 30531, 30616, 30700, + 30783, 30864, 30943, 31021, 31097, 31172, 31244, 31316, + 31386, 31454, 31520, 31585, 31648, 31710, 31769, 31827, + 31884, 31939, 31992, 32043, 32093, 32140, 32187, 32231, + 32274, 32315, 32354, 32391, 32427, 32461, 32493, 32524, + 32552, 32579, 32604, 32628, 32649, 32669, 32687, 32703, + 32717, 32730, 32741, 32750, 32757, 32762, 32766, 32767 +}; + +const Word16 POW_ATT_TABLE0[OFF_FRAMES_LIMIT+1] = +{ + 32767, 31293, 29885, 28540, 27255, 26029, 24857, 23738, 22670, 21650, + 20675, 19745, 18856, 18007, 17197, 16423, 8211, 4106, 2053, 1026, + 513, 257, 128, 64, 32, 16, 8, 4, 2, 1, 0 +}; +const Word16 POW_ATT_TABLE1[OFF_FRAMES_LIMIT+1] = +{ + 32767, 31656, 30581, 29543, 28540, 27571, 26635, 25731, 24857, 24013, + 23198, 22410, 21650, 20915, 20205, 19519, 9759, 4880, 2440, 1220, + 610, 305, 152, 76, 38, 19, 10, 5, 2, 1, 0 +}; +const Word16 GR_POW_HEADROOM[Lgw_max] = /* in Q0-- Number of bits down-shifting to prevent from saturation in group power accumulation.*/ +{ + 0, 0, 1, 2, 2, 3, 4, 4, 4 +}; + +/*---------------------------------------------------------------------* + * NB post-filter tables + *---------------------------------------------------------------------*/ + +const Word16 Tab_hup_s[SIZ_TAB_HUP_S] = +{ + -188, 2873, 31650, -1597, -484, 7041, 28469, -2147, -933, 12266, + 23705, -1992, -1492, 18050, 18050, -1492, -1992, 23705, 12266, -933, + -2147, 28469, 7041, -484, -1597, 31650, 2873, -188 +}; + +const Word16 Tab_hup_l[SIZ_TAB_HUP_L] = +{ + -40, 72, -156, 315, -579, 1023, -1874, 4439, + 31915, -3390, 1595, -887, 501, -266, 130, -59, + -77, 147, -317, 631, -1150, 2030, -3773, 9639, + 29436, -5579, 2727, -1527, 859, -453, 218, -101, + -106, 212, -455, 892, -1614, 2850, -5392, 15206, + 25569, -6549, 3303, -1860, 1041, -543, 258, -122, + -123, 253, -538, 1044, -1876, 3319, -6414, 20676, + 20676, -6414, 3319, -1876, 1044, -538, 253, -123, + -122, 258, -543, 1041, -1860, 3303, -6549, 25569, + 15206, -5392, 2850, -1614, 892, -455, 212, -106, + -101, 218, -453, 859, -1527, 2727, -5579, 29436, + 9639, -3773, 2030, -1150, 631, -317, 147, -77, + -59, 130, -266, 501, -887, 1595, -3390, 31915, + 4439, -1874, 1023, -579, 315, -156, 72, -40 +}; + + +/*Table 256 / (L_frame*2) , needed in sig_classifier.c and er_dec_acelp.c*/ +const Word16 T_256DIV_L_Frame[]= +{ + 6554 /*L_Frame 640*/ + ,8192 /*L_Frame 512*/ + ,8738 /*L_Frame 480*/ + ,13107/*L_Frame 320*/ + ,16384 /*L_Frame 256*/ + ,26214 /*L_Frame 160*/ +}; + +const Word16 T_DIV_L_Frame[] = /*0Q15 * 2^-7 */ +{ + 26214 /*160*/ + ,16384 /*256*/ + ,13107 /*320*/ + ,8738 /*480*/ + ,8192 /*512*/ + ,6553 /*640*/ +}; + + +/*er_dec_tcx.c*/ +const Word16 h_high3_32[L_FIR_FER2] = { -1694/*-0.0517f Q15*/, -1923/*-0.0587f Q15*/, -2687/*-0.0820f Q15*/, -3355/*-0.1024f Q15*/, -3814/*-0.1164f Q15*/, 28790/*0.8786f Q15*/, -3814/*-0.1164f Q15*/, -3355/*-0.1024f Q15*/, -2687/*-0.0820f Q15*/, -1923/*-0.0587f Q15*/, -1694/*-0.0517f Q15*/}; +const Word16 h_high3_16[L_FIR_FER2] = { 0/* 0.f Q15*/, -672/*-0.0205f Q15*/, -2133/*-0.0651f Q15*/, -4116/*-0.1256f Q15*/, -5872/*-0.1792f Q15*/, 26306/*0.8028f Q15*/, -5872/*-0.1792f Q15*/, -4116/*-0.1256f Q15*/, -2133/*-0.0651f Q15*/, -672/*-0.0205f Q15*/, 0/* 0.f Q15*/}; + +const Word16 pow2tab[15] = { 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; + +/* CLDFB-BPF */ +/** + \brief Bass Post Filter weights + First bpf_weights coefficient is scaled by 0.5 +*/ +const Word16 bpf_weights_16_Fx[16] = +{ + 16385/*0.500020f Q15*/, 23022/*0.702561f Q15*/, 6843/*0.208838f Q15*/, 51/*0.001553f Q15*/, + 58/*0.001777f Q15*/, 45/*0.001370f Q15*/, 30/*0.000926f Q15*/, 18/*0.000554f Q15*/, + 9/*0.000270f Q15*/, 3/*0.000080f Q15*/, 1/*0.000030f Q15*/, 3/*0.000082f Q15*/, + 3/*0.000081f Q15*/, 2/*0.000052f Q15*/, 1/*0.000017f Q15*/, 1/*0.000016f Q15*/ +}; + + +/* Word16 (Q15) Hann window ranging from 0 to 32767/32768 (~0.999969) */ +const Word16 pcmdsp_window_hann_960[960] = +{ + 0, 0, 1, 3, 6, 9, 13, 17, 22, 28, 35, 42, 51, 59, 69, + 79, 90, 101, 114, 127, 140, 155, 170, 185, 202, 219, 237, 255, 274, 294, + 315, 336, 358, 381, 404, 428, 453, 478, 504, 531, 558, 586, 615, 645, 675, + 705, 737, 769, 802, 835, 869, 904, 940, 976, 1013, 1050, 1088, 1127, 1166, 1206, + 1247, 1289, 1331, 1373, 1416, 1460, 1505, 1550, 1596, 1643, 1690, 1737, 1786, 1835, 1884, + 1935, 1985, 2037, 2089, 2142, 2195, 2249, 2303, 2359, 2414, 2471, 2528, 2585, 2643, 2702, + 2761, 2821, 2882, 2943, 3004, 3066, 3129, 3192, 3256, 3321, 3386, 3451, 3517, 3584, 3651, + 3719, 3787, 3856, 3926, 3995, 4066, 4137, 4208, 4280, 4353, 4426, 4499, 4574, 4648, 4723, + 4799, 4875, 4951, 5028, 5106, 5184, 5263, 5342, 5421, 5501, 5581, 5662, 5743, 5825, 5907, + 5990, 6073, 6157, 6241, 6325, 6410, 6495, 6581, 6667, 6754, 6841, 6928, 7016, 7104, 7193, + 7282, 7371, 7461, 7551, 7641, 7732, 7823, 7915, 8007, 8099, 8192, 8285, 8378, 8472, 8566, + 8661, 8755, 8850, 8946, 9042, 9138, 9234, 9331, 9427, 9525, 9622, 9720, 9818, 9917,10015, + 10114,10213,10313,10413,10512,10613,10713,10814,10915,11016,11118,11219,11321,11423,11525, + 11628,11731,11834,11937,12040,12144,12247,12351,12455,12559,12664,12768,12873,12978,13083, + 13188,13293,13398,13504,13609,13715,13821,13927,14033,14139,14245,14352,14458,14565,14671, + 14778,14885,14992,15099,15205,15312,15419,15527,15634,15741,15848,15955,16062,16170,16277, + 16384,16491,16598,16706,16813,16920,17027,17134,17241,17349,17456,17563,17669,17776,17883, + 17990,18097,18203,18310,18416,18523,18629,18735,18841,18947,19053,19159,19264,19370,19475, + 19580,19685,19790,19895,20000,20104,20209,20313,20417,20521,20624,20728,20831,20934,21037, + 21140,21243,21345,21447,21549,21650,21752,21853,21954,22055,22155,22256,22355,22455,22555, + 22654,22753,22851,22950,23048,23146,23243,23341,23437,23534,23630,23726,23822,23918,24013, + 24107,24202,24296,24390,24483,24576,24669,24761,24853,24945,25036,25127,25217,25307,25397, + 25486,25575,25664,25752,25840,25927,26014,26101,26187,26273,26358,26443,26527,26611,26695, + 26778,26861,26943,27025,27106,27187,27267,27347,27426,27505,27584,27662,27740,27817,27893, + 27969,28045,28120,28194,28269,28342,28415,28488,28560,28631,28702,28773,28842,28912,28981, + 29049,29117,29184,29251,29317,29382,29447,29512,29576,29639,29702,29764,29825,29886,29947, + 30007,30066,30125,30183,30240,30297,30354,30409,30465,30519,30573,30626,30679,30731,30783, + 30833,30884,30933,30982,31031,31078,31125,31172,31218,31263,31308,31352,31395,31437,31479, + 31521,31562,31602,31641,31680,31718,31755,31792,31828,31864,31899,31933,31966,31999,32031, + 32063,32093,32123,32153,32182,32210,32237,32264,32290,32315,32340,32364,32387,32410,32432, + 32453,32474,32494,32513,32531,32549,32566,32583,32598,32613,32628,32641,32654,32667,32678, + 32689,32699,32709,32717,32726,32733,32740,32746,32751,32755,32759,32762,32765,32767,32767, + 32767,32767,32766,32764,32761,32758,32754,32750,32745,32739,32732,32725,32716,32708,32698, + 32688,32677,32666,32653,32640,32627,32612,32597,32582,32565,32548,32530,32512,32493,32473, + 32452,32431,32409,32386,32363,32339,32314,32289,32263,32236,32209,32181,32152,32122,32092, + 32062,32030,31998,31965,31932,31898,31863,31827,31791,31754,31717,31679,31640,31601,31561, + 31520,31478,31436,31394,31351,31307,31262,31217,31171,31124,31077,31030,30981,30932,30883, + 30832,30782,30730,30678,30625,30572,30518,30464,30408,30353,30296,30239,30182,30124,30065, + 30006,29946,29885,29824,29763,29701,29638,29575,29511,29446,29381,29316,29250,29183,29116, + 29048,28980,28911,28841,28772,28701,28630,28559,28487,28414,28341,28268,28193,28119,28044, + 27968,27892,27816,27739,27661,27583,27504,27425,27346,27266,27186,27105,27024,26942,26860, + 26777,26694,26610,26526,26442,26357,26272,26186,26100,26013,25926,25839,25751,25663,25574, + 25485,25396,25306,25216,25126,25035,24944,24852,24760,24668,24575,24482,24389,24295,24201, + 24106,24012,23917,23821,23725,23629,23533,23436,23340,23242,23145,23047,22949,22850,22752, + 22653,22554,22454,22354,22255,22154,22054,21953,21852,21751,21649,21548,21446,21344,21242, + 21139,21036,20933,20830,20727,20623,20520,20416,20312,20208,20103,19999,19894,19789,19684, + 19579,19474,19369,19263,19158,19052,18946,18840,18734,18628,18522,18415,18309,18202,18096, + 17989,17882,17775,17668,17562,17455,17348,17240,17133,17026,16919,16812,16705,16597,16490, + 16383,16276,16169,16061,15954,15847,15740,15633,15526,15418,15311,15204,15098,14991,14884, + 14777,14670,14564,14457,14351,14244,14138,14032,13926,13820,13714,13608,13503,13397,13292, + 13187,13082,12977,12872,12767,12663,12558,12454,12350,12246,12143,12039,11936,11833,11730, + 11627,11524,11422,11320,11218,11117,11015,10914,10813,10712,10612,10511,10412,10312,10212, + 10113,10014,9916, 9817, 9719, 9621, 9524, 9426, 9330, 9233, 9137, 9041, 8945, 8849, 8754, + 8660, 8565, 8471, 8377, 8284, 8191, 8098, 8006, 7914, 7822, 7731, 7640, 7550, 7460, 7370, + 7281, 7192, 7103, 7015, 6927, 6840, 6753, 6666, 6580, 6494, 6409, 6324, 6240, 6156, 6072, + 5989, 5906, 5824, 5742, 5661, 5580, 5500, 5420, 5341, 5262, 5183, 5105, 5027, 4950, 4874, + 4798, 4722, 4647, 4573, 4498, 4425, 4352, 4279, 4207, 4136, 4065, 3994, 3925, 3855, 3786, + 3718, 3650, 3583, 3516, 3450, 3385, 3320, 3255, 3191, 3128, 3065, 3003, 2942, 2881, 2820, + 2760, 2701, 2642, 2584, 2527, 2470, 2413, 2358, 2302, 2248, 2194, 2141, 2088, 2036, 1984, + 1934, 1883, 1834, 1785, 1736, 1689, 1642, 1595, 1549, 1504, 1459, 1415, 1372, 1330, 1288, + 1246, 1205, 1165, 1126, 1087, 1049, 1012, 975, 939, 903, 868, 834, 801, 768, 736, + 704, 674, 644, 614, 585, 557, 530, 503, 477, 452, 427, 403, 380, 357, 335, + 314, 293, 273, 254, 236, 218, 201, 184, 169, 154, 139, 126, 113, 100, 89, + 78, 68, 58, 50, 41, 34, 27, 21, 16, 12, 8, 5, 2, 0, 0 +}; + +/* Word16 (Q15) Hann window ranging from 0 to 32767/32768 (~0.999969) */ +const Word16 pcmdsp_window_hann_640[640] = +{ + 0, 1, 3, 7, 13, 20, 28, 39, 51, 64, 79, 95, 114, 133, 155, + 177, 202, 228, 255, 284, 315, 347, 381, 416, 453, 491, 531, 572, 615, 660, + 705, 753, 802, 852, 904, 958, 1013, 1069, 1127, 1186, 1247, 1309, 1373, 1438, 1505, + 1573, 1643, 1713, 1786, 1859, 1935, 2011, 2089, 2168, 2249, 2331, 2414, 2499, 2585, 2672, + 2761, 2851, 2943, 3035, 3129, 3224, 3321, 3418, 3517, 3618, 3719, 3822, 3926, 4031, 4137, + 4244, 4353, 4463, 4574, 4686, 4799, 4913, 5028, 5145, 5263, 5381, 5501, 5622, 5743, 5866, + 5990, 6115, 6241, 6368, 6495, 6624, 6754, 6884, 7016, 7148, 7282, 7416, 7551, 7687, 7823, + 7961, 8099, 8238, 8378, 8519, 8661, 8803, 8946, 9089, 9234, 9379, 9525, 9671, 9818, 9966, + 10114,10263,10413,10563,10713,10864,11016,11168,11321,11474,11628,11782,11937,12092,12247, + 12403,12559,12716,12873,13030,13188,13346,13504,13662,13821,13980,14139,14299,14458,14618, + 14778,14938,15099,15259,15419,15580,15741,15902,16062,16223,16384,16545,16706,16866,17027, + 17188,17349,17509,17669,17830,17990,18150,18310,18469,18629,18788,18947,19106,19264,19422, + 19580,19738,19895,20052,20209,20365,20521,20676,20831,20986,21140,21294,21447,21600,21752, + 21904,22055,22205,22355,22505,22654,22802,22950,23097,23243,23389,23534,23679,23822,23965, + 24107,24249,24390,24530,24669,24807,24945,25081,25217,25352,25486,25620,25752,25884,26014, + 26144,26273,26400,26527,26653,26778,26902,27025,27146,27267,27387,27505,27623,27740,27855, + 27969,28082,28194,28305,28415,28524,28631,28737,28842,28946,29049,29150,29251,29350,29447, + 29544,29639,29733,29825,29917,30007,30096,30183,30269,30354,30437,30519,30600,30679,30757, + 30833,30909,30982,31055,31125,31195,31263,31330,31395,31459,31521,31582,31641,31699,31755, + 31810,31864,31916,31966,32015,32063,32108,32153,32196,32237,32277,32315,32352,32387,32421, + 32453,32484,32513,32540,32566,32591,32613,32635,32654,32673,32689,32704,32717,32729,32740, + 32748,32755,32761,32765,32767,32767,32766,32764,32760,32754,32747,32739,32728,32716,32703, + 32688,32672,32653,32634,32612,32590,32565,32539,32512,32483,32452,32420,32386,32351,32314, + 32276,32236,32195,32152,32107,32062,32014,31965,31915,31863,31809,31754,31698,31640,31581, + 31520,31458,31394,31329,31262,31194,31124,31054,30981,30908,30832,30756,30678,30599,30518, + 30436,30353,30268,30182,30095,30006,29916,29824,29732,29638,29543,29446,29349,29250,29149, + 29048,28945,28841,28736,28630,28523,28414,28304,28193,28081,27968,27854,27739,27622,27504, + 27386,27266,27145,27024,26901,26777,26652,26526,26399,26272,26143,26013,25883,25751,25619, + 25485,25351,25216,25080,24944,24806,24668,24529,24389,24248,24106,23964,23821,23678,23533, + 23388,23242,23096,22949,22801,22653,22504,22354,22204,22054,21903,21751,21599,21446,21293, + 21139,20985,20830,20675,20520,20364,20208,20051,19894,19737,19579,19421,19263,19105,18946, + 18787,18628,18468,18309,18149,17989,17829,17668,17508,17348,17187,17026,16865,16705,16544, + 16383,16222,16061,15901,15740,15579,15418,15258,15098,14937,14777,14617,14457,14298,14138, + 13979,13820,13661,13503,13345,13187,13029,12872,12715,12558,12402,12246,12091,11936,11781, + 11627,11473,11320,11167,11015,10863,10712,10562,10412,10262,10113, 9965, 9817, 9670, 9524, + 9378, 9233, 9088, 8945, 8802, 8660, 8518, 8377, 8237, 8098, 7960, 7822, 7686, 7550, 7415, + 7281, 7147, 7015, 6883, 6753, 6623, 6494, 6367, 6240, 6114, 5989, 5865, 5742, 5621, 5500, + 5380, 5262, 5144, 5027, 4912, 4798, 4685, 4573, 4462, 4352, 4243, 4136, 4030, 3925, 3821, + 3718, 3617, 3516, 3417, 3320, 3223, 3128, 3034, 2942, 2850, 2760, 2671, 2584, 2498, 2413, + 2330, 2248, 2167, 2088, 2010, 1934, 1858, 1785, 1712, 1642, 1572, 1504, 1437, 1372, 1308, + 1246, 1185, 1126, 1068, 1012, 957, 903, 851, 801, 752, 704, 659, 614, 571, 530, + 490, 452, 415, 380, 346, 314, 283, 254, 227, 201, 176, 154, 132, 113, 94, + 78, 63, 50, 38, 27, 19, 12, 6, 2, 0 +}; + + diff --git a/lib_dec/rom_dec_fx.h b/lib_dec/rom_dec_fx.h new file mode 100644 index 0000000..d99979e --- /dev/null +++ b/lib_dec/rom_dec_fx.h @@ -0,0 +1,86 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#ifndef ROM_DEC_FX_H +#define ROM_DEC_FX_H + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" + +/*----------------------------------------------------------------------------------* + * General tables + *----------------------------------------------------------------------------------*/ +extern const Word16 gw_fx[Lgw_max]; +extern const Word16 gw_len_inv_fx[Lgw_max-1]; +extern const Word16 gwlpr_fx[Lgw_max]; + +extern const Word16 hestable_fx[15]; + +extern const Word16 h_high_fx[5]; +extern const Word16 inv_sqi[15]; +extern const Word16 sqi[15]; + + +/*------------------------------------------------------------------------------* + * AVQ - RE8 tables + *------------------------------------------------------------------------------*/ + +extern const Word16 mult_avq_tab_fx[]; +extern const Word16 shift_avq_tab_fx[]; + +/*----------------------------------------------------------------------------------* + * HR SWB BWE parameters + *----------------------------------------------------------------------------------*/ + +extern const Word16 swb_hr_inv_frm_len[4]; /* in Q19 */ +extern const Word16 inv_tbl_2n_minus1[]; + +/*---------------------------------------------------------------------* + * TABLE ROM, defined in lib_dec_fx\rom_dec_fx.c + *---------------------------------------------------------------------*/ + +extern const Word16 hntable_fx[55]; +extern const Word16 hetable_fx[57]; + +extern const Word16 H_low[5]; + +extern const Word16 lsf_tab_fx[LPC_SHB_ORDER]; + +/*---------------------------------------------------------------------* + * NB post-filter tables + *---------------------------------------------------------------------*/ + +extern const Word16 Tab_hup_s[]; +extern const Word16 Tab_hup_l[]; + + +/*----------------------------- + * FEC_HQ_phase_ecu + *------------------------------*/ +extern const Word16 FFT_W256[]; +extern const Word16 w_hamm_sana48k_2_fx[]; +extern const Word16 w_hamm48k_2_fx[]; +extern const Word16 w_hamm32k_2_fx[]; +extern const Word16 w_hamm16k_2_fx[]; +extern const Word16 POW_ATT_TABLE0[]; +extern const Word16 POW_ATT_TABLE1[]; +extern const Word16 GR_POW_HEADROOM[]; + + +/*Table 256 / (L_frame*2) , needed in sig_classifier.c and er_dec_acelp.c*/ +extern const Word16 T_256DIV_L_Frame[]; +extern const Word16 T_DIV_L_Frame[]; /*0Q15 * 2^-7 */ + +/* er_dec_tcx.c */ +extern const Word16 h_high3_32[L_FIR_FER2]; +extern const Word16 h_high3_16[L_FIR_FER2]; + +extern const Word16 pow2tab[15]; + +/* CLDFB BPF */ +extern const Word16 bpf_weights_16_Fx[16]; + +#endif /* ROM_DEC_FX.H */ diff --git a/lib_dec/rst_dec_fx.c b/lib_dec/rst_dec_fx.c new file mode 100644 index 0000000..718f460 --- /dev/null +++ b/lib_dec/rst_dec_fx.c @@ -0,0 +1,85 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "stl.h" +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ + +/*----------------------------------------------------------------------------------* + * CNG_reset_dec() + * + * Reset decoder static variables in case of CNG frame + *----------------------------------------------------------------------------------*/ + +void CNG_reset_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *pitch_buf, /* o : floating pitch for each subframe */ + Word16 *voice_factors /* o : voicing factors */ +) +{ + Word16 tmp, exp; + Word32 L_tmp; + Copy( UVWB_Ave_fx, st_fx->mem_AR_fx, M ); + set16_fx( st_fx->mem_MA_fx, 0, M ); + /*set16_fx( st_fx->dispMem_fx, 0, 8 );*/ + set16_fx( st_fx->dm_fx.prev_gain_pit , 0, 6 ); + st_fx->dm_fx.prev_gain_code = L_deposit_l(0); + st_fx->dm_fx.prev_state = 0; + move16(); + + st_fx->tilt_code_fx = 0; + move16(); + st_fx->gc_threshold_fx = 0; + move16(); + + /* last good received frame for FEC in ACELP */ + st_fx->clas_dec = UNVOICED_CLAS; + move16(); + st_fx->last_good_fx = UNVOICED_CLAS; + move16(); + + /* LP-filtered pitch gain set to 0 */ + st_fx->lp_gainp_fx = 0; + move16(); + + /* convert CNG energy into CNG gain for ACELP FEC */ + /* st->lp_gainc = sqrt( st->lp_ener ); */ + st_fx->lp_gainc_fx = 0; + move16(); + + IF (st_fx->lp_ener_fx != 0) + { + exp = norm_l(st_fx->lp_ener_fx); /* In Q6 */ + tmp = extract_h(L_shl(st_fx->lp_ener_fx, exp)); + exp = sub(exp, 30-6); + + tmp = div_s(16384, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp); + + st_fx->lp_gainc_fx = round_fx(L_shl(L_tmp, sub(exp, 12))); /* In Q3 */ + } + /* reset the pitch buffer in case of FRAME_NO_DATA or SID frames */ + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + set16_fx( pitch_buf, L_SUBFR<<6, NB_SUBFR ); + } + ELSE /* st->L_frame == L_FRAME16k */ + { + set16_fx( pitch_buf, L_SUBFR16k<<6, NB_SUBFR16k ); + } + + set16_fx( voice_factors, 32767, NB_SUBFR16k ); + + /* deactivate bass post-filter */ + st_fx->bpf_off_fx = 1; + move16(); + /* Reset active frame counter */ + st_fx->act_cnt2_fx = 0; + move16(); + + return; +} diff --git a/lib_dec/rtpdump.c b/lib_dec/rtpdump.c new file mode 100644 index 0000000..b563d97 --- /dev/null +++ b/lib_dec/rtpdump.c @@ -0,0 +1,351 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "rtpdump.h" + +struct RTPDUMP +{ + FILE * file; + unsigned int startSeconds; + unsigned int startMicroSeconds; + unsigned int source; + unsigned short port; +}; + +/** function to read a 32-bit value from a buffer */ +static unsigned char * parseLong( unsigned char * buffer, unsigned int * value ) +{ + *value = 0; + *value = (unsigned int)( buffer[3] & 0xFF ); + *value |= (unsigned int)( buffer[2] & 0xFF ) << 8; + *value |= (unsigned int)( buffer[1] & 0xFF ) << 16; + *value |= (unsigned int)( buffer[0] & 0xFF ) << 24; + return buffer + 4; +} + +/** function to read a 16-bit value from a buffer */ +static unsigned char * parseShort( unsigned char * buffer, unsigned short * value ) +{ + *value = 0; + *value = (unsigned int)( buffer[1] & 0xFF ); + *value |= (unsigned int)( buffer[0] & 0xFF ) << 8; + return buffer + 2; +} + +/** function to read a 8-bit value from a buffer */ +static unsigned char * parseByte( unsigned char * buffer, unsigned char * value ) +{ + *value = 0; + *value = (unsigned int)( buffer[0] & 0xFF ); + return buffer + 1; +} + +/** function to read a 32-bit value from the file */ +static int readLong( FILE * file, unsigned int * value ) +{ + char buffer[4] = {0}; + if( fread( buffer, 4, 1, file ) != 1U ) + { + return -1; + } + *value = 0; + *value = (unsigned int)( buffer[3] & 0xFF ); + *value |= (unsigned int)( buffer[2] & 0xFF ) << 8; + *value |= (unsigned int)( buffer[1] & 0xFF ) << 16; + *value |= (unsigned int)( buffer[0] & 0xFF ) << 24; + return 0; +} + +/** function to read a 16-bit value from the file */ +static int readShort( FILE * file, unsigned short * value ) +{ + char buffer[2] = {0}; + if( fread( buffer, 2, 1, file ) != 1U ) + { + return -1; + } + *value = 0; + *value = (unsigned int)( buffer[1] & 0xFF ); + *value |= (unsigned int)( buffer[0] & 0xFF ) << 8; + return 0; +} + +/** function to write a 32-bit value to the file */ +static int writeLong( FILE * file, unsigned int value ) +{ + char buffer[4] = {0}; + buffer[3] = value & 0xff; + buffer[2] = (value >> 8) & 0xff; + buffer[1] = (value >> 16) & 0xff; + buffer[0] = (value >> 24) & 0xff; + if( fwrite( buffer, 4, 1, file ) != 1U ) + { + return -1; + } + return 0; +} + +/** function to write a 16-bit value to the file */ +static int writeShort( FILE * file, unsigned short value ) +{ + char buffer[2] = {0}; + buffer[1] = value & 0xff; + buffer[0] = (value >> 8) & 0xff; + if( fwrite( buffer, 2, 1, file ) != 1U ) + { + return -1; + } + return 0; +} + +/** function to write a 8-bit value to the file */ +static int writeByte( FILE * file, unsigned char value ) +{ + if(fputc(value, file) == value) + { + return 0; + } + return -1; +} + +/** function to parse the rtpdump file header */ +static int readHeader(struct RTPDUMP * hRTPDUMP) +{ + unsigned short padding; + char buffer[255] = {0}; + /* read identifier */ + /* + char buffer[255] = {0}; + const char id [] = "#!rtpplay1.0"; + fgets( buffer, sizeof(buffer), hRTPDUMP->file ); + if( memcmp( buffer, id, sizeof(id)-1 ) != 0 ) + return -1; + */ + char version [4] = {0}; + char address [128] = {0}; + unsigned int port = 0; + unsigned int a, b, c, d; + + fgets( buffer, sizeof(buffer), hRTPDUMP->file ); + if(sscanf(buffer, "#!rtpplay%3s %127[0123456789.]/%u\n", version, address, &port) == 3) + { + if(sscanf(address, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) + { + return -1; + } + } else if(sscanf(buffer, "#!rtpplay%3s %127[0123456789abcdef:]/%u\n", version, address, &port) == 3) + /* no verification of IPv6 addresses yet */ + { + } else + { + fprintf(stderr, "unable to read rtpplay\n"); + fprintf(stderr, "Buffer: %s\n", buffer); + return -1; + } + if(strcmp(version, "1.0")) + { + return -1; + } + + /* read binary header (RD_hdr_t) */ + readLong( hRTPDUMP->file, &(hRTPDUMP->startSeconds)); + readLong( hRTPDUMP->file, &(hRTPDUMP->startMicroSeconds)); + readLong( hRTPDUMP->file, &(hRTPDUMP->source)); + readShort( hRTPDUMP->file, &(hRTPDUMP->port) ); + readShort( hRTPDUMP->file, &padding ); + + return 0; +} + +static int writeHeader(struct RTPDUMP * hRTPDUMP) +{ + /* write rtpdump header */ + fprintf(hRTPDUMP->file, "#!rtpplay%s %s/%d\n", "1.0", "127.0.0.1", 5000); + if(!writeLong(hRTPDUMP->file, hRTPDUMP->startSeconds) && + !writeLong(hRTPDUMP->file, hRTPDUMP->startMicroSeconds) && + !writeLong(hRTPDUMP->file, hRTPDUMP->source) && + !writeShort(hRTPDUMP->file, hRTPDUMP->port) && + !writeShort(hRTPDUMP->file, 0) + ) + { + return 0; + } + return -1; +} + +RTPDUMP_ERROR +RTPDUMP_OpenForReading(RTPDUMP_HANDLE* phRTPDUMP, const char * filename) +{ + return RTPDUMP_OpenWithFileToRead(phRTPDUMP, fopen( filename, "rb" )); +} + +RTPDUMP_ERROR +RTPDUMP_OpenWithFileToRead(RTPDUMP_HANDLE* phRTPDUMP, FILE *file) +{ + *phRTPDUMP = (RTPDUMP_HANDLE) calloc(1, sizeof(struct RTPDUMP) ); + if ( !phRTPDUMP ) + { + return RTPDUMP_MEMORY_ERROR; + } + + /* open file stream */ + (*phRTPDUMP)->file = file; + if( (*phRTPDUMP)->file == NULL ) + { + return RTPDUMP_FILE_NOT_FOUND; + } + + if( readHeader(*phRTPDUMP) != 0) + { + return RTPDUMP_INIT_ERROR; + } + + return RTPDUMP_NO_ERROR; +} + +RTPDUMP_ERROR +RTPDUMP_OpenForWriting(RTPDUMP_HANDLE* phRTPDUMP, const char * filename) +{ + *phRTPDUMP = (RTPDUMP_HANDLE) calloc(1, sizeof(struct RTPDUMP) ); + if ( !phRTPDUMP ) + { + return RTPDUMP_MEMORY_ERROR; + } + + /* open file stream */ + (*phRTPDUMP)->file = fopen( filename, "wb" ); + if( (*phRTPDUMP)->file == NULL ) + { + return RTPDUMP_FILE_NOT_FOUND; + } + + if( writeHeader(*phRTPDUMP) != 0) + { + return RTPDUMP_INIT_ERROR; + } + + return RTPDUMP_NO_ERROR; +} + +RTPDUMP_ERROR +RTPDUMP_ReadPacket(RTPDUMP_HANDLE hRTPDUMP, + RTPDUMP_RTPPACKET * packet, + uint32_t * timeoffset_ms) +{ + unsigned short length = 0; + + if(!hRTPDUMP) + { + return RTPDUMP_NOT_INITIALIZED; + } + + /* length of packet, including this header (may be smaller than plen if not whole packet recorded) */ + if( readShort(hRTPDUMP->file, &length ) ) + { + return RTPDUMP_READ_ENDOFFILE; + } + length -= 8; + + /* actual header+payload length for RTP, 0 for RTCP */ + if( readShort(hRTPDUMP->file, &(packet->payloadSize) ) ) + { + return RTPDUMP_READ_ERROR; + } + if(packet->payloadSize < length ) + { + return RTPDUMP_UNKNOWN_ERROR; + } + + /* remove size of RTP header so that plen is payload length */ + packet->headerSize = 12; + packet->payloadSize -= packet->headerSize; + + /* milliseconds since the start of recording */ + if( readLong(hRTPDUMP->file, timeoffset_ms ) ) + { + return RTPDUMP_READ_ERROR; + } + + if(length > sizeof(packet->data) / sizeof(packet->data[0])) + { + return RTPDUMP_UNKNOWN_ERROR; + } + + /* read entire RTP packet */ + if( length != 0U) + { + fread( packet->data, length, 1, hRTPDUMP->file ); + } + + RTPDUMP_ParseRTPHeader(packet); + return RTPDUMP_NO_ERROR; +} + +RTPDUMP_ERROR +RTPDUMP_WritePacket(RTPDUMP_HANDLE hRTPDUMP, + const RTPDUMP_RTPPACKET * packet, + uint32_t timeoffset_ms) +{ + /* rtpdump packet header */ + writeShort(hRTPDUMP->file, 8 + packet->headerSize + packet->payloadSize); + writeShort(hRTPDUMP->file, packet->headerSize + packet->payloadSize); + writeLong(hRTPDUMP->file, timeoffset_ms); + + /* RTP header */ + writeByte(hRTPDUMP->file, packet->v_p_x_xx); + writeByte(hRTPDUMP->file, packet->payloadTypeId); + writeShort(hRTPDUMP->file, packet->sequenceNumber); + writeLong(hRTPDUMP->file, packet->timeStamp); + writeLong(hRTPDUMP->file, packet->ssrc); + + /* RTP payload */ + fwrite(packet->data + packet->headerSize, packet->payloadSize, 1, hRTPDUMP->file); + return RTPDUMP_NO_ERROR; +} + +void +RTPDUMP_Close(RTPDUMP_HANDLE* phRTPDUMP, short closeFile) +{ + if ( !phRTPDUMP ) + { + return; + } + + if ( !(*phRTPDUMP) ) + { + return; + } + + if(closeFile && (*phRTPDUMP)->file) + { + fclose((*phRTPDUMP)->file); + } + + free(*phRTPDUMP); + *phRTPDUMP = NULL; +} + +void RTPDUMP_SetDefaultRtpPacketHeader(RTPDUMP_RTPPACKET * packet) +{ + packet->v_p_x_xx = 128; + packet->payloadTypeId = 96; + packet->sequenceNumber = 0; + packet->timeStamp = 0; + packet->ssrc = 0xaabbccdd; + packet->headerSize = 12; + packet->payloadSize = 0; +} + +void RTPDUMP_ParseRTPHeader(RTPDUMP_RTPPACKET * packet) +{ + unsigned char *payload = (unsigned char *)packet->data; + payload = parseByte(payload, &(packet->v_p_x_xx)); + payload = parseByte(payload, &(packet->payloadTypeId)); + payload = parseShort(payload, &(packet->sequenceNumber)); + payload = parseLong(payload, &(packet->timeStamp)); + parseLong(payload, &(packet->ssrc)); +} diff --git a/lib_dec/rtpdump.h b/lib_dec/rtpdump.h new file mode 100644 index 0000000..e6880f9 --- /dev/null +++ b/lib_dec/rtpdump.h @@ -0,0 +1,74 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#pragma once +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum _RTPDUMP_ERROR +{ + RTPDUMP_NO_ERROR = 0x0000, + RTPDUMP_MEMORY_ERROR = 0x0001, + RTPDUMP_WRONG_PARAMS = 0x0002, + RTPDUMP_INIT_ERROR = 0x0003, + RTPDUMP_WRITE_ERROR = 0x0004, + RTPDUMP_READ_ERROR = 0x0005, + RTPDUMP_FILE_NOT_FOUND = 0x0006, + RTPDUMP_NOT_IMPLEMENTED = 0x0010, + RTPDUMP_NOT_INITIALIZED = 0x0100, + RTPDUMP_READ_ENDOFFILE = 0x0101, + RTPDUMP_UNKNOWN_ERROR = 0x1000 +} RTPDUMP_ERROR; + +typedef struct RTPDUMP * RTPDUMP_HANDLE; +typedef struct RTPDUMP RTPDUMP; + +typedef struct RTPDUMP_RTPPACKET +{ + unsigned char v_p_x_xx; /* version, padding, extension etc. */ + unsigned char payloadTypeId; + unsigned short sequenceNumber; + unsigned int timeStamp; + unsigned int ssrc; + char data[1500 + 12]; /* raw RTP packet */ + unsigned short headerSize; + unsigned short payloadSize; +} RTPDUMP_RTPPACKET; + + +RTPDUMP_ERROR +RTPDUMP_OpenForReading(RTPDUMP_HANDLE* phRTPDUMP, const char * filename); + +RTPDUMP_ERROR +RTPDUMP_OpenWithFileToRead(RTPDUMP_HANDLE* phRTPDUMP, FILE *file); + +RTPDUMP_ERROR +RTPDUMP_OpenForWriting(RTPDUMP_HANDLE* phRTPDUMP, const char * filename); + +RTPDUMP_ERROR +RTPDUMP_ReadPacket(RTPDUMP_HANDLE hRTPDUMP, + RTPDUMP_RTPPACKET * packet, + uint32_t * timeoffset_ms); + +RTPDUMP_ERROR +RTPDUMP_WritePacket(RTPDUMP_HANDLE hRTPDUMP, + const RTPDUMP_RTPPACKET * packet, + uint32_t timeoffset_ms); + +void +RTPDUMP_Close(RTPDUMP_HANDLE* phRTPDUMP, short closeFile); + +void +RTPDUMP_SetDefaultRtpPacketHeader(RTPDUMP_RTPPACKET * packet); + +void +RTPDUMP_ParseRTPHeader(RTPDUMP_RTPPACKET * packet); + +#ifdef __cplusplus +} +#endif diff --git a/lib_dec/stat_dec_fx.h b/lib_dec/stat_dec_fx.h new file mode 100644 index 0000000..800d304 --- /dev/null +++ b/lib_dec/stat_dec_fx.h @@ -0,0 +1,1114 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#ifndef STAT_DEC_FX_H +#define STAT_DEC_FX_H + + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" +#include "stat_com.h" + + +/*------------------------------------------------------------------------------------------* + * Indice + *------------------------------------------------------------------------------------------*/ + + +/* decoder mode enums */ +typedef enum _DEC_MODE +{ + DEC_NO_FRAM_LOSS = 0x0, + DEC_CONCEALMENT_EXT = 0x1 +} DEC_MODE; + +typedef enum +{ + FRAMEMODE_NORMAL = 0x0, /**< frame available */ + FRAMEMODE_MISSING = 0x1, /**< frame missing => conceal */ + FRAMEMODE_FUTURE = 0x2 +} frameMode_fx; + + +struct dispMem_fx +{ + Word16 prev_state; /*Q0 */ + Word32 prev_gain_code; /*Q16 */ + Word16 prev_gain_pit[6]; /*Q14 */ +}; + + +/*ari.h*/ +typedef struct +{ + Word32 low,high,vobf; +} TastatDec; + +/*---------------------------------------------------------------* + * IGF * + *---------------------------------------------------------------*/ +/* IGFSCFDecoder.h */ +typedef struct +{ + Word16 bitsRead; /* after a call bitsRead contains the number of bits consumed by the decoder */ + Word16 prev[64]; /* no more than 64 SCFs for the IGF energy envelope of one block, short or long */ + Word16 scfCountLongBlock; + Word16 t; + const Word16 *cf_se00; + const Word16 *cf_se01; + Word16 cf_off_se01; + const Word16 *cf_se02; + const Word16 *cf_off_se02; + const Word16 *cf_se10; + Word16 cf_off_se10; + const Word16 *cf_se11; + const Word16 *cf_off_se11; + TastatDec acState; +} IGFSCFDEC_INSTANCE, *IGFSCFDEC_INSTANCE_HANDLE; + +/* IGFDec.h */ +typedef struct igfdec_private_data_struct +{ + + IGF_INFO igfInfo; + /* envelope reconstruction: */ + Word32 igf_sN[IGF_MAX_SFB]; /* Q31 | only with short blocks as static needed */ + Word16 igf_sN_e[IGF_MAX_SFB]; /* | exponent for igf_sN */ + Word32 igf_pN[IGF_MAX_SFB]; /* Q31 | only with short blocks as static needed */ + Word16 igf_pN_e[IGF_MAX_SFB]; /* | exponent for igf_sN */ + Word16 igf_curr[IGF_MAX_SFB]; /* Q0 | igf_curr = [0, 91], current igf energies from bitstream */ + Word16 igf_prev[IGF_MAX_SFB]; /* Q0 | igf_prev = [0, 91], needed for concealment or indepflag==0 */ + Word16 igf_curr_subframe[IGF_MAX_SUBFRAMES][IGF_TRANS_FAK][IGF_MAX_SFB]; /* | current igf energies per subframe */ + Word16 igf_prev_subframe[IGF_MAX_SUBFRAMES][IGF_MAX_SFB]; /* | needed for concealment or indepflag==0 */ + Word16 igf_flatteningTrigger_subframe[IGF_MAX_SUBFRAMES]; + + /* spectral whitening: */ + Word32 pSpecFlat[IGF_START_MX]; /* Q31 | MDCT spectrum before LPC shaping */ + Word16 pSpecFlat_exp; /* | exponent of pSpecFlat */ + Word16 currWhiteningLevel[IGF_MAX_TILES]; /* Q0 | currWhiteningLevel = [0, 2], whitening lvl from bitstream */ + Word16 prevWhiteningLevel[IGF_MAX_TILES]; /* Q0 | prevWhiteningLevel = [0, 2], needed for concealment */ + Word16 currWhiteningLevel_subframe[IGF_MAX_SUBFRAMES][IGF_MAX_TILES]; + Word16 prevWhiteningLevel_subframe[IGF_MAX_SUBFRAMES][IGF_MAX_TILES]; /* | needed for concealment */ + + Word32 totalNoiseNrg; + Word16 n_noise_bands; + Word16 headroom_TCX_noise_white; + Word16 headroom_TCX_noise; + + Word32 totalNoiseNrg_off; + Word16 n_noise_bands_off; + + /* IGF SCF decoding: */ + IGFSCFDEC_INSTANCE hArithSCFdec; + + /* concealment: */ + Word16 frameLossCounter; + +} IGFDEC_PRIVATE_DATA,*IGF_DEC_PRIVATE_DATA_HANDLE; + +typedef struct igfdec_instance_struct +{ + Word16 isIGFActive; + Word16 infoIGFAllZero; + Word16 infoIGFStopLine; + Word16 infoIGFStartLine; + Word16 infoIGFStopFreq; + Word16 infoIGFStartFreq; + Word16 infoTCXNoise[IGF_START_MX]; + Word16 flag_sparse[N_MAX_TCX-IGF_START_MN]; + Word32 virtualSpec[N_MAX_TCX-IGF_START_MN]; /* Q31 | buffer for temp flattening */ + Word16 virtualSpec_e; /* | exponent of virtualSpec */ + Word16 flatteningTrigger; + IGFDEC_PRIVATE_DATA igfData; +} IGFDEC_INSTANCE, *IGF_DEC_INSTANCE_HANDLE; + +typedef struct +{ + Word16 FrameSize; + Word16 Pitch_fx; + Word8 T_bfi_fx; + Word16 Transient[MAX_POST_LEN]; + Word16 TCX_Tonality[DEC_STATE_LEN]; + Word16 outx_new_n1_fx; + Word16 nsapp_gain_fx; + Word16 nsapp_gain_n_fx; + Word32 data_reci2_fx[L_FRAME_MAX]; + Word16 data_reci2_scale; + Word16 data_noise[L_FRAME_MAX]; + Word32 ener_mean_fx; + Word32 ener_fx; + Word16 zp_fx; + Word16 recovery_gain; /*outside waveformadjustment: Q14 - insinde waveformadjustment: Q15*/ + Word16 step_concealgain_fx; + Word16 concealment_method; + Word16 subframe_fx; + Word32 nbLostCmpt; + Word16 seed; +} T_PLCInfo; + +/*---------------------------------------------------------------* + * Structures for Tonal MDCT PLC * + *---------------------------------------------------------------*/ +typedef enum +{ + TONALMDCTCONCEAL_OK = 0, + + __error_codes_start = -100, + + TONALMDCTCONCEAL_NSAMPLES_LARGER_THAN_MAXBLOCKSIZE, + TONALMDCTCONCEAL_INVALIDPOINTER, + TONALMDCTCONCEAL_UNEXPECTED_ERROR, + + __error_codes_end +} TONALMDCTCONCEAL_ERROR; + +typedef struct +{ + Word16 nSamples; + Word16 nSamplesCore; + Word16 * spectralData; + Word16 spectralData_exp; + Word16 * scaleFactors; + Word16 * scaleFactors_exp; + Word16 scaleFactors_max_e; + Word16 gain_tcx_exp; + Word8 blockIsValid; + Word16 blockIsConcealed; + Word8 tonalConcealmentActive; +} blockData; + +typedef struct +{ + Word16 numIndexes; + Word16 indexOfTonalPeak[MAX_NUMBER_OF_IDX]; + Word16 lowerIndex[MAX_NUMBER_OF_IDX]; + Word16 upperIndex[MAX_NUMBER_OF_IDX]; + Word16 phaseDiff[MAX_NUMBER_OF_IDX]; /* This one can be stored with 16 bits in range 0..2*PI */ + Word16 phase_currentFramePredicted[MAX_NUMBER_OF_IDX*GROUP_LENGTH]; /* This one can be stored with 16 bits in range [-pi;pi] 2Q13, but the code has to be adapted to use moduo(2*PI) after adding */ +} TonalComponentsInfo; + +typedef void (*ApplyScaleFactorsPointer)(Word16 const x[], Word16 lg, Word16 lg_total, Word16 const scaleFactors[], Word16 const scaleFactors_exp[], Word16 gains_max_exp, Word32 y[]); + +struct tonalmdctconceal +{ + TCX_config * tcx_cfg; + Word16 * pMDSTData; + Word16 nSamples; + Word16 nSamplesCore; + Word16 nNonZeroSamples; + Word16 nScaleFactors; + + Word32 lastPitchLag; + + blockData lastBlockData; + blockData secondLastBlockData; + + Word16 scaleFactorsBuffers[2][FDNS_NPTS]; /* Contains also global gain. */ + Word16 scaleFactorsBuffers_exp[2][FDNS_NPTS]; + Word16 spectralDataBuffers[2][L_FRAME_MAX]; /* 16 bits is enough, because it is stored before applying scale factors. Take care that power spectrum is also stored here. */ + Word16 timeDataBuffer[(3*L_FRAME_MAX)/2]; /* 16 bits are enough for the TD signal */ + + Word16 * lastPcmOut; + Word16 * secondLastPcmOut; + Word16 * secondLastPowerSpectrum; + Word16 secondLastPowerSpectrum_exp; + + Word16 nFramesLost; + + TonalComponentsInfo * pTCI; +}; + +typedef struct tonalmdctconceal* TonalMDCTConcealPtr; + +/*****************************************/ +/* STAT DEC */ +/*****************************************/ + +/*fd_cng_dec.h*/ +/* Arrays and variables specific to decoder */ +typedef struct +{ + HANDLE_FD_CNG_COM hFdCngCom; + + Word16 olapBufferAna[320]; + Word16 olapBufferSynth2[FFTLEN]; + + Word32 msPeriodog[NPART_SHAPING]; /* Periodogram */ + Word16 msPeriodog_exp; /* Common exponent for fft and cldfb energies */ + Word16 msPeriodog_exp_fft; + Word16 msPeriodog_exp_cldfb; + Word32 msBminWin[NPART_SHAPING]; + Word32 msBminSubWin[NPART_SHAPING]; + Word16 msPsd[NPART_SHAPING]; /* Power Spectral Density estimate (i.e., smoothed periodogram) */ + Word16 msPsd_exp_fft; + Word32 msAlpha[NPART_SHAPING]; /* Optimal smoothing parameter */ + + + Word32 msMinBuf[MSNUMSUBFR*NPART_SHAPING]; /* Buffer of minima */ + Word32 msCurrentMinOut[NPART_SHAPING]; + Word32 msCurrentMin[NPART_SHAPING]; + Word32 msCurrentMinSubWindow[NPART_SHAPING]; + + Word16 msLocalMinFlag[NPART_SHAPING]; + Word16 msNewMinFlag[NPART_SHAPING]; + + Word16 msPsdFirstMoment[NPART_SHAPING]; + Word32 msPsdSecondMoment[NPART_SHAPING]; + Word16 msNoiseFloor[NPART_SHAPING]; /* Estimated noise floor */ + Word32 msNoiseEst[NPART_SHAPING]; /* Estimated noise level */ + Word16 msNoiseEst_exp; + + Word16 npart_shaping; /* Number of partitions */ + Word16 nFFTpart_shaping; /* Number of hybrid spectral partitions */ + Word16 part_shaping[NPART_SHAPING]; /* Partition upper boundaries (band indices starting from 0) */ + Word16 midband_shaping[NPART_SHAPING]; /* Central band of each partition */ + Word16 psize_shaping[NPART_SHAPING]; /* Partition sizes */ + Word16 psize_shaping_norm[NPART_SHAPING]; /* Partition sizes, fractional variable */ + Word16 psize_shaping_norm_exp; /* Partition sizes exponent for fractional variable */ + Word16 psize_inv_shaping[NPART_SHAPING]; /* Inverse of partition sizes */ + Word32 bandNoiseShape[FFTLEN2]; /* CNG spectral shape computed at the decoder */ + Word16 bandNoiseShape_exp; /* exponent of bandNoiseShape */ + Word32 partNoiseShape[NPART]; /* CNG spectral shape computed at the decoder */ + Word16 partNoiseShape_exp; /* exponent of partNoiseShape */ + + Word16 flag_dtx_mode; + + Word32 lp_speech; /* format: Q9.23 */ + Word32 lp_noise; /* format: Q9.23 */ + + Word16 msPeriodogBuf[MSBUFLEN*NPART_SHAPING]; + Word16 msPeriodogBufPtr; + + Word16 msLogPeriodog[NPART_SHAPING]; + Word16 msLogNoiseEst[NPART_SHAPING]; +} +FD_CNG_DEC; +typedef FD_CNG_DEC *HANDLE_FD_CNG_DEC; + + +typedef struct Decoder_State_fx +{ + + /*----------------------------------------------------------------------------------* + * Common parameters + *----------------------------------------------------------------------------------*/ + Word16 codec_mode; /* MODE1 or MODE2 */ + Word16 mdct_sw_enable; /* MDCT switching enable flag */ + Word16 mdct_sw; /* MDCT switching indicator */ + Word16 last_codec_mode; /* last used codec mode*/ + UWord16 *bit_stream_fx; + Word16 next_bit_pos_fx; /* position of the next bit to be read from the bitstream */ + Word16 bitstreamformat; /* Bitstream format flag (G.192/MIME/VOIP_G192_RTP/VOIP_RTPDUMP) */ + Word16 sdp_hf_only; /* RTP payload format parameter: only Header-Full format without zero padding for size collision avoidance */ + Word16 amrwb_rfc4867_flag; /* MIME from rfc4867 is used */ + Word16 total_num_bits; /* == st->total_brate / 50 */ + Word16 BER_detect; /* flag to signal detected bit error in the bitstream */ + + Word32 output_Fs_fx; /* output sampling rate Q0*/ + Word16 output_frame_fx; /* Output frame length Q0*/ + Word32 total_brate_fx; /* total bitrate in kbps of the codec Q0*/ + Word32 last_total_brate_fx; /* last total bitrate in kbps of the codec Q0*/ + Word32 last_total_brate_ber_fx; /* last total bitrate in kbps of the codec - used only when first frame is lost and BER is detected afterwards */ + Word16 core_fx; /* core (ACELP_CORE, TCX_20_CORE, TCX_10_CORE, HQ_CORE, AMR_WB_CORE) */ + Word32 core_brate_fx; /* core bitrate */ + Word32 last_core_brate_fx; /* previous frame core bitrate Q0*/ + Word16 extl_fx; /* extension layer Q0*/ + Word16 last_extl_fx; /* previous extension layer Q0*/ + Word32 extl_brate_fx; /* extension layer bitrate */ + Word16 L_frame_fx; /* ACELP core internal frame length */ + Word16 bwidth_fx; /* encoded signal bandwidth */ + Word16 Opt_AMR_WB_fx; /* flag indicating AMR-WB IO mode Q0*/ + Word16 Opt_VOIP_fx; /* flag indicating VOIP mode with JBM */ + Word16 ini_frame_fx; /* initialization frames counter */ + Word16 CNG_fx; /* RXDTX handler: CNG=1, nonCNG=0 */ + Word16 prev_ft_speech_fx; /* RXDTX handler: previous frametype flag for G.192 format AMRWB SID_FIRST detection */ + + /*----------------------------------------------------------------------------------* + * ACELP core parameters + *----------------------------------------------------------------------------------*/ + + Word16 old_exc_fx[L_EXC_MEM_DEC]; /* old excitation Q_exc*/ + Word16 old_excFB_fx[L_FRAME48k]; /* old excitation FB */ + Word16 lsp_old_fx[M]; /* old LSP vector at the end of the frame Q15*/ + Word16 lsf_old_fx[M]; /* old LSF vector at the end of the frame Q2.56*/ + Word32 offset_scale1_fx[MAX_NO_MODES+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure 1st 8-dim subvector*/ + Word32 offset_scale2_fx[MAX_NO_MODES+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure 2nd 8-dim subvector*/ + Word32 offset_scale1_p_fx[MAX_NO_MODES_p+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure, pred. case, 1st 8-dim subvector*/ + Word32 offset_scale2_p_fx[MAX_NO_MODES_p+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure, pred. case, 2nd 8-dim subvector*/ + Word16 no_scales_fx[MAX_NO_MODES][2]; /* LSF LVQ structure Q0*/ + Word16 no_scales_p_fx[MAX_NO_MODES_p][2]; /* LSF LVQ structure Q0*/ + Word16 tilt_code_fx; /* tilt of code Q15*/ + Word16 mem_syn2_fx[M]; /* synthesis filter memory Q_syn*/ + Word16 mem_syn1_fx[M]; /* synthesis filter memory (for core switching and FD BWE) */ + Word16 mem_syn3_fx[M]; + Word16 mem_deemph_fx; /* deemphasis filter memory Q_syn*/ + Word32 L_mem_hp_out_fx[5]; /* hp filter memory for synthesis */ + Word16 mem_MA_fx[M]; /* MA memory of LSF quantizer (past quantized residual)(Qx2.56)*/ + Word16 mem_AR_fx[M]; /* AR memory of LSF quantizer (past quantized LSFs without mean)(Qx2.56) */ + Word16 stab_fac_fx; /* LSF stability factor Q15*/ + Word16 stab_fac_smooth_fx; /* low-pass filtered stability factor Q15*/ + Word16 last_coder_type_fx; /* previous coder type Q0*/ + Word16 agc_mem_fx[2]; /* memory of AGC for saturation control Q0*/ + Word16 past_qua_en_fx[GAIN_PRED_ORDER]; /* gain quantization memory (used also in AMR-WB IO mode) */ + Word16 mid_lsf_int_fx; + Word16 safety_net_fx; + + Word16 seed_tcx_fx; /* AC mode (GSC) - seed for noise fill Q0*/ + Word16 GSC_noisy_speech_fx; /* AC mode (GSC) - flag to indicate GSC osn SWB noisy speech */ + Word16 Last_GSC_noisy_speech_flag_fx; /* AC mode (GSC) - mem of the past flag to indicate GSC osn SWB noisy speech */ + Word16 cor_strong_limit_fx; /* AC mode (GSC) - Indicator about high spectral correlation per band */ + Word16 old_y_gain_fx[MBANDS_GN]; /* AC mode (GSC) - AR mem for low rate gain quantization */ + Word16 noise_lev_fx; /* AC mode (GSC) - noise level Q0*/ + Word16 lt_ener_per_band_fx[MBANDS_GN]; /* Q12 */ + Word32 Last_frame_ener_fx; /* AC mode (GSC) - last frame energy */ + Word16 Last_GSC_spectrum_fx[L_FRAME]; /* AC mode (GSC) - Last good GSC spectrum */ + Word16 Last_GSC_pit_band_idx_fx; /* AC mode (GSC) - Last pitch band index Q0*/ + Word16 last_exc_dct_in_fx[L_FRAME]; /* AC mode (GSC) - previous excitation */ + Word16 last_ener_fx; /* AC mode (GSC) - previous energy */ + Word16 last_bitallocation_band_fx[6]; /* AC mode (GSC) - previous bit allocation of each band */ + + Word32 gc_threshold_fx; /* Noise enhancer - threshold for gain_code Q16*/ + struct dispMem_fx dm_fx; /* Noise enhancer - phase dispersion algorithm memory */ + + Word16 prev_r_fx; /* HF BWE - previous sub-frame gain */ + Word16 fmerit_w_sm_fx; /* HF BWE - fmerit parameter memory */ + Word16 frame_count_fx; /* HF BWE - frame count */ + Word16 ne_min_fx; /* HF BWE - minimum Noise gate - short-term energy */ + Word16 fmerit_m_sm_fx; /* HF BWE - memory of fmerit_m param */ + Word16 voice_fac_amr_wb_hf; /* HF BWE - voice factor */ + Word16 unvoicing_fx; /* HF BWE - unvoiced parameter */ + Word16 unvoicing_sm_fx; /* HF BWE - smoothed unvoiced parameter */ + Word16 unvoicing_flag_fx; /* HF BWE - unvoiced flag */ + Word16 voicing_flag_fx; /* HF BWE - voiced flag */ + Word16 start_band_old_fx; /* HF BWE - previous start point for copying frequency band */ + Word32 OptCrit_old_fx; /* HF BWE - previous criterion value for deciding the start point */ + + Word16 seed2_fx; /* HF (6-7kHz) BWE - seed for random signal generator Q0*/ + Word16 mem_hp400_fx[6]; /* HF (6-7kHz) BWE - hp400 filter memory */ + Word16 mem_hf_fx[2*L_FILT16k]; /* HF (6-7kHz) BWE - band-pass filter memory Q(-2-memExp1)*/ + Word16 mem_syn_hf_fx[M]; /* HF (6-7kHz) BWE - synthesis filter memory Q0*/ + Word16 delay_syn_hf_fx[NS2SA(16000,DELAY_CLDFB_NS)]; /* HF (6-7kHz) BWE - To synchronise BWE content with postfiltered synthesis Q0*/ + Word16 mem_hp_interp_fx[INTERP_3_1_MEM_LEN]; /* HF (6-7 kHz) BWE - interp. memory */ + + Word16 unv_cnt_fx; /* Stationary noise UV modification - unvoiced frame counter Q0*/ + Word16 uv_count_fx; /* Stationary noise UV modification - unvoiced counter Q0*/ + Word16 act_count_fx; /* Stationary noise UV modification - activation counter Q0*/ + Word32 ge_sm_fx; /* Stationary noise UV modification - smoothed excitation gain Q(GE_SHIFT)*/ + Word16 lspold_s_fx[M]; /* Stationary noise UV modification - old LSP vector Q15*/ + Word16 noimix_seed_fx; /* Stationary noise UV modification - mixture seed Q0*/ + Word16 min_alpha_fx; /* Stationary noise UV modification - minimum alpha Q15*/ + Word16 Q_stat_noise; /* Q of Exc_pe */ + Word16 exc_pe_fx; /* Stationary noise UV modification - scale (Q_stat_noise) */ + Word16 Q_stat_noise_ge; /* Q of ge_sm_fx */ + + Word16 bfi_fx; /* FEC - bad frame indicator */ + Word16 prev_bfi_fx; /* FEC - previous bad frame indicator Q0*/ + Word16 seed_fx; /* FEC - seed for random generator for excitation Q0*/ + Word16 lp_ener_FER_fx; /* FEC - long-term active-signal average energy Q8*/ + Word16 last_good_fx; /* FEC - clas of last good received Q0*/ + Word16 lp_gainc_fx; /* FEC - low-pass filtered code gain Q3*/ + Word16 lp_gainp_fx; /* FEC - low-pass filtered pitch gain Q14 */ + Word32 lp_ener_fx; /* FEC - low-pass filtered energy Q6*/ + Word32 enr_old_fx; /* FEC - energy of the concealed frame Q0*/ + Word16 bfi_pitch_fx; /* FEC - pitch for FEC */ + Word16 bfi_pitch_frame_fx; /*FEC - frame length when pitch for FEC is saved Q0*/ + Word32 old_pitch_buf_fx[2*NB_SUBFR16k+2]; /* FEC - buffer of old subframe pitch values 15Q16 */ + Word16 upd_cnt_fx; /* FEC - counter of frames since last update Q0*/ + Word16 scaling_flag; /* FEC - flag to indicate energy control of syn */ + Word32 lp_ener_FEC_av; /* FEC - averaged voiced signal energy Q0 */ + Word32 lp_ener_FEC_max; /* FEC - averaged voiced signal energy Q0 */ + Word16 old_enr_LP; /* FEC - LP filter gain Q5*/ + Word16 lsfoldbfi0_fx[M]; /* FEC - LSF vector of the previous frame (Qx2.56)*/ + Word16 lsfoldbfi1_fx[M]; /* FEC - LSF vector of the past previous frame (Qx2.56) */ + Word16 lsf_adaptive_mean_fx[M]; /* FEC - adaptive mean LSF vector for FEC (Qx2.56)*/ + Word16 decision_hyst_fx; /* FEC - hysteresis of the music/speech decision Q0*/ + Word16 old_exc2_fx[L_EXC_MEM]; /* FEC - old excitation2 used in fast recovery */ + Word16 old_syn2_fx[L_EXC_MEM]; /* FEC - old syn speech used in fast recovery */ + Word16 relax_prev_lsf_interp_fx; + Word16 mem_syn_clas_estim_fx[L_SYN_MEM_CLAS_ESTIM]; /* FEC - memory of the synthesis signal for frame class estimation */ + Word16 tilt_swb_fec_fx; /* FEC - SWB TBE TILT */ + + Word16 cng_seed_fx; /*CNG and DTX - seed for white noise random generator*/ + Word16 lspCNG_fx[M]; /* CNG and DTX - LP filtered ISPs Q15*/ + Word16 first_CNG_fx; /* CNG and DTX - first CNG frame flag Q0*/ + Word32 Enew_fx; /* CNG and DTX - decoded residual energy Q6*/ + Word16 old_enr_index_fx; /* CNG and DTX - index of last encoded CNG energy Q0*/ + Word16 cng_ener_seed_fx; /*CNG and DTX - seed for random generator for variation of excitation energyQ0*/ + Word16 cng_ener_seed1_fx; + Word16 last_allow_cn_step_fx; /*Q0*/ + Word16 ho_hist_size_fx; /* CNG and DTX - size of DTX hangover history buffer for averaging, <0,HO_HIST_SIZE> */ + Word16 ho_hist_ptr_fx; /* CNG and DTX - pointer for averaging buffers */ + Word32 ho_sid_bw_fx; /* CNG and DTX - SID bandwidth flags */ + Word16 ho_lsp_hist_fx[HO_HIST_SIZE*M]; /* CNG and DTX - old LSP buffer for averaging */ + Word32 ho_ener_hist_fx[HO_HIST_SIZE]; /* CNG and DTX - energy buffer for averaging */ /*Q6 */ + Word32 ho_env_hist_fx[HO_HIST_SIZE*NUM_ENV_CNG]; + Word16 act_cnt_fx; /* CNG and DTX - counter of active frames */ + Word16 ho_circ_size_fx; /* CNG and DTX - size of DTX hangover history buffer for averaging, <0,HO_HIST_SIZE> */ + Word16 ho_circ_ptr_fx; /* CNG and DTX - pointer for averaging buffers */ + Word16 ho_lsp_circ_fx[HO_HIST_SIZE*M]; /* CNG and DTX - old LSP buffer for averaging */ + Word32 ho_ener_circ_fx[HO_HIST_SIZE]; /* CNG and DTX - energy buffer for averaging */ /* Q6 */ + Word32 ho_env_circ_fx[HO_HIST_SIZE*NUM_ENV_CNG]; + Word16 num_ho_fx; /* DTX/CNG - number of selected hangover frames */ + Word16 ho_16k_lsp_fx[HO_HIST_SIZE]; /* DTX/CNG - 16k LSPs flags */ + Word16 CNG_mode_fx; /* DTX/CNG - mode for DTX configuration */ + Word32 last_active_brate_fx; /* DTX/CNG - last active frame bitrate used for CNG_mode control */ + Word16 last_CNG_L_frame_fx; /* DTX/CNG - last CNG frame length */ + Word16 act_cnt2_fx; /* DTX/CNG - counter of active frames for CNG_mode switching */ + Word16 cng_type_fx; /* DTX/CNG - flag indicating LP or CLDFB based SID/CNG */ + Word16 last_cng_type_fx; /* DTX/CNG - flag indicating last frame LP or CLDFB based SID/CNG */ + Word32 old_env_fx[20]; + Word32 lp_env_fx[20]; + Word16 exc_mem_fx[24]; + Word16 exc_mem1_fx[30]; + + Word16 bpf_off_fx; /* Bass post-filter - do not use BPF when this flag is set to 1 Q0*/ + Word16 pst_old_syn_fx[NBPSF_PIT_MAX]; /* Bass post-filter - old synthesis buffer 1 Q_syn2-1*/ + Word16 pst_mem_deemp_err_fx; /* Bass post-filter - filter memory of noise LP filter Q_syn2-1*/ + Word16 pst_lp_ener_fx; /* Bass post-filter - long-term energy Q8*/ + Word16 Track_on_hist_fx[L_TRACK_HIST]; /* Bass post-filter - History of half frame usage */ + Word16 vibrato_hist_fx[L_TRACK_HIST]; /* Bass post-filter - History of frames declared as vibrato */ + Word16 psf_att_fx; /* Bass post-filter - post filter attenuation factor */ + Word16 mem_mean_pit_fx[L_TRACK_HIST]; /* Bass post-filter - average pitch memory */ + + Word16 Ng_ener_ST_fx; /* Noise gate - short-term energy Q8*/ + + Word16 last_L_frame_fx; /* ACELP@16kHz - last value of st->L_frame */ + Word16 mem_preemp_preQ_fx; /* ACELP@16kHz - prequantizer preemhasis memory */ + Word16 last_nq_preQ_fx; /* ACELP@16kHz - AVQ subquantizer number of the last sub-band of the last subframe */ + Word16 use_acelp_preq; /* ACELP@16kHz - flag of prequantizer usage */ + + /* Improvement of unvoiced and audio signals in AMR-WB IO mode */ + Word16 UV_cnt_fx; /* number of consecutives frames classified as UV */ + Word16 LT_UV_cnt_fx; /* long-term consecutives frames classified as UV */ + Word16 Last_ener_fx; /* last_energy frame */ + Word16 lt_diff_etot_fx[MAX_LT]; /* stability estimation - long-term total energy variation */ + Word16 old_Aq_fx[68]; /* old LPC filter coefficient */ + Word16 lt_voice_fac_fx; /* average voice factor over 4 sub-frames */ + + /*----------------------------------------------------------------------------------* + * SC-VBR + *----------------------------------------------------------------------------------*/ + + Word16 last_ppp_mode_dec_fx; /*Q0*/ + Word16 ppp_mode_dec_fx; /*Q0*/ + Word16 last_nelp_mode_dec_fx; + Word16 nelp_mode_dec_fx; /* Q0 */ + Word16 firstTime_voiceddec_fx; /*Q0*/ + + /* DTFS variables */ + Word16 dtfs_dec_a_fx[MAXLAG_WI]; /*Variable Q format in dtfs_dec_Q*/ + Word16 dtfs_dec_b_fx[MAXLAG_WI]; /*Variable Q format in dtfs_dec_Q*/ + Word16 dtfs_dec_lag_fx; + Word16 dtfs_dec_nH_fx; + Word16 dtfs_dec_nH_4kHz_fx; /*Q0*/ + Word16 dtfs_dec_upper_cut_off_freq_of_interest_fx; /*Q0*/ + Word16 dtfs_dec_upper_cut_off_freq_fx; /*Q0*/ + Word16 ph_offset_D_fx; /* normalized by 2Pi Q15*/ + Word16 lastLgainD_fx; /* previous gain value for the low band Q11*/ + Word16 lastHgainD_fx; /* previous gain value for the high band Q11 */ + Word16 lasterbD_fx[NUM_ERB_WB]; /* previous amplitude spectrum (ERB) Q13*/ + Word16 dtfs_dec_Q; /*Q0*/ + + /* NELP decoder variables */ + Word32 bp1_filt_mem_nb_dec_fx[14]; /* qfm currently Q0*/ + Word16 bp1_filt_mem_wb_dec_fx[8]; /* qfm currently Q0*/ + Word16 shape1_filt_mem_dec_fx[10]; /* qfm currently Q0*/ + Word16 shape2_filt_mem_dec_fx[10]; /* qfm currently Q0*/ + Word16 shape3_filt_mem_dec_fx[10]; /* qfm currently Q0*/ + Word16 nelp_dec_seed_fx; /* Q0*/ + Word16 FadeScale_fx; /*Q15*/ + Word16 prev_gain_pit_dec_fx; /*Q14*/ + Word16 prev_tilt_code_dec_fx; /*Q15*/ + + /*----------------------------------------------------------------------------------* + * channel-aware mode + *----------------------------------------------------------------------------------*/ + + Word16 tilt_code_dec_fx[NB_SUBFR16k]; + Word16 rf_frame_type; + Word16 use_partial_copy; + Word16 prev_use_partial_copy; + Word16 rf_flag; + Word16 rf_flag_last; + + Word16 rf_fec_offset; + Word16 next_coder_type; + Word16 prev_rf_frame_type; + Word16 rf_target_bits; + + Word16 rf_indx_nelp_fid; + Word16 rf_indx_nelp_iG1; + Word16 rf_indx_nelp_iG2[2]; + Word16 rf_indx_tbeGainFr; + + /*----------------------------------------------------------------------------------* + * HR SWB BWE parameters + *----------------------------------------------------------------------------------*/ + + Word16 bwe_highrate_seed_fx; + Word16 t_audio_prev_fx[2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_START_FREQ_COEF]; + Word16 t_audio_prev_fx_exp[NUM_TIME_SWITCHING_BLOCKS]; + Word16 old_is_transient_hr_bwe_fx; + Word32 L_mem_EnergyLT_fx; + Word16 mem_EnergyLT_fx_exp; + + /*----------------------------------------------------------------------------------* + * HQ core parameters + *----------------------------------------------------------------------------------*/ + + Word16 synth_history_fx[Lprot48k + L_FRAME_MAX]; /* unified synthesis memory */ + Word16 *old_synthFB_fx; + Word16 old_out_fx[L_FRAME48k]; /* HQ core - previous synthesis for OLA */ + + Word16 old_out_LB_fx[L_FRAME32k]; /* HQ core - previous synthesis for OLA for Low Band */ + Word16 Q_old_wtda_LB; + Word16 Q_old_wtda; + Word16 Q_old_postdec; /*scaling of the output of core_switching_post_dec_fx() */ + Word16 Qprev_synth_buffer_fx; + Word32 oldIMDCTout_fx[L_FRAME8k/2]; + Word16 prev_oldauOut_fx[L_FRAME8k]; + Word16 old_auOut_2fr_fx[L_FRAME8k*2]; + Word16 old_out_pha_fx[2][N_LEAD_NB]; /* FEC for HQ Core, 0-phase matching old_out, 1-overlapping original old_out and phase matching old_out*/ + Word16 diff_energy_fx; + Word32 old_coeffs_fx[L_FRAME8k]; /* HQ core - old coefficients (for FEC) */ + Word16 stat_mode_out_fx; + Word16 stat_mode_old_fx; + Word16 phase_mat_flag_fx; + Word16 phase_mat_next_fx; + Word16 old_Min_ind_fx; + Word16 old_is_transient_fx[3]; /* HQ core - previous transient flag (for FEC) */ + Word16 old_bfi_cnt_fx; /* HQ core - # of bfi until previous frame(for FEC) */ + Word16 prev_old_bfi_fx; + Word32 ynrm_values_fx[MAX_SB_NB][MAX_PGF]; + Word32 r_p_values_fx[MAX_SB_NB][MAX_ROW]; + /*Word16 old_hqswb_clas;*/ /* only used in inactive code, where it might probably be replaced by old_hqswb_clas_fx */ + Word16 Norm_gain_fx[SFM_N_NB]; + Word16 HQ_FEC_seed_fx; + Word16 energy_MA_Curr_fx[2]; + Word16 last_core_fx; /*Q0*/ + Word16 last_core_bs_fx; + Word16 prev_last_core_fx; + + Word16 last_hq_core_type_fx; /*Q0*/ + Word16 last_L_frame_ori_fx; + Word16 previoussynth_fx[L_FRAME48k]; + Word16 old_synth_sw_fx[NS2SA(48000,FRAME_SIZE_NS-ACELP_LOOK_NS-DELAY_BWE_TOTAL_NS)]; + Word16 delay_buf_out_fx[HQ_DELTA_MAX*HQ_DELAY_COMP]; /*Q0*/ + Word16 mem_norm_fx[SFM_N_ENV_STAB]; /* Q0 */ + Word16 mem_env_delta_fx; /* Q11 */ + Word16 no_att_hangover_fx; /* Q0 */ + Word32 energy_lt_fx; /* Q13 */ + Word16 hq_generic_seed_fx; + Word16 prev_noise_level_fx[2]; /* Q15 */ + Word16 prev_hqswb_clas_fx; + Word16 prev_R_fx; /* the table of bit allocation of last frame */ + Word32 prev_coeff_out_fx[L_HQ_WB_BWE]; /* Q12 */ /* the coefficients of last frame */ + Word16 prev_SWB_peak_pos_fx[SPT_SHORTEN_SBNUM]; + Word16 old_Aq_12_8_fx[M+1]; /* Q12 old Aq[] for core switching */ + Word16 old_Es_pred_fx; /* old Es_pred for core switching */ + + + Word16 HqVoicing_fx; + Word16 fer_samples_fx[L_FRAME48k]; + Word32 prev_normq_fx[SFM_N_WB]; /* Q14 */ /* previous norms */ + Word32 prev_env_fx[SFM_N_WB]; /* previous noise envelopes */ + + Word32 last_ni_gain_fx[BANDS_MAX]; + Word16 last_env_fx[BANDS_MAX]; + Word16 last_max_pos_pulse_fx; + + /* pre-echo reduction */ + Word16 memfilt_lb_fx; /* Q0 */ + Word32 mean_prev_hb_fx; /* Q0 */ + Word16 smoothmem_fx; /* Q15 */ + Word32 mean_prev_fx; /* Q0 */ + Word32 mean_prev_nc_fx; /* Q0 */ + Word16 wmold_hb_fx; /* Q15 */ + Word16 prevflag_fx; /* Q0 */ + Word16 pastpre_fx; /* Q0 */ + + Word16 prev_frm_hfe2_fx; + Word16 prev_stab_hfe2_fx; + Word16 prev_ni_ratio_fx; /* 15 */ + Word16 prev_En_sb_fx[NB_SWB_SUBBANDS]; /* QsEn(4) */ + + /* PVQ range coder state */ + UWord32 rc_low_fx; + UWord32 rc_range_fx; + UWord32 rc_help_fx; + Word16 rc_num_bits_fx; + Word16 rc_offset_fx; + Word16 rc_end_fx; + + Word16 prev_env_Q[SFM_N_WB]; + + /*----------------------------------------------------------------------------------* + * TBE parameters + *----------------------------------------------------------------------------------*/ + + /* states for the filters used in generating SHB excitation from WB excitation */ + Word16 state_lpc_syn_fx[LPC_SHB_ORDER]; + Word32 mem_csfilt_fx [2]; + + /* states for the filters used in generating SHB signal from SHB excitation*/ + Word16 state_syn_shbexc_fx[L_SHB_LAHEAD]; + Word16 syn_overlap_fx[L_SHB_LAHEAD]; /* overlap buffer used to Adjust SHB Frame Gain*/ + + /* previous frame parameters for frame error concealment */ + Word16 lsp_prevfrm_fx[ LPC_SHB_ORDER]; + Word32 GainFrame_prevfrm_fx; + Word16 GainAttn_fx; + + Word16 old_bwe_exc_fx[PIT16k_MAX * 2]; /*Q_exc*/ + Word16 bwe_seed_fx[2]; /*Q0*/ + Word32 bwe_non_lin_prev_scale_fx; + Word16 old_bwe_exc_extended_fx[NL_BUFF_OFFSET]; + Word16 last_voice_factor_fx; /* Q6*/ + + Word32 genSHBsynth_Hilbert_Mem_fx[HILBERT_MEM_SIZE]; + Word16 mem_genSHBexc_filt_down_shb_fx[2*ALLPASSSECTIONS_STEEP+1]; + Word16 mem_genSHBexc_filt_down_wb2_fx[2*ALLPASSSECTIONS_STEEP+1]; + Word16 mem_genSHBexc_filt_down_wb3_fx[2*ALLPASSSECTIONS_STEEP+1]; + Word16 genSHBsynth_state_lsyn_filt_shb_local_fx[ 2 * ALLPASSSECTIONS_STEEP ]; + Word16 state_lsyn_filt_shb_fx[ 2 * ALLPASSSECTIONS_STEEP ]; + Word16 state_lsyn_filt_dwn_shb_fx[ 2 * ALLPASSSECTIONS_STEEP ]; + Word16 state_32and48k_WB_upsample_fx[2 * ALLPASSSECTIONS_STEEP]; /* !!! this memory in FLP is called mem_resamp_HB */ + Word16 hb_prev_synth_buffer_fx[NS2SA(48000, DELAY_BWE_TOTAL_NS)]; + Word16 old_bwe_delay_fx; /*Q0*/ + + Word16 syn_dm_phase_fx; + Word32 fbbwe_hpf_mem_fx[4][4]; + Word16 fbbwe_hpf_mem_fx_Q[4]; + Word32 prev_wb_bwe_frame_pow_fx; + Word32 prev_swb_bwe_frame_pow_fx; + Word32 prev_ener_fx; + Word16 prev_ener_fx_Q; + Word16 prev_GainShape_fx; + Word16 fb_state_lpc_syn_fx[LPC_SHB_ORDER]; + Word16 prev_Q_bwe_exc_fb; + Word16 fb_tbe_demph_fx; + Word16 prev_fbbwe_ratio_fx; + + /* WB/SWB bandwidth switching */ + Word16 tilt_wb_fx; + Word16 tilt_swb_fx; + Word16 prev_ener_shb_fx; + Word32 enerLH_fx; + Word32 prev_enerLH_fx; + Word32 enerLL_fx; + Word32 prev_enerLL_fx; + + Word16 prev_fractive_fx; + Word16 prev_bws_cnt_fx; + Word16 bws_cnt_fx; + Word16 bws_cnt1_fx; + Word16 attenu_fx; + Word16 last_inner_frame_fx; /* (HQ_CORE) DCT length */ + Word16 last_bwidth_fx; + Word16 prev_weight1_fx; + Word16 t_audio_q_fx[L_FRAME]; + Word16 tbe_demph_fx; + Word16 tbe_premph_fx; + Word16 mem_stp_swb_fx[LPC_SHB_ORDER]; + Word16 *ptr_mem_stp_swb_fx; + Word16 gain_prec_swb_fx; + Word16 mem_zero_swb_fx[LPC_SHB_ORDER]; + + Word16 swb_lsp_prev_interp_fx[LPC_SHB_ORDER]; + Word32 prev1_shb_ener_sf_fx, prev2_shb_ener_sf_fx, prev3_shb_ener_sf_fx; + Word16 prev_res_shb_gshape_fx, prev_mixFactors_fx; + Word16 tilt_mem_fx; /* Formant factor adaptation tilt smoothing memory */ + Word16 prev_lsf_diff_fx[LPC_SHB_ORDER-2]; + Word16 prev_tilt_para_fx; + Word16 cur_sub_Aq_fx[M+1]; + + Word16 lsf_idx_fx[NUM_Q_LSF]; + Word16 m_idx_fx; + Word16 grid_idx_fx; + Word16 idxSubGains_fx; + Word16 idxFrameGain_fx; + Word16 idx_shb_fr_gain_fx; + Word16 idx_res_gs_fx[NB_SUBFR16k]; + Word16 idx_mixFac_fx; + + Word16 lsf_WB_fx; + Word16 gFrame_WB_fx; + + Word16 idxGain_fx; + + Word16 old_core_synth_fx[L_FRAME16k]; + Word16 old_tbe_synth_fx[L_SHB_TRANSITION_LENGTH]; + Word16 int_3_over_2_tbemem_dec_fx[INTERP_3_2_MEM_LEN]; + Word16 interpol_3_2_cng_dec_fx[INTERP_3_2_MEM_LEN]; + Word16 mem_resamp_HB_fx[INTERP_3_1_MEM_LEN]; + Word16 mem_resamp_HB_32k_fx[2*ALLPASSSECTIONS_STEEP+1]; + + /*----------------------------------------------------------------------------------* + * SWB BWE parameters + *----------------------------------------------------------------------------------*/ + Word16 old_wtda_wb_fx_exp; + Word16 L_old_wtda_swb_fx[L_FRAME48k]; + Word16 old_wtda_swb_fx_exp; + Word16 mem_imdct_exp_fx; + Word16 old_syn_12k8_16k_fx[NS2SA(16000, DELAY_FD_BWE_ENC_NS)]; /*Q_syn2-1*/ + + Word16 mem_deemph_old_syn_fx; + Word16 prev_mode_fx; + Word16 prev_SWB_fenv_fx[SWB_FENV]; + Word16 prev_Energy_fx; + Word32 prev_Energy_wb_fx; + Word16 prev_L_swb_norm_fx; + Word16 Seed_fx; + Word16 memExp1; + Word16 prev_frica_flag_fx; + Word16 mem_imdct_fx[L_FRAME48k]; + Word16 prev_td_energy_fx; + Word16 prev_weight_fx; + Word16 prev_coder_type_fx; + Word16 prev_flag_fx; + Word16 last_wb_bwe_ener_fx; + Word16 prev_frame_pow_exp; + Word16 prev_Qx; + Word16 prev_Q_bwe_exc; + Word16 prev_Q_synth; + Word16 prev_fb_ener_adjust_fx; + + /*----------------------------------------------------------------------------------* + * SWB DTX/CNG parameters + *----------------------------------------------------------------------------------*/ + + Word16 shb_cng_ener_fx; + Word16 wb_cng_ener_fx; + Word16 last_wb_cng_ener_fx; + Word16 last_shb_cng_ener_fx; + Word16 swb_cng_seed_fx; + Word16 lsp_shb_prev_prev_fx[LPC_SHB_ORDER]; + Word16 lsp_shb_prev_fx[LPC_SHB_ORDER]; + Word16 shb_dtx_count_fx; + Word16 last_vad_fx; + Word16 trans_cnt_fx; + Word16 burst_cnt_fx; + Word16 last_shb_ener_fx; + + /*----------------------------------------------------------------------------------* + * HQ FEC + *----------------------------------------------------------------------------------*/ + + Word16 *prev_good_synth_fx; + Word16 prev_sign_switch_fx[HQ_FEC_SIGN_SFM]; + Word16 prev_sign_switch_2_fx[HQ_FEC_SIGN_SFM]; + + /* HQ PHASE ECU internal state */ + Word16 time_offs_fx; + Word16 X_sav_fx[PH_ECU_SPEC_SIZE]; + Word16 Q_X_sav; + Word16 num_p_fx; + Word16 plocs_fx[MAX_PLOCS]; + Word32 plocsi_fx[MAX_PLOCS]; + Word16 env_stab_fx; + Word16 mem_norm_hqfec_fx[SFM_N_ENV_STAB]; + Word16 mem_env_delta_hqfec_fx; + Word16 env_stab_plc_fx; + Word16 env_stab_state_p_fx[NUM_ENV_STAB_PLC_STATES]; + Word16 envstabplc_hocnt_fx; + Word16 mag_chg_1st_fx[Lgw_max]; /* i/o: per band magnitude modifier for transients*/ + Word16 Xavg_fx[Lgw_max]; /* Frequency group average gain to fade to */ + Word16 beta_mute_fx; /* Factor for long-term mute */ + Word16 last_fec_fx; + Word16 ph_ecu_HqVoicing_fx; + Word16 oldHqVoicing_fx; + Word16 oldgapsynth_fx[L_FRAME48k]; + Word16 ph_ecu_active_fx; /* Set if Phase ECU was used in last bad frame */ + Word16 ni_seed_forfec; + Word16 ber_occured_in_pvq; /* flag for BER detection from PVQ routines */ + + /*----------------------------------------------------------------------------------* + * LD music post-filter + *----------------------------------------------------------------------------------*/ + Word16 LDm_mem_etot_fx; /* LD music post-filter - total energy memory */ + Word16 LDm_last_music_flag_fx; /* LD music post-filter - last music flag */ + Word16 LDm_nb_thr_1_fx; /* LD music post-filter - number of consecutives frames of level 1 */ + Word16 LDm_nb_thr_3_fx; + Word16 dct_post_old_exc_fx[DCT_L_POST-OFFSET2]; + Word16 LDm_thres_fx[4]; /* LD music post-filter - Classification threshold */ + Word16 LDm_lt_diff_etot_fx[MAX_LT]; /* LD music post-filter - long-term total energy variation */ + Word16 LDm_enh_lp_gbin_fx[VOIC_BINS_HR]; /* LD music post-filter - smoothed suppression gain, per bin FFT */ + Word32 LDm_enh_lf_EO_fx[VOIC_BINS_HR]; /* LD music post-filter - old per bin E for previous half frame */ + Word16 LDm_enh_min_ns_gain_fx; /* LD music post-filter - minimum suppression gain */ + Word32 LDm_bckr_noise_fx[MBANDS_GN_LD]; /* LD music post-filter - background noise estimation per critical band */ + Word16 filt_lfE_fx[DCT_L_POST]; + Word16 last_nonfull_music_fx; + Word16 Old_ener_Q; /* Old energy scaling factor */ + + /*----------------------------------------------------------------------------------* + * Fixed point only + *----------------------------------------------------------------------------------*/ + Word16 Q_exc; + Word16 prev_Q_exc; + Word16 Q_subfr[L_Q_MEM]; + + Word16 prev_Q_bwe_syn; + Word16 prev_Q_bwe_syn2; + + Word16 Q_syn2; + Word16 Q_syn; + Word16 prev_Q_syn; + Word16 prev_hb_synth_fx_exp; + + Word16 prev_synth_buffer_fx[NS2SA(48000,DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS)]; + Word16 prev_lpc_wb_fx[LPC_SHB_ORDER_WB]; + Word16 GainShape_Delay[NUM_SHB_SUBFR/2]; + Word16 vbr_hw_BWE_disable_dec_fx; + Word16 last_vbr_hw_BWE_disable_dec_fx; + + HANDLE_CLDFB_FILTER_BANK cldfbAna_fx; /* main analysis filter bank handle */ + HANDLE_CLDFB_FILTER_BANK cldfbBPF_fx; /* BPF analysis filter bank handle */ + HANDLE_CLDFB_FILTER_BANK cldfbSyn_fx; /* main synthesis filter bank handle */ + + Word16 last_active_bandsToZero_bwdec; + Word16 flag_NB_bwddec; + Word16 last_flag_filter_NB; + Word16 perc_bwddec; /*Q14*/ + Word16 active_frame_cnt_bwddec; + Word16 flag_buffer[20]; + Word16 total_frame_cnt_bwddec; + Word32 avg_nrg_LT; + /*Frequency-domain-based CNG*/ + HANDLE_FD_CNG_DEC hFdCngDec_fx; + + /*ACELP config*/ + Word16 force_lpd_reset; + ACELP_config acelp_cfg; /*configuration set for each frame*/ + + ACELP_config acelp_cfg_rf; /* configuration for RF frame */ + + /*TCX config*/ + TCX_config tcx_cfg; + Word16 L_frameTCX; + + /* evs decoder */ + Word16 m_decodeMode; + Word16 m_frame_type; /*ZERO_FRAME/SID_FRAME/ACTIVE_FRAME*/ + Word16 m_old_frame_type; /*ZERO_FRAME/SID_FRAME/ACTIVE_FRAME*/ + + + /*dec_prm.c*/ + Word16 bits_frame; /* bit per frame overall included */ + Word16 bits_frame_core; /* bit per frame for the core */ + Word8 narrowBand; + Word16 bits_common; /* read bits from header and LPC*/ + + Word8 last_is_cng; + + Word16 old_syn_Overl[L_FRAME32k/2]; + + Word16 syn_Overl_TDAC[L_FRAME32k/2]; + Word16 syn_Overl_TDACFB[L_FRAME_MAX/2]; + + Word16 syn_Overl[L_FRAME32k/2]; + Word16 syn_OverlFB[L_FRAME_MAX/2]; + Word16 old_synth[OLD_SYNTH_INTERNAL_DEC]; /* synthesis memory */ + Word16 old_synth_len; + Word16 old_synth_lenFB; + Word16 syn[M+1]; + + /* bass_pf.c */ + Word16 bpf_gain_param; /*int*/ /* bass post-filter gain factor parameter (0->noBpf)*/ + + Word16 L_frame_past; + Word16 L_frameTCX_past; + + Word16 lsfold_uw[M]; /* old lsf (unweighted) */ + Word16 lspold_uw[M]; /* old lsp (unweighted) */ + Word16 seed_tcx_plc; /* seed memory (for random function in TCX PLC) */ + Word16 past_gpit; /* past gain of pitch (for frame recovery) */ + Word32 past_gcode; /* past energy (!) of code (for frame recovery) */ /*15Q16*/ + Word16 lsf_cng[M]; /* xSF coefficients used for CNG generation (long term) */ + Word16 lspold_cng[M]; /* xSP coefficients used for CNG generation (long term) */ + Word8 plcBackgroundNoiseUpdated; /* flag: Is background noise estimate updated? */ + Word16 lsp_q_cng[M]; /* xSP coefficients used for CNG generation (short term interpolated) */ + Word16 old_lsp_q_cng[M]; /* xSP coefficients used for CNG generation (short term interpolated) */ + Word16 lsf_q_cng[M]; /* xSF coefficients used for CNG generation (short term interpolated) */ + Word16 old_lsf_q_cng[M]; /* xSF: old quantized lsfs for background noise */ + Word16 Aq_cng[(NB_SUBFR16k+1)*(M+1)]; /* LPC coefficients derived from CNG estimate */ + Word16 mem_syn_unv_back[M]; /* filter memory for unvoiced synth */ + Word16 last_gain_syn_deemph; /*Q15*/ + Word16 last_gain_syn_deemph_e; + Word16 last_concealed_gain_syn_deemph; /*Q15*/ + Word16 last_concealed_gain_syn_deemph_e; + + Word8 enableTcxLpc; /* global toggle for the TCX LPC quantizer */ + Word8 envWeighted; /* are is{p,f}_old[] weighted or not? */ + + /* variables for framing */ + Word16 nb_subfr; + + Word16 fscale; + Word16 fscale_old; + Word32 sr_core; /*Q0*/ + + Word16 pit_min; /*int*/ + Word16 pit_fr1; + Word16 pit_fr1b; + Word16 pit_fr2; + Word16 pit_max; /*int Q0*/ + Word16 pit_res_max; + Word16 pit_res_max_past; + + Word16 pit_max_TCX; /*int Q0*/ + Word16 pit_min_TCX; /*int*/ + + /*Preemphasis factor*/ + Word16 preemph_fac; /*0Q15*/ + Word16 gamma; + Word16 inv_gamma; + + /*for AMR-WB like 6.4 to 7 kHz upsampling and noise filling*/ + Word16 mem_Aq[(NB_SUBFR16k)*(M+1)]; /* Q12 */ + + /* Error concealment */ + Word16 last_core_bfi; + Word16 nbLostCmpt; /* compt for number of consecutive lost frame*/ + Word16 prev_nbLostCmpt; /* compt for number of consecutive lost frame at the previous frame*/ + Word16 mode_lvq; /* index for LSF mean vector */ + Word32 old_fpitch; /* last pitch of previous frame */ /*15Q16*/ + Word32 old_fpitchFB; /* PLC - last pitch of previous FB frame (depends on output sr) */ /*15Q16*/ + Word16 clas_dec; + Word16 mem_pitch_gain[2*NB_SUBFR16k+2]; /* Pitch gain memory Q14 */ + Word8 plc_use_future_lag; + Word16 prev_widow_left_rect; + Word32 Mode2_lp_gainc; /* 15Q16 low passed code gain used for concealment*/ + Word32 Mode2_lp_gainp; /* 15Q16 low passed pitch gain used for concealment*/ + Word16 conCngLevelBackgroundTrace; /* Q15 long term gain estimate for background level, used for PLC fade out */ + Word16 conCngLevelBackgroundTrace_e; + /* state variables for the minimum statistics used for PLC */ + Word16 conNoiseLevelMemory[PLC_MIN_STAT_BUFF_SIZE];/*Q15*/ + Word16 conNoiseLevelMemory_e[PLC_MIN_STAT_BUFF_SIZE]; + Word16 conNoiseLevelIndex; /*Q0*/ + Word16 conCurrLevelIndex; /*Q0*/ + Word16 conLastFrameLevel;/*Q15*/ + Word16 conLastFrameLevel_e; + + Word16 old_gaintcx_bfi, old_gaintcx_bfi_e; + Word16 cummulative_damping_tcx; + Word16 cummulative_damping; /*Q15*/ + Word16 cngTDLevel; + Word16 cngTDLevel_e; + + Word16 conceal_eof_gain; /*Q14*/ + Word16 damping; /* 1Q14 */ + Word16 gainHelper; /*can be >1*/ + Word16 gainHelper_e; + Word16 stepCompensate; + Word16 stepCompensate_e; + Word16 reset_mem_AR; + Word16 tcxConceal_recalc_exc; + + + Word16 classifier_Q_mem_syn; /*scalingfactor of mem_syn_clas_estim_fx in MODE2 */ + + Word16 rate_switching_init; + + /* LPC quantization */ + Word16 lpcQuantization; + Word16 numlpc; + + /* Bandwidth */ + Word16 TcxBandwidth; + + /* For NB and formant post-filter */ + PFSTAT pfstat; + Word16 psf_lp_noise_fx; + + /* For adaptive tilt_code */ + Word16 voice_fac; + + Word8 tcxonly; + + /*TCX resisual Q*/ + Word16 resQBits[NB_DIV]; /* number of bits read for the residual Quantization in TCX*/ + + Word16 last_ctx_hm_enabled; + + /* TCX-LTP */ + Word8 tcxltp; + Word16 tcxltp_gain; + Word16 tcxltp_pitch_int; + Word16 tcxltp_pitch_fr; + + Word16 tcxltp_mem_in[TCXLTP_MAX_DELAY]; + Word16 tcxltp_mem_out[L_FRAME48k]; + Word16 tcxltp_pitch_int_post_prev; + Word16 tcxltp_pitch_fr_post_prev; + Word16 tcxltp_gain_post_prev; + Word16 tcxltp_filt_idx_prev; + + struct tonalmdctconceal tonalMDCTconceal; + Word8 tonal_mdct_plc_active; + Word8 last_tns_active; + Word8 second_last_tns_active; + Word16 second_last_core; + Word32 tcxltp_second_last_pitch; + Word32 tcxltp_third_last_pitch; + Word16 tcxltp_last_gain_unmodified; + + Word16 FBTCXdelayBuf[111]; /* 2.3125ms at 48kHz -> 111 samples */ + + /* parameters for switching */ + Word16 mem_syn_r[L_SYN_MEM]; /*LPC synthesis memory needed for rate switching*/ + Word16 rate_switching_reset; + + Word32 lp_error_ener; + Word32 mem_error; + Word16 bpf_noise_buf[L_FRAME_16k]; + Word16 *p_bpf_noise_buf; + + Word8 enableGplc; + Word16 flagGuidedAcelp; /*int*/ + Word16 T0_4th;/*int*/ + Word16 guidedT0; /*int*/ + + Word16 enablePlcWaveadjust; + Word16 tonality_flag; + T_PLCInfo plcInfo; + + Word8 VAD; + Word8 flag_cna; + Word8 last_flag_cna; + + Word32 lp_noise; + + Word16 seed_acelp; + + Word16 core_ext_mode; /*GC,VC,UC,TC: core extended mode used for PLC or Acelp-external modules.*/ + + Word8 dec_glr; + Word16 dec_glr_idx; + + Word16 tcx_hm_LtpPitchLag; + Word16 tcx_lpc_shaped_ari; + + Word16 igf; + IGFDEC_INSTANCE hIGFDec; + + CLDFB_SCALE_FACTOR scaleFactor; + + Word16 tec_tfa; + Word16 tec_flag; + Word16 tfa_flag; + TEMPORAL_ENVELOPE_CODING_DECODER_FX tecDec_fx; + + Word16 con_tcx; + Word16 last_con_tcx; + Word16 old_ppp_mode_fx; + Word16 old_hb_synth_fx[L_FRAME48k]; + + Word16 prev_Q_exc_fr; + Word16 prev_Q_syn_fr; + + Word16 writeFECoffset; + + +} Decoder_State_fx; +#endif diff --git a/lib_dec/stat_noise_uv_dec_fx.c b/lib_dec/stat_noise_uv_dec_fx.c new file mode 100644 index 0000000..8fa2b8a --- /dev/null +++ b/lib_dec/stat_noise_uv_dec_fx.c @@ -0,0 +1,84 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "stl.h" +#include "prot_fx.h" /* Function prototypes */ + + +/*---------------------------------------------------------* + * stat_noise_uv_dec() + * + * Modifies excitation signal in UC mode when the noise is stationary + *---------------------------------------------------------*/ +void stat_noise_uv_dec_fx( + Decoder_State_fx *st_fx, /* i/o: Decoder static memory */ + const Word16 coder_type, /* i : coding type */ + Word16 *lsp_new, /* i : end-frame LSP vector */ + Word16 *lsp_mid, /* i : mid-frame LSP vector */ + Word16 *Aq, /* o : A(z) quantized for the 4 subframes */ + Word16 *exc2 /* i/o: excitation buffer */ +) +{ + Word16 noisiness = 0, i; + Word32 L_tmp; + + /*-----------------------------------------------------------------* + * Decode the VAD flag + *-----------------------------------------------------------------*/ + test(); + test(); + IF( EQ_16(coder_type,UNVOICED )||(EQ_16(coder_type,INACTIVE)&&LE_32(st_fx->core_brate_fx,ACELP_9k60))) + { + /* read the noisiness parameter */ + noisiness = (Word16)get_next_indice_fx( st_fx, 5 ); + move16(); + } + + /*-----------------------------------------------------------------* + * Update long-term energies for FEC + * Update LSP vector for CNG + *-----------------------------------------------------------------*/ + IF (EQ_16(coder_type,INACTIVE)) + { + IF (GT_16(st_fx->unv_cnt_fx,20)) + { + /*ftmp = st->lp_gainc * st->lp_gainc;*/ + L_tmp = L_mult0(st_fx->lp_gainc_fx, st_fx->lp_gainc_fx); /*Q3 * Q3 ->Q6*/ + /*st->lp_ener = 0.7f * st->lp_ener + 0.3f * ftmp;*/ + L_tmp = Mult_32_16(L_tmp, 9830); + st_fx->lp_ener_fx = L_add(Mult_32_16(st_fx->lp_ener_fx, 22938), L_tmp); + move16(); /*Q6 + Q6*/ + + FOR( i=0 ; ilspCNG[i] = (float)(0.9f * st->lspCNG[i] + 0.1f * lspnew[i]);*/ + L_tmp = L_mult(lsp_new[i], 3277); + st_fx->lspCNG_fx[i] = mac_r(L_tmp, st_fx->lspCNG_fx[i], 29491); + move16();/*Q15*/ + } + } + ELSE + { + st_fx->unv_cnt_fx = add(st_fx->unv_cnt_fx,1); + } + } + ELSE + { + st_fx->unv_cnt_fx = 0; + move16(); + } + + IF (!st_fx->Opt_AMR_WB_fx) + { + stat_noise_uv_mod_fx( coder_type, noisiness, st_fx->lsp_old_fx, lsp_new, lsp_mid, Aq + ,exc2, st_fx->Q_exc, 0, &st_fx->ge_sm_fx, &st_fx->uv_count_fx, &st_fx->act_count_fx, + st_fx->lspold_s_fx, &st_fx->noimix_seed_fx, &st_fx->min_alpha_fx, + &st_fx->exc_pe_fx, st_fx->core_brate_fx, st_fx->bwidth_fx, + &st_fx->Q_stat_noise, &st_fx->Q_stat_noise_ge ); + } + + + return ; +} diff --git a/lib_dec/swb_bwe_dec_fx.c b/lib_dec/swb_bwe_dec_fx.c new file mode 100644 index 0000000..17b1370 --- /dev/null +++ b/lib_dec/swb_bwe_dec_fx.c @@ -0,0 +1,968 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "rom_enc_fx.h" + + +#include "stl.h" +#define MAX_Q_NEW_INPUT 8 +#define Q_WTDA_FX 13 +#define Q_32_BITS 15 + +/*-------------------------------------------------------------------* + * para_pred_bws() + * + * predict SWB parameters for bandwidth switching + *-------------------------------------------------------------------*/ +static +Word16 para_pred_bws_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *signal_wb_fx, /* i : wideband frequency signal */ + Word16 *SWB_fenv_fx, /* o : frequency-domain BWE envelope */ + Word16 Q_syn + ,Word16 coder_type /* i : coding type */ +) +{ + Word16 i, j, k; + Word16 mode; + Word16 tmp, tmp_den, tmp_num; + Word32 L_tmp, L_tmp_max; + Word16 exp; + Word16 *input_hi_fx; + Word32 *mea; + Word16 peak_fx, mag_fx; + Word32 mean_fx[7], peak_32_fx; + Word32 avrg1_fx, avrg2_fx, min_fx; + Word16 att_fx; + + mode = NORMAL; + move16(); + + k = 0; + move16(); + input_hi_fx = &signal_wb_fx[SHARP_WIDTH]; + move16(); + FOR(i = 0; i < 7; i ++) + { + peak_fx = 0; + move16(); + mean_fx[i] = 0; + move16(); + FOR(j = 0; j < SHARP_WIDTH; j ++) + { + mag_fx = abs_s(*input_hi_fx); + peak_fx = s_max(peak_fx ,mag_fx); + /*IF (sub(mag_fx, peak_fx) > 0) */ + /*{ */ + /* peak_fx = mag_fx; */ + /*} */ + mean_fx[i] = L_add(mean_fx[i], L_deposit_l(mag_fx)); + move32(); + input_hi_fx ++; + } + + IF(Q_syn < 11) + { + tmp = 1; + move16(); + } + ELSE + { + tmp = 0; + move16(); + if(GT_16(shr(peak_fx, 3), shl(1, Q_syn))) + { + tmp = 1; + move16(); + } + } + IF( tmp > 0) + { + L_tmp = L_msu0(Mult_32_16(L_shl(mean_fx[i], 10), 18432), peak_fx, 4544); + if (L_tmp < 0) + { + k = add(k, 1); + } + } + } + + avrg1_fx = L_deposit_l(0); + avrg2_fx = L_deposit_l(0); + FOR(i=1; i<4; i++) + { + avrg1_fx = L_add(avrg1_fx, mean_fx[i]); + avrg2_fx = L_add(avrg2_fx, mean_fx[i+3]); + } + avrg1_fx = Mult_32_16(avrg1_fx, 10923); + avrg2_fx = Mult_32_16(avrg2_fx, 10923); /* 1/3 -> Q15 -> 10923 */ + + min_fx = L_add(2147483647, 0); /*2^31 */ + peak_32_fx = L_deposit_l(0); + FOR(i = 4; i < 7; i ++) + { + IF(GT_32(mean_fx[i], L_shl(avrg2_fx, 1))) + { + exp = norm_l(mean_fx[i]); + IF(LT_16(exp, 16)) + { + tmp_den = extract_l(L_shr(mean_fx[i], sub(16, exp))); /*Qsyn - 16 + exp */ + tmp_num = extract_l(L_shr(avrg2_fx, sub(15, exp))); /*//Qsyn - 16 + exp */ + } + ELSE + { + tmp_den = extract_l(mean_fx[i]); + tmp_num = extract_l(L_shl(avrg2_fx, 1)); + } + + tmp_den = div_s(1, tmp_den); + + tmp = i_mult(tmp_num, tmp_den); /*Q15 */ + + mean_fx[i] = Mult_32_16(mean_fx[i], tmp); + move32(); + } + min_fx = L_min(min_fx, mean_fx[i]); + peak_32_fx = L_max(peak_32_fx, mean_fx[i]); + /*IF(L_sub(mean_fx[i], min_fx) < 0) */ + /*{ */ + /* min_fx = mean_fx[i]; */ + /*} */ + /*IF(L_sub(mean_fx[i], peak_32_fx) > 0) */ + /*{ */ + /* peak_32_fx = mean_fx[i]; */ + /*} */ + } + + IF(GT_16(st_fx->tilt_wb_fx, 16384)) + { + IF(GT_16(st_fx->tilt_wb_fx, 30720)) + { + min_fx = peak_32_fx; + } + ELSE + { + tmp = extract_l(L_shr(L_mult0(st_fx->tilt_wb_fx, 17476), 14)); /*Q15 */ + min_fx = Mult_32_16(peak_32_fx, tmp); + } + } + + test(); + IF(peak_32_fx == 0 || min_fx == 0) + { + set16_fx(SWB_fenv_fx, 0, SWB_FENV); + } + ELSE + { + exp = norm_l(peak_32_fx); + IF(LT_16(exp, 16)) + { + tmp_den = extract_l(L_shr(peak_32_fx, sub(16, exp))); /*Qsyn - 16 + exp */ + tmp = div_s(16384, tmp_den); /*Q15+14 - (Qsyn - 16 + exp) */ + tmp_num = extract_l(L_shr(min_fx, sub(16, exp))); /*Qsyn - 16 + exp */ + + tmp = extract_l(L_shr(L_mult0(tmp_num, tmp), 14)); /*Q15 */ + } + ELSE + { + tmp_den = extract_l(peak_32_fx); /*Qsyn */ + exp = norm_s(tmp_den); + tmp = div_s(shl(1, sub(14,exp)), tmp_den); /*Q 29-exp - Qsyn */ + tmp_num = extract_l(min_fx); /*Qsyn */ + + tmp = extract_l(L_shr(L_mult0(tmp_num, tmp), sub(14, exp))); /*Q15 */ + } + + j = 0; + move16(); + mea = &mean_fx[4]; + move16(); + L_tmp_max = L_shl(32767, add(Q_syn, 5)); + FOR(i = 0; i < SWB_FENV; i++) + { + IF(j == 5) + { + mea++; + move16(); + j = 0; + move16(); + } + j++; + move16(); + L_tmp = L_min(Mult_32_16(*mea, tmp), L_tmp_max); + SWB_fenv_fx[i] = extract_l(L_shr(L_tmp, add(Q_syn, 5))); + } + } + + j = 0; + move16(); + FOR(i = shr(SWB_FENV, 1); i < SWB_FENV; i++) + { + tmp = sub(32767, i_mult(j, 2341)); + move16(); + SWB_fenv_fx[i] = mult_r(SWB_fenv_fx[i], tmp); + move16(); + j++; + move16(); + } + + IF(GT_32(avrg1_fx, L_shl(avrg2_fx, 3))) + { + FOR(i = 0; i < SWB_FENV; i ++) + { + SWB_fenv_fx[i] = shr(SWB_fenv_fx[i], 1); + move16(); + } + } + + test(); + test(); + test(); + test(); + test(); + IF( NE_16(st_fx->last_core_fx, HQ_CORE)&&EQ_16(st_fx->last_codec_mode,MODE1)&& + (GT_32(st_fx->enerLH_fx, L_shr(st_fx->prev_enerLH_fx, 1)) && LT_32(L_shr(st_fx->enerLH_fx, 1), st_fx->prev_enerLH_fx) ) && + (GT_32(st_fx->enerLL_fx, L_shr(st_fx->prev_enerLL_fx, 1)) && LT_32(L_shr(st_fx->enerLL_fx, 1), st_fx->prev_enerLL_fx) ) ) + { + FOR(i=0; iprev_coder_type_fx, coder_type)&>_16(mult_r(SWB_fenv_fx[i],16384),st_fx->prev_SWB_fenv_fx[i])) + { + /*SWB_fenv_fx[i] = add(mult_r(SWB_fenv_fx[i], 3277), mult_r(st_fx->prev_SWB_fenv_fx[i], 29491)); */ + SWB_fenv_fx[i] = round_fx(L_mac(L_mult(SWB_fenv_fx[i], 3277), st_fx->prev_SWB_fenv_fx[i], 29491)); + } + ELSE + { + /*SWB_fenv_fx[i] = add(mult_r(SWB_fenv_fx[i], st_fx->attenu_fx), mult_r(st_fx->prev_SWB_fenv_fx[i], sub(32767, st_fx->attenu_fx))); */ + SWB_fenv_fx[i] = round_fx(L_mac(L_mult(SWB_fenv_fx[i], st_fx->attenu_fx), st_fx->prev_SWB_fenv_fx[i], sub(32767, st_fx->attenu_fx))); + } + } + + IF(LT_16(st_fx->attenu_fx, 29491)) + { + st_fx->attenu_fx = add(st_fx->attenu_fx, 1638); + move16(); + } + } + ELSE + { + test(); + test(); + test(); + test(); + IF( NE_32(st_fx->core_brate_fx, st_fx->last_core_brate_fx)||(GT_32(st_fx->enerLH_fx,L_shr(st_fx->prev_enerLH_fx,1))&<_32(L_shr(st_fx->enerLH_fx,1),st_fx->prev_enerLH_fx))|| + (GT_32(st_fx->enerLL_fx, L_shr(st_fx->prev_enerLL_fx, 1)) && LT_32(L_shr(st_fx->enerLL_fx, 1), st_fx->prev_enerLL_fx) ) ) + { + FOR(i=0; iprev_SWB_fenv_fx[i])) + { + SWB_fenv_fx[i] = st_fx->prev_SWB_fenv_fx[i]; + move16(); + } + } + } + + FOR(i=0; iprev_SWB_fenv_fx[i], 3277)); */ + SWB_fenv_fx[i] = round_fx(L_mac(L_mult(SWB_fenv_fx[i], 29491), st_fx->prev_SWB_fenv_fx[i], 3277)); + } + st_fx->attenu_fx = 3277; + move16(); + } + + if(GT_16(k, 3)) + { + mode = HARMONIC; + move16(); + } + + + att_fx = i_mult(sub(N_WS2N_FRAMES, st_fx->bws_cnt_fx), 819); + move16();/*15 */ + IF( EQ_16(st_fx->L_frame_fx, L_FRAME16k)) + { + FOR( i = 0; i < 4; i++ ) + { + SWB_fenv_fx[i] = mult_r(SWB_fenv_fx[i], att_fx); + move16(); /*Q1 */ + } + } + + FOR( i=4; iL_old_wtda_swb_fx, + &st_fx->old_wtda_swb_fx_exp, ALDO_WINDOW, ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */ + output_frame ); + *Qpost = sub(new_input_fx_exp,15); + /* DCT of the ACELP core synthesis */ + direct_transform_fx(L_wtda_synth_fx, ysynth_32, 0, output_frame, &new_input_fx_exp); + + /* Convert to 16 Bits (Calc Shift Required to Stay within MAX_Q_NEW_INPUT) */ + scl = sub(16+MAX_Q_NEW_INPUT, new_input_fx_exp); + /* Possible to Upscale? */ + IF (scl > 0) + { + /* Yes */ + /* Calc Room to Upscale */ + Q_syn = Find_Max_Norm32(ysynth_32, output_frame); + /* Stay within MAX_Q_NEW_INPUT */ + scl = s_min(Q_syn, scl); + } + Copy_Scale_sig32_16(ysynth_32, ysynth_fx, output_frame, scl); + Q_syn = add(sub(new_input_fx_exp, 16), scl); + IF( !st_fx->bfi_fx ) + { + IF( EQ_32(st_fx->total_brate_fx, ACELP_13k20)) + { + /* de-quantization */ + mode = WB_BWE_gain_deq_fx(st_fx, WB_fenv_fx ); + st_fx->last_wb_bwe_ener_fx = mult_r(add(WB_fenv_fx[0], WB_fenv_fx[1]), 16384); + } + ELSE + { + if( NE_16(st_fx->last_extl_fx, WB_BWE)) + { + st_fx->prev_SWB_fenv_fx[0] = 0; + move16(); + } + + mode = WB_BWE_gain_pred_fx( WB_fenv_fx, ysynth_fx, coder_type, st_fx->prev_coder_type_fx, st_fx->prev_SWB_fenv_fx[0], + voice_factors_fx, pitch_buf_fx, st_fx->last_core_brate_fx, st_fx->last_wb_bwe_ener_fx, Q_syn + ,st_fx->last_extl_fx, st_fx->tilt_wb_fx + ); + move16(); + } + } + ELSE + { + /* FEC */ + mode = NORMAL; + move16(); + FOR(i=0; i<2; i++) + { + WB_fenv_fx[i] = mult_r(st_fx->prev_SWB_fenv_fx[i], 24576); + } + } + test(); + IF( NE_16(st_fx->last_extl_fx, WB_BWE)||st_fx->bfi_fx) + { + Copy( WB_fenv_fx, st_fx->prev_SWB_fenv_fx, 2 ); + } + + exp = norm_l(st_fx->prev_Energy_wb_fx); + IF(GT_16(add(st_fx->prev_Q_synth, exp),Q_syn)) + { + st_fx->prev_Energy_wb_fx = L_shr(st_fx->prev_Energy_wb_fx, sub(st_fx->prev_Q_synth, Q_syn)); + } + ELSE + { + Q_syn = add(st_fx->prev_Q_synth, exp); + st_fx->prev_Energy_wb_fx = L_shl(st_fx->prev_Energy_wb_fx, exp); + } + WB_BWE_decoding_fx( ysynth_fx, WB_fenv_fx, ysynth_32, L_FRAME16k, mode, + st_fx->last_extl_fx, &st_fx->prev_Energy_wb_fx, st_fx->prev_SWB_fenv_fx, &st_fx->prev_L_swb_norm_fx, + st_fx->extl_fx, coder_type, st_fx->total_brate_fx, &st_fx->Seed_fx, &st_fx->prev_flag_fx, + st_fx->prev_coder_type_fx, Q_syn, &Q_syn_hb ); + IF ( EQ_32(st_fx->output_Fs_fx, 32000)) + { + set32_fx( &ysynth_32[L_FRAME16k], 0, L_FRAME16k ); + } + ELSE IF ( EQ_32(st_fx->output_Fs_fx, 48000)) + { + set32_fx( &ysynth_32[L_FRAME16k], 0, L_FRAME32k ); + } + Inverse_Transform( ysynth_32, &Q_syn_hb, t_audio32_tmp, 0, output_frame, output_frame ); + window_ola_fx( t_audio32_tmp, hb_synth_fx, &Q_syn_hb, st_fx->mem_imdct_fx, &st_fx->mem_imdct_exp_fx, output_frame, + ALDO_WINDOW,ALDO_WINDOW, 0,0,0); + st_fx->prev_mode_fx = mode; + st_fx->prev_Q_synth = Q_syn; + return Q_syn_hb; +} +/*-------------------------------------------------------------------* + * swb_bwe_gain_deq() + * + * Decoding of SWB parameters + *-------------------------------------------------------------------*/ +Word16 swb_bwe_gain_deq_fx( /* o : BWE class */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 core, /* i : core */ + Word16 *SWB_tenv, /* o : Q0, time-domain BWE envelope */ + Word16 *SWB_fenv, /* o : Q1, frequency-domain BWE envelope */ + const Word16 hr_flag, /* i : high rate flag */ + const Word16 hqswb_clas /* i : HQ BWE class */ +) +{ + Word16 index, mode, n_band; + Word16 indice[6]; + Word16 quant_tmp[SWB_FENV/2], quant_tmp2[SWB_FENV/2]; + Word16 nb_bits[6]; + Word16 nenv; + Word16 tmp,exp,frac; + Word32 L_tmp; + + IF ( hqswb_clas > 0) + { + mode = (Word16)get_next_indice_fx( st_fx, 1 ); + IF (mode == 0) + { + mode = (Word16)get_next_indice_fx( st_fx, 1 ); + } + ELSE + { + mode = HQ_GENERIC_SP_EXC; + move16(); + } + } + ELSE + { + mode = (Word16)get_next_indice_fx( st_fx, 2 ); + } + + test(); + IF( EQ_16(mode,1)&&EQ_16(core,ACELP_CORE)) + { + FOR( n_band = 0; n_band < SWB_TENV; n_band++ ) + { + index = (Word16)get_next_indice_fx(st_fx, 4 ); + SWB_tenv[n_band] = shl(1, index); + move16(); + } + + indice[0] = (Word16)get_next_indice_fx(st_fx, 7 ); + move16(); + indice[1] = (Word16)get_next_indice_fx(st_fx, 6 ); + move16(); + + tmp = shl(indice[0],1); + FOR(n_band = 0; n_band < DIM_TR1; n_band++) + { + /*Env_TR_Cdbk1_fx[ indice[0]*DIM_TR1+n_band]*/ + quant_tmp[2*n_band] = Env_TR_Cdbk1_fx[add(tmp,n_band)];/*Q8 */ move16(); + } + + /*tmp = indice[1]*DIM_TR2*/ + tmp = shl(indice[1],1); + quant_tmp[1] = add(shr(add(quant_tmp[0], quant_tmp[2]),1), Env_TR_Cdbk2_fx[tmp]); + move16();/*Q8 */ + quant_tmp[3] = add(quant_tmp[2],Env_TR_Cdbk2_fx[add(tmp,1)]); + move16();/*Q8 */ + + FOR(n_band = 0; n_band < SWB_FENV_TRANS; n_band++) + { + tmp = add(quant_tmp[n_band], Mean_env_tr_fx[n_band]); /*Q8 */ + + /*-----------------------------------------------------------------* + * SWB_fenv[n_band] = pow(10.0, tmp/40) + * = pow(2, 3.321928*tmp/40) + * = pow(2, 0.0830482*tmp) + *-----------------------------------------------------------------*/ + L_tmp = L_mult(tmp, 21771); /* 0.0830482 in Q18 -> Q27 */ + L_tmp = L_shr(L_tmp, 11); /* From Q27 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */ + tmp = extract_l(Pow2(13, frac)); + exp = sub(exp, 13); + SWB_fenv[n_band] = shl(tmp, add(exp, 1)); + move16();/*Q1 */ + } + /* in case of band-width switching, attenuate frame gain */ + IF( st_fx->bws_cnt1_fx > 0 ) + { + tmp = i_mult(st_fx->bws_cnt1_fx, 1638); + FOR(n_band = 0; n_band < SWB_TENV; n_band++) + { + SWB_tenv[n_band] = mult_r(SWB_tenv[n_band], tmp); + move16(); + } + + FOR (n_band = 0; n_band < SWB_FENV_TRANS; n_band++) + { + SWB_fenv[n_band] = mult_r(SWB_fenv[n_band], tmp); + move16(); + } + } + } + ELSE + { + nb_bits[0] = 5; + move16(); + nb_bits[1] = 7; + move16(); + nb_bits[2] = 6; + move16(); + nb_bits[3] = 5; + move16(); + + IF ( EQ_16(hr_flag,1)) + { + nb_bits[4] = 5; + move16(); + nenv = SWB_FENV - 2; + move16(); + } + ELSE + { + nb_bits[4] = 6; + move16(); + nenv = SWB_FENV; + move16(); + } + + FOR (n_band = 0; n_band < 5; n_band++) + { + indice[n_band] = (Word16) get_next_indice_fx(st_fx, nb_bits[n_band] ); + move16(); + } + + IF ( EQ_16(hqswb_clas,HQ_GEN_FB)) + { + indice[n_band] = (Word16) get_next_indice_fx(st_fx, 5 ); + move16(); + } + + Copy( &EnvCdbk11_fx[i_mult2(indice[0], DIM11)], quant_tmp, DIM11 ); + Copy( &EnvCdbk1st_fx[i_mult2(indice[1], DIM1ST)], quant_tmp2, DIM1ST ); + Copy( &EnvCdbk2nd_fx[i_mult2(indice[2], DIM2ND)], quant_tmp2+DIM1ST, DIM2ND ); + + FOR( n_band = 0; n_band < DIM11-1; n_band++ ) + { + quant_tmp[n_band] = add(quant_tmp[n_band], quant_tmp2[n_band]); + move16();/*Q8 */ + SWB_fenv[n_band*2] = quant_tmp[n_band]; + move16(); /*Q8 */ + } + + IF ( EQ_16(hr_flag,1)) + { + quant_tmp[6] = add(quant_tmp[6],quant_tmp2[6]); + move16();/*Q8 */ + SWB_fenv[11] = quant_tmp[6]; + move16(); + + Copy( &EnvCdbk3rd_fx[indice[3] * DIM3RD], quant_tmp2, DIM3RD ); + Copy( &EnvCdbk3rd_fx[indice[4] * DIM3RD], quant_tmp2+DIM3RD, DIM3RD ); + + FOR(n_band = 0; n_band < 5; n_band++) + { + SWB_fenv[add(shl(n_band,1),1)] = add(shr(add(quant_tmp[n_band], quant_tmp[n_band+1]),1), quant_tmp2[n_band+1]); + move16();/*Q8 */ + } + + SWB_fenv[0] = add(SWB_fenv[0], quant_tmp2[0]); + move16();/*Q8 */ + } + ELSE + { + quant_tmp[DIM11-1]=add(quant_tmp[DIM11-1],quant_tmp2[DIM11-1]); + move16();/*Q8 */ + SWB_fenv[(DIM11-1)*2] = quant_tmp[DIM11-1]; + move16(); + + Copy( &EnvCdbk3rd_fx[i_mult2(indice[3], DIM3RD)], quant_tmp2, DIM3RD ); + Copy( &EnvCdbk4th_fx[i_mult2(indice[4], DIM4TH)], quant_tmp2+DIM3RD, DIM4TH ); + + FOR( n_band = 0; n_band < DIM12-1; n_band++ ) + { + SWB_fenv[add(shl(n_band,1),1)] = add(shr(add(quant_tmp[n_band],quant_tmp[n_band+1]),1),quant_tmp2[n_band]); + move16();/*Q8 */ + } + + SWB_fenv[n_band*2+1] = add(quant_tmp[n_band],quant_tmp2[n_band]); + move16();/*Q8 */ + } + + FOR( n_band = 0; n_band < nenv; n_band++ ) + { + tmp = add(SWB_fenv[n_band],Mean_env_fx[n_band]); /*Q8 */ + + L_tmp = L_mult(tmp, 21771); /* 0.166096 in Q17 -> Q26 */ + L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */ + + tmp = extract_l(Pow2(13, frac));/* Put 13 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp = sub(exp, 13); + SWB_fenv[n_band] = shl(tmp, add(exp,1)); + move16();/*Q1 */ + } + + IF ( EQ_16(hqswb_clas,HQ_GEN_FB)) + { + Copy( &EnvCdbkFB_fx[i_mult2(indice[5], DIM_FB)], &SWB_fenv[nenv], DIM_FB ); /*Q7 */ + + FOR( n_band = 0; n_band < DIM_FB; n_band++ ) + { + tmp = add(SWB_fenv[add(n_band,nenv)], Mean_env_fb_fx[n_band]); + L_tmp = L_mult(tmp, 21771); /* 0.166096 in Q17 -> Q25 */ + L_tmp = L_shr(L_tmp, 9); /* From Q25 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */ + + tmp = extract_l(Pow2(13, frac));/* Put 13 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp = sub(exp, 13); + SWB_fenv[add(n_band,nenv)] = shl(tmp, add(exp,1)); + move16(); + } + } + + /* in case of band-width switching, attenuate frame gain */ + } + + return mode; +} + +/*-------------------------------------------------------------------* + * swb_bwe_dec() + * + * SWB BWE decoder (only for 32kHz signals) + *-------------------------------------------------------------------*/ +Word16 swb_bwe_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *synth_fx, /* i/o: ACELP core synthesis/final synthesis (might be rescaled inside wtda() ) */ + Word16 *hb_synth_fx, /* o : SHB synthesis/final synthesis */ + const Word16 output_frame /* i : frame length */ + ,Word16 * Qpost + ,Word16 coder_type /* i : coding type */ +) +{ + Word16 i, l_subfr; + Word16 mode; + Word16 frica_flag = 0; + Word16 idxGain; + Word16 Q_syn, Q_syn_hb; + Word16 ysynth_fx[L_FRAME48k]; + Word16 tmp; + Word16 SWB_tenv_fx[SWB_TENV]; + Word32 L_wtda_synth_fx[2*L_FRAME48k], ysynth_32[L_FRAME48k]; + Word16 scl, new_input_fx_exp; + Word32 t_audio32_tmp[L_FRAME48k]; + Word32 SWB_tenv_tmp_fx[SWB_TENV]; + Word32 L_tmp; + Word16 exp, frac; + Word16 fb_ener_adjust_fx = 0; + Word16 SWB_fenv_fx[SWB_FENV]; + Word16 L; + Word16 j = 0; + Word16 ener_adjust_quan_fx; + Word16 tmp2; + /*---------------------------------------------------------------------* + * SWB BWE decoding + *---------------------------------------------------------------------*/ + /* windowing of the ACELP core synthesis */ + new_input_fx_exp = *Qpost; + wtda_fx(synth_fx, &new_input_fx_exp, L_wtda_synth_fx, st_fx->L_old_wtda_swb_fx, + &st_fx->old_wtda_swb_fx_exp, + ALDO_WINDOW, + ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */ + output_frame ); + *Qpost = sub(new_input_fx_exp,15); + /* DCT of the ACELP core synthesis */ + direct_transform_fx(L_wtda_synth_fx, ysynth_32, 0, output_frame, &new_input_fx_exp); + + /* Convert to 16 Bits (Calc Shift Required to Stay within MAX_Q_NEW_INPUT) */ + scl = sub(16+MAX_Q_NEW_INPUT, new_input_fx_exp); + /* Possible to Upscale? */ + IF (scl > 0) + { + /* Yes */ + /* Calc Room to Upscale */ + Q_syn = Find_Max_Norm32(ysynth_32, output_frame); + /* Stay within MAX_Q_NEW_INPUT */ + scl = s_min(Q_syn, scl); + } + Copy_Scale_sig32_16(ysynth_32, ysynth_fx, output_frame, scl); + Q_syn = add(sub(new_input_fx_exp, 16), scl); + + IF( !st_fx->bfi_fx ) + { + IF( st_fx->bws_cnt_fx > 0 ) + { + /* estimate parameters */ + mode = para_pred_bws_fx( st_fx, ysynth_fx, SWB_fenv_fx, Q_syn, coder_type ); + move16(); + } + ELSE + { + /* de-quantization */ + mode = swb_bwe_gain_deq_fx(st_fx, ACELP_CORE, SWB_tenv_fx, SWB_fenv_fx, 0, -1 ); + move16(); + } + + L = SWB_FENV; + move16(); + if(EQ_16(mode, TRANSIENT)) + { + L = SWB_FENV_TRANS; + move16(); + } + L_tmp = 0; + move16(); + FOR(i=0; iQ(15-exp) */ + st_fx->prev_ener_shb_fx = round_fx(L_shl(L_tmp, add(exp,2))); /*Q1 */ + } + ELSE + { + /* SHB FEC */ + IF( NE_16(st_fx->prev_mode_fx, TRANSIENT)) + { + mode = st_fx->prev_mode_fx; + move16(); + } + ELSE + { + mode = NORMAL; + move16(); + } + + Copy( st_fx->prev_SWB_fenv_fx, SWB_fenv_fx, SWB_FENV ); + } + + /* reconstruction of MDCT spectrum of the error signal */ + set32_fx( ysynth_32, 0, output_frame ); + IF ( EQ_16(st_fx->L_frame_fx, L_FRAME16k)) + { + SWB_BWE_decoding_fx( ysynth_fx, SWB_fenv_fx, ysynth_32, L_FRAME32k-80, mode, &frica_flag, &st_fx->prev_Energy_fx, st_fx->prev_SWB_fenv_fx, + &st_fx->prev_L_swb_norm_fx, st_fx->tilt_wb_fx, &st_fx->Seed_fx, 80, &st_fx->prev_weight_fx, st_fx->extl_fx, Q_syn + ,st_fx->last_extl_fx + ); + } + ELSE + { + SWB_BWE_decoding_fx( ysynth_fx, SWB_fenv_fx, ysynth_32, L_FRAME32k-80, mode, &frica_flag, &st_fx->prev_Energy_fx, st_fx->prev_SWB_fenv_fx, + &st_fx->prev_L_swb_norm_fx, st_fx->tilt_wb_fx, &st_fx->Seed_fx, 6, &st_fx->prev_weight_fx, st_fx->extl_fx, Q_syn + ,st_fx->last_extl_fx + ); + } + + test(); + IF ( EQ_16(st_fx->prev_frica_flag_fx, 1)&&frica_flag==0) + { + FOR( i = 0; i < L_SUBFR; i++ ) + { + tmp = sub(32767, extract_l(L_mult0(i, 512))); /*Q15 */ + st_fx->mem_imdct_fx[i] = mult_r(st_fx->mem_imdct_fx[i], tmp); + move16(); /*Q_synth */ + } + + FOR( ; i < output_frame; i++ ) + { + st_fx->mem_imdct_fx[i] = 0; + move16(); + } + } + + /* decode information */ + IF ( EQ_16(st_fx->extl_fx, FB_BWE)) + { + IF( !st_fx->bfi_fx ) + { + idxGain = (Word16)get_next_indice_fx(st_fx, NUM_BITS_FB_FRAMEGAIN ); + fb_ener_adjust_fx = usdequant_fx(idxGain, FB_GAIN_QLOW_FX, FB_GAIN_QDELTA_FX); /*Q15 */ + } + ELSE if( st_fx->bfi_fx ) + { + fb_ener_adjust_fx = st_fx->prev_fb_ener_adjust_fx; + move16(); + } + + st_fx->prev_fb_ener_adjust_fx = fb_ener_adjust_fx; + move16(); + IF(EQ_16(mode, TRANSIENT)) + { + ener_adjust_quan_fx = shr(fb_ener_adjust_fx, 2); + move16(); /*Q13*/ + } + ELSE + { + IF(SWB_fenv_fx[7] != 0) + { + tmp = div_s(1, SWB_fenv_fx[7]); + move16(); /*Q14*/ + ener_adjust_quan_fx = s_min(shr(i_mult(SWB_fenv_fx[13], tmp), 2), 32767); + move16(); /*Q13*/ + } + ELSE + { + ener_adjust_quan_fx = 0; + move16(); /*Q13*/ + } + } + + FOR( i = FB_BAND_BEGIN; i < FB_BAND_BEGIN+DE_OFFSET1; i++ ) + { + tmp = sub(32767, i_mult(j, 1024)); + tmp = mult_r(tmp, ener_adjust_quan_fx); /*Q13*/ + + tmp2 = i_mult(j, 256); /*Q13*/ + tmp2 = mult_r(tmp2, fb_ener_adjust_fx); /*Q13*/ + + tmp = add(tmp, tmp2); /*Q13*/ + ysynth_32[i] = ysynth_32[i-FB_BAND_WIDTH]; + move16(); + ysynth_32[i] = L_shl(Mult_32_16(ysynth_32[i], tmp), 2); + move32();/*15+Q_syn */ + j = add(j, 1); + } + + FOR( ; imem_imdct_fx, &st_fx->mem_imdct_exp_fx, output_frame, + ALDO_WINDOW, ALDO_WINDOW, 0,0,0); + l_subfr = mult(output_frame, 8192); + + test(); + IF( EQ_16(mode,TRANSIENT)) + { + FOR(i = 0; i < SWB_TENV; i++) + { + SWB_tenv_tmp_fx[i] = L_mult0(SWB_tenv_fx[i], 26214); + move32();/*Q15 */ + } + + /* time envelope shaping when the current frame is TRANSIENT frame */ + time_envelop_shaping_fx( hb_synth_fx, SWB_tenv_tmp_fx, output_frame, &Q_syn_hb ); + Q_syn_hb = sub(Q_syn_hb, 3); + + st_fx->prev_td_energy_fx = SWB_tenv_fx[3]; + move16(); + } + ELSE IF( EQ_16(frica_flag, 1)&&st_fx->prev_frica_flag_fx==0) + { + time_reduce_pre_echo_fx( synth_fx, hb_synth_fx, st_fx->prev_td_energy_fx, l_subfr, *Qpost, Q_syn_hb ); + } + ELSE + { + tmp = i_mult2(3, l_subfr); + L_tmp = L_deposit_l(0); + FOR(i=0; iprev_td_energy_fx = 0; + move16(); + IF(L_tmp != 0) + { + exp = norm_l(L_tmp); + frac = extract_h(L_shl(L_tmp, exp)); + exp = sub(exp, sub(30,shl(Q_syn_hb,1))); + + tmp = div_s(16384, frac); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp); /*Q(31-exp) */ + st_fx->prev_td_energy_fx = round_fx(L_shl(L_tmp, sub(exp,15))); /*Q0 */ + } + } + + st_fx->prev_frica_flag_fx = frica_flag; + move16(); + st_fx->prev_mode_fx = mode; + move16(); + + return Q_syn_hb; +} diff --git a/lib_dec/swb_bwe_dec_hr_fx.c b/lib_dec/swb_bwe_dec_hr_fx.c new file mode 100644 index 0000000..7855044 --- /dev/null +++ b/lib_dec/swb_bwe_dec_hr_fx.c @@ -0,0 +1,1488 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "rom_dec_fx.h" /* Static table prototypes */ +#include "cnst_fx.h" /* Static table prototypes */ +#include "stl.h" + +#define Q_GUARD 1 +#define Q_32_BITS 14 /* scaling of 't_audio32' */ +#define MAKE_PSEUDO_FLT(v,e) ((((Word32)(v))<<16) + (e)) + +/*-----------------------------------------------------------* + * Gain_Dequant_HR() + * + * Returns decoded gain quantized between the specified + * range using the specified number of levels. + *-----------------------------------------------------------*/ +/* It would be more efficient (PROM wise) to combine + with gain_dequant_fx(). But for now the 'max' param has + a larger allowed range here (Q13) than in gain_dequant_fx() + where is is in Q15. This applies for the 'min' param too. + Here it is Q6 in gain_dequant_fx() it is Q0. But merging the + two functions would be less efficient (Performance Wise) + since the function here doesn't use 'Log2_norm_lc' at all + versus gain_dequant_fx() which does. */ +static Word16 Gain_Dequant_HR( /* o: decoded gain (Q13) */ + Word16 index, /* i: quantization index */ + const Word16 min, /* i: value of lower limit (Q13) */ + const Word16 bits, /* i: number of bits to dequantize */ + Word16 *exp /* o: exponent of Decoded Gain */ +) +{ + Word32 L_mini, L_fact; + Word16 gain; + Word32 L_temp; + Word16 exp1,exp2, p2_frac,p2_int; + + L_mini=0; /* no complexity counted, just to remove warning */ + L_fact=0; /* no complexity counted, just to remove warning */ + + move32(); + move32(); + IF (EQ_16(min, G_AVQ_MIN_FX)) + { + L_mini = MAKE_PSEUDO_FLT(26214, 15); /* 0.8 in Q15 */ + L_fact = MAKE_PSEUDO_FLT(14145, 11); /* Log2(96) - Log2(0.8) in Q11 */ + } + ELSE IF (EQ_16(min, G_AVQ_MIN_DIV10_FX)) + { + L_mini = MAKE_PSEUDO_FLT(20972, 18); /* 0.8*0.1 in Q18 */ + L_fact = MAKE_PSEUDO_FLT(20949, 11); /* Log2(96) - Log2(0.8*0.1) in Q11 */ + } + ELSE IF (EQ_16(min, G_CODE_MIN_FX)) + { + L_mini = MAKE_PSEUDO_FLT(20972, 20); /* 0.02 in Q20 */ + L_fact = MAKE_PSEUDO_FLT(32628, 12); /* Log2(5) - Log2(0.02) in Q12 */ + } + ELSE IF (EQ_16(min, G_CODE_MIN_TC192_FX)) + { + L_mini = MAKE_PSEUDO_FLT(19661, 15); /* 0.6 in Q15 */ + L_fact = MAKE_PSEUDO_FLT(24963, 12); /* Log2(41) - Log2(0.6) in Q12 */ + } + ELSE IF (EQ_16(min, MIN_GLOB_GAIN_BWE_HR_FX)) + { + L_mini = MAKE_PSEUDO_FLT(24576, 13); /* 3.0 in Q13 */ + L_fact = MAKE_PSEUDO_FLT(30232, 12); /* Log2(500) - Log2(3) in Q12 */ + } + /* levels = 1< 0.5f) ? 1.0f : 0.5f;*/ + /* beta_flt = (alpha_flt - gain_flt)/sub(input_frame, ind2);*/ + temp2 = sub(16384, temp); + if (temp2 < 0) + temp2 = add(temp2, 16384); + temp3 = sub(input_frame, ind2); + /* Inverse 'temp3' */ + temp1 = norm_s(temp3); + temp3 = shl(temp3, temp1); + temp3 = div_s(16384, temp3); + L_Energy2 = L_mult0(temp2, temp3); + temp1 = add(temp1, 1); /* because we used 0.5 (16384) to inverse and not 1.0 (32768) */ + /* Back to Q31 */ + L_Energy2 = L_shr(L_Energy2, temp1); + + FOR( i = ind2; i < input_frame; i++ ) + { + hb_synth_fx[i] = mult_r(round_fx(L_Energy), hb_synth_fx[i]); + move16(); + L_Energy = L_add(L_Energy, L_Energy2); + } + } + } + + return temp; /* in Q15 */ +} + +/*-------------------------------------------------------------------* + * swb_bwe_dec_hr_fx() + * + * HR SWB BWE decoder + *-------------------------------------------------------------------*/ + +Word16 swb_bwe_dec_hr_fx( /* o : Exponent of SHB synthesis */ + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 *syn_12k8_16k_fx,/* i : ACELP core synthesis @16kHz */ + const Word16 exp, /* i : Exponent of core synthesis */ + Word16 *hb_synth_fx, /* o : SHB synthesis */ + const Word16 output_frame, /* i : frame length */ + const Word16 unbits, /* i : number of core unused bits */ + const Word16 pitch_buf[] /* i : pitch buffer */ +) +{ + Word16 i, j, k, nBits, nBits_total, nBits_block, Nsv, Nsv2, width_noncoded; + Word16 is_transient, tmpS, incr, IsTransient, pos; + Word16 x_norm[NSV_MAX*(WIDTH_BAND+1)], x_norm1[NSV_MAX*(WIDTH_BAND+1)]; + Word32 t_audio32_tmp[L_FRAME48k]; + Word32 t_audio32[L_FRAME48k]; + Word16 t_audio_exp; + Word16 en_band[N_BANDS_BWE_HR]; + Word16 ind1, ind2; + Word32 L_EnergyLT, L_Energy; + Word16 nq[NSV_MAX], nq2[NSV_MAX], nq_tmp[NSV_MAX]; + Word16 alpha; + Word16 temp, temp2, temp3, temp4; + Word16 en_noncoded, min_env, max_env; + Word16 gain_fx = 0, gain2_fx, exp1, exp2; + Word16 len; + Word16 pitch; + Word32 L_temp, L_temp2; + Word32 L_tilt_wb; + Word16 hb_synth_fx_exp; + Word16 *ptr16; + Word32 *ptr32; + Word32 L_ener_all, L_ener_saved; + Word16 ener_all_exp, ener_saved_exp; + Word16 *t_audio, *t_audio_tmp; + Word16 env = 0; + Word16 exp_L, inv_L, frac; + + /* Use 't_audio32_tmp' Word32 Buffer as two Word16 Buffers to save local Stack. */ + /* There is no possible overlap so it is ok */ + t_audio = (Word16 *)&t_audio32_tmp[0]; + t_audio_tmp = (Word16 *)&t_audio32_tmp[L_FRAME48k/2]; + + st_fx->bwe_highrate_seed_fx = extract_l(L_mult0(pitch_buf[0],pitch_buf[3])); + + /*---------------------------------------------------------------------* + * initializations + *---------------------------------------------------------------------*/ + + set16_fx(t_audio, 0, output_frame); + set32_fx(t_audio32, 0, output_frame); + exp2 = 0; + move16(); + Nsv2 = 0; + move16(); + /* only to suppress warnings (no complexity counted) */ + gain2_fx = 0; + move16(); + ind2 = 0; + move16(); + L_ener_saved = 0; + move16(); + ener_saved_exp = 0; + move16(); + + /* reset memories in case that last frame was a different technology */ + test(); + IF( EQ_16(st_fx->last_core_fx, HQ_CORE)||NE_16(st_fx->last_extl_fx,st_fx->extl_fx)) + { + set16_fx( st_fx->L_old_wtda_swb_fx, 0, L_FRAME48k ); + st_fx->Q_old_wtda = 14; + move16(); + } + + /* calculate SWB BWE bit-budget */ + /* nBits = st->extl_brate/50 + unbits */ + nBits = add(320,unbits); /* st->extl_brate_fx is always 16kbps */ + nBits_total = nBits; + move16(); + + /*---------------------------------------------------------------------* + * calculate tilt of the core synthesis + *---------------------------------------------------------------------*/ + L_tilt_wb = calc_tilt_bwe_fx( syn_12k8_16k_fx, exp, L_FRAME16k ); + L_temp = L_mac(1L, 8192, pitch_buf[0]); + FOR (i = 1; i < NB_SUBFR16k-1; i++) + { + L_temp = L_mac(L_temp, 8192, pitch_buf[i]); + } + pitch = mac_r(L_temp, 8192, pitch_buf[i]); + /* pitch now in Q4 (Q6 div by 4) */ + + /*---------------------------------------------------------------------* + * FEC, or good frame decoding + *---------------------------------------------------------------------*/ + + IF( st_fx->bfi_fx ) + { + is_transient = st_fx->old_is_transient_hr_bwe_fx; + move16(); + + /* Replication of the last spectrum, with an attenuation */ + test(); + test(); + IF( (EQ_16(st_fx->clas_dec, VOICED_CLAS)||EQ_16(st_fx->clas_dec,INACTIVE_CLAS))&&LE_16(st_fx->nbLostCmpt,3)) + { + alpha = 26214; /* 0.80 */ move16(); + t_audio_exp = 0; + move16(); + } + ELSE IF ( is_transient ) + { + alpha = 19661 /* 0.15 */; + move16(); + t_audio_exp = 2; + move16(); + } + ELSE + { + alpha = 19661 /* 0.30 */; + move16(); + t_audio_exp = 1; + move16(); + } + + IF( is_transient ) + { + /* output_frame == L_FRAME48k */ + tmpS = (2*END_FREQ_BWE_FULL_FB/50)/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_START_FREQ_COEF; + move16(); + /* set BWE spectrum length */ + if( EQ_16(output_frame, L_FRAME32k)) + { + tmpS = L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_START_FREQ_COEF; + move16(); + } + + temp = shr(output_frame, 2); + pos = NUM_TRANS_START_FREQ_COEF; + move16(); + ind1 = 0; + move16(); + /* reconstruct */ + len = 0; + move16(); + /* Here t_audio was initialy filled with zeros */ + /* So, after the loop, the Q will be 'Q_32_Bits' */ + FOR( k=0; kt_audio_prev_fx_exp[k], Q_32_BITS); + temp4 = add(temp4, t_audio_exp); + FOR( i=0; it_audio_prev_fx[i + ind1]); + L_temp = L_shr(L_temp, temp4); + t_audio32[pos + i] = L_temp; + move32(); + } + ind1 = add(ind1, tmpS); + pos = add(pos, temp); + } + /* Save transform coefficients for the next frame (needed in case of frame erasures) */ + FOR( k=0; kt_audio_prev_fx + i_mult2(k, tmpS), tmpS, temp4); + st_fx->t_audio_prev_fx_exp[k] = add(Q_32_BITS, temp4); + move16(); + len = add(len, shr(output_frame, 2)); + } + } + ELSE + { + /* output_frame == L_FRAME48k */ + tmpS = 2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_START_FREQ_COEF; + move16(); + /* set BWE spectrum length */ + if( EQ_16(output_frame, L_FRAME32k)) + { + tmpS = L_FRAME32k - NUM_NONTRANS_START_FREQ_COEF; + move16(); + } + + /* reconstruct */ + /* Here t_audio was initialy filled with zeros */ + /* So, after the loop, the Q will be 'Q_32_Bits' */ + temp4 = sub(st_fx->t_audio_prev_fx_exp[0], Q_32_BITS); + temp4 = add(temp4, t_audio_exp); + ptr32 = &t_audio32[NUM_NONTRANS_START_FREQ_COEF]; + FOR( i=0; it_audio_prev_fx[i]); + L_temp = L_shr(L_temp, temp4); + *ptr32++ = L_temp; + move32(); + } + /* Save transform coefficients for the next frame (needed in case of frame erasures) */ + temp = NUM_NONTRANS_START_FREQ_COEF; + move16(); /* not necessary but improves readability and allows a larger common code path */ + temp4 = Find_Max_Norm32(t_audio32 + temp, tmpS); + Copy_Scale_sig32_16(t_audio32 + temp, st_fx->t_audio_prev_fx, tmpS, temp4); + st_fx->t_audio_prev_fx_exp[0] = add(Q_32_BITS, temp4); + move16(); + } + + st_fx->L_mem_EnergyLT_fx = Mul_flt32_Q15(st_fx->L_mem_EnergyLT_fx, &st_fx->mem_EnergyLT_fx_exp, alpha); + move32(); + st_fx->mem_EnergyLT_fx_exp = add(st_fx->mem_EnergyLT_fx_exp, t_audio_exp); + + /* Set Exponent */ + t_audio_exp = Q_32_BITS; + move16(); + exp_L = norm_s(output_frame); + inv_L = div_s(shl(1,sub(14,exp_L)), output_frame); /*Q(29-exp_L)*/ + + /*Q(st_fx->mem_EnergyLT_fx_exp+29-exp_L-15) -> Q(st_fx->mem_EnergyLT_fx_exp-exp_L+14)*/ + st_fx->L_mem_EnergyLT_fx = Mul_flt32_Q15(st_fx->L_mem_EnergyLT_fx, &st_fx->mem_EnergyLT_fx_exp, inv_L); + move32(); + IF(st_fx->L_mem_EnergyLT_fx != 0) + { + exp1 = norm_l(st_fx->L_mem_EnergyLT_fx); + frac = extract_h(L_shl(st_fx->L_mem_EnergyLT_fx, exp1)); + exp1 = sub(exp1,sub(16,sub(st_fx->mem_EnergyLT_fx_exp,exp_L))); + + temp = div_s(16384, frac); + L_temp = L_deposit_h(temp); + L_temp = Isqrt_lc(L_temp, &exp1); + gain_fx = extract_l(L_shl(L_temp, sub(exp1, 2))); /*Q(31-exp + (exp-3)) -> Q13*/ + } + + env = 512; + move16(); + } + ELSE + { + /*---------------------------------------------------------------------* + * get transient frame flag + *---------------------------------------------------------------------*/ + + is_transient = (Word16) get_next_indice_fx( st_fx, 1 ); + + IF( is_transient ) + { + nBits = -1; + move16(); /* is_transient flag */ + nBits_block = shr(nBits_total, 2); + nBits = add(nBits, s_and(nBits_total, 3)); + + /* set width of noncoded (blind estimated) spectrum */ + test(); + IF( EQ_16(st_fx->extl_fx, SWB_BWE_HIGHRATE)||EQ_16(output_frame,L_FRAME32k)) + { + width_noncoded = L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF; + move16(); + tmpS = L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF_EFF; + move16(); + } + ELSE /* st->extl == FB_BWE_HIGHRATE */ + { + width_noncoded = (2*END_FREQ_BWE_FULL_FB/50)/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF; + move16(); + tmpS = (2*END_FREQ_BWE_FULL_FB/50)/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF_EFF; + move16(); + } + + /*---------------------------------------------------------------------* + * transient frames: processing in blocks (subframes) + *---------------------------------------------------------------------*/ + len = 0; + move16(); + FOR( k = 0; k < NUM_TIME_SWITCHING_BLOCKS; k++ ) + { + nBits = add(nBits, nBits_block); + + /*---------------------------------------------------------------------* + * global gain and envelope decoding + *---------------------------------------------------------------------*/ + + /* get global gain */ + ind1 = (Word16) get_next_indice_fx( st_fx, NBITS_GLOB_GAIN_BWE_HR ); + gain_fx = Gain_Dequant_HR( ind1, MIN_GLOB_GAIN_BWE_HR_FX, NBITS_GLOB_GAIN_BWE_HR, &exp1 ); + nBits = sub(nBits, NBITS_GLOB_GAIN_BWE_HR); + + /* get energy per band */ + IF( k == 0 ) + { + ind1 = (Word16)get_next_indice_fx( st_fx, NBITS_ENVELOPE_BWE_HR_TR ); + ind2 = ind1; + move16(); + nBits = sub(nBits, NBITS_ENVELOPE_BWE_HR_TR); + } + ELSE + { + ind1 = (Word16)get_next_indice_fx( st_fx, NBITS_ENVELOPE_BWE_HR_TR - 1 ); + if( GE_16(ind2, 8)) + { + ind1 = add(ind1, NUM_ENVLOPE_CODE_HR_TR2); + } + nBits = sub(nBits, NBITS_ENVELOPE_BWE_HR_TR - 1); + } + + temp = shl(ind1, 1); + en_band[0] = swb_hr_env_code3_fx[temp]; + move16(); + en_band[1] = swb_hr_env_code3_fx[add(temp, 1)]; + move16(); + + /*env = add(shr(en_band[0], 1), shr(en_band[1], 1));*/ + env = mac_r(L_mult(en_band[0], 16384), en_band[1], 16384); + + /*---------------------------------------------------------------------* + * estimate energy of noncoded spectrum (14.4-20kHz) + *---------------------------------------------------------------------*/ + + en_noncoded = en_band[N_BANDS_TRANS_BWE_HR-1]; + move16(); + + IF( EQ_16(st_fx->extl_fx, FB_BWE_HIGHRATE)) + { + ind1 = (Word16)get_next_indice_fx( st_fx, NBITS_HF_GAIN_BWE_HR ); + nBits = sub(nBits, NBITS_HF_GAIN_BWE_HR); + + IF (EQ_16(ind1, 1)) + { + en_noncoded = round_fx(L_mult0(en_noncoded, BWE_HR_TRANS_EN_LIMIT1_FX_Q16)); + } + + IF( EQ_16(ind1, 2)) + { + en_noncoded = round_fx(L_mult0(en_noncoded, BWE_HR_TRANS_EN_LIMIT2_FX_Q16)); + } + + IF( EQ_16(ind1, 3)) + { + en_noncoded = round_fx(L_mult0(en_noncoded, BWE_HR_TRANS_EN_LIMIT3_FX_Q16)); + } + } + + /*---------------------------------------------------------------------* + * AVQ decoding (dequantize normalized spectrum) + *---------------------------------------------------------------------*/ + + Nsv = (NUM_TRANS_END_FREQ_COEF - NUM_TRANS_START_FREQ_COEF) / WIDTH_BAND; + move16(); + AVQ_demuxdec_fx( st_fx, x_norm, &nBits, Nsv, nq ); + + temp = add(len, NUM_TRANS_START_FREQ_COEF); + /* 't_audio' in Q8 */ + t_audio_exp = 8; + move16(); + FOR( i=0; i < Nsv*WIDTH_BAND; i++ ) + { + t_audio[temp + i] = shl(x_norm[i], t_audio_exp); + move16(); + } + + /* apply noise-fill */ + swb_hr_noise_fill_fx( is_transient, NUM_TRANS_START_FREQ_COEF, NUM_TRANS_END_FREQ_COEF, + round_fx(L_shl(L_tilt_wb, 3)), /* Q(24+3-16) -> Q11 */ + pitch, nq, Nsv, &st_fx->bwe_highrate_seed_fx, t_audio+temp, t_audio_exp ); + + /* Go from Q't_audio_exp' on 16 Bits to 'Q_32_BITS' on 32 bits */ + temp2 = i_mult2(WIDTH_BAND, Nsv); + ptr16 = &t_audio[temp]; + move16(); + ptr32 = &t_audio32[temp]; + j = shl(1, sub(Q_32_BITS, t_audio_exp)); + FOR (i = 0; i< temp2; i++) + { + /* put in 'Q_32_BITS' in a 32 Bits */ + L_temp = L_mult0(*ptr16++, j); + *ptr32++ = L_temp; + move32(); + } + + /*---------------------------------------------------------------------* + * reconstruction + *---------------------------------------------------------------------*/ + + temp = add(temp, NUM_TRANS_END_FREQ_COEF_EFF-NUM_TRANS_START_FREQ_COEF); + pos = sub(temp, tmpS); + ptr32 = &t_audio32[temp]; + /* reconstruct 14-16(20) kHz spectrum */ + FOR( j = 0; j < tmpS; j++ ) + { + *ptr32++ = L_shr(t_audio32[pos + j], 1); + move32(); + } + + temp = i_mult2(shr(output_frame, 2), k); + + temp2 = add(NUM_TRANS_START_FREQ_COEF, temp); + ptr32 = &t_audio32[temp2]; + /* envelope denormalization */ + FOR( i=0; it_audio_prev_fx + i_mult2(k, pos), pos, temp4); + st_fx->t_audio_prev_fx_exp[k] = add(Q_32_BITS, temp4); + move16(); + len = add(len, shr(output_frame, 2)); + + /* attenuate HFs in case of band-width switching */ + IF( st_fx->bws_cnt1_fx > 0 ) + { + temp = shr(output_frame, 2); + temp = i_mult(k, temp); + temp = add(NUM_TRANS_START_FREQ_COEF, temp); + temp2 = i_mult(st_fx->bws_cnt1_fx, 1638); /*Q15*/ + + j = (2*END_FREQ_BWE_FULL_FB/50)/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_START_FREQ_COEF; + move16(); + if( output_frame == L_FRAME32k ) + { + j = L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_START_FREQ_COEF; + move16(); + } + + FOR( i=0; iextl_fx, FB_BWE_HIGHRATE)) + { + ind1 = (Word16) get_next_indice_fx( st_fx, NBITS_HF_GAIN_BWE_HR ); + nBits = sub(nBits, NBITS_HF_GAIN_BWE_HR); + + if (EQ_16(ind1, 1)) + { + /* en_noncoded = BWE_HR_NONTRANS_EN_LIMIT1*(0.5*min_env) ==> 0.25*min_env */ + en_noncoded = mult_r(min_env, BWE_HR_NONTRANS_EN_LIMIT2_FX_Q15/2); + } + + IF (EQ_16(ind1, 2)) + { + /* en_noncoded = 2.0*BWE_HR_NONTRANS_EN_LIMIT2*(0.5*min_env) ==> 1.2*min_env */ + en_noncoded = round_fx(L_shl(L_mult(BWE_HR_NONTRANS_EN_LIMIT2_FX_Q14, min_env), 1)); + } + + if (EQ_16(ind1, 3)) + { + /* en_noncoded = 2.0*BWE_HR_NONTRANS_EN_LIMIT3*(0.5*min_env) ==> 0.8*min_env */ + en_noncoded = mult_r(BWE_HR_NONTRANS_EN_LIMIT3_FX_Q15, min_env); + } + } + + /*---------------------------------------------------------------------* + * AVQ decoding (dequantize normalized spectrum) + *---------------------------------------------------------------------*/ + + /* Nsv = i / WIDTH_BAND */ + Nsv = shr(i, 3); + AVQ_demuxdec_fx( st_fx, x_norm, &nBits, Nsv, nq ); + + /*---------------------------------------------------------------------* + * second stage decoding + *---------------------------------------------------------------------*/ + + test(); + IF( GE_16(nBits, 9 + NBITS_GLOB_GAIN_BWE_HR)&&sum16_fx(nq,Nsv)>0) + { + ind1 = (Word16) get_next_indice_fx( st_fx, NBITS_GLOB_GAIN_BWE_HR ); + gain2_fx = Gain_Dequant_HR( ind1, MIN_GLOB_GAIN_BWE_HR_FX, NBITS_GLOB_GAIN_BWE_HR, &exp2 ); + /* gain2_flt *= 0.0625f */ + exp2 = add(exp2, 4); + + /* calculate the number of subbands according to the rest bits */ + IF( GT_16(nBits, 396)) + { + Nsv2 = 33; + move16(); + } + ELSE + { + /* Here what is acheived is an integer divide by 12 with truncation. */ + /* nBits/12 */ + Nsv2 = mult(nBits, 2731); + /* But, we have imprecision of the fraction so correction is necessary. */ + /* We crosscheck if 'Nsv2' is either too high or too low. */ + /* Finally, the result must satisfy: */ + /* Nsv2 * 12 <= nBits (Nsv2 is not too high) AND */ + /* nBits - Nsv2 * 12 < 12 (Nsv2 is the highest divisor) */ + L_temp = L_msu0(L_deposit_l(nBits), 12, Nsv2); + if (GE_32(L_temp, 12L)) + Nsv2 = add(Nsv2, 1); + if (L_temp < 0) + Nsv2 = sub(Nsv2, 1); + } + + nBits = sub(nBits, NBITS_GLOB_GAIN_BWE_HR); + AVQ_demuxdec_fx( st_fx, x_norm1, &nBits, Nsv2, nq2 ); + } + + /*---------------------------------------------------------------------* + * dequantization + *---------------------------------------------------------------------*/ + + /* set 't_audio' exp */ + t_audio_exp = 10; + move16(); + FOR( i = 0; i < Nsv*WIDTH_BAND; i++ ) + { + t_audio_tmp[i] = shl(x_norm[i], t_audio_exp); + move16(); + } + + Copy( nq, nq_tmp, Nsv ); + IF( GT_16(Nsv2, Nsv)) + { + /* Safety check, happens rarely */ + set16_fx( nq_tmp + Nsv, 0, sub(Nsv2, Nsv) ); + } + + incr = 0; + move16(); + ptr16 = x_norm1; + temp2 = sub(sub(exp2, 15), t_audio_exp); /* go to Q't_audio' */ + FOR( i=0; i=ind1; i-- ) + { + nq[j] = nq[i]; + move16(); + j = sub(j, 1); + } + + Copy( nq + ind2, nq + ind1, add(WIDTH_BAND, pos) ); + } + } + + /* apply noise-fill */ + IF( LT_16(nBits, 200)) + { + swb_hr_noise_fill_fx( is_transient, NUM_NONTRANS_START_FREQ_COEF, NUM_NONTRANS_END_FREQ_COEF, + round_fx(L_shl(L_tilt_wb, 3)), /* Q(24+3-16) -> Q11 */ + pitch, nq, Nsv, &st_fx->bwe_highrate_seed_fx, t_audio + NUM_NONTRANS_START_FREQ_COEF, t_audio_exp ); + } + + /* Go from Q't_audio_exp' on 16 Bits to Q16 on 32 bits */ + ptr32 = &t_audio32[NUM_NONTRANS_START_FREQ_COEF]; + j = shl(1, sub(Q_32_BITS, t_audio_exp)); + FOR (i = 0; i < temp4; i++) + { + /* put in 'Q_32_BITS' in a 32 Bits */ + L_temp = L_mult0(*ptr16++, j); + *ptr32++ = L_temp; + move32(); + } + + /*---------------------------------------------------------------------* + * reconstruction + *---------------------------------------------------------------------*/ + + /* smoothing 12.6-12.8kHz */ + test(); + IF( EQ_16(pos, 3)&&LE_16(nBits_total,400)) + { + ptr16 = &t_audio[NUM_NONTRANS_START_FREQ_COEF + 200 - WIDTH_BAND]; + L_temp = L_mac0(1L/* EPSILON */, *ptr16, *ptr16); + FOR (i = 1; i < WIDTH_BAND; i++) + { + ptr16++; + L_temp = L_mac0(L_temp, *ptr16, *ptr16); + } + ptr16++; + L_temp2 = L_mac0(1L/* EPSILON */, *ptr16, *ptr16); + FOR (i = 1; i < WIDTH_BAND; i++) + { + ptr16++; + L_temp2 = L_mac0(L_temp2, *ptr16, *ptr16); + } + L_temp = Sqrt_Ratio32(L_temp, 0, L_temp2, 0, &temp); + + /* if 'temp' is < 0 then it is req to shift right before substracting 1.0 */ + temp2 = s_min(0, temp); + L_temp = L_shl(L_temp, temp2); + /* Energy_flt - i*(Energy_flt-1.0)/8.0 */ + L_temp2 = L_add(L_temp, L_shr(-2147483647L-1L, s_max(0, temp))); /* 1.0 in same Q as Sqrt minus the Guard */ + /* / 8.0 */ + L_temp2 = L_shr(L_temp2, 3+Q_GUARD); + /* Add Guard */ + L_temp = L_shr(L_temp, Q_GUARD); + /* Set Index */ + ptr16 = &t_audio[NUM_NONTRANS_START_FREQ_COEF + 200]; + ptr32 = &t_audio32[NUM_NONTRANS_START_FREQ_COEF + 200]; + /* Set Exponent (relative to t_audio_exp (from 16 bits vector) */ + temp2 = add(sub(temp, temp2), sub(Q_GUARD-(16-Q_32_BITS), t_audio_exp)); + + FOR( i=0; iextl == FB_BWE_HIGHRATE */ + test(); + if( EQ_16(st_fx->extl_fx, SWB_BWE_HIGHRATE)||EQ_16(output_frame,L_FRAME32k)) + { + width_noncoded = L_FRAME32k - NUM_NONTRANS_END_FREQ_COEF; + move16(); + } + + ptr16 = &t_audio[NUM_NONTRANS_END_FREQ_COEF - WIDTH_BAND]; + L_temp = L_mac0(1L/* EPSILON */, *ptr16, *ptr16); + FOR (i = 1; i < WIDTH_BAND; i++) + { + ptr16++; + L_temp = L_mac0(L_temp, *ptr16, *ptr16); + } + + ptr16 = &t_audio[sub(NUM_NONTRANS_END_FREQ_COEF, width_noncoded)]; + L_temp2 = L_mac0(1L/* EPSILON */, *ptr16, *ptr16); + FOR (i = 1; i < WIDTH_BAND; i++) + { + ptr16++; + L_temp2 = L_mac0(L_temp2, *ptr16, *ptr16); + } + L_temp = Sqrt_Ratio32(L_temp, 0, L_temp2, 0, &temp); + + /* So part of the copy can be skipped because the loop that follows */ + /* will take the values from t_audio (16 bits) */ + /* Since 'width_noncoded' is always > WIDTH_BAND, we can substract it from the length */ + /* and adjust the offset accordingly */ + Copy32( t_audio32 + sub(NUM_NONTRANS_END_FREQ_COEF+WIDTH_BAND, width_noncoded), + t_audio32 + NUM_NONTRANS_END_FREQ_COEF+WIDTH_BAND, sub(width_noncoded, WIDTH_BAND) ); + + /* smoothing 14.4-14.8kHz */ + ptr16 = &t_audio[sub(NUM_NONTRANS_END_FREQ_COEF, width_noncoded)]; + ptr32 = &t_audio32[NUM_NONTRANS_END_FREQ_COEF]; + temp = sub(temp, add(t_audio_exp, 16-Q_32_BITS)); + FOR( i=0; iextl_fx,SWB_BWE_HIGHRATE)||LT_16(temp,shl(18022,sub(15-13,temp2)))) /* 2.2 in Q13 == 18022 */ + { + + /* (en_band_flt[3] - j*(en_band_flt[3]/WIDTH_BAND - en_noncoded_flt/WIDTH_BAND)) */ + L_temp = L_deposit_h(en_band[3]); + L_temp2 = L_mult(sub(en_band[3], en_noncoded), 32768/WIDTH_BAND); + ptr32 = &t_audio32[NUM_NONTRANS_END_FREQ_COEF]; + /* in L_temp/L_temp2, value in Q16+9 */ + FOR( j=0; j Q23 */ + L_temp2 = Mult_32_16(L_temp,32768/160); /* step */ + FOR( j=0; j Q25 */ + L_temp2 = Mult_32_16(L_temp,32768/320); /* step */ + FOR( ; jt_audio_prev_fx, pos, temp4); + st_fx->t_audio_prev_fx_exp[0] = add(Q_32_BITS, temp4); + move16(); + + /* attenuate HFs in case of band-width switching */ + IF( st_fx->bws_cnt1_fx > 0 ) + { + temp = i_mult(st_fx->bws_cnt1_fx, 1638); /*Q15*/ + + j = 2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_START_FREQ_COEF; + move16(); + if( output_frame == L_FRAME32k ) + { + j = L_FRAME32k - NUM_NONTRANS_START_FREQ_COEF; + move16(); + } + + FOR( i=0; iprev_ener_shb_fx = extract_h(L_shr(L_mult0(32767, env), 7)); + } + ELSE + { + st_fx->prev_ener_shb_fx = extract_h(L_shr(L_mult0(gain_fx, env), 7)); + } + FOR(i=0; iprev_SWB_fenv_fx[i] = st_fx->prev_ener_shb_fx; + move16(); + } + + /*---------------------------------------------------------------------* + * iOLA and iMDCT + *---------------------------------------------------------------------*/ + + t_audio_exp = Q_32_BITS; + + Inverse_Transform( t_audio32, &t_audio_exp, t_audio32_tmp, is_transient, output_frame, output_frame ); + + window_ola_fx( t_audio32_tmp, hb_synth_fx, &t_audio_exp, st_fx->L_old_wtda_swb_fx, &st_fx->Q_old_wtda, output_frame, + ALDO_WINDOW, ALDO_WINDOW, 0,0,0); + + hb_synth_fx_exp = t_audio_exp; + move16(); + + /*---------------------------------------------------------------------* + * final adjustments + *---------------------------------------------------------------------*/ + + IF( !st_fx->bfi_fx ) + { + IsTransient = 0; + move16(); + L_EnergyLT = L_add(st_fx->L_mem_EnergyLT_fx, 0); + temp4 = st_fx->mem_EnergyLT_fx_exp; + move16(); + pos = 0; + move16(); + + ptr16 = hb_synth_fx; + move16(); + + len = shr(output_frame, 2); /* Divide Frame Len by 4, all (160, 320, 640, 960) are divisible by 4 */ + L_ener_all = L_deposit_l(0); + ener_all_exp = 40; + move16(); /* set to a high exponent */ + + FOR( j=0; j<4; j++ ) + { + L_Energy = Calc_Energy_Autoscaled(ptr16, hb_synth_fx_exp, len, &temp2); + ptr16 += len; + move16(); + /* Normalize Energy */ + temp = norm_l(L_Energy); + L_Energy = L_shl(L_Energy, temp); + /* Update Exponent of 'L_Energy' */ + temp2 = add(temp2, temp); + + /* Normalize Long Term Energy */ + temp = norm_l(L_EnergyLT); + L_EnergyLT = L_shl(L_EnergyLT, temp); + /* Calculate Exponent of Long Term Energy */ + temp = add(temp, temp4); + + /* Divide by 12.5 */ + L_temp = Mult_32_16(L_Energy, 20972); /* 20972 = 1/12.5*32768*8 (*8 to boost precision) */ + temp3 = norm_l(L_temp); + L_temp = L_shl(L_temp, temp3); + temp3 = add(add(temp2, temp3), 3); + /* Energies are Strictly Positive Values and Normalized + (compare exponent and value only if exponent is same) */ + /* Replaces: 'if (Energy_flt > 12.5f * EnergyLT_flt )' */ + temp3 = sub(temp3, temp); + test(); + test(); + IF (temp3 < 0 || (GT_32(L_temp, L_EnergyLT)&&temp3==0)) + { + IsTransient = 1; + move16(); + pos = j; + move16(); + L_ener_saved = L_add(L_ener_all, 0); + ener_saved_exp = ener_all_exp; + move16(); + } + + L_ener_all = Add_flt32_flt32(L_Energy, temp2, L_ener_all, ener_all_exp, &ener_all_exp); + /* 0.25f*Energy_flt */ + temp2 = add(temp2, 2); + /* 0.75f*EnergyLT_flt */ + L_EnergyLT = L_sub(L_EnergyLT, L_shr(L_EnergyLT, 2)); + /* Exponent of 'L_EnergyLT' is 'temp' */ + /* Exponent of 'L_Energy' is 'temp2' */ + /* EnergyLT = 0.75f*EnergyLT + 0.25f*Energy */ + L_EnergyLT = Add_flt32_flt32(L_Energy, temp2, L_EnergyLT, temp, &temp4); + } + + test(); + test(); + test(); + IF( IsTransient != 0 && pos > 0 && LT_32(L_tilt_wb, 16777216L*3/*tilt_wb in Q24*/)&>_16(pitch,500*16/*Q4*/)) + { + Nsv = i_mult2(pos, shr(output_frame, 2)); + + gain_fx = 16384; /* sqrt(1.0) in Q14 */ + /* pos is 1,2 or 3 */ + temp3 = sub(pos, 2); + if (temp3 == 0) + { + gain_fx = 23170; + move16(); /* sqrt(2.0) in Q14 */ + } + + if (temp3 > 0) + { + gain_fx = 28378; + move16(); /* sqrt(3.0) in Q14 */ + } + exp1 = 14; + move16(); + + IF( EQ_16(st_fx->last_extl_fx, st_fx->extl_fx)) + { + L_temp = Div_flt32_flt32( L_ener_saved, ener_saved_exp, st_fx->L_mem_EnergyLT_fx, st_fx->mem_EnergyLT_fx_exp, &temp2 ); + temp3 = sub(temp2, 1); + L_temp2 = Isqrt_lc(L_temp, &temp3); + temp3 = sub(sub(30+31-15+1, temp2), temp3); + + L_temp = Mult_32_16(L_temp2, gain_fx); + temp = norm_l(L_temp); + L_temp2 = L_shl(L_temp, temp); + gain_fx = round_fx(L_temp2); + exp1 = sub(add(temp3, temp), sub(31, exp1)); /* gain_fx is in Q14 */ + } + + L_temp = L_mult0(26214, gain_fx); + /* +16: Because 26214 is 0.2 in Q16 + * -16: Because of round_fx + * -15: To get exponent with ref to Q15 + * +1: Because of L_mult'0' + * and the normalization + */ + exp2 = add(exp1, +16-16-15+1); + temp = norm_l(L_temp); + L_temp = L_shl(L_temp, temp); + exp2 = add(exp2, temp); + temp = round_fx(L_temp); /* Gain is in Q15+x */ + FOR( i=0; i>(19-15+1)); /* 19-15+1 to Bring to Q30 */ + FOR ( i = 0; i < len; i++ ) + { + /* hb_synth[i+Nsv] *= (gain_flt - i*8.0f*(1.0f/output_frame*gain_flt - 1.0f/output_frame)) */ + *ptr16 = round_fx(L_shl(Mult_32_16(L_temp, *ptr16), 1)); + ptr16++; + L_temp = L_sub(L_temp, L_temp2); + } + } + + st_fx->L_mem_EnergyLT_fx = L_EnergyLT; + move32(); + st_fx->mem_EnergyLT_fx_exp = temp4; + move16(); + st_fx->old_is_transient_hr_bwe_fx = is_transient; + move16(); + } + + /* post-processing in case of TD/FD switching */ + test(); + IF( EQ_16(st_fx->last_core_fx, HQ_CORE)||NE_16(st_fx->last_extl_fx,st_fx->extl_fx)) + { + IF( LT_32(L_tilt_wb, 16777216L*3/*tilt_wb in Q24*/)) + { + temp = TD_Postprocess( hb_synth_fx, hb_synth_fx_exp, output_frame, st_fx->last_extl_fx ); + + FOR( i=0; iL_old_wtda_swb_fx[i] = mult_r(st_fx->L_old_wtda_swb_fx[i], temp); + move16(); + } + + tmpS = L_FRAME32k - NUM_NONTRANS_START_FREQ_COEF; + move16(); + if( EQ_16(output_frame,L_FRAME48k)) + { + tmpS = 2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_START_FREQ_COEF; + move16(); + } + + FOR( i=0; it_audio_prev_fx[i] = mult_r(st_fx->t_audio_prev_fx[i], temp); + move16(); + } + } + } + + return hb_synth_fx_exp; +} diff --git a/lib_dec/swb_bwe_dec_lr_fx.c b/lib_dec/swb_bwe_dec_lr_fx.c new file mode 100644 index 0000000..cb8fd84 --- /dev/null +++ b/lib_dec/swb_bwe_dec_lr_fx.c @@ -0,0 +1,357 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "cnst_fx.h" + +#include "prot_fx.h" +#include "rom_com_fx.h" + +#include "stl.h" /* required for wmc_tool */ + +/*-------------------------------------------------------------------* + * DecodeSWBGenericParameters() + * + * Decoding of generic subband coding parameters + *-------------------------------------------------------------------*/ + +static void DecodeSWBGenericParameters_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 *lagIndices_fx, /* o : lowband index for each subband */ + const Word16 nBands_search_fx, /* i : number of subbnads for SSearch */ + const Word16 BANDS_fx, /* i : total number of subbands per frame */ + const Word16 *p2a_flags_fx, /* i : HF tonal flag */ + const Word16 hq_swb_clas_fx /* i : mode of operation HQ_NORMAL or HQ_HARMONIC */ +) +{ + Word16 sb; + + /* lag index for each subband (except last two) */ + FOR (sb = 0; sb < nBands_search_fx; sb++) + { + IF( EQ_16(hq_swb_clas_fx, HQ_HARMONIC)) + { + lagIndices_fx[sb] = get_next_indice_fx(st_fx, bits_lagIndices_mode0_Har_fx[sb]); + move16(); + } + ELSE + { + IF( p2a_flags_fx[BANDS_fx-NB_SWB_SUBBANDS+sb] == 0 ) + { + lagIndices_fx[sb] = get_next_indice_fx(st_fx, bits_lagIndices_modeNormal_fx[sb]); + move16(); + } + ELSE + { + lagIndices_fx[sb] = 0; + move16(); + } + } + } + + return; +} + +/*-------------------------------------------------------------------* + * DecodeSWBSubbands() + * + * Main routine for generic SWB coding + * + * High-frequency subbands are replicated based on the lowband signal using a lowband index denoting + * the selected lowband subband as well as linear and logarithmic domain gains + *-------------------------------------------------------------------*/ + +static void DecodeSWBSubbands_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word32 *L_spectra, /* i/o: MDCT domain spectrum */ + Word16 QsL, /* i : Q value of spectra */ + const Word16 fLenLow_fx, /* i : lowband length */ + const Word16 fLenHigh_fx, /* i : highband length */ + const Word16 nBands_fx, /* i : number of subbands */ + const Word16 *sbWidth_fx, /* i : subband lengths */ + const Word16 *subband_offsets_fx, /* i : subband offsets */ + Word16 *lagIndices_fx, /* i : lowband index for each subband */ + Word16 *lagGains_fx, /* i : first gain for each subband */ + Word16 *QlagGains, /* i : Q value of lagGains */ + Word16 BANDS_fx, /* i : number subbands per frame */ + Word16 *band_start_fx, /* i : band start of each SB */ + Word16 *band_end_fx, /* i : band end of each SB */ + Word32 *L_band_energy, /* i : band energy of each SB */ + Word16 Qbe, /* i : Q value of band energy */ + Word16 *p2a_flags_fx, /* i : HF tonal indicator */ + const Word16 hqswb_clas_fx, /* i : class information */ + const Word16 har_bands_fx, /* i : number of LF harmonic bands */ + const Word16 *subband_search_offset_fx, /* i : Number of harmonic LF bands */ + Word16 *prev_frm_hfe2_fx, /* i/o: */ + Word16 *prev_stab_hfe2_fx, /* i/o: */ + Word16 band_width_fx[], /* i : subband band widths */ + const Word32 L_spectra_ni[], /* i/o: core coder with sparseness filled */ + Word16 *ni_seed_fx /* i/o: random seed for search buffer NI */ +) +{ + Word16 i,k; + + Word16 sspectra_fx[L_FRAME32k]; + Word16 Qss; + + Word16 sspectra_ni_fx[L_FRAME32k], sspectra_diff_fx[L_FRAME32k]; + Word32 L_be_tonal[SWB_HAR_RAN1]; + Word16 ss_min_fx; /* Qss */ + Word32 L_th_g[NB_SWB_SUBBANDS]; + Word16 QbeL; + GainItem_fx pk_sf_fx[N_NBIGGEST_SEARCH_LRG_B]; + Word16 pul_res_fx[NB_SWB_SUBBANDS]; + Word16 g_fx; /* Q11 */ + Word16 imin_fx; + Word16 Qg; + + Word16 lagIndices_real_fx[NB_SWB_SUBBANDS]; + Word32 L_xSynth_har[L_FRAME32k]; /* Qs */ + + Word32 L_temp; + Word16 temp_lo_fx, temp_hi_fx; + + Word16 har_freq_est1; + Word16 har_freq_est2; + Word16 flag_dis; + Word16 pos_max_hfe2; + + + har_freq_est1 = 0; + move16(); + har_freq_est2 = 0; + move16(); + flag_dis = 1; + move16(); + pos_max_hfe2 = 0; + move16(); + + set16_fx(pul_res_fx,0,NB_SWB_SUBBANDS); + + IF( EQ_16(hqswb_clas_fx, HQ_HARMONIC)) + { + pos_max_hfe2 = har_est_fx( L_spectra, fLenLow_fx, &har_freq_est1, &har_freq_est2, &flag_dis, prev_frm_hfe2_fx, subband_search_offset_fx, sbWidth_fx, prev_stab_hfe2_fx ); + noise_extr_corcod_fx(L_spectra, L_spectra_ni, sspectra_fx, sspectra_diff_fx, sspectra_ni_fx, fLenLow_fx, st_fx->prev_hqswb_clas_fx, &(st_fx->prev_ni_ratio_fx), &Qss); + IF( flag_dis == 0 ) + { + test(); + if( NE_16(har_freq_est2, SWB_HAR_RAN1)||NE_16(har_freq_est2,*prev_frm_hfe2_fx)) + { + har_freq_est2 = add(har_freq_est2, lagIndices_fx[0]); + } + } + + /* Generate HF noise */ + genhf_noise_fx(sspectra_diff_fx, Qss, L_xSynth_har, QsL, sspectra_fx, BANDS_fx, har_bands_fx, har_freq_est2, pos_max_hfe2, pul_res_fx, pk_sf_fx, fLenLow_fx, fLenHigh_fx, sbWidth_fx, lagIndices_fx, subband_offsets_fx, subband_search_offset_fx); + + imin_fx = get_next_indice_fx(st_fx, 2); + move16(); + /* g= pow(10.0f, gain_table_SWB_BWE[imin]) */ + L_temp = L_mult(gain_table_SWB_BWE_fx[imin_fx], 27213); /* Q14+Q13+1=Q28 log(10)/log(2)=3.3219 27213.23(Q13) */ + L_temp = L_shr(L_temp, 12); /* Q28-Q12 -> Q16 */ + temp_lo_fx = L_Extract_lc(L_temp, &temp_hi_fx); + Qg = sub(14, temp_hi_fx); + g_fx = extract_l(Pow2(14, temp_lo_fx)); + g_fx = shl(g_fx, sub(11, Qg)); + + /* tonal energy estimation */ + ton_ene_est_fx( + L_xSynth_har, QsL, L_be_tonal, &QbeL, L_band_energy, Qbe, + band_start_fx, band_end_fx, band_width_fx, fLenLow_fx, fLenHigh_fx, + BANDS_fx, har_bands_fx, g_fx, pk_sf_fx, Qss, pul_res_fx + ); + + /*HF Spectrum Generation*/ + Gettonl_scalfact_fx( + L_xSynth_har, QsL, L_spectra_ni, fLenLow_fx, fLenHigh_fx, har_bands_fx, BANDS_fx, L_band_energy, Qbe, band_start_fx, band_end_fx, + p2a_flags_fx, L_be_tonal, QbeL, pk_sf_fx ,Qss, pul_res_fx); + + IF( flag_dis == 0 ) + { + *prev_frm_hfe2_fx = 0; + move16(); + } + ELSE + { + *prev_frm_hfe2_fx = har_freq_est2; + move16(); + } + + FOR( k = har_bands_fx; k < BANDS_fx; k++ ) + { + FOR( i = band_start_fx[k]; i <= band_end_fx[k]; i++ ) + { + L_spectra[i] = L_xSynth_har[i-fLenLow_fx]; + move32(); /* QsL */ + } + } + } + ELSE IF ( EQ_16(hqswb_clas_fx, HQ_NORMAL)) + { + ss_min_fx = spectrumsmooth_noiseton_fx( + L_spectra, /*QsL,*/ L_spectra_ni, sspectra_fx, sspectra_diff_fx, sspectra_ni_fx, &Qss, fLenLow_fx, ni_seed_fx); + + convert_lagIndices_pls2smp_fx( lagIndices_fx, nBands_fx, lagIndices_real_fx, sspectra_fx, sbWidth_fx, fLenLow_fx ); + FOR (k = 0; k < nBands_fx; k++) + { + if ( EQ_16(p2a_flags_fx[BANDS_fx-NB_SWB_SUBBANDS+k], 1)) + { + lagIndices_real_fx[k] = 0; + move16(); + } + } + + GetlagGains_fx( sspectra_ni_fx, Qss, + &L_band_energy[BANDS_fx-NB_SWB_SUBBANDS], Qbe, + nBands_fx, sbWidth_fx, lagIndices_real_fx, fLenLow_fx, lagGains_fx, QlagGains ); + + FOR(k=0; k Qs */ + } + } + + /* Construct spectrum */ + GetSynthesizedSpecThinOut_fx( + sspectra_ni_fx, Qss, L_xSynth_har, QsL, nBands_fx, sbWidth_fx, + lagIndices_real_fx, lagGains_fx, QlagGains, fLenLow_fx + ); + + /* Level adjustment for the missing bands */ + noiseinj_hf_fx( + L_xSynth_har, QsL, L_th_g, L_band_energy, Qbe, st_fx->prev_En_sb_fx, + p2a_flags_fx, BANDS_fx, band_start_fx, band_end_fx, fLenLow_fx, fLenHigh_fx + ); + + FOR( k = sub(BANDS_fx, NB_SWB_SUBBANDS); k < BANDS_fx; k++ ) + { + IF( p2a_flags_fx[k] == 0 ) + { + FOR( i = band_start_fx[k]; i <= band_end_fx[k]; i++ ) + { + L_spectra[i] = L_xSynth_har[i-fLenLow_fx]; + move32(); /* QsL */ + } + } + ELSE + { + FOR( i = band_start_fx[k]; i <= band_end_fx[k]; i++ ) + { + L_spectra[i] = L_spectra_ni[i]; + move32(); + } + } + } + } + + return; +} + +/*-------------------------------------------------------------------* + * swb_bwe_dec_lr() + * + * Main decoding routine of SWB BWE for the LR MDCT core + *-------------------------------------------------------------------*/ +void swb_bwe_dec_lr_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 L_m_core[], /* i : lowband synthesis */ + const Word16 QsL, /* i : Q value of m_core */ + Word32 L_m[], /* o : highband synthesis with lowband zeroed */ + const Word32 L_total_brate, /* i : total bitrate for selecting subband pattern */ + Word16 BANDS_fx, /* i : Number subbands/Frame */ + Word16 *band_start_fx, /* i : Band Start of each SB */ + Word16 *band_end_fx, /* i : Band end of each SB */ + Word32 *L_band_energy, /* i : Band energy of each SB : Qbe */ + Word16 Qbe, /* i : Q value of band energy */ + Word16 *p2a_flags_fx, /* i : HF tonal Indicator */ + const Word16 hqswb_clas_fx, /* i : class information */ + Word16 lowlength_fx, /* i : Lowband Length */ + Word16 highlength_fx, /* i : Highband Length */ + const Word16 har_bands_fx, /* i : Number of LF harmonic bands */ + Word16 *prev_frm_hfe2_fx, /* i/o: */ + Word16 *prev_stab_hfe2_fx, /* i/o: */ + Word16 band_width_fx[], /* i : subband bandwidth */ + const Word32 L_y2_ni[], /* i/o: Sparse filled corecoder */ + Word16 *ni_seed_fx /* i/o: random seed */ +) +{ + Word16 k; + Word16 nBands_fx; + Word16 nBands_search_fx; + Word16 wBands_fx[NB_SWB_SUBBANDS]; + Word16 lagIndices_fx[NB_SWB_SUBBANDS]; + Word16 lagGains_fx[NB_SWB_SUBBANDS]; + Word16 QlagGains[NB_SWB_SUBBANDS]; + Word16 swb_lowband_fx, swb_highband_fx, allband_fx; + + const Word16 *subband_offsets_fx; + const Word16 *subband_search_offset_fx; + + Word32 *p_L_m; + + subband_search_offset_fx = subband_search_offsets_13p2kbps_Har_fx; + subband_offsets_fx = subband_offsets_sub5_13p2kbps_Har_fx; + + hf_parinitiz_fx(L_total_brate,hqswb_clas_fx,lowlength_fx,highlength_fx,wBands_fx,&subband_search_offset_fx,&subband_offsets_fx,&nBands_fx,&nBands_search_fx,&swb_lowband_fx,&swb_highband_fx); + allband_fx = add(swb_lowband_fx, swb_highband_fx); + move16(); + + /* Decoding of the SWB parameters */ + DecodeSWBGenericParameters_fx( st_fx, lagIndices_fx, nBands_search_fx, BANDS_fx, p2a_flags_fx, hqswb_clas_fx ); + + /* Copy WB synthesis for SWB decoding */ + Copy32( L_m_core, L_m, swb_lowband_fx + swb_highband_fx ); + + /* Generic subband processing */ + DecodeSWBSubbands_fx( + st_fx, + L_m, QsL, + swb_lowband_fx, swb_highband_fx, nBands_fx, wBands_fx, subband_offsets_fx, + lagIndices_fx, lagGains_fx, QlagGains, + BANDS_fx, band_start_fx, band_end_fx, + L_band_energy, Qbe, + p2a_flags_fx, hqswb_clas_fx, har_bands_fx, subband_search_offset_fx, + prev_frm_hfe2_fx, prev_stab_hfe2_fx, band_width_fx, L_y2_ni, ni_seed_fx + ); + + p_L_m = &L_m[sub(allband_fx, 1)]; + *p_L_m = Mult_32_16(*p_L_m, 2028); + move32(); + p_L_m--; /* 0.0625 = 2028 (Q15) */ + *p_L_m = Mult_32_16(*p_L_m, 4096); + move32(); + p_L_m--; /* 0.125 = 4096 (Q15) */ + *p_L_m = Mult_32_16(*p_L_m, 8192); + move32(); + p_L_m--; /* 0.25 = 8192 (Q15) */ + *p_L_m = Mult_32_16(*p_L_m, 16384); + move32(); + p_L_m--; /* 0.5 = 16384 (Q15) */ + + /* set low frequencies to zero */ + FOR ( k = 0; k < swb_lowband_fx; k++ ) + { + L_m[k] = L_deposit_l(0); + } + + return; +} diff --git a/lib_dec/swb_tbe_dec_fx.c b/lib_dec/swb_tbe_dec_fx.c new file mode 100644 index 0000000..441cecd --- /dev/null +++ b/lib_dec/swb_tbe_dec_fx.c @@ -0,0 +1,3624 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + + +#include +#include "options.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "rom_dec_fx.h" +#include "stl.h" + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + + +static void dequantizeSHBparams_fx_9_1( Decoder_State_fx* st_fx, const Word16 extl, Word32 extl_brate, + Word16* Q_lsf, Word16* Q_subgain, Word32* Q_framegrain, Word16* uv_flag, + Word32* Q_shb_ener_sf_32, Word16* Q_shb_res_gshape, Word16* Q_mixFactors); +static void find_max_mem_dec( Decoder_State_fx* st_fx, Word16* n_mem, Word16 *n_mem2, Word16 *n_mem3 ); +static void rescale_genSHB_mem_dec( Decoder_State_fx* st_fx, Word16 sf ); +static void find_max_mem_wb( Decoder_State_fx* st_fx, Word16* n_mem ); +static void rescale_genWB_mem( Decoder_State_fx* st_fx, Word16 sf ); +static void Dequant_lower_LSF_fx( const Word16 lsf_idx[], Word16 lsf_q[] ); +static void Map_higher_LSF_fx( Word16 lsf_q[], const Word16 m, const Word16 grid_in[] ); +static void Dequant_mirror_point_fx( const Word16 lsf_q[], const Word16 m_idx, Word16* m ); + +/* gain shape concealment code */ +static void gradientGainShape(Decoder_State_fx *st_fx, Word16 *GainShape, Word32 *GainFrame); + +/*-------------------------------------------------------------------* + * find_max_mem_dec() + * + * Find norm and max in TBE memories and past buffers + *-------------------------------------------------------------------*/ +void find_max_mem_dec( + Decoder_State_fx *st_fx, + Word16 *n_mem, + Word16 *n_mem2 + ,Word16 *n_mem3 +) +{ + Word16 i; + Word16 n_mem_32; + Word16 max = 0; + Word32 Lmax = 0; + Word16 tempQ15, max2 = 0; + Word16 max3; + Word32 tempQ32, Lmax3; + + /* old BWE exc max */ + FOR( i = 0; i < NL_BUFF_OFFSET; i++ ) + { + tempQ15 = abs_s( st_fx->old_bwe_exc_extended_fx[i] ); + max = s_max( max, tempQ15 ); + } + + /* decimate all-pass steep memory */ + FOR ( i = 0; i < 7; i++ ) + { + tempQ15 = abs_s( st_fx->mem_genSHBexc_filt_down_shb_fx[i] ); + max = s_max(max, tempQ15); + } + + /* -- keep norm of state_lpc_syn_fx, state_syn_shbexc_fx, + and mem_stp_swb_fx separately for 24.4 and 32kbps ----*/ + /* findMaxMem2() inside tbe com */ + FOR ( i = 0; i < LPC_SHB_ORDER; i++ ) + { + tempQ15 = abs_s( st_fx->state_lpc_syn_fx[i] ); + max2 = s_max(max2, tempQ15); + } + + /* findMaxMem2() inside tbe com */ + FOR ( i = 0; i < L_SHB_LAHEAD; i++ ) + { + tempQ15 = abs_s( st_fx->state_syn_shbexc_fx[i] ); + max2 = s_max(max2, tempQ15); + } + + /* findMaxMem2() inside tbe com */ + FOR ( i = 0; i < LPC_SHB_ORDER; i++ ) + { + tempQ15 = abs_s( st_fx->mem_stp_swb_fx[i] ); + max2 = s_max(max2, tempQ15); + } + + /* for total_brate > 16.4kbps, use n_mem2; else account for the max2 for n_mem calculation */ + *n_mem2 = norm_s(max2); + if(max2 == 0) *n_mem2 = 15; + + if(LT_32(st_fx->total_brate_fx, ACELP_24k40)) + { + max = s_max(max, max2); + } + + /* de-emph and pre-emph memory */ + tempQ15 = abs_s( st_fx->tbe_demph_fx ); + max = s_max(max, tempQ15); + + tempQ15 = abs_s( st_fx->tbe_premph_fx ); + max = s_max(max, tempQ15); + + IF( EQ_16(st_fx->extl_fx, FB_TBE)) + { + FOR ( i = 0; i < LPC_SHB_ORDER; i++ ) + { + tempQ15 = abs_s( st_fx->fb_state_lpc_syn_fx[i] ); + max = s_max(max, tempQ15); + } + /* FB de-emph memory */ + tempQ15 = abs_s( st_fx->fb_tbe_demph_fx); + max = s_max(max, tempQ15); + } + /* estimate the norm for 16-bit memories */ + *n_mem = norm_s( max ); + if( max == 0 ) + { + *n_mem = 15; + } + + /* estimate the norm for 32-bit memories */ + Lmax = L_abs( st_fx->mem_csfilt_fx[0] ); /* only element [0] is used in env. shaping */ + + n_mem_32 = norm_l( Lmax ); + if( Lmax == 0 ) + { + n_mem_32 = 31; + } + + tempQ15 = sub( s_min( *n_mem, n_mem_32 ), 1 ); + *n_mem = s_max( tempQ15, 0 ); + + /* --------------------------------------------------------------*/ + /* Find headroom for synthesis stage associated with these memories: + 1. st_fx->syn_overlap_fx + 2. st_fx->genSHBsynth_state_lsyn_filt_shb_local + 3. st_fx->genSHBsynth_Hilbert_Mem_fx (32-bit) */ + max3 = 0; + /* find max in prev overlapSyn */ + FOR ( i = 0; i < L_SHB_LAHEAD; i++ ) + { + tempQ15 = abs_s( st_fx->syn_overlap_fx[i] ); + max3 = s_max(max3, tempQ15); + } + /* find max in prev genSHBsynth_state_lsyn_filt_shb_local_fx */ + FOR ( i = 0; i < 2*ALLPASSSECTIONS_STEEP; i++ ) + { + tempQ15 = abs_s( st_fx->genSHBsynth_state_lsyn_filt_shb_local_fx[i] ); + max3 = s_max(max3, tempQ15); + } + /* find max in prev int_3_over_2_tbemem_dec_fx */ + IF( EQ_32(st_fx->output_Fs_fx, 48000)) + { + FOR ( i = 0; i < INTERP_3_2_MEM_LEN; i++ ) + { + tempQ15 = abs_s( st_fx->int_3_over_2_tbemem_dec_fx[i] ); + max3 = s_max(max3, tempQ15); + } + } + IF( EQ_32(st_fx->output_Fs_fx, 16000)) + { + FOR ( i = 0; i < (2*ALLPASSSECTIONS_STEEP+1); i++ ) + { + tempQ15 = abs_s( st_fx->mem_resamp_HB_32k_fx[i] ); + max3 = s_max(max3, tempQ15); + } + } + /* estimate the norm for 16-bit memories */ + *n_mem3 = norm_s( max3 ); + if( max3 == 0 ) *n_mem3 = 15; + + Lmax3 = 0; + IF(EQ_16(st_fx->L_frame_fx, L_FRAME)) + { + /* find max in prev genSHBsynth_Hilbert_Mem_fx */ + FOR ( i = 0; i < HILBERT_MEM_SIZE; i++ ) + { + tempQ32 = L_abs( st_fx->genSHBsynth_Hilbert_Mem_fx[i] ); + Lmax3 = L_max(Lmax3, tempQ32); + } + } + + /* estimate the norm for 32-bit memories */ + n_mem_32 = norm_l( Lmax3 ); + if( Lmax3 == 0 ) n_mem_32 = 31; + + tempQ15 = sub( s_min( *n_mem3, n_mem_32 ), 2 ); /* very important leave at least 2 bit head room + because of the Hilber transform and Q14 coeffs */ + *n_mem3 = s_max( tempQ15, 0 ); + /* --------------------------------------------------------------*/ +} + +/*-------------------------------------------------------------------* + * rescale_genSHB_mem_dec() + * + * Rescale genSHB memories + *-------------------------------------------------------------------*/ +void rescale_genSHB_mem_dec( + Decoder_State_fx *st_fx, + Word16 sf ) +{ + Word16 i; + + FOR( i = 0; i < NL_BUFF_OFFSET; i++ ) + { + st_fx->old_bwe_exc_extended_fx[i] = shl( st_fx->old_bwe_exc_extended_fx[i], sf ); + move16(); + } + + FOR( i = 0; i < 7; i++ ) + { + st_fx->mem_genSHBexc_filt_down_shb_fx[i] = shl( st_fx->mem_genSHBexc_filt_down_shb_fx[i], sf ); + move16(); + } + + /* -- Apply memory scaling for 13.2 and 16.4k bps using sf ----*/ + IF(LT_32(st_fx->total_brate_fx, ACELP_24k40)) + { + FOR ( i = 0; i < LPC_SHB_ORDER; i++ ) + { + st_fx->state_lpc_syn_fx[i] = shl( st_fx->state_lpc_syn_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < L_SHB_LAHEAD; i++ ) + { + st_fx->state_syn_shbexc_fx[i] = shl( st_fx->state_syn_shbexc_fx[i], sf ); + move16(); + } + } + + IF( EQ_16(st_fx->extl_fx, FB_TBE)) + { + } + st_fx->mem_csfilt_fx[0] = L_shl( st_fx->mem_csfilt_fx[0], sf ); + move32(); + + st_fx->tbe_demph_fx = shl_r( st_fx->tbe_demph_fx, sf ); + move16(); + st_fx->tbe_premph_fx = shl_r( st_fx->tbe_premph_fx, sf ); + move16(); + +} + +void find_max_mem_wb( Decoder_State_fx* st_fx, Word16* n_mem ) +{ + Word16 i; + Word16 max = 0; + Word32 Lmax = 0; + Word16 n_mem_32; + + FOR( i = 0; i < NL_BUFF_OFFSET; i++ ) + max = s_max( max, abs_s( st_fx->old_bwe_exc_extended_fx[i] ) ); + + FOR( i = 0; i < 7; i++ ) + { + + if( abs_s( st_fx->mem_genSHBexc_filt_down_shb_fx[i] ) > max ) + max = abs_s( st_fx->mem_genSHBexc_filt_down_shb_fx[i] ); + } + + FOR( i = 0; i < 7; i++ ) + { + if( abs_s( st_fx->mem_genSHBexc_filt_down_wb2_fx[i] ) > max ) + max = abs_s( st_fx->mem_genSHBexc_filt_down_wb2_fx[i] ); + } + + FOR( i = 0; i < 7; i++ ) + { + + if( abs_s( st_fx->mem_genSHBexc_filt_down_wb3_fx[i] ) > max ) + max = abs_s( st_fx->mem_genSHBexc_filt_down_wb3_fx[i] ); + } + + FOR( i = 0; i < 10; i++ ) + { + + if( abs_s( st_fx->state_lpc_syn_fx[i] ) > max ) + max = abs_s( st_fx->state_lpc_syn_fx[i] ); + } + + FOR( i = 0; i < 5; i++ ) + { + + if( abs_s( st_fx->state_syn_shbexc_fx[i] ) > max ) + max = abs_s( st_fx->state_syn_shbexc_fx[i] ); + } + + IF ( max == 0 ) + { + *n_mem = 15; + move16(); + } + ELSE + { + *n_mem = norm_s( max ); + move16(); + } + + + FOR( i = 0; i < 2; i++ ) + { + + if( L_abs( st_fx->mem_csfilt_fx[i] ) > Lmax ) + Lmax = L_abs( st_fx->mem_csfilt_fx[i] ); + } + + IF ( Lmax == 0 ) + { + n_mem_32 = 31; + move16(); + } + ELSE + { + n_mem_32 = norm_l( Lmax ); + } + + *n_mem = sub( s_min( *n_mem, n_mem_32 ), 1 ); + *n_mem = s_max( *n_mem, 0 ); +} + +void rescale_genWB_mem( Decoder_State_fx* st_fx, Word16 sf ) +{ + Word16 i; + FOR( i = 0; i < NL_BUFF_OFFSET; i++ ) + { + st_fx->old_bwe_exc_extended_fx[i] = shl( st_fx->old_bwe_exc_extended_fx[i], sf ); + move16(); + } + + FOR( i = 0; i < 10; i++ ) + { + st_fx->state_lpc_syn_fx[i] = shl( st_fx->state_lpc_syn_fx[i], sf ); + move16(); + } + + FOR( i = 0; i < 5; i++ ) + { + st_fx->state_syn_shbexc_fx[i] = shl( st_fx->state_syn_shbexc_fx[i], sf ); + move16(); + } + + FOR( i = 0; i < 7; i++ ) + { + st_fx->mem_genSHBexc_filt_down_shb_fx[i] = shl( st_fx->mem_genSHBexc_filt_down_shb_fx[i], sf ); + move16(); + } + + FOR( i = 0; i < 7; i++ ) + { + st_fx->mem_genSHBexc_filt_down_wb2_fx[i] = shl( st_fx->mem_genSHBexc_filt_down_wb2_fx[i], sf ); + move16(); + } + + FOR( i = 0; i < 7; i++ ) + { + st_fx->mem_genSHBexc_filt_down_wb3_fx[i] = shl( st_fx->mem_genSHBexc_filt_down_wb3_fx[i], sf ); + move16(); + } + + FOR( i = 0; i < 2; i++ ) + { + st_fx->mem_csfilt_fx[i] = L_shl( st_fx->mem_csfilt_fx[i], sf ); + move32(); + } +} + + + +void InitSWBdecBuffer_fx( + Decoder_State_fx* st_fx /* i/o: SHB decoder structure */ +) +{ + set16_fx( st_fx->old_bwe_exc_fx, 0, ( PIT16k_MAX * 2 ) ); + st_fx->bwe_seed_fx[0] = 23; + move16(); + st_fx->bwe_seed_fx[1] = 59; + move16(); + + set16_fx( st_fx->old_bwe_exc_extended_fx, 0, NL_BUFF_OFFSET ); + st_fx->bwe_non_lin_prev_scale_fx = 0; + move16(); + st_fx->last_voice_factor_fx = 0; + move16(); + + set32_fx( st_fx->genSHBsynth_Hilbert_Mem_fx, 0, HILBERT_MEM_SIZE ); + set16_fx(st_fx->genSHBsynth_state_lsyn_filt_shb_local_fx, 0, 2*ALLPASSSECTIONS_STEEP); /* Interp all pass memory */ + + st_fx->syn_dm_phase_fx = 0; + move16(); + st_fx->prev_fbbwe_ratio_fx = 32767/*1.0f Q15*/; + + /* these are fd-bwe constants */ + st_fx->prev_wb_bwe_frame_pow_fx = 4194l/*0.001f Q22*/; /* Q22 */ + st_fx->prev_swb_bwe_frame_pow_fx = 4194l/*0.001f Q22*/; /* Q22 */ + st_fx->prev_fb_ener_adjust_fx = 0; + + set16_fx( st_fx->prev_lpc_wb_fx, 0, LPC_SHB_ORDER_WB); + st_fx->prev_Q_bwe_exc = 31; + move16(); + st_fx->prev_ener_fx_Q = 31; + move16(); + st_fx->prev_Qx = 0; + move16(); + st_fx->prev_frame_pow_exp = 0; + move16(); + st_fx->prev_Q_bwe_syn = 0; + move16(); + st_fx->prev_Q_bwe_syn2 = 0; + move16(); + return; +} + + +void ResetSHBbuffer_Dec_fx( Decoder_State_fx* st_fx /* i/o: SHB encoder structure */ ) +{ + Word16 i; + Word16 f; + Word16 inc; + + IF( st_fx->extl_fx != WB_TBE ) + { + f = 1489; + move16(); /* Q15 */ + inc = 1489; + move16(); /* Q15 */ + } + ELSE + { + f = 5461; + move16();/* Q15 */ + inc = 5461; + move16(); /* Q15 */ + } + + /* states for the filters used in generating SHB excitation from WB excitation*/ + set32_fx( st_fx->mem_csfilt_fx, 0, 2 ); + + /* states for the filters used in generating SHB signal from SHB excitation*/ + set16_fx( st_fx->state_syn_shbexc_fx, 0, L_SHB_LAHEAD ); + set16_fx( st_fx->state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + + IF( EQ_16(st_fx->extl_fx, FB_TBE)) + { + set16_fx( st_fx->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + st_fx->fb_tbe_demph_fx = 0; + move16(); + fb_tbe_reset_synth_fx( st_fx->fbbwe_hpf_mem_fx, st_fx->fbbwe_hpf_mem_fx_Q,&st_fx->prev_fbbwe_ratio_fx ); + } + /* states for the filters used in generating SHB signal from SHB excitation in wideband*/ + set16_fx( st_fx->mem_genSHBexc_filt_down_shb_fx, 0, 2*ALLPASSSECTIONS_STEEP+1); + set16_fx( st_fx->mem_genSHBexc_filt_down_wb2_fx, 0, 2*ALLPASSSECTIONS_STEEP+1); + set16_fx( st_fx->mem_genSHBexc_filt_down_wb3_fx, 0, 2*ALLPASSSECTIONS_STEEP+1); + set16_fx( st_fx->state_lsyn_filt_shb_fx,0, 2 * ALLPASSSECTIONS_STEEP ); + set16_fx( st_fx->state_lsyn_filt_dwn_shb_fx,0, 2 * ALLPASSSECTIONS_STEEP ); + set16_fx( st_fx->state_32and48k_WB_upsample_fx, 0, 2 * ALLPASSSECTIONS_STEEP ); + + /* States for the local synthesis filters */ + set16_fx( st_fx->syn_overlap_fx, 0, L_SHB_LAHEAD ); + + /* States for FEC */ + + IF( st_fx->extl_fx != WB_TBE ) + { + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + st_fx->lsp_prevfrm_fx[i] = f; + move16(); /*Q15*/ + f = add( f, inc ); + move16(); + } + } + ELSE + { + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->lsp_prevfrm_fx[i] = f; + move16();/*Q15*/ + f = add( f, inc ); + move16(); + } + FOR( ; ilsp_prevfrm_fx[i] = 0; + move16(); + } + } + st_fx->GainFrame_prevfrm_fx = 0; + move16();/*Q18*/ + st_fx->GainAttn_fx = 32767; + move16();/*Q15*/ + st_fx->tbe_demph_fx = 0; + st_fx->tbe_premph_fx = 0; + set16_fx(st_fx->mem_stp_swb_fx, 0, LPC_SHB_ORDER); + st_fx->gain_prec_swb_fx = 16384;/*Q14 =1*/ + set16_fx( &st_fx->GainShape_Delay[0], 0, NUM_SHB_SUBFR / 2 ); + + set16_fx(st_fx->old_core_synth_fx, 0, L_FRAME16k); + set16_fx(st_fx->old_tbe_synth_fx, 0, L_SHB_TRANSITION_LENGTH); + st_fx->tilt_swb_fec_fx = 0; + move16(); + + return; +} + + + + +/*==========================================================================*/ +/* FUNCTION : void wb_tbe_dec_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : WB TBE decoder, 6 - 8 kHz band decoding module */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _Word16 coder_type i : coding type */ +/* _Word32 *bwe_exc_extended i : bandwidth extended exciatation 2*Q_exc*/ +/* _Word16 Q_exc i : Q format */ +/* _Word16 voice_factors[] i : voicing factors Q15 */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _Word16 *synth o : WB synthesis/final synthesis Q_synth */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Decoder_State_fx *st_fx, i/o: decoder state structure */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*==========================================================================*/ +void wb_tbe_dec_fx( + Decoder_State_fx* st_fx, /* i/o: decoder state structure */ + const Word16 coder_type, /* i : coding type */ + Word32* bwe_exc_extended, /* i : bandwidth extended exciatation 2*Q_exc*/ + const Word16 Q_exc, + const Word16 voice_factors[], /* i : voicing factors */ + Word16* synth, /* o : WB synthesis/final synthesis */ + Word16* Q_synth +) +{ + Word16 i; + Word16 shaped_wb_excitation [ ( L_FRAME16k + L_SHB_LAHEAD )/4 ]; + Word16 shaped_wb_excitation_frac[ L_FRAME16k/4 ]; + Word16 bwe_exc_extended_16[ L_FRAME32k+40 ]; + Word16 exc4kWhtnd [ L_FRAME16k / 4]; + Word16 lsf_wb[ LPC_SHB_ORDER_WB ], lpc_wb[ LPC_SHB_ORDER_WB + 1 ], GainShape[ NUM_SHB_SUBFR ]; + Word32 GainFrame; + Word16 error[ L_FRAME16k ]; + Word16 synth_frac[ L_FRAME16k ]; + Word16 upsampled_synth[ L_FRAME48k ]; + Word32 prev_pow, curr_pow, curr_frame_pow; + Word16 curr_frame_pow_exp; + Word16 temp, scale, n; + Word16 j; + + Word16 Q_bwe_exc, Q_bwe_exc_ext, Qx; + Word16 n_mem, cnt; + Word16 max = 0; + Word32 L_tmp, Lacc, Lscale, Lmax = 0; + Word16 tmp, exp, sc; + Word16 vf_modified[ NB_SUBFR16k ]; + Word16 uv_flag = 0; + Word16 dummy=0; + Word32 dummy2[HILBERT_MEM_SIZE]= {0}; + Word16 f, inc; + + IF( st_fx->bws_cnt_fx == 0 ) + { + /* Initialization */ + set16_fx(GainShape, 11469/*0.35f Q15*/, NUM_SHB_SUBFR); + GainFrame = 1; + + IF( !st_fx->bfi_fx ) + { + IF(EQ_16(st_fx->use_partial_copy,1)) + { + IF(NE_16(st_fx->last_extl_fx, WB_TBE)) + { + st_fx->GainFrame_prevfrm_fx = 0; + st_fx->lsp_prevfrm_fx[0] = 3277/*0.1f Q15*/; + move16(); + FOR (i=1; ilsp_prevfrm_fx[i] = add(st_fx->lsp_prevfrm_fx[i-i], 3277/*0.1f Q15*/); + } + } + Copy( st_fx->lsp_prevfrm_fx, lsf_wb, LPC_SHB_ORDER_LBR_WB ); + set16_fx( GainShape, RECIP_ROOT_EIGHT_FX, NUM_SHB_SUBFR/2 ); + + IF( EQ_16(st_fx->rf_frame_type,RF_NELP)) + { + /* Frame gain */ + st_fx->rf_indx_tbeGainFr = s_and(st_fx->rf_indx_tbeGainFr, 0xF); /* only four LSBs are valid */ + Copy32( SHBCB_FrameGain16_fx + st_fx->rf_indx_tbeGainFr, &GainFrame, 1 ); + IF( EQ_16(st_fx->core_fx,ACELP_CORE)&&EQ_16(st_fx->last_core_fx,ACELP_CORE) + && !st_fx->prev_use_partial_copy && EQ_16(st_fx->prev_coder_type_fx,UNVOICED) + && NE_32(GainFrame,st_fx->GainFrame_prevfrm_fx) && EQ_16(st_fx->last_extl_fx, WB_TBE) ) + { + /*GainFrame = 0.2f*GainFrame + 0.8f*st_fx->GainFrame_prevfrm_fx;*/ + GainFrame = L_add(Mult_32_16(st_fx->GainFrame_prevfrm_fx, 26214), Mult_32_16(GainFrame, 6553)); + } + } + ELSE + { + temp = 0; + move16(); + /* Frame gain */ + SWITCH (st_fx->rf_indx_tbeGainFr) + { + case 0: + GainFrame = 131072; /* 0.5f in Q18 */ + IF(LE_32(st_fx->GainFrame_prevfrm_fx, 327680l/*1.25 Q18*/)) temp = 26214/*0.8 Q15*/; + move16(); + BREAK; + case 1: + GainFrame = 524288; /* 2.0f in Q18 */ + IF(GT_32(st_fx->GainFrame_prevfrm_fx, 327680l/*1.25 Q18*/)&&LE_32(st_fx->GainFrame_prevfrm_fx,786432l/*3 Q18*/)) temp = 26214/*0.8 Q15*/; + move16(); + test(); + BREAK; + case 2: + GainFrame = 1048576;/* 4.0f in Q18 */ + IF(GT_32(st_fx->GainFrame_prevfrm_fx, 786432l/*3 Q18*/)&&LE_32(st_fx->GainFrame_prevfrm_fx,1572864l/*6 Q18*/)) temp = 26214/*0.8 Q15*/; + move16(); + test(); + BREAK; + case 3: + GainFrame = 2097152;/* 8.0f in Q18 */ + IF(GT_32(st_fx->GainFrame_prevfrm_fx, 1572864l/*6 Q18*/)&&LE_32(st_fx->GainFrame_prevfrm_fx,4194304l/*16 Q18*/)) temp = 26214/*0.8 Q15*/; + move16(); + test(); + BREAK; + default: + fprintf(stderr, "RF SWB-TBE gain bits not supported."); + } + IF(EQ_16(st_fx->last_extl_fx, WB_TBE)) + { + + GainFrame = L_add(Mult_32_16(st_fx->GainFrame_prevfrm_fx, temp), Mult_32_16(GainFrame, sub(32767,temp))); + } + IF(EQ_16(st_fx->core_fx,ACELP_CORE)&&EQ_16(st_fx->last_core_fx,ACELP_CORE)) + { + IF(!st_fx->prev_use_partial_copy && EQ_16(st_fx->last_coder_type_fx, VOICED)&&EQ_16(st_fx->rf_frame_type,RF_GENPRED) + && LT_16(st_fx->prev_tilt_code_dec_fx,1497) && GT_16(st_fx->prev_tilt_code_dec_fx,200) ) + { + GainFrame = Mult_32_16(GainFrame,9830); + } + } + } + } + ELSE + { + /* de-quantization */ + dequantizeSHBparams_fx_9_1( st_fx, st_fx->extl_fx, st_fx->extl_brate_fx, lsf_wb, GainShape, &GainFrame, &uv_flag, 0, 0, 0 ); + } + } + ELSE + { + IF( EQ_32( st_fx->extl_brate_fx, WB_TBE_0k35)) + { + Copy( st_fx->lsp_prevfrm_fx, lsf_wb, LPC_SHB_ORDER_LBR_WB ); + } + ELSE + { + Copy( st_fx->lsp_prevfrm_fx, lsf_wb, LPC_SHB_ORDER_WB ); + } + set16_fx( GainShape, RECIP_ROOT_EIGHT_FX, NUM_SHB_SUBFR / 2 ); + + st_fx->GainAttn_fx = mult_r( st_fx->GainAttn_fx, 27853 ); + move16(); + + IF(EQ_16(st_fx->codec_mode, MODE1)) + { + GainFrame = Mult_32_16( st_fx->GainFrame_prevfrm_fx, st_fx->GainAttn_fx ); /*Q18*/ + } + ELSE + { + GainFrame = st_fx->GainFrame_prevfrm_fx; /*Q18*/ + } + } + + IF( st_fx->extl_brate_fx == WB_TBE_0k35 ) + { + /* convert LSPs back into LP coeffs */ + lsp2lpc_fx( lpc_wb + 1, lsf_wb, st_fx->prev_lpc_wb_fx, LPC_SHB_ORDER_LBR_WB ); + set16_fx( lpc_wb + LPC_SHB_ORDER_LBR_WB + 1, 0, ( LPC_SHB_ORDER_WB - LPC_SHB_ORDER_LBR_WB ) ); + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lpc_wb_fx[i] = lpc_wb[i + 1]; + move16(); + } + FOR( i = 1; i < LPC_SHB_ORDER_LBR_WB + 1; i++ ) + { + lpc_wb[i] = negate( lpc_wb[i] ); + move16(); + } + lpc_wb[0] = 4096; + move16(); + } + ELSE + { + /* convert LSPs back into LP coeffs */ + lsp2lpc_fx( lpc_wb + 1, lsf_wb, st_fx->prev_lpc_wb_fx, LPC_SHB_ORDER_WB ); + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lpc_wb_fx[i] = lpc_wb[i + 1]; + move16(); + } + FOR( i = 1; i < LPC_SHB_ORDER_WB + 1; i++ ) + { + lpc_wb[i] = negate( lpc_wb[i] ); + move16(); + } + lpc_wb[0] = 4096; + move16(); + } + + Copy( voice_factors, vf_modified, NB_SUBFR16k ); + IF( coder_type == VOICED ) + { + FOR( i = 1; i < NB_SUBFR; i++ ) + { + vf_modified[i] = add( mult_r( 26214, voice_factors[i] ), mult_r( 6554, voice_factors[i - 1] ) ); /* Q15 */ move16(); + } + IF( st_fx->L_frame_fx != L_FRAME ) + { + vf_modified[4] = add( mult_r( 26214, voice_factors[4] ), mult_r( 6554, voice_factors[3] ) ); /* Q15 */ move16(); + } + } + + /* From low band excitation, generate highband excitation */ + Lmax = 0; + FOR( cnt = 0; cnt < L_FRAME32k; cnt++ ) + { + Lmax = L_max( Lmax, L_abs( bwe_exc_extended[cnt] ) ); + } + Q_bwe_exc = ( Lmax == 0 )?31:norm_l( Lmax ); + Q_bwe_exc = sub( Q_bwe_exc, 1 ); + Q_bwe_exc = add( Q_bwe_exc, add( Q_exc, Q_exc ) ); + + find_max_mem_wb( st_fx, &n_mem ); + + if( sub( Q_bwe_exc, st_fx->prev_Q_bwe_exc ) > n_mem ) + { + Q_bwe_exc = add( st_fx->prev_Q_bwe_exc, n_mem ); + } + + test(); + if( uv_flag && GT_16( Q_bwe_exc, 20 )) + { + Q_bwe_exc = 20; + move16(); /* restrict this to 21 due to the Q factor requireemnt of the random number generator (keep 1 bit headroom) */ + } + + prev_pow = 0; + FOR( i = 0; i < L_SHB_LAHEAD / 4; i++ ) + { + prev_pow = L_mac0( prev_pow, st_fx->state_syn_shbexc_fx[i], st_fx->state_syn_shbexc_fx[i] ); /*Q(2*(st_fx->prev_Q_bwe_exc-16))*/ + } + + rescale_genWB_mem( st_fx, sub( Q_bwe_exc, st_fx->prev_Q_bwe_exc ) ); + + Copy( st_fx->old_bwe_exc_extended_fx, bwe_exc_extended_16, NL_BUFF_OFFSET ); + sc = sub( Q_bwe_exc, add( Q_exc, Q_exc ) ); + FOR( cnt = 0; cnt < L_FRAME32k; cnt++ ) + { + bwe_exc_extended_16[cnt + NL_BUFF_OFFSET] = round_fx( L_shl( bwe_exc_extended[cnt], sc ) ); + } + Copy( bwe_exc_extended_16 + L_FRAME32k, st_fx->old_bwe_exc_extended_fx, NL_BUFF_OFFSET ); + + Copy( st_fx->state_syn_shbexc_fx, shaped_wb_excitation, L_SHB_LAHEAD / 4 ); + + Q_bwe_exc_ext = sub( Q_bwe_exc, 16 ); + + GenShapedWBExcitation_fx( shaped_wb_excitation + L_SHB_LAHEAD / 4, lpc_wb, exc4kWhtnd, st_fx->mem_csfilt_fx, + st_fx->mem_genSHBexc_filt_down_shb_fx, st_fx->mem_genSHBexc_filt_down_wb2_fx, + st_fx->mem_genSHBexc_filt_down_wb3_fx, st_fx->state_lpc_syn_fx, coder_type, + bwe_exc_extended_16, Q_bwe_exc_ext, st_fx->bwe_seed_fx, vf_modified, uv_flag + , st_fx->igf + ); + + curr_pow = 0; + FOR( i = 0; i < L_SHB_LAHEAD / 4; i++ ) + { + curr_pow = L_mac0( curr_pow, shaped_wb_excitation[i + L_SHB_LAHEAD / 4], shaped_wb_excitation[i + + L_SHB_LAHEAD / 4] ); /* Q(2*Q_bwe_exc_ext) */ + } + + if( GT_16( voice_factors[0], 24576 )) + { + curr_pow = L_shr( curr_pow, 2 ); /* Q(2*Q_bwe_exc_ext) */ + } + + Lscale = root_a_over_b_fx( curr_pow, shl_r( Q_bwe_exc_ext, 1 ), prev_pow, + shl_r( sub( st_fx->prev_Q_bwe_exc, 16 ), 1 ), &exp ); + + FOR( i = 0; i < L_SHB_LAHEAD / 4 - 1; i++ ) + { + L_tmp = Mult_32_16( Lscale, shaped_wb_excitation[i] ); /* Q(16-exp+Q_bwe_exc_ext) */ + shaped_wb_excitation[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc_ext */ + } + Lscale = root_a_fx( Lscale, 31 - exp, &exp ); + L_tmp = Mult_32_16( Lscale, shaped_wb_excitation[L_SHB_LAHEAD / 4 - 1] ); /* Q(16-exp+Q_bwe_exc_ext) */ + shaped_wb_excitation[L_SHB_LAHEAD / 4 - 1] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc_ext */ + + /* Update SHB excitation */ + Copy( shaped_wb_excitation + L_FRAME16k / 4, st_fx->state_syn_shbexc_fx, L_SHB_LAHEAD / 4 ); + + + /* Adjust the subframe and frame gain of the synthesized shb signal */ + /* Scale the shaped excitation */ + ScaleShapedWB_fx( SHB_OVERLAP_LEN / 2, shaped_wb_excitation, st_fx->syn_overlap_fx, GainShape, GainFrame, + window_wb_fx, subwin_wb_fx, + Q_bwe_exc_ext + , st_fx->L_frame_fx + , 0 + , &dummy + , dummy + , dummy2 + ); + + max = 0; + FOR( i = 0; i < L_FRAME16k / 4; i++ ) + { + max = s_max( max, shaped_wb_excitation[i] ); /*Q0*/ + } + + IF( max == 0 ) + { + curr_frame_pow = 1; + move16(); + n = 0; + move16(); + } + ELSE + { + n = norm_s( max ); + FOR( i = 0; i < L_FRAME16k / 4; i++ ) + { + shaped_wb_excitation_frac[i] = shl( shaped_wb_excitation[i], n ); /*Q14*/ move16(); + } + n = sub( 14, n ); + curr_frame_pow = 1; + FOR( i = 0; i < L_FRAME16k / 4; i++ ) + { + L_tmp = L_mult( shaped_wb_excitation_frac[i], shaped_wb_excitation_frac[i] ); /*Q29*/ + curr_frame_pow = L_add( curr_frame_pow, L_shr( L_tmp, 7 ) ); /*Q22*/ + } + } + curr_frame_pow_exp = add( n, n ); + + IF ( GT_16(st_fx->prev_frame_pow_exp, curr_frame_pow_exp)) + { + curr_frame_pow = L_shr( curr_frame_pow, sub( st_fx->prev_frame_pow_exp, curr_frame_pow_exp ) ); + curr_frame_pow_exp = st_fx->prev_frame_pow_exp; + } + ELSE + { + st_fx->prev_wb_bwe_frame_pow_fx = L_shr( st_fx->prev_wb_bwe_frame_pow_fx, sub( curr_frame_pow_exp, st_fx->prev_frame_pow_exp ) ); + } + + test(); + IF( !st_fx->bfi_fx && st_fx->prev_bfi_fx ) + { + IF( GT_32( L_shr( curr_frame_pow, 1 ), st_fx->prev_wb_bwe_frame_pow_fx )) + { + L_tmp = root_a_over_b_fx( st_fx->prev_wb_bwe_frame_pow_fx, 22, curr_frame_pow, 22, &exp ); + scale = round_fx( L_shl( L_tmp, exp ) ); /*Q15*/ + + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + temp = round_fx( L_shl( L_tmp, exp ) ); /* Q15 */ + } + ELSE + { + scale = temp = 32767; + move16();/* Q15 */ + } + + FOR( j = 0; j < 8; j++ ) + { + GainShape[2 * j] = mult_r( GainShape[2 * j], scale ); + GainShape[2 * j + 1] = mult_r( GainShape[2 * j + 1], scale ); + FOR( i = 0; i < L_FRAME16k / ( 4 * 8 ); i++ ) + { + shaped_wb_excitation[i + j * L_FRAME16k / ( 4 * 8 )] = mult_r( shaped_wb_excitation[i + j * L_FRAME16k / ( 4 * 8 )], scale ); + } + IF( temp > 0 ) + { + IF( LT_16( scale, temp )) + { + scale = div_s( scale, temp ); + } + ELSE + { + scale = 32767; + move16(); + } + } + ELSE + { + scale = 0; + move16(); + } + } + } + + st_fx->prev_wb_bwe_frame_pow_fx = curr_frame_pow; + move32(); + st_fx->prev_frame_pow_exp = curr_frame_pow_exp; + move16(); + + /* generate 16kHz SHB signal (6 - 8 kHz) from 2kHz signal */ + max = 0; + move16(); + FOR( cnt = 0; cnt < ( L_FRAME16k + L_SHB_LAHEAD ) / 4; cnt++ ) + { + if( abs_s( shaped_wb_excitation[cnt] ) > max ) + { + max = abs_s( shaped_wb_excitation[cnt] ); + } + } + Qx = norm_s( max ); + if ( max == 0 ) + { + Qx = 15; + move16(); + } + + Qx = sub( Qx, 1 ); /* 1 bit space for saturation */ + + max = 0; + move16(); + FOR( i = 0; i < 2*ALLPASSSECTIONS_STEEP; i++ ) + { + if( abs_s( st_fx->state_lsyn_filt_shb_fx[i] ) > max ) + max = abs_s( st_fx->state_lsyn_filt_shb_fx[i] ); + } + + FOR( i = 0; i < 2*ALLPASSSECTIONS_STEEP; i++ ) + { + if( abs_s( st_fx->state_lsyn_filt_dwn_shb_fx[i] ) > max ) + max = abs_s( st_fx->state_lsyn_filt_dwn_shb_fx[i] ); + } + + IF( EQ_32(st_fx->output_Fs_fx, 32000)) + { + FOR ( i = 0; i < 2*ALLPASSSECTIONS_STEEP; i++ ) + { + max = s_max(max, abs_s( st_fx->state_32and48k_WB_upsample_fx[i] )); + } + } + IF( EQ_32(st_fx->output_Fs_fx, 48000)) + { + FOR ( i = 0; i < INTERP_3_1_MEM_LEN; i++ ) + { + max = s_max(max, abs_s( st_fx->mem_resamp_HB_fx[i] )); + } + } + n_mem = 15; + if( max != 0 ) + { + n_mem = norm_s( max ); + } + n_mem = s_max( n_mem, 0 ); + + if( sub( Qx, st_fx->prev_Qx ) > n_mem ) + Qx = add( st_fx->prev_Qx, n_mem ); + + FOR( i = 0; i < ( L_FRAME16k + L_SHB_LAHEAD ) / 4; i++ ) + { + shaped_wb_excitation[i] = shl( shaped_wb_excitation[i], Qx ); + move16(); + } + + FOR( i = 0; i < 2*ALLPASSSECTIONS_STEEP; i++ ) + { + st_fx->state_lsyn_filt_shb_fx[i] = shl( st_fx->state_lsyn_filt_shb_fx[i], sub( Qx, st_fx->prev_Qx ) ); + move16(); + } + + FOR( i = 0; i < 2*ALLPASSSECTIONS_STEEP; i++ ) + { + st_fx->state_lsyn_filt_dwn_shb_fx[i] = shl( st_fx->state_lsyn_filt_dwn_shb_fx[i], sub( Qx, st_fx->prev_Qx ) ); + move16(); + } + + GenWBSynth_fx( shaped_wb_excitation, error, st_fx->state_lsyn_filt_shb_fx, st_fx->state_lsyn_filt_dwn_shb_fx ); + + Copy( error + L_FRAME16k - L_SHB_TRANSITION_LENGTH, st_fx->old_tbe_synth_fx, L_SHB_TRANSITION_LENGTH ); + + FOR( i = 0; i < L_FRAME16k; i++ ) + { + synth[i] = mult_r( error[i], 21299 ); + move16(); + } + + max = 0; + move16(); + FOR( cnt = 0; cnt < L_FRAME16k; cnt++ ) + { + max = s_max( max, abs_s( synth[cnt] ) ); + } + + IF( max == 0 ) + { + st_fx->last_wb_bwe_ener_fx = 0; + move16(); + } + ELSE + { + n = norm_s( max ); + FOR( cnt = 0; cnt < L_FRAME16k; cnt++ ) + { + synth_frac[cnt] = shl( synth[cnt], n ); /*Q14*/ move16(); + } + n = sub( sub( 14, n ), Qx ); + + Lacc = 0; + FOR( i = 0; i < L_FRAME16k; i++ ) + { + L_tmp = L_mult( synth_frac[i], synth_frac[i] ); /* Q29 */ + Lacc = L_add( Lacc, L_shr( L_tmp, 7 ) ); /* Q22 */ + } + + L_tmp = Mult_32_16( Lacc, 102 ); /* Q22 */ + exp = norm_l( L_tmp ); + tmp = round_fx( L_shl( L_tmp, exp ) ); + exp = sub( add( exp, 22 ), 30 ); + tmp = div_s( 16384, tmp ); + L_tmp = Isqrt_lc( L_deposit_h( tmp ), &exp ); /* Q(31-exp) */ + st_fx->last_wb_bwe_ener_fx = round_fx( L_shl( L_tmp, add( exp, n - 12 ) ) ); /* Q3 */ + } + + + IF( EQ_32(st_fx->output_Fs_fx, 32000)) /* 32kHz sampling rate, but only WB output - interpolate */ + { + Scale_sig(st_fx->state_32and48k_WB_upsample_fx, 2*ALLPASSSECTIONS_STEEP, sub( Qx, st_fx->prev_Qx )); + Interpolate_allpass_steep_fx( synth, st_fx->state_32and48k_WB_upsample_fx, L_FRAME16k, upsampled_synth ); + Copy( upsampled_synth, synth, L_FRAME32k ); + } + ELSE IF( EQ_32(st_fx->output_Fs_fx, 48000)) + { + Scale_sig(st_fx->mem_resamp_HB_fx, INTERP_3_1_MEM_LEN, sub( Qx, st_fx->prev_Qx )); + interpolate_3_over_1_allpass_fx( synth, L_FRAME16k, upsampled_synth, st_fx->mem_resamp_HB_fx, allpass_poles_3_ov_2 ); + Copy( upsampled_synth, synth, L_FRAME48k ); + } + } + ELSE + { + f = 5461; + move16();/* Q15 */ + inc = 5461; + move16();/* Q15 */ + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + lsf_wb[i] = f; + move16();/*Q15*/ + f = add( f, inc ); + move16(); + } + GainFrame = 0; /* Q18 */ + Qx = 0; + Q_bwe_exc = 31; + st_fx->prev_wb_bwe_frame_pow_fx = 4194l/*0.001f Q22*/; /* Q22 */ + st_fx->prev_frame_pow_exp = 0; + move16(); + } + + /* Update previous frame parameters for FEC */ + IF( EQ_32( st_fx->extl_brate_fx, WB_TBE_0k35 ) ) + { + Copy( lsf_wb, st_fx->lsp_prevfrm_fx, LPC_SHB_ORDER_LBR_WB ); + } + ELSE + { + Copy( lsf_wb, st_fx->lsp_prevfrm_fx, LPC_SHB_ORDER_WB ); + } + st_fx->GainFrame_prevfrm_fx = GainFrame; /* Q18 */ + + if( !st_fx->bfi_fx ) + { + st_fx->GainAttn_fx = 32767; + move16(); + } + + *Q_synth = Qx; + move16(); + + st_fx->prev_Q_bwe_exc = Q_bwe_exc; + move16(); + st_fx->prev_Qx = Qx; + move16(); + + return; +} + + + +/*======================================================================================*/ +/* FUNCTION : void swb_tbe_dec_fx () */ +/*--------------------------------------------------------------------------------------*/ +/* PURPOSE : SWB TBE decoder, 6 - 14 kHz (or 7.5 - 15.5 kHz) band decoding module */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16) coder_type : coding type */ +/* _(Word16*) bwe_exc_extended :bandwidth extended exciatation Q0 */ +/* _(Word16[]) voice_factors :voicing factors Q15 */ +/* _(Word16*) Q_white_exc :Q Format of White Exc */ +/* _(Word16*) Q_synth :Q Format of Synthesis */ +/*--------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16*)synth : SHB synthesis/final synthesis Q_white_exc */ +/* _(Word16*)White_exc16k : shaped white excitation for the FB TBE Q_synth */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ Decoder_State_fx *st_fx: : Decoder state structure */ +/*--------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------------------*/ +/* CALLED FROM : RX */ +/*======================================================================================*/ +void swb_tbe_dec_fx( + Decoder_State_fx* st_fx, /* i/o: decoder state structure */ + const Word16 coder_type, /* i : coding type */ + Word32* bwe_exc_extended, /* i : bandwidth extended excitation 2*Q_exc */ + Word16 Q_exc, + const Word16 voice_factors[], /* i : voicing factors */ + const Word16 old_syn_12k8_16k[], /* i : low band synthesis */ + Word16* White_exc16k, /* o : shaped white excitation for the FB TBE */ + Word16* Q_white_exc, + Word16* synth, /* o : SHB synthesis/final synthesis */ + Word16* Q_synth, + Word16* pitch_buf /* i : pitch buffer Q6 */ +) +{ + Word16 i; + Word16 shaped_shb_excitation [ L_FRAME16k + L_SHB_LAHEAD ]; + Word16 bwe_exc_extended_16[L_FRAME32k+NL_BUFF_OFFSET]; + Word16 lsf_shb[LPC_SHB_ORDER], lpc_shb[LPC_SHB_ORDER + 1], GainShape[NUM_SHB_SUBFR]; + Word32 GainFrame; + Word16 error[L_FRAME32k]; + Word32 L_ener; + Word16 ener; + Word16 is_fractive; + Word32 prev_pow, curr_pow, Lscale; + Word16 scale; + Word16 exp, tmp; + Word16 j, cnt ; + Word16 n_mem, n_mem2, Qx, sc; + Word16 n_mem3; + Word32 Lmax, L_tmp; + Word16 frac; + + Word32 L_tmp1, L_tmp2; + Word16 expa, expb; + Word16 fraca, fracb; + Word16 GainShape_tmp[NUM_SHB_SUBGAINS]; + Word16 Q_bwe_exc; + Word16 Q_shb; + Word16 vf_modified[NB_SUBFR16k]; + Word16 stemp; + + Word16 tilt_swb_fec; + Word16 Q_bwe_exc_fb; + + Word16 lsp_shb_1[LPC_SHB_ORDER], lsp_shb_2[LPC_SHB_ORDER], lsp_temp[LPC_SHB_ORDER]; + Word16 lpc_shb_sf[4*(LPC_SHB_ORDER+1)]; + const Word16 *ptr_lsp_interp_coef; + Word32 shb_ener_sf_32; + Word16 shb_res_gshape[NB_SUBFR16k]; + Word16 mixFactors; + Word16 vind; + Word16 shb_res_dummy[L_FRAME16k]; + Word16 shaped_shb_excitationTemp[L_FRAME16k]; + Word32 ener_tmp[NUM_SHB_SUBGAINS]; + Word16 pitch_fx; + Word16 l_subframe_fx; + Word16 formant_fac; + Word16 lsf_diff[LPC_SHB_ORDER], w[LPC_SHB_ORDER]; + Word16 refl[M]; + Word16 tilt_para; + Word16 tmp1,tmp2; + Word16 f_fx, inc_fx; + Word32 GainFrame_prevfrm_fx; + + Word16 synth_scale_fx; + Word16 mean_vf; + Word16 exp_ener, inv_ener; + Word32 prev_ener_ratio_fx=0; /* initialize just to avoid compiler warning */ + Word16 max,n,temp,shaped_shb_excitation_frac [ L_FRAME16k + L_SHB_LAHEAD ]; + Word32 curr_frame_pow; + Word16 curr_frame_pow_exp; + Word32 L_prev_ener_shb; + /* initializations */ + GainFrame = L_deposit_l(0); + mixFactors = 0; + move16(); + shb_ener_sf_32 = L_deposit_l(0); + set16_fx( shaped_shb_excitationTemp, 0, L_FRAME16k ); + st_fx->shb_dtx_count_fx = 0; + move16(); + is_fractive = 0; + move16(); + set16_fx( shb_res_gshape, 1638/*0.1f Q14*/, NB_SUBFR16k ); /* Q14 */ + Q_shb = 0; /* high band target Q factor set to zero */ + + L_tmp = calc_tilt_bwe_fx(old_syn_12k8_16k, st_fx->Q_syn2, st_fx->L_frame_fx); + tilt_swb_fec = round_fx(L_shl(L_tmp, 3)); + /* i: old_syn_12k8_16k in st_fx->Q_syn2 */ + /* o: tilt_swb_fec in Q11 */ + test(); + IF( st_fx->bfi_fx && NE_16(st_fx->clas_dec,UNVOICED_CLAS)) + { + tilt_swb_fec = st_fx->tilt_swb_fec_fx; + move16(); + } + + /* WB/SWB bandwidth switching */ + test(); + test(); + IF( ( GT_16(st_fx->tilt_wb_fx, 10240)&&EQ_16(st_fx->clas_dec,UNVOICED_CLAS))||GT_16(st_fx->tilt_wb_fx,20480)) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( (st_fx->prev_fractive_fx == 0 && + (LT_32( st_fx->prev_enerLH_fx, L_shl( st_fx->enerLH_fx, 1 ) ) && GT_32( st_fx->prev_enerLH_fx, L_shr( st_fx->enerLH_fx, 1 ) ) + && LT_32( st_fx->prev_enerLL_fx, L_shl( st_fx->enerLL_fx, 1 ) ) && GT_32( st_fx->prev_enerLL_fx, L_shr( st_fx->enerLL_fx, 1 ) ) )) + || (EQ_16(st_fx->prev_fractive_fx,1) && + GT_32(L_shr(st_fx->prev_enerLH_fx,2), Mult_32_16(st_fx->enerLH_fx,24576)) ) /* 24576 in Q13*/ + || (GT_32(L_shr(st_fx->enerLL_fx,1), Mult_32_16(st_fx->enerLH_fx, 24576)) && /*24576 = 1.5 in Q14*/ + LT_16(st_fx->tilt_wb_fx, 20480) )/* 20480 = 10 in Q11*/ + ) + { + is_fractive = 0; + move16(); + } + ELSE + { + is_fractive = 1; + move16(); + } + } + + /* WB/SWB bandwidth switching */ + IF( st_fx->bws_cnt_fx > 0 ) + { + f_fx = 1489; /*Q15*/ + inc_fx = 1489; /*Q15*/ + IF(EQ_16(is_fractive, 1)) + { + Copy(lsf_tab_fx, st_fx->lsp_prevfrm_fx, LPC_SHB_ORDER); + } + ELSE + { + FOR (i=0; ilsp_prevfrm_fx[i] = f_fx; + move16(); + f_fx = add(f_fx, inc_fx); + } + } + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( (NE_16(st_fx->last_extl_fx, SWB_TBE)&&NE_16(st_fx->last_extl_fx,FB_TBE)&& + !(L_sub(L_shr(st_fx->prev_enerLH_fx, 1), st_fx->enerLH_fx) < 0 &&L_sub(st_fx->prev_enerLH_fx, L_shr(st_fx->enerLH_fx,1)>0))) + || sub(st_fx->last_core_fx, ACELP_CORE) != 0 + || (sub(st_fx->last_core_fx, ACELP_CORE) == 0 && L_sub(L_abs(L_sub(st_fx->last_core_brate_fx, st_fx->core_brate_fx)), 3600) > 0) + || sub((is_fractive ^ st_fx->prev_fractive_fx), 1) == 0 ) + { + set16_fx( GainShape, 11587, NUM_SHB_SUBFR ); + } + ELSE + { + if(GT_16(st_fx->prev_GainShape_fx, 11587)) + { + st_fx->prev_GainShape_fx = 11587; + move16(); + } + set16_fx( GainShape, st_fx->prev_GainShape_fx, NUM_SHB_SUBFR ); + } + + Copy( st_fx->lsp_prevfrm_fx, lsf_shb, LPC_SHB_ORDER ); + set16_fx( shb_res_gshape, 3277/*0.2f Q14*/, NB_SUBFR16k ); /* Q14 */ + } + ELSE /* No bandwidth switching */ + { + test(); + IF( NE_16(st_fx->last_extl_fx, SWB_TBE)&&NE_16(st_fx->last_extl_fx,FB_TBE)) + { + f_fx = 1489; /*Q15*/ move16(); + inc_fx = 1489; /*Q15*/ move16(); + FOR (i=0; ilsp_prevfrm_fx[i] = f_fx; + move16(); + f_fx = add(f_fx, inc_fx); + } + } + + IF( !st_fx->bfi_fx ) + { + IF(st_fx->use_partial_copy) + { + IF(NE_16(st_fx->last_extl_fx, SWB_TBE)) + { + st_fx->GainFrame_prevfrm_fx = 0; + move16(); + move16(); + move16(); + f_fx = 1489/*0.045454f Q15*/; /*Q15*/ + inc_fx = 1489/*0.045454f Q15*/;; /*Q15*/ + FOR (i=0; ilsp_prevfrm_fx[i] = f_fx; + move16(); + f_fx = add(f_fx, inc_fx); + } + } + Copy( st_fx->lsp_prevfrm_fx, lsf_shb, LPC_SHB_ORDER ); + set16_fx( GainShape, RECIP_ROOT_EIGHT_FX, NUM_SHB_SUBFR ); + + IF( EQ_16(st_fx->rf_frame_type,RF_NELP)) + { + /* Frame gain */ + GainFrame = L_mac( SHB_GAIN_QLOW_FX, st_fx->rf_indx_tbeGainFr, SHB_GAIN_QDELTA_FX ); + move32();/*Q18*/ + L_tmp = Mult_32_16( GainFrame, 27213 ); /*Q16*/ /* 3.321928 in Q13 */ + + frac = L_Extract_lc( L_tmp, &exp ); + L_tmp = Pow2( 30, frac ); + GainFrame = L_shl( L_tmp, sub( exp, 12 ) ); /*Q18*/ + IF( EQ_16(st_fx->core_fx,ACELP_CORE)&&EQ_16(st_fx->last_core_fx,ACELP_CORE) + && !st_fx->prev_use_partial_copy && EQ_16(st_fx->prev_coder_type_fx,UNVOICED) + && NE_32(GainFrame,st_fx->GainFrame_prevfrm_fx) && NE_16(st_fx->next_coder_type,GENERIC) && EQ_16(st_fx->last_extl_fx, SWB_TBE) ) + { + /*GainFrame = 0.2f*GainFrame + 0.8f*st_fx->GainFrame_prevfrm_fx;*/ + GainFrame = L_add(Mult_32_16(st_fx->GainFrame_prevfrm_fx, 26214), Mult_32_16(GainFrame, 6553)); + } + } + ELSE + { + temp = 0; + move16(); + /* Frame gain */ + SWITCH (st_fx->rf_indx_tbeGainFr) + { + case 0: + GainFrame = 131072; /* 0.5f in Q18 */ + IF(LE_32(st_fx->GainFrame_prevfrm_fx, 327680l/*1.25 Q18*/)) temp = 26214/*0.8 Q15*/; + move16(); + BREAK; + case 1: + GainFrame = 524288; /* 2.0f in Q18 */ + IF(GT_32(st_fx->GainFrame_prevfrm_fx, 327680l/*1.25 Q18*/)&&LE_32(st_fx->GainFrame_prevfrm_fx,786432l/*3 Q18*/)) temp = 26214/*0.8 Q15*/; + move16(); + test(); + BREAK; + case 2: + GainFrame = 1048576;/* 4.0f in Q18 */ + IF(GT_32(st_fx->GainFrame_prevfrm_fx, 786432l/*3 Q18*/)&&LE_32(st_fx->GainFrame_prevfrm_fx,1572864l/*6 Q18*/)) temp = 26214/*0.8 Q15*/; + move16(); + test(); + BREAK; + case 3: + GainFrame = 2097152;/* 8.0f in Q18 */ + IF(GT_32(st_fx->GainFrame_prevfrm_fx, 1572864l/*6 Q18*/)&&LE_32(st_fx->GainFrame_prevfrm_fx,4194304l/*16Q18*/)) temp = 26214/*0.8 Q15*/; + move16(); + test(); + BREAK; + default: + fprintf(stderr, "RF SWB-TBE gain bits not supported."); + } + IF(EQ_16(st_fx->last_extl_fx, SWB_TBE)) + { + GainFrame = L_add(Mult_32_16(st_fx->GainFrame_prevfrm_fx, temp), Mult_32_16(GainFrame, sub(32767,temp))); + } + IF(EQ_16(st_fx->core_fx,ACELP_CORE)&&EQ_16(st_fx->last_core_fx,ACELP_CORE)) + { + IF(!st_fx->prev_use_partial_copy && EQ_16(st_fx->last_coder_type_fx, VOICED)&&EQ_16(st_fx->rf_frame_type,RF_GENPRED)&>_32(GainFrame,2097152)&<_32(GainFrame,3059606)) + { + GainFrame = Mult_32_16(GainFrame,9830); + } + } + } + } + ELSE + { + + /* de-quantization */ + dequantizeSHBparams_fx_9_1( st_fx, st_fx->extl_fx, st_fx->extl_brate_fx, lsf_shb, GainShape, &GainFrame, &stemp, + &shb_ener_sf_32, shb_res_gshape, &mixFactors ); + Q_shb = 0; + move16(); + /* o: shb_ener_sf_32 in (2*Q_shb) */ + /* o: shb_res_gshape in Q14 */ + /* o: GainShape Q15 */ + /* o: GainFrame Q18 */ + } + } + ELSE /* FER concealment of TBE parameters */ + { + Copy( st_fx->lsp_prevfrm_fx, lsf_shb, LPC_SHB_ORDER ); + + /* Gain shape concealment */ + IF( EQ_16(st_fx->codec_mode, MODE1)) + { + /* Gradient based GS estimation */ + gradientGainShape(st_fx, GainShape, &GainFrame); + /* o: GainShape[16] in Q15 */ + /* o: GainFrame in Q18 */ + } + ELSE + { + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + FOR( j = 0; j < 4; j++ ) + { + GainShape[i * 4 + j] = mult_r( st_fx->cummulative_damping, st_fx->GainShape_Delay[4+i]); + move16(); + } + } + IF( GT_16( tilt_swb_fec, 8<<11 )) /* tilt_swb_fec in Q11 */ + { + IF ( EQ_16(st_fx->nbLostCmpt, 1)) + { + GainFrame = Mult_32_16(st_fx->GainFrame_prevfrm_fx, 19661/*0.6f Q15*/); + } + ELSE IF( EQ_16(st_fx->nbLostCmpt, 2)) + { + GainFrame = Mult_32_16(st_fx->GainFrame_prevfrm_fx, 11469/*0.35f Q15*/); + } + ELSE + { + GainFrame = Mult_32_16(st_fx->GainFrame_prevfrm_fx, 6554/*0.2f Q15*/); + } + GainFrame = Mult_32_16( GainFrame, st_fx->cummulative_damping); + } + ELSE + { + GainFrame = st_fx->GainFrame_prevfrm_fx; + move16(); /* gain locking */ + } + } + + /* FER concealment for 24.4kbps and 32kbps */ + test(); + IF(EQ_32(st_fx->total_brate_fx,ACELP_24k40)||EQ_32(st_fx->total_brate_fx,ACELP_32k)) + { + IF(EQ_16(st_fx->codec_mode, MODE1)) + { + /*scale = st->prev1_shb_ener_sf/root_a(st->prev2_shb_ener_sf * st->prev3_shb_ener_sf); */ + L_tmp = L_mult(extract_l(st_fx->prev2_shb_ener_sf_fx), extract_l(st_fx->prev3_shb_ener_sf_fx)); /*Q1*/ + tmp = round_fx(root_a_fx(L_tmp, 1, &exp)); /* Q = 15-exp */ + tmp1 = extract_l(st_fx->prev1_shb_ener_sf_fx); /*Q0*/ + i = sub(norm_s(tmp1), 1); + tmp1 = shl(tmp1, i); /* Qi */ + if(tmp == 0) + { + tmp = 32767/*1.0f Q15*/; + move16(); /*Q15*/ + } + ELSE + { + scale = div_s(tmp1, tmp); /* Q15 - Q(15-exp) + Qi = Qexp+i */ + scale = s_max(scale, 0); + /*scale = st->prev_res_shb_gshape * min(scale, 1.0f); */ + tmp = shl(scale, 15 - exp - i); /*Q15*/ + } + scale = mult_r(st_fx->prev_res_shb_gshape_fx, tmp); /* Q14 */ + + test(); + IF( GT_32( L_shr(st_fx->prev2_shb_ener_sf_fx, 1), st_fx->prev1_shb_ener_sf_fx )|| + GT_32( L_shr(st_fx->prev3_shb_ener_sf_fx, 1), st_fx->prev2_shb_ener_sf_fx ) ) + { + /* shb_ener_sf_32 = 0.5f * scale * st_fx->prev1_shb_ener_sf_fx; */ + shb_ener_sf_32 = Mult_32_16( st_fx->prev1_shb_ener_sf_fx, scale ); + + if( GT_16(st_fx->nbLostCmpt, 1)) + { + /* shb_ener_sf_32 *= 0.5f; */ + shb_ener_sf_32 = L_shr(shb_ener_sf_32, 1); + } + } + ELSE + { + /* shb_ener_sf = scale * scale * st_fx->prev1_shb_ener_sf_fx; */ + L_tmp = L_mult(scale, scale); /* Q29 */ + shb_ener_sf_32 = L_shl(Mult_32_16(st_fx->prev1_shb_ener_sf_fx, round_fx(L_tmp)), 2); + } + } + ELSE + { + test(); + IF( GT_32( L_shr(st_fx->prev2_shb_ener_sf_fx, 1), st_fx->prev1_shb_ener_sf_fx )|| + GT_32( L_shr(st_fx->prev3_shb_ener_sf_fx, 1), st_fx->prev2_shb_ener_sf_fx ) ) + { + /* shb_ener_sf_32 = 0.5f * st->cummulative_damping * st_fx->prev1_shb_ener_sf_fx; */ + shb_ener_sf_32 = L_shr( Mult_32_16( st_fx->prev1_shb_ener_sf_fx, st_fx->cummulative_damping ), 1 ); + } + ELSE + { + shb_ener_sf_32 = Mult_32_16( st_fx->prev1_shb_ener_sf_fx, st_fx->cummulative_damping ); + } + } + } + + shb_ener_sf_32 = L_max( shb_ener_sf_32, 1l/*1.0f Q0*/ ); + mixFactors = st_fx->prev_mixFactors_fx; + + IF(EQ_16(st_fx->codec_mode, MODE1)) + { + set16_fx( shb_res_gshape, 3277/*0.2f Q14*/, 5 ); /* Q14 */ + } + ELSE + { + set16_fx( shb_res_gshape, 16384/*1.0f Q14*/, 5 ); /* Q14 */ + } + } + } + + /* get the gainshape delay */ + Copy( &st_fx->GainShape_Delay[4], &st_fx->GainShape_Delay[0], NUM_SHB_SUBFR / 4 ); + IF ( (st_fx->rf_flag != 0) || EQ_32(st_fx->total_brate_fx, ACELP_9k60)) + { + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + st_fx->GainShape_Delay[i + 4] = s_min( s_max( GainShape[i * 4], 3277/*0.1f Q15*/ ), 16384/*0.5f Q15*/ ); + move16(); + } + } + ELSE + { + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + st_fx->GainShape_Delay[i + 4] = GainShape[i * 4]; + move16(); + } + } + + /* voice factor modification to limit any spurious jumps in the middle of voiced subframes*/ + /* mean(voice_factors[i], 4); */ + L_tmp = L_mult(voice_factors[0], 8192); + L_tmp = L_mac(L_tmp, voice_factors[1], 8192); + L_tmp = L_mac(L_tmp, voice_factors[2], 8192); + mean_vf = mac_r(L_tmp, voice_factors[3], 8192); + + Copy( voice_factors, vf_modified, NB_SUBFR16k ); + + test(); + IF( EQ_16(coder_type, VOICED)||GT_16(mean_vf,13107/*0.4f Q15*/ )) + { + FOR( i = 1; i < NB_SUBFR; i++ ) + { + L_tmp = L_mult(voice_factors[i], 26214/*0.8f Q15*/); + vf_modified[i] = mac_r(L_tmp, voice_factors[i-1], 6554/*0.2f Q15*/); + move16(); + } + IF( NE_16(st_fx->L_frame_fx, L_FRAME)) + { + L_tmp = L_mult(voice_factors[4], 26214/*0.8f Q15*/); + vf_modified[4] = mac_r(L_tmp, voice_factors[3], 6554/*0.2f Q15*/); + move16(); + } + } + + /* convert quantized LSFs to LSPs for interpolation */ + E_LPC_lsf_lsp_conversion(lsf_shb, lsp_shb_2, LPC_SHB_ORDER); + + test(); + IF( EQ_16(st_fx->last_extl_fx, SWB_TBE)||EQ_16(st_fx->last_extl_fx,FB_TBE)) + { + /* SHB LSP values from prev. frame for interpolation */ + Copy(st_fx->swb_lsp_prev_interp_fx, lsp_shb_1, LPC_SHB_ORDER); + } + ELSE + { + /* Use current frame's LSPs; in effect no interpolation */ + Copy(lsp_shb_2, lsp_shb_1, LPC_SHB_ORDER); + } + + test(); + test(); + test(); + IF( st_fx->bws_cnt_fx == 0 && st_fx->bws_cnt1_fx == 0 && st_fx->prev_use_partial_copy == 0 && st_fx->use_partial_copy == 0 ) + { + lsf_diff[0] = 16384; + move16(); /*Q15*/ + lsf_diff[sub(LPC_SHB_ORDER,1)] = 16384; + move16(); /*Q15*/ + FOR(i=1; i < LPC_SHB_ORDER-1; i++) + { + lsf_diff[i] = sub(lsf_shb[i],lsf_shb[sub(i,1)]); + move16(); + } + + a2rc_fx (st_fx->cur_sub_Aq_fx+1, refl, M); + tmp = add(16384, shr(refl[0],1)); /*Q14*/ + tmp1 = mult(27425,tmp); + tmp1 = mult(tmp1,tmp); /*Q10*/ + tmp2 = shr(mult(31715,tmp),2); /*Q10*/ + tilt_para = add(sub(tmp1,tmp2),1335); /*Q10*/ + + test(); + IF(NE_16(st_fx->last_extl_fx,SWB_TBE)&&NE_16(st_fx->last_extl_fx,FB_TBE)) + { + FOR( i=1; iprev_lsf_diff_fx[i-1] = shr(lsf_diff[i], 1); + move16(); + } + } + + IF( LE_32(st_fx->total_brate_fx,ACELP_16k40)) + { + test(); + test(); + test(); + test(); + test(); + IF(!(GT_16(st_fx->prev_tilt_para_fx,5120)&&(EQ_16(coder_type,TRANSITION)||LT_16(tilt_para,1024)))&& + !(((LT_16(st_fx->prev_tilt_para_fx,3072) && GE_16(st_fx->prev_coder_type_fx,VOICED))) && GT_16(tilt_para,5120) )) + { + FOR( i = 1; i < LPC_SHB_ORDER-1; i++ ) + { + IF(LT_16(lsf_diff[i],st_fx->prev_lsf_diff_fx[i-1])) + { + tmp = mult(26214,lsf_diff[i]); + + test(); + IF( st_fx->prev_lsf_diff_fx[i-1] <= 0 || tmp < 0 ) /* safety check in case of bit errors */ + { + st_fx->BER_detect = 1; + move16(); + tmp = 0; + } + ELSE + { + tmp = div_s(tmp,st_fx->prev_lsf_diff_fx[i-1]); + } + + tmp = s_max(tmp,16384); + w[i] = s_min(tmp,32767); + move16(); + } + ELSE + { + tmp = mult(26214,st_fx->prev_lsf_diff_fx[i-1]); + + test(); + IF( lsf_diff[i] <= 0 || tmp < 0 ) /* safety check in case of bit errors */ + { + st_fx->BER_detect = 1; + move16(); + tmp = 0; + } + ELSE + { + tmp = div_s(tmp,lsf_diff[i]); + } + + tmp = s_max(tmp,16384); + w[i] = s_min(tmp,32767); + move16(); + } + } + w[0] = w[1]; + w[sub(LPC_SHB_ORDER,1)] = w[sub(LPC_SHB_ORDER,2)]; + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + tmp1 = mult(lsp_shb_1[i],sub(32767,w[i])); + tmp2 = mult(lsp_shb_2[i],w[i]); + lsp_temp[i] =add(tmp1,tmp2); + move16(); + } + } + ELSE + { + Copy(lsp_shb_2, lsp_temp, LPC_SHB_ORDER); + } + } + + Copy( lsf_diff + 1, st_fx->prev_lsf_diff_fx, LPC_SHB_ORDER-2 ); + st_fx->prev_tilt_para_fx = tilt_para; + } + ELSE + { + Copy(lsp_shb_2, lsp_temp, LPC_SHB_ORDER); + } + + test(); + IF ( EQ_32(st_fx->total_brate_fx, ACELP_24k40 )||EQ_32(st_fx->total_brate_fx,ACELP_32k)) + { + /* ---------- SHB LSP interpolation ---------- */ + ptr_lsp_interp_coef = interpol_frac_shb; /*Q15*/ + FOR( j = 0; j < 4; j++ ) + { + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + /*lsp_temp_fx[i] = lsp_shb_1_fx[i]*(*ptr_lsp_interp_coef_fx) */ + /* + lsp_shb_2_fx[i]*(*(ptr_lsp_interp_coef_fx+1));*/ + L_tmp = L_mult(lsp_shb_1[i], (*ptr_lsp_interp_coef)); + lsp_temp[i] = mac_r(L_tmp, lsp_shb_2[i], (*(ptr_lsp_interp_coef+1))); + move16(); + } + ptr_lsp_interp_coef += 2; + + /* convert from lsp to lsf */ + /*old code: lsp2lsf_fx(lsp_temp, lsp_temp, LPC_SHB_ORDER, INT_FS_FX); */ /* input lsp_temp_fx in Q15*/ + + tmp = i_mult(j, (LPC_SHB_ORDER+1)); + /* convert LSPs to LP coefficients */ + E_LPC_f_lsp_a_conversion(lsp_temp, lpc_shb_sf+tmp, LPC_SHB_ORDER); + /* Bring the LPCs to Q12 */ + Copy_Scale_sig( lpc_shb_sf+tmp, lpc_shb_sf+tmp, LPC_SHB_ORDER+1, sub(norm_s(lpc_shb_sf[tmp]),2) ); + } + } + /*ELSE*/ + { + /* for 13.2 and 16.4kbps */ + E_LPC_f_lsp_a_conversion(lsp_temp, lpc_shb, LPC_SHB_ORDER); + Copy_Scale_sig( lpc_shb, lpc_shb, LPC_SHB_ORDER+1, sub(norm_s(lpc_shb[0]),2) ); /* Q12 */ + } + + /* Save the SWB LSP values from current frame for interpolation */ + Copy(lsp_shb_2, st_fx->swb_lsp_prev_interp_fx, LPC_SHB_ORDER); + /* lsp_shb_2_fx in Q15 */ + + /* save the shb_ener Q18, prev_resgainshape Q14, and mixFactor Q15 values */ + st_fx->prev3_shb_ener_sf_fx = st_fx->prev2_shb_ener_sf_fx; + st_fx->prev2_shb_ener_sf_fx = st_fx->prev1_shb_ener_sf_fx; + st_fx->prev1_shb_ener_sf_fx = shb_ener_sf_32; + st_fx->prev_res_shb_gshape_fx = shb_res_gshape[4]; + st_fx->prev_mixFactors_fx = mixFactors; + + /* SWB CNG/DTX - update memories */ + Copy( st_fx->lsp_shb_prev_fx, st_fx->lsp_shb_prev_prev_fx, LPC_SHB_ORDER ); /* Q15 */ + Copy( lsf_shb, st_fx->lsp_shb_prev_fx, LPC_SHB_ORDER ); /* Q15 */ + + /* vind = (short)(mixFactors*8.0f); */ + vind = shl(mixFactors,3-15); /* 3 for mpy by 8.0f, -15 to bring it to Q0 */ + /* i: mixFactors in Q15 */ + /* o: vind in Q0 */ + + /* Determine formant PF strength */ + formant_fac = swb_formant_fac_fx( lpc_shb[1], &st_fx->tilt_mem_fx ); + /* o: formant_fac in Q15 */ + + /* -------- start of memory rescaling -------- */ + /* ----- calculate optimum Q_bwe_exc and rescale memories accordingly ----- */ + Lmax = 0; + FOR( cnt = 0; cnt < L_FRAME32k; cnt++ ) + { + Lmax = L_max( Lmax, L_abs( bwe_exc_extended[cnt] ) ); + } + Q_bwe_exc = norm_l( Lmax ); + if(Lmax == 0) + { + Q_bwe_exc = 31; + } + Q_bwe_exc = add( Q_bwe_exc, add( Q_exc, Q_exc ) ); + + /* Account for any outliers in the memories from previous frame for rescaling to avoid saturation */ + find_max_mem_dec( st_fx, &n_mem, &n_mem2, &n_mem3 ); /* for >=24.4, use n_mem2 lpc_syn, shb_20sample, and mem_stp_swb_fx memory */ + + tmp = add( st_fx->prev_Q_bwe_exc, n_mem ); + if( GT_16( Q_bwe_exc, tmp)) + { + Q_bwe_exc = tmp; + } + + /* rescale the memories if Q_bwe_exc is different from previous frame */ + sc = sub( Q_bwe_exc, st_fx->prev_Q_bwe_exc ); + IF( sc != 0 ) + { + rescale_genSHB_mem_dec( st_fx, sc ); + } + + /* rescale the bwe_exc_extended and bring it to 16-bit single precision with dynamic norm */ + Copy( st_fx->old_bwe_exc_extended_fx, bwe_exc_extended_16, NL_BUFF_OFFSET ); + sc = sub( Q_bwe_exc, add( Q_exc, Q_exc ) ); + + FOR( cnt = 0; cnt < L_FRAME32k; cnt++ ) + { + bwe_exc_extended_16[cnt + NL_BUFF_OFFSET] = round_fx( L_shl( bwe_exc_extended[cnt], sc ) ); + } + Copy( bwe_exc_extended_16 + L_FRAME32k, st_fx->old_bwe_exc_extended_fx, NL_BUFF_OFFSET ); + + /* state_syn_shbexc_fx is kept at (st_fx->prev_Q_bwe_syn) for 24.4/32kbps or is kept at Q_bwe_exc for 13.2/16.4kbps */ + Copy( st_fx->state_syn_shbexc_fx, shaped_shb_excitation, L_SHB_LAHEAD ); + + /* save the previous Q factor (32-bit) of the buffer */ + st_fx->prev_Q_bwe_exc = Q_bwe_exc; + move16(); + + Q_bwe_exc = sub( Q_bwe_exc, 16 ); /* Q_bwe_exc reflecting the single precision dynamic norm-ed buffers from here */ + + /* -------- end of rescaling memories -------- */ + Q_bwe_exc_fb = st_fx->prev_Q_bwe_exc_fb; + move16(); + + IF( GT_32(st_fx->total_brate_fx, ACELP_32k)) + { + FOR( j = 0; j < 4; j++ ) + { + Copy(lpc_shb, &lpc_shb_sf[j*(LPC_SHB_ORDER+1)], LPC_SHB_ORDER+1); + } + } + + /* Calculate the 6 to 14 kHz (or 7.5 - 15.5 kHz) SHB excitation signal from the low band ACELP core excitation */ + GenShapedSHBExcitation_fx( shaped_shb_excitation + L_SHB_LAHEAD, lpc_shb, White_exc16k, + st_fx->mem_csfilt_fx, st_fx->mem_genSHBexc_filt_down_shb_fx, st_fx->state_lpc_syn_fx, + coder_type, bwe_exc_extended_16, st_fx->bwe_seed_fx, vf_modified, st_fx->extl_fx, + &( st_fx->tbe_demph_fx ), &( st_fx->tbe_premph_fx ), lpc_shb_sf, shb_ener_sf_32, + shb_res_gshape, shb_res_dummy, &vind, formant_fac, st_fx->fb_state_lpc_syn_fx, + &(st_fx->fb_tbe_demph_fx), &Q_bwe_exc, &Q_bwe_exc_fb,Q_shb, n_mem2, st_fx->prev_Q_bwe_syn, st_fx->total_brate_fx, st_fx->prev_bfi_fx ); + + *Q_white_exc = Q_bwe_exc_fb; + IF( EQ_16(st_fx->extl_fx, FB_TBE)) + { + st_fx->prev_Q_bwe_exc_fb = Q_bwe_exc_fb; + move16(); + } + ELSE + { + /*Indirectly a memory reset of FB memories for next frame such that rescaling of memories would lead to 0 due to such high prev. Q value. + 51 because of 31 + 20(shift of Q_bwe_exc_fb before de-emphasis)*/ + st_fx->prev_Q_bwe_exc_fb = 51; + move16(); + } + /* rescale the TBE post proc memory */ + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + st_fx->mem_stp_swb_fx[i] = shl(st_fx->mem_stp_swb_fx[i], Q_bwe_exc - st_fx->prev_Q_bwe_syn); + move16(); + } + + FOR( i = 0; i < L_FRAME16k; i+=L_SUBFR16k ) + { + /* TD BWE post-processing */ + PostShortTerm_fx( &shaped_shb_excitation[L_SHB_LAHEAD+i], lpc_shb, &shaped_shb_excitationTemp[i], st_fx->mem_stp_swb_fx, + st_fx->ptr_mem_stp_swb_fx, &(st_fx->gain_prec_swb_fx), st_fx->mem_zero_swb_fx, formant_fac ); + } + Copy( shaped_shb_excitationTemp, &shaped_shb_excitation[L_SHB_LAHEAD], L_FRAME16k ); /* Q_bwe_exc */ + + tmp = sub(shl(Q_bwe_exc, 1), 31+16); + prev_pow = L_shl(1407374848l/*0.00001f Q47*/, tmp); /* 2*(Q_bwe_exc) */ + curr_pow = L_shl(1407374848l/*0.00001f Q47*/, tmp); /* 2*(Q_bwe_exc) */ + FOR( i = 0; i < L_SHB_LAHEAD + 10; i++ ) + { + prev_pow = L_mac0( prev_pow, shaped_shb_excitation[i], shaped_shb_excitation[i] ); /*2*Q_bwe_exc*/ + curr_pow = L_mac0( curr_pow, shaped_shb_excitation[i + L_SHB_LAHEAD + 10], shaped_shb_excitation[i+L_SHB_LAHEAD + 10] ); /* 2*Q_bwe_exc */ + } + + if( GT_16( voice_factors[0], 24576/*0.75f Q15*/ )) + { + curr_pow = L_shr( curr_pow, 2 ); /* Q(2*Q_bwe_exc) */ + } + + Lscale = root_a_over_b_fx( curr_pow, + shl(Q_bwe_exc, 1), + prev_pow, + shl(Q_bwe_exc, 1), + &exp ); + + FOR( i = 0; i < L_SHB_LAHEAD; i++ ) + { + L_tmp = Mult_32_16( Lscale, shaped_shb_excitation[i] ); /* Q_bwe_exc + (31-exp) - 15 */ + shaped_shb_excitation[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc */ + } + IF( exp < 0 ) + { + Lscale = L_shl(Lscale, exp); + exp = 0; + } + FOR( ; i < L_SHB_LAHEAD + 10; i++ ) + { + temp = i_mult(sub(i,19), 3277/*0.1f Q15*/); /* Q15 */ + L_tmp1 = Mult_32_16(L_shl(1, sub(31,exp)), temp); /* Q31-exp */ + temp = sub(32767/*1.0f Q15*/, temp); + Lscale = L_add(Mult_32_16(Lscale, temp), L_tmp1); + L_tmp = Mult_32_16( Lscale, shaped_shb_excitation[i] ); /* Q_bwe_exc + (31-exp) - 15 */ + shaped_shb_excitation[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc */ + } + + /* Update SHB excitation */ + Copy( shaped_shb_excitation + L_FRAME16k, st_fx->state_syn_shbexc_fx, L_SHB_LAHEAD ); /* Q_bwe_exc */ + + l_subframe_fx = L_FRAME16k/NUM_SHB_SUBGAINS; + L_ener = 0; + FOR(i = 0; i < NUM_SHB_SUBGAINS; i++) + { + L_tmp = 0; + ener_tmp[i] = 0; + + { + Word64 tmp64 = 0; + move64(); + FOR(j = 0; j < l_subframe_fx; j++) + { + tmp64 = W_mac0_16_16( tmp64, shaped_shb_excitation[i*l_subframe_fx+j], shaped_shb_excitation[i*l_subframe_fx+j] );/* 2*Q_bwe_exc */ + } + L_tmp = W_sat_l(tmp64); + } + + L_tmp = Mult_32_16(L_tmp, 410/*0.0125 Q15*/); /* 2*Q_bwe_exc: ener_tmp_fx in (2*Q_bwe_exc) */ + IF( L_tmp != 0 ) + { + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + exp = sub( exp, 30 - (2 * Q_bwe_exc) ); + + tmp = div_s( 16384, tmp ); + L_tmp = L_deposit_h( tmp ); + L_tmp = Isqrt_lc( L_tmp, &exp ); + ener_tmp[i] = L_shl( L_tmp, sub(add( exp, shl(Q_bwe_exc,1)),31)); /*2 * Q_bwe_exc: Q31 -exp +exp +2 * Q_bwe_exc -31 */ move32(); + L_ener = L_add(L_ener, L_shr(ener_tmp[i], 2));/* 2*Q_bwe_exc */ + } + } + ener = s_max(1, round_fx( L_shl( L_ener, sub(19, shl(Q_bwe_exc, 1)) ) )); /* Q3: 2*Q_bwe_exc+19-2*Q_bwe_exc-16 */ + + /* WB/SWB bandwidth switching */ + IF( st_fx->bws_cnt_fx > 0 ) + { + ener = mult(ener, 11587); + /*bandwidth switching should be updated*/ + if( GT_16( st_fx->tilt_swb_fx, 16384 )) + { + st_fx->prev_fractive_fx = 1; + move16(); + } + + IF( is_fractive == 0 ) + { + IF( GT_16( st_fx->tilt_wb_fx, 2048 )) /*assuming st_fx->tilt_wb_fx in Q11*/ + { + st_fx->tilt_wb_fx = 2048; + move16(); + } + ELSE IF( LT_16( st_fx->tilt_wb_fx, 1024 )) + { + st_fx->tilt_wb_fx = 1024; + move16(); + } + test(); + if( st_fx->prev_fractive_fx == 1 && GT_16( st_fx->tilt_wb_fx, 1024 )) + { + st_fx->tilt_wb_fx = 1024; + move16(); + } + } + ELSE + { + IF(GT_16(st_fx->tilt_wb_fx, 8192)) + { + IF(st_fx->prev_fractive_fx == 0) + { + st_fx->tilt_wb_fx = 8192; + } + ELSE + { + st_fx->tilt_wb_fx = 16384; + } + } + ELSE + { + st_fx->tilt_wb_fx = shl(st_fx->tilt_wb_fx, 2); + } + } + + IF(ener != 0) + { + L_tmp = L_shl(L_mult0(ener, st_fx->tilt_wb_fx), sub(st_fx->Q_syn2, 14)); /* 3+11 +st_fx->Q_syn2 -14 = st_fx->Q_syn2*/ + exp_ener = norm_s(ener); + tmp = shl(ener, exp_ener);/*Q(3+exp)*/ + inv_ener = div_s(16384, tmp);/*Q(15+14-3-exp) = 26- exp*/ + + test(); + IF( GT_32(L_tmp, st_fx->enerLH_fx)) /*st_fx->Q_syn2*/ + { + st_fx->tilt_wb_fx = extract_h(L_shr(Mult_32_16(st_fx->enerLH_fx, inv_ener), sub(sub(st_fx->Q_syn2, exp_ener),16))); /*Q11*/ + /*st_fx->Q_syn2 -1 + 26- exp_ener -15 -(st_fx->Q_syn2 -exp_ener -16 ) -16 +1 -1 = (11) *0.5*/ + } + ELSE IF( LT_32(L_tmp, Mult_32_16(st_fx->enerLH_fx, 1638))&&EQ_16(is_fractive,1)) + { + st_fx->tilt_wb_fx = extract_h(L_shr(Mult_32_16(st_fx->enerLH_fx, inv_ener), sub(sub(st_fx->Q_syn2, exp_ener), 15))); /*Q11*/ + /*st_fx->Q_syn2 -1 + 26- exp_ener -15 -(st_fx->Q_syn2 -exp_ener -15 ) -16 = (11) 0.25*/ + } + L_tmp = L_mult0(st_fx->prev_ener_shb_fx, inv_ener); /*Q(1+15+14-3-exp_ener) = 27 -exp_ener*/ + GainFrame_prevfrm_fx = L_shr(L_tmp, sub(9, exp_ener)); /*27 -exp_ener -(9-exp_ener )= Q18*/ + } + ELSE + { + GainFrame_prevfrm_fx = 0; + } + + IF( EQ_16(is_fractive , 1)) + { + GainFrame = L_shl((Word32)st_fx->tilt_wb_fx, 10); + } + ELSE + { + GainFrame = L_shl((Word32)st_fx->tilt_wb_fx, 8); + } + + test(); + IF( EQ_16((is_fractive & st_fx->prev_fractive_fx), 1)&>_32(GainFrame,GainFrame_prevfrm_fx)) + { + GainFrame = L_add(Mult_32_16(GainFrame_prevfrm_fx, 26214), Mult_32_16(GainFrame, 6554));/* 18 +15 -15 = 18*/ + } + ELSE + { + test(); + test(); + test(); + test(); + IF((LT_32(L_shr(st_fx->prev_enerLH_fx, 1), st_fx->enerLH_fx)&& GT_32(st_fx->prev_enerLH_fx,L_shr(st_fx->enerLH_fx,1))) + && (LT_32(L_shr(st_fx->prev_enerLL_fx, 1), st_fx->enerLL_fx) && GT_32(st_fx->prev_enerLL_fx, L_shr(st_fx->enerLL_fx, 1)) ) && (is_fractive ^ st_fx->prev_fractive_fx) == 0) + { + GainFrame = L_add(L_shr(GainFrame, 1), L_shr(GainFrame_prevfrm_fx, 1)); + } + ELSE + { + test(); + IF(is_fractive == 0 && EQ_16(st_fx->prev_fractive_fx, 1)) + { + L_tmp1 = L_shl(Mult_32_16(GainFrame, 3277), 13); /* 31 */ + L_tmp = L_sub(2147483647, L_tmp1); /* 31 */ + GainFrame = L_add(Mult_32_32(GainFrame, L_tmp), Mult_32_32(GainFrame_prevfrm_fx, L_tmp1)); /* 18 */ + } + ELSE + { + GainFrame = L_add(L_shr(GainFrame, 1), L_shr(L_min(GainFrame_prevfrm_fx, GainFrame), 1)); /* 18 */ + } + } + } + + GainFrame = Mult_32_16(GainFrame, i_mult(sub(N_WS2N_FRAMES, st_fx->bws_cnt_fx), 819)); /*Q18*/ + } + ELSE + { + IF(st_fx->bws_cnt1_fx > 0) + { + GainFrame = Mult_32_16(GainFrame, i_mult(st_fx->bws_cnt1_fx, 819)); /*Q18*/ + } + IF(GE_16(st_fx->nbLostCmpt, 1)) + { + ener = s_max(1, ener); + exp_ener = norm_s(ener); + tmp = shl(ener, exp_ener);/*Q(3+exp)*/ + inv_ener = div_s(16384, tmp);/*Q(15+14-3-exp)*/ + prev_ener_ratio_fx = L_shr(L_mult0(st_fx->prev_ener_shb_fx, inv_ener), sub(9, exp_ener)); /*Q: 1+26-exp-9+exp = 18 */ + } + + IF(EQ_16(st_fx->nbLostCmpt, 1)) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( NE_16(st_fx->clas_dec, UNVOICED_CLAS)&&NE_16(st_fx->clas_dec,UNVOICED_TRANSITION)&<_16(st_fx->tilt_swb_fec_fx,16384)&& + ((GT_32(st_fx->enerLL_fx, L_shr(st_fx->prev_enerLL_fx, 1)) && LT_32(L_shr(st_fx->enerLL_fx, 1), st_fx->prev_enerLL_fx) )|| (GT_32(st_fx->enerLH_fx, L_shr(st_fx->prev_enerLH_fx, 1)) && LT_32(L_shr(st_fx->enerLH_fx, 1), st_fx->prev_enerLH_fx)))) + { + IF(GT_32(L_shr(prev_ener_ratio_fx, 2), GainFrame))/*18*/ + { + GainFrame = L_add(Mult_32_16(prev_ener_ratio_fx, 13107), Mult_32_16(GainFrame, 19661));/*18*/ + } + ELSE IF(GT_32(L_shr(prev_ener_ratio_fx, 1), GainFrame)) + { + GainFrame = L_add(Mult_32_16(prev_ener_ratio_fx, 26214), Mult_32_16(GainFrame, 6554)); + } + ELSE + { + GainFrame = L_add(Mult_32_16(prev_ener_ratio_fx, 6554), Mult_32_16(GainFrame, 26214)); + } + + test(); + IF(GT_16(tilt_swb_fec, st_fx->tilt_swb_fec_fx)&&st_fx->tilt_swb_fec_fx>0) + { + exp = norm_s(st_fx->tilt_swb_fec_fx); + tmp = shl(st_fx->tilt_swb_fec_fx, exp);/*Q(11+exp)*/ + tmp = div_s(16384, tmp);/*Q(15+14-11-exp)*/ + tmp = extract_h(L_shl(L_mult0(tmp, st_fx->tilt_wb_fx),sub(exp,1)));/*18 -exp +11 + exp -1 -16 =12; */ + GainFrame = L_shl(Mult_32_16(GainFrame, s_min(tmp, 20480)), 3); /*Q18 = 18 +12 -15 +3 */ + } + + } + ELSE IF( (NE_16(st_fx->clas_dec, UNVOICED_CLAS)||GT_16(st_fx->tilt_swb_fec_fx,16384))&>_32(L_shr(prev_ener_ratio_fx,2),GainFrame)&& + (GT_32(st_fx->enerLL_fx, L_shr(st_fx->prev_enerLL_fx, 1)) || GT_32(st_fx->enerLH_fx, L_shr(st_fx->prev_enerLH_fx, 1)) ) ) + { + GainFrame = L_add(Mult_32_16(prev_ener_ratio_fx, 6554), Mult_32_16(GainFrame, 26214)); + } + } + ELSE IF( GT_16(st_fx->nbLostCmpt, 1)) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF(GT_32(L_shr(prev_ener_ratio_fx, 2), GainFrame)&&((EQ_16(st_fx->codec_mode,MODE1)&>_32(st_fx->enerLL_fx,st_fx->prev_enerLL_fx)&>_32(st_fx->enerLH_fx,st_fx->prev_enerLH_fx))||EQ_16(st_fx->codec_mode,MODE2))) + { + test(); + IF( GT_16(tilt_swb_fec, 20480)&>_16(st_fx->tilt_swb_fec_fx,20480)) + { + GainFrame = L_min(L_add(Mult_32_16(prev_ener_ratio_fx, 26214), Mult_32_16(GainFrame, 6554)), L_shl(Mult_32_16(GainFrame, 16384), 3)); /*Q18*/ + } + ELSE + { + GainFrame = L_min(L_add(Mult_32_16(prev_ener_ratio_fx, 16384), Mult_32_16(GainFrame, 16384)), L_shl(Mult_32_16(GainFrame, 16384), 3)); /*Q18*/ + } + } + ELSE IF(GT_32(prev_ener_ratio_fx, GainFrame)&&((EQ_16(st_fx->codec_mode,MODE1)&>_32(st_fx->enerLL_fx,st_fx->prev_enerLL_fx)&>_32(st_fx->enerLH_fx,st_fx->prev_enerLH_fx))||EQ_16(st_fx->codec_mode,MODE2))) + { + test(); + IF( GT_16(tilt_swb_fec, 20480)&>_16(st_fx->tilt_swb_fec_fx,20480)) + { + GainFrame = L_add(Mult_32_16(prev_ener_ratio_fx, 16384), Mult_32_16(GainFrame, 16384)); + } + ELSE + { + GainFrame = L_add(Mult_32_16(prev_ener_ratio_fx, 6554), Mult_32_16(GainFrame, 26214)); + } + } + } + } + st_fx->prev_fractive_fx = is_fractive; + move16(); + + /* Adjust the subframe and frame gain of the synthesized shb signal */ + IF( EQ_16(st_fx->L_frame_fx, L_FRAME)) + { + /* pitch = 0.25f*sum_s(pitch_buf, 4); */ + L_tmp = L_mult(pitch_buf[0], 8192); + FOR (i=1; itotal_brate_fx, ACELP_24k40)&&EQ_16(st_fx->prev_coder_type_fx,coder_type)&&NE_16(coder_type,UNVOICED)) + || (LE_32(st_fx->total_brate_fx, ACELP_16k40) && (EQ_16(st_fx->prev_coder_type_fx, coder_type) || (EQ_16(st_fx->prev_coder_type_fx, VOICED) && EQ_16(coder_type, GENERIC) ) || (EQ_16(st_fx->prev_coder_type_fx, GENERIC) && EQ_16(coder_type, VOICED) )))) + && GT_16(pitch_fx, 4480 /*70 in Q6*/) && LT_16(st_fx->extl_fx, FB_TBE) ) + { + FOR(i=0; i st_fx->prev_ener_fx*st_fx->prev_GainShape_fx ) */ + L_tmp1 = Mult_32_16(ener_tmp[i], GainShape_tmp[i]); /* (2*Q_bwe_exc) */ + L_tmp2 = Mult_32_16(st_fx->prev_ener_fx, st_fx->prev_GainShape_fx); /* (2*st_fx->prev_ener_fx_Q) */ + tmp = sub(shl(Q_bwe_exc, 1), shl(st_fx->prev_ener_fx_Q, 1)); + L_tmp2 = L_shl(L_tmp2, tmp); /* new Q = (2*Q_bwe_exc) */ + + IF (GT_32(L_tmp1,L_tmp2)) + { + /*GainShape_tmp_fx[i] = 0.5f*(L_tmp2/ener_tmp_fx[i] + GainShape_tmp_fx[i]);*/ + /* tmp = L_tmp2/ener_tmp_fx[i]*/ + L_tmp = L_tmp2; + if(L_tmp2 < 0) + { + L_tmp = L_negate(L_tmp2); + } + + expb = norm_l(L_tmp); + fracb = round_fx(L_shl(L_tmp,expb)); + expb = 30-expb; /* - (2*Q_bwe_exc_ext); */ + + expa = norm_l(ener_tmp[i]); + fraca = extract_h(L_shl(ener_tmp[i],expa)); + expa = 30-expa ; + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); + exp = sub(sub(expb,expa),1); + tmp = shl(tmp,exp); + GainShape_tmp[i] = add(tmp,shr(GainShape_tmp[i],1));/* Q15 */ + } + + st_fx->prev_ener_fx = ener_tmp[i]; + st_fx->prev_GainShape_fx = GainShape_tmp[i]; + st_fx->prev_ener_fx_Q = Q_bwe_exc; + } + FOR(i=0; iprev_ener_fx_Q = Q_bwe_exc; + move16(); + } + + + /* Back up the Q_bwe_exc associated with shaped_shb_excitation for the next frame*/ + st_fx->prev_Q_bwe_syn = Q_bwe_exc; + move16(); + + /* Scale the shaped excitation */ + ScaleShapedSHB_fx( SHB_OVERLAP_LEN, + shaped_shb_excitation, /* i/o: Q_bwe_exc */ + st_fx->syn_overlap_fx, + GainShape, /* Q15 */ + GainFrame, /* Q18 */ + window_shb_fx, + subwin_shb_fx, + &Q_bwe_exc + , &Qx + , n_mem3 + , st_fx->prev_Q_bwe_syn2 + ); + /* i: GainShape Q15 */ + /* i: GainFrame Q18 */ + /* i: shaped_shb_excitation Q_bwe_exc */ + /* o: shaped_shb_excitation Q_bwe_exc */ + /* o: st_fx->syn_overlap_fx Q_bwe_exc */ + + + max = 0; + FOR( i = 0; i < L_FRAME16k; i++ ) + { + max = s_max( max, shaped_shb_excitation[i] ); /* Q0 */ + } + + IF( max == 0 ) + { + curr_frame_pow = 0; + move16(); + n = 0; + move16(); + } + ELSE + { + n = norm_s( max ); + max = 0; + FOR( i = 0; i < L_FRAME16k; i++ ) + { + shaped_shb_excitation_frac[i] = shl( shaped_shb_excitation[i], n ); /*Q_bwe_exc+n*/ move16(); + } + + curr_frame_pow = 0; + FOR( i = 0; i < L_FRAME16k; i++ ) + { + L_tmp = L_mult0( shaped_shb_excitation_frac[i], shaped_shb_excitation_frac[i] ); /*2*(Q_bwe_exc+n)*/ + curr_frame_pow = L_add( curr_frame_pow, L_shr( L_tmp, 9 ) ); /*2*(Q_bwe_exc+n)-9*/ + } + } + curr_frame_pow_exp = sub(shl(add( Q_bwe_exc, n ), 1), 9); + + + tmp=sub( st_fx->prev_frame_pow_exp, curr_frame_pow_exp ); + IF( tmp > 0 ) /* shifting prev */ + { + IF (GT_16(tmp,32)) + { + st_fx->prev_frame_pow_exp = add(curr_frame_pow_exp,32); + tmp = 32; + } + st_fx->prev_swb_bwe_frame_pow_fx = L_shr(st_fx->prev_swb_bwe_frame_pow_fx, tmp); + st_fx->prev_frame_pow_exp = curr_frame_pow_exp; + move16(); + } + ELSE /* shifting curr */ + { + IF (LT_16(tmp,-32)) + { + curr_frame_pow_exp = sub(st_fx->prev_frame_pow_exp,32); + tmp = -32; + } + curr_frame_pow = L_shr(curr_frame_pow, -tmp); + curr_frame_pow_exp = st_fx->prev_frame_pow_exp; + } + test(); + IF( !st_fx->bfi_fx && st_fx->prev_bfi_fx ) + { + L_tmp = L_shr( curr_frame_pow, 4 ); + L_tmp = Mult_32_16( L_tmp, 17476 ); + + test(); + test(); + IF( ( GT_32( L_shr( curr_frame_pow, 1 ), st_fx->prev_swb_bwe_frame_pow_fx ))&& + ( GT_32( st_fx->prev_swb_bwe_frame_pow_fx, L_tmp ) ) && EQ_16(st_fx->prev_coder_type_fx,UNVOICED) ) + { + L_tmp = root_a_over_b_fx( st_fx->prev_swb_bwe_frame_pow_fx, curr_frame_pow_exp, curr_frame_pow, curr_frame_pow_exp, &exp ); + scale = round_fx( L_shl( L_tmp, exp ) ); /*Q15*/ + + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + temp = round_fx( L_shl( L_tmp, exp ) ); /*Q15*/ + } + ELSE + { + scale = temp = 32767; + move16();/*Q15*/ + } + FOR( j = 0; j < 8; j++ ) + { + GainShape[2 * j] = mult_r( GainShape[2 * j], scale ); + move16(); + GainShape[2 * j + 1] = mult_r( GainShape[2 * j + 1], scale ); + move16(); + FOR( i = 0; i < L_FRAME16k / 8; i++ ) + { + shaped_shb_excitation[i + j*L_FRAME16k/8] = mult_r( shaped_shb_excitation[i + j*L_FRAME16k/8],scale ); + move16(); + } + + IF( temp > 0 ) + { + /* scale <= temp, due to scale = sqrt( st->prev_swb_bwe_frame_pow_fx/curr_frame_pow ), temp = sqrt( scale, 1.f/8.f ) + and curr_frame_pow > st->prev_swb_bwe_frame_pow_fx -> scale <= 1.0, sqrt(scale, 1.f/8.f) >= scale */ + IF( LT_16( scale, temp )) + { + scale = div_s( scale, temp ); + } + ELSE + { + scale = 32767; + move16(); + } + } + ELSE + { + scale = 0; + move16(); + } + } + } + + /* adjust the FEC frame energy */ + IF( st_fx->bfi_fx ) + { + scale = temp = 4096; + move16();/*Q12*/ + + IF (EQ_16(st_fx->nbLostCmpt,1)) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( GT_32(curr_frame_pow, st_fx->prev_swb_bwe_frame_pow_fx)&& + NE_16(st_fx->prev_coder_type_fx, UNVOICED) && + NE_16(st_fx->last_good_fx,UNVOICED_CLAS) ) + { + L_tmp = root_a_over_b_fx( st_fx->prev_swb_bwe_frame_pow_fx, curr_frame_pow_exp, curr_frame_pow, curr_frame_pow_exp, &exp ); /*31 - exp*/ + scale = round_fx( L_shl( L_tmp, sub(exp,3))); /*Q12*/ + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + temp = round_fx( L_shl( L_tmp, sub(exp,3))); /*Q12*/ + } + ELSE IF( LT_32(curr_frame_pow, L_shr(st_fx->prev_swb_bwe_frame_pow_fx,1))&&EQ_16(st_fx->nbLostCmpt,1)&& + (GT_32(st_fx->enerLL_fx, L_shr( st_fx->prev_enerLL_fx,1)) || GT_32(st_fx->enerLH_fx, L_shr(st_fx->prev_enerLH_fx,1)) ) && + (EQ_16(st_fx->prev_coder_type_fx ,UNVOICED) || EQ_16(st_fx->last_good_fx, UNVOICED_CLAS) || GT_16(st_fx->tilt_swb_fec_fx , 10240) )) + { + L_tmp = root_a_over_b_fx( st_fx->prev_swb_bwe_frame_pow_fx, curr_frame_pow_exp, curr_frame_pow, curr_frame_pow_exp, &exp ); + scale = round_fx( L_shl( L_tmp, sub(exp,3) ) ); /*Q12*/ + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + temp = round_fx( L_shl( L_tmp, sub(exp,3) ) ); /*Q12*/ + } + } + ELSE IF (GT_16(st_fx->nbLostCmpt,1)) + { + test(); + test(); + test(); + test(); + test(); + IF( GT_32(curr_frame_pow , st_fx->prev_swb_bwe_frame_pow_fx)) + { + L_tmp = root_a_over_b_fx( st_fx->prev_swb_bwe_frame_pow_fx, curr_frame_pow_exp, curr_frame_pow, curr_frame_pow_exp, &exp ); + scale = round_fx( L_shl( L_tmp, sub(exp,3) ) ); /*Q12*/ + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + temp = round_fx( L_shl( L_tmp, sub(exp,3) ) ); /*Q12*/ + + } + ELSE IF( LT_32(curr_frame_pow, L_shr(st_fx->prev_swb_bwe_frame_pow_fx,1))&& + (GT_32(st_fx->enerLL_fx, L_shr( st_fx->prev_enerLL_fx,1)) || GT_32(st_fx->enerLH_fx, L_shr(st_fx->prev_enerLH_fx,1)) ) && + (st_fx->prev_coder_type_fx == UNVOICED || st_fx->last_good_fx == UNVOICED_CLAS || GT_16(st_fx->tilt_swb_fec_fx , 10240)) ) + { + L_tmp = root_a_over_b_fx( st_fx->prev_swb_bwe_frame_pow_fx, curr_frame_pow_exp, curr_frame_pow, curr_frame_pow_exp, &exp ); + L_tmp =L_min(L_tmp,L_shl(2,(31 - exp)));/*31 - exp*/ + scale = round_fx( L_shl( L_tmp, sub(exp,3) )); /*Q12*/ + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + L_tmp = root_a_fx( L_tmp, 31 - exp, &exp ); + temp = round_fx( L_shl( L_tmp, sub(exp,3) ) ); /*Q12*/ + } + } + FOR( j = 0; j < 8; j++ ) + { + GainShape[2 * j] = shl(mult_r( GainShape[2 * j], scale ),3); + move16(); /* 15 +12 +3-15 =15*/ + GainShape[2 * j + 1] = shl(mult_r( GainShape[2 * j + 1], scale ),3); + move16(); + FOR( i = 0; i < 40; i++ ) + { + shaped_shb_excitation[add(i,i_mult(j,40))] = shl(mult_r( shaped_shb_excitation[add(i,i_mult(j,40))], scale) ,3); + move16(); /* Q_bwe_exc +12+3 -15 =Q_bwe_exc*/ + } + + IF( temp > 0 ) + { + IF( LT_16( scale, temp )) + { + scale = shr(div_s( scale, temp ),3); + } + ELSE + { + tmp1 = sub(norm_s(scale), 1); + tmp2 = norm_s(temp); + scale = div_s( shl(scale, tmp1), shl(temp, tmp2) ); + scale = shr(scale, add(sub(tmp1, tmp2), 3)); + } + } + ELSE + { + scale = 0; + move16(); + } + } + } + + st_fx->prev_swb_bwe_frame_pow_fx = curr_frame_pow; + move32(); + st_fx->prev_frame_pow_exp = curr_frame_pow_exp; + move16(); + + + { + Word64 prev_ener_shb64 = 0; + move64(); + FOR( i = 0; i < L_FRAME16k; i++ ) + { + prev_ener_shb64 = W_mac0_16_16( prev_ener_shb64, shaped_shb_excitation[i], shaped_shb_excitation[i] ); /* Q0 */ + } + L_prev_ener_shb = W_sat_l(prev_ener_shb64); + } + + + /* st->prev_ener_shb = sqrt(st->prev_ener_shb/L_FRAME16k) */ + L_prev_ener_shb = Mult_32_16( L_prev_ener_shb, 26214 ); /* 2*Q_bwe_exc_mod+8; 26214=(1/L_FRAME16k) in Q23 */ + st_fx->prev_ener_shb_fx = 0; + move16(); + + IF( L_prev_ener_shb != 0 ) + { + exp = norm_l( L_prev_ener_shb ); + tmp = extract_h( L_shl( L_prev_ener_shb, exp ) ); + exp = sub( exp, 30 - ( 2 * Q_bwe_exc + 8 ) ); + + tmp = div_s( 16384, tmp ); + L_tmp = L_deposit_h( tmp ); + L_tmp = Isqrt_lc( L_tmp, &exp ); + st_fx->prev_ener_shb_fx = round_fx( L_shl( L_tmp, sub( exp, 14 ) ) ); /* Q1 */ + } + /* st->prev_SWB_fenv[i] = sqrt(curr_frame_pow/L_FRAME16k); */ + L_tmp = Mult_32_16( curr_frame_pow, 26214 ); /* curr_frame_pow_exp+8; 26214=(1/L_FRAME16k) in Q23 */ + tmp =0; + IF( L_tmp != 0 ) + { + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + exp = sub( exp, 30 - ( curr_frame_pow_exp + 8 ) ); + + tmp = div_s( 16384, tmp ); + L_tmp = L_deposit_h( tmp ); + L_tmp = Isqrt_lc( L_tmp, &exp ); + tmp = round_fx( L_shl( L_tmp, sub( exp, 14 ) ) ); /* Q1 */ + } + set16_fx(st_fx->prev_SWB_fenv_fx, tmp, SWB_FENV); /* Q1 */ + + + /* rescale the memories if Q_bwe_exc is different from previous frame */ + sc = sub( Q_bwe_exc, st_fx->prev_Q_bwe_syn2 ); + IF( sc != 0 ) + { + FOR( i = 0; i < 2*ALLPASSSECTIONS_STEEP; i++ ) + { + st_fx->genSHBsynth_state_lsyn_filt_shb_local_fx[i] = shl( st_fx->genSHBsynth_state_lsyn_filt_shb_local_fx[i], sc ); + move16(); + } + + IF(EQ_16(st_fx->L_frame_fx, L_FRAME)) + { + FOR( i = 0; i < HILBERT_MEM_SIZE; i++ ) + { + st_fx->genSHBsynth_Hilbert_Mem_fx[i] = L_shl( st_fx->genSHBsynth_Hilbert_Mem_fx[i], sc ); + move32(); + } + } + IF( st_fx->output_Fs_fx == 48000 ) + { + Scale_sig(st_fx->int_3_over_2_tbemem_dec_fx, INTERP_3_2_MEM_LEN, sc); + } + IF( st_fx->output_Fs_fx == 16000 ) + { + Scale_sig(st_fx->mem_resamp_HB_32k_fx, 2*ALLPASSSECTIONS_STEEP + 1, sc); + } + } + /* i: shaped_shb_excitation[320] in (Q_bwe_exc) */ + /* i/o: st_fx->genSHBsynth_Hilbert_Mem_fx in (Q_bwe_exc) */ + /* i/o: st_fx->genSHBsynth_state_lsyn_filt_shb_local_fx in (Q_bwe_exc) */ + /* o: error in (Qx) */ + GenSHBSynth_fx( shaped_shb_excitation, error, st_fx->genSHBsynth_Hilbert_Mem_fx, + st_fx->genSHBsynth_state_lsyn_filt_shb_local_fx, st_fx->L_frame_fx, &( st_fx->syn_dm_phase_fx ) ); + + Copy( error + L_FRAME32k - L_SHB_TRANSITION_LENGTH, st_fx->old_tbe_synth_fx, L_SHB_TRANSITION_LENGTH ); + + /* resample SHB synthesis (if needed) and scale down */ + synth_scale_fx = 32767; + move16(); /* 1.0 in Q15 */ + if(EQ_16(st_fx->codec_mode,MODE1)) + { + synth_scale_fx = 29491; + move16(); /* 0.9 in Q15 */ + } + + IF( EQ_32(st_fx->output_Fs_fx, 48000)) + { + IF( EQ_32(st_fx->extl_fx,FB_TBE)) + { + tmp = norm_l( GainFrame ); + if(GainFrame == 0) + { + tmp = 31; + } + L_tmp = L_shl(GainFrame,tmp);/* 18 + tmp */ + + tmp1 =0; + FOR( i = 0; i < L_FRAME16k; i++ ) + { + L_tmp1 = Mult_32_16( L_tmp, GainShape[NUM_SHB_SUBFR * i / L_FRAME16k] ); /* Q : 18 + tmp +15 -15*/ + White_exc16k[i] = round_fx( Mult_32_16( L_tmp1, White_exc16k[i] ) );/* 18 + tmp +*Q_white_exc -15 -16 */ + tmp1 = s_max(tmp1,abs_s(White_exc16k[i])); + } + + *Q_white_exc = sub(add(*Q_white_exc, tmp),13); /* *Q_white_exc + 18 + tmp -15 -16 */ + tmp = norm_s( tmp1 ); + if(tmp1 == 0) + { + tmp = 15; + } + + FOR(i=0; iint_3_over_2_tbemem_dec_fx, allpass_poles_3_ov_2 ); + } + ELSE IF( EQ_32(st_fx->output_Fs_fx, 32000)) + { + IF( NE_16(synth_scale_fx,32767)) /* 1.0 in Q15 */ + { + FOR( i = 0; i < L_FRAME32k; i++ ) + { + synth[i] = mult_r( synth_scale_fx, error[i] ); + move16();/*Qx*/ + } + } + ELSE + { + Copy(error, synth, L_FRAME32k); + } + } + ELSE IF( EQ_32(st_fx->output_Fs_fx, 16000)) + { + IF( NE_16(synth_scale_fx,32767)) /* 1.0 in Q15 */ + { + FOR( i = 0; i < L_FRAME32k; i++ ) + { + error[i] = mult_r(error[i],synth_scale_fx); + move16(); + } + } + + Decimate_allpass_steep_fx( error, st_fx->mem_resamp_HB_32k_fx, L_FRAME32k, synth ); + } + + /* Update previous frame parameters for FEC */ + Copy( lsf_shb, st_fx->lsp_prevfrm_fx, LPC_SHB_ORDER ); + IF(EQ_16(st_fx->codec_mode, MODE1)) + { + st_fx->GainFrame_prevfrm_fx = GainFrame; + move16(); /*Q18*/ + st_fx->tilt_swb_fec_fx = tilt_swb_fec; + + if( !st_fx->bfi_fx ) + { + st_fx->GainAttn_fx = 32767; + move16(); + } + } + ELSE + { + IF( !st_fx->bfi_fx ) + { + st_fx->GainFrame_prevfrm_fx = GainFrame; + move16(); /*Q18*/ + st_fx->tilt_swb_fec_fx = tilt_swb_fec; + move16(); + st_fx->GainAttn_fx = 32767; + move16(); + } + } + + st_fx->prev_ener_fx = ener_tmp[NUM_SHB_SUBGAINS-1]; + st_fx->prev_GainShape_fx = GainShape[NUM_SHB_SUBFR-1]; + *Q_synth = Q_bwe_exc; + move16(); + st_fx->prev_Q_bwe_syn2 = Q_bwe_exc; + move16(); + st_fx->prev_Qx = Q_bwe_exc; + move16(); + return; +} + +static void gradientGainShape( + Decoder_State_fx *st_fx, + Word16 *GainShape, + Word32 *GainFrame) +{ + Word16 i,j,tmp; + Word16 GainShapeTemp[NUM_SHB_SUBFR/4]; + Word16 GainGrad0[3]; + Word16 GainGrad1[3]; + Word16 GainGradFEC[4]; + + /* the previous frame gainshape gradient and the gainshape gradient pattern for the current frame */ + FOR( j = 0; j < 3; j++ ) + { + GainGrad0[j] = sub( shr( st_fx->GainShape_Delay[j + 1], 1 ), shr( st_fx->GainShape_Delay[j], 1 ) ); + move16();/* Q14 */ + GainGrad1[j] = sub( shr( st_fx->GainShape_Delay[j + 5], 1 ), shr( st_fx->GainShape_Delay[j + 4], 1 ) ); + move16();/* Q14 */ + GainGradFEC[j + 1] = add( mult_r( GainGrad0[j], 13107 ), mult_r( GainGrad1[j], 19660 ) ); + move16(); /* Q14 */ + } + + /* gradient for the first gainshape */ + test(); + test(); + test(); + IF( ( ( GT_16( shr( GainGrad1[2], 1 ), GainGrad1[1] ))&&(GT_16(shr(GainGrad1[1],1),GainGrad1[0])))|| + ( ( LT_16( shr( GainGrad1[2], 1 ), GainGrad1[1] ) ) && ( LT_16( shr( GainGrad1[1], 1 ), GainGrad1[0] ) ) ) ) + { + GainGradFEC[0] = add( mult_r( GainGrad1[1], 3277 ), mult_r( GainGrad1[2], 29490 ) ); + move16(); /* Q14 */ + } + ELSE + { + GainGradFEC[0] = add( mult_r( GainGrad1[0], 6553 ), mult_r( GainGrad1[1], 9830 ) ); + move16(); + GainGradFEC[0] = add( GainGradFEC[0], mult_r( GainGrad1[2], 16384 ) ); + move16(); /* Q14 */ + } + + /* get the first gainshape template */ + test(); + test(); + IF( ( st_fx->prev_coder_type_fx == UNVOICED || st_fx->last_good_fx == UNVOICED_CLAS ) && GainGradFEC[0] > 0 ) + { + GainShapeTemp[0] = add( shr( st_fx->GainShape_Delay[7], 1 ), GainGradFEC[0] ); + move16(); + } + ELSE IF( GainGradFEC[0] > 0 ) + { + GainShapeTemp[0] = add( shr( st_fx->GainShape_Delay[7], 1 ), mult_r( GainGradFEC[0], 16384 ) ); + move16(); /* Q14 */ + } + ELSE + { + GainShapeTemp[0] = shr( st_fx->GainShape_Delay[7], 1 ); + move16();/* Q14 */ + } + + /*Get the second the third and the fourth gainshape template*/ + + tmp = shr( GainGrad1[2], 3 ); /* GainGrad1[2]/8 */ + tmp = mult_r( tmp, 26214 ); /* 0.8 in Q15 tmp*(8/10) */ + + test(); + IF( ( GT_16( tmp, GainGrad1[1] ))&&GainGrad1[1]>0) + { + FOR( i = 1; i < NUM_SHB_SUBFR / 4; i++ ) + { + GainShapeTemp[i] = add( GainShapeTemp[i - 1], mult_r( GainGradFEC[i], 26214 ) ); + move16(); /* GainShapeTemp[i-1] + 0.8* GainShapeTemp[i] */ + GainShapeTemp[i] = s_max( GainShapeTemp[i], 328/*0.01f Q15*/ ); + move16(); + } + } + ELSE + { + test(); + IF( ( GT_16( tmp, GainGrad1[1] ))&&GainGrad1[1]<0) + { + FOR( i = 1; i < NUM_SHB_SUBFR / 4; i++ ) + { + GainShapeTemp[i] = add( GainShapeTemp[i - 1], mult_r( GainGradFEC[i], 6553 ) ); + move16(); /* GainShapeTemp[i-1] + 0.8* GainShapeTemp[i] */ + GainShapeTemp[i] = s_max( GainShapeTemp[i], 328/*0.01f Q15*/ ); + move16(); /* Q14 */ + } + } + ELSE + { + FOR( i = 1; i < NUM_SHB_SUBFR / 4; i++ ) + { + GainShapeTemp[i] = add( GainShapeTemp[i - 1], GainGradFEC[i] ); + move16(); + GainShapeTemp[i] = s_max( GainShapeTemp[i], 328/*0.01f Q15*/ ); + move16(); + } + } + } + + /* Get the gainshape and gain frame for the current frame*/ + test(); + test(); + test(); + IF( ( st_fx->prev_coder_type_fx == UNVOICED || st_fx->last_good_fx == UNVOICED_CLAS ) && st_fx->nbLostCmpt == 1 ) + { + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + FOR( j = 0; j < 4; j++ ) + { + tmp = mult_r( GainShapeTemp[i], 19660 ); /* GainShapeTemp[i]*0.6 */ + + IF( GT_16( 8192, tmp )) + { + GainShape[i * 4 + j ] = shl( tmp, 2 ); + move16(); /* (GainShapeTemp[i]*0.6)>>1 */ + } + ELSE + { + GainShape[i * 4 + j ] = 32767; + move16(); /* Clipping here to avoid the a huge change of the code due to gain shape change */ + } + } + } + st_fx->GainAttn_fx = mult_r( st_fx->GainAttn_fx, 31129 ); + } + ELSE IF( st_fx->prev_coder_type_fx == UNVOICED || st_fx->last_good_fx == UNVOICED_CLAS ) + { + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + FOR( j = 0; j < 4; j++ ) + { + IF( LT_16( GainShapeTemp[i], 16384 )) + { + GainShape[i * 4 + j ] = shl( GainShapeTemp[i], 1 ); + move16(); + } + ELSE + { + GainShape[i * 4 + j ] = 32767 ; + move16(); + } + } + } + st_fx->GainAttn_fx = mult_r( st_fx->GainAttn_fx, 31129 ); + } + ELSE IF( st_fx->nbLostCmpt > 1 ) + { + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + FOR( j = 0; j < 4; j++ ) + { + GainShape[i * 4 + j ] = GainShapeTemp[i]; + move16(); + } + } + st_fx->GainAttn_fx = mult_r( st_fx->GainAttn_fx, 16384 ); + } + ELSE + { + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + FOR( j = 0; j < 4; j++ ) + { + IF( LT_16( GainShapeTemp[i], 16384 )) + { + GainShape[i * 4 + j] = shl( GainShapeTemp[i], 1 ); + move16(); + } + ELSE + { + GainShape[i * 4 + j] = 32767; + move16(); + } + } + } + st_fx->GainAttn_fx = mult_r( st_fx->GainAttn_fx, 27852 ); + } + + *GainFrame = Mult_32_16( st_fx->GainFrame_prevfrm_fx, st_fx->GainAttn_fx ); /* Q18 */ +} + +/*-------------------------------------------------------------------* + * Dequant_lower_LSF() + * + * Dequantized the lower LSFs + *-------------------------------------------------------------------*/ + + +static void Dequant_lower_LSF_fx( + const Word16 lsf_idx[], /* i : LSF indices */ + Word16 lsf_q[] /* o : Quantized LSFs */ +) +{ + Word16 i; + + lsf_q[0] = lsf_q_cb_fx[0][lsf_idx[0]]; + move16(); + FOR( i = 1; i < NUM_Q_LSF; i++ ) + { + lsf_q[i] = add( lsf_q_cb_fx[i][lsf_idx[i]], lsf_q[i - 1] ); + move16(); + } + + return; +} + +/*-------------------------------------------------------------------* + * Map_higher_LSF() + * + * Map the higher LSFs from the lower LSFs + *-------------------------------------------------------------------*/ + +static void Map_higher_LSF_fx( + Word16 lsf_q[], /* i/o : Quantized lower LSFs */ + const Word16 m, /* i : Mirroring point */ + const Word16 grid_in[] /* i : Input LSF smoohthing grid */ ) +{ + Word16 lsf_map[NUM_MAP_LSF]; + Word16 grid[NUM_MAP_LSF]; + Word16 last_q_lsf; + Word16 lsf_smooth[NUM_MAP_LSF]; + Word16 offset; + Word16 i; + Word16 scale; + + FOR( i = 0; i < NUM_MAP_LSF; i++ ) + { + lsf_map[i] = sub( shl( m, 1 ), lsf_q[NUM_MAP_LSF - 1 - i] ); + move16(); + } + + IF( GT_16( m, MAX_LSF_FX_BY_2 )) + { + offset = lsf_map[0]; + move16(); + scale = div_s( sub( MAX_LSF_FX, m ), m ); + FOR( i = 0; i < NUM_MAP_LSF; i++ ) + { + lsf_map[i] = add( mult_r( sub( lsf_map[i], offset ), scale ), offset ); + move16(); + } + } + + last_q_lsf = lsf_q[NUM_Q_LSF - 1]; + move16(); + scale = sub( MAX_LSF_FX, last_q_lsf ); + + FOR( i = 0; i < NUM_MAP_LSF; i++ ) + { + grid[i] = add( mult_r( grid_in[i], scale ), last_q_lsf ); + move16(); + } + + FOR( i = 0; i < NUM_MAP_LSF; i++ ) + { + lsf_smooth[i] = sub( mult_r( grid_smoothing_fx[i], grid[i] ), + mult_r( lsf_map[i], add( grid_smoothing_fx[i], -32768/*-1.0f Q15*/ ) ) ); + move16(); + } + + FOR( i = 0; i < NUM_MAP_LSF; i++ ) + { + lsf_q[NUM_Q_LSF + i] = lsf_smooth[i]; + move16(); + } + + return; +} + + + + +static void Dequant_mirror_point_fx( + const Word16 lsf_q[], /* i/o : Quantized lower LSFs */ + const Word16 m_idx, /* i : Mirror point index */ Word16* m /* i : Mirroring point */ ) +{ + *m = add( mirror_point_q_cb_fx[m_idx], lsf_q[NUM_Q_LSF - 1] ); + move16(); + + return; +} + + +/*==========================================================================*/ +/* FUNCTION : static void dequantizeSHBparams_fx_9_1 () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Dequantize super highband spectral envolope */ +/* temporal gains and frame gain */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _Word16 extl i : extension layer */ +/* _Word32 extl_brate i : extensiuon layer bitrate */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _Word16 *Q_lsf, o : SHB LSF from de-quantization Q15 */ +/* _Word16 *Q_subgain, o : SHB subframe gains from de-quantization Q15*/ +/* _Word32 *Q_framegrain o : SHB frame gain from de-quantization Q18 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*==========================================================================*/ +static void dequantizeSHBparams_fx_9_1( + Decoder_State_fx* st_fx, + const Word16 extl, /* i : extension layer */ + Word32 extl_brate, /* i : extensiuon layer bitrate */ + Word16* Q_lsf, /* o : SHB LSF from de-quantization Q15*/ + Word16* Q_subgain, /* o : SHB subframe gains from de-quantization Q15*/ + Word32* Q_framegrain, /* o : SHB frame gain from de-quantization Q18*/ + Word16* uv_flag, /* o : unvoiced flag*/ + Word32* Q_shb_ener_sf, /* o : Q15 */ + Word16* Q_shb_res_gshape, /* o : Q14 */ + Word16* Q_mixFactors /* o : Q15 */ +) +{ + Word16 i, j, idxLSF, idxSubGain, idxFrameGain; + Word16 Q_combined_gains[NUM_SHB_SUBFR/4]; + Word16 lsf_q[LPC_SHB_ORDER]; + Word16 lsf_idx[NUM_Q_LSF]; + Word16 m_idx, grid_idx; + Word16 m; + Word32 L_tmp; + Word16 tmp, frac, exp; + Word16 idx_shb_fr_gain, idx_res_gs[5], idx_mixFac; + Word16 temp_shb_ener_sf_fx; + + /* LSFs */ + + IF( EQ_16( extl, WB_TBE )) + { + IF( EQ_32( extl_brate, WB_TBE_0k35 )) + { + idxFrameGain = st_fx->gFrame_WB_fx; + idxLSF = st_fx->lsf_WB_fx; + + Copy( lbr_wb_bwe_lsfvq_cbook_2bit_fx + idxLSF * LPC_SHB_ORDER_LBR_WB, Q_lsf, LPC_SHB_ORDER_LBR_WB ); + set16_fx( Q_subgain, RECIP_ROOT_EIGHT_FX, NUM_SHB_SUBFR / 2 ); + Copy32( SHBCB_FrameGain16_fx + idxFrameGain, Q_framegrain, 1 ); + } + ELSE + { + *uv_flag = ( Word16 )get_next_indice_fx( st_fx, 1 ); + idxSubGain = ( Word16 )get_next_indice_fx( st_fx, NUM_BITS_SHB_SUBGAINS ); + move16(); + idxFrameGain = ( Word16 )get_next_indice_fx( st_fx, NUM_BITS_SHB_FrameGain ); + move16(); + idxLSF = ( Word16 )get_next_indice_fx( st_fx, NUM_BITS_WB_LSF ); + move16(); + Copy( wb_bwe_lsfvq_cbook_8bit_fx + idxLSF * LPC_SHB_ORDER_WB, Q_lsf, LPC_SHB_ORDER_WB ); + Copy( HBCB_SubGain5bit_fx + idxSubGain * NUM_SHB_SUBFR / 4, Q_combined_gains, NUM_SHB_SUBFR / 4 ); + + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + + L_tmp = L_mult( Q_combined_gains[i], 21771 ); /*Q26 0.166096 in Q17 */ + L_tmp = L_shr( L_tmp, 10 ); + frac = L_Extract_lc( L_tmp, &exp ); + tmp = extract_l( Pow2( 14, frac ) ); /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + Q_combined_gains[i] = shl( tmp, add( exp, 1 ) ); /* Q15 */ + } + + FOR( i=0; i < NUM_SHB_SUBFR / 2; i+= 2) + { + Q_subgain[i] = Q_combined_gains[i / 2]; + move16(); + Q_subgain[i + 1] = Q_combined_gains[i / 2]; + move16(); + } + + /* frame gain */ + Copy32( SHBCB_FrameGain64_fx + idxFrameGain, Q_framegrain, 1 ); + } + } + ELSE /* SWB TBE DEC */ + { + IF(EQ_16(st_fx->codec_mode,MODE2)) + { + idxSubGain = st_fx->idxSubGains_fx; + idxFrameGain = st_fx->idxFrameGain_fx; + } + ELSE + { + idxSubGain = ( Word16 )get_next_indice_fx( st_fx, NUM_BITS_SHB_SUBGAINS ); + idxFrameGain = ( Word16 )get_next_indice_fx( st_fx, NUM_BITS_SHB_FRAMEGAIN ); + } + + test(); + IF( EQ_32(st_fx->total_brate_fx, ACELP_24k40)||EQ_32(st_fx->total_brate_fx,ACELP_32k)) + { + IF(EQ_16(st_fx->codec_mode,MODE2)) + { + idx_shb_fr_gain = st_fx->idx_shb_fr_gain_fx; + } + ELSE + { + idx_shb_fr_gain = get_next_indice_fx( st_fx, NUM_BITS_SHB_ENER_SF ); + } + temp_shb_ener_sf_fx = usdequant_fx(idx_shb_fr_gain, 0, 86); /* 86 = 0.042f in Q11 = Qin-1 */ + /* o: temp_shb_ener_sf_fx in Q12 */ + + /* *Q_shb_ener_sf = Pow(10.0, temp_shb_ener_sf_fx ); */ + /* = pow(2, 3.321928*temp_shb_ener_sf_fx) */ + L_tmp = L_mult(temp_shb_ener_sf_fx, 27213 ); /* 3.321928 in Q13 -> L_tmp in Q12+Q13+1 = Q26 */ + L_tmp = L_shl( L_tmp, -10 ); /* bring L_tmp from Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); /* Extract exponent */ + L_tmp = Pow2(14, frac ); + *Q_shb_ener_sf = L_shl(L_tmp, exp-14+0 ); /* In Q_ener: 2*Q_shb+1, Q_shb = 0; */ + + FOR(i=0; i<5; i++) + { + IF(EQ_16(st_fx->codec_mode,MODE2)) + { + idx_res_gs[i] = st_fx->idx_res_gs_fx[i]; + move16(); + } + ELSE + { + idx_res_gs[i] = get_next_indice_fx( st_fx, NUM_BITS_SHB_RES_GS ); + move16(); + } + Q_shb_res_gshape[i] = usdequant_fx(idx_res_gs[i], + 2048/*0.125f Q14*/, /*2048 = 0.125 in Q14 */ + 1024/*0.125f Q13*/ /*1024 = 0.125 in Q13 */ + ); + move16(); + /* o: Q_shb_res_gshape in Q14 */ + } + + IF(EQ_16(st_fx->codec_mode,MODE2)) + { + idx_mixFac = st_fx->idx_mixFac_fx; + move16(); + } + ELSE + { + idx_mixFac = (Word16)get_next_indice_fx( st_fx, NUM_BITS_SHB_VF ); + } + *Q_mixFactors = usdequant_fx(idx_mixFac, 4096 /* 0.125 in Q15 */, 2048 /* 0.125 in Q14 */); + move16(); + /* o: Q_mixFactors in Q15 */ + } + ELSE + { + *Q_shb_ener_sf = L_deposit_l(0); + *Q_mixFactors = 0; + move16(); + set16_fx(Q_shb_res_gshape, 0, 5); + } + + /* LSFs */ + + + test(); + test(); + test(); + test(); + test(); + IF( (st_fx->rf_flag == 0) && !((EQ_32(st_fx->total_brate_fx, ACELP_9k60))||((st_fx->total_brate_fx==0)&&((EQ_32(st_fx->last_total_brate_fx,ACELP_9k60))||(EQ_32(st_fx->last_total_brate_fx,ACELP_13k20)&&EQ_16(st_fx->rf_flag_last,1)))))) + + { + /* LSFs */ + test(); + test(); + test(); + IF ( EQ_32(extl_brate, SWB_TBE_1k6)||EQ_32(extl_brate,FB_TBE_1k8)||EQ_32(extl_brate,SWB_TBE_2k8)||EQ_32(extl_brate,FB_TBE_3k0)) + { + IF(EQ_16(st_fx->codec_mode,MODE2)) + { + FOR (i = 0; i < NUM_Q_LSF; i++) + { + lsf_idx[i] = st_fx->lsf_idx_fx[i]; + move16(); + + } + } + ELSE + { + FOR (i = 0; i < NUM_Q_LSF; i++) + { + lsf_idx[i] = (Word16)get_next_indice_fx(st_fx, lsf_q_num_bits[i]); + move16(); + } + } + } + Dequant_lower_LSF_fx( lsf_idx, lsf_q ); + + IF(EQ_16(st_fx->codec_mode,MODE2)) + { + m_idx = st_fx->m_idx_fx; + } + ELSE + { + m_idx = (Word16)get_next_indice_fx( st_fx, MIRROR_POINT_BITS ); + move16(); + } + + Dequant_mirror_point_fx( lsf_q, m_idx, &m ); + + /* safety check in case of bit errors */ + IF(GT_16(m, MAX_LSF_FX)) + { + st_fx->BER_detect = 1; + m = MAX_LSF_FX-1; + } + + IF(EQ_16(st_fx->codec_mode,MODE2)) + { + grid_idx = st_fx->grid_idx_fx; + } + ELSE + { + grid_idx = (Word16)get_next_indice_fx( st_fx, NUM_LSF_GRID_BITS ); + move16(); + } + + Map_higher_LSF_fx( lsf_q, m, lsf_grid_fx[grid_idx] ); + + FOR (i = 0; i < LPC_SHB_ORDER; i++) + { + /* safety check in case of bit errors */ + IF(GT_16(lsf_q[LPC_SHB_ORDER - 1 - i], MAX_LSF_FX)) + { + st_fx->BER_detect = 1; + lsf_q[LPC_SHB_ORDER - 1 - i] = MAX_LSF_FX - 1; + } + Q_lsf[i] = sub( 16384, lsf_q[LPC_SHB_ORDER - 1 - i] ); + move16(); + } + } + ELSE + { + set16_fx(lsf_idx, 0, 5); + Copy(st_fx->lsf_idx_fx, lsf_idx, 5); + grid_idx = 0; + m_idx = 0; + Copy(swb_tbe_lsfvq_cbook_8b + lsf_idx[0]*LPC_SHB_ORDER, Q_lsf, LPC_SHB_ORDER); + } + + space_lsfs_fx( Q_lsf, LPC_SHB_ORDER ); + + /* Dequantize subgain indices */ + j = idxSubGain * NUM_SHB_SUBGAINS; + move16(); + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + /* Q_subgain[i] = (float) pow(10.0, SHBCB_SubGain5bit[j++]); */ + + L_tmp = L_mult( SHBCB_SubGain5bit_fx[j++], 27213 ); /*Q28 3.321928 in Q13 */ + L_tmp = L_shr( L_tmp, 12 ); + frac = L_Extract_lc( L_tmp, &exp ); + tmp = extract_l( Pow2( 14, frac ) ); /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + Q_subgain[i] = shl( tmp, add( exp, 1 ) ); /*Q15*/ move16(); + } + + FOR( i = NUM_SHB_SUBFR - 1; i >= 0; i-- ) + { + Q_subgain[i] = Q_subgain[i * NUM_SHB_SUBGAINS / NUM_SHB_SUBFR]; + move16(); + } + + /* Frame gain */ + *Q_framegrain = L_mac( SHB_GAIN_QLOW_FX, idxFrameGain, SHB_GAIN_QDELTA_FX ); + move32();/*Q18*/ + L_tmp = Mult_32_16( *Q_framegrain, 27213 ); /*Q16*/ /* 3.321928 in Q13 */ + frac = L_Extract_lc( L_tmp, &exp ); + L_tmp = Pow2( 30, frac ); + *Q_framegrain = L_shl( L_tmp, sub( exp, 12 ) ); /*Q18*/ + } + + return; +} + +/*-------------------------------------------------------------------* + * fb_tbe_dec() + * + * FB TBE decoder, 14(resp. 15.5) - 20 kHz band decoding module + *-------------------------------------------------------------------*/ +void fb_tbe_dec_fx( + Decoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 fb_exc[], /* i : FB excitation from the SWB part */ + Word16 Q_fb_exc, + Word16 *hb_synth, /* o : high-band synthesis */ + Word16 hb_synth_exp +) + +{ + Word16 i; + Word16 ratio = 0; + Word32 fb_exc_energy = 0; + Word16 fb_synth[L_FRAME48k]; + + /* decode FB slope information */ + test(); + test(); + IF ( EQ_16(st->extl_fx,FB_TBE)&&!st->bfi_fx) + { + IF( EQ_16(st->codec_mode,MODE2)) + { + i = st->idxGain_fx; + move16(); + } + ELSE + { + i = (Word16)get_next_indice_fx( st, 4 ); + } + ratio = shl(1,i); + } + ELSE if ( EQ_16(st->extl_fx,FB_TBE)&&st->bfi_fx) + { + ratio = st->prev_fbbwe_ratio_fx; + move16(); + } + fb_exc_energy = sum2_fx_mod(fb_exc,L_FRAME16k); + + /* FB TBE synthesis */ + synthesise_fb_high_band_fx( fb_exc,Q_fb_exc,fb_synth,fb_exc_energy,ratio, st->L_frame_fx, st->bfi_fx, &(st->prev_fbbwe_ratio_fx), st->fbbwe_hpf_mem_fx, st->fbbwe_hpf_mem_fx_Q,hb_synth_exp); + + /* add the fb_synth component to the hb_synth component */ + /* v_add_fx( hb_synth, fb_synth, hb_synth, L_FRAME48k );*/ + FOR (i=0; irf_flag,1)||EQ_32(st_fx->total_brate_fx,ACELP_9k60))&&EQ_16(st_fx->bwidth_fx,WB)) + { + /* WB LSF */ + st_fx->lsf_WB_fx = get_next_indice_fx(st_fx, NUM_BITS_LBR_WB_LSF); + + /* WB frame gain */ + st_fx->gFrame_WB_fx = get_next_indice_fx(st_fx, NUM_BITS_SHB_FrameGain_LBR_WB); + } + ELSE IF ( ( GE_32( st_fx->total_brate_fx, ACELP_9k60 ))&&(LE_32(st_fx->total_brate_fx,ACELP_32k))&& + ( ( EQ_16( st_fx->bwidth_fx, SWB ) ) || ( EQ_16( st_fx->bwidth_fx, FB ) ) ) ) + { + test(); + IF( (st_fx->rf_flag == 0) && (GT_32(st_fx->total_brate_fx, ACELP_9k60))) + { + FOR (i = 0; i < NUM_Q_LSF; i++) + { + st_fx->lsf_idx_fx[i] = get_next_indice_fx(st_fx, lsf_q_num_bits[i]); + move16(); + } + + st_fx->m_idx_fx = get_next_indice_fx(st_fx, MIRROR_POINT_BITS); + + st_fx->grid_idx_fx = get_next_indice_fx(st_fx, NUM_LSF_GRID_BITS); + + } + ELSE + { + st_fx->lsf_idx_fx[0] = get_next_indice_fx(st_fx, 8); + move16(); + st_fx->m_idx_fx = 0; + move16(); + st_fx->grid_idx_fx = 0; + move16(); + } + + /* shape gains */ + st_fx->idxSubGains_fx = get_next_indice_fx(st_fx, NUM_BITS_SHB_SUBGAINS); + + /* frame gain */ + st_fx->idxFrameGain_fx = get_next_indice_fx(st_fx, NUM_BITS_SHB_FRAMEGAIN); + + IF ( GE_32( st_fx->total_brate_fx, ACELP_24k40 )) + { + /* sub frame energy*/ + st_fx->idx_shb_fr_gain_fx = get_next_indice_fx(st_fx, NUM_BITS_SHB_ENER_SF); + + /* gain shapes residual */ + FOR (i = 0; i < NB_SUBFR16k; i++) + { + st_fx->idx_res_gs_fx[i] = get_next_indice_fx(st_fx, NUM_BITS_SHB_RES_GS); + move16(); + } + + /* voicing factor */ + st_fx->idx_mixFac_fx = get_next_indice_fx(st_fx, NUM_BITS_SHB_VF); + } + + IF (EQ_16(st_fx->tec_tfa, 1)) + { + st_fx->tec_flag = get_next_indice_fx(st_fx, BITS_TEC); + st_fx->tfa_flag = get_next_indice_fx(st_fx, BITS_TFA); + test(); + IF (st_fx->tfa_flag && st_fx->tec_flag) + { + st_fx->tec_flag = 2; + move16(); + st_fx->tfa_flag = 0; + move16(); + } + } + ELSE + { + st_fx->tec_flag = 0; + move16(); + st_fx->tfa_flag = 0; + move16(); + } + } + + IF ( EQ_16( st_fx->bwidth_fx, FB )) + { + st_fx->idxGain_fx = get_next_indice_fx(st_fx, 4); + } +} + + +/*---------------------------------------------------------------------* +* GenTransition() +* +* Generate a highband transition signal from the gain shape overlap +* buffer to fill the gap caused by the delay alignment buffer when +* switching from TBE to IGF +*---------------------------------------------------------------------*/ +void GenTransition_fx( + const Word16 *input, /* i : gain shape overlap buffer */ + const Word16 *old_hb_synth, /* i : synthesized HB from previous frame */ + Word16 length, /* i : targeted length of transition signal */ + Word16 *output, /* o : synthesized transitions signal */ + Word32 Hilbert_Mem[], /* i/o: memory */ + Word16 state_lsyn_filt_shb_local[],/* i/o: memory */ + Word16 mem_resamp_HB_32k[], /* i/o: memory */ + Word16 *syn_dm_phase, + Word32 target_fs, + Word16 *up_mem, + Word16 rf_flag + , Word32 bitrate +) +{ + Word16 i; + Word16 syn_overlap_32k[L_FRAME32k]; + Word32 L_tmp; + Word16 ol_len = 2*SHB_OVERLAP_LEN; + + /* upsample overlap snippet */ + Interpolate_allpass_steep_fx( input, state_lsyn_filt_shb_local, SHB_OVERLAP_LEN, syn_overlap_32k ); + + /* perform spectral flip and downmix with overlap snippet to match HB synth */ + test(); + IF( (rf_flag != 0) || EQ_32( bitrate, ACELP_9k60 )) + { + flip_and_downmix_generic_fx( syn_overlap_32k, syn_overlap_32k, 2*SHB_OVERLAP_LEN, Hilbert_Mem, + Hilbert_Mem + HILBERT_ORDER1, Hilbert_Mem + (HILBERT_ORDER1+2*HILBERT_ORDER2), + syn_dm_phase ); + } + ELSE + { + FOR(i = 0; i < ol_len; i=i+2) + { + syn_overlap_32k[i] = negate(syn_overlap_32k[i]); + move16(); + syn_overlap_32k[i+1] = syn_overlap_32k[i+1]; + move16(); + } + } + + /* cross fade of overlap snippet and mirrored HB synth from previous frame */ + FOR ( i = 0; i < ol_len; i++ ) + { + L_tmp = L_mult( window_shb_32k_fx[i], old_hb_synth[L_SHB_TRANSITION_LENGTH-1-i] ); + output[i] = mac_r( L_tmp, window_shb_32k_fx[2*L_SHB_LAHEAD-1-i], syn_overlap_32k[i] ); + } + + /* fill transition signal with mirrored HB synth from previous frame to fully fill delay alignment buffer gap */ + FOR ( ; i < length; i++) + { + output[i] = old_hb_synth[L_SHB_TRANSITION_LENGTH-1-i]; + } + + IF ( EQ_32( target_fs, 48000 )) + { + interpolate_3_over_2_allpass_fx( output, length, output, up_mem, allpass_poles_3_ov_2 ); + } + ELSE IF( EQ_32( target_fs, 16000 )) + { + Decimate_allpass_steep_fx( output, mem_resamp_HB_32k, L_FRAME32k, output ); + } + + return; +} + + +/*---------------------------------------------------------------------* + * GenTransition_WB_fx() + * + *---------------------------------------------------------------------*/ + +void GenTransition_WB_fx( + const Word16 *input, /* i : gain shape overlap buffer */ + const Word16 *old_hb_synth, /* i : synthesized HB from previous frame */ + const Word16 prev_Qx, /* i : scaling of old_hb_synth */ + Word16 length, /* i : targeted length of transition signal */ + Word16 *output, /* o : synthesized transitions signal */ + Word16 state_lsyn_filt_shb1[], + Word16 state_lsyn_filt_shb2[], + Word32 output_Fs, + Word16 *up_mem +) +{ + Word16 i; + Word32 L_tmp; + Word16 speech_buf_16k1[L_FRAME16k], speech_buf_16k2[L_FRAME16k]; + Word16 upsampled_synth[L_FRAME48k]; + Word16 input_scaled[SHB_OVERLAP_LEN/2]; + + /* upsample overlap snippet */ + Copy_Scale_sig(input, input_scaled, SHB_OVERLAP_LEN/2, prev_Qx); + Interpolate_allpass_steep_fx( input_scaled, state_lsyn_filt_shb1, SHB_OVERLAP_LEN/2, speech_buf_16k1); + Interpolate_allpass_steep_fx( speech_buf_16k1, state_lsyn_filt_shb2, SHB_OVERLAP_LEN, speech_buf_16k2); + + + /* perform spectral flip and downmix with overlap snippet to match HB synth */ + FOR(i = 0; i < SHB_OVERLAP_LEN; i+=2) + { + speech_buf_16k2[i] = negate(speech_buf_16k2[i]); + speech_buf_16k2[i+1] = speech_buf_16k2[i+1]; + } + + /* cross fade of overlap snippet and mirrored HB synth from previous frame */ + FOR (i=0; ilast_core_fx,ACELP_CORE)) + { + set16_fx( st_fx->old_bwe_exc_fx, 0, PIT16k_MAX * 2 ); + st_fx->bwe_non_lin_prev_scale_fx = L_deposit_l(0); + st_fx->prev_Q_bwe_exc = 31; + move16(); + } + + test(); + IF( EQ_16(bandwidth, WB)) + { + wb_tbe_extras_reset_fx( st_fx->mem_genSHBexc_filt_down_wb2_fx, st_fx->mem_genSHBexc_filt_down_wb3_fx ); + wb_tbe_extras_reset_synth_fx( st_fx->state_lsyn_filt_shb_fx, st_fx->state_lsyn_filt_dwn_shb_fx, st_fx->state_32and48k_WB_upsample_fx, st_fx->mem_resamp_HB_fx ); + + set16_fx( st_fx->mem_genSHBexc_filt_down_shb_fx, 0, 7 ); + set16_fx( st_fx->state_lpc_syn_fx, 0, 10 ); + set16_fx( st_fx->state_syn_shbexc_fx, 0, L_SHB_LAHEAD/4 ); + set16_fx( st_fx->syn_overlap_fx, 0, L_SHB_LAHEAD ); + set32_fx( st_fx->mem_csfilt_fx, 0, 2 ); + } + ELSE IF( EQ_16(bandwidth, SWB)||EQ_16(bandwidth,FB)) + { + swb_tbe_reset_fx( st_fx->mem_csfilt_fx, st_fx->mem_genSHBexc_filt_down_shb_fx, st_fx->state_lpc_syn_fx, + st_fx->syn_overlap_fx, st_fx->state_syn_shbexc_fx, &(st_fx->tbe_demph_fx), + &(st_fx->tbe_premph_fx), st_fx->mem_stp_swb_fx, &(st_fx->gain_prec_swb_fx) ); + + swb_tbe_reset_synth_fx( st_fx->genSHBsynth_Hilbert_Mem_fx, st_fx->genSHBsynth_state_lsyn_filt_shb_local_fx ); + + set16_fx( st_fx->GainShape_Delay, 0, NUM_SHB_SUBFR/2 ); + set16_fx( st_fx->int_3_over_2_tbemem_dec_fx, 0, INTERP_3_2_MEM_LEN); + set16_fx( st_fx->mem_resamp_HB_32k_fx, 0, 2*ALLPASSSECTIONS_STEEP+1 ); + + IF( EQ_16(bandwidth, FB)) + { + st_fx->prev_fb_ener_adjust_fx = 0; + set16_fx( st_fx->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + st_fx->fb_tbe_demph_fx = 0; + fb_tbe_reset_synth_fx( st_fx->fbbwe_hpf_mem_fx, st_fx->fbbwe_hpf_mem_fx_Q,&st_fx->prev_fbbwe_ratio_fx ); + } + } + + return; +} diff --git a/lib_dec/syn_outp_fx.c b/lib_dec/syn_outp_fx.c new file mode 100644 index 0000000..c26b00e --- /dev/null +++ b/lib_dec/syn_outp_fx.c @@ -0,0 +1,116 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Debug prototypes */ +#include "stl.h" /* required for wmc_tool */ + +/*-------------------------------------------------------------------* + * syn_output() + * + * Output synthesis signal with compensation for saturation + *-------------------------------------------------------------------*/ + +void syn_output_fx( + const Word16 codec_mode, /* i : MODE1 or MODE2 */ + Word16 *synth, /* i/o: float synthesis signal */ + const Word16 output_frame, /* i : output frame length */ + Word16 *synth_out, /* o : integer 16 bits synthesis signal */ + const Word16 Q_syn2 /* i : Synthesis scaling factor */ +) +{ + Word16 i, tmp; + Word32 L_tmp; + + /*tmp = sub(Q_syn2, 1); */ + tmp = Q_syn2; + + /*-----------------------------------------------------------------* + * Output synthesis signal with compensation for saturation + *-----------------------------------------------------------------*/ + + test(); + IF( codec_mode == MODE2 || EQ_16(output_frame,L_FRAME8k)) + { + /* integer conversion */ + /*mvr2s( synth, synth_out, output_frame ); */ + FOR (i = 0; i < output_frame; i++) + { + L_tmp = L_deposit_h(synth[i]); + synth_out[i] = round_fx(L_shr(L_tmp, tmp)); + } + } + ELSE + { + Copy_Scale_sig( synth, synth_out, output_frame, negate(tmp) ); + } + + return; +} +/*-------------------------------------------------------------------* + * Local function + * unscale_AGC + * + * Output synthesis signal with compensation for saturation + *-------------------------------------------------------------------*/ +void unscale_AGC( + const Word16 x[], /* i: 16kHz synthesis Qx */ + const Word16 Qx, /* i: scale factor of x */ + Word16 y[], /* o: output vector Q0 */ + Word16 mem[], /* i/o: mem[2] should be init to [0,0] */ + const Word16 n /* i: vector size */ +) +{ + Word16 i, fac, tmp, frame_fac, max; + Word32 L_tmp; + + /*----------------------------------------------------------------* + * calculate AGC factor to avoid saturation + *----------------------------------------------------------------*/ + + max = abs_s(x[0]); + FOR (i = 1; i < n; i++) + { + max = s_max(max, abs_s(x[i])); + } + BASOP_SATURATE_WARNING_OFF + tmp = shl(30000, Qx); /* saturation can occurs here */ + BASOP_SATURATE_WARNING_ON + frame_fac = 0; + move16(); + IF (GT_16(max, tmp)) + { + frame_fac = sub(16384, div_s(shr(tmp, 1), max)); /* frame fac in Q15 */ + } + + /*----------------------------------------------------------------* + * AGC + *----------------------------------------------------------------*/ + /* update AGC factor (slowly) */ + fac = mac_r(L_mult(32440, mem[0]), 328, frame_fac); + + L_tmp = L_mult(x[0], 16384); + L_tmp = L_msu0(L_tmp, fac, x[0]); + L_tmp = L_msu(L_tmp, fac, mem[1]); + L_tmp = L_shr(L_tmp, -1); /* saturation can occur here */ + + y[0] = round_fx(L_tmp); + + FOR (i = 1; i < n; i++) + { + /* update AGC factor (slowly) */ + fac = mac_r(L_mult(32440, fac), 328, frame_fac); + + L_tmp = L_deposit_h(x[i]); + L_tmp = L_msu(L_tmp, fac, x[i]); + L_tmp = L_msu(L_tmp, fac, x[i-1]); + y[i] = round_fx(L_tmp); + } + + mem[0] = fac; + move16(); + mem[1] = shr(x[sub(i, 1)], 1); + move16(); +} diff --git a/lib_dec/tcq_core_dec_fx.c b/lib_dec/tcq_core_dec_fx.c new file mode 100644 index 0000000..68f4dbb --- /dev/null +++ b/lib_dec/tcq_core_dec_fx.c @@ -0,0 +1,475 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ + +#include "prot_fx.h" +#include "stl.h" /* required for wmc_tool */ + +void tcq_core_LR_dec_fx( + Decoder_State_fx *st_fx, + Word16 *inp_vector_fx, /* x5 */ + const Word16 bit_budget, + const Word16 BANDS, + const Word16 *band_start, + const Word16 *band_width, + Word32 *Rk_fx, /* Q16 */ + Word16 *npulses, + Word16 *k_sort, + const Word16 *p2a_flags, + const Word16 p2a_bands, + const Word16 *last_bitalloc, + const Word16 input_frame, + const Word16 adjustFlag, + const Word16 *is_transient +) +{ + Word16 i, j, k; + Word32 Rk_sort_fx[NB_SFM]; + Word16 flag_wbnb = 0; + Word16 USQ_TCQ[NB_SFM]; /* TCQ is selected by default*/ + Word16 nb_bytes, pulsesnum, nz; + + Word16 positions_fx[L_FRAME48k]; + Word32 surplus_fx, delta_fx; + Word16 k_num[2]; + Word32 bit_surplus_fx[2]; + ARCODEC_FX ardec_fx, *pardec_fx; + BITSTREAM_FX bs_fx, *pbs_fx; + + Word16 nzb = 0; + Word16 nzbands = 0; + Word16 lsbtcq_bits = TCQ_AMP; + Word16 tcq_arbits = 2; + + /* LSB TCQ variables*/ + Word16 dpath[280]; + Word16 bcount = 0; + Word32 bsub_fx = 0; + Word16 mbuffer_fx[560]; + + Word32 leftbits = 0; + Word32 sepbits = 0; + Word32 divider = 0; + + if (Overflow == 1) + { + Overflow = 0; /* set overflow flag to zero before entering TCQ finctions without any message */ + } + + /* initialization */ + set16_fx(dpath, 0, 280); + set16_fx( USQ_TCQ, 0, NB_SFM ); + set16_fx(positions_fx, 0, L_FRAME32k); + set16_fx(mbuffer_fx, 0, 560); + + test(); + test(); + IF ( LE_16(input_frame, L_FRAME16k)&&adjustFlag==0&&*is_transient==0) + { + flag_wbnb = 1; + move16(); + lsbtcq_bits = 0; + move16(); + tcq_arbits = 0; + move16(); + } + + pardec_fx = &ardec_fx; + pbs_fx = &bs_fx; + pbs_fx->curPos = 7; + move16(); + pbs_fx->numbits = L_deposit_l(0); + pbs_fx->numByte = L_deposit_l(0); + + /* Bits distribution analysis*/ + FOR ( i = 0; i < BANDS; i++ ) + { + IF (GE_32(ar_div(Rk_fx[i], band_width[i]), 49152)) + { + /* USQ used for high importance bands*/ + USQ_TCQ[i] = 1; + move16(); + } + ELSE + { + /* TCQ used for usual bands*/ + USQ_TCQ[i] = 0; + move16(); + } + if ( Rk_fx[i] > 0 ) + { + nzbands = add(nzbands, 1); + } + } + + FOR ( j = 0; j < BANDS; j++ ) + { + if ( Rk_fx[j] > 0 ) + { + nzb = add(nzb, 1); + } + } + + bsub_fx = L_shl(L_add(tcq_arbits, lsbtcq_bits), 16); + if( bsub_fx > 0) + { + bsub_fx = L_add( bsub_fx, 2048); + } + FOR ( j = BANDS - 1; j >= 0; j-- ) + { + IF ( Rk_fx[j] > 0 ) + { + Rk_fx[j] = L_sub(Rk_fx[j], ar_div(bsub_fx, nzb)); + IF ( Rk_fx[j] < 0) + { + bsub_fx = L_sub(bsub_fx, L_add(ar_div(bsub_fx, nzb), Rk_fx[j])); + Rk_fx[j] = L_deposit_l(0); + } + ELSE + { + bsub_fx = L_sub(bsub_fx, ar_div(bsub_fx, nzb)); + } + nzb = sub(nzb, 1); + } + } + + srt_vec_ind_fx(Rk_fx, Rk_sort_fx, k_sort, BANDS); + + /*read the bits*/ + nb_bytes = shr(bit_budget, 3); + k = sub(bit_budget, shl(nb_bytes, 3)); + FOR ( i = 0; i < nb_bytes; i++ ) + { + pbs_fx->buf[i] = (UWord8)get_next_indice_fx(st_fx, 8); + move16(); + } + + IF ( k > 0 ) + { + Word16 tmp; + tmp = (UWord8)get_next_indice_fx(st_fx, k); + pbs_fx->buf[nb_bytes] = (UWord8)shl(tmp,sub(8,k)); + /* i++; + nb_bytes++; */ + i = add(i, 1); + nb_bytes = add(nb_bytes, 1); + } + /* set two more bytes, which are used to flush the arithmetic coder, to 0 + -> this avoids reading of uninitialized memory */ + nb_bytes = s_min(add(nb_bytes, 2), MAX_SIZEBUF_PBITSTREAM); + FOR ( ; i < nb_bytes; i++ ) + { + pbs_fx->buf[i] = 0; + move16(); + } + + pbs_fx->maxBytes = nb_bytes; + move16(); + + ar_decoder_start_fx(pardec_fx, pbs_fx); + + delta_fx = L_deposit_l(0); + surplus_fx = L_deposit_l(0); + + test(); + test(); + IF( LE_16(input_frame, L_FRAME16k)&&adjustFlag==0&&*is_transient==0) + { + surplus_fx = -131072; + move32();/*16 */ + + bit_allocation_second_fx(Rk_fx, Rk_sort_fx, BANDS, band_width, k_sort, k_num, p2a_flags, p2a_bands, last_bitalloc, input_frame); + + nzbands = 0; + move16(); + FOR ( j = 0; j < BANDS; j++ ) + { + IF( EQ_16(j, k_num[0])||EQ_16(j,k_num[1])) + { + sepbits = L_add( sepbits, Rk_fx[k_sort[j]]); + } + ELSE + { + leftbits = L_add( leftbits, Rk_fx[k_sort[j]]); + if( Rk_fx[k_sort[j]] > 0 ) + { + nzbands = add(nzbands, 1); + } + } + } + + FOR( k = 0; k < BANDS; k++ ) + { + test(); + IF( NE_16(k, k_num[0])&&NE_16(k,k_num[1])) + { + test(); + test(); + IF (Rk_fx[k_sort[k]] > 0 && USQ_TCQ[k_sort[k]] == 0) + { + /* When number of bits per band is less than + arithmetic bits overhead, this band is not encoded. + It may happens when the actual number of bits per + band is near same to estimated number of bits, for + most bands (very unprobable but possible) */ + IF( L_add( Rk_fx[k_sort[k]], delta_fx) < 0 ) + { + pulsesnum = 0; + move16(); + FOR( i = 0; i < band_width[k_sort[k]]; i++ ) + { + inp_vector_fx[band_start[k_sort[k]] + i] = 0; + move16(); + } + IF( surplus_fx != 0 ) + { + /* surplus_fx += (Rk[k_sort[k]] + delta);*/ + surplus_fx = L_add( Rk_fx[k_sort[k]], surplus_fx); + surplus_fx = L_add( delta_fx, surplus_fx); + } + } + ELSE + { + /*get number of pulses */ + pulsesnum = GetScale_fx( band_width[k_sort[k]], + L_add( Rk_fx[k_sort[k]], delta_fx), + &surplus_fx ); + leftbits = L_sub( leftbits, L_add( Rk_fx[k_sort[k]], delta_fx) ); + decode_position_ari_fx( pardec_fx, band_width[k_sort[k]], pulsesnum, &nz, &positions_fx[band_start[k_sort[k]]] ); + /*decode tcq magniitude and update the surplus bits.*/ + decode_mangitude_tcq_fx( pardec_fx, band_width[k_sort[k]], pulsesnum, nz, &positions_fx[band_start[k_sort[k]]], &inp_vector_fx[band_start[k_sort[k]]], &surplus_fx ); + decode_signs_fx( pardec_fx, band_width[k_sort[k]], &inp_vector_fx[band_start[k_sort[k]]] ); + } + nzbands--; + move16(); + } + ELSE IF (Rk_fx[k_sort[k]] > 0 && EQ_16(USQ_TCQ[k_sort[k]], 1)) + { + /* When number of bits per band is less than + arithmetic bits overhead, this band is not encoded. + It may happens when the actual number of bits per + band is near same to estimated number of bits, for + most bands (very unprobable but possible) */ + IF( L_add( Rk_fx[k_sort[k]], delta_fx) < 0 ) + { + pulsesnum = 0; + move16(); + FOR( i = 0; i < band_width[k_sort[k]]; i++ ) + { + inp_vector_fx[band_start[k_sort[k]] + i] = 0; + move16(); + } + IF( surplus_fx != 0 ) + { + surplus_fx = L_add( Rk_fx[k_sort[k]], surplus_fx); + surplus_fx = L_add( delta_fx, surplus_fx); + } + } + ELSE + { + pulsesnum = GetScale_fx(band_width[k_sort[k]], + L_add( Rk_fx[k_sort[k]], delta_fx), + &surplus_fx); + leftbits = L_sub( leftbits, L_add( Rk_fx[k_sort[k]], delta_fx) ); + decode_position_ari_fx( pardec_fx, band_width[k_sort[k]], pulsesnum, &nz, &positions_fx[band_start[k_sort[k]]] ); + /*decode usq magnitude and don't need to update surplus bits*/ + decode_magnitude_usq_fx( pardec_fx, band_width[k_sort[k]], pulsesnum, nz, &positions_fx[band_start[k_sort[k]]], &inp_vector_fx[band_start[k_sort[k]]] ); + decode_signs_fx( pardec_fx, band_width[k_sort[k]], &inp_vector_fx[band_start[k_sort[k]]] ); + } + nzbands--; + move16(); + } + ELSE + { + pulsesnum = 0; + move16(); + FOR ( i = 0; i < band_width[k_sort[k]]; i++ ) + { + inp_vector_fx[band_start[k_sort[k]] + i] = 0; + move16(); + } + } + + npulses[k_sort[k]] = pulsesnum; + move16(); + + delta_fx = L_deposit_l(0); + test(); + IF( Rk_fx[k_sort[k]] > 0 && surplus_fx < 0 ) + { + IF( nzbands <= 1 ) + { + divider = 0; + } + ELSE + { + divider = 2; + } + + IF( L_add( L_add( surplus_fx, sepbits), ar_div( leftbits, divider ) ) < 0 ) + { + /* Overflow possible => start to distribute negative surplus */ + delta_fx = ar_div( surplus_fx + sepbits, nzbands); + } + else + { + delta_fx = 0; + } + surplus_fx = L_sub(surplus_fx, delta_fx); + + } + } + } + + test(); + test(); + test(); + IF (( GT_32(surplus_fx,524288)&&EQ_16(input_frame,L_FRAME8k))||(GT_32(surplus_fx,786432)&&EQ_16(input_frame,L_FRAME16k))) + { + bit_surplus_fx[0] = Mult_32_16(surplus_fx,24576);/* Q16 */ + bit_surplus_fx[1] = Mult_32_16(surplus_fx,8192);/* Q16 */ + } + ELSE + { + bit_surplus_fx[0] = surplus_fx; + move32(); + bit_surplus_fx[1] = L_deposit_l(0); + } + + FOR ( k = 0; k < BANDS; k++ ) + { + FOR ( j = 0; j < 2; j++ ) + { + IF ( EQ_16(k, k_num[j])) + { + Rk_fx[k_sort[k]] = L_add(Rk_fx[k_sort[k]],bit_surplus_fx[j]); + move32(); + + test(); + test(); + IF ( Rk_fx[k_sort[k]] > 0 && USQ_TCQ[k_sort[k]] == 0 ) + { + /* get number of pulses */ + pulsesnum = GetScale_fx( band_width[k_sort[k]], Rk_fx[k_sort[k]], &surplus_fx ); + + decode_position_ari_fx( pardec_fx, band_width[k_sort[k]], pulsesnum, &nz, &positions_fx[band_start[k_sort[k]]] ); + /* decode tcq magniitude and update the surplus bits. */ + decode_mangitude_tcq_fx( pardec_fx, band_width[k_sort[k]], pulsesnum, nz, &positions_fx[band_start[k_sort[k]]], &inp_vector_fx[band_start[k_sort[k]]], &surplus_fx ); + decode_signs_fx( pardec_fx, band_width[k_sort[k]], &inp_vector_fx[band_start[k_sort[k]]] ); + } + ELSE IF( Rk_fx[k_sort[k]] > 0 && USQ_TCQ[k_sort[k]] == 1 ) + { + pulsesnum = GetScale_fx( band_width[k_sort[k]], Rk_fx[k_sort[k]], &surplus_fx ); + + decode_position_ari_fx( pardec_fx, band_width[k_sort[k]], pulsesnum, &nz, &positions_fx[band_start[k_sort[k]]] ); + /* decode usq magnitude and don't need to update surplus bits */ + decode_magnitude_usq_fx( pardec_fx, band_width[k_sort[k]], pulsesnum, nz, &positions_fx[band_start[k_sort[k]]], &inp_vector_fx[band_start[k_sort[k]]] ); + decode_signs_fx( pardec_fx, band_width[k_sort[k]], &inp_vector_fx[band_start[k_sort[k]]] ); + } + ELSE + { + pulsesnum = 0; + move16(); + FOR ( i = 0; i < band_width[k_sort[k]]; i++ ) + { + inp_vector_fx[band_start[k_sort[k]] + i] = 0; + move16(); + } + } + + npulses[k_sort[k]] = pulsesnum; + move16(); + } + } + } + } + ELSE + { + FOR ( k = 0; k < BANDS; k++ ) + { + IF ( Rk_fx[k_sort[k]] > 0 ) + { + pulsesnum = GetScale_fx(band_width[k_sort[k]], Rk_fx[k_sort[k]] + delta_fx, &surplus_fx); + + decode_position_ari_fx( pardec_fx, band_width[k_sort[k]], pulsesnum, &nz, &positions_fx[band_start[k_sort[k]]] ); + + /*decode usq magnitude and don't need to update surplus bits*/ + decode_magnitude_usq_fx( pardec_fx, band_width[k_sort[k]], pulsesnum, nz, &positions_fx[band_start[k_sort[k]]], &inp_vector_fx[band_start[k_sort[k]]] ); + decode_signs_fx( pardec_fx, band_width[k_sort[k]], &inp_vector_fx[band_start[k_sort[k]]] ); + + nzbands = sub(nzbands, 1); + } + ELSE + { + pulsesnum = 0; + move16(); + FOR ( i = 0; i < band_width[k_sort[k]]; i++ ) + { + inp_vector_fx[band_start[k_sort[k]] + i] = 0; + move16(); + } + } + + npulses[k_sort[k]] = pulsesnum; + move16(); + + /* surplus distribution */ + test(); + IF ( surplus_fx > 0 && nzbands > 0 ) + { + delta_fx = ar_div(surplus_fx, nzbands); + surplus_fx = L_sub(surplus_fx, delta_fx); + } + } + } + + /* Load TCQ path from bitstream */ + LoadTCQdata_fx(pardec_fx, dpath, lsbtcq_bits); + + TCQLSBdec_fx(dpath, mbuffer_fx, 2*lsbtcq_bits); + + ar_decoder_done_fx(pardec_fx); + + /* Restore TCQ */ + IF ( !flag_wbnb ) + { + FOR ( k = 0; k < BANDS; k++) + { + IF ( Rk_fx[k_sort[k]] > 0 ) + { + RestoreTCQdec_fx( &inp_vector_fx[ band_start[ k_sort[ k]]], band_width[k_sort[k]], &bcount, mbuffer_fx ); + } + } + } + ELSE + { + FOR( k = 0; k < BANDS; k++) + { + test(); + test(); + IF( Rk_fx[k_sort[k]] > 0 && k != k_num[0] && k != k_num[1] ) + { + RestoreTCQdec_fx( &inp_vector_fx[ band_start[ k_sort[ k]]], band_width[k_sort[k]], &bcount, mbuffer_fx ); + } + } + + FOR ( k = 0; k < BANDS; k++) + { + test(); + test(); + IF ( Rk_fx[k_sort[k]] > 0 && (k == k_num[0] || k == k_num[1]) ) + { + RestoreTCQdec_fx( &inp_vector_fx[ band_start[ k_sort[ k]]], band_width[k_sort[k]], &bcount, mbuffer_fx ); + } + } + } + + + + return; +} diff --git a/lib_dec/tcx_utils_dec.c b/lib_dec/tcx_utils_dec.c new file mode 100644 index 0000000..91cc01d --- /dev/null +++ b/lib_dec/tcx_utils_dec.c @@ -0,0 +1,343 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include +#include "stl.h" +#include "options.h" +#include "prot_fx.h" +#include "rom_basop_util.h" +#include "basop_util.h" +#include "rom_com_fx.h" + +void tcx_decoder_memory_update( + Word16 *xn_buf, /* i/o: mdct output buffer used also as temporary buffer */ + Word16 *synthout, /* o: synth */ + Word16 L_frame_glob, /* i: global frame length */ + Word16 *A, /* i: Quantized LPC coefficients */ + Decoder_State_fx *st, + Word16 *syn, /* o: st->syn */ + Word8 fb /* i: fullband flag */ +) +{ + Word16 tmp; + Word16 *synth; + Word16 buf[1+M+LFAC+L_FRAME_PLUS]; + Word16 preemph; + + + preemph = st->preemph_fac; + move16(); + + /* Output synth */ + Copy(xn_buf, synthout, L_frame_glob); + + /* Update synth */ + + synth = buf + M+1; + Copy(syn, buf, M+1); + Copy(xn_buf, synth, L_frame_glob); + Copy(synth + sub(L_frame_glob, M+1), syn, M+1); + + + IF (!fb) + { + + /* Emphasis of synth -> synth_pe */ + tmp = synth[-M-1]; + move16(); + st->Q_syn = E_UTIL_f_preemph3(synth - M, preemph, add(M, L_frame_glob), &tmp, 1); + st->prev_Q_syn = st->Q_syn = st->Q_syn - 1; + Copy(synth + sub(L_frame_glob, M), st->mem_syn2_fx, M); + Copy(synth + sub(L_frame_glob, L_SYN_MEM), st->mem_syn_r, L_SYN_MEM); + + test(); + IF ( st->tcxonly == 0 || LE_16(L_frame_glob,L_FRAME16k)) + { + /* Update excitation */ + IF(NE_16(st->Q_syn+1,st->Q_exc)) + { + Scale_sig(st->old_exc_fx, L_EXC_MEM_DEC, sub(st->Q_syn+1,st->Q_exc)); + } + st->Q_exc = st->Q_syn + 1; + st->Q_subfr[0] = st->Q_subfr[1] = st->Q_subfr[2] = st->Q_subfr[3] = st->Q_subfr[4] = st->Q_exc; + + assert(L_frame_glob< L_EXC_MEM_DEC); + Copy( st->old_exc_fx + L_frame_glob, st->old_exc_fx, sub(L_EXC_MEM_DEC, L_frame_glob) ); + Residu3_fx(A, synth, st->old_exc_fx + sub(L_EXC_MEM_DEC, L_frame_glob), L_frame_glob, 1); + } + + /* Update old_Aq */ + Copy(A, st->old_Aq_12_8_fx, M+1); + } + +} + +/* Returns: number of bits used (including "bits") */ +Word16 tcx_ari_res_invQ_spec( + Word32 x_Q[], /* i/o: quantized spectrum Q31-e */ + Word16 x_Q_e, /* i: quantized spectrum exponent Q0 */ + Word16 L_frame, /* i: number of lines Q0 */ + const Word16 prm[], /* i: bit-stream Q0 */ + Word16 target_bits, /* i: number of bits available Q0 */ + Word16 bits, /* i: number of bits used so far Q0 */ + Word16 deadzone, /* i: quantizer deadzone Q15 */ + const Word16 x_fac[] /* i: spectrum post-quantization factors Q14 */ +) +{ + Word16 i, j, num_zeros; + Word16 zeros[L_FRAME_PLUS]; + Word16 fac_p, sign; + Word32 L_tmp; + Word16 s; + + + /* Limit the number of residual bits */ + target_bits = s_min(target_bits, NPRM_RESQ); + + + /* Requantize the spectrum line-by-line */ + /* fac_m = deadzone * 0.5f; */ + num_zeros = 0; + move16(); + + FOR (i=0; i < L_frame; i++) + { + IF (GE_16(bits, target_bits)) /* no bits left */ + { + BREAK; + } + + IF (x_Q[i] != 0) + { + sign = x_fac[i]; + move16(); + if (x_Q[i] < 0) sign = negate(sign); + + /* x_Q[i] += sign*(prm[bits++] * 0.5f - fac_m); */ + x_Q[i] = L_sub(x_Q[i], L_shr(L_mult(sign, add(deadzone, lshl(prm[bits], 15))), x_Q_e)); + move32(); + bits = add(bits, 1); + } + ELSE + { + zeros[num_zeros] = i; + move16(); + num_zeros = add(num_zeros, 1); + } + } + + /* Requantize zeroed-lines of the spectrum */ + fac_p = msu_r(1417339264l/*0.33f*2.0f Q31*/, deadzone, 21627/*0.33f*2.0f Q15*/); /* Q15 */ + target_bits = sub(target_bits, 1); /* reserve 1 bit for the check below */ + + s = sub(x_Q_e, 1); + FOR (j = 0; j < num_zeros; j++) + { + IF (GE_16(bits, target_bits)) /* 1 or 0 bits left */ + { + BREAK; + } + + i = zeros[j]; + move16(); + + IF (prm[bits] != 0) + { + bits = add(bits, 1); + L_tmp = L_mult(fac_p, x_fac[i]); /* Q30 */ + if (prm[bits] == 0) L_tmp = L_negate(L_tmp); + x_Q[i] = L_shr(L_tmp, s); + move32(); + } + bits = add(bits, 1); + } + + + return bits; +} + +Word16 tcx_res_invQ_gain( + Word16 *gain_tcx, + Word16 *gain_tcx_e, + Word16 *prm, + Word16 resQBits +) +{ + Word16 bits; + Word16 gain, tmp1, tmp2; + + + gain = *gain_tcx; + move16(); + + /* make sure we have a bit of headroom */ + IF (GT_16(gain, 0x7000)) + { + gain = shr(gain, 1); + *gain_tcx_e = add(*gain_tcx_e, 1); + move16(); + } + + /*Refine the gain quantization*/ + tmp1 = s_min(resQBits, TCX_RES_Q_BITS_GAIN); + FOR (bits=0; bits < tmp1; bits++) + { + tmp2 = gain_corr_fac[bits]; + move16(); + if (prm[bits] == 0) + { + tmp2 = gain_corr_inv_fac[bits]; + move16(); + } + + gain = mult_r(gain, tmp2); + if (prm[bits] != 0) gain = shl(gain, 1); + } + + *gain_tcx = gain; + move16(); + + + return bits; +} + +Word16 tcx_res_invQ_spec( + Word32 *x, + Word16 x_e, + Word16 L_frame, + Word16 *prm, + Word16 resQBits, + Word16 bits, + Word16 sq_round, + const Word16 lf_deemph_factors[] +) +{ + Word16 i; + Word16 fac_m, fac_p; + Word16 lf_deemph_factor, c, s; + Word32 tmp; + + + /* Limit the number of residual bits */ + resQBits = s_min(resQBits, NPRM_RESQ); + + /* Requantize the spectrum line-by-line */ + fac_m = shr(sq_round, 1); + fac_p = sub(0x4000, fac_m); + + lf_deemph_factor = 0x4000; + move16(); + s = sub(x_e, 1); + + FOR (i = 0; i < L_frame; i++) + { + IF (GE_16(bits, resQBits)) + { + BREAK; + } + + test(); + test(); + IF ((x[i] != 0) && ((lf_deemph_factors == NULL) || (GT_16(lf_deemph_factors[i], 0x2000)))) + { + if (lf_deemph_factors != NULL) + { + lf_deemph_factor = lf_deemph_factors[i]; + move16(); + } + + IF (prm[bits] == 0) + { + + /* Debug initialization to catch illegal cases of x[i] */ + tmp = 0; + + if (x[i] > 0) tmp = L_mult(fac_m, lf_deemph_factor); + if (x[i] < 0) tmp = L_mult(fac_p, lf_deemph_factor); + + assert(tmp != 0); + + x[i] = L_sub(x[i], L_shr(tmp, s)); + move32(); + } + ELSE + { + + /* Debug initialization to catch illegal cases of x[i] */ + tmp = 0; + + if (x[i] > 0) tmp = L_mult(fac_p, lf_deemph_factor); + if (x[i] < 0) tmp = L_mult(fac_m, lf_deemph_factor); + + assert(tmp != 0); + + x[i] = L_add(x[i], L_shr(tmp, s)); + move32(); + } + bits = add(bits, 1); + } + } + + /*Quantize zeroed-line of the spectrum*/ + resQBits = sub(resQBits, 1); + + IF (lf_deemph_factors == NULL) + { + FOR (i = 0; i < L_frame; i++) + { + IF (GE_16(bits, resQBits)) + { + BREAK; + } + + IF (x[i] == 0) + { + IF (prm[bits] != 0) + { + bits = add(bits, 1); + + tmp = L_mult(21627/*1.32f Q14*/, fac_p); + if (prm[bits] == 0) tmp = L_negate(tmp); + + x[i] = L_shr(tmp, s); + move32(); + } + bits = add(bits, 1); + } + } + } + ELSE + { + c = sub(21627/*0.66f Q15*/, mult_r(sq_round, 21627/*0.66f Q15*/)); + + FOR (i = 0; i < L_frame; i++) + { + IF (GE_16(bits, resQBits)) + { + BREAK; + } + + test(); + IF ((x[i] == 0) && (GT_16(lf_deemph_factors[i], 0x2000))) + { + IF (prm[bits] != 0) + { + bits = add(bits, 1); + + tmp = L_mult(c, lf_deemph_factors[i]); + if (prm[bits] == 0) tmp = L_negate(tmp); + + x[i] = L_shr(tmp, s); + move32(); + } + bits = add(bits, 1); + } + } + } + + return bits; +} diff --git a/lib_dec/tns_base_dec.c b/lib_dec/tns_base_dec.c new file mode 100644 index 0000000..96ae4c0 --- /dev/null +++ b/lib_dec/tns_base_dec.c @@ -0,0 +1,94 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include "stl.h" +#include "prot_fx.h" +#include "stl.h" +#include +#include +#include "rom_com_fx.h" + +/** Linear prediction analysis/synthesis filter definition. + * @param order filter order. + * @param parCoeff filter (PARCOR) coefficients. + * @param state state of the filter. Must be at least of 'order' size. + * @param x the current input value. + * @return the output of the filter. + */ +typedef Word32 (* TLinearPredictionFilter)(Word16 order, Word16 const parCoeff[], Word32 * state, Word32 x); + +/********************************/ +/* Interface functions */ +/********************************/ + +Word16 ReadTnsData(STnsConfig const * pTnsConfig, Decoder_State_fx *st, Word16 * pnBits, Word16 * stream, Word16 * pnSize) +{ + Word16 start_bit_pos; + + + move16(); + start_bit_pos = st->next_bit_pos_fx; + + IF ( GT_16(pTnsConfig->nMaxFilters, 1)) + { + + IF ( LT_16(pTnsConfig->iFilterBorders[0],512)) + { + ReadFromBitstream(tnsEnabledSWBTCX10BitMap, 1, st, &stream, pnSize); + } + ELSE + { + ReadFromBitstream(tnsEnabledSWBTCX20BitMap, 1, st, &stream, pnSize); + } + } + ELSE + { + ReadFromBitstream(tnsEnabledWBTCX20BitMap, 1, st, &stream, pnSize); + } + + move16(); + *pnBits = sub(st->next_bit_pos_fx, start_bit_pos); + + + return TNS_NO_ERROR; +} + +Word16 DecodeTnsData(STnsConfig const * pTnsConfig, Word16 const * stream, Word16 * pnSize, STnsData * pTnsData) +{ + Word16 result; + + + + ResetTnsData(pTnsData); + + IF ( GT_16(pTnsConfig->nMaxFilters, 1)) + { + + IF ( LT_16(pTnsConfig->iFilterBorders[0],512)) + { + SetParameters(tnsEnabledSWBTCX10BitMap, 1, pTnsData, &stream, pnSize); + } + ELSE + { + SetParameters(tnsEnabledSWBTCX20BitMap, 1, pTnsData, &stream, pnSize); + } + } + ELSE + { + SetParameters(tnsEnabledWBTCX20BitMap, 1, pTnsData, &stream, pnSize); + } + + move16(); + result = FALSE; + if (pTnsData->nFilters > 0) + { + move16(); + result = TRUE; + } + + + return result; +} + diff --git a/lib_dec/tonalMDCTconcealment.c b/lib_dec/tonalMDCTconcealment.c new file mode 100644 index 0000000..54454d4 --- /dev/null +++ b/lib_dec/tonalMDCTconcealment.c @@ -0,0 +1,1246 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#define _USE_MATH_DEFINES + +#include +#include "stl.h" +#include "basop_util.h" +#include "options.h" +#include "typedef.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include "stat_com.h" + + +/************************************************************************************/ +/* forward declarations for local functions, see implementation at end of this file */ +/************************************************************************************/ + +static void CalcMDXT(TonalMDCTConcealPtr const self, + Word16 const type, + Word16 const * const timeSignal, + Word32 * const mdxtOutput, + Word16 * const mdxtOutput_e); + +static void CalcPowerSpec(Word32 * mdctSpec, /* i: MDCT spectrum */ + Word16 mdctSpec_exp, /* i: exponent of MDCT spectrum */ + Word32 * mdstSpec, /* i: MDST spectrum */ + Word16 mdstSpec_exp, /* i: exponent of MDST spectrum */ + Word16 nSamples, /* i: frame size */ + Word16 floorPowerSpectrum, /* i: lower limit for power spectrum bins */ + Word32 * powerSpec, /* o: power spectrum */ + Word16 * powerSpec_exp); + +static void CalcPowerSpecAndDetectTonalComponents(TonalMDCTConcealPtr const self, + Word32 secondLastMDST[], + Word16 secondLastMDST_exp, + Word32 secondLastMDCT[], + Word16 secondLastMDCT_exp, + Word32 const pitchLag); +static void FindPhases( /* o: current phase [-pi;pi] 2Q13 */ + TonalMDCTConcealPtr const self, /* i: pointer to internal structure */ + Word32 secondLastMDCT[], /* i: MDST spectrum data */ + Word32 secondLastMDST[], /* i: MDCT spectrum data */ + Word16 diff_exp); /* i: exp_MDST - exp_MDCT */ + +static void FindPhaseDifferences( /* o: Phase difference [-pi;pi] 2Q13*/ + TonalMDCTConcealPtr const self, /* i: Pointer to internal structure */ + Word32 powerSpectrum[]); /* i: Power spectrum data */ + + +/*******************************************************/ +/*-------------- public functions -------------------- */ +/*******************************************************/ + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_Init( TonalMDCTConcealPtr self, + Word16 nSamples, + Word16 nSamplesCore, + Word16 nScaleFactors, + TCX_config * tcx_cfg + ) +{ + test(); + IF (GT_16(nSamples,L_FRAME_MAX)||GT_16(nScaleFactors,FDNS_NPTS)) + { + assert(nSamples <= L_FRAME_MAX); + assert(nScaleFactors <= FDNS_NPTS); + return TONALMDCTCONCEAL_NSAMPLES_LARGER_THAN_MAXBLOCKSIZE; + } + assert((self->nScaleFactors == nScaleFactors) || (self->nSamples != nSamples)); /* If nSamples doesn't change then also nScaleFactors must stay the same */ + + self->tcx_cfg = tcx_cfg; + + self->lastBlockData.spectralData = self->spectralDataBuffers[0]; + move16(); + self->secondLastBlockData.spectralData = self->spectralDataBuffers[1]; + move16(); + self->secondLastPowerSpectrum = self->secondLastBlockData.spectralData; + move16(); + + self->lastBlockData.scaleFactors = self->scaleFactorsBuffers[0]; + move16(); + self->secondLastBlockData.scaleFactors = self->scaleFactorsBuffers[1]; + move16(); + self->lastBlockData.scaleFactors_exp = self->scaleFactorsBuffers_exp[0]; + move16(); + self->secondLastBlockData.scaleFactors_exp = self->scaleFactorsBuffers_exp[1]; + move16(); + + self->lastBlockData.blockIsValid = 0; + move16(); + self->secondLastBlockData.blockIsValid = 0; + move16(); + self->nSamples = 0; + move16(); + self->nScaleFactors = 0; + move16(); + + self->lastBlockData.blockIsConcealed = 0; + move16(); + self->secondLastBlockData.blockIsConcealed = 0; + move16(); + + self->pTCI = (TonalComponentsInfo *)self->timeDataBuffer; + move16(); + + + self->lastPitchLag = L_deposit_l(0); + + IF (NE_16(self->nSamples,nSamples)) + { + self->secondLastBlockData.blockIsValid = 0; + move16(); + self->lastBlockData.blockIsValid = 0; + move16(); + } + + self->nSamples = nSamples; + move16(); + self->nSamplesCore = nSamplesCore; + move16(); + + self->nScaleFactors = nScaleFactors; + move16(); + + /* Offset the pointer to the end of buffer, so that pTCI is not destroyed when + new time samples are stored in lastPcmOut */ move16(); + move16(); + /* just the second half of the second last pcm output is needed */ + self->secondLastPcmOut = &self->timeDataBuffer[sub((3*L_FRAME_MAX)/2,3*(s_min(L_FRAME_MAX, nSamples))/2)]; + self->lastPcmOut = &self->timeDataBuffer[sub((3*L_FRAME_MAX)/2, s_min(L_FRAME_MAX, nSamples)) ]; + + /* If the second last frame was lost, we reuse saved TonalComponentsInfo and don't update pcm buffers */ + assert(sizeof(*self->pTCI) <= (self->lastPcmOut-self->timeDataBuffer)*sizeof(self->timeDataBuffer[0])); + + return TONALMDCTCONCEAL_OK; +} + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_SaveFreqSignal( TonalMDCTConcealPtr self, + Word32 const *mdctSpectrum, + Word16 const mdctSpectrum_exp, + Word16 nNewSamples, + Word16 nNewSamplesCore, + Word16 const *scaleFactors, + Word16 const *scaleFactors_exp, + Word16 const gain_tcx_exp + ) +{ + Word16 * temp; + Word16 nOldSamples, tmp_exp, s, i, max_exp; + + + assert(nNewSamples > 0 && nNewSamples <= 2*L_FRAME_MAX); + + /* Avoid overwriting self->secondLastPowerSpectrum stored in spectralData, + because it is needed if the second last and the current frame are lost + and concealed using the Tonal MDCT PLC */ test(); + IF (!self->lastBlockData.tonalConcealmentActive || NE_16(self->lastBlockData.nSamples,nNewSamples)) + { + IF (LE_16(nNewSamples,L_FRAME_MAX)) + { + /* Shift the buffers */ + temp = self->secondLastBlockData.spectralData; /* Save the pointer */ move16(); + self->secondLastBlockData.spectralData = self->lastBlockData.spectralData; + move16(); + self->lastBlockData.spectralData = temp; + move16(); + + tmp_exp = self->secondLastBlockData.spectralData_exp; /* Save the pointer */ move16(); + self->secondLastBlockData.spectralData_exp = self->lastBlockData.spectralData_exp; + move16(); + self->lastBlockData.spectralData_exp = tmp_exp; + move16(); + + tmp_exp = self->secondLastBlockData.gain_tcx_exp; /* Save the pointer */ move16(); + self->secondLastBlockData.gain_tcx_exp = self->lastBlockData.gain_tcx_exp; + move16(); + self->lastBlockData.gain_tcx_exp = tmp_exp; + move16(); + + tmp_exp = self->secondLastBlockData.scaleFactors_max_e; /* Save the pointer */ move16(); + self->secondLastBlockData.scaleFactors_max_e = self->lastBlockData.scaleFactors_max_e; + move16(); + self->lastBlockData.scaleFactors_max_e = tmp_exp; + move16(); + + temp = self->secondLastBlockData.scaleFactors; + move16(); + self->secondLastBlockData.scaleFactors = self->lastBlockData.scaleFactors; + move16(); + self->lastBlockData.scaleFactors = temp; + move16(); + + temp = self->secondLastBlockData.scaleFactors_exp; + move16(); + self->secondLastBlockData.scaleFactors_exp = self->lastBlockData.scaleFactors_exp; + move16(); + self->lastBlockData.scaleFactors_exp = temp; + move16(); + } + ELSE + { + self->lastBlockData.spectralData = self->spectralDataBuffers[0]; + move16(); + self->secondLastBlockData.spectralData = self->spectralDataBuffers[1]; + move16(); + self->lastBlockData.scaleFactors = self->scaleFactorsBuffers[0]; + move16(); + self->secondLastBlockData.scaleFactors = self->scaleFactorsBuffers[1]; + move16(); + self->lastBlockData.scaleFactors_exp = self->scaleFactorsBuffers_exp[0]; + move16(); + self->secondLastBlockData.scaleFactors_exp = self->scaleFactorsBuffers_exp[1]; + move16(); + } + + nOldSamples = self->lastBlockData.nSamples; + move16(); + self->lastBlockData.nSamples = nNewSamples; + move16(); + self->secondLastBlockData.nSamples = nOldSamples; + move16(); + + nOldSamples = self->lastBlockData.nSamplesCore; + move16(); + self->lastBlockData.nSamplesCore = nNewSamplesCore; + move16(); + self->secondLastBlockData.nSamplesCore = nOldSamples; + move16(); + } + + test(); + IF ((nNewSamples > 0) && (LE_16(nNewSamples,2*L_FRAME_MAX))) + { + /* Store new data */ + s = getScaleFactor32(mdctSpectrum, nNewSamples); + + /*Copy(scaleFactors_exp, self->lastBlockData.scaleFactors_exp, self->nScaleFactors);*/ + max_exp = 0; + FOR (i = 0; i < self->nScaleFactors; i++) + { + self->lastBlockData.scaleFactors_exp[i] = scaleFactors_exp[i]; + move16(); + max_exp = s_max(max_exp, scaleFactors_exp[i]); + } + + /*s = sub(s, max_exp);*/ + self->lastBlockData.scaleFactors_max_e = max_exp; + + FOR (i = 0; i < nNewSamples; i++) + { + self->lastBlockData.spectralData[i] = extract_h(L_shl(mdctSpectrum[i], s)); + move16(); + } + self->lastBlockData.spectralData_exp = sub(mdctSpectrum_exp,s); + move16(); + self->lastBlockData.gain_tcx_exp = gain_tcx_exp; + + Copy(scaleFactors, self->lastBlockData.scaleFactors, self->nScaleFactors); + } + return TONALMDCTCONCEAL_OK; +} + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_UpdateState(TonalMDCTConcealPtr self, + Word16 nNewSamples, + Word32 pitchLag, + Word16 badBlock, + Word8 tonalConcealmentActive + ) +{ + Word8 newBlockIsValid; + + assert(!(!badBlock && tonalConcealmentActive)); + + IF (badBlock) + { + newBlockIsValid = self->lastBlockData.blockIsValid; + move16(); + } + ELSE + { + newBlockIsValid = 0; + move16(); + test(); + if((LE_16(nNewSamples,2*L_FRAME_MAX))&&(nNewSamples>0)) + { + newBlockIsValid = 1; + move16(); + } + } + + /* Shift old state */ move16(); + move16(); + move16(); + self->secondLastBlockData.blockIsConcealed = self->lastBlockData.blockIsConcealed; + self->secondLastBlockData.blockIsValid = self->lastBlockData.blockIsValid; + self->secondLastBlockData.tonalConcealmentActive = self->lastBlockData.tonalConcealmentActive; + + /* Store new state */ move16(); + move16(); + move16(); + self->lastBlockData.blockIsConcealed = badBlock; + self->lastBlockData.blockIsValid = newBlockIsValid; + self->lastBlockData.tonalConcealmentActive = tonalConcealmentActive; + + self->lastPitchLag = pitchLag; + move32(); + + return TONALMDCTCONCEAL_OK; +} +static void FindPhases( /* o: currenc phase [-pi;pi] 2Q13 */ + TonalMDCTConcealPtr const self, /* i: pointer to internal structure */ + Word32 secondLastMDCT[], /* i: MDST spectrum data */ + Word32 secondLastMDST[], /* i: MDCT spectrum data */ + Word16 diff_exp) /* i: exp_MDST - exp_MDCT */ +{ + Word16 i; + Word16 l; + Word16 *pCurrentPhase; + + + + pCurrentPhase = self->pTCI->phase_currentFramePredicted; + /* for each index/index group */ + FOR( i = 0; i < self->pTCI->numIndexes; i++) + { + FOR (l = self->pTCI->lowerIndex[i]; l <= self->pTCI->upperIndex[i]; l++) + { + /* in contrast to the float code, the parameter secondLastMDST[l] + needs not to be negated - due to a different implementation of + the MDST */ + *pCurrentPhase++ = BASOP_util_atan2(secondLastMDST[l], secondLastMDCT[l], diff_exp); + move16(); + } + } + +} + +#define BANDWIDTH 7.0f +#define G 789516047l/*1.0/(2*1.36) Q31*/ +#define MAXRATIO 22938/*44.8f Q9*/ /* Maximum ratio |ODFT[k-1]|/|ODFT[k+1]| is 16.5 dB, that is maximum ratio (for fractional = 0) is (cos(PI/bandwidth)/cos(3PI/bandwidth))^1.36 */ +#define MM 1934815907 /* FL2WORD32(cos(EVS_PI/BANDWIDTH)); */ +#define SS 29166 /* FL2WORD16(cos((3*EVS_PI)/BANDWIDTH)*4); Q17*/ +#define N 931758243 /* FL2WORD32(sin(EVS_PI/BANDWIDTH)); */ +#define J 31946 /* FL2WORD16(sin((3*EVS_PI)/BANDWIDTH)); */ + +static void FindPhaseDifferences( /* o: Phase difference [-pi;pi] 2Q13*/ + TonalMDCTConcealPtr const self, /* i: Pointer to internal structure */ + Word32 powerSpectrum[]) /* i: Power spectrum data */ +{ + Word16 i, k; + Word16 * phaseDiff; + Word16 fractional, sf, sfn, sfd; + Word16 divi, s, j; + Word32 a, Q, L_tmp, m, n; + + s = SS; + move16(); + j = J; + move16(); + + phaseDiff = self->pTCI->phaseDiff; + + FOR (i = 0; i < self->pTCI->numIndexes; i++) + { + m = MM; + move16(); + n = N; + move16(); + + k = self->pTCI->indexOfTonalPeak[i]; + move16(); + + IF (GE_32(Mpy_32_16_1(powerSpectrum[k-1],512/*1.0f Q9*/),Mpy_32_16_1(powerSpectrum[k+1], MAXRATIO))) + { + phaseDiff[i] = 0; /*(float)tan(0.0f*EVS_PI/bandwidth);*/ move16(); + if(s_and(k,1) != 0) + phaseDiff[i] = -12868/*-EVS_PI 3Q12*/; + } + ELSE + { + IF (GE_32(Mpy_32_16_1(powerSpectrum[k+1],512/*1.0f Q9*/),Mpy_32_16_1(powerSpectrum[k-1], MAXRATIO))) + { + phaseDiff[i] = 12868/*EVS_PI 3Q12*/; /*(float)tan(2.0f*PI/bandwidth);*/ move16(); + if(s_and(k,1) != 0) + phaseDiff[i] = 0/*0 Q13*/; /*2Q13*/ + } + ELSE { + /*Q = (float)pow(odft_left/odft_right, G); + a = (m - Q * s) / (n + Q * j); + phaseDiff[i] = (float)atan(a) * (bandwidth/2.0f);*/ + /*max divi=44.8 & sf=6*/ + divi = BASOP_Util_Divide3232_uu_1616_Scale(powerSpectrum[k-1],powerSpectrum[k+1], &sf); + Q = BASOP_Util_fPow(L_deposit_h(divi), sf, G, 0, &sf); + L_tmp = Mpy_32_16_1(Q,s); + sfn = sub(sf, 2); + + if(sfn > 0) + m = L_shr(m, sfn); + + IF(sfn < 0) + { + L_tmp = L_shl(L_tmp, sfn); + sfn = 0; + } + + a = L_sub(m, L_tmp); /*sf*/ + + L_tmp = Mpy_32_16_1(Q,j); + IF(sf >= 0) + { + L_tmp = L_shr(L_tmp, 1); + sfd = add(sf,1); + n = L_shr(n,sfd); + } + ELSE{ + sfd = 0; + L_tmp = L_shl(L_tmp, sf); + } + + L_tmp = L_add(n,L_tmp); + fractional = BASOP_util_atan2(a, L_tmp, sub(sfn,sfd)); /*2Q13*/ + L_tmp = L_mult(fractional, 28672/*BANDWIDTH/2.0f Q13*/); /*2Q13*2Q13=4Q27*/ move16(); + + /* fractional is in the range 0..+pi */ + /* we need to stay in the range -2pi..+2pi */ + if(EQ_16(s_and(k,3),1)) + { + L_tmp = L_add(L_tmp, 421657440l/*+1*EVS_PI Q27*/); + } + if(EQ_16(s_and(k,3),2)) + { + L_tmp = L_sub(L_tmp, 843314880l/*+2*EVS_PI=-2*EVS_PI Q27*/); + } + if(EQ_16(s_and(k,3),3)) + { + L_tmp = L_sub(L_tmp, 421657440l/*+3*EVS_PI=-1*EVS_PI Q27*/); + } + phaseDiff[i] = round_fx(L_shl(L_tmp,1)); /*3Q12*/ + } + } + } +} + +static void CalcPowerSpecAndDetectTonalComponents(TonalMDCTConcealPtr const self, + Word32 secondLastMDST[], + Word16 secondLastMDST_exp, + Word32 secondLastMDCT[], + Word16 secondLastMDCT_exp, + Word32 const pitchLag) +{ + Word16 nSamples; + Word16 i; + Word16 floorPowerSpectrum; /* Minimum significant value of a spectral line in the power spectrum */ + Word32 powerSpectrum[L_FRAME_MAX]; + Word16 invScaleFactors[FDNS_NPTS]; + Word16 invScaleFactors_exp[FDNS_NPTS]; + Word16 powerSpectrum_exp, tmp_exp, old_exp; + + + + nSamples = self->nNonZeroSamples; + move16(); + + /* It is taken into account that the MDCT is not normalized. */ + floorPowerSpectrum/*Q0*/ = extract_l(Mpy_32_16_1(L_mult0(self->nSamples,self->nSamples),82)); /*1/400 = 82 Q15*/ + powerSpectrum_exp = 0; + move16(); + + CalcPowerSpec(secondLastMDCT, + secondLastMDCT_exp, + secondLastMDST, + secondLastMDST_exp, + nSamples, + floorPowerSpectrum, + powerSpectrum, + &powerSpectrum_exp); + + /* This setting to minimal level is required because the power spectrum is used in the threshold adaptation using the pitch up to self->nSamples. */ + set32_fx(powerSpectrum+nSamples, floorPowerSpectrum, sub(self->nSamples, nSamples)); + /* this setting to zero is needed since the FDNS needs to be called + with self->nSamplesCore; it relevant only for nb; it has no effect + to the output, but memory checker may complain otherwise due to the + usage of uninitialized values */ + IF ( GT_16(self->nSamplesCore, self->nSamples)) + { + set32_fx(powerSpectrum+self->nSamples, 0, sub(self->nSamplesCore, self->nSamples)); + } + + DetectTonalComponents(self->pTCI->indexOfTonalPeak, + self->pTCI->lowerIndex, + self->pTCI->upperIndex, + &self->pTCI->numIndexes, + self->lastPitchLag, + pitchLag, + self->lastBlockData.spectralData, + add(self->lastBlockData.spectralData_exp,self->lastBlockData.gain_tcx_exp), + self->lastBlockData.scaleFactors, + self->lastBlockData.scaleFactors_exp, + self->lastBlockData.scaleFactors_max_e, + powerSpectrum, + nSamples, + self->nSamplesCore, + floorPowerSpectrum); + + FindPhases(self, secondLastMDCT, secondLastMDST, sub(secondLastMDST_exp,secondLastMDCT_exp)); + + FindPhaseDifferences(self, powerSpectrum); + + IF (self->pTCI->numIndexes > 0) + { + + self->secondLastPowerSpectrum = self->secondLastBlockData.spectralData; + + /*sqrtFLOAT(powerSpectrum, powerSpectrum, nSamples);*/ + old_exp = powerSpectrum_exp; + powerSpectrum_exp = mult_r(sub(powerSpectrum_exp,2), 1 << 14); /*remove 2 bits of headroom from CalcPowerSpec*/ + FOR (i = 0; i < nSamples; i++) + { + tmp_exp = old_exp; + powerSpectrum[i] = Sqrt32(powerSpectrum[i], &tmp_exp); + powerSpectrum[i] = L_shr(powerSpectrum[i], sub(powerSpectrum_exp, tmp_exp)); + move32(); + } + + FOR (i = 0; i < self->nScaleFactors; i++) + { + move16(); + move16(); + invScaleFactors_exp[i] = self->secondLastBlockData.scaleFactors_exp[i]; + invScaleFactors[i] = Inv16(self->secondLastBlockData.scaleFactors[i], &invScaleFactors_exp[i]); + } + + + /* here mdct_shaping() is intentionally used rather then mdct_shaping_16() */ + mdct_shaping(powerSpectrum, self->nSamplesCore, invScaleFactors, invScaleFactors_exp); + FOR (i = self->nSamplesCore; i < nSamples; i++) + { + powerSpectrum[i] = L_shl(Mpy_32_16_1(powerSpectrum[i], invScaleFactors[FDNS_NPTS-1]), invScaleFactors_exp[FDNS_NPTS-1]); + move32(); + } + + /* 16 bits are now enough for storing the power spectrum */ + FOR (i = 0; i < nSamples; i++) + { + self->secondLastPowerSpectrum[i] = round_fx(powerSpectrum[i]); + } + + powerSpectrum_exp = sub(powerSpectrum_exp, self->secondLastBlockData.gain_tcx_exp); + self->secondLastPowerSpectrum_exp = powerSpectrum_exp; + move16(); + } +} + + +static void CalcMDXT(TonalMDCTConcealPtr const self, + Word16 const type, + Word16 const * const timeSignal, + Word32 * const mdxtOutput, + Word16 * const mdxtOutput_e) +{ + Word16 windowedTimeSignal[L_FRAME_PLUS+2*L_MDCT_OVLP_MAX]; + Word16 left_overlap, right_overlap, L_frame; + + L_frame = self->nSamples; + move16(); + + WindowSignal(self->tcx_cfg, + self->tcx_cfg->tcx_offsetFB, + FULL_OVERLAP, + FULL_OVERLAP, + &left_overlap, + &right_overlap, + timeSignal, + &L_frame, + windowedTimeSignal, + 1); + + IF (type == 0) + { + TCX_MDST(windowedTimeSignal, + mdxtOutput, + mdxtOutput_e, + left_overlap, + sub(L_frame, shr(add(left_overlap, right_overlap), 1)), + right_overlap); + } + ELSE + { + TCX_MDCT(windowedTimeSignal, + mdxtOutput, + mdxtOutput_e, + left_overlap, + sub(L_frame, shr(add(left_overlap, right_overlap), 1)), + right_overlap); + } +} + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_Detect( TonalMDCTConcealPtr const self, + Word32 const pitchLag, + Word16 * const numIndices) +{ + Word32 secondLastMDST[L_FRAME_MAX]; + Word32 secondLastMDCT[L_FRAME_MAX]; + Word16 secondLastMDCT_exp; + Word32 * powerSpectrum = secondLastMDST; + Word16 i, powerSpectrum_exp, secondLastMDST_exp, s; + Word16 nSamples; + + + nSamples = self->nSamples; + move16(); + secondLastMDST_exp = 16; /*time signal Q-1*/ + secondLastMDCT_exp = 16; /*time signal Q-1*/ + test(); + test(); + test(); + test(); + test(); + IF (self->lastBlockData.blockIsValid && self->secondLastBlockData.blockIsValid + && (EQ_16(self->lastBlockData.nSamples,nSamples) ) && (EQ_16(self->secondLastBlockData.nSamples,nSamples) ) + && (!self->secondLastBlockData.blockIsConcealed || self->secondLastBlockData.tonalConcealmentActive || (pitchLag != 0)) /* Safety if the second last frame was concealed and tonal concealment was inactive */ + ) + { + + IF (self->lastBlockData.blockIsConcealed == 0) + { + IF (self->secondLastBlockData.tonalConcealmentActive == 0) + { + CalcMDXT(self, 0, self->secondLastPcmOut, secondLastMDST, &secondLastMDST_exp); + CalcMDXT(self, 1, self->secondLastPcmOut, secondLastMDCT, &secondLastMDCT_exp); + self->nNonZeroSamples = 0; + FOR (i = 0; i < self->nSamples; i++) + { + if (self->secondLastBlockData.spectralData[i] != 0) + { + self->nNonZeroSamples = i; + move16(); + } + } + + /* 23 is the maximum length of the MA filter in getEnvelope */ + self->nNonZeroSamples = s_min(self->nSamples, add(self->nNonZeroSamples, 23)); + move16(); + nSamples = self->nNonZeroSamples; + move16(); + + s = getScaleFactor32(secondLastMDST, nSamples); + + FOR (i = 0; i < nSamples; i++) + { + secondLastMDST[i] = L_shl(secondLastMDST[i], s); + move32(); + } + secondLastMDST_exp = sub(secondLastMDST_exp, s); + move16(); + s = getScaleFactor32(secondLastMDCT, nSamples); + + FOR (i = 0; i < nSamples; i++) + { + secondLastMDCT[i] = L_shl(secondLastMDCT[i], s); + move32(); + } + secondLastMDCT_exp = sub(secondLastMDCT_exp, s); + move16(); + CalcPowerSpecAndDetectTonalComponents(self, secondLastMDST, secondLastMDST_exp, secondLastMDCT, secondLastMDCT_exp, pitchLag); + } + ELSE + { + /* If the second last frame was also lost, it is expected that pastTimeSignal could hold a bit different signal (e.g. including fade-out) from the one stored in TonalMDCTConceal_SaveTimeSignal. */ + /* That is why we reuse the already stored information about the concealed spectrum in the second last frame */ + nSamples = self->nNonZeroSamples; + move16(); + mdct_shaping_16(self->secondLastPowerSpectrum, self->nSamplesCore, nSamples, + self->secondLastBlockData.scaleFactors, self->secondLastBlockData.scaleFactors_exp, + self->secondLastBlockData.scaleFactors_max_e, powerSpectrum); + + powerSpectrum_exp = getScaleFactor32(powerSpectrum, nSamples); + powerSpectrum_exp = sub(powerSpectrum_exp, 3); /*extra 3 bits of headroom for MA filter in getEnvelope*/ + + /* multFLOAT(powerSpectrum, powerSpectrum, powerSpectrum, nSamples); */ + FOR(i = 0; i < nSamples; i++) + { + Word32 const t = L_shl(powerSpectrum[i], powerSpectrum_exp); + powerSpectrum[i] = Mpy_32_32(t, t); + move32(); + } + + RefineTonalComponents(self->pTCI->indexOfTonalPeak, + self->pTCI->lowerIndex, + self->pTCI->upperIndex, + self->pTCI->phaseDiff, + self->pTCI->phase_currentFramePredicted, + &self->pTCI->numIndexes, + self->lastPitchLag, + pitchLag, + self->lastBlockData.spectralData, + add(self->lastBlockData.spectralData_exp,self->lastBlockData.gain_tcx_exp), + self->lastBlockData.scaleFactors, + self->lastBlockData.scaleFactors_exp, + self->lastBlockData.scaleFactors_max_e, + powerSpectrum, + nSamples, + self->nSamplesCore, + extract_l(Mpy_32_16_1(L_mult0(self->nSamples,self->nSamples),82))); /* floorPowerSpectrum */ + + } + } + } + ELSE + { + self->pTCI->numIndexes = 0; + move16(); + } + + *numIndices = self->pTCI->numIndexes; + move16(); + + + return TONALMDCTCONCEAL_OK; +} + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_InsertNoise( TonalMDCTConcealPtr self, /*IN */ + Word32* mdctSpectrum, /*OUT*/ + Word16* mdctSpectrum_exp, /*OUT*/ + Word8 tonalConcealmentActive, + Word16* pSeed, /*IN/OUT*/ + Word16 tiltCompFactor, + Word16 crossfadeGain, + Word16 crossOverFreq) +{ + Word16 i, ld, fac; + Word16 rnd, exp, exp_last, exp_noise, inv_samples, inv_exp; + Word16 g, tiltFactor, tilt, tmp; + Word32 nrgNoiseInLastFrame, nrgWhiteNoise, L_tmp, L_tmp2; + + + + g = sub(32767/*1.0f Q15*/,crossfadeGain); + + rnd = 1977; + move16(); + if (self->lastBlockData.blockIsConcealed) + { + rnd = *pSeed; + move16(); + } + + IF (self->lastBlockData.blockIsValid == 0) + { + /* may just become active if the very first frame is lost */ + set32_fx(mdctSpectrum, 0, self->nSamples); + *mdctSpectrum_exp = SPEC_EXP_DEC; + } + ELSE + { + L_tmp = 805306368l/*0.375f Q31*/; + inv_exp = 15; + move16(); + inv_samples = Inv16(self->lastBlockData.nSamples, &inv_exp); + tiltFactor = round_fx(BASOP_Util_fPow(L_max(L_tmp, L_deposit_h(tiltCompFactor)), 0, L_deposit_h(inv_samples),inv_exp, &exp)); + BASOP_SATURATE_WARNING_OFF /*next op may result in 32768*/ + tiltFactor = shl(tiltFactor, exp); + BASOP_SATURATE_WARNING_ON + + tilt = 32767/*1.0f Q15*/; + move16(); + + nrgNoiseInLastFrame = L_deposit_h(0); + nrgWhiteNoise = L_deposit_h(0); + exp_last = exp_noise = 0; + move16(); + move16(); + IF (!tonalConcealmentActive) + { + ld = sub(14,norm_s(self->lastBlockData.nSamples)); + fac = shr(-32768,ld); + + FOR (i = 0; i < crossOverFreq; i++) + { + Word16 x = self->lastBlockData.spectralData[i]; + Word32 y; + rnd = extract_l(L_mac0(13849, rnd, 31821)); + y = L_mult(tilt,rnd); + + nrgNoiseInLastFrame = L_add(nrgNoiseInLastFrame, Mpy_32_16_1(L_msu(0, x,fac),x)); + x = round_fx(y); + nrgWhiteNoise = L_add(nrgWhiteNoise, Mpy_32_16_1(L_msu(0, x,fac),x)); + + mdctSpectrum[i] = y; /* 15Q16 */ move32(); + + tilt = mult_r(tilt,tiltFactor); + } + + IF (nrgNoiseInLastFrame == 0) + { + set32_fx(mdctSpectrum, 0, crossOverFreq); + *mdctSpectrum_exp = SPEC_EXP_DEC; + } + ELSE + { + exp_last = add(ld,shl(self->lastBlockData.spectralData_exp,1)); + exp_noise = add(ld,30); + + IF (nrgWhiteNoise > 0) + { + ld = norm_l(nrgNoiseInLastFrame); + nrgNoiseInLastFrame = L_shl(nrgNoiseInLastFrame,ld); + exp_last = sub(exp_last,ld); + ld = norm_l(nrgWhiteNoise); + nrgWhiteNoise = L_shl(nrgWhiteNoise,ld); + exp_noise = sub(exp_noise,ld); + + exp = sub(exp_last, exp_noise); + + IF(nrgNoiseInLastFrame > nrgWhiteNoise) + { + nrgNoiseInLastFrame = L_shr(nrgNoiseInLastFrame,1); + exp = add(exp,1); + } + tmp = div_l(nrgNoiseInLastFrame,round_fx(nrgWhiteNoise)); + tmp = Sqrt16(tmp, &exp); + g = mult_r(g,tmp); + + L_tmp = L_deposit_h(0); + ld = sub(self->lastBlockData.spectralData_exp, 15); + exp = sub(ld, exp); + + IF(exp > 0) + { + g = shr(g,exp); + *mdctSpectrum_exp = self->lastBlockData.spectralData_exp; + } + ELSE + { + crossfadeGain = shl(crossfadeGain,exp); + *mdctSpectrum_exp = sub(self->lastBlockData.spectralData_exp,exp); + } + /*make a headroom for mdct_shaping*/ + exp = sub(*mdctSpectrum_exp, SPEC_EXP_DEC); + /* assert(exp < 0);*/ + IF(exp < 0) + { + *mdctSpectrum_exp = SPEC_EXP_DEC; + } + ELSE + { + exp = 0; + } + } + + FOR (i = 0; i < crossOverFreq; i++) + { + Word16 const x = self->lastBlockData.spectralData[i]; + Word32 const y = mdctSpectrum[i]; + + if(g > 0) + { + L_tmp = Mpy_32_16_1(y,g); + } + + L_tmp2 = L_msu(L_tmp,crossfadeGain,x); + if(y > 0) + { + L_tmp2 = L_mac(L_tmp,crossfadeGain,x); + } + mdctSpectrum[i] = L_shl(L_tmp2, exp); + move32(); + } + } + exp = sub(self->lastBlockData.spectralData_exp, sub(*mdctSpectrum_exp,16)); + FOR (i = crossOverFreq; i < self->lastBlockData.nSamples; i++) + { + mdctSpectrum[i] = L_shl(L_deposit_l(self->lastBlockData.spectralData[i]), exp); + move32(); + } + } + ELSE + { + Word16 l; + assert(self->pTCI->numIndexes > 0); + + FOR (l = self->pTCI->lowerIndex[0]; l <= self->pTCI->upperIndex[0]; l++) + { + mdctSpectrum[l] = L_deposit_l(0); + } + + ld = sub(14,norm_s(self->lastBlockData.nSamples)); + fac = shr(-32768,ld); + FOR (l = 0; l < self->pTCI->lowerIndex[0]; l++) + { + Word16 x = self->lastBlockData.spectralData[l]; + Word32 y; + rnd = extract_l(L_mac0(13849, rnd, 31821)); + y = L_mult(tilt,rnd); + + nrgNoiseInLastFrame = L_add(nrgNoiseInLastFrame, Mpy_32_16_1(L_msu(0, x,fac),x)); + x = round_fx(y); + nrgWhiteNoise = L_add(nrgWhiteNoise, Mpy_32_16_1(L_msu(0, x,fac),x)); + + mdctSpectrum[l] = y; /* 15Q16 L_deposit_l(y);*/ move32(); + + tilt = mult_r(tilt,tiltFactor); + } + + FOR (i = 1; i < self->pTCI->numIndexes; i++) + { + /*tilt *= (float)pow(tiltFactor, self->pTCI->upperIndex[i-1]-self->pTCI->lowerIndex[i-1]+1);*/ + tmp= round_fx(BASOP_Util_fPow(L_deposit_h(tiltFactor), 0, L_deposit_h(self->pTCI->upperIndex[i-1]-self->pTCI->lowerIndex[i-1]+1),15, &exp)); + tmp = shl(tmp, exp); + tilt = mult_r(tilt,tmp); + + FOR (l = self->pTCI->lowerIndex[i]; l <= self->pTCI->upperIndex[i]; l++) + { + mdctSpectrum[l] = L_deposit_l(0); + } + + FOR (l = self->pTCI->upperIndex[i-1]+1; l < self->pTCI->lowerIndex[i]; l++) + { + Word16 x = self->lastBlockData.spectralData[l]; + Word32 y; + rnd = extract_l(L_mac0(13849, rnd, 31821)); + y = L_mult(tilt,rnd); + + nrgNoiseInLastFrame = L_add(nrgNoiseInLastFrame, Mpy_32_16_1(L_msu(0, x,fac),x)); + x = round_fx(y); + nrgWhiteNoise = L_add(nrgWhiteNoise, Mpy_32_16_1(L_msu(0, x,fac),x)); + + mdctSpectrum[l] = y; /* 15Q16 L_deposit_l(y);*/ move32(); + + tilt = mult_r(tilt,tiltFactor); + } + } + + tmp = round_fx(BASOP_Util_fPow(L_deposit_h(tiltFactor), 0, L_deposit_h(self->pTCI->upperIndex[self->pTCI->numIndexes-1]-self->pTCI->lowerIndex[self->pTCI->numIndexes-1]+1),15, &exp)); + BASOP_SATURATE_WARNING_OFF /*next op may result in 32768*/ + tmp = shl(tmp, exp); + BASOP_SATURATE_WARNING_ON + tilt = mult_r(tilt,tmp); + + FOR (l = add(self->pTCI->upperIndex[self->pTCI->numIndexes-1], 1); l < crossOverFreq; l++) + { + Word16 x = self->lastBlockData.spectralData[l]; + Word32 y; + rnd = extract_l(L_mac0(13849, rnd, 31821)); + y = L_mult(tilt,rnd); + + nrgNoiseInLastFrame = L_add(nrgNoiseInLastFrame, Mpy_32_16_1(L_msu(0, x,fac),x)); + x = round_fx(y); + nrgWhiteNoise = L_add(nrgWhiteNoise, Mpy_32_16_1(L_msu(0, x,fac),x)); + + mdctSpectrum[l] = y; /* 15Q16 L_deposit_l(y);*/ move32(); + + tilt = mult_r(tilt,tiltFactor); + } + + IF (nrgNoiseInLastFrame == 0) + { + set32_fx(mdctSpectrum, 0, crossOverFreq); + *mdctSpectrum_exp = SPEC_EXP_DEC; + } + ELSE + { + exp_last = add(ld,shl(self->lastBlockData.spectralData_exp,1)); + exp_noise = add(ld,shl(15,1)); + + ld = norm_l(nrgNoiseInLastFrame); + nrgNoiseInLastFrame = L_shl(nrgNoiseInLastFrame,ld); + exp_last = sub(exp_last,ld); + ld = norm_l(nrgWhiteNoise); + nrgWhiteNoise = L_shl(nrgWhiteNoise,ld); + exp_noise = sub(exp_noise,ld); + + exp = sub(exp_last, exp_noise); + + IF(nrgNoiseInLastFrame > nrgWhiteNoise) + { + nrgNoiseInLastFrame = L_shr(nrgNoiseInLastFrame,1); + exp = add(exp,1); + } + tmp = div_l(nrgNoiseInLastFrame,round_fx(nrgWhiteNoise)); + tmp = Sqrt16(tmp, &exp); + g = mult_r(g,tmp); + + L_tmp = L_deposit_h(0); + ld = sub(self->lastBlockData.spectralData_exp, 15); + exp = sub(ld, exp); + IF(exp > 0) + { + g = shr(g,exp); + *mdctSpectrum_exp = self->lastBlockData.spectralData_exp; + } + ELSE { + crossfadeGain = shl(crossfadeGain,exp); + *mdctSpectrum_exp = sub(self->lastBlockData.spectralData_exp,exp); + } + /*make a headroom for mdct_shaping*/ + exp = sub(*mdctSpectrum_exp, SPEC_EXP_DEC); + + + IF(exp < 0) + { + *mdctSpectrum_exp = SPEC_EXP_DEC; + } + ELSE + { + exp = 0; + } + + FOR (l = 0; l < self->pTCI->lowerIndex[0]; l++) + { + Word16 const x = self->lastBlockData.spectralData[l]; + Word32 const y = mdctSpectrum[l]; + + if(g > 0) + { + L_tmp = Mpy_32_16_1(y,g); + } + + L_tmp2 = L_msu(L_tmp,crossfadeGain,x); + if(y > 0) + { + L_tmp2 = L_mac(L_tmp,crossfadeGain,x); + } + mdctSpectrum[l] = L_shl(L_tmp2, exp); + move32(); + } + + FOR (i = 1; i < self->pTCI->numIndexes; i++) + { + FOR (l = self->pTCI->upperIndex[i-1]+1; l < self->pTCI->lowerIndex[i]; l++) + { + Word16 const x = self->lastBlockData.spectralData[l]; + Word32 const y = mdctSpectrum[l]; + + if(g > 0) + { + L_tmp = Mpy_32_16_1(y,g); + } + + L_tmp2 = L_msu(L_tmp,crossfadeGain,x); + if(y > 0) + { + L_tmp2 = L_mac(L_tmp,crossfadeGain,x); + } + mdctSpectrum[l] = L_shl(L_tmp2, exp); + move32(); + } + } + + /* initialize bins of tonal components with zero: basically not + necessary, but currently the whole spectrum is rescaled in + mdct_noiseShaping() and then there would be a processing of + uninitialized values */ + FOR (i = 0; i < self->pTCI->numIndexes; i++) + { + FOR (l = self->pTCI->lowerIndex[i]; l <= self->pTCI->upperIndex[i]; l++) + { + mdctSpectrum[l] = L_deposit_l(0); + } + } + + FOR (l = add(self->pTCI->upperIndex[self->pTCI->numIndexes-1], 1); l < crossOverFreq; l++) + { + Word16 const x = self->lastBlockData.spectralData[l]; + Word32 const y = mdctSpectrum[l]; + + if(g > 0) + { + L_tmp = Mpy_32_16_1(y,g); + } + + L_tmp2 = L_msu(L_tmp,crossfadeGain,x); + if(y > 0) + { + L_tmp2 = L_mac(L_tmp,crossfadeGain,x); + } + mdctSpectrum[l] = L_shl(L_tmp2, exp); + move32(); + } + } + exp = sub(self->lastBlockData.spectralData_exp, sub(*mdctSpectrum_exp,16)); + FOR (l = crossOverFreq; l < self->lastBlockData.nSamples; l++) + { + mdctSpectrum[l] = L_shl(L_deposit_l(self->lastBlockData.spectralData[l]), exp); + move32(); + } + } + } + + *pSeed = rnd; + move16(); + + return TONALMDCTCONCEAL_OK; +} + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_Apply(TonalMDCTConcealPtr self, /*IN */ + Word32 *mdctSpectrum, /*IN/OUT*/ + Word16 *mdctSpectrum_exp /*IN */ + ) +{ + Word16 i, l, exp; + Word16 * phaseDiff, * pCurrentPhase; + Word32 phaseToAdd, currentPhase; + Word32 powerSpectrum[L_FRAME_MAX]; + Word16 nSamples; + + + + IF (self->lastBlockData.blockIsValid & self->secondLastBlockData.blockIsValid) + { + assert(self->pTCI->numIndexes > 0); + + nSamples = self->nNonZeroSamples; + move16(); + assert(self->pTCI->upperIndex[self->pTCI->numIndexes-1] < nSamples); + + + mdct_shaping_16(self->secondLastPowerSpectrum, self->nSamplesCore, nSamples, + self->secondLastBlockData.scaleFactors, self->secondLastBlockData.scaleFactors_exp, + self->secondLastBlockData.scaleFactors_max_e, powerSpectrum); + + phaseDiff = self->pTCI->phaseDiff; /* if multiple frame loss occurs use the phase from the last frame and continue rotating */ + pCurrentPhase = self->pTCI->phase_currentFramePredicted; + + exp = sub(*mdctSpectrum_exp, add(add(self->secondLastPowerSpectrum_exp, add(self->secondLastBlockData.gain_tcx_exp,1)),self->secondLastBlockData.scaleFactors_max_e)); + + IF (!self->lastBlockData.blockIsConcealed) + { + if (self->secondLastBlockData.tonalConcealmentActive != 0) + { + self->nFramesLost = add(self->nFramesLost,2); /*Q1*/ move16(); + } + if (self->secondLastBlockData.tonalConcealmentActive == 0) + { + self->nFramesLost = 3; /*Q1*/ move16(); + } + } + /* for each index group */ + FOR (i = 0; i < self->pTCI->numIndexes; i++) + { + /*phaseToAdd = self->nFramesLost*phaseDiff[i]; */ + phaseToAdd = L_mult0(self->nFramesLost,phaseDiff[i]); /*Q1*3Q12=2Q13*/ + /* Move phaseToAdd to range -PI..PI */ + + WHILE (GT_32(phaseToAdd, 25736l/*EVS_PI Q13*/)) + { + phaseToAdd = L_sub(phaseToAdd, 51472l/*2*EVS_PI Q13*/); + } + WHILE (LT_32(phaseToAdd, -25736l/*-EVS_PI Q13*/)) + { + phaseToAdd = L_add(phaseToAdd, 51472l/*2*EVS_PI Q13*/); + } + + FOR (l = self->pTCI->lowerIndex[i]; l <= self->pTCI->upperIndex[i]; l++) + { + /* *pCurrentPhase and phaseToAdd are in range -PI..PI */ + currentPhase = L_mac0(phaseToAdd, (*pCurrentPhase++), 1); /*2Q13+2Q13=3Q13*/ + + if (GT_32(currentPhase, 25736l/*EVS_PI Q13*/)) + { + currentPhase = L_sub(currentPhase, 51472l/*2*EVS_PI Q13*/); + } + if (LT_32(currentPhase, -25736l/*-EVS_PI Q13*/)) + { + currentPhase = L_add(currentPhase, 51472l/*2*EVS_PI Q13*/); + } + /* getCosWord16 returns 1Q14*/ + mdctSpectrum[l] = Mpy_32_16_1(powerSpectrum[l],getCosWord16(extract_l(currentPhase))); + move32(); + mdctSpectrum[l] = L_shr(mdctSpectrum[l], exp); + } + } + } + + self->nFramesLost = add(self->nFramesLost,2); /*Q1*/ move16(); + + return TONALMDCTCONCEAL_OK; +} + +TONALMDCTCONCEAL_ERROR TonalMDCTConceal_SaveTimeSignal( TonalMDCTConcealPtr self, + Word16* timeSignal, + Word16 nNewSamples + ) +{ + IF (EQ_16(nNewSamples,self->nSamples)) + { + assert(nNewSamples <= L_FRAME_MAX); + IF (!self->secondLastBlockData.tonalConcealmentActive) + { + Copy(self->lastPcmOut + self->nSamples/2, self->secondLastPcmOut, self->nSamples/2); + } + Copy(timeSignal, self->lastPcmOut, self->nSamples); + } + + return TONALMDCTCONCEAL_OK; +} +static void CalcPowerSpec(Word32 * mdctSpec, /* i: MDCT spectrum Q31,mdctSpec_exp */ + Word16 mdctSpec_exp, /* i: exponent of MDCT spectrum */ + Word32 * mdstSpec, /* i: MDST spectrum Q31,mdstSpec_exp */ + Word16 mdstSpec_exp, /* i: exponent of MDST spectrum */ + Word16 nSamples, /* i: frame size */ + Word16 floorPowerSpectrum, /* i: lower limit for power spectrum bins Q0 */ + Word32 * powerSpec, /* o: power spectrum */ + Word16 * powerSpec_exp) /* o: exponent of power spectrum */ +{ + Word16 k, s1, s2, tmp; + Word32 x, L_tmp, L_tmp_floor; + + + k = s_max(mdctSpec_exp, mdstSpec_exp); + *powerSpec_exp = add(add(k, k), 3); /*extra 3 bits of headroom for MA filter in getEnvelope*/ move16(); + s1 = sub(*powerSpec_exp, add(mdctSpec_exp, mdctSpec_exp)); + s2 = sub(*powerSpec_exp, add(mdstSpec_exp, mdstSpec_exp)); + + k = sub(31, *powerSpec_exp); + /* If the signal is bellow floor, special care is needed for *powerSpec_exp */ + IF (LT_16(add(16-3, norm_s(floorPowerSpectrum)), k)) /*extra 3 bits of headroom for MA filter in getEnvelope*/ + { + k = sub(k, add(16-3, norm_s(floorPowerSpectrum))); /*extra 3 bits of headroom for MA filter in getEnvelope*/ + *powerSpec_exp = add(*powerSpec_exp, k); + s1 = add(s1, k); + s2 = add(s2, k); + k = add(16-3, norm_s(floorPowerSpectrum)); + } + L_tmp_floor = L_shl(L_deposit_l(floorPowerSpectrum), k); + + tmp = sub(nSamples, 2); + FOR (k = 1; k <= tmp; k++) + { + x = Mpy_32_32(mdctSpec[k], mdctSpec[k]); /*Q31,2*mdctSpec_exp*/ + + L_tmp = Mpy_32_32(mdstSpec[k], mdstSpec[k]); /*Q31,2*mdstSpec_exp*/ + x = L_add(L_shr(x,s1), L_shr(L_tmp,s2)); /*Q31,*powerSpec_exp*/ + + powerSpec[k] = L_max(L_tmp_floor, x); + move32(); + } + + powerSpec[0] = L_shr(powerSpec[1], 1); + move32(); + powerSpec[nSamples-1] = L_shr(powerSpec[nSamples-2], 1); + move32(); + +} diff --git a/lib_dec/transition_dec_fx.c b/lib_dec/transition_dec_fx.c new file mode 100644 index 0000000..500c4e5 --- /dev/null +++ b/lib_dec/transition_dec_fx.c @@ -0,0 +1,925 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*----------------------------------------------------------------------* + * Local functions + *----------------------------------------------------------------------*/ + +static void tc_dec_fx( Decoder_State_fx *st_fx, const Word16 L_frame,Word16 exc[], Word16 *T0,Word16 *T0_frac, const Word16 i_subfr, + const Word16 tc_subfr, Word16 *position, const Word32 core_brate, Word16 bwe_exc[], Word16 *Q_exc ); + +/*======================================================================*/ +/* FUNCTION : transition_dec_fx() */ +/*----------------------------------------------------------------------*/ +/* PURPOSE : Principal function for TC decoding */ +/* */ +/*----------------------------------------------------------------------*/ +/* GLOBAL INPUT ARGUMENTS : */ +/* const Word32 core_brate, : core bitrate Q0 */ +/* _ (Word16) L_frame_fx : length of the frame Q0 */ +/* _ (Word16[]) pitch_buf_fx : floating pitch values for each subframe Q6*/ +/* _ (Word16[]) voice_factors_fx: frame error rate Q15 */ +/*-----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Q0) */ +/* _ (Word16[]) exc2_fx : adapt. excitation/total exc (Q0) */ +/*-----------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*=======================================================================*/ + +void transition_dec_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 coder_type, /* i : coder type */ + const Word16 tc_subfr, /* i : TC subframe index */ + Word16 *Jopt_flag, /* i : joint optimization flag */ + Word16 *exc, /* o : excitation signal */ + Word16 *T0, /* o : close loop integer pitch */ + Word16 *T0_frac, /* o : close loop fractional part of the pitch */ + Word16 *T0_min, /* i/o: delta search min for sf 2 & 4 */ + Word16 *T0_max, /* i/o: delta search max for sf 2 & 4 */ + Word16 **pt_pitch, /* o : floating pitch values */ + Word16 *position, /* i/o: first glottal impulse position in frame */ + Word16 *bwe_exc, /* o : excitation for SWB TBE */ + Word16 *Q_exc /*i/o : scaling of excitation */ +) +{ + Word16 pit_flag, pit_start, pit_limit, index, nBits; + Word16 i, offset,temp,tmp; + Word16 limit_flag; + + /* Set limit_flag to 0 for restrained limits, and 1 for extended limits */ + limit_flag = 0; + + /*---------------------------------------------------------------------* + * zero adaptive contribution (glottal shape codebook search not + * in first subframe(s) ) + *---------------------------------------------------------------------*/ + IF(GT_16(tc_subfr, add(i_subfr,TC_0_192))) + { + set16_fx(&exc[i_subfr], 0, L_SUBFR); + + IF( EQ_16(L_frame,L_FRAME)) + { + set16_fx(&bwe_exc[i_subfr*HIBND_ACB_L_FAC], 0, (Word16) (L_SUBFR*HIBND_ACB_L_FAC)); /* set past excitation buffer to 0 */ + } + ELSE + { + set16_fx(&bwe_exc[i_subfr*2], 0, (Word16) (L_SUBFR*2)); /* set past excitation buffer to 0 */ + } + + *T0 = L_SUBFR; + move16(); + *T0_frac = 0; + move16(); + **pt_pitch = L_SUBFR_Q6; + move16(); + } + + /*---------------------------------------------------------------------* + * glottal shape codebook search + *---------------------------------------------------------------------*/ + + ELSE IF(((GE_16(tc_subfr,i_subfr))&&(LE_16(sub(tc_subfr,i_subfr),TC_0_192)))) + { + set16_fx( exc-L_EXC_MEM, 0, L_EXC_MEM ); /* set past excitation buffer to 0 */ + + IF( EQ_16(L_frame,L_FRAME)) + { + set16_fx( bwe_exc-PIT_MAX*HIBND_ACB_L_FAC, 0, PIT_MAX*HIBND_ACB_L_FAC); /* set past excitation buffer to 0 */ + } + ELSE + { + set16_fx( bwe_exc-PIT16k_MAX*2, 0, PIT16k_MAX*2); /* set past excitation buffer to 0 */ + } + + /* glottal shape codebook contribution construction */ + tc_dec_fx( st_fx, L_frame, exc, T0, T0_frac, i_subfr, tc_subfr, position, core_brate, bwe_exc, Q_exc ); + + **pt_pitch = shl(add(shl(*T0,2),*T0_frac),4); + move16(); /* save subframe pitch values Q6 */ + + *Jopt_flag = 1; + move16(); + } + + /*---------------------------------------------------------------------* + * Regular ACELP Decoding using GENERIC type decoder + * (all subframes following subframe with glottal shape codebook seach) + * - search the position of the 2nd glottal impulse in case that the first + * one is in the 1st subframe (different adaptive contribution + * construction and the pitch period coding is used) + *---------------------------------------------------------------------*/ + + ELSE IF ( LT_16(tc_subfr,i_subfr)) + { + IF( EQ_16(L_frame,L_FRAME)) + { + *Jopt_flag = 1; + move16(); + test(); + IF( (GE_16(sub(i_subfr,tc_subfr),L_SUBFR))&&(LE_16(sub(i_subfr,tc_subfr),L_SUBFR+TC_0_192))) + { + pit_flag = 0; + move16(); + } + ELSE + { + pit_flag = L_SUBFR; + move16(); + } + IF( EQ_16(tc_subfr,TC_0_0)) + { + IF( EQ_16(i_subfr,L_SUBFR)) + { + limit_T0_fx( L_FRAME, 8, pit_flag, limit_flag, *T0, 0, T0_min, T0_max ); + } + pit_flag = 1; + move16(); + } + + /*-----------------------------------------------------------------* + * get number of bits for pitch decoding + *-----------------------------------------------------------------*/ + + nBits = ACB_bits_tbl[BIT_ALLOC_IDX_fx(core_brate, TRANSITION, i_subfr, TC_SUBFR2IDX_fx(tc_subfr))]; + move16(); + + /*------------------------------------------------------------* + * first glottal impulse is in the 1st subframe + *------------------------------------------------------------*/ + test(); + test(); + test(); + test(); + test(); + test(); + IF( (EQ_16(i_subfr,L_SUBFR))&&(GE_16(tc_subfr,TC_0_128))) + { + /*--------------------------------------------------------* + * second glottal impulse is in the 3rd or 4th subframe + * - build exc[] in 2nd subframe + *--------------------------------------------------------*/ + + *T0 = 2*L_SUBFR; + move16(); + *T0_frac = 0; + move16(); + *Jopt_flag = 0; + move16(); + + /* set adaptive part of exciation for curent subframe to 0 */ + set16_fx( &exc[i_subfr], 0, (Word16)(L_SUBFR+1) ); + set16_fx( &bwe_exc[i_subfr*HIBND_ACB_L_FAC], 0, (Word16)(L_SUBFR*HIBND_ACB_L_FAC) ); + + } + ELSE IF( (EQ_16(i_subfr,L_SUBFR))&&(EQ_16(tc_subfr,TC_0_64))) + { + /*--------------------------------------------------------* + * second glottal impulse is in the 2nd subframe, + * - build exc[] in 2nd subframe + *--------------------------------------------------------*/ + pit_start = PIT_MIN; + move16(); + if (GT_16(PIT_MIN,(*position))) + { + pit_start = sub(L_SUBFR, *position); + } + + pit_start = s_max(pit_start, PIT_MIN ); + pit_limit = add(shl(pit_start,1), *position); + + /* 7 bit pitch DECODER */ + index = (Word16)get_next_indice_fx( st_fx, nBits ); + + *T0 = add(pit_start, shr((index),1)); + move16(); + *T0_frac = shl(sub((index),shl(sub(*T0, pit_start),1)),1); + move16(); + + limit_T0_fx( L_FRAME, 8, pit_flag, limit_flag, *T0, 0, T0_min, T0_max ); /* find T0_min and T0_max */ + + /* Find the adaptive codebook vector - ACELP long-term prediction */ + pred_lt4(&exc[i_subfr], &exc[i_subfr], *T0, *T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP); + offset = tbe_celp_exc_offset(*T0, *T0_frac, L_frame); + + move16(); + move16(); /* penality for 2 ptrs initialization */ + + FOR (i=0; iBER_detect = 1; + move16(); + } + + /* Find the adaptive codebook vector. ACELP long-term prediction */ + pred_lt4(&exc[i_subfr], &exc[i_subfr], *T0, *T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP); + offset = tbe_celp_exc_offset(*T0, *T0_frac, L_frame); + move16(); + move16(); /* penality for 2 ptrs initialization */ + FOR (i=0; iBER_detect ); + + /* Find the adaptive codebook vector */ + pred_lt4(&exc[i_subfr], &exc[i_subfr], *T0, *T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP); + offset = tbe_celp_exc_offset(*T0, *T0_frac, L_frame); + move16(); + move16(); /* penality for 2 ptrs initialization */ + FOR (i=0; iBER_detect ); + } + ELSE IF( EQ_16(nBits,8)) /* tc_subfr==0 && i_subfr==L_SUBFR */ + { + /*-----------------------------------------------------------------------------* + * The pitch range is encoded absolutely with 8 bits and is divided as follows: + * PIT16k_MIN to PIT16k_FR2_TC0_2SUBFR-1 resolution 1/4 (frac = 0,1,2 or 3) + * PIT16k_FR2_TC0_2SUBFR to 2*L_SUBFR resolution 1/2 (frac = 0 or 2) + *-----------------------------------------------------------------------------*/ + + IF( LT_16(index,(PIT16k_FR2_TC0_2SUBFR-PIT16k_MIN)*4))/*(PIT16k_FR2_TC0_2SUBFR-PIT16k_MIN)*4*/ + { + *T0 = add(PIT16k_MIN,shr(index,2)); + move16(); + temp = shl(sub(*T0,PIT16k_MIN),2); + move16(); + *T0_frac = sub(index,temp); + move16(); + } + ELSE + { + index = sub(index,(PIT16k_FR2_TC0_2SUBFR-PIT16k_MIN)*4); /* (PIT16k_FR2_TC0_2SUBFR-PIT16k_MIN)*4 */ + *T0 = add(PIT16k_FR2_TC0_2SUBFR,shr(index,1)); + move16(); + temp = shl(sub(*T0,PIT16k_FR2_TC0_2SUBFR),1); + move16(); + *T0_frac = shl(sub(index,temp),1); + move16(); + } + + /* biterror detection mechanism */ + IF( GT_16(add((*T0<<2),*T0_frac),((2*L_SUBFR)<<2))) + { + *T0 = L_SUBFR; + move16(); + *T0_frac = 0; + move16(); + st_fx->BER_detect = 1; + move16(); + } + } + ELSE IF( EQ_16(nBits,6)) + { + delta_pit_dec_fx( 4, index, T0, T0_frac, *T0_min ); + } + IF( EQ_16(nBits,6)) + { + limit_T0_fx( L_FRAME16k, 8, L_SUBFR, limit_flag, *T0, *T0_frac, T0_min, T0_max ); /* find T0_min and T0_max */ + } + + /*-----------------------------------------------------------------* + * - find the adaptive codebook vector + * - LP filtering of the adaptive excitation (if non-zero) + *-----------------------------------------------------------------*/ + test(); + IF( (EQ_16(i_subfr,L_SUBFR))&&(EQ_16(*T0,2*L_SUBFR))) + { + /* no adaptive excitation in the second subframe */ + set16_fx( &exc[i_subfr], 0, L_SUBFR+1 ); + get_next_indice_fx( st_fx, 1 ); /* this bit is actually not needed */ + set16_fx( &bwe_exc[i_subfr * 2], 0, L_SUBFR * 2 ); + } + ELSE + { + /* Find the adaptive codebook vector - ACELP long-term prediction */ + pred_lt4(&exc[i_subfr], &exc[i_subfr], *T0, *T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP); + offset = tbe_celp_exc_offset(*T0, *T0_frac, L_frame); + move16(); + move16(); /* penalty for 2 ptrs initialization */ + FOR (i=0; i /* Debug prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * updt_dec() + * + * Common updates (all frame types) + *-------------------------------------------------------------------*/ +void updt_dec_fx( + Decoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + const Word16 *old_exc_fx, /* i : buffer of excitation */ + const Word16 *pitch_buf_fx, /* i : floating pitch values for each subframe */ + const Word16 Es_pred, /* i : predicited scaled innovation energy */ + const Word16 *Aq, /* i : A(z) quantized for all subframes */ + const Word16 *lsf_new_fx, /* i : current frame LSF vector */ + const Word16 *lsp_new_fx, /* i : current frame LSP vector */ + const Word16 voice_factors[], /* i : voicing factors */ + const Word16 *old_bwe_exc_fx, /* i : buffer of excitation */ + const Word16 *gain_buf /* i : Q14*/ +) +{ + Word16 i, len; + + /* update old excitation buffer */ + Copy( &old_exc_fx[L_frame], st_fx->old_exc_fx, L_EXC_MEM_DEC ); + IF( !st_fx->Opt_AMR_WB_fx ) + { + Copy( &old_bwe_exc_fx[L_FRAME32k], st_fx->old_bwe_exc_fx, PIT16k_MAX * 2 ); + } + + /* update old LSP and LSF vector */ + Copy( lsf_new_fx, st_fx->lsf_old_fx, M ); + Copy( lsp_new_fx, st_fx->lsp_old_fx, M ); + + /* update last coding type */ + st_fx->last_coder_type_fx = coder_type; + test(); + test(); + test(); + if( EQ_16(coder_type,INACTIVE)||(EQ_16(st_fx->bpf_off_fx,1)&&NE_16(coder_type,AUDIO)&&NE_16(coder_type,TRANSITION))) + { + st_fx->last_coder_type_fx = UNVOICED; + move16(); + } + test(); + test(); + if( (NE_16(coder_type,AUDIO)||st_fx->Last_GSC_noisy_speech_flag_fx!=0)&&st_fx->Last_GSC_pit_band_idx_fx>0) + { + st_fx->Last_GSC_pit_band_idx_fx = 0; + move16(); /*The temporal contribution of the GSC is meaningless after 1 frame lost for inactive & unvoiced content */ + } + /* this ensures that st_fx->last_coder_type_fx is never set to INACTIVE in case of AVQ inactive because the FEC does not distinguish between GSC inactive and AVQ inactive */ + + test(); + if( GT_32(st_fx->total_brate_fx,ACELP_24k40)&&EQ_16(coder_type,INACTIVE)) + { + st_fx->last_coder_type_fx = GENERIC; + move16(); + } + test(); + test(); + test(); + IF( EQ_16(st_fx->Opt_AMR_WB_fx,1)&&EQ_16(coder_type,INACTIVE)&&NE_32(st_fx->core_brate_fx,SID_1k75)&&NE_32(st_fx->core_brate_fx,FRAME_NO_DATA)) + { + /* overwrite previous coding type to help FEC */ + st_fx->last_coder_type_fx = UNVOICED; + move16(); + st_fx->last_voice_factor_fx = voice_factors[NB_SUBFR-1]; + move16(); + } + + IF( !st_fx->Opt_AMR_WB_fx ) + { + /* update voicing factor of TBE to help FEC */ + + st_fx->last_voice_factor_fx = voice_factors[NB_SUBFR16k-1]; + move16(); + if( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + st_fx->last_voice_factor_fx = voice_factors[NB_SUBFR-1]; + move16(); + } + } + + test(); + IF ( coder_type != AUDIO && coder_type != INACTIVE ) + { + st_fx->noise_lev_fx = NOISE_LEVEL_SP3; + move16(); + set16_fx( st_fx->old_y_gain_fx, 0, MBANDS_GN ); + + FOR( i = 0; i < L_FRAME; i++ ) + { + Word16 tmp_seed = st_fx->seed_tcx_fx; + move16(); + st_fx->Last_GSC_spectrum_fx[i] = shr_r(Random( &tmp_seed ),5); + move16(); /*Q10*/ + } + } + + /* update last GSC SWB speech flag for FEC */ + st_fx->Last_GSC_noisy_speech_flag_fx = st_fx->GSC_noisy_speech_fx; + move16(); + + /* update counter for FEC pitch estimate */ + st_fx->upd_cnt_fx = add(st_fx->upd_cnt_fx,1); + + st_fx->upd_cnt_fx = s_min(st_fx->upd_cnt_fx, MAX_UPD_CNT); + + len = shr(L_frame,6); + Copy32( &st_fx->old_pitch_buf_fx[len], st_fx->old_pitch_buf_fx, len ); + FOR ( i = 0; i < len; i++ ) + { + st_fx->old_pitch_buf_fx[len+i] = L_mult0(pitch_buf_fx[i], 1<<10); + move32(); + } + Copy( &st_fx->mem_pitch_gain[2], &st_fx->mem_pitch_gain[L_frame/L_SUBFR+2], L_frame/L_SUBFR ); + IF (EQ_16(L_frame , L_FRAME)) + { + st_fx->mem_pitch_gain[2] = gain_buf[3]; + move16(); + st_fx->mem_pitch_gain[3] = gain_buf[2]; + move16(); + st_fx->mem_pitch_gain[4] = gain_buf[1]; + move16(); + st_fx->mem_pitch_gain[5] = gain_buf[0]; + move16(); + } + ELSE + { + st_fx->mem_pitch_gain[2] = gain_buf[4]; + move16(); + st_fx->mem_pitch_gain[3] = gain_buf[3]; + move16(); + st_fx->mem_pitch_gain[4] = gain_buf[2]; + move16(); + st_fx->mem_pitch_gain[5] = gain_buf[1]; + move16(); + st_fx->mem_pitch_gain[6] = gain_buf[0]; + move16(); + } + + + /* FEC - update adaptive LSF mean vector */ + Copy( st_fx->lsfoldbfi0_fx, st_fx->lsfoldbfi1_fx, M ); + Copy( lsf_new_fx, st_fx->lsfoldbfi0_fx, M ); + + /* update of pitch and voicing information for HQ FEC */ + IF ( NE_16(st_fx->last_core_fx,HQ_CORE)) + { + st_fx->HqVoicing_fx = 1; + move16(); + test(); + if( !st_fx->Opt_AMR_WB_fx && EQ_16(coder_type,UNVOICED)) + { + st_fx->HqVoicing_fx = 0; + move16(); + } + } + + /* SC-VBR */ + st_fx->old_ppp_mode_fx = st_fx->last_ppp_mode_dec_fx; + move16(); + st_fx->last_ppp_mode_dec_fx = st_fx->ppp_mode_dec_fx; + move16(); + st_fx->last_nelp_mode_dec_fx = st_fx->nelp_mode_dec_fx; + move16(); + st_fx->last_vbr_hw_BWE_disable_dec_fx = st_fx->vbr_hw_BWE_disable_dec_fx; + move16(); + + /*core switching updates*/ + Copy( &Aq[(st_fx->L_frame_fx/L_SUBFR-1)*(M+1)], st_fx->old_Aq_12_8_fx, M+1 ); + st_fx->old_Es_pred_fx = Es_pred; + move16(); + + return; +} + +/*-------------------------------------------------------------------* + * updt_IO_switch() + * + * Common updates for AMR-WB IO mode and EVS primary switching + *-------------------------------------------------------------------*/ +void updt_IO_switch_dec_fx( + const Word16 output_frame, /* i : output frame length */ + Decoder_State_fx *st_fx /* o : Decoder static variables structure */ +) +{ + Word16 xsp_tmp[M]; + IF( EQ_16(st_fx->last_core_fx,AMR_WB_CORE)) /* switching to EVS primary mode */ + { + /* AMR-WB IO mode uses ISF(ISP), but EVS primary mode mode LSF(LSP) */ + Copy( stable_LSP_fx, xsp_tmp, M ); + isf2lsf_fx( st_fx->lsf_old_fx, st_fx->lsf_old_fx, xsp_tmp); + Copy( stable_LSP_fx, xsp_tmp, M ); + /*isp2lsp( st->lsp_old, st->lsp_old, xsp_tmp, M, grid100 );*/ + isp2lsp_fx( st_fx->lsp_old_fx, st_fx->lsp_old_fx, xsp_tmp, M); + + /* AMR-WB IO mode uses ISF(ISP), but EVS primary mode uses LSF(LSP) */ + Copy( stable_LSP_fx, xsp_tmp, M ); + /*isp2lsp( st->lspCNG, st->lspCNG, xsp_tmp, M, grid100 );*/ + isp2lsp_fx( st_fx->lspCNG_fx, st_fx->lspCNG_fx, xsp_tmp, M); + + st_fx->old_enr_index_fx = s_min(shl(st_fx->old_enr_index_fx,1), 127 ); + + /* reset TD BWE buffers */ + set16_fx( st_fx->old_bwe_exc_fx, 0, PIT16k_MAX * 2 ); + set16_fx( st_fx->old_bwe_exc_extended_fx, 0, NL_BUFF_OFFSET ); + st_fx->bwe_non_lin_prev_scale_fx = 0; + move16(); + st_fx->last_voice_factor_fx = 0; + move16(); + + wb_tbe_extras_reset_fx( st_fx->mem_genSHBexc_filt_down_wb2_fx, st_fx->mem_genSHBexc_filt_down_wb3_fx ); + wb_tbe_extras_reset_synth_fx( st_fx->state_lsyn_filt_shb_fx, st_fx->state_lsyn_filt_dwn_shb_fx, st_fx->state_32and48k_WB_upsample_fx, st_fx->mem_resamp_HB_fx ); + + IF( GE_16(output_frame,L_FRAME32k)) + { + swb_tbe_reset_fx( st_fx->mem_csfilt_fx, st_fx->mem_genSHBexc_filt_down_shb_fx, st_fx->state_lpc_syn_fx, + st_fx->syn_overlap_fx, st_fx->state_syn_shbexc_fx, &st_fx->tbe_demph_fx, &st_fx->tbe_premph_fx + ,st_fx->mem_stp_swb_fx,&(st_fx->gain_prec_swb_fx) ); + set16_fx( st_fx->GainShape_Delay, 0, NUM_SHB_SUBFR/2 ); + swb_tbe_reset_synth_fx( st_fx->genSHBsynth_Hilbert_Mem_fx, st_fx->genSHBsynth_state_lsyn_filt_shb_local_fx ); + } + + IF( EQ_16(output_frame,L_FRAME48k)) + { + st_fx->prev_fb_ener_adjust_fx = 0; + move16(); + set16_fx( st_fx->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + st_fx->fb_tbe_demph_fx = 0; + fb_tbe_reset_synth_fx( st_fx->fbbwe_hpf_mem_fx, st_fx->fbbwe_hpf_mem_fx_Q,&st_fx->prev_fbbwe_ratio_fx ); + } + st_fx->prev_Energy_wb_fx = L_deposit_l(0); + st_fx->prev_weight_fx = 6554; + move16(); + + /* reset FD BWE buffers */ + st_fx->prev_mode_fx = NORMAL; + move16(); + st_fx->prev_Energy_fx = 0; + move16(); + st_fx->prev_L_swb_norm_fx = 8; + move16(); + st_fx->prev_frica_flag_fx = 0; + move16(); + set16_fx( st_fx->mem_imdct_fx, 0, L_FRAME48k ); + st_fx->prev_td_energy_fx = 0; + move16(); + set16_fx(st_fx->L_old_wtda_swb_fx, 0, L_FRAME48k ); + /* HQ core buffers */ + set16_fx( st_fx->delay_buf_out_fx, 0, HQ_DELTA_MAX*HQ_DELAY_COMP ); + + /* reset the unvoiced/audio signal improvement memories */ + st_fx->seed_tcx_fx = 15687; + move16(); + st_fx->UV_cnt_fx = 30; + move16(); + st_fx->LT_UV_cnt_fx = (60<<6); + move16(); + + st_fx->use_acelp_preq = 0; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + if(EQ_16(st_fx->last_flag_filter_NB, 1)) + st_fx->cldfbSyn_fx->bandsToZero = 0; + st_fx->last_active_bandsToZero_bwdec = 0; + st_fx->flag_NB_bwddec = 0; + st_fx->perc_bwddec = 0; + st_fx->last_flag_filter_NB = 0; + st_fx->active_frame_cnt_bwddec = 0; + set16_fx(st_fx->flag_buffer, 0, 20); + } + ELSE /* switching to AMR-WB IO mode */ + { + /* ISF Q memories */ + set16_fx( st_fx->mem_MA_fx, 0, M ); + + /* AMR-WB IO mode uses ISF(ISP), but EVS primary mode LSF(LSP) */ + Copy( stable_ISP_fx, xsp_tmp, M ); + lsf2isf_fx( st_fx->lsf_old_fx, st_fx->lsf_old_fx, xsp_tmp, M); + Copy( stable_ISP_fx, xsp_tmp, M ); + lsp2isp_fx( st_fx->lsp_old_fx, st_fx->lsp_old_fx, xsp_tmp, M); + + /* AMR-WB IO mode uses ISF(ISP), but EVS primary mode LSF(LSP) */ + Copy( stable_ISP_fx, xsp_tmp, M ); + lsp2isp_fx( st_fx->lspCNG_fx, st_fx->lspCNG_fx, xsp_tmp, M); + + st_fx->old_enr_index_fx = s_max(s_min(shr(st_fx->old_enr_index_fx, 1), 63 ),0); + + + /* gain quantization memory */ + set16_fx( st_fx->past_qua_en_fx, -14*1024, GAIN_PRED_ORDER ); + + /* HF synthesis memories */ + st_fx->Ng_ener_ST_fx = -51*256; /*Q8*/ move16(); + + hf_synth_amr_wb_reset_fx( &st_fx->seed2_fx, st_fx->mem_syn_hf_fx, st_fx->mem_hp_interp_fx, + &st_fx->prev_r_fx, &st_fx->fmerit_w_sm_fx, st_fx->delay_syn_hf_fx, &st_fx->frame_count_fx, + &st_fx->ne_min_fx, &st_fx->fmerit_m_sm_fx, &st_fx->voice_fac_amr_wb_hf, + &st_fx->unvoicing_fx, &st_fx->unvoicing_sm_fx, &st_fx->unvoicing_flag_fx, + &st_fx->voicing_flag_fx, &st_fx->start_band_old_fx, &st_fx->OptCrit_old_fx ); + + /* reset the unvoiced/audio signal improvement memories */ + st_fx->seed_tcx_fx = 15687; + move16(); + st_fx->UV_cnt_fx = 30; + move16(); + st_fx->LT_UV_cnt_fx = 60<<6; + move16(); + st_fx->Last_ener_fx = 0; + move16(); + st_fx->lt_voice_fac_fx = 0; + move16(); + + st_fx->psf_lp_noise_fx = round_fx(L_shl(st_fx->lp_noise,1)); + + /* reset VBR signalling */ + st_fx->last_ppp_mode_dec_fx = 0; + move16(); + st_fx->last_nelp_mode_dec_fx = 0; + move16(); + st_fx->ppp_mode_dec_fx = 0; + move16(); + st_fx->nelp_mode_dec_fx = 0; + move16(); + } + + /* CNG - reset */ + st_fx->ho_hist_size_fx = 0; + move16(); + + /* LSF Q memories */ + Copy( UVWB_Ave_fx, st_fx->mem_AR_fx, M ); + + /* FEC - update adaptive LSF mean vector */ + Copy( st_fx->lsf_old_fx, st_fx->lsfoldbfi0_fx, M ); + Copy( st_fx->lsf_old_fx, st_fx->lsfoldbfi1_fx, M ); + Copy( st_fx->lsf_old_fx, st_fx->lsf_adaptive_mean_fx, M ); + + return; +} + +/*-------------------------------------------------------------------* + * updt_bw_switching() + * + * Updates for BW switching + *-------------------------------------------------------------------*/ + +void updt_bw_switching_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + const Word16 *synth, /* i : float synthesis signal */ + const Word16 Qpost +) +{ + test(); + IF(st_fx->output_Fs_fx == 32000 && st_fx->bwidth_fx == SWB) + { + st_fx->tilt_swb_fx = round_fx(L_shl(calc_tilt_bwe_fx(synth, Qpost, L_FRAME32k), 3)); + } + + st_fx->prev_enerLH_fx = st_fx->enerLH_fx; + move32(); + st_fx->prev_enerLL_fx = st_fx->enerLL_fx; + move32(); + st_fx->last_bwidth_fx = st_fx->bwidth_fx; + move32(); + + IF( EQ_16(st_fx->core_fx, ACELP_CORE)) + { + st_fx->last_inner_frame_fx = L_FRAME32k; + move16(); + test(); + if( EQ_16(st_fx->bwidth_fx, WB)&&st_fx->bws_cnt_fx==0) + { + st_fx->last_inner_frame_fx = L_FRAME16k; + move16(); + } + + st_fx->prev_weight1_fx = 16384; + move16(); + if(EQ_16(st_fx->prev_mode_fx, HARMONIC)) + { + st_fx->prev_weight1_fx = 6554; + move16(); + } + } + ELSE + { + test(); + test(); + test(); + IF( !(GE_16(st_fx->last_inner_frame_fx, L_FRAME16k)&&LE_16(inner_frame_tbl[st_fx->bwidth_fx],L_FRAME16k)&&st_fx->bws_cnt_fx>0&<_16(st_fx->bws_cnt_fx,N_WS2N_FRAMES))) + { + st_fx->last_inner_frame_fx = inner_frame_tbl[st_fx->bwidth_fx]; + move16(); + } + + test(); + IF(GE_16(inner_frame_tbl[st_fx->bwidth_fx], L_FRAME32k)||LE_32(st_fx->core_brate_fx,HQ_16k40)) + { + st_fx->prev_weight1_fx = 16384; + move16(); + test(); + if(EQ_16(st_fx->prev_hqswb_clas_fx, HQ_HARMONIC)||EQ_16(st_fx->prev_hqswb_clas_fx,HQ_HVQ)) + { + st_fx->prev_weight1_fx = 6554; + move16(); + } + } + } + + return; +} + +/*-------------------------------------------------------------------* + * updt_dec_common() + * + * Common updates for MODE1 and MODE2 + *-------------------------------------------------------------------*/ + +void updt_dec_common_fx( + Decoder_State_fx *st_fx, /* i/o: decoder state structure */ + Word16 hq_core_type_fx, /* i : HQ core type */ + const Word16 *synth /* i : decoded synthesis */ +) +{ + + st_fx->last_codec_mode = st_fx->codec_mode; + move16(); + st_fx->last_extl_fx = st_fx->extl_fx; + move16(); + st_fx->last_L_frame_fx = st_fx->L_frame_fx; + move16(); + + st_fx->prev_old_bfi_fx = st_fx->prev_bfi_fx; + move16(); + st_fx->prev_bfi_fx = st_fx->bfi_fx; + move16(); + st_fx->old_bfi_cnt_fx = st_fx->nbLostCmpt; + move16(); + st_fx->last_con_tcx = st_fx->con_tcx; + move16(); + st_fx->con_tcx = 0; + + move16(); + st_fx->prev_last_core_fx = st_fx->last_core_fx; + + st_fx->tcxConceal_recalc_exc = 0; + move16(); + test(); + test(); + IF( (GE_16(st_fx->rf_frame_type,RF_TCXFD)&&LE_16(st_fx->rf_frame_type,RF_TCXTD2)&&st_fx->use_partial_copy&&st_fx->bfi_fx)||!st_fx->bfi_fx) + { + test(); + test(); + test(); + if( st_fx->bfi_fx && (LE_16(st_fx->last_good_fx, UNVOICED_TRANSITION))&&(GT_16(st_fx->clas_dec,UNVOICED_TRANSITION))&&st_fx->last_con_tcx) + { + st_fx->tcxConceal_recalc_exc = 1; + move16(); + } + st_fx->last_good_fx = st_fx->clas_dec; + move16(); + } + IF (st_fx->use_partial_copy) + { + st_fx->prev_rf_frame_type = st_fx->rf_frame_type; + } + ELSE + { + st_fx->prev_rf_frame_type = INACTIVE; + } + + if (EQ_16(st_fx->m_frame_type, ACTIVE_FRAME)&&(st_fx->bfi_fx!=1||st_fx->use_partial_copy!=0)) + { + st_fx->rf_flag_last = st_fx->rf_flag; + } + + IF( EQ_16(st_fx->codec_mode,MODE1)) + { + test(); + if( !st_fx->bfi_fx && st_fx->core_brate_fx > SID_2k40 ) + { + move16(); + st_fx->last_active_brate_fx = st_fx->total_brate_fx; + } + + move16(); + move16(); + st_fx->last_core_fx = st_fx->core_fx; + st_fx->last_hq_core_type_fx = hq_core_type_fx; + } + ELSE IF( EQ_16(st_fx->codec_mode,MODE2)) + { + test(); + if ((!st_fx->bfi_fx) && (st_fx->last_is_cng==0)) + { + move16(); + st_fx->last_active_brate_fx = st_fx->total_brate_fx; + } + /* INFO: moved from update_decoder_LPD_cng() */ + if (NE_16(st_fx->m_frame_type,ACTIVE_FRAME)) + { + move16(); + st_fx->last_is_cng = 1; + } + + + if (!st_fx->bfi_fx) + { + st_fx->last_core_fx = st_fx->core_fx; + } + move16(); + move16(); + st_fx->last_core_bfi = st_fx->core_fx; /* also required for clean channel decoding */ + } + move16(); + st_fx->last_core_brate_fx = st_fx->core_brate_fx; + + /* save synthesis for core switching */ + Copy_Scale_sig( synth + NS2SA_fx2(st_fx->output_Fs_fx,ACELP_LOOK_NS+DELAY_BWE_TOTAL_NS), st_fx->old_synth_sw_fx, NS2SA_fx2(st_fx->output_Fs_fx,FRAME_SIZE_NS-ACELP_LOOK_NS-DELAY_BWE_TOTAL_NS), st_fx->Q_old_postdec ); + + test(); + test(); + test(); + IF( ((LE_32(st_fx->core_brate_fx,SID_2k40))&&EQ_16(st_fx->cng_type_fx,FD_CNG)) + || (st_fx->tcxonly && EQ_16(st_fx->codec_mode,MODE2)) + ) + + { + /* reset LP memories */ + set16_fx( st_fx->mem_MA_fx,0, M ); + IF( EQ_32(st_fx->sr_core,16000)) + { + Copy( GEWB2_Ave_fx, st_fx->mem_AR_fx, M ); + } + ELSE + { + Copy( GEWB_Ave_fx, st_fx->mem_AR_fx, M ); + } + } + return; +} + + +void update_decoder_LPD_cng( Decoder_State_fx *st, Word16 coder_type, Word16 *timeDomainBuffer, Word16 *A, Word16 *bpf_noise_buf) +{ + Word16 i; + Word16 lsp[M], lsf[M]; + Word16 *synth, synth_buf[M+1+L_FRAME_MAX+L_FRAME_MAX/2], tmp; + Word16 buf_synth[OLD_SYNTH_SIZE_DEC+L_FRAME_MAX+M]; + Word16 pf_pitch[NB_SUBFR16k]; + Word16 pf_gain[NB_SUBFR16k]; + Word16 pitch[NB_SUBFR16k]; + + + /* LPC order */ + move16(); + + /* LPC -> LSP */ + E_LPC_a_lsp_conversion( A, lsp, st->lsp_old_fx, M ); + + /* LSP -> LSF */ + IF(EQ_16(st->L_frame_fx, L_FRAME16k)) + { + lsp2lsf_fx( lsp, lsf, M, INT_FS_16k_FX ); + } + ELSE + { + E_LPC_lsp_lsf_conversion( lsp, lsf, M ); + } + + + Copy( st->old_synth, buf_synth, st->old_synth_len ); + Copy( timeDomainBuffer, buf_synth+st->old_synth_len, st->L_frame_fx ); + + /* Update synth memory */ + + move16(); + synth = synth_buf + (1+M) ; + + Copy( st->syn, synth_buf, 1+M ); + Copy( timeDomainBuffer, synth, st->L_frame_fx ); + Copy( synth+st->L_frame_fx-(1+M), st->syn, 1+M ); + Copy( st->old_synth+st->L_frame_fx, st->old_synth, st->old_synth_len-st->L_frame_fx ); + Copy( synth, st->old_synth+st->old_synth_len-st->L_frame_fx, st->L_frame_fx ); + bufferCopyFx( synth+st->L_frame_fx-(st->L_frame_fx/2), st->old_syn_Overl, st->L_frame_fx/2,0 /*Qf_syn*/, -1 /*Qf_old_xnq*/, 0 , 0 /*Q_old_xnq*/); + + st->tcxltp_last_gain_unmodified = 0; + + /* Update pe-synth memory */ + move16(); + tmp = synth[-(1+M)]; + + st->Q_syn = E_UTIL_f_preemph3( synth-M, st->preemph_fac, M+st->L_frame_fx, &tmp, 1 ); + st->prev_Q_syn = st->Q_syn = st->Q_syn - 1; + Copy( synth+st->L_frame_fx-M, st->mem_syn2_fx, M ); + Copy( synth+st->L_frame_fx-L_SYN_MEM, st->mem_syn_r, L_SYN_MEM ); + + /* Update excitation memory */ + assert(st->L_frame_fx < L_EXC_MEM_DEC); + IF(NE_16(add(st->Q_syn,1),st->Q_exc)) + { + Scale_sig(st->old_exc_fx, L_EXC_MEM_DEC, sub(add(st->Q_syn,1),st->Q_exc)); + } + st->Q_exc = st->Q_syn + 1; + Copy( st->old_exc_fx+st->L_frame_fx, st->old_exc_fx, sub(L_EXC_MEM_DEC,st->L_frame_fx) ); + Residu3_fx( A, synth, st->old_exc_fx+L_EXC_MEM_DEC-st->L_frame_fx, st->L_frame_fx, 1 ); + + /* Update LPC-related memories */ + + Copy( lsp, st->lsp_old_fx, M ); + Copy( lsf, st->lsf_old_fx, M ); + Copy( lsp, st->lspold_uw, M ); + Copy( lsf, st->lsfold_uw, M ); + move16(); + move16(); + st->envWeighted = 0; + Copy( A, st->old_Aq_12_8_fx, M+1 ); + st->old_Es_pred_fx=0; + + /* Reset acelp memories */ + + move16(); + st->dm_fx.prev_gain_code = L_deposit_l(0); + set16_fx(st->dm_fx.prev_gain_pit, 0, 6); + st->dm_fx.prev_state = 0; + + move16(); + move16(); + st->tilt_code_fx = TILT_CODE; + st->gc_threshold_fx = 0; + + /* Update ace/tcx mode */ + st->core_fx = ACELP_CORE; + move16(); + move16(); + move16(); + st->last_is_cng = 1; + move16(); + + /* Reset TCX overlap */ + move16(); + move16(); + st->tcx_cfg.tcx_curr_overlap_mode = st->tcx_cfg.tcx_last_overlap_mode = ALDO_WINDOW; + + /* For BBWE and Postfilter */ + + Copy( A, &(st->mem_Aq[0]), M+1 ); + Copy( A, &(st->mem_Aq[(M+1)]), M+1 ); + Copy( A, &(st->mem_Aq[2*(M+1)]), M+1 ); + Copy( A, &(st->mem_Aq[3*(M+1)]), M+1 ); + IF( EQ_16(st->L_frame_fx, L_FRAME16k)) + { + Copy( A, &(st->mem_Aq[4*(M+1)]), M+1 ); + } + + /* Update for concealment */ + move16(); + move16(); + st->nbLostCmpt = 0; + st->prev_old_bfi_fx = 0; + + FOR (i=0; ilsf_adaptive_mean_fx[i] = add( mult_r(st->lsfoldbfi1_fx[i], 10923/*1.0f/3.0f Q15*/), add( mult_r(st->lsfoldbfi0_fx[i], 10923/*1.0f/3.0f Q15*/), mult_r(lsf[i], 10923/*1.0f/3.0f Q15*/) ) ); + st->lsfoldbfi1_fx[i] = st->lsfoldbfi0_fx[i]; + st->lsfoldbfi0_fx[i] = lsf[i]; + } + + set16_fx(pitch, shl(L_SUBFR, 6), NB_SUBFR16k); + + FEC_clas_estim_fx( + st, + /*Opt_AMR_WB*/0, /*A*/ + st->L_frame_fx, + &(st->clas_dec), + coder_type, + pitch, + synth, + &st->lp_ener_FER_fx, + /**decision_hyst*/NULL, /* i/o: hysteresis of the music/speech decision */ + /**UV_cnt*/ NULL, /* i/o: number of consecutives frames classified as UV */ + /**LT_UV_cnt*/ NULL, /* i/o: long term consecutives frames classified as UV */ + /**Last_ener*/ NULL, /* i/o: last_energy frame */ + /**locattack*/ NULL, /* i/o: detection of attack (mainly to localized speech burst) */ + /**lt_diff_etot*/NULL, /* i/o: long-term total energy variation */ + /**amr_io_class*/ NULL, /* i/o: classification for AMR-WB IO mode */ + /*bitrate*/ 0 , /* i : Decoded bitrate */ + st->Q_syn, /* i : Synthesis scaling */ + /**class_para*/ NULL, /* o : classification para. fmerit1 */ + st->mem_syn_clas_estim_fx, /* i/o: memory of the synthesis signal for frame class estimation */ + &st->classifier_Q_mem_syn, /*i/o : exponent for memory of synthesis signal for frame class estimation */ + -32768/*-1.f Q15*/, /* i : LTP Gain */ + 0/*CLASSIFIER_ACELP*/, /* i : signal classifier mode */ + 0/*bfi*/, /* i : bad frame indicator */ + st->last_core_brate_fx /* i : bitrate of previous frame */ + ); + + /* Postfiltering */ + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + pf_pitch[0] = pf_pitch[1] = pf_pitch[2] = pf_pitch[3] = pf_pitch[4] = L_SUBFR; + pf_gain[0] = pf_gain[1] = pf_gain[2] = pf_gain[3] = pf_gain[4] = 0; + st->bpf_gain_param=0; + move16(); + + post_decoder( st, coder_type, buf_synth, pf_gain, pf_pitch, timeDomainBuffer, bpf_noise_buf ); + + return; +} + diff --git a/lib_dec/vlpc_1st_dec.c b/lib_dec/vlpc_1st_dec.c new file mode 100644 index 0000000..a891e83 --- /dev/null +++ b/lib_dec/vlpc_1st_dec.c @@ -0,0 +1,30 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "prot_fx.h" +#include "stl.h" + +extern Word16 const dico_lsf_abs_8b[]; + +void vlpc_1st_dec( + Word16 index, /* input: codebook index */ + Word16 *lsfq) /* i/o: i:prediction o:quantized lsf */ +{ + Word16 i; + const Word16 *p_dico; + + + + assert(index < 256); + p_dico = &dico_lsf_abs_8b[index * M]; + FOR (i = 0; i < M; i++) + { + lsfq[i] = add(lsfq[i], *p_dico); + move16(); + p_dico++; + } + + +} diff --git a/lib_dec/vlpc_2st_dec.c b/lib_dec/vlpc_2st_dec.c new file mode 100644 index 0000000..8214da5 --- /dev/null +++ b/lib_dec/vlpc_2st_dec.c @@ -0,0 +1,59 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "prot_fx.h" +#include "stl.h" + +void vlpc_2st_dec( + Word16 *lsfq, /* i/o: i:1st stage o:1st+2nd stage */ + Word16 *indx, /* input: index[] (4 bits per words) */ + Word16 mode, /* input: 0=abs, >0=rel */ + Word32 sr_core) +{ + Word16 i; + Word16 w[M]; + Word16 xq[M]; + Word16 gap; + + + + /* weighting from the 1st stage */ + lsf_weight_2st(lsfq, w, mode); + + /* quantize */ + AVQ_dec_lpc(indx, xq, 2); + + /* quantized lsf */ + + FOR (i=0; i +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "log2.h" +#include "stl.h" + +/*===================================================================*/ +/* FUNCTION : void ppp_voiced_decoder_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ Word16 bfi_fx - Q0 bad frame indicator */ +/* _ const Word16 *lpc2_fx - Q12 current frame LPC */ +/* _ Word16 *exc_fx - Q0 previous frame excitation */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ Decoder_State_fx *st_fx: */ +/* _ lastLgainD_fx - Q11 */ +/* _ lastHgainD_fx - Q11 */ +/* _ lasterbD_fx - Q13 */ +/* _ Word16 *pitch - Q6 floating pitch values for each subframe */ +/* _ Word16 *out_fx - Q0 residual signal */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ Decoder_State_fx *st_fx: */ +/* _ lsp_old_fx - Q15 */ +/* _ st_fx->dtfs_dec_xxxx */ +/* _ a nd b in st_fx->dtfs_dec_Q */ +/* rest all in Q0 */ +/* _ gainp_ppp Q14 */ +/* _ Word16 *pitch_buf_fx - Q6 fixed pitch values for each subframe */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : RX */ +/*===================================================================*/ +void ppp_voiced_decoder_fx( + Decoder_State_fx *st_fx, /* i/o: state structure */ + Word16 *out_fx, /* o : residual signal */ + const Word16 *lpc2_fx, /* i : current frame LPC */ + Word16 *exc_fx, /* i : previous frame excitation */ + Word16 *pitch, /* o : floating pitch values for each subframe */ + Word16 bfi /* i : Frame error rate */ +) +{ + Word16 k, delta_lag_D = 0,temp,Ql,Qh,diff; + Word16 upper_cut_off_freq_of_interest = 0, upper_cut_off_freq = 0; + Word16 pl, l,n,rem_fx; + Word16 temp_l_fx, temp_pl_fx,interp_delay_fx[3]; + Word32 logLag,Ltemp_q,Ltemp,rem32,temp32_fx,tempnH_fx; + Word16 exp,tmp; + Word32 L_tmp; + + DTFS_STRUCTURE_FX *TMPDTFS_FX = DTFS_new_fx(); + DTFS_STRUCTURE_FX *CURRP_Q_D_FX = DTFS_new_fx(); + + DTFS_STRUCTURE_FX *dtfs_temp_fx = DTFS_new_fx(); + + Word16 pf_temp1[MAXLAG_WI]; /*maynot need more than MAXLAG_WI/2+1 */ + Word16 pf_temp2[MAXLAG_WI]; + Word16 pf_temp[MAXLAG_WI]; + Word16 pf_n2[MAXLAG_WI]; + Word16 S_fx[4*PIT_MAX+1], C_fx[4*PIT_MAX+1]; + Word16 temp_Fs; + + test(); + IF (EQ_16(st_fx->bwidth_fx,WB)||EQ_16(st_fx->bwidth_fx,SWB)) + { + upper_cut_off_freq_of_interest = 0x2800; + move16();/*4000 normalized to 12800 in Q15 */ + upper_cut_off_freq = 0x4000; + move16();/*6400 normalized to 12800 in Q15 */ + } + ELSE IF (EQ_16(st_fx->bwidth_fx,NB)) + { + upper_cut_off_freq_of_interest = 0x2100; + move16();/*3300 normalized to 12800 in Q15 */ + upper_cut_off_freq = 0x2800; + move16(); + } + + temp_Fs = 8000; + + if ( EQ_16( st_fx->bwidth_fx, WB)) + { + temp_Fs = 16000; + move16(); + } + + + + /* Initialization */ + IF (st_fx->firstTime_voiceddec_fx) + { + st_fx->firstTime_voiceddec_fx=0; + move16(); + + /* (st_fx->PREV_CW_D) = DTFS_new();*/ + st_fx->dtfs_dec_lag_fx = 0; + move16(); + st_fx->dtfs_dec_nH_fx = 0; + move16(); + st_fx->dtfs_dec_nH_4kHz_fx = 0; + move16(); + st_fx->dtfs_dec_upper_cut_off_freq_of_interest_fx = 3300; + move16(); + st_fx->dtfs_dec_upper_cut_off_freq_fx = 4000; + move16(); + + FOR(k = 0; k < MAXLAG_WI; k++) + { + st_fx->dtfs_dec_a_fx[k] = 0; + move16(); + st_fx->dtfs_dec_b_fx[k] = 0; + move16(); + } + st_fx->dtfs_dec_Q = 0; + move16(); + } + + pl = s_min(rint_new_fx(st_fx->old_pitch_buf_fx[(2*NB_SUBFR)-1]),MAX_LAG_PIT); + delta_lag_D = (Word16) get_next_indice_fx( st_fx, 5 ); + + + l = s_min(MAX_LAG_PIT,add(pl,sub(delta_lag_D,11))); + + + temp_pl_fx = pl; + move16(); + temp_l_fx = l; + move16(); + + IF (NE_16(temp_pl_fx,temp_l_fx)) + { + FOR(k=0; klast_coder_type_fx,UNVOICED)) + { + pl = l; + move16(); /* if prev frame was sil/uv*/ + } + + temp = mult(shl(l,3),30310);/*Q3+14+1-16 = Q2 30310 is 1.85 in Q14 */ + + IF( temp >= 0 ) + { + temp = add(temp,2); + } + ELSE + { + temp = sub(temp,2); + } + temp = shr(temp,2);/*Q0 */ + + if (GT_16(pl,temp)) + { + pl = shr(pl,1); + } + + temp = mult(shl(l,3),8857);/*Q3+14+1-16 = Q2 8847 is 0.54 in Q14 */ + IF( temp >= 0 ) + { + temp = add(temp,2); + } + ELSE + { + temp = sub(temp,2); + } + temp = shr(temp,2);/*Q0 */ + + test(); + if (LE_16(shl(pl,1),PIT_MAX)&&LE_16(pl,temp)) + { + pl = shl(pl,1); + } + + /* Restoring PPP memories when the last frame is non-PPP or full-rate PPP */ + IF (NE_16(st_fx->last_ppp_mode_dec_fx,1)) + { + + GetSinCosTab_fx(pl, S_fx, C_fx); + DTFS_to_fs_fx(exc_fx-pl, pl, dtfs_temp_fx, temp_Fs, 0, S_fx, C_fx); + + st_fx->ph_offset_D_fx = 0 ; + move16(); + + /* Copy over PREV_CW_D into TMPDTFS */ + DTFS_copy_fx(TMPDTFS_FX, *dtfs_temp_fx); + + DTFS_car2pol_fx(TMPDTFS_FX); + + /*st_fx->lastLgainD = (float) log10(TMPDTFS->lag*DTFS_setEngyHarm(92.0,1104.5,0.0,1104.5,1.0,TMPDTFS)); */ + + L_tmp = L_deposit_h(TMPDTFS_FX->lag_fx);/*Q16 */ + exp = norm_l(L_tmp); + tmp = Log2_norm_lc(L_shl(L_tmp,exp)); + exp = (30-exp-16); + L_tmp = Mpy_32_16(exp,tmp,12330);/* Q13 */ /* 10*log10(2) in Q12*/ + logLag = L_shl(L_tmp, 10);/*Q23 */ + + Ltemp_q=L_shl(L_mult(shl(TMPDTFS_FX->Q,1),24660),9); /* Ltemp_q=2Q*10log10(2), Q23 */ + /* Process low band */ + Ltemp=DTFS_setEngyHarm_fx(236,2828,0,2828,1,0,&Ql,TMPDTFS_FX);/* Ltemp in 2*TMP.Q */ + /* Compensate for Q factor of energy to get log10(lag*eng) */ + + + Ltemp=log10_fx(Ltemp); /* Ltemp=10log10(eng), Q23 */ + Ltemp=L_add(L_sub(Ltemp,Ltemp_q),logLag); /* Ltemp=10*log10(lag*eng), Q23 */ + st_fx->lastLgainD_fx=round_fx(L_shl((Word32)Mpy_32_16(extract_h(Ltemp),extract_l(Ltemp),0x6666),1)); /* Q11 */ + + + + /* Process high band */ + Ltemp=DTFS_setEngyHarm_fx(2828,upper_cut_off_freq_of_interest,2828,upper_cut_off_freq,1,0,&Qh,TMPDTFS_FX); + + + Ltemp=log10_fx(Ltemp); + Ltemp=L_add(L_sub(Ltemp,Ltemp_q),logLag); /* Ltemp=10*log10(lag*eng), Q23 */ + st_fx->lastHgainD_fx=round_fx(L_shl((Word32)Mpy_32_16(extract_h(Ltemp),extract_l(Ltemp),0x6666),1)); /* Q11 */ + + + /* Need to unify the Q factors of both bands */ + TMPDTFS_FX->Q=s_min(Ql,Qh); /* set Q factor to be the smaller one */ + n=sub(Ql,Qh); /* compare band Q factors */ + + /*This logic adjusts difference between Q formats of both bands */ + IF (n<0) + { + rshiftHarmBand_fx(TMPDTFS_FX,2828, upper_cut_off_freq,n); + } + ELSE IF (n>0) + { + rshiftHarmBand_fx(TMPDTFS_FX,0, 2828, sub(Qh,Ql)); + } + + DTFS_to_erb_fx(*TMPDTFS_FX,st_fx->lasterbD_fx); + + } + ELSE + { + /* Copy DTFS related parameters from 'st' to 'dtfs_temp' structure */ + dtfs_temp_fx->lag_fx = st_fx->dtfs_dec_lag_fx; + move16(); + dtfs_temp_fx->nH_fx = st_fx->dtfs_dec_nH_fx; + move16(); + dtfs_temp_fx->nH_4kHz_fx = st_fx->dtfs_dec_nH_4kHz_fx; + move16(); + dtfs_temp_fx->upper_cut_off_freq_of_interest_fx = st_fx->dtfs_dec_upper_cut_off_freq_of_interest_fx; + move16(); + dtfs_temp_fx->upper_cut_off_freq_fx = st_fx->dtfs_dec_upper_cut_off_freq_fx; + move16(); + + Copy(st_fx->dtfs_dec_a_fx, dtfs_temp_fx->a_fx, MAXLAG_WI); + Copy(st_fx->dtfs_dec_b_fx, dtfs_temp_fx->b_fx, MAXLAG_WI); + dtfs_temp_fx->Q = st_fx->dtfs_dec_Q; + move16(); + } + + CURRP_Q_D_FX->lag_fx = l; + move16(); + + /* safety check in case of bit errors */ + IF( CURRP_Q_D_FX->lag_fx <= 0 ) + { + CURRP_Q_D_FX->lag_fx = 1; + move16(); + st_fx->BER_detect = 1; + move16(); + } + + /* compute nH for lag */ + Ltemp = L_shl((Word32)upper_cut_off_freq,13);/*Q28 */ + upper_cut_off_freq = (Word16)find_remd(Ltemp, 20971,&rem32);/*denormalize upper_cut_off_freq */ + + + + /* temp32_fx = (Word32)divide_dp((Word40)819200,(Word40)L_shl((Word32)CURRP_Q_D_FX->lag_fx,6),-23,1);//Q6 */ + exp = norm_s(CURRP_Q_D_FX->lag_fx); + tmp = div_s(shl(1,sub(14,exp)),CURRP_Q_D_FX->lag_fx);/*29-exp */ + L_tmp =L_shl(L_mult0(tmp,12800),exp - 7); + temp32_fx = round_fx(L_tmp); + diff = round_fx(L_shl(temp32_fx,16-6));/*Q0 */ + + CURRP_Q_D_FX->nH_fx = find_rem(upper_cut_off_freq,diff,&rem_fx);/*Q0 */ + + exp = norm_s(diff); + tmp = div_s(shl(1,sub(14,exp)),diff);/*29-exp */ + L_tmp = L_shl(L_mult0(4000,tmp),exp - 7); + tempnH_fx = extract_h(L_tmp); + CURRP_Q_D_FX->nH_4kHz_fx = round_fx(L_shl(tempnH_fx,16-6));/*Q0 */ + + + IF(GE_16(sub(upper_cut_off_freq,shr((Word16)L_mult(diff,CURRP_Q_D_FX->nH_fx),1)),diff)) + { + CURRP_Q_D_FX->nH_fx = add(CURRP_Q_D_FX->nH_fx,1); + } + tempnH_fx = L_mult0(extract_l(temp32_fx),CURRP_Q_D_FX->nH_4kHz_fx);/* */ + tempnH_fx = L_sub((Word32)256000,tempnH_fx);/*Q6 */ + + if(GE_32(tempnH_fx,temp32_fx)) + { + CURRP_Q_D_FX->nH_4kHz_fx = add(CURRP_Q_D_FX->nH_4kHz_fx,1); + } + + CURRP_Q_D_FX->upper_cut_off_freq_fx = dtfs_temp_fx->upper_cut_off_freq_fx; + move16(); + CURRP_Q_D_FX->upper_cut_off_freq_of_interest_fx = dtfs_temp_fx->upper_cut_off_freq_of_interest_fx; + move16(); + GetSinCosTab_fx(CURRP_Q_D_FX->lag_fx,S_fx,C_fx); + + IF ( bfi == 0 ) + { + ppp_quarter_decoder_fx(CURRP_Q_D_FX,dtfs_temp_fx->lag_fx,&(st_fx->lastLgainD_fx), + &(st_fx->lastHgainD_fx),st_fx->lasterbD_fx,bfi,S_fx,C_fx,*dtfs_temp_fx, st_fx); + } + + WIsyn_fx(*dtfs_temp_fx, CURRP_Q_D_FX, lpc2_fx, &(st_fx->ph_offset_D_fx), out_fx, (Word16)L_FRAME, 0, + S_fx, C_fx, pf_temp1, pf_temp2, pf_temp, pf_n2); + + DTFS_copy_fx(dtfs_temp_fx, *CURRP_Q_D_FX); + + /* Copy DTFS related parameters from 'dtfs_temp' to 'st' structure */ + st_fx->dtfs_dec_lag_fx = dtfs_temp_fx->lag_fx; + move16(); + st_fx->dtfs_dec_nH_fx = dtfs_temp_fx->nH_fx; + move16(); + st_fx->dtfs_dec_nH_4kHz_fx = dtfs_temp_fx->nH_4kHz_fx; + move16(); + st_fx->dtfs_dec_upper_cut_off_freq_of_interest_fx = dtfs_temp_fx->upper_cut_off_freq_of_interest_fx; + move16(); + st_fx->dtfs_dec_upper_cut_off_freq_fx = dtfs_temp_fx->upper_cut_off_freq_fx; + move16(); + + Copy(dtfs_temp_fx->a_fx, st_fx->dtfs_dec_a_fx, MAXLAG_WI); + Copy(dtfs_temp_fx->b_fx, st_fx->dtfs_dec_b_fx, MAXLAG_WI); + + st_fx->dtfs_dec_Q = dtfs_temp_fx->Q; + move16(); + + free(TMPDTFS_FX); + free(CURRP_Q_D_FX); + free(dtfs_temp_fx); + + return; +} diff --git a/lib_dec/voip_client.c b/lib_dec/voip_client.c new file mode 100644 index 0000000..1fc17ec --- /dev/null +++ b/lib_dec/voip_client.c @@ -0,0 +1,372 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include +#include +#include "options.h" +#include "stl.h" +#include "prot_fx.h" +#include "cnst_fx.h" +#include "basop_util.h" +#include "EvsRXlib.h" +#include "g192.h" +#include "evs_rtp_payload.h" + + +/*------------------------------------------------------------------------------------------* + * Global variables + *------------------------------------------------------------------------------------------*/ +extern long frame; /* Counter of frames */ + +/*------------------------------------------------------------------------------------------* + * Local constants + *------------------------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------------------------* + * decodeVoip() + * + * Main function for EVS decoder with VOIP mode + *------------------------------------------------------------------------------------------*/ + +Word16 decodeVoip( + Decoder_State_fx *st_fx, + FILE *f_stream, + FILE *f_synth, +#ifdef SUPPORT_JBM_TRACEFILE + const char *jbmTraceFileName, +#endif + const char *jbmFECoffsetFileName, /* : Output file for Optimum FEC offset */ + const Word16 quietMode +) +{ + /* input/output */ + G192_HANDLE g192 = NULL; + G192_ERROR g192err; + EVS_RTPDUMP_DEPACKER rtpdumpDepacker; + EVS_RTPDUMP_DEPACKER_ERROR rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_NO_ERROR; + + Word16 optimum_offset, FEC_hi; + FILE *f_offset = 0; + + /* main loop */ + Word32 nextPacketRcvTime_ms = 0; + Word32 systemTime_ms = 0; + Word32 nFramesFed = 0; + + EVS_RX_HANDLE hRX = NULL; + EVS_RX_ERROR rxerr = EVS_RX_NO_ERROR; + Word16 jbmSafetyMargin = 60; /* allowed delay reserve in addition to network jitter to reduce late-loss [milliseconds] */ + Word16 dec_delay, zero_pad; + + unsigned char au[2560]; + Word16 auSize; + unsigned char *auPtr = NULL; + bool isAMRWB_IOmode; + uint16_t frameTypeIndex; + bool qBit; + Word16 rtpSequenceNumber; + Word32 rtpTimeStamp; + + Word16 pcmBuf[3 * L_FRAME48k] = {0}; + Word16 pcmBufSize = 3 * L_FRAME48k; + + rtpdumpDepacker.rtpdump = NULL; + if( st_fx->bitstreamformat == VOIP_RTPDUMP ) + { + rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_open(&rtpdumpDepacker, f_stream, st_fx->sdp_hf_only != 0); + if(rtpdumpDepackerError != EVS_RTPDUMP_DEPACKER_NO_ERROR) + { + fprintf(stderr,"error in EVS_RTPDUMP_DEPACKER_open(): %d\n", rtpdumpDepackerError); + return -1; + } + g192err = G192_NO_ERROR; + } + else + { + assert( st_fx->bitstreamformat == VOIP_G192_RTP ); + /* open input file */ + g192err = G192_Reader_Open(&g192, f_stream); + if(g192err != G192_NO_ERROR) + { + fprintf(stderr,"error in G192_Reader_Open(): %d\n", g192err); + return -1; + } + auPtr = au; + } + + if(jbmFECoffsetFileName) + { + f_offset = fopen( jbmFECoffsetFileName, "w+" ); + if(f_offset == NULL) + { + fprintf(stderr,"unable to open CA offset file: %s\n", jbmFECoffsetFileName); + G192_Reader_Close(&g192); + EVS_RTPDUMP_DEPACKER_close(&rtpdumpDepacker); + return -1; + } + } + + /* initialize receiver */ + rxerr = EVS_RX_Open(&hRX, st_fx, jbmSafetyMargin); + if(rxerr) + { + fprintf(stderr,"unable to open receiver\n"); + G192_Reader_Close(&g192); + EVS_RTPDUMP_DEPACKER_close(&rtpdumpDepacker); + if( f_offset ) + { + fclose(f_offset); + } + return -1; + } +#ifdef SUPPORT_JBM_TRACEFILE + rxerr = EVS_RX_SetJbmTraceFileName(hRX, jbmTraceFileName); + if(rxerr) + { + fprintf(stderr,"unable to set JBM trace file: %s\n", jbmTraceFileName); + G192_Reader_Close(&g192); + EVS_RTPDUMP_DEPACKER_close(&rtpdumpDepacker); + if( f_offset ) + { + fclose(f_offset); + } + EVS_RX_Close(&hRX); + return -1; + } +#endif + + /* calculate the delay compensation to have the decoded signal aligned with the original input signal */ + /* the number of first output samples will be reduced by this amount */ + dec_delay = NS2SA_fx2(st_fx->output_Fs_fx, get_delay_fx(DEC, st_fx->output_Fs_fx)); + zero_pad = dec_delay; + + /* start WMOPS counting for decoding process only */ + BASOP_end_noprint + BASOP_init + + if (st_fx->bitstreamformat == VOIP_G192_RTP) + { + /* read first packet */ + g192err = G192_ReadVoipFrame_compact(g192, au, &auSize, + &rtpSequenceNumber, &rtpTimeStamp, &nextPacketRcvTime_ms); + if (!evsPayload_getFrameTypeFromSize(auSize, &isAMRWB_IOmode, &frameTypeIndex)) + { + g192err = G192_INVALID_DATA; + } + qBit = 1; /* good q_bit for VOIP_G192_RTP */ + } + else { + auPtr = au; /* might have been set to RTP packet in prev call */ + rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_readNextFrame(&rtpdumpDepacker, (uint16_t*)&rtpSequenceNumber, (uint32_t*)&rtpTimeStamp, + (uint32_t*)&nextPacketRcvTime_ms, + &isAMRWB_IOmode, &frameTypeIndex, &qBit, + &auPtr, (uint16_t*)&auSize); + /* EVS RTP payload format has timescale 16000, JBM uses 1000 internally */ + rtpTimeStamp = rtpTimeStamp / 16; + } + if(g192err != G192_NO_ERROR || rtpdumpDepackerError != EVS_RTPDUMP_DEPACKER_NO_ERROR) + { + fprintf(stderr,"failed to read first RTP packet\n"); + G192_Reader_Close(&g192); + EVS_RTPDUMP_DEPACKER_close(&rtpdumpDepacker); + if( f_offset ) + { + fclose(f_offset); + } + EVS_RX_Close(&hRX); + return -1; + } + + if( quietMode == 0 ) + { + fprintf( stdout, "\n------ Running the decoder ------\n\n" ); + fprintf( stdout, "Frames processed: " ); + } + else + { + fprintf( stdout, "\n-- Start the decoder (quiet mode) --\n\n" ); + } + + /* main receiving/decoding loop */ + for( ; ; ) + { + Word16 nSamples = 0; +#if (WMOPS) + fwc(); + Reset_WMOPS_counter(); +#endif + + /* read all packets with a receive time smaller than the system time */ + while( nextPacketRcvTime_ms != -1 && nextPacketRcvTime_ms <= systemTime_ms ) + { + /* feed the previous read packet into the receiver now */ + rxerr = EVS_RX_FeedFrame(hRX, auPtr, auSize, rtpSequenceNumber, rtpTimeStamp, + nextPacketRcvTime_ms, isAMRWB_IOmode, frameTypeIndex, qBit); + if (rxerr != EVS_RX_NO_ERROR) + { + printf("\nerror in feeding access unit: %8x", rxerr); + G192_Reader_Close(&g192); + EVS_RTPDUMP_DEPACKER_close(&rtpdumpDepacker); + if( f_offset ) + { + fclose(f_offset); + } + EVS_RX_Close(&hRX); + return -1; + } + ++nFramesFed; + /* read the next packet */ + if (st_fx->bitstreamformat == VOIP_G192_RTP) { + g192err = G192_ReadVoipFrame_compact(g192, au, &auSize, + &rtpSequenceNumber, &rtpTimeStamp, &nextPacketRcvTime_ms); + if (!evsPayload_getFrameTypeFromSize(auSize, &isAMRWB_IOmode, &frameTypeIndex)) + { + g192err = G192_INVALID_DATA; + } + qBit = 1; /* good q_bit for VOIP_G192_RTP */ + } + else { + auPtr = au; /* might have been set to RTP packet in prev call */ + rtpdumpDepackerError = EVS_RTPDUMP_DEPACKER_readNextFrame(&rtpdumpDepacker, (uint16_t*)&rtpSequenceNumber, (uint32_t*)&rtpTimeStamp, + (uint32_t*)&nextPacketRcvTime_ms, + &isAMRWB_IOmode, &frameTypeIndex, &qBit, + &auPtr, (uint16_t*)&auSize); + /* EVS RTP payload format has timescale 16000, JBM uses 1000 internally */ + rtpTimeStamp = rtpTimeStamp / 16; + } + if(g192err == G192_EOF + || rtpdumpDepackerError == EVS_RTPDUMP_DEPACKER_EOF + ) + { + /* finished reading */ + nextPacketRcvTime_ms = -1; + } + else if(g192err != G192_NO_ERROR + || rtpdumpDepackerError != EVS_RTPDUMP_DEPACKER_NO_ERROR + ) + { + fprintf(stderr,"failed to read RTP packet\n"); + G192_Reader_Close(&g192); + EVS_RTPDUMP_DEPACKER_close(&rtpdumpDepacker); + if( f_offset ) + { + fclose(f_offset); + } + EVS_RX_Close(&hRX); + return -1; + } + } + + /* we are finished when all packets have been received and jitter buffer is empty */ + /* also stop when the input file contains less than two frames, because JBM cannot calculate a delay value and won't start decoding */ + if( nextPacketRcvTime_ms == -1 && ( EVS_RX_IsEmpty(hRX) || nFramesFed < 2 ) ) + break; + + /* decode and get samples */ + rxerr = EVS_RX_GetSamples(hRX, &nSamples, pcmBuf, pcmBufSize, systemTime_ms); + + EVS_RX_Get_FEC_offset(hRX, &optimum_offset, &FEC_hi); + + if ( st_fx->writeFECoffset == 1 && f_offset ) + { + if ( FEC_hi == 1) + { + fprintf( f_offset, "HI " ); + } + else + { + fprintf( f_offset, "LO " ); + } + + if ( optimum_offset == 1 || optimum_offset == 2 ) + { + optimum_offset =2; + } + else if ( optimum_offset == 3 || optimum_offset == 4 ) + { + optimum_offset = 3; + } + else if ( optimum_offset == 5 || optimum_offset == 6 ) + { + optimum_offset = 5; + } + else if ( optimum_offset >= 7) + { + optimum_offset = 7; + } + + fprintf( f_offset, "%d\n", optimum_offset ); + } + + + if(rxerr != EVS_RX_NO_ERROR) + { + printf("\nerror in getting samples: %8x", rxerr); + G192_Reader_Close(&g192); + EVS_RTPDUMP_DEPACKER_close(&rtpdumpDepacker); + if( f_offset ) + { + fclose(f_offset); + } + EVS_RX_Close(&hRX); + return -1; + } + + /* write the synthesized signal into output file */ + /* do final delay compensation */ + IF ( dec_delay == 0 ) + { + fwrite( pcmBuf, sizeof(Word16), nSamples, f_synth ); + } + ELSE + { + IF ( LE_16(dec_delay, nSamples)) + { + fwrite( pcmBuf + dec_delay, sizeof(Word16), sub(nSamples, dec_delay), f_synth ); + dec_delay = 0; + move16(); + } + ELSE + { + dec_delay = sub(dec_delay, nSamples); + } + } + frame++; + if( quietMode == 0 ) + { + fprintf( stdout, "%-8ld\b\b\b\b\b\b\b\b", frame ); + } + systemTime_ms += 20; + } + + /* add zeros at the end to have equal length of synthesized signals */ + set16_fx( pcmBuf, 0, zero_pad ); + fwrite( pcmBuf, sizeof(Word16), zero_pad, f_synth ); + + if( quietMode == 0 ) + { + fprintf( stdout, "\n\n" ); + fprintf( stdout, "Decoding finished\n\n" ); + } + else + { + fprintf( stdout, "Decoding of %ld frames finished\n\n", frame ); + } + + /* end of WMOPS counting */ + BASOP_end + + /* free memory etc. */ + BASOP_init + G192_Reader_Close(&g192); + EVS_RTPDUMP_DEPACKER_close(&rtpdumpDepacker); + EVS_RX_Close(&hRX); + BASOP_end_noprint + return 0; +} + diff --git a/lib_dec/waveadjust_fec_dec.c b/lib_dec/waveadjust_fec_dec.c new file mode 100644 index 0000000..8cd6734 --- /dev/null +++ b/lib_dec/waveadjust_fec_dec.c @@ -0,0 +1,1602 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include +#include "prot_fx.h" +#include "basop_util.h" +#include "stat_com.h" +#include "stl.h" /* FOR wmc_tool */ + +void get_maxConv_and_pitch_x(Word16 *s_LP, Word16 s, Word16 e, Word16 N, + Word32 *maxConv, Word16 *maxConv_bits, Word16 *pitch); +Word16 get_voicing_x(Word16 *s_LP, Word16 pitch, Word32 covMax,Word16 maxConv_bits, Word16 Framesize); +Word32 con_Log10(Word32 i_s32Val, Word16 i_s16Q); + + +Word16 vadmin(Word16 a, Word16 b) +{ + return s_min(a, b); +} + +void set_state(Word16 *state, Word16 num, Word16 N) +{ + Word16 i, tmp; + + tmp = sub(N, 1); + FOR (i = 0; i < tmp; i++) + { + state[i] = state[i+1]; + move16(); + } + state[tmp] = num; + move16(); +} + +void concealment_update_x(Word16 bfi, Word16 curr_mode, Word16 tonality, Word32 *invkoef, Word16 *invkoef_scale, void *_plcInfo) +{ + T_PLCInfo *plcInfo = (T_PLCInfo*)_plcInfo; + Word32 *data_reci2 = plcInfo->data_reci2_fx; + Word16 *tcx_tonality = plcInfo->TCX_Tonality; + Word16 FrameSize = plcInfo->FrameSize; + Word16 subframe = plcInfo->subframe_fx; + Word16 i; + move16(); + move16(); + IF (EQ_16(curr_mode ,1)) + { + set_state(plcInfo->Transient, curr_mode, MAX_POST_LEN); + + FOR (i = 0; i < FrameSize; i++) + { + data_reci2[i] = invkoef[i]; + move32(); + + } + plcInfo->data_reci2_scale = *invkoef_scale; + move16(); + IF (!bfi) + { + set_state(tcx_tonality, tonality, DEC_STATE_LEN); + } + } + ELSE + { + + IF (EQ_16(subframe,0)) + { + set_state(plcInfo->Transient, curr_mode, MAX_POST_LEN); + + IF (!bfi) + { + set_state(tcx_tonality, tonality, DEC_STATE_LEN); + } + } + /* don't store the second subframe during frameloss; in + pitch_search_fx(), low_freq_rate is derived on the last good + TCX-10 spectrum */ + test(); + IF (!bfi || EQ_16(subframe,0)) + { + + Word32 *ptr = data_reci2+subframe; + Word16 FrameSize2 = shr(FrameSize,1); + + FOR (i = 0; i < FrameSize2; i++) + { + ptr[i] = invkoef[i]; + move32(); + } + + plcInfo->data_reci2_scale = *invkoef_scale; + move16(); + } + } + return; +} + +static Word16 zero_pass_w32_x(Word16 *s, Word16 N) +{ + Word16 i; + Word32 temp, zp = L_deposit_l(0); + + FOR (i = 1; i < N; i++) + { + temp = L_mac0(-1L, s[i],s[i-1]); + zp = L_sub(zp, L_shr(temp,31)); + } + return extract_l(zp); +} + +Word16 Sqrt_x_fast(Word32 value) +{ + Word16 norm; + Word16 result, index; + + norm = sub(23, norm_l(value)); + index = extract_l( L_shr_r(value, add(norm, s_and(norm, 1)))); + result = shr(sqrt_table_pitch_search[index], sub(11, shr(add(norm,1),1))); + return result; +} + +Word32 dot_w32_accuracy_x(Word16 *s1, Word16 *s2, Word16 nbits, Word16 N) +{ + Word16 i; + Word32 eng = L_deposit_l(0), temp; + + FOR (i = 0; i < N; i++) + { + temp = L_mult0(s1[i], s2[i]); + eng = L_add(eng, L_shr(temp,nbits)); + } + + return eng; +} + + +Word16 int_div_s_x(Word16 a, Word16 b) +{ + Word16 result = 0; + Word16 norm, left=0, i; + move16(); + move16(); + test(); + IF (LT_16(a,b)||b==0) + { + return 0; + } + ELSE + { + a = add(a, shr(b,1)); + norm = sub(norm_s(b),norm_s(a)); + + FOR (i = norm; i>= 0; i--) + { + left = shr(a, i); + result = shl(result,1); + IF (GE_16(left,b)) + { + result = add(result,1); + left= sub(left, b); + a = add(shl(left,i), s_and(a, sub(shl(1,i),1))); + } + } + } + + return result; +} + +Word16 GetW32Norm_x(Word32 *s, Word16 N) +{ + Word32 smax = L_deposit_l(0); + Word16 smax_norm, i; + + FOR (i = 0; i < N; i++) + { + smax = L_or(smax, L_abs(s[i])); + } + + smax_norm = norm_l(smax); + + return smax_norm; +} + +Word16 harmo_x(Word32 *X, Word16 Framesize, Word16 pitch) +{ + Word16 h, k, result = 0; + Word32 ener = L_deposit_l(0), ener_harmo = L_deposit_l(0); + Word16 norm1, d1, d2; + Word16 ener_w, ener_harmo_w; + Word16 nbits = sub(15, norm_s(Framesize)); + move16(); + norm1 = GetW32Norm_x(X, Framesize); + + FOR (k = 1; k < 9; k++) + { + h = sub(int_div_s_x(extract_l(L_mult(k, Framesize)), pitch),1); + + d1 = extract_h(L_shl(X[h], norm1)); + d2 = extract_h(L_shl(X[h+1],norm1)); + + ener_harmo = L_add(ener_harmo, + L_shr(L_mac0(L_mult0(d1, d1), d2, d2),nbits)); + } + + FOR (k = 0; k < Framesize; k++) + { + d1 = extract_h(L_shl(X[k],norm1)); + ener = L_add(ener, L_shr(L_mult0(d1, d1),nbits)); + } + + norm1 = norm_l(ener); + ener_w = extract_h(L_shl(ener,norm1)); + ener_harmo_w = extract_h(L_shl(ener_harmo,norm1)); + + IF (GE_32(ener_harmo ,ener)) + { + return 32767; + } + test(); + IF ((ener_harmo_w <= 0)||(ener_w <= 0)) + { + return 0; + } + result = div_s(ener_harmo_w, ener_w); + return result; +} + +static +Word16 get_low_freq_eng_rate_x(Word32 *mdct_data, + Word16 curr_mode, + Word16 N) +{ + Word16 N1, N2, i; + Word32 low_eng = L_deposit_l(0), eng = L_deposit_l(0), smax = L_deposit_l(0); + Word16 nbits, temp, norm = 0; + move16(); + N1 = 30; + N2 = N; + move16(); + move16(); + IF (EQ_16(2 ,curr_mode)) + { + N1 = shr(30,1); + N2 = shr(N,1); + } + + nbits = sub(15, norm_s(N2)); + + FOR (i = 0; i < N2; i++) + { + smax = L_or(smax, L_abs(mdct_data[i])); + } + + norm = norm_l(smax); + + FOR (i = 0; i < N1; i++) + { + temp = extract_h(L_shl(mdct_data[i], norm)); + low_eng = L_add(low_eng, L_shr(L_mult0(temp, temp),nbits)); + } + + FOR (i = N1; i < N2; i++) + { + temp = extract_h(L_shl(mdct_data[i], norm)); + eng = L_add(eng, L_shr(L_mult0(temp, temp),nbits)); + } + eng = L_add(low_eng, eng); + + /* IF (low_eng<(eng+EPSILON)*0.02) return 1;ELSE return 0; */ + /* smax=eng*0.02 */ + smax = L_shr(Mpy_32_16_1(eng, 5243), 3); + + return (L_sub(low_eng,smax) <= 0); +} + +void LpFilter2_x(Word16 *x, Word16 *y, Word16 N) +{ + Word16 i; + Word16 smax, norm; + Word16 a1 = 5898; /* W16(0.18f); */ + Word16 a2 = 20971; /* W16(0.64f); */ + move16(); + move16(); + smax=0; + move16(); + FOR (i = 0; i < N; i++) + { + smax = s_or(smax, abs_s(x[i])); + } + norm = norm_s(smax); + + y[0] = mult(shl(x[0],norm), a1); + move16(); + y[1] = add(mult(y[0], a2),mult(shl(x[1],norm), a1)); + move16(); + + FOR (i = 2; i < N; i++) + { + /* 5898*2+20971=32767 -->no overflow */ + y[i] = add(mult(y[i-2],a1), add(mult(y[i-1],a2), mult(shl(x[i],norm),a1))); + move16(); + } +} + +void sig_tilt_x(Word16 *s, Word16 FrameSize, Word32 *enr1, Word32 *enr2) +{ + Word16 subFrameSize, shIFt; + Word16 *p1, *p2; + Word16 nbits; + + subFrameSize = shr(FrameSize, 2); + p1 = s+subFrameSize; + p2 = s+sub(subFrameSize, 2); + + shIFt = sub(FrameSize, subFrameSize); + nbits = sub(15, norm_s(shIFt)); + *enr1 = dot_w32_accuracy_x(p1, p2, nbits, shIFt); + move32(); + *enr2 = dot_w32_accuracy_x(p1, p1, nbits, shIFt); + move32(); +} + +void get_maxConv_and_pitch_x(Word16 *s_LP, Word16 s, Word16 e, Word16 N, + Word32 *maxConv, Word16 *maxConv_bits, Word16 *pitch) +{ + Word16 t, cov_size, size = N; + Word32 tmp_sigma = L_deposit_l(0), cov_max_sigma = L_deposit_l(0); + Word16 nbits,tmp_pitch=0; + Word32 r1_high, r2_high; + UWord16 r1_low, r2_low; + Word32 tmp_sigma_last = L_deposit_l(0); /* not needed, just to avoid compiler warning */ + Word16 cov_size_last = N; /* not needed, just to avoid compiler warning */ + Word32 cov_max_sigma_tmp = L_deposit_l(0); + Word16 size_tmp = N; + move16(); + move16(); + nbits = sub(15, norm_s(sub(N, s))); + + FOR (t = s; t < e; t++) + { + cov_size = sub(N,t); + tmp_sigma = dot_w32_accuracy_x(s_LP, s_LP+t, nbits, cov_size); + + IF (GT_16(t,s)) /* don't use the first value */ + { + Mpy_32_16_ss(tmp_sigma , cov_size_last, &r1_high, &r1_low); + Mpy_32_16_ss(tmp_sigma_last, cov_size , &r2_high, &r2_low); + /* tmp_sigma > tmp_sigma_last */ + test(); + test(); + move16(); + move16(); /* moves are for the (Word32) casts */ + IF((GT_32(r1_high, r2_high))|| + (EQ_32(r1_high, r2_high) && GT_32((Word32)r1_low, (Word32)r2_low) )) + { + /* store the current cov, if it is larger than the last one */ + cov_max_sigma_tmp = tmp_sigma; + move32(); + size_tmp = cov_size; + move16(); + } + ELSE + { + Mpy_32_16_ss(cov_max_sigma , size_tmp, &r1_high, &r1_low); + Mpy_32_16_ss(cov_max_sigma_tmp, size , &r2_high, &r2_low); + /* cov_max_sigma < cov_max_sigma_tmp */ + test(); + test(); + move16(); + move16(); /* moves are for the (Word32) casts */ + IF((LT_32(r1_high, r2_high))|| + (EQ_32(r1_high, r2_high) && LT_32((Word32)r1_low, (Word32)r2_low))) + { + /* otherwise */ + /* use the last value of cov, being a max */ + cov_max_sigma = cov_max_sigma_tmp; + move32(); + size = cov_size; + move16(); + /* and use the last index as pitch */ + tmp_pitch = sub(t,1); + } + } + } + tmp_sigma_last = tmp_sigma; + move32(); + cov_size_last = cov_size; + move16(); + } + *pitch = tmp_pitch; + move16(); + *maxConv = cov_max_sigma; + move32(); + *maxConv_bits = nbits; + move16(); +} + +Word16 get_voicing_x(Word16 *s_LP, Word16 pitch, Word32 covMax,Word16 maxConv_bits, Word16 Framesize) +{ + Word32 eng1 = L_deposit_l(0), eng2 = L_deposit_l(0); + Word16 voicing, norm; + Word16 tmpLen, nbits; + Word16 eng1_w, eng2_w; + + IF (covMax <= 0) + { + return 0; + } + ELSE + { + tmpLen = sub(Framesize, pitch); + nbits = maxConv_bits; + move16(); + + eng1 = dot_w32_accuracy_x(s_LP, s_LP, nbits, tmpLen); + eng2 = dot_w32_accuracy_x(s_LP+pitch, s_LP+pitch, nbits, tmpLen); + + norm = sub(norm_l(L_or(eng1, L_or(eng2, covMax))),1); + eng1 = L_shl(eng1, norm); + eng2 = L_shl(eng2, norm); + covMax = L_shl(covMax, norm); + + eng1_w = Sqrt_x_fast(eng1); + eng2_w = Sqrt_x_fast(eng2); + + eng1 = L_mult0(eng1_w, eng2_w); + norm = norm_l(eng1); + eng1_w = extract_h(L_shl(eng1, norm)); + eng2_w = extract_h(L_shl(covMax, norm)); + + IF (GE_32(covMax , eng1)) + { + return 32767; + } + test(); + IF ((eng2_w <= 0)||(eng1_w <= 0)) + { + return 0; + } + voicing = div_s(eng2_w, eng1_w); + + return voicing; + } +} + +void pitch_modify_x(Word16 *s_LP, Word16 *voicing, Word16 *pitch, Word16 FrameSize) +{ + Word32 eng1, eng2, eng3; + Word16 shIFt = shr(*pitch ,1); + Word16 tmpLen, nbits, norm, voicing2; + Word16 eng1_w, eng2_w; + + tmpLen = sub(FrameSize, shIFt); + nbits = sub(15, norm_s(tmpLen)); + + eng1 = dot_w32_accuracy_x(s_LP+shIFt, s_LP+shIFt, nbits, tmpLen); + eng2 = dot_w32_accuracy_x(s_LP, s_LP, nbits, tmpLen); + eng3 = dot_w32_accuracy_x(s_LP+shIFt, s_LP, nbits, tmpLen); + + IF (eng3 <= 0) + { + return ; + } + + norm = sub(norm_l(L_or(eng1, L_or(eng2, eng3))),1); + eng1 = L_shl(eng1, norm); + eng2 = L_shl(eng2, norm); + eng3 = L_shl(eng3, norm); + + eng1_w = Sqrt_x_fast(eng1); + eng2_w = Sqrt_x_fast(eng2); + + eng1 = L_mult0(eng1_w, eng2_w); + + norm = norm_l(eng1); + eng1_w = extract_h(L_shl(eng1, norm)); + eng2_w = extract_h(L_shl(eng3, norm)); + + IF (GE_32(eng3,eng1)) + { + voicing2 = 32767; + move16(); + } + ELSE { test(); + IF ((eng2_w <= 0)||(eng1_w <= 0)) + { + voicing2 = 0; + move16(); + } + ELSE { + voicing2 = div_s(eng2_w, eng1_w); + } + } + + IF (GT_16(voicing2, *voicing)) + { + *pitch = shIFt; + move16(); + *voicing = voicing2; + move16(); + } +} + +Word16 Is_Periodic_x(Word32 *mdct_data, Word16 cov_max, Word16 zp, Word32 ener, + Word32 ener_mean, Word16 pitch, Word16 Framesize) +{ + Word16 flag =0; + Word16 harm; + move16(); + test(); + test(); + test(); + IF (LT_32(ener, L_shl(50,8))||(LT_32(ener,L_sub(ener_mean,L_shl(8,8))) + && LT_16(cov_max, 29491) )) + { + flag = 0; + move16(); + } + ELSE IF (GT_16(cov_max, 26214)) + { + flag = 1; + move16(); + } + ELSE IF (GT_16(zp, 100)) + { + flag = 0; + move16(); + } + ELSE IF (LT_32(ener, L_sub(ener_mean,L_shl(6,8)))) + { + flag = 0; + move16(); + } + ELSE IF (GT_32(ener, L_add(ener_mean, L_shl(1,8)))&>_16(cov_max,19661)) + { + flag = 1; + move16(); + } + ELSE + { + harm = harmo_x(mdct_data, Framesize, pitch); + flag = 1; + move16(); + if (LT_16(harm, 22938)) + { + flag = 0; + move16(); + } + } + + return flag; +} + +Word16 get_conv_relation_x(Word16 *s_LP, Word16 shIFt, Word16 N) +{ + Word32 eng1,eng2, eng3; + Word16 eng1_w, eng2_w; + Word16 tmp, norm, nbits; + + nbits = sub(15, norm_s(N)); + eng3 = dot_w32_accuracy_x(s_LP, s_LP+shIFt, nbits, N); + + IF (eng3 <= 0) + { + return 0; + } + + eng1 = dot_w32_accuracy_x(s_LP+shIFt, s_LP+shIFt, nbits, N); + eng2 = dot_w32_accuracy_x(s_LP, s_LP, nbits, N); + + norm = sub(norm_l(L_or(eng1, L_or(eng2, eng3))),1); + eng1 = L_shl(eng1, norm); + eng2 = L_shl(eng2, norm); + eng3 = L_shl(eng3, norm); + + eng1_w = Sqrt_x_fast(eng1); + eng2_w = Sqrt_x_fast(eng2); + + eng1 = L_mult0(eng1_w, eng2_w); + + norm = norm_l(eng1); + eng1_w = extract_h(L_shl(eng1, norm)); + eng2_w = extract_h(L_shl(eng3, norm)); + + IF (GE_32(eng3, eng1)) + { + return 32767; + } + test(); + IF ((eng2_w <= 0)||(eng1_w <= 0)) + { + return 0; + } + + tmp = div_s(eng2_w, eng1_w); + + return tmp; +} + +static +Word16 pitch_search_fx(Word16 *s, /* lastPcmOut */ + Word16 *outx_new, + Word16 Framesize, + Word16 *voicing, + Word16 zp, + Word32 ener, + Word32 ener_mean, + Word32 *mdct_data, + Word16 curr_mode + ) +{ + Word16 pitch = 0; + Word32 cov_max = L_deposit_l(0), tilt_enr1, tilt_enr2; + Word16 s_LP[L_FRAME_MAX]; + Word16 start_pos, end_pos; + Word16 low_freq_rate_result; + Word16 flag = 0, zp_current; + Word32 *mdctPtr; + Word16 curr_frmsize; + Word16 cov_max_bits=0; + Word16 i; + move16(); + move16(); + move16(); + *voicing = 0; + move16(); + curr_frmsize = Framesize; + move16(); + if (EQ_16(2, curr_mode)) + { + curr_frmsize = shr(Framesize, 1); + } + + zp_current = zero_pass_w32_x(outx_new, curr_frmsize); + + if (EQ_16(2, curr_mode)) + { + zp_current = shl(zp_current,1); + } + IF (LE_16(Framesize, 256)) + { + IF (GT_16(zp_current, 70)) + { + return 0; + } + } + ELSE + { + IF (GT_16(zp_current, 105)) + { + return 0; + } + } + + mdctPtr = mdct_data; + if (EQ_16(2, curr_mode)) + { + mdctPtr = mdct_data + shr(Framesize,1); + } + + low_freq_rate_result = get_low_freq_eng_rate_x(mdctPtr, + curr_mode, + Framesize); + + IF(low_freq_rate_result) + { + return 0; + } + + LpFilter2_x(s, s_LP, Framesize); + sig_tilt_x(s_LP, Framesize, &tilt_enr1, &tilt_enr2); + IF (LE_16(Framesize, 320)) + { + test(); + IF ((0==tilt_enr2) || + (LT_32(tilt_enr1, L_shr(tilt_enr2, 1)) )) + { + return 0; + } + } + ELSE + { + test(); + IF ((0==tilt_enr2) || + (LT_32(tilt_enr1, Mpy_32_16_1(tilt_enr2, 22938)) )) + { + return 0; + } + } + + IF (LE_16(Framesize, 320)) + { + start_pos = extract_l(L_shr(L_mac0(0x80, 34, Framesize), 8)); + end_pos = extract_l(L_shr(L_mac0(0x2 , 3, Framesize), 2)); + get_maxConv_and_pitch_x(s_LP, start_pos, end_pos, Framesize, &cov_max, &cov_max_bits, &pitch); + *voicing = get_voicing_x(s_LP, pitch, cov_max, cov_max_bits, Framesize); + move16(); + pitch_modify_x(s_LP, voicing, &pitch, Framesize); + } + ELSE + { + Word16 s_tmp[L_FRAME_MAX]; + Word16 Framesize_tmp; + Word16 pitch_tmp[3]; + Word16 cov_size; + + Framesize_tmp = shr(Framesize, 1); + FOR (i = 0; i < Framesize_tmp; i++) + { + s_tmp[i] = s_LP[2*i]; + move16(); + } + + start_pos = extract_l( L_shr(L_mac0(0x80, 34, Framesize_tmp), 8)); + end_pos = extract_l( L_shr(L_mac0(0x2, 3, Framesize_tmp), 2)); + + cov_max = L_deposit_l(0); + pitch = 0; + move16(); + get_maxConv_and_pitch_x(s_tmp, start_pos, end_pos, Framesize_tmp, &cov_max, &cov_max_bits, &pitch); + + IF (pitch > 0) + { + pitch_tmp[0] = 0; + move16(); + if (GT_16(shl(pitch, 1), 1)) + { + pitch_tmp[0] = sub(shl(pitch, 1), 1); + move16(); + } + pitch_tmp[1] = shl(pitch, 1); + move16(); + pitch_tmp[2] = add(shl(pitch, 1), 1); + move16(); + start_pos = 0; + move16(); + pitch = 0; + move16(); + FOR (i = 0; i < 3; i++) + { + cov_size = sub(Framesize, pitch_tmp[i]); + end_pos = get_conv_relation_x(s_LP, pitch_tmp[i], cov_size); + IF (GT_16(end_pos, start_pos)) + { + start_pos = end_pos; + move16(); + pitch = pitch_tmp[i]; + move16(); + } + } + *voicing = start_pos; + move16(); + } + } + + IF (pitch > 0) + { + flag = Is_Periodic_x(mdct_data, *voicing, zp, ener, ener_mean, pitch, Framesize); + } + if (flag == 0 ) + { + pitch = 0; + move16(); + } + return pitch; +} + +void concealment_init_x(Word16 N, void *_plcInfo) +{ + T_PLCInfo *plcInfo = (T_PLCInfo*)_plcInfo; + Word16 i; + + plcInfo->FrameSize = N; + move16(); + plcInfo->Pitch_fx = 0; + move16(); + plcInfo->T_bfi_fx = 0; + move16(); + plcInfo->outx_new_n1_fx = 0; + move16(); + plcInfo->nsapp_gain_fx = 0; + move16(); + plcInfo->nsapp_gain_n_fx = 0; + move16(); + plcInfo->ener_mean_fx = L_deposit_l(15213); /*Q8 59.4260f*256*/ + plcInfo->ener_fx = L_deposit_l(0); + plcInfo->zp_fx = N; + move16(); + plcInfo->recovery_gain = 0; + move16(); + plcInfo->step_concealgain_fx = 0; + move16(); + plcInfo->concealment_method = TCX_NONTONAL; + move16(); + plcInfo->subframe_fx = 0; + move16(); + plcInfo->nbLostCmpt = L_deposit_l(0); + plcInfo->seed = 21845; + move16(); + + FOR (i = 0; i < TCX_TONALITY_INIT_CNT; i++) + { + plcInfo->TCX_Tonality[i] = 1; + move16(); + } + FOR (i = TCX_TONALITY_INIT_CNT; i < DEC_STATE_LEN; i++) + { + plcInfo->TCX_Tonality[i] = 0; + move16(); + } + + FOR (i = 0; i < MAX_POST_LEN; i++) + { + plcInfo->Transient[i] = 1; + move16(); + } + + FOR (i = 0; i < L_FRAME_MAX; i++) + { + plcInfo->data_reci2_fx[i] = L_deposit_l(0); + } + return; +} + +static Word16 own_random_fix( /* o : output random value */ + Word16 *seed /* i/o: random seed */ +) +{ + *seed = extract_l(L_mac0(13849L, *seed , 31821)); + return(*seed); +} + +void concealment_decode_fix(Word16 curr_mode, Word32 *invkoef, Word16 *invkoef_scale,void *_plcInfo) +{ + T_PLCInfo *plcInfo = (T_PLCInfo*)_plcInfo; + Word16 i; + Word16 N = plcInfo->FrameSize; + Word16 *seed = &(plcInfo->seed); + Word16 sign; + move16(); + IF (plcInfo->concealment_method == TCX_NONTONAL) /* #define TCX_NONTONAL 0 */ + { + IF (EQ_16(curr_mode, 1)) + { + /* copy the data of the last frame */ + mvr2r_Word32(plcInfo->data_reci2_fx, invkoef, N); + *invkoef_scale = plcInfo->data_reci2_scale; + move16(); + /* sign randomization */ + FOR (i = 0; i < N; i++) + { + sign = add(shl(shr(own_random_fix(seed),15),1),1); + if(EQ_16(sign,-1)) + { + invkoef[i] = L_negate(invkoef[i]); + move32(); + } + } + } + } + return; +} + + +Word16 Spl_GetScalingSquare_x(Word16 *in_vector, Word16 in_vector_length, Word16 times) +{ + Word16 nbits = sub(15, norm_s(times))/*Spl_GetSizeInBits_x(times)*/; + Word16 i; + Word16 smax = -1; + Word16 sabs; + Word16 *sptr = in_vector; + Word16 t; + move16(); + FOR (i = in_vector_length; i > 0; i--) + { + + sabs = abs_s(*sptr); + sptr++; + smax = s_max(sabs, smax); + + } + + t = norm_l(L_mult0(smax, smax)); + + IF (smax == 0) + { + return 0; /* Since norm(0) returns 0 */ + } + ELSE + { + nbits = sub(nbits, t); + nbits = s_max(0,nbits); + + return nbits; + } +} + + +Word32 Spl_Energy_x(Word16* vector, Word16 vector_length, Word16* scale_factor) +{ + Word32 en = L_deposit_l(0); + Word32 i; + Word16 scaling = Spl_GetScalingSquare_x(vector, vector_length, vector_length); + + FOR (i = 0; i < vector_length; i++) + { + en = L_add(en,L_shr(L_mult0(vector[i], vector[i]), scaling)); + } + + move32(); + *scale_factor = scaling; + + return en; +} + +void Log10OfEnergy_x(Word16 *s, Word32 *enerlogval, Word16 len) +{ + Word32 energy = L_deposit_l(0), tmp2 = L_deposit_l(0); + Word16 shfts = 0; + Word32 Log10_energy = L_deposit_l(0), Log10_len = L_deposit_l(0); + move16(); + energy = Spl_Energy_x(s, len, &shfts);/* Q:-shfts */ + IF (energy > 0) + { + Log10_energy = con_Log10(energy, negate(shfts)); /* Q25 */ + Log10_len = con_Log10(L_deposit_l(len), 0); /* Q25 */ + tmp2 = L_sub(Log10_energy,Log10_len); /* Q25 */ + tmp2 = Mpy_32_16_1(tmp2,20480); /* Q11->10 Q=25+11-15=21 */ + *enerlogval = L_shr(tmp2,13); /* Q8 */ move32(); + } + ELSE + { + *enerlogval = -25600; + move32(); + } + +} + +static Word32 fnLog2(Word32 L_Input) +{ + + Word16 swC0 = -0x2b2a, swC1 = 0x7fc5, swC2 = -0x54d0; + Word16 siShIFtCnt, swInSqrd, swIn; + Word32 LwIn; + move16(); + move16(); + move16(); + /*_________________________________________________________________________ + | | + | Executable Code | + |_________________________________________________________________________| + */ + + /* normalize input and store shIFts required */ + /* ----------------------------------------- */ + + siShIFtCnt = norm_l(L_Input); + LwIn = L_shl(L_Input, siShIFtCnt); + siShIFtCnt = add(siShIFtCnt, 1); + siShIFtCnt = negate(siShIFtCnt); + + /* calculate x*x*c0 */ + /* ---------------- */ + + swIn = extract_h(LwIn); + swInSqrd = mult_r(swIn, swIn); + LwIn = L_mult(swInSqrd, swC0); + + /* add x*c1 */ + /* --------- */ + + LwIn = L_mac(LwIn, swIn, swC1); + + /* add c2 */ + /* ------ */ + + LwIn = L_add(LwIn, L_deposit_h(swC2)); + + /* apply *(4/32) */ + /* ------------- */ + + LwIn = L_shr(LwIn, 3); + LwIn = L_and(LwIn, 0x03ffffff); + siShIFtCnt = shl(siShIFtCnt, 10); + LwIn = L_add(LwIn, L_deposit_h(siShIFtCnt)); + + /* return log2 */ + /* ----------- */ + + return (LwIn); +} + +static Word32 fnLog10(Word32 L_Input) +{ + + Word16 Scale = 9864; /* 0.30103 = log10(2) */ + Word32 LwIn; + move16(); + /*_________________________________________________________________________ + | | + | Executable Code | + |_________________________________________________________________________| + */ + + /* 0.30103*log2(x) */ + /* ------------------- */ + + LwIn = fnLog2(L_Input); + LwIn = Mpy_32_16_1(LwIn, Scale); + + return (LwIn); +} + +Word32 con_Log10(Word32 i_s32Val, Word16 i_s16Q) +{ + Word32 s32Out; + Word32 s32Correct; /* corrected (31-q)*log10(2) */ + const Word16 s16Log10_2 = 19728; /* log10(2)~Q16 */ move16(); + + IF(0 == i_s32Val) + { + return EVS_LW_MIN; + } + + s32Out = fnLog10(i_s32Val); /* (2^26)*log10(a) */ + + s32Correct = L_mult(sub(31,i_s16Q), s16Log10_2); /* q = 17 */ + s32Correct = L_shl(s32Correct, 8); /* q = 25 */ + s32Out = L_shr(s32Out, 1); /* q = 25 */ + + s32Out = L_add(s32Out, s32Correct); + + return s32Out; +} + +void concealment_update2_x(Word16 *outx_new, void *_plcInfo, Word16 FrameSize) +{ + T_PLCInfo *plcInfo = (T_PLCInfo*)_plcInfo; + + plcInfo->zp_fx = zero_pass_w32_x(outx_new, FrameSize); + move16(); + + Log10OfEnergy_x(outx_new, &plcInfo->ener_fx, FrameSize); /* Q8 */ + test(); + IF (LT_16(plcInfo->zp_fx, 100)&>_32(plcInfo->ener_fx,L_shl(50,8))) + { + plcInfo->ener_mean_fx = L_add(Mpy_32_16_1(plcInfo->ener_mean_fx ,32112/* 0.98 Q15 */), + Mpy_32_16_1(plcInfo->ener_fx , 655/* 0.02 Q15 */)); + move32(); + } + return; +} + +static Word16 array_max_indx_fx(Word16 *s, Word16 N) +{ + Word16 i, indx = 0; + move16(); + FOR (i = 0; i < N; i++) + { + if (GT_16(s[i], s[indx])) + { + indx = i; + move16(); + } + } + return indx; +} + +Word16 ffr_getSfWord16( /* o: measured headroom in range [0..15], 0 IF all x[i] == 0 */ + Word16 *x, /* i: array containing 16-bit data */ + Word16 len_x) /* i: length of the array to scan */ +{ + Word16 i, i_min, i_max; + Word16 x_min, x_max; + + + x_max = 0; + move16(); + x_min = 0; + move16(); + FOR (i = 0; i < len_x; i++) + { + if (x[i] >= 0) + x_max = s_max(x_max,x[i]); + if (x[i] < 0) + x_min = s_min(x_min,x[i]); + } + + i_max = 0x10; + move16(); + i_min = 0x10; + move16(); + + if (x_max != 0) + i_max = norm_s(x_max); + + if (x_min != 0) + i_min = norm_s(x_min); + + i = s_and(s_min(i_max, i_min),0xF); + + + return i; +} + +static Word16 OverlapAdd_fx(Word16 *pitch125_data, Word16 *sbuf, + Word16 n, Word16 pitch, Word16 Framesize) +{ + Word16 n1,n2,s,s16MaxCoefNorm,s16MaxCoefNorm2,tmp16; + Word16 i; + Word16 pitch125 =extract_l(L_shr(L_add(L_add(L_deposit_h(pitch), L_mult(pitch, 8192)), 32768) ,16)); + Word16 Loverlap = sub(pitch125,pitch); + Word16 Framesize_sub_n = sub(Framesize, n); + + n1 = Framesize_sub_n; + move16(); + n2 = Framesize_sub_n; + move16(); + if(LT_16(Loverlap, Framesize_sub_n)) + { + n1 = Loverlap; + move16(); + } + if(LT_16(pitch125, Framesize_sub_n)) + { + n2 = pitch125; + move16(); + } + s16MaxCoefNorm = sub(ffr_getSfWord16(sbuf+n, n1),1); + s16MaxCoefNorm2 = ffr_getSfWord16(pitch125_data, n1); + Loverlap = s_max(1, Loverlap); + tmp16 =BASOP_Util_Divide1616_Scale(1, Loverlap,&s); + FOR (i = 0; i < n1; i++) + { + Word16 tmp; + Word16 dat; + dat= shl(sbuf[n+i],s16MaxCoefNorm); + tmp = extract_l(L_shl(L_mult0(i, tmp16), s)); /* q15 */ + sbuf[n+i] = round_fx(L_add(L_shr(L_mult(dat, sub(32767,tmp)),s16MaxCoefNorm), + L_shr(L_mult(shl(pitch125_data[i],s16MaxCoefNorm2),tmp),s16MaxCoefNorm2))); + } + + FOR (i = n1; i < n2; i++) + { + sbuf[n+i] = pitch125_data[i]; + move16(); + } + + pitch = add(n, pitch); + + return pitch; +} + +static void add_noise (Word16 * const sbuf, + Word16 * const outx_new_n1, + Word16 const* const noise_seg, + Word16 const Len, + Word16 * const gain, + Word16 const* const gain_n, + Word8 const firstFrame) +{ + Word16 i; + Word16 temp_OUT; + + IF( !firstFrame ) + { + temp_OUT = sub(noise_seg[0], mult((*outx_new_n1),22282/* 0.68 Q15 */)); + sbuf[0] = add(sbuf[0], mult((temp_OUT), *gain)); + move16(); + *gain = mac_r(L_mult(32439/* 0.99 Q15 */,*gain),328/* 0.01 Q15 */,*gain_n); + } + + FOR( i = 1; i < Len; i++ ) + { + temp_OUT = sub(noise_seg[i], mult((noise_seg[i-1]),22282/* 0.68 Q15 */)); + sbuf[i] = add(sbuf[i], mult((temp_OUT), *gain)); + move16(); + *gain = mac_r(L_mult(32439/* 0.99 Q15 */,*gain),328/* 0.01 Q15 */,*gain_n); + } + + *outx_new_n1 = noise_seg[i-1]; /*q0*/ + + return; +} + +static +Word16 waveform_adj_fix(Word16 *overlapbuf, + Word16 *outdata2, + Word16 *outx_new, + Word16 *data_noise, + Word16 *outx_new_n1, + Word16 *nsapp_gain, + Word16 *nsapp_gain_n, + Word16 Framesize, + Word8 T_bfi, + Word16 voicing, + Word16 curr_mode, + Word16 pitch) +{ + Word16 i, zp1, zp2,Framesizediv2,s16MaxCoefNorm; + Word16 sbuf[L_FRAME_MAX]; + Word16 tmp; + + Framesizediv2=shr(Framesize,1); + zp1 = zero_pass_w32_x(outdata2, Framesizediv2); + zp2 = zero_pass_w32_x(outdata2+Framesizediv2, Framesizediv2); + + /* judge if the pitch is usable */ + tmp = 1; + move16(); + if (GT_16(zp1, 1)) + { + tmp = zp1; + move16(); + } + IF (LT_16(shl(tmp,2), zp2)) + { + move16(); + return 0; + } + + /* adjust the pitch value */ + test(); + test(); + test(); + IF (T_bfi && (LE_16(pitch , Framesizediv2)) + && (GT_16(Framesize ,256)) && (EQ_16(curr_mode , 1))) + { + Word16 i1 = 0, i2 = 0; + Word16 pos1, pos2, pos3; + move16(); + move16(); + i1 = add(1 , array_max_indx_fx(outx_new, pitch)); + i2 = add(1 , array_max_indx_fx(outx_new+pitch, pitch)); + + pos1 = add(i2,sub(pitch,i1)); + pos3 = add(pos1, mult(pos1, 8192/* 0.25 Q15 */)); + pos2 = add(pitch,mult(pitch, 8192/* 0.25 Q15 */)); + + test(); + test(); + IF ((LT_16(pos1,pos2))&&(GT_16(pos3,pitch))&&(LT_16(pos1,Framesizediv2))) + { + pitch = add(i2,sub(pitch,i1)); + } + } + + { + Word16 pitch125 = 0, Loverlap = 0, n = 0; + Word16 pitch125_data[L_FRAME_MAX]; + move16(); + move16(); + pitch125 = extract_l((L_shr(L_add(L_add(L_deposit_h(pitch), L_mult(pitch, 8192)), 32768) ,16))); + Loverlap = sub(pitch125,pitch); + FOR (i = 0; i < pitch; i++) + { + pitch125_data[i] = outdata2[Framesize-pitch+i]; + move16(); + } + FOR (i = 0; i < Loverlap; i++) + { + pitch125_data[pitch+i] = outx_new[i]; + move16(); + } + FOR (i = 0; i < Framesize; i++) + { + sbuf[i] = outx_new[i]; + move16(); + } + + { + Word16 pitch125a1; + Word16 tmp_buf[2*L_FRAME_MAX], *p_tmp = tmp_buf+1; + + FOR (i = 0; i < pitch125; i++) + { + p_tmp[i] = pitch125_data[i]; + move16(); + } + + p_tmp[-1] = outdata2[Framesize-pitch-1]; + move16(); + p_tmp[pitch125] = outx_new[Loverlap]; + move16(); + pitch125a1 = add(pitch125,1); + s16MaxCoefNorm = sub(ffr_getSfWord16(p_tmp-1, pitch125a1),1); + FOR (i = 0; i < pitch125a1; i++) + { + p_tmp[i-1] = shl(p_tmp[i-1],s16MaxCoefNorm); + move16(); + } + FOR (i = 0; i < pitch125; i++) + { + pitch125_data[i] = round_fx(L_shr(L_add((L_mult(p_tmp[i], 20972)),L_mac(L_mult(p_tmp[i-1], 5898),p_tmp[i+1],5898)),s16MaxCoefNorm)); + } + } + + WHILE (LT_16(n, Framesize)) /* periodical extension */ + { + n = OverlapAdd_fx(pitch125_data,sbuf,n,pitch,Framesize); + } + + /* maximum pitch lag is 3/4 Framesize; pitch125_data is reused for + temporary storage, since outdata2 (holding the pcm data of the + last good frame) is still needed and overlapbuf overlaps outdata2 */ + Copy(&sbuf[Framesize/4], pitch125_data, (3*Framesize)/4); + + *nsapp_gain = 0; + move16(); + *nsapp_gain_n = sub(32767 ,shr(voicing,1)); /* q15 */ + tmp = Framesize; + move16(); + /* use last good signal for noise generation */ + add_noise(sbuf, outx_new_n1, outdata2, tmp, nsapp_gain, nsapp_gain_n, 1); + /* save current (noisy) output from IMDCT */ + mvr2r_Word16(outx_new, data_noise, tmp); + /* overlapbuf can now be filled with sbuf, needed for subsequently lost frames */ + Copy(pitch125_data, &overlapbuf[Framesize/4], (3*Framesize)/4); + } + FOR (i = 0; i < Framesize; i++) + { + outx_new[i] = sbuf[i]; + move16(); + } + return pitch; +} + +void waveform_adj2_fix( Word16 *overlapbuf, + Word16 *outx_new, + Word16 *data_noise, + Word16 *outx_new_n1, + Word16 *nsapp_gain, + Word16 *nsapp_gain_n, + Word16 *recovery_gain, + Word16 step_concealgain, + Word16 pitch, + Word16 Framesize, + Word16 delay, + Word16 bfi_cnt, + Word16 bfi + ) +{ + Word16 i, n,tablescale,ratio, + dat,Framesizesubn,Framesizesubp,tmp16,s,ptable,temp_OUT,s16MaxCoefNorm,s16MaxCoefNorm2; + Word16 sbuf[L_FRAME_MAX]; + + n=0; + move16(); + Framesizesubn = sub(Framesize,n); + Framesizesubp = sub(Framesize,pitch); + IF (pitch > 0) + { + WHILE (Framesizesubn>0) + { + /* periodical extension */ + Word16 tmp = vadmin(pitch, Framesizesubn); + FOR (i = 0; i < tmp; i++) + { + sbuf[n+i] = overlapbuf[Framesizesubp+i]; + move16(); + } + n = add(n, pitch); + Framesizesubn = sub(Framesize,n); + } + + FOR (i = 0; i < Framesize; i++) + { + overlapbuf[i] = sbuf[i]; + move16(); + } + + { + Word16 size = Framesize; + Word16* noise_ptr = data_noise; + + /* use last (noisy) output from IMDCT for noise generation */ + add_noise(sbuf, outx_new_n1, noise_ptr, size, nsapp_gain, nsapp_gain_n, 0); + + /* save current (noisy) output from IMDCT */ + IF( bfi ) + { + mvr2r_Word16(outx_new, noise_ptr, size); + } + } + test(); + IF (EQ_16(bfi_cnt ,4)||bfi==0) + { + SWITCH ( Framesize) + { + case 160: + { + tablescale =8; + move16(); + ptable = 26214; /* (Word16)(32767*256/160.0+0.5); q7+15 */ move16(); + BREAK; + } + case 320: + { + tablescale =9; + move16(); + ptable = 26214; /* (Word16)(32767*256/320.0+0.5); q8+15 */ move16(); + BREAK; + } + case 512: + { + tablescale =10; + move16(); + ptable = 32767; /* q9+15 */ move16(); + BREAK; + } + case 640: + { + tablescale =10; + move16(); + ptable = 26214; /* (Word16)(32767*512/640.0+0.5); q9+15 */ move16(); + BREAK; + } + default: /* 960 */ + { + tablescale =10; + move16(); + ptable = 17456; /* (Word16)(32767*512/960.0); q9+15 */ move16(); + BREAK; + } + } + IF (bfi == 0) /* overlap-and-add */ + { + Word16 gain_zero_start = 10000; + move16(); + + IF (step_concealgain > 0) + { + gain_zero_start = BASOP_Util_Divide1616_Scale(*recovery_gain, step_concealgain,&s); + gain_zero_start= shl(gain_zero_start, sub(s,14)); /* q0 */ + gain_zero_start= add(gain_zero_start,1); + } + + IF (delay > 0) + { + Framesize = sub(Framesize,delay); + } + + s16MaxCoefNorm = sub(ffr_getSfWord16(sbuf, Framesize),1); + s16MaxCoefNorm2 = ffr_getSfWord16(outx_new, Framesize); + tmp16 = vadmin(gain_zero_start, Framesize); + FOR (i = 0; i < tmp16; i++) + { + ratio = extract_l(L_shr(L_mult(i, ptable), tablescale)); + dat= shl(sbuf[i],s16MaxCoefNorm); + temp_OUT= mult(*recovery_gain, sub(32767,ratio)); + outx_new[i]= round_fx(L_add(L_shr(L_mult(temp_OUT,dat ),s16MaxCoefNorm-1), L_shr(L_mult(shl(outx_new[i],s16MaxCoefNorm2),ratio),s16MaxCoefNorm2))); + move16(); + *recovery_gain =sub(*recovery_gain,shr_r(step_concealgain,1)); /* q14 */ + } + FOR (i = gain_zero_start; i < Framesize; i++) + { + ratio = extract_l(L_shr(L_mult(i, ptable), tablescale)); + outx_new[i] = round_fx(L_shr(L_mult(shl(outx_new[i],s16MaxCoefNorm2),ratio),s16MaxCoefNorm2)); + + } + + if (*recovery_gain < 0) + { + *recovery_gain = 0; + move16(); + } + } + ELSE + { + /* overlap-and-add */ + Word16 tmp; + s16MaxCoefNorm = sub(ffr_getSfWord16(sbuf, Framesize),1); + s16MaxCoefNorm2 = ffr_getSfWord16(outx_new, Framesize); + FOR (i = 0; i < Framesize; i++) + { + dat = shl(sbuf[i], s16MaxCoefNorm); + tmp = extract_l(L_shr(L_mult(i, ptable), tablescale)); + outx_new[i] = round_fx(L_add(L_shr(L_mult(dat, sub(32767,tmp)),s16MaxCoefNorm), L_shr(L_mult(shl(outx_new[i],s16MaxCoefNorm2),tmp),s16MaxCoefNorm2))); + } + } + } + ELSE + { + FOR (i = 0; i < Framesize; i++) + { + outx_new[i] = sbuf[i]; + move16(); + } + } + } + return; +} + +void concealment_signal_tuning_fx(Word16 bfi, Word16 curr_mode, Word16 *outx_new_fx, void *_plcInfo, Word16 nbLostCmpt, Word16 pre_bfi, Word16 *OverlapBuf_fx, Word16 past_core_mode, Word16 *outdata2_fx, Decoder_State_fx *st) +{ + T_PLCInfo *plcInfo = (T_PLCInfo*)_plcInfo; + Word16 FrameSize = plcInfo->FrameSize; + Word16 Pitch = plcInfo->Pitch_fx; + Word16 voicing_fx = 0; + move16(); + move16(); + move16(); + move16(); + IF (bfi) + { + + test(); + IF (st->enablePlcWaveadjust && plcInfo->concealment_method == TCX_NONTONAL) /* #define TCX_NONTONAL 0 */ + { + + IF (EQ_16(nbLostCmpt, 1)) + { + plcInfo->Pitch_fx = pitch_search_fx(outdata2_fx, + outx_new_fx, + FrameSize, + &voicing_fx, + plcInfo->zp_fx, + (plcInfo->ener_fx), + (plcInfo->ener_mean_fx), + plcInfo->data_reci2_fx, + curr_mode + ); + move16(); + + IF (plcInfo->Pitch_fx) /* waveform adjustment for the first lost frame */ + { + plcInfo->Pitch_fx = waveform_adj_fix(OverlapBuf_fx, + outdata2_fx, + outx_new_fx, + plcInfo->data_noise, + &plcInfo->outx_new_n1_fx, + &plcInfo->nsapp_gain_fx, + &plcInfo->nsapp_gain_n_fx, + FrameSize, + plcInfo->T_bfi_fx, + voicing_fx, + curr_mode, + plcInfo->Pitch_fx); + move16(); + } + } + ELSE IF (LT_16(nbLostCmpt, 5)) /* waveform adjustment for the 2nd~4th lost frame */ + { + waveform_adj2_fix(OverlapBuf_fx, + outx_new_fx, + plcInfo->data_noise, + &plcInfo->outx_new_n1_fx, + &plcInfo->nsapp_gain_fx, + &plcInfo->nsapp_gain_n_fx, + &plcInfo->recovery_gain, + plcInfo->step_concealgain_fx, + Pitch, + FrameSize, + 0, + nbLostCmpt, + bfi); + } + } + plcInfo->T_bfi_fx = 1; + move16(); + } + ELSE + { + test(); + test(); + test(); + IF (pre_bfi && + past_core_mode != 0 && + GE_32(st->last_total_brate_fx, 48000) && + EQ_16(st->last_codec_mode, MODE2) ) + { + IF (plcInfo->concealment_method == TCX_NONTONAL) /* #define TCX_NONTONAL 0 */ + { + IF (LT_32(plcInfo->nbLostCmpt, 4)) /* smoothing of the concealed signal with the good signal */ + { + waveform_adj2_fix(OverlapBuf_fx, + outx_new_fx, + plcInfo->data_noise, + &plcInfo->outx_new_n1_fx, + &plcInfo->nsapp_gain_fx, + &plcInfo->nsapp_gain_n_fx, + &plcInfo->recovery_gain, + plcInfo->step_concealgain_fx, + Pitch, + FrameSize, + 0, + add(extract_l(plcInfo->nbLostCmpt), 1), + bfi); + } + } + } + ELSE + { + plcInfo->T_bfi_fx = 0; + move16(); + } + } + return; +} diff --git a/lib_enc/ACcontextMapping_enc.c b/lib_enc/ACcontextMapping_enc.c new file mode 100644 index 0000000..c574f5f --- /dev/null +++ b/lib_enc/ACcontextMapping_enc.c @@ -0,0 +1,713 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include +#include "options.h" +#include "stl.h" +#include "basop_util.h" +#include "stl.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include "rom_com_fx.h" + +/** + * \brief Arithmetic encoder + * \param[i] x + * \param[o] ntuples amount of encoded tuple (2 lines per tuple) + * \param[i] nt + * \param[i] nbbits + * \param[i] resQMaxBits + * \return none + */ +Word16 ACcontextMapping_encode2_no_mem_s17_LC( + Encoder_State_fx *st, + Word16 *x, + Word16 nt, + Word16 lastnz, + Word16 nbbits, + Word16 resQMaxBits, + CONTEXT_HM_CONFIG *hm_cfg) +{ + Word16 ptr[BITBUFSIZE]; + TastatEnc as, as_overflow; + Word16 bp, bp_overflow; + Word16 a1, b1, a1_i, b1_i, k; + Word16 t, pki, lev1; + Word16 rateFlag; + Word16 value; + Word16 nbbits_ntuples, nbbits_lsbs, nbbits_signs, nbbits_signs_overflow, nbbits_lsbs_overflow, flag_overflow; + Word16 *lsbs_bits2; + Word16 tmp; + Word16 nt_half; + Word16 c[2], *ctx; + Word16 p1, p2; + Word16 ii[2], idx1, idx2, idx; + Word16 numPeakIndicesOrig, numHoleIndices; + get_next_coeff_function get_next_coeff; + Word16 signs[N_MAX]; + Word16 nbbits_m2; + + a1 = 0; /* to avoid compilation warnings */ + b1 = 0; /* to avoid compilation warnings */ + + + /* Rate flag */ + rateFlag = 0; + move16(); + if (GT_16(nbbits, 400)) + { + rateFlag = 2 << NBITS_CONTEXT; + move16(); + } + + /* Init */ + nt_half = shr(nt, 1); + c[0] = c[1] = 0; + move16(); + move16(); + + /* Bits for encoding the number of encoded tuples */ + nbbits_ntuples = sub(14, norm_s(negate(nt))); + + t = 0; + move16(); + bp = nbbits_ntuples; + move16(); + nbbits_signs = 0; + move16(); + nbbits_lsbs = 0; + move16(); + nbbits_m2 = sub(nbbits, 2); + flag_overflow = 0; + move16(); + + IF (hm_cfg) /* mapped domain */ + { + numPeakIndicesOrig = hm_cfg->numPeakIndices; + move16(); + hm_cfg->numPeakIndices = s_min(hm_cfg->numPeakIndices, lastnz); + move16(); + numHoleIndices = sub(lastnz, hm_cfg->numPeakIndices); + + /* Mark hole indices beyond lastnz as pruned */ + FOR (k=numHoleIndices; knumHoleIndices; ++k) + { + hm_cfg->holeIndices[k] = add(hm_cfg->holeIndices[k], nt); + move16(); + } + + ii[0] = numPeakIndicesOrig; + move16(); + ii[1] = 0; + move16(); + + get_next_coeff = get_next_coeff_mapped; + move16(); + } + ELSE /* unmapped domain */ + { + ii[0] = 0; + move16(); + + p1 = p2 = 0; + move16(); + move16(); + + get_next_coeff = get_next_coeff_unmapped; + move16(); + + /* Find last non-zero tuple */ + /* ensure termination of while loop by dummy value */ + a1 = x[0]; + move16(); + x[0] = 1; + move16(); + + WHILE (s_or(x[lastnz-1], x[lastnz-2]) == 0) + { + lastnz = sub(lastnz, 2); + } + x[0] = a1; + move16(); + } + + lsbs_bits2 = ptr+nbbits-1; + + /*Start Encoding*/ + ari_start_encoding_14bits(&as); + + /*Main Loop through the 2-tuples*/ + b1_i = -1; + move16(); + FOR (k = 0; k < lastnz; k += 2) + { + /* First coefficient */ + a1_i = get_next_coeff(ii, &p1, &idx1, hm_cfg); + + /* Second coefficient */ + b1_i = get_next_coeff(ii, &p2, &idx2, hm_cfg); + + idx = s_min(idx1, idx2); + + /* Get context */ + ctx = &c[s_or(p1, p2)]; + move16(); + + t = add(*ctx, rateFlag); + if (GT_16(idx, nt_half)) + { + t = add(t, 1 << NBITS_CONTEXT); + } + + /* Init current 2-tuple encoding */ + if (flag_overflow != 0) + { + x[a1_i] = 0; + move16(); + } + if (flag_overflow != 0) + { + x[b1_i] = 0; + move16(); + } + + a1 = abs_s(x[a1_i]); + b1 = abs_s(x[b1_i]); + + lev1 = -1; + move16(); + + /*Copy states*/ + ari_copy_states(&as, &as_overflow); + bp_overflow = bp; + move16(); + nbbits_signs_overflow = nbbits_signs; + move16(); + nbbits_lsbs_overflow = nbbits_lsbs; + move16(); + + /*Signs encoding*/ + signs[nbbits_signs] = lshr(x[a1_i], 15); + move16(); + if (a1 > 0) + { + nbbits_signs = add(nbbits_signs, 1); + } + signs[nbbits_signs] = lshr(x[b1_i], 15); + move16(); + if (b1 > 0) + { + nbbits_signs = add(nbbits_signs, 1); + } + + /* MSBs coding */ + WHILE (GE_16(s_max(a1, b1), A_THRES)) + { + tmp = add(t, Tab_esc_nb[lev1+1]); + assert(tmp >= 0 && tmp < 4096); + pki = ari_lookup_s17_LC[tmp]; + move16(); + bp = ari_encode_14bits_ext(ptr, bp, &as, VAL_ESC, ari_pk_s17_LC_ext[pki]); + + *lsbs_bits2-- = s_and(a1, 1); + move16(); + *lsbs_bits2-- = s_and(b1, 1); + move16(); + + /* LSBs bit counting */ + nbbits_lsbs = add(nbbits_lsbs, 2); + + a1 = shr(a1, 1); + b1 = shr(b1, 1); + + lev1 = s_min(add(lev1, 1), 2); + } + + tmp = add(t, Tab_esc_nb[lev1+1]); + assert(tmp >= 0 && tmp < 4096); + pki = ari_lookup_s17_LC[tmp]; + move16(); + bp = ari_encode_14bits_ext(ptr, bp, &as, add(a1, shl(b1, A_THRES_SHIFT)), ari_pk_s17_LC_ext[pki]); + + /* Check bit budget */ + IF (GT_16(add(add(add(bp, extract_l(as.vobf)), nbbits_signs), nbbits_lsbs), nbbits_m2)) + { + ari_copy_states(&as_overflow, &as); + bp = bp_overflow; + move16(); + + IF (flag_overflow == 0) + { + nbbits_signs = nbbits_signs_overflow; + move16(); + nbbits_lsbs = nbbits_lsbs_overflow; + move16(); + IF (hm_cfg) + { + flag_overflow = 1; + move16(); + + /* Code from now only zeros */ + x[a1_i] = 0; + move16(); + x[b1_i] = 0; + move16(); + lev1 = -1; + move16(); + + assert(t >= 0 && t < 4096); + pki = ari_lookup_s17_LC[t]; + move16(); + bp = ari_encode_14bits_ext(ptr, bp, &as, 0, ari_pk_s17_LC_ext[pki]); + + IF (GT_16(add(add(add(bp, extract_l(as.vobf)), nbbits_signs), nbbits_lsbs), nbbits_m2)) + { + ari_copy_states(&as_overflow, &as); + bp = bp_overflow; + move16(); + BREAK; + } + } + ELSE + { + BREAK; + } + } + ELSE + { + BREAK; + } + } + + /* Update context for next 2-tuple */ + IF (EQ_16(p1, p2)) /* peak-peak or hole-hole context */ + { + if (lev1 > 0) t = add(12, lev1); + if (lev1 <= 0) t = add(a1, b1); + if (lev1 == 0) t = add(t, t); + + *ctx = add(shl(s_and(*ctx, 0xf), 4), add(t, 1)); + move16(); + } + ELSE /* mixed context */ + { + IF (s_and(idx1, 1)) /* update first context */ + { + c[p1] = update_mixed_context(c[p1], abs_s(x[a1_i])); + move16(); + } + + IF (s_and(idx2, 1)) /* update second context */ + { + c[p2] = update_mixed_context(c[p2], abs_s(x[b1_i])); + move16(); + } + } + } /*end of the 2-tuples loop*/ + + /* End arithmetic coder, overflow management */ + bp = ari_done_encoding_14bits(ptr, bp, &as); + + /* Overflow is detected */ + IF (NE_16(k, lastnz)) + { + IF (hm_cfg) + { + /* Fill with zero to be sure that the decoder finishes the MSB decoding at the same position */ + tmp = sub(nbbits, add(nbbits_signs, nbbits_lsbs)); + set16_fx(&ptr[bp], 0, sub(tmp, bp)); + bp = tmp; + move16(); + } + if (!hm_cfg) + { + lastnz = k; + move16(); + } + } + + /* Push number of encoded tuples */ + value = sub(shr(lastnz, 1), 1); + push_next_indice_fx(st, value, nbbits_ntuples); + + /* Push arithmetic coded bits */ + push_next_bits_fx(st, &ptr[nbbits_ntuples], sub(bp, nbbits_ntuples)); + + /* Push sign bits */ + push_next_bits_fx(st, signs, nbbits_signs); + bp = add(bp, nbbits_signs); + + /*write residual Quantization bits*/ + tmp = s_min(sub(sub(nbbits, bp), nbbits_lsbs), resQMaxBits); + FOR (k = 0; k < tmp; k++) + { + ptr[nbbits-1-nbbits_lsbs-k] = x[nt+k]; + move16(); + } + /* Write filler bits */ + tmp = sub(nbbits, add(bp, nbbits_lsbs)); + FOR (; kindexBuffer; + move16(); + } + + lobs[0] = 4; + move16(); + lobs[1] = shr(length, 1); /* length/2 */ move16(); + lobs[2] = add(lobs[1], shr(length, 2)); + move16(); + lobs[3] = add(lobs[2], shr(length, 3)); + move16(); + + last_nz = 0; + move16(); + i = length; + move16(); + FOR (stage=3; stage>=0; --stage) + { + IF (hm_cfg) /* mapped kernel */ + { + FOR (; i >= lobs[stage]; i-=2) + { + if (x[tmp[i-2]] != 0) + { + last_nz = s_max(last_nz, i); + } + if (x[tmp[i-1]] != 0) + { + last_nz = s_max(last_nz, i); + } + } + } + ELSE /* unmapped kernel */ + { + FOR (; i >= lobs[stage]; i-=2) + { + if (x[i-2] != 0) + { + last_nz = s_max(last_nz, i); + } + if (x[i-1] != 0) + { + last_nz = s_max(last_nz, i); + } + } + } + IF (last_nz > 0) + { + BREAK; + } + } + + return s_max(last_nz, 2); +} + +Word16 ACcontextMapping_encode2_estimate_no_mem_s17_LC( + const Word16 *x, + Word16 nt, + Word16 *lastnz_out, + Word16 *nEncoded, + Word16 target, + Word16 *stop, + CONTEXT_HM_CONFIG *hm_cfg +) +{ + Word16 a1, b1, a1_i, b1_i; + Word16 k, t, pki, lev1; + Word16 lastnz, lastnz2; + Word16 rateFlag; + Word16 nbits_old, nbits; + Word16 stop2; + Word16 cum_freq_norm, cum_freq_norm_e; + Word32 proba; + Word16 nlz; + const UWord16 *cum_freq; + Word16 symbol; + const Word8 *lookup; + Word16 nt_half; + Word16 c[2], *ctx; + Word16 p1, p2; + Word16 ii[2], idx1, idx2, idx; + Word16 numPeakIndicesOrig=0, numHoleIndices=0; /* initialize just to avoid compiler warning */ + get_next_coeff_function get_next_coeff; + + + /* Rate flag */ + rateFlag = 0; + move16(); + if (GT_16(target, 400)) + { + rateFlag = 2 << NBITS_CONTEXT; + move16(); + } + + /* proba coded on 14bits -> proba=1 */ + proba = L_deposit_l(16384); + + /* Init */ + nt_half = shr(nt, 1); + stop2 = 0; + move16(); + c[0] = c[1] = 0; + move16(); + move16(); + + /* bits to encode lastnz + 2 bits headroom */ + nbits = sub(2+14, norm_s(sub(nt, 1))); + nbits_old = nbits; + move16(); + nbits = sub(nbits, target); + + /* Find last non-zero tuple in the mapped domain signal */ + lastnz = find_last_nz_pair(x, nt, hm_cfg); + + /* At least one tuple is coded */ + lastnz2 = 2; + move16(); + + IF (hm_cfg) /* mapped domain */ + { + numPeakIndicesOrig = hm_cfg->numPeakIndices; + move16(); + hm_cfg->numPeakIndices = s_min(hm_cfg->numPeakIndices, lastnz); + move16(); + numHoleIndices = sub(lastnz, hm_cfg->numPeakIndices); + + /* Mark hole indices beyond lastnz as pruned */ + FOR (k=numHoleIndices; knumHoleIndices; ++k) + { + hm_cfg->holeIndices[k] = add(hm_cfg->holeIndices[k], nt); + move16(); + } + + ii[0] = numPeakIndicesOrig; + move16(); + ii[1] = 0; + move16(); + + get_next_coeff = get_next_coeff_mapped; + move16(); + } + ELSE /* unmapped domain */ + { + ii[0] = 0; + move16(); + + p1 = p2 = 0; + move16(); + move16(); + + get_next_coeff = get_next_coeff_unmapped; + move16(); + } + + /* Main Loop through the 2-tuples */ + FOR (k=0; k 0) + { + nbits = add(nbits, 1); + } + + if (b1 > 0) + { + nbits = add(nbits, 1); + } + + /* pre-compute address of ari_pk_s17_LC_ext[0][Val_esc] to avoid doing it multiple times inside the loop */ + + /* check while condition */ + + /* MSBs coding */ + lookup = &ari_lookup_s17_LC[t] + (1 << (NBITS_CONTEXT+NBITS_RATEQ)); /* address calculation not counted */ + WHILE (GE_16(s_max(a1, b1), A_THRES)) + { + pki = lookup[lev1]; + move16(); + cum_freq = ari_pk_s17_LC_ext[pki] + VAL_ESC; /* address calculation not counted */ + /*p1*p2=proba on 28 bits: p=0.5->power(2,27)*/ + + cum_freq_norm_e = norm_s(cum_freq[0]); + cum_freq_norm = shl(cum_freq[0], cum_freq_norm_e); + proba = Mpy_32_16_1(proba, cum_freq_norm); + proba = L_shl(proba, sub(14, cum_freq_norm_e)); + + /*Number of leading zero computed in one cycle=norm_l() in BASOP*/ + nlz = sub(norm_l(proba), 2); + proba = L_shl(proba, sub(nlz, 15)); + + nbits = add(nbits, nlz); + /*addition added as shift not done in norm_l(): real shift = 14-nlz*/ + /*proba is rounded down on 14 bits ->automatic over-estimation of bit consumption*/ + + a1 = shr(a1, 1); + b1 = shr(b1, 1); + lev1 = s_min(add(lev1, 1 << (NBITS_CONTEXT+NBITS_RATEQ)), 2 << (NBITS_CONTEXT+NBITS_RATEQ)); + } + + pki = lookup[lev1]; + move16(); + symbol = add(a1, shl(b1, A_THRES_SHIFT)); + cum_freq = ari_pk_s17_LC_ext[pki] + symbol; /* address calculation not counted */ + /*p1*p2=proba on 28 bits: p=0.5->power(2,27)*/ + + cum_freq_norm = sub(cum_freq[0], cum_freq[1]); + cum_freq_norm_e = norm_s(cum_freq_norm); + cum_freq_norm = shl(cum_freq_norm, cum_freq_norm_e); + proba = Mpy_32_16_1(proba, cum_freq_norm); + proba = L_shl(proba, sub(15, cum_freq_norm_e)); + + /*Number of leading zero computed in one cycle=norm_l() in BASOP*/ + nlz = sub(norm_l(proba), 3); + proba = L_shl(proba, sub(nlz, 14)); + + nbits = add(nbits, nlz); + /*addition added as shift not done in norm_l(): real shift = 14-nlz*/ + /*proba is rounded down on 14 bits ->automatic over-estimation of bit consumption*/ + + /* Should we truncate? */ + + IF (nbits > 0) + { + stop2 = 1; + move16(); + + IF (*stop) + { + BREAK; + } + } + ELSE + { + test(); + test(); + IF (hm_cfg || k==0 || s_or(x[a1_i], x[b1_i])) + { + nbits_old = add(nbits, target); + lastnz2 = add(b1_i, 1); + } + } + + /* Update context for next 2-tuple */ + IF (EQ_16(p1, p2)) /* peak-peak or hole-hole context */ + { + lev1 = shr(lev1, NBITS_CONTEXT+NBITS_RATEQ); + if (lev1 > 0) t = add(12, lev1); + if (lev1 <= 0) t = add(a1, b1); + if (lev1 == 0) t = add(t, t); + + *ctx = add(shl(s_and(*ctx, 0xf), 4), add(t, 1)); + move16(); + } + ELSE /* mixed context */ + { + IF (s_and(idx1, 1)) /* update first context */ + { + c[p1] = update_mixed_context(c[p1], abs_s(x[a1_i])); + move16(); + } + + IF (s_and(idx2, 1)) /* update second context */ + { + c[p2] = update_mixed_context(c[p2], abs_s(x[b1_i])); + move16(); + } + } + } /* end of the 2-tuples loop */ + + nbits = add(nbits, target); + + /* Output */ + if (*stop) + { + nbits = nbits_old; + move16(); + } + + if (stop2) + { + stop2 = nbits; + move16(); + } + *nEncoded = lastnz2; + move16(); + *stop = stop2; + move16(); + if (lastnz_out) + { + *lastnz_out = lastnz; + move16(); + } + + IF (hm_cfg) + { + /* Restore hole indices beyond lastnz */ + FOR (k=numHoleIndices; knumHoleIndices; ++k) + { + hm_cfg->holeIndices[k] = sub(hm_cfg->holeIndices[k], nt); + move16(); + } + hm_cfg->numPeakIndices = numPeakIndicesOrig; + move16(); + } + + + return nbits_old; +} + + diff --git a/lib_enc/FEC_enc_fx.c b/lib_enc/FEC_enc_fx.c new file mode 100644 index 0000000..404dd2b --- /dev/null +++ b/lib_enc/FEC_enc_fx.c @@ -0,0 +1,294 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" + + + +/*============================================================================*/ +/* FUNCTION : void FEC_encode_fx() */ +/*----------------------------------------------------------------------------*/ +/* PURPOSE : Encoder supplementary information for FEC */ +/*----------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 *synth i : pointer to synthesized speech for E computation */ +/* Word16 coder_type i : type of coder */ +/* Word16 clas i : signal clas for current frame */ +/* Word16 *fpit i : close loop fractional pitch buffer */ +/* Word16 *res i : LP residual signal frame */ +/* Word16 L_frame i : Frame length */ +/* Word32 total_brate i : total codec bitrate */ +/*----------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*----------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Word16 *last_pulse_pos i/o: Position of the last pulse */ +/* Encoder_State_fx *st_fx i/o: state structure */ +/*----------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*----------------------------------------------------------------------------*/ +/* */ +/*============================================================================*/ +void FEC_encode_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *synth, /* i : pointer to synthesized speech for E computation */ + const Word16 coder_type, /* i : type of coder */ + Word16 clas, /* i : signal clas for current frame */ + const Word16 *fpit, /* i : close loop fractional pitch buffer */ + const Word16 *res, /* i : LP residual signal frame */ + Word16 *last_pulse_pos, /* i/o: Position of the last pulse */ + const Word16 L_frame, /* i : Frame length */ + const Word32 total_brate, /* i : total codec bitrate */ + const Word32 core_brate, /* i : total codec bitrate */ + const Word16 Q_new, /* i : input scaling */ + const Word16 shift /* i : scaling to get 12bits */ +) +{ + Word16 tmpS, index; + Word16 maxi, sign, tmp_FER_pitch; + Word32 enr_q, Ltmp; + Word16 enr_lg_ent, enr_lg_frac, exp_enrq; + + + tmpS = 0; + move16(); + enr_q = 1; + move16(); + sign = 0; + move16(); + test(); + test(); + IF( GT_16(coder_type,UNVOICED)&<_16(coder_type,AUDIO)&&GE_32(core_brate,ACELP_11k60)) + { + /*-----------------------------------------------------------------* + * encode signal class (not needed for VC mode since it is clearly voiced) (2 bits) + *-----------------------------------------------------------------*/ + IF ( NE_16(coder_type,VOICED)) + { + /* encode signal clas with 2 bits */ + test(); + IF(EQ_16(clas,UNVOICED_CLAS)) + { + index = 0; + move16(); + } + ELSE IF( EQ_16(clas,VOICED_TRANSITION)||EQ_16(clas,UNVOICED_TRANSITION)) + { + index = 1; + move16(); + } + ELSE IF( EQ_16(clas,VOICED_CLAS)) + { + index = 2; + move16(); + } + ELSE + { + index = 3; + move16(); + } + push_indice_fx( st_fx, IND_FEC_CLAS, index, FEC_BITS_CLS); + } + + /*-----------------------------------------------------------------* + * encode frame energy (5 bits) + *-----------------------------------------------------------------*/ + test(); + IF( GE_32(total_brate,ACELP_16k40)&&NE_16(coder_type,TRANSITION)) /* GENERIC and VOICED frames */ + { + /* frame energy (maximum energy per pitch period for voiced frames or mean energy per sample over 2nd halframe for unvoiced frames) */ + /*frame_ener( L_frame, clas, synth, fpit[(L_frame>>6)-1], &enr_q, 0 );*/ + exp_enrq = frame_ener_fx( L_frame, clas, synth, shr_r(fpit[sub(shr(L_frame , 6),1)],6), &enr_q, L_frame, Q_new, shift, 1); + + /* linearly quantize the energy in the range 0 : FEC_ENR_STEP : 96 dB */ + /*tmpS = (short)( 10.0 * log10( enr_q + 0.001f ) / FEC_ENR_STEP )*/ /*To be converted fl_2_fx*/ + + enr_lg_frac = Log2_norm_lc(enr_q); + enr_lg_ent = sub(30, exp_enrq); + Ltmp = Mpy_32_16(enr_lg_ent,enr_lg_frac, LG10_s3_0); + tmpS = extract_h(L_shl(Ltmp, 1)); + + tmpS = s_min(tmpS, 31); + tmpS = s_max(tmpS, 0); + + push_indice_fx( st_fx, IND_FEC_ENR, tmpS, FEC_BITS_ENR ); + } + /*-----------------------------------------------------------------* + * Encode last glottal pulse position (8 bits) + *-----------------------------------------------------------------*/ + test(); + IF( GE_32(total_brate,ACELP_32k)&&NE_16(coder_type,TRANSITION)) /* GENERIC frames */ + { + /* retrieve the last glottal pulse position of the previous frame */ + /* use the current pitch information to scale or not the quantization */ + tmp_FER_pitch = shr(fpit[0],6); /* take the 1st subframe pit, since it is easier to get on decoder side */ + sign = 0; + move16(); + maxi = *last_pulse_pos; + move16(); + IF ( maxi < 0 ) + { + sign = 1; + move16(); + /*maxi = -maxi; */ + maxi = negate(maxi); + } + + if ( GE_16(tmp_FER_pitch,128)) + { + maxi = shr(maxi , 1); + } + + if ( GT_16(maxi,127)) + { + /* better not use the glottal pulse position at all instead of using a wrong pulse */ + /* can happen only with pitch > 254 and max pit = 289 and should happen very rarely */ + maxi = 0; + move16(); + } + + if( sign == 1 ) + { + maxi = add(maxi,128);/* use 8 bits (MSB represent the sign of the pulse) */ + } + + push_indice_fx( st_fx, IND_FEC_POS, maxi, FEC_BITS_POS ); + } + maxi = 0; + move16(); + + /* If bitrate < 24k4, then the pitch + is not represented in the same domain (12.k instead of 16k) */ + test(); + IF( GE_16(clas,VOICED_CLAS)&&GE_32(total_brate,ACELP_24k40)) + { + /*maxi = findpulse( L_frame, res, (short)(fpit[(L_frame>>6)-1]), 0, &sign ); */ + maxi = findpulse_fx( L_frame, res, shr_r(fpit[sub(shr(L_frame , 6) , 1)], 6), 0, &sign ); + if ( sign == 1 ) + { + /*maxi = -maxi;*/ + maxi = negate(maxi); + } + } + + *last_pulse_pos = maxi; + move16(); + } + ELSE + { + *last_pulse_pos = 0; + move16(); + } + + return; +} + + +/*-------------------------------------------------------------------* +* FEC_lsf_estim_enc_fx() +* +* Simulates LSF estimation in case of FEC in the encoder ( only one frame erasure is considered ) +* The estimated LSF vector is then used to check LSF stability and may invoke safety-net usage in the next frame +*-------------------------------------------------------------------*/ + +void FEC_lsf_estim_enc_fx( + Encoder_State_fx *st_fx, /* i : Encoder static memory */ + const Word16 L_frame, /* i : length of the frame */ + Word16 *lsf /* o : estimated LSF vector */ +) +{ + Word16 i; + Word16 alpha, lsf_mean[M]; + Word16 tmp; + + IF( EQ_16(L_frame, L_FRAME)) + { + Copy( UVWB_Ave_fx, lsf_mean, M ); + } + ELSE + { + Copy( GEWB2_Ave_fx, lsf_mean, M ); + } + + /*----------------------------------------------------------------------* + * Initialize the alpha factor + *----------------------------------------------------------------------*/ + + IF( EQ_16(st_fx->last_coder_type_fx, UNVOICED)) + { + /* clearly unvoiced */ + alpha = _ALPHA_UU_FX; + move16(); + } + ELSE + { + test(); + test(); + IF( EQ_16(st_fx->last_coder_type_fx, AUDIO)||EQ_16(st_fx->clas_fx,INACTIVE_CLAS)) + { + alpha = 32604; + move16(); + } + ELSE IF( EQ_16(st_fx->clas_fx, UNVOICED_CLAS)) + { + /* if stable, do not flatten the spectrum in the first erased frame */ + /* alpha = st->stab_fac * (1.0f - 2.0f*ALPHA_U) + 2.0f*ALPHA_U; */ + alpha = add(mult(st_fx->stab_fac_fx, 32768 - _ALPHA_U_FX_X_2), _ALPHA_U_FX_X_2); + } + ELSE IF( EQ_16(st_fx->clas_fx, UNVOICED_TRANSITION)) + { + alpha = _ALPHA_UT_FX; + move16(); + } + ELSE IF( EQ_16(st_fx->clas_fx, VOICED_CLAS)||EQ_16(st_fx->clas_fx,ONSET)) + { + /* clearly voiced - mild convergence to the CNG spectrum for the first three erased frames */ + alpha = _ALPHA_V_FX; + move16(); + } + ELSE IF( EQ_16(st_fx->clas_fx, SIN_ONSET)) + { + alpha = _ALPHA_S_FX; + move16(); + } + ELSE + { + /* long erasures and onsets - rapid convergence to the CNG spectrum */ + alpha = _ALPHA_VT_FX; + move16(); + } + } + /*----------------------------------------------------------------------* + * Extrapolate LSF vector + *----------------------------------------------------------------------*/ + tmp = sub(32767, alpha); + /* extrapolate the old LSF vector */ + FOR (i=0; ilsf_adaptive_mean[i]; */ + lsf_mean[i] = mac_r(L_mult(BETA_FEC_FX, lsf_mean[i]), 32768-BETA_FEC_FX, st_fx->lsf_adaptive_mean_fx[i]); + + /* move old LSF vector towards the mean LSF vector */ + /* lsf[i] = alpha * st->lsf_old[i] + (1.0f - alpha) * lsf_mean[i]; */ + lsf[i] = mac_r(L_mult(alpha, st_fx->lsf_old_fx[i]), tmp, lsf_mean[i]); + } + + /* check LSF stability through LSF ordering */ + IF( EQ_16(L_frame, L_FRAME)) + { + reorder_lsf_fx( lsf, MODE1_LSF_GAP_FX, M , INT_FS_FX); + } + ELSE /* L_frame == L_FRAME16k */ + { + reorder_lsf_fx( lsf, MODE1_LSF_GAP_FX, M, INT_FS_16k_FX); + } + + return; +} diff --git a/lib_enc/SNR_calc.c b/lib_enc/SNR_calc.c new file mode 100644 index 0000000..d40df5b --- /dev/null +++ b/lib_enc/SNR_calc.c @@ -0,0 +1,525 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include + +#include "basop_util.h" +#include "options.h" +#include "stl.h" +#include "vad_basop.h" +#include "rom_enc_fx.h" +#include "prot_fx.h" +#include "rom_enc_fx.h" + + + +void calc_lf_snr( + Word32 *lf_snr_smooth, /*(o) smoothed lf_snr*/ + Word32 *lf_snr, /*(o) long time frequency domain + SNR calculated by l_speech_snr and l_silence_snr*/ + Word32 l_speech_snr, /*(i) sum of active frames snr */ + Word32 l_speech_snr_count, /*(i) amount of the active frame */ + Word32 l_silence_snr, /*(i) sum of the nonactive frames snr*/ + Word32 l_silence_snr_count, /*(i) amount of the nonactive frame */ + Word16 fg_energy_count, /*(i) amount of the foreground energy frame */ + Word16 bg_energy_count, /*(i) amount of the background energy frame */ + Word16 bw_index /*(i) band width index*/ +) +{ + + Word32 l_snr,div1,div2,tmp; + Word16 q_divout,q_divout1; + + + div1 = VAD_L_div(l_speech_snr,l_speech_snr_count,16,0,&q_divout); + div2 = VAD_L_div(l_silence_snr,l_silence_snr_count,16,0,&q_divout1); + l_snr = VAD_L_ADD(div1,q_divout,L_negate(div2),q_divout1,&q_divout); + + *lf_snr_smooth = MUL_F(*lf_snr_smooth, 29490/* 0.9 Q15 */); + move32(); + tmp = MUL_F(l_snr, 26214); + *lf_snr_smooth = VAD_L_ADD( *lf_snr_smooth, 25, tmp, add(3,q_divout), &q_divout1); + move32(); + *lf_snr_smooth = L_shr(*lf_snr_smooth, sub(q_divout1, 25)); + move32(); + l_snr = L_shr(l_snr, sub(q_divout, 25)); + + test(); + if(( LT_16(bg_energy_count, 56))||(LT_16(fg_energy_count,56))) + { + l_snr = 161061275/* 4.8 Q25 */; + move32(); + } + + l_snr = MUL_F(l_snr, 3932/* 0.12 Q15 */); + l_snr = L_sub(l_snr, 12079595/* 0.36 Q25 */); + + l_snr = L_max(0, l_snr); + l_snr = L_min(l_snr, MAX_LF_SNR_TAB[bw_index]); + + *lf_snr = l_snr; + move32(); + +} + +void calc_lt_snr(T_CldfbVadState *st, /*(io) vad state*/ + Word32 *lt_snr_org_fp, /*(o) original long time SNR*/ + Word32 *lt_snr_fp, /*(o) long time SNR calculated by fg_energy and bg_energy*/ + Word32 fg_energy, /*(i) foreground energy sum */ + Word16 fg_energy_count, /*(i) amount of the foreground energy frame */ + Word32 bg_energy, /*(i) background energy sum */ + Word16 bg_energy_count, /*(i) amount of the background energy frame */ + Word16 bw_index, /*(i) band width index*/ + Word16 lt_noise_sp_center0 /*(i) long time noise spectral center by 0*/ + ) +{ + Word16 tmp_lt_noise_sp_center; + Word16 q_div1,q_div2,q_divout,q_divout1; + Word32 lt_snr_org; + Word32 lt_snr,div1,div2,tmp; + + + tmp_lt_noise_sp_center = sub(lt_noise_sp_center0,1432/* 1.4 Q10 */); + if(GT_16(tmp_lt_noise_sp_center, 818/* 0.8 Q10 */)) + { + tmp_lt_noise_sp_center = 818/* 0.8 Q10 */; + move16(); + } + + if(tmp_lt_noise_sp_center<0) + { + tmp_lt_noise_sp_center = 0; + move16(); + } + + div1 = MUL_F(fg_energy,bg_energy_count); + div1 = VAD_L_ADD(div1,st->fg_energy_scale, 1, 126 ,&q_div1); + div2 = MUL_F(bg_energy,fg_energy_count); + div2 = VAD_L_ADD(div2,st->bg_energy_scale, 1, 126 ,&q_div2); + if( div2 == 0 ) + { + div2 = 1; + move32(); /* div2==0 , may occur for >30000 frames all zero input */ + if(div1 != 0) + { + st->bg_energy_scale = add(st->fg_energy_scale, 50); + } + } + div2 = VAD_L_div(div1,div2,q_div1,q_div2,&q_divout); + lt_snr_org = VAD_Log2(div2,q_divout); + lt_snr_org = MUL_F(lt_snr_org, 9864); + lt_snr = lt_snr_org; move32(); + *lt_snr_org_fp = lt_snr; + move32(); + + test(); + IF(LT_16(bg_energy_count, 56)||LT_16(fg_energy_count,56)) + { + lt_snr = 70464302/* 2.1 Q25 */; + move32(); + } + + IF(EQ_16(bw_index, CLDFBVAD_NB_ID)) + { + lt_snr = L_sub(L_shr(lt_snr,1), 25165823/* 0.75 Q25 */); + } + ELSE IF(EQ_16(bw_index, CLDFBVAD_WB_ID)) + { + lt_snr = L_sub(L_shr(lt_snr,1), 25165823/* 0.75 Q25 */); + } + ELSE + { + lt_snr = MUL_F(lt_snr, 15073/* 0.46 Q15 */); + lt_snr = L_sub(lt_snr, 23152557/* 0.69 Q25 */); + } + + tmp = MUL_F(lt_snr,13107/* 0.4 Q15 */); + + tmp = L_add(L_shr(tmp,1), -26214); + + tmp = MUL_F(tmp, 13107/* 0.4 Q15 */); + tmp = MUL_F(tmp,tmp_lt_noise_sp_center); + lt_snr = VAD_L_ADD(lt_snr, 25, tmp,19, &q_divout1); + lt_snr = L_shr(lt_snr, sub(q_divout1,25)); + + lt_snr = L_max(0, lt_snr); + + if(GT_32(lt_snr,67108862/* 2.0 Q25 */)) + { + lt_snr = 67108862/* 2.0 Q25 */; + move32(); + } + + *lt_snr_fp = lt_snr; + move32(); + +} + + +void calc_snr_flux( + Word32 tsnr, /*(i) time-domain SNR*/ + Word32 *pre_snr, /*(io) time-domain SNR storage*/ + Word32 *snr_flux_fp /*(o) average tsnr*/ +) +{ + Word32 i; + Word32 tmp, snr_flux; + Word16 s16MaxCoefNorm; + /*save a new time-domain SNR to pre_snr[0]*/ + + + test(); + IF( (LT_32(L_shr(tsnr,1) , 43620759/* 2.6f/2.0f Q25 */))&&tsnr>0) + { + pre_snr[0] = tsnr; + move32(); + } + ELSE IF(tsnr <= 0) + { + pre_snr[0] = 0; + move32(); + } + ELSE + { + pre_snr[0] = 87241517/* 2.6 Q25 */; + move32(); + } + + /*calculate snr_flux*/ + snr_flux = 0; + move32(); + s16MaxCoefNorm = sub(ffr_getSfWord32(pre_snr, 32), 5); + FOR(i=0; i<32; i++) + { + tmp = L_shl(pre_snr[i],s16MaxCoefNorm); + snr_flux = L_add(snr_flux, tmp); + } + snr_flux = L_shr(snr_flux,add(s16MaxCoefNorm,5)); + *snr_flux_fp = snr_flux; + move32(); + + /*update the tsnr storage pre_snr*/ + FOR(i=PRE_SNR_NUM-1; i>0; i--) + { + pre_snr[i] = pre_snr[i-1]; + move32(); + } + +} + + + +void snr_calc(T_CldfbVadState *st, /*(io) vad state*/ + Word16 sacle_sbpower, /*(i) the Scaling of sbpower*/ + Word32 *snr, /*(o) frequency domain SNR */ + Word32 *tsnr, /*(o) time domain SNR */ + Word32 frame_energy, /*(i) current frame energy */ + Word32 bandwith /*(i) band width*/ + ) +{ + Word32 i; + Word32 tmpframe_eg,tmpsb_eg,constff,div1,div2; + Word32 snr_tmp, tmp; + + Word32 SNR_sb_num; + Word32 *sb_bg_energy ; + Word32 *frame_sb_energy ; + Word32 t_bg_energy; + Word16 tmp_addQ1,tmp_addQ2,minscale,minscale1,minscale2,s16MaxCoefNorm,q_divout; + Word32 tmpspec_amp; + Word32 const CONSTfix= 1759218560; + Word32 snr_tmpidx[12] = {0}; + + + SNR_sb_num = SNR_SUB_BAND_NUM[bandwith-CLDFBVAD_NB_ID]; + move16(); + sb_bg_energy = st->sb_bg_energy; + frame_sb_energy = st->frame_sb_energy; + t_bg_energy = st->t_bg_energy; + move32(); + + snr_tmp = 0; + move32(); + FOR(i=0; iframe_sb_energy_scale, CONSTfix, 44, &tmp_addQ1); + div2 = VAD_L_ADD(sb_bg_energy[i], st->sb_bg_energy_scale, CONSTfix, 44, &tmp_addQ2); + tmp = VAD_L_div(div1, div2, tmp_addQ1, tmp_addQ2, &q_divout); + tmp = VAD_Log2(tmp, q_divout); + + if(GT_32(tmp, -3355443/* -0.10 Q25 */)) + { + snr_tmpidx[i] = tmp; + move32(); + } + } + + s16MaxCoefNorm = sub(ffr_getSfWord32(snr_tmpidx, (Word16)SNR_sb_num), 4); + FOR(i=0; i< SNR_sb_num; i++) + { + tmpspec_amp = L_shl(snr_tmpidx[i], s16MaxCoefNorm); + snr_tmp = L_add(snr_tmp, tmpspec_amp); + } + snr_tmp = L_max(0, snr_tmp); + snr_tmp = MUL_F(snr_tmp,BAND_MUL[bandwith-CLDFBVAD_NB_ID]); + *snr = L_shr(snr_tmp,s16MaxCoefNorm); + move32(); + + IF(bandwith == CLDFBVAD_SWB_ID) + { + IF(t_bg_energy) + { + minscale = norm_l(t_bg_energy); + minscale2 = sub(s_min(add(minscale,st->scale_t_bg_energy),31),1); + tmpsb_eg = L_shr(t_bg_energy,sub(st->scale_t_bg_energy,minscale2)); + constff = L_shr(1,sub(31,minscale2)); + } + ELSE + { + tmpsb_eg = 0; move32(); + constff = 1; move32(); + minscale2 = 31; + move16(); + } + div2 = L_add(tmpsb_eg,constff); + tmp = VAD_L_div(frame_energy, div2, sacle_sbpower, minscale2, &q_divout); + IF(tmp) + { + minscale = norm_l(tmp); + minscale2 = sub(s_min(add(minscale,q_divout), 31), 1); + tmpsb_eg = L_shr(tmp, limitScale32(sub(q_divout, minscale2))); + constff = L_shr(1, sub(31, minscale2)); + tmp = L_add(tmpsb_eg, constff); + } + ELSE + { + tmp = 1; move32(); + minscale2 = 31; + move16(); + } + *tsnr = VAD_Log2(tmp, minscale2); + move32(); + *tsnr = L_add(*tsnr, MUL_F(*tsnr, 6226)); /* *tsnr *= 1.2; */ + move32(); + } + ELSE + { + IF(frame_energy) + { + minscale = norm_l(frame_energy); + minscale1 = sub(s_min(add(minscale,sacle_sbpower),44),1); + tmpframe_eg = L_shr(frame_energy,sub(sacle_sbpower,minscale1)); + constff = L_shr(CONSTfix,sub(44,minscale1)); + } + ELSE + { + tmpframe_eg = 0; move32(); + constff = CONSTfix; move32(); + minscale1 = 44; + move16(); + } + div1 = L_add(tmpframe_eg, constff); + IF(t_bg_energy) + { + minscale = norm_l(t_bg_energy); + minscale2 = sub(s_min(add(minscale,st->scale_t_bg_energy),44),1); + tmpsb_eg = L_shr(t_bg_energy,sub(st->scale_t_bg_energy,minscale2)); + constff = L_shr(CONSTfix,sub(44,minscale2)); + } + ELSE + { + tmpsb_eg = 0; move32(); + constff = CONSTfix; move32(); + minscale2 = 44; + move16(); + } + div2 = L_add(tmpsb_eg, constff); + tmp = VAD_L_div(div1, div2, minscale1, minscale2, &q_divout); + *tsnr = VAD_Log2(tmp,q_divout); + move32(); + } + +} + +Word32 construct_snr_thresh( Word16 sp_center[], /*(i) spectral center*/ + Word32 snr_flux, /*(i) snr flux*/ + Word32 lt_snr, /*(i) long time time domain snr*/ + Word32 l_snr, /*(i) long time frequency domain snr*/ + Word32 continuous_speech_num, /*(i) amount of continuous speech frames*/ + Word16 continuous_noise_num, /*(i) amount of continuous noise frames*/ + Word32 fg_energy_est_start, /*(i) whether if estimated energy*/ + Word16 bw_index /*(i) band width index*/ + ) +{ + + Word32 bw_snr,tmp_snr,snr_delta,test_l_snr,tmp,div1,div2; + + + + + snr_delta = COMVAD_INIT_SNR_DELTA[bw_index]; + move32(); + bw_snr = lt_snr; + move32(); + + + + test_l_snr = lt_snr; move32(); + IF(EQ_16(bw_index, CLDFBVAD_SWB_ID)) + { + + IF(GT_16(sp_center[3], 2864/* 2.80 Q10 */)) + { + snr_delta = snr_delta; + move32(); + } + ELSE IF(GT_16(sp_center[2], 2660/* 2.6 Q10 */)) + { + snr_delta = L_add(snr_delta, 1006633/* 0.03 Q25 */); + } + ELSE IF(GT_16(sp_center[2], 1637/* 1.6 Q10 */)) + { + snr_delta = L_add(snr_delta ,1677722/* 0.05 Q25 */); + } + ELSE IF(GT_16(sp_center[3], 1432/* 1.4 Q10 */)) + { + snr_delta = L_add(snr_delta , 3355443/* 0.10 Q25 */); + } + ELSE + { + snr_delta = L_add(snr_delta , 13421773/* 0.40 Q25 */); + } + + tmp = MUL_F(l_snr, 3277/* 0.1 Q15 */); + tmp = L_add(tmp,20132659/* 0.6 Q25 */); + + test(); + test(); + IF(GT_32(continuous_speech_num, 8)&&EQ_32(fg_energy_est_start,1)) + { + snr_delta = L_sub(snr_delta, 6710886/* 0.2 Q25 */); + } + ELSE IF(GT_16(continuous_noise_num,12)&&(GT_32(snr_flux,tmp))) + { + snr_delta = L_add(snr_delta, 3355443/* 0.10 Q25 */); + } + ELSE IF(GT_16(continuous_noise_num, 24)) + { + snr_delta = L_add(snr_delta, 6710886/* 0.2 Q25 */); + } + ELSE IF((GT_16(continuous_noise_num, 4))) + { + snr_delta = L_add(snr_delta, 3355443/* 0.10 Q25 */); + } + } + ELSE IF(EQ_16(bw_index, CLDFBVAD_WB_ID)) + { + + IF(GT_16(sp_center[3], 2864/* 2.80 Q10 */)) + { + snr_delta = snr_delta; + move32(); + } + ELSE IF(GT_16(sp_center[2], 2660/* 2.6 Q10 */)) + { + snr_delta = L_add(snr_delta, 1006633/* 0.03 Q25 */); + } + ELSE IF(GT_16(sp_center[2], 1637/* 1.6 Q10 */)) + { + snr_delta = L_add(snr_delta, 1677722/* 0.05 Q25 */); + } + ELSE IF(GT_16(sp_center[3], 1432/* 1.4 Q10 */)) + { + snr_delta = L_add(snr_delta, 3355443/* 0.10 Q25 */); + } + ELSE + { + snr_delta = L_add(snr_delta, 10066330/* 0.30 Q25 */); + } + + tmp = MUL_F(bw_snr, 3277/* 0.1 Q15 */); + tmp = L_add(tmp,20132659/* 0.6 Q25 */); + + test(); + test(); + IF(GT_32(continuous_speech_num, 8)&&EQ_32(fg_energy_est_start,1)) + { + snr_delta = L_sub(snr_delta, 3355443/* 0.10 Q25 */); + } + ELSE IF(GT_16(continuous_noise_num,12)&&(GT_32(snr_flux,tmp))) + { + snr_delta = L_add(snr_delta, 3355443/* 0.10 Q25 */); + } + ELSE IF(GT_16(continuous_noise_num,24)) + { + snr_delta = L_add(snr_delta, 6710886/* 0.20 Q25 */); + } + ELSE IF((GT_16(continuous_noise_num,4))) + { + snr_delta = L_add(snr_delta, 3355443/* 0.10 Q25 */); + } + } + ELSE IF(EQ_16(bw_index, CLDFBVAD_NB_ID)) + { + + IF(GT_16(sp_center[3], 3069/* 3.0 Q10 */)) + { + snr_delta = snr_delta; + move32(); + } + ELSE IF(GT_16(sp_center[2], 2660/* 2.6 Q10 */)) + { + snr_delta = L_add(snr_delta , 671089/* 0.02 Q25 */); + } + ELSE IF(GT_16(sp_center[2],1637/* 1.6 Q10 */)) + { + snr_delta = L_add(snr_delta , 1342177/* 0.04 Q25 */); + } + ELSE IF(GT_16(sp_center[2], 1494/* 1.46 Q10 */)) + { + snr_delta = L_add(snr_delta , 3355443/* 0.10 Q25 */); + } + ELSE + { + snr_delta = L_add(snr_delta , 6039798/* 0.18 Q25 */); + } + + tmp = MUL_F(l_snr, 3277/* 0.1 Q15 */); + div1 = L_add(tmp,6710886/* 0.2 Q25 */); + div2 = L_add(tmp,20132659/* 0.6 Q25 */); + + test(); + test(); + test(); + test(); + test(); + IF(GT_32(continuous_speech_num, 80)&&EQ_32(fg_energy_est_start,1)&&(GT_16(sp_center[0],1432/* 1.4 Q10 */))) + { + snr_delta = L_sub(snr_delta, 10737418/* 0.32 Q25 */); + } + ELSE IF(GT_32(continuous_speech_num,8)&&EQ_32(fg_energy_est_start,1)&&(GT_32(snr_flux,div1))) + { + snr_delta = L_sub(snr_delta, 3355443/* 0.10 Q25 */); + } + ELSE IF(GT_16(continuous_noise_num,12)&&(GT_32(snr_flux,div2))) + { + snr_delta = L_add(snr_delta, 3355443/* 0.10 Q25 */); + } + ELSE IF(GT_16(continuous_noise_num, 24)) + { + snr_delta = L_add(snr_delta, 6710886/* 0.2 Q25 */); + } + } + ELSE + { + snr_delta = 33554431/* 1.0 Q25 */; + move32(); + } + tmp_snr = L_add(snr_delta, test_l_snr); + + + return tmp_snr; +} + diff --git a/lib_enc/acelp_core_enc_fx.c b/lib_enc/acelp_core_enc_fx.c new file mode 100644 index 0000000..b7fb8b5 --- /dev/null +++ b/lib_enc/acelp_core_enc_fx.c @@ -0,0 +1,654 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_enc_fx.h" /* Encoder static table prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * acelp_core_enc() + * + * ACELP core encoder + *--------------------------------------------------------------------*/ +void acelp_core_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 inp_fx[], /* i : input signal of the current frame */ + const Word16 vad_flag_fx, + const Word32 ener_fx, /* i : residual energy from Levinson-Durbin*/ + const Word16 pitch[3], /* i : open-loop pitch values for quantiz. */ + const Word16 voicing_fx[3], /* i : Open-loop pitch gains */ + Word16 A_fx[NB_SUBFR16k*(M+1)], /* i : A(z) unquantized for the 4 subframes*/ + Word16 Aw_fx[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/ + const Word16 epsP_h_fx[M+1], /* i : LP prediction errors */ + const Word16 epsP_l_fx[M+1], /* i : LP prediction errors */ + Word16 lsp_new_fx[M], /* i : LSPs at the end of the frame */ + Word16 lsp_mid_fx[M], /* i : LSPs in the middle of the frame */ + Word16 coder_type_fx, /* i : coding type */ + const Word16 sharpFlag_fx, /* i : formant sharpening flag */ + Word16 vad_hover_flag_fx, + const Word16 gsc_attack_flag_fx, /* i : flag signalling attack encoded by AC mode (GSC) */ + Word32 bwe_exc_extended_fx[], /* i/o: bandwidth extended excitation */ + Word16 *voice_factors_fx, /* o : voicing factors */ + Word16 old_syn_12k8_16k_fx[], /* o : intermediate ACELP synthesis at 12.8kHz or 16kHz to be used by SWB BWE */ + Word16 pitch_buf_fx[NB_SUBFR16k], /* o : floating pitch for each subframe */ + Word16 *unbits_fx, /* o : number of unused bits */ + const Word16 Q_new, + const Word16 shift +) +{ + Word16 nBits; /* reserved bits */ + Word16 i; + Word16 old_exc_fx[L_EXC], *exc_fx; /* excitation signal buffer */ + Word16 lsf_new_fx[M]; /* ISFs at the end of the frame */ + Word16 Aq_fx[NB_SUBFR16k*(M+1)]; /* A(z) quantized for the 4 subframes */ + Word16 syn_fx[L_FRAME16k]; /* synthesis vector */ + Word16 res_fx[L_FRAME16k]; /* Residual signal for FER protection */ + Word16 exc2_fx[L_FRAME16k]; /* enhanced excitation */ + Word16 Es_pred_fx; /* predicited scaled innovation energy */ + Word16 tmp_noise_fx; /* NB post-filter long-term noise energy*/ + Word16 tc_subfr_fx; /* TC sub-frame indication */ + Word16 old_bwe_exc_fx[(PIT16k_MAX + (L_FRAME16k + 1) + L_SUBFR16k) * 2]; /* excitation buffer */ + Word16 *bwe_exc_fx; /* excitation for SWB TBE */ + Word16 allow_cn_step_fx; + Word16 int_fs_fx; + Word32 L_epsP[2]; + /* SC-VBR - back-up memories for LSF quantizer and synthesis filter */ + Word16 mCb1_fx, pstreaklen_fx; + Word16 mem_MA_fx[M], mem_AR_fx[M], lsp_new_bck_fx[M], lsf_new_bck_fx[M], lsp_mid_bck_fx[M], mem_syn_bck_fx[M]; + Word32 Bin_E_fx[L_FFT], Bin_E_old_fx[L_FFT/2]; + Word16 clip_var_fx, mem_w0_bck_fx, streaklimit_fx; + Word16 T_op_fx[3]; + Word16 nb_bits; + Word16 indice; + Word16 tmp16; + Word16 enr_index; + Word16 enr, maxv, scale, att; + Word16 hi, lo; + Word16 *pt_res; + Word32 L_tmp, L_ener; + + Word16 tilt_code_bck_fx; + Word32 gc_threshold_bck_fx; + Word16 clip_var_bck_fx[6]; + Word16 next_force_sf_bck_fx; + Word32 q_env[NUM_ENV_CNG]; + Word16 sid_bw=-1; + Word16 exc3_fx[L_FRAME16k]; + Word16 syn1_fx[L_FRAME16k]; + + + + /*------------------------------------------------------------------* + * Initialization + *------------------------------------------------------------------*/ + + Es_pred_fx = 0; + move16(); + + Copy( pitch, T_op_fx, 3 ); + + /* convert pitch values to 16kHz domain */ + IF ( EQ_16(st_fx->L_frame_fx,L_FRAME16k)) + { + /*T_op[0] = (short)(T_op[0] * 1.25f + 0.5f);*/ + T_op_fx[0] = round_fx(L_mac(L_shl(T_op_fx[0],16), T_op_fx[0], 8192)); + /*T_op[1] = (short)(T_op[1] * 1.25f + 0.5f);*/ + T_op_fx[1] = round_fx(L_mac(L_shl(T_op_fx[1],16), T_op_fx[1], 8192)); + T_op_fx[2] = T_op_fx[1]; + move16(); + } + exc_fx = old_exc_fx + L_EXC_MEM; /* pointer to excitation signal in the current frame */ + Copy( mem->old_exc, old_exc_fx, L_EXC_MEM ); + + bwe_exc_fx = old_bwe_exc_fx + PIT16k_MAX * 2; /* pointer to BWE excitation signal in the current frame */ + Copy( st_fx->old_bwe_exc_fx, old_bwe_exc_fx, PIT16k_MAX * 2); + + st_fx->bpf_off_fx = 0; + move16(); + test(); + IF( EQ_16(st_fx->last_core_fx,HQ_CORE)||EQ_16(st_fx->last_codec_mode,MODE2)) + { + /* in case of HQ->ACELP switching, do not apply BPF */ + st_fx->bpf_off_fx = 1; + move16(); + st_fx->Last_frame_ener_fx = MAX_32; + move32(); + } + + /* force safety-net LSFQ in the first frames after CNG segment */ + if( LE_32(st_fx->last_core_brate_fx,SID_2k40)) + { + st_fx->Nb_ACELP_frames_fx = 0; + move16(); + } + st_fx->Nb_ACELP_frames_fx = add(st_fx->Nb_ACELP_frames_fx,1); + + int_fs_fx = INT_FS_16k_FX; + move16(); + if( EQ_16(st_fx->L_frame_fx, L_FRAME)) + { + int_fs_fx = INT_FS_FX; + move16(); + } + + tmp_noise_fx = 0; + move16(); + tc_subfr_fx = 0; + move16(); + + /* SC-VBR temporary variables */ + mCb1_fx = 0; + move16(); + pstreaklen_fx = 0; + move16(); + clip_var_fx = 0; + move16(); + mem_w0_bck_fx = 0; + move16(); + streaklimit_fx = 0; + move16(); + + /* channel-aware mode */ + reset_rf_indices(st_fx); + + /*-----------------------------------------------------------------* + * ACELP@12k8 / ACELP@16k switching + *-----------------------------------------------------------------*/ + test(); + IF( NE_16(st_fx->last_L_frame_fx,st_fx->L_frame_fx)&&NE_16(st_fx->last_core_fx,HQ_CORE)) + { + /* in case of switching, do not apply BPF */ + st_fx->bpf_off_fx = 1; + move16(); + + /* force safety-net LSFQ in the first frames after ACELP@12k8/ACELP@16k switching */ + st_fx->Nb_ACELP_frames_fx = 1; + move16(); + + /* convert old quantized LSP vector */ + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + st_fx->rate_switching_reset = lsp_convert_poly_fx( st_fx->lsp_old_fx, st_fx->L_frame_fx, 0 ); + } + ELSE + { + st_fx->rate_switching_reset=st_fx->rate_switching_reset_16kHz; + move16(); + Copy( st_fx->lsp_old16k_fx, st_fx->lsp_old_fx, M ); + } + + /* convert old quantized LSF vector */ + lsp2lsf_fx( st_fx->lsp_old_fx, st_fx->lsf_old_fx, M, int_fs_fx ); + + /* interpolation of unquantized ISPs */ + IF( st_fx->rate_switching_reset ) + { + /*extrapolation in case of unstable LSP*/ + int_lsp4_fx( st_fx->L_frame_fx, lsp_mid_fx, lsp_mid_fx, lsp_new_fx, A_fx, M, 0 ); + } + ELSE + { + int_lsp4_fx( st_fx->L_frame_fx, st_fx->lsp_old_fx, lsp_mid_fx, lsp_new_fx, A_fx, M, 0 ); + } + + /* Reset LPC mem */ + Copy( GEWB_Ave_fx, st_fx->mem_AR_fx, M ); + set16_fx( st_fx->mem_MA_fx,0, M ); + + /* update synthesis filter memories */ + synth_mem_updt2( st_fx->L_frame_fx, st_fx->last_L_frame_fx, mem->old_exc, mem->mem_syn_r,mem->mem_syn2, mem->mem_syn, ENC ); + Copy( mem->old_exc, old_exc_fx, L_EXC_MEM ); + Copy( mem->mem_syn2,st_fx->mem_syn1_fx, M ); + Copy( mem->mem_syn2, mem->mem_syn3, M ); + + /* update Aw[] coefficients */ + weight_a_subfr_fx( shr(st_fx->L_frame_fx,6), A_fx, Aw_fx, st_fx->gamma, M ); + + } + + test(); + test(); + if(EQ_16(st_fx->last_bwidth_fx,NB)&&NE_16(st_fx->bwidth_fx,NB)&&st_fx->ini_frame_fx!=0) + { + st_fx->rate_switching_reset=1; + move16(); + } + /*----------------------------------------------------------------* + * Encoding of CNG frames + *----------------------------------------------------------------*/ + test(); + IF ( EQ_32(st_fx->core_brate_fx,SID_2k40)||EQ_32(st_fx->core_brate_fx,FRAME_NO_DATA)) + { + IF( EQ_16(st_fx->cng_type_fx,LP_CNG)) + { + /* Run CNG post parameter update */ + cng_params_postupd_fx( st_fx->ho_circ_ptr_fx, &st_fx->cng_buf_cnt, st_fx->cng_exc2_buf, st_fx->cng_Qexc_buf, + st_fx->cng_brate_buf, st_fx->ho_env_circ_fx); + /* encode CNG parameters */ + CNG_enc_fx( st_fx, st_fx->L_frame_fx, Aq_fx, inp_fx, ener_fx, lsp_new_fx, lsf_new_fx, &allow_cn_step_fx, st_fx->burst_ho_cnt_fx, sub(Q_new,1), q_env, &sid_bw, st_fx->exc_mem2_fx ); + + /* comfort noise generation */ + CNG_exc_fx( st_fx->core_brate_fx, st_fx->L_frame_fx, &st_fx->Enew_fx, &st_fx->cng_seed_fx, exc_fx, exc2_fx, &st_fx->lp_ener_fx, st_fx->last_core_brate_fx, + &st_fx->first_CNG_fx, &st_fx->cng_ener_seed_fx, bwe_exc_fx, allow_cn_step_fx, &st_fx->last_allow_cn_step_fx, sub(st_fx->prev_Q_new,1), sub(Q_new,1), st_fx->num_ho_fx, + q_env, st_fx->lp_env_fx, st_fx->old_env_fx, st_fx->exc_mem_fx, st_fx->exc_mem1_fx, &sid_bw, &st_fx->cng_ener_seed1_fx, exc3_fx, st_fx->Opt_AMR_WB_fx ); + } + ELSE + { + IF( EQ_32(st_fx->core_brate_fx, SID_2k40)) + { + FdCng_encodeSID( st_fx->hFdCngEnc_fx, st_fx, st_fx->preemph_fac ); + st_fx->last_CNG_L_frame_fx = st_fx->L_frame_fx; + move16(); + } + + generate_comfort_noise_enc( st_fx, Q_new, 1 ); + + FdCng_exc( st_fx->hFdCngEnc_fx->hFdCngCom, &st_fx->CNG_mode_fx, st_fx->L_frame_fx, st_fx->lsp_old_fx, + st_fx->first_CNG_fx, st_fx->lspCNG_fx, Aq_fx, lsp_new_fx, lsf_new_fx, exc_fx, exc2_fx, bwe_exc_fx ); + + Copy( exc2_fx, exc3_fx, st_fx->L_frame_fx ); + + IF( EQ_32(st_fx->core_brate_fx, SID_2k40)) + { + maxv = 0; + move16(); + FOR(i = 0; i < st_fx->L_frame_fx; i++) + { + maxv = s_max(maxv, abs_s(exc_fx[i])); + } + scale = norm_s(maxv); + pt_res = exc_fx; + L_ener = L_deposit_l(1); + IF( EQ_16(st_fx->L_frame_fx, L_FRAME)) + { + FOR (i=0; i<128; i++) + { + tmp16 = shl(*pt_res,scale); + L_tmp = L_mult0(tmp16, tmp16); + pt_res++; + tmp16 = shl(*pt_res,scale); + L_tmp = L_mac0(L_tmp, tmp16, tmp16); /* 2*(Q_new+scale) */ + pt_res++; + L_ener = L_add(L_ener, L_shr(L_tmp, 7)); /* 2*(Q_new+scale)+1, divide by L_frame done here */ + } + } + ELSE /* L_FRAME16k */ + { + FOR (i=0; i<160; i++) + { + tmp16 = shl(*pt_res,scale); + L_tmp = L_mult0(tmp16, tmp16); + pt_res++; + tmp16 = shl(*pt_res,scale); + L_tmp = L_mac0(L_tmp, tmp16, tmp16); /* 2*(Q_new+scale) */ + pt_res++; + L_ener = L_add(L_ener, L_shr(Mult_32_16(L_tmp,26214 /* 256/320, Q15 */), 7)); /* 2*(Q_new+scale)+15+1-16+1, divide by L_frame done here */ + } + } + + hi = norm_l(L_ener); + lo = Log2_norm_lc(L_shl(L_ener, hi)); + hi = sub(30, add(hi, shl(add(Q_new, scale), 1))); /* log2 exp in Q2*(Q_new+scale) */ + L_tmp = L_Comp(hi, lo); /* Q16 */ + enr = round_fx(L_shl(L_tmp, 8)); /* Q8 (16+8-16) */ + + /* decrease the energy in case of WB input */ + IF( NE_16(st_fx->bwidth_fx, NB)) + { + IF( EQ_16(st_fx->bwidth_fx,WB)) + { + IF( st_fx->CNG_mode_fx >= 0 ) + { + /* Bitrate adapted attenuation */ + att = ENR_ATT_fx[st_fx->CNG_mode_fx]; + } + ELSE + { + /* Use least attenuation for higher bitrates */ + att = ENR_ATT_fx[4]; + } + } + ELSE + { + att = 384; + move16();/*Q8*/ + } + enr = sub(enr, att ); + } + + /* calculate the energy quantization index */ + enr_index = add(enr, 512 /* Q8(2.0) */); /* enr + 2.0 */ + enr_index = extract_l(L_shr(L_mult0(enr_index, STEP_SID_FX), 12+8)); /* Q0 (8+12-(8+12)) */ + + /* limit the energy quantization index */ + enr_index = s_min(enr_index, 127); + enr_index = s_max(enr_index, 0); + + st_fx->old_enr_index_fx = enr_index; + move16(); + } + } + + st_fx->burst_ho_cnt_fx = 0; + + /* synthesis at 12.8kHz sampling rate */ + syn_12k8_fx( st_fx->L_frame_fx, Aq_fx, exc3_fx, syn1_fx, mem->mem_syn3, 1, Q_new, st_fx->Q_syn ); + + /* reset the encoder */ + CNG_reset_enc_fx( st_fx, mem, pitch_buf_fx, voice_factors_fx, 0 ); + + /* update st->mem_syn1 for ACELP core switching */ + Copy( mem->mem_syn3, st_fx->mem_syn1_fx, M ); + + /* update ACELP core synthesis filter memory */ + Copy( mem->mem_syn3, mem->mem_syn, M ); + + /* update old synthesis buffer - needed for ACELP internal sampling rate switching */ + Copy( syn1_fx + st_fx->L_frame_fx - L_SYN_MEM, mem->mem_syn_r, L_SYN_MEM ); + + /* save and delay synthesis to be used by SWB BWE */ + save_old_syn_fx( st_fx->L_frame_fx, syn1_fx, old_syn_12k8_16k_fx, st_fx->old_syn_12k8_16k_fx, st_fx->preemph_fac, &st_fx->mem_deemph_old_syn_fx ); + /* Update MODE2 core switching memory */ + tmp16 = mem->syn[M]; + move16(); + E_UTIL_deemph2( sub(Q_new,1), syn1_fx, st_fx->preemph_fac, st_fx->L_frame_fx, &tmp16 ); + Copy( syn1_fx+st_fx->L_frame_fx-M-1, mem->syn, M+1 ); + + } + + /*----------------------------------------------------------------* + * Encoding of all other frames + *----------------------------------------------------------------*/ + + ELSE + { + /*-----------------------------------------------------------------* + * After inactive period, use the most up-to-date ISPs + *-----------------------------------------------------------------*/ + + test(); + IF ( EQ_32(st_fx->last_core_brate_fx,FRAME_NO_DATA)||EQ_32(st_fx->last_core_brate_fx,SID_2k40)) + { + Copy( st_fx->lspCNG_fx, st_fx->lsp_old_fx, M ); + + lsp2lsf_fx( st_fx->lspCNG_fx, st_fx->lsf_old_fx, M, int_fs_fx ); + } + + /*-----------------------------------------------------------------* + * Reset higher ACELP pre-quantizer in case of switching + *-----------------------------------------------------------------*/ + IF( !st_fx->use_acelp_preq ) + { + st_fx->mem_deemp_preQ_fx = 0; + move16(); + st_fx->mem_preemp_preQ_fx = 0; + move16(); + st_fx->last_nq_preQ_fx = 0; + move16(); + } + + st_fx->use_acelp_preq = 0; + move16(); + + /*-----------------------------------------------------------------* + * LSF Quantization + * A[z] calculation + *-----------------------------------------------------------------*/ + + /* SC-VBR - back-up memories for LSF quantizer and synthesis filter */ + lsf_syn_mem_backup_fx( st_fx, &(st_fx->LPDmem), &tilt_code_bck_fx, &gc_threshold_bck_fx, clip_var_bck_fx, &next_force_sf_bck_fx, + lsp_new_fx, lsf_new_fx, lsp_mid_fx, &clip_var_fx, mem_AR_fx, mem_MA_fx, lsp_new_bck_fx, lsf_new_bck_fx, + lsp_mid_bck_fx, &mCb1_fx, Bin_E_fx, Bin_E_old_fx, mem_syn_bck_fx, &mem_w0_bck_fx, &streaklimit_fx, &pstreaklen_fx); + + lsf_enc_fx( st_fx, st_fx->L_frame_fx, coder_type_fx, lsf_new_fx, lsp_new_fx, lsp_mid_fx, Aq_fx, &st_fx->stab_fac_fx, + st_fx->Nb_ACELP_frames_fx, Q_new ); + + /*---------------------------------------------------------------* + * Calculation of LP residual (filtering through A[z] filter) + *---------------------------------------------------------------*/ + + calc_residu_fx( st_fx, inp_fx, res_fx, Aq_fx, vad_hover_flag_fx, vad_flag_fx ); + + /*---------------------------------------------------------------* + * Calculation of prediction for scaled innovation energy + * (for memory-less gain quantizer) + *---------------------------------------------------------------*/ + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( NE_16(coder_type_fx,UNVOICED)&&NE_16(coder_type_fx,AUDIO)&&NE_16(coder_type_fx,INACTIVE) + && !(LE_32(st_fx->core_brate_fx,ACELP_8k00) && NE_16(coder_type_fx,TRANSITION) ) ) + || (EQ_16(coder_type_fx,INACTIVE) && GE_32(st_fx->total_brate_fx,ACELP_32k) ) ) + { + nb_bits = Es_pred_bits_tbl[BIT_ALLOC_IDX_fx(st_fx->core_brate_fx, coder_type_fx, -1, -1)]; + move16(); + Es_pred_enc_fx( &Es_pred_fx, &indice, st_fx->L_frame_fx, res_fx, voicing_fx, nb_bits, 0, Q_new ); + push_indice_fx( st_fx, IND_ES_PRED, indice, nb_bits ); + } + + + /*------------------------------------------------------------* + * Encode excitation according to coding type + *------------------------------------------------------------*/ + test(); + test(); + IF( st_fx->nelp_mode_fx ) + { + /* SC-VBR - NELP frames */ + encod_nelp_fx( st_fx, mem, inp_fx, Aw_fx, Aq_fx, res_fx, syn_fx, &tmp_noise_fx, exc_fx, exc2_fx, pitch_buf_fx, + voice_factors_fx, bwe_exc_fx, Q_new, shift); + } + ELSE IF( EQ_16(coder_type_fx,UNVOICED)) + { + /* UNVOICED frames (Gauss. excitation) */ + encod_unvoiced_fx( st_fx, mem, inp_fx, Aw_fx, Aq_fx, vad_flag_fx, res_fx, syn_fx, + &tmp_noise_fx, exc_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx,Q_new,shift ); + } + ELSE IF( EQ_16(coder_type_fx,TRANSITION)) + { + tc_subfr_fx = encod_tran_fx( st_fx, mem, st_fx->L_frame_fx, inp_fx, Aw_fx, Aq_fx, coder_type_fx, Es_pred_fx, T_op_fx, voicing_fx, res_fx, syn_fx, + exc_fx, exc2_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, gsc_attack_flag_fx, unbits_fx, sharpFlag_fx, shift, Q_new ); + move16(); + } + ELSE IF( st_fx->ppp_mode_fx ) + { + encod_ppp_fx( st_fx, mem, inp_fx, Aw_fx, Aq_fx, &coder_type_fx, sharpFlag_fx, T_op_fx, voicing_fx, + res_fx, syn_fx, exc_fx, exc2_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, Q_new, shift); + + IF( st_fx->bump_up_fx ) /* PPP failed, bump up */ + { + /* restore memories of LSF quantizer and synthesis filter */ + lsf_syn_mem_restore_fx( st_fx, &(st_fx->LPDmem), tilt_code_bck_fx, gc_threshold_bck_fx, clip_var_bck_fx, next_force_sf_bck_fx, + lsp_new_fx, lsf_new_fx, lsp_mid_fx, clip_var_fx, mem_AR_fx, mem_MA_fx, lsp_new_bck_fx, lsf_new_bck_fx, + lsp_mid_bck_fx, mCb1_fx, Bin_E_fx,Bin_E_old_fx,mem_syn_bck_fx, mem_w0_bck_fx, streaklimit_fx, pstreaklen_fx ); + + /* redo LSF quantization */ + lsf_enc_fx( st_fx, st_fx->L_frame_fx, coder_type_fx, lsf_new_fx, lsp_new_fx, lsp_mid_fx, Aq_fx, &st_fx->stab_fac_fx, st_fx->Nb_ACELP_frames_fx, Q_new ); + + /* recalculation of LP residual (filtering through A[z] filter) */ + calc_residu_fx( st_fx, inp_fx, res_fx, Aq_fx, 0, 0 ); + st_fx->burst_ho_cnt_fx = 0; + move16(); + /* VOICED frames in SC-VBR when bumped up*/ + encod_gen_voic_fx( st_fx, mem, st_fx->L_frame_fx, sharpFlag_fx, inp_fx, Aw_fx, Aq_fx, coder_type_fx, Es_pred_fx, T_op_fx, voicing_fx, res_fx, syn_fx, + exc_fx, exc2_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, unbits_fx, shift, Q_new ); + } + } + ELSE IF( EQ_16(coder_type_fx,AUDIO)||(EQ_16(coder_type_fx,INACTIVE)&&LE_32(st_fx->core_brate_fx,ACELP_24k40))) + { + /* AUDIO and INACTIVE frames (coded by GSC technology) */ + encod_audio_fx( st_fx, mem, inp_fx, Aw_fx, Aq_fx, T_op_fx, voicing_fx, res_fx, syn_fx, exc_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, + gsc_attack_flag_fx, coder_type_fx, lsf_new_fx, &tmp_noise_fx, Q_new , shift); + } + ELSE + { + /* GENERIC, VOICED and INACTIVE frames (coded by AVQ technology) */ + encod_gen_voic_fx( st_fx, mem, st_fx->L_frame_fx, sharpFlag_fx, inp_fx, Aw_fx, Aq_fx, coder_type_fx, Es_pred_fx, T_op_fx, voicing_fx, res_fx, syn_fx, + exc_fx, exc2_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, unbits_fx, shift, Q_new ); + } + + /* update st->mem_syn1 for ACELP core switching */ + Copy( mem->mem_syn, st_fx->mem_syn1_fx, M ); + + /* update old synthesis buffer - needed for ACELP internal sampling rate switching */ + Copy( syn_fx + st_fx->L_frame_fx - L_SYN_MEM, mem->mem_syn_r, L_SYN_MEM ); + + /* save and delay synthesis to be used by SWB BWE */ + save_old_syn_fx( st_fx->L_frame_fx, syn_fx, old_syn_12k8_16k_fx, st_fx->old_syn_12k8_16k_fx, st_fx->preemph_fac, &st_fx->mem_deemph_old_syn_fx ); + + /*Update MODE2 core switching memory*/ + Copy( syn_fx, syn1_fx, st_fx->L_frame_fx ); + E_UTIL_deemph2( sub(Q_new,1), syn1_fx, st_fx->preemph_fac, st_fx->L_frame_fx, &mem->syn[M] ); + Copy( syn1_fx+st_fx->L_frame_fx-M-1, mem->syn, M+1 ); + + + /*--------------------------------------------------------------------------------------* + * Modify the excitation signal when the noise is stationary + *--------------------------------------------------------------------------------------*/ + + IF ( NE_16(st_fx->nelp_mode_fx,1)) + { + L_epsP[0] = L_Comp(epsP_h_fx[2],epsP_l_fx[2]); + move32(); + L_epsP[1] = L_Comp(epsP_h_fx[M],epsP_l_fx[M]); + move32(); + Copy(exc_fx, exc2_fx, st_fx->L_frame_fx); + stat_noise_uv_enc_fx( st_fx, coder_type_fx, L_epsP, lsp_new_fx, lsp_mid_fx, Aq_fx, exc2_fx, Q_new ); + } + + /*-----------------------------------------------------------------* + * Encode supplementary information for Frame Error Concealment + *-----------------------------------------------------------------*/ + + FEC_encode_fx( st_fx, syn_fx, coder_type_fx, st_fx->clas_fx, pitch_buf_fx, res_fx, &st_fx->Last_pulse_pos_fx, + st_fx->L_frame_fx, st_fx->total_brate_fx, st_fx->core_brate_fx, Q_new, shift ); + + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + Copy( Aq_fx+2*(M+1), st_fx->cur_sub_Aq_fx, (M+1) ); + } + ELSE + { + Copy( Aq_fx+3*(M+1), st_fx->cur_sub_Aq_fx, (M+1) ); + } + + } /* end of active inp coding */ + + /*-----------------------------------------------------------------* + * Write ACELP unused bits + *-----------------------------------------------------------------*/ + + test(); + test(); + IF ( NE_32(st_fx->core_brate_fx,SID_2k40)&&NE_32(st_fx->core_brate_fx,FRAME_NO_DATA)&&NE_32(st_fx->core_brate_fx,PPP_NELP_2k80)) + { + /* reserved bits */ + test(); + test(); + IF ( EQ_16(coder_type_fx,AUDIO)||(EQ_16(coder_type_fx,INACTIVE)&&LE_32(st_fx->core_brate_fx,ACELP_24k40))) + { + nBits = 0; + move16(); + } + ELSE IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + nBits = reserved_bits_tbl[BIT_ALLOC_IDX_fx(st_fx->core_brate_fx, coder_type_fx, -1, TC_SUBFR2IDX_fx(tc_subfr_fx))]; + move16(); + } + ELSE + { + nBits = 0; + move16(); + } + WHILE( nBits > 0 ) + { + i = s_min(nBits, 16); + push_indice_fx( st_fx, IND_UNUSED, 0, i ); + nBits = sub(nBits,i); + } + } + + + /*-----------------------------------------------------------------* + * Apply non linearity in case of SWB TBE + *-----------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF ( (EQ_16(st_fx->last_Opt_SC_VBR_fx,1)&&st_fx->Opt_SC_VBR_fx==0)||((EQ_16(st_fx->extl_fx,SWB_TBE)||EQ_16(st_fx->extl_fx,WB_TBE)||EQ_16(st_fx->extl_fx,FB_TBE))&&NE_16(st_fx->last_extl_fx,SWB_TBE)&&NE_16(st_fx->last_extl_fx,WB_TBE)&&NE_16(st_fx->last_extl_fx,FB_TBE))) + { + st_fx->bwe_non_lin_prev_scale_fx = L_deposit_l(0); + set16_fx( st_fx->old_bwe_exc_extended_fx, 0, NL_BUFF_OFFSET ); + } + + IF( !st_fx->Opt_SC_VBR_fx ) + { + /* Apply a non linearity to the SHB excitation */ + non_linearity_fx( bwe_exc_fx, bwe_exc_extended_fx, L_FRAME32k, &st_fx->bwe_non_lin_prev_scale_fx, Q_new, coder_type_fx, voice_factors_fx, st_fx->L_frame_fx); + } + test(); + if ( EQ_32(st_fx->core_brate_fx,SID_2k40)||EQ_32(st_fx->core_brate_fx,FRAME_NO_DATA)) + { + st_fx->bwe_non_lin_prev_scale_fx = L_deposit_l(0); + } + + /*-----------------------------------------------------------------* + * Updates + *-----------------------------------------------------------------*/ + updt_enc_fx( st_fx, st_fx->L_frame_fx, coder_type_fx, old_exc_fx, pitch_buf_fx, + Es_pred_fx,Aq_fx, lsf_new_fx, lsp_new_fx, old_bwe_exc_fx ); + + test(); + IF( (st_fx->Opt_DTX_ON_fx != 0 ) && (GT_32(st_fx->core_brate_fx,SID_2k40))) + { + /* update CNG parameters in active frames */ + cng_params_upd_fx( lsp_new_fx, exc_fx, st_fx->L_frame_fx, &st_fx->ho_circ_ptr_fx, st_fx->ho_ener_circ_fx, + &st_fx->ho_circ_size_fx, st_fx->ho_lsp_circ_fx, Q_new, ENC, NULL, &st_fx->cng_buf_cnt, + st_fx->cng_exc2_buf, st_fx->cng_Qexc_buf, st_fx->cng_brate_buf, st_fx->last_active_brate_fx ); + + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + /* store LSPs@16k, potentially to be used in CNG@16k */ + Copy( st_fx->lsp_old16k_fx, &(st_fx->ho_lsp_circ2_fx[(st_fx->ho_circ_ptr_fx)*M]), M ); + } + + /* Set 16k LSP flag for CNG buffer */ + st_fx->ho_16k_lsp_fx[st_fx->ho_circ_ptr_fx] = 0; + move16(); + if(NE_16(st_fx->L_frame_fx, L_FRAME)) + { + st_fx->ho_16k_lsp_fx[st_fx->ho_circ_ptr_fx] = 1; + move16(); + } + + /* efficient DTX hangover control */ + IF ( GT_16(st_fx->burst_ho_cnt_fx,1)) + { + dtx_hangover_control_fx( st_fx, lsp_new_fx ); + } + } + + /* SC-VBR update of average data rate */ + IF ( EQ_16(vad_flag_fx,1)) + { + update_average_rate_fx( st_fx ); + + } + + return; +} diff --git a/lib_enc/acelp_core_switch_enc_fx.c b/lib_enc/acelp_core_switch_enc_fx.c new file mode 100644 index 0000000..fe42397 --- /dev/null +++ b/lib_enc/acelp_core_switch_enc_fx.c @@ -0,0 +1,535 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "rom_com_fx.h" +#include "prot_fx.h" +#include "stl.h" /* required for wmc_tool */ + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static void encod_gen_voic_core_switch_fx( Encoder_State_fx *st_fx, + LPD_state *mem, + const Word16 L_frame_fx, const Word16 inp_fx[], + const Word16 Aq_fx[], const Word16 A_fx[], const Word16 coder_type_fx, const Word16 T_op_fx[], + const Word16 voicing_fx[], Word16 *exc_fx, const Word32 core_bitrate_fx, Word16 shift, Word16 Q_new ); + +static void bwe_switch_enc_fx( Encoder_State_fx *st_fx, const Word16 *new_speech ); + +static Word16 dotprod_satcont(const Word16 *x, const Word16 *y, Word16 qx, Word16 qy, Word16 *qo, Word16 len, Word16 delta); + +/*-------------------------------------------------------------------* + * acelp_core_switch_enc_fx() + * + * ACELP core encoder in the ACELP->HQ switching frame + *--------------------------------------------------------------------*/ + +void acelp_core_switch_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + LPD_state *mem, + const Word16 inp12k8[], /* i : input signal @12.8 kHz Q0 */ + const Word16 inp16k[], /* i : input signal @16 kHz Q0 */ + const Word16 T_op_orig[2], /* i : open-loop pitch values for quantiz. Q0 */ + const Word16 voicing[3], /* i : Open-loop pitch gains Q15 */ + const Word16 A[NB_SUBFR16k*(M+1)], /* i : A(z) unquantized for the 4 subframes Q12*/ + Word16 shift, + Word16 Q_new +) +{ + Word16 i, T_op[2]; + Word16 old_exc[L_EXC], *exc; /* excitation signal buffer Qexc */ + const Word16 *inp; + Word32 cbrate; + Word16 Aq[2*(M+1)]; + + /* initializations */ + exc = &old_exc[L_EXC_MEM]; + move16(); /* pointer to excitation signal in the current frame */ + Copy( mem->old_exc, old_exc, L_EXC_MEM ); /*now old_exc has the same scaling as st_fx->old_exc; need to change later? */ + + Copy( st_fx->old_Aq_12_8_fx, Aq, M+1 ); + Copy( st_fx->old_Aq_12_8_fx, Aq + (M+1), M+1 ); + + T_op[0] = T_op_orig[0]; + move16(); + T_op[1] = T_op_orig[1]; + move16(); + + /*----------------------------------------------------------------* + * set switching frame bit-rate + *----------------------------------------------------------------*/ + + IF( EQ_16(st_fx->last_L_frame_fx, L_FRAME)) /* ACELP@12k8 core */ + { + inp = inp12k8; + + IF( GT_32(st_fx->core_brate_fx, ACELP_24k40 )) + { + cbrate = L_add(ACELP_24k40, 0); + } + ELSE + { + cbrate = L_add(st_fx->core_brate_fx, 0); + } + } + ELSE /* ACELP@16k core */ + { + inp = inp16k; + + IF( LE_32(st_fx->core_brate_fx, ACELP_8k00)) + { + cbrate = L_add(ACELP_8k00, 0); + } + ELSE IF (LE_32(st_fx->core_brate_fx, ACELP_14k80)) + { + cbrate = L_add(ACELP_14k80, 0); + } + ELSE + { + cbrate = L_min( st_fx->core_brate_fx, ACELP_22k60 ); + } + } + + IF( NE_16(st_fx->last_L_frame_fx, L_FRAME) ) + { + T_op[0] = shr(add(round_fx(L_shl(L_mult(20480, T_op[0]), 2)), 1), 1); + move16(); + T_op[1] = shr(add(round_fx(L_shl(L_mult(20480, T_op[1]), 2)), 1), 1); + move16(); + } + + /*----------------------------------------------------------------* + * Excitation encoding + *----------------------------------------------------------------*/ + + encod_gen_voic_core_switch_fx( st_fx, mem, st_fx->last_L_frame_fx, inp, Aq, A, GENERIC, T_op, voicing, exc, cbrate, shift, Q_new ); + + /*----------------------------------------------------------------* + * bit-stream: modify the layer of sub frame CELP + *----------------------------------------------------------------*/ + + FOR( i=0; i<20; i++ ) + { + st_fx->ind_list_fx[IND_CORE_SWITCHING_CELP_SUBFRAME+i].value=st_fx->ind_list_fx[TAG_ACELP_SUBFR_LOOP_START+i].value; + move16(); + st_fx->ind_list_fx[IND_CORE_SWITCHING_CELP_SUBFRAME+i].nb_bits=st_fx->ind_list_fx[TAG_ACELP_SUBFR_LOOP_START+i].nb_bits; + move16(); + st_fx->ind_list_fx[TAG_ACELP_SUBFR_LOOP_START+i].nb_bits=-1; + move16(); + } + + /*----------------------------------------------------------------* + * BWE encoding + *----------------------------------------------------------------*/ + + test(); + test(); + IF( !( ( EQ_16(st_fx->last_L_frame_fx, L_FRAME16k)&&EQ_16(inner_frame_tbl[st_fx->bwidth_fx],L_FRAME16k))||EQ_16(inner_frame_tbl[st_fx->bwidth_fx],L_FRAME8k))) + { + bwe_switch_enc_fx( st_fx, (const Word16 *)st_fx->old_input_signal_fx ); + } + + return; +} + +/*-------------------------------------------------------------------* + * encod_gen_voic_core_switch() + * + * Encode excitation signal in ACELP->HQ switching frame + *-------------------------------------------------------------------*/ + +static void encod_gen_voic_core_switch_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + LPD_state *mem, + const Word16 L_frame, /* i : length of the frame */ + const Word16 inp[], /* i : input signal */ + const Word16 Aq[], /* i : LP coefficients */ + const Word16 A[], /* i : unquantized A(z) filter */ + const Word16 coder_type, /* i : coding type */ + const Word16 T_op[], /* i : open loop pitch */ + const Word16 voicing[], /* i : voicing */ + Word16 *exc, /* i/o: current non-enhanced excitation */ + const Word32 core_bitrate, /* i : switching frame bit-rate */ + Word16 shift, + Word16 Q_new +) +{ + Word16 res[L_SUBFR]; /* residual signal Qexc */ + Word16 Ap[M+1]; /* A(z) with spectral expansion Q12 */ + Word16 xn[L_SUBFR]; /* Target vector for pitch search */ + Word16 xn2[L_SUBFR]; /* Target vector for codebook search */ + Word16 cn[L_SUBFR]; /* Target vector in residual domain */ + Word16 h1[L_SUBFR+(M+1)]; /* Impulse response vector */ + + Word16 code[L_SUBFR]; /* Fixed codebook excitation Q9 */ + Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */ + Word16 y2[L_SUBFR]; /* Filtered algebraic excitation */ + Word16 gain_pit ; /* Pitch gain Q15 */ + Word16 voice_fac; /* Voicing factor Q15 */ + Word32 gain_code; /* Gain of code Q16 */ + Word16 gain_inov; /* inovation gain */ + Word16 i,gcode16; /* tmp variables */ + Word16 T0, T0_frac; /* close loop integer pitch and fractional part */ + Word16 T0_min, T0_max; /* pitch variables */ + + Word16 pitch,tmp16; /* floating pitch value */ + Word16 g_corr[6]; /* ACELP correl, values + gain pitch */ + Word16 clip_gain; /* ISF clip gain */ + + Word16 unbits; /* number of unused bits for PI */ + Word32 norm_gain_code; + Word16 pitch_limit_flag; + Word32 L_tmp, Lgcode; + Word16 shift_wsp; + Word16 h2[L_SUBFR+(M+1)]; + Word16 lp_select, lp_flag; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + shift_wsp = add(Q_new,shift); + + unbits = 0; + move16(); + + IF( EQ_16(L_frame, L_FRAME)) + { + T0_max = PIT_MAX; + move16(); + T0_min = PIT_MIN; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + T0_max = PIT16k_MAX; + move16(); + T0_min = PIT16k_MIN; + move16(); + } + + /*------------------------------------------------------------------* + * Calculation of LP residual (filtering through A[z] filter) + *------------------------------------------------------------------*/ + + tmp16=st_fx->L_frame_fx; + move16(); + st_fx->L_frame_fx=L_SUBFR; + move16(); + calc_residu_fx(st_fx, inp, res, Aq, 0, 0); + st_fx->burst_ho_cnt_fx = 0; + move16(); + st_fx->L_frame_fx=tmp16; + move16(); + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + + + Copy( res, exc, L_SUBFR ); + + IF( EQ_16(L_frame,L_FRAME16k)) + { + weight_a_fx( A, Ap, GAMMA16k, M ); /* Bandwidth expansion of A(z) filter coefficients */ + find_targets_fx(inp, mem->mem_syn, 0, &mem->mem_w0, Aq, res, L_SUBFR, Ap, PREEMPH_FAC_16k, xn, cn, h1); + } + ELSE + { + weight_a_fx( A, Ap, GAMMA1, M ); /* Bandwidth expansion of A(z) filter coefficients */ + find_targets_fx(inp, mem->mem_syn,0,&mem->mem_w0, Aq, res, L_SUBFR, Ap, TILT_FAC_FX, xn, cn ,h1); + } + + /*Scale_sig(h1, L_SUBFR, shift); *//*Q14-shift */ + Copy_Scale_sig(h1, h2, L_SUBFR, -2); + Scale_sig(h1, L_SUBFR, add(1, shift)); /* set h1[] in Q14 with scaling for convolution */ + + /* scaling of xn[] to limit dynamic at 12 bits */ + Scale_sig(xn, L_SUBFR, shift); + + /*----------------------------------------------------------------* + * Close-loop pitch search and quantization + * Adaptive exc. construction + *----------------------------------------------------------------*/ + + pitch = pit_encode_fx( st_fx, core_bitrate, 0, L_frame, coder_type, &pitch_limit_flag, + 0, exc, L_SUBFR, T_op, &T0_min, &T0_max, &T0, &T0_frac, h1, xn ); + + /*-----------------------------------------------------------------* + * Find adaptive exitation + *-----------------------------------------------------------------*/ + + pred_lt4( &exc[0], &exc[0], T0, T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP ); + + /*-----------------------------------------------------------------* + * Gain clipping test to avoid unstable synthesis on frame erasure + * or in case of floating point encoder & fixed p. decoder + *-----------------------------------------------------------------*/ + + clip_gain = gp_clip_fx( core_bitrate, voicing, 0, coder_type, xn, st_fx->clip_var_fx, sub(shift_wsp, 1) ); + + /*-----------------------------------------------------------------* + * LP filtering of the adaptive excitation, codebook target computation + *-----------------------------------------------------------------*/ + + lp_select = lp_filt_exc_enc_fx( MODE1, core_bitrate, 0, coder_type, 0, exc, h1, xn, y1, xn2, L_SUBFR, L_frame, g_corr, clip_gain, &gain_pit, &lp_flag ); + + IF( EQ_16(lp_flag,NORMAL_OPERATION)) + { + push_indice_fx( st_fx, IND_LP_FILT_SELECT, lp_select, 1 ); + } + + /*-----------------------------------------------------------------* + * Innovation encoding + *-----------------------------------------------------------------*/ + + inov_encode_fx( st_fx, core_bitrate, 0, L_frame,st_fx->last_L_frame_fx, coder_type, st_fx->bwidth_fx, 0, 0, -1, Aq, gain_pit, cn, exc, + h2, mem->tilt_code, pitch, xn2, code, y2, &unbits,shift); + + /*-----------------------------------------------------------------* + * Gain encoding + *-----------------------------------------------------------------*/ + IF( EQ_16(L_frame,L_FRAME)) + { + gain_enc_mless_fx( st_fx,core_bitrate, L_frame, TRANSITION, 0, -1, xn, y1, shift_wsp, y2, code, st_fx->old_Es_pred_fx, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain ); + } + ELSE + { + gain_enc_mless_fx( st_fx,core_bitrate, L_frame, coder_type, 0, -1, xn, y1, shift_wsp, y2, code, st_fx->old_Es_pred_fx, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain ); + } + + gp_clip_test_gain_pit_fx( core_bitrate, gain_pit, st_fx->clip_var_fx ); + + Lgcode = L_shl(gain_code, Q_new); /* scaled gain_code with Qnew -> Q16*/ + gcode16 = round_fx(Lgcode); + + mem->tilt_code = Est_tilt2( exc+0, gain_pit, code, gain_code, &voice_fac,shift ); + + /*-----------------------------------------------------------------* + * Construct adaptive part of the excitation + *-----------------------------------------------------------------*/ + + FOR( i = 0; i < L_SUBFR; i++ ) + { + /* code in Q9, gain_pit in Q14 */ + L_tmp = L_mult(gcode16, code[i]); + L_tmp = L_shl(L_tmp, 5); + L_tmp = L_mac(L_tmp, exc[i ], gain_pit); + L_tmp = L_shl(L_tmp, 1); /* saturation can occur here */ + exc[i ] = round_fx(L_tmp); + } + + /* write reserved bits */ + IF( unbits ) + { + push_indice_fx(st_fx, IND_UNUSED, 0, unbits ); + } + + /*-----------------------------------------------------------------* + * long term prediction on the 2nd sub frame + *-----------------------------------------------------------------*/ + + pred_lt4(&exc[L_SUBFR], &exc[L_SUBFR], T0, T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP); + + FOR( i = L_SUBFR; i < 2*L_SUBFR; i++ ) + { + exc[i] = round_fx(L_shl(L_mult(exc[i], gain_pit), 1)); + } + + return; +} + + +/*-------------------------------------------------------------------* + * bwe_switch_enc() + * + * Encode BWE in ACELP->HQ switching frame + *-------------------------------------------------------------------*/ + +static void bwe_switch_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *new_speech_fx /* i : original input signal Q0 */ +) +{ + + Word16 k, Loverlapp_fx, d1m_fx, maxd1_fx, ind1_fx, gapsize_fx; + Word16 delta_fx, fdelay_fx; + const Word16 *hp_filter_fx; + const Word16 *fpointers_tab[6] = {hp12800_16000_fx, hp12800_32000_fx, hp12800_48000_fx, hp16000_48000_fx, hp16000_32000_fx, hp16000_48000_fx}; + Word16 tmp, shift; + const Word16 *ptmp; + Word16 tmp_mem_fx[2*L_FILT48k], tmp_mem2_fx[2*L_FILT48k], hb_synth_tmp_fx[480]; + Word16 Fs_kHz; + Word16 q_tmp1, q_tmp2, Qmc, Qsq; + Word32 L_tmp1, L_tmp2, L_tmp3, min_sq_cross_fx; + Word16 accA_fx, accB_fx, min_corr_fx, E1_fx, E2_fx, gain_fx; + Word16 synth_subfr_bwe_fx[SWITCH_MAX_GAP]; /* synthesized bwe for core switching */ + + Word16 n, L; + L = NS2SA_fx2(st_fx->input_Fs_fx,FRAME_SIZE_NS); + + /* set multiplication factor according to the sampling rate */ + tmp = extract_l(L_shr(st_fx->input_Fs_fx,14)); + delta_fx = add(tmp,1); + Fs_kHz = shl(delta_fx,4); + tmp = add(tmp,i_mult2(3,(sub(st_fx->last_L_frame_fx,L_FRAME)!=0))); + ptmp = fpointers_tab[tmp]; + move16(); + + hp_filter_fx = ptmp; + fdelay_fx=i_mult2(16,delta_fx); + IF(EQ_16(st_fx->last_L_frame_fx,L_FRAME)) + { + fdelay_fx=i_mult2(20,delta_fx); + } + + n = i_mult2(N16_CORE_SW,delta_fx); + + set16_fx( tmp_mem_fx, 0, 2*L_FILT48k); + set16_fx( tmp_mem2_fx, 0, 2*L_FILT48k); + + Loverlapp_fx = i_mult2(delta_fx,SWITCH_OVERLAP_8k*2); + gapsize_fx = i_mult2(delta_fx,NS2SA(16000,SWITCH_GAP_LENGTH_NS)); + + shift = sub(add(add(shr(L,1),n),Loverlapp_fx),gapsize_fx) ; + Copy( new_speech_fx+shift,synth_subfr_bwe_fx,add(gapsize_fx,fdelay_fx) ); + Copy( new_speech_fx+sub(shift,fdelay_fx),tmp_mem_fx,fdelay_fx ); + + tmp = add(gapsize_fx, fdelay_fx); + fir_fx( synth_subfr_bwe_fx, hp_filter_fx, synth_subfr_bwe_fx, tmp_mem_fx, tmp, fdelay_fx, 1, 0 ); + Copy(synth_subfr_bwe_fx+shr(fdelay_fx,1),synth_subfr_bwe_fx,sub(gapsize_fx,shr(fdelay_fx,1)) ); + + tmp = i_mult2(Fs_kHz,10); + fir_fx( new_speech_fx, hp_filter_fx, hb_synth_tmp_fx, tmp_mem2_fx, tmp, fdelay_fx, 1, 0 ); + + min_sq_cross_fx = L_negate(1); + Qsq = 0; + move16(); + min_corr_fx = 0; + move16(); + Qmc = 0; + move16(); + d1m_fx = 0; + move16(); + + maxd1_fx = sub(tmp,add(gapsize_fx,fdelay_fx)); + + IF (EQ_16(delta_fx, 2)) + { + maxd1_fx = shr(maxd1_fx,1); + } + ELSE IF (EQ_16(delta_fx, 3)) + { + maxd1_fx = extract_h(L_mult(maxd1_fx, 10923)); + } + + /* find delay */ + ptmp = &hb_synth_tmp_fx[fdelay_fx]; + move16(); + FOR( k = 0; k < maxd1_fx; k++ ) + { + accA_fx = dotprod_satcont(ptmp, ptmp, 0, 0, &q_tmp1, gapsize_fx, delta_fx); + accB_fx = dotprod_satcont(ptmp, synth_subfr_bwe_fx, 0, 0, &q_tmp2, gapsize_fx, delta_fx); + ptmp += delta_fx; + L_tmp1 = L_mult0(accB_fx, accB_fx); /*2*q_tmp2; */ + L_tmp2 = Mult_32_16(L_tmp1, min_corr_fx); /*2*q_tmp2+Qmc-15 */ + L_tmp3 = Mult_32_16(min_sq_cross_fx, accA_fx); /*Qsq+q_tmp1-15 */ + shift = s_min(add(shl(q_tmp2,1),Qmc),add(q_tmp1,Qsq)); + L_tmp2 = L_shr(L_tmp2, sub(add(shl(q_tmp2,1),Qmc),shift)); + L_tmp3 = L_shr(L_tmp3, sub(add(q_tmp1,Qsq),shift)); + + IF (GE_32(L_tmp2,L_tmp3)) + { + d1m_fx = k; + move16(); + min_corr_fx = accA_fx; + move16(); + Qmc = q_tmp1; + move16(); + min_sq_cross_fx = L_add(L_tmp1, 0); + Qsq = shl(q_tmp2,1); + move16(); + } + } + + push_indice_fx(st_fx, IND_CORE_SWITCHING_AUDIO_DELAY, d1m_fx, AUDIODELAYBITS ); + + tmp = add(i_mult2(d1m_fx,delta_fx),fdelay_fx); + ptmp = &hb_synth_tmp_fx[tmp]; + move16(); + E1_fx = dotprod_satcont(synth_subfr_bwe_fx, synth_subfr_bwe_fx, 0, 0, &q_tmp1, gapsize_fx, 1); + E2_fx = dotprod_satcont(ptmp, ptmp, 0, 0, &q_tmp2, gapsize_fx, 1); + + IF (!E1_fx) + { + E1_fx = shl(1,14); + q_tmp1 = 14; + move16(); + } + IF (!E2_fx) + { + E2_fx = shl(1,14); + q_tmp2 = 14; + move16(); + } + + tmp = div_s(shl(1, 14), E1_fx); /*Q(29-q_tmp1) */ + L_tmp1 = L_mult(tmp, E2_fx); /*30-q_tmp1+q_tmp2 */ + q_tmp2 = sub(q_tmp1, q_tmp2); /*30-q_tmp2 */ + L_tmp1 = L_shl(L_tmp1, sub(q_tmp2, 24)); + gain_fx = round_fx(Isqrt(L_tmp1)); /*Q12 */ + + ind1_fx = usquant_fx( gain_fx, &gain_fx, shr(MINVALUEOFFIRSTGAIN_FX,1), shr(DELTAOFFIRSTGAIN_FX,4), (1 << NOOFGAINBITS1) ); + push_indice_fx( st_fx,IND_CORE_SWITCHING_AUDIO_GAIN, ind1_fx, NOOFGAINBITS1 ); + + return; +} + +static Word16 dotprod_satcont(const Word16 *x, const Word16 *y, Word16 qx, Word16 qy, Word16 *qo, Word16 len, Word16 delta) +{ + Word16 tmp_tabx[L_FRAME48k], tmp_taby[L_FRAME48k]; + Word16 shift, q, ener, i; + Word32 L_tmp; + + Copy( x, tmp_tabx, len ); + Copy( y, tmp_taby, len ); + shift = 0; + move16(); + DO + { + L_tmp = L_deposit_l(0); + Overflow = 0; + move16(); + FOR ( i = 0; i < len; i += delta ) + { + L_tmp = L_mac0(L_tmp, tmp_tabx[i], tmp_taby[i]); /*Q(qx+qy-shift) */ + } + + IF(Overflow != 0) + { + FOR( i = 0; i < len; i += delta ) + { + tmp_tabx[i] = shr(tmp_tabx[i], 2); + move16(); + tmp_taby[i] = shr(tmp_taby[i], 2); + move16(); + } + shift = add(shift, 4); + } + } + WHILE(Overflow != 0); + + q = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, q); /*Q(qx+qy-shift+q) */ + ener = extract_h(L_tmp); /*Q(qx+qy-shift+q-16) */ + q = add(q, add(qx, qy)); + *qo = sub(q, add(shift, 16)); + + return ener; +} diff --git a/lib_enc/acelp_enc_util.c b/lib_enc/acelp_enc_util.c new file mode 100644 index 0000000..bfd1bfb --- /dev/null +++ b/lib_enc/acelp_enc_util.c @@ -0,0 +1,280 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include "stl.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "options.h" +#include "cnst_fx.h" +#include "stl.h" +#include "rom_com_fx.h" +#include "rom_enc_fx.h" + + +#define _1_Q9 0x200 + + +/* + * E_ACELP_toeplitz_mul + * + * Parameters: + * R I: coefficients of Toeplitz matrix (Q9) + * c I: input vector Q_xn + * d O: output vector, exponent = j + * + * Function: + * Multiplication of Toeplitz matrix with vector c, such that + * d = toeplitz(R)*c + * Vector length is L_SUBFR +*/ +Word16 E_ACELP_toeplitz_mul(const Word16 R[], const Word16 c[], Word16 d[], const Word16 L_subfr, const Word16 highrate) +{ + static const Word16 step = 4; + Word16 k, j, i; + Word32 s; + Word32 y32[L_SUBFR16k], L_maxloc, L_tot; + + + assert(L_subfr <= L_SUBFR16k); + + + /* first keep the result on 32 bits and find absolute maximum */ + L_tot = L_deposit_l(1); + + FOR (k = 0; k < step; k++) + { + L_maxloc = L_deposit_l(0); + FOR (i = k; i < L_subfr; i += step) + { + s = L_mult(R[i], c[0]); + FOR (j = 1; j < i; j++) + { + s = L_mac(s, R[i-j], c[j]); + } + FOR (; j 16 x tot */ + + Copy_Scale_sig_32_16(y32, d, L_subfr, j); + + return j; +} + +void E_ACELP_weighted_code( + const Word16 code[], /* i: code */ + const Word16 H[], /* i: impulse response */ + Word16 Q, /* i: Q format of H */ + Word16 y[] /* o: weighted code */ +) +{ + Word16 i, j, k, one, n, nz[L_SUBFR]; + Word32 L_tmp; + + /* Collect nonzeros */ + n = 0; + move16(); + FOR (i=0; i 0); + + one = shl(1, Q); + Q = sub(15, Q); + + /* Generate weighted code */ + j = nz[0]; + move16(); + set16_fx(y, 0, j); + FOR (k=0; knb_pulse+(k*4) <= 40); + + copyWord8((const Word8*)E_ROM_tipos+(k * 4), (Word8*)ipos, config->nb_pulse); + + /* if all tracks do not have equal number of pulses */ + restpulses = s_and(config->nb_pulse, 3); + + IF (restpulses) + { + SWITCH (config->codetrackpos) + { + case TRACKPOS_FIXED_FIRST: /* fixed track positions, starting from left */ + /* add tracks from left */ + FOR (iPulse=0; iPulsenb_pulse-restpulses+iPulse] = (UWord8)iPulse; + move16(); + } + /* Put the same track on the next position, because the 1-pulse search + * will access it to determine if this could be in any track. */ + ipos[config->nb_pulse] = ipos[config->nb_pulse-1]; + move16(); + BREAK; + case TRACKPOS_FIXED_EVEN: /* fixed track positions, odd tracks */ + /* odd tracks, switch order for every iteration */ + ipos[config->nb_pulse-restpulses] = (UWord8)s_and(lshl(k,1),2); + move16();/* 0 for even k, 2 for odd */ + ipos[config->nb_pulse-restpulses+1] = (UWord8)s_xor(ipos[config->nb_pulse-restpulses], 2); + move16();/* 2 for even k, 0 for odd */ + BREAK; + case TRACKPOS_FIXED_TWO: /* two tracks instead of four */ + /* Put the next track on the next position, because the 1-pulse search + * will access it to determine if this could be in any track. */ + ipos[config->nb_pulse] = (UWord8)s_and(add(ipos[config->nb_pulse-1],1),3); + move16(); + BREAK; + default: /* one or three free track positions */ + /* copy an extra position from table - 1pulse search will access this */ + ipos[config->nb_pulse] = E_ROM_tipos[add(shl(k,2),config->nb_pulse)]; + move16(); + BREAK; + } + } +} + diff --git a/lib_enc/amr_wb_enc_fx.c b/lib_enc/amr_wb_enc_fx.c new file mode 100644 index 0000000..bc10a23 --- /dev/null +++ b/lib_enc/amr_wb_enc_fx.c @@ -0,0 +1,625 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_enc_fx.h" /* Encoder static table prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required by wmc_tool */ +#include "basop_util.h" + +/*-------------------------------------------------------------------* + * amr_wb_enc() + * + * AMR-WB encoder + *--------------------------------------------------------------------*/ + +void amr_wb_enc_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 input_sp[], /* i : input signal */ + const Word16 n_samples /* i : number of input samples */ +) +{ + Word16 i, delay; + Word16 old_inp[L_INP_12k8], *new_inp, *inp; /* buffer of old input signal */ + Word16 old_inp_16k[L_INP_12k8+L_SUBFR], *inp_16k, *new_inp_16k;/* buffer of old input signal @16kHz*/ + Word16 old_exc[L_EXC], *exc; /* excitation signal buffer */ + Word16 old_wsp[L_WSP], *wsp; /* weighted input signal buffer */ + Word16 input_frame; /* frame length at input sampling freq. */ + Word32 fr_bands[2*NB_BANDS]; /* energy in frequency bands */ + Word32 lf_E[2*VOIC_BINS]; /* per bin spectrum energy in lf */ + Word32 tmpN[NB_BANDS]; /* temporary noise update */ + Word32 tmpE[NB_BANDS], PS[L_FFT/2]; /* temporary averaged energy of 2 sf. */ + Word16 corr_shift; /* correlation shift */ + Word16 relE; /* frame relative energy */ + Word16 cor_map_sum, sp_div; + Word16 vad_flag; + Word16 localVAD; + Word16 Etot; /* total energy */ + Word32 ener = 0; /* residual energy from Levinson-Durbin */ + Word16 pitch[3]; /* open-loop pitch values */ + Word16 voicing[3]; /* open-loop pitch gains */ + Word16 A[NB_SUBFR*(M+1)]; /* A(z) unquantized for the 4 subframes */ + Word16 Aw[NB_SUBFR*(M+1)]; /* A(z) unquantized for the 4 subframes */ + Word16 vad_hover_flag, noisy_speech_HO, clean_speech_HO, NB_speech_HO; + Word16 epsP_h[M+1]; /* LP prediction errors */ + Word16 epsP_l[M+1]; /* LP prediction errors */ + Word16 isp_new[M]; /* ISPs at the end of the frame */ + Word16 isf_new[M]; /* ISFs at the end of the frame */ + Word16 isp_tmp[M]; + Word16 Aq[NB_SUBFR*(M+1)]; /* A(z) quantized for the 4 subframes */ + Word16 syn[L_FRAME]; /* synthesis vector */ + Word16 res[L_FRAME]; /* residual signal for FER protection */ + Word16 exc2[L_FRAME]; /* enhanced excitation */ + Word16 pitch_buf[NB_SUBFR]; /* floating pitch for each subframe */ + Word16 dummy_buf[L_FRAME32k]; /* dummy buffer - no usage */ + Word16 snr_sum_he; + Word16 allow_cn_step; + Word16 tmps; + Word16 harm_flag; /* Q0 */ + Word16 high_lpn_flag; + Word16 localVAD_HE_SAD; + Word16 vad_flag_dtx; + Word16 coder_type; + Word16 hf_gain_fx[NB_SUBFR]; + Word16 Q_new, Q_exp,Q_r[2]; + Word16 excitation_max_test, shift; + Word32 Le_min_scaled; + Word16 Q_sp_div; + Word16 non_staX, Scale_fac[2]; + Word16 sp_floor; + Word16 fft_buff[2*L_FFT]; + Word32 q_env[NUM_ENV_CNG]; + Word16 sid_bw = 0; + Word16 exc3[L_FRAME]; + Word32 lp_bckr, hp_bckr, Ltmp; + Word16 tmp, e_tmp; + + /*------------------------------------------------------------------* + * Initialization + *------------------------------------------------------------------*/ + + st->L_frame_fx = L_FRAME; + move16(); + st->gamma = GAMMA1; + move16(); + st->core_fx = AMR_WB_CORE; + move16(); + st->core_brate_fx = st->total_brate_fx; + move16(); + st->input_bwidth_fx = st->last_input_bwidth_fx; + move16(); + st->bwidth_fx = st->last_bwidth_fx; + move16(); + coder_type = GENERIC; + move16(); + input_frame = st->input_frame_fx; + move16(); /* frame length of the input signal */ + st->extl_fx = -1; + st->encoderPastSamples_enc = (L_FRAME*9)/16; + st->encoderLookahead_enc = L_LOOK_12k8; + st->bpf_off_fx = 0; + move16(); + test(); + if( EQ_16(st->last_core_fx,HQ_CORE)||EQ_16(st->last_codec_mode,MODE2)) + { + st->bpf_off_fx = 1; + move16(); + } + st->igf = 0; + move16(); + + /* Updates in case of EVS primary mode -> AMR-WB IO mode switching */ + IF( NE_16(st->last_core_fx,AMR_WB_CORE)) + { + updt_IO_switch_enc_fx( st, input_frame); + } + + /* Updates in case of HQ -> AMR-WB IO mode switching */ + Q_new = 0; + move16(); /* prevent compiler warning only*/ + core_switching_pre_enc_fx( st,&(st->LPDmem), NULL, NULL ); + + set16_fx( hf_gain_fx, 0, NB_SUBFR ); + set16_fx( old_inp, 0, L_INP_12k8 ); + exc = old_exc + L_EXC_MEM; /* pointer to excitation signal in the current frame */ + + Copy( st->LPDmem.old_exc, old_exc, L_EXC_MEM ); + + new_inp = old_inp + L_INP_MEM; /* pointer to new samples of the input signal */ + inp = new_inp - L_LOOK_12k8; /* pointer to current frame of input signal */ + wsp = old_wsp + L_WSP_MEM; /* pointer to current frame of weighted signal */ + + Copy( st->old_inp_12k8_fx, old_inp, L_INP_MEM ); + Copy( st->old_wsp_fx, old_wsp, L_WSP_MEM ); + + new_inp_16k = old_inp_16k + L_INP_MEM; /* pointer to new samples of the input signal in 16kHz core */ + inp_16k = new_inp_16k - L_LOOK_16k; /* pointer to the current frame of input signal in 16kHz core */ + Copy( st->old_inp_16k_fx, old_inp_16k, L_INP_MEM ); + + /* in case of switching, reset AMR-WB BWE memories */ + test(); + IF( EQ_32(st->total_brate_fx,ACELP_23k85)&&NE_32(st->last_core_brate_fx,ACELP_23k85)) + { + hf_cod_init_fx( st->mem_hp400_enc_fx, st->mem_hf_enc_fx, st->mem_syn_hf_enc_fx, st->mem_hf2_enc_fx, &st->gain_alpha_fx ); + } + + /*----------------------------------------------------------------* + * set input samples buffer + *----------------------------------------------------------------*/ + + /* get delay to synchronize ACELP and MDCT frame */ + delay = NS2SA_fx2(st->input_Fs_fx, DELAY_FIR_RESAMPL_NS); + + Copy( st->input - delay, st->old_input_signal_fx, input_frame+delay ); + + /*----------------------------------------------------------------* + * Buffering of input signal + * HP filtering + *----------------------------------------------------------------*/ + + Copy( input_sp, st->input, n_samples ); + FOR( i = n_samples; i < input_frame; i++ ) + { + st->input[i] = 0; + move16(); + } + hp20( st->input, 1, input_frame, st->mem_hp20_in_fx, st->input_Fs_fx ); + + /*-----------------------------------------------------------------* + * switching from ACELP@16k core to AMR-WB IO mode + *-----------------------------------------------------------------*/ + + st->rate_switching_reset=0; + move16(); + test(); + test(); + IF( NE_16(st->last_core_fx,AMR_WB_CORE)&&EQ_16(st->last_L_frame_fx,L_FRAME16k)&&NE_16(st->last_core_fx,HQ_CORE)) + { + /* in case of switching, do not apply BPF */ + st->bpf_off_fx = 1; + move16(); + st->rate_switching_reset=lsp_convert_poly_fx(st->lsp_old_fx, L_FRAME, 1); + + /* convert old quantized LSF vector */ + lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, INT_FS_FX ); + + /* Reset LPC mem */ + Copy( GEWB_Ave_fx, st->mem_AR_fx, M ); + set16_fx( st->mem_MA_fx,0, M ); + + /* update synthesis filter memories */ + synth_mem_updt2( L_FRAME, st->last_L_frame_fx, st->LPDmem.old_exc, st->LPDmem.mem_syn_r, st->mem_syn1_fx, st->LPDmem.mem_syn, ENC ); + Copy( st->LPDmem.old_exc, old_exc, L_EXC_MEM ); + Copy( st->mem_syn1_fx, st->LPDmem.mem_syn2, M ); + Copy( st->LPDmem.mem_syn2, st->LPDmem.mem_syn3, M ); + + /* lsp -> isp */ + Copy( stable_ISP_fx, isp_tmp, M ); + lsp2isp_fx( st->lsp_old_fx, st->lsp_old_fx, isp_tmp, M ); + + } + + /* update buffer of old subframe pitch values */ + IF( NE_16(st->last_L_frame_fx,L_FRAME)) + { + move16(); + IF( EQ_16(st->last_L_frame_fx,L_FRAME32k)) + { + /* (float)12800/(float)32000; */ + tmp = 13107; + } + ELSE IF( EQ_16(st->last_L_frame_fx,512)) + { + /* (float)12800/(float)25600; */ + tmp = 16384; + } + ELSE /* st->last_L_frame == L_FRAME16k */ + { + /* (float)12800/(float)16000; */ + tmp = 26214; + } + + FOR( i=NB_SUBFR16k-NB_SUBFR; iold_pitch_buf_fx[i-1] = mult_r(tmp, st->old_pitch_buf_fx[i]); + move16(); + } + + FOR( i=2*NB_SUBFR16k-NB_SUBFR; i<2*NB_SUBFR16k; i++ ) + { + st->old_pitch_buf_fx[i-2] = mult_r(tmp, st->old_pitch_buf_fx[i]); + move16(); + } + } + + test(); + if( EQ_16(st->last_bwidth_fx,NB)&&st->ini_frame_fx!=0) + { + st->rate_switching_reset=1; + move16(); + } + + /*----------------------------------------------------------------* + * Change the sampling frequency to 12.8 kHz + *----------------------------------------------------------------*/ + + modify_Fs_fx( st->input, input_frame, st->input_Fs_fx, new_inp, 12800, st->mem_decim_fx, 0 ); + + /* update signal buffer */ + Copy( new_inp, st->buf_speech_enc+L_FRAME, L_FRAME ); + Scale_sig( st->buf_speech_enc+L_FRAME, L_FRAME, 1 ); + + /*------------------------------------------------------------------* + * Perform fixed preemphasis through 1 - g*z^-1 + *-----------------------------------------------------------------*/ + + Preemph_scaled( new_inp, &Q_new, &st->mem_preemph_fx, st->Q_max, PREEMPH_FAC, 0, 1, L_Q_MEM, L_FRAME, st->last_coder_type_fx, 1 ); + + Q_exp = sub(Q_new, st->Q_old); + move16(); + st->Q_old = Q_new; + move16(); + + Le_min_scaled = Scale_mem_pre_proc( st->ini_frame_fx, Q_exp, &Q_new, old_inp, &(st->mem_wsp_fx), st->enrO_fx, st->bckr_fx, st->ave_enr_fx, + st->ave_enr2_fx, st->fr_bands1_fx, st->fr_bands2_fx, st->Bin_E_old_fx ); + + Q_exp = sub(Q_new, st->prev_Q_new); + move16(); + Scale_mem_enc( Q_exp, old_inp_16k, old_exc, st->old_bwe_exc_fx, &(st->LPDmem.mem_w0), st->LPDmem.mem_syn, st->LPDmem.mem_syn2, + &st->mem_deemp_preQ_fx, st->last_exc_dct_in_fx, st->old_input_lp_fx ); + + /*----------------------------------------------------------------* + * Compute spectrum, find energy per critical frequency band + * Track energy and signal dynamics + * Detect NB spectrum in a 16kHz-sampled input + *----------------------------------------------------------------*/ + + analy_sp( inp, Q_new, fr_bands, lf_E, &Etot, st->min_band_fx, st->max_band_fx, Le_min_scaled, Scale_fac, st->Bin_E_fx, + st->Bin_E_old_fx, PS, st->lgBin_E_fx, st->band_energies, fft_buff ); + + noise_est_pre_fx( Etot, st->ini_frame_fx, &st->Etot_l_fx, &st->Etot_h_fx, &st->Etot_l_lp_fx, &st->Etot_last_fx, + &st->Etot_v_h2_fx, &st->sign_dyn_lp_fx, st->harm_cor_cnt_fx, &st->Etot_lp_fx ); + + /*----------------------------------------------------------------* + * VAD + *----------------------------------------------------------------*/ + + vad_flag = wb_vad_fx( st, fr_bands, &localVAD, &noisy_speech_HO, &clean_speech_HO, &NB_speech_HO, + &snr_sum_he, &localVAD_HE_SAD, &(st->flag_noisy_speech_snr), Q_new ) ; + + if ( vad_flag == 0 ) + { + coder_type = INACTIVE; + move16(); + } + + /* apply DTX hangover for CNG analysis */ + vad_flag_dtx = dtx_hangover_addition_fx( st, localVAD, vad_flag, sub(st->lp_speech_fx, st->lp_noise_fx), 0, &vad_hover_flag ); + + /*-----------------------------------------------------------------* + * Select SID or FRAME_NO_DATA frame if DTX enabled + *-----------------------------------------------------------------*/ + + IF ( NE_16(st->last_core_fx,AMR_WB_CORE)) + { + st->fd_cng_reset_flag = 1; + move16(); + } + ELSE IF ( s_and((st->fd_cng_reset_flag > 0),(Word16)(LT_16(st->fd_cng_reset_flag,10)))) + { + st->fd_cng_reset_flag = add(st->fd_cng_reset_flag,1); + } + ELSE + { + st->fd_cng_reset_flag = 0; + move16(); + } + + dtx_fx( st, vad_flag_dtx, inp, Q_new ); + + /*----------------------------------------------------------------* + * Noise energy down-ward update and total noise energy estimation + * Long-term energies and relative frame energy updates + * Correlation correction as a function of total noise level + *----------------------------------------------------------------*/ + + noise_est_down_fx( fr_bands, st->bckr_fx, tmpN, tmpE, st->min_band_fx, st->max_band_fx, &st->totalNoise_fx, + Etot, &st->Etot_last_fx, &st->Etot_v_h2_fx, Q_new, Le_min_scaled ); + + high_lpn_flag = 0; + move16(); /* Q0 flag */ + long_enr_fx( st, Etot, localVAD_HE_SAD, high_lpn_flag ); + relE = sub(Etot, st->lp_speech_fx); /* Q8 */ + + IF( NE_16(st->bwidth_fx, NB)) + { + lp_bckr = Mean32( st->bckr_fx, 10 ); + } + ELSE + { + lp_bckr = Mean32( st->bckr_fx+1, 9 ); + } + hp_bckr = L_shr(L_add(st->bckr_fx[st->max_band_fx-1] , st->bckr_fx[st->max_band_fx]),1); + if( hp_bckr == 0 ) /* Avoid division by zero. */ + { + hp_bckr = L_deposit_l(1); + } + tmp = BASOP_Util_Divide3232_Scale( lp_bckr, hp_bckr, &e_tmp ); + Ltmp = L_shr_r( L_deposit_h( tmp ), sub( 15, e_tmp ) ); + st->bckr_tilt_lt = L_add( Mpy_32_16_r( st->bckr_tilt_lt, 29491 ), Mpy_32_16_r( Ltmp, 3277 ) ); + + corr_shift = correlation_shift_fx( st->totalNoise_fx ); + + /*----------------------------------------------------------------* + * WB, SWB and FB bandwidth detector + *----------------------------------------------------------------*/ + + bw_detect_fx( st, st->input, localVAD, NULL, NULL ); + + /* in AMR_WB IO, limit the maximum band-width to WB */ + if( GT_16(st->bwidth_fx,WB)) + { + st->bwidth_fx = WB; + move16(); + } + + /*----------------------------------------------------------------* + * Perform LP analysis + * Compute weighted inp + * Perform open-loop pitch analysis + * Perform 1/4 pitch precision improvement + *----------------------------------------------------------------*/ + + IF ( vad_flag == 0 ) + { + /* reset the OL pitch tracker memories during inactive frames */ + pitch_ol_init_fx( &st->old_thres_fx, &st->old_pitch, &st->delta_pit_fx, &st->old_corr_fx) ; + } + + analy_lp_AMR_WB_fx( inp, &ener, A, epsP_h, epsP_l, isp_new, st->lsp_old1_fx, + isf_new, st->old_pitch_la, st->old_voicing_la, Q_new, Q_r ); + + find_wsp( A, inp, wsp, &st->mem_wsp_fx, TILT_FAC_FX, L_FRAME, L_LOOK_12k8, L_SUBFR, Aw, GAMMA1, NB_SUBFR ); + Scale_wsp( wsp, &(st->old_wsp_max), &shift, &Q_exp, &(st->old_wsp_shift), + st->old_wsp2_fx, st->mem_decim2_fx, st->old_wsp_fx, add(L_FRAME, L_LOOK_12k8)); + + excitation_max_test = -32768; + move16(); + FOR (i = 0; i < L_EXC_MEM; i++) + { + excitation_max_test = s_max(abs_s(old_exc[i]),excitation_max_test); + } + + test(); + if( GT_16(excitation_max_test,8192)&&shift==0) + { + shift = -1; + move16(); + } + pitch_ol_fx( pitch, voicing, &st->old_pitch, &st->old_corr_fx, corr_shift, &st->old_thres_fx, &st->delta_pit_fx, st->old_wsp2_fx, wsp, st->mem_decim2_fx, relE, 0, st->bwidth_fx, st->Opt_SC_VBR_fx ); + st->old_pitch_la = pitch[2]; + move16(); + st->old_voicing_la = voicing[2]; + move16(); + + /* VAD parameters update */ + vad_param_updt_fx( st, pitch, voicing, st->pitO_fx, corr_shift, vad_flag, A ); + + /*------------------------------------------------------------------* + * Update estimated noise energy and voicing cut-off frequency + *-----------------------------------------------------------------*/ + + noise_est_fx( st, tmpN, pitch, voicing, epsP_h, epsP_l, Etot, relE, corr_shift, tmpE, fr_bands, &cor_map_sum, &sp_div, &Q_sp_div, &non_staX, &harm_flag, + lf_E, &st->harm_cor_cnt_fx, st->Etot_l_lp_fx, st->Etot_v_h2_fx, &st->bg_cnt_fx, st->lgBin_E_fx, Q_new, Le_min_scaled, &sp_floor ); + + /*----------------------------------------------------------------* + * Change the sampling frequency to 16 kHz, + * input@16kHz needed for AMR-WB IO BWE @23.85kbps + *----------------------------------------------------------------*/ + + test(); + IF( EQ_32(st->input_Fs_fx, 16000)) + { + /* no resampling needed, only delay adjustement to account for the FIR resampling delay */ + tmps = NS2SA_fx2(16000, DELAY_FIR_RESAMPL_NS); + Copy_Scale_sig( &st->mem_decim16k_fx[tmps], new_inp_16k, tmps, -1 ); /* Input in Q0 -> Output in Q-1 to mimic the resampling filter */ + Copy_Scale_sig( st->input, new_inp_16k + tmps, sub(input_frame, tmps), -1 ); /* Input in Q0 -> Output in Q-1 to mimic the resampling filter */ + Copy( st->input + input_frame - shl(tmps,1), st->mem_decim16k_fx, shl(tmps,1) ); /* memory still in Q0 */ + } + ELSE IF( EQ_32(st->input_Fs_fx, 32000)||EQ_32(st->input_Fs_fx,48000)) + { + modify_Fs_fx( st->input, input_frame, st->input_Fs_fx, new_inp_16k, 16000, st->mem_decim16k_fx, 0 ); + } + + /*----------------------------------------------------------------* + * Encoding of SID frames + *----------------------------------------------------------------*/ + + test(); + IF ( EQ_32(st->core_brate_fx,SID_1k75)||EQ_32(st->core_brate_fx,FRAME_NO_DATA)) + { + /* encode CNG parameters */ + CNG_enc_fx( st, L_FRAME, Aq, inp, ener, isp_new, isf_new , &allow_cn_step, st->burst_ho_cnt_fx, sub(Q_new,1), + q_env, &sid_bw, st->exc_mem2_fx ); + + /* comfort noise generation */ + CNG_exc_fx( st->core_brate_fx, L_FRAME, &st->Enew_fx, &st->cng_seed_fx, exc, exc2, &st->lp_ener_fx, + st->last_core_brate_fx, &st->first_CNG_fx, &st->cng_ener_seed_fx, dummy_buf, allow_cn_step, + &st->last_allow_cn_step_fx, sub(st->prev_Q_new,1), sub(Q_new,1), st->num_ho_fx, q_env, st->lp_env_fx, + st->old_env_fx, st->exc_mem_fx, st->exc_mem1_fx, &sid_bw, &st->cng_ener_seed1_fx, exc3, st->Opt_AMR_WB_fx ); + + if ( st->first_CNG_fx == 0 ) + { + st->first_CNG_fx = 1; + move16(); + } + + /* synthesis */ + syn_12k8_fx( L_FRAME, Aq, exc2, dummy_buf, st->LPDmem.mem_syn3, 1, Q_new, st->Q_syn ); + + /* reset the encoder */ + CNG_reset_enc_fx( st, &(st->LPDmem), pitch_buf, dummy_buf+L_FRAME, 0 ); + + /* update st->mem_syn1 for ACELP core switching */ + Copy( st->LPDmem.mem_syn3, st->mem_syn1_fx, M ); + + /* update ACELP core synthesis filter memory */ + Copy( st->LPDmem.mem_syn3, st->LPDmem.mem_syn, M ); + + /* update old synthesis buffer - needed for ACELP internal sampling rate switching */ + Copy( dummy_buf + L_FRAME - L_SYN_MEM, st->LPDmem.mem_syn_r, L_SYN_MEM ); + /* Update MODE2 core switching memory */ + E_UTIL_deemph2( sub(Q_new,1), dummy_buf, PREEMPH_FAC, L_FRAME, &(st->LPDmem.syn[M]) ); + Copy( dummy_buf+L_FRAME-M-1, st->LPDmem.syn, M+1 ); + + } + + /*----------------------------------------------------------------* + * Encoding of all other frames + *----------------------------------------------------------------*/ + + ELSE + { + /*-----------------------------------------------------------------* + * After inactive period, use the most up-to-date ISPs + *-----------------------------------------------------------------*/ + test(); + IF( EQ_32(st->last_core_brate_fx,FRAME_NO_DATA)||EQ_32(st->last_core_brate_fx,SID_1k75)) + { + Copy( st->lspCNG_fx, st->lsp_old_fx, M ); + E_LPC_isp_isf_conversion( st->lspCNG_fx, st->lsf_old_fx, M); + set16_fx( old_exc, 0, L_EXC_MEM ); + } + + /*-----------------------------------------------------------------* + * ISF Quantization and interpolation + *-----------------------------------------------------------------*/ + + isf_enc_amr_wb_fx( st, isf_new, isp_new, Aq, &st->stab_fac_fx); + + /*---------------------------------------------------------------* + * Calculation of LP residual (filtering through A[z] filter) + *---------------------------------------------------------------*/ + + calc_residu_fx( st, inp, res, Aq, 0, 0 ); + st->burst_ho_cnt_fx = 0; + move16(); + + /*------------------------------------------------------------* + * Encode excitation + *------------------------------------------------------------*/ + + encod_amr_wb_fx( st, &(st->LPDmem), inp, Aw, Aq, pitch, voicing, res, syn, exc, exc2, pitch_buf, hf_gain_fx, inp_16k, shift, Q_new ); + + /* update st->mem_syn1 for ACELP core switching */ + Copy( st->LPDmem.mem_syn, st->mem_syn1_fx, M ); + + /* update old synthesis buffer - needed for ACELP internal sampling rate switching */ + Copy( syn + L_FRAME - L_SYN_MEM, st->LPDmem.mem_syn_r, L_SYN_MEM ); + + /* Update MODE2 core switching memory */ + E_UTIL_deemph2( sub(Q_new,1), syn, PREEMPH_FAC, L_FRAME, &(st->LPDmem.syn[M]) ); + Copy( syn+L_FRAME-M-1, st->LPDmem.syn, M+1 ); + + /*--------------------------------------------------------------------------------------* + * Write VAD information into the bitstream in AMR-WB IO mode + *--------------------------------------------------------------------------------------*/ + + push_indice_fx( st, IND_VAD_FLAG, vad_flag, 1 ); + } + + /*-----------------------------------------------------------------* + * Updates + *-----------------------------------------------------------------*/ + + /* update old weighted speech buffer - for OL pitch analysis */ + Copy( &old_wsp[L_FRAME], st->old_wsp_fx, L_WSP_MEM ); + + /* update old input signal buffer */ + Copy( &old_inp[L_FRAME], st->old_inp_12k8_fx, L_INP_MEM ); + + /* update old input signal @16kHz buffer */ + IF( GT_32(st->input_Fs_fx,8000)) + { + Copy( &old_inp_16k[L_FRAME16k], st->old_inp_16k_fx, L_INP_MEM ); + } + + /* update of old per-band energy spectrum */ + Copy32( fr_bands + NB_BANDS, st->enrO_fx, NB_BANDS ); + + /* update the last bandwidth */ + st->last_input_bwidth_fx = st->input_bwidth_fx; + st->last_bwidth_fx = st->bwidth_fx; + + /* update signal buffers */ + Copy( new_inp, st->buf_speech_enc_pe+L_FRAME, L_FRAME ); + Copy( wsp, st->buf_wspeech_enc+L_FRAME+L_SUBFR, L_FRAME + L_LOOK_12k8 ); + updt_enc_fx( st, L_FRAME, coder_type, old_exc, pitch_buf, 0, Aq, isf_new, isp_new, dummy_buf ); + + core_encode_update( st ); + + /* update main codec parameters */ + st->last_extl_fx = -1; + move16(); + st->last_core_fx = st->core_fx; + move16(); + st->last_L_frame_fx = L_FRAME; + move16(); + st->last_core_brate_fx = st->core_brate_fx; + move16(); + st->last_total_brate_fx = st->total_brate_fx; + move16(); + st->Etot_last_fx = Etot; + move16(); + st->last_coder_type_raw_fx = st->coder_type_raw_fx; + move16(); + st->last_codec_mode = st->codec_mode; + move16(); + + st->prev_Q_new = Q_new; + + /* Increase the counter of initialization frames */ + if( LT_16(st->ini_frame_fx,MAX_FRAME_COUNTER)) + { + st->ini_frame_fx = add(st->ini_frame_fx,1); + } + + if( GT_32(st->core_brate_fx,SID_1k75)) + { + st->last_active_brate_fx = st->total_brate_fx; + move32(); + } + + test(); + IF ( GT_32(st->core_brate_fx,SID_1k75)&&st->first_CNG_fx) + { + if( GE_16(st->act_cnt_fx,BUF_DEC_RATE)) + { + st->act_cnt_fx = 0; + move16(); + } + + st->act_cnt_fx = add(st->act_cnt_fx,1); + + test(); + if( EQ_16(st->act_cnt_fx,BUF_DEC_RATE)&&st->ho_hist_size_fx>0) + { + st->ho_hist_size_fx = sub(st->ho_hist_size_fx,1); + } + + st->act_cnt2_fx = add(st->act_cnt2_fx,1); + if( GE_16(st->act_cnt2_fx, MIN_ACT_CNG_UPD)) + { + st->act_cnt2_fx = MIN_ACT_CNG_UPD; + move16(); + } + } + + + return; +} diff --git a/lib_enc/analy_lp_fx.c b/lib_enc/analy_lp_fx.c new file mode 100644 index 0000000..0ca8c66 --- /dev/null +++ b/lib_enc/analy_lp_fx.c @@ -0,0 +1,173 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "rom_enc_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * analy_lp() + * + * Perform LP analysis + * + * - autocorrelations + lag windowing + * - Levinson-Durbin algorithm to find A(z) + * - convert A(z) to LSPs + * - find interpolated LSPs and convert back to A(z) for all subframes + * - update LSPs for the next frame + *-------------------------------------------------------------------*/ + +void analy_lp_fx( + const Word16 speech[], /* i : pointer to the speech frame */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 L_look, /* i : look-ahead */ + Word32 *ener, /* o : residual energy from Levinson-Durbin */ + Word16 A[], /* o : A(z) filter coefficients */ + Word16 epsP_h[], /* o : LP analysis residual energies for each iteration */ + Word16 epsP_l[], /* o : LP analysis residual energies for each iteration */ + Word16 lsp_new[], /* o : current frame LSPs */ + Word16 lsp_mid[], /* o : current mid-frame LSPs */ + Word16 lsp_old[], /* i/o: previous frame unquantized LSPs */ + const Word16 Top[2], /* i : open loop pitch lag */ + const Word16 Tnc[2], /* i : open loop pitch gain */ + const Word32 Core_sr, /* i : Internal core sampling rate */ + Word16 Q_new, + Word16 *Q_r +) +{ + Word16 r_h[M+1]; /* Autocorrelations of windowed speech MSB */ + Word16 r_l[M+1]; /* Autocorrelations of windowed speech LSB */ + Word32 LepsP[M+1]; + Word16 i, i_subfr, wind_length = 0; + Word16 *lsp; + const Word16 *wind = NULL; + const Word16 *pt; + Word16 half_frame; + + IF( EQ_16(L_frame,L_FRAME)) + { + wind_length = L_LP; + move16(); + wind = Assym_window_W16fx; + } + ELSE /* L_frame == L_FRAME16k */ + { + wind_length = L_LP_16k; + move16(); + wind = assym_window_16k_fx; + } + lsp = lsp_mid; + half_frame = shr(L_frame,1); + + FOR( i_subfr = 0; i_subfr <= 1; i_subfr++ ) + { + pt = speech + sub(add(half_frame, L_look), wind_length); + half_frame = shl(half_frame,1); + + /* Autocorrelations */ + autocorr_fx(pt, M, r_h, r_l, &Q_r[1-i_subfr], wind_length, wind, 0, 0 ); + + /* Lag windowing */ + adapt_lag_wind( r_h, r_l, M, Top[i_subfr], Tnc[i_subfr], Core_sr ); + + /* Levinson-Durbin */ + E_LPC_lev_dur(r_h, r_l, A, LepsP, M, NULL); + FOR (i = 0; i <= M; i++) + { + L_Extract(LepsP[i], &epsP_h[i], &epsP_l[i]); + } + /*Q_r[... might not be needed from external...*/ + Q_r[1-i_subfr] = add(Q_r[1-i_subfr], shl(Q_new, 1)); + move16(); + + /* Conversion of A(z) to LSPs */ + E_LPC_a_lsp_conversion( A, lsp, lsp_old, M ); + + lsp = lsp_new; + } + + /* LSP interpolation */ + int_lsp4_fx( L_frame, lsp_old, lsp_mid, lsp_new, A , M, 0 ); + Copy (lsp_new, lsp_old, M); + *ener = L_Comp(epsP_h[M],epsP_l[M]); + move32(); + + return; + +} + + +/*-------------------------------------------------------------------* + * analy_lp_AMR_WB() + * + * Perform LP analysis for AMR-WB IO mode + * + * - autocorrelations + lag windowing + * - Levinson-Durbin algorithm to find A(z) + * - convert A(z) to ISPs + * - find interpolated ISPs and convert back to A(z) for all subframes + * - update ISPs for the next frame + *-------------------------------------------------------------------*/ + +void analy_lp_AMR_WB_fx( + const Word16 speech[], /* i : pointer to the speech frame */ + Word32 *ener, /* o : residual energy from Levinson-Durbin */ + Word16 A[], /* o : A(z) filter coefficients */ + Word16 epsP_h[], /* o : LP analysis residual energies for each iteration */ + Word16 epsP_l[], /* o : LP analysis residual energies for each iteration */ + Word16 isp_new[], /* o : current frame ISPs */ + Word16 isp_old[], /* i/o: previous frame unquantized ISPs */ + Word16 isf_new[], /* o : current frame ISPs */ + Word16 Top, /* i : open loop pitch lag */ + Word16 Tnc, /* i : open loop pitch gain */ + Word16 Q_new, + Word16 *Q_r +) +{ + Word16 r_h[M+1]; /* Autocorrelations of windowed speech MSB */ + Word16 r_l[M+1]; /* Autocorrelations of windowed speech LSB */ + Word32 LepsP[M+1]; + Word16 i, wind_length = 0; + const Word16 *wind; + + /* Initialization */ + wind_length = L_LP_AMR_WB; + move16(); + wind = Hamcos_Window; + + /* Autocorrelations */ + autocorr_fx( speech - L_SUBFR, M, r_h, r_l, &Q_r[0], wind_length, wind, 0, 0 ); + + /* Lag windowing */ + adapt_lag_wind( r_h, r_l, M, Top, Tnc, INT_FS_FX ); + + /* Levinson-Durbin */ + /*lev_dur( A, r, M, epsP );*/ + E_LPC_lev_dur(r_h, r_l, A, LepsP, M, NULL); + FOR (i = 0; i <= M; i++) + { + L_Extract(LepsP[i], &epsP_h[i], &epsP_l[i]); + } + /*Q_r[... might not be needed from external...*/ + Q_r[0] = add(Q_r[0], shl(Q_new, 1)); + move16(); + + E_LPC_a_lsf_isf_conversion( A, isf_new, stable_ISF_fx, M, 0 ); + E_LPC_isf_isp_conversion( isf_new, isp_new, M ); + + /* ISP interpolation */ + int_lsp_fx( L_FRAME, isp_old, isp_new, A, M, interpol_isp_amr_wb_fx, 1 ); + + /**ener = epsP[M];*/ + *ener = L_Comp(epsP_h[M],epsP_l[M]); + move32(); + + /* updates */ + Copy( isp_new, isp_old, M ); + + return; +} diff --git a/lib_enc/analy_sp.c b/lib_enc/analy_sp.c new file mode 100644 index 0000000..149f738 --- /dev/null +++ b/lib_enc/analy_sp.c @@ -0,0 +1,387 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "cnst_fx.h" +#include "stl.h" +#include "basop_util.h" +#include "prot_fx.h" +#include "rom_enc_fx.h" +#include + + +static void find_enr( Word16 data[], Word32 band[], Word32 *ptE, Word32 *LEtot, const Word16 min_band, const Word16 max_band, + const Word16 Q_new2, const Word32 e_min, Word32 *Bin_E, Word16 BIN_FREQ_FX, Word32 *band_energies ); + +/*-------------------------------------------------------------------* + * analy_sp() + * + * Spectral analysis of 12.8kHz input + *-------------------------------------------------------------------*/ + +void analy_sp( + Word16 *speech, /* i : speech buffer Q_new - preemph_bits */ + const Word16 Q_new, /* i : current scaling exp Q0 */ + Word32 *fr_bands, /* o : energy in critical frequency bands Q_new + QSCALE */ + Word32 *lf_E, /* o : per bin E for first... Q_new + QSCALE - 2*/ + Word16 *Etot, /* o : total input energy Q8 */ + const Word16 min_band, /* i : minimum critical band Q0 */ + const Word16 max_band, /* i : maximum critical band Q0 */ + const Word32 e_min_scaled, /* i : minimum energy scaled Q_new + QSCALE */ + Word16 Scale_fac[2], /* o : FFT scales factors (2 values by frame) Q0 */ + Word32 *Bin_E, /* o : per-bin energy spectrum */ + Word32 *Bin_E_old, /* o : per-bin energy spectrum of the previous frame */ + Word32 *PS, /* o : per-bin energy spectrum */ + Word16 *EspecdB, /* o : per-bin log energy spectrum (with f=0) Q7 */ + Word32 *band_energies,/* o : energy in critical frequency bands without minimum noise floor MODE2_E_MIN */ + Word16 *fft_buff /* o : FFT coefficients */ +) +{ + Word16 *pt; + Word16 i_subfr, i, exp_etot, frac_etot, exp, exp_frac, exp2; + Word32 *pt_bands; + Word32 Ltmp, LEtot, L_tmp2; + Word16 *pt_fft; + Word16 Min_val, Max_val; + Word16 Scale_fac2; + Word16 fft_temp[L_FFT]; + + + /*-----------------------------------------------------------------* + * Compute spectrum + * find energy per critical frequency band and total energy in dB + *-----------------------------------------------------------------*/ + + pt_bands = fr_bands; + pt_fft = fft_buff; + LEtot = L_deposit_l(0); + + FOR (i_subfr=0; i_subfr <= 1; i_subfr++) + { + pt = speech + 3*(L_SUBFR/2) - L_FFT/2; + if(i_subfr != 0) + { + pt = speech + 7*(L_SUBFR/2) - L_FFT/2; + } + + /* Clear 1st value of 1st part, copy 1st value of 2nd part */ + fft_temp[0] = 0; + move16(); + fft_temp[L_FFT/2] = pt[L_FFT/2]; + move16(); + Max_val = s_max(fft_temp[0],fft_temp[L_FFT/2]); + Min_val = s_min(fft_temp[0],fft_temp[L_FFT/2]); + + FOR (i=1; i 0) + Max_val = s_max(Max_val, fft_temp[i]); + if (fft_temp[i] < 0) + Min_val = s_min(Min_val, fft_temp[i]); + + /* 2nd windowed part */ + fft_temp[L_FFT-i] = mult_r(pt[L_FFT-i], sqrt_han_window[i]); + move16(); + if (fft_temp[L_FFT-i] > 0) + Max_val = s_max(Max_val, fft_temp[L_FFT-i]); + if (fft_temp[L_FFT-i] < 0) + Min_val = s_min(Min_val, fft_temp[L_FFT-i]); + } + + /* Combine -Min_val and Max_val into one */ + Max_val = s_max(negate(Min_val),Max_val); + + Scale_fac[i_subfr] = s_min(sub(norm_s(Max_val), 1), 6); + move16(); + Scale_fac2 = shl(Scale_fac[i_subfr], 1); + Scale_sig(fft_temp, L_FRAME_12k8, Scale_fac[i_subfr]); + + r_fft_fx_lc(FFT_W128, SIZE_256, SIZE2_256, NUM_STAGE_256, fft_temp, pt_fft, 1); + + /* find energy per critical band */ + find_enr( pt_fft, pt_bands, lf_E + i_subfr*VOIC_BINS, &LEtot, min_band, max_band, + add(Q_new,Scale_fac2), e_min_scaled, &Bin_E[i_subfr*L_FFT/2], BIN, band_energies + i_subfr*NB_BANDS); + + pt_bands += NB_BANDS; + pt_fft += L_FFT; + } + + /* Average total log energy over both half-frames */ + frac_etot = 0; + move16(); + exp_etot = norm_l(LEtot); + IF (LEtot != 0) /* Log2_norm_lc doesn't Support Input <= 0; deal with it here */ + { + frac_etot = Log2_norm_lc(L_shl(LEtot, exp_etot)); + exp_etot = sub(30, exp_etot); + } + exp_etot = sub(exp_etot, add(Q_new, 1+3)); /* remove scaling effect, 4 already removed */ + Ltmp = Mpy_32(exp_etot, frac_etot, LG10, 0); + + /*Q8 Averaged the total energy over both half-frames in log10 */ + *Etot = extract_l(L_shr(Ltmp, 14-8)); + + Bin_E[L_FFT/2-1] = Bin_E[L_FFT/2-2]; + move32(); + Bin_E[L_FFT-1] = Bin_E[L_FFT-2]; + move32(); + + /* Per-bin log-energy spectrum */ + exp2 = sub(31, add(Q_new, QSCALE-2)); + L_tmp2 = L_mac(-56783L, exp2, 28391); + FOR (i = 0; i < L_FFT/2; i++) + { + Bin_E_old[i] = Bin_E[i]; + move32(); + + /* tmp = (input[i] + input[i+Len]+0.001f)/2.0f */ + Ltmp = L_max(1, L_add(L_shr(Bin_E[i],1), L_shr(Bin_E[i+L_FFT/2],1))); + if(PS != NULL) + { + PS[i] = Ltmp; + move32(); + } + + /* 10.0*log((float)tmp) */ + /* 10.0*Log(2)*Log2(L_tmp/2) */ + /* 6.93147*Log2(L_tmp/2) */ + /* 0.86643*(Log2(L_tmp)-1)*8 */ + /* 0.86643*Log2(L_tmp)*8 - 6.93147 */ + /* We'll put it in Q8 */ + exp = norm_l(Ltmp); + exp_frac = Log2_norm_lc(L_shl(Ltmp, exp)); + /* -56783L is to substract 0.86643 in Q16 */ + /* 28391 is 0.86643 in Q15 */ + /* 1774 is (0.86643 in Q15) * 8 / 128 (/128 to go in Q7) */ + EspecdB[i] = mac_r(L_shl(L_msu(L_tmp2, exp, 28391), 3+7), exp_frac, 887); + move16(); + } + + + return; +} + +/*------------------------------------------------------------------------* + * find_enr() + * + * find input signal energy for each critical band and first 74 LF bins + * The energy is normalized by the number of frequency bins in a channel + *------------------------------------------------------------------------*/ + +static void find_enr( + Word16 data[], /* i : fft result */ + Word32 band[], /* o : per band energy Q_new + QSCALE */ + Word32 *ptE, /* o : per bin energy for low frequencies Q_new + QSCALE-2 */ + Word32 *LEtot, /* o : total energy Q_new + QSCALE */ + const Word16 min_band, /* i : minimum critical band Q0 */ + const Word16 max_band, /* i : maximum critical band Q0 */ + const Word16 Q_new2, /* i : scaling factor Q0 */ + const Word32 e_min, /* i : minimum energy scaled Q_new + QSCALE */ + Word32 *Bin_E, /* o : Per bin energy Q_new + QSCALE-2 */ + Word16 BIN_FREQ_FX, /* i : Number of frequency bins */ + Word32 *band_energies /* o : per band energy without MODE2_E_MIN */ +) +{ + Word16 i, cnt, shift_to_norm; + Word16 freq, wtmp; + Word16 *ptR, *ptI, diff_scaleP1, diff_scaleM2; + Word16 exp_band; + Word32 Ltmp, Ltmp1; + Word16 voic_band; + Word32 etot; + Word16 exp_etot; + Word32 *tmpptr; + + + ptR = &data[1]; /* first real */ + ptI = &data[L_FFT-1]; /* first imaginary */ + + /*-----------------------------------------------------------------------------------* + * Scaling needed by band and ptE output + * Wants all energies scaled by Q_new + QSCALE to maintain maximum + * precision on bckr noise in clean speech + * First shift left by Q_new + QSCALE than shift right by 2*Q_new-1 + * shift left (Q_new + QSCALE - (2*Q_new -1)) + * shift left (QSCALE - Q_new + 1) == shift left by (QSCALE+1) - Q_new + *-----------------------------------------------------------------------------------*/ + + diff_scaleP1 = sub(QSCALE+1 + 1, Q_new2); + diff_scaleM2 = sub(QSCALE+1 - 2, Q_new2); + + voic_band = VOIC_BAND_8k; + move16(); + assert (VOIC_BAND == VOIC_BAND_8k); + + etot = L_deposit_l(0); + exp_etot = 0; + move16(); + + /*-----------------------------------------------------------------* + * For low frequency bins, save per bin energy for the use + * in NS and find_tilt() + *-----------------------------------------------------------------*/ + + freq = BIN_FREQ_FX; + move16(); + FOR (i = 0; i < voic_band; i++) /* up to maximum allowed voiced critical band */ + { + tmpptr = Bin_E; + move16(); + Ltmp1 = L_deposit_l(0); + + FOR (; freq <= crit_bands[i]; freq += BIN_FREQ_FX) + { + /*ptE = *ptR * *ptR + *ptI * *ptI */ /* energy */ + Ltmp = L_mult(*ptI, *ptI); + Ltmp = L_mac(Ltmp, *ptR, *ptR); + + /* *ptE *= 4.0 / (L_FFT*L_FFT) */ + /* normalization - corresponds to FFT normalization by 2/L_FFT */ + BASOP_SATURATE_WARNING_OFF; /* saturation seems to have no effect (tested by simulation) */ + *ptE = L_shl(Ltmp, diff_scaleM2); + move32(); /* scaled by Q_new + QSCALE - 2 */ + BASOP_SATURATE_WARNING_ON; + /*band[i] += *ptE++;*/ + *Bin_E = *ptE; + move32(); + Bin_E++; + Ltmp1 = L_add(Ltmp1, Ltmp); + + ptE++; + ptR++; + ptI--; + } + + exp_band = sub(norm_l(Ltmp1), 1);/* divide by 2 to ensure band < cnt */ + wtmp = round_fx(L_shl(Ltmp1, exp_band)); + + /* band[i] /= cnt */ /* normalization per frequency bin */ + cnt = (Word16)(Bin_E - tmpptr); + shift_to_norm = norm_s(cnt); + wtmp = div_s(wtmp, shl(cnt, shift_to_norm)); + Ltmp1 = L_deposit_l(wtmp); + + exp_band = sub(exp_band, shift_to_norm); + exp_band = sub(diff_scaleP1, exp_band); + BASOP_SATURATE_WARNING_OFF; /* saturation seems to have no effect (tested by simulation) */ + band[i] = L_shl(Ltmp1, exp_band); + move32();/* band scaled by Q_new + QSCALE */ + BASOP_SATURATE_WARNING_ON; + + test(); + IF (GE_16(i,min_band)&&LE_16(i,max_band)) + { + IF (LT_32(band[i],e_min)) + { + Ltmp1 = L_shl(e_min, 0); + exp_band = 0; + move16(); + } + + wtmp = sub(exp_band, exp_etot); + if (wtmp > 0) + { + etot = L_shr(etot, wtmp); + } + exp_etot = s_max(exp_etot, exp_band); + etot = L_add(etot, L_shl(Ltmp1, sub(exp_band, exp_etot))); + } + + band_energies[i] = band[i]; + move32(); + + band[i] = L_max(band[i], e_min); + move32(); + } + + IF (EQ_16(BIN_FREQ_FX, 50)) + { + /*-----------------------------------------------------------------* + * Continue compute the E per critical band for high frequencies + *-----------------------------------------------------------------*/ + + FOR (i = voic_band; i < NB_BANDS; i++) + { + tmpptr = Bin_E; + move16(); + Ltmp1 = L_deposit_l(0); + + FOR (; freq <= crit_bands[i]; freq += BIN_FREQ_FX) + { + /* *ptE = *ptR * *ptR + *ptI * *ptI */ + Ltmp = L_mult(*ptI, *ptI); + Ltmp = L_mac(Ltmp, *ptR, *ptR); + + /* *ptE *= 4.0 / (L_FFT*L_FFT) */ + /* normalization - corresponds to FFT normalization by 2/L_FFT */ + BASOP_SATURATE_WARNING_OFF; /* saturation seems to have no effect (tested by simulation) */ + *Bin_E = L_shl(Ltmp, diff_scaleM2); + move32(); /* scaled by Q_new + QSCALE - 2 */ + BASOP_SATURATE_WARNING_ON; + Bin_E++; + Ltmp1 = L_add(Ltmp1, Ltmp); + + ptR++; + ptI--; + } + + exp_band = sub(norm_l(Ltmp1), 1); /* divide by 2 to ensure band < cnt */ + wtmp = round_fx(L_shl(Ltmp1, exp_band)); + + /* band[i] /= cnt */ /* normalization per frequency bin */ + cnt = (Word16)(Bin_E - tmpptr); + shift_to_norm = norm_s(cnt); + wtmp = div_s(wtmp, shl(cnt, shift_to_norm)); + Ltmp1 = L_deposit_l(wtmp); + + exp_band = sub(exp_band, shift_to_norm); + exp_band = sub(diff_scaleP1, exp_band); + BASOP_SATURATE_WARNING_OFF; /* saturation seems to have no effect (tested by simulation) */ + band[i] = L_shl(Ltmp1, exp_band); + move32();/* band scaled by Q_new + QSCALE */ + BASOP_SATURATE_WARNING_ON; + + test(); + IF (GE_16(i,min_band)&&LE_16(i,max_band)) + { + IF (LT_32(band[i],e_min)) + { + Ltmp1 = L_shl(e_min, 0); + exp_band = 0; + move16(); + } + + wtmp = sub(exp_band, exp_etot); + if (wtmp > 0) + { + etot = L_shr(etot, wtmp); + } + exp_etot = s_max(exp_etot, exp_band); + + etot = L_add(etot, L_shl(Ltmp1, sub(exp_band, exp_etot))); + } + + band_energies[i] = band[i]; + move32(); + + band[i] = L_max(band[i], e_min); + move32(); + } + } + + /*-----------------------------------------------------------------* + * Find the total energy over the input bandwidth + *-----------------------------------------------------------------*/ + + etot = L_add(*LEtot, L_shl(etot, sub(exp_etot, 4))); + + *LEtot = etot; + move32(); + + + return; +} diff --git a/lib_enc/ari_enc.c b/lib_enc/ari_enc.c new file mode 100644 index 0000000..afae0f3 --- /dev/null +++ b/lib_enc/ari_enc.c @@ -0,0 +1,321 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "assert.h" +#include "stl.h" +#include "basop_mpy.h" +#include "cnst_fx.h" +#include "rom_com_fx.h" +#include "prot_fx.h" + +/** + * \brief Copy state + * + * \param[i] source + * \param[o] dest + * + * \return none + */ +void ari_copy_states(TastatEnc *source, TastatEnc *dest) +{ + dest->low = source->low; + move32(); + dest->high = source->high; + move32(); + dest->vobf = source->vobf; + move16(); +} + +/*--------------------------------------------------------------- + Ari encoder 14 bits routines + -------------------------------------------------------------*/ + + +/** + * \brief Start ArCo encoding + * + * \param[o] s + * + * \return none + */ +void ari_start_encoding_14bits(TastatEnc *s) +{ + s->low = L_deposit_l(0); + s->high = ari_q4new + 1; + move32(); + s->vobf = 0; + move16(); +} + + +/* Returns: new bit-stream position */ +static Word16 ari_put_bit_plus_follow( + Word16 ptr[], /* o: bit-stream */ + Word16 bp, /* i: bit-stream position */ + Word16 bits_to_follow, /* i: number of opposite bits to follow 'bit' */ + Word16 bit /* i: bit to send */ +) +{ + assert(bit == 0 || bit == 1); + ptr[bp++] = bit; /* send initially a zero or one */ move16(); + bit = s_xor(bit, 1); /* invert bit to send */ + FOR ( ; bits_to_follow > 0; bits_to_follow--) + { + ptr[bp++] = bit; /* send inverted bit */ move16(); + } + return bp; +} + +/** + * \brief Finish ArCo encoding + * + * \param[o] ptr + * \param[i] bp + * \param[i] s + * + * \return bit consumption + */ +Word16 ari_done_encoding_14bits(Word16 *ptr, Word16 bp, TastatEnc *s) +{ + Word16 bit; + + bit = 0; + move16(); + if ( GE_32(s->low,ari_q1new)) + { + bit = s_xor(bit,1); + } + return ari_put_bit_plus_follow(ptr, bp, add(s->vobf, 1), bit); +} + + + +/** + * \brief encode function for extended proba tables: less branches needed for coding + * + * \param[o] ptr + * \param[i] bp + * \param[i/o] s + * \param[i] symbol + * \param[i] cum_freq + * + * \return bit consumption + */ +Word16 ari_encode_14bits_ext( + Word16 *ptr, + Word16 bp, + TastatEnc *s, + Word32 symbol, + UWord16 const *cum_freq +) +{ + Word32 low; + Word32 high; + Word32 range; + Word16 bits_to_follow; + Word16 i; + UWord16 temp; + Word32 L_temp1, L_temp2; + + high = L_add(s->high, 0); + low = L_add(s->low, 0); + range = L_sub(high, low); + + L_temp1 = L_shl(range,15-stat_bitsnew/*both are constants*/); + Mpy_32_16_ss(L_temp1, cum_freq[symbol+1], &L_temp2, &temp); + if (symbol != 0) /* when symbol is 0, range remains unchanged */ + { + Mpy_32_16_ss(L_temp1, cum_freq[symbol], &range, &temp); + } + high = L_add(low, range); + low = L_add(low, L_temp2); + + bits_to_follow = s->vobf; + move16(); + + FOR (i = 0; i < 0x7FFF; i++) + { + IF (LE_32(high, ari_q2new)) + { + bp = ari_put_bit_plus_follow(ptr, bp, bits_to_follow, 0); + bits_to_follow = 0; + move16(); + } + ELSE IF (GE_32(low, ari_q2new)) + { + bp = ari_put_bit_plus_follow(ptr, bp, bits_to_follow, 1); + bits_to_follow = 0; + move16(); + low = L_sub(low, ari_q2new); + high = L_sub(high, ari_q2new); /* Subtract offset to top. */ + } + ELSE + { + test(); + IF (GE_32(low, ari_q1new)&&LE_32(high,ari_q3new)) + { + /* Output an opposite bit */ + /* later if in middle half. */ + bits_to_follow = add(bits_to_follow, 1); + low = L_sub(low, ari_q1new); /* Subtract offset to middle*/ + high = L_sub(high, ari_q1new); + } + ELSE { + BREAK; /* Otherwise exit loop. */ + } + } + + low = L_add(low, low); + high = L_add(high, high); /* Scale up code range. */ + } + + s->low = low; + move32(); + s->high = high; + move32(); + s->vobf = bits_to_follow; + move16(); + + return bp; +} + +Word16 ari_encode_overflow(TastatEnc *s) +{ + return L_sub(L_sub(s->high, 1), s->low) <= 0; +} + + +static Word16 ari_encode_14bits_high_low(Word16 *ptr, Word16 bp, Word16 bits, TastatEnc *s, Word32 high, Word32 low) +{ + Word16 bits_to_follow, tmp; + + bits_to_follow = s->vobf; + move16(); + + /* while there are more than 16 bits left */ + tmp = sub(16, bits); + WHILE (add(add(bp, bits_to_follow), tmp) < 0) + { + IF (LE_32(high, ari_q2new)) + { + bp = ari_put_bit_plus_follow(ptr, bp, bits_to_follow, 0); + bits_to_follow = 0; + move16(); + } + ELSE IF (GE_32(low, ari_q2new)) + { + bp = ari_put_bit_plus_follow(ptr, bp, bits_to_follow, 1); + bits_to_follow = 0; + move16(); + low = L_sub(low, ari_q2new); + high = L_sub(high, ari_q2new); /* Subtract offset to top. */ + } + ELSE + { + test(); + IF (GE_32(low, ari_q1new)&&LE_32(high,ari_q3new)) + { + /* Output an opposite bit */ + /* later if in middle half. */ + bits_to_follow = add(bits_to_follow, 1); + low = L_sub(low, ari_q1new); /* Subtract offset to middle*/ + high = L_sub(high, ari_q1new); + } + ELSE { + BREAK; /* Otherwise exit loop. */ + } + } + + low = L_add(low, low); + high = L_add(high, high); /* Scale up code range. */ + } + + s->low = low; + move32(); + s->high = high; + move32(); + s->vobf = bits_to_follow; + move16(); + + return bp; +} + +/*------------------------------------------------------------------------ + * Function: ari_encode_14bits_range + * + * Encode an cumulative frequency interval. + *-------------------------------------------------------------------------*/ + +Word16 ari_encode_14bits_range(Word16 *ptr, Word16 bp, Word16 bits, TastatEnc *s, Word16 cum_freq_low, Word16 cum_freq_high) +{ + Word32 low, high, range; + + range = L_sub(s->high, s->low); + + high = L_add(s->low, mul_sbc_14bits(range, cum_freq_high)); + low = L_add(s->low, mul_sbc_14bits(range, cum_freq_low)); + + return ari_encode_14bits_high_low(ptr, bp, bits, s, high, low); +} + + +/*------------------------------------------------------------------------ + * Function: ari_encode_14bits_sign + * + * Encode a sign with equal probabilities. + *-------------------------------------------------------------------------*/ +Word16 ari_encode_14bits_sign(Word16 *ptr, Word16 bp, Word16 bits, TastatEnc *s, Word16 sign) +{ + Word32 low, high, range; + Word32 L_tmp; + + high = L_add(s->high, 0); + low = L_add(s->low, 0); + range = L_sub(high, low); + + L_tmp = L_shr(range, 1); + if (sign != 0) + { + high = L_add(low, L_tmp); + } + if (sign == 0) + { + low = L_add(low, L_tmp); + } + + return ari_encode_14bits_high_low(ptr, bp, bits, s, high, low); +} + +/*------------------------------------------------------------------------ + * Function: ari_done_cbr_encoding_14bits + * + * Finish up encoding in CBR mode. + *-------------------------------------------------------------------------*/ +Word16 ari_done_cbr_encoding_14bits(Word16 *ptr, Word16 bp, Word16 bits, TastatEnc *s) +{ + Word16 high, tmp, k; + + tmp = sub(bits, 16); + WHILE (GT_16(sub(tmp, bp), s->vobf)) + { + bp = ari_encode_14bits_sign(ptr, bp, bits, s, 0); + } + + high = extract_l(L_sub(s->high, 1)); + + bp = ari_put_bit_plus_follow(ptr, bp, s->vobf, lshr(high, 15)); + high = lshl(high, 1); + + tmp = s_min(15, sub(bits, bp)); + FOR (k=0; k +#include +#include +#include +#include "stl.h" +#include "cnst_fx.h" +#include "basop_util.h" +#include "rom_com_fx.h" +#include "rom_enc_fx.h" +#include "prot_fx.h" + +Word16 EncodeIndex( + Word16 Bandwidth, + Word16 PeriodicityIndex, + Encoder_State_fx *st +) +{ + Word16 NumRatioBitsBwLtpIndx; + + IF ( s_and(PeriodicityIndex, kLtpHmFlag) != 0 ) + { + Word16 LtpPitchIndex = shr(PeriodicityIndex, 9); + assert(0 <= LtpPitchIndex && LtpPitchIndex <= 16); + + PeriodicityIndex = sub(PeriodicityIndex, 1); + assert((PeriodicityIndex & 0xff) < (1 << NumRatioBits[Bandwidth][LtpPitchIndex])); + + NumRatioBitsBwLtpIndx = NumRatioBits[Bandwidth][LtpPitchIndex]; + move16(); + + push_next_indice_fx(st, s_and(PeriodicityIndex, 0xff), NumRatioBitsBwLtpIndx); + return NumRatioBitsBwLtpIndx; + } + ELSE + { + push_next_indice_fx(st, PeriodicityIndex, 8); + return 8; + } +} + +static Word16 SearchPeriodicityIndex_Single( + const Word16 AbsMdct3[], + Word16 NumToConsider, + Word32 Lag, + Word16 FractionalResolution +) +{ + Word16 HighestMultiplier; + Word32 AbsMeanCurrent3; /* Mean for BucketWidth == 3 */ + Word32 Limit, OldIndex, i; + Word16 Result, tmp1, tmp2; + + + Limit = L_deposit_l(sub(NumToConsider, 1)); + Limit = L_shl(Limit, FractionalResolution); + AbsMeanCurrent3 = L_deposit_l(0); + HighestMultiplier = 0; + move16(); + + FOR (i=Lag; i 0) && (GT_16(LtpGain, kLtpHmGainThr))) + { + Bandwidth = 0; + move16(); + if (GE_16(NumToConsider, 256)) + { + Bandwidth = 1; + move16(); + } + + LtpPitchIndex = sub(mult_r(LtpPitchLag, 1 << (15-kLtpHmFractionalResolution)), 2); + assert(0 <= LtpPitchIndex && LtpPitchIndex <= 16); + + tmp32 = L_shl(L_deposit_l(sub(NumToConsider, 2)), kLtpHmFractionalResolution); + tmp = shl(1, NumRatioBits[Bandwidth][LtpPitchIndex]); + FOR (Multiplier = 1; Multiplier <= tmp; ++Multiplier) + { + Lag = L_shr(L_mult0(LtpPitchLag, Ratios[Bandwidth][LtpPitchIndex][Multiplier-1]), 8); + + test(); + IF ((GE_32(Lag, 4< 0) + { + tmp32 = L_mult0(Score, NumToConsider); /* -> 16Q15 */ + tmp = sub(norm_l(tmp32), 1); + tmp2 = norm_l(AbsTotal); + tmp3 = div_s( round_fx(L_shl(tmp32, tmp)), round_fx(L_shl(AbsTotal, tmp2)) ); + BASOP_SATURATE_WARNING_OFF + *RelativeScore = shr(tmp3, add(sub(tmp, tmp2), 2)); /* -> 2Q13 */ move16(); + BASOP_SATURATE_WARNING_ON + } + ELSE + { + *RelativeScore = 0; + move16(); + } + + return PeriodicityIndex; +} + +static void PeakFilter( + const Word32 x[], /* (I) absolute spectrum */ + Word32 y[], /* (O) filtered absolute spectrum, must not alias x[] */ + Word16 L_frame /* (I) number of spectral lines */ +) +{ + Word16 flen, i; +#define kPeakElevationThreshold 1.0f + Word16 m; + Word32 a; + + flen = shr(L_frame, 4); + /* m = kPeakElevationThreshold / (float)(2*flen + 1); */ + m = shr(div_s(8/*kPeakElevationThreshold Q3*/, add(shl(flen,1), 1)), 3); + + a = L_deposit_l(0); + FOR (i=0; i 0 ) + { + prm_hm[0] = 1; /* flag: on */ move16(); + + hm_bits = add(hm_bits, CountIndexBits(bw_flag, prm_hm[1])); + + if (EQ_16(coder_type, VOICED)) + { + hm_bits = add(hm_bits, kTcxHmNumGainBits); + } + + tcx_hm_modify_envelope( + gain, + lag, + fract_res, + p, + env, + L_frame + ); + } + ELSE + { + prm_hm[0] = 0; /* flag: off */ move16(); + prm_hm[1] = -1; /* pitch index */ move16(); + prm_hm[2] = 0; /* gain index */ move16(); + } + + *hm_bits_out = hm_bits; + move16(); +} + diff --git a/lib_enc/arith_coder_enc.c b/lib_enc/arith_coder_enc.c new file mode 100644 index 0000000..19d3e0e --- /dev/null +++ b/lib_enc/arith_coder_enc.c @@ -0,0 +1,814 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include + +#include "options.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "rom_com_fx.h" +#include "stl.h" + +/* Returns: estimated SQ scale Q15-e */ +static Word16 tcx_arith_estimate_scale( + const Word32 abs_spectrum[], /* i: absolute MDCT coefficients Q31-e */ + Word16 abs_spectrum_e, /* i: MDCT exponent Q0 */ + Word16 L_frame, /* i: number of spectral lines Q0 */ + const Word16 envelope[], /* i: scaled envelope Q15-e */ + Word16 envelope_e, /* i: scaled envelope exponent Q0 */ + Word16 *scale_e /* o: scale exponent Q0 */ +) +{ + Word16 scale, tmp, k, s, s1; + Word32 L_tmp, accu; + + + + /* compute normalised standard deviation and determine approximate scale */ + accu = L_deposit_l(0); + s = 30; + move16(); + + FOR (k = 0; k < L_frame; k++) + { + /* tmp = abs_spectrum[k] * envelope[k]; + scale += tmp * tmp; */ + + /* normalize, multiply, square */ + s1 = 30; + move16(); + if (abs_spectrum[k] != 0) + { + s1 = norm_l(abs_spectrum[k]); + } + + tmp = mult_r(round_fx(L_shl(abs_spectrum[k], s1)), envelope[k]); + L_tmp = L_mult0(tmp, tmp); + tmp = sub(shl(s1, 1), 1); + + /* adjust accu scaling */ + s1 = s; + move16(); + if (L_and(accu, 0x40000000) != 0) s = sub(s, 1); + s = s_min(s, tmp); + + s1 = sub(s1, s); + if (s1 != 0) accu = L_shr(accu, s1); + + /* scale and accumulate */ + BASOP_SATURATE_WARNING_OFF; + accu = L_add(accu, L_shr(L_tmp, sub(tmp, s))); + BASOP_SATURATE_WARNING_ON; + } + s = sub(shl(add(abs_spectrum_e, envelope_e), 1), s); + if (accu == 0) accu = L_deposit_l(1); + + /* scale = (float)sqrt((L_frame * 65536.0f*65536.0f*4.0f) / scale); */ + scale = BASOP_Util_Divide3216_Scale(accu, shl(L_frame, 2), &tmp); + s = sub(add(s, tmp), 15); + scale = ISqrt16(scale, &s); + *scale_e = s; + + + return scale; +} + +#define kMaxNumHeapElems 10 + +typedef struct HeapElem +{ + Word32 mScore; /* Sort key */ + Word16 mIndex; /* Original index */ +} HeapElem; + +typedef struct Heap +{ + HeapElem mElem[2*kMaxNumHeapElems+1]; + Word16 mSize; +} Heap; + +static void MinHeapify_i(Heap *H, Word16 i) +{ + Word16 left, right, largest; + HeapElem T; + + + + left = add(shl(i, 1), 1); + right = add(left, 1); + largest = i; + move16(); + + if (LT_32(H->mElem[left].mScore, H->mElem[largest].mScore)) + { + largest = left; + move16(); + } + + if (LT_32(H->mElem[right].mScore, H->mElem[largest].mScore)) + { + largest = right; + move16(); + } + + WHILE (NE_16(largest, i)) + { + T.mIndex = H->mElem[i].mIndex; + move16(); + T.mScore = L_add(H->mElem[i].mScore, 0); + + H->mElem[i].mIndex = H->mElem[largest].mIndex; + move16(); + H->mElem[i].mScore = H->mElem[largest].mScore; + move32(); + + H->mElem[largest].mIndex = T.mIndex; + move16(); + H->mElem[largest].mScore = T.mScore; + move32(); + + i = largest; + move16(); + + left = add(shl(i, 1), 1); + right = add(left, 1); + + if (LT_32(H->mElem[left].mScore, H->mElem[largest].mScore)) + { + largest = left; + move16(); + } + + if (LT_32(H->mElem[right].mScore, H->mElem[largest].mScore)) + { + largest = right; + move16(); + } + } + +} + +static Word16 tcx_arith_find_max_scale( /* Q15-e */ + const Word32 abs_spectrum[], /* i: absolute MDCT coefficients Q31-e */ + Word16 abs_spectrum_e, /* i: MDCT exponent Q0 */ + Word16 L_frame, /* i: number of spectral lines Q0 */ + const Word16 envelope[], /* i: scaled envelope Q15-e */ + Word16 envelope_e, /* i: scaled envelope exponent Q0 */ + const Word16 exps[], /* i: expfp(-(int)envelope[]/2) Q15 */ + Word16 deadzone, /* i: deadzone (0.5f = no deadzone) Q15 */ + Word16 *scale_e /* o: scale exponent Q0 */ +) +{ + Word16 i, k, q, scale, tmp, s; + Word32 p, L_tmp; + Heap heap = {{{0,0}},0}; /* silence a compiler warning */ + Word16 tmpi1, tmpi2; + const Word32 limit = -325614240l/*-9.70406052784f Q25*/; /* = ln(1/16384): log of smallest allowed probability */ + + + + /* Find the top most offending lines according to probability estimates */ + heap.mSize = kMaxNumHeapElems; + move16(); + + FOR (i = 0; i < heap.mSize; i++) + { + heap.mElem[i].mIndex = 0; + move16(); + heap.mElem[i].mScore = L_deposit_l(0); + } + + tmp = add(shl(heap.mSize, 1), 1); + FOR (; i < tmp; i++) + { + heap.mElem[i].mScore = L_deposit_h(0x7FFF); + } + + FOR (k = 0; k < L_frame; k++) + { + p = Mpy_32_16_1(abs_spectrum[k], envelope[k]); + + IF (GT_32(p, heap.mElem[0].mScore)) + { + heap.mElem[0].mScore = p; + move32(); + heap.mElem[0].mIndex = k; + move16(); + MinHeapify_i(&heap, 0); + } + } + + /* Make sure the scale is limited so that the offending lines don't cause probability underflow. */ + /* Also limit scale to avoiding saturation of the gain quantizer */ + /* scale = 1.0f/(float)sqrt(L_frame*0.5f); */ + tmp = 15-1; + move16(); + scale = ISqrt16(L_frame, &tmp); + *scale_e = tmp; + move16(); + + FOR (i = 0; i < heap.mSize; i++) + { + k = heap.mElem[i].mIndex; + move16(); + + /* Get approximate maximum allowed magnitude */ + /* q = (int)ceil(((limit - log(1.0f - (exps[k]/65536.0) * (exps[k]/65536.0))) / (-(int)envelope[k]/2/65536.0) - 1) / 2.0f); */ + L_tmp = L_sub(0x7FFFFFFF, L_mult(exps[k], exps[k])); + L_tmp = Mpy_32_16_1(BASOP_Util_Log2(L_tmp), 22713); /* Q25; 22713 -> 1/log2(e) */ + L_tmp = L_sub(limit, L_tmp); + tmp = negate(BASOP_Util_Divide3216_Scale(L_tmp, envelope[k], &s)); + s = sub(add(s, 6), sub(envelope_e, 1)); + L_tmp = L_shl(L_deposit_h(tmp), sub(s, 15+1)); /* Q16 */ + L_tmp = L_sub(L_tmp, 0x8000); + q = extract_h(L_add(L_tmp, 0xFFFF)); /* ceil */ + + /* Refinement: get the exact q */ + powfp_odd2(exps[k], q, &tmpi1, &tmpi2); + + IF (GE_16(sub(tmpi1, tmpi2), 2)) /* q may be too low */ + { + powfp_odd2(exps[k], add(q, 1), &tmpi1, &tmpi2); + + WHILE (GE_16(sub(tmpi1, tmpi2), 2)) + { + q = add(q, 1); + powfp_odd2(exps[k], add(q, 1), &tmpi1, &tmpi2); + } + } + ELSE /* q is too high */ + { + q = sub(q, 1); + powfp_odd2(exps[k], q, &tmpi1, &tmpi2); + + WHILE (LT_16(sub(tmpi1, tmpi2), 2)) + { + q = sub(q, 1); + powfp_odd2(exps[k], q, &tmpi1, &tmpi2); + } + } + + /* Find the largest scale so that the quantized magnitude is at most q */ + /* p = (q+0.99f-deadzone)/(abs_spectrum[k] + 0.000001f); */ + L_tmp = L_add(L_deposit_h(q), L_mult(sub(32440/*0.99f Q15*/, deadzone), 1)); /* Q16 */ + tmp = BASOP_Util_Divide3232_Scale(L_tmp, L_add(abs_spectrum[k], 1), &s); + s = sub(add(s, 15), abs_spectrum_e); + + k = norm_s(tmp); + tmp = shl(tmp, k); + s = sub(s, k); + + /* assert((int)(abs_spectrum[k] * p + deadzone) <= q); */ + + /* scale = min(scale, p); */ + IF (compMantExp16Unorm(tmp, s, scale, *scale_e) < 0) + { + scale = tmp; + move16(); + *scale_e = s; + move16(); + } + } + + + return scale; +} + +/* Returns: index of highest freq. nonzero line (-1 if all zeros) */ +static Word16 tcx_arith_find_kMax( + const Word32 abs_spectrum[], /* i: absolute MDCT coefficients Q31-e */ + Word16 abs_spectrum_e, /* i: MDCT exponent Q0 */ + Word16 L_frame, /* i: number of spectral lines Q0 */ + Word16 scale, /* i: scalar quantizer scale Q15-e */ + Word16 scale_e, /* i: scale exponent Q0 */ + Word16 deadzone, /* i: deadzone (0.5f = no deadzone) Q15 */ + const Word8 deadzone_flags[] /* i: line-wise deadzone control */ +) +{ + Word16 kMax; + Word32 tmp[2]; + + + move32(); + move32(); + tmp[0] = L_shr(L_mac(0x7FFFFFFF, deadzone, (Word16)0x8000), abs_spectrum_e); /* 1.0f - deadzone scaled to MDCT exponent */ + tmp[1] = L_shr(0x7FFFFFFF, abs_spectrum_e); /* 1.0f scaled to MDCT exponent */ + + FOR (kMax = sub(L_frame, 1); kMax >= 0; kMax--) + { + IF (GE_32(L_shl(Mpy_32_16_1(abs_spectrum[kMax], scale), scale_e), tmp[deadzone_flags[kMax]])) + { + BREAK; + } + } + + + return kMax; +} + +#define LOG2_E 23637/*1.44269504089f Q14*/ + +/* Returns: best scale Q15-e */ +static Word16 tcx_arith_rateloop( + const Word32 abs_spectrum[], /* i: absolute MDCT coefficients Q31-e */ + Word16 abs_spectrum_e, /* i: MDCT exponent Q0 */ + Word16 L_frame, /* i: number of spectral lines Q0 */ + const Word16 envelope[], /* i: scaled envelope Q15-e */ + Word16 envelope_e, /* i: scaled envelope exponent Q0 */ + const Word16 exps[], /* i: expfp(-(int)envelope[]/2) Q15 */ + Word16 target_bits, /* i: target bit budget Q0 */ + Word16 deadzone, /* i: deadzone (0.5f = no deadzone) Q15 */ + const Word8 deadzone_flags[], /* i: line-wise deadzone control Q0 */ + Word16 *target_bits_fac, /* i/o: scale estimator compensation Q14 */ + Word16 *scale_e /* o: scale exponent Q0 */ +) +{ + Word16 k, kMax, q; + Word16 s, adjust; + Word16 fixed_bits[2][N_MAX_ARI]; + Word32 max_complexity; + Word16 iter; /* rate loop iteration counter */ + Word16 scale; /* SQ scale factor to try next */ + Word16 scale_best; /* best SQ scale factor */ + Word16 scale_max; /* maximum allowable scale factor */ + Word16 lob; /* lower bound of SQ scale factor */ + Word16 hib; /* upper bound of SQ scale factor */ + Word16 flag; /* 1:bit surplus, -1:bit deficit, 0:unknown */ + Word32 complexity; /* cumulative rate loop complexity */ + Word32 bits; /* number of bits (approximate) Q9 */ + Word32 L_tmp; + Word16 tmp, tmp3; + Word32 tmp2; + + + + scale = tcx_arith_estimate_scale(abs_spectrum, abs_spectrum_e, L_frame, envelope, envelope_e, &tmp); + scale = mult_r(scale, *target_bits_fac); + tmp = add(tmp, 1); + + scale_max = tcx_arith_find_max_scale(abs_spectrum, abs_spectrum_e, L_frame, envelope, envelope_e, exps, deadzone, scale_e); + + BASOP_SATURATE_WARNING_OFF; + scale = shl(scale, sub(tmp, *scale_e)); + BASOP_SATURATE_WARNING_ON; + scale = s_min(scale, scale_max); + + scale_best = scale; + move16(); + lob = 0; + move16(); + hib = 0; + move16(); + flag = 0; + move16(); + complexity = L_deposit_l(0); + bits = L_deposit_l(0); + iter = 0; + move16(); + + max_complexity = L_mult0(96, L_frame); + + /* Precalculate fixed bit costs */ + FOR (k = 0; k < L_frame; k++) + { + /* fixed_bits[0][k] = -log2f(1 - exps[k] / 65536.0f); */ + L_tmp = L_mac(0x7FFFFFFF, exps[k], (Word16)0x8000); /* Q31 */ + L_tmp = L_negate(BASOP_Util_Log2(L_tmp)); /* Q25 */ + fixed_bits[0][k] = round_fx(L_tmp); /* Q9 */ + + /* fixed_bits[1][k] = 1 - s*0.5f*LOG2_E - log2f(1 - (exps[k]/65536.0f) * (exps[k]/65536.0f)); */ + L_tmp = L_msu(0x7FFFFFFF, exps[k], exps[k]); /* Q31 */ + L_tmp = BASOP_Util_Log2(L_tmp); /* Q25 */ + L_tmp = L_sub(1<<25, L_tmp); + L_tmp = L_sub(L_tmp, L_shl(L_mult0(mult_r(envelope[k], LOG2_E), 1<<10), envelope_e)); + fixed_bits[1][k] = round_fx(L_tmp); /* Q9 */ + } + + tmp2 = L_msu0(L_sub(max_complexity, 48), L_frame, 11); + WHILE (LT_32(complexity, tmp2)) + { + kMax = tcx_arith_find_kMax( + abs_spectrum, + abs_spectrum_e, + L_frame, + scale, *scale_e, + deadzone, + deadzone_flags + ); + complexity = L_mac0(L_mac0(L_add(complexity, 16+2), sub(L_frame, kMax), 5), kMax, 2); + + bits = /*estimator_undershoot * kMax +*/ L_deposit_l(1<<9); /* Q9 */ + + L_tmp = L_mult(deadzone, 1); /* Q16 */ + tmp = add(sub(abs_spectrum_e, 15), *scale_e); + tmp3 = add(2+9, envelope_e); + FOR (k = 0; k <= kMax; k++) + { + q = extract_h(L_add(L_shl(Mpy_32_16_1(abs_spectrum[k], scale), tmp), L_tmp)); + bits = L_mac0(bits, fixed_bits[s_min(1,q)][k], 1); /* Q9 */ + bits = L_mac0(bits, round_fx(L_shl(L_mult0(mult_r(envelope[k], LOG2_E), q), tmp3)), 1); + } + complexity = L_mac0(L_add(complexity, 32), 6, kMax); + + IF (iter == 0) /* First rate loop iteration */ + { + IF (LT_16(scale, scale_max)) /* Only update in non-degenerate case */ + { + /* Update estimator temporal compensation factor */ + tmp = BASOP_Util_Divide3232_Scale(L_mult0(target_bits, 1<<9), bits, &s); + BASOP_SATURATE_WARNING_OFF; + tmp = shl(mult_r(*target_bits_fac, tmp), s); + BASOP_SATURATE_WARNING_ON; + tmp = s_min(tmp, 20480/*1.25f Q14*/); + tmp = s_max(tmp, 12288/*0.75f Q14*/); + *target_bits_fac = tmp; + move16(); + } + } + + IF (LE_32(bits, L_mult0(target_bits, 1<<9))) /* Bits leftover => scale is too small */ + { + test(); + IF (flag <= 0 || GE_16(scale, scale_best)) + { + scale_best = scale; + move16(); + flag = 1; + move16(); + } + + lob = scale; + move16(); + + IF (hib > 0) /* Bisection search */ + { + scale = add(shr(lob, 1), shr(hib, 1)); + } + ELSE /* Initial scale adaptation */ + { + /* adjust = 1.25f * target_bits / (float)bits; */ + tmp = BASOP_Util_Divide3232_Scale(L_mult0(target_bits, 0x280), bits, &s); + BASOP_SATURATE_WARNING_OFF; /* adjust limited to <= 2.0, scale to <= scale_max */ + adjust = shl(tmp, sub(s, 1)); /* Q14 */ + scale = shl(mult_r(scale, adjust), 1); + BASOP_SATURATE_WARNING_ON; + scale = s_min(scale, scale_max); + } + } + ELSE /* Ran out of bits => scale is too large */ + { + hib = scale; + move16(); + + IF (lob > 0) /* Bisection search */ + { + scale = add(shr(lob, 1), shr(hib, 1)); + } + ELSE { /* Initial scale adaptation */ + /* adjust = 0.8f * target_bits / (float)bits; */ + tmp = BASOP_Util_Divide3232_Scale(L_mult0(target_bits, 0x19A), bits, &s); + adjust = shl(tmp, s); /* Q15 */ + adjust = s_max(adjust, 16384/*0.5f Q15*/); + scale = mult_r(scale, adjust); + } + + IF (flag <= 0) + { + scale_best = scale; + move16(); + flag = 0; + move16(); + } + } + iter = add(iter, 1); + } + + + return scale_best; +} + +/* Returns: number of bits consumed */ +static Word16 tcx_arith_encode( + Word16 q_abs_spectrum[], /* i/o: scalar quantized absolute spectrum Q0 */ + const Word16 signs[], /* i: signs */ + Word16 kMax, /* i: number of nonzero spectral lines to code Q0 */ + Word16 L_frame, /* i: nominal number of spectral lines Q0 */ + const Word16 exps[], /* i: expfp(-(int)envelope[]/2) Q15 */ + Word16 target_bits, /* i: target bit budget Q0 */ + Word16 prm[] /* o: bit-stream Q0 */ +) +{ + TastatEnc as, as_lastgood; + Word16 bp, bp_lastgood; + Word16 k; + Word16 kEncoded; + Word16 tmpi1, tmpi2; + + + + /* Final coding */ + ari_start_encoding_14bits(&as); + ari_copy_states(&as, &as_lastgood); + bp = 0; + move16(); + bp_lastgood = 0; + move16(); + kEncoded = kMax; + move16(); + + FOR (k = 0; k <= kMax; k++) + { + IF (q_abs_spectrum[k] == 0) + { + assert(exps[k] >= 2); + bp = ari_encode_14bits_range(prm, bp, target_bits, &as, shr(exps[k], 1), 16384); + } + ELSE /* q_abs_spectrum[k] != 0 */ + { + powfp_odd2(exps[k], q_abs_spectrum[k], &tmpi1, &tmpi2); + + WHILE (LT_16(tmpi1, add(tmpi2, 2))) + { + q_abs_spectrum[k] = sub(q_abs_spectrum[k], 1); + move16(); + powfp_odd2(exps[k], q_abs_spectrum[k], &tmpi1, &tmpi2); + } + + bp = ari_encode_14bits_range(prm, bp, target_bits, &as, shr(tmpi2, 1), shr(tmpi1, 1)); + bp = ari_encode_14bits_sign(prm, bp, target_bits, &as, signs[k]); + } + /* Check bit budget status */ + IF (ari_encode_overflow(&as)) /* no bits left */ + { + /* printf("\noverflow at %d\n\n", k); */ + + IF (GT_16(q_abs_spectrum[k], 1)) /* Lower magnitude is still > 0 */ + { + /* Restore state */ + ari_copy_states(&as_lastgood, &as); + bp = bp_lastgood; + move16(); + + /* Quantize to lower magnitude */ + q_abs_spectrum[k] = sub(q_abs_spectrum[k], 1); + move16(); + + /* Retry encoding */ + powfp_odd2(exps[k], q_abs_spectrum[k], &tmpi1, &tmpi2); + + bp = ari_encode_14bits_range(prm, bp, target_bits, &as, shr(tmpi2, 1), shr(tmpi1, 1)); + bp = ari_encode_14bits_sign(prm, bp, target_bits, &as, signs[k]); + + IF (!ari_encode_overflow(&as)) /* Success */ + { + ari_copy_states(&as, &as_lastgood); + bp_lastgood = bp; + move16(); + kEncoded = k; + move16(); + + set16_fx(q_abs_spectrum+k+1, 0, sub(kMax, k)); + BREAK; + } + } + ari_copy_states(&as_lastgood, &as); + bp = bp_lastgood; + move16(); + kEncoded = sub(k, 1); + + set16_fx(q_abs_spectrum+k, 0, sub(kMax, kEncoded)); + BREAK; + } + ELSE + { + ari_copy_states(&as, &as_lastgood); + bp_lastgood = bp; + move16(); + } + } + + /* Send zeros until L_frame */ + tmpi1 = add(kEncoded, 1); + kEncoded = sub(L_frame, 1); + FOR (k = tmpi1; k < L_frame; k++) + { + assert(exps[k] >= 1); + + bp = ari_encode_14bits_range(prm, bp, target_bits, &as, shr(exps[k],1), 16384); + /* Check bit budget status */ + IF (ari_encode_overflow(&as)) /* no bits left */ + { + ari_copy_states(&as_lastgood, &as); + bp = bp_lastgood; + move16(); + kEncoded = sub(k, 1); + BREAK; + } + ELSE + { + ari_copy_states(&as, &as_lastgood); + bp_lastgood = bp; + move16(); + } + } + + IF (EQ_16(kEncoded, sub(L_frame, 1))) /* RESQ bits possibly available */ + { + /* Limit target bits to actually needed bits */ + target_bits = add(add(bp, 16), extract_l(as.vobf)); + } + return ari_done_cbr_encoding_14bits(prm, bp, target_bits, &as); +} + +void tcx_arith_encode_envelope( + Word32 spectrum[], /* i/o: MDCT coefficients Q31-e */ + Word16 *spectrum_e, /* i/o: MDCT exponent Q0 */ + Word16 signs[], /* o: signs (spectrum[.]<0) Q0 */ + Word16 L_frame, /* i: frame or MDCT length Q0 */ + Word16 L_spec, /* i: frame or MDCT length Q0 */ + Encoder_State_fx *st, /* i/o: coder state */ + const Word16 A_ind[], /* i: quantised LPC coefficients Q12 */ + Word16 target_bits, /* i: number of available bits Q0 */ + Word16 prm[], /* o: bitstream parameters Q0 */ + Word8 use_hm, /* i: use HM in current frame? */ + Word16 prm_hm[], /* o: HM parameter area Q0 */ + Word16 tcxltp_pitch, /* i: TCX LTP pitch in FD, -1 if n/a Q0*/ + Word16 *arith_bits, /* o: bits used for ari. coding Q0 */ + Word16 *signaling_bits, /* o: bits used for signaling Q0 */ + Word16 *nf_seed /* o: noise filling seed Q0 */ + ,Word16 low_complexity /* i: low-complexity flag Q0 */ +) +{ + Word32 env[N_MAX_ARI]; /* unscaled envelope (Q16) */ + Word16 *envelope; /* scaled envelope (Q15-e) */ + Word16 envelope_e; + Word16 exponents[N_MAX_ARI]; /* Q15 */ + Word16 L_spec_core; + Word16 *q_spectrum; + TCX_config *tcx_cfg; + Word16 scale, scale_e; + Word16 k, kMax; + Word16 deadzone; + const Word8 *deadzone_flags; + Word16 gamma_w, gamma_uw; + Word16 hm_bits; + Word32 L_tmp, L_tmp2; + Word16 tmp; + + + assert(L_spec <= N_MAX_ARI); + + + tcx_cfg = &st->tcx_cfg; + deadzone = tcx_cfg->sq_rounding; + move16(); + deadzone_flags = st->memQuantZeros; + *signaling_bits = 0; + move16(); + + assert(st->enableTcxLpc); + gamma_w = 32767/*1.0f Q15*/; + move16(); + gamma_uw = st->inv_gamma; + move16(); + + tcx_arith_render_envelope( + A_ind, + L_frame, + L_spec, + tcx_cfg->preemph_fac, + gamma_w, + gamma_uw, + env + ); + + FOR (k = 0; k < L_spec; k++) + { + signs[k] = extract_l(L_lshr(spectrum[k], 31)); + if (spectrum[k] < 0) + { + spectrum[k] = L_abs(spectrum[k]); + move32(); + } + } + + IF (use_hm != 0) + { + tcx_hm_analyse( + spectrum, + spectrum_e, + L_spec, + env, + target_bits, + tcx_cfg->coder_type, + prm_hm, + tcxltp_pitch, + st->tcxltp_gain, + &hm_bits + ); + + target_bits = sub(target_bits, hm_bits); + *signaling_bits = add(*signaling_bits, hm_bits); + move16(); + } + ELSE + { + prm_hm[0] = 0; /* just to be sure */ move16(); + hm_bits = 0; + move16(); + } + + L_spec_core = L_spec; + move16(); + if (st->igf) + { + L_spec_core = s_min(L_spec_core, st->hIGFEnc.infoStartLine); + } + envelope = (Word16*)env; + + tcx_arith_scale_envelope( + L_spec, + L_spec_core, + env, + target_bits, + low_complexity, + envelope, + &envelope_e + ); + + tmp = sub(envelope_e, 1+15); + FOR (k = 0; k < L_spec; k++) + { + exponents[k] = round_fx(expfp(envelope[k], tmp)); + } + + scale = tcx_arith_rateloop( + spectrum, + *spectrum_e, + L_spec, + envelope, + envelope_e, + exponents, + target_bits, + deadzone, + deadzone_flags, + &st->LPDmem.tcx_target_bits_fac, + &scale_e + ); + + /* Final quantization */ + kMax = tcx_arith_find_kMax( + spectrum, + *spectrum_e, + L_spec, + scale, scale_e, + deadzone, + deadzone_flags + ); + + q_spectrum = (Word16*)env; /* Reuse buffer */ + + L_tmp = L_mult(deadzone, 1); /* Q16 */ + tmp = add(sub(*spectrum_e, 15), scale_e); + FOR (k = 0; k <= kMax; k++) + { + /* quantise using dead-zone */ + q_spectrum[k] = extract_h(L_add(L_shl(Mpy_32_16_1(spectrum[k], scale), tmp), L_tmp)); + } + + /* Final encoding */ + *arith_bits = tcx_arith_encode( + q_spectrum, + signs, + kMax, + L_spec, + exponents, + target_bits, + prm + ); + + /* Multiply back the signs */ + L_tmp2 = L_deposit_l(0); + FOR (k = 0; k <= kMax; k++) + { + L_tmp2 = L_macNs(L_tmp2, q_spectrum[k], k); + + if (signs[k] != 0) L_tmp = L_mult(q_spectrum[k], -(1<< (30 - SPEC_EXP_DEC))); + if (signs[k] == 0) L_tmp = L_mult(q_spectrum[k], 1 << (30 - SPEC_EXP_DEC)); + spectrum[k] = L_tmp; + move32(); + } + *spectrum_e = SPEC_EXP_DEC; + move16(); + set32_fx(spectrum+k, 0, sub(s_max(L_frame, L_spec), k)); + + /* noise filling seed */ + *nf_seed = extract_l(L_tmp2); + +} + diff --git a/lib_enc/avq_cod_fx.c b/lib_enc/avq_cod_fx.c new file mode 100644 index 0000000..5b968bd --- /dev/null +++ b/lib_enc/avq_cod_fx.c @@ -0,0 +1,460 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* +* Function AVQ_cod() * +* * +* Split algevraic vector quantizer (AVQ) base on RE8 latice * +*-------------------------------------------------------------------*/ + +void AVQ_cod_fx( /* o: comfort noise gain factor */ + const Word16 xri[], /* i: vector to quantize */ + Word16 xriq[], /* o: quantized normalized vector (assuming the bit budget is enough) */ + const Word16 NB_BITS, /* i: number of allocated bits */ + const Word16 Nsv /* i: number of subvectors (lg=Nsv*8) */ + ,const Word16 Q_in_ref /* i: Scaling input */ +) +{ + Word16 i, l, iter, c[8]; + Word16 gain_inv, tmp, nbits, nbits_max, fac, offset; + Word16 ebits[NSV_MAX], e_ebits, f_ebits, e_tmp,f_tmp, tmp16, l_8; + Word32 Lener, Ltmp, Lgain, x1[8]; + Word16 tot_est_bits, Q_in; + + Q_in = sub(Q_in_ref,1); + move16(); + + /* find energy of each subvector in log domain (scaled for bits estimation) */ + /* if the number of allocated bits is high, recompute the energy of sub vectors with a different scaling factor (applicable only in BASOP code) */ + DO + { + Q_in = add(Q_in,1); + tot_est_bits = 0; + move16(); + FOR (l=0; l= 0 */ + FOR (i=0; i<8; i++) + { + Lener = L_mac(Lener, xri[l*8+i], xri[l*8+i]); + } + /* estimated bit consumption when gain=1 */ + /* ebits[l] = 5.0 * FAC_LOG2 * (Word16)log10(ener * 0.5) */ + e_ebits = norm_l(Lener); + f_ebits = Log2_norm_lc(L_shl(Lener, e_ebits)); + e_ebits = sub(30-2, e_ebits); /* -2 = *0.25 */ + e_ebits = sub(e_ebits, shl(Q_in,1)); + + Ltmp = L_deposit_h(e_ebits); + Ltmp = L_mac(Ltmp, f_ebits, 1); + Ltmp = L_add(L_shl(Ltmp,6), L_shl(Ltmp,4)); /* Mult by 5.0 and then by 16 (To go to Q4). Do it using Mult by 80 (which is 64+16) */ + ebits[l] = round_fx(Ltmp); /*Q4*/ + tot_est_bits = add(tot_est_bits, shr(ebits[l],4)); + } + test(); + test(); + } + WHILE( (LE_16(Q_in, Q_in_ref))&&LE_16(tot_est_bits,mult(26214,NB_BITS))&>_16(tot_est_bits,600)); /* limited to 1 possible iteration */ + + /*----------------------------------------------------------------* + * subvector energy worst case: + * - typically, it's a tone with maximum of amplitude (RMS=23170). + * - fft length max = 1024 (N/2 is 512) + * log10(energy) = log10(23710*23710*1024*(N/2)) = 14.45 + * ebits --> 5.0*FAC_LOG2*14.45 = 240 bits + *----------------------------------------------------------------*/ + + /* estimate gain according to number of bits allowed */ + /* start at the middle (offset range = 0 to 255.75) Q6 */ + fac = 2048; + move16(); + offset = 0; + move16(); + + Ltmp = L_mult(31130, sub(NB_BITS, Nsv)); /* (1810 - 8 - 1152/8)*.95*/ + nbits_max = round_fx(L_shl(Ltmp, 4)); + + /* tree search with 10 iterations : offset with step of 0.25 bits (0.3 dB) */ + FOR (iter=0; iter<10; iter++) + { + offset = add(fac, offset); + /* calculate the required number of bits */ + nbits = 0; + move16(); + FOR (l=0; l 0 ) + { + j = pos_max; + move16(); + j = s_max(pos,j); + + /* compute (number of bits -1) to describe Q #nq */ + IF(GE_16(nq[pos],2)) + { + overflow = sub(i_mult2(nq[pos],5),1); + } + ELSE + { + overflow = 0; + move16(); + } + + /* check for overflow and compute number of bits-1 (n) */ + IF( GT_16(add(bits,add(overflow,j)),*nb_bits)) + { + /* if budget overflow */ + pos_tmp = add(shl(pos,3),8); /*(pos*8)+8*/ + FOR( j=pos*8; j 0 ) + { + /* write the unary code */ + FOR( ; j > 16; j -= 16 ) + { + push_indice_fx( st_fx, nq_ind, 65535, 16 ); + bits = sub(bits,16); + } + + IF ( j > 0 ) + { + push_indice_fx( st_fx, nq_ind, extract_l(L_sub(L_shl(1L,j),1L)), j ); + bits = sub(bits,j); + } + } + IF ( !overflow ) + { + /* write the stop bit */ + push_indice_fx( st_fx, nq_ind, 0, 1 ); + bits = sub(bits,1); + } + + /* write codebook indices (rank I and event. Voronoi index kv) */ + IF( nq[i] == 0 ) /* Q0 */ + { + /* nothing to write */ + } + ELSE IF( LT_16(nq[i],5)) /* Q2, Q3, Q4 */ + { + push_indice_fx( st_fx, i_ind, I[i], shl(nq[i],2) ); + bits = sub(bits, shl(nq[i],2)); + } + ELSE IF( s_and(nq[i],1) == 0 ) /* Q4 + Voronoi extensions r=1,2,3,... */ + { + push_indice_fx( st_fx, i_ind, I[i], 4*4 ); + bits = sub(bits,4*4); + pos = sub(shr(nq[i],1), 2); /* Voronoi order determination */ + move16(); /*ptr init*/ + FOR( j=0; j<8; j++ ) + { + push_indice_fx( st_fx, kv_ind, kv[i*8+j], pos ); + } + + bits = sub(bits,shl(pos,3)); + } + ELSE /* Q3 + Voronoi extensions r=1,2,3,... */ + { + push_indice_fx( st_fx, i_ind, I[i], 4*3 ); + bits = sub(bits, 4*3); + + pos = sub(shr(nq[i],1), 1); /* Voronoi order determination */ + move16(); /* ptr init */ + FOR( j=0; j<8; j++ ) + { + push_indice_fx( st_fx, kv_ind, kv[i*8+j], pos ); + } + + bits = sub(bits,shl(pos,3)); + } + } + } /* for */ + + *nb_bits = bits; + move16(); + + FOR( i=0; i 16Q15*/ move32(); + } + re8_PPV_fx(x1, c); /*x1:8Q15, c:15Q0*/ + re8_cod_fx(c, &nq, &I16, kv); + I = UL_deposit_l(I16); + + FOR (i=0; i<8; i++) + { + nvecq[l*8+i] = shl(c[i],10); /*15Q0->5Q10*/ move16(); + } + + indx[l] = nq; /* index[0..Nsv-1] = quantizer number (0,2,3,4...) */ move16(); + nk = 0; + move16(); + n = nq; + move16(); + + IF (GT_16(nq,4)) + { + nk = shr(sub(nq,3),1); /*nk = (nq-3)>>1;*/ + n = sub(nq,shl(nk,1)); /*n = nq - nk*2; */ + } + + /* write n groups of 4-bit for base codebook index (I) */ + FOR ( ; n > 0; n-- ) + { + indx[pos++] = s_and(extract_l(I),0x000F); + move16(); + I = L_shr(I,4); + } + + /* write n groups of 4-bit for Voronoi index (k[]) */ + FOR ( ; nk > 0; nk--) + { + ival = 0; + move16(); + FOR (i=0; i<8; i++) + { + ival = shl(ival,1); /*ival <<= 1;*/ + ival = add(ival,s_and(kv[i],0x0001)); /*ival += (kv[i] & 0x01);*/ + kv[i] = shr(kv[i],1); /*kv[i] >>= 1;*/ move16(); + } + indx[pos++] = s_and(ival,0x000F); + move16(); + ival = shr(ival,4); + indx[pos++] = s_and(ival,0x000F); + move16(); + } + } + + + return; +} diff --git a/lib_enc/bass_psfilter_enc.c b/lib_enc/bass_psfilter_enc.c new file mode 100644 index 0000000..7771ed7 --- /dev/null +++ b/lib_enc/bass_psfilter_enc.c @@ -0,0 +1,389 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + + +#include +#include +#include +#include "options.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "stl.h" + + + +Word16 bass_pf_enc( + Word16 *orig, /* (i) : 12.8kHz original signal Q0 */ + Word16 *syn, /* (i) : 12.8kHz synthesis to postfilter Q0 */ + Word16 *T_sf, /* (i) : Pitch period for all subframes (T_sf[16]) Q0 */ + Word16 *gainT_sf, /* (i) : Pitch gain for all subframes (gainT_sf[16]) Q14 */ + Word16 l_frame, /* (i) : frame length (should be multiple of l_subfr) Q0 */ + Word16 l_subfr, /* (i) : sub-frame length (60/64) Q0 */ + Word16 *gain_factor_param, /* (o) : quantized gain factor Q0 */ + Word16 mode, /* (i) : coding mode of adapt bpf */ + struct MEM_BPF *mem_bpf /* i/o : memory state */ +) +{ + Word16 i, j, sf, i_subfr, T, lg, l_filt; + Word16 gain, d, tmp16, hr, s1, s2, s2_old, s3, s4, st, st2, st3; + Word32 nrg, tmp, nrg1, nrg2, n, snr, lp_error, tmp32; + Word16 noise_buf[L_FILT16k+2*L_SUBFR], *noise, *noise_in; + Word16 error_buf[L_FILT16k+2*L_SUBFR], *error, *error_in; + Word32 cross_n_d, nrg_n; + const Word16 *pFilt; + Word32 ener2; + + + IF (NE_16(l_frame, L_FRAME16k)) + { + pFilt = filt_lp; + l_filt = L_FILT; + move16(); + } + ELSE + { + pFilt = filt_lp_16kHz; + l_filt = L_FILT16k; + move16(); + } + + noise = noise_buf + l_filt; + noise_in = noise_buf + shl(l_filt, 1); + error = error_buf; + error_in = error_buf + l_filt; + + sf = 0; + move16(); + snr = L_deposit_l(0); + nrg_n = L_deposit_l(0); + cross_n_d = L_deposit_l(0); + lp_error = L_shl(mem_bpf->lp_error, 0); + s2_old = mem_bpf->noise_shift_old; + move16(); + s3 = s4 = 0; /* initialization of s3 and s4 to suppress compiler warnings; + s3 and s4 get initialized for i_subfr == 0 */ + + nrg1 = nrg2 = 0; /* initialization fo nrg1 and nrg2 to suppress compiler warnings; + nrg1 and nrg1 get initialized for i_subfr == 0 */ + + FOR (i_subfr = 0; i_subfr < l_frame; i_subfr += l_subfr) + { + T = T_sf[sf]; + move16(); + + lg = sub(sub(l_frame, T), i_subfr); + if (lg < 0) + { + lg = 0; + move16(); + } + if (GT_16(lg, l_subfr)) + { + lg = l_subfr; + move16(); + } + + IF (gainT_sf[sf] > 0) + { + /* get headroom for used part of syn */ + tmp16 = s_max(add(lg, shl(T, 1)), add(l_subfr, T)); + hr = getScaleFactor16(syn + sub(i_subfr, T), tmp16); + s1 = sub(hr, 3); + + tmp = L_deposit_l(1); + nrg = L_deposit_l(1); + + IF (lg > 0) + { + FOR (i = 0; i < lg; i++) + { + tmp32 = L_mult(syn[i+i_subfr-T], 0x4000); + tmp32 = L_mac(tmp32, syn[i+i_subfr+T], 0x4000); + tmp16 = round_fx(L_shl(tmp32, s1)); /* Q0+s1 */ + + tmp = L_mac0(tmp, shl(syn[i+i_subfr], s1), tmp16); /* Q0+2*s1 */ + nrg = L_mac0(nrg, tmp16, tmp16); /* Q0+2*s1 */ + } + } + + IF (LT_16(lg, l_subfr)) + { + FOR (i = lg; i < l_subfr; i++) + { + tmp16 = shl(syn[i+i_subfr-T], s1); /* Q0+s1 */ + tmp = L_mac0(tmp, shl(syn[i+i_subfr], s1), tmp16); /* Q0+2*s1 */ + nrg = L_mac0(nrg, tmp16, tmp16); /* Q0+2*s1 */ + } + } + + /* gain = tmp/nrg; */ + gain = BASOP_Util_Divide3232_Scale(tmp, nrg, &tmp16); + BASOP_SATURATE_WARNING_OFF; + gain = shl(gain, tmp16); /* Q15 */ + BASOP_SATURATE_WARNING_ON; + + if (gain < 0) + { + gain = 0; + move16(); + } + + st = sub(norm_l(lp_error), 3); + test(); + if ((LT_16(st, s1))&&(lp_error!=0)) + { + s1 = st; + move16(); + } + + ener2 = L_deposit_l(0); + + IF (lg > 0) + { + FOR (i = 0; i < lg; i++) + { + tmp32 = L_msu0(0, gain, syn[i+i_subfr-T]); + tmp32 = L_msu0(tmp32, gain, syn[i+i_subfr+T]); + tmp16 = mac_r(tmp32, gain, syn[i+i_subfr]); /* Q0 */ + + lp_error = Mpy_32_16_1(lp_error, 29491/*0.9f Q15*/); + lp_error = L_mac(lp_error, tmp16, 0x1000); /* Q13 */ + + tmp16 = round_fx(L_shl(lp_error, s1)); /* Q0+s1-3 */ + ener2 = L_mac0(ener2, tmp16, tmp16); /* Q0+(s1-3)*2 */ + } + } + + IF (LT_16(lg, l_subfr)) + { + FOR (i = lg; i < l_subfr; i++) + { + tmp32 = L_mult0(gain, syn[i+i_subfr]); + tmp32 = L_msu0(tmp32, gain, syn[i+i_subfr-T]); /* Q0 */ + tmp16 = round_fx(tmp32); + + lp_error = Mpy_32_16_1(lp_error, 29491/*0.9f Q15*/); + lp_error = L_mac(lp_error, tmp16, 0x1000); /* Q13 */ + + tmp16 = round_fx(L_shl(lp_error, s1)); /* Q0+s1-3 */ + ener2 = L_mac0(ener2, tmp16, tmp16); /* Q0+(s1-3)*2 */ + } + } + + st = shl(sub(s1, 3), 1); + + IF (ener2 > 0) + { + ener2 = L_shr(BASOP_Util_Log2(ener2), 9); /* 15Q16 */ + ener2 = L_add(ener2, L_deposit_h(sub(31, st))); + } + ELSE + { + ener2 = 0xFFF95B2C; /* log2(0.01) (15Q16) */ move32(); + } + + mem_bpf->lp_error_ener = L_add(Mpy_32_16_1(L_sub(mem_bpf->lp_error_ener, ener2), 32440/*0.99f Q15*/), ener2); /* 15Q16 */ + + st = add(st, 6); + ener2 = L_sub(mem_bpf->lp_error_ener, L_deposit_h(sub(31, st))); + IF (ener2 >= 0) + { + tmp16 = add(extract_h(ener2), 1); + ener2 = L_sub(ener2, L_deposit_h(tmp16)); + tmp = L_shr(tmp, tmp16); + nrg = L_shr(nrg, tmp16); + } + ener2 = BASOP_Util_InvLog2(L_shl(ener2, 9)); /* Q0+2*s1 */ + + tmp32 = L_add(L_shr(nrg, 1), L_shr(ener2, 1)); + if (tmp32 == 0) tmp32 = L_deposit_l(1); + tmp16 = BASOP_Util_Divide3232_Scale(tmp, tmp32, &st); + BASOP_SATURATE_WARNING_OFF; + tmp16 = shl(tmp16, sub(st, 2)); /* Q15 */ + + if (GT_16(tmp16, 16384/*0.5f Q15*/)) + { + tmp16 = 16384/*0.5f Q15*/; + move16(); + } + if (tmp16 < 0) + { + tmp16 = 0; + move16(); + } + BASOP_SATURATE_WARNING_ON; + + s2 = hr; + move16(); + + IF (lg > 0) + { + FOR (i = 0; i < lg; i++) + { + tmp32 = L_msu0(0, tmp16, syn[i+i_subfr-T]); + tmp32 = L_msu0(tmp32, tmp16, syn[i+i_subfr+T]); + tmp32 = L_mac(tmp32, tmp16, syn[i+i_subfr]); + noise_in[i] = round_fx(L_shl(tmp32, s2)); /* Q0+s2 */ + + error_in[i] = sub(orig[i+i_subfr], syn[i+i_subfr]); /*Q0*/ move16(); + } + } + + IF (LT_16(lg, l_subfr)) + { + FOR (i = lg; i < l_subfr; i++) + { + tmp32 = L_mult0(tmp16, syn[i+i_subfr]); + tmp32 = L_msu0(tmp32, tmp16, syn[i+i_subfr-T]); + noise_in[i] = round_fx(L_shl(tmp32, s2)); /* Q0+s2 */ + + error_in[i] = sub(orig[i+i_subfr], syn[i+i_subfr]); /*Q0*/ move16(); + } + } + } + ELSE + { + set16_fx(noise_in, 0, l_subfr); + set16_fx(error_in, 0, l_subfr); + s2 = s2_old; + } + + tmp16 = shl(l_filt, 1); + + /* copy history buffers (rescale noise history to new exponent) */ + st = sub(s2, s2_old); + FOR (i = 0; i < tmp16; i++) + { + noise_buf[i] = shl(mem_bpf->noise_buf[i], st); + move16(); + } + Copy(noise_buf+l_subfr, mem_bpf->noise_buf, tmp16); + s2_old = s2; + move16(); + + Copy(mem_bpf->error_buf, error_buf, l_filt); + Copy(error_buf+l_subfr, mem_bpf->error_buf, l_filt); + + /* get noise shift */ + st = getScaleFactor16(noise-l_filt, add(l_subfr, shl(l_filt, 1))); + st = add(sub(st, 3), s2); + if (i_subfr == 0) + { + s3 = st; + move16(); + } + tmp16 = sub(st, s3); + IF (tmp16 < 0) + { + nrg_n = L_shl(nrg_n, s_max(-15, shl(tmp16, 1))); + cross_n_d = L_shl(cross_n_d, tmp16); + s3 = st; + move16(); + } + + /* get error shift */ + st = getScaleFactor16(error, l_subfr); + st = sub(st, 3); + if (i_subfr == 0) + { + s4 = st; + move16(); + } + tmp16 = sub(st, s4); + IF (tmp16 < 0) + { + cross_n_d = L_shl(cross_n_d, tmp16); + nrg1 = L_shl(nrg1, shl(tmp16, 1)); + nrg2 = L_shl(nrg2, shl(tmp16, 1)); + s4 = st; + move16(); + } + + nrg1 = L_deposit_l(1); + nrg2 = L_deposit_l(1); + + /* substract from voiced speech low-pass filtered noise */ + st = sub(s_min(s3, s4), 1); + st2 = sub(s3, s2); + st3 = sub(st,s2); + FOR (i = 0; i < l_subfr; i++) + { + n = L_mult(pFilt[0], noise[i]); /* Q16+s2 */ + + FOR (j = 1; j <= l_filt; j++) + { + n = L_mac(n, pFilt[j], noise[i-j]); + n = L_mac(n, pFilt[j], noise[i+j]); + } + + /*for optimal g*/ + tmp16 = round_fx(L_shl(n, st2)); /* Q0+s3 */ + d = shl(error[i], s4); /* Q0+s4 */ + nrg_n = L_mac0(nrg_n, tmp16, tmp16); /* Q0+2*s3 */ + cross_n_d = L_mac0(cross_n_d, tmp16, d); /* Q0+s3+s4 */ + + /*for evaluating SNR*/ + tmp16 = round_fx(L_shl(n, st3)); /* Q0+st */ + tmp16 = add(tmp16, shl(error[i], st)); /* Q0+st */ + nrg1 = L_mac0(nrg1, tmp16, tmp16); /* Q0+2*st */ + nrg2 = L_mac0(nrg2, d, d); /* Q0+2*s4 */ + } + + /*SegSNR*/ + snr = L_add(snr, L_shr(L_sub(BASOP_Util_Log2(nrg2), BASOP_Util_Log2(nrg1)), 9)); /* 15Q16 */ + snr = L_add(snr, L_deposit_h(shl(sub(st, s4), 1))); + + sf = add(sf, 1); + } + + if (nrg_n == 0) + { + nrg_n = L_deposit_l(1); + } + + /*Compute and quantize optimal gain*/ + /* optimal gain = -/ */ + *gain_factor_param = 2; + move16(); + IF (EQ_16(mode, 2)) + { + /* *gain_factor_param = (int)(-2.f*(cross_n_d/nrg_n)+0.5f); */ + tmp16 = BASOP_Util_Divide3232_Scale(cross_n_d, nrg_n, &st); /* Q15-st-s3+s4 */ + BASOP_SATURATE_WARNING_OFF; + tmp16 = shl(negate(tmp16), add(sub(add(st, s3), s4), 1-14)); /* Q1 */ + tmp16 = shr(add(tmp16, 1), 1); /* Q0 */ + BASOP_SATURATE_WARNING_ON; + + *gain_factor_param = tmp16; + move16(); + if (GT_16(tmp16, 3)) + { + *gain_factor_param = 3; + move16(); + } + if (tmp16 < 0) + { + *gain_factor_param = 0; + move16(); + } + + /*If optimal gain negatif or zero but snr still positif->gain=0.5f*/ + test(); + if (snr > 0 && *gain_factor_param == 0) + { + *gain_factor_param = 1; + move16(); + } + } + + mem_bpf->lp_error = lp_error; + move32(); + mem_bpf->noise_shift_old = s2_old; + move16(); + + + return 0; +} + diff --git a/lib_enc/bw_detect_fx.c b/lib_enc/bw_detect_fx.c new file mode 100644 index 0000000..6ca3dca --- /dev/null +++ b/lib_enc/bw_detect_fx.c @@ -0,0 +1,915 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_enc_fx.h" /* Encoder static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +#include "rom_com_fx.h" +#include "basop_util.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define ALPHA_BWD_FX 24576 /* 0.75 in Q15*/ +#define BWD_LT_THRESH_FX 19661 /* 0.6 in Q15*/ + +#define BWD_COUNT_MAX 100 +#define BWD_COUNT_WIDER_BW 10 + +#define BWD_N_BINS_MAX 13 + +#define CLDFB_ENER_OFFSET_FX 26214 /* 1.6 in Q14 */ + +/*-------------------------------------------------------------------* + * bw_detect() + * + * WB, SWB and FB bandwidth detector + *--------------------------------------------------------------------*/ + +void bw_detect_fx( + Encoder_State_fx *st, /* i/o: Encoder State */ + const Word16 signal_in[], /* i : input signal */ + const Word16 localVAD, + Word32 *enerBuffer, /* i : CLDFB Energy Q31 */ + Word16 *cldfbBuf_Ener_Exp /* i : CLDFB Energy Exponent */ +) +{ + Word16 Q_dct; + Word16 i, j, k, bw_max, bin_width, n_bins; + Word16 max_NB, max_WB, max_SWB, max_FB, mean_NB, mean_WB, mean_SWB, mean_FB; /* Q11*/ + const Word16 *pt, *pt1; + Word16 spect[BWD_TOTAL_WIDTH], spect_bin[BWD_N_BINS_MAX]; + Word32 spect32[BWD_TOTAL_WIDTH],in_win32[BWD_TOTAL_WIDTH]; + Word16 e_tmp, f_tmp; + Word32 L_tmp, sum32; + + Word32 L_tmp1, L_tmp2, L_tmp3; + Word16 scale; + Word16 ScalFac, ScalFacInv; + Word32 cldfb_bin[9]; + Word16 cldfb_bin_Exp[9]; + Word16 cldfb_bin_width = 4; + const Word32 *pt32; + Word32 max_NB32, max_WB32, max_SWB32, max_FB32, mean_NB32, mean_WB32, mean_SWB32, mean_FB32; /* Q11*/ /* we need Word32 for the new cldfb energy vectors */ + + /* only for debugging */ + /* float cldfbBuf_Ener_float[CLDFB_NO_CHANNELS_MAX]; + for(i=0; i< CLDFB_NO_CHANNELS_MAX; i++){ + cldfbBuf_Ener_float[i] = (enerBuffer[i] * pow (2, -(31 - cldfbBuf_Ener_Exp[i]))); + } + */ + + IF( GT_32(st->input_Fs_fx,8000)) + { + + IF ( enerBuffer != NULL) + { + n_bins = 9; + move16(); + scale = st->cldfbAna_Fx->scale; + move16();/* 7Q8 */ + + /*ScalFac = 1/ ( st->cldfbAnaEnc->scale * st->cldfbAnaEnc->scale * 8.f);*/ + /*hs->CLDFBscalingFactor = div_s(1, shl(i_mult2(CLDFBscale, CLDFBscale), 3));*/ + + assert(2048/*1.0/(1<<4) Q15*/ < mult(scale, scale)); + /* Exponent ScalFacInv: -16 = -(2*7 (CLDFBscale) + 2 (8.0) */ + ScalFacInv = shl(mult(scale,scale),1); /* Q8*Q8 = Q16 + shl -> Q17 -16 -> Q1; shl -> Q2 */ + /* Exponent ScalFac: -15 = -(2*7 (CLDFBscale) + 2 (8.0) - 1 (1.0)) */ + ScalFac = div_s(0x4000,ScalFacInv); /* bin(17214) *2^-15 * 2^-15 = 0.0000160 , use CLDFBscalingFactor_EXP for this*/ /*Q15*/ + + + /*set_f( cldfb_bin, 0.001f, 9 );*/ + set32_fx( cldfb_bin, 1, n_bins ); /* Q31*/ + set16_fx( cldfb_bin_Exp, -15, n_bins ); + + /* NB: 1.2 - 2.8 kHz, 4 cldfb-bands */ + FOR(i=0; i< cldfb_bin_width; i++ ) + { + cldfb_bin[0] = BASOP_Util_Add_Mant32Exp( cldfb_bin[0],cldfb_bin_Exp[0], enerBuffer[3+i], cldfbBuf_Ener_Exp[3+i], &(cldfb_bin_Exp[0]) ); + move32();/* result: Q31 */ + } + + cldfb_bin[0] = Mpy_32_16_1(cldfb_bin[0], ScalFac ); + move32(); /* Q31 */ + cldfb_bin_Exp[0] = add( cldfb_bin_Exp[0], CLDFBscalingFactor_EXP); + move16(); + + if(cldfb_bin[i] == 0) + { + cldfb_bin[i] = L_deposit_l(1); + } + L_tmp = BASOP_Util_Log2(cldfb_bin[0]); /*(log2(660423549*2^(-31))/64)*2^31*/ + L_tmp = L_add(L_tmp,L_shl(L_deposit_l(cldfb_bin_Exp[0]),31-LD_DATA_SCALE)); /* Q25 */ + cldfb_bin[0] = Mpy_32_16_1(L_tmp, 9864/*1.0f/3.3219280948873623478703194294894f Q15*/); + move32();/* 1/log2(10) */ /* Q25 */ + + /* WB: 4.4 - 7.2 kHz, 8 cldfb-bands, mid band(14) counted twice */ + IF( GE_32(st->input_Fs_fx,16000)) + { + /* + cldfb_bin[1] += Sum( &(enerBuffer[11]), cldfb_bin_width ); + cldfb_bin[2] += Sum( &(enerBuffer[14]), cldfb_bin_width );*/ + FOR(i=0; i< cldfb_bin_width; i++ ) + { + cldfb_bin[1] = BASOP_Util_Add_Mant32Exp( cldfb_bin[1],cldfb_bin_Exp[1], enerBuffer[11+i], cldfbBuf_Ener_Exp[11+i], &(cldfb_bin_Exp[1]) ); + move32(); + cldfb_bin[2] = BASOP_Util_Add_Mant32Exp( cldfb_bin[2],cldfb_bin_Exp[2], enerBuffer[14+i], cldfbBuf_Ener_Exp[14+i], &(cldfb_bin_Exp[2]) ); + move32(); + } + FOR(i=1; i<= 2; i++ ) + { + cldfb_bin[i] = Mpy_32_16_1(cldfb_bin[i], ScalFac ); + move32(); + cldfb_bin_Exp[i] = add( cldfb_bin_Exp[i], CLDFBscalingFactor_EXP); + move16(); + + if(cldfb_bin[i] == 0) + { + cldfb_bin[i] = L_deposit_l(1); + } + L_tmp = BASOP_Util_Log2(cldfb_bin[i]); /*(log2(660423549*2^(-31))/64)*2^31*/ + L_tmp = L_add(L_tmp,L_shl(L_deposit_l(cldfb_bin_Exp[i]),31-LD_DATA_SCALE)); /* Q25 */ + cldfb_bin[i] = Mpy_32_16_1(L_tmp, 9864/*1.0f/3.3219280948873623478703194294894f Q15*/); + move32();/* 1/log2(10) */ /* Q25 */ + } + } + + /* SWB: 9.2 - 15.6 kHz, 16 cldfb-bands */ + IF( GE_32(st->input_Fs_fx,32000)) + { + /* + cldfb_bin[3] += Sum( &(enerBuffer[23]), cldfb_bin_width ); + cldfb_bin[4] += Sum( &(enerBuffer[27]), cldfb_bin_width ); + cldfb_bin[5] += Sum( &(enerBuffer[31]), cldfb_bin_width ); + cldfb_bin[6] += Sum( &(enerBuffer[35]), cldfb_bin_width ); + */ + FOR(i=0; i< cldfb_bin_width; i++ ) + { + cldfb_bin[3] = BASOP_Util_Add_Mant32Exp( cldfb_bin[3],cldfb_bin_Exp[3], enerBuffer[23+i], cldfbBuf_Ener_Exp[23+i], &(cldfb_bin_Exp[3]) ); + move32(); + cldfb_bin[4] = BASOP_Util_Add_Mant32Exp( cldfb_bin[4],cldfb_bin_Exp[4], enerBuffer[27+i], cldfbBuf_Ener_Exp[27+i], &(cldfb_bin_Exp[4]) ); + move32(); + cldfb_bin[5] = BASOP_Util_Add_Mant32Exp( cldfb_bin[5],cldfb_bin_Exp[5], enerBuffer[31+i], cldfbBuf_Ener_Exp[31+i], &(cldfb_bin_Exp[5]) ); + move32(); + cldfb_bin[6] = BASOP_Util_Add_Mant32Exp( cldfb_bin[6],cldfb_bin_Exp[6], enerBuffer[35+i], cldfbBuf_Ener_Exp[35+i], &(cldfb_bin_Exp[6]) ); + move32(); + } + FOR(i=3; i<= 6; i++ ) + { + cldfb_bin[i] = Mpy_32_16_1(cldfb_bin[i], ScalFac ); + move32(); + cldfb_bin_Exp[i] = add( cldfb_bin_Exp[i], CLDFBscalingFactor_EXP); + move16(); + + if(cldfb_bin[i] == 0) + { + cldfb_bin[i] = L_deposit_l(1); + } + L_tmp = BASOP_Util_Log2(cldfb_bin[i]); /*(log2(660423549*2^(-31))/64)*2^31*/ + L_tmp = L_add(L_tmp,L_shl(L_deposit_l(cldfb_bin_Exp[i]),31-LD_DATA_SCALE)); /* Q25 */ + cldfb_bin[i] = Mpy_32_16_1(L_tmp, 9864/*1.0f/3.3219280948873623478703194294894f Q15*/); + move32();/* 1/log2(10) */ /* Q25 */ + } + } + + /* FB: 16.8 - 20.0 kHz, 8 cldfb-bands */ + IF( GE_32(st->input_Fs_fx,48000)) + { + /* + cldfb_bin[7] += Sum( &(enerBuffer[42]), cldfb_bin_width ); + cldfb_bin[8] += Sum( &(enerBuffer[46]), cldfb_bin_width ); + */ + FOR(i=0; i< cldfb_bin_width; i++ ) + { + cldfb_bin[7] = BASOP_Util_Add_Mant32Exp( cldfb_bin[7],cldfb_bin_Exp[7], enerBuffer[42+i], cldfbBuf_Ener_Exp[42+i], &(cldfb_bin_Exp[7]) ); + move32(); + cldfb_bin[8] = BASOP_Util_Add_Mant32Exp( cldfb_bin[8],cldfb_bin_Exp[8], enerBuffer[46+i], cldfbBuf_Ener_Exp[46+i], &(cldfb_bin_Exp[8]) ); + move32(); + } + FOR(i=7; i<= 8; i++ ) + { + cldfb_bin[i] = Mpy_32_16_1(cldfb_bin[i], ScalFac ); + move32(); + cldfb_bin_Exp[i] = add( cldfb_bin_Exp[i], CLDFBscalingFactor_EXP); + move16(); + + if(cldfb_bin[i] == 0) + { + cldfb_bin[i] = L_deposit_l(1); + } + L_tmp = BASOP_Util_Log2(cldfb_bin[i]); /*(log2(660423549*2^(-31))/64)*2^31*/ + L_tmp = L_add(L_tmp,L_shl(L_deposit_l(cldfb_bin_Exp[i]),31-LD_DATA_SCALE)); /* Q25 */ + cldfb_bin[i] = Mpy_32_16_1(L_tmp, 9864/*1.0f/3.3219280948873623478703194294894f Q15*/); + move32();/* 1/log2(10) */ /* Q25 */ + } + } + /* cldfb_bin_Exp[] are applied now in cldfb_bin[i] -> don't use again */ + set16_fx( cldfb_bin_Exp, 0, n_bins ); + + } + ELSE + { + + /* set width of a speactral bin (corresponds to 1.5kHz) */ + IF( EQ_32(st->input_Fs_fx,16000)) + { + bw_max = WB; + move16(); + bin_width = 60; + move16(); + n_bins = 5; + move16(); /* spectrum to 7.5 kHz */ + } + ELSE IF( EQ_32(st->input_Fs_fx,32000)) + { + bw_max = SWB; + move16(); + bin_width = 30; + move16(); + n_bins = 10; + move16(); /* spectrum to 15.0 kHz */ + } + ELSE /* st->input_Fs == 48000 */ + { + bw_max = FB; + move16(); + bin_width = 20; + move16(); + n_bins = BWD_N_BINS_MAX; + move16(); /* spectrum to 19.5 kHz */ + } + + /*---------------------------------------------------------------------* + * windowing of the input signal + *---------------------------------------------------------------------*/ + Q_dct = 0; + move16(); + pt = signal_in; + pt1 = hann_window_320_fx; + /* 1st half of the window */ + FOR( i=0; i Q16*/ + } + pt1--; + /* 2nd half of the window */ + FOR(; i Q25 */ + + mean_NB = extract_l(L_shr( L_add(mean_NB32 ,cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */ + max_NB = extract_l(L_shr( L_add(max_NB32 ,cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */ + mean_WB = extract_l(L_shr( L_add(mean_WB32 ,cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */ + max_WB = extract_l(L_shr( L_add(max_WB32 ,cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */ + + + /*if WB */ + IF( EQ_32(st->input_Fs_fx,16000)) + { + /* for 16kHz sampled inputs, do not check SWB & FB */ + mean_SWB = 0; + move16(); + max_SWB = 0; + move16(); + mean_FB = 0; + move16(); + max_FB = 0; + move16(); + } + ELSE + { + /* else if SWB */ + IF( EQ_32(st->input_Fs_fx,32000)) + { + + /* for 32kHz sampled inputs, do not check FB */ + mean_FB = 0; + move16(); + max_FB = 0; + move16(); + + /* SWB: 8,8 - 15,2 kHz, 16 cldfb-bands (4 bins) */ + + maximum_32_fx( pt32, 4, &max_SWB32 ); + + L_tmp = L_shr(*pt32++, 2); /* /4 */ + L_tmp = L_add(L_tmp,L_shr(*pt32++, 2)); + L_tmp = L_add(L_tmp,L_shr(*pt32++, 2)); + mean_SWB32 = L_add(L_tmp,L_shr(*pt32++, 2)); + + mean_SWB = extract_l(L_shr(L_add(mean_SWB32, cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */ + max_SWB = extract_l(L_shr(L_add(max_SWB32 , cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */ + + } + ELSE + { /* FB */ + /* SWB: 8,8 - 15,2 kHz, 16 cldfb-bands (4 bins) */ + + maximum_32_fx( pt32, 4, &max_SWB32 ); + + L_tmp = L_shr(*pt32++, 2); /* /4 */ + L_tmp = L_add(L_tmp,L_shr(*pt32++, 2)); + L_tmp = L_add(L_tmp,L_shr(*pt32++, 2)); + mean_SWB32 = L_add(L_tmp,L_shr(*pt32++, 2)); + + mean_SWB = extract_l(L_shr(L_add(mean_SWB32, cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */ + max_SWB = extract_l(L_shr(L_add(max_SWB32 , cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */ + + + /* FB: 16,4 - 19,6 kHz, 8 cldfb-bands (2 bins) */ + + maximum_32_fx( pt32, 2, &max_FB32 ); + + L_tmp = L_shr(*pt32++, 1); + mean_FB32 = L_add(L_tmp,L_shr(*pt32++, 1)); + + mean_FB = extract_l(L_shr(L_add(mean_FB32, cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */ + max_FB = extract_l(L_shr(L_add(max_FB32 , cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */ + + } + } + } + ELSE + { + pt = (const Word16 *)spect_bin; + /* NB: 1.5-3.0kHz (1 bin) */ + pt++; + mean_NB = *pt++; + move16(); + max_NB = mean_NB; + move16(); + + /* WB: 4.5-7.5kHz (2 bins) */ + pt++; + maximum_fx( pt, 2, &max_WB ); + L_tmp = L_mult(*pt++,16384); + L_tmp = L_mac(L_tmp,*pt++,16384); + mean_WB = round_fx(L_tmp); + + IF( EQ_32(st->input_Fs_fx,16000)) + { + /* for 16kHz sampled inputs, do not check SWB & FB */ + mean_SWB = 0; + move16(); + max_SWB = 0; + move16(); + mean_FB = 0; + move16(); + max_FB = 0; + move16(); + } + ELSE + { + /* SWB: 9.0-15.0kHz (4 bins) */ + pt++; + maximum_fx( pt, 4, &max_SWB ); + L_tmp = L_mult(*pt++,8192); + L_tmp = L_mac(L_tmp,*pt++,8192); + L_tmp = L_mac(L_tmp,*pt++,8192); + L_tmp = L_mac(L_tmp,*pt++,8192); + mean_SWB = round_fx(L_tmp); + + IF( EQ_32(st->input_Fs_fx,48000)) + { + /* FB: 16.5-19.5kHz (2 bins) */ + pt++; + maximum_fx( pt, 2, &max_FB ); + L_tmp = L_mult(*pt++,16384); + L_tmp = L_mac(L_tmp,*pt++,16384); + mean_FB = round_fx(L_tmp); + } + ELSE + { + /* for 32kHz sampled inputs, do not check FB */ + mean_FB = 0; + move16(); + max_FB = 0; + move16(); + } + } + } + /*---------------------------------------------------------------------* + * update LT counters and energies + *---------------------------------------------------------------------*/ + + /*if( localVAD || st->lp_noise > 30 )*/ + test(); + IF( localVAD || GT_16(st->lp_noise_fx,7680)) + { + /*st->lt_mean_NB_fx = ALPHA_BWD * st->lt_mean_NB_fx + (1-ALPHA_BWD) * mean_NB;*/ + L_tmp = L_mult(ALPHA_BWD_FX, st->lt_mean_NB_fx); /* Q15 * Q11 -> Q27 */ + L_tmp = L_mac(L_tmp, 32768-ALPHA_BWD_FX, mean_NB); /* Q15 * Q11) -> L_mac(Q27, Q27) -> Q27*/ + st->lt_mean_NB_fx = round_fx(L_tmp); /* Q11 (27-16) */ + + /*st->lt_mean_WB_fx = ALPHA_BWD * st->lt_mean_WB_fx + (1-ALPHA_BWD) * mean_WB;*/ + L_tmp = L_mult(ALPHA_BWD_FX, st->lt_mean_WB_fx); + L_tmp = L_mac(L_tmp, 32768-ALPHA_BWD_FX, mean_WB); + st->lt_mean_WB_fx = round_fx(L_tmp); + + /*st->lt_mean_SWB_fx = ALPHA_BWD * st->lt_mean_SWB_fx + (1-ALPHA_BWD) * mean_SWB;*/ + L_tmp = L_mult(ALPHA_BWD_FX, st->lt_mean_SWB_fx); + L_tmp = L_mac(L_tmp, 32768-ALPHA_BWD_FX, mean_SWB); + st->lt_mean_SWB_fx = round_fx(L_tmp); + + + + IF ( enerBuffer != NULL ) + { + /*if( 0.9f * max_WB > BWD_LT_THRESH_FX * st->lt_mean_NB_fx )*/ + + /* optim: if( max_WB > (BWD_LT_THRESH_FX / 0.9) * st->lt_mean_NB_fx )*/ + + L_tmp = L_mult(3686,max_WB); /* (0.9 in Q12) x Q11 -> Q24*/ + + L_tmp1 = L_mult(BWD_LT_THRESH_FX,st->lt_mean_NB_fx); /* Q15 x Q11 -> Q27 */ + L_tmp1 = L_shl(L_tmp1, 24-27); /* Q27 -> Q24) */ + L_tmp1 = L_sub(L_tmp, L_tmp1 ); + + IF( L_tmp1 > 0 ) + { + /*if( 2.5f * max_WB > max_NB )*/ + L_tmp = L_mult(10240,max_WB); /* 2.5 in Q12 x Q11 -> Q24 */ + L_tmp1 = L_mult(max_NB, 4096); /* Q11 x (1 in Q12) -> Q24 */ + IF( GT_32(L_tmp,L_tmp1)) /* Q24 */ + { + st->count_WB_fx = add(st->count_WB_fx,1); + } + } + ELSE + { + /*if( 3.5f * mean_WB < mean_NB )*/ + L_tmp = L_mult(14336,mean_WB); /* 3.5 in Q12 x Q11 -> Q24*/ + L_tmp1 = L_mult(mean_NB,4096); + L_tmp = L_sub(L_tmp, L_tmp1); + IF( L_tmp < 0 ) + { + st->count_WB_fx = sub(st->count_WB_fx, 1); + } + } + + /*if( 0.83f * max_SWB > BWD_LT_THRESH_FX * st->lt_mean_WB_fx && max_WB > BWD_LT_THRESH_FX * st->lt_mean_NB_fx )*/ + /* IF( L_msu( L_tmp,BWD_LT_THRESH_FX,st->lt_mean_WB_fx) > 0 && L_msu( L_deposit_h(max_WB),BWD_LT_THRESH_FX,st->lt_mean_NB_fx) > 0 ) + {*/ + + L_tmp = L_mult(3400,max_SWB); /* (0.83 in Q12) x Q11 -> Q24*/ + L_tmp1 = L_mult(BWD_LT_THRESH_FX,st->lt_mean_WB_fx); /* Q15 x Q11 -> Q27 */ + L_tmp1 = L_shl(L_tmp1, 24-27); /* Q27 -> Q24) */ + L_tmp1 = L_sub(L_tmp, L_tmp1 ); + + L_tmp = L_mult( max_WB,4096); + L_tmp2 = L_mult(BWD_LT_THRESH_FX,st->lt_mean_NB_fx); /* Q15 x Q11 -> Q27 */ + L_tmp2 = L_shl(L_tmp2, 24-27); /* Q27 -> Q24) */ + L_tmp2 = L_sub(L_tmp, L_tmp2 ); + + test(); + IF(L_tmp1 > 0 && L_tmp2 > 0 ) + { + /*if( 2 * max_SWB > max_WB )*/ + L_tmp = L_mult(max_WB,4096); + L_tmp1 = L_mult(8192,max_SWB); /* 2.0 in Q12 x Q11 -> Q24*/ + L_tmp1 = L_sub(L_tmp1, L_tmp); /* Q24 - (Q11 x (1 in Q12) ) = Q24 */ + IF(L_tmp1 > 0 ) + { + st->count_SWB_fx = add(st->count_SWB_fx, 1); + } + } + ELSE + { + /*if( 3 * mean_SWB < mean_WB )*/ + L_tmp = L_mult(mean_WB,4096); + L_tmp1 = L_mult(12288,mean_SWB); /* 3.0 in Q12 x Q11 -> Q24*/ + L_tmp1 = L_sub(L_tmp1,L_tmp); /* Q24 - (Q11 x (1 in Q12) ) = Q24 */ + IF(L_tmp1 < 0 ) + { + st->count_SWB_fx = sub(st->count_SWB_fx,1); + } + } + /*if( max_FB > BWD_LT_THRESH_FX * st->lt_mean_SWB_fx && 0.83f * max_SWB > BWD_LT_THRESH_FX * st->lt_mean_WB_fx && max_WB > BWD_LT_THRESH_FX * st->lt_mean_NB_fx )*/ + + L_tmp = L_mult(max_FB, 4096); /* Q11 x (1 in Q12) = Q24 */ + L_tmp1 = L_mult(BWD_LT_THRESH_FX, st->lt_mean_SWB_fx); /* Q15 x Q11 -> Q27 */ + L_tmp1 = L_shl(L_tmp1, 24-27); /* Q27 -> Q24) */ + L_tmp1 = L_sub( L_tmp, L_tmp1); /* Q24 */ + + L_tmp = L_mult(max_SWB, 3400 ); /* (0.83 in Q12) x Q11) = Q24 */ + L_tmp2 = L_mult(BWD_LT_THRESH_FX,st->lt_mean_WB_fx); /* Q15 x Q11 -> Q27 */ + L_tmp2 = L_shl(L_tmp2, 24-27); /* Q27 -> Q24) */ + L_tmp2 = L_sub(L_tmp, L_tmp2 ); /* Q24 */ + + L_tmp = L_mult(max_WB,4096); /* Q11 x (1 in Q12) = Q24*/ + + L_tmp3 = L_mult(BWD_LT_THRESH_FX,st->lt_mean_NB_fx); /* Q15 x Q11 -> Q27 */ + L_tmp3 = L_shl(L_tmp3, 24-27); /* Q27 -> Q24) */ + L_tmp3 = L_sub(L_tmp, L_tmp3 ); + + test(); + test(); + IF(L_tmp1 > 0 && L_tmp2 > 0 && L_tmp3 > 0 ) + { + /*if( 3 * max_FB > max_SWB )*/ + L_tmp = L_mult( max_SWB,4096 ); /* Q11 x (1 in Q12) = Q24*/ + L_tmp1 = L_mult(12288,max_FB); /* 3.0 in Q12 x Q11 -> Q24*/ + L_tmp1 = L_sub(L_tmp1, L_tmp); /* Q24 */ + IF(L_tmp1 > 0 ) + { + st->count_FB_fx = add(st->count_FB_fx,1); + } + } + ELSE + { + /* if( 4.1f * mean_FB < mean_SWB )*/ + L_tmp = L_mult(mean_SWB,4096); /* Q11 x (1 in Q12) = Q24 */ + L_tmp1 = L_mult(16794,mean_FB); /* 4.1 in Q12 x Q11 -> Q24*/ + L_tmp1 = L_sub(L_tmp1,L_tmp); /* Q24 */ + IF(L_tmp1 < 0 ) + { + st->count_FB_fx = sub(st->count_FB_fx,1); + } + } + + } + ELSE /* DCT based detection */ + { + /*if( max_WB > BWD_LT_THRESH * st->lt_mean_NB_fx )*/ + IF( L_msu( L_deposit_h(max_WB),BWD_LT_THRESH_FX,st->lt_mean_NB_fx) > 0 ) + { + /*if( 2 * max_WB > max_NB )*/ + L_tmp = L_mult(8192,max_WB); /* 2.0 in Q12 x Q11 -> Q24*/ + if( L_msu(L_tmp,max_NB,4096) > 0 ) + { + st->count_WB_fx = add(st->count_WB_fx,1); + } + } + ELSE + { + /*if( 2.6f * mean_WB < mean_NB )*/ + L_tmp = L_mult(10650,mean_WB); /* 2.6 in Q12 x Q11 -> Q24*/ + L_tmp = L_msu(L_tmp,mean_NB,4096); + test(); + test(); + if( L_tmp < 0 && !(EQ_16(mean_WB,-1)&&EQ_16(mean_NB,-1))) + { + st->count_WB_fx = sub(st->count_WB_fx, 1); + } + } + + test(); + /*if( max_SWB > BWD_LT_THRESH * st->lt_mean_WB_fx && max_WB > BWD_LT_THRESH * st->lt_mean_NB_fx )*/ + test(); + IF( L_msu( L_deposit_h(max_SWB),BWD_LT_THRESH_FX,st->lt_mean_WB_fx) > 0 && L_msu( L_deposit_h(max_WB),BWD_LT_THRESH_FX,st->lt_mean_NB_fx) > 0 ) + { + /*if( 2 * max_SWB > max_WB )*/ + L_tmp = L_mult(8192,max_SWB); /* 2.0 in Q12 x Q11 -> Q24*/ + if( L_msu(L_tmp,max_WB,4096) > 0 ) + { + st->count_SWB_fx = add(st->count_SWB_fx,1); + } + } + ELSE + { + /*if( 3 * mean_SWB < mean_WB )*/ + L_tmp = L_mult(12288,mean_SWB); /* 3.0 in Q12 x Q11 -> Q24*/ + L_tmp = L_msu(L_tmp,mean_WB,4096); + test(); + test(); + if( L_tmp < 0 && !(EQ_16(mean_SWB,-1)&&EQ_16(mean_WB,-1))) + { + st->count_SWB_fx = sub(st->count_SWB_fx,1); + } + } + + test(); + test(); + /*if( max_FB > BWD_LT_THRESH * st->lt_mean_SWB_fx && max_SWB > BWD_LT_THRESH * st->lt_mean_WB_fx && max_WB > BWD_LT_THRESH * st->lt_mean_NB_fx )*/ + IF( L_msu( L_deposit_h(max_FB),BWD_LT_THRESH_FX,st->lt_mean_SWB_fx) > 0 && L_msu( L_deposit_h(max_SWB),BWD_LT_THRESH_FX,st->lt_mean_WB_fx) > 0 && L_msu( L_deposit_h(max_WB),BWD_LT_THRESH_FX,st->lt_mean_NB_fx) > 0 ) + { + /*if( 2 * max_FB > max_SWB )*/ + L_tmp = L_mult(8192,max_FB); /* 2.0 in Q12 x Q11 -> Q24*/ + if( L_msu(L_tmp,max_SWB,4096) > 0 ) + { + st->count_FB_fx = add(st->count_FB_fx,1); + } + } + ELSE + { + /*if( 3 * mean_FB < mean_SWB )*/ + L_tmp = L_mult(12288,mean_FB); /* 3.0 in Q12 x Q11 -> Q24*/ + test(); + test(); + if( L_msu(L_tmp,mean_SWB,4096) < 0 && !(EQ_16(mean_FB,-1)&&EQ_16(mean_SWB,-1))) + { + st->count_FB_fx = sub(st->count_FB_fx,1); + } + } + } + + st->count_WB_fx = s_min(st->count_WB_fx,BWD_COUNT_MAX); + move16(); + st->count_SWB_fx = s_min(st->count_SWB_fx,BWD_COUNT_MAX); + move16(); + st->count_FB_fx = s_min(st->count_FB_fx,BWD_COUNT_MAX); + move16(); + st->count_WB_fx = s_max(st->count_WB_fx,0); + move16(); + st->count_SWB_fx = s_max(st->count_SWB_fx,0); + move16(); + st->count_FB_fx = s_max(st->count_FB_fx,0); + move16(); + + /*---------------------------------------------------------------------* + * check against thresholds + * detect a band-width change + *---------------------------------------------------------------------*/ + + /* switching to a higher BW */ + IF( EQ_16(st->last_input_bwidth_fx,NB)) + { + IF( GT_16(st->count_WB_fx,BWD_COUNT_WIDER_BW)) + { + st->input_bwidth_fx = WB; + move16(); + st->count_WB_fx = BWD_COUNT_MAX; + move16(); + + IF( GT_16(st->count_SWB_fx,BWD_COUNT_WIDER_BW)) + { + st->input_bwidth_fx = SWB; + move16(); + st->count_SWB_fx = BWD_COUNT_MAX; + move16(); + + IF( GT_16(st->count_FB_fx,BWD_COUNT_WIDER_BW)) + { + st->input_bwidth_fx = FB; + move16(); + st->count_FB_fx = BWD_COUNT_MAX; + move16(); + } + } + } + } + + test(); + IF( EQ_16(st->last_input_bwidth_fx,WB)&>_32(st->input_Fs_fx,16000)) + { + IF( GT_16(st->count_SWB_fx,BWD_COUNT_WIDER_BW)) + { + st->input_bwidth_fx = SWB; + move16(); + st->count_SWB_fx = BWD_COUNT_MAX; + move16(); + + IF( GT_16(st->count_FB_fx,BWD_COUNT_WIDER_BW)) + { + st->input_bwidth_fx = FB; + move16(); + st->count_FB_fx = BWD_COUNT_MAX; + move16(); + } + } + } + + test(); + IF( EQ_16(st->last_input_bwidth_fx,SWB)&>_32(st->input_Fs_fx,32000)) + { + IF( GT_16(st->count_FB_fx,BWD_COUNT_WIDER_BW)) + { + st->input_bwidth_fx = FB; + move16(); + st->count_FB_fx = BWD_COUNT_MAX; + move16(); + } + } + + /* switching to a lower BW */ + IF( EQ_16(st->last_input_bwidth_fx,FB)) + { + IF( LT_16(st->count_FB_fx,10)) + { + st->input_bwidth_fx = SWB; + move16(); + st->count_FB_fx = 0; + move16(); + } + IF( LT_16(st->count_SWB_fx,10)) + { + st->input_bwidth_fx = WB; + move16(); + st->count_SWB_fx = 0; + move16(); + st->count_FB_fx = 0; + move16(); + } + IF( LT_16(st->count_WB_fx,10)) + { + st->input_bwidth_fx = NB; + move16(); + st->count_WB_fx = 0; + move16(); + st->count_SWB_fx = 0; + move16(); + st->count_FB_fx = 0; + move16(); + } + } + + IF( EQ_16(st->last_input_bwidth_fx,SWB)) + { + IF( LT_16(st->count_SWB_fx,10)) + { + st->input_bwidth_fx = WB; + move16(); + st->count_SWB_fx = 0; + move16(); + st->count_FB_fx = 0; + move16(); + } + IF( LT_16(st->count_WB_fx,10)) + { + st->input_bwidth_fx = NB; + move16(); + st->count_WB_fx = 0; + move16(); + st->count_SWB_fx = 0; + move16(); + st->count_FB_fx = 0; + move16(); + } + + } + + IF( EQ_16(st->last_input_bwidth_fx,WB)) + { + IF( LT_16(st->count_WB_fx,10)) + { + st->input_bwidth_fx = NB; + move16(); + st->count_WB_fx = 0; + move16(); + st->count_SWB_fx = 0; + move16(); + st->count_FB_fx = 0; + move16(); + } + } + } + } + + + /* verify that maximum encoded bandwidth (specified on the command line) is not exceeded */ + IF( GT_16(st->input_bwidth_fx,st->max_bwidth_fx)) + { + st->input_bwidth_fx = st->max_bwidth_fx; + move16(); + } + + /* Set and limit the encoded bandwidth */ + IF ( EQ_16(st->codec_mode,MODE1)) + { + Word32 total_brate_fx; + + st->bwidth_fx = st->input_bwidth_fx; + move16(); + + total_brate_fx = L_add(st->total_brate_fx, 0); + + /* change the encoded bandwidth, if not supported at particular bitrate */ + test(); + test(); + test(); + test(); + test(); + IF ( LE_32(total_brate_fx, ACELP_9k60)&&NE_16(st->bwidth_fx,NB)&&NE_16(st->bwidth_fx,WB)) + { + st->bwidth_fx = WB; + move16(); + } + ELSE IF ( GE_32(st->total_brate_fx,ACELP_13k20)&&LE_32(st->total_brate_fx,ACELP_16k40)&>_16(st->bwidth_fx,SWB)) + { + st->bwidth_fx = SWB; + move16(); + } + ELSE IF ( GE_32(st->total_brate_fx,ACELP_32k)&<_16(st->bwidth_fx,WB)) + { + st->bwidth_fx = WB; + move16(); + } + } + ELSE + { + Word16 n, bits_frame_nominal; + + UWord16 lsb; + Word16 tmpbandwidthMin; + + Mpy_32_16_ss(st->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + bits_frame_nominal = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + + FOR (n=0; nrf_mode,1)) + { + tmpbandwidthMin = WB; + } + st->bwidth_fx = s_max(s_min(st->input_bwidth_fx, FrameSizeConfig[n].bandwidth_max), tmpbandwidthMin); + } + + return; +} + diff --git a/lib_enc/cng_enc_fx.c b/lib_enc/cng_enc_fx.c new file mode 100644 index 0000000..3bdc655 --- /dev/null +++ b/lib_enc/cng_enc_fx.c @@ -0,0 +1,1377 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_enc_fx.h" /* Encoder static table prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "basop_mpy.h" + +/*---------------------------------------------------------------------* +* Local constants +*---------------------------------------------------------------------*/ + +#define MAX_DELTA 1 +#define MIN_CNT 50 /* Minimum frame number before SID interval adaptation */ +#define INT_H 50 +#define INT_L 8 + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ +static void shb_CNG_encod_fx( + Encoder_State_fx *st_fx, /* i/o: State structure */ + const Word16 update_fx /* i : SID update flag */ +); +static Word16 shb_DTX_fx( + Encoder_State_fx *st_fx, /* i/o: State structure */ + const Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz */ + const Word16 *syn_12k8_16k /* i : ACELP core synthesis at 12.8kHz or 16kHz */ +); + +void CNG_enc_fx( + Encoder_State_fx *st_fx,/* i/o: State structure */ + const Word16 L_frame, /* i : length of the frame Q0 */ + Word16 Aq[], /* o : LP coefficients Q12 */ + const Word16 *speech, /* i : pointer to current frame input speech buffer Q_new */ + Word32 L_enr, /* i : residual energy from Levinson-Durbin Q6 */ + Word16 *lsp_new, /* i/o: current frame ISPs Q15 */ + Word16 *lsf_new, /* i/o: current frame ISFs Qlog2(2.56) */ + Word16 *allow_cn_step, /* o : allow CN step Q0 */ + Word16 burst_ho_cnt, /* i : hangover frames at end of speech burst Q0 */ + Word16 Q_new /* i : Q value of speech */ + ,Word32 *q_env + ,Word16 *sid_bw + ,Word16 *exc_mem2 +) +{ + Word16 enr_index; + Word16 i, j, ptr; + Word16 m1; + Word16 res[L_FRAME16k]; + Word16 step_inv=0; + Word16 hi, lo; + Word16 maxl=0; + Word16 num_bits=0; + Word16 step=0; + Word16 *pt_res; + const Word16 *pt_sp; + Word16 enr; + Word32 L_tmp, L_ener; + Word16 k, tmp1; + Word16 weights; + Word16 sp_enr; + Word32 L_tmp1; + Word16 exp; + Word16 m = 0; + Word16 tmp[HO_HIST_SIZE*M]; + Word16 ll, s_ptr; + Word16 tmpv, maxv, scale, att = 1; + Word16 lsf_tmp[M]; + Word32 C[M]; + Word32 max[2]; + Word16 max_idx[2]; + Word16 ftmp_fx; + Word16 lsp_tmp[M]; + Word16 dev; + Word16 max_dev; + Word16 dist; + Word16 max_idx1[2]= {0,0}; + Word16 fft_io[L_FRAME16k]; + Word16 *ptR,*ptI; + Word32 enr1=0; + Word32 env[NUM_ENV_CNG]; + Word32 min1; + Word16 min1_idx; + Word32 d; + Word16 res1[L_FRAME16k]; + Word32 tmp_env[HO_HIST_SIZE*NUM_ENV_CNG]; + Word16 fra; + Word16 temp_lo_fx, temp_hi_fx; + Word16 exp_pow; + Word16 force_cn_step=0; + Word16 tmp_loop; + Word16 st_lp_sp_enr; + + st_lp_sp_enr = st_fx->lp_sp_enr_fx; + /* Temp variables for floating point functions */ + + /*sp_enr = (float) log10( sum2_f( speech, L_frame )/L_frame + 0.1f )/ (float)log10(2.0f);*//*9.1 */ + pt_sp = speech; + L_ener = L_deposit_l(1); + /* L_ener = L_add(L_shr(sum2_f_fx( speech, L_frame ), 8) , L_ener);*/ + IF( EQ_16(L_frame, L_FRAME)) + { + FOR (j=0; j<128; j++) + { + L_tmp = L_mult0(*pt_sp, *pt_sp); + pt_sp++; + L_tmp = L_mac0(L_tmp, *pt_sp, *pt_sp); + pt_sp++; + L_ener = L_add(L_ener, L_shr(L_tmp, 7)); /* 2*Q_new + 1, divide by L_frame done here */ + } + } + ELSE /* L_FRAME16k */ + { + FOR (i=0; i<2; i++) + { + FOR (j=0; j<80; j++) + { + L_tmp = L_mult0(*pt_sp, *pt_sp); + pt_sp++; + L_tmp = L_mac0(L_tmp, *pt_sp, *pt_sp); + pt_sp++; + L_ener = L_add(L_ener, L_shr(Mult_32_16(L_tmp,26214 /* 256/320, Q15 */), 7)); /* 2*Q_new + 1, divide by L_frame done here */ + } + } + } + + hi = norm_l(L_ener); + lo = Log2_norm_lc(L_shl(L_ener, hi)); + hi = sub(29, hi); /* log2 exp in Q2*Q_new */ + hi = sub(hi, shl(Q_new, 1)); /* Q0 */ + L_tmp = L_Comp(hi, lo); /* Q16 */ + sp_enr = round_fx(L_shl(L_tmp, 8)); /* Q8 (16+8-16) */ + + if (sp_enr < 0) + { + sp_enr = 0; + move16(); + } + test(); + IF ( st_fx->first_CNG_fx == 0 || st_fx->old_enr_index_fx < 0 ) + { + st_fx->lp_sp_enr_fx = sp_enr; + move16(); /* Q8 */ + } + ELSE + { + test(); + test(); + test(); + test(); + IF( GT_32(st_fx->last_core_brate_fx, SID_2k40) && ( EQ_16( st_fx->last_core_fx, HQ_CORE ) || burst_ho_cnt > 0 ) && LT_16(st_fx->lp_sp_enr_fx, 1536) && + GT_16(sub(sp_enr, st_fx->lp_sp_enr_fx), 1024) && GT_16(sp_enr, 1536) ) + { + st_fx->lp_sp_enr_fx = sp_enr; + move16(); + force_cn_step = 1; + move16(); + } + ELSE + { + st_fx->lp_sp_enr_fx = round_fx(L_mac(L_mult(29491 /* 0.9, Q15 */,st_fx->lp_sp_enr_fx), 3277 /* 0.1, Q15 */,sp_enr)); /* Q8 (8+15+1-16) */ + } + } + /* update the pointer to circular buffer of old LSP vectors */ + st_fx->cng_hist_ptr_fx = add(st_fx->cng_hist_ptr_fx,1); + if(EQ_16(st_fx->cng_hist_ptr_fx, DTX_HIST_SIZE)) + { + st_fx->cng_hist_ptr_fx = 0; + move16(); + } + + /* update the circular buffer of old LSP vectors with the new LSP vector */ + Copy( lsp_new, &(st_fx->cng_lsp_hist_fx[(st_fx->cng_hist_ptr_fx)*M]), M ); + + /*-----------------------------------------------------------------* + * Find CNG spectral envelope + * Find LSP median + *-----------------------------------------------------------------*/ + test(); + test(); + IF( (EQ_32(st_fx->core_brate_fx, SID_2k40)||EQ_32(st_fx->core_brate_fx,SID_1k75))&&GE_16(st_fx->cng_cnt_fx,sub(st_fx->cng_hist_size_fx,1))) + { + set32_fx( max, 0, 2 ); + set16_fx( max_idx, 0, 2 ); + + FOR( i=0; icng_hist_size_fx; i++ ) + { + IF ( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + lsp2lsf_fx( &st_fx->cng_lsp_hist_fx[i*M], lsf_tmp, M, INT_FS_FX ); + ftmp_fx = 964; + move16();/*QX2.56 */ + tmpv = sub(16384,add(lsf_tmp[M-1],ftmp_fx)); /*QX2.56 */ + L_tmp = L_mult0(tmpv,tmpv); /*QX6.5536 */ + } + ELSE + { + lsp2lsf_fx( &st_fx->cng_lsp_hist_fx[i*M], lsf_tmp, M, INT_FS_16k ); + ftmp_fx = 1205; + move16();/*QX2.56 */ + tmpv = sub(20480,add(lsf_tmp[M-1],ftmp_fx)); /*QX2.56 */ + L_tmp = L_mult0(tmpv,tmpv); /*QX6.5536 */ + } + + tmpv = sub(lsf_tmp[0],ftmp_fx); /*QX2.56 */ + L_tmp = L_mac0(L_tmp,tmpv,tmpv); /*QX6.5536 */ + FOR ( j=0; jcng_hist_size_fx; j++ ) + { + L_tmp = L_add(L_tmp,L_deposit_l(st_fx->cng_lsp_hist_fx[j*M+i])); /*Q15 */ + } + + L_tmp = L_sub(L_tmp,L_add(L_deposit_l(st_fx->cng_lsp_hist_fx[max_idx[0]*M+i]),L_deposit_l(st_fx->cng_lsp_hist_fx[max_idx[1]*M+i]))); /*Q15 */ + tmpv= div_s(1,sub(st_fx->cng_hist_size_fx,2)); /*Q15 */ + L_tmp = Mpy_32_16_1(L_tmp,tmpv); /*Q15 */ + lsp_new[i] = extract_l(L_tmp); /*Q15 */ + } + max_idx1[0] = max_idx[0]; + move16(); + max_idx1[1] = max_idx[1]; + move16(); + } + + /*-----------------------------------------------------------------* + * Quantize CNG spectral envelope (only in SID frame) + * Quantize the LSF vector + *-----------------------------------------------------------------*/ + *allow_cn_step = 0; + move16(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ((st_fx->cng_cnt_fx == 0) && + GT_16(st_fx->lp_sp_enr_fx, 1536) && + (LT_16(add(st_lp_sp_enr, 1024 /* 4.0, Q8 */), sp_enr)) && + (st_fx->first_CNG_fx != 0) && + (st_fx->old_enr_index_fx >= 0) && + (GT_32(st_fx->last_core_brate_fx, SID_2k40))) || + EQ_16(force_cn_step, 1)) + { + *allow_cn_step = 1; + move16(); + } + test(); + IF( EQ_32(st_fx->core_brate_fx, SID_2k40)||EQ_32(st_fx->core_brate_fx,SID_1k75)) + { + /* LSF quantization */ + IF ( st_fx->Opt_AMR_WB_fx != 0 ) + { + isf_enc_amr_wb_fx( st_fx, lsf_new, lsp_new, 0, 0 ); + } + ELSE + { + lsf_enc_fx( st_fx, L_frame, INACTIVE, lsf_new, lsp_new, 0, 0, 0, 100, Q_new ); + } + /* Reset CNG history if CNG frame length is changed */ + test(); + test(); + if ( EQ_16(st_fx->bwidth_fx,WB)&&st_fx->first_CNG_fx!=0&&NE_16(st_fx->L_frame_fx,st_fx->last_CNG_L_frame_fx)) + { + st_fx->ho_hist_size_fx = 0; + move16(); + } + } + ELSE + { + /* Use old LSP vector */ + Copy( st_fx->lsp_old_fx, lsp_new, M ); + Copy( st_fx->lsf_old_fx, lsf_new, M ); + } + + /* Initialize the CNG spectral envelope in case of the very first CNG frame */ + IF( st_fx->first_CNG_fx == 0 ) + { + Copy( st_fx->lsp_old_fx, st_fx->lspCNG_fx, M ); + } + + /*---------------------------------------------------------------------* + * CNG spectral envelope update + * Find A(z) coefficients + *---------------------------------------------------------------------*/ + + IF( LE_32(st_fx->last_core_brate_fx, SID_2k40)) + { + /* Reset hangover counter if not first SID period */ + if( GT_32(st_fx->core_brate_fx,FRAME_NO_DATA)) + { + st_fx->num_ho_fx = 0; + move16(); + } + /* Update LSPs if last SID energy not outlier or insufficient number of hangover frames */ + test(); + IF( LT_16(st_fx->num_ho_fx,3)||LT_32(Mult_32_16(st_fx->Enew_fx,21845 /*1/1.5f, Q15*/), st_fx->lp_ener_fx)) + { + FOR( i=0; ilspCNG_fx[i] = mac_r(L_mult(CNG_ISF_FACT_FX,st_fx->lspCNG_fx[i]),32768-CNG_ISF_FACT_FX,lsp_new[i]); + move16(); /* Q15 (15+15+1-16) */ + } + } + } + ELSE + { + /* Update CNG_mode if allowed */ + test(); + test(); + test(); + IF( ( st_fx->Opt_AMR_WB_fx || EQ_16(st_fx->bwidth_fx,WB)) + && ( !st_fx->first_CNG_fx || GE_16(st_fx->act_cnt2_fx,MIN_ACT_CNG_UPD) ) ) + { + IF( GT_32(st_fx->last_active_brate_fx,ACELP_16k40)) + { + st_fx->CNG_mode_fx = -1; + move16(); + } + ELSE IF( GT_32(st_fx->last_active_brate_fx,ACELP_13k20)) + { + st_fx->CNG_mode_fx = 4; + move16(); + } + ELSE IF( GT_32(st_fx->last_active_brate_fx,ACELP_9k60)) + { + st_fx->CNG_mode_fx = 3; + move16(); + } + ELSE IF( GT_32(st_fx->last_active_brate_fx,ACELP_8k00)) + { + st_fx->CNG_mode_fx = 2; + move16(); + } + ELSE IF( GT_32(st_fx->last_active_brate_fx,ACELP_7k20)) + { + st_fx->CNG_mode_fx = 1; + move16(); + } + ELSE + { + st_fx->CNG_mode_fx = 0; + move16(); + } + } + + /* If first sid after active burst update LSF history from circ buffer */ + st_fx->act_cnt_fx = 0; + move16(); + s_ptr = add(sub(st_fx->ho_circ_ptr_fx,burst_ho_cnt),1); + + if( s_ptr < 0 ) + { + s_ptr = add(s_ptr, st_fx->ho_circ_size_fx); + } + + FOR( ll = burst_ho_cnt; ll > 0; ll-- ) + { + st_fx->ho_hist_ptr_fx = add(st_fx->ho_hist_ptr_fx,1); + if( EQ_16(st_fx->ho_hist_ptr_fx, HO_HIST_SIZE)) + { + st_fx->ho_hist_ptr_fx = 0; + move16(); + } + + /* Conversion between 12.8k and 16k LSPs */ + test(); + test(); + IF( EQ_16(L_frame,L_FRAME )&&EQ_16(st_fx->ho_16k_lsp_fx[s_ptr],1)) + { + /* Conversion from 16k LPSs to 12k8 */ + lsp_convert_poly_fx( &(st_fx->ho_lsp_circ_fx[s_ptr*M]), L_frame, 0 ); + } + ELSE IF ( EQ_16(L_frame,L_FRAME16k)&&st_fx->ho_16k_lsp_fx[s_ptr]==0) + { + /* 16k LSPs already converted and stored, just copy to the other buffer */ + Copy(&(st_fx->ho_lsp_circ2_fx[s_ptr*M]), &(st_fx->ho_lsp_circ_fx[s_ptr*M]), M ); + } + /* update the circular buffers */ + Copy(&(st_fx->ho_lsp_circ_fx[s_ptr*M]), &(st_fx->ho_lsp_hist_fx[st_fx->ho_hist_ptr_fx*M]), M ); + Copy32(&(st_fx->ho_ener_circ_fx[s_ptr]), &(st_fx->ho_ener_hist_fx[st_fx->ho_hist_ptr_fx]), 1 ); + st_fx->ho_sid_bw_fx = L_shl(L_and(st_fx->ho_sid_bw_fx, (Word32) 0x3fffffffL ), 1); + Copy32(&(st_fx->ho_env_circ_fx[s_ptr*NUM_ENV_CNG]), &(st_fx->ho_env_hist_fx[st_fx->ho_hist_ptr_fx*NUM_ENV_CNG]), NUM_ENV_CNG ); + + st_fx->ho_hist_size_fx = add(st_fx->ho_hist_size_fx,1); + if (GT_16(st_fx->ho_hist_size_fx, HO_HIST_SIZE)) + { + st_fx->ho_hist_size_fx = HO_HIST_SIZE; + move16(); + } + + s_ptr = add(s_ptr,1); + + if( EQ_16(s_ptr, st_fx->ho_circ_size_fx)) + { + s_ptr = 0; + move16(); + } + } + + IF ( burst_ho_cnt > 0) + { + /**allow_cn_step |= ( st_fx->ho_ener_hist_fx[st_fx->ho_hist_ptr_fx] > 4 * st_fx->lp_ener_fx ); */ + L_tmp1 = L_shr(st_fx->ho_ener_hist_fx[st_fx->ho_hist_ptr_fx],2); + L_tmp1 = L_sub(L_tmp1,st_fx->lp_ener_fx); + + if(L_tmp1>0) + { + *allow_cn_step = s_or(*allow_cn_step,1); + } + } + test(); + IF ( *allow_cn_step == 0 && st_fx->ho_hist_size_fx > 0 ) + { + /* Use average of energies below last energy */ + ptr = st_fx->ho_hist_ptr_fx; + move16(); + Copy( &(st_fx->ho_lsp_hist_fx[ptr*M]), tmp, M ); + m1 = 0; + move16(); + IF( L_and(st_fx->ho_sid_bw_fx, (Word32) 0x1) == 0 ) + { + Copy32( &st_fx->ho_env_hist_fx[ptr*NUM_ENV_CNG], tmp_env, NUM_ENV_CNG ); + m1 = 1; + move16(); + } + L_enr = Mult_32_16(st_fx->ho_ener_hist_fx[ptr],W_DTX_HO_FX[0]) ;/* Q6+15-15->Q6 */ + + weights = W_DTX_HO_FX[0]; /* Q15 */ + + m = 1; + move16(); + FOR( k=1; kho_hist_size_fx; k++ ) + { + ptr = sub(ptr,1); + if( ptr < 0 ) + { + ptr = HO_HIST_SIZE - 1; + move16(); + } + + test(); + IF ( LT_32(Mult_32_16(st_fx->ho_ener_hist_fx[ptr],ONE_OVER_BUF_H_NRG_FX),st_fx->ho_ener_hist_fx[st_fx->ho_hist_ptr_fx])&& + GT_32(st_fx->ho_ener_hist_fx[ptr],Mult_32_16(st_fx->ho_ener_hist_fx[st_fx->ho_hist_ptr_fx], BUF_L_NRG_FX)) ) + { + /*enr += W_DTX_HO[k] * st_fx->ho_ener_hist[ptr]; */ + L_tmp1 = Mult_32_16(st_fx->ho_ener_hist_fx[ptr],W_DTX_HO_FX[k]) ; /* Q6+15-15->Q6 */ + L_enr = L_add(L_enr,L_tmp1); /* Q6 */ + + /*weights += W_DTX_HO[k]; */ + weights = add( weights, W_DTX_HO_FX[k]); /* Q15 */ + + Copy( &st_fx->ho_lsp_hist_fx[ptr*M], &tmp[m*M], M ); + IF( L_and(st_fx->ho_sid_bw_fx, L_shl((Word32)0x1,k)) == 0 ) + { + Copy32( &st_fx->ho_env_hist_fx[ptr*NUM_ENV_CNG], &tmp_env[m1*NUM_ENV_CNG], NUM_ENV_CNG ); + m1 = add(m1,1); + } + m = add(m,1); + } + } + + /*enr /= weights; */ + exp = norm_s(weights); + tmp1 = div_s(shl(1,sub(14,exp)),weights); /* Q(15+14-exp-15) */ + L_tmp1 = Mult_32_16(L_enr,tmp1); /* Q(14-exp+6-15)->Q(5-exp) */ + L_enr = L_shl(L_tmp1,add(exp,1)); /* Q6 */ + + st_fx->lp_ener_fx = L_enr; + move32();/* Q6 */ + + set32_fx( max, 0, 2 ); + set16_fx( max_idx, 0, 2 ); + + FOR( i=0; iL_frame_fx,L_FRAME)) + { + lsp2lsf_fx( &tmp[i*M], lsf_tmp, M, INT_FS_FX ); + ftmp_fx = 964; + move16();/*QX2.56 */ + tmpv = sub(16384,add(lsf_tmp[M-1],ftmp_fx)); /*QX2.56 */ + L_tmp = L_mult0(tmpv,tmpv); /*QX6.5536 */ + } + ELSE + { + lsp2lsf_fx( &tmp[i*M], lsf_tmp, M, INT_FS_16k ); + ftmp_fx = 1205; + move16();/*QX2.56 */ + tmpv = sub(20480,add(lsf_tmp[M-1],ftmp_fx)); /*QX2.56 */ + L_tmp = L_mult0(tmpv,tmpv); /*QX6.5536 */ + } + + tmpv = sub(lsf_tmp[0],ftmp_fx); /*QX2.56 */ + L_tmp = L_mac0(L_tmp,tmpv,tmpv); /*QX6.5536 */ + FOR ( j=0; jlspCNG_fx[i] = lsp_tmp[i]; + move16(); /*Q15 */ + } + } + ELSE + { + FOR( i=0; ilspCNG_fx[i] = add(mult_r(26214,lsp_tmp[i]),mult_r(6554,lsp_new[i])); + move16(); + } + } + IF( m1 > 0 ) + { + FOR ( i=0; ilp_ener_fx; */ + IF(EQ_16(m1,1)) + { + L_tmp = L_sub(L_tmp,L_add(st_fx->lp_ener_fx,st_fx->lp_ener_fx)); + } + ELSE + { + tmp1 = div_s(1,m1); + L_tmp = Mult_32_16(L_tmp,tmp1); + L_tmp = L_sub(L_tmp,L_add(st_fx->lp_ener_fx,st_fx->lp_ener_fx)); + } + + env[i] = L_tmp; + move32(); + } + Copy32(env, st_fx->lp_env_fx, NUM_ENV_CNG); + } + } + ELSE + { + Copy( lsp_new, st_fx->lspCNG_fx, M ); /* use newly analyzed ISFs */ + } + } + IF ( st_fx->Opt_AMR_WB_fx != 0 ) + { + E_LPC_f_isp_a_conversion( st_fx->lspCNG_fx, Aq, M ); + } + ELSE + { + E_LPC_f_lsp_a_conversion( st_fx->lspCNG_fx, Aq, M ); /* Find A(z) (not interpolated) */ + } + + tmp_loop = shr(L_frame,6); + FOR( i=1; ibwidth_fx,NB)) + { + test(); + IF( EQ_16(st_fx->bwidth_fx,WB)&&st_fx->CNG_mode_fx>=0) + { + ftmp_fx = HO_ATT_FX[st_fx->CNG_mode_fx]; + } + ELSE + { + ftmp_fx = 19661; + move16(); + } + + att = mult(ftmp_fx,5461);/* Q15 */ + L_tmp = L_mult(att,8);/* Q16 */ + tmp1 = extract_l(L_shr(L_tmp,2));/* Q14 */ + tmp1 = add(16384,tmp1); + att = div_s(16374,tmp1); /* Q15 */ + + IF ( LT_16(att,ftmp_fx)) + { + att = ftmp_fx; + move16(); + } + + FOR( i = 0; i < st_fx->L_frame_fx; i++ ) + { + /*res1[i] *= att;*/ + res1[i] = mult(res1[i],att); + move16();/* Q_new */ + } + att = shr(att,7);/* Q8 */ + } + + /* calculate the spectrum of residual signal */ + Copy(res1, fft_io, st_fx->L_frame_fx); + + IF ( EQ_16(st_fx->L_frame_fx,L_FRAME16k)) + { + modify_Fs_fx( fft_io, L_FRAME16k, 16000, fft_io, 12800, exc_mem2,0); + } + + fft_rel_fx(fft_io, L_FFT, LOG2_L_FFT); + ptR = &fft_io[1]; + ptI = &fft_io[L_FFT-1]; + FOR ( i=0; icng_res_env_fx[(st_fx->cng_hist_ptr_fx)*NUM_ENV_CNG]), NUM_ENV_CNG ); + + /* calculate the residual signal energy */ + /*enr = dotp( res, res, L_frame ) / L_frame; */ + maxv = 0; + move16(); + FOR(i = 0; i < st_fx->L_frame_fx; i++) + { + maxv = s_max(maxv, abs_s(res[i])); + } + scale = norm_s(maxv); + pt_res = res; + L_ener = L_deposit_l(1); + IF( EQ_16(L_frame, L_FRAME)) + { + FOR (j=0; j<128; j++) + { + tmpv = shl(*pt_res,scale); + L_tmp = L_mult0(tmpv, tmpv); + pt_res++; + tmpv = shl(*pt_res,scale); + L_tmp = L_mac0(L_tmp, tmpv, tmpv); /* 2*(Q_new+scale) */ + pt_res++; + L_ener = L_add(L_ener, L_shr(L_tmp, 7)); /* 2*(Q_new+scale)+1, divide by L_frame done here */ + } + } + ELSE /* L_FRAME16k */ + { + FOR (j=0; j<160; j++) + { + tmpv = shl(*pt_res,scale); + L_tmp = L_mult0(tmpv, tmpv); + pt_res++; + tmpv = shl(*pt_res,scale); + L_tmp = L_mac0(L_tmp, tmpv, tmpv); /* 2*(Q_new+scale) */ + pt_res++; + L_ener = L_add(L_ener, L_shr(Mult_32_16(L_tmp,26214 /* 256/320, Q15 */), 7)); /* 2*(Q_new+scale)+15+1-16+1, divide by L_frame done here */ + } + } + /* convert log2 of residual signal energy */ + /*enr = (float)log10( enr + 0.1f ) / (float)log10( 2.0f ); */ + hi = norm_l(L_ener); + lo = Log2_norm_lc(L_shl(L_ener, hi)); + hi = sub(29, hi); /* log2 exp in Q2*(Q_new+scale) */ + hi = sub(hi, shl(add(Q_new,scale), 1)); /* Q0 */ + L_tmp = L_Comp(hi, lo); /* Q16 */ + enr = round_fx(L_shl(L_tmp, 8)); /* Q8 (16+8-16) */ + + /* update the circular buffer of old energies */ + st_fx->cng_ener_hist_fx[st_fx->cng_hist_ptr_fx] = enr; + move16(); /* Q8 */ + + /*-----------------------------------------------------------------* + * Quantize residual signal energy (only in SID frame) + *-----------------------------------------------------------------*/ + test(); + IF( EQ_32(st_fx->core_brate_fx, SID_2k40)||EQ_32(st_fx->core_brate_fx,SID_1k75)) + { + IF( GE_16(st_fx->cng_cnt_fx,sub(st_fx->cng_hist_size_fx,1))) + { + /* average the envelope except outliers */ + FOR ( i=0; icng_hist_size_fx; j++ ) + { + L_tmp1 = L_add(L_tmp1,st_fx->cng_res_env_fx[j*NUM_ENV_CNG+i]); + } + L_tmp = L_add(st_fx->cng_res_env_fx[max_idx1[0]*NUM_ENV_CNG+i],st_fx->cng_res_env_fx[max_idx1[1]*NUM_ENV_CNG+i]); + L_tmp1 = L_sub(L_tmp1,L_tmp); + + /* env[i] /= (float)(st_fx->cng_hist_size_fx - 2); */ + tmp1 = sub(st_fx->cng_hist_size_fx,2); + IF(GT_16(tmp1,1)) + { + tmp1 = div_s(1,tmp1); + L_tmp1 = Mult_32_16(L_tmp1,tmp1); + } + + env[i] = L_tmp1; + move32(); + } + /* compute average excitation energy */ + L_tmp = L_deposit_l(0); + ptr = st_fx->cng_hist_ptr_fx; + move16(); + + FOR (k=0; kcng_hist_size_fx; k++) + { + /* enr += W_HIST[k]*cng_ener_hist[ptr] */ + L_tmp = L_mac0(L_tmp, W_HIST_FX[k], st_fx->cng_ener_hist_fx[ptr]); /* Q24 (8+16) */ + ptr = sub(ptr, 1); + if (ptr < 0) /* check for circular pointer */ + { + ptr = DTX_HIST_SIZE - 1; + move16(); + } + } + /*----------------------------------------------------------- + * here we want to divide L_tmp by the sum + * of all the coefs used W_HIST[0..cng_hist_size-1] + * The table W_HIST_S already contains the inverted sum. + * That is + * W_HIST_S[k] 1 + * ------------- = --------------------------- + * 4096 W_HIST[0] + ... + W_HIST[k] + * + * 1 / Sum(W_HIST[0..k]) is always > 1 since the sum + * of the coefs 0..k is always < 1 but > 0 + * enr is in Q8 since the history buffer constains Q8 energies + *-----------------------------------------------------------*/ + /*L_tmp = Mpy_32_16_1(L_tmp, W_HIST_S_FX[k-1]); */ /* normalize average value */ + L_tmp = Mult_32_16(L_tmp, W_HIST_S_FX[k-1]); /* Q21 (24+12+1-16) */ + L_tmp = L_shl(L_tmp, 3); /* Q24 */ + enr = round_fx(L_tmp); /* Q8 */ + } + /* decrease the energy in case of WB input */ + IF( NE_16(st_fx->bwidth_fx, NB)) + { + IF( EQ_16(st_fx->bwidth_fx,WB)) + { + IF( st_fx->CNG_mode_fx >= 0 ) + { + /* Bitrate adapted attenuation */ + att = ENR_ATT_fx[st_fx->CNG_mode_fx]; + move16(); + } + ELSE + { + /* Use least attenuation for higher bitrates */ + att = ENR_ATT_fx[4]; + move16(); + } + } + ELSE + { + att = 384; + move16();/*Q8*/ + } + enr = sub(enr, att ); + } + /* intialize the energy quantization parameters */ + IF( st_fx->Opt_AMR_WB_fx == 0 ) + { + step = STEP_SID_FX; + move16(); + step_inv = ISTEP_SID_FX; + move16(); + maxl = 127; + move16(); + num_bits = 7; + move16(); + } + ELSE + { + step = STEP_AMR_WB_SID_FX; + move16(); + step_inv = ISTEP_AMR_WB_SID_FX; + move16(); + maxl = 63; + move16(); + num_bits = 6; + move16(); + } + + /* calculate the energy quantization index */ + enr_index = add(enr, 512 /* Q8(2.0) */); /* enr + 2.0 */ + enr_index = extract_l(L_shr(L_mult0(enr_index, step), 12+8)); /* Q0 (8+12-(8+12)) */ + + /* limit the energy quantization index */ + enr_index = s_min(enr_index, maxl); + enr_index = s_max(enr_index, 0); + + /* allow only slow energy increase */ + test(); + IF( st_fx->old_enr_index_fx >= 0 && GT_16(enr_index, add(st_fx->old_enr_index_fx, MAX_DELTA))) + { + IF( *allow_cn_step != 0 ) + { + tmp1 = mult(27853 /* Q15(0.85) */,sub(enr_index,st_fx->old_enr_index_fx)); + enr_index = add(st_fx->old_enr_index_fx,tmp1); + } + ELSE + { + enr_index = add(st_fx->old_enr_index_fx, MAX_DELTA); + } + } + st_fx->old_enr_index_fx = enr_index; + move16(); + + push_indice_fx( st_fx, IND_ENERGY, enr_index, num_bits ); + if ( enr_index == 0 ) + { + enr_index = -5; + move16(); + } + /* Find quantized energy */ + /* *Enew = (float)enr_index / step - 2.0 */ + /* *Enew = (float)pow(2.0, *Enew) */ + L_tmp = L_mult(enr_index, step_inv); /* Q16(0+15+1) */ + /* substract by 2 not done to leave Energy in Q2 */ + lo = L_Extract_lc(L_tmp, &hi); + st_fx->Enew_fx = Pow2(add(hi, 4), lo); /* Q6 */ + IF ( EQ_32(st_fx->core_brate_fx, SID_2k40)) + { + /* enr1 = (float)log10( st->Enew*L_frame + 0.1f ) / (float)log10( 2.0f );*/ + exp = norm_l(st_fx->Enew_fx); + L_tmp = L_shl(st_fx->Enew_fx,exp); /*Q(exp+6) */ + L_tmp = Mult_32_16(L_tmp,shl(L_frame,5));/* Q(exp+6+5-15=exp-4) */ + L_tmp = L_shr(L_tmp,sub(exp,10)); /* Q6 */ + + exp = norm_l(L_tmp); + fra = Log2_norm_lc(L_shl(L_tmp,exp)); + exp = sub(sub(30,exp),6); + L_tmp = L_Comp(exp,fra); + enr1 = L_shr(L_tmp,10);/* Q6 */ + + FOR ( i=0; iEnew;*/ + L_tmp1 = L_add(env[i], 0); + L_tmp = L_add(st_fx->Enew_fx,st_fx->Enew_fx); + L_tmp1 = L_sub(L_tmp1,L_tmp); /*Q6*/ + + IF ( L_tmp1 < 0 ) + { + L_tmp1 = L_deposit_l(6); /* (0.1)Q6 */ + } + /* env[i] = (float)log10( env[i] + 0.1f ) / (float)log10( 2.0f ); */ + exp = norm_l(L_tmp1); + fra = Log2_norm_lc(L_shl(L_tmp1,exp)); + exp = sub(sub(30,exp),6); + L_tmp = L_Comp(exp,fra); + L_tmp1 = L_shr(L_tmp,10); /* Q6 */ + + L_tmp = L_shr(L_deposit_l(att),2);/* Q6 */ + L_tmp1 = L_sub(L_tmp1,L_tmp); + + IF ( L_tmp1 < 0 ) + { + L_tmp1 = L_deposit_l(0); + } + + L_tmp1 = L_sub(enr1,L_tmp1); + + env[i] = L_tmp1; + move32(); + } + + /* codebook search */ + min1 = L_add(1310588928, 0); /* Q17 */ + min1_idx = 0; + move16(); + + FOR ( i=0; i<64; i++ ) + { + d = L_deposit_l(0); + FOR ( j=0; jEnew_fx,21845 /*1/1.5f, Q15*/), st_fx->lp_ener_fx)) + { + /* update the pointer to circular buffer of old LSP vectors */ + st_fx->ho_hist_ptr_fx = add(st_fx->ho_hist_ptr_fx, 1); + if( EQ_16(st_fx->ho_hist_ptr_fx,HO_HIST_SIZE)) + { + st_fx->ho_hist_ptr_fx = 0; + move16(); + } + + /* update the circular buffer of old LSP vectors with the new LSP vector */ + Copy( lsp_new, &(st_fx->ho_lsp_hist_fx[(st_fx->ho_hist_ptr_fx)*M]), M ); + + /* update the hangover energy buffer */ + st_fx->ho_ener_hist_fx[st_fx->ho_hist_ptr_fx] = st_fx->Enew_fx; + move32(); + IF ( EQ_32(st_fx->core_brate_fx, SID_2k40)) + { + FOR ( i=0; iEnew;*/ + L_tmp = L_sub(enr1,q_env[i]);/* Q6 */ + L_tmp = L_shl(L_tmp, 10);/* 16 */ + temp_lo_fx = L_Extract_lc(L_tmp, &temp_hi_fx); + + exp_pow = sub(14, temp_hi_fx); + L_tmp = Pow2(14, temp_lo_fx); /* Qexp_pow */ + env[i] = L_shl(L_tmp, sub(6, exp_pow)); + move32(); /* Q6 */ + L_tmp = L_add(st_fx->Enew_fx,st_fx->Enew_fx); + env[i] = L_add(env[i],L_tmp); + move32();/* Q6 */ + } + Copy32( env, &(st_fx->ho_env_hist_fx[(st_fx->ho_hist_ptr_fx)*NUM_ENV_CNG]), NUM_ENV_CNG ); + } + st_fx->ho_hist_size_fx = add(st_fx->ho_hist_size_fx,1); + if( GT_16(st_fx->ho_hist_size_fx,HO_HIST_SIZE)) + { + st_fx->ho_hist_size_fx = HO_HIST_SIZE; + move16(); + } + } + } + /* dithering bit for AMR-WB IO mode is always set to 0 */ + IF( EQ_32(st_fx->core_brate_fx, SID_1k75)) + { + push_indice_fx( st_fx, IND_DITHERING, 0, 1 ); + } + IF ( EQ_32(st_fx->core_brate_fx, SID_2k40)) + { + IF(EQ_16(st_fx->L_frame_fx, L_FRAME16k)) + { + push_indice_fx( st_fx, IND_ACELP_16KHZ, 1, 1 ); + } + ELSE + { + push_indice_fx( st_fx, IND_ACELP_16KHZ, 0, 1 ); + } + } + + IF ( EQ_32(st_fx->core_brate_fx, SID_2k40)) + { + push_indice_fx( st_fx, IND_CNG_HO, s_min(st_fx->burst_ho_cnt_fx, 7 ), 3 ); + st_fx->num_ho_fx = m; + move16(); + push_indice_fx( st_fx, IND_SID_TYPE, 0, 1 ); + + IF ( LT_32(st_fx->input_Fs_fx, 32000)) + { + push_indice_fx( st_fx, IND_SID_BW, 0, 1 ); + *sid_bw = 0; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Updates + *-----------------------------------------------------------------*/ + /* update the SID frames counter */ + test(); + IF( EQ_32(st_fx->core_brate_fx, SID_2k40)||EQ_32(st_fx->core_brate_fx,SID_1k75)) + { + st_fx->cng_cnt_fx = 0; + move16(); + st_fx->cng_hist_ptr_fx = -1; + move16(); + /* update frame length memory */ + st_fx->last_CNG_L_frame_fx = st_fx->L_frame_fx; + move16(); + } + ELSE + { + st_fx->cng_cnt_fx = add(st_fx->cng_cnt_fx,1); + } + + return; +} +/*---------------------------------------------------------------------* + * swb_CNG_enc() + * + * SWB DTX/CNG encoding + *---------------------------------------------------------------------*/ +void swb_CNG_enc_fx( + Encoder_State_fx *st_fx, /* i/o: State structure */ + const Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz (Q0) */ + const Word16 *syn_12k8_16k_fx /* i : ACELP core synthesis at 12.8kHz or 16kHz (st_fx->Q_syn = 0) */ +) +{ + Word16 shb_SID_updt_fx=0; + + test(); + IF ( EQ_32(st_fx->core_brate_fx, SID_2k40)||st_fx->core_brate_fx==FRAME_NO_DATA) + { + IF (EQ_16(st_fx->cng_type_fx,LP_CNG)) + { + /* decide if SHB SID encoding or not */ + shb_SID_updt_fx = shb_DTX_fx( st_fx, shb_speech_fx, syn_12k8_16k_fx ); + + /* SHB CNG encoding */ + shb_CNG_encod_fx( st_fx, shb_SID_updt_fx ); + } + st_fx->last_vad_fx = 0; + move16(); + } + ELSE + { + st_fx->last_vad_fx = 1; + move16(); + } + + return; +} + +/*---------------------------------------------------------------------* + * shb_CNG_encod() + * + * SID parameters encoding for SHB signal + *---------------------------------------------------------------------*/ +static void shb_CNG_encod_fx( + Encoder_State_fx *st_fx, /* i/o: State structure */ + const Word16 update_fx /* i : SID update flag */ +) +{ + Word16 idx_ener_fx; + + idx_ener_fx = 0; + move16(); + IF ( EQ_16(update_fx, 1)) + { + /* SHB energy quantization */ + idx_ener_fx = shr(add(mult(st_fx->mov_shb_cng_ener_fx, 9797), 1510), 8); /* Q0 */ + + if ( LT_16(st_fx->bwidth_fx, SWB)) + { + idx_ener_fx = 0; + move16(); + } + + IF ( GT_16(idx_ener_fx, 15)) + { + idx_ener_fx = 15; + move16(); + } + ELSE + { + idx_ener_fx = s_max(idx_ener_fx,0); + } + + push_indice_fx( st_fx, IND_SHB_CNG_GAIN, idx_ener_fx, 4); + push_indice_fx( st_fx, IND_SID_BW, 1, 1 ); + st_fx->nb_bits_tot_fx = sub(st_fx->nb_bits_tot_fx,st_fx->ind_list_fx[IND_CNG_ENV1].nb_bits); + st_fx->ind_list_fx[IND_CNG_ENV1].nb_bits = -1; + move16(); + push_indice_fx( st_fx, IND_UNUSED, 0, 2); + st_fx->ho_sid_bw_fx = L_shl(L_and(st_fx->ho_sid_bw_fx, (Word32) 0x3fffffffL ), 1); + st_fx->ho_sid_bw_fx = L_or(st_fx->ho_sid_bw_fx, 0x1L); + } + ELSE + { + IF ( EQ_32(st_fx->core_brate_fx, SID_2k40)) + { + st_fx->ho_sid_bw_fx = L_shl(L_and(st_fx->ho_sid_bw_fx, (Word32) 0x3fffffffL ), 1); + push_indice_fx( st_fx, IND_SID_BW, 0, 1 ); + } + } + + return; +} + +/*---------------------------------------------------------------------* +* shb_DTX() +* +* Decide if encoding SHB SID or not +*---------------------------------------------------------------------*/ +static Word16 shb_DTX_fx( + Encoder_State_fx *st_fx, /* i/o: State structure */ + const Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz (Q0) */ + const Word16 *syn_12k8_16k /* i : ACELP core synthesis at 12.8kHz or 16kHz (st_fx->Q_syn = 0) */ +) +{ + Word16 i; + Word16 update_fx; + Word16 shb_old_speech_fx[(ACELP_LOOK_12k8 + L_SUBFR + L_FRAME) * 5/4]; + Word16 *shb_new_speech_fx; + Word32 wb_ener_fx; + Word32 shb_ener_fx; + Word16 log_wb_ener_fx; + Word16 log_shb_ener_fx; + Word16 tmp; + Word16 exp; + Word16 fra; + Word16 allow_cn_step_fx=0; + + shb_new_speech_fx = shb_old_speech_fx + (ACELP_LOOK_12k8 + L_SUBFR) * 5/4; + Copy( st_fx->old_speech_shb_fx, shb_old_speech_fx, (ACELP_LOOK_12k8 + L_SUBFR) * 5/4 ); + Copy( shb_speech_fx, shb_new_speech_fx, L_FRAME16k ); + Copy( shb_old_speech_fx + L_FRAME16k, st_fx->old_speech_shb_fx, (ACELP_LOOK_12k8 + L_SUBFR) * 5/4 ); + + shb_ener_fx = L_deposit_l(0); + FOR ( i=0; iL_frame_fx; i++ ) + { + wb_ener_fx = L_mac(wb_ener_fx, syn_12k8_16k[i], syn_12k8_16k[i]); + } + + wb_ener_fx = L_add(Mpy_32_16_1(wb_ener_fx, 128), 1); /* 128 in Q15, wb_ener_fx in Q1 */ + + exp = norm_l(wb_ener_fx); + fra = Log2_norm_lc(L_shl(wb_ener_fx, exp)); + exp = sub(30-1, exp); + wb_ener_fx = Mpy_32_16(exp, fra, LG10); + log_wb_ener_fx = round_fx(L_shl(wb_ener_fx, 10)); /* log_wb_ener_fx in Q8 */ + + exp = norm_l(shb_ener_fx); + fra = Log2_norm_lc(L_shl(shb_ener_fx, exp)); + exp = sub(30-1, exp); + shb_ener_fx = Mpy_32_16(exp, fra, LG10); + log_shb_ener_fx = sub(round_fx(L_shl(shb_ener_fx, 10)), 1664); /* log_shb_ener_fx in Q8 */ + + IF ( st_fx->first_CNG_fx == 0 ) + { + st_fx->mov_wb_cng_ener_fx = log_wb_ener_fx; + move16(); + st_fx->mov_shb_cng_ener_fx = log_shb_ener_fx; + move16(); + st_fx->last_wb_cng_ener_fx = log_wb_ener_fx; + move16(); + st_fx->last_shb_cng_ener_fx = log_shb_ener_fx; + move16(); + } + + if ( GT_16(abs_s(sub(log_wb_ener_fx, st_fx->mov_wb_cng_ener_fx)), 3072)) + { + allow_cn_step_fx = 1; + move16(); + } + + IF ( EQ_16(allow_cn_step_fx, 1)) + { + st_fx->mov_wb_cng_ener_fx = log_wb_ener_fx; + move16(); + st_fx->mov_shb_cng_ener_fx = log_shb_ener_fx; + move16(); + } + ELSE + { + tmp = sub(log_wb_ener_fx, st_fx->mov_wb_cng_ener_fx); /* Q8 */ + tmp = mult(tmp, 29491); /* Q8 */ + st_fx->mov_wb_cng_ener_fx = add(st_fx->mov_wb_cng_ener_fx, tmp); /* Q8 */ + + tmp = sub(log_shb_ener_fx, st_fx->mov_shb_cng_ener_fx); + tmp = mult(tmp, 8192); /* Q8 */ + st_fx->mov_shb_cng_ener_fx = add(st_fx->mov_shb_cng_ener_fx, tmp); /* Q8 */ + } + st_fx->shb_NO_DATA_cnt_fx = add(st_fx->shb_NO_DATA_cnt_fx, 1); + + update_fx = 0; + move16(); + IF ( EQ_32(st_fx->core_brate_fx, SID_2k40)) + { + test(); + test(); + IF ( st_fx->first_CNG_fx == 0 || EQ_16(st_fx->last_vad_fx, 1)||GE_16(st_fx->shb_NO_DATA_cnt_fx,100)) + { + update_fx = 1; + move16(); + } + ELSE + { + IF ( st_fx->shb_cng_ini_cnt_fx > 0 ) + { + update_fx = 1; + move16(); + st_fx->shb_cng_ini_cnt_fx = sub(st_fx->shb_cng_ini_cnt_fx, 1); + } + ELSE + { + IF ( GT_16(abs_s(sub(sub(st_fx->mov_wb_cng_ener_fx, st_fx->mov_shb_cng_ener_fx), sub(st_fx->last_wb_cng_ener_fx, st_fx->last_shb_cng_ener_fx))), 768)) + { + update_fx = 1; + move16(); + } + ELSE + { + test(); + IF ( GE_16(st_fx->bwidth_fx, SWB)&<_16(st_fx->last_SID_bwidth_fx,SWB)) + { + update_fx = 1; + move16(); + } + ELSE + { + test(); + IF ( LT_16(st_fx->bwidth_fx, SWB)&&GE_16(st_fx->last_SID_bwidth_fx,SWB)) + { + update_fx = 1; + move16(); + } + } + } + } + } + + st_fx->last_SID_bwidth_fx = st_fx->bwidth_fx; + move16(); + } + + IF ( EQ_16(update_fx, 1)) + { + st_fx->last_wb_cng_ener_fx = st_fx->mov_wb_cng_ener_fx; + move16(); + st_fx->last_shb_cng_ener_fx = st_fx->mov_shb_cng_ener_fx; + move16(); + st_fx->shb_NO_DATA_cnt_fx = 0; + move16(); + } + + + return (update_fx); +} diff --git a/lib_enc/cod2t32_fx.c b/lib_enc/cod2t32_fx.c new file mode 100644 index 0000000..588a00a --- /dev/null +++ b/lib_enc/cod2t32_fx.c @@ -0,0 +1,383 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + + +/*-------------------------------------------------------------------* +* Local Constants +*-------------------------------------------------------------------*/ + +#define STEP 2 +#define MSIZE 1024 + +/*---------------------------------------------------------------------------------- +* Function acelp_2t32() +* +* 12 bits algebraic codebook. +* 2 tracks x 32 positions per track = 64 samples. +* +* 12 bits --> 2 pulses in a frame of 64 samples. +* +* All pulses can have two (2) possible amplitudes: +1 or -1. +* Each pulse can have 32 possible positions. +*----------------------------------------------------------------------------------*/ + +void acelp_2t32_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 dn[], /* i : corr. between target and h[]. */ + const Word16 h[], /* i : impulse response of weighted synthesis filter */ + Word16 code[], /* o : algebraic (fixed) codebook excitation */ + Word16 y[] /* o : filtered fixed codebook excitation */ +) +{ + Word16 i, j, k, i0, i1, ix, iy, pos, pos2, sign0, sign1,index; + Word16 ps1, ps2, alpk, alp1, alp2; + Word16 sq,psk; + Word16 pol[L_SUBFR], dn_p[L_SUBFR]; + Word16 ii,jj; + Word16 *p0, *p1, *p2; + const Word16 *ptr_h1, *ptr_h2, *ptr_hf; + + Word32 s, L_cor; + Word32 L_tmp; + Word16 rrixix[NB_TRACK_FCB_2T][NB_POS_FCB_2T]; + Word16 rrixiy[MSIZE]; + + /*----------------------------------------------------------------* + * Compute rrixix[][] needed for the codebook search. + *----------------------------------------------------------------*/ + + /* Init pointers to last position of rrixix[] */ + p0 = &rrixix[0][NB_POS_FCB_2T - 1]; + move16(); + p1 = &rrixix[1][NB_POS_FCB_2T - 1]; + move16(); + + ptr_h1 = h; + move16(); + L_cor = L_deposit_h(1); + FOR (i = 0; i < NB_POS_FCB_2T; i++) + { + L_cor = L_mac(L_cor, *ptr_h1, *ptr_h1); + ptr_h1++; + *p1-- = extract_h(L_cor); + move16(); /*Q9 Q7*/ + L_cor = L_mac(L_cor, *ptr_h1, *ptr_h1); + ptr_h1++; + *p0-- = extract_h(L_cor); + move16(); /*Q9 Q7*/ + } + + p0 = rrixix[0]; + move16(); + p1 = rrixix[1]; + move16(); + + FOR (i = 0; i < NB_POS_FCB_2T; i++) + { + *p0 = shr(*p0, 1); + move16(); + p0++; + *p1 = shr(*p1, 1); + move16(); + p1++; + } + + /*------------------------------------------------------------* + * Compute rrixiy[][] needed for the codebook search. + *------------------------------------------------------------*/ + + pos = MSIZE - 1; + move16(); + pos2 = MSIZE - 2; + move16(); + ptr_hf = h + 1; + move16(); + + FOR (k = 0; k < NB_POS_FCB_2T; k++) + { + /* Init pointers to last position of diagonals */ + p1 = &rrixiy[pos]; + move16(); + p0 = &rrixiy[pos2]; + move16(); + + ptr_h1 = h; + move16(); + ptr_h2 = ptr_hf; + move16(); + + L_cor = L_mult(*ptr_h1++, *ptr_h2++); + FOR (i = k; i < NB_POS_FCB_2T-1; i++) + { + *p1 = round_fx(L_cor); + L_cor = L_mac(L_cor, *ptr_h1++, *ptr_h2++); + *p0 = round_fx(L_cor); + L_cor = L_mac(L_cor, *ptr_h1++, *ptr_h2++); + + p1 -= (NB_POS_FCB_2T + 1); + move16(); + p0 -= (NB_POS_FCB_2T + 1); + move16(); + } + + *p1 = round_fx(L_cor); + + pos -= NB_POS_FCB_2T; + move16(); + pos2--; + ptr_hf += STEP; + move16(); + } + + /*----------------------------------------------------------------* + * computing reference vector and pre-selection of polarities + *----------------------------------------------------------------*/ + + L_tmp = L_deposit_h(dn[0]); + FOR(i=0; i=0) + { + pol[i] = 1; + move16(); + dn_p[i] = dn[i]; + move16(); + } + ELSE + { + pol[i] = -1; + move16(); + dn_p[i] = negate(dn[i]); + move16(); + } + } + + /*----------------------------------------------------------------* + * compute denominator ( multiplied by polarity ) + *----------------------------------------------------------------*/ + + k=0; + ii=0; + move16(); + move16(); + FOR(i=0; i 0) + { + psk = sq; + move16(); + alpk = alp2; + move16(); + pos = i1; + move16(); + } + } + p1 -= NB_POS_FCB_2T; + move16(); + + IF (pos >= 0) + { + ix = i0; + move16(); + iy = pos; + move16(); + } + } + + i0 = shr(ix,1); + i1 = shr(iy,1); + + sign0 = shl(pol[ix],9); + sign1 = shl(pol[iy],9); + + /*-------------------------------------------------------------------* + * Build the codeword, the filtered codeword and index of codevector. + *-------------------------------------------------------------------*/ + + set16_fx( code, 0, L_SUBFR ); + + code[ix] = sign0; + move16(); + code[iy] = sign1; + move16(); + + index = add(shl(i0, 6), i1); + + + if (sign0 < 0) + { + index = add(index, 0x800); + } + if (sign1 < 0) + { + index = add(index, 0x20); /* move16();*/ + } + + set16_fx( y, 0, L_SUBFR ); + /* y_Q9 = sign_Q9<<3 * h_Q12 */ + + sign0 = shl(sign0, 3); + sign1 = shl(sign1, 3); + + FOR(i=ix; i0) + { + y[i] = shr_r(h[i-pos],3); + move16(); + } + ELSE + { + y[i] = negate(shr_r(h[i-pos],3)); + move16(); + } + } + + index = pos; + move16(); + if( sgn > 0 ) + { + index = add(index,L_SUBFR); + } + { + push_indice_fx( st_fx, IND_ALG_CDBK_1T64, index, 7 ); + } + + return; +} diff --git a/lib_enc/cod4t64_fx.c b/lib_enc/cod4t64_fx.c new file mode 100644 index 0000000..3008aaf --- /dev/null +++ b/lib_enc/cod4t64_fx.c @@ -0,0 +1,1167 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* VMR-WB compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_enc_fx.h" /* Encoder static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" + + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define STEP 4 +#define MSIZE 256 +#define NB_MAX 8 + +/*-------------------------------------------------------------------* + * Local function prototypes + *-------------------------------------------------------------------*/ +static Word16 quant_1p_N1_fx(const Word16 pos,const Word16 N); +static Word16 quant_2p_2N1_fx(const Word16 pos1, const Word16 pos2, const Word16 N); +static Word16 quant_3p_3N1_fx( const Word16 pos1, const Word16 pos2, const Word16 pos3, const Word16 N ); +static Word32 quant_4p_4N_fx( const Word16 pos[], const Word16 N ); +static Word32 quant_5p_5N_fx( const Word16 pos[], const Word16 N ); +static Word32 quant_6p_6N_2_fx( const Word16 pos[], const Word16 N ); + + + +static Word32 fcb_encode_position_fx(Word16 pos_vector[],Word32 n,Word32 pos_num,Word32 flag); +static Word32 fcb_encode_class_fx(Word32 sector_6p_num[],Word32 pulse_num,Word32 pulse_pos_num); +static Word32 fcb_encode_PI_fx(const Word16 v[], Word32 pulse_num); +static Word32 pre_process_fx( const Word16 v[], Word16 sector_6p[], Word32 sector_6p_num[], Word32 *pulse_pos_num ); + +/*---------------------------------------------------------------------* + * ACELP_4t64() + * + * 20, 36, 44, 52, 64, 72, 88 bits algebraic codebook. + * 4 tracks x 16 positions per track = 64 samples. + * + * 20 bits --> 4 pulses in a frame of 64 samples. + * 36 bits --> 8 pulses in a frame of 64 samples. + * 44 bits 13 + 9 + 13 + 9 --> 10 pulses in a frame of 64 samples. + * 52 bits 13 + 13 + 13 + 13 --> 12 pulses in a frame of 64 samples. + * 64 bits 2 + 2 + 2 + 2 + 14 + 14 + 14 + 14 --> + * 16 pulses in a frame of 64 samples. + * 72 bits 10 + 2 + 10 + 2 + 10 + 14 + 10 + 14 --> + * 18 pulses in a frame of 64 samples. + * 88 bits 11 + 11 + 11 + 11 + 11 + 11 + 11 + 11 --> + * 24 pulses in a frame of 64 samples. + * All pulses can have two (2) possible amplitudes: +1 or -1. + * Each pulse can have sixteen (16) possible positions. + *---------------------------------------------------------------------*/ + +Word16 acelp_4t64_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 dn[], /* i : corr. between target and h[]. */ + const Word16 cn[], /* i : residual after long term prediction Q_new*/ + const Word16 H[], /* i : impulse response of weighted synthesis filter Q12*/ + Word16 R[], /* i : autocorrelation values */ + const Word16 acelpautoc, /* i : autocorrealtion flag */ + Word16 code[], /* o : algebraic (fixed) codebook excitation Q9*/ + Word16 y[], /* o : filtered fixed codebook excitation Q9*/ + Word16 nbbits, /* i : number of bits per codebook */ + const Word16 cmpl_flag, /* i : complexity reduction flag */ + const Word16 Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */ +) +{ + + Word16 i, k, index, track; + Word32 L_index; + Word16 ind[NPMAXPT*NB_TRACK_FCB_4T+32]; /* VE3: why +32 ???*/ + Word16 codvec[NB_PULSE_MAX+4]= {0}; + Word16 saved_bits = 0; + + PulseConfig config; + Word16 indexing_indices[6], wordcnt, bitcnt; + + set16_fx(codvec, 0, NB_PULSE_MAX+4); + SWITCH (nbbits) + { + + case 20: /* EVS/AMR-WB pulse indexing: 20 bits, 4 pulses, 4 tracks */ + config.nbiter = 4; + move16(); /* 4x12x16=768 loop */ + config.alp = 16384; + move16(); /* 2 in Q13*/ + config.nb_pulse = 4; + move16(); + config.fixedpulses = 0; + move16(); + config.nbpos[0] = 4; + move16(); + config.nbpos[1] = 8; + move16(); + BREAK; + + case 28: /* EVS pulse indexing: 28 bits, 6 pulses, 4 tracks */ + config.nbiter = 4; + move16(); /* 4x20x16=1280 loops */ + config.alp = 8192; + move16(); /* coeff FOR sign setting */ + config.nb_pulse = 6; + move16(); + config.fixedpulses = 0; + move16(); + config.nbpos[0] = 6; + move16(); + config.nbpos[1] = 6; + move16(); + config.nbpos[2] = 8; + move16(); + BREAK; + + case 36: /* EVS/AMR-WB pulse indexing: 36 bits, 8 pulses, 4 tracks */ + config.nbiter = 4; + move16(); /* 4x20x16=1280 loops */ + config.alp = 8192; + move16(); /* coeff FOR sign setting */ + config.nb_pulse = 8; + move16(); + config.fixedpulses = 2; + move16(); + config.nbpos[0] = 4; + move16(); + config.nbpos[1] = 8; + move16(); + config.nbpos[2] = 8; + move16(); + BREAK; + + case 43: /* EVS pulse indexing: 43 bits, 10 pulses, 4 tracks */ + case 44: /* AMR-WB pulse indexing: 44 bits, 10 pulses, 4 tracks */ + config.nbiter = 4; + move16(); /* 4x26x16=1664 loops */ + config.alp = 8192; + move16(); + config.nb_pulse = 10; + move16(); + config.fixedpulses = 2; + move16(); + config.nbpos[0] = 4; + move16(); + config.nbpos[1] = 6; + move16(); + config.nbpos[2] = 8; + move16(); + config.nbpos[3] = 8; + move16(); + BREAK; + + case 50: /* EVS pulse indexing: 50 bits, 12 pulses, 4 tracks */ + case 52: /* AMR-WB pulse indexing: 52 bits, 12 pulses, 4 tracks */ + config.nbiter = 4; + move16(); /* 4x26x16=1664 loops */ + config.alp = 8192; + move16(); + config.nb_pulse = 12; + move16(); + config.fixedpulses = 4; + move16(); + config.nbpos[0] = 4; + move16(); + config.nbpos[1] = 6; + move16(); + config.nbpos[2] = 8; + move16(); + config.nbpos[3] = 8; + move16(); + BREAK; + + case 62: /* EVS pulse indexing: 62 bits, 16 pulses, 4 tracks */ + case 64: /* AMR-WB pulse indexing: 64 bits, 16 pulses, 4 tracks */ + config.nbiter = 3; + move16(); /* 3x36x16=1728 loops */ + config.alp = 6554; + move16(); + config.nb_pulse = 16; + move16(); + config.fixedpulses = 4; + move16(); + config.nbpos[0] = 4; + move16(); + config.nbpos[1] = 4; + move16(); + config.nbpos[2] = 6; + move16(); + config.nbpos[3] = 6; + move16(); + config.nbpos[4] = 8; + move16(); + config.nbpos[5] = 8; + move16(); + BREAK; + + case 72: /* AMR-WB pulse indexing: 72 bits, 18 pulses, 4 tracks */ + config.nbiter = 3; + move16(); /* 3x35x16=1680 loops */ + config.alp = 6144; + move16(); + config.nb_pulse = 18; + move16(); + config.fixedpulses = 4; + move16(); + config.nbpos[0] = 2; + move16(); + config.nbpos[1] = 3; + move16(); + config.nbpos[2] = 4; + move16(); + config.nbpos[3] = 5; + move16(); + config.nbpos[4] = 6; + move16(); + config.nbpos[5] = 7; + move16(); + config.nbpos[6] = 8; + move16(); + BREAK; + + case 88: /* AMR-WB pulse indexing: 88 bits, 24 pulses, 4 tracks */ + config.nbiter = 2; + move16(); /* 2x53x16=1696 loop */ + config.alp = 4096; + move16(); + config.nb_pulse = 24; + move16(); + config.fixedpulses = 4; + move16(); + config.nbpos[0] = 2; + move16(); + config.nbpos[1] = 2; + move16(); + config.nbpos[2] = 3; + move16(); + config.nbpos[3] = 4; + move16(); + config.nbpos[4] = 5; + move16(); + config.nbpos[5] = 6; + move16(); + config.nbpos[6] = 7; + move16(); + config.nbpos[7] = 8; + move16(); + config.nbpos[8] = 8; + move16(); + config.nbpos[9] = 8; + move16(); + BREAK; + + case 87: /* EVS pulse indexing: 87 bits, 26 pulses, 4 tracks */ + config.nbiter = 1; + move16(); + config.alp = 4096; + move16(); + config.nb_pulse = 26; + move16(); + config.fixedpulses = 4; + move16(); + config.nbpos[0] = 4; + move16(); + config.nbpos[1] = 6; + move16(); + config.nbpos[2] = 6; + move16(); + config.nbpos[3] = 8; + move16(); + config.nbpos[4] = 8; + move16(); + config.nbpos[5] = 8; + move16(); + config.nbpos[6] = 8; + move16(); + config.nbpos[7] = 8; + move16(); + config.nbpos[8] = 8; + move16(); + config.nbpos[9] = 8; + move16(); + config.nbpos[10] = 8; + move16(); + BREAK; + } + + /* reduce the number of iterations as a compromise between the performance and complexity */ + if( cmpl_flag > 0 ) + { + config.nbiter = cmpl_flag; + move16(); + } + + config.codetrackpos = TRACKPOS_FIXED_FIRST; + move16(); + config.bits = nbbits; + move16(); + + IF (acelpautoc) + { + E_ACELP_4tsearchx( dn, cn, R, code, &config, ind ); + + /* Generate weighted code */ + E_ACELP_weighted_code(code, H, 12, y); + } + ELSE + { + E_ACELP_4tsearch(dn, cn, H, code, &config, ind, y); + + FOR(i=0; i it doesn't need to be operated by Basic Operators */ + + n_1 = (Word16) (N - 1); + move16(); + nb_pos = shl(1, n_1); /* nb_pos = (1< 1, Q0 */ + IF (v[k]>0) + { + sign = L_shl(sign, 1); + } + ELSE + { + sign = L_add(L_shl( sign, 1), 1); + } + j =add(j, 1); + } + } + *pulse_pos_num = L_deposit_l(j); + + return sign; +} + + +/*--------------------------------------------------------------------------* +* E_ACELP_code43bit +* +* Fixed bit-length arithmetic coding of pulses +* v - (input) pulse vector +* s - (output) encoded state +* n - (output) range of possible states (0...n-1) +* p - (output) number of pulses found +* len - (input) length of pulse vector +* trackstep - (input) step between tracks +*--------------------------------------------------------------------------*/ + +Word16 E_ACELP_code43bit(const Word16 code[], UWord32 *ps, Word16 *p, UWord16 idxs[]) +{ + Word16 i,j,k,track; + Word16 ind[32]; + + Word16 tmp; + Word32 L_tmp; + Word32 joint_index; + static const Word32 joint_offset = 3611648; /*offset for 3 pulses per track*/ + Word16 saved_bits = 0; + + FOR (track = 0; track < 2; track++) + { + ps[track] = fcb_encode_PI_fx(code+track, 3); + move32(); + p[track] = 3; + move16(); + } + + FOR (track = 2; track < NB_TRACK_FCB_4T; track++) + { + i = j = i_mult2(track, NPMAXPT); + move16(); + FOR (k = track; k < 64; k += 4) + { + IF (code[k]) + { + tmp = shr(k, 2); + if (code[k] < 0) + { + tmp = add(tmp, 16); + } + ind[j] = tmp; + move16(); + IF (GT_16(abs_s(code[k]), 512)) + { + ind[j + 1] = tmp; + move16(); + BREAK; + } + j = add(j, 1); + } + } + ps[track] = quant_2p_2N1_fx(ind[i], ind[i+1], 4); + move32(); + p[track] = 2; + move16(); + } + /* joint_index = ps[0]*5472 + ps[1]; */ + L_tmp = L_shl(ps[0], 12); + L_tmp = L_add(L_tmp, L_shl(ps[0], 10)); + L_tmp = L_add(L_tmp, L_shl(ps[0], 8)); + L_tmp = L_add(L_tmp, L_shl(ps[0], 6)); + L_tmp = L_add(L_tmp, L_shl(ps[0], 5)); + joint_index = L_add(L_tmp, ps[1]); + L_tmp = L_sub(joint_index, joint_offset); + if (L_tmp >= 0) + { + joint_index = L_add(joint_index, joint_offset); + } + if (L_tmp < 0) + { + saved_bits = add(saved_bits, 1); + } + idxs[0] = extract_l(L_add(L_shl(ps[2], 9), ps[3])); + idxs[1] = extract_l(L_add(L_shl(joint_index, 2), L_shr(ps[2], 7))); + idxs[2] = extract_l(L_shr(joint_index, 14)); + + return saved_bits; +} diff --git a/lib_enc/cod_ace.c b/lib_enc/cod_ace.c new file mode 100644 index 0000000..3d8137b --- /dev/null +++ b/lib_enc/cod_ace.c @@ -0,0 +1,606 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "prot_fx.h" +#include "basop_util.h" +#include "options.h" +#include "stl.h" + +#include "rom_basop_util.h" + +/*-------------------------------------------------------------------* + * coder_acelp() + * + * Encode ACELP frame + *-------------------------------------------------------------------*/ + +Word16 coder_acelp( /* output SEGSNR for CL decision */ + ACELP_config *acelp_cfg, /*input/output: configuration of the ACELP coding*/ + const Word16 coder_type, /* input: coding type */ + const Word16 A[], /* input: coefficients 4xAz[M+1] */ + const Word16 Aq[], /* input: coefficients 4xAz_q[M+1] */ + Word16 speech[], /* input: speech[-M..lg] */ + Word16 synth[], + LPD_state *LPDmem, + const Word16 voicing[], /* input: open-loop LTP gain */ + const Word16 T_op[], /* input: open-loop LTP lag */ + Word16 *prm, /* output: acelp parameters */ + Word16 stab_fac, + Encoder_State_fx *st, + HANDLE_PLC_ENC_EVS hPlc_Ext, + Word16 target_bits, /* i/o : coder memory state */ + Word16 Q_new, + Word16 shift + ,Word16 *pitch_buf /* output : pitch values for each subfr.*/ + ,Word16 *voice_factors /* output : voicing factors */ + ,Word16 *bwe_exc /* output : excitation for SWB TBE */ +) +{ + Word16 i, j, i_subfr, j_subfr; + Word16 T0, T0_min, T0_min_frac, T0_max, T0_max_frac, T0_res; + Word16 T0_frac; + Word16 tmp, tmp2, Es_pred; + Word16 gain_pit, voice_fac; + Word32 gain_code, Ltmp, Ltmp2; + ACELP_CbkCorr g_corr; + const Word16 *p_A, *p_Aq; + Word16 h1[L_SUBFR]; /* weighted impulse response of LP */ + Word16 code[L_SUBFR]; + Word16 xn_exp; + Word16 Q_xn; + Word16 Q_new_p5; + Word16 cn[L_SUBFR]; + Word16 xn[L_SUBFR]; + Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */ + Word16 y2[L_SUBFR]; /* Filtered adaptive excitation */ + Word16 res_save; + Word16 exc_buf[L_EXC_MEM+L_DIV_MAX+1], *exc; + Word16 exc2[L_SUBFR]; + Word16 *syn,syn_buf[M+L_DIV_MAX+L_DIV_MAX/2]; /*128 for the memory, L_DIV for the current synth and 128 for the ZIR for next TCX*/ + Word16 syn2[L_DIV_MAX]; + Word16 gain_inov; + Word32 past_gcode; + Word16 L_frame; + Word16 clip_gain; + Word32 gain_code2; + Word16 code2[L_SUBFR]; + Word16 y22[L_SUBFR]; /* Filtered adaptive excitation */ + Word32 gain_code_vect[2]; + Word16 error = 0; + Word16 gain_preQ = 0; /* Gain of prequantizer excitation */ + Word16 code_preQ[L_SUBFR]; /* Prequantizer excitation */ + + Word16 dummy = 0; + set16_fx(code_preQ, 0, L_SUBFR); + + + T0 = 0; /* to avoid compilation warnings */ + T0_frac = 0; /* to avoid compilation warnings */ + T0_res = 0; /* to avoid compilation warnings */ + gain_pit = 0; /* to avoid compilation warnings */ + + + /* Configure ACELP */ + LPDmem->nbits = BITS_ALLOC_config_acelp( target_bits, coder_type, &(st->acelp_cfg), st->narrowBand, st->nb_subfr ); + + /* Init Framing parameters */ + move16(); + move16(); + move16(); + L_frame = st->L_frame_fx; + + + /*------------------------------------------------------------------------* + * Previous frame is TCX (for non-EVS modes)(deactivated permanently) * + *------------------------------------------------------------------------*/ + + /*------------------------------------------------------------------------* + * Initialize buffers * + *------------------------------------------------------------------------*/ + + /* Rescale ACELP memories, which were not scaled yet*/ + xn_exp = sub(sub(15+1, Q_new),shift); + Q_xn = add(sub(Q_new,1),shift); + Q_new_p5 = add(Q_new, 5); + + /* Reset phase dispersion */ + IF (st->last_core_fx > ACELP_CORE) + { + move16(); + move16(); + move16(); + st->dm_fx.prev_gain_code = 0; + set16_fx(st->dm_fx.prev_gain_pit, 0, 6); + st->dm_fx.prev_state = 0; + } + + /* set excitation memory*/ + move16(); + move16(); + exc = exc_buf+L_EXC_MEM; + Copy(LPDmem->old_exc, exc_buf, L_EXC_MEM); + *(exc+st->L_frame_fx) = 0; + + /* Init syn buffer */ + move16(); + syn = syn_buf + M; + Copy(LPDmem->mem_syn, syn_buf, M); + + + /* calculate residual */ + move16(); + p_Aq = Aq; + FOR (i_subfr=0; i_subfrnrg_mode>0) + { + + Es_pred_enc_fx(&Es_pred, prm, L_frame, exc, voicing, acelp_cfg->nrg_bits, acelp_cfg->nrg_mode>1, Q_new + ); + prm++; + } + ELSE + { + + Es_pred=0; + } + + IF (EQ_16(st->L_frame_fx,L_FRAME)) + { + Copy(Aq+2*(M+1), st->cur_sub_Aq_fx, (M+1)); + } + ELSE + { + Copy(Aq+3*(M+1), st->cur_sub_Aq_fx, (M+1)); + } + + + /*------------------------------------------------------------------------* + * Loop for every subframe in the analysis frame * + *------------------------------------------------------------------------* + * To find the pitch and innovation parameters. The subframe size is * + * L_SUBFR and the loop is repeated L_FRAME_PLUS/L_SUBFR * + * times. * + * - compute impulse response of weighted synthesis filter (h1[]) * + * - compute the target signal for pitch search * + * - find the closed-loop pitch parameters * + * - encode the pitch delay * + * - update the impulse response h1[] by including fixed-gain pitch * + * - find target vector for codebook search * + * - correlation between target vector and impulse response * + * - codebook search * + * - encode codebook address * + * - VQ of pitch and codebook gains * + * - find synthesis speech * + * - update states of weighting filter * + *------------------------------------------------------------------------*/ + move16(); + move16(); + p_A = A; + p_Aq = Aq; + + move16(); + res_save = exc[0]; + + j_subfr = 0; + move16(); + FOR (i_subfr=0; i_subfrmem_w0, + p_Aq, + exc, + L_SUBFR, + p_A, + st->preemph_fac, + xn, + cn + ,h1 + ); + + /*---------------------------------------------------------------* + * Compute impulse response, h1[], of weighted synthesis filter * + *---------------------------------------------------------------*/ + Scale_sig(h1, L_SUBFR, add(1,shift)); /* Q13+1-shift */ + + /* scaling of xn[] to limit dynamic at 12 bits */ + Scale_sig(xn, L_SUBFR, shift); + + /*-----------------------------------------------------------------* + * Gain clipping test to avoid unstable synthesis on frame erasure + * or in case of floating point encoder & fixed p. decoder + *-----------------------------------------------------------------*/ + + clip_gain = Mode2_gp_clip( voicing, i_subfr, coder_type, xn, st->clip_var_fx, L_SUBFR, Q_xn ); + + /*-----------------------------------------------------------------* + * - find unity gain pitch excitation (adaptive codebook entry) * + * with fractional interpolation. * + * - find filtered pitch exc. y1[]=exc[] convolved with h1[]) * + * - compute pitch gain1 * + *-----------------------------------------------------------------*/ + + IF ( acelp_cfg->ltp_bits!=0 ) + { + /* Adaptive Codebook (GC and VC) */ + + Mode2_pit_encode( acelp_cfg->ltp_mode, + i_subfr, + &prm, + &exc[i_subfr], + T_op, + &T0_min, + &T0_min_frac, + &T0_max, + &T0_max_frac, + &T0, + &T0_frac, + &T0_res, + h1, + xn, + st->pit_min, + st->pit_fr1, + st->pit_fr1b, + st->pit_fr2, + st->pit_max, + st->pit_res_max); + + E_ACELP_adaptive_codebook( exc, + T0, + T0_frac, + T0_res, + st->pit_res_max, + acelp_cfg->ltf_mode, + i_subfr, + L_SUBFR, + L_frame, + h1, + clip_gain, + xn, + y1, + &g_corr, + &prm, + &gain_pit, + xn_exp + ,0 + ,0 + ,&dummy + ); + + + + } + ELSE IF ( acelp_cfg->ltp_bits==0 ) + { + /* No adaptive codebook (UC) */ + gain_pit=0; + g_corr.xy1=0; + g_corr.xy1_e=0; + g_corr.y1y1=0; + g_corr.y1y1_e=0; + set16_fx(y1,0,L_SUBFR); + set16_fx(exc+i_subfr,0,L_SUBFR); + T0 = L_SUBFR; + T0_frac = 0; + T0_res = 1; + } + + IF( st->igf != 0 ) + { + tbe_celp_exc(L_frame, i_subfr, T0, T0_frac, &error, bwe_exc); + } + + pitch_buf[i_subfr/L_SUBFR] = shl(add(shl(T0,2),T0_frac), 4); + + /*----------------------------------------------------------------------* + * Encode the algebraic innovation * + *----------------------------------------------------------------------*/ + + E_ACELP_innovative_codebook( exc, + T0, + T0_frac, + T0_res, + gain_pit, + LPDmem->tilt_code, + acelp_cfg->fixed_cdk_index[j_subfr], + acelp_cfg->formant_enh, + acelp_cfg->formant_tilt, + acelp_cfg->formant_enh_num, + acelp_cfg->formant_enh_den, + acelp_cfg->pitch_sharpening, + acelp_cfg->pre_emphasis, + acelp_cfg->phase_scrambling, + i_subfr, + p_Aq, + h1, + xn, + cn, + y1, + y2, + st->acelp_autocorr, + &prm, + code, + shift + ,st->L_frame_fx, + st->last_L_frame_fx, + st->total_brate_fx + ); + + E_ACELP_xy2_corr(xn, y1, y2, &g_corr, L_SUBFR, Q_xn); + + g_corr.y2y2_e = sub(g_corr.y2y2_e, 18); /* -18 (y2*y2: Q9*Q9) */ + g_corr.xy2_e = sub(g_corr.xy2_e, add(Q_xn,9)); /* -(Q_xn+9) (xn: Q_xn y2: Q9) */ + g_corr.y1y2_e = sub(g_corr.y1y2_e, add(Q_xn,9)); /* -(Q_xn+9) (y1: Q_xn y2: Q9) */ + g_corr.xx_e = sub(g_corr.xx_e, add(Q_xn,Q_xn)); /* -(Q_xn+Q_xn) (xn: Q_xn) */ + + + /*----------------------------------------------------------------------* + * Add Gaussian excitation * + *----------------------------------------------------------------------*/ + + IF (EQ_16(acelp_cfg->gains_mode[j_subfr], 7)) + { + + gauss_L2(h1, + code2, + y2, + y22, + &gain_code2, + &g_corr, + gain_pit, + LPDmem->tilt_code, + p_Aq, + acelp_cfg->formant_enh_num, + &(st->seed_acelp), + shift + ); + } + ELSE + { + gain_code2 = L_deposit_l(0); + set16_fx(code2, 0, L_SUBFR); + set16_fx(y22, 0, L_SUBFR); + } + + /*----------------------------------------------------------* + * - Compute the fixed codebook gain * + * - quantize fixed codebook gain * + *----------------------------------------------------------*/ + + encode_acelp_gains( code, + acelp_cfg->gains_mode[j_subfr], + Es_pred, + clip_gain, + &g_corr, + &gain_pit, + &gain_code, + &prm, + &past_gcode, + &gain_inov, + L_SUBFR, + code2, + &gain_code2, + st->flag_noisy_speech_snr + ); + + gp_clip_test_gain_pit_fx( st->core_brate_fx, gain_pit, st->clip_var_fx ); + + gain_code_vect[0] = gain_code; + move32(); + gain_code_vect[1] = gain_code; + move32(); + + /*----------------------------------------------------------* + * - voice factor (for pitch enhancement) * + *----------------------------------------------------------*/ + E_UTIL_voice_factor( exc, + i_subfr, + code, + gain_pit, + gain_code, + &voice_fac, + &(LPDmem->tilt_code), + L_SUBFR, + acelp_cfg->voice_tilt, + Q_new, + shift + ); + + st->rf_tilt_buf[i_subfr/L_SUBFR] = LPDmem->tilt_code; + + /*-----------------------------------------------------------------* + * Update memory of the weighting filter + *-----------------------------------------------------------------*/ + /* st_fx->mem_w0 = xn[L_SUBFR-1] - (gain_pit*y1[L_SUBFR-1]) - (gain_code*y2[L_SUBFR-1]); */ + Ltmp = Mpy_32_16_1(gain_code, y2[L_SUBFR-1]); + Ltmp = L_shl(Ltmp, add(5,Q_xn)); + Ltmp = L_mac(Ltmp, y1[L_SUBFR-1], gain_pit); + /* Add Gaussian contribution*/ + Ltmp2 = Mpy_32_16_1(gain_code2, y22[L_SUBFR-1]); + Ltmp2 = L_shl(Ltmp2, add(5,Q_xn)); + Ltmp = L_add(Ltmp, Ltmp2); + LPDmem->mem_w0 =sub(xn[L_SUBFR-1], round_fx(L_shl(Ltmp, 1))); + move16(); + BASOP_SATURATE_WARNING_OFF; + LPDmem->mem_w0 =shr(LPDmem->mem_w0, shift); /*Qnew-1*/ + BASOP_SATURATE_WARNING_ON; + + + + /*-------------------------------------------------------* + * - Find the total excitation. * + *-------------------------------------------------------*/ + + tmp2 = shr(L_SUBFR, 1); + FOR (j = 0; j < 2; j++) + { + FOR (i = sub(tmp2, shr(L_SUBFR, 1)); i < tmp2; i++) + { + /* code in Q9, gain_pit in Q14; exc Q_new */ + Ltmp = Mpy_32_16_1(gain_code2, code2[i]); + Ltmp = L_shl(Ltmp, Q_new_p5); + Ltmp = L_mac(Ltmp, gain_pit, exc[i+i_subfr]); + BASOP_SATURATE_WARNING_OFF + exc2[i] = round_fx(L_shl(Ltmp, 1)); + BASOP_SATURATE_WARNING_ON + + Ltmp2 = Mpy_32_16_1(gain_code_vect[j], code[i]); + Ltmp2 = L_shl(Ltmp2, Q_new_p5); + Ltmp = L_add(Ltmp, Ltmp2); + BASOP_SATURATE_WARNING_OFF + Ltmp = L_shl(Ltmp, 1); /* saturation can occur here */ + BASOP_SATURATE_WARNING_ON + exc[i + i_subfr] = round_fx(Ltmp); + } + tmp2 = L_SUBFR; + move16(); + } + + /*-----------------------------------------------------------------* + * Prepare TBE excitation + *-----------------------------------------------------------------*/ + + IF( st->igf != 0 ) + { + prep_tbe_exc_fx( L_frame, + i_subfr, + gain_pit, + gain_code, + code, + voice_fac, + &voice_factors[i_subfr/L_SUBFR], + bwe_exc, + gain_preQ, + code_preQ, + Q_new, + T0, + T0_frac, + coder_type, + st->core_brate_fx ); + } + + /*---------------------------------------------------------* + * Enhance the excitation * + *---------------------------------------------------------*/ + + E_UTIL_enhancer( voice_fac, + stab_fac, + past_gcode, + gain_inov, + &LPDmem->gc_threshold, + code, + exc2, + gain_pit, + &st->dm_fx.prev_gain_code, + st->dm_fx.prev_gain_pit, + &st->dm_fx.prev_state, + coder_type, + acelp_cfg->fixed_cdk_index[j_subfr], + L_SUBFR, + L_frame, + Q_new + ); + + /*----------------------------------------------------------* + * - compute the synthesis speech * + *----------------------------------------------------------*/ + + E_UTIL_synthesis(1, p_Aq, exc2, &syn2[i_subfr], L_SUBFR, LPDmem->mem_syn2, 1, M); + + /*Save data for BPF*/ + + move16(); + move16(); + /* st->bpf_T[j_subfr] = (int)((float)T0+(float)T0_frac/(float)T0_res+0.5f); */ + st->bpf_T[j_subfr] = add(T0, shr(div_s(T0_frac, T0_res), 14)); + st->bpf_gainT[j_subfr] = gain_pit; + + E_UTIL_synthesis(1, p_Aq, &exc[i_subfr], &syn[i_subfr], L_SUBFR, &syn[i_subfr-M], 0, M); + + /*----------------------------------------------------------* + * Update * + *----------------------------------------------------------*/ + move16(); + move16(); + p_A += (M+1); + p_Aq += (M+1); + + IF( hPlc_Ext != NULL ) + { + hPlc_Ext->T0_4th = T0; + move16(); + } + + move32(); + st->gain_code[j_subfr] = gain_code; + + j_subfr = add(j_subfr, 1); + } /* end of subframe loop */ + + p_A -= (M+1); + p_Aq -= (M+1); + + + /*----------------------------------------------------------* + * Update LPD memory * + *----------------------------------------------------------*/ + Copy (exc+L_frame-L_EXC_MEM, LPDmem->old_exc, L_EXC_MEM); + Copy(syn+L_frame-M, LPDmem->mem_syn, M); + Copy(syn+L_frame-L_SYN_MEM, LPDmem->mem_syn_r, L_SYN_MEM); + + IF( hPlc_Ext != NULL ) + { + hPlc_Ext->Q_exp = sub( Q_new, hPlc_Ext->Q_new ); + move16(); + hPlc_Ext->Q_new = Q_new; + move16(); + Copy( exc+L_frame-L_EXC_MEM-8, hPlc_Ext->old_exc_Qold, 8); + } + + /*----------------------------------------------------------* + * ZIR at the end of the ACELP frame (for TCX) * + *----------------------------------------------------------*/ + Copy(syn2, syn, L_frame); + move16(); + tmp = LPDmem->syn[M]; + E_UTIL_deemph2(sub(Q_new,1), syn, st->preemph_fac, L_frame, &tmp); + + bufferCopyFx(syn+L_frame-(L_frame/2), LPDmem->Txnq, shr(L_frame,1),0 /*Qf_syn*/, -1 /*Qf_Txnq*/, 0 /*Q_syn*/ , 0 /*Q_Txnq*/); + Copy(syn+L_frame-M-1, LPDmem->syn, 1+M); /*Q0*/ + Copy(syn, synth, L_frame); + + assert(T0_res <= 6); + + /*Update MODE1*/ + Copy(p_Aq, st->old_Aq_12_8_fx, M+1 ); + st->old_Es_pred_fx = Es_pred; + + return 0; +} diff --git a/lib_enc/cod_tcx.c b/lib_enc/cod_tcx.c new file mode 100644 index 0000000..dcd3ddc --- /dev/null +++ b/lib_enc/cod_tcx.c @@ -0,0 +1,2328 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include +#include "stat_com.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "stl.h" +#include "basop_mpy.h" + + + +/* Up to the Autocorrelation it is the same code as in GetMDCT, with the difference in the parameters in the call to tcx_windowing_analysis */ +void HBAutocorrelation( + TCX_config *tcx_cfg, /* input: configuration of TCX */ + Word16 left_overlap_mode, /* input: overlap mode of left window half */ + Word16 right_overlap_mode, /* input: overlap mode of right window half */ + Word16 speech[], /* input: speech[-LFAC..L_frame+LFAC] */ + Word16 L_frame, /* input: frame length */ + Word32 *r, /* output: autocorrelations vector */ + Word16 m /* input : order of LP filter */ +) +{ + Word16 i, j, left_overlap, right_overlap; + Word16 len, norm, shift, fact; + Word32 L_tmp, L_sum; + Word16 y[L_MDCT_OVLP_MAX+L_FRAME_PLUS+L_MDCT_OVLP_MAX]; + + + /*-----------------------------------------------------------* + * Windowing * + *-----------------------------------------------------------*/ + + WindowSignal(tcx_cfg, tcx_cfg->tcx_offset, left_overlap_mode, right_overlap_mode, &left_overlap, &right_overlap, speech, &L_frame, y, 0); + + /*-----------------------------------------------------------* + * Autocorrelation * + *-----------------------------------------------------------*/ + + len = add(L_frame, shr(add(left_overlap, right_overlap), 1)); + + /* calculate shift */ + shift = 0; + move16(); + L_sum = L_deposit_l(0); + Overflow = 0; + move16(); + FOR (i = 0; i < len; i+=1) + { + /* Test Addition */ + L_mac0(L_sum, y[i], y[i]); + IF (Overflow) + { + Overflow = 0; + move16(); + shift = 1; + move16(); + L_tmp = L_msu0( 0, y[i], y[i] ); + L_tmp = L_shr( L_tmp, 1 ); + L_sum = L_add( L_shr( L_sub( L_sum, 1 ), 1 ), 1 ); + + L_sum = L_sub( L_sum, L_tmp ); + + FOR (j = add(i,1); j 0) + { + fact = lshr(-32768, shift); + FOR (i = 0; i < len; i++) + { + y[i] = mult_r(y[i], fact); + move16(); + } + } + + /* Compute and normalize r[0] */ + L_sum = L_mac0(1, y[0], y[0]); + FOR (i = 1; i < len; i++) + { + L_sum = L_mac0(L_sum, y[i], y[i]); + } + + norm = norm_l(L_sum); + L_sum = L_shl(L_sum, norm); + r[0] = L_sum; + move32(); + + /* Compute r[1] to r[m] */ + FOR (i = 1; i <= m; i++) + { + L_sum = L_mult0(y[0],y[i]); + FOR (j = 1; j < len - i; j++) + { + L_sum = L_mac0(L_sum, y[j], y[j + i]); + } + + L_sum = L_shl(L_sum, norm); + r[i] = L_sum; + move32(); + } + +} + +void TNSAnalysis( + TCX_config *tcx_cfg, /* input: configuration of TCX */ + Word16 L_frame, /* input: frame length */ + Word16 L_spec, + Word16 tcxMode, /* input: TCX mode for the frame/subframe - TCX20 | TCX10 | TCX 5 (meaning 2 x TCX 5) */ + Word8 isAfterACELP, /* input: Flag indicating if the last frame was ACELP. For the second TCX subframe it should be 0 */ + Word32 spectrum[], /* input: MDCT spectrum */ + STnsData * pTnsData, /* output: Tns data */ + Word8 * pfUseTns, /* output: Flag indicating if TNS is used */ + Word16 *predictionGain +) +{ + Word32 buff[8]; + Word16 tmp = 0; /* initialization only to avoid compiler warning, not counted */ + Word16 tmp2 = 0; /* initialization only to avoid compiler warning, not counted */ + + + /* Init TNS */ + *pfUseTns = 0; + move16(); + + IF (tcx_cfg->fIsTNSAllowed != 0) + { + tcx_cfg->pCurrentTnsConfig = &tcx_cfg->tnsConfig[sub(tcxMode, TCX_20) == 0][isAfterACELP]; + test(); + L_spec = tcx_cfg->pCurrentTnsConfig->iFilterBorders[0]; + move16(); + + /*-----------------------------------------------------------* + * Temporal Noise Shaping analysis * + *-----------------------------------------------------------*/ + + IF (EQ_16(tcxMode, TCX_5)) + { + tmp = shr(L_frame,2); + + /* rearrange LF sub-window lines prior to TNS analysis & filtering */ + tmp2 = shr(L_spec,1); + + IF (LT_16(tmp2, tmp)) + { + Copy32(spectrum+8, spectrum+16, sub(tmp2, 8)); + Copy32(spectrum+tmp, spectrum+8, 8); + Copy32(spectrum+tmp+8, spectrum+tmp2+8, sub(tmp2, 8)); + } + ELSE + { + Copy32(spectrum+tmp, buff, 8); + Copy32(spectrum+8, spectrum+16, sub(tmp, 8)); + Copy32(buff, spectrum+8, 8); + } + } + + move16(); + *pfUseTns = (Word8)DetectTnsFilt(tcx_cfg->pCurrentTnsConfig, spectrum, pTnsData, predictionGain); + + /* If TNS should be used then get the residual after applying it inplace in spectrum */ + IF (*pfUseTns != 0) + { + ApplyTnsFilter(tcx_cfg->pCurrentTnsConfig, pTnsData, spectrum, 1); + } + + IF (EQ_16(tcxMode, TCX_5)) + { + /* undo rearrangement of LF sub-window lines prior to TNS analysis */ + IF (LT_16(tmp2, tmp)) + { + Copy32(spectrum+tmp2+8, spectrum+tmp+8, sub(tmp2, 8)); + Copy32(spectrum+8, spectrum+tmp, 8); + Copy32(spectrum+16, spectrum+8, sub(tmp2, 8)); + set32_fx(spectrum+tmp2, 0, sub(tmp,tmp2)); + set32_fx(spectrum+tmp+tmp2, 0, sub(tmp,tmp2)); + } + ELSE + { + Copy32(spectrum+8, buff, 8); + Copy32(spectrum+16, spectrum+8, sub(tmp, 8)); + Copy32(buff, spectrum+tmp, 8); + } + } + } + +} + +void ShapeSpectrum( + TCX_config *tcx_cfg,/*input: configuration of TCX*/ + Word16 A[], /* input: quantized coefficients NxAz_q[M+1] */ + Word16 gainlpc[], /* output: MDCT gains for the previous frame */ + Word16 gainlpc_e[], /* output: MDCT gains exponents */ + Word16 L_frame_glob,/* input: frame length */ + Word16 L_spec, + Word32 spectrum[], /* i/o: MDCT spectrum */ + Word8 pfUseTns, /* output: Flag indicating if TNS is used */ + Encoder_State_fx *st +) +{ + Word16 L_frame; + Word16 Ap[M+2]; + Word16 gamma1; + Word16 gainlpc_noinv[FDNS_NPTS]; + Word16 gainlpc_noinv_e[FDNS_NPTS]; + Word16 i; + Word32 max_low_pre = 0, max_high_pre = 0; + + + /*-----------------------------------------------------------* + * Init * + *-----------------------------------------------------------*/ + + /* Init lengths */ + L_frame = L_frame_glob; + move16(); + gamma1 = st->gamma; + move16(); + if (st->enableTcxLpc != 0) + { + gamma1 = 0x7FFF; + move16(); + } + + /* if past frame is ACELP */ + + IF (st->last_core_fx == ACELP_CORE) + { + L_frame = add(L_frame, tcx_cfg->tcx_offset); + L_spec = add(L_spec, shr(tcx_cfg->tcx_coded_lines, 2)); + if(tcx_cfg->lfacNext<0) + { + L_frame = sub(L_frame,tcx_cfg->lfacNext); + move16(); + } + } + + test(); + tcxGetNoiseFillingTilt(A, + M, + L_frame, + (GE_32(st->total_brate_fx, ACELP_13k20) && st->rf_mode == 0 ), + &st->noiseTiltFactor); + + /* Calculate Spectrum Flatness Measure for the TCX Concealment */ + IF (st->enablePlcWaveadjust) + { + tcx_cfg->SFM2 = SFM_Cal(spectrum, s_min(200, L_frame)); + } + + test(); + test(); + test(); + IF( (EQ_32(st->total_brate_fx, ACELP_9k60)&&EQ_16(st->bwidth_fx,SWB))|| + (EQ_32(st->total_brate_fx, ACELP_13k20) && EQ_16(st->bwidth_fx, SWB) ) ) + { + max_low_pre = 0; + move32(); + FOR (i = 0; i < L_frame; i++) + { + Word32 tmp = L_abs(spectrum[i]); + if( GT_32(tmp, max_low_pre)) + { + max_low_pre = tmp; + move32(); + } + } + + max_high_pre = 0; + move32(); + for (i = 0; i < L_spec - L_frame; i++) + { + Word32 tmp = L_abs(spectrum[L_frame + i]); + if( GT_32( tmp, max_high_pre)) + { + max_high_pre = tmp; + move32(); + } + } + } + + /*-----------------------------------------------------------* + * Pre-shaping in frequency domain using weighted LPC (Wz) * + *-----------------------------------------------------------*/ + + weight_a_fx( A, Ap, gamma1, M ); + + lpc2mdct( Ap, M, gainlpc_noinv, gainlpc_noinv_e, gainlpc, gainlpc_e ); + + mdct_shaping( spectrum, L_frame, gainlpc_noinv, gainlpc_noinv_e ); + FOR (i = L_frame; i < L_spec; i++) + { + spectrum[i] = L_shl(Mpy_32_16_1(spectrum[i], gainlpc_noinv[FDNS_NPTS-1]), gainlpc_noinv_e[FDNS_NPTS-1]); + move32(); + } + + /* reduce the peaks in the IGF region, to make life of the core-coder easier... */ + test(); + IF( ( EQ_32(st->total_brate_fx, ACELP_9k60)&&EQ_16(st->bwidth_fx,SWB))|| + ( EQ_32(st->total_brate_fx, ACELP_13k20)&&EQ_16(st->bwidth_fx, SWB)) ) + { + Word16 sf_width; + Word16 dist_low, dist_high; + Word16 max_fac_s, max_fac_m; + Word32 max_low, max_low1, max_low2, max_high; + Word16 headroom, shift, tmp16; + + + max_fac_m = 24576; + move16(); + /* max_fac = 3 */ + max_fac_s = 2; + move16(); + if( st->tcx_lpc_shaped_ari ) + { + /* max_fac = 1.5 */ + max_fac_s = 1; + move16(); + } + + sf_width = shr(L_frame, 1); + + max_low2 = 0; + move32(); + dist_low = 0; + move16(); + FOR (i = 0; i < sf_width; i++) + { + Word32 tmp = L_abs(spectrum[L_frame - 1 - i]); + IF( GT_32(tmp, max_low2)) + { + max_low2 = tmp; + move32(); + dist_low = i; + move16(); + } + } + + max_low1 = 0; + move32(); + FOR (i = 0; i < sub(L_frame, sf_width); i++) + { + Word32 tmp = L_abs(spectrum[L_frame - sf_width - 1 - i]); + if( GT_32(tmp, max_low1)) + { + max_low1 = tmp; + move32(); + } + if( tmp > max_low2 ) + { + dist_low = add(sf_width, i); + } + } + + max_low = L_max(max_low1, max_low2); + + max_high = 0; + move32(); + dist_high = 0; + move16(); + FOR (i = 0; i < sub(L_spec, L_frame); i++) + { + Word32 tmp = L_abs(spectrum[L_frame + i]); + if( GT_32(tmp, max_high)) + { + max_high = tmp; + move32(); + dist_high = i; + move16(); + } + } + + /* at least 9 bits headroom are needed for below multiplicitions */ + shift = 0; + move16(); + headroom = 31; + move16(); + + tmp16 = norm_l(max_low); + if(max_low != 0) headroom = s_min(headroom, tmp16); + + tmp16 = norm_l(max_low2); + if(max_low2 != 0) headroom = s_min(headroom, tmp16); + + tmp16 = norm_l(max_high); + if(max_high != 0) headroom = s_min(headroom, tmp16); + + if( LT_16(headroom, 9)) + { + shift = sub(9, headroom); + } + max_low = L_shr(max_low, shift); + max_low2 = L_shr(max_low2, shift); + max_high = L_shr(max_high, shift); + + test(); + test(); + IF( GT_32(imult3216(max_high, dist_high), imult3216(L_shr(max_low, 2), dist_low))&&(GT_32(max_low_pre,L_shr(max_high_pre,4)))&&(GT_32(max_high,L_shl(Mpy_32_16_r(max_low2,max_fac_m),max_fac_s)))) + { + Word16 fac; + fac = divide3232(max_low2, max_high); + fac = shl(mult_r( fac, max_fac_m ), max_fac_s); + + FOR (i = 0; i < sub(L_spec, L_frame); i++) + { + spectrum[L_frame + i] = Mpy_32_16_1(spectrum[L_frame + i], fac); + } + } + } + + + test(); + test(); + test(); + IF( st->tcxonly && st->tcxltp && (st->tcxltp_gain > 0) && !pfUseTns ) + { + PsychAdaptLowFreqEmph(spectrum, gainlpc, gainlpc_e); + } + +} + + +void QuantizeSpectrum( + TCX_config *tcx_cfg, /*input: configuration of TCX*/ + Word16 A[], /* input: quantized coefficients NxAz_q[M+1] */ + Word16 Aqind[], /* input: frame-independent quantized coefficients (M+1) */ + Word16 gainlpc[], /* input: MDCT gains of the previous frame */ + Word16 gainlpc_e[], /* input: MDCT gains exponents */ + Word16 synth[], + Word16 L_frame_glob, /* input: frame length */ + Word16 L_frameTCX_glob, + Word16 L_spec, + Word16 nb_bits, /*input: bit budget*/ + Word8 tcxonly, /*input: only TCX flag*/ + Word32 spectrum[], /* i/o: MDCT spectrum, input is shaped MDCT spectrum */ + Word16 *spectrum_e, /* i/o: MDCT spectrum exponent */ + STnsData * pTnsData, /* input: Tns data */ + Word8 fUseTns, /* input: Flag indicating if TNS is used */ + Word16 tnsSize, /* input: number of tns parameters put into prm */ + LPD_state *LPDmem, /*i/o: memories*/ + Word16 prm[], /* output: tcx parameters */ + Word16 frame_cnt, /* input: frame counter in the super_frame */ + Encoder_State_fx *st, + CONTEXT_HM_CONFIG *hm_cfg +) +{ + Word16 i, L_frame, tcx_offset; + Word16 stop; + Word16 tmp1, tmp2, tmp3, tmp4, s; + Word32 tmp32; + Word8 tmp8; + Word16 *tmpP16; + Word16 L_frameTCX; + Word16 fac_ns; + Word16 nf_seed; + Word32 ener; + Word16 ener_e; + Word16 gain_tcx, gain_tcx_e; + Word16 sqBits; + Word16 overlap; + Word16 noiseFillingSize; + Word16 noiseTransWidth; + Word32 *OriginalSpectrum; + Word16 OriginalSpectrum_e; + Word16 ctxHmBits; + Word16 resQBits; + Word16 *signs; + Word16 signaling_bits; + Word16 *prm_ltp, *prm_tns, *prm_hm, *prm_lastnz, *prm_target; + Word16 Aq_old[M+1]; + Word32 SFM; + Word32 K, K2; + Word16 aldo; /* ALDO flag in current frame*/ + Word16 nz; /* non-zero length in ALDO window*/ + CONTEXT_HM_CONFIG * phm_cfg; + + + /* Stack memory is split between encoder and internal decoder to reduce max + stack memory usage. */ + { + Word16 sqTargetBits; + Word16 gain_tcx_opt, gain_tcx_opt_e; + Word16 sqGain, sqGain_e; + Word16 sqBits_noStop; + Word16 nEncoded; + Word16 maxNfCalcBw; + Word16 PeriodicityIndex; + Word16 NumIndexBits; + Word16 nEncodedCtxHm, stopCtxHm, sqBitsCtxHm, Selector; + Word16 lastnz, lastnzCtxHm; + Word16 RelativeScore; + Word32 x_orig[N_MAX]; + Word16 x_orig_e; + Word16 resQTargetBits; + Word16 xn_buf16[L_FRAME_PLUS]; + Word16 *sqQ; + Word16 LtpPitchLag; + + + sqGain = 0x4000; + move16(); + sqGain_e = 1; + move16(); + noiseTransWidth = MIN_NOISE_FILLING_HOLE; + move16(); + resQTargetBits = 0; + move16(); + + /*-----------------------------------------------------------* + * Init * + *-----------------------------------------------------------*/ + + /* Init lengths */ + L_frame = L_frame_glob; + move16(); + L_frameTCX = L_frameTCX_glob; + move16(); + overlap = tcx_cfg->tcx_mdct_window_length; + move16(); + aldo = 0; + move16(); + nz = NS2SA_fx2(st->sr_core, N_ZERO_MDCT_NS); + move16(); + /* Modified the overlap to the delay in case of short blocks*/ + tcx_offset = tcx_cfg->tcx_offset; + move16(); + + OriginalSpectrum = NULL; + signs = NULL; /* silence warning */ + NumIndexBits = 0; + move16(); + sqBits = 0; + move16(); + ctxHmBits = 0; + move16(); + resQBits = 0; + move16(); + prm_ltp = &prm[1+NOISE_FILL_RANGES]; + move16(); + prm_tns = prm_ltp + LTPSIZE; + move16(); + prm_hm = prm_tns + tnsSize; + move16(); + prm_lastnz = prm_hm + 2; + move16(); + sqQ = prm_hm + NPRM_CTX_HM; + move16(); + + /* if past frame is ACELP */ + + IF (st->last_core_fx == ACELP_CORE) + { + tcx_cfg->last_aldo = 0; + move16(); + + L_frame = add(L_frame, tcx_offset); + L_frameTCX = add(L_frameTCX, tcx_cfg->tcx_offsetFB); + L_spec = add(L_spec, shr(tcx_cfg->tcx_coded_lines, 2)); + tcx_offset = 0; + move16(); + IF(tcx_cfg->lfacNext<0) + { + L_frame = sub(L_frame,tcx_cfg->lfacNext); + L_frameTCX = sub(L_frameTCX, tcx_cfg->lfacNextFB); + tcx_offset = tcx_cfg->lfacNext; + move16(); + } + st->noiseLevelMemory = 0; + move16(); + } + + + E_LPC_f_lsp_a_conversion(st->lsp_old_fx, Aq_old, M); + + /* target bitrate for SQ */ + sqTargetBits = sub(nb_bits, 7 + NBITS_NOISE_FILL_LEVEL); + + /*Unquantized spectrum here*/ + IF (st->enablePlcWaveadjust) + { + + + SFM = SFM_Cal(spectrum, s_min(200, L_frame_glob)); + test(); + IF (LE_16(L_frame_glob, 256)) + { + K = 0x33333333; + move32(); + K2 = 0xCCCCCCD; + move32(); + } + ELSE IF (EQ_16(L_frame_glob,320)||EQ_16(L_frame_glob,512)) + { + K = 0x33333333; + move32(); + K2 = 0xCCCCCCD; + move32(); + } + ELSE /*FrameSize_Core == 640*/ + { + K = 0x2CCCCCCD; + move32(); + K2 = 0x51EB852; + move32(); + } + + + IF ( LT_32(SFM, K)) + { + st->Tonal_SideInfo = 1; + move16(); + } + ELSE + { + st->Tonal_SideInfo = 0; + move16(); + } + + if ( LT_32(tcx_cfg->SFM2, K2)) + { + st->Tonal_SideInfo = 1; + move16(); + } + } + + /* Save pre-shaped spectrum*/ + Copy32(spectrum, x_orig, L_spec); + x_orig_e = *spectrum_e; + move16(); + + /*-----------------------------------------------------------* + * Bandwidth Limitation * + *-----------------------------------------------------------*/ + + noiseFillingSize = L_spec; + move16(); + IF (st->igf != 0) + { + noiseFillingSize = st->hIGFEnc.infoStartLine; + move16(); + } + ELSE + { + st->hIGFEnc.infoStopLine = noiseFillingSize; + move16(); + } + + FOR (i=st->hIGFEnc.infoStopLine; itcx_lpc_shaped_ari == 0) /* old arithmetic coder */ + { + + /* Fast estimation of the scalar quantizer step size */ + test(); + IF ((tcx_cfg->ctx_hm != 0) && (st->last_core_fx != ACELP_CORE)) + { + LtpPitchLag = -1; + move16(); + + test(); + IF ((tcxonly == 0) && (LT_16(st->tcxltp_pitch_int, st->L_frame_fx))) + { + tmp32 = L_shl(L_mult0(st->L_frame_fx, st->pit_res_max), 1+kLtpHmFractionalResolution+1); + tmp1 = add(imult1616(st->tcxltp_pitch_int, st->pit_res_max), st->tcxltp_pitch_fr); + LtpPitchLag = div_l(tmp32, tmp1); + } + + ctxHmBits = add(ctxHmBits, 1); /* ContextHM flag */ + sqTargetBits = sub(sqTargetBits, 1); /* ContextHM flag */ + + OriginalSpectrum = spectrum; + OriginalSpectrum_e = *spectrum_e; + move16(); + + tmp1 = -1; + move16(); + if (st->tcxltp != 0) + { + tmp1 = st->tcxltp_gain; + move16(); + } + PeriodicityIndex = SearchPeriodicityIndex( + OriginalSpectrum, + NULL, + L_spec, + sqTargetBits, + LtpPitchLag, + tmp1, + &RelativeScore + ); + + ConfigureContextHm( + L_spec, + sqTargetBits, + PeriodicityIndex, + LtpPitchLag, + hm_cfg + ); + + tmp1 = 1; + move16(); + if (LT_16(L_spec, 256)) + { + tmp1 = 0; + move16(); + } + NumIndexBits = CountIndexBits( tmp1, PeriodicityIndex); + + + + /* Quantize original spectrum */ + + sqGain = SQ_gain(OriginalSpectrum, OriginalSpectrum_e, + shl(mult(LPDmem->tcx_target_bits_fac, sqTargetBits), 1), + L_spec, + &sqGain_e); + + tcx_scalar_quantization(OriginalSpectrum, OriginalSpectrum_e, + sqQ, + L_spec, + sqGain, sqGain_e, + tcx_cfg->sq_rounding, + st->memQuantZeros, + tcxonly); + + /* Estimate original bitrate */ + stop = 0; + move16(); + + sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC(sqQ, + L_spec, + &lastnz, + &nEncoded, + sqTargetBits, + &stop, + NULL); + + /* Estimate context mapped bitrate */ + + stopCtxHm = 0; + move16(); + + /* Context Mapping */ + sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC(sqQ, + L_spec, + &lastnzCtxHm, + &nEncodedCtxHm, + sub(sqTargetBits, NumIndexBits), + &stopCtxHm, + hm_cfg + ); + + /* Decide whether or not to use context mapping */ + Selector = sub(s_max(stop, sqBits), add(s_max(stopCtxHm, sqBitsCtxHm), NumIndexBits)); + + test(); + test(); + IF ((GT_16(Selector, 2))||((LE_16(abs_s(Selector),2))&& + (LT_16(kCtxHmOlRSThr, RelativeScore) ))) + { + /* CtxHm is likely better */ + sqTargetBits = sub(sqTargetBits, NumIndexBits); + ctxHmBits = add(ctxHmBits, NumIndexBits); + prm_hm[0] = 1; + move16(); + prm_hm[1] = PeriodicityIndex; + move16(); + *prm_lastnz = lastnzCtxHm; + move16(); + sqBits_noStop = sqBits = sqBitsCtxHm; + move16(); + move16(); + nEncoded = nEncodedCtxHm; + move16(); + stop = stopCtxHm; + move16(); + } + ELSE /* Original is better or not much difference */ + { + prm_hm[0] = 0; + move16(); + prm_hm[1] = PeriodicityIndex; + move16(); + *prm_lastnz = lastnz; + move16(); + PeriodicityIndex = -1; + move16(); + + sqBits_noStop = sqBits; + move16(); + } + + + if (stop != 0) + { + + sqBits = stop; + move16(); + } + } + ELSE /* no context hm*/ + { + PeriodicityIndex = -1; + move16(); + + sqGain = SQ_gain(spectrum, *spectrum_e, + shl(mult(LPDmem->tcx_target_bits_fac, sqTargetBits), 1), + L_spec, + &sqGain_e); + + /* Quantize spectrum */ + + tcx_scalar_quantization(spectrum, *spectrum_e, + sqQ, + L_spec, + sqGain, sqGain_e, + tcx_cfg->sq_rounding, + st->memQuantZeros, + tcxonly + ); + + /* Estimate bitrate */ + stop = 0; + move16(); + sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC(sqQ, + L_spec, + prm_lastnz, /* lastnz */ + &nEncoded, + sqTargetBits, + &stop, + NULL); + + sqBits_noStop = sqBits; + move16(); + + if (stop != 0) + { + sqBits = stop; + move16(); + } + } /* end of if (ctx_hm) */ + + /* Adjust correction factor */ + tmp1 = sqBits; + move16(); + + if (s_and(L_spec, sub(L_spec, 1)) == 0) /* power-of-2 */ + { + tmp1 = add(tmp1, 1); + } + + tmp1 = BASOP_Util_Divide1616_Scale(sqTargetBits, tmp1, &tmp2); + BASOP_SATURATE_WARNING_OFF + LPDmem->tcx_target_bits_fac = shl(mult(LPDmem->tcx_target_bits_fac, tmp1), tmp2); + BASOP_SATURATE_WARNING_ON + + if (GT_16(LPDmem->tcx_target_bits_fac, 0x5000)) + { + LPDmem->tcx_target_bits_fac = 0x5000; + move16(); + } + if (LT_16(LPDmem->tcx_target_bits_fac, 0x3000)) + { + LPDmem->tcx_target_bits_fac = 0x3000; + move16(); + } + + /* Refine quantizer step size with a rate-control-loop (optional) */ + phm_cfg = NULL; + move16(); + if (PeriodicityIndex >= 0) + { + phm_cfg = hm_cfg; + move16(); + } + sqBits = tcx_scalar_quantization_rateloop(spectrum, *spectrum_e, + sqQ, + L_spec, + &sqGain, &sqGain_e, + tcx_cfg->sq_rounding, + st->memQuantZeros, + prm_lastnz, /* lastnz */ + sqTargetBits, + &nEncoded, + &stop, + sqBits_noStop, + sqBits, + tcx_cfg->tcxRateLoopOpt, + tcxonly, + phm_cfg + ); + + IF (ctxHmBits > 0) /* Mapping tool is enabled */ + { + /* Truncate spectrum */ + set16_fx(sqQ+nEncoded, 0, sub(L_spec, nEncoded)); + + IF (PeriodicityIndex >= 0) /* Mapping is used */ + { + /* Estimate non-mapped bitrate */ + stopCtxHm = 1; + move16(); + + sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC(sqQ, + L_spec, + &lastnz, + &nEncodedCtxHm, + sqTargetBits, + &stopCtxHm, + NULL); + + /* Decide whether or not to revert mapping */ + Selector = sub(sqBits, add(sqBitsCtxHm, NumIndexBits)); + + test(); + IF (stopCtxHm == 0 && Selector > 0) /* Non-mapped is better */ + { + sqTargetBits = add(sqTargetBits, NumIndexBits); + ctxHmBits = sub(ctxHmBits, NumIndexBits); + prm_hm[0] = 0; + move16(); + *prm_lastnz = lastnz; + move16(); + PeriodicityIndex = -1; + move16(); + sqBits_noStop = sqBits = sqBitsCtxHm; + move16(); + move16(); + nEncoded = nEncodedCtxHm; + move16(); + stop = stopCtxHm; + move16(); + } + } + ELSE /* Mapping is not used */ + { + /* Estimate mapped bitrate */ + stopCtxHm = 1; + move16(); + sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC(sqQ, + L_spec, + &lastnzCtxHm, + &nEncodedCtxHm, + sub(sqTargetBits, NumIndexBits), + &stopCtxHm, + hm_cfg + ); + + /* Decide whether or not to use mapping */ + Selector = sub(sqBits, add(sqBitsCtxHm, NumIndexBits)); + + test(); + IF (stopCtxHm == 0 && Selector > 0) /* Mapped is better */ + { + sqTargetBits = sub(sqTargetBits, NumIndexBits); + ctxHmBits = add(ctxHmBits, NumIndexBits); + prm_hm[0] = 1; + move16(); + *prm_lastnz = lastnzCtxHm; + move16(); + PeriodicityIndex = prm_hm[1]; + move16(); + sqBits_noStop = sqBits = sqBitsCtxHm; + move16(); + move16(); + nEncoded = nEncodedCtxHm; + move16(); + stop = stopCtxHm; + move16(); + } + } + } + + /* Limit low sqGain for avoiding saturation of the gain quantizer*/ + tmp1 = mult_r(shl(L_spec, 5), 26214/*128.f/NORM_MDCT_FACTOR Q15*/); + s = 15-5-7; + IF( L_spec >= 1024 ) + { + /*reduce precision for avoiding overflow*/ + tmp1 = mult_r(shl(L_spec, 4), 26214/*128.f/NORM_MDCT_FACTOR Q15*/); + s = 15-4-7; + } + tmp1 = ISqrt16(tmp1, &s); + + tmp2 = sub(sqGain_e, s); + IF (tmp2 >= 0) + { + BASOP_SATURATE_WARNING_OFF; + tmp2 = sub(sqGain, shr(tmp1, tmp2)); + BASOP_SATURATE_WARNING_ON; + } + ELSE + { + tmp2 = sub(shl(sqGain, s_max(-15, tmp2)), tmp1); + } + + IF (tmp2 < 0) + { + sqGain = tmp1; + sqGain_e = s; + + tcx_scalar_quantization( spectrum, *spectrum_e, + sqQ, + L_spec, + sqGain, sqGain_e, + tcx_cfg->sq_rounding, + st->memQuantZeros, + tcxonly + ); + + move16(); + stop=1; + + phm_cfg = NULL; + move16(); + if (PeriodicityIndex >= 0) + { + phm_cfg = hm_cfg; + move16(); + } + sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC(sqQ, + L_spec, + prm_lastnz, + &nEncoded, + sqTargetBits, + &stop, + phm_cfg + ); + } + + /* Truncate spectrum (for CBR) */ + IF (stop != 0) + { + set16_fx(sqQ+nEncoded, 0, sub(L_spec, nEncoded)); + } + + /* Save quantized Values */ + tmp32 = L_deposit_l(0); + FOR(i=0; itcx_lpc_shaped_ari, + gainlpc, gainlpc_e, + L_frame + ); + + prm_target = sqQ; + move16(); + sqQ = prm_target + 1; + move16(); + signs = hm_cfg->indexBuffer; + move16(); + + LtpPitchLag = -1; + move16(); + + IF (LT_16(st->tcxltp_pitch_int, st->L_frame_fx)) + { + tmp32 = L_shl(L_mult0(st->L_frame_fx, st->pit_res_max), 1+kLtpHmFractionalResolution+1); + tmp1 = add(imult1616(st->tcxltp_pitch_int, st->pit_res_max), st->tcxltp_pitch_fr); + LtpPitchLag = div_l(tmp32, tmp1); + } + + tmp8 = 1; + move16(); + if (EQ_16(st->last_core_fx, ACELP_CORE)) + { + tmp8 = 0; + move16(); + } + + tcx_arith_encode_envelope( + spectrum, + spectrum_e, + signs, + L_frame, + L_spec, + st, + Aqind, + sqTargetBits, + sqQ, + tmp8, + prm_hm, /* HM parameter area */ + LtpPitchLag, + &sqBits, + &signaling_bits, + &nf_seed + , shr(st->bwidth_fx, 1) /* equivalent to: (st->bwidth_fx > WB)?1:0 */ + ); + + sqTargetBits = sub(sqTargetBits, signaling_bits); + *prm_target = sqTargetBits; + move16(); + } + + /*-----------------------------------------------------------* + * Compute optimal TCX gain. * + *-----------------------------------------------------------*/ + /* initialize LF deemphasis factors in xn_buf */ + set16_fx(xn_buf16, 0x4000, L_spec); + + IF (tcxonly == 0) + { + + AdaptLowFreqDeemph(spectrum, *spectrum_e, + st->tcx_lpc_shaped_ari, + gainlpc, gainlpc_e, + L_frame, + xn_buf16 /* LF deemphasis factors */ + ); + } + + tcx_get_gain(x_orig, x_orig_e, + spectrum, *spectrum_e, + L_spec, + &gain_tcx_opt, &gain_tcx_opt_e, + &ener, &ener_e); + + IF (gain_tcx_opt <= 0) + { + gain_tcx_opt = sqGain; + move16(); + gain_tcx_opt_e = sqGain_e; + move16(); + } + gain_tcx = gain_tcx_opt; + move16(); + gain_tcx_e = gain_tcx_opt_e; + move16(); + + /* Save gains for FAC and Residual Q*/ + + /*-----------------------------------------------------------* + * Quantize TCX gain * + *-----------------------------------------------------------*/ + + IF (GE_32(st->total_brate_fx, ACELP_13k20)&&st->rf_mode==0) + { + QuantizeGain(L_spec, &gain_tcx, &gain_tcx_e, &prm[0]); + } + + + /*-----------------------------------------------------------* + * Residual Quantization * + *-----------------------------------------------------------*/ + + IF (tcx_cfg->resq) + { + + resQTargetBits = sub(sqTargetBits, sqBits); + + IF (st->tcx_lpc_shaped_ari) /* new arithmetic coder */ + { + Word16 *prm_resq; + + prm_resq = sqQ + sqTargetBits - resQTargetBits; + + resQBits = tcx_ari_res_Q_spec(x_orig, x_orig_e, signs, spectrum, *spectrum_e, L_spec, gain_tcx, gain_tcx_e, + prm_resq, + resQTargetBits, + resQBits, + tcx_cfg->sq_rounding, + xn_buf16 /* LF deemphasis factors */ ); + + /* Transmit zeros when there bits remain after RESQ */ + set16_fx(prm_resq+resQBits, 0, sub(resQTargetBits, resQBits)); + } + ELSE /* old arithmetic coder */ + { + move16(); + tmpP16 = NULL; + if (tcxonly == 0) + { + move16(); + tmpP16 = xn_buf16; + } + + resQBits = tcx_res_Q_gain(gain_tcx_opt, gain_tcx_opt_e, + &gain_tcx, &gain_tcx_e, + &sqQ[L_spec], + resQTargetBits); + + resQBits = tcx_res_Q_spec(x_orig, x_orig_e, + spectrum, *spectrum_e, + L_spec, + gain_tcx, gain_tcx_e, + &sqQ[L_spec], + resQTargetBits, + resQBits, + tcx_cfg->sq_rounding, + tmpP16 /* LF deemphasis factors */ ); + } + + + } + + + /*-----------------------------------------------------------* + * ALFE tcx only bitrates * + *-----------------------------------------------------------*/ + + IF (st->tcxonly != 0) + { + test(); + test(); + IF (st->tcxltp != 0 && (st->tcxltp_gain > 0) && fUseTns == 0) + { + + PsychAdaptLowFreqDeemph(spectrum, gainlpc, gainlpc_e, NULL); + } + } + + /*-----------------------------------------------------------* + * TCX SNR for Analysis purposes * + *-----------------------------------------------------------*/ + + { + maxNfCalcBw = s_min(noiseFillingSize, round_fx(L_shl(L_mult(st->measuredBwRatio, L_frame), 1))); + + /*-----------------------------------------------------------* + * Estimate and quantize noise factor * + *-----------------------------------------------------------*/ + + IF (GE_32(st->total_brate_fx, HQ_96k)) + { + fac_ns = 0; + move16(); + prm[1] = 0; + move16(); + } + ELSE + { + /* noise filling start bin */ + i = shr(L_frame, 3); + IF (GE_32(st->total_brate_fx, ACELP_13k20)&&st->rf_mode==0) + { + i = idiv1616U(L_frame, 6); + } + + IF (tcxonly) + { + tmp1 = 0; + move16(); + test(); + test(); + if ((tcx_cfg->ctx_hm != 0) && (st->last_core_fx != ACELP_CORE) && (prm_hm[0] != 0)) + { + tmp1 = 10240/*0.3125f Q15*/; + move16(); + } + noiseTransWidth = HOLE_SIZE_FROM_LTP(s_max(st->tcxltp_gain, tmp1)); + + if (EQ_16(L_frame, shr(st->L_frame_fx, 1))) + { + /* minimum transition for noise filling in TCX-10 */ + noiseTransWidth = 3; + move16(); + } + } + + tcx_noise_factor( x_orig, x_orig_e, + spectrum, + i, + maxNfCalcBw, + noiseTransWidth, + L_frame, + gain_tcx, gain_tcx_e, + st->noiseTiltFactor, + &fac_ns, &prm[NOISE_FILL_RANGES] ); + + /* hysteresis for very tonal passages (more stationary noise filling level) */ + + IF (EQ_16(prm[NOISE_FILL_RANGES], 1)) + { + st->noiseLevelMemory = add(1, abs_s(st->noiseLevelMemory)); /* update counter */ + } + ELSE { + test(); + IF ((EQ_16(prm[NOISE_FILL_RANGES], 2))&& + (GT_16(abs_s(st->noiseLevelMemory), 5))) + { + /* reduce noise filling level by one step */ + prm[NOISE_FILL_RANGES] = 1; + move16(); + fac_ns = shr(0x6000, NBITS_NOISE_FILL_LEVEL); + + /* signal that noise level is changed by inverting sign of level memory */ + tmp1 = 5; + move16(); + if (st->noiseLevelMemory >= 0) + { + tmp1 = sub(-1, st->noiseLevelMemory); + } + st->noiseLevelMemory = tmp1; + } + ELSE { + /* reset memory since level is too different */ + st->noiseLevelMemory = 0; + move16(); + } + } + + } /* bitrate */ + } + + /* Free encoder specific stack to use it below for the internal TCX decoder. */ + } + + /*-----------------------------------------------------------* + * Internal TCX decoder * + *-----------------------------------------------------------*/ + { + /* Overlay of a 16-bit buffer xn_buf16 with a 32-bit buffer xn_buf32 */ + /* The size is determined by the requirements of the 16-bit buffer. */ + Word32 xn_buf32[(L_MDCT_OVLP_MAX+L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2]; + Word16 *xn_buf16 = (Word16*)xn_buf32; + + /*Enable internal TCX decoder to run always to update LPD memory for rate switching */ + + IF (tcxonly == 0) + { + } + + /*-----------------------------------------------------------* + * Noise Filling. * + *-----------------------------------------------------------*/ + + /* Replication of ACELP formant enhancement for low rates */ + IF ( LT_32(st->total_brate_fx, ACELP_13k20)||st->rf_mode!=0) + { + tcxFormantEnhancement(xn_buf16, gainlpc, gainlpc_e, spectrum, spectrum_e, L_frame, L_spec); + } + + IF (fac_ns > 0) + { + tmp1 = 0; + move16(); + if ( GE_32(st->total_brate_fx, ACELP_13k20)&&st->rf_mode==0) + { + tmp1 = 1; + move16(); + } + + i = tcxGetNoiseFillingTilt(A, + M, + L_frame, + tmp1, + &st->noiseTiltFactor); + + tcx_noise_filling(spectrum, *spectrum_e, + nf_seed /* seed */, + i, + noiseFillingSize, + noiseTransWidth, + L_frame, + st->noiseTiltFactor, + fac_ns, + NULL + ); + } + + IF (LT_32(st->total_brate_fx, ACELP_13k20)||st->rf_mode!=0) + { + /* partially recompute global gain (energy part), taking noise filling and formant enhancement into account */ + s = sub(getScaleFactor32(spectrum, L_spec), 4); + tmp32 = L_deposit_l(1); + + FOR (i = 0; i < L_spec; i++) + { + tmp1 = round_fx(L_shl(spectrum[i], s)); + tmp32 = L_mac0(tmp32, tmp1, tmp1); + } + + tmp1 = BASOP_Util_Divide3232_Scale(ener, tmp32, &tmp2); + tmp2 = add(tmp2, sub(ener_e, add(shl(sub(*spectrum_e, s), 1), 1))); + tmp1 = Sqrt16(tmp1, &tmp2); + + gain_tcx = mult(gain_tcx, tmp1); + gain_tcx_e = add(gain_tcx_e, tmp2); + + QuantizeGain(L_spec, &gain_tcx, &gain_tcx_e, &prm[0]); + } + + /*end of noise filling*/ + + /*-----------------------------------------------------------* + * Noise shaping in frequency domain (1/Wz) * + *-----------------------------------------------------------*/ + + /* LPC gains already available */ + mdct_shaping(spectrum, L_frame, gainlpc, gainlpc_e); + + /*-----------------------------------------------------------* + * Apply gain * + *-----------------------------------------------------------*/ + IF (EQ_16(st->tcx_cfg.coder_type, INACTIVE)) + { + gain_tcx = mult_r(gain_tcx, tcx_cfg->na_scale); + } + + FOR (i = 0; i < L_spec; i++) + { + spectrum[i] = Mpy_32_16_1(spectrum[i], gain_tcx); + move32(); + } + *spectrum_e = add(*spectrum_e, gain_tcx_e); + move16(); + + stop = tcx_cfg->tcx_last_overlap_mode; /* backup last TCX overlap mode */ move16(); + + test(); + IF ((EQ_16(L_frame, shr(st->L_frame_fx, 1)))&&(tcxonly!=0)) + { + Word16 L = L_frame; + move16(); + + test(); + test(); + if (((tcx_cfg->fIsTNSAllowed != 0) && (fUseTns != 0)) || (GT_16(L_spec, L_frame))) + { + L = L_spec; + move16(); + } + + tcxInvertWindowGrouping(tcx_cfg, + xn_buf32, + spectrum, + L, + fUseTns, + st->last_core_fx, + stop, + frame_cnt, + 0); + } + + /*-----------------------------------------------------------* + * Temporal Noise Shaping Synthesis * + *-----------------------------------------------------------*/ + + IF (tcx_cfg->fIsTNSAllowed != 0) + { + test(); + test(); + test(); + SetTnsConfig(tcx_cfg, sub(L_frame_glob, st->L_frame_fx) == 0, (st->last_core_fx == ACELP_CORE) && (frame_cnt == 0)); + + /* Apply TNS to get the reconstructed signal */ + IF (fUseTns != 0) + { + ApplyTnsFilter(tcx_cfg->pCurrentTnsConfig, pTnsData, spectrum, 0); + + test(); + IF ((EQ_16(L_frame, shr(st->L_frame_fx, 1)))&&(tcxonly!=0)) + { + test(); + test(); + test(); + IF ( (tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) || + ((tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP) && (frame_cnt == 0) && (stop == 0)) ) + { + tmp1 = shr(L_spec, 1); + /* undo rearrangement of LF sub-window lines for TNS synthesis filter */ + assert(L_frame <= L_spec); + Copy32(spectrum+8, xn_buf32, 8); + Copy32(spectrum+16, spectrum+8, sub(tmp1,8)); + Copy32(xn_buf32, spectrum+tmp1, 8); + } + } + } + } + + { + /* normalize spectrum to minimize IMDCT noise */ + s = getScaleFactor32(spectrum, L_frame); + FOR (i = 0; i < L_frame; i++) + { + spectrum[i] = L_shl(spectrum[i], s); + move32(); + } + *spectrum_e = sub(*spectrum_e, s); + + /*-----------------------------------------------------------* + * Compute inverse MDCT of spectrum[]. * + *-----------------------------------------------------------*/ + test(); + IF ((EQ_16(L_frame, shr(st->L_frame_fx, 1)))&&(tcxonly!=0)) + { + IF (tcx_cfg->tcx_last_overlap_mode != FULL_OVERLAP) + { + Word16 win[(L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2]; + Word16 L_win, L_spec_TCX5, L_ola, w; + + /* minimum or half overlap, two transforms, grouping into one window */ + L_win = shr(L_frame, 1); + L_spec_TCX5 = shr(s_max(L_frame, L_spec), 1); + L_ola = tcx_cfg->tcx_mdct_window_half_length; + move16(); + if ( EQ_16(tcx_cfg->tcx_last_overlap_mode, MIN_OVERLAP)) + { + L_ola = tcx_cfg->tcx_mdct_window_min_length; + move16(); + } + + set16_fx(win, 0, (L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2); + set16_fx(xn_buf16, 0, add(tcx_offset, shr(L_ola, 1))); /* zero left end of buffer */ + + FOR (w = 0; w < 2; w++) + { + + IF (EQ_16(tcx_cfg->tcx_last_overlap_mode, MIN_OVERLAP)) + { + TCX_MDCT_Inverse(spectrum + L_mult0(w, L_spec_TCX5), sub(*spectrum_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM), + win, + L_ola, sub(L_win, L_ola), L_ola); + } + ELSE + { + TCX_MDCT_Inverse(spectrum + L_mult0(w, L_spec_TCX5), sub(*spectrum_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM), + win, + L_ola, sub(L_win, L_ola), L_ola); + } + + tmp1 = tcx_cfg->tcx_last_overlap_mode; + move16(); + test(); + test(); + if ((w > 0) || ((w == 0) && (EQ_16(stop, 2)))) + { + tmp1 = MIN_OVERLAP; + move16(); + } + + tmp2 = 0; + move16(); + test(); + if ((w == 0) && (st->last_core_fx == ACELP_CORE)) + { + tmp2 = 1; + move16(); + } + + tmp3 = st->last_core_fx; + move16(); + if (w > 0) + { + tmp3 = 1; + move16(); + } + + tmp4 = 0; + move16(); + if (tcx_offset < 0) + { + tmp4 = negate(tcx_offset); + } + + tcx_windowing_synthesis_current_frame(win, + tcx_cfg->tcx_aldo_window_2, + tcx_cfg->tcx_mdct_window_half, + tcx_cfg->tcx_mdct_window_minimum, + L_ola, + tcx_cfg->tcx_mdct_window_half_length, + tcx_cfg->tcx_mdct_window_min_length, + tmp2, + tmp1, + LPDmem->acelp_zir, + st->LPDmem.Txnq, + NULL, + Aq_old, + tcx_cfg->tcx_mdct_window_trans, + L_win, + tmp4, + tmp3, + 0, + 0 + ); + + tmp1 = add(tcx_offset, imult1616(w, L_win)); + move16(); + tmpP16 = xn_buf16 + sub(tmp1, shr(L_ola, 1)); + + IF (w > 0) + { + tcx_windowing_synthesis_past_frame(tmpP16, + tcx_cfg->tcx_aldo_window_1_trunc, + tcx_cfg->tcx_mdct_window_half, + tcx_cfg->tcx_mdct_window_minimum, + L_ola, + tcx_cfg->tcx_mdct_window_half_length, + tcx_cfg->tcx_mdct_window_min_length, + 2 + ); + } + /* add part of current sub-window overlapping with previous window */ + FOR (i = 0; i < L_ola; i++) + { + tmpP16[i] = add(tmpP16[i], win[i]); + move16(); + } + /* copy new sub-window region not overlapping with previous window */ + Copy(win + L_ola, xn_buf16 + add(tmp1, shr(L_ola, 1)), L_win); + } + /* To assure that no garbage values are copied to LPDmem->Txnq */ + set16_fx(xn_buf16 + add(add(L_frame, tcx_offset), shr(L_ola, 1)), + 0, sub(sub(overlap, tcx_offset), shr(L_ola, 1))); + + + } + ELSE IF ( s_and(frame_cnt == 0, (tcx_cfg->tcx_curr_overlap_mode == FULL_OVERLAP)) ) + { + /* special overlap attempt, two transforms, grouping into one window */ + Word16 win[(L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2]; + Word16 L_win, L_spec_TCX5, L_ola, w; + + L_win = shr(L_frame, 1); + L_spec_TCX5 = shr(s_max(L_frame, L_spec), 1); + L_ola = tcx_cfg->tcx_mdct_window_min_length; + move16(); + + set16_fx(win, 0, (L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2); + + /* Resize overlap (affect only asymmetric window)*/ + overlap = st->tcx_cfg.tcx_mdct_window_delay; + /* 1st TCX-5 window, special MDCT with minimum overlap on right side */ + TCX_MDCT_Inverse(spectrum, sub(*spectrum_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM), + win + L_win, + 0, sub(L_win, shr(L_ola, 1)), L_ola); + + /* copy new sub-window region not overlapping with previous window */ + Copy(win+L_win, xn_buf16+shr(overlap, 1), add(L_win, shr(L_ola, 1))); + + /* 2nd TCX-5 window, regular MDCT with minimum overlap on both sides */ + + TCX_MDCT_Inverse(spectrum + L_spec_TCX5, sub(*spectrum_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM), + win, + L_ola, sub(L_win, L_ola), L_ola); + + tmp4 = 0; + move16(); + if (tcx_offset <0) + { + tmp4 = negate(tcx_offset); + } + tcx_windowing_synthesis_current_frame(win, + tcx_cfg->tcx_aldo_window_2, + tcx_cfg->tcx_mdct_window_half, + tcx_cfg->tcx_mdct_window_minimum, + L_ola, + tcx_cfg->tcx_mdct_window_half_length, + tcx_cfg->tcx_mdct_window_min_length, + 0, /* left_rect */ + 2, /* left_mode */ + LPDmem->acelp_zir, + st->LPDmem.Txnq, + NULL, + Aq_old, + tcx_cfg->tcx_mdct_window_trans, + L_win, + tmp4, + 1, /* not LPDmem->mode */ + 0, + 0 + ); + + + move16(); + tmpP16 = xn_buf16 + add(sub(L_win, shr(L_ola, 1)), shr(overlap,1)); + + tcx_windowing_synthesis_past_frame(tmpP16, + tcx_cfg->tcx_aldo_window_1_trunc, + tcx_cfg->tcx_mdct_window_half, + tcx_cfg->tcx_mdct_window_minimum, + L_ola, + tcx_cfg->tcx_mdct_window_half_length, + tcx_cfg->tcx_mdct_window_min_length, + 2 + ); + + /* add part of current sub-window overlapping with previous window */ + FOR (i = 0; i < L_ola; i++) + { + tmpP16[i] = add(tmpP16[i], win[i]); + move16(); + } + + /* copy new sub-window region not overlapping with previous window */ + Copy(win + L_ola, + xn_buf16 + add(add(shr(overlap,1), shr(L_ola, 1)), L_win), + L_win); + + /* extra folding-out on left side of win, for perfect reconstruction */ + FOR (w = shr(overlap,1); w < overlap; w++) + { + xn_buf16[overlap-1-w] = negate(xn_buf16[w]); + move16(); + } + + tmp4 = 0; + move16(); + if (tcx_offset < 0) + { + tmp4 = negate(tcx_offset); + } + tcx_windowing_synthesis_current_frame(xn_buf16, + tcx_cfg->tcx_aldo_window_2, + tcx_cfg->tcx_mdct_window_half, + tcx_cfg->tcx_mdct_window_minimum, + overlap, + tcx_cfg->tcx_mdct_window_half_length, + tcx_cfg->tcx_mdct_window_min_length, + st->last_core_fx==ACELP_CORE, + 0, + LPDmem->acelp_zir, + st->LPDmem.Txnq, + NULL, + Aq_old, + tcx_cfg->tcx_mdct_window_trans, + L_win, + tmp4, + st->last_core_fx, + 0, + 0 + ); + } + ELSE /* default, i.e. maximum overlap, single transform, no grouping */ + { + + TCX_MDCT_Inverse(spectrum, sub(*spectrum_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM), + xn_buf16, + overlap, sub(L_frame, overlap), overlap); + + tmp1 = stop; + move16(); + test(); + test(); + if ((frame_cnt > 0) && (stop == 0) && (st->last_core_fx != ACELP_CORE)) + { + tmp1 = 2; + move16(); + } + + tmp4 = 0; + move16(); + if (tcx_offset <0) + { + tmp4 = negate(tcx_offset); + } + tcx_windowing_synthesis_current_frame(xn_buf16, + tcx_cfg->tcx_aldo_window_2, + tcx_cfg->tcx_mdct_window_half, + tcx_cfg->tcx_mdct_window_minimum, + overlap, /*tcx_cfg->tcx_mdct_window_length*/ + tcx_cfg->tcx_mdct_window_half_length, + tcx_cfg->tcx_mdct_window_min_length, + st->last_core_fx==ACELP_CORE, + tmp1, + LPDmem->acelp_zir, + st->LPDmem.Txnq, + NULL, + Aq_old, + tcx_cfg->tcx_mdct_window_trans, + shr(L_frame_glob, 1), + tmp4, + st->last_core_fx, + 0, + 0 + ); + + } /* tcx_last_overlap_mode > 0 */ + + } + ELSE /* frame is TCX-20 or not TCX-only */ + { + IF (NE_16(st->tcx_cfg.tcx_last_overlap_mode, TRANSITION_OVERLAP)) + { + Word32 tmp_buf[L_FRAME_PLUS]; + Word16 Q; + + /* DCT */ + Q = sub(31, *spectrum_e); + edct_fx(spectrum, tmp_buf, L_frame, &Q); + + /* scale by sqrt(L / NORM_MDCT_FACTOR) */ + tmp1 = mult_r(shl(L_frame, 4), 26214/*128.f / NORM_MDCT_FACTOR Q15*/); /* 4Q11 */ + tmp2 = 4; + move16(); + tmp1 = Sqrt16(tmp1, &tmp2); + + FOR (i = 0; i < L_frame; i++) + { + tmp_buf[i] = Mpy_32_16_1(tmp_buf[i], tmp1); + move32(); + } + Q = sub(Q, tmp2); + + + window_ola_fx(tmp_buf, + xn_buf16, + &Q, + st->old_out_fx, + &st->Q_old_out, + L_frame, + tcx_cfg->tcx_last_overlap_mode, + tcx_cfg->tcx_curr_overlap_mode, + 0, + 0, + NULL); + + /* scale output */ + FOR (i = 0; i < L_frame; i++) + { + xn_buf16[i] = shr(xn_buf16[i], Q); + move16(); + } + + aldo = 1; + move16(); + } + ELSE + { + + TCX_MDCT_Inverse(spectrum, sub(*spectrum_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM), + xn_buf16, + overlap, sub(L_frame, overlap), overlap); + + /*-----------------------------------------------------------* + * Windowing, overlap and add * + *-----------------------------------------------------------*/ + + /* Window current frame */ + tmp4 = 0; + move16(); + if (tcx_offset<0) + { + tmp4 = negate(tcx_offset); + } + tcx_windowing_synthesis_current_frame(xn_buf16, + tcx_cfg->tcx_aldo_window_2, + tcx_cfg->tcx_mdct_window_half, + tcx_cfg->tcx_mdct_window_minimum, + overlap, /*tcx_cfg->tcx_mdct_window_length*/ + tcx_cfg->tcx_mdct_window_half_length, + tcx_cfg->tcx_mdct_window_min_length, + st->last_core_fx==ACELP_CORE, + tcx_cfg->tcx_last_overlap_mode, /*left mode*/ + LPDmem->acelp_zir, + st->LPDmem.Txnq, + NULL, + Aq_old, + tcx_cfg->tcx_mdct_window_trans, + shr(L_frame_glob, 1), + tmp4, + st->last_core_fx, + 0, + 0 + ); + } + } /* TCX-10 and TCX-only */ + + /* Window and overlap-add past frame if past frame is TCX */ + test(); + test(); + test(); + IF ((st->last_core_fx > ACELP_CORE) && (((EQ_16(L_frameTCX, shr(st->L_frameTCX, 1)))&&(st->tcxonly!=0))||(EQ_16(st->tcx_cfg.tcx_last_overlap_mode,TRANSITION_OVERLAP)))) + { + + IF (tcx_cfg->last_aldo != 0) + { + tmp2 = add(st->Q_old_out, TCX_IMDCT_HEADROOM); + + tmp1 = sub(overlap, tcx_cfg->tcx_mdct_window_min_length); + FOR (i=0; i < tmp1; i++) + { + xn_buf16[i] = shl(add(xn_buf16[i], shr(st->old_out_fx[i+nz], tmp2)), TCX_IMDCT_HEADROOM); + move16(); + } + + /* fade truncated ALDO window */ + tmp1 = sub(overlap, shr(tcx_cfg->tcx_mdct_window_min_length, 1)); + FOR ( ; i < tmp1; i++) + { + tmp3 = mult_r(shr(st->old_out_fx[i+nz], tmp2), tcx_cfg->tcx_mdct_window_minimum[i-overlap+tcx_cfg->tcx_mdct_window_min_length].v.re); + xn_buf16[i] = shl(add(xn_buf16[i], tmp3), TCX_IMDCT_HEADROOM); + move16(); + } + FOR ( ; i < overlap; i++) + { + tmp3 = mult_r(shr(st->old_out_fx[i+nz], tmp2), tcx_cfg->tcx_mdct_window_minimum[overlap-1-i].v.im); + xn_buf16[i] = shl(add(xn_buf16[i], tmp3), TCX_IMDCT_HEADROOM); + move16(); + } + + FOR ( ; i < L_frame; i++) + { + xn_buf16[i] = shl(xn_buf16[i], TCX_IMDCT_HEADROOM); + move16(); + } + } + ELSE + { + test(); + test(); + test(); + if ((frame_cnt > 0) && (stop == 0) && (tcx_cfg->tcx_curr_overlap_mode == 0) && (st->last_core_fx != ACELP_CORE)) + { + stop = 2; /* use minimum overlap between the two TCX-10 windows */ move16(); + } + + tmp1 = stop; + move16(); + test(); + if ((stop == 0) || (EQ_16(tcx_cfg->tcx_last_overlap_mode, MIN_OVERLAP))) + { + tmp1 = tcx_cfg->tcx_last_overlap_mode; + move16(); + } + + tcx_windowing_synthesis_past_frame( LPDmem->Txnq + , + tcx_cfg->tcx_aldo_window_1_trunc, + tcx_cfg->tcx_mdct_window_half, + tcx_cfg->tcx_mdct_window_minimum, + overlap, + tcx_cfg->tcx_mdct_window_half_length, + tcx_cfg->tcx_mdct_window_min_length, + tmp1 + ); + + BASOP_SATURATE_WARNING_OFF; + FOR (i=0; iTxnq[i]), TCX_IMDCT_HEADROOM); + move16(); + } + + IF (LT_16(i, L_frame)) + { + FOR ( ; i < L_frame; i++) + { + xn_buf16[i] = shl(xn_buf16[i], TCX_IMDCT_HEADROOM); + move16(); + } + } + BASOP_SATURATE_WARNING_ON; + } + } + ELSE + { + IF (aldo == 0) + { + BASOP_SATURATE_WARNING_OFF; + FOR (i = 0; i < L_frame; i++) + { + xn_buf16[i] = shl(xn_buf16[i], TCX_IMDCT_HEADROOM); + move16(); + } + BASOP_SATURATE_WARNING_ON; + } + } + + test(); + test(); + test(); + IF ( (aldo == 0) && + ((EQ_16(L_frameTCX, shr(st->L_frameTCX, 1)) && frame_cnt > 0) || + NE_16(L_frameTCX, shr(st->L_frameTCX, 1)) ) ) + { + /*Compute windowed synthesis in case of switching to ALDO windows in next frame*/ + FOR (i = 0; i < nz; i++) + { + st->old_out_fx[i] = shr(xn_buf16[L_frame-nz+i], TCX_IMDCT_HEADROOM); + move16(); + } + Copy(xn_buf16+L_frame, st->old_out_fx+nz, overlap); + set16_fx(st->old_out_fx+nz+overlap, 0, nz); + + tcx_windowing_synthesis_past_frame( st->old_out_fx+nz, + tcx_cfg->tcx_aldo_window_1_trunc, + tcx_cfg->tcx_mdct_window_half, + tcx_cfg->tcx_mdct_window_minimum, + overlap, + tcx_cfg->tcx_mdct_window_half_length, + tcx_cfg->tcx_mdct_window_min_length, + tcx_cfg->tcx_curr_overlap_mode + ); + + /* If current overlap mode = FULL_OVERLAP -> ALDO_WINDOW */ + IF (EQ_16(tcx_cfg->tcx_curr_overlap_mode, FULL_OVERLAP)) + { + FOR (i=0; iold_out_fx[nz+overlap+i] = shr(mult_r(xn_buf16[L_frame-1-i], tcx_cfg->tcx_aldo_window_1[nz-1-i]), TCX_IMDCT_HEADROOM); + move16(); + } + tcx_cfg->tcx_curr_overlap_mode = ALDO_WINDOW; + move16(); + } + + st->Q_old_out = -TCX_IMDCT_HEADROOM; + move16(); + } + tcx_cfg->last_aldo = aldo; + move16(); + + /* Update Txnq */ + IF (tcx_cfg->last_aldo == 0) + { + Copy(xn_buf16 + L_frame, LPDmem->Txnq, overlap); + } + + + /* Output */ + Copy(xn_buf16+shr(overlap,1)-tcx_offset, synth, L_frame_glob); + + } + + /* Free internal TCX decoder stack memory */ + } + + /* Update L_frame_past */ + st->L_frame_past = L_frame; + move16(); + +} + + +void coder_tcx( + Word16 n, + TCX_config *tcx_cfg, /*input: configuration of TCX*/ + Word16 A[], /* input: quantized coefficients NxAz_q[M+1] */ + Word16 Aqind[], /* input: frame-independent quantized coefficients (M+1) */ + Word16 synth[], + Word16 L_frame_glob, /* input: frame length */ + Word16 L_frameTCX_glob, + Word16 L_spec, + Word16 nb_bits, /*input: bit budget*/ + Word8 tcxonly, /*input: only TCX flag*/ + Word32 spectrum[], /* i/o: MDCT spectrum */ + Word16 *spectrum_e, /* i/o: MDCT spectrum exponent */ + LPD_state *LPDmem, /*i/o: memories*/ + Word16 prm[], /* output: tcx parameters */ + Encoder_State_fx *st, + CONTEXT_HM_CONFIG *hm_cfg +) +{ + Word16 L_frame; + Word16 left_overlap, right_overlap; + Word16 tnsSize; /* number of tns parameters put into prm */ + Word16 tnsBits; /* number of tns bits in the frame */ + Word16 ltpBits; + Word16 gainlpc[FDNS_NPTS], gainlpc_e[FDNS_NPTS]; + Word16 win[N_MAX+L_MDCT_OVLP_MAX]; + Word32 powerSpec[N_MAX]; + Word16 powerSpec_e; + Word16 winMDST[N_MAX+L_MDCT_OVLP_MAX]; + Word16 *pWinMDST; + Word16 left_overlap_mode, right_overlap_mode; + + + left_overlap = right_overlap = -1; + move16(); + move16(); + tnsSize = 0; + move16(); + tnsBits = 0; + move16(); + ltpBits = 0; + move16(); + + L_frame = L_frameTCX_glob; + move16(); + + /*-----------------------------------------------------------* + * Windowing * + *-----------------------------------------------------------*/ + IF (EQ_16(st->tcx_cfg.tcx_last_overlap_mode, TRANSITION_OVERLAP)) + { + + WindowSignal(tcx_cfg, + tcx_cfg->tcx_offsetFB, + tcx_cfg->tcx_last_overlap_mode, + tcx_cfg->tcx_curr_overlap_mode, + &left_overlap, &right_overlap, + st->speech_TCX, + &L_frame, + win + ,1 + ); + + /*-----------------------------------------------------------* + * Compute MDCT * + *-----------------------------------------------------------*/ + + *spectrum_e = 16; + move16(); + TCX_MDCT(win, spectrum, spectrum_e, left_overlap, sub(L_frame, shr(add(left_overlap, right_overlap), 1)), right_overlap); + } + ELSE + { + Word32 tmp_buf[L_FRAME_PLUS]; + Word16 Q, tmp1, tmp2, i; + + Q = 0; + move16(); + + wtda_fx(st->new_speech_TCX, + &Q, + tmp_buf, + NULL, + NULL, + tcx_cfg->tcx_last_overlap_mode, + tcx_cfg->tcx_curr_overlap_mode, + L_frame); + + left_overlap_mode = tcx_cfg->tcx_last_overlap_mode; + move16(); + if (EQ_16(left_overlap_mode, ALDO_WINDOW)) + { + left_overlap_mode = FULL_OVERLAP; + move16(); + } + right_overlap_mode = tcx_cfg->tcx_curr_overlap_mode; + move16(); + if (EQ_16(right_overlap_mode, ALDO_WINDOW)) + { + right_overlap_mode = FULL_OVERLAP; + move16(); + } + + WindowSignal( tcx_cfg, tcx_cfg->tcx_offsetFB, + left_overlap_mode, right_overlap_mode, + &left_overlap, &right_overlap, st->speech_TCX, &L_frame, winMDST, 1 ); + + /* scale by NORM_MDCT_FACTOR / L */ + tmp1 = mult_r(shl(L_frame, 4), 26214/*128.f / NORM_MDCT_FACTOR Q15*/); /* 4Q11 */ + tmp2 = 4; + move16(); + tmp1 = ISqrt16(tmp1, &tmp2); + + FOR (i = 0; i < L_frame; i++) + { + tmp_buf[i] = Mpy_32_16_1(tmp_buf[i], tmp1); + move32(); + } + Q = sub(Q, tmp2); + + /* DCT */ + edct_fx(tmp_buf, spectrum, L_frame, &Q); + *spectrum_e = sub(31, Q); + } + + + /*-----------------------------------------------------------* + * Attenuate upper end of NB spectrum, * + * to simulate ACELP behavior * + *-----------------------------------------------------------*/ + + IF (st->narrowBand != 0) + { + attenuateNbSpectrum(L_frame, spectrum); + } + + /*-----------------------------------------------------------* + * Compute noise-measure flags for spectrum filling * + * and quantization (0: tonal, 1: noise-like). * + * Detect low pass if present. * + *-----------------------------------------------------------*/ + + pWinMDST = winMDST; + move16(); + if (EQ_16(st->tcx_cfg.tcx_last_overlap_mode, TRANSITION_OVERLAP)) + { + pWinMDST = win; + move16(); + } + + AnalyzePowerSpectrum(st, + round_fx(L_shl(Mpy_32_16_1(L_mult0(L_frame,st->L_frame_fx)/*Q0*/, + getInvFrameLen(st->L_frameTCX)/*Q21*/)/*Q6*/,16-6)), + L_frame, + left_overlap, right_overlap, + spectrum, *spectrum_e, + pWinMDST, + powerSpec, &powerSpec_e); + IF (tcx_cfg->fIsTNSAllowed != 0) + { + test(); + test(); + SetTnsConfig(tcx_cfg, sub(L_frame_glob, st->L_frame_fx) == 0, st->last_core_fx == 0); + + TNSAnalysis(tcx_cfg, L_frame, L_spec, TCX_20, st->last_core_fx == 0, spectrum, st->tnsData, st->fUseTns + , &st->hIGFEnc.tns_predictionGain + ); + + } + ELSE + { + st->fUseTns[0] = st->fUseTns[1] = 0; + move16(); + move16(); + } + + IF(st->igf) + { + ProcessIGF(&st->hIGFEnc, st, spectrum, spectrum_e, powerSpec, &powerSpec_e, 1, st->fUseTns[0], (st->last_core_fx == ACELP_CORE), 0); + } + + ShapeSpectrum(tcx_cfg, A, gainlpc, gainlpc_e, + L_frame_glob, + L_spec, + spectrum, + st->fUseTns[0], + st + ); + if(st->igf) + { + nb_bits = sub(nb_bits, st->hIGFEnc.infoTotalBitsPerFrameWritten); + } + IF (tcx_cfg->fIsTNSAllowed != 0) + { + EncodeTnsData(tcx_cfg->pCurrentTnsConfig, st->tnsData, prm+1+NOISE_FILL_RANGES+LTPSIZE, &tnsSize, &tnsBits); + } + + QuantizeSpectrum(tcx_cfg, + A, + Aqind, + gainlpc, gainlpc_e, + synth, + L_frame_glob, + L_frameTCX_glob, + L_spec, + sub(sub(nb_bits, tnsBits), ltpBits), + tcxonly, + spectrum, spectrum_e, + st->tnsData, + st->fUseTns[0], + tnsSize, + LPDmem, + prm, + n, + st, + hm_cfg + ); + + LPDmem->nbits = add(LPDmem->nbits, add(tnsBits, ltpBits)); + +} + + +/*-------------------------------------------------------------------* +* coder_tcx_post() +* +* +*-------------------------------------------------------------------*/ + +void coder_tcx_post(Encoder_State_fx *st, + LPD_state *LPDmem, + TCX_config *tcx_cfg, + Word16 *synth, + const Word16 *A, + const Word16 *Ai, + Word16 *wsig, + Word16 Q_new, + Word16 shift + ) +{ + Word16 xn_buf[L_FRAME_MAX]; + + /* TCX output */ + Copy( synth, xn_buf, st->L_frame_fx ); + + + /*-----------------------------------------------------------* + * Memory update * + *-----------------------------------------------------------*/ + + /* Update LPDmem (Txnq,syn,syn_pe,old_exc,wsyn,Ai,Aq) */ + tcx_encoder_memory_update( wsig, xn_buf, st->L_frame_fx, Ai, A, tcx_cfg->preemph_fac, LPDmem, st, synth, Q_new, shift ); + + return; +} diff --git a/lib_enc/cod_uv.c b/lib_enc/cod_uv.c new file mode 100644 index 0000000..bff71e0 --- /dev/null +++ b/lib_enc/cod_uv.c @@ -0,0 +1,88 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include +#include "prot_fx.h" +#include "stl.h" + +/*-------------------------------------------------------------------* + * gauss_L2: + * + * encode an additional Gaussian excitation for unvoiced subframes and compute + * associated xcorrelations for gains computation + * + * Gaussian excitation is generated by a white noise and shapes it with LPC-derived filter + *-------------------------------------------------------------------*/ +void gauss_L2( + const Word16 h[], /* i : weighted LP filter impulse response Q14+s */ + Word16 code[], /* o : gaussian excitation Q9 */ + const Word16 y2[], /* i : zero-memory filtered code. excitation Q9 */ + Word16 y11[], /* o : zero-memory filtered gauss. excitation Q9 */ + Word32 *gain, /* o : excitation gain Q16 */ + ACELP_CbkCorr *g_corr, /*i/o : correlation structure for gain coding */ + const Word16 gain_pit, /* i : unquantized gain of code Q14 */ + const Word16 tilt_code, /* i : tilt of code Q15 */ + const Word16 *Aq, /* i : quantized LPCs Q12 */ + const Word16 formant_enh_num, /* i : formant enhancement numerator factor Q15 */ + Word16 *seed_acelp, /*i/o : random seed Q0 */ + const Word16 shift +) +{ + Word16 i, tmp16; + Word32 tmp32, tmp32_2; + + + assert(gain_pit==0); + + /*-----------------------------------------------------------------* + * Find new target for the Gaussian codebook + *-----------------------------------------------------------------*/ + + /*Generate white gaussian noise using central limit theorem method (N only 4 as E_util_random is not purely uniform)*/ + FOR (i = 0; i < L_SUBFR; i++) + { + *seed_acelp = own_random2_fx(*seed_acelp); + tmp32 = L_mac(0, *seed_acelp, 1<<9); + + *seed_acelp = own_random2_fx(*seed_acelp); + tmp32 = L_mac(tmp32, *seed_acelp, 1<<9); + + *seed_acelp = own_random2_fx(*seed_acelp); + code[i] = mac_r(tmp32, *seed_acelp, 1<<9); + move16(); + } + + /*Shape the gaussian excitation*/ + cb_shape_fx( 1, 0, 0, 1, 0, formant_enh_num, FORMANT_SHARPENING_G2, Aq, code, tilt_code, 0, 1 ); + + /*compute 0s memory weighted synthesis contribution and find gain*/ + E_UTIL_f_convolve(code, h, y11, L_SUBFR); /* y11: Q8+shift */ + Scale_sig(y11, L_SUBFR, sub(1, shift)); /* Q9 */ + *gain = L_deposit_l(0); + + /*Update correlations for gains coding */ + tmp32 = L_shr(21474836l/*0.01f Q31*/, 31-18); /* Q18 */ + tmp32_2 = L_shr(21474836l/*0.01f Q31*/, 31-18); /* Q18 */ + + FOR (i = 0; i < L_SUBFR; i++) + { + tmp32 = L_mac0(tmp32, y11[i], y11[i]); /* Q18 */ + tmp32_2 = L_mac0(tmp32_2, y11[i], y2[i]); /* Q18 */ + } + + tmp16 = norm_l(tmp32); + g_corr->y1y1 = round_fx(L_shl(tmp32, tmp16)); + g_corr->y1y1_e = sub(31-18, tmp16); + move16(); + + tmp16 = norm_l(tmp32_2); + g_corr->y1y2 = round_fx(L_shl(tmp32_2, tmp16)); + g_corr->y1y2_e = sub(31-18, tmp16); + move16(); + +} + diff --git a/lib_enc/comvad_decision.c b/lib_enc/comvad_decision.c new file mode 100644 index 0000000..4ea3bd9 --- /dev/null +++ b/lib_enc/comvad_decision.c @@ -0,0 +1,886 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include + + +#include "basop_util.h" +#include "stl.h" +#include "vad_basop.h" +#include "prot_fx.h" +#include "rom_enc_fx.h" + + + + +/* only one is activated in below preprocessing*/ +/*#define CLDFB_VAD*/ /* test on the CLDFB-VAD */ + +static +Word16 comvad_hangover( Word32 lt_snr_org, /*(i)original long time SNR*/ + Word32 snr, /*(i) frequency domain SNR */ + Word32 l_snr, /*(i) long time frequency domain + SNR calculated by l_speech_snr and l_silence_snr*/ + Word32 snr_flux, /*(i) average tsnr*/ + Word16 bw_index, /*(i) band width index*/ + Word16 vad_flag, + Word16 pre_res_hang_num, /*(i) residual amount of previous hangover */ + Word16 continuous_speech_num2, /*(i) amount of continuous speech frames*/ + Word16 noisy_type /*(i) noisy type*/ + ) +{ + Word32 l_snr_add; + Word16 speech_flag; + + + speech_flag = pre_res_hang_num; + move16(); + + IF(EQ_16(bw_index, CLDFBVAD_SWB_ID)) + { + IF(vad_flag) + { + speech_flag = 4; + move16(); + if(GT_32(lt_snr_org, 117440509/* 3.5 Q25 */)) + { + speech_flag = 3; + move16(); + } + + test(); + test(); + IF((LT_16(continuous_speech_num2, 8))&&(LT_32(lt_snr_org,134217724/* 4.0 Q25 */))) + { + speech_flag = sub(8, continuous_speech_num2); + } + ELSE IF((GT_32(snr_flux, 26843545/* 0.8 Q25 */))&&(GT_16(continuous_speech_num2,24))) + { + IF(GT_32(lt_snr_org, 120795952/* 3.6 Q25 */)) + { + speech_flag = 3; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 87241521/* 2.6 Q25 */)) + { + speech_flag = 3; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 53687090/* 1.6 Q25 */)) + { + speech_flag = 4; + move16(); + } + ELSE + { + speech_flag = 5; + move16(); + } + speech_flag = sub(speech_flag,1); + } + + IF(LT_16(continuous_speech_num2, 120)) + { + test(); + IF(GT_32(snr, 50331647/* 1.5 Q25 */)) + { + speech_flag = 9; + move16(); + } + ELSE IF(GT_32(snr, 33554431/* 1.0 Q25 */)&<_16(speech_flag,7)) + { + speech_flag = 7; + move16(); + } + ELSE IF(LT_16(speech_flag,3)) + { + speech_flag = 3; + move16(); + } + if(GT_16(speech_flag,3)) + { + speech_flag =sub(speech_flag,2); + } + } + ELSE + { + IF(GT_32(lt_snr_org, 120795952/* 3.6 Q25 */)) + { + speech_flag = 1; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 100663293/* 3.0 Q25 */)) + { + speech_flag = 2; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 83886078/* 2.5 Q25 */)) + { + speech_flag = 3; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 67108862/* 2.0 Q25 */)) + { + speech_flag = 3; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 50331647/* 1.5 Q25 */)) + { + speech_flag = 4; + move16(); + } + ELSE + { + speech_flag = 5; + move16(); + } + } + + if(EQ_16(noisy_type, SILENCE)) + { + speech_flag = 6; + move16(); + } + } + } + ELSE IF(EQ_16(bw_index, CLDFBVAD_WB_ID)) + { + IF(vad_flag) + { + IF(GT_32(lt_snr_org, 117440509/* 3.5 Q25 */)) + { + speech_flag = 1; + move16(); + } + ELSE + { + speech_flag = 2; + move16(); + } + + test(); + test(); + IF((LT_16(continuous_speech_num2, 8))&&(LT_32(lt_snr_org,134217724/* 4.0 Q25 */))) + { + speech_flag = sub(8, continuous_speech_num2); + } + ELSE IF((GT_32(snr_flux, 30198988/* 0.9 Q25 */))&&(GT_16(continuous_speech_num2,50))) + { + IF(GT_32(lt_snr_org, 120795952/* 3.6 Q25 */)) + { + speech_flag = 1; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 87241521/* 2.6 Q25 */)) + { + speech_flag = 5; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 53687090/* 1.6 Q25 */)) + { + speech_flag = 6; + move16(); + } + ELSE + { + speech_flag = 7; + move16(); + } + IF(GT_16(speech_flag , 1)) + { + speech_flag = sub(speech_flag , 1); + } + } + + IF(LT_16(continuous_speech_num2, 120)) + { + test(); + test(); + test(); + IF(GT_32(snr, 50331647/* 1.5 Q25 */)) + { + speech_flag = 6; + move16(); + } + ELSE IF(GT_32(snr, 33554431/* 1.0 Q25 */)&<_16(speech_flag,5)) + { + speech_flag = 5; + move16(); + } + ELSE IF(GT_32(snr, 26843545/* 0.8 Q25 */)&<_32(lt_snr_org,67108862/* 2.0 Q25 */)&<_16(speech_flag,4)) + { + speech_flag = 4; + move16(); + } + ELSE IF(LT_16(speech_flag, 3)) + { + speech_flag = 3; + move16(); + } + } + ELSE + { + IF(GT_32(lt_snr_org,120795952/* 3.6 Q25 */)) + { + speech_flag = 1; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 100663293/* 3.0 Q25 */)) + { + speech_flag = 2; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 83886078/* 2.5 Q25 */)) + { + speech_flag = 2; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 67108862/* 2.0 Q25 */)) + { + speech_flag = 3; + move16(); + } + ELSE { + speech_flag = 3; + move16(); + } + } + + if(EQ_16(noisy_type, SILENCE)) + { + speech_flag = 6; + move16(); + } + } + } + ELSE /* NB */ + { + IF(vad_flag) + { + l_snr_add = L_add(0x0199999a,MUL_F(l_snr,0x0ccd)); + + IF(GT_32(lt_snr_org, 117440509/* 3.5 Q25 */)) + { + speech_flag = 3; + move16(); + } + ELSE + { + speech_flag = 4; + move16(); + } + + test(); + test(); + IF((LT_16(continuous_speech_num2,8))&&(LT_32(lt_snr_org,134217724/* 4.0 Q25 */))) + { + speech_flag = sub(8, continuous_speech_num2); + } + ELSE IF((GT_32(snr_flux, l_snr_add))&&(GT_16(continuous_speech_num2,24))) + { + IF(GT_32(lt_snr_org, 120795952/* 3.6 Q25 */)) + { + speech_flag = 3; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 87241521/* 2.6 Q25 */)) + { + speech_flag = 8; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 40265317/* 1.2 Q25 */)) + { + speech_flag = 10; + move16(); + } + ELSE + { + speech_flag = 12; + move16(); + } + + IF(GT_16(speech_flag ,2)) + { + speech_flag = sub(speech_flag,2); + } + } + + IF(LT_16(continuous_speech_num2, 120)) + { + test(); + test(); + IF(GT_32(snr, 50331647/* 1.5 Q25 */)) + { + speech_flag = 10; + move16(); + } + ELSE IF(GT_32(snr, 33554431/* 1.0 Q25 */)&<_16(speech_flag,7)) + { + speech_flag = 7; + move16(); + } + ELSE IF(LT_16(speech_flag, 3)&>_16(continuous_speech_num2,12)) + { + speech_flag = 3; + move16(); + } + } + ELSE + { + IF(GT_32(lt_snr_org, 120795952/* 3.6 Q25 */)) + { + speech_flag = 2; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 100663293/* 3.0 Q25 */)) + { + speech_flag = 2; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 83886078/* 2.5 Q25 */)) + { + speech_flag = 3; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 67108862/* 2.0 Q25 */)) + { + speech_flag = 3; + move16(); + } + ELSE IF(GT_32(lt_snr_org, 50331647/* 1.5 Q25 */)) + { + speech_flag = 4; + move16(); + } + ELSE + { + speech_flag = 4; + move16(); + } + } + + if(EQ_16(noisy_type, SILENCE)) + { + speech_flag = 2; + move16(); + } + } + } + + + IF((EQ_16(vad_flag,1))) + { + IF((NE_16(noisy_type, SILENCE))) + { + speech_flag--; + } + ELSE + { + speech_flag = sub(speech_flag, 3); + } + speech_flag = s_max(speech_flag, 0); + } + + + return speech_flag; +} + + + +Word16 comvad_decision( T_CldfbVadState *st, + Word32 l_snr, /*(i) long time frequency domain*/ + Word32 lt_snr_org, /*(i) original long time SNR*/ + Word32 lt_snr, /*(i) long time SNR calculated by fg_energy and bg_energy*/ + Word32 snr_flux, /*(i) average tsnr of several frames*/ + Word32 snr, /*(i) frequency domain SNR */ + Word32 tsnr, /*(i) time domain SNR */ + Word32 frame_energy, /*(i) current frame energy */ + Word16 music_backgound_f, /*(i) background music flag*/ + Word16 frame_energy_Q, /*(i) the Scaling of current frame energy*/ + Word16 *cldfb_addition, /*o: adjust the harmonized hangover */ + Word16 vada_flag + ) +{ + Word16 speech_flag; + Word32 fg_energy; + Word32 bg_energy; + Word32 tmp_snr; + Word16 vad_flag; + Word16 vadb_flag; + Word32 l_silence_snr_count; + Word32 snr_sub; + Word32 snr_div_fix32; + Word32 l_silence_snr; + + Word16 snr_div_fix; + Word16 Qnorm_silence,Qnorm_silence_count; + Word16 tmpout; + Word16 noisy_type; + Word32 lt_snr_org_cmp; + + + + /* avoid overflows in the following if conditions */ + tsnr = L_shr(tsnr,1); + + noisy_type = UNKNOWN_NOISE; + move16(); + speech_flag = st->speech_flag; + move16(); + fg_energy = st->fg_energy; + move32(); + bg_energy = st->bg_energy; + move32(); + + Qnorm_silence = 0; + move16(); + Qnorm_silence_count = 0; + move16(); + + test(); + IF(GT_32(st->lf_snr_smooth, LS_MIN_SILENCE_SNR[st->bw_index - CLDFBVAD_NB_ID] )&>_32(lt_snr_org,LT_MIN_SILENCE_SNR[st->bw_index-CLDFBVAD_NB_ID])) + { + noisy_type = SILENCE; + move16(); + } + + tmp_snr = construct_snr_thresh( st->sp_center, + snr_flux, + lt_snr, + l_snr, + st->continuous_speech_num, + st->continuous_noise_num, + st->fg_energy_est_start, + st->bw_index); + + { + vad_flag = 0; + move16(); + if(GT_32(snr, tmp_snr)) + { + vad_flag = 1; + move16(); + } + + if(GT_32(tsnr, 67108862/* 4.0/2.0 Q25 */)) + { + vad_flag = 1; + move16(); + } + } + + IF(GT_16(st->frameloop, 25)) + { + test(); + IF(EQ_16(vad_flag, 1)&&EQ_32(st->fg_energy_est_start,1)) + { + Word32 frame_energy_mult_fix32,bg_energy_mult_fix32; + Word16 frame_energy_mult_Q,bg_energy_mult_Q; + + IF(EQ_16(st->fg_energy_count, 512)) + { + fg_energy = MUL_F(fg_energy, 0x6000); + st->fg_energy_count = 384; + move16(); + } + + frame_energy_mult_fix32 = MUL_F(frame_energy, st->bg_energy_count); + frame_energy_mult_Q = sub(frame_energy_Q, 15); + + bg_energy_mult_fix32 = MUL_F(bg_energy, 6); + bg_energy_mult_Q = sub(st->bg_energy_scale, 15); + + IF(GT_16(frame_energy_mult_Q, bg_energy_mult_Q)) + { + frame_energy_mult_fix32 = L_shr(frame_energy_mult_fix32,sub(frame_energy_mult_Q, bg_energy_mult_Q)); + } + IF(LT_16(frame_energy_mult_Q, bg_energy_mult_Q)) + { + bg_energy_mult_fix32 = L_shr(bg_energy_mult_fix32,limitScale32(sub(bg_energy_mult_Q, frame_energy_mult_Q))); + } + + IF(GT_32(frame_energy_mult_fix32, bg_energy_mult_fix32)) + { + fg_energy = VAD_L_ADD(fg_energy, st->fg_energy_scale, frame_energy, frame_energy_Q, &st->fg_energy_scale); + st->fg_energy_count = add(st->fg_energy_count, 1); + move16(); + } + } + } + + if(music_backgound_f) + { + vad_flag = 1; + move16(); + } + + IF(EQ_16(vad_flag, 1)) + { + IF (st->l_silence_snr == 0) + { + snr_div_fix = 0; + move16(); + } + ELSE + { + Qnorm_silence=sub(norm_l(st->l_silence_snr), 1); + Qnorm_silence_count=norm_l(st->l_silence_snr_count); + l_silence_snr = L_shl(st->l_silence_snr,Qnorm_silence); + l_silence_snr_count = L_shl(st->l_silence_snr_count,Qnorm_silence_count); + snr_div_fix = div_l(l_silence_snr,extract_h(l_silence_snr_count)); + } + snr_sub = L_sub(snr, 0x3000000); + snr_div_fix32 = L_deposit_l(snr_div_fix); + snr_div_fix32 = L_shr(snr_div_fix32, add(6, sub(Qnorm_silence, Qnorm_silence_count))); + + + IF(GT_32(snr_sub, snr_div_fix32)) + { + IF(EQ_32(st->l_speech_snr_count, 512)) + { + st->l_speech_snr = L_add(MUL_F(st->l_speech_snr, 0x6000), L_shr(snr, 9)); + move32(); + st->l_speech_snr_count = L_deposit_l(384+1); + move32(); + } + ELSE + { + st->l_speech_snr = L_add(st->l_speech_snr, L_shr(snr, 9)); + move32(); + st->l_speech_snr_count = L_add(st->l_speech_snr_count, 1); + move32(); + } + } + } + + lt_snr_org_cmp = L_sub(lt_snr_org, 117440509/* 3.5 Q25 */); + + IF(EQ_16(st->bw_index, CLDFBVAD_NB_ID)) + { + Word32 lt_snr_add; + + lt_snr_add = L_add(0x03cccccd, MUL_F(lt_snr, 0x23d7)); + + if(GT_32(snr_flux, lt_snr_add)) + { + vad_flag = 1; + move16(); + } + + test(); + test(); + if( (GT_32(snr_flux, 50331647/* 1.5 Q25 */))&&(GT_16(st->sp_center[3],1637/* 1.6 Q10 */))&&(lt_snr_org_cmp<0)) + { + vad_flag = 1; + move16(); + } + + test(); + test(); + if( (GT_32(snr_flux, 40265317/* 1.2 Q25 */))&&(GT_16(st->sp_center[3],1944/* 1.9 Q10 */))&&(lt_snr_org_cmp<0)) + { + vad_flag = 1; + move16(); + } + + test(); + test(); + if((GT_32(snr_flux, 33554431/* 1.0 Q25 */))&&(GT_16(st->sp_center[3],3274/* 3.2 Q10 */))&&(lt_snr_org_cmp<0)) + { + vad_flag = 1; + move16(); + } + } + ELSE IF(EQ_16(st->bw_index, CLDFBVAD_WB_ID)) + { + Word32 lt_snr_add; + + lt_snr_add = L_add(0x04333333, MUL_F(lt_snr, 0x1eb8)); + + if(GT_32(snr_flux, lt_snr_add)) + { + vad_flag = 1; + move16(); + } + + test(); + test(); + if((GT_32(snr_flux, 53687090/* 1.6 Q25 */))&&(GT_16(st->sp_center[3],2558/* 2.5 Q10 */))&&(lt_snr_org_cmp<0)) + { + vad_flag = 1; + move16(); + } + + test(); + test(); + if((GT_32(snr_flux, 40265317/* 1.2 Q25 */))&&(GT_16(st->sp_center[3],2864/* 2.8 Q10 */))&&(lt_snr_org_cmp<0)) + { + vad_flag = 1; + move16(); + } + + test(); + test(); + if((GT_32(snr_flux, 33554431/* 1.0 Q25 */))&&(GT_16(st->sp_center[3],4604/* 4.5 Q10 */))&&(lt_snr_org_cmp<0)) + { + vad_flag = 1; + move16(); + } + } + ELSE + { + Word32 lt_snr_add; + + lt_snr_add = L_add(0x04333333, MUL_F(lt_snr, 0x28f5)); + + if((GT_32(snr_flux, lt_snr_add))) + { + vad_flag = 1; + move16(); + } + + test(); + test(); + if((GT_32(snr_flux, 56371444/* 1.68 Q25 */))&&(GT_16(st->sp_center[3],2823/* 2.76 Q10 */))&&(lt_snr_org_cmp<0)) + { + vad_flag = 1; + move16(); + } + + test(); + test(); + if((GT_32(snr_flux, 41607494/* 1.24 Q25 */))&&(GT_16(st->sp_center[3],2987/* 2.92 Q10 */))&&(lt_snr_org_cmp<0)) + { + vad_flag = 1; + move16(); + } + + test(); + test(); + if((GT_32(snr_flux, 36909874/* 1.10 Q25 */))&&(GT_16(st->sp_center[3],4706/* 4.6 Q10 */))&&(lt_snr_org_cmp<0)) + { + vad_flag = 1; + move16(); + } + } + + + IF(st->fg_energy_est_start==0) + { + tmpout = VAD_L_CMP(frame_energy, frame_energy_Q, 50, 0); + + test(); + test(); + if(GT_16(st->ltd_stable_rate[0], 2621/* 0.08 Q15 */)&&EQ_16(vad_flag,1)&&(tmpout>0)) + { + st->fg_energy_est_start = L_deposit_l(1); + } + } + + speech_flag = comvad_hangover( lt_snr_org, + snr, + l_snr, + snr_flux, + st->bw_index, + vad_flag, + speech_flag, + st->continuous_speech_num2, + noisy_type); + + + + test(); + IF(vad_flag == 0 && speech_flag > 0) + { + speech_flag = sub(speech_flag, 1); + vad_flag = 1; + move16(); + } + vadb_flag = vad_flag; + + IF(EQ_16(st->bw_index, CLDFBVAD_SWB_ID)) + { + test(); + test(); + test(); + IF(EQ_16(SILENCE, noisy_type) + && GT_32(snr, 6710886/* 0.2 Q25 */) + && vad_flag == 0) + { + vad_flag = vada_flag; + move16(); + } + ELSE IF(LT_32(st->lf_snr_smooth,352321526/* 10.5 Q25 */)||NE_16(SILENCE,noisy_type)) + { + test(); + test(); + test(); + IF(GT_32(snr_flux, 83886078/* 2.5 Q25 */) + || ( st->continuous_speech_num2 > 40 && GT_32(snr_flux, 67108862/* 2.0 Q25 */) ) + || music_backgound_f == 1) + { + vad_flag = s_or(vad_flag, vada_flag); + } + ELSE IF(EQ_16(SILENCE, noisy_type)) + { + vad_flag = vada_flag; + } + } + + } + ELSE IF(EQ_16(st->bw_index, CLDFBVAD_WB_ID)) + { + test(); + test(); + test(); + IF(EQ_16(SILENCE, noisy_type) + && GT_32(snr, 6710886/* 0.2 Q25 */) + && vad_flag == 0) + { + vad_flag = vada_flag; + move16(); + } + ELSE IF(LT_32(st->lf_snr_smooth,352321526/* 10.5 Q25 */)||NE_16(SILENCE,noisy_type)) + { + test(); + test(); + test(); + IF(GT_32(snr_flux, 73819748/* 2.2 Q25 */) + || (st->continuous_speech_num2 > 40 && GT_32(snr_flux, 57042532/* 1.7 Q25 */) ) + || music_backgound_f == 1) + { + vad_flag = s_or(vad_flag, vada_flag); + } + ELSE IF(EQ_16(SILENCE, noisy_type)) + { + vad_flag = vada_flag; + } + + } + + } + ELSE + { + IF(EQ_16(SILENCE, noisy_type)) + { + test(); + IF(GT_32(st->lf_snr_smooth , 419430388/* 12.5 Q25 */) + && music_backgound_f == 0) + { + vad_flag = vada_flag; + } + } + ELSE + { + test(); + test(); + test(); + IF(GT_32(snr_flux, 67108862/* 2.0 Q25 */) + || (st->continuous_speech_num2 > 30 && GT_32(snr_flux, 50331647/* 1.5 Q25 */) ) + || music_backgound_f == 1) + { + vad_flag = s_or(vad_flag, vada_flag); + } + } + } + + IF(vad_flag == 0) + { + IF(EQ_32(st->l_silence_snr_count, 512)) + { + st->l_silence_snr = L_add(MUL_F(st->l_silence_snr, 0x6000),L_shr(snr, 9)); + move32(); + st->l_silence_snr_count = L_deposit_l(384+1); + move32(); + } + ELSE IF(LT_32(snr, 26843545/* 0.8 Q25 */)) + { + st->l_silence_snr = L_add(st->l_silence_snr, L_shr(snr,9)); + move32(); + st->l_silence_snr_count = L_add(st->l_silence_snr_count, 1); + move32(); + } + } + + IF(vad_flag == 0) + { + IF(EQ_16(st->bg_energy_count, 512)) + { + bg_energy = MUL_F(bg_energy, 0x6000); + st->bg_energy_count = 384; + move16(); + } + + IF(LT_32(tsnr, 16777216/* 1.0/2.0 Q25 */)) + { + bg_energy = VAD_L_ADD(bg_energy, st->bg_energy_scale, frame_energy, frame_energy_Q, &st->bg_energy_scale); + st->bg_energy_count = add(st->bg_energy_count, 1); + move16(); + } + } + + test(); + st->vad_flag_for_bk_update = vad_flag; + IF(LT_16(st->update_count, 12)&&EQ_16(vadb_flag,1)) + { + st->warm_hang_num = s_max(20, speech_flag); + } + test(); + IF(vad_flag == 0 && st->warm_hang_num > 0) + { + st->warm_hang_num = sub(st->warm_hang_num, 1); + vad_flag = 1; + move16(); + } + + + + + st->lt_snr_org = lt_snr_org; + move32(); + st->fg_energy = fg_energy; + move32(); + st->bg_energy = bg_energy; + move32(); + + st->speech_flag = speech_flag; + move16(); + + move16(); + test(); + IF(EQ_16(noisy_type, SILENCE) + && NE_16(st->bw_index, CLDFBVAD_NB_ID)) + { + *cldfb_addition = 2; + } + ELSE + { + *cldfb_addition = 0; + + if(EQ_16(st->bw_index, CLDFBVAD_WB_ID)) + { + *cldfb_addition = 3; + move16(); + } + if(EQ_16(st->bw_index, CLDFBVAD_SWB_ID)) + { + *cldfb_addition = 1; + move16(); + } + if(EQ_16(st->bw_index, CLDFBVAD_NB_ID)) + { + *cldfb_addition = 1; + move16(); + } + + } + + + + + return vad_flag; +} + diff --git a/lib_enc/cor_shif_fx.c b/lib_enc/cor_shif_fx.c new file mode 100644 index 0000000..71a455b --- /dev/null +++ b/lib_enc/cor_shif_fx.c @@ -0,0 +1,50 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + + +/*-------------------------------------------------------------------* + * correlation_shift_fx + * + * Find normalized correlation correction dependent on estimated noise + * Note: this variable is basically active only if noise suppression + * is desactivated. Otherwise, for default NS = 14 dB and up to 10dB SNR + * it can be assumed about 0 + *-------------------------------------------------------------------*/ + +Word16 correlation_shift_fx( /* o : noise dependent voicing correction Q15 */ + Word16 totalNoise_fx /* i/o: noise estimate over all critical bands Q8 */ +) +{ + Word16 corr_shift_fx, e_Noise, f_Noise, wtmp; + Word32 Ltmp; + + corr_shift_fx = 0; + move16(); + + IF (GT_16(totalNoise_fx, 7215)) /* to make corr_shift > 0.0 */ + { + /*------------------------------------------------------------* + * useful values range from 0 to 1 (can saturate at 1.0) Q31 value + * corr_shift = 2.4492E-4 * exp(0.1596 * totalNoise) - 0.022 + * Result in Q14 + *------------------------------------------------------------*/ + Ltmp = L_mult(totalNoise_fx, 7545); /* Q24 */ + Ltmp = L_shr(Ltmp, 8); /* Q24 -> Q16 */ + f_Noise = L_Extract_lc(Ltmp, &e_Noise); + wtmp = extract_l(Pow2(14, f_Noise)); /* Put 14 as exponent */ + + e_Noise = sub(e_Noise, 14); /* Retreive exponent of wtmp */ + Ltmp = Mpy_32_16(8, 837, wtmp); /* 2.4492e-4(Q31) * exp(0.1596*totalNoise) */ + Ltmp = L_shl(Ltmp,add(e_Noise, 15)); /* Result in Q31 */ + corr_shift_fx = round_fx(L_sub(Ltmp, 47244640)); /* Represents corr_shift in Q15 */ + } + corr_shift_fx = s_min(corr_shift_fx,16384); /* limit to 0.5 */ + + return corr_shift_fx; +} diff --git a/lib_enc/core_enc_2div.c b/lib_enc/core_enc_2div.c new file mode 100644 index 0000000..799a255 --- /dev/null +++ b/lib_enc/core_enc_2div.c @@ -0,0 +1,342 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include +#include "prot_fx.h" +#include "basop_util.h" +#include "options.h" +#include "cnst_fx.h" +#include "stl.h" + +void core_encode_twodiv( + const Word16 new_samples[], + Encoder_State_fx *st, /* i/o : coder memory state */ + const Word16 coder_type, /* i : coding type */ + const Word16 pitch[3], /* i : open-loop pitch values for quantiz. */ + const Word16 voicing[3], /* i : open-loop pitch gains */ + Word16 Aw[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/ + Word16 *Q_new, + Word16 *shift +) +{ + Word16 n; + Word16 lsp_new[M], lsp_mid[M]; + Word16 lsf_q[M], lsp_q[M], lspmid_q[M]; + Word16 A_q[M+1]; + Word16 param_lpc[NPRM_LPC_NEW]; + Word16 nbits_lpc[2]; + Word16 param_core[2*NPRM_DIV]; + Word16 target_bits; + Word16 gainlpc[2][FDNS_NPTS]; + Word16 gainlpc_e[2][FDNS_NPTS]; + Word16 tnsSize[2]; /* number of tns parameters put into prm */ + Word16 tnsBits[2]; /* number of tns bits in the frame */ + Word16 ltpBits; + Word16 bitsAvailable; + Word32 spectrum_buf[N_MAX]; + Word32 *spectrum[2]; /* MDCT spectrum */ + Word16 spectrum_e[2]; + Word16 indexBuffer[2*((N_MAX/2)+1)]; + CONTEXT_HM_CONFIG hm_cfg[2]; + Word16 i, T_op[3]; + Word16 bits_param_lpc[10], no_param_lpc; + + + spectrum[0] = spectrum_buf; + spectrum[1] = spectrum_buf + N_TCX10_MAX; + + hm_cfg[0].indexBuffer = &indexBuffer[0]; + move16(); + hm_cfg[1].indexBuffer = &indexBuffer[N_MAX/2+1]; + move16(); + + move16(); + move16(); + move16(); + move16(); + move16(); + tnsSize[0] = 0; + tnsSize[1] = 0; + tnsBits[0] = 0; + tnsBits[1] = 0; + ltpBits = 0; + + FOR( i = 0; i < 3; i++ ) + { + move16(); + T_op[i] = pitch[i]; + + /* check minimum pitch for quantization */ + IF ( LT_16(T_op[i], PIT_MIN_SHORTER)) + { + move16(); + T_op[i] = shl(T_op[i], 1); + } + + /* convert pitch values to core sampling-rate */ + IF ( NE_16(st->L_frame_fx, L_FRAME)) + { + move16(); + /* T_op[i] = (short)(T_op[i] * (float)st->L_frame_fx/(float)L_FRAME + 0.5f); */ + T_op[i] = round_fx(L_shr(L_mult0(T_op[i], st->L_frame_fx), 8 - 16)); + } + } + + /*--------------------------------------------------------------* + * TCX20/TCX10 switching decision + *---------------------------------------------------------------*/ + + move16(); + st->core_fx = TCX_10_CORE; + if ( EQ_16(st->tcxMode,TCX_20)) + { + move16(); + st->core_fx = TCX_20_CORE; + } + assert(st->tcxMode == TCX_20 || st->tcxMode == TCX_10); + + /*--------------------------------------------------------------* + * Core Signal Analysis: MDCT, TNS, LPC analysis + *---------------------------------------------------------------*/ + + core_signal_analysis_high_bitrate( new_samples, + T_op, + voicing, + pitch, + Aw, + lsp_new, + lsp_mid, + st, + tnsSize, + tnsBits, + param_core, + <pBits, + st->L_frame_fx, + st->L_frameTCX, + spectrum, + spectrum_e, + Q_new, + shift + ); + + /*--------------------------------------------------------------* + * LPC Quantization + *---------------------------------------------------------------*/ + lpc_quantization( st, st->core_fx, st->lpcQuantization, st->lsf_old_fx , lsp_new, lsp_mid, lsp_q, lsf_q, + lspmid_q, NULL, st->clip_var_fx, st->mem_MA_fx, st->mem_AR_fx, + st->narrowBand, coder_type, 0, param_lpc, nbits_lpc, bits_param_lpc, &no_param_lpc, &(st->seed_acelp), + st->Bin_E_fx, st->Bin_E_old_fx, add(*Q_new, Q_SCALE - 2) ); + + /*--------------------------------------------------------------* + * Rate switching + *---------------------------------------------------------------*/ + IF( st->rate_switching_reset!=0 ) + { + Copy( lsp_q, st->lsp_old_fx, M ); + Copy( lsf_q, st->lsf_old_fx, M ); + } + + + + /*--------------------------------------------------------------* + * Run Two TCX10 + *---------------------------------------------------------------*/ + + IF ( EQ_16(st->core_fx,TCX_10_CORE)) + { + Word16 last_ace_mode; + + + move16(); + last_ace_mode = st->last_core_fx; + + + FOR (n = 0; n < 2; n++) + { + IF(n == 0) + { + E_LPC_f_lsp_a_conversion(lspmid_q, A_q, M); + } + ELSE + { + E_LPC_f_lsp_a_conversion(lsp_q, A_q, M); + } + + /* Shape spectrum */ + ShapeSpectrum(&(st->tcx_cfg), + A_q, + gainlpc[n], + gainlpc_e[n], + shr(st->L_frame_fx, 1), + shr(st->tcx_cfg.tcx_coded_lines, 1), + spectrum[n], + st->fUseTns[n], + st + ); + + st->last_core_fx = st->core_fx; + move16(); + } + st->last_core_fx = last_ace_mode; + move16(); + + + /* Calculate target bits */ + bitsAvailable = sub(sub(sub(st->bits_frame_core, nbits_lpc[0]), nbits_lpc[1]), st->nb_bits_header_tcx); + + /* subtract bits for TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */ + bitsAvailable = sub(bitsAvailable,1); + test(); + if (EQ_16(st->tcx_cfg.tcx_curr_overlap_mode, HALF_OVERLAP)||EQ_16(st->tcx_cfg.tcx_curr_overlap_mode,MIN_OVERLAP)) + { + bitsAvailable = sub(bitsAvailable,1); + } + + bitsAvailable = sub(bitsAvailable, st->hIGFEnc.infoTotalBitsWritten); + + /* calculate noise-filling over whole spectrum for TCX10 frames */ + move16(); + st->measuredBwRatio = 0x4000; + + FOR (n = 0; n < 2; n++) + { + target_bits = sub(shr(sub(add(bitsAvailable, 1), n),1), tnsBits[n]); + + if (n == 0) + { + target_bits = sub(target_bits, ltpBits); + } + + test(); + if(st->enablePlcWaveadjust && n) + { + target_bits = sub(target_bits, 1); + } + + + /* Run TCX10 encoder */ + + QuantizeSpectrum( + &(st->tcx_cfg), + A_q, + NULL, + gainlpc[n], + gainlpc_e[n], + st->synth+n*st->L_frame_fx/2, + shr(st->L_frame_fx, 1), + shr(st->L_frameTCX, 1), + shr(st->tcx_cfg.tcx_coded_lines, 1), + target_bits, + st->tcxonly, + spectrum[n], + &spectrum_e[n], + st->tnsData+n, + st->fUseTns[n], + tnsSize[n], + &(st->LPDmem), + param_core+n*NPRM_DIV, + n, + st, + &hm_cfg[n] + ); + + /* Update tcx overlap mode */ + test(); + if ((n > 0) || (st->tcxonly==0)) + { + move16(); + st->tcx_cfg.tcx_last_overlap_mode = st->tcx_cfg.tcx_curr_overlap_mode; + } + + } + + coder_tcx_post( st, &(st->LPDmem), &(st->tcx_cfg), st->synth, A_q, Aw, st->wspeech_enc, *Q_new, *shift ); + } + + /*--------------------------------------------------------------* + * Run One TCX20 + *---------------------------------------------------------------*/ + + IF ( EQ_16(st->core_fx,TCX_20_CORE)) + { + + E_LPC_f_lsp_a_conversion(lsp_q, A_q, M); + + + ShapeSpectrum(&(st->tcx_cfg), + A_q, + gainlpc[0], + gainlpc_e[0], + st->L_frame_fx, + st->tcx_cfg.tcx_coded_lines, + spectrum[0], + st->fUseTns[0], + st + ); + + /* Calculate target bits */ + + target_bits = sub(sub(sub(sub(st->bits_frame_core, tnsBits[0]), nbits_lpc[0]), st->nb_bits_header_tcx), ltpBits); + /* subtract bits for TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */ + target_bits = sub(target_bits,1); + test(); + if (EQ_16(st->tcx_cfg.tcx_curr_overlap_mode, HALF_OVERLAP)||EQ_16(st->tcx_cfg.tcx_curr_overlap_mode,MIN_OVERLAP)) + { + target_bits = sub(target_bits,1); + } + + target_bits = sub(target_bits, st->hIGFEnc.infoTotalBitsPerFrameWritten); + + + if(st->enablePlcWaveadjust) + { + target_bits = sub(target_bits, 1); + } + + + QuantizeSpectrum( + &(st->tcx_cfg), + A_q, + NULL, + gainlpc[0], + gainlpc_e[0], + st->synth, + st->L_frame_fx, + st->L_frameTCX, + st->tcx_cfg.tcx_coded_lines, + target_bits, + st->tcxonly, + spectrum[0], + &spectrum_e[0], + &st->tnsData[0], + st->fUseTns[0], + tnsSize[0], + &(st->LPDmem), + param_core, + 0, + st, + &hm_cfg[0] + ); + + coder_tcx_post( st, &(st->LPDmem), &(st->tcx_cfg), st->synth, A_q, Aw, st->wspeech_enc, *Q_new, *shift ); + + } + + /* Update lsp/lsf memory */ + Copy(lsf_q, st->lsf_old_fx, M); + Copy(lsp_q, st->lsp_old_fx, M); + + + + /*--------------------------------------------------------------* + * Generate Bitstream + *---------------------------------------------------------------*/ + + enc_prm( coder_type, param_core, param_lpc, st, st->L_frame_fx, hm_cfg, bits_param_lpc, no_param_lpc ); + +} + diff --git a/lib_enc/core_enc_init.c b/lib_enc/core_enc_init.c new file mode 100644 index 0000000..5c9baa7 --- /dev/null +++ b/lib_enc/core_enc_init.c @@ -0,0 +1,861 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "prot_fx.h" +#include "basop_mpy.h" +#include "options.h" +#include "cnst_fx.h" +#include "stl.h" +#include "count.h" +#include "basop_util.h" +#include "rom_com_fx.h" +#include + + +/*-----------------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------------*/ + +static void init_tcx( Encoder_State_fx *st, Word16 L_frame_old ); +static void init_core_sig_ana( Encoder_State_fx *st ); +static void init_acelp( Encoder_State_fx *st, Word16 L_frame_old, const Word16 shift); +static void init_modes( Encoder_State_fx *st ); + +/*-----------------------------------------------------------------------* + * init_coder_ace_plus() + * + * Initialization of state variables + *-----------------------------------------------------------------------*/ + +void init_coder_ace_plus(Encoder_State_fx *st, const Word16 shift) +{ + Word16 L_frame_old; /*keep old frame size for switching */ + Word16 L_subfr; + + + /* Bitrate */ + st->tcxonly = getTcxonly(st->total_brate_fx); + move16(); + + /* Core Sampling Rate */ + st->sr_core = getCoreSamplerateMode2(st->total_brate_fx, st->bwidth_fx, st->rf_mode ); + st->fscale = sr2fscale(st->sr_core); + move16(); + + /* Narrowband? */ + st->narrowBand = 0; + move16(); + if( EQ_16(st->bwidth_fx, NB)) + { + st->narrowBand = 1; + move16(); + } + + /* Core Framing */ + L_frame_old = st->last_L_frame_fx; + move16(); + st->L_frame_fx = extract_l(Mult_32_16(st->sr_core , 0x0290)); + st->L_frame_past = -1; + move16(); + + st->L_frameTCX = extract_l(Mult_32_16(st->input_Fs_fx , 0x0290)); + + st->nb_subfr = NB_SUBFR; + move16(); + L_subfr = shr(st->L_frame_fx, 2); + test(); + IF ( EQ_16(st->L_frame_fx, L_FRAME16k)&&LE_32(st->total_brate_fx,32000)) + { + st->nb_subfr = NB_SUBFR16k; + move16(); + L_subfr = mult(st->L_frame_fx, 0x199A); /*1/5 = 0x199A Q15*/ move16(); + } + + /* Core Lookahead */ + st->encoderLookahead_enc = NS2SA_fx2(st->sr_core, ACELP_LOOK_NS); + move16(); + st->encoderLookahead_FB = NS2SA_fx2(st->input_Fs_fx, ACELP_LOOK_NS); + move16(); + + IF ( st->ini_frame_fx == 0 ) + { + st->acelpFramesCount = 0; + move16(); + st->prevTempFlatness_fx = 128/*1.0f Q7*/; + move16(); + } + + /* Initialize TBE */ + st->prev_coder_type_fx = GENERIC; + move16(); + set16_fx( st->prev_lsf_diff_fx, 16384, LPC_SHB_ORDER-2 ); + st->prev_tilt_para_fx = 0; + move16(); + set16_fx( st->cur_sub_Aq_fx, 0, M+1 ); + + st->currEnergyHF_fx = 0; + move16(); + st->currEnergyHF_e_fx = 0; + move16(); + st->energyCoreLookahead_Fx = 0; + move16(); + + /* Initialize LPC analysis/quantization */ + st->lpcQuantization = 0; + move16(); + test(); + if( LE_32(st->sr_core,16000)&&st->tcxonly==0) + { + st->lpcQuantization = 1; + move16(); + } + + + st->next_force_safety_net_fx = 0; + move16(); + test(); + test(); + IF ( NE_16(st->last_L_frame_fx,st->L_frame_fx)||EQ_16(st->last_core_fx,AMR_WB_CORE)||EQ_16(st->last_core_fx,HQ_CORE)) + { + set16_fx( st->mem_MA_fx, 0, M ); + Copy(GEWB_Ave_fx, st->mem_AR_fx, M); + } + + /* Initialize IGF */ + st->hIGFEnc.infoStopFrequency = -1; + move16(); + IF( st->igf ) + { + IGFEncSetMode(&st->hIGFEnc, st->total_brate_fx, st->bwidth_fx, st->rf_mode); + } + + /* Initialize TCX */ + init_tcx( st, L_frame_old ); + + /* Initialize Core Signal Analysis Module */ + init_core_sig_ana( st ); + + /* Initialize Signal Buffers */ + init_sig_buffers( st, L_frame_old, L_subfr ); + + /* Initialize ACELP */ + init_acelp( st, L_frame_old , shift); + + if(st->ini_frame_fx == 0) + { + st->tec_tfa = 0; + move16(); + } + IF(st->tec_tfa == 0) + { + resetTecEnc_Fx(&st->tecEnc, 0); + } + ELSE + { + resetTecEnc_Fx(&st->tecEnc, 1); + } + st->tec_tfa = 0; + move16(); + test(); + test(); + if( EQ_16(st->bwidth_fx, SWB)&&(EQ_32(st->total_brate_fx,ACELP_16k40)||EQ_32(st->total_brate_fx,ACELP_24k40))) + { + st->tec_tfa = 1; + move16(); + } + + st->tec_flag = 0; + move16(); + st->tfa_flag = 0; + move16(); + /* Initialize DTX */ + IF( st->ini_frame_fx == 0 ) + { + + vad_init(&st->vad_st); + } + + st->glr = 0; + move16(); + + test(); + test(); + test(); + if( (EQ_32(st->total_brate_fx, ACELP_9k60))||(EQ_32(st->total_brate_fx,ACELP_16k40))|| + (EQ_32(st->total_brate_fx, ACELP_24k40))||(EQ_32(st->total_brate_fx, ACELP_32k))) + { + st->glr = 1; + move16(); + } + + st->glr_reset = 0; + move16(); + + /* Initialize ACELP/TCX Modes */ + init_modes( st ); + + /* Init I/O */ + + + /* Adaptive BPF */ + set16_fx(st->mem_bpf.noise_buf, 0, 2*L_FILT16k); + set16_fx(st->mem_bpf.error_buf, 0, L_FILT16k); + set16_fx(st->bpf_gainT, 0, NB_SUBFR16k); + + set16_fx(st->bpf_T, PIT_MIN_12k8, NB_SUBFR16k); + + st->mem_bpf.noise_shift_old = 0; + move16(); + + IF ( st->ini_frame_fx == 0 ) + { + st->Q_max_enc[0] = 15; + move16(); + st->Q_max_enc[1] = 15; + move16(); + } + + st->enablePlcWaveadjust = 0; + move16(); + if (GE_32(st->total_brate_fx, 48000)) + { + st->enablePlcWaveadjust = 1; + move16(); + } + + open_PLC_ENC_EVS( &st->plcExt, st->sr_core ); + + st->glr_idx[0] = 0; + move16(); + st->glr_idx[1] = 0; + move16(); + move16(); + move16(); /* casts */ + st->mean_gc[0] = L_deposit_h(0); + st->mean_gc[1] = L_deposit_h(0); + st->prev_lsf4_mean = 0; + move16(); + + st->last_stab_fac = 0; + move16(); + + + return; +} + +static void init_tcx( Encoder_State_fx *st, Word16 L_frame_old ) +{ + Word16 i; + Word16 fscaleFB; + + + fscaleFB = div_l(L_shl(st->input_Fs_fx, LD_FSCALE_DENOM+1), 12800); + + init_TCX_config(&st->tcx_cfg, st->L_frame_fx, st->fscale, st->L_frameTCX, fscaleFB ); + + st->tcx_cfg.tcx_mdct_window_length_old = st->tcx_cfg.tcx_mdct_window_length; + move16(); + + /* TCX Offset */ + st->tcx_cfg.tcx_offset = shr(st->tcx_cfg.tcx_mdct_window_delay, 1); + move16(); + st->tcx_cfg.tcx_offsetFB = shr(st->tcx_cfg.tcx_mdct_window_delayFB, 1); + move16(); + + /*<0 rectangular transition with optimized window size = L_frame+L_frame/4*/ + st->tcx_cfg.lfacNext = sub(st->tcx_cfg.tcx_offset, shr(st->L_frame_fx, 2)); + move16(); + st->tcx_cfg.lfacNextFB = sub(st->tcx_cfg.tcx_offsetFB, shr(st->L_frameTCX, 2)); + + IF ( st->ini_frame_fx == 0 ) + { + st->tcx_cfg.tcx_curr_overlap_mode = st->tcx_cfg.tcx_last_overlap_mode = ALDO_WINDOW; + move16(); + move16(); + } + + /* Init TCX target bits correction factor */ + st->LPDmem.tcx_target_bits_fac = 0x4000; /*1.0f in 1Q14*/ move16(); + st->measuredBwRatio = 0x4000; /*1.0f in 1Q14*/ move16(); + st->noiseTiltFactor = 9216; /*0.5625f in 1Q14*/ move16(); + st->noiseLevelMemory = 0; + move16(); + /*SQ deadzone & memory quantization*/ + + /*0.375f: deadzone of 1.25->rounding=1-1.25/2 (No deadzone=0.5)*/ + st->tcx_cfg.sq_rounding = 12288/*0.375f Q15*/; + move16(); + + FOR (i = 0; i < L_FRAME_PLUS; i++) + { + st->memQuantZeros[i] = 0; + move16(); + } + + /* TCX rate loop */ + st->tcx_cfg.tcxRateLoopOpt = 0; + move16(); + + if ( st->tcxonly != 0 ) + { + st->tcx_cfg.tcxRateLoopOpt = 2; + move16(); + } + + /* TCX bandwidth */ + move16(); + st->tcx_cfg.bandwidth = getTcxBandwidth(st->bwidth_fx); + + + /* set number of coded lines */ + st->tcx_cfg.tcx_coded_lines = getNumTcxCodedLines(st->bwidth_fx); + + /* TNS in TCX */ + move16(); + move16(); + st->tcx_cfg.fIsTNSAllowed = getTnsAllowed(st->total_brate_fx + ,st->igf + ); + st->tcx_cfg.pCurrentTnsConfig = NULL; + + IF ( st->tcx_cfg.fIsTNSAllowed != 0 ) + { + InitTnsConfigs(bwMode2fs[st->bwidth_fx], st->tcx_cfg.tcx_coded_lines, st->tcx_cfg.tnsConfig, st->hIGFEnc.infoStopFrequency, st->total_brate_fx); + } + + /* TCX-LTP */ + st->tcxltp = getTcxLtp(st->sr_core); + + test(); + test(); + test(); + test(); + IF( st->ini_frame_fx == 0 ) + { + + st->tcxltp_pitch_int_past = st->L_frame_fx; + move16(); + st->tcxltp_pitch_fr_past = 0; + move16(); + st->tcxltp_gain_past = 0; + move16(); + st->tcxltp_norm_corr_past = 0; + move16(); + } + ELSE IF ( NE_16(st->L_frame_fx,L_frame_old)&&!((st->total_brate_fx==16400||st->total_brate_fx==24400)&&(st->total_brate_fx==st->last_total_brate_fx)&&(st->last_bwidth_fx==st->bwidth_fx))) + { + Word16 pitres, pitres_old; + Word16 pit, pit_old; + + pitres_old = 4; + move16(); + if (EQ_16(160,shr(L_frame_old,sub(7,norm_s(L_frame_old))))) /*if ( L_frame_old%160==0 )*/ + { + pitres_old = 6; + move16(); + } + + /*pit_old = (float)st->tcxltp_pitch_int_past + (float)st->tcxltp_pitch_fr_past/(float)pitres_old;*/ + pit_old = add(st->tcxltp_pitch_int_past, mult_r(st->tcxltp_pitch_fr_past, div_s(1,pitres_old))); + + pitres = 4; + move16(); + if (EQ_16(160,shr(st->L_frame_fx,sub(7,norm_s(st->L_frame_fx))))) /*if ( st->L_frame_fx%160==0 )*/ + { + pitres = 6; + move16(); + } + + /*pit = pit_old * (float)st->L_frame_fx/(float)L_frame_old;*/ + pit = shl(mult_r(pit_old, div_s(st->L_frame_fx, shl(L_frame_old, 2))), 2); + /* assert(pit <= st->L_frame_fx);*/ + + st->tcxltp_pitch_int_past = pit; + move16(); + move16(); + st->tcxltp_pitch_fr_past = i_mult2(sub(pit,st->tcxltp_pitch_int_past),pitres); + move16(); + } + + /* Residual Coding*/ + st->tcx_cfg.resq = getResq(st->total_brate_fx); + move16(); + + test(); + if ( st->tcx_cfg.resq != 0 && st->tcxonly == 0) + { + st->tcx_cfg.tcxRateLoopOpt = 1; + move16(); + } + + st->tcx_cfg.ctx_hm = getCtxHm( st->total_brate_fx, st->rf_mode ); + + st->tcx_lpc_shaped_ari = getTcxLpcShapedAri( + st->total_brate_fx, + st->bwidth_fx + ,st->rf_mode + ); + +} + +void init_sig_buffers( Encoder_State_fx *st, const Word16 L_frame_old, const Word16 L_subfr ) +{ + + /* Encoder Past Samples at encoder-sampling-rate */ + st->encoderPastSamples_enc = shr(imult1616(st->L_frame_fx, 9), 4); + + /* Initialize Signal Buffers and Pointers at encoder-sampling-rate */ + IF ( st->ini_frame_fx == 0 ) + { + set16_fx(st->buf_speech_enc, 0, L_PAST_MAX_32k+L_FRAME32k+L_NEXT_MAX_32k); + set16_fx(st->buf_speech_enc_pe, 0, L_PAST_MAX_32k+L_FRAME32k+L_NEXT_MAX_32k); + set16_fx(st->buf_speech_ltp, 0, L_PAST_MAX_32k+L_FRAME32k+L_NEXT_MAX_32k); + set16_fx(st->buf_wspeech_enc, 0, L_FRAME16k+L_SUBFR+L_FRAME16k+L_NEXT_MAX_16k); + } + ELSE + { + test(); + test(); + test(); + test(); + test(); + IF ( NE_16(st->L_frame_fx,L_frame_old)&&!((EQ_32(st->total_brate_fx,ACELP_16k40)||EQ_32(st->total_brate_fx,ACELP_24k40))&&(EQ_32(st->total_brate_fx,st->last_total_brate_fx))&&(EQ_16(st->last_bwidth_fx,st->bwidth_fx)))) + { + lerp( st->buf_speech_enc, st->buf_speech_enc, st->L_frame_fx, L_frame_old ); + test(); + IF( NE_16(st->last_core_fx,TCX_20_CORE)&&NE_16(st->last_core_fx,TCX_10_CORE)) /* condition should be checked again */ + { + Copy( st->buf_speech_enc, st->buf_speech_ltp, st->L_frame_fx ); + } + + Copy_Scale_sig( st->old_wsp_fx, st->buf_wspeech_enc+st->L_frame_fx + L_SUBFR-L_WSP_MEM,L_WSP_MEM, sub(st->prev_Q_new, st->prev_Q_old)); + + /*Resamp buffers needed only for ACELP*/ + test(); + test(); + IF( EQ_16(st->L_frame_fx,L_FRAME)&&!st->tcxonly) + { + Copy_Scale_sig( st->old_inp_12k8_fx, st->buf_speech_enc_pe+st->L_frame_fx-L_INP_MEM,L_INP_MEM, sub(st->prev_Q_new, st->prev_Q_old)); + + } + ELSE IF( EQ_16(st->L_frame_fx,L_FRAME16k)&&!st->tcxonly) + { + lerp( st->buf_wspeech_enc+st->L_frame_fx + L_SUBFR-L_WSP_MEM, st->buf_wspeech_enc+st->L_frame_fx + L_SUBFR-310, 310, L_WSP_MEM ); + Copy( st->old_inp_16k_fx, st->buf_speech_enc_pe+st->L_frame_fx-L_INP_MEM,L_INP_MEM); + + } + + st->mem_preemph_enc = st->buf_speech_enc[st->encoderPastSamples_enc+st->encoderLookahead_enc-1]; + move16(); + st->mem_wsp_enc = st->buf_wspeech_enc[st->L_frame_fx+L_SUBFR-1]; + move16(); + } + /*coming from TCXonly modes*/ + ELSE IF( !st->tcxonly && GE_32(st->last_total_brate_fx,ACELP_32k)) + { + + Copy_Scale_sig( st->old_wsp_fx, st->buf_wspeech_enc+st->L_frame_fx + L_SUBFR-L_WSP_MEM,L_WSP_MEM, sub(st->prev_Q_new, st->prev_Q_old)); + + /*Resamp buffers needed only for ACELP*/ + IF( EQ_16(st->L_frame_fx,L_FRAME16k)) + { + lerp( st->buf_wspeech_enc+st->L_frame_fx + L_SUBFR-L_WSP_MEM, st->buf_wspeech_enc+st->L_frame_fx + L_SUBFR-310, 310, L_WSP_MEM ); + } + st->LPDmem.mem_w0 = 0; + move16(); + st->mem_wsp_enc = st->buf_wspeech_enc[st->L_frame_fx+L_SUBFR-1]; + move16(); + } + } + + st->new_speech_enc = st->buf_speech_enc + st->encoderPastSamples_enc + st->encoderLookahead_enc; + st->new_speech_enc_pe = st->buf_speech_enc_pe + st->encoderPastSamples_enc + st->encoderLookahead_enc; + st->new_speech_ltp = st->buf_speech_ltp + st->encoderPastSamples_enc + st->encoderLookahead_enc; + st->new_speech_TCX = st->input_buff + L_FRAME48k + NS2SA(48000, DELAY_FIR_RESAMPL_NS) - NS2SA(st->input_Fs_fx, DELAY_FIR_RESAMPL_NS); + + st->speech_enc = st->buf_speech_enc + st->encoderPastSamples_enc; + st->speech_enc_pe = st->buf_speech_enc_pe + st->encoderPastSamples_enc; + st->speech_ltp = st->buf_speech_ltp + st->encoderPastSamples_enc; + st->speech_TCX = st->new_speech_TCX - st->encoderLookahead_FB; + + st->wspeech_enc = st->buf_wspeech_enc + st->L_frame_fx + L_subfr; + + test(); + test(); + IF( st->ini_frame_fx == 0 || NE_16(st->L_frame_fx,L_frame_old)||EQ_16(st->last_codec_mode,MODE1)) + { + set16_fx(st->buf_synth, 0, OLD_SYNTH_SIZE_ENC+L_FRAME32k); + } + + st->synth = st->buf_synth + st->L_frame_fx + L_subfr; + + + return; +} + +static void init_core_sig_ana( Encoder_State_fx *st ) +{ + + + /* Pre-emphasis factor and memory */ + + st->preemph_fac = PREEMPH_FAC_SWB; /*SWB*/ move16(); + IF ( LT_16(st->fscale, (16000*FSCALE_DENOM)/12800)) + { + st->preemph_fac = PREEMPH_FAC; /*WB*/ move16(); + } + ELSE IF ( LT_16(st->fscale, (24000*FSCALE_DENOM)/12800)) + { + st->preemph_fac = PREEMPH_FAC_16k; /*WB*/ move16(); + } + + st->tcx_cfg.preemph_fac=st->preemph_fac; + move16(); + + st->gamma = GAMMA1; + move16(); + st->inv_gamma = GAMMA1_INV; + move16(); + IF ( EQ_32(st->sr_core, 16000)) + { + st->gamma = GAMMA16k; + move16(); + st->inv_gamma = GAMMA16k_INV; + move16(); + } + + + st->min_band_fx = 1; + move16(); + st->max_band_fx = 16; + move16(); + + IF ( st->narrowBand == 0) + { + st->min_band_fx = 0; + move16(); + st->max_band_fx = 19; + move16(); + } + + + return; +} + +static void init_acelp( Encoder_State_fx *st, Word16 L_frame_old , const Word16 shift) +{ + Word16 mem_syn_r_size_old; + Word16 mem_syn_r_size_new; + + + /* Init pitch lag */ + st->pit_res_max = initPitchLagParameters(st->sr_core, &st->pit_min, &st->pit_fr1, &st->pit_fr1b, &st->pit_fr2, &st->pit_max); + + + /* Init LPDmem */ + IF( st->ini_frame_fx == 0 ) + { + set16_fx( st->LPDmem.syn, 0, 1+M ); + + set16_fx( st->LPDmem.Txnq, 0, L_FRAME32k/2+64); + st->LPDmem.acelp_zir = st->LPDmem.Txnq + shr(st->L_frame_fx,1); + set16_fx( st->LPDmem.mem_syn_r, 0, L_SYN_MEM ); + } + ELSE /*Rate switching*/ + { + IF( EQ_16(st->last_core_fx,ACELP_CORE)) + { + lerp( st->LPDmem.Txnq,st->LPDmem.Txnq, shr(st->L_frame_fx,1), shr(L_frame_old,1) ); + } + ELSE + { + lerp( st->LPDmem.Txnq,st->LPDmem.Txnq, st->tcx_cfg.tcx_mdct_window_length, st->tcx_cfg.tcx_mdct_window_length_old ); + } + st->LPDmem.acelp_zir = st->LPDmem.Txnq + shr(st->L_frame_fx,1); + + /* Rate switching */ + IF( EQ_16(st->last_codec_mode,MODE1)) + { + Copy( st->mem_syn1_fx, st->LPDmem.mem_syn2, M ); + set16_fx( st->LPDmem.Txnq, 0, L_FRAME32k/2+64); + set16_fx( st->LPDmem.syn, 0, M ); + } + + /*AMR-WBIO->MODE2*/ + IF( EQ_16(st->last_core_fx,AMR_WB_CORE)) + { + st->next_force_safety_net_fx=1; + move16(); + st->last_core_fx = ACELP_CORE; + move16(); + } + /*HQ-CORE->MODE2*/ + test(); + IF( EQ_16(st->last_codec_mode,MODE1)&&EQ_16(st->last_core_fx,HQ_CORE)) + { + /*Reset of ACELP memories*/ + st->next_force_safety_net_fx=1; + move16(); + st->rate_switching_reset = 1; + move16(); + st->LPDmem.tilt_code = TILT_CODE; + move16(); + set16_fx( st->LPDmem.old_exc, 0, L_EXC_MEM ); + set16_fx( st->LPDmem.syn, 0, 1+M ); + st->LPDmem.mem_w0 = 0; + move16(); + set16_fx( st->LPDmem.mem_syn, 0, M ); + set16_fx( st->LPDmem.mem_syn2, 0, M ); + + /* unquantized LPC*/ + test(); + IF ( !((EQ_32(st->total_brate_fx,ACELP_16k40)||EQ_32(st->total_brate_fx,ACELP_24k40))&&(EQ_32(st->total_brate_fx,st->last_total_brate_fx))&&(EQ_16(st->last_bwidth_fx,st->bwidth_fx)))) + { + Copy( st->lsp_old1_fx, st->lspold_enc_fx, M ); /*lsp old @12.8kHz*/ + IF( EQ_16(st->L_frame_fx,L_FRAME16k)) + { + lsp_convert_poly_fx( st->lspold_enc_fx, st->L_frame_fx, 0 ); + } + } + Copy( st->lspold_enc_fx, st->lsp_old_fx, M ); /*used unquantized values for mid-LSF Q*/ + IF( st->tcxonly == 0 ) + { + lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, st->sr_core ); + } + ELSE + { + E_LPC_lsp_lsf_conversion( st->lsp_old_fx, st->lsf_old_fx, M ); + } + st->last_core_fx = TCX_20_CORE; + move16(); + + st->tcx_cfg.last_aldo=1; /*It was previously ALDO*/ + st->tcx_cfg.tcx_curr_overlap_mode = ALDO_WINDOW; + /*ALDO overlap windowed past: also used in MODE1 but for other MDCT-FB*/ + set16_fx( st->old_out_fx, 0, st->L_frame_fx ); + } + ELSE + { + test(); + test(); + IF( (NE_16(st->L_frame_fx,L_frame_old))&&(LE_16(st->L_frame_fx,L_FRAME16k))&&(LE_16(L_frame_old,L_FRAME16k))) + { + /* convert quantized LSP vector */ + st->rate_switching_reset=lsp_convert_poly_fx( st->lsp_old_fx, st->L_frame_fx, 0 ); + IF( st->tcxonly == 0 ) + { + lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, st->sr_core ); + } + ELSE + { + E_LPC_lsp_lsf_conversion( st->lsp_old_fx, st->lsf_old_fx, M ); + } + IF( EQ_16(st->L_frame_fx,L_FRAME16k)) + { + Copy( st->lsp_old_fx, st->lspold_enc_fx, M ); + } + ELSE + { + Copy( st->lsp_old1_fx, st->lspold_enc_fx, M ); + } + + synth_mem_updt2( st->L_frame_fx, st->last_L_frame_fx, st->LPDmem.old_exc, st->LPDmem.mem_syn_r, st->LPDmem.mem_syn2, st->LPDmem.mem_syn, ENC ); + + /*Mem of deemphasis stay unchanged : st->LPDmem.syn*/ + { + Word16 tmp, A[M+1], Ap[M+1],tmp_buf[M+1]; + /* Update wsyn */ + /* lsp2a_stab( st->lsp_old, A, M ); */ + E_LPC_f_lsp_a_conversion(st->lsp_old_fx, A, M); + weight_a_fx( A, Ap, GAMMA1, M ); + tmp=0; + move16(); + tmp_buf[0]=0; + move16(); + Copy( st->LPDmem.mem_syn2, tmp_buf+1, M ); + deemph_fx( tmp_buf+1, st->preemph_fac, M, &tmp ); + Residu3_fx( Ap, tmp_buf+M, &tmp, 1, 1 ); + st->LPDmem.mem_w0 = sub(shr(st->wspeech_enc[-1],shift), tmp); + } + } + ELSE IF((NE_16(st->L_frame_fx,L_frame_old))) + { + /*Partial reset of ACELP memories*/ + st->next_force_safety_net_fx=1; + move16(); + st->rate_switching_reset = 1; + move16(); + + /*reset partly some memories*/ + st->LPDmem.tilt_code = TILT_CODE; + move16(); + set16_fx( st->LPDmem.old_exc, 0, L_EXC_MEM ); + move16(); + + /*Resamp others memories*/ + /*Size of LPC syn memory*/ + /* 1.25/20.0 = 1.0/16.0 -> shift 4 to the right. */ + mem_syn_r_size_old = shr(L_frame_old, 4); + mem_syn_r_size_new = shr(st->L_frame_fx, 4); + + lerp( st->LPDmem.mem_syn_r+L_SYN_MEM-mem_syn_r_size_old, st->LPDmem.mem_syn_r+L_SYN_MEM-mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old ); + Copy( st->LPDmem.mem_syn_r+L_SYN_MEM-M, st->LPDmem.mem_syn, M); + Copy( st->LPDmem.mem_syn, st->LPDmem.mem_syn2, M ); + + /*Untouched memories : st->LPDmem.syn & st->LPDmem.mem_w0*/ + st->LPDmem.mem_w0 = 0; + move16(); + + /* unquantized LPC*/ + Copy( st->lsp_old1_fx, st->lspold_enc_fx, M ); /*lsp old @12.8kHz*/ + IF( EQ_16(st->L_frame_fx,L_FRAME16k)) + { + lsp_convert_poly_fx( st->lspold_enc_fx, st->L_frame_fx, 0 ); + } + Copy( st->lspold_enc_fx, st->lsp_old_fx, M ); /*used unquantized values for mid-LSF Q*/ + IF( st->tcxonly == 0 ) + { + lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, st->sr_core ); + } + ELSE + { + E_LPC_lsp_lsf_conversion( st->lsp_old_fx, st->lsf_old_fx, M ); + } + } + ELSE IF( !st->tcxonly && EQ_16(st->L_frame_fx,L_FRAME16k)&>_32(st->last_total_brate_fx,ACELP_32k)) + { + lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, st->sr_core ); + } + } + } + + test(); + test(); + if(EQ_16(st->last_bwidth_fx,NB)&&NE_16(st->bwidth_fx,NB)&&st->ini_frame_fx!=0) + { + st->rate_switching_reset=1; + move16(); + } + + /* Post-processing */ + st->dm_fx.prev_gain_code = L_deposit_l(0); + set16_fx(st->dm_fx.prev_gain_pit, 0, 6); + st->dm_fx.prev_state = 0; + move16(); + st->LPDmem.gc_threshold = 0; + move16(); + + /* Pulse Search configuration */ + st->acelp_autocorr = 1; + move16(); + + /*Use for 12.8 kHz sampling rate and low bitrates, the conventional pulse search->better SNR*/ + if ((LE_32(st->total_brate_fx, ACELP_9k60)||st->rf_mode!=0)&&(EQ_32(st->sr_core,12800))) + { + st->acelp_autocorr = 0; + move16(); + } + + + /*BPF parameters for adjusting gain in function of background noise*/ + IF( EQ_16(st->codec_mode,MODE2)) + { + st->mem_bpf.lp_error_ener = L_deposit_l(0); + if( st->last_codec_mode == MODE1 ) + { + st->mem_bpf.lp_error = L_deposit_l(0); + } + } + + + return; +} + +static void init_modes( Encoder_State_fx *st ) +{ + Word8 n; + Word32 tmp32; + + + + + /* Restrict ACE/TCX20/TCX10 mode */ + move16(); + st->restrictedMode = getRestrictedMode(st->total_brate_fx, st->Opt_AMR_WB_fx); + move16(); + st->acelpEnabled = 0; + move16(); + st->tcx20Enabled = 0; + move16(); + st->tcx10Enabled = 0; + + if (EQ_16(s_and(st->restrictedMode,1),1)) + { + st->acelpEnabled = 1; + move16(); + } + if (EQ_16(s_and(st->restrictedMode,2),2)) + { + st->tcx20Enabled = 1; + move16(); + } + if (EQ_16(s_and(st->restrictedMode,4),4)) + { + st->tcx10Enabled = 1; + move16(); + } + + + /* TCX mode (TCX20 TCX10_10 or NO_TCX) */ + st->tcxMode = NO_TCX; + move16(); + + /* Bits Budget */ + /*st->bits_frame_nominal = (int)( (float)st->L_frame_fx * (float)FSCALE_DENOM * (float)st->bitrate / ( (float)st->fscale * 12800.0f ) );*/ + /*st->bits_frame_nominal = (int)( (float)st->L_frame_fx/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->bitrate/100.0f + 0.49f );*/ + /*328 = 0.010009765625 in 0Q15*/ + /* st->bits_frame_nominal = extract_h(L_add(L_mult(div_l(L_mult(shl(st->L_frame_fx,2),st->bitrate),st->fscale),328),16056)); */ + + /* st->bits_frame_nominal = (int)( (float)st->L_frame_fx/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->bitrate/100.0f + 0.49f ); */ + assert(FSCALE_DENOM == 512); + assert(st->fscale == 2 * st->L_frame_fx); /* this assumption is true if operated in 20ms frames with FSCALE_DENOM == 512, which is the current default */ + tmp32 = L_shl(st->total_brate_fx, 1); /* (float)st->L_frame_fx/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->bitrate */ + st->bits_frame_nominal = extract_l(L_shr(Mpy_32_16_1(tmp32, 20972), 6)); /* 20972 = 0.01 * 64 * 32768 */ + assert(st->bits_frame_nominal == (int)( (float)st->L_frame_fx/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->total_brate_fx/100.0f + 0.49f )); + + IF (st->Opt_AMR_WB_fx) + { + st->bits_frame = st->bits_frame_nominal; + st->bits_frame_core = st->bits_frame_nominal; + st->frame_size_index = 0; + move16(); + } + ELSE + { + FOR (n=0; nbits_frame_nominal)) + { + move16(); + move16(); + move16(); + st->frame_size_index = n; + st->bits_frame = FrameSizeConfig[n].frame_bits; + st->bits_frame_core = FrameSizeConfig[n].frame_net_bits; + BREAK; + } + } + if (n==FRAME_SIZE_NB) + { + assert(!"Bitrate not supported: not part of EVS"); + } + } + + /* Reconfigure core */ + core_coder_reconfig( st ); + + + return; +} diff --git a/lib_enc/core_enc_ol.c b/lib_enc/core_enc_ol.c new file mode 100644 index 0000000..3a16ba9 --- /dev/null +++ b/lib_enc/core_enc_ol.c @@ -0,0 +1,1612 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "prot_fx.h" +#include "basop_util.h" +#include "options.h" +#include "cnst_fx.h" +#include "stl.h" +#include "stl.h" +#include "rom_com_fx.h" + + + +void closest_centroid_rf(const Word16 *data, /* i : input data */ + const Word16 *weights, /* i : weights */ + const Word16 *quantizer, /* i : quantizer table */ + const Word16 centroids, /* i : number of centroids */ + const Word16 length, /* i : dimension of quantiser */ + Word16 *ind_vec); /* o : list of best match indice vectors */ + + +/*-------------------------------------------------------------------* + * core_encode_openloop() + * + * Open-loop core encoder + *-------------------------------------------------------------------*/ + +void core_encode_openloop( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 coder_type, /* i : coding type */ + const Word16 pitch[3], /* i : open-loop pitch values for quantiz. */ + const Word16 voicing[3], /* i : open-loop pitch gains */ + const Word16 Aw[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/ + const Word16 *lsp_new, /* i : LSPs at the end of the frame */ + const Word16 *lsp_mid, /* i : LSPs at the middle of the frame */ + Word16 *pitch_buf, /* i/o: floating pitch values for each subfr*/ + Word16 *voice_factors, /* o : voicing factors */ + Word16 *ptr_bwe_exc, /* o : excitation for SWB TBE */ + const Word16 vad_hover_flag, + const Word16 vad_flag_dtx, + Word16 Q_new, + Word16 shift +) +{ + Word16 lsf_q[M], lsp_q[M], lspmid_q[M], lsf_tcx_q[M], lsp_tcx_q[M]; + Word16 lspq_ind[M]; + Word16 A_q_ind[M+1]; + Word16 tcx_lpc_cdk; + Word16 A_w[M+1]; + Word16 A_q[NB_SUBFR16k*(M+1)]; + Word16 param_lpc[NPRM_LPC_NEW]; + Word16 nbits_lpc; + Word16 param_core[2*NPRM_DIV]; + Word16 target_bits; + Word16 stab_fac; + Word32 spectrum_long[N_MAX]; /* MDCT output for a long block */ + Word16 spectrum_long_e; + Word16 indexBuffer[N_MAX+1]; + CONTEXT_HM_CONFIG hm_cfg; + Word16 bits_param_lpc[10], no_param_lpc; + + Word16 i; + /* lsf quant parameters */ + Word16 lsp_q_rf[M]; + Word16 Aq_rf[NB_SUBFR*(M+1)]; + Word16 stab_fac_rf; + Word16 *exc_rf; + Word16 *syn_rf; + Word16 tmp; + Word16 rf_PLC_Mode; + Word16 TD_mode; + Word16 xsp[M], xsf[M]; + Word16 rf_mem_MA[M]; + + Word16 exc_buf_rf[L_EXC_MEM + L_FRAME + 1]; + Word16 syn_buf_rf[M+L_FRAME16k+L_FRAME16k/2]; + + Word16 w_rf[M+1], lsf_uq_rf[M+1]; + Word16 lsf_q_1st_rf[M+1], lsf_q_d_rf[M+1], lsf_q_rf[M+1]; + Word16 lsp_old_q_rf[M+1], lsf_old_q_rf[M+1]; + + + /* copy primary memories to use later during partial copy assembly */ + + /* These primary memories are already scaled by (Q_new-st->prev_Q_new) inside pre_proc_fx() + and copied to the partial frame at start of each frame to be used in computing partial copy params. + But then they are discarded, not need for continuation + The idea is to not maintain these memories seperately, and have the ability to generate the + primary copy memories using the partial copy parameters at decode, so same in enc + */ + + /* back up the old LSPs and LSFs */ + Copy(st->lsp_old_fx, lsp_old_q_rf, M); + Copy(st->lsf_old_fx, lsf_old_q_rf, M); + + /* back up old exc before primary encoding */ + set16_fx( exc_buf_rf, 0, (L_EXC_MEM+L_FRAME+1) ); + exc_rf = exc_buf_rf + L_EXC_MEM; + Copy(st->LPDmem.old_exc, exc_buf_rf, L_EXC_MEM); + + /* back up old synthesis before primary encoding */ + set16_fx( syn_buf_rf, 0, (M+L_FRAME16k+L_FRAME16k/2) ); + syn_rf = syn_buf_rf + M; + Copy(st->LPDmem.mem_syn, syn_buf_rf, M); + + /* back up syn2 mem */ + Copy(st->LPDmem.mem_syn2, st->rf_mem_syn2, M); + + /* back up LPD mem_w0 target generation memory */ + st->rf_mem_w0 = st->LPDmem.mem_w0; + + /* back up clip gain memory */ + Copy( st->clip_var_fx, st->rf_clip_var, 6 ); + + /* back up tilt code */ + st->rf_tilt_code = st->LPDmem.tilt_code; + + /* back up dispMem */ + st->rf_dm_fx.prev_state = st->dm_fx.prev_state; + st->rf_dm_fx.prev_gain_code = st->dm_fx.prev_gain_code; + FOR(i=0; i<6; i++) + { + st->rf_dm_fx.prev_gain_pit[i] = st->dm_fx.prev_gain_pit[i]; + } + + /* back up gc_threshold for noise addition */ + st->rf_gc_threshold = st->LPDmem.gc_threshold; + + + /* initialization */ + tcx_lpc_cdk = 0; + move16(); + set16_fx( param_lpc, 0, NPRM_LPC_NEW ); + set16_fx( param_core, 0, 2*NPRM_DIV ); + Copy( st->tcxltp_param, ¶m_core[1+NOISE_FILL_RANGES], LTPSIZE ); + + no_param_lpc = 0; + move16(); /* avoid MSVC warnings */ + nbits_lpc = 0; + move16(); /* avoid MSVC warnings */ + stab_fac = 0; + move16(); /* avoid MSVC warnings */ + + set32_fx(spectrum_long, 0, N_MAX); + + hm_cfg.indexBuffer = indexBuffer; + move16(); + + /*--------------------------------------------------------------* + * LPC Quantization + *---------------------------------------------------------------*/ + + st->acelp_cfg.midLpc = st->acelp_cfg.midLpc_enable; + move16(); + test(); + if ( (EQ_16(st->lpcQuantization, 1))&&(EQ_16(coder_type,VOICED))) + { + st->acelp_cfg.midLpc = 0; + move16(); + } + + test(); + IF ( st->core_fx==ACELP_CORE || !st->enableTcxLpc ) + { + IF (st->envWeighted) + { + /* Unweight the envelope */ + E_LPC_lsp_unweight( st->lsp_old_fx, st->lsp_old_fx, st->lsf_old_fx, st->inv_gamma, M ); + st->envWeighted = 0; + move16(); + } + + IF(EQ_16(st->core_fx,TCX_20_CORE)) + { + lpc_quantization( st, st->core_fx, st->lpcQuantization, st->lsf_old_fx, lsp_new, lsp_mid, + lsp_q, lsf_q, lspmid_q, lspq_ind, st->clip_var_fx, st-> mem_MA_fx, st->mem_AR_fx, + st->narrowBand, AUDIO, st->acelp_cfg.midLpc, param_lpc, &nbits_lpc, bits_param_lpc, &no_param_lpc, + &(st->seed_acelp), st->Bin_E_fx, st->Bin_E_old_fx, add(Q_new, Q_SCALE - 2) ); + + } + ELSE + { + + lpc_quantization( st, st->core_fx, st->lpcQuantization, st->lsf_old_fx, lsp_new, lsp_mid, + lsp_q, lsf_q, lspmid_q, lspq_ind, st->clip_var_fx, st-> mem_MA_fx, st->mem_AR_fx, + st->narrowBand, coder_type, st->acelp_cfg.midLpc, param_lpc, &nbits_lpc, bits_param_lpc, &no_param_lpc, + &(st->seed_acelp), st->Bin_E_fx, st->Bin_E_old_fx, add(Q_new, Q_SCALE - 2) ); + } + + /*-------------------------------------------------------------* + * Rate switching: reset + *---------------------------------------------------------------*/ + IF( st->rate_switching_reset!=0 ) + { + Copy( lsp_q, st->lsp_old_fx, M ); + Copy( lsf_q, st->lsf_old_fx, M ); + Copy( lsp_q, lspmid_q, M ); + } + + stab_fac = lsf_stab_fx(lsf_q, st->lsf_old_fx, 0, st->L_frame_fx); + } + + + + + /*--------------------------------------------------------------* + * Run ACELP + *---------------------------------------------------------------*/ + IF ( st->core_fx==ACELP_CORE ) + { + IF ( st->acelp_cfg.midLpc != 0 ) + { + int_lsp4_fx( st->L_frame_fx, st->lsp_old_fx, lspmid_q, lsp_q, A_q, M, 0 ); + } + ELSE + { + int_lsp_fx( st->L_frame_fx, st->lsp_old_fx, lsp_q, A_q, M, interpol_frac_fx, 0 ); + } + + /* Calculate target bits */ + target_bits = sub(sub(st->bits_frame_core, nbits_lpc), st->nb_bits_header_ace); + + if(EQ_16(st->rf_mode,1)) + { + /* joint bit allocation for redundant frame and TBE */ + /* calculate target bits for core coding */ + target_bits = sub(target_bits, st->rf_target_bits_write); + } + IF( st->igf != 0 ) + { + target_bits = sub( target_bits, get_tbe_bits_fx( st->total_brate_fx, st->bwidth_fx, st->rf_mode ) ); + + } + + if ( st->acelp_cfg.midLpc != 0) + { + target_bits = sub(target_bits, MIDLSF_NBITS ); + } + + if( st->plcExt.enableGplc ) + { + target_bits = sub(target_bits, st->plcExt.nBits); + } + + /* reset TBE buffers previous frame frame wasn't ACELP*/ + IF( NE_16( st->last_core_fx, ACELP_CORE )) + { + TBEreset_enc_fx( st, st->bwidth_fx ); + } + + + /* Run ACELP encoder */ + coder_acelp( + &(st->acelp_cfg), + coder_type, + Aw, + A_q, + st->speech_enc_pe, + st->synth, + &(st->LPDmem), + voicing, + pitch, + param_core, + stab_fac, + st, + &st->plcExt, + target_bits, + Q_new, + shift, + pitch_buf, + voice_factors, + ptr_bwe_exc + ); + + + st->glr_idx[0] = encSideSpecPowDiffuseDetector( st->plcExt.last_lsf_ref, st->plcExt.last_lsf_con, st->last_sr_core, &(st->prev_lsf4_mean), st->glr, coder_type ); + Copy(lsf_q, st->plcExt.last_lsf_ref, M); + Copy(st->plcExt.lsf_con, st->plcExt.last_lsf_con, M); + + updateSpecPowDiffuseIdx(st); + + if(GT_16(st->last_stab_fac, 655/*0.02f Q15*/)) + { + move16(); + st->glr_idx[0] = 0; + } + move16(); + st->last_stab_fac = stab_fac; + + move16(); + st->plcExt.LPDmem = &st->LPDmem; + encoderSideLossSimulation( st, &st->plcExt, lsf_q, stab_fac, st->plcExt.calcOnlylsf, st->L_frame_fx); + + st->tcxltp_norm_corr_past = voicing[1]; + move16(); + + st->tcx_cfg.tcx_curr_overlap_mode = st->tcx_cfg.tcx_last_overlap_mode = ALDO_WINDOW; + move16(); + + } + + + + /*--------------------------------------------------------------* + * Run TCX20 + *---------------------------------------------------------------*/ + + IF ( EQ_16(st->core_fx, TCX_20_CORE)) + { + IF (st->enableTcxLpc) + { + IF( EQ_16(st->rf_mode,1)) + { + Copy(st->mem_MA_fx, rf_mem_MA, M); + } + + tcx_lpc_cdk = tcxlpc_get_cdk(st->tcx_cfg.coder_type); + + /* Get the envelope corresponding to the current frame */ + E_LPC_int_lpc_tcx( st->lspold_enc_fx, lsp_new, A_q ); + + /* Weight the envelope */ + weight_a_fx(A_q, A_q, st->gamma, M); + + /* Save the weighted envelope */ + Copy(A_q, A_w, M+1); + + /* Convert to xSP and xSF */ + E_LPC_a_lsp_conversion(A_q, xsp, lsp_new, M ); + E_LPC_lsp_lsf_conversion(xsp, xsf, M); + + /* Quantize */ + Q_lsf_tcxlpc( xsf, lsf_tcx_q, lspq_ind, param_lpc, M, st->narrowBand, tcx_lpc_cdk, st-> mem_MA_fx, + st->tcx_cfg.coder_type, st->Bin_E_fx, add(Q_new, Q_SCALE-2) ); + + /* Account for consumed bits */ + nbits_lpc = TCXLPC_NUMBITS; + move16(); + if (param_lpc[0]) + { + nbits_lpc = add(nbits_lpc, TCXLPC_IND_NUMBITS); + } + + /* Convert quantized xSF to xSP and A */ + E_LPC_lsf_lsp_conversion(lsf_tcx_q, lsp_tcx_q, M); + E_LPC_f_lsp_a_conversion(lsp_tcx_q, A_q, M); + } + ELSE + { + E_LPC_int_lpc_tcx( st->lsp_old_fx, lsp_q, A_q ); + } + + IF (st->tcx_lpc_shaped_ari != 0) + { + E_LPC_f_lsp_a_conversion(lspq_ind, A_q_ind, M); + } + + /* Calculate target bits */ + target_bits = sub(sub(st->bits_frame_core, nbits_lpc), st->nb_bits_header_tcx); + if(EQ_16(st->rf_mode,1)) + { + /* joint bit allocation for redundant frame and TBE */ + /* calculate target bits for core coding */ + target_bits = sub(target_bits, st->rf_target_bits_write); + } + + IF (EQ_16(st->mdct_sw, MODE1)) + { + /* Account for core mode signaling bits difference: bandwidth and ACELP/TCX signaling bit are replaced */ + target_bits = add(target_bits, sub(add(FrameSizeConfig[st->frame_size_index].bandwidth_bits, 1), signalling_mode1_tcx20_enc(st, 0))); + } + ELSE if ( EQ_16(st->mdct_sw_enable, MODE2)) + { + target_bits = sub(target_bits, 1); + } + + if( st->plcExt.enableGplc ) + { + target_bits = sub(target_bits, st->plcExt.nBits); + } + + /* subtract bits for TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */ + target_bits = sub(target_bits,1); + test(); + if (EQ_16(st->tcx_cfg.tcx_curr_overlap_mode, HALF_OVERLAP)||EQ_16(st->tcx_cfg.tcx_curr_overlap_mode,MIN_OVERLAP)) + { + target_bits = sub(target_bits,1); + } + + target_bits = sub(target_bits, st->tcxltp_bits); + + + coder_tcx( + 0, + &(st->tcx_cfg), + A_q, + A_q_ind, + st->synth, + st->L_frame_fx, + st->L_frameTCX, + st->tcx_cfg.tcx_coded_lines, + target_bits, + st->tcxonly, + spectrum_long, + &spectrum_long_e, + &(st->LPDmem), + param_core, + st, + &hm_cfg + ); + + coder_tcx_post( st, &(st->LPDmem), &(st->tcx_cfg), st->synth, A_q, Aw, st->wspeech_enc, Q_new, shift ); + + + move16(); + st->plcExt.LPDmem = &(st->LPDmem); + + GplcTcxEncSetup(st, &st->plcExt, Q_new); + + IF (st->enableTcxLpc) + { + E_LPC_lsp_unweight( lsp_tcx_q, lsp_q, lsf_q, st->inv_gamma, M ); + } + + encoderSideLossSimulation( st, &st->plcExt, lsf_q, stab_fac, 1, st->L_frame_fx ); + + } + + + + /* Update lsp/lsf memory */ + Copy( lsp_new, st->lspold_enc_fx, M ); + + test(); + IF ( st->enableTcxLpc && st->core_fx != ACELP_CORE ) + { + /* Update lsf/lsp memory */ + Copy(lsf_tcx_q, st->lsf_old_fx, M); + Copy(lsp_tcx_q, st->lsp_old_fx, M); + st->envWeighted = 1; + move16(); + + /* Update ACELP quantizer state */ + lsf_update_memory( st->narrowBand, st->lsf_old_fx, st-> mem_MA_fx, st-> mem_MA_fx, M ); + + st->pstreaklen_fx = 0; + st->streaklimit_fx = 32767; + /* check resonance for pitch clipping algorithm */ + gp_clip_test_lsf_fx( st->lsf_old_fx, st->clip_var_fx, 0 ); + Copy(st->lsf_old_fx, st->mem_AR_fx, M); + } + ELSE + { + /* Update ISP/ISF memory */ + Copy(lsf_q, st->lsf_old_fx, M); + Copy(lsp_q, st->lsp_old_fx, M); + } + + /*--------------------------------------------------------------* + * Update LP_CNG parameters + *--------------------------------------------------------------*/ + + test(); + IF( st->Opt_DTX_ON_fx != 0 && vad_hover_flag != 0 ) + { + st->burst_ho_cnt_fx = add(st->burst_ho_cnt_fx,1); + if( GT_16(st->burst_ho_cnt_fx,HO_HIST_SIZE)) + { + st->burst_ho_cnt_fx = HO_HIST_SIZE; + move16(); + } + } + ELSE + { + IF( st->Opt_DTX_ON_fx != 0 && vad_flag_dtx != 0 ) + { + st->burst_ho_cnt_fx = 0; + move16(); + } + } + + IF( st->Opt_DTX_ON_fx != 0 ) + { + /* update CNG parameters in active frames */ + IF ( EQ_16(st->bwidth_fx,NB)&&st->enableTcxLpc&&st->core_fx!=ACELP_CORE) + { + Word16 buf[L_LP], res[L_FRAME], A[M+1], r_l[M+1], r_h[M+1], lsptmp[M], Q_r; + assert(st->L_frame_fx==L_FRAME); + Copy(st->synth+L_FRAME-L_LP, buf, L_LP); + tmp = st->synth[L_FRAME-L_LP-1]; + E_UTIL_f_preemph2(Q_new-1, buf, st->preemph_fac, L_LP, &tmp); + autocorr_fx( buf, M, r_h, r_l, &Q_r, L_LP, Assym_window_W16fx, 0, 0 ); + lag_wind(r_h, r_l, M, INT_FS_FX, LAGW_WEAK); + E_LPC_lev_dur(r_h, r_l, A, NULL, M, NULL); + E_LPC_a_lsp_conversion(A, lsptmp, lsp_new, M); + Residu3_fx(A, buf+L_LP-L_FRAME, res, L_FRAME, 1); + cng_params_upd_fx( lsptmp, res, st->L_frame_fx, &st->ho_circ_ptr_fx, + st->ho_ener_circ_fx, &st->ho_circ_size_fx, st->ho_lsp_circ_fx, + Q_new, ENC, NULL, &st->cng_buf_cnt, st->cng_exc2_buf, + st->cng_Qexc_buf, st->cng_brate_buf, st->last_active_brate_fx ); + } + ELSE + { + cng_params_upd_fx( lsp_new, st->LPDmem.old_exc+L_EXC_MEM-st->L_frame_fx, + st->L_frame_fx, &st->ho_circ_ptr_fx, st->ho_ener_circ_fx, + &st->ho_circ_size_fx, st->ho_lsp_circ_fx, Q_new, ENC, NULL, + &st->cng_buf_cnt, st->cng_exc2_buf, + st->cng_Qexc_buf, st->cng_brate_buf, + st->last_active_brate_fx ); + } + + IF( EQ_16(st->L_frame_fx,L_FRAME)) + { + /* store LSPs@16k, potentially to be used in CNG@16k */ + Copy( st->lsp_old16k_fx, &(st->ho_lsp_circ2_fx[(st->ho_circ_ptr_fx)*M]), M ); + } + + /* Set 16k LSP flag for CNG buffer */ + st->ho_16k_lsp_fx[st->ho_circ_ptr_fx] = 1; + move16(); + if ( EQ_16(st->L_frame_fx,L_FRAME)) + { + st->ho_16k_lsp_fx[st->ho_circ_ptr_fx] = 0; + move16(); + } + + /* efficient DTX hangover control */ + IF ( GT_16(st->burst_ho_cnt_fx, 1)) + { + dtx_hangover_control_fx( st, lsp_new ); + } + } + + /*--------------------------------------------------------------* + * Adaptive Bass Post-filter + *---------------------------------------------------------------*/ + + test(); + IF (GT_16(st->core_fx, ACELP_CORE)||(st->rate_switching_reset!=0)) + { + /*TCX mode: copy values*/ + set16_fx(st->mem_bpf.noise_buf, 0, 2*L_FILT16k); /*TCX->no gain*/ + set16_fx(st->mem_bpf.error_buf, 0, L_FILT16k); /*TCX->no gain*/ + st->bpf_gain_param=0; + } + ELSE IF (st->acelp_cfg.bpf_mode > 0) + { + /*ACELP: estimate bpf parameter with delay=0*/ + + /*Estimate bpf parameter*/ + bass_pf_enc( st->speech_enc, st->synth, st->bpf_T, st->bpf_gainT, st->L_frame_fx, L_SUBFR, &(st->bpf_gain_param), st->acelp_cfg.bpf_mode, &(st->mem_bpf) ); + } + + + + + /*--------------------------------------------------------------* + * Analysis Print Out + *---------------------------------------------------------------*/ + + + /*--------------------------------------------------------------* + * Generate Bitstream + *---------------------------------------------------------------*/ + + enc_prm( coder_type, param_core, param_lpc, st, st->L_frame_fx, &hm_cfg, bits_param_lpc, no_param_lpc ); + + /* Channel-aware mode - encode partial copy */ + IF( EQ_16(st->rf_mode,1)) + { + set16_fx(lsf_q_1st_rf, 0, M); + IF (EQ_16(st->core_fx, ACELP_CORE)) + { + /* convert LSPs to LP coefficients */ + lsp2lsf_fx( lsp_new, lsf_uq_rf, M, st->sr_core ); + /*i: lsp_new Q15 */ + /*o: lsf_uq_rf Qx2.56*/ + + /* first stage VQ, 8 bits; reuse TCX high rate codebook */ + st->rf_indx_lsf[0][0] = vlpc_1st_cod(lsf_uq_rf, lsf_q_1st_rf, w_rf, st->rf_mode); + /*v_sub(lsf_uq_rf, lsf_q_1st_rf, lsf_q_d_rf, M);*/ + FOR (i=0; irf_indx_lsf[0][1]); + /*i: lsf_q_d_rf in Q6 */ + /*o: quantization index Q0 */ + + /* quantized lsf from two stages */ + /*v_add(lsf_q_1st_rf, lsf_q_diff_cb_8b_rf + M * st->rf_indx_lsf[0][1], lsf_q_rf, M);*/ + FOR (i=0; irf_indx_lsf[0][1]]; /*tmp = quantized lsf_q_d_rf in Q6*/ + tmp = shr(mult_r(tmp,20972),4); /* bring lsf_q_d_rf to Qx2.56 for addition */ + lsf_q_rf[i] = add(lsf_q_1st_rf[i], tmp); + } + + v_sort( lsf_q_rf, 0, M-1 ); + reorder_lsf_fx( lsf_q_rf, LSF_GAP_FX, M, st->sr_core ); + } + ELSE + { + Word16 rf_tcx_lpc_cdk; + + rf_tcx_lpc_cdk = tcxlpc_get_cdk( GENERIC ); + /* Quantize */ + Q_lsf_tcxlpc( xsf, lsf_tcx_q, lspq_ind, param_lpc, M, st->narrowBand, rf_tcx_lpc_cdk, rf_mem_MA, GENERIC, st->Bin_E_fx, add(Q_new, Q_SCALE-2) ); + + /* VQ, 5+4+4 bits; reuse TCX low rate codebook */ + st->rf_indx_lsf[0][0] = param_lpc[1]; + st->rf_indx_lsf[0][1] = param_lpc[2]; + st->rf_indx_lsf[0][2] = param_lpc[3]; + } + + IF (EQ_16(st->core_fx, ACELP_CORE)) + { + /* current n-th ACELP frame and its corresponding partial copy */ + + /*lsf2lsp( lsf_q_rf, lsp_q_rf, M, st->sr_core );*/ + E_LPC_lsf_lsp_conversion( lsf_q_rf, lsp_q_rf, M ); + /*i: lsf_q_rf in Qx2.56*/ + /*o: lsp_q_rf in Q15*/ + + /* Interpolate LSPs and convert to LPC */ + int_lsp_fx( st->L_frame_fx, lsp_old_q_rf, lsp_q_rf, Aq_rf, M, interpol_frac_fx, 0 ); + + /* stability estimation */ + stab_fac_rf = lsf_stab_fx( lsf_q_rf, lsf_old_q_rf, 0, st->L_frame_fx ); /*Q15*/ + + /* Configure partial copy estimation of the current n-th frame to be packed in future with n+fec_offset frame */ + /* o: rf_frame_type, o: rf_target_bits */ + BITS_ALLOC_ACELP_config_rf( coder_type, st->rf_tilt_buf, &st->rf_frame_type, &st->rf_target_bits, st->nb_subfr, st->rf_fec_indicator, pitch_buf ); + + /* RF frame type in the buffer */ + st->rf_indx_frametype[0] = st->rf_frame_type; + st->rf_targetbits_buff[0] = st->rf_target_bits; + + IF( NE_16(st->rf_frame_type,RF_NO_DATA)) + { + /* coder_acelp_rf does the partial copy encoding based on the rf frame type chosen for the RF encoding */ + coder_acelp_rf(&(st->acelp_cfg_rf), coder_type, Aw, Aq_rf, st->speech_enc_pe, voicing, pitch, + stab_fac_rf, st, st->rf_target_bits, st->rf_frame_type, exc_rf, syn_rf, Q_new, shift); + } + } + ELSE + { + st->rf_clas[0] = st->clas_fx; + move16(); + st->rf_gain_tcx[0] = param_core[0]; + move16(); + + /* attenuate somewhat the gain for onset when the correlation with previous frame is too low: avoid preecho */ + tmp = mult_r(shl(st->rf_gain_tcx[1], 1), 26214/*0.8f Q15*/); + + test(); + test(); + IF( (st->rf_gain_tcx[1] != 0) && (GT_16(st->rf_gain_tcx[0], tmp))&&(LE_16(st->tcxltp_gain,6554/*0.2 Q15*/))) + { + st->rf_gain_tcx[0] = tmp; + move16(); + + if( GT_16(tmp, 127)) + { + st->rf_gain_tcx[0] = 127; + move16(); + } + } + + /* get concealment decision*/ + rf_PLC_Mode = 0; + move16(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( + (EQ_16(st->core_fx, TCX_20_CORE) )/*(st->core == TCX_20_CORE)*/ + && (EQ_16(st->last_core_fx,TCX_20_CORE) )/*&&(st->last_core == TCX_20_CORE)*/ + && (EQ_16(st->rf_second_last_core, TCX_20_CORE) )/*&& (st->rf_second_last_core == TCX_20_CORE)*/ + && ( (LE_16(st->tcxltp_pitch_int, shr(st->L_frame_fx, 1)) ) || ( LE_16(st->tcxltp_gain, 13107/*0.4f Q15*/) ) )/*&& ((st->tcxltp_pitch_int <= 0.5f*st->L_frame) || ( st->tcxltp_gain <= 0.4f))*/ + && (EQ_16(st->tcxltp_pitch_int, st->rf_tcxltp_pitch_int_past) )/*&& (st->tcxltp_pitch_int == st->rf_tcxltp_pitch_int_past)*/ + && (st->rf_last_tns_active == 0)/*!st->rf_last_tns_active*/ + && (st->rf_second_last_tns_active == 0)/*!st->rf_second_last_tns_active*/ + && ( (st->tcx_cfg.fIsTNSAllowed & st->fUseTns[0]) == 0)/*!(st->tcx_cfg.fIsTNSAllowed & st->fUseTns[0])*/ + ) + { + rf_PLC_Mode = 1; + move16(); + } + ELSE IF (st->last_core_fx != 0) + { + test(); + test(); + test(); + IF ( ((LE_16(st->clas_fx, UNVOICED_TRANSITION))||(LE_16(st->last_clas_fx,UNVOICED_TRANSITION))||(LE_16(st->tcxltp_gain,13107/*0.4f Q15*/))) + && NE_16(st->last_core_fx, -1) ) + { + rf_PLC_Mode = st->last_core_fx; + move16(); + } + } + + /* call TD1 when the gain drop compare to previous frame*/ + test(); + test(); + test(); + test(); + IF( rf_PLC_Mode == 0 && st->rf_gain_tcx[1] != 0 && + ( (st->transientDetection.transientDetector.bIsAttackPresent != 0 && LT_16(st->rf_gain_tcx[0], mult_r(st->rf_gain_tcx[1], 31785/*0.97f Q15*/)) ) || + LT_16(st->rf_gain_tcx[0], mult_r(st->rf_gain_tcx[1], 29491/*0.90f Q15*/)) ) + ) + { + TD_mode = 0; + } + ELSE + { + TD_mode = 1; + } + + /* updates */ + st->rf_tcxltp_pitch_int_past = st->tcxltp_pitch_int; + move16(); + st->rf_second_last_tns_active = st->rf_last_tns_active; + move16(); + st->rf_last_tns_active = (st->tcx_cfg.fIsTNSAllowed & st->fUseTns[0]); + move16(); + st->rf_second_last_core = st->last_core_fx; + move16(); + + st->rf_tcxltp_param[0] = st->tcxltp_param[1]; + move16(); + + /* Configure partial copy estimation of the current n-th frame to be packed in future with n+fec_offset frame */ + /* o: rf_frame_type, o: rf_target_bits */ + BITS_ALLOC_TCX_config_rf( &st->rf_frame_type, &st->rf_target_bits, rf_PLC_Mode, coder_type, st->last_core_fx, TD_mode); + + /* RF frame type in the buffer */ + st->rf_indx_frametype[0] = st->rf_frame_type; + move16(); + st->rf_targetbits_buff[0] = st->rf_target_bits; + move16(); + + } + } + + + + return; +} + + +/*-------------------------------------------------------------------* +* closest_centroid_rf() +* +* Determine a set of closest VQ centroids for a given input +*-------------------------------------------------------------------*/ +void closest_centroid_rf( + const Word16 *data, /* i : input data Qx */ + const Word16 *weights, /* i : weights */ + const Word16 *quantizer, /* i : quantizer table Qx */ + const Word16 centroids, /* i : number of centroids */ + const Word16 length, /* i : dimension of quantiser */ + Word16 *ind_vec /* o : list of best match indice vectors */ +) +{ + Word16 i,j; + Word16 tmp, tmpL; + Word64 werr_64; + Word32 L_tmp, best_werr, werr; + + + ind_vec[0] = 0; + move16(); + best_werr = MAX_32; + move32(); + + FOR( i = 0; i < centroids; i++ ) + { + werr_64 = 0; + move64(); + + tmpL = i_mult2(i, length); + FOR( j = 0; j < length; j++ ) + { + tmp = sub( data[j], quantizer[tmpL + j] ); + L_tmp = L_mult( tmp, tmp ); + werr_64 = W_mac_32_16( werr_64, L_tmp, weights[j] ); + } + werr = W_sat_m( werr_64); + if( LT_32( werr, best_werr) ) + { + ind_vec[0] = i; + move16(); + } + best_werr = L_min( best_werr, werr ); + } + + return; +} + + +void core_acelp_tcx20_switching( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 vad_flag, + Word16 sp_aud_decision0, + Word16 non_staX, + Word16 *pitch, /* i : open-loop pitch values for quantiz. */ + Word16 *pitch_fr, /* i/o: fraction pitch values */ + Word16 *voicing_fr, /* i/o: fractional voicing values */ + const Word16 currFlatness, /* i : flatness */ + const Word16 lsp_mid[M], /* i : LSPs at the middle of the frame */ + const Word16 stab_fac, /* i : LP filter stability */ + Word16 Q_new, + Word16 shift +) +{ + Word16 i, j, iter; + Word16 xn_buf[L_MDCT_OVLP_MAX+L_FRAME_PLUS+L_MDCT_OVLP_MAX]; + Word16 Ap[M+1]; + Word16 gainlpc[FDNS_NPTS]; + Word16 gainlpc_e[FDNS_NPTS]; + Word32 en[N_MAX/4]; + Word32 ener, tmp32, fac, offset; + Word32 offset_tcx; + Word16 ener_e; + Word16 L_frame; + Word16 overlap; + Word16 x_e; + Word16 tcx_offset; + Word32 spectrum_long[N_MAX]; + Word32 *x = spectrum_long; + Word32 target; + Word32 tcx_snr; + Word16 tmp16, s; + Word16 L_frame_4; + Word16 i2, T0; + Word32 gain, signal, noise; + Word16 A_q_tcx[(NB_SUBFR16k+1)*(M+1)]; + Word16 snr_tcx, snr_acelp, dsnr; + + /* Check minimum pitch for quantization */ + FOR( i = 0; i < 3; i++ ) + { + tmp16 = pitch[i]; + move16(); + /* check minimum pitch for quantization */ + if (LT_16(tmp16, PIT_MIN_SHORTER)) + { + tmp16 = shl(tmp16, 1); + } + + /* convert pitch values to 16kHz domain */ + s = mult_r(tmp16, 8192/*0.25f Q15*/); + if (EQ_16(st->L_frame_fx, L_FRAME16k)) + { + /*pitch[i] = (short)(pitch[i] * 1.25f + 0.5f);*/ + tmp16 = add(tmp16, s); + } + pitch[i] = tmp16; + move16(); + } + IF (st->narrowBand != 0) + { + pitchDoubling_det( st->wspeech_enc, pitch, pitch_fr, voicing_fr ); + } + + E_LPC_f_lsp_a_conversion(lsp_mid, A_q_tcx, M); + + + /* LTP */ + + tcx_ltp_encode( st->tcxltp, + st->tcxonly, + TCX_20, + st->L_frame_fx, + L_SUBFR, + st->speech_enc + st->encoderLookahead_enc, + st->speech_ltp + st->encoderLookahead_enc, + st->wspeech_enc + st->encoderLookahead_enc, + pitch[1], + st->tcxltp_param, + &st->tcxltp_bits, + &st->tcxltp_pitch_int, + &st->tcxltp_pitch_fr, + &st->tcxltp_gain, + &st->tcxltp_pitch_int_past, + &st->tcxltp_pitch_fr_past, + &st->tcxltp_gain_past, + &st->tcxltp_norm_corr_past, + st->last_core_fx, + st->pit_min, + st->pit_fr1, + st->pit_fr2, + st->pit_max, + st->pit_res_max, + &st->transientDetection, + 0, + A_q_tcx, + M + ); + + /* Force TCX when TCX20 in MODE1 is selected */ + IF ( EQ_16(st->mdct_sw, MODE1)) + { + st->core_fx = TCX_20_CORE; + move16(); + } + ELSE + { + /*--------------------------------------------------------------* + * Estimate TCX SNR + *---------------------------------------------------------------*/ + + L_frame = st->L_frame_fx; + move16(); + tcx_offset = st->tcx_cfg.tcx_offset; + move16(); + + target = L_add(0x14C315C, 0); /* 1000.f * log2(10)/10 (15Q16) */ + test(); + if (EQ_32(st->sr_core, 16000)||EQ_32(st->sr_core,12800)) + { + target = L_add(0x11A5D28, 0); /* 850.f * log2(10)/10 (15Q16) */ + } + if ( st->narrowBand != 0 ) + { + target = L_add(0xA618AE, 0); /* 500f * log2(10)/10 (15Q16) */ + } + + IF (st->last_core_fx == ACELP_CORE) + { + L_frame = add(L_frame, tcx_offset); + tcx_offset = s_min(st->tcx_cfg.lfacNext, 0); + L_frame = sub(L_frame, tcx_offset); + } + L_frame_4 = shr(L_frame, 2); + overlap = st->tcx_cfg.tcx_mdct_window_delay; + move16(); + Copy(st->speech_ltp + sub(tcx_offset, shr(overlap, 1)), xn_buf, add(L_frame, overlap)); + + tmp16 = shr(overlap, 1); + IF (EQ_16(st->last_core_fx,ACELP_CORE)) + { + IF (tcx_offset < 0) + { + set16_fx(xn_buf, 0, tmp16); + } + } + ELSE + { + FOR (i = 0; i < tmp16; i++) + { + xn_buf[i] = mult_r(xn_buf[i], st->tcx_cfg.tcx_mdct_window[i].v.im); + move16(); + } + FOR ( ; i < overlap; i++) + { + xn_buf[i] = mult_r(xn_buf[i], st->tcx_cfg.tcx_mdct_window[overlap-1-i].v.re); + move16(); + } + } + + FOR (i = 0; i < tmp16; i++) + { + xn_buf[L_frame+i] = mult_r(xn_buf[L_frame+i], st->tcx_cfg.tcx_mdct_window[i].v.re); + move16(); + } + FOR ( ; i < overlap; i++) + { + xn_buf[L_frame+i] = mult_r(xn_buf[L_frame+i], st->tcx_cfg.tcx_mdct_window[overlap-1-i].v.im); + move16(); + } + + x_e = 16; + move16(); + TCX_MDCT(xn_buf, x, &x_e, overlap, sub(L_frame, overlap), overlap); + tmp16 = mult_r(shl(L_frame, 5), 29309/*16*0.0559017 Q15*/); /* L_frame / sqrt(2*NORM_MDCT_FACTOR); Q9 */ + FOR (i = 0; i < L_frame; i++) + { + x[i] = Mpy_32_16_1(x[i], tmp16); + move32(); + } + x_e = add(x_e, 6); + + weight_a_fx(A_q_tcx, Ap, st->gamma, M); + + lpc2mdct(Ap, M, gainlpc, gainlpc_e, NULL, NULL); + + mdct_shaping(x, L_frame, gainlpc, gainlpc_e); + + IF ( st->narrowBand ) + { + j = mult( L_frame, 20480 ); + set32_fx(&x[j], 0, sub(L_frame, j)); + } + + FOR (i = 0; i < L_frame_4; i++) + { + /* normalization */ + s = 31; + move16(); + + tmp16 = norm_l(x[0]); + if (x[0] != 0) s = s_min(s, tmp16); + + tmp16 = norm_l(x[1]); + if (x[1] != 0) s = s_min(s, tmp16); + + tmp16 = norm_l(x[2]); + if (x[2] != 0) s = s_min(s, tmp16); + + tmp16 = norm_l(x[3]); + if (x[3] != 0) s = s_min(s, tmp16); + + s = sub(s, 2); /* 2 bits headroom */ + + /* calc quadruple energy */ + ener = L_deposit_l(1); + + tmp16 = extract_h(L_shl(x[0], s)); + ener = L_mac(ener, tmp16, tmp16); + + tmp16 = extract_h(L_shl(x[1], s)); + ener = L_mac(ener, tmp16, tmp16); + + tmp16 = extract_h(L_shl(x[2], s)); + ener = L_mac(ener, tmp16, tmp16); + + tmp16 = extract_h(L_shl(x[3], s)); + ener = L_mac(ener, tmp16, tmp16); + + s = shl(sub(x_e, s), 1); + + tmp32 = L_add(BASOP_Util_Log2(ener), L_shl(L_deposit_l(s), 25)); /* log2, 6Q25 */ + tmp32 = L_shr(tmp32, 9); /* 15Q16 */ + en[i] = L_add(tmp32, 0x2FD5F); /* 0x2FD5F -> 9.f * log2(10)/10 (15Q16) */ move32(); + + x += 4; + } + + fac = L_add(0x2A854B, 0); /* 0x2A854B -> 128.f * log2(10)/10 (15Q16) */ + offset = L_add(fac, 0); + + FOR (iter = 0; iter < 10; iter++) + { + fac = L_shr(fac, 1); + offset = L_sub(offset, fac); + ener = L_deposit_l(0); + + assert(L_frame_4 % 4 == 0); + FOR (i=0; i < L_frame_4; i+=4) + { + tmp32 = L_sub(en[i], offset); + + if (GT_32(tmp32, 0xFF20)) /* 0xFF20 -> 3.f * log2(10)/10 */ + { + ener = L_add(ener, tmp32); + } + + tmp32 = L_sub(en[i+1], offset); + + if (GT_32(tmp32, 0xFF20)) /* 0xFF20 -> 3.f * log2(10)/10 */ + { + ener = L_add(ener, tmp32); + } + + tmp32 = L_sub(en[i+2], offset); + + if (GT_32(tmp32, 0xFF20)) /* 0xFF20 -> 3.f * log2(10)/10 */ + { + ener = L_add(ener, tmp32); + } + + tmp32 = L_sub(en[i+3], offset); + + if (GT_32(tmp32, 0xFF20)) /* 0xFF20 -> 3.f * log2(10)/10 */ + { + ener = L_add(ener, tmp32); + } + + IF (GT_32(ener, target)) + { + offset = L_add(offset, fac); + BREAK; + } + } + } + + if (LE_32(offset, 0xAA153)) /* 0xAA153 -> 32.f * log2(10)/10 */ + { + offset = L_add(0xFFD57AB5, 0); /* 0xFFD57AB5 -> -128.f * log2(10)/10; */ + } + offset_tcx = offset; + move32(); + + s = add(extract_h(offset), 1); + offset = L_sub(L_and(offset, 0xFFFF), 0x10000); + ener = BASOP_Util_InvLog2(L_shl(offset, 9)); + + ener = Mpy_32_16_1(Mpy_32_16_1(ener, 0x78AE), getInvFrameLen(L_frame)); /* 0x78AE -> sqrt(2)/12 (Q18) */ + ener_e = sub(s, 9); + + tcx_snr = L_deposit_l(0); + + FOR (i = 0; i < st->L_frame_fx; i += L_SUBFR) + { + tmp32 = L_deposit_l(0); + + FOR (j = 0; j < L_SUBFR; j++) + { + tmp32 = L_mac0(tmp32, st->wspeech_enc[i+j], st->wspeech_enc[i+j]); + } + tmp32 = L_shr(BASOP_Util_Log2(tmp32), 9); /* 15Q16 */ + tmp32 = L_add(tmp32, L_sub( 0x1F0000, L_shl( L_deposit_h( add( Q_new, sub( shift, 1 ) ) ), 1 ) ) ); /* wspeech_enc scaling */ + if (LT_32(tmp32, (Word32)0xFFEC1185)) + { + tmp32 = 0xFFEC1185; /* 0xFFEC1185 -> log2(1e-6) in 15Q16 */ + move32(); + } + + tcx_snr = L_add(tcx_snr, tmp32); + } + tcx_snr = Mpy_32_16_1(tcx_snr, div_s(L_SUBFR, st->L_frame_fx)); + tcx_snr = L_sub(tcx_snr, L_shr(BASOP_Util_Log2(Mpy_32_16_1(ener, L_SUBFR)), 9)); + tcx_snr = L_sub(tcx_snr, L_deposit_h(add(ener_e, 15))); + tcx_snr = L_shl(Mpy_32_16_1(tcx_snr, 0x6054), 2); /* 0x6054 -> 10/log2(10) (2Q13) */ + + BASOP_SATURATE_WARNING_OFF + snr_tcx = round_fx(L_shl(tcx_snr, 8)); /* 7Q8 */ + BASOP_SATURATE_WARNING_ON + + /*--------------------------------------------------------------* + * Estimate ACELP SNR + *---------------------------------------------------------------*/ + + tmp32 = L_deposit_l(0); + + /* + snr_acelp = 1/nSubFrames + sum( 10*log10( signal / (noise*0.055) ) + snr_acelp = sum( (log2(signal) - log2(noise)) * 10/log2(10) )/nSubFrames - 10*log10(0.055) + */ + + i2 = 0; + move16(); + FOR (i = 0; i < st->L_frame_fx; i += L_SUBFR) + { + IF ( EQ_32( st->sr_core, 16000 )) + { + T0 = shr(add( add(pitch_fr[mult_r(i2,26214/*(float)L_FRAME/(float)L_FRAME16k Q15*/)], shr(pitch_fr[mult_r(i2,26214/*(float)L_FRAME/(float)L_FRAME16k Q15*/)], 2)) , (1 << 5) ), 6); + } + ELSE + { + T0 = shr(add( pitch_fr[i2] , (1 << 5) ), 6); + } + + gain = get_gain( st->wspeech_enc + i, st->wspeech_enc + sub(i, T0), L_SUBFR ); + + signal = L_deposit_l(1); + noise = L_deposit_l(1); + + FOR (j = 0; j < L_SUBFR; j++) + { + signal = L_mac0(signal, st->wspeech_enc[i+j], st->wspeech_enc[i+j]); + + tmp16 = round_fx(L_shl(Mpy_32_16_r(gain, st->wspeech_enc[i+j-T0]), 15)); + tmp16 = sub(st->wspeech_enc[i+j], tmp16); + noise = L_mac0(noise, tmp16, tmp16); + } + /* Assume always 4 sub frames. */ + /*assert( (st->L_frame_fx / L_SUBFR) == 4);*/ + tmp32 = L_add(tmp32, Mpy_32_16_1(L_sub(BASOP_Util_Log2(signal), BASOP_Util_Log2(noise)), 12330/*3.0102999566398119521373889472449 Q12*/)); + i2 = add(i2, 1); + } + + if(EQ_16(st->L_frame_fx,L_FRAME16k)) + { + tmp32 = Mpy_32_16_1(tmp32,26214/*(float)L_FRAME/(float)L_FRAME16k Q15*/); + } + + offset = -211332072l/*-12.5963731051575616 Q24*/; /* 10*log10(0.055f) */ + move32(); + if (EQ_32(st->sr_core, 16000)) + { + offset = -173847554l/*-10.362121726544446 Q24*/; /* 10*log10(0.092f) */ + move32(); + } + if (EQ_32(st->sr_core, 12800)) + { + offset = -206216813l/*-12.291479883578557 Q24*/; /* 10*log10(0.059f) */ + move32(); + } + if (st->narrowBand != 0) + { + offset = -138228949l/*-8.2390874094431865 Q24*/; /* 10*log10(0.15f) */ + move32(); + } + + tmp32 = L_sub(tmp32, offset); + + snr_acelp = round_fx(tmp32); /* 7Q8 */ + + /*--------------------------------------------------------------* + * Switching Decision + *---------------------------------------------------------------*/ + + dsnr = 0; + move16(); + /* hysteresis for very small SNR differences between ACELP and TCX */ + + /* try to use TCX instead of ACELP on temporally stationary frames */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + if ((GT_16(snr_acelp, snr_tcx))&& + (LT_16(snr_acelp, add(snr_tcx, 512/*2.0f Q8*/)) ) && + (LT_16(add(st->prevTempFlatness_fx, currFlatness), 416/*3.25f Q7*/) || EQ_16(stab_fac, 0x7fff) || (EQ_32(st->sr_core, 12800) && EQ_16(sp_aud_decision0,1) && LT_16(add(st->prevTempFlatness_fx, currFlatness), 2560/*20.f Q7*/) )) && + (LE_16(st->acelpFramesCount, 6) )) + { + dsnr = -512/*-2.0f Q8*/; + move16(); + } + + /* try to use ACELP instead of TCX on transient and "buzzy" frames */ + test(); + test(); + test(); + if ((LT_16(snr_acelp, snr_tcx))&& + (GT_16(snr_acelp, sub(snr_tcx, 512/*2.0f Q8*/)) ) && + (GT_16(add(st->prevTempFlatness_fx, currFlatness), 416/*3.25f Q7*/) ) && + (GE_16(st->acelpFramesCount, 6) )) + { + dsnr = 512/*2.0f Q8*/; + move16(); + } + + tmp16 = 0; + move16(); + FOR(i = 0; i < 4; i++) + { + tmp16 = add(tmp16, shr(voicing_fr[i],2)); /*mean of voicing_fr in Q15*/ + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + if( EQ_32(st->sr_core, 12800)&&(offset_tcx<0x18950F)&>_16(non_staX,1280 /*5.0f Q8*/ )&&(snr_acelp>=snr_tcx-1024 /*4.0f in Q8*/)&&GE_16(st->acelpFramesCount,1)&&((GT_16(st->lps_fx,st->lpm_fx)&&GE_16(tmp16,9830))||(GE_16(st->acelpFramesCount,6)&&(st->lps_fx>st->lpm_fx-768)))&&(sp_aud_decision0==0)&&vad_flag!=0) + { + /* Fine tuned across various databases based on various metrics to detect TCX frames in speech.*/ + dsnr = 1024; + move16(); + } + + IF ( st->flag_noisy_speech_snr ) + { + test(); + IF ( vad_flag || st->Opt_DTX_ON_fx ) + { + dsnr = add(dsnr, 512/*2.0f Q8*/); + } + ELSE + { + dsnr = sub(dsnr, 512/*2.0f Q8*/); + } + } + + test(); + test(); + test(); + test(); + test(); + test(); + if (EQ_32(st->sr_core, 12800)&&(LT_16(non_staX,512/*2.0f Q8*/)||(st->flag_noisy_speech_snr==0&&EQ_16(vad_flag,1)&&(offset_tcx==L_add(0xFFD57AB5,0))&&GE_16(st->acelpFramesCount,6)))&&(st->last_core_fx==ACELP_CORE||st->last_core_fx==TCX_20_CORE)) + { + st->core_fx = st->last_core_fx; + } + ELSE IF ( GT_16(add(snr_acelp, dsnr), snr_tcx)) + { + st->core_fx = ACELP_CORE; + move16(); + st->acelpFramesCount = s_min(32767-1, add(st->acelpFramesCount, 1)); + } + ELSE + { + st->core_fx = TCX_20_CORE; + move16(); + st->acelpFramesCount = 0; + move16(); + } + + } + + /* Fixed Decision (using -C) */ + test(); + if ( st->acelpEnabled != 0 && st->tcx20Enabled == 0 ) + { + st->core_fx = ACELP_CORE; + move16(); + } + + test(); + if ( st->acelpEnabled == 0 && st->tcx20Enabled != 0 ) + { + st->core_fx = TCX_20_CORE; + move16(); + } + + st->prevTempFlatness_fx = currFlatness; + move16(); +} + + + + +/*-------------------------------------------------------------------* + * BITS_ALLOC_ACELP_config_rf() + * + * configure channel aware mode + *-------------------------------------------------------------------*/ +void BITS_ALLOC_ACELP_config_rf(const Word16 coder_type, + Word16 *tilt_code, + Word16 *rf_frame_type, + Word16 *rf_target_bits, + Word16 nb_subfr + , Word16 rf_fec_indicator + , Word16 *pitch_buf + ) +{ + Word16 mean_tc, min_tilt_code, max_tilt_code; + Word16 nrgMode, ltfMode, ltpMode, gainsMode; + Word32 L_tmp; + + Word16 en_partial_red = 1; + Word16 dpit1, dpit2, dpit3; + + /* Init */ + *rf_target_bits = 0; + move16(); + + /* ----------------------------------------* + * RF frame type selection * + *-----------------------------------------*/ + /* Mean tilt code estimation */ + mean_tc = 0; + move16(); + /*mean_tc = mean_fx(tilt_code, nb_subfr);*/ + IF( EQ_16(nb_subfr, 4)) + { + /* subframe 4 case */ + L_tmp = L_mult(tilt_code[0], 8192); + L_tmp = L_mac(L_tmp, tilt_code[1], 8192 ); + L_tmp = L_mac(L_tmp, tilt_code[2], 8192 ); + mean_tc = mac_r(L_tmp, tilt_code[3], 8192 ); /* mean_tc in Q15 */ + } + ELSE + { + /* subframe 5 case */ + L_tmp = L_mult(tilt_code[0], 6554); + L_tmp = L_mac(L_tmp, tilt_code[1], 6554 ); + L_tmp = L_mac(L_tmp, tilt_code[2], 6554 ); + L_tmp = L_mac(L_tmp, tilt_code[3], 6554 ); + mean_tc = mac_r(L_tmp, tilt_code[4], 6554 ); /* mean_tc in Q15 */ + } + + /* Maximum tilt code estimation */ + max_tilt_code = tilt_code[0]; + move16(); + maximum_fx(tilt_code, nb_subfr, &max_tilt_code); + + /* Minimum tilt code estimation */ + min_tilt_code=tilt_code[0]; + move16(); + minimum_fx(tilt_code, nb_subfr, &min_tilt_code); + + /* Estimate the frame's criticality and decide + whether to transmit partial redundancy information */ + dpit1 = abs_s( sub(pitch_buf[1], pitch_buf[0])); + dpit2 = abs_s( sub(pitch_buf[2], pitch_buf[1])); + dpit3 = abs_s( sub(pitch_buf[3], pitch_buf[2])); + + IF ( EQ_16( rf_fec_indicator, 1 )) + { + test(); + test(); + test(); + test(); + IF ( GT_16( max_tilt_code, 15729/*0.48f Q15*/ )&&LE_16(dpit1,0)&&LE_16(dpit2,0)&&LE_16(dpit3,0)&&EQ_16(coder_type,VOICED)) + { + en_partial_red = 0; + move16(); + } + ELSE IF ( GT_16( max_tilt_code, 15401/*0.47f Q15*/ )&&LE_16(dpit1,64)&&LE_16(dpit2,64)&&LE_16(dpit3,64)&&EQ_16(coder_type,GENERIC)) + { + en_partial_red = 0; + move16(); + } + } + ELSE + { + test(); + test(); + test(); + test(); + IF ( GT_16( max_tilt_code, 15401/*0.47f Q15*/ )&&LE_16(dpit1,16)&&LE_16(dpit2,16)&&LE_16(dpit3,16)&&EQ_16(coder_type,VOICED)) + { + en_partial_red = 0; + move16(); + } + ELSE IF ( GT_16( max_tilt_code, 14746/*0.45f Q15*/ )&&LE_16(dpit1,80)&&LE_16(dpit2,80)&&LE_16(dpit3,80)&&EQ_16(coder_type,GENERIC)) + { + en_partial_red = 0; + move16(); + } + } + + /* ---------------------------------------------------------* + * Identify number of bits required as per rf frame type * + * ---------------------------------------------------------*/ + + /* rf_mode, 1 bit */ + *rf_target_bits = add(*rf_target_bits,1); + + /* rf_fec_offset 2 bits */ + *rf_target_bits = add(*rf_target_bits,2); + + /* rf_frame_type, 3 bits */ + *rf_target_bits = add(*rf_target_bits,3); + + /* LSF bits 8 + 8 bits */ + *rf_target_bits = add(*rf_target_bits,16); + + /* Intialize the RF mode frame type to all-pred */ + *rf_frame_type = RF_ALLPRED; + + test(); + IF( EQ_16(coder_type,INACTIVE)||en_partial_red==0) + { + *rf_frame_type = RF_NO_DATA; + } + ELSE IF ( EQ_16(coder_type,UNVOICED)||EQ_16(coder_type,INACTIVE)) + { + *rf_frame_type = RF_NELP; + } + ELSE IF( EQ_16(coder_type,GENERIC)&<_16(max_tilt_code,1638/*0.05f Q15*/)) + { + *rf_frame_type = RF_NOPRED; + } + ELSE IF( EQ_16(coder_type,GENERIC)&<_16(mean_tc,9830/*0.3f Q15*/)) + { + *rf_frame_type = RF_GENPRED; + } + + nrgMode = ACELP_NRG_MODE[1][1][*rf_frame_type]; + ltfMode = ACELP_LTF_MODE[1][1][*rf_frame_type]; + ltpMode = ACELP_LTP_MODE[1][1][*rf_frame_type]; + gainsMode = ACELP_GAINS_MODE[1][1][*rf_frame_type]; + + /* Number of RF bits for different RF coder types */ + SWITCH (*rf_frame_type) + { + case RF_ALLPRED: + /* Es_pred bits 3 bits, LTF: 1, pitch: 8,5,5,5, FCB: 0, gain: 7,0,7,0, Diff GFr: 4*/ + *rf_target_bits += ( ACELP_NRG_BITS[nrgMode] + + ACELP_LTF_BITS[ltfMode] + + ACELP_LTP_BITS_SFR[ltpMode][0] + ACELP_LTP_BITS_SFR[ltpMode][1] + ACELP_LTP_BITS_SFR[ltpMode][2] + ACELP_LTP_BITS_SFR[ltpMode][3] + + ACELP_GAINS_BITS[gainsMode] + ACELP_GAINS_BITS[gainsMode] + + 2 /*2 bits for PartialCopy GainFrame*/ + ); + BREAK; + + case RF_NOPRED: + /* Es_pred bits 3 bits, LTF: 0, pitch: 0, FCB: 7,7,7,7, gain: 6,0,6,0, Diff GFr: 2*/ + /*bits += (3 + 0 + 0 + 28 + 12 + 2); *//* 64 rf bits */ + *rf_target_bits += ( ACELP_NRG_BITS[nrgMode] + + ACELP_LTF_BITS[ltfMode] + + 28 + + ACELP_GAINS_BITS[gainsMode] + ACELP_GAINS_BITS[gainsMode] + + 2 /*2 bits for PartialCopy GainFrame*/ + ); + BREAK; + + case RF_GENPRED: + /* Es_pred bits 3 bits, LTF: 0, pitch: 8,0,8,0, FCB: 6,7,5,5, gain: 5,0,5,0, Diff GFr: 0*/ + /*bits += (3 + 0 + 16 + 23 + 10 + 0); */ /* 72 rf bits */ + *rf_target_bits += ( ACELP_NRG_BITS[nrgMode] + + ACELP_LTF_BITS[ltfMode] + + ACELP_LTP_BITS_SFR[ltpMode][0] + ACELP_LTP_BITS_SFR[ltpMode][1] + ACELP_LTP_BITS_SFR[ltpMode][2] + ACELP_LTP_BITS_SFR[ltpMode][3] + + 14 + + ACELP_GAINS_BITS[gainsMode] + ACELP_GAINS_BITS[gainsMode] + + 2 /*2 bits for PartialCopy GainFrame*/ + ); + BREAK; + + case RF_NELP: + /* gain: 19, Diff GFr: 5 */ + /*bits += (19 + 5); */ + *rf_target_bits += (19 + NUM_BITS_SHB_FRAMEGAIN); + BREAK; + + case RF_NO_DATA: + *rf_target_bits = 6; + BREAK; + + default: + assert(!"RF_Frame_type does not belong to ACELP Partial copy frame types possible!"); + break; + } + + return; + +} + +/*-------------------------------------------------------------------* + * BITS_ALLOC_TCX_config_rf() + * + * configure channel aware mode + *-------------------------------------------------------------------*/ +void BITS_ALLOC_TCX_config_rf( + Word16 *rf_frame_type, + Word16 *rf_target_bits, + Word16 PLC_Mode, + Word16 coder_type, + Word16 last_core, + Word16 TD_mode +) +{ + Word16 bits; + + /* Init: rf_mode + rf_fec_offset + rf_frame_type */ + bits = 1 + 2 + 3; + move16(); + + test(); + IF( EQ_16(coder_type, INACTIVE)||EQ_16(last_core,ACELP_CORE)) + { + *rf_frame_type = RF_NO_DATA; + move16(); + } + ELSE + { + /* classification */ + bits = add(bits, 2); + + IF( PLC_Mode != 0 ) + { + /* TCX global gain = 7 bits */ + bits = add(bits, 7); + *rf_frame_type = RF_TCXFD; + move16(); + } + ELSE + { + /* pitch and gain */ + /* LTP data */ + IF( TD_mode != 0) + { + bits = add(bits, 9); + *rf_frame_type = RF_TCXTD2; + move16(); + } + ELSE + { + bits = add(bits, 9); + *rf_frame_type = RF_TCXTD1; + move16(); + } + } + + if( EQ_16(*rf_frame_type, RF_TCXFD)) + { + /* TCXFD: LSF bits 5 + 4 + 4 bits */ + /* only embed LSF for FD concealment */ + bits = add(bits, TCXLPC_NUMBITS); + } + } + + *rf_target_bits = bits; + move16(); + + return; +} + + + + + + diff --git a/lib_enc/core_enc_reconf.c b/lib_enc/core_enc_reconf.c new file mode 100644 index 0000000..f616d3d --- /dev/null +++ b/lib_enc/core_enc_reconf.c @@ -0,0 +1,277 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "prot_fx.h" +#include "options.h" +#include "cnst_fx.h" +#include "stl.h" +#include "rom_com_fx.h" +#include "rom_enc_fx.h" + +/*-----------------------------------------------------------------* + * Funtion core_coder_reconfig * + * ~~~~~~~~~~~~~~~~~~~ * + * - reconfig core coder when switching to another frame type * + *-----------------------------------------------------------------*/ +void core_coder_reconfig(Encoder_State_fx *st) +{ + Word16 i; + + + + /*Configuration of ACELP*/ + BITS_ALLOC_init_config_acelp(st->total_brate_fx, st->narrowBand, st->nb_subfr, &(st->acelp_cfg)); + + /*Configuration of partial copy*/ + st->acelp_cfg_rf.mode_index = 1; + st->acelp_cfg_rf.midLpc = 0; + st->acelp_cfg_rf.midLpc_enable = 0; + st->acelp_cfg_rf.pre_emphasis = 0; + st->acelp_cfg_rf.formant_enh = 1; + st->acelp_cfg_rf.formant_tilt = 1; + st->acelp_cfg_rf.voice_tilt = 1; + st->acelp_cfg_rf.formant_enh_num = FORMANT_SHARPENING_G1; + st->acelp_cfg_rf.formant_enh_den = FORMANT_SHARPENING_G2; + + st->nb_bits_header_tcx = 2; /*Mode(1) + Last_mode(1)*/ move16(); + IF (st->tcxonly == 0) + { + move16(); + st->nb_bits_header_ace = 4; + st->nb_bits_header_tcx = st->nb_bits_header_ace; + move16(); + if ( st->tcx_cfg.lfacNext<=0 ) + { + /*st->nb_bits_header_ace--;*/ /*No Last_mode*/ + st->nb_bits_header_ace = sub(st->nb_bits_header_ace,1); + } + } + + if ( st->tcxonly) + { + st->nb_bits_header_tcx = add(st->nb_bits_header_tcx,2); + } + + + /*Switch off TCX or ACELP?*/ + IF( EQ_32(st->sr_core,12800)) + { + st->acelpEnabled = 0; + move16(); + + if( s_and(st->restrictedMode,1) != 0) + { + st->acelpEnabled = 1; + move16(); + } + + st->tcx20Enabled = 0; + move16(); + if( s_and(st->restrictedMode,2) != 0) + { + + st->tcx20Enabled = 1; + move16(); + } + } + move32(); + move32(); + move16(); + st->prevEnergyHF_fx = st->currEnergyHF_fx = 1073725440l/*65535.0f Q14*/; /* prevent block switch */ + st->currEnergyHF_e_fx = 17; + + /*Sanity check : don't need to be instrumented*/ + if(st->tcxonly==0) + { + assert(st->acelpEnabled || st->tcx20Enabled || st->frame_size_index==0); + } + else + { + assert(st->tcx10Enabled || st->tcx20Enabled || st->frame_size_index==0); + } + + /* TCX-LTP */ + st->tcxltp = getTcxLtp(st->sr_core); + + /*Use for 12.8 kHz sampling rate and low bitrates, the conventional pulse search->better SNR*/ + + st->acelp_autocorr = 1; + move16(); + + test(); + if( (LE_32(st->total_brate_fx, 9600))&&(EQ_32(st->sr_core,12800))) + { + st->acelp_autocorr = 0; + move16(); + } + + { + Word16 bandwidth_mode; + + /*Get bandwidth mode*/ + IF(st->narrowBand) + { + bandwidth_mode=0; + } + ELSE IF( LE_32(st->sr_core, 16000)) + { + move16(); + bandwidth_mode=1; + } + ELSE + { + move16(); + bandwidth_mode=2; + } + + /*Scale TCX for non-active frames to adjust loudness with ACELP*/ + st->tcx_cfg.na_scale=32767/*1.0f Q15*/; + + test(); + IF( LT_16(bandwidth_mode,2)&&(st->tcxonly==0)) + { + const Word16 scaleTableSize = sizeof (scaleTcxTable) / sizeof (scaleTcxTable[0]); + + FOR (i = 0 ; i < scaleTableSize ; i++) + { + + test(); + test(); + IF ( EQ_16(bandwidth_mode, scaleTcxTable[i].bwmode)&& + GE_32(st->total_brate_fx, scaleTcxTable[i].bitrateFrom) && + LT_32(st->total_brate_fx, scaleTcxTable[i].bitrateTo) ) + { + if( st->rf_mode ) + { + i--; + } + move16(); + st->tcx_cfg.na_scale = scaleTcxTable[i].scale; + BREAK; + } + } + } + } + + st->enableTcxLpc = 0; + move16(); + + test(); + if ( EQ_16(st->lpcQuantization, 1)&&(LE_32(st->total_brate_fx,LOWRATE_TCXLPC_MAX_BR)||st->rf_mode!=0)) + { + st->enableTcxLpc = 1; + move16(); + } + + IF ( st->ini_frame_fx == 0 || EQ_16(st->last_codec_mode, MODE1)) + { + st->envWeighted = 0; + move16(); + } + + test(); + test(); + IF( EQ_16(st->bwidth_fx, SWB)&& + (EQ_32(st->total_brate_fx, ACELP_16k40) || EQ_32(st->total_brate_fx, ACELP_24k40)) ) + { + IF(st->tec_tfa == 0) + { + FOR (i = 0; i < MAX_TEC_SMOOTHING_DEG; i++) + { + st->tecEnc.loBuffer[i] = 0; + move16(); + } + } + st->tec_tfa = 1; + move16(); + } + ELSE + { + st->tec_tfa = 0; + move16(); + } + + st->enablePlcWaveadjust = 0; + move16(); + IF (GE_32(st->total_brate_fx, 48000)) + { + st->enablePlcWaveadjust = 1; + move16(); + } + + + move16(); + st->glr = 0; + test(); + test(); + test(); + if( (EQ_32(st->total_brate_fx, 9600))||(EQ_32(st->total_brate_fx,16400))|| + (EQ_32(st->total_brate_fx, 24400))) + { + move16(); + st->glr = 1; + } + + if(st->glr) + { + + st->nb_bits_header_ace = add(st->nb_bits_header_ace, G_LPC_RECOVERY_BITS); + } + + test(); + IF (EQ_16(st->bwidth_fx, NB)||EQ_16(st->bwidth_fx,WB)) + { + test(); + IF (st->rf_mode==0) + { + st->nmStartLine = startLineWB[s_min((sizeof(startLineWB)/sizeof(startLineWB[0])-1), s_max(3, st->frame_size_index))]; + move16(); + } + ELSE + { + st->nmStartLine = startLineWB[s_min((sizeof(startLineWB)/sizeof(startLineWB[0])-1), s_max(3, st->frame_size_index-1))]; + move16(); + } + } + ELSE /* (st->bwidth_fx == SWB || st->bwidth_fx == FB) */ + { + IF (st->rf_mode==0) + { + st->nmStartLine = startLineSWB[s_min((sizeof(startLineSWB)/sizeof(startLineSWB[0])-1), sub(s_max(3, st->frame_size_index), 3))]; + move16(); + } + ELSE { + st->nmStartLine = startLineSWB[s_min((sizeof(startLineSWB)/sizeof(startLineSWB[0])-1), sub(s_max(3, st->frame_size_index-1), 3))]; + move16(); + } + } + + test(); + test(); + test(); + test(); + test(); + IF ( (LT_32(st->total_brate_fx, ACELP_24k40))&&((GT_32(st->total_brate_fx,st->last_total_brate_fx))||(EQ_16(st->last_codec_mode,MODE1)))) + { + /* low-freq memQuantZeros must be reset partially if bitrate increased */ + FOR (i = 0; i < st->nmStartLine; i++) + { + st->memQuantZeros[i] = 0; + move16(); + } + } + ELSE IF ( (GE_32(st->total_brate_fx, ACELP_24k40))&&(LE_32(st->total_brate_fx,ACELP_32k))&&(GE_32(st->last_total_brate_fx,ACELP_13k20))&&(LT_32(st->last_total_brate_fx,ACELP_24k40))) + { + FOR (i = 0; i < st->L_frame_fx; i++) /* memQuantZeros won't be updated */ + { + st->memQuantZeros[i] = 0; + move16(); + } + } + +} + diff --git a/lib_enc/core_enc_switch.c b/lib_enc/core_enc_switch.c new file mode 100644 index 0000000..315f908 --- /dev/null +++ b/lib_enc/core_enc_switch.c @@ -0,0 +1,230 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "prot_fx.h" +#include "basop_mpy.h" +#include "options.h" +#include "cnst_fx.h" +#include "rom_com_fx.h" + +#include "stl.h" + +void core_coder_mode_switch( Encoder_State_fx *st, const Word16 bandwidth_in, + const Word32 bitrate, + const Word16 shift) +{ + Word16 i, fscale, switchWB; + Word16 bSwitchFromAmrwbIO; + Word16 bandwidth; + Word32 tmp32; + Word32 sr_core; + + + move16(); + move16(); + move16(); + move16(); + + bandwidth = bandwidth_in; + + switchWB = 0; + bSwitchFromAmrwbIO = 0; + if ( EQ_16(st->last_core_fx, AMR_WB_CORE)) + { + move16(); + bSwitchFromAmrwbIO = 1; + } + + sr_core = getCoreSamplerateMode2(bitrate, bandwidth, st->rf_mode); + move16(); + fscale = sr2fscale(sr_core); + move16(); + + IF ( s_and(s_and((Word16)GE_16(bandwidth,WB),(Word16)EQ_16(fscale,(FSCALE_DENOM*16000)/12800)),(Word16)EQ_16(fscale,st->fscale))) + { + IF ( s_or(s_and((Word16)GT_32(bitrate, 32000),(st->tcxonly==0)),s_and((Word16)LE_32(bitrate,32000),st->tcxonly!=0))) + { + move16(); + switchWB = 1; + } + } + if( EQ_16(st->last_codec_mode,MODE1)) + { + move16(); + switchWB = 1; /*force init when coming from MODE1*/ + } + test(); + if( GT_32(st->last_total_brate_fx,ACELP_32k)&&LE_32(st->total_brate_fx,ACELP_32k)) + { + move16(); + switchWB = 1; /*force init when coming from MODE1*/ + } + + test(); + test(); + IF ( (EQ_16(fscale, st->fscale))&&(bSwitchFromAmrwbIO==0)&&(switchWB==0)) + { + st->total_brate_fx = bitrate; + move32(); + st->sr_core = sr_core; + move32(); + st->L_frame_fx = extract_l(Mult_32_16(st->sr_core , 0x0290)); + assert(st->L_frame_fx == st->sr_core / 50); + st->tcxonly = getTcxonly(st->total_brate_fx); + + /* st->bits_frame_nominal = (int)( (float)st->L_frame_fx/(float)st->fscale ) * (float)FSCALE_DENOM/128.0f * (float)st->bitrate/100.0f + 0.49f ; */ + /* st->bits_frame_nominal = extract_l(L_shr(Mpy_32_16_1( L_shl(st->bitrate,8), mult_r(div_s(st->fscale, shl(st->L_frame_fx,4)), FL2WORD16(FSCALE_DENOM/12800.f))), 6)); */ + tmp32 = L_shl(st->total_brate_fx, 1); /* (float)st->L_frame_fx/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->bitrate */ + st->bits_frame_nominal = extract_l(L_shr(Mpy_32_16_1(tmp32, 20972), 6)); /* 20972 = 0.01 * 64 * 32768 */ + assert(st->bits_frame_nominal == (int)( (float)st->L_frame_fx/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->total_brate_fx/100.0f + 0.49f )); + + st->igf = getIgfPresent(bitrate, bandwidth, st->rf_mode); + + /* switch IGF configuration */ + IF (st->igf) + { + IGFEncSetMode( &st->hIGFEnc, st->total_brate_fx, bandwidth, st->rf_mode ); + } + + st->tcx_cfg.tcx_coded_lines = getNumTcxCodedLines(bandwidth); + move16(); + st->tcx_cfg.bandwidth = getTcxBandwidth(st->bwidth_fx); + move16(); + move16(); + st->tcx_cfg.tcxRateLoopOpt = 0; + if (st->tcxonly) + { + move16(); + st->tcx_cfg.tcxRateLoopOpt = 2; + } + + st->tcx_cfg.ctx_hm = getCtxHm(st->total_brate_fx, st->rf_mode ); + move16(); + st->tcx_cfg.resq = getResq(st->total_brate_fx); + move16(); + st->tcx_lpc_shaped_ari = getTcxLpcShapedAri( + st->total_brate_fx, + bandwidth + ,st->rf_mode + ); + + test(); + if (st->tcx_cfg.resq != 0 && st->tcxonly == 0) + { + st->tcx_cfg.tcxRateLoopOpt = 1; + move16(); + } + st->tcx_cfg.fIsTNSAllowed = getTnsAllowed(st->total_brate_fx, st->igf); + IF (st->tcx_cfg.fIsTNSAllowed != 0) + { + InitTnsConfigs(bwMode2fs[bandwidth], st->tcx_cfg.tcx_coded_lines, st->tcx_cfg.tnsConfig, st->hIGFEnc.infoStopFrequency, st->total_brate_fx); + } + move16(); + + st->narrowBand = 0; + move16(); + if(EQ_16(st->bwidth_fx, NB)) + { + st->narrowBand = 1; + move16(); + } + IF ( st->narrowBand ) + { + st->min_band_fx = 1; + move16(); + st->max_band_fx = 16; + move16(); + } + ELSE + { + st->min_band_fx = 0; + move16(); + st->max_band_fx = 19; + move16(); + } + + FOR (i=0; ibits_frame_nominal)) + { + move16(); + move16(); + move16(); + st->frame_size_index = i; + st->bits_frame = FrameSizeConfig[i].frame_bits; + st->bits_frame_core = FrameSizeConfig[i].frame_net_bits; + BREAK; + } + } + + st->restrictedMode = getRestrictedMode(st->total_brate_fx, 0); + + core_coder_reconfig( st ); + } + ELSE + { + st->igf = getIgfPresent(bitrate, bandwidth, st->rf_mode); + init_coder_ace_plus(st, shift); + } + + IF( st->igf != 0 ) + { + test(); + test(); + test(); + test(); + test(); + IF( (EQ_16(st->bwidth_fx, WB)&&NE_16(st->last_extl_fx,WB_TBE))|| + (EQ_16(st->bwidth_fx, SWB) && NE_16(st->last_extl_fx, SWB_TBE) ) || + (EQ_16(st->bwidth_fx, FB) && NE_16(st->last_extl_fx, FB_TBE) ) ) + { + /* reset TBE buffers as previous frame wasn't using TBE */ + TBEreset_enc_fx( st, st->bwidth_fx ); + } + ELSE + { + set16_fx( st->state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + set16_fx( st->state_syn_shbexc_fx, 0, L_SHB_LAHEAD ); + set16_fx( st->mem_stp_swb_fx, 0, LPC_SHB_ORDER ); + set16_fx( st->mem_zero_swb_fx, 0, LPC_SHB_ORDER ); + st->gain_prec_swb_fx = 16384; + move16(); /*Q14 = 1 */ + } + } + + IF ( s_and(st->envWeighted!=0, st->enableTcxLpc==0) ) + { + /* Unweight the envelope */ + E_LPC_lsp_unweight( + st->lsp_old_fx, + st->lsp_old_fx, + st->lsf_old_fx, + st->inv_gamma, + M + ); + move16(); + st->envWeighted = 0; + } + + st->enablePlcWaveadjust = 0; + move16(); + if (GE_32(bitrate, 48000)) + { + st->enablePlcWaveadjust = 1; + move16(); + } + + test(); + IF(GT_32(st->last_total_brate_fx, 32000) + || EQ_32(st->last_codec_mode,MODE1)) + { + move16(); + st->glr_reset = 1; + } +} + diff --git a/lib_enc/core_enc_updt.c b/lib_enc/core_enc_updt.c new file mode 100644 index 0000000..a84a99e --- /dev/null +++ b/lib_enc/core_enc_updt.c @@ -0,0 +1,257 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "prot_fx.h" +#include "basop_util.h" +#include "options.h" +#include "cnst_fx.h" +#include "stl.h" + +void core_encode_update(Encoder_State_fx *st + ) +{ + Word16 n; + + + + /*--------------------------------------------------------------* + * Update Buffers + *---------------------------------------------------------------*/ + + /* Update Input Signal Buffers */ + + n = add(st->encoderPastSamples_enc, st->encoderLookahead_enc); + + Copy(st->buf_speech_enc +st->L_frame_fx, st->buf_speech_enc, n); + Copy(st->buf_speech_enc_pe+st->L_frame_fx, st->buf_speech_enc_pe, n); + + + IF(!st->tcxonly) + { + n = add(st->L_frame_fx, shr(st->L_frame_fx,2)); + Copy(st->buf_wspeech_enc+st->L_frame_fx, st->buf_wspeech_enc, n); + } + + + IF ( s_or( s_or(st->core_fx == ACELP_CORE, s_or( (Word16)EQ_32(st->core_brate_fx, SID_2k40),(Word16)EQ_32(st->core_brate_fx,FRAME_NO_DATA))),(Word16)EQ_32(st->core_fx,AMR_WB_CORE))) + { + Copy(st->buf_speech_enc + st->L_frame_fx, st->buf_speech_ltp + st->L_frame_fx, st->L_frame_fx); + } + + n = add(st->encoderPastSamples_enc, st->encoderLookahead_enc); + Copy(st->buf_speech_ltp+st->L_frame_fx, st->buf_speech_ltp, n); + Copy(st->buf_synth+st->L_frame_fx, st->buf_synth, add(st->L_frame_fx,L_SUBFR)); + + /* Update previous mode */ + + move16(); + st->last_core_fx = st->core_fx; /* not in float -> remove? */ + + + test(); + test(); + test(); + IF( ((LE_32(st->core_brate_fx,SID_2k40))&&EQ_16(st->cng_type_fx,FD_CNG)) + || (st->tcxonly && EQ_16(st->codec_mode,MODE2)) + ) + { + /* reset LP memories */ + set16_fx( st->mem_MA_fx,0, M ); + Copy( GEWB_Ave_fx, st->mem_AR_fx, M ); + } + +} + + +void core_encode_update_cng( Encoder_State_fx *st, + Word16 *timeDomainBuffer, + Word16 *A, + Word16 *Aw, + Word16 Q_new, + Word16 shift + ) +{ + Word16 i; + Word16 lsp[M]; + Word16 lsf[M]; /* 14Q1 * 1.28 */ + Word16 *synth, synth_buf[M+1+L_FRAME_PLUS+L_FRAME_PLUS/2], wsyn[L_FRAME_PLUS]; + Word16 *p_A, tmp; + Word16 enr_index; + Word16 enr, tmpv, maxv, scale, att; + Word16 hi, lo; + Word16 *pt_res; + Word32 L_tmp, L_ener; + + + /* LPC -> LSP/lsp */ + /* LSP/lsp -> LSF/lsf */ + E_LPC_a_lsp_conversion( A, lsp, st->lsp_old_fx, M ); + IF(EQ_16(st->L_frame_fx, L_FRAME16k)) + { + lsp2lsf_fx( lsp, lsf, M, INT_FS_16k_FX ); + } + ELSE + { + E_LPC_lsp_lsf_conversion( lsp, lsf, M ); + } + + /* Update synth memory */ + move16(); + synth = synth_buf + (1+M); + Copy( st->LPDmem.syn, synth_buf, 1+M ); + Copy( timeDomainBuffer, synth, st->L_frame_fx ); + Copy( synth+st->L_frame_fx-(1+M), st->LPDmem.syn, 1+M ); + Copy( synth, st->synth, st->L_frame_fx ); + + /* Update ZIR */ + set16_fx( synth+st->L_frame_fx, 0, shr(st->L_frame_fx,1) ); + E_UTIL_synthesis(1, A, synth+st->L_frame_fx, synth+st->L_frame_fx, shr(st->L_frame_fx,1), &synth[st->L_frame_fx-M], 0, M ); + Copy( synth+st->L_frame_fx-(st->L_frame_fx/2), st->LPDmem.Txnq, shr(st->L_frame_fx,1) ); + + /* Update pe-synth memory */ + move16(); + tmp = synth[-(1+M)]; + E_UTIL_f_preemph2( Q_new-1, synth-M, st->preemph_fac, M+st->L_frame_fx, &tmp ); + Copy( synth+st->L_frame_fx-M, st->LPDmem.mem_syn, M ); + Copy( synth+st->L_frame_fx-M, st->LPDmem.mem_syn2, M ); + + /* Update excitation memory */ + Copy( st->LPDmem.old_exc+st->L_frame_fx, st->LPDmem.old_exc, s_max(L_EXC_MEM-st->L_frame_fx, 0 )); + Residu3_fx( A, synth, st->LPDmem.old_exc+s_max(L_EXC_MEM-st->L_frame_fx, 0), st->L_frame_fx, 1 ); + + /* Update LP_CNG memory */ + IF( EQ_32(st->core_brate_fx, SID_2k40)) + { + pt_res = st->LPDmem.old_exc + L_EXC_MEM - st->L_frame_fx; + maxv = 0; + move16(); + FOR(i = 0; i < st->L_frame_fx; i++) + { + maxv = s_max(maxv, abs_s(pt_res[i])); + } + scale = norm_s(maxv); + L_ener = L_deposit_l(1); + IF( EQ_16(st->L_frame_fx, L_FRAME)) + { + FOR (i=0; i<128; i++) + { + tmpv = shl(*pt_res,scale); + L_tmp = L_mult0(tmpv, tmpv); + pt_res++; + tmpv = shl(*pt_res,scale); + L_tmp = L_mac0(L_tmp, tmpv, tmpv); /* 2*(Q_new+scale) */ + pt_res++; + L_ener = L_add(L_ener, L_shr(L_tmp, 7)); /* 2*(Q_new+scale)+1, divide by L_frame done here */ + } + } + ELSE /* L_FRAME16k */ + { + FOR (i=0; i<160; i++) + { + tmpv = shl(*pt_res,scale); + L_tmp = L_mult0(tmpv, tmpv); + pt_res++; + tmpv = shl(*pt_res,scale); + L_tmp = L_mac0(L_tmp, tmpv, tmpv); /* 2*(Q_new+scale) */ + pt_res++; + L_ener = L_add(L_ener, L_shr(Mult_32_16(L_tmp,26214 /* 256/320, Q15 */), 7)); /* 2*(Q_new+scale)+15+1-16+1, divide by L_frame done here */ + } + } + + hi = norm_l(L_ener); + lo = Log2_norm_lc(L_shl(L_ener, hi)); + hi = sub(30, add(hi, shl(add(Q_new, scale), 1))); /* log2 exp in Q2*(Q_new+scale) */ + L_tmp = L_Comp(hi, lo); /* Q16 */ + enr = round_fx(L_shl(L_tmp, 8)); /* Q8 (16+8-16) */ + + /* decrease the energy in case of WB input */ + IF( NE_16(st->bwidth_fx, NB)) + { + IF( EQ_16(st->bwidth_fx,WB)) + { + IF( st->CNG_mode_fx >= 0 ) + { + /* Bitrate adapted attenuation */ + att = ENR_ATT_fx[st->CNG_mode_fx]; + } + ELSE + { + /* Use least attenuation for higher bitrates */ + att = ENR_ATT_fx[4]; + } + } + ELSE + { + att = 384; + move16();/*Q8*/ + } + enr = sub(enr, att ); + } + + /* calculate the energy quantization index */ + enr_index = add(enr, 512 /* Q8(2.0) */); /* enr + 2.0 */ + enr_index = extract_l(L_shr(L_mult0(enr_index, STEP_SID_FX), 12+8)); /* Q0 (8+12-(8+12)) */ + + /* limit the energy quantization index */ + enr_index = s_min(enr_index, 127); + enr_index = s_max(enr_index, 0); + + st->old_enr_index_fx = enr_index; + } + + /* Update weighted synthesis memory */ + move16(); + p_A = Aw; + FOR ( i = 0; i < st->L_frame_fx; i += L_SUBFR ) + { + Residu3_fx( p_A, &synth[i], &wsyn[i], L_SUBFR, 0); + p_A += (M+1); + } + move16(); + + + + tmp = sub(st->wspeech_enc[-1],shl(st->LPDmem.mem_w0,shift)); + E_UTIL_deemph2( -shift, wsyn, st->preemph_fac, st->L_frame_fx, &tmp ); + st->LPDmem.mem_w0 = sub(st->wspeech_enc[st->L_frame_fx-1], tmp); + st->LPDmem.mem_w0 =shr(st->LPDmem.mem_w0, shift); + + /* Update LPC-related memories */ + + Copy( lsp, st->lsp_old_fx, M ); + Copy( lsf, st->lsf_old_fx, M ); + move16(); + st->envWeighted = 0; + Copy( A, st->old_Aq_12_8_fx, M+1 ); + st->old_Es_pred_fx=0; + + + /* Reset acelp memories */ + move16(); + move16(); + st->dm_fx.prev_gain_code = L_deposit_l(0); + set16_fx(st->dm_fx.prev_gain_pit,0,6); + st->dm_fx.prev_state = 0; + st->LPDmem.tilt_code = TILT_CODE; + st->LPDmem.gc_threshold = L_deposit_l(0); + + /* Update ace/tcx mode */ + move16(); + st->core_fx = ACELP_CORE; + + /* Reset TCX overlap */ + st->tcx_cfg.tcx_curr_overlap_mode = st->tcx_cfg.tcx_last_overlap_mode = ALDO_WINDOW; + move16(); + + IF( st->first_CNG_fx == 0 ) + { + Copy( st->lsp_old_fx, st->lspCNG_fx, M ); + } + + return; +} + diff --git a/lib_enc/core_switching_enc_fx.c b/lib_enc/core_switching_enc_fx.c new file mode 100644 index 0000000..d71e607 --- /dev/null +++ b/lib_enc/core_switching_enc_fx.c @@ -0,0 +1,512 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_enc_fx.h" /* Encoder static table prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required for wmc_tool */ + + +/*---------------------------------------------------------------------* +* core_switching_pre_enc() +* +* Preprocessing (preparing) for ACELP/HQ core switching +*---------------------------------------------------------------------*/ + +void core_switching_pre_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + LPD_state *mem, /* i/o: encoder state structure */ + const Word16 *old_inp_12k8, /* i : old input signal @12.8kHz */ + const Word16 *old_inp_16k /* i : old input signal @16kHz */ +) +{ + Word16 Sample_Delay_HP, Sample_Delay_LP; + Word16 tmp16; + Word16 tmp; + + /* Mode switching */ + IF( EQ_16(st_fx->last_codec_mode,MODE2)) + { + st_fx->mem_deemph_fx = st_fx->LPDmem.syn[M]; + move16(); + + Copy( mem->mem_syn2, st_fx->mem_syn1_fx, M ); + + st_fx->igf = 0; + move16(); + + IF( NE_16(st_fx->last_core_fx,ACELP_CORE)) + { + /* reset BWE memories */ + set16_fx( st_fx->old_bwe_exc_fx, 0, PIT16k_MAX*2 ); + st_fx->bwe_non_lin_prev_scale_fx = L_deposit_l(0); + } + + set16_fx( st_fx->old_syn_12k8_16k_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) ); + + test(); + IF( EQ_16(st_fx->last_core_fx,TCX_20_CORE)||EQ_16(st_fx->last_core_fx,TCX_10_CORE)) + { + st_fx->last_core_fx = HQ_CORE; + move16(); + + set32_fx( st_fx->last_ni_gain_fx, 0, BANDS_MAX ); + set16_fx( st_fx->last_env_fx, 0, BANDS_MAX ); + st_fx->last_max_pos_pulse_fx = 0; + move16(); + + st_fx->mode_count_fx = 0; + move16(); + st_fx->mode_count1_fx = 0; + move16(); + + set16_fx( st_fx->prev_SWB_peak_pos_fx, 0, SPT_SHORTEN_SBNUM ); + st_fx->prev_frm_hfe2_fx = 0; + move16(); + st_fx->prev_stab_hfe2_fx = 0; + move16(); + + /*ALDO overlap windowed past: also used in MODE2 but for other MDCT-LB*/ + set16_fx( st_fx->old_out_fx, 0, L_FRAME32k ); + } + + test(); + IF( (EQ_16(st_fx->L_frame_fx,L_FRAME16k))&&(EQ_16(st_fx->last_L_frame_fx,L_FRAME))) + { + Copy( st_fx->lsp_old_fx, st_fx->lsp_old16k_fx, M ); + + st_fx->rate_switching_reset_16kHz = lsp_convert_poly_fx( st_fx->lsp_old16k_fx, st_fx->L_frame_fx, 0 ); + } + + st_fx->use_acelp_preq = 0; + move16(); + + } + + test(); + IF( EQ_16(st_fx->last_core_fx, -1) && EQ_16(st_fx->core_fx, HQ_CORE)) + { + /* very first frame is HQ_CORE */ + st_fx->last_core_fx = HQ_CORE; + move16(); + } + + test(); + test(); + IF( EQ_16(st_fx->core_fx, HQ_CORE)&&(EQ_16(st_fx->last_core_fx,ACELP_CORE)||EQ_16(st_fx->last_core_fx,AMR_WB_CORE))) /* HQ init */ + { + set32_fx( st_fx->last_ni_gain_fx, 0, BANDS_MAX ); + set16_fx( st_fx->last_env_fx, 0, BANDS_MAX ); + st_fx->last_max_pos_pulse_fx = 0; + move16(); + + st_fx->mode_count_fx = 0; + move16(); + st_fx->mode_count1_fx = 0; + move16(); + + set16_fx( st_fx->prev_SWB_peak_pos_fx, 0, SPT_SHORTEN_SBNUM ); + st_fx->prev_frm_hfe2_fx = 0; + move16(); + st_fx->prev_stab_hfe2_fx = 0; + move16(); + + set16_fx( st_fx->old_out_fx, 0, L_FRAME32k ); + } + + /* Here we only handle cases where last_ppp and last_nelp not updated when coming from CodecB or other cores + within ACELP_CORE if switching from another bitarate to vbr, last_ppp and last_nelp is always updated in the previous frame */ + test(); + test(); + IF( EQ_16(st_fx->core_fx, ACELP_CORE)&&(NE_16(st_fx->last_core_fx,ACELP_CORE)||EQ_16(st_fx->last_codec_mode,MODE2))) + { + st_fx->last_last_ppp_mode_fx = 0; + move16(); + st_fx->last_ppp_mode_fx = 0; + move16(); + st_fx->last_nelp_mode_fx =0; + move16(); + } + + test(); + test(); + test(); + IF( EQ_16(st_fx->core_fx, ACELP_CORE)&&(NE_16(st_fx->last_core_fx,ACELP_CORE)||EQ_16(st_fx->last_codec_mode,MODE2)||LE_32(st_fx->last_total_brate_fx,PPP_NELP_2k80))) + { + st_fx->act_count_fx = 3; + move16(); + st_fx->uv_count_fx = 0; + move16(); + } + + test(); + test(); + IF( ( EQ_16(st_fx->core_fx, ACELP_CORE)||EQ_16(st_fx->core_fx,AMR_WB_CORE))&&EQ_16(st_fx->last_core_fx,HQ_CORE)) + { + IF(EQ_16(st_fx->L_frame_fx, L_FRAME16k)) + { + Copy( TRWB2_Ave_fx, st_fx->lsf_old_fx, M ); /* init of LSP */ + lsf2lsp_fx( st_fx->lsf_old_fx, st_fx->lsp_old_fx, M, INT_FS_16k ); + } + ELSE + { + Copy( TRWB_Ave_fx, st_fx->lsf_old_fx, M ); /* init of LSP */ + lsf2lsp_fx( st_fx->lsf_old_fx, st_fx->lsp_old_fx, M, INT_FS_FX ); + } + + st_fx->mem_deemph_fx = 0; + move16(); + st_fx->LPDmem.syn[M] = 0; + move16(); + set16_fx(mem->mem_syn2, 0, M ); + set16_fx( mem->mem_syn, 0, M ); + set16_fx( st_fx->mem_syn1_fx, 0, M ); + st_fx->Nb_ACELP_frames_fx = 0; + move16(); + + /* Reset ACELP parameters */ + set16_fx( st_fx->mem_MA_fx,0, M ); + Copy( GEWB_Ave_fx, st_fx->mem_AR_fx, M ); + mem->mem_w0 = 0; + move16(); + mem->tilt_code = 0; + move16(); + init_gp_clip_fx( st_fx->clip_var_fx ); + mem->gc_threshold = 0; + move16(); + + /* set16_fx( st_fx->dispMem, 0, 8 ); */ + set16_fx( st_fx->dm_fx.prev_gain_pit, 0, 6 ); + st_fx->dm_fx.prev_state = 0; + move16(); + st_fx->dm_fx.prev_gain_code = L_deposit_l(0); + + st_fx->last_coder_type_fx = GENERIC; + move16(); + + tmp16 = add(NB_SUBFR,1); + move16(); + + if( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + tmp16=NB_SUBFR; + move16(); + } + + Copy( st_fx->old_pitch_buf_fx + tmp16, st_fx->old_pitch_buf_fx, tmp16 ); + set16_fx( st_fx->old_pitch_buf_fx + tmp16, L_SUBFR,tmp16); + + /* Reset old ACELP buffers */ + set16_fx( mem->old_exc, 0, L_EXC_MEM ); + set16_fx( st_fx->old_bwe_exc_fx, 0, PIT16k_MAX*2 ); + + /* reset BWE memories */ + st_fx->bwe_non_lin_prev_scale_fx = 0; + set16_fx( st_fx->old_syn_12k8_16k_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) ); + } + + test(); + test(); + IF( GE_32(st_fx->input_Fs_fx, 16000)&&NE_16(st_fx->last_extl_fx,WB_BWE)&&EQ_16(st_fx->extl_fx,WB_BWE)) + { + test(); + IF( NE_16(st_fx->last_extl_fx, SWB_BWE)&&NE_16(st_fx->last_extl_fx,FB_BWE)) + { + st_fx->prev_mode_fx = NORMAL; + move16(); + st_fx->modeCount_fx = 0; + move16(); + } + + st_fx->prev_L_swb_norm1_fx = 8; + move16(); + } + + test(); + test(); + test(); + test(); + test(); + IF( ( GE_32(st_fx->input_Fs_fx, 32000)&&NE_16(st_fx->last_extl_fx,SWB_BWE)&&EQ_16(st_fx->extl_fx,SWB_BWE))|| + ( GE_32(st_fx->input_Fs_fx, 48000) && NE_16(st_fx->last_extl_fx, FB_BWE) && EQ_16(st_fx->extl_fx, FB_BWE) ) ) + { + /* we are switching to SWB BWE - reset SWB BWE buffers */ + + IF( EQ_16(st_fx->L_frame_fx, L_FRAME)) + { + Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ); + Sample_Delay_LP = NS2SA( 12800, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS ); + + Copy( old_inp_12k8 + sub(L_INP_MEM + L_FRAME, Sample_Delay_LP), st_fx->old_input_lp_fx, Sample_Delay_LP ); + } + ELSE + { + Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ); + Sample_Delay_LP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS ); + Copy( old_inp_16k + sub(L_INP_MEM + L_FRAME, Sample_Delay_LP), st_fx->old_input_lp_fx, Sample_Delay_LP ); + } + + tmp = sub(L_LOOK_16k + L_SUBFR16k, Sample_Delay_HP); + Copy( &st_fx->old_speech_shb_fx[tmp], st_fx->new_input_hp_fx, Sample_Delay_HP ); + add(0,0); + + IF (NE_16(st_fx->last_extl_fx,WB_BWE)) + { + st_fx->prev_mode_fx = NORMAL; + move16(); + st_fx->modeCount_fx = 0; + move16(); + } + st_fx->EnergyLF_fx = L_deposit_l(0); + st_fx->prev_L_swb_norm1_fx = 8; + move16();/*8.0 in Q0 */ + st_fx->EnergyLT_fx_exp = 30; + move16(); /* Set to a High Exponent so it is 1^-30 */ + } + + return; +} + + + +/*---------------------------------------------------------------------* +* core_switching_post_enc() +* +* Postprocessing for ACELP/HQ core switching +*---------------------------------------------------------------------*/ +void core_switching_post_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 old_inp_12k8[], /* i : input signal @12.8 kHz Qinp */ + const Word16 old_inp_16k[], /* i : input signal @16 kHz Qinp */ + const Word16 pitch[3], /* i : open-loop pitch values for quantiz. */ + const Word16 voicing[3], /* i : Open-loop pitch gains */ + const Word16 A[], /* i : unquant. LP filter coefs. (Q12) */ + Word16 Qshift, + Word16 Q_new, + const Word16 Qsp, /* i/o : Q from acelp synthsis */ + Word16 *Qmus /* i/o : Q from mdct synthsis / Q of output synthesis */ +) +{ + Word16 T_op[3]; + + Copy( pitch, T_op, 3 ); + + IF( EQ_16(st_fx->core_fx, HQ_CORE)) + { + st_fx->use_acelp_preq = 0; + move16(); + + test(); + IF( ( EQ_16(st_fx->last_core_fx, ACELP_CORE)||EQ_16(st_fx->last_core_fx,AMR_WB_CORE))) /* core switching ==> CELP subframe encoding */ + { + acelp_core_switch_enc_fx( st_fx, &(st_fx->LPDmem),old_inp_12k8 + L_INP_MEM - NS2SA_fx2(INT_FS_FX, ACELP_LOOK_NS), + old_inp_16k + L_INP_MEM - NS2SA_fx2(INT_FS_16k, ACELP_LOOK_NS), T_op, voicing, A, Qshift, Q_new ); + } + + st_fx->bwe_non_lin_prev_scale_fx = L_deposit_l(0); + st_fx->mem_deemph_old_syn_fx = 0; + move16(); + + } + ELSE + { + *Qmus=Qsp; /* Write Qout */ + + /* reset SWB TBE buffers */ + test(); + IF( EQ_16(st_fx->extl_fx, WB_TBE)&&NE_16(st_fx->last_extl_fx,WB_TBE)) + { + wb_tbe_extras_reset_fx( st_fx->mem_genSHBexc_filt_down_wb2_fx, st_fx->mem_genSHBexc_filt_down_wb3_fx ); + + IF ( NE_16(st_fx->last_extl_fx, WB_BWE)) + { + set16_fx( st_fx->decim_state1_fx, 0, 2*ALLPASSSECTIONS_STEEP+1 ); + set16_fx( st_fx->decim_state2_fx, 0, 2*ALLPASSSECTIONS_STEEP+1 ); + } + + set16_fx( st_fx->state_syn_shbexc_fx, 0, L_SHB_LAHEAD/4 ); + set16_fx( st_fx->syn_overlap_fx, 0, L_SHB_LAHEAD ); + set32_fx( st_fx->mem_csfilt_fx, 0, 2 ); + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( (EQ_16(st_fx->extl_fx, SWB_TBE)||EQ_16(st_fx->extl_fx,FB_TBE))&& + ( EQ_16(st_fx->last_core_fx,HQ_CORE) || NE_16(st_fx->L_frame_fx, st_fx->last_L_frame_fx) || + ( NE_16(st_fx->last_extl_fx, SWB_TBE) && NE_16(st_fx->last_extl_fx, FB_TBE) ) ) + ) + { + set16_fx( st_fx->state_ana_filt_shb_fx, 0, (2*ALLPASSSECTIONS_STEEP+1) ); + set16_fx( st_fx->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k ); + + swb_tbe_reset_fx( st_fx->mem_csfilt_fx, st_fx->mem_genSHBexc_filt_down_shb_fx, st_fx->state_lpc_syn_fx, + st_fx->syn_overlap_fx, st_fx->state_syn_shbexc_fx, &(st_fx->tbe_demph_fx), &(st_fx->tbe_premph_fx), + st_fx->mem_stp_swb_fx, &(st_fx->gain_prec_swb_fx)); + + set16_fx( st_fx->dec_2_over_3_mem_fx,0, 12 ); + set16_fx( st_fx->dec_2_over_3_mem_lp_fx,0, 6 ); + } + ELSE IF( ( EQ_16(st_fx->extl_fx, SWB_TBE)||EQ_16(st_fx->extl_fx,FB_TBE))&& + ( NE_32(st_fx->last_total_brate_fx, st_fx->total_brate_fx) || NE_16(st_fx->last_bwidth_fx, st_fx->bwidth_fx) || + NE_16(st_fx->last_codec_mode, MODE1) || NE_16(st_fx->rf_mode, st_fx->rf_mode_last) ) ) + { + set16_fx( st_fx->state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + set16_fx( st_fx->state_syn_shbexc_fx, 0, L_SHB_LAHEAD ); + set16_fx( st_fx->mem_stp_swb_fx, 0, LPC_SHB_ORDER ); + set16_fx( st_fx->mem_zero_swb_fx, 0, LPC_SHB_ORDER ); + st_fx->gain_prec_swb_fx = 16384; + move16(); /*Q14 = 1 */ + } + + test(); + test(); + IF( EQ_16(st_fx->extl_fx, FB_TBE)&&(NE_16(st_fx->last_extl_fx,FB_TBE)||NE_16(st_fx->L_frame_fx,st_fx->last_L_frame_fx))) + { + set16_fx( st_fx->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + st_fx->fb_tbe_demph_fx = 0; + fb_tbe_reset_enc_fx( st_fx->elliptic_bpf_2_48k_mem_fx, &st_fx->prev_fb_energy_fx,st_fx->elliptic_bpf_2_48k_mem_fx_Q,&st_fx->prev_fb_energy_fx_Q); + } + } + + return; +} + +/*---------------------------------------------------------------------* +* core_switching_hq_prepare_enc() +* +* Preprocessing in the first HQ frame after ACELP frame +* - modify bit allocation for HQcore removing CELP subframe budget +* - update st->old_wtda to modify windows at the encoder +*---------------------------------------------------------------------*/ + +void core_switching_hq_prepare_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *num_bits, /* i/o: bit budget update */ + const Word16 input_frame, /* i : frame length */ + Word32 *wtda_audio, /* shall be q_audio + 15, audio allready scalled in wtda function */ + const Word16 *audio +) +{ + Word16 delta, Loverlapp, i; + Word16 tmp16; + Word32 cbrate, *pt_32; + const Word16 *pt_cos, *pt_16; + Word16 n; + + SWITCH (input_frame) + { + case L_FRAME8k: + delta = 1; + move16(); + pt_cos= sin_switch_8; + BREAK; + case L_FRAME16k: + delta = 2; + move16(); + pt_cos= sin_switch_16; + BREAK; + case L_FRAME32k: + delta = 4; + move16(); + pt_cos= sin_switch_32; + BREAK; + default : + delta = 6; + move16(); + pt_cos= sin_switch_48; + BREAK; + } + + /* set switching frame bit-rate */ + IF( EQ_16(st_fx->last_L_frame_fx, L_FRAME)) + { + IF( GT_32(st_fx->core_brate_fx, ACELP_24k40)) + { + cbrate = L_add(ACELP_24k40, 0); + } + ELSE + { + cbrate = L_add(st_fx->core_brate_fx, 0); + } + + /* subtract ACELP switching frame bits */ + IF( GE_32(st_fx->core_brate_fx, ACELP_11k60)) + { + (*num_bits) = sub((*num_bits), 1); /* LP_FLAG bit */ + } + *num_bits = sub( (*num_bits), ACB_bits_tbl[BIT_ALLOC_IDX_fx(cbrate, GENERIC, 0, 0)] ); /* pitch bits*/ + *num_bits = sub( (*num_bits), gain_bits_tbl[BIT_ALLOC_IDX_fx(cbrate, TRANSITION, 0, 0)] ); /* gain bits */ + *num_bits = sub( (*num_bits), FCB_bits_tbl[BIT_ALLOC_IDX_fx(cbrate, GENERIC, 0, 0)] ); /* FCB bits */ + } + ELSE /* L_frame == L_FRAME16k */ + { + IF( LE_32(st_fx->core_brate_fx, ACELP_8k00)) + { + cbrate = L_add(ACELP_8k00, 0); + } + ELSE IF( LE_32(st_fx->core_brate_fx, ACELP_14k80)) + { + cbrate = L_add(ACELP_14k80, 0); + } + ELSE + { + cbrate = L_min(st_fx->core_brate_fx, ACELP_22k60); + } + + /* subtract ACELP switching frame bits */ + IF( GE_32(st_fx->core_brate_fx, ACELP_11k60)) + { + (*num_bits) = sub((*num_bits), 1); /* LP_FLAG bit */ + } + *num_bits = sub((*num_bits), ACB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(cbrate, GENERIC, 0, 0)]); /* pitch bits*/ + *num_bits = sub((*num_bits), gain_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(cbrate, GENERIC, 0, 0)]); /* gain bits */ + *num_bits = sub((*num_bits), FCB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(cbrate, GENERIC, 0, 0)]); /* FCB bits */ + } + + /* subtract BWE bits */ + test(); + test(); + IF( !( ( EQ_16(inner_frame_tbl[st_fx->bwidth_fx], L_FRAME16k)&&EQ_16(st_fx->last_L_frame_fx,L_FRAME16k))||EQ_16(inner_frame_tbl[st_fx->bwidth_fx],L_FRAME8k))) + { + *num_bits = sub((*num_bits), (NOOFGAINBITS1 + AUDIODELAYBITS)); + } + + /* Transition window at the encoder */ + n=i_mult2(N_ZERO_8,delta); + Loverlapp=i_mult2(SWITCH_OVERLAP_8k,delta); + /*Overflow=0; */ + + pt_32 = wtda_audio+shr(input_frame,1); + pt_16 = audio+sub(n,1); + tmp16 = sub(shr(input_frame,1),Loverlapp); + + FOR( i = 0; i < tmp16; i++ ) + { + /* wtda_audio[i+input_frame/2] = - audio[n-i-1]; */ + *pt_32++=L_negate(L_shr(L_deposit_h(*pt_16--),1)); /* Q +16 -1 */ + } + + pt_cos = pt_cos + Loverlapp - 1; + FOR( i = tmp16; i < shr(input_frame,1); i++ ) + { + /* *pt_32++ = - audio[n-i-1] *(float)cos((i+1-input_frame/2+Loverlapp)*EVS_PI/(2*(Loverlapp+1))); win=cos() */ + *pt_32++=L_negate(L_mult0(*pt_16--,*pt_cos--)); + } + + /* reset state of old_out if switching */ + set16_fx( st_fx->old_out_fx, 0, L_FRAME32k ); + + return; +} diff --git a/lib_enc/corr_xh_fx.c b/lib_enc/corr_xh_fx.c new file mode 100644 index 0000000..862c955 --- /dev/null +++ b/lib_enc/corr_xh_fx.c @@ -0,0 +1,65 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "prot_fx.h" +#include "cnst_fx.h" +#include "stl.h" + + +#define NB_TRACK 4 +#define STEP NB_TRACK + +/*-------------------------------------------------------------------* + * corr_xh_fx: + * + * Compute the correlation between the target signal and the impulse + * response of the weighted synthesis filter. + * + * y[i]=sum(j=i,l-1) x[j]*h[j-i], i=0,l-1 + *-------------------------------------------------------------------*/ +void corr_xh_fx( + const Word16 x[], /* i : target signal */ + Word16 dn[], /* o : correlation between x[] and h[] */ + const Word16 h[] /* i : impulse response (of weighted synthesis filter) */ +) +{ + Word16 i, j, k; + Word32 L_tmp, y32[L_SUBFR], L_maxloc, L_tot; + + /* first keep the result on 32 bits and find absolute maximum */ + L_tot = L_deposit_l(1); + + FOR (k = 0; k < NB_TRACK; k++) + { + L_maxloc = L_deposit_l(0); + FOR (i = k; i < L_SUBFR; i += STEP) + { + L_tmp = L_mac(1L, x[i], h[0]); /* 1 -> to avoid null dn[] */ + FOR (j = i; j < L_SUBFR-1; j++) + { + L_tmp = L_mac(L_tmp, x[j+1], h[j+1 - i]); + } + + y32[i] = L_tmp; + move32(); + L_tmp = L_abs(L_tmp); + L_maxloc = L_max(L_tmp, L_maxloc); + } + /* tot += 3*max / 8 */ + L_maxloc = L_shr(L_maxloc, 2); + L_tot = L_add(L_tot, L_maxloc); /* +max/4 */ + L_tot = L_add(L_tot, L_shr(L_maxloc, 1)); /* +max/8 */ + } + + /* Find the number of right shifts to do on y32[] so that */ + /* 6.0 x sumation of max of dn[] in each track not saturate. */ + + j = sub(norm_l(L_tot), 4); /* 4 -> 16 x tot */ + + FOR (i = 0; i < L_SUBFR; i++) + { + dn[i] = round_fx(L_shl(y32[i], j)); + } +} diff --git a/lib_enc/decision_matrix_enc_fx.c b/lib_enc/decision_matrix_enc_fx.c new file mode 100644 index 0000000..fc844ca --- /dev/null +++ b/lib_enc/decision_matrix_enc_fx.c @@ -0,0 +1,751 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" +#include "prot_fx.h" +#include "stat_enc_fx.h" +#include "rom_com_fx.h" +#include "stl.h" + + +/*-----------------------------------------------------------------* + * decision_matrix_enc() + * + * Select operating point (combination of technologies) based on input signal properties and command-line parameters: + * + * 7.20 8.00 9.60 13.20 16.40 24.40 32 48 64 96 128 + * Mode 1 1 2 1 2 2 2 2 1 2 2 + * ---------------------------------------------------------------------------------------------------------------------------------------------------------------- + * NB + * speech ACELP@12k8 ACELP@12k8 ACELP@12k8 ACELP@12k8 + * audio LR MDCT LR MDCT TCX LR MDCT + * inactive GSC@12k8 GSC@12k8 TCX GSC@12k8 + * ---------------------------------------------------------------------------------------------------------------------------------------------------------------- + * WB + * speech ACELP@12k8 ACELP@12k8 ACELP@12k8 ACELP@12k8 ACELP@16k ACELP@16k ACELP@16k TCX ACELP@16k TCX TCX + * +0b WB BWE +0b WB BWE +TD WB BWE +TD WB BWE + * audio GSC@12k8 GSC@12k8 TCX LR MDCT TCX TCX HQ TCX HQ TCX TCX + * +0b WB BWE +0b WB BWE +IGF + * inactive GSC@12k8 GSC@12k8 TCX GSC@12k8 TCX TCX AVQ@16k TCX AVQ@16k TCX TCX + * +0b WB BWE +0b WB BWE +IGF +FD WB BWE + * ---------------------------------------------------------------------------------------------------------------------------------------------------------------- + * SWB + * speech ACELP@12k8 ACELP@16k ACELP@16k ACELP@16k TCX ACELP@16k TCX TCX + * +TD SWB BWE +TD SWB BWE +TD SWB BWE +TD SWB BWE +IGF +HR SWB BWE + * audio LR MDCT/GSC TCX TCX HQ TCX HQ TCX TCX + * +FD SWB BWE +IGF +IGF +FD SWB BWE +IGF + * inactive GSC@12k8 TCX TCX AVQ@16k TCX AVQ@16k TCX TCX + * +FD SWB BWE +IGF +IGF +FD SWB BWE +IGF +HR SWB BWE + * ---------------------------------------------------------------------------------------------------------------------------------------------------------------- + * FB + * speech ACELP@16k ACELP@16k ACELP@16k TCX ACELP@16k TCX TCX + * +TD FB BWE +TD FB BWE +TD FB BWE +IGF +HR FB BWE + * audio TCX TCX HQ TCX HQ TCX TCX + * +IGF +IGF +FD FB BWE +IGF + * inactive TCX TCX AVQ@16k TCX AVQ@16k TCX TCX + * +IGF +IGF +FD FB BWE +IGF +HR FB BWE + * --------------------------------------------------------------------------------------------------------------------------------------------------------------- + * + * Note: the GSC technology is part of the ACELP core as AUDIO coder_type (it is used also at 13.2 and 16.4 kbps for SWB unvoiced noisy speech) + * Note2: FB processing is optional and is activated via "-band FB" option on the encoder command line + * Note3: NB (0-4kHz), WB (0-8kHz), SWB (0-16kHz), FB (0-20kHz) + * + * Signalling of modes (x marks a mode that must be signalled in the bitstream) + * + * 7.20 8.00 9.6 13.2 16.4 24.4 32 48 64 + * NB WB SWB FB NB WB SWB FB NB WB SWB FB NB WB SWB FB NB WB SWB FB NB WB SWB FB NB WB SWB FB NB WB SWB FB NB WB SWB FB + * GC, 12k8 x x x x x x x x x x x x x + * UC, 12k8 x x x x x x + * VC, 12k8 x x x x x x x x x x x x x + * TC, 12k8 x x x x x x x x x x x x x + * GC, 16k x x x x x x x x x x x x + * TC, 16k x x x x x x x x x x x x + * AC(GSC) x x x x x x x x x x x x x + * IC x x x x x x x x x x x x x x x x x x x x x x x x x + * + * GC, 12k8, FS x x x x x x x x x x x x x + * GC, 16k, FS x x x x x x x x x x x + * VC, 12k8, FS x x x x x x x + * TC, 12k8, FS x + * TC, 16k, FS x x x x x x x x x x x + * + * LR MDCT x x x x x x x x x x x + * + *-----------------------------------------------------------------*/ + +void decision_matrix_enc_fx( + Encoder_State_fx *st_fx, /* i : encoder state structure */ + const Word16 sp_aud_decision1, /* i : 1st stage speech/music classification */ + const Word16 sp_aud_decision2, /* i : 2nd stage speech/music classification */ + const Word16 coder_type, /* i : coder type */ + const Word16 vad_flag, + Word16 *hq_core_type /* o : HQ core type */ +) +{ + /* initialization */ + st_fx->core_fx = -1; + move16(); + st_fx->extl_fx = -1; + move16(); + st_fx->extl_brate_fx = 0; + move16(); + *hq_core_type = -1; + move16(); + st_fx->igf = 0; + move16(); + /* SID and FRAME_NO_DATA frames */ + test(); + test(); + IF( st_fx->Opt_DTX_ON_fx && (EQ_32(st_fx->core_brate_fx,SID_2k40)||EQ_32(st_fx->core_brate_fx,FRAME_NO_DATA))) + { + st_fx->core_fx = ACELP_CORE; + move16(); + + test(); + if( GE_32(st_fx->input_Fs_fx,32000)&&GE_16(st_fx->bwidth_fx,SWB)) + { + st_fx->extl_fx = SWB_CNG; + move16(); + } + + st_fx->rf_mode = 0; + move16(); + + return; + } + + st_fx->core_brate_fx = L_deposit_l(0); + + /* SC-VBR */ + IF ( st_fx->Opt_SC_VBR_fx ) + { + /* SC-VBR */ + st_fx->core_fx = ACELP_CORE; + move16(); + st_fx->core_brate_fx = ACELP_7k20; + move32(); + st_fx->total_brate_fx = ACELP_7k20; + move32(); + + test(); + test(); + test(); + IF ( EQ_16(st_fx->ppp_mode_fx,1)) + { + /* PPP mode */ + st_fx->core_brate_fx = PPP_NELP_2k80; + move16(); + } + ELSE IF ( ( ( EQ_16(coder_type,UNVOICED)||EQ_16(coder_type,TRANSITION))&&sp_aud_decision1==0)||NE_16(st_fx->bwidth_fx,NB)) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF ( EQ_16(coder_type,UNVOICED)&&EQ_16(vad_flag,1)&& + ( ( GE_16(st_fx->last_bwidth_fx,SWB) && st_fx->last_Opt_SC_VBR_fx == 1 ) || LT_16(st_fx->last_bwidth_fx, SWB) ) && + ( NE_16(st_fx->last_core_fx,HQ_CORE) || NE_16(st_fx->bwidth_fx, NB) ) ) + { + /* NELP mode */ + st_fx->nelp_mode_fx = 1; + move16(); + st_fx->core_brate_fx = PPP_NELP_2k80; + move32(); + } + ELSE IF ( EQ_16(coder_type,TRANSITION)||(EQ_16(coder_type,UNVOICED)&&NE_16(st_fx->nelp_mode_fx,1))|| + ( ( EQ_16(coder_type,AUDIO) || EQ_16(coder_type,INACTIVE) ) && NE_16(st_fx->bwidth_fx, NB) ) ) + + { + /* silence portions */ + st_fx->core_brate_fx = ACELP_8k00; + move32(); + st_fx->total_brate_fx = ACELP_8k00; + move32(); + } + } + + return; + } + + /*---------------------------------------------------------------------* + * NB + *---------------------------------------------------------------------*/ + + ELSE IF ( EQ_16(st_fx->bwidth_fx,NB)) + { + st_fx->core_fx = ACELP_CORE; + move16(); + + test(); + if ( GE_32(st_fx->total_brate_fx,HQCORE_NB_MIN_RATE)&&EQ_16(sp_aud_decision1,1)) + { + st_fx->core_fx = HQ_CORE; + move16(); + } + } + + /*---------------------------------------------------------------------* + * WB + *---------------------------------------------------------------------*/ + + ELSE IF ( EQ_16(st_fx->bwidth_fx,WB)) + { + st_fx->core_fx = ACELP_CORE; + move16(); + + test(); + test(); + IF ( ( GE_32(st_fx->total_brate_fx,HQCORE_WB_MIN_RATE)&&EQ_16(sp_aud_decision1,1))|| + GE_32(st_fx->total_brate_fx,HQ_96k) ) + { + st_fx->core_fx = HQ_CORE; + move16(); + } + ELSE + { + test(); + test(); + test(); + test(); + IF ( EQ_16(st_fx->bwidth_fx,WB)&<_32(st_fx->total_brate_fx,ACELP_9k60)) + { + st_fx->extl_fx = WB_BWE; + move16(); + } + ELSE IF ( EQ_16(st_fx->bwidth_fx,WB)&&GE_32(st_fx->total_brate_fx,ACELP_9k60)&&LE_32(st_fx->total_brate_fx,ACELP_16k40)) + { + /* Note: WB BWE is used exceptionally at 13.2 kbps if GSC is selected instead of LR-MDCT */ + test(); + test(); + test(); + IF ( EQ_16(sp_aud_decision1,1)||EQ_16(coder_type,INACTIVE)||(sp_aud_decision1==0&&EQ_16(sp_aud_decision2,1))) + { + st_fx->extl_fx = WB_BWE; + move16(); + st_fx->extl_brate_fx = WB_BWE_0k35; + move32(); + } + ELSE + { + st_fx->extl_fx = WB_TBE; + move16(); + st_fx->extl_brate_fx = WB_TBE_1k05; + move32(); + } + } + } + } + + /*---------------------------------------------------------------------* + * SWB and FB + *---------------------------------------------------------------------*/ + + ELSE IF ( EQ_16(st_fx->bwidth_fx,SWB)||EQ_16(st_fx->bwidth_fx,FB)) + { + test(); + test(); + IF ( ( GE_32(st_fx->total_brate_fx,HQCORE_SWB_MIN_RATE)&&EQ_16(sp_aud_decision1,1))|| + GE_32(st_fx->total_brate_fx,HQ_96k) ) + { + st_fx->core_fx = HQ_CORE; + move16(); + } + ELSE + { + st_fx->core_fx = ACELP_CORE; + move16(); + + test(); + test(); + IF ( GE_32(st_fx->total_brate_fx,ACELP_13k20)&<_32(st_fx->total_brate_fx,ACELP_48k)) + { + /* Note: SWB BWE is not used in case of GSC noisy speech */ + /* Note: SWB BWE is used exceptionally at 13.2 kbps if GSC is selected instead of LR-MDCT */ + test(); + test(); + test(); + test(); + IF ( (EQ_16(sp_aud_decision1,1)||EQ_16(coder_type,INACTIVE)||(sp_aud_decision1==0&&EQ_16(sp_aud_decision2,1)))&&st_fx->GSC_noisy_speech_fx==0) + { + st_fx->extl_fx = SWB_BWE; + move16(); + st_fx->extl_brate_fx = SWB_BWE_1k6; + move32(); + + test(); + IF ( EQ_16(st_fx->bwidth_fx,FB)&&GE_32(st_fx->total_brate_fx,ACELP_24k40)) + { + st_fx->extl_fx = FB_BWE; + move16(); + st_fx->extl_brate_fx = FB_BWE_1k8; + move32(); + } + } + ELSE + { + st_fx->extl_fx = SWB_TBE; + move16(); + st_fx->extl_brate_fx = SWB_TBE_1k6; + move32(); + if( GE_32(st_fx->total_brate_fx,ACELP_24k40)) + { + st_fx->extl_brate_fx = SWB_TBE_2k8; + move32(); + } + + test(); + IF ( EQ_16(st_fx->bwidth_fx,FB)&&GE_32(st_fx->total_brate_fx,ACELP_24k40)) + { + st_fx->extl_fx = FB_TBE; + move16(); + { + st_fx->extl_brate_fx = FB_TBE_3k0; + move32(); + } + } + } + } + ELSE IF ( GE_32(st_fx->total_brate_fx,ACELP_48k)) + { + st_fx->extl_fx = SWB_BWE_HIGHRATE; + move16(); + st_fx->extl_brate_fx = SWB_BWE_16k; + move32(); + + if( EQ_16(st_fx->bwidth_fx,FB)) + { + st_fx->extl_fx = FB_BWE_HIGHRATE; + move32(); + } + } + } + } + + /*-----------------------------------------------------------------* + * Set HQ core type + *-----------------------------------------------------------------*/ + + IF( EQ_16(st_fx->core_fx,HQ_CORE)) + { + *hq_core_type = NORMAL_HQ_CORE; + move16(); + + test(); + test(); + IF( (EQ_16(st_fx->bwidth_fx,SWB)||EQ_16(st_fx->bwidth_fx,WB))&&LE_32(st_fx->total_brate_fx,LRMDCT_CROSSOVER_POINT)) + { + /* note that FB is always coded with NORMAL_HQ_CORE */ + *hq_core_type = LOW_RATE_HQ_CORE; + move16(); + } + ELSE IF( EQ_16(st_fx->bwidth_fx,NB)) + { + *hq_core_type = LOW_RATE_HQ_CORE; + move16(); + } + } + + /* set core bitrate */ + st_fx->core_brate_fx = L_sub(st_fx->total_brate_fx, st_fx->extl_brate_fx); + + IF ( st_fx->ini_frame_fx == 0 ) + { + /* avoid switching in the very first frame */ + st_fx->last_core_fx = st_fx->core_fx; + move16(); + st_fx->last_core_brate_fx = st_fx->core_brate_fx; + move32(); + st_fx->last_extl_fx = st_fx->extl_fx; + move16(); + } + + return; +} + +/*---------------------------------------------------------------------* + * signalling_mode1_tcx20_enc() + * + * write MODE1 TCX20 signalling information into the bit-stream + *---------------------------------------------------------------------*/ + +Word16 signalling_mode1_tcx20_enc( + Encoder_State_fx *st, /* i : encoder state structure */ + Word16 push +) +{ + Word16 num_bits; + Word16 nBits, idx, start_idx; + + assert(st->core_fx == TCX_20_CORE); + + num_bits = 0; + move16(); + + /* Use ACELP signaling for LR MDCT */ + IF ( LE_32(st->total_brate_fx, ACELP_16k40)) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + idx = 0; + move16(); + WHILE ( NE_32(acelp_sig_tbl[idx], st->total_brate_fx)) + { + idx = add(idx, 1); + } + + /* retrieve the number of bits for signalling */ + idx = add(idx, 1); + nBits = extract_l(acelp_sig_tbl[idx]); + + /* retrieve the signalling index */ + idx = add(idx, 1); + start_idx = idx; + move16(); + WHILE ( NE_32(acelp_sig_tbl[idx], SIG2IND_fx(LR_MDCT, st->bwidth_fx, 0, 0))) + { + idx = add(idx, 1); + } + + num_bits = add(num_bits, nBits); + IF (push != 0) + { + push_indice_fx( st, IND_ACELP_SIGNALLING, sub(idx, start_idx), nBits ); + } + + /* HQ/TCX core switching flag */ + num_bits = add(num_bits, 1); + IF (push != 0) + { + push_indice_fx( st, IND_MDCT_CORE, 1, 1 ); + } + } + ELSE + { + IF ( LE_32(st->core_brate_fx, ACELP_64k)) + { + /* write ACELP/HQ core indication flag */ + num_bits = add(num_bits, 1); + IF (push != 0) + { + push_indice_fx( st, IND_CORE, 1, 1 ); + } + } + + /* HQ/TCX core switching flag */ + num_bits = add(num_bits, 1); + IF (push != 0) + { + push_indice_fx( st, IND_MDCT_CORE, 1, 1 ); + } + + num_bits = add(num_bits, 2); + IF (push != 0) + { + /* write band-width (needed for different I/O sampling rate support) */ + IF ( EQ_16(st->bwidth_fx, NB)) + { + push_indice_fx( st, IND_HQ_BWIDTH, 0, 2 ); + } + ELSE IF ( EQ_16(st->bwidth_fx, WB)) + { + push_indice_fx( st, IND_HQ_BWIDTH, 1, 2 ); + } + ELSE IF ( EQ_16(st->bwidth_fx, SWB)) + { + push_indice_fx( st, IND_HQ_BWIDTH, 2, 2 ); + } + ELSE /* st->bwidth == FB */ + { + push_indice_fx( st, IND_HQ_BWIDTH, 3, 2 ); + } + } + } + + return num_bits; +} + +/*---------------------------------------------------------------------* + * signalling_enc() + * + * write signalling information into the bit-stream + *---------------------------------------------------------------------*/ + +void signalling_enc_fx( + Encoder_State_fx *st_fx, /* i : encoder state structure */ + const Word16 coder_type, /* i : coder type */ + const Word16 sharpFlag /* i : formant sharpening flag */ +) +{ + Word16 nBits, idx, start_idx; + Word32 k; + + IF (EQ_16(st_fx->mdct_sw, MODE2)) + { + + assert(!st_fx->tcxonly); + assert(st_fx->core_fx == HQ_CORE); + + push_next_indice_fx(st_fx, 1, 1); /* TCX */ + push_next_indice_fx(st_fx, 1, 1); /* HQ_CORE */ + + /* write ACELP->HQ core switching flag */ + test(); + IF ( EQ_16(st_fx->last_core_fx, ACELP_CORE)||EQ_16(st_fx->last_core_fx,AMR_WB_CORE)) + { + push_indice_fx( st_fx, IND_HQ_SWITCHING_FLG, 1, 1 ); + + /* write ACELP L_frame info */ + IF( EQ_16(st_fx->last_L_frame_fx, L_FRAME)) + { + push_indice_fx( st_fx, IND_LAST_L_FRAME, 0, 1 ); + } + ELSE + { + push_indice_fx( st_fx, IND_LAST_L_FRAME, 1, 1 ); + } + } + ELSE + { + push_indice_fx( st_fx, IND_HQ_SWITCHING_FLG, 0, 1 ); + } + + return; + } + IF( EQ_16(st_fx->core_fx,ACELP_CORE )) + { + + test(); + test(); + IF( EQ_16(st_fx->ppp_mode_fx,1)||EQ_16(st_fx->nelp_mode_fx,1)) + { + + /* 1 bit to distinguish between 2.8kbps PPP/NELP frame and SID frame */ + push_indice_fx( st_fx, IND_CORE, 0, 1 ); + /* SC-VBR: 0 - PPP_NB, 1 - PPP_WB, 2 - NELP_NB, 3 - NELP_WB */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF ( EQ_16(coder_type,VOICED)&&EQ_16(st_fx->bwidth_fx,NB)&&EQ_16(st_fx->ppp_mode_fx,1)) + { + push_indice_fx( st_fx, IND_PPP_NELP_MODE, 0, 2 ); + } + ELSE IF ( EQ_16(coder_type,VOICED)&&NE_16(st_fx->bwidth_fx,NB)&&EQ_16(st_fx->ppp_mode_fx,1)) + { + push_indice_fx( st_fx, IND_PPP_NELP_MODE, 1, 2 ); + } + ELSE IF ( EQ_16(coder_type,UNVOICED)&&EQ_16(st_fx->bwidth_fx,NB)&&EQ_16(st_fx->nelp_mode_fx,1)) + { + push_indice_fx( st_fx, IND_PPP_NELP_MODE, 2, 2); + } + ELSE IF ( EQ_16(coder_type,UNVOICED)&&NE_16(st_fx->bwidth_fx,NB)&&EQ_16(st_fx->nelp_mode_fx,1)) + { + push_indice_fx( st_fx, IND_PPP_NELP_MODE, 3, 2 ); + } + } + ELSE IF( NE_32(st_fx->core_brate_fx,SID_2k40)&&NE_32(st_fx->core_brate_fx,FRAME_NO_DATA)) + { + /* write the ACELP/HQ core selection bit */ + IF (GE_32(st_fx->total_brate_fx,ACELP_24k40)) + { + push_indice_fx( st_fx, IND_CORE, 0, 1 ); + } + + /* find the section in the ACELP signalling table corresponding to bitrate */ + idx = 0; + WHILE ( NE_32(acelp_sig_tbl[idx],st_fx->total_brate_fx)) + { + idx++; + } + + /* retrieve the number of bits for signalling */ + nBits = (short) acelp_sig_tbl[++idx]; + + /* retrieve the signalling index */ + start_idx = ++idx; + k = SIG2IND_fx(coder_type, st_fx->bwidth_fx, sharpFlag, st_fx->rf_mode); + WHILE( NE_32(acelp_sig_tbl[idx], k)) + { + idx++; + } + + push_indice_fx( st_fx, IND_ACELP_SIGNALLING, idx - start_idx, nBits ); + } + + /* write extension layer flag to distinguish between TBE (0) and BWE (1) */ + IF( st_fx->extl_brate_fx > 0 ) + { + test(); + test(); + test(); + test(); + IF( EQ_16(st_fx->extl_fx,WB_TBE)||EQ_16(st_fx->extl_fx,SWB_TBE)||EQ_16(st_fx->extl_fx,FB_TBE)) + { + push_indice_fx( st_fx, IND_BWE_FLAG, 0, 1 ); + } + ELSE IF( EQ_16(st_fx->extl_fx,WB_BWE)||EQ_16(st_fx->extl_fx,SWB_BWE)||EQ_16(st_fx->extl_fx,FB_BWE)) + { + push_indice_fx( st_fx, IND_BWE_FLAG, 1, 1 ); + } + } + } + ELSE /* HQ core */ + { + /* write ACELP->HQ switching frame flag */ + test(); + IF( EQ_16(st_fx->last_core_fx,ACELP_CORE)||EQ_16(st_fx->last_core_fx,AMR_WB_CORE)) + { + push_indice_fx( st_fx, IND_HQ_SWITCHING_FLG, 1, 1 ); + /* write ACELP L_frame info */ + IF( EQ_16(st_fx->last_L_frame_fx, L_FRAME)) + { + push_indice_fx( st_fx, IND_LAST_L_FRAME, 0, 1 ); + } + ELSE + { + push_indice_fx( st_fx, IND_LAST_L_FRAME, 1, 1 ); + } + } + ELSE + { + push_indice_fx( st_fx, IND_HQ_SWITCHING_FLG, 0, 1 ); + } + + /* HQ/TCX core switching flag */ + push_indice_fx( st_fx, IND_MDCT_CORE, 0, 1 ); + + /* Use ACELP signaling for LR MDCT */ + IF ( LE_32(st_fx->total_brate_fx,ACELP_16k40)) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + idx = 0; + WHILE ( NE_32(acelp_sig_tbl[idx],st_fx->total_brate_fx)) + { + idx++; + } + + /* retrieve the number of bits for signalling */ + nBits = extract_l(acelp_sig_tbl[++idx]); + + /* retrieve the signalling index */ + start_idx = ++idx; + move16(); + k = SIG2IND_fx(LR_MDCT, st_fx->bwidth_fx, 0, 0); + WHILE( NE_32(acelp_sig_tbl[idx], k)) + { + idx++; + } + + push_indice_fx( st_fx, IND_ACELP_SIGNALLING, idx - start_idx, nBits ); + } + ELSE + { + + IF( LE_32(st_fx->core_brate_fx,ACELP_64k)) + { + /* write ACELP/HQ core indication flag */ + push_indice_fx( st_fx, IND_CORE, 1, 1 ); + } + + /* write band-width (needed for different I/O sampling rate support) */ + IF( EQ_16(st_fx->bwidth_fx,NB)) + { + push_indice_fx( st_fx, IND_HQ_BWIDTH, 0, 2 ); + } + ELSE IF( EQ_16(st_fx->bwidth_fx,WB)) + { + push_indice_fx( st_fx, IND_HQ_BWIDTH, 1, 2 ); + } + ELSE IF( EQ_16(st_fx->bwidth_fx,SWB)) + { + push_indice_fx( st_fx, IND_HQ_BWIDTH, 2, 2 ); + } + ELSE /* st_fx->bwidth_fx == FB */ + { + push_indice_fx( st_fx, IND_HQ_BWIDTH, 3, 2 ); + } + } + } + + return; +} + +/*---------------------------------------------------------------------* + * signalling_enc_rf() + * + * write channel-aware signalling information into the bit-stream + *---------------------------------------------------------------------*/ + +void signalling_enc_rf( + Encoder_State_fx *st /* i : encoder state structure */ +) +{ + Word16 i, tmp_rf; + Word16 sfr; + + + /* write partial copy into bitstream */ + IF(EQ_16(st->rf_mode,1)) + { + enc_prm_rf(st, st->rf_indx_frametype[st->rf_fec_offset], st->rf_fec_offset); + st->rf_indx_tbeGainFr[0] = st->rf_bwe_gainFr_ind; + } + + /* Shift the RF indices such that the partial copy associated with + (n-fec_offset)th frame is included in the bitstream in nth frame. */ + tmp_rf = st->rf_fec_offset; + + FOR(i = tmp_rf; i >= 0 ; i--) + { + /* rf frame type */ + st->rf_indx_frametype[i+1] = st->rf_indx_frametype[i]; + /* rf target bits buffer */ + st->rf_targetbits_buff[i+1] = st->rf_targetbits_buff[i]; + + /* lsf indx */ + st->rf_indx_lsf[i+1][0] = st->rf_indx_lsf[i][0]; + st->rf_indx_lsf[i+1][1] = st->rf_indx_lsf[i][1]; + st->rf_indx_lsf[i+1][2] = st->rf_indx_lsf[i][2]; + + /* ES pred energy */ + st->rf_indx_EsPred[i+1] = st->rf_indx_EsPred[i]; + + /* LTF mode, sfr params: pitch, fcb and gain */ + FOR(sfr = 0; sfr < st->nb_subfr; sfr++) + { + st->rf_indx_ltfMode[i+1][sfr] = st->rf_indx_ltfMode[i][sfr]; + st->rf_indx_pitch[i+1][sfr] = st->rf_indx_pitch[i][sfr]; + st->rf_indx_fcb[i+1][sfr] = st->rf_indx_fcb[i][sfr]; + st->rf_indx_gain[i+1][sfr] = st->rf_indx_gain[i][sfr]; + } + + /* shift the nelp indices */ + st->rf_indx_nelp_iG1[i+1] = st->rf_indx_nelp_iG1[i]; + st->rf_indx_nelp_iG2[i+1][0] = st->rf_indx_nelp_iG2[i][0]; + st->rf_indx_nelp_iG2[i+1][1] = st->rf_indx_nelp_iG2[i][1]; + st->rf_indx_nelp_fid[i+1] = st->rf_indx_nelp_fid[i]; + + /* tbe gain Fr shift */ + st->rf_indx_tbeGainFr[i+1] = st->rf_indx_tbeGainFr[i]; + st->rf_clas[i+1] = st->rf_clas[i]; + st->rf_gain_tcx[i+1] = st->rf_gain_tcx[i]; + st->rf_tcxltp_param[i+1] = st->rf_tcxltp_param[i]; + } + + return; +} + + diff --git a/lib_enc/detect_transient_fx.c b/lib_enc/detect_transient_fx.c new file mode 100644 index 0000000..8fc3db5 --- /dev/null +++ b/lib_enc/detect_transient_fx.c @@ -0,0 +1,352 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required for wmc_tool */ + +/*--------------------------------------------------------------------------*/ +/* Function hp_filter */ +/* ~~~~~~~~~~~~~~~~~~~~ */ +/* */ +/* High pass filter */ +/*--------------------------------------------------------------------------*/ +/* float x (i) in Q_new input to filter */ +/* float y (o) in Q_new +2 output of filter */ +/* float *oldy (i/o) previous output of filter */ +/* float *oldx (i/o) in Q_memx previous input of filter */ +/* short L (i) in Q_memx +2 length (32 or 48 kHz) */ +/*--------------------------------------------------------------------------*/ + +static void hp_filter_fx( + const Word16 *x, /*Q_new */ + Word16 *y, /*Q_new */ + Word16 *oldy, /*Q_new */ + Word16 *oldx, /*Q_new */ + const Word16 L +) +{ + Word16 i; + Word32 L_tmp; + + + /*y[0] = 0.4931f * *oldy + 0.7466f*(x[0] - *oldx); */ + L_tmp = L_mult(sub(x[0],*oldx),24465);/*Q_new+16 */ + L_tmp = L_mac(L_tmp,*oldy,16158);/*Q_new+16 */ + y[0] = round_fx(L_tmp);/*Q_new */ + + FOR (i = 1; i < L; i++) + { + /*y[i] = 0.4931f*y[i-1] + 0.7466f*(x[i] - x[i-1]); */ + L_tmp = L_mult(sub(x[i],x[i-1]),24465);/*Q_new+16 */ + L_tmp = L_mac(L_tmp,y[i-1],16158);/*Q_new+16 */ + y[i] = round_fx(L_tmp); /*Q_new */ + } + + *oldx = x[L - 1]; + move16();/*Q_new */ + *oldy = y[L - 1]; + move16();/*Q_new */ + +} +/*--------------------------------------------------------------------------*/ +/* Function detect_transient */ +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +/* */ +/* Detect if the signal is a transient */ +/*--------------------------------------------------------------------------*/ +/* float in[] (i) input signal Q_new */ +/* Encoder_State *st (i/o) state of coder */ +/* short L (i) length (32 or 48 kHz) */ +/*--------------------------------------------------------------------------*/ +/* short return (o) result of transient check */ +/*--------------------------------------------------------------------------*/ + +Word16 detect_transient_fx( + const Word16 *in_fx, /*Q_new */ + /*Encoder_State *st, */ + const Word16 L, + const Word16 coder_type , /* i : coder type */ + Word16 Q_new, + Encoder_State_fx *st_fx +) +{ + Word32 Energy,L_tmp; + Word32 EnergyLT; + Word16 i, blk; + Word16 IsTransient; + Word16 out_filt_fx[L_FRAME48k]; + Word16 position = 0; + Word16 thr; + Word32 L_tmp2; + Word16 shift; + Word32 Energy_fx, E_in_fx = 0, E_out_fx = 0, Energy_in_fx[5] = {0,0,0,0,0}; /* Energy_fx can be replaced by Energy */ + Word32 E_low_fx, E_high_fx; + Word16 temp16, Thres_fx = 0; + Word16 exp; + + shift = 0; + move16(); + + IsTransient = 0; + move16(); + IF (NE_16(st_fx->last_extl_fx, st_fx->extl_fx)) + { + st_fx->TransientHangOver_fx = 0; + move16(); + st_fx->old_hpfilt_in_fx = 0; + move16(); + st_fx->old_hpfilt_out_fx = 0; + move16(); + } + + /* High pass filter */ + hp_filter_fx(in_fx, out_filt_fx, &(st_fx->old_hpfilt_in_fx), &(st_fx->old_hpfilt_out_fx), L); + + /* Long term energy */ + test(); + test(); + test(); + IF (NE_16(st_fx->last_extl_fx, st_fx->extl_fx)||(EQ_16(st_fx->last_extl_fx,st_fx->extl_fx)&&NE_16(st_fx->last_core_fx,st_fx->core_fx))||EQ_16(st_fx->last_codec_mode,MODE2)) + { + /*EnergyLT = EPSILON_FX; */ + EnergyLT = L_deposit_l(0); + FOR (i = 0; i < L/4; i++) + { + /*EnergyLT += out_filt[i] * out_filt[i]; */ + EnergyLT = L_mac0(EnergyLT, out_filt_fx[i], out_filt_fx[i]); /*2Q_new */ + } + } + ELSE + { + EnergyLT = L_add(st_fx->EnergyLT_fx, 0); /*2Q_new */ + } + IF (EQ_16(L, L_FRAME8k)) + { + Energy_in_fx[0] = st_fx->Energy_Old_fx; + move32(); + /* Compute block energy */ + FOR ( blk = 0; blk < 4; blk++ ) + { + Energy_fx = L_deposit_l(0); + Energy_in_fx[blk + 1] = L_deposit_l(0); + FOR ( i = 0; i < L/4; i++ ) + { + temp16 = extract_l(L_shr(out_filt_fx[i + blk*(L/4)], 12)); + Energy_fx = L_add(Energy_fx, L_mult0(temp16, temp16)); + temp16 = shr(in_fx[i + blk*(L/4)], Q_new); + Energy_in_fx[blk+1] = L_add(Energy_in_fx[blk+1], L_mult0(temp16, temp16)); + move32(); + } + + E_in_fx = L_add(E_in_fx, Energy_in_fx[blk + 1]); + E_out_fx = L_add(E_out_fx, Energy_fx); + + Thres_fx = 2185;/*1 /15 */ + move16(); + IF (GT_32(Mult_32_16(Energy_fx, 5461), EnergyLT)) + { + IsTransient = 1; + move16(); + position = blk; + move16(); + } + + EnergyLT = L_add(Mult_32_16(EnergyLT, 24576), Mult_32_16(Energy_fx, 8192)); + } + } + ELSE + { + /* Compute block energy */ + FOR ( blk = 0; blk < 4; blk++ ) + { + L_tmp = L_deposit_l(0); + FOR ( i = 0; i < L/8; i++ ) + { + /*Energy += out_filt_fx[i + blk*(L/4)] * out_filt_fx[i + blk*(L/4)]; */ + L_tmp = L_mac0(L_tmp, out_filt_fx[i + blk*(L/4)], out_filt_fx[i + blk*(L/4)]); /*2Q_new */ + } + L_tmp2 = L_deposit_l(0); + FOR (; i < L/4; i++ ) + { + /*Energy += out_filt_fx[i + blk*(L/4)] * out_filt_fx[i + blk*(L/4)]; */ + L_tmp2 = L_mac0(L_tmp2, out_filt_fx[i + blk*(L/4)], out_filt_fx[i + blk*(L/4)]); /*2Q_new */ + } + Overflow = 0; + move16(); + Energy = L_add(L_tmp, L_tmp2); + shift = 0; + if (Overflow != 0) + { + shift = 1; + move16(); + } + Overflow = 0; + move16(); + + Energy = L_add(L_shr(L_tmp, shift), L_shr(L_tmp2, shift)); + + test(); + IF( EQ_16(st_fx->extl_fx,SWB_BWE)||EQ_16(st_fx->extl_fx,FB_BWE)) + { + /*Calculate shift to get to Q0*/ + test(); + test(); + IF((GT_32(Mult_32_16(Energy, shl(2427, shift)), EnergyLT))||(GT_32(Mult_32_16(Energy,shl(3277,shift)),EnergyLT)&&EQ_16(coder_type,INACTIVE))) + { + IsTransient = 1; + move16(); + position = blk; + move16(); + } + } + ELSE + { + test(); + IF( LE_32(st_fx->total_brate_fx,HQ_16k40)&&EQ_16(st_fx->bwidth_fx,SWB)) + { + thr = 2427; + move16(); + } + ELSE + { + thr = 5461; + move16(); + } + thr = shl(thr, shift); + /*if(Energy > L_shr(Mult_32_16(EnergyLT,22624),shift_cnt)) //getting in Q0 32*16 = Q_inp1+Q_inp2+1-16 */ + IF(GT_32(Mult_32_16(Energy, thr),EnergyLT)) + /*if(Energy > 6.0f * EnergyLT) */ + { + IsTransient = 1; + move16(); + position = blk; + move16(); + } + } + /*EnergyLT = 0.75f*EnergyLT + 0.25f*Energy; */ + /*0.75f*EnergyLT in Q0 //0.25f*Energy in Q0 */ + EnergyLT = L_add(Mult_32_16(EnergyLT,24576),Mult_32_16(Energy, shl(8192, shift))); /*2Q_new */ + } + } + st_fx->EnergyLT_fx = EnergyLT; + move32(); + + test(); + test(); + test(); + test(); + test(); + if( ( NE_16(st_fx->last_extl_fx,SWB_BWE)&&NE_16(st_fx->last_extl_fx,SWB_TBE)&&EQ_16(st_fx->extl_fx,SWB_BWE))|| + ( NE_16(st_fx->last_extl_fx,FB_BWE) && NE_16(st_fx->last_extl_fx,FB_TBE) && EQ_16(st_fx->extl_fx,FB_BWE) ) ) + { + IsTransient = 0; + move16(); + } + + test(); + IF ( IsTransient && L == L_FRAME8k ) + { + blk = 0; + move16(); + E_low_fx = L_deposit_l(0); + FOR (i=0; icore_brate_fx,ACELP_24k40)) + { + test(); + IF ( NE_16(st_fx->last_core_fx,HQ_CORE)||NE_32(st_fx->last_core_brate_fx,ACELP_24k40)) + { + st_fx->TransientHangOver_fx = 0; + move16(); + IsTransient = 0; + move16(); + } + ELSE + { + IF ( IsTransient ) + { + IF ( EQ_16(position,3)) + { + /* Set Hangover */ + st_fx->TransientHangOver_fx = 1; + move16(); + } + } + ELSE + { + IF ( st_fx->TransientHangOver_fx ) + { + st_fx->TransientHangOver_fx = 0; + move16(); + IsTransient = 1; + move16(); + } + } + } + } + ELSE + { + IF ( IsTransient ) + { + st_fx->TransientHangOver_fx = 1; + move16(); + } + ELSE + { + IF( st_fx->TransientHangOver_fx ) + { + st_fx->TransientHangOver_fx = 0; + move16(); + IsTransient = 1; + move16(); + } + } + } + + IF (EQ_16(L, L_FRAME8k)) + { + st_fx->Energy_Old_fx = Energy_in_fx[4]; + move32(); + } + + return IsTransient; +} diff --git a/lib_enc/diffcod_fx.c b/lib_enc/diffcod_fx.c new file mode 100644 index 0000000..79869f2 --- /dev/null +++ b/lib_enc/diffcod_fx.c @@ -0,0 +1,142 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function Prototypes */ +#include "stl.h" + +/*--------------------------------------------------------------------------*/ +/* Function diffcod */ +/* ~~~~~~~~~~~~~~~~~ */ +/* */ +/* Differential coding for indices of quantized norms */ +/*--------------------------------------------------------------------------*/ +/* Word16 N (i) number of sub-vectors */ +/* Word16 *y (i/o) indices of quantized norms */ +/* Word16 *difidx (o) differential code */ +/*--------------------------------------------------------------------------*/ + +void diffcod_fx( + const Word16 N, /* (i) number of sub-vectors */ + Word16 *y, /* (i/o) indices of quantized norms */ + Word16 *difidx /* (o) differential code */ +) +{ + Word16 i, k, r; + + FOR (i=N-1; i>0; i--) + { + r = sub(i, 1); + k = sub(y[i], y[r]); + if ( LT_16(k, -15)) + { + y[r] = add(y[i], 15); + move16(); + } + } + + FOR (i=1; i0; i--) + { + r = sub(i, 1); + k = sub(y[i], y[r]); + move16(); + if ( LT_16(k, thr_l)) + { + y[r] = sub(y[i], thr_l); + move16(); + } + } + + FOR (i=1; iini_frame_fx == 0 ) + { + st_fx->active_fr_cnt_fx = CNG_TYPE_HO; + move16(); + + st_fx->cng_type_fx = FD_CNG; + move16(); + test(); + if( EQ_16( st_fx->codec_mode, MODE1 )||st_fx->Opt_AMR_WB_fx) + { + st_fx->cng_type_fx = LP_CNG; + move16(); + } + } + test(); + test(); + IF( st_fx->Opt_DTX_ON_fx && vad == 0 && + GT_16(st_fx->ini_frame_fx,2) && /* CNG coding starts after 2 frames */ + st_fx->fd_cng_reset_flag == 0 && + NE_16(st_fx->last_core_fx, AMR_WB_CORE) && + st_fx->Opt_AMR_WB_fx == 0 ) + { + test(); + test(); + test(); + test(); + test(); + IF ( GT_32(st_fx->last_core_brate_fx,SID_2k40)&& + NE_32(st_fx->last_total_brate_cng_fx,-1) && + NE_32(st_fx->last_total_brate_cng_fx,st_fx->total_brate_fx) && + ( (LE_32(st_fx->last_total_brate_cng_fx, ACELP_24k40) ) || (LT_16(st_fx->lp_noise_fx, 1280) ) ) ) + { + st_fx->total_brate_fx = st_fx->last_total_brate_cng_fx; + move32(); + test(); + if( !(EQ_32(st_fx->total_brate_fx,ACELP_7k20)&&st_fx->Opt_SC_VBR_fx)) + { + st_fx->Opt_SC_VBR_fx = 0; + move16(); + } + st_fx->rf_mode = st_fx->last_rf_mode_cng; + move16(); + st_fx->bwidth_fx = st_fx->last_bwidth_cng_fx; + move16(); + st_fx->codec_mode = st_fx->last_codec_mode_cng; + move16(); + } + test(); + test(); + test(); + test(); + test(); + IF ( LE_32(st_fx->last_core_brate_fx,SID_2k40)&& + NE_32(st_fx->last_total_brate_fx,st_fx->total_brate_fx)&& + ( LE_32(st_fx->last_total_brate_fx,ACELP_24k40) || LT_16(st_fx->lp_noise_fx, 1280) ) ) + + { + st_fx->total_brate_fx = st_fx->last_total_brate_fx; + move32(); + test(); + if( !(EQ_32(st_fx->total_brate_fx,ACELP_7k20)&&st_fx->Opt_SC_VBR_fx)) + { + st_fx->Opt_SC_VBR_fx = 0; + move16(); + } + + st_fx->Opt_RF_ON = 0; + move16(); + test(); + test(); + test(); + if( st_fx->rf_mode && st_fx->rf_fec_offset > 0 && EQ_32(st_fx->total_brate_fx,ACELP_13k20)&&NE_16(st_fx->bwidth_fx,NB)) + { + st_fx->Opt_RF_ON = 1; + move16(); + } + st_fx->rf_mode = st_fx->Opt_RF_ON; + move16(); + st_fx->bwidth_fx = st_fx->last_bwidth_fx; + move32(); + SWITCH ( st_fx->total_brate_fx ) + { + case 5900: + st_fx->codec_mode = MODE1; + move16(); + BREAK; + case 7200: + st_fx->codec_mode = MODE1; + move16(); + BREAK; + case 8000: + st_fx->codec_mode = MODE1; + move16(); + BREAK; + case 9600: + st_fx->codec_mode = MODE2; + move16(); + BREAK; + case 13200: + st_fx->codec_mode = MODE1; + move16(); + BREAK; + case 16400: + st_fx->codec_mode = MODE2; + move16(); + BREAK; + case 24400: + st_fx->codec_mode = MODE2; + move16(); + BREAK; + case 32000: + st_fx->codec_mode = MODE1; + move16(); + BREAK; + case 48000: + st_fx->codec_mode = MODE2; + move16(); + BREAK; + case 64000: + st_fx->codec_mode = MODE1; + move16(); + BREAK; + case 96000: + st_fx->codec_mode = MODE2; + move16(); + BREAK; + case 128000: + st_fx->codec_mode = MODE2; + move16(); + BREAK; + } + } + } + + /*------------------------------------------------------------------------* + * Select SID or FRAME_NO_DATA frame if DTX is enabled + *------------------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + test(); + IF( st_fx->Opt_DTX_ON_fx && vad == 0 && + GT_16(st_fx->ini_frame_fx,2) && /* CNG coding starts after 2 frames */ + ( LE_32(st_fx->total_brate_fx,ACELP_24k40) || LT_16(st_fx->lp_noise_fx, 1280)) && + st_fx->fd_cng_reset_flag == 0 ) + { + /* reset counter */ + st_fx->active_fr_cnt_fx = 0; + move16(); + + IF( st_fx->Opt_AMR_WB_fx ) + { + st_fx->last_total_brate_cng_fx = -1; + st_fx->last_rf_mode_cng = st_fx->rf_mode; + move16(); + } + ELSE + { + st_fx->last_total_brate_cng_fx = st_fx->total_brate_fx; + st_fx->last_bwidth_cng_fx = st_fx->bwidth_fx; + st_fx->last_codec_mode_cng = st_fx->codec_mode; + } + + IF( st_fx->cnt_SID_fx == 0 ) + { + /* this will be a SID frame */ + IF ( st_fx->Opt_AMR_WB_fx ) + { + st_fx->core_brate_fx = SID_1k75; + move32(); + } + ELSE + { + st_fx->core_brate_fx = SID_2k40; + move32(); + } + } + ELSE + { + /* this will be a no data frame */ + st_fx->core_brate_fx = FRAME_NO_DATA; + move32(); + } + + test(); + test(); + IF( EQ_32(st_fx->core_brate_fx,FRAME_NO_DATA)&&NE_16(st_fx->last_core_fx,ACELP_CORE)&&!st_fx->Opt_AMR_WB_fx) + { + /* force SID frame when switching from HQ core or AMR-WB IO mode into inactive frame in ACELP core when DTX is on */ + st_fx->core_brate_fx = SID_2k40; + move32(); + } + + test(); + IF( EQ_16(st_fx->cng_type_fx,FD_CNG)&&LE_32(st_fx->total_brate_fx,ACELP_24k40)) /* at highest bit-rates, use exclusively LP_CNG */ + { + test(); + test(); + IF ( EQ_32(st_fx->total_brate_fx,ACELP_9k60)||EQ_32(st_fx->total_brate_fx,ACELP_16k40)||EQ_32(st_fx->total_brate_fx,ACELP_24k40)) + { + st_fx->codec_mode = MODE2; + move16(); + } + } + ELSE + { + st_fx->cng_type_fx = LP_CNG; + move16(); + IF ( st_fx->codec_mode == MODE2 ) + { + st_fx->lp_cng_mode2 = 1; + move16(); + } + st_fx->codec_mode = MODE1; + move16(); + } + + + } + + /*------------------------------------------------------------------------* + * Reset counters when in active frame (not in SID or FRAME_NO_DATA frame) + *------------------------------------------------------------------------*/ + /* NB core bit rate can be "-1" at startup , so one can not use core_brate_fx <=2400 */ + test(); + test(); + IF ( (NE_32(st_fx->core_brate_fx ,SID_2k40))&&(NE_32(st_fx->core_brate_fx,SID_1k75))&&(st_fx->core_brate_fx!=0)) + { + st_fx->cnt_SID_fx = 0; + move16(); + + /* change SID update rate */ + /* first SID update is only 8 (3) frames after the active speech end */ + IF( !st_fx->Opt_AMR_WB_fx ) + { + st_fx->max_SID_fx = FIXED_SID_RATE; + move16(); + } + ELSE + { + st_fx->max_SID_fx = 3; + move16(); /* first SID update is only 3 frames after the active speech end */ + } + + IF ( LT_16(st_fx->interval_SID_fx,st_fx->max_SID_fx)) + { + st_fx->max_SID_fx = st_fx->interval_SID_fx; + move16();/* change SID update rate */ + } + + st_fx->cng_cnt_fx = 0; + move16(); /* reset the counter of CNG frames for averaging */ + + test(); + IF( GE_16(st_fx->active_fr_cnt_fx,CNG_TYPE_HO)&&st_fx->Opt_AMR_WB_fx==0) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_16(st_fx->cng_type_fx,LP_CNG)&&((EQ_16(st_fx->input_bwidth_fx,NB)&>_32(st_fx->bckr_tilt_lt,589824l/*9.f Q16*/))||(GT_16(st_fx->input_bwidth_fx,NB)&>_32(st_fx->bckr_tilt_lt,2949120l/*45.f Q16*/)))) + { + st_fx->cng_type_fx = FD_CNG; + move16(); + } + ELSE IF( EQ_16(st_fx->cng_type_fx,FD_CNG)&&((EQ_16(st_fx->input_bwidth_fx,NB)&<_32(st_fx->bckr_tilt_lt,131072l/*2.f Q16*/))||(GT_16(st_fx->input_bwidth_fx,NB)&<_32(st_fx->bckr_tilt_lt,655360l/*10.f Q16*/)))) + { + st_fx->cng_type_fx = LP_CNG; + move16(); + } + st_fx->last_total_brate_cng_fx = -1; + } + ELSE IF( st_fx->Opt_AMR_WB_fx ) + { + st_fx->cng_type_fx = LP_CNG; + move16(); + } + st_fx->active_fr_cnt_fx = add( st_fx->active_fr_cnt_fx, 1 ); + st_fx->active_fr_cnt_fx = s_min(st_fx->active_fr_cnt_fx, 200); + } + + /*------------------------------------------------------------------------* + * Update speech and background noise long-term energy + *------------------------------------------------------------------------*/ + + st_fx->frame_ener_fx = L_deposit_l(0); + + IF ( st_fx->Opt_DTX_ON_fx ) + { + Q_speech2 = add(shl(Q_speech, 1), 7); + FOR (j=0; j<16; j++) + { + L_tmp = L_mult0(*speech, *speech); + speech++; + FOR (i = 1; i< L_FRAME/16; i++) + { + L_tmp = L_mac0(L_tmp, *speech, *speech); + speech++; + } + st_fx->frame_ener_fx = L_add(st_fx->frame_ener_fx, L_shr(L_tmp, Q_speech2));/*Q(-7) */ + } + + /* Active speech (voiced) */ + + IF ( EQ_16(st_fx->clas_fx,VOICED_CLAS)) + { + alpha = ALPHA_ENER_SLOW_FX; + move16(); + if ( GT_32(st_fx->frame_ener_fx,st_fx->lt_ener_voiced_fx)) + { + alpha = ALPHA_ENER_FAST_FX; + move16();/*Q15 */ + } + + /*st_fx->lt_ener_voiced_fx = alpha * st_fx->lt_ener_voiced_fx + (1.0f-alpha) * st_fx->frame_ener_fx;*/ + L_tmp = L_sub(st_fx->lt_ener_voiced_fx, st_fx->frame_ener_fx); + L_tmp = Mult_32_16(L_tmp, alpha); + st_fx->lt_ener_voiced_fx = L_add(L_tmp, st_fx->frame_ener_fx); /*Q(-7) */ + + st_fx->VarDTX_cnt_voiced_fx = add(st_fx->VarDTX_cnt_voiced_fx,1); + + st_fx->VarDTX_cnt_voiced_fx = s_min(st_fx->VarDTX_cnt_voiced_fx, MIN_CNT); + } + /* Background noise */ + ELSE IF( !st_fx->Opt_AMR_WB_fx ) + { + alpha = ALPHA_ENER_SLOW_FX; + move16(); + if (LT_32(st_fx->frame_ener_fx,st_fx->lt_ener_noise_fx)) + { + alpha = ALPHA_ENER_FAST_FX; + move16(); + } + + /*st_fx->lt_ener_noise_fx = alpha * st_fx->lt_ener_noise_fx + (1.0f-alpha) * st_fx->frame_ener_fx;*/ + L_tmp = L_sub(st_fx->lt_ener_noise_fx, st_fx->frame_ener_fx); + L_tmp = Mult_32_16(L_tmp, alpha); + st_fx->lt_ener_noise_fx = L_add(L_tmp, st_fx->frame_ener_fx); + move32();/*Q(-7) */ + + st_fx->VarDTX_cnt_noise_fx = add(st_fx->VarDTX_cnt_noise_fx,1); + + st_fx->VarDTX_cnt_noise_fx = s_min(st_fx->VarDTX_cnt_noise_fx, MIN_CNT); + } + } + + /* Update of the SID counter */ + update_SID_cnt( st_fx ); + + /* Update encoded bandwidth */ + test(); + test(); + IF( st_fx->Opt_DTX_ON_fx && (st_fx->core_brate_fx == SID_2k40 || st_fx->core_brate_fx == FRAME_NO_DATA ) ) + { + + st_fx->bwidth_fx = st_fx->last_bwidth_fx; + move16(); + test(); + if( GT_32(st_fx->last_core_brate_fx, SID_2k40)&&NE_32(st_fx->last_total_brate_cng_fx,-1)) + { + st_fx->bwidth_fx = st_fx->last_bwidth_cng_fx; + move16(); + } + + test(); + test(); + IF( st_fx->Opt_RF_ON && (EQ_32(st_fx->total_brate_fx, ACELP_13k20))&&(EQ_16(st_fx->bwidth_fx,NB))) + { + st_fx->codec_mode = MODE1; + move16(); + reset_rf_indices(st_fx); + st_fx->Opt_RF_ON = 0; + move16(); + st_fx->rf_mode = 0; + move16(); + } + + test(); + test(); + IF( st_fx->Opt_RF_ON && NE_32(st_fx->total_brate_fx, ACELP_13k20) ) + { + reset_rf_indices(st_fx); + move16(); + st_fx->Opt_RF_ON = 0; + move16(); + st_fx->rf_mode = 0; + } + + /* Set and limit the encoded bandwidth */ + IF ( EQ_16(st_fx->codec_mode, MODE2)) + { + Word16 n, bits_frame_nominal; + + UWord16 lsb; + Word16 tmpbandwidthMin; + + Mpy_32_16_ss(st_fx->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + bits_frame_nominal = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + + FOR (n=0; nrf_mode,1)) + { + tmpbandwidthMin = WB; + } + st_fx->bwidth_fx = s_max(s_min(st_fx->bwidth_fx, FrameSizeConfig[n].bandwidth_max), tmpbandwidthMin); + } + + } + + return; +} + +/*---------------------------------------------------------------------* + * update_SID_cnt() + * + * Update of the SID counter + *---------------------------------------------------------------------*/ + +static void update_SID_cnt( + Encoder_State_fx *st_fx /* i/o: State structure */ +) +{ + Word16 EstimatedSNR, delta, frac, exp; + Word32 L_tmp1, L_tmp2; + + test(); + test(); + IF( EQ_32(st_fx->core_brate_fx, SID_2k40)||EQ_32(st_fx->core_brate_fx,SID_1k75)||st_fx->core_brate_fx==FRAME_NO_DATA) + { + /* Adapt the SID interval */ + test(); + test(); + IF ( st_fx->var_SID_rate_flag_fx != 0 && EQ_16(st_fx->VarDTX_cnt_voiced_fx, MIN_CNT)&&EQ_16(st_fx->VarDTX_cnt_noise_fx,MIN_CNT)) + { + /* EstimatedSNR = 10.0f * (float)log10( (0.01f + st_fx->lt_ener_voiced) / (0.01f + st_fx->lt_ener_noise) ); */ + + L_tmp1 = L_max(st_fx->lt_ener_voiced_fx, 1); + exp = norm_l(L_tmp1); + frac = Log2_norm_lc(L_shl(L_tmp1, exp)); + exp = sub(30, exp); + L_tmp1 = L_Comp(exp, frac); + L_tmp2 = L_max(st_fx->lt_ener_noise_fx, 1); + exp = norm_l(L_tmp2); + frac = Log2_norm_lc(L_shl(L_tmp2, exp)); + exp = sub(30, exp); + L_tmp1 = L_sub(L_tmp1, L_Comp(exp, frac)); + /* 10 x Log10(a/b) = 10 x Log10(2) x [Log2(a) - Log2(b)] */ + /* 10 x Log10(2) = ~3.0103 */ + L_tmp1 = Mpy_32_16_1(L_tmp1, 24660); /* mult by 3.0103 / 4 in Q15 */ + L_tmp1 = L_shl(L_tmp1, 2+8); /* mult by 4 and shift left 8 to go in Q24 */ + EstimatedSNR = round_fx(L_tmp1); /* now in Q8 */ + IF ( GT_16(EstimatedSNR,SNR_H_FX)) + { + st_fx->interval_SID_fx = INT_H; + move16(); + } + ELSE IF ( LT_16(EstimatedSNR,SNR_L_FX)) + { + st_fx->interval_SID_fx = INT_L; + move16(); + } + ELSE + { + st_fx->interval_SID_fx = extract_h(L_mac(INT_L*65536L-SNR_L_FX/256*65536L*RATIO,(32768/256)*RATIO, EstimatedSNR)); + } + st_fx->interval_SID_fx = s_min(s_max(st_fx->interval_SID_fx, INT_L), INT_H); + + test(); + + if( st_fx->Opt_AMR_WB_fx == 0 || NE_16(st_fx->max_SID_fx,3)) + { + st_fx->max_SID_fx = st_fx->interval_SID_fx; + move16(); /* change SID update rate */ + } + } + test(); + IF( st_fx->Opt_DTX_ON_fx != 0 && st_fx->cnt_SID_fx != 0 ) + { + L_tmp1 = L_max(st_fx->lt_ener_noise_fx, 1); + exp = norm_l(L_tmp1); + frac = Log2_norm_lc(L_shl(L_tmp1, exp)); + exp = sub(30, exp); + L_tmp1 = L_Comp(exp, frac); + L_tmp2 = L_max(st_fx->lt_ener_last_SID_fx, 1); + exp = norm_l(L_tmp2); + frac = Log2_norm_lc(L_shl(L_tmp2, exp)); + exp = sub(30, exp); + L_tmp1 = L_sub(L_tmp1, L_Comp(exp, frac)); + /* 10 x Log10(a/b) = 10 x Log10(2) x [Log2(a) - Log2(b)] */ + /* 10 x Log10(2) = ~3.0103 */ + L_tmp1 = Mpy_32_16_1(L_tmp1, 24660); /* mult by 3.0103 / 4 in Q15 */ + L_tmp1 = L_shl(L_tmp1, 2+8); /* mult by 4 and shift left 8 to go in Q24 */ + delta = round_fx(L_tmp1); /* now in Q8 */ + test(); + test(); + if ( LT_16(delta,LTE_VAR_FX)&&EQ_16(st_fx->VarDTX_cnt_voiced_fx,MIN_CNT)&&EQ_16(st_fx->VarDTX_cnt_noise_fx,MIN_CNT)) + { + /* Send SID frame, and reset lt_ener_noise */ + st_fx->lt_ener_noise_fx = st_fx->frame_ener_fx; + move32(); + } + } + ELSE + { + /* If SID frame was sent, update long-term energy */ + st_fx->lt_ener_last_SID_fx = st_fx->lt_ener_noise_fx; + move32(); + } + st_fx->cnt_SID_fx = add(st_fx->cnt_SID_fx,1); + + IF( st_fx->var_SID_rate_flag_fx ) + { + test(); + test(); + test(); + + if( st_fx->Opt_AMR_WB_fx != 0 && EQ_16(st_fx->max_SID_fx,3)&&EQ_16(st_fx->cnt_SID_fx,3)) + { + /* set the size of CNG history buffer for averaging to DTX_HIST_SIZE frames */ + /* be sure that DTX_HIST_SIZE >= INT_L */ + st_fx->cng_hist_size_fx = 3; + move16(); + } + test(); + /*else if ( st_fx->max_SID_fx != 3 && st_fx->cnt_SID_fx == DTX_HIST_SIZE )//compile error */ + if( NE_16(st_fx->max_SID_fx,3)&&EQ_16(st_fx->cnt_SID_fx,DTX_HIST_SIZE)) + { + /* set the size of CNG history buffer for averaging to 3 frames */ + st_fx->cng_hist_size_fx = DTX_HIST_SIZE; + move16(); + } + } + test(); + IF( st_fx->var_SID_rate_flag_fx == 0 && GT_16(st_fx->interval_SID_fx,1)) + { + /* set the size of CNG history buffer for averaging to interval_SID frames */ + st_fx->cng_hist_size_fx = st_fx->interval_SID_fx; + move16(); + if ( GT_16(st_fx->cng_hist_size_fx, DTX_HIST_SIZE)) + { + st_fx->cng_hist_size_fx = DTX_HIST_SIZE; + move16(); + } + } + IF( GE_16(st_fx->cnt_SID_fx,st_fx->max_SID_fx)) + { + /* adaptive SID update interval */ + st_fx->max_SID_fx = st_fx->interval_SID_fx; + move16(); + st_fx->cnt_SID_fx = 0; + move16(); + } + } + + return; +} + + +void dtx_hangover_control_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 lsp_new_fx[M] /* i : current frame LSPs */ +) +{ + Word16 ptr; + Word16 i,j,m; + Word16 tmp_lsp[/*max(DTX_HIST_SIZE,*/HO_HIST_SIZE/*)*/*M]; + Word32 tmp_enr[/*max(DTX_HIST_SIZE,*/HO_HIST_SIZE/*)*/]; + Word16 tmp[/*max(DTX_HIST_SIZE,*/HO_HIST_SIZE/*)*/*M]; + Word16 enr_new; + Word16 weights; + Word32 enr_est; + Word16 enr_est_log; + Word16 lsp_est[M]; + Word16 Dlsp,Denr; + Word16 lsf_tmp[M]; + Word32 C[M]; + Word32 max[2]; + Word16 max_idx[2]; + Word16 ftmp_fx; + Word16 Dlsp_n2e,Denr_n2e; + Word16 exp,fra,exp2,fra2; + Word16 S_max; + Word16 S_tmp; + Word32 L_tmp; + + + /* get current frame exc energy in log2 */ + exp = norm_l(st_fx->ho_ener_circ_fx[st_fx->ho_circ_ptr_fx]); + fra = Log2_norm_lc(L_shl(st_fx->ho_ener_circ_fx[st_fx->ho_circ_ptr_fx],exp)); + exp = sub(sub(30,exp),6); + L_tmp = L_Comp(exp,fra); + enr_new = round_fx(L_shl(L_tmp,8)); /*Q8 */ + + if ( enr_new < 0 ) + { + enr_new = 0; + move16(); /*Q8 */ + } + + /* get energies and lsps of hangover frames */ + ptr = sub(st_fx->ho_circ_ptr_fx,sub(st_fx->burst_ho_cnt_fx,1)); + IF ( ptr < 0 ) + { + ptr = add(st_fx->ho_circ_size_fx,ptr); + } + + FOR ( i=0; iburst_ho_cnt_fx-1; i++ ) + { + Copy( &(st_fx->ho_lsp_circ_fx[ptr*M]), &(tmp_lsp[i*M]), M ); + tmp_enr[i] = st_fx->ho_ener_circ_fx[ptr]; + move32();/*Q6 */ + + ptr = add(ptr,1); + if ( EQ_16(ptr,st_fx->ho_circ_size_fx)) + { + ptr = 0; + move16(); + } + } + + /* get estimated CNG energy and lsps assuming terminate hangover at current frame */ + ptr = sub(st_fx->burst_ho_cnt_fx,2); + enr_est = Mpy_32_16_1(tmp_enr[ptr],W_DTX_HO_FX[0]); /*Q6 */ + weights = W_DTX_HO_FX[0]; + move16();/*Q15 */ + Copy( &(tmp_lsp[ptr*M]), tmp, M ); + m = 1; + move16(); + + FOR ( i=1; iburst_ho_cnt_fx-2; i++ ) + { + test(); + IF ( LT_32(Mpy_32_16_1(tmp_enr[ptr-i],ONE_OVER_BUF_H_NRG_FX),tmp_enr[ptr])&& + GT_32(tmp_enr[ptr-i],Mpy_32_16_1(tmp_enr[ptr], BUF_L_NRG_FX)) ) + { + enr_est = L_add(enr_est,Mpy_32_16_1(tmp_enr[ptr-i],W_DTX_HO_FX[i])); /*Q6 */ + weights = add(weights,W_DTX_HO_FX[i]); /*Q15 */ + Copy( &tmp_lsp[(ptr-i)*M], &tmp[m*M], M ); + m = add(m,1); + } + } + + exp = norm_l(enr_est); + fra = round_fx(L_shl(enr_est,exp)); + exp2 = norm_s(weights); + fra2 = shl(weights,exp2); + exp = sub(sub(exp,16),exp2); + IF ( GT_16(fra,fra2)) + { + fra = shr(fra,1); + exp = sub(exp,1); + } + L_tmp = L_deposit_l(div_s(fra,fra2)); + enr_est = L_shr(L_tmp,exp); /*Q6 */ + + if ( LT_32(enr_est,64)) + { + enr_est = 64; + move16();/*Q6 */ + } + + exp = norm_l(enr_est); + fra = Log2_norm_lc(L_shl(enr_est,exp)); + exp = sub(sub(30,exp),6); + L_tmp = L_Comp(exp,fra); + enr_est_log = round_fx(L_shl(L_tmp,8)); /*Q8 */ + Denr_n2e = abs_s(sub(enr_new,enr_est_log)); /*Q8 */ + + IF ( LT_16(m,3)) + { + enr_est = L_add(Mpy_32_16_1(enr_est,26214),Mpy_32_16_1(st_fx->ho_ener_circ_fx[st_fx->ho_circ_ptr_fx],6554)); /*Q6 */ + } + ELSE + { + enr_est = L_add(Mpy_32_16_1(enr_est,31130),Mpy_32_16_1(st_fx->ho_ener_circ_fx[st_fx->ho_circ_ptr_fx],1638)); /*Q6 */ + } + + exp = norm_l(enr_est); + fra = Log2_norm_lc(L_shl(enr_est,exp)); + exp = sub(sub(30,exp),6); + L_tmp = L_Comp(exp,fra); + enr_est_log = round_fx(L_shl(L_tmp,8)); /*Q8 */ + + if ( enr_est_log < 0 ) + { + enr_est_log = 0; + move16(); + } + + set32_fx( max, 0, 2 ); + set16_fx( max_idx, 0, 2 ); + + FOR( i=0; iL_frame_fx,L_FRAME)) + { + lsp2lsf_fx( &tmp[i*M], lsf_tmp, M, INT_FS_FX ); + ftmp_fx = 964; + move16();/*QX2.56 */ + S_tmp = sub(16384,add(lsf_tmp[M-1],ftmp_fx)); /*QX2.56 */ + C[i] = L_mult0(S_tmp,S_tmp); /*QX6.5536 */ + } + ELSE + { + lsp2lsf_fx( &tmp[i*M], lsf_tmp, M, INT_FS_16k ); + ftmp_fx = 1205; + move16();/*QX2.56 */ + S_tmp = sub(20480,add(lsf_tmp[M-1],ftmp_fx)); /*QX2.56 */ + C[i] = L_mult0(S_tmp,S_tmp); /*QX6.5536 */ + } + + S_tmp = sub(lsf_tmp[0],ftmp_fx); /*QX2.56 */ + C[i] = L_mac0(C[i],S_tmp,S_tmp); /*QX6.5536 */ + FOR ( j=0; jlspCNG_fx[i],lsp_est[i])); /*Q15 */ + Dlsp = add(Dlsp,S_tmp); /*Q15 */ + IF ( GT_16(S_tmp,S_max)) + { + S_max = S_tmp; /*Q15 */ + } + } + + exp = norm_l(st_fx->lp_ener_fx); + fra = Log2_norm_lc(L_shl(st_fx->lp_ener_fx,exp)); + exp = sub(sub(30,exp),6); + L_tmp = L_Comp(exp,fra); + S_tmp = round_fx(L_shl(L_tmp,8)); /*Q8 */ + Denr = abs_s(sub(S_tmp,enr_est_log)); /*Q8 */ + + /* make decision if DTX hangover can be terminated */ + st_fx->hangover_terminate_flag_fx = 0; + move16(); /*Q0 */ + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF ( ( LT_16(Dlsp,13107)&<_16(Denr,359)&<_16(S_max,3277) + && LT_16(Dlsp_n2e,13107) && LT_16(Denr_n2e,308) && st_fx->Opt_SC_VBR_fx == 1 ) || + ( LT_16(Dlsp,13107) && LT_16(Denr,205) && LT_16(S_max,3277) + && LT_16(Dlsp_n2e,13107) && LT_16(Denr_n2e,205) && st_fx->Opt_SC_VBR_fx == 0 ) ) + + { + st_fx->hangover_terminate_flag_fx = 1; + move16(); /*Q0 */ + } + + return; +} diff --git a/lib_enc/enc_acelp.c b/lib_enc/enc_acelp.c new file mode 100644 index 0000000..6719b1e --- /dev/null +++ b/lib_enc/enc_acelp.c @@ -0,0 +1,2049 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "stl.h" +#include "prot_fx.h" +#include "options.h" +#include "basop_util.h" +#include "rom_com_fx.h" +#include "rom_enc_fx.h" + + +#define _2_ 0x4000 /*Q12*/ +#define _1_ 0x2000 /*Q12*/ +#define _1_Q9 0x200 +/* + * E_ACELP_h_vec_corrx + * + * Parameters: + * h I: scaled impulse response + * vec I: vector to correlate with h[] + * track I: track to use + * sign I: sign vector + * rrixix I: correlation of h[x] with h[x] + * cor O: result of correlation (16 elements) + * + * Function: + * Calculate the correlations of h[] with vec[] for the specified track + * + * Returns: + * void + */ +void E_ACELP_h_vec_corr1(Word16 h[], Word16 vec[], UWord8 track, + Word16 sign[], Word16 (*rrixix)[16], + Word16 cor[], Word16 dn2_pos[], + Word16 nb_pulse) +{ + Word16 i, j; + Word16 dn, corr; + Word16 *dn2; + Word16 *p0, *p1, *p2; + Word32 L_sum; + + dn2 = &dn2_pos[shl(track,3)]; + p0 = rrixix[track]; + + FOR (i = 0; i < nb_pulse; i++) + { + dn = dn2[i]; + move16(); + L_sum = L_deposit_l(0); + p1 = h; + p2 = &vec[dn]; + FOR (j = dn; j < L_SUBFR-1; j++) + L_sum = L_mac(L_sum, *p1++, *p2++); + + corr = mac_r(L_sum, *p1++, *p2++); /*Q9*/ + + /*cor[dn >> 2] = sign[dn] * s + p0[dn >> 2];*/ + j = shr(dn,2); + if(sign[dn] > 0) + { + corr = add(p0[j], corr); + } + if(sign[dn] < 0) + { + corr = sub(p0[j], corr); + } + + cor[j] = corr; + move16(); + } +} + +void E_ACELP_h_vec_corr2(Word16 h[], Word16 vec[], UWord8 track, + Word16 sign[], Word16 (*rrixix)[16], + Word16 cor[]) +{ + Word16 i, j, pos, corr; + Word16 *p0, *p1, *p2; + Word32 L_sum; + + p0 = rrixix[track]; + + pos = track; + move16(); + FOR (i = 0; i < 16; i++) + { + L_sum = L_deposit_l(0); + p1 = h; + p2 = &vec[pos]; + FOR (j = pos; j < L_SUBFR-1; j++) + L_sum = L_mac(L_sum, *p1++, *p2++); + + corr = mac_r(L_sum, *p1++, *p2++); /*Q9*/ + + /*cor[i] = s * sign[track] + p0[i];*/ + + if(sign[pos] > 0) + { + corr = add(*p0++, corr); + } + if(sign[pos] < 0) + { + corr = sub(*p0++, corr); + } + cor[i] = corr; + move16(); + + pos = add(pos,4); + } +} + + +/* + * E_ACELP_2pulse_search + * + * Parameters: + * nb_pos_ix I: nb of pos for pulse 1 (1..8) + * track_x I: track of pulse 1 + * track_y I: track of pulse 2 + * ps I/O: correlation of all fixed pulses + * alp I/O: energy of all fixed pulses + * ix O: position of pulse 1 + * iy O: position of pulse 2 + * dn I: corr. between target and h[] + * dn2 I: vector of selected positions + * cor_x I: corr. of pulse 1 with fixed pulses + * cor_y I: corr. of pulse 2 with fixed pulses + * rrixiy I: corr. of pulse 1 with pulse 2 + * + * Function: + * Find the best positions of 2 pulses in a subframe + * + * Returns: + * void + */ +static void E_ACELP_2pulse_search(Word16 nb_pos_ix, UWord8 track_x, + UWord8 track_y, Word16 *ps, Word16 *alp, + Word16 *ix, Word16 *iy, Word16 dn[], + Word16 *dn2, Word16 cor_x[], + Word16 cor_y[], Word16 (*rrixiy)[256]) +{ + Word16 x, x2, y, i, *pos_x; + Word16 ps0, ps1, alp2_16, ps2, sq; + Word32 alp0, alp1, alp2, s; + Word16 *p1, *p2; + Word16 sqk[2], alpk[2], ik; + Word32 xy_save; + Word16 check = 0; /* debug code not instrumented */ + + + /* eight dn2 max positions per track */ + /*pos_x = &dn2[track_x << 3]; SHIFT(1); PTR_INIT(1);*/ + pos_x = &dn2[shl(track_x, 3)]; + move16(); + + /* save these to limit memory searches */ + alp0 = L_deposit_h(*alp); + ps0 = *ps; + move16(); + + alpk[0] = 1; + move16(); + sqk[0] = -1; + move16(); + x2 = shr(pos_x[0], 2); + if (mac_r(L_mac(L_mac(alp0, cor_x[x2], _1_), cor_y[0], _1_), rrixiy[track_x][shl(x2,4)], _1_) < 0) + { + sqk[0] = 1; + move16(); + } + ik = 0; + move16(); + xy_save = L_mac0(L_deposit_l(track_y), track_x, L_SUBFR); + + /* loop track 1 */ + FOR (i = 0; i < nb_pos_ix; i++) + { + x = pos_x[i]; + move16(); + x2 = shr(x, 2); + /* dn[x] has only nb_pos_ix positions saved */ + /*ps1 = ps0 + dn[x];*/ + ps1 = add(ps0, dn[x]); + + /*alp1 = alp0 + cor_x[x2];*/ + alp1 = L_mac(alp0, cor_x[x2], _1_); /*Q22*/ + + p1 = cor_y; + p2 = &rrixiy[track_x][shl(x2,4)]; + + FOR (y = track_y; y < L_SUBFR; y += 4) + { + /*ps2 = ps1 + dn[y];*/ + ps2 = add(ps1, dn[y]); + + /*alp2 = alp1 + (*p1++) + (*p2++);*/ + alp2 = L_mac(alp1, *p1++, _1_); + alp2_16 = mac_r(alp2, *p2++, _1_); /*Q6*/ + alpk[1-ik] = alp2_16; + move16(); + + /*sq = ps2 * ps2;*/ + sq = mult(ps2, ps2); + sqk[1-ik] = sq; + move16(); + + /*s = (alpk[ik] * sq) - (sqk[0] * alp2);*/ + s = L_msu(L_mult(alpk[ik], sq), sqk[ik], alp2_16); /*Q16*/ + + if (s > 0) + { + ik = sub(1, ik); + check = 1; /* debug code not instrumented */ + } + if (s > 0) + { + xy_save = L_mac0(y, x, L_SUBFR); + } + } + } + + assert(check); /* debug code not instrumented */ + + ps2 = extract_l(xy_save); + *iy = s_and(ps2, L_SUBFR-1); + move16(); + *ix = lshr(ps2, 6); + move16(); + + /**ps = ps0 + dn[*ix] + dn[*iy];*/ + *ps = add(ps0, add(dn[*ix], dn[*iy])); + move16(); + + *alp = alpk[ik]; + move16(); +} + + + +/* + * E_ACELP_1pulse_search + * + * Parameters: + * track_x I: track of pulse 1 + * track_y I: track of pulse 2 + * ps I/O: correlation of all fixed pulses + * alp I/O: energy of all fixed pulses + * ix O: position of pulse 1 + * dn I: corr. between target and h[] + * cor_x I: corr. of pulse 1 with fixed pulses + * cor_y I: corr. of pulse 2 with fixed pulses + * + * Function: + * Find the best positions of 1 pulse in a subframe + * + * Returns: + * void + */ +static void E_ACELP_1pulse_search(UWord8 tracks[2], + Word16 *ps, + Word16 *alp, + Word16 *ix, + Word16 dn[], + Word16 cor_x[], + Word16 cor_y[]) +{ + Word16 x, x_save = 0; + Word16 ps0; + Word16 ps1, sq; + Word16 alp1; + Word32 s, alp0; + Word16 sqk[2], alpk[2], ik; + Word16 ntracks, t; + Word16 check = 0; /* debug code not instrumented */ + + /* save these to limit memory searches */ + alp0 = L_deposit_h(*alp); + ps0 = *ps; + move16(); + + alpk[0] = 1; + move16(); + sqk[0] = -1; + move16(); + if (mac_r(alp0, cor_x[shr(tracks[0],2)], _1_) < 0) + { + sqk[0] = 1; + move16(); + } + ik = 0; + move16(); + + ntracks = 1; + if (NE_16(tracks[1], tracks[0])) + { + ntracks = 2; + move16(); + } + FOR (t=0; t>2]; SHIFT(1);ADD(1);*/ + alp1 = mac_r(alp0, cor_x[shr(x,2)], _1_); /*Q6*/ + alpk[1-ik] = alp1; + move16(); + + /*sq = ps1 * ps1; MULT(1);*/ + sq = mult(ps1, ps1); + sqk[1-ik] = sq; + move16(); + + /*s = (alpk * sq) - (sqk * alp1); MULT(1);MAC(1); */ + s = L_msu(L_mult(alpk[ik], sq), sqk[ik], alp1);/*Q16*/ + + if (s > 0) + { + ik = sub(1, ik); + check = 1; /* debug code not instrumented */ + } + if (s > 0) + { + x_save = x; + move16(); + } + } + + assert( check ); /* debug code not instrumented */ + } + *ps = add(ps0, dn[x_save]); + move16(); + *alp = alpk[ik]; + move16(); + *ix = x_save; + move16(); +} + +/* + * E_ACELP_xh_corr + * + * Parameters: + * h I: impulse response (of weighted synthesis filter) (Q12) + * x I: target signal (Q0) + * y O: correlation between x[] and h[] <12b + * + * Function: + * Compute the correlation between the target signal and the impulse + * response of the weighted synthesis filter. + * + * y[i]=sum(j=i,l-1) x[j]*h[j-i], i=0,l-1 + * + * Vector size is L_SUBFR + * + * Returns: + * void + */ +static void E_ACELP_xh_corr(Word16 *x, Word16 *y, Word16 *h, Word16 L_subfr) +{ + Word16 i, j,k; + Word32 L_tmp, y32[L_SUBFR16k], L_maxloc, L_tot; + + assert(L_subfr <= L_SUBFR16k); + + /* first keep the result on 32 bits and find absolute maximum */ + L_tot = L_deposit_l(1); + + FOR (k = 0; k < 4; k++) + { + L_maxloc = L_deposit_l(0); + FOR (i = k; i < L_subfr; i += 4) + { + L_tmp = L_mac0(1L, x[i], h[0]); /* 1 -> to avoid null dn[] */ + FOR (j = i; j < L_subfr-1; j++) + { + L_tmp = L_mac0(L_tmp, x[j+1], h[j+1 - i]); + } + + y32[i] = L_tmp; + move32(); + L_tmp = L_abs(L_tmp); + L_maxloc = L_max(L_tmp, L_maxloc); + } + /* tot += 3*max / 8 */ + L_maxloc = L_shr(L_maxloc, 2); + /* Do not warn saturation of L_tot, since its for headroom estimation. */ + BASOP_SATURATE_WARNING_OFF + L_tot = L_add(L_tot, L_maxloc); /* +max/4 */ + L_tot = L_add(L_tot, L_shr(L_maxloc, 1)); /* +max/8 */ + BASOP_SATURATE_WARNING_ON + } + + /* Find the number of right shifts to do on y32[] so that */ + /* 6.0 x sumation of max of dn[] in each track not saturate. */ + + j = sub(norm_l(L_tot), 4+16); /* 4 -> 16 x tot */ + + Copy_Scale_sig_32_16(y32, y, L_subfr, j); +} + +/** + * \brief calculate autocorrelation of vector x + * \param x input vector 4Q11 + * \param y output (autocorrelation coefficients) + * \param L_subfr length of x (and y) + * \param bits amount of target headroom bits for y + * \return exponent of y + */ +Word16 E_ACELP_hh_corr(Word16 *x, Word16 *y, Word16 L_subfr, Word16 bits) +{ + Word16 i, j, k = 0; /* initialize just to avoid compiler warning */ + Word32 L_tmp, L_sum; + + FOR (i = 0; i < L_subfr-1; i++) + { + Word64 L_tmp_64; + Word64 L_sum_64; + + L_tmp_64 = W_mult0_16_16( x[i], x[0] ); + FOR (j = i+2; j < L_subfr; j+=2) + { + L_tmp_64 = W_mac0_16_16( L_tmp_64, x[j], x[j-i] ); + } + L_sum_64 = L_tmp_64; + move64(); + + L_tmp_64 = W_mult0_16_16( x[i+1], x[1] ); + FOR (j = i+3; j < L_subfr; j+=2) + { + L_tmp_64 = W_mac0_16_16( L_tmp_64, x[j], x[j-i] ); + } + L_sum_64 = W_add_nosat( W_shr(L_sum_64,1), W_shr(L_tmp_64,1) ); + L_sum = W_sat_l( L_sum_64 ); + /* L_sum = L_shr( L_sum, 1 ); */ + if (i == 0) + { + k = norm_l(L_sum); + } + if (i == 0) + { + k = sub(k, bits); + } + + y[i] = round_fx( L_shl( L_sum, k ) ); + } + + L_tmp = L_mult0( x[i], x[0] ); + L_sum = L_shr( L_tmp, 1 ); + y[i] = round_fx( L_shl( L_sum, k ) ); + + k = add(1, k); + + return k; +} + +/* + * E_ACELP_xy1_corr + * + * Parameters: + * xn I: target signal + * y1 I: filtered adaptive codebook excitation + * g_coeff O: correlations and -2 + * norm_flag I: flag to trigger normalization of the result + * L_subfr I: length of data + * exp_xn I: common exponent of xn[] and y1[] + * + * Function: + * Find the correlations between the target xn[] and the filtered adaptive + * codebook excitation y1[]. ( and -2 ) + * Subframe size = L_SUBFR + * + * Returns: + * pitch gain (0 ... 1.2F) (Q14) + */ +Word16 E_ACELP_xy1_corr(Word16 xn[], Word16 y1[], ACELP_CbkCorr *g_corr, Word16 norm_flag, Word16 L_subfr, Word16 exp_xn) +{ + Word16 i, Q_xn; + Word16 xy, yy, exp_xy, exp_yy, gain; + Word32 L_off; + + L_off = L_shr(10737418l/*0.01f/2.0f Q31*/, s_min(add(exp_xn,exp_xn), 31)); + L_off = L_max(1,L_off); /* ensure at least a '1' */ + + /* Compute scalar product t1: */ + yy = round_fx(Dot_product15_offs(y1, y1, L_subfr, &exp_yy, L_off)); + + /* Compute scalar product t0: */ + xy = round_fx(Dot_product12_offs(xn, y1, L_subfr, &exp_xy, L_off)); + + /* Compute doubled format out of the exponent */ + Q_xn = shl(sub(15,exp_xn),1); + g_corr->y1y1 = yy; + move16(); + g_corr->y1y1_e = sub(exp_yy, Q_xn); + move16(); + g_corr->xy1 = xy; + move16(); + g_corr->xy1_e = sub(exp_xy, Q_xn); + move16(); + + /* If (xy < 0) gain = 0 */ + IF (xy < 0) + { + move16(); + gain = 0; + GOTO bail; + } + + /* compute gain = xy/yy */ + + xy = mult_r(xy,0x4000); /* Be sure xy < yy */ + gain = div_s(xy, yy); + + i = add(exp_xy, 1 - 1); /* -1 -> gain in Q14 */ + i = sub(i, exp_yy); + BASOP_SATURATE_WARNING_OFF + gain = shl(gain, i); /* saturation can occur here */ + BASOP_SATURATE_WARNING_ON + /* gain = s_max(0, gain); */ /* see above xy < 0. */ + + /* if (gain > 1.2) gain = 1.2 in Q14 */ + + gain = s_min(19661/*1.2f Q14*/ /* 19661 */, gain); + + /*Limit the energy of pitch contribution*/ + IF (norm_flag) + { + Word16 tmp, exp_tmp, exp_div; + + /* Compute scalar product */ + tmp = round_fx(Dot_product12_offs(xn, xn, L_subfr, &exp_tmp, 1)); + /* gain_p_snr = sqrt(/) */ + tmp = BASOP_Util_Divide1616_Scale(tmp, yy, &exp_div); + exp_tmp = add(sub(exp_tmp, exp_yy), exp_div); + + tmp = Sqrt16(tmp, &exp_tmp); + + /* Note: shl works as shl or shr. */ + exp_tmp = sub(exp_tmp,1); + BASOP_SATURATE_WARNING_OFF + tmp = round_fx(L_shl(Mpy_32_16_1( 1717986944l/*ACELP_GAINS_CONST Q31*/, tmp), exp_tmp)); + BASOP_SATURATE_WARNING_ON + + gain = s_min(gain, tmp); + } + +bail: + + + return (gain); +} + +/* + * E_ACELP_xy2_corr + * + * Parameters: + * xn I: target signal in Q_xn + * y1 I: filtered adaptive codebook excitation in Q_xn + * y2 I: filtered fixed codebook excitation in Q9 + * g_corr O: correlations , -2, 2 + * L_subfr I: subframe size + * + * Function: + * Find the correlations between the target xn[], the filtered adaptive + * codebook exc. y1[], and the filtered fixed codebook innovation y2[]. + * ( , -2 and 2 ) + * Subrame size = L_SUBFR + * + * Returns: + * pitch gain (0 ... 1.2F) + */ +void E_ACELP_xy2_corr(Word16 xn[], Word16 y1[], Word16 y2[], + ACELP_CbkCorr *g_corr, Word16 L_subfr, Word16 exp_xn) +{ + Word16 xny2, y2y2, y1y2, xx, exp_xny2, exp_y2y2, exp_y1y2, exp_xx; + Word32 L_off; + + BASOP_SATURATE_ERROR_ON; + + /* Compute scalar product */ + y2y2 = extract_h(Dot_product15_offs(y2, y2, L_subfr, &exp_y2y2, 5243l/*0.01f Q19*/)); + + /* L_off = 1L; */ + L_off = L_shr(10737418l/*0.01f/2.0f Q31*/, sub(30-9, exp_xn)); + + /* Compute scalar product */ + xny2 = extract_h(Dot_product12_offs(xn, y2, L_subfr, &exp_xny2, L_off)); + + /* Compute scalar product */ + y1y2 = extract_h(Dot_product12_offs(y1, y2, L_subfr, &exp_y1y2, L_off)); + + /* Compute scalar product */ + L_off = L_shr(21474836l/*0.01f Q31*/, s_min(31, sub(30, shl(exp_xn, 1)))); + xx = extract_h(Dot_product12_offs(xn, xn, L_subfr, &exp_xx, L_off)); + + + g_corr->y2y2 = y2y2; + move16(); + g_corr->y2y2_e = exp_y2y2; + move16(); + g_corr->xy2 = xny2; + move16(); + g_corr->xy2_e = exp_xny2; + move16(); + g_corr->y1y2 = y1y2; + move16(); + g_corr->y1y2_e = exp_y1y2; + move16(); + g_corr->xx = xx; + move16(); + g_corr->xx_e = exp_xx; + move16(); + + + BASOP_SATURATE_ERROR_OFF; +} + + + +/* + * E_ACELP_codebook_target_update + * + * Parameters: + * x I: old target (for pitch search) (Q_xn) + * x2 O: new target (for codebook search) (Q_xn) + * y I: filtered adaptive codebook vector (Q_xn) + * gain I: adaptive codebook gain (Q14) + * + * Function: + * Update the target vector for codebook search. + * Subframe size = L_SUBFR + * Returns: + * void + */ +void E_ACELP_codebook_target_update(Word16 *x, Word16 *x2, Word16 *y, + Word16 gain, Word16 L_subfr) +{ + Word16 i, Q15_flag; + Word32 L_tmp; + + assert(gain >= 0); + + Q15_flag = 0; + move16(); + if (LT_16(gain, 1<<14)) + { + Q15_flag = 1; + move16(); + } + gain = shl(gain, Q15_flag); + + FOR (i = 0; i < L_subfr; i++) + { + L_tmp = L_deposit_h(x[i]); + if (Q15_flag == 0) + { + L_tmp = L_msu(L_tmp, y[i], gain); + } + x2[i] = msu_r(L_tmp, y[i], gain); + move16(); + } +} + + +/* + * E_ACELP_pulsesign + * + * Parameters: + * cn I: residual after long term prediction <12b + * dn I: corr. between target and h[]. <12b + * dn2 I/O: dn2[] = mix of dn[] and cn[] + * sign O: sign of pulse 0 or -1 + * vec O: negative sign of pulse + * alp I: energy of all fixed pulses Q13 + * sign_val I: value for signs + * L_subfr I: subframe length + * + * Function: + * Determine sign of each pulse position, store them in "sign" + * and change dn to all positive. + * Subframe size = L_SUBFR + * Returns: + * void + */ +void E_ACELP_pulsesign(const Word16 cn[], Word16 dn[], Word16 dn2[], Word16 sign[], Word16 vec[], const Word16 alp, const Word16 sign_val, const Word16 L_subfr) +{ + Word16 i; + Word32 Lval, Lcor; + Word16 k_cn, k_dn, sign_neg, e_dn, e_cn; + Word16 signs[3]; + Word16 *ptr16; + Word16 val, index; + + + /* calculate energy for normalization of cn[] and dn[] */ + Lval = L_mac0(1, cn[0], cn[0]); + Lcor = L_mac0(1, dn[0], dn[0]); + + FOR (i = 1; i < L_subfr; i++) + { + Lval = L_mac0(Lval, cn[i], cn[i]); + Lcor = L_mac0(Lcor, dn[i], dn[i]); + } + + e_dn = 31; + move16(); + e_cn = 31; + move16(); + + Lval = Sqrt32(Lval, &e_dn); + Lcor = Sqrt32(Lcor, &e_cn); + i = sub(e_dn,e_cn); + if(i < 0) + Lval = L_shl(Lval, i); + if(i > 0) + Lcor = L_shr(Lcor, i); + + k_dn = round_fx(Lval); + k_cn = round_fx(Lcor); + + k_cn = mult_r(0x2000, k_cn); /* 1 in Q13 */ + k_dn = mult_r(alp, k_dn); /* alp in Q13 */ + + sign_neg = negate(sign_val); + + signs[0] = sign_neg; + move16(); + signs[1] = sign_val; + move16(); + signs[2] = sign_neg; + move16(); + ptr16 = &signs[1]; + + FOR (i = 0; i < L_subfr; i++) + { + /*cor = (s * cn[i]) + (alp * dn[i]); MULT(1);MAC(1);*/ + Lcor = L_mult(cn[i], k_cn); + Lcor = L_mac(Lcor, dn[i], k_dn); + val = round_fx(L_shl(Lcor,4)); /*shifting by 4 may overflow but improves accuracy*/ + + index = shr(val, 15); + sign[i] = ptr16[index]; + move16(); /* yields -1 (when ps < 0) or 0 (when ps >= 0) */ + vec[i] = ptr16[index+1]; + move16(); + + if (val < 0) + { + dn[i] = negate(dn[i]); + move16(); + } + dn2[i] = abs_s(val); + move16(); /* dn2[] = mix of dn[] and cn[] */ + } +} + + +void E_ACELP_findcandidates(Word16 dn2[], Word16 dn2_pos[], Word16 pos_max[]) +{ + Word16 i, k, j, i8; + Word16 *ps_ptr; + + FOR (i = 0; i < 4; i++) + { + i8 = shl(i, 3); + FOR (k = i8; k < i8+8; k++) + { + ps_ptr = &dn2[i]; + + FOR (j = i+4; j < L_SUBFR; j += 4) + { + if (GT_16(dn2[j], *ps_ptr)) + { + ps_ptr = &dn2[j]; + move16(); + } + } + + *ps_ptr = -1; /* dn2 < 0 when position is selected */ move16(); + dn2_pos[k] = (Word16)(ps_ptr - dn2); + move16(); + } + pos_max[i] = dn2_pos[i8]; + move16(); + } +} + + +static void E_ACELP_apply_sign(Word16 *p0, Word16 *psign0) +{ + p0[0] = mult_r( p0[0] , psign0[ 0]); + move16(); + p0[1] = mult_r( p0[1] , psign0[ 4]); + move16(); + p0[2] = mult_r( p0[2] , psign0[ 8]); + move16(); + p0[3] = mult_r( p0[3] , psign0[12]); + move16(); + p0[4] = mult_r( p0[4] , psign0[16]); + move16(); + p0[5] = mult_r( p0[5] , psign0[20]); + move16(); + p0[6] = mult_r( p0[6] , psign0[24]); + move16(); + p0[7] = mult_r( p0[7] , psign0[28]); + move16(); + p0[8] = mult_r( p0[8] , psign0[32]); + move16(); + p0[9] = mult_r( p0[9] , psign0[36]); + move16(); + p0[10] = mult_r( p0[10] , psign0[40]); + move16(); + p0[11] = mult_r( p0[11] , psign0[44]); + move16(); + p0[12] = mult_r( p0[12] , psign0[48]); + move16(); + p0[13] = mult_r( p0[13] , psign0[52]); + move16(); + p0[14] = mult_r( p0[14] , psign0[56]); + move16(); + p0[15] = mult_r( p0[15] , psign0[60]); + move16(); +} + +void E_ACELP_vec_neg(Word16 h[], Word16 h_inv[], Word16 L_subfr) +{ + Word16 i; + + FOR(i = 0; i < L_subfr; i ++) + { + h_inv[i] = negate(h[i]); + move16(); + } +} + + +void E_ACELP_corrmatrix(Word16 h[], Word16 sign[], Word16 vec[], Word16 rrixix[4][16], Word16 rrixiy[4][256]) +{ + + Word16 *p0, *p1, *p2, *p3, *psign0, *psign1, *psign2, *psign3; + Word16 *ptr_h1, *ptr_h2, *ptr_hf; + Word32 cor; + Word16 i, /* j, */ k,pos; + + /* + * Compute rrixix[][] needed for the codebook search. + */ + + /* storage order --> i3i3, i2i2, i1i1, i0i0 */ + + /* Init pointers to last position of rrixix[] */ + p0 = &rrixix[0][16 - 1]; /* Q9 */ + p1 = &rrixix[1][16 - 1]; + p2 = &rrixix[2][16 - 1]; + p3 = &rrixix[3][16 - 1]; + + ptr_h1 = h; + cor = L_deposit_l(0); + FOR (i = 0; i < 16; i++) + { + cor = L_mac(cor, *ptr_h1, *ptr_h1); + ptr_h1++; + *p3-- = round_fx(L_shr(cor, 1)); + cor = L_mac(cor, *ptr_h1, *ptr_h1); + ptr_h1++; + *p2-- = round_fx(L_shr(cor, 1)); + cor = L_mac(cor, *ptr_h1, *ptr_h1); + ptr_h1++; + *p1-- = round_fx(L_shr(cor, 1)); + cor = L_mac(cor, *ptr_h1, *ptr_h1); + ptr_h1++; + *p0-- = round_fx(L_shr(cor, 1)); /* Q9 */ + } + + + /* + * Compute rrixiy[][] needed for the codebook search. + */ + + /* storage order --> i2i3, i1i2, i0i1, i3i0 */ + + pos = 256 - 1; + ptr_hf = h + 1; + FOR (k = 0; k < 16; k++) + { + p3 = &rrixiy[2][pos]; + p2 = &rrixiy[1][pos]; + p1 = &rrixiy[0][pos]; + p0 = &rrixiy[3][pos - 16]; + + cor = L_deposit_h(0); + ptr_h1 = h; + ptr_h2 = ptr_hf; + + FOR (i = k; i < 16-1; i++) + { + cor = L_mac(cor, *ptr_h1++, *ptr_h2++); + *p3 = round_fx(cor); + cor = L_mac(cor, *ptr_h1++, *ptr_h2++); + *p2 = round_fx(cor); + cor = L_mac(cor, *ptr_h1++, *ptr_h2++); + *p1 = round_fx(cor); + cor = L_mac(cor, *ptr_h1++, *ptr_h2++); + *p0 = round_fx(cor); + + p3 -= (16 + 1); + p2 -= (16 + 1); + p1 -= (16 + 1); + p0 -= (16 + 1); + } + cor = L_mac(cor, *ptr_h1++, *ptr_h2++); + *p3 = round_fx(cor); + cor = L_mac(cor, *ptr_h1++, *ptr_h2++); + *p2 = round_fx(cor); + cor = L_mac(cor, *ptr_h1++, *ptr_h2++); + *p1 = round_fx(cor); + + pos -= 16; + ptr_hf += 4; + } + + /* storage order --> i3i0, i2i3, i1i2, i0i1 */ + + pos = 256 - 1; + ptr_hf = h + 3; + FOR (k = 0; k < 16; k++) + { + p3 = &rrixiy[3][pos]; + p2 = &rrixiy[2][pos - 1]; + p1 = &rrixiy[1][pos - 1]; + p0 = &rrixiy[0][pos - 1]; + + cor = L_deposit_h(0); + ptr_h1 = h; + ptr_h2 = ptr_hf; + FOR (i = k; i < 16-1; i++) + { + cor = L_mac(cor, *ptr_h1++, *ptr_h2++); + *p3 = round_fx(cor); + cor = L_mac(cor, *ptr_h1++, *ptr_h2++); + *p2 = round_fx(cor); + cor = L_mac(cor, *ptr_h1++, *ptr_h2++); + *p1 = round_fx(cor); + cor = L_mac(cor, *ptr_h1++, *ptr_h2++); + *p0 = round_fx(cor); + + p3 -= (16 + 1); + p2 -= (16 + 1); + p1 -= (16 + 1); + p0 -= (16 + 1); + } + cor = L_mac(cor, *ptr_h1++, *ptr_h2++); + *p3 = round_fx(cor); + + pos--; + ptr_hf += 4; + } + + /* + * Modification of rrixiy[][] to take signs into account. + */ + + p0 = &rrixiy[0][0]; + + /* speed-up: 11% */ + p1 = &rrixiy[1][0]; + p2 = &rrixiy[2][0]; + p3 = &rrixiy[3][0]; + + FOR(i = 0; i < L_SUBFR; i += 4) + { + + psign0 = &vec[1]; + if (sign[i+0] > 0 ) psign0 = &sign[1]; + + psign1 = &vec[2]; + if (sign[i+1] > 0 ) psign1 = &sign[2]; + + psign2 = &vec[3]; + if (sign[i+2] > 0 ) psign2 = &sign[3]; + + psign3 = &vec[0]; + if (sign[i+3] > 0 ) psign3 = &sign[0]; + + E_ACELP_apply_sign(p0, psign0); + p0 += 16; + + E_ACELP_apply_sign(p1, psign1); + p1 += 16; + + E_ACELP_apply_sign(p2, psign2); + p2 += 16; + + E_ACELP_apply_sign(p3, psign3); + p3 += 16; + } +} + +void E_ACELP_4tsearch(Word16 dn[], const Word16 cn[], const Word16 H[], Word16 code[], + const PulseConfig *config, Word16 ind[], Word16 y[]) +{ + Word16 sign[L_SUBFR], vec[L_SUBFR]; + Word16 cor_x[16], cor_y[16], h_buf[4 * L_SUBFR]; + Word16 rrixix[4][16]; + Word16 rrixiy[4][256]; + Word16 dn2[L_SUBFR]; + Word16 psk, ps, alpk, alp = 0; + Word16 codvec[NB_PULSE_MAX]; + Word16 pos_max[4]; + Word16 dn2_pos[8 * 4]; + UWord8 ipos[NB_PULSE_MAX]; + Word16 *p0, *p1, *p2, *p3; + Word16 *h, *h_inv; + Word16 i, j, k, l, st, pos; + Word16 val, tmp, scale; + Word32 s, L_tmp; + Word16 nb_pulse, nb_pulse_m2; + Word16 check = 0; /* debug code not instrumented */ + + + alp = config->alp; /* Q13 */ /* initial value for energy of all fixed pulses */ move16(); + nb_pulse = config->nb_pulse; + move16(); + nb_pulse_m2 = sub(nb_pulse, 2); + + set16_fx(codvec, 0, nb_pulse); + + /* + * Find sign for each pulse position. + */ + + E_ACELP_pulsesign(cn, dn, dn2, sign, vec, alp, 0x7fff, L_SUBFR); + + /* + * Select the most important 8 position per track according to dn2[]. + */ + E_ACELP_findcandidates(dn2, dn2_pos, pos_max); + + /* + * Compute h_inv[i]. + */ + set16_fx(h_buf, 0, L_SUBFR); + + set16_fx(h_buf + (2 * L_SUBFR),0,L_SUBFR); + + h = h_buf + L_SUBFR; + h_inv = h_buf + (3 * L_SUBFR); + + /*Check the energy if it is too high then scale to prevent an overflow*/ + scale = 0; + move16(); + L_tmp = L_deposit_l(0); + BASOP_SATURATE_WARNING_OFF + FOR (i = 0; i < L_SUBFR; i++) + { + L_tmp = L_mac(L_tmp, H[i], H[i]); + } + val = extract_h(L_tmp); + BASOP_SATURATE_WARNING_ON + + if (GT_16(val, 0x2000)) + { + scale = -1; + move16(); + } + if (GT_16(val, 0x7000)) + { + scale = -2; + move16(); + } + + Copy_Scale_sig(H, h, L_SUBFR, scale); + + E_ACELP_vec_neg(h, h_inv, L_SUBFR); + + + /* + * Compute correlation matrices needed for the codebook search. + */ + E_ACELP_corrmatrix(h, sign, vec, rrixix, rrixiy); + + + /* + * Deep first search: + * ------------------ + * 20 bits (4p): 4 iter x ((4x16)+(8x16)) = 768 tests + * 36 bits (8p): 4 iter x ((1x1)+(4x16)+(8x16)+(8x16)) = 1280 tests + * 52 bits (12p): 3 iter x ((1x1)+(1x1)+(4x16)+(6x16) + * +(8x16)+(8x16)) = 1248 tests + * 64 bits (16p): 2 iter x ((1x1)+(1x1)+(4x16)+(6x16) + * +(6x16)+(8x16)+(8x16)+(8x16)) = 1280 tests + */ + psk = -1; + move16(); + alpk = 1; + move16(); + + /*Number of iterations*/ + FOR (k = 0; k < config->nbiter; k++) + { + E_ACELP_setup_pulse_search_pos(config, k, ipos); + + /* format of alp changes to Q(15-ALP2_E) */ + + pos = config->fixedpulses; + move16(); + + IF (config->fixedpulses == 0) /* 1100, 11, 1110, 1111, 2211 */ + { + ps = 0; + move16(); + alp = 0; + move16(); + set16_fx(vec, 0, L_SUBFR); + } + ELSE IF (EQ_16(config->fixedpulses, 2)) /* 2222 and 3322 */ + { + /* first stage: fix 2 pulses */ + ind[0] = pos_max[ipos[0]]; + move16(); + ind[1] = pos_max[ipos[1]]; + move16(); + ps = add(dn[ind[0]], dn[ind[1]]); + + /*alp = rrixix[ipos[0]][ind[0] >> 2] + rrixix[ipos[1]][ind[1] >> 2] + + rrixiy[ipos[0]][((ind[0] >> 2) << 4) + (ind[1] >> 2)];*/ + + i = shr(ind[0], 2); + j = shr(ind[1], 2); + l = add(shl(i, 4), j); + s = L_mult(rrixix[ipos[0]][i], _1_); /* Q9+Q12+1 */ + s = L_mac(s, rrixix[ipos[1]][j], _1_); + alp = mac_r(s, rrixiy[ipos[0]][l], _1_); + + p0 = h - ind[0]; + if (sign[ind[0]] < 0) + { + p0 = h_inv - ind[0]; + } + + p1 = h - ind[1]; + if (sign[ind[1]] < 0) + { + p1 = h_inv - ind[1]; + } + + FOR (i = 0; i < L_SUBFR; i++) + { + vec[i] = add(*p0++, *p1++); + move16(); + } + } + ELSE /* 3333 and above */ + { + /* first stage: fix 4 pulses */ + + ind[0] = pos_max[ipos[0]]; + move16(); + ind[1] = pos_max[ipos[1]]; + move16(); + ind[2] = pos_max[ipos[2]]; + move16(); + ind[3] = pos_max[ipos[3]]; + move16(); + + /*ps = dn[ind[0]] + dn[ind[1]] + dn[ind[2]] + dn[ind[3]];*/ + ps = add(add(add(dn[ind[0]], dn[ind[1]]), dn[ind[2]]), dn[ind[3]]); + + p0 = h - ind[0]; + if (sign[ind[0]] < 0) + { + p0 = h_inv - ind[0]; + } + + p1 = h - ind[1]; + if (sign[ind[1]] < 0) + { + p1 = h_inv - ind[1]; + } + + p2 = h - ind[2]; + if (sign[ind[2]] < 0) + { + p2 = h_inv - ind[2]; + } + + p3 = h - ind[3]; + if (sign[ind[3]] < 0) + { + p3 = h_inv - ind[3]; + } + + FOR (i = 0; i < L_SUBFR; i++) + { + vec[i] = add(add(add(*p0++, *p1++), *p2++), *p3++); + move16(); + } + + L_tmp = L_mult(vec[0], vec[0]); + FOR (i = 1; i < L_SUBFR; i++) + L_tmp = L_mac(L_tmp, vec[i], vec[i]); + + alp = round_fx(L_shr(L_tmp, 3)); + + /*alp *= 0.5F; */ + } + + /* other stages of 2 pulses */ + st = 0; + move16(); + FOR (j = pos; j < nb_pulse; j += 2) + { + IF (GE_16(nb_pulse_m2, j)) /* pair-wise search */ + { + /* + * Calculate correlation of all possible positions + * of the next 2 pulses with previous fixed pulses. + * Each pulse can have 16 possible positions. + */ + E_ACELP_h_vec_corr1(h, vec, ipos[j], sign, rrixix, cor_x, dn2_pos, config->nbpos[st]); + + E_ACELP_h_vec_corr2(h, vec, ipos[j + 1], sign, rrixix, cor_y); + + /* + * Find best positions of 2 pulses. + */ + E_ACELP_2pulse_search(config->nbpos[st], ipos[j], ipos[j + 1], &ps, &alp, + &ind[j], &ind[j+1], dn, dn2_pos, cor_x, cor_y, rrixiy); + + } + ELSE /* single pulse search */ + { + E_ACELP_h_vec_corr2(h, vec, ipos[j], sign, rrixix, cor_x); + + E_ACELP_h_vec_corr2(h, vec, ipos[j + 1], sign, rrixix, cor_y); + + E_ACELP_1pulse_search(&ipos[j], &ps, &alp, + &ind[j], dn, cor_x, cor_y); + } + + IF (GT_16(nb_pulse_m2, j)) + { + p0 = h - ind[j]; + if (sign[ind[j]] < 0) + { + p0 = h_inv - ind[j]; + } + + p1 = h - ind[j + 1]; + if (sign[ind[j + 1]] < 0) + { + p1 = h_inv - ind[j + 1]; + } + + + FOR (i = 0; i < L_SUBFR; i++) + { + tmp = add(*p0++, *p1++); + vec[i] = add(vec[i], tmp); /* can saturate here. */ move16(); + } + + } + st = add(st, 1); + } + + /* memorise the best codevector */ + + /*ps = ps * ps; MULT(1);*/ + ps = mult(ps, ps); + /*s = (alpk * ps) - (psk * alp); MULT(2);ADD(1);*/ + s = L_msu(L_mult(alpk, ps), psk, alp); /*Q9+Q6+1=Q16*/ + + if (psk < 0) + { + s = 1; + } + IF (s > 0) + { + psk = ps; + move16(); + alpk = alp; + move16(); + Copy(ind,codvec, nb_pulse); + check = 1; /* debug code not instrumented */ + } + } + + assert( check ); /* debug code not instrumented */ + + /* + * Build the codeword, the filtered codeword and index of codevector, as well as store weighted correlations. + */ + + E_ACELP_build_code(nb_pulse, codvec, sign, code, ind); + + set16_fx(y, 0, L_SUBFR); + FOR (k = 0; k 0) + { + p0 -= 2*L_SUBFR; + } + FOR (i=0; i 4 pulses in a frame of 64 samples. + * 36 bits 9 + 9 + 9 + 9 --> 8 pulses in a frame of 64 samples. + * 44 bits 13 + 9 + 13 + 9 --> 10 pulses in a frame of 64 samples. + * 52 bits 13 + 13 + 13 + 13 --> 12 pulses in a frame of 64 samples. + * 64 bits 2 + 2 + 2 + 2 + 14 + 14 + 14 + 14 --> + * 16 pulses in a frame of 64 samples. + * 72 bits 10 + 2 + 10 + 2 + 10 + 14 + 10 + 14 --> + * 18 pulses in a frame of 64 samples. + * 88 bits 11 + 11 + 11 + 11 + 11 + 11 + 11 + 11 --> + * 24 pulses in a frame of 64 samples. + * + * All pulses can have two (2) possible amplitudes: +1 or -1. + * Each pulse can sixteen (16) possible positions. + * + * Returns: + * void + */ +static +void E_ACELP_4t( + Word16 dn[], Word16 cn[] /* Q_xn */, Word16 H[], + Word16 R[], Word8 acelpautoc, + Word16 code[], + Word16 cdk_index, Word16 _index[] + ,const Word16 L_frame, + const Word16 last_L_frame, + const Word32 total_brate, + const Word16 i_subfr +) +{ + PulseConfig config; + Word16 ind[NPMAXPT*4]; + Word16 y[L_SUBFR]; + + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + memcpy(&config, &PulseConfTable[cdk_index], sizeof(PulseConfTable[cdk_index])); + + test(); + test(); + IF( NE_16(L_frame,last_L_frame)&&EQ_32(total_brate,ACELP_24k40)&<_32(i_subfr,5*L_SUBFR)) + { + config.nbiter = sub(config.nbiter, 1); + config.nbiter = s_max(config.nbiter, 1); + } + + IF (acelpautoc) + { + E_ACELP_4tsearchx(dn, cn, R, code, &config, ind); + } + ELSE + { + E_ACELP_4tsearch(dn, cn, H, code, &config, ind, y); + } + E_ACELP_indexing(code, &config, NB_TRACK_FCB_4T, _index); +} + +static void E_ACELP_indexing_shift( + Word16 wordcnt, /* i: 16-bit word count including the newly shifted-in bits */ + Word16 shift_bits, /* i: number of bits to shift in from the lsb */ + UWord16 lsb_bits, /* i: bits to shift in from the lsb */ + const UWord16 src[], /* i: source buffer */ + UWord16 dst[] /* o: destination buffer */ +) +{ + Word16 right_shift, i; + + assert(shift_bits <= 16); + + right_shift = sub(16, shift_bits); + + FOR (i=sub(wordcnt, 1); i>0; --i) + { + dst[i] = s_or(lshl(src[i], shift_bits), lshr(src[i-1], right_shift)); + move16(); + } + dst[i] = s_or(lshl(src[i], shift_bits), lsb_bits); + move16(); +} + +#define MAX_IDX_LEN 9 + +Word16 E_ACELP_indexing( + const Word16 code[], + const PulseConfig *config, + Word16 num_tracks, + Word16 prm[] +) +{ + Word16 track, shift_bits; + Word16 p[NB_TRACK_FCB_4T], wordcnt; + UWord32 s[NB_TRACK_FCB_4T], n[NB_TRACK_FCB_4T]; + UWord16 idx[MAX_IDX_LEN]; + Word16 saved_bits; + + assert(num_tracks == NB_TRACK_FCB_4T); + + saved_bits = 0; + move16(); + + /* + * Code state of pulses of all tracks + * */ + wordcnt = shr(add(config->bits, 15), 4); /* ceil(bits/16) */ + + set16_fx((Word16*)idx, 0, wordcnt); + + IF (EQ_16(config->bits, 43)) /* EVS pulse indexing */ + { + saved_bits = E_ACELP_code43bit(code, s, p, idx); + } + ELSE + { + FOR (track = 0; track < num_tracks; track++) + { + /* Code track of length 2^4 where step between tracks is 4. */ + E_ACELP_codearithp(code+track, &n[track], &s[track], &p[track]); + } + fcb_pulse_track_joint(idx, wordcnt, s, p, num_tracks); + } + + /* check if we need to code track positions */ + track = 0; + move16(); + shift_bits = 0; + move16(); + SWITCH (config->codetrackpos) + { + case TRACKPOS_FIXED_TWO: + /* Code position of consecutive tracks with single extra pulses */ + /* Find track with one pulse less. */ + if (NE_16(p[0], p[1])) + { + /* Either 0110 or 1001 */ + track = 1; + move16(); + } + if (GT_16(p[3], p[1])) + { + track = add(track, 2); + } + shift_bits = 2; + move16(); + BREAK; + + case TRACKPOS_FREE_THREE: + /* Code position of track with one pulse less than others */ + /* Find track with one pulse less. */ + if (LT_16(p[1], p[0])) + { + track = 1; + move16(); + } + if (LT_16(p[2], p[0])) + { + track = 2; + move16(); + } + if (LT_16(p[3], p[0])) + { + track = 3; + move16(); + } + shift_bits = 2; + move16(); + BREAK; + + case TRACKPOS_FREE_ONE: + /* Code position of track with one pulse less than others */ + /* Find track with one pulse less. */ + if (GT_16(p[1], p[0])) + { + track = 1; + move16(); + } + if (GT_16(p[2], p[0])) + { + track = 2; + move16(); + } + if (GT_16(p[3], p[0])) + { + track = 3; + move16(); + } + shift_bits = 2; + move16(); + BREAK; + + case TRACKPOS_FIXED_EVEN: + case TRACKPOS_FIXED_FIRST: + BREAK; + + default: + printf("Codebook mode not implemented.\n"); + assert(0); /* mode not yet implemented*/ + BREAK; + } + + E_ACELP_indexing_shift(wordcnt, shift_bits, track, idx, (UWord16*)prm); + + return saved_bits; +} + +/*--------------------------------------------------------------------------* + * E_ACELP_adaptive_codebook + * + * Find adaptive codebook. + *--------------------------------------------------------------------------*/ +void E_ACELP_adaptive_codebook( + Word16 *exc, /* i/o: pointer to the excitation frame Q_new */ + Word16 T0, /* i : integer pitch lag Q0 */ + Word16 T0_frac, /* i : fraction of lag */ + Word16 T0_res, /* i : pitch resolution */ + Word16 T0_res_max, /* i : maximum pitch resolution */ + Word16 mode, /* i : filtering mode (0: no, 1: yes, 2: adaptive) */ + Word16 i_subfr, /* i : subframe index */ + Word16 L_subfr, /* i : subframe length */ + Word16 L_frame, /* i : subframe length */ + Word16 *h1, /* i : impulse response of weighted synthesis filter 1Q14+shift */ + Word16 clip_gain, /* i : flag to indicate ??? */ + Word16 *xn, /* i : Close-loop Pitch search target vector Q_xn */ + Word16 *y1, /* o : zero-memory filtered adaptive excitation Q_xn */ + ACELP_CbkCorr *g_corr,/* o : ACELP correlation values */ + Word16 **pt_indice, /* i/o: quantization indices pointer */ + Word16 *pitch_gain, /* o : adaptive codebook gain 1Q14 */ + Word16 exp_xn /* i : exponent of xn (Q_xn-15) */ + ,Word16 rf_mode + ,Word16 rf_coder_type + ,Word16* lp_select + +) +{ + Word16 y2[L_SUBFR], xn2[L_SUBFR], code[L_SUBFR]; + ACELP_CbkCorr g_corr2; + Word16 gain1 = 0, gain2 = 0, fac_m, fac_n; + Word16 i, select, exp_ener; + Word32 L_tmp, L_ener; + const Word16 *pitch_inter; + Word16 pit_L_interpol, pit_up_samp; + Word16 use_prev_sf_pit_gain = 0; + + if( rf_mode == 1 && rf_coder_type == 100) + { + use_prev_sf_pit_gain = 1; + } + + BASOP_SATURATE_ERROR_ON; + + L_ener = L_deposit_l(0); + + /* find pitch excitation */ + /*for &exc[i_subfr]*/ + if (EQ_16(T0_res, shr(T0_res_max, 1))) + { + T0_frac = shl(T0_frac, 1); + } + + IF (EQ_16(T0_res_max, 6)&&rf_mode==0) + { + pitch_inter = pitch_inter6_2; + pit_L_interpol = PIT_L_INTERPOL6_2; + move16(); + pit_up_samp = PIT_UP_SAMP6; + move16(); + } + ELSE + { + pitch_inter = pitch_inter4_2; + pit_L_interpol = L_INTERPOL2; + move16(); + pit_up_samp = PIT_UP_SAMP; + move16(); + } + + pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, T0_frac, L_SUBFR+1, pitch_inter, pit_L_interpol, pit_up_samp); + + test(); + IF(EQ_16(mode,NORMAL_OPERATION)||(EQ_16(mode,FULL_BAND))) + { + E_UTIL_f_convolve(&exc[i_subfr], h1, y1,L_subfr); + + IF(use_prev_sf_pit_gain == 0) + { + gain1 = E_ACELP_xy1_corr(xn, y1, g_corr,1,L_subfr,exp_xn); + + /* clip gain if necessary to avoid problem at decoder */ test(); + if (clip_gain && GT_16(gain1,15565/*0.95 Q14*/)) + { + gain1 = 15565/*0.95f Q14*/; + move16(); + } + *pitch_gain = gain1; + move16(); + } + + /* find energy of new target xn2[] */ + E_ACELP_codebook_target_update(xn, xn2, y1, gain1, L_subfr); + L_ener = Dot_product12_offs(xn2, xn2, L_subfr, &exp_ener, 0); + L_ener = L_shr(L_ener,sub(31,exp_ener)); + } + + /*-----------------------------------------------------------------* + * - find pitch excitation filtered by 1st order LP filter. * + * - find filtered pitch exc. y2[]=exc[] convolved with h1[]) * + * - compute pitch gain2 * + *-----------------------------------------------------------------*/ test(); + IF(EQ_16(mode,NORMAL_OPERATION)||EQ_16(mode,LOW_PASS)) + { + /* find pitch excitation with lp filter */ + fac_m = 20972/*0.64f Q15*/; + move16(); + if ( EQ_16(L_frame,L_FRAME16k)) + { + fac_m = 19005/*0.58f Q15*/; + move16(); + } + /* fac_n = 0.5*(1.0-fac_m); */ + fac_n = mult_r(sub(0x7FFF,fac_m),0x4000); + FOR (i=0; iy1y1 = g_corr2.y1y1; + move16(); + g_corr->xy1 = g_corr2.xy1; + move16(); + g_corr->y1y1_e = g_corr2.y1y1_e; + move16(); + g_corr->xy1_e = g_corr2.xy1_e; + move16(); + } + ELSE + { + /* no filter used for pitch excitation prediction */ + select = FULL_BAND; + move16(); + *pitch_gain = gain1; + move16(); + } + + IF(EQ_16(mode,NORMAL_OPERATION)) + { + **pt_indice = select; + (*pt_indice)++; + move16(); + } + } + ELSE + { + /* no filter used for pitch excitation prediction */ + select = FULL_BAND; + move16(); + } + *lp_select=select; + + BASOP_SATURATE_ERROR_OFF; +} + + +/*--------------------------------------------------------------------------* + * E_ACELP_innovative_codebook + * + * Find innovative codebook. + *--------------------------------------------------------------------------*/ +void E_ACELP_innovative_codebook( + Word16 *exc, /* i : pointer to the excitation frame Q_new */ + Word16 T0, /* i : integer pitch lag Q0 */ + Word16 T0_frac, /* i : fraction of lag Q0 */ + Word16 T0_res, /* i : pitch resolution Q0 */ + Word16 gain_pit, /* i : adaptive codebook gain 1Q14 */ + Word16 tilt_code, /* i : tilt factor Q15 */ + Word16 mode, /* i : innovative codebook mode Q0 */ + Word16 formant_enh, /* i : use formant enhancement Q0 */ + Word16 formant_tilt, /* i : use tilt of formant enhancement Q0 */ + const Word16 formant_enh_num, /* i : formant sharpening numerator weighting */ + const Word16 formant_enh_den, /* i : formant sharpening denominator weighting */ + Word16 pitch_sharpening, /* i : use pitch sharpening Q0 */ + Word16 pre_emphasis, + Word16 phase_scrambling, + Word16 i_subfr, /* i : subframe index */ + const Word16 *Aq, /* i : quantized LPC coefficients 3Q12 */ + Word16 *h1, /* i : impulse response of weighted synthesis filter 1Q14+shift */ + Word16 *xn, /* i : Close-loop Pitch search target vector Q_xn */ + Word16 *cn, /* i : Innovative codebook search target vector Q_new */ + Word16 *y1, /* i : zero-memory filtered adaptive excitation Q_xn */ + Word16 *y2, /* o : zero-memory filtered algebraic excitation Q9 */ + Word8 acelpautoc, /* i : autocorrelation mode enabled */ + Word16 **pt_indice, /* i/o: quantization indices pointer */ + Word16 *code, /* o : innovative codebook Q9 Q9 */ + Word16 shift /* i : Scaling to get 12 bits */ + ,const Word16 L_frame, /* i : length of the frame */ + const Word16 last_L_frame,/* i : length of the last frame */ + const Word32 total_brate /* i : ttoal bit-rate */ +) +{ + Word16 xn2[L_SUBFR] /* Q_xn */, cn2[L_SUBFR] /* Q_xn */, dn[L_SUBFR] /* Rw2*cn2 */, h2[L_SUBFR] /* 4Q11 */; + Word16 Rw2[L_SUBFR]; + Word16 pitch; + + + pitch = T0; + move16(); + if (GT_16(T0_frac, shr(T0_res, 1))) + { + pitch = add(pitch,1); + } + + BASOP_SATURATE_ERROR_ON; + + /* Update target vector for ACELP codebook search */ + E_ACELP_codebook_target_update(xn, xn2, y1, gain_pit, L_SUBFR); + + /* Include fixed-gain pitch contribution into impulse resp. h1[] */ + Copy_Scale_sig(h1, h2, L_SUBFR, sub(-3, shift)); /*h2 1Q14+shift -> 4Q11, 1bit of headroom for Residu and xh_corr*/ + + cb_shape_fx(pre_emphasis, pitch_sharpening, phase_scrambling, formant_enh, formant_tilt, + formant_enh_num, formant_enh_den, Aq, h2, tilt_code, pitch, 1); + + /* Correlation between target xn2[] and impulse response h1[] */ + IF (acelpautoc) + { + /* h2: 4Q11, Rw2: (Rw2_e)Q */ + /* Rw2_e = */ E_ACELP_hh_corr(h2, Rw2, L_SUBFR, 3); + + E_ACELP_conv(xn2, h2, cn2); + + /* dn_e -> Rw2_e*Q_xn */ + /*dn_e = */ E_ACELP_toeplitz_mul(Rw2,cn2,dn,L_SUBFR,sub((Word16)PulseConfTable[mode].nb_pulse, 24) > 0); + + } + ELSE + { + BASOP_SATURATE_WARNING_OFF; + E_ACELP_codebook_target_update(cn, cn2, &exc[i_subfr], gain_pit, L_SUBFR); + BASOP_SATURATE_WARNING_ON; + Scale_sig(cn2, L_SUBFR, shift); + E_ACELP_xh_corr(xn2, dn, h2, L_SUBFR); + } + + /* Innovative codebook search */ + assert(mode < ACELP_FIXED_CDK_NB); + + E_ACELP_4t( dn, cn2, h2, Rw2, acelpautoc, code, mode, *pt_indice, L_frame, last_L_frame, total_brate, i_subfr ); + + *pt_indice += 8; + + /* Generate weighted code */ + E_ACELP_weighted_code(code, h2, 11, y2); + + /*-------------------------------------------------------* + * - Add the fixed-gain pitch contribution to code[]. * + *-------------------------------------------------------*/ + + cb_shape_fx(pre_emphasis, pitch_sharpening, phase_scrambling, formant_enh, formant_tilt, + formant_enh_num, formant_enh_den, Aq, code, tilt_code, pitch, 1); + + BASOP_SATURATE_ERROR_OFF; +} + + + +/*--------------------------------------------------------------------------* + * E_ACELP_codearithp + * + * Fixed bit-length arithmetic coding of pulses + * v - (input) pulse vector + * ps - (output) encoded state + * n - (output) range of possible states (0...n-1) + * p - (output) number of pulses found + *--------------------------------------------------------------------------*/ +void E_ACELP_codearithp(const Word16 v[], UWord32 *n, UWord32 *ps, Word16 *p) +{ + Word16 k, nb_pulse, i, t, pos[NPMAXPT], posno; + Word16 sign, m; + UWord32 s; + + /* Collect different pulse positions to pos[], number of them to posno */ + posno = 0; + move16(); + t = 0; + move16(); + FOR (k=0; k= 0 ) + { + BREAK; + } + } + + /* Iterate over the different pulse positions */ + s = L_deposit_l(0); + t = 0; + move16(); + nb_pulse = 0; + move16(); + FOR (k=0; k= 0 ) + { + BREAK; + } + } + + /* Code sign */ + /* We use L_add_c since we want to work with unsigned UWord32 */ + /* Therefore, we have to clear carry */ + Carry = 0; + s = L_lshl(s, 1); + if (sign < 0) + { + s = L_add_c(s, 1); + } + + /* Code last pulse */ + Carry = 0; + s = L_add_c(s, pulsestostates[pos[k]][t]); + t = add(t, 1); + } + + *ps = s; + move32(); + *n = L_deposit_l(0); + if (nb_pulse) + { + *n = pulsestostates[NB_POS_FCB_4T][nb_pulse-1]; + move32(); + } + + *p = nb_pulse; + move16(); +} + +void fcb_pulse_track_joint(UWord16 *idxs, Word16 wordcnt, UWord32 *index_n, Word16 *pulse_num, Word16 track_num) +{ + Word16 hi_to_low[10]; + UWord32 index, index_mask; + Word32 indx_tmp; + Word16 indx_flag, indx_flag_1; + Word16 track, track_num1, pulse_num0, pulse_num1; + Word16 indx_flag_2; + + Copy(hi_to_low_tmpl, hi_to_low, 10); + + indx_flag = 0; + move16(); + indx_flag_1 = 0; + move16(); + indx_flag_2 = 0; + move16(); + + FOR (track = 0; track < track_num; track++) + { + indx_flag = add(indx_flag, shr(pulse_num[track], 2)); + indx_flag_1 = add(indx_flag_1, shr(pulse_num[track], 1)); + indx_flag_2 = add(indx_flag_2, shr(pulse_num[track], 3)); + } + + IF (GE_16(indx_flag_2, 1)) + { + hi_to_low[7] = 9; + move16(); + index_mask = 0xFFFFFF; + move32(); + } + ELSE + { + if (LT_16(indx_flag, track_num)) + { + hi_to_low[4] = 1; + move16(); + } + index_mask = L_shr(0xFFFF, sub(9, hi_to_low[4])); + } + + IF (GE_16(indx_flag_1, track_num)) + { + indx_tmp = L_deposit_l(0); + index = L_shr(index_n[0], low_len[pulse_num[0]]); + FOR (track = 1; track < track_num; track++) + { + pulse_num0 = pulse_num[track - 1]; + move16(); + pulse_num1 = pulse_num[track]; + move16(); + indx_tmp = L_lshr(index_n[track], low_len[pulse_num1]); + /* index = index * indx_fact[pulse_num1] + indx_tmp; */ + index = UL_Mpy_32_32(index, UL_deposit_l(indx_fact[pulse_num1])); + index = UL_addNsD(index, indx_tmp); + index_n[track - 1] = L_add(L_and(index_n[track - 1], low_mask[pulse_num0]), + L_and(L_lshl(index, low_len[pulse_num0]), index_mask)); + + index = L_lshr(index, hi_to_low[pulse_num0]); + } + track_num1 = sub(track_num, 1); + pulse_num1 = pulse_num[track_num1]; + move16(); + index_n[track_num1] = L_and(L_add(L_and(index_n[track_num1], low_mask[pulse_num1]), + L_lshl(index, low_len[pulse_num1])), index_mask); + index = L_lshr(index, hi_to_low[pulse_num1]); + IF (GE_16(indx_flag, track_num)) + { + IF (GE_16(indx_flag_2, 1)) + { + idxs[0] = extract_l(index_n[0]); + idxs[1] = extract_l(L_add(L_lshl(index_n[1], 8), L_lshr(index_n[0], 16))); + idxs[2] = extract_l(L_lshr(index_n[1], 8)); + idxs[3] = extract_l(index_n[2]); + idxs[4] = extract_l(L_add(L_lshl(index_n[3], 8), L_lshr(index_n[2], 16))); + idxs[5] = extract_l(L_lshr(index_n[3], 8)); + track = 6; + move16(); + } + ELSE + { + FOR (track = 0; track < track_num; track++) + { + idxs[track] = extract_l(index_n[track]); + } + } + } + ELSE + { + idxs[0] = extract_l(L_add(L_lshl(index_n[0], 8), index_n[1])); + idxs[1] = extract_l(L_add(L_lshl(index_n[2], 8), index_n[3])); + track = 2; + move16(); + } + } + ELSE + { + index = index_n[0]; + move32(); + FOR (track = 1; track < 4; track++) + { + pulse_num1 = pulse_num[track]; + index = L_add(L_lshl(index, index_len[pulse_num1]), index_n[track]); + } + track = 0; + move16(); + } + FOR (; track < wordcnt; track++) + { + idxs[track] = extract_l(index); + index = L_lshr(index, 16); + } +} diff --git a/lib_enc/enc_acelp_tcx_main.c b/lib_enc/enc_acelp_tcx_main.c new file mode 100644 index 0000000..7a3d82d --- /dev/null +++ b/lib_enc/enc_acelp_tcx_main.c @@ -0,0 +1,114 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "prot_fx.h" +#include "options.h" +#include "cnst_fx.h" +#include "stl.h" + + +void enc_acelp_tcx_main( + const Word16 new_samples[], /* i : new samples */ + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 coder_type, /* i : coding type */ + const Word16 pitch[3], /* i : open-loop pitch values for quantiz. */ + const Word16 voicing[3], /* i : open-loop pitch gains */ + Word16 Aw[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/ + const Word16 lsp_new[M], /* i : LSPs at the end of the frame */ + const Word16 lsp_mid[M], /* i : LSPs at the middle of the frame */ + HANDLE_FD_CNG_ENC hFdCngEnc, /* i/o: FD CNG handle */ + Word32 bwe_exc_extended[], /* i/o: bandwidth extended excitation */ + Word16 *voice_factors, /* o : voicing factors */ + Word16 pitch_buf[], /* o : floating pitch for each subframe */ + Word16 vad_hover_flag, + const Word16 vad_flag_dtx, + Word16 *Q_new, + Word16 *shift +) +{ + Word16 old_bwe_exc[(PIT16k_MAX + (L_FRAME16k + 1) + L_SUBFR16k) * 2]; /* excitation buffer */ + Word16 *ptr_bwe_exc; + ptr_bwe_exc = old_bwe_exc + PIT16k_MAX * 2; + + IF( EQ_16( st->last_core_fx, ACELP_CORE)) + { + set16_fx( old_bwe_exc + PIT16k_MAX * 2, 0, ((L_FRAME16k + 1) + L_SUBFR16k) * 2 ); + Copy( st->old_bwe_exc_fx, old_bwe_exc, PIT16k_MAX * 2 ); + } + ELSE + { + set16_fx( old_bwe_exc, 0, ((L_FRAME16k + 1) + L_SUBFR16k + PIT16k_MAX) * 2 ); + } + + /* PLC: [Guided ACELP PLC] */ + gPLC_encInfo(&st->plcExt, + st->total_brate_fx, + st->bwidth_fx, + st->clas_fx, + coder_type + ); + + IF ( s_and(st->core_brate_fx!=FRAME_NO_DATA, st->core_brate_fx!=SID_2k40) ) + { + + /* Run Core Coder */ + IF (st->tcxonly == 0) + { + core_encode_openloop( st, coder_type, + pitch, + voicing, Aw, lsp_new, lsp_mid, + pitch_buf, voice_factors, ptr_bwe_exc, + vad_hover_flag, vad_flag_dtx, *Q_new, *shift ); + } + ELSE + { + core_encode_twodiv( new_samples, + st, coder_type, pitch, voicing, Aw, Q_new, shift ); + } + /*-----------------------------------------------------------------* + * Apply non linearity to the SHB excitation + *-----------------------------------------------------------------*/ + + + test(); + IF( EQ_16( st->core_fx, ACELP_CORE )&&st->igf!=0) + { + non_linearity_fx( ptr_bwe_exc, bwe_exc_extended, L_FRAME32k, &st->bwe_non_lin_prev_scale_fx, *Q_new + , coder_type, voice_factors, st->L_frame_fx + ); + + /* update the old BWE exe memory */ + Copy( &old_bwe_exc[L_FRAME32k], st->old_bwe_exc_fx, PIT16k_MAX * 2 ); + } + ELSE + { + set16_fx( st->old_bwe_exc_extended_fx, 0, NL_BUFF_OFFSET ); + set16_fx( st->old_bwe_exc_fx, 0, PIT16k_MAX * 2 ); + st->bwe_non_lin_prev_scale_fx = 0; + } + } + ELSE + { + /* Run SID Coder */ + IF ( st->core_brate_fx == SID_2k40 ) + { + FdCng_encodeSID( hFdCngEnc, st, st->preemph_fac ); + } + + /* Generate Comfort Noise */ + generate_comfort_noise_enc( st, *Q_new, 1 ); + + /* Update Core Encoder */ + core_encode_update_cng( st, hFdCngEnc->hFdCngCom->timeDomainBuffer, hFdCngEnc->hFdCngCom->A_cng, Aw, *Q_new, *shift ); + } + + /* coreSwitching update of MODE1 parameters in the last frame */ + st->last_coder_type_fx = coder_type; + + + return; +} diff --git a/lib_enc/enc_acelpx.c b/lib_enc/enc_acelpx.c new file mode 100644 index 0000000..7d66440 --- /dev/null +++ b/lib_enc/enc_acelpx.c @@ -0,0 +1,541 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include "stl.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "options.h" +#include "rom_enc_fx.h" + +#define _1_Q11 (2048/*1.0f Q11*/) /* 1.0f in 4Q11 */ + +static void E_ACELP_update_cor( + const Word16 pos[], /* i */ + Word16 nb_pulse, /* i */ + const Word16 sign[], /* i */ + const Word16 R[], /* i */ + const Word16 cor_in[], /* i */ + Word16 cor_out[] /* o */ +) +{ + Word16 sign_x, sign_y; + const Word16 *pRx, *pRy; + Word16 i, tmp; + + IF (EQ_16(nb_pulse, 2)) + { + /* Update product of autocorrelation and already fixed pulses. with the + * two newly found ones */ + sign_x = sign[pos[0]]; + move16(); + sign_y = sign[pos[1]]; + move16(); + + IF (s_xor(sign_x, sign_y) < 0) + { + i = 1; + move16(); + if (sign_x > 0) + { + i = 0; + move16(); + } + pRx = R-pos[i]; + pRy = R-pos[1-i]; + /* different sign x and y */ + FOR (i=0; i 0) + { + /* sign x and y is positive */ + FOR (i=0; i 0 in the first iteration, the actual values do not matter. */ + sqk[0] = -1; + move16(); + alpk[0] = 1; + move16(); + x = pos_x[0]; + move16(); + sgnx = sign[track_y]; + move16(); + if (sign[x] < 0) + { + sgnx = negate(sgnx); + } + if (mac_r(L_mac(L_mac(alp0, cor[x], sign[x]), cor[track_y], sign[track_y]), R[track_y-x], sgnx) < 0) + { + sqk[0] = 1; + move16(); + } + ik = 0; + move16(); + + xy_save = L_mac0(L_deposit_l(track_y), track_x, L_SUBFR); + + /* loop track 1 */ + FOR (i=0; i 0) + { + alp2_16 = mac_r(alp2, pR[y], sign[y]); /* Qalp = (Q_R=Q_cor)*Q_signval */ + } + if (sgnx < 0) + { + alp2_16 = msu_r(alp2, pR[y], sign[y]); /* Qalp = (Q_R=Q_cor)*Q_signval */ + } + alpk[1-ik] = alp2_16; + move16(); + + /*sq = ps2 * ps2; MULT(1);*/ + sq = mult_r(ps2, ps2); /* (3+3)Q -> 6Q9 */ + sqk[1-ik] = sq; + move16(); + + + /*s = (alpk * sq) - (sqk * alp2); MULT(1);MAC(1);*/ + s = L_msu(L_mult(alpk[ik], sq), sqk[ik], alp2_16); /* Q_sq = Q_sqk, Q_alpk = Q_alp */ + if (s > 0) + { + ik = sub(1, ik); + } + if (s > 0) + { + xy_save = L_mac0(y, x, L_SUBFR); + } + assert( ((s >= 0 && i==0 && y == track_y)) || (y > track_y) || (i > 0)); + } + } + ps1 = extract_l(xy_save); + pos[1] = s_and(ps1, L_SUBFR-1); + move16(); + pos[0] = lshr(ps1, 6); + move16(); + /* Update numerator */ + *ps = add(add(ps0,dn[pos[0]]),dn[pos[1]]); + move16(); + + /* Update denominator */ + *alp = alpk[ik]; + move16(); + + E_ACELP_update_cor(pos, 2, sign, R, cor, cor); + + *ix = pos[0]; + move16(); + *iy = pos[1]; + move16(); + + assert(((pos[0] & 3) == track_x) && ((pos[1] & 3) == track_y)); /* sanity check */ +} + + +/* static */ +static void E_ACELP_1pulse_searchx(UWord8 tracks[2], + Word16 *R, Word16 *ps, Word16 *alp, + Word16 *ix, Word16 dn[], + Word16 cor[], Word16 sign[], Word16 sign_val_1) +{ + Word16 x, x_save = 0; + Word16 ps0; + Word32 alp0; + Word16 ps1, sq; + Word16 alp1; + Word32 s; + Word16 ntracks, t; + Word16 sqk[2], alpk[2], ik; + + /* save these to limit memory searches */ + /*alp0 = *alp + R[0]; INDIRECT(1);*/ + ps0 = *ps; + move16(); + alp0 = L_deposit_h(*alp); + alp0 = L_mac(alp0, R[0], sign_val_1); /* Qalp = (Q_R=Q_cor)*Q_signval */ + + /* Ensure that in the loop below s > 0 in the first iteration, the actual values do not matter. */ + move16(); + move16(); + alpk[0] = 1; + sqk[0] = -1; + ik = 0; + move16(); + if (mac_r(alp0, cor[tracks[0]], sign[tracks[0]]) < 0) + { + sqk[0] = 1; + move16(); + } + + x_save = tracks[0]; + move16(); + + ntracks = 1; + if (NE_16(tracks[1], tracks[0])) + { + ntracks = 2; + move16(); + } + FOR (t=0; t 0) + { + ik = sub(1, ik); + } + if (s > 0) + { + x_save = x; + move16(); + } + assert( t>0 || ((s >= 0) && (x == tracks[t])) || x > tracks[t]); + } + } + + *ps = add(ps0, dn[x_save]); + move16(); + *alp = alpk[ik]; + move16(); + *ix = x_save; + move16(); +} + + +/* Autocorrelation method for searching pulse positions effectively + * Algorithm is identical to traditional covariance method. */ +void E_ACELP_4tsearchx(Word16 dn[], const Word16 cn[], Word16 Rw[], Word16 code[], const PulseConfig *config, Word16 ind[]) +{ + Word16 sign[L_SUBFR], vec[L_SUBFR]; + Word16 cor[L_SUBFR]; + Word16 R_buf[2*L_SUBFR-1], *R; + Word16 dn2[L_SUBFR]; + Word16 ps2k, ps /* same format as dn[] */, ps2, alpk, alp = 0 /* Q13 and later Q_Rw*Q_signval=Q_cor*Q_signval */; + Word32 s; + Word16 codvec[NB_PULSE_MAX]; + Word16 pos_max[4]; + Word16 dn2_pos[8 * 4]; + UWord8 ipos[NB_PULSE_MAX]; + Word16 i, j, k, st, pos = 0; + Word16 scale; + Word16 sign_val_1, sign_val_2; + Word16 nb_pulse, nb_pulse_m2; + + ps = 0; /* to avoid compilation warnings */ + + + + alp = config->alp; /* Q13 */ move16(); + nb_pulse = config->nb_pulse; + move16(); + nb_pulse_m2 = sub(nb_pulse, 2); + + /* Init to avoid crash when the search does not find a solution */ + FOR (k=0; k 0 in the first iteration, the actual values do not matter. */ + ps2k = -1; + move16(); + alpk = 1; + move16(); + + /* Number of iterations */ + FOR (k = 0; k < config->nbiter; k++) + { + E_ACELP_setup_pulse_search_pos(config, k, ipos); + + /* index to first non-fixed position */ + pos = config->fixedpulses; + move16(); + + IF (config->fixedpulses == 0)/* 1100, 11, 1110, 1111, 2211 */ + { + ps = 0; + move16(); + alp = 0; + move16(); + set16_fx(cor, 0, L_SUBFR); + } + ELSE + { + assert(config->fixedpulses == 2 || config->fixedpulses == 4); + + /* set fixed positions */ + FOR (i=0; ifixedpulses, sign, R, NULL, cor); + + /* normalisation contribution of fixed part */ + s = L_mult0(cor[ind[0]], sign[ind[0]]); + ps = dn[ind[0]]; + move16(); + FOR (i=1; i>1 sign = 2*/ + } + + /* other stages of 2 pulses */ + st = 0; + move16(); + FOR (j = pos; j < nb_pulse; j += 2) + { + IF (GE_16(nb_pulse_m2, j)) /* pair-wise search */ + { + /* + * Calculate correlation of all possible positions + * of the next 2 pulses with previous fixed pulses. + * Each pulse can have 16 possible positions. + */ + + E_ACELP_2pulse_searchx(config->nbpos[st], ipos[j], ipos[j + 1], R, &ps, &alp, + &ind[j], &ind[j+1], dn, dn2_pos, cor, sign, sign_val_2); + + } + ELSE /* single pulse search */ + { + E_ACELP_1pulse_searchx(&ipos[j], R, &ps, &alp, + &ind[j], dn, cor, sign, sign_val_1); + } + + + st = add(st, 1); + } + + /* memorise the best codevector */ + /*ps2 = ps * ps; MULT(1);*/ + ps2 = mult(ps, ps); + + /*s = (alpk * ps2) - (ps2k * alp); MULT(2);ADD(1);*/ + s = L_msu(L_mult(alpk, ps2), ps2k, alp); + + IF (s > 0) + { + ps2k = ps2; + move16(); + alpk = alp; + move16(); + Copy(ind, codvec, nb_pulse); + } + } + + + /* + * Store weighted energy of code, build the codeword and index of codevector. + */ + E_ACELP_build_code(nb_pulse, codvec, sign, code, ind); +} diff --git a/lib_enc/enc_amr_wb_fx.c b/lib_enc/enc_amr_wb_fx.c new file mode 100644 index 0000000..45b8af1 --- /dev/null +++ b/lib_enc/enc_amr_wb_fx.c @@ -0,0 +1,232 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" /* required by wmc_tool */ + +/*-------------------------------------------------------------------* + * encod_amr_wb() + * + * Encode excitation signal in AMR-WB IO mode + *-------------------------------------------------------------------*/ +void encod_amr_wb_fx( + Encoder_State_fx *st, /* i/o: state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 speech[], /* i : input speech */ + const Word16 Aw[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq[], /* i : 12k8 Lp coefficient */ + const Word16 pitch[3], /* i : open-loop pitch values for quantiz. */ + const Word16 voicing[], /* i : voicing */ + const Word16 *res, /* i : residual signal */ + Word16 *syn, /* i/o: core synthesis */ + Word16 *exc, /* i/o: current non-enhanced excitation */ + Word16 *exc2, /* i/o: current enhanced excitation */ + Word16 *pitch_buf, /* i/o: floating pitch values for each subframe */ + Word16 hf_gain_fx[NB_SUBFR], /* o : decoded HF gain */ + const Word16 *speech16k_fx, + Word16 shift, + Word16 Q_new +) +{ + Word16 xn[L_SUBFR]; /* Target vector for pitch search */ + Word16 xn2[L_SUBFR]; /* Target vector for codebook search */ + Word16 cn[L_SUBFR]; /* Target vector in residual domain */ + Word16 h1[L_SUBFR+(M+1)]; /* Impulse response vector */ + Word16 h2[L_SUBFR+(M+1)]; /* Impulse response vector */ + Word16 code[L_SUBFR]; /* Fixed codebook excitation */ + Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */ + Word16 y2[L_SUBFR]; /* Filtered algebraic excitation */ + Word16 gain_pit ; /* Pitch gain */ + Word16 voice_fac; /* Voicing factor */ + Word32 gain_code; /* Gain of code */ + Word16 gain_inov; /* inovation gain */ + Word16 i, i_subfr; /* tmp variables */ + Word16 T0, T0_frac; /* close loop integer pitch and fractional part */ + Word16 T0_min, T0_max; /* pitch variables */ + Word16 *pt_pitch; /* pointer to floating pitch buffer */ + Word16 g_corr[10]; /* ACELP correl, values + gain pitch */ + Word16 clip_gain; /* LSF clip gain */ + const Word16 *p_Aw, *p_Aq; /* pointer to LP filter coeff. vector*/ + Word16 unbits; + Word32 norm_gain_code; + Word16 pitch_limit_flag; + Word16 shift_wsp; + Word32 L_tmp; + Word16 gcode16; + Word32 Ltmp; + Word32 Lgcode; + Word16 T_op[3]; /* pitch period for quantization */ + Word16 lp_select, lp_flag; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + set16_fx( y2, 0, L_SUBFR ); + set16_fx( code, 0, L_SUBFR ); + + pitch_limit_flag = 0; + move16(); /* always restrained pitch Q range in IO mode */ + T0_max = PIT_MAX; + move16(); + T0_min = PIT_MIN; + move16(); + unbits = 0; + move16(); + + p_Aw = Aw; + p_Aq = Aq; + pt_pitch = pitch_buf; + shift_wsp = add(Q_new,shift); + + Copy( pitch, T_op, 2 ); + if (LE_16(T_op[0],PIT_MIN)) + { + T_op[0] = shl(T_op[0],1); + move16(); + } + + if (LE_16(T_op[1],PIT_MIN)) + { + /*T_op[1] *= 2;*/ + T_op[1] = shl(T_op[1],1); + move16(); + } + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + FOR ( i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR ) + { + /*----------------------------------------------------------------* + * Bandwidth expansion of A(z) filter coefficients + * Find the the excitation search target "xn" and innovation + * target in residual domain "cn" + * Compute impulse response, h1[], of weighted synthesis filter + *----------------------------------------------------------------*/ + Copy( &res[i_subfr], &exc[i_subfr], L_SUBFR ); + + find_targets_fx( speech, mem->mem_syn, i_subfr, &mem->mem_w0, p_Aq, + res, L_SUBFR, p_Aw, TILT_FAC_FX, xn, cn, h1 ); + + Copy_Scale_sig(h1, h2, L_SUBFR, -2); + Scale_sig(h1, L_SUBFR, add(1, shift)); /* set h1[] in Q14 with scaling for convolution */ + + /* scaling of xn[] to limit dynamic at 12 bits */ + Scale_sig(xn, L_SUBFR, shift); + + /*----------------------------------------------------------------* + * Close-loop pitch search and quantization + * Adaptive exc. construction + *----------------------------------------------------------------*/ + + *pt_pitch = pit_encode_fx(st, st->core_brate_fx, 1, L_FRAME, -1, &pitch_limit_flag, i_subfr, exc, + L_SUBFR, T_op, &T0_min, &T0_max, &T0, &T0_frac, h1, xn ); + + /*-----------------------------------------------------------------* + * Find adaptive exitation + *-----------------------------------------------------------------*/ + + pred_lt4(&exc[i_subfr], &exc[i_subfr], T0, T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP); + + /*-----------------------------------------------------------------* + * Gain clipping test to avoid unstable synthesis on frame erasure + * or in case of floating point encoder & fixed p. decoder + *-----------------------------------------------------------------*/ + + clip_gain = gp_clip_fx( st->core_brate_fx, voicing, i_subfr, 0, xn, st->clip_var_fx, sub(shift_wsp,1)); + + /*-----------------------------------------------------------------* + * LP filtering of the adaptive excitation, codebook target computation + *-----------------------------------------------------------------*/ + + lp_select = lp_filt_exc_enc_fx( MODE1, st->core_brate_fx, 1, -1, i_subfr, exc, h1, + xn, y1, xn2, L_SUBFR, L_FRAME, g_corr, clip_gain, &gain_pit, &lp_flag ); + + IF( EQ_16(lp_flag,NORMAL_OPERATION)) + { + push_indice_fx( st, IND_LP_FILT_SELECT, lp_select, 1 ); + } + + /*-----------------------------------------------------------------* + * Innovation encoding + *-----------------------------------------------------------------*/ + inov_encode_fx( st, st->core_brate_fx, 1, L_FRAME, st->last_L_frame_fx, -1, -1, 0, i_subfr, -1, p_Aq, gain_pit, cn, + exc, h2, mem->tilt_code, *pt_pitch, xn2, code, y2, &unbits, shift ); + /*-----------------------------------------------------------------* + * Gain encoding + * Pitch gain clipping test + * Estimate spectrum tilt and voicing + *-----------------------------------------------------------------*/ + gain_enc_amr_wb_fx( st, xn, shift_wsp, y1, y2, code, st->core_brate_fx, &gain_pit, &gain_code, + &gain_inov, &norm_gain_code, g_corr, clip_gain, st->past_qua_en_fx ); + + gp_clip_test_gain_pit_fx( st->core_brate_fx, gain_pit, st->clip_var_fx ); + Lgcode = L_shl(gain_code, Q_new); /* scaled gain_code with Qnew -> Q16*/ + gcode16 = round_fx(Lgcode); + + mem->tilt_code = Est_tilt2( exc+i_subfr, gain_pit, code, Lgcode, &voice_fac, shift ); + + FOR (i = 0; i < L_SUBFR; i++) + { + exc2[i+i_subfr] = round_fx(L_shl(L_mult(gain_pit,exc[i+i_subfr]),1)); + } + + /*-----------------------------------------------------------------* + * Update memory of the weighting filter + *-----------------------------------------------------------------*/ + + /*st->mem_w0 = xn[L_SUBFR-1] - gain_pit * y1[L_SUBFR-1] - gain_code * y2[L_SUBFR-1];*/ + Ltmp = L_mult(gcode16, y2[L_SUBFR - 1]); + Ltmp = L_shl(Ltmp, add(5, shift)); + Ltmp = L_negate(Ltmp); + Ltmp = L_mac(Ltmp, xn[L_SUBFR - 1], 16384); + Ltmp = L_msu(Ltmp, y1[L_SUBFR - 1], gain_pit); + Ltmp = L_shl(Ltmp, sub(1, shift)); + mem->mem_w0 = round_fx(Ltmp); /*Q_new-1 */ + + /*-----------------------------------------------------------------* + * Find the total excitation + *-----------------------------------------------------------------*/ + FOR (i = 0; i < L_SUBFR; i++) + { + L_tmp = L_mult(gcode16, code[i]); + L_tmp = L_shl(L_tmp, 5); + L_tmp = L_mac(L_tmp, exc[i + i_subfr], gain_pit); + L_tmp = L_shl(L_tmp, 1); /* saturation can occur here */ + exc[i + i_subfr] = round_fx(L_tmp); + } + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[] + * Update A(z) filters + *-----------------------------------------------------------------*/ + Syn_filt_s(1, p_Aq, M, &exc[i_subfr], &syn[i_subfr], L_SUBFR, mem->mem_syn, 1 ); + + /*-----------------------------------------------------------------* + * HF gain modification factors at 23.85 kbps + *-----------------------------------------------------------------*/ + + IF ( EQ_32(st->core_brate_fx,ACELP_23k85)) + { + IF( GE_32(st->input_Fs_fx,16000)) + { + hf_cod_fx( st->core_brate_fx, &speech16k_fx[i_subfr * L_SUBFR16k/L_SUBFR], Aq, &exc[i_subfr], &syn[i_subfr], + &st->seed2_enc_fx, st->mem_hp400_enc_fx, st->mem_syn_hf_enc_fx, st->mem_hf_enc_fx, st->mem_hf2_enc_fx, + st->hangover_cnt_fx, &st->gain_alpha_fx, &hf_gain_fx[i_subfr/L_SUBFR], add(Q_new,1), st->Q_syn); + } + + push_indice_fx(st, IND_HF_GAIN_MODIFICATION, hf_gain_fx[i_subfr/L_SUBFR], 4 ); + } + + p_Aw += (M+1); + p_Aq += (M+1); + pt_pitch++; + } + + return; +} diff --git a/lib_enc/enc_gain.c b/lib_enc/enc_gain.c new file mode 100644 index 0000000..23c64cb --- /dev/null +++ b/lib_enc/enc_gain.c @@ -0,0 +1,395 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include +#include "stl.h" +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "basop_util.h" + + +/* + * E_GAIN_norm_corr + * + * Parameters: + * exc I: excitation buffer (Q_new) + * xn I: target signal (Q_new+shift-1) + * h I: weighted synthesis filter impulse response (Q14+shift) + * t0_min I: minimum value in the searched range + * t0_max I: maximum value in the searched range + * corr_norm O: normalized correlation (Q15+(Q_new+shift-1)+scale) + * + * Function: + * Find the normalized correlation between the target vector and the + * filtered past excitation (correlation between target and filtered + * excitation divided by the square root of energy of filtered excitation) + * Size of subframe = L_SUBFR. + * + * Returns: + * void + */ +void E_GAIN_norm_corr(Word16 exc[], Word16 xn[], Word16 h[], + Word16 t_min, Word16 t_max, Word16 corr_norm[], Word16 L_subfr) +{ + Word16 excf[L_SUBFR]; /* filtered past excitation (Q_new+shift-1) */ + Word16 ps, norm, exp_alp, exp_ps, scale, L_subfr2; + Word16 t, j, k; + Word32 L_tmp, L_tmp2; + + + k = negate(t_min); + L_subfr2 = shr(L_subfr, 1); + + /* compute the filtered excitation for the first delay t_min */ + E_UTIL_f_convolve(&exc[k], h, excf,L_subfr); + + /* Compute rounded down 1/sqrt(energy of xn[]) */ + Dot_product12_offs(xn, xn, L_subfr, &scale, 1); + + scale = add(scale, 2+1); /* energy of xn[] x 2 + rounded up */ + scale = negate(shr(scale, 1)); /* (1< 0; j--) + { + /*excf[j] = excf[j - 1] + exc[k] * h[j]; MAC(1); STORE(1);*/ + /* saturation can occur in add() */ + excf[j] = add(mult_r(exc[k], h[j]), excf[j - 1]); + move16(); + + } + excf[0] = mult_r(exc[k],h[0]); + move16(); + } + /* Last reduced iteration for t=t_max */ + L_tmp = Dot_product12_offs(xn, excf, L_subfr, &exp_ps, 1); + ps = extract_h(L_tmp); + + + /* Compute 1/sqrt(energy of excf[]) */ + L_tmp = Dot_product12_offs(excf, excf, L_subfr2, NULL, 1); + L_tmp2 = Dot_product12_offs(excf+L_subfr2, excf+L_subfr2, L_subfr2, NULL, 1); + exp_alp = sub(s_min(norm_l(L_tmp), norm_l(L_tmp2)), 1); + L_tmp = L_add(L_shl(L_tmp, exp_alp), L_shl(L_tmp2, exp_alp)); + exp_alp = sub(31+1, exp_alp); + + + /*norm = (Float32)(1.0F / sqrt(alp)); SQRT(1);*/ + L_tmp = ISqrt32(L_tmp, &exp_alp); + norm = extract_h(L_tmp); + + /* Normalize correlation = correlation * (1/sqrt(energy)) */ + /*corr_norm[t-t_min] = ps * norm; MULT(1); STORE(1);*/ + L_tmp = L_mult(ps, norm); + L_tmp = L_shl(L_tmp, add(add(exp_ps, exp_alp), scale)); + corr_norm[t-t_min] = round_fx(L_tmp); + + return; +} + + +/* + * E_GAIN_norm_corr_interpolate + * + * Parameters: + * x I: input vector + * frac I: fraction (-4..+3) + * + * Function: + * Interpolating the normalized correlation + * + * Returns: + * interpolated value + */ +static Word16 E_GAIN_norm_corr_interpolate(Word16 *x, Word16 frac) +{ + Word16 *x1, *x2, i; + const Word16 *c1, *c2; + Word32 s; + + IF (frac < 0) + { + frac = add(frac,4); + x--; + } + + x1 = &x[0]; + x2 = &x[1]; + c1 = &E_ROM_inter4_1[frac]; + c2 = &E_ROM_inter4_1[4 - frac]; + + /*s = x1[0] * c1[0] + x2[0] * c2[0]; + s += x1[-1] * c1[4] + x2[1] * c2[4]; + s += x1[-2] * c1[8] + x2[2] * c2[8]; + s += x1[-3] * c1[12] + x2[3] * c2[12];*/ + + s = L_deposit_l(0); + FOR (i = 0; i < 4; i++) + { + s = L_mac(s,*x1--,*c1); + s = L_mac(s,*x2++,*c2); + c1 += 4; + c2 += 4; + } + + return round_fx(L_shl(s, 1)); +} + +static Word16 E_GAIN_norm_corr_interpolate6(Word16 *x, Word16 frac) +{ + Word16 *x1, *x2, i; + const Word16 *c1, *c2; + Word32 s; + + IF (frac < 0) + { + frac = add(frac,6); + x--; + } + + x1 = &x[0]; + x2 = &x[1]; + c1 = &E_ROM_inter6_1[frac]; + c2 = &E_ROM_inter6_1[6 - frac]; + + /*s = x1[0] * c1[0] + x2[0] * c2[0]; + s += x1[-1] * c1[6] + x2[1] * c2[6]; + s += x1[-2] * c1[12] + x2[2] * c2[12]; + s += x1[-3] * c1[18] + x2[3] * c2[18];*/ + s = L_deposit_l(0); + FOR (i = 0; i < 4; i++) + { + s = L_mac(s,*x1--,*c1); + s = L_mac(s,*x2++,*c2); + c1 += 6; + c2 += 6; + } + + return round_fx(L_shl(s, 1)); +} + +/* + * E_GAIN_closed_loop_search + * + * Parameters: + * exc I: excitation buffer + * xn I: target signal + * h I: weighted synthesis filter impulse response + * dn I: residual domain target signal + * t0_min I: minimum value in the searched range + * t0_max I: maximum value in the searched range + * pit_frac O: chosen fraction + * i_subfr I: flag to first subframe + * t0_fr2 I: minimum value for resolution 1/2 + * t0_fr1 I: minimum value for resolution 1 + * + * Function: + * Find the closed loop pitch period with 1/4 subsample resolution. + * + * Returns: + * chosen integer pitch lag + */ +Word16 E_GAIN_closed_loop_search(Word16 exc[], + Word16 xn[], Word16 h[], + Word16 t0_min, Word16 t0_min_frac, Word16 t0_max, Word16 t0_max_frac, Word16 t0_min_max_res, Word16 *pit_frac, Word16 *pit_res, Word16 pit_res_max, + Word16 i_subfr, Word16 pit_min, Word16 pit_fr2, Word16 pit_fr1, Word16 L_subfr) +{ + Word16 corr_v[32 + 2 * L_INTERPOL1 + 1]; + Word16 cor_max, max, temp; + Word16 *corr; + Word16 i, fraction, frac1, frac2, step; + Word16 t0, t_min, t_max; + + set16_fx(corr_v, 0, 32 + 2 * L_INTERPOL1 + 1); + /* Find interval to compute normalized correlation */ + if (t0_min_frac>0) + { + t0_min = add(t0_min,1); + } + t_min = sub(t0_min,L_INTERPOL1); + t_max = add(t0_max,L_INTERPOL1); + + /* allocate memory to normalized correlation vector */ + corr = &corr_v[negate(t_min)]; /* corr[t_min..t_max] */ + + /* Compute normalized correlation between target and filtered excitation */ + E_GAIN_norm_corr(exc, xn, h, t_min, t_max, corr_v, L_subfr); + + /* find integer pitch */ + max = corr[t0_min]; + move16(); + t0 = t0_min; + move16(); + + FOR(i = t0_min + 1; i <= t0_max; i++) + { + BASOP_SATURATE_WARNING_OFF; + if( GE_16(corr[i],max)) + { + t0 = i; + move16(); + } + max = s_max(max, corr[i]); + BASOP_SATURATE_WARNING_ON; + } + + + + /* If first subframe and t0 >= pit_fr1, do not search fractionnal pitch */ + test(); + IF((i_subfr == 0) && GE_16(t0,pit_fr1)) + { + *pit_frac = 0; + move16(); + *pit_res = 1; + move16(); + return(t0); + } + + + /* + * Search fractionnal pitch + * Test the fractions around t0 and choose the one which maximizes + * the interpolated normalized correlation. + */ + + IF ( EQ_16(t0_min_max_res,shr(pit_res_max,1))) + { + t0_min_frac = shl(t0_min_frac,1); + t0_max_frac = shl(t0_max_frac,1); + } + + step = 1; + frac1 = sub(1,pit_res_max); + frac2 = sub(pit_res_max,1); + + test(); + test(); + IF (((i_subfr == 0) && GE_16(t0,pit_fr2))||LE_16(pit_fr2,pit_min)) + { + step = 2; + frac1 = sub(2,pit_res_max); + frac2 = sub(pit_res_max,2); + } + test(); + IF ( (EQ_16(t0,t0_min))&&(t0_min_frac==0)) + { + frac1 = t0_min_frac; + move16(); + } + ELSE + { + test(); + IF ( (EQ_16(t0,t0_min))&&(LT_16(add(frac1,pit_res_max),t0_min_frac))) + { + frac1 = sub(t0_min_frac,pit_res_max); + } + } + + if (EQ_16(t0,t0_max)) + { + frac2 = t0_max_frac; + move16(); + } + assert(frac1<=0 && frac2>=0 && frac2>frac1); + + IF (EQ_16(pit_res_max,6)) + { + cor_max = E_GAIN_norm_corr_interpolate6(&corr[t0], frac1); + fraction = frac1; + + FOR (i = (frac1 + step); i <= frac2; i += step) + { + temp = E_GAIN_norm_corr_interpolate6(&corr[t0], i); + IF (GT_16(temp,cor_max)) + { + cor_max = temp; + move16(); + fraction = i; + move16(); + } + + } + } + ELSE + { + cor_max = E_GAIN_norm_corr_interpolate(&corr[t0], frac1); + fraction = frac1; + + FOR (i = (frac1 + step); i <= frac2; i += step) + { + temp = E_GAIN_norm_corr_interpolate(&corr[t0], i); + IF (GT_16(temp,cor_max)) + { + cor_max = temp; + move16(); + fraction = i; + move16(); + } + + } + } + + /* limit the fraction value */ + IF (fraction < 0) + { + fraction = add(fraction,pit_res_max); + t0 = sub(t0,1); + } + test(); + test(); + IF (((i_subfr == 0) && GE_16(t0,pit_fr2))||LE_16(pit_fr2,pit_min)) + { + *pit_res = shr(pit_res_max,1); + move16(); + *pit_frac = shr(fraction,1); + move16(); + } + ELSE + { + *pit_res = pit_res_max; + move16(); + *pit_frac = fraction; + move16(); + } + return (t0); +} + diff --git a/lib_enc/enc_gen_voic_fx.c b/lib_enc/enc_gen_voic_fx.c new file mode 100644 index 0000000..f34d500 --- /dev/null +++ b/lib_enc/enc_gen_voic_fx.c @@ -0,0 +1,382 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ + +#include "stl.h" + + +/*======================================================================*/ +/* FUNCTION : encod_gen_voic_fx() */ +/*----------------------------------------------------------------------*/ +/* PURPOSE : encode generic (GC), voiced (VC) and AMR-WB IO frames */ +/* */ +/*----------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Struct) st_fx : encoder static memory */ +/* _ (Word16) L_frame_fx : length of the frame Q0 */ + +/* _ (Word16[]) speech_fx : input speech Q0 */ +/* _ (Word16[]) Aq_fx : LP filter coefficient Q12 */ +/* _ (Word16[]) A_fx : unquantized A(z) filter */ +/* with bandwidth expansion Q12 */ +/* _ (Word16) coder_type_fx : coding type */ +/* _ (Word16) Es_pred_fx : predicted scaled innov. energy Q8 */ +/* _ (Word16[]) T_op_fx : open loop pitch Q0 */ +/* _ (Word16[]) voicing_fx : floating pitch values for each subframe Q15*/ +/* _ (Word16[]) res_fx : residual signal Q_new */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Q0) */ +/* _ (Word16[]) exc2_fx : adapt. excitation/total exc (Q0) */ +/* _ (Word16[]) pitch_buf_fx : floating pitch values for each subframe Q6*/ +/* _ (Word16) shift : shift */ +/* _ (Word16) Q_new : */ +/*-----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Q0) */ +/* _ (Word16[]) exc2_fx : adapt. excitation/total exc (Q0) */ +/* _ (Word16[]) syn_fx :core synthesis Q_new */ +/* _ (Word16[]) voice_factors_fx: voicing factors Q15 */ +/* _ (Word16[]) bwe_exc_fx : excitation for SWB TBE Q0 */ +/*-----------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*=======================================================================*/ + +void encod_gen_voic_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 L_frame_fx, /* i : length of the frame */ + const Word16 sharpFlag_fx, /* o : formant sharpening flag */ + const Word16 speech_fx[], /* i : input speech */ + const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */ + const Word16 coder_type_fx, /* i : coding type */ + const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */ + const Word16 T_op_fx[], /* i : open loop pitch */ + const Word16 voicing_fx[], /* i : voicing */ + const Word16 *res_fx, /* i : residual signal */ + Word16 *syn_fx, /* i/o: core synthesis */ + Word16 *exc_fx, /* i/o: current non-enhanced excitation */ + Word16 *exc2_fx, /* i/o: current enhanced excitation */ + Word16 *pitch_buf_fx, /* i/o: floating pitch values for each subframe */ + Word16 *voice_factors_fx, /* o : voicing factors */ + Word16 *bwe_exc_fx, /* o : excitation for SWB TBE */ + Word16 *unbits_fx, /* i/o: number of unused bits */ + Word16 shift, + Word16 Q_new +) +{ + Word16 xn_fx[L_SUBFR]; /* Target vector for pitch search */ + Word16 xn2_fx[L_SUBFR]; /* Target vector for codebook search */ + Word16 cn_fx[L_SUBFR]; /* Target vector in residual domain */ + Word16 h1_fx[L_SUBFR+(M+1)]; /* Impulse response vector */ + Word16 h2_fx[L_SUBFR+(M+1)]; /* Impulse response vector */ + Word16 code_fx[L_SUBFR]; /* Fixed codebook excitation */ + Word16 y1_fx[L_SUBFR]= {0}; /* Filtered adaptive excitation */ + Word16 y2_fx[L_SUBFR]; /* Filtered algebraic excitation */ + Word16 gain_pit_fx = 0; /* Pitch gain */ + Word16 voice_fac_fx; /* Voicing factor */ + Word32 gain_code_fx = 0; /* Gain of code */ + Word16 gain_inov_fx=0; /* inovation gain */ + Word32 gc_mem[NB_SUBFR-1]; /* gain_code from previous subframes */ + Word16 gp_mem[NB_SUBFR-1]; /* gain_pitch from previous subframes*/ + Word16 i, i_subfr_fx; /* tmp variables */ + Word16 T0_fx=0, T0_frac_fx=0; /* close loop integer pitch and fractional part */ + Word16 T0_min_fx, T0_max_fx; /* pitch variables */ + Word16 *pt_pitch_fx; /* pointer to floating pitch buffer */ + Word16 g_corr_fx[10]; /* ACELP correl, values + gain pitch */ + Word16 clip_gain_fx; /* LSF clip gain */ + const Word16 *p_Aw_fx, *p_Aq_fx; /* pointer to LP filter coeff. vector*/ + Word16 error_fx = 0; + Word16 gain_preQ_fx = 0; /* Gain of prequantizer excitation */ + Word16 code_preQ_fx[L_SUBFR]; /* Prequantizer excitation */ + Word16 unbits_PI_fx = 0; /* number of unused bits for PI */ + Word32 norm_gain_code_fx=0; + Word16 pitch_limit_flag; + Word16 gcode16; + Word32 Ltmp; + Word32 Ltmp1; + Word32 Lgcode; + Word16 tmp1_fx; + Word16 shift_wsp; + Word16 harm_flag_acelp; + Word16 lp_select, lp_flag; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + gain_pit_fx = 0; + move16(); + gain_code_fx = L_deposit_l(0); + gain_preQ_fx = 0; + move16(); + unbits_PI_fx = 0; + move16(); + error_fx = 0; + move16(); + + IF( EQ_16(L_frame_fx,L_FRAME)) + { + T0_max_fx = PIT_MAX; + move16(); + T0_min_fx = PIT_MIN; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + T0_max_fx = PIT16k_MAX; + move16(); + T0_min_fx = PIT16k_MIN; + move16(); + } + + p_Aw_fx = Aw_fx; + p_Aq_fx = Aq_fx; + pt_pitch_fx = pitch_buf_fx; + gain_preQ_fx = 0; + move16(); + set16_fx( code_preQ_fx, 0, L_SUBFR ); + + shift_wsp = add(Q_new,shift); + + /* set and write harmonicity flag */ + harm_flag_acelp = 0; + move16(); + test(); + test(); + IF( GT_32(st_fx->core_brate_fx,ACELP_24k40)&&LE_32(st_fx->core_brate_fx,ACELP_32k)&&EQ_16(coder_type_fx,GENERIC)) + { + if( GT_16(st_fx->last_harm_flag_acelp_fx,2)) + { + harm_flag_acelp = 1; + move16(); + } + + push_indice_fx( st_fx, IND_HARM_FLAG_ACELP, harm_flag_acelp, 1 ); + } + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + + FOR( i_subfr_fx=0; i_subfr_fxmem_syn, i_subfr_fx, &mem->mem_w0, p_Aq_fx, + res_fx, L_SUBFR, p_Aw_fx, st_fx->preemph_fac, xn_fx, cn_fx, h1_fx ); + + Copy_Scale_sig( h1_fx, h2_fx, L_SUBFR, -2 ); + Scale_sig( h1_fx, L_SUBFR, add(1, shift) ); /* set h1[] in Q14 with scaling for convolution */ + + /* scaling of xn[] to limit dynamic at 12 bits */ + Scale_sig( xn_fx, L_SUBFR, shift ); + + *pt_pitch_fx = pit_encode_fx( st_fx, st_fx->core_brate_fx, 0, L_frame_fx, coder_type_fx, &pitch_limit_flag, i_subfr_fx, exc_fx, + L_SUBFR, T_op_fx, &T0_min_fx, &T0_max_fx, &T0_fx, &T0_frac_fx, h1_fx, xn_fx ); + + tbe_celp_exc(L_frame_fx,i_subfr_fx,T0_fx, T0_frac_fx, &error_fx, bwe_exc_fx); + + /*-----------------------------------------------------------------* + * Find adaptive exitation + *-----------------------------------------------------------------*/ + + pred_lt4(&exc_fx[i_subfr_fx], &exc_fx[i_subfr_fx], T0_fx, T0_frac_fx, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP); + + /*-----------------------------------------------------------------* + * Gain clipping test to avoid unstable synthesis on frame erasure + *-----------------------------------------------------------------*/ + + clip_gain_fx = gp_clip_fx(st_fx->core_brate_fx,voicing_fx,i_subfr_fx,coder_type_fx,xn_fx,st_fx->clip_var_fx,sub(shift_wsp, 1)); + + if( EQ_16(coder_type_fx,INACTIVE)) + { + /* in case of AVQ inactive, limit the gain to 0.65 */ + clip_gain_fx = 2; + move16(); + } + + /*-----------------------------------------------------------------* + * LP filtering of the adaptive excitation, codebook target computation + *-----------------------------------------------------------------*/ + + lp_select = lp_filt_exc_enc_fx( MODE1, st_fx->core_brate_fx, 0, coder_type_fx, i_subfr_fx, exc_fx, h1_fx, + xn_fx, y1_fx, xn2_fx, L_SUBFR, L_frame_fx, g_corr_fx, clip_gain_fx, &gain_pit_fx, &lp_flag ); + + IF( EQ_16(lp_flag,NORMAL_OPERATION)) + { + push_indice_fx( st_fx, IND_LP_FILT_SELECT, lp_select, 1 ); + } + + /*st_fx->lowrate_pitchGain = 0.9f * st_fx->lowrate_pitchGain + 0.1f * gain_pit_fx;*/ + st_fx->lowrate_pitchGain = round_fx(L_mac(L_mult(29491, st_fx->lowrate_pitchGain), 6554, gain_pit_fx)); /*Q14*Q16(0.1) + Q15 -> Q15*/ + + /*-----------------------------------------------------------------* + * Transform domain contribution encoding - active frames + *-----------------------------------------------------------------*/ + + test(); + IF( GT_32(st_fx->core_brate_fx,ACELP_24k40)&&NE_16(coder_type_fx,INACTIVE)) + { + transf_cdbk_enc_fx( st_fx, st_fx->core_brate_fx, st_fx->extl_fx, coder_type_fx, harm_flag_acelp, i_subfr_fx, -1, cn_fx, exc_fx, + p_Aq_fx, p_Aw_fx, h1_fx, xn_fx, xn2_fx, y1_fx, y2_fx, Es_pred_fx, &gain_pit_fx, gain_code_fx, g_corr_fx, clip_gain_fx, + &(st_fx->mem_deemp_preQ_fx), &(st_fx->mem_preemp_preQ_fx), &gain_preQ_fx, code_preQ_fx, unbits_fx, Q_new, shift); + } + + /*-----------------------------------------------------------------* + * Innovation encoding + *-----------------------------------------------------------------*/ + + inov_encode_fx( st_fx, st_fx->core_brate_fx, 0, L_frame_fx, st_fx->last_L_frame_fx, + coder_type_fx, st_fx->bwidth_fx, sharpFlag_fx, i_subfr_fx, -1, p_Aq_fx, + gain_pit_fx, cn_fx, exc_fx, h2_fx, mem->tilt_code, *pt_pitch_fx, xn2_fx, code_fx, y2_fx, &unbits_PI_fx, shift ); + + /*-----------------------------------------------------------------* + * Gain encoding + *-----------------------------------------------------------------*/ + + IF ( LE_32(st_fx->core_brate_fx,ACELP_8k00)) + { + gain_enc_lbr_fx( st_fx, st_fx->core_brate_fx, coder_type_fx, i_subfr_fx, xn_fx, y1_fx, shift_wsp, y2_fx, code_fx, + &gain_pit_fx, &gain_code_fx, &gain_inov_fx, &norm_gain_code_fx, g_corr_fx, gc_mem, gp_mem, clip_gain_fx ); + } + ELSE IF ( GT_32(st_fx->core_brate_fx,ACELP_32k)) + { + gain_enc_SQ_fx( st_fx, st_fx->core_brate_fx, coder_type_fx, i_subfr_fx, -1, xn_fx, y1_fx, y2_fx, code_fx, Es_pred_fx, + &gain_pit_fx, &gain_code_fx, &gain_inov_fx, &norm_gain_code_fx, g_corr_fx, clip_gain_fx, shift_wsp ); + } + ELSE + { + gain_enc_mless_fx( st_fx, st_fx->core_brate_fx, L_frame_fx, coder_type_fx, i_subfr_fx, -1, xn_fx, y1_fx, shift_wsp, y2_fx, code_fx, Es_pred_fx, + &gain_pit_fx, &gain_code_fx, &gain_inov_fx, &norm_gain_code_fx, g_corr_fx, clip_gain_fx ); + } + + if ( EQ_16(st_fx->last_ppp_mode_fx,1)) + { + /* SC-VBR - all other st->clip_var values will be updated even in a PPP frame */ + st_fx->clip_var_fx[1] = gain_pit_fx; + move16(); + } + gp_clip_test_gain_pit_fx( st_fx->core_brate_fx, gain_pit_fx, st_fx->clip_var_fx ); + + Lgcode = L_shl(gain_code_fx, Q_new); /* scaled gain_code with Qnew -> Q16*/ + gcode16 = round_fx(Lgcode); + + mem->tilt_code = Est_tilt2(&exc_fx[i_subfr_fx], gain_pit_fx, code_fx, Lgcode, &voice_fac_fx, shift); + + /*-----------------------------------------------------------------* + * Transform domain contribution encoding - inactive frames + *-----------------------------------------------------------------*/ + + test(); + IF ( GT_32(st_fx->core_brate_fx,ACELP_24k40)&&EQ_16(coder_type_fx,INACTIVE)) + { + transf_cdbk_enc_fx( st_fx, st_fx->core_brate_fx, st_fx->extl_fx, coder_type_fx, 0, i_subfr_fx, -1, cn_fx, exc_fx, + p_Aq_fx, p_Aw_fx, h1_fx, xn_fx, xn2_fx, y1_fx, y2_fx, Es_pred_fx, &gain_pit_fx, gain_code_fx, g_corr_fx, clip_gain_fx, + &(st_fx->mem_deemp_preQ_fx), &(st_fx->mem_preemp_preQ_fx), &gain_preQ_fx, code_preQ_fx, unbits_fx, Q_new, shift); + } + + /*-----------------------------------------------------------------* + * Update memory of the weighting filter + *-----------------------------------------------------------------*/ + + /* st_fx->mem_w0 = xn[L_SUBFR-1] - (gain_pit*y1[L_SUBFR-1]) - (gain_code*y2[L_SUBFR-1]); */ + Ltmp = L_mult(gcode16, y2_fx[L_SUBFR - 1]); + Ltmp = L_shl(Ltmp, add(5, shift)); + Ltmp = L_negate(Ltmp); + Ltmp = L_mac(Ltmp, xn_fx[L_SUBFR - 1], 16384); + Ltmp = L_msu(Ltmp, y1_fx[L_SUBFR - 1], gain_pit_fx); + Ltmp = L_shl(Ltmp, sub(1, shift)); + mem->mem_w0 = round_fx(Ltmp); /*Q_new-1 */ + + IF( GT_32(st_fx->core_brate_fx,ACELP_24k40)) + { + tmp1_fx = add(16-(2+Q_AVQ_OUT_DEC+1),Q_new); + + FOR( i = 0; i < L_SUBFR; i++ ) + { + /* Contribution from AVQ layer */ + Ltmp1 = L_mult(gain_preQ_fx, code_preQ_fx[i]); /* Q2 + Q6 -> Q9*/ + Ltmp1 = L_shl(Ltmp1,tmp1_fx); /* Q16 + Q_exc */ + + /* Compute exc2 */ + Ltmp = L_shl(L_mult(gain_pit_fx,exc_fx[i+i_subfr_fx]),1); + exc2_fx[i+i_subfr_fx] = round_fx(L_add(Ltmp, Ltmp1)); + + /* code in Q9, gain_pit in Q14 */ + Ltmp = L_mult(gcode16, code_fx[i]); + Ltmp = L_shl(Ltmp, 5); + Ltmp = L_mac(Ltmp, exc_fx[i + i_subfr_fx], gain_pit_fx); + Ltmp = L_shl(Ltmp, 1); /* saturation can occur here */ + + exc_fx[i+i_subfr_fx] = round_fx(L_add(Ltmp, Ltmp1)); + } + + } + ELSE + { + /*-----------------------------------------------------------------* + * Construct adaptive part of the excitation + * Save the non-enhanced excitation for FEC_exc + *-----------------------------------------------------------------*/ + FOR (i = 0; i < L_SUBFR; i++) + { + /* code in Q9, gain_pit in Q14 */ + Ltmp = L_mult(gcode16, code_fx[i]); + Ltmp = L_shl(Ltmp, 5); + Ltmp = L_mac(Ltmp, exc_fx[i + i_subfr_fx], gain_pit_fx); + Ltmp = L_shl(Ltmp, 1); /* saturation can occur here */ + exc_fx[i + i_subfr_fx] = round_fx(Ltmp); + } + } + /*-----------------------------------------------------------------* + * Prepare TBE excitation + *-----------------------------------------------------------------*/ + + prep_tbe_exc_fx( L_frame_fx, i_subfr_fx, gain_pit_fx, gain_code_fx, code_fx, voice_fac_fx, + &voice_factors_fx[i_subfr_fx/L_SUBFR], bwe_exc_fx, gain_preQ_fx, code_preQ_fx, Q_new, + T0_fx, T0_frac_fx, coder_type_fx, st_fx->core_brate_fx ); + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[]. + * Update A(z) filters + *-----------------------------------------------------------------*/ + + Syn_filt_s( 1, p_Aq_fx, M, &exc_fx[i_subfr_fx], &syn_fx[i_subfr_fx], L_SUBFR, mem->mem_syn, 1 ); + + p_Aw_fx += (M+1); + p_Aq_fx += (M+1); + pt_pitch_fx++; + } + + /* write reserved bits */ + WHILE( unbits_PI_fx > 0 ) + { + i = s_min(unbits_PI_fx, 16); + push_indice_fx( st_fx, IND_UNUSED, 0, i ); + unbits_PI_fx -= i; + } + /* SC-VBR */ + st_fx->prev_ppp_gain_pit_fx = gain_pit_fx; + move16(); + st_fx->prev_tilt_code_fx = mem->tilt_code; + move16(); + + return; + +} diff --git a/lib_enc/enc_gen_voic_rf_fx.c b/lib_enc/enc_gen_voic_rf_fx.c new file mode 100644 index 0000000..975d6b5 --- /dev/null +++ b/lib_enc/enc_gen_voic_rf_fx.c @@ -0,0 +1,624 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "stl.h" +#include "rom_basop_util.h" +#include "basop_mpy.h" + + + +void reset_rf_indices( + Encoder_State_fx *st /* i: state structure - contains partial RF indices */ +) +{ + st->rf_frame_type = 0; /* since this function is called every frame this will happen even for a SID frame, hence treating it as GSC frame, i.e no RF encoding */ + + { + Word16 i, j; + + st->rf_mem_w0 = 0; + move16(); + set16_fx(st->rf_clip_var, 0 ,6); + st->rf_tilt_code = 0; + move16(); + set16_fx(st->rf_mem_syn2, 0, M); + st->rf_dm_fx.prev_state = 0; + move16(); + st->rf_dm_fx.prev_gain_code = 0; + move32(); + + FOR(i=0; i<6; i++) + { + st->rf_dm_fx.prev_gain_pit[i] = 0; + move16(); + } + + st->rf_gc_threshold = 0; + move32(); + set16_fx(st->rf_tilt_buf, 0, NB_SUBFR16k); + + st->rf_target_bits = 0; + move16(); + st->rf_target_bits_write = 0; + move16(); + st->rf_tcxltp_pitch_int_past = st->L_frame_fx; + move16(); + st->rf_last_tns_active = 0; + move16(); + st->rf_second_last_tns_active = 0; + move16(); + st->rf_second_last_core= 0; + move16(); + + FOR( i = 0; i < MAX_RF_FEC_OFFSET; i++) + { + st->rf_indx_frametype[i] = RF_NO_DATA; + move16(); /* rf_mode: 1, rf_frame_type: 3, and fec_offset: 2 */ + st->rf_targetbits_buff[i] = 6; + move16(); + st->rf_indx_lsf[i][0] = 0; + move16(); + st->rf_indx_lsf[i][1] = 0; + move16(); + st->rf_indx_lsf[i][2] = 0; + move16(); + st->rf_indx_EsPred[i] = 0; + move16(); + st->rf_indx_nelp_fid[i] = 0; + move16(); + st->rf_indx_nelp_iG1[i] = 0; + move16(); + st->rf_indx_nelp_iG2[i][0] = 0; + move16(); + st->rf_indx_nelp_iG2[i][1] = 0; + move16(); + + FOR( j = 0; j < NB_SUBFR16k; j++) + { + st->rf_indx_ltfMode[i][j] = 0; + move16(); + st->rf_indx_pitch[i][j] = 0; + move16(); + st->rf_indx_fcb[i][j] = 0; + move16(); + st->rf_indx_gain[i][j] = 0; + move16(); + } + + st->rf_clas[i] = UNVOICED_CLAS; + move16(); + st->rf_gain_tcx[i] = 0; + move16(); + st->rf_tcxltp_param[i] = 0; + move16(); + + st->rf_indx_tbeGainFr[i] = 0; + move16(); + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * coder_acelp_rf() + * + * Encode excitation signal (partial redundancy) + *-------------------------------------------------------------------*/ +void coder_acelp_rf( + ACELP_config *acelp_cfg_rf, /*input/output: configuration of the ACELP coding*/ + const Word16 coder_type, /* input: coding type */ + const Word16 A[], /* input: coefficients 4xAz[M+1] */ + const Word16 Aq[], /* input: coefficients 4xAz_q[M+1] */ + Word16 speech[], /* input: speech[-M..lg] */ + const Word16 voicing[], /* input: open-loop LTP gain */ + const Word16 T_op[], /* input: open-loop LTP lag */ + Word16 stab_fac, + Encoder_State_fx *st, + Word16 target_bits, /* i/o : coder memory state */ + const Word16 rf_frame_type, /* i : rf_frame_type */ + Word16 *exc_rf, /* i/o: pointer to RF excitation */ + Word16 *syn_rf, /* i/o: pointer to RF synthesis */ + Word16 Q_new, + Word16 shift +) +{ + Word16 i, j, i_subfr, j_subfr; + Word16 T0, T0_min, T0_min_frac, T0_max, T0_max_frac, T0_res; + Word16 T0_frac; + Word16 tmp2; + Word16 gain_pit, voice_fac; + Word32 gain_code, Ltmp, Ltmp2; + ACELP_CbkCorr g_corr; + const Word16 *p_A, *p_Aq; + Word16 h1[L_SUBFR]; /* weighted impulse response of LP */ + Word16 code[L_SUBFR]; + Word16 xn_exp; + Word16 Q_xn; + Word16 Q_new_p5; + Word16 cn[L_SUBFR]; + Word16 xn[L_SUBFR]; + Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */ + Word16 y2[L_SUBFR]; /* Filtered adaptive excitation */ + Word16 res_save; + Word16 exc_nelp[L_FRAME]; + Word16 exc2[L_SUBFR]; + Word16 syn2[L_DIV_MAX]; + Word16 gain_inov; + Word32 past_gcode; + Word16 L_frame; + Word16 clip_gain; + Word32 gain_code2; + Word16 code2[L_SUBFR]; + Word16 y22[L_SUBFR]; /* Filtered adaptive excitation */ + Word32 gain_code_vect[2]; + Word16 *prm_rf; + Word16 Es_pred_rf; + Word16 nSubfr; + Word16 prev_gain_pit; + Word16 rf_coder_type; + Word16 lp_select; + + /* to avoid compilation warnings */ + past_gcode = 0; + gain_inov = 0; + T0 = 0; + T0_frac = 0; + T0_res = 0; + gain_pit = 0; + gain_code = 0; + voice_fac = 0; + prev_gain_pit=0; + Es_pred_rf = 0; + set16_fx(code, 0, L_SUBFR); + + /*-----------------------------------------------------------------------* + * Configure ACELP partial copy * + *------------------------------------------------------------------------*/ + tmp2 = BITS_ALLOC_config_acelp( target_bits, rf_frame_type, acelp_cfg_rf, 0, st->nb_subfr ); + + /* Init Framing parameters */ + L_frame = st->L_frame_fx; + + /*------------------------------------------------------------------------* + * Initialize buffers * + *------------------------------------------------------------------------*/ + + /* Rescale ACELP memories, which were not scaled yet*/ + xn_exp = sub(sub(15+1, Q_new),shift); + Q_xn = add(sub(Q_new,1),shift); + Q_new_p5 = add(Q_new, 5); + + /* Reset phase dispersion */ + IF (st->last_core_fx > ACELP_CORE) + { + st->rf_dm_fx.prev_gain_code = 0; + set16_fx(st->rf_dm_fx.prev_gain_pit, 0, 6); + st->rf_dm_fx.prev_state = 0; + } + + /* calculate residual */ + p_Aq = Aq; + FOR (i_subfr=0; i_subfrnrg_mode > 0 && NE_16(rf_frame_type,RF_NELP)) + { + Es_pred_enc_fx(&Es_pred_rf, &st->rf_indx_EsPred[0], L_frame, exc_rf, voicing, + acelp_cfg_rf->nrg_bits, acelp_cfg_rf->nrg_mode>1, Q_new); + } + + /*------------------------------------------------------------------------* + * Loop for every subframe in the analysis frame * + *------------------------------------------------------------------------* + * To find the pitch and innovation parameters. The subframe size is * + * L_SUBFR and the loop is repeated L_FRAME_PLUS/L_SUBFR * + * times. * + * - compute impulse response of weighted synthesis filter (h1[]) * + * - compute the target signal for pitch search * + * - find the closed-loop pitch parameters * + * - encode the pitch delay * + * - update the impulse response h1[] by including fixed-gain pitch * + * - find target vector for codebook search * + * - correlation between target vector and impulse response * + * - codebook search * + * - encode codebook address * + * - VQ of pitch and codebook gains * + * - find synthesis speech * + * - update states of weighting filter * + *------------------------------------------------------------------------*/ + p_A = A; + p_Aq = Aq; + + res_save = exc_rf[0]; + nSubfr = 0; + j_subfr = 0; + + FOR (i_subfr=0; i_subfrrf_mem_w0), + p_Aq, + exc_rf, + L_SUBFR, + p_A, + st->preemph_fac, + xn, + cn + ,h1 + ); + + /*---------------------------------------------------------------* + * Compute impulse response, h1[], of weighted synthesis filter * + *---------------------------------------------------------------*/ + Scale_sig(h1, L_SUBFR, add(1,shift)); /* Q13+1-shift */ + + /* scaling of xn[] to limit dynamic at 12 bits */ + Scale_sig(xn, L_SUBFR, shift); + + } + + + /*-----------------------------------------------------------------* + * Gain clipping test to avoid unstable synthesis on frame erasure + * or in case of floating point encoder & fixed p. decoder + *-----------------------------------------------------------------*/ + /* full frame nelp partial copy encoding */ + IF( EQ_16(rf_frame_type,RF_NELP)) + { + IF( i_subfr == 0 ) + { + nelp_encoder_fx( st, exc_rf, exc_nelp, &Q_new,0); + } + Copy( &exc_nelp[i_subfr], exc2, L_SUBFR ); + Copy( &exc_nelp[i_subfr], exc_rf, L_SUBFR ); + + } + ELSE + { + clip_gain = Mode2_gp_clip( voicing, i_subfr, coder_type, xn, st->rf_clip_var, L_SUBFR, Q_xn ); + + /*-----------------------------------------------------------------* + * - find unity gain pitch excitation (adaptive codebook entry) * + * with fractional interpolation. * + * - find filtered pitch exc. y1[]=exc[] convolved with h1[]) * + * - compute pitch gain1 * + *-----------------------------------------------------------------*/ + if( acelp_cfg_rf->gains_mode[i_subfr/L_SUBFR] == 0 ) + { + gain_pit = prev_gain_pit; + move16(); + } + + IF ( acelp_cfg_rf->ltp_bits!=0 ) + { + prm_rf = &st->rf_indx_pitch[0][nSubfr]; + + /* Adaptive Codebook (GC and VC) */ + Mode2_pit_encode( acelp_cfg_rf->ltp_mode, + i_subfr, + &prm_rf, + &exc_rf[i_subfr], + T_op, + &T0_min, + &T0_min_frac, + &T0_max, + &T0_max_frac, + &T0, + &T0_frac, + &T0_res, + h1, + xn, + st->pit_min, + st->pit_fr1, + st->pit_fr1b, + st->pit_fr2, + st->pit_max, + st->pit_res_max); + + /* find ACB excitation */ + rf_coder_type = 100; + move16(); + if( acelp_cfg_rf->gains_mode[i_subfr/L_SUBFR] > 0 ) + { + rf_coder_type = acelp_cfg_rf->gains_mode[i_subfr/L_SUBFR]; + move16(); + } + + E_ACELP_adaptive_codebook( exc_rf, + T0, + T0_frac, + T0_res, + st->pit_res_max, + acelp_cfg_rf->ltf_mode, + i_subfr, + L_SUBFR, + L_frame, + h1, + clip_gain, + xn, + y1, + &g_corr, + &prm_rf, + &gain_pit, + xn_exp + ,st->rf_mode + ,rf_coder_type + ,&lp_select + ); + + + + if( acelp_cfg_rf->ltf_mode == NORMAL_OPERATION ) + { + st->rf_indx_ltfMode[0][nSubfr] = lp_select; + } + } + ELSE IF ( acelp_cfg_rf->ltp_bits==0 ) + { + /* No adaptive codebook (UC) */ + gain_pit=0; + g_corr.xy1=0; + g_corr.xy1_e=0; + g_corr.y1y1=0x4000; /* set to 0x4000 instead of 0 to avoid assert failue in gain_enc : assert(coeff0 >= 0x4000) */ + g_corr.y1y1_e=0; + set16_fx(y1,0,L_SUBFR); + set16_fx(exc_rf+i_subfr,0,L_SUBFR); + T0 = L_SUBFR; + T0_frac = 0; + T0_res = 1; + } + + + /*----------------------------------------------------------------------* + * Encode the algebraic innovation * + *----------------------------------------------------------------------*/ + IF( acelp_cfg_rf->fixed_cdk_index[i_subfr/L_SUBFR] >= 0 ) + { + prm_rf = &st->rf_indx_fcb[0][nSubfr]; + + E_ACELP_innovative_codebook( exc_rf, + T0, + T0_frac, + T0_res, + gain_pit, + st->rf_tilt_code, + acelp_cfg_rf->fixed_cdk_index[j_subfr], + acelp_cfg_rf->formant_enh, + acelp_cfg_rf->formant_tilt, + acelp_cfg_rf->formant_enh_num, + acelp_cfg_rf->formant_enh_den, + acelp_cfg_rf->pitch_sharpening, + acelp_cfg_rf->pre_emphasis, + acelp_cfg_rf->phase_scrambling, + i_subfr, + p_Aq, + h1, + xn, + cn, + y1, + y2, + st->acelp_autocorr, + &prm_rf, + code, + shift + ,st->L_frame_fx, + st->last_L_frame_fx, + st->total_brate_fx + ); + } + ELSE + { + set16_fx(code, 0, L_SUBFR); + set16_fx(y2, 0, L_SUBFR); + } + + IF( i_subfr < sub(L_frame,L_SUBFR) ) + { + E_ACELP_xy2_corr(xn, y1, y2, &g_corr, L_SUBFR, Q_xn); + + g_corr.y2y2_e = sub(g_corr.y2y2_e, 18); /* -18 (y2*y2: Q9*Q9) */ + g_corr.xy2_e = sub(g_corr.xy2_e, add(Q_xn,9)); /* -(Q_xn+9) (xn: Q_xn y2: Q9) */ + g_corr.y1y2_e = sub(g_corr.y1y2_e, add(Q_xn,9)); /* -(Q_xn+9) (y1: Q_xn y2: Q9) */ + g_corr.xx_e = sub(g_corr.xx_e, add(Q_xn,Q_xn)); /* -(Q_xn+Q_xn) (xn: Q_xn) */ + + + /*----------------------------------------------------------------------* + * Add Gaussian excitation * + *----------------------------------------------------------------------*/ + gain_code2 = L_deposit_l(0); + set16_fx(code2, 0, L_SUBFR); + set16_fx(y22, 0, L_SUBFR); + + + + + /*----------------------------------------------------------* + * - Compute the fixed codebook gain * + * - quantize fixed codebook gain * + *----------------------------------------------------------*/ + IF( acelp_cfg_rf->gains_mode[i_subfr/L_SUBFR] != 0 ) + { + prm_rf = &st->rf_indx_gain[0][nSubfr]; + + encode_acelp_gains( code, + acelp_cfg_rf->gains_mode[j_subfr], + Es_pred_rf, + clip_gain, + &g_corr, + &gain_pit, + &gain_code, + &prm_rf, + &past_gcode, + &gain_inov, + L_SUBFR, + code2, + &gain_code2, + st->flag_noisy_speech_snr + ); + } + + + + gp_clip_test_gain_pit_fx( st->core_brate_fx, gain_pit, st->rf_clip_var ); + + gain_code_vect[0] = gain_code; + move32(); + gain_code_vect[1] = gain_code; + move32(); + + /*----------------------------------------------------------* + * - voice factor (for pitch enhancement) * + *----------------------------------------------------------*/ + E_UTIL_voice_factor( exc_rf, + i_subfr, + code, + gain_pit, + gain_code, + &voice_fac, + &(st->rf_tilt_code), + L_SUBFR, + acelp_cfg_rf->voice_tilt, + Q_new, + shift + ); + + + /*-----------------------------------------------------------------* + * Update memory of the weighting filter + *-----------------------------------------------------------------*/ + /* st_fx->_rf_mem_w0 = xn[L_SUBFR-1] - (gain_pit*y1[L_SUBFR-1]) - (gain_code*y2[L_SUBFR-1]); */ + Ltmp = Mpy_32_16_1(gain_code, y2[L_SUBFR-1]); + Ltmp = L_shl(Ltmp, add(5,Q_xn)); + Ltmp = L_mac(Ltmp, y1[L_SUBFR-1], gain_pit); + /* Add Gaussian contribution*/ + Ltmp2 = Mpy_32_16_1(gain_code2, y22[L_SUBFR-1]); + Ltmp2 = L_shl(Ltmp2, add(5,Q_xn)); + Ltmp = L_add(Ltmp, Ltmp2); + st->rf_mem_w0 =sub(xn[L_SUBFR-1], round_fx(L_shl(Ltmp, 1))); + move16(); + BASOP_SATURATE_WARNING_OFF; + st->rf_mem_w0 =shr(st->rf_mem_w0, shift); /*Qnew-1*/ + BASOP_SATURATE_WARNING_ON; + + + + /*-------------------------------------------------------* + * - Find the total excitation. * + *-------------------------------------------------------*/ + + tmp2 = shr(L_SUBFR, 1); + FOR (j = 0; j < 2; j++) + { + FOR (i = sub(tmp2, shr(L_SUBFR, 1)); i < tmp2; i++) + { + /* code in Q9, gain_pit in Q14; exc Q_new */ + Ltmp = Mpy_32_16_1(gain_code2, code2[i]); + Ltmp = L_shl(Ltmp, Q_new_p5); + Ltmp = L_mac(Ltmp, gain_pit, exc_rf[i+i_subfr]); + BASOP_SATURATE_WARNING_OFF + exc2[i] = round_fx(L_shl(Ltmp, 1)); + BASOP_SATURATE_WARNING_ON + + Ltmp2 = Mpy_32_16_1(gain_code_vect[j], code[i]); + Ltmp2 = L_shl(Ltmp2, Q_new_p5); + Ltmp = L_add(Ltmp, Ltmp2); + BASOP_SATURATE_WARNING_OFF + Ltmp = L_shl(Ltmp, 1); /* saturation can occur here */ + BASOP_SATURATE_WARNING_ON + exc_rf[i + i_subfr] = round_fx(Ltmp); + } + tmp2 = L_SUBFR; + } + + + + /*---------------------------------------------------------* + * Enhance the excitation * + *---------------------------------------------------------*/ + E_UTIL_enhancer( voice_fac, + stab_fac, + past_gcode, + gain_inov, + &st->rf_gc_threshold, + code, + exc2, + gain_pit, + &st->rf_dm_fx.prev_gain_code, + st->rf_dm_fx.prev_gain_pit, + &st->rf_dm_fx.prev_state, + coder_type, + acelp_cfg_rf->fixed_cdk_index[j_subfr], + L_SUBFR, + L_frame, + Q_new + ); + } + } + + IF( i_subfr < sub(L_frame,L_SUBFR) || NE_16(rf_frame_type,RF_NELP) ) + { + + /*----------------------------------------------------------* + * - compute the synthesis speech * + *----------------------------------------------------------*/ + + E_UTIL_synthesis(1, p_Aq, exc2, &syn2[i_subfr], L_SUBFR, st->rf_mem_syn2, 1, M); + + E_UTIL_synthesis(1, p_Aq, &exc_rf[i_subfr], &syn_rf[i_subfr], L_SUBFR, &syn_rf[i_subfr-M], 0, M); + + /*----------------------------------------------------------* + * Update * + *----------------------------------------------------------*/ + p_A += (M+1); + p_Aq += (M+1); + nSubfr++; + + st->gain_code[j_subfr] = gain_code; + j_subfr = add(j_subfr, 1); + + /* copy current gain for next subframe use, in case there is no explicit encoding */ + prev_gain_pit = gain_pit; + + } + + + + } /* end of subframe loop */ + + + return; +} + + diff --git a/lib_enc/enc_higher_acelp_fx.c b/lib_enc/enc_higher_acelp_fx.c new file mode 100644 index 0000000..37a3c38 --- /dev/null +++ b/lib_enc/enc_higher_acelp_fx.c @@ -0,0 +1,456 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ +static void find_cn_fx( const Word16 xn[], const Word16 Ap[], const Word16 *p_Aq, Word16 cn[] ); + +/*-----------------------------------------------------------------* + * Transform domain contribution encoding + *-----------------------------------------------------------------*/ +#define Q_MINUS 4 +void transf_cdbk_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 extl, /* i : extension layer */ + const Word16 coder_type, /* i : coding type */ + const Word16 harm_flag_acelp,/* i : harmonic flag for higher rates ACELP */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + Word16 cn[], /* i/o: target vector in residual domain */ + Word16 exc[], /* i/o: pointer to excitation signal frame */ + const Word16 *p_Aq, /* i : 12k8 Lp coefficient */ + const Word16 Ap[], /* i : weighted LP filter coefficients */ + const Word16 h1[], /* i : weighted filter input response */ + Word16 xn[], /* i/o: target vector */ + Word16 xn2[], /* i/o: target vector for innovation search */ + Word16 y1[], /* i/o: zero-memory filtered adaptive excitation */ + const Word16 y2[], /* i : zero-memory filtered innovative excitation */ + const Word16 Es_pred, /* i : predicited scaled innovation energy */ + Word16 *gain_pit, /* i/o: adaptive excitation gain */ + const Word32 gain_code, /* i : innovative excitation gain */ + Word16 g_corr[], /* o : ACELP correlation values */ + const Word16 clip_gain, /* i : adaptive gain clipping flag */ + Word16 *mem_deemp, /* i/o: prequantizer deemhasis memory */ + Word16 *mem_preemp, /* i/o: prequantizer preemhasis memory */ + Word16 *gain_preQ, /* o : prequantizer excitation gain */ + Word16 code_preQ[], /* o : prequantizer excitation */ + Word16 *unbits, /* o : number of AVQ unused bits */ + const Word16 Q_new, /* i : Current frame scaling */ + const Word16 shift /* i : shifting applied to y1, xn,... */ +) +{ + Word16 i, index, nBits, Nsv, Es_pred_loc; + Word16 x_in[L_SUBFR], x_tran[L_SUBFR], gcode16, stmp; + Word16 e_corr, m_corr, e_ener, m_ener, m_den, e_den; + Word16 x_norm[L_SUBFR+L_SUBFR/WIDTH_BAND]; + Word32 L_corr, L_ener, Ltmp, Ltmp1; + Word16 nq[L_SUBFR/WIDTH_BAND]; + Word32 out32[L_SUBFR]; + Word16 Qdct; + + /*--------------------------------------------------------------* + * Set bit-allocation + *--------------------------------------------------------------*/ + + Nsv = 8; + move16(); + nBits = AVQ_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ_fx(tc_subfr))]; + move16(); + + /* increase # of AVQ allocated bits by unused bits from the previous subframe */ + nBits = add(nBits, *unbits); + + /*--------------------------------------------------------------* + * Compute/Update target + * For inactive frame, find target in residual domain + * Deemphasis + *--------------------------------------------------------------*/ + IF (EQ_16(coder_type,INACTIVE)) + { + gcode16 = round_fx(L_shl(gain_code, Q_new)); + FOR( i=0; i Q_new-4*/ + /*Copy( x_in, x_tran, L_SUBFR );*/ + Qdct = sub(Q_new,Q_MINUS); + } + ELSE + { + Qdct = 0; + move16(); + edct2_fx( L_SUBFR, -1, x_in, out32, &Qdct, ip_edct2_64_fx, w_edct2_64_fx ); + Qdct = negate(Qdct); + Copy_Scale_sig_32_16(out32, x_tran, L_SUBFR, sub(Qdct,Q_MINUS-1)); /* Output in Q_new-4 */ + Qdct = sub(Q_new,Q_MINUS); + } + + /*--------------------------------------------------------------* + * Split algebraic vector quantizer based on RE8 lattice + *--------------------------------------------------------------*/ + AVQ_cod_fx( x_tran, x_norm, nBits, Nsv, 0 ); + + /*--------------------------------------------------------------* + * Find prequantizer excitation gain + * Quantize the gain + *--------------------------------------------------------------*/ + L_corr = L_deposit_l(0); + L_ener = L_deposit_l(0); + FOR (i = 0; i < Nsv*8; i++) + { + /*fcorr += fx_tran[i]*(float)ix_norm[i];*/ + /*fener += (float)ix_norm[i]*(float)ix_norm[i];*/ + stmp = shl(x_norm[i],Q_AVQ_OUT ); + L_corr = L_mac(L_corr, x_tran[i], stmp); + L_ener = L_mac(L_ener, stmp, stmp); + } + L_ener = L_max(L_ener,1); + + /* No negative gains allowed in the quantizer*/ + L_corr = L_max(L_corr,0); + + e_corr = norm_l(L_corr); + m_corr = extract_h(L_shl(L_corr, e_corr)); + e_corr = sub(30, add(e_corr,sub(Qdct,Q_AVQ_OUT))); + e_ener = norm_l(L_ener); + m_ener = extract_h(L_shl(L_ener, e_ener)); + e_ener = sub(30, e_ener); + + IF(GT_16(m_corr,m_ener)) + { + m_corr = shr(m_corr,1); + e_corr = add(e_corr,1); + } + m_corr = div_s(m_corr, m_ener); + e_corr = sub(e_corr, e_ener); + Ltmp = L_shl(m_corr, s_min(add(e_corr,1),31)); /* Lgain in Q16 */ + IF ( EQ_16(coder_type,INACTIVE)) + { + Ltmp1 = L_max(gain_code,1); + e_den = norm_l(Ltmp1); + m_den = extract_h(L_shl(Ltmp1, e_den)); + /* ensure m_corr < m_den */ + test(); + IF( m_corr>0 && m_den >0) + { + m_corr = div_s(16384, m_den); + e_corr = sub(14+4, e_den); + Ltmp = L_shr(Mult_32_16(Ltmp, m_corr), e_corr); /*Q12*/ + stmp = round_fx(L_shl(Ltmp,16)); + } + ELSE + { + stmp = 0; + move16(); + } + IF( EQ_32(core_brate,ACELP_64k)) + { + index = usquant_fx( stmp, &stmp, G_AVQ_MIN_INACT_64k_Q12, G_AVQ_DELTA_INACT_64k_Q12>>1, (1 << G_AVQ_BITS) ); + } + ELSE IF( EQ_32(core_brate,ACELP_48k)) + { + index = usquant_fx( stmp, &stmp, G_AVQ_MIN_INACT_48k_Q12, G_AVQ_DELTA_INACT_48k_Q12>>1, (1 << G_AVQ_BITS) ); + } + ELSE + { + index = usquant_fx( stmp, &stmp, G_AVQ_MIN_INACT_Q12, G_AVQ_DELTA_INACT_Q12>>1, (1 << G_AVQ_BITS) ); + } + Ltmp = Mult_32_16(gain_code,stmp); /* Q16 * Q12 - 15 -> Q13*/ + Ltmp = L_shl(Ltmp,5); /* Q13 -> Q18*/ + *gain_preQ = round_fx(Ltmp); /* Q2*/ + } + ELSE + { + IF( Es_pred < 0 ) + { + Es_pred_loc = shr(negate(Es_pred),2); + } + ELSE + { + Es_pred_loc = Es_pred; + move16(); + } + + e_den = norm_s(Es_pred_loc); + m_den = shl(Es_pred_loc, e_den); + /* ensure m_corr < m_den */ + test(); + IF( m_corr>0 && m_den >0) + { + m_corr = div_s(16384, m_den); + e_corr = sub(14-8, e_den); + Ltmp = L_shr(Mult_32_16(Ltmp, m_corr), e_corr); + } + ELSE + { + Ltmp = L_deposit_l(0); + } + test(); + IF( LE_32(core_brate,ACELP_32k)&>_32(core_brate,ACELP_24k40)) + { + index = gain_quant_fx(&Ltmp, &stmp, LG10_G_AVQ_MIN_32kbps_Q14, LG10_G_AVQ_MAX_Q13, G_AVQ_BITS, &e_den ); + } + ELSE + { + index = gain_quant_fx(&Ltmp, &stmp, LG10_G_AVQ_MIN_Q14, LG10_G_AVQ_MAX_Q13, G_AVQ_BITS, &e_den ); + } + Ltmp = L_mult(stmp,Es_pred_loc); /* Q0*Q8 -> Q9*/ + Ltmp = L_shl(Ltmp,add(e_den,9)); /* Q18*/ + *gain_preQ = round_fx(Ltmp); /* Q2*/ + } + push_indice_fx( st_fx, IND_AVQ_GAIN, index, G_AVQ_BITS ); + + /*--------------------------------------------------------------* + * Encode and multiplex subvectors into bit-stream + *--------------------------------------------------------------*/ + + AVQ_encmux_fx( st_fx, -1, x_norm, &nBits, Nsv, nq ); + + /* save # of AVQ unused bits for next subframe */ + *unbits = nBits; + move16(); + + /* at the last subframe, write AVQ unused bits */ + test(); + test(); + IF( EQ_16(i_subfr,4*L_SUBFR)&&NE_16(extl,SWB_BWE_HIGHRATE)&&NE_16(extl,FB_BWE_HIGHRATE)) + { + WHILE( *unbits > 0 ) + { + i = s_min(*unbits, 16); + push_indice_fx( st_fx, IND_UNUSED, 0, i ); + *unbits -= i; + } + } + + /*--------------------------------------------------------------* + * DCT transform + *--------------------------------------------------------------*/ + + FOR( i=0; ilast_nq_preQ_fx, nq[0]), 7))) + { + /* *mem_preemp /= 16; */ + *mem_preemp = shr(*mem_preemp,4); + move16(); + } + st_fx->last_nq_preQ_fx = nq[7]; + move16(); + preemph_fx( code_preQ, FAC_PRE_AVQ_FX, L_SUBFR, mem_preemp ); + + /*--------------------------------------------------------------* + * For inactive segments + * - Zero-memory filtered pre-filter excitation + * - Update of targets and gain_pit + * For inactive segments + * - Update xn[L_subfr-1] for updating the memory of the weighting filter + *--------------------------------------------------------------*/ + + IF ( EQ_16(coder_type,INACTIVE)) + { + /*ftemp = fcode_preQ[0] *fh1[L_SUBFR-1];*/ + Ltmp = L_mult(code_preQ[0], h1[L_SUBFR-1]); /*1+14+shift + Q_AVQ_OUT */ + FOR( i=1; i Q_new + shift -1 */ + } + ELSE + { + conv_fx( code_preQ, h1, x_tran, L_SUBFR ); + updt_tar_HR_fx( cn, cn, code_preQ, *gain_preQ, sub(Q_new, add(-15+2,Q_AVQ_OUT_DEC)), L_SUBFR ); + + updt_tar_HR_fx( xn, xn, x_tran, *gain_preQ, sub(Q_new, add(-15+2,Q_AVQ_OUT_DEC)), L_SUBFR ); + *gain_pit = corr_xy1_fx( xn, y1, g_corr, L_SUBFR, 0 ); + + /* clip gain if necessary to avoid problems at decoder */ + test(); + if( EQ_16(clip_gain,1)&>_16(*gain_pit,15565)) + { + *gain_pit = 15565; + move16(); + } + updt_tar_fx( xn, xn2, y1, *gain_pit, L_SUBFR ); + } + + st_fx->use_acelp_preq = 1; + move16(); + + return; + +} +/*-------------------------------------------------------------------* + * Find target in residual domain - cn[] + *-------------------------------------------------------------------*/ + +static void find_cn_fx( + const Word16 xn[], /* i : target signal */ + const Word16 Ap[], /* i : weighted LP filter coefficients */ + const Word16 *p_Aq, /* i : 12k8 LP coefficients */ + Word16 cn[] /* o : target signal in residual domain */ +) +{ + Word16 tmp, tmp_fl[L_SUBFR+M]; + + set16_fx( tmp_fl, 0, M ); + Copy( xn, tmp_fl+M, L_SUBFR ); + tmp = 0; + move16(); + preemph_fx( tmp_fl+M, PREEMPH_FAC_16k, L_SUBFR, &tmp ); + syn_filt_s_lc_fx(0, Ap, tmp_fl+M, tmp_fl+M, L_SUBFR); + Residu3_lc_fx( p_Aq, M, tmp_fl+M, cn, L_SUBFR, 1 ); + + return; +} + + +/*-----------------------------------------------------------------* + * Transform domain contribution encoding + *-----------------------------------------------------------------*/ +Word16 gain_quant_fx( /* o: quantization index */ + Word32 *gain, /* i: quantized gain (Q16) */ + Word16 *gain16, /* o: quantized gain (expg) */ + const Word16 c_min, /* i: log10 of lower limit in Q14 */ + const Word16 c_max, /* i: log10 of upper limit in Q13 */ + const Word16 bits, /* i: number of bits to quantize */ + Word16 *expg /* o: output exponent of gain16 */ +) +{ + Word16 index, levels; + Word16 c_gain; + Word16 e_tmp, f_tmp, exp; + Word16 tmp, tmp1, tmp2, frac; + Word32 L_tmp; + + levels = shl(1, bits); + /* Prevent gain to be smaller than 0.0003. */ + /* This is to avoid an overflow when the gain is very small */ + /* the log10 give a high negative value in Q13 that overflow */ + /* on this code (the resulting value of 'index' is not affected. */ + /* tmp2 = msu_r(L_deposit_h(c_gain),c_min,16384) */ + L_tmp = L_max(*gain, 20); + + /*c_min = (float)log10(min);*/ + /*c_mult = (float) ((levels-1)/(log10(max)-c_min));*/ + + /*tmp = c_mult * ((float)log10(*gain) - c_min); + = ((levels-1)/(log10(max)-log10(min)))*((float)log10(*gain) - log10(min));*/ + + e_tmp = norm_l(L_tmp); + f_tmp = Log2_norm_lc(L_shl(L_tmp, e_tmp)); + e_tmp = sub(30-16,e_tmp);/*Q(min)=16*/ + L_tmp = Mpy_32_16(e_tmp, f_tmp, 9864); /* Q16 */ /*log10(2) in Q15*/ + c_gain = round_fx(L_shl(L_tmp, 13)); /* Q13 */ + + /*tmp1 = sub(c_max,c_min); Q14*/ + /*tmp2 = sub(c_gain,c_min); Q14*/ + + tmp1 = msu_r(L_deposit_h(c_max/*in Q13 already*/),c_min, 16384); /*Q13*/ + tmp2 = msu_r(L_deposit_h(c_gain/*in Q13 already*/),c_min,16384); /*Q13*/ + IF(tmp1 != 0) + { + exp = norm_s(tmp1); + frac = div_s(shl(1,sub(14,exp)),tmp1); /*Q(15-exp)*/ + L_tmp = L_mult(tmp2,frac); /*Q(30-exp)*/ + L_tmp = Mult_32_16(L_tmp,sub(levels,1)); /*Q(15-exp)*/ + index = extract_l(L_shr(L_add(L_tmp,shr(1<<14,exp)),sub(15,exp))); + } + ELSE + { + L_tmp = L_mult(tmp2,sub(levels,1)); /*Q15*/ + index = extract_l(L_shr(L_add(L_tmp,1<<14),15)); + } + + index = s_max(index ,0); + index = s_min(index ,sub(levels,1)); + + /**gain = (float)pow( 10.0, (((float)index)/c_mult) + c_min ); + y = index/c_mult + c_min; + = (index/(levels-1))*(log10(max) - log10(min)) + log10(min); + = z*log10(max) + (1-z)*log10(min) + z = (index/(levels-1))*/ + tmp = div_s(index,sub(levels,1)); /*Q15*/ + L_tmp = L_mult(tmp,c_max);/*Q29*/ + L_tmp = L_mac0(L_tmp,sub(32767,tmp),c_min); /*Q29*/ + + L_tmp = Mult_32_16(L_tmp,27213); /*Q27, 3.321928 in Q13*/ + L_tmp = L_shr(L_tmp,11); /*Q27->Q16*/ + + frac = L_Extract_lc(L_tmp, expg); /* Extract exponent of gcode0 */ + + *gain16 = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + *expg = sub(*expg, 14); + move16(); + + return(index); +} diff --git a/lib_enc/enc_nelp_fx.c b/lib_enc/enc_nelp_fx.c new file mode 100644 index 0000000..6cb5dc4 --- /dev/null +++ b/lib_enc/enc_nelp_fx.c @@ -0,0 +1,172 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*==============================================================================*/ +/* FUNCTION : encod_nelp_fx() */ +/*------------------------------------------------------------------------------*/ +/* PURPOSE : Encode Unvoiced frames in SC-VBR */ +/*------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Encoder_State_fx) st_fx: state structure */ +/* _ (Word16[]) speech_fx : input speech Q_new-1 */ +/* _ (Word16[]) Aq_fx : 12k8 Lp coefficient Q12 */ +/* _ (Word16[]) A_fx : unquantized A(z) filter */ +/* with bandwidth expansion Q12 */ +/* _ (Word16) coder_type_fx : coding type */ +/* _ (Word16[]) res_fx : residual signal Q_new */ +/* _ (Word16*) Q_new : res qformat */ +/* _ (Word16) shift */ +/*------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) synth_fx : core synthesis */ +/* _ (Word16[]) tmp_noise_fx: long-term noise energy Q0 */ +/* _ (Word16[]) exc_fx : current non-enhanced excitation Q_new */ +/* _ (Word16[]) exc2_fx : current enhanced excitation Q_new */ +/* _ (Word16[]) pitch_buf_fx: floating pitch values for each subframe Q6 */ +/* _ (Word16*) voice_factors : voicing factors */ +/* _ (Word16*) bwe_exc : excitation for SWB TBE */ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*==============================================================================*/ +void encod_nelp_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 *speech_fx, /* i : input speech */ + const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */ + Word16 *res_fx, /* o : residual signal */ + Word16 *synth_fx, /* o : core synthesis */ + Word16 *tmp_noise_fx, /* o : long-term noise energy */ + Word16 *exc_fx, /* i/o: current non-enhanced excitation */ + Word16 *exc2_fx, /* i/o: current enhanced excitation */ + Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe */ + Word16* voice_factors_fx, /* o : voicing factors */ + Word16* bwe_exc_fx, /* o : excitation for SWB TBE */ + Word16 Q_new, + Word16 shift + +) +{ + Word16 xn_fx[L_SUBFR]; /* Target vector for pitch search */ + Word16 h1_fx[L_SUBFR]; /* Impulse response vector */ + Word16 exc_nelp_fx[L_FRAME]; + + Word16 i_subfr, j; + + const Word16 *p_Aw_fx, *p_Aq_fx; /* pointer to LP filter coeff. vector */ + Word16 saved_Q_new = Q_new; + + Word16 reduce_gains = 0; + + IF ( EQ_16(st_fx->bwidth_fx, NB)&&GE_32(st_fx->input_Fs_fx,16000)) + { + IF (st_fx->last_nelp_mode_fx == 0) + { + set16_fx( st_fx->nelp_lp_fit_mem, 0, NELP_LP_ORDER*2 ); + } + Scale_sig(st_fx->nelp_lp_fit_mem, NELP_LP_ORDER*2, sub(Q_new, st_fx->prev_Q_new)); + + pz_filter_sp_fx( num_nelp_lp_fx, den_nelp_lp_fx, res_fx, res_fx, st_fx->nelp_lp_fit_mem, NELP_LP_ORDER, NELP_LP_ORDER, L_FRAME, 3); /*16-Q of filter coeff*/ + + } + + p_Aw_fx = Aw_fx; + p_Aq_fx = Aq_fx; + + + FOR (i_subfr=0; i_subfrmem_syn, i_subfr, &mem->mem_w0, p_Aq_fx, + res_fx, L_SUBFR, p_Aw_fx, TILT_FAC_FX, xn_fx, NULL + ,h1_fx + ); + /* scale xn[] and h1[] to avoid overflow in dot_product12() */ + Scale_sig(xn_fx, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */ + + IF (i_subfr == 0) + { + test(); + IF ( EQ_16(st_fx->Local_VAD, 1 )&&EQ_16(st_fx->bwidth_fx,NB)) + { + reduce_gains = 1; + } + + nelp_encoder_fx( st_fx, res_fx, exc_nelp_fx, &Q_new + ,reduce_gains + ); + + Scale_sig(exc_nelp_fx, L_FRAME, (saved_Q_new - Q_new)); + } + + + *tmp_noise_fx = 0; + move16(); + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[]. + * Update A(z) filters + *-----------------------------------------------------------------*/ + Syn_filt_s(1, p_Aq_fx, M, &exc_nelp_fx[i_subfr], &synth_fx[i_subfr], L_SUBFR, mem->mem_syn, 1); + + p_Aw_fx += (M+1); + move16(); + p_Aq_fx += (M+1); + move16(); + *pitch_buf_fx = L_SUBFR_Q6; + move16(); + + pitch_buf_fx++; + move16(); + } + + Copy(exc_nelp_fx, exc_fx, L_FRAME); + + /*-----------------------------------------------------------------* + * Updates: last value of new target is stored in mem_w0 + *-----------------------------------------------------------------*/ + + mem->mem_w0 = sub(shr(xn_fx[L_SUBFR-1],shift), shr(exc_fx[L_FRAME-1],1)); + move16();/*Q_new-1 */ + mem->tilt_code = 0; + move16();/* purely unvoiced */ + st_fx->prev_tilt_code_fx = mem->tilt_code; + move16(); + + Copy(exc_fx, exc2_fx, L_FRAME); + + st_fx->prev_ppp_gain_pit_fx = 0; + move16(); + + st_fx->dm_fx.prev_state = 0; + move16(); + st_fx->dm_fx.prev_gain_pit[0] = st_fx->prev_ppp_gain_pit_fx; + move16(); + + FOR(j=1; j<5; j++) + { + st_fx->dm_fx.prev_gain_pit[j] = st_fx->dm_fx.prev_gain_pit[j-1]; + move16(); + } + + interp_code_5over2_fx( exc2_fx, bwe_exc_fx, L_FRAME ); + set16_fx( voice_factors_fx, 0, NB_SUBFR16k ); + + return; +} diff --git a/lib_enc/enc_pit_exc_fx.c b/lib_enc/enc_pit_exc_fx.c new file mode 100644 index 0000000..4858117 --- /dev/null +++ b/lib_enc/enc_pit_exc_fx.c @@ -0,0 +1,361 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ + + +#include "stl.h" + +/*======================================================================*/ +/* FUNCTION : enc_pit_exc_fx() */ +/*----------------------------------------------------------------------*/ +/* PURPOSE : Encode pitch only contribution */ +/* */ +/*----------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Struct) st_fx : encoder static memory */ +/* _ (Word16[]) speech_fx : input speech Qnew-1 */ +/* _ (Word16[]) Aq_fx : LP filter coefficient Q12 */ +/* _ (Word16[]) A_fx : unquantized A(z) filter */ +/* with bandwidth expansion Q12 */ +/* _ (Word16) coder_type_fx : coding type */ +/* _ (Word16) Es_pred_fx : predicted scaled innov. energy Q8 */ +/* _ (Word16[]) T_op_fx : open loop pitch Q0 */ +/* _ (Word16[]) voicing_fx : floating pitch values for each subframe Q15*/ +/* _ (Word16[]) res_fx : residual signal Q_new */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Qnew) */ +/* _ (Word16[]) exc2_fx : adapt. excitation/total exc (Qnew) */ +/* _ (Word16[]) pitch_buf_fx : floating pitch values for each subframe Q6*/ +/* _ (Word16[]) *wH1, : Weighted impulses response mask */ +/* _ (Word16) shift : shift */ +/* _ (Word16) Q_new : */ +/*-----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Qnew) */ +/* _ (Word16[]) exc2_fx : adapt. excitation/total exc (Qnew) */ +/* _ (Word16[]) syn_fx :core synthesis */ +/* _ (Word16[]) voice_factors_fx: voicing factors Q15 */ +/* _ (Word16[]) bwe_exc_fx : excitation for SWB TBE Q0 */ +/*-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*=======================================================================*/ +void enc_pit_exc_fx( + Encoder_State_fx *st_fx, /* i/o: State structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 *speech, /* i : Input speech */ + const Word16 Aw[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq[], /* i : 12k8 Lp coefficient */ + const Word16 Es_pred, /* i : predicted scaled innov. energy */ + const Word16 *T_op, /* i : open loop pitch */ + const Word16 *voicing, /* i : voicing */ + const Word16 *res, /* i : residual signal */ + Word16 *synth, /* i/o: core synthesis */ + Word16 *exc, /* i/o: current non-enhanced excitation */ + Word16 *T0, /* i/o: close loop integer pitch */ + Word16 *T0_frac, /* i/o: close-loop pitch period - fractional part */ + Word16 *pitch_buf, /* i/o: Fractionnal per subframe pitch */ + const Word16 nb_subfr, /* i : Number of subframe considered */ + Word16 *gpit, /* o : pitch mean gpit */ + Word16 *saved_bit_pos, /* o : saved position in the bitstream before pitch contribution */ + Word16 Q_new, + Word16 shift +) +{ + Word16 xn[PIT_EXC_L_SUBFR]; /* Target vector for pitch search */ + Word16 xn2[PIT_EXC_L_SUBFR]; /* Target vector for codebook search */ + Word16 h1[PIT_EXC_L_SUBFR+(M+1)]; /* Impulse response vector */ + Word16 y1[PIT_EXC_L_SUBFR]; /* Filtered adaptive excitation */ + Word16 code[L_SUBFR]; /* Fixed codebook excitation */ + Word16 y2[L_SUBFR]; /* Filtered algebraic excitation */ + Word16 voice_fac; /* Voicing factor */ + Word32 gain_code; /* Gain of code */ + Word16 gain_inov; /* inovation gain */ + Word16 gain_pit; /* Pitch gain */ + Word16 pit_idx, i_subfr; /* tmp variables */ + Word16 T0_min, T0_max; /* pitch variables */ + Word16 g_corr[10]; /* ACELP correlation values + gain pitch */ + Word16 clip_gain, i; /* LSF clip gain and LP flag */ + const Word16 *p_Aw, *p_Aq; /* pointer to LP filter coefficient vector */ + Word16 cn1[L_SUBFR], *cn; /* (Used only when L_subfr == L_SUBFR) Target vector in residual domain */ + Word16 *pt_pitch; /* pointer to floating pitch */ + Word16 L_subfr; + Word16 cum_gpit, gpit_tmp; + Word16 Local_BR, Pitch_BR, Pitch_CT; + Word16 unbits_PI = 0; /* saved bits for PI */ + Word32 norm_gain_code; + Word16 pitch_limit_flag; + Word16 h2[PIT_EXC_L_SUBFR+(M+1)]; /* Impulse response vector */ + Word32 Ltmp; + Word32 Lgcode; + Word16 gcode16; + Word16 shift_wsp; + Word16 lp_select, lp_flag; + /*------------------------------------------------------------------* + * Initialization + *------------------------------------------------------------------*/ + + pitch_limit_flag = 1; + move16(); /* always extended pitch Q range */ + + IF( st_fx->GSC_noisy_speech_fx ) + { + Local_BR = ACELP_7k20; + move16(); + Pitch_CT = GENERIC; + move16(); + Pitch_BR = ACELP_7k20; + move16(); + } + ELSE + { + + Local_BR = ACELP_7k20; + move16(); + Pitch_CT = AUDIO; + move16(); + Pitch_BR = extract_l(st_fx->core_brate_fx); + } + gain_code = 0; + move16(); + T0_max = PIT_MAX; + move16(); + T0_min = PIT_MIN; + move16(); + + cum_gpit = 0; + move16(); + + L_subfr = mult_r(L_FRAME,div_s(1,nb_subfr)); + + *saved_bit_pos = st_fx->next_bit_pos_fx; + move16(); + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + cn = NULL; + if(EQ_16(L_subfr, L_SUBFR)) + { + cn = cn1; + move16(); + } + p_Aw = Aw; + + p_Aq = Aq; + pt_pitch = pitch_buf; /* pointer to the pitch buffer */ + shift_wsp = add(Q_new,shift); + FOR ( i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_subfr ) + { + + /*----------------------------------------------------------------* + * Bandwidth expansion of A(z) filter coefficients + * Find the the excitation search target "xn" and innovation + * target in residual domain "cn" + * Compute impulse response, h1[], of weighted synthesis filter + *----------------------------------------------------------------*/ + Copy( &res[i_subfr], &exc[i_subfr], L_subfr ); + /* condition on target (compared to float) has been put outside the loop */ + find_targets_fx( speech, mem->mem_syn, i_subfr, &mem->mem_w0, p_Aq, + res, L_subfr, p_Aw, st_fx->preemph_fac, xn, cn,h1); + Copy_Scale_sig(h1, h2, L_subfr, -2); + Scale_sig(h1, L_subfr, add(1, shift)); /* set h1[] in Q14 with scaling for convolution */ + + /* scaling of xn[] to limit dynamic at 12 bits */ + Scale_sig(xn, L_subfr, shift); + + /*----------------------------------------------------------------* + * Close-loop pitch search and quantization + * Adaptive exc. construction + *----------------------------------------------------------------*/ + *pt_pitch = pit_encode_fx( st_fx, Pitch_BR, 0, L_FRAME, Pitch_CT, &pitch_limit_flag, i_subfr, exc, + L_subfr, T_op, &T0_min, &T0_max, T0, T0_frac, h1, xn ); + /*-----------------------------------------------------------------* + * Find adaptive exitation + *-----------------------------------------------------------------*/ + + pred_lt4(&exc[i_subfr], &exc[i_subfr], *T0, *T0_frac, L_subfr+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP); + /*-----------------------------------------------------------------* + * Gain clipping test to avoid unstable synthesis on frame erasure + * or in case of floating point encoder & fixed p. decoder + *-----------------------------------------------------------------*/ + + clip_gain = gp_clip_fx(st_fx->core_brate_fx, voicing, i_subfr, AUDIO, xn, st_fx->clip_var_fx,sub(shift_wsp, 1)); + + /*-----------------------------------------------------------------* + * Codebook target computation + * (No LP filtering of the adaptive excitation) + *-----------------------------------------------------------------*/ + + lp_select = lp_filt_exc_enc_fx( MODE1, st_fx->core_brate_fx, 0, AUDIO, i_subfr, exc, h1, + xn, y1, xn2, L_subfr, L_FRAME, g_corr, clip_gain, &gain_pit, &lp_flag ); + + IF( EQ_16(lp_flag,NORMAL_OPERATION)) + { + push_indice_fx( st_fx, IND_LP_FILT_SELECT, lp_select, 1 ); + } + + /*st_fx->lowrate_pitchGain = 0.9f * st_fx->lowrate_pitchGain + 0.1f * gain_pit;*/ + st_fx->lowrate_pitchGain = round_fx(L_mac(L_mult(29491, st_fx->lowrate_pitchGain), 6554, gain_pit)); /*Q14*Q16(0.1) + Q15 -> Q15*/ + + + gpit_tmp = gain_pit; + move16(); /*Q14*/ + test(); + IF( st_fx->GSC_noisy_speech_fx == 0 || NE_16(L_subfr,L_SUBFR )) + { + pit_idx = vquant_fx( &gain_pit, mean_gp_fx, &gain_pit, dic_gp_fx, 1, 16 ); + push_indice_fx( st_fx, IND_PIT_IDX, pit_idx, 4 ); + } + ELSE + { + /*-----------------------------------------------------------------* + * Innovation & gain encoding + *-----------------------------------------------------------------*/ + /* h2 in Q12 for codebook search */ + /* h1 has been scaled with 1 + shift so we need to remove 2 and (1+shift) = -3 - shift*/ + Copy_Scale_sig( h1, h2, L_subfr, sub(-2-1,shift) ); + + inov_encode_fx( st_fx, Local_BR, 0, L_FRAME, st_fx->last_L_frame_fx, LOCAL_CT, WB, 1, i_subfr, -1, p_Aq, + gain_pit, cn, exc, h2, mem->tilt_code, *pt_pitch, xn2, code, y2, &unbits_PI,shift + ); + /*-----------------------------------------------------------------* + * Gain encoding + *-----------------------------------------------------------------*/ + gain_enc_mless_fx( st_fx, Local_BR, L_FRAME, LOCAL_CT, i_subfr, -1, xn, y1, shift_wsp, y2, code, Es_pred, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain ); + } + + gp_clip_test_gain_pit_fx( st_fx->core_brate_fx, gain_pit, st_fx->clip_var_fx ); + + Lgcode = L_shl(gain_code, Q_new); /* scaled gain_code with Qnew -> Q16*/ + gcode16 = round_fx(Lgcode); + IF( st_fx->GSC_noisy_speech_fx) + { + mem->tilt_code = Est_tilt2(&exc[i_subfr], gain_pit, code, Lgcode, &voice_fac, shift); + move16(); + } + ELSE + { + mem->tilt_code = 0; + move16(); + } + /*-----------------------------------------------------------------* + * Update memory of the weighting filter + *-----------------------------------------------------------------*/ + IF( st_fx->GSC_noisy_speech_fx) + { + Ltmp = L_mult(gcode16, y2[L_subfr - 1]); + Ltmp = L_shl(Ltmp, add(5, shift)); + Ltmp = L_negate(Ltmp); + Ltmp = L_mac(Ltmp, xn[L_subfr - 1], 16384); + Ltmp = L_msu(Ltmp, y1[L_subfr - 1], gain_pit); + Ltmp = L_shl(Ltmp, sub(1, shift)); + mem->mem_w0 = round_fx(Ltmp); /*Q_new-1 */ + } + ELSE + { + Ltmp = L_mult(xn[L_subfr - 1], 16384); + Ltmp = L_msu(Ltmp, y1[L_subfr - 1], gain_pit); + Ltmp = L_shl(Ltmp, sub(1, shift)); + mem->mem_w0 = round_fx(Ltmp); /*Q_new-1 */ + } + + /*-----------------------------------------------------------------* + * Construct adaptive part of the excitation + * Save the non-enhanced excitation for FEC_exc + *-----------------------------------------------------------------*/ + IF( st_fx->GSC_noisy_speech_fx) + { + FOR ( i = 0; i < L_subfr; i++ ) + { + /* code in Q9, gain_pit in Q14 */ + Ltmp = L_mult(gcode16, code[i]); + Ltmp = L_shl(Ltmp, 5); + Ltmp = L_mac(Ltmp, exc[i + i_subfr], gain_pit); + Ltmp = L_shl(Ltmp, 1); /* saturation can occur here */ + exc[i + i_subfr] = round_fx(Ltmp); + } + } + ELSE + { + FOR ( i = 0; i < L_subfr; i++ ) + { + + Ltmp = L_mult(exc[i + i_subfr], gain_pit); + Ltmp = L_shl(Ltmp, 1); /* saturation can occur here */ + exc[i + i_subfr] = round_fx(Ltmp); + } + } + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[]. + * Update A(z) filters + *-----------------------------------------------------------------*/ + + Syn_filt_s( 1, p_Aq, M, &exc[i_subfr], &synth[i_subfr], L_subfr, st_fx->mem_syn_tmp_fx, 1 ); + IF( EQ_16(L_subfr,2*L_SUBFR)) + { + IF( i_subfr == 0 ) + { + cum_gpit = mult_r(gpit_tmp,16384); + } + ELSE + { + cum_gpit = add(cum_gpit,mult_r(gpit_tmp,16384)); + } + p_Aw += 2*(M+1); + move16(); + p_Aq += 2*(M+1); + move16(); + pt_pitch++; + *pt_pitch = *(pt_pitch-1); + move16(); + pt_pitch++; + } + ELSE IF(EQ_16(L_subfr,4*L_SUBFR)) + { + cum_gpit = gpit_tmp; + move16(); + + pt_pitch++; + *pt_pitch = *(pt_pitch-1); + move16(); + pt_pitch++; + *pt_pitch = *(pt_pitch-1); + move16(); + pt_pitch++; + *pt_pitch = *(pt_pitch-1); + pt_pitch++; + p_Aw += 4*(M+1); + p_Aq += 4*(M+1); + } + ELSE + { + IF( i_subfr == 0 ) + { + + cum_gpit = mult_r(gpit_tmp,8192); + } + ELSE + { + cum_gpit = add(cum_gpit,mult_r(gpit_tmp,8192)); + } + + pt_pitch++; + p_Aw += (M+1); + p_Aq += (M+1); + } + } + + cum_gpit = shl(cum_gpit,1); /*Q15*/ + *gpit = round_fx(L_mac(L_mult(3277 , *gpit), 29491, cum_gpit)); /*Q15*/ + + +} diff --git a/lib_enc/enc_ppp_fx.c b/lib_enc/enc_ppp_fx.c new file mode 100644 index 0000000..d33416a --- /dev/null +++ b/lib_enc/enc_ppp_fx.c @@ -0,0 +1,227 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +/*Temporary location to be move in prot* when merge is done */ +void E_LPC_f_lsp_a_conversion(const Word16 *lsp, Word16 *a, const Word16 m); + +/*=======================================================================================*/ +/* FUNCTION : encod_ppp_fx() */ +/*---------------------------------------------------------------------------------------*/ +/* PURPOSE : */ +/*---------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) speech_fx[], i : input speech Q_new */ +/* _ (Word16) Aq_fx[], i : 12k8 Lp coefficient Q12 */ +/* _ (Word16) A_fx[], i : unquantized A(z) filter with bandwidth expansion Q12*/ +/* _ (Word16) coder_type_fx, i : coding type */ +/* _ (Word16) T_op_fx[], i : open loop pitch */ +/* _ (Word16) voicing_fx[], i : voicing Q15 */ +/* _ (Word16) *res_fx, i : residual signal Q_new */ +/* _ (Word16) Q_new i : Q factor for res */ +/* _ (Word16) vadsnr_fx i : SNR for current frame Q7 */ +/*---------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16) *exc2_fx, o : current enhanced excitation Q0 */ +/* _ (Word16) *pitch_buf_fx, o : floating pitch values for each subframe Q6 */ +/* _ (Word16) *synth_fx, o : core synthesis Q-1 */ +/* _ Encoder_State_fx *st_fx: */ +/* _ lastLgainE_fx - Q11 */ +/* _ lastHgainE_fx - Q11 */ +/* _ lasterbE_fx - Q13 */ +/*---------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ Encoder_State_fx *st_fx: */ +/* _ st_fx->dtfs_enc_xxxx */ +/* _ a nd b in st_fx->dtfs_enc_Q */ +/* rest all in Q0 */ +/* - bump_up_fx - Q0 */ +/* _ (Word16) *exc_fx, o : current enhanced excitation Q0 */ +/*---------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None. */ +/*---------------------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*=======================================================================================*/ +void encod_ppp_fx( + Encoder_State_fx* st_fx, /* i/o: state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 speech_fx[], /* i : input speech Q_new*/ + const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */ + Word16 *coder_type_fx, /* i : coding type */ + Word16 sharpFlag_fx, /* i : formant sharpening flag */ + const Word16 T_op_fx[], /* i : open loop pitch */ + const Word16 voicing_fx[], /* i : voicing Q15*/ + Word16 *res_fx, /* i : residual signal Q_new*/ + Word16 *synth_fx, /* o : core synthesis Q-1*/ + Word16 *exc_fx, /* i/o: current non-enhanced excitation Q_new*/ + Word16 *exc2_fx, /* o: current enhanced excitation Q0*/ + Word16 *pitch_buf_fx, /* o: floating pitch values for each subframe Q6*/ + Word16 *voice_factors, /* o : voicing factors */ + Word16 *bwe_exc, /* o : excitation for SWB TBE */ + Word16 Q_new, + Word16 shift +) +{ + Word16 xn_fx[L_SUBFR]; /* Target vector for pitch search */ + Word16 h1_fx[L_SUBFR+(M+1)]; /* Impulse response vector */ + Word16 i_subfr; /* tmp variables */ + const Word16 *p_Aw_fx, *p_Aq_fx; /* pointer to LP filter coeff. vector*/ + + Word16 k; + Word16 p_Aq_old_fx[M+1], excQ_ppp_fx[L_FRAME] ,p_Aq_curr_fx[M], pitch_fx[NB_SUBFR]; + Word16 LPC_de_old_fx[M+1], LPC_de_curr_fx[M+1]; + Word16 shift_wsp = add(Q_new,shift); + Word16 rate_ctrl_fx; + Word16 saved_Q_new = Q_new; + + rate_ctrl_fx = st_fx->rate_control_fx; + move16(); + + /*------------------------------------------------------------------* + * ACELP subframe loop + *------------------------------------------------------------------*/ + p_Aw_fx = Aw_fx; + p_Aq_fx = Aq_fx; + FOR (i_subfr=0; i_subfrmem_syn, i_subfr, &mem->mem_w0, p_Aq_fx, + res_fx, L_SUBFR, p_Aw_fx, TILT_FAC_FX, xn_fx, NULL + ,h1_fx + ); + + /* scale xn[] and h1[] to avoid overflow in dot_product12() */ + Scale_sig(xn_fx, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */ + + /* call voiced encoder at this point */ + IF (i_subfr == 0) /* generate the L_FRAME exc */ + { + FOR(k=0; klsp_old_fx, p_Aq_old_fx, M ); + deemph_lpc_fx( p_Aq_curr_fx, p_Aq_old_fx, LPC_de_curr_fx, LPC_de_old_fx ,1); + /* both outputs LPC_de_curr_fx and LPC_de_old_fx are in Q12 */ + + + /* last frame-end lpc and curr frame-end lpc */ + ppp_voiced_encoder_fx( st_fx, res_fx, excQ_ppp_fx, T_op_fx[1], LPC_de_old_fx, + LPC_de_curr_fx, exc_fx, pitch_fx, st_fx->vadsnr_fx, Q_new ); + + Scale_sig(exc_fx, L_FRAME, (saved_Q_new - Q_new)); + if (EQ_16(st_fx->bump_up_fx,1)) + { + i_subfr = L_FRAME; + move16(); + } + } + + IF( NE_16(st_fx->bump_up_fx,1)) + { + /*-----------------------------------------------------------------* + * Gain clipping test to avoid unstable synthesis on frame erasure + * or in case of floating point encoder & fixed p. decoder + *-----------------------------------------------------------------*/ + gp_clip_fx(st_fx->core_brate_fx, voicing_fx, i_subfr, *coder_type_fx, xn_fx, st_fx->clip_var_fx, sub(shift_wsp,1)); + + + /* run the above to maintain gain clipping memories */ + gp_clip_test_gain_pit_fx( st_fx->core_brate_fx, st_fx->prev_ppp_gain_pit_fx, st_fx->clip_var_fx ); + + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[]. + * Update A(z) filters + *-----------------------------------------------------------------*/ + + Syn_filt_s( 1, p_Aq_fx, M, &excQ_ppp_fx[i_subfr], &synth_fx[i_subfr], L_SUBFR, mem->mem_syn, 1 ); + + + p_Aw_fx += (M+1); + p_Aq_fx += (M+1); + } + + } /* end of subframe loop */ + + IF( st_fx->bump_up_fx ) + { + /* PPP failed, bump up */ + st_fx->ppp_mode_fx = 0; + move16(); + st_fx->core_brate_fx = ACELP_7k20; + move16(); + st_fx->pppcountE_fx = 0; + move16(); + + IF ( st_fx->set_ppp_generic_fx ) + { + *coder_type_fx = GENERIC; + move16(); + } + ELSE + { + *coder_type_fx = VOICED; + move16(); + } + + /* We write signalling indices again only in case of bump_up */ + /* delete previous indices */ + reset_indices_enc_fx( st_fx ); + + /* signalling matrix (writing of signalling bits) */ + signalling_enc_fx( st_fx, *coder_type_fx, sharpFlag_fx ); + } + ELSE + { + Copy(excQ_ppp_fx, exc_fx, L_FRAME); + + /*-----------------------------------------------------------------* + * Updates: last value of new target is stored in mem_w0 + *-----------------------------------------------------------------*/ + + mem->mem_w0 = sub(shr(xn_fx[L_SUBFR-1],shift), shr(exc_fx[L_FRAME-1],1)); /*Q_new-1 */ + + Copy(exc_fx, exc2_fx, L_FRAME); + + st_fx->dm_fx.prev_state = 2; + move16();/*Q0 dispMem index 0 */ + st_fx->dm_fx.prev_gain_pit[0] = st_fx->prev_ppp_gain_pit_fx; + move16();/*Q14 dispMem index 2 */ + + FOR( k=1; k<5; k++ ) + { + st_fx->dm_fx.prev_gain_pit[k] = st_fx->dm_fx.prev_gain_pit[k-1]; + move16(); + } + + mem->tilt_code = st_fx->prev_tilt_code_fx; + move16(); + Copy(pitch_fx, pitch_buf_fx, NB_SUBFR); + pitch_buf_fx[ NB_SUBFR16k -1 ] = pitch_fx[ NB_SUBFR - 1 ]; + + interp_code_5over2_fx( exc2_fx, bwe_exc, L_FRAME ); + set16_fx( voice_factors, 0, NB_SUBFR16k ); + } + + st_fx->rate_control_fx = rate_ctrl_fx; + move16(); + + return; +} diff --git a/lib_enc/enc_prm.c b/lib_enc/enc_prm.c new file mode 100644 index 0000000..4ee6a97 --- /dev/null +++ b/lib_enc/enc_prm.c @@ -0,0 +1,915 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include +#include "options.h" +#include "rom_com_fx.h" +#include "stl.h" +#include "prot_fx.h" + + +static void enc_prm_hm( + Word16 *prm_hm, + Encoder_State_fx *st, + Word16 L_frame +) +{ + Word8 flag; + + /* Disable HM for non-GC,VC modes */ + test(); + IF (NE_16(st->tcx_cfg.coder_type, VOICED)&&NE_16(st->tcx_cfg.coder_type,GENERIC)) + { + return; + } + + /* Flag */ + push_next_indice_fx(st, prm_hm[0], 1); + + IF (prm_hm[0]) + { + /* Periodicy index */ + flag = 0; + move16(); + if ( GE_16(L_frame, 256)) + { + flag = 1; + move16(); + } + EncodeIndex(flag, prm_hm[1], st); + + IF (EQ_16(st->tcx_cfg.coder_type, VOICED)) + { + /* Gain index */ + push_next_indice_fx(st, prm_hm[2], kTcxHmNumGainBits); + } + } +} + +/*-----------------------------------------------------------------* + * Function enc_prm_rf() * + * ~~~~~~~~~~~~~~~~~~~~~~ * + * * + * encode RF parameters for ACELP and TCX partial copy * + *-----------------------------------------------------------------*/ + +void enc_prm_rf( Encoder_State_fx *st, + const Word16 rf_frame_type, + const Word16 fec_offset + ) +{ + Word16 sfr, nb_subfr, n, index; + Word16 ltp_mode, ltf_mode, gains_mode; + + nb_subfr = st->nb_subfr; + + /* partial copy bitstream writing */ + test(); + IF ( GE_16(rf_frame_type,RF_TCXFD)&&LE_16(rf_frame_type,RF_TCXTD2)) + { + /* TCX frames partial copy write */ + + /* LSF indices */ + IF( EQ_16(rf_frame_type, RF_TCXFD)) + { + push_next_indice_fx(st, st->rf_indx_lsf[fec_offset][0], lsf_numbits[0]); /* VQ 1 */ + push_next_indice_fx(st, st->rf_indx_lsf[fec_offset][1], lsf_numbits[1]); /* VQ 2 */ + push_next_indice_fx(st, st->rf_indx_lsf[fec_offset][2], lsf_numbits[2]); /* VQ 3 */ + } + + /* classification */ + test(); + test(); + IF( EQ_16(st->rf_clas[fec_offset], UNVOICED_CLAS)) + { + index = 0; + move16(); + } + ELSE IF( (EQ_16(st->rf_clas[fec_offset], VOICED_TRANSITION))||(EQ_16(st->rf_clas[fec_offset],UNVOICED_TRANSITION))) + { + index = 1; + move16(); + } + ELSE IF( EQ_16(st->rf_clas[fec_offset], VOICED_CLAS)) + { + index = 2; + move16(); + } + ELSE + { + index = 3; + move16(); + } + push_next_indice_fx(st, index, 2); + + IF( EQ_16(rf_frame_type, RF_TCXFD)) + { + /* TCX global gain = 7 bits */ + push_next_indice_fx(st, st->rf_gain_tcx[fec_offset], 7); + /*window info + 1 bit for long overlap + 2 if minimum or half overlap*/ + } + ELSE + { + /*gains adapt + gains inov*/ + + /*LPC on full rate -> excitation */ + /* pitch and gain */ + /* LTP data */ + test(); + IF ( (EQ_16(rf_frame_type, RF_TCXTD1)||EQ_16(rf_frame_type,RF_TCXTD2))&&st->tcxltp!=0) + { + push_next_indice_fx(st, st->rf_tcxltp_param[fec_offset], 9); + } + } + } + ELSE IF( EQ_16(rf_frame_type,7)) /* NELP bitstream writing */ + { + /* LSF indices */ + push_next_indice_fx(st, st->rf_indx_lsf[fec_offset][0], 8); /* VQ 1 */ + push_next_indice_fx(st, st->rf_indx_lsf[fec_offset][1], 8); /* VQ 2 */ + + /* NELP gain indices */ + push_next_indice_fx( st, st->rf_indx_nelp_iG1[fec_offset], 5 ); + push_next_indice_fx( st, st->rf_indx_nelp_iG2[fec_offset][0], 6 ); + push_next_indice_fx( st, st->rf_indx_nelp_iG2[fec_offset][1], 6 ); + + /* NELP filter selection index */ + push_next_indice_fx( st, st->rf_indx_nelp_fid[fec_offset], 2 ); + + /* tbe gainFr */ + push_next_indice_fx( st, st->rf_indx_tbeGainFr[fec_offset], 5 ); + } + ELSE IF ( GE_16(rf_frame_type,4)) /* rf_frame_type ALL_PRED: 4, NO_PRED: 5, GEN_PRED: 6 */ + { + /* LSF indices */ + push_next_indice_fx(st, st->rf_indx_lsf[fec_offset][0], 8); /* VQ 1 */ + push_next_indice_fx(st, st->rf_indx_lsf[fec_offset][1], 8); /* VQ 2 */ + + /* ES pred */ + push_next_indice_fx(st, st->rf_indx_EsPred[fec_offset], 3); + + ltp_mode = ACELP_LTP_MODE[1][1][rf_frame_type]; + ltf_mode = ACELP_LTF_MODE[1][1][rf_frame_type]; + gains_mode = ACELP_GAINS_MODE[1][1][rf_frame_type]; + + /* Subframe parameters */ + FOR( sfr = 0; sfr < nb_subfr; sfr++ ) + { + /* Pitch lag (5, or 8 bits) */ + n = ACELP_LTP_BITS_SFR[ltp_mode][sfr]; + IF (n != 0) + { + push_next_indice_fx(st, st->rf_indx_pitch[fec_offset][sfr], n); + } + + /* Adaptive codebook filtering (1 bit) */ + IF( EQ_16(ltf_mode,2)) + { + push_next_indice_fx(st, st->rf_indx_ltfMode[fec_offset][sfr], 1); + } + + /*Innovative codebook*/ + test(); + test(); + test(); + IF( (EQ_16(rf_frame_type,RF_NOPRED))|| + (EQ_16(rf_frame_type,RF_GENPRED) && + (sfr == 0 || EQ_16(sfr,2))) ) + { + push_next_indice_fx(st, st->rf_indx_fcb[fec_offset][sfr], 7); + } + + /* Gains (5b, 6b or 7b / subfr) */ + test(); + IF( sfr == 0 || EQ_16(sfr,2)) + { + n = ACELP_GAINS_BITS[gains_mode]; + push_next_indice_fx(st, st->rf_indx_gain[fec_offset][sfr], n); + } + } + /* tbe gainFr */ + push_next_indice_fx( st, st->rf_indx_tbeGainFr[fec_offset], 2 ); + } + + /***************/ + /*IMPORTANT: The last three bits are always the rf_frame_type in the bitstream (for both acelp and tcx partial copy); + the rf_frame_type indicates the length of the partial copy payload at the decoder. + The 2 bits before the rf_frame_type contains the fec_offset */ + + /***************/ + /* write FEC offset just before the rf_frame_type */ + test(); + test(); + IF(EQ_16(fec_offset,2)) + { + push_next_indice_fx(st, 0, 2); + } + ELSE IF(EQ_16(fec_offset,3)||EQ_16(fec_offset,5)||EQ_16(fec_offset,7)) + { + push_next_indice_fx(st, (fec_offset - 1)/2, 2); + } + + /* write RF frame type last in the bitstream */ + push_next_indice_fx(st, rf_frame_type, 3); + +} + + + + +/*-----------------------------------------------------------------* + * Funtion enc_prm() * + * ~~~~~~~~~~~~~~~~~~~~~~ * + * * + * encode parameters according to selected mode including * + * the FAC parameters when transition occurs. * + *-----------------------------------------------------------------*/ + +void enc_prm( + const Word16 coder_type, /* (i) : coding type */ + Word16 param[], /* (i) : parameters */ + Word16 param_lpc[], /* (i) : LPC parameters */ + Encoder_State_fx *st, /* i/o : quantization Analysis values */ + Word16 L_frame, + CONTEXT_HM_CONFIG hm_cfg[] + ,Word16 * bits_param_lpc, + Word16 no_param_lpc +) +{ + Word16 j, k, n, sfr, core, last_core, *prm, tmp; + Word16 nbits_start, total_nbbits; + Word16 nbits_header; + Word16 nbits_lpc; + Word16 nbits_tcx; + Word16 lg,nb_subfr; + Word16 lgFB; + Word16 nTnsParams; + Word16 nTnsBits; + Word16 ix, j_old, wordcnt, bitcnt; + Word16 hm_size; + Word16 numlpc; + Word8 flag_ctx_hm; + Word16 index; + Word32 tmp32; + CONTEXT_HM_CONFIG * phm_cfg; + Word16 idx; + Word16 start_idx; + Word16 nBits; + + /*--------------------------------------------------------------------------------* + * INIT + *--------------------------------------------------------------------------------*/ + + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + nbits_lpc=0; + nbits_tcx = 0; + + flag_ctx_hm = 0; + + /* Useful parameters */ + move16(); + move16(); + move16(); + nb_subfr = st->nb_subfr; + core = st->core_fx; + last_core = st->last_core_fx; + + /* Initialize pointers */ + move16(); + prm = param; + + /* Init counters */ + move16(); + move16(); + j = 0; + nbits_start = st->nb_bits_tot_fx; + + + /*--------------------------------------------------------------------------------* + * HEADER + *--------------------------------------------------------------------------------*/ + + IF (EQ_16(st->mdct_sw, MODE1)) + { + /* Adjust st->bits_frame_core not to subtract MODE2 bandwidth signaling */ + st->bits_frame_core = add(st->bits_frame_core, FrameSizeConfig[st->frame_size_index].bandwidth_bits); + + /* Write MODE1 core mode signaling */ + signalling_mode1_tcx20_enc(st, 1); + } + + /* Modes (ACE_GC, ACE_UC, TCX20, TCX10...) */ + + IF ( st->tcxonly ) + { + push_next_indice_fx(st, core==TCX_10_CORE, 1); + { + index = 3; + move16(); + test(); + IF( EQ_16(st->clas_fx, UNVOICED_CLAS)) + { + index = 0; + move16(); + } + ELSE IF( (EQ_16(st->clas_fx, VOICED_TRANSITION))||(EQ_16(st->clas_fx,UNVOICED_TRANSITION))) + { + index = 1; + move16(); + } + ELSE IF( EQ_16(st->clas_fx, VOICED_CLAS)) + { + index = 2; + move16(); + } + push_next_indice_fx(st, index, 2); + } + } + ELSE + { + IF ( core==ACELP_CORE ) + { + /* write the RF signalling information */ + IF( EQ_16(st->rf_mode,1)) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + idx = 0; + WHILE ( NE_32(acelp_sig_tbl[idx],st->total_brate_fx)) /* total bitrate is kept at 13.2kbps */ + { + idx = add(idx,1); + } + + /* retrieve the number of bits for signalling */ + nBits = (Word16) acelp_sig_tbl[++idx]; + + /* retrieve the signalling index */ + idx = add(idx,1); + start_idx = idx; + tmp32 = SIG2IND_fx(coder_type, st->bwidth_fx, st->sharpFlag, st->rf_mode); + WHILE( NE_32(acelp_sig_tbl[idx], tmp32)) + { + idx = add(idx,1); + } + push_next_indice_fx( st, idx - start_idx, nBits); + push_next_indice_fx( st, 0, 1); /* Indicate to the decoder that the core is ACELP*/ + nbits_start = 3; + } + ELSE + { + push_next_indice_fx(st, coder_type, 3); + } + } + ELSE + { + IF (EQ_16(st->mdct_sw, MODE1)) + { + /* 2 bits instead of 3 as TCX is already signaled */ + push_next_indice_fx(st, st->tcx_cfg.coder_type, 2 ); + } + ELSE + { + IF (EQ_16(st->mdct_sw_enable, MODE2)) + { + push_next_indice_fx(st, 1, 1); /* TCX */ + push_next_indice_fx(st, 0, 1); /* not HQ_CORE */ + push_next_indice_fx(st, st->tcx_cfg.coder_type, 2); + } + ELSE + { + /*write the RF signalling information*/ + IF( EQ_16(st->rf_mode,1)) + { + /* find the section in the ACELP signalling table corresponding to bitrate */ + idx = 0; + WHILE (NE_32(acelp_sig_tbl[idx],st->total_brate_fx)) + { + idx = add(idx,1); + } + + /* retrieve the number of bits for signalling */ + nBits = (Word16) acelp_sig_tbl[++idx]; + + test(); + test(); + IF(EQ_16(st->tcx_cfg.coder_type,VOICED)|| + EQ_16(st->tcx_cfg.coder_type,GENERIC)|| + EQ_16(st->tcx_cfg.coder_type,TRANSITION)) + { + st->sharpFlag=1; + } + ELSE + { + st->sharpFlag=0; + } + + /* retrieve the signalling index */ + idx = add(idx,1); + start_idx = idx; + tmp32 = SIG2IND_fx(st->tcx_cfg.coder_type, st->bwidth_fx, st->sharpFlag, st->rf_mode); + WHILE( NE_32(acelp_sig_tbl[idx], tmp32)) + { + idx = add(idx,1); + } + push_next_indice_fx( st, idx - start_idx, nBits); + push_next_indice_fx( st, 1, 1); /* Indicate to the decoder that the core is TCX*/ + nbits_start = 3; + } + ELSE + { + push_next_indice_fx(st, 4+st->tcx_cfg.coder_type, 3 ); + } + } + } + } + } + + /* Encode previous mode for error concealment */ + test(); + IF (!(core==ACELP_CORE&&st->tcx_cfg.lfacNext<=0)) + { + tmp = 0; + move16(); + test(); + IF( NE_16(last_core, ACELP_CORE)||EQ_16(core,TCX_10_CORE)) + + { + tmp = TCX_20_CORE; + move16(); + } + push_next_indice_fx(st, tmp, 1); + } + + /* write TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */ + IF ( core!=ACELP_CORE ) + { + Word16 overlap_code; + assert(st->tcx_cfg.tcx_curr_overlap_mode != NOT_SUPPORTED && st->tcx_cfg.tcx_curr_overlap_mode <= ALDO_WINDOW && st->tcx_cfg.tcx_curr_overlap_mode >= FULL_OVERLAP); /*1 is not allowed!*/ + IF (EQ_16(st->tcx_cfg.tcx_curr_overlap_mode, MIN_OVERLAP)) + { + nbits_tcx = 2; + move16(); + overlap_code = 2; + move16(); + } + ELSE IF (EQ_16(st->tcx_cfg.tcx_curr_overlap_mode, HALF_OVERLAP)) + { + nbits_tcx = 2; + move16(); + overlap_code = 3; + move16(); + } + ELSE + { + nbits_tcx = 1; + move16(); + overlap_code = 0; + move16(); + } + push_next_indice_fx(st, overlap_code, nbits_tcx); + } + + IF( st->plcExt.enableGplc ) + { + /* encode side information. */ + enc_prm_side_Info( &st->plcExt, st ); + } + + IF( st->glr != 0) + { + test(); + test(); + test(); + test(); + if (core != ACELP_CORE || EQ_16(coder_type,INACTIVE)||(st->last_core_fx==ACELP_CORE&&EQ_16(st->last_coder_type_raw_fx,INACTIVE))||st->glr_reset!=0) + { + st->glr_idx[0] = 0; + move16(); + } + + IF( EQ_16(core,ACELP_CORE)) + { + push_next_indice_fx(st, st->glr_idx[0], G_LPC_RECOVERY_BITS); + } + } + + st->glr_reset = 0; + move16(); + + nbits_header = sub(st->nb_bits_tot_fx, nbits_start); + + + /*--------------------------------------------------------------------------------* + * LPC PARAMETERS + *--------------------------------------------------------------------------------*/ + + IF ( s_and(st->enableTcxLpc!=0, core != ACELP_CORE) ) + { + /* Encode the indices */ + nbits_lpc = enc_lsf_tcxlpc(¶m_lpc, st); + } + ELSE + { + IF (st->lpcQuantization == 0) + { + /* LPC quantizer */ + numlpc = 2; + move16(); + if(EQ_16(core, TCX_20_CORE)) + { + numlpc = 1; + move16(); + } + + nbits_lpc = encode_lpc_avq(st, numlpc, param_lpc, core); + } + ELSE IF (EQ_16(st->lpcQuantization, 1)) + { + test(); + test(); + IF(EQ_32(st->sr_core, 16000)&&EQ_16(coder_type,VOICED)&&EQ_16(core,ACELP_CORE)) + { + nbits_lpc = lsf_bctcvq_encprm(st, param_lpc, bits_param_lpc, no_param_lpc); + } + ELSE + { + nbits_lpc = lsf_msvq_ma_encprm(st, param_lpc, core, coder_type, st->acelp_cfg.midLpc, bits_param_lpc, no_param_lpc ); + } + } + ELSE + { + assert(0 && "LPC quant not supported!"); + } + } + + + /*--------------------------------------------------------------------------------* + * PRINT BIT ALLOCATION + *--------------------------------------------------------------------------------*/ + + + + /*--------------------------------------------------------------------------------* + * ACELP + *--------------------------------------------------------------------------------*/ + + IF (core == ACELP_CORE) + { + /* Adaptive BPF (2 bits)*/ + n = ACELP_BPF_BITS[st->acelp_cfg.bpf_mode]; + + IF(n!=0) + { + push_next_indice_fx(st, st->bpf_gain_param, n); + } + + /* Mean energy (2 or 3 bits) */ + n = ACELP_NRG_BITS[st->acelp_cfg.nrg_mode]; + + IF(n!=0) + { + push_next_indice_fx(st, prm[j++], n); + } + + /* Subframe parameters */ + + FOR (sfr=0; sfracelp_cfg.ltp_mode][sfr]; + + IF (n!=0) + { + push_next_indice_fx(st, prm[j++], n); + } + + /* Adaptive codebook filtering (1 bit) */ + + IF(EQ_16(st->acelp_cfg.ltf_mode,2)) + { + push_next_indice_fx(st, prm[j++], 1); + } + + /*Innovative codebook*/ + { + move16(); + j_old = j; + + if ((st->acelp_cfg.fixed_cdk_index[sfr] >= ACELP_FIXED_CDK_NB) || (st->acelp_cfg.fixed_cdk_index[sfr] < 0)) + { + fprintf(stderr,"ACELP bits allocation: wrong fixed cdk bit allocation\n"); + assert(0); + } + + + wordcnt = shr(ACELP_FIXED_CDK_BITS(st->acelp_cfg.fixed_cdk_index[sfr]), 4); + + bitcnt = s_and(ACELP_FIXED_CDK_BITS(st->acelp_cfg.fixed_cdk_index[sfr]), 15); + + + FOR (ix = 0; ix < wordcnt; ix++) + { + push_next_indice_fx(st, prm[j++], 16); + } + + IF (bitcnt) + { + push_next_indice_fx(st, prm[j++], bitcnt); + } + + j = add(j_old, 8); + } + + /* Gains (5b, 6b or 7b / subfr) */ + n = ACELP_GAINS_BITS[st->acelp_cfg.gains_mode[sfr]]; + push_next_indice_fx(st, prm[j++], n); + }/*end of for(sfr)*/ + }/*end of mode[0]==0*/ + + + /*--------------------------------------------------------------------------------* + * TCX20 + *--------------------------------------------------------------------------------*/ + IF ( s_or((Word16)EQ_16(core,TCX_20_CORE),(Word16)EQ_16(core,HQ_CORE))) + { + flag_ctx_hm = 0; + move16(); + IF(st->enablePlcWaveadjust) + { + push_next_indice_fx(st, st->Tonal_SideInfo, 1); + } + + /* TCX Gain = 7 bits */ + push_next_indice_fx(st, prm[j++], 7); + + /* TCX Noise Filling = NBITS_NOISE_FILL_LEVEL bits */ + push_next_indice_fx(st, prm[j++], NBITS_NOISE_FILL_LEVEL); + + /* LTP data */ + test(); + IF ( st->tcxltp || GT_32(st->sr_core, 25600)) + { + IF ( prm[j] ) + { + push_next_indice_fx(st, 1 , 1); + push_next_indice_fx(st, prm[j+1], 9); + push_next_indice_fx(st, prm[j+2], 2); + } + ELSE + { + push_next_indice_fx(st, 0 , 1); + } + } + j = add(j, 3); + + /* TCX spectral data */ + lg = L_frame; + move16(); + lgFB = st->tcx_cfg.tcx_coded_lines; + move16(); + + IF ( last_core==ACELP_CORE ) + { + /* ACE->TCX transition */ + lg = add(lg, st->tcx_cfg.tcx_offset); + lgFB = add(lgFB, shr(lgFB, 2)); + if(st->tcx_cfg.lfacNext<0) + { + lg = sub(lg,st->tcx_cfg.lfacNext); + } + } + + /* TNS data */ + nTnsParams = 0; + move16(); + nTnsBits = 0; + move16(); + + IF (st->tcx_cfg.fIsTNSAllowed) + { + WriteTnsData(st->tcx_cfg.pCurrentTnsConfig, prm+j, &nTnsParams, st, &nTnsBits); + j = add(j, nTnsParams); + } + + hm_size = shl(mult(st->tcx_cfg.bandwidth, lg), 1); + test(); + IF ( st->tcx_lpc_shaped_ari && NE_16(last_core, ACELP_CORE)) + { + enc_prm_hm(&prm[j], st, hm_size); + } + + /*Context HM flag*/ + test(); + IF ( st->tcx_cfg.ctx_hm && NE_16(last_core, ACELP_CORE)) + { + push_next_indice_fx(st, prm[j], 1); + + IF (prm[j]) + { + EncodeIndex(sub(hm_size,256) >= 0, prm[j+1], st); + flag_ctx_hm = 1; + move16(); + } + } + j = add(j, NPRM_CTX_HM); + + IF (st->igf) + { + st->hIGFEnc.infoTotalBitsPerFrameWritten = 0; + move16(); + IF (EQ_16(st->last_core_fx, ACELP_CORE)) + { + IGFEncWriteBitstream( &st->hIGFEnc, st, &st->hIGFEnc.infoTotalBitsPerFrameWritten, + IGF_GRID_LB_TRAN, 1 ); + } + ELSE + { + IGFEncWriteBitstream( &st->hIGFEnc, st, &st->hIGFEnc.infoTotalBitsPerFrameWritten, + IGF_GRID_LB_NORM, 1 ); + } + } + total_nbbits = sub(st->nb_bits_tot_fx, nbits_start); + if(EQ_16(st->rf_mode,1)) + { + total_nbbits = add(total_nbbits,st->rf_target_bits_write); + } + nbits_tcx = sub(st->bits_frame_core, total_nbbits); + + IF (st->tcx_lpc_shaped_ari != 0) + { + push_next_bits_fx(st, &prm[++j], nbits_tcx); + j = add(j, nbits_tcx); + } + ELSE + { + phm_cfg = NULL; + move16(); + if (flag_ctx_hm) + { + phm_cfg = hm_cfg; + move16(); + } + ACcontextMapping_encode2_no_mem_s17_LC(st, prm+j, + lgFB, + prm[j-1], /* lastnz */ + nbits_tcx, NPRM_RESQ * st->tcx_cfg.resq, phm_cfg); + } + + } + + + /*--------------------------------------------------------------------------------* + * TCX10 + *--------------------------------------------------------------------------------*/ + + + IF (EQ_16(core,TCX_10_CORE)) + { + Word16 nbits_igf = 0; + move16(); + IF (st->igf) + { + nbits_igf = IGFEncWriteConcatenatedBitstream( &st->hIGFEnc, st ); + } + FOR (k = 0; k < 2; k++) + { + flag_ctx_hm = 0; + move16(); + + move16(); + move16(); + prm = param + (k*NPRM_DIV); + + j = 0; + + move16(); + nbits_tcx = total_nbbits = sub(st->nb_bits_tot_fx, nbits_start); + + test(); + IF(st->enablePlcWaveadjust && k) + { + push_next_indice_fx(st, st->Tonal_SideInfo, 1); + } + + /* TCX Gain = 7 bits */ + push_next_indice_fx(st, prm[j++], 7); + + /* TCX Noise Filling = NBITS_NOISE_FILL_LEVEL bits */ + push_next_indice_fx(st, prm[j++], NBITS_NOISE_FILL_LEVEL); + + /* LTP data */ + test(); + test(); + IF ( (k == 0) && (st->tcxltp!=0 || GT_32(st->sr_core, 25600)))/* PLC pitch info for HB */ + { + IF ( prm[j] ) + { + push_next_indice_fx(st, 1 , 1); + push_next_indice_fx(st, prm[j+1], 9); + push_next_indice_fx(st, prm[j+2], 2); + } + ELSE + { + push_next_indice_fx(st, 0 , 1); + } + } + j = add(j, 3); + + /* TCX spectral data */ + lg = shr(L_frame, 1); + lgFB = shr(st->tcx_cfg.tcx_coded_lines, 1); + + IF ( s_and(k==0, last_core==ACELP_CORE) ) + { + /* ACE->TCX transition */ + lg = add(lg, st->tcx_cfg.tcx_offset); + lgFB = add(lgFB, shr(lgFB, 1)); + if(st->tcx_cfg.lfacNext<0) + { + lg = sub(lg,st->tcx_cfg.lfacNext); + } + } + + /* TNS data */ + move16(); + move16(); + nTnsParams = 0; + nTnsBits = 0; + + IF (st->tcx_cfg.fIsTNSAllowed) + { + + SetTnsConfig(&st->tcx_cfg, 0, (last_core == ACELP_CORE) && (k == 0)); + + WriteTnsData(st->tcx_cfg.pCurrentTnsConfig, prm+j, &nTnsParams, st, &nTnsBits); + j = add(j, nTnsParams); + } + + hm_size = shl(mult(st->tcx_cfg.bandwidth, lgFB), 1); + + /*Context HM flag*/ + test(); + test(); + IF ( st->tcx_cfg.ctx_hm && !(last_core == ACELP_CORE && k == 0) ) + { + push_next_indice_fx(st, prm[j], 1); + + IF (prm[j]) + { + EncodeIndex(sub(hm_size,256) >= 0, prm[j+1], st); + flag_ctx_hm = 1; + move16(); + } + } + j = add(j, NPRM_CTX_HM); + + total_nbbits = sub(st->nb_bits_tot_fx, nbits_start); + + nbits_tcx = sub(shr(sub(add(sub(sub(sub(st->bits_frame_core, nbits_header), nbits_lpc), nbits_igf), 1), k), 1), sub(total_nbbits, nbits_tcx)); + + phm_cfg = NULL; + move16(); + if (flag_ctx_hm) + { + phm_cfg = &hm_cfg[k]; + move16(); + } + ACcontextMapping_encode2_no_mem_s17_LC(st, prm+j, + lgFB, + prm[j-1], /* lastnz */ + nbits_tcx, NPRM_RESQ * st->tcx_cfg.resq, phm_cfg); + + } /* k, window index */ + } + + + /*--------------------------------------------------------------------------------* + * END + *--------------------------------------------------------------------------------*/ + + + total_nbbits = sub(st->nb_bits_tot_fx, nbits_start); + + + /* Check if total encoded bits does not exceed CBR target bits (->this must never happen) */ + if (st->bits_frame_core&&(total_nbbits>st->bits_frame_core)) + { + fprintf(stderr,"AllocatedBits: %d Used bits: %d \n", st->bits_frame_core,total_nbbits); + assert(!"Core totalbits > CBR target bitrate"); + } + + return; +} + diff --git a/lib_enc/enc_tran_fx.c b/lib_enc/enc_tran_fx.c new file mode 100644 index 0000000..ee87cd6 --- /dev/null +++ b/lib_enc/enc_tran_fx.c @@ -0,0 +1,416 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ + + +#include "stl.h" + +/*=================================================================================*/ +/* FUNCTION : void encod_tran_fx () */ +/*---------------------------------------------------------------------------------*/ +/* PURPOSE : */ +/*---------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* (Word16) L_frame_fx : length of the frame Q0 */ +/* (Word16[]) speech_fx : input speech Q0 */ +/* (Word16[]) Aq_fx : 12k8 Lp coefficient Q12 */ +/* (Word16[]) A_fx : unquantized A(z) filter with bandwidth expansion Q12 */ +/* (Word16) coder_type : coding type Q0 */ +/* (Word16) Es_pred_fx : predicted scaled innov. energy Q8 */ +/* (Word16[]) T_op_fx : open loop pitch Q0 */ +/* (Word16[]) voicing_fx : voicing Q15 */ +/* (Word16*) res_fx : residual signal Q_new*/ +/* (Word16) gsc_attack_flag : Flag to indicate when an audio attack is deal with TM*/ +/* (Word16) shift : shift factor */ +/* (Word16[]) Q_new : input scaling */ +/*---------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* (Word16*) voice_factors : voicing factors Q15 */ +/*---------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Encoder_State_fx *st_fx :Encoder state structure */ +/* (Word16*) syn_fx :core synthesis Qnew */ +/* (Word16*) exc_fx :current non-enhanced excitation Q0 */ +/* (Word16*) exc2_fx :current enhanced excitation Q0 */ +/* (Word16*) pitch_buf_fx :floating pitch values for each subframe Q6 */ +/* (Word16*) bwe_exc_fx :excitation for SWB TBE Q0 */ +/*---------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*---------------------------------------------------------------------------------*/ + +Word16 encod_tran_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 L_frame_fx, /* i : length of the frame */ + const Word16 speech_fx[], /* i : input speech */ + const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */ + const Word16 coder_type, /* i : coding type */ + const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */ + const Word16 T_op_fx[], /* i : open loop pitch */ + const Word16 voicing_fx[], /* i : voicing */ + const Word16 *res_fx, /* i : residual signal */ + Word16 *syn_fx, /* i/o: core synthesis */ + Word16 *exc_fx, /* i/o: current non-enhanced excitation */ + Word16 *exc2_fx, /* i/o: current enhanced excitation */ + Word16 *pitch_buf_fx, /* i/o: floating pitch values for each subframe */ + Word16 *voice_factors, /* o : voicing factors */ + Word16 *bwe_exc_fx, /* i/o: excitation for SWB TBE */ + const Word16 gsc_attack_flag, /* i : Flag to indicate when an audio attack is deal with TM */ + Word16 *unbits, /* i/o: number of unused bits */ + Word16 sharpFlag, /* o : formant sharpening flag */ + const Word16 shift, /* i : Scaling to get 12 bits */ + const Word16 Q_new /* i : Input scaling */ +) +{ + Word16 xn[L_SUBFR]; /* Target vector for pitch search */ + Word16 xn2[L_SUBFR]; /* Target vector for codebook search */ + Word16 cn[L_SUBFR]; /* Target vector in residual domain */ + Word16 h1[L_SUBFR+(M+1)]; /* Impulse response vector */ + Word16 h2_fx[L_SUBFR+(M+1)]; /* Impulse response vector */ + Word16 code[L_SUBFR]; /* Fixed codebook excitation */ + Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */ + Word16 y2[L_SUBFR]; /* Filtered algebraic excitation */ + Word16 gain_pit = 0,Gain_pitX2,gcode16; /* Pitch gain */ + Word16 voice_fac; /* Voicing factor */ + Word32 gain_code = 0; /* Gain of code */ + Word32 Lgcode; + Word16 gain_inov=0; /* inovation gain */ + Word16 i, i_subfr, tc_subfr,tmp1_fx,tmp_fx; /* tmp variables */ + Word16 position, T0_min, T0_max; /* pitch and TC variables */ + Word16 T0, T0_frac; /* close loop integer pitch and fractional part */ + Word16 *pt_pitch; /* pointer to floating pitch buffer */ + Word16 g_corr[10]; /* ACELP correlation values and gain pitch */ + Word16 clip_gain; /* LSF clip gain */ + const Word16 *p_Aw, *p_Aq; /* pointer to LP filter coefficient vector */ + Word16 gain_preQ = 0; /* Gain of prequantizer excitation */ + Word16 code_preQ[L_SUBFR]; /* Prequantizer excitation */ + Word16 Jopt_flag; /* joint optimization flag */ + Word16 unbits_PI = 0; /* saved bits for PI */ + Word32 norm_gain_code=0; + + Word16 shift_wsp; + Word32 L_tmp; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + gain_pit = 0; + move16(); + gain_code = L_deposit_l(0); + gain_preQ = 0; + move16(); + unbits_PI = 0; + move16(); + IF( EQ_16(L_frame_fx,L_FRAME)) + { + T0_max = PIT_MAX; + move16(); + T0_min = PIT_MIN; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + T0_max = PIT16k_MAX; + move16(); + T0_min = PIT16k_MIN; + move16(); + } + + /**unbits = 0;move16();*/ + Jopt_flag = 0; + move16(); + tc_subfr = -1; + move16(); + if( gsc_attack_flag ) + { + tc_subfr = 3*L_SUBFR; + move16(); + } + + p_Aw = Aw_fx; + p_Aq = Aq_fx; + pt_pitch = pitch_buf_fx; + gain_preQ = 0; + move16(); + set16_fx( code_preQ, 0, L_SUBFR ); + shift_wsp = add(Q_new,shift); + + /*----------------------------------------------------------------* + * ACELP subframe loop + *----------------------------------------------------------------*/ + + FOR ( i_subfr=0; i_subfrmem_syn, i_subfr, &mem->mem_w0, p_Aq, + res_fx, L_SUBFR, p_Aw, st_fx->preemph_fac, xn, cn, h1 ); + + Copy_Scale_sig(h1, h2_fx, L_SUBFR, -2); + Scale_sig(h1, L_SUBFR, add(1, shift)); /* set h1[] in Q14 with scaling for convolution */ + + /* scaling of xn[] to limit dynamic at 12 bits */ + Scale_sig(xn, L_SUBFR, shift); + + /*-----------------------------------------------------------------* + * TC: subframe determination & + * adaptive/glottal part of excitation construction + *-----------------------------------------------------------------*/ + + transition_enc_fx( st_fx, st_fx->core_brate_fx, L_frame_fx, coder_type, i_subfr, &tc_subfr, &Jopt_flag, &position, voicing_fx, T_op_fx, &T0, + &T0_frac, &T0_min, &T0_max, exc_fx, y1, res_fx, h1, xn, xn2, st_fx->clip_var_fx, &gain_pit, g_corr, &clip_gain, &pt_pitch, bwe_exc_fx ,Q_new,shift); + + /*-----------------------------------------------------------------* + * Transform domain contribution encoding - active frames + *-----------------------------------------------------------------*/ + + IF( GT_32(st_fx->core_brate_fx,ACELP_24k40)) + { + transf_cdbk_enc_fx( st_fx, st_fx->core_brate_fx, st_fx->extl_fx, coder_type, 0, i_subfr, tc_subfr, cn, exc_fx, + p_Aq, Aw_fx, h1, xn, xn2, y1, y2, Es_pred_fx, &gain_pit, gain_code, g_corr, clip_gain, + &(st_fx->mem_deemp_preQ_fx), &(st_fx->mem_preemp_preQ_fx), &gain_preQ, code_preQ, unbits, Q_new, shift); + } + + /*-----------------------------------------------------------------* + * ACELP codebook search + pitch sharpening + *-----------------------------------------------------------------*/ + + inov_encode_fx( st_fx, st_fx->core_brate_fx, 0, L_frame_fx, st_fx->last_L_frame_fx, coder_type, st_fx->bwidth_fx, sharpFlag, + i_subfr, tc_subfr, p_Aq, gain_pit, cn, exc_fx, h2_fx, mem->tilt_code, *pt_pitch, xn2, code, y2, &unbits_PI, shift ); + + test(); + test(); + test(); + if( (EQ_16(st_fx->L_frame_fx,L_FRAME16k))&&(tc_subfr==0)&&(EQ_16(i_subfr,L_SUBFR))&&(EQ_16(T0,2*L_SUBFR))) + { + Jopt_flag = 1; + move16(); + } + /*-----------------------------------------------------------------* + * Quantize the gains + * Test quantized gain of pitch for pitch clipping algorithm + * Update tilt of code: 0.0 (unvoiced) to 0.5 (voiced) + *-----------------------------------------------------------------*/ + IF( Jopt_flag == 0 ) + { + /* SQ gain_code */ + gain_enc_tc_fx( st_fx, st_fx->core_brate_fx, L_frame_fx, i_subfr, tc_subfr, xn, y2, code, Es_pred_fx, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, shift_wsp ); + } + ELSE + { + IF ( GT_32(st_fx->core_brate_fx,ACELP_32k)) + { + /* SQ gain_pit and gain_code */ + gain_enc_SQ_fx( st_fx, st_fx->core_brate_fx, coder_type, i_subfr, tc_subfr, xn, y1, y2, code, Es_pred_fx, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain, shift_wsp ); + } + ELSE + { + /* VQ gain_pit and gain_code */ + gain_enc_mless_fx( st_fx, st_fx->core_brate_fx, L_frame_fx, coder_type, i_subfr, tc_subfr, xn, y1, shift_wsp, y2, code, Es_pred_fx, + &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain ); + } + } + gp_clip_test_gain_pit_fx( st_fx->core_brate_fx, gain_pit, st_fx->clip_var_fx ); + + Lgcode = L_shl(gain_code, Q_new); /* scaled gain_code with Qnew -> Q16*/ + gcode16 = round_fx(Lgcode); + mem->tilt_code = Est_tilt2(&exc_fx[i_subfr], gain_pit, code, Lgcode, &voice_fac, shift); + /*-----------------------------------------------------------------* + * Update memory of the weighting filter + *-----------------------------------------------------------------*/ + + /*st->mem_w0 = xn[L_SUBFR-1] - (gain_pit*y1[L_SUBFR-1]) - (gain_code*y2[L_SUBFR-1]);*/ + L_tmp = L_mult(gcode16, y2[L_SUBFR - 1]); + L_tmp = L_shl(L_tmp, add(5, shift)); + L_tmp = L_negate(L_tmp); + L_tmp = L_mac(L_tmp, xn[L_SUBFR - 1], 16384); + L_tmp = L_msu(L_tmp, y1[L_SUBFR - 1], gain_pit); + L_tmp = L_shl(L_tmp, sub(1, shift)); + mem->mem_w0 = round_fx(L_tmp); /*Q_new-1*/ + + /*-----------------------------------------------------------------* + * Construct adaptive part of the excitation + * Save the non-enhanced excitation for FEC_exc + *-----------------------------------------------------------------*/ + + /* Here, all these conditions have one purpose: to use */ + /* the most efficient loop (the one with the least ops) */ + /* This is done by upscaling gain_pit_fx and/or gain_code16 */ + /* when they don't use all 16 bits of precision */ + + /* exc Q_exc, gpit Q14, code Q12, gcode Q0 */ + IF (norm_s(gain_pit) == 0) + { + FOR (i = 0; i < L_SUBFR; i++) + { + exc2_fx[i+i_subfr] = round_fx(L_shl(L_mult(gain_pit,exc_fx[i+i_subfr]),1)); + } + } + ELSE + { + Gain_pitX2 = shl(gain_pit, 1); + FOR (i = 0; i < L_SUBFR; i++) + { + exc2_fx[i+i_subfr] = mult_r(Gain_pitX2,exc_fx[i+i_subfr]); + } + } + + /*-----------------------------------------------------------------* + * Construct adaptive part of the excitation + * Save the non-enhanced excitation for FEC_exc + *-----------------------------------------------------------------*/ + FOR (i = 0; i < L_SUBFR; i++) + { + /* code in Q9, gain_pit in Q14 */ + L_tmp = L_mult(gcode16, code[i]); + L_tmp = L_shl(L_tmp, 5); + L_tmp = L_mac(L_tmp, exc_fx[i + i_subfr], gain_pit); + L_tmp = L_shl(L_tmp, 1); /* saturation can occur here */ + exc_fx[i + i_subfr] = round_fx(L_tmp); + } + + /*-----------------------------------------------------------------* + * Add the ACELP pre-quantizer contribution + *-----------------------------------------------------------------*/ + + IF( GT_32(st_fx->core_brate_fx,ACELP_24k40)) + { + tmp1_fx = add(16-(2+Q_AVQ_OUT_DEC+1),Q_new); + FOR( i = 0; i < L_SUBFR; i++ ) + { + L_tmp = L_mult(gain_preQ, code_preQ[i]); /* Q2 + Q10 -> Q13*/ + L_tmp = L_shl(L_tmp,tmp1_fx); /* Q16 + Q_exc */ + tmp_fx = round_fx(L_tmp); + + exc2_fx[i+i_subfr] = add(exc2_fx[i+i_subfr],tmp_fx); + move16(); + exc_fx[i+i_subfr] = add(exc_fx[i+i_subfr],tmp_fx); + move16(); + } + } + + /*-----------------------------------------------------------------* + * Prepare TBE excitation + *-----------------------------------------------------------------*/ + + prep_tbe_exc_fx( L_frame_fx, i_subfr, gain_pit, gain_code, code, voice_fac, &voice_factors[i_subfr/L_SUBFR], + bwe_exc_fx, gain_preQ, code_preQ, Q_new, T0, T0_frac, coder_type, st_fx->core_brate_fx ); + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[]. + * Update A(z) filters + *-----------------------------------------------------------------*/ + + Syn_filt_s( 1, p_Aq, M, &exc_fx[i_subfr], &syn_fx[i_subfr], L_SUBFR, mem->mem_syn, 1 ); + + p_Aw += (M+1); + p_Aq += (M+1); + pt_pitch++; + } + + /* write reserved bits */ + WHILE( unbits_PI > 0 ) + { + i = s_min(unbits_PI, 16); + push_indice_fx( st_fx, IND_UNUSED, 0, i ); + unbits_PI -= i; + } + + /* write TC configuration */ + IF( EQ_16(L_frame_fx,L_FRAME)) + { + IF( EQ_16(tc_subfr,TC_0_0)) + { + push_indice_fx( st_fx, IND_TC_SUBFR, 1, 1 ); + } + ELSE IF( EQ_16(tc_subfr,TC_0_64)) + { + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 1, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 1, 1 ); + } + ELSE IF( EQ_16(tc_subfr,TC_0_128)) + { + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 1, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + } + ELSE IF( EQ_16(tc_subfr,TC_0_192)) + { + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 1, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 1, 1 ); + } + ELSE IF( EQ_16(tc_subfr,L_SUBFR)) + { + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 1, 1 ); + } + ELSE IF( EQ_16(tc_subfr,2*L_SUBFR)) + { + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 1, 1 ); + } + ELSE IF( EQ_16(tc_subfr,3*L_SUBFR)) + { + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + } + + } + ELSE /* L_frame == L_FRAME16k */ + { + IF( tc_subfr == 0 ) + { + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 2 ); + } + ELSE IF( EQ_16(tc_subfr,L_SUBFR)) + { + push_indice_fx( st_fx, IND_TC_SUBFR, 1, 2 ); + } + ELSE IF( EQ_16(tc_subfr,2*L_SUBFR)) + { + push_indice_fx( st_fx, IND_TC_SUBFR, 2, 2 ); + } + ELSE IF( EQ_16(tc_subfr,3*L_SUBFR)) + { + push_indice_fx( st_fx, IND_TC_SUBFR, 3, 2 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 0, 1 ); + } + ELSE IF( EQ_16(tc_subfr,4*L_SUBFR)) + { + push_indice_fx( st_fx, IND_TC_SUBFR, 3, 2 ); + push_indice_fx( st_fx, IND_TC_SUBFR, 1, 1 ); + } + + } + + /* SC-VBR */ + st_fx->prev_ppp_gain_pit_fx = gain_pit; + move16(); + st_fx->prev_tilt_code_fx = mem->tilt_code; + move16(); + + return tc_subfr; +} diff --git a/lib_enc/enc_uv_fx.c b/lib_enc/enc_uv_fx.c new file mode 100644 index 0000000..798af31 --- /dev/null +++ b/lib_enc/enc_uv_fx.c @@ -0,0 +1,119 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * encod_unvoiced() + * + * Encode unvoiced (UC) frames + *-------------------------------------------------------------------*/ +/*fixed point implementation of unvoiced_encoder*/ +void encod_unvoiced_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + LPD_state *mem, /* i/o: acelp memories */ + const Word16 *speech_fx, /* i : Input speech */ + const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */ + const Word16 *Aq_fx, /* i : 12k8 Lp coefficient */ + const Word16 vad_flag_fx, + const Word16 *res_fx, /* i : residual signal */ + Word16 *syn_fx, /* o : core synthesis */ + Word16 *tmp_noise_fx, /* o : long-term noise energy */ + Word16 *exc_fx, /* i/o: current non-enhanced excitation */ + Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe */ + Word16 *voice_factors_fx, /* o : voicing factors */ + Word16 *bwe_exc_fx, /* i/o: excitation for SWB TBE */ + const Word16 Q_new, + const Word16 shift +) +{ + Word16 xn_fx[L_SUBFR]; /* Target vector for pitch search */ + Word16 h1_fx[L_SUBFR]; /* Impulse response vector */ + Word16 code_fx[L_SUBFR]; /* Fixed codebook excitation */ + Word16 y2_fx[L_SUBFR]; /* Filtered algebraic excitation */ + Word16 *pt_pitch_fx; /* pointer to floating pitch buffer */ + Word16 gain_pit_fx; /* Pitch gain */ + Word16 voice_fac_fx; /* Voicing factor */ + Word32 L_gain_code_fx; /* gain of code */ + Word16 gain_inov_fx; /* inovative gain */ + const Word16 *p_Aw_fx, *p_Aq_fx; /* pointer to LP filter coeff. vector */ + Word16 i_subfr; + Word32 norm_gain_code_fx; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + gain_pit_fx = 0; + move16(); + + test(); + test(); + test(); + IF( st_fx->Opt_SC_VBR_fx && vad_flag_fx == 0 && (EQ_16(st_fx->last_ppp_mode_fx,1)||EQ_16(st_fx->last_nelp_mode_fx,1))) + { + /* SC_VBR - reset the encoder, to avoid memory not updated issue for the + case when UNVOICED mode is used to code inactive speech */ + CNG_reset_enc_fx( st_fx, mem, pitch_buf_fx, voice_factors_fx, 1 ); + } + + p_Aw_fx = Aw_fx; + p_Aq_fx = Aq_fx; + pt_pitch_fx = pitch_buf_fx; + move16(); + + FOR (i_subfr=0; i_subfrmem_syn, i_subfr, &mem->mem_w0, p_Aq_fx, + res_fx, L_SUBFR, p_Aw_fx, st_fx->preemph_fac, xn_fx, NULL + ,h1_fx + ); + /*Copy_Scale_sig(h1_fx, h2_fx, L_SUBFR, -2);*/ + Scale_sig(h1_fx, L_SUBFR, add(1, shift)); /* set h1[] in Q14 with scaling for convolution */ + + /* scaling of xn[] to limit dynamic at 12 bits */ + Scale_sig(xn_fx, L_SUBFR, shift); + /*----------------------------------------------------------------* + * Unvoiced subframe processing + *----------------------------------------------------------------*/ + + *pt_pitch_fx = gaus_encode_fx( st_fx, i_subfr, h1_fx, xn_fx, exc_fx, &mem->mem_w0, st_fx->clip_var_fx, + &mem->tilt_code, code_fx, &L_gain_code_fx, y2_fx, &gain_inov_fx, + &voice_fac_fx, &gain_pit_fx, Q_new,shift,&norm_gain_code_fx, st_fx->core_brate_fx ); + + *tmp_noise_fx = extract_h(norm_gain_code_fx); + + voice_factors_fx[i_subfr/L_SUBFR] = 0; + move16(); + + interp_code_5over2_fx( &exc_fx[i_subfr], &bwe_exc_fx[i_subfr * HIBND_ACB_L_FAC], L_SUBFR ); + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[]. + * Update A(z) filters + *-----------------------------------------------------------------*/ + Syn_filt_s(1, p_Aq_fx, M, &exc_fx[i_subfr], &syn_fx[i_subfr], L_SUBFR, mem->mem_syn, 1 ); + + p_Aw_fx += (M+1); + p_Aq_fx += (M+1); + pt_pitch_fx++; + } + + /* SC-VBR */ + st_fx->prev_ppp_gain_pit_fx = gain_pit_fx; + move16(); + st_fx->prev_tilt_code_fx = mem->tilt_code; + move16(); + + return; +} diff --git a/lib_enc/encoder.c b/lib_enc/encoder.c new file mode 100644 index 0000000..5b47e3b --- /dev/null +++ b/lib_enc/encoder.c @@ -0,0 +1,282 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "options.h" +#include "stl.h" +#include "disclaimer.h" +#include "g192.h" +#include "stat_enc_fx.h" +#include "prot_fx.h" + +/*------------------------------------------------------------------------------------------* + * Global variables + *------------------------------------------------------------------------------------------*/ +long frame = 0; /* Counter of frames */ + +/*------------------------------------------------------------------------------------------* + * Local constants + *------------------------------------------------------------------------------------------*/ + + + + +int main( int argc, char** argv ) +{ + FILE *f_stream = NULL; /* output bitstream file */ + Indice_fx ind_list[MAX_NUM_INDICES]; /* list of indices */ + Encoder_State_fx *st_fx; /*Encoder state struct*/ + Word16 enc_delay; + FILE *f_input; /* input signal file */ + FILE *f_rate; /* bitrate switching profile file */ + FILE *f_bwidth; /* bandwidth switching profile file */ + FILE *f_rf = NULL; /* Channel aware configuration file */ + Word16 input_frame; + Word16 tmps; + Word16 n_samples; + Word16 data[L_FRAME48k]; /* Input buffer */ + Word32 bwidth_profile_cnt = 0; /* counter of frames for bandwidth switching profile file */ + Word16 quietMode = 0; + Word16 noDelayCmp = 0; + Word16 Opt_RF_ON_loc, rf_fec_offset_loc; + + + UWord8 pFrame[(MAX_BITS_PER_FRAME + 7) >> 3]; + Word16 pFrame_size = 0; + + + /* start WMOPS counting */ + BASOP_init + + /*Inits*/ + f_bwidth = f_rate = NULL; + + /*------------------------------------------------------------------------------------------* + * Allocate memory for static variables + * Processing of command-line parameters + * Encoder initialization + *------------------------------------------------------------------------------------------*/ + + if ( (st_fx = (Encoder_State_fx *) calloc( 1, sizeof(Encoder_State_fx) ) ) == NULL ) + { + fprintf(stderr, "Can not allocate memory for encoder state structure\n"); + exit(-1); + } + + io_ini_enc_fx( argc, argv, &f_input, &f_stream, &f_rate, &f_bwidth, + &f_rf, + &quietMode, &noDelayCmp, st_fx); + + /*input_frame = (short)(st->input_Fs / 50);*/ + st_fx->input_frame_fx = extract_l(Mult_32_16(st_fx->input_Fs_fx , 0x0290)); + input_frame = st_fx->input_frame_fx; + + Opt_RF_ON_loc = st_fx->Opt_RF_ON; + rf_fec_offset_loc = st_fx->rf_fec_offset; + + st_fx->ind_list_fx = ind_list; + init_encoder_fx( st_fx ); + + /*------------------------------------------------------------------------------------------* + * Compensate for encoder delay (bitstream aligned with input signal) + * Compensate for the rest of codec delay (local synthesis aligned with decoded signal and original signal) + *------------------------------------------------------------------------------------------*/ + + enc_delay = NS2SA(st_fx->input_Fs_fx, get_delay_fx(ENC, st_fx->input_Fs_fx)); + + if ( noDelayCmp == 0 ) + { + /* read samples and throw them away */ + if( (tmps = (Word16)fread(data, sizeof(short), enc_delay, f_input)) != enc_delay ) + { + } + + } + + /*------------------------------------------------------------------------------------------* + * Loop for every frame of input data + * - Read the input data + * - Select the best operating mode + * - Run the encoder + * - Write the parameters into output bitstream file + *------------------------------------------------------------------------------------------*/ + BASOP_end_noprint; + BASOP_init; + +#if (WMOPS) + Init_WMOPS_counter(); + Reset_WMOPS_counter(); + setFrameRate(48000, 960); +#endif + + + if (quietMode == 0) + { + fprintf( stdout, "\n------ Running the encoder ------\n\n" ); + fprintf( stdout, "Frames processed: " ); + } + else + { + fprintf( stdout, "\n-- Start the encoder (quiet mode) --\n\n" ); + } + + + /*Encode-a-frame loop start*/ + while( (n_samples = (short)fread(data, sizeof(short), input_frame, f_input)) > 0 ) + { +#if (WMOPS) + Reset_WMOPS_counter(); +#endif + SUB_WMOPS_INIT("enc"); + + IF(f_rf != NULL) + { + read_next_rfparam_fx( + &st_fx->rf_fec_offset, &st_fx->rf_fec_indicator, f_rf); + rf_fec_offset_loc = st_fx->rf_fec_offset; + } + + IF(f_rate != NULL) + { + /* read next bitrate from profile file (only if invoked on the cmd line) */ + read_next_brate_fx( &st_fx->total_brate_fx, st_fx->last_total_brate_fx, + f_rate, st_fx->input_Fs_fx, &st_fx->Opt_AMR_WB_fx, &st_fx->Opt_SC_VBR_fx, &st_fx->codec_mode ); + } + + IF (f_bwidth != NULL) + { + /* read next bandwidth from profile file (only if invoked on the cmd line) */ + read_next_bwidth_fx( &st_fx->max_bwidth_fx, f_bwidth, &bwidth_profile_cnt, st_fx->input_Fs_fx ); + } + + IF( ( st_fx->Opt_RF_ON && ( NE_32( st_fx->total_brate_fx, ACELP_13k20 )||EQ_32(st_fx->input_Fs_fx,8000)||st_fx->max_bwidth_fx==NB)) + || st_fx->rf_fec_offset == 0 ) + { + IF( EQ_32( st_fx->total_brate_fx, ACELP_13k20)) + { + st_fx->codec_mode = MODE1; + reset_rf_indices(st_fx); + } + st_fx->Opt_RF_ON = 0; + st_fx->rf_fec_offset = 0; + + } + + IF( Opt_RF_ON_loc && rf_fec_offset_loc != 0 && EQ_32( st_fx->total_brate_fx, ACELP_13k20 )&&NE_32(st_fx->input_Fs_fx,8000)&&st_fx->max_bwidth_fx!=NB) + { + st_fx->codec_mode = MODE2; + IF(st_fx->Opt_RF_ON == 0) + { + reset_rf_indices(st_fx); + } + st_fx->Opt_RF_ON = 1; + st_fx->rf_fec_offset = rf_fec_offset_loc; + } + + /* in case of 8kHz sampling rate or when in "max_band NB" mode, limit the total bitrate to 24.40 kbps */ + IF ( (EQ_32( st_fx->input_Fs_fx, 8000 )||(st_fx->max_bwidth_fx==NB))&>_32(st_fx->total_brate_fx,ACELP_24k40)) + { + st_fx->total_brate_fx = ACELP_24k40; + st_fx->codec_mode = MODE2; + } + + + /* run the main encoding routine */ + + + IF ( st_fx->Opt_AMR_WB_fx ) + { + SUB_WMOPS_INIT("amr_wb_enc"); + amr_wb_enc_fx( st_fx, data, n_samples); + END_SUB_WMOPS; + } + ELSE + { + SUB_WMOPS_INIT("evs_enc"); + /* EVS encoder*/ + evs_enc_fx( st_fx, data, n_samples); + END_SUB_WMOPS; + } + /* pack indices into serialized payload format */ + if( st_fx->bitstreamformat == MIME ) + { + indices_to_serial(st_fx, pFrame, &pFrame_size); + } + + /* write indices into bitstream file */ + write_indices_fx( st_fx, f_stream, pFrame, pFrame_size ); + + END_SUB_WMOPS; + /* update WMPOS counting (end of frame) */ + + + fflush(stderr); + + frame++; + if (quietMode == 0) + { + fprintf( stdout, "%-8ld\b\b\b\b\b\b\b\b", frame ); + } + +#if (WMOPS) + fwc(); +#endif + } + /* ----- Encode-a-frame loop end ----- */ + + + if (quietMode == 0) + { + fprintf( stdout, "\n\n" ); + fprintf(stderr, "Encoding finished\n\n"); + } + else + { + fprintf(stderr, "Encoding of %ld frames finished\n\n", frame); + } + + + + +#if (WMOPS) + fwc(); + printf("\nEncoder complexity\n"); + WMOPS_output(0); + printf("\n"); +#endif + + /* Close Encoder, Close files and free ressources */ + BASOP_init + + + IF(st_fx != NULL) + { + /* common delete function */ + destroy_encoder_fx( st_fx ); + free(st_fx); + } + + BASOP_end_noprint + + + IF(f_input) + fclose(f_input); + IF(f_stream) + fclose(f_stream); + IF(f_rate) + fclose(f_rate); + IF(f_bwidth) + fclose(f_bwidth); + + + return 0; +} diff --git a/lib_enc/energy.c b/lib_enc/energy.c new file mode 100644 index 0000000..c710e77 --- /dev/null +++ b/lib_enc/energy.c @@ -0,0 +1,457 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include + + +#include "basop_util.h" +#include "stl.h" +#include "rom_enc_fx.h" +#include "vad_basop.h" +#include "prot_fx.h" + +void est_energy( + Word32 enerBuffer[CLDFB_NO_CHANNELS_MAX], /* i: energy vector per band */ + Word16 enerBuffer_exp, /* i: exponent of energy vector */ + Word32 *frame_sb_energy, /*(o) energy of sub-band divided non-uniformly*/ + Word32 *frame_energy2_p, /*(o) frame energy 2*/ + Word32 *HB_Power_p, /*(o) high frequency energy*/ + Word32 *frame_energy_p, /*(o) frame energy 1*/ + Word16 *sb_power_Q, /*(o) the scaling of sb_power*/ + Word16 *frame_energy2_Q, /*(o) the scaling of frame_energy*/ + Word16 *HB_Power_Q, /*(o) the scaling of HB_Power*/ + Word16 *frame_energy_Q, /*(o) the Scaling of frame_energy*/ + Word16 *frame_sb_energy_scale, /*(o) the Scaling of frame_sb_energy[]*/ + Word32 bandwidth /*(i) band width*/ +) +{ + Word32 i,j; + Word32 frame_energy2,HB_Power,tmpspec_amp; + Word32 sb_power_tmp; + Word32 frame_energy,s32CopyPower; + Word32 SNR_sb_num; + Word16 shr_tmp; + Word32 BandNum; + Word16 widthsb,s16MaxCoefNorm; + const Word16 *Nregion_index; + Word32 *sb_power = enerBuffer; + Word32 Ltmp32 = 0; + + SNR_sb_num = SNR_SUB_BAND_NUM[bandwidth-CLDFBVAD_NB_ID]; + move16(); + Nregion_index = REGION_INDEX[bandwidth-CLDFBVAD_NB_ID]; + move16(); + + shr_tmp = BAND_SCALE_AJ[bandwidth]; + move16(); + BandNum = BAND_NUM_TAB[bandwidth]; + move16(); + + frame_energy2 = L_shr(sb_power[1], shr_tmp); + HB_Power = L_shr(sb_power[6], shr_tmp); + FOR(i = 2; i < BandNum; i++) + { + Ltmp32 = L_shr(sb_power[i],shr_tmp); + frame_energy2 = L_add(frame_energy2, Ltmp32 ); + if(i > 6) HB_Power = L_add(HB_Power, Ltmp32 ); + } + frame_energy2 = L_sub(frame_energy2, Ltmp32 ); + + sb_power_tmp = L_shr(sb_power[0],shr_tmp); + + IF(EQ_32(bandwidth,1)) + { + frame_energy = L_add(frame_energy2,MUL_F(sb_power_tmp,0x147a)); + } + ELSE IF(EQ_32(bandwidth,2)) + { + frame_energy = L_add(frame_energy2,MUL_F(sb_power_tmp,0x1eb8)); + } + ELSE IF(EQ_32(bandwidth,3)) + { + frame_energy = L_add(frame_energy2,MUL_F(sb_power_tmp,0x23d7)); + } + ELSE IF(EQ_32(bandwidth,4)) + { + frame_energy = L_add(frame_energy2,MUL_F(sb_power_tmp,0x23d7)); + } + ELSE + { + frame_energy = L_add(frame_energy2,MUL_F(sb_power_tmp,0x23d7)); + } + + *frame_energy2_p = frame_energy2; + move32(); + *HB_Power_p = HB_Power; + move32(); + *frame_energy_p = frame_energy; + move32(); + /* enerBuffer(float) = enerBuffer(fixed) * 2^(-(31-enerBuffer_exp)) */ + /* +30 is to keep original precision */ + *sb_power_Q = sub(31+30,enerBuffer_exp); + move16(); + *frame_energy2_Q = sub(*sb_power_Q,shr_tmp); + move16(); + *HB_Power_Q = sub(*sb_power_Q,shr_tmp); + move16(); + *frame_energy_Q = sub(*sb_power_Q,shr_tmp); + move16(); + + FOR(i=0; i<6; i++) + { + frame_sb_energy[i] = sb_power[i]; + move32(); + } + + FOR(i=6; if_tonality_rate; + Word16 *ltd_stable_rate = st->ltd_stable_rate; + Word32 bandwith = st->bw_index; + Word16 cmp_tmp; + T_VAD_EXP exp_frame_energy_amendment; + + move32(); + move16(); + move16(); + + + tmp = L_deposit_l(-1); + + CONST32fix.s16Exp = 44; + move16(); + CONST32fix.s32Mantissa = 1759218560; + move32(); + SNR_sb_num = SNR_SUB_BAND_NUM[bandwith - CLDFBVAD_NB_ID]; + move16(); + scale_sb_energy = st->sb_bg_energy_scale; + move16(); + + sb_bg_energy = st->sb_bg_energy; + move32(); + frame_sb_energy = st->frame_sb_energy; + move32(); + t_bg_energy = st->t_bg_energy; + move32(); + + t_bg_energy_sum = st->t_bg_energy_sum; + move32(); + normscal = norm_l(frame_energy); + exp_frame_energy.s16Exp = add(scale,normscal); + exp_frame_energy.s32Mantissa = L_shl(frame_energy,normscal); + exp_frame_energy = VAD_AddExp(exp_frame_energy,CONST32fix); + cmp_lt_frame = VAD_L_CMP(exp_frame_energy.s32Mantissa,exp_frame_energy.s16Exp,46,0); + + FOR(i=0; iframeloop, 60))&&(GT_16(st->frameloop,5))&&(LT_16(f_tonality_rate[0],9174/* 0.56 Q14 */)) + && (LT_16(f_tonality_rate[1],8192/* 0.5 Q14 */)) && (LT_16(ltd_stable_rate[1],1966/* 0.06 Q15 */)) + && LT_32(snr, 83886080) ) + { + IF( LT_16(st->frameloop, 50) ) + { + exp_frame_energy_amendment.s32Mantissa = VAD_L_div(exp_frame_energy.s32Mantissa, 10, exp_frame_energy.s16Exp, 0, &q_divout); + exp_frame_energy_amendment.s16Exp = q_divout; + t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy_amendment); + } + ELSE + { + t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy); + } + update_sb_bg_energy(sb_bg_energy, &st->tbg_energy_count, p_scale_sb_energy, SNR_sb_num, frame_sb_energy, st->frame_sb_energy_scale, + 29490/* 0.90 Q15 */, 3, 5242/* 0.01 Q19 */);//5243 + } + + test(); + test(); + IF((EQ_32(update_flag,1))&&(GT_16(st->frameloop,2))&&music_backgound_f==0) + { + IF(LT_16(st->bg_update_count, 16)) + { + IF( LT_16(st->frameloop, 50) ) + { + exp_frame_energy_amendment.s32Mantissa = VAD_L_div(exp_frame_energy.s32Mantissa, 10, exp_frame_energy.s16Exp, 0, &q_divout); + exp_frame_energy_amendment.s16Exp = q_divout; + t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy_amendment); + } + ELSE + { + t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy); + } + update_sb_bg_energy(sb_bg_energy, &st->tbg_energy_count, p_scale_sb_energy, SNR_sb_num, frame_sb_energy, st->frame_sb_energy_scale, + 31456/* 0.96 Q15 */, 4, 20971/* 0.04 Q19 */); + + st->bg_update_count = add(st->bg_update_count, 1); + } + ELSE + { + + cmp_lt_frame = VAD_L_CMP(t_bg_energy, st->scale_t_bg_energy, exp_frame_energy.s32Mantissa, exp_frame_energy.s16Exp); + cmp_pre_frame = VAD_L_CMP(MUL_F(st->frame_energy_smooth, 24576), sub(st->frame_energy_smooth_scale, 5), exp_frame_energy.s32Mantissa, exp_frame_energy.s16Exp); + cmp_tmp = VAD_L_CMP(MUL_F(t_bg_energy, 24576), sub(st->scale_t_bg_energy, 4), exp_frame_energy.s32Mantissa, exp_frame_energy.s16Exp); + + test(); + IF( (cmp_lt_frame < 0) && (cmp_pre_frame < 0) ) + { + tmpQ = add(9, st->frame_sb_energy_scale); + FOR(i=0; iframeloop, 50) ) + { + exp_frame_energy_amendment.s32Mantissa = VAD_L_div(exp_frame_energy.s32Mantissa, 10, exp_frame_energy.s16Exp, 0, &q_divout); + exp_frame_energy_amendment.s16Exp = q_divout; + t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy_amendment); + } + ELSE + { + t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy); + } + update_sb_bg_energy(sb_bg_energy, &st->tbg_energy_count, p_scale_sb_energy, SNR_sb_num, frame_sb_energy, st->frame_sb_energy_scale, + 31456/* 0.96 Q15 */, 4, 20971/* 0.04 Q19 */); + + } + ELSE + { + cmp_pre_frame = VAD_L_CMP(t_bg_energy, st->scale_t_bg_energy, exp_frame_energy.s32Mantissa, exp_frame_energy.s16Exp); + IF(cmp_pre_frame>0) + { + IF( LT_16(st->frameloop, 50) ) + { + exp_frame_energy_amendment.s32Mantissa = VAD_L_div(exp_frame_energy.s32Mantissa, 10, exp_frame_energy.s16Exp, 0, &q_divout); + exp_frame_energy_amendment.s16Exp = q_divout; + t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy_amendment); + } + ELSE + { + t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy); + } + update_sb_bg_energy(sb_bg_energy, &st->tbg_energy_count, p_scale_sb_energy, SNR_sb_num, frame_sb_energy, st->frame_sb_energy_scale, + 31129/* 0.95 Q15 */, 4, 26214/* 0.05 Q19 */); + + } + ELSE + { + IF( LT_16(st->frameloop, 50) ) + { + exp_frame_energy_amendment.s32Mantissa = VAD_L_div(exp_frame_energy.s32Mantissa, 10, exp_frame_energy.s16Exp, 0, &q_divout); + exp_frame_energy_amendment.s16Exp = q_divout; + t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy_amendment); + } + ELSE + { + t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy); + } + update_sb_bg_energy(sb_bg_energy, &st->tbg_energy_count, p_scale_sb_energy, SNR_sb_num, frame_sb_energy, st->frame_sb_energy_scale, + 31456/* 0.96 Q15 */, 4, 20971/* 0.04 Q19 */); + + } + } + } + } + ELSE + { + cmp_pre_frame = VAD_L_CMP(t_bg_energy, st->scale_t_bg_energy, MUL_F(exp_frame_energy.s32Mantissa, 32000), sub(exp_frame_energy.s16Exp, 9)); + cmp_lt_frame = VAD_L_CMP(sb_bg_energy[0], scale_sb_energy, MUL_F(frame_sb_energy[0], 20480), sub(st->frame_sb_energy_scale, 4)); + + test(); + IF( (cmp_pre_frame > 0) && (cmp_lt_frame > 0) ) + { + tmpQ = add(3, st->frame_sb_energy_scale); + FOR(i=0; iscale_t_bg_energy, MUL_F(exp_frame_energy.s32Mantissa, 20480), sub(exp_frame_energy.s16Exp, 4)); + IF( cmp_pre_frame > 0 ) + { + tmpQ = add(9, st->frame_sb_energy_scale); + FOR(i=0; itbg_energy_count); + cmp_pre_frame = VAD_L_CMP(t_bg_energy_sum.s32Mantissa, t_bg_energy_sum.s16Exp, tmp, 0); + IF(cmp_pre_frame > 0) + { + i = norm_l(tmp); + t_bg_energy_sum.s32Mantissa = L_shl(tmp, i); + t_bg_energy_sum.s16Exp = i; + move16(); + } + NormEnergyWord32(sb_bg_energy, SNR_sb_num, p_scale_sb_energy, &scale_sb_energy); + cmp_pre_frame = VAD_L_CMP(t_bg_energy, st->scale_t_bg_energy, 1, 0); + + test(); + test(); + test(); + IF( (EQ_16(music_backgound_f, 1))&&(LT_32(st->lt_snr_org,107374179/* 3.2 Q25 */)) + && (cmp_pre_frame > 0) && update_flag == 0) + { + tmp = L_shr(2147/* 0.000001 Q31 */, sub(31, scale_sb_energy)); + FOR(i=0; iscale_t_bg_energy, 15)); + IF(cmp_pre_frame < 0) + { + tmp = L_shr(2147/* 0.000001 Q31 */, sub(31, scale_sb_energy)); + FOR(i=0; itbg_energy_count, 64))) + { + st->tbg_energy_count = 48; + move16(); + t_bg_energy_sum.s32Mantissa = MUL_F(t_bg_energy_sum.s32Mantissa, 24575/* 0.75 Q15 */); + } + + t_bg_energy = VAD_L_div(t_bg_energy_sum.s32Mantissa, st->tbg_energy_count, t_bg_energy_sum.s16Exp, 0, &q_divout); + st->scale_t_bg_energy = q_divout; + move16(); + st->t_bg_energy = t_bg_energy; + move32(); + st->sb_bg_energy_scale = scale_sb_energy; + move16(); + st->t_bg_energy_sum = t_bg_energy_sum; + move16(); + move32(); + +} + diff --git a/lib_enc/eval_pit_contr_fx.c b/lib_enc/eval_pit_contr_fx.c new file mode 100644 index 0000000..48c9048 --- /dev/null +++ b/lib_enc/eval_pit_contr_fx.c @@ -0,0 +1,413 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * Local constantes + *-------------------------------------------------------------------*/ +#define NB_VOIC_FX 13 +#define DIV_NB_VOIC_FX 2521 + +#define ALPA_FX 31130 +#define ALPAM1_FX (32768-ALPA_FX) + +#define BETA_FX 819 +#define AFREQ_THR 2 + +#define HANGOVER_DELAY 2 + +/*======================================================================*/ +/* FUNCTION : Pit_exc_contribution_len_fx() */ +/*----------------------------------------------------------------------*/ +/* PURPOSE : Determine up to which band the pit contribution is significant*/ +/*----------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Struct) st_fx : encoder static memory */ +/* _ (Word16[]) dct_res : DCT of residual Qnew */ +/* _ (Word16[]) dct_pitex : DCT of pitch contribution Qnew */ +/* _ (Word16[]) pitch_buf : Pitch per subframe Q6 */ +/* _ (Word16[]) nb_subfr : Number of subframe considered */ +/* _ (Word16) hangover : hangover for the time contribution switching*/ +/* _ (Word16) Qnew : */ +/*-----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) dct_res : DCT of residual Qnew */ +/* _ (Word16[]) dct_pitex : DCT of pitch contribution Qnew */ +/*-----------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*=======================================================================*/ + +Word16 Pit_exc_contribution_len_fx( /* o : bin where pitch contribution is significant */ + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 *dct_res, /* i : DCT of residual */ + Word16 *dct_pitex, /* i/o: DCT of pitch contribution */ + Word16 *pitch_buf, /* i/o: Pitch per subframe */ + const Word16 nb_subfr, /* i : Number of subframe considered */ + Word16 *hangover, /* i : hangover for the time contribution switching */ + const Word16 coder_type, /* i : coding type */ + Word16 Qnew +) +{ + + Word16 corr_dct_pit[MBANDS_LOC]; + Word32 corr_tmp,L_tmp; + Word16 av_corr, min_corr, ftmp, tmp_ex, tmp_res; + Word16 freq, i, j; + Word16 last_pit_band, pit_contr_idx, last_pit_bin; + Word32 ener_res; + Word32 ener_pit; + Word16 low_pit, F1st_harm, F8th_harm; + Word16 corr_dct_pit_tmp[MBANDS_LOC]; + Word16 time_flg = 0; + Word16 Len, max_len; + Word16 tmp_dec; + Word16 Mbands_loc = MBANDS_LOC-2; + Word16 exp1,tmp,exp2; + Word32 L_tmp1, ener_init; + Word16 exp_norm; + Word16 norm; + Word16 val_thrs; + + if( EQ_16(st_fx->L_frame_fx,L_FRAME16k)) + { + Mbands_loc = MBANDS_LOC; + move16(); + } + + minimum_fx( pitch_buf, nb_subfr, &low_pit); + exp1 = norm_s(low_pit); + tmp = shl(low_pit,exp1); + { + /*F1st_harm = 12800.0f/low_pit;*/ + tmp = div_s(12800,tmp); /*15-6-exp1(->9-exp1)*/ + F1st_harm = shr_r(tmp,sub(5,exp1)); /*Q4*/ + } + + /*F8th_harm = 8.0f*F1st_harm;*/ + F8th_harm = extract_l(L_shr_r(L_mult0(F1st_harm,8),2)); /*Q2*/ + + freq = 0; + move16(); + ener_init = L_shl(3,2*Qnew-5); /*(0.1->3 in Q5) 2*Qnew*/ + FOR (i = 0; i core_brate_fx,ACELP_9k60)) + { + av_corr = shl(av_corr,1); /*Q2 Correlation really poor at low rate, time domain still valide*/ + } + min_corr = abs_s(sub(mfreq_loc_Q2fx[0],av_corr)); /*Q2*/ + + FOR (i = 1; i core_brate_fx,CFREQ_BITRATE)||EQ_16(st_fx->bwidth_fx,NB)))/*Added for 9.1*/ + { + last_pit_band = 7+BAND1k2; + move16(); + } + ELSE IF ( GT_16(last_pit_band,10+BAND1k2)&&GE_32(st_fx->core_brate_fx,CFREQ_BITRATE)) + { + last_pit_band = add(10,BAND1k2); + } + + time_flg = 0; + move16(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( (st_fx->mem_last_pit_band_fx > 0 && GT_16(st_fx->old_corr_fx,16384)&>_16(st_fx->mold_corr_fx,16384)&&GE_16(st_fx->lt_gpitch_fx,19661)/*1.5f*GPIT_THR*/) + || (GT_16(last_pit_band,6) ) + || (GE_16(last_pit_band,4) && GE_16(st_fx->lt_gpitch_fx,19661) /*1.5f*GPIT_THR*/ && GT_16(st_fx->old_corr_fx,22938) ) + || (GT_16(last_pit_band,BAND1k2) && GT_16(st_fx->mold_corr_fx,26214) && GE_16(st_fx->lt_gpitch_fx,13107) /*GPIT_THR*/) + ) + { + tmp_dec = 1; + move16(); + } + ELSE + { + tmp_dec = 0; + move16(); + } + + /* Different past and current decision */ + test(); + test(); + test(); + IF ( (st_fx->mem_last_pit_band_fx == 0 && EQ_16(tmp_dec,1))||(st_fx->mem_last_pit_band_fx>0&&tmp_dec==0)) + { + IF( *hangover == 0 ) + { + time_flg = tmp_dec; + move16(); + *hangover = HANGOVER_DELAY; + move16(); + } + ELSE + { + time_flg = 0; + move16(); + if( st_fx->mem_last_pit_band_fx > 0 ) + { + time_flg = 1; + move16(); + } + + (*hangover) = sub((*hangover),1); + if( *hangover < 0 ) + { + *hangover = 0; + move16(); + } + } + } + ELSE + { + time_flg = tmp_dec; + move16(); + *hangover = HANGOVER_DELAY; + move16(); + } + + /* Decicison on final lenght of time contribution */ + pit_contr_idx = 0; + move16(); + test(); + test(); + IF( EQ_16(time_flg,1)||NE_16(coder_type,INACTIVE)||st_fx->GSC_noisy_speech_fx) + { + test(); + test(); + /*if(st_fx->core_brate_fx core_brate_fx,ACELP_9k60)&<_16(low_pit,4096)) + { + last_pit_band = add(9 , BAND1k2); + if(EQ_16(st_fx->bwidth_fx,NB)) + { + last_pit_band = add(7,BAND1k2); + } + } + ELSE IF(LT_32(st_fx->core_brate_fx,ACELP_9k60)&<_16(low_pit,8192)) + { + last_pit_band = add(5 , BAND1k2); + } + ELSE IF(LT_32(st_fx->core_brate_fx,ACELP_9k60)) + { + last_pit_band = add(3 , BAND1k2); + } + ELSE IF( LT_16(last_pit_band,add(BAND1k2,1))) + { + last_pit_band = add(BAND1k2,1); + } + last_pit_bin = mfreq_loc_div_25[last_pit_band]; + move16(); + + st_fx->bpf_off_fx = 0; + move16(); + + max_len = sub(st_fx->L_frame_fx,last_pit_bin); + + if( EQ_16(st_fx->bwidth_fx,NB)) + { + max_len = sub(160,last_pit_bin); + } + + Len = 80; + move16(); + if(LT_16(max_len,80)) + { + Len = max_len; + move16(); + } + test(); + IF((EQ_32(st_fx->core_brate_fx,ACELP_8k00))&&(NE_16(st_fx->bwidth_fx,NB))) + { + move16(); /*ptr init*/ + FOR (i=0; i < max_len; i++) + { + dct_pitex[i+last_pit_bin] = 0; + move16(); + } + } + ELSE + { + + FOR (i = 0; i < Len; i++) + { + dct_pitex[i+last_pit_bin] = mult_r(dct_pitex[i+last_pit_bin],sm_table_fx[i]); + } + FOR (; i < max_len; i++) + { + dct_pitex[i+last_pit_bin] = 0; + move16(); + } + } + st_fx->mem_last_pit_band_fx = last_pit_band; + move16(); + pit_contr_idx = sub(last_pit_band,BAND1k2); + } + ELSE + { + set16_fx(dct_pitex, 0, st_fx->L_frame_fx); + st_fx->bpf_off_fx = 1; + move16(); + last_pit_bin = 0; + move16(); + last_pit_band = 0; + move16(); + pit_contr_idx = 0; + move16(); + st_fx->mem_last_pit_band_fx = 0; + move16(); + + { + set16_fx( pitch_buf, shl(L_SUBFR,6), NB_SUBFR ); + } + /* pitch contribution useless - delete all previously written indices belonging to pitch contribution */ + FOR ( i = TAG_ACELP_SUBFR_LOOP_START; i < TAG_ACELP_SUBFR_LOOP_END; i++ ) + { + IF ( st_fx->ind_list_fx[i].nb_bits != -1 ) + { + st_fx->nb_bits_tot_fx = sub(st_fx->nb_bits_tot_fx,st_fx->ind_list_fx[i].nb_bits); + st_fx->ind_list_fx[i].nb_bits = -1; + move16(); + } + } + + IF ( st_fx->ind_list_fx[IND_ES_PRED].nb_bits != -1 ) + { + st_fx->nb_bits_tot_fx = sub(st_fx->nb_bits_tot_fx,st_fx->ind_list_fx[IND_ES_PRED].nb_bits); + st_fx->ind_list_fx[IND_ES_PRED].nb_bits = -1; + move16(); + } + } + IF( LT_32(st_fx->core_brate_fx,CFREQ_BITRATE)) + { + IF(LT_32(st_fx->core_brate_fx,ACELP_9k60)) + { + if(pit_contr_idx>0) + { + pit_contr_idx=1; + move16(); + } + + IF( EQ_16(coder_type,INACTIVE)) + { + push_indice_fx( st_fx, IND_PIT_CONTR_IDX, pit_contr_idx, 1 ); + } + } + ELSE + { + push_indice_fx( st_fx, IND_PIT_CONTR_IDX, pit_contr_idx, 3 ); + } + } + ELSE + { + push_indice_fx( st_fx, IND_PIT_CONTR_IDX, pit_contr_idx, 4 ); + } + + return last_pit_bin; + +} diff --git a/lib_enc/evs_enc_fx.c b/lib_enc/evs_enc_fx.c new file mode 100644 index 0000000..a6b7016 --- /dev/null +++ b/lib_enc/evs_enc_fx.c @@ -0,0 +1,804 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" +#include "cnst_fx.h" /* Common constants */ +#include "stl.h" /* Debug prototypes */ +#include "rom_com_fx.h" /* Common constants */ + +static void initFrameHeader_loc( Encoder_State_fx *st ); +static void writeFrameHeader_loc( Encoder_State_fx *st ); +static void configure_core_coder_loc( Encoder_State_fx *st, Word16 *coder_type,const Word16 localVAD); + +/*-------------------------------------------------------------------* + * evs_enc() + * + * Principal encoder routine + *-------------------------------------------------------------------*/ + +void evs_enc_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 *data, /* i : input signal */ + const Word16 n_samples /* i : number of input samples */ +) +{ + Word16 i, input_frame, delay; + Word16 old_inp_12k8[L_INP_12k8], *inp = 0; /* buffer of input signal @ 12k8 */ + Word16 old_inp_16k[L_INP]; /* buffer of input signal @ 16kHz */ + Word16 sp_aud_decision1; /* 1st stage speech/music classification */ + Word16 sp_aud_decision2; /* 2nd stage speech/music classification */ + Word32 fr_bands[2*NB_BANDS]; /* energy in frequency bands */ + Word16 vad_flag; + Word16 localVAD; + Word16 Etot; /* total energy; correlation shift */ + Word32 ener; /* residual energy from Levinson-Durbin */ + Word16 pitch[3]; /* open-loop pitch values for quantization */ + Word16 voicing[3]; /* OL maximum normalized correlation */ + Word16 A[NB_SUBFR16k*(M+1)]; /* A(z) unquantized for subframes */ + Word16 Aw[NB_SUBFR16k*(M+1)]; /* weighted A(z) unquantized for subframes */ + Word16 epsP_h[M+1]; /* LP prediction errors */ + Word16 epsP_l[M+1]; /* LP prediction errors */ + Word32 epsP[M+1]; /* LP prediction errors */ + Word16 lsp_new[M]; /* LSPs at the end of the frame */ + Word16 lsp_mid[M]; /* ISPs in the middle of the frame */ + Word16 coder_type; /* coder type */ + Word16 sharpFlag; /* formant sharpening flag */ + Word16 vad_hover_flag; + Word16 hq_core_type; /* HQ core type (HQ, or LR-MDCT) */ + + Word16 attack_flag; /* flag signalling attack encoded by the AC mode (GSC) */ + Word16 new_inp_resamp16k[L_FRAME16k]; /* new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ + Word16 old_syn_12k8_16k[L_FRAME16k]; /* ACELP core synthesis at 12.8kHz or 16kHz to be used by the SWB BWE */ + Word16 shb_speech[L_FRAME16k]; + Word16 hb_speech[L_FRAME16k/4]; + Word16 new_swb_speech[L_FRAME48k]; + Word32 bwe_exc_extended[L_FRAME32k + NL_BUFF_OFFSET]; /* non-linear bandwidth extension buffer */ + Word16 voice_factors[NB_SUBFR16k]; + Word16 fb_exc[L_FRAME16k]; + Word16 Voicing_flag; + Word16 pitch_buf[NB_SUBFR16k]; + Word16 unbits; + + Word16 padBits; + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; /* real buffer */ + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; /* imag buffer */ + CLDFB_SCALE_FACTOR cldfbScale; + Word16 Q_new, shift, Q_synth; + Word16 Q_r[2]; + Word16 Q_shb_spch, Q_fb_exc; + Word32 L_tmp; + UWord16 lsb; + Word16 tmp; + + Q_shb_spch = 0; + move16(); /* to avoid compiler warnings */ + + + + + /*------------------------------------------------------------------* + * Initializiation + *-----------------------------------------------------------------*/ + + input_frame = st->input_frame_fx; + move16(); + st->core_fx = -1; + move16(); + st->extl_fx = -1; + move16(); + st->core_brate_fx = -1; + move32(); + st->input_bwidth_fx = st->last_input_bwidth_fx; + move16(); + st->bwidth_fx = st->last_bwidth_fx; + move16(); + hq_core_type = -1; + move16(); + unbits = 0; + move16(); + + st->bits_frame_core = 0; + move16(); /* For getting bit consumption in core coder */ + st->lp_cng_mode2 = 0; + move16(); + st->mdct_sw_enable = 0; + move16(); + st->mdct_sw = 0; + move16(); + shift = st->old_wsp_shift; + move16(); + st->rate_switching_reset = 0; + move16(); + + /*----------------------------------------------------------------* + * set input samples buffer + *----------------------------------------------------------------*/ + + /* get delay to synchronize ACELP and MDCT frame */ + delay = NS2SA_fx2(st->input_Fs_fx, DELAY_FIR_RESAMPL_NS); + + Copy( st->input - delay, st->old_input_signal_fx, input_frame+delay ); + + /*----------------------------------------------------------------* + * convert 'short' input data to 'float' + *----------------------------------------------------------------*/ + + Copy(data, st->input, input_frame); + IF( LT_16(n_samples,input_frame)) + { + set16_fx( st->input + n_samples, 0, sub(input_frame, n_samples) ); + } + + /*----------------------------------------------------------------* + * HP filtering + *----------------------------------------------------------------*/ + + hp20( st->input, 1, input_frame, st->mem_hp20_in_fx, st->input_Fs_fx ); + + /*----------------------------------------------------------------* + * Updates in case of AMR-WB IO mode -> EVS primary mode switching + *----------------------------------------------------------------*/ + + IF( EQ_16(st->last_core_fx, AMR_WB_CORE)) + { + updt_IO_switch_enc_fx( st, input_frame ); + set16_fx(st->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k); + cldfb_reset_memory( st->cldfbAna_Fx ); + cldfb_reset_memory( st->cldfbSyn_Fx ); + } + + /*---------------------------------------------------------------------* + * Pre-processing + *---------------------------------------------------------------------*/ + + pre_proc_fx( st, input_frame, st->input, old_inp_12k8, old_inp_16k, &inp, &sp_aud_decision1, + &sp_aud_decision2, fr_bands, &vad_flag, &localVAD, &Etot, &ener, pitch, voicing, + A, Aw, epsP_h, epsP_l, epsP, lsp_new, lsp_mid, &coder_type, &sharpFlag, &vad_hover_flag, + &attack_flag, new_inp_resamp16k, &Voicing_flag, realBuffer, imagBuffer, &cldfbScale, st->LPDmem.old_exc, + &hq_core_type, + &Q_new, &shift, Q_r ); + + st->sharpFlag = sharpFlag; + + IF (EQ_16(st->mdct_sw,MODE2)) + { + + Mpy_32_16_ss(st->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + st->bits_frame_nominal = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + + initFrameHeader_loc( st ); + writeFrameHeader_loc( st ); + + test(); + test(); + test(); + IF ((GT_32(st->total_brate_fx,ACELP_24k40)&<_32(st->total_brate_fx,HQ_96k))||(EQ_32(st->total_brate_fx,ACELP_24k40)&&GE_16(st->bwidth_fx,WB))) + { + st->L_frame_fx = L_FRAME16k; + move16(); + st->gamma = GAMMA16k; + move16(); + st->preemph_fac = PREEMPH_FAC_16k; + move16(); + + weight_a_subfr_fx( NB_SUBFR16k, A, Aw, GAMMA16k, M ); + test(); + IF (EQ_16(st->last_L_frame_fx,L_FRAME)&&st->ini_frame_fx!=0) + { + /* this is just an approximation, but it is sufficient */ + Copy( st->lsp_old1_fx, st->lspold_enc_fx, M ); + } + } + ELSE + { + st->L_frame_fx = L_FRAME; + move16(); + st->gamma = GAMMA1; + move16(); + st->preemph_fac = PREEMPH_FAC; + move16(); + } + + st->sr_core = L_mult0(50,st->L_frame_fx); + st->core_brate_fx = st->total_brate_fx; + move32(); + + st->igf = 0; + move16(); + hq_core_type = NORMAL_HQ_CORE; + move16(); + test(); + test(); + IF( (EQ_16(st->bwidth_fx,SWB)||EQ_16(st->bwidth_fx,WB))&&LE_32(st->total_brate_fx,LRMDCT_CROSSOVER_POINT)) + { + /* note that FB (bit-rate >= 24400bps) is always coded with NORMAL_HQ_CORE */ + hq_core_type = LOW_RATE_HQ_CORE; + move16(); + } + ELSE IF( EQ_16(st->bwidth_fx,NB)) + { + hq_core_type = LOW_RATE_HQ_CORE; + move16(); + } + } + + IF( EQ_16(st->codec_mode,MODE1)) + { + /*---------------------------------------------------------------------* + * Write signalling info into the bitstream + *---------------------------------------------------------------------*/ + + signalling_enc_fx( st, coder_type, sharpFlag ); + + /*---------------------------------------------------------------------* + * Preprocessing (preparing) for ACELP/HQ core switching + *---------------------------------------------------------------------*/ + + core_switching_pre_enc_fx( st,&(st->LPDmem), old_inp_12k8, old_inp_16k); + + /*---------------------------------------------------------------------* + * ACELP core encoding + *---------------------------------------------------------------------*/ + + IF( EQ_16(st->core_fx,ACELP_CORE)) + { + acelp_core_enc_fx( st, &(st->LPDmem), inp, vad_flag, ener, + pitch, voicing, A, Aw, epsP_h, epsP_l, lsp_new, lsp_mid, coder_type, sharpFlag, vad_hover_flag, + attack_flag, bwe_exc_extended, voice_factors, old_syn_12k8_16k, pitch_buf, &unbits, Q_new, shift ); + } + + /*---------------------------------------------------------------------* + * HQ core encoding + *---------------------------------------------------------------------*/ + + IF( EQ_16(st->core_fx,HQ_CORE)) + { + hq_core_enc_fx( st, st->input - delay, input_frame, hq_core_type, Voicing_flag); + } + + /*---------------------------------------------------------------------* + * Postprocessing for ACELP/HQ core switching + *---------------------------------------------------------------------*/ + core_switching_post_enc_fx( st, old_inp_12k8, old_inp_16k, pitch, voicing, + A, shift, Q_new, st->Q_syn2, &Q_synth ); + } + ELSE /* MODE2 */ + { + /*----------------------------------------------------------------* + * Configuration of core coder/SID + * Write Frame Header + *----------------------------------------------------------------*/ + + configure_core_coder_loc( st, &coder_type, localVAD ); + + IF (st->mdct_sw != MODE1) + { + writeFrameHeader_loc( st ); + } + + /*----------------------------------------------------------------* + * Core-Coder + *----------------------------------------------------------------*/ + + /* Call main encoding function */ + enc_acelp_tcx_main( old_inp_16k + L_INP_MEM, st, coder_type, pitch, voicing, Aw, lsp_new, lsp_mid, + st->hFdCngEnc_fx, bwe_exc_extended, voice_factors, pitch_buf, + vad_hover_flag, vad_flag, &Q_new, &shift ); + + /*---------------------------------------------------------------------* + * Postprocessing for codec switching + *---------------------------------------------------------------------*/ + /* TBE interface */ + test(); + IF ( st->igf != 0 && GT_32(st->core_brate_fx,SID_2k40)) + { + IF( EQ_16(st->core_fx,ACELP_CORE)) + { + SWITCH (st->bwidth_fx) + { + case WB: + st->extl_fx = WB_TBE; + move16(); + st->extl_brate_fx = WB_TBE_0k35; + move32(); + BREAK; + + case SWB: + st->extl_fx = SWB_TBE; + move16(); + st->extl_brate_fx = SWB_TBE_1k6; + move32(); + BREAK; + + case FB: + st->extl_fx = FB_TBE; + move16(); + st->extl_brate_fx = FB_TBE_1k8; + move32(); + BREAK; + } + } + ELSE + { + coder_type = -1; + move16(); + st->extl_fx = IGF_BWE; + move16(); + st->extl_brate_fx = 0; + move32(); + } + + st->core_brate_fx = L_sub(st->total_brate_fx, st->extl_brate_fx); + + IF( EQ_16(st->tec_tfa, 1)) + { + st->core_brate_fx = L_sub(st->core_brate_fx, BITS_TEC); + st->core_brate_fx = L_sub(st->core_brate_fx, BITS_TFA); + } + } + + /*----------------------------------------------------------------* + * Complete Bitstream Writing + *----------------------------------------------------------------*/ + + padBits = 0; + + test(); + test(); + IF( st->igf != 0 && EQ_16(st->core_fx,ACELP_CORE)&>_32(st->core_brate_fx,SID_2k40)) + { + /* padBits = ((st->bits_frame+7)/8)*8 - (st->nb_bits_tot + (st->rf_target_bits_write - ((st->Opt_RF_ON==1)?1:0) ) + get_tbe_bits(st->total_brate, st->bwidth, st->rf_mode )); */ + tmp = add(get_tbe_bits_fx(st->total_brate_fx, st->bwidth_fx, st->rf_mode), sub(st->rf_target_bits_write, st->rf_mode)); + padBits = sub(sub(shl(shr(add(st->bits_frame,7),3),3), st->nb_bits_tot_fx), tmp); + } + ELSE + { + /* padBits = ((st->bits_frame+7)/8)*8 - (st->nb_bits_tot + (st->rf_target_bits_write - ((st->Opt_RF_ON==1)?1:0) )); */ + tmp = sub(st->rf_target_bits_write, st->rf_mode); + padBits = sub(shl(shr(add(st->bits_frame,7),3),3), add(st->nb_bits_tot_fx, tmp)); + } + + FOR( i = 0; iinput_Fs_fx,16000 )&&(LT_16(st->bwidth_fx,SWB))) + { + /* Common pre-processing for WB TBE and WB BWE */ + wb_pre_proc_fx( st, new_inp_resamp16k, hb_speech ); + /* o: new_inp_resamp16k at Q = -1 */ + } + + IF ( EQ_16(st->extl_fx,WB_TBE)) + { + /* WB TBE encoder */ + wb_tbe_enc_fx( st, coder_type, hb_speech, bwe_exc_extended, Q_new, voice_factors, pitch_buf, voicing); + + IF( EQ_16(st->codec_mode,MODE2)) + { + tbe_write_bitstream_fx( st ); + } + } + ELSE IF ( EQ_16(st->extl_fx, WB_BWE)) + { + /* WB BWE encoder */ + wb_bwe_enc_fx( st, new_inp_resamp16k, coder_type ); + + } + + /*---------------------------------------------------------------------* + * SWB(FB) TBE encoding + * SWB BWE encoding + *---------------------------------------------------------------------*/ + test(); + IF (!st->Opt_SC_VBR_fx && GE_32(st->input_Fs_fx,32000)) + { + /* Common pre-processing for SWB(FB) TBE and SWB BWE */ + swb_pre_proc_fx(st, st->input, new_swb_speech, shb_speech, &Q_shb_spch, realBuffer, imagBuffer, &cldfbScale ); + } + ELSE IF( GE_32(st->input_Fs_fx,32000)) + { + set16_fx( st->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k ); + set16_fx( shb_speech, 0, L_FRAME16k ); + } + + /* SWB TBE encoder */ + test(); + test(); + test(); + test(); + test(); + test(); + IF ( EQ_16(st->extl_fx, SWB_TBE)||EQ_16(st->extl_fx,FB_TBE)||(st->igf!=0&&EQ_16(st->core_fx,ACELP_CORE)&&NE_16(st->extl_fx,WB_TBE))) + { + test(); + IF( NE_32(st->core_brate_fx,FRAME_NO_DATA)&&NE_32(st->core_brate_fx,SID_2k40)) + { + swb_tbe_enc_fx( st, coder_type, shb_speech, bwe_exc_extended, voice_factors, fb_exc, &Q_fb_exc, Q_new, Q_shb_spch, voicing, pitch_buf ); + + IF ( EQ_16(st->extl_fx,FB_TBE)) + { + /* FB TBE encoder */ + fb_tbe_enc_fx( st, st->input, fb_exc, Q_fb_exc ); + } + + IF( EQ_16(st->codec_mode,MODE2)) + { + IF( EQ_16(st->tec_tfa, 1)) + { + tecEnc_TBE_fx(&st->tecEnc.corrFlag, voicing, coder_type); + + IF( EQ_16(coder_type, INACTIVE)) + { + st->tec_flag = 0; + move16(); + st->tecEnc.corrFlag = 0; + move16(); + } + st->tfa_flag = tfaEnc_TBE_fx( st->tfa_enr, st->last_core_fx, voicing, pitch_buf, shl(Q_shb_spch, 1)); + set_TEC_TFA_code_fx( st->tecEnc.corrFlag, &st->tec_flag, &st->tfa_flag ); + } + ELSE + { + st->tec_flag = 0; + move16(); + st->tecEnc.corrFlag = 0; + move16(); + st->tfa_flag = 0; + move16(); + } + + tbe_write_bitstream_fx( st ); + } + } + } + ELSE IF ( EQ_16(st->extl_fx,SWB_BWE)||EQ_16(st->extl_fx,FB_BWE)) + { + /* SWB BWE encoder */ + swb_bwe_enc_fx( st, old_inp_12k8, old_inp_16k, old_syn_12k8_16k, new_swb_speech, shb_speech, coder_type, Q_shb_spch, sub(Q_new, 1) ); + } + ELSE IF( EQ_16(st->extl_fx,SWB_BWE_HIGHRATE)||EQ_16(st->extl_fx,FB_BWE_HIGHRATE)) + { + /* SWB HR BWE encoder */ + swb_bwe_enc_hr_fx(st, st->input - delay, st->Q_syn2, input_frame, coder_type, unbits ); + } + + /*---------------------------------------------------------------------* + * SWB DTX/CNG encoding + *---------------------------------------------------------------------*/ + + test(); + IF ( st->Opt_DTX_ON_fx && GE_16(input_frame,L_FRAME32k)) + { + swb_CNG_enc_fx( st, shb_speech, old_syn_12k8_16k ); + } + + /*---------------------------------------------------------------------* + * Channel-aware mode - write signaling information into the bit-stream + *---------------------------------------------------------------------*/ + + signalling_enc_rf( st ); + + /*---------------------------------------------------------------------* + * Updates - MODE1 + *---------------------------------------------------------------------*/ + + st->last_sr_core = st->sr_core; + move16(); + st->last_codec_mode = st->codec_mode; + move16(); + st->last_L_frame_fx = st->L_frame_fx; + move16(); + st->last_core_fx = st->core_fx; + move16(); + + st->last_total_brate_fx = st->total_brate_fx; + move32(); + st->last_core_brate_fx = st->core_brate_fx; + move32(); + st->last_extl_fx = st->extl_fx; + move16(); + st->last_input_bwidth_fx = st->input_bwidth_fx; + move16(); + st->last_bwidth_fx = st->bwidth_fx; + move16(); + st->Etot_last_fx = Etot; + move16(); + st->last_coder_type_raw_fx = st->coder_type_raw_fx; + move16(); + + st->prev_Q_new = Q_new; + + if( GT_32(st->core_brate_fx,SID_2k40)) + { + st->last_active_brate_fx = st->total_brate_fx; + move32(); + } + IF ( EQ_16(st->core_fx,HQ_CORE)) + { + /* in the HQ core, coder_type is not used so it could have been set to anything */ + st->prev_coder_type_fx = GENERIC; + } + ELSE + { + st->prev_coder_type_fx = coder_type; + } + + test(); + IF( GT_32(st->core_brate_fx,SID_2k40)&&EQ_16(st->first_CNG_fx,1)) + { + if( GE_16(st->act_cnt_fx,BUF_DEC_RATE)) + { + st->act_cnt_fx = 0; + move16(); + } + + st->act_cnt_fx = add(st->act_cnt_fx,1); + + test(); + if( EQ_16(st->act_cnt_fx,BUF_DEC_RATE)&&st->ho_hist_size_fx>0) + { + st->ho_hist_size_fx = sub(st->ho_hist_size_fx,1); + } + + st->act_cnt2_fx = add(st->act_cnt2_fx,1); + if( GE_16(st->act_cnt2_fx,MIN_ACT_CNG_UPD)) + { + st->act_cnt2_fx = MIN_ACT_CNG_UPD; + move16(); + } + } + + test(); + test(); + if ( LE_32(st->core_brate_fx,SID_2k40)&&st->first_CNG_fx==0&&EQ_16(st->cng_type_fx,LP_CNG)) + { + st->first_CNG_fx = 1; + move16(); + } + + /*-----------------------------------------------------------------* + * Increase the counter of initialization frames + * Limit the max number of init. frames + *-----------------------------------------------------------------*/ + + if( LT_16(st->ini_frame_fx,MAX_FRAME_COUNTER)) + { + st->ini_frame_fx = add(st->ini_frame_fx, 1); + } + + /* synchronisation of CNG seeds */ + test(); + IF( NE_32(st->core_brate_fx,FRAME_NO_DATA)&&NE_32(st->core_brate_fx,SID_2k40)) + { + Random( &(st->cng_seed_fx) ); + Random( &(st->cng_ener_seed_fx) ); + } + + + /*---------------------------------------------------------------------* + * Updates - MODE2 + *---------------------------------------------------------------------*/ + IF( EQ_16(st->mdct_sw,MODE2)) + { + st->codec_mode = MODE2; + move16(); + st->sr_core = getCoreSamplerateMode2( st->total_brate_fx, st->bwidth_fx, st->rf_mode); + Mpy_32_16_ss(st->sr_core, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + st->L_frame_fx = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + assert(st->L_frame_fx == st->sr_core / 50); + IF ( EQ_32(st->sr_core,12800)) + { + st->preemph_fac = PREEMPH_FAC; + move16(); + st->gamma = GAMMA1; + move16(); + } + ELSE + { + st->preemph_fac = PREEMPH_FAC_16k; + move16(); + st->gamma = GAMMA16k; + move16(); + } + st->igf = getIgfPresent(st->total_brate_fx, st->bwidth_fx, st->rf_mode); + } + + /* update FER clas */ + st->last_clas_fx = st->clas_fx; + + core_encode_update( st ); + if( EQ_16(st->mdct_sw,MODE1)) + { + st->codec_mode = MODE1; + move16(); + } + if( st->lp_cng_mode2 ) + { + st->codec_mode = MODE2; + move16(); + } + + IF (EQ_16(st->rf_mode,1)) + { + IF (EQ_16(st->rf_frame_type,RF_NELP)) + { + st->last_nelp_mode_fx = 1; + } + ELSE + { + st->last_nelp_mode_fx = 0; + } + } + + /* RF mode updates */ + st->rf_mode_last = st->rf_mode; + IF(EQ_16(st->Opt_RF_ON,1)) + { + st->L_frame_fx = L_FRAME; + st->rf_mode = 1; + } + + + + return; +} + + +/*-------------------------------------------------------------------* + * initFrameHeader() + * + * Initialize MODE2 frame header + *-------------------------------------------------------------------*/ +static void initFrameHeader_loc( Encoder_State_fx *st ) +{ + + Word16 n; + + IF( EQ_32(st->core_brate_fx, SID_2k40)) + { + /*Get size of frame*/ + st->bits_frame = FRAME_2_4; + move16(); + st->bits_frame_core = add(st->bits_frame_core, FRAME_2_4-4); /*1 bit for SID on/off + 3 bits for bandwith in case of SID.*/ + st->frame_size_index = 2; + move16(); + } + ELSE IF( EQ_32(st->core_brate_fx,FRAME_NO_DATA)) + { + st->bits_frame = FRAME_0; + move16(); + st->bits_frame_core = add(st->bits_frame_core,st->bits_frame); + st->frame_size_index = 0; + move16(); + } + ELSE + { + FOR( n=0; nbits_frame_nominal)) + { + st->frame_size_index = n; + move16(); + st->bits_frame = FrameSizeConfig[n].frame_bits; + move16(); + st->bits_frame_core = FrameSizeConfig[n].frame_net_bits; + move16(); + BREAK; + } + } + } + + return; +} + +/*-------------------------------------------------------------------* + * writeFrameHeader() + * + * Write MODE2 frame header + *-------------------------------------------------------------------*/ +static void writeFrameHeader_loc( Encoder_State_fx *st ) +{ + + IF( NE_32(st->core_brate_fx,FRAME_NO_DATA)) + { + /* SID flag at 2.4kbps */ + IF( EQ_32(st->core_brate_fx,SID_2k40)) + { + IF ( EQ_16(st->cng_type_fx,FD_CNG)) + { + /* write SID/CNG type flag */ + push_next_indice_fx( st, 1, 1 ); + + /* write bandwidth mode */ + push_next_indice_fx( st, st->bwidth_fx, 2 ); + + /* write L_frame */ + IF( EQ_16(st->L_frame_fx,L_FRAME)) + { + push_next_indice_fx( st, 0, 1 ); + } + ELSE + { + push_next_indice_fx( st, 1, 1 ); + } + } + } + ELSE /* active frames */ + { + IF(st->rf_mode == 0) + { + push_next_indice_fx( st, sub(st->bwidth_fx,FrameSizeConfig[st->frame_size_index].bandwidth_min), FrameSizeConfig[st->frame_size_index].bandwidth_bits); + } + } + + /* Write reserved bit */ + test(); + IF( FrameSizeConfig[st->frame_size_index].reserved_bits && st->rf_mode == 0) + { + push_next_indice_fx( st, 0, FrameSizeConfig[st->frame_size_index].reserved_bits ); + } + } + + return; +} + +/*------------------------------------------------------------------------* +* Configuration of core coder/SID +*------------------------------------------------------------------------*/ + +static void configure_core_coder_loc( + Encoder_State_fx *st, /* i/o: encoder state structure */ + Word16 *coder_type, /* i : coder type */ + const Word16 localVAD +) +{ + + initFrameHeader_loc( st ); + + test(); + IF( NE_32(st->core_brate_fx, SID_2k40)&&NE_32(st->core_brate_fx,FRAME_NO_DATA)) + { + if( st->tcxonly ) + { + *coder_type = GENERIC; + move16(); + } + + st->tcx_cfg.coder_type = *coder_type; + move16(); + + + test(); + test(); + if( !st->tcxonly && !localVAD && EQ_16(st->tcx_cfg.coder_type,GENERIC)) + { + st->tcx_cfg.coder_type = UNVOICED; + move16(); + } + } + + st->igf = getIgfPresent(st->total_brate_fx, st->bwidth_fx, st->rf_mode); + + test(); + if( NE_32(st->core_brate_fx,SID_2k40)&&NE_32(st->core_brate_fx,FRAME_NO_DATA)) + { + st->core_brate_fx = st->total_brate_fx; + move32(); + } + + return; +} diff --git a/lib_enc/ext_sig_ana.c b/lib_enc/ext_sig_ana.c new file mode 100644 index 0000000..86f252d --- /dev/null +++ b/lib_enc/ext_sig_ana.c @@ -0,0 +1,485 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "prot_fx.h" +#include "stl.h" +#include "basop_util.h" + + + +/*-------------------------------------------------------------- + * Main Functions + *--------------------------------------------------------------*/ + +void core_signal_analysis_high_bitrate( const Word16 *new_samples, /*i: 0Q15*/ + const Word16 T_op[3], /* i : open-loop pitch values for quantiz. */ + const Word16 voicing[3], /* i : open-loop pitch gains */ + const Word16 pitch[2], + Word16 Aw[NB_SUBFR16k*(M+1)],/* i : weighted A(z) unquant. for subframes*/ + Word16 lsp_new[], + Word16 lsp_mid[], + Encoder_State_fx *st, + Word16 pTnsSize[], + Word16 pTnsBits[], + Word16 param_core[], + Word16 *ltpBits, + Word16 L_frame, + Word16 L_frameTCX, + Word32 **spectrum, + Word16 *spectrum_e, + Word16 *Q_new, + Word16 *shift + ) +{ + const Word16 last_overlap = st->tcx_cfg.tcx_last_overlap_mode; + const Word16 curr_overlap = st->tcx_cfg.tcx_curr_overlap_mode; + Word16 i, frameno; + Word16 L_subframe; + Word16 left_overlap, right_overlap, folding_offset; + Word32 buf[N_MAX]; /* Buffer for TCX20/TCX10 windowing, power spectrum */ + Word16 A[M+1]; + Word16 mdstWin[N_MAX+L_MDCT_OVLP_MAX]; /* Buffer for MDST windowing */ + Word16 * pMdstWin; + Word16 lpc_left_overlap_mode, lpc_right_overlap_mode; + Word16 * tcx20Win = (Word16*)buf; + Word32 powerSpec[N_MAX]; + Word16 powerSpec_e; + Word32 interleaveBuf[N_TCX10_MAX]; + Word16 *tcx5Win = (Word16*)interleaveBuf; /* Buffer for TCX5 windowing and interleaving. */ + Word16 r_h[NB_DIV][M+1], r_l[NB_DIV][M+1]; + Word32 r[M+1], epsP[M+1]; + Word16 *lsp[2]; + Word8 tmp8; + Word16 alw_pitch_lag_12k8[2], alw_pitch_lag_12k8_wc; + Word16 alw_voicing[2], alw_voicing_wc; + Word16 nSubframes; + Word16 overlap_mode[3]; + Word16 transform_type[2]; + Word16 tcx10SizeFB; + Word16 tcx5SizeFB; + Word16 tcx10Size; + Word16 tmp, *tmpP16; + Word32 *tmpP32; + Word16 Q_exp; + + + (void)Aw; + (void)shift; + + left_overlap = -1; + move16(); + right_overlap = -1; + move16(); + + tcx10SizeFB = shl(st->tcx_cfg.tcx5SizeFB, 1); + tcx5SizeFB = st->tcx_cfg.tcx5SizeFB; + move16(); + tcx10Size = shl(st->tcx_cfg.tcx5Size, 1); + + /*--------------------------------------------------------------* + * Input Signal Processing: copy, HP filter, pre-emphasis + *---------------------------------------------------------------*/ + + /* Copy Samples */ + Copy(new_samples, st->new_speech_enc, L_frame ); + Scale_sig( st->new_speech_enc, L_frame, 1 ); + + /*--------------------------------------------------------------* + * TCX-LTP + *---------------------------------------------------------------*/ + + tmp8 = 0; + move16(); + if(GT_32(st->sr_core, 25600)) + { + tmp8 = 1; + move16(); + } + + tcx_ltp_encode( st->tcxltp, + st->tcxonly, + st->tcxMode, + L_frame, + L_SUBFR, + st->speech_enc+st->encoderLookahead_enc, + st->speech_ltp+st->encoderLookahead_enc, + st->speech_enc+st->encoderLookahead_enc, + T_op[1], + ¶m_core[1+NOISE_FILL_RANGES], + ltpBits, + &st->tcxltp_pitch_int, + &st->tcxltp_pitch_fr, + &st->tcxltp_gain, + &st->tcxltp_pitch_int_past, + &st->tcxltp_pitch_fr_past, + &st->tcxltp_gain_past, + &st->tcxltp_norm_corr_past, + st->last_core_fx, + st->pit_min, + st->pit_fr1, + st->pit_fr2, + st->pit_max, + st->pit_res_max, + &st->transientDetection, + tmp8, + NULL, + M + ); + + + Copy(st->speech_enc+st->encoderLookahead_enc, st->new_speech_enc_pe, L_frame); + + Preemph_scaled(st->new_speech_enc_pe, /* input: Q0, output: Q_new - 1 */ + Q_new, + &(st->mem_preemph_enc), + st->Q_max_enc, + st->preemph_fac, + 1, /* preemph_bits = output scaling */ + 0, + 2, + L_frame, + st->coder_type_raw_fx,1 + ); + + Q_exp = sub(*Q_new, st->prev_Q_new); + move16(); + + /* Rescale Memory */ + Scale_sig(st->old_inp_16k_fx, L_INP_MEM, sub(*Q_new,st->Q_old)); + IF (Q_exp != 0) + { + Scale_sig(st->buf_speech_enc_pe, st->encoderPastSamples_enc+st->encoderLookahead_enc, Q_exp); + Scale_sig(&(st->mem_wsp_enc), 1, Q_exp); + } + + IF (EQ_16(st->tcxMode,TCX_10)) + { + Copy( ¶m_core[1+NOISE_FILL_RANGES], ¶m_core[NPRM_DIV+1+NOISE_FILL_RANGES], LTPSIZE ); + } + + lsp[0] = lsp_new; + lsp[1] = lsp_mid; + + /*-------------------------------------------------------------------------* + * Decision matrix for the transform and overlap length + *--------------------------------------------------------------------------*/ + + alw_pitch_lag_12k8[0] = pitch[0]; + move16(); + alw_pitch_lag_12k8[1] = pitch[1]; + move16(); + alw_voicing[0] = voicing[0]; + move16(); + alw_voicing[1] = voicing[1]; + move16(); + alw_pitch_lag_12k8_wc = s_min(alw_pitch_lag_12k8[0], alw_pitch_lag_12k8[1]); + alw_voicing_wc = s_max(alw_voicing[0], alw_voicing[1]); + overlap_mode[0] = last_overlap; /* Overlap between the last and the current frame */ move16(); + + IF (EQ_16(st->tcxMode, TCX_20)) + { + nSubframes = 1; + move16(); + transform_type[0] = TCX_20; + move16(); + overlap_mode[1] = curr_overlap; /* Overlap between the current and the next frame */ move16(); + alw_pitch_lag_12k8[0] = alw_pitch_lag_12k8_wc; + move16(); + alw_voicing[0] = alw_voicing_wc; + move16(); + } + ELSE + { + nSubframes = 2; + move16(); + IF (EQ_16(curr_overlap, FULL_OVERLAP)) + { + transform_type[0] = TCX_5; + move16(); + transform_type[1] = TCX_10; + move16(); + + overlap_mode[1] = MIN_OVERLAP; /* Overlap between 2nd and 3rd sub-frame */ move16(); + if (EQ_16(last_overlap, HALF_OVERLAP)) + { + overlap_mode[1] = HALF_OVERLAP; + move16(); + } + } + ELSE IF (EQ_16(last_overlap, FULL_OVERLAP)) + { + transform_type[0] = TCX_10; + move16(); + transform_type[1] = TCX_5; + move16(); + + overlap_mode[1] = MIN_OVERLAP; /* Overlap between 1st and 2nd sub-frame */ move16(); + if (EQ_16(curr_overlap, HALF_OVERLAP)) + { + overlap_mode[1] = HALF_OVERLAP; + move16(); + } + } + ELSE + { + transform_type[0] = transform_type[1] = TCX_5; + move16(); + move16(); + + overlap_mode[1] = MIN_OVERLAP; /* Overlap between 2nd and 3rd sub-frame */ move16(); + test(); + if (EQ_16(last_overlap, HALF_OVERLAP)&&EQ_16(curr_overlap,HALF_OVERLAP)) + { + overlap_mode[1] = HALF_OVERLAP; + move16(); + } + } + overlap_mode[2] = curr_overlap; /* Overlap between the current and the next frame */ move16(); + } + IF (NE_16(transform_type[0], TCX_20)) + { + IGFEncResetTCX10BitCounter(&st->hIGFEnc); + } + /*-------------------------------------------------------------------------* + * Get MDCT output and TNS parameters. Apply TNS in the spectrum if needed + *--------------------------------------------------------------------------*/ + + FOR (frameno = 0; frameno < nSubframes; frameno++) + { + L_subframe = L_frameTCX; + move16(); + if (NE_16(nSubframes, 1))L_subframe=shr(L_frameTCX,1); + + lpc_left_overlap_mode = overlap_mode[frameno]; + move16(); + lpc_right_overlap_mode = overlap_mode[frameno+1]; + move16(); + if (EQ_16(lpc_left_overlap_mode, ALDO_WINDOW)) + { + lpc_left_overlap_mode = FULL_OVERLAP; + move16(); + } + if (EQ_16(lpc_right_overlap_mode, ALDO_WINDOW)) + { + lpc_right_overlap_mode = FULL_OVERLAP; + move16(); + } + + test(); + IF ((NE_16(transform_type[frameno], TCX_20))||(EQ_16(st->tcx_cfg.tcx_last_overlap_mode,TRANSITION_OVERLAP))) + { + /* Windowing of the 2xTCX5 subframes or 1xTCX10 or 1xTCX20 */ + WindowSignal(&st->tcx_cfg, + st->tcx_cfg.tcx_offsetFB, + overlap_mode[frameno], + overlap_mode[frameno+1], + &left_overlap, &right_overlap, + &st->speech_TCX[frameno*tcx10SizeFB], + &L_subframe, + tcx20Win + ,1 + ); + } + + IF (EQ_16(transform_type[frameno], TCX_5)) + { + folding_offset = shr(left_overlap, 1); + + /* Outter left folding */ + FOR (i = 0; i < folding_offset; i++) + { + tcx20Win[folding_offset+i] = sub(tcx20Win[folding_offset+i], tcx20Win[folding_offset-1-i]); + move16(); + } + /* Outter right folding */ + tmp = shr(right_overlap, 1); + FOR (i = 0; i < tmp; i++) + { + tcx20Win[L_subframe+folding_offset-1-i] = add(tcx20Win[L_subframe+folding_offset-1-i], tcx20Win[L_subframe+folding_offset+i]); + move16(); + } + /* 2xTCX5 */ + L_subframe = tcx5SizeFB; + move16(); + + tmpP16 = tcx20Win; + tmpP32 = spectrum[frameno]; + FOR (i = 0; i < 2; i++) + { + test(); + test(); + WindowSignal(&st->tcx_cfg, + folding_offset, + mac_r(-(1<<16), 3<<8, shl(i,7)), /* equivalent to: i == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP */ + mac_r(2<<16, -(3<<8), shl(i,7)), /* equivalent to: sub(i, 1) == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP */ + &left_overlap, &right_overlap, + tmpP16, + &L_subframe, + tcx5Win + ,1 + ); + spectrum_e[frameno] = 16; + move16(); + TCX_MDCT(tcx5Win, + tmpP32, + &spectrum_e[frameno], + left_overlap, + sub(L_subframe, shr(add(left_overlap, right_overlap), 1)), + right_overlap); + + tmpP16 += tcx5SizeFB; + tmpP32 += tcx5SizeFB; + } + } + ELSE /* transform_type[frameno] != TCX_5 */ + { + assert(transform_type[frameno] == TCX_10 || transform_type[frameno] == TCX_20); + + /* TCX20/TCX10 */ + spectrum_e[frameno] = 16; + move16(); + test(); + IF ((EQ_16(transform_type[frameno], TCX_20))&&(NE_16(st->tcx_cfg.tcx_last_overlap_mode,TRANSITION_OVERLAP))) + { + Word32 tmp_buf[L_FRAME_PLUS]; + Word16 Q, tmp1, tmp2; + + Q = 0; + move16(); + + wtda_fx(st->new_speech_TCX, + &Q, + tmp_buf, + NULL, + NULL, + overlap_mode[frameno], + overlap_mode[frameno+1], + L_frameTCX); + + WindowSignal(&st->tcx_cfg, + st->tcx_cfg.tcx_offsetFB, + lpc_left_overlap_mode, + lpc_right_overlap_mode, + &left_overlap, &right_overlap, + &st->speech_TCX[frameno*tcx10SizeFB], + &L_subframe, + mdstWin + ,1 + ); + + /* scale by NORM_MDCT_FACTOR / L */ + tmp1 = mult_r(shl(L_subframe, 4), 26214/*128.f / NORM_MDCT_FACTOR Q15*/); /* 4Q11 */ + tmp2 = 4; + move16(); + tmp1 = ISqrt16(tmp1, &tmp2); + + FOR (i = 0; i < L_subframe; i++) + { + tmp_buf[i] = Mpy_32_16_1(tmp_buf[i], tmp1); + move32(); + } + Q = sub(Q, tmp2); + + /* DCT */ + edct_fx(tmp_buf, spectrum[frameno], L_subframe, &Q); + *spectrum_e = sub(31, Q); + } + ELSE + { + TCX_MDCT(tcx20Win, + spectrum[frameno], + &spectrum_e[frameno], + left_overlap, + sub(L_subframe, shr(add(left_overlap, right_overlap), 1)), + right_overlap); + } + + /* For TCX20 at bitrates up to 64 kbps we need the power spectrum */ + test(); + test(); + IF (EQ_16(st->tcxMode, TCX_20)&&((LT_32(st->total_brate_fx,HQ_96k))||st->igf)) + { + + pMdstWin = tcx20Win; + test(); + if (((EQ_16(st->tcxMode, TCX_20))&&(NE_16(st->tcx_cfg.tcx_last_overlap_mode,TRANSITION_OVERLAP)))) + { + pMdstWin = mdstWin; + } + + /* Compute noise-measure flags for spectrum filling and quantization */ + AnalyzePowerSpectrum(st, + div_l(L_mult(L_subframe, st->L_frame_fx), st->L_frameTCX), + L_subframe, + left_overlap, right_overlap, + spectrum[frameno], spectrum_e[frameno], + pMdstWin, + powerSpec, &powerSpec_e); + } + } + + test(); + test(); + TNSAnalysis(&st->tcx_cfg, L_frameTCX, + st->tcx_cfg.tcx_coded_lines, + transform_type[frameno], (frameno == 0) && (st->last_core_fx == ACELP_CORE), + spectrum[frameno], &st->tnsData[frameno], &st->fUseTns[frameno], NULL + ); + + EncodeTnsData(st->tcx_cfg.pCurrentTnsConfig, &st->tnsData[frameno], + param_core+frameno*NPRM_DIV+1+NOISE_FILL_RANGES+LTPSIZE, pTnsSize+frameno, pTnsBits+frameno); + + IF (EQ_16(transform_type[frameno], TCX_5)) + { + /* group sub-windows: interleave bins according to their frequencies */ + FOR (i = 0; i < tcx5SizeFB; i++) + { + interleaveBuf[2*i] = spectrum[frameno][i]; + move32(); + interleaveBuf[2*i+1] = spectrum[frameno][tcx5SizeFB+i]; + move32(); + } + Copy32(interleaveBuf, spectrum[frameno], tcx10SizeFB); + } + + /*--------------------------------------------------------------* + * LPC analysis + *---------------------------------------------------------------*/ + + + HBAutocorrelation(&st->tcx_cfg, + lpc_left_overlap_mode, + lpc_right_overlap_mode, + &st->speech_enc_pe[frameno*tcx10Size], + shr(L_frame, sub(nSubframes, 1)), + r, + M); + + FOR (i=0; i <= M; i++) + { + move16(); + move16(); + r_l[frameno][i] = L_Extract_lc(r[i], &r_h[frameno][i]); + } + + adapt_lag_wind( r_h[frameno], r_l[frameno], M, alw_pitch_lag_12k8[frameno], alw_voicing[frameno], st->sr_core ); + + E_LPC_lev_dur(r_h[frameno], r_l[frameno], A, epsP, M, NULL); + + E_LPC_a_lsp_conversion(A, lsp[nSubframes-1-frameno], st->lspold_enc_fx, M ); + + IF (st->igf) + { + ProcessIGF(&st->hIGFEnc, st, spectrum[frameno], &(spectrum_e[frameno]), powerSpec, &powerSpec_e, transform_type[frameno] == TCX_20, st->fUseTns[frameno], (st->last_core_fx == ACELP_CORE), frameno); + } + } + + /* Copy memory */ + mvr2r_Word16(lsp_new, st->lspold_enc_fx, M); + + +} + diff --git a/lib_enc/fd_cng_enc.c b/lib_enc/fd_cng_enc.c new file mode 100644 index 0000000..6264bef --- /dev/null +++ b/lib_enc/fd_cng_enc.c @@ -0,0 +1,1500 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include "stl.h" +#include "options.h" +#include "stl.h" +#include "rom_com_fx.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "rom_basop_util.h" + + +/******************************** +* External functions * +********************************/ + +#define swap(x,y,type) {type u__p; u__p=x; x=y; y=u__p;} + + +/************************************* +* Create an instance of type FD_CNG * +*************************************/ +void createFdCngEnc(HANDLE_FD_CNG_ENC* hFdCngEnc) +{ + HANDLE_FD_CNG_ENC hs; + + /* Allocate memory */ + hs = (HANDLE_FD_CNG_ENC) calloc(1, sizeof (FD_CNG_ENC)); + move16(); + + + createFdCngCom(&(hs->hFdCngCom)); + *hFdCngEnc = hs; + move16(); + + return; +} + +void initFdCngEnc(HANDLE_FD_CNG_ENC hsEnc, Word32 input_Fs, Word16 scale) +{ + Word16 j; + HANDLE_FD_CNG_COM hsCom = hsEnc->hFdCngCom; + + /* Initialize common */ + + initFdCngCom( hsCom, scale ); + + /* Configure the Noise Estimator */ + + hsCom->numSlots = 16; + move16(); + hsCom->numCoreBands = 16; + move16(); + hsCom->regularStopBand = idiv1616U( extract_l( L_shr( input_Fs, 5 ) ), 25 ); + if ( GT_16( hsCom->regularStopBand, 40 )) + { + hsCom->regularStopBand = 40; + move16(); + } + + hsCom->startBand = 2; + move16(); + IF ( EQ_16( hsCom->regularStopBand, 10 )) + { + hsCom->stopFFTbin = 160; + move16(); + hsCom->stopBand = 160; + move16(); + hsCom->nFFTpart = 17; + move16(); + } + ELSE + { + hsCom->stopFFTbin = 256; + move16(); + hsCom->stopBand = add( sub( hsCom->regularStopBand, hsCom->numCoreBands ), hsCom->stopFFTbin ); + hsCom->nFFTpart = 20; + move16(); + } + + initPartitions( sidparts_encoder_noise_est, 24, hsCom->startBand, hsCom->stopBand, hsCom->part, &hsCom->npart, hsCom->midband, hsCom->psize, hsCom->psize_norm, &hsCom->psize_norm_exp, hsCom->psize_inv, 0); + + hsCom->nCLDFBpart = sub( hsCom->npart, hsCom->nFFTpart ); + FOR(j=0; jnCLDFBpart; j++) + { + hsCom->CLDFBpart[j] = sub( hsCom->part[j+hsCom->nFFTpart], sub( 256, hsCom->startBand ) ); + hsCom->CLDFBpsize_inv[j] = hsCom->psize_inv[j+hsCom->nFFTpart]; + } + + /* Initialize noise estimation algorithm */ + set32_fx( hsEnc->msPeriodog, 0, NPART ); + hsEnc->msPeriodog_exp_fft = 0; + move16(); + hsEnc->msPeriodog_exp_cldfb = 0; + move16(); + set32_fx( hsEnc->msAlpha, 0, NPART ); + set32_fx( hsEnc->msBminWin, 0, NPART ); + set32_fx( hsEnc->msBminSubWin, 0, NPART ); + + set32_fx( hsEnc->msNoiseEst, 0, NPART ); + hsEnc->msNoiseEst_exp = 0; + move16(); + set32_fx( hsEnc->energy_ho, 0, NPART ); + set32_fx( hsEnc->msNoiseEst_old, 0, NPART ); + + set16_fx( hsEnc->msLogPeriodog, 0, NPART ); + set16_fx( hsEnc->msLogNoiseEst, 0, NPART ); + set16_fx( hsEnc->msPsd, 0, NPART ); + set16_fx( hsEnc->msNoiseFloor, 0, NPART ); + set32_fx( hsEnc->msMinBuf, 2147483647l/*1.0 Q31*/, MSNUMSUBFR*NPART ); + set32_fx( hsEnc->msCurrentMin, 2147483647l/*1.0 Q31*/, NPART ); + set32_fx( hsEnc->msCurrentMinOut, 2147483647l/*1.0 Q31*/, NPART ); + set32_fx( hsEnc->msCurrentMinSubWindow, 2147483647l/*1.0 Q31*/, NPART ); + set16_fx( hsEnc->msPsdFirstMoment, 0, NPART ); + set16_fx( hsEnc->msPeriodogBuf, 0, MSBUFLEN*NPART ); + + set16_fx( hsEnc->msLocalMinFlag, 0, NPART ); + set16_fx( hsEnc->msNewMinFlag, 0, NPART ); + hsEnc->msPeriodogBufPtr = 0; + move16(); + set32_fx( hsEnc->msPsdSecondMoment, 0, NPART ); + + + return; +} + +/************************************ +* Configure FD_CNG * +************************************/ +void configureFdCngEnc(HANDLE_FD_CNG_ENC hsEnc, /* i/o: Contains the variables related to the FD-based CNG process */ + Word16 bandwidth, /* i: bandwidth */ + Word32 bitrate + ) +{ + HANDLE_FD_CNG_COM hsCom = hsEnc->hFdCngCom; + Word16 psizeDec[NPART]; + Word16 psizeDec_norm[NPART]; + Word16 psizeDec_norm_exp; + Word16 psize_invDec[NPART]; + + set16_fx(psizeDec, 0, NPART); + + hsCom->CngBandwidth = bandwidth; + move16(); + IF ( EQ_16( hsCom->CngBandwidth, FB )) + { + hsCom->CngBandwidth = SWB; + } + hsCom->CngBitrate = bitrate; + move32(); + + /* NB configuration */ + IF ( EQ_16(bandwidth,NB)) + { + hsCom->FdCngSetup = FdCngSetup_nb; /* PTR assignation -> no move needed*/ + } + + /* WB configuration */ + ELSE IF ( EQ_16(bandwidth,WB)) + { + /* FFT 6.4kHz, no CLDFB */ + IF ( LE_32(bitrate,ACELP_8k00)) + { + hsCom->FdCngSetup = FdCngSetup_wb1; + } + /* FFT 6.4kHz, CLDFB 8.0kHz */ + ELSE IF ( LE_32(bitrate,ACELP_13k20)) + { + hsCom->FdCngSetup = FdCngSetup_wb2; + } + /* FFT 8.0kHz, no CLDFB */ + ELSE + { + hsCom->FdCngSetup = FdCngSetup_wb3; + } + } + + /* SWB/FB configuration */ + ELSE + { + /* FFT 6.4kHz, CLDFB 14kHz */ + IF ( LE_32(bitrate,ACELP_13k20)) + { + hsCom->FdCngSetup = FdCngSetup_swb1; + } + /* FFT 8.0kHz, CLDFB 16kHz */ + ELSE + { + hsCom->FdCngSetup = FdCngSetup_swb2; + } + } + hsCom->fftlen = hsCom->FdCngSetup.fftlen; + move16(); + hsEnc->stopFFTbinDec = hsCom->FdCngSetup.stopFFTbin; + move16(); + + /* Configure the SID quantizer and the Confort Noise Generator */ + + hsEnc->startBandDec = hsCom->startBand; + move16(); + hsEnc->stopBandDec = add( hsCom->FdCngSetup.sidPartitions[hsCom->FdCngSetup.numPartitions-1], 1 ); + move16(); + initPartitions( hsCom->FdCngSetup.sidPartitions, + hsCom->FdCngSetup.numPartitions, + hsEnc->startBandDec, + hsEnc->stopBandDec, + hsEnc->partDec, + &hsEnc->npartDec, + hsEnc->midbandDec, + psizeDec, + psizeDec_norm, + &psizeDec_norm_exp, + psize_invDec, + 0 + ); + IF ( EQ_16(hsEnc->stopFFTbinDec,160)) + { + hsEnc->nFFTpartDec = 17; + move16(); + } + ELSE IF ( EQ_16(hsEnc->stopFFTbinDec,256)) + { + hsEnc->nFFTpartDec = 20; + move16(); + } + ELSE + { + hsEnc->nFFTpartDec = 21; + move16(); + } + + SWITCH (hsCom->fftlen) + { + case 512: + hsCom->fftlenShift = 8; + move16(); + hsCom->fftlenFac = 32767/*1.0 Q15*/; + move16(); + BREAK; + case 640: + hsCom->fftlenShift = 9; + move16(); + hsCom->fftlenFac = 20480/*0.625 Q15*/; + move16(); + BREAK; + default: + assert(!"Unsupported FFT length for FD-based CNG"); + BREAK; + } + BASOP_getTables( &hsCom->olapWinAna, NULL, NULL, shr(hsCom->fftlen, 1)); + BASOP_getTables( &hsCom->olapWinSyn, NULL, NULL, shr(hsCom->fftlen, 2)); + hsCom->frameSize = shr( hsCom->fftlen, 1 ); + +} + +/************************************** +* Delete the instance of type FD_CNG * +**************************************/ +void deleteFdCngEnc(HANDLE_FD_CNG_ENC * hFdCngEnc) +{ + + HANDLE_FD_CNG_ENC hsEnc; + hsEnc = *hFdCngEnc; + move16(); + IF (hsEnc != NULL) + { + deleteFdCngCom(&(hsEnc->hFdCngCom)); + free(hsEnc); + *hFdCngEnc = NULL; + move16(); + } +} + + +void resetFdCngEnc( + Encoder_State_fx * st +) +{ + Word16 tmpTest; + Word16 n; + Word16 totalNoiseIncrease; + Word16 thresh = 5 * 256; /* 5.0 in Q8 */ + + /* st->totalNoise_fx; Q8 Noise estimator - total noise energy */ + + /* Detect fast increase of totalNoise */ + totalNoiseIncrease = sub(st->totalNoise_fx, st->last_totalNoise_fx); + st->last_totalNoise_fx = st->totalNoise_fx; + move16(); + IF ( totalNoiseIncrease > 0 ) + { + IF ( EQ_16(st->totalNoise_increase_len_fx,TOTALNOISE_HIST_SIZE)) + { + FOR ( n = 0; n < TOTALNOISE_HIST_SIZE-1; n++ ) + { + st->totalNoise_increase_hist_fx[n] = st->totalNoise_increase_hist_fx[n+1]; + move16(); + } + st->totalNoise_increase_hist_fx[TOTALNOISE_HIST_SIZE-1] = totalNoiseIncrease; + move16(); + } + ELSE + { + st->totalNoise_increase_hist_fx[st->totalNoise_increase_len_fx] = totalNoiseIncrease; + move16(); + st->totalNoise_increase_len_fx = add(st->totalNoise_increase_len_fx, 1); + } + } + ELSE + { + st->totalNoise_increase_len_fx = 0; + move16(); + } + totalNoiseIncrease = 0; + move16(); + FOR ( n = 0; n < st->totalNoise_increase_len_fx; n++ ) + { + totalNoiseIncrease = add(totalNoiseIncrease, st->totalNoise_increase_hist_fx[n]); + } + + test(); + test(); + tmpTest = ((GT_16 (totalNoiseIncrease,thresh) ) && (EQ_16(st->totalNoise_increase_len_fx,TOTALNOISE_HIST_SIZE)) && (GT_16(st->ini_frame_fx,150)) ); + + test(); + IF ( tmpTest || ( GT_16(st->input_bwidth_fx,st->last_input_bwidth_fx) ) || EQ_16(st->last_core_fx,AMR_WB_CORE)) + { + st->fd_cng_reset_flag = 1; + move16(); + st->hFdCngEnc_fx->hFdCngCom->msFrCnt_init_counter = 0; + move16(); + st->hFdCngEnc_fx->hFdCngCom->init_old = 32767; + move16(); + } + ELSE IF ( s_and((st->fd_cng_reset_flag > 0),(Word16)(LT_16(st->fd_cng_reset_flag,10)))) + { + st->fd_cng_reset_flag = add(st->fd_cng_reset_flag,1); + } + ELSE + { + st->fd_cng_reset_flag = 0; + move16(); + } +} + +/* + perform_noise_estimation_enc + + Parameters: + + band_energies i: energy in critical bands without minimum noise floor MODE2_E_MIN + band_energies_exp i: exponent for energy in critical bands without minimum noise floor MODE2_E_MIN + cldfbBufferReal, i: real part of the CLDFB buffer + cldfbBufferImag, i: imaginary part of the CLDFB buffer + cldfbBufferExp, i: exponent for CLDFB buffer + bitrate i: bitrate + st i/o: FD_CNG structure containing all buffers and variables + + Function: + Perform noise estimation + + Returns: + void +*/ +void perform_noise_estimation_enc (Word32 *band_energies, /* i: energy in critical bands without minimum noise floor MODE2_E_MIN */ + Word16 band_energies_exp, /* i: exponent for energy in critical bands without minimum noise floor MODE2_E_MIN */ + Word32 *enerBuffer, + Word16 enerBuffer_exp, + HANDLE_FD_CNG_ENC st /* i/o: FD_CNG structure containing all buffers and variables */ + ) +{ + Word16 i, j, s, s1, s2; + Word16 nFFTpart; + Word16 nCLDFBpart; + Word16 numBands; + Word16 numCoreBands; + Word16 regularStopBand; + Word16 numSlots; + Word32 tmp; + Word32 *periodog; + Word32 *ptr_per; + Word32 *msPeriodog; + + + + nFFTpart = st->hFdCngCom->nFFTpart; + move16(); + nCLDFBpart = st->hFdCngCom->nCLDFBpart; + move16(); + numCoreBands = st->hFdCngCom->numCoreBands; + move16(); + regularStopBand = st->hFdCngCom->regularStopBand; + move16(); + numSlots = st->hFdCngCom->numSlots; + move16(); + periodog = st->hFdCngCom->periodog; + move16(); + ptr_per = periodog; + move16(); + msPeriodog = st->msPeriodog; + move16(); + + assert(numSlots == 16); + + /* preemphasis compensation and grouping of per bin energies into msPeriodog */ + FOR (i=0; i < nFFTpart; i++) + { + tmp = L_add(L_shr(band_energies[i], 1), L_shr(band_energies[i+NB_BANDS], 1)); + msPeriodog[i] = Mpy_32_16_1(tmp, preemphCompensation[i]); + move32(); + } + + /* exponent for fft part of msPeriodog */ + st->msPeriodog_exp_fft = add(band_energies_exp, PREEMPH_COMPENSATION_EXP); + move16(); + + numBands = sub(regularStopBand, numCoreBands); + + IF ( numBands > 0 ) + { + /* Adjust to the desired time resolution by averaging the periodograms over the CLDFB time slots */ + + FOR (j=numCoreBands; j < regularStopBand; j++) + { + *ptr_per = Mpy_32_16_1(enerBuffer[j], st->hFdCngCom->scalingFactor); + move32(); + + ptr_per++; + } + + /* exponent for cldfb part of msPeriodog */ + st->hFdCngCom->exp_cldfb_periodog = add( sub(enerBuffer_exp, 4), CLDFBscalingFactor_EXP ); + + /* Adjust CLDFB filterbank to the desired frequency resolution by averaging over spectral partitions for SID transmission */ + bandcombinepow ( + periodog, + st->hFdCngCom->exp_cldfb_periodog, + numBands, + st->hFdCngCom->CLDFBpart, + st->hFdCngCom->nCLDFBpart, + st->hFdCngCom->CLDFBpsize_inv, + &msPeriodog[nFFTpart], + &st->msPeriodog_exp_cldfb + ); + + /* find common exponent for fft part and cldfb part of msperiodog */ + s1 = getScaleFactor32 (msPeriodog,nFFTpart); + s2 = getScaleFactor32 (&msPeriodog[nFFTpart],nCLDFBpart); + + s = s_max(sub(st->msPeriodog_exp_fft,s1), sub(st->msPeriodog_exp_cldfb,s2)); + s1 = sub(s,st->msPeriodog_exp_fft); + s2 = sub(s,st->msPeriodog_exp_cldfb); + + st->msPeriodog_exp_fft = s; + move16(); + st->msPeriodog_exp_cldfb = s; + move16(); + + FOR (i=0; i < nFFTpart; i++) + { + msPeriodog[i] = L_shr(msPeriodog[i],s1); + move32(); + } + + FOR (i=0; i < nCLDFBpart; i++) + { + msPeriodog[nFFTpart+i] = L_shr(msPeriodog[nFFTpart+i],s_min(31,s2)); + move32(); + } + } + + /* exponent for entire msPeriodog vector */ + st->msPeriodog_exp = st->msPeriodog_exp_fft; + move16(); + + /* Compress MS inputs */ + compress_range(st->msPeriodog, st->msPeriodog_exp, st->msLogPeriodog, st->hFdCngCom->npart); + + /* Call the minimum statistics routine for noise estimation */ + minimum_statistics ( + st->hFdCngCom->npart, + st->hFdCngCom->nFFTpart, + st->hFdCngCom->psize_norm, + st->msLogPeriodog, + st->msNoiseFloor, + st->msLogNoiseEst, + st->msAlpha, + st->msPsd, + st->msPsdFirstMoment, + st->msPsdSecondMoment, + st->msMinBuf, + st->msBminWin, + st->msBminSubWin, + st->msCurrentMin, + st->msCurrentMinOut, + st->msCurrentMinSubWindow, + st->msLocalMinFlag, + st->msNewMinFlag, + st->msPeriodogBuf, + &(st->msPeriodogBufPtr), + st->hFdCngCom + ); + + /* Expand MS outputs */ + expand_range(st->msLogNoiseEst, st->msNoiseEst, &st->msNoiseEst_exp, st->hFdCngCom->npart); + + +} + +/* + AdjustFirstSID + + Parameters: + + npart i : number of parts + msPeriodog i : pointer to periodog vector + msPeriodog_exp i : exponent of periodog vector + energy_ho i/o : pointer to energy + energy_ho_exp i/o : pointer to exponent of energy + msNoiseEst i/o : pointer to estimated noise + msNoiseEst_exp i/o : pointer to exponent of estimated noise + msNoiseEst_old i/o : pointer to old estimated noise + msNoiseEst_old_exp i/o : pointer to exponent of old estimated noise + active_frame_counter i/o : pointer to active frame counter + stcod i : pointer to Coder_State structure + + Function: + Adjust the noise estimator at the beginning of each CNG phase (encoder-side) + + Returns: + void +*/ +Word16 +AdjustFirstSID (Word16 npart, /* i : number of parts */ + Word32 *msPeriodog, /* i : pointer to periodog vector */ + Word16 msPeriodog_exp, /* i : exponent of periodog vector */ + Word32 *energy_ho, /* i/o : pointer to energy */ + Word16 *energy_ho_exp, /* i/o : pointer to exponent of energy */ + Word32 *msNoiseEst, /* i/o : pointer to estimated noise */ + Word16 *msNoiseEst_exp, /* i/o : pointer to exponent of estimated noise */ + Word32 *msNoiseEst_old, /* i/o : pointer to old estimated noise */ + Word16 *msNoiseEst_old_exp, /* i/o : pointer to exponent of old estimated noise */ + Word16 *active_frame_counter, /* i/o : pointer to active frame counter */ + Encoder_State_fx *stcod /* i : pointer to Coder_State_Plus structure */ + ) +{ + Word16 i, sc, s1, s2, lambda, lambdaM1, invFac; + Word32 tmp32, energy_ho_local, msNoiseEst_local; + + + test(); + IF ( EQ_16(stcod->cnt_SID_fx,1)&>_32(stcod->last_core_brate_fx,SID_2k40)) + { + /* Detect the hangover period and the first SID frame at the beginning of each CNG phase */ + + /* First hangover frame */ + Copy32 (msPeriodog, energy_ho, npart); + *energy_ho_exp = msPeriodog_exp; + move16(); + + /* Set first SID to current input level but add some smoothing */ + IF ( GE_16(*active_frame_counter,254)) + { + lambda = 0; + move16(); + lambdaM1 = 0x7FFF; + move16(); + } + ELSE + { + /* -0.94229902485 = 1024.0*log10(0.96)/log10(2.0)/64.0 */ + /* active_frame_counter scaled by (1/1024.0) for compensation */ + tmp32 = L_shl(L_deposit_l(add(*active_frame_counter, 1)), WORD32_BITS-1-10); + tmp32 = BASOP_Util_InvLog2(Mpy_32_16_1(tmp32, -30877/*-0.94229902485 Q15*/)); + lambda = extract_h(tmp32); + lambdaM1 = extract_h(L_sub(0x7FFFFFFF, tmp32)); + } + + invFac = getNormReciprocalWord16(1); + + /* one bit headroom for addition */ + sc = add(s_max(*msNoiseEst_old_exp, *energy_ho_exp), 1); + s1 = limitScale32(sub(sc, *msNoiseEst_old_exp)); + s2 = limitScale32(sub(sc, *energy_ho_exp)); + *energy_ho_exp = sc; + move16(); + + FOR (i=0; i 0 ) + { + tmp32 = 1; + move32(); + } + } + /* Set exponent to zero if msNoiseEst is zero */ + if ( tmp32==0 ) + { + *msNoiseEst_exp = 0; + move16(); + } + + *active_frame_counter = 0; + move16(); + } + test(); + IF ( NE_32(stcod->core_brate_fx,SID_2k40)&&NE_32(stcod->core_brate_fx,FRAME_NO_DATA)) + { + /* Count the number of active frames in a row */ + *active_frame_counter = add(*active_frame_counter, 1); + move16(); + } + ELSE + { + /* Store the noise estimate obtained in the CNG phases */ + Copy32 (msNoiseEst, msNoiseEst_old, npart); + *msNoiseEst_old_exp = *msNoiseEst_exp; + move16(); + + } + + + return 0; +} + + +/* + msvq_encoder + + Parameters: + + cb i : Codebook (indexed cb[stages][levels][p]) format Q9.7 + u[] i : Vector to be encoded (prediction and mean removed) format Q9.7 + levels i : Number of levels in each stage + maxC i : Tree search size + stages i : Number of stages + N i : Vector dimension + maxN i : Codebook vector dimension + Idx o : Indices + + + Function: + multi stage vector quantisation + + Returns: + void +*/ +static void msvq_encoder (const Word16 * const cb[], /* i : Codebook (indexed cb[*stages][levels][p]) scaled with 8 bits */ + Word16 u[], /* i : Vector to be encoded (prediction and mean removed) */ + const Word16 levels[], /* i : Number of levels in each stage */ + Word16 maxC, /* i : Tree search size */ + Word16 stages, /* i : Number of stages */ + Word16 N, /* i : Vector dimension */ + Word16 maxN, /* i : Codebook vector dimension */ + Word16 Idx[] /* o : Indices */ + ) +{ + Word32 *dist[2]; + Word32 t1, en, ss2, tmp; + const Word16 *cbp, *cb_stage, *p2; + Word16 *p1, *pTmp; + Word16 *indices[2], *resid[2], Tmp[M_MAX]; + Word16 i, j, m, s, c, c2, p_max; + Word16 parents[MBEST_MAX]; + Word32 dist_buf[2*MBEST_MAX]; + Word16 resid_buf[2*MBEST_MAX*M_MAX]; + Word16 idx_buf[2*MBEST_MAX*NSTAGES_MAX]; + + + + /*----------------------------------------------------------------* + * Allocate memory for previous (parent) and current nodes. + * Parent node is indexed [0], current node is indexed [1]. + *----------------------------------------------------------------*/ + + indices[0] = idx_buf; + indices[1] = idx_buf + maxC*stages; + set16_fx(idx_buf, 0, 2*stages*maxC); + + resid[0] = resid_buf; + resid[1] = resid_buf + maxC*N; + + dist[0] = dist_buf; + dist[1] = dist_buf + maxC; + + set16_fx(parents, 0, maxC); + + /*----------------------------------------------------------------* + * ISF weights are normalized, so it is always better to multiply it first + * Set up inital distance vector + *----------------------------------------------------------------*/ + + ss2 = L_mult(u[0], u[0]); + FOR (j=1; j < N; j++) + { + ss2 = L_mac(ss2, u[j], u[j]); + } + + FOR (j=0; j < maxC; j++) + { + dist[1][j] = ss2; + move32(); + } + + /* Set up inital error (residual) vectors */ + pTmp = resid[1]; + FOR (c=0; chFdCngCom; + + E_Exp = stenc->msNoiseEst_exp; + move16(); + E_ExpLd64 = L_shl(E_Exp, WORD32_BITS-1-LD_DATA_SCALE); + E = stenc->msNoiseEst; + + N = stenc->npartDec; + move16(); + + normFacN = getNormReciprocalWord16(N); + normShiftN = BASOP_util_norm_s_bands2shift(N); + + normFacGain = getNormReciprocalWord16(N_GAIN_MAX-N_GAIN_MIN); + normShiftGain = BASOP_util_norm_s_bands2shift(N_GAIN_MAX-N_GAIN_MIN); + + /* Convert to LOG */ + + /* e: Q14.23 format, v: Q9.23 format */ + e = L_deposit_l(0); + tmp = Mpy_32_32_r(L_shl(1, sub(31, E_Exp)), 214748); /* 1e-4f, Q31-E_Exp */ + FOR (i=0; iCngBandwidth, st->CngBitrate ); + + + /* Quantize gain, Q14.23 format */ + gain = L_add(gain, L_shr(gain,1)); + gain = L_add(gain, 507510784l/*60.5 Q23*/); + index = extract_l(L_shr(gain,WORD32_BITS-1-8)); + + + if ( index < 0 ) + { + index = 0; + move16(); + } + + if ( GT_16(index,127)) + { + index = 127; + move16(); + } + + /* gain Q14.23 format */ + gain = L_shl(L_deposit_l(index), WORD32_BITS-1-8); + gain = L_sub(gain, 503316480l/*60.0 Q23*/); + gain = Mpy_32_16_1(gain, 21845/*2.0f/3.0f Q15*/); + + + /* Apply gain and undo log */ + + /* sidNoiseEst: format Q6.26, 0.66438561897 = log10(10)/log10(2.0) / 10.0 * 2.0 */ + + /* calculate worst case for scaling */ + maxVal = 0x80000000/*-1.0 Q31*/; + move32(); + FOR (i=0; i= 0) + { + maxVal = L_sub(maxVal, 33554432l/*0.015625 Q31*/); + sidNoiseEst_Exp = add(sidNoiseEst_Exp,1); + } + st->sidNoiseEstExp = sidNoiseEst_Exp; + move16(); + E_ExpLd64 = L_shl(sidNoiseEst_Exp, WORD32_BITS-1-LD_DATA_SCALE); + + FOR (i=0; isidNoiseEst[i] = BASOP_Util_InvLog2(tmp); + move32(); + } + + /* NB last band energy compensation */ + IF ( EQ_16(st->CngBandwidth,NB)) + { + st->sidNoiseEst[N-1] = Mpy_32_16_1(st->sidNoiseEst[N-1], NB_LAST_BAND_SCALE); + move32(); + } + + test(); + if (EQ_16( st->CngBandwidth,SWB)&&LE_32(st->CngBitrate,ACELP_13k20)) + { + st->sidNoiseEst[N-1] = Mpy_32_16_1(st->sidNoiseEst[N-1], SWB_13k2_LAST_BAND_SCALE); + move32(); + } + + + /* Write bitstream */ + IF ( EQ_16(corest->codec_mode, MODE2)) + { + FOR (i=0; ibwidth_fx, 2 ); + IF (EQ_16(corest->L_frame_fx, L_FRAME16k)) + { + push_indice_fx( corest, IND_ACELP_16KHZ, 1, 1 ); + } + ELSE + { + push_indice_fx( corest, IND_ACELP_16KHZ, 0, 1 ); + } + FOR (i=0; i cngNoiseLevel: Q6.26 format */ + scalebands(st->sidNoiseEst, stenc->partDec, stenc->npartDec, stenc->midbandDec, stenc->nFFTpartDec, sub(stenc->stopBandDec,stenc->startBandDec), st->cngNoiseLevel, 1); + st->cngNoiseLevelExp = st->sidNoiseEstExp; + move16(); + + + lpc_from_spectrum(st->cngNoiseLevel, st->cngNoiseLevelExp, stenc->startBandDec, stenc->stopFFTbinDec, st->fftlen, st->A_cng, M, preemph_fac ); + + +} + + +void generate_comfort_noise_enc (Encoder_State_fx *stcod, + Word16 Q_new, + Word16 gen_exc + ) +{ + Word16 i, s, sn, cnt; + Word16 startBand2; + Word16 stopFFTbin2; + Word16 preemph_fac; + Word32 sqrtNoiseLevel; + Word16 randGaussExp; + Word16 fftBufferExp; + Word16 cngNoiseLevelExp; + Word16 *seed; + Word16 *timeDomainOutput; + Word32 *ptr_r, *ptr_i; + Word32 *cngNoiseLevel; + Word32 *ptr_level; + Word32 *fftBuffer; + Word16 old_syn_pe_tmp[16]; + Word16 tcx_transition = 0; + HANDLE_FD_CNG_ENC stenc = stcod->hFdCngEnc_fx; + HANDLE_FD_CNG_COM st = stenc->hFdCngCom; + + + + /* Warning fix */ + s = 0; + + /* pointer initialization */ + + cngNoiseLevel = st->cngNoiseLevel; + cngNoiseLevelExp = st->cngNoiseLevelExp; + ptr_level = cngNoiseLevel; + seed = &(st->seed); + fftBuffer = st->fftBuffer; + timeDomainOutput = st->timeDomainBuffer; + + /* + Generate Gaussian random noise in real and imaginary parts of the FFT bins + Amplitudes are adjusted to the estimated noise level cngNoiseLevel in each bin + scaling Gaussian random noise: format Q3.29 + */ + sn = 0; + move16(); + IF ( s_and(cngNoiseLevelExp,1) != 0 ) + { + sn = add(sn,1); + cngNoiseLevelExp = add(cngNoiseLevelExp,sn); + move16(); + } + + randGaussExp = CNG_RAND_GAUSS_SHIFT; + move16(); + cnt = sub(stenc->stopFFTbinDec, stenc->startBandDec); + IF ( stenc->startBandDec == 0 ) + { + /* DC component in FFT */ + s = 0; + move16(); + sqrtNoiseLevel = Sqrt32(L_shr(*ptr_level,sn), &s); + + fftBuffer[0] = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),s); + move32(); + + /* Nyquist frequency is discarded */ + fftBuffer[1] = L_deposit_l(0); + + ptr_level = ptr_level + 1; + ptr_r = fftBuffer + 2; + cnt = sub(cnt, 1); + } + ELSE + { + startBand2 = shl(stenc->startBandDec,1); + set32_fx(fftBuffer, 0, startBand2); + ptr_r = fftBuffer + startBand2; + } + + sn = add(sn,1); + ptr_i = ptr_r + 1; + FOR (i=0; i < cnt; i++) + { + s = 0; + move16(); + sqrtNoiseLevel = Sqrt32(L_shr(*ptr_level,sn), &s); + + /* Real part in FFT bins */ + *ptr_r = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),s); + move32(); + + /* Imaginary part in FFT bins */ + *ptr_i = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),s); + move32(); + + ptr_r = ptr_r + 2; + ptr_i = ptr_i + 2; + ptr_level = ptr_level + 1; + } + + /* Remaining FFT bins are set to zero */ + stopFFTbin2 = shl(stenc->stopFFTbinDec,1); + set32_fx(fftBuffer+stopFFTbin2, 0, sub(st->fftlen,stopFFTbin2)); + + fftBufferExp = add(shr(cngNoiseLevelExp,1),randGaussExp); + + /* If previous frame is active, reset the overlap-add buffer */ + IF ( GT_32(stcod->last_core_brate_fx,SID_2k40)) + { + set16_fx(st->olapBufferSynth, 0, st->fftlen); + test(); + test(); + IF ( (GT_32(stcod->last_core_fx,ACELP_CORE)&&EQ_16(stcod->codec_mode,MODE2))||EQ_16(stcod->codec_mode,MODE1)) + { + tcx_transition = 1; + move16(); + } + } + + /* Perform STFT synthesis */ + SynthesisSTFT (fftBuffer, fftBufferExp, timeDomainOutput, st->olapBufferSynth, st->olapWinSyn, + tcx_transition, + st, gen_exc, &Q_new); + { + Word32 Lener, att; + Word16 exp; + /* update CNG excitation energy for LP_CNG */ + + /* calculate the residual signal energy */ + /*enr = dotp( st->exc_cng, st->exc_cng, st->frameSize ) / st->frameSize;*/ + Lener = Dot_productSq16HQ(1,st->exc_cng,stcod->L_frame_fx,&exp); + exp = add(sub(shl(sub(15,Q_new),1),8),exp); /*8 = log2(256)*/ + + /* convert log2 of residual signal energy */ + /*(float)log10( enr + 0.1f ) / (float)log10( 2.0f );*/ + Lener = BASOP_Util_Log2(Lener); + Lener = L_add(Lener,L_shl(L_deposit_l(exp),WORD32_BITS-1-LD_DATA_SCALE)); /*Q25*/ + if(EQ_16(stcod->L_frame_fx,L_FRAME16k)) + { + Lener = L_sub(Lener, 10802114l/*0.3219280949f Q25*/); /*log2(320) = 8.3219280949f*/ + } + /* decrease the energy in case of WB input */ + IF( NE_16(stcod->bwidth_fx, NB)) + { + IF( EQ_16(stcod->bwidth_fx,WB)) + { + IF( stcod->CNG_mode_fx >= 0 ) + { + /* Bitrate adapted attenuation */ + att = L_shl(L_deposit_l(ENR_ATT_fx[stcod->CNG_mode_fx]),17); + } + ELSE + { + /* Use least attenuation for higher bitrates */ + att = L_shl(L_deposit_l(ENR_ATT_fx[4]),17); + } + } + ELSE + { + att = 384<<17; + move32();/*1.5 Q8<<17=Q25*/ + } + Lener = L_sub(Lener, att ); + } + /*stdec->lp_ener = 0.8f * stcod->lp_ener + 0.2f * pow( 2.0f, enr );*/ + Lener = BASOP_util_Pow2(Lener, 6, &exp); + Lener = Mult_32_16(Lener, 6554/*0.2f Q15*/); + exp = sub(25,exp); + Lener = L_shr(Lener, exp); /*Q6*/ + stcod->lp_ener_fx = L_add(Mult_32_16(stcod->lp_ener_fx, 26214/*0.8f Q15*/), Lener); /*Q6*/ + } + + /* Overlap-add when previous frame is active */ + test(); + IF ( ( GT_32(stcod->last_core_brate_fx,SID_2k40))&&(EQ_16(stcod->codec_mode,MODE2))) + { + Word32 old_exc_ener, gain, noise32; + Word16 seed_loc, lpcorder, old_syn, tmp, gain16, N, N2, N4, N8; + Word16 old_exc_ener_exp, gain_exp; + Word16 normFacE, normShiftE, normShiftEM1; + Word16 normFacG, normShiftG, normShiftGM1; + Word16 noiseExp, *old_exc, old_Aq[M+1], *old_syn_pe; + Word16 noise[640], normShiftP2; + Word16 Q_exc, Q_syn; + + + assert(st->frameSize <= 640); + + seed_loc = st->seed; + move16(); + N = st->frameSize; + move16(); + N2 = shr(st->frameSize,1); + + IF ( GT_16(stcod->last_core_fx,ACELP_CORE)) + { + Word16 left_overlap_mode; + left_overlap_mode = stcod->tcx_cfg.tcx_last_overlap_mode; + move16(); + if (EQ_16(left_overlap_mode, ALDO_WINDOW)) + { + left_overlap_mode = FULL_OVERLAP; + move16(); + } + + tcx_windowing_synthesis_current_frame( timeDomainOutput, + stcod->tcx_cfg.tcx_mdct_window, /*Keep sine windows for limiting Time modulation*/ + stcod->tcx_cfg.tcx_mdct_window_half, + stcod->tcx_cfg.tcx_mdct_window_minimum, + stcod->tcx_cfg.tcx_mdct_window_length, + stcod->tcx_cfg.tcx_mdct_window_half_length, + stcod->tcx_cfg.tcx_mdct_window_min_length, + 0, + left_overlap_mode, + NULL, + NULL, + NULL, + NULL, + NULL, + N/2, + shr(sub(abs_s(stcod->tcx_cfg.tcx_offset), stcod->tcx_cfg.tcx_offset), 1), /* equivalent to: stdec->tcx_cfg.tcx_offset<0?-stdec->tcx_cfg.tcx_offset:0 */ + 1, + 0, + 0 + ); + + IF (stcod->tcx_cfg.last_aldo != 0) + { + FOR (i=0; iframeSize; i++) + { + timeDomainOutput[i] = add(timeDomainOutput[i], shr_r(stcod->old_out_fx[i+NS2SA(stcod->sr_core, N_ZERO_MDCT_NS)],stcod->Q_old_out)); + move16(); + } + } + ELSE + { + tcx_windowing_synthesis_past_frame( stcod->LPDmem.Txnq, + stcod->tcx_cfg.tcx_aldo_window_1_trunc, + stcod->tcx_cfg.tcx_mdct_window_half, + stcod->tcx_cfg.tcx_mdct_window_minimum, + stcod->tcx_cfg.tcx_mdct_window_length, + stcod->tcx_cfg.tcx_mdct_window_half_length, + stcod->tcx_cfg.tcx_mdct_window_min_length, + stcod->tcx_cfg.tcx_last_overlap_mode + ); + + FOR (i=0; iLPDmem.Txnq[i],TCX_IMDCT_HEADROOM)); + move16(); + } + } + } + ELSE + { + + /* + - the scaling of the LPCs (e.g. old_Aq) is always Q12 (encoder or decoder) + + - the scaling of the deemphasized signals (e.g. old_syn) is always Q0 (encoder or decoder) + + - the scaling of the excitation signals in the encoder (e.g. old_exc) is Q_new + - the scaling of the preemphasized signals in the encoder (e.g. old_syn_pe) is Q_new-1 + + - the scaling of the excitation signals in the decoder (e.g. old_exc) is Q_exc (or stdec->Q_exc) + - the scaling of the preemphasized signals in the decoder (e.g. old_syn_pe) is Q_syn (or stdec->Q_syn) + */ + + lpcorder = M; + move16(); + E_LPC_f_lsp_a_conversion(stcod->lsp_old_fx, old_Aq, M); + old_exc = stcod->LPDmem.old_exc+sub(L_EXC_MEM,N2); + old_syn_pe = stcod->LPDmem.mem_syn2; + old_syn = stcod->LPDmem.syn[lpcorder]; + move16(); + preemph_fac = stcod->preemph_fac; + move16(); + Q_exc = Q_new; + Q_syn = sub(Q_new,1); + + /* shift to be in the range of values supported by getNormReciprocalWord16() */ + N8 = shr(N2, CNG_NORM_RECIPROCAL_RANGE_SHIFT); + + assert( N2 == (N8<olapWinSyn[i].v.re); + timeDomainOutput[i] = add(timeDomainOutput[i],tmp); + move16(); + tmp = mult(noise[i+N4],st->olapWinSyn[N4-1-i].v.im); + timeDomainOutput[i+N4] = add(timeDomainOutput[i+N4],tmp); + move16(); + } + } + } + +} + diff --git a/lib_enc/find_tar_fx.c b/lib_enc/find_tar_fx.c new file mode 100644 index 0000000..cb1099b --- /dev/null +++ b/lib_enc/find_tar_fx.c @@ -0,0 +1,155 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "cnst_fx.h" /* Common constants */ +#include "basop_util.h" +#include "stl.h" + + + +void find_targets_fx( + const Word16 *speech, /* i : pointer to the speech frame Q_new-1*/ + const Word16 *mem_syn, /* i : memory of the synthesis filter Q_new-1*/ + const Word16 i_subfr, /* i : subframe index */ + Word16 *mem_w0, /* i/o: weighting filter denominator memory Q_new-1*/ + const Word16 *p_Aq, /* i : interpolated quantized A(z) filter Q12*/ + const Word16 *res, /* i : residual signal Q_new*/ + const Word16 L_subfr, /* i : length of vectors for gain quantization */ + const Word16 *Ap, /* i : unquantized A(z) filter with bandwidth expansion Q12*/ + Word16 tilt_fac, /* i : tilt factor Q15 */ + Word16 *xn, /* o : Close-loop Pitch search target vector Q_new-1*/ + Word16 *cn /* o : target vector in residual domain Q_new*/ + ,Word16 *h1 +) +{ + Word16 i; + Word16 temp[M+5*L_SUBFR]; /* error of quantization */ + Word16 scale,scaleq,j,d,s,s2,tmp; + Word16 Aqs[M+1]; + Word32 Ltmp; + /*------------------------------------------------------------------------* + * Find the target vector for excitation search: + * + * |------| res[n] + * speech[n]---| A(z) |-------- + * |------| | |--------| error[n] |------| + * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target + * exc |--------| |------| + * + * Instead of subtracting the zero-input response of filters from + * the weighted input speech, the above configuration is used to + * compute the target vector. + *-----------------------------------------------------------------------*/ + FOR (i=0; i cn[] */ + temp[0] = 0; + move16(); + preemph_copy_fx(xn, cn, tilt_fac, L_SUBFR/2, temp); + syn_filt_s_lc_fx(1, Ap, cn, temp, L_SUBFR/2); /* Q-1 -> Q-2 */ + Residu3_lc_fx(p_Aq, M, temp, cn, L_SUBFR/2, 1); /* Q-2 -> Q-1 */ + Scale_sig(cn, L_SUBFR/2,1); + + /* second half: res[] --> cn[] (approximated and faster) */ + Copy(&res[i_subfr+(L_SUBFR/2)], cn+(L_SUBFR/2), L_SUBFR/2); + } + + /*---------------------------------------------------------------* + * Compute impulse response, h1[], of weighted synthesis filter * + *---------------------------------------------------------------*/ + + scale = norm_s( Ap[0] ); + scaleq = norm_s( p_Aq[0] ); + d = sub( scaleq, scale ); + IF ( d >= 0 ) + { + Copy( p_Aq, Aqs, M+1 ); + s = add( scaleq, 1 ); + s2 = shr( 16384, d ); + } + ELSE + { + Copy_Scale_sig( p_Aq, Aqs, M+1, d ); + s = add( scale, 1 ); + s2 = 16384; + } + Overflow = 0; + move16(); + FOR (i = 0; i < M; i++) + { + Ltmp = L_mult(Ap[i], s2); + FOR (j = 1; j <= i; j++) + { + Ltmp = L_msu(Ltmp, Aqs[j], h1[i-j]); + } + h1[i] = round_fx(L_shl(Ltmp, s)); + } + Ltmp = L_mult(Ap[i], s2); + FOR (j = 1; j <= M; j++) + { + Ltmp = L_msu(Ltmp, Aqs[j], h1[i-j]); + } + h1[M] = round_fx(L_shl(Ltmp, s)); + FOR (i=M+1; i < L_subfr; i++) + { + Ltmp = L_msu(0, Aqs[1], h1[i-1]); + FOR (j = 2; j <= M; j++) + { + Ltmp = L_msu(Ltmp, Aqs[j], h1[i-j]); + } + h1[i] = round_fx(L_shl(Ltmp, s)); + } + IF(Overflow) + { + s2 = shr(s2, 1); + FOR (i = 0; i < M; i++) + { + Ltmp = L_mult(Ap[i], s2); + FOR (j = 1; j <= i; j++) + { + Ltmp = L_msu(Ltmp, Aqs[j], h1[i-j]); + } + h1[i] = round_fx(L_shl(Ltmp, s)); + } + Ltmp = L_mult(Ap[i], s2); + FOR (j = 1; j <= M; j++) + { + Ltmp = L_msu(Ltmp, Aqs[j], h1[i-j]); + } + h1[M] = round_fx(L_shl(Ltmp, s)); + FOR (i=M+1; i < L_subfr; i++) + { + Ltmp = L_msu(0, Aqs[1], h1[i-1]); + FOR (j = 2; j <= M; j++) + { + Ltmp = L_msu(Ltmp, Aqs[j], h1[i-j]); + } + h1[i] = round_fx(L_shl(Ltmp, s)); + } + } + + tmp = 0; + Deemph2(h1, tilt_fac, L_subfr, &tmp); + + return; + +} diff --git a/lib_enc/find_tilt_fx.c b/lib_enc/find_tilt_fx.c new file mode 100644 index 0000000..800e056 --- /dev/null +++ b/lib_enc/find_tilt_fx.c @@ -0,0 +1,229 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "basop_util.h" + +/*-------------------------------------------------------------------* + * find_tilt() + * + * Find LF/HF energy ratio + *-------------------------------------------------------------------*/ + +void find_tilt_fx( + const Word32 fr_bands[], /* i : energy in frequency bands Q_new + Q_SCALE*/ + const Word32 bckr[], /* i : per band background noise energy estimate Q_new + Q_SCALE*/ + Word32 ee[2], /* o : lf/hf E ration for present frame Q6*/ + const Word16 pitch[3], /* i : open loop pitch values for 3 half-frames Q0*/ + const Word16 voicing[3], /* i : normalized correlation for 3 half-frames Q15*/ + const Word32 *lf_E, /* i : per bin energy for low frequencies Q_new + Q_SCALE - 2*/ + const Word16 corr_shift, /* i : normalized correlation correction Q15*/ + const Word16 bwidth, /* i : input signal bandwidth */ + const Word16 max_band, /* i : maximum critical band */ + Word32 hp_E[], /* o : energy in HF Q_new + Q_SCALE*/ + const Word16 codec_mode, /* i : MODE1 or MODE2 */ + const Word16 Q_new, /* i : scaling factor */ + Word32 *bckr_tilt_lt /* i/o: lf/hf E ratio of background noise Q16 */ + ,Word16 Opt_vbr_mode +) +{ + Word32 lp_bckr = 0, hp_bckr = 0, lp_E, Ltmp; + const Word32 *pt_E, *pt_bands, *pt_bckr, *hf_bands, *tmp_E; + Word16 tmp, freq, f0, f1, f2, mean_voi, bin; + Word16 i, nb_bands; + Word16 e_tmp, m_tmp; + Word16 m_Fs, e_Fs; + Word16 m_cnt, e_cnt; + Word16 m_hpE, e_hpE; + Word16 scaling; + /*-----------------------------------------------------------------* + * Initializations + *-----------------------------------------------------------------*/ + + scaling = add(Q_new, QSCALE); + IF( NE_16(bwidth,NB)) + { + /* WB processing */ + bin = BIN4_FX; + move16(); /* First useful frequency bin ~ 50 Hz */ + pt_bands = fr_bands; + tmp_E = lf_E; + pt_bckr = bckr; + nb_bands = 10; + move16(); + } + ELSE + { + /* NB processing */ + bin = add(shl(BIN4_FX,1), BIN4_FX); /* First useful frequency bin ~ 150 Hz */ + pt_bands = fr_bands+1; /* Exlcude 1st critical band */ + tmp_E = lf_E + 2; /* Start at the 3rd bin (150 Hz) */ + pt_bckr = bckr+1; /* Exlcude 1st critical band */ + nb_bands = 9; + move16(); /* Nb. of "low" frequency bands taken into account in NB processing */ + } + + /*-----------------------------------------------------------------* + * Find spectrum tilt + *-----------------------------------------------------------------*/ + + pt_E = tmp_E; /* Point at the 1st useful element of the per-bin energy vector */ + hf_bands = fr_bands; + + /* bckr + voicing */ + /*lp_bckr = mean( pt_bckr, nb_bands );*/ /* estimated noise E in first critical bands, up to 1270 Hz */ + lp_bckr = Mean32(pt_bckr, nb_bands); + /*hp_bckr = 0.5f * (bckr[max_band-1] + bckr[max_band]);*/ /* estimated noise E in last 2 critical bands */ + hp_bckr = L_shr(L_add(bckr[max_band-1] , bckr[max_band]),1); + if (hp_bckr == 0) /* Avoid division by zero. */ + { + hp_bckr = L_deposit_l(1); + } + tmp = BASOP_Util_Divide3232_Scale( lp_bckr, hp_bckr, &e_tmp ); + Ltmp = L_shr_r( L_deposit_h( tmp ), sub( 15, e_tmp ) ); + *bckr_tilt_lt = L_add( Mpy_32_16_r( *bckr_tilt_lt, 29491 ), Mpy_32_16_r( Ltmp, 3277 ) ); + + test(); + IF ( EQ_16(codec_mode,MODE2)||Opt_vbr_mode==1) + { + /*lp_bckr *= FACT;*/ + /*hp_bckr *= FACT;*/ + lp_bckr = L_add(L_shl(lp_bckr,1),lp_bckr); + hp_bckr = L_add(L_shl(hp_bckr,1),hp_bckr); + } + /*mean_voi = 0.5f * (voicing[1] + voicing[2]) + corr_shift;*/ + Ltmp = L_mult(voicing[1], 16384); + Ltmp = L_mac(Ltmp, voicing[2], 16384); + Ltmp = L_mac(Ltmp,corr_shift, 32767); + mean_voi = round_fx(Ltmp); + + /*f0 = INT_FS_FX / pitch[2];*/ + e_tmp = norm_s(pitch[2]); + m_tmp = shl(pitch[2], e_tmp); + + m_Fs = div_s(INT_FS_FX, m_tmp); + e_Fs = sub(15, e_tmp); + f0 = shr(m_Fs, sub(e_Fs,4)); /* Q4 */ + + FOR( i=0; i<2; i++ ) + { + /*hp_E[i] = 0.5f * (hf_bands[max_band-1] + hf_bands[max_band]) - hp_bckr; *//* averaged E in last 2 critical bands */ + Ltmp = L_add(L_shr(hf_bands[max_band-1], 1), L_shr(hf_bands[max_band], 1)); + hp_E[i] = L_sub(Ltmp, hp_bckr); + IF ( Opt_vbr_mode == 0 ) + { + hp_E[i] = L_max(hp_E[i], L_shl(E_MIN_FX, Q_new)); + move32(); + } + ELSE + { + hp_E[i] = L_max(hp_E[i], L_shl(1, scaling)); + move32(); + } + + test(); + IF(GT_16(mean_voi,TH_COR_FX)&<_16(pitch[2],TH_PIT_FX)) /* High-pitched voiced frames */ + { + freq = bin; + move16(); /* 1st useful frequency bin */ + m_cnt = 0; + move16(); + lp_E = L_deposit_l(0); + + f1 = add(shr(f0,1),f0); /* Middle between 2 harmonics */ + f2 = f0; + move16(); + WHILE(LE_16(freq, 20320)) /* End frequency of 10th critical band */ + { + FOR (; freq <= f1; freq += BIN4_FX) + { + /* include only bins sufficiently close to harmonics */ + tmp = sub(freq, f2); + IF(L_mac0(-(Word32)TH_D_FX*TH_D_FX, tmp, tmp) < 0) + { + lp_E = L_add(*pt_E, lp_E); + m_cnt = add(m_cnt, 1); + } + pt_E++; + } + f1 = add(f1,f0); + f2 = add(f2,f0); + } + /*lp_E = lp_E / (float)cnt - lp_bckr;*/ + e_tmp = sub(norm_l(lp_E), 1); + m_tmp = extract_h(L_shl(lp_E, e_tmp)); + + e_tmp = sub(e_tmp,2); /* lf_e divided by 4 in anal_sp */ + + e_cnt = norm_s(m_cnt); + m_cnt = shl(m_cnt, e_cnt); + + m_tmp = div_s(m_tmp, m_cnt); + e_tmp = sub(e_tmp, e_cnt); + + lp_E = L_sub(L_shr(m_tmp, sub(e_tmp, 1)), lp_bckr); + + + pt_E = tmp_E + VOIC_BINS; /* Update for next half-frame */ + } + ELSE /* Other than high-pitched voiced frames */ + { + /*lp_E = mean( pt_bands, nb_bands ) - lp_bckr;*/ /* averaged E in first critical bands, up to 1270 Hz */ + lp_E = L_sub(Mean32( pt_bands, nb_bands ) , lp_bckr); + } + IF ( Opt_vbr_mode == 0 ) + { + lp_E = L_max(lp_E, L_shl(E_MIN_FX,Q_new)); + } + ELSE + { + lp_E = L_max(lp_E, 0); + } + /*ee[i] = lp_E / hp_E[i];*/ /* LF/HF ratio */ + test(); + IF (lp_E != 0 && hp_E[i] != 0) + { + e_tmp = sub(norm_l(lp_E), 1); + m_tmp = extract_h(L_shl(lp_E, e_tmp)); + e_hpE = norm_l(hp_E[i]); + m_hpE = extract_h(L_shl(hp_E[i], e_hpE)); + m_tmp = div_s(m_tmp, m_hpE); + e_tmp = sub(e_tmp, e_hpE); + + ee[i] = L_shr(m_tmp, add(e_tmp, 15-6)); /* ee in Q6 */ + } + ELSE IF (lp_E == 0) + { + ee[i] = L_deposit_l(0); + } + ELSE + { + ee[i] = MAX_32; + } + + IF( EQ_16(bwidth,NB)) /* For NB input, compensate for the missing bands */ + { + Ltmp = L_shl(ee[i], 3); + IF (EQ_32(Ltmp, MAX_32)) /* if Overflow: Compute with less precision */ + { + Ltmp = Mult_32_16(ee[i], 24576); /* 6/8 */ + ee[i] = L_shl(Ltmp, 3); + move32(); /* x8 */ + } + ELSE + { + ee[i] = Mult_32_16(Ltmp, 24576); + move32();/* 6/8 */ + } + } + + pt_bands += NB_BANDS; /* Update for next half-frame */ + hf_bands += NB_BANDS; + } + + return; +} diff --git a/lib_enc/find_uv.c b/lib_enc/find_uv.c new file mode 100644 index 0000000..f1204a1 --- /dev/null +++ b/lib_enc/find_uv.c @@ -0,0 +1,551 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define L_ENR (NB_SSF+2) + + + +/*-------------------------------------------------------------------* + * find_ener_decrease_fx() + * + * Find maximum energy ration between short subblocks in case + * energy is trailing off after a spike + *-------------------------------------------------------------------*/ + +static Word16 find_ener_decrease_fx( /* o : maximum energy ratio Q10 */ + const Word16 ind_deltaMax, /* i : index of the beginning of maximum energy search */ + const Word32 *pt_enr_ssf /* i : Pointer to the energy buffer */ +) +{ + Word16 i, j, end, flag; + Word16 wtmp0, wtmp1; + Word32 maxEnr, minEnr; + Word16 dE2, exp0, exp1; + + dE2 = 0; + move16(); + + j = ind_deltaMax+2; + move16(); + end = j+L_ENR; + move16(); + maxEnr = L_add(pt_enr_ssf[j], 0); + j = add(j, 1); + flag = 0; + move16(); + FOR( i=j; iee_old + ee[0] + ee[1]); */ /* coefficients take into account the position of the window */ + mean_ee = L_add(L_add(st_fx->ee_old_fx, ee[0]), ee[1]); + mean_ee = Mult_32_16(mean_ee, 10923); /*Q6*/ + + /* mean_voi3 = 1.0f/3.0f * (voicing[0] + voicing[1] + voicing[2]);*/ + Ltmp0 = L_mult( voicing[0], 10923); + Ltmp0 = L_mac(Ltmp0, voicing[1], 10923); + mean_voi3 = mac_r(Ltmp0, voicing[2], 10923); /*Q15*/ + + /*-----------------------------------------------------------------* + * Total frame energy difference (dE3) + *-----------------------------------------------------------------*/ + + dE3 = sub(Etot, st_fx->Etot_last_fx); /*Q8*/ + + /*-----------------------------------------------------------------* + * Energy decrease after spike (dE2) + *-----------------------------------------------------------------*/ + + /* set different thresholds and conditions for NB and WB input */ + dE2_th = 30<<10; + move32(); + nb_cond = 1; + move16(); /* no additional condition for WB input */ + IF ( EQ_16(st_fx->input_bwidth_fx,NB)) + { + dE2_th = 21<<10; + move32(); + if(GE_16(add(mean_voi3, corr_shift), 22282)) /*( mean_voi3 + corr_shift ) >= 0.68f*/ + { + nb_cond = 0; + move16(); + } + } + + /* calcualte maximum energy decrease */ + dE2 = 0; + move16(); /* Test on energy decrease after an energy spike */ + pt_enr_ssf = enr_ssf + 2*NB_SSF; + + test(); + IF( GT_32(dE1, 30<<13)&&nb_cond) /*>30 Q13*/ + { + IF( LT_16(sub(shl(NB_SSF,1), ind_deltaMax),L_ENR)) + { + st_fx->old_ind_deltaMax_fx = ind_deltaMax; + move16(); + Copy32( pt_enr_ssf, st_fx->old_enr_ssf_fx, 2*NB_SSF ); + } + ELSE + { + st_fx->old_ind_deltaMax_fx = -1; + move16(); + dE2 = find_ener_decrease_fx( ind_deltaMax, pt_enr_ssf ); /*Q10*/ + + if( GT_32(dE2,dE2_th)) + { + st_fx->spike_hyst_fx = 0; + move16(); + } + } + } + ELSE + { + IF( st_fx->old_ind_deltaMax_fx >= 0 ) + { + Copy32( st_fx->old_enr_ssf_fx, enr_ssf, 2*NB_SSF ); + dE2 = find_ener_decrease_fx( st_fx->old_ind_deltaMax_fx, enr_ssf ); + + if( GT_32(dE2,dE2_th)) + { + st_fx->spike_hyst_fx = 1; + move16(); + } + } + + st_fx->old_ind_deltaMax_fx = -1; + move16(); + } + + /*-----------------------------------------------------------------* + * Detection of voiced offsets (tmp_offset_flag) + *-----------------------------------------------------------------*/ + + tmp_offset_flag = 1; + move16(); + + IF ( NE_16(st_fx->input_bwidth_fx, NB)) + { + ee0_th = 154; /*2.4 in Q6 */ move16(); + voi_th = 24248; /*0.74f Q15 */ move16(); + } + ELSE + { + ee0_th = 627; /*9.8f Q6 */ move16(); + voi_th = 24904; /*0.76f Q15*/ move16(); + } + + test(); + test(); + test(); + if( ( EQ_16(st_fx->last_coder_type_raw_fx,UNVOICED))|| /* previous frame was unvoiced */ + ( ( LT_32(ee[0],ee0_th) ) && ( GT_32(hp_E[0],L_shl(E_MIN_FX,Q_new)) ) && /* energy is concentrated in high frequencies provided that some energy is present in HF */ + ( LT_16(add(voicing[0],corr_shift),voi_th)))) /* normalized correlation is low */ + { + tmp_offset_flag = 0; + move16(); + } + + /*-----------------------------------------------------------------* + * Decision about UC + *-----------------------------------------------------------------*/ + + /* SC-VBR - set additional parameters and thresholds for SC-VBR */ + mean_voi3_offset = 0; + move16(); + flag_low_relE = 0; + move16(); + ee1_th = 608; /*9.5 Q6*/ move16(); + IF ( st_fx->Opt_SC_VBR_fx ) + { + ee1_th = 544; /*8.5f Q6*/ move16(); + + /* SC-VBR - determine the threshold on relative energy as a function of lp_noise */ + IF ( NE_16(st_fx->input_bwidth_fx,NB)) + { + /*relE_thres = 0.700f * st->lp_noise - 33.5f; (lp_noise in Q8, constant Q8<<16) */ + L_tmp = L_mac(-562036736, 22938, st_fx->lp_noise_fx); + if ( st_fx->Last_Resort_fx == 0 ) + { + /*relE_thres = 0.650f * st->lp_noise - 33.5f; (lp_noise in Q8, constant Q8<<16)*/ + L_tmp = L_mac(-562036736, 21299, st_fx->lp_noise_fx); + } + relE_thres = round_fx(L_tmp); + } + ELSE + { + + /*relE_thres = 0.60f * st->lp_noise - 28.2f; (lp_noise in Q8, constant Q8<<16)*/ + L_tmp = L_mac(-473117491, 19661, st_fx->lp_noise_fx); + relE_thres = round_fx(L_tmp); + } + relE_thres = s_max(relE_thres , -6400); /* Q8 */ + + /* SC-VBR = set flag on low relative energy */ + if ( LT_16(relE,relE_thres)) + { + flag_low_relE = 1; + move16(); + } + + /* SC-VBR - correction of voicing threshold for NB inputs (important only in noisy conditions) */ + test(); + if ( EQ_16(st_fx->input_bwidth_fx,NB)&<_16(st_fx->vadnoise_fx,20<<8)) /* vadnoise in Q8, constant Q0<<8 */ + { + mean_voi3_offset = 1638; /*0.05f Q15*/ move16(); + } + } + + /* make decision whether frame is unvoiced */ + E_min_th = L_shl(E_MIN_FX,Q_new); + coder_type = GENERIC; + move16(); + IF ( EQ_16(st_fx->input_bwidth_fx,NB)) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + if( ( ( LT_16(add(mean_voi3, corr_shift),add(22282,mean_voi3_offset)))&& /* normalized correlation low */ + ( LT_16(add(voicing[2], corr_shift),25887) ) && /* normalized correlation low on look-ahead - onset detection */ + ( LT_32(ee[0], 640) ) && ( GT_32(hp_E[0], E_min_th) ) && /* energy concentrated in high frequencies provided that some energy is present in HF... */ + ( LT_32(ee[1], ee1_th) ) && ( GT_32(hp_E[1], E_min_th) ) && /* ... biased towards look-ahead to detect onsets */ + ( tmp_offset_flag == 0 ) && /* Take care of voiced offsets */ + ( st_fx->music_hysteresis_fx == 0 ) && /* ... and in segment after AUDIO frames */ + ( LE_32(dE1, 237568) ) && /* Avoid on sharp energy spikes */ + ( LE_32(st_fx->old_dE1_fx,237568) ) && /* + one frame hysteresis */ + ( st_fx->spike_hyst_fx < 0 ) ) || /* Avoid after sharp energy spikes followed by decay (e.g. castanets) */ + flag_low_relE ) /* low relative frame energy (only for SC-VBR) */ + { + coder_type = UNVOICED; + move16(); + } + } + ELSE + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + if( ( ( LT_16(add(mean_voi3, corr_shift),add(22774,mean_voi3_offset)))&& /* normalized correlation low */ + ( LT_16(add(voicing[2], corr_shift),25887) ) && /* normalized correlation low on look-ahead - onset detection */ + ( LT_32(ee[0], 397) ) && ( GT_32(hp_E[0], E_min_th) ) && /* energy concentrated in high frequencies provided that some energy is present in HF... */ + ( LT_32(ee[1], 397) ) && ( GT_32(hp_E[1], E_min_th) ) && /* ... biased towards look-ahead to detect onsets */ + ( tmp_offset_flag == 0 ) && /* Take care of voiced offsets */ + ( st_fx->music_hysteresis_fx == 0 ) && /* ... and in segment after AUDIO frames */ + ( LE_32(dE1, 245760) ) && /* Avoid on sharp energy spikes */ + ( LE_32(st_fx->old_dE1_fx,245760) ) && /* + one frame hysteresis */ + ( st_fx->spike_hyst_fx < 0 ) ) /* Avoid after sharp energy spikes followed by decay (e.g. castanets) */ + || ( flag_low_relE + && ( LE_32(st_fx->old_dE1_fx,245760) ) + ) + ) /* low relative frame energy (only for SC-VBR) */ + { + coder_type = UNVOICED; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Decision about VC + *-----------------------------------------------------------------*/ + + st_fx->set_ppp_generic_fx = 0; + move16(); + + test(); + test(); + IF( EQ_16(localVAD,1)&&EQ_16(coder_type,GENERIC)&&NE_16(last_core_orig,AMR_WB_CORE)) + { + dpit1 = abs_s( sub(T_op_fr[1], T_op_fr[0])); + dpit2 = abs_s( sub(T_op_fr[2], T_op_fr[1])); + dpit3 = abs_s( sub(T_op_fr[3], T_op_fr[2])); + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( GT_16(voicing_fr[0],19825))&& /* normalized correlation high in 1st sf. */ + ( GT_16(voicing_fr[1],19825) ) && /* normalized correlation high in 2st sf. */ + ( GT_16(voicing_fr[2],19825) ) && /* normalized correlation high in 3st sf. */ + ( GT_16(voicing_fr[3],19825) ) && /* normalized correlation high in 4st sf. */ + ( GT_32(mean_ee,256) ) && /* energy concentrated in low frequencies */ + ( LT_16(dpit1,3<<6) ) && + ( LT_16(dpit2,3<<6) ) && + ( LT_16(dpit3,3<<6) ) ) + { + coder_type = VOICED; + move16(); + } + ELSE IF ( st_fx->Opt_SC_VBR_fx && EQ_16(st_fx->input_bwidth_fx,NB)&<_16(st_fx->vadnoise_fx,20<<8)) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( GT_16(voicing_fr[0],8192)&& /* normalized correlation high in 1st sf. */ + ( GT_16(voicing_fr[1],8192) ) && /* normalized correlation high in 2st sf. */ + ( GT_16(voicing_fr[2],8192) ) && /* normalized correlation high in 3st sf. */ + ( GT_16(voicing_fr[3],8192) ) && /* normalized correlation high in 4st sf. */ + ( GT_32(mean_ee,64) ) && /* energy concentrated in low frequencies */ + ( LT_16(dpit1,5<<6) ) && + ( LT_16(dpit2,5<<6) ) && + ( LT_16(dpit3,5<<6) ) ) + { + st_fx->set_ppp_generic_fx = 1; + move16(); + coder_type = VOICED; + move16(); + } + } + + /* set VOICED mode for frames with very stable pitch and high correlation + and avoid to switch to AUDIO/MUSIC later */ + voicing_m = mac_r(L_mac(L_mac(L_mult(voicing_fr[3], 8192), voicing_fr[2], 8192),voicing_fr[1], 8192),voicing_fr[0], 8192); + test(); + test(); + test(); + test(); + test(); + IF ( *flag_spitch || ( LE_16(dpit1,3<<6)&&LE_16(dpit2,3<<6)&&LE_16(dpit3,3<<6)&& + GT_16(voicing_m, 31130) && GT_16(voicing_sm, 31785) ) ) + { + coder_type = VOICED; + move16(); + *flag_spitch = 1; + move16();/*to avoid switch to AUDIO/MUSIC later*/ + } + } + + /*-----------------------------------------------------------------* + * Channel-aware mode - set RF mode and total bitrate + *-----------------------------------------------------------------*/ + + st_fx->rf_mode = st_fx->Opt_RF_ON; + move16(); + + IF ( EQ_16 ( coder_type, GENERIC ) ) + { + test(); + test(); + test(); + test(); + IF( ( LT_16(voicing_fr[0],6554))&& /* normalized correlation high in 2st sf. */ + ( LT_16(voicing_fr[1],6554) ) && /* normalized correlation high in 2st sf. */ + ( LT_16(voicing_fr[2],6554) ) && /* normalized correlation high in 3rd sf. */ + ( LT_16(voicing_fr[3],6554) ) && /* normalized correlation high in 4th sf. */ + ( GT_16(st_fx->vadnoise_fx, 25 << 8 ) )) /* when speech is clean */ + + { + st_fx->rf_mode = 0; + move16(); + /* Current frame cannot be compressed to pack the partial redundancy;*/ + + if( st_fx->rf_mode != st_fx->Opt_RF_ON ) + { + core_coder_mode_switch( st_fx, st_fx->bwidth_fx, st_fx->total_brate_fx, shift ); + } + } + } + + + + + + /*-----------------------------------------------------------------* + * Updates + *-----------------------------------------------------------------*/ + + /* update spike hysteresis parameters */ + test(); + if( st_fx->spike_hyst_fx >= 0 && LT_16(st_fx->spike_hyst_fx,2)) + { + st_fx->spike_hyst_fx = add(st_fx->spike_hyst_fx,1); + } + + /* reset spike hysteresis */ + test(); + test(); + test(); + if( ( GT_16(st_fx->spike_hyst_fx,1))&& + ( GT_16(dE3,5<<8) || /* energy increases */ + ( GT_16(relE, -3328)&&(GT_16(add(mean_voi3,corr_shift),22774))))) /* normalized correlation is high */ + { + st_fx->spike_hyst_fx = -1; + move16(); + } + + /* update tilt parameters */ + st_fx->ee_old_fx = ee[1]; + move32(); /*Q6*/ + st_fx->old_dE1_fx = dE1; + move32(); /*Q13*/ + + /* save the raw coder_type for various modules later in the codec (the reason is that e.g. UNVOICED is lost at higher rates) */ + st_fx->coder_type_raw_fx = coder_type; + move16(); + + return coder_type; +} diff --git a/lib_enc/find_wsp_fx.c b/lib_enc/find_wsp_fx.c new file mode 100644 index 0000000..acbc503 --- /dev/null +++ b/lib_enc/find_wsp_fx.c @@ -0,0 +1,86 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include "stl.h" +#include "prot_fx.h" +#include "options.h" +#include "cnst_fx.h" +#include "stl.h" + + + +/* + * find_wsp + * + * Parameters: + * Az I: A(z) filter coefficients Q12 + * speech I: pointer to the denoised speech frame Q_new - preemph_bits + * wsp O: pointer to the weighted speech frame Q_new - preemph_bits + * mem_wsp I/O: W(z) denominator memory + * preemph_fac I: pre-emphasis factor Q15 + * L_frame I: length of the frame + * lookahead I: length of a look-ahead + * L_subfr I: length of the sub-frame + * + * Function: + * Find weighted speech (formula from AMR-WB) + * + * Returns: + * void + */ +void find_wsp( + const Word16 Az[], + const Word16 speech[], + Word16 wsp[], + Word16 *mem_wsp, + const Word16 preemph_fac, + const Word16 L_frame, + const Word16 lookahead, + const Word16 L_subfr, + Word16 *Aw, /* o : weighted A(z) filter coefficients */ + const Word16 gamma, /* i : weighting factor */ + const Word16 nb_subfr /* i : number of subframes */ +) +{ + Word16 i_subfr, wtmp; + const Word16 *p_Az; + /*-----------------------------------------------------------------* + * Compute weighted A(z) unquantized for subframes + *-----------------------------------------------------------------*/ + + weight_a_subfr_fx( nb_subfr, Az, Aw, gamma, M ); + + + /*----------------------------------------------------------------* + * Compute weighted speech for all subframes + *----------------------------------------------------------------*/ + BASOP_SATURATE_WARNING_OFF + p_Az = Aw; /*move16();*/ + FOR (i_subfr = 0; i_subfr < L_frame; i_subfr += L_subfr) + { + Residu3_fx(p_Az, &speech[i_subfr], &wsp[i_subfr], L_subfr, 0); + p_Az += (M+1); + } + p_Az -= (M+1); + BASOP_SATURATE_WARNING_ON + /*----------------------------------------------------------------* + * Weighted speech computation is extended on look-ahead + *----------------------------------------------------------------*/ + deemph_fx(wsp, preemph_fac, L_frame, mem_wsp); /* use Deemph2 to prevent saturation */ + + IF ( lookahead != 0 ) + { + Residu3_fx(p_Az, &speech[L_frame], &wsp[L_frame], lookahead, 0); + wtmp = *mem_wsp; + move16(); + deemph_fx(&wsp[L_frame], preemph_fac, lookahead, &wtmp); + } + +} + + + diff --git a/lib_enc/frame_spec_dif_cor_rate.c b/lib_enc/frame_spec_dif_cor_rate.c new file mode 100644 index 0000000..a87186f --- /dev/null +++ b/lib_enc/frame_spec_dif_cor_rate.c @@ -0,0 +1,112 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include + +#include "basop_util.h" +#include "stl.h" +#include "vad_basop.h" +#include "prot_fx.h" + + + +void frame_spec_dif_cor_rate(T_CldfbVadState *st, /*(io) vad state*/ + Word32 *spec_amp, /*(i) spectral amplitude*/ + Word16 sacle, /*(i) the scaling of spec_amp*/ + Word16 f_tonality_rate[3] /*(o) tonality rate*/ + ) + +{ + Word32 i,tmp; + Word16 spec_low_dif_tmp,tmpq,tmpq2,*p_dx_Q,dx_Q=0; + Word32 tmpspec_low_dif[PRE_SPEC_DIF_NUM]; + Word32 maxVal; + Word16 resu; + Word16 scalefactor,spec_dif_cor_rate; + Word32 m,dx,dy; + Word16 *pre_spec_low_dif = st->pre_spec_low_dif; + const Word32 FIX_cost1 = 2147484/* 0.001f Q31 */; + + + + p_dx_Q = &dx_Q; + maxVal = 0; move32(); + FOR(i=0; i< PRE_SPEC_DIF_NUM; i++) + { + tmp = L_sub(spec_amp[i+6] ,spec_amp[i+5]); + if ( tmp < 0 ) + { + tmp = 0; + move32(); + } + tmpspec_low_dif[i] = tmp; + move32(); + maxVal = L_max(maxVal,tmp); + } + resu = 31; + move16(); + if ( maxVal ) + { + resu = norm_l(maxVal); + } + + m = 0; move32(); + dx = 0; move32(); + dy = 0; move32(); + + scalefactor = sub(resu,3); + + FOR (i = 0; i < PRE_SPEC_DIF_NUM; i++) + { + spec_low_dif_tmp = round_fx(L_shl(tmpspec_low_dif[i],scalefactor)); + m = L_mac0(m,spec_low_dif_tmp,pre_spec_low_dif[i]); + dx = L_mac0(dx, spec_low_dif_tmp, spec_low_dif_tmp); + dy = L_mac0(dy, pre_spec_low_dif[i], pre_spec_low_dif[i]); + pre_spec_low_dif[i] = spec_low_dif_tmp; + move16(); + } + dx = L_mult0(round_fx(dx),round_fx(dy)); + tmpq = add(sacle,scalefactor); + tmpq = sub(tmpq,16); + tmpq2 = add(tmpq,st->scale_spec_low_dif); + *p_dx_Q = shl(tmpq2,1); + move16(); + *p_dx_Q = sub(*p_dx_Q ,32); + move16(); + IF(LT_16(*p_dx_Q , 31)) + { + dx = L_add(dx,L_shr(FIX_cost1,limitScale32(sub(31,*p_dx_Q)))); + } + ELSE + { + dx = L_add(L_shr(dx,limitScale32(sub(*p_dx_Q,31))),FIX_cost1); + *p_dx_Q = 31; + move16(); + } + + dx = vad_Sqrt_l(dx,p_dx_Q); + + m = L_shr(m,limitScale32(add(sub(tmpq2,*p_dx_Q),1))); + spec_dif_cor_rate = 16384; + move16(); + + if(dx) + { + spec_dif_cor_rate = divide3232(m,dx); + } + + f_tonality_rate[0] = spec_dif_cor_rate; + move16(); + tmp = L_mac0(L_mult0(f_tonality_rate[1],31456/* 0.96 Q15 */), spec_dif_cor_rate,1311/* 0.04 Q15 */); + f_tonality_rate[1] = shl(round_fx(tmp),1); + move16(); + tmp = L_mac0(L_mult0(f_tonality_rate[2],29490/* 0.90 Q15 */), spec_dif_cor_rate,3277/* 0.1 Q15 */); + f_tonality_rate[2] = shl(round_fx(tmp),1); + move16(); + st->scale_spec_low_dif = tmpq; + move16(); + +} + diff --git a/lib_enc/gain_enc_fx.c b/lib_enc/gain_enc_fx.c new file mode 100644 index 0000000..d287b53 --- /dev/null +++ b/lib_enc/gain_enc_fx.c @@ -0,0 +1,1901 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define RANGE 64 +#define NB_QUA_GAIN7B 128 /* Number of quantization levels */ + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static Word16 Find_Opt_gainQ_fx(Word16 *coeff, Word16 *exp_coeff, Word16 *gain_pit, Word32 *gain_code, + Word16 gcode0,Word16 exp_gcode0,const Word16 *cdbk, const Word16 size ); + +/*==========================================================================*/ +/* FUNCTION : Es_pred_enc_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Calculation and quantization of average predicted innovation energy to be*/ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ Word16 L_frame, i : length of the frame Q0 */ +/* _ Word16 *res, i : residual signal Q_new */ +/* _ Word16 *voicing, i : normalized correlation in three 1/2frames Q15*/ +/* _ Word16 coder_type, i : coder_type Q0 */ +/* _ Word16 bwidth, i : input signal bandwidth Q0 */ +/* _ Word32 core_brate, i : core bitrate Q0 */ +/* _ Word16 Q_new i : Scaling in speech Q0 */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ Word16 *Es_pred, o : predicited scaled innovation energy Q8 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None. */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*--------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*==========================================================================*/ + +void Es_pred_enc_fx( + Word16 *Es_pred, /* o : predicited scaled innovation energy Q8 */ + Word16 *indice, /* o : indice of quantization */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 *res, /* i : residual signal */ + const Word16 *voicing, /* i : normalized correlation in three 1/2frames */ + const Word16 nb_bits, /* i : allocated number of bits */ + const Word16 no_ltp, /* i : no_ltp flag */ + Word16 Q_new /* i : Scaling in speech Q0 */ +) +{ + Word16 i, i_subfr,size, tmp16, tmp16_2, Q_res; + Word16 weight; + Word16 s0,s1, ener_dB, mean_ener_code16; + const Word16 *qua_table; + Word32 ener_fx, Lmean_ener_code, Ltmp; + + Lmean_ener_code = L_deposit_l(0); + Q_res = sub(shl(Q_new, 1), 3); + + IF( EQ_16(L_frame,L_FRAME)) + { + weight = 8192; + move16();/*0.25f in Q15*/ + } + ELSE /* L_frame == L_FRAME16k */ + { + weight = 6554; + move16();/*0.2f in Q15*/ + } + + /*----------------------------------------------------------* + * calculate the average residual signal energy in four sframes + *----------------------------------------------------------*/ + + FOR (i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR) + { + /* calculate the energy of residual signal */ + tmp16 = mult_r(res[i_subfr+0], 8192); /* remove 2bits */ + ener_fx = L_mult(tmp16, tmp16); + FOR (i=1; i, -2,, -2 and 2 */ + const Word16 clip_gain /* i : gain pitch clipping flag (1 = clipping) */ + +) +{ + + Word16 index, size, nBits, nBits2; + Word16 gcode0, Ei, gain_code16; + const Word16 *qua_table; + Word16 coeff[5], exp_coeff[5]; + Word16 exp, exp_code, exp_inov, exp_gcode0, frac, tmp; + Word32 L_tmp, L_tmp1, L_tmp2; + Word16 tmp1, expg; + Word16 exp1, exp2; + Word16 exp_num, exp_den, exp_div, frac_den; + Word32 L_frac_num, L_frac_den, L_div; + + /*-----------------------------------------------------------------* + * calculate the rest of the correlation coefficients + * c2 = , c3 = -2, c4 = 2 + *-----------------------------------------------------------------*/ + + coeff[0] = g_corr[0]; + move16(); + exp_coeff[0] = g_corr[1]; + move16(); + coeff[1] = negate(g_corr[2]); + move16(); /* coeff[1] = -2 xn yy1 */ + exp_coeff[1] = add(g_corr[3], 1); + move16(); + + /* Compute scalar product */ + coeff[2] = extract_h(Dot_product12(y2, y2, L_SUBFR, &exp)); + exp_coeff[2] = add(sub(exp, 18), shl(Q_xn, 1)); + move16(); /* -18 (y2 Q9) */ + + /* Compute scalar product -2* */ + coeff[3] = extract_h(L_negate(Dot_product12(xn, y2, L_SUBFR, &exp))); + exp_coeff[3] = add(sub(exp, 9 - 1), Q_xn); + move16(); /* -9 (y2 Q9), +1 (2 xn y2) */ + + /* Compute scalar product 2* */ + coeff[4] = extract_h(Dot_product12(y1, y2, L_SUBFR, &exp)); + exp_coeff[4] = add(sub(exp, 9 - 1), Q_xn); + move16(); /* -9 (y2 Q9), +1 (2 y1 y2) */ + + /*-----------------------------------------------------------------* + * calculate the unscaled innovation energy + * calculate the predicted gain code + *-----------------------------------------------------------------*/ + + /* gain_inov = 1.0f / sqrt((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */ + L_tmp = Dot_product12(code, code, L_SUBFR, &exp_code); + exp_inov = sub(exp_code, 18+6); + exp_code = sub(exp_code, 30); + + /*Ei = 10 * log10((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */ + + /*----------------------------------------------------------------* + * calculate the predicted gain code + *----------------------------------------------------------------*/ + tmp = norm_l(L_tmp); + frac = Log2_norm_lc(L_shl(L_tmp, tmp)); + tmp = add(30-18-6-1, sub(exp_code, tmp)); /* exp: -18 (code in Q9), -6 (/L_SUBFR) */ + L_tmp1 = Mpy_32_16(tmp, frac, 12330); /* Q13 */ + Ei = round_fx(L_shl(L_tmp1, 11)); /* Q8 */ + + /* predicted codebook gain */ + gcode0 = sub(Es_pred, Ei); /* Q8 */ + + /*---------------------------------------------------------------* + * Decode codebook gain and the adaptive excitation low-pass + * filtering factor (Finalize computation ) + *---------------------------------------------------------------*/ + /* gain_inov = 1.0f / sqrt((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */ + L_tmp = Isqrt_lc(L_tmp, &exp_inov); + *gain_inov = extract_h(L_shl(L_tmp, sub(exp_inov, 3))); /* gain_inov in Q12 */ + + /* gcode0 = pow(10, 0.05 * (Es_pred - Ei)) */ + /*----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *----------------------------------------------------------------*/ + + L_tmp = L_mult(gcode0, 21771); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */ + + gcode0 = extract_l(Pow2(14, frac)); /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + + /*-----------------------------------------------------------------* + * select the codebook, size and number of bits + * set the gains searching range + *-----------------------------------------------------------------*/ + IF( EQ_16(L_frame,L_FRAME)) + { + nBits = gain_bits_tbl[BIT_ALLOC_IDX_fx(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_fx(tc_subfr))]; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + nBits = gain_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ_fx(tc_subfr)) ]; + move16(); + } + test(); + test(); + test(); + test(); + test(); + IF( (EQ_16(tc_subfr,3*L_SUBFR)&&EQ_16(i_subfr,3*L_SUBFR)&&EQ_16(L_frame,L_FRAME))|| + (EQ_16(tc_subfr,4*L_SUBFR) && EQ_16(i_subfr,4*L_SUBFR) && EQ_16(L_frame,L_FRAME16k) ) ) + { + /* *gain_pit = (g_corr[2]*tmp2) - (0.5f*g_corr[4]*tmp3); + = ((-0.5f*g_corr[1]*g_corr[2]) - (-0.25*g_corr[3]*g_corr[4]))/tmp1; + = ((0.25*g_corr[3]*g_corr[4]) - (0.5*g_corr[1]*g_corr[2]))/tmp1; */ + + /* *gain_code = (g_corr[0]*tmp3) - (0.5f*g_corr[4]*tmp2); + = ((-0.5*g_corr[3]*g_corr[0]) - (-0.25*g_corr[1]*g_corr[4]))/tmp1; + = ((0.25*g_corr[1]*g_corr[4]) - (0.5*g_corr[0]*g_corr[3]))/tmp1; */ + + L_tmp1 = L_mult(coeff[0],coeff[2]); /*Q31*/ + exp1 = add(exp_coeff[0], exp_coeff[2]); + + L_tmp2 = L_shr(L_mult(coeff[4],coeff[4]),2); /*Q31*/ + exp2 = add(exp_coeff[4], exp_coeff[4]); + + IF(GT_16(exp1,exp2)) + { + L_tmp2 = L_shr(L_tmp2,sub(exp1,exp2)); /*Q31*/ + exp_den = exp1; + move16(); + } + ELSE + { + L_tmp1 = L_shr(L_tmp1,sub(exp2,exp1)); /*Q31*/ + exp_den = exp2; + move16(); + } + L_frac_den = L_sub(L_tmp1,L_tmp2); /*Q31*/ + + frac_den = extract_h(L_frac_den); + frac_den = s_max(frac_den,1); + L_frac_den = L_max(L_frac_den,1); + exp = norm_l(L_frac_den); + tmp = div_s(shl(1,sub(14,exp)),frac_den); /*Q(14-exp)*/ + + L_tmp1 = L_shr(L_mult(coeff[3],coeff[4]),2); /*Q31*/ + exp1 = add(exp_coeff[3], exp_coeff[4]); + + L_tmp2 = L_shr(L_mult(coeff[1],coeff[2]),1); /*Q31*/ + exp2 = add(exp_coeff[1], exp_coeff[2]); + + IF(GT_16(exp1,exp2)) + { + L_tmp2 = L_shr(L_tmp2,sub(exp1,exp2)); /*Q31*/ + exp_num = exp1; + move16(); + } + ELSE + { + L_tmp1 = L_shr(L_tmp1,sub(exp2,exp1)); /*Q31*/ + exp_num = exp2; + move16(); + } + L_frac_num = L_sub(L_tmp1,L_tmp2); /*Q31*/ + + L_div = Mult_32_16(L_frac_num,tmp); /*Q(30-exp)*/ + exp_div = sub(exp_num,exp_den); + + *gain_pit = round_fx(L_shl(L_div,add(exp,exp_div))); /*Q14*/ + + L_tmp1 = L_shr(L_mult(coeff[1],coeff[4]),2); /*Q31*/ + exp1 = add(exp_coeff[1], exp_coeff[4]); + + L_tmp2 = L_shr(L_mult(coeff[0],coeff[3]),1); /*Q31*/ + exp2 = add(exp_coeff[0], exp_coeff[3]); + + IF(GT_16(exp1,exp2)) + { + L_tmp2 = L_shr(L_tmp2,sub(exp1,exp2)); /*Q31*/ + exp_num = exp1; + } + ELSE + { + L_tmp1 = L_shr(L_tmp1,sub(exp2,exp1)); /*Q31*/ + exp_num = exp2; + } + L_frac_num = L_sub(L_tmp1,L_tmp2); /*Q31*/ + + L_div = Mult_32_16(L_frac_num,tmp); /*Q(30-exp)*/ + exp_div = sub(exp_num,exp_den); + + *gain_code = L_shl(L_div,sub(add(exp,exp_div),14)); + move32();/*Q16*/ + + *gain_pit = s_max(G_PITCH_MIN_TC192_Q14,s_min(*gain_pit,G_PITCH_MAX_TC192_Q14)); + + /* set number of bits for two SQs */ + nBits2 = shr(add(nBits,1),1); + nBits = shr(nBits,1); + + /* gain_pit Q */ + + tmp1 = mult_r(G_PITCH_MAX_MINUS_MIN_TC192_Q13,div_s(1,sub(shl(1, nBits), 1))); /*Q13*/ /* set quantization step */ + index = usquant_fx( *gain_pit, gain_pit, G_PITCH_MIN_TC192_Q14, tmp1, shl(1, nBits) ); + move16(); + push_indice_fx( st_fx, IND_GAIN_PIT, index, nBits ); + + /* gain_code Q */ + /**gain_code /= gcode0;*/ + IF(gcode0 != 0) + { + tmp = div_s(16384,gcode0); /*Q15*/ + L_tmp = Mult_32_16(*gain_code,tmp); /*Q16*/ + *gain_code = L_shr(L_tmp,add(14,exp_gcode0)); /*Q16*/ + } + + index = gain_quant_fx( gain_code, &gain_code16, LG10_G_CODE_MIN_TC192_Q14, LG10_G_CODE_MAX_TC192_Q13, nBits2, &expg ); + push_indice_fx( st_fx, IND_GAIN_CODE, index, nBits2 ); + L_tmp = L_mult(gain_code16,gcode0); /*Q0*Q0 -> Q1*/ + *gain_code = L_shl(L_tmp,add(add(expg,exp_gcode0),15)); /*Q16*/ + } + ELSE + { + size = extract_l(pow2[nBits]); + + SWITCH ( nBits ) + { + case 7: + { + qua_table = gain_qua_mless_7b_fx; + move16(); + if ( EQ_16(clip_gain,1))size=sub(size,30); + BREAK; + } + case 6: + { + qua_table = gain_qua_mless_6b_fx; + move16(); + if ( EQ_16(clip_gain,1))size=sub(size,14); + BREAK; + } + case 5: + { + qua_table = gain_qua_mless_5b_fx; + move16(); + if ( EQ_16(clip_gain,1))size=sub(size,6); + BREAK; + } + default: + { + qua_table = gain_qua_mless_6b_fx; + move16(); + if ( EQ_16(clip_gain,1))size=sub(size,14); + BREAK; + } + } + + /* in case of AVQ inactive, limit the gain_pit to 0.65 */ + test(); + IF( EQ_16(clip_gain,2)&&EQ_16(nBits,6)) + { + size = sub(size,36); + nBits = sub(nBits,1); + } + + /*-----------------------------------------------------------------* + * search for the best quantizer + *-----------------------------------------------------------------*/ + index = Find_Opt_gainQ_fx(coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, qua_table, size); + push_indice_fx( st_fx, IND_GAIN, index, nBits ); + } + + /* *norm_gain_code = *gain_code / *gain_inov; */ + exp = sub(norm_s(*gain_inov),1); + exp = s_max(exp, 0); + + tmp = div_s(shr(8192,exp),*gain_inov); + *norm_gain_code = L_shr(Mult_32_16(*gain_code, tmp),sub(1,exp)); + move32(); + + return; +} + + +/*---------------------------------------------------------------------* +* gain_enc_SQ() +* +* Scalar Quantization of pitch and codebook gains without prediction +* - an initial predicted gain, gcode0, is first determined based on +* the predicted scaled innovation energy +* - a correction factor gamma = g_code / gcode0 is then vector quantized +* along with gain_pit +* - the mean-squared weighted error criterion is used for codebook search +*---------------------------------------------------------------------*/ + +void gain_enc_SQ_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 coder_type, /* i : coding type */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 *xn, /* i : target vector Q_xn */ + const Word16 *yy1, /* i : zero-memory filtered adaptive excitation Q_xn */ + const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation Q9 */ + const Word16 *code, /* i : algebraic excitation Q9 */ + const Word16 Es_pred, /* i : predicted scaled innovation energy Q8 */ + Word16 *gain_pit, /* o : quantized pitch gain Q14 */ + Word32 *gain_code, /* o : quantized codebook gain Q16 */ + Word16 *gain_inov, /* o : gain of the innovation (used for normalization) Q12 */ + Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation Q16 */ + Word16 *g_corr, /* i/o: correlations , ,, -2 and 2 */ + const Word16 clip_gain, /* i : gain pitch clipping flag (1 = clipping) */ + const Word16 Q_xn /* i : xn and y1 scaling */ +) +{ + Word16 index, nBits_pitch, nBits_code; + Word16 gcode0, Ei, gain_code16; + Word16 coeff[5], exp_coeff[5]; + Word16 exp, exp_code, exp_inov, exp_gcode0, frac, tmp; + + Word32 L_tmp, L_tmp1, L_tmp2; + Word16 tmp1, expg; + Word16 exp1, exp2; + Word16 exp_num, exp_den, exp_div, frac_den; + Word32 L_frac_num, L_frac_den, L_div; + + /*-----------------------------------------------------------------* + * calculate the rest of the correlation coefficients + * c2 = , c3 = -2, c4 = 2 + *-----------------------------------------------------------------*/ + /*g_corr[1] *= -0.5;*/ + /*g_corr[2] = dotp( y2, y2, L_SUBFR ) + 0.01f;*/ + /*g_corr[3] = dotp( xn, y2, L_SUBFR ) - 0.02f;*/ + /*g_corr[4] = dotp( yy1, y2, L_SUBFR ) + 0.02f;*/ + + coeff[0] = g_corr[0]; + move16(); + exp_coeff[0] = g_corr[1]; + move16(); + coeff[1] = g_corr[2]; + move16(); /* coeff[1] = xn yy1 */ + exp_coeff[1] = g_corr[3]; + move16(); + + /* Compute scalar product */ + coeff[2] = extract_h(Dot_product12(y2, y2, L_SUBFR, &exp)); + exp_coeff[2] = add(sub(exp, 18), shl(Q_xn, 1)); + move16(); /* -18 (y2 Q9) */ + + /* Compute scalar product */ + coeff[3] = extract_h(Dot_product12(xn, y2, L_SUBFR, &exp)); + exp_coeff[3] = add(sub(exp, 9 ), Q_xn); + move16(); /* -9 (y2 Q9), (xn y2) */ + + /* Compute scalar product */ + coeff[4] = extract_h(Dot_product12(yy1, y2, L_SUBFR, &exp)); + exp_coeff[4] = add(sub(exp, 9), Q_xn); + move16(); /* -9 (y2 Q9), (y1 y2) */ + + /*-----------------------------------------------------------------* + * calculate the unscaled innovation energy + * calculate the predicted gain code + * calculate optimal gains + *-----------------------------------------------------------------*/ + /*Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR;*/ + /**gain_inov = 1.0f / (float)sqrt( Ecode );*/ + + L_tmp = Dot_product12(code, code, L_SUBFR, &exp_code); + exp_inov = sub(exp_code, 18+6); + exp_code = sub(exp_code, 30); + + /*Ei = 10 * log10((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */ + /*----------------------------------------------------------------* + * calculate the predicted gain code + *----------------------------------------------------------------*/ + tmp = norm_l(L_tmp); + frac = Log2_norm_lc(L_shl(L_tmp, tmp)); + tmp = add(30-18-6-1, sub(exp_code, tmp)); /* exp: -18 (code in Q9), -6 (/L_SUBFR) */ + L_tmp1 = Mpy_32_16(tmp, frac, 12330); /* Q13 */ + Ei = round_fx(L_shl(L_tmp1, 11)); /* Q8 */ + + /* predicted codebook gain */ + gcode0 = sub(Es_pred, Ei); /* Q8 */ + + /*---------------------------------------------------------------* + * Decode codebook gain and the adaptive excitation low-pass + * filtering factor (Finalize computation ) + *---------------------------------------------------------------*/ + /* gain_inov = 1.0f / sqrt((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */ + L_tmp = Isqrt_lc(L_tmp, &exp_inov); + *gain_inov = extract_h(L_shl(L_tmp, sub(exp_inov, 3))); /* gain_inov in Q12 */ + + /* gcode0 = pow(10, 0.05 * (Es_pred - Ei)) */ + /*----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *----------------------------------------------------------------*/ + + L_tmp = L_mult(gcode0, 21771); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */ + + gcode0 = extract_l(Pow2(14, frac)); /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + + + /*tmp1 = (g_corr[0]*g_corr[2]) - (g_corr[4]*g_corr[4]); + tmp2 = g_corr[1]/tmp1; + tmp1 = g_corr[3]/tmp1; + + *gain_pit = (g_corr[2]*tmp2) - (g_corr[4]*tmp1); + *gain_code = (g_corr[0]*tmp1) - (g_corr[4]*tmp2);*/ + + /* *gain_pit = (g_corr[2]*tmp2) - (g_corr[4]*tmp3); + = ((g_corr[1]*g_corr[2]) - (g_corr[3]*g_corr[4]))/tmp1;*/ + + /* *gain_code = (g_corr[0]*tmp3) - (g_corr[4]*tmp2); + = ((g_corr[3]*g_corr[0]) - (g_corr[1]*g_corr[4]))/tmp1;*/ + + L_tmp1 = L_mult(coeff[0],coeff[2]); /*Q31*/ + exp1 = add(exp_coeff[0], exp_coeff[2]); + + L_tmp2 = L_mult(coeff[4],coeff[4]); /*Q31*/ + exp2 = add(exp_coeff[4], exp_coeff[4]); + + IF(GT_16(exp1,exp2)) + { + L_tmp2 = L_shr(L_tmp2,sub(exp1,exp2)); /*Q31*/ + exp_den = exp1; + move16(); + } + ELSE + { + L_tmp1 = L_shr(L_tmp1,sub(exp2,exp1)); /*Q31*/ + exp_den = exp2; + move16(); + } + L_frac_den = L_sub(L_tmp1,L_tmp2); /*Q31*/ + + frac_den = extract_h(L_frac_den); + frac_den = s_max(frac_den,1); + L_frac_den = L_max(L_frac_den,1); + exp = norm_l(L_frac_den); + tmp = div_s(shl(1,sub(14,exp)),frac_den); /*Q(14-exp)*/ + + + + L_tmp1 = L_mult(coeff[3],coeff[4]); /*Q31*/ + exp1 = add(exp_coeff[3], exp_coeff[4]); + + L_tmp2 = L_mult(coeff[1],coeff[2]); /*Q31*/ + exp2 = add(exp_coeff[1], exp_coeff[2]); + + IF(GT_16(exp1,exp2)) + { + L_tmp2 = L_shr(L_tmp2,sub(exp1,exp2)); /*Q31*/ + exp_num = exp1; + move16(); + } + ELSE + { + L_tmp1 = L_shr(L_tmp1,sub(exp2,exp1)); /*Q31*/ + exp_num = exp2; + move16(); + } + L_frac_num = L_sub(L_tmp2, L_tmp1); /*Q31*/ + + L_div = Mult_32_16(L_frac_num,tmp); /*Q(30-exp)*/ + exp_div = sub(exp_num,exp_den); + + *gain_pit = round_fx(L_shl(L_div,add(exp,exp_div))); /*Q14*/ + + L_tmp1 = L_mult(coeff[1],coeff[4]); /*Q31*/ + exp1 = add(exp_coeff[1], exp_coeff[4]); + + L_tmp2 = L_mult(coeff[0],coeff[3]); /*Q31*/ + exp2 = add(exp_coeff[0], exp_coeff[3]); + + IF(GT_16(exp1,exp2)) + { + L_tmp2 = L_shr(L_tmp2,sub(exp1,exp2)); /*Q31*/ + exp_num = exp1; + } + ELSE + { + L_tmp1 = L_shr(L_tmp1,sub(exp2,exp1)); /*Q31*/ + exp_num = exp2; + } + L_frac_num = L_sub(L_tmp2, L_tmp1); /*Q31*/ + + L_div = Mult_32_16(L_frac_num,tmp); /*Q(30-exp)*/ + exp_div = sub(exp_num,exp_den); + + *gain_code = L_shl(L_div,s_max(-31,sub(add(exp,exp_div),14))); + move32();/*Q16*/ + + *gain_pit = s_max(G_PITCH_MIN_Q14,s_min(*gain_pit,G_PITCH_MAX_Q14)); + + /*-----------------------------------------------------------------* + * limit the pitch gain searching range (if indicated by clip_gain) + *-----------------------------------------------------------------*/ + + test(); + test(); + IF( EQ_16(clip_gain,1)&>_16(*gain_pit,15565)) + { + *gain_pit = 15565; + move16(); + } + ELSE IF( EQ_16(clip_gain,2)&>_16(*gain_pit,10650)) + { + *gain_pit = 10650; + move16(); + } + + /*-----------------------------------------------------------------* + * search for the best quantized values + *-----------------------------------------------------------------*/ + + nBits_pitch = gain_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ_fx(tc_subfr)) ]; + + /* set number of bits for two SQs */ + nBits_code = shr(add(nBits_pitch,1),1); + nBits_pitch = shr(nBits_pitch,1); + + /* gain_pit Q */ + /*tmp1 = (G_PITCH_MAX - G_PITCH_MIN) / ((1 << nBits_pitch) - 1);*/ /* set quantization step */ + tmp1 = mult_r(G_PITCH_MAX_Q13,div_s(1,sub(shl(1, nBits_pitch), 1))); /*Q13*/ /* set quantization step */ + + index = usquant_fx( *gain_pit, gain_pit, G_PITCH_MIN_Q14, tmp1, shl(1, nBits_pitch) ); + move16(); + push_indice_fx( st_fx, IND_GAIN_PIT, index, nBits_pitch ); + + /* gain_code Q */ + /* *gain_code /= gcode0; */ + IF(gcode0 != 0) + { + tmp = div_s(16384,gcode0); /*Q15*/ + L_tmp = Mult_32_16(*gain_code,tmp); /*Q16*/ + *gain_code = L_shr(L_tmp,add(14,exp_gcode0)); /*Q16*/ + } + + index = gain_quant_fx( gain_code, &gain_code16, LG10_G_CODE_MIN_Q14, LG10_G_CODE_MAX_Q13, nBits_code, &expg ); + push_indice_fx( st_fx, IND_GAIN_CODE, index, nBits_code ); + L_tmp = L_mult(gain_code16,gcode0); /*Q0*Q0 -> Q1*/ + *gain_code = L_shl(L_tmp,add(add(expg,exp_gcode0),15)); + move32(); /*Q16*/ + + /* *norm_gain_code = *gain_code / *gain_inov; */ + exp = sub(norm_s(*gain_inov),1); + exp = s_max(exp, 0); + + tmp = div_s(shr(8192,exp),*gain_inov); + *norm_gain_code = L_shr(Mult_32_16(*gain_code, tmp),sub(1,exp)); + move32(); + + return; +} + +/*-------------------------------------------------------------------* + * gain_enc_gaus() + * + * Quantization of gain for Gaussian codebook + *-------------------------------------------------------------------*/ +Word16 gain_enc_gaus_fx( /* o : Return index of quantization */ + Word32 *gain, /* i/o: Code gain to quantize */ + const Word16 bits, /* i : number of bits to quantize */ + const Word16 lowBound, /* i : lower bound of quantizer (dB) Q8 */ + const Word16 stepSize, /* i : Step size choice Q14 */ + const Word16 inv_stepSize /* i : Step size choice Q15 */ +) +{ + Word16 index, exp_gain, frac_gain, wtmp; + Word16 enr_q, wenr; + Word32 Ltmp, enr; + + /*enr = 20.0 * log10(*gain + 0.001) codebook gain in dB */ + exp_gain = norm_l(*gain); + frac_gain = Log2_norm_lc(L_shl(*gain, exp_gain)); + exp_gain = sub(30-16, exp_gain); + + enr = Mpy_32_16(exp_gain, frac_gain, LG10); /* Output in Q13 */ + wenr = extract_h(L_shl(enr, 8+3)); + + /*----------------------------------------------------------------* + * Quantize linearly the log E + *----------------------------------------------------------------*/ + + wtmp = sub(wenr, lowBound); /* Q8 */ + + index = extract_l(L_shr(L_mac(8388608, wtmp, inv_stepSize),16+8)); + + /* index [0 (1< Q26 */ + enr = L_shr(enr, 10); /*Q26->Q16*/ + frac_gain = L_Extract_lc(enr, &exp_gain); + + Ltmp = Pow2(14, frac_gain); /* Put 14 as exponent */ + exp_gain= sub(exp_gain, 14); /* Retreive exponent of wtmp */ + *gain = L_shl(Ltmp ,add(16,exp_gain)); + move32(); /*Q16*/ + + return index; +} +/*-----------------------------------------------------------------* + * gain_enc_tc() + * + * Search and quantization of gain_code for subframes (in the + * beginning of frame) without pulses in TC - 3b coding. + * In this case: + * - gain_pit = 0 + * - gain_code - scalar quantization (no prediciton history used) + *-----------------------------------------------------------------*/ +void gain_enc_tc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 xn_fx[], /* i : target vector */ + const Word16 y2_fx[], /* i : zero-memory filtered algebraic codebook excitation */ + const Word16 code_fx[], /* i : algebraic excitation */ + const Word16 Es_pred_fx, /* i : predicted scaled innovation energy */ + Word16 *gain_pit_fx, /* o : Pitch gain / Quantized pitch gain */ + Word32 *gain_code_fx, /* o : quantized codebook gain */ + Word16 *gain_inov_fx, /* o : innovation gain */ + Word32 *norm_gain_code_fx, /* o : norm. gain of the codebook excitation */ + const Word16 Q_xn /* i : xn and y1 scaling Q0 */ +) +{ + Word16 i, index=0, nBits, num, den, exp_num, exp_den; + Word16 Ei_fx, g_code_fx, gcode0_fx; + Word16 expg, expg2, e_tmp, f_tmp, exp_gcode0, tmp_fx, frac,tmp16; + Word32 L_tmp, L_tmp1; + Word16 wgain_code=0, gain_code16; + *gain_pit_fx = 0; + move16(); + /*----------------------------------------------------------------* + * get number of bits for gain quantization + *----------------------------------------------------------------*/ + IF( EQ_16(L_frame,L_FRAME)) + { + nBits = gain_bits_tbl[BIT_ALLOC_IDX_fx(core_brate, TRANSITION, i_subfr, TC_SUBFR2IDX_fx(tc_subfr))]; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + nBits = gain_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(core_brate, TRANSITION, i_subfr, TC_SUBFR2IDX_16KHZ_fx(tc_subfr))]; + move16(); + } + + /*----------------------------------------------------------------* + * find the code pitch (for current subframe) + *----------------------------------------------------------------*/ + + /**gain_code = dotp( xn, y2, L_SUBFR )/( dotp( y2, y2, L_SUBFR ) + 0.01f );*/ + /* Compute scalar product */ + L_tmp = Dot_product(y2_fx, y2_fx, L_SUBFR); /* -18 (y2 Q9) */ + exp_den = norm_l(L_tmp); + den = extract_h(L_shl(L_tmp, exp_den)); + exp_den = sub(add(exp_den, 18), shl(Q_xn, 1)); + + /* Compute scalar product */ + L_tmp1 = Dot_product(xn_fx, y2_fx, L_SUBFR); /* -9 (y2 Q9) */ + exp_num = sub(norm_l(L_tmp1),1); + num = extract_h(L_shl(L_tmp1, exp_num)); + exp_num = sub(add(exp_num, 8 ), Q_xn); + + tmp16 = s_or(shr(num, 16), 1); /* extract sign if num < 0 tmp16 = -1 else tmp16 = 1 */ + num = abs_s(num); + + /*----------------------------------------------------------------* + * compute gain = xy/yy + *----------------------------------------------------------------*/ + g_code_fx = div_s(num, den); + + i = sub(exp_num, exp_den); /* Gain_trans in Q7 */ + g_code_fx = i_mult2(g_code_fx, tmp16); /* apply sign */ + *gain_code_fx = L_shr(L_deposit_l(g_code_fx),i); + move32(); + + /*----------------------------------------------------------------* + * calculate the predicted gain code + * decode codebook gain + *----------------------------------------------------------------*/ + + *gain_pit_fx = 0; + move16(); + + /*Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR; + *gain_inov = 1.0f / (float)sqrt( Ecode );*/ + + L_tmp = Dot_product12(code_fx, code_fx, L_SUBFR, &expg); + expg = sub(expg, 18 + 6); /* exp: -18 (code in Q9), -6 (/L_SUBFR) */ + expg2 = expg; + move16(); + L_tmp1 = L_tmp; /* sets to 'L_tmp' in 1 clock */ + move32(); + L_tmp = Isqrt_lc(L_tmp, &expg); + + *gain_inov_fx = extract_h(L_shl(L_tmp, sub(expg, 3))); + move16();/* gain_inov in Q12 */ + + /*Ei = 10 * (float)log10( Ecode );*/ + e_tmp = norm_l(L_tmp1); + f_tmp = Log2_norm_lc(L_shl(L_tmp1, e_tmp)); + e_tmp = sub(expg2,add(1,e_tmp)); + L_tmp1 = Mpy_32_16(e_tmp, f_tmp, 12330); /* Q13 */ /* 10*log10(2) in Q12*/ + Ei_fx = round_fx(L_shl(L_tmp1, 11)); /* Q8 */ + /*gcode0 = (float) pow(10, 0.05 * (Es_pred - Ei));*/ + gcode0_fx = sub(Es_pred_fx, Ei_fx); /* Q8 */ + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *-----------------------------------------------------------------*/ + L_tmp = L_mult(gcode0_fx, 21771); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */ + gcode0_fx = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + exp_gcode0 = sub(exp_gcode0, 14); + IF( GT_16(nBits,3)) + { + /*g_code = *gain_code / gcode0;*/ + IF(gcode0_fx != 0) + { + tmp16 = div_s(16384,gcode0_fx); /*Q15*/ + L_tmp = Mult_32_16(*gain_code_fx,tmp16); /*Q16*/ + *gain_code_fx = L_shr(L_tmp,add(14,exp_gcode0)); /*Q16*/ + } + ELSE + { + *gain_code_fx = MAX_32; + move32(); + } + + /*index = gain_quant( &g_code, G_CODE_MIN, G_CODE_MAX, nBits );*/ + index = gain_quant_fx( gain_code_fx, &gain_code16, LG10_G_CODE_MIN_TC_Q14, LG10_G_CODE_MAX_TC_Q13, nBits, &expg ); + + /**gain_code = g_code * gcode0;*/ + L_tmp = L_mult(gain_code16,gcode0_fx); /*Q0*Q0 -> Q1*/ + *gain_code_fx = L_shl(L_tmp,add(add(expg,exp_gcode0),15)); /*Q16*/ move32(); + + push_indice_fx( st_fx, IND_GAIN_CODE, index, nBits ); + } + ELSE + { + index = N_GAIN_CODE_TC-1; + move16(); + FOR( i=0; i < N_GAIN_CODE_TC-1; i++ ) + { + L_tmp = L_mult(tbl_gain_code_tc_quant_mean[i], gcode0_fx); /* Q13*Q0 -> Q14 */ + L_tmp = L_shl(L_tmp, add(exp_gcode0, 2)); /* Q14 -> Q16 */ + + IF( LT_32(*gain_code_fx, L_tmp)) + { + index = i; + move16(); + BREAK; + } + } + /*----------------------------------------------------------------* + * 3-bit -> 2-bit encoding + *----------------------------------------------------------------*/ + IF( EQ_16(nBits,2)) + { + /* 2-bit -> 3-bit decoding */ + index = shr(index ,1); + wgain_code = tbl_gain_code_tc_fx[shl(index,1)]; + move16(); + /**gain_code *= gcode0;*/ + L_tmp = L_mult(wgain_code, gcode0_fx); /* Q13*Q0 -> Q14 */ + *gain_code_fx= L_shl(L_tmp, add(exp_gcode0, 2)); + move32(); /* Q14 -> Q16 */ + push_indice_fx( st_fx, IND_GAIN_CODE, index, nBits ); + } + ELSE /* nBits == 3 */ + { + wgain_code = tbl_gain_code_tc_fx[index]; + move16(); + /**gain_code *= gcode0;*/ + L_tmp = L_mult(wgain_code, gcode0_fx); /* Q13*Q0 -> Q14 */ + *gain_code_fx= L_shl(L_tmp, add(exp_gcode0, 2)); + move32(); /* Q14 -> Q16 */ + push_indice_fx( st_fx, IND_GAIN_CODE, index, nBits ); + } + } + + /*-----------------------------------------------------------------* + * decode normalized codebook gain + *-----------------------------------------------------------------*/ + /**norm_gain_code = *gain_code / *gain_inov;*/ + expg = sub(norm_s(*gain_inov_fx),1); + expg = s_max(expg, 0); + + tmp_fx = div_s(shr(8192,expg),*gain_inov_fx); + *norm_gain_code_fx = L_shr(Mult_32_16(*gain_code_fx, tmp_fx),sub(1,expg)); + move32(); + return; +} +/*-----------------------------------------------------------------* + * Find_Opt_gainQ_fx() + * + * Find the best quantizer + *-----------------------------------------------------------------*/ +static Word16 Find_Opt_gainQ_fx( + Word16 *coeff, + Word16 *exp_coeff, + Word16 *gain_pit, + Word32 *gain_code, + Word16 gcode0, + Word16 exp_gcode0, + const Word16 *cdbk, /* i : Codebook used */ + const Word16 size /* i : size of Codebook used */ +) +{ + Word16 index, i, j; + const Word16 *p; + Word16 g_pitch, g2_pitch, g_code, g_pit_cod, g2_code, g2_code_lo; + Word32 dist_min; + Word16 coeff_lo[5]; + Word16 exp_max[5]; + Word16 exp_code, e_max; + Word32 L_tmp, L_tmp1; + + + /*----------------------------------------------------------------* + * Find the best quantizer + * ~~~~~~~~~~~~~~~~~~~~~~~ + * Before doing the computation we need to align exponents of coeff[] + * to be sure to have the maximum precision. + * + * In the table the pitch gains are in Q14, the code gains are in Q9 and + * are multiply by gcode0 which have been multiply by 2^exp_gcode0. + * Also when we compute g_pitch*g_pitch, g_code*g_code and g_pitch*g_code + * we divide by 2^15. + * Considering all the scaling above we have: + * + * exp_code = exp_gcode0-9+15 = exp_gcode0+6 + * + * g_pitch*g_pitch = -14-14+15 + * g_pitch = -14 + * g_code*g_code = (2*exp_code)+15 + * g_code = exp_code + * g_pitch*g_code = -14 + exp_code +15 + * + * g_pitch*g_pitch * coeff[0] ;exp_max0 = exp_coeff[0] - 13 + * g_pitch * coeff[1] ;exp_max1 = exp_coeff[1] - 14 + * g_code*g_code * coeff[2] ;exp_max2 = exp_coeff[2] +15+(2*exp_code) + * g_code * coeff[3] ;exp_max3 = exp_coeff[3] + exp_code + * g_pitch*g_code * coeff[4] ;exp_max4 = exp_coeff[4] + 1 + exp_code + *----------------------------------------------------------------*/ + + exp_code = add(exp_gcode0, 6); + + exp_max[0] = sub(exp_coeff[0], 13); + move16(); + exp_max[1] = sub(exp_coeff[1], 14); + move16(); + exp_max[2] = add(exp_coeff[2], add(15, shl(exp_code, 1))); + move16(); + exp_max[3] = add(exp_coeff[3], exp_code); + move16(); + exp_max[4] = add(exp_coeff[4], add(1, exp_code)); + move16(); + + /* Find maximum exponant */ + e_max = exp_max[0]; + move16(); + FOR (i = 1; i < 5; i++) + { + e_max = s_max(exp_max[i], e_max); + } + + /* align coeff[] and save in special 32 bit double precision */ + FOR (i = 0; i < 5; i++) + { + j = add(sub(e_max, exp_max[i]), 2); /* /4 to avoid overflow */ + L_tmp = L_deposit_h(coeff[i]); + L_tmp = L_shr(L_tmp, j); + L_Extract(L_tmp, &coeff[i], &coeff_lo[i]); + coeff_lo[i] = shr(coeff_lo[i], 3);/* lo >> 3 */ move16(); + } + + /* searching of codebook */ + p = cdbk; + move16(); + dist_min = L_deposit_h(MAX_16); + index = 0; + move16(); + FOR (i = 0; i < size; i++) + { + g_pitch = *p++; + move16(); + g_code = *p++; + move16(); + + g_code = mult_r(g_code, gcode0); + g2_pitch = mult_r(g_pitch, g_pitch); + g_pit_cod = mult_r(g_code, g_pitch); + L_tmp = L_mult(g_code, g_code); + g2_code_lo = L_Extract_lc(L_tmp, &g2_code); + + L_tmp = L_mult(coeff[2], g2_code_lo); + L_tmp = L_shr(L_tmp, 3); + L_tmp = L_mac(L_tmp, coeff_lo[0], g2_pitch); + L_tmp = L_mac(L_tmp, coeff_lo[1], g_pitch); + L_tmp = L_mac(L_tmp, coeff_lo[2], g2_code); + L_tmp = L_mac(L_tmp, coeff_lo[3], g_code); + L_tmp = L_mac(L_tmp, coeff_lo[4], g_pit_cod); + L_tmp = L_shr(L_tmp, 12); + L_tmp = L_mac(L_tmp, coeff[0], g2_pitch); + L_tmp = L_mac(L_tmp, coeff[1], g_pitch); + L_tmp = L_mac(L_tmp, coeff[2], g2_code); + L_tmp = L_mac(L_tmp, coeff[3], g_code); + L_tmp = L_mac(L_tmp, coeff[4], g_pit_cod); + + L_tmp1 = L_sub(L_tmp, dist_min); + if (L_tmp1 < 0) + { + index = i; + move16(); + } + dist_min = L_min(L_tmp, dist_min); + } + + p = &cdbk[add(index, index)]; + move16(); + + *gain_pit = *p++; /* selected pitch gain in Q14 */ move16(); + g_code = *p++; /* selected code gain in Q9 */ move16(); + + L_tmp = L_mult(g_code, gcode0); /* Q9*Q0 -> Q10 */ + L_tmp = L_shl(L_tmp, add(exp_gcode0, 6)); /* Q10 -> Q16 */ + + *gain_code = L_tmp; /* gain of code in Q16 */ move16(); + return index; +} +/*---------------------------------------------------------------------* + * gain_enc_lbr() + * + * Quantization of pitch and codebook gains without prediction (memory-less) + * in ACELP at 6.6 and 7.5 kbps + * - the gain codebooks and gain estimation constants are different in each subframe + * - the estimated gain, gcode0, is first determined based on + * classification and/or previous quantized gains (from previous subframes in the current frame) + * - a correction factor gamma = g_code / gcode0 is then vector quantized + * along with gain_pit + * - the mean-squared error criterion is used for codebook search + *---------------------------------------------------------------------*/ + +void gain_enc_lbr_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 coder_type, /* i : coding type */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 *xn, /* i : target vector Q_xn*/ + const Word16 *y1, /* i : zero-memory filtered adaptive excitation Q_xn*/ + const Word16 Q_xn, /* i : xn and y1 format */ + const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation Q9*/ + const Word16 *code, /* i : algebraic excitation Q9*/ + Word16 *gain_pit, /* o : quantized pitch gain Q14*/ + Word32 *gain_code, /* o : quantized codebook gain Q16*/ + Word16 *gain_inov, /* o : gain of the innovation (used for normalization) Q12*/ + Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation Q16*/ + Word16 *g_corr, /* i/o: correlations , -2,, -2 and 2 mant/exp*/ + Word32 gc_mem[], /* i/o: gain_code from previous subframes */ + Word16 gp_mem[], /* i/o: gain_pitch from previous subframes */ + const Word16 clip_gain /* i : gain pitch clipping flag (1 = clipping) */ +) +{ + + Word16 index = 0, size, nBits, n_pred, ctype; + const Word16 *b, *cdbk = 0; + Word16 gcode0, aux[10]; + Word16 coeff[5], exp_coeff[5]; + Word16 exp, exp_code, exp_inov, exp_gcode0, frac, tmp; + Word32 L_tmp, L_tmp1, L_inov; + + /*-----------------------------------------------------------------* + * calculate the rest of the correlation coefficients + * c2 = , c3 = -2, c4 = 2, c5* = + * c5* - not necessary to calculate + *-----------------------------------------------------------------*/ + + coeff[0] = g_corr[0]; + move16(); + exp_coeff[0] = g_corr[1]; + move16(); + coeff[1] = negate(g_corr[2]); + move16(); /* coeff[1] = -2 xn yy1 */ + exp_coeff[1] = add(g_corr[3], 1); + move16(); + + /* Compute scalar product */ + + coeff[2] = extract_h(Dot_product12(y2, y2, L_SUBFR, &exp)); + exp_coeff[2] = add(sub(exp, 18), shl(Q_xn, 1)); /* -18 (y2 Q9) */ move16(); + + /* Compute scalar product -2* */ + + coeff[3] = extract_h(L_negate(Dot_product12(xn, y2, L_SUBFR, &exp))); + exp_coeff[3] = add(sub(exp, 9 - 1), Q_xn); /* -9 (y2 Q9), +1 (2 xn y2) */ move16(); + + /* Compute scalar product 2* */ + + coeff[4] = extract_h(Dot_product12(y1, y2, L_SUBFR, &exp)); + exp_coeff[4] = add(sub(exp, 9 - 1), Q_xn); /* -9 (y2 Q9), +1 (2 yy1 y2) */ move16(); + + /*g_corr[2] += 0.01F; g_corr[3] -= 0.02F; g_corr[4] += 0.02F;*/ + + /*Ecode = ( dotp( code, code, L_SUBFR ) + 0.01f ) / L_SUBFR; + *gain_inov = 1.0f / (float)sqrt(Ecode);*/ + L_tmp = Dot_product12(code, code, L_SUBFR, &exp_code); + L_inov = L_tmp; /* sets to 'L_tmp' in 1 clock */ + move32(); + /* exp_code: -18 (code in Q9), -6 (/L_SUBFR), -31 (L_tmp Q31->Q0) */ + /* output gain_inov*/ + exp_inov = sub(exp_code, 18 + 6); + L_inov = Isqrt_lc(L_inov, &exp_inov); + *gain_inov = extract_h(L_shl(L_inov, sub(exp_inov, 3))); /* gain_inov in Q12 */ + + + /*-----------------------------------------------------------------* + * select the codebook, size and number of bits + * set the gains searching range + *-----------------------------------------------------------------*/ + + nBits = gain_bits_tbl[BIT_ALLOC_IDX_fx(core_brate, coder_type, i_subfr, 0)]; + move16(); + size = extract_l(pow2[nBits]); + + ctype = shl(sub(coder_type, 1), 1); + + /*-----------------------------------------------------------------* + * calculate prediction of gcode + * search for the best codeword + *-----------------------------------------------------------------*/ + IF (i_subfr == 0) + { + b = b_1sfr_fx; + move16(); + n_pred = 2; + move16(); + + SWITCH ( nBits ) + { + case 8: + { + cdbk = gp_gamma_1sfr_8b_fx; + move16(); + if ( EQ_16(clip_gain,1))size=sub(size,60); + move16(); + BREAK; + } + case 7: + { + cdbk = gp_gamma_1sfr_7b_fx; + move16(); + if ( EQ_16(clip_gain,1))size=sub(size,27); + move16(); + BREAK; + } + case 6: + { + cdbk = gp_gamma_1sfr_6b_fx; + move16(); + if ( EQ_16(clip_gain,1))size=sub(size,10); + move16(); + BREAK; + } + } + + /* calculate predicted gain */ + aux[0] = 4096; + move16(); + aux[1] = shl(ctype,12); + + /* gcode0 = (float)pow(10, dotp(b, aux, n_pred) - 0.5f * (float)log10(Ecode)); + gcode0 = (float)pow(10, dotp(b, aux, n_pred) - 0.05f * 10 * (float)log10(Ecode)); + gcode0 = (float)pow(10, 0.05(20 * dotp(b, aux, n_pred) - 10 * (float)log10(Ecode))); */ + + exp_code = sub(exp_code, 18 + 6 + 1); + exp = norm_l(L_tmp); + frac = Log2_norm_lc(L_shl(L_tmp, exp)); + exp = sub(exp_code,exp); + L_tmp1 = Mpy_32_16(exp, frac, 24660); /* Q14 */ /* 10*log10(2) in Q13*/ + + L_tmp = Dot_product(b, aux, n_pred); /*Q25*/ + L_tmp = Mult_32_16(L_tmp,320);/*Q14, 20 in Q4*/ + L_tmp = L_sub(L_tmp,L_tmp1);/*Q14*/ + + gcode0 = round_fx(L_shl(L_tmp, 10)); /* Q8 */ + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *-----------------------------------------------------------------*/ + + L_tmp = L_mult(gcode0, 21771); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */ + + gcode0 = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + index= Find_Opt_gainQ_fx(coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, cdbk, size); + + gc_mem[0] = *gain_code; + move16(); /*Q16*/ + gp_mem[0] = *gain_pit; + move16();/*Q14*/ + } + ELSE IF (EQ_16(i_subfr,L_SUBFR)) + { + b = b_2sfr_fx; + move16(); + n_pred = 4; + move16(); + + switch ( nBits ) + { + case 7: + { + cdbk = gp_gamma_2sfr_7b_fx; + move16(); + if ( EQ_16(clip_gain,1))size=sub(size,30); + move16(); + BREAK; + } + case 6: + { + cdbk = gp_gamma_2sfr_6b_fx; + move16(); + if ( EQ_16(clip_gain,1))size=sub(size,12); + move16(); + BREAK; + } + } + + /* calculate predicted gain */ + aux[0] = 4096; + move16(); + aux[1] = shl(ctype,12); + move16(); + + /*aux[2] = (float)log10(gc_mem[0]); + = log2(gc_mem[0])*log10(2);*/ + exp = norm_l(gc_mem[0]); + frac = Log2_norm_lc(L_shl(gc_mem[0], exp)); + exp = sub(sub(30,exp),16); /*Q_format(gc_1sfr_fx)=16*/ + L_tmp1 = Mpy_32_16(exp, frac, 9864); + move16(); /* Q16 */ + aux[2] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + aux[3] = shr(gp_mem[0],2); + move16();/*Q12*/ + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, dotp(b, aux, n_pred) + * = pow(2, 3.321928*dotp(b, aux, n_pred) + *-----------------------------------------------------------------*/ + L_tmp = Dot_product(b, aux, n_pred); /*Q25*/ + L_tmp = Mult_32_16(L_tmp, 27213); /* *3.321928 in Q13 -> Q23 */ + L_tmp = L_shr(L_tmp, 7); /* From Q23 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */ + + gcode0 = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + + index= Find_Opt_gainQ_fx(coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, cdbk, size); + gc_mem[1] = *gain_code; + move32(); + gp_mem[1] = *gain_pit; + move16(); + } + ELSE IF (EQ_16(i_subfr,2*L_SUBFR)) + { + b = b_3sfr_fx; + move16(); + n_pred = 6; + move16(); + cdbk = gp_gamma_3sfr_6b_fx; + move16(); + if ( EQ_16(clip_gain,1)) + { + size = sub(size,11); + } + + /* calculate predicted gain */ + aux[0] = 4096; + move16(); + aux[1] = shl(ctype,12); + move16(); + + /*aux[2] = (float)log10(gc_mem[0]); + = log2(gc_mem[0])*log10(2);*/ + exp = norm_l(gc_mem[0]); + frac = Log2_norm_lc(L_shl(gc_mem[0], exp)); + exp = sub(sub(30,exp),16); /*Q_format(gc_mem[0])=16*/ + L_tmp1 = Mpy_32_16(exp, frac, 9864); /* Q16 */ + aux[2] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + /*aux[3] = (float)log10(gc_mem[1]); + = log2(gc_mem[1])*log10(2);*/ + exp = norm_l(gc_mem[1]); + frac = Log2_norm_lc(L_shl(gc_mem[1], exp)); + exp = sub(sub(30,exp),16); /*Q_format(gc_mem[1])=16*/ + L_tmp1 = Mpy_32_16(exp, frac, 9864); /* Q16 */ + aux[3] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + aux[4] = shr(gp_mem[0],2); + move16();/*Q12*/ + aux[5] = shr(gp_mem[1],2); + move16();/*Q12*/ + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, dotp(b, aux, n_pred) + * = pow(2, 3.321928*dotp(b, aux, n_pred) + *-----------------------------------------------------------------*/ + L_tmp = Dot_product(b, aux, n_pred); /*Q25*/ + L_tmp = Mult_32_16(L_tmp, 27213); /* *3.321928 in Q13 -> Q23 */ + L_tmp = L_shr(L_tmp, 7); /* From Q23 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */ + + gcode0 = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + + /*----------------------------------------------------------------* + * Find the best quantizer + * ~~~~~~~~~~~~~~~~~~~~~~~ + * Before doing the computation we need to align exponents of coeff[] + * to be sure to have the maximum precision. + * + * In the table the pitch gains are in Q14, the code gains are in Q9 and + * are multiply by gcode0 which have been multiply by 2^exp_gcode0. + * Also when we compute g_pitch*g_pitch, g_code*g_code and g_pitch*g_code + * we divide by 2^15. + * Considering all the scaling above we have: + * + * exp_code = exp_gcode0-9+15 = exp_gcode0+6 + * + * g_pitch*g_pitch = -14-14+15 + * g_pitch = -14 + * g_code*g_code = (2*exp_code)+15 + * g_code = exp_code + * g_pitch*g_code = -14 + exp_code +15 + * + * g_pitch*g_pitch * coeff[0] ;exp_max0 = exp_coeff[0] - 13 + * g_pitch * coeff[1] ;exp_max1 = exp_coeff[1] - 14 + * g_code*g_code * coeff[2] ;exp_max2 = exp_coeff[2] +15+(2*exp_code) + * g_code * coeff[3] ;exp_max3 = exp_coeff[3] + exp_code + * g_pitch*g_code * coeff[4] ;exp_max4 = exp_coeff[4] + 1 + exp_code + *----------------------------------------------------------------*/ + + index= Find_Opt_gainQ_fx(coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, cdbk, size); + + gc_mem[2] = *gain_code; + move32(); + gp_mem[2] = *gain_pit; + move16(); + } + ELSE IF (EQ_16(i_subfr,3*L_SUBFR)) + { + b = b_4sfr_fx; + move16(); + n_pred = 8; + move16(); + + cdbk = gp_gamma_4sfr_6b_fx; + move16(); + if ( EQ_16(clip_gain,1)) + { + size = sub(size,11); + move16(); + } + + /* calculate predicted gain */ + aux[0] = 4096; + move16(); + aux[1] = shl(ctype,12); + move16(); + + /*aux[2] = (float)log10(gc_mem[0]); + = log2(gc_mem[0])*log10(2);*/ + exp = norm_l(gc_mem[0]); + frac = Log2_norm_lc(L_shl(gc_mem[0], exp)); + exp = sub(sub(30,exp),16); /*Q_format(gc_mem[0])=16*/ + L_tmp1 = Mpy_32_16(exp, frac, 9864); /* Q16 */ + aux[2] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + /*aux[3] = (float)log10(gc_mem[1]); + = log2(gc_mem[1])*log10(2);*/ + exp = norm_l(gc_mem[1]); + frac = Log2_norm_lc(L_shl(gc_mem[1], exp)); + exp = sub(sub(30,exp),16); /*Q_format(gc_mem[1])=16*/ + L_tmp1 = Mpy_32_16(exp, frac, 9864); /* Q16 */ + aux[3] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + + /*aux[4] = (float)log10(gc_mem[2]); + = log2(gc_mem[2])*log10(2);*/ + exp = norm_l(gc_mem[2]); + frac = Log2_norm_lc(L_shl(gc_mem[2], exp)); + exp = sub(sub(30,exp),16); /*Q_format(gc_mem[2])=16*/ + L_tmp1 = Mpy_32_16(exp, frac, 9864); /* Q16 */ + aux[4] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + aux[5] = shr(gp_mem[0],2); + move16();/*Q12*/ + aux[6] = shr(gp_mem[1],2); + move16();/*Q12*/ + aux[7] = shr(gp_mem[2],2); + move16();/*Q12*/ + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, dotp(b, aux, n_pred) + * = pow(2, 3.321928*dotp(b, aux, n_pred) + *-----------------------------------------------------------------*/ + L_tmp = Dot_product(b, aux, n_pred); /*Q25*/ + L_tmp = Mult_32_16(L_tmp, 27213); /* *3.321928 in Q13 -> Q23 */ + L_tmp = L_shr(L_tmp, 7); /* From Q23 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */ + + gcode0 = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + + index = Find_Opt_gainQ_fx(coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, cdbk, size); + } + + /* *norm_gain_code = *gain_code / *gain_inov; */ + exp = sub(norm_s(*gain_inov),1); + exp = s_max(exp, 0); + + tmp = div_s(shr(8192,exp),*gain_inov); + *norm_gain_code = L_shr(Mult_32_16(*gain_code, tmp),sub(1,exp)); + move32(); + { + push_indice_fx( st_fx, IND_GAIN, index, nBits ); + } + return; +} + +/*-------------------------------------------------------------------* + * gain_enc_amr_wb() + * + * Quantization of pitch and codebook gains (used also in AMR-WB IO mode) + * MA prediction is performed on the innovation energy (in dB with mean removed). + * An initial predicted gain, gcode0, is first determined and the correction + * factor alpha = g_code / gcode0 is quantized. + * The pitch gain and the correction factor are vector quantized and the + * mean-squared weighted error criterion is used in the quantizer search. + *-------------------------------------------------------------------*/ + + +void gain_enc_amr_wb_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 *xn, /* i : target vector */ + const Word16 Q_xn, /* i : xn and yy1 format Q0 */ + const Word16 *yy1, /* i : zero-memory filtered adaptive excitation */ + const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation */ + const Word16 *code, /* i : algebraic excitation */ + const Word32 core_brate, /* i : core bitrate */ + Word16 *gain_pit, /* i/o: pitch gain / Quantized pitch gain */ + Word32 *gain_code, /* o : quantized codebook gain */ + Word16 *gain_inov, /* o : gain of the innovation (used for normalization) */ + Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation */ + Word16 *g_coeff, /* i/o: correlations , -2,, -2 and 2 */ + const Word16 clip_gain, /* i : gain pitch clipping flag (1 = clipping) */ + Word16 *past_qua_en /* i/o: gain quantization memory (4 words) */ +) +{ + + Word16 i, j, index, min_ind, size; + Word16 exp, frac, gcode0, exp_gcode0, e_max, exp_code, exp_inov, qua_ener; + Word16 g_pitch, g2_pitch, g_code, g_pit_cod, g2_code, g2_code_lo; + Word16 coeff[5], coeff_lo[5], exp_coeff[5]; + Word16 exp_max[5], tmp, nBits; + Word32 L_tmp, dist_min, L_inov, L_tmp1; + const Word16 *t_qua_gain, *p; + + /*----------------------------------------------------------------* + * Find the initial quantization pitch index + * Set gains search range + *----------------------------------------------------------------*/ + IF (core_brate>= ACELP_12k65) + { + t_qua_gain = t_qua_gain7b_fx; + move16(); + /* pt at 1/4th of table */ + p = t_qua_gain7b_fx + RANGE; + move16(); + + j = NB_QUA_GAIN7B - RANGE; + move16(); + + IF (EQ_16(clip_gain, 1)) + { + j = sub(j, 27); /* limit gain pitch to 1.0 */ + } + min_ind = 0; + move16(); + g_pitch = *gain_pit; + move16(); + + FOR (i = 0; i < j; i++) + { + if (GT_16(g_pitch, *p)) + { + min_ind = add(min_ind, 1); + } + p += 2; + } + size = RANGE; + move16(); + nBits = 7; + } + ELSE + { + t_qua_gain = t_qua_gain6b_fx; + min_ind = 0; + move16(); + size = RANGE; + move16(); + if (EQ_16(clip_gain, 1)) + { + size = sub(size, 16); /* limit gain pitch to 1.0 */ + } + nBits = 6; + } + /*----------------------------------------------------------------* + * Compute coefficients needed for the quantization. + * + * coeff[0] = yy1 yy1 + * coeff[1] = -2 xn yy1 + * coeff[2] = y2 y2 + * coeff[3] = -2 xn y2 + * coeff[4] = 2 yy1 y2 + * + * Product and have been computed in Adpt_enr() and + * are in vector g_coeff[]. + *----------------------------------------------------------------*/ + coeff[0] = g_coeff[0]; + move16(); + exp_coeff[0] = g_coeff[1]; + move16(); + coeff[1] = negate(g_coeff[2]); + move16(); /* coeff[1] = -2 xn yy1 */ + exp_coeff[1] = add(g_coeff[3], 1); + move16(); + + /* Compute scalar product */ + coeff[2] = extract_h(Dot_product12(y2, y2, L_SUBFR, &exp)); + exp_coeff[2] = add(sub(exp, 18), shl(Q_xn, 1)); /* -18 (y2 Q9) */ + + /* Compute scalar product -2* */ + coeff[3] = extract_h(L_negate(Dot_product12(xn, y2, L_SUBFR, &exp))); + exp_coeff[3] = add(sub(exp, 9 - 1), Q_xn); /* -9 (y2 Q9), +1 (2 xn y2) */ + + /* Compute scalar product 2* */ + coeff[4] = extract_h(Dot_product12(yy1, y2, L_SUBFR, &exp)); + exp_coeff[4] = add(sub(exp, 9 - 1), Q_xn); /* -9 (y2 Q9), +1 (2 yy1 y2) */ + + /*----------------------------------------------------------------* + * Find energy of code and compute: + * + * L_tmp = MEAN_ENER - 10log10(energy of code/ L_subfr) + * = MEAN_ENER - 3.0103*log2(energy of code/ L_subfr) + *----------------------------------------------------------------*/ + L_tmp = Dot_product12(code, code, L_SUBFR, &exp_code); + L_inov = L_add(L_tmp, 0); + /* exp_code: -18 (code in Q9), -6 (/L_subfr), -31 (L_tmp Q31->Q0) */ + /* output gain_inov*/ + exp_inov = sub(exp_code, 18 + 6); + L_inov = Isqrt_lc(L_inov, &exp_inov); + *gain_inov = extract_h(L_shl(L_inov, sub(exp_inov, 3))); /* gain_inov in Q12 */ + + exp_code = sub(exp_code, 18 + 6 + 31); + frac = Log2_lc(L_tmp, &exp); + exp = add(exp, exp_code); + L_tmp = Mpy_32_16(exp, frac, -24660); /* x -3.0103(Q13) -> Q14 */ + + L_tmp = L_mac(L_tmp, MEAN_ENER, 8192); /* + MEAN_ENER in Q14 */ + + /*----------------------------------------------------------------* + * predicted codebook gain + *----------------------------------------------------------------*/ + L_tmp = L_shl(L_tmp, 10); /* From Q14 to Q24 */ + L_tmp = L_mac0(L_tmp, pred_gain_fx[0], past_qua_en[0]); /* Q14*Q10 -> Q24 */ + L_tmp = L_mac0(L_tmp, pred_gain_fx[1], past_qua_en[1]); /* Q14*Q10 -> Q24 */ + L_tmp = L_mac0(L_tmp, pred_gain_fx[2], past_qua_en[2]); /* Q14*Q10 -> Q24 */ + L_tmp = L_mac0(L_tmp, pred_gain_fx[3], past_qua_en[3]); /* Q14*Q10 -> Q24 */ + + gcode0 = extract_h(L_tmp); /* From Q24 to Q8 */ + + /*----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *----------------------------------------------------------------*/ + L_tmp = L_mult(gcode0, 5443); /* *0.166096 in Q15 -> Q24 */ + L_tmp = L_shr(L_tmp, 8); /* From Q24 to Q16 */ + L_Extract(L_tmp, &exp_gcode0, &frac); /* Extract exponent of gcode0 */ + + gcode0 = extract_l(Pow2(14, frac)); /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + exp_gcode0 = sub(exp_gcode0, 14); + + /*----------------------------------------------------------------* + * Find the best quantizer + * ~~~~~~~~~~~~~~~~~~~~~~~ + * Before doing the computation we need to aling exponents of coeff[] + * to be sure to have the maximum precision. + * + * In the table the pitch gains are in Q14, the code gains are in Q11 and + * are multiply by gcode0 which have been multiply by 2^exp_gcode0. + * Also when we compute g_pitch*g_pitch, g_code*g_code and g_pitch*g_code + * we divide by 2^15. + * Considering all the scaling above we have: + * + * exp_code = exp_gcode0-11+15 = exp_gcode0+4 + * + * g_pitch*g_pitch = -14-14+15 + * g_pitch = -14 + * g_code*g_code = (2*exp_code)+15 + * g_code = exp_code + * g_pitch*g_code = -14 + exp_code +15 + * + * g_pitch*g_pitch * coeff[0] ;exp_max0 = exp_coeff[0] - 13 + * g_pitch * coeff[1] ;exp_max1 = exp_coeff[1] - 14 + * g_code*g_code * coeff[2] ;exp_max2 = exp_coeff[2] +15+(2*exp_code) + * g_code * coeff[3] ;exp_max3 = exp_coeff[3] + exp_code + * g_pitch*g_code * coeff[4] ;exp_max4 = exp_coeff[4] + 1 + exp_code + *----------------------------------------------------------------*/ + + exp_code = add(exp_gcode0, 4); + + exp_max[0] = sub(exp_coeff[0], 13); + move16(); + exp_max[1] = sub(exp_coeff[1], 14); + move16(); + exp_max[2] = add(exp_coeff[2], + add(15, shl(exp_code, 1))); + move16(); + exp_max[3] = add(exp_coeff[3], exp_code); + move16(); + exp_max[4] = add(exp_coeff[4], + add(1, exp_code)); + move16(); + + /* Find maximum exponant */ + e_max = exp_max[0]; + move16(); + FOR (i = 1; i < 5; i++) + { + e_max = s_max(exp_max[i], e_max); + } + + /* align coeff[] and save in special 32 bit double precision */ + FOR (i = 0; i < 5; i++) + { + j = add(sub(e_max, exp_max[i]), 2); /* /4 to avoid overflow */ + L_tmp = L_deposit_h(coeff[i]); + L_tmp = L_shr(L_tmp, j); + L_Extract(L_tmp, &coeff[i], &coeff_lo[i]); + coeff_lo[i] = shr(coeff_lo[i], 3);/* lo >> 3 */move16(); + } + + /* Codebook search */ + dist_min = L_add(MAX_32, 0); + p = &t_qua_gain[shl(min_ind, 1)]; + move16(); + + index = 0; + move16(); + FOR (i = 0; i < size; i++) + { + g_pitch = *p++; + move16(); + g_code = *p++; + move16(); + + g_code = mult_r(g_code, gcode0); + g2_pitch = mult_r(g_pitch, g_pitch); + g_pit_cod = mult_r(g_code, g_pitch); + L_tmp = L_mult(g_code, g_code); + L_Extract(L_tmp, &g2_code, &g2_code_lo); + + L_tmp = L_mult(coeff[2], g2_code_lo); + L_tmp = L_shr(L_tmp, 3); + L_tmp = L_mac(L_tmp, coeff_lo[0], g2_pitch); + L_tmp = L_mac(L_tmp, coeff_lo[1], g_pitch); + L_tmp = L_mac(L_tmp, coeff_lo[2], g2_code); + L_tmp = L_mac(L_tmp, coeff_lo[3], g_code); + L_tmp = L_mac(L_tmp, coeff_lo[4], g_pit_cod); + L_tmp = L_shr(L_tmp, 12); + L_tmp = L_mac(L_tmp, coeff[0], g2_pitch); + L_tmp = L_mac(L_tmp, coeff[1], g_pitch); + L_tmp = L_mac(L_tmp, coeff[2], g2_code); + L_tmp = L_mac(L_tmp, coeff[3], g_code); + L_tmp = L_mac(L_tmp, coeff[4], g_pit_cod); + + L_tmp1 = L_sub(L_tmp, dist_min); + /* splitting the if cost half the complexity of using IF macro */ + if (L_tmp1 < 0) + { + dist_min = L_add(L_tmp, 0); + } + if (L_tmp1 < 0) + { + index = i; + move16(); + } + + } + /* Read the quantized gains */ + index = add(index, min_ind); + + p = &t_qua_gain[add(index, index)]; + move16(); + *gain_pit = *p++; /* selected pitch gain in Q14 */ move16(); + g_code = *p++; /* selected code gain in Q11 */ move16(); + + L_tmp = L_mult(g_code, gcode0); /* Q11*Q0 -> Q12 */ + L_tmp = L_shl(L_tmp, add(exp_gcode0, 4)); /* Q12 -> Q16 */ + + *gain_code = L_tmp; /* gain of code in Q16 */ move16(); + + /*---------------------------------------------------* + * qua_ener = 20*log10(g_code) + * = 6.0206*log2(g_code) + * = 6.0206*(log2(g_codeQ11) - 11) + *---------------------------------------------------*/ + L_tmp = L_deposit_l(g_code); + frac = Log2_lc(L_tmp, &exp); + exp = sub(exp, 11); + L_tmp = Mpy_32_16(exp, frac, 24660); /* x 6.0206 in Q12 */ + + qua_ener = extract_l(L_shr(L_tmp, 3)); /* result in Q10 */ + + /*----------------------------------------------------------------* + * update table of past quantized energies + *----------------------------------------------------------------*/ + + past_qua_en[3] = past_qua_en[2]; + move16(); + past_qua_en[2] = past_qua_en[1]; + move16(); + past_qua_en[1] = past_qua_en[0]; + move16(); + past_qua_en[0] = qua_ener; + move16(); + + + exp = sub(norm_s(*gain_inov),1); + exp = s_max(exp, 0); + + tmp = div_s(shr(8192,exp),*gain_inov); + *norm_gain_code = L_shr(Mult_32_16(*gain_code, tmp),sub(1,exp)); + move32(); + + push_indice_fx( st, IND_GAIN, index, nBits ); + + return; +} diff --git a/lib_enc/gaus_enc_fx.c b/lib_enc/gaus_enc_fx.c new file mode 100644 index 0000000..a43f011 --- /dev/null +++ b/lib_enc/gaus_enc_fx.c @@ -0,0 +1,666 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "rom_enc_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "basop_mpy.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define NMAX 8 /* Control of the routine's complexity */ +/* #define FAC_DELTA 16.0f */ +#define SFAC_DELTA 11 + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static Word16 cod_2pos_fx( const Word16 ind1, const Word16 ind2, const Word16 sign1, const Word16 sign2, const Word16 n ); + +static void gauss2v_fx( Encoder_State_fx *st_fx, const Word16 h[], const Word16 xn[], const Word16 dn[], Word16 code[], + Word16 y1[], Word32 *gain, const Word16 lg, const Word16 shift, const Word16 Q_new, const Word16 nb_bits ); + +/*-------------------------------------------------------------------* + * Gaus_encode + * + * Encoder UnVoiced excitation coding using Gaussian codebooks + * - ACELP quantized Gaussian excitation + * - gain quantization + * - Total excitation for UnVoiced coders + * - Updates + *-------------------------------------------------------------------*/ +Word16 gaus_encode_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 *h1, /* i : weighted filter input response */ + const Word16 *xn, /* i : target vector */ + Word16 *exc, /* o : pointer to excitation signal frame */ + Word16 *mem_w0, /* o : weighting filter denominator memory */ + Word16 *clip_gain, /* o : memory of gain of pitch clipping algorithm */ + Word16 *tilt_code, /* o : synthesis excitation spectrum tilt */ + Word16 *code, /* o : algebraic excitation Q9 */ + Word32 *gain_code, /* o : Code gain. Q16 */ + Word16 *y2, /* o : zero-memory filtered adaptive excitation Q9 */ + Word16 *gain_inov, /* o : innovation gain Q12 */ + Word16 *voice_fac, /* o : voicing factor Q15 */ + Word16 *gain_pit, /* o : adaptive excitation gain Q14 */ + const Word16 Q_new, /* i : scaling factor */ + const Word16 shift, /* i : scaling factor */ + Word32 *norm_gain_code, /* o : normalized innovative cb. gain Q16 */ + const Word32 core_brate /* i : core bitrate */ +) +{ + Word16 nb_bits, idx; + Word16 i=0; + Word32 Ltmp; + Word16 dn[L_SUBFR], exp_code, gcode; /* Correlation between xn and h1 */ + Word16 exp,tmp; + + /*----------------------------------------------------------------* + * Encode gaussian excitation + *----------------------------------------------------------------*/ + + /* Correlation between target xn2[] and impulse response h1[] */ + corr_xh_fx(xn, dn, h1); + + nb_bits = FCB_bits_tbl[BIT_ALLOC_IDX_fx(core_brate, UNVOICED, i_subfr, TC_SUBFR2IDX_fx(-1))]; + + gauss2v_fx(st_fx, h1, xn, dn, code, y2, gain_code, L_SUBFR, shift, Q_new, shr(nb_bits,1)); + + /*----------------------------------------------------------------* + * Encode gaussian gain + *----------------------------------------------------------------*/ + + /* codeword energy computation */ + Ltmp = Dot_product12(code, code, L_SUBFR, &exp_code); + + exp_code = sub(exp_code, 18 + 6); /* exp: -18 (code in Q9), -6 (L_subfr = 64) */ + Ltmp = Isqrt_lc(Ltmp, &exp_code); + *gain_inov = extract_h(L_shl(Ltmp, sub(exp_code, 3))); /* g_code_inov in Q12 */ + + nb_bits = gain_bits_tbl[BIT_ALLOC_IDX_fx(core_brate, UNVOICED, i_subfr, TC_SUBFR2IDX_fx(-1))]; + /* low bound = -30; stepSize = 1.71875; inv_stepSize = 0.5818181 */ + idx = gain_enc_gaus_fx(gain_code, nb_bits, -7680, 28160, 19065); + push_indice_fx( st_fx, IND_GAIN, idx, nb_bits ); + + /*----------------------------------------------------------------* + * Total excitation for Unvoiced coders + *----------------------------------------------------------------*/ + gcode = round_fx(L_shl(*gain_code, Q_new)); /* scaled gain_code with Qnew */ + FOR (i = 0; i < L_SUBFR; i++) + { + exc[i+i_subfr] = round_fx(L_shl(L_mult(gcode, code[i]), 15-9)); + } + + /*----------------------------------------------------------------* + * Updates: last value of new target is stored in mem_w0 + *----------------------------------------------------------------*/ + + Ltmp = L_mult(gcode, y2[L_SUBFR - 1]); + Ltmp = L_shl(Ltmp, add(5, shift)); + Ltmp = L_negate(Ltmp); + Ltmp = L_mac(Ltmp, xn[L_SUBFR - 1], 16384); + Ltmp = L_shl(Ltmp, sub(1, shift)); + *mem_w0 = round_fx(Ltmp); + init_gp_clip_fx(clip_gain); /* reset pitch clipping parameters */ + + *gain_pit = 0; + *tilt_code = 0; + move16(); /* purely unvoiced */ + *voice_fac = -32768; + move16(); /* purely unvoiced */ + exp = sub(norm_s(*gain_inov),1); + exp = s_max(exp, 0); + + tmp = div_s(shr(8192,exp),*gain_inov); + *norm_gain_code = L_shr(Mult_32_16(*gain_code, tmp),sub(1,exp)); + move16(); + + return (L_SUBFR<<6); +} + +/*-------------------------------------------------------------------* + * gauss2v() + * + * encoder of Gaussian Codebook for unvoiced + * consisting of addition of 2 Gaussian vectors + * + * One Gaussian vector of 192 values vectors delayed by 2 + *-------------------------------------------------------------------*/ +void gauss2v_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 h[], /* i : weighted LP filter impulse response Q15 */ + const Word16 xn[], /* i : target signal Q12 */ + const Word16 dn[], /* i : backward filtered target Q12 */ + Word16 code[], /* o : gaussian excitation Q9 */ + Word16 y1[], /* o : zero-memory filtered gauss. excitation Q8 */ + Word32 *gain, /* o : excitation gain. 32-bit number in Q16 */ + const Word16 lg, /* i : subframe size Q0 */ + const Word16 shift, /* i : Scaling factor Q0 */ + const Word16 Q_new, /* i : Scaling factor Q0 */ + const Word16 nb_bits /* i : nb ob bits per track (max 6) */ +) +{ + Word16 i, j, ind1, ind2; + Word16 nvec, step; + Word32 cor, cora, dotprod; + Word16 enerw; + Word32 eneri,cor2; + Word32 enerw32,cor2w32; + Word16 *cpt1; + Word16 *pt1, *pt2; + Word32 max[NMAX+1]; + Word16 *pos[NMAX+1]; + Word32 sign[NMAX+1]; + Word32 ener[NMAX+1], corr[NMAX+1], ener1; + Word16 dico2[L_SUBFR*NMAX]; + Word16 exp_num; + Word16 exp_den; + Word16 Num; + Word16 Den; + Word32 GainPortion1; + Word32 GainPortion2; + Word32 cor_abs; + Word16 cor_neg; + Word16 div_result; + Word32 ener_sqrt; + Word32 Portion; + Word16 sign1,sign2; + Word16 enerw_norm,enerw_mantissa; + Word16 cor2w_norm,cor2w_mantissa; + Word16 eneri_norm,eneri_mantissa; + Word16 cor2_norm ,cor2_mantissa; + Word16 difference_norm; + Word32 cor32; /* 32-bit intermediate value*/ + Word16 hi1, lo1; + Word16 update_best; + Word16 idx; + Word32 Lc0,Lc1, Lnum, Lden; + Word16 gxx, gcc,index_delta, delta, m_sign, inv_delta; + Word16 hg[190],Gaus_dico2[190]; + Word16 shiftP3; + + /*----------------------------------------------------------------* + * Encode the tilt of gaussian excitation + *----------------------------------------------------------------*/ + + /* Compute spectral tilt of target */ + Lc0 = L_mult(xn[1], xn[1]); + Lc1 = L_mult(xn[1], xn[0]); + FOR (i=2; i 0) /* Adapt spectral tilt of initial codebook */ + { + /* Computation of 1 / (1+fdelta*fdelta) */ + inv_delta = inv_delta_tab[sub(index_delta, 1)]; + move16(); /* Q15 */ + + /* fgaus_dico2[0] = gaus_dico[0] */ + Gaus_dico2[0] = gaus_dico_fx[0]; + FOR (i=1; i<190; i++) + { + /* fgaus_dico2[i] = (gaus_dico[i] - fdelta*gaus_dico[i-1]) / (1 + fdelta*fdelta) */ + Lnum = L_msu(L_deposit_h(gaus_dico_fx[i]), delta, gaus_dico_fx[i-1]); + Gaus_dico2[i] = round_fx(Mpy_32_16_1(Lnum, inv_delta)); + } + } + ELSE + { + FOR (i=0; i<190; i++) + { + /* fgaus_dico2[i] = gaus_dico[i] */ + Gaus_dico2[i] = gaus_dico_fx[i]; + move16(); + } + } + + /*----------------------------------------------------------------* + * Initializations + *----------------------------------------------------------------*/ + + ind1 = 0; + move16(); + ind2 = 0; + move16(); + + nvec = shl(1, nb_bits); + step = shr(0x80, nb_bits); + + /*----------------------------------------------------------------* + * dot product between dn and gaussian codevectors, + * keep NMAX best vectors + *----------------------------------------------------------------*/ + + set32_fx(max, 0, NMAX+1); + set32_fx(sign, 0, NMAX+1); + + FOR (i = 0; i < NMAX+1; i++) + { + pos[i] = (Word16 *)Gaus_dico2; + } + + cpt1 = Gaus_dico2; + move16(); + + FOR (i=0; i< nvec; i++) + { + /* Dot product without normalization, because values are compared with each other afterwards. */ + cor = Dot_product(cpt1, dn, lg); /* Q12 * Q12 * length of 64 + 1 left shift ==> Q31*/ + cora = L_abs(cor); + j = NMAX-1; + move16(); + + DO + { + IF (GE_32(cora, max[j])) + { + max[j+1] = max[j]; + move32(); /*Q31*/ + pos[j+1] = pos[j]; + move16(); /*Pointer*/ + sign[j+1] = sign[j]; + move32(); /*Q31*/ + max[j] = cora; + move32(); /*Q31*/ + pos[j] = cpt1; + move16(); /*Pointer*/ + sign[j] = cor; + move32(); /*Q31*/ + } + j--; + } + WHILE (j >= 0); + cpt1 += step; + } + + /*----------------------------------------------------------------* + * filter selected vectors + * put sign + * compute energy + *----------------------------------------------------------------*/ + + pt1 = dico2; + move16(); + FOR (i=0; i Q31 */ + corr[i] = Dot_product(pt1,xn,lg); /* must be equal to sign[i] !! */ + move32(); /* pt1 points into dico2, in Q12. xn is in Q12 */ + /* Result is for Q12 * Q12 with length of 64 (6 bits) + 1 left shift => Q31 */ + pt1 += L_SUBFR; + } + + /*------------------------------------------------------------------------* + * try all combinations of NMAX best vectors + *------------------------------------------------------------------------*/ + + pt1 = dico2; + move16(); + + /* Initial values for search algorithm */ + enerw32 = L_deposit_h(0x80); + cor2w32 = L_deposit_l(-2); + enerw_norm = norm_l(enerw32); + cor2w_norm = norm_l(cor2w32); + cor2w_mantissa = round_fx(L_shl(cor2w32,cor2w_norm)); + enerw_mantissa = round_fx(L_shl(enerw32,enerw_norm)); + + FOR (i=0; i< NMAX; i++) + { + pt2 = pt1; + move16(); + FOR (j=i; j Q31 */ + + /* eneri = round_fx(ener[i]) + round_fx(ener[j]) + 2*round_fx(dotprod) */ + /* Use ScalingShift to stay aligned with ener[] */ + eneri=L_shl(dotprod, 1); /* One left shift added for factor of 2 */ + eneri=L_add(ener[i], eneri); + eneri=L_add(ener[j], eneri); /* Q31 */ + + lo1 = L_Extract_lc(cor32, &hi1); + cor2 = Sad_32(0, hi1, lo1); /* Square + Add */ + + cor2_norm = norm_l(cor2); + eneri_norm = norm_l(eneri); + cor2_mantissa = round_fx(L_shl(cor2, cor2_norm)); + eneri_mantissa = round_fx(L_shl(eneri, eneri_norm)); + + difference_norm = sub(add(cor2_norm, enerw_norm), add(cor2w_norm, eneri_norm)); + + update_best = 0; + move16(); + + IF (difference_norm > 0) + { + if (GT_32(L_shr(L_mult(cor2_mantissa, enerw_mantissa), difference_norm), + L_mult(cor2w_mantissa, eneri_mantissa))) + { + update_best = 1; + move16(); + } + } + ELSE + { + if (L_msu(L_shl(L_mult(cor2w_mantissa, eneri_mantissa), difference_norm), cor2_mantissa, enerw_mantissa) < 0) + { + update_best=1; + move16(); + } + } + IF (update_best != 0) + { + cor2w_mantissa = cor2_mantissa; + move16(); + cor2w_norm = cor2_norm; + move16(); + enerw_mantissa = eneri_mantissa; + move16(); + enerw_norm = eneri_norm; + move16(); + ind1 = i; + move16(); + ind2 = j; + move16(); + } + pt2 += L_SUBFR; + } + pt1 += L_SUBFR; + } + + enerw = round_fx(L_shr(L_deposit_h(enerw_mantissa), enerw_norm)); + + /*----------------------------------------------------------------* + * Compute zero-memory filtered gauss. excitation y + *----------------------------------------------------------------*/ + + pt1 = dico2 + ind1*L_SUBFR; + move16(); /*Pointer arithmetic*/ + pt2 = dico2 + ind2*L_SUBFR; + move16(); + + shiftP3 = add(shift, 3); + FOR (i=0; i= 0) + { + sign1 = 32767; + move16(); + } + + sign2 = (-32768); + move16(); + if (sign[ind2] >= 0) + { + sign2 = 32767; + move16(); + } + + /*----------------------------------------------------------------* + * Compute code + *----------------------------------------------------------------*/ + + pt1 = pos[ind1]; + move16(); /* Points to gaussian vector (gaus_dico_fx) in Q12 */ + pt2 = pos[ind2]; + move16(); /* Points to gaussian vector (gaus_dico_fx) in Q12 */ + + /* sign[ind1] and sign[ind2] */ + FOR (i=0; i Q31 */ + + exp_num = sub(norm_s(enerw), 1); + exp_den = norm_l(ener1); + Num = shl(enerw, exp_num); + Den = round_fx(L_shl(ener1, exp_den)); + + GainPortion2 = L_deposit_l(0); /* Unexpected division by zero. Eliminate this gain contribution */ + IF (Den != 0) /* Protection against division by zero */ + { + div_result = div_s(Num, Den); /* Q15 */ + + /* Re-scale to compensate for normalization*/ + GainPortion2 = L_shr(L_deposit_l(div_result), sub(exp_num, exp_den)); + } + + ener_sqrt = Isqrt(L_shl(GainPortion2, 1)); /* Make value a Q16 prior to division (align on power of 4) */ + ener_sqrt = L_shr(ener_sqrt, 8); /* Left-shift Q23 result to make a Q15 result */ + + Portion = Mult_32_16(GainPortion1, 19661); /* Performs GainPortion1*.6 */ + Portion = Madd_32_16(Portion, ener_sqrt, 13107); /* Performs ener_sqrt*.4 */ + + /* Gain must be output in a 32-bit variable as a Q16 */ + /* Compensate for Q_new */ + *gain = L_shl(Portion, sub(13, Q_new)); + move32(); + + return; +} + + +/*---------------------------------------------------------------------* + * Put selected codevector positions and signs into quantization index + *---------------------------------------------------------------------*/ +static Word16 cod_2pos_fx( /* o : codebook quantization index */ + const Word16 ind1, /* i : index of 1st gaussian vector */ + const Word16 ind2, /* i : index of 2nd gaussian vector */ + const Word16 sign1, /* i : sign of 1st gaussian vector */ + const Word16 sign2, /* i : sign of 2nd gaussian vector */ + const Word16 n /* i : nb. of codebook vectors */ +) +{ + Word16 i1, i2, index, s1, s2; + s1 = 1; + move16(); + + if (sign1 > 0) + { + s1 = 0; + move16(); + } + s2 = 1; + move16(); + if (sign2 > 0) + { + s2 = 0; + move16(); + } + + IF (EQ_16(s1, s2)) + { + IF (LE_16(ind1, ind2)) + { + i1 = ind1; + move16(); + i2 = ind2; + move16(); + } + ELSE + { + i1 = ind2; + move16(); + i2 = ind1; + move16(); + } + } + ELSE + { + IF (GT_16(ind1, ind2)) + { + i1 = ind1; + move16(); + i2 = ind2; + move16(); + } + ELSE + { + i1 = ind2; + move16(); + i2 = ind1; + move16(); + s1 = s2; + move16(); + } + } + + index = extract_l(L_mult(i1, n)); + index = add(index, shl(i2, 1)); + index = add(index, s1); + + return index; +} diff --git a/lib_enc/gp_clip_fx.c b/lib_enc/gp_clip_fx.c new file mode 100644 index 0000000..8b7ec88 --- /dev/null +++ b/lib_enc/gp_clip_fx.c @@ -0,0 +1,396 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "basop_util.h" +#include "stl.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define DIST_ISF_MAX_IO 384 /* 150 Hz (6400Hz=16384) */ +#define DIST_ISF_MAX 307 /* 120 Hz (6400Hz=16384) */ +#define DIST_ISF_THRES 154 /* 60 (6400Hz=16384) */ +#define GAIN_PIT_THRES 14746 /* 0.9 in Q14 */ +#define GAIN_PIT_MIN 9830 /* 0.6 in Q14 */ + +#define ALPHA1 32113 /* 0.98f */ +#define ALPHA4 32440 /* 0.99f */ +#define WINDOW_SIZE 50 +#define THRESH_TYPE 13926 /* 0.85f in Q14 */ +#define THRESH_VOICING 14090 /* 0.86f in Q14 */ + +#define GPCLIP_E (6+2) + +#define ALPHA1_M1 21474836l/*1.0f-0.98 Q30*/ +#define ALPHA4_M1 10737408l/*1.0f-0.99f Q30*/ + +/*-------------------------------------------------------------------* + * init_gp_clip + * + * Pitch Gain clipping initializations + *-------------------------------------------------------------------*/ +void init_gp_clip_fx( + Word16 mem[] /* o : memory of gain of pitch clipping algorithm */ +) +{ + mem[0] = DIST_ISF_MAX; + move16(); /* Q0 */ + mem[1] = GAIN_PIT_MIN; + move16(); /* 1Q14 */ + mem[2] = 0; + move16(); /* 8Q7 */ /* old energy of target (dB) */ + mem[3] = 0; + move16(); /* Q0 */ + mem[4] = 0; + move16(); /* Q14 */ + mem[5] = 13107;/*0.8*/ move16(); /* Q14 */ + + return; +} + +/*-------------------------------------------------------------------* + * Function gp_clip + * + * The gain needs to be limited (gain pitch < 1.0) when one of the + * following cases occurs: + * - a resonance on LPC filter (lp_disp < 60 Hz) AND a good pitch + * prediction (lp_gp > 0.9) + * - target energy drops by 6 dB AND a good pitch prediction (lp_gp>1.0) + *-------------------------------------------------------------------*/ + +Word16 gp_clip_fx( + const Word32 core_brate, /* i : core bitrate */ + const Word16 *voicing, /* i : normalized correlations (from OL pitch) */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 coder_type, /* i : type of coder */ + const Word16 xn[], /* i : target vector */ + Word16 mem[], /* i/o: memory of gain of pitch clipping algorithm */ + const Word16 Q_new /* i : scaling factor */ +) +{ + Word16 clip; + Word16 i, wener; + Word16 e_ener, f_ener; + Word32 ener; + Word32 L_tmp; + Word16 thres; + + clip = 0; + move16(); + test(); + IF( (core_brate == ACELP_6k60) || (core_brate == ACELP_8k85) ) + { + thres = add(14746, mult(1638, extract_l(L_mult(mem[0], (Word16)(16384/DIST_ISF_MAX_IO))))); /* clipping is activated when filtered pitch gain > threshold (0.94 to 1 in Q14) */ + test(); + if (GT_16(mem[1], thres)) + { + clip = 1; + move16(); + } + } + ELSE + { + test(); + if(LT_16(mem[0], DIST_ISF_THRES)&>_16(mem[1],GAIN_PIT_THRES)) + { + clip = 1; + move16(); + } + } + + ener = L_mac(1L, xn[0], xn[0]); + FOR (i=1; i250ms) */ + L_tmp = L_mac(L_tmp, 655, gain_pit); + } + ELSE + { + L_tmp = L_mult(29491, mem[1]); + L_tmp = L_mac(L_tmp, 3277, gain_pit); + } + gain = extract_h(L_tmp); + gain = s_max(gain, GAIN_PIT_MIN); + mem[1] = gain; + move16(); + + return; +} + + +/*-------------------------------------------------------------------* + * Function gp_clip + * + * The gain needs to be limited (gain pitch < 1.0) when one of the + * following cases occurs: + * - a resonance on LPC filter (lp_disp < 60 Hz) AND a good pitch + * prediction (lp_gp > 0.9) + * - target energy drops by 6 dB AND a good pitch prediction (lp_gp>1.0) + *-------------------------------------------------------------------*/ +Word16 Mode2_gp_clip( + const Word16 voicing[3], /* i : normalized correlations from OL pitch Q15 */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 coder_type, /* i : type of coder */ + const Word16 xn[], /* i : target vector Q_xn */ + Word16 mem[], /* i/o: memory of gain of pitch clipping algorithm */ + /* mem[0]: Q0 */ + /* mem[1]: 1Q14 */ + /* mem[2]: 8Q7 */ + /* mem[3]: Q0 (integer) */ + /* mem[4]: Q14 */ + /* mem[5]: Q14 */ + const Word16 L_subfr, + const Word16 Q_xn /* i : scaling factor of vector xn[] */ +) +{ + Word16 clip, tmp, exp_xn; + Word16 i; + Word32 wener, Ltmp; + + move16(); + clip = 0; + + test(); + if ((LT_16(mem[0],DIST_ISF_THRES))&&(GT_16(mem[1],GAIN_PIT_THRES))) + { + move16(); + clip = 1; + } + + /*ener_exp = exp_xn * 2 + 1*/ + exp_xn = add(shl(sub(15,Q_xn),1), 1); + wener = L_shr(21474836l/*0.01f Q31*/, s_min(31,exp_xn)); + wener = L_max(1,wener); + + FOR (i=0; imem_syn, st_fx->mem_syn_tmp_fx, M); + st_fx->mem_w0_tmp_fx = mem->mem_w0; + move16(); + Es_pred = 0; + move16(); + + /*---------------------------------------------------------------* + * Encode GSC attack flag (used to reduce possible pre-echo) + * Encode GSC SWB speech flag + *---------------------------------------------------------------*/ + push_indice_fx( st_fx, IND_GSC_ATTACK, attack_flag, 1 ); + + test(); + IF( NE_16(coder_type,INACTIVE )&&GE_32(st_fx->total_brate_fx,ACELP_13k20)) + { + push_indice_fx( st_fx,IND_GSC_SWB_SPEECH, st_fx->GSC_noisy_speech_fx, 1); + } + /*---------------------------------------------------------------* + * Find and encode the number of subframes + *---------------------------------------------------------------*/ + test(); + IF ( GE_32(st_fx->core_brate_fx,ACELP_9k60)&&LE_32(st_fx->core_brate_fx,ACELP_13k20)) + { + FOR( i = 0; i < 5; i++) + { + test(); + if( GT_16(abs_s(st_fx->gsc_lt_diff_etot_fx[MAX_LT-i-1]),1536)&&EQ_16(st_fx->cor_strong_limit_fx,1)) + { + st_fx->cor_strong_limit_fx = 0; + move16(); + } + } + } + IF( st_fx->GSC_noisy_speech_fx ) + { + nb_subfr = NB_SUBFR; + move16(); + st_fx->cor_strong_limit_fx = 0; + move16(); + nb_subfr_flag = 1; + move16(); + } + ELSE + { + test(); + test(); + IF( (st_fx->cor_strong_limit_fx == 0 || EQ_16(coder_type,INACTIVE))&&GE_32(st_fx->core_brate_fx,ACELP_9k60)) + { + nb_subfr = 2; + move16(); + nb_subfr_flag = 0; + move16(); + st_fx->cor_strong_limit_fx = 0; + move16(); + } + ELSE + { + nb_subfr = SWNB_SUBFR; + move16(); + nb_subfr_flag = 1; + move16(); + } + IF( GE_32(st_fx->core_brate_fx,ACELP_9k60)) + { + /* nb_subfr_flag can only have the value 0 or 1 */ + push_indice_fx( st_fx, IND_HF_NOISE, nb_subfr_flag, 1); + } + } + + /*---------------------------------------------------------------* + * Compute adaptive (pitch) excitation contribution + *---------------------------------------------------------------*/ + + test(); + IF( st_fx->GSC_noisy_speech_fx && EQ_16(nb_subfr,NB_SUBFR )) + { + nb_bits = Es_pred_bits_tbl[BIT_ALLOC_IDX_fx(st_fx->core_brate_fx, GENERIC, -1, -1)]; + move16(); + Es_pred_enc_fx( &Es_pred, &indice, L_FRAME, res, voicing, nb_bits,0, Q_new + ); + push_indice_fx( st_fx, IND_ES_PRED, indice, nb_bits ); + } + + enc_pit_exc_fx( st_fx, mem, speech, Aw, Aq,Es_pred, T_op, voicing, res, synth, exc, &T0_tmp, + &T0_frac_tmp, pitch_buf, nb_subfr, &st_fx->lt_gpitch_fx, &saved_bit_pos, Q_new, shift ); + + /*---------------------------------------------------------------* + * DCT transform + *---------------------------------------------------------------*/ + edct_16fx( exc, dct_epit, L_FRAME, 7 ); + edct_16fx( res, dct_res, L_FRAME, 7 ); + /*---------------------------------------------------------------* + * Calculate energy dynamics + *---------------------------------------------------------------*/ + Lm_mean = L_deposit_l(0); + FOR( i = 7; i < 15; i++ ) + { + /*m_mean = add(m_mean,edyn_fx( dct_res+i*16, 16, Q_new )); */ + Lm_mean = L_mac(Lm_mean, edyn_fx( dct_res+i*16, 16, Q_new ), 4096);/*Q7*/ + } + m_mean = round_fx(Lm_mean);/*Q7*/ + + IF( GT_16(m_mean,st_fx->mid_dyn_fx)) + { + /*st_fx->mid_dyn_fx = 0.2f * st_fx->mid_dyn_fx + 0.8f * m_mean;*/ + st_fx->mid_dyn_fx = round_fx(L_mac(L_mult(26214,m_mean),6554,st_fx->mid_dyn_fx));/*Q7*/ + } + ELSE + { + /*st_fx->mid_dyn_fx = 0.6f * st_fx->mid_dyn_fx + 0.4f * m_mean;*/ + st_fx->mid_dyn_fx = round_fx(L_mac(L_mult(13107,m_mean),19661,st_fx->mid_dyn_fx));/*Q7*/ + } + IF( NE_16(coder_type,INACTIVE)) + { + st_fx->noise_lev_fx = sub((NOISE_LEVEL_SP3+1), usquant_fx(st_fx->mid_dyn_fx, &m_mean, MIN_DYNAMIC_FX, shr(GSF_NF_DELTA_FX,1), GSC_NF_STEPS)); + + st_fx->noise_lev_fx = s_min(st_fx->noise_lev_fx, NOISE_LEVEL_SP3); + } + + st_fx->past_dyn_dec_fx = st_fx->noise_lev_fx; + move16(); + IF( LE_32(st_fx->core_brate_fx,ACELP_8k00)) + { + st_fx->noise_lev_fx = s_max(st_fx->noise_lev_fx, NOISE_LEVEL_SP2); + push_indice_fx( st_fx, IND_NOISE_LEVEL, sub(st_fx->noise_lev_fx, NOISE_LEVEL_SP2), 2 ); + } + ELSE IF( st_fx->GSC_noisy_speech_fx ) + { + st_fx->noise_lev_fx = NOISE_LEVEL_SP3; + move16(); + } + ELSE + { + push_indice_fx( st_fx, IND_NOISE_LEVEL, sub(st_fx->noise_lev_fx, NOISE_LEVEL_SP0), 3 ); + } + + /*---------------------------------------------------------------* + * Find and encode the last band where the adaptive (pitch) contribution is significant + *---------------------------------------------------------------*/ + + last_pit_bin = Pit_exc_contribution_len_fx( st_fx, dct_res, dct_epit, pitch_buf, nb_subfr, &st_fx->pit_exc_hangover, coder_type, Q_new ); + + IF( last_pit_bin == 0 ) + { + mem->tilt_code = 0; + move16(); + } + ELSE + { + /*last_pit_bin++;*/ + last_pit_bin = add(last_pit_bin,1); + } + + /*--------------------------------------------------------------------------------------* + * GSC encoder + *--------------------------------------------------------------------------------------*/ + + /* Find the current total number of bits used */ + tmp_nb_bits_tot = st_fx->nb_bits_tot_fx; + move16(); + + + if( st_fx->extl_brate_fx > 0 ) + { + /* subtract 1 bit for TBE/BWE BWE flag (bit counted in extl_brate) */ + tmp_nb_bits_tot = sub(tmp_nb_bits_tot,1); + } + test(); + if( EQ_16(coder_type,INACTIVE)&&LE_32(st_fx->core_brate_fx,ACELP_9k60)) + { + /* add 5 bits for noisiness */ + tmp_nb_bits_tot = add(tmp_nb_bits_tot,5); + } + + gsc_enc_fx( st_fx, dct_res, dct_epit, last_pit_bin, tmp_nb_bits_tot, nb_subfr, coder_type, lsf_new, exc_wo_nf, tmp_noise, Q_new ); + + /*--------------------------------------------------------------------------------------* + * iDCT transform + *--------------------------------------------------------------------------------------*/ + + edct_16fx( dct_epit, exc, L_FRAME, 7 ); + edct_16fx( exc_wo_nf, exc_wo_nf, L_FRAME, 7 ); + /*--------------------------------------------------------------------------------------* + * Remove potential pre-echo in case an onset has been detected + *--------------------------------------------------------------------------------------*/ + + pre_echo_att_fx( &st_fx->Last_frame_ener_fx, exc, attack_flag, Q_new + ,st_fx->last_coder_type_fx + ); + + /*--------------------------------------------------------------------------------------* + * Update BWE excitation + *--------------------------------------------------------------------------------------*/ + + set16_fx( voice_factors, 0, NB_SUBFR ); + interp_code_5over2_fx( exc, bwe_exc, L_FRAME ); + + /*--------------------------------------------------------------------------------------* + * Synthesis + *--------------------------------------------------------------------------------------*/ + + p_Aq = Aq; + FOR (i_subfr=0; i_subfrmem_syn, 1 ); + p_Aq += (M+1); + } + + /*--------------------------------------------------------------------------------------* + * Updates + *--------------------------------------------------------------------------------------*/ + + mem->mem_w0 = st_fx->mem_w0_tmp_fx; + move16(); + Copy( exc_wo_nf, exc, L_FRAME ); + + return; +} + +/*================================================================================*/ +/* FUNCTION : void gsc_enc_fx () */ +/*--------------------------------------------------------------------------------*/ +/* PURPOSE : Generic audio signal encoder */ +/*--------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) res_dct_in : dct of residual signal Q_exc */ +/* _ (Word16) Diff_len : Lenght of the difference signal Q0 */ +/* _ (Word16) coder_type : coding type Q0 */ +/* _ (Word16) bits_used : Number of bit used before frequency Q Q0 */ +/* _ (Word16) nb_subfr : Number of subframe considered Q0 */ +/* _ (Word16) Qexc : Q format of exc_dct_in */ +/*--------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Encoder_State_fx *st_fx:Encoder State Structure */ +/* _ (Word16[]) exc_dct_in : dctof pitch-only excitation / total excitation Q_exc */ +/*--------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _None */ +/*================================================================================*/ + + +static void gsc_enc_fx( + Encoder_State_fx *st_fx, /* i/o: State structure */ + Word16 res_dct_in[], /* i : dct of residual signal */ + Word16 exc_dct_in[], /* i/o: dct of pitch-only excitation / total excitation */ + const Word16 Diff_len, + const Word16 bits_used, + const Word16 nb_subfr, + const Word16 coder_type, + Word16 *lsf_new, /* i : ISFs at the end of the frame */ + Word16 *exc_wo_nf, /* o : excitation (in f domain) without noisefill */ + Word16 *tmp_noise, /* o : noise energy */ + Word16 Q_exc +) +{ + Word16 y2_filt[L_FRAME]; + Word16 exc_diffQ[L_FRAME]; + Word16 exc_diff[L_FRAME]; + Word16 bit,tmp; + Word16 nb_subbands; + Word16 pvq_len, i; + Word16 bits_per_bands[MBANDS_GN]; + Word16 tmp_band; + Word16 concat_in[L_FRAME]; + Word16 concat_out[L_FRAME]; + Word16 max_ener_band[MBANDS_GN], j; + Word16 Ener_per_bd_iQ[MBANDS_GN]; + Word16 last_bin, mean_gain; + Word16 bitallocation_band[MBANDS_GN]; + Word16 bitallocation_exc[2]; + + Word16 inpulses_fx[NB_SFM]; + Word16 imaxpulse_fx[NB_SFM]; + Word16 Q_tmp; + Word16 seed_init; + + set16_fx( inpulses_fx, 0, NB_SFM ); + set16_fx( imaxpulse_fx, 0, NB_SFM ); + + /*--------------------------------------------------------------------------------------* + * Initialization + *--------------------------------------------------------------------------------------*/ + + bit = bits_used; + move16(); + set16_fx( exc_diffQ, 0, L_FRAME ); + set16_fx( y2_filt, 0, L_FRAME ); + + /*--------------------------------------------------------------------------------------* + * Calculate the difference between the residual spectrum and the spectrum of adaptive excitation + * (non valuable temporal content present in exc_dct_in is already zeroed) + *--------------------------------------------------------------------------------------*/ + + Vr_subt( res_dct_in, exc_dct_in, exc_diff, L_FRAME ); + exc_diff[0] = 0; + move16(); + + /*--------------------------------------------------------------------------------------* + * Multiply the difference spectrum with the normalized spectral shape of the residual signal + * This improves the stability of the differnece spectrum since the spectral shape of the + * residual signal is less suseptible to rapid changes than the difference spectrum + *--------------------------------------------------------------------------------------*/ + IF( Diff_len == 0 ) + { + tmp_band = 0; + move16(); + } + ELSE + { + tmp_band = st_fx->mem_last_pit_band_fx; + move16(); + } + + Ener_per_band_comp_fx( exc_diff, Ener_per_bd_iQ, Q_exc, MBANDS_GN, 1 ); + + /*--------------------------------------------------------------------------------------* + * Gain quantizaion + *--------------------------------------------------------------------------------------*/ + + mean_gain = gsc_gainQ_fx( st_fx, Ener_per_bd_iQ, Ener_per_bd_iQ, st_fx->core_brate_fx, coder_type, st_fx->bwidth_fx ); + *tmp_noise = mult_r(320,mean_gain); /*10 in Q5 lp_gainc in Q3 */ + + /*--------------------------------------------------------------------------------------* + * Frequency encoder + *--------------------------------------------------------------------------------------*/ + + bands_and_bit_alloc_fx( st_fx->cor_strong_limit_fx, st_fx->noise_lev_fx, st_fx->core_brate_fx, Diff_len, bit, &bit, Ener_per_bd_iQ, + max_ener_band, bits_per_bands, &nb_subbands, exc_diff, concat_in, &pvq_len, coder_type, st_fx->bwidth_fx, st_fx->GSC_noisy_speech_fx ); + + Q_tmp = Q_exc; + move16(); + + tmp = pvq_core_enc_fx( st_fx, concat_in, concat_out, &Q_tmp, bit, nb_subbands, gsc_sfm_start, gsc_sfm_end, + gsc_sfm_size, bits_per_bands, NULL, inpulses_fx, imaxpulse_fx, ACELP_CORE ); + Scale_sig( concat_out, gsc_sfm_end[nb_subbands-1], sub(Q_PVQ_OUT, Q_tmp) ); + + bit = sub(bit,tmp); + /* write unused bits */ + WHILE( bit > 0 ) + { + i = s_min( bit, 16 ); + push_indice_fx( st_fx, IND_UNUSED, 0, i ); + bit = sub(bit,i); + } + /* Reorder Q bands */ + seed_init = 0; + move16(); + last_bin = 0; + move16(); + set16_fx( bitallocation_band, 0, MBANDS_GN ); + + FOR(j = 0; j < nb_subbands; j++) + { + Copy( concat_out+j*16, exc_diffQ + max_ener_band[j]*16, 16 );/*Q12*/ + + last_bin = s_max(last_bin , max_ener_band[j]); + + bitallocation_band[ max_ener_band[j]] = 1; + move16(); + + seed_init = add(seed_init,inpulses_fx[j]); + move16(); + } + test(); + IF( NE_16(st_fx->last_coder_type_fx, AUDIO) /* First audio frame */ + && NE_16(st_fx->last_coder_type_fx, UNVOICED) )/* last_coder_type == INACTIVE is overwritten in update_enc to UNVOICED */ + { + FOR( j = 0; j < shl(nb_subbands,4); j++ ) + { + IF( concat_out[j] > 0 ) + { + seed_init = extract_l(L_shl(seed_init,3)); + } + IF( concat_out[j] < 0 ) + { + seed_init = add(seed_init,3); + move16(); + } + } + st_fx->seed_tcx_fx = seed_init; + move16(); + } + test(); + IF( EQ_32(st_fx->core_brate_fx,ACELP_8k00)&&NE_16(st_fx->bwidth_fx,NB)) + { + bitallocation_exc[0] = 0; + move16(); + bitallocation_exc[1] = 0; + move16(); + if( exc_diffQ[L_FRAME8k - 2] != 0 ) + { + bitallocation_exc[0] = 1; + move16(); + } + if( exc_diffQ[L_FRAME8k - 1] != 0 ) + { + bitallocation_exc[1] = 1; + move16(); + } + } + + /*--------------------------------------------------------------------------------------* + * Skip adaptive (pitch) contribution frequency band (no noise added over the adaptive (pitch) contribution) + * Find x pulses between 1.6-3.2kHz to code in the spectrum of the residual signal + * Gain is based on the inter-correlation gain between the pulses found and residual signal + *--------------------------------------------------------------------------------------*/ + + freq_dnw_scaling_fx( st_fx->cor_strong_limit_fx, coder_type, st_fx->noise_lev_fx, st_fx->core_brate_fx, exc_diffQ, Q_PVQ_OUT ); + + /*--------------------------------------------------------------------------------------* + * Estimate noise level + *--------------------------------------------------------------------------------------*/ + + highband_exc_dct_in_fx( st_fx->core_brate_fx, mfreq_bindiv_loc_fx, last_bin, Diff_len, st_fx->noise_lev_fx, tmp_band, exc_diffQ, + &st_fx->seed_tcx_fx, Ener_per_bd_iQ, nb_subfr, exc_dct_in, st_fx->last_coder_type_fx, bitallocation_band, lsf_new, + st_fx->last_exc_dct_in_fx, &st_fx->last_ener_fx, st_fx->last_bitallocation_band_fx, bitallocation_exc, 0, coder_type, + st_fx->bwidth_fx, exc_wo_nf, Q_PVQ_OUT, Q_exc, st_fx->GSC_noisy_speech_fx, NULL ); + + exc_dct_in[0] = 0; + move16(); + + return; +} + +/*======================================================================*/ +/* FUNCTION : edyn_fx() */ +/*----------------------------------------------------------------------*/ +/* PURPOSE : Calculate energy dynamics in a vector */ +/* (ratio of energy maximum to energy mean) */ +/* */ +/*----------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16 *) vec : ratio of max to mean Qnew */ +/* _ (Word16) lvec : input vector */ +/* _ (Word16) Q_new : */ +/*-----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16) dyn : ratio of energy maximum to energy mean (Q7) */ +/*-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*=======================================================================*/ + +static Word16 edyn_fx( /* o : ratio of max to mean */ + const Word16 *vec, /* i : input vector */ + const Word16 lvec, /* i : length of input vector */ + Word16 Qnew +) +{ + Word16 j=0; + Word16 dyn; + Word32 L_tmp, ener_max, ener_mean; + Word16 tmp,exp2,tmp2,tmp1,exp1,exp3; + Word16 scale; + + ener_mean = L_shl(1,shl(Qnew,1)); /*2*Qnew*/ + ener_max = L_shl(1,shl(Qnew,1)); + + FOR( j=0; j 0) + { + exp1 = norm_l(ener_mean); + tmp1 = round_fx(L_shl(ener_mean,exp1)); + exp1 = sub(30,exp1); + + exp2 = norm_l(ener_max); + tmp2 = extract_h(L_shl(ener_max,exp2)); + exp2 = sub(30,exp2); + + scale = shr(sub(tmp1, tmp2), 15); + tmp2 = shl(tmp2, scale); + exp2 = sub(exp2, scale); + + exp3 = sub(exp1,exp2); + + tmp = div_s(tmp2, tmp1); /*Q(15+exp3)*/ + + L_tmp = L_shr_r(L_mult(tmp,10),exp3); + dyn = round_fx(L_shl(L_tmp,7)); /*Q7*/ + } + ELSE + { + dyn = 1280; + move16(); + } + return dyn; + +} diff --git a/lib_enc/guided_plc_enc.c b/lib_enc/guided_plc_enc.c new file mode 100644 index 0000000..d085715 --- /dev/null +++ b/lib_enc/guided_plc_enc.c @@ -0,0 +1,445 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include "stl.h" +#include "prot_fx.h" +#include "stat_dec_fx.h" +#include "basop_util.h" + + +/************************************************************/ +/* Macro for the functions to be implemented. */ +/************************************************************/ + +void coderLookAheadInnovation( + Word16 A_3Q12[], /* input: coefficients NxAz[M+1] */ + Word16 *pT, /* out: pitch */ + HANDLE_PLC_ENC_EVS st, /* i/o: coder memory state */ + Word16 *speechLookAhead_Qx, /* i: input speech in Q(st->Qold) */ + Word16 *old_exc, /* i: input excitation in Q(st->Qold) */ + Word16 L_frame +) +{ + Word16 i; + Word16 prev_pitch, T0_fx; + Word16 *exc_Qx, exc_buf_Qx[L_EXC_MEM+2*L_SUBFR+8]; + Word32 mantissa_max = -0x7fffffffL; + Word16 subfr_len = 0; + Word16 search_range = 9; + Word16 exc_max; + Word16 exc_sh; + Word32 ps,alp, alp_ini; + Word32 alp_s1, alp_s2; + Word16 k; + Word16 ps_e,alp_e; + Word32 max_ps, max_ps_tmp; + Word16 max_ps_e; + Word16 tmp_loop; + + /* Debug init (not instrumented) */ + T0_fx = -3000; + subfr_len = shl(L_SUBFR,1); /* 2*L_SUBFR */ + if( GT_16( L_FRAME16k, L_frame )) + { + subfr_len = add(L_SUBFR,48); /* 1.75*L_SUBFR */ + } + + /*------------------------------------------------------------------------* + * - BASOP specific initialization. * + *------------------------------------------------------------------------*/ + /* initialization */ + exc_Qx = exc_buf_Qx + L_EXC_MEM + 8; + FOR( i=0; iT0_4th; + move16(); + /* find best candidate of pitch lag */ + T0_fx = st->T0_4th; + move16(); + mantissa_max = -0x7fffffffL; + move32(); + max_ps = -0x7fffffffL; + move32(); + max_ps_e = 16; + move16(); + + /*find maximum*/ + exc_max = 0; + move16(); + tmp_loop = s_min(-prev_pitch+search_range+subfr_len,0); + FOR(i=-prev_pitch-search_range; i < tmp_loop; i++) + { + exc_max = s_max(exc_Qx[i],exc_max); + } + FOR(i= 0; ipit_max)||LT_16(add(prev_pitch,i),st->pit_min)) + { + CONTINUE; + } + ps = L_deposit_l(0); + alp_s1 = L_deposit_l(0); + alp_s2 = L_deposit_l(0); + + FOR(k=0; kT0_4th; + move16(); + } + + /* Update excitation */ + pT[0] = T0_fx; + move16(); + + return; +} + +/************************************************************/ +/* Static functions */ +/************************************************************/ +void enc_prm_side_Info( HANDLE_PLC_ENC_EVS hPlc_Ext, Encoder_State_fx *st ) +{ + Word16 diff_pitch; + Word16 bits_per_subfr, search_range; + + bits_per_subfr = 4; + move16(); + search_range = 8; + move16(); + + IF( GT_16(hPlc_Ext->nBits,1)) + { + + push_next_indice_fx(st, 1, 1); + + diff_pitch = sub(hPlc_Ext->T0, hPlc_Ext->T0_4th); + test(); + if( (GT_16(diff_pitch,sub(search_range,1)))||(LT_16(diff_pitch,add(-search_range,1)))) + { + diff_pitch = -8; + move16(); + } + + push_next_indice_fx(st, add(diff_pitch, search_range), bits_per_subfr); + } + ELSE + { + push_next_indice_fx(st, 0, 1); + } + + return; +} + +/************************************************************/ +/* Functions for encoder side loss simulation */ +/************************************************************/ +void encoderSideLossSimulation( + Encoder_State_fx *st, + HANDLE_PLC_ENC_EVS hPlc_Ext, + Word16 *lsf_q, /* Q1*1.28 */ + Word16 stab_fac, /* Q15 */ + Word8 calcOnlyISF, + const Word16 L_frame +) +{ + Word16 lspLocal_Q15[M]; + Word16 const* xsfBase; /* base for differential XSF coding */ + + + /************************************************************* + * Decoder state could be stored with memcpy, + * since Decoder_State does not contain pointer member. + *************************************************************/ + + /* Decoder State Update */ + IF( EQ_16(L_frame,L_FRAME_16k)) + { + lsf2lsp_fx( lsf_q, lspLocal_Q15, M, INT_FS_16k_FX ); + } + ELSE + { + lsf2lsp_fx( lsf_q, lspLocal_Q15, M, INT_FS_FX ); + } + + + xsfBase = PlcGetLsfBase (st->lpcQuantization, + st->narrowBand, + st->sr_core); + + Copy( st->mem_MA_fx, hPlc_Ext->mem_MA_14Q1, M ); + Copy( st->mem_AR_fx, hPlc_Ext->mem_AR, M ); + + + /* ISF parameter processing for concealment */ + updateLSFForConcealment( hPlc_Ext, lsf_q, M ); + hPlc_Ext->stab_fac_Q15 = stab_fac; + move16(); + + Copy( lsf_q, hPlc_Ext->lsfold_14Q1, M ); + Copy( lspLocal_Q15, hPlc_Ext->lspold_Q15, M ); + + + IF (calcOnlyISF != 0) + { + /* ISF concealment simulation */ + getConcealedLSF( hPlc_Ext, xsfBase, st->clas_fx, L_frame ); + hPlc_Ext->T0 = hPlc_Ext->T0_4th; + move16(); + } + ELSE + { + Word16 old_exc_Qx[L_EXC_MEM+8]; + Word16 A_3Q12[(NB_SUBFR16k+1)*(M+1)]; + Word16 *speechLookAhead_Qx; + + /* calculate Q-value for input speech */ + speechLookAhead_Qx = &(st->speech_enc_pe[L_frame]); + + Copy( hPlc_Ext->old_exc_Qold, old_exc_Qx, 8 ); + Copy( hPlc_Ext->LPDmem->old_exc, &old_exc_Qx[8], L_EXC_MEM ); + Scale_sig( old_exc_Qx, 8, hPlc_Ext->Q_exp ); + + /* ISF concealment simulation */ + getConcealedLP( hPlc_Ext, A_3Q12, xsfBase, st->clas_fx, L_frame ); + + /* apply encoder side PLC simulation */ + hPlc_Ext->pit_min = st->pit_min; + move16(); + hPlc_Ext->pit_max = st->pit_max; + move16(); + coderLookAheadInnovation( A_3Q12, &(hPlc_Ext->T0), hPlc_Ext, speechLookAhead_Qx, old_exc_Qx, L_frame ); + } + return; +} + + +void GplcTcxEncSetup( Encoder_State_fx *st, HANDLE_PLC_ENC_EVS hPlc_Ext, Word16 Q_new ) +{ + hPlc_Ext->T0_4th = st->tcxltp_pitch_int; + move16(); + hPlc_Ext->Q_exp = sub( Q_new, hPlc_Ext->Q_new); + move16(); + hPlc_Ext->Q_new = Q_new; + move16(); + set16_fx( hPlc_Ext->old_exc_Qold, 0, 8); +} + +Word16 encSideSpecPowDiffuseDetector( + Word16 *lsf_ref, + Word16 *lsf_con, + Word32 sr_core, + Word16 *prev_lsf4_mean, + Word8 sw + , Word16 coder_type +) +{ + Word16 tmp; + Word16 lsf_mod[M]; + Word32 dist1, dist2, cum_dist1, cum_dist2; + Word16 lsf4_mean; + Word16 th; + Word16 idx; + Word16 cnt_imprv, i; + Word32 L_tmp; + Word16 th_dif; + + /* calculate the mean of the lowest 4 LSFs */ + + L_tmp = L_mult(lsf_ref[0], 8192/*1.0/4.0 Q15*/); + L_tmp = L_mac(L_tmp, lsf_ref[1], 8192/*1.0/4.0 Q15*/); + L_tmp = L_mac(L_tmp, lsf_ref[2], 8192/*1.0/4.0 Q15*/); + lsf4_mean = mac_r(L_tmp, lsf_ref[3], 8192/*1.0/4.0 Q15*/); + + IF(sw) + { + Copy(lsf_con, lsf_mod, M); + + modify_lsf(lsf_mod, M, sr_core, 1 ); + + move16(); + move16(); + cum_dist1 = 0; + cum_dist2 = 0; + + cnt_imprv = 0; + + IF( EQ_32( sr_core, 16000 )) + { + th = 2560; + move16(); /* LSF */ + th_dif = 288; + move16(); /* LSF */ + } + ELSE + { + th = 2048; + move16(); /* LSF */ + th_dif = 230; + move16(); /* LSF */ + } + + FOR(i = 0; i < M; i++) + { + tmp = sub(lsf_con[i], lsf_ref[i]); + dist1 = L_mult(tmp, tmp); + tmp = sub(lsf_mod[i], lsf_ref[i]); + dist2 = L_mult(tmp, tmp); + + if(GT_32(dist1, dist2)) + { + cnt_imprv = add(cnt_imprv, 1); + } + cum_dist1 = L_add(cum_dist1, dist1); + cum_dist2 = L_add(cum_dist2, dist2); + } + + idx = 0; + move16(); + + test(); + test(); + test(); + if(GT_32(cum_dist1, L_add(cum_dist2, Mpy_32_16_1(cum_dist2, 4915))) + && GT_16(sub(lsf4_mean, *prev_lsf4_mean), th_dif) + && LT_16(*prev_lsf4_mean, th) + && GT_16(cnt_imprv, 2) + && EQ_16(coder_type, GENERIC) ) + { + idx = 1; + move16(); + } + + } + ELSE + { + move16(); + idx = 0; + } + /* update parameters */ + move16(); + *prev_lsf4_mean = lsf4_mean; + + return idx; +} + +void updateSpecPowDiffuseIdx( Encoder_State_fx *st) +{ + Word16 min_gp; + Word16 k; + + + move32(); + move16(); + st->mean_gc[1] = st->gain_code[0]; + min_gp = st->bpf_gainT[0]; + + FOR(k = 1; k < 4; k++) + { + st->mean_gc[1] = L_add(st->mean_gc[1], st->gain_code[k]); + min_gp = s_min(min_gp, st->bpf_gainT[k]); + } + + /* Suppress saturation warning in threshold comparison. */ + test(); + if(LT_32(st->mean_gc[1], L_add(st->mean_gc[0], Mpy_32_16_r(st->mean_gc[0], 3211/*0.098 Q15*/)))|| + GT_16(min_gp, 13435/*0.82 Q14*/)) + { + move16(); + st->glr_idx [0]= 0; + } + move16(); + st->mean_gc[0] = st->mean_gc[1]; + +} + diff --git a/lib_enc/hf_cod_amrwb_fx.c b/lib_enc/hf_cod_amrwb_fx.c new file mode 100644 index 0000000..11a1299 --- /dev/null +++ b/lib_enc/hf_cod_amrwb_fx.c @@ -0,0 +1,224 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "stl.h" +#include "cnst_fx.h" + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +void hf_cod_init_fx( + Word16 *mem_hp400_enc, /* o: memory of hp 400 Hz filter */ + Word16 *mem_hf1_enc, /* o: HF band-pass filter memory */ + Word16 *mem_syn_hf_enc, /* o: HF synthesis memory */ + Word16 *mem_hf2_enc, /* o: HF band-pass filter memory */ + Word16 *gain_alpha_fx /* o: smoothing gain for transitions between active and inactive frames */ +) +{ + set16_fx( mem_hp400_enc, 0, 6); + set16_fx( mem_hf1_enc, 0, L_FIR-1 ); + set16_fx( mem_syn_hf_enc, 0, M ); + set16_fx( mem_hf2_enc, 0, L_FIR-1 ); + + *gain_alpha_fx = 16384; + move16(); + + return; +} + +void hf_cod_fx( + const Word32 core_brate_fx, /* i : core bitrate */ + const Word16 *speech16k_fx, /* i : original speech at 16 kHz */ + const Word16 Aq_fx[], /* i : quantized Aq */ + const Word16 exc_fx[], /* i : excitation at 12.8 kHz */ + Word16 synth_fx[], /* i : 12.8kHz synthesis signal */ + Word16 *seed2_enc_fx, /* i/o: random seed for HF noise gen */ + Word16 *mem_hp400_enc_fx, /* i/o: memory of hp 400 Hz filter */ + Word16 *mem_syn_hf_enc_fx, /* i/o: HF synthesis memory */ + Word16 *mem_hf1_enc_fx, /* i/o: HF band-pass filter memory */ + Word16 *mem_hf2_enc_fx, /* i/o: HF band-pass filter memory */ + const Word16 dtxHangoverCount_fx, + Word16 *gain_alpha_fx, /* i/o: smoothing gain for transitions between active and inactive frames */ + Word16 *hf_gain_fx, /* o : HF gain to be transmitted to decoder */ + Word16 Q_exc, + Word16 Q_syn +) +{ + /*------------------------Scaling------------------------------------------------- + speech16k - Q0 + Aq - Q12 + exc - Q_exc + synth - Q_syn + mem_hp400_enc - Q_syn + mem_syn_hf_enc - Q0 + mem_hf1_enc - Q0 + mem_hf2_enc - Q0 + gain_alpha_fx - Q14 + ener - all dynamic + fac, scale - Q12 + Ap - Q12 + HF_SP - Q0 + ---------------------------------------------------------------------------------*/ + + Word16 i, q1, q2, sign; + Word16 shift; + Word16 ener_hf_fx, ener_exc_fx, ener_input_fx, fac_fx, tmp_fx, ener_fx, scale_fx; + Word16 Ap_fx[M+1]; + Word16 HF_SP_fx[L_SUBFR16k]; + Word16 HF_est_gain_fx, HF_calc_gain_fx, HF_corr_gain_fx, HF_gain_ind_fx; + Word32 dist_min_fx, dist_fx; + Word16 HF_fx[L_SUBFR16k], HF_syn_fx[L_SUBFR16k]; /* o : HF excitation */ + Word32 L_tmp; + Word16 *pt1; + const Word16 *pt2; + + /* Original speech signal as reference for high band gain quantisation */ + Copy(speech16k_fx, HF_SP_fx, L_SUBFR16k); + + /*-----------------------------------------------------------------* + * generate white noise vector + *-----------------------------------------------------------------*/ + + Random_Fill(seed2_enc_fx, L_SUBFR16k, HF_fx, 3); /*Q(-3) */ + + /*-----------------------------------------------------------------* + * calculate energy scaling factor so that white noise would have the + * same energy as exc12k8 + *-----------------------------------------------------------------*/ + + ener_exc_fx = dot_prod_satcontr(exc_fx, exc_fx, Q_exc, Q_exc, &q1, L_SUBFR); + ener_hf_fx = dot_prod_satcontr(HF_fx, HF_fx, -3, -3, &q2, L_SUBFR16k); + + scale_fx = div_s(shl(1, 14), ener_exc_fx); /*Q(29-q1) */ + L_tmp = L_mult(ener_hf_fx, scale_fx); /*30-q1+q2 */ + q2 = sub(q1, q2); /*30-q2 */ + scale_fx = round_fx(Isqrt(L_shl(L_tmp, sub(q2, 26)))); /*Q13 */ + + + pt1 = HF_fx; + FOR( i = 0; i < L_SUBFR16k; i++ ) + { + *pt1 = round_fx(L_shl(L_mult((*pt1), scale_fx), 5)); /*Q0 */ + pt1++; + } + + /*-----------------------------------------------------------------* + * calculate energy scaling factor to respect tilt of synth12k8 + * (tilt: 1=voiced, -1=unvoiced) + *-----------------------------------------------------------------*/ + + hp400_12k8_fx( synth_fx, L_SUBFR, mem_hp400_enc_fx ); /*synth_fx: Q(Q_syn-4) */ + + ener_fx = dot_prod_satcontr(&synth_fx[1], &synth_fx[1], sub(Q_syn, 4), sub(Q_syn, 4), &q1, sub(L_SUBFR, 1)); + tmp_fx = dot_prod_satcontr(&synth_fx[1], synth_fx, sub(Q_syn ,4), sub(Q_syn, 4), &q2, sub(L_SUBFR, 1)); + + IF ( GE_16(abs_s(tmp_fx), ener_fx )) + { + tmp_fx = shr(tmp_fx, 1); + q2 = sub(q2, 1); + } + + sign = 0; + move16(); + IF ( tmp_fx < 0 ) + { + tmp_fx = abs_s(tmp_fx); + sign = 1; + move16(); + } + + fac_fx = div_s(tmp_fx, ener_fx); /*Q(15+q2-q1) */ + shift = sub(q1, add(q2, 5)); + fac_fx = shl(fac_fx, shift); /*Q10 */ + IF (sign) + { + fac_fx = s_xor(fac_fx, -1); + } + + HF_est_gain_fx = sub(1024, fac_fx); /*Q12 */ + + test(); + IF( EQ_32(core_brate_fx, SID_1k75)||core_brate_fx==FRAME_NO_DATA) + { + HF_est_gain_fx = round_fx(L_shl(L_mult(HF_est_gain_fx, 20480), 1)); /*Q10 */ + } + + HF_est_gain_fx = s_max(HF_est_gain_fx, 102); + HF_est_gain_fx = s_min(HF_est_gain_fx, 1024); + + /*-----------------------------------------------------------------* + * synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz + *-----------------------------------------------------------------*/ + + weight_a_lc_fx( Aq_fx, Ap_fx, Gamma_19661_Tbl_fx, M ); + Syn_filt_s( 0, Ap_fx, M, HF_fx, HF_syn_fx, L_SUBFR16k, mem_syn_hf_enc_fx, 1 ); /*Q0 */ + + /*-----------------------------------------------------------------* + * high pass filtering (0.9375ms of delay = 15 samples@16k) + *-----------------------------------------------------------------*/ + + fir_fx(HF_syn_fx, fir_6k_8k_fx, HF_syn_fx, mem_hf1_enc_fx, L_SUBFR16k, L_FIR-1, 1, 0); + fir_fx(HF_SP_fx, fir_6k_8k_fx, HF_SP_fx, mem_hf2_enc_fx, L_SUBFR16k, L_FIR-1, 1, 0); + + /* check the gain difference */ + + ener_hf_fx = dot_prod_satcontr(HF_syn_fx, HF_syn_fx, 0, 0, &q2, L_SUBFR16k); + ener_input_fx = dot_prod_satcontr(HF_SP_fx, HF_SP_fx, 0, 0, &q1, L_SUBFR16k); + + HF_calc_gain_fx = div_s(shl(1, 14), ener_input_fx); /*Q(29-q1) */ + L_tmp = L_mult(ener_hf_fx, HF_calc_gain_fx); /*30-q1+q2 */ + q2 = sub(q1, q2); /*30-q2 */ + HF_calc_gain_fx = round_fx(Isqrt(L_shl(L_tmp, sub(q2, 20)))); /*Q10 */ + + + /* set energy of HF synthesis to energy of original HF: + cross-fade between HF levels in active and inactive frame in hangover period */ + + IF ( GT_16(4, dtxHangoverCount_fx)) + { + *gain_alpha_fx = 16384; + move16(); + } + ELSE + { + L_tmp = L_shl(L_mult(sub(10, dtxHangoverCount_fx), 4681), 15);/*Q31 */ + L_tmp = Mult_32_16(L_tmp, *gain_alpha_fx); /*Q30 */ + *gain_alpha_fx = round_fx(L_tmp); /*Q14 */ + } + L_tmp = L_mult(sub(16384, *gain_alpha_fx), HF_est_gain_fx); /*Q25 */ + L_tmp = L_mac(L_tmp, *gain_alpha_fx, HF_calc_gain_fx); /*Q25 */ + IF (GE_32(L_tmp,67108863)) + { + L_tmp = 67108863; + move32(); + } + L_tmp = L_shl(L_tmp, 5); + HF_corr_gain_fx = extract_h(L_tmp); /*Q14; HF_corr_gain_fx/2 in Q15 */ + + /* Quantize the correction gain */ + dist_min_fx = 2147483647; + move32(); + HF_gain_ind_fx = 0; + move16(); + pt2 = HP_gain_fx; + FOR ( i = 0; i < 16; i++ ) + { + dist_fx = L_mult(sub(HF_corr_gain_fx, *pt2), sub(HF_corr_gain_fx, *pt2)); + pt2++; + IF ( GT_32(dist_min_fx, dist_fx)) + { + dist_min_fx = L_add(dist_fx, 0); + HF_gain_ind_fx = i; + move16(); + } + } + *hf_gain_fx = HF_gain_ind_fx; + move16(); + + return; +} diff --git a/lib_enc/hq_classifier_enc_fx.c b/lib_enc/hq_classifier_enc_fx.c new file mode 100644 index 0000000..602c334 --- /dev/null +++ b/lib_enc/hq_classifier_enc_fx.c @@ -0,0 +1,671 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" /* Debug prototypes */ + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +#define SHARP_DIST_THRES 22.2f +#define SHARP_DIST_THRES_FX 1420 /* Q6, 22.2 */ + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + +void hvq_classifier_fx( const Word32 *input, Word16 *prev_Npeaks, Word16 *prev_peaks, + Word16 *hqswb_clas, Word16 *Npeaks, Word16 *peaks, const Word32 L_core_brate, + const Word16 last_core, Word32 *L_nf_gains, Word16 *hvq_hangover, Word32 *L_pe_gains ); + +/*--------------------------------------------------------------------------* + * hq_classifier_enc_fx() + * + * HQ mode selector (decision_matrix) + *--------------------------------------------------------------------------*/ + +Word16 hq_classifier_enc_fx( /* o : Consumed bits Q0 */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 length, /* i : Frame length Q0 */ + const Word32 *coefs, /* i : Spectral coefficients Q12 */ + const Word16 is_transient, /* i : Transient flag Q0 */ + Word16 *Npeaks, /* o : Number of identified peaks Q0 */ + Word16 *peaks, /* o : Peak indices Q0 */ + Word32 *pe_gains, /* o : Peak gains Q12 */ + Word32 *nf_gains, /* o : Noise-fill gains Q12 */ + Word16 *hqswb_clas /* o : HQ class Q0 */ +) +{ + Word16 bits; + + *hqswb_clas = HQ_NORMAL; + IF( EQ_16( is_transient, 1)) + { + *hqswb_clas = HQ_TRANSIENT; + move16(); + } + + /* classification and limit bandwidth for bit allocation */ + test(); + test(); + test(); + IF( EQ_16(length, L_FRAME32k)&&NE_16(is_transient,1)&&LE_32(st_fx->core_brate_fx,HQ_32k)&&EQ_16(st_fx->bwidth_fx,st_fx->last_bwidth_fx)) + { + /* Detect HQ_HARMONIC mode */ + *hqswb_clas = peak_avrg_ratio_fx( st_fx->total_brate_fx, coefs, NUMC_N+96, &st_fx->mode_count_fx, &st_fx->mode_count1_fx, 12 ); + + /* Detect harmonic VQ mode HQ_HVQ */ + hvq_classifier_fx( coefs, &st_fx->prev_Npeaks_fx, st_fx->prev_peaks_fx, hqswb_clas, Npeaks, peaks, st_fx->core_brate_fx, st_fx->last_core_fx, + nf_gains, &st_fx->hvq_hangover_fx, pe_gains ); + } + + test(); + test(); + test(); + IF ( EQ_16(length, L_FRAME48k)&&NE_16(is_transient,1)&&LE_32(st_fx->core_brate_fx,HQ_32k)&&EQ_16(st_fx->bwidth_fx,st_fx->last_bwidth_fx)) + { + /* Detect HQ_HARMONIC mode */ + *hqswb_clas = peak_avrg_ratio_fx( st_fx->total_brate_fx, coefs, NUMC_N+96, &st_fx->mode_count_fx, &st_fx->mode_count1_fx, 12); + /* Detect harmonic VQ mode HQ_HVQ */ + hvq_classifier_fx( coefs, &st_fx->prev_Npeaks_fx, st_fx->prev_peaks_fx, hqswb_clas, Npeaks, peaks, + st_fx->core_brate_fx, st_fx->last_core_fx, nf_gains, &st_fx->hvq_hangover_fx, pe_gains ); + } + + test(); + test(); + IF( EQ_16(length, L_FRAME48k)&&LE_32(st_fx->core_brate_fx,HQ_32k)&&EQ_16(*hqswb_clas,HQ_NORMAL)) + { + *hqswb_clas = HQ_GEN_FB; + move16(); + } + + test(); + IF( GE_16( length, L_FRAME32k)&&LE_32(st_fx->core_brate_fx,HQ_32k)) + { + bits = 2; + move16(); + } + ELSE + { + bits = 1; + move16(); + } + + test(); + IF ( EQ_16( length, L_FRAME48k)&&LE_32(st_fx->core_brate_fx,HQ_32k)) + { + IF ( GE_16( *hqswb_clas, HQ_GEN_SWB)) + { + push_indice_fx( st_fx, IND_HQ_SWB_CLAS, *hqswb_clas - 5, bits ); + } + ELSE + { + push_indice_fx( st_fx, IND_HQ_SWB_CLAS, *hqswb_clas, bits ); + } + } + ELSE + { + push_indice_fx( st_fx, IND_HQ_SWB_CLAS, *hqswb_clas, bits ); + } + + test(); + test(); + IF ( EQ_16( *hqswb_clas, HQ_NORMAL)&&EQ_16(length,L_FRAME32k)&&LE_32(st_fx->core_brate_fx,HQ_32k)) + { + *hqswb_clas = HQ_GEN_SWB; + move16(); + } + + return bits; +} + +/*--------------------------------------------------------------------------* + * peak_avrg_ratio() + * + * Classify the input signal and decide if it has a harmonic structure + *--------------------------------------------------------------------------*/ +Word16 peak_avrg_ratio_fx( + const Word32 total_brate, + const Word32 *input_hi_fx, /* i : input signal */ + const Word16 length, /* i : number of coefficients */ + Word16 *mode_count, /* i/o: HQ_HARMONIC mode count */ + Word16 *mode_count1, /* i/o: HQ_NORMAL mode count */ + Word16 Q_coeff +) +{ + Word16 i, j, q, k, k1, hqswb_clas; + Word32 mean_fx, peak_fx; + Word32 input_abs_fx[L_FRAME32k]; + Word32 peak_th_fx; + + FOR ( i = 96; i < length; i++) + { + input_abs_fx[i] = L_abs(input_hi_fx[i]); + } + + hqswb_clas = HQ_NORMAL; + move16(); + peak_th_fx = L_shl(10L, sub(Q_coeff, 5)); /* 5 is safe shift */ + + k = 0; + move16(); + k1 = 0; + move16(); + q = 96; /* q used for indexing */ + + FOR( i = 3; i < 17; i ++ ) + { + peak_fx = L_deposit_l(0); + mean_fx = L_deposit_l(1); + + /*for(j = 0; j < 32; j ++, q ++) */ + FOR(j = 0; j < 32; j ++) + { + input_abs_fx[q] =L_shr(input_abs_fx[q],5); /*Q_coeff-5 */ + mean_fx =L_add(mean_fx,input_abs_fx[q]); /*Q_coeff-5 */ + IF (GT_32(input_abs_fx[q] , peak_fx)) + { + peak_fx =input_abs_fx[q] ; /*Q_coeff-5 */ + } + q ++; + } + + IF(LT_16(i,8)) + { + if(GT_32(peak_fx, Mult_32_16(mean_fx, 4608))) /* Q15 0.140625 */ + { + k = add(k,1); + } + } + ELSE + { + test(); + if(GT_32(peak_fx, Mult_32_16(mean_fx, 3686)) /*Q15 0.1125 */ + && GT_32(peak_fx, peak_th_fx)) /*Q27 10 */ + { + k1 = add(k1,1); + } + } + } + + test(); + IF( GE_16(add(k,k1),10)&>_16(k1,5)) + { + if( LT_16(*mode_count,8)) + { + *mode_count = add(*mode_count,1); + } + + if( *mode_count1 > 0 ) + { + *mode_count1 = sub(*mode_count1,1); + } + } + ELSE + { + if( LT_16(*mode_count1,8)) + { + *mode_count1 = add(*mode_count1,1); + } + + if( *mode_count > 0 ) + { + *mode_count = sub(*mode_count,1); + } + } + + test(); + test(); + test(); + test(); + test(); + test(); + if ((GE_16(add(k, k1), 5)&>_16(k1,2)&&EQ_32(total_brate,HQ_24k40)) + || (((GE_16(add(k, k1), 10) && GT_16(k1, 5) ) || GE_16(*mode_count, 5) ) && LT_16(*mode_count1, 5) )) + { + hqswb_clas = HQ_HARMONIC; + move16(); + } + + return hqswb_clas; +} + +/*--------------------------------------------------------------------------* + * hvq_classifier() + * + * Classification of harmonic low band content for Harmonic VQ + *--------------------------------------------------------------------------*/ + +void hvq_classifier_fx( + const Word32 *input, /* i : input signal Q12 */ + Word16 *prev_Npeaks, /* i/o: Peak number memory Q0 */ + Word16 *prev_peaks, /* i/o: Peak indices memory Q0 */ + Word16 *hqswb_clas, /* i/o: HQ class Q0 */ + Word16 *Npeaks, /* o : Number of peaks Q0 */ + Word16 *peaks, /* o : Peak indices Q0 */ + const Word32 L_core_brate, /* i : Core bit-rate Q0 */ + const Word16 last_core, /* i : Last core used Q0 */ + Word32 *L_nf_gains, /* o : Noisefloor gains Q12 */ + Word16 *hvq_hangover, /* i/o: Mode-switch hangover Q0 */ + Word32 *L_pe_gains /* o : peak gains Q12 */ +) +{ + const Word16 *p_adj; + UWord16 lsb; + + Word32 L_input_abs[L_FRAME32k]; + Word32 L_input_max; + Word32 L_thr[L_FRAME16k]; + Word32 L_thr_tmp; + Word32 L_m; + Word32 L_tmp; + Word32 L_d; + Word32 L_peak; + Word32 L_nf, L_pe; + Word32 L_pe_mean[HVQ_NSUB_32k], L_nf_mean[HVQ_NSUB_32k]; + + Word16 inv_nsub; + Word16 sharp_dist; + Word16 exp1, exp2; + Word16 tmp; + Word16 shift; + Word16 idx; + Word16 frac; + Word16 inv_nf_mean; + Word16 inv_gains_nsub; + Word16 nf_mean_norm; + Word16 num_sharp_bands, i, j, k, q, peak_th, nsub, pindx, N, offset; + Word16 num_peak_cands, high, low; + Word16 sharp[HVQ_NSUB_32k]; + Word16 peak_cand_idx[HVQ_THRES_BIN_32k], avail_peaks[HVQ_NSUB_32k]; + + L_input_max = L_deposit_l(0); + set32_fx(L_thr, 0, L_FRAME16k); + + IF ( EQ_32(L_core_brate, HQ_24k40)) + { + nsub = HVQ_NSUB_24k; + move16(); + inv_nsub = 4681; + move16(); /* 1/7 in Q15 */ + inv_gains_nsub = 10923; + move16(); /* 1/3 in Q15 */ + } + ELSE + { + nsub = HVQ_NSUB_32k; + move16(); + inv_nsub = 3277; + move16(); /* 1/10 in Q15 */ + inv_gains_nsub = 6554; + move16(); /* 1/5 in Q15 */ + } + + N = shl(nsub, 5); /* Mult by 32 (HVQ_BW) */ + + test(); + test(); + IF ( EQ_16(*hqswb_clas, HQ_HARMONIC)&&last_core!=ACELP_CORE&&NE_16(last_core,AMR_WB_CORE)) + { + FOR ( i = 0; i < N; i++ ) + { + L_input_abs[i] = L_abs(input[i]); + if (L_input_abs[i] > L_input_max) + { + L_input_max = L_input_abs[i]; + move16(); + } + } + + exp1 = norm_l(L_input_max); + + *Npeaks = 0; + move16(); + L_nf = 3276800; + move32(); /* 800 in Q12 */ + L_pe = 3276800; + move32(); /* 800 in Q12 */ + num_sharp_bands = 0; + move16(); + k = 0; + move16(); + q = 0; + move16(); + sharp_dist = 0; + move16(); + + /* Find peak threshold */ + FOR ( i = 0; i < nsub; i++ ) + { + L_peak = 0; + L_nf_mean[i] = 0; + L_pe_mean[i] = 0; + FOR ( j = 0; j < HVQ_BW; j++ ) + { + L_d = L_input_abs[q]; + IF ( GT_32(L_d, L_nf)) + { + /*nf = HVQ_NF_WEIGHT1 * nf + (1 - HVQ_NF_WEIGHT1) * d; */ + Mpy_32_16_ss(L_d, HVQ_NF_WEIGHT1B, &L_tmp, &lsb); /* 12+15-15=12 */ + Mpy_32_16_ss(L_nf, HVQ_NF_WEIGHT1_FX, &L_nf, &lsb); /* 12+15-15=12 */ + L_nf = L_add(L_nf, L_tmp); /*Q12 */ + } + ELSE + { + /*nf = HVQ_NF_WEIGHT2 * nf + (1 - HVQ_NF_WEIGHT2) * d; */ + Mpy_32_16_ss(L_d, HVQ_NF_WEIGHT2B, &L_tmp, &lsb); /* 12+15-15=12 */ + Mpy_32_16_ss(L_nf, HVQ_NF_WEIGHT2_FX, &L_nf, &lsb); /* 12+15-15=12 */ + L_nf = L_add(L_nf, L_tmp); /*Q12 */ + } + + IF ( GT_32(L_d, L_pe)) + { + /*pe = HVQ_PE_WEIGHT1 * pe + (1 - HVQ_PE_WEIGHT1) * d; */ + Mpy_32_16_ss(L_d, HVQ_PE_WEIGHT1B, &L_tmp, &lsb); /* 12+15-15=12 */ + Mpy_32_16_ss(L_pe, HVQ_PE_WEIGHT1_FX, &L_pe, &lsb); /* 12+15-15=12 */ + L_pe = L_add(L_pe, L_tmp); /*Q12 */ + } + ELSE + { + /*pe = HVQ_PE_WEIGHT2 * pe + (1 - HVQ_PE_WEIGHT2) * d; */ + Mpy_32_16_ss(L_d, HVQ_PE_WEIGHT2B, &L_tmp, &lsb); /* 12+15-15=12 */ + Mpy_32_16_ss(L_pe, HVQ_PE_WEIGHT2_FX, &L_pe, &lsb); /* 12+15-15=12 */ + L_pe = L_add(L_pe, L_tmp); /*Q12 */ + } + + L_nf_mean[i] = L_add(L_nf_mean[i], L_nf); + L_pe_mean[i] = L_add(L_pe_mean[i], L_pe); + + IF ( GT_32(L_d, L_peak)) + { + L_peak = L_add(L_d, 0); + } + + q = add(q, 1); + } + L_nf_mean[i] = L_shr(L_nf_mean[i], 5); /* Divide by 5 (HVQ_BW) */ + L_pe_mean[i] = L_shr(L_pe_mean[i], 5); /* Divide by 5 (HVQ_BW) */ + + /*thr_tmp = (float)pow( pe_mean[i]/nf_mean[i], HVQ_THR_POW ) * nf_mean[i]; */ + exp1 = norm_l(L_nf_mean[i]); + nf_mean_norm = extract_h(L_shl(L_nf_mean[i], exp1)); /* 12+s-16=s-4 */ + IF ( nf_mean_norm == 0 ) + { + inv_nf_mean = 0; + } + ELSE + { + inv_nf_mean = div_s(1<<14, nf_mean_norm); /* 15+14-s+4=33-s */ + } + Mpy_32_16_ss(L_pe_mean[i], inv_nf_mean, &L_tmp, &lsb); /*12+33-s-15=30-s */ + + exp2 = norm_l(L_tmp); + tmp = Log2_norm_lc(L_shl(L_tmp, exp2)); /* Q15 */ + exp2 = exp1 - exp2; /* Q0 */ + L_tmp = Mpy_32_16(exp2, tmp, 32767); /* 1 in Q15. Q16 */ + Mpy_32_16_ss(L_tmp, 28836, &L_tmp, &lsb); /* 16+15-15=16 */ + frac = L_Extract_lc(L_tmp, &tmp); /* Q15 and Q0 */ + L_tmp = Pow2(14, frac); /* Q14 */ + L_tmp = L_shl(L_tmp, tmp); /* Q14 */ + + Mpy_32_16_ss(L_tmp, nf_mean_norm, &L_tmp, &lsb); /*14+s-4-15=s-5 */ + shift = sub(17, exp1); /* 16-(s-5)=17-s */ + L_thr_tmp = L_shl(L_tmp, shift); /* Q16 */ + L_thr_tmp = L_add(L_thr_tmp, lshr(lsb, sub(16, shift))); /*Q16 */ + + set32_fx(&L_thr[k], L_thr_tmp, HVQ_BW); + k = add(k, HVQ_BW); + + /*sharp[i] = peak/nf_mean[i]; */ + Mpy_32_16_ss(L_peak, inv_nf_mean, &L_tmp, &lsb); /* 12+33-s-15=30-s */ + shift = sub(exp1, 8); + sharp[i] = extract_h(L_shl(L_tmp, shift)); /* 30-s+s-8-16 -> Q6 */ + + /*sharp_dist += (sharp[i]-HVQ_SHARP_THRES); */ + sharp_dist = add(sharp_dist, sub(sharp[i], HVQ_SHARP_THRES_FX)); + + if ( GT_16(sharp[i], HVQ_SHARP_THRES_FX)) + { + num_sharp_bands = add(num_sharp_bands, 1); + } + } + + /* Estimate noise floor gains */ + offset = s_and(nsub, 1); + FOR ( i = 0; i < s_and(nsub, (Word16)0xFFFE); i++ ) + { + /*(2*i+1)/nsub */ + idx = mult(add(shl(i, 1), 1), add(inv_nsub, 1)); /*0+15-15 = 0 */ + L_nf_gains[idx] = L_add(L_nf_gains[idx], L_nf_mean[i+offset]); + L_pe_gains[idx] = L_add(L_pe_gains[idx], L_pe_mean[i+offset]); + } + + FOR ( i = 0; i < HVQ_NF_GROUPS; i++ ) + { + Mpy_32_16_ss(L_nf_gains[i], inv_gains_nsub, &L_nf_gains[i], &lsb); /*12+15-15=12 */ + Mpy_32_16_ss(L_pe_gains[i], inv_gains_nsub, &L_pe_gains[i], &lsb); /*12+15-15=12 */ + } + + /* Allocate available peaks */ + FOR ( i = 0; i < nsub; i++ ) + { + avail_peaks[i] = HVQ_PA_PEAKS_SHARP1; + move16(); + idx = mult(add(shl(i, 1), 1), add(inv_nsub, 1)); /*0+15-15 = 0 */ + Mpy_32_16_ss(L_nf_gains[idx], HVQ_PA_FAC_FX, &L_tmp, &lsb); /* 12+15-15 -> Q12 */ + IF( LT_32(L_nf_mean[i], L_tmp)) + { + IF ( LT_16(sharp[i], HVQ_PA_SHARP_THRES3_FX)) + { + avail_peaks[i] = HVQ_PA_PEAKS_SHARP3; + move16(); + } + ELSE IF( LT_16(sharp[i], HVQ_PA_SHARP_THRES2_FX)) + { + avail_peaks[i] = HVQ_PA_PEAKS_SHARP2; + move16(); + } + } + } + + + + /* Adjust threshold around previous peaks */ + FOR ( i = 0; i < *prev_Npeaks; i++ ) + { + j = sub(prev_peaks[i], 2); + k = add(prev_peaks[i], 2); + p_adj = hvq_thr_adj_fx; + + FOR( q = j; q < k; q++ ) + { + Mpy_32_16_ss(L_thr[q], *p_adj++, &L_thr[q], &lsb); /* 12+15-15=12 */ + move32(); + } + } + + num_peak_cands = 0; + move16(); + + /* Remove everything below threshold for peak search */ + L_input_abs[0] = L_deposit_l(0); + L_input_abs[1] = L_deposit_l(0); + L_input_abs[N-2] = L_deposit_l(0); + L_input_abs[N-1] = L_deposit_l(0); + FOR ( i = 0; i < N-2; i++ ) + { + IF ( LT_32(L_input_abs[i], L_thr[i])) + { + L_input_abs[i] = L_deposit_l(0); + } + ELSE + { + L_input_abs[num_peak_cands] = L_input_abs[i]; + move32(); + peak_cand_idx[num_peak_cands] = i; + move16(); + num_peak_cands = add(num_peak_cands, 1); + } + } + + IF ( EQ_32(L_core_brate, HQ_24k40)) + { + peak_th = HVQ_MAX_PEAKS_24k_CLAS; + move16(); + } + ELSE + { + peak_th = HVQ_MAX_PEAKS_32k; + move16(); + } + + /* Find peaks */ + pindx = maximum_32_fx(L_input_abs, num_peak_cands, &L_m); + i = 0; + move16(); + + WHILE ( L_m > 0 && LT_16(i, peak_th+1)) + { + idx = mult(peak_cand_idx[pindx], INV_HVQ_BW); /* 0+15-15=0 */ + IF ( avail_peaks[idx] > 0 ) + { + peaks[i++] = peak_cand_idx[pindx]; + avail_peaks[idx]--; + } + + j = sub(pindx, 2); + k = add(pindx, 2); + + if ( j < 0 ) + { + j = 0; + move16(); + } + + tmp = sub(num_peak_cands, 1); + if ( GT_16(k, tmp)) + { + k = tmp; + move16(); + } + + low = sub(peak_cand_idx[pindx], 2); + high = add(peak_cand_idx[pindx], 2); + + if ( low < 0 ) + { + low = 0; + move16(); + } + + tmp = sub(N, 1); + if ( GT_16(high, tmp)) + { + high = tmp; + move16(); + } + + FOR( q = j; q <= pindx; q++ ) + { + IF( GE_16(peak_cand_idx[q], low)) + { + peak_cand_idx[q] = 0; + move16(); + L_input_abs[q] = 0; + move16(); + } + } + + FOR( q = pindx + 1; q <= k; q++ ) + { + IF ( LE_16(peak_cand_idx[q], high)) + { + peak_cand_idx[q] = 0; + move16(); + L_input_abs[q] = 0; + move16(); + } + } + + pindx = maximum_32_fx(L_input_abs, num_peak_cands, &L_m); + } + + *Npeaks = i; + move16(); + IF ( GT_16(*Npeaks, HVQ_MIN_PEAKS)) + { + test(); + IF ( GT_16(num_sharp_bands, sub(nsub, 3))&&LE_16(*Npeaks,peak_th)) + { + sharp_dist = mult(sharp_dist, inv_nsub); /*x+15-15=x */ + test(); + IF ( LE_16(sharp_dist, SHARP_DIST_THRES_FX)&&*hvq_hangover<0) + { + *hvq_hangover = add(*hvq_hangover, 1); + } + ELSE + { + *hqswb_clas = HQ_HVQ; + move16(); + *hvq_hangover = 2; + move16(); + } + + /* update memory */ + *prev_Npeaks = *Npeaks; + move16(); + Copy( peaks, prev_peaks, *Npeaks ); + } + ELSE + { + IF( *hvq_hangover > 0 ) + { + *hqswb_clas = HQ_HVQ; + move16(); + *hvq_hangover = sub(*hvq_hangover, 1); + move16(); + } + ELSE + { + *hvq_hangover = -1; + move16(); + } + } + } + ELSE + { + /* Zero peaks, likely silence input. */ + *hvq_hangover = -1; + move16(); + } + + + IF ( EQ_32(L_core_brate, HQ_24k40)) + { + *Npeaks = s_min( HVQ_MAX_PEAKS_24k, *Npeaks ); + move16(); + } + ELSE + { + *Npeaks = s_min( HVQ_MAX_PEAKS_32k, *Npeaks ); + move16(); + } + } + ELSE + { + *prev_Npeaks = 0; + move16(); + *hvq_hangover = 0; + move16(); + } + + + return; +} + + diff --git a/lib_enc/hq_core_enc_fx.c b/lib_enc/hq_core_enc_fx.c new file mode 100644 index 0000000..7546f02 --- /dev/null +++ b/lib_enc/hq_core_enc_fx.c @@ -0,0 +1,202 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------------- + * hq_core_enc() + * + * HQ core encoder + *--------------------------------------------------------------------------*/ + +void hq_core_enc_fx( + Encoder_State_fx *st_fx, + const Word16 *audio, /* i : input audio signal Q0 */ + const Word16 input_frame_orig, /* i : frame length */ + const Word16 hq_core_type, /* i : HQ core type */ + const Word16 Voicing_flag +) +{ + Word16 i, is_transient, num_bits, extra_unused; + Word32 wtda_audio[2 * L_FRAME48k]; + Word32 t_audio[L_FRAME48k]; /* Q12 */ + Word16 Q_audio = 0; + Word16 inner_frame, input_frame; + Word16 ener_match; /* Q13/Q15 */ + + Word16 tmp; + Word32 L_tmp; + UWord16 lsb; + + Word16 two_frames_buffer[2*L_FRAME48k]; + + set32_fx( t_audio, 0, L_FRAME48k ); + st_fx->Nb_ACELP_frames_fx = 0; + move16(); + + /* set input_frame length */ + input_frame = input_frame_orig; + move16(); + + st_fx->tcx_cfg.tcx_last_overlap_mode = st_fx->tcx_cfg.tcx_curr_overlap_mode; + move16(); + st_fx->tcx_cfg.tcx_curr_overlap_mode = ALDO_WINDOW; + move16(); + + /*-------------------------------------------------------------------------- + * Preprocessing in the first HQ frame after ACELP frame + * Find the number of bits for PVQ coding + * Write signalling information + *--------------------------------------------------------------------------*/ + + /*num_bits = (short)(st->total_brate / 50); */ + Mpy_32_16_ss(st_fx->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + num_bits = extract_l(L_shr(L_tmp, 3)); /*Q0 */ + extra_unused = 0; + move16(); + + /*-------------------------------------------------------------------------- + * Detect signal transition + *--------------------------------------------------------------------------*/ + + is_transient = detect_transient_fx( audio, input_frame, HQ_CORE, 0, st_fx); + + /*-------------------------------------------------------------------------- + * Windowing and time-domain aliasing + * DCT transform + *--------------------------------------------------------------------------*/ + + Copy( st_fx->old_input_signal_fx, two_frames_buffer, input_frame ); + Copy( audio, two_frames_buffer+input_frame, input_frame ); + + wtda_fx( two_frames_buffer+input_frame, &Q_audio, wtda_audio, NULL, 0, + st_fx->tcx_cfg.tcx_last_overlap_mode, st_fx->tcx_cfg.tcx_curr_overlap_mode, input_frame ); + + test(); + IF ( st_fx->last_core_fx == ACELP_CORE || EQ_16(st_fx->last_core_fx, AMR_WB_CORE)) + { + /* Preprocessing in the first HQ frame after ACELP frame */ + core_switching_hq_prepare_enc_fx( st_fx, &num_bits, input_frame, wtda_audio, two_frames_buffer+input_frame ); + + /* During ACELP->HQ core switching, limit the HQ core bitrate to 48kbps */ + IF ( GT_16(num_bits, ACELP_48k_BITS)) + { + extra_unused = sub(num_bits, ACELP_48k_BITS); + num_bits = ACELP_48k_BITS; + move16(); + } + } + + /* subtract signalling bits */ + num_bits = sub(num_bits, st_fx->nb_bits_tot_fx); + + direct_transform_fx( wtda_audio, t_audio, is_transient, input_frame, &Q_audio ); + + /* scale coefficients to their nominal level (8kHz) */ + IF ( NE_16(input_frame, NORM_MDCT_FACTOR)) + { + IF (EQ_16(input_frame, L_FRAME32k)) + { + Q_audio = add(Q_audio, 1); /* Divide by 2 */ + } + ELSE + { + tmp = mult_r(input_frame, 410/2); /* 1/8000 in Q15 */ + ener_match = hq_nominal_scaling[tmp]; + FOR( i=0; i < input_frame; i++ ) + { + /*t_audio_q[i] *= ener_match; */ + Mpy_32_16_ss(t_audio[i], ener_match, &t_audio[i], &lsb); + move16(); /* Q12 */ + } + } + } + + /* limit encoded band-width according to the command-line OR BWD limitation */ + inner_frame = inner_frame_tbl[st_fx->bwidth_fx]; + move16(); + + IF( GT_16(input_frame, inner_frame)) + { + IF( EQ_16(is_transient, 1)) + { + FOR ( i = 1; i < NUM_TIME_SWITCHING_BLOCKS; i++ ) + { + tmp = i_mult2(i, shr(input_frame, 2)); + tmp = shr(inner_frame, 2); + Copy32( t_audio + i_mult2(i, shr(input_frame, 2)), t_audio + i_mult2(i, tmp), tmp ); + } + } + + set32_fx( t_audio + inner_frame, 0, sub(input_frame, inner_frame) ); + } + + /*-------------------------------------------------------------------------- + * Classify whether to put extra bits for FER mitigation + *--------------------------------------------------------------------------*/ + + test(); + IF ( EQ_16(st_fx->last_core_fx, HQ_CORE)&>_32(st_fx->core_brate_fx,MINIMUM_RATE_TO_ENCODE_VOICING_FLAG)) + { + IF ( Voicing_flag > 0 ) + { + push_indice_fx( st_fx, IND_HQ_VOICING_FLAG, 1, 1 ); + num_bits = sub(num_bits, 1); + + } + ELSE + { + push_indice_fx( st_fx, IND_HQ_VOICING_FLAG, 0, 1 ); + num_bits = sub(num_bits, 1); + } + } + + /*-------------------------------------------------------------------------- + * Transform-domain encoding + *--------------------------------------------------------------------------*/ + + IF ( EQ_16(hq_core_type, LOW_RATE_HQ_CORE)) + { + /* HQ low rate encoder */ + FOR (i = 0; i < inner_frame; i++) + { + t_audio[i] = L_shr(t_audio[i], sub(Q_audio, 12)); /* Q12 */ + } + hq_lr_enc_fx( st_fx, t_audio, inner_frame, &num_bits, is_transient ); + Q_audio = 12; + move16(); + } + ELSE + { + /* HQ high rate encoder */ + FOR (i = 0; i < inner_frame; i++) + { + t_audio[i] = L_shr(t_audio[i], sub(Q_audio, 12)); /* Q12 */ + } + + hq_hr_enc_fx( st_fx, t_audio, inner_frame, &num_bits, is_transient ); + Q_audio = 12; + move16(); + } + + /* write all unused bits to the bitstream */ + num_bits = add(num_bits, extra_unused); + + WHILE( num_bits >= 16 ) + { + push_indice_fx( st_fx, IND_UNUSED, 0, 16 ); + num_bits = sub(num_bits, 16); + } + + IF ( num_bits != 0 ) + { + push_indice_fx( st_fx, IND_UNUSED, 0, num_bits ); + } + + return; +} diff --git a/lib_enc/hq_env_enc_fx.c b/lib_enc/hq_env_enc_fx.c new file mode 100644 index 0000000..1941931 --- /dev/null +++ b/lib_enc/hq_env_enc_fx.c @@ -0,0 +1,597 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_enc_fx.h" +#include "stl.h" + +/*--------------------------------------------------------------------------------------* + * encode_envelope_indices_fx() + * + * Encode envelope indices + *--------------------------------------------------------------------------------------*/ + +Word16 encode_envelope_indices_fx( /* o : Number of bits if flag_pack=0,0 if flag_pack=1 Q0 */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 num_sfm, /* i : Number of subbands Q0 */ + const Word16 numnrmibits, /* i : Bitrate of fall-back coding mode Q0 */ + Word16 *difidx, /* i/o: Diff indices/encoded diff indices Q0 */ + Word16 *LCmode, /* o : Coding mode if flag_pack=0, i : if flag_pack=1 Q0 */ + const Word16 flag_pack, /* i : indicator of packing or estimating bits Q0 */ + const Word16 flag_HQ2 /* i : indicator of HQ2 core Q0 */ + ,const Word16 is_transient /* i : indicator of HQ_TRANSIENT Q0 */ +) +{ + Word16 bits; + Word16 prevj; + Word16 hcode_l; + Word16 i,j; + Word16 difidx_flag; + Word16 index_max, index_min, index_rad; + Word16 difidx_org[NB_SFM]; /* lenght of this buffer is max(BANDS_MAX,NB_SFM) */ + Word16 m, r; + Word16 v, k; + + set16_fx( difidx_org, 0, NB_SFM ); + difidx_flag = 0; + move16(); + + /*------------------------------------------------------------------* + * Check Huffman encoding for QNorm indices + *------------------------------------------------------------------*/ + + /* LC mode index is changed to synchronize LR_MDCT signaling */ + /* LC mode 0 = Context based coding */ + /* LC mode 1 = resized huffman coding */ + /* LC mode 2 = normal Huffman Coding */ + /* LC mode 3 = bit packing */ + IF ( flag_pack == 0 ) + { + test(); + IF( is_transient && EQ_16(flag_HQ2, LOW_RATE_HQ_CORE_TRAN)) + { + bits = 0; + move16(); + index_max = 0; + move16(); + index_min = 31; + move16(); + FOR( i = 0; i< num_sfm; i++ ) + { + IF( GT_16(difidx[i], index_max)) + { + index_max = difidx[i]; + move16(); + } + IF( LT_16(difidx[i], index_min)) + { + index_min = difidx[i]; + move16(); + } + } + test(); + IF(GT_16(index_min, 10)&<_16(index_max,22)) + { + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + bits = add(bits, huffsizn_tran[j]); + } + } + hcode_l= 0; + move16(); + *LCmode = 0; + move16(); + prevj = add(difidx[0], OFFSET_NORM); + /* LC mode 0 = Context based coding */ + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + IF( GT_16(prevj, HTH_NORM)) + { + /* above */ + hcode_l = add(hcode_l, huffsizn_n_fx[31-j]); + } + ELSE + { + IF( LT_16(prevj, LTH_NORM)) + { + /* less */ + hcode_l = add(hcode_l, huffsizn_n_fx[j]); + } + ELSE + { + /* equal */ + hcode_l = add(hcode_l, huffsizn_e_fx[j]); + } + } + prevj = j; + move16(); + } + test(); + IF( GE_16(hcode_l, bits)&&bits!=0) + { + /* LC mode 1 Transient Huffman Coding */ + *LCmode = 1; + move16(); + hcode_l = bits; + move16(); + } + } + ELSE + { + /* Check bits if LC mode == 3 -> Check bits if LC mode == 0 */ + hcode_l= 0; + move16(); + prevj = add(difidx[0], OFFSET_NORM); + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + IF( GT_16(prevj, HTH_NORM)) + { + /* above */ + hcode_l = add(hcode_l, huffsizn_n_fx[sub(31,j)]); + } + ELSE + { + IF( LT_16(prevj, LTH_NORM)) + { + /* less */ + hcode_l = add(hcode_l, huffsizn_n_fx[j]); + } + ELSE + { + /* equal */ + hcode_l = add(hcode_l, huffsizn_e_fx[j]); + } + } + prevj = j; + move16(); + } + + *LCmode = 0; + move16(); + + /* LR-MDCT core doesn't have coding mode 2 and 3 */ + IF( flag_HQ2 == NORMAL_HQ_CORE ) + { + /* Check bits if LC mode == 1 -> Check bits if LC mode == 2 */ + bits = 0; + move16(); + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + bits = add(bits, huffsizn[j]); + } + + /*------------------------------------------------------------------------------* + * comparing bit expenses of coding mode 2 with that of the optimal coding mode + *------------------------------------------------------------------------------*/ + + if( GT_16(hcode_l, bits)) + { + *LCmode = 2; + move16(); + } + hcode_l = s_min(hcode_l, bits); + } + + /* Check bits if LC mode == 2 -> Check bits if LC mode == 1 */ + bits = 0; + move16(); + index_max = 0; + move16(); + index_min = 31; + move16(); + FOR( i = 1; i < num_sfm; i++ ) + { + difidx_org[i] = difidx[i]; + move16(); + } + + difidx_flag = 0; + move16(); + FOR( i = 2; i < num_sfm; i++ ) + { + IF( GT_16(difidx_org[i-1], 17)) + { + difidx[i] = add(difidx_org[i], s_min(sub(difidx_org[i-1],17),3)); + move16(); + IF( GT_16(difidx[i], 31)) + { + difidx_flag = 1; + move16(); + BREAK; + } + } + + IF( LT_16(difidx_org[i-1], 13)) + { + difidx[i] = add(difidx_org[i], s_max(sub(difidx_org[i-1],13),-3)); + move16(); + IF( difidx[i] < 0 ) + { + difidx_flag = 1; + move16(); + BREAK; + } + } + } + + index_rad = 0; + move16(); + IF( difidx_flag == 0 ) + { + FOR( i = 1; i< num_sfm; i++ ) + { + index_max = s_max(index_max, difidx[i]); + index_min = s_min(index_min, difidx[i]); + } + + index_rad = s_max(sub(15, index_min),sub(index_max, 15)); + + IF( LE_16(index_rad, HUFF_THR)) + { + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + bits = add(bits, resize_huffsizn[j]); + } + + /*------------------------------------------------------------------* + * comparing bit expenses of coding mode 1 with that of coding mode 0 + *------------------------------------------------------------------*/ + + if( GT_16(hcode_l, bits)) + { + *LCmode = 1; + move16(); + } + hcode_l = s_min(hcode_l, bits); + + } + } + + /* LR-MDCT core doesn't have coding mode 2 and 3 */ + IF( flag_HQ2 == NORMAL_HQ_CORE ) + { + /*------------------------------------------------------------------------------* + * comparing bit expenses of coding mode 3 with that of the optimal coding mode + *------------------------------------------------------------------------------*/ + + if( GE_16(hcode_l, numnrmibits)) + { + *LCmode = 3; + move16(); + } + hcode_l = s_min(hcode_l, numnrmibits); + } + + test(); + test(); + IF( (NE_16(*LCmode, 1)&&flag_HQ2==NORMAL_HQ_CORE)||EQ_16(flag_HQ2,LOW_RATE_HQ_CORE)) + { + FOR(i = 2; i< num_sfm; i++) + { + difidx[i] = difidx_org[i]; + move16(); + } + } + } + } + ELSE + { + test(); + IF( EQ_16(flag_HQ2, LOW_RATE_HQ_CORE_TRAN)||EQ_16(flag_HQ2,LOW_RATE_HQ_CORE)) + { + push_indice_fx( st_fx, IND_HQ2_DENG_HMODE, *LCmode, BITS_DE_HMODE); + push_indice_fx( st_fx, IND_HQ2_DIFF_ENERGY, difidx[0], BITS_DE_FCOMP); + } + ELSE + { + push_indice_fx( st_fx, IND_LC_MODE, *LCmode, 2 ); + push_indice_fx( st_fx, IND_YNRM, difidx[0], NORM0_BITS ); + } + + test(); + IF(is_transient && EQ_16(flag_HQ2, LOW_RATE_HQ_CORE_TRAN)) + { + hcode_l = 0; + move16(); + IF ( EQ_16(*LCmode, 1)) + { + /* LC mode 0 Transient Huffman Coding */ + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + m = huffnorm_tran[j]; + move16(); + r = huffsizn_tran[j]; + move16(); + v = 0; + move16(); + + /* Bit reverse */ + FOR( k = 0; k < r; k++ ) + { + v = lshl(v, 1); + v = s_or(v, s_and(m, 1)); + m = lshr(m, 1); + } + + push_indice_fx(st_fx, IND_HQ2_DIFF_ENERGY, v, r); + } + } + ELSE + { + /* LC mode 1 context based Coding */ + prevj = add(difidx[0], OFFSET_NORM); + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + + IF( GT_16(prevj, HTH_NORM)) + { + /* above */ + r = huffsizn_n_fx[sub(31,j)]; + move16(); + m = huffnorm_n_fx[sub(31,j)]; + move16(); + } + ELSE + { + IF( LT_16(prevj, LTH_NORM)) + { + /* less */ + r = huffsizn_n_fx[j]; + move16(); + m = huffnorm_n_fx[j]; + move16(); + } + ELSE + { + /* equal */ + r = huffsizn_e_fx[j]; + move16(); + m = huffnorm_e_fx[j]; + move16(); + } + } + push_indice_fx(st_fx, IND_HQ2_DIFF_ENERGY, m, r); + prevj = j; + move16(); + } + } + } + ELSE + { + hcode_l = 0; + move16(); + IF ( *LCmode == 0 ) + { + /* LC mode 3 -> LC mode 0 */ + prevj = add(difidx[0], OFFSET_NORM); + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + + IF( GT_16(prevj, HTH_NORM)) + { + /* above */ + r = huffsizn_n_fx[sub(31,j)]; + move16(); + m = huffnorm_n_fx[sub(31,j)]; + move16(); + } + ELSE + { + IF( LT_16(prevj, LTH_NORM)) + { + /* less */ + r = huffsizn_n_fx[j]; + move16(); + m = huffnorm_n_fx[j]; + move16(); + } + ELSE + { + /* equal */ + r = huffsizn_e_fx[j]; + move16(); + m = huffnorm_e_fx[j]; + move16(); + } + } + + IF( EQ_16(flag_HQ2, LOW_RATE_HQ_CORE)) + { + push_indice_fx(st_fx, IND_HQ2_DIFF_ENERGY, m, r); + } + ELSE + { + push_indice_fx( st_fx, IND_YNRM, m, r ); + } + + prevj = j; + move16(); + } + } + ELSE IF( EQ_16(*LCmode, 1)) + { + IF ( EQ_16(flag_HQ2, 1)) + { + index_max = 0; + move16(); + index_min = 31; + move16(); + FOR(i = 1; i< num_sfm; i++) + { + difidx_org[i] = difidx[i]; + move16(); + } + + FOR(i = 2; i< num_sfm; i++) + { + IF(GT_16(difidx_org[i-1], 17)) + { + difidx[i] = add(difidx_org[i], s_min(sub(difidx_org[i-1],17),3)); + move16(); + IF(GT_16(difidx[i], 31)) + { + difidx_flag = 1; + move16(); + BREAK; + } + } + + IF(LT_16(difidx_org[i-1], 13)) + { + difidx[i] = add(difidx_org[i], s_max(sub(difidx_org[i-1],13),-3)); + move16(); + IF(difidx[i] < 0) + { + difidx_flag = 1; + move16(); + BREAK; + } + } + } + + IF( difidx_flag == 0 ) + { + FOR(i = 1; i< num_sfm; i++) + { + index_max = s_max(index_max, difidx[i]); + index_min = s_min(index_min, difidx[i]); + } + + index_rad = s_max(sub(15, index_min),sub(index_max, 15)); + + IF(LE_16(index_rad, HUFF_THR)) + { + FOR (i = 1; i < num_sfm; i++) + { + j = difidx[i]; + move16(); + } + } + } + } + + /* LC mode 2 -> LC mode 1 */ + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + + m = resize_huffnorm_fx[j]; + move16(); + r = resize_huffsizn[j]; + move16(); + v = 0; + move16(); + + /* Bit reverse */ + FOR( k = 0; k < r; k++ ) + { + v = lshl(v, 1); + v = s_or(v,s_and(m, 1)); + m = lshr(m, 1); + } + + IF ( flag_HQ2 == 0 ) + { + push_indice_fx( st_fx, IND_YNRM, v, r ); + } + ELSE + { + push_indice_fx( st_fx, IND_HQ2_DIFF_ENERGY, v, r); + } + } + } + ELSE IF( EQ_16(*LCmode, 2)) + { + /* LC mode 1 -> LC mode 2 */ + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + + m = huffnorm_fx[j]; + move16(); + r = huffsizn[j]; + move16(); + + push_indice_fx( st_fx, IND_YNRM, m, r ); + } + } + ELSE + { + FOR( i = 1; i < num_sfm; i++ ) + { + push_indice_fx( st_fx, IND_YNRM, difidx[i], NORMI_BITS ); + } + } + } + } + + return hcode_l; +} + +/*--------------------------------------------------------------------------* + * diff_envelope_coding_fx() + * + * Differential envelope coding + *--------------------------------------------------------------------------*/ + +void diff_envelope_coding_fx( + const Word16 is_transient, /* i : transient indicator Q0 */ + const Word16 num_env_bands, /* i : number of envelope bands to code Q0 */ + const Word16 start_norm, /* i : start of envelope coding Q0 */ + Word16 *ynrm, /* i/o: quantization indices for norms Q0 */ + Word16 *normqlg2, /* i/o: quantized norms Q0 */ + Word16 *difidx /* o : differential code Q0 */ +) +{ + Word16 i, tmp; + Word16 idxbuf[NB_SFM]; + Word16 normbuf[NB_SFM]; + + /* Differential coding for indices of quantized norms */ + IF( is_transient != 0 ) + { + /* Reorder quantization indices and quantized norms */ + reordernorm_fx( ynrm, normqlg2, idxbuf, normbuf, num_env_bands ); + diffcod_fx( num_env_bands, idxbuf, &difidx[1] ); + difidx[0] = idxbuf[0]; + move16(); + recovernorm_fx( idxbuf, ynrm, normqlg2, num_env_bands ); + } + ELSE + { + diffcod_fx( num_env_bands, &ynrm[start_norm], &difidx[1] ); + difidx[0] = ynrm[start_norm]; + move16(); + + tmp = add(start_norm, num_env_bands); + FOR( i = start_norm; i < tmp; i++ ) + { + normqlg2[i] = dicnlg2[ynrm[i]]; + move16(); + move16(); + } + } + + return; +} diff --git a/lib_enc/hq_hr_enc_fx.c b/lib_enc/hq_hr_enc_fx.c new file mode 100644 index 0000000..bccba4a --- /dev/null +++ b/lib_enc/hq_hr_enc_fx.c @@ -0,0 +1,235 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" + +/*--------------------------------------------------------------------------* + * hq_hr_enc_fx() + * + * HQ High rate encoding routine + *--------------------------------------------------------------------------*/ +void hq_hr_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure fx */ + Word32 *t_audio, /* i/o: transform-domain coefficients Q12 */ + const Word16 length, /* i : length of spectrum Q0 */ + Word16 *num_bits, /* i : number of available bits Q0 */ + const Word16 is_transient /* i : transient flag Q0 */ +) +{ + Word16 nb_sfm; /* Q0 */ + Word16 sum, hcode_l; /* Q0 */ + Word16 difidx[NB_SFM]; /* Q0 */ + Word16 normqlg2[NB_SFM], ynrm[NB_SFM]; /* Q0 */ + Word16 nf_idx; /* Q0 */ + Word16 bits; /* */ + Word16 LCmode; /* Q0 */ + Word16 shape_bits, num_sfm, numnrmibits; /* Q0 */ + Word16 hqswb_clas; /* Q0 */ + Word16 num_env_bands; /* Q0 */ + Word16 Npeaks, start_norm; /* Q0 */ + Word16 difidx_org[NB_SFM]; /* Q0 */ + Word16 R[NB_SFM]; /* Q0 */ + Word16 peaks[HVQ_MAX_PEAKS]; /* Q0 */ + const Word16 *sfmsize, *sfm_start, *sfm_end; /* Q0 */ + Word16 npulses[NB_SFM], maxpulse[NB_SFM]; /* Q0 */ + Word16 Rsubband[NB_SFM]; /* Q3 */ + Word32 t_audio_q[L_FRAME48k]; /* Q12 */ + Word32 nf_gains[HVQ_NF_GROUPS]; /* Q12 */ + Word32 pe_gains[HVQ_NF_GROUPS]; /* Q12 */ + Word16 noise_level[HVQ_BWE_NOISE_BANDS]; /* Q15 */ + Word16 hq_generic_offset; /* Q0 */ + Word16 hq_generic_fenv[HQ_FB_FENV]; /* Q1 */ + Word16 hq_generic_exc_clas = 0; /* Q0 */ + Word16 core_sfm; /* Q0 */ + Word16 har_freq_est1, har_freq_est2; + Word16 flag_dis; + const Word16 *subband_search_offset; + Word16 wBands[2]; + + Word16 t_audio_norm[L_FRAME48k]; + Word16 t_audio_q_norm[L_FRAME48k]; + Word16 Q_audio; + Word16 i; + Word16 b_delta_env; + Word16 Q_shift; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + Npeaks = 0; + Q_audio = 0; /* to avoid compilation warnings */ + + set16_fx( npulses, 0, NB_SFM ); + set16_fx( maxpulse, 0, NB_SFM ); + set16_fx( difidx_org, 0, NB_SFM ); + set32_fx( t_audio_q, 0, L_FRAME48k ); + set32_fx( nf_gains, 0, HVQ_NF_GROUPS ); + set32_fx( pe_gains, 0, HVQ_NF_GROUPS ); + flag_dis = 1; + move16(); + har_freq_est1 = 0; + move16(); + har_freq_est2 = 0; + move16(); + + /*------------------------------------------------------------------* + * Classification + *------------------------------------------------------------------*/ + + bits = hq_classifier_enc_fx( st_fx, length, t_audio, is_transient, &Npeaks, peaks, pe_gains, nf_gains, &hqswb_clas ); + + *num_bits = sub(*num_bits, bits); + + /*------------------------------------------------------------------* + * set quantization parameters + *------------------------------------------------------------------*/ + + hq_configure_fx( length, hqswb_clas, st_fx->core_brate_fx, &num_sfm, &nb_sfm, &start_norm, &num_env_bands, &numnrmibits, &hq_generic_offset, + &sfmsize, &sfm_start, &sfm_end ); + + /*------------------------------------------------------------------* + * Transient frame handling + *------------------------------------------------------------------*/ + + /* Interleave MLT coefficients of 4 sub-vectors in case of transient */ + IF( EQ_16( is_transient, 1 )) + { + interleave_spectrum_fx( t_audio, length ); + } + + /*------------------------------------------------------------------* + * Scalar quantization of norms + * Encode norm indices + *------------------------------------------------------------------*/ + + /* calculate and quantize norms */ + calc_norm_fx( t_audio, 12, ynrm, normqlg2, start_norm, num_env_bands, sfmsize, sfm_start ); + + /* create differential code of quantized norm indices */ + diff_envelope_coding_fx(is_transient, num_env_bands, start_norm, ynrm, normqlg2, difidx); + + /* Find coding mode and calculate bit rate */ + hcode_l = encode_envelope_indices_fx( st_fx, num_env_bands, numnrmibits, difidx, &LCmode, 0, NORMAL_HQ_CORE, is_transient ); + *num_bits = sub(*num_bits, add( hcode_l, NORM0_BITS + FLAGS_BITS ) ); + + /* Encode norm indices */ + encode_envelope_indices_fx( st_fx, num_env_bands, numnrmibits, difidx, &LCmode, 1, NORMAL_HQ_CORE, is_transient ); + + /*------------------------------------------------------------------* + * HQ Generic HF encoding + *------------------------------------------------------------------*/ + + test(); + IF ( EQ_16( hqswb_clas, HQ_GEN_SWB )||EQ_16(hqswb_clas,HQ_GEN_FB)) + { + hq_generic_encoding_fx(t_audio, hq_generic_fenv, hq_generic_offset, st_fx, &hq_generic_exc_clas); + IF (EQ_16(hq_generic_exc_clas , HQ_GENERIC_SP_EXC)) + { + *num_bits = add(*num_bits,1); /* conditional 1 bit saving for representing FD3 BWE excitation class */ + } + map_hq_generic_fenv_norm_fx( hqswb_clas, hq_generic_fenv, ynrm, normqlg2, num_env_bands, nb_sfm, hq_generic_offset ); + } + + /*------------------------------------------------------------------* + * Bit allocation + *------------------------------------------------------------------*/ + + hq_bit_allocation_fx( st_fx->core_brate_fx, length, hqswb_clas, num_bits, normqlg2, nb_sfm, sfmsize, noise_level, + R, Rsubband, &sum, &core_sfm, num_env_bands ); + + /*------------------------------------------------------------------* + * Normalize coefficients with quantized norms + *------------------------------------------------------------------*/ + IF( hqswb_clas != HQ_HVQ ) + { + test(); + IF (hqswb_clas == HQ_GEN_SWB || hqswb_clas == HQ_GEN_FB) + { + b_delta_env = calc_nor_delta_hf_fx( st_fx, t_audio, ynrm, Rsubband, num_env_bands, nb_sfm, sfmsize, sfm_start, core_sfm ); + sum -= b_delta_env; + } + normalizecoefs_fx( t_audio, ynrm, nb_sfm, sfm_start, sfm_end, t_audio_norm ); + Q_audio = 12; + } + + /*------------------------------------------------------------------* + * Quantize/code spectral fine structure using PVQ or HVQ + *------------------------------------------------------------------*/ + IF( EQ_16( hqswb_clas, HQ_HVQ)) + { + sum = hvq_enc_fx( st_fx, st_fx->core_brate_fx, *num_bits, Npeaks, ynrm, R, peaks, nf_gains, + noise_level, pe_gains, t_audio, t_audio_q ); + *num_bits = sub(*num_bits, sum); + } + ELSE + { + shape_bits = pvq_core_enc_fx( st_fx, t_audio_norm, t_audio_q_norm, &Q_audio, sum, nb_sfm, sfm_start, sfm_end, sfmsize, Rsubband, R, + npulses, maxpulse, HQ_CORE ); + *num_bits = add( *num_bits, sub( sum, shape_bits) ); + } + + test(); + IF ( EQ_16(hqswb_clas, HQ_HVQ)||EQ_16(hqswb_clas,HQ_HARMONIC)) + { + subband_search_offset = subband_search_offsets_13p2kbps_Har_fx; + wBands[0] = SWB_SB_BW_LEN0_16KBPS_HAR; + move16(); + wBands[1] = SWB_SB_BW_LEN1_16KBPS_HAR; + move16(); + + IF (EQ_16(hqswb_clas, HQ_HARMONIC)) + { + Q_shift = sub(SWB_BWE_LR_Qs, Q_audio); + FOR (i = 0; i < 300; i++) + { + t_audio_q[i] = L_shl(L_deposit_l(t_audio_q_norm[i]), Q_shift); /* Q12 */ + } + } + + har_est_fx( t_audio_q, 300, &har_freq_est1, &har_freq_est2, &flag_dis, &st_fx->prev_frm_hfe2_fx, subband_search_offset, wBands, &st_fx->prev_stab_hfe2_fx ); + + st_fx->prev_frm_hfe2_fx = har_freq_est2; + move16(); + } + + test(); + test(); + IF ( NE_16(hqswb_clas, HQ_HARMONIC)||NE_16(hqswb_clas,HQ_HVQ)||flag_dis==0) + { + st_fx->prev_frm_hfe2_fx = 0; /*reset*/ move16(); + st_fx->prev_stab_hfe2_fx = 0; /*reset*/ move16(); + } + + nf_idx = 0; + move16(); + test(); + test(); + test(); + IF ( NE_16(is_transient,1 )&&NE_16(hqswb_clas,HQ_HVQ)&&!(EQ_16(length,L_FRAME16k)&&EQ_32(st_fx->core_brate_fx,HQ_32k))) + { + test(); + IF (EQ_16(hqswb_clas, HQ_GEN_SWB)||EQ_16(hqswb_clas,HQ_GEN_FB)) + { + nf_idx = noise_adjust_fx( t_audio_norm, 12, R, sfm_start, sfm_end, s_max(core_sfm,sub(num_env_bands,1))); + push_indice_fx( st_fx, IND_NF_IDX, nf_idx, 2 ); + } + ELSE + { + nf_idx = noise_adjust_fx( t_audio_norm, 12, R, sfm_start, sfm_end, core_sfm ); + push_indice_fx( st_fx, IND_NF_IDX, nf_idx, 2 ); + } + } + /* updates */ + st_fx->prev_hqswb_clas_fx = hqswb_clas; + move16(); + + + return; +} + diff --git a/lib_enc/hq_lr_enc_fx.c b/lib_enc/hq_lr_enc_fx.c new file mode 100644 index 0000000..297948f --- /dev/null +++ b/lib_enc/hq_lr_enc_fx.c @@ -0,0 +1,1928 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "rom_enc_fx.h" +#include "stl.h" +#include "basop_mpy.h" + +/*--------------------------------------------------------------------------* + * Local functions + *--------------------------------------------------------------------------*/ + +static Word16 band_energy_quant_fx( Encoder_State_fx *st_fx, const Word32 *L_t_audio, const Word16 band_start_fx[], const Word16 band_end_fx[], Word32 L_band_energy[], + const Word16 bands_fx, const Word32 L_qint, const Word16 eref_fx, const Word16 is_transient_fx ); + +static Word16 p2a_threshold_quant_fx( Encoder_State_fx *st_fx, const Word32 *L_t_audio, const Word16 band_start[], const Word16 band_end[], const Word16 band_width[], + const Word16 bands, const Word16 p2a_bands, const Word16 p2a_th, Word16 *p2a_flags ); + +static void mdct_spectrum_fine_gain_enc_fx( Encoder_State_fx *st_fx, const Word32 L_ybuf[], Word32 L_y2[], const Word16 band_start[], const Word16 band_end[], + const Word16 k_sort[], const Word16 bands, + const Word32 L_qint, const Word16 Ngq, const Word16 gqlevs, const Word16 gqbits ); + +/*--------------------------------------------------------------------------* + * spt_shorten_domain_set() + * + * Track the spectral peak based on peak -avg analysis + *--------------------------------------------------------------------------*/ + +static void spt_shorten_domain_set_fx( + Encoder_State_fx *st_fx, /* i: encoder state structure */ + const Word32 L_t_audio[], /* i: input spectrum */ + const Word16 p2a_flags[], /* i: p2a anlysis information */ + const Word16 new_band_start[], /* i: new band start position */ + const Word16 new_band_end[], /* i: new band end position */ + const Word16 new_band_width[], /* i: new subband band width */ + const Word16 bands, /* i: total number of subbands */ + Word16 band_start[], /* i/o: band start position */ + Word16 band_end[], /* i/o: band end position */ + Word16 band_width[], /* i: sub band band width */ + Word16 *bit_budget /* i/o: bit budget */ +) +{ + Word16 i, j, k; + Word16 kpos; + Word32 L_max_y2; + Word16 max_y2_pos; + Word16 spt_shorten_flag[SPT_SHORTEN_SBNUM]; + + kpos = 0; + j = 0; + move16(); + FOR(k=sub(bands,SPT_SHORTEN_SBNUM); kprev_SWB_peak_pos_fx[kpos] != 0) + { + L_max_y2 = L_deposit_l(0); + max_y2_pos = 0; + move16(); + FOR(i=band_start[k]; i<=band_end[k]; i++) + { + IF( LT_32( L_max_y2, L_abs(L_t_audio[i]))) + { + L_max_y2 = L_abs(L_t_audio[i]); + max_y2_pos = i; + move16(); + } + } + test(); + IF( GE_16(max_y2_pos, new_band_start[j])&&LE_16(max_y2_pos,new_band_end[j])) + { + band_start[k] = new_band_start[j]; + move16(); + band_end[k] = new_band_end[j]; + move16(); + band_width[k] = new_band_width[j]; + move16(); + spt_shorten_flag[j] = 1; + move16(); + } + } + push_indice_fx(st_fx, IND_HQ2_SPT_SHORTEN, spt_shorten_flag[j], 1); + *bit_budget = sub(*bit_budget, 1); + } + + kpos = add(kpos, 1); + j = add(j, 1); + } + + return; +} + +/*--------------------------------------------------------------------------* + * hq_lr_enc_fx() + * + * HQ Low rate encoding routine + *--------------------------------------------------------------------------*/ + +void hq_lr_enc_fx( + Encoder_State_fx *st_fx, /* i/o: : encoder state structure */ + Word32 L_t_audio[], /* i/o: Q12 : transform-domain coefs. */ + const Word16 inner_frame_fx, /* i : Q0 : inner frame length */ + Word16 *num_bits_fx, /* i/o: Q0 : number of available bits */ + const Word16 is_transient_fx /* i : Q0 : transient flag */ +) +{ + Word16 i, k1_fx, k2_fx; + Word16 bit_budget_fx, pbits_fx; + Word16 bands_fx, length_fx, ni_seed_fx, gqlevs_fx, gqbits_fx, Ngq_fx, p2a_bands_fx; + Word16 p2a_flags_fx[BANDS_MAX]; + Word16 band_start[BANDS_MAX], band_end[BANDS_MAX], band_width[BANDS_MAX]; + Word32 L_band_energy[BANDS_MAX], L_Rk[BANDS_MAX]; + Word16 ebits_fx; + + Word32 L_qint; + /*Word16 Qqint=29;*/ + Word16 eref_fx/*, Qeref=10*/; + Word16 bit_alloc_weight_fx/*, Qbaw=13*/; + Word16 ld_slope_fx/*, Qldslope=15*/; + Word16 p2a_th_fx/*, Qp2ath=11*/; + Word16 pd_thresh_fx/*, Qpdth=15*/; + Word16 ni_coef_fx/*, Qnicoef=14*/; + + Word16 k_sort_fx[BANDS_MAX]; + Word16 npulses_fx[BANDS_MAX]; + Word16 inp_vector_fx[L_FRAME48k]; + Word32 L_y2[L_FRAME48k]; + Word32 L_y2_ni[L_FRAME48k]; + Word16 hqswb_clas_fx; + Word16 lowlength_fx; + Word16 highlength_fx; + Word32 L_m[L_FRAME32k]; + Word16 har_bands_fx; + Word16 bw_low, bw_high; + Word32 L_band_energy_tmp[BANDS_MAX]; + Word32 L_bwe_br; + Word16 trans_bit; + Word16 adjustFlag; + Word16 prev_SWB_peak_pos_tmp_fx[SPT_SHORTEN_SBNUM]; + Word16 k,j; + Word16 flag_spt_fx; + Word16 org_band_start[SPT_SHORTEN_SBNUM]; + Word16 org_band_end[SPT_SHORTEN_SBNUM]; + Word16 org_band_width[SPT_SHORTEN_SBNUM]; + Word16 new_band_start[SPT_SHORTEN_SBNUM]; + Word16 new_band_end[SPT_SHORTEN_SBNUM]; + Word16 new_band_width[SPT_SHORTEN_SBNUM]; + + Word16 k1_step_fx, k2_step_fx; + Word16 exp_norm; + + Word16 lowband,highband,p2a_flags_tmp[BANDS_MAX]; + Word32 L_tmp,L_tmp2,L_tmp3; + Word16 exp,exp2,tmp,tmp1,tmp2,tmp3,frac1,alpha_fx,Q_band_energy; + Word32 enerH_fx; + Word32 enerL_fx; + Word32 Ep_fx[BANDS_MAX]; + Word32 Ep_avrg_fx, Ep_vari_fx; + Word32 Ep_avrgL_fx; + Word32 Ep_peak_fx; + Word32 Ep_tmp_fx[BANDS_MAX]; + Word16 gama_fx;/*Q15 0.85f;// */ + Word16 beta_fx;/*Q14 1.05f; */ + + set32_fx( L_y2, 0x0L, L_FRAME48k ); + set16_fx( inp_vector_fx, 0, inner_frame_fx ); + flag_spt_fx = 0; + move16(); + set16_fx(prev_SWB_peak_pos_tmp_fx, 0, SPT_SHORTEN_SBNUM); + adjustFlag = 0; + move16(); + bw_low = 0; + move16(); + bw_high = 20; + move16(); + enerL_fx = L_deposit_l(0); + enerH_fx = L_deposit_l(0); + + tmp2 = 0; /* to avoid compilation warnings */ + + L_bwe_br = L_add(st_fx->core_brate_fx, 0); + hqswb_clas_fx = HQ_NORMAL; + move16(); + test(); + test(); + IF( EQ_16(st_fx->bwidth_fx, SWB)&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))) + { + IF ( EQ_16(is_transient_fx, 1)) + { + hqswb_clas_fx = HQ_TRANSIENT; + move16(); + } + ELSE + { + hqswb_clas_fx = peak_avrg_ratio_fx( st_fx->total_brate_fx, L_t_audio, NUMC_N, &st_fx->mode_count_fx, &st_fx->mode_count1_fx, SWB_BWE_LR_Qs ); + } + + /* write the classification information into the bitstream */ + push_indice_fx( st_fx, IND_HQ2_SWB_CLAS, hqswb_clas_fx, 2 ); + (*num_bits_fx) = sub(*num_bits_fx, 2); + if( EQ_16(hqswb_clas_fx, HQ_NORMAL)) + { + flag_spt_fx = 1; + move16(); + } + } + ELSE + { + /* write the transient bit into the bitstream */ + push_indice_fx( st_fx, IND_HQ2_SWB_CLAS, is_transient_fx, 1 ); + + /* subtract one bit for the transient flag */ + (*num_bits_fx)--; + } + + hq2_core_configure_fx( inner_frame_fx, *num_bits_fx, is_transient_fx, &bands_fx, &length_fx, band_width, band_start, band_end, + &L_qint, &eref_fx, &bit_alloc_weight_fx, &gqlevs_fx, &Ngq_fx, &p2a_bands_fx, &p2a_th_fx, &pd_thresh_fx, &ld_slope_fx, &ni_coef_fx + ,L_bwe_br); + + highlength_fx = band_end[sub(bands_fx, 1)]; + move16(); + har_bands_fx = bands_fx; + move16(); + + test(); + test(); + test(); + IF( EQ_16(st_fx->bwidth_fx, SWB)&&is_transient_fx==0&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))) + { + /* reserve bits for HQ_NORMAL2 and HQ_HARMONIC modes */ + test(); + IF( EQ_16(hqswb_clas_fx, HQ_NORMAL)||EQ_16(hqswb_clas_fx,HQ_HARMONIC)) + { + (*num_bits_fx) = sub(*num_bits_fx, get_usebit_npswb_fx(hqswb_clas_fx)); + } + } + + test(); + test(); + IF(( EQ_32(L_bwe_br, HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))&&EQ_16(st_fx->bwidth_fx,SWB)) + { + IF( NE_16(st_fx->prev_hqswb_clas_fx, HQ_NORMAL)) + { + j = 0; + move16(); + FOR(k=sub(bands_fx,SPT_SHORTEN_SBNUM); kprev_SWB_peak_pos_fx[j] = 0; + move16(); + j = add(j, 1); + } + } + } + + /* Check if input frame is larger than coded bandwidth */ + test(); + IF ( GT_16(inner_frame_fx, length_fx)&&is_transient_fx) + { + /* If so, collapse transient frame (4 short transforms) to remove uncoded coefficients */ + + k1_step_fx = shr(length_fx, 2); /* k1 = length/NUM_TIME_SWITCHING_BLOCKS */ + k2_step_fx = shr(inner_frame_fx, 2); /* k2 = inner_frame/NUM_TIME_SWITCHING_BLOCKS */ + k1_fx = k1_step_fx; + k2_fx = k2_step_fx; + FOR (i = 1; i < NUM_TIME_SWITCHING_BLOCKS; i++) + { + /*k1 = i*length/NUM_TIME_SWITCHING_BLOCKS; */ + /*k2 = i*inner_frame/NUM_TIME_SWITCHING_BLOCKS; */ + + Copy32( &L_t_audio[k2_fx], &L_t_audio[k1_fx], k1_step_fx ); + + k1_fx = add(k1_fx, k1_step_fx); + k2_fx = add(k2_fx, k2_step_fx); + } + } + + /* Spectral energy calculation/quantization */ + ebits_fx = band_energy_quant_fx( st_fx, L_t_audio, band_start, band_end, L_band_energy, bands_fx, + L_qint, eref_fx, is_transient_fx ); + + /* First pass bit budget for TCQ of spectral band information */ + exp_norm = norm_s(gqlevs_fx); /* gqbits_fx = (short int) log2_f ((float) gqlevs_fx); */ + gqbits_fx = sub(14, exp_norm); + + bit_budget_fx = sub(sub(*num_bits_fx, ebits_fx), round_fx(L_shl(L_mult(Ngq_fx, gqbits_fx), 15))); /* (*num_bits) - (short) ceil (ebits) - Ngq * gqbits; */ + + + pbits_fx = 0; + move16(); + + test(); + test(); + IF( EQ_16(st_fx->bwidth_fx, SWB)&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))) + { + IF( EQ_16(hqswb_clas_fx, HQ_HARMONIC)) + { + set16_fx( p2a_flags_fx, 1, har_bands_fx ); + } + ELSE + { + /* High band tonality detector based on per band peak-to-average ratio */ + pbits_fx = p2a_threshold_quant_fx( st_fx, L_t_audio, band_start, band_end, band_width, bands_fx, p2a_bands_fx, p2a_th_fx, p2a_flags_fx ); + bit_budget_fx = sub(bit_budget_fx, pbits_fx); + + IF( EQ_16(hqswb_clas_fx, HQ_NORMAL)) + { + return_bits_normal2_fx( &bit_budget_fx, p2a_flags_fx, bands_fx, bits_lagIndices_modeNormal_fx ); + } + } + } + ELSE + { + /* High band tonality detector based on per band peak-to-average ratio */ + pbits_fx = p2a_threshold_quant_fx( st_fx, L_t_audio, band_start, band_end, band_width, bands_fx, p2a_bands_fx, p2a_th_fx, p2a_flags_fx ); + bit_budget_fx = sub(bit_budget_fx, pbits_fx); + } + + IF(EQ_16(flag_spt_fx, 1)) + { + spt_shorten_domain_band_save_fx(bands_fx, band_start, band_end, band_width, org_band_start, org_band_end, org_band_width); + spt_shorten_domain_pre_fx(band_start, band_end, st_fx->prev_SWB_peak_pos_fx, bands_fx, L_bwe_br, new_band_start, new_band_end, new_band_width); + spt_shorten_domain_set_fx(st_fx, L_t_audio, p2a_flags_fx, new_band_start, new_band_end, new_band_width, bands_fx, band_start, band_end, band_width, &bit_budget_fx); + } + + /* Estimate number of bits per band */ + Q_band_energy = SWB_BWE_LR_Qbe; + + FOR(i = 0; i < bands_fx; i++) + { + L_tmp = L_shl(L_band_energy[i],sub(16,Q_band_energy));/*Q16 */ + + frac1 = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */ + L_tmp = Pow2(30, frac1); + exp = sub(exp, 30); + Ep_fx[i] = L_shl(L_tmp , s_max(sub(exp,6), -31)); /* Q -6 */ + } + + FOR( i = 0; i < bands_fx; i++ ) + { + L_tmp2 = Ep_fx[i]; + L_tmp = L_max(1, L_tmp2); + exp = norm_l(L_tmp); + tmp = extract_h(L_shl(L_tmp, exp)); + + L_tmp3 = (Word32)band_width[i]; + exp2 = norm_l(L_tmp3); + tmp2 = extract_h(L_shl(L_tmp3, exp2)); + + exp2 = sub(exp, exp2); /* Denormalize and substract */ + + tmp3 = sub(tmp2, tmp); + if (tmp3 > 0) + { + tmp2 = shr(tmp2, 1); + } + if (tmp3 > 0) + { + exp2 = add(exp2, 1); + } + tmp = div_s(tmp2, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp2);/*Q(31-exp2) */ + Ep_tmp_fx[i] = L_shr(L_tmp,sub(15,exp2));/*Q13 */ + } + + test(); + test(); + test(); + test(); + test(); + test(); + IF ( is_transient_fx == 0 && EQ_16(inner_frame_fx, L_FRAME8k)&&LE_32(st_fx->core_brate_fx,ACELP_13k20)) + { + lowband = 6; + move16(); + trans_bit = 2; + move16(); + bit_budget_fx =sub(bit_budget_fx,trans_bit); + gama_fx = 27852; /*Q15 0.85f;// */ + beta_fx = 17203; + move16();/*Q14 1.05f; */ + + set16_fx( &p2a_flags_tmp[sub(bands_fx,trans_bit)], 0, 2 ); + + IF( EQ_32(st_fx->core_brate_fx, ACELP_13k20)) + { + beta_fx = 13107; + move16();/*14 1.25f; */ + gama_fx = 31130; + move16();/*0.95f; */ + Copy(&p2a_flags_fx[sub(bands_fx,trans_bit)], &p2a_flags_tmp[sub(bands_fx,trans_bit)], trans_bit); + } + /* calculate the the low band/high band energy and the variance/avrage of the envelopes */ + Ep_vari_fx = L_deposit_l(0); + Ep_avrg_fx = L_deposit_l(0); + Ep_avrgL_fx = L_deposit_l(0); + Ep_peak_fx = L_deposit_l(0); + FOR( i = 0; i < bands_fx; i++ ) + { + IF( GE_16(i,lowband)) + { + Ep_vari_fx = L_add(Ep_vari_fx,L_abs(L_sub(Ep_tmp_fx[i],Ep_tmp_fx[sub(i,1)])));/*Q15 */ + Ep_avrg_fx = L_add(Ep_avrg_fx,Ep_tmp_fx[i]);/*Q15 */ + + } + ELSE + { + Ep_avrgL_fx = L_add(Ep_avrgL_fx,Ep_tmp_fx[i]);/*Q15 */ + IF(GT_32(Ep_tmp_fx[i],Ep_peak_fx)) + { + Ep_peak_fx = L_add(Ep_tmp_fx[i], 0); /*Q15 */ + } + } + } + /* modify the last p2a_bands subbands band_energies */ + Copy32( L_band_energy,L_band_energy_tmp,bands_fx ); /*Q_band_energy */ + L_tmp = Mult_32_16(Ep_peak_fx,24576);/*Q(13+14-15 = 12) 1.5 lowband = 6; */ + L_tmp2 =Mult_32_16(Ep_peak_fx,shl(sub(bands_fx,lowband),9));/*Q(13+9-15 = 7) */ + L_tmp3 =Mult_32_16(Ep_avrg_fx,1126);/*Q(13+9-15 = 7) */ + + test(); + test(); + test(); + test(); + IF(( (LT_32(L_tmp, L_shr(Ep_avrgL_fx,1))&&EQ_32(st_fx->core_brate_fx,ACELP_13k20))||LT_32(st_fx->core_brate_fx,ACELP_13k20))&& + LT_32(L_tmp2, L_tmp3) && GT_32(L_tmp2, L_shr(Ep_avrg_fx,7)) ) + { + FOR(i = lowband; i < bands_fx; i++) + { + L_tmp = Mult_32_16(Ep_avrg_fx,24576);/*Q(13+14-15 = 12) 1.5 */ + IF(LT_32(L_shr(Ep_tmp_fx[i],1), L_tmp)) + { + L_tmp = Mult_32_16(Ep_peak_fx,sub(bands_fx,lowband));/*Q(13+0-15 = -2) */ + tmp = extract_h(L_shl(L_tmp,14));/*Q-4 */ + IF(tmp != 0) + { + exp = norm_s(tmp); + tmp = shl(tmp,exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + /*when the divisor is zero, happens rarely*/ + tmp = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = L_shl(Mult_32_16(Ep_avrg_fx,tmp),sub(13,exp));/*Q(13+exp-15 +13-exp +4 = 15) */ + L_tmp2 = L_add(L_tmp,13107); /*15 */ + tmp2 = extract_l(L_min(L_max(L_tmp2,16384),gama_fx)); /*15 = 15 */ + L_band_energy_tmp[i] = Mult_32_16(L_band_energy_tmp[i],tmp2);/*Q(Q_band_energy+15-15 = Q_band_energy) */ + } + } + } + ELSE + { + j = 0; + FOR(i = sub(bands_fx,trans_bit); i < bands_fx; i++) + { + alpha_fx = 16384; + move16();/*Q14 */ + IF( EQ_16(p2a_flags_tmp[i],1)) + { + L_tmp = Mult_32_16(Ep_tmp_fx[i],sub(bands_fx,lowband));/*Q(13+0-15 = -2) */ + tmp = extract_h(L_shl(L_tmp,14));/*Q-4 */ + IF(tmp != 0) + { + exp = norm_s(tmp); + tmp = shl(tmp,exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + /*when the divisor is zero, happens rarely*/ + tmp = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp =Mult_32_16(Ep_vari_fx,3277);/*13+15-15=13 */ + L_tmp = L_shl(Mult_32_16(L_tmp,tmp),sub(12,exp));/*Q(13+exp-15 +12-exp +4 = 14) */ + + tmp2 = extract_h(Ep_avrg_fx);/*Q13-16=-3 */ + IF(tmp2 != 0) + { + exp = norm_s(tmp2); + tmp2 = shl(tmp2,exp);/*Q(exp) */ + tmp2 = div_s(16384,tmp2);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + tmp2 = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp2 =Mult_32_16(Ep_vari_fx,6554);/*13+15-15=13 */ + L_tmp2 = L_shl(Mult_32_16(L_tmp2,tmp2),sub(13,exp));/*Q(13+exp-15 +13-exp +3 = 14) */ + L_tmp=L_min(L_tmp,L_tmp2);/*14 */ + tmp=extract_l(L_min(L_tmp,13107));/*14 */ + alpha_fx =add(16384,tmp); + + } + IF(EQ_16(st_fx->last_bitalloc_max_band_fx[j++], 1)) + { + L_tmp = Mult_32_16(Ep_tmp_fx[i],sub(bands_fx,lowband));/*Q(13+0-15 = -2) */ + tmp = extract_h(L_shl(L_tmp,14));/*Q-2 */ + IF(tmp != 0) + { + exp = norm_s(tmp); + tmp = shl(tmp,exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + tmp = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = L_shl(Mult_32_16(Ep_avrg_fx,tmp),sub(14,exp));/*Q(13+exp-15 +14-exp+2 = 14) */ + L_tmp =L_max(L_tmp,16384); /*14 */ + tmp=extract_l(L_min(L_tmp,beta_fx)); /*14 */ + alpha_fx=shl(mult(alpha_fx,tmp),1);/*14+14-15 +1=14 */ + } + ELSE + { + tmp2 = extract_h(Ep_avrg_fx);/*13 -16 =-3 */ + IF(tmp2 != 0) + { + exp = norm_s(tmp2); + tmp2 = shl(tmp2,exp);/*Q(exp) */ + tmp2 = div_s(16384,tmp2);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + /*when the divisor is zero, happens rarely*/ + tmp2 = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = L_shl(Mult_32_16(Ep_tmp_fx[i],tmp2),sub(19,exp));/*Q(13+exp-15 +19-exp +3 = 20) */ + L_tmp = Mult_32_16(L_tmp,shl(sub(bands_fx,lowband),9));/*20 +9 -15 =14 */ + L_tmp =L_max(L_tmp,13926); /*14 */ + tmp2 =extract_l(L_min(L_tmp,16384)); /*14 */ + alpha_fx=shl(mult(alpha_fx,tmp2),1);/*14+14-15+1 =14 */ + } + L_band_energy_tmp[i] = L_shl(Mult_32_16(L_band_energy_tmp[i],alpha_fx),1);/*Q(Q_band_energy+14-15 +1= Q_band_energy) */ + } + } + lowband = 3; + move16(); + Ep_avrg_fx = L_deposit_l(0); + Ep_avrgL_fx = L_deposit_l(0); + Ep_peak_fx = L_deposit_l(0); + FOR(i = 0; i < bands_fx; i++) + { + IF(GE_16(i,lowband)) + { + Ep_avrg_fx = L_add(Ep_avrg_fx,Ep_tmp_fx[i]);/*Q15 */ + } + ELSE + { + Ep_avrgL_fx = L_add(Ep_avrgL_fx,L_shr(Ep_tmp_fx[i],1));/*Q12 */ + IF(GT_32(Ep_tmp_fx[i],Ep_peak_fx)) + { + Ep_peak_fx = L_add(Ep_tmp_fx[i], 0); /*Q13 */ + } + } + } + L_tmp = Mult_32_16(Ep_peak_fx,28262);/*Q(13+14-15 = 12) 1.725 lowband = 3; */ + L_tmp2 =Mult_32_16(Ep_avrgL_fx,24576);/*Q(12+14-15 = 11) */ + test(); + test(); + IF( GT_32(L_shr(Ep_avrg_fx,2), L_tmp2)&<_32(L_shr(Ep_avrg_fx,4),L_tmp2)&>_32(L_tmp,Ep_avrgL_fx)) + { + adjustFlag = 1; + move16(); + FOR (i = 0; i < lowband; i++) + { + tmp = extract_h(Ep_avrgL_fx);/*Q-4 */ + IF(tmp != 0) + { + exp = norm_s(tmp); + tmp = shl(tmp,exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + /*when the divisor is zero, happens rarely*/ + tmp = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = Mult_32_16(Ep_peak_fx,tmp);/*Q(13+exp-15+4 = exp+2) */ + L_tmp = Mult_32_16(L_tmp,lowband);/*Q(exp+2+0-15 = exp-13) */ + L_tmp = Mult_32_16(L_tmp,18842);/*Q(exp-13+16-16 = exp-13) */ + L_tmp = L_shl(L_tmp,sub(27,exp));/*Q14 0.5 */ + tmp2=extract_l(L_min(L_tmp,19661));/*14 */ + L_tmp = Mult_32_16(L_band_energy_tmp[i],tmp2);/*Q(Q_band_energy+14-15 = Q_band_energy-1) */ + L_band_energy_tmp[i] = L_shl(L_tmp,1); /*Q_band_energy */ + } + } + hq2_bit_alloc_fx( L_band_energy_tmp, bands_fx, L_Rk, &bit_budget_fx, p2a_flags_fx, bit_alloc_weight_fx, band_width, + *num_bits_fx, hqswb_clas_fx, st_fx->bwidth_fx, is_transient_fx ); + + /* encode the last p2a_bands-1 subbands bit-allocation index of the previous frame */ + FOR(i = 0; i < 2; i++) + { + push_indice_fx ( st_fx, IND_HQ2_LAST_BA_MAX_BAND, st_fx->last_bitalloc_max_band_fx[i], 1 ); + } + } + ELSE IF( is_transient_fx == 0 && EQ_16(inner_frame_fx, L_FRAME16k)) + { + bit_budget_fx = sub(bit_budget_fx,2);/* bits in high bands to indicate the last 2 subbands is allocated bits or not */ + FOR( i = 0; i < bands_fx; i++ ) + { + Ep_tmp_fx[i] = L_shl(Ep_tmp_fx[i],2); + } + IF( EQ_32( st_fx->core_brate_fx, ACELP_13k20 )) + { + lowband = 8; + move16(); + highband = 15; + move16(); + bw_low = sub(band_start[highband],band_start[lowband]); + bw_high = sub(add(band_end[sub(bands_fx,1)],1),band_start[highband]); + } + ELSE + { + lowband = 8; + move16(); + highband = 16; + move16(); + bw_low = sub(band_start[highband],band_start[lowband]); + bw_high = sub(add(band_end[sub(bands_fx,1)],1),band_start[highband]); + } + /* calculate the the low band/high band energy and the variance/avrage of the envelopes */ + enerL_fx = L_deposit_l(0); + enerH_fx = L_deposit_l(0); + Ep_vari_fx = L_deposit_l(0); + Ep_avrg_fx = L_deposit_l(0); + FOR( i = 0; i < bands_fx; i++ ) + { + test(); + IF( GE_16(i,lowband)&&add(sub(i,bands_fx),p2a_bands_fx)<0) + { + Ep_vari_fx = L_add(Ep_vari_fx,L_abs(L_sub(Ep_tmp_fx[i],Ep_tmp_fx[sub(i,1)])));/*Q15 */ + Ep_avrg_fx = L_add(Ep_avrg_fx,Ep_tmp_fx[i]);/*Q15 */ + } + + IF(GE_16(i,highband)) + { + enerH_fx = L_add(enerH_fx,L_shl(Ep_fx[i],2));/*Q0 */ + } + ELSE IF(GE_16(i,lowband)) + { + enerL_fx = L_add(enerL_fx,L_shl(Ep_fx[i],2));/*Q0 */ + } + } + + /* modify the last p2a_bands subbands band_energies */ + Copy32( L_band_energy,L_band_energy_tmp,bands_fx ); /*Q_band_energy */ + L_tmp = L_max(enerH_fx,enerL_fx); + tmp = s_max(bw_low,bw_high); + i = norm_l(L_tmp); + j = norm_s(tmp); + L_tmp = Mult_32_16(L_shl(enerH_fx,i), shl(bw_low,j)); /* i + j -15 */ + L_tmp2 = Mult_32_16(L_shl(enerL_fx,i), shl(bw_high,j)); /*i + j -15 */ + L_tmp2 = L_sub(L_tmp,L_tmp2); + FOR( i = sub(bands_fx,p2a_bands_fx); i < bands_fx; i++ ) + { + test(); + IF( EQ_16(p2a_flags_fx[i],1)||L_tmp2>0) + { + tmp = sub(bands_fx,p2a_bands_fx); + tmp = sub(tmp,lowband);/*Q0 */ + + tmp1 = extract_h(L_shl(Ep_avrg_fx,1));/*Q0 */ + IF(tmp1 != 0) + { + exp = norm_s(tmp1); + tmp1 = shl(tmp1,exp);/*Q(exp) */ + tmp1 = div_s(16384,tmp1);/*Q(15+14-exp = 29-exp) */ + exp = sub(29,exp); + } + ELSE + { + tmp1 = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = Mult_32_16(Ep_tmp_fx[i],tmp1);/*Q(15+exp-15 = exp) */ + L_tmp = Mult_32_16(L_tmp,tmp);/*Q(exp+0-15 = exp-15) */ + L_tmp = Mult_32_16(L_tmp,16384);/*Q(exp-15+13-15 = exp-17) */ + L_tmp = L_shl(L_tmp,sub(32,exp));/*Q15 */ + tmp = extract_l(L_min(L_tmp,6554));/*Q15 */ + L_tmp = Mult_32_16(Ep_vari_fx,tmp1);/*Q(15+exp-15 = exp) */ + L_tmp = Mult_32_16(L_tmp,tmp);/*Q(exp+15-15 = exp) */ + L_tmp = L_shl(L_tmp,sub(15,exp));/*Q15 */ + tmp = extract_l(L_shr(L_min(L_tmp,13107),1));/*Q14 */ + alpha_fx = add(tmp,16384);/*Q14 */ + } + ELSE + { + alpha_fx = 16384; + move16();/*Q14 */ + } + + IF(add(sub(i,bands_fx),p2a_bands_fx) > 0) + { + tmp = sub(bands_fx,p2a_bands_fx); + IF(EQ_16(st_fx->last_bitalloc_max_band_fx[sub(i, add(tmp, 1))], 1)) + { + tmp = sub(tmp,lowband); + L_tmp = Mult_32_16(Ep_tmp_fx[i],tmp);/*Q(15+0-15 = 0) */ + tmp = extract_h(L_shl(L_tmp,16));/*Q0 */ + IF(tmp != 0) + { + exp = norm_s(tmp); + tmp = shl(tmp,exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + tmp = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = Mult_32_16(Ep_avrg_fx,tmp);/*Q(15+exp-15 = exp) */ + L_tmp = L_shl(L_tmp,sub(14,exp));/*Q14 */ + tmp = extract_l(L_min(L_max(L_tmp,16384),20480));/*Q14 */ + L_tmp = L_mult(alpha_fx,tmp);/*Q(14+14+1=29) */ + alpha_fx = extract_l(L_shr(L_tmp,15)); /*Q14 */ + } + ELSE + { + tmp = sub(tmp,lowband); + + tmp1 = extract_h(L_shl(Ep_avrg_fx,1));/*Q0 */ + IF(tmp1 != 0) + { + exp = norm_s(tmp1); + tmp1 = shl(tmp1,exp);/*Q(exp) */ + tmp1 = div_s(16384,tmp1);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + tmp1 = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = Mult_32_16(Ep_tmp_fx[i],tmp1);/*Q(15+exp-15 = exp) */ + L_tmp = Mult_32_16(L_tmp,tmp);/*Q(exp+0-15 = exp-15) */ + L_tmp = L_shl(L_tmp,sub(29,exp));/*Q14 */ + tmp = extract_l(L_min(L_max(L_tmp,13926),16384));/*Q14 */ + L_tmp = L_mult(alpha_fx,tmp);/*Q(14+14+1=29) */ + alpha_fx = extract_l(L_shr(L_tmp,15)); /*Q14 */ + } + } + L_tmp = Mult_32_16(L_band_energy_tmp[i],alpha_fx);/*Q(Q_band_energy+14-15=Q_band_energy-1) */ + L_band_energy_tmp[i] = L_shl(L_tmp,1);/*Q Q_band_energy */ + } + lowband = 6; + move16(); + Ep_avrg_fx = L_deposit_l(0); + Ep_avrgL_fx = L_deposit_l(0); + Ep_peak_fx = L_deposit_l(0); + FOR(i = 0; i < bands_fx; i++) + { + IF(GE_16(i,lowband)) + { + Ep_avrg_fx = L_add(Ep_avrg_fx,Ep_tmp_fx[i]);/*Q15 */ + } + ELSE + { + Ep_avrgL_fx = L_add(Ep_avrgL_fx,Ep_tmp_fx[i]);/*Q15 */ + IF(GT_32(Ep_tmp_fx[i],Ep_peak_fx)) + { + Ep_peak_fx = L_add(Ep_tmp_fx[i], 0); /*Q15 */ + } + } + } + + L_tmp = Mult_32_16(Ep_peak_fx,24576);/*Q(15+12-15 = 12) lowband = 6; */ + L_tmp2 =Mult_32_16(Ep_peak_fx,19661);/*Q(15+14-15 = 14) */ + L_tmp3 =Mult_32_16(Ep_avrgL_fx,24576);/*Q(15+12-15 = 12) */ + + test(); + test(); + test(); + test(); + test(); + IF( (GT_32(L_shr(Ep_avrgL_fx,1), Ep_avrg_fx)&>_32(L_tmp,L_shr(Ep_avrgL_fx,2))&<_32(L_shr(Ep_avrgL_fx,1),L_tmp2))|| + (GT_32(L_shr(Ep_avrg_fx,1), Ep_avrgL_fx) && LT_32(L_shr(Ep_avrg_fx,3),L_tmp3) && GT_32(L_tmp,L_shr(Ep_avrgL_fx,2)) ) ) + { + adjustFlag = 1; + move16(); + FOR (i = 0; i < lowband; i++) + { + tmp = extract_h(L_shl(Ep_avrgL_fx,1));/*Q0 */ + IF(tmp != 0) + { + exp = norm_s(tmp); + tmp = shl(tmp,exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + tmp = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = Mult_32_16(Ep_peak_fx,tmp);/*Q(15+exp-15 = exp) */ + L_tmp = Mult_32_16(L_tmp,lowband);/*Q(exp+0-15 = exp-15) */ + L_tmp = L_shl(L_tmp,sub(28,exp));/*Q14 0.5 */ + tmp = extract_l(L_min(L_tmp,19661));/*//Q14 */ + L_tmp = Mult_32_16(L_band_energy_tmp[i],tmp);/*Q(Q_band_energy+14-15 = Q_band_energy-1) */ + L_band_energy_tmp[i] = L_shl(L_tmp,1); /*Q_band_energy */ + } + } + + hq2_bit_alloc_fx( L_band_energy_tmp, bands_fx, L_Rk, &bit_budget_fx, p2a_flags_fx, bit_alloc_weight_fx, band_width, + *num_bits_fx, hqswb_clas_fx, st_fx->bwidth_fx, is_transient_fx ); + + /* encode the last p2a_bands-1 subbands bit-allocation index of the previous frame */ + FOR(i = 0; i < 2; i++) + { + push_indice_fx( st_fx, IND_HQ2_LAST_BA_MAX_BAND, st_fx->last_bitalloc_max_band_fx[i], 1 ); + } + } + ELSE IF( EQ_16(st_fx->bwidth_fx, SWB)&&EQ_16(hqswb_clas_fx,HQ_HARMONIC)&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))) + { + /* bit allocation for harmonic mode */ + hq2_bit_alloc_har_fx( L_band_energy, bit_budget_fx, bands_fx, L_Rk, p2a_bands_fx, L_bwe_br, p2a_flags_fx, band_width ); + } + ELSE + { + + /* estimate number of bits per band */ + hq2_bit_alloc_fx( + L_band_energy, bands_fx, L_Rk, &bit_budget_fx, p2a_flags_fx, bit_alloc_weight_fx, band_width, + *num_bits_fx, hqswb_clas_fx, st_fx->bwidth_fx, is_transient_fx ); + } + + tcq_core_LR_enc_fx( st_fx, inp_vector_fx, /*t_audio, */L_t_audio, /*y2, */L_y2, bit_budget_fx, bands_fx, band_start, band_end, band_width, /*Rk*/L_Rk, npulses_fx, k_sort_fx, + p2a_flags_fx, p2a_bands_fx, st_fx->last_bitalloc_max_band_fx, inner_frame_fx, adjustFlag, is_transient_fx ); + + IF((EQ_16(inner_frame_fx, L_FRAME8k)&&LE_32(st_fx->core_brate_fx,ACELP_13k20))||EQ_16(inner_frame_fx,L_FRAME16k)) + { + j = 0; + FOR(i = 2; i > 0; i--) + { + IF(npulses_fx[bands_fx-i] > 0) + { + st_fx->last_bitalloc_max_band_fx[j] = 1; + } + ELSE + { + st_fx->last_bitalloc_max_band_fx[j] = 0; + } + j++; + } + } + + /* Denormalize the coded MDCT spectrum */ + mdct_spectrum_denorm_fx( inp_vector_fx, L_y2, band_start, band_end, band_width, L_band_energy, npulses_fx, bands_fx, ld_slope_fx, pd_thresh_fx ); + + /* Apply fine gain quantization to denormalized coded spectrum */ + mdct_spectrum_fine_gain_enc_fx( st_fx, L_t_audio, L_y2, band_start, band_end, k_sort_fx, bands_fx, + L_qint, Ngq_fx, gqlevs_fx, gqbits_fx ); + + + /* Restore the band information */ + IF( EQ_16(flag_spt_fx, 1)) + { + spt_shorten_domain_band_restore_fx(bands_fx, band_start, band_end, band_width, org_band_start, org_band_end, org_band_width); + } + + /* Inject noise into components having relatively low pulse energy per band */ + ni_seed_fx = add(add(add(npulses_fx[0], npulses_fx[1]), npulses_fx[2]), npulses_fx[3]); + + Copy32(L_y2, L_y2_ni, band_end[bands_fx-1]+1); + hq2_noise_inject_fx( L_y2_ni, band_start, band_end, band_width, Ep_fx, L_Rk, npulses_fx, ni_seed_fx, bands_fx, 0, bw_low, bw_high, enerL_fx, enerH_fx, + st_fx->last_ni_gain_fx, st_fx->last_env_fx, &st_fx->last_max_pos_pulse_fx, p2a_flags_fx, p2a_bands_fx, + hqswb_clas_fx, st_fx->bwidth_fx, L_bwe_br ); + + test(); + test(); + IF( EQ_16(st_fx->bwidth_fx, SWB)&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))) + { + test(); + IF( EQ_16(hqswb_clas_fx, HQ_NORMAL)||EQ_16(hqswb_clas_fx,HQ_HARMONIC)) + { + preset_hq2_swb_fx( hqswb_clas_fx, band_end, &har_bands_fx, p2a_bands_fx,length_fx, bands_fx, &lowlength_fx, &highlength_fx, L_m ); + + swb_bwe_enc_lr_fx( + st_fx, + L_y2, SWB_BWE_LR_Qs, L_t_audio, L_m, + L_bwe_br, + bands_fx, band_start, band_end, + L_band_energy, SWB_BWE_LR_Qbe, + p2a_flags_fx, + hqswb_clas_fx, lowlength_fx, highlength_fx, + st_fx->prev_frm_index_fx, + har_bands_fx, + &st_fx->prev_frm_hfe2_fx, &st_fx->prev_stab_hfe2_fx, + band_width, L_y2_ni, &ni_seed_fx + ); + + post_hq2_swb_fx( L_m, lowlength_fx, highlength_fx, hqswb_clas_fx, har_bands_fx, bands_fx, p2a_flags_fx, band_start, band_end, L_y2, npulses_fx ); + + IF( EQ_16(hqswb_clas_fx, HQ_NORMAL)) + { + spt_swb_peakpos_tmp_save_fx(L_y2, bands_fx, band_start, band_end, prev_SWB_peak_pos_tmp_fx); + FOR( k=0; kbwidth_fx, is_transient_fx, hqswb_clas_fx, &st_fx->prev_hqswb_clas_fx, + st_fx->prev_SWB_peak_pos_fx, prev_SWB_peak_pos_tmp_fx, &st_fx->prev_frm_hfe2_fx, &st_fx->prev_stab_hfe2_fx, 0 ); + + IF( NE_16(st_fx->bwidth_fx, SWB)) + { + /* reset HQ classifier memories */ + st_fx->mode_count_fx = 0; + move16(); + st_fx->mode_count1_fx = 0; + move16(); + } + + test(); + test(); + test(); + IF( NE_16(hqswb_clas_fx, HQ_HARMONIC)&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))&&EQ_16(st_fx->bwidth_fx,SWB)) + { + st_fx->prev_frm_index_fx[0] = -1; + move16(); + st_fx->prev_frm_index_fx[1] = -1; + move16(); + } + + /* update number of unused bits */ + *num_bits_fx = 0; + move16(); + + st_fx->hvq_hangover_fx = 0; + move16(); + + return; +} + +/*--------------------------------------------------------------------------* + * small_symbol_enc_tran() + * + * Huffman encoding of differential energies, estimating or packing bits + * if flag_pack = 0, LC mode info. is output else LC mode info. is input + * if flag_pack = 0, estimatng else packing bits + *--------------------------------------------------------------------------*/ + +static Word16 small_symbol_enc_tran_fx( /* o : bits */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *qbidx, /* i : input of dequantized differential energy */ + const Word16 BANDS, /* i : number of bands */ + Word16 *hLCmode, /* i/o: LC mode info */ + const Word16 flag_pack, /* i : indicator of packing or estimating bits */ + const Word16 is_transient +) +{ + Word16 i, bits; + Word16 difidx[BANDS_MAX]; + + FOR( i=0; i= -(2<<(i+1))) */ + test(); + IF ( LE_16(max_q, sub(shl(2, add(i,1)), 1))&& GE_16(min_q,-shl(2,add(i,1)))) + { + BREAK; + } + } + basic_shift = i; + move16(); + + min_bits = 1000; + move16(); + min_bits_pos = basic_shift; + move16(); + tmp = add(basic_shift, 3); + FOR( offset0=basic_shift; offset0 0 ) + { + FOR( i=0; i QE) */ + FOR (i = band_start[k]; i <= band_end[k]; i++) + { + /*E += yos[i] * yos[i]; */ + temp_fx = round_fx(L_shl(L_t_audio[i], exp_norm)); + L_E = L_mac(L_E, temp_fx, temp_fx); /* (Qs+exp_norm-16)*2+1 */ + } + + /*band_energy[k] = (float) log2_f (E + 1.0e-1f); */ + exp_norm2 = norm_l(L_E); + exp = add(add(shl(sub(add(SWB_BWE_LR_Qs, exp_norm), 16), 1), 1), exp_norm2); + L_E = L_shl(L_E, exp_norm2); + frac = Log2_norm_lc(L_E); + exp = sub(30, exp); + L_tmp = L_Comp(exp, frac); + L_band_energy[k] = L_shr(L_tmp, 2); /* Q16->Qbe(Q14) */ + } + + IF (is_transient_fx) + { + reverse_transient_frame_energies_fx( L_band_energy, bands_fx ); + } + + + /* Quantize the reference and band energies */ + exp_normd = norm_l(L_qint); + rev_qint_fx = div_s(0x4000, round_fx(L_shl(L_qint, exp_normd))); /* Q14-(29+exp_normd-16)+15 */ + Qrev_qint = sub(14-(29-16)+15, exp_normd); + + bq0_fx = round_fx(L_shl(L_mult(eref_fx, rev_qint_fx), sub(5, Qrev_qint))); /* 16-(10+Qrev_qint+1) */ + FOR (k = 0; k < bands_fx; k++) + { + /*bq1[k] = round_f (band_energy[k] / qint); */ + L_tmp = Mpy_32_16_1(L_band_energy[k], rev_qint_fx); /* Q14+Qrev_qint-15 */ + bq1_fx[k] = round_fx( L_shl(L_tmp, sub(17, Qrev_qint)) ); /* 16-(14+Qrev_qint-15) */ + } + + IF(is_transient_fx) + { + + Copy(bq1_fx, bq1_temp_fx, bands_fx); + + /* Calculate the differential energies */ + diffcod_lrmdct_fx(bands_fx, bq0_fx, bq1_temp_fx, bq2_temp_fx, is_transient_fx); + } + + /* Calculate the differential energies */ + bq2_fx[0] = sub(bq1_fx[0], bq0_fx); + FOR (k = 1; k < bands_fx; k++) + { + bq2_fx[k] = sub(bq1_fx[k], bq1_fx[k - 1]); + move16(); + } + + /* Modifying qbidx to be located in the range -256~255 */ + FOR( i=0; i Qbe(Q14) */ + } + + IF (is_transient_fx) + { + reverse_transient_frame_energies_fx( L_band_energy, bands_fx ); + } + + return( deng_bits ); +} + + +/*-------------------------------------------------------------------* + * p2a_threshold_quant() + * + * + *-------------------------------------------------------------------*/ + +static Word16 p2a_threshold_quant_fx( + Encoder_State_fx *st, /* i/o: : encoder state structure */ + const Word32 *L_t_audio, /* i : Q12 : input spectrum */ + const Word16 band_start[], /* i : Q0 : table of start freq for every subband */ + const Word16 band_end[], /* i : Q0 : table of end freq for every subband */ + const Word16 band_width[], /* i : Q0 : table of bandwidth for every subband */ + const Word16 bands, /* i : Q0 : number of subbands */ + const Word16 p2a_bands, /* i : Q0 : tonality indicator */ + const Word16 p2a_th_fx, /* i : Q11 : threshold tonal or not */ + Word16 *p2a_flags_fx /* i/o: Q0 : tonality flag */ +) +{ + Word16 i, j, k; + Word32 L_a, L_p, L_e; + Word16 Qa; + Word32 L_tmp; + Word16 temp_fx; + Word16 exp_norm; + Word16 exp_safe; + Word16 exp_normn, exp_normd; + + Word16 norm_a_fx,Qnorm_a; + Word16 pa_fx, Qpa; + + Word16 exp, frac; + + Word32 L_p2a; + Word16 p2a_fx; + + exp_safe=4; /* never happen overflow. */ + + set16_fx(p2a_flags_fx, 1, bands); + + j = 0; + move16(); + FOR (k = sub(bands, p2a_bands); k < bands; k++) + { + L_a = L_deposit_l(0); + L_p = L_deposit_l(0); + + L_tmp = L_deposit_l(0); + FOR (i = band_start[k]; i <= band_end[k]; i++) + { + L_tmp = L_or(L_tmp, L_abs(L_t_audio[i])); + } + exp_norm = norm_l(L_tmp); + exp_norm = sub(exp_norm, exp_safe); + + FOR (i = band_start[k]; i <= band_end[k]; i++) + { + temp_fx = round_fx(L_shl(L_t_audio[i], exp_norm)); /* Q12+exp_norm-16 -> exp_norm-4 */ + L_e = L_mult(temp_fx, temp_fx); + + if ( GT_32(L_e, L_p)) + { + L_p = L_add(L_e, 0); + } + L_a = L_add(L_a, L_e); + } + Qa = sub(shl(exp_norm, 1), 7); /* (exp_norm-4)*2+1 */ + + IF ( L_a > 0x0L ) + { + /* a /= band_width[k]; */ + exp_normn = norm_l(L_a); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_s(band_width[k]); + norm_a_fx = div_l(L_shl(L_a, exp_normn), shl(band_width[k], exp_normd)); + Qnorm_a = sub(sub(add(Qa, exp_normn), exp_normd), 1); /* (Qa+exp_normn)-exp_normd-1); */ + + /*p2a = 10.0f * (float) log10 (p / a); */ + p2a_fx = 0; + move16(); + IF ( norm_a_fx > 0 ) + { + exp_normn = norm_l(L_p); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_s(norm_a_fx); + pa_fx = div_l(L_shl(L_p, exp_normn), shl(norm_a_fx, exp_normd)); + Qpa = sub(sub(add(Qa, exp_normn), add(Qnorm_a, exp_normd)), 1); + + L_tmp = L_deposit_h(pa_fx); + Qpa = add(Qpa, 16); + exp = norm_l(L_tmp); + frac = Log2_norm_lc(L_shl(L_tmp, exp)); + exp = sub(30, exp); + exp = sub(exp, Qpa); + L_tmp = L_Comp(exp, frac); + + /* 10/( log(10)/log(2) ) = 3.01029995663981195211 24660(Q13) */ + L_p2a = Mpy_32_16_1(L_tmp, 24660); /* 16+13-15 -> Q14 */ + + p2a_fx = round_fx(L_shl(L_p2a, 13)); /* 27 -16 -> 11 */ + } + + if ( LE_16(p2a_fx, p2a_th_fx)) + { + p2a_flags_fx[k] = 0; + move16(); + } + } + ELSE + { + p2a_flags_fx[k] = 0; + move16(); + } + + push_indice_fx( st, IND_HQ2_P2A_FLAGS, p2a_flags_fx[k], 1 ); + j = add(j, 1); + } + + return( j ); +} + +/*-------------------------------------------------------------------* + * mdct_spectrum_fine_gain_enc() + * + * + *-------------------------------------------------------------------*/ + +static void mdct_spectrum_fine_gain_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 L_ybuf[], /* i : Q12 : input spectrum */ + Word32 L_y2[], /* i/o: Q12 : decoded spectrum */ + const Word16 band_start[], /* i : Q0 : table of start freq for every subband */ + const Word16 band_end[], /* i : Q0 : table of end freq for every subband */ + const Word16 k_sort[], /* i : Q0 : sort table by band_energy */ + const Word16 bands, /* i : Q0 : nubmber of subbands */ + const Word32 L_qint, /* i : Q29 : */ + const Word16 Ngq, /* i : Q0 : */ + const Word16 gqlevs, /* i : Q0 : quantized level */ + const Word16 gqbits /* i : Q0 : quantized bits */ +) +{ + Word16 i, k; + + Word16 delta_fx, Qdelta; + Word32 L_delta; + Word32 L_q; + + Word16 gain_table_fx[MAX_GQLEVS]; + Word16 Qgt; + Word16 gamma_fx; + Word16 Qgamma; + + Word16 exp_safe; + Word16 exp_normn, exp_normd; + Word16 exp_norm; + + Word32 L_temp; + Word16 temp_lo_fx, temp_hi_fx, temp_fx, temp2_fx; + + Word32 L_Eyy, L_Exy; + /*Word16 QE; */ + + Word16 d_fx; + Word16 dmin_fx; + Word16 imin_fx; + + /* Fine gain quantization on only the most significant energy bands */ + + /*delta = qint / gqlevs; */ + exp_normn = norm_l(L_qint); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_s(gqlevs); + delta_fx = div_l(L_shl(L_qint, exp_normn), shl(gqlevs, exp_normd)); + Qdelta = add(sub(exp_normn, exp_normd), 28); /* 29+exp_normn-(exp_normd)-1; */ + L_delta = L_shl(L_deposit_h(delta_fx), sub(13, Qdelta)); + /*q = (-qint + delta) / 2.0f; */ + L_q = L_shr(L_sub(L_delta, L_qint), 1); + + FOR (i = 0; i < gqlevs; i++) + { + /*gain_table[i] = (float) pow (2.0f, q * 0.5f); */ + L_temp = L_shr(L_shr(L_q, 1), sub(29, 16)); + temp_lo_fx = L_Extract_lc(L_temp, &temp_hi_fx); + Qgt = sub(14, temp_hi_fx); + gain_table_fx[i] = extract_l(Pow2(14, temp_lo_fx)); /* Qgt */ + + /*q += delta; */ + L_q = L_add(L_q, L_delta); + gain_table_fx[i] = shl(gain_table_fx[i], sub(14, Qgt)); /* Qgt -> Q14 */ + } + + FOR (k = sub(bands, Ngq); k < bands; k++) + { + /*Eyy = 0.0f; */ + /*Exy = 0.0f; */ + /*for (i = band_start[k_sort[k]]; i <= band_end[k_sort[k]]; i++) */ + /*{ */ + /* Eyy += y2[i] * y2[i]; */ + /* Exy += ybuf[i] * y2[i]; */ + /*} */ + exp_safe = 4; + move16(); /* 4 is too large. but never happen overflow */ + L_temp = L_deposit_l(0); + FOR (i = band_start[k_sort[k]]; i <= band_end[k_sort[k]]; i++) + { + L_temp = L_or(L_temp, L_abs(L_y2[i])); + L_temp = L_or(L_temp, L_abs(L_ybuf[i])); + } + exp_norm = norm_l(L_temp); + exp_norm = sub(exp_norm, exp_safe); /* safe_shift */ + + L_Eyy = L_deposit_l(0); + L_Exy = L_deposit_l(0); + /*QE = add(shl(add(Qs-16, exp_norm), 1), 1); //(Qs+exp_norm-16)*2+1; */ + FOR (i = band_start[k_sort[k]]; i <= band_end[k_sort[k]]; i++) + { + /*Eyy += y2[i] * y2[i]; */ + temp_fx = round_fx(L_shl(L_y2[i], exp_norm)); + L_Eyy = L_mac(L_Eyy, temp_fx, temp_fx); + + /*Exy += ybuf[i] * y2[i]; */ + temp2_fx = round_fx(L_shl(L_ybuf[i], exp_norm)); + L_Exy = L_mac(L_Exy, temp2_fx, temp_fx); + } + + test(); + IF ( L_Eyy > 0x0L && L_Exy > 0x0L ) + { + /*gamma = Exy / Eyy; */ + exp_normn = norm_l(L_Exy); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_l(L_Eyy); + gamma_fx = div_l(L_shl(L_Exy, exp_normn), round_fx(L_shl(L_Eyy, exp_normd))); + Qgamma = add(sub(exp_normn, exp_normd), 15); /* exp_normn - (exp_normd-16) - 1; */ + gamma_fx = shl(gamma_fx, sub(14, Qgamma)); /* Qgamma -> Q14 */ + + dmin_fx = 32767; + move16(); + imin_fx = -1; + move16(); + FOR (i = 0; i < gqlevs; i++) + { + d_fx = abs_s (sub(gamma_fx, gain_table_fx[i])); + IF ( LT_16(d_fx, dmin_fx)) + { + dmin_fx = d_fx; + move16(); + imin_fx = i; + move16(); + } + } + + gamma_fx = gain_table_fx[imin_fx]; + move16(); /* Q14 */ + + FOR (i = band_start[k_sort[k]]; i <= band_end[k_sort[k]]; i++) + { + /*y2[i] *= gamma; */ + /* This IF statement for keeping same mantissa evenif y2 is plus or minus */ + IF ( L_y2[i] >= 0x0 ) + { + L_y2[i] = L_shl(Mpy_32_16_1(L_y2[i], gamma_fx), 1); + } + ELSE + { + L_y2[i] = L_negate(L_shl(Mpy_32_16_1(L_abs(L_y2[i]), gamma_fx), 1)); + } + } + } + ELSE + { + imin_fx = 0; + move16(); + } + + push_indice_fx( st_fx, IND_HQ2_SUBBAND_GAIN, imin_fx, gqbits ); + } + + return; +} diff --git a/lib_enc/hvq_enc_fx.c b/lib_enc/hvq_enc_fx.c new file mode 100644 index 0000000..9db2687 --- /dev/null +++ b/lib_enc/hvq_enc_fx.c @@ -0,0 +1,232 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" +#include "cnst_fx.h" +#include "stl.h" + +#define HVQ_ENC_NOISE_DELTA ((Word16)3277) /* 0.1 in Q15 */ + +static Word16 quant_lc(const Word16, Word16 *); + + +/*--------------------------------------------------------------------------* + * hvq_enc_fx() + * + * Harmonic VQ encoder + *--------------------------------------------------------------------------*/ + +Word16 hvq_enc_fx( /*o : Consumed bits */ + Encoder_State_fx *st_fx, /*i/o: encoder state structure */ + const Word32 brate, /*i : Total bit rate */ + const Word16 hvq_bits, /*i : HVQ bit budget */ + const Word16 Npeaks, /*i : Number of peaks */ + const Word16 *ynrm, /* i : Envelope coefficients */ + Word16 *R, /* i/o: Bit allocation/updated bit allocation */ + Word16 *peaks, /* i : Peak pos. / Encoded peak pos. */ + Word32 *nf_gains, /* i/o: Noise fill gains / Quant. nf gains */ + Word16 *noise_level, /* o : Quantized noise level */ + const Word32 *pe_gains, /* i : Peak gains */ + const Word32 *coefs, /* i : spectrum coefficients in Q12 */ + Word32 *coefs_out /* o : encoded spectrum coefficients in Q12 */ +) +{ + const Word32 *pCoefs; + Word16 bin_th,j,i,n; + Word16 nf_cnt; + Word16 q_noise_level_idx[HVQ_BWE_NOISE_BANDS]; + Word16 q_noise_level[HVQ_BWE_NOISE_BANDS]; + Word32 d, nf_mean; + Word32 nf, pe, pe_mean; + Word16 bits_used, nBits; + Word16 lb_nfpe; + UWord16 dontCare; + Word32 acc, numerator, denominator; + Word16 expPeMean, expNfMean, expNfpe, expNfpe3, expo, expo3; + Word16 manPeMean, manNfMean, manNfpe, man; + Word16 tmp16, adjust; + + bits_used = 0; + move16(); + + IF ( brate == HQ_24k40 ) + { + bin_th = HVQ_THRES_BIN_24k; + move16(); + n = (L_FRAME32k - HVQ_THRES_BIN_24k)/HVQ_BWE_NOISE_BANDS; + move16(); + } + ELSE + { + bin_th = HVQ_THRES_BIN_32k; + move16(); + n = (L_FRAME32k - HVQ_THRES_BIN_32k)/HVQ_BWE_NOISE_BANDS; + move16(); + } + + nf = 800*4096L; /* Q12 */ move32(); + pe = 800*4096L; /* Q12 */ move32(); + pCoefs = &coefs[bin_th]; + + /* Find HB noise level */ + FOR( i = 0; i < HVQ_BWE_NOISE_BANDS; i++ ) + { + nf_cnt = 0; + move16(); + nf_mean = L_deposit_l(0); + pe_mean = L_deposit_l(0); + FOR( j = 0; j < n; j++) + { + d = L_abs(*pCoefs++); /* Q12 */ + + IF( GT_32(d, pe)) + { + /* W*pe + (1 - W)*d = (pe - d)*W + d */ + acc = L_sub(pe, d); + Mpy_32_16_ss(acc, HVQ_BWE_WEIGHT2_FX, &acc, &dontCare); + pe = L_add(acc, d); /* in Q12 and always positive */ + } + ELSE + { + /* W*pe + (1 - W)*d = (pe - d)*W + d */ + acc = L_sub(pe, d); + Mpy_32_16_ss(acc, HVQ_BWE_WEIGHT1_FX, &acc, &dontCare); + pe = L_add(acc, d); /* in Q12 and always positive */ + + IF( GT_32(d, nf)) + { + acc = L_sub(nf, d); + Mpy_32_16_ss(acc, HVQ_BWE_WEIGHT1_FX, &acc, &dontCare); + nf = L_add(acc, d); /* in Q12 and always positive */ + } + ELSE + { + acc = L_sub(nf, d); + Mpy_32_16_ss(acc, HVQ_BWE_WEIGHT2_FX, &acc, &dontCare); + nf = L_add(acc, d); /* in Q12 always positive */ + } + nf_mean = L_add(nf_mean, nf); /* in Q12 and always positive */ + nf_cnt = add(nf_cnt, 1); /* Q0 */ + } + + pe_mean = L_add(pe_mean, pe); /* in Q12 and always positive */ + } + + IF (pe_mean > 0) + { + expPeMean = norm_l(pe_mean); /* exponent */ + manPeMean = extract_h(L_shl(pe_mean, expPeMean)); /* mantissa */ + expNfMean = norm_l(nf_mean); /* exponent */ + manNfMean = extract_h(L_shl(nf_mean, expNfMean)); /* mantissa */ + + numerator = L_mult0(manNfMean, n); + IF ( nf_cnt > 0 ) + { + denominator = L_mult0(manPeMean, nf_cnt); /* in Q15 */ + } + ELSE + { + denominator = L_mult0(manPeMean, 1); /* in Q15 */ + } + manNfpe = ratio(numerator, denominator, &expo); /* manNfpe in Q14 */ + expNfpe = add(sub(expNfMean, expPeMean), expo); + + tmp16 = mult_r(manNfpe, manNfpe); /* in Q(14+14+1-16) = Q13 */ + tmp16 = mult_r(tmp16, manNfpe); /* in Q(13+14+1-16) = Q12 */ + acc = L_mult(tmp16, HVQ_NFPE_FACTOR_CUBE_FX); /* in Q(12+6+1) = Q19 */ + expNfpe3 = extract_l(L_mult0(expNfpe, 3)); /* Cube operation */ + /* Number of bits required to adjust to Q15 */ + adjust = add(19 - (15 + 16), expNfpe3); /* +16 is due to the following extract_h(). */ + noise_level[i] = extract_h(L_shr(acc, adjust)); /* noise_level[] in Q15 */ + + q_noise_level_idx[i] = quant_lc( noise_level[i], &q_noise_level[i] ); + } + ELSE + { + q_noise_level_idx[i] = 0; + move16(); + q_noise_level[i] = 0; + move16(); + } + push_indice_fx(st_fx, IND_HVQ_BWE_NL, q_noise_level_idx[i], 2 ); + bits_used = add(bits_used, 2); + + noise_level[i] = q_noise_level[i]; /* in Q15 */ + } + + FOR( i = 0; i < HVQ_NF_GROUPS; i ++ ) + { + IF (pe_gains[i] != 0) + { + /* Neither pe_gains[] nor nf_gains[] is zero. */ + man = ratio(nf_gains[i], pe_gains[i], &expo); /* man in Q14 */ + tmp16 = mult_r(man, man); /* in Q(14+14+1-16) = Q13 */ + tmp16 = mult_r(tmp16, man); /* in Q(13+14+1-16) = Q12 */ + acc = L_mult(tmp16, HVQ_LB_NFPE_FACTOR_CUBE_FX); /* in Q(12+9+1) = Q22 */ + expo3 = extract_l(L_mult0(expo, 3)); /* Cube operation. */ + /* Number of bits required to adjust to Q15 */ + adjust = add(22 - (15 + 16), expo3); /* +16 is due to the following extract_h(). */ + lb_nfpe = extract_h(L_shr(acc, adjust)); /* noise_level[] in Q15 */ + + IF( lb_nfpe > 16384 ) /* in Q15 */ + { + lb_nfpe = 16384; + move16(); + } + Mpy_32_16_ss(nf_gains[i], shl(lb_nfpe, 1), &nf_gains[i], &dontCare); /* nf_gains[] in Q12 */ + } + ELSE + { + nf_gains[i] = 0; + move16(); + } + } + nBits = peak_vq_enc_fx( st_fx, coefs, coefs_out, brate, sub(hvq_bits, bits_used), + Npeaks, ynrm, R, peaks, &nf_gains[0] ); + bits_used = add(bits_used, nBits); + return bits_used; +} + +/*----------------------------------------------------------------------------- + * quant() + * + * Quantize the noise to one of the levels in {0, 0.1, 0.2, 0.3} + *----------------------------------------------------------------------------*/ +static Word16 quant_lc(const Word16 x, Word16 *qx) +{ + Word16 indx; + + IF (LT_16(x, HVQ_ENC_NOISE_DELTA/2)) + { + indx = 0; + move16(); + *qx = 0; + move16(); + } + ELSE IF (LT_16(x, 3*HVQ_ENC_NOISE_DELTA/2)) + { + indx = 1; + move16(); + *qx = HVQ_ENC_NOISE_DELTA; + move16(); + } + ELSE IF (LT_16(x, 5*HVQ_ENC_NOISE_DELTA/2)) + { + indx = 2; + move16(); + *qx = 2*HVQ_ENC_NOISE_DELTA; + move16(); + } + ELSE + { + indx = 3; + move16(); + *qx = 3*HVQ_ENC_NOISE_DELTA; + move16(); + } + + return indx; +} + diff --git a/lib_enc/igf_enc.c b/lib_enc/igf_enc.c new file mode 100644 index 0000000..fcf2f37 --- /dev/null +++ b/lib_enc/igf_enc.c @@ -0,0 +1,1316 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "options.h" +#include "stl.h" +#include "prot_fx.h" +#include "cnst_fx.h" +#include "stat_enc_fx.h" +#include "basop_util.h" + +/**********************************************************************/ /* +write single bit to stream +**************************************************************************/ +static void IGF_write_bit(Encoder_State_fx *st, /**< in: | encoder state structure */ + Word16 *bitCount, /**< in/out: | bit counter */ + Word16 bit /**< in: | value of bit */ + ) +{ + IGFCommonFuncsWriteSerialBit(st, bitCount, bit); + +} + +/**********************************************************************/ /* +write bits to stream +**************************************************************************/ +static void IGF_write_bits(Encoder_State_fx *st, /**< in: | encoder state structure */ + Word16 *bitCount, /**< in/out: | bit counter */ + Word16 value, /**< in: | value to be written */ + Word16 bits /**< in: Q0 | number of bits */ + ) +{ + Word16 tmp; + + WHILE (bits) + { + bits = sub(bits, 1); + tmp = s_and(value, shl(1, bits)); + IF (tmp == 0) + { + IGF_write_bit(st, bitCount, 0); + } + ELSE + { + IGF_write_bit(st, bitCount, 1); + } + } + + return; +} + + +/**********************************************************************/ /* +envelope estimation +**************************************************************************/ +static void IGF_CalculateEnvelope(const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + Word32 *pMDCTSpectrum, /**< in: Q31 | MDCT spectrum */ + Word16 MDCTSpectrum_e, /**< in: | exponent of MDCT spectrum */ + Word32 *pPowerSpectrum, /**< in: Q31 | MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 PowerSpectrum_e, /**< in: | exponent of MDCT^2 + MDST^2 spectrum, or estimate */ + const Word16 igfGridIdx /**< in: Q0 | IGF grid index */ + + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 *swb_offset; + Word16 sfb; /* this is the actual scalefactor band */ + Word16 width; /* this is width in subbands of the actual scalefactor band */ + Word16 tile_idx; + Word16 strt_cpy; + Word16 gain; /* the gain which has to be applied to the source tile to get the destination energy */ + Word16 gain_exp; + Word16 tb; + Word16 zeroNrg; /* Q0 | flag indicating if the signal contains almost no energy */ + Word32 sfbEnergyR[IGF_MAX_SFB]; + Word16 sfbEnergyR_exp[IGF_MAX_SFB]; + Word32 sfbEnergyC[IGF_MAX_SFB]; /* the energy of the destination region of the tile */ + Word16 sfbEnergyC_exp[IGF_MAX_SFB]; + Word32 sfbEnergyTileR[IGF_MAX_SFB]; + Word16 sfbEnergyTileR_exp[IGF_MAX_SFB]; + Word32 sfbEnergyTileC[IGF_MAX_SFB]; /* the energy of the destination region of the tile */ + Word16 sfbEnergyTileC_exp[IGF_MAX_SFB]; + Word32 LFMDCTSpectrum[N_MAX]; + Word16 LFMDCTSpectrum_exp; + Word32 LFPowerSpectrum[N_MAX]; + Word16 tmp; + Word16 tmp_exp; + Word32 L_tmp; + Word16 shift; + + + /* initialize variables */ + Copy32(pMDCTSpectrum + IGF_START_MN, hInstance->spec_be_igf, hInstance->infoStopLine-IGF_START_MN); + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + swb_offset = hGrid->swb_offset; + move16(); + hInstance->spec_be_igf_e = MDCTSpectrum_e; + move16(); + zeroNrg = 0; + move16(); + + + IF (pPowerSpectrum != NULL) + { + FOR (tile_idx = 0; tile_idx < hGrid->nTiles; tile_idx++) + { + strt_cpy = hGrid->sbWrap[tile_idx]; + move16(); + FOR (sfb = hGrid->sfbWrap[tile_idx]; sfb < hGrid->sfbWrap[tile_idx + 1]; sfb++) + { + FOR (tb = swb_offset[ sfb ]; tb < swb_offset[ sfb+1 ]; tb++) + { + LFMDCTSpectrum[tb] = pMDCTSpectrum[strt_cpy]; + move32(); + LFPowerSpectrum[tb] = pPowerSpectrum[strt_cpy]; + move32(); + strt_cpy = add(strt_cpy, 1); + } + } + } + IGFCommonFuncsCalcSfbEnergyPowerSpec(hGrid->startSfb, + hGrid->stopSfb, + hGrid->swb_offset, + pPowerSpectrum, + &PowerSpectrum_e, + sfbEnergyC, + sfbEnergyC_exp); + IGFCommonFuncsCalcSfbEnergyPowerSpec(hGrid->startSfb, + hGrid->stopSfb, + hGrid->swb_offset, + LFPowerSpectrum, + &PowerSpectrum_e, + sfbEnergyTileC, + sfbEnergyTileC_exp); + IGFCommonFuncsMDCTSquareSpec(hGrid->startLine, + hGrid->stopLine, + LFMDCTSpectrum, + MDCTSpectrum_e, + LFMDCTSpectrum, + &LFMDCTSpectrum_exp, + 0); + IGFCommonFuncsCalcSfbEnergyPowerSpec(hGrid->startSfb, + hGrid->stopSfb, + hGrid->swb_offset, + LFMDCTSpectrum, + &LFMDCTSpectrum_exp, + sfbEnergyTileR, + sfbEnergyTileR_exp); + } + ELSE + { + IGFCommonFuncsMDCTSquareSpec(hGrid->startLine, + hGrid->stopLine, + pMDCTSpectrum, + MDCTSpectrum_e, + LFMDCTSpectrum, + &LFMDCTSpectrum_exp, + 0); + IGFCommonFuncsCalcSfbEnergyPowerSpec(hGrid->startSfb, + hGrid->stopSfb, + hGrid->swb_offset, + LFMDCTSpectrum, + &LFMDCTSpectrum_exp, + sfbEnergyR, + sfbEnergyR_exp); + } + + FOR (tile_idx = 0; tile_idx < hGrid->nTiles; tile_idx++) + { + + FOR(sfb = hGrid->sfbWrap[tile_idx]; sfb < hGrid->sfbWrap[tile_idx + 1]; sfb++) + { + + + width = sub(swb_offset[sfb + 1], swb_offset[sfb]); + L_tmp = 0; + move16(); + gain_exp = 0; + move16(); + + IF (pPowerSpectrum) + { + IF (sfbEnergyTileR[sfb] == 0) + { + sfbEnergyTileR[sfb] = 0x00010000; + move32(); + sfbEnergyTileR_exp[sfb] = 0; + move16(); + zeroNrg = 1; + move16(); + } + IF (sfbEnergyTileC[sfb] == 0) + { + sfbEnergyTileC[sfb] = 0x00010000; + move32(); + sfbEnergyTileC_exp[sfb] = 0; + move16(); + zeroNrg = 1; + move16(); + } + IF (sfbEnergyC[sfb] == 0) + { + sfbEnergyC[sfb] = 0x00010000; + move32(); + sfbEnergyC_exp[sfb] = 0; + move16(); + zeroNrg = 1; + move16(); + } + + BASOP_Util_Divide_MantExp(round_fx(sfbEnergyTileR[sfb]), + sfbEnergyTileR_exp[sfb], + width, + 15, + &gain, + &gain_exp); + BASOP_Util_Divide_MantExp(round_fx(sfbEnergyC[sfb]), + sfbEnergyC_exp[sfb], + round_fx(sfbEnergyTileC[sfb]), + sfbEnergyTileC_exp[sfb], + &tmp, + &tmp_exp); + L_tmp = L_mult(gain, tmp); + gain_exp = add(gain_exp, tmp_exp); + + + } + ELSE + { + IF(sfbEnergyR[sfb] == 0) + { + sfbEnergyR[sfb] = 0x00010000; + move32(); + sfbEnergyR_exp[sfb] = 0; + move16(); + zeroNrg = 1; + move16(); + } + BASOP_Util_Divide_MantExp(round_fx(sfbEnergyR[sfb]), + sfbEnergyR_exp[sfb], + width, + 15, + &gain, + &gain_exp); + L_tmp = L_deposit_h(gain); + + + } + + /* gain = 0.5f + (float)((2.885390081777927f * log(gain) + 16.f)); */ + L_tmp = BASOP_Util_Log2(L_tmp); + L_tmp = L_add(L_tmp, L_deposit_h(shl(gain_exp, 15-6))); + shift = norm_l(L_tmp); + gain = round_fx(L_shl(L_tmp, shift)); + gain_exp = sub(7, shift); + gain_exp = BASOP_Util_Add_MantExp(gain, gain_exp, 32767/*16 Q11*/, 4, &gain); + gain_exp = BASOP_Util_Add_MantExp(gain, gain_exp, 0x4000, 0, &gain); + gain = shr(gain, s_min(sub(15, gain_exp), 15)); + + if (gain > 91) + { + gain = s_min(gain, 91); /* 13+15+63, see arithocde encode residual */ + } + if (gain < 0) + { + gain = s_max(gain, 0); + } + + /* set gain to zero if the signal contains too less energy */ + if (zeroNrg != 0) + { + gain = 0; + move16(); + } + + hPrivateData->igfScfQuantized[sfb] = gain; + move16(); + } + } + + return; +} + +/**********************************************************************/ /* +writes IGF SCF values +**************************************************************************/ +static void IGF_WriteEnvelope( /**< out: Q0 | number of bits writen */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + Encoder_State_fx *st, /**< in: | encoder state */ + Word16 *pBitOffset, /**< in: | ptr to bitOffset counter */ + const Word16 igfGridIdx, /**< in: Q0 | igf grid index see declaration of IGF_GRID_IDX for details */ + const Word16 isIndepFlag, /**< in: Q0 | if 1 frame is independent, 0 = frame is coded with data from previous frame */ + Word16 *igfAllZero /**< in: Q0 | returns 1 if all IGF scfs are zero, else 0 */ +) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 sfb; + + *igfAllZero = 1; + move16(); + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + + FOR (sfb = hGrid->startSfb; sfb < hGrid->stopSfb; sfb++) + { + IF (hPrivateData->igfScfQuantized[sfb] != 0) + { + *igfAllZero = 0; + move16(); + BREAK; + } + } + + IF (*igfAllZero != 0) + { + IGF_write_bit(st, pBitOffset, 1); + IF (NULL == st) + { + IGFSCFEncoderSaveContextState(&hPrivateData->hIGFSCFArithEnc); + } + IGFSCFEncoderReset(&hPrivateData->hIGFSCFArithEnc); + IF (NULL == st) + { + IGFSCFEncoderRestoreContextState(&hPrivateData->hIGFSCFArithEnc); + } + } + ELSE + { + IGF_write_bit(st, pBitOffset, 0); + IF (NULL == st) + { + IGFSCFEncoderSaveContextState(&hPrivateData->hIGFSCFArithEnc); + } + + *pBitOffset = IGFSCFEncoderEncode(&hPrivateData->hIGFSCFArithEnc, + st, + *pBitOffset, + &hPrivateData->igfScfQuantized[hGrid->startSfb], + isIndepFlag, + (NULL != st)); + move16(); + + IF (NULL == st) + { + IGFSCFEncoderRestoreContextState(&hPrivateData->hIGFSCFArithEnc); + } + } + +} + +/**********************************************************************/ /* +identifies significant spectral content +**************************************************************************/ +static void IGF_ErodeSpectrum(Word16 *highPassEner_exp, /**< out: | exponent of highPassEner */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + Word32 *pSpectrum, /**< in/out: | MDCT spectrum */ + Word32 *pPowerSpectrum, /**< in/out: | power spectrum */ + Word16 pPowerSpectrum_exp, /**< in: | exponent of power spectrum */ + const Word16 igfGridIdx /**< in: Q0 | IGF grid index */ + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 i; + Word16 igfBgn; + Word16 igfEnd; + Word32 highPassEner; /* Q31 */ + Word32 lastLine; + Word32 nextLine; + Word32 L_c; + Word32 highPassEner_Ovfl; + Word16 s; + Word16 tmploop; + Word16 *swb_offset; + Word16 sfb; + Word16 startSfb; + Word16 stopSfb; + Word16 line; + Word16 flag; + Word16 *igfScaleF; + Word16 tmp; + Word32 L_tmp; + + + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + igfBgn = hGrid->startLine; + move16(); + igfEnd = hGrid->stopLine; + move16(); + swb_offset = hGrid->swb_offset; + move16(); + startSfb = hGrid->startSfb; + move16(); + stopSfb = hGrid->stopSfb; + move16(); + igfScaleF = hPrivateData->igfScfQuantized; + move16(); + *highPassEner_exp = 0; + move16(); + highPassEner = 0; + move32(); + + IF (NULL == pPowerSpectrum) + { + FOR (i = igfBgn; i< hGrid->infoGranuleLen; i++) + { + pSpectrum[i] = L_deposit_l(0); + } + return; + } + + IF (igfBgn > 0) + { + L_c = 0; move32(); + FOR (i = 0; i < igfBgn; i++) + { + Carry = 0; + highPassEner = L_add_c(highPassEner, Mpy_32_16_1(pPowerSpectrum[i], shl(i,4)/*Q4*/)/*Q20, pPowerSpectrum_exp*/); + Overflow = 0; + L_c = L_macNs(L_c, 0, 0); + } + + highPassEner = norm_llQ31(L_c, highPassEner, highPassEner_exp); /*Q20, highPassEner_exp*/ + *highPassEner_exp = add(*highPassEner_exp, pPowerSpectrum_exp); + test(); + test(); + if ( NE_16(hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_SWB_9600)&& + NE_16(hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_RF_SWB_13200) && + NE_16(hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_SWB_13200 ) ) + { + igfBgn = shl(igfBgn, 1); + } + highPassEner = L_deposit_l(BASOP_Util_Divide3216_Scale(highPassEner/*Q20, highPassEner_exp*/, igfBgn /*Q0*/,&s)); /*Q15, highPassEner_exp+11-16+s*/ + *highPassEner_exp = add(add(*highPassEner_exp,s),12 - 16 + (31 - 15)); /*Q15->Q31,highPassEner_exp*/ + lastLine = pSpectrum[i - 1]; + move32(); + nextLine = 0; + move32(); + + /* May overflow - just for threshold comparison */ + /* negate because the negated may be 1 larger in abs, */ + /* so whenever compared to the negation of a maximum possible pPowerspectrum, it is still larger */ + BASOP_SATURATE_WARNING_OFF + highPassEner_Ovfl = L_shl(L_negate(highPassEner), sub(*highPassEner_exp, pPowerSpectrum_exp)); + L_tmp = L_add(pPowerSpectrum[i - 1], highPassEner_Ovfl); + BASOP_SATURATE_WARNING_ON + + if (L_tmp >= 0) + { + nextLine = pSpectrum[i]; + move32(); + } + tmploop = sub(igfEnd,1); + FOR (/*i*/; i < tmploop; i++) + { + /* May overflow - just for threshold comparison */ + BASOP_SATURATE_WARNING_OFF + L_tmp = L_add(pPowerSpectrum[i], highPassEner_Ovfl); + BASOP_SATURATE_WARNING_ON + + IF (L_tmp < 0) + { + lastLine = pSpectrum[i]; + move32(); + pSpectrum[i] = nextLine; + move32(); + nextLine = 0; + move32(); + } + ELSE + { + pSpectrum[i-1] = lastLine; + move32(); + lastLine = pSpectrum[i]; + move32(); + nextLine = pSpectrum[i+1]; + move32(); + } + } + + /* May overflow - just for threshold comparison */ + BASOP_SATURATE_WARNING_OFF + L_tmp = L_add(pPowerSpectrum[i], highPassEner_Ovfl); + BASOP_SATURATE_WARNING_ON + IF (L_tmp < 0) + { + pSpectrum[i] = L_deposit_l(0); + } + } + + /* delete spectrum above igfEnd: */ + FOR (i = igfEnd; i < hGrid->infoGranuleLen; i++) + { + pSpectrum[i] = L_deposit_l(0); + pPowerSpectrum[i] = L_deposit_l(0); + } + + FOR (sfb = startSfb; sfb < stopSfb; sfb++) + { + flag = 0; + move16(); + FOR (line = swb_offset[sfb]; line < swb_offset[sfb+1]; line++) + { + if (pSpectrum[line] != 0) + { + flag = 1; + move16(); + } + } + tmp = igfScaleF[sfb]; + move16(); + if(flag) + { + tmp = sub(igfScaleF[sfb], 1); + } + if (igfScaleF[sfb]) + { + igfScaleF[sfb] = tmp; + move16(); + } + } + +} + +/**********************************************************************/ /* +crest factor calculation +**************************************************************************/ +static Word16 IGF_getCrest( /**< out: Q15| crest factor */ + Word16 *crest_exp, /**< out: | exponent of crest factor */ + const Word32 *powerSpectrum, /**< in: Q31 | power spectrum */ + const Word16 powerSpectrum_exp, /**< in: | exponent of power spectrum */ + const Word16 start, /**< in: Q0 | start subband index */ + const Word16 stop /**< in: Q0 | stop subband index */ +) +{ + Word16 i; + Word16 x; + Word16 s; + Word32 x_eff32; + Word16 x_max; + Word16 crest; + Word16 tmp; + Word32 tmp32; + + x_eff32 = 0; move32(); + x_max = 0; + move16(); + crest = 16384/*.5f Q15*/; + move16(); + *crest_exp = 1; + move16(); + + FOR (i = start; i < stop; i++) + { + /*x = max(0, (int)(log(powerSpectrum[i]) * INV_LOG_2));*/ + + /*see IGF_getSFM for more comment */ + x = sub(sub(powerSpectrum_exp, norm_l(powerSpectrum[i])), 1); /*Q0*/ + if (powerSpectrum[i] == 0) /*special case: energy is zero*/ + { + x = 0; + move16(); + } + x = s_max(0, x); + x_eff32 = L_mac0(x_eff32, x ,x); /*Q0*/ + x_max = s_max(x_max, x); /*Q0*/ + } + + /*x_eff /= (stop - start);*/ + x_eff32 = BASOP_Util_Divide3216_Scale(x_eff32, sub(stop,start), &s); /*Q-1, s*/ + s = add(s, 32); /*make x_eff Q31*/ + + /*trunkate to int*/ + x_eff32 = L_shr(x_eff32, sub(31, s)); + x_eff32 = L_shl(x_eff32, sub(31, s)); + + test(); + IF (x_eff32 > 0 && x_max > 0) + { + /*crest = max(1.f, (float)x_max/sqrt(x_eff));*/ + tmp32 = ISqrt32(x_eff32, &s); /*Q31, s*/ + tmp32 = Mpy_32_16_1(tmp32/*Q31, s*/, x_max/*Q0*/); /*Q16, s*/ + i = norm_l(tmp32); + tmp32 = L_shl(tmp32, i); /*Q31, s-i+15*/ + crest = extract_h(tmp32); + *crest_exp = add(sub(s, i), 15); + + /* limit crest factor to a lower bound of 1, may overflow */ + BASOP_SATURATE_WARNING_OFF + tmp = shl(-1, sub(15, *crest_exp)); /* build negative threshold */ + tmp = add(crest, tmp); + BASOP_SATURATE_WARNING_ON + if (tmp < 0) + { + crest = 1; + move16(); + } + if (tmp < 0) + { + *crest_exp = 15; + move16(); + } + } + + return crest; +} + +/************************************************************************* +calculates spectral flatness measurment +**************************************************************************/ +static Word16 IGF_getSFM( /**< out: Q15| SFM value */ + Word16 *SFM_exp, /**< out: | exponent of SFM Factor */ + const Word32 *energy, /**< in: Q31| energies */ + const Word16 *energy_exp, /**< in: | exponent of energies */ + const Word16 start, /**< in: Q0 | start subband index */ + const Word16 stop /**< in: Q0 | stop subband index */ +) +{ + Word16 n,i, s; + Word32 num; + Word32 denom; + Word16 denom_exp; + Word16 invDenom_exp, numf_exp; + Word16 numf; + Word32 SFM32; + Word32 L_c; + Word16 invDenom, SFM; + + L_c = 0; move32(); + num = 0; move32(); + denom = L_shr(2147483 /*0,001 in Q31 - float is "1", here*/,s_min(*energy_exp, 31)); + denom = L_max(denom, 1); + *SFM_exp = 0; + move16(); + SFM = 32767/*1.0f Q15*/; + move16(); + + FOR (i = start; i < stop; i++) + { + /*ln(x * 2^-Qx * 2^xExp) = ln(x) - Qx + xExp*/ + + /* n = sub(sub(31,norm_l(tmp32)),1); */ /*<- ld */ + /* n = sub(n,31); */ /*<- -Qx */ + /* n = add(n,*energy_exp); */ /*<- +xExp */ + + n = sub(sub(*energy_exp, norm_l(energy[i])), 1); /*<-- short form*/ + + if (energy[i] == 0) /*special case: energy is zero*/ + { + n = 0; + move16(); + } + + n = s_max(0, n); + num = L_add(num, L_deposit_l(n)); /*Q0*/ + + Carry = 0; + denom = L_add_c(energy[i], denom); + Overflow = 0; + + L_c = L_macNs(L_c, 0, 0); + } + + denom = norm_llQ31(L_c, denom, &denom_exp); /*Q31*/ + denom_exp = add(denom_exp, *energy_exp); + + /* calculate SFM only if signal is present */ + IF (denom != 0) + { + /*numf = (float)num / (float)(stop - start);*/ + numf = BASOP_Util_Divide3216_Scale(num, /*Q0*/ + sub(stop,start), /*Q0*/ + &s); /*Q-1 s*/ + numf_exp = add(s,16); /*-> numf Q15 numf_exp*/ + /*denom /= (float)(stop - start);*/ + /*return ((float)pow(2.0, numf + 0.5f) / denom);*/ + + /*SFM= ((float)pow(2.0, numf + 0.5f) * invDenom);*/ + invDenom = BASOP_Util_Divide3232_uu_1616_Scale(L_deposit_l(sub(stop, start)) /*Q0*/, + denom /*Q31, denom_exp*/, + &s); /*Q-16, s-denom_exp*/ + invDenom_exp = add(sub(s, denom_exp), 31); /*invDenom: Q15, invDenom_exp*/ + + /*add .5f to numf*/ + SFM32 = L_add(L_shl(L_deposit_l(numf), numf_exp) /*16Q15*/,16384l/*.5f Q15*/); /*16Q15*/ + s = norm_l(SFM32); + SFM32 = L_shl(SFM32, s); + s = sub(16, s); /*SFM32(numf) is Q31 now*/ + + /*do the pow2 and the mult*/ + SFM32 = BASOP_util_Pow2(SFM32, s, &s); + SFM32 = Mpy_32_16_1(SFM32, invDenom); + *SFM_exp = add(s, invDenom_exp); + + /*Transform to Q15*/ + s = norm_l(SFM32); + SFM = round_fx(L_shl(SFM32, s)); + *SFM_exp = sub(*SFM_exp, s); + + /**SFM_exp = s_min(*SFM_exp, 0);*/ + IF (*SFM_exp > 0) + { + *SFM_exp = 0; + move16(); + SFM = 32767/*1.0f Q15*/; + move16(); + } + } + + return SFM /*Q15*/; +} + +/**********************************************************************/ /* +calculates the IGF whitening levels by SFM and crest +**************************************************************************/ +static void IGF_Whitening(const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + Word32 *powerSpectrum, /**< in: Q31 | MDCT/MDST power spectrum */ + const Word16 powerSpectrum_exp, /**< in: | exponent of powerspectrum */ + const Word16 igfGridIdx, /**< in: Q0 | IGF grid index */ + Word16 isTransient, /**< in: Q0 | boolean, indicating if transient is detected */ + Word16 last_core_acelp /**< in: Q0 | indictaor if last frame was acelp coded */ + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 p; /*Q0*/ + Word16 tmp; + Word16 SFM; + Word16 crest; + Word16 SFM_exp; + Word16 crest_exp; + Word16 s; + Word32 tmp32; + Word32 SFM32; + + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + + IF (igfGridIdx != IGF_GRID_LB_NORM) + { + FOR (p = 0; p < hGrid->nTiles; p++) + { + /* reset filter */ + hPrivateData->prevSFM_FIR[p] = L_deposit_l(0); + hPrivateData->prevSFM_IIR[p] = 0; + move16(); + + /* preset values: */ + hPrivateData->igfCurrWhiteningLevel[p] = IGF_WHITENING_OFF; + move16(); + } + } + FOR (p = 0; p < IGF_MAX_TILES; p++) + { + /* update prev data: */ + hPrivateData->igfPrevWhiteningLevel[p] = hPrivateData->igfCurrWhiteningLevel[p]; + move16(); + /* preset values: */ + hPrivateData->igfCurrWhiteningLevel[p] = IGF_WHITENING_OFF; + move16(); + } + + IF (!s_or(isTransient, hPrivateData->wasTransient)) + { + IF (powerSpectrum) + { + Word16 nT = hGrid->nTiles; + SWITCH (hPrivateData->igfInfo.bitRateIndex) + { + case IGF_BITRATE_WB_9600: + case IGF_BITRATE_SWB_9600: + case IGF_BITRATE_SWB_16400: + case IGF_BITRATE_SWB_24400: + case IGF_BITRATE_SWB_32000: + case IGF_BITRATE_FB_16400: + case IGF_BITRATE_FB_24400: + case IGF_BITRATE_FB_32000: + nT = sub(nT, 1); + BREAK; + default: + BREAK; + } + FOR (p = 0; p < nT; p++) + { + /*tmp = IGF_getSFM(powerSpectrum, hGrid->tile[p], hGrid->tile[p+1]) / IGF_getCrest(powerSpectrum, hGrid->tile[p], hGrid->tile[p+1]);*/ + SFM = IGF_getSFM(&SFM_exp, powerSpectrum, &powerSpectrum_exp, hGrid->tile[p], hGrid->tile[p + 1]); + crest = IGF_getCrest(&crest_exp, powerSpectrum, powerSpectrum_exp, hGrid->tile[p], hGrid->tile[p + 1]); + + tmp = BASOP_Util_Divide1616_Scale(SFM, crest, &s); /* Q15 */ + s = add(s, sub(SFM_exp, crest_exp)); + tmp32 = L_shl(L_deposit_l(tmp)/*16Q15, s*/,add(s,1)); /* 15Q16 */ + + test(); + IF (last_core_acelp || hPrivateData->wasTransient) + { + hPrivateData->prevSFM_FIR[p] = tmp32; /* 15Q16 */ move32(); + hPrivateData->prevSFM_IIR[p] = shr(tmp, 2); /* 2Q13 */ move16(); + } + + /*SFM = tmp + hPrivateData->prevSFM_FIR[p] + 0.5f * hPrivateData->prevSFM_IIR[p];*/ + SFM32 = L_add(tmp32,hPrivateData->prevSFM_FIR[p]); + SFM32 = L_mac0(SFM32,hPrivateData->prevSFM_IIR[p]/*Q13*/,4/*.5f Q3*/);/*15Q16*/ + + BASOP_SATURATE_WARNING_OFF + /*SFM = min(2.7f, SFM);*/ + /*Overflow possible in shift, intended*/ + SFM = s_min(22118/*2.7f Q13*/,extract_h(L_shr(SFM32,16-29)/*->Q29*/)/*->Q13*/ ); + BASOP_SATURATE_WARNING_ON + + hPrivateData->prevSFM_FIR[p] = tmp32; /*15Q16*/ move32(); + hPrivateData->prevSFM_IIR[p] = SFM; + move16(); + + IF (GT_16(SFM , hGrid->whiteningThreshold[1][p])) + { + hPrivateData->igfCurrWhiteningLevel[p] = IGF_WHITENING_STRONG; + move16(); + } + ELSE IF (GT_16(SFM , hGrid->whiteningThreshold[0][p])) + { + hPrivateData->igfCurrWhiteningLevel[p] = IGF_WHITENING_MID; + move16(); + } + } + SWITCH (hPrivateData->igfInfo.bitRateIndex) + { + case IGF_BITRATE_WB_9600: + case IGF_BITRATE_RF_WB_13200: + case IGF_BITRATE_RF_SWB_13200: + case IGF_BITRATE_SWB_9600: + case IGF_BITRATE_SWB_16400: + case IGF_BITRATE_SWB_24400: + case IGF_BITRATE_SWB_32000: + case IGF_BITRATE_FB_16400: + case IGF_BITRATE_FB_24400: + case IGF_BITRATE_FB_32000: + move16(); + hPrivateData->igfCurrWhiteningLevel[hGrid->nTiles - 1] = hPrivateData->igfCurrWhiteningLevel[hGrid->nTiles - 2]; + BREAK; + default: + BREAK; + } + } + ELSE + { + FOR (p = 0; p < hGrid->nTiles; p++) + { + hPrivateData->igfCurrWhiteningLevel[p] = IGF_WHITENING_MID; + move16(); + } + } + } + ELSE + { + /* reset filter */ + FOR (p = 0; p < IGF_MAX_TILES; p++) + { + hPrivateData->prevSFM_FIR[p] = L_deposit_l(0); + hPrivateData->prevSFM_IIR[p] = 0; + move16(); + } + } + hPrivateData->wasTransient = isTransient; + move16(); + +} + +/**********************************************************************/ /* +write whitening levels into bitstream +**************************************************************************/ +static void IGF_WriteWhiteningTile( /**< out: Q0 | number of bits written */ + Encoder_State_fx *st, /**< in: | encoder state handle */ + Word16 *pBitOffset, /**< in: | ptr to bitOffset counter */ + Word16 whiteningLevel /**< in: Q0 | whitening levels to write */ +) +{ + IF (EQ_32(whiteningLevel, IGF_WHITENING_MID)) + { + IGF_write_bits(st, pBitOffset, 0, 1); + } + ELSE + { + IGF_write_bits(st, pBitOffset, 1, 1); + IF (EQ_32(whiteningLevel , IGF_WHITENING_OFF)) + { + IGF_write_bits(st, pBitOffset, 0, 1); + } + ELSE + { + IGF_write_bits(st, pBitOffset, 1, 1); + } + } +} + +/**********************************************************************/ /* +writes the whitening levels +**************************************************************************/ +static void IGF_WriteWhiteningLevels( /**< out: Q0 | total number of bits written */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF encoder */ + Encoder_State_fx *st, /**< in: | encoder state */ + Word16 *pBitOffset, /**< in: | ptr to bitOffset counter */ + const Word16 igfGridIdx, /**< in: Q0 | igf grid index see declaration of IGF_GRID_IDX for details */ + const Word16 isIndepFlag /**< in: Q0 | if 1 frame is independent, 0 = frame is coded with data from previous frame */ +) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 p; + Word16 nTiles; + Word16 isSame; + Word32 tmp32; + + + isSame = 1; + move16(); + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + nTiles = hGrid->nTiles; + move16(); + + IF (isIndepFlag) + { + isSame = 0; + move16(); + } + ELSE + { + p = 0; + move16(); + tmp32 = 0; + move32(); + + WHILE ((LT_16(p, nTiles))&&(tmp32==0)) + { + test(); + tmp32 = L_sub(hPrivateData->igfCurrWhiteningLevel[p] , hPrivateData->igfPrevWhiteningLevel[p]); + if (tmp32 != 0) + { + isSame = 0; + move16(); + } + p++; + } + } + IF (isSame) + { + IGF_write_bits(st, pBitOffset, 1, 1); + } + ELSE + { + IF (!isIndepFlag) + { + IGF_write_bits(st, pBitOffset, 0, 1); + } + IGF_WriteWhiteningTile(st, pBitOffset, hPrivateData->igfCurrWhiteningLevel[0]); + p = 1; + move16(); + tmp32 = 0; + move32(); + if (LT_16(p, nTiles)) + { + isSame = 1; + move16(); + } + + WHILE ((LT_16(p, nTiles))&&(tmp32==0)) + { + test(); + tmp32 = L_sub(hPrivateData->igfCurrWhiteningLevel[p] , hPrivateData->igfCurrWhiteningLevel[p - 1]); + if (tmp32 != 0) + { + isSame = 0; + move16(); + } + p++; + } + + IF (!isSame) + { + IGF_write_bits(st, pBitOffset, 1, 1); + FOR (p = 1; p < nTiles; p++) + { + IGF_WriteWhiteningTile(st, pBitOffset, hPrivateData->igfCurrWhiteningLevel[p]); + } + } + ELSE + { + IGF_write_bits(st, pBitOffset, 0, 1); + } + } + +} + +/**********************************************************************/ /* +write flattening trigger +**************************************************************************/ +static void IGF_WriteFlatteningTrigger( /**< out: | number of bits written */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + Encoder_State_fx *st, /**< in: | encoder state */ + Word16 *pBitOffset /**< in: | ptr to bitOffset counter */ +) +{ + Word16 flatteningTrigger; + + + flatteningTrigger = hInstance->flatteningTrigger; + move16(); + + IGF_write_bits(st, pBitOffset, flatteningTrigger, 1); + +} + +/**********************************************************************/ /* +updates the start/stop frequency of IGF according to igfGridIdx +**************************************************************************/ +static void IGF_UpdateInfo(const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + const Word16 igfGridIdx /**< in: Q0 | IGF grid index */ + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + + + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + hInstance->infoStartFrequency = hGrid->startFrequency; + move16(); + hInstance->infoStopFrequency = hGrid->stopFrequency; + move16(); + hInstance->infoStartLine = hGrid->startLine; + move16(); + hInstance->infoStopLine = hGrid->stopLine; + move16(); + + return; +} + +/**********************************************************************/ /* +IGF bitsream writer +**************************************************************************/ +Word16 IGFEncWriteBitstream( /**< out: | number of bits written per frame */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + Encoder_State_fx *st, /**< in: | encoder state */ + Word16 *pBitOffset, /**< in: | ptr to bitOffset counter */ + const Word16 igfGridIdx, /**< in: Q0 | igf grid index see declaration of IGF_GRID_IDX for details */ + const Word16 isIndepFlag /**< in: Q0 | if 1 frame is independent, 0 = frame is coded with data from previous frame */ +) +{ + Word16 igfAllZero; + Word16 startBitCount; + + + startBitCount = *pBitOffset; + move16(); + hInstance->infoTotalBitsPerFrameWritten = 0; + move16(); + + if (isIndepFlag) + { + hInstance->infoTotalBitsWritten = 0; + move16(); + } + + IGF_WriteEnvelope(hInstance, /* i: instance handle of IGF Encoder */ + st, /* i: encoder state */ + pBitOffset, /* i: ptr to bitOffset counter */ + igfGridIdx, /* i: igf grid index see definition of IGF_GRID_IDX for details */ + isIndepFlag, /* i: if 1 frame is independent, 0 = frame is coded with data from previous frame */ + &igfAllZero); /* o: *igfAllZero */ + + IGF_WriteWhiteningLevels(hInstance, /* i: instance handle of IGF Encoder */ + st, /* i: encoder state */ + pBitOffset, /* i: ptr to bitOffset counter */ + igfGridIdx, /* i: igf grid index see definition of IGF_GRID_IDX for details */ + isIndepFlag); /* i: if 1 frame is independent, 0 = frame is coded with data from previous frame */ + + IGF_WriteFlatteningTrigger(hInstance, /* i: instance handle of IGF Encoder */ + st, /* i: encoder state */ + pBitOffset); /* i: ptr to bitOffset counter */ + + hInstance->infoTotalBitsPerFrameWritten = sub(*pBitOffset, startBitCount); + hInstance->infoTotalBitsWritten = add(hInstance->infoTotalBitsWritten, hInstance->infoTotalBitsPerFrameWritten); + + return hInstance->infoTotalBitsPerFrameWritten; +} + +/**********************************************************************/ /* +sets the IGF mode according to given bitrate +**************************************************************************/ +void IGFEncSetMode(const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + const Word32 bitRate, /**< in: Q0 | encoder bitrate */ + const Word16 mode /**< in: Q0 | encoder bandwidth mode */ + ,const Word16 rf_mode /**< in: Q0 | flag to signal the RF mode */ + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + Word16 i; + + hPrivateData = &hInstance->igfData; + hPrivateData->igfBitstreamBits = 0; + move16(); + set16_fx(hPrivateData->igfScfQuantized, 0, IGF_MAX_SFB); + set16_fx(hPrivateData->igfCurrWhiteningLevel, 0, IGF_MAX_TILES); + set16_fx(hPrivateData->igfPrevWhiteningLevel, 0, IGF_MAX_TILES); + FOR( i = 0; i < BITBUFSIZE/8; i++) + { + hPrivateData->igfBitstream[i] = 0; + move16(); + } + hPrivateData->wasTransient = 0; + move16(); + set32_fx(hPrivateData->prevSFM_FIR, 0, IGF_MAX_TILES); + set16_fx(hPrivateData->prevSFM_IIR, 0, IGF_MAX_TILES); + + IF (IGFCommonFuncsIGFConfiguration(bitRate, mode, &hPrivateData->igfInfo,rf_mode) != 0) + { + IGFSCFEncoderOpen(&hPrivateData->hIGFSCFArithEnc, + sub(hPrivateData->igfInfo.grid[0].stopSfb, hPrivateData->igfInfo.grid[0].startSfb), + bitRate, + mode + ,rf_mode + + ); + + hInstance->infoSamplingRate = hPrivateData->igfInfo.sampleRate; + move32(); + hInstance->infoStartFrequency = hPrivateData->igfInfo.grid[0].startFrequency; + move16(); + hInstance->infoStopFrequency = hPrivateData->igfInfo.grid[0].stopFrequency; + move16(); + hInstance->infoStartLine = hPrivateData->igfInfo.grid[0].startLine; + move16(); + hInstance->infoStopLine = hPrivateData->igfInfo.grid[0].stopLine; + move16(); + } + ELSE + { + /* IGF configuration failed -> error! */ + hInstance->infoSamplingRate = 0; + move32(); + hInstance->infoStartFrequency = -1; + move16(); + hInstance->infoStopFrequency = -1; + move16(); + hInstance->infoStartLine = -1; + move16(); + hInstance->infoStopLine = -1; + move16(); + fprintf(stderr,"IGFEncSetMode: initialization error!\n"); + } + + /* reset remaining variables */ + hInstance->infoTotalBitsWritten = 0; + move16(); + hInstance->infoTotalBitsPerFrameWritten = 0; + move16(); + hInstance->flatteningTrigger = 0; + move16(); + hInstance->spec_be_igf_e = 0; + move16(); + hInstance->tns_predictionGain = 0; + move16(); + set32_fx(hInstance->spec_be_igf, 0, N_MAX_TCX-IGF_START_MN); + return; +} + +/**********************************************************************/ /* +IGF bitsream concatenation for TCX10 modes +**************************************************************************/ +void IGFEncConcatenateBitstream(const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + Word16 bsBits, /**< in: Q0 | number of IGF bits written to list of indices */ + Word16 *next_ind, /**< in/out: | pointer to actual bit indice */ + Word16 *nb_bits, /**< in/out: | total number of bits already written */ + Indice_fx *ind_list_fx /**< in: | pointer to list of indices */ + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + + hPrivateData = &hInstance->igfData; + *next_ind = *next_ind - bsBits; + + indices_to_serial_generic( + &ind_list_fx[*next_ind], + bsBits, + hPrivateData->igfBitstream, + &hPrivateData->igfBitstreamBits + ); + + *nb_bits = sub(*nb_bits, bsBits); + + return; +} + +/**********************************************************************/ /* +IGF reset bitsream bit counter for TCX10 modes +**************************************************************************/ +void IGFEncResetTCX10BitCounter(const IGF_ENC_INSTANCE_HANDLE hInstance /**< in: | instance handle of IGF Encoder */ + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + + hPrivateData = &hInstance->igfData; + hPrivateData->igfBitstreamBits = 0; + move16(); + hInstance->infoTotalBitsWritten = 0; + move16(); + + return; +} + +/**********************************************************************/ /* +IGF write concatenated bitsream for TCX10 modes +**************************************************************************/ +Word16 IGFEncWriteConcatenatedBitstream( /**< out: Q0 | total number of bits written */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + void *st /**< in: | encoder state */ +) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + Word16 i; + Word16 tmp; + Word16 bitsLeft; + UWord8 *pBitstream; + + hPrivateData = &hInstance->igfData; + pBitstream = &hPrivateData->igfBitstream[0]; + + tmp = shr(hPrivateData->igfBitstreamBits, 3); + FOR (i = 0; i < tmp; i++) + { + push_next_indice_fx(st, pBitstream[i], 8); + } + + bitsLeft = s_and(hPrivateData->igfBitstreamBits, 0x7); + IF(bitsLeft > 0) + { + push_next_indice_fx(st, shr(pBitstream[i], sub(8, bitsLeft)), bitsLeft); + } + + return hInstance->infoTotalBitsWritten; +} + +/**********************************************************************/ /* +apply the IGF encoder, main encoder interface +**************************************************************************/ +void IGFEncApplyMono(const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + const Word16 igfGridIdx, /**< in: Q0 | IGF grid index */ + Encoder_State_fx *st, /**< in: | Encoder state */ + Word32 *pMDCTSpectrum, /**< in: Q31 | MDCT spectrum */ + Word16 MDCTSpectrum_e, /**< in: | exponent of MDCT spectrum */ + Word32 *pPowerSpectrum, /**< in: Q31 | MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 PowerSpectrum_e, /**< in: | exponent of pPowerSpectrum */ + Word16 isTCX20, /**< in: Q0 | flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + Word16 isTNSActive, /**< in: Q0 | flag indicating if the TNS is active */ + Word16 last_core_acelp /**< in: Q0 | indicator if last frame was acelp coded */ + ) +{ + Word32 *pPowerSpectrumParameter; /* If it is NULL it informs a function that specific handling is needed */ + Word32 *pPowerSpectrumParameterWhitening; /* If it is NULL it informs a function that specific handling is needed */ + Word16 highPassEner_exp; /*exponent of highpass energy - maybe not needed*/ + + + pPowerSpectrumParameter = NULL; + test(); + if ((isTNSActive == 0) && (isTCX20 != 0)) + { + pPowerSpectrumParameter = pPowerSpectrum; + } + pPowerSpectrumParameterWhitening = NULL; + if (isTCX20 != 0) + { + pPowerSpectrumParameterWhitening = pPowerSpectrum; + } + + IGF_UpdateInfo(hInstance, /* i: instance handle of IGF Encoder */ + igfGridIdx); /* i: IGF grid index */ + + IGF_CalculateEnvelope(hInstance, /* i: instance handle of IGF Encoder */ + pMDCTSpectrum, /* i: MDCT spectrum */ + MDCTSpectrum_e, /* i: exponent of MDCT spectrum */ + pPowerSpectrumParameter, /* i: MDCT^2 + MDST^2 spectrum, or estimate */ + PowerSpectrum_e, /* i: exponent of pPowerSpectrum */ + igfGridIdx /* i: IGF grid index */ + ); + + + IGF_Whitening(hInstance, /* i: instance handle of IGF Encoder */ + pPowerSpectrumParameterWhitening, /* i: MDCT^2 + MDST^2 spectrum, or estimate */ + PowerSpectrum_e, /* i: exponent of powerSpectrum */ + igfGridIdx, /* i: IGF grid index */ + (st->transientDetection.transientDetector.bIsAttackPresent == 1), + last_core_acelp); /* i: last frame was acelp indicator */ + + pPowerSpectrumParameter = NULL; + if (isTCX20 != 0) + { + pPowerSpectrumParameter = pPowerSpectrum; + } + + IGF_ErodeSpectrum( /* o: highpass energy */ + &highPassEner_exp, /* o: exponent of highPassEner */ + hInstance, /* i: instance handle of IGF Encoder */ + pMDCTSpectrum, /* i: MDCT spectrum */ + pPowerSpectrumParameter, /* i: MDCT^2 + MDST^2 spectrum, or estimate */ + PowerSpectrum_e, /* i: exponent of pPowerSpectrum */ + igfGridIdx); /* i: IGF grid index */ + +} + diff --git a/lib_enc/igf_scf_enc.c b/lib_enc/igf_scf_enc.c new file mode 100644 index 0000000..bce80fe --- /dev/null +++ b/lib_enc/igf_scf_enc.c @@ -0,0 +1,430 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "options.h" +#include "stl.h" +#include "prot_fx.h" +#include "stat_enc_fx.h" +#include "stat_com.h" +#include "cnst_fx.h" +#include "basop_util.h" + + +/**********************************************************************/ /** +initialization of an instance of this module +**************************************************************************/ +void IGFSCFEncoderOpen( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /* i/o: handle to public data */ + Word16 scfCountLongBlock, /* i: number of SCFs for a long block */ + Word32 bitRate, /* i: bitrate in bps */ + Word16 mode /* i: operating mode */ + , Word16 rf_mode /**< in: flag to signal the RF mode */ +) +{ + + + hPublicData->ptrBitIndex = 0; + move16(); + hPublicData->bitCount = 0; + move16(); + hPublicData->tSave = 0; + move16(); + hPublicData->context_saved = 0; + move16(); + hPublicData->acState.low = 0; + move32(); + hPublicData->acState.high = 0; + move32(); + hPublicData->acState.vobf = 0; + move16(); + set16_fx(hPublicData->prev, 0, 64); + set16_fx(hPublicData->prevSave, 0, 64); + + hPublicData->scfCountLongBlock = scfCountLongBlock; + move16(); + hPublicData->t = 0; + move16(); /* protect against the invalid request of starting encoding with a dependent block */ + + IGFCommonFuncsIGFGetCFTables( + bitRate, + mode, + rf_mode, + &hPublicData->cf_se00, + &hPublicData->cf_se01, + &hPublicData->cf_off_se01, + &hPublicData->cf_se02, + &hPublicData->cf_off_se02, + &hPublicData->cf_se10, + &hPublicData->cf_off_se10, + &hPublicData->cf_se11, + &hPublicData->cf_off_se11 + ); + +} + + +static Word16 quant_ctx( + Word16 ctx /* i: the context value to be quantized */ +) +{ + /* + ctx ... -5 -4 -3 -2 -1 0 1 2 3 4 5 ... + Q(ctx)... -3 -3 -3 -2 -1 0 1 2 3 3 3 ... + */ + Word16 result; + + + result = s_min(abs_s(ctx), IGF_CTX_OFFSET); /* limit the absolute value to IGF_CTX_OFFSET */ + if (ctx < 0) /* add the sign back, if needed */ + { + result = negate(result); + } + + return result; +} + + + +static void arith_encode_bits( + IGFSCFENC_INSTANCE_HANDLE hPrivateData, /* i/o: instance handle */ + Word16 *ptr, /* i/o: pointer to expanded bit buffer, one bit in each Word16 */ + Word16 x, /* i: value to encode */ + Word16 nBits /* i: number of bits to encode */ +) +{ + Word16 i; + Word16 bit; + + + FOR (i = nBits - 1; i >= 0; --i) /* nBits > 0 */ + { + bit = s_and(shr(x, i), 1); + hPrivateData->ptrBitIndex = ari_encode_14bits_sign(ptr, + hPrivateData->ptrBitIndex, + 32767, /* disable the bit count limitation */ + &hPrivateData->acState, + bit + ); + } + +} + +static void arith_encode_residual( + IGFSCFENC_INSTANCE_HANDLE hPrivateData, /* i/o: instance handle */ + Word16 *ptr, /* i/o: pointer to expanded bit buffer, one bit in each Word16 */ + Word16 x, /* i: residual value to encode */ + const Word16 *cumulativeFrequencyTable, /* i: cumulative frequency table to be used */ + Word16 tableOffset /* i: offset used to align the table */ +) +{ + Word16 extra; + Word16 extra_tmp; + Word16 extra_safety; + + + x = add(x, tableOffset); + + test(); + IF ((GE_16(x, IGF_MIN_ENC_SEPARATE))&&(LE_16(x,IGF_MAX_ENC_SEPARATE))) + { + x = sub(x, IGF_MIN_ENC_SEPARATE - 1); /* (x - IGF_MIN_ENC_SEPARATE) + 1 */ + /* encode one of the IGF_SYMBOLS_IN_TABLE == 27 alphabet symbols using the new raw AC function */ + hPrivateData->ptrBitIndex = ari_encode_14bits_ext(ptr, + hPrivateData->ptrBitIndex, + &hPrivateData->acState, + x, + (const UWord16*) cumulativeFrequencyTable + ); + + return; + } + + IF (LT_16(x, IGF_MIN_ENC_SEPARATE)) + { + /* send escape code 0 to indicate x <= IGF_MIN_ENC_SEPARATE - 1 */ + extra = sub(IGF_MIN_ENC_SEPARATE - 1, x); + hPrivateData->ptrBitIndex = ari_encode_14bits_ext(ptr, + hPrivateData->ptrBitIndex, + &hPrivateData->acState, + 0, + (const UWord16*) cumulativeFrequencyTable + ); + } + ELSE /* x > IGF_MAX_ENC_SEPARATE */ + { + /* send escape code (IGF_SYMBOLS_IN_TABLE - 1) to indicate x >= IGF_MAX_ENC_SEPARATE + 1 */ + extra = sub(x, IGF_MAX_ENC_SEPARATE + 1); + hPrivateData->ptrBitIndex = ari_encode_14bits_ext(ptr, + hPrivateData->ptrBitIndex, + &hPrivateData->acState, + IGF_SYMBOLS_IN_TABLE - 1, + (const UWord16*) cumulativeFrequencyTable + ); + } + + /* encode one of the tails of the distribution */ + extra_tmp = sub(extra, 15); + IF (extra_tmp < 0) + { + /* encode extra with 4 bits if extra < 15 */ + arith_encode_bits(hPrivateData, ptr, extra, 4); + } + ELSE /* extra >= 15 */ + { + /* send escape code 15 to indicate extra >= 15 */ + arith_encode_bits(hPrivateData, ptr, 15, 4); + + extra_safety = sub(extra_tmp, 63); + IF (extra_safety < 0) + { + /* encode additional extra with 6 bits */ + arith_encode_bits(hPrivateData, ptr, extra_tmp, 6); + } + ELSE { /* extra_tmp >= 63 */ + /* encode safety extra with 7 bits */ + arith_encode_bits(hPrivateData, ptr, extra_safety, 7); + } + } + +} + + +static void encode_sfe_vector( + IGFSCFENC_INSTANCE_HANDLE hPrivateData, /* i/o: instance handle */ + Word16 *ptr, /* i/o: pointer to expanded bit buffer, one bit in each Word16 */ + Word16 t, /* i: counter reset to 0 at each independent block */ + Word16 *prev_x, /* i: previous vector */ + Word16 *x, /* i: current vector to encode */ + Word16 length /* i: number of elements to encode */ +) +{ + /* + f + ^ + | d a x + | c b + | e --> t + */ + Word16 f; + Word16 pred; + Word16 res; + Word16 ctx; + Word16 ctx_f; + Word16 ctx_t; + Word16 prev_offset; + Word32 index1; + Word32 index2; + + + + FOR (f = 0; f < length; ++f) + { + IF (t == 0) + { + IF (f == 0) + { + /* (t == 0) && (f == 0) */ + /* encode one of the IGF_SYMBOLS_IN_TABLE == 27 alphabet symbols using the new raw AC function */ + hPrivateData->ptrBitIndex = ari_encode_14bits_ext(ptr, + hPrivateData->ptrBitIndex, + &hPrivateData->acState, + shr(x[f], 2), + (const UWord16*) hPrivateData->cf_se00 + ); + arith_encode_bits(hPrivateData, ptr, s_and(x[f], 3), 2); /* LSBs as 2 bit raw */ + } + ELSE IF (EQ_16(f, 1)) + { + /* (t == 0) && (f == 1) */ + res = sub(x[f], x[0]); /* pred = b */ + arith_encode_residual(hPrivateData, + ptr, + res, + hPrivateData->cf_se01, + hPrivateData->cf_off_se01); + } + ELSE + { + /* (t == 0) && (f >= 2) */ + prev_offset = sub(f, 1); + res = sub(x[f], x[prev_offset]); + move16(); /* pred = b */ + ctx = quant_ctx(sub(x[prev_offset], x[sub(prev_offset, 1)])); /* Q(b - e) */ + /* index1 is (IGF_SYMBOLS_IN_TABLE + 1) * (CTX_OFFSET + ctx) */ + index1 = L_mac0((IGF_SYMBOLS_IN_TABLE + 1) * IGF_CTX_OFFSET, (IGF_SYMBOLS_IN_TABLE + 1), ctx); + /* index2 is IGF_CTX_OFFSET + ctx */ + index2 = L_mac0(IGF_CTX_OFFSET, 1, ctx); + arith_encode_residual(hPrivateData, + ptr, + res, + hPrivateData->cf_se02 + index1, + hPrivateData->cf_off_se02[index2]); + } + } + ELSE + { + /* t == 1 */ + IF (f == 0) + { + /* (t == 1) && (f == 0) */ + res = sub(x[f], prev_x[f]); + move16(); /* pred = a */ + arith_encode_residual(hPrivateData, + ptr, + res, + hPrivateData->cf_se10, + hPrivateData->cf_off_se10); + } + ELSE + { + /* (t == 1) && (f >= 1) */ + prev_offset = sub(f, 1); + pred = add(prev_x[f], x[prev_offset]); + pred = sub(pred, prev_x[prev_offset]); /* pred = a + b - c */ + res = sub(x[f], pred); + ctx_f = quant_ctx(sub(prev_x[f], prev_x[prev_offset])); /* Q(a - c) */ + ctx_t = quant_ctx(sub(x[prev_offset], prev_x[prev_offset])); /* Q(b - c) */ + /* index1 is (IGF_SYMBOLS_IN_TABLE + 1) * IGF_CTX_COUNT * (IGF_CTX_OFFSET + ctx_t) + + (IGF_SYMBOLS_IN_TABLE + 1) * (IGF_CTX_OFFSET + ctx_f) */ + index1 = L_mac0( + ((IGF_SYMBOLS_IN_TABLE + 1) * IGF_CTX_COUNT + (IGF_SYMBOLS_IN_TABLE + 1)) * IGF_CTX_OFFSET, + (IGF_SYMBOLS_IN_TABLE + 1) * IGF_CTX_COUNT, ctx_t); + index1 = L_mac0(index1, (IGF_SYMBOLS_IN_TABLE + 1), ctx_f); + /* index2 is IGF_CTX_COUNT * (IGF_CTX_OFFSET + ctx_t) + (IGF_CTX_OFFSET + ctx_f) */ + index2 = L_mac0((IGF_CTX_COUNT + 1) * IGF_CTX_OFFSET, IGF_CTX_COUNT, ctx_t); + index2 = L_mac0(index2, 1, ctx_f); + arith_encode_residual(hPrivateData, + ptr, + res, + hPrivateData->cf_se11 + index1, + hPrivateData->cf_off_se11[index2]); + } + } + } + +} + + +/**********************************************************************/ /** +resets the internal encoder memory (context memory) +**************************************************************************/ +void IGFSCFEncoderReset( + IGFSCFENC_INSTANCE_HANDLE hPublicData /* i/o: handle to public data */ +) +{ + + + /* reset of coder */ + hPublicData->t = 0; + move16(); /* indicate that an independent block follows */ + /* we do not need to fill hPublicData->prev with zeros, because when t = 0 no previous information is used */ + +} + +/**********************************************************************/ /** +main encoder function +**************************************************************************/ +Word16 IGFSCFEncoderEncode( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /* i/o: handle to public data */ + Encoder_State_fx *st, /* i/o: pointer to encoder state */ + Word16 bitCount, /* i: offset to the first bit in bitbuffer which should be written by the raw AC functions */ + Word16 *sfe, /* i: pointer to an array which contains the quantized SCF energies to be encoded */ + Word16 indepFlag, /* i: 1 if the block is an independent block, 0 otherwise */ + Word16 doRealEncoding /* i: whether the real encoding is needed, otherwise only the number of bits is used */ +) +{ + Word16 ptr[BITBUFSIZE]; /* temporary expanded bit buffer, one bit in each Word16 */ + Word16 i; + + + + /* insert data: */ + hPublicData->ptrBitIndex = 0; + move16(); + hPublicData->bitCount = bitCount; + move16(); + ari_start_encoding_14bits(&hPublicData->acState); /* start AC encoding */ + + /* check if coder needs a reset and do it if necessary */ + IF (indepFlag != 0) + { + /* reset of coder */ + IGFSCFEncoderReset(hPublicData); + } + + encode_sfe_vector(hPublicData, + ptr, + hPublicData->t, + hPublicData->prev, + sfe, + hPublicData->scfCountLongBlock + ); + + hPublicData->ptrBitIndex = ari_done_encoding_14bits(ptr, + hPublicData->ptrBitIndex, + &hPublicData->acState + ); /* finish AC encoding */ + hPublicData->bitCount = add(hPublicData->bitCount, hPublicData->ptrBitIndex); + + + /* advance history */ + Copy(sfe, hPublicData->prev, hPublicData->scfCountLongBlock); + hPublicData->t = add(hPublicData->t, 1); + + + /* copy the bits from the temporary bit buffer, if doRealEncoding is enabled */ + IF (doRealEncoding != 0) + { + FOR (i = 0; i < hPublicData->ptrBitIndex; ++i) + { + push_next_indice_fx(st, ptr[i], 1); + } + } + + /* return next bit offset in the stream */ + return hPublicData->bitCount; +} + +/**********************************************************************/ /** +for a closed loop encoder, the SCF encoder needs to memorize the context +**************************************************************************/ +void IGFSCFEncoderSaveContextState( + IGFSCFENC_INSTANCE_HANDLE hPublicData /* i/o: handle to public data */ +) +{ + + + hPublicData->tSave = hPublicData->t; + move16(); + + Copy(hPublicData->prev, + hPublicData->prevSave, + hPublicData->scfCountLongBlock + ); + + +} + +/**********************************************************************/ /** +for a closed loop encoder, the SCF encoder needs to memorize the context +**************************************************************************/ +void IGFSCFEncoderRestoreContextState( + IGFSCFENC_INSTANCE_HANDLE hPublicData /* i/o: handle to public data */ +) +{ + + + hPublicData->t = hPublicData->tSave; + move16(); + + Copy(hPublicData->prevSave, + hPublicData->prev, + hPublicData->scfCountLongBlock + ); + + +} diff --git a/lib_enc/init_enc_fx.c b/lib_enc/init_enc_fx.c new file mode 100644 index 0000000..a3f071e --- /dev/null +++ b/lib_enc/init_enc_fx.c @@ -0,0 +1,1008 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + + +/*-----------------------------------------------------------------------* + * init_encoder_fx() + * + * Initialization of state variables + *-----------------------------------------------------------------------*/ +void init_encoder_fx( + Encoder_State_fx *st_fx /* i/o: Encoder static variables structure */ +) +{ + Word16 i; + Word32 L_tmp; + + st_fx->nb_bits_tot_fx = 0; + move16(); + /*-----------------------------------------------------------------* + * ACELP core parameters + *-----------------------------------------------------------------*/ + st_fx->last_core_fx = -1; + move16(); + if ( st_fx->Opt_AMR_WB_fx ) + { + st_fx->last_core_fx = AMR_WB_CORE; + move16(); + } + + st_fx->L_frame_fx = L_FRAME; + move16(); + st_fx->last_coder_type_fx = GENERIC; + move16(); + st_fx->last_7k2_coder_type_fx = GENERIC; + move16(); + st_fx->last_total_brate_fx = st_fx->total_brate_fx; + move32(); + st_fx->last_total_brate_cng_fx = -1; + move32(); + st_fx->last_core_brate_fx = st_fx->total_brate_fx; + move32(); + st_fx->extl_fx = -1; + move16(); + st_fx->last_extl_fx = -1; + move16(); + st_fx->last_L_frame_fx = L_FRAME; + move16(); + st_fx->rate_switching_reset = 0; + move16(); + st_fx->rate_switching_reset_16kHz = 0; + move16(); + Copy( GEWB_Ave_fx, st_fx->mem_AR_fx, M ); + Copy( GEWB_Ave_fx, st_fx->lsfoldbfi0_fx, M ); + Copy( GEWB_Ave_fx, st_fx->lsfoldbfi1_fx, M ); + Copy( GEWB_Ave_fx, st_fx->lsf_adaptive_mean_fx, M ); + init_lvq_fx( st_fx->offset_scale1_fx, st_fx->offset_scale2_fx, st_fx->offset_scale1_p_fx, st_fx->offset_scale2_p_fx, st_fx->no_scales_fx, st_fx->no_scales_p_fx ); + st_fx->next_force_safety_net_fx = 0; + + st_fx->pstreaklen_fx = 0; + move16(); + st_fx->streaklimit_fx = 32767; + move16(); /*1;//Q15 */ + set16_fx( st_fx->mem_MA_fx, 0, M ); + + init_gp_clip_fx( st_fx->clip_var_fx ); + pitch_ol_init_fx( &st_fx->old_thres_fx, &st_fx->old_pitch, &st_fx->delta_pit_fx, &st_fx->old_corr_fx ) ; + + hf_cod_init_fx( st_fx->mem_hp400_enc_fx, st_fx->mem_hf_enc_fx, st_fx->mem_syn_hf_enc_fx, st_fx->mem_hf2_enc_fx, &st_fx->gain_alpha_fx ); + + st_fx->LPDmem.tilt_code = 0; + move16(); + st_fx->LPDmem.gc_threshold = 0; + move16(); + + st_fx->clas_fx = UNVOICED_CLAS; + move16(); + set16_fx( st_fx->old_inp_12k8_fx, 0, L_INP_MEM); /* memory of input signal at 12.8kHz */ + set16_fx( st_fx->old_wsp_fx, 0, L_WSP_MEM ); + set16_fx( st_fx->LPDmem.old_exc, 0, L_EXC_MEM ); + set16_fx( st_fx->old_wsp2_fx, 0, (L_WSP_MEM - L_INTERPOL)/OPL_DECIM ); + set16_fx( st_fx->old_inp_16k_fx, 0, L_INP_MEM ); + + st_fx->mem_deemph_fx = 0; + move16(); + st_fx->mem_preemph_fx = 0; + move16(); + st_fx->mem_preemph16k_fx = 0; + move16(); + st_fx->mem_preemph_enc = 0; + move16(); + + /* AVQ pre-quantizer memory */ + st_fx->mem_preemp_preQ_fx = 0; + move16(); + st_fx->mem_deemp_preQ_fx = 0; + move16(); + st_fx->last_nq_preQ_fx = 0; + move16(); + st_fx->use_acelp_preq = 0; + move16(); + + /* (Decimated) Weighted Speech Memory */ + st_fx->mem_wsp_enc = 0; + move16(); + + set16_fx( st_fx->mem_decim16k_fx, 0, 2*L_FILT_MAX ); + st_fx->mem_wsp_fx = 0; + move16(); + st_fx->LPDmem.mem_w0 = 0; + move16(); + set16_fx( st_fx->LPDmem.mem_syn, 0, M ); + set16_fx( st_fx->mem_syn1_fx, 0, M ); + st_fx->mem_deemph_old_syn_fx = 0; + move16(); + set16_fx( st_fx->LPDmem.mem_syn2, 0, M ); + set16_fx( st_fx->mem_decim_fx, 0, 2*L_FILT_MAX ); + set16_fx( st_fx->mem_decim2_fx, 0, 3 ); + set32_fx( st_fx->Bin_E_fx, 0, L_FFT ); + set16_fx( st_fx->lgBin_E_fx, 0, L_FFT/2 ); + set32_fx( st_fx->Bin_E_old_fx, 0, L_FFT/2 ); + set16_fx( st_fx->LPDmem.mem_syn3, 0, M ); + + st_fx->ini_frame_fx = 0; + move16(); + st_fx->ee_old_fx = 640; + move32();/*chk //10 in Q6 */ + st_fx->Nb_ACELP_frames_fx = 0; + move16(); + st_fx->audio_frame_cnt_fx = AUDIO_COUNTER_INI; + move16();/* Initializatin of the audio frame counter mildly into the audio mode */ + + /* adaptive lag window memory */ + st_fx->old_pitch_la = 0; + move16(); + st_fx->old_voicing_la = 0; + move16(); + set32_fx( st_fx->mem_hp20_in_fx, 0, 5 ); + + st_fx->Last_Resort_fx = 0; + st_fx->set_ppp_generic_fx = 0; + + st_fx->dm_fx.prev_state = 0; + move16(); /* This corresponds to st_fx->dispMem in FLP */ + st_fx->dm_fx.prev_gain_code = 0; + move32(); + + FOR(i=2; i<8; i++) + { + st_fx->dm_fx.prev_gain_pit[i-2] = 0; + move16(); + } + + st_fx->seed2_enc_fx = RANDOM_INITSEED; + move16(); + + + st_fx->old_hpfilt_in_fx = 0; + move16(); + st_fx->old_hpfilt_out_fx = 0; + move16(); + st_fx->EnergyLT_fx = 0; + move32(); + st_fx->prev_Q_new = 0; + move16(); + + + FOR (i=0; ipast_qua_en_fx[i] = -14336; /* Q10gain quantization memory (used also in AMR-WB IO mode) */ + } + + IF( EQ_32(st_fx->input_Fs_fx,8000)) + { + st_fx->min_band_fx = 1; + move16(); + st_fx->max_band_fx = 16; + move16(); + } + ELSE + { + st_fx->min_band_fx = 0; + move16(); + st_fx->max_band_fx = 19; + move16(); + } + + FOR( i=0; ifr_bands1_fx[i] = 1; + move32();/*1e-5f; */ + st_fx->fr_bands2_fx[i] = 1; + move32();/*1e-5f; */ + st_fx->ave_enr2_fx[i] = E_MIN_FX; + move32(); /*Q7//E_MIN; */ + } + IF ( st_fx->Opt_AMR_WB_fx ) + { + Copy( mean_isf_amr_wb_fx, st_fx->lsf_old_fx, M ); + E_LPC_isf_isp_conversion( st_fx->lsf_old_fx, st_fx->lsp_old1_fx, M); + } + ELSE + { + Copy( GEWB_Ave_fx, st_fx->lsf_old_fx, M ); + lsf2lsp_fx( st_fx->lsf_old_fx, st_fx->lsp_old1_fx, M, INT_FS_FX); + } + + Copy( st_fx->lsf_old_fx, st_fx->lsf_old1_fx, M ); + Copy( st_fx->lsp_old1_fx, st_fx->lsp_old_fx, M ); + Copy( st_fx->lsp_old_fx, st_fx->lsp_old16k_fx, M ); + Copy( st_fx->lsp_old_fx, st_fx->lspold_enc_fx, M ); + + st_fx->stab_fac_fx = 0; + move16(); + + MDCT_selector_reset(st_fx); + + /* Bass post-filter memories - encoder side of MODE2 */ + st_fx->bpf_off_fx = 0; + move16(); + + /* TC mode */ + st_fx->tc_cnt_fx = 0; + move16(); + st_fx->mCb1_fx = 0; + move16(); + + /* AC mode */ + st_fx->seed_tcx_fx = 15687; + move16(); + st_fx->cor_strong_limit_fx = 1; + move16(); + set16_fx( st_fx->last_exc_dct_in_fx, 0, L_FRAME ); + st_fx->last_ener_fx = 0; + set16_fx( st_fx->last_bitallocation_band_fx, 0, 6 ); + + st_fx->mem_last_pit_band_fx = BAND1k2+1; + move16(); + + st_fx->old_dE1_fx = 0; + move16(); + st_fx->old_ind_deltaMax_fx = 0; + move32(); + set32_fx( st_fx->old_enr_ssf_fx, 0, 2*NB_SSF ); + st_fx->spike_hyst_fx = -1; + move16(); + st_fx->music_hysteresis_fx = 0; + move16(); /* Counter of frames after AUDIO frame to prevent UC */ + st_fx->last_harm_flag_acelp_fx = 0; + move16(); + st_fx->GSC_noisy_speech_fx = 0; + move16(); + + /* speech/music classifier */ + st_fx->inact_cnt_fx = 0; + move16(); + set16_fx(st_fx->past_dec_fx, 0, HANG_LEN-1 ); + set16_fx(st_fx->past_dlp_fx, 0, HANG_LEN-1 ); + set16_fx(st_fx->past_log_enr_fx, -1448, NB_BANDS_SPMUS); /* log(E_MIN) in Q8 */ + + st_fx->sp_mus_state_fx = -8; + move16(); + st_fx->wdrop_fx = 0; + move16(); + st_fx->wdlp_0_95_sp_fx = 0; + move16(); + set16_fx( st_fx->last_lsp_fx, 0, M_LSP_SPMUS ); + st_fx->last_cor_map_sum_fx = 0; + move16(); + st_fx->last_non_sta_fx = 0; + move16(); + set32_fx( st_fx->past_PS_fx, 0, HIGHEST_FBIN-LOWEST_FBIN ); + st_fx->past_ps_diff_fx = 0; + move16(); + st_fx->past_epsP2_fx = 1024; + move16(); + + + st_fx->gsc_thres_fx[0] = TH_0_MIN_FX; + move16(); + st_fx->gsc_thres_fx[1] = TH_1_MIN_FX; + move16(); + st_fx->gsc_thres_fx[2] = TH_2_MIN_FX; + move16(); + st_fx->gsc_thres_fx[3] = TH_3_MIN_FX; + move16(); + set16_fx(st_fx->gsc_lt_diff_etot_fx, 0, 40); + st_fx->gsc_mem_etot_fx = 0; + move16(); + st_fx->gsc_last_music_flag_fx = 0; + move16(); + st_fx->gsc_nb_thr_1_fx = 0; + move16(); + st_fx->gsc_nb_thr_3_fx = 0; + move16(); + st_fx->mold_corr_fx = 29491; + move16(); + st_fx->lt_gpitch_fx = 0; + move16(); + st_fx->mean_avr_dyn_fx = 64; + move16();/*Q7 */ + st_fx->last_sw_dyn_fx = 2560; + move16(); + st_fx->pit_exc_hangover = 0; + move16(); + st_fx->Last_pulse_pos_fx = 0; + move16(); + + /* speech/music classifier improvement */ + FOR ( i=0; ibuf_flux_fx[i] = -12800; + move16(); /*-100.0 in Q7 */ + st_fx->buf_pkh_fx[i] = 0; + move16(); + st_fx->buf_epsP_tilt_fx[i] = 0; + move16(); + st_fx->buf_cor_map_sum_fx[i] = 0; + move16(); + st_fx->buf_Ntonal_fx[i] = 0; + move16(); + st_fx->buf_Ntonal2_fx[i] = 0; + move16(); + st_fx->buf_Ntonal_lf_fx[i] = 0; + move16(); + } + + set16_fx(st_fx->lpe_buf_fx, 0, HANG_LEN_INIT); + set16_fx(st_fx->voicing_buf_fx, 0, HANG_LEN_INIT); + st_fx->gsc_hangover_fx = 0; + move16(); + set16_fx(st_fx->sparse_buf_fx, 0, HANG_LEN_INIT); + set16_fx(st_fx->hf_spar_buf_fx, 0, HANG_LEN_INIT); + st_fx->LT_sparse_fx = 0; + move16(); + st_fx->gsc_cnt_fx = 0; + move16(); + st_fx->last_vad_spa_fx = 0; + move16(); + + set16_fx( st_fx->old_Bin_E_fx, 0, 3*N_OLD_BIN_E ); + set16_fx( st_fx->buf_etot_fx, 0, 4 ); + set16_fx( st_fx->buf_dlp_fx, 0, 10 ); + + st_fx->UV_cnt1_fx = 300; + move16(); + st_fx->LT_UV_cnt1_fx = 16000; + move16(); /*250.0f in Q6 */ + st_fx->onset_cnt_fx = 0; + move16(); + st_fx->attack_hangover_fx = 0; + move16(); + st_fx->dec_mov_fx = 0; + move16(); + st_fx->dec_mov1_fx = 0; + move16(); + st_fx->mov_log_max_spl_fx = 25600; + move16(); /*200.0 in Q7 */ + st_fx->old_lt_diff_fx[0] = 0; + move16(); + st_fx->old_lt_diff_fx[1] = 0; + move16(); + + /* GSC - pitch excitation parameters */ + st_fx->mem_w0_tmp_fx = 0; + move16(); + set16_fx(st_fx->mem_syn_tmp_fx, 0, M); + st_fx->high_stable_cor_fx = 0; + move16(); + set16_fx(st_fx->var_cor_t_fx, 0, VAR_COR_LEN); + + st_fx->lps_fx = 0; + move16(); + st_fx->lpm_fx = 0; + move16(); + st_fx->Last_frame_ener_fx = MAX_32; + move32(); + st_fx->lt_dec_thres_fx = 5120; + move16(); /*10 in Q9 */ + st_fx->ener_RAT_fx = 0; + move16(); + st_fx->mid_dyn_fx = 5120; + move16(); /*40 -> Q7 */ + st_fx->noise_lev_fx = NOISE_LEVEL_SP0; + move16(); + st_fx->past_dyn_dec_fx = 0; + move16(); + + wb_vad_init_fx( &st_fx->nb_active_frames_fx, &st_fx->hangover_cnt_fx, &st_fx->lp_speech_fx, &st_fx->nb_active_frames_he_fx, + &st_fx->hangover_cnt_he_fx, &st_fx->bcg_flux_fx, &st_fx->soft_hangover_fx, &st_fx->voiced_burst_fx, + &st_fx->bcg_flux_init_fx, &st_fx->nb_active_frames_he1_fx, &st_fx->hangover_cnt_he1_fx, + &st_fx->L_vad_flag_reg_H_fx, &st_fx->L_vad_flag_reg_L_fx, &st_fx->L_vad_prim_reg_fx, &st_fx->vad_flag_cnt_50_fx, + &st_fx->vad_prim_cnt_16_fx, &st_fx->hangover_cnt_dtx_fx, &st_fx->hangover_cnt_music_fx ); + st_fx->Pos_relE_cnt = 5120; move16(); /*20.0f*/ + st_fx->nb_active_frames_HE_SAD_fx = 0; + move16(); + /* avoid uninitialized memory access */ + noise_est_init_fx( &st_fx->totalNoise_fx, &st_fx->first_noise_updt_fx, st_fx->bckr_fx, st_fx->enrO_fx, + st_fx->ave_enr_fx, &st_fx->pitO_fx, &st_fx->aEn_fx, &st_fx->harm_cor_cnt_fx,&st_fx->bg_cnt_fx, + &st_fx->lt_tn_track_fx, &st_fx->lt_tn_dist_fx, &st_fx->lt_Ellp_dist_fx, + &st_fx->lt_haco_ev_fx, &st_fx->low_tn_track_cnt_fx + ,&st_fx->Etot_st_est_fx,&st_fx->Etot_sq_st_est_fx + ); + + st_fx->epsP_0_2_lp_fx = 4096; /*1.0 Q12*/ move16(); + st_fx->epsP_0_2_ad_lp_fx = 0; + move16(); + st_fx->epsP_2_16_lp_fx = 4096; + move16(); + st_fx->epsP_2_16_lp2_fx = 4096; + move16(); + st_fx->epsP_2_16_dlp_lp2_fx = 0; + move16(); + st_fx->lt_aEn_zero_fx = 0; + move16(); + + + + + st_fx->prim_act_quick_fx=0; + move16(); + st_fx->prim_act_slow_fx=0; + move16(); + st_fx->prim_act_fx=0; + move16(); + st_fx->prim_act_quick_he_fx=0; + move16(); + st_fx->prim_act_slow_he_fx=0; + move16(); + st_fx->prim_act_he_fx=0; + move16(); + st_fx->bckr_tilt_lt=0; + move32(); + + /* WB, SWB and FB bandwidth detector */ + st_fx->lt_mean_NB_fx = 0; + move16(); + st_fx->lt_mean_WB_fx = 0; + move16(); + st_fx->lt_mean_SWB_fx = 0; + move16(); + st_fx->count_WB_fx = BWD_COUNT_MAX; + move16(); + st_fx->count_SWB_fx = BWD_COUNT_MAX; + move16(); + st_fx->count_FB_fx = BWD_COUNT_MAX; + move16(); + st_fx->bwidth_fx = st_fx->max_bwidth_fx; + move16(); + st_fx->last_input_bwidth_fx = st_fx->bwidth_fx; + move16(); + st_fx->last_bwidth_fx = st_fx->bwidth_fx; + move16(); + st_fx->last_bwidth_cng_fx = st_fx->bwidth_fx; + move16(); + + /* Tonal detector */ + FOR ( i=0; iold_S_fx[i] = 1; + move16(); + } + set16_fx( st_fx->cor_map_fx, 0, L_FFT/2 ); + st_fx->act_pred_fx = 32767; + move16(); + st_fx->noise_char_fx = 0; + move16(); + st_fx->multi_harm_limit_fx = THR_CORR_INIT_FX; + move16(); + st_fx->coder_type_raw_fx = VOICED; + st_fx->last_coder_type_raw_fx = st_fx->coder_type_raw_fx; + + /* Stationary noise UV modification */ + st_fx->ge_sm_fx = 640; + move32();/*Q(GE_SHIFT) */ + st_fx->uv_count_fx = 0; + move16(); + st_fx->act_count_fx = 3; + move16(); + Copy(st_fx->lsp_old_fx, st_fx->lspold_s_fx, M); + st_fx->noimix_seed_fx = RANDOM_INITSEED; + move16(); + st_fx->min_alpha_fx = 1; + move16(); + st_fx->exc_pe_fx = 0; + move16(); + + /* CNG and DTX */ + st_fx->lp_noise_fx = 0; + move16(); + Copy( st_fx->lsp_old1_fx, st_fx->lspCNG_fx, M ); + st_fx->cng_seed_fx = RANDOM_INITSEED; + move16(); + st_fx->cng_ener_seed_fx = RANDOM_INITSEED; + move16(); + st_fx->cng_ener_seed1_fx = RANDOM_INITSEED; + st_fx->lp_ener_fx = 0; + move32(); + st_fx->first_CNG_fx = 0; + move16(); + st_fx->cnt_SID_fx = 0; + move16(); + st_fx->max_SID_fx = 2; + move16(); + st_fx->old_enr_index_fx = -1; + move16(); + st_fx->Enew_fx = 0; + move32(); + st_fx->VarDTX_cnt_voiced_fx = 0; + move16(); + st_fx->lt_ener_voiced_fx = 0; + move32(); + st_fx->VarDTX_cnt_noise_fx = 0; + move16(); + st_fx->lt_ener_noise_fx = 0; + move32(); + st_fx->lt_ener_last_SID_fx = 0; + move32(); + if( st_fx->var_SID_rate_flag_fx ) + { + st_fx->interval_SID_fx = 12; + move16(); + } + st_fx->lp_sp_enr_fx = 0; + move16(); + st_fx->last_allow_cn_step_fx = 0; + move16(); + + st_fx->fd_cng_reset_flag = 0; + move16(); + + IF( st_fx->Opt_DTX_ON_fx ) + { + st_fx->cng_hist_ptr_fx = -1; + move16(); + set16_fx( st_fx->cng_lsp_hist_fx, 0, DTX_HIST_SIZE*M ); + set16_fx( st_fx->cng_ener_hist_fx, 0, DTX_HIST_SIZE ); + st_fx->cng_cnt_fx = 0; + move16(); + + st_fx->ho_hist_ptr_fx = -1; + move16(); + st_fx->ho_sid_bw_fx = L_deposit_l(0); + set16_fx( st_fx->ho_lsp_hist_fx, 0, HO_HIST_SIZE*M ); + set32_fx( st_fx->ho_ener_hist_fx, 0, HO_HIST_SIZE ); + set32_fx( st_fx->ho_env_hist_fx, 0, HO_HIST_SIZE*NUM_ENV_CNG ); + st_fx->ho_hist_size_fx = 0; + move16(); + st_fx->act_cnt_fx = 0; + move16(); + } + st_fx->active_fr_cnt_fx = 0; + move16(); + st_fx->cng_type_fx = -1; + move16(); + + st_fx->CNG_mode_fx = -1; + move16(); + st_fx->last_active_brate_fx = ACELP_7k20; + move32(); + st_fx->last_CNG_L_frame_fx = L_FRAME; + move16(); + set16_fx( st_fx->ho_16k_lsp_fx, 0, HO_HIST_SIZE ); + st_fx->act_cnt2_fx = 0; + move16(); + st_fx->num_ho_fx = 0; + move16(); + st_fx->hangover_terminate_flag_fx = 0; + move16(); + + st_fx->ho_circ_ptr_fx = -1; + move16(); + set16_fx( st_fx->ho_lsp_circ_fx, 0, HO_HIST_SIZE*M ); + set32_fx( st_fx->ho_ener_circ_fx, 0, HO_HIST_SIZE ); + set32_fx( st_fx->ho_env_circ_fx, 0, HO_HIST_SIZE*NUM_ENV_CNG ); + st_fx->ho_circ_size_fx = 0; + move16(); + st_fx->burst_ho_cnt_fx = 0; + move16(); + st_fx->cng_buf_cnt = 0; + move16(); + + test(); + test(); + IF( st_fx->var_SID_rate_flag_fx || ((!st_fx->var_SID_rate_flag_fx) && (st_fx->interval_SID_fx >= DTX_HIST_SIZE)) ) + { + st_fx->cng_hist_size_fx = DTX_HIST_SIZE; + move16(); + } + ELSE + { + st_fx->cng_hist_size_fx = st_fx->interval_SID_fx; + move16(); + } + set32_fx(st_fx->lp_env_fx, 0, 20); + set32_fx(st_fx->cng_res_env_fx, 0, 20*8); + set16_fx(st_fx->exc_mem_fx, 0, 24); + set16_fx(st_fx->exc_mem1_fx, 0, 30); + set16_fx(st_fx->exc_mem2_fx, 0, 30); + set32_fx(st_fx->old_env_fx, 0, NUM_ENV_CNG); + + /* SWB CNG/DTX */ + st_fx->last_wb_cng_ener_fx = -1541; + move16(); /* Q8 */ + st_fx->last_shb_cng_ener_fx = -1541; + move16(); /* Q8 */ + st_fx->mov_wb_cng_ener_fx = -1541; + move16(); /* Q8 */ + st_fx->mov_shb_cng_ener_fx = -1541; + move16(); /* Q8 */ + st_fx->shb_cng_ini_cnt_fx = 1; + move16(); + st_fx->shb_NO_DATA_cnt_fx = 0; + move16(); + st_fx->last_SID_bwidth_fx = s_min(st_fx->max_bwidth_fx, SWB); + st_fx->last_vad_fx = 0; + move16(); + + /* FEC */ + st_fx->last_clas_fx = UNVOICED_CLAS; + move16(); + + FOR (i=0; i<2*NB_SUBFR16k; i++) + { + st_fx->old_pitch_buf_fx[i] = L_SUBFR_Q6; + move16(); + } + st_fx->old_Es_pred_fx = 0; + move16(); + set16_fx(st_fx->old_Aq_12_8_fx + 1, 0, M ); + st_fx->old_Aq_12_8_fx[0] = 4096; + move16(); + + /*-----------------------------------------------------------------* + * CLDFB Analysis + *-----------------------------------------------------------------*/ + + /* open analysis for input SR */ + openCldfb ( &st_fx->cldfbAna_Fx, CLDFB_ANALYSIS, CLDFB_getNumChannels(st_fx->input_Fs_fx), st_fx->input_frame_fx ); + + openCldfb ( &st_fx->cldfbSyn_Fx, CLDFB_SYNTHESIS, CLDFB_getNumChannels(16000), L_FRAME16k); + + st_fx->energyCoreLookahead_Fx = 0; + move32(); + st_fx->sf_energyCoreLookahead_Fx = 0; + move16(); + + /*-----------------------------------------------------------------* + * SC-VBR parameters + *-----------------------------------------------------------------*/ + + st_fx->nelp_enc_seed_fx = 0; + move16(); + st_fx->last_nelp_mode_fx = 0; + move16(); + st_fx->pppcountE_fx = 0; + move16(); + st_fx->last_ppp_mode_fx = 0; + move16(); + st_fx->last_last_ppp_mode_fx = 0; + move16(); + st_fx->firstTime_voicedenc_fx = 1; + move16(); + st_fx->prev_ppp_gain_pit_fx = 0; + move16(); + st_fx->prev_tilt_code_fx = 0; + move16(); + + st_fx->ppp_mode_fx = 0; + move16(); + st_fx->nelp_mode_fx = 0; + move16(); + + /* stable short pitch detection */ + st_fx->voicing0_sm_fx = 0; + move16(); + st_fx->voicing_sm_fx = 0; + move16(); + st_fx->LF_EnergyRatio_sm_fx = 128; + move16(); + st_fx->predecision_flag_fx = 0; + move16(); + st_fx->diff_sm_fx = 0; + move32(); + st_fx->energy_sm_fx = 0; + move32(); + + st_fx->pattern_m_fx = 0; + move16(); + st_fx->Last_Resort_fx = 0; + move16(); + st_fx->Q_to_F_fx = 0; + move16(); + + st_fx->numactive_fx = 0; /* keep the count of the frames inside current 600 frame bloack.*/ + st_fx->sum_of_rates_fx = 0; /* sum of the rates of past 600 active frames*/ + st_fx->global_avr_rate_fx = 0; /* global rate upto current time. recorded a (rate in kbps) *6000*/ + st_fx->frame_cnt_ratewin_fx = 0; /* 600 active frame block count. Used to update the global rate*/ + st_fx->rate_control_fx = 0; + move16(); + st_fx->SNR_THLD_fx = SNR_THLD_FX_Q8; + move16(); + st_fx->mode_QQF_fx = 1; + move16(); + + + /*-----------------------------------------------------------------* + * SWB BWE parameters + *-----------------------------------------------------------------*/ + + set16_fx( st_fx->new_input_hp_fx, 0, NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS)); + set16_fx( st_fx->old_input_fx, 0, NS2SA(48000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) ); + set16_fx( st_fx->old_input_wb_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_12k8_NS) ); + set16_fx( st_fx->old_input_lp_fx, 0, NS2SA(16000, ACELP_LOOK_NS + DELAY_SWB_TBE_16k_NS) ); + set16_fx( st_fx->old_syn_12k8_16k_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) ); + + st_fx->prev_mode_fx = NORMAL; + move16(); + st_fx->modeCount_fx = 0; + move16(); + st_fx->EnergyLF_fx = 0; + move32(); + + set16_fx( st_fx->L_old_wtda_swb_fx, 0, L_FRAME48k ); + + st_fx->prev_Q_input_lp = 0; + move16(); + + st_fx->prev_global_gain_fx = 0; + move32(); + st_fx->prev_Q_shb = 0; + move16(); + st_fx->prev_L_swb_norm1_fx = 8; + move16(); + st_fx->last_Opt_SC_VBR_fx = 0; + move16(); + + /*-----------------------------------------------------------------* + * TBE parameters + *-----------------------------------------------------------------*/ + + InitSWBencBuffer_fx(st_fx); + ResetSHBbuffer_Enc_fx(st_fx); + set16_fx( st_fx->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k ); + set16_fx( st_fx->old_speech_wb_fx, 0, (L_LOOK_12k8 + L_SUBFR) * 5/16); + set16_fx( st_fx->old_input_fhb_fx, 0, NS2SA(48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) - L_FRAME48k/2); + st_fx->old_input_fhb_fx_Q = 0; + move16(); + st_fx->cldfbHBLT = 8192/*1.0f Q13*/; + + st_fx->prev_gainFr_SHB_fx = 0; + set16_fx(st_fx->lsp_shb_slow_interpl_fx, 0, LPC_SHB_ORDER); + set16_fx(st_fx->lsp_shb_fast_interpl_fx, 0, LPC_SHB_ORDER); + set16_fx( st_fx->shb_inv_filt_mem_fx, 0, LPC_SHB_ORDER ); + set16_fx( st_fx->lsp_shb_spacing_fx, 3277, 3); + st_fx->prev_swb_GainShape_fx= 0; + move16(); + st_fx->prev_frGainAtten_fx = 0; + move16(); + st_fx->prev_wb_GainShape = 0; + move16(); + st_fx->prev_Q_bwe_exc_fb = 51; + move16(); + set16_fx(st_fx->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER); + st_fx->fb_tbe_demph_fx = 0; + move16(); + st_fx->tilt_mem_fx = 0; + move16(); + st_fx->prev_coder_type_fx = GENERIC; + move16(); + set16_fx( st_fx->prev_lsf_diff_fx, 16384, LPC_SHB_ORDER-2 ); + st_fx->prev_tilt_para_fx = 0; + move16(); + set16_fx( st_fx->cur_sub_Aq_fx, 0, M+1 ); + + /* TD BWE post-processing */ + st_fx->ptr_mem_stp_swb_fx = st_fx->mem_stp_swb_fx + LPC_SHB_ORDER - 1; + set16_fx(st_fx->mem_zero_swb_fx, 0, LPC_SHB_ORDER); + + FOR ( i=0; iswb_lsp_prev_interp_fx[i] = swb_lsp_prev_interp_init[i]; + } + + set16_fx( st_fx->dec_2_over_3_mem_fx, 0, 12 ); + set16_fx( st_fx->dec_2_over_3_mem_lp_fx, 0, 6 ); + set16_fx( st_fx->old_fdbwe_speech_fx, 0, L_FRAME48k ); + + /*-----------------------------------------------------------------* + * HQ core parameters + *-----------------------------------------------------------------*/ + + st_fx->input = st_fx->input_buff+L_FRAME48k+NS2SA(48000, DELAY_FIR_RESAMPL_NS); + set16_fx( st_fx->input_buff+L_FRAME48k, 0, L_FRAME48k+NS2SA(48000, DELAY_FIR_RESAMPL_NS) ); + st_fx->old_input_signal_fx = st_fx->input - add(NS2SA_fx2(st_fx->input_Fs_fx, DELAY_FIR_RESAMPL_NS), st_fx->input_frame_fx); + + st_fx->Q_old_out = 0; + move16(); + + st_fx->Energy_Old_fx = 0; + move16(); + st_fx->Q_old_wtda=15; + move16(); + st_fx->EnergyLT_fx = 1; + move32(); + st_fx->EnergyLT_fx_exp = 30; + move16(); /* Set to a High Exponent so it is 1^-30 */ + st_fx->TransientHangOver_fx = 0; + move16(); + + set16_fx( st_fx->old_out_fx, 0, L_FRAME32k ); + st_fx->mode_count_fx = 0; + move16(); + st_fx->mode_count1_fx = 0; + move16(); + + st_fx->hq_generic_speech_class_fx = 0; + move16(); + st_fx->prev_Npeaks_fx = 0; + set16_fx(st_fx->prev_peaks_fx, 0, HVQ_MAX_PEAKS); + st_fx->hvq_hangover_fx = 0; + st_fx->prev_hqswb_clas_fx = HQ_NORMAL; + + set16_fx(st_fx->prev_SWB_peak_pos_fx, 0, SPT_SHORTEN_SBNUM); + st_fx->clas_sec_old_fx = 8192; /* 1.0f in Q13 */; + st_fx->clas_final_old_fx = 1; /* Q0 */ + st_fx->last_gain1 = 0; + move32(); + st_fx->last_gain2 = 0; + move32(); + st_fx->last_enerBuffer_exp = 0; + move16(); + /* speech/music classification */ + set16_fx(st_fx->lt_old_mode, 1, 3); + st_fx->lt_voicing = 16384/*0.5f Q15*/; + st_fx->lt_corr = 16384/*0.5f Q15*/; + st_fx->lt_tonality = 0; + move32(); + set16_fx(st_fx->lt_corr_pitch, 0, 3); + st_fx->lt_hangover = 0; + move16(); + st_fx->lowrate_pitchGain = 0; + move16(); + + + st_fx->lt_music_hangover_fx = 0; + move16(); + set16_fx(st_fx->tonality2_buf_fx,0,HANG_LEN_INIT); + set16_fx(st_fx->tonality3_buf_fx,0,HANG_LEN_INIT); + set16_fx(st_fx->LPCErr_buf_fx,0,HANG_LEN_INIT); + st_fx->lt_music_state_fx = 0; + move16(); + st_fx->lt_speech_state_fx = 0; + move16(); + st_fx->lt_speech_hangover_fx = 0; + move16(); + st_fx->consec_inactive_fx = 0; + move16(); + st_fx->spectral_tilt_reset_fx = 1; + move16(); + st_fx->running_avg_fx = 0; + move16(); + st_fx->ra_deltasum_fx = 0; + move16(); + st_fx->trigger_SID_fx = 0; + move16(); + st_fx->L_snr_sum_vad_fx = 0; + move32(); + + set16_fx( st_fx->prev_frm_index_fx, -1, NB_SWB_SUBBANDS_HAR_SEARCH_SB ); + st_fx->prev_frm_hfe2_fx = 0; + move16(); + st_fx->prev_stab_hfe2_fx = 0; + move16(); + st_fx->prev_ni_ratio_fx = 16384; + move16(); /* 0.5 */ + set16_fx(st_fx->prev_En_sb_fx, 0, NB_SWB_SUBBANDS); + set16_fx(st_fx->last_bitalloc_max_band_fx, 0, 2); + set32_fx( st_fx->last_ni_gain_fx, 0, BANDS_MAX ); + set16_fx( st_fx->last_env_fx, 0, BANDS_MAX ); + st_fx->last_max_pos_pulse_fx = 0; + move16(); + + /*-----------------------------------------------------------------* + * Channel-aware mode + *-----------------------------------------------------------------*/ + + + test(); + test(); + test(); + IF( st_fx->Opt_RF_ON == 0 || (NE_16(st_fx->bwidth_fx,WB)&&NE_16(st_fx->bwidth_fx,SWB))||NE_32(st_fx->total_brate_fx,ACELP_13k20)) + { + IF (EQ_16(st_fx->Opt_RF_ON,1)) + { + printf("\nWarning: Channel-aware mode only available for 13.2 kbps WB/SWB\n"); + printf(" Switched to normal mode!\n"); + st_fx->Opt_RF_ON = 0; + move16(); + st_fx->rf_fec_offset = 0; + move16(); + } + st_fx->rf_mode = 0; + move16(); + } + ELSE + { + st_fx->rf_mode = st_fx->Opt_RF_ON; + move16(); + } + st_fx->rf_mode_last = st_fx->rf_mode; + + /* initialize RF indice buffers */ + reset_rf_indices( st_fx ); + + /*-----------------------------------------------------------------* + * MODE2 initialization + *-----------------------------------------------------------------*/ + + st_fx->last_sr_core = i_mult2 (st_fx->last_L_frame_fx, 50); + + + IF( EQ_16(st_fx->codec_mode, MODE2)) + { + st_fx->igf = getIgfPresent( st_fx->total_brate_fx, st_fx->bwidth_fx, st_fx->rf_mode); + } + ELSE + { + st_fx->igf = 0; + move16(); + } + + /* FD-CNG encoder */ + createFdCngEnc(&st_fx->hFdCngEnc_fx); + initFdCngEnc(st_fx->hFdCngEnc_fx, st_fx->input_Fs_fx, st_fx->cldfbAna_Fx->scale); + L_tmp = st_fx->total_brate_fx; + move32(); + test(); + if( st_fx->rf_mode && EQ_32(st_fx->total_brate_fx,ACELP_13k20)) + { + L_tmp = ACELP_9k60; + move32(); + } + configureFdCngEnc( st_fx->hFdCngEnc_fx, st_fx->bwidth_fx, L_tmp ); + + st_fx->last_totalNoise_fx = 0; + move16(); + set16_fx( st_fx->totalNoise_increase_hist_fx, 0, TOTALNOISE_HIST_SIZE ); + st_fx->totalNoise_increase_len_fx = 0; + move16(); + init_coder_ace_plus( st_fx, 0); + + InitTransientDetection( extract_l(Mult_32_16(st_fx->input_Fs_fx, 0x0290)), + NS2SA_fx2(st_fx->input_Fs_fx, DELAY_FIR_RESAMPL_NS), + &st_fx->transientDetection ); + + reset_indices_enc_fx( st_fx ); + + + st_fx->Q_syn2 = 0; + move16(); + st_fx->Q_syn = 0; + move16(); + set16_fx(st_fx->Q_max, Q_MAX, L_Q_MEM); + set16_fx(st_fx->Q_max_16k, Q_MAX, L_Q_MEM); + st_fx->Q_old = 15; + move16(); + st_fx->old_wsp_max = 0; + move16(); + st_fx->old_wsp_shift = 0; + move16(); + + st_fx->vbr_generic_ho_fx = 0; + move16(); + + st_fx->sharpFlag = 0; + move16(); + + st_fx->Local_VAD = 0; + + set16_fx( st_fx->nelp_lp_fit_mem, 0, NELP_LP_ORDER*2 ); + + return; +} + +/*-----------------------------------------------------------------------* + * destroy_encoder() + * + * Free memory which was allocated in init_encoder() + *-----------------------------------------------------------------------*/ + +void destroy_encoder_fx( + Encoder_State_fx *st_fx /* i/o: Encoder static variables structure */ +) +{ + deleteCldfb( &st_fx->cldfbAna_Fx ); + deleteCldfb( &st_fx->cldfbSyn_Fx ); + + deleteFdCngEnc( &st_fx->hFdCngEnc_fx ); + + return; +} diff --git a/lib_enc/inov_enc_fx.c b/lib_enc/inov_enc_fx.c new file mode 100644 index 0000000..dc89b04 --- /dev/null +++ b/lib_enc/inov_enc_fx.c @@ -0,0 +1,332 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "basop_util.h" +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" + + +/*==============================================================================*/ +/* FUNCTION : inov_encode_fx() */ +/*------------------------------------------------------------------------------*/ +/* PURPOSE : Encode the algebraic innovation */ +/*------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) core_brate: core bitrate Q0 */ +/* _ (Word16) Opt_AMR_WB: flag indicating AMR-WB IO mode Q0 */ +/* _ (Word16) bwidth : input signal bandwidth Q0 */ +/* _ (Word16) L_frame_fx : length of the frame Q0 */ +/* _ (Word16[]) h2 : weighted filter input response Q12 */ +/* _ (Word16[]) xn2 : target vector Q_new */ +/* _ (Word16) coder_type_fx : coding type Q0 */ +/* _ (Word16) i_subfr : current sub frame indicator Q0 */ +/* _ (Word16[]) exc_fx : pointer to excitation signal frame Q_new */ +/* _ (Word16) L_subfr : subframe length Q0 */ +/* _ (Word16) clip_gain : adaptive gain clipping flag Q0 */ +/* _ (Word16) gain_pit : adaptive excitation gain Q14 */ +/* _ (Word16) sharpFlag : formant sharpening flag Q0 */ +/* _ (Word16) tc_subfr : TC subframe index Q0 */ +/* _ (Word16) p_Aq : LP filter coefficients Q12 */ +/* _ (Word16) Jopt_flag :joint optimization flag Q0 */ +/* _ (Word16) y1 : Filtered adaptive excitation Q_new */ +/* _ (Word16) y2 :zero-memory filtered algebraic excitation Q_new */ +/* _ (Word16) cn : target vector in residual domain Q_new */ +/* _ (Word16) tilt_code : tilt of the excitation of previous subframe Q15 */ +/* _ (Word16) pt_pitch : pointer to current subframe fractional pitchQ6 */ +/* _ (Word16) index_buf_4T :5Sx4Track buffer for PI Q0 */ +/* _ (Word16) shift :shift */ +/* _ (Word16) Q_new : */ +/*------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Q0) */ +/* _ (Word16) cn : target vector in residual domain Q_new */ +/* _ (Word16) code :algebraic excitation Q9 */ +/* _ (Word16) y2 :zero-memory filtered algebraic excitation Q_new */ +/* _ (Word16) unbits :number of unused bits for PI Q0 */ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*==============================================================================*/ + +Word16 inov_encode_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 last_L_frame, /* i : length of the last frame */ + const Word16 coder_type, /* i : coding type */ + const Word16 bwidth, /* i : input signal bandwidth */ + const Word16 sharpFlag, /* i : formant sharpening flag */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 *p_Aq, /* i : LP filter coefficients Q12*/ + const Word16 gain_pit, /* i : adaptive excitation gain Q14*/ + Word16 *cn, /* i/o: target vector in residual domain Q_new*/ + const Word16 *exc, /* i : pointer to excitation signal frame Q_new*/ + Word16 *h2, /* i/o: weighted filter input response Q12*/ + const Word16 tilt_code, /* i : tilt of the excitation of previous subframe Q15*/ + const Word16 pt_pitch, /* i : pointer to current subframe fractional pitch Q6*/ + const Word16 *xn2, /* i : target vector for innovation search Q_new-1+shift*/ + Word16 *code, /* o : algebraic excitation Q9*/ + Word16 *y2, /* o : zero-memory filtered algebraic excitation Q9*/ + Word16 *unbits, /* o : number of unused bits for PI */ + Word16 shift +) +{ + Word16 dn[L_SUBFR]; + Word16 nBits, cmpl_flag; + Word16 stack_pulses; + Word16 g1, g2; + Word16 Rw[L_SUBFR]; + Word16 acelpautoc; + + stack_pulses = 0; + move16(); + + IF( EQ_16(L_frame,L_FRAME)) + { + g1 = FORMANT_SHARPENING_G1; + move16(); + g2 = FORMANT_SHARPENING_G2; + move16(); + } + ELSE + { + g1 = FORMANT_SHARPENING_G1_16k; + move16(); + g2 = FORMANT_SHARPENING_G2_16k; + move16(); + } + + /*----------------------------------------------------------------* + * Update target vector for codebook search in residual domain + * Preemphasize the impulse response and include fixed-gain pitch contribution into impulse resp. h1[] (pitch sharpenning) + * Correlation between target xn2[] and impulse response h1[] + *----------------------------------------------------------------*/ + + test(); + IF (GT_32(core_brate, ACELP_13k20)&&!Opt_AMR_WB) + { + acelpautoc = 1; + move16(); + + cb_shape_fx( 1, 1, 0, sharpFlag, 0, g1, g2, p_Aq, h2, tilt_code, shr(add(pt_pitch,26),6), 0 ); + /* h2: Q11, Rw: (Rw_e)Q */ + /* Rw_e = */ E_ACELP_hh_corr(h2, Rw, L_SUBFR, 3); + + E_ACELP_conv(xn2, h2, cn); + + /* dn_e -> Rw_e*Q_xn */ + /*dn_e = */ E_ACELP_toeplitz_mul( Rw, cn, dn, L_SUBFR, 1 ); + } + ELSE + { + acelpautoc = 0; + move16(); + updt_tar_fx( cn, cn, &exc[i_subfr], gain_pit, L_SUBFR ); + /* scaling of cn[] to limit dynamic at 12 bits */ + Scale_sig(cn, L_SUBFR, shift); + + cb_shape_fx( 1, 1, 0, sharpFlag, 0, g1, g2, p_Aq, h2, tilt_code, shr(add(pt_pitch,26),6), 0 ); + corr_xh_fx( xn2, dn, h2 ); + } + + /*-----------------------------------------------------------------* + * Set complexity reduction flag to limit the number of iterations + * in algebraic innovation search + *-----------------------------------------------------------------*/ + cmpl_flag = 0; + move16(); + test(); + IF( EQ_16(L_frame,L_FRAME)&&EQ_16(coder_type,TRANSITION)) + { + test(); + test(); + if( EQ_32(core_brate,ACELP_8k00)&&i_subfr==0&<_16(tc_subfr,L_SUBFR)) + { + cmpl_flag = 3; + move16(); + } + test(); + test(); + test(); + test(); + test(); + if( EQ_32(core_brate,ACELP_11k60)&&((i_subfr==0&<_16(tc_subfr,L_SUBFR))||EQ_16(tc_subfr,TC_0_0)||(EQ_16(i_subfr,3*L_SUBFR)&&EQ_16(tc_subfr,TC_0_64)))) + { + cmpl_flag = 3; + move16(); + } + test(); + test(); + test(); + test(); + if( (EQ_32(core_brate,ACELP_13k20)||EQ_32(core_brate,ACELP_12k15))&&((i_subfr==0&<_16(tc_subfr,L_SUBFR))||LE_16(tc_subfr,TC_0_64))) + { + cmpl_flag = 3; + move16(); + } + } + + IF( EQ_16(L_frame,L_FRAME16k)) + { + IF( LE_32(core_brate,ACELP_32k)) + { + cmpl_flag = 4; + move16(); + + test(); + IF( EQ_16(coder_type,TRANSITION)&>_16(bwidth,WB)) + { + IF( LE_16(i_subfr,L_SUBFR)) + { + cmpl_flag = sub(cmpl_flag,1); + } + ELSE + { + cmpl_flag = sub(cmpl_flag,2); + } + } + } + ELSE IF( LE_32(core_brate,ACELP_48k)) + { + cmpl_flag = 3; + move16(); + + IF( EQ_16(coder_type,TRANSITION)) + { + IF( LE_16(i_subfr,L_SUBFR)) + { + cmpl_flag = sub(cmpl_flag,1); + } + ELSE + { + cmpl_flag = sub(cmpl_flag,2); + } + } + } + ELSE + { + cmpl_flag = 4; + move16(); + + IF( EQ_16(coder_type,TRANSITION)) + { + IF( LE_16(i_subfr,L_SUBFR)) + { + cmpl_flag = sub(cmpl_flag,1); + } + ELSE + { + cmpl_flag = sub(cmpl_flag,2); + } + } + + if( EQ_16(coder_type,INACTIVE)) + { + cmpl_flag = 4; + move16(); + } + } + } + + test(); + test(); + test(); + IF( NE_16(L_frame,last_L_frame)&>_32(core_brate,ACELP_13k20)&&(LT_32(core_brate,ACELP_32k)||EQ_16(bwidth,WB))) + { + if( GT_16(cmpl_flag,1)) + { + cmpl_flag = sub(cmpl_flag,1); + } + } + + /*-----------------------------------------------------------------* + * Find and encode the algebraic innovation + *-----------------------------------------------------------------*/ + + set16_fx( y2, 0, L_SUBFR ); + + IF ( !Opt_AMR_WB ) + { + IF( EQ_16(L_frame,L_FRAME)) + { + nBits = FCB_bits_tbl[BIT_ALLOC_IDX_fx(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_fx(tc_subfr))]; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + nBits = FCB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ_fx(tc_subfr))]; + move16(); + } + + IF( EQ_16(nBits,7)) + { + acelp_1t64_fx( st_fx, dn, h2, code, y2 ); + } + ELSE IF( EQ_16(nBits,12)) + { + acelp_2t32_fx(st_fx, dn, h2, code, y2 ); + } + ELSE + { + *unbits = add(*unbits, acelp_4t64_fx(st_fx, dn, cn, h2, Rw, acelpautoc, code, y2, nBits, cmpl_flag, Opt_AMR_WB)); + move16(); + } + } + ELSE + { + IF (EQ_32(core_brate,ACELP_6k60)) + { + acelp_2t32_fx( st_fx, dn, h2, code, y2 ); + } + ELSE IF( (EQ_32(core_brate,ACELP_8k85))) + { + acelp_4t64_fx(st_fx, dn, cn, h2, Rw, acelpautoc, code, y2, 20, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32(core_brate,ACELP_12k65)) + { + acelp_4t64_fx(st_fx, dn, cn, h2, Rw, acelpautoc, code, y2, 36, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32(core_brate,ACELP_14k25)) + { + acelp_4t64_fx( st_fx, dn, cn, h2, Rw, acelpautoc, code, y2, 44, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32(core_brate,ACELP_15k85)) + { + acelp_4t64_fx( st_fx, dn, cn, h2, Rw, acelpautoc, code, y2, 52, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32(core_brate,ACELP_18k25)) + { + acelp_4t64_fx(st_fx, dn, cn, h2, Rw, acelpautoc, code, y2, 64, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32(core_brate,ACELP_19k85)) + { + acelp_4t64_fx(st_fx, dn, cn, h2, Rw, acelpautoc, code, y2, 72, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32(core_brate,ACELP_23k05)) + { + acelp_4t64_fx(st_fx, dn, cn, h2, Rw, acelpautoc, code, y2, 88, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32(core_brate,ACELP_23k85)) + { + acelp_4t64_fx(st_fx, dn, cn, h2, Rw, acelpautoc, code, y2, 88, 1, Opt_AMR_WB); + } + } + + + /*----------------------------------------------------------------* + * Pitch sharpening + *----------------------------------------------------------------*/ + + cb_shape_fx( 1, 1, 0, sharpFlag, 0, g1, g2, p_Aq, code, tilt_code, shr(add(pt_pitch,26),6), 0 ); + + return stack_pulses; + +} diff --git a/lib_enc/io_enc_fx.c b/lib_enc/io_enc_fx.c new file mode 100644 index 0000000..8d7bf20 --- /dev/null +++ b/lib_enc/io_enc_fx.c @@ -0,0 +1,1051 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "stl.h" +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "disclaimer.h" /* for disclaimer */ +#include +#include "mime.h" +#include + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static void usage_enc(void); +static char *to_upper( char *str ); + +static char * bit_rate_to_string(char *string, Word32 bit_rate) +{ + char *src, *dst; + + assert(bit_rate >= 100); + src = string + sprintf(string, "%i", bit_rate); + /* Insert a '.' before last two digits and remove last digit */ + /* What we want is to print %.2f of bit_rate/1000.0 */ + dst = src--; + *--dst = *--src; + *--dst = *--src; + *--dst = '.'; + + return string; +} + +/*---------------------------------------------------------------------* + * io_ini_enc() + * + * Processing of command line parameters + *---------------------------------------------------------------------*/ + +void io_ini_enc_fx( + const int argc, /* i : command line arguments number */ + char *argv[], /* i : command line arguments */ + FILE **f_input, /* o : input signal file */ + FILE **f_stream, /* o : output bitstream file */ + FILE **f_rate, /* o : bitrate switching profile (0 if N/A) */ + FILE **f_bwidth, /* o : bandwidth switching profile (0 if N/A) */ + FILE **f_rf, /* o : channel aware configuration file */ + Word16 *quietMode, /* o : limit printouts */ + Word16 *noDelayCmp, /* o : turn off delay compensation */ + Encoder_State_fx *st /* o : state structure */ +) +{ + short i = 1, j; + short max_bwidth_user = -1; + char max_bwidth_string[4]; + int tmp; + char stmp[FILENAME_MAX]; + short rf_file_attempt = 1; + char first_char; + char rf_file_name[300]; + char bit_rate_string[14]; + + print_disclaimer(stderr); + + /*-----------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + /*The complexity don't need to be taken into account given that is only initialisation */ + + *f_input = NULL; + *f_stream = NULL; + *quietMode = 0; + + st->input_Fs_fx = 16000; + st->total_brate_fx = ACELP_12k65; + + st->Opt_AMR_WB_fx = 0; + st->Opt_RF_ON = 0; + st->rf_fec_offset = 0; + st->rf_fec_indicator = 1; + + st->max_bwidth_fx = SWB; + st->interval_SID_fx = FIXED_SID_RATE; + st->var_SID_rate_flag_fx = 1; + st->Opt_HE_SAD_ON_fx = 0; + st->Opt_SC_VBR_fx = 0; + st->last_Opt_SC_VBR_fx = 0; + st->bitstreamformat = G192; + + if ( argc < 5 ) + { + usage_enc(); + } + + + /*-----------------------------------------------------------------* + * Optional input arguments + *-----------------------------------------------------------------*/ + + while ( i < argc-4 ) + { + /*-----------------------------------------------------------------* + * Bandwidth limitation + *-----------------------------------------------------------------*/ + + if ( strcmp( to_upper(argv[i]), "-MAX_BAND") == 0 ) + { + strncpy( stmp, argv[i+1], sizeof(stmp) ); + + if (strcmp( to_upper(stmp), "-NB") == 0 || strcmp( to_upper(stmp), "NB") == 0) + { + st->max_bwidth_fx = max_bwidth_user = NB; + } + else if (strcmp( to_upper(stmp), "-WB") == 0 || strcmp( to_upper(stmp), "WB") == 0) + { + st->max_bwidth_fx = max_bwidth_user = WB; + } + else if (strcmp( to_upper(stmp), "-SWB") == 0 || strcmp( to_upper(stmp), "SWB") == 0) + { + st->max_bwidth_fx = max_bwidth_user = SWB; + } + else if (strcmp( to_upper(stmp), "-FB") == 0 || strcmp( to_upper(stmp), "FB") == 0) + { + st->max_bwidth_fx = max_bwidth_user = FB; + } + else if ( (*f_bwidth = fopen(argv[i+1], "rb")) == NULL ) + { + fprintf(stderr, "Error: incorect bandwidth specification or the bandwidth profile file could not be opened: %s\n\n", argv[i+1]); + usage_enc(); + } + /* read first bandwidth value from the profile file (just to check validity) */ + if ( *f_bwidth != NULL ) + { + if ( fscanf( *f_bwidth, "%d %s", &tmp, stmp) == EOF ) + { + fprintf (stderr,"Error: cannot read the bandwidth profile file\n\n"); + usage_enc(); + } + + rewind(*f_bwidth); + + if ( (st->max_bwidth_fx = CONV_BWIDTH( stmp )) == -1 ) + { + fprintf (stderr,"Error: incorrect bandwidth specified (only NB, WB, SWB and FB are supported)\n\n"); + usage_enc(); + } + else + { + fprintf(stdout, "Bandwidth switching file: %s\n", argv[i+1]); + } + } + else + { + fprintf(stdout, "Maximum encoded bandwidth: %s\n", stmp); + } + + i += 2; + } + + /*-----------------------------------------------------------------* + * Quiet mode + *-----------------------------------------------------------------*/ + + else if( strcmp( to_upper(argv[i]), "-Q" ) == 0 ) + { + i++; + *quietMode = 1; + } + + /*-----------------------------------------------------------------* + * DTX/CNG + *-----------------------------------------------------------------*/ + + else if( strcmp( to_upper(argv[i]), "-DTX" ) == 0 ) + { + i++; + if( i < argc-4 ) + { + if( sscanf(argv[i], "%d", &tmp) <= 0 ) + { + tmp = FIXED_SID_RATE; + } + else + { + i++; + } + } + else + { + tmp = FIXED_SID_RATE; + } + + st->Opt_DTX_ON_fx = 1; + if( tmp == 0 ) + { + st->var_SID_rate_flag_fx = 1; + st->interval_SID_fx = 0; + } + else if (tmp >= 3 && tmp <= 100) + { + st->var_SID_rate_flag_fx = 0; + st->interval_SID_fx = (short)tmp; + } + else + { + fprintf(stderr, "Error: Incorrect SID update interval specified: %d (supported 3-100)\n\n", tmp); + usage_enc(); + } + } + + /*-----------------------------------------------------------------* + * Deactivate delay compensation + *-----------------------------------------------------------------*/ + else if( strcmp( to_upper(argv[i]), "-NO_DELAY_CMP" ) == 0 ) + { + *noDelayCmp = 1; + i++; + } + + + /*-----------------------------------------------------------------* + * Activate channel-aware mode + *-----------------------------------------------------------------*/ + + else if ( strcmp( to_upper(argv[i]), "-RF" ) == 0 ) + { + st->Opt_RF_ON = 1; + i++; + + if( i < argc - 4 ) + { + rf_file_attempt = 1; + sscanf(argv[i], "%s", rf_file_name); + if ( ( strcmp( to_upper(argv[i]), "LO") == 0 ) ) + { + st->rf_fec_indicator = 0; + i++; + rf_file_attempt = 0; + } + else if ( ( strcmp( to_upper(argv[i]), "HI") == 0 ) ) + { + st->rf_fec_indicator = 1; + i++; + rf_file_attempt = 0; + } + + if ( ( sscanf(argv[i], "%d", &tmp) == 1 ) && ( i < argc - 4 ) ) + { + if ( tmp == 0 ) + { + st->Opt_RF_ON = 0; + st->rf_fec_offset = 0; + i++; + rf_file_attempt = 0; + } + else if( tmp == 2 || tmp == 3 || tmp == 5 || tmp == 7 ) + { + st->rf_fec_offset = (Word16)tmp; + i++; + rf_file_attempt = 0; + } + else + { + fprintf (stderr,"Error: incorrect FEC offset specified; RF offset can be 2, 3, 5, or 7. \n\n"); + usage_enc(); + } + } + else + { + st->rf_fec_offset = FEC_OFFSET; + } + if ( rf_file_attempt == 1 ) + { + first_char = rf_file_name[0]; + if ( first_char != '-' ) + { + if ( (*f_rf = fopen(rf_file_name, "r")) == NULL ) + { + fprintf(stderr, "Error: Incorrect specification of channal aware configuration or the CA configuration file could not be opened: %s\n\n", argv[i]); + usage_enc(); + } + i++; + } + } + } + else + { + st->rf_fec_indicator = 1; + st->rf_fec_offset = FEC_OFFSET; + } + } + + /*-----------------------------------------------------------------* + * MIME output file format + *-----------------------------------------------------------------*/ + else if( strcmp( to_upper(argv[i]), "-MIME" ) == 0 ) + { + st->bitstreamformat = MIME; + i++; + } + /*-----------------------------------------------------------------* + * Option not recognized + *-----------------------------------------------------------------*/ + + else + { + fprintf(stderr, "Error: option not recognized, %s\n\n", argv[i]); + usage_enc(); + } + } /* end of while */ + + /*-----------------------------------------------------------------* + * Mandatory input arguments + *-----------------------------------------------------------------*/ + + /*-----------------------------------------------------------------* + * Bitrate + *-----------------------------------------------------------------*/ + + if ( i < argc-2 ) + { + /* check if profile file has been entered instead of a fixed bitrate */ + if (sscanf(argv[i], "%d", &tmp) != 1) + { + if ( (*f_rate = fopen(argv[i], "rb")) == NULL ) + { + fprintf(stderr, "Error: bitrate profile file %s could not be opened\n\n", argv[i]); + usage_enc(); + } + + /* read first bitrate value from the profile file (just to check validity)*/ + if ( fread( &st->total_brate_fx, 4, 1, *f_rate ) != 1 && feof(*f_rate) ) + { + fprintf (stderr,"Error: cannot read the bitrate profile file\n\n"); + usage_enc(); + } + + rewind(*f_rate); + + fprintf(stdout, "Bitrate switching file: %s\n", argv[i]); + } + else + { + st->total_brate_fx = tmp; + + /* channel-aware mode is supported only at 13.20 */ + if( st->Opt_RF_ON && st->total_brate_fx != ACELP_13k20 ) + { + st->Opt_RF_ON = 0; + } + } + + /* SC-VBR at 5.90 kbps */ + if ( st->total_brate_fx == ACELP_5k90 ) + { + st->Opt_SC_VBR_fx = 1; + st->last_Opt_SC_VBR_fx = st->Opt_SC_VBR_fx; + st->total_brate_fx = ACELP_7k20; + + if ( st->max_bwidth_fx != NB ) + { + st->max_bwidth_fx = WB; + } + } + + /* check if the entered bitrate is supported */ + j = 0; + while ( j < SIZE_BRATE_TBL && st->total_brate_fx != brate_tbl[j] ) + { + j++; + } + + /* AMR-WB IO/EVS primary mode determination */ + if ( j >= SIZE_BRATE_TBL ) + { + switch ( st->total_brate_fx ) + { + case ACELP_6k60 : + case ACELP_8k85 : + case ACELP_12k65 : + case ACELP_14k25 : + case ACELP_15k85 : + case ACELP_18k25 : + case ACELP_19k85 : + case ACELP_23k05 : + case ACELP_23k85 : + break; + default : + { + fprintf(stderr, "Error: Incorrect bitrate specification: %d\n\n", st->total_brate_fx ); + usage_enc(); + } + } + + st->Opt_AMR_WB_fx = 1; + } + else + { + st->Opt_AMR_WB_fx = 0; + } + + i++; + } + else + { + fprintf(stderr, "Error: no bitrate specified\n\n"); + usage_enc(); + } + + /*-----------------------------------------------------------------* + * Input sampling frequency + *-----------------------------------------------------------------*/ + + if( i < argc-2 ) + { + st->input_Fs_fx = (int) atoi( argv[i] ) * 1000; + if( st->Opt_RF_ON && st->input_Fs_fx == 8000 ) + { + /* Reset RF parameters if NB input_Fs; + For FB input @13.2kbps, the codec is shifted down to SWB below. */ + st->Opt_RF_ON = 0; + st->rf_fec_offset = 0; + } + + if( (st->input_Fs_fx != 8000) && ( st->input_Fs_fx != 16000) && (st->input_Fs_fx != 32000) && (st->input_Fs_fx != 48000) ) + { + fprintf(stderr, "Error: %d kHz is not a supported sampling rate\n\n", atoi( argv[i] ) ); + usage_enc(); + } + + i++; + } + else + { + fprintf(stderr, "Error: no input sampling frequency specified\n\n"); + usage_enc(); + } + + /*-----------------------------------------------------------------* + * Input file + *-----------------------------------------------------------------*/ + + if( i < argc-1 ) + { + if ( (*f_input = fopen(argv[i], "rb")) == NULL ) + { + fprintf(stderr, "Error: input audio file %s could not be opened\n\n", argv[i]); + usage_enc(); + } + + fprintf(stdout, "Input audio file: %s\n", argv[i]); + i++; + } + else + { + fprintf(stderr, "Error: no input file specified\n\n"); + usage_enc(); + } + + /*-----------------------------------------------------------------* + * Output bitstream file + *-----------------------------------------------------------------*/ + + if( i < argc ) + { + if ( (*f_stream = fopen(argv[i], "wb")) == NULL) + { + fprintf(stderr, "Error: output bitstream file %s could not be opened\n\n", argv[i]); + usage_enc(); + } + fprintf(stdout, "Output bitstream file: %s\n", argv[i]); + i++; + /* If MIME/storage format selected, write the magic number at the beginning of the bitstream file */ + if( st->bitstreamformat == MIME ) + { + char buf[4]; + fwrite(EVS_MAGIC_NUMBER, sizeof(char), strlen(EVS_MAGIC_NUMBER), *f_stream); + buf[0] = buf[1] = buf[2] = 0; + buf[3] = 1; + fwrite(&buf, sizeof(char), 4, *f_stream); + fprintf(stdout, "Output bitstream file format: MIME"); + } + } + else + { + fprintf(stderr, "Error: no output bitstream file specified\n\n"); + usage_enc(); + } + + fprintf( stdout, "\n" ); + + + /* Prevent st->max_bwidth from being higher than Fs/2 */ + if ( st->input_Fs_fx == 8000 && st->max_bwidth_fx > NB ) + { + st->max_bwidth_fx = NB; + } + else if ( st->input_Fs_fx == 16000 && st->max_bwidth_fx > WB ) + { + st->max_bwidth_fx = WB; + } + else if ( st->input_Fs_fx == 32000 && st->max_bwidth_fx > SWB ) + { + st->max_bwidth_fx = SWB; + } + + IF ( st->Opt_AMR_WB_fx ) + { + st->codec_mode = MODE1; + move16(); + } + ELSE + { + SWITCH ( st->total_brate_fx ) + { + case 5900: + st->codec_mode = MODE1; + move16(); + BREAK; + case 7200: + st->codec_mode = MODE1; + move16(); + BREAK; + case 8000: + st->codec_mode = MODE1; + move16(); + BREAK; + case 9600: + st->codec_mode = MODE2; + move16(); + BREAK; + case 13200: + st->codec_mode = MODE1; + move16(); + BREAK; + case 16400: + st->codec_mode = MODE2; + move16(); + BREAK; + case 24400: + st->codec_mode = MODE2; + move16(); + BREAK; + case 32000: + st->codec_mode = MODE1; + move16(); + BREAK; + case 48000: + st->codec_mode = MODE2; + move16(); + BREAK; + case 64000: + st->codec_mode = MODE1; + move16(); + BREAK; + case 96000: + st->codec_mode = MODE2; + move16(); + BREAK; + case 128000: + st->codec_mode = MODE2; + move16(); + BREAK; + } + } + + IF( st->total_brate_fx == 13200 && st->Opt_RF_ON == 1) + { + st->codec_mode = MODE2; + } + + st->last_codec_mode = st->codec_mode; + move16(); + /*-----------------------------------------------------------------* + * Print info on screen + *-----------------------------------------------------------------*/ + /*-----------------------------------------------------------------* + * Print input signal sampling frequency + *-----------------------------------------------------------------*/ + + fprintf(stdout, "Input sampling rate: %d Hz\n", st->input_Fs_fx); + + /*-----------------------------------------------------------------* + * Print bitrate + *-----------------------------------------------------------------*/ + + if ( st->Opt_SC_VBR_fx ) + { + fprintf(stdout, "Average bitrate: %s kbps\n", bit_rate_to_string(bit_rate_string, ACELP_5k90)); + } + else + { + fprintf(stdout, "Bitrate: %s kbps\n", bit_rate_to_string(bit_rate_string, st->total_brate_fx)); + } + + /*-----------------------------------------------------------------* + * Print CNG update interval, if DTX is activated + *-----------------------------------------------------------------*/ + + if ( st->Opt_DTX_ON_fx ) + { + if( st->var_SID_rate_flag_fx ) + { + fprintf(stdout, "DTX: ON, variable CNG update interval\n"); + } + else + { + fprintf(stdout, "DTX: ON, CNG update interval = %d frames\n", st->interval_SID_fx); + } + } + + /*-----------------------------------------------------------------* + * Print channel-aware mode info + *-----------------------------------------------------------------*/ + + if ( st->Opt_RF_ON ) + { + if ( *f_rf == NULL ) + { + fprintf(stdout, "Channel-aware mode: ON, FEC indicator : %s FEC offset: %d \n", (st->rf_fec_indicator==0)?"LO":"HI", st->rf_fec_offset); + } + else + { + fprintf(stdout, "Channel-aware mode: ON, Channel-aware config file name: %s \n", rf_file_name ); + } + + } + + /*-----------------------------------------------------------------* + * Print potential limitation of audio bandwidth + *-----------------------------------------------------------------*/ + switch(st->max_bwidth_fx) + { + case NB: + strncpy(max_bwidth_string, "NB\0", sizeof(max_bwidth_string)); + break; + case WB: + strncpy(max_bwidth_string, "WB\0", sizeof(max_bwidth_string)); + break; + case SWB: + strncpy(max_bwidth_string, "SWB\0", sizeof(max_bwidth_string)); + break; + case FB: + strncpy(max_bwidth_string, "FB\0", sizeof(max_bwidth_string)); + break; + default: + memset(max_bwidth_string, 0, sizeof(max_bwidth_string)); + break; + } + + if ( st->Opt_SC_VBR_fx && !st->Opt_DTX_ON_fx) + { + fprintf(stderr, "\nError: SC-VBR 5900 bit/s not supported without DTX\n\n"); + exit(-1); + } + + if ( (max_bwidth_user != -1) && (st->max_bwidth_fx != max_bwidth_user) ) + { + fprintf(stdout, "\nBandwidth limited to %s.\n", max_bwidth_string); + } + if( (max_bwidth_user == -1) && (st->max_bwidth_fx < FB) && (st->input_Fs_fx == 48000) ) + { + fprintf(stdout, "\nBandwidth limited to %s. To enable FB coding, please use -max_band FB.\n", max_bwidth_string); + } + if( (st->max_bwidth_fx == FB) && (st->total_brate_fx < ACELP_16k40) ) + { + fprintf(stdout, "\nFB coding not supported below %s kbps. ", bit_rate_to_string(bit_rate_string, ACELP_16k40)); + if( st->total_brate_fx < ACELP_9k60 ) + { + fprintf(stdout, "Switching to WB.\n"); + } + else + { + fprintf(stdout, "Switching to SWB.\n"); + } + } + if( (st->max_bwidth_fx == SWB) && (st->total_brate_fx < ACELP_9k60) ) + { + fprintf(stdout, "\nSWB coding not supported below %s kbps. Switching to WB.", bit_rate_to_string(bit_rate_string, ACELP_9k60)); + } + /* in case of 8kHz input sampling or "-max_band NB", require the total bitrate to be below 24.40 kbps */ + if ( ((st->max_bwidth_fx == NB) || (st->input_Fs_fx == 8000)) && (st->total_brate_fx > ACELP_24k40) ) + { + fprintf(stderr, "\nError: Unsupported mode NB %d bit/s, NB mode supports rates 5900-24400 bit/s\n\n", st->total_brate_fx); + exit(-1); + } + + fprintf(stdout, "\n"); + return; +} + +/*---------------------------------------------------------------------* + * read_next_rfparam_fx() + * + * Read next channel aware configuration parameters + * p: RF FEC indicator HI or LO, and + * o: RF FEC offset in number of frame (2, 3, 5, or 7) + *---------------------------------------------------------------------*/ + +void read_next_rfparam_fx( + Word16 *rf_fec_offset, /* o: rf offset */ + Word16 *rf_fec_indicator, /* o: rf FEC indicator */ + FILE* f_rf /* i: file pointer to read parameters */ +) +{ + char rline[10], str[4]; + Word32 tmp; + + /* initialize */ + *rf_fec_offset = 0; + *rf_fec_indicator = 1; + + + if( f_rf != NULL ) + { + + while ( fgets(rline, 10, f_rf) == NULL && feof(f_rf) ) + { + rewind(f_rf); + } + } + else + { + return; + } + + if ( sscanf (rline,"%s %d",str,&tmp) != 2) + { + fprintf(stderr, "Error in the RF configuration file. There is no proper configuration line.\n"); + exit(-1); + } + + /* Read RF FEC indicator */ + if ( strcmp( to_upper(str), "HI" ) == 0 ) + { + *rf_fec_indicator = 1; + } + else if ( strcmp( to_upper(str), "LO" ) == 0 ) + { + *rf_fec_indicator = 0; + } + else + { + fprintf(stderr, " Incorrect FEC indicator string. Exiting the encoder.\n"); + exit(-1); + } + + /* Read RF FEC offset */ + if( tmp == 0 || tmp == 2 || tmp == 3 || tmp == 5 || tmp == 7 ) + { + *rf_fec_offset = (Word16)tmp; + } + else + { + fprintf (stderr,"Error: incorrect FEC offset specified in the RF configration file; RF offset can be 2, 3, 5, or 7. \n"); + exit(-1); + } +} + + + + +/*---------------------------------------------------------------------* + * read_next_brate() + * + * Read next bitrate from profile file (only if invoked on cmd line) + *---------------------------------------------------------------------*/ + +void read_next_brate_fx( + Word32 *total_brate, /* i/o: total bitrate */ + const Word32 last_total_brate, /* i : last total bitrate */ + FILE *f_rate, /* i : bitrate switching profile (0 if N/A) */ + Word32 input_Fs, /* i : input sampling frequency */ + Word16 *Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + Word16 *Opt_SC_VBR, /* i/o: SC-VBR flag */ + Word16 *codec_mode /* i/o: MODE1 or MODE2 */ +) +{ + Word16 j; + + /*The complexity don't need to be taken into account given that is only simulation */ + /* read next bitrate value from the profile file */ + if( f_rate != NULL ) + { + while ( fread( total_brate, 4, 1, f_rate ) != 1 && feof(f_rate) ) + { + rewind(f_rate); + } + } + else + { + *total_brate = last_total_brate; + } + + /* SC-VBR at 5.90 kbps */ + if ( *total_brate == ACELP_5k90 ) + { + *Opt_SC_VBR = 1; + *total_brate = ACELP_7k20; + } + else + { + *Opt_SC_VBR = 0; + } + + /* check if the entered bitrate is supported */ + j = 0; + while ( j < SIZE_BRATE_TBL && *total_brate != brate_tbl[j] ) + { + j++; + } + + /* AMR-WB IO/EVS primary mode determination */ + if ( j >= SIZE_BRATE_TBL ) + { + switch (*total_brate) + { + case ACELP_6k60 : + case ACELP_8k85 : + case ACELP_12k65 : + case ACELP_14k25 : + case ACELP_15k85 : + case ACELP_18k25 : + case ACELP_19k85 : + case ACELP_23k05 : + case ACELP_23k85 : + break; + default : + { + fprintf(stderr, "Error: Incorrect bitrate specification: %d\n\n", *total_brate ); + usage_enc(); + } + break; + } + + *Opt_AMR_WB = 1; + } + else + { + *Opt_AMR_WB = 0; + } + /* in case of 8kHz signal, limit the total bitrate to 24.40 kbps */ + if ( (input_Fs == 8000) && (*total_brate > ACELP_24k40) ) + { + *total_brate = ACELP_24k40; + } + if ( *Opt_AMR_WB ) + { + *codec_mode = MODE1; + } + else + { + switch ( *total_brate ) + { + case 2800: + *codec_mode = MODE1; + move16(); + BREAK; + case 5900: + *codec_mode = MODE1; + move16(); + BREAK; + case 7200: + *codec_mode = MODE1; + move16(); + BREAK; + case 8000: + *codec_mode = MODE1; + move16(); + BREAK; + case 9600: + *codec_mode = MODE2; + move16(); + BREAK; + case 13200: + *codec_mode = MODE1; + move16(); + BREAK; + case 16400: + *codec_mode = MODE2; + move16(); + BREAK; + case 24400: + *codec_mode = MODE2; + move16(); + BREAK; + case 32000: + *codec_mode = MODE1; + move16(); + BREAK; + case 48000: + *codec_mode = MODE2; + move16(); + BREAK; + case 64000: + *codec_mode = MODE1; + move16(); + BREAK; + case 96000: + *codec_mode = MODE2; + move16(); + BREAK; + case 128000: + *codec_mode = MODE2; + move16(); + BREAK; + } + } + + return; +} + +/*---------------------------------------------------------------------* + * read_next_bwidth() + * + * Read next bandwidth from profile file (only if invoked on cmd line) + *---------------------------------------------------------------------*/ + +void read_next_bwidth_fx( + Word16 *max_bwidth, /* i/o: maximum encoded bandwidth */ + FILE *f_bwidth, /* i : bandwidth switching profile (0 if N/A) */ + Word32 *bwidth_profile_cnt, /* i/o: counter of frames for bandwidth switching profile file */ + Word32 input_Fs /* i : input sampling frequency */ +) +{ + int res; + char stmp[4]; + + if ( *bwidth_profile_cnt == 0 ) + { + /* read next bandwidth value and number of frames from the profile file */ + while ( (res = fscanf( f_bwidth, "%d %3s", bwidth_profile_cnt, stmp)) != 2 && feof(f_bwidth)) + { + rewind(f_bwidth); + } + + (*bwidth_profile_cnt)--; + + if (strcmp( to_upper(stmp), "NB") == 0 ) + { + *max_bwidth = NB; + } + else if (strcmp( to_upper(stmp), "WB") == 0 ) + { + *max_bwidth = WB; + } + else if (strcmp( to_upper(stmp), "SWB") == 0 ) + { + *max_bwidth = SWB; + } + else if (strcmp( to_upper(stmp), "FB") == 0 ) + { + *max_bwidth = FB; + } + + /* Prevent max_bwidth from being higher than Fs/2 */ + if ( input_Fs == 8000 && *max_bwidth > NB ) + { + *max_bwidth = NB; + } + else if ( input_Fs == 16000 && *max_bwidth > WB ) + { + *max_bwidth = WB; + } + else if ( input_Fs == 32000 && *max_bwidth > SWB ) + { + *max_bwidth = SWB; + } + + } + else + { + /* current profile still active, only decrease the counter */ + (*bwidth_profile_cnt)--; + } + + return; +} + + + +/*---------------------------------------------------------------------* + * to_upper() + * + * Capitalize all letters of a string. + * (normally, _strupr() function would be used but it does not work in Unix) + *---------------------------------------------------------------------*/ + +static char *to_upper( char *str ) +{ + short i; + + i = 0; + while (str[i] != 0) + { + if (str[i] >= 'a' && str[i] <= 'z') str[i] += 'A' - 'a'; + i++; + } + + return str; +} + +static void usage_enc( void ) +{ + fprintf(stdout, "Usage: EVS_cod.exe [Options] R Fs input_file bitstream_file\n\n"); + + fprintf(stdout, "Mandatory parameters:\n"); + fprintf(stdout, "---------------------\n"); + fprintf(stdout, "R : Bitrate in bps,\n"); + fprintf(stdout, " for EVS native modes R = (5900*, 7200, 8000, 9600, 13200, 16400,\n"); + fprintf(stdout, " 24400, 32000, 48000, 64000, 96000, 128000)\n"); + fprintf(stdout, " *VBR mode (average bitrate),\n"); + fprintf(stdout, " for AMR-WB IO modes R = (6600, 8850, 12650, 14250, 15850, 18250,\n"); + fprintf(stdout, " 19850, 23050, 23850)\n"); + fprintf(stdout, " Alternatively, R can be a bitrate switching file which consists of R values\n"); + fprintf(stdout, " indicating the bitrate for each frame in bit/s. These values are stored in\n"); + fprintf(stdout, " binary format using 4 bytes per value\n"); + fprintf(stdout, "Fs : Input sampling rate in kHz, Fs = (8, 16, 32 or 48)\n"); + fprintf(stdout, "input_file : Input signal filename (*.8k, *.16k, *.32k, *.48k)\n"); + fprintf(stdout, "bitstream_file : Output bitstream filename (*.192)\n\n"); + + fprintf(stdout, "Options:\n"); + fprintf(stdout, "--------\n"); + fprintf(stdout, "-dtx D : Activate DTX mode, D = (0, 3-100) is the SID update rate\n"); + fprintf(stdout, " where 0 = adaptive, 3-100 = fixed in number of frames,\n"); + fprintf(stdout, " default is deactivated\n"); + fprintf(stdout, "-dtx : Activate DTX mode with a SID update rate of 8 frames\n"); + fprintf(stdout, "-rf p o : Activate channel-aware mode for WB and SWB signal at 13.2kbps,\n"); + fprintf(stdout, " where FEC indicator, p: LO or HI, and FEC offset, o: 2, 3, 5, or 7 in number of frames.\n"); + fprintf(stdout, " Alternatively p and o can be replaced by a rf configuration file with each line\n"); + fprintf(stdout, " contains the values of p and o separated by a space.\n"); + fprintf(stdout, " default is deactivated\n"); + fprintf(stdout, "-max_band B : Activate bandwidth limitation, B = (NB, WB, SWB or FB)\n"); + fprintf(stdout, " alternatively, B can be a text file where each line contains\n"); + fprintf(stdout, " \"nb_frames B\"\n"); + fprintf(stdout, "-no_delay_cmp : Turn off delay compensation\n"); + fprintf(stdout, "-mime : Mime output bitstream file format\n"); + fprintf(stdout, " The encoder produces TS26.445 Annex A.2.6 Mime Storage Format, (not RFC4867 Mime Format).\n"); + fprintf(stdout, " default output bitstream file format is G.192\n"); + fprintf(stdout, "-q : Quiet mode, no frame counters\n"); + fprintf(stdout, " default is deactivated\n"); + fprintf(stdout, "\n"); + exit(-1); +} diff --git a/lib_enc/isf_enc_amr_wb_fx.c b/lib_enc/isf_enc_amr_wb_fx.c new file mode 100644 index 0000000..26da8d5 --- /dev/null +++ b/lib_enc/isf_enc_amr_wb_fx.c @@ -0,0 +1,544 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_enc_fx.h" /* Encoder static table prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required by wmc_tool */ + + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +#define DICO1_NS_19b 16 /* codebook dimensions for SID ISF quantizers */ +#define DICO2_NS_19b 16 +#define DICO3_NS_19b 16 +#define DICO4_NS_19b 8 +#define DICO5_NS_19b 16 + +#define DICO1_NS_28b 64 +#define DICO2_NS_28b 64 +#define DICO3_NS_28b 64 +#define DICO4_NS_28b 32 +#define DICO5_NS_28b 32 + +#define N_SURV_MAX 4 /* maximum number of survivors */ + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static void qisf_ns_28b_fx( Encoder_State_fx *st, Word16 *isf ); +static void qisf_2s_46b_fx( Encoder_State_fx *st, Word16 *isf, Word16 nb_surv, Word16 *mem_AR, Word16 *mem_MA ); +static void qisf_2s_36b_fx( Encoder_State_fx *st, Word16 *isf, Word16 nb_surv, Word16 *mem_AR, Word16 *mem_MA ); +static void VQ_stage1_fx(const Word16 *x, const Word16 *dico, const Word16 dim, const Word16 dico_size, Word16 *index, const Word16 surv); +static Word16 sub_VQ_fx(Word16 *x, const Word16 *dico, const Word16 dim, const Word16 dico_size, Word32 *distance); + +/*-------------------------------------------------------------------* + * isf_enc_amr_wb() + * + * Quantization of ISF parameters in AMR-WB IO mode + *-------------------------------------------------------------------*/ + +void isf_enc_amr_wb_fx( + Encoder_State_fx *st, /* i/o: state structure */ + Word16 *isf_new, /* i/o: quantized ISF vector */ + Word16 *isp_new, /* i/o: ISP vector to quantize/quantized */ + Word16 *Aq, /* o : quantized A(z) for 4 subframes */ + Word16 *stab_fac /* o : ISF stability factor */ +) +{ + + + /*---------------------------------* + * ISF quantization of SID frames + *---------------------------------*/ + + IF ( EQ_32(st->core_brate_fx,SID_1k75)) + { + qisf_ns_28b_fx( st, isf_new ); + + reorder_isf_fx( isf_new, ISF_GAP_FX, M, Fs_2); + + E_LPC_isf_isp_conversion( isf_new, isp_new, M); + + /* return if SID frame (conversion to A(z) done in the calling function) */ + return; + } + + /* check resonance for pitch clipping algorithm */ + gp_clip_test_isf_fx( st->core_brate_fx, isf_new, st->clip_var_fx, 1 ); + + /*---------------------------------------* + * ISF quantization of all other frames + *---------------------------------------*/ + + IF ( EQ_32(st->core_brate_fx,ACELP_6k60)) + { + qisf_2s_36b_fx( st, isf_new, 4, st->mem_AR_fx, st->mem_MA_fx ); + } + ELSE IF( GE_32(st->core_brate_fx,ACELP_8k85)) + { + qisf_2s_46b_fx( st, isf_new, 4, st->mem_AR_fx, st->mem_MA_fx ); + } + + reorder_isf_fx( isf_new, ISF_GAP_FX, M, Fs_2 ); + /* convert quantized ISFs back to ISPs */ + E_LPC_isf_isp_conversion( isf_new, isp_new, M); + + /*-------------------------------------------------------------------------------------* + * ISP interpolation + * A(z) calculation + *-------------------------------------------------------------------------------------*/ + + if(st->rate_switching_reset) + { + Copy( isf_new, st->lsf_old_fx, M ); + Copy( isp_new, st->lsp_old_fx, M ); + } + + int_lsp_fx( L_FRAME, st->lsp_old_fx, isp_new, Aq, M, interpol_isp_amr_wb_fx, 1 ); + + /*------------------------------------------------------------------* + * Calculate ISF stability (distance between old ISF and current ISF) + *------------------------------------------------------------------*/ + + *stab_fac = lsf_stab_fx( isf_new, st->lsf_old_fx, 1, L_FRAME ); + + + return; +} + +/*-------------------------------------------------------------------* +* qisf_ns_28b() +* +* ISF quantizer for SID frames (only in AMR-WB IO mode) +*-------------------------------------------------------------------*/ + +static void qisf_ns_28b_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + Word16 *isf /* i/o: unquantized/quantized ISF vector */ +) +{ + Word16 i, indice[5]; + Word32 tmp; + + FOR (i=0; i do not allow */ + + /* write indices to array */ + push_indice_fx( st, IND_ISF_0_0, indice[0], 6 ); + push_indice_fx( st, IND_ISF_0_1, indice[1], 6 ); + push_indice_fx( st, IND_ISF_0_2, indice[2], 6 ); + push_indice_fx( st, IND_ISF_0_3, indice[3], 5 ); + push_indice_fx( st, IND_ISF_0_4, indice[4], 5 ); + + /* decoding the ISFs */ + disf_ns_28b_fx( indice, isf); + + return; +} + + +/*---------------------------------------------------------------------* + * qisf_2s_36b() + * + * ISF quantizer for AMR-WB 6k60 frames + * + * The ISF vector is quantized using two-stage MA-prediction VQ with split-by-2 + * in 1st stage and split-by-3 in the second stage. + *---------------------------------------------------------------------*/ + +static void qisf_2s_36b_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + Word16 *isf, /* i/o: unquantized/quantized ISF vector */ + Word16 nb_surv, /* i : number of survivors (1, 2, 3 or 4) */ + Word16 *mem_AR, /* o : quantizer memory for AR model */ + Word16 *mem_MA /* i/o: quantizer memory for MA model */ +) +{ + Word16 i, k, indice[5], tmp_ind[2]; + Word16 surv1[N_SURV_MAX], tmp16; /* indices of survivors from 1st stage */ + Word32 temp, min_err, distance; + Word16 isf2[M]; + + /*------------------------------------------------------------------------* + * Subtract mean + *------------------------------------------------------------------------*/ + + FOR (i=0; ik; l--) + { + dist_min[l] = dist_min[l - 1]; + move32(); + index[l] = index[l - 1]; + move16(); + } + dist_min[k] = dist; + move32(); + index[k] = i; + move16(); + BREAK; + } + } + } + return; +} + +/*-------------------------------------------------------------------* + * sub_VQ_fx() + * + * Quantization of a subvector in Split-VQ of ISFs + *-------------------------------------------------------------------*/ + +static Word16 sub_VQ_fx( /* o : selected codebook vector index */ + Word16 *x, /* i/o: ISF vector */ + const Word16 *dico, /* i : ISF codebook */ + const Word16 dim, /* i : codebook dimension */ + const Word16 dico_size, /* i : codebook size */ + Word32 *distance /* o : quantization error (min. distance) */ +) +{ + Word32 dist_min, dist; + const Word16 *p_dico; + Word16 i, j, index, temp; + + + dist_min = MAX_32; + move32(); + p_dico = dico; + move16(); + + index = 0; + move16(); + FOR (i = 0; i < dico_size; i++) + { + dist = L_deposit_l(0); + FOR (j = 0; j < dim; j++) + { + /*temp = x[j] - *p_dico++;*/ + temp = sub(x[j], *p_dico++); + /*dist += temp * temp;*/ + dist = L_mac(dist, temp, temp); + } + + IF (LT_32(dist,dist_min)) + { + dist_min = L_add(dist, 0); + index = i; + move16(); + } + } + + *distance = dist_min; + move32(); + + /* Reading the selected vector */ + p_dico = &dico[i_mult2(index, dim)]; + FOR (j = 0; j < dim; j++) + { + x[j] = *p_dico++; + move16(); + } + return index; +} diff --git a/lib_enc/lead_indexing_fx.c b/lib_enc/lead_indexing_fx.c new file mode 100644 index 0000000..fff763a --- /dev/null +++ b/lib_enc/lead_indexing_fx.c @@ -0,0 +1,196 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ + +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "stl.h" /* required for wmc_tool */ + +/*-------------------------------------------------------------------* + * Local function prototypes + *-------------------------------------------------------------------*/ +static Word16 fcb_encode_pos_fx(const Word16 pos_vector[], const Word16 pulse_num, + const Word16 pos_num); + +/*-------------------------------------------------------------------* + * re8_compute_base_index_fx: + * + * Compute base index for RE8 + *-------------------------------------------------------------------*/ +void re8_compute_base_index_fx( + const Word16 *x, /* i : Elemen of Q2, Q3 or Q4 */ + const Word16 ka, /* i : Identifier of the absolute leader related to x */ + UWord16 *I /* o : index */ +) +{ + Word16 i, j, k1 ,m; + Word16 setor_8p[8], setor_8p_temp[8]; + Word16 sign_8p; + Word16 code_level, code_area; + + const Word16 *a1,*a2; + Word16 code_index; + UWord16 offset; + + a1 = vals_a_fx[ka]; + move16(); + a2 = vals_q_fx[ka]; + move16(); + + /* the sign process */ + + sign_8p = 0; + move16(); + m = 0; + move16(); + code_index = 0; + move16(); + k1 = a2[0]; + move16(); + + test(); + test(); + IF (EQ_16(a2[1], 2)&&s_xor(a1[0],1)&&sub(ka,5)) + { + FOR (i=0; i<8; i++) + { + IF (x[i] != 0) + { + sign_8p = shl(sign_8p, 1); + setor_8p_temp[m] = i; + move16(); + m = add(m, 1); + } + + IF (x[i] < 0) + { + sign_8p = add(sign_8p, 1); + } + } + + code_index = fcb_encode_pos_fx(setor_8p_temp,8,m); + code_index = add(shl(code_index,k1),sign_8p); + + offset = Is_fx[ka]; + move16(); + + *I = extract_l(L_add(offset, (Word32) code_index)); + } + ELSE + { + FOR (i=0; i<8; i++) + { + setor_8p[i] = abs_s(x[i]); + + IF (x[i] != 0) + { + sign_8p = shl(sign_8p, 1); + m = add(m, 1); + } + + IF (x[i] < 0) + { + sign_8p = add(sign_8p, 1); + } + } + + IF (NE_16(k1, m)) + { + sign_8p = shr(sign_8p, 1); + } + + /* code level by level */ + + code_level = sub(a2[1], 1); + code_area = 8; + move16(); + + IF (NE_16(a2[2], 1)) + { + FOR (j=0; jini_frame_fx, 4 )) + + { + + st_fx->lp_noise_fx = st_fx->totalNoise_fx; + move16(); + tmp = add(st_fx->lp_noise_fx, 2560); /*10.0 in Q8*/ + st_fx->lp_speech_fx = s_max(st_fx->lp_speech_fx, tmp); + } + ELSE + { + /* if ( st->ini_frame < 150 ) { + st->lp_noise = 0.95f * st->lp_noise + 0.05f * st->totalNoise; + } else { + st->lp_noise = 0.98f * st->lp_noise + 0.02f * st->totalNoise; + } */ + alpha = 655; + move16();/* 0.02 Q15 */ + if ( LT_16(st_fx->ini_frame_fx, 150)) /* should match HE_LT_CNT_INIT_FX */ + { + alpha = 1638 ; + move16(); /* 0.05 Q15 */ + } + st_fx->lp_noise_fx = noise_est_AR1_Qx( st_fx->totalNoise_fx, st_fx->lp_noise_fx , alpha); /* Q8 state, alpha in Q15 */ + + test(); + IF ( (localVAD_HE_SAD != 0) + && ( high_lpn_flag == 0) ) + { + IF( LT_16(sub(st_fx->lp_speech_fx, Etot ), 10*256 )) /* 10.0 in Q8 */ + { + /* st->lp_speech = 0.98f * st->lp_speech + 0.02f * Etot; */ + st_fx->lp_speech_fx = noise_est_AR1_Qx(Etot, st_fx->lp_speech_fx, 655); /* Q8 state, 0.02 in Q15 */ + } + ELSE + { + st_fx->lp_speech_fx = sub(st_fx->lp_speech_fx, 13); /* st->lp_speech = st->lp_speech - 0.05f; linear decay*/ + } + } + + } + + + /*-----------------------------------------------------------------* + * Initialize parameters for energy tracking and signal dynamics + *-----------------------------------------------------------------*/ + return; +} diff --git a/lib_enc/lp_exc_e_fx.c b/lib_enc/lp_exc_e_fx.c new file mode 100644 index 0000000..c763242 --- /dev/null +++ b/lib_enc/lp_exc_e_fx.c @@ -0,0 +1,417 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "basop_util.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define GAIN_PIT_MAX 19661 +#define HIGH_LTP_LIMIT 1.0f +#define LOW_LTP_LIMIT 0.55f + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static Word16 adpt_enr_fx(const Word16 codec_mode, const Word16 *exc, const Word16 *h1, Word16 *y1, const Word16 L_subfr, + Word16 *gain, Word16 *g_corr, const Word16 clip_gain, const Word16 *xn, Word16 *xn2, Word16 *exp_ener + ,Word16 use_prev_sf_pit_gain + ); + +/*-------------------------------------------------------------------* + * function lp_filt_exc_enc_fx() + * + * Low-pass filtering of the adaptive excitation + * Innovation target construction + * Gain quantization limitation + *-------------------------------------------------------------------*/ + +Word16 lp_filt_exc_enc_fx( + const Word16 codec_mode, /* i : MODE1 or MODE2 Q0 */ + const Word32 core_brate, /* i : core bitrate Q0 */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode Q0 */ + const Word16 coder_type, /* i : coding type Q0 */ + const Word16 i_subfr, /* i : subframe index Q0 */ + Word16 *exc, /* i/o: pointer to excitation signal frame Q_new */ + const Word16 *h1, /* i : weighted filter input response Q(14+shift) */ + const Word16 *xn, /* i : target vector Q_new-1+shift */ + Word16 *y1, /* o : zero-memory filtered adaptive excitation Q_new-1+shift */ + Word16 *xn2, /* o : target vector for innovation search Q_new-1+shift */ + const Word16 L_subfr, /* i : length of vectors for gain quantization Q0 */ + const Word16 L_frame, /* i : frame size Q0 */ + Word16 *g_corr, /* o : ACELP correlation values mant/exp */ + const Word16 clip_gain, /* i : adaptive gain clipping flag Q0 */ + Word16 *gain_pit, /* o : adaptive excitation gain Q14 */ + Word16 *lp_flag /* i/o: mode selection Q0 */ +) +{ + Word16 gain1, gain2, g_corr2[4], exc_tmp[5*L_SUBFR], xn2_tmp[5*L_SUBFR]; + Word16 y1_tmp[5*L_SUBFR]; + Word16 select, i, exp_ener, exp_ener1; + Word16 wtmp, wtmp1; + Word32 Ltmp; + + Word16 use_prev_sf_pit_gain = 0; + + gain1 = 0; + move16(); + gain2 = 0; + move16(); + + /*-----------------------------------------------------------------* + * Select LP filtering flag + *-----------------------------------------------------------------*/ + + IF ( EQ_16(codec_mode,MODE1)) + { + test(); + test(); + test(); + test(); + IF ( ( Opt_AMR_WB || EQ_16(coder_type,GENERIC)||EQ_16(coder_type,TRANSITION))&<_32(core_brate,ACELP_11k60)) + { + *lp_flag = LOW_PASS; + move16(); + } + ELSE IF ( GE_32(core_brate,ACELP_11k60)&&NE_16(coder_type,AUDIO)) + { + *lp_flag = NORMAL_OPERATION; + move16(); + } + ELSE + { + *lp_flag = FULL_BAND; + move16(); + } + + } + + /*----------------------------------------------------------------* + * Find the target energy if the adaptive exc. is not filtered + *----------------------------------------------------------------*/ + test(); + IF( EQ_16(codec_mode,MODE2)&&EQ_16(coder_type,100)) + { + use_prev_sf_pit_gain = 1; + } + exp_ener = 0; + move16(); + wtmp = 0; + move16(); + test(); + IF( EQ_16(*lp_flag,FULL_BAND)||EQ_16(*lp_flag,NORMAL_OPERATION)) + { + wtmp = adpt_enr_fx( codec_mode, &exc[i_subfr], h1, y1, L_subfr, &gain1, g_corr, clip_gain, xn, xn2, &exp_ener, use_prev_sf_pit_gain); + move16(); + + } + + /*----------------------------------------------------------------* + * Filter the adaptive excitation + * Find the target energy if the adapt. exc. is filtered + *----------------------------------------------------------------*/ + + exp_ener1 = 0; + move16(); + wtmp1 = 0; + move16(); + test(); + IF( (EQ_16(*lp_flag,LOW_PASS))||(EQ_16(*lp_flag,NORMAL_OPERATION))) + { + test(); + IF( EQ_16(codec_mode,MODE2)&&EQ_16(L_frame,L_FRAME16k)) + { + FOR ( i=0; i and -2 ) + *-------------------------------------------------------------------*/ + +Word16 corr_xy1_fx( /* o : pitch gain (0..GAIN_PIT_MAX) */ + const Word16 xn_1[], /* i : target signal */ + const Word16 y1_1[], /* i : filtered adaptive codebook excitation */ + Word16 g_corr[], /* o : correlations and -2 */ + const Word16 L_subfr, /* i : vector length */ + const Word16 norm_flag /* i : flag for constraining pitch contribution */ +) +{ + Word16 i; + Word16 tmp, xx, xy, yy, exp_xy, exp_xx, exp_yy, exp_div, gain, gain_p_snr; + Word32 Ltmp1, Ltmp2; + Word16 xn[L_FRAME16k], y1[L_FRAME16k]; + + /*----------------------------------------------------------------* + * Find the ACELP correlations and the pitch gain + *----------------------------------------------------------------*/ + + /* Compute scalar product */ + Copy(xn_1, xn, L_subfr); + Copy(y1_1, y1, L_subfr); + Overflow = 0; + move16(); + Ltmp1 = Dot_product12(y1, y1, L_subfr, &exp_yy); + + IF( Overflow ) + { + FOR(i = 0; i < L_subfr; i++) + { + xn[i] = mult_r(xn_1[i], 4096); + move16(); + y1[i] = mult_r(y1_1[i], 4096); + move16(); + } + + Ltmp1 = Dot_product12(y1, y1, L_subfr, &exp_yy); + exp_yy = add(exp_yy, 6); + yy = extract_h(Ltmp1); + + /* Compute scalar product */ + Ltmp2 = Dot_product12(xn, y1, L_subfr, &exp_xy); + xy = extract_h(Ltmp2); + exp_xy = add(exp_xy, 6); + + g_corr[0] = yy; + move16(); + g_corr[1] = exp_yy; + move16(); + /* -2.0*temp1 + 0.01 is done in Gain_enc_2 function */ + g_corr[2] = xy; + move16(); + g_corr[3] = exp_xy; + move16(); + } + ELSE + { + yy = extract_h(Ltmp1); + /* Ltmp1 = L_shr(Ltmp1, sub(30, exp_yy));*/ + + /* Compute scalar product */ + Ltmp2 = Dot_product12(xn, y1, L_subfr, &exp_xy); + xy = extract_h(Ltmp2); + /* Ltmp2 = L_shr(Ltmp2, sub(30, exp_xy));*/ + + g_corr[0] = yy; + move16(); + g_corr[1] = exp_yy; + move16(); + /* -2.0*temp1 + 0.01 is done in Gain_enc_2 function*/ + g_corr[2] = xy; + move16(); + g_corr[3] = exp_xy; + move16(); + } + + /* find pitch gain and bound it by [0,GAIN_PIT_MAX] */ + test(); + IF ( xy >= 0 && NE_16(s_or(yy, xy), 16384)) + { + /* compute gain = xy/yy */ + xy = shr(xy, 1); /* be sure that xy < yy */ + gain = div_s(xy, yy); + i = sub(exp_xy, exp_yy); + gain = shl(gain, i); /* saturation can occur here */ + + gain = s_max(gain, 0); + gain = s_min(gain, GAIN_PIT_MAX); /* 1.2 in Q14 */ + } + ELSE + { + gain = 0; + move16(); + } + + /* Limit the energy of pitch contribution */ + IF (norm_flag) + { + /* Compute scalar product */ + xx = round_fx(Dot_product12_offs(xn, xn, L_subfr, &exp_xx, 1)); + + /* gain_p_snr = sqrt(/) */ + tmp = BASOP_Util_Divide1616_Scale(xx, yy, &exp_div); + exp_xx = add(sub(exp_xx, exp_yy), exp_div); + tmp = Sqrt16(tmp, &exp_xx); + + /* Note: shl works as shl or shr. */ + exp_xx = sub(exp_xx,1); + BASOP_SATURATE_WARNING_OFF + gain_p_snr = round_fx(L_shl(Mpy_32_16_1( 1717986944l/*ACELP_GAINS_CONST Q31*/, tmp), exp_xx)); + BASOP_SATURATE_WARNING_ON + + gain = s_min(gain, gain_p_snr); + } + + return gain; +} diff --git a/lib_enc/lsf_enc_fx.c b/lib_enc/lsf_enc_fx.c new file mode 100644 index 0000000..ca2de53 --- /dev/null +++ b/lib_enc/lsf_enc_fx.c @@ -0,0 +1,2350 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "rom_enc_fx.h" +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "prot_fx.h" + + + +/*-----------------------------------------------------------------* +* Local constants +*-----------------------------------------------------------------*/ +#define MIN_LOG_FX 0 +#define MIN_LOG_VAL_FX -15360 /* -60.0f in Q8 */ +#define MSVQ_MAXCNT 3000 +#define MAXINT32 MAX_32 + +/*---------------------------------------------------------------------* +* Local functions +*---------------------------------------------------------------------*/ + +static void lsfq_CNG_fx( Encoder_State_fx *st_fx, const Word16 *lsf, const Word16 *wghts, Word16 *qlsf, Word32 *p_offset_scale1, Word32 * p_offset_scale2, + Word16 * p_no_scales ); + +static Word32 vq_lvq_lsf_enc( Word16 pred_flag, Word16 mode, Word16 u[], Word16 * levels, Word16 stages, Word16 w[], Word16 Idx[], const Word16 * lsf, + const Word16 * pred, Word32 p_offset_scale1[][MAX_NO_SCALES+1], Word32 p_offset_scale2[][MAX_NO_SCALES+1], + Word16 p_no_scales[][2], Word16 *resq, Word16 * lsfq ); + +static void lsf_mid_enc_fx( Encoder_State_fx *st_fx,const Word16 int_fs, const Word16 qisp0[], const Word16 qisp1[], Word16 isp[], const Word16 coder_type, + const Word16 bwidth, const Word32 core_brate, Word32 Bin_Ener_old[], Word32 Bin_Ener[], Word16 Q_ener, Word16 ppp_mode, Word16 nelp_mode ); + + +/*===========================================================================*/ +/* FUNCTION : lsf_enc_fx() */ +/*---------------------------------------------------------------------------*/ +/* PURPOSE : Quantization of LSF vector */ +/*---------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) L_frame : length of the frame */ +/* _ (Word16) coder_type : coding type */ +/*---------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) Aq : LP filter coefficient Q12 */ +/* _ (Word16*) lsf_ne w : LP filter coefficient Q(x2.56) */ +/* _ (Word16) st_fx->stab_fac_fx : LSF stability factor Q15 */ +/*---------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Struct) st_fx : state structure */ +/* _ (Word16*) lsp_new : LP filter coefficient Q15 */ +/* _ (Word16*) lsp_mid : LP filter coefficient Q15 */ +/* _ (Word16[]) st_fx->mem_AR_fx : AR memory of LSF quantizer */ +/* (past quantized LSFs without mean) x2.56 */ +/* _ (Word16[]) st_fx->clip_var_fx : pitch gain clipping memory x2.56*/ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*===========================================================================*/ +void lsf_enc_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + Word16 *lsf_new, /* o : quantized LSF vector */ + Word16 *lsp_new, /* i/o: LSP vector to quantize/quantized */ + Word16 *lsp_mid, /* i/o : mid-frame LSP vector */ + Word16 *Aq, /* o : quantized A(z) for 4 subframes */ + Word16 *stab_fac, /* o : LSF stability factor */ + const Word16 Nb_ACELP_frames, + const Word16 Q_new +) +{ + Word16 nBits = 0; + Word16 int_fs; + Word16 force_sf = 0; + Word16 fec_lsf[M], stab; + Word16 i; + Word32 L_tmp; + + /* initialize */ + int_fs = INT_FS_16k_FX; + move16(); + if( EQ_16(L_frame, L_FRAME)) + { + int_fs = INT_FS_FX; + move16(); + } + + /* convert LSPs to LSFs */ + lsp2lsf_fx( lsp_new, lsf_new, M, int_fs); + + /* check resonance for pitch clipping algorithm */ + gp_clip_test_lsf_fx( lsf_new, st_fx->clip_var_fx, 0 ); + + /* Find the number of bits for LSF quantization */ + IF ( EQ_32(st_fx->core_brate_fx, SID_2k40)) + { + nBits = LSF_BITS_CNG; + move16(); + } + ELSE + { + test(); + IF ( (st_fx->nelp_mode_fx == 0) && (st_fx->ppp_mode_fx == 0) ) + { + nBits = LSF_bits_tbl[LSF_BIT_ALLOC_IDX_fx(st_fx->core_brate_fx, coder_type)]; + move16(); + } + ELSE IF ( EQ_16(st_fx->nelp_mode_fx, 1)) + { + nBits = 30; + move16(); + + if ( EQ_16(st_fx->bwidth_fx,NB)) + { + nBits = 32; + move16(); + } + } + ELSE IF ( EQ_16(st_fx->ppp_mode_fx, 1)) + { + nBits = 26; + move16(); + } + } + + /* first three ACELP frames after an HQ frame shall be processed only with safety-net quantizer */ + if( (LT_16(Nb_ACELP_frames, 3))) + { + force_sf = 1; + move16(); + } + + /* in case of unstable filter in decoder FEC, choose safety-net to help FEC */ + IF ( EQ_16(st_fx->next_force_safety_net_fx ,1)) + { + force_sf = 1; + move16(); + st_fx->next_force_safety_net_fx = 0; + move16(); + } + + /*-------------------------------------------------------------------------------------* + * Frame end LSF quantization + *-------------------------------------------------------------------------------------*/ + + lsf_end_enc_fx( st_fx, lsf_new, lsf_new, st_fx->mem_AR_fx, st_fx->mem_MA_fx, nBits, coder_type, st_fx->bwidth_fx, + st_fx->Bin_E_fx, Q_new+QSCALE-2, int_fs, st_fx->core_brate_fx, &st_fx->streaklimit_fx, &st_fx->pstreaklen_fx, + force_sf, 0, 0, NULL, NULL, NULL, st_fx->coder_type_raw_fx ); + + /* convert quantized LSFs back to LSPs */ + lsf2lsp_fx( lsf_new, lsp_new, M, int_fs); + + test(); + IF ( EQ_16(st_fx->last_core_fx, HQ_CORE)&&EQ_16(st_fx->core_fx,ACELP_CORE)) + { + /* don't use old LSF values if this is the first ACELP frame after HQ frames */ + Copy( lsf_new, st_fx->lsf_old_fx, M ); + } + IF ( EQ_32(st_fx->core_brate_fx, SID_2k40)) + { + /* return if SID frame (conversion to A(z) done in the calling function) */ + return; + } + + /*-------------------------------------------------------------------------------------* + * FEC - enforce safety-net in the next frame in case of unstable filter + *-------------------------------------------------------------------------------------*/ + + IF( NE_16(st_fx->last_L_frame_fx, st_fx->L_frame_fx)) + { + /* FEC - in case of core switching, use old LSFs */ + Copy( st_fx->lsf_old_fx, st_fx->lsfoldbfi1_fx, M ); + Copy( st_fx->lsf_old_fx, st_fx->lsfoldbfi0_fx, M ); + Copy( st_fx->lsf_old_fx, st_fx->lsf_adaptive_mean_fx, M ); + } + + FEC_lsf_estim_enc_fx( st_fx, st_fx->L_frame_fx, fec_lsf ); + + /* in case of FEC in decoder - calculate LSF stability */ + stab = lsf_stab_fx( lsf_new, fec_lsf, 0, st_fx->L_frame_fx ); + + test(); + test(); + test(); + /* If decoder FEC frame may be unstable force safety-net usage */ + IF ( (EQ_16(st_fx->L_frame_fx, L_FRAME16k))&&(LT_16(stab,STAB_FAC_LIMIT_FX))&&(EQ_16(coder_type,GENERIC))) + { + st_fx->next_force_safety_net_fx = 1; + move16(); + } + ELSE IF((LT_16(stab, STAB_FAC_LIMIT_FX))&&(EQ_16(st_fx->clas_fx,VOICED_CLAS)||(LT_16(st_fx->clas_fx,VOICED_CLAS)&&EQ_16(coder_type,AUDIO)))) + { + st_fx->next_force_safety_net_fx = 1; + move16(); + } + + + /* FEC - update adaptive LSF mean vector */ + FOR (i=0; ilsfoldbfi1_fx[i], 10922); /*Q(x2.56+16)*/ + L_tmp = L_mac(L_tmp, st_fx->lsfoldbfi0_fx[i], 10922); /*Q(x2.56+16)*/ + st_fx->lsf_adaptive_mean_fx[i] = round_fx(L_tmp); /*Q(x2.56)*/ + } + + /* FEC - update LSF memories */ + Copy( st_fx->lsfoldbfi0_fx, st_fx->lsfoldbfi1_fx, M ); + Copy( lsf_new, st_fx->lsfoldbfi0_fx, M ); + + + /*-------------------------------------------------------------------------------------* + * Mid-frame LSF encoding + * LSP interpolation and conversion of LSPs to A(z) + *-------------------------------------------------------------------------------------*/ + if(st_fx->rate_switching_reset) + { + /*extrapolation in case of unstable LSF convert*/ + Copy( lsp_new, st_fx->lsp_old_fx, M ); + Copy( lsf_new, st_fx->lsf_old_fx, M ); + } + /* Mid-frame LSF encoding */ + lsf_mid_enc_fx( st_fx, int_fs, st_fx->lsp_old_fx, lsp_new, lsp_mid, coder_type, st_fx->bwidth_fx, st_fx->core_brate_fx, st_fx->Bin_E_old_fx, st_fx->Bin_E_fx, Q_new+QSCALE-2, st_fx->ppp_mode_fx, st_fx->nelp_mode_fx); + + test(); + IF ( EQ_16(st_fx->last_core_fx,HQ_CORE)&&EQ_16(st_fx->core_fx,ACELP_CORE)) + { + /* don't use old LSP/LSF values if this is the first ACELP frame after HQ frames */ + Copy( lsp_mid, st_fx->lsp_old_fx, M ); + lsp2lsf_fx( lsp_mid, st_fx->lsf_old_fx, M, int_fs ); + } + + /* LSP interpolation and conversion of LSPs to A(z) */ + int_lsp4_fx( L_frame, st_fx->lsp_old_fx, lsp_mid, lsp_new, Aq, M, 0 ); + + /*------------------------------------------------------------------* + * Check LSF stability (distance between old LSFs and current LSFs) + *------------------------------------------------------------------*/ + *stab_fac = lsf_stab_fx( lsf_new, st_fx->lsf_old_fx, 0, st_fx->L_frame_fx ); + + return; +} + + +/*-------------------------------------------------------------------* +* lsfq_CNG_fx() +* +* LSF quantizer for SID frames (uses 29 bits, 4 for VQ, 25 for LVQ) +* Note: +* The sampling frequency of the LP-CNG frame can be determined by checking the value of the highest order LSF +* coefficient (last coefficient of lsf). If the last LSF coefficient (lsf[M-1]) is larger than 6350 +* the decoded frame is WB2 with sampling rate of 16 kHz, otherwise it is sampled at 12.8kHz and contains +* either NB or WB LSF data. +*-------------------------------------------------------------------*/ + +static void lsfq_CNG_fx( + Encoder_State_fx *st_fx, + const Word16 *lsf, /*x2.56 unquantized LSF vector */ + const Word16 *wghts, /*Q10 LSF weights */ + Word16 *qlsf, /*x2.56 quantized LSF vecotor */ + Word32 *p_offset_scale1, + Word32 *p_offset_scale2, + Word16 *p_no_scales +) +{ + Word16 i, j, idx_cv, idx_lvq[3]; + Word32 min_dist, dist; + Word16 dd[M], ddq[M]; + const Word16 *p_cb; + Word16 first_cb, last_cb; + Word16 idx_lead_cng[2], idx_scale_cng[2]; + Word16 tmp; + + idx_cv = 0; + move16(); + + /* quantize first stage with 4 bits + The sampling frequency of the LP-CNG frame can be determined by checking the value of the highest order LSF + coefficient (last coefficient of lsf). If the last LSF coefficient (lsf[M-1]) is larger than 6350 + the decoded frame is WB2 with sampling rate of 16 kHz, otherwise it is sampled at 12.8kHz and contains + either NB or WB LSF data. */ + IF(GT_16(lsf[M - 1], WB_LIMIT_LSF_FX)) /* 16kHz sampled LSF vector*/ + { + p_cb = &CNG_SN1_fx[0]; + move16(); + first_cb = 0; + move16(); + last_cb = 6; + move16(); + } + ELSE /* 12.8kHz sampled LSF vector*/ + { + p_cb = &CNG_SN1_fx[6*M]; + move16(); + first_cb = 6; + move16(); + last_cb = M; + move16(); + } + + + min_dist = L_add(MAXINT32, 0); + FOR ( i = first_cb; i < last_cb; i++ ) + { + tmp = sub(*p_cb,shl(lsf[0],1)); /*x2.56 */ + dist = Mult_32_16(L_mult0(wghts[0], *p_cb),tmp); /*Q8 + x2.56 -Q15 + x2.56 = Q-7 + x2.56+x.256 */ + p_cb++; + FOR (j=1; joffset_scale1_fx[0][0], &st->offset_scale2_fx[0][0], &st->no_scales_fx[0][0] ); + sort_fx( qlsf, 0, M-1 ); + reorder_lsf_fx( qlsf, MODE1_LSF_GAP_FX, M, int_fs ); + + return; + } + /* Find allowed predictor mode for current coder_type. (SN only (0), SN/AR switched (2) or MA predictive (1) */ + predmode = find_pred_mode(coder_type, bwidth, int_fs, &mode_lvq, &mode_lvq_p,st->total_brate_fx); + + /*----------------------------------------------------------------* + * Calculate number of stages and levels for each stage based on the allowed bit allocation + * (subtract one bit for LSF predictor selection) + *----------------------------------------------------------------*/ + lsf_allocate_fx( sub(nBits, shr(predmode,1)), mode_lvq, mode_lvq_p, &stages0, &stages1, levels0, levels1, bits0, bits1); + + + /*--------------------------------------------------------------------------------* + * LSF quantization of all other frames but SID frames + * Select safety-net or predictive mode + *--------------------------------------------------------------------------------*/ + + Err[0] = MAXINT32; + move32(); + Err[1] = MAXINT32; + move32(); + /* for mem_MA update */ + FOR (i=0; ioffset_scale1_fx,st->offset_scale2_fx, st->no_scales_fx, resq, lsfq); + safety_net = 1; + move16(); + *pstreaklen = 0; + move16();/* predictive LSF quantizer streak is ended with safety-net */ + } + ELSE IF (EQ_16(predmode, 1)) /* only MA prediction */ + { + Vr_subt(lsf, pred1, Tmp1, M); + Err[1] = vq_lvq_lsf_enc(2, mode_lvq_p, Tmp1, levels1, stages1, wghts, Idx1, lsf, pred1, + st->offset_scale1_p_fx,st->offset_scale2_p_fx,st->no_scales_p_fx,resq, lsfq ); + + safety_net = 0; + move16(); + } + ELSE + { + /* Adaptive scaling factor (multiplier) is updated in order to reduce the amount of consecutive predictive frames in + case of possible frame erasure. AR-predictive usage for VOICED mode is allowed to be higher than other modes. */ + test(); + test(); + test(); + IF ( ((GT_16(*pstreaklen, (STREAKLEN+3)))&&(EQ_16(coder_type,VOICED)))||((GT_16(*pstreaklen,(STREAKLEN)))&&(NE_16(coder_type,VOICED)))) + { + /* update the adaptive scaling factor to become smaller with increasing number of concecutive predictive frames. */ + *streaklimit = mult(*streaklimit,STREAKMULT_FX); + move16(); + } + + IF ( *pstreaklen == 0 ) + { + /* reset the consecutive AR-predictor multiplier */ + *streaklimit = 32767; /*1.0 in Q15 */ move16(); + } + + /* VOICED_WB@16kHz */ + test(); + IF ( EQ_32(int_fs, INT_FS_16k)&&EQ_16(coder_type,VOICED)) + { + /* Subtract mean and AR prediction */ + Copy( ModeMeans_fx[mode_lvq], pred0, M ); + /* subtract only mean */ + Vr_subt(lsf, pred0, Tmp, M); + + FOR (i = 0; i < M; i++) + { + /* subtract mean and AR prediction */ + pred2[i] = mult(Predictors_fx[mode_lvq_p][i],sub(mem_AR[i],pred0[i])); + Tmp2[i] = sub(Tmp[i], pred2[i]); + pred2[i] = add(pred2[i], pred0[i]); + } + + /* select safety_net or predictive */ + safety_net = qlsf_Mode_Select_fx( wghts, Tmp2, *streaklimit, OP_LOOP_THR_HVO ); + IF ( EQ_16(force_sf, 1)) + { + safety_net = 1; + move16(); + } + + IF ( safety_net ) + { + /* Safety-net - BC-TCQ quantization : SN */ + Err[0] = qlsf_ARSN_tcvq_Enc_16k_fx( Tmp, lsfq, TCQIdx0, wghts, sub(nBits,1), safety_net); + *pstreaklen = 0; + move16(); + } + ELSE + { + /* predictive - BC-TCQ quantization : AR */ + Err[1] = qlsf_ARSN_tcvq_Enc_16k_fx( Tmp2, lsfq, TCQIdx0, wghts, sub(nBits,1), safety_net); + *pstreaklen=add(*pstreaklen,1); + } + } + /* all other frames (not VOICED@16kHz) */ + ELSE + { + /* Subtract mean and AR prediction */ + Copy( ModeMeans_fx[mode_lvq], pred0, M ); + /* subtract only mean */ + Vr_subt(lsf, pred0, Tmp, M); + + FOR (i = 0; i < M; i++) + { + /* subtract mean and AR prediction */ + pred2[i] = add(pred0[i],mult(Predictors_fx[mode_lvq_p][i],sub(mem_AR[i],pred0[i]))); + Tmp2[i] = sub(lsf[i], pred2[i]); + } + + /* safety-net */ + Err[0] = vq_lvq_lsf_enc(0, mode_lvq, Tmp, levels0, stages0, wghts, Idx0, lsf, pred0, + st->offset_scale1_fx,st->offset_scale2_fx,st->no_scales_fx, resq, lsfq); + /* Predictive quantizer is calculated only if it can be selected */ + test(); + IF (!force_sf || GT_32(Err[0],abs_threshold)) + { + Err[1] = vq_lvq_lsf_enc(2, mode_lvq_p, Tmp2, levels1, stages1, wghts, Idx1, lsf, pred2, + st->offset_scale1_p_fx, st->offset_scale2_p_fx, st->no_scales_p_fx, &resq[M], &lsfq[M]); + + } + test(); + test(); + /* Select whether to use safety-net (non-predictive) or predictive LSF quantizer. The decision is based on following: + if the non-predictive (safety-net) quantization error (Err[0]) is low enough (spectral distortion is low) it is selected + or if the predictively quantized error (Err[1]) is by at least adaptive margin smaller than non-predictive quantizer. + or if the in case of frame erasure the resulting concealed predictive LSF would be unstable safety-net is selected */ + IF ( force_sf || LT_32(Mult_32_16(Err[0],(*streaklimit)),L_add(Err[1],Mult_32_16(Err[1],PREFERSFNET_FX)))||LT_32(Err[0],abs_threshold)) + { + safety_net = 1; + move16(); + *pstreaklen = 0; + move16(); /* Reset the consecutive predictive frame counter */ + } + ELSE + { + safety_net = 0; + move16(); /* Increase the consecutive predictive frame counter by one */ + *pstreaklen=add(*pstreaklen,1); + } + } + } + /*--------------------------------------------------------------------------* + * Write indices to array + *--------------------------------------------------------------------------*/ + + IF (mode2_flag == 0) + { + /* write coder_type bit for VOICED@16kHz or GENERIC@16kHz */ + test(); + IF(EQ_16(coder_type_org, GENERIC)&&EQ_32(int_fs,INT_FS_16k)) + { + /* VOICED =2 and GENERIC=3, so "coder_type-2" means VOICED =0 and GENERIC=1*/ + push_indice_fx( st, IND_LSF_PREDICTOR_SELECT_BIT, sub(coder_type,2), 1 ); + } + + /* write predictor selection bit */ + IF ( EQ_16(predmode, 2)) + { + push_indice_fx( st, IND_LSF_PREDICTOR_SELECT_BIT, safety_net, 1 ); + } + + test(); + IF ( EQ_16(coder_type, VOICED)&&EQ_32(int_fs,INT_FS_16k)) + { + /* BC-TCVQ (only for VOICED@16kHz) */ + TCQIdx = &TCQIdx0[1]; + Bit_alloc1 = &BC_TCVQ_BIT_ALLOC_40B[1]; + FOR( i=0; i<(M/2)+3; i++ ) + { + push_indice_fx( st, IND_LSF, TCQIdx[i], Bit_alloc1[i]); + } + } + ELSE + { + cumleft = nBits; + move16(); + IF (EQ_16( predmode, 2 )) + { + /* subtract predictor selection bit */ + cumleft = sub(nBits, 1); + } + + IF ( safety_net ) + { + stages = stages0; + move16(); + Idx = Idx0; + move16(); + bits = bits0; + move16(); + } + ELSE + { + stages = stages1; + move16(); + Idx = Idx1; + move16(); + bits = bits1; + move16(); + } + + tmp = sub(stages,1); + FOR ( i=0; i 0 ) + { + indice[i] = Idx[i]; + move16(); + + IF ( GT_16(cumleft, LEN_INDICE)) + { + num_bits = LEN_INDICE; + move16(); + } + ELSE + { + num_bits = cumleft; + move16(); + } + + cumleft = sub(cumleft, num_bits); + push_indice_fx( st, IND_LSF, indice[i], num_bits ); + i=add(i,1); + } + } + } + ELSE + { + test(); + IF ( EQ_16(coder_type, VOICED)&&EQ_32(int_fs,INT_FS_16k)) + { + /* BC-TCVQ (only for VOICED@16kHz) */ + /* Number of quantization indices */ + *no_indices = 10; + move16(); + FOR(i=0; i<*no_indices; i++) + { + lpc_param[i] = TCQIdx0[i]; + move16(); + bits_param_lpc[i] = BC_TCVQ_BIT_ALLOC_40B[i]; + move16(); + } + } + ELSE + { + /* Number of quantization indices */ + + /* there are 31 bits */ + IF (EQ_16(safety_net, 1)) + { + Idx = Idx0; + move16(); + *no_indices = add(stages0 ,1); + FOR( i=0; i0; i--) + { + tmp = sub(i,1); + lpc_param[i] = lpc_param[tmp]; + move16(); + bits_param_lpc[i] = bits_param_lpc[tmp]; + move16(); + } + lpc_param[0] = safety_net; + move16();/* put the safety net info on the last param */ + bits_param_lpc[0] = 1; + move16(); + *no_indices = add(*no_indices,1); + } + } + } + + + /*--------------------------------------------------------------------------* + * De-quantize encoded LSF vector + *--------------------------------------------------------------------------*/ + + IF ( safety_net ) + { + /* Safety-net */ + test(); + IF ( EQ_16(coder_type, VOICED)&&EQ_32(int_fs,INT_FS_16k)) + { + /* BC-TCQ */ + Copy( lsfq, mem_MA, M ); + Vr_add( lsfq, pred0, qlsf, M ); + } + ELSE + { + vq_dec_lvq_fx( 1, qlsf, &indice[0], stages0, M, mode_lvq, levels0[stages0-1], + &st->offset_scale1_fx[0][0], &st->offset_scale2_fx[0][0], &st->offset_scale1_p_fx[0][0], &st->offset_scale2_p_fx[0][0], + &st->no_scales_fx[0][0], &st->no_scales_p_fx[0][0] ); + + Vr_add( qlsf, pred0, qlsf, M ); + Vr_subt(qlsf, pred1,mem_MA, M); + } + } + ELSE + { + test(); + IF ( EQ_16(coder_type, VOICED)&&EQ_32(int_fs,INT_FS_16k)) + { + /* BC-TCVQ */ + Copy( lsfq, mem_MA, M ); + Vr_add( lsfq, pred2, qlsf, M ); + } + ELSE + { + /* LVQ */ + vq_dec_lvq_fx( 0, qlsf, &indice[0], stages1, M, mode_lvq_p, levels1[stages1-1], + &st->offset_scale1_fx[0][0], &st->offset_scale2_fx[0][0], &st->offset_scale1_p_fx[0][0], + &st->offset_scale2_p_fx[0][0], &st->no_scales_fx[0][0], &st->no_scales_p_fx[0][0] ); + IF (EQ_16(predmode,1)) + { + Copy(qlsf, mem_MA, M); + Vr_add( qlsf, pred1, qlsf, M ); + } + ELSE + { + Vr_add( qlsf, pred2, qlsf, M ); + Vr_subt(qlsf, pred1, mem_MA, M); + } + } + } + + /* Sort the quantized vector to ascending order */ + sort_fx( qlsf, 0, M-1 ); + + /* Verify stability by adding minimum separation */ + reorder_lsf_fx( qlsf, MODE1_LSF_GAP_FX, M, int_fs ); + + /* Update AR-predictor memories */ + Copy( qlsf, mem_AR, M ); + return; +} + + + + +/*-------------------------------------------------------------------* +* first_VQstages() +* +* +*-------------------------------------------------------------------*/ + +static void first_VQstages( + const Word16 * const *cb, + Word16 u[], /* i : vector to be encoded (prediction and mean removed) */ + Word16 *levels, /* i : number of levels in each stage */ + Word16 stagesVQ, /* i : number of stages */ + Word16 w[], /* i : weights */ + Word16 N, /* i : vector dimension */ + Word16 max_inner, /* i : maximum number of swaps in inner loop */ + Word16 indices_VQstage[] +) +{ + Word16 resid_buf[2*LSFMBEST*M], *resid[2]; + Word32 dist_buf[2*LSFMBEST], *dist[2], en; + Word32 f_tmp, L_tmp, L_tmp1, *pTmp32; + Word16 Tmp[M], *pTmp, cs; + Word16 *pTmp_short, idx_buf[2*LSFMBEST*MAX_VQ_STAGES], parents[LSFMBEST], counter=0, j, + m, s,c, c2, p_max, *indices[2]; + Word16 maxC = LSFMBEST; + + /*float dd[16];*/ + const Word16 *cb_stage, *cbp; + + /* Set pointers to previous (parent) and current node (parent node is indexed [0], current node is indexed [1]) */ + indices[0] = idx_buf; + move16(); + indices[1] = idx_buf + maxC*stagesVQ; + move16(); + resid[0] = resid_buf; + move16(); + resid[1] = resid_buf + maxC*N; + move16(); + dist[0] = dist_buf; + move16(); + dist[1] = dist_buf + maxC; + move16(); + + set16_fx( idx_buf, 0, (const Word16)(2*stagesVQ*maxC) ); + set16_fx( parents, 0, maxC ) ; + + /* Set up inital distance vector */ + L_tmp = L_deposit_l(0); + FOR( j=0; j0) + { + /* first VQ stages */ + first_VQstages( cb, u, levels, stagesVQ, w, M, MSVQ_MAXCNT, indices_firstVQ ); + } + + + FOR ( i=0; i= 0; stage --) + { + bestCodeword[stage] = codeWord[stage][prev_state]; + move16(); + bestState[stage] = preState[stage][prev_state]; + move16(); + prev_state = bestState[stage]; + move16(); + } + + FOR (stage = 0; stage < 4; stage ++) + { + bestCodeword[stage + 4] = blockCodeword[fBlock][stage]; + move16(); + } + + return fBlock; +} + +static void quantEnc_fx( + Word16 *y_fx, + Word16 c[], + const Word16 CB_SUB1_fx[][128][2], + const Word16 CB_SUB2_fx[][64][2], + const Word16 CB_SUB3_fx[][32][2], + const Word16 itc_fx[][2][2] +) +{ + Word16 i,j; + Word16 stage; + Word16 pred_fx[N_DIM], Y_fx[8][2]; + + /* stage #1 */ + Y_fx[0][0] = CB_SUB1_fx[0][c[0]][0]; + move16(); + Y_fx[0][1] = CB_SUB1_fx[0][c[0]][1]; + move16(); + + /* stage #2 */ + pred_fx[0] = add(mult_r(itc_fx[0][0][0], Y_fx[0][0]), mult_r(itc_fx[0][0][1], Y_fx[0][1])); + move16(); + pred_fx[1] = add(mult_r(itc_fx[0][1][0], Y_fx[0][0]), mult_r(itc_fx[0][1][1], Y_fx[0][1])); + move16(); + Y_fx[1][0] = add(CB_SUB1_fx[1][c[1]][0], pred_fx[0]); + move16(); + Y_fx[1][1] = add(CB_SUB1_fx[1][c[1]][1], pred_fx[1]); + move16(); + + /* stage #3 - #4 */ + FOR (stage = 2; stage < N_STAGE_VQ-4; stage ++) + { + pred_fx[0] = add(mult_r(itc_fx[stage-1][0][0], Y_fx[stage-1][0]), mult_r(itc_fx[stage-1][0][1], Y_fx[stage-1][1])); + move16(); + pred_fx[1] = add(mult_r(itc_fx[stage-1][1][0], Y_fx[stage-1][0]), mult_r(itc_fx[stage-1][1][1], Y_fx[stage-1][1])); + move16(); + + Y_fx[stage][0] = add(CB_SUB2_fx[stage-2][c[stage]][0], pred_fx[0]); + move16(); + Y_fx[stage][1] = add(CB_SUB2_fx[stage-2][c[stage]][1], pred_fx[1]); + move16(); + } + + /* stage #5 - #8 */ + FOR (stage = N_STAGE_VQ-4; stage < N_STAGE_VQ; stage ++) + { + pred_fx[0] = add(mult_r(itc_fx[stage-1][0][0], Y_fx[stage-1][0]), mult_r(itc_fx[stage-1][0][1], Y_fx[stage-1][1])); + move16(); + pred_fx[1] = add(mult_r(itc_fx[stage-1][1][0], Y_fx[stage-1][0]), mult_r(itc_fx[stage-1][1][1], Y_fx[stage-1][1])); + move16(); + + Y_fx[stage][0] = add(CB_SUB3_fx[stage-4][c[stage]][0], pred_fx[0]); + move16(); + Y_fx[stage][1] = add(CB_SUB3_fx[stage-4][c[stage]][1], pred_fx[1]); + move16(); + } + + /* Transform Vector to Scalar */ + FOR (i = 0; i < N_STAGE_VQ; i++) + { + FOR (j = 0; j < N_DIM; j++) + { + y_fx[i*N_DIM+j] = Y_fx[i][j]; + move16(); + } + } + + return; +} + +static void buildCode_fx( + Word16 *ind, + Word16 fins, + Word16 c[], + Word16 s[] +) +{ + Word16 stage; + Word16 BrIndex[4]; + + set16_fx(BrIndex, 0, (N_STAGE_VQ - 4)); + + + FOR (stage = N_STAGE_VQ - 4; stage >= 1; stage--) + { + if(GT_16(s[stage], 7)) + { + BrIndex[stage-1] =1; + move16(); + } + } + ind[0] = fins; + move16(); + + /* stage #1 - #2 */ + FOR (stage = 0; stage < 2; stage++) + { + ind[stage+1] = shl(BrIndex[stage], 4); + move16(); + ind[stage+1] = add(ind[stage+1], shr(c[stage], 3)); + move16(); + } + + /* stage #3 - #4 */ + FOR (stage = 2; stage < N_STAGE_VQ - 4; stage++) + { + ind[stage+1] = shl(BrIndex[stage], 3); + move16(); + ind[stage+1] = add(ind[stage+1], shr(c[stage], 3)); + move16(); + } + + /* Stage #5 - #8 */ + FOR (stage = N_STAGE_VQ-4; stage < N_STAGE_VQ; stage++) + { + ind[stage+1] = shr(c[stage], 3); + move16(); + } + + return; +} +static void BcTcvq_fx( + Word16 snFlag, + const Word16 *x_fx, + Word16 *y_fx, + const Word16 *weight_fx, + Word16 *ind +) +{ + Word16 X_fx[N_STAGE_VQ][N_DIM], W_fx[N_STAGE_VQ][N_DIM]; + + /* Count Variable */ + Word16 i,j; + + /* TCVQ Structure */ + Word16 stage, state, prev_state; + Word16 preState[N_STAGE_VQ][NUM_STATE]; + Word16 codeWord[N_STAGE_VQ][NUM_STATE]; + Word32 acumDist_fx[N_STAGE_VQ-4][NUM_STATE]; + Word16 inis, fins, ptr_fins; + Word16 fBlock; + Word16 fState[NUM_STATE]; + Word16 fCodeword[4][4]; + Word16 iniBlock[NUM_STATE]; + Word16 blockCodeword[NUM_STATE][4]; + + /* Prediction variable */ + Word16 quant_fx[N_STAGE_VQ][NUM_STATE][N_DIM]; + + /* Distortion variable */ + Word32 minDist_fx; + Word32 fDist_fx; + Word32 blockDist_fx[NUM_STATE]; + + /* Decoding variable */ + Word16 bestCodeword[N_STAGE_VQ]; + Word16 bestState[N_STAGE_VQ]; + + /* Code Share variable */ + const Word16 (*TCVQ_CB_SUB1_fx)[128][2], (*TCVQ_CB_SUB2_fx)[64][2], (*TCVQ_CB_SUB3_fx)[32][2]/**/; + const Word16 (*IntraCoeff_fx)[2][2]; + + /* Memoryless Module */ + IF (snFlag) + { + TCVQ_CB_SUB1_fx = SN_TCVQ_CB_SUB1_fx; + TCVQ_CB_SUB2_fx = SN_TCVQ_CB_SUB2_fx; + TCVQ_CB_SUB3_fx = SN_TCVQ_CB_SUB3_fx; + IntraCoeff_fx = SN_IntraCoeff_fx; + } + ELSE /* Memory Module */ + { + TCVQ_CB_SUB1_fx = AR_TCVQ_CB_SUB1_fx; + TCVQ_CB_SUB2_fx = AR_TCVQ_CB_SUB2_fx; + TCVQ_CB_SUB3_fx = AR_TCVQ_CB_SUB3_fx; + IntraCoeff_fx = AR_IntraCoeff_fx; + } + + /* Transform Scalar to Vector */ + FOR (i = 0; i < N_STAGE_VQ; i++) + { + FOR(j = 0; j < N_DIM; j++) + { + X_fx[i][j] = x_fx[(N_DIM*i) + j]; + move16(); + W_fx[i][j] = weight_fx[(N_DIM*i) + j]; + move16(); + } + } + + /* Initialzie */ + FOR (i=0; i= 0; stage--) + { + prev_state = preState[stage][prev_state]; + move16(); + } + iniBlock[state] = prev_state; + move16(); + } + + /* stage #5 - #8 */ + FOR (state = 0; state < NUM_STATE; state++) + { + inis = iniBlock[state]; + move16(); + ptr_fins = shr(inis, 2); + minDist_fx = L_add(MAX_32, 0); + + FOR (i = 0; i < 4; i++) + { + fins = add(shl(ptr_fins, 2), i); + prev_state = state; + move16(); + fDist_fx = BcTcvq_FixSearch_fx(X_fx, TCVQ_CB_SUB3_fx, fCodeword, quant_fx, FixBranch_tbl, N_STAGE_VQ-4, inis, i, &prev_state, W_fx, IntraCoeff_fx); + + FOR (stage = N_STAGE_VQ-3; stage < N_STAGE_VQ; stage++) + { + fDist_fx = L_add(fDist_fx, BcTcvq_FixSearch_fx(X_fx, TCVQ_CB_SUB3_fx, fCodeword, quant_fx, FixBranch_tbl, stage, inis, i, &prev_state, W_fx, IntraCoeff_fx)); + } + IF (LT_32(fDist_fx, minDist_fx)) + { + minDist_fx = L_add(fDist_fx, 0); + blockDist_fx[state] = minDist_fx; + move32(); + + fState[state] = fins; + move16(); + + blockCodeword[state][0] = fCodeword[i][0]; + move16(); + blockCodeword[state][1] = fCodeword[i][1]; + move16(); + blockCodeword[state][2] = fCodeword[i][2]; + move16(); + blockCodeword[state][3] = fCodeword[i][3]; + move16(); + } + } + } + + /* Select optimal path */ + fBlock = optimalPath_fx(acumDist_fx, blockDist_fx, blockCodeword, bestCodeword, codeWord, bestState, preState); + + /* Select Quantized Value */ + quantEnc_fx(y_fx, bestCodeword, TCVQ_CB_SUB1_fx, TCVQ_CB_SUB2_fx, TCVQ_CB_SUB3_fx, IntraCoeff_fx); + + /* Buid Code for Decoder */ + buildCode_fx(ind, fState[fBlock], bestCodeword, bestState); + + return; +} + +static Word16 SVQ_2d_fx( + Word16 *x_fx, + Word16 *y_fx, + const Word16 *W_fx, + const Word16 CB_fx[][8], + Word16 Size +) +{ + Word16 i, j; + Word16 index = 0; + Word32 distortion_fx; + Word32 temp_fx; + Word16 temp16_fx; + + temp_fx = L_add(MAX_32, 0); + + FOR (i = 0; i < Size; i++) + { + distortion_fx = L_deposit_l(0); + FOR (j = 0; j < 8; j++) + { + temp16_fx = sub(x_fx[j], CB_fx[i][j]); + distortion_fx = L_add(distortion_fx, + L_shr(Mult_32_16(L_mult(temp16_fx, temp16_fx), W_fx[j]), 1)); + } + + IF (LT_32(distortion_fx, temp_fx)) + { + temp_fx = L_add(distortion_fx, 0); + index = i; + move16(); + } + } + + FOR (i = 0; i < M/2; i++) + { + y_fx[i] = CB_fx[index][i]; + move16(); + } + + return index; +} + + +Word32 qlsf_ARSN_tcvq_Enc_16k_fx ( + const Word16 *x_fx, /* i : Vector to be encoded x2.65 */ + Word16 *y_fx, /* o : Quantized LSF vector x2.65 */ + Word16 *indice, /* o : Indices */ + const Word16 *w_fx, /* i : LSF Weights Q8 */ + const Word16 nBits, /* i : number of bits */ + Word16 safety_net /* i : safety_net flag */ +) +{ + Word16 i; + Word16 x_q_fx[M]; + Word16 yy_fx[M]; + Word16 error_svq_fx[M], error_svq_q_fx[M]; + Word16 cl, cs; + Word32 temp_l; + IF (EQ_16(safety_net, 1)) + { + indice[0] = 1; + move16(); + BcTcvq_fx(1, /*x, x_q, w, */x_fx, x_q_fx, w_fx, &indice[1]); + + IF (GT_16(nBits, 30)) + { + /* SVQ */ + FOR (i = 0; i < M; i++) + { + error_svq_fx[i] = mult_r(sub(x_fx[i], x_q_fx[i]), scale_inv_ARSN_fx[i]); + move16(); + } + + /* 5bits 1st Split VQ for Residual*/ + indice[10] = SVQ_2d_fx(error_svq_fx, error_svq_q_fx, w_fx, AR_SVQ_CB1_fx, 32); + /* 4bits 2nd Split VQ for Residual*/ + indice[11] = SVQ_2d_fx(&error_svq_fx[8], &error_svq_q_fx[8], &w_fx[8], AR_SVQ_CB2_fx, 16 ); + + FOR (i = 0; i < M; i++) + { + x_q_fx[i] = add(x_q_fx[i], extract_h(L_shl(L_mult0(error_svq_q_fx[i], scale_ARSN_fx[i]), 2))); + move16(); + } + } + } + ELSE + { + indice[0] = 0; + move16(); + BcTcvq_fx(0, /*x, x_q, w, */x_fx, x_q_fx, w_fx, &indice[1]); + + IF (GT_16(nBits, 30)) + { + /* SVQ */ + FOR (i = 0; i < M; i++) + { + error_svq_fx[i] = sub(x_fx[i], x_q_fx[i]); + move16(); + } + + /* 5bits 1st Split VQ for Residual*/ + indice[10] = SVQ_2d_fx(error_svq_fx, error_svq_q_fx, w_fx, AR_SVQ_CB1_fx, 32); + /* 4bits 2nd Split VQ for Residual*/ + indice[11] = SVQ_2d_fx(&error_svq_fx[8], &error_svq_q_fx[8], &w_fx[8], AR_SVQ_CB2_fx, 16 ); + + FOR (i = 0; i < M; i++) + { + x_q_fx[i] = add(x_q_fx[i], error_svq_q_fx[i]); + move16(); + } + } + } + + cl = 0; + move16(); + FOR (i = 0; i < M; i ++) + { + yy_fx[i] = sub(x_fx[i], x_q_fx[i]); + move16(); + cl = s_max(cl, abs_s(yy_fx[i])); + } + cs = norm_s(cl); + temp_l = 0; + move16(); + + FOR (i = 0; i < M; i ++) + { + yy_fx[i] = shl(yy_fx[i], cs); + move16(); + temp_l = L_mac(temp_l, mult(yy_fx[i], shl(w_fx[i],2) ), yy_fx[i]); + } + cs = shl(cs, 1); + temp_l = L_shr(temp_l, cs); + temp_l = Mult_32_16(temp_l, LSF_1_OVER_256SQ); /* Q-4 */ + + /* Recover the quantized LSF */ + Copy(x_q_fx, y_fx, M); + + return temp_l; +} + +static void FFT_Mid_Interpol_16k_fx( + Word32 Bin_Ener_old[], /* i/o: Old 2nd FFT Bin energy (128) */ + Word32 Bin_Ener[], /* i : Current 2nd FFT Bin energy (128) */ + Word32 Bin_Ener_mid[] /* o : LP weighting filter (numerator) */ +) +{ + Word16 i; + + FOR( i=0; i 0 && LT_16(j, M)&<_16(qlsf[j],add(qlsf[j-1],LSF_GAP_MID_FX))) + { + qlsf[j] = add(qlsf[j-1], LSF_GAP_MID_FX); + move16(); + } + + tmp = sub(lsf[j],qlsf[j]); + /* err += wghts[j] * ftemp * ftemp; */ + /* tmp is usually very small, we can have some extra precision with very rare saturation */ + tmp = shl(tmp, 4); + tmp = mult_r(tmp, tmp); + err = L_mac(err, tmp, shl(wghts[j],2) ); + } + /* err = L_shl(err,Wscale); */ + err = Mult_32_16(err,LSF_1_OVER_256SQ); + /* err = Mult_32_16(err,Wmult); */ + + IF ( LT_32(err,err_min)) + { + err_min = L_add(err, 0); + idx = k; + move16(); + } + k1+=M; + move16(); + } + + /* calculate the quantized LSF vector */ + FOR ( j = 0; j < M; j++ ) + { + /* qlsf[j] = (1.0f - ratio[idx*M+j]) * qlsf0[j] + ratio[idx*M+j] * qlsf1[j]; */ + L_tmp = L_mult(sub(0x2000, ratio[idx*M+j]), qlsf0[j]); + L_tmp = L_mac(L_tmp,ratio[idx*M+j],qlsf1[j]); + qlsf[j] = round_fx(L_shl(L_tmp,2)); + + test(); + test(); + IF ( j > 0 && LT_16(j, M)&<_16(qlsf[j],add(qlsf[j-1],LSF_GAP_MID_FX))) + { + qlsf[j] = add(qlsf[j-1], LSF_GAP_MID_FX); + move16(); + } + } + + reorder_lsf_fx( qlsf, LSF_GAP_MID_FX, M, int_fs ); + + /* convert LSFs back to LSPs */ + lsf2lsp_fx( qlsf, lsp, M, int_fs); + push_indice_fx( st_fx, IND_MID_FRAME_LSF_INDEX, idx, nb_bits ); + + return; +} + diff --git a/lib_enc/lsf_msvq_ma_enc.c b/lib_enc/lsf_msvq_ma_enc.c new file mode 100644 index 0000000..e4124f6 --- /dev/null +++ b/lib_enc/lsf_msvq_ma_enc.c @@ -0,0 +1,718 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "cnst_fx.h" +#include "rom_com_fx.h" +#include "prot_fx.h" +#include "stl.h" +#include "basop_util.h" +#include "rom_enc_fx.h" + + +#define MAXINT32 2147483647 +#define swap(x,y,type) {type u__p; u__p=x; x=y; y=u__p;} + + + +#define depack_4_values(cbp, val0, val1, val2, val3) \ + val0 = shr((cbp)[0], 4); \ + val1 = shr((cbp)[1], 4); \ + val2 = shr((cbp)[2], 4); \ + val3 = add(add(shr(lshl((cbp)[2],12),4),lshr(lshl((cbp)[1],12),8)),s_and((cbp)[0],0xF)); + +static Word32 depack_mul_values(Word16 *Tmp, const Word16 *w, const Word16 *cbp, const Word16 N) +{ + Word16 i, val0, val1, val2, val3; + Word32 en; + + en = 0; + move32(); + FOR (i = 0; i < N; i+=4) + { + depack_4_values(cbp+i_mult(shr(i,2),3), val0, val1, val2, val3) + Tmp[i+0] = mult_r(shl(w[i+0],2),val0); + move16(); + en = L_mac(en, val0, Tmp[i+0]); + Tmp[i+1] = mult_r(shl(w[i+1],2),val1); + move16(); + en = L_mac(en, val1, Tmp[i+1]); + Tmp[i+2] = mult_r(shl(w[i+2],2),val2); + move16(); + en = L_mac(en, val2, Tmp[i+2]); + Tmp[i+3] = mult_r(shl(w[i+3],2),val3); + move16(); + en = L_mac(en, val3, Tmp[i+3]); + } + + return en; +} + +static void depack_sub_values(Word16 *pTmp, const Word16 *p1, const Word16 *cbp, const Word16 N) +{ + Word16 j, val0, val1, val2, val3; + + FOR (j=0; j> 16 => Qwnorm-15/16 * Q0/16 << 1 => Qwnorm-14/32 * 6.5536 */ + ss2 = L_mult(mult(u[0], shl( w[0], 2 )), u[0]); + move16(); + FOR (j=1; j 0 && LT_16(j, M)&<_16(qlsf[j],add(qlsf[j-1],LSF_GAP_MID_FX))) + { + qlsf[j] = add(qlsf[j-1], LSF_GAP_MID_FX); + } + + tmp = sub(lsf[j],qlsf[j]); + /* err += wghts[j] * ftemp * ftemp; */ + /* tmp is usually very small, we can have some extra precision with very rare saturation */ + tmp = shl(tmp, 4); + tmp = mult_r(tmp, tmp); + err = L_mac(err, tmp, wghts[j]); + } + err = L_shl( err, 2 ); + + /* err = L_shl(err,Wscale); */ + err = Mult_32_16(err,LSF_1_OVER_256SQ); + /* err = Mult_32_16(err,Wmult); */ + + IF ( LT_32(err,err_min)) + { + err_min = L_add(err, 0); + *idx = k; + move16(); + } + k1+=M; + move16(); + } + + return; +} + + +/* Returns: number of indices */ +Word16 Q_lsf_tcxlpc( + /* const */ Word16 lsf[], /* (I) original lsf */ + Word16 lsf_q[], /* (O) quantized lsf */ + Word16 lsp_q_ind[], /* (O) quantized lsp (w/o MA prediction) */ + Word16 indices[], /* (O) VQ indices */ + Word16 lpcorder, /* (I) LPC order */ + Word16 narrowband, /* (I) narrowband flag */ + Word16 cdk, /* (I) codebook selector */ + Word16 mem_MA[] /* (I) MA memory */ + , Word16 coder_type + , Word32 * Bin_Ener + ,const Word16 Q_ener +) +{ + Word16 weights[17]; + Word16 pred[M16k]; + Word16 i; + Word16 NumIndices; + Word16 lsf_q_ind[M16k]; + const Word16 *means; + Word16 lsf_rem[M]; + Word16 lsf_rem_q_ind[M]; + + Unified_weighting_fx( Bin_Ener, Q_ener, lsf, weights, narrowband,(Word16)EQ_16(coder_type,UNVOICED),12800,M); + + move16(); + NumIndices = 0; + + /* Put disabled flag */ + indices[NumIndices] = 0; + move16(); + NumIndices = add(NumIndices, 1); + + /* Inter-frame prediction */ + + means = lsf_means[narrowband]; /* 14Q1 * 1.28 */ + + FOR (i=0; iframes_power_32; + Q_frames_power_last_32 = st->Q_frames_power_32; + move16(); + leadingzero_midamp = 31; + move16(); + leadingzero_tmp32 = 31; + move16(); + Q_frames_power32 = Q_frames_power; + move16(); + + frame_energy_Sqr = FixSqrt(frame_energy, &Q_frames_power32); + frame_energy_Sqr32 = L_deposit_l(frame_energy_Sqr); + frame_energy_Sqr32 = L_shl(frame_energy_Sqr32,16); + Q_frames_power32 = add(Q_frames_power32, 16); + + /* +0.1 */ + IF (GE_16(Q_frames_power32, 40)) + { + zerop001 = L_shr(CNT0P001, 1); + frame_energy_Sqr32 = L_shr(frame_energy_Sqr32,sub(Q_frames_power32, 39)); + Q_frames_power32 = 39; + move16(); + } + ELSE + { + Q_frames_power32 = sub(Q_frames_power32, 1); + frame_energy_Sqr32 = L_shr(frame_energy_Sqr32,1); + zerop001 = L_shr(CNT0P001, sub(40, Q_frames_power32)); + } + frames_power_32[0] = L_add(frame_energy_Sqr32, zerop001); + move32(); + + IF(LT_16(frameloop, 3)) + { + FOR(i=1; i<40; i++) + { + frames_power_32[i] = frames_power_32[0]; + move32(); + } + } + ELSE + { + Word16 leadingzero; + maxVal = 0; + move32(); + FOR(i=1; i<40; i++) + { + maxVal = L_max(maxVal,frames_power_32[i]); + } + leadingzero = 31; + move16(); + if(maxVal) + leadingzero = norm_l(maxVal); + Q_frames_power_last_32 = add(Q_frames_power_last_32, leadingzero); + + + IF (GT_16(Q_frames_power_last_32,Q_frames_power32)) + { + scale1 = sub(Q_frames_power_last_32, Q_frames_power32); + scale1 = sub(scale1, leadingzero); + FOR(i=1; i<40; i++) + { + frames_power_32[i] = L_shr(frames_power_32[i],scale1); + move32(); + } + } + ELSE + { + scale1 = sub(Q_frames_power32, Q_frames_power_last_32); + frames_power_32[0] = L_shr(frames_power_32[0],scale1); + move32(); + Q_frames_power32 = Q_frames_power_last_32; + move16(); + FOR(i=1; i<40; i++) + { + frames_power_32[i] = L_shl(frames_power_32[i], leadingzero); + move32(); + } + } + } + + FOR(i=0; i<20; i++) + { + mid_frame_ampadd32[i] = L_add(L_shr(frames_power_32[2*i], 1), L_shr(frames_power_32[2*i+1], 1)); + move32(); + } + + maxVal = 0; move32(); + FOR(i=0; i<20; i++) + { + maxVal = L_max(maxVal,mid_frame_ampadd32[i]); + } + leadingzero_midamp = 31; + move16(); + if(maxVal) + leadingzero_midamp = norm_l(maxVal); + + FOR(i=0; i<20; i++) + { + mid_frame_amp32[i] = L_shl(mid_frame_ampadd32[i], leadingzero_midamp); + move32(); + } + + seg_amp32 = 0; move32(); + FOR(i=0; i<20; i++) + { + seg_amp32 = L_add(seg_amp32, L_shr(mid_frame_amp32[i], 5)); + } + seg_amp32 = MUL_F(seg_amp32, 0x0666); + + dif32 = 0; move32(); + apow32 = 0; move32(); + + seg_amp32tmp = L_shl(seg_amp32, 5); + FOR(i=0; i<20; i++) + { + tmp32[i] = L_sub(mid_frame_amp32[i],seg_amp32tmp); + move32(); + } + + maxVal = 0; move32(); + FOR(i=0; i<20; i++) + { + maxVal = L_max(maxVal,L_abs(tmp32[i])); + } + leadingzero_tmp32 = 31; + move16(); + if(maxVal) + leadingzero_tmp32 = norm_l(maxVal); + + FOR(i=0; i<20; i++) + { + tmp16[i] = extract_h(L_shl(tmp32[i], leadingzero_tmp32)); + } + + FOR(i=0; i<20; i++) + { + tmp_mul = L_mult(tmp16[i],tmp16[i]); + tmp_mul = L_shr(tmp_mul,5); + dif32 = L_add(dif32,tmp_mul); + + tmp = extract_h(mid_frame_amp32[i]); + mid_frame_amp_mul = L_mult(tmp,tmp); + mid_frame_amp_mul = L_shr(mid_frame_amp_mul,5); + apow32 = L_add(apow32,mid_frame_amp_mul); + } + + + IF (dif32==0) + { + ltd_stable_rate[0] = 0; + move16(); + } + ELSE + { + Q_dif = sub(norm_l(dif32), 1); + Q_apow = norm_l(apow32); + dif32 = L_shl(dif32,Q_dif); + apow32 = L_shl(apow32,Q_apow); + ltd_stable_rate[0] = div_l(dif32,extract_h(apow32)); + move16(); + } + + ltd_stable_rate_Qtmp = sub(Q_dif, Q_apow); + ltd_stable_rate_Qtmp = add(ltd_stable_rate_Qtmp, leadingzero_tmp32); + ltd_stable_rate_Qtmp = add(ltd_stable_rate_Qtmp, leadingzero_tmp32); + ltd_stable_rate_Qtmp = add(ltd_stable_rate_Qtmp, 15); + ltd_stable_rate_Qtmp = sub(ltd_stable_rate_Qtmp, ITD_STABLE_RATE_Q); + + ltd_stable_rate_Qtmp = limitScale16(ltd_stable_rate_Qtmp); + ltd_stable_rate[0] = shr(ltd_stable_rate[0],ltd_stable_rate_Qtmp); + move16(); + + maxVal = 0; move32(); + FOR(i=0; i<14; i++) + { + maxVal = L_max(maxVal, L_abs(mid_frame_ampadd32[i])); + } + leadingzero_midamp = 31; + move16(); + if(maxVal) + leadingzero_midamp = norm_l(maxVal); + + FOR(i=0; i<14; i++) + { + mid_frame_amp32[i] = L_shl(mid_frame_ampadd32[i],leadingzero_midamp); + move32(); + } + + seg_amp32 = 0; move32(); + FOR(i=0; i<14; i++) + { + seg_amp32 = L_add(seg_amp32, L_shr(mid_frame_amp32[i],4)); + } + seg_amp32 = MUL_F(seg_amp32, 0x0924); + + dif32 = 0; move32(); + apow32 = 0; move32(); + seg_amp32tmp = L_shl(seg_amp32, 4); + FOR(i=0; i<14; i++) + { + tmp32[i] = L_sub(mid_frame_amp32[i], seg_amp32tmp); + move32(); + } + + maxVal = 0; move32(); + FOR(i=0; i<14; i++) + { + maxVal = L_max(maxVal,L_abs(tmp32[i])); + } + leadingzero_tmp32 = 31; + move16(); + if(maxVal) + leadingzero_tmp32 = norm_l(maxVal); + + FOR(i=0; i<14; i++) + { + tmp32[i] = L_shl(tmp32[i], leadingzero_tmp32); + move32(); + } + + FOR(i=0; i<14; i++) + { + tmp = extract_h(tmp32[i]); + tmp_mul = L_mult(tmp, tmp); + tmp_mul = L_shr(tmp_mul, 4); + dif32 = L_add(dif32, tmp_mul); + + tmp = extract_h(mid_frame_amp32[i]); + mid_frame_amp_mul = L_mult(tmp,tmp); + mid_frame_amp_mul = L_shr(mid_frame_amp_mul, 4); + apow32 = L_add(apow32, mid_frame_amp_mul); + } + + Qsum_apow32 = add(Q_frames_power32, Q_frames_power32); + Qsum_apow32 = add(Qsum_apow32, leadingzero_midamp); + Qsum_apow32 = add(Qsum_apow32, leadingzero_midamp); + Qsum_apow32 = sub(Qsum_apow32, 37); + + Qsum_dif32 = add(Qsum_apow32, leadingzero_tmp32); + Qsum_dif32 = add(Qsum_dif32, leadingzero_tmp32); + + /* +0.1 */ + IF (GE_16(Qsum_apow32,44)) + { + zerop001 = L_shr(CNT0P0001, 1); + apow32 = L_shr(apow32,limitScale32(sub(Qsum_apow32,43))); + Qsum_apow32 = 43; + move16(); + } + ELSE + { + Qsum_apow32 = sub(Qsum_apow32, 1); + apow32 = L_shr(apow32, 1); + zerop001 = L_shr(CNT0P0001, limitScale32(sub(44, Qsum_apow32))); + } + apow32 = L_add(apow32, zerop001); + IF (apow32 == 0) + { + apow32 = CNT0P0001; move32(); + Qsum_apow32 = 44; + move16(); + } + + IF (dif32 == 0) + { + ltd_stable_rate[1] = 0; + move16(); + } + ELSE + { + Q_dif=sub(norm_l(dif32), 1); + Q_apow=norm_l(apow32); + dif32 = L_shl(dif32,Q_dif); + apow32 = L_shl(apow32,Q_apow); + + ltd_stable_rate[1] = div_l(dif32,extract_h(apow32)); + move16(); + } + + ltd_stable_rate_Qtmp = add(Qsum_dif32, Q_dif); + ltd_stable_rate_Qtmp = sub(ltd_stable_rate_Qtmp, Qsum_apow32); + ltd_stable_rate_Qtmp = sub(ltd_stable_rate_Qtmp, Q_apow); + ltd_stable_rate_Qtmp = add(ltd_stable_rate_Qtmp, 15); + ltd_stable_rate_Qtmp = sub(ltd_stable_rate_Qtmp, ITD_STABLE_RATE_Q); + + ltd_stable_rate_Qtmp = limitScale16(ltd_stable_rate_Qtmp); + + ltd_stable_rate[1] = shr(ltd_stable_rate[1],ltd_stable_rate_Qtmp); + move16(); + + maxVal = 0; move32(); + FOR(i=0; i<8; i++) + { + maxVal = L_max(maxVal,L_abs(mid_frame_ampadd32[i])); + } + leadingzero_midamp = 31; + move16(); + if(maxVal) + leadingzero_midamp = norm_l(maxVal); + + FOR(i=0; i<8; i++) + { + mid_frame_amp32[i] = L_shl(mid_frame_ampadd32[i], leadingzero_midamp); + move32(); + } + + seg_amp32 = 0; move32(); + FOR(i=0; i<8; i++) + { + seg_amp32 = L_add(seg_amp32, L_shr(mid_frame_amp32[i], 3)); + } + seg_amp32 = MUL_F(seg_amp32, 0x1000); + + dif32 = 0; move32(); + apow32 = 0; move32(); + seg_amp32tmp = L_shl(seg_amp32, 3); + FOR(i=0; i<8; i++) + { + tmp32[i] = L_sub(mid_frame_amp32[i], seg_amp32tmp); + move32(); + } + + maxVal = 0; move32(); + FOR(i=0; i<8; i++) + { + maxVal = L_max(maxVal,L_abs(tmp32[i])); + } + leadingzero_tmp32 = 31; + move16(); + if(maxVal) + leadingzero_tmp32 = norm_l(maxVal); + + FOR(i=0; i<8; i++) + { + tmp32[i] = L_shl(tmp32[i],leadingzero_tmp32); + move32(); + } + + FOR(i=0; i<8; i++) + { + tmp = extract_h(tmp32[i]); + tmp_mul = L_mult(tmp,tmp); + tmp_mul = L_shr(tmp_mul, 3); + dif32 = L_add(dif32, tmp_mul); + + tmp = extract_h(mid_frame_amp32[i]); + mid_frame_amp_mul = L_mult(tmp,tmp); + mid_frame_amp_mul = L_shr(mid_frame_amp_mul,3); + apow32 = L_add(apow32, mid_frame_amp_mul); + } + + Qsum_apow32 = add(Q_frames_power32,Q_frames_power32); + Qsum_apow32 = add(Qsum_apow32,leadingzero_midamp); + Qsum_apow32 = add(Qsum_apow32,leadingzero_midamp); + Qsum_apow32 = sub(Qsum_apow32,36); + + Qsum_dif32 = add(Qsum_apow32,leadingzero_tmp32); + Qsum_dif32 = add(Qsum_dif32,leadingzero_tmp32); + + /* +0.1 */ + IF (GE_16(Qsum_apow32,44)) + { + zerop001 = L_shr(CNT0P0001, 1); + apow32 = L_shr(apow32,limitScale32(sub(Qsum_apow32,43))); + Qsum_apow32 = 43; + move16(); + } + ELSE + { + Qsum_apow32 = sub(Qsum_apow32, 1); + apow32 = L_shr(apow32,1); + zerop001 = L_shr(CNT0P0001, limitScale32(sub(44, Qsum_apow32))); + } + apow32 = L_add(apow32, zerop001); + IF (apow32 == 0) + { + apow32 = CNT0P0001; move32(); + Qsum_apow32 = 44; + move16(); + } + + IF (dif32 == 0) + { + ltd_stable_rate[2] = 0; + move16(); + } + ELSE + { + Q_dif = sub(norm_l(dif32), 1); + Q_apow = norm_l(apow32); + dif32 = L_shl(dif32, Q_dif); + apow32 = L_shl(apow32, Q_apow); + + ltd_stable_rate[2] = div_l(dif32, extract_h(apow32)); + move16(); + } + + ltd_stable_rate_Qtmp = add(Qsum_dif32, Q_dif); + ltd_stable_rate_Qtmp = sub(ltd_stable_rate_Qtmp, Qsum_apow32); + ltd_stable_rate_Qtmp = sub(ltd_stable_rate_Qtmp, Q_apow); + ltd_stable_rate_Qtmp = add(ltd_stable_rate_Qtmp, 15); + ltd_stable_rate_Qtmp = sub(ltd_stable_rate_Qtmp, ITD_STABLE_RATE_Q); + + ltd_stable_rate_Qtmp = limitScale16(ltd_stable_rate_Qtmp); + + ltd_stable_rate[2] = shr(ltd_stable_rate[2], ltd_stable_rate_Qtmp); + move16(); + ltd_stable_rate[3] = add(mult(ltd_stable_rate[3], 0x7333), mult(ltd_stable_rate[2], 0x0ccc)); + move16(); + + FOR(i=55; i>0; i--) + { + frames_power_32[i] = frames_power_32[i-1]; + move32(); + } + st->Q_frames_power_32 = Q_frames_power32; + move16(); + +} diff --git a/lib_enc/mdct_classifier_fx.c b/lib_enc/mdct_classifier_fx.c new file mode 100644 index 0000000..52401fe --- /dev/null +++ b/lib_enc/mdct_classifier_fx.c @@ -0,0 +1,470 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include "stl.h" + +/*--------------------------------------------------------------------------* + * mdct_classifier() + * + * MDCT signal classifier + *--------------------------------------------------------------------------*/ + +#define MDCT_CLASSIFER_SMOOTH_FILT_COEFF 26214 /* 0.8 in Q15 */ +#define MDCT_CLASSIFER_THRESH_UP 13107 /* 1.6 in Q13 */ +#define MDCT_CLASSIFER_THRESH_DOWN 9011 /* 1.1 in Q13 */ +#define MDCT_CLASSIFER_HQ_LOCAL (3 << 13) /* Q13, Define those local to make the filtering operation robust in case classes numbers are changed */ +#define MDCT_CLASSIFER_TCX_LOCAL (1 << 13) /* Q13 */ + + +/*----------------------------------------------------------------------------- + * dft_mag_square_fx() + * + * Square magnitude of fft spectrum + *----------------------------------------------------------------------------*/ +static void dft_mag_square_fx( + const Word16 x[], /* i : Input vector: re[0], re[1], ..., re[n/2], im[n/2 - 1], im[n/2 - 2], ..., im[1] */ + Word32 magSq[], /* o : Magnitude square spectrum */ + const Word16 n /* i : Input vector length */ +) +{ + Word16 i, l; + const Word16 *pRe, *pIm; + Word32 *pMagSq, acc; + + /* Magnitude square at 0. */ + pMagSq = &magSq[0]; + pRe = &x[0]; + *pMagSq++ = L_mult0(*pRe, *pRe); + pRe++; + move32(); + + /* From 1 to (N/2 - 1). */ + l = sub(shr(n, 1), 1); /* N/2 - 1. */ + pIm = &x[n]; + pIm--; + FOR (i = 0; i < l; i++) + { + acc = L_mult0(*pRe, *pRe); + pRe++; + *pMagSq++ = L_mac0(acc, *pIm, *pIm); + pIm--; + move32(); + } + + /* The magnitude square at N/2 */ + *pMagSq = L_mult0(*pRe, *pRe); + move32(); + return; +} + +Word16 mdct_classifier_fx( /* o: MDCT A/B decision */ + const Word16 *Y, /* i: re[0], re[1], ..., re[n/2], im[n/2 - 1], im[n/2 - 2], ..., im[1] */ + Encoder_State_fx *st_fx, /* i/o: Encoder state variable */ + Word16 vadflag + , Word32 *cldfbBuf_Ener + ,Word16 enerBuffer_exp +) +{ + Word16 c; + Word32 magSq[129], *pMagSq, nf, pe; + Word16 k; + Word16 np; + Word32 max_cand; + Word16 max_i; + Word32 p_energy_man, n_energy_man, man; + Word16 p_energy_exp, n_energy_exp, expo; + Word16 d_acc; + Word16 pos_last; + Word16 clas_sec; + Word16 clas_final; + Word16 condition1, condition2; + Word16 factor; + Word32 acc; + UWord16 lsb16; + UWord32 lsb32; + Word32 gain1, gain2, gain3, gain11, gain4; + Word32 peak_l, peak_h, avrg_l, avrg_h, peak_H1, avrg_H1, peak_H2, avrg_H2; + Word16 condition3, condition4; + Word32 gain1_tmp = 0, gain2_tmp = 0; + Word16 exp, exp1, exp2, exp3; + Word32 L_tmp, L_tmp1; + + dft_mag_square_fx(Y, magSq, 256); + + nf = L_add(magSq[0], 0); + pe = L_add(magSq[0], 0); + np = 0; + move16(); + max_cand = L_negate(1); + max_i = 0; + move16(); + p_energy_man = L_deposit_l(0); + n_energy_man = L_deposit_l(0); + p_energy_exp = n_energy_exp = 32; + move16(); + move16(); + d_acc = 0; + move16(); + pos_last = -1; + move16(); + + pMagSq = magSq; + FOR (k = 0; k < 128; k++) + { + /* NB: a*f + b*(1 - f) needs two multiplies + * = (a - b)*f + b saves one multiply */ + IF (GT_32(*(++pMagSq), nf)) + { + factor = 31385; + move16();/* 0.9578 in Q15 */ + } + ELSE + { + factor = 21207; + move16();/* 0.6472 in Q15 */ + } + acc = L_sub(nf, *pMagSq); + Mpy_32_16_ss(acc, factor, &acc, &lsb16); + nf = L_add(acc, *pMagSq); + IF (GT_32(*pMagSq, pe)) + { + factor = 13840; + move16();/* 0.42237 in Q15 */ + } + ELSE + { + factor = 26308; + move16();/* 0.80285 in Q15 */ + } + acc = L_sub(pe, *pMagSq); + Mpy_32_16_ss(acc, factor, &acc, &lsb16); + pe = L_add(acc, *pMagSq); + Mpy_32_16_ss(pe, 20972, &acc, &lsb16); /* 0.64 in Q15 */ + IF (GT_32(*pMagSq, acc)) + { + IF (GT_32(*pMagSq, max_cand)) + { + max_cand = L_add(*pMagSq, 0); + max_i = add(2, k); + } + } + ELSE + { + IF (max_i > 0) + { + IF (GT_16(np, 0)) + { + d_acc = sub(add(d_acc, max_i), pos_last); + } + np = add(np, 1); + pos_last = max_i; + move16(); + } + + max_cand = L_negate(1); + max_i = 0; + move16(); + } + + IF (pe != 0) + { + expo = norm_l(pe); + man = L_shl(pe, expo); + Mpy_32_32_ss(man, man, &man, &lsb32); /* pe square */ + expo = shl(expo, 1); /* Multiply by 2 due to squaring. */ + floating_point_add(&p_energy_man, &p_energy_exp, man, expo); + } + IF (nf != 0) + { + expo = norm_l(nf); + man = L_shl(nf, expo); + Mpy_32_32_ss(man, man, &man, &lsb32); /* nf square */ + expo = shl(expo, 1); /* Multiply by 2 due to squaring. */ + floating_point_add(&n_energy_man, &n_energy_exp, man, expo); + } + } + + gain1 = L_deposit_l(0); + gain2 = L_deposit_l(0); + gain3 = L_deposit_l(0); + FOR (k = 0; k < 8; k++) + { + gain1 = L_add(gain1, L_shr(cldfbBuf_Ener[k], 3)); + gain2 = L_add(gain2, L_shr(cldfbBuf_Ener[k + 8], 3)); + gain3 = L_add(gain3, L_shr(cldfbBuf_Ener[k + 16], 3)); + } + + /* gain11 = 8*(gain1 - cldfbBuf_Ener[0]/8)/7; */ + acc = L_shr(cldfbBuf_Ener[0], 3); + acc = L_sub(gain1, acc); + acc = Mult_32_16(acc, 4681); + gain11 = L_shl(acc, 3); + gain4 = L_deposit_l(0); + FOR (k = 0; k < 12; k++) + { + gain4 = L_add(gain4, Mult_32_16(cldfbBuf_Ener[k + 12], 2731)); + } + + + peak_H1 = L_add(cldfbBuf_Ener[25], 0); + Mpy_32_16_ss(cldfbBuf_Ener[25], 6554, &avrg_H1, &lsb16); + FOR (k = 1; k < 5; k++) + { + IF(GT_32(cldfbBuf_Ener[k + 25], peak_H1)) + { + peak_H1 = L_add(cldfbBuf_Ener[k + 25], 0); + } + avrg_H1 = L_add(avrg_H1, Mult_32_16(cldfbBuf_Ener[k + 25], 6554)); + } + + peak_H2 = L_add(cldfbBuf_Ener[20], 0); + Mpy_32_16_ss(cldfbBuf_Ener[20], 6554, &avrg_H2, &lsb16); + FOR (k = 1; k < 5; k++) + { + IF (GT_32(cldfbBuf_Ener[k + 20], peak_H2)) + { + peak_H2 = L_add(cldfbBuf_Ener[k + 20], 0); + } + avrg_H2 = L_add(avrg_H2, Mult_32_16(cldfbBuf_Ener[k + 20], 6554)); + } + + peak_l = L_deposit_l(0); + avrg_l = L_deposit_l(0); + peak_h = L_deposit_l(0); + avrg_h = L_deposit_l(0); + FOR (k = 0; k < 32; k++) + { + avrg_l = L_add(avrg_l, L_shr(magSq[k + 20], 5)); + avrg_h = L_add(avrg_h, L_shr(magSq[k + 96], 5)); + IF (GT_32(magSq[k + 20], peak_l)) + { + peak_l = L_add(magSq[k + 20], 0); + } + IF (GT_32(magSq[k + 96], peak_h)) + { + peak_h = L_add(magSq[k + 96], 0); + } + } + + /* Compute: d_acc - 12*(np -1). */ + acc = L_deposit_l(d_acc); + IF (L_msu(acc, 12/2, sub(np, 1)) > 0) /* 12/2 is to compensate the fractional mode multiply */ + { + condition1 = 1; /* Signifies: d_acc/(np - 1) > 12 */ move16(); + } + ELSE + { + condition1 = 0; /* Signifies: d_acc/(np - 1) <= 12 */ move16(); + /* NB: For np = 0 or 1, it fits this condition. */ + } + + /* Compute: p_energy - 147.87276*n_energy. */ + IF (n_energy_man != 0) + { + Mpy_32_16_ss(n_energy_man, 18928, &acc, &lsb16); /* 147.87276 in Q7 */ + expo = sub(n_energy_exp, 15 - 7); /* Due to 18928 in Q7 */ + acc = L_negate(acc); /* To facilitate the following floating_point_add() to perform subtraction. */ + floating_point_add(&acc, &expo, p_energy_man, p_energy_exp); + } + ELSE + { + acc = L_deposit_l(0); + } + IF (acc > 0) + { + condition2 = 1; /* Signifies: p_energy / n_energy > 147.87276 */ move16(); + } + ELSE + { + condition2 = 0; /* Signifies: p_energy / n_energy <= 147.87276 */ move16(); + } + + condition3 = 0; + move16(); + condition4 = 0; + move16(); + + L_tmp = Mult_32_16(peak_h, 12603); + IF(GT_32(peak_l, L_tmp)) + { + exp = norm_l(peak_l); + } + ELSE + { + exp = norm_l(L_tmp); + } + IF(GT_32(avrg_h, avrg_l)) + { + exp1 = norm_l(avrg_h); + } + ELSE + { + exp1 = norm_l(avrg_l); + } + + L_tmp1 = Mult_32_16(peak_l, 12603); + IF(GT_32(peak_h, L_tmp1)) + { + exp2 = norm_l(peak_h); + } + ELSE + { + exp2 = norm_l(L_tmp1); + } + + test(); + test(); + test(); + test(); + IF (GT_32(Mult_32_16(gain3, 27307), gain2)||(GE_32(gain3,Mult_32_16(gain2,26214))&>_32(peak_H1,L_shl(avrg_H1,1))) + || (LT_32(Mult_32_32(L_shl(peak_l, exp), L_shl(avrg_h, exp1)), Mult_32_32(L_shl(L_tmp, exp), L_shl(avrg_l, exp1))) + || GT_32(Mult_32_32(L_shl(L_tmp1, exp2), L_shl(avrg_h, exp1)), Mult_32_32(L_shl(peak_h, exp2), L_shl(avrg_l, exp1))))) + { + condition3 = 1; + move16(); + } + + L_tmp = Mult_32_16(peak_h, 12800); + IF(GT_32(peak_l, L_tmp)) + { + exp = norm_l(peak_l); + } + ELSE + { + exp = norm_l(L_tmp); + } + + L_tmp1 = Mult_32_16(peak_l, 6400); + IF(GT_32(peak_h, L_tmp1)) + { + exp2 = norm_l(peak_h); + } + ELSE + { + exp2 = norm_l(L_tmp1); + } + + IF(GT_32(peak_h, L_shl(L_tmp1, 1))) + { + exp3 = norm_l(peak_h); + } + ELSE + { + exp3 = sub(norm_l(L_tmp1), 1); + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF ((GT_32(gain4, Mult_32_16(gain11, 26214))&>_32(Mult_32_32(L_shl(peak_l,exp),L_shl(avrg_h,exp1)),Mult_32_32(L_shl(Mult_32_16(peak_h,12800),exp),L_shl(avrg_l,exp1))) + && LT_32(Mult_32_32(L_shl(Mult_32_16(peak_l, 6400), exp2), L_shl(avrg_h, exp1)), Mult_32_32(L_shl(peak_h, exp2), L_shl(avrg_l, exp1)))) + || (GT_32(gain4, Mult_32_16(gain11, 9830))&& LT_32(Mult_32_16(peak_h, 21845), avrg_h)&& LT_32(Mult_32_16(peak_H2, 21845), avrg_H2)) + || (LT_32(Mult_32_32(L_shl(peak_l, exp), L_shl(avrg_h, exp1)), Mult_32_32(L_shl(Mult_32_16(peak_h, 12800), exp), L_shl(avrg_l, exp1))) && GT_32(Mult_32_16(peak_h, 21845), avrg_h)) + || (GT_32(Mult_32_32(L_shl(Mult_32_16(peak_l, 12800), exp3), L_shl(avrg_h, exp1)), Mult_32_32(L_shl(peak_h, exp3), L_shl(avrg_l, exp1))) > 0 && LT_32(Mult_32_16(peak_h, 21845), avrg_h))) + { + condition4 = 1; + move16(); + } + + test(); + test(); + test(); + test(); + IF ((EQ_32(st_fx->total_brate_fx, HQ_32k)&&(s_xor(condition1,condition2)!=0||condition3)) + || (EQ_32(st_fx->total_brate_fx, HQ_24k40)&& condition4)) + { + c = MDCT_CLASSIFER_HQ_LOCAL; /* Q13 */ move16(); + } + ELSE + { + c = MDCT_CLASSIFER_TCX_LOCAL; /* Q13 */ move16(); + } + + /* Smooth decision from instantaneous decision*/ + acc = L_mult(st_fx->clas_sec_old_fx, MDCT_CLASSIFER_SMOOTH_FILT_COEFF); /* st_fx->clas_sec_old_fx in Q13 */ + clas_sec = mac_r(acc, c, 0x7fff - MDCT_CLASSIFER_SMOOTH_FILT_COEFF); /* clas_sec and c are in Q13 */ + /* Do thresholding with hysteresis */ + IF(GT_16(st_fx->last_enerBuffer_exp, enerBuffer_exp)) + { + gain1_tmp = L_shr(gain1, sub(st_fx->last_enerBuffer_exp, enerBuffer_exp)); + move32(); + gain2_tmp = L_shr(gain2, sub(st_fx->last_enerBuffer_exp, enerBuffer_exp)); + move32(); + } + ELSE + { + st_fx->last_gain1 = L_shr(st_fx->last_gain1, sub(enerBuffer_exp, st_fx->last_enerBuffer_exp)); + move32(); + st_fx->last_gain2 = L_shr(st_fx->last_gain2, sub(enerBuffer_exp, st_fx->last_enerBuffer_exp)); + move32(); + gain1_tmp = gain1; + move32(); + gain2_tmp = gain2; + move32(); + } + + test(); + test(); + test(); + test(); + test(); + test(); + IF ((EQ_16(st_fx->clas_final_old_fx, HQ_CORE)||EQ_16(st_fx->clas_final_old_fx,TCX_20_CORE)) + && ((GT_32(st_fx->last_gain1, L_shr(gain1_tmp, 1)) && LT_32(st_fx->last_gain1, L_shl(gain1_tmp, 1))) + && (GT_32(st_fx->last_gain2, L_shr(gain2_tmp, 1)) && LT_32(st_fx->last_gain2, L_shl(gain2_tmp, 1))))) + { + clas_final = st_fx->clas_final_old_fx; + move16(); + } + ELSE IF (GT_16(clas_sec, st_fx->clas_sec_old_fx)&>_16(clas_sec,MDCT_CLASSIFER_THRESH_UP)) /* Going up? */ + { + clas_final = HQ_CORE; /* Q0 */ move16(); + } + ELSE IF (LT_16(clas_sec, MDCT_CLASSIFER_THRESH_DOWN))/* Going down */ + { + clas_final = TCX_20_CORE; + move16(); + } + ELSE + { + clas_final = st_fx->clas_final_old_fx; + move16(); + } + + test(); + test(); + test(); + /* Prevent the usage of MDCTA on noisy-speech or inactive */ + if ( EQ_16(st_fx->mdct_sw_enable, MODE2)&&(EQ_16(st_fx->flag_noisy_speech_snr,1)||vadflag==0)&&EQ_16(clas_final,HQ_CORE)) + { + clas_final = TCX_20_CORE; + move16(); + } + + + /* Memory update */ + st_fx->clas_sec_old_fx = clas_sec; + move16(); /* Q13 */ + st_fx->clas_final_old_fx = clas_final; + move16(); /* Q0 */ + st_fx->last_gain1 = gain1; + move32(); + st_fx->last_gain2 = gain2; + move32(); + st_fx->last_enerBuffer_exp = enerBuffer_exp; + move16(); + + return clas_final; /* Q0 */ +} + + diff --git a/lib_enc/mdct_selector.c b/lib_enc/mdct_selector.c new file mode 100644 index 0000000..9b3045c --- /dev/null +++ b/lib_enc/mdct_selector.c @@ -0,0 +1,355 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "stl.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include + + +# define MDCT_SW_SIG_LINE_THR 840 /* 2.85f*LOG_10 in Q7 */ /* Significant spectral line threshold above Etot (dB) */ +# define MDCT_SW_SIG_PEAK_THR 9216 /* 36.0f in Q8 */ /* Significant peak threshold below Etot (dB) */ +# define MDCT_SW_HI_SPARSE_THR 8192 /* 0.25f in Q15*/ /* Max. ratio of significant spectral lines for the spectrum to be considered sparse */ +# define MDCT_SW_HI_ENER_LO_THR 1920 /* 7.5f in Q8 */ /* Hi band low energy threshold (dB) */ +# define MDCT_SW_SPARSE_THR 6554 /* 0.25f*0.8f in Q15*/ +# define MDCT_SW_1_VOICING_THR 29491 /* 0.9f in Q15*/ /* Voicing threshold */ +# define MDCT_SW_1_VOICING_THR2 23593 /* 0.9f*0.8f in Q15*/ +# define MDCT_SW_1_HI_ENER_LO_THR 3200 /* 12.5f in Q8 */ /* Hi band high energy threshold (dB) */ +# define MDCT_SW_1_SIG_HI_LEVEL_THR 7168 /* 28.0f in Q8 */ /* High signal level threshold above noise floor (dB) */ +# define MDCT_SW_1_SIG_LO_LEVEL_THR 5760 /* 22.5f in Q8 */ /* Low signal level threshold above noise floor (dB) */ +# define MDCT_SW_1_COR_THR 20480 /* 80.0f in Q8 */ /* Threshold on cor_map_sum to indicate strongly tonal signal */ +# define MDCT_SW_1_COR_THR2 16384 /* 80.0f*0.8f in Q8 */ +# define MDCT_SW_1_SPARSENESS_THR 21299 /* 0.65f in Q15*/ /* Threshold on spectrum sparseness */ +# define MDCT_SW_1_SPARSENESS_THR2 17039 /* 0.65f*0.8f in Q15*/ + +# define MDCT_SW_2_VOICING_THR 19661 /* 0.6f in Q15*/ /* Voicing threshold */ +# define MDCT_SW_2_VOICING_THR2 15729 /* 0.6f*0.8f in Q15*/ +# define MDCT_SW_2_HI_ENER_LO_THR 2432 /* 9.5f in Q8 */ /* Hi band low energy threshold (dB) */ +# define MDCT_SW_2_SIG_HI_LEVEL_THR 4864 /* 19.0f in Q8 */ /* High signal level threshold above noise floor (dB) */ +# define MDCT_SW_2_SIG_LO_LEVEL_THR 6016 /* 23.5f in Q8 */ /* Low signal level threshold above noise floor (dB) */ +# define MDCT_SW_2_COR_THR 16000 /* 62.5f in Q8 */ /* Threshold on cor_map_sum to indicate strongly tonal signal */ +# define MDCT_SW_2_COR_THR2 12800 /* 62.5f*0.8f in Q8 */ +# define MDCT_SW_2_SPARSENESS_THR 13107 /* 0.4f in Q15*/ /* Threshold on spectrum sparseness */ +# define MDCT_SW_2_SPARSENESS_THR2 10486 /* 0.4f*0.8f in Q15*/ + +static Word16 get_sparseness( /* Returns sparseness measure (Q15) */ + const Word16 Bin_E[], /* i : per bin energy dB Q7 */ + Word16 n, /* i : number of bins Q0 */ + Word16 thr /* i : peak threshold Q8 */ +) +{ + Word16 num_max, i; + + thr = add(thr, mult(thr, 4958)); /* Convert to 10*log() domain from 10*log10() domain, and also to Q7 */ + + thr = s_max(thr, 384); /* 3.0 in Q7 */ /* Set an absolute minimum for close to silent signals */ + + num_max = 0; + move16(); + + FOR (i=1; imdct_sw_enable, MODE1)||EQ_16(st->mdct_sw_enable,MODE2)) + { + Word16 hi_ener, frame_voicing, sparseness; + Word16 peak_count; + Word16 prefer_tcx, prefer_hq_core, switching_point, hi_sparse, sparse; + Word16 lob_cldfb, hib_cldfb, lob_fft, hib_fft; + Word16 i, tmp; + Word16 sig_lo_level_thr, sig_hi_level_thr, cor_thr, cor_thr2, voicing_thr, voicing_thr2, sparseness_thr, sparseness_thr2, hi_ener_lo_thr; + Word16 last_core; + + sp_floor = shl(sp_floor, 1); /* convert to Q8 */ + + IF (EQ_16(st->bwidth_fx, NB)) + { + lob_cldfb = 3200/400; + move16(); + hib_cldfb = 4000/400; + move16(); + lob_fft = (L_FFT/2)/2; /* 3.2 KHz */ move16(); + hib_fft = (40*(L_FFT/2))/64; /* 4.0 KHz */ move16(); + } + ELSE IF (EQ_16(st->bwidth_fx, WB)) + { + lob_cldfb = 4800/400; + move16(); + hib_cldfb = 8000/400; + move16(); + lob_fft = 3*L_FFT/2/4; /* 4.8 KHz */ move16(); + hib_fft = L_FFT/2; /* 6.4 KHz (should be 8 KHz) */ move16(); + } + ELSE + { + lob_cldfb = 6400/400; + move16(); + hib_cldfb = 16000/400; + move16(); + if (EQ_16(st->bwidth_fx, FB)) + { + hib_cldfb = 24000/400; + move16(); + } + lob_fft = L_FFT/2; /* 6.4 KHz */ move16(); + hib_fft = L_FFT/2; /* 6.4 KHz (should be 8 KHz) */ move16(); + } + + /* st->last_core_fx is reset to TCX_20_CORE in init_acelp() => fix it here */ + last_core = st->last_core_fx; + move16(); + test(); + if (EQ_16(st->last_codec_mode, MODE1)&&EQ_16(last_core,TCX_20_CORE)) + { + last_core = HQ_CORE; + move16(); + } + + /* Voicing */ + frame_voicing = add(shr(voicing[0], 1), shr(voicing[1], 1)); + + /* Spectral sparseness */ + sparseness = get_sparseness(st->lgBin_E_fx, lob_fft, sub(Etot, MDCT_SW_SIG_PEAK_THR)); + + /* Hi band energy */ + hi_ener = get_mean_ener(&enerBuffer[lob_cldfb], enerBuffer_exp, sub(hib_cldfb, lob_cldfb)); + + /* Hi band sparseness */ + IF (GE_16(st->bwidth_fx, SWB)) + { + /* For SWB, assume hi band sparseness based on 4.8 KHz-6.4 KHz band */ + lob_fft = 3*L_FFT/2/4; /* 4.8 KHz */ move16(); + } + peak_count = 0; + move16(); + tmp = add(MDCT_SW_SIG_LINE_THR, shr(Etot, 1)); /* Q7 */ + FOR (i=lob_fft; ilgBin_E_fx[i], tmp)) + { + peak_count = add(peak_count, 1); + } + } + + hi_sparse = 0; + move16(); + if (LE_16(peak_count, mult_r(sub(hib_fft, lob_fft), MDCT_SW_HI_SPARSE_THR))) + { + hi_sparse = 1; + move16(); + } + + sparse = 0; + move16(); + if (LE_16(peak_count, mult_r(sub(hib_fft, lob_fft), MDCT_SW_SPARSE_THR))) + { + sparse = 1; + move16(); + } + + /* Hysteresis */ + test(); + test(); + if (st->prev_hi_sparse > 0 && sparse > 0 && GE_16(s_min(s_min(voicing[0], voicing[1]), voicing[2]), MDCT_SW_1_VOICING_THR)) + { + hi_sparse = 1; + move16(); + } + + /* Allowed switching point? */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + switching_point = (NE_16(last_core, HQ_CORE) && NE_16(last_core, TCX_20_CORE) ) || /* previous core was non-MDCT */ + (LE_16(st->prev_hi_ener, MDCT_SW_HI_ENER_LO_THR) || LE_16(hi_ener, MDCT_SW_HI_ENER_LO_THR) ) || /* hi band is close to silent */ + (EQ_16(last_core, HQ_CORE) && (EQ_16(st->mdct_sw_enable, MODE1) || (hi_sparse > 0 && st->prev_hi_sparse >= 0 && LE_16(st->prev_hi_sparse, 1) ))) || /* HQ_CORE and hi band became sparse */ + (EQ_16(last_core, TCX_20_CORE) && (hi_sparse == 0 && st->prev_hi_sparse > 0)); /* TCX and hi band became dense */ + + IF (EQ_16(st->mdct_sw_enable, MODE1)) + { + sig_lo_level_thr = MDCT_SW_1_SIG_LO_LEVEL_THR; + move16(); + sig_hi_level_thr = MDCT_SW_1_SIG_HI_LEVEL_THR; + move16(); + cor_thr = MDCT_SW_1_COR_THR; + move16(); + cor_thr2 = MDCT_SW_1_COR_THR2; + move16(); + voicing_thr = MDCT_SW_1_VOICING_THR; + move16(); + voicing_thr2 = MDCT_SW_1_VOICING_THR2; + move16(); + sparseness_thr = MDCT_SW_1_SPARSENESS_THR; + move16(); + sparseness_thr2 = MDCT_SW_1_SPARSENESS_THR2; + move16(); + hi_ener_lo_thr = MDCT_SW_1_HI_ENER_LO_THR; + move16(); + } + ELSE /* st->mdct_sw_enable == MODE2 */ + { + sig_lo_level_thr = MDCT_SW_2_SIG_LO_LEVEL_THR; + move16(); + sig_hi_level_thr = MDCT_SW_2_SIG_HI_LEVEL_THR; + move16(); + cor_thr = MDCT_SW_2_COR_THR; + move16(); + cor_thr2 = MDCT_SW_2_COR_THR2; + move16(); + voicing_thr = MDCT_SW_2_VOICING_THR; + move16(); + voicing_thr2 = MDCT_SW_2_VOICING_THR2; + move16(); + sparseness_thr = MDCT_SW_2_SPARSENESS_THR; + move16(); + sparseness_thr2 = MDCT_SW_2_SPARSENESS_THR2; + move16(); + hi_ener_lo_thr = MDCT_SW_2_HI_ENER_LO_THR; + move16(); + } + + test(); + test(); + test(); + test(); + test(); + prefer_tcx = (GE_16(sub(Etot, sp_floor), sig_hi_level_thr)) && /* noise floor is low */ + (GE_16(cor_map_sum, cor_thr) || GE_16(frame_voicing, voicing_thr) || GE_16(sparseness, sparseness_thr) ) && /* strong tonal components */ + (LE_16(hi_ener, hi_ener_lo_thr) || hi_sparse > 0); /* high freqs have low energy or are sparse */ + + test(); + test(); + test(); + test(); + test(); + test(); + prefer_hq_core = (LT_16(sub(Etot, sp_floor), sig_lo_level_thr) ) || /* noise floor is very high */ + (LT_16(cor_map_sum, cor_thr2) && LT_16(frame_voicing, voicing_thr2) && LT_16(sparseness, sparseness_thr2) ) || /* too weak tonal components */ + (EQ_16(st->mdct_sw_enable, MODE1) && prefer_tcx == 0 && EQ_16(st->transientDetection.transientDetector.bIsAttackPresent, 1) ); + + /* Prefer HQ_CORE on transients */ + test(); + IF ( EQ_16(st->mdct_sw_enable, MODE2)&&EQ_16(st->transientDetection.transientDetector.bIsAttackPresent,1)) + { + prefer_tcx = 0; + move16(); + prefer_hq_core = 1; + move16(); + } + + test(); + test(); + test(); + IF (switching_point && (prefer_tcx || prefer_hq_core)) + { + IF (prefer_tcx) + { + st->core_fx = TCX_20_CORE; + move16(); + } + ELSE /* prefer_hq_core */ + { + st->core_fx = HQ_CORE; + move16(); + } + } + ELSE IF (EQ_16(last_core, HQ_CORE)||EQ_16(last_core,TCX_20_CORE)) + { + st->core_fx = last_core; + move16(); + } + + test(); + test(); + test(); + /* Prevent the usage of HQ_CORE on noisy-speech or inactive */ + IF (EQ_16(st->mdct_sw_enable, MODE2)&&EQ_16(st->core_fx,HQ_CORE)&&(EQ_16(st->flag_noisy_speech_snr,1)||vadflag==0)) + { + st->core_fx = TCX_20_CORE; + move16(); + } + + /* Update memories */ + st->prev_hi_sparse = add(st->prev_hi_sparse, hi_sparse); + move16(); + if (hi_sparse <= 0) + { + st->prev_hi_sparse = hi_sparse; + move16(); + } + st->prev_hi_sparse = s_min(st->prev_hi_sparse, 2); + st->prev_hi_ener = hi_ener; + move16(); + } +} + +void MDCT_selector_reset( + Encoder_State_fx *st /* i/o: Encoder State */ +) +{ + st->prev_hi_ener = 0; + move16(); + st->prev_hi_sparse = -1; + move16(); +} diff --git a/lib_enc/mslvq_enc_fx.c b/lib_enc/mslvq_enc_fx.c new file mode 100644 index 0000000..1a6e073 --- /dev/null +++ b/lib_enc/mslvq_enc_fx.c @@ -0,0 +1,898 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "cnst_fx.h" +#include "stl.h" + + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + +static Word32 quantize_data_fx( Word16 *data, const Word16 *w_in, Word16 *qin, Word16 *cv_out, Word16 *idx_lead, Word16 *idx_scale, const Word16 *sigma, const Word16 *inv_sigma, + const Word16 *scales, Word16 no_scales, const Word16 *no_lead ); +static Word32 q_data_fx(Word16 *pTmp1, const Word16 *w1, Word16 *quant, Word16 *cv_out, Word16 *idx_lead, Word16 *idx_scale, + const Word16 *p_sigma, const Word16 *p_inv_sigma, const Word16 *p_scales, Word16 *p_no_scales, + const Word16 *p_no_lead); +static void prepare_data_fx( Word16 *xsort, Word16 *sign, Word16 *data, Word32 *w, const Word16 *w_in, + const Word16 *sigma, const Word16 * inv_sigma, Word16 *p_sig ); +static Word32 calculate_min_dist_fx(Word16 cv_pot[LATTICE_DIM],Word16 no_scales, const Word16 *scale, + const Word32 *w, Word16 *p_best_scale, Word16 *p_best_idx, const Word16 *no_leaders, Word16 sig,Word16 *indx); +static Word16 find_pos_fx( Word16 *c, Word16 len, Word16 arg, Word16 *p ); +static void take_out_val_fx( Word16 *v, Word16 *v_out, Word16 val, Word16 len ); +static Word16 index_leaders_fx( Word16 *cv, Word16 idx_lead, Word16 dim ); +static Word16 c2idx_fx( Word16 n, Word16 *p, Word16 k ); +static Word16 encode_sign_pc1_fx( Word16 parity, Word16 *cv); +static Word32 encode_comb_fx( Word16 *cv, Word16 idx_lead ); +static void sort_desc_ind_fx( Word16 *s, Word16 len, Word16 *ind ); + + +/*-----------------------------------------------------------------* + * mslvq_fx() + * + * Encodes the LSF residual + *-----------------------------------------------------------------*/ +Word32 mslvq_fx ( + Word16 *pTmp, /* i : M-dimensional input vector x2.56*/ + Word16 *quant, /* o : quantized vector x2.56*/ + Word16 *cv_out, /* o : corresponding 8-dim lattice codevectors (without the scaling) Q13*/ + Word16 *idx_lead, /* o : leader index for each 8-dim subvector */ + Word16 *idx_scale, /* o : scale index for each subvector */ + Word16 *w, /* i : weights for LSF quantization Q10*/ + Word16 mode, /* i : number indicating the coding type (V/UV/G...)*/ + Word16 mode_glb, /* i : LVQ coding mode */ + Word16 pred_flag, /* i : prediction flag (0: safety net, 1,2 - predictive )*/ + Word16 no_scales[][2] +) +{ + Word32 dist, L_tmp; + const Word16 * p_scales, *p_sigma, *p_inv_sigma; + const Word16 *p_no_lead; + Word16 * p_no_scales; + + + dist = L_deposit_l(0); + p_no_scales = no_scales[mode_glb]; + move16(); + + IF ( pred_flag == 0 ) + { + p_sigma = sigma_MSLVQ_fx[mode]; + /* inverse sigma is precomputed to save complexity */ + p_inv_sigma = inv_sigma_MSLVQ_fx[mode]; + p_scales = scales_fx[mode_glb]; + p_no_lead = no_lead_fx[mode_glb]; + } + ELSE + { + p_sigma = sigma_p_fx[mode]; + /* inverse sigma is precomputed to save complexity */ + p_inv_sigma = inv_sigma_p_fx[mode]; + p_scales = scales_p_fx[mode_glb]; + p_no_lead = no_lead_p_fx[mode_glb]; + } + + /* first subvector */ + dist = quantize_data_fx( pTmp, w, quant, cv_out, idx_lead, idx_scale, + p_sigma, p_inv_sigma, p_scales, p_no_scales[0], p_no_lead ); + /* second subvector */ + L_tmp = quantize_data_fx( pTmp+LATTICE_DIM, w+LATTICE_DIM, quant+LATTICE_DIM, + cv_out+LATTICE_DIM, &idx_lead[1], &idx_scale[1], + p_sigma+LATTICE_DIM, p_inv_sigma+LATTICE_DIM, p_scales+MAX_NO_SCALES, + p_no_scales[1], p_no_lead+MAX_NO_SCALES ); + + dist = L_add(dist,L_tmp); + + return dist; +} +/*-----------------------------------------------------------------* + * q_data() + * + * (used for LSF quantization in CNG) + *-----------------------------------------------------------------*/ + +static Word32 q_data_fx( + Word16 *pTmp1, /* i: M-dimensional input vector x2.56 */ + const Word16 *w1, /* i: M-dimensional weight vector Q8 */ + Word16 *quant, /* o: quantized vector x2.56 */ + Word16 *cv_out, /* o: non-scaled lattice codevector x2.56 */ + Word16 *idx_lead, /* o: leader indexes for each subvector */ + Word16 *idx_scale, /* o: scale indexes for each subvector */ + const Word16 *p_sigma, /* i: standard deviation x2.56 */ + const Word16 *p_inv_sigma, /* i: inverse standard deviation Q15 */ + const Word16 *p_scales, /* i: scale values Q11 */ + Word16 *p_no_scales, /* i: number of scales/truncations for each subvector */ + const Word16 *p_no_lead /* i: number of leaders for each truncation and each subvector */ +) +{ + Word32 dist, L_tmp; + /* first subvector */ + dist = quantize_data_fx( pTmp1, w1, quant, cv_out, idx_lead, idx_scale, + p_sigma, p_inv_sigma, p_scales, p_no_scales[0], p_no_lead ); + /* second subvector */ + L_tmp = quantize_data_fx( pTmp1+LATTICE_DIM, w1+LATTICE_DIM, + quant+LATTICE_DIM, cv_out+LATTICE_DIM, &idx_lead[1], &idx_scale[1], + p_sigma+LATTICE_DIM, p_inv_sigma+LATTICE_DIM, p_scales+MAX_NO_SCALES, + p_no_scales[1], p_no_lead+MAX_NO_SCALES ); + + dist = L_add(dist,L_tmp); + + return dist; +} + +/*-----------------------------------------------------------------* + * mslvq_cng() + * + * Encodes the LSF residual in SID frames with LVQ + * LVQ has separate codebook for each individual first stage index + *-----------------------------------------------------------------*/ + + +Word32 mslvq_cng_fx ( + Word16 idx_cv, /* i : index of cv from previous stage */ + Word16 *pTmp, /* i : 16 dimensional input vector x2.56*/ + Word16 *quant, /* o : quantized vector x2.56*/ + Word16 *cv_out, /* o : corresponding 8-dim lattice codevectors (without the scaling) Q13*/ + Word16 *idx_lead, /* o : leader index for each 8-dim subvector */ + Word16 *idx_scale, /* o : scale index for each subvector */ + const Word16 *w, /* i : weights for LSF quantization Q10*/ + Word16 * no_scales +) +{ + Word32 dist; + const Word16 *p_scales, *p_sigma, *p_inv_sigma; + const Word16 *p_no_lead; + Word16 *p_no_scales; + Word16 mode_glb, mode, i; + Word16 pTmp1[M], w1[M]; + + dist = L_deposit_l(0); + mode = add(LVQ_COD_MODES, idx_cv); + move16(); + + /* for CNG there is only one bitrate but several lattice quantizer structures, + depending on the previous VQ stage */ + mode_glb = add(START_CNG, idx_cv); + move16(); + + p_sigma = sigma_MSLVQ_fx[mode]; + move16(); + p_inv_sigma = inv_sigma_MSLVQ_fx[mode]; + move16(); + p_scales = scales_fx[mode_glb]; + move16(); + p_no_lead = no_lead_fx[mode_glb]; + move16(); + p_no_scales = &no_scales[shl(mode_glb,1)]; + move16(); + + /* check if LSF component permutation is needed or not */ + IF ( cng_sort_fx[idx_cv] ) + { + FOR( i=0; i 0 ) + { + prepare_data_fx( cv_pot, sign, data, w, w_in, sigma, inv_sigma, &sig ); + move16(); + /* sorting of the input vector based on its absolute values; indx: permutation corresponding to the sorting */ + sort_desc_ind_fx( cv_pot, LATTICE_DIM, indx ); + smallest = indx[LATTICE_DIM-1]; + move16(); + + min_dist = calculate_min_dist_fx( cv_pot, no_scales, scale, w, &best_scale, &best_idx ,no_leaders, sig, indx); + + IF ( GT_16(best_scale,-1) ) + { + FOR(j=0; j 0 ; k-- ) + { + IF (sorted) + { + BREAK; + } + + sorted = 1; + move16(); + FOR ( i=0 ; i < k ; i++ ) + { + IF ( LT_16(s[i],s[i+1])) + { + sorted = 0; + move16(); + t = s[i]; + move16(); + s[i] = s[i+1]; + move16(); + s[i+1] = t; + move16(); + a = ind[i]; + move16(); + ind[i] = ind[i+1]; + move16(); + ind[i+1] = a; + move16(); + } + } + } + + return; +} + +/*-----------------------------------------------------------------* + * index_lvq() + * + * sorts in descending order and computes indices in the sorted vector + *-----------------------------------------------------------------*/ +void index_lvq_fx ( + Word16 *quant, /* i : codevector to be indexed (2 8-dim subvectors) Q13*/ + Word16 *idx_lead, /* i : leader class index for each subvector */ + Word16 *idx_scale, /* i :scale index for each subvector */ + Word16 mode, /* i : integer signalling the quantizer structure for the current bitrate */ + Word16 *index, /* o : encoded index (represented on 3 short each with 15 bits ) */ + Word32 * p_offset_scale1, /* i : scales for first subvector */ + Word32 * p_offset_scale2, /* i : scales for second subvector */ + Word16 * p_no_scales /* i : number of scales for each subvector */ +) +{ + Word32 index1, index2 + ; + Word16 len_offset; + Word64 idx64; + Word64 index2_64; + + len_offset = add(MAX_NO_SCALES,1); + move16(); + + index1 = 0; + move16(); + + /* for first subvector */ + IF ( GT_16(idx_scale[0],-1) ) + { + index1 = L_add(encode_comb_fx(quant, idx_lead[0]), L_add(table_no_cv_fx[idx_lead[0]] , p_offset_scale1[i_mult2(mode,len_offset) +idx_scale[0]])); + } + + /* for second subvector */ + index2 = L_deposit_l(0); + + IF ( GT_16(idx_scale[1], -1) ) + { + index2 = L_add(encode_comb_fx(&quant[LATTICE_DIM], idx_lead[1]), L_add(table_no_cv_fx[idx_lead[1]], p_offset_scale2[i_mult2(mode,len_offset)+idx_scale[1]])); + } + idx64 = W_mult0_32_32(index1, p_offset_scale2[mode*len_offset+p_no_scales[mode*2+1]]); + index2_64 = W_deposit32_l (index2); + idx64 = W_add_nosat(idx64, index2_64); + + /* convert to 3 short */ + index[0] = ((idx64)&(0x7fff)); + move16(); + index[1] = (idx64>>15)&(0x7fff); + move16(); + index[2] = (idx64>>30)&(0x7fff); + move16(); + return; +} + + +/*-----------------------------------------------------------------* + * encode_comb() + * + * creates an index for the lattice codevector + *-----------------------------------------------------------------*/ + +static Word32 encode_comb_fx( /* o : index of the absolute valued codevector*/ + Word16 *cv, /* i : codevector to be indexed Q13*/ + Word16 idx_lead /* i : leader class index, to know the values */ +) +{ + Word16 idx_sign, idx_ld_class; + Word32 L_tmp; + + idx_sign = encode_sign_pc1_fx( pl_par_fx[idx_lead], cv ); + move16(); + idx_ld_class = index_leaders_fx( cv, idx_lead, LATTICE_DIM ); + move16(); + + L_tmp = L_mac0(idx_ld_class, idx_sign,pi0_fx[idx_lead]); + + return L_tmp; +} + +/*-----------------------------------------------------------------* + * index_leaders() + * + * gives the index in a class of leaders without considering the sign yet + *-----------------------------------------------------------------*/ + +static Word16 index_leaders_fx( /* o : index */ + Word16 *cv, /* i : codevector to be indexed Q13*/ + Word16 idx_lead, /* i : leader class index */ + Word16 dim /* i : vector dimension */ +) +{ + Word16 index; + Word16 i, no_vals_loc, nr, p[LATTICE_DIM], dim_loc; + Word16 cv_copy[LATTICE_DIM], val_crt; + + no_vals_loc = no_vals_fx[idx_lead]; + move16(); + + IF ( EQ_16(no_vals_loc, 1)) + { + return 0; + } + + FOR( i=0; i 0 ) + { + cnt = add(cnt, 1); + } + } + + return idx_sign; +} + +/*-----------------------------------------------------------------* + * take_out_val() + * + * removes the value val from the vector v + *-----------------------------------------------------------------*/ + +static void take_out_val_fx( + Word16 *v, /* i : input vector x2.56*/ + Word16 *v_out, /* o : output vector without the value val */ + Word16 val, /* i : value to be removed x2.56*/ + Word16 len /* i : input vector length */ +) +{ + Word16 i, cnt; + + cnt = 0; + move16(); + + FOR( i=0; i 0) + { + L_acc = L_deposit_l(0); + FOR (i=0; i 0) + { + Lcorx2 = L_deposit_l(0); + Lcorxy = L_deposit_l(0); + stemp = ind_mins[0]; + move16(); + Lcory2 = L_mult(old_S[stemp],old_S[stemp]); + k = 1; + move16(); + + FOR (i = add(stemp,1); i <= ind_mins[N_mins]; i++) + { + IF (EQ_16(i,ind_mins[k])) + { + /* include the last peak point (new minimum) to the corr. sum */ + Lcory2 = L_mac(Lcory2, old_S[i], old_S[i]); + + /* calculation of the norm. peak correlation */ + test(); + IF (Lcorx2 != 0 && Lcory2 != 0) + { + /* corxy * corxy*/ + tmp16 = sub(norm_l(Lcorxy),1); + corxy = extract_h(L_shl(Lcorxy, tmp16)); + corxy = mult_r(corxy, corxy); + /* (corx2 * cory2) */ + Expx2 = norm_l(Lcorx2); + Expy2 = norm_l(Lcory2); + corx2 = extract_h(L_shl(Lcorx2, Expx2)); + cory2 = extract_h(L_shl(Lcory2, Expy2)); + corx2 = mult_r(corx2, cory2); + Expx2 = add(Expy2, Expx2); + /* Validate num < den */ + cor = sub(corx2, corxy); + cor = shr(cor, 15); + /* Add 1 to tmp16 & shr by 2 if corxy > corx2 */ + tmp16 = sub(tmp16, cor); + corxy = shl(corxy, cor); + corxy = shl(corxy, cor); + /* cor = corxy * corxy / (corx2 * cory2) */ + corxy = div_s(corxy, corx2); + cor = shr(corxy, sub(shl(tmp16, 1), Expx2)); /* Q15 */ + } + ELSE + { + cor = 0; + move16(); + } + + /* save the norm. peak correlation in the correlation map */ + FOR (j=ind_mins[k-1]; j 0) || (cor_strong != 0) ) + { + harm = 1; + move16(); + } + + /*------------------------------------------------------------------* + * updating of the decision threshold + *------------------------------------------------------------------*/ + + stemp = add(*multi_harm_limit, THR_CORR_STEP_FX); + if (GT_32(Lcor_map_LT_sum, THR_CORR_FX)) /* Q15 */ + { + /* *multi_harm_limit -= THR_CORR_STEP_FX */ + stemp = sub(*multi_harm_limit, THR_CORR_STEP_FX); + } + + stemp = s_min(stemp, THR_CORR_MAX_FX); + *multi_harm_limit = s_max(stemp, THR_CORR_MIN_FX); + move16(); + + IF (N_mins <= 0) + { + set16_fx(old_S, 0, L); + } + + return harm; +} diff --git a/lib_enc/nelp_enc_fx.c b/lib_enc/nelp_enc_fx.c new file mode 100644 index 0000000..c0165d4 --- /dev/null +++ b/lib_enc/nelp_enc_fx.c @@ -0,0 +1,975 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "control.h" +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" + + +#include "stl.h" + +/*===================================================================*/ +/* FUNCTION : quantize_uvg_fx() */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : This function returns the quantized gain vector */ +/* and corresponding table indices, given the + input unquantized gain vector */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16*) G : Un-quantized gain vector (Q0) */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16) iG1 : UVG1CB_fx table index (Q0) */ +/* _ (Word16*) iG2 : UVG2CB_fx table indices (Q0) */ +/* _ (Word16*) quantG : Output quantized gain vector */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None. */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None. */ +/*===================================================================*/ + +void quantize_uvg_fx(Word16 *G, Word16 *iG1, Word16 *iG2, Word16 *quantG, Word16 bwidth_fx) +{ + Word16 G1[2], G2[10],L16,L16_1; + Word16 i, j, k, ind,temp; + Word32 mmse; + Word16 exp,tmp,frac; + Word32 Lacc,Lexp[2],L_tmp; + const Word16 (*UVG1CB_fx)[2]=NULL; + const Word16 (*UVG2CB1_fx)[5]=NULL; + const Word16 (*UVG2CB2_fx)[5]=NULL; + test(); + IF( EQ_16(bwidth_fx,NB)) + { + UVG1CB_fx = UVG1CB_NB_FX; + move16();/*Q13 */ + UVG2CB1_fx = UVG2CB1_NB_FX; + move16();/*Q12 */ + UVG2CB2_fx = UVG2CB2_NB_FX; + move16();/*Q12 */ + } + ELSE IF( EQ_16(bwidth_fx,WB)||EQ_16(bwidth_fx,SWB)) + { + UVG1CB_fx = UVG1CB_WB_FX; + move16();/*Q13 */ + UVG2CB1_fx = UVG2CB1_WB_FX; + move16();/*Q12 */ + UVG2CB2_fx = UVG2CB2_WB_FX; + move16();/*Q12 */ + } + + + FOR (i=0; i<2; i++) + { + Lacc = L_deposit_l(0); + FOR (j=0; j<5; j++) + { + ind=add(shr(extract_l(L_mult(i,5)),1),j); + Lacc=L_mac0(Lacc,G[ind],G[ind]); /*Q0 */ + } + + IF (Lacc==0) + { + Lacc = L_deposit_l(1); /* to avoid log10(0) */ + } + + /*G1[i] = (float) log10(sqrt(G1[i]/5)); */ + L_tmp = Mult_32_16(Lacc,13108); + IF(L_tmp) + { + exp = norm_l(L_tmp); + frac = Log2_norm_lc(L_shl(L_tmp,exp)); + exp = (30-exp-1); + move16();/*(+1)=/2 in log */ + L_tmp = Mpy_32_16(exp,frac,4932); /*Q16 ; 0.5*log10(2) in Q15 */ + G1[i]= round_fx(L_shl(L_tmp,13)); /*Q13 */ + } + ELSE + { + G1[i] = 0; + move16(); + } + + } + + + mmse = L_add(MAX_32, 0); + *iG1=0; + move16(); + FOR (i=0; i< UVG1_CBSIZE; i++) + { + L16 = shr(sub(G1[0],UVG1CB_fx[i][0]),1); /* Q12 */ + L16_1 = shr(sub(G1[1],UVG1CB_fx[i][1]),1); /* Q12 */ + Lacc = 0; + Lacc = L_mac0(Lacc,L16,L16); /*Q24 */ + Lacc = L_mac0(Lacc,L16_1,L16_1);/*Q24 */ + + IF (LT_32(Lacc,mmse)) + { + *iG1 = i; + move16(); + mmse = Lacc; + } + + } + + L_tmp = L_mult0(UVG1CB_fx[*iG1][0], 27213);/*Q26 */ + L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */ + L_tmp = Pow2(30, frac); + exp = exp-30; /*move16(); */ + Lexp[0] = L_shl(L_tmp,exp +15 ); + + + L_tmp = L_mult0(UVG1CB_fx[*iG1][1], 27213);/*Q26 */ + L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */ + frac = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */ + L_tmp = Pow2(30, frac); + exp = exp-30; /*move16(); */ + Lexp[1] = L_shl(L_tmp,exp +15 ); + + + FOR (i=0; i<2; i++) + { + FOR (j=0; j<5; j++) + { + exp = norm_l(Lexp[i]); + tmp = extract_h(L_shl(Lexp[i],exp)); + exp = sub(sub(30,exp),15); + tmp = div_s(16384,tmp); /*Q(15+exp) */ + L_tmp = L_shr(L_mult0(G[i*5+j],tmp),exp+3); /*Q12 */ + G2[i*5+j] = extract_l(L_tmp); /*Q12 */ + } + } + + + FOR (i=0; i<2; i++) + { + mmse=MAX_32; + iG2[i]=0; + FOR (j=0; jrf_mode; + + if (EQ_16(st_fx->last_nelp_mode_fx,1)&&NE_16(st_fx->bwidth_fx,st_fx->last_bwidth_fx)) + { + st_fx->last_nelp_mode_fx = 0; + } + + qIn = *qIn1; + move16(); + test(); + IF (EQ_16(st_fx->bwidth_fx,NB)) + { + IF (st_fx->last_nelp_mode_fx != 1) + { + BP1_ORDER = 7; + move16(); + set32_fx(st_fx->bp1_filt_mem_nb_fx, 0, BP1_ORDER*2); + st_fx->qprevGain_fx = 0; + move16(); + } + } + ELSE IF (EQ_16(st_fx->bwidth_fx,WB)||EQ_16(st_fx->bwidth_fx,SWB)) + { + IF (st_fx->last_nelp_mode_fx != 1) + { + BP1_ORDER =4; + move16(); + set16_fx(st_fx->bp1_filt_mem_wb_fx, 0, BP1_ORDER*2); + } + } + + IF (st_fx->last_nelp_mode_fx != 1) + { + test(); + IF (st_fx->bwidth_fx == WB || EQ_16(st_fx->bwidth_fx,SWB)) + { + set16_fx(st_fx->shape1_filt_mem_fx, 0, 10); + set16_fx(st_fx->shape2_filt_mem_fx, 0, 10); + set16_fx(st_fx->shape3_filt_mem_fx, 0, 10); + set16_fx(st_fx->txlpf1_filt1_mem_fx, 0, 10); + set16_fx(st_fx->txlpf1_filt2_mem_fx, 0, 10); + set16_fx(st_fx->txhpf1_filt1_mem_fx, 0, 10); + set16_fx(st_fx->txhpf1_filt2_mem_fx, 0, 10); + st_fx->qprevIn_fx = 0; + move16(); + st_fx->qprevGain_fx = 0; + move16(); + } + } + + /* Start Unvoiced/NELP Processing */ + test(); + IF ( EQ_16(st_fx->bwidth_fx,WB)||EQ_16(st_fx->bwidth_fx,SWB)) + { + qE1 = qIn; + move16(); + E1_fx = L_deposit_l(0); + FOR (i=0 ; itxlpf1_filt1_mem_fx, 10, (qf-st_fx->qprevIn_fx)); + pz_filter_sp_fx(txlpf1_num_coef_fx,txlpf1_den_coef_fx, in_fx, filtRes_fx, st_fx->txlpf1_filt1_mem_fx,10,10, L_FRAME, 3);/*1 = (16-qformat of shape1 cofficient) */ + + qEL1 = qf; + move16(); + EL1_fx = L_deposit_l(0); + FOR (i=0 ; itxhpf1_filt1_mem_fx, 10, qf-st_fx->qprevIn_fx); + pz_filter_sp_fx(txhpf1_num_coef_fx,txhpf1_den_coef_fx, in_fx, filtRes_fx, st_fx->txhpf1_filt1_mem_fx,10,10, L_FRAME, 3);/*1 = (16-qformat of shape1 cofficient) */ + st_fx->qprevIn_fx = qf; + move16(); + + qEH1 = qf; + move16(); + EH1_fx = L_deposit_l(0); + FOR (i=0 ; ilast_nelp_mode_fx != 1) /* if prev frame was not NELP then init mem*/ + { + st_fx->nelp_gain_mem_fx = Gains_fx[0]; + move16(); + qNelpGain = qGain; + move16(); + } + + /* tmp = (float) (20.0 * (log10 (Gains[0]) - log10 (st->nelp_gain_mem) ) ); */ + /* var_dB = tmp * tmp; */ + L_tmp = L_deposit_l(Gains_fx[0]); + L_tmp = L_max(L_tmp,1); + exp2 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, exp2);/*15+qEL1-qEL2-exp1+exp2 */ + exp2 = 30-exp2-qGain; + move16(); + tmp1 = Log2_norm_lc(L_tmp); + Ltemp = Mpy_32_16(exp2, tmp1,9864); /*log(2) in Q13 format = Q0 format */ + /*tmp1 = round_fx(L_shl(Ltemp,12)); Q12 */ + + L_tmp = L_deposit_l(st_fx->nelp_gain_mem_fx); /*Q0 */ + L_tmp = L_max(L_tmp,1); + exp2 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, exp2);/*15+qEL1-qEL2-exp1+exp2 */ + exp2 = 30-exp2-qNelpGain; + move16(); + tmp2 = Log2_norm_lc(L_tmp); + Ltemp1 = Mpy_32_16(exp2, tmp2,9864); /*log(2) in Q13 format = Q0 format */ + Ltemp1 = L_sub(Ltemp, Ltemp1);/*Q16 */ + Ltemp = Mult_32_16(Ltemp1, 20480);/*Q11 (20 in Q10) */ + L_tmp = L_shl(Ltemp,12);/*Q23 */ + var_dB_fx = Mult_32_32(L_tmp, L_tmp);/*Q15 */ + + FOR (i = 1; i < 10; i++) + { + L_tmp = L_deposit_l(Gains_fx[i]); + L_tmp = L_max(L_tmp,1); + exp2 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, exp2);/*15+qEL1-qEL2-exp1+exp2 */ + exp2 = 30-exp2-qGain; + move16(); + tmp1 = Log2_norm_lc(L_tmp); + Ltemp = Mpy_32_16(exp2, tmp1,9864); /*log(2) in Q13 format = Q0 format */ + + L_tmp = L_deposit_l(Gains_fx[i-1]); /*Q0 */ + L_tmp = L_max(L_tmp,1); + exp2 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, exp2);/*15+qEL1-qEL2-exp1+exp2 */ + exp2 = 30-exp2-qGain; + move16(); + tmp2 = Log2_norm_lc(L_tmp); + Ltemp1 = Mpy_32_16(exp2, tmp2,9864); /*log(2) in Q13 format = Q0 format */ + Ltemp1 = L_sub(Ltemp, Ltemp1);/*Q16 */ + Ltemp = Mult_32_16(Ltemp1, 20480);/*Q11 (20 in Q10) */ + L_tmp = L_shl(Ltemp,12);/*Q23 */ + L_tmp = Mult_32_32(L_tmp, L_tmp);/*Q15 */ + var_dB_fx = L_add(L_tmp, var_dB_fx);/*Q15 */ + } + + IF (st_fx->last_nelp_mode_fx!=1) + { + /*var_dB *= 0.111f; */ + var_dB_fx = Mult_32_16(var_dB_fx, 3637); /*0.111 in Q15 */ + } + ELSE + { + /*var_dB *= 0.1f; */ + var_dB_fx = Mult_32_16(var_dB_fx, 3277); /*0.1 in Q15 */ + } + + max1 = 0; + move16(); + FOR(i = 0; i < 10; i++) + { + max1=s_max(max1, abs_s(Gains_fx[i])); + } + + qf=norm_s((Word16)max1); + test(); + IF((qf == 0)&&(((Word16)max1)==0)) + { + qf= 15; + move16(); + } + qf = sub(qf,1); + qGain = add(qGain,qf); + + Scale_sig(Gains_fx, 10, qf); + + L_tmp = L_sub(var_dB_fx, 655360); /* 20 in Q15 */ + Ltemp = L_shr_r(L_tmp, 2);/*Q15 */ + { + /*exp = pow(2, x*log2(e)) */ + L_tmp = Mult_32_16(Ltemp, 23637); /*15 + 14 -15 ->Q14 */ + L_tmp = L_shl(L_tmp, 2); /*Q16 */ + f_Noise = L_Extract_lc(L_tmp, &e_Noise); /*Q16 */ + etmp = extract_l(Pow2(14, f_Noise)); /* Put 14 as exponent */ + e_Noise = sub(e_Noise, 14); /* Retreive exponent of etmp */ + + + IF(e_Noise > 0) + { + L_tmp = L_shl(etmp,e_Noise); /* Result in Q30 */ + L_tmp = L_add(1, L_tmp); + + exp1 = norm_l(L_tmp); + tmp1 = extract_h(L_shl(L_tmp, exp1));/*exp1-16 */ + tmp1 = div_s(16384, tmp1);/*14-(exp1-16)-> 30+15-exp1 */ + fdbck_fx = mult(26870, tmp1);/*45-exp1+15-15=>45-exp1 */ + fdbck_fx = shr_r(fdbck_fx, 14); + exp1 = sub(31,exp1); + } + ELSE + { + L_tmp = L_shl(etmp,add(e_Noise, 14)); /* Result in Q30 */ + L_tmp = L_add(16384, L_tmp); + + exp1 = norm_l(L_tmp); + tmp1 = extract_h(L_shl(L_tmp, exp1));/*14+exp1-16 */ + tmp1 = div_s(16384, tmp1);/*14-(14+exp1-16)-> 16+15-exp1 */ + fdbck_fx = mult(26870, tmp1);/*31-exp1+15-15=>31-exp1 */ + exp1 = sub(31,exp1); + } + } + + IF(exp1 == 31) + { + L_const_1=0x7fffffff; + move32(); + } + ELSE + { + L_const_1 = L_shl(1, exp1); + } + + l_nelp_gain_mem = L_deposit_l(st_fx->nelp_gain_mem_fx); + IF(NE_16(qNelpGain,qGain)) + { + l_nelp_gain_mem = L_shl(l_nelp_gain_mem, sub(qGain, qNelpGain)); + } + + FOR (i = 0; i < 10; i++) + { + /*Gains[i] = (float)((1.0f - fdbck) * Gains[i] + fdbck * st->nelp_gain_mem); */ + L_tmp = L_sub(L_const_1, L_deposit_l(fdbck_fx));/*31-exp1 */ + L_tmp = Mult_32_16(L_tmp, Gains_fx[i]);/*exp1+qGain-15=>exp1-15+qGain */ + Ltemp1 = Mult_32_16(l_nelp_gain_mem, fdbck_fx);/*exp1+qGain-15 */ + L_tmp = L_add(L_tmp, Ltemp1); + L_tmp = L_shr_r(L_tmp, (exp1-15)); + Gains_fx[i] = round_fx(L_shl(L_tmp,16)); + move16(); + l_nelp_gain_mem = L_tmp; + } + + st_fx->nelp_gain_mem_fx = round_fx(L_shl(l_nelp_gain_mem,16)); + + Scale_sig(&st_fx->nelp_gain_mem_fx, 1, -qGain); + Scale_sig(Gains_fx, 10, -qGain); + qGain =0; + move16(); + + quantize_uvg_fx(Gains_fx, &iG1_fx, iG2_fx, Gains_fx, st_fx->bwidth_fx); + + IF( EQ_16(rf_flag,1)) + { + st_fx->rf_indx_nelp_iG1[0] = iG1_fx; + st_fx->rf_indx_nelp_iG2[0][0] = iG2_fx[0]; + st_fx->rf_indx_nelp_iG2[0][1] = iG2_fx[1]; + } + ELSE + { + push_indice_fx( st_fx, IND_IG1, iG1_fx, 5); + push_indice_fx( st_fx, IND_IG2A, iG2_fx[0], 6 ); + push_indice_fx( st_fx, IND_IG2B, iG2_fx[1], 6 ); + } + + test(); + IF (EQ_16(st_fx->bwidth_fx,WB)||EQ_16(st_fx->bwidth_fx,SWB)) + { + gain_fac_fx = 19005; + move16();/* 1.16f in Q14 */ + } + ELSE + { + gain_fac_fx = 22446; + move16(); /* 1.37f in Q14 */ + } + + /* Normalize Gains_fx[10] with headroom 4 */ + /* This fills up qGain with some new value */ + normalize_arr(Gains_fx, &qGain, 10, 4); + + generate_nelp_excitation_fx(&(st_fx->nelp_enc_seed_fx), Gains_fx, ptr_fx, gain_fac_fx); + test(); + IF (EQ_16(st_fx->bwidth_fx,WB)||EQ_16(st_fx->bwidth_fx,SWB)) + { + BP1_ORDER = 4; + Scale_sig(st_fx->bp1_filt_mem_wb_fx, BP1_ORDER*2, qGain-st_fx->qprevGain_fx);/*qf-qAdj */ + pz_filter_sp_fx(bp1_num_coef_wb_fx,bp1_den_coef_wb_fx, ptr_fx, ptr_tmp_fx, st_fx->bp1_filt_mem_wb_fx, BP1_ORDER, BP1_ORDER, L_FRAME, 2); + Copy(ptr_tmp_fx,ptr_fx,L_FRAME); + } + ELSE IF (EQ_16(st_fx->bwidth_fx,NB)) + { + BP1_ORDER = 7; + move16(); + Scale_sig32(st_fx->bp1_filt_mem_nb_fx, BP1_ORDER*2, (qGain - st_fx->qprevGain_fx)); + pz_filter_dp_fx(bp1_num_coef_nb_fx_order7, bp1_den_coef_nb_fx_order7, ptr_fx, ptr_tmp_fx, st_fx->bp1_filt_mem_nb_fx, BP1_ORDER, BP1_ORDER, L_FRAME, (sub(16,BP1_COEF_NB_QF_ORDER7))); + Copy(ptr_tmp_fx,ptr_fx,L_FRAME); + + Scale_sig(ptr_fx, L_FRAME, -1); /* bring exc to qgain-1 */ + *qIn1 = qGain-1; /* use this temp only in the parent */ + } + + E3_fx = L_deposit_l(0); + FOR (i=0 ; ibwidth_fx == WB|| EQ_16(st_fx->bwidth_fx,SWB)) + { + Scale_sig(st_fx->shape1_filt_mem_fx, 10, (qGain-st_fx->qprevGain_fx)); + pz_filter_sp_fx(shape1_num_coef_fx,shape1_den_coef_fx, ptr_fx, ptr_tmp_fx, st_fx->shape1_filt_mem_fx,10,10, L_FRAME, 1);/*1 = (16-qformat of shape1 cofficient) */ + Copy(ptr_tmp_fx,ptr_fx,L_FRAME); + + qf = qGain; + move16(); + E2_fx = L_deposit_l(0); + FOR (i=0 ; i 30-qE1-exp1 */ + exp1 = sub(exp1, 30-qE1); + + L_tmp = L_deposit_h(tmp1); + L_tmp = Isqrt_lc(L_tmp, &exp1); + Ltemp = L_shl(L_tmp, sub(exp1, 12)); + R_fx = round_fx(Ltemp); + } + ELSE + { + exp1 = norm_l(E1_fx); + tmp1 = extract_h(L_shl(E1_fx, exp1));/*qE1+exp1-16 */ + tmp1 = div_s(16384, tmp1);/*14-(qE1+exp1-16)-> 30-qE1-exp1 */ + L_tmp = Mult_32_16(E2_fx, tmp1);/*qE2+30-qE1-exp1-15=>15+qE2-qE1-exp1 */ + + exp2 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, exp2);/*15+qE2-qE1-exp1+exp2 */ + exp2 = 30-(15+qE2-qE1-exp1+exp2); + move16(); + L_tmp = Isqrt_lc(L_tmp, &exp2);/*Q(31+exp2) */ + R_fx = round_fx(L_tmp); + exp1 = 31-exp2-16-7; + move16(); + } + + FOR (i=0; itxlpf1_filt2_mem_fx, 10, (qf1-st_fx->qprevGain_fx)); + + pz_filter_sp_fx(txlpf1_num_coef_fx,txlpf1_den_coef_fx, filtRes_fx, ptr_tmp_fx, st_fx->txlpf1_filt2_mem_fx,10,10, L_FRAME, 3);/*1 = (16-qformat of shape1 cofficient) */ + Copy(ptr_tmp_fx,filtRes_fx,L_FRAME); + + qEL2 = qf1; + move16(); + EL2_fx = L_deposit_l(0); + FOR (i=0; itxhpf1_filt2_mem_fx, 10, (qf-st_fx->qprevGain_fx)); + pz_filter_sp_fx(txhpf1_num_coef_fx,txhpf1_den_coef_fx, filtRes_fx, ptr_tmp_fx, st_fx->txhpf1_filt2_mem_fx,10,10, L_FRAME, 3);/*1 = (16-qformat of shape1 cofficient) */ + + Copy(ptr_tmp_fx,filtRes_fx,L_FRAME); + + qEH2 = qf; + move16(); + EH2_fx = L_deposit_l(0); + FOR (i=0; i 30-qEL2-exp1 */ + L_tmp = Mult_32_16(EL1_fx, tmp1);/*qEL1+30-qEL2-exp1-15=>15+qE1-qEL2-exp1 */ + + exp2 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, exp2);/*15+qEL1-qEL2-exp1+exp2 */ + exp2 = 30-(30+qEL1-qEL2-exp1+exp2); + move16(); + tmp1 = Log2_norm_lc(L_tmp); + Ltemp = Mpy_32_16(exp2, tmp1,9864); /*10*log(2) in Q15 format = Q0 format */ + tmp1 = round_fx(L_shl(Ltemp,12));/* Q12 */ + RL_fx = L_mult0(tmp1, 10); + } + + IF(EH2_fx==0) + { + exp2 = norm_l(EH2_fx); + L_tmp = L_shl(EH2_fx, exp2); + exp2 = 30-exp2-qEH2; + move16(); + tmp1 = Log2_norm_lc(L_tmp); + Ltemp = Mpy_32_16(exp2, tmp1,9864); /*10*log(2) in Q13 format = Q0 format */ + tmp1 = round_fx(L_shl(Ltemp,12));/* Q12 */ + RH_fx = L_mult0(tmp1, 10); + } + ELSE + { + exp1 = norm_l(EH2_fx); + tmp1 = extract_h(L_shl(EH2_fx, exp1));/*qEH2+exp1-16 */ + tmp1 = div_s(16384, tmp1);/*14-(qEH2+exp1-16)-> 30-qEH2-exp1 */ + L_tmp = Mult_32_16(EH1_fx, tmp1);/*15+qEH1-qEH2-exp1 */ + + exp2 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, exp2);/*15+qEH1-qEH2-exp1+exp2 */ + exp2 = 30-(30+qEH1-qEH2-exp1+exp2); + move16(); + tmp1 = Log2_norm_lc(L_tmp); + Ltemp = Mpy_32_16(exp2, tmp1,9864); /*10*log(2) in Q13 format = Q0 format */ + tmp1 = round_fx(L_shl(Ltemp,12));/* Q12 */ + RH_fx = L_mult0(tmp1, 10); + } + + fid = 0; + move16(); + IF (LT_32(RL_fx, -12288)) /* -3 in Q12 */ + { + fid = 1; + move16(); + } + ELSE IF (LT_32(RH_fx, -12288)) /* -3 in Q12 */ + { + fid = 2; + move16(); + } + + IF( rf_flag == 0 ) + { + + SWITCH(fid) + { + case 1: + /* Update other filter memory */ + Scale_sig(st_fx->shape3_filt_mem_fx, 10, (qGain-st_fx->qprevGain_fx)); + pz_filter_sp_fx(shape3_num_coef_fx,shape3_den_coef_fx, ptr_fx, filtRes_fx, st_fx->shape3_filt_mem_fx,10,10, L_FRAME, 1);/*1 = (16-qformat of shape1 cofficient) */ + + /* filter the residual to desired shape */ + Scale_sig(st_fx->shape2_filt_mem_fx, 10, (qGain-st_fx->qprevGain_fx)); + pz_filter_sp_fx(shape2_num_coef_fx,shape2_den_coef_fx, ptr_fx, ptr_tmp_fx, st_fx->shape2_filt_mem_fx,10,10, L_FRAME, 1);/*1 = (16-qformat of shape1 cofficient) */ + Copy(ptr_tmp_fx,ptr_fx,L_FRAME); + + BREAK; + case 2: + /* Update other filter memory */ + Scale_sig(st_fx->shape2_filt_mem_fx, 10, (qGain-st_fx->qprevGain_fx)); + pz_filter_sp_fx(shape2_num_coef_fx,shape2_den_coef_fx, ptr_fx, filtRes_fx, st_fx->shape2_filt_mem_fx,10,10, L_FRAME, 1);/*1 = (16-qformat of shape1 cofficient) */ + + /* filter the residual to desired shape */ + Scale_sig(st_fx->shape3_filt_mem_fx, 10, (qGain-st_fx->qprevGain_fx)); + pz_filter_sp_fx(shape3_num_coef_fx,shape3_den_coef_fx, ptr_fx, ptr_tmp_fx, st_fx->shape3_filt_mem_fx,10,10, L_FRAME, 1);/*1 = (16-qformat of shape1 cofficient) */ + + Copy(ptr_tmp_fx,ptr_fx,L_FRAME); + + BREAK; + default: + Scale_sig(st_fx->shape2_filt_mem_fx, 10, (qGain-st_fx->qprevGain_fx)); + pz_filter_sp_fx(shape2_num_coef_fx,shape2_den_coef_fx, ptr_fx, filtRes_fx, st_fx->shape2_filt_mem_fx,10,10, L_FRAME, 1);/*1 = (16-qformat of shape1 cofficient) */ + + Scale_sig(st_fx->shape3_filt_mem_fx, 10, (qGain-st_fx->qprevGain_fx)); + pz_filter_sp_fx(shape3_num_coef_fx,shape3_den_coef_fx, ptr_fx, filtRes_fx, st_fx->shape3_filt_mem_fx,10,10, L_FRAME, 1);/*1 = (16-qformat of shape1 cofficient) */ + + BREAK; + } + + qE2 = qGain; + move16(); + + E2_fx = L_deposit_l(0); + FOR (i=0 ; i 30-qE3-exp1 */ + exp1 = sub(exp1, 30-qE3); + + L_tmp = L_deposit_h(tmp1); + L_tmp = Isqrt_lc(L_tmp, &exp1); + Ltemp = L_shl(L_tmp, sub(exp1, 12)); + R_fx = round_fx(Ltemp); + } + ELSE + { + exp1 = norm_l(E3_fx); + tmp1 = extract_h(L_shl(E3_fx, exp1));/*qE3+exp1-16 */ + tmp1 = div_s(16384, tmp1);/*14-(qE3+exp1-16)-> 30-qE3-exp1 */ + L_tmp = Mult_32_16(E2_fx, tmp1);/*qE2+30-qE3-exp1-15=>15+qE2-qE3-exp1 */ + + exp2 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, exp2);/*15+qE2-qE3-exp1+exp2 */ + exp2 = 30-(15+qE2-qE3-exp1+exp2); + move16(); + L_tmp = Isqrt_lc(L_tmp, &exp2);/*Q(31+exp2) */ + R_fx = round_fx(L_tmp); + exp1 = 31-exp2-16-7; + move16(); + } + + FOR (i=0; irf_indx_nelp_fid[0] = fid; + move16(); + } + ELSE + { + push_indice_fx( st_fx, IND_NELP_FID, fid, 2 ); + } + } + + st_fx->qprevGain_fx = qGain; + move16(); + + IF( rf_flag == 0 ) + { + FOR (i = 0; i < L_FRAME; i++) + { + exc_fx[i] = ptr_fx[i]; + move16(); + } + } + + return; +} + + diff --git a/lib_enc/nois_est_fx.c b/lib_enc/nois_est_fx.c new file mode 100644 index 0000000..a66fd17 --- /dev/null +++ b/lib_enc/nois_est_fx.c @@ -0,0 +1,1721 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "cnst_fx.h" +#include "prot_fx.h" +#include "stl.h" +#include "basop_util.h" + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +#define ALPHA_FX 3277 /*.1 Q15*/ +#define ALPHAM1_FX 29491 /*.9 Q15*/ + +#define TH_PC_FX 12 /* max sum of pitch differencies */ + +#define BCKR_SLOW_UPDATE_SCALE_FX 3277 /*Q15 Step size for slow bckr update */ +#define COR_MIN16_FX 17039 /*.52 Q15 */ +#define COR_MAX16_FX 27853 /*.85 Q15 */ + +/* 10.0e5f causes problems with music - as the noise estimate starts to track the music */ +#define TH_STA16_FX (350000<<10) /* MODE1: 3.5e5f */ + +#define TH_EPS16_FX 3277 /* Q11 (1.6) tuned for speech only, not for music */ +#define K_16_FX 25690 /* Q20 (0.0245f) */ +#define C_16_FX -1925 /* Q13 (-0.235f) */ +#define ALPHA_MAX16_FX 32440 /* Q15 (0.99) */ + +#define COR_MIN8_FX 21299 /*.65 Q15 */ +#define COR_MAX8_FX 22938 /*.70 Q15 */ +#define TH_EPS8_FX 21299 /* 10.4 in Q11 Thresholds for NB processing - ... */ +#define TH_STA8_FX (500000<<10) +#define K_8_FX 9452 /* Q20 (0.0091f) */ +#define C_8_FX 2609 /* Q13 (0.0091f) */ +#define ALPHA_MAX8_FX 32735 /* Q15 (0.999) */ + +#define HC_CNT_SLOW_FX 80 /* limit for harm corr count slow */ + +#define HE_LT_CNT_PRE_FX 50 +#define HE_LT_CNT_INIT_FX 150 +#define HE_LT_CNT_PRE_SHORT_FX 250 +#define HE_LT_CNT_FX 30 + +#define LN_E_MIN_PLUS_ONE_FX 1 /* max(1, ln(E_MIN+1.0)) = max(1,ln(0.0035f+1f)) in Q8 */ +#define COR_MAX_NNE_FX 27853 /* 0.85 Q15 */ + +#define HE_LT_THR1_FX 2560 /*10.0 Q8*/ +#define HE_LT_THR2_FX 7680 /*30.0 Q8*/ + +/*-----------------------------------------------------------------* + * noise_est_AR1_Qx() + * + * y(n)(Qx) = alpha(Q15) * x(Qx) + (1.0f-alpha)* y(n-1) (Qx) + *-----------------------------------------------------------------*/ + +Word16 noise_est_AR1_Qx( /* o : Qx y(n) */ + Word16 x, /* i : Qx x(n) */ + Word16 y, /* i : Qx y(n-1) */ + Word16 alpha /*i : Q15 scaling of driving x(n) */ +) +{ + Word16 alpham1; + /*alpham1 = negate(add((Word16)-32768, alpha)); */ + alpham1 = sub(32767, alpha); /* one cycle less */ + + return mac_r(L_mult(y, alpham1), x, alpha); +} + +/*-----------------------------------------------------------------* + * noise_est_ln_q8_fx() + * + * q8 = (float)log( L_enr[i] + add1po*1.0 ); + *-----------------------------------------------------------------*/ + +static Word16 noise_est_ln_q8_fx( + Word32 L_enr, + Word16 flag_add1p0, /* flag to add 1.0 */ + Word16 q_new_plus_q_scale ) +{ + Word16 e_ener, f_ener; + Word32 L_tmp; + + L_tmp = L_add(L_enr, L_shl((Word32)1L, q_new_plus_q_scale)); /* +1.0f */ + if( flag_add1p0 == 0 ) + { + L_tmp = L_add(L_enr, 0); /* +0 , no offset */ + } + + L_tmp = L_max(L_tmp,(Word32)1L); /* make sure log2_norm_lc does not cause table reading out of bounds */ + + e_ener = norm_l(L_tmp); + f_ener = Log2_norm_lc(L_shl(L_tmp, e_ener)); + e_ener = sub(sub(30,e_ener),q_new_plus_q_scale); + L_tmp = Mpy_32_16(e_ener, f_ener, 22713); /* Q16 (22713 = Ln(2) in Q15)*/ + return round_fx(L_shl(L_tmp, 8)); /* Q8 */ +} + +/*-----------------------------------------------------------------* + * eps_quota_fx() + * + * + *-----------------------------------------------------------------*/ + +static Word32 eps_quota_fx( /* o: eps_num/eps_den in q_out */ + Word16 eps_num_h, /* num high ,*/ + Word16 eps_num_l, /* num low (signed) ,*/ + Word16 eps_den_h, /* den low */ + Word16 eps_den_l, /* den low (signed),*/ + Word16 q_out /* range 15...0 , tested with 11 and 12 */ +) +{ + Word32 L_tmp_num, L_tmp_den; + Word16 exp_num, exp_den; + Word16 m_num, m_den; + Word16 num_shift; + + + L_tmp_num = L_Comp(eps_num_h, eps_num_l); + L_tmp_den = L_Comp(eps_den_h, eps_den_l); + + exp_num = sub(norm_l(L_tmp_num), 1); /* make sure m_ num is lower than m_den */ + m_num = extract_h(L_shl(L_tmp_num, exp_num)); + exp_den = norm_l(L_tmp_den); + m_den = extract_h(L_shl(L_tmp_den, exp_den)); + + exp_num = sub(exp_num, exp_den); + if (m_den != 0) + { + assert(m_den >= m_num); + m_num = div_s(m_num, m_den); /* single basop */ + } + + num_shift = add(15-q_out, exp_num); + if (m_den == 0) + { + /* no division made due to zero denominator */ + m_num = 0; + move16(); + } + + return L_shr(m_num, num_shift); +} + +/*-----------------------------------------------------------------* + * noise_est_init_fx() + * + * Initialization of Noise estimator + *-----------------------------------------------------------------*/ + +void noise_est_init_fx( + Word16 *totalNoise, /* o : noise estimate over all critical bands */ + Word16 *first_noise_updt, /* o : noise update initialization flag */ + Word32 bckr[], /* o : per band background noise energy estimate */ + Word32 enrO[], /* o : per band old input energy */ + Word32 ave_enr[], /* o : per band long-term average energies */ + Word16 *pitO, /* o : open-loop pitch values from preceed. frame */ + Word16 *aEn, /* o : noise adaptation hangover counter */ + Word16 *st_harm_cor_cnt, /* i/o: 1st harm correlation timer */ + Word16 *bg_cnt, /* i/o: pause burst length counter */ + Word16 *lt_tn_track, /* Q15 */ + Word16 *lt_tn_dist, /* Q8 */ + Word16 *lt_Ellp_dist, /* Etot low lp same domain as *Etot_l_lp, Q8 */ + Word16 *lt_haco_ev, /* Q15 */ + Word16 *low_tn_track_cnt /* Q0 */ + ,Word16 *Etot_st_est, /* Q8 */ + Word16 *Etot_sq_st_est /* Q2 */ + +) +{ + Word16 i; + + FOR( i=0; i 0 ) && (LT_16(ini_frame_fx, HE_LT_CNT_INIT_FX) ) ) + || (GT_16(sub(*Etot_l_lp, *Etot_l), HE_LT_THR2_FX ) ) + ) + { + /**Etot_l_lp = 0.03f * *Etot_l + (1.0f - 0.03f) * *Etot_l_lp; */ + *Etot_l_lp = mac_r(L_mult(983, *Etot_l), 31785, *Etot_l_lp); + move16(); + + } + ELSE + { + /* *Etot_l_lp = 0.02f * *Etot_l + (1.0f - 0.02f) * *Etot_l_lp; */ + *Etot_l_lp = round_fx(L_mac(L_mult(655 , *Etot_l), 32113 , *Etot_l_lp )); + } + } + /**sign_dyn_lp = 0.1f * (*Etot_h - *Etot_l) + (1.0f - 0.1f) * *sign_dyn_lp;*/ + *sign_dyn_lp = round_fx(L_mac(L_mult(3277, sub(*Etot_h, *Etot_l)), 29491, *sign_dyn_lp)); + } + + return; +} + +/*==================================================================================*/ +/* FUNCTION : noise_est_down_fx() */ +/*----------------------------------------------------------------------------------*/ +/* PURPOSE : Down-ward noise udatation routine */ +/*----------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word32[]) fr_bands : per band input energy Q_new+QSCALE */ +/* _ (Word32[]) bckr : per band background noise energy estimate Q_new+QSCALE */ +/* _ (Word16 ) min_band : minimum critical band Q0 */ +/* _ (Word16 ) max_band : maximum critical band Q0 */ +/* _ (Word32[]) bckr_he : per band background noise energy estimate Q_new+QSCALE */ +/* _ (Word16 ) Etot : Energy of current frame Q8 */ +/* _ (Word16* ) Etot_last : Energy of last frame Q8 */ +/* _ (Word16* ) Etot_v_h2 : Energy variaions of noise frames Q8 */ +/* _ (Word16 ) Q_new : Qformat */ +/*----------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word32[]) bckr : per band background noise energy estimate Q_new+QSCALE */ +/* _ (Word32[]) tmpN : temporary noise update Q_new+QSCALE */ +/* _ (Word32[]) enr : averaged energy over both subframes Q_new+QSCALE */ +/* _ (Word16* ) totalNoise : noise estimate over all critical bands Q8 */ +/* _ (Word16 ) Etot : Energy of current frame Q8 */ +/* _ (Word16* ) Etot_last : Energy of last frame Q8 */ +/* _ (Word16* ) Etot_v_h2 : Energy variaions of noise frames Q8 */ +/* _ (Word32[]) tmpN_he1 : temporary noise update 1 Q_new+QSCALE */ +/*----------------------------------------------------------------------------------*/ + + +void noise_est_down_fx( + const Word32 fr_bands[], /* i : per band input energy (contains 2 vectors) */ + Word32 bckr[], /* i/o: per band background noise energy estimate */ + Word32 tmpN[], /* o : temporary noise update */ + Word32 enr[], /* o : averaged energy over both subframes */ + const Word16 min_band, /* i : minimum critical band */ + const Word16 max_band, /* i : maximum critical band */ + Word16 *totalNoise, /* o : noise estimate over all critical bands */ + Word16 Etot, /* i : Energy of current frame */ + Word16 *Etot_last, /* i/o: Energy of last frame Q8 */ + Word16 *Etot_v_h2, /* i/o: Energy variations of noise frames Q8 */ + Word16 Q_new, + const Word32 e_min /* i : minimum energy scaled Q_new + QSCALE */ +) + +{ + Word32 Ltmp, L_tmp; + const Word32 *pt1, *pt2; + Word16 i; + Word16 e_Noise, f_Noise; + Word16 scale; + Word32 totalNoise_temp; + Word32 L_Etot, L_Etot_last, L_Etot_v_h2, L_Etot_v; + + L_Etot = L_shl(Etot, 16); /*Q24 for later AR1 computations*/ + L_Etot_last = L_shl(*Etot_last, 16); + L_Etot_v_h2 = L_shl(*Etot_v_h2, 16); + scale = add(Q_new,QSCALE); + move16(); + + /*-----------------------------------------------------------------* + * Estimate total noise energy + *-----------------------------------------------------------------*/ + + totalNoise_temp = L_deposit_l(0); + FOR (i = min_band; i <= max_band; i++) + { + totalNoise_temp = L_add(totalNoise_temp, bckr[i]); /*Q_new+QSCALE*/ + } + totalNoise_temp = L_max(totalNoise_temp,L_shl(e_min,4)); + + + totalNoise_temp = L_max(totalNoise_temp,(Word32)1L); /* make sure log2_norm_lc does not cause table reading out of bounds */ + + /*totalNoise = 10.0f * (float)log10( *totalNoise );*/ + e_Noise = norm_l(totalNoise_temp); + f_Noise = Log2_norm_lc(L_shl(totalNoise_temp, e_Noise)); + e_Noise = sub(30, e_Noise); + e_Noise = sub(e_Noise, scale); + Ltmp = Mpy_32_16(e_Noise, f_Noise, LG10); + *totalNoise = round_fx(L_shl(Ltmp, 10)); /*Q8*/ + + /*-----------------------------------------------------------------* + * Average energy per frame for each frequency band + *-----------------------------------------------------------------*/ + + pt1 = fr_bands; /*Q_new+QSCALE*/ + pt2 = fr_bands + NB_BANDS; + + FOR( i=0 ; i < NB_BANDS; i++ ) + { + Ltmp = L_add(L_shr_r(*pt1,1),L_shr_r(*pt2,1)); + /*Ltmp = L_shr_r(L_add(*pt1,*pt2),1);*/ + enr[i] = Ltmp; + move32();/*Q_new+QSCALE*/ + pt1++; + pt2++; + } + + /*-----------------------------------------------------------------* + * Background noise energy update + *-----------------------------------------------------------------*/ + + FOR( i=0; i< NB_BANDS; i++ ) + { + /* tmpN[i] = (1-ALPHA) * bckr[i] + ALPHA * enr[i]; */ + L_tmp = Mult_32_16(enr[i], ALPHA_FX); /*ALPHA * enr2*/ + tmpN[i] = Madd_32_16(L_tmp, bckr[i], ALPHAM1_FX); + move32();/*Q_new+QSCALE*/ + tmpN[i] =L_max( tmpN[i] , e_min); /* handle div by zero in find_tilt_fx */ + + /* if( tmpN[i] < bckr[i] ) { bckr[i] = tmpN[i]; }*/ + /* Defend to increase noise estimate: keep as it is or decrease */ + bckr[i] = L_max(L_min(bckr[i], tmpN[i]), e_min); + move32();/*Q_new+QSCALE*/ + } + + /*------------------------------------------------------------------* + * Energy variation update + *------------------------------------------------------------------*/ + /*Etot_v = (float) fabs(*Etot_last - Etot);*/ + L_Etot_v = L_abs(L_sub(L_Etot_last, L_Etot)); /* Q24 */ + + /* *Etot_v_h2 = (1.0f-0.02f) * *Etot_v_h2 + 0.02f * min(3.0f, Etot_v); */ + L_Etot_v_h2 = Mult_32_16(L_Etot_v_h2, 32113); /*.98 in Q15 , Q24+Q15+1 -16 => Q24 */ + L_Etot_v = L_min((Word32)(3*(1<<24)), L_Etot_v); + L_tmp = Mult_32_16(L_Etot_v, 655); /*.02 in Q15 , Q24+Q15+1 -16 ==> Q24 ) */ + + *Etot_v_h2 = round_fx(L_add(L_Etot_v_h2, L_tmp)); /*Q24->Q8*/ + + /* if (*Etot_v_h2 < 0.1f) { *Etot_v_h2 = 0.1f; } */ + *Etot_v_h2 = s_max(*Etot_v_h2, 26 ); /* 0.1 in Q8*/ + + return; +} + +/*-----------------------------------------------------------------* +* noise_est_fx() +* +* Noise energy estimation (noise energy is updated in case of noise-only frame) +*-----------------------------------------------------------------*/ +void noise_est_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word32 tmpN[], /* i : temporary noise update Q_new + QSCALE */ + const Word16 *pit, /* i : open-loop pitch values for each half-frame Q0 */ + const Word16 cor[], /* i : normalized correlation for all half-frames Q15 */ + const Word16 epsP_h[], /* i : msb prediction error energies Q_r-1 */ + const Word16 epsP_l[], /* i : msb prediction error energies Q_r-1 */ + const Word16 Etot, /* i : total channel E (see find_enr_fx.c) Q8 */ + const Word16 relE, /* i : (VA_CHECK addition) relative frame energy Q8? */ + const Word16 corr_shift, /* i : normalized correlation correction Q15 */ + const Word32 enr[], /* i : averaged energy over both subframes Q_new + Q_SCALE */ + Word32 fr_bands[], /* i : spectrum per critical bands of the current frame Q_new + Q_SCALE */ + Word16 *cor_map_sum, /* o : Q8 */ + Word16 *sp_div, /* o : Q_sp_div */ + Word16 *Q_sp_div, /* o : Q factor for sp_div */ + Word16 *non_staX, /* o : non-stationarity for sp/mus classifier */ + Word16 *loc_harm , /* o : multi-harmonicity flag for UV classifier */ + const Word32 *lf_E, /* i : per bin energy for low frequencies Q_new + Q_SCALE -2 */ + Word16 *st_harm_cor_cnt, /* i/o : 1st harm correlation timer Q0 */ + const Word16 Etot_l_lp, /* i : Smoothed low energy Q8 */ + const Word16 Etot_v_h2, /* i : Energy variations Q8 */ + Word16 *bg_cnt, /* i : Background burst length timer Q0 */ + Word16 EspecdB[], /* i/o: log E spectrum (with f=0) of the current frame Q7 for multi harm */ + Word16 Q_new, /* i : SCaling of current frame */ + const Word32 Le_min_scaled, /*i : Minimum energy value in Q_new + Q_SCALE */ + Word16 *sp_floor /* o : noise floor estimate Q7 */ +) +{ + Word16 alpha, alpha2, alpha2m1, alpham1; + Word16 cor_min, cor_max, num, den, ExpNum, ExpDen, noise_chartmp; + Word16 wtmp1,wtmp, ExpLmax, ExpLmax2, tmpExp, nchar_thr, cor_tmp; + Word16 i, tmp_pc, pc,th_eps; + Word32 th_sta, Lnum, Lden, non_sta, LepsP, Ltmpden; + Word16 e_ener, f_ener; + Word32 Ltmp, Ltmp1,Lsum_num, Lsum_den, *pt1, *pt2,Ltmp2, Lnon_sta2; + Word16 spec_div, noise_char; + Word16 log_enr16; + Word16 updt_step ; /* Q15 */ + Word16 aE_bgd,sd1_bgd,bg_bgd2; + Word16 tn_ini; + Word16 epsP_0_2,epsP_0_2_ad,epsP_0_2_ad_lp_max; + Word16 epsP_2_16,epsP_2_16_dlp,epsP_2_16_dlp_max; + Word16 PAU, BG_1, NEW_POS_BG; + + Word16 haco_ev_max; + Word16 Etot_l_lp_thr; + Word16 comb_ahc_epsP, comb_hcm_epsP; + + Word16 enr_bgd,cns_bgd,lp_bgd,ns_mask; + Word16 lt_haco_mask, bg_haco_mask; + Word16 SD_1,SD_1_inv, bg_bgd3,PD_1,PD_2,PD_3,PD_4,PD_5; + + Word16 non_staB; /* Q8 */ + Word32 L_tmp_enr, L_tmp_ave_enr, L_tmp_ave_enr2; + Word16 tmp_Q; + Word16 tmp, tmp2; /* general temp registers */ + Word16 tmp_enr, tmp_floor ; /* constants in Q8 */ + Word16 vad_bwidth_fx; /* vad ns control variabel for input bwidth from teh BWD */ + /* for DTX operation */ + Word16 vad_2nd_stage_fx; + + Word16 lim_Etot_fx; /* Q8 */ + Word16 lim_Etot_sq_fx; /* Q2 */ + Word16 st_E_var_est_fx; /* Q2 */ + + /*-----------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + vad_bwidth_fx = st_fx->input_bwidth_fx; + move16(); + + /*st_fx->ener_RAT = 10.0f * (float)log10( mean(lf_E, 8));*/ + Ltmp = L_shr(lf_E[0],3); + FOR(i = 1; i < 8; i++) + { + Ltmp = L_add(Ltmp, L_shr(lf_E[i],3)); + } + Ltmp = L_max(Ltmp,(Word32)1L); /* make sure log2_norm_lc does not cause table reading out of bounds */ + e_ener = norm_l(Ltmp); + f_ener = Log2_norm_lc(L_shl(Ltmp, e_ener)); + e_ener = sub(30, e_ener); + e_ener = sub(e_ener, sub(add(Q_new,QSCALE),2)); + Ltmp = Mpy_32_16(e_ener, f_ener, LG10); + wtmp = round_fx(L_shl(Ltmp, 10));/*Q8*/ + + /* st_fx->ener_RAT /= (Etot + 0.01f); */ + wtmp1 = add(Etot,3);/*3 is 0.01 in Q8 */ + /* st_fx->ener_RAT_fx = wtmp/wtmp1 */ + st_fx->ener_RAT_fx = 0; + move16(); + IF( wtmp > 0 ) + { + st_fx->ener_RAT_fx = 32767; + move16(); /*Q15*/ + if(GE_16(wtmp1, wtmp )) + { + st_fx->ener_RAT_fx = div_s(wtmp, wtmp1); /*Q15*//* wtmp1 gte than wtmp */ + } + } + + /*-----------------------------------------------------------------* + * Set the threshold for eps & non_sta based on input sampling rate + * The reason is that in case of 8kHz sampling input, there is nothing + * between 4kHz-6.4kHz. In noisy conditions, this makes a fast + * transition even in noise-only parts, hence producing a "higher + * order" spectral envelope => the epsP ratio is much less effective. + *-----------------------------------------------------------------*/ + + IF (NE_16(vad_bwidth_fx,NB)) /* WB input */ + { + th_eps = TH_EPS16_FX; + move16();/*Q11*/ + th_sta = TH_STA16_FX; + move16();/*Q10 */ + cor_min = COR_MIN16_FX; + move16();/*Q15*/ + cor_max = COR_MAX16_FX; + move16();/*Q15*/ + } + ELSE /* NB input */ + { + th_eps = TH_EPS8_FX; + move16();/* Q11 */ + th_sta = TH_STA8_FX; + move16(); /* Q10 */ + cor_min = COR_MIN8_FX; + move16(); + cor_max = COR_MAX8_FX; + move16(); + } + + + /*-----------------------------------------------------------------* + * Estimation of pitch stationarity + *-----------------------------------------------------------------*/ + + /* pc = abs(pit[0] - pitO) + abs(pit[1] - pit[0]) */ /* needed in signal_clas() */ + wtmp = abs_s(sub(pit[0], st_fx->pitO_fx)); + wtmp1 = abs_s(sub(pit[1], pit[0])); + pc = add(wtmp, wtmp1); + + + Ltmp = L_deposit_h(corr_shift); + Ltmp = L_mac(Ltmp, cor[0], 10923); + Ltmp = L_mac(Ltmp, cor[1], 10923); + wtmp = mac_r(Ltmp, cor[2], 10923); + + tmp_pc = pc; + move16(); + if (LT_16(wtmp, cor_min)) + { + tmp_pc = TH_PC_FX; + move16(); /* low correlation -> probably inactive signal */ + } + + st_fx->pitO_fx = pit[1]; + move16(); /* Update */ + + /*-----------------------------------------------------------------* + * Multi-harmonic analysis + *-----------------------------------------------------------------*/ + + *loc_harm = multi_harm_fx( EspecdB, st_fx->old_S_fx, st_fx->cor_map_fx, &st_fx->multi_harm_limit_fx, st_fx->total_brate_fx, + st_fx->bwidth_fx, &st_fx->cor_strong_limit_fx, &st_fx->mean_avr_dyn_fx, &st_fx->last_sw_dyn_fx, cor_map_sum, sp_floor ); + + /*-----------------------------------------------------------------* + * Detection of frames with non-stationary spectral content + *-----------------------------------------------------------------*/ + + /* weighted sum of spectral changes per critical bands */ + Lsum_num = L_deposit_l(0); + Lsum_den = L_deposit_l(0); + + /* Find a proper scaling to prevent overflow, but acheiving good computation on low level signals */ + tmpExp = 0; + move16(); + ExpLmax = sub(30, norm_l(fr_bands[10])); + ExpLmax2 = sub(30, norm_l(st_fx->fr_bands2_fx[10])); + tmpExp = s_max(tmpExp, sub(shl(s_max(ExpLmax,ExpLmax2), 1), s_min(ExpLmax, ExpLmax2))); + FOR (i = 11; i<= st_fx->max_band_fx; i++) + { + ExpLmax = sub(30, norm_l(fr_bands[i])); + ExpLmax2 = sub(30, norm_l(st_fx->fr_bands2_fx[i])); + tmpExp = s_max(tmpExp, sub(shl(s_max(ExpLmax,ExpLmax2), 1), s_min(ExpLmax, ExpLmax2))); + } + tmpExp = sub(tmpExp, 30-4-4); /* 4bits for internal summation and 4 bits for comparaison */ + + pt1 = fr_bands + 10; + pt2 = st_fx->fr_bands2_fx + 10; + FOR (i=10; i<=st_fx->max_band_fx; i++) + { + Lnum = L_max(*pt1, *pt2); /* Don't need if anymore */ + Lsum_den = L_add(Lsum_den, Lnum); + Ltmpden = L_min(*pt1, *pt2); + if( Ltmpden == 0 ) + { + Ltmpden = L_add(Ltmpden,1); + } + ExpNum = sub(norm_l(Lnum), 1); + num = extract_h(L_shl(Lnum, ExpNum)); + num = mult_r(num, num); + ExpDen = norm_l(Ltmpden); + den = extract_h(L_shl(Ltmpden, ExpDen)); + num = div_s(num, den); + Ltmp = L_shr(num, add(sub(sub(shl(ExpNum, 1), ExpDen), 15+1), tmpExp)); + Lsum_num = L_add(Lsum_num, Ltmp); + + pt1++; + pt2++; + } + Lsum_den = L_shr(Lsum_den, tmpExp); + + + /* calculation of spectral diversity */ + /* THR_SPDIV_FX = 5 , 1/5 Q15 = 6554 */ + spec_div = 0; + move16(); + if (GT_32(Mult_32_16(Lsum_num, 6554), Lsum_den)) /* Qx+Q15+1-16 ==> Qx */ + { + spec_div = 1; + move16(); + } + + /* *sp_div = Lsum_num / (Lsum_den + 1e-5f); */ + ExpNum = sub(norm_l(Lsum_num), 1); + num = extract_h(L_shl(Lsum_num, ExpNum)); + + Lsum_den = L_add(Lsum_den,1); + + ExpDen = norm_l(Lsum_den); + den = extract_h(L_shl(Lsum_den, ExpDen)); + + *sp_div = div_s(num, den); + move16(); + + *Q_sp_div = add(15,sub(ExpNum ,ExpDen)); + move16(); + + /*-----------------------------------------------------------------* + * Detection of frames with high energy content in high frequencies + *-----------------------------------------------------------------*/ + + /* calculation of energy in first 10 critical bands */ + Ltmp = sum32_fx( &fr_bands[st_fx->min_band_fx], sub(10, st_fx->min_band_fx) ); + + /* calculation of energy in the rest of bands */ + Ltmp2 = sum32_fx( &fr_bands[10], sub(st_fx->max_band_fx,9) ); + + wtmp = shl(1, sub(add(Q_new, QSCALE), 1)); + + test(); + IF (L_msu(Ltmp, 100, wtmp) < 0 || L_msu(Ltmp2, 100, wtmp) < 0) + { + noise_chartmp = 0; + move16(); + } + ELSE + { + /* ftemp2 /= ftemp */ + ExpNum = sub(norm_l(Ltmp2), 1); + num = extract_h(L_shl(Ltmp2, ExpNum)); + + ExpDen = norm_l(Ltmp); + den = extract_h(L_shl(Ltmp, ExpDen)); + num = div_s(num, den); + noise_chartmp = extract_h(L_shr(num, add(sub(ExpNum, ExpDen), 4-16))); /* Q11 */ + } + + noise_chartmp = s_min(noise_chartmp, (Word16)10<<11); /* Q11 */ + + /* update LT value of the final parameter */ + /* *st_noise_char = M_ALPHA * *st_noise_char + (1-M_ALPHA) * noise_chartmp */ + st_fx->noise_char_fx = mac_r(L_mult(M_ALPHA_FX, st_fx->noise_char_fx), ONE_MINUS_M_ALPHA, noise_chartmp); + + + nchar_thr = THR_NCHAR_WB_FX; + move16(); /* 1.0 Q11 */ + if( EQ_16(vad_bwidth_fx,NB)) + { + nchar_thr = THR_NCHAR_NB_FX; + move16(); /* 1.0 Q11 */ + } + + noise_char = 0; + move16(); + if (GT_16(st_fx->noise_char_fx, nchar_thr)) + { + noise_char = 1; + move16(); + } + + /* save the 2 last spectra per crit. bands for the future */ + Copy32(st_fx->fr_bands1_fx, st_fx->fr_bands2_fx, NB_BANDS); + Copy32(fr_bands+NB_BANDS, st_fx->fr_bands1_fx, NB_BANDS); + + /*-----------------------------------------------------------------* + * Non-stationarity estimation for each band + * Handicap high E frames in average computing + *-----------------------------------------------------------------*/ + + /* set averaging factor */ + /* ftemp = relE; */ + /* if( ftemp < 0.0f ) { ftemp = 0.0f; } */ + tmp = s_max(relE,0); /* Q8 */ + + /* alpha = 0.064f * ftemp + 0.75f; */ + Ltmp = Mult_32_16((Word32)137438953L, tmp); /* Q31(.064)+Q8+1-16 --> Q24 */ + Ltmp = L_mac(Ltmp,256,24576) ; /* Q8+Q15(.75)+1 --> Q24 */ + alpha = round_fx(L_shl(Ltmp,7)); /*Q24 +7 --> Q31 Q15*/ + + /*if( alpha > 0.999f { alpha = 0.999f;} */ + alpha = s_min(alpha, 32735 ); /*.999 in Q15*/ + alpham1 = negate(add(-32768, alpha)); /* 1.0 - alpha */ + /*--------------------------------------------------------------* + * during significant attacks, replace the LT energy by the + * current energy this will cause non_sta2 failures to occur in + * different frames than non_sta failures + *--------------------------------------------------------------*/ + + alpha2 = alpha; + move16(); + alpha2m1 = alpham1; + move16(); + IF (spec_div > 0) + { + alpha2 = 0; + move16(); + alpha2m1 = 32767; + move16(); + } + Lnon_sta2 = L_deposit_l(1<<10); + + non_sta = L_deposit_l(1<<10); + *non_staX = 0; + move16(); + non_staB = 0; + move16(); + + FOR( i = st_fx->min_band_fx; i <= st_fx->max_band_fx; i++ ) + { + /* + 1.0f added to reduce sensitivity to non stationarity in low energies */ + /* tmp_enr = enr[i] + 1.0f; */ + tmp_Q = add(Q_new, Q_SCALE); + Ltmp = L_shl((Word32)1L, tmp_Q); /* 1.0 added in the right dynamic domain */ + L_tmp_enr = L_add(enr[i] , Ltmp ); /* enr scale dynamic */ + L_tmp_ave_enr = L_add(st_fx->ave_enr_fx[i], Ltmp); /* ave__enr scale dynamic */ + + IF (LE_32(non_sta, th_sta)) /* Just to limit the saturation */ + { + /* if( enr[i] > st_ave_enr2[i] ) */ + /* non_sta2 = non_sta2 * ((enr[i]+1) / (st_ave_enr2[i]+1)) */ + Lnum = L_max(L_tmp_enr, L_tmp_ave_enr); + + /* else */ + /* non_sta2 = non_sta2 * ((st_ave_enr2[i]+1) / (enr[i]+1)) */ + Lden = L_min(L_tmp_enr, L_tmp_ave_enr); + + ExpNum = sub(norm_l(Lnum), 1); + num = extract_h(L_shl(Lnum, ExpNum)); + Lnum = L_shl(Lnum, ExpNum); + ExpDen = norm_l(Lden); + den = extract_h(L_shl(Lden, ExpDen)); + num = div_s(num, den); + Ltmp = Mult_32_16(non_sta, num); + non_sta = L_shr(Ltmp, sub(ExpNum, ExpDen)); /* Q10 */ + } + + /* st->ave_enr[i] = alpha * st->ave_enr[i] + (1-alpha) * enr[i];*/ /* update long-term average */ + Ltmp = Mult_32_16(st_fx->ave_enr_fx[i], alpha); + Ltmp = L_add(Ltmp, Mult_32_16(enr[i], alpham1)); + st_fx->ave_enr_fx[i] = L_max(Le_min_scaled, Ltmp); + move32(); + + /* calculation of another non-stationarity measure (following attacks) */ + /*if( non_sta2 <= th_sta ){ + tmp_ave2 = st->ave_enr2[i] + 1.0f; + if( tmp_enr > tmp_ave2 ){ + non_sta2 = non_sta2 * ( tmp_enr / tmp_ave2 ); + } else { + non_sta2 = non_sta2 * (tmp_ave2 / tmp_enr ); + } + } */ + + /* ave_enr2:: calculation of another non-stationarity measure (following attacks) */ + Ltmp = L_shl((Word32)1L, tmp_Q ); /* 1.0 added in the right dynamic domain */ + /*L_tmp_enr = L_add(enr[i] , Ltmp );*/ /* enr scale dynamic , done above */ + L_tmp_ave_enr2 = L_add(st_fx->ave_enr2_fx[i], Ltmp); /* ave__enr scale dynamic */ + + IF (LE_32(Lnon_sta2, th_sta )) /* Just to limit the saturation */ + { + Lnum = L_max(L_tmp_enr, L_tmp_ave_enr2 ); + Lden = L_min(L_tmp_enr, L_tmp_ave_enr2 ); + + ExpNum = sub(norm_l(Lnum), 1); + num = extract_h(L_shl(Lnum, ExpNum)); + Lnum = L_shl(Lnum, ExpNum); + ExpDen = norm_l(Lden); + den = extract_h(L_shl(Lden, ExpDen)); + num = div_s(num, den); + Ltmp1 = Mult_32_16(Lnon_sta2, num); + Lnon_sta2 = L_shr(Ltmp1, sub(ExpNum, ExpDen)); /* Q10 */ + } + + /* st_ave_enr2[i] = (float)alpha2 * st_ave_enr2[i] + + (1.0f - alpha2) * (enr[i]) */ + Ltmp1 = Mult_32_16(st_fx->ave_enr2_fx[i], alpha2); + Ltmp1 = L_add(Ltmp1, Mult_32_16(enr[i], alpha2m1)); + st_fx->ave_enr2_fx[i] = L_max(Le_min_scaled, Ltmp1); + move32(); + + /* calculation of non-stationarity measure for speech/music classification */ + test(); + IF ( GE_16(i,START_BAND_SPMUS)&<_16(i,NB_BANDS_SPMUS+START_BAND_SPMUS)) + { + /* log_enr = (float)ln_fx(enr[i]); */ + log_enr16 = noise_est_ln_q8_fx( enr[i], 0 ,tmp_Q); + wtmp = abs_s(sub(log_enr16, st_fx->past_log_enr_fx[i-START_BAND_SPMUS])); + *non_staX = add(*non_staX, wtmp); + move16(); /* Q8 */ + st_fx->past_log_enr_fx[i-START_BAND_SPMUS] = log_enr16; + move16(); + + /* calculate non-stationarity feature relative background */ + tmp_enr = noise_est_ln_q8_fx( enr[i], 1 , tmp_Q); /* 1.0f added */ + tmp_floor = LN_E_MIN_PLUS_ONE_FX ; + move16(); /* non dynamic init constant in Q8 */ + IF ( GE_16(st_fx->ini_frame_fx, 100 )) + { + tmp_floor = noise_est_ln_q8_fx( st_fx->bckr_fx[i], 1, tmp_Q ); + } + non_staB = add(non_staB, abs_s(sub(tmp_enr, tmp_floor))); /* Q8 */ + } + + } /* end of band loop FOR( i = st_fx->min_band_fx; i <= st_fx->max_band_fx; i++ ) */ + + IF (LT_16(Etot,-1280)) + { + non_sta = L_deposit_l(1024); /* 1.0 in Q10 */ + Lnon_sta2 = L_deposit_l(1024); /* 1.0 in Q10 */ + } + + lim_Etot_fx = s_max(5120,Etot); /* 20.0f Q8 */ + lim_Etot_sq_fx = extract_h(L_shl_r(L_mult(lim_Etot_fx,lim_Etot_fx),1)); /* Q2 */ + + if ( st_fx->ini_frame_fx < 150 ) + { + /* Allow use of quicker filter during init - if needed */ + /* st->Etot_st_est = 0.25f * lim_Etot + (1.0f-0.25F) * st->Etot_st_est; */ + st_fx->Etot_st_est_fx = mac_r(L_mult(8192, lim_Etot_fx), 24576, st_fx->Etot_st_est_fx); + move16(); + /* st->Etot_sq_st_est = 0.25f * lim_Etot * lim_Etot + (1.0f-0.25f) * st->Etot_sq_st_est; */ + st_fx->Etot_sq_st_est_fx = mac_r(L_mult(8192, lim_Etot_sq_fx), 24576, st_fx->Etot_sq_st_est_fx); + move16(); + } + else + { + /* st->Etot_st_est = 0.25f * lim_Etot + (1.0f-0.25F) * st->Etot_st_est; */ + st_fx->Etot_st_est_fx = mac_r(L_mult(8192, lim_Etot_fx), 24576, st_fx->Etot_st_est_fx); + move16(); + /* st->Etot_sq_st_est = 0.25f * lim_Etot * lim_Etot + (1.0f-0.25f) * st->Etot_sq_st_est; */ + st_fx->Etot_sq_st_est_fx = mac_r(L_mult(8192, lim_Etot_sq_fx), 24576, st_fx->Etot_sq_st_est_fx); + move16(); + } + + st_E_var_est_fx = sub(st_fx->Etot_sq_st_est_fx,extract_h(L_shl_r(L_mult(st_fx->Etot_st_est_fx,st_fx->Etot_st_est_fx),1))); + + + + /*-----------------------------------------------------------------* + * Count frames since last correlation or harmonic event + *-----------------------------------------------------------------*/ + + Ltmp = L_mult(cor[0], 16384); + Ltmp = L_mac(Ltmp, cor[1], 16384); + + test(); + test(); + *st_harm_cor_cnt = add(*st_harm_cor_cnt , 1); + if( (Etot > 0) && ( (*loc_harm > 0 ) || (GT_16(round_fx(Ltmp), COR_MAX_NNE_FX )))) + { + *st_harm_cor_cnt = 0; + move16(); + } + + IF( (GT_16(*st_harm_cor_cnt,1))&&((LT_16(Etot,3840))||/* 15 in Q8 */ + ( GT_16(st_fx->ini_frame_fx,10) && + GT_16(sub(Etot,st_fx->Etot_lp_fx),1792) )) /* 7 in Q8 */ + ) + { + *st_harm_cor_cnt = 1; + } + + if ( GT_16(*st_harm_cor_cnt,1)&& + GT_16(Etot,7680) && /* 30.0f in Q8 */ + GT_16(st_E_var_est_fx,32 ) /* 8.0f in Q2 */ + ) + { + + /* st->harm_cor_cnt = max(1, (short) round_f( (float) st->harm_cor_cnt / 4.0f )) ; */ + *st_harm_cor_cnt = s_max(1, shr(add(*st_harm_cor_cnt,2),1)); + } + + + /*-----------------------------------------------------------------* + * Energy based pause length counter + *-----------------------------------------------------------------*/ + test(); + IF( (*bg_cnt >= 0) && (GT_16(sub(Etot , Etot_l_lp),1280)/*5.0 in Q8*/)) + { + /* Possible speech burst */ + *bg_cnt = -1; + move16(); + } + ELSE + { + test(); + if( EQ_16(*bg_cnt,-1)&&(LT_16(sub(Etot,Etot_l_lp),1280))/*5 in Q8*/) + { + /* Possible start of speech pause */ + *bg_cnt = 0; + move16(); + } + } + if (*bg_cnt >= 0) + { + *bg_cnt = add(*bg_cnt,1); + move16(); + } + + /*-----------------------------------------------------------------* + * Linear predition efficiency 0 to 2 order + *-----------------------------------------------------------------*/ + + /*epsP_0_2 = max(0 , min(8, epsP[0] / epsP[2])); */ + Ltmp = eps_quota_fx(epsP_h[0], epsP_l[0], + epsP_h[2], epsP_l[2] , 12 ); /* Word32 Q12 */ + BASOP_SATURATE_WARNING_OFF /* may saturate*/ + epsP_0_2 = round_fx(L_shl(Ltmp,16)); /* Q12+16 -16 -> Q12 , NB saturation in Q12 sets max value to 7,999 */ + BASOP_SATURATE_WARNING_ON + + epsP_0_2 = s_max(0, epsP_0_2); /* min value is 0 , Q12 */ + + + /* st->epsP_0_2_lp = 0.15f * epsP_0_2 + (1.0f-0.15f) * st->epsP_0_2_lp; */ + alpha = 4915; + move16(); /*0.15 in Q15 */ + st_fx->epsP_0_2_lp_fx = noise_est_AR1_Qx(epsP_0_2, st_fx->epsP_0_2_lp_fx ,alpha); + + /* epsP_0_2_ad = (float) fabs(epsP_0_2 - st->epsP_0_2_lp ); */ + epsP_0_2_ad = abs_s(sub(epsP_0_2, st_fx->epsP_0_2_lp_fx)); /* Q12 */ + + /*if (epsP_0_2_ad < st->epsP_0_2_ad_lp) { + st->epsP_0_2_ad_lp = 0.1f * epsP_0_2_ad + (1.0f - 0.1f) * st->epsP_0_2_ad_lp; + } else { + st->epsP_0_2_ad_lp = 0.2f * epsP_0_2_ad + (1.0f - 0.2f) * st->epsP_0_2_ad_lp; + } */ + alpha = 6554; + move16();/* 0.2 Q15 */ + if (LT_16(epsP_0_2_ad, st_fx->epsP_0_2_ad_lp_fx)) + { + alpha = shr(alpha,1); /* 0.1 Q15 */ + } + st_fx->epsP_0_2_ad_lp_fx = noise_est_AR1_Qx(epsP_0_2_ad, st_fx->epsP_0_2_ad_lp_fx ,alpha); + + /* epsP_0_2_ad_lp_max = max(epsP_0_2_ad,st->epsP_0_2_ad_lp);*/ + epsP_0_2_ad_lp_max = s_max(epsP_0_2_ad, st_fx->epsP_0_2_ad_lp_fx); /* Q12 */ + + + /*-----------------------------------------------------------------* + * Linear predition efficiency 2 to 16 order + *-----------------------------------------------------------------*/ + + /* epsP_2_16 = max(0 , min(8, epsP[2] / epsP[16])); */ + Ltmp = eps_quota_fx(epsP_h[2], epsP_l[2], + epsP_h[16], epsP_l[16] , 12 ); /* Word32 Q12 */ + BASOP_SATURATE_WARNING_OFF /* may saturate*/ + epsP_2_16 = round_fx(L_shl(Ltmp,16)); /* Q12+16 -16 -> Q12 , + NB saturation in Q12 sets max value to 7,999 */ + BASOP_SATURATE_WARNING_ON + + epsP_2_16 = s_max(0, epsP_2_16); /* min value is 0 , Q12 */ + + + /* if (epsP_2_16 > st->epsP_2_16_lp){ + st->epsP_2_16_lp = 0.2f * epsP_2_16 + (1.0f-0.2f) * st->epsP_2_16_lp; + } else { + st->epsP_2_16_lp = 0.03f * epsP_2_16 + (1.0f-0.03f) * st->epsP_2_16_lp; + } + + st->epsP_2_16_lp2 = 0.02f * epsP_2_16 + (1.0f-0.02f) * st->epsP_2_16_lp2; */ + + alpha = 983 ; + move16();/* 0.03 Q15 */ + if (GT_16(epsP_2_16 , st_fx->epsP_2_16_lp_fx)) + { + alpha = 6554; + move16();/* 0.2 Q15 */ + } + st_fx->epsP_2_16_lp_fx = noise_est_AR1_Qx(epsP_2_16, st_fx->epsP_2_16_lp_fx , alpha); + + st_fx->epsP_2_16_lp2_fx = noise_est_AR1_Qx(epsP_2_16, st_fx->epsP_2_16_lp2_fx , 655); /* 0.02 */ + + epsP_2_16_dlp = sub(st_fx->epsP_2_16_lp_fx, st_fx->epsP_2_16_lp2_fx); + + + /* if (epsP_2_16_dlp < st->epsP_2_16_dlp_lp2 ) { + st->epsP_2_16_dlp_lp2 = 0.02f * epsP_2_16_dlp + (1.0f-0.02f) * st->epsP_2_16_dlp_lp2; + } else { + st->epsP_2_16_dlp_lp2 = 0.05f * epsP_2_16_dlp + (1.0f-0.05f) * st->epsP_2_16_dlp_lp2; + }*/ + alpha = 1638; + move16();/* 0.05 Q15 */ + if (LT_16(epsP_2_16_dlp , st_fx->epsP_2_16_dlp_lp2_fx)) + { + alpha = 655; + move16();/* 0.02 Q15 */ + } + st_fx->epsP_2_16_dlp_lp2_fx = noise_est_AR1_Qx(epsP_2_16_dlp, st_fx->epsP_2_16_dlp_lp2_fx , alpha); + + /* epsP_2_16_dlp_max = max(epsP_2_16_dlp,st->epsP_2_16_dlp_lp2); */ + epsP_2_16_dlp_max = s_max(epsP_2_16_dlp, st_fx->epsP_2_16_dlp_lp2_fx); + + /*-----------------------------------------------------------------* + * long term extensions of frame features + *-----------------------------------------------------------------*/ + + tmp = sub(Etot, st_fx->totalNoise_fx ); /* Q8 */ + /* st->lt_tn_track = 0.03f* (Etot - st->totalNoise < 10) + 0.97f*st->lt_tn_track; */ + tmp2 = 0; + move16(); + if( LT_16(tmp, 2560 )) /*10 in Q8 */ + { + tmp2=32767; + move16(); + } + st_fx->lt_tn_track_fx = noise_est_AR1_Qx(tmp2, st_fx->lt_tn_track_fx , 983); /*0.03 in Q15 ,Q15 state*/ + + /* st->lt_tn_dist = 0.03f* (Etot - st->totalNoise) + 0.97f*st->lt_tn_dist; */ + st_fx->lt_tn_dist_fx = noise_est_AR1_Qx(tmp, st_fx->lt_tn_dist_fx , 983); /*0.03 in Q15 ,Q8 state*/ + + /* st->lt_Ellp_dist = 0.03f* (Etot - st->Etot_l_lp) + 0.97f*st->lt_Ellp_dist;*/ + tmp = sub(Etot,st_fx->Etot_l_lp_fx); /* Q8 */ + st_fx->lt_Ellp_dist_fx = noise_est_AR1_Qx(tmp, st_fx->lt_Ellp_dist_fx, 983); /*0.03 in Q15 ,Q8 state*/ + + + + /* if (st->harm_cor_cnt == 0) { + st->lt_haco_ev = 0.03f*1.0 + 0.97f*st->lt_haco_ev; + } else { + st->lt_haco_ev = 0.99f*st->lt_haco_ev; + } */ + IF ( *st_harm_cor_cnt == 0) + { + st_fx->lt_haco_ev_fx = noise_est_AR1_Qx((Word16)32767, st_fx->lt_haco_ev_fx, 983); /*.03 in Q15 , Q15 state */ + } + ELSE + { + st_fx->lt_haco_ev_fx = mult_r(32440, st_fx->lt_haco_ev_fx); /*.99 in Q15 , Q15 state */ + } + + + /* if (st->lt_tn_track < 0.05f) { + st->low_tn_track_cnt++; + } else { + st->low_tn_track_cnt=0; + }*/ + tmp = 0; + move16(); + move16(); + if( LT_16( st_fx->lt_tn_track_fx , 1638 )) /* 0.05 in Q15*/ + { + tmp = add(st_fx->low_tn_track_cnt_fx, 1); + } + st_fx->low_tn_track_cnt_fx = tmp; + move16(); + + + /* update of the long-term non-stationarity measure (between 0 and 1) */ + /* if ( (non_sta > th_sta) || (*loc_harm > 0) ) { + st->act_pred = M_GAMMA * st->act_pred + (1-M_GAMMA) * 1; + } else { + st->act_pred = M_GAMMA * st->act_pred + (1-M_GAMMA) * 0; + }*/ + Ltmp = L_mult(M_GAMMA_FX, st_fx->act_pred_fx); /*Q15*Q15+1 --> Q31 , 32440= .99 Q15 */ + tmp = round_fx(Ltmp); /* Q15 */ + test(); + if ( ( GT_32(non_sta, th_sta)) /* float th_sta NB 5e10 , WB 3.5e10*/ + || (*loc_harm > 0) + ) + { + tmp = mac_r(Ltmp, (-32768+M_GAMMA_FX), -32768); /* (-0.01)*(-1.0) */ + } + st_fx->act_pred_fx = tmp ; + move16(); + + + + /*-----------------------------------------------------------------* + * Background noise adaptation enable flag + *-----------------------------------------------------------------*/ + Ltmp = L_mult(cor[0], 16384); + Ltmp = L_mac(Ltmp, cor[1], 16384); + cor_tmp = mac_r(Ltmp, corr_shift,MAX_16); + + LepsP = eps_quota_fx(epsP_h[2] , epsP_l[2], + epsP_h[16], epsP_l[16] , 11 ); /* L_epsP in Q11 */ + /* note this epsP2/eps16 is not limited to 8 as, epsP_2_16 is !! */ + + vad_2nd_stage_fx = 0; + move16(); /* background noise present - decrement counter */ + /* + if( ( (*st_harm_cor_cnt < 3*HC_CNT_SLOW ) + && ( ( non_sta > th_sta ) || + ( tmp_pc < TH_PC ) || + ( noise_char > 0) ) + ) + || + ( (st->ini_frame > 150) && (Etot - Etot_l_lp) > 10 ) || + ( 0.5f * (voicing[0]+voicing[1]) > cor_max ) || + ( epsP[2] / epsP[16] > th_eps ) || + ( *loc_harm > 0) || + ((st->act_pred > 0.8f) && (non_sta2 > th_sta)) + ) */ + + Ltmp = L_mult(cor[0], 16384); /* Q15 + Q15(.5)) + 1 -> Q31 */ + cor_tmp = mac_r(Ltmp, cor[1], 16384 ); /* Q31 -16 -> Q15 */ + if ( Etot < 0 ) + { + cor_tmp = 0; + move16(); + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + + if( ( ( LT_16(*st_harm_cor_cnt, (3*HC_CNT_SLOW_FX) )) + && ( ( GT_32(non_sta, th_sta) ) || (LT_16(tmp_pc, TH_PC_FX) ) || ( GT_16(noise_char ,0)) ) ) + || + ( (GT_16(st_fx->ini_frame_fx, HE_LT_CNT_INIT_FX ) ) && ( GT_16(sub(Etot, Etot_l_lp), 2560) ) ) || + ( GT_16(cor_tmp, cor_max) ) || /* Q15 */ + ( GT_32(LepsP, th_eps) ) || /* Q11 */ + ( GT_16(*loc_harm,0)) || + ((GT_16(st_fx->act_pred_fx, 26214) ) && (GT_32(Lnon_sta2, th_sta) ) ) /*act_pred in Q15 , th_sta in Q10 */ + ) + { + vad_2nd_stage_fx = 1; + move16(); /* active signal present - increment counter */ + } + + tmp = 2; + move16(); /* Signal present */ + if(vad_2nd_stage_fx == 0 ) + { + tmp = -1; + move16(); /* Background present */ + } + st_fx->aEn_fx = add(st_fx->aEn_fx, tmp); + + + st_fx->aEn_fx = s_min(st_fx->aEn_fx,6); + st_fx->aEn_fx = s_max(st_fx->aEn_fx,0); + + + + + /* Additional NNE detectors */ + + /* comb_ahc_epsP = max(max(st->act_pred, st->lt_haco_ev), epsP_2_16_dlp); */ + /* Q15 Q15 Q12 */ + comb_ahc_epsP = s_max(s_max(shr(st_fx->act_pred_fx,15-12), shr(st_fx->lt_haco_ev_fx, 15-12)), epsP_2_16_dlp); /* Q12 */ + + + /* comb_hcm_epsP = max(max(st->lt_haco_ev,epsP_2_16_dlp_max),epsP_0_2_ad_lp_max); */ + /* Q15 Q12 Q12 */ + comb_hcm_epsP = s_max(s_max(shr(st_fx->lt_haco_ev_fx,15-12), epsP_2_16_dlp_max), epsP_0_2_ad_lp_max); /* Q12 */ + + /*haco_ev_max = max(*st_harm_cor_cnt==0,st->lt_haco_ev); */ + tmp = 0; + move16(); + if ( *st_harm_cor_cnt == 0 ) + { + tmp = (Word16)32767; + move16(); + } + haco_ev_max = s_max(tmp, st_fx->lt_haco_ev_fx); /* Q15 */ + + /* Etot_l_lp_thr = st->Etot_l_lp + (1.5f + 1.5f * (st->Etot_lp<50.0f))*st->Etot_v_h2; */ + tmp = 12288; + move16();/* 1.5 Q13 */ + if( LT_16(st_fx->Etot_lp_fx, 12800 )) /* 50.0 in Q8 */ + { + tmp =shl(tmp,1); /*1.5 + 1.5 Q13 */ + } + Ltmp = L_deposit_h(st_fx->Etot_l_lp_fx); + Etot_l_lp_thr = round_fx(L_add(Ltmp, L_shl(L_mult(tmp, Etot_v_h2),2))); /* Q13+Q8+1 +2 = Q24 -> Q8*/ + + /* enr_bgd = Etot < Etot_l_lp_thr; */ + enr_bgd = 0; + move16(); + if(LT_16(Etot, Etot_l_lp_thr )) /* Q8 */ + { + enr_bgd = 1; + move16();/* Q0 */ + } + + /* cns_bgd = (epsP_0_2 > 7.95f) && (non_sta< 1e3f); */ + cns_bgd = 0 ; + move16(); + test(); + if( (GT_16(epsP_0_2, 32563)) /* 7.95 in Q12 */ + && (LT_32(non_sta, 1024000L) ) ) /* 1e3f in Q10 ? */ + { + cns_bgd = 1; + move16(); /* Q0 */ + } + + /*lp_bgd = epsP_2_16_dlp_max < 0.10f; */ + lp_bgd = 0; + move16(); + if( LT_16(epsP_2_16_dlp_max, 410)) /*0.10 Q12 */ + { + lp_bgd = 1; + move16(); /* Q0 */ + } + + + /* ns_mask = non_sta < 1e5f; */ + ns_mask = 0; + move16(); + if( LT_32(non_sta, (Word32)102400000L )) /* (1e5f in Q10)*/ + { + ns_mask = 1; + move16(); /* Q0 */ + } + + + /* lt_haco_mask = st->lt_haco_ev < 0.5f; */ + lt_haco_mask = 0; + move16(); + if( LT_16(st_fx->lt_haco_ev_fx, 16384 )) /* ( .5 in Q15)*/ + { + lt_haco_mask = 1; + move16(); /* Q0 */ + } + + /* bg_haco_mask = haco_ev_max < 0.4f; */ + bg_haco_mask = 0; + move16(); + if( LT_16(haco_ev_max, 13107)) /* ( 0.4 in Q15)*/ + { + bg_haco_mask = 1; + move16(); /* Q0 */ + } + + + /* SD_1 = ( (epsP_0_2_ad > 0.5f) && (epsP_0_2 > 7.95f) ); */ + SD_1 = 0; + move16(); + test(); + if( (GT_16(epsP_0_2_ad,2048)) /* 0.5 in Q12 */ + && (GT_16(epsP_0_2, 32563) )) /* 7.95 in Q12 */ + { + SD_1 = 1; + move16(); /* Q0 */ + } + SD_1_inv = sub(1, SD_1); /* Q0 */ + + /* NB "STL::test()"; has a cost of 2, using bitwise "s_and" , "s_or" at a cost of 1 */ + /* NB only lowest bit position is used, result is always 0 or 1 */ + + /* bg_bgd3 = enr_bgd || ( ( cns_bgd || lp_bgd ) && ns_mask && lt_haco_mask && SD_1==0 ); */ + tmp = s_and(s_and(s_and(s_or(cns_bgd, lp_bgd), ns_mask), lt_haco_mask ), SD_1_inv); + bg_bgd3 = s_or(enr_bgd, tmp); + + /*PD_1 = (epsP_2_16_dlp_max < 0.10f ) ; */ + PD_1 = 0; + move16(); + if( (LT_16( epsP_2_16_dlp_max, 410))) /* 0.10 in Q12 */ + { + PD_1 = 1; + move16(); /* Q0 */ + } + + /*PD_2 = (epsP_0_2_ad_lp_max < 0.10f ) ; */ + PD_2 = 0; + move16(); + if( (LT_16( epsP_0_2_ad_lp_max, 410))) /* 0.10 in Q12 */ + { + PD_2 = 1; + move16(); /* Q0 */ + } + + /*PD_3 = (comb_ahc_epsP < 0.85f ); */ + PD_3 = 0; + move16(); + if( (LT_16(comb_ahc_epsP, 3482 ))) /* 0.85 in Q12 */ + { + PD_3 = 1; + move16(); /* Q0 */ + } + + /* PD_4 = comb_ahc_epsP < 0.15f; */ + PD_4 = 0; + move16(); + if( (LT_16(comb_ahc_epsP, 614))) /* 0.15 in Q12 */ + { + PD_4 = 1; + move16(); /* Q0 */ + } + + /*PD_5 = comb_hcm_epsP < 0.30f; */ + PD_5 = 0; + move16(); + if( (LT_16(comb_hcm_epsP, 1229))) /* 0.30 in Q12 */ + { + PD_5 = 1; + move16(); /* Q0 */ + } + + /* BG_1 = ( (SD_1==0) || (Etot < Etot_l_lp_thr) ) + && bg_haco_mask && (st->act_pred < 0.85f) && (st->Etot_lp < 50.0f); */ + BG_1 = 0; + move16(); + test(); + test(); + test(); + test(); + if( ( (SD_1 == 0) || (LT_16(Etot, Etot_l_lp_thr))) + && (bg_haco_mask != 0) && ( LT_16(st_fx->act_pred_fx, 27853 ) ) /* 0.85f in Q15 */ + && (LT_16(st_fx->Etot_lp_fx, 50*256) )) /* 50.0 in Q8 */ + { + BG_1 = 1; + move16(); + } + + /* PAU = (st->aEn==0) + || ( (Etot < 55.0f) && (SD_1==0) + && ( ( PD_3 && (PD_1 || PD_2 ) ) || ( PD_4 || PD_5 ) ) ); */ + PAU=0; + move16();/*Q0*/ + if(st_fx->aEn_fx == 0) + { + PAU = 1; + move16();/*Q0*/ + } + tmp = 0; + move16();/*Q0*/ + if( LT_16(Etot, 55*256)) /*55.0 in Q8 */ + { + tmp = 1; + move16();/*Q0*/ + } + tmp = s_and(tmp, SD_1_inv); + PAU = s_or(PAU, s_and(tmp, s_or(s_and(PD_3, s_or(PD_1, PD_2 )) , s_or( PD_4, PD_5 )))) ; + + + /* NEW_POS_BG = (PAU | BG_1) & bg_bgd3; note bitwise logic in float */ + NEW_POS_BG = s_and(s_or(PAU, BG_1),bg_bgd3); + + /* Original silence detector works in most cases */ + /* aE_bgd = (st->aEn == 0);*/ + aE_bgd = 0; + move16(); + if(st_fx->aEn_fx == 0) + { + aE_bgd = 1; + move16(); + } + + + + /* When the signal dynamics is high and the energy is close to the background estimate */ + /* sd1_bgd = (st->sign_dyn_lp > 15) + && (Etot - st->Etot_l_lp ) < 2*st->Etot_v_h2 + && st->harm_cor_cnt > 20; */ + sd1_bgd = 0; + move16(); + test(); + test(); + if ( ( GT_16(st_fx->sign_dyn_lp_fx, 15*256)) /* 15 in Q8 */ + && ( LT_16(sub(Etot, st_fx->Etot_l_lp_fx ), shl(Etot_v_h2, 1) ) ) /* Q8 , Etot_v_h2 has limited dynmics can be upscaled*/ + && (GT_16(*st_harm_cor_cnt, 20) ) ) + { + sd1_bgd = 1; + move16(); + } + + /* tn_ini = st->ini_frame < 150 && st->harm_cor_cnt > 5 && + ( (st->act_pred < 0.59f && st->lt_haco_ev <0.23f ) || + st->act_pred < 0.38f || + st->lt_haco_ev < 0.15f || + non_staB < 50.0f || + aE_bgd );*/ + + tmp = 0; + move16(); + test(); + test(); + test(); + test(); + test(); + if ( ( (LT_16(st_fx->act_pred_fx, 19333))&&(LT_16(st_fx->lt_haco_ev_fx,7537))) /* .59 in Q15 .23 in Q15 */ + || (LT_16(st_fx->act_pred_fx, 12452) ) /* .38 in Q15 */ + || (LT_16(st_fx->lt_haco_ev_fx, 4915) ) /* .15 in Q15 */ + || (LT_16(non_staB, 50*256 ) ) /* 50.0 in Q8 */ + || aE_bgd != 0 + || ( (LT_16(Etot,10752)) /* 42 in Q8 */ + && (GT_16(st_fx->harm_cor_cnt_fx, 10) ) + && ( LT_16(st_fx->lt_haco_ev_fx, 11469) ) /* 0.35 in Q15 */ + && ( LT_16(st_fx->act_pred_fx, 26214) ) /* 0.80 in Q15 */ + ) + ) + { + tmp = 1; + move16(); + } + + tn_ini = 0; + move16(); + test(); + test(); + if ( ( LT_16(st_fx->ini_frame_fx, HE_LT_CNT_INIT_FX )) + && ( GT_16(st_fx->harm_cor_cnt_fx,5)) /* > 5 Q0 */ + && ( LT_16(sub(Etot,st_fx->Etot_lp_fx),1792 )) /* 7 in Q8 */ + && ( NE_16(tmp, 0)) ) + { + tn_ini = 1; + move16(); + } + + /* Energy close to the background estimate serves as a mask for other background detectors */ + /* bg_bgd2 = Etot < Etot_l_lp_thr || tn_ini ; */ + bg_bgd2 = 0; + move16(); + test(); + if ( ( LT_16(Etot, Etot_l_lp_thr)) + || (tn_ini != 0 ) ) + { + bg_bgd2 = 1; + move16(); /* Q0 */ + } + + updt_step = 0; + move16(); /* Q15 */ + /*if (( bg_bgd2 && ( aE_bgd || sd1_bgd || st->lt_tn_track >0.90f || NEW_POS_BG ) ) + || tn_ini ) */ + tmp = 0; + move16(); + if( GT_16(st_fx->lt_tn_track_fx, 29491 )) /* .90 in Q15 */ + { + tmp = 1; + move16(); + } + + IF ( s_or(s_and(bg_bgd2 , s_or(aE_bgd, s_or(sd1_bgd, s_or(tmp, NEW_POS_BG)))), tn_ini) ) + { + /*if( ( ( st->act_pred < 0.85f ) + && (aE_bgd !=0) + && ( st->lt_Ellp_dist < 10 || sd1_bgd ) + && (st->lt_tn_dist<40) + && ( ( Etot - st->totalNoise ) < 10.0f ) + ) + || ( (st->first_noise_updt == 0) && (st->harm_cor_cnt > 80) && (aE_bgd!=0) && (st->lt_aEn_zero > 0.5f) ) + || ( (tn_ini!=0) && ( aE_bgd != 0) || (non_staB < 10.0) || (st->harm_cor_cnt > 80) ) + )*/ + + test(); + test(); + test(); + test(); + test(); + test(); + test(); /* for the ELSE IF below*/ + test(); + test(); + test(); + test(); + test(); + test(); /* for the ELSE IF below*/ + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( ( LT_16(st_fx->act_pred_fx, 27853)) /* 0.85 in Q15 */ + && ( NE_16(aE_bgd ,0) ) + && ( (LT_16(st_fx->lt_Ellp_dist_fx, 10*256) ) || ( NE_16(sd1_bgd, 0) ) ) /* 10.0 in Q8*/ + && ( LT_16(st_fx->lt_tn_dist_fx, 40*256 ) ) /* 40.0 in Q8*/ + && ( LT_16(sub(Etot, st_fx->totalNoise_fx), 10*256) ) /* 10.0 in Q8*/ + ) + || ( (st_fx->first_noise_updt_fx == 0) && (GT_16(st_fx->harm_cor_cnt_fx,80) ) + && ( aE_bgd != 0 ) && (GT_16(st_fx->lt_aEn_zero_fx, 16384) ) /*.5 in Q15*/ + ) + || ( (tn_ini != 0 ) && ( ( aE_bgd != 0 ) || ( LT_16(non_staB, 10*256) ) || (GT_16(st_fx->harm_cor_cnt_fx, 80) ) ) /* 10.0 in Q8*/ + ) + ) + + { + updt_step = 32767; + move16(); + st_fx->first_noise_updt_fx = 1; + FOR( i=0; i< NB_BANDS; i++ ) + { + st_fx->bckr_fx[i] = tmpN[i]; + move32(); + } + } + /* else if ( ( ( st->act_pred < 0.80f ) && ( aE_bgd || PAU ) && st->lt_haco_ev < 0.10f ) + || ( ( st->act_pred < 0.70f ) && ( aE_bgd || non_staB < 17.0f ) && PAU && st->lt_haco_ev < 0.15f ) + || ( st->harm_cor_cnt > 80 && st->totalNoise > 5.0f && Etot < max(1.0f,Etot_l_lp + 1.5f* st->Etot_v_h2) ) + || + ( st->harm_cor_cnt > 50 && st->first_noise_updt > 30 && aE_bgd && st->lt_aEn_zero>0.5f ) + || tn_ini + ) */ + ELSE IF ( ( ( LT_16(st_fx->act_pred_fx, 26214)) /* .8 in Q15*/ + && ( ( aE_bgd != 0 ) || ( PAU != 0 ) ) + && (LT_16(st_fx->lt_haco_ev_fx, 3277) ) ) /* .10 in q15*/ + || ( ( LT_16(st_fx->act_pred_fx, 22938 ) ) /* 0.70 in Q15 */ + && ( (aE_bgd!=0 ) || ( LT_16(non_staB, 17*256 ) ) )/* 17.0 in Q8 */ + && ( PAU != 0 ) + && ( LT_16(st_fx->lt_haco_ev_fx,4915) ) /* 0.15 in Q15 */ + ) + || ( (GT_16(st_fx->harm_cor_cnt_fx, 80) ) && (GT_16(st_fx->totalNoise_fx, 5*256) ) /* 5.0 in Q8 */ + && ( LT_16(Etot, s_max((Word16)1*256, add(Etot_l_lp, add(st_fx->Etot_v_h2_fx,shr(st_fx->Etot_v_h2_fx,1))))) ) /* 1.5= 1.0+.5 */ + ) + || ( (GT_16(st_fx->harm_cor_cnt_fx,50) ) && (GT_16(st_fx->first_noise_updt_fx, 30) ) + && (aE_bgd != 0) && (GT_16(st_fx->lt_aEn_zero_fx, 16384) ) ) /*.5 in Q15*/ + || ( tn_ini != 0 ) + ) + + { + updt_step = 3277; + move16(); /* 0.1 in Q15 */ + /* if ( !aE_bgd && st->harm_cor_cnt < 50 + && ( (st->act_pred > 0.6f) + || ( (tn_ini==0) && (Etot_l_lp - st->totalNoise < 10.0f) && non_staB > 8.0f ) + ) + ) + */ + test(); + test(); + test(); + test(); + test(); + IF ( ( aE_bgd==0 ) + && ( LT_16(st_fx->harm_cor_cnt_fx, 50) ) + && ( ( GT_16(st_fx->act_pred_fx, 19661) ) /* 0.6 in Q15*/ + || ( ( tn_ini==0 ) + && (LT_16(sub(Etot_l_lp, st_fx->totalNoise_fx),10*256) ) /* 10.0 in Q8 */ + && (GT_16(non_staB, 8*256) ) /* 8.0 in in Q8*/ + ) + ) + ) + { + updt_step = 328; + move16(); /* 0.01 Q15 */ + } + /* + IF (updt_step > 0 ) + { + */ + st_fx->first_noise_updt_fx = 1; + move16(); + FOR( i=0; i< NB_BANDS; i++ ) + { + /* st->bckr[i] = st->bckr[i] + updt_step * (tmpN[i]-st->bckr[i]);*/ + /* 32 bit state update */ + Ltmp = L_sub(tmpN[i], st_fx->bckr_fx[i]); /*Q_new+Q_SCALE*/ + Ltmp = Mult_32_16(Ltmp, updt_step ); /* Q_new+Q_SCALE+15+1 -16*/ + st_fx->bckr_fx[i] = L_add(Ltmp, st_fx->bckr_fx[i]); + move32(); + } + /* + } */ + } + /*else if (aE_bgd || st->harm_cor_cnt > 100 )*/ + ELSE IF ( (aE_bgd !=0) || (GT_16(st_fx->harm_cor_cnt_fx, 100))) + { + st_fx->first_noise_updt_fx = add(st_fx->first_noise_updt_fx,1); + } + } + ELSE + { + /* If in music lower bckr to drop further */ + test(); + test(); + IF ( (GT_16(st_fx->low_tn_track_cnt_fx, 300)) + && (GT_16(st_fx->lt_haco_ev_fx, 29491 ) ) /*.9 in Q15 */ + && (st_fx->totalNoise_fx > 0 ) ) + { + updt_step = -655; + move16(); /* for debug purposes */ + FOR( i=0; i< NB_BANDS; i++ ) + { + IF( GT_32(st_fx->bckr_fx[i], L_shl(Le_min_scaled, 1L) )) /* 2*E_MIN(float) in float, here we use 2*Le_min_scaled Q_new+Q_SCALE */ + { + /* st->bckr[i] = 0.98f*st->bckr[i]; */ + st_fx->bckr_fx[i] = Mult_32_16(st_fx->bckr_fx[i], 32113); /* .98 in Q15 */ + move32(); /* move to array */ + } + } + } + /*st->lt_aEn_zero = 0.2f * (st->aEn==0) + (1-0.2f) *st->lt_aEn_zero;*/ + /* y(n+1)= alpha*tmp + (1-alpha)*y(n) */ + tmp=0; + move16(); + if( st_fx->aEn_fx == 0 ) + { + tmp=32767; + move16(); + } + st_fx->lt_aEn_zero_fx = noise_est_AR1_Qx(tmp, st_fx->lt_aEn_zero_fx, 6554); /* alpha=0.2 , Q15 */ + + } + + + return; +} + + diff --git a/lib_enc/noise_adjust_fx.c b/lib_enc/noise_adjust_fx.c new file mode 100644 index 0000000..74b6d52 --- /dev/null +++ b/lib_enc/noise_adjust_fx.c @@ -0,0 +1,69 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ + +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" /* required for wmc_tool */ + +/*--------------------------------------------------------------------------* + * noise_adjust_fx() + * + * Calculate attenuation + *--------------------------------------------------------------------------*/ + +Word16 noise_adjust_fx( /* o : index of noise attenuation Q0 */ + const Word16 *coeffs_norm, /* i : normalized coefficients Qx */ + const Word16 qx, /* i : Q value of coeffs_norm */ + const Word16 *bitalloc, /* i : bit allocation Q0 */ + const Word16 *sfm_start, /* i : band start Q0 */ + const Word16 *sfm_end, /* i : band end Q0 */ + const Word16 core_sfm /* i : index of the end band for core Q0 */ +) +{ + Word16 nf_idx, sfm, bin, num_coeffs; + Word16 E, diff, inv_num_coeffs; + + E = 0; + move16(); + num_coeffs = 0; + move16(); + + FOR (sfm = 0; sfm <= core_sfm; sfm++) + { + IF (bitalloc[sfm] == 0) + { + FOR (bin = sfm_start[sfm]; bin < sfm_end[sfm]; bin++) + { + IF (coeffs_norm[bin] == 0) + { + E = sub(E, 1); + } + ELSE + { + E = add(E, sub(15+8,add(qx,norm_s(coeffs_norm[bin])))); + } + num_coeffs = add(num_coeffs, 1); + } + } + } + + IF (num_coeffs != 0) + { + inv_num_coeffs = div_s(1,num_coeffs); /* Q15 */ + E = mult(E,inv_num_coeffs); /* Q0 (0+15-15) */ + } + ELSE + { + E = 0; + move16(); + } + + diff = sub(7, E); + nf_idx = s_min(s_max(diff,0),3); + + return nf_idx; +} diff --git a/lib_enc/normalizecoefs_fx.c b/lib_enc/normalizecoefs_fx.c new file mode 100644 index 0000000..5b2eec9 --- /dev/null +++ b/lib_enc/normalizecoefs_fx.c @@ -0,0 +1,61 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "stl.h" +#include "basop_mpy.h" +#include "prot_fx.h" +#include "cnst_fx.h" /* Common constants */ + + +/*-------------------------------------------------------------------------- + * normalizecoefs_fx() + * + * Normalize MDCT coefficients with quantized norms + *--------------------------------------------------------------------------*/ + +void normalizecoefs_fx( + Word32 *coefs, /* i : Input vector (Q12) */ + const Word16 *ynrm, /* i : quantization indices for norms */ + const Word16 num_bands, /* i : Number of bands */ + const Word16 *band_start, /* i : Start of bands */ + const Word16 *band_end, /* i : End of bands */ + Word16 *coefs_norm /* o : Normalized output vector */ +) +{ + Word16 band, j, k, r, v; + Word16 *pcoefs16; + Word32 *pcoefs; + Word16 subvec_start, subvec_end, num_coefs; + pcoefs = coefs; + pcoefs16 = coefs_norm; + + FOR (band = 0; band < num_bands; band++) + { + r = s_and(ynrm[band], 1); + v = shr(ynrm[band], 1); + k = sub(sub(17, r), v); + + subvec_start = band_start[band]; + move16(); + subvec_end = band_end[band]; + move16(); + num_coefs = sub(subvec_end, subvec_start); + + FOR (j = 0; j < num_coefs; j++) + { + IF (r!=0) + { + *pcoefs = Mpy_32_16_1(*pcoefs, INV2POWHALF); + move32(); + } + BASOP_SATURATE_WARNING_OFF /* May saturate for strong peaks in a high band, in which case saturation is desirable */ + *pcoefs16++ = round_fx( L_shl(*pcoefs++, 16-k) ); /* Q12 */ + BASOP_SATURATE_WARNING_ON + } + } + + return; +} + diff --git a/lib_enc/peak_vq_enc_fx.c b/lib_enc/peak_vq_enc_fx.c new file mode 100644 index 0000000..9c634d6 --- /dev/null +++ b/lib_enc/peak_vq_enc_fx.c @@ -0,0 +1,782 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" +#include "rom_enc_fx.h" +#include "rom_com_fx.h" +#include "stl.h" /* required for wmc_tool */ + +/*-------------------------------------------------------------------------- + * Local functions + *--------------------------------------------------------------------------*/ + +static void quant_peaks_fx(Encoder_State_fx *, const Word32*, Word32*, const Word32*, + Word16*, const Word16, const Word32, const Word16); +static Word16 hvq_code_pos_fx(Encoder_State_fx *st_fx, const Word16 *inp, const Word16 length, const Word16 num_peaks); +static Word16 sparse_code_pos_fx(const Word16 *inp, const Word16 length, Word16 *result); + +/*-------------------------------------------------------------------------- + * peak_vq_enc_fx() + * + * Vector Quantization of MDCT peaks + *--------------------------------------------------------------------------*/ + +Word16 peak_vq_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 *coefs, /* i : Input coefficient vector Q12 */ + Word32 *coefs_out, /* o : Quantized output vector Q12 */ + const Word32 brate, /* i : Core bitrate */ + const Word16 num_bits, /* i : Number of bits for HVQ */ + const Word16 vq_peaks, /* i : Number of identified peaks */ + const Word16 *ynrm, /* i : Envelope coefficients */ + Word16 *R, /* i/o: Bit allocation/updated bit allocation */ + Word16 *vq_peak_idx, /* i : Peak index vector */ + Word32 *nf_gains /* i : Estimated noise floor gains Q12 */ +) +{ + Word16 pos_bits; + Word32 normq; + Word32 pgain_q[HVQ_MAX_PEAKS_32k]; + Word32 peak_gains[HVQ_MAX_PEAKS_32k]; + Word16 coefs_pvq[HVQ_PVQ_BUF_LEN], *pCoefsPvq; /* Q12 */ + Word32 pvq_vector[HVQ_PVQ_BUF_LEN], *pPvqVector; + Word32 *pPvqVectorBandStart; + Word16 pvq_vector_norm[HVQ_PVQ_BUF_LEN]; + Word16 fg_pred[NB_SFM_MAX]; + Word16 i, j, k, m, r, pvq_bands, num_overlap_bins; + Word16 hcode_l, FlagN, low_peak_bin, vq_cb_idx, max_peaks, bin_th, bin_th2; + Word16 bits; + Word16 nf_seed; + Word16 pgain_cb_idx[HVQ_MAX_PEAKS], pgain_difidx[HVQ_MAX_PEAKS]; /* Q0 */ + Word16 pvq_norm[MAX_PVQ_BANDS]; + Word16 pvq_bits, bit_budget; + Word16 pos_vec[HVQ_THRES_BIN_32k]; + Word16 npulses[MAX_PVQ_BANDS]; + Word16 pvq_inp_vector[HVQ_PVQ_BUF_LEN]; + Word16 k_sort[MAX_PVQ_BANDS]; + Word16 Rk[MAX_PVQ_BANDS]; + Word16 gopt[NB_SFM]; + Word16 tmp1, exp1; + Word16 Q_coefs; + + + Word16 indx, vqPeaksMinus1, tmp16, whiteNoise; + Word16 *pPgainDifIdx, *pPgainCbIdx, *pVqPeakIdx, *pPosVec; + Word32 *pPeakGains, *pCoefsOut; + const Word32 *pCoefs; + Word32 acc; + UWord16 dontCare16; + Word32 manE_peak, manPeakGains, manPkEnrg; /* Due to very wide dynamic range, use floating point format, i.e., (man, exp) */ + Word16 expE_peak, expPeakGains, expPkEnrg; + Word16 *pSelBnds; + Word16 sel_bnds[HVQ_NUM_SFM_24k]; + Word16 hvq_band_end[MAX_PVQ_BANDS]; + Word16 hvq_band_start[MAX_PVQ_BANDS]; + Word16 hvq_band_width[MAX_PVQ_BANDS]; + Word16 n_sel_bnds; + UWord32 lsb; + bits = 0; + move16(); + nf_seed = RANDOM_INITSEED; + move16(); + + + set16_fx(coefs_pvq, 0, HVQ_PVQ_BUF_LEN ); + set32_fx(pvq_vector, 0, HVQ_PVQ_BUF_LEN ); + set16_fx(pvq_vector_norm, 0, HVQ_PVQ_BUF_LEN ); + set16_fx(npulses, 0, MAX_PVQ_BANDS ); + + /* Set bit-rate dependent variables */ + IF (EQ_32(brate, HQ_24k40)) + { + max_peaks = HVQ_MAX_PEAKS_24k; + move16(); + bin_th = HVQ_THRES_BIN_24k; + move16(); + bin_th2 = HVQ_THRES_BIN_24k/HVQ_NF_GROUPS; + move16(); + } + ELSE + { + max_peaks = HVQ_MAX_PEAKS_32k; + move16(); + bin_th = HVQ_THRES_BIN_32k; + move16(); + bin_th2 = HVQ_THRES_BIN_32k/HVQ_NF_GROUPS; + move16(); + } + + FOR (i = 0; i < bin_th; i++) + { + pos_vec[i] = 0; + move16(); + } + + /* Quantize noise floor gains */ + FOR (i = 0; i < HVQ_NF_GROUPS; i++) + { + logqnorm_fx(&nf_gains[i], 12, &indx, 32, 1, 0); + + /* De-quantization */ + acc = L_add(dicn_fx[indx], 0); /* Q14 */ + nf_gains[i] = L_shr(acc, 1 + 2); /* nf_gains in Q12. dicn_fx is in Q14. Need extra shift +2. */ + push_indice_fx(st_fx, IND_HVQ_NF_GAIN , (int)indx, 5); + bits = add(bits, 5); + } + + /* Signal number of peaks */ + i = sub(max_peaks, vq_peaks); + push_indice_fx(st_fx, IND_NUM_PEAKS, (int)i, 5); + bits = add(bits, 5); + + /* Identify position of first peak and arrange peak gains by position */ + pVqPeakIdx = &vq_peak_idx[0]; + low_peak_bin = bin_th; + FOR (i = 0; i < vq_peaks; i++) + { + indx = *pVqPeakIdx++; + move16(); + IF (LT_16(indx, low_peak_bin)) + { + low_peak_bin = indx; + move16(); + } + /* Store the sign information. */ + IF ( coefs[indx] < 0) + { + pos_vec[indx] = -1; /* Negative. */ move16(); + } + ELSE + { + pos_vec[indx] = 1; /* Positive */ move16(); + } + } + + pPeakGains = &peak_gains[0]; + pVqPeakIdx = &vq_peak_idx[0]; + pPosVec = &pos_vec[0]; + pCoefs = &coefs[0]; + FOR (i = 0; i < bin_th; i++) + { + acc = *pCoefs++; + IF(*pPosVec++ != 0) + { + *pPeakGains++ = L_abs(acc); /* in Q12 */ move32(); + *pVqPeakIdx++ = i; + move16(); + } + } + + /* Scale down peak gains */ + /* Divided by 4 is equivalent to consider peak_gains to be in Q14 from Q12. + * No physical bit shift is actually required. + */ + + /* Quantize peak gains */ + pPeakGains = &peak_gains[0]; + pPgainCbIdx = &pgain_cb_idx[0]; + logqnorm_fx(pPeakGains++, 14, pPgainCbIdx++, 32, 1, 1); + vqPeaksMinus1 = sub(vq_peaks, 1); + FOR (i = 0; i < vqPeaksMinus1; i++) + { + logqnorm_fx(pPeakGains++, 14, pPgainCbIdx++, 45, 1, 1); + } + + /* Code quantized peak gain indices + * and also scale up peak gains. */ + diffcod_fx(vq_peaks, pgain_cb_idx, &pgain_difidx[1]); + /* Accumulate peak energy. */ + manE_peak = L_deposit_l(0); + expE_peak = 32; + move16(); + FOR (i = 0; i < vq_peaks; i++) + { + indx = pgain_cb_idx[i]; + move16(); + /* Scale up peak gains */ + pgain_q[i] = L_shl(dicn_pg_fx[indx], 2); /* pgain_q in Q12 */ move32(); + /* Use floating point operation to deal with wide dynamic range.l + * 32-bit mantissa is used here. It should be even more accurate than + * the floating-point reference code with 24-bit mantissa! */ + expPeakGains = norm_l(pgain_q[i]); + manPeakGains = L_shl(pgain_q[i], expPeakGains); + Mpy_32_32_ss(manPeakGains, manPeakGains, &manPkEnrg, &lsb); /* peak_gains square */ + expPkEnrg = shl(expPeakGains, 1); /* Multiply by 2 due to squaring. */ + /* True floating value = manPkEng x 2^(32 - 1 - expPkEnrg - 2*12). + * In this context, the 32-bit manPkEng is in Q0. + * 32 is due to Mpy_32_32() only providing the 32 MSBs of the 64 bits product. + * -1 is due fractional mode Multiply. 2*12 is due to square of Q12. */ + floating_point_add(&manE_peak, &expE_peak, manPkEnrg, expPkEnrg); + } + pgain_difidx[0] = pgain_cb_idx[0]; + move16(); + + /* Huffman coding */ + hcode_l = 0; + pPgainDifIdx = &pgain_difidx[1]; + FOR (i = 0; i < vqPeaksMinus1; i++) + { + indx = *pPgainDifIdx++; + move16(); + hcode_l = add(hcode_l, pgain_huffsizn[indx]); + } + + FlagN = HUFCODE; + move16(); + + tmp16 = extract_l(L_mult0(GAINI_BITS, vqPeaksMinus1)); + IF ( GE_16(hcode_l, tmp16)) + { + hcode_l = tmp16; + move16(); + FlagN = NOHUFCODE; + move16(); + } + + push_indice_fx(st_fx, IND_FLAGN, (int)FlagN, 1); + push_indice_fx(st_fx, IND_PG_IDX, (int)pgain_difidx[0], GAIN0_BITS); + + IF (FlagN) + { + pPgainDifIdx = &pgain_difidx[1]; + FOR (i = 0; i < vqPeaksMinus1; i++) + { + j = *pPgainDifIdx++; + move16(); + m = pgain_huffnorm_fx[j]; + move16(); + r = pgain_huffsizn[j]; + move16(); + + push_indice_fx(st_fx, IND_PG_IDX, (int)m, r ); + } + } + ELSE + { + pPgainDifIdx = &pgain_difidx[1]; + FOR (i = 0; i < vqPeaksMinus1; i++) + { + push_indice_fx(st_fx, IND_PG_IDX, (int)(*pPgainDifIdx++), GAINI_BITS ); + } + } + + /* Number of bits used for peak gain quantization */ + bits = add(bits, add(FLAGN_BITS + GAIN0_BITS, hcode_l)); + + /* Add sign for peak shape normalization */ + FOR (i = 0; i < vq_peaks; i++) + { + indx = vq_peak_idx[i]; + move16(); + peak_gains[i] = pgain_q[i]; /* Q12 */ move32(); + IF (pos_vec[indx] < 0) + { + peak_gains[i] = L_negate(peak_gains[i]); /* Q12 */ + } + } + + /* Quantize peak shapes */ + FOR (i = 0; i < vqPeaksMinus1; i++) + { + num_overlap_bins = sub(5, sub(vq_peak_idx[i+1], vq_peak_idx[i])); + indx = sub(vq_peak_idx[i], 2); + quant_peaks_fx(st_fx, &coefs[indx], &coefs_out[indx], &peak_gains[i], &vq_cb_idx, num_overlap_bins, brate, vq_peaks); + push_indice_fx(st_fx, IND_HVQ_PEAKS, (UWord16)vq_cb_idx, 8 ); + bits = add(bits, 9); + } + + indx = sub(vq_peak_idx[i], 2); + quant_peaks_fx(st_fx, &coefs[indx], &coefs_out[indx], &peak_gains[i], &vq_cb_idx, 0, brate, vq_peaks); + push_indice_fx(st_fx, IND_HVQ_PEAKS, (UWord16)vq_cb_idx, 8 ); + bits = add(bits, 9); + + /* Quantize peak positions and sign with HVQ */ + pos_bits = hvq_code_pos_fx( st_fx, pos_vec, bin_th, vq_peaks ); + + bits = add(bits, pos_bits); + bit_budget = sub(num_bits, bits); + + /* Calculate number of PVQ bands to code and assign bits */ + pvq_bands = hvq_pvq_bitalloc_fx(bit_budget, brate, st_fx->bwidth_fx, ynrm, manE_peak, expE_peak, Rk, R, sel_bnds, + &n_sel_bnds); + + /* Get band limits for concatenated PVQ target */ + hvq_concat_bands_fx(pvq_bands, sel_bnds, n_sel_bnds, hvq_band_start, + hvq_band_width, hvq_band_end); + + /* Quantize PVQ bands */ + pCoefsOut = coefs_out; + pCoefs = coefs; + pPvqVector = pvq_vector; + pSelBnds = sel_bnds; + m = bin_th; + move16(); + FOR (k = 0; k < pvq_bands; k++) + { + IF (GE_16(k, sub(pvq_bands, n_sel_bnds))) + { + i = band_start_harm[*pSelBnds++]; + move16(); + pCoefs = coefs + i; + pCoefsOut = coefs_out + i; + } + k_sort[k] = k; + j = 0; + move16(); + pPvqVectorBandStart = pPvqVector; + WHILE (LT_16(j, hvq_band_width[k])) + { + IF (*pCoefsOut++ == 0) + { + *pPvqVector++ = *pCoefs; /* Q12 */ move32(); + j = add(j, 1); + } + pCoefs++; + } + logqnorm_fx( pPvqVectorBandStart, 12, &pvq_norm[k], 40, hvq_band_width[k], 0 ); + + } + + /* Normalize coefficients */ + normalizecoefs_fx( pvq_vector, pvq_norm, pvq_bands, hvq_band_start, hvq_band_end, pvq_vector_norm ); + Q_coefs = 12; + move16(); + + bit_budget = sub(bit_budget, i_mult2(HVQ_PVQ_GAIN_BITS, pvq_bands)); + + pvq_bits = bit_budget; + move16(); + set16_fx( npulses, 0, MAX_PVQ_BANDS ); + + pvq_encode_frame_fx(st_fx, pvq_vector_norm, Q_coefs, coefs_pvq, gopt, npulses, pvq_inp_vector, hvq_band_start, hvq_band_end, hvq_band_width, pvq_bands, + Rk, pvq_bits, HQ_CORE ); + + FOR (i = 0; i < pvq_bands; i++) + { + k_sort[i] = i; + move16(); + } + + + fine_gain_pred_fx( hvq_band_start, hvq_band_end, hvq_band_width, k_sort, npulses, NULL, NULL, pvq_bands, coefs_pvq, + pvq_inp_vector, fg_pred, HQ_CORE ); + + pCoefsOut = &coefs_out[0]; + pSelBnds = &sel_bnds[0]; + pCoefsPvq = &coefs_pvq[0]; + FOR (k = 0; k < pvq_bands; k++) + { + indx = pvq_norm[k]; + tmp1 = ratio(gopt[k], fg_pred[k], &exp1); + tmp1 = shr(tmp1, sub(1, exp1)); /* Q13 */ + Mpy_32_16_ss(dicn_fx[indx], tmp1, &normq, &dontCare16); /* dicn_fx in Q14, sorted_pvq_gain_pred_err_fx in Q13. */ + + logqnorm_fx(&normq, 12, &pvq_norm[k], 40, 1, 0); /* normq in Q(14+(16+13)+1-32)=Q12 */ + pvq_norm[k] = sub(pvq_norm[k], 8); + IF (pvq_norm[k] < 0) + { + pvq_norm[k] = 0; + move16(); + } + + push_indice_fx(st_fx, IND_HVQ_PVQ_GAIN, pvq_norm[k], HVQ_PVQ_GAIN_BITS); + pvq_bits = add(pvq_bits, HVQ_PVQ_GAIN_BITS); + + pvq_norm[k] = add(pvq_norm[k], 8); + + indx = pvq_norm[k]; + move16(); + normq = L_add(dicn_fx[indx], 0); /* in Q14 */ + j = 0; + move16(); + IF (GE_16(k, sub(pvq_bands, n_sel_bnds))) + { + i = band_start_harm[*pSelBnds++]; + move16(); + pCoefsOut = coefs_out + i; + } + WHILE (LT_16(j, hvq_band_width[k])) + { + IF (EQ_32(*pCoefsOut, 0)) + { + acc = L_mult(*pCoefsPvq++, fg_pred[k]); /* in Q(15 + 1 + 12 = 28) */ + tmp16 = extract_h(acc); /* in Q(28 - 16 = 12) */ + Mpy_32_16_ss(normq, tmp16, &acc, &dontCare16); /* acc(Q11), normq(Q14), tmp16(Q12) */ + *pCoefsOut = L_shl(acc, 12 - 11); /* Q12 */ + j = add(j, 1); + } + pCoefsOut++; + } + } + bits = add(bits, pvq_bits); + + /* Noise fill unqantized coeffs with one gain per group */ + pCoefsOut = &coefs_out[-1]; + FOR (i = 0; i < HVQ_NF_GROUPS; i++) + { + FOR (j = 0; j < bin_th2; j++) + { + IF (*(++pCoefsOut) == 0) + { + whiteNoise = Random(&nf_seed); /* Q15 */ + Mpy_32_16_ss(nf_gains[i], whiteNoise, pCoefsOut, &dontCare16); /* nf_gains in Q12. *pCoefsOut in Q12 */ + } + } + } + + return bits; +} + +/*-------------------------------------------------------------------------- + * quant_peaks_fx() + * + * Applies VQ on input vector + *--------------------------------------------------------------------------*/ + +static void quant_peaks_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 *vect_in, /* i : Target vector in Q12 */ + Word32 *vect_out, /* i/o: Quantized vector in Q12 */ + const Word32 *peak_gain, /* i : Peak gain vector in Q12 */ + Word16 *vq_idx, /* o : Codebook index */ + const Word16 overlap, /* i : Overlap indicator */ + const Word32 brate, /* i : Core bitrate */ + const Word16 Npeaks /* i : Number of peaks */ +) +{ + Word16 x[4]; /* Qx */ + Word16 xq[4]; /* Q15 */ + Word16 weights[4]; /* Q0 */ + Word16 *pWeights; + Word16 i, cb_class, search_overlap, indx, cbSize; + Word16 expPeakGain, manPeakGain, expIn, manIn; + Word32 vectIn, absPeakGain1, absPeakGain; + UWord16 dontCare; + Word16 Qx_vec[4]; + Word16 Qx = 15; + + set16_fx(weights,1,4); + + /* Divide vect_in[] by peak_gain to yield x[]. */ + expPeakGain = norm_l(*peak_gain); /* exponent */ + manPeakGain = extract_h(L_shl(*peak_gain, expPeakGain)); /* mantissa */ + manPeakGain = abs_s(manPeakGain); /* Prepare for div_s() only accepting +ve. */ + FOR (i = 0; i < 4; i++) + { + indx = hvq_index_mapping_fx[i]; + move16(); + vectIn = L_add(vect_in[indx], 0); + expIn = norm_l(vectIn); /* exponent */ + expIn = sub(expIn, 1); + expIn = s_min(expIn, expPeakGain); /* highest Q is Q15 */ + manIn = extract_h(L_shl(vectIn, expIn)); /* mantissa */ + manIn = abs_s(manIn); /* Prepare for div_s() only accepting +ve. */ + + x[i] = div_s(manIn, manPeakGain); /* in Q(15+expIn-expPeakGain) */ + + Qx_vec[i] = add(15, sub(expIn, expPeakGain)); + Qx = s_min(Qx, Qx_vec[i]); + + /* Restore the sign destroyed by abs operations. */ + if (L_xor(vectIn, *peak_gain) < 0) /* Check the sign bits (MSB). */ + { + x[i] = negate(x[i]); + } + } + FOR (i = 0; i < 4; i++) + { + IF (NE_16(Qx_vec[i], Qx)) + { + x[i] = shr(x[i], sub(Qx_vec[i], Qx)); /* Qx */ + } + } + absPeakGain = L_abs(peak_gain[0]); + IF (vect_out[0] != 0) + { + absPeakGain1 = L_abs(peak_gain[-1]); + IF (GT_32(absPeakGain1, absPeakGain)) + { + weights[0] = 0; + move16(); + if (vect_out[1] != 0) + { + weights[1] = 0; + move16(); + } + } + } + IF (overlap > 0) + { + absPeakGain1 = L_abs(peak_gain[1]); + IF (GT_32(absPeakGain1, absPeakGain)) + { + indx = sub(4, overlap); + pWeights = &weights[indx]; + FOR (i = 0; i < overlap; i++) + { + *pWeights++ = 0; + move16(); + } + } + } + + /* Classify */ +#if HVQ_VQ_DIM != 5 +#error w_vquant_fx() is hard-wired to dim = 4 = (HVQ_VQ_DIM - 1). +#endif + cb_class = w_vquant_fx(x, Qx, weights, 0, hvq_class_c_fx, HVQ_NUM_CLASS, 0); + IF (brate == HQ_24k40) + { + indx = sub(HVQ_MAX_PEAKS_24k, Npeaks); + search_overlap = hvq_cb_search_overlap24k[indx]; + move16(); + } + ELSE + { + indx = sub(HVQ_MAX_PEAKS_32k, Npeaks); + search_overlap = hvq_cb_search_overlap32k[indx]; + move16(); + } + + /* Quantize */ + cbSize = add(HVQ_CB_SIZE/2, search_overlap); + IF ( cb_class == 0 ) + { + *vq_idx = w_vquant_fx(x, Qx, weights, xq, hvq_peak_cb_fx, cbSize, 0); + push_indice_fx(st_fx, IND_HVQ_PEAKS, 0, 1 ); + } + ELSE IF( EQ_16(cb_class, 1)) + { + indx = sub(HVQ_CB_SIZE*2, shl(search_overlap,2)); + *vq_idx = w_vquant_fx(x, Qx, weights, xq, &hvq_peak_cb_fx[indx], cbSize, 0); + *vq_idx = add(*vq_idx, sub(HVQ_CB_SIZE/2, search_overlap)); + push_indice_fx(st_fx, IND_HVQ_PEAKS, 0, 1 ); + } + ELSE IF( EQ_16(cb_class, 2)) + { + indx = sub(HVQ_CB_SIZE*2, shl(search_overlap,2)); + *vq_idx = w_vquant_fx(x, Qx, weights, xq, &hvq_peak_cb_fx[indx], cbSize, 1); + *vq_idx = add(*vq_idx, sub(HVQ_CB_SIZE/2, search_overlap)); + push_indice_fx(st_fx, IND_HVQ_PEAKS, 1, 1 ); + } + ELSE + { + *vq_idx = w_vquant_fx(x, Qx, weights, xq, hvq_peak_cb_fx, cbSize, 1); + push_indice_fx(st_fx, IND_HVQ_PEAKS, 1, 1 ); + } + + FOR (i = 0; i < 4; i++) + { + indx = hvq_index_mapping_fx[i]; + move16(); + IF (weights[i] != 0) + { + Mpy_32_16_ss(*peak_gain, xq[i], &vect_out[indx], &dontCare); /* peak_gains in Q12, xq in Q15 -> Q12. */ + move32(); + } + } + vect_out[2] = *peak_gain; + move32(); /* vect_out in Q12 */ + + return; +} + +/*-------------------------------------------------------------------------- + * code_pos() + * + * Code pulse positions + *--------------------------------------------------------------------------*/ + +static Word16 sparse_code_pos_fx( + const Word16 *inp, + const Word16 length, + Word16 *result +) +{ + Word16 layer2[HVQ_CP_L2_MAX]; + Word16 layer_length; + Word16 i,j,tmp; + Word16 val, idx; + Word16 bits = 0; + Word16 mask; + + set16_fx(layer2, 0, HVQ_CP_L2_MAX); + + /*layer_length = (short)((float)length/HVQ_CP_L1_LEN + 0.5); */ + layer_length = round_fx(L_mult0(length, 13107)); /* 0+16-16, 13107 is 1/5 in Q16 */ + + FOR (j = 0; j < layer_length; j++) + { + tmp = s_min(i_mult2(add(j,1),HVQ_CP_L1_LEN), length); + FOR (i = i_mult2(j, HVQ_CP_L1_LEN); i < tmp; i++) + { + IF (inp[i] != 0) + { + layer2[j] = 1; + move16(); + BREAK; + } + } + } + + FOR (i = 0; i < layer_length; i++) + { + result[i] = layer2[i]; + move16(); + } + bits = add(bits, layer_length); + + FOR (j = 0; j < layer_length; j++) + { + IF (layer2[j] != 0) + { + val = 0; + move16(); + tmp = s_min(i_mult2(add(j,1),HVQ_CP_L1_LEN), length); + FOR (i = i_mult2(j, HVQ_CP_L1_LEN); i < tmp; i++) + { + val = shl(val, 1); + val = s_or(val, inp[i]); + } + + FOR (idx = 0; idx < HVQ_CP_MAP_LEN; idx++) + { + IF (EQ_16(hvq_cp_layer1_map5[idx], val)) + { + BREAK; + } + } + + mask = shl(1, HVQ_CP_MAP_IDX_LEN - 1); + FOR (i = 0; i < HVQ_CP_MAP_IDX_LEN; i++) + { + result[bits++] = shr(s_and(idx, mask), sub(HVQ_CP_MAP_IDX_LEN - 1, i)); + mask >>= 1; + } + } + } + + return bits; +} + +/*-------------------------------------------------------------------------- + * hvq_code_pos() + * + * Code pulse positions + *--------------------------------------------------------------------------*/ + +static Word16 hvq_code_pos_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *inp, + const Word16 length, + const Word16 num_peaks +) +{ + Word16 sparse_result[4*HVQ_THRES_BIN_32k/HVQ_CP_L1_LEN]; + Word16 delta[HVQ_MAX_PEAKS_32k]; + Word16 peak_idx[HVQ_MAX_PEAKS_32k]; + Word16 inp_abs[HVQ_THRES_BIN_32k]; + Word16 inp_sign[HVQ_MAX_PEAKS_32k]; + + Word16 i, j; + Word16 bits; + Word16 delta_max; + Word16 delta_bits, sparse_bits; + Word16 tmp; + + bits = 0; + move16(); + + /* Extract sorted peak index vector and sign vector */ + j = 0; + move16(); + FOR(i = 0; i < length; i++) + { + inp_abs[i] = abs_s(inp[i]); + IF (inp[i] != 0) + { + peak_idx[j] = i; + move16(); + inp_sign[j] = inp[i]; + move16(); + j = add(j, 1); + } + } + + /* Calculate delta */ + delta[0] = add(peak_idx[0], HVQ_CP_HUFF_OFFSET); + move16(); + delta_max = delta[0]; + move16(); + FOR (i = 1; i < num_peaks; i++) + { + delta[i] = sub(sub(peak_idx[i], peak_idx[i-1]), HVQ_CP_HUFF_OFFSET); + if (LT_16(delta_max, delta[i])) + { + delta_max = delta[i]; + move16(); + } + } + + /* Calculate bits needed for huffman coding of deltas */ + delta_bits = -1; + move16(); + IF (LE_16(delta_max, HVQ_CP_HUFF_MAX)) + { + delta_bits = 0; + move16(); + FOR (i = 0; i < num_peaks; i++) + { + delta_bits = add(delta_bits, hvq_cp_huff_len[delta[i]]); + } + } + + /* Calculate bits neeed for sparse coding */ + sparse_bits = sparse_code_pos_fx(inp_abs, length, sparse_result); + + /* Decide which coding mode to use */ + test(); + IF (GT_16(delta_bits, sparse_bits)||delta_bits<0) + { + push_indice_fx(st_fx, IND_POS_IDX, HVQ_CP_SPARSE, 1); + + FOR (i = 0; i < sparse_bits; i++) + { + push_indice_fx(st_fx, IND_POS_IDX, sparse_result[i], 1); + } + bits = add(add(bits, sparse_bits), 1); + } + ELSE + { + push_indice_fx(st_fx, IND_POS_IDX, HVQ_CP_DELTA, 1); + + FOR (i = 0; i < num_peaks; i++) + { + j = delta[i]; + move16(); + push_indice_fx(st_fx, IND_POS_IDX, hvq_cp_huff_val[j], hvq_cp_huff_len[j]); + } + bits = add(add(bits, delta_bits), 1); + } + + /* Send sign */ + FOR (i = 0; i < num_peaks; i++) + { + tmp = 1; + move16(); + if (inp_sign[i] < 0) + { + tmp = 0; + move16(); + } + push_indice_fx(st_fx, IND_POS_IDX, tmp, 1); + } + bits = add(bits, num_peaks); + + return bits; +} + diff --git a/lib_enc/pit_enc_fx.c b/lib_enc/pit_enc_fx.c new file mode 100644 index 0000000..a4ac085 --- /dev/null +++ b/lib_enc/pit_enc_fx.c @@ -0,0 +1,1505 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_enc_fx.h" /* Encoder static table prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" +#include "rom_basop_util.h" + +#define inv_T0_res InvIntTable + +static void limit_T0_voiced2( Word16 res, const Word16 *T_op, Word16 *T0_min, Word16 *T0_min_frac, + Word16 *T0_max, Word16 *T0_max_frac, Word16 pit_min, Word16 pit_max, Word16 i_subfr ); + +/*==============================================================================*/ +/* FUNCTION : pit_encode_fx() */ +/*------------------------------------------------------------------------------*/ +/* PURPOSE : Close-loop pitch lag search and pitch lag quantization */ +/* Adaptive excitation construction */ +/*------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) core_brate: core bitrate Q0 */ +/* _ (Word16) Opt_AMR_WB: flag indicating AMR-WB IO mode Q0 */ +/* _ (Word16) bwidth : input signal bandwidth Q0 */ +/* _ (Word16[]) T_op : open loop pitch estimates in current frame Q0 */ +/* _ (Word16) T0_min : lower limit for close-loop search Q0 */ +/* _ (Word16) T0_max : higher limit for close-loop search Q0 */ +/* _ (Word16) T0 : close loop integer pitch Q0 */ +/* _ (Word16) T0_frac : close loop fractional part of the pitch Q0 */ +/* _ (Word16) L_frame_fx : length of the frame Q0 */ +/* _ (Word16[]) h1 : weighted filter input response Q15 */ +/* _ (Word16[]) xn : target vector Q_new */ +/* _ (Word16) coder_type_fx : coding type Q0 */ +/* _ (Word16) i_subfr : current sub frame indicator Q0 */ +/* _ (Word16[]) exc_fx : pointer to excitation signal frame Q_new */ +/* _ (Word16[]) L_subfr : subframe length Q0 */ +/*------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Q0) */ +/* _ (Word16) T0_min : lower limit for close-loop search Q0 */ +/* _ (Word16) T0_max : higher limit for close-loop search Q0 */ +/* _ (Word16) T0 : close loop integer pitch Q0 */ +/* _ (Word16) T0_frac : close loop fractional part of the pitch Q0 */ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*==============================================================================*/ + +Word16 pit_encode_fx( /* o : Fractional pitch for each subframe */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + Word16 *limit_flag, /* i/o: restrained(0) or extended(1) Q limits */ + const Word16 i_subfr, /* i : subframe index */ + Word16 *exc, /* i/o: pointer to excitation signal frame */ + const Word16 L_subfr, /* i : subframe length */ + const Word16 *T_op, /* i : open loop pitch estimates in current frame */ + Word16 *T0_min, /* i/o: lower limit for close-loop search */ + Word16 *T0_max, /* i/o: higher limit for close-loop search */ + Word16 *T0, /* i/o: close loop integer pitch */ + Word16 *T0_frac, /* i/o: close loop fractional part of the pitch */ + const Word16 *h1, /* i : weighted filter input response */ + const Word16 *xn /* i : target vector */ +) +{ + Word16 pitch; + Word16 pit_flag, delta, mult_Top, nBits; + + + /*----------------------------------------------------------------* + * Set pit_flag to 0 for every subframe with absolute pitch search + *----------------------------------------------------------------*/ + pit_flag = i_subfr; + move16(); + if (EQ_16(i_subfr,2*L_SUBFR)) + { + pit_flag = 0; + move16(); + } + + /*-----------------------------------------------------------------* + * Limit range of pitch search + * Fractional pitch search + * Pitch quantization + *-----------------------------------------------------------------*/ + mult_Top = 1; + move16(); + + IF( !Opt_AMR_WB ) + { + /*----------------------------------------------------------------* + * pitch Q: Set limit_flag to 0 for restrained limits, and 1 for extended limits + *----------------------------------------------------------------*/ + test(); + test(); + IF( i_subfr == 0 ) + { + *limit_flag = 1; + move16(); + if( EQ_16(coder_type,VOICED)) + { + *limit_flag = 2; + move16(); /* double-extended limits */ + } + test(); + if( EQ_16(coder_type,GENERIC)&&EQ_32(core_brate,ACELP_7k20)) + { + *limit_flag = 0; + move16(); + } + } + ELSE IF( EQ_16(i_subfr,2*L_SUBFR)&&EQ_16(coder_type,GENERIC)&&LE_32(core_brate,ACELP_13k20)) + { + /*if( *T0 > (PIT_FR1_EXTEND_8b + PIT_MIN)>>1 )*/ + if( GT_16(*T0,shr(add(PIT_FR1_EXTEND_8b , PIT_MIN), 1))) + { + *limit_flag = 0; + move16(); + } + } + + IF( *limit_flag == 0 ) + { + test(); + test(); + IF( i_subfr == 0 && LT_16(T_op[0],PIT_MIN)) + { + mult_Top = 2; + move16(); + } + ELSE IF( EQ_16(i_subfr,2*L_SUBFR)&<_16(T_op[1],PIT_MIN)) + { + mult_Top = 2; + move16(); + } + } + /*-------------------------------------------------------* + * Retrieve the number of Q bits + *-------------------------------------------------------*/ + nBits = 0; + move16(); + IF( NE_16(coder_type,AUDIO)) + { + /* find the number of bits */ + IF( EQ_16(L_frame,L_FRAME)) + { + { + nBits = ACB_bits_tbl[BIT_ALLOC_IDX_fx(core_brate, coder_type, i_subfr, 0)]; + move16(); + } + } + ELSE /* L_frame == L_FRAME16k */ + { + nBits = ACB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(core_brate, coder_type, i_subfr, 0)]; + move16(); + } + } + IF( EQ_16(coder_type,AUDIO)) + { + /*-------------------------------------------------------* + * Pitch encoding in AUDIO mode + * (both ACELP@12k8 and ACELP@16k cores) + *-------------------------------------------------------*/ + + delta = 4; + move16(); + test(); + test(); + if ( EQ_16(L_subfr,L_frame/2)&&i_subfr!=0&&EQ_16(L_frame,L_FRAME)) + { + pit_flag = L_SUBFR; + move16(); + } + IF ( pit_flag == 0 ) + { + nBits = 10; + move16(); + } + ELSE + { + nBits = 6; + move16(); + } + + /* pitch lag search limitation */ + test(); + IF( i_subfr == 0 ) + { + limit_T0_fx( L_frame, delta, pit_flag, *limit_flag, mult_Top*T_op[0], 0, T0_min, T0_max ); + } + ELSE IF( EQ_16(i_subfr,2*L_SUBFR)&& pit_flag == 0 ) + { + limit_T0_fx( L_frame, delta, pit_flag, *limit_flag, mult_Top*T_op[1], 0, T0_min, T0_max ); + } + + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MAX, PIT_MAX, L_FRAME, L_subfr ); + + pit_Q_enc_fx( st_fx, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + ELSE IF( EQ_16(coder_type,VOICED)) + { + /*-------------------------------------------------------* + * Pitch encoding in VOICED mode (ACELP@12k8 core only) + *-------------------------------------------------------*/ + + delta = 4; + move16(); + if ( EQ_16(i_subfr,2*L_SUBFR)) + { + pit_flag = i_subfr; + move16(); + } + + /* pitch lag search limitation */ + IF (i_subfr == 0) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, mult_Top*T_op[0], 0, T0_min, T0_max ); + } + + /* search and encode the closed loop pitch period */ + test(); + test(); + IF( EQ_16(nBits,9)||EQ_16(nBits,5)) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_FR2_DOUBLEEXTEND_9b, PIT_FR1_DOUBLEEXTEND_9b, L_FRAME, L_SUBFR ); + move16(); + } + ELSE IF( EQ_16(nBits,10)) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MAX, PIT_MAX, L_FRAME, L_SUBFR ); + move16(); + } + + pit_Q_enc_fx( st_fx, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + ELSE + { + /*-------------------------------------------------------* + * Pitch encoding in GENERIC mode + * (both ACELP@12k8 and ACELP@16k cores) + *-------------------------------------------------------*/ + + delta = 8; + move16(); + + /* pitch lag search limitation */ + IF( i_subfr == 0 ) + { + limit_T0_fx( L_frame, delta, pit_flag, *limit_flag, mult_Top*T_op[0], 0, T0_min, T0_max ); + } + ELSE IF( EQ_16(i_subfr,2*L_SUBFR)) + { + limit_T0_fx( L_frame, delta, pit_flag, *limit_flag, mult_Top*T_op[1], 0, T0_min, T0_max ); + } + + /* search and encode the closed loop pitch period */ + IF( EQ_16(L_frame,L_FRAME)) + { + test(); + test(); + IF( EQ_16(nBits,8)||EQ_16(nBits,5)) + { + IF( *limit_flag == 0 ) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN, PIT_FR1_8b, L_FRAME, L_SUBFR ); + } + ELSE + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN_EXTEND, PIT_FR1_EXTEND_8b, L_FRAME, L_SUBFR ); + } + } + ELSE IF( EQ_16(nBits,9)||EQ_16(nBits,6)) + { + IF( *limit_flag == 0 ) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_FR2_9b, PIT_FR1_9b, L_FRAME, L_SUBFR ); + } + ELSE + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_FR2_EXTEND_9b, PIT_FR1_EXTEND_9b, L_FRAME, L_SUBFR ); + } + } + ELSE IF( EQ_16(nBits,10)) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MAX, PIT_MAX, L_FRAME, L_SUBFR ); + } + + pit_Q_enc_fx( st_fx, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + ELSE /* L_frame == L_FRAME16k */ + { + test(); + IF( EQ_16(nBits,9)||EQ_16(nBits,6)) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT16k_FR2_EXTEND_9b, PIT16k_FR1_EXTEND_9b, L_FRAME16k, L_SUBFR ); + } + ELSE IF( nBits == 10 ) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT16k_FR2_EXTEND_10b, PIT16k_MAX, L_FRAME16k, L_SUBFR ); + } + + pit16k_Q_enc_fx( st_fx, nBits, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + } + } + + /*-------------------------------------------------------* + * Pitch encoding in AMR-WB IO mode + *-------------------------------------------------------*/ + + ELSE + { + delta = 8; + move16(); + *limit_flag = 0; + move16(); + + IF( EQ_32(core_brate,ACELP_6k60)) + { + nBits = 5; + move16(); + + /* pitch lag search limitation */ + IF( i_subfr == 0 ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, i_mult2(mult_Top,T_op[0]), 0, T0_min, T0_max ); + nBits = 8; + move16(); + } + + if( EQ_16(i_subfr,2*L_SUBFR)) + { + /* rewrite pit_flag - it must not be zero */ + pit_flag = i_subfr; + move16(); + } + + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN, PIT_FR1_8b, L_FRAME, L_SUBFR ); + } + ELSE IF( EQ_32(core_brate,ACELP_8k85)) + { + nBits = 5; + move16(); + + /* pitch lag search limitation */ + IF( i_subfr == 0 ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, i_mult2(mult_Top,T_op[0]), 0, T0_min, T0_max ); + nBits = 8; + move16(); + } + ELSE IF( EQ_16(i_subfr,2*L_SUBFR)) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, i_mult2(mult_Top,T_op[1]), 0, T0_min, T0_max ); + nBits = 8; + move16(); + } + + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN, PIT_FR1_8b, L_FRAME, L_SUBFR ); + } + ELSE + { + nBits = 6; + move16(); + + /* pitch lag search limitation */ + IF( i_subfr == 0 ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, i_mult2(mult_Top,T_op[0]), 0, T0_min, T0_max ); + nBits = 9; + move16(); + } + ELSE IF( EQ_16(i_subfr,2*L_SUBFR)) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, i_mult2(mult_Top,T_op[1]), 0, T0_min, T0_max ); + nBits = 9; + move16(); + } + ELSE + { + limit_T0_fx( L_FRAME, delta, pit_flag, 0, *T0, 0, T0_min, T0_max ); /* T0_frac==0 to keep IO with AMR-WB */ + } + + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_FR2_9b, PIT_FR1_9b, L_FRAME, L_SUBFR ); + } + + pit_Q_enc_fx( st_fx, 1, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + + /*-------------------------------------------------------* + * Compute floating pitch output + *-------------------------------------------------------*/ + + /*pitch = (float)(*T0) + (float)(*T0_frac)/4.0f;*/ /* save subframe pitch values */ + pitch = shl(add(shl(*T0,2),*T0_frac),4); /* save subframe pitch values Q6 */ + + return pitch; + +} + +/*-------------------------------------------------------------------* + * abs_pit_enc() + * + * Encode pitch lag absolutely with resolution for shortest pitches + * depending on parameter 'fr_step': + * fr_step = 2: pitch range encoded with 8 bits + * fr_step = 4: pitch range encoded with 8 bits + *-------------------------------------------------------------------*/ + +Word16 abs_pit_enc_fx( /* o : pitch index */ + const Word16 fr_steps, /* i : fractional resolution steps (2 or 4) for shortest pitches*/ + const Word16 limit_flag, /* i : restrained(0) or extended(1) limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac /* i : pitch fraction */ +) +{ + Word16 pitch_index = 0; + + IF( limit_flag == 0 ) + { + IF( EQ_16(fr_steps,2)) + { + /*-----------------------------------------------------------------* + * The pitch range is encoded absolutely with 8 bits + * and is divided as follows: + * PIT_MIN to PIT_FR1_8b-1 resolution 1/2 (frac = 0 or 2) + * PIT_FR1_8b to PIT_MAX resolution 1 (frac = 0) + *-----------------------------------------------------------------*/ + + IF (LT_16(T0,PIT_FR1_8b)) + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT_MIN*2);*/ + pitch_index = sub(add(shl(T0,1),shr(T0_frac,1)),(PIT_MIN*2)); + } + ELSE + { + /*pitch_index = T0 - PIT_FR1_8b + ((PIT_FR1_8b-PIT_MIN)*2);*/ + pitch_index = add(sub(T0,PIT_FR1_8b),((PIT_FR1_8b-PIT_MIN)*2)); + } + } + ELSE IF( EQ_16(fr_steps,4)) + { + /*-------------------------------------------------------------------* + * The pitch range is encoded absolutely with 9 bits + * and is divided as follows: + * PIT_MIN to PIT_FR2_9b-1 resolution 1/4 (frac = 0,1,2 or 3) + * PIT_FR2_9b to PIT_FR1_9b-1 resolution 1/2 (frac = 0 or 2) + * PIT_FR1_9b to PIT_MAX resolution 1 (frac = 0) + *-------------------------------------------------------------------*/ + + IF (LT_16(T0,PIT_FR2_9b)) + { + /*pitch_index = T0*4 + T0_frac - (PIT_MIN*4);*/ + pitch_index = add(shl(T0,2),sub(T0_frac,(PIT_MIN*4))); + } + ELSE IF (LT_16(T0,PIT_FR1_9b)) + { + /* pitch_index = T0*2 + (T0_frac>>1) - (PIT_FR2_9b*2) + ((PIT_FR2_9b-PIT_MIN)*4);*/ + pitch_index = add(sub(add(shl(T0,1),shr(T0_frac,1)),(PIT_FR2_9b*2)),((PIT_FR2_9b-PIT_MIN)*4)); + } + ELSE + { + /* pitch_index = T0 - PIT_FR1_9b + ((PIT_FR2_9b-PIT_MIN)*4) + ((PIT_FR1_9b-PIT_FR2_9b)*2);*/ + pitch_index = add(add(sub(T0,PIT_FR1_9b),((PIT_FR2_9b-PIT_MIN)*4)),((PIT_FR1_9b-PIT_FR2_9b)*2)); + } + } + ELSE /* fr_step == 0 */ + { + /* not used in the codec */ + pitch_index = 0; + move16(); + } + } + ELSE IF( EQ_16(limit_flag,1)) /* extended Q range */ + { + IF( EQ_16(fr_steps,2)) + { + /*-----------------------------------------------------------------* + * The pitch range is encoded absolutely with 8 bits + * and is divided as follows: + * PIT_MIN_EXTEND to PIT_FR1_EXTEND_8b-1 resolution 1/2 (frac = 0 or 2) + * PIT_FR1_EXTEND_8b to PIT_MAX_EXTEND resolution 1 (frac = 0) + *-----------------------------------------------------------------*/ + + IF( LT_16(T0,PIT_FR1_EXTEND_8b)) + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT_MIN_EXTEND*2);*/ + pitch_index = sub(add(shl(T0,1),shr(T0_frac,1)),(PIT_MIN_EXTEND*2)); + } + ELSE + { + /*pitch_index = T0 - PIT_FR1_EXTEND_8b + ((PIT_FR1_EXTEND_8b-PIT_MIN_EXTEND)*2);*/ + pitch_index = add(sub(T0,PIT_FR1_EXTEND_8b),((PIT_FR1_EXTEND_8b-PIT_MIN_EXTEND)*2)); + } + } + ELSE IF( EQ_16(fr_steps,4)) + { + /*-------------------------------------------------------------------* + * The pitch range is encoded absolutely with 9 bits + * and is divided as follows: + * PIT_MIN_EXTEND to PIT_FR2__EXTEND9b-1 resolution 1/4 (frac = 0,1,2 or 3) + * PIT_FR2_EXTEND_9b to PIT_FR1__EXTEND9b-1 resolution 1/2 (frac = 0 or 2) + * PIT_FR1_EXTEND_9b to PIT_MAX_EXTEND resolution 1 (frac = 0) + *-------------------------------------------------------------------*/ + + IF( LT_16(T0,PIT_FR2_EXTEND_9b)) + { + /*pitch_index = T0*4 + T0_frac - (PIT_MIN_EXTEND*4);*/ + pitch_index = add(shl(T0,2),sub(T0_frac,(PIT_MIN_EXTEND*4))); + } + ELSE IF( T0 < PIT_FR1_EXTEND_9b ) + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT_FR2_EXTEND_9b*2) + ((PIT_FR2_EXTEND_9b-PIT_MIN_EXTEND)*4);*/ + pitch_index = add(sub(add(shl(T0,1),shr(T0_frac,1)),(PIT_FR2_EXTEND_9b*2)),((PIT_FR2_EXTEND_9b-PIT_MIN_EXTEND)*4)); + } + ELSE + { + /*pitch_index = T0 - PIT_FR1_EXTEND_9b + ((PIT_FR2_EXTEND_9b-PIT_MIN_EXTEND)*4) + ((PIT_FR1_EXTEND_9b-PIT_FR2_EXTEND_9b)*2);*/ + pitch_index = add(add(sub(T0,PIT_FR1_EXTEND_9b),((PIT_FR2_EXTEND_9b-PIT_MIN_EXTEND)*4)),((PIT_FR1_EXTEND_9b-PIT_FR2_EXTEND_9b)*2)); + } + + } + ELSE /* fr_step == 0 */ + { + /* not used in the codec */ + pitch_index = 0; + move16(); + } + } + ELSE /* double-extended Q range */ + { + IF( EQ_16(fr_steps,2)) + { + /*-----------------------------------------------------------------* + * The pitch range is encoded absolutely with 8 bits + * and is divided as follows: + * PIT_MIN_DOUBLEEXTEND to PIT_FR1_DOUBLEEXTEND_8b-1 resolution 1/2 (frac = 0 or 2) + * PIT_FR1_DOUBLEEXTEND_8b to PIT_MAX_EXTEND resolution 1 (frac = 0) + *-----------------------------------------------------------------*/ + + IF( LT_16(T0,PIT_FR1_DOUBLEEXTEND_8b)) + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT_MIN_DOUBLEEXTEND*2);*/ + pitch_index = sub(add(shl(T0,1),shr(T0_frac,1)),(PIT_MIN_DOUBLEEXTEND*2)); + } + ELSE + { + /*pitch_index = T0 - PIT_FR1_DOUBLEEXTEND_8b + ((PIT_FR1_DOUBLEEXTEND_8b-PIT_MIN_DOUBLEEXTEND)*2); */ + pitch_index = add(sub(T0,PIT_FR1_DOUBLEEXTEND_8b),((PIT_FR1_DOUBLEEXTEND_8b-PIT_MIN_DOUBLEEXTEND)*2)); + } + } + ELSE IF( EQ_16(fr_steps,4)) + { + /*-------------------------------------------------------------------* + * The pitch range is encoded absolutely with 9 bits + * and is divided as follows: + * PIT_MIN_DOUBLEEXTEND to PIT_FR2_DOUBLEEXTEND9b-1 resolution 1/4 (frac = 0,1,2 or 3) + * PIT_FR2_DOUBLEEXTEND_9b to PIT_FR1_DOOBLEEXTEND9b-1 resolution 1/2 (frac = 0 or 2) + * PIT_FR1_DOUBLEEXTEND_9b to PIT_MAX_EXTEND resolution 1 (frac = 0) + *-------------------------------------------------------------------*/ + + IF(LT_16(T0,PIT_FR2_DOUBLEEXTEND_9b)) + { + /*pitch_index = T0*4 + T0_frac - (PIT_MIN_DOUBLEEXTEND*4);*/ + pitch_index = add(shl(T0,2),sub(T0_frac,(PIT_MIN_DOUBLEEXTEND*4))); + } + ELSE IF( LT_16(T0,PIT_FR1_DOUBLEEXTEND_9b)) + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT_FR2_DOUBLEEXTEND_9b*2) + ((PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4);*/ + pitch_index = add(sub(add(shl(T0,1),shr(T0_frac,1)),(PIT_FR2_DOUBLEEXTEND_9b*2)),((PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4)); + } + ELSE + { + /*pitch_index = T0 - PIT_FR1_DOUBLEEXTEND_9b + ((PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4) + ((PIT_FR1_DOUBLEEXTEND_9b-PIT_FR2_DOUBLEEXTEND_9b)*2);*/ + pitch_index = add(add(sub(T0,PIT_FR1_DOUBLEEXTEND_9b),((PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4)),((PIT_FR1_DOUBLEEXTEND_9b-PIT_FR2_DOUBLEEXTEND_9b)*2)); + } + } + ELSE /* fr_step == 0 */ + { + /* not used in the codec */ + pitch_index = 0; + move16(); + } + } + + return pitch_index; +} + + +/*-------------------------------------------------------------------* + * delta_pit_enc: + * + * Encode pitch lag differentially from T0_min to T0_max + * with resolution depending on parameter 'fr_step': + * fr_step = 0: resolusion 1 (frac = 0), or + * fr_step = 2: resolusion 1/2 (frac = 0 or 2), or + * fr_step = 4: resolution 1/4 (frac = 0, 1, 2, or 3) + *-------------------------------------------------------------------*/ + +Word16 delta_pit_enc_fx( /* o : pitch index */ + const Word16 fr_steps, /* i : fractional resolution steps (2 or 4)*/ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + const Word16 T0_min /* i : delta search min */ +) +{ + Word16 pitch_index = 0; + + IF( fr_steps == 0 ) + { + pitch_index = sub(T0,T0_min); + } + ELSE IF( EQ_16(fr_steps,2)) + { + /* pitch_index = (T0 - T0_min) * 2 + (T0_frac>>1);*/ + pitch_index = add(shl(sub(T0,T0_min),1),shr(T0_frac,1)); + } + ELSE IF( EQ_16(fr_steps,4)) + { + /*pitch_index = (T0 - T0_min) * 4 + T0_frac;*/ + pitch_index = add(shl(sub(T0,T0_min),2),T0_frac); + } + + return pitch_index; +} + +/*-------------------------------------------------------------------* + * pitch_fr4() + * + * Find the closed loop pitch period with 1/4 subsample resolution. + *-------------------------------------------------------------------*/ + +Word16 pitch_fr4_fx( /* o : chosen integer pitch lag */ + const Word16 exc[], /* i : excitation buffer Q_new*/ + const Word16 xn[], /* i : target signal Q_new-1+shift*/ + const Word16 h[], /* i : weighted synthesis filter impulse response Q(14+shift)*/ + const Word16 t0_min, /* i : minimum value in the searched range. Q0*/ + const Word16 t0_max, /* i : maximum value in the searched range. Q0*/ + Word16 *pit_frac, /* o : chosen fraction (0, 1, 2 or 3) */ + const Word16 i_subfr, /* i : flag to first subframe */ + const Word16 limit_flag, /* i : flag for limits (0=restrained, 1=extended) */ + const Word16 t0_fr2, /* i : minimum value for resolution 1/2 */ + const Word16 t0_fr1, /* i : minimum value for resolution 1 */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 L_subfr /* i : size of subframe */ +) +{ + Word16 i; + Word16 t_min, t_max; + Word16 max, t0, t1, fraction, step, temp; + Word16 *corr; + Word16 corr_v[15+2*L_INTERPOL1+1]; /* Total length = t0_max-t0_min+1+2*L_inter */ + Word16 pit_min; + Word16 cor_max; + + /* initialization */ + IF( limit_flag == 0 ) + { + IF( EQ_16(L_frame,L_FRAME)) + { + pit_min = PIT_MIN; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + pit_min = PIT16k_MIN; + move16(); + } + } + ELSE + { + IF( EQ_16(L_frame,L_FRAME)) + { + pit_min = PIT_MIN_EXTEND; + move16(); + IF( EQ_16(limit_flag,2)) + { + pit_min = PIT_MIN_DOUBLEEXTEND; + move16(); + } + } + ELSE /* L_frame == L_FRAME16k */ + { + pit_min = PIT16k_MIN_EXTEND; + move16(); + } + } + + /*-----------------------------------------------------------------* + * - Find interval to compute normalized correlation + * - allocate memory to normalized correlation vector + * - Compute normalized correlation between target and filtered + * excitation + *-----------------------------------------------------------------*/ + + t_min = sub(t0_min, L_INTERPOL1); + t_max = add(t0_max, L_INTERPOL1); + corr = &corr_v[-t_min]; + move16(); + move16(); /* corr[t_min..t_max] */ + + norm_corr_fx( exc, xn, h, t_min, t_max, corr, L_subfr ); + + /*-----------------------------------------------------------------* + * Find integer pitch + *-----------------------------------------------------------------*/ + + max = corr[t0_min]; + move16(); + t0 = t0_min; + move16(); + + FOR (i = add(t0_min, 1); i <= t0_max; i++) + { + if (corr[i] >= max) + { + t0 = i; + move16(); + } + max = s_max(corr[i], max); + } + + IF( EQ_16(t0_fr1,pit_min)) + { + /* don't search fraction (for 7b/4b quant) */ + test(); + IF((i_subfr == 0) && (GE_16(t0,t0_fr2))) + { + i = shl(shr(t0,1),1); /* 2 samples resolution */ + if (GT_16(add(i,2),PIT_MAX)) + { + i = sub(i,2); + } + IF (GT_16(corr[i],corr[i+2])) + { + t0 = i; + move16(); + } + ELSE + { + t0 = add(i,2); + } + } + *pit_frac = 0; + move16(); + + return(t0); + } + + test(); + IF( (i_subfr == 0) && (GE_16(t0,t0_fr1))) + { + *pit_frac = 0; + move16(); + + return(t0); + } + + /*------------------------------------------------------------------* + * Search fractionnal pitch with 1/4 subsample resolution. + * search the fractions around t0 and choose the one which maximizes + * the interpolated normalized correlation. + *-----------------------------------------------------------------*/ + + t1 = t0; + move16(); + step = 1; + move16(); /* 1/4 subsample resolution */ + fraction = 1; + move16(); + test(); + test(); + IF (((i_subfr == 0) && (GE_16(t0,t0_fr2)))||(EQ_16(t0_fr2,pit_min))) + { + step = 2; + move16(); /* 1/2 subsample resolution */ + fraction = 2; + move16(); + } + + IF (EQ_16(t0,t0_min)) /* Limit case */ + { + fraction = 0; + move16(); + cor_max = Interpol_4( &corr[t0], fraction); + } + ELSE + { + t0 = sub(t0, 1); + cor_max = Interpol_4( &corr[t0], fraction); + FOR(i = add(fraction, step); i <= 3; i = (Word16) (i + step)) + { + temp = Interpol_4( &corr[t0], i); + IF (GT_16(temp,cor_max)) + { + cor_max = temp; + move16(); + fraction = i; + move16(); + } + } + } + + FOR (i = 0; i <= 3; i = (Word16) (i + step)) + { + temp = Interpol_4( &corr[t1], i); + IF (GT_16(temp,cor_max)) + { + cor_max = temp; + move16(); + fraction = i; + move16(); + t0 = t1; + move16(); + } + } + + *pit_frac = fraction; + move16(); + + return (t0); + +} + +/*-------------------------------------------------------------------* + * norm_corr() + * + * Find the normalized correlation between the target vector and the + * filtered past excitation (correlation between target and filtered + * excitation divided by the square root of energy of filtered + * excitation) + *---------------------------------------------------------------------*/ + +void norm_corr_fx( + const Word16 exc[], /* i : excitation buffer Q_new*/ + const Word16 xn[], /* i : target signal Q_new-1+shift*/ + const Word16 h[], /* i : weighted synthesis filter impulse response Q(14+shift)*/ + const Word16 t_min, /* i : minimum value of searched range */ + const Word16 t_max, /* i : maximum value of searched range */ + Word16 ncorr[], /* o : normalized correlation Q15 */ + const Word16 L_subfr /* i : subframe size */ +) +{ + Word16 i, k, t; + Word16 corr, exp_corr, norm, exp_norm, exp, scale; + Word16 excf[L_FRAME16k]; + Word32 L_tmp; + + k = negate(t_min); + + /*-----------------------------------------------------------------* + * compute the filtered excitation for the first delay t_min + *-----------------------------------------------------------------*/ + + conv_fx( &exc[k], h, excf, L_subfr ); + + /* Compute rounded down 1/sqrt(energy of xn[]) */ + L_tmp = L_mac(1, xn[0], xn[0]); + FOR (i = 1; i < L_subfr; i++) + { + L_tmp = L_mac(L_tmp, xn[i], xn[i]); + } + exp = norm_l(L_tmp); + exp = sub(30, exp); + + exp = add(exp, 2); /* energy of xn[] x 2 + rounded up */ + scale = negate(shr(exp, 1)); /* (1< 0; i--) + { + /* saturation can occur in add() */ + /*excf[i] = add(mult(exc[k], h[i]), excf[i - 1]); move16(); */ + excf[i] = round_fx(L_mac(L_mult(excf[i - 1], 32767), exc[k], h[i])); + } + excf[0] = mult_r(exc[k], h[0]); + move16(); + } + } + + return; +} + +/*-------------------------------------------------------------------* + * pit_Q_enc() + * + * Encode subframe pitch lag + *-------------------------------------------------------------------*/ + +void pit_Q_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 delta, /* i : Half the CL searched interval */ + const Word16 pit_flag, /* i : absolute(0) or delta(1) pitch Q */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* o : delta search max */ +) +{ + Word16 pitch_index; + + IF( EQ_16(nBits,10)) /* absolute encoding with 10 bits */ + { + IF( limit_flag == 0 ) + { + /* pitch_index = T0*4 + T0_frac - (PIT_MIN*4);*/ + pitch_index = sub(add(shl(T0 , 2), T0_frac), (PIT_MIN*4)); + } + ELSE IF( EQ_16(limit_flag,1)) + { + /*pitch_index = T0*4 + T0_frac - (PIT_MIN_EXTEND*4);*/ + pitch_index = sub(add(shl(T0 , 2),T0_frac),(PIT_MIN_EXTEND*4)); + } + ELSE /* limit_flag == 2 */ + { + /*pitch_index = T0*4 + T0_frac - (PIT_MIN_DOUBLEEXTEND*4);*/ + pitch_index = sub(add(shl(T0 , 2) ,T0_frac) , (PIT_MIN_DOUBLEEXTEND*4)); + } + } + ELSE IF( EQ_16(nBits,9)) /* absolute encoding with 9 bits */ + { + pitch_index = abs_pit_enc_fx( 4, limit_flag, T0, T0_frac ); + + /* find T0_min and T0_max for delta search */ + IF( Opt_AMR_WB ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, 0, T0, 0, T0_min, T0_max ); /* T0_frac==0 to keep IO with AMR-WB */ + } + } + ELSE IF( EQ_16(nBits,8)) /* absolute encoding with 8 bits */ + { + pitch_index = abs_pit_enc_fx( 2, limit_flag, T0, T0_frac ); + + /* find T0_min and T0_max for delta search */ + IF( Opt_AMR_WB ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, 0, T0, 0, T0_min, T0_max ); /* T0_frac==0 to keep IO with AMR-WB */ + } + } + ELSE IF( EQ_16(nBits,6)) /* relative encoding with 6 bits */ + { + pitch_index = delta_pit_enc_fx( 4, T0, T0_frac, *T0_min ); + } + ELSE IF( EQ_16(nBits,5)) /* relative encoding with 5 bits */ + { + IF( EQ_16(delta,8)) + { + pitch_index = delta_pit_enc_fx( 2, T0, T0_frac, *T0_min ); + } + ELSE /* delta == 4 */ + { + pitch_index = delta_pit_enc_fx( 4, T0, T0_frac, *T0_min ); + } + } + ELSE /* nBits == 4 ) */ /* relative encoding with 4 bits */ + { + IF( EQ_16(delta,8)) + { + pitch_index = delta_pit_enc_fx( 0, T0, T0_frac, *T0_min ); + } + ELSE /* delta == 4 */ + { + pitch_index = delta_pit_enc_fx( 2, T0, T0_frac, *T0_min ); + } + } + + IF( !Opt_AMR_WB ) + { + /* find T0_min and T0_max for delta search */ + limit_T0_fx( L_FRAME, delta, L_SUBFR, limit_flag, T0, T0_frac, T0_min, T0_max ); + } + + { + push_indice_fx( st_fx, IND_PITCH, pitch_index, nBits ); + } + + return; +} + +/*-------------------------------------------------------------------* + * pit16k_Q_enc() + * + * Encode subframe pitch lag @16kHz core + *-------------------------------------------------------------------*/ + +void pit16k_Q_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* o : delta search max */ +) +{ + Word16 pitch_index; + + IF( EQ_16(nBits,10)) /* absolute encoding with 10 bits */ + { + { + IF( LT_16(T0,PIT16k_FR2_EXTEND_10b)) + { + /*pitch_index = T0*4 + T0_frac - (PIT16k_MIN_EXTEND*4);*/ + pitch_index = add(shl(T0 , 2) , sub(T0_frac , (PIT16k_MIN_EXTEND*4))); + } + ELSE + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT16k_FR2_EXTEND_10b*2) + ((PIT16k_FR2_EXTEND_10b-PIT16k_MIN_EXTEND)*4);*/ + pitch_index = add(sub(add(shl(T0,1),shr(T0_frac,1)),(PIT16k_FR2_EXTEND_10b*2)),((PIT16k_FR2_EXTEND_10b-PIT16k_MIN_EXTEND)*4)); + } + } + + push_indice_fx( st_fx, IND_PITCH, pitch_index, nBits ); + } + ELSE IF( EQ_16(nBits,9)) /* absolute encoding with 9 bits */ + { + { + /*-------------------------------------------------------------------* + * The pitch range is encoded absolutely with 9 bits + * and is divided as follows: + * PIT16k_EXTEND_MIN to PIT16k_FR2_EXTEND_9b-1 resolution 1/4 (frac = 0,1,2 or 3) + * PIT16k_FR2_EXTEND_9b to PIT16k_FR1_EXTEND_9b-1 resolution 1/2 (frac = 0 or 2) + * PIT16k_FR1_EXTEND_9b to PIT16k_MAX_EXTEND resolution 1 (frac = 0) + *-------------------------------------------------------------------*/ + + IF( LT_16(T0,PIT16k_FR2_EXTEND_9b)) + { + /*pitch_index = T0*4 + T0_frac - (PIT16k_MIN_EXTEND*4);*/ + pitch_index = add(shl(T0 , 2) , sub(T0_frac , (PIT16k_MIN_EXTEND*4))); + } + ELSE IF( LT_16(T0,PIT16k_FR1_EXTEND_9b)) + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT16k_FR2_EXTEND_9b*2) + ((PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4);*/ + pitch_index = add(sub(add(shl(T0,1),shr(T0_frac,1)),(PIT16k_FR2_EXTEND_9b*2)),((PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4)); + } + ELSE + { + /*pitch_index = T0 - PIT16k_FR1_EXTEND_9b + ((PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4) + ((PIT16k_FR1_EXTEND_9b-PIT16k_FR2_EXTEND_9b)*2);*/ + pitch_index = add(add(sub(T0, PIT16k_FR1_EXTEND_9b) , ((PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4)), ((PIT16k_FR1_EXTEND_9b-PIT16k_FR2_EXTEND_9b)*2)); + } + } + + push_indice_fx( st_fx, IND_PITCH, pitch_index, 9 ); + } + ELSE /* nBits == 6 */ /* relative encoding with 6 bits */ + { + /*pitch_index = (T0 - *T0_min) * 4 + T0_frac;*/ + pitch_index = add(shl(sub(T0,*T0_min),2),T0_frac); + + push_indice_fx( st_fx, IND_PITCH, pitch_index, nBits ); + } + + limit_T0_fx( L_FRAME16k, 8, L_SUBFR, limit_flag, T0, T0_frac, T0_min, T0_max ); + + return; +} + + +/*------------------------------------------------------------------* + * pit_encode: + * + * Close-loop pitch lag search and pitch lag quantization + * Adaptive excitation construction + *------------------------------------------------------------------*/ +void Mode2_pit_encode( + const Word16 coder_type, /* i : coding model */ + const Word16 i_subfr, /* i : subframe index */ + Word16 **pt_indice, /* i/o: quantization indices pointer */ + Word16 *exc, /* i/o: pointer to excitation signal frame */ + const Word16 *T_op, /* i : open loop pitch estimates in current frame */ + Word16 *T0_min, /* i/o: lower limit for close-loop search */ + Word16 *T0_min_frac, /* i/o: lower limit for close-loop search */ + Word16 *T0_max, /* i/o: higher limit for close-loop search */ + Word16 *T0_max_frac, /* i/o: higher limit for close-loop search */ + Word16 *T0, /* i/o: close loop integer pitch */ + Word16 *T0_frac, /* i/o: close loop fractional part of the pitch */ + Word16 *T0_res, /* i/o: close loop pitch resolution */ + Word16 *h1, /* i : weighted filter impulse response 1Q14+shift*/ + Word16 *xn, /* i : target vector */ + Word16 pit_min, + Word16 pit_fr1, + Word16 pit_fr1b, + Word16 pit_fr2, + Word16 pit_max, + Word16 pit_res_max +) +{ + Word16 pit_flag; + + BASOP_SATURATE_ERROR_ON; + + /* Pitch flag */ + pit_flag = i_subfr; + move16(); + if ( EQ_16(i_subfr,(2*L_SUBFR))) + { + pit_flag = 0; + move16(); + } + + /*-----------------------------------------------------------------* + * - Limit range of pitch search + * - Fractional pitch search + * - Pitch quantization + *-----------------------------------------------------------------*/ + IF(coder_type == 0) /*Unvoiced Coding do nothing*/ + { + *T0 = L_SUBFR; + move16(); + *T0_frac = 0; + move16(); + *T0_res = 1; + move16(); + + } + ELSE IF(EQ_16(coder_type,1)) /* 8/4/4/4 (EVS) */ + { + IF (i_subfr == 0) + { + limit_T0_voiced( 4, shr(pit_res_max,1), T_op[0], 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + ELSE + { + limit_T0_voiced( 4, shr(pit_res_max,1), *T0, *T0_frac, *T0_res, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + *T0 = E_GAIN_closed_loop_search(exc, xn, h1, *T0_min, *T0_min_frac, *T0_max, *T0_max_frac, shr(pit_res_max,1), T0_frac, T0_res, pit_res_max, + i_subfr, pit_min, pit_min, pit_fr1b, L_SUBFR); + move16(); + + IF (i_subfr == 0) + { + Mode2_abs_pit_enc( *T0, *T0_frac, pt_indice, pit_min, pit_fr1b, pit_min, pit_res_max ); + } + ELSE + { + Mode2_delta_pit_enc( *T0, *T0_frac, shr(pit_res_max,1), *T0_min, *T0_min_frac, pt_indice ); + } + + } + ELSE IF(EQ_16(coder_type,2)) /* 8/5/8/5 (EVS) */ + { + IF (i_subfr == 0) + { + limit_T0_voiced( 5, shr(pit_res_max,1), T_op[0], 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + ELSE IF(i_subfr == 2*L_SUBFR) + { + limit_T0_voiced( 5, shr(pit_res_max,1), T_op[1], 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + ELSE + { + limit_T0_voiced( 5, shr(pit_res_max,1), *T0, *T0_frac, *T0_res, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + *T0 = E_GAIN_closed_loop_search(exc, xn, h1, *T0_min, *T0_min_frac, *T0_max, *T0_max_frac, shr(pit_res_max,1), T0_frac, T0_res, pit_res_max, + pit_flag, pit_min, pit_min, pit_fr1b, L_SUBFR); + move16(); + + IF (pit_flag == 0) + { + Mode2_abs_pit_enc( *T0, *T0_frac, pt_indice, pit_min, pit_fr1b, pit_min, pit_res_max ); + } + ELSE + { + Mode2_delta_pit_enc( *T0, *T0_frac, shr(pit_res_max,1), *T0_min, *T0_min_frac, pt_indice ); + } + } + ELSE IF(EQ_16(coder_type,3)) /* 9/6/6/6 (HRs- VC) */ + { + Word16 pit_res_max2 = pit_res_max; + + if ( EQ_16(pit_min,PIT_MIN_16k)) + { + pit_res_max2 = shr(pit_res_max, 1); + } + + IF ( (i_subfr == 0) ) + { + limit_T0_voiced2( pit_res_max2, T_op, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max, i_subfr ); + } + ELSE + { + limit_T0_voiced( 6, pit_res_max2, *T0, 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max); + } + *T0 = E_GAIN_closed_loop_search(exc, xn, h1, *T0_min, *T0_min_frac, *T0_max, *T0_max_frac, pit_res_max2, T0_frac, T0_res, pit_res_max, + i_subfr, pit_min, pit_fr2, pit_fr1, L_SUBFR); + move16(); + + IF (i_subfr == 0) /* if 1st subframe */ + { + Mode2_abs_pit_enc( *T0, *T0_frac, pt_indice, pit_min, pit_fr1, pit_fr2, pit_res_max ); + } + ELSE + { + Mode2_delta_pit_enc( *T0, *T0_frac, pit_res_max2, *T0_min, *T0_min_frac, pt_indice ); + } + } + ELSE IF(coder_type == 4) /* 9/6/9/6 (AMRWB) */ + { + Word16 pit_res_max2 = pit_res_max; + if ( EQ_16(pit_min,PIT_MIN_16k)) + { + pit_res_max2 = shr(pit_res_max,1); + } + test(); + IF ( (i_subfr == 0) || EQ_16(i_subfr,shl(L_SUBFR,1))) + { + limit_T0_voiced2( pit_res_max2, T_op, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max, i_subfr ); + } + ELSE + { + limit_T0_voiced( 6, pit_res_max2, *T0, 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max); + } + *T0 = E_GAIN_closed_loop_search(exc, xn, h1, *T0_min, *T0_min_frac, *T0_max, *T0_max_frac, pit_res_max2, T0_frac, T0_res, pit_res_max, + pit_flag, pit_min, pit_fr2, pit_fr1, L_SUBFR); + IF (pit_flag == 0) /* if 1st/3rd/5th subframe */ + { + Mode2_abs_pit_enc( *T0, *T0_frac, pt_indice, pit_min, pit_fr1, pit_fr2, pit_res_max ); + } + ELSE /* if subframe 2 or 4 */ + { + Mode2_delta_pit_enc( *T0, *T0_frac, pit_res_max2, *T0_min, *T0_min_frac, pt_indice ); + } + } + ELSE IF(EQ_16(coder_type,8)) /* 8/5/5/5 (RF all pred mode) */ + { + IF (i_subfr == 0) + { + limit_T0_voiced( 5, shr(pit_res_max,1), T_op[0], 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + ELSE + { + limit_T0_voiced( 5, shr(pit_res_max,1), *T0, *T0_frac, *T0_res, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + *T0 = E_GAIN_closed_loop_search( exc, xn, h1, *T0_min, *T0_min_frac, *T0_max, *T0_max_frac, shr(pit_res_max,1), T0_frac, T0_res, pit_res_max, + i_subfr, pit_min, pit_min, pit_fr1b, L_SUBFR ); + + IF (i_subfr == 0) + { + Mode2_abs_pit_enc( *T0, *T0_frac, pt_indice, pit_min, pit_fr1b, pit_min, pit_res_max ); + } + ELSE + { + Mode2_delta_pit_enc( *T0, *T0_frac, shr(pit_res_max,1), *T0_min, *T0_min_frac, pt_indice ); + } + } + ELSE IF(EQ_16(coder_type,9)) /* 8/0/8/0 (RF mode Gen pred) */ + { + IF (i_subfr == 0) + { + limit_T0_voiced( 4, shr(pit_res_max,1), T_op[0], 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + ELSE + { + limit_T0_voiced( 4, shr(pit_res_max,1), *T0, *T0_frac, *T0_res, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + *T0 = E_GAIN_closed_loop_search( exc, xn, h1, *T0_min, *T0_min_frac, *T0_max, *T0_max_frac, shr(pit_res_max,1), T0_frac, T0_res, pit_res_max, + i_subfr, pit_min, pit_min, pit_fr1b, L_SUBFR ); + + IF (i_subfr == 0) + { + Mode2_abs_pit_enc( *T0, *T0_frac, pt_indice, pit_min, pit_fr1b, pit_min, pit_res_max ); + } + ELSE + { + Mode2_delta_pit_enc( *T0, *T0_frac, shr(pit_res_max,1), *T0_min, *T0_min_frac, pt_indice ); + } + } + + BASOP_SATURATE_ERROR_OFF; + + return; +} + +static void limit_T0_voiced2( + Word16 res, + const Word16 *T_op, + Word16 *T0_min, + Word16 *T0_min_frac, + Word16 *T0_max, + Word16 *T0_max_frac, + Word16 pit_min, + Word16 pit_max, + Word16 i_subfr +) +{ + Word16 t, temp1, temp2, res2; + + assert(res > 1 && res<=6); + + res2 = res; + move16(); + if(EQ_16(res,6)) + { + res2 =shr(res2,1); + } + + /* Lower-bound */ + IF (i_subfr == 0) + { + temp1 = sub(i_mult2(T_op[0],res),32); + } + ELSE + { + temp1 = sub(i_mult2(T_op[1],res),32); + } + + IF (LT_16(T_op[0],T_op[1])) + { + t = sub(i_mult2(T_op[0],res),16); + } + ELSE + { + t = sub(i_mult2(T_op[1],res),16); + } + + if (LT_16(temp1,t)) + { + temp1 = t; + } + + temp2 = mult(temp1,inv_T0_res[res2]); + if(EQ_16(res,6)) + { + temp2 = shr(temp2,1); + } + + *T0_min = temp2; + move16(); + + *T0_min_frac = sub(temp1,i_mult2(temp2,res)); + move16(); + + IF ( LT_16(*T0_min,pit_min)) + { + *T0_min = pit_min; + move16(); + *T0_min_frac = 0; + move16(); + } + + /* Higher-bound */ + temp1 = add(i_mult2(*T0_min,res),add(*T0_min_frac,63)); + + IF (T_op[0] +#include +#include "prot_fx.h" +#include "cnst_fx.h" +#include "basop_util.h" +#include "stl.h" +#include "rom_com_fx.h" +#include "rom_enc_fx.h" + +/*-----------------------------------------------------------------* + * Local Constants + *-----------------------------------------------------------------*/ +#define PIT_MIN2 20 /* pit_min for pitch tracking */ +#define PIT_MIN_1 44 /* for second pitch track */ +#define PIT_MIN2_1 24 + +#define THR_relE -2816 /* -11 (Q8) */ + +#define THRES0 4792 /* Threshold to favor smaller pitch lags; 1.17 (Q12) */ +#define DELTA0 2 /* multiples' search range initial */ +#define STEP 1 /* multiples' search range increment */ + +#define THRES1 13107 /* Threshold to favor pitch lags coherence for neighbours; 0.4 (Q15) */ +#define DELTA_COH 14 /* Maximum pitch lags difference for neighbours to be considered as coherent */ +#define THRES3 22938 /* Threshold to favor pitch lags coherence with previous frames; 0.7 (Q15) */ + +#define CORR_TH0 13107 /* Noise threshold for past frame correlations; 0.4 (Q15) */ +#define CORR_TH1 16384 /* Noise threshold for past frame correlations; 0.5 (Q15) */ + +#define LEN_X ((PIT_MAX/OPL_DECIM)-(PIT_MIN2/OPL_DECIM)+1) /* Correlation buffer length */ +#define COH_FAC 5734 /* Factor for measuring the pitch coherence; 1.4 (Q12) */ + +#define NSUBSECT 7 +#define NSECT 4 +#define NHFR 3 +#define L_FIR_PO 5 +#define L_MEM (L_FIR_PO-2) + + +/*-----------------------------------------------------------------* + * Local function prototypes + *-----------------------------------------------------------------*/ +static void LP_Decim2_Copy( + const Word16 x[], + Word16 y[], + Word16 l, + Word16 mem[] +); + +static void pitch_neighbour_fx( + Word16 sect0, + Word16 pitch_tmp[], + Word16 pitch[3][2*NSECT], + Word16 corr_tmp[], + Word16 corr[3][2*NSECT], + Word16 thres1[2*NHFR], + Word16 ind_tmp[2*NHFR] +); + +static void find_mult_fx( + Word16 *fac, + Word16 pitch0, + Word16 pitch1, + Word16 pit_max0, + Word16 *corr, + Word16 *old_pitch, + Word16 *old_corr, + Word16 delta, + Word16 step +); + +static Word16 pitch_coherence_fx( + Word16 pitch0, + Word16 pitch1, + Word16 fac_max, + Word16 diff_max +); + +static Word32 Dot_product12_OL( + Word16 *sum1, + const Word16 x[], + const Word16 y[], + const Word16 lg, + const Word16 lg2, + Word16 *exp, + Word16 *exp2 +); + +static Word32 Dot_product12_OL_back( + Word16 *sum1, + const Word16 x[], + const Word16 y[], + const Word16 lg, + const Word16 lg2, + Word16 *exp, + Word16 *exp2 +); + + +/*-----------------------------------------------------------------* + * pitch_ol_init() + * + * Open loop pitch variable initialization + *-----------------------------------------------------------------*/ +void pitch_ol_init_fx( + Word16 *old_thres, /* o : threshold for reinforcement of past pitch influence */ + Word16 *old_pitch, /* o : pitch of the 2nd half-frame of previous frame */ + Word16 *delta_pit, /* o : pitch evolution extrapolation */ + Word16 *old_corr /* o : correlation */ +) +{ + *old_thres = 0; + move16(); + *old_pitch = 0; + move16(); + *delta_pit = 0; + move16(); + *old_corr = 0; + move16(); +} + + +/*==================================================================================*/ +/* FUNCTION : pitch_ol_fx() */ +/*----------------------------------------------------------------------------------*/ +/* PURPOSE : + * Compute the open loop pitch lag. + * + * The pitch lag search is divided into two sets. + * Each set is divided into three sections. + * Each section cannot have a pitch multiple. + * We find a maximum for each section. + * We compare the maxima of each section. + * + * 1st set 2nd set + * 1st section: lag delay = 115 down to 62 and 115 down to 78 + * 2nd section: lag delay = 61 down to 32 and 77 down to 41 + * 3rd section: lag delay = 31 down to 17 and 40 down to 22 + * 4th section: lag delay = 16 down to 10 and 21 down to 12 + * + * As there is a margin between section overlaps, especially for + * longer delays, this section selection is more robust for not + * to find multiples in the same section when pitch evolves rapidly. + * + * For each section, the length of the vectors to correlate is + * greater/equal to the longest pitch delay. */ +/*----------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16[]) old_pitch : OL pitch of the 2nd half-frame of the last frame Q0 */ +/* _ (Word16[]) old_corr_fx : correlation Q15 */ +/* _ (Word16[]) corr_shift_fx : normalized correlation correction Q15 */ +/* _ (Word16[]) old_thres_fx : maximum correlation weighting with respect */ +/* to past frame pitch Q15 */ +/* _ (Word16[]) delta_pit : old pitch extrapolation correction Q0 */ +/* _ (Word16[]) st_old_wsp2_fx: weighted speech memory qwsp */ +/* _ (Word16[]) wsp_fx : weighted speech for current frame & look-ahead qwsp */ +/* _ (Word16[]) mem_decim2_fx : wsp decimation filter memory qwsp */ +/* _ (Word16[]) relE_fx : relative frame energy Q8 */ +/* _ (Word16[]) L_look : look-ahead Q0 */ +/* _ (Word16[]) Opt_SC_VBR : SC-VBR flag Q0 */ +/* _ (Word16*) qwsp : wsp & filter memory Qformat */ +/*----------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) pitch : open loop pitch lag for each half-frame Q0 */ +/* _ (Word16[]) T_op : open loop pitch lag for each half-frm for quant Q0 */ +/* _ (Word16[]) voicing_fx : max normalized correlation for each half-frame QIn */ +/* _ (Word16[]) old_pitch : OL pitch of the 2nd half-frame of the last frame Q0 */ +/* _ (Word16[]) old_corr_fx : correlation Q15 */ +/* _ (Word16[]) old_thres_fx : maximum correlation weighting with respect */ +/* to past frame pitch Q15 */ +/* _ (Word16[]) delta_pit : old pitch extrapolation correction Q0 */ +/* _ (Word16[]) st_old_wsp2_fx: weighted speech memory qwsp */ +/* _ (Word16[]) mem_decim2_fx : wsp decimation filter memory qwsp */ +/*----------------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*==================================================================================*/ + +void pitch_ol_fx( + Word16 pitch[3], /* o : open loop pitch lag for each half-frame in range [29,231] Q0 */ + Word16 voicing[3], /* o : maximum normalized correlation for each half-frame in [0,1.0[ Q15 */ + Word16 *old_pitch, /* i/o: pitch of the 2nd half-frame of previous frame (i.e. pitch[1]) Q0 */ + Word16 *old_corr, /* i/o: correlation of old_pitch (i.e. voicing[1] or corr_mean) Q15 */ + Word16 corr_shift, /* i : normalized correlation correction Q15 */ + Word16 *old_thres, /* i/o: maximum correlation weighting with respect to past frame pitch Q15 */ + Word16 *delta_pit, /* i/o: old pitch extrapolation correction in range [-14,+14] Q0 */ + Word16 *st_old_wsp2, /* i/o: weighted speech memory qwsp */ + const Word16 *wsp, /* i : weighted speech for current frame and look-ahead qwsp */ + Word16 mem_decim2[3], /* i/o: wsp decimation filter memory qwsp */ + const Word16 relE, /* i : relative frame energy Q8 */ + const Word16 last_class, /* i : frame classification of last frame */ + const Word16 bwidth, /* i : bandwidth */ + const Word16 Opt_SC_VBR /* i : SC-VBR flag */ +) +{ + Word16 ftmp, old_wsp2[(L_WSP-L_INTERPOL)/OPL_DECIM], *wsp2; + Word16 tmp_mem[3]; + + Word16 scale1[2*DELTA_COH-1]; + Word16 scaled_buf[2*LEN_X + 3*(DELTA_COH-1)]; + Word16 scaled_buf_exp[2*LEN_X + 3*(DELTA_COH-1)], exp_sect[8], exp_sect1[8], exp_sect0; + Word16 cor_buf[2*LEN_X]; + Word16 *pt_exp1, *pt_exp2, *pt_exp3, *pt_exp4; + Word16 *pt1, *pt2, *pt3, *pt4, *pt5, *pt6; + Word16 *pt_cor0, *pt_cor1, *pt_cor2, *pt_cor3, *pt_cor4, *pt_cor5, *pt_cor6; + Word16 thres1[6]; + Word16 diff, cnt, ind, ind1, offset, offset1, offset_la, offset_la1, coh_flag, coh_flag1; + Word16 ind_corX, ind1_corX; + + Word16 i, j, k, m, pit_min, pit_min1, sect0, subsect0, add_sect0, sub_sect0, old_tmp, old_tmp1, len_x, len_x1; + Word16 len_temp; + Word16 pitchX[NHFR][2*NSECT], pitch_tmp[2*NHFR], ind_tmp[2*NHFR], tmp_buf[NHFR+1]; + + Word16 enr0[NSECT], enr0_exp[NSECT], enr0_1[NSECT], enr0_1_exp[NSECT], enr1, enr1_exp, enr2_exp; + Word32 enr, enr2, Ltmp; + Word16 fac, tmp16, tmp16_2; + Word16 qCorX, qScaledX; + Word16 scaledX[NHFR][2*NSECT], corX[NHFR][2*NSECT], cor_tmp[2*NHFR], cor_mean; + const Word16 *len, *len1, *sublen, *sublen1, *pit_max, *sec_length, *sec_length1; + + Word16 pit_min_coding; + + /*--------------------------------------------------------------* + * Initialization + *--------------------------------------------------------------*/ + len = len_12k8_fx; + len1 = len1_12k8_fx; + sublen = sublen_12k8_fx; + sublen1 = sublen1_12k8_fx; + pit_max = pit_max_12k8_fx; + sec_length = sec_length_12k8_fx; + sec_length1 = sec_length1_12k8_fx; + + test(); + if ((LT_16(last_class,VOICED_TRANSITION))&&(NE_16(bwidth,NB))) + { + /*reset last pitch reinforcement in case of unvoiced or transitions: it avoids some pitch doublings*/ + *old_thres = 0; + move16(); + } + + pit_min_coding = PIT_MIN_EXTEND; + move16(); + test(); + test(); + test(); + test(); + IF ( ( (NE_16(bwidth,NB))&&(GT_16(*old_pitch,PIT_MIN)))|| + ( (EQ_16(bwidth,NB) ) && ( (GT_16(*old_pitch,PIT_MIN2_1) ) || (LT_16(*old_thres,3277) ) ) ) ) /* 0.1 inQ15*/ + { + pit_min = PIT_MIN/OPL_DECIM; + move16(); + pit_min1= PIT_MIN_1/OPL_DECIM; + move16(); + subsect0 = 2; + move16(); + sect0 = 1; + move16(); + } + ELSE + { + pit_min = PIT_MIN2/OPL_DECIM; + move16(); + pit_min1= PIT_MIN2_1/OPL_DECIM; + move16(); + subsect0 = 0; + move16(); + sect0 = 0; + move16(); + } + + len_x = (PIT_MAX/OPL_DECIM - pit_min + 1); + move16(); + len_x1= (PIT_MAX/OPL_DECIM - pit_min1 + 1); + move16(); + + /*--------------------------------------------------------------* + * Find decimated weighted speech + * Update wsp buffer with the memory + * decimation of wsp[] to search pitch in LF and to reduce complexity + * Extend the decimation of wsp to the end of the speech buffer + * Update wsp memory + *--------------------------------------------------------------*/ + Copy(st_old_wsp2, old_wsp2, (L_WSP_MEM-L_INTERPOL)/OPL_DECIM); + wsp2 = old_wsp2 + ((L_WSP_MEM-L_INTERPOL)/OPL_DECIM); + + LP_Decim2_Copy(wsp, wsp2, L_FRAME, mem_decim2); + + /* Avoid uninitialized memory access */ + set16_fx(wsp2 + L_FRAME/2, 0, sizeof(old_wsp2)/sizeof(Word16)-((L_WSP_MEM-L_INTERPOL)/OPL_DECIM)-L_FRAME/2); + tmp_mem[0] = mem_decim2[0]; + move16(); + tmp_mem[1] = mem_decim2[1]; + move16(); + tmp_mem[2] = mem_decim2[2]; + move16(); + + LP_Decim2_Copy(&wsp[L_FRAME], &wsp2[shr(L_FRAME,1)], L_LOOK_12k8, tmp_mem); /* shr() used instead of division by OPL_DECIM*/ + + Copy(&old_wsp2[shr(L_FRAME,1)], st_old_wsp2, (L_WSP_MEM-L_INTERPOL)/OPL_DECIM); + + /*-----------------------------------------------------------------* + * Attenuate the correlation correction factor due to noise. + * Reset correlation buffer outside the useful range. + * Find the scaling functions for immediate neigbours and + * further ones. + *-----------------------------------------------------------------*/ + + corr_shift = shr(corr_shift, 1); + + set16_fx( scaled_buf, 0, DELTA_COH-1 ); + set16_fx( scaled_buf + (DELTA_COH-1) + len_x, 0, DELTA_COH-1 ); + set16_fx( scaled_buf + 2*(DELTA_COH-1) + len_x + len_x1, 0, DELTA_COH-1 ); + set16_fx( scaled_buf_exp, 0, len_x + len_x1 + 3*(DELTA_COH-1)); + + pt1 = scale1 + DELTA_COH-1; + pt2 = pt1; + tmp16 = mult(negate(*old_thres), MAX_16/DELTA_COH); + k = *old_thres; + move16(); + FOR (i=0; i < DELTA_COH; i++) + { + /* + * *pt1 = ( -(*old_thres)/DELTA_COH * i + *old_thres+1.0f ); + * To keep Q15 values, the following code does not add 1 to the result. + * A scaling factor must be applied accordingly (see next use of scale1) + */ + *pt1 = k; + move16(); + k = add(k, tmp16); + *pt2-- = *pt1++; + move16(); + } + + /*-----------------------------------------------------------------------------* + * Estimate the new pitch by extrapolating the old pitch value for 2 half-frames + *-----------------------------------------------------------------------------*/ + old_tmp = add(*old_pitch, *delta_pit); + old_tmp = s_min(old_tmp, PIT_MAX/OPL_DECIM); + old_tmp = s_max(old_tmp, pit_min); + old_tmp1 = add(old_tmp, *delta_pit); + old_tmp1 = s_min(old_tmp1, PIT_MAX/OPL_DECIM); + old_tmp1 = s_max(old_tmp1, pit_min); + + /*-----------------------------------------------------------------* + * Loop for all three half-frames (current frame + look-ahead) + *-----------------------------------------------------------------*/ + pt_cor0 = scaled_buf + DELTA_COH-1; + + pt_cor2 = pt_cor0 - pit_min + old_tmp; + pt_cor4 = pt_cor0 - pit_min1 + old_tmp + (DELTA_COH-1) + len_x; + + FOR( i=0; i Q12 */ + pt2 = pt1 - pit_min; /* *pt2 -> Q12 */ + pt4 = pt1 - pit_min1; /* *pt4 -> Q12 */ + + enr = L_deposit_l(1); + + pt_cor1 = pt_cor0; + pt_cor3 = pt_cor0 + (DELTA_COH-1) + len_x; + + pt_exp1 = scaled_buf_exp + DELTA_COH-1; + pt_exp2 = pt_exp1; + pt_exp3 = scaled_buf_exp + 2*(DELTA_COH-1) + len_x; + pt_exp4 = pt_exp3; + + IF( LT_16(i,NHFR-1)) /* First two half-frames (current frame) */ + { + pt3 = pt1; + pt5 = pt1; + + FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ + { + /*-----------------------------------------------------------------* + * Find fixed vector energy + *-----------------------------------------------------------------*/ + + /* 1st set */ + k = (Word16)(pt1 - pt3); + move16(); + + FOR (k = add(k, len[j]); k > 0; k--) + { + enr = L_mac0(enr, *pt3, *pt3); + pt3++; + } + /* keep Q15 normalized result */ + cnt = norm_l(enr); + enr0[j] = extract_h(L_shl(enr, cnt)); + enr0_exp[j] = sub(30, cnt); + move16(); + + /* Reduce complexity (length of 'enr2' section is equal or larger than 'enr') */ + pt5 = pt3; + enr2 = enr; /* sets to 'enr' in 1 clock */ + move32(); + + /* 2nd set */ + k = (Word16)(pt1 - pt5); + move16(); + + FOR (k = add(k, len1[j]); k > 0; k--) + { + enr2 = L_mac0(enr2, *pt5, *pt5); + pt5++; + } + cnt = norm_l(enr2); + enr0_1[j] = extract_h(L_shl(enr2, cnt)); + enr0_1_exp[j] = sub(30, cnt); + move16(); + } + + /*----------------------------------------------------------* + * Find correlation for the non-overlapping pitch lag values + *----------------------------------------------------------*/ + exp_sect[subsect0] = 0; + move16(); + pt_cor5 = pt_cor1; + pt_cor6 = pt_cor3; + + tmp16 = exp_sect[subsect0]; + move16(); + + k = (Word16)(pt2 - pt1 + pit_max[subsect0]); + + IF (k >= 0) + { + len_temp = sublen[0]; + move16(); + + FOR (; k >= 0; k--) + { + /* Keep Q15 normalized result */ + /* shr by 1 to make room for scaling in the neighbourhood of the extrapolated pitch */ + /* Update exponent to reflect shr by 1 */ + *pt_cor1 = extract_h(L_shr(Dot_product12(pt1, pt2--, len_temp, pt_exp1), 1)); + + /* save the biggest exponent */ + tmp16 = s_max(tmp16, *pt_exp1); + + pt_cor1++; + pt_exp1++; + } + } + exp_sect[subsect0] = tmp16; + move16(); + + /*----------------------------------------------------------* + * For each subsection, find the correlation + *----------------------------------------------------------*/ + FOR (j = subsect0; j < NSUBSECT; j++) + { + len_temp = sublen[j]; + move16(); + + k = (Word16)(pt2 - pt1); + move16(); + k = add(k,pit_max[j+1]); + exp_sect[j+1] = 0; + move16(); + exp_sect1[j] = 0; + move16(); + + IF (k >= 0) + { + ind = exp_sect[j+1]; + move16(); + ind1 = exp_sect1[j]; + move16(); + + FOR (; k >= 0; k--) + { + /* Keep Q15 normalized result */ + /* shr by 1 to make room for scaling in the neighbourhood of the extrapolated pitch */ + /* Update exponent to reflect shr by 1 (done in Dot_product12_OL() for pt_cor3/pt_exp3) */ + *pt_cor1 = extract_h(L_shr(Dot_product12_OL(pt_cor3, pt1, pt2--, sublen[j], sublen1[j], pt_exp1, pt_exp3), 1)); + /* The line above replaces: + * *pt_cor1 = shr(extract_h(Dot_product12(pt1, pt2, Sublen[j], pt_exp1)),1); move16(); + * *pt_cor3 = shr(extract_h(Dot_product12(pt1, pt2--, Sublen1[j+i*7], pt_exp3)),1); move16(); + */ + + /* save the biggest exponent */ + ind = s_max(ind, *pt_exp1); + ind1 = s_max(ind1, *pt_exp3); + + pt_cor1++; + pt_exp1++; + pt_cor3++; + pt_exp3++; + } + exp_sect[j+1] = ind; + move16(); + exp_sect1[j] = ind1; + move16(); + } /* IF (k >= 0) */ + } /* FOR (j = subsect0; ... */ + } + ELSE /* 3rd half-frame (look-ahead) */ + { + pt6 = pt1 + L_LOOK_12k8/OPL_DECIM - 1; + pt3 = pt6; + pt5 = pt6; + + /*-----------------------------------------------------------------* + * For each section in both sets, find fixed vector energy + *-----------------------------------------------------------------*/ + + FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ + { + /* 1st set */ + k = (Word16)(pt3 - pt6); + move16(); + + FOR (k = add(k, len[j]); k > 0; k--) + { + enr = L_mac0(enr, *pt3, *pt3); + pt3--; + } + + cnt = norm_l(enr); + enr0[j] = extract_h(L_shl(enr, cnt)); /*qwsp+cnt-16*/ + enr0_exp[j] = sub(30, cnt); + move16(); + + /* Reduce complexity (length of 'enr2' section is equal or larger than 'enr') */ + pt5 = pt3; + enr2 = enr; + move16(); + + /* 2nd set */ + k = (Word16)(pt5 - pt6); + move16(); + + FOR (k = add(k, len1[j]); k > 0; k--) + { + enr2 = L_mac0(enr2, *pt5, *pt5); + pt5--; + } + + cnt = norm_l(enr2); + enr0_1[j] = extract_h(L_shl(enr2, cnt)); /*qwsp+cnt-16*/ + enr0_1_exp[j] = sub(30, cnt); + move16(); + } + + /* Set pointers */ + IF( sect0 != 0 ) + { + pt2 = pt6 - add(pit_max[1],1); + k = sub(pit_max[2],pit_max[1]); + move16(); + } + ELSE + { + pt2 = pt6 - pit_min; + k = 2; + move16(); + } + + /*-----------------------------------------------------------------* + * Find correlation for the non-overlapping pitch lag values + *-----------------------------------------------------------------*/ + exp_sect[subsect0] = 0; + move16(); + pt_cor5 = pt_cor1; + pt_cor6 = pt_cor3; + + tmp16 = exp_sect[subsect0]; + move16(); + + IF (k > 0) + { + len_temp = sublen[0]; + move16(); + + FOR ( ; k > 0; k-- ) + { + /* Following lines are equivalent of Dot_product12() but with a backward incrementing */ + Ltmp = L_deposit_l(1); + FOR( m = 0; m < len_temp; m++ ) + { + Ltmp = L_mac(Ltmp, pt6[-m], pt2[-m]); + } + + /* Normalize acc in Q31 */ + tmp16_2 = norm_l(Ltmp); + Ltmp = L_shl(Ltmp, tmp16_2); + *pt_exp1 = sub(30, tmp16_2); + move16(); /* exponent = 0..30 */ + + /* Save result */ + *pt_cor1 = extract_h(L_shr(Ltmp,1)); + + /* Save the biggest exponent */ + tmp16 = s_max(tmp16, *pt_exp1); + + pt_cor1++; + pt_exp1++; + pt2--; + } + exp_sect[subsect0] = tmp16; + move16(); + } + + /*-----------------------------------------------------------------* + * For each subsection, find the correlation (overlapping pitch lag values) + *-----------------------------------------------------------------*/ + + FOR( j = subsect0; j < NSUBSECT; j++ ) + { + exp_sect[j+1] = 0; + move16(); + exp_sect1[j] = 0; + move16(); + + ind = exp_sect[j+1]; + move16(); + ind1 = exp_sect1[j]; + move16(); + + k = sub(pit_max[j+1], pit_max[j]); + + FOR( ; k > 0; k-- ) + { + *pt_cor1 = extract_h(L_shr(Dot_product12_OL_back(pt_cor3, pt6, pt2--, sublen[j], sublen1[j], pt_exp1, pt_exp3), 1)); + + /* Save the biggest exponent */ + ind = s_max(ind, *pt_exp1); + ind1 = s_max(ind1, *pt_exp3); + + pt_cor1++; + pt_exp1++; + pt_cor3++; + pt_exp3++; + } + exp_sect[j+1] = ind; + move16(); + exp_sect1[j] = ind1; + move16(); + } + } /* 3rd half-frame (look-ahead) */ + + /* Scale all values in each section to the same exponent for upcoming Find_max() */ + offset = 0; + move16(); + offset1 = 0; + move16(); + exp_sect1[7] = 0; /* padding */ move16(); + FOR (j = sect0; j < NSECT; j++) + { + exp_sect0 = s_max(exp_sect[j*2], exp_sect[j*2+1]); + + /* scaling of exp for track 1 */ + offset = add(offset, sec_length[j]); + k = (Word16)(pt_cor0 - pt_cor5); + move16(); + FOR (k = add(k, offset); k > 0; k--) + { + cnt = sub(exp_sect0, *pt_exp2); + tmp16 = s_min(15, cnt); + if (cnt > 0) + { + tmp16 = shr(*pt_cor5, tmp16); + } + if (cnt > 0) + { + *pt_cor5 = tmp16; + move16(); + } + *pt_exp2 = s_max(*pt_exp2, exp_sect0); + move16(); + pt_cor5++; + pt_exp2++; + } + + exp_sect0 = s_max(exp_sect1[j*2], exp_sect1[j*2+1]); + + /* scaling of exp for track 2 */ + offset1 = add(offset1, sec_length1[j]); + k = (Word16)(pt_cor0 - pt_cor6 + (DELTA_COH-1)); + move16(); + k = add(k, len_x); + FOR (k = add(k, offset1); k > 0; k--) + { + cnt = sub(exp_sect0, *pt_exp4); + tmp16 = s_min(15, cnt); + if (cnt > 0) + { + tmp16 = shr(*pt_cor6, tmp16); + } + if (cnt > 0) + { + *pt_cor6 = tmp16; + move16(); + } + *pt_exp4 = s_max(*pt_exp4, exp_sect0); + move16(); + pt_cor6++; + pt_exp4++; + } + } /* FOR (j = sect0; ... */ + + Copy( pt_cor0, cor_buf, len_x ); /* Save unscaled correlation vector */ + Copy( pt_cor0+(DELTA_COH-1)+len_x, cor_buf+len_x, len_x1 ) ; + + /*-----------------------------------------------------------------* + * Scale correlation function in the neighbourhood of + * the extrapolated pitch + *-----------------------------------------------------------------*/ + pt_cor1 = pt_cor2 - (DELTA_COH-1); + pt_cor3 = pt_cor4 - (DELTA_COH-1); + pt2 = scale1; + + FOR( k=0 ; k < 2*DELTA_COH-1 ; k++ ) + { + /* all Q15 here */ + *pt_cor1 = add(*pt_cor1, mult(*pt_cor1, *pt2)); + move16(); + *pt_cor3 = add(*pt_cor3, mult(*pt_cor3, *pt2++)); + move16(); + + pt_cor1++; + pt_cor3++; + } + + /* Update for next half-frame & look-ahead */ + pt_cor2 = pt_cor0 - pit_min + old_tmp1; + pt_cor4 = pt_cor0 - pit_min1 + old_tmp1 + (DELTA_COH-1) + len_x; + + /*-----------------------------------------------------------------* + * For each section, find maximum correlation and compute + * normalized correlation + *-----------------------------------------------------------------*/ + + pt_cor1 = pt_cor0; + pt_exp1 = scaled_buf_exp + DELTA_COH-1; + offset = 0; + move16(); + pt_cor3 = pt_cor0 + (DELTA_COH-1) + len_x; + pt_exp3 = scaled_buf_exp + 2*(DELTA_COH-1) + len_x; + offset1 = 0; + move16(); + + FOR( j=sect0; j < NSECT; j++ ) /* loop for each section */ + { + /* 1st set */ + offset_la = 0; + move16(); + if( EQ_16(i,2)) + { + offset_la = sub(L_LOOK_12k8/OPL_DECIM,len[j]); + } + + /* 2nd set */ + offset_la1 = 0; + move16(); + if( EQ_16(i,2)) + { + offset_la1 = sub(L_LOOK_12k8/OPL_DECIM,len1[j]); + } + + /* 1st set of candidates */ + ind = add(maximum_fx( pt_cor1, sec_length[j], &ftmp ), offset); + pitchX[i][j] = add(ind, pit_min); + move16(); + pt2 = pt1 - pitchX[i][j] +/*-*/ offset_la; /* selected moving vector */ + + enr1_exp = 0; + move16(); + enr1 = add(extract_h(dotp_fx( pt2, pt2, len[j], &enr1_exp)), 1); + + enr2 = L_mult(enr0[j], enr1); + enr2_exp = norm_l(enr2); + enr2 = L_shl(enr2, enr2_exp); + enr2_exp = sub(31,add(sub(28,add(enr0_exp[j],enr1_exp)),add(enr2_exp,1))); + + enr2 = Isqrt_lc(enr2, &enr2_exp); /* 1/sqrt(energy) */ /*31-enr2_exp*/ + enr1_exp = norm_l(enr2); + enr1 = extract_h(L_shl(enr2, enr1_exp)); /*31-enr2_exp+enr1_exp-16*/ + enr1_exp = sub(enr2_exp, enr1_exp); /*15-enr1_exp*/ + + Ltmp = L_mult0(cor_buf[ind], enr1); + qCorX = add(sub(15,enr1_exp), sub(14,pt_exp1[ind])); + corX[i][j] = extract_h(L_shr(Ltmp, sub(qCorX,31))); + qCorX = 31; + move16(); + + Ltmp = L_mult0(pt_cor0[ind], enr1); + qScaledX = add(sub(15,enr1_exp),sub(14,pt_exp1[ind])); + scaledX[i][j] = round_fx(L_shl(Ltmp, sub(16+12,qScaledX))); + qScaledX =12; + move16(); + + pt_cor1 += sec_length[j]; + move16(); + offset = add(offset,sec_length[j]); + + /* 2nd set of candidates */ + ind1 = add(maximum_fx( pt_cor3, sec_length1[j], &ftmp ), offset1); + pitchX[i][j+NSECT] = add(ind1, pit_min1); + move16(); + pt4 = pt1 - pitchX[i][j+NSECT] +/*-*/ offset_la1; + move16(); /* selected moving vector */ + enr1_exp = 0; + move16(); + enr1 = add(extract_h(dotp_fx( pt4, pt4, len1[j], &enr1_exp)), 1); + + enr2 = L_mult(enr0_1[j], enr1); + enr2_exp = norm_l(enr2); + enr2 = L_shl(enr2, enr2_exp); + + enr2_exp = sub(31,add(sub(28,add(enr0_1_exp[j],enr1_exp)),add(enr2_exp,1))); + enr2 = Isqrt_lc(enr2, &enr2_exp); /* 1/sqrt(energy) */ /*31-enr2_exp*/ + enr1_exp = norm_l(enr2); + enr1 = extract_h(L_shl(enr2, enr1_exp)); /*31-enr2_exp+enr1_exp-16*/ + enr1_exp = sub(enr2_exp, enr1_exp); /*15-enr1_exp*/ + + Ltmp = L_mult0(cor_buf[ind1+len_x], enr1); + + qCorX = add(sub(15,enr1_exp),sub(14,pt_exp3[ind1])); + corX[i][j+NSECT] = extract_h(L_shr(Ltmp, qCorX-31)); + qCorX = 31; + move16(); + + Ltmp = L_mult0(pt_cor0[ind1+(DELTA_COH-1)+len_x], enr1); + qScaledX = add(sub(15,enr1_exp),sub(14,pt_exp3[ind1])); + scaledX[i][j+NSECT] = round_fx(L_shl(Ltmp, sub(16+12,qScaledX))); + /*scaledX[i][j+NSECT] = saturate(L_shr(Ltmp, qScaledX-12));*/ + qScaledX =12; + move16(); + + pt_cor3 += sec_length1[j]; + move16(); + offset1 = add(offset1, sec_length1[j]); + + } /* FOR j < NSECT */ + } /* FOR i < NHFR */ + + /*-----------------------------------------------------------------* + * Favor a smaller delay if it happens that it has its multiple + * in the longer-delay sections (harmonics check) + *-----------------------------------------------------------------*/ + + FOR( i=0; i < 2; i++ ) /* loop for the 2 half-frames */ + { + fac = THRES0; + move16(); + find_mult_fx(&fac, pitchX[i][2], pitchX[i][3], pit_max[7], &scaledX[i][2], old_pitch, old_corr, DELTA0, STEP); /* Multiples in 3rd section */ + find_mult_fx(&fac, pitchX[i][1], pitchX[i][2], pit_max[5], &scaledX[i][1], old_pitch, old_corr, DELTA0, STEP); /* Multiples in 2nd section */ + test(); + IF((sect0==0) && GE_16(shl(pitchX[i][0],1),pit_min_coding)) + { + find_mult_fx( &fac, pitchX[i][0], pitchX[i][1], pit_max[3], &scaledX[i][0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + } + fac = THRES0; + move16(); + find_mult_fx(&fac, pitchX[i][NSECT+2], pitchX[i][NSECT+3], pit_max[7], &scaledX[i][NSECT+2], old_pitch, old_corr, DELTA0, STEP); /* Multiples in 3rd section */ + find_mult_fx(&fac, pitchX[i][NSECT+1], pitchX[i][NSECT+2], pit_max[6], &scaledX[i][NSECT+1], old_pitch, old_corr, DELTA0, STEP); /* Multiples in 2nd section */ + test(); + IF((sect0==0) && GE_16(shl(pitchX[i][NSECT+0],1),pit_min_coding)) + { + find_mult_fx( &fac, pitchX[i][NSECT+0], pitchX[i][NSECT+1], pit_max[4], &scaledX[i][NSECT+0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + } + } + + fac = THRES0; + move16(); /* the look-ahead */ + find_mult_fx(&fac, pitchX[i][2], pitchX[i][3], pit_max[7], &scaledX[i][2], old_pitch, old_corr, 2, 2); /* Multiples in 3rd section */ + find_mult_fx(&fac, pitchX[i][1], pitchX[i][2], pit_max[5], &scaledX[i][1], old_pitch, old_corr, DELTA0, STEP); /* Multiples in 2nd section */ + test(); + IF((sect0==0) && GE_16(shl(pitchX[i][0],1),pit_min_coding)) + { + find_mult_fx( &fac, pitchX[i][0], pitchX[i][1], pit_max[3], &scaledX[i][0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + } + fac = THRES0; + move16(); + find_mult_fx(&fac, pitchX[i][NSECT+2], pitchX[i][NSECT+3], pit_max[7], &scaledX[i][NSECT+2], old_pitch, old_corr, 2, 2); /* Multiples in 3rd section */ + find_mult_fx(&fac, pitchX[i][NSECT+1], pitchX[i][NSECT+2], pit_max[6], &scaledX[i][NSECT+1], old_pitch, old_corr, DELTA0, STEP); /* Multiples in 2nd section */ + test(); + IF((sect0==0) && GE_16(shl(pitchX[i][NSECT+0],1),pit_min_coding)) + { + find_mult_fx( &fac, pitchX[i][NSECT+0], pitchX[i][NSECT+1], pit_max[4], &scaledX[i][NSECT+0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ /* Multiples in 2nd section */ + } + + /*-----------------------------------------------------------------* + * Do 1st estimate for pitch values + * Adjust the normalized correlation using estimated noise level + * Compute the maximum scaling for the neighbour correlation + * reinforcement + *-----------------------------------------------------------------*/ + add_sect0 = add(NSECT,sect0); + sub_sect0 = sub(NSECT,sect0); + FOR (i=0; i < NHFR; i++) + { + /* 1st set of pitch candidates */ + ind = add(maximum_fx(scaledX[i]+sect0, sub_sect0, &ftmp), sect0); + ind_tmp[i] = ind; + move16(); + pitch_tmp[i] = pitchX[i][ind]; + move16(); + cor_tmp[i] = add(corX[i][ind], corr_shift); + move16(); + + /* Higher is the neighbour's correlation, higher is the weighting */ + /* operands are Q15, result is Q15 */ + thres1[i] = mult(THRES1, cor_tmp[i]); + move16(); + + /* 2nd set of pitch candidates */ + ind1 = add(maximum_fx(scaledX[i]+add_sect0, sub_sect0, &ftmp), add_sect0); + ind_tmp[i+NHFR] = ind1; + move16(); + pitch_tmp[i+NHFR] = pitchX[i][ind1]; + move16(); + cor_tmp[i+NHFR] = add(corX[i][ind1], corr_shift); + move16(); + + /* Higher is the neighbour's correlation, higher is the weighting */ + /* operands are Q15, result is Q15 */ + thres1[i+NHFR] = mult(THRES1, cor_tmp[i+NHFR]); + move16(); + } + /*-----------------------------------------------------------------* + * Take into account previous and next pitch values of the present + * frame and look-ahead. Choose the pitch lags and normalize + * correlations for each half-frame & look-ahead + *-----------------------------------------------------------------*/ + + pitch_neighbour_fx(sect0, pitch_tmp, pitchX, cor_tmp, scaledX, thres1, ind_tmp); + FOR( i = 0; i < NHFR; i++ ) + { + ind = add(maximum_fx(scaledX[i]+sect0, sub_sect0, &ftmp), sect0); + ind_corX = add(maximum_fx(corX[i]+sect0, sub_sect0, &ftmp), sect0); + + ind1 = add(maximum_fx(scaledX[i]+add_sect0, sub_sect0, &ftmp), add_sect0); + ind1_corX = add(maximum_fx(corX[i]+add_sect0, sub_sect0, &ftmp), add_sect0); + + if ( GT_16(scaledX[i][ind1],scaledX[i][ind])) + { + ind = ind1; + move16(); + } + test(); + if ( Opt_SC_VBR && GT_16(corX[i][ind1_corX],corX[i][ind_corX])) + { + ind_corX = ind1_corX; + move16(); + } + test(); + test(); + test(); + IF (Opt_SC_VBR && (LT_16(mult(pitchX[i][ind], 13107 /*0.4 in Q15*/),pitchX[i][ind_corX]))&& + (GT_16(mult(pitchX[i][ind], 19661 /*0.6 in Q15*/),pitchX[i][ind_corX]) ) && + (GE_16(corX[i][ind_corX],29491/*0.9 in Q15*/))) + { + pitch[i] = pitchX[i][ind_corX]; + move16(); + voicing[i] = corX[i][ind_corX]; + move16(); + } + ELSE + { + pitch[i] = pitchX[i][ind]; + move16(); + voicing[i] = corX[i][ind]; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Increase the threshold for correlation reinforcement with + * the past if correlation high and pitch stable + *-----------------------------------------------------------------*/ + + /* all Q15 here */ + /* cor_mean = 0.5f * (voicing[0] + voicing[1]) + corr_shift; */ + Ltmp = L_mult(voicing[0], 16384); + Ltmp = L_mac(Ltmp, voicing[1], 16384); + cor_mean = round_fx(L_add(Ltmp, corr_shift)); + + /* pitch unstable in present frame or from previous frame or normalized correlation too low */ + coh_flag = pitch_coherence_fx(pitch[0], pitch[1], COH_FAC, DELTA_COH); + move16(); + coh_flag1 = pitch_coherence_fx(pitch[0], *old_pitch, COH_FAC, DELTA_COH); + move16(); + + test(); + test(); + test(); + IF ((coh_flag == 0) || (coh_flag1 == 0) || (LT_16(cor_mean, CORR_TH0))||(LT_16(relE,THR_relE))) + { + /* Reset the threshold */ + *old_thres = 0; + move16(); + } + ELSE + { + /* The threshold increase is directly dependent on normalized correlation */ + /* *old_thres += (0.16f * cor_mean); */ + *old_thres = round_fx(L_mac(L_deposit_h(*old_thres), 5243, cor_mean)); + } + + *old_thres = s_min(*old_thres, THRES3); + move16(); + + IF (GT_16(voicing[1], voicing[0])) + { + *old_corr = voicing[1]; + move16(); + } + ELSE + { + *old_corr = cor_mean; + move16(); + } + + /*-----------------------------------------------------------------* + * Extrapolate the pitch value for the next frame by estimating + * the pitch evolution. This value is added to the old_pitch + * in the next frame and is then used when the normalized + * correlation is reinforced by the past estimate + *-----------------------------------------------------------------*/ + tmp_buf[0] = *old_pitch; + move16(); + FOR( i = 0; i < NHFR; i++ ) + { + tmp_buf[i+1] = pitch[i]; + move16(); + } + + *delta_pit = 0; + move16(); + cnt = 0; + move16(); + + FOR ( i = 0; i < NHFR; i++ ) + { + diff = sub(tmp_buf[i+1], tmp_buf[i]); + move16(); + coh_flag = pitch_coherence_fx(tmp_buf[i], tmp_buf[i+1], COH_FAC, DELTA_COH); + + if (coh_flag != 0) + { + *delta_pit = add(*delta_pit, diff); + move16(); + } + cnt = add(cnt, coh_flag); + } + if (EQ_16(cnt, 2)) + { + /* *delta_pit /= 2; */ + *delta_pit = shr(*delta_pit, 1); + move16(); + } + IF (EQ_16(cnt, 3)) + { + k = *delta_pit; + move16(); + /* *delta_pit /= 3; */ + if (k < 0) + { + *delta_pit = mult(*delta_pit, -32768); + move16(); + } + tmp16 = mult(*delta_pit, 10923); + if (k < 0) + { + tmp16 = mult(tmp16, -32768); + } + *delta_pit = tmp16; + move16(); + } + + /*--------------------------------------------------------------* + * Update old pitch, upsample pitch, + *--------------------------------------------------------------*/ + + *old_pitch = pitch[1]; + move16(); + + FOR ( i = 0; i < NHFR; i++ ) + { + /* compensate decimation */ + pitch[i] = i_mult2(pitch[i], OPL_DECIM); + move16(); + } + + return; +} + + +/*-----------------------------------------------------------------* + * find_mult_fx + * + * Verifies whether max pitch delays in higher sections have multiples + * in lower sections + *-----------------------------------------------------------------*/ +static void find_mult_fx( + Word16 *fac, /* i/o: correlation scaling factor Q12 */ + Word16 pitch0, /* i : pitch of max correlation in the c section */ + Word16 pitch1, /* i : pitch of max correlation in the longer-delay section*/ + Word16 pit_max0, /* i : max pitch delay in the longer-delay section */ + Word16 *corr, /* i/o: max correlation in the shorter-delay section Q12 */ + Word16 *old_pitch, /* i : pitch from previous frame */ + Word16 *old_corr, /* i : max correlation from previous frame */ + Word16 delta, /* i : initial multiples search range */ + Word16 step /* i : increment in range of multiples search */ +) +{ + Word16 pit_min; + Word32 L_tmp; + + pit_min = shl(pitch0, 1); /* double the higher section pitch */ + + WHILE (LE_16(pit_min, add(pit_max0, delta))) /* check for section boundary */ + { + IF (LE_16(abs_s(sub(pit_min, pitch1)), delta)) /* if multiple in the allowed range */ + { + L_tmp = L_shl(L_mult(*corr, *fac), 3); + + /* if ( *old_corr < 0.6f || (float)pitch0 > (float)*old_pitch * 0.4f ) */ + IF (s_max(sub(19660, *old_corr), sub(pitch0, mult(*old_pitch, 13107))) > 0) + { + /* reinforce the normalized correlation */ + /* operands are Q12, result is Q12 */ + *corr = extract_h(L_tmp); + } + /* operands are Q12, result is Q12 */ + *fac = extract_h(L_shl(L_mult(*fac, THRES0), 3)); + } + pit_min = add(pit_min, pitch0); /* next multiple */ + delta = add(delta, step); /* the incertitude to the allowed range */ + } +} + +/*---------------------------------------------------------------------------* + * pitch_neighbour_fx + * + * Verifies if the maximum correlation pitch lag is coherent with neighbour + * values + *---------------------------------------------------------------------------*/ +static void pitch_neighbour_fx( + Word16 sect0, /* i : indicates whether section 0 (below PIT_MIN) is used */ + Word16 pitch_tmp[], /* i : estimated pitch values for each half-frame & look-ahead */ + Word16 pitch[3][2*NSECT], /* i : tested pitch values for each half-frame & look-ahead */ + Word16 corr_tmp[], /* i : raw normalized correlation (before different scalings) Q15*/ + Word16 corr[3][2*NSECT], /* i/o: normalized correlation for each half-frame & look-ahead Q12 */ + Word16 thres1[2*NHFR], /* i : maximum scaling for the immediate neighbours Q15 */ + Word16 ind_tmp[2*NHFR] /* i : best section index for each half-frame & look-ahead */ +) +{ + Word16 delta, i, j, k, K, coh_flag, fac; + + /*--------------------- + * 1st set of sections + ---------------------*/ + FOR ( k = sect0; k < NSECT; k++ ) /* loop for each section */ + { + K = 3; + move16(); + if (EQ_16(k, (NSECT-1))) /* the number of tests depends on the section */ + { + K = 2; + move16(); + } + /*pt = &pitch[i][k] and pt = &corr[i][k]*/ + FOR (i=0; i < K; i++) /* for the 2 half-frames and look-ahead */ + { + /* Compare pitch values of the present frame */ + FOR (j=0; j < K; j++) /* Verify pitch coherence with neighbours (including past pitch) */ + { + IF (NE_16(j, i)) /* Exclude itself, of course */ + { + IF (GE_16(corr_tmp[j], CORR_TH1)) /* reinforcement can happen only if the correlation is high enough */ + { + delta = abs_s(sub(pitch[i][k], pitch_tmp[j])); /* Find difference of pitch values */ + coh_flag = pitch_coherence_fx(pitch[i][k], pitch_tmp[j], COH_FAC, DELTA_COH); + + IF (coh_flag != 0) + { + /* Favour stability across sections, favour closer values */ + IF (EQ_16(ind_tmp[j], k)) + { + /* corr[i][k] *= ( -thres1[j]/DELTA1 * delta + thres1[j]+1 ); */ + /* operands are Q15, except corr[i][k] which is Q12 */ + fac = mult(negate(thres1[j]), MAX_16/DELTA_COH); + fac = add(i_mult2(fac, delta), thres1[j]); + } + ELSE + { + /* corr[i][k] *= ( -thres1[j]/DELTA1 * 0.625f * delta + 0.625f * thres1[j] +1.0f ); */ + fac = mult(negate(thres1[j]), 20479/DELTA_COH); + fac = add(i_mult2(fac,delta), mult(20479, thres1[j])); + } + corr[i][k] = add(corr[i][k], mult(fac, corr[i][k])); + move16(); + } + } + } + } + } + } + + /*--------------------- + * 2nd set of sections + ---------------------*/ + FOR ( k = sect0; k < NSECT; k++ ) /* loop for each section */ + { + K = 3; + move16(); + if (EQ_16(k, (NSECT-1))) /* the number of tests depends on the section */ + { + K = 2; + move16(); + } + /*pt = &pitch[i][k] and pt = &corr[i][k]*/ + FOR (i=0; i < K; i++)/* BRANCH(1); for the 2 half-frames and look-ahead */ + { + /* Compare pitch values of the present frame */ + FOR (j=0; j < K; j++)/* Verify pitch coherence with neighbours (including past pitch) */ + { + IF (NE_16(j, i))/* Exclude itself, of course */ + { + IF (GE_16(corr_tmp[j+NHFR], CORR_TH1))/* reinforcement can happen only if the correlation is high enough */ + { + delta = abs_s(sub(pitch[i][NSECT+k], pitch_tmp[j+NHFR])); /* Find difference of pitch values */ + coh_flag = pitch_coherence_fx(pitch[i][NSECT+k], pitch_tmp[j+NHFR], COH_FAC, DELTA_COH); + + IF (coh_flag != 0) + { + /* Favour stability across sections, favour closer values */ + IF (EQ_16(ind_tmp[j+NHFR], add(NSECT, k))) + { + /* corr[i][k] *= ( -thres1[j+NHFR]/DELTA1 * delta + thres1[j+NHFR]+1 ); */ + /* operands are Q15, except corr[i][NSECT+k] which is Q12 */ + fac = mult(negate(thres1[j+NHFR]), MAX_16/DELTA_COH); + fac = add(extract_l(L_shr(L_mult(fac, delta), 1)), thres1[j+NHFR]); + corr[i][NSECT+k] = add(corr[i][NSECT+k], mult(fac, corr[i][NSECT+k])); + move16(); + } + ELSE + { + /* corr[i][k] *= ( -thres1[j+NHFR]/DELTA1 * 0.625f * delta + 0.625f * thres1[j+NHFR] +1.0f ); */ + fac = mult(negate(thres1[j+NHFR]), 20479/DELTA_COH); + fac = add(extract_l(L_shr(L_mult(fac,delta), 1)), mult(20479, thres1[j+NHFR])); + corr[i][NSECT+k] = add(corr[i][NSECT+k], mult(fac, corr[i][NSECT+k])); + move16(); + } + } + } + } + } + } + } +} + +/*-----------------------------------------------------------------* + * pitch_coherence_fx + * + * Verify if pitch evolution is smooth + *-----------------------------------------------------------------*/ +static Word16 pitch_coherence_fx( + Word16 pitch0, /* i : first pitch to compare */ + Word16 pitch1, /* i : 2nd pitch to compare */ + Word16 fac_max, /* i : max ratio of both values Q12 */ + Word16 diff_max /* i : max difference of both values */ +) +{ + Word16 smaller, larger; + Word16 pc; + + smaller = s_min(pitch0, pitch1); + larger = s_max(pitch0, pitch1); + + pc = 0; + move16(); + test(); + if( (LE_16(larger, extract_h(L_shl(L_mult(fac_max, smaller), 3))))&& /* Changed to <= to keep BE */ + (LT_16(sub(larger, smaller), diff_max))) + { + pc = 1; + move16(); + } + + return pc; +} + +/*-----------------------------------------------------------------* + * LP_Decim2_Copy: + * + * Decimate a vector by 2 with 2nd order fir filter. + *-----------------------------------------------------------------*/ +static void LP_Decim2_Copy( + const Word16 x[], /* i: signal to process */ + Word16 y[], /* o: signal to process */ + Word16 l, /* i : size of filtering */ + Word16 mem[] /* i/o: memory (size=3) */ +) +{ + Word16 *p_x, x_buf[L_FRAME + L_MEM]; + Word16 i, j, k; + Word32 L_tmp; + + /* copy initial filter states into buffer */ + p_x = x_buf; + FOR (i = 0; i < L_MEM; i++) + { + *p_x++ = mem[i]; + move16(); + } + FOR (i = 0; i < l; i++) + { + *p_x++ = x[i]; + move16(); + } + if (l & 1) /* Fix for valgrind error in case l is odd. Anyway this function will be removed. */ + { + *p_x = *(p_x-1); + move16(); + } + + FOR (i = 0; i < L_MEM; i++) + { + mem[i] = x[l - L_MEM + i]; + move16(); + } + p_x = x_buf; + j = 0; + move16(); + FOR (i = 0; i < l; i += 2) + { + L_tmp = L_mult(*p_x, H_fir[0]); + FOR (k = 1; k < L_FIR_PO; k++) + { + L_tmp = L_mac(L_tmp, p_x[k], H_fir[k]); + } + p_x+=2; + + y[j++] = round_fx(L_tmp); + } +} +/*---------------------------------------------------------------------* + * Dot_product12_OL + * + * two different length dot products of x and y + *---------------------------------------------------------------------*/ +static Word32 Dot_product12_OL( /* o : Q31: normalized result (1 < val <= -1) */ + Word16 *sum1, /* o : Q31: normalized result 2 */ + const Word16 x[], /* i : 12bits: x vector */ + const Word16 y[], /* i : 12bits: y vector */ + const Word16 lg, /* i : vector length */ + const Word16 lg2, /* i : vector length 2 */ + Word16 *exp, /* o : exponent of result (0..+30) */ + Word16 *exp2 /* o : exponent of result 2 (0..+30) */ +) +{ + Word16 i, sft; + Word32 L_sum, L_sum2; + + L_sum = L_mac(1, x[0], y[0]); + IF (LE_16(lg, lg2)) + { + FOR (i = 1; i < lg; i++) + { + L_sum = L_mac(L_sum, x[i], y[i]); + } + /* sets to 'L_sum' in 1 clock */ + L_sum2 = L_sum; move32(); + FOR (; i < lg2; i++) + { + L_sum2 = L_mac(L_sum2, x[i], y[i]); + } + } + ELSE + { + FOR (i = 1; i < lg2; i++) + { + L_sum = L_mac(L_sum, x[i], y[i]); + } + /* sets to 'L_sum' in 1 clock */ + L_sum2 = L_sum; move32(); + FOR (; i < lg; i++) + { + L_sum = L_mac(L_sum, x[i], y[i]); + } + } + + /* Q31 */ + sft = norm_l(L_sum); + L_sum = L_shl(L_sum, sft); + *exp = sub(30, sft); + move16(); /* exponent = 0..30 */ + + sft = norm_l(L_sum2); + L_sum2 = L_shl(L_sum2, sft); + *exp2 = sub(30, sft); + move16(); /* exponent = 0..30 */ + + *sum1 = extract_h(L_shr(L_sum2, 1)); + + return L_sum; +} + +/*---------------------------------------------------------------------* + * Dot_product12_OL_back() + * + * two different length dot products of x and y, computed backward + *---------------------------------------------------------------------*/ +static Word32 Dot_product12_OL_back(/* o : Q31: normalized result (1 < val <= -1) */ + Word16 *sum1, /* o : Q31: normalized result 2 */ + const Word16 x[], /* i : 12bits: x vector */ + const Word16 y[], /* i : 12bits: y vector */ + const Word16 lg, /* i : vector length */ + const Word16 lg2, /* i : vector length 2 */ + Word16 *exp, /* o : exponent of result (0..+30) */ + Word16 *exp2 /* o : exponent of result 2 (0..+30) */ +) +{ + Word16 i, sft; + Word32 L_sum, L_sum2; + + L_sum = L_mac(1, x[0], y[0]); + IF (LE_16(lg, lg2)) + { + FOR (i = 1; i < lg; i++) + { + L_sum = L_mac(L_sum, x[-i], y[-i]); + } + /* sets to 'L_sum' in 1 clock */ + L_sum2 = L_sum; move32(); + FOR (; i < lg2; i++) + { + L_sum2 = L_mac(L_sum2, x[-i], y[-i]); + } + } + ELSE + { + FOR (i = 1; i < lg2; i++) + { + L_sum = L_mac(L_sum, x[-i], y[-i]); + } + /* sets to 'L_sum' in 1 clock */ + L_sum2 = L_sum; move32(); + FOR (; i < lg; i++) + { + L_sum = L_mac(L_sum, x[-i], y[-i]); + } + } + + /* Q31 */ + sft = norm_l(L_sum); + L_sum = L_shl(L_sum, sft); + *exp = sub(30, sft); + move16(); /* exponent = 0..30 */ + + sft = norm_l(L_sum2); + L_sum2 = L_shl(L_sum2, sft); + *exp2 = sub(30, sft); + move16(); /* exponent = 0..30 */ + + *sum1 = extract_h(L_shr(L_sum2, 1)); + + return L_sum; +} + + +void pitchDoubling_det( + Word16 *wspeech, + Word16 *pitch_ol, + Word16 *T_op_fr, + Word16 *voicing_fr +) +{ + Word16 new_op_fr[2]; + Word16 new_voicing[2]; + Word16 new_Top[2]; + Word16 m, T; + + + /*save initial values*/ + + new_Top[0]=pitch_ol[0]; + move16(); + new_Top[1]=pitch_ol[1]; + move16(); + + FOR(m=2; m<5; m++) + { + + /* T= pitch_ol[0]/m; */ + T = mult(pitch_ol[0],One_div_fx[m-1]); + + IF(GE_16(T,PIT_MIN_12k8)) + { + pitch_ol2_fx( PIT_MIN_SHORTER, T, &(new_op_fr[0]), &new_voicing[0], 0, wspeech, 2 ); + pitch_ol2_fx( PIT_MIN_SHORTER, T, &(new_op_fr[1]), &new_voicing[1], L_SUBFR, wspeech, 2 ); + /* IF(sub(add(new_voicing[0],new_voicing[1]),add(voicing_fr[0],voicing_fr[1]))>0 */ + IF( L_msu(L_msu(L_mac(L_mult(new_voicing[0], 8192),new_voicing[1], 8192), voicing_fr[0], 8192), voicing_fr[1], 8192) > 0 ) + { + new_Top[0]=T; + move16(); + T_op_fr[0]=new_op_fr[0]; + move16(); + T_op_fr[1]=new_op_fr[1]; + move16(); + voicing_fr[0]=new_voicing[0]; + move16(); + voicing_fr[1]=new_voicing[1]; + move16(); + } + } + + /* T= pitch_ol[1]/m; */ + T = mult(pitch_ol[1],One_div_fx[m-1]); + + IF(GE_16(T,PIT_MIN_12k8)) + { + pitch_ol2_fx( PIT_MIN_SHORTER, T, &(new_op_fr[0]), &new_voicing[0], 2*L_SUBFR, wspeech, 2 ); + pitch_ol2_fx( PIT_MIN_SHORTER, T, &(new_op_fr[1]), &new_voicing[1], 3*L_SUBFR, wspeech, 2 ); + /* IF(sub(add(new_voicing[0],new_voicing[1]),add(voicing_fr[2],voicing_fr[3]))>0) */ + IF( L_msu(L_msu(L_mac(L_mult(new_voicing[0], 8192),new_voicing[1], 8192), voicing_fr[2], 8192), voicing_fr[3], 8192) > 0 ) + { + new_Top[1]=T; + move16(); + T_op_fr[2]=new_op_fr[0]; + move16(); + T_op_fr[3]=new_op_fr[1]; + move16(); + voicing_fr[2]=new_voicing[0]; + move16(); + voicing_fr[3]=new_voicing[1]; + move16(); + } + } + } + + pitch_ol[0]=new_Top[0]; + move16(); + pitch_ol[1]=new_Top[1]; + move16(); + +}/*end of pitch doubling detection*/ diff --git a/lib_enc/pitch_ol2_fx.c b/lib_enc/pitch_ol2_fx.c new file mode 100644 index 0000000..007de95 --- /dev/null +++ b/lib_enc/pitch_ol2_fx.c @@ -0,0 +1,392 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_enc_fx.h" /* Encoder static table prototypes */ +#include "rom_com_fx.h" /* Encoder static table prototypes */ +#include "rom_dec_fx.h" +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define MAX_DELTA 16 /* half-length of the delta search */ +#define COR_BUF_LEN (L_INTERPOL1*2 + MAX_DELTA*2 + 1) + +/*-------------------------------------------------------------------* + * pitch_ol2() + * + * Open-loop pitch precision improvement with 1/4 resolution + * The pitch is searched in the interval + +#include "stl.h" +#include "cnst_fx.h" +#include "stat_enc_fx.h" +#include "prot_fx.h" + +#define NBITS_GACELP 5 + +extern const Word16 lsf_init[16]; + + +void open_PLC_ENC_EVS( + HANDLE_PLC_ENC_EVS hPlcExt, + Word32 sampleRate /* core coder SR */ +) +{ + Word16 itr; + + + hPlcExt->enableGplc = 0; + move16(); + hPlcExt->calcOnlylsf = 1; + move16(); + hPlcExt->nBits = NBITS_GACELP; + move16(); + + hPlcExt->Q_exp = 0; + move16(); + hPlcExt->Q_new = 0; + move16(); + + set16_fx(hPlcExt->mem_MA_14Q1,0,M); + set16_fx(hPlcExt->mem_AR,0,M); + set16_fx(hPlcExt->lsfold_14Q1,0,M); + set16_fx(hPlcExt->lspold_Q15,0,M); + + set16_fx(hPlcExt->old_exc_Qold,0,8); + + set16_fx(hPlcExt->lsfoldbfi0_14Q1,0,M); + set16_fx(hPlcExt->lsfoldbfi1_14Q1,0,M); + set16_fx(hPlcExt->lsf_adaptive_mean_14Q1,0,M); + hPlcExt->stab_fac_Q15 = 0; + move16(); + IF( EQ_32(sampleRate,12800)) + { + hPlcExt->T0_4th = L_SUBFR; + move16(); + hPlcExt->T0 = L_SUBFR; + move16(); + FOR( itr=0; itrlsf_con[itr] = lsf_init[itr]; + move16(); + hPlcExt->last_lsf_ref[itr] = lsf_init[itr]; + move16(); + hPlcExt->last_lsf_con[itr] = lsf_init[itr]; + move16(); + } + } + ELSE + { + hPlcExt->T0_4th = L_SUBFR; + move16(); + hPlcExt->T0 = L_SUBFR; + move16(); + FOR( itr=0; itrlsf_con[itr] = add(lsf_init[itr],shr(lsf_init[itr],2)); + hPlcExt->last_lsf_ref[itr] = add(lsf_init[itr],shr(lsf_init[itr],2)); + hPlcExt->last_lsf_con[itr] = add(lsf_init[itr],shr(lsf_init[itr],2)); + } + } + + return; +} + + +/* + function to extract and write guided information +*/ +void gPLC_encInfo (HANDLE_PLC_ENC_EVS self, + Word32 modeBitrate, + Word16 modeBandwidth, + Word16 old_clas, + Word16 coder_type + ) +{ + + + IF (self) + { + self->calcOnlylsf = 1; + move16(); + test(); + test(); + test(); + test(); + test(); + IF ( ( EQ_16(modeBandwidth, WB)&&EQ_32(modeBitrate,24400))|| + ( EQ_16(modeBandwidth, SWB) && EQ_32(modeBitrate, 24400) ) || + ( EQ_16(modeBandwidth, FB) && EQ_32(modeBitrate, 24400) ) ) + { + self->enableGplc = 1; + move16(); + self->nBits = 1; + move16(); + test(); + test(); + test(); + IF ( (EQ_16(old_clas, VOICED_CLAS)||EQ_16(old_clas,ONSET))&& + (EQ_16(coder_type, VOICED) || EQ_16(coder_type, GENERIC) ) ) + { + self->nBits = NBITS_GACELP; + move16(); + self->calcOnlylsf = 0; + move16(); + } + } + ELSE + { + self->enableGplc = 0; + move16(); + self->nBits = NBITS_GACELP; + move16(); + } + + } + +} + diff --git a/lib_enc/ppp_enc_fx.c b/lib_enc/ppp_enc_fx.c new file mode 100644 index 0000000..0c9fc74 --- /dev/null +++ b/lib_enc/ppp_enc_fx.c @@ -0,0 +1,342 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "cnst_fx.h" +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "stl.h" + +/*=======================================================================================*/ +/* FUNCTION : ppp_quarter_encoder_fx() */ +/*---------------------------------------------------------------------------------------*/ +/* PURPOSE : Quarter rate PPP encoder main routine */ +/*---------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16 []) curr_lpc_fx: LPC coefficients, Q12 */ +/* _ (struct DTFS_STRUCTURE_FX) CURRCW_NQ_FX : prototype in Cartesian domain */ +/* (Word16) lag_fx: length of prototype */ +/* (Word16 []) a/b: harmonics, normalized */ +/* (Word16) Q: norm factor of a */ +/* _ (struct DTFS_STRUCTURE_FX) PREV_CW_E_FX : past dtfs in Cartesian domain */ +/* (Word16) lag: length of prototype */ +/* (Word16 []) a/b: harmonics, normalized */ +/* (Word16) Q: norm factor of a */ +/* _ (Word16) prevCW_lag_fx: Previous lag, Q0 */ +/* _ (Word16 *) exc : Global input (Q0) */ +/* _ (Word16 []) sinTab, Q15 : sin(2pi/4L*n), n=0,1,...,4L-1 */ +/* _ (Word16 []) cosTab, Q15 : cos(2pi/4L*n), n=0,1,...,4L-1 */ +/*---------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16) pidx: Power index */ +/* _ (Word16[]) aidx: Amplitude indices, 2 words */ +/* _ (struct DTFS_fx *) CURRCW_Q_FX : quantized prototype in Cartesian domain */ +/* (Word16) lag_fx: length of prototype in time domain */ +/* (Word16 []) a/b: harmonics, normalized */ +/* (Word16) Q: norm factor of a */ +/* _ (struct DTFS_fx *) TARGETCW_FX : Target prototype in Cartesian domain */ +/* (Word16) lag_fx: length of prototype in time domain */ +/* (Word16 []) a/b: harmonics, normalized */ +/* (Word16) Q: norm factor of a */ +/*---------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16[]) lasterbE_fx: ERB history for differential */ +/* quantization, Q13 */ +/* _ (Word16) lastLgainE_fx: low band power history, log domain, */ +/* Q11 */ +/* _ (Word16) lastHgainE_fx: high band power history, log domain, */ +/* Q11 */ +/*---------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word16) returnFlag: flag indicating success/failure */ +/* (TRUE/FALSE) */ +/*---------------------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*=======================================================================================*/ + +Word16 ppp_quarter_encoder_fx( + DTFS_STRUCTURE_FX *CURRCW_Q_FX, /* o : Quantized (amp/phase) DTFS */ + DTFS_STRUCTURE_FX *TARGETCW_FX, /* o : DTFS with quant phase but unquant Amp */ + Word16 prevCW_lag, /* i : previous lag */ + DTFS_STRUCTURE_FX vCURRCW_NQ_FX, /* i : Unquantized DTFS */ + const Word16 *curr_lpc_fx, /* i : LPCS */ + Word16 *lastLgainE_fx, /* i/o: last low band gain */ + Word16 *lastHgainE_fx, /* i/o: last high band gain */ + Word16 *lasterbE_fx, /* i/o: last ERB vector */ + DTFS_STRUCTURE_FX PREV_CW_E_FX, /* i : past DTFS */ + Word16 *S_fx, /* i : sin table, Q15 */ + Word16 *C_fx, /* i : cos table, Q15 */ + Encoder_State_fx *st_fx +) +{ + DTFS_STRUCTURE_FX *PREVDTFS_FX = DTFS_new_fx(); + Word16 tmp_fx, temp_pl_fx, temp_l_fx; + Word16 temp; + Word16 l; + Word16 returnFlag = 1; + Word16 POWER_IDX_FX; /* Codebook index for the power quantization for PPP */ + Word16 AMP_IDX_fx[2]; /* Codebook index for the Amplitude quantization for PPP */ + Word16 Erot_fx = 0; + /* Word16 S_fx[PIT_MAX*4+1], C_fx[PIT_MAX*4+1];*/ + Word32 Ltempd,Ltempn; + Word32 L_tmp, L_tmp1; + Word16 tmp, exp; + DTFS_copy_fx( CURRCW_Q_FX, vCURRCW_NQ_FX ); + DTFS_copy_fx( PREVDTFS_FX, PREV_CW_E_FX ); + + l = CURRCW_Q_FX->lag_fx; + move16(); + temp_l_fx = CURRCW_Q_FX->lag_fx; + move16(); + temp_pl_fx = prevCW_lag; + move16(); + + DTFS_adjustLag_fx( PREVDTFS_FX, l ); + + + /* z = ((L_FRAME-temp_l)*(temp_l+temp_pl))/(2*temp_l*temp_pl); */ + /* Erot = (float) (temp_l - rint_new(temp_l*(z - floor(z)))); */ + temp = sub(L_FRAME,temp_l_fx); /*Q0 */ + exp = norm_s(temp_pl_fx); + tmp = div_s(shl(1,sub(14,exp)),temp_pl_fx); /*Q(29-exp) */ + L_tmp = L_mult(temp,tmp); /*Q(31-exp); +1 due to /2 */ + L_tmp = L_shl(L_tmp,sub(exp,15)); /*Q16 */ + + exp = norm_s(temp_l_fx); + tmp = div_s(shl(1,sub(14,exp)),temp_l_fx); /*Q(29-exp) */ + L_tmp1 = L_mult(temp,tmp); /*Q(31-exp); +1 due to /2 */ + L_tmp1 = L_shl(L_tmp1,sub(exp,15)); /*Q16 */ + + L_tmp = L_add(L_tmp,L_tmp1); /*Q16 */ + + tmp = lshr(extract_l(L_tmp),1); /*Q15 */ + L_tmp = L_mult(temp_l_fx,tmp); /*Q16 */ + temp = rint_new_fx(L_tmp); + Erot_fx = sub(temp_l_fx,temp); /*Q0 */ + + GetSinCosTab_fx(CURRCW_Q_FX->lag_fx,S_fx,C_fx);/*get cos and sin tables for lag */ + Q2phaseShift_fx(PREVDTFS_FX,shl(Erot_fx,2),CURRCW_Q_FX->lag_fx,S_fx,C_fx); + + DTFS_copy_fx(TARGETCW_FX,*CURRCW_Q_FX); + /* Amplitude Quantization */ + DTFS_car2pol_fx(CURRCW_Q_FX); /* at this point currCW_q=curr_nq */ + + /*As the upper cut of freqencies are normalized to 12800, we have to multiply upper cut off freq by + 2.56(1/12800 in Q15) */ + Ltempn = L_mult(CURRCW_Q_FX->upper_cut_off_freq_fx,10486);/* Q0+Q27 = Q28 */ + CURRCW_Q_FX->upper_cut_off_freq_fx = (Word16)L_shr(Ltempn,13);/*Q15 */ + Ltempn = L_mult(CURRCW_Q_FX->upper_cut_off_freq_of_interest_fx,10486);/* Q0+Q27 = Q28 */ + CURRCW_Q_FX->upper_cut_off_freq_of_interest_fx = (Word16)L_shr(Ltempn,13);/*Q15 */ + + returnFlag = DTFS_quant_cw_fx(CURRCW_Q_FX,prevCW_lag,curr_lpc_fx,&POWER_IDX_FX, + AMP_IDX_fx,lastLgainE_fx,lastHgainE_fx,lasterbE_fx,S_fx,C_fx); + move16(); + + /*De-normalize cut off frequencies */ + Ltempn = L_shl((Word32)CURRCW_Q_FX->upper_cut_off_freq_fx,13);/*Q28 */ + CURRCW_Q_FX->upper_cut_off_freq_fx = (Word16)find_remd(Ltempn, 20971,&Ltempd); + move16(); + Ltempn = L_shl((Word32)CURRCW_Q_FX->upper_cut_off_freq_of_interest_fx,13);/*Q28 */ + CURRCW_Q_FX->upper_cut_off_freq_of_interest_fx = (Word16)find_remd(Ltempn, 20971,&Ltempd); + + push_indice_fx( st_fx, IND_AMP0, AMP_IDX_fx[0], 6 ); + push_indice_fx( st_fx, IND_AMP1, AMP_IDX_fx[1], 6 ); + push_indice_fx( st_fx, IND_POWER, POWER_IDX_FX, 6); + + /*Phase copying is done through copy_phase instead of car2pol and pol2car */ + copy_phase_fx(TARGETCW_FX,*CURRCW_Q_FX,TARGETCW_FX); + /*Phase copying is done through copy_phase instead of car2pol and pol2car */ + copy_phase_fx(PREVDTFS_FX,*CURRCW_Q_FX,CURRCW_Q_FX); + /* Copying phase spectrum over */ + /*mvr2r(PREVDTFS->b, CURRCW_Q->b, (short)(CURRCW_Q->lag>>1)+1 ); */ + + /*DTFS_pol2car(CURRCW_Q); */ + /*DTFS_pol2car(TARGETCW); */ + + tmp_fx = DTFS_alignment_fine_new_fx(*TARGETCW_FX,*CURRCW_Q_FX,S_fx,C_fx); + move16(); + + test(); + IF (GT_16(add(tmp_fx,12),28)||LT_16(tmp_fx,-12)) + { + tmp_fx = 0; + move16(); + returnFlag = 0; + move16(); + } + + /*DTFS_phaseShift( CURRCW_Q,(float)(PI2*tmp/CURRCW_Q->lag) ); */ + Q2phaseShift_fx(CURRCW_Q_FX,tmp_fx,CURRCW_Q_FX->lag_fx,S_fx,C_fx); + + push_indice_fx( st_fx, IND_GLOBAL_ALIGNMENT, shr(add(tmp_fx,12),2), 3 ); + + free(PREVDTFS_FX); + return returnFlag; +} + +/*-------------------------------------------------------------------* +* set_ppp_mode_fx() + * + * Determine if the current frame should be coded by PPP or not + * Impose PPP - CELP - CELP pattern + *-------------------------------------------------------------------*/ +void set_ppp_mode_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + Word16 *coder_type /* i : coding type */ + ,const Word16 noisy_speech_HO, /* i : SC-VBR noisy speech HO flag */ + const Word16 clean_speech_HO, /* i : SC-VBR clean speech HO flag */ + const Word16 NB_speech_HO, /* i : SC-VBR NB speech HO flag */ + const Word16 localVAD, + const Word16 localVAD_he, /* i : HE-SAD flag without hangover */ + Word16 *vad_flag + ,Word16 T_op_fx[] /* i : open loop pitch lag */ + ,Word16 sp_aud_decision1 /* i : Speech Audio Decision */ +) +{ + + test(); + test(); + test(); + test(); + test(); + + IF ( EQ_16( *vad_flag, 1)&& + ( EQ_16( noisy_speech_HO , 1 ) || EQ_16( clean_speech_HO, 1 ) || EQ_16( NB_speech_HO, 1) ) && + ( localVAD == 0 || localVAD_he == 0 ) ) + + { + *coder_type = UNVOICED; + move16(); + } + + test(); + test(); + IF ( EQ_16( *coder_type , INACTIVE )&&(*vad_flag==0)&&EQ_16(st_fx->last_nelp_mode_fx,1)) /* avoid HO frame go to GSC */ + { + *coder_type = UNVOICED; + move16(); + } + + + /* force the coder to NELP mode during the first five frames */ + /* this will indicate the decoder that the coder is operating in the VBR mode */ + IF ( LT_16( st_fx->ini_frame_fx, 5)) + { + *coder_type = UNVOICED; + move16(); + *vad_flag = 1; + move16(); + } + /* Pattern PPP-CELP-CELP (pppcountE holds number of consecutive PPP frames) */ + test(); + IF ( NE_16( *coder_type, VOICED )||EQ_16(st_fx->last_coder_type_fx,TRANSITION)) + { + /* ensure no transient to PPP transition */ + st_fx->pppcountE_fx = 0; + move16(); + } + ELSE + { + /* current mode is voiced */ + st_fx->pppcountE_fx = add( st_fx->pppcountE_fx, 1); + test(); + test(); + test(); + test(); + IF ( ( EQ_16( st_fx->pppcountE_fx, 1 )&&NE_16(st_fx->last_last_ppp_mode_fx,1)&&st_fx->rate_control_fx==0)|| + ( EQ_16( st_fx->pppcountE_fx, 1 ) && st_fx->mode_QQF_fx != 0) ) + { + st_fx->ppp_mode_fx = 1; + move16(); + st_fx->core_brate_fx = PPP_NELP_2k80; + move32(); + } + ELSE IF ( EQ_16(st_fx->pppcountE_fx, 2 )) + { + test(); + IF ( st_fx->last_ppp_mode_fx != 0 && st_fx->mode_QQF_fx == 0 ) + { + /* QFF mode */ + st_fx->ppp_mode_fx = 0; + move16(); + } + ELSE + { + /* QQF Mode */ + st_fx->ppp_mode_fx = 1; + move16(); + st_fx->core_brate_fx = PPP_NELP_2k80; + move32(); + } + } + ELSE + { + st_fx->ppp_mode_fx = 0; + move16(); + st_fx->pppcountE_fx = 0; + move16(); + } + } + + + test(); + IF ( st_fx->ppp_mode_fx == 0 && EQ_16( st_fx->set_ppp_generic_fx, 1)) + { + st_fx->set_ppp_generic_fx = 0; + move16(); + *coder_type = GENERIC; + move16(); + } + + IF ( st_fx->last_core_fx == HQ_CORE ) + { + st_fx->ppp_mode_fx = 0; + move16(); + st_fx->set_ppp_generic_fx = 0; + move16(); + *coder_type = TRANSITION; + move16(); + } + + test(); + test(); + test(); + test(); + IF ( (st_fx->last_ppp_mode_fx != 0 ) && ( st_fx->ppp_mode_fx == 0 ) && ( sp_aud_decision1 != 0) + && EQ_16(st_fx->bwidth_fx, NB)&&st_fx->Opt_SC_VBR_fx!=0) /*if it were about to go from ppp->HQ*/ + { + st_fx->avoid_HQ_VBR_NB = 1; + move16(); + *coder_type = GENERIC; + move16(); + } + + test(); + test(); + test(); + IF ( (st_fx->last_nelp_mode_fx != 0) && ( sp_aud_decision1 != 0) && EQ_16( st_fx->bwidth_fx, NB)&&(st_fx->Opt_SC_VBR_fx!=0)) /*if it were about to go from nelp->HQ*/ + { + st_fx->avoid_HQ_VBR_NB = 1; + move16(); + *coder_type = GENERIC; + move16(); + } + + + test(); + test(); + test(); + IF( ( GT_16(st_fx->old_pitch_buf_fx[(2*NB_SUBFR)-1], PPP_LAG_THRLD_Q6)|| + GT_16(T_op_fx[1], PPP_LAG_THRLD) || !st_fx->last_Opt_SC_VBR_fx ) && + EQ_16(st_fx->ppp_mode_fx,1) ) + { + st_fx->ppp_mode_fx=0; + move16(); + st_fx->core_brate_fx = ACELP_7k20; + move32(); + } + + + return; +} diff --git a/lib_enc/pre_proc_fx.c b/lib_enc/pre_proc_fx.c new file mode 100644 index 0000000..23802e5 --- /dev/null +++ b/lib_enc/pre_proc_fx.c @@ -0,0 +1,1281 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" +#include "cnst_fx.h" +#include "rom_com_fx.h" +#include "prot_fx.h" +#include "stl.h" + +/*-------------------------------------------------------------------* + * pre_proc() + * + * Pre-processing (spectral analysis, LP analysis, VAD, + * OL pitch calculation, coder mode selection, ...) + *--------------------------------------------------------------------*/ + +void pre_proc_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 input_frame, /* i : frame length */ + const Word16 signal_in[], /* i : new samples */ + Word16 old_inp_12k8[], /* i/o: buffer of old input signal */ + Word16 old_inp_16k[], /* i/o: buffer of old input signal @ 16kHz */ + Word16 **inp, /* o : ptr. to inp. signal in the current frame */ + Word16 *sp_aud_decision1, /* o : 1st stage speech/music classification */ + Word16 *sp_aud_decision2, /* o : 2nd stage speech/music classification */ + Word32 fr_bands[2*NB_BANDS], /* o : energy in frequency bands */ + Word16 *vad_flag, + Word16 *localVAD, + Word16 *Etot, /* o : total energy */ + Word32 *ener, /* o : residual energy from Levinson-Durbin */ + Word16 pitch[3], /* o : open-loop pitch values for quantiz. */ + Word16 voicing[3], /* o : OL maximum normalized correlation */ + Word16 A[NB_SUBFR16k*(M+1)], /* o : A(z) unquantized for the 4 subframes */ + Word16 Aw[NB_SUBFR16k*(M+1)], /* o : weighted A(z) unquantized for subframes */ + Word16 epsP_h[M+1], /* o : LP prediction errors */ + Word16 epsP_l[M+1], /* o : LP prediction errors */ + Word32 epsP[M+1], /* o : LP prediction errors */ + Word16 lsp_new[M], /* o : LSPs at the end of the frame */ + Word16 lsp_mid[M], /* o : LSPs in the middle of the frame */ + Word16 *coder_type, /* o : coder type */ + Word16 *sharpFlag, /* o : formant sharpening flag */ + Word16 *vad_hover_flag, + Word16 *attack_flag, /* o : flag signalling attack encoded by AC mode (GSC) */ + Word16 *new_inp_resamp16k, /* o : new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ + Word16 *Voicing_flag, /* o : voicing flag for HQ FEC */ + + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : cldfb real buffer */ + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o : cldfb imag buffer */ + CLDFB_SCALE_FACTOR *cldfbScale, /* o : cldfb scale*/ + Word16 *old_exc, + Word16 *hq_core_type, /* o : HQ core type */ + Word16 *Q_new, + Word16 *shift, + Word16 *Q_r +) +{ + Word16 delay; + Word16 i; + Word16 *inp_12k8, *new_inp_12k8, *inp_16k, *new_inp_16k; /* pointers to current frame and new data */ + Word16 old_wsp[L_WSP], *wsp; /* weighted input signal buffer */ + Word16 pitch_fr[NB_SUBFR]; /* fractional pitch values */ + Word16 voicing_fr[NB_SUBFR]; /* fractional pitch gains */ + Word32 lf_E[2*VOIC_BINS]; /* per bin spectrum energy in lf */ + Word32 tmpN[NB_BANDS]; /* Temporary noise update */ + Word32 tmpE[NB_BANDS]; /* Temporary averaged energy of 2 sf. */ + Word32 ee[2]; /* Spectral tilt */ + Word16 corr_shift; /* correlation shift */ + Word16 relE; /* frame relative energy */ + Word16 loc_harm; /* harmonicity flag */ + Word16 cor_map_sum, sp_div; /* speech/music clasif. parameters */ + Word32 PS[128]; + Word16 L_look; /* length of look-ahead */ + + Word16 Q_sp_div, Q_esp; + Word16 localVAD_HE_SAD; /* HE SAD parameters */ + Word16 snr_sum_he; /* HE SAD parameters */ + + Word16 vad_flag_cldfb; + + Word16 vad_flag_dtx; + Word16 old_cor; + Word16 uc_clas; + Word32 hp_E[2]; /* Energy in HF */ + Word16 noisy_speech_HO, clean_speech_HO, NB_speech_HO; /* SC-VBR HO flags */ + Word16 non_staX; /* unbound non-stationarity for sp/mus clas. */ + Word32 sr_core_tmp; + Word16 L_frame_tmp; + Word16 Q_exp, Q_wsp_exp, Q_new_16k; + Word16 shift_exp; + Word16 Scale_fac[2]; + Word32 Le_min_scaled; + Word16 excitation_max_test; + Word16 lsf_new[M], stab_fac; + Word32 enerBuffer[CLDFB_NO_CHANNELS_MAX]; + Word16 enerBuffer_exp; /*[CLDFB_NO_CHANNELS_MAX];*/ + Word16 realBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word16 imagBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word16 tmp_e; + Word16 currFlatness; + Word16 high_lpn_flag; + Word16 alw_pitch_lag_12k8[2]; + Word16 alw_voicing[2]; + Word16 flag_spitch; + Word16 sf_energySum[CLDFB_NO_CHANNELS_MAX]; + Word32 L_tmp; + UWord16 lsb; + Word16 fft_buff[2*L_FFT]; + Word16 sp_floor; + Word16 freqTable[2] = {20, 40}; + Word16 sp_aud_decision0; + Word16 last_core_orig; + Word16 headroom; + Word16 cldfb_addition = 0; move16(); + Word16 old_pitch1; + + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + vad_flag_dtx = 0; + move16(); + localVAD_HE_SAD = 0; + move16(); + NB_speech_HO = 0; + move16(); + clean_speech_HO = 0; + move16(); + noisy_speech_HO = 0; + move16(); + snr_sum_he = 0; + move16(); + currFlatness = 0; + move16(); + + Q_new_16k = 0; + move16(); + + *vad_hover_flag = 0; + move16(); + uc_clas = VOICED_CLAS; + move16(); + *sp_aud_decision1 = 0; + move16(); + *sp_aud_decision2 = 0; + move16(); + *coder_type = GENERIC; + move16(); + st->noise_lev_fx = NOISE_LEVEL_SP0; + move16(); + *attack_flag = 0; + move16(); + + st->bump_up_fx = 0; + move16(); + st->ppp_mode_fx = 0; + move16(); + st->nelp_mode_fx = 0; + move16(); + st->avoid_HQ_VBR_NB = 0; + move16(); + + L_look = L_LOOK_12k8; + move16(); /* lookahead at 12.8kHz */ + + new_inp_12k8 = old_inp_12k8 + L_INP_MEM; /* pointer to new samples of the input signal in 12.8kHz core */ + inp_12k8 = new_inp_12k8 - L_look; /* pointer to the current frame of input signal in 12.8kHz core */ + Copy( st->old_inp_12k8_fx, old_inp_12k8, L_INP_MEM ); + + Copy( st->old_wsp_fx, old_wsp, L_WSP_MEM ); + wsp = old_wsp + L_WSP_MEM; /* pointer to the current frame of weighted signal in 12.8kHz core */ + + old_cor = st->old_corr_fx; + move16(); /* save old_cor for speech/music classifier */ + + st->rf_mode = st->Opt_RF_ON; + move16(); + + last_core_orig = st->last_core_fx; + move16(); + + /*--------------------------------------------------------------* + * Cldfb analysis + *---------------------------------------------------------------*/ + + move32(); + move16(); + st->prevEnergyHF_fx = st->currEnergyHF_fx; + tmp_e = st->currEnergyHF_e_fx; + + analysisCldfbEncoder_fx( st, signal_in, realBuffer, imagBuffer, realBuffer16, imagBuffer16, enerBuffer, &enerBuffer_exp, cldfbScale); + cldfbScale->hb_scale = cldfbScale->lb_scale; + + /*----------------------------------------------------------------* + * Change the sampling frequency to 12.8 kHz + *----------------------------------------------------------------*/ + + modify_Fs_fx( signal_in, input_frame, st->input_Fs_fx, new_inp_12k8, 12800, st->mem_decim_fx, (const Word16)(EQ_16(st->max_bwidth_fx,NB))); + Copy( new_inp_12k8, st->buf_speech_enc+L_FRAME32k, L_FRAME ); + Scale_sig( st->buf_speech_enc+L_FRAME32k, L_FRAME, 1 ); + /*------------------------------------------------------------------* + * Perform fixed preemphasis (12.8 kHz signal) through 1 - g*z^-1 + *-----------------------------------------------------------------*/ + + /* rf_mode: first time Q_new is computed here inside Preemph_scaled() for primary copy + these are the same memories used in partial frame assembly as well */ + + headroom = 1; + move16(); + test(); + test(); + /* reserve an extra bit of headroom in case of NB coding and if there is a chance of energy above 4 kHz */ + /* st->bwidth_fx refers to the coded bandwidth of the previous frame */ + if( ((EQ_16(st->bwidth_fx, NB))||(EQ_16(st->max_bwidth_fx,NB)))&&(GT_32(st->input_Fs_fx,8000))) + { + headroom = add(headroom, 1); + } + Preemph_scaled( new_inp_12k8, Q_new, &st->mem_preemph_fx, st->Q_max, + PREEMPH_FAC, 0, headroom, L_Q_MEM, L_FRAME, st->last_coder_type_fx, 1 ); + + Q_exp = sub(*Q_new, st->Q_old); + st->prev_Q_old=st->Q_old; + move16(); + st->Q_old = *Q_new; + move16(); + + /*------------------------------------------------------------------* + * Scaling of memories + *-----------------------------------------------------------------*/ + + Le_min_scaled = Scale_mem_pre_proc( st->ini_frame_fx, Q_exp, Q_new, old_inp_12k8, &(st->mem_wsp_fx), st->enrO_fx, st->bckr_fx, + st->ave_enr_fx, st->ave_enr2_fx, st->fr_bands1_fx, st->fr_bands2_fx, st->Bin_E_old_fx ); + + /*-------------------------------------------------------------------------* + * Spectral analysis + *--------------------------------------------------------------------------*/ + + analy_sp( inp_12k8, *Q_new, fr_bands, lf_E, Etot, st->min_band_fx, st->max_band_fx, Le_min_scaled, Scale_fac, st->Bin_E_fx, st->Bin_E_old_fx, + PS, st->lgBin_E_fx, st->band_energies, fft_buff ); + + st->band_energies_exp = sub(sub(WORD32_BITS-1,*Q_new),QSCALE); + move16(); + + /*----------------------------------------------------------------* + * SAD (1-signal, 0-noise) + *----------------------------------------------------------------*/ + + noise_est_pre_fx( *Etot, st->ini_frame_fx, &st->Etot_l_fx, &st->Etot_h_fx, &st->Etot_l_lp_fx, &st->Etot_last_fx, + &st->Etot_v_h2_fx, &st->sign_dyn_lp_fx, st->harm_cor_cnt_fx, &st->Etot_lp_fx ); + + *vad_flag = wb_vad_fx( st, fr_bands, localVAD, &noisy_speech_HO, &clean_speech_HO, &NB_speech_HO, + &snr_sum_he, &localVAD_HE_SAD, &(st->flag_noisy_speech_snr), *Q_new ); + + vad_flag_cldfb = vad_proc( &(st->vad_st),realBuffer, imagBuffer, cldfbScale->lb_scale, &cldfb_addition, + enerBuffer, enerBuffer_exp,st->cldfbAna_Fx->no_channels, *vad_flag ); + + + IF ( LT_16( st->Pos_relE_cnt, 20) ) /* Ensure the level is high enough and cldfb decision is reliable */ + { + /* Combine decisions from SADS */ + test(); + IF (*vad_flag != 0 && vad_flag_cldfb == 0) + { + *localVAD = 0; + move16(); + } + + *vad_flag = vad_flag_cldfb; + move16(); + } + + /* apply DTX hangover for CNG analysis */ + vad_flag_dtx = dtx_hangover_addition_fx( st, *localVAD, *vad_flag, sub(st->lp_speech_fx,st->lp_noise_fx), cldfb_addition, vad_hover_flag ); + + /*----------------------------------------------------------------* + * NB/WB/SWB/FB bandwidth detector + *----------------------------------------------------------------*/ + + FOR( i=0; i< CLDFB_NO_CHANNELS_MAX; i++ ) + { + sf_energySum[i] = enerBuffer_exp; + move16(); + } + + bw_detect_fx( st, signal_in, *localVAD, enerBuffer, sf_energySum ); + + /*----------------------------------------------------------------* + * Noise energy down-ward update and total noise energy estimation + * Long-term energies and relative frame energy updates + * Correlation correction as a function of total noise level + *----------------------------------------------------------------*/ + + noise_est_down_fx( fr_bands, st->bckr_fx, tmpN, tmpE, st->min_band_fx, st->max_band_fx, &st->totalNoise_fx, + *Etot, &st->Etot_last_fx, &st->Etot_v_h2_fx, *Q_new , Le_min_scaled ); + + relE = sub(*Etot, st->lp_speech_fx); /* Q8 */ /* relE = *Etot - st->lp_speech;*/ + + test(); + IF ( GT_16(relE, 384) ) /*relE > 1.5 */ + { + st->Pos_relE_cnt = 0; + move16(); + } + ELSE IF (relE < 0 && *vad_flag == 1) + { + st->Pos_relE_cnt = add(st->Pos_relE_cnt, 1); + } + + corr_shift = correlation_shift_fx( st->totalNoise_fx ); + + /*----------------------------------------------------------------* + * FD-CNG Noise Estimator + *----------------------------------------------------------------*/ + + resetFdCngEnc ( st ); + perform_noise_estimation_enc ( st->band_energies, st->band_energies_exp, enerBuffer, enerBuffer_exp, st->hFdCngEnc_fx ); + + /*-----------------------------------------------------------------* + * Select SID or FRAME_NO_DATA frame if DTX enabled + *-----------------------------------------------------------------*/ + + dtx_fx(st, vad_flag_dtx, inp_12k8, *Q_new); + + /*----------------------------------------------------------------* + * Adjust FD-CNG Noise Estimator + *----------------------------------------------------------------*/ + test(); + IF( (NE_32(st->last_total_brate_fx,st->total_brate_fx))||(NE_16(st->last_bwidth_fx,st->bwidth_fx))) + { + L_tmp = st->total_brate_fx; + move32(); + test(); + if( st->rf_mode && EQ_32(st->total_brate_fx,ACELP_13k20)) + { + L_tmp = ACELP_9k60; + move32(); + } + configureFdCngEnc( st->hFdCngEnc_fx, st->bwidth_fx, L_tmp ); + } + test(); + IF ( st->hFdCngEnc_fx!=NULL && st->Opt_DTX_ON_fx ) + { + AdjustFirstSID( st->hFdCngEnc_fx->hFdCngCom->npart, st->hFdCngEnc_fx->msPeriodog, st->hFdCngEnc_fx->msPeriodog_exp, st->hFdCngEnc_fx->energy_ho, + &st->hFdCngEnc_fx->energy_ho_exp,st->hFdCngEnc_fx->msNoiseEst, &st->hFdCngEnc_fx->msNoiseEst_exp, st->hFdCngEnc_fx->msNoiseEst_old, + &st->hFdCngEnc_fx->msNoiseEst_old_exp, &(st->hFdCngEnc_fx->hFdCngCom->active_frame_counter), st ); + } + + /*----------------------------------------------------------------* + * Reconfigure MODE2 + *----------------------------------------------------------------*/ + + IF ( EQ_16(st->codec_mode,MODE2)) + { + SetModeIndex( st, st->total_brate_fx, st->bwidth_fx, *shift); + } + + calcLoEnvCheckCorrHiLo_Fix( st->cldfbAna_Fx->no_col, freqTable, (st->tecEnc).loBuffer, (st->tecEnc).loTempEnv, + (st->tecEnc).loTempEnv_ns, (st->tecEnc).hiTempEnv, &((st->tecEnc).corrFlag) ); + + /*---------------------------------------------------------------* + * Time-domain transient detector + *---------------------------------------------------------------*/ + + /* Adjust prevEnergyHF and currEnergyHF to same exponent */ + i = sub(st->currEnergyHF_e_fx, tmp_e); + + /* If i > 0: currEnergyHF is higher => shr prevEnergyHF, exponent remains as is */ + st->prevEnergyHF_fx = L_shr(st->prevEnergyHF_fx, s_max(0, i)); + move32(); + + /* If i < 0: currEnergyHF is lower => shr currEnergyHF, exponent changes to previous */ + st->currEnergyHF_fx = L_shl(st->currEnergyHF_fx, s_min(0, i)); + move32(); + + if ( i < 0 ) + { + st->currEnergyHF_e_fx = tmp_e; + move16(); + } + + test(); + IF( st->tcx10Enabled || st->tcx20Enabled ) + { + RunTransientDetection( signal_in, input_frame, &st->transientDetection); + currFlatness = GetTCXAvgTemporalFlatnessMeasure( &st->transientDetection, NSUBBLOCKS, 0 ); + } + + /*----------------------------------------------------------------* + * LP analysis + *----------------------------------------------------------------*/ + + alw_pitch_lag_12k8[0] = st->old_pitch_la; + move16(); + alw_pitch_lag_12k8[1] = st->old_pitch_la; + move16(); + alw_voicing[0] = st->old_voicing_la; + move16(); + alw_voicing[1] = st->old_voicing_la; + move16(); + + analy_lp_fx( inp_12k8, L_FRAME, L_look, ener, A, epsP_h, epsP_l, lsp_new, lsp_mid, st->lsp_old1_fx, alw_pitch_lag_12k8, alw_voicing, 12800, *Q_new, Q_r ); + + lsp2lsf_fx( lsp_new, lsf_new, M, INT_FS_FX ); + stab_fac = lsf_stab_fx( lsf_new, st->lsf_old1_fx, 0, L_FRAME ); + Copy( lsf_new, st->lsf_old1_fx, M ); + + /*----------------------------------------------------------------* + * Compute weighted input (for OL pitch analysis) + * OL pitch analysis + * 1/4 pitch precision improvement + *----------------------------------------------------------------*/ + + find_wsp( A, inp_12k8, wsp, &st->mem_wsp_fx, TILT_FAC_FX, L_FRAME, L_look, L_SUBFR, Aw, GAMMA1, NB_SUBFR ); + + Q_wsp_exp = Q_exp; + move16(); + Scale_wsp( wsp, &(st->old_wsp_max), shift, &Q_wsp_exp, &(st->old_wsp_shift), st->old_wsp2_fx, + st->mem_decim2_fx, old_wsp, add(L_FRAME, L_look) ); + shift_exp=sub(Q_wsp_exp, Q_exp); + + IF( *vad_flag == 0 ) + { + /* reset the OL pitch tracker memories during inactive frames */ + pitch_ol_init_fx( &st->old_thres_fx, &st->old_pitch, &st->delta_pit_fx, &st->old_corr_fx) ; + } + + pitch_ol_fx( pitch, voicing, &st->old_pitch, &st->old_corr_fx, corr_shift, &st->old_thres_fx, + &st->delta_pit_fx, st->old_wsp2_fx, wsp, st->mem_decim2_fx, relE, st->clas_fx, st->bwidth_fx, st->Opt_SC_VBR_fx ); + + /* Updates for adaptive lag window memory */ + st->old_pitch_la = pitch[2]; + move16(); + st->old_voicing_la = voicing[2]; + move16(); + + /* Detection of very short stable pitch period (MODE1 bit-rates) */ + StableHighPitchDetect_fx( &flag_spitch, pitch, voicing, wsp, *localVAD, &st->voicing_sm_fx, &st->voicing0_sm_fx, + &st->LF_EnergyRatio_sm_fx, &st->predecision_flag_fx, &st->diff_sm_fx, &st->energy_sm_fx,*Q_new,st->lgBin_E_fx); + + /* 1/4 pitch precision improvement */ + IF( LE_32(st->total_brate_fx,ACELP_24k40)) + { + /* 1/4 pitch precision improvement */ + pitch_ol2_fx( PIT_MIN_EXTEND, pitch[0], &pitch_fr[0], &voicing_fr[0], 0, wsp, 7 ); + pitch_ol2_fx( PIT_MIN_EXTEND, pitch[0], &pitch_fr[1], &voicing_fr[1], L_SUBFR, wsp, 7 ); + pitch_ol2_fx( PIT_MIN_EXTEND, pitch[1], &pitch_fr[2], &voicing_fr[2], 2*L_SUBFR, wsp, 7 ); + pitch_ol2_fx( PIT_MIN_EXTEND, pitch[1], &pitch_fr[3], &voicing_fr[3], 3*L_SUBFR, wsp, 7 ); + } + ELSE + { + pitch_fr[0] = pitch[0]; + move16(); + pitch_fr[1] = pitch[0]; + move16(); + pitch_fr[2] = pitch[1]; + move16(); + pitch_fr[3] = pitch[1]; + move16(); + + voicing_fr[0] = voicing[0]; + move16(); + voicing_fr[1] = voicing[0]; + move16(); + voicing_fr[2] = voicing[1]; + move16(); + voicing_fr[3] = voicing[1]; + move16(); + } + + old_pitch1 = st->pitO_fx; + move16(); + + /*------------------------------------------------------------------* + * Update estimated noise energy and voicing cut-off frequency + *-----------------------------------------------------------------*/ + + noise_est_fx( st, tmpN, pitch, voicing, epsP_h,epsP_l, *Etot, relE, corr_shift, tmpE, fr_bands, &cor_map_sum, + &sp_div, &Q_sp_div, &non_staX , &loc_harm, lf_E, &st->harm_cor_cnt_fx ,st->Etot_l_lp_fx, + st->Etot_v_h2_fx ,&st->bg_cnt_fx, st->lgBin_E_fx,*Q_new, Le_min_scaled, &sp_floor ); + + /*------------------------------------------------------------------* + * Update parameters used in the VAD and DTX + *-----------------------------------------------------------------*/ + + vad_param_updt_fx( st, pitch, voicing, old_pitch1, corr_shift, *vad_flag, A ); + + /*-----------------------------------------------------------------* + * Find spectral tilt + * UC and VC frame selection + *-----------------------------------------------------------------*/ + + find_tilt_fx( fr_bands, st->bckr_fx, ee, pitch, voicing, lf_E, corr_shift, st->input_bwidth_fx, + st->max_band_fx, hp_E, st->codec_mode, *Q_new, &(st->bckr_tilt_lt), st->Opt_SC_VBR_fx ); + + *coder_type = find_uv_fx( st, pitch_fr, voicing_fr, voicing, inp_12k8, *localVAD, ee, corr_shift, + relE, *Etot, hp_E, *Q_new, &flag_spitch, st->voicing_sm_fx, *shift, last_core_orig ); + + /*----------------------------------------------------------------* + * channel aware mode configuration * + *-----------------------------------------------------------------*/ + test(); + test(); + test(); + IF( !st->Opt_RF_ON) + { + st->rf_mode = 0; + st->rf_target_bits_write = 0; + } + ELSE IF( st->rf_mode && NE_32(st->core_brate_fx,FRAME_NO_DATA)&&NE_32(st->core_brate_fx,SID_2k40)) + { + /* the RF config is for (n- fec_offset)th frame that will be packed along with the n-th frame bistream */ + st->rf_mode = 1; + st->codec_mode = MODE2; + + st->rf_target_bits_write = st->rf_targetbits_buff[st->rf_fec_offset]; + } + ELSE + { + st->rf_mode = 0; + st->codec_mode = MODE1; + st->rf_indx_frametype[0] = RF_NO_DATA; + st->rf_targetbits_buff[0] = 6; /* rf_mode: 1, rf_frame_type: 3, and fec_offset: 2 */ + } + + /*-----------------------------------------------------------------* + * Signal classification for FEC + * TC frame selection + *-----------------------------------------------------------------*/ + + st->clas_fx = signal_clas_fx( st, coder_type, voicing, inp_12k8, *localVAD, pitch, ee, relE, L_look, &uc_clas); + + st->Local_VAD = *localVAD; + + /*----------------------------------------------------------------* + * Speech/music classification + * AC frame selection + *----------------------------------------------------------------*/ + + FOR( i=0; iOpt_DTX_ON_fx ) + { + *vad_flag = vad_flag_dtx; + move16(); /* flag now with the DTX-HO for use in further high rate encoding below */ + } + + /*----------------------------------------------------------------* + * Selection of internal ACELP Fs (12.8 kHz or 16 kHz) + *----------------------------------------------------------------*/ + + IF( EQ_16(st->codec_mode,MODE1)) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_32(st->core_brate_fx,FRAME_NO_DATA)) + { + /* prevent "L_frame" changes in CNG segments */ + st->L_frame_fx = st->last_L_frame_fx; + move16(); + } + ELSE IF ( EQ_32(st->core_brate_fx,SID_2k40)&&GE_16(st->bwidth_fx,WB)&&st->first_CNG_fx&<_16(st->act_cnt2_fx,MIN_ACT_CNG_UPD)) + { + /* prevent "L_frame" changes in SID frame after short segment of active frames */ + st->L_frame_fx = st->last_CNG_L_frame_fx; + move16(); + } + ELSE IF ( ( EQ_32(st->core_brate_fx,SID_2k40)&&GE_32(st->total_brate_fx,ACELP_9k60)&&((EQ_16(st->bwidth_fx,WB)&&!(EQ_32(st->total_brate_fx,ACELP_13k20)&&EQ_16(st->cng_type_fx,FD_CNG)))||(EQ_16(st->cng_type_fx,LP_CNG)&>_16(st->bwidth_fx,WB)&&GE_32(st->total_brate_fx,ACELP_16k40))))|| + ( GT_32(st->total_brate_fx,ACELP_24k40) && LT_32(st->total_brate_fx,HQ_96k) ) || ( EQ_32(st->total_brate_fx,ACELP_24k40) && GE_16(st->bwidth_fx,WB) ) ) + { + st->L_frame_fx = L_FRAME16k; + move16(); + } + ELSE + { + st->L_frame_fx = L_FRAME; + move16(); + } + + if( st->ini_frame_fx == 0 ) + { + /* avoid switching of internal ACELP Fs in the very first frame */ + st->last_L_frame_fx = st->L_frame_fx; + move16(); + } + + IF( EQ_16(st->L_frame_fx,L_FRAME)) + { + st->gamma = GAMMA1; + move16(); + st->preemph_fac = PREEMPH_FAC; + move16(); + } + ELSE + { + st->gamma = GAMMA16k; + move16(); + st->preemph_fac = PREEMPH_FAC_16k; + move16(); + } + + st->sr_core = L_mult0(50,st->L_frame_fx); + st->encoderLookahead_enc = NS2SA_fx2(st->sr_core, ACELP_LOOK_NS); + move16(); + st->encoderPastSamples_enc = shr(imult1616(st->L_frame_fx, 9), 4); + } + + /*-----------------------------------------------------------------* + * coder_type rewriting in case of switching + * IC frames selection + * enforce TC frames in case of switching + *-----------------------------------------------------------------*/ + + IF( EQ_16(st->codec_mode,MODE1)) + { + /* enforce TRANSITION frames */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( NE_16(st->last_L_frame_fx,st->L_frame_fx)&&NE_32(st->core_brate_fx,FRAME_NO_DATA)&&NE_32(st->core_brate_fx,SID_2k40)&&(NE_16(st->coder_type_raw_fx,VOICED))) + { + /* enforce TC frame in case of ACELP@12k8 <-> ACELP@16k core switching */ + *coder_type = TRANSITION; + move16(); + } + ELSE IF( EQ_16(st->last_core_fx,HQ_CORE)||EQ_16(st->last_core_fx,TCX_10_CORE)||EQ_16(st->last_core_fx,TCX_20_CORE)) + { + /* enforce TC frame in case of HQ/TCX -> ACELP core switching */ + *coder_type = TRANSITION; + move16(); + } + ELSE IF( LE_32(st->last_core_brate_fx,SID_2k40)&&EQ_16(st->cng_type_fx,FD_CNG)) + { + /* enforce TC frame in case of FD_CNG -> ACELP switching (past excitation not available) */ + *coder_type = TRANSITION; + move16(); + } + + /* select INACTIVE frames */ + ELSE IF( LE_32(st->total_brate_fx,ACELP_24k40)&&*vad_flag==0) + { + /* inactive frames will be coded by GSC technology */ + /* except for the VBR mode. VBR mode uses NELP for that */ + test(); + IF ( !( EQ_16(st->Opt_SC_VBR_fx, 1)&&EQ_16(vad_flag_dtx,1))) + { + *coder_type = INACTIVE; + move16(); + st->noise_lev_fx = NOISE_LEVEL_SP3; + move16(); + } + } + ELSE IF( GT_32(st->total_brate_fx,ACELP_24k40)&& + ( (*vad_flag == 0 && GE_16(st->bwidth_fx,SWB) && GE_16(st->max_bwidth_fx,SWB) ) || (*localVAD == 0 && (LE_16(st->bwidth_fx,WB) || LE_16(st->max_bwidth_fx,WB))) ) + ) + { + /* inactive frames will be coded by AVQ technology */ + *coder_type = INACTIVE; + move16(); + } + } + ELSE + { + IF( !(*vad_flag) ) + { + *coder_type = INACTIVE; + move16(); + } + ELSE IF( GT_16(*coder_type,GENERIC)) + { + *coder_type = GENERIC; + move16(); + } + } + + /*---------------------------------------------------------------* + * SC-VBR - decision about PPP/NELP mode + *---------------------------------------------------------------*/ + + IF( st->Opt_SC_VBR_fx ) + { + set_ppp_mode_fx( st, coder_type, noisy_speech_HO, clean_speech_HO, NB_speech_HO, *localVAD, localVAD_HE_SAD, vad_flag, pitch, *sp_aud_decision1 ); + } + test(); + IF ( !st->Opt_AMR_WB_fx && !st->rf_mode ) + { + test(); + test(); + IF ( EQ_32(st->total_brate_fx,ACELP_13k20)||EQ_32(st->total_brate_fx,ACELP_32k)) + { + st->mdct_sw_enable = MODE1; + move16(); + } + ELSE IF ( LE_32(ACELP_16k40,st->total_brate_fx)&&LE_32(st->total_brate_fx,ACELP_24k40)) + { + st->mdct_sw_enable = MODE2; + move16(); + } + } + + IF( EQ_16(st->codec_mode,MODE1)) + { + /*---------------------------------------------------------------------* + * Decision matrix (selection of technologies) + *---------------------------------------------------------------------*/ + + decision_matrix_enc_fx( st, *sp_aud_decision1, *sp_aud_decision2, *coder_type, *vad_flag, hq_core_type ); + + /* HQ_CORE/TCX_20_CORE decision */ + IF ( EQ_16(st->core_fx,HQ_CORE)) /* Decision matrix decided for MDCT coding */ + { + test(); + test(); + IF( (EQ_16(st->bwidth_fx,SWB)||EQ_16(st->bwidth_fx,FB))&&EQ_32(st->total_brate_fx,32000)) + { + /* Select MDCT Core */ + st->core_fx = mdct_classifier_fx(fft_buff,st,*vad_flag, enerBuffer + ,sub(enerBuffer_exp, 31) + ); + } + test(); + IF( (EQ_32(st->total_brate_fx,13200))&&(NE_16(st->bwidth_fx,FB))) + { + MDCT_selector( st, sp_floor, *Etot, cor_map_sum, voicing, enerBuffer, enerBuffer_exp, *vad_flag ); + } + } + ELSE + { + MDCT_selector_reset( st ); + } + + /* Switch to MODE2 if TCX_20_CORE */ + IF( EQ_16(st->core_fx,TCX_20_CORE)) + { + st->codec_mode = MODE2; + move16(); + IF( EQ_16(st->last_codec_mode,MODE1)) + { + Word32 last_total_brate = L_add(st->last_total_brate_fx, 0); + st->last_total_brate_fx = -1; + move32(); + SetModeIndex( st, st->total_brate_fx, st->bwidth_fx, *shift ); + st->last_total_brate_fx = last_total_brate; + move32(); + } + ELSE + { + SetModeIndex( st, st->total_brate_fx, st->bwidth_fx, *shift); + st->sr_core = getCoreSamplerateMode2( st->total_brate_fx, st->bwidth_fx, st->rf_mode); + + Mpy_32_16_ss(st->sr_core, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + st->L_frame_fx = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + st->encoderLookahead_enc = NS2SA_fx2(st->sr_core, ACELP_LOOK_NS); + move16(); + st->encoderPastSamples_enc = shr(imult1616(st->L_frame_fx, 9), 4); + assert(st->L_frame_fx == st->sr_core / 50); + + IF ( EQ_32(st->sr_core,12800)) + { + st->preemph_fac = PREEMPH_FAC; + move16(); + st->gamma = GAMMA1; + move16(); + } + ELSE + { + st->preemph_fac = PREEMPH_FAC_16k; + move16(); + st->gamma = GAMMA16k; + move16(); + } + + st->igf = getIgfPresent(st->total_brate_fx, st->bwidth_fx, st->rf_mode); + } + + *coder_type = st->coder_type_raw_fx; + move16(); + + IF( *vad_flag == 0 ) + { + *coder_type = INACTIVE; + move16(); + } + ELSE IF( GT_16((*coder_type),GENERIC)) + { + *coder_type = GENERIC; + move16(); + } + + st->mdct_sw = MODE1; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Update of ACELP harmonicity counter (used in ACELP transform codebook @32kbps) + *-----------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + IF( EQ_32(st->total_brate_fx, ACELP_32k)&&EQ_16(loc_harm,1)&>_16(cor_map_sum,50<<8) + && EQ_16(st->clas_fx, VOICED_CLAS) && EQ_16(*coder_type,GENERIC) ) + { + st->last_harm_flag_acelp_fx = add(st->last_harm_flag_acelp_fx,1); + st->last_harm_flag_acelp_fx = s_min(st->last_harm_flag_acelp_fx,10); + } + ELSE + { + st->last_harm_flag_acelp_fx = 0; + move16(); + } + + /*-----------------------------------------------------------------* + * Update audio frames counter (used for UV decision) + *-----------------------------------------------------------------*/ + + IF( EQ_16(*coder_type,AUDIO)) + { + st->audio_frame_cnt_fx = add(st->audio_frame_cnt_fx,AUDIO_COUNTER_STEP); + } + ELSE IF (NE_16(*coder_type,INACTIVE)) + { + st->audio_frame_cnt_fx = sub(st->audio_frame_cnt_fx,1); + } + + st->audio_frame_cnt_fx = s_min(st->audio_frame_cnt_fx,AUDIO_COUNTER_MAX); + st->audio_frame_cnt_fx = s_max(st->audio_frame_cnt_fx,0); + + /*-----------------------------------------------------------------* + * Set formant sharpening flag + *-----------------------------------------------------------------*/ + + *sharpFlag = 0; + move16(); + IF( EQ_16(*coder_type,TRANSITION)) + { + test(); + test(); + test(); + test(); + test(); + IF( ( GT_32(st->total_brate_fx,ACELP_48k)&<_16(st->bwidth_fx,SWB))|| /* Deactivate for core bitrates higher than 48.0 kb/s */ + ( GE_32(st->total_brate_fx,ACELP_13k20) && LE_32(st->total_brate_fx,ACELP_16k40) ) || /* Deactivate for bitrates <13.2, 16.4> kb/s (this is basically due to lack of signaling configurations */ + ( GT_32(st->total_brate_fx,ACELP_16k40)&>_16(st->lp_noise_fx,FORMANT_SHARPENING_NOISE_THRESHOLD_FX))) /* Deactivate for bitrates >= 24.4 kb/s if the long-term noise level exceeds 34 dB */ + { + *sharpFlag= 0; + move16(); + } + ELSE + { + *sharpFlag= 1; + move16(); + } + } + + test(); + IF( EQ_16(*coder_type,GENERIC)||EQ_16(*coder_type,VOICED)) + { + test(); + test(); + test(); + test(); + test(); + IF( *vad_hover_flag || + ( GT_32(st->total_brate_fx,ACELP_48k) && LT_16(st->bwidth_fx,SWB) ) || /* Deactivate for core bitrates higher than 48.0 kb/s */ + ( GE_32(st->total_brate_fx,ACELP_13k20)&>_16(st->lp_noise_fx,FORMANT_SHARPENING_NOISE_THRESHOLD_FX) /* Deactivate for bitrates >= 13.2 kb/s if the long-term noise level exceeds 34 dB */ + && GT_32(st->total_brate_fx,CNA_MAX_BRATE) ) ) + { + *sharpFlag = 0; + move16(); + } + ELSE + { + *sharpFlag = 1; + move16(); + } + } + + /* channel-aware mode - due to lack of signalling bit, sharpFlag is 1 always in RF mode */ + test(); + test(); + IF( EQ_16(st->rf_mode,1)&&(EQ_16(*coder_type,VOICED)||EQ_16(*coder_type,GENERIC))) + { + *sharpFlag = 1; + } + + /*-----------------------------------------------------------------* + * Set voicing flag for HQ FEC + *-----------------------------------------------------------------*/ + + *Voicing_flag = 0; + move16(); + test(); + test(); + if ( *sp_aud_decision1 == 0 && ( EQ_16(*coder_type,VOICED)||EQ_16(*coder_type,GENERIC))) + { + *Voicing_flag = 1; + move16(); + } + + /*---------------------------------------------------------------* + * Preprocessing at other sampling frequency rate (16/25.6/32kHz) + *----------------------------------------------------------------*/ + + sr_core_tmp = L_max(INT_FS_16k_FX,st->sr_core); /* indicates the ACELP sampling rate for MODE2, 16 kHz for MODE1 */ + if( EQ_16(st->codec_mode,MODE1)) + { + sr_core_tmp = INT_FS_16k_FX; + move32(); + } + + L_frame_tmp = s_max(L_FRAME16k,st->L_frame_fx); + if( EQ_16(st->codec_mode,MODE1)) + { + L_frame_tmp = L_FRAME16k; + move16(); + } + L_look = NS2SA_fx2(sr_core_tmp, ACELP_LOOK_NS); + move16(); /* lookahead at other sampling rate (16kHz, 25.5kHz, 32kHz) */ + + new_inp_16k = old_inp_16k + L_INP_MEM; /* pointer to new samples of the input signal in 16kHz core */ + inp_16k = new_inp_16k - L_look; /* pointer to the current frame of input signal in 16kHz core */ + Copy( st->old_inp_16k_fx, old_inp_16k, L_INP_MEM ); /* Note: The merory has been rescaled at the begining of the function*/ + + /*---------------------------------------------------------------* + * Change the sampling frequency to 16/25.6/32 kHz + *----------------------------------------------------------------*/ + + test(); + IF( EQ_32(st->input_Fs_fx,sr_core_tmp)) + { + /* no resampling needed, only delay adjustement to account for the FIR resampling delay */ + delay = NS2SA_fx2(st->input_Fs_fx, DELAY_FIR_RESAMPL_NS); + Copy_Scale_sig( st->mem_decim16k_fx + delay, new_inp_16k, delay, -1 ); /* Input in Q0 -> Output in Q-1 to mimic the resampling filter */ + Copy_Scale_sig( signal_in, new_inp_16k + delay, input_frame - delay, -1 ); /* Input in Q0 -> Output in Q-1 to mimic the resampling filter */ + Copy( signal_in + input_frame - shl(delay,1), st->mem_decim16k_fx, shl(delay,1) ); /* memory still in Q0 */ + } + ELSE IF( EQ_32(st->input_Fs_fx,32000)||EQ_32(st->input_Fs_fx,48000)) + { + modify_Fs_fx( signal_in, input_frame, st->input_Fs_fx, new_inp_16k, sr_core_tmp, st->mem_decim16k_fx, 0 ); + } + ELSE /* keep memories up-to-date in case of bit-rate switching */ + { + /* no resampling needed, only delay adjustement to account for the FIR resampling delay */ + delay = NS2SA_fx2(st->input_Fs_fx, DELAY_FIR_RESAMPL_NS); + Copy( st->mem_decim16k_fx + delay, new_inp_16k, delay ); + Copy( signal_in, new_inp_16k + delay, sub(input_frame, delay) ); + Copy( signal_in + sub(input_frame, shl(delay,1)), st->mem_decim16k_fx, shl(delay,1) ); + } + + IF( EQ_32(sr_core_tmp,16000)) + { + /* save input resampled at 16kHz, non-preemhasised */ + Copy( new_inp_16k, new_inp_resamp16k, L_FRAME16k ); + } + ELSE IF( GT_32(sr_core_tmp,16000)) + { + /* reset the buffer, the signal is needed for WB BWEs */ + set16_fx( new_inp_resamp16k, 0, L_FRAME16k ); + } + + /*------------------------------------------------------------------* + * Perform fixed preemphasis (16kHz signal) through 1 - g*z^-1 + *-----------------------------------------------------------------*/ + + test(); + test(); + IF( ((st->tcxonly == 0) || (EQ_16(st->codec_mode,MODE1)))&>_32(st->input_Fs_fx,8000)) + { + st->mem_preemph_enc = shl(new_inp_16k[sub(L_frame_tmp,1)],1); + } + + test(); + IF( GT_32(st->input_Fs_fx,8000)&&EQ_32(sr_core_tmp,16000)) + { + Preemph_scaled( new_inp_16k, &Q_new_16k, &(st->mem_preemph16k_fx), st->Q_max_16k, PREEMPH_FAC_16k, 0, 1, L_Q_MEM, L_FRAME16k, st->last_coder_type_fx, 1); + } + ELSE IF( GT_32(st->input_Fs_fx,8000)) /* keep memory up-to-date in case of bit-rate switching */ + { + st->mem_preemph16k_fx = new_inp_16k[sub(L_frame_tmp,1)]; + move16(); + } + + /*------------------------------------------------------------------* + * Core-encoder memories scaling + *-----------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( ((st->tcxonly == 0) || !(NE_32(st->core_brate_fx,FRAME_NO_DATA)||NE_32(st->core_brate_fx,SID_2k40)))&&EQ_16(st->L_frame_fx,L_FRAME16k)&&EQ_16(st->codec_mode,MODE2))|| + ( EQ_16(st->L_frame_fx,L_FRAME16k) && EQ_16(st->codec_mode,MODE1) ) ) + { + *Q_new = Q_new_16k; + move16(); + } + ELSE + { + IF( GT_32(st->input_Fs_fx,8000)&&EQ_32(sr_core_tmp,16000)) + { + Scale_sig(new_inp_16k, L_FRAME16k, sub(*Q_new,Q_new_16k)); + } + } + + /* Above computed Q_new is used to scale primary copy exc and memory here by (Q_new, st->prev_Q_new) */ + + Q_exp = sub(*Q_new, st->prev_Q_new); + move16(); + Q_wsp_exp = add(Q_exp,shift_exp); + + Scale_mem_enc( Q_exp, old_inp_16k, old_exc, st->old_bwe_exc_fx, &(st->LPDmem.mem_w0), st->LPDmem.mem_syn, + st->LPDmem.mem_syn2, &st->mem_deemp_preQ_fx, st->last_exc_dct_in_fx, st->old_input_lp_fx ); + + /*-----------------------------------------------------------------* + * Redo LP analysis at 16kHz if ACELP@16k core was selected + * update buffers + *-----------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( ((st->tcxonly == 0) || !(NE_32(st->core_brate_fx,FRAME_NO_DATA)||NE_32(st->core_brate_fx,SID_2k40)))&&EQ_16(st->L_frame_fx,L_FRAME16k)&&EQ_16(st->codec_mode,MODE2))|| + ( EQ_16(st->L_frame_fx,L_FRAME16k) && EQ_16(st->codec_mode,MODE1) ) ) + { + /* update signal buffers */ + Copy( new_inp_resamp16k, st->buf_speech_enc+L_FRAME16k, L_FRAME16k ); + Scale_sig( st->buf_speech_enc+L_FRAME16k, L_FRAME16k, 1 ); + Copy( new_inp_16k, st->buf_speech_enc_pe+L_FRAME16k, L_FRAME16k ); + IF( Q_exp != 0 ) + { + Scale_sig(st->buf_speech_enc_pe, st->encoderPastSamples_enc+st->encoderLookahead_enc, Q_exp); + Scale_sig(&(st->mem_wsp_enc), 1, Q_exp); + } + + /*--------------------------------------------------------------* + * LPC analysis + *---------------------------------------------------------------*/ + + test(); + IF( EQ_16(st->last_L_frame_fx,L_FRAME)&&EQ_16(st->codec_mode,MODE1)) + { + /* this is just an approximation, but it is sufficient */ + Copy( st->lsp_old1_fx, st->lspold_enc_fx, M ); + } + + analy_lp_fx( inp_16k, L_FRAME16k, L_look, ener, A, epsP_h, epsP_l, lsp_new, lsp_mid, st->lspold_enc_fx, pitch, voicing, 16000, *Q_new, Q_r ); + + /*--------------------------------------------------------------* + * Compute Weighted Input + *---------------------------------------------------------------*/ + + IF( EQ_16(st->codec_mode,MODE2)) + { + find_wsp( A, st->speech_enc_pe, st->wspeech_enc, &st->mem_wsp_enc, PREEMPH_FAC_16k, L_FRAME16k, L_LOOK_16k, L_SUBFR, Aw, st->gamma, st->nb_subfr); + + /* This need to be harmonized with MODE2 */ + Scale_sig( st->wspeech_enc, L_FRAME16k+L_LOOK_16k, *shift ); + + } + ELSE + { + weight_a_subfr_fx( NB_SUBFR16k, A, Aw, GAMMA16k, M ); + } + } + ELSE + { + /* update signal buffers */ + Copy( new_inp_12k8, st->buf_speech_enc_pe+st->L_frame_fx, L_FRAME ); + Copy( st->buf_speech_enc+L_FRAME32k, st->buf_speech_enc+st->L_frame_fx, L_FRAME ); + + if ( st->tcxonly == 0 ) + { + Copy( wsp, st->buf_wspeech_enc+st->L_frame_fx+L_SUBFR, L_FRAME + L_LOOK_12k8 ); + } + test(); + test(); + IF( EQ_16(st->codec_mode,MODE2)&&st->tcxonly==0&&Q_exp!=0) + { + Scale_sig( st->buf_speech_enc_pe, st->encoderPastSamples_enc+st->encoderLookahead_enc, Q_exp ); + Scale_sig( &(st->mem_wsp_enc), 1, Q_exp ); + } + } + + excitation_max_test = -32768; + move16(); + FOR( i = 0; i < L_EXC_MEM; i++ ) + { + excitation_max_test = s_max(abs_s(old_exc[i]),excitation_max_test); + } + + test(); + IF( GT_16(excitation_max_test,8192)&&*shift==0) + { + excitation_max_test = 1; + move16(); + *shift = -1; + move16(); + st->old_wsp_shift=-1; + move16(); + Scale_sig( old_wsp, L_WSP_MEM+L_FRAME+L_LOOK_12k8, -1 ); + } + ELSE + { + excitation_max_test = 0; + move16(); + } + + test(); + IF ( EQ_16(st->codec_mode,MODE2)&&st->tcxonly==0) + { + IF (Q_wsp_exp != 0) + { + Scale_sig(st->buf_wspeech_enc, st->L_frame_fx+L_SUBFR, Q_wsp_exp); + } + IF( EQ_16(excitation_max_test,1)) + { + Scale_sig( st->buf_wspeech_enc, st->L_frame_fx+L_SUBFR+st->L_frame_fx+st->encoderLookahead_enc, -1 ); + } + } + + /*-----------------------------------------------------------------* + * ACELP/TCX20/HQ Switching Decision + *-----------------------------------------------------------------*/ + + IF ( EQ_16(st->codec_mode,MODE2)) + { + test(); + test(); + IF((NE_32(st->core_brate_fx,FRAME_NO_DATA)&&NE_32(st->core_brate_fx,SID_2k40)&&st->tcxonly==0)) + { + core_acelp_tcx20_switching( st,*vad_flag, + sp_aud_decision0, non_staX, + pitch, pitch_fr, voicing_fr, currFlatness, lsp_mid, stab_fac, *Q_new, *shift ); + } + + test(); + IF (EQ_16(st->mdct_sw_enable,MODE2)&&!st->rf_mode) + { + IF (EQ_16(st->core_fx,TCX_20_CORE)) /* Switching only possible from TCX_20 frames, not from TCX_10 frames */ + { + /* Select MDCT Core */ + test(); + test(); + IF ((EQ_16(st->bwidth_fx,SWB)||EQ_16(st->bwidth_fx,FB))&&EQ_32(st->total_brate_fx,24400)) + { + st->core_fx = mdct_classifier_fx(fft_buff,st,*vad_flag, enerBuffer + ,sub(enerBuffer_exp, 31) + ); + } + test(); + IF ((EQ_32(st->total_brate_fx,16400))&&(NE_16(st->bwidth_fx,FB))) + { + MDCT_selector( st, sp_floor, *Etot, cor_map_sum, voicing, enerBuffer, enerBuffer_exp, *vad_flag ); + } + } + ELSE + { + MDCT_selector_reset( st ); + } + + /* Do the switching that was decided in the MDCT selector */ + test(); + IF( EQ_16(st->core_fx,HQ_CORE)) + { + st->codec_mode = MODE1; + move16(); + st->mdct_sw = MODE2; + move16(); + } + ELSE IF( EQ_16(st->last_codec_mode,MODE1)&&EQ_16(st->last_core_fx,HQ_CORE)) + { + Word16 L_frame_old = st->last_L_frame_fx; + move16(); + st->last_L_frame_fx = st->L_frame_fx; + move16(); + SetModeIndex( st, st->total_brate_fx, st->bwidth_fx, *shift ); + st->last_L_frame_fx = L_frame_old; + move16(); + } + } + + /*--------------------------------------------------------------* + * TCX mode decision + *---------------------------------------------------------------*/ + + SetTCXModeInfo( st, &st->transientDetection, &st->tcx_cfg.tcx_curr_overlap_mode ); + } + + /*-----------------------------------------------------------------* + * Updates + *-----------------------------------------------------------------*/ + + /* update old weighted speech buffer - for OL pitch analysis */ + Copy( &old_wsp[L_FRAME], st->old_wsp_fx, L_WSP_MEM ); + + /* update old input signal buffer */ + Copy( &old_inp_12k8[L_FRAME], st->old_inp_12k8_fx, L_INP_MEM ); + + /* update old input signal @16kHz buffer */ + test(); + IF( GT_32(st->input_Fs_fx,8000)&&EQ_32(sr_core_tmp,16000)) + { + Copy( &old_inp_16k[L_frame_tmp], st->old_inp_16k_fx, L_INP_MEM ); + } + ELSE IF( GT_32(st->input_Fs_fx,8000)) + { + lerp( st->old_inp_12k8_fx+L_INP_MEM-L_INP_MEM*4/5, st->old_inp_16k_fx, L_INP_MEM, L_INP_MEM*4/5); + Scale_sig(st->old_inp_16k_fx, L_INP_MEM, sub(*Q_new,st->Q_old)); + } + + test(); + test(); + IF( (EQ_32(sr_core_tmp,16000))&&st->tcxonly&&EQ_16(st->codec_mode,MODE2)) + { + /* copy input resampled at 16kHz, non-preemhasised */ + Copy( new_inp_resamp16k, new_inp_16k, L_FRAME16k ); + } + + /* update of old per-band energy spectrum */ + Copy32( fr_bands + NB_BANDS, st->enrO_fx, NB_BANDS ); + + /* set the pointer of the current frame for the ACELP core */ + *inp = inp_16k; + if ( EQ_16(st->L_frame_fx,L_FRAME)) + { + *inp = inp_12k8; + } + + + return; +} diff --git a/lib_enc/pvq_core_enc_fx.c b/lib_enc/pvq_core_enc_fx.c new file mode 100644 index 0000000..7450792 --- /dev/null +++ b/lib_enc/pvq_core_enc_fx.c @@ -0,0 +1,633 @@ +#include "options.h" +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +static Word16 calc_pvq_splits_fx(Encoder_State_fx *st_fx, const Word16 band_bits, const Word16 sfmsize, const Word16 *y, const Word16 Q_y, + Word16 *bits); + +static void densityIndexSymbolEncode_fx( Encoder_State_fx *st_fx, const Word16 density , const Word16 r_dim, const Word16 l_dim , const Word16 index_phi ); + +/* Encode band with PVQ */ + +static void pvq_encode_band_fx( + Encoder_State_fx *st_fx, + const Word16 *coefs_norm, + const Word16 Q_coefs, + Word16 *pulse_vector, + Word16 *npulses, + Word16 *coefs_quant, + const Word16 sfmsize, + const Word16 band_bits, + Word16 *bits_left, + const Word16 strict_bits +) +{ + + Word16 K_val; + Word16 j, Np; + Word32 enr, E_part[MAX_SPLITS+1]; + Word16 part_start[MAX_SPLITS+1], dim_part[MAX_SPLITS+1], bits_part[MAX_SPLITS+1]; + Word16 pool_tot, pool_part, dim_parts; + Word16 g_part[MAX_SPLITS]; + Word16 g_part_neg[MAX_SPLITS]; + Word16 sg_part[MAX_SPLITS+1]; + Word16 idx_sort[MAX_SPLITS+1]; + Word16 js, band_bits_tot, split_bit; + Word16 tmp; + Word32 L_coefs_quant_fx[PVQ_MAX_BAND_SIZE]; + + Np = calc_pvq_splits_fx(st_fx, band_bits, sfmsize, coefs_norm, Q_coefs, &split_bit); + band_bits_tot = sub(band_bits, split_bit); + + enr = L_deposit_l(0); + FOR (j = 0; j < sfmsize; j++) + { + /* This is of paramount importance that the number of bits down-shift here + * MUST BE IDENTICAL to that used to compute "l_enr" in encode_energies_fx(). + * If the number of bits down-shift is changed here, that in encode_energies_fx() + * must be changed to the same amount as well! + */ + tmp = shr(coefs_norm[j], 2); + enr = L_mac0(enr, tmp, tmp); + } + + dim_parts = extract_h(L_mult(negate(sfmsize),lim_neg_inv_tbl_fx[Np])); + set16_fx( dim_part, dim_parts, sub(Np, 1) ); + dim_part[Np-1] = sub(sfmsize, i_mult2(dim_parts, sub(Np, 1))); + move16(); + + part_start[0] = 0; + move16(); + FOR (j = 1; j < Np; j++) + { + part_start[j] = add(part_start[j-1], dim_part[j-1]); + move16(); + } + + /* Encode energies */ + set16_fx(g_part_neg, -32768, Np); /* -1.0 in Q15 */ + IF (GT_16(Np, 1)) + { + encode_energies_fx( st_fx, coefs_norm, Q_coefs, Np, dim_part, E_part, bits_part, g_part_neg, band_bits_tot, bits_left, enr, sfmsize, strict_bits ); + } + ELSE + { + bits_part[0] = band_bits_tot; + move16(); + } + + pool_tot = 0; /* Word16 */ + pool_part = 0; /* Word16 */ + + FOR (j = 0; j < Np; j++) + { + g_part[j] = negate(g_part_neg[j]); + } + srt_vec_ind16_fx(g_part, sg_part, idx_sort, Np); + FOR(j = 0; j < Np; j++) + { + js = idx_sort[Np-1-j]; + pool_part = shrtCDivSignedApprox( pool_tot, sub(Np, j) ); + bits_part[js] = s_max(0, s_min(add(bits_part[js], pool_part), 256)); + + conservativeL1Norm_fx(dim_part[js], bits_part[js], strict_bits, *bits_left, pool_tot, *npulses, /* inputs */ + &K_val, bits_left, &pool_tot, npulses); /* outputs */ + + IF( K_val > 0 ) + { + pvq_encode_fx(st_fx,coefs_norm + part_start[js], pulse_vector + part_start[js], + coefs_quant + part_start[js], L_coefs_quant_fx, K_val, dim_part[js], g_part_neg[js]); + } + ELSE + { + set16_fx(coefs_quant + part_start[js], 0, dim_part[js]); + set16_fx(pulse_vector + part_start[js], 0, dim_part[js]); + } + } + + return; +} + +void pvq_encode_frame_fx( + Encoder_State_fx *st_fx, + const Word16 *coefs_norm, /* i : normalized coefficients to encode */ + Word16 Q_coefs, /* i : Q-point of coefs_norm[] */ + Word16 *coefs_quant, /* o : quantized coefficients */ + Word16 *gopt, /* o : optimal shape gains */ + Word16 *npulses, /* o : number of pulses per band */ + Word16 *pulse_vector, /* o : non-normalized pulse shapes */ + const Word16 *sfm_start, /* i : indices of first coefficients in the bands */ + const Word16 *sfm_end, /* i : indices of last coefficients in the bands */ + const Word16 *sfmsize, /* i : band sizes */ + const Word16 nb_sfm, /* i : total number of bands */ + const Word16 *R, /* i : bitallocation per band Q3 */ + const Word16 pvq_bits, /* i : number of bits avaiable */ + const Word16 core /* i : core */ +) +{ + Word16 i, j; + Word16 band_bits, bits_left; + + Word16 bit_pool = 0; + Word16 coded_bands, bands_to_code; + Word16 bits; + Word16 R_sort[NB_SFM]; + Word16 is, i_sort[NB_SFM]; + Word16 strict_bits; + Word16 exp, tmp, shift; + Word32 xy_corr, yy_corr; + rc_enc_init_fx(st_fx, pvq_bits); + + bits = shl(sub(pvq_bits, RC_BITS_RESERVED), 3); + + bands_to_code = 0; + move16(); + FOR (i = 0; i < nb_sfm; i++) + { + if (R[i] > 0) + { + bands_to_code = add(bands_to_code, 1); + } + } + + IF (core == ACELP_CORE) + { + strict_bits = 1; + move16(); + srt_vec_ind16_fx(R, R_sort, i_sort, nb_sfm); + } + ELSE + { + strict_bits = 0; + move16(); + FOR (i = 0; i < nb_sfm; i++) + { + i_sort[i] = i; + move16(); + } + } + + coded_bands = 0; + move16(); + FOR (i = 0; i < nb_sfm; i++) + { + is = i_sort[i]; + move16(); + gopt[is] = 0; + move16(); + IF (R[is] > 0) + { + bandBitsAdjustment_fx(st_fx->rc_num_bits_fx, st_fx->rc_range_fx, bits, bands_to_code, bands_to_code-coded_bands, sfmsize[is] ,R[is], bit_pool, /* inputs */ + &band_bits, &bits_left, &bit_pool); /* outputs */ + pvq_encode_band_fx( st_fx, &coefs_norm[sfm_start[is]], Q_coefs, &pulse_vector[sfm_start[is]], + &npulses[is], &coefs_quant[sfm_start[is]], sfmsize[is], band_bits, + &bits_left, strict_bits); + + xy_corr = L_deposit_l(0); + yy_corr = L_deposit_l(1); + shift = band_len_ener_shift[ band_len_idx[ shr(sfmsize[is], 3)] ]; + move16(); + FOR (j = 0; j < sfmsize[i]; j++) + { + tmp = shr(coefs_quant[sfm_start[is]+j], shift); + xy_corr = L_mac0(xy_corr, shr(coefs_norm[sfm_start[is]+j], 1), tmp); /* Q_coefs-1+15-shift */ + yy_corr = L_mac0(yy_corr, tmp, tmp); /* 2*(15-shift) */ + } + + tmp = ratio(xy_corr, yy_corr, &exp); + gopt[is] = shl(tmp, sub(sub(sub(14, Q_coefs), shift), exp)); + + if (gopt[is] == 0) + { + gopt[is] = 1; + move16(); + } + + /* Updates */ + coded_bands = add(coded_bands, 1); + } + ELSE + { + FOR (j = sfm_start[is]; j < sfm_end[is]; j++) + { + coefs_quant[j] = 0; + move16(); + pulse_vector[j] = 0; + move16(); + } + } + } + + rc_enc_finish_fx(st_fx); + + return; +} + +/*---------------------------------------------------------------------* + * pvq_core_enc() + * + * Main Generic Audio Encoder Routine + *---------------------------------------------------------------------*/ + +Word16 pvq_core_enc_fx( + Encoder_State_fx *st_fx, + Word16 coefs_norm[], + Word16 coefs_quant[], + Word16 *Q_coefs, + Word16 bits_tot, /* total number of bits */ + Word16 nb_sfm, + const Word16 *sfm_start, + const Word16 *sfm_end, + const Word16 *sfmsize, + Word16 *R, /* Q3 */ + Word16 *Rs, + Word16 *npulses, + Word16 *maxpulse, + const Word16 core +) +{ + Word16 i; + Word16 R_upd; /* Q3 */ + Word16 ord[NB_SFM_MAX]; + Word16 fg_pred[NB_SFM_MAX]; + Word16 pvq_bits; + + Word16 pulse_vector[L_FRAME48k]; + Word16 gopt[NB_SFM]; + Word16 gain_bits_array[NB_SFM]; + Word16 gain_bits_tot; + + + R_upd = shl(bits_tot, 3); + gain_bits_tot = assign_gain_bits_fx( core, nb_sfm, sfmsize, R, gain_bits_array, &R_upd ); + pvq_bits = shr(R_upd, 3); + + pvq_encode_frame_fx( st_fx, coefs_norm, *Q_coefs, coefs_quant, gopt, npulses, pulse_vector, sfm_start, sfm_end, sfmsize, nb_sfm, R, pvq_bits, core ); + + bits_tot = add(pvq_bits, gain_bits_tot); + + + IF( Rs != NULL ) + { + FOR (i=0; i < nb_sfm; i++) + { + if (npulses[i] <= 0) + { + Rs[i] = 0; + move16(); /* Update Rs in case no pulses were assigned */ + } + } + } + + FOR (i=0; i < nb_sfm; i++) + { + ord[i] = i; + move16(); + if (npulses[i] <= 0) + { + R[i] = 0; + move16(); /* Update in case no pulses were assigned */ + } + } + + get_max_pulses_fx( sfm_start, sfm_end, ord, npulses, nb_sfm, pulse_vector, maxpulse ); + + /* Fine gain prediction */ + fine_gain_pred_fx( sfm_start, sfm_end, sfmsize, ord, npulses, maxpulse, R, nb_sfm, + coefs_quant, pulse_vector, fg_pred, core); + + fine_gain_quant_fx(st_fx, ord, nb_sfm, gain_bits_array, fg_pred, gopt); + + apply_gain_fx(ord, sfm_start, sfm_end, nb_sfm, fg_pred, coefs_quant); + *Q_coefs = 12; + + return bits_tot; +} + +void encode_energies_fx( + Encoder_State_fx *st_fx, + const Word16 *coefs, /* In block-floating point format with a common block-exponent + not used in this function. Hence, the block-exponent is + not in the parameter list. */ + const Word16 Q_coefs, + Word16 Np, + Word16 *dim_part, + Word32 *E_part, /* 32-bit Q15 */ + Word16 *bits_part, + Word16 *g_part, /* Q15 */ + Word16 qband, + Word16 *bits_left, + Word32 enr, + Word16 dim, + const Word16 strict_bits +) +{ + Word16 i, j, l_Np, r_Np; + Word16 l_bits, r_bits, l_dim, r_dim; + Word32 l_enr, r_enr; + Word16 l_gain, r_gain; + Word16 il, ir; + Word16 density; + Word16 phi; + Word16 index_phi = -1; + Word16 oppRQ3, qzero ; + Word16 angle; + Word32 sqrt_r_enr, sqrt_l_enr; + Word16 exp1, exp2, tmp; + l_Np = shr(Np, 1); + r_Np = sub(Np, l_Np); + + l_enr = L_deposit_l(0); + l_bits = 0; + move16(); + l_dim = 0; + move16(); + FOR (i = 0; i < l_Np; i++) + { + l_dim = add(l_dim, dim_part[i]); + } + FOR (j = 0; j < l_dim; j++) + { + /* This is of paramount importance that the number of bits down-shift + * must be identical to that used to compute "enr" in pvq_encode_band_fx(). + * Otherwise, the subsequent "r_enr" will be computed incorrectly. + */ + tmp = shr(coefs[j], 2); + l_enr = L_mac0(l_enr, tmp, tmp); + } + r_enr = L_sub(enr, l_enr); + r_dim = sub(dim, l_dim); + + obtainEnergyQuantizerDensity_fx(dim, qband, &density); + sqrt_r_enr = Sqrt_l(r_enr, &exp1); + sqrt_l_enr = Sqrt_l(l_enr, &exp2); + + IF (LT_16(exp1, exp2)) + { + sqrt_l_enr = L_shr(sqrt_l_enr, shr(sub(exp2, exp1), 1)); + } + ELSE IF (LT_16(exp2, exp1)) + { + sqrt_r_enr = L_shr(sqrt_r_enr, shr(sub(exp1, exp2), 1)); + exp1 = exp2; + move16(); + } + + exp1 = add(shl(sub(Q_coefs, 2), 1), add(31, exp1)); /* 2x exponent */ + IF (EQ_16(s_and(exp1, 1), 1)) + { + sqrt_r_enr = Mult_32_16(sqrt_r_enr, 23170); /* Q(exp1/2) */ + sqrt_l_enr = Mult_32_16(sqrt_l_enr, 23170); /* Q(exp1/2) */ + } + + IF (sqrt_r_enr != 0) + { + angle = atan2_fx(sqrt_r_enr, sqrt_l_enr); /* Q14 */ + } + ELSE + { + angle = 0; + move16(); + } + + phi = mult_r(angle, 20861); + + rangeCoderFinalizationFBits_fx((Word16)st_fx->rc_num_bits_fx, (UWord32)st_fx->rc_range_fx, &qzero); + densityAngle2RmsProjEnc_fx(density, phi , &index_phi, &ir, &il, &oppRQ3); + densityIndexSymbolEncode_fx( st_fx, density , r_dim, l_dim , index_phi ); + + + + l_gain = il; /* Q15 */ move16(); + r_gain = ir; /* Q15 */ move16(); + + FOR (i = 0; i < l_Np; i++) + { + g_part[i] = mult_r(l_gain, g_part[i]); + } + + FOR (i = l_Np; i < Np; i++) + { + g_part[i] = mult_r(r_gain, g_part[i]); + } + + NearOppSplitAdjustment_fx( qband, qzero, st_fx->rc_num_bits_fx, st_fx->rc_range_fx, *bits_left, + strict_bits, Np, dim_part[0], dim_part[Np-1], + l_dim, r_dim, oppRQ3, + &l_bits, &r_bits, bits_left); + + IF (GT_16(l_Np, 1)) + { + encode_energies_fx( st_fx, coefs, Q_coefs, l_Np, dim_part, E_part, bits_part, g_part, l_bits, bits_left, l_enr, l_dim, strict_bits ); + } + ELSE + { + E_part[0] = l_enr; + move32(); + bits_part[0] = l_bits; + move16(); + } + IF (GT_16(r_Np, 1)) + { + encode_energies_fx( st_fx, &coefs[l_dim], Q_coefs, r_Np, &dim_part[l_Np], &E_part[l_Np], &bits_part[l_Np], &g_part[l_Np], r_bits, bits_left, r_enr, r_dim, strict_bits ); + } + ELSE + { + E_part[1] = r_enr; + move32(); + bits_part[1] = r_bits; + move16(); + } + + return; +} + + +void densityIndexSymbolEncode_fx( + Encoder_State_fx *st_fx, + const Word16 density , + const Word16 r_dim, + const Word16 l_dim, + const Word16 index_phi +) +{ + Word16 angle, c, densitySubIndex, densitySubC; + Word32 sym_freq, cum_freq, tot; + Word32 acc; + UWord16 lsb; + + sym_freq = L_deposit_l(1); + + IF( s_and((Word16)0xFFFE, density) != 0 ) /* even */ + { + angle = atan2_fx(SQRT_DIM_fx[r_dim], SQRT_DIM_fx[l_dim]); + angle = shl(angle, 1); + angle = mult_r(angle, 20861); + c = mult_r(density, angle); + + densitySubIndex = sub(density, index_phi); + densitySubC = sub(density, c); + + IF (c == 0) + { + tot = L_mac0(1L, density, add(density, 1)); + sym_freq = L_deposit_l(add(shl(sub(density, index_phi), 1), 1)); + cum_freq = L_mac0(L_mult(index_phi, density), index_phi, 1); + } + ELSE IF (EQ_16(c, density)) + { + tot = L_mac0(1L, density, add(density, 1)); + sym_freq = L_deposit_l(add(shl(index_phi, 1), 1)); + cum_freq = L_mult0(index_phi, index_phi); + } + ELSE + { + acc = L_mult0(density, c); /* density*c */ + Mpy_32_16_ss(acc, densitySubC, &acc, &lsb); /* density*c*(density - c) */ + acc = L_or(L_shl(acc, 16), L_and(lsb, 0xffffL)); /* Concatenate acc and lsb forming 48-bit; upshift 16 bits; keep 32 MSB. */ + acc = L_shr(acc, 1); /* Compensate fractional mode multiply (Mpy_32_16_ss) */ + tot = L_add(L_add(acc, (Word32)density), 1L); /* density*c*(density - c) + density + 1 */ + IF (LE_16(index_phi, c)) + { + sym_freq = L_mac(1L, index_phi, densitySubC); + acc = L_mult0(densitySubC, sub(index_phi, 1)); + acc = L_add(acc, 1); + Mpy_32_16_ss(acc, index_phi, &acc, &lsb); + acc = L_or(L_shl(acc, 16), L_and(lsb, 0xffffL)); + cum_freq = L_shr(acc, 1); + } + ELSE + { + sym_freq = L_mac(1L, densitySubIndex, c); + acc = L_mult0(densitySubIndex, add(densitySubIndex, 1)); + Mpy_32_16_ss(acc, c, &acc, &lsb); + acc = L_or(L_shl(acc, 16), L_and(lsb, 0xffffL)); + acc = L_shr(acc, 1); + acc = L_sub(acc, (Word32)index_phi); + acc = L_add(add(density, 1), acc); + cum_freq = L_sub(tot, acc); + } + } + + rc_encode_fx(st_fx, cum_freq, sym_freq, tot); + } + + return; +} + +/*--------------------------------------------------------------------------* + * calc_pvq_splits() + * + * Calculate the number of segments needed + *--------------------------------------------------------------------------*/ + +static Word16 calc_pvq_splits_fx( /* o : Number of segments */ + Encoder_State_fx *st_fx, /* i/o: Encoder state */ + const Word16 band_bits, /* i : Band bit rate */ + const Word16 sfmsize, /* i : Band width */ + const Word16 *y, /* i : Target vector */ + const Word16 Q_y, /* i : Q point of y */ + Word16 *bits /* o : Consumed bits */ +) +{ + Word16 Np; + Word16 Npart; + Word16 i,j; + Word16 E[MAX_SPLITS]; + Word16 Emean, eTotal; + Word16 tmp, expo; + const Word16 *pY; + Word16 max_dev,qPoint; + Word32 acc, acc1; + + IF (band_bits == 0) + { + Np = 1; + move16(); + } + ELSE + { + acc = L_mult0(band_bits, 0x7a44); + Np = extract_l(L_shr(acc, 23)); /* Get integer part. */ + if (L_and(acc, 0x7fffffL) != 0) /* If fractional part != 0, add 1. */ + { + Np = add(Np, 1); /* ceiling operation */ + } + } + *bits = 0; + move16(); + + IF (LT_16(Np, MAX_SPLITS)) + { + acc = L_mult0(8*THR_ADD_SPLIT, sfmsize); + IF (GT_32(band_bits, acc)) + { + Npart = extract_l((Word32)intLimCDivPos_fx(UL_deposit_l((UWord16)sfmsize), Np)); + *bits = 8; + move16(); + eTotal = 0; + move16(); + pY = y; + qPoint = shl(Q_y, 1); /* acc in 2*Q_y */ + FOR (i = 0; i < Np; i++) + { + acc = L_deposit_l(0); + FOR (j = 0; j < Npart; j++) + { + acc= L_mac0(acc, *pY, *pY); + pY++; + } + acc = L_shr(acc, qPoint); + + E[i] = sub(30, norm_l(L_max(1L,acc))); /* L_max needed to handle low subvector levels */ + eTotal = add(eTotal, E[i]); + } + + Emean = ratio(eTotal, Np, &expo); + Emean = shr(Emean, add(14 - 8, expo)); /* Emean in Q8 */ + + max_dev = -1; + move16(); + FOR (i = 0; i < Np; i++) + { + tmp = abs_s(sub(shl(E[i], 8), Emean)); /* in Q8 */ + max_dev = s_max(tmp, max_dev); + } + + acc = L_sub(L_shl(Np, 5 + 3 + 8), L_shl(band_bits, 8)); /* NB: max_dev in Q8 */ + acc1 = L_shl(L_mult0(Np, max_dev), 3); + + tmp = 0; + move16() ; + if( GT_32(acc1, acc)) + { + tmp = 1; + move16(); + } + rc_enc_bits_fx(st_fx, tmp, 1); + Np = add(Np, tmp); + } + } + + /* Check constraints for number of splits */ + /* The following code assumes that PVQ_MAX_BAND_SIZE is 64 */ + i = shr(sfmsize, 6); /* 6 = log2(64) = log2(PVQ_MAX_BAND_SIZE) */ + if (s_and(sfmsize, 0x3f) != 0) + { + i = add(i, 1); /* ceiling operation */ + } + + Np = s_max(i, Np); + Np = s_min(MAX_SPLITS, Np); + Np = s_min(sfmsize, Np); /* The code line assumes that MIN_BAND_SIZE is 1 */ + return Np; +} + + diff --git a/lib_enc/pvq_encode_fx.c b/lib_enc/pvq_encode_fx.c new file mode 100644 index 0000000..b850930 --- /dev/null +++ b/lib_enc/pvq_encode_fx.c @@ -0,0 +1,370 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" +#include "stl.h" +#include "prot_fx.h" +#include "rom_com_fx.h" + +#include +/* PVQ MIXED_SEARCH_LOOP: + low precision 16/32 + energy selective high precision 32/64, + mixed perf , 10 dB SEGSNR better than the low precision loop only, + active if k>=128 and accumulated energy is high enough, + comes at a controlled complexity cost, as dimensions decrease for high k's*/ + +static +Word16 max_val_fx( /* o : maximum value in the input vector */ + const Word16 *vec, /* i : input vector */ + const Word16 lvec /* i : length of input vector */ +) +{ + Word16 j,tmp; + + tmp = vec[0]; + move16(); + FOR ( j=1 ; j 0 ); +} + + +/* The inner search loop for one single additional unit pulse, starting from pulse_tot , + with information about required energy precision/down scaling for the dim loop in en_dn_shift, + and the current max_xabs absolute value to be used for an near optimal correlation upscaling. + returns the index of the best positioned unit pulse in imax +*/ +static +Word16 one_pulse_search(const Word16 dim, /* vector dimension */ + const Word16* x_abs, /* absolute vector values */ + Word16* y, /* output vector */ + Word16 *pulse_tot_ptr, + Word32* L_xy_ptr, /* accumulated correlation */ + Word32* L_yy_ptr, /* accumulated energy */ + Word16 high_prec_active, + Word16 en_dn_shift, + Word16 max_xabs) /* current accumulated max amplitude for pulses */ +{ + Word16 i, corr_up_shift, corr_tmp, imax, corr_sq_tmp, en_max_den, cmax_num, en_tmp; + Word32 L_tmp_en_lc, L_tmp_corr ; + Word32 L_tmp_en, L_en_max_den, L_corr_sq_max, L_tmp_corr_sq; + Word32 L_left_h, L_right_h; + UWord32 UL_left_l, UL_right_l, UL_dummy; + Word32 L_tmp; + UWord16 u_sgn; + + en_tmp = en_dn_shift; /* dummy assignment to avoid compiler warning for unused parameter */ + + /* maximize correlation precision, prior to every unit pulse addition in the vector */ + corr_up_shift = norm_l(L_mac(*L_xy_ptr, 1, max_xabs)); /* pre analyze worst case L_xy update in the dim loop , 2 ops */ + imax = -1; /* not needed for search, only added to avoid compiler warning */ + + /* clean BE code, with split out low/high precision loops */ + /* activate low complexity en/corr search section conditionally if resulting vector energy is within limits */ + /* typical case for higher dimensions */ + + IF( high_prec_active == 0 ) + { + en_max_den = 0; /*move16()*/; /* OPT: move saved by using high_prec_active as en_max_den */ /* 1 op */ + cmax_num = -1; + move16(); /* req. to force a 1st update for n==0 */ /* 1 op */ + + FOR(i = 0; i < dim; i++) /* FOR 3 ops */ + { + L_tmp_corr = L_shl(L_mac(*L_xy_ptr,1,x_abs[i]), corr_up_shift ); /* actual in-loop target value, 2 ops */ + corr_tmp = round_fx(L_tmp_corr); /* 1 op */ + corr_sq_tmp = mult(corr_tmp, corr_tmp); /* CorrSq, is a 16bit for low compelxity cross multiplication 1 op */ + + L_tmp_en_lc = L_mac(*L_yy_ptr, 1,y[i] ); /*Q1 result , energy may span up to ~14+1(Q1)+1(sign)=16 bits, 1 op */ + /* extract_l without shift can always be used for this section as energy is guaranteed to stay in the lower word, 1 op */ + en_tmp = extract_l(L_tmp_en_lc); /* L_shl + round_fx could also be used also but then adds an uphift cost (2-3 ops)*/ + + /* 16/32 bit comparison WC (4 +1+1 + (1+1+1) = 9 */ + IF( L_msu(L_mult(corr_sq_tmp, en_max_den),cmax_num , en_tmp) > 0) /* use L_mult and then a L_msu, 2 ops */ + { + cmax_num = corr_sq_tmp; + move16(); /* 1 op */ + en_max_den = en_tmp; + move16(); /* 1 op */ + imax = i; + move16(); /* 1 op */ + } + } /* dim */ + + } + ELSE + { + /* High resolution section activated when vector energy is becoming high (peaky or many pulses) */ + /* BASOP operator Mpy32_32_ss used to allow higher resolution for both the CorrSq term and the Energy term */ + + L_en_max_den = L_deposit_l(0); /* 1 op */ + L_corr_sq_max = L_deposit_l(-1); /* req. to force a 1st update */ /* 1 op */ + + FOR(i = 0; i < dim; i++) /* FOR 3 ops */ + { + L_tmp_corr = L_shl(L_mac(*L_xy_ptr,1,x_abs[i]), corr_up_shift ); /* actual in loop WC value 2 ops */ + Mpy_32_32_ss(L_tmp_corr,L_tmp_corr, &L_tmp_corr_sq, &UL_dummy); /* CorrSq 32 bits, 4 ops */ + + L_tmp_en = L_mac(*L_yy_ptr, 1, y[i]); /* Q1,energy may span up to sign+19 bits , 1 op */ + /* For highest accuracy use pairs of maximum upshifted 32x32 bit signed values */ + /* (L_tmp_corr_sq / L_tmp_en) > (L_corr_sq_max/L_en_max_den) */ + /* (L_tmp_corr_sq * L_en_max_den) > (L_corr_sq_max * L_tmp_en) */ + Mpy_32_32_ss( L_en_max_den, L_tmp_corr_sq, &L_left_h, &UL_left_l); /* 4 ops */ + Mpy_32_32_ss( L_tmp_en, L_corr_sq_max, &L_right_h, &UL_right_l); /* 4 ops */ + + /* STL optimized "Lazy evaluation" of: + IF( (L_left_h > L_right_h) || ( (L_left_h == L_right_h) && (UL_left_l > UL_right_l) ) + */ + /* 32/64 bit Lazy eval comparison WC cost is (1+ 1+1+1 + 4 +(2+2+1) = 13 , and average is ~12 */ + /* Unoptimized 32/64 bit comparison WC cost is (1+1+ 2x2 + 4 +(2+2+1) = 15 */ + L_tmp = L_sub(L_left_h, L_right_h); /* high signed word check 1 op */ + u_sgn = 0; + move16(); /* 1 op */ + if(L_tmp == 0) /* L_tmp high Word testing is always needed */ + { + /* The returned UL value from UL_subNs is not needed, only u_sgn is needed */ + UL_subNs(UL_right_l, UL_left_l, &u_sgn); /* low unsigned word check, note left/right order switch of ">" due to ">=" inside UL_subNs, 1 op */ + } + if( u_sgn != 0) + { + L_tmp = L_add(L_tmp, 1); /* 0+1 --> 1 use wrap/sign result of low Word u_sgn check */ /* 1 op */ + } + IF( L_tmp > 0 ) /* IF 4 ops */ + { + L_corr_sq_max = L_add(L_tmp_corr_sq, 0); /* 1-2 ops */ + L_en_max_den = L_add(L_tmp_en, 0); /* 1-2 ops */ + imax = i; + move16(); /* 1 op */ + } + } /* dim loop */ + + } + /* Complexity comparison per coeff for low precision vs. high precision + low precision: pulse_tot <= 127, 16 bit: WC 2+3 +(15)*dim ops, dim=5 --> 5+15*5 = 90 ops, 18 ops/coeff + high precision: pulse_tot > 127, 32 bit: WC 1+3+3 +(26-28)*dim ops, WC-band dim=5 --> 7+28*5 = 147 ops, 29 ops/coeff ~61% increase + */ + + /* finally add found unit pulse contribution to past L_xy, Lyy, for next pulse loop */ + *L_xy_ptr = L_mac(*L_xy_ptr, x_abs[imax], 1); /* Q12+1 */ + *L_yy_ptr = L_mac(*L_yy_ptr, 1, y[imax]); + + y[imax] = add(y[imax],1); + move16(); /* Q0 added pulse */ + (*pulse_tot_ptr) = add((*pulse_tot_ptr) ,1); /* increment total pulse sum */ + + return imax; +} +/*-----------------------------------------------------------------------* + * Function pvq_encode_fx() * + * * + *-----------------------------------------------------------------------*/ +void pvq_encode_fx( + Encoder_State_fx *st_fx, + const Word16 *x, /* i: vector to quantize Q15-3=>Q12 */ + Word16 *y, /* o: raw pulses (non-scaled short) Q0 */ + Word16 *xq, /* o: quantized vector Q15 */ + Word32 *L_xq, /* o: quantized vector Q31 fot eval */ + const Word16 pulses, /* i: number of allocated pulses */ + const Word16 dim, /* i: Length of vector */ + const Word16 neg_gain /* i: - Gain use - negative gain in Q15 0..1 */ +) +{ + Word16 i; + Word16 pulse_tot; + Word16 xabs[PVQ_MAX_BAND_SIZE]; + Word16 max_xabs; + Word32 L_xsum; + Word32 L_proj_fac; + Word32 L_yy, L_xy; + Word16 max_amp_y, imax; + Word16 k, en_margin, en_dn_shift, high_prec_active ; + + Word32 L_num, L_tmp; + Word16 proj_fac, tmp, shift_den,shift_num,shift_delta, num,den; + + UWord16 u16_tmp; + Word16 dim_m1; + Word32 L_isqrt; + Word16 neg_gain_norm, shift_tot; + Word16 high_pulse_density_flag; + PvqEntry_fx entry; + + L_proj_fac = 4096; + L_xsum = L_deposit_h(0); + max_xabs = -1; + move16(); + + FOR( i = 0; i < dim; i++) + { + xabs[i] = abs_s(x[i]); + move16(); /* Q12 */ + max_xabs = s_max(max_xabs, xabs[i] ); /* for efficient search correlation scaling */ + L_xsum = L_mac0(L_xsum, 1, xabs[i] ); /* stay in Q12 */ + y[i] = 0; + move16(); /* init, later only non-zero values need to be normalized */ + } + + test(); + IF( L_xsum == 0 || neg_gain == 0 ) + { + pulse_tot = pulses; + move16(); + dim_m1 = sub(dim,1); + y[dim_m1] = 0; + move16(); + y[0] = shr(pulses,1); + move16(); + y[dim_m1] = add(y[dim_m1], sub(pulses, y[0])); + move16(); + L_yy = L_mult(y[0],y[0]); /* L_yy needed for normalization */ + if(dim_m1 != 0) + { + L_yy = L_mac(L_yy, y[dim_m1],y[dim_m1]); /* (single basop) */ + } + } + ELSE + { + + num = sub(pulses, PYR_OFFSET); + high_pulse_density_flag = pyramidSearchProjInit_fx(dim, pulses ); + + test(); + IF( (num > 0) && (high_pulse_density_flag != 0) ) + { + shift_den = norm_l(L_xsum); /* x_sum input Q12 */ + den = extract_h(L_shl(L_xsum, shift_den)); /* now in Q12+shift_den */ + + L_num = L_deposit_l(num); + shift_num = sub(norm_l(L_num) ,1); + L_num = L_shl(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 */ + + shift_delta=sub(shift_num,shift_den); + L_proj_fac = L_shl(L_deposit_l(proj_fac), sub(9, shift_delta)); /* bring to a fixed Q12 */ + } + + pulse_tot = 0; + move16(); + L_yy = L_deposit_l(0); + L_xy = L_deposit_l(0); + test(); + IF( (num > 0 ) && (high_pulse_density_flag != 0 ) ) + { + FOR( i = 0; i < dim ; i++) /* max 64 */ + { + Mpy_32_16_ss(L_proj_fac,xabs[i],&L_tmp,&u16_tmp); /*Q12 *Q12 +1 */ + y[i] = extract_l(L_shr( L_tmp, 12+12-16+1 )); + move16();/* Q12 *Q12 -> Q0 */ + + pulse_tot = add(pulse_tot, y[i]); /* Q0 */ + L_yy = L_mac(L_yy, y[i], y[i]); /* Energy, result will scale up by 2 by L_mac */ + L_xy = L_mac(L_xy, xabs[i], y[i]); /* Corr, Q0*Q12 +1 --> Q13 */ + } + } + + + L_yy=L_shr(L_yy,1); + IF (LE_16(pulses,127)) + { + /* LC inner loop, enters here always for dimensions 6 and higher, and also sometimes for dimensions 1 .. 5 */ + /* ( if high energy precision is inactive, max_amp_y is not needed , no max_amp_y(k-1) update ) */ + FOR (k=pulse_tot; k +#include "prot_fx.h" +#include "stl.h" +#include "basop_util.h" +#include "rom_com_fx.h" + +enum FUNC_GAIN_ENC +{ + FUNC_GAIN_ENC_MLESS = 0, /* Memory-less gain coding */ + FUNC_GAIN_ENC_2 = 1, /* AMR-WB gains quantizer (6bits/subfr (mode 4) or 7bits/subfr (mode 5)) */ /* !!! to be removed !!! */ + FUNC_GAIN_ENC_UV, /* UV gains quantizer (5bits/subfr) */ + FUNC_GAIN_ENC_GACELP_UV /* UV GACELP gain quantizer ((7=5-2bits/subfr) */ +}; + + + +void encode_acelp_gains( + Word16 *code, + Word16 gains_mode, + Word16 mean_ener_code, + Word16 clip_gain, + ACELP_CbkCorr *g_corr, + Word16 *gain_pit, + Word32 *gain_code, + Word16 **pt_indice, + Word32 *past_gcode, + Word16 *gain_inov, + Word16 L_subfr + , Word16 *code2, + Word32 *gain_code2 + ,Word8 noisy_speech_flag /* (i) : noisy speech flag */ +) +{ + Word16 index = 0, func_type = 0; + + BASOP_SATURATE_ERROR_ON; + + SWITCH(gains_mode) + { + case 1: + case 2: + case 3: + /* Memory-less gain coding */ + gains_mode = sub(gains_mode, 1); + func_type = FUNC_GAIN_ENC_MLESS; + move16(); + BREAK; + case 4: + case 5: + assert(0); + BREAK; + case 6: + /* UV gains quantizer (6 bits/subfr) */ + gains_mode = sub(gains_mode, 6); + func_type = FUNC_GAIN_ENC_UV; + move16(); + BREAK; + case 7: + gains_mode = sub(gains_mode, 7); + func_type = FUNC_GAIN_ENC_GACELP_UV; + move16(); + BREAK; + default: + fprintf(stderr, "invalid gains coding for acelp!\n"); + assert(0); + func_type = 0; + move16(); /*To avoid compiler warning*/ + BREAK; + } + + IF( func_type == FUNC_GAIN_ENC_MLESS ) + { + index = gain_enc(code, + L_subfr, gain_pit, gain_code, g_corr, mean_ener_code, + clip_gain, past_gcode, gain_inov, gains_mode, func_type); + } + ELSE + { + index = gain_enc_uv(code, + code2, + L_subfr, gain_pit, gain_code, + gain_code2, + noisy_speech_flag, + g_corr, mean_ener_code, + past_gcode, gain_inov, + func_type); + } + + move16(); + **pt_indice = index; + (*pt_indice)++; + + BASOP_SATURATE_ERROR_OFF; +} + +/*---------------------------------------------------------------------* + * procedure gain_enc_mless + * Quantization of pitch and codebook gains. + * - an initial predicted gain, gcode0, is first determined based on + * the predicted scaled innovation energy + * - the correction factor gamma = g_code / gcode0 is then vector quantized + * along with gain_pit + * - the mean-squared weighted error criterion is used for the quantizer search + *---------------------------------------------------------------------*/ + +Word16 gain_enc( /* o : quantization pitch index */ + const Word16 *code, /* i : algebraic excitation */ + Word16 lcode, /* (i) : Subframe size in range: 40,64,80 */ + Word16 *gain_pit, /* o : quantized pitch gain */ + /* i/o : only func=1,coder_type=1 quantized pitch gain */ + Word32 *gain_code, /* o : quantized codebook gain */ + ACELP_CbkCorr *g_coeff, /* i : correlations , -2,, -2 and 2 */ + Word16 mean_ener, /* (i) : only func=0: mean_ener defined in open-loop (3 bits) */ + const Word16 clip_gain, /* i : only func=0,1: gain pitch clipping flag (1 = clipping) */ + Word32 *past_gcode, /* o : past gain of code */ + Word16 *gain_inov, /* (o) : Q12 innovation gain */ + const Word16 coder_type, /* (i) : only func=0,1: coder type */ + const Word16 func_type /* (i) : algorithm: 0=gain_enc_mless, 1=gain_enc_2 */ +) +{ + Word16 i, j, index, size, min_index, exp_L_tmp1; + Word16 gcode0, gcode0_gi, exp_gcode0, exp_sum, exp_code, g_code_shl; + + Word16 g_code; + Word16 coeff0, coeff1, coeff2, coeff3, coeff4, exp_coeff0, exp_coeff1, exp_coeff2, exp_coeff3, exp_coeff4; + Word16 shr_coeff0, shr_coeff1, shr_coeff2, shr_coeff3, shr_coeff4; + const Word16 *p; + const Word16 *t_qua_gain; + Word32 L_tmp, dist_min, L_tmp1; + + + + assert((func_type != FUNC_GAIN_ENC_UV) && (func_type != FUNC_GAIN_ENC_GACELP_UV)); + + /* Debug test value (not instrumented) */ + gcode0 = -3000; + move16(); + + /*----------------------------------------------------------------* + * - calculate the unscaled innovation energy + * - calculate the predicted gain code + *----------------------------------------------------------------*/ + + /* gain_inov = 1.0f / sqrt((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */ + L_tmp = calc_gain_inov(code, lcode, &L_tmp1, &exp_L_tmp1); + move16(); + *gain_inov = round_fx(L_shl(L_tmp, 15-3)); /* gain_inov in Q12 */ + + /*----------------------------------------------------------------* + * calculate the predicted gain code + *----------------------------------------------------------------*/ + IF (func_type == FUNC_GAIN_ENC_MLESS) + { + /*j = 10 * log10((dot_product(code, code, lcode) + 0.01) / lcode) */ + j = BASOP_Util_lin2dB(L_tmp1, exp_L_tmp1, 1); /* Q8 */ + + /* predicted codebook gain */ + gcode0 = sub(mean_ener, j); /* Q8 */ + + } + + /*----------------------------------------------------------------* + * Compute coefficients needed for the quantization. + * + * coeff[0] = yy1 yy1 + * coeff[1] = -2 xn yy1 + * coeff[2] = y2 y2 + * coeff[3] = -2 xn y2 + * coeff[4] = 2 yy1 y2 + * + * Product and have been computed in Adpt_enr() and + * are in vector g_coeff[]. + *----------------------------------------------------------------*/ + + coeff0 = g_coeff->y1y1; + move16(); + exp_coeff0 = g_coeff->y1y1_e; + move16(); + coeff2 = g_coeff->y2y2; + move16(); + exp_coeff2 = g_coeff->y2y2_e; + move16(); + + coeff1 = g_coeff->xy1; + move16(); + exp_coeff1 = add(g_coeff->xy1_e, 1); + coeff3 = g_coeff->xy2; + move16(); + exp_coeff3 = add(g_coeff->xy2_e, 1); + coeff4 = g_coeff->y1y2; + move16(); + exp_coeff4 = add(g_coeff->y1y2_e, 1); + + /*---------------------------------------------------------------* + * Decode codebook gain and the adaptive excitation low-pass + * filtering factor (Finalize computation ) + *---------------------------------------------------------------*/ + + + /* gcode0 = pow(10, 0.05 * (Es_pred - Ei)) */ + /*----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) gcode in Q8 + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *----------------------------------------------------------------*/ + + /* Check if gcode0 was uninitialized. */ + assert(gcode0 != -3000); + + L_tmp = L_mult(gcode0, 5443/*0.166096f Q15*/); + exp_gcode0 = add(1,extract_l(L_shr(L_tmp, 24))); + L_tmp = L_lshl(L_tmp, 7); + L_tmp = L_and(0x7FFFFFFF, L_tmp); + + L_tmp = Pow2(30,round_fx(L_tmp)); + gcode0 = round_fx(L_tmp); + /* exponent of gcode0 = exp_gcode0 */ + + /*-----------------------------------------------------------------* + * gain quantization initializations + * - find the initial quantization pitch index + * - set the gains searching range + *----------------------------------------------------------------*/ + + /*----------------------------------------------------------------* + * Find the best quantizer + * + * Before doing the computation we need to align exponents of coeff[] + * to be sure to have the maximum precision. + * + * In the table the pitch gains are in Q14, the code gains are in Q11 and + * are multiplied by gcode0 which have been multiplied by 2^exp_gcode0. + * Also when we compute g_pitch*g_pitch, g_code*g_code and g_pitch*g_code + * we divide by 2^15. + * Considering all the scaling above we have: + * + * exp_code = exp_gcode0 + 4 + * if (func_type == gain_enc_2) + * gcode0 *= gain_inov (in Q12) => exp_code += 3 + * + * g_pitch*g_pitch = +1+1 + * g_pitch = +1 + * g_code*g_code = (2*exp_code) + * g_code = exp_code + * g_pitch*g_code = + 1 + exp_code + * + * g_pitch*g_pitch * coeff[0] ;exp_max0 = exp_coeff[0] + 2 + * g_pitch * coeff[1] ;exp_max1 = exp_coeff[1] + 1 + * g_code*g_code * coeff[2] ;exp_max2 = exp_coeff[2] + (2*exp_code) + * g_code * coeff[3] ;exp_max3 = exp_coeff[3] + exp_code + * g_pitch*g_code * coeff[4] ;exp_max4 = exp_coeff[4] + 1 + exp_code + *----------------------------------------------------------------*/ + + exp_code = add(exp_gcode0, 4); + + exp_coeff0 = add(exp_coeff0, 2); + exp_coeff1 = add(exp_coeff1, 1); + exp_coeff2 = add(exp_coeff2, shl(exp_code, 1)); + exp_coeff3 = add(exp_coeff3, exp_code); + exp_coeff4 = add(exp_coeff4, add(1, exp_code)); + + /* Find maximum exponent */ + exp_sum = s_max(exp_coeff1, exp_coeff0); + exp_sum = s_max(exp_coeff2, exp_sum); + exp_sum = s_max(exp_coeff3, exp_sum); + exp_sum = s_max(exp_coeff4, exp_sum); + exp_sum = add(exp_sum,2); + + /* Align exponents of summands in loop far below. */ + shr_coeff0 = sub(exp_sum, exp_coeff0); + shr_coeff1 = sub(exp_sum, exp_coeff1); + shr_coeff2 = sub(exp_sum, exp_coeff2); + shr_coeff3 = sub(exp_sum, exp_coeff3); + shr_coeff4 = sub(exp_sum, exp_coeff4); + /* Codebook search */ + + dist_min = L_deposit_h(MAX_16); + + min_index = 0; + move16(); + + { + Word16 size_clip; + + + IF( coder_type == 0) + { + + t_qua_gain = E_ROM_qua_gain5b_const; + size_clip=9; + size=NB_QUA_GAIN5B; + } + ELSE IF(coder_type == 1) + { + + t_qua_gain = E_ROM_qua_gain6b_const; + size_clip=6; + size = NB_QUA_GAIN6B; /* searching range of the gain quantizer */ + } + ELSE + { + + t_qua_gain = E_ROM_qua_gain7b_const; + size_clip=21; + size = NB_QUA_GAIN7B; + } + + if ( EQ_16(clip_gain,1)) + { + size = sub(size, size_clip); /* limit pitch gain to 1.0 */ + } + gcode0_gi = gcode0; + move16(); + + } + move16(); + p = t_qua_gain; + + index = 0; + move16(); + + /* divide all coeff1,2,3,4 by coeff0 */ + /* in order to skip multiplication with coeff0 in loop */ + assert(coeff0 >= 0x4000); + coeff0 = div_s(0x4000,coeff0); + coeff1 = mult_r(coeff1,coeff0); + coeff2 = mult_r(coeff2,coeff0); + coeff3 = mult_r(coeff3,coeff0); + coeff4 = mult_r(coeff4,coeff0); + + FOR (i = 0; i < size; i++) + { + /* + Note: gcode0_gi: either gcode0 or gcode0*gain_inov + g_pitch = *p++; + g_code = gcode0_gi * *p++; + + dist = g_pitch*g_pitch * coeff.y1y1 + + g_pitch * coeff.xy1 (negated) + + g_code*g_code * coeff.y2y2 + + g_code * coeff.xy2 (negated) + + g_pitch*g_code * coeff.y1y2; + */ + + /* Since g_code has a significant dynamic, we prefer to normalize this 16-bit value */ + g_code_shl = norm_s(p[2*i+1]); + g_code = shl(p[2*i+1],g_code_shl); + g_code = mult_r(g_code, gcode0_gi); + BASOP_SATURATE_WARNING_OFF /* needed to skip overflow warnings due to exceeding shift values */ + L_tmp = L_shr(Mpy_32_16_1(L_mult(g_code, g_code),coeff2),shr_coeff2); + if (g_code_shl != 0) + L_tmp = L_shr(L_tmp,g_code_shl); + L_tmp = L_sub(L_tmp,L_shr(L_mult(g_code, coeff3),shr_coeff3)); + L_tmp = L_add(L_tmp,L_shr(Mpy_32_16_1(L_mult(g_code, p[2*i+0]), coeff4),shr_coeff4)); + if (g_code_shl != 0) + L_tmp = L_shr(L_tmp,g_code_shl); + /* Here, we use L_mult0 to compensate the factor 0.5 applied to coeff[1..4] before */ + L_tmp = L_add(L_tmp,L_shr(L_mult0(p[2*i+0],p[2*i+0]), shr_coeff0)); + L_tmp = L_sub(L_tmp,L_shr(L_mult(p[2*i+0], coeff1),shr_coeff1)); + L_tmp1= L_sub(L_tmp, dist_min); + BASOP_SATURATE_WARNING_ON + if (L_tmp1 < 0) + { + index = i; + move16(); + } + if (L_tmp1 < 0) + { + dist_min = L_min(L_tmp, dist_min); + } + } + index = add(index, min_index); + *gain_pit = t_qua_gain[2*index+0]; + move16(); + g_code = t_qua_gain[2*index+1]; + move16(); + + L_tmp = L_mult(g_code, gcode0); /* Q11*Q15 -> Q27 */ + exp_gcode0 = add(exp_gcode0,-11); + L_tmp = L_shl(L_tmp, exp_gcode0); /* Q27 -> Q16 */ + + + *gain_code = L_tmp; + move32(); + /* Q16/Q12 => Q5 */ + L_tmp = L_deposit_h(BASOP_Util_Divide3216_Scale(L_tmp,*gain_inov,&i)); + *past_gcode = L_shl(L_tmp,sub(i,15-12)); + + + return index; +} + +Word16 gain_enc_uv( /* o : quantization pitch index */ + const Word16 *code, /* i : algebraic excitation */ + const Word16 *code2, /* i : gaussian excitation */ + Word16 lcode, /* (i) : Subframe size in range: 40,64,80 */ + Word16 *gain_pit, /* o : quantized pitch gain */ + Word32 *gain_code, /* o : quantized codebook gain */ + Word32 *gain_code2, /* o : quantized codebook gain */ + Word8 noisy_speech_flag, /* (i) : noisy speech flag */ + ACELP_CbkCorr *g_coeff, /* i : correlations , -2,, -2 and 2 */ + Word16 mean_ener, /* (i) : only func=0: mean_ener defined in open-loop (3 bits) */ + Word32 *past_gcode, /* o : past gain of code */ + Word16 *gain_inov, /* (o) : Q12 innovation gain */ + const Word16 func_type /* (i) : algorithm: 2=gain_enc_uv, 3=gain_enc_gacelp_uv */ +) +{ + Word16 i, index, exp_L_tmp1, tmp; + Word16 exp_gcode; + Word16 g_code; + Word32 L_tmp, L_tmp1; + Word8 gacelp_uv; + Word32 pred_nrg_frame; + Word16 exp_gcode2, g_code2, norm_code2; + Word16 c, c_e, c_index2, c_index2_e, c_first, c_first_e; + Word16 s, tmp1, s1; + Word16 index2; + const Word16 log2_scale=16; + + pred_nrg_frame = 0; /* to suppress compilation warnings */ + g_code2 = 0; /* to suppress compilation warnings */ + exp_gcode2 = 0; /* to suppress compilation warnings */ + + + assert((func_type != FUNC_GAIN_ENC_MLESS) ); + + /* Debug check value (not instrumented) */ + index2 = -3000; + move16(); + + gacelp_uv = 0; + move16(); + if (EQ_16(func_type, FUNC_GAIN_ENC_GACELP_UV)) + { + gacelp_uv = 1; + move16(); + } + + /*----------------------------------------------------------------* + * - calculate the unscaled innovation energy + * - calculate the predicted gain code + *----------------------------------------------------------------*/ + + /* gain_inov = 1.0f / sqrt((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */ + L_tmp = calc_gain_inov(code, lcode, NULL, NULL); + *gain_inov = round_fx(L_shl(L_tmp, 15-3)); /* gain_inov in Q12 */ + + /*----------------------------------------------------------------* + * calculate the predicted gain code + *----------------------------------------------------------------*/ + IF (gacelp_uv != 0) + { + /* pred_nrg_frame = (float)pow(10.0,mean_ener/20.0); */ + L_tmp = L_mult(mean_ener, 10885/*0.166096f * 2 Q15*/); /* 6Q25 */ + pred_nrg_frame = BASOP_Util_InvLog2(L_sub(L_tmp, 503316480l/*15.f Q25*/)); /* 15Q16 */ + + /* gcode = pred_nrg_frame * (*gain_inov); */ + L_tmp = Mpy_32_16_1(pred_nrg_frame, *gain_inov); /* 18Q13 */ + i = norm_l(L_tmp); + g_code = round_fx(L_shl(L_tmp, i)); + exp_gcode = sub(18, i); + + /* norm_code2 = 1.0f / sqrt((dot_product(code2, code2, lcode) + 0.01f) / lcode); */ + L_tmp = calc_gain_inov(code2, lcode, NULL, NULL); + norm_code2 = round_fx(L_shl(L_tmp, 15-3)); /* Q12 */ + + /* g_code2 = pred_nrg_frame * norm_code2; */ + L_tmp = Mpy_32_16_1(pred_nrg_frame, norm_code2); /* 18Q13 */ + i = norm_l(L_tmp); + g_code2 = round_fx(L_shl(L_tmp, i)); + exp_gcode2 = sub(18, i); + } + ELSE + { + g_code = *gain_inov; + move16(); + exp_gcode = 3; + move16(); + } + + tmp = BASOP_Util_Divide1616_Scale(g_coeff->xy2, mult_r(g_coeff->y2y2, g_code), &i); /*Correlation based*/ + L_tmp = L_shl( L_deposit_h(tmp), add(i, sub(g_coeff->xy2_e, add(g_coeff->y2y2_e, add(exp_gcode, log2_scale)))) ); + /* exponent of L_tmp is 16, accounted below by adding log2(2^16) */ + + index = 0; + move16(); + + IF (L_tmp > 0) + { + /*index = (int)(((20.f*log10(g_code)+30.f)/1.9f)+0.5f))); */ + /* Since ((20*log10(x)+30)/1.9)+0.5 = 63 (max index) implies x is between 2^15 and 2^16, + L_tmp might saturate at 65535 and above. That is why log2_scale is 16. */ + tmp = BASOP_Util_lin2dB(L_tmp, 16, 0); /* Q8 */ + + IF (gacelp_uv != 0) + { + L_tmp = L_mult(add(tmp, 5120/*20.0f Q8*/), 26214/*1.0f/1.25f Q15*/); + } + ELSE + { + L_tmp = L_mult(add(tmp, 7680/*30.0f Q8*/), 17246/*1.0f/1.9f Q15*/); + } + + index = round_fx(L_shr(L_tmp, 8)); + index = s_max(0, s_min(63, index)); + if (gacelp_uv != 0) index = s_min(31, index); + } + + /* *gain_code= (float) pow(10.f,(((index*1.9f)-30.f)/20.f)); */ + + /*----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *----------------------------------------------------------------*/ + IF (gacelp_uv != 0) + { + L_tmp = L_mac(-111465139l/*-0.166096*20.0f Q25*/,shl(index, 16-7), 6803/*0.166096f*1.25f Q15*/); + } + ELSE + { + L_tmp = L_mac(-167197708l/*-0.166096*30.0f Q25*/,shl(index, 16-7), 10341/*0.166096f*1.9f Q15*/); + } + i = add(1,extract_l(L_shr(L_tmp, 25))); + L_tmp = L_lshl(L_tmp, 6); + L_tmp = L_and(0x7FFFFFFF, L_tmp); + + L_tmp = Pow2(30,round_fx(L_tmp)); + L_tmp = L_shl(L_tmp, i-(31-16)); /* Q16 */ + + IF (gacelp_uv != 0) + { + /* *past_gcode = L_tmp * pred_nrg_frame; */ + i = norm_l(L_tmp); + L_tmp1 = L_shl(L_tmp, i); + exp_L_tmp1 = sub(15, i); + + i = norm_l(pred_nrg_frame); + L_tmp1 = Mpy_32_32(L_tmp1, L_shl(pred_nrg_frame, i)); + exp_L_tmp1 = add(exp_L_tmp1, sub(15, i)); + + *past_gcode = L_shl(L_tmp1, sub(exp_L_tmp1, 15)); /* Q16 */ move32(); + } + ELSE + { + *past_gcode = L_tmp; /*unscaled gain*/ move32(); + } + + + *gain_code = L_shl(Mpy_32_16_1(*past_gcode, *gain_inov), 3); + move32(); + + *gain_pit = 0; + move16(); + + IF (gacelp_uv != 0) + { + /* c_first = 0.8f*g_coeff->xx - (*gain_code) * (*gain_code) * g_coeff->y2y2; */ + /* c_first = g_coeff->xx - (*gain_code) * (*gain_code) * g_coeff->y2y2; */ + tmp = g_coeff->xx; + move16(); + if (noisy_speech_flag != 0) + { + tmp = mult_r(26214/*0.8f Q15*/, tmp); + } + + s1 = norm_l(*gain_code); + tmp1 = round_fx(L_shl(*gain_code, s1)); + s1 = sub(15, s1); + tmp1 = mult_r(mult_r(tmp1, tmp1), g_coeff->y2y2); + + c_first_e = BASOP_Util_Add_MantExp(tmp, g_coeff->xx_e, + negate(tmp1), add(g_coeff->y2y2_e, shl(s1, 1)), + &c_first); + + L_tmp = Mpy_32_16_1(*gain_code, BASOP_Util_Divide1616_Scale(g_code2, g_code, &s)); + L_tmp = L_shl(L_tmp, sub(sub(add(s, exp_gcode2), exp_gcode), 2)); /* Q16 */ + L_tmp1 = L_add(L_tmp, 0); + + s1 = norm_l(*gain_code); + tmp1 = round_fx(L_shl(*gain_code, s1)); + s1 = sub(15, s1); + + c_index2 = 0x7FFF; + move16(); + c_index2_e = 127; + move16(); + FOR (i = 0; i < 4; i++) + { + /* c = c_first - L_tmp1 * (L_tmp1 * g_coeff->y1y1 + 2 * (*gain_code) * g_coeff->y1y2); */ + s = norm_l(L_tmp1); + tmp = round_fx(L_shl(L_tmp1, s)); + s = sub(15, s); + + c_e = BASOP_Util_Add_MantExp(mult_r(tmp, g_coeff->y1y1), add(s, g_coeff->y1y1_e), + mult_r(tmp1, g_coeff->y1y2), add(add(s1, g_coeff->y1y2_e), 1), + &c); + c = mult_r(c, tmp); + c_e = add(c_e, s); + c_e = BASOP_Util_Add_MantExp(c_first, c_first_e, negate(c), c_e, &c); + + tmp = 0; + move16(); + if (LT_16(c_e, c_index2_e)) + { + tmp = 1; + move16(); + } + test(); + if (EQ_16(c_e, c_index2_e)&<_16(abs_s(c),abs_s(c_index2))) + { + tmp = 1; + move16(); + } + + IF (tmp != 0) + { + index2 = i; + move16(); + c_index2 = c; + move16(); + c_index2_e = c_e; + move16(); + *gain_code2 = L_tmp1; + move32(); + } + + L_tmp1 = L_add(L_tmp1, L_tmp); + } + + /* check if value was uninitialized */ + assert(index2 != -3000); + index = add(index, shl(index2, 5)); + } + + + return index; +} + diff --git a/lib_enc/qlpc_avq.c b/lib_enc/qlpc_avq.c new file mode 100644 index 0000000..afc09f7 --- /dev/null +++ b/lib_enc/qlpc_avq.c @@ -0,0 +1,332 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include +#include "stl.h" +#include "control.h" +#include "prot_fx.h" + + +/* Prototypes */ + +void qlpc_avq( + const Word16 *lsf, /* (i) Input LSF vectors (14Q1*1.28) */ + const Word16 *lsfmid, /* (i) Input LSF vectors (14Q1*1.28) */ + Word16 *lsf_q, /* (o) Quantized LFS vectors (14Q1*1.28) */ + Word16 *lsfmid_q, /* (o) Quantized LFS vectors (14Q1*1.28) */ + Word16 *index, /* (o) Quantization indices */ + Word16 *nb_indices, /* (o) Number of quantization indices */ + Word16 *nbbits, /* (o) Number of quantization bits */ + const Word16 core, /* (i) TCX10 or TCX20 */ + Word32 sr_core +) +{ + Word16 i; + Word16 lsfmid_q0[M]; + Word16 *tmp_index, indxt[256], nit, nbits, nbt; + Word16 dummy[M]; + + + /* Init */ + tmp_index = &index[0]; + *nb_indices = 0; + move16(); + + tmp_index[0] = vlpc_1st_cod(lsf, lsf_q, dummy, 0); + + nbt = vlpc_2st_cod(lsf, lsf_q, &tmp_index[1], 0, sr_core); + + /*nit = 1 + 2 + index[1] + index[2]; nit < NPRM_LPC_NEW(=50) */ + nit = add(add(3,index[1]),index[2]); + assert(nit < NPRM_LPC_NEW); + + /*tmp_index += nit;*/ + tmp_index = tmp_index + nit; + /**nb_indices += nit;*/ + *nb_indices = add(*nb_indices,nit); + move16(); + /*nbbits[0] = 8 + nbt;*/ + nbbits[0] = add(8,nbt); + move16(); + + *tmp_index = 0; + move16(); + + IF (EQ_16(core, TCX_20_CORE)) + { + + return; + } + + /* Quantize intermediate LPC (512 framing) */ + tmp_index++; + /**nb_indices +=1;*/ + *nb_indices = add(*nb_indices,1); + move16(); + + /* LPC2: Abs? */ + tmp_index[0] = vlpc_1st_cod(lsfmid, lsfmid_q, dummy, 0); + + nbits = vlpc_2st_cod(lsfmid, lsfmid_q, &tmp_index[1], 0, sr_core); + /*nbt = 8 + nbits;*/ + nbt = add(8,nbits); + /*nit = 1 + 2 + tmp_index[1] + tmp_index[2];*/ + nit = add(add(3,tmp_index[1]),tmp_index[2]); + + /* LPC2: RelR? */ + FOR (i=0; i 0; ind--) + { + push_next_indice_fx(st, 1, 1); + nb_bits = add(nb_bits, 1); + } + + /* Stop bit */ + push_next_indice_fx(st, 0, 1); + + return(nb_bits); +} + +static Word16 unpack4bits(Word16 nbits, const Word16 *prm, Encoder_State_fx *st) +{ + Word16 i; + + IF (nbits == 0) + { + push_next_indice_fx(st, 0, 0); + i = 1; + move16(); + } + ELSE + { + move16(); + i=0; + + FOR ( ; nbits > 4; nbits -= 4) + { + push_next_indice_fx(st, prm[i], 4); + i = add(i, 1); + } + push_next_indice_fx(st, prm[i], nbits); + i = add(i, 1); + } + + return(i); +} +Word16 encode_lpc_avq( Encoder_State_fx *st, Word16 numlpc, Word16 *param_lpc, Word16 mode ) +{ + Word16 k,j; + Word16 q_type, nb_ind; + Word16 i,qn1,qn2,nb,avqBits,st1; + Word16 nb_bits; + + move16(); + move16(); + move16(); + st1=0; + j = 0; + nb_bits = 0; + + FOR (k=0; k 0) + { + unary_code(nb, st); + } + nb_bits = add(nb_bits, nb); + + move16(); + nb = qn2; + + IF ( GT_16(nb,6)) + { + nb = sub(nb, 3); + } + ELSE IF ( GT_16(nb,4)) + { + nb = sub(nb, 4); + } + ELSE IF (nb == 0) + { + move16(); + nb = 3; + } + ELSE + { + move16(); + nb = 0; + } + + IF (nb > 0) + { + unary_code(nb, st); + } + nb_bits = add(nb_bits, nb); + + avqBits = shl(qn1,2); + unpack4bits(avqBits, ¶m_lpc[j], st); + j = add(j, qn1); + nb_bits = add(nb_bits, avqBits); + + avqBits = shl(qn2, 2); + unpack4bits(avqBits, ¶m_lpc[j], st); + j = add(j, qn2); + nb_bits = add(nb_bits, avqBits); + } + ELSE + { + j = add(j, nb_ind); + } + } + + return(nb_bits); +} + diff --git a/lib_enc/qlpc_stoch.c b/lib_enc/qlpc_stoch.c new file mode 100644 index 0000000..5efa7fd --- /dev/null +++ b/lib_enc/qlpc_stoch.c @@ -0,0 +1,437 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include + +#include "cnst_fx.h" +#include "rom_enc_fx.h" +#include "rom_com_fx.h" +#include "stl.h" +#include "prot_fx.h" +#include "basop_util.h" +#include "rom_basop_util.h" + + + +void lpc_quantization( + Encoder_State_fx * st, + const Word16 core, + const Word16 lpcQuantization, + const Word16 lsfold_q[], + const Word16 lsp[], + const Word16 lspmid[], + Word16 lsp_q[], + Word16 lsf_q[], /* 14Q1*1.28 */ + Word16 lspmid_q[], + Word16 lspq_ind[], + Word16 clip_var[], + Word16 mem_MA[], + Word16 mem_AR[], + const Word8 narrowBand, + const Word16 coder_type, + const Word8 acelp_midLpc, + Word16 param_lpc[], + Word16 nbits_lpc[], + Word16 * bits_param_lpc, + Word16 *no_param_lpc, + Word16 *seed_acelp, + Word32 * Bin_Ener, + Word32 * Bin_Ener_old, + const Word16 Q_ener +) +{ + + Word16 nb_indices; + Word16 lsfmid_q[M]; /* 14Q1*1.28 */ + Word16 lsfmid_idx; + Word16 i, force_sf; + Word16 lsf[M], lsfmid[M]; + + Word16 fec_lsf[M], stab; + + nb_indices = 0; + move16(); + + /****** High-rate LPC quantizer *******/ + + IF (lpcQuantization==0) + { + E_LPC_lsp_lsf_conversion(lsp, lsf, M); + + /* check resonance for pitch clipping algorithm */ + gp_clip_test_lsf_fx( lsf, clip_var, M ); + + IF ( (EQ_16(core, TCX_10_CORE))) + { + E_LPC_lsp_lsf_conversion(lspmid, lsfmid, M); + } + + /* LPC quantizer */ + qlpc_avq(lsf, lsfmid, lsf_q, lsfmid_q, param_lpc, &nb_indices, nbits_lpc, core, st->sr_core); + + E_LPC_lsf_lsp_conversion(lsf_q, lsp_q, M); + + IF( EQ_16(core, TCX_10_CORE)) + { + E_LPC_lsf_lsp_conversion( lsfmid_q, lspmid_q, M ); + } + + /* assert(nb_indices<=NPRM_LPC_NEW); */ + } + + /****** Low-rate LPC quantizer *******/ + + ELSE IF ( EQ_16(lpcQuantization, 1)) + { + lsp2lsf_fx(lsp, lsf, M, extract_l(st->sr_core)); + + gp_clip_test_lsf_fx( lsf, clip_var, M ); + + force_sf = 0; + move16(); + /*Force safety net when possible in case of transitions*/ + test(); + test(); + IF( st->tc_cnt_fx >= 1 || LE_32(st->last_core_brate_fx,SID_2k40)||(EQ_16(st->next_force_safety_net_fx,1))) + { + force_sf = 1; + move16(); + st->next_force_safety_net_fx = 0; + move16(); + } + + test(); + IF ( EQ_16(st->next_force_safety_net_fx,1)&&EQ_16(st->Opt_RF_ON,1)) + { + force_sf = 1; + st->next_force_safety_net_fx = 0; + } + + test(); + IF ( EQ_32(st->sr_core, INT_FS_16k)&&EQ_16(coder_type,UNVOICED)) + { + lsf_end_enc_fx( st, lsf, lsf_q, mem_AR, mem_MA, ENDLSF_NBITS, GENERIC, st->bwidth_fx, Bin_Ener, Q_ener, st->sr_core, st->core_brate_fx, + &st->streaklimit_fx, &st->pstreaklen_fx, force_sf, 0, + 1, param_lpc, no_param_lpc, bits_param_lpc, GENERIC ); + + nb_indices = *no_param_lpc; + } + ELSE + { + lsf_end_enc_fx( st, lsf, lsf_q, mem_AR, mem_MA, ENDLSF_NBITS, coder_type, st->bwidth_fx, Bin_Ener, Q_ener, st->sr_core, st->core_brate_fx, + &st->streaklimit_fx, &st->pstreaklen_fx, force_sf, 0, + 1, param_lpc, no_param_lpc, bits_param_lpc, coder_type ); + + nb_indices = *no_param_lpc; + } + + + FEC_lsf_estim_enc_fx( st, st->L_frame_fx, fec_lsf ); + + /* FEC - calculate LSF stability */ + stab = lsf_stab_fx( lsf_q, fec_lsf, 0, st->L_frame_fx); /*Q15*/ + + + test(); + test(); + test(); + IF ( LT_16(stab,add(STAB_FAC_LIMIT_FX, 6553/* =0.2 in Q15*/))&& + ( EQ_16(coder_type,VOICED) || EQ_16(coder_type,GENERIC) ) && EQ_16(st->Opt_RF_ON,1 )) + { + st->next_force_safety_net_fx = 1; + } + + lsf2lsp_fx(lsf_q, lsp_q, M, st->sr_core); + + *nbits_lpc = ENDLSF_NBITS; + move16(); + + } + ELSE + { + assert(0); + } + + IF (lspq_ind != NULL) + { + E_LPC_lsf_lsp_conversion( lsf_q, lspq_ind, M ); + } + + *seed_acelp=0; + move16(); + FOR(i=nb_indices-1; i>=0; i--) + { + *seed_acelp = extract_l(L_mac0(L_mac0(13849, shr(*seed_acelp, 1), 31821), param_lpc[i], 31821)); + move16(); + } + + /* Mid-frame LPC quantization */ + + test(); + IF(lpcQuantization && acelp_midLpc) + { + + IF(st->rate_switching_reset==0) + { + lsp2lsf_fx(lspmid, lsfmid, M, extract_l(st->sr_core)); + + midlsf_enc ( lsfold_q, lsf_q, lsfmid, &lsfmid_idx, M, Bin_Ener_old, Q_ener, narrowBand, st->sr_core, coder_type ); + param_lpc[nb_indices++] = lsfmid_idx; + move16(); + midlsf_dec (lsfold_q, lsf_q, lsfmid_idx, lsfmid_q, coder_type + ,NULL,0,1 + ); + + reorder_lsf_fx( lsfmid_q, LSF_GAP_MID_FX, M, st->sr_core ); + lsf2lsp_fx(lsfmid_q, lspmid_q, M, st->sr_core); + } + ELSE + { + param_lpc[nb_indices++] = 0; + move16(); + } + } + + + + return; +} + + + +#define MIN_LOG_FX 0 +#define MIN_LOG_VAL_FX -15360 /* -60.0f in Q8 */ + +void Unified_weighting_fx( + Word32 Bin_Ener_128_fx[], /* i : FFT Bin energy 128 bins in two sets Q_ener */ + Word16 Q_ener, + const Word16 lsf_fx[], /* i : LSF vector x2.56 */ + Word16 w_fx[], /* o : LP weighting filter (numerator) Q8 */ + const Word16 narrowBand, /* i : flag for Narrowband */ + const Word16 unvoiced, /* i : flag for Unvoiced frame */ + const Word32 sr_core, /* i : sampling rate of core-coder */ + const Word16 order /* i : LP order */ +) +{ + Word16 i; + const Word16 (*ptr_lsf_fit_model)[M]; + Word16 last_bin; + /*float compen;*/ + + Word16 exp, frac; + Word16 w_fft_fx[M]/*, w_fx[M]*/; + Word16 norm_lsf_fx[M]; /* Q0 */ + Word16 tmp_fx, min_fx, tmp1_fx, tmp2_fx, s1, s2; + Word32 L_tmp; + Word16 nf_fx; + Word32 Bin_Ener_160_fx[160]; + Word32 *Bin_Ener_fx; + const Word32 *Freq_w_Table_fx; + + + /*Config. weighting*/ + IF ( narrowBand ) + { + ptr_lsf_fit_model = lsf_unified_fit_model_nb; + nf_fx = 16384; + move16(); /* x2.56 */ + + last_bin = 127; + move16(); + Bin_Ener_fx = Bin_Ener_128_fx; + } + ELSE IF( EQ_32(sr_core, 12800)) + { + ptr_lsf_fit_model = lsf_unified_fit_model_wb; + nf_fx = 16384; + move16(); /* x2.56 */ + + last_bin = 127; + move16(); + Bin_Ener_fx = Bin_Ener_128_fx; + } + ELSE + { + ptr_lsf_fit_model = lsf_unified_fit_model_wbhb; + nf_fx = 20480; + move16(); /* x2.56 */ + + /* Fill the missing part (128~159) of the bin energy */ + last_bin = 159; + move16(); + + Copy32(Bin_Ener_128_fx, Bin_Ener_160_fx, L_FFT/2); + + /* Find average bin energy (32 Energy) */ + L_tmp = L_deposit_l(0); + FOR ( i=95; i<127; i++ ) + { + L_tmp = L_add(L_tmp, Bin_Ener_160_fx[i]); + } + + L_tmp = L_shr(L_tmp, 5); + FOR ( i=127; i<160; i++ ) + { + Bin_Ener_160_fx[i] = L_tmp; + move32(); + } + + Bin_Ener_fx = Bin_Ener_160_fx; + } + + /* 1) FFT weights*/ + Freq_w_Table_fx = Freq_Weight_Com_fx; + if ( unvoiced ) + { + Freq_w_Table_fx = Freq_Weight_UV_fx; + } + + /* Use Envelope */ + min_fx = MAX_16; + move16(); + FOR ( i=0; i 0) + { + tmp1_fx = sub(tmp1_fx, lsf_fx[i-1]); + } + + tmp2_fx = nf_fx; + move16(); + if (NE_16(i, order - 1)) + { + tmp2_fx = lsf_fx[i+1]; + move16(); + } + tmp2_fx = sub(tmp2_fx, lsf_fx[i]); + + s1 = 15; + move16(); + s2 = 15; + move16(); + if(tmp1_fx == 0) + { + tmp1_fx = 8; + } + tmp1_fx = Inv16(tmp1_fx, &s1); + if(tmp2_fx == 0) + { + tmp2_fx = 8; + } + tmp2_fx = Inv16(tmp2_fx, &s2); + s1 = BASOP_Util_Add_MantExp(tmp1_fx, s1, tmp2_fx, s2, &tmp1_fx); /* x * 2.56 / pow(2.0, 15 + |s1|) */ + tmp_fx = mult_r(nf_fx, 10430); + s2 = norm_s(tmp_fx); + tmp_fx = shl(tmp_fx, s2); + s1 = sub(s1, s2); + + tmp1_fx = mult_r(tmp1_fx, tmp_fx); /* |s1| */ + s1 = abs_s(s1); + + /* 3) Fitting model combining the two weights*/ + L_tmp = L_add(ptr_lsf_fit_model[0][i], 0); /* Q10 */ + L_tmp = L_add(L_tmp, L_shl(L_mult0(ptr_lsf_fit_model[1][i], tmp1_fx), sub(-5, s1))); /* Q10 */ + L_tmp = L_add(L_tmp, L_shl(L_mult0(mult_r(tmp1_fx, tmp1_fx), ptr_lsf_fit_model[2][i]), sub(7, shl(s1, 1)))); + L_tmp = L_add(L_tmp, L_shl(L_mult0(w_fft_fx[i], ptr_lsf_fit_model[3][i]), -12)); + move16(); /* Q10 */ + + IF ( LT_32( L_shl( L_tmp, 5), InvIntTable[i+1] )) + { + w_fx[i] = shr( InvIntTable[i+1], 7); + move16(); + } + ELSE + { + IF( norm_l( L_tmp ) < 14 ) + { + w_fx[i] = MAX_16; + move16(); + } + ELSE + { + w_fx[i] = extract_l( L_shr( L_tmp, 2 ) ); + } + } + } + + return; +} diff --git a/lib_enc/range_enc_fx.c b/lib_enc/range_enc_fx.c new file mode 100644 index 0000000..95a4fa8 --- /dev/null +++ b/lib_enc/range_enc_fx.c @@ -0,0 +1,297 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ + +#include "stl.h" + +static void rc_enc_shift_fx(Encoder_State_fx *st_fx); +static void rc_enc_write_fx(Encoder_State_fx *st_fx, Word16 byte, Word16 bits); + +/*-------------------------------------------------------------------* + * rc_enc_init() + * + * Initalize range coder + *-------------------------------------------------------------------*/ + +void rc_enc_init_fx( + Encoder_State_fx *st_fx, /* i/o: Encoder state */ + Word16 tot_bits /* i : Total bit budget */ +) +{ + st_fx->rc_low_fx = L_deposit_l(0); + st_fx->rc_range_fx = 0xffffffff; + move32(); + st_fx->rc_cache_fx = -1; + move16(); + st_fx->rc_carry_fx = 0; + move16(); + st_fx->rc_carry_count_fx = 0; + move16(); + st_fx->rc_num_bits_fx = 0; + move16(); + st_fx->rc_tot_bits_fx = tot_bits; + move16(); + st_fx->rc_offset_fx = 0; + move16(); + + return; +} + +/*-------------------------------------------------------------------* + * rc_encode() + * + * Encode symbol with range coder + *-------------------------------------------------------------------*/ + +void rc_encode_fx( + Encoder_State_fx *st_fx, /* i/o: Encoder state */ + UWord32 cum_freq, /* i : Cumulative frequency up to symbol */ + UWord32 sym_freq, /* i : Symbol probability */ + UWord32 tot /* i : Total cumulative frequency */ +) +{ + UWord32 r, tmp, inv_tot, lsb; + Word16 exp; + UWord16 carry; + + inv_tot = UL_inverse(tot, &exp); + Mpy_32_32_uu(st_fx->rc_range_fx, inv_tot, &tmp, &lsb); /*0+exp-32 */ + r = UL_lshr(tmp, sub(exp, 32)); /* exp-32-exp3+32 = 0 */ + tmp = UL_Mpy_32_32(r, cum_freq); + + st_fx->rc_low_fx = UL_addNs(st_fx->rc_low_fx, tmp, &carry); + if (carry != 0) + { + st_fx->rc_carry_fx = carry; + move16(); + } + + st_fx->rc_range_fx = UL_Mpy_32_32(r, sym_freq); + + WHILE (st_fx->rc_range_fx < 1<<24) + { + L_sub(0, 0); /* Comparison in while */ + st_fx->rc_range_fx = UL_lshl(st_fx->rc_range_fx, 8); + st_fx->rc_num_bits_fx = add(st_fx->rc_num_bits_fx, 8); + rc_enc_shift_fx(st_fx); + } + + return; +} + +/*-------------------------------------------------------------------* + * rc_enc_finish() + * + * Finalize range coder + *-------------------------------------------------------------------*/ + +void rc_enc_finish_fx( + Encoder_State_fx *st_fx /* i/o: Encoder state */ +) +{ + UWord32 val, mask, high; + Word16 bits; + UWord16 over1, over2; + + bits = add(norm_ul(st_fx->rc_range_fx), 1); + mask = UL_lshr(0xffffffff, bits); + + val = UL_addNs(st_fx->rc_low_fx, mask, &over1); + high = UL_addNs(st_fx->rc_low_fx, st_fx->rc_range_fx, &over2); + + val = L_and(val, ~mask); + L_xor(0,0); /* For bit not */ + + IF ( (L_xor(over1, over2)) == 0 ) + { + L_sub(0, 0); /* For comparision in if */ + IF (UL_addNsD(val, mask) >= high) + { + bits = add(bits, 1); + mask = UL_lshr(mask, 1); + val = UL_and(UL_addNsD(st_fx->rc_low_fx, mask), ~mask); + L_xor(0,0); /* For bit not */ + } + + if (val < st_fx->rc_low_fx) + { + st_fx->rc_carry_fx = 1; + move16(); + } + } + + st_fx->rc_low_fx = val; + move32(); + + IF ( GT_16(bits, sub(st_fx->rc_tot_bits_fx, st_fx->rc_num_bits_fx))) + { + bits = sub(st_fx->rc_tot_bits_fx, st_fx->rc_num_bits_fx); + + } + + st_fx->rc_num_bits_fx = add(st_fx->rc_num_bits_fx, bits); + FOR ( ; bits > 0; bits -= 8) + { + rc_enc_shift_fx(st_fx); + } + bits = add(bits, 8); + + IF ( st_fx->rc_carry_count_fx > 0 ) + { + rc_enc_write_fx(st_fx, add(st_fx->rc_cache_fx, st_fx->rc_carry_fx), 8); + + FOR ( ; st_fx->rc_carry_count_fx > 1; st_fx->rc_carry_count_fx--) + { + rc_enc_write_fx(st_fx, (st_fx->rc_carry_fx + 0xff), 8); + } + rc_enc_write_fx(st_fx, s_and(add(st_fx->rc_carry_fx, 0xff), sub(lshl(1, bits), 1)), bits); + } + ELSE + { + rc_enc_write_fx(st_fx, lshr(add(st_fx->rc_cache_fx, st_fx->rc_carry_fx), sub(8, bits)), bits); + } + + bits = st_fx->rc_num_bits_fx; + move16(); + WHILE (LT_16(bits, sub(st_fx->rc_tot_bits_fx, 16))) + { + rc_enc_write_fx(st_fx, 0, 16); + bits = add(bits, 16); + } + + bits = sub(st_fx->rc_tot_bits_fx, bits); + IF (bits > 0) + { + rc_enc_write_fx(st_fx, 0, bits); + } + + return; +} + +/*-------------------------------------------------------------------* + * rc_enc_shift() + * + * Shift a byte out to bitstream + *-------------------------------------------------------------------*/ + +static void rc_enc_shift_fx( + Encoder_State_fx *st_fx /* i/o: Encoder state */ +) +{ + test(); + L_sub(0, 0); /* For comparision in if */ + IF (st_fx->rc_low_fx < (0xff000000UL) || EQ_16(st_fx->rc_carry_fx, 1)) + { + IF (st_fx->rc_cache_fx >= 0) + { + rc_enc_write_fx(st_fx, add(st_fx->rc_cache_fx, st_fx->rc_carry_fx), 8); + } + + WHILE (st_fx->rc_carry_count_fx > 0) + { + rc_enc_write_fx(st_fx, s_and(add(st_fx->rc_carry_fx, 0xff), 255), 8); + st_fx->rc_carry_count_fx = sub(st_fx->rc_carry_count_fx, 1); + } + + st_fx->rc_cache_fx = u_extract_l(UL_lshr(st_fx->rc_low_fx, 24)); + st_fx->rc_carry_fx = 0; + move16(); + } + ELSE + { + st_fx->rc_carry_count_fx = add(st_fx->rc_carry_count_fx, 1); + } + st_fx->rc_low_fx = UL_lshl(st_fx->rc_low_fx, 8); + + return; +} + +/*-------------------------------------------------------------------* + * rc_enc_bits() + * + * + *-------------------------------------------------------------------*/ + +void rc_enc_bits_fx( + Encoder_State_fx *st_fx, /* i/o: Encoder state */ + UWord32 value, /* i : Value to encode */ + Word16 bits /* i : Number of bits used */ +) +{ + IF ( LE_16(add(rc_get_bits2_fx(st_fx->rc_num_bits_fx, st_fx->rc_range_fx), bits), st_fx->rc_tot_bits_fx)) + { + st_fx->rc_num_bits_fx = add(st_fx->rc_num_bits_fx, bits); + + IF ( GT_16(bits, 16)) + { + push_indice_fx(st_fx, sub(IND_RC_END, st_fx->rc_offset_fx), u_extract_l(UL_lshr(value, 16)), sub(bits, 16)); + st_fx->rc_offset_fx = add(st_fx->rc_offset_fx, 1); + push_indice_fx(st_fx, sub(IND_RC_END, st_fx->rc_offset_fx), u_extract_l(UL_and(value, 0x0000ffff)), 16); + st_fx->rc_offset_fx = add(st_fx->rc_offset_fx, 1); + } + ELSE + { + push_indice_fx(st_fx, sub(IND_RC_END, st_fx->rc_offset_fx), u_extract_l(value), bits); + st_fx->rc_offset_fx = add(st_fx->rc_offset_fx, 1); + } + } + ELSE + { + } + + return; +} + +/*-------------------------------------------------------------------* + * rc_enc_uniform() + * + * Encode with uniform distribution + *-------------------------------------------------------------------*/ + +void rc_enc_uniform_fx( + Encoder_State_fx *st_fx, /* i/o: Encoder state */ + UWord32 value, /* i : Value to encode */ + UWord32 tot /* i : Maximum value */ +) +{ + Word16 n; + + n = sub(32, norm_ul(UL_subNsD(tot, 1))); + + IF (LE_16(n, 8)) + { + rc_encode_fx(st_fx, value, 1, tot); + } + ELSE + { + n = sub(n, 8); + rc_encode_fx(st_fx, UL_lshr(value, n), 1, UL_addNsD(UL_lshr(tot, n), 1)); + rc_enc_bits_fx(st_fx, UL_and(value, UL_subNsD(UL_lshl(1, n), 1)), n); + } + + return; +} + +/*-------------------------------------------------------------------* + * rc_enc_write() + * + * Write a byte to bitstream + *-------------------------------------------------------------------*/ + +static void rc_enc_write_fx( + Encoder_State_fx *st_fx, /* i/o: Encoder state */ + Word16 byte, /* i : Byte to write */ + Word16 bits /* i : Number of bits */ +) +{ + push_indice_fx(st_fx, IND_RC_START, byte, bits); + + return; +} diff --git a/lib_enc/re8_cod_fx.c b/lib_enc/re8_cod_fx.c new file mode 100644 index 0000000..59f98c2 --- /dev/null +++ b/lib_enc/re8_cod_fx.c @@ -0,0 +1,53 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" +#include "stl.h" + +/*------------------------------------------------------------------------ + * RE8_cod: + * + * MULTI-RATE INDEXING OF A POINT y in THE LATTICE RE8 (INDEX COMPUTATION) + * note: the index I is defined as a 32-bit word, but only + * 16 bits are required (long can be replaced by unsigned integer) + *--------------------------------------------------------------------------*/ + +void re8_cod_fx( + Word16 x[], /* i : point in RE8 (8-dimensional integer vector) */ + Word16 *n, /* i : codebook number (*n is an integer defined in {0,2,3,4,..,n_max}) */ + UWord16 *I, /* o : index of c (pointer to unsigned 16-bit word) */ + Word16 k[] /* o : index of v (8-dimensional vector of binary indices) = Voronoi index */ +) +{ + Word16 ka_fx, c_fx[8]; + /*---------------------------------------------------------------------- + * decompose x as x = 2^r c + v, where r is an integer >=0, c is an element + * of Q0, Q2, Q3 or Q4, and v is an element of a Voronoi code in RE8 + * (if r=0, x=c) + * this decomposition produces as a side-product the index k[] of v + * and the identifier ka of the absolute leader related to c + * + * the index of y is split into 2 parts : + * - the index I of c + * - the index k[] of v + ----------------------------------------------------------------------*/ + re8_vor_fx(x, n, k, c_fx, &ka_fx); + + /* safeguard in case that the AVQ subquantizer is not found - might happen for extremely strong onsets at the end of the frame */ + IF( GE_16(ka_fx,NB_LEADER)) + { + *n = 0; + move16(); + set16_fx( x, 0, 8 ); + } + + /* compute the index I (only if c is in Q2, Q3 or Q4) */ + IF (*n > 0) + { + re8_compute_base_index_fx(c_fx, ka_fx, I); + } + + return; +} diff --git a/lib_enc/reordernorm_fx.c b/lib_enc/reordernorm_fx.c new file mode 100644 index 0000000..187b08e --- /dev/null +++ b/lib_enc/reordernorm_fx.c @@ -0,0 +1,57 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" + +#include "prot_fx.h" +#include "stl.h" /* required for wmc_tool */ + +/*--------------------------------------------------------------------------*/ +/* Function reordernorm_fx */ +/* ~~~~~~~~~~~~~~~~~~~~~ */ +/* */ +/* Reorder quantization indices and norms */ +/*--------------------------------------------------------------------------*/ + +void reordernorm_fx( + const Word16 *ynrm, /* i : quantization indices for norms Q0 */ + const Word16 *normqlg2, /* i : quantized norms Q0 */ + Word16 *idxbuf, /* o : reordered quantization indices Q0 */ + Word16 *normbuf, /* o : reordered quantized norms Q0 */ + const Word16 nb_sfm /* i : number of bands Q0 */ +) +{ + Word16 i; + const Word16 *order = NULL; + + SWITCH(nb_sfm) + { + case NB_SFM: + order = norm_order_48; + BREAK; + case SFM_N_SWB: + order = norm_order_32; + BREAK; + case SFM_N_WB: + order = norm_order_16; + BREAK; + default: + order = norm_order_48; + BREAK; + } + + FOR (i = 0; i < nb_sfm; i++) + { + idxbuf[i] = ynrm[order[i]]; + move16(); + move16(); + normbuf[i] = normqlg2[order[i]]; + move16(); + move16(); + } + + return; +} diff --git a/lib_enc/rom_enc_fx.c b/lib_enc/rom_enc_fx.c new file mode 100644 index 0000000..25138d0 --- /dev/null +++ b/lib_enc/rom_enc_fx.c @@ -0,0 +1,696 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "stl.h" +#include "cnst_fx.h" /* Common constants */ +#include "rom_enc_fx.h" +#include "basop_util.h" + +/*----------------------------------------------------------------------------------* + * VAD tables + *----------------------------------------------------------------------------------*/ +const Word16 hangover_hd_tbl_fx[3] = {1, 1, 3}; +const Word16 hangover_sf_tbl_fx[6] = {1, 3, 4, 1, 1, 2}; + +const Word16 H_fir[] = { 4260, 7536, 9175, 7536, 4260 }; +const Word16 pit_max_12k8_fx[9] = { 11, 16, 21, 31, 40, 61, 77, 115, 115 }; + +const Word16 len_12k8_fx[4] = { 40, 40, 62, 115 } ; +const Word16 len1_12k8_fx[4] = { 40, 50, 80, 115 }; +const Word16 sublen_12k8_fx[7] = { 40, 40, 40, 62, 62, 115, 115 }; +const Word16 sublen1_12k8_fx[7] = { 40, 40, 50, 50, 80, 80, 115 } ; + +const Word16 sec_length_12k8_fx[4] = { 7, 15, 30, 54 }; +const Word16 sec_length1_12k8_fx[4] = { 10, 19, 37, 38 }; +const Word16 SF_mult_fx[N_FEATURES] = +{ + 20133, /*Q22*/ + 32767, /*Q15*/ + 20401, /*Q15*/ + 18013, /*Q15*/ + 16263, /*Q15*/ + 16545, /*Q15*/ + 16610, /*Q15*/ + 17197, /*Q22*/ + 18455, /*Q23*/ + 16515, /*Q18*/ + 17931, /*Q18*/ + 30382 /*Q18*/ +}; + +const Word32 SF_add_fx[N_FEATURES] = +{ + -798595, /*Q23*/ + 0, /*Q31*/ + -37312528, /*Q29*/ + -67914170, /*Q29*/ + -119722213, /*Q29*/ + -220278135, /*Q29*/ + -306929100, /*Q29*/ + 0, /*Q30*/ + -6227703, /*Q31*/ + 537676218, /*Q29*/ + 488713591, /*Q29*/ + -314713729 /*Q30*/ +}; + +const Word16 SF_8k_mult_fx[N_FEATURES] = +{ + 17197, /*Q22*/ + 28088, /*Q15*/ + 22082, /*Q15*/ + 20503, /*Q15*/ + 18006, /*Q15*/ + 18983, /*Q15*/ + 8199 , /*Q15*/ + 17197, /*Q22*/ + 16777, /*Q23*/ + 16515, /*Q18*/ + 15676, /*Q18*/ + 16541 /*Q18*/ +}; + +const Word32 SF_8k_add_fx[N_FEATURES] = +{ + 0, /*Q23*/ + 219043332, /*Q31*/ + -53687091, /*Q29*/ + -90086939, /*Q29*/ + -127775277, /*Q29*/ + -249430226, /*Q29*/ + 0, /*Q29*/ + 0, /*Q30*/ + 0, /*Q31*/ + 537676218, /*Q29*/ + 481412147, /*Q29*/ + 0 /*Q30*/ +}; + +const Word16 w_spmus_fx[HANG_LEN][HANG_LEN] = +{ + /*Q15*/ + {32767, 0, 0, 0, 0, 0, 0, 0,}, + {19661, 13107, 0, 0, 0, 0, 0, 0,}, + {15401, 10813, 6554, 0, 0, 0, 0, 0,}, + {13107, 9830, 6554, 3277, 0, 0, 0, 0,}, + { 9830, 8192, 6554, 4915, 3277, 0, 0, 0,}, + { 7635, 6783, 5898, 5014, 4162, 3277, 0, 0,}, + { 7700, 6717, 5702, 4686, 3670, 2654, 1638, 0,}, + { 6554, 5865, 5145, 4456, 3736, 3047, 2327, 1638} +}; +const Word16 m_speech_fx[N_MIXTURES*N_FEATURES] = +{ + /*Q15*/ + 9436, 29987, 4795, 7076, 11050, 13645, 15206, 15194, 1936, 27952, 25172, 10301, + 10057, 30685, 8381, 9965, 10762, 8680, 11589, 15788, 1641, 26751, 27163, 10992, + 7927, 31230, 7191, 8505, 14304, 16336, 14972, 16077, 2052, 27271, 27694, 10859, + 13914, 17323, 10682, 16458, 17807, 18403, 19368, 12665, 2205, 29598, 29213, 11285, + 12468, 23848, 6880, 10301, 13824, 13066, 14647, 13189, 3451, 28442, 28766, 10410, + 11304, 21566, 7894, 11411, 14194, 15739, 16351, 13744, 6130, 28445, 28034, 11380 +}; +const Word32 invV_speech_fx[N_MIXTURES*N_FEATURES*N_FEATURES] = +{ + /*Q10*/ + -40443, -14756, -39560, -18113, 8983, -11676, 450, -10588, -49908, 358, 17222, 32914, + -14756, -200610, -27679, -28092, -16846, -6393, 5954, 13058, -67051, -47861, -8575, 18740, + -39560, -27679, -772035, 118158, -48299, 27758, -37782, 74336, -305470, -23323, 181510, 91957, + -18113, -28092, 118158, -228070, 41104, -46248, 21977, 8161, -27789, 78357, 26088, 39736, + 8983, -16846, -48299, 41104, -96670, 41164, -18208, 3995, -14774, 23704, 13802, 17925, + -11676, -6393, 27758, -46248, 41164, -95654, 58562, 3668, 103, 5952, 9479, 11083, + 450, 5954, -37782, 21977, -18208, 58562, -91964, -5597, -47161, -15941, 14870, 11028, + -10588, 13058, 74336, 8161, 3995, 3668, -5597, -102767, 25363, -21490, -48411, 13509, + -49908, -67051, -305470, -27789, -14774, 103, -47161, 25363, -1410848, -57997, 238792, -117641, + 358, -47861, -23323, 78357, 23704, 5952, -15941, -21490, -57997, -221932, -936, 40579, + 17222, -8575, 181510, 26088, 13802, 9479, 14870, -48411, 238792, -936, -157118, -49202, + 32914, 18740, 91957, 39736, 17925, 11083, 11028, 13509, -117641, 40579, -49202, -321159, + -54755, -48603, -918, -25735, 31634, -27972, 23305, -18449, -68162, -3670, -7982, 35965, + -48603, -449238, -11496, -14811, 12790, -11453, 2686, -3752, -86924, -30083, -54695, 17457, + -918, -11496, -258042, 157642, 4617, 27546, -22677, 7281, -221085, -48457, 80126, 16406, + -25735, -14811, 157642, -334462, 64217, 7724, 24309, 20322, -99420, 2896, 76924, 35785, + 31634, 12790, 4617, 64217, -296101, 182629, -27282, 11581, -10495, 16901, 50011, 20823, + -27972, -11453, 27546, 7724, 182629, -274190, 15505, 4345, -7824, 79496, -2218, 12832, + 23305, 2686, -22677, 24309, -27282, 15505, -73195, 2055, -4690, 31413, 15447, 8774, + -18449, -3752, 7281, 20322, 11581, 4345, 2055, -77913, 57514, -8586, -106171, 6233, + -68162, -86924, -221085, -99420, -10495, -7824, -4690, 57514, -1966183, -9074, 512909, -17375, + -3670, -30083, -48457, 2896, 16901, 79496, 31413, -8586, -9074, -185355, -15990, 8445, + -7982, -54695, 80126, 76924, 50011, -2218, 15447, -106171, 512909, -15990, -444405, -71821, + 35965, 17457, 16406, 35785, 20823, 12832, 8774, 6233, -17375, 8445, -71821, -222292, + -96397, -65745, 316, -47258, 43061, -42973, 10442, -19582, -43973, -19682, -21732, 48029, + -65745, -838575, 30816, -43250, 6642, -4487, 11239, 338, -17329, -59741, -114530, -1706, + 316, 30816, -351192, 207585, -68100, 60838, -83672, 14796, -158998, 13313, 122647, 38113, + -47258, -43250, 207585, -322741, 76525, -99711, 59838, 20166, -63534, 7136, 76247, 22923, + 43061, 6642, -68100, 76525, -96244, 54110, -21689, 2401, -36455, -19725, 38782, 6802, + -42973, -4487, 60838, -99711, 54110, -284964, 220150, -642, -44874, -21815, 16040, 3963, + 10442, 11239, -83672, 59838, -21689, 220150, -239817, 2018, -17214, -1904, 16387, 4095, + -19582, 338, 14796, 20166, 2401, -642, 2018, -58537, 20742, -9245, -85094, 8867, + -43973, -17329, -158998, -63534, -36455, -44874, -17214, 20742, -1009892, 28181, 407531, -10963, + -19682, -59741, 13313, 7136, -19725, -21815, -1904, -9245, 28181, -186118, -32487, 5665, + -21732, -114530, 122647, 76248, 38782, 16040, 16387, -85094, 407531, -32487, -511009, -66277, + 48029, -1706, 38113, 22923, 6802, 3963, 4095, 8867, -10963, 5665, -66277, -251113, + -21146, 1393, -2365, 3756, -4538, -1528, 2298, -6668, -7599, -2720, -5226, 3049, + 1393, -46612, -28502, 11801, -5967, 8395, -4182, 13773, 18586, -9799, -6696, -3522, + -2365, -28502, -77446, 55688, -10615, 10476, -6282, 5520, -19365, 8818, -4576, 2603, + 3756, 11801, 55688, -152293, 104577, -8742, 15278, -2773, 16622, -12382, -2828, 5452, + -4538, -5967, -10615, 104577, -245151, 117173, -5020, 3412, -2855, -19929, 9729, 1888, + -1528, 8395, 10476, -8742, 117173, -258943, 136249, -2960, -8257, -20123, -6735, -6316, + 2298, -4182, -6282, 15278, -5020, 136249, -192889, 889, -6047, -74906, 15861, 4026, + -6668, 13773, 5520, -2773, 3412, -2960, 889, -298321, 8558, 5827, -66886, -3080, + -7599, 18586, -19365, 16622, -2855, -8257, -6047, 8558, -837495, -36576, 477123, -58582, + -2720, -9799, 8818, -12382, -19929, -20123, -74906, 5827, -36576, -279826, 29479, 36566, + -5226, -6696, -4576, -2828, 9729, -6735, 15861, -66886, 477123, 29479, -1017755, -75828, + 3049, -3522, 2603, 5452, 1888, -6316, 4026, -3080, -58582, 36566, -75828, -193453, + -30403, -6761, -6085, -8388, 12841, -17600, 8289, -11817, -4054, -3000, -13322, 14944, + -6761, -28452, -12326, -8945, 10515, -8369, -520, 2242, -3287, -20124, 179, 12354, + -6085, -12326, -180408, 89468, -19908, 3017, -41552, 4204, -31158, -23783, 87004, 44784, + -8388, -8945, 89468, -146434, 53166, -28645, 29987, -2506, -12242, 28411, 11874, 403, + 12841, 10515, -19908, 53166, -182342, 131104, -3630, 7016, -11031, -43497, 35570, 41136, + -17600, -8369, 3017, -28645, 131104, -169537, 52490, -4955, 3848, 41489, -7925, -19614, + 8289, -520, -41552, 29987, -3630, 52490, -111006, -916, 3418, 2295, 3395, 1491, + -11817, 2242, 4204, -2506, 7016, -4955, -916, -219477, -4965, -3871, -77054, -1199, + -4054, -3287, -31158, -12242, -11031, 3848, 3418, -4965, -272588, 2948, 184352, -45153, + -3000, -20124, -23783, 28411, -43497, 41489, 2295, -3871, 2948, -160538, -11875, 4491, + -13322, 179, 87004, 11874, 35570, -7925, 3395, -77054, 184352, -11875, -501251, -59166, + 14944, 12354, 44784, 403, 41136, -19614, 1491, -1199, -45153, 4491, -59166, -256669, + -24496, -5820, -2150, 131, 5291, -10279, 6605, -749, -2301, -4257, 6742, 4179, + -5820, -30866, -8866, -12879, -1341, 2042, -4488, 6991, -847, -21654, 3707, 11359, + -2150, -8866, -123923, 90609, -28405, 24864, -28222, 3814, 6439, -12821, 2736, 12974, + 131, -12879, 90609, -147490, 86712, -38319, 26159, 1048, -7654, 17099, 8973, 1271, + 5291, -1341, -28405, 86712, -147877, 74296, -14561, 2055, 18062, 1238, -4181, 14726, + -10279, 2042, 24864, -38319, 74296, -168459, 117891, -874, -17255, 675, 13174, -13101, + 6605, -4488, -28222, 26159, -14561, 117891, -147764, -13296, 2771, -4243, -4809, 1608, + -749, 6991, 3814, 1048, 2055, -874, -13296, -77582, -32335, -4868, 9778, -6784, + -2301, -847, 6439, -7654, 18062, -17255, 2771, -32335, -69840, 11490, 21385, -23633, + -4257, -21654, -12821, 17099, 1238, 675, -4243, -4868, 11490, -151841, -2520, 12898, + 6742, 3707, 2736, 8973, -4181, 13174, -4809, 9778, 21385, -2520, -60529, -3814, + 4179, 11359, 12974, 1271, 14726, -13101, 1608, -6784, -23633, 12898, -3814, -63927 +}; +const Word32 lvm_speech_fx[N_MIXTURES] = +{ + /*Q10*/ + 32765, 33549, 33755, 32747, 31627, 26814 +}; +const Word16 m_music_fx[N_MIXTURES*N_FEATURES] = +{ + /*Q15*/ + 14804, 25446, 8882, 11624, 12963, 13563, 14794, 20567, 1033, 27373, 23772, 11713, + 15975, 20612, 7737, 12728, 14424, 15237, 16190, 15239, 2277, 30096, 28120, 11522, + 17631, 19827, 9280, 14111, 15555, 16289, 17009, 17271, 1132, 31186, 27733, 12469, + 15863, 24390, 7804, 11176, 11734, 11986, 12857, 23015, 713, 28823, 23782, 13779, + 10022, 22691, 12397, 15249, 15957, 16382, 17058, 15509, 4107, 23807, 22701, 12269, + 16842, 22819, 8062, 11248, 12283, 12978, 13722, 21178, 867, 30480, 25501, 12111 +}; +const Word32 invV_music_fx[N_MIXTURES*N_FEATURES*N_FEATURES] = +{ + /*Q10*/ + -7878, -673, -2037, -885, -236, -667, 749, -1726, -20424, -859, 2463, 4011, + -673, -31356, -1591, -3048, -1872, 1277, -3806, 8836, 5555, -2031, -11076, -7329, + -2037, -1591, -65556, 42935, -11408, 12166, 751, 8792, 24077, -15804, -2546, -2517, + -885, -3048, 42935, -88483, 42957, -13081, 4776, 14411, 23734, -5735, 15306, 15210, + -236, -1872, -11408, 42957, -90738, 37950, -1795, 4021, -35266, 12445, 13655, 17403, + -667, 1277, 12166, -13081, 37950, -86289, 37943, 3429, -5655, 5664, 8658, -11, + 749, -3806, 751, 4776, -1795, 37943, -77863, -8515, -74265, 22313, 3842, 645, + -1726, 8836, 8792, 14411, 4021, 3429, -8515, -59311, -121235, 1622, -8500, 4967, + -20424, 5555, 24077, 23734, -35266, -5655, -74265, -121235, -5534279, 175865, 247781, -296138, + -859, -2031, -15804, -5735, 12445, 5664, 22313, 1622, 175865, -104343, -1168, 32220, + 2463, -11076, -2546, 15306, 13655, 8658, 3842, -8500, 247781, -1168, -79522, -45571, + 4011, -7329, -2517, 15210, 17403, -11, 645, 4967, -296138, 32220, -45571, -249005, + -10115, 613, -4406, -403, 731, 898, 350, -1995, -8975, -169, -1296, 1233, + 613, -30663, -12425, -1115, -1862, 2906, -2485, 12887, -8842, -12067, 4833, 3070, + -4406, -12425, -86550, 49625, -11519, 15386, -20054, 20873, -13684, 28341, 23152, -807, + -403, -1115, 49625, -131210, 81002, 1045, 3085, 8149, -11887, -3094, 43855, 14533, + 731, -1862, -11519, 81002, -226160, 115669, 9052, -6427, -19605, -20406, 7481, 6064, + 898, 2906, 15386, 1045, 115669, -281745, 150559, -5530, 271, -5717, 1673, 7674, + 350, -2485, -20054, 3085, 9052, 150559, -200735, -21872, -9366, 10471, -2190, 3083, + -1995, 12887, 20873, 8149, -6427, -5530, -21872, -111299, -29613, -27611, -54741, -9432, + -8975, -8842, -13684, -11887, -19605, 271, -9366, -29613, -616730, 74872, 189453, -79618, + -169, -12067, 28341, -3094, -20406, -5717, 10471, -27611, 74872, -359342, -12919, 29609, + -1296, 4833, 23152, 43855, 7481, 1673, -2190, -54741, 189453, -12919, -407670, -16961, + 1233, 3070, -807, 14533, 6064, 7674, 3083, -9432, -79618, 29609, -16961, -180700, + -12411, 5539, -1902, 92, 2813, 339, -114, -1078, -24097, -2938, -1812, 399, + 5539, -36224, -7229, -766, -2442, 2066, -2896, 8507, 16429, -11423, -12067, -191, + -1902, -7230, -115426, 44336, 11635, 13946, -3573, 22728, -73099, 119214, 70165, 4686, + 92, -766, 44336, -187908, 81624, 24838, 12765, 1471, -43322, -24066, 44669, 3543, + 2813, -2442, 11635, 81624, -295220, 104190, 52986, -3246, -146322, -78690, 34365, -2814, + 339, 2066, 13946, 24838, 104190, -347659, 169287, -4458, -127093, -94499, 42989, 5700, + -114, -2896, -3573, 12765, 52986, 169287, -310084, -18605, -27182, -19113, -2714, 11, + -1078, 8507, 22728, 1471, -3246, -4458, -18605, -69283, 40578, -47905, -135760, -6645, + -24097, 16429, -73099, -43322, -146322, -127093, -27182, 40578, -8241631, -71531, 1853193, -175523, + -2938, -11423, 119214, -24066, -78690, -94499, -19113, -47905, -71531, -1361618, -36609, 26675, + -1812, -12067, 70165, 44669, 34365, 42989, -2714, -135760, 1853193, -36609, -1337597, -83909, + 399, -191, 4686, 3543, -2814, 5700, 11, -6645, -175523, 26675, -83909, -223653, + -8809, 3326, -1275, -1509, 1423, 1222, -767, -3923, -65513, -5992, 9965, 3853, + 3326, -31906, -1905, 4114, -4704, 1138, -584, 10709, 104184, 6118, -30358, -5240, + -1275, -1905, -184413, 67973, -17415, 32246, -7121, 16051, -2994, -52989, 23547, 27770, + -1509, 4114, 67973, -160389, 86351, -8947, 13772, 8224, 3480, 2626, 24337, 1870, + 1423, -4704, -17415, 86351, -198772, 68001, 7361, 14025, 11152, 23137, 12598, 9972, + 1222, 1138, 32246, -8947, 68001, -166130, 57911, 17629, 118765, 39472, 1806, 7267, + -767, -584, -7121, 13772, 7361, 57911, -123203, 2059, 47920, 59494, 10484, -5066, + -3923, 10709, 16051, 8224, 14025, 17629, 2059, -90332, -367027, -30259, -20438, -3054, + -65513, 104184, -2994, 3480, 11152, 118765, 47920, -367027, -16854832, -181537, 903929, -95027, + -5992, 6118, -52989, 2626, 23137, 39472, 59494, -30259, -181537, -320917, -11497, 56536, + 9965, -30358, 23547, 24337, 12598, 1806, 10484, -20438, 903929, -11497, -197437, -16106, + 3853, -5240, 27770, 1870, 9972, 7267, -5066, -3054, -95027, 56536, -16106, -107942, + -14599, -2426, -4488, 2252, 20, -696, -2636, 5531, 1097, 109, 1359, 2742, + -2426, -22977, 1326, -4413, -6555, 199, -2249, 16239, 6914, -6267, 1335, -319, + -4488, 1326, -38846, 40605, -16372, -138, 6341, 2358, -5859, 1498, -1344, -3917, + 2252, -4413, 40605, -94592, 69176, -3799, -16812, -5416, -11189, -3107, 2060, -3508, + 20, -6555, -16372, 69176, -121278, 55283, 86, 3716, 11782, -9657, 3416, 549, + -696, 199, -138, -3799, 55283, -105539, 62225, 5299, 3619, 1933, -2511, 609, + -2636, -2249, 6341, -16812, 86, 62225, -79693, -7236, -9729, -2907, 2795, 57, + 5531, 16239, 2358, -5416, 3716, 5299, -7236, -52597, -40766, -5195, 2995, 11158, + 1097, 6914, -5859, -11189, 11782, 3619, -9729, -40766, -95884, 18462, 2795, -18509, + 109, -6267, 1498, -3107, -9657, 1933, -2907, -5195, 18462, -29138, 3027, 17268, + 1359, 1335, -1344, 2060, 3416, -2511, 2795, 2995, 2795, 3027, -10878, -6828, + 2742, -319, -3917, -3508, 549, 609, 57, 11158, -18509, 17268, -6828, -48324, + -9462, 2969, -1087, -1924, 1418, -350, 396, -3124, -35326, 682, 3248, 5848, + 2969, -29148, -2662, 2400, -3059, 2772, 847, 8375, 60040, -6778, -23223, -7694, + -1087, -2662, -172602, 83798, 2597, 33012, 3851, 12397, 81998, -81017, 15831, 35467, + -1924, 2400, 83798, -204141, 66003, 2928, 18028, 14706, 8557, 16030, 44283, 36177, + 1418, -3059, 2597, 66003, -202589, 47215, 19493, 10544, -4664, 46480, 10895, 18165, + -350, 2772, 33012, 2928, 47215, -198011, 76335, 14223, 123301, 70945, 1870, 8265, + 396, 847, 3851, 18028, 19493, 76335, -177594, -5345, 78880, 114804, -171, 3539, + -3124, 8375, 12397, 14706, 10544, 14223, -5345, -67596, -251454, -55035, -21890, 7263, + -35326, 60040, 81998, 8557, -4664, 123301, 78880, -251454, -12784658, -217014, 810245, -725111, + 682, -6778, -81017, 16030, 46480, 70945, 114804, -55035, -217014, -793758, -8106, 74886, + 3248, -23223, 15831, 44283, 10895, 1870, -171, -21890, 810245, -8106, -319630, -77833, + 5848, -7694, 35467, 36177, 18165, 8265, 3539, 7263, -725111, 74886, -77832, -481222 +}; +const Word32 lvm_music_fx[N_MIXTURES] = +{ + /*Q10*/ + 28603, 31076, 35357, 31989, 20938, 34395 +}; +const Word16 m_noise_fx[N_MIXTURES*N_FEATURES] = +{ + /*Q15*/ + 14825, 18681, 7930, 11230, 13228, 13602, 14556, 14377, 1133, 29263, 26842, 13270, + 14312, 14992, 9378, 12891, 14075, 14581, 15548, 12386, 1050, 32143, 28322, 12379, + 18179, 16617, 8015, 13153, 13932, 14462, 15329, 11848, 1033, 31841, 28406, 12222, + 15822, 17883, 3231, 8086, 9983, 9933, 11537, 11904, 1018, 29549, 27473, 11111, + 13821, 16109, 8734, 12035, 13351, 13603, 15024, 12957, 1163, 31179, 28243, 11865, + 13845, 15577, 10545, 14292, 15353, 15784, 16567, 12750, 1589, 31695, 28796, 13420 +}; +const Word32 invV_noise_fx[N_MIXTURES*N_FEATURES*N_FEATURES] = +{ + /*Q10*/ + -11129, -775, -807, 4750, -4310, -1632, 1694, 530, -25134, -2399, 1632, 1938, + -775, -43700, -5296, -23144, -4086, -2008, 9445, 12956, 17119, 10623, -18169, -14373, + -807, -5296, -117924, 78859, -23526, 22681, -7637, 52382, 20661, -1131, 18004, -18669, + 4750, -23144, 78859, -165973, 70704, -954, 10160, 6713, 50481, 19307, -10190, 16924, + -4310, -4086, -23526, 70704, -186160, 114906, -28994, 9999, 17677, -18372, -20805, -12577, + -1632, -2008, 22681, -954, 114906, -235840, 123708, -3753, 21616, 9200, 15641, -10616, + 1694, 9445, -7637, 10160, -28994, 123708, -156081, -1564, -7627, 5159, 14184, -12573, + 530, 12956, 52382, 6713, 9999, -3753, -1564, -116541, -130257, -2892, -51260, -1433, + -25134, 17119, 20661, 50481, 17677, 21616, -7627, -130257, -6857531, -23164, 425725, -172307, + -2399, 10623, -1131, 19307, -18372, 9200, 5159, -2892, -23164, -157605, 9307, 20639, + 1632, -18169, 18004, -10190, -20805, 15641, 14184, -51260, 425725, 9307, -184817, -2232, + 1938, -14373, -18669, 16924, -12577, -10616, -12573, -1433, -172307, 20639, -2232, -94498, + -23585, -1283, 2220, 5814, -1063, -5524, 5040, -408, -7744, 65700, -4948, 1221, + -1283, -102238, 18435, -18156, -6216, 17104, -1870, 25097, 97427, 32242, -77595, -4567, + 2220, 18435, -305438, 139861, 24123, 32851, -45614, 45538, 124040, 301172, -22649, 3625, + 5814, -18156, 139861, -565373, 242575, 46852, 50718, -18774, -159188, 141029, 89911, 9768, + -1063, -6216, 24123, 242575, -798475, 256535, 104095, 9375, -84525, -408528, 98204, 4495, + -5524, 17104, 32851, 46852, 256535, -845586, 312678, -6990, 50242, -543393, -42629, 99, + 5040, -1870, -45614, 50718, 104095, 312678, -732093, 14409, 83177, -140864, -2169, -2321, + -408, 25097, 45538, -18774, 9375, -6990, 14409, -314037, 273543, -30059, -253352, -3462, + -7744, 97427, 124040, -159188, -84525, 50242, 83177, 273543, -19301626, -952154, 3668367, -93870, + 65700, 32242, 301172, 141029, -408528, -543393, -140864, -30059, -952154, -16033274, -164405, -24189, + -4948, -77595, -22649, 89911, 98204, -42629, -2169, -253352, 3668367, -164405, -2501887, -105127, + 1221, -4567, 3625, 9768, 4495, 99, -2321, -3462, -93870, -24189, -105127, -252171, + -11556, 5444, 1053, 1823, -1754, -6509, 3535, -483, 5751, 22898, -4369, 2503, + 5444, -61418, -46603, 523, -4221, 5377, -14703, 2336, 4414, 4601, 17795, 5358, + 1053, -46603, -197022, 61944, 30015, 11139, -14163, 4583, 14704, 174734, 105587, 3797, + 1823, 523, 61944, -579713, 310766, -24876, -8601, -1522, -38055, -308764, 10254, 11526, + -1754, -4221, 30015, 310766, -873205, 294102, 7806, 2338, -28081, -507955, -5526, -1671, + -6509, 5377, 11139, -24876, 294102, -740664, 309186, -19342, -50840, -143800, 27527, 4324, + 3535, -14703, -14163, -8601, 7806, 309186, -508227, 24986, 208442, -230010, -48336, -9651, + -483, 2336, 4583, -1522, 2338, -19342, 24986, -362502, 140055, -118693, -134546, 982, + 5751, 4414, 14704, -38055, -28081, -50840, 208442, 140055, -20820834, -328791, 3081671, -99923, + 22898, 4601, 174734, -308764, -507955, -143800, -230010, -118693, -328791, -7236926, -225976, -47887, + -4369, 17795, 105587, 10254, -5526, 27527, -48336, -134546, 3081671, -225976, -2500626, -124929, + 2503, 5358, 3797, 11526, -1671, 4324, -9651, 982, -99923, -47887, -124929, -277469, + -14533, 3263, -8141, 13301, 5586, 1808, -5289, 472, 7371, -21379, -2460, 596, + 3263, -46002, -56596, 9198, -765, 13994, 5247, 2629, -14758, -21574, 5644, 3817, + -8141, -56596, -895669, 406276, -247505, 72418, -246462, 32532, -190899, -74267, 59747, 10271, + 13301, 9198, 406276, -551172, 137309, 34772, -5367, 41269, 67372, 262339, 42457, 60892, + 5586, -765, -247505, 137309, -964866, 393695, 36960, 5148, 114354, 66434, -19640, 18501, + 1808, 13994, 72418, 34772, 393695, -906317, 366933, 14058, 76374, 284422, 16253, 32973, + -5289, 5247, -246462, -5367, 36960, 366933, -711303, 23465, 84856, 157990, 2319, 21580, + 472, 2629, 32532, 41269, 5148, 14058, 23465, -349612, -74011, -89655, -17686, 7616, + 7371, -14758, -190899, 67372, 114354, 76374, 84856, -74011, -17027780, -264311, 396822, -266476, + -21379, -21574, -74267, 262339, 66434, 284422, 157990, -89655, -264311, -871539, 3553, 2308, + -2460, 5644, 59747, 42457, -19640, 16253, 2319, -17686, 396822, 3553, -334956, -46272, + 596, 3817, 10271, 60892, 18501, 32973, 21580, 7616, -266476, 2308, -46272, -357254, + -21040, -1263, -6696, 8169, -1272, -4427, 4142, -8459, -63196, -17218, 710, 2270, + -1263, -83196, -34319, -27267, 2213, -240, -783, 22287, 136898, 9589, -27942, -6781, + -6696, -34319, -329281, 107754, 677, -33332, -46218, 43055, -204958, -43031, 204918, 20438, + 8169, -27267, 107754, -371373, 103141, 10674, 46337, -3299, -65216, -42038, -5280, 13005, + -1272, 2213, 677, 103141, -420124, 194457, 1575, 22157, -26994, 36729, 47504, 13852, + -4427, -240, -33332, 10674, 194457, -368592, 152851, 14172, 107043, 44274, -23917, -8922, + 4142, -783, -46218, 46337, 1575, 152851, -280668, -8210, 40158, 24389, 13385, 8410, + -8459, 22287, 43055, -3299, 22157, 14172, -8210, -256064, 79772, -1255, -101174, 759, + -63196, 136898, -204958, -65216, -26994, 107043, 40158, 79772, -13100212, 263557, 2000831, -242675, + -17218, 9589, -43031, -42038, 36729, 44274, 24389, -1255, 263557, -1223057, -216580, -23199, + 710, -27942, 204918, -5280, 47504, -23917, 13385, -101174, 2000831, -216580, -1303910, -90175, + 2270, -6781, 20438, 13005, 13852, -8922, 8410, 759, -242675, -23199, -90175, -372746, + -24335, -321, -1426, 1524, 1959, -4164, 7012, -3148, -7859, 9391, 3193, 2194, + -321, -90890, -9068, -27277, 5303, 10922, 2298, 22512, 17201, 4798, 13388, -2773, + -1426, -9068, -180137, 85478, 42242, 14714, -12908, 34197, 67246, 40663, 36965, -9792, + 1524, -27277, 85478, -392290, 221884, 12492, 33161, -14359, 7950, -103145, -29210, -5361, + 1959, 5303, 42242, 221884, -600963, 259592, 30301, 7895, -32577, -115360, 20766, -7273, + -4164, 10922, 14714, 12492, 259592, -611459, 304095, 6323, -42968, -37072, -21092, -15235, + 7012, 2298, -12908, 33161, 30301, 304095, -467758, 26953, -35709, 29107, 35819, -8754, + -3148, 22512, 34197, -14359, 7895, 6323, 26953, -271919, 2988, 852, -128460, -11407, + -7859, 17201, 67246, 7950, -32577, -42968, -35709, 2988, -1773460, -215853, 756954, -99883, + 9391, 4798, 40663, -103145, -115360, -37072, 29107, 852, -215853, -2382074, -108833, 1061, + 3193, 13388, 36965, -29210, 20766, -21092, 35819, -128460, 756954, -108833, -1923617, -116204, + 2194, -2773, -9792, -5361, -7273, -15235, -8754, -11407, -99883, 1061, -116204, -103840 +}; +const Word32 lvm_noise_fx[N_MIXTURES] = +{ + /*Q10*/ + 29413, 42169, 40240, 39433, 37918, 36348 +}; +/* Inv possible delta used in gaus_enc (1.0/(1.0+delta*delta)) and delta = [1,7] */ +const Word16 inv_delta_tab[7] = /*Q15*/ +{ + 32640, + 32264, + 31655, + 30840, + 29855, + 28728, + 27504 +}; + +const Word16 lsf_unified_fit_model_nb[4][16] = +{ + {12506 , -17641 , -6444 , -6646 , -3523 , -2132 , -511 , -92 , 699 , 1062 , 2578 , 3564 , 3200 , -285 , 2928 , -250}, + {20383 , 18855 , 8494 , 8062 , 8105 , 6211 , 5068 , 4408 , 3741 , 3458 , 2732 , 3174 , 2412 , 17421 , -21717 , 0}, + {-717 , -617 , -144 , -117 , -229 , -144 , -141 , -98 , -92 , -69 , -51 , -87 , -37 , -3019 , 19864 , 8034}, + {-2424 , 8999 , 5723 , 5629 , 4239 , 3423 , 2507 , 2019 , 1245 , 736 , -907 , -2237 , -2558 , -1979 , -652 , 1657} +}; + +const Word16 lsf_unified_fit_model_wb[4][16] = +{ + {8323 , -567 , 3402 , 1389 , 1437 , 1820 , 1407 , 1299 , 1292 , 1206 , 1031 , 928 , 898 , 832 , 840 , 681}, + {24635 , 19605 , 9294 , 7407 , 6419 , 5459 , 4966 , 4189 , 3394 , 2964 , 2425 , 2110 , 2140 , 1972 , 1540 , 2252}, + {-867 , -666 , -168 , -114 , -90 , -122 , -129 , -101 , -65 , -56 , -39 , -35 , -40 , -42 , -35 , -56}, + {-2313 , 3035 , 1677 , 2854 , 2334 , 1232 , 1347 , 1034 , 863 , 707 , 886 , 891 , 432 , 357 , 206 , -310} +}; + +const Word16 lsf_unified_fit_model_wbhb[4][16] = +{ + {5312 , 1967 , 2914 , 1438 , 2595 , 1848 , 1980 , 2021 , 1535 , 1489 , 1651 , 1502 , 1447 , 1311 , 1353 , 1202}, + {28135 , 16053 , 10129 , 7366 , 5898 , 5341 , 3290 , 2780 , 3146 , 2423 , 1613 , 1370 , 1294 , 1635 , 1105 , 1431}, + {-615 , -308 , -147 , -119 , -104 , -105 , -30 , -28 , -50 , -39 , -15 , -14 , -14 , -21 , -19 , -29}, + {1534 , 3569 , 3138 , 4023 , 2105 , 2023 , 2046 , 1264 , 1340 , 1067 , 780 , 547 , 188 , -540 , -722 , -479} +}; + +const Word32 Freq_Weight_Com_fx[160] = /*Q31 */ +{ + 1073741824, 1351646720, 1610612736, 1832992000, 2003629568, 2110896768, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2088915968, 2033457920, 1980868480, + 1930930688, 1883448832, 1838246016, 1795162112, 1754051584, 1714781696, 1677231744, 1641291136, + 1606858368, 1573840768, 1542152704, 1511715456, 1482456448, 1454308608, 1427209600, 1401102080, + 1375932672, 1351651456, 1328212480, 1305572480, 1283691392, 1262531584, 1242058112, 1222238080, + 1203040640, 1184436864, 1166399744, 1148903808, 1131924864, 1115440512, 1099429376, 1083871488, + 1068747648, 1054040128, 1039731904, 1025806912, 1012249984, 999046720, 986183488, 973647232, + 961425728, 949507264, 937880640, 926535296, 915461184, 904648640, 894088512, 883772096, + 873691072, 863837376, 854203520, 844782144, 835566336, 826549440, 817725120, 809087168, + 800629824, 792347392, 784234624, 776286336, 768497472, 760863424, 753379520, 746041408, + 738844864, 731785856, 724860416, 718064832, 711395520, 704848896, 698421760, 692110720, + 685912704, 679824704, 673843840, 667967296, 662192384, 656516416, 650936960, 645451520, + 640057792, 634753472, 629536320, 624404224, 619355136, 614387008, 609497984, 604686208, + 599949760, 595286912, 590696000, 586175360, 581723392, 577338560, 573019328, 568764224, + 564571840, 560440832, 556369856, 552357568, 548402752, 544504128, 540660608, 536870912, + 533133984, 529448736, 525814080, 522228992, 518692448, 515203488, 511761152, 508364480, + 505012640, 501704704, 498439808, 495217120, 492035872, 488895200, 485794400, 482732672, + 479709280, 476723552, 473774752, 470862208, 467985248, 465143232, 462335520, 459561504, + 456820576, 454112160, 451435648, 448790528, 446176224, 443592192, 441037920, 438512896 +}; + + +const Word32 Freq_Weight_UV_fx[160] = /*Q31 */ +{ + 1073741824, 1351646720, 1610612736, 1832992000, 2003629568, 2110896768, 2147483647, 2129881344, + 2112565248, 2095528448, 2078764160, 2062265984, 2046027776, 2030043136, 2014306304, 1998811648, + 1983553536, 1968526720, 1953725696, 1939145728, 1924781696, 1910628864, 1896682624, 1882938624, + 1869392256, 1856039424, 1842876032, 1829897984, 1817101568, 1804482816, 1792038016, 1779763840, + 1767656576, 1755713024, 1743929728, 1732303488, 1720831232, 1709510016, 1698336768, 1687308544, + 1676422656, 1665676416, 1655067008, 1644591872, 1634248576, 1624034560, 1613947392, 1603984640, + 1594144256, 1584423936, 1574821376, 1565334528, 1555961216, 1546699520, 1537547520, 1528503040, + 1519564416, 1510729728, 1501997184, 1493365120, 1484831488, 1476395008, 1468053760, 1459806336, + 1451650944, 1443586176, 1435610624, 1427722624, 1419920896, 1412203904, 1404570368, 1397018880, + 1389548288, 1382157056, 1374844032, 1367608064, 1360447744, 1353362048, 1346349824, 1339409920, + 1332541184, 1325742464, 1319012736, 1312351104, 1305756416, 1299227648, 1292763776, 1286363904, + 1280027136, 1273752576, 1267539072, 1261385984, 1255292416, 1249257344, 1243280000, 1237359616, + 1231495424, 1225686400, 1219932032, 1214231424, 1208583808, 1202988544, 1197444736, 1191951872, + 1186509184, 1181116032, 1175771648, 1170475264, 1165226496, 1160024704, 1154868992, 1149758976, + 1144693888, 1139673344, 1134696576, 1129763200, 1124872448, 1120023808, 1115216768, 1110450944, + 1105725568, 1101040384, 1096394624, 1091787904, 1087219712, 1082689664, 1078197248, 1073741824, + 1069323136, 1064940672, 1060593984, 1056282624, 1052006144, 1047764224, 1043556288, 1039382080, + 1035241152, 1031132992, 1027057408, 1023013888, 1019002048, 1015021568, 1011072064, 1007153152, + 1003264576, 999405824, 995576704, 991776768, 988005760, 984263360, 980549120, 976862848, + 973204224, 969572864, 965968512, 962390848, 958839552, 955314432, 951815104, 948341312, +}; +const Word16 hann_window_320_fx[BWD_TOTAL_WIDTH/2] = +{ + 0, 1, 3, 7, 13, 20, 29, 39, + 51, 64, 79, 96, 114, 134, 155, 177, + 202, 227, 255, 283, 314, 345, 379, 413, + 449, 487, 525, 566, 607, 650, 695, 740, + 787, 835, 885, 935, 987, 1040, 1095, 1150, + 1207, 1265, 1323, 1383, 1444, 1506, 1569, 1633, + 1698, 1764, 1831, 1899, 1967, 2036, 2106, 2177, + 2249, 2321, 2394, 2468, 2543, 2617, 2693, 2769, + 2846, 2923, 3000, 3078, 3156, 3235, 3314, 3394, + 3473, 3553, 3633, 3713, 3794, 3874, 3955, 4035, + 4116, 4197, 4277, 4358, 4438, 4519, 4599, 4679, + 4759, 4838, 4917, 4996, 5075, 5153, 5231, 5308, + 5385, 5461, 5537, 5612, 5687, 5761, 5834, 5907, + 5979, 6050, 6121, 6190, 6259, 6327, 6395, 6461, + 6526, 6591, 6654, 6717, 6778, 6839, 6898, 6956, + 7014, 7070, 7125, 7178, 7231, 7282, 7332, 7381, + 7429, 7475, 7520, 7563, 7606, 7647, 7686, 7724, + 7761, 7796, 7830, 7863, 7894, 7923, 7951, 7978, + 8003, 8026, 8048, 8068, 8087, 8105, 8121, 8135, + 8147, 8158, 8168, 8176, 8182, 8187, 8190, 8192 +}; +const Word16 W_HIST_FX[DTX_HIST_SIZE] = {13107, 10486, 8389, 6711, 5369, 4295, 3436, 687}; /* Q16 */ +const Word16 W_HIST_S_FX[DTX_HIST_SIZE] = {20480, 11378, 8393, 6938, 6092, 5551, 5183, 5115}; /* Q12 */ + +/*----------------------------------------------------------------------------------* + * Starting points for pulse position search in Algebraic innovation codebook + * Used in lib_enc\cod4t64.c + *----------------------------------------------------------------------------------*/ + + + +const Word16 huffnorm_e_fx[32] = +{ + 1062, 550, 314, 274, 273, 272, 156, 79, 69, 38, + 18, 40, 5, 3, 0, 1, 3, 4, 11, 21, + 41, 32, 35, 67, 133, 264, 530, 315, 551, 2126, 4254, 4255 +}; + +const Word16 huffnorm_n_fx[32] = +{ + 14831, 14830, 7414, 3706, 593, 927, 462, 297, 230, 116, + 50, 36, 13, 8, 5, 1, 0, 2, 6, 7, + 15, 19, 24, 56, 59, 51, 114, 117, 75, 149, 592, 1852 +}; + +const Word16 huffsizn_e_fx[32] = +{ + 13, 12, 11, 11, 11, 11, 10, 9, 9, 8, + 7, 6, 5, 4, 3, 2, 2, 3, 4, 5, + 6, 8, 8, 9, 10, 11, 12, 11, 12, 14, 15, 15 +}; + +const Word16 huffsizn_n_fx[32] = +{ + 14, 14, 13, 12, 10, 10, 9, 9, 8, 7, + 7, 6, 5, 4, 3, 3, 3, 3, 3, 4, + 4, 5, 6, 6, 6, 7, 7, 7, 7, 8, 10, 11 +}; + +const Word16 resize_huffnorm_fx[32] = +{ + 0, 0, 0, 0, 0, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, + 2, 5, 11, 23, 47, 95, 191, 383, 767, 2047, 0, 0, 0, 0, 0, 0 +}; + +const Word16 huffnorm_fx[32] = +{ + 26, 58, 90, 122, 27, 59, 91, 123, 12, 28, 44, 60, 2, 6, 4, 6, + 0, 2, 10, 14, 14, 30, 46, 62, 30, 62, 94, 126, 31, 63, 95, 127 +}; + +const Word16 pgain_huffnorm_fx[32] = +{ + 1, 1, 2, 3, 3, 2, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 4, 5, 3, 2, 3, 3, 4, 5, 0, 1 +}; + +const Word16 hessize_fx[8]= +{ + 7, 5, 3, 2, 1, 4, 6, 7 +}; + +const Word16 hescode_fx[8]= +{ + 11, 3, 1, 1, 1, 0, 4, 10 +}; + +/*----------------------------------------------------------------------------------* + * Encoder TABLE ROM + *----------------------------------------------------------------------------------*/ + +/* [129] - half of the square root hanning window for spectral analysis and NS */ +const Word16 sqrt_han_window[L_FFT/2+1] = +{ + 0, 402, 804, 1206, 1608, 2009, 2410, 2811, 3212, + 3612, 4011, 4410, 4808, 5205, 5602, 5998, 6393, 6786, + 7179, 7571, 7962, 8351, 8739, 9126, 9512, 9896, 10278, + 10659, 11039, 11417, 11793, 12167, 12539, 12910, 13279, 13645, + 14010, 14372, 14732, 15090, 15446, 15800, 16151, 16499, 16846, + 17189, 17530, 17869, 18204, 18537, 18868, 19195, 19519, 19841, + 20159, 20475, 20787, 21096, 21403, 21705, 22005, 22301, 22594, + 22884, 23170, 23452, 23731, 24007, 24279, 24547, 24811, 25072, + 25329, 25582, 25832, 26077, 26319, 26556, 26790, 27019, 27245, + 27466, 27683, 27896, 28105, 28310, 28510, 28706, 28898, 29085, + 29268, 29447, 29621, 29791, 29956, 30117, 30273, 30424, 30571, + 30714, 30852, 30985, 31113, 31237, 31356, 31470, 31580, 31685, + 31785, 31880, 31971, 32057, 32137, 32213, 32285, 32351, 32412, + 32469, 32521, 32567, 32609, 32646, 32678, 32705, 32728, 32745, + 32757, 32765, 32767 +}; + +/*------------------------------------------------------------------------------* + * Critical bands in Q0 + *------------------------------------------------------------------------------*/ +const Word16 crit_bands[] = +{ + 100, 200, 300, 400, 510, 630, 770, 920, 1080, 1270, + 1480, 1720, 2000, 2320, 2700, 3150, 3700, 4400, 5300, 6350 +}; + +/*----------------------------------------------------------------------------------* + * Open-loop pitch tables, + * Used in lib_enc\pitch_ol.c + *----------------------------------------------------------------------------------*/ + + +/* integer square (i*i) */ +const Word16 int_sqr[17] = +{ + 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256 +}; + + +/*ari_hm_enc.c*/ +/* Q13 format */ +const Word16 kLowPeriodicityThr[2] = { 4096/*0.5f Q13*/, 1638/*0.2f Q13*/ }; + +/* pow(3 * i + 1, 0.3) / pow(256 - 1, 0.3) */ +const Word16 Weight[86] = +{ + 0x1848, 0x24CD, 0x2B87, 0x3072, 0x3469, 0x37C8, 0x3ABB, 0x3D5F, 0x3FC6, 0x41FA, 0x4406, 0x45EF, 0x47BB, 0x496E, 0x4B0A, + 0x4C93, 0x4E0A, 0x4F71, 0x50CA, 0x5216, 0x5357, 0x548C, 0x55B8, 0x56DA, 0x57F4, 0x5905, 0x5A10, 0x5B13, 0x5C10, 0x5D06, 0x5DF7, + 0x5EE2, 0x5FC8, 0x60A9, 0x6185, 0x625D, 0x6331, 0x6401, 0x64CD, 0x6595, 0x6659, 0x671B, 0x67D9, 0x6893, 0x694B, 0x6A00, 0x6AB2, + 0x6B62, 0x6C0F, 0x6CB9, 0x6D61, 0x6E07, 0x6EAB, 0x6F4C, 0x6FEB, 0x7088, 0x7124, 0x71BD, 0x7254, 0x72EA, 0x737E, 0x7410, 0x74A1, + 0x752F, 0x75BD, 0x7649, 0x76D3, 0x775C, 0x77E3, 0x7869, 0x78EE, 0x7971, 0x79F3, 0x7A74, 0x7AF4, 0x7B72, 0x7BF0, 0x7C6C, 0x7CE7, + 0x7D61, 0x7DDA, 0x7E51, 0x7EC8, 0x7F3E, 0x7FB3, 0x7FFF +}; + +const Word16 lsf_numlevels[TCXLPC_NUMSTAGES] = { 32, 16, 16 }; +const Word16 lsf_ind_numlevels[TCXLPC_IND_NUMSTAGES] = { 4 }; + +/*----------------------------------------------------------------------------------* + * Starting line for the noise measurement in TCX. + *----------------------------------------------------------------------------------*/ +const Word16 startLineWB[11] = { 8, 23, 36, 45, 66, 128 /* 13.2kbps */, 200, 320, 320, 320 /* 48kbps */, 320 }; +const Word16 startLineSWB[9] = { 8, 44, 96 /* 13.2kbps */, 160, 320, 320, 256 /* 48kbps */, 341, 640 }; + +/*----------------------------------------------------------------------------------* + * CLDFB-based VAD + *----------------------------------------------------------------------------------*/ +/* SNR_calc.c */ +const Word16 Nregion_index_NB[9] = {0,1,2,3,4,5,6,7, 9}; +const Word16 Nregion_index_WB[13] = {0,1,2,3,4,5,6,8,10,12,16}; +const Word16 Nregion_index_SWB[16] = {0,1,2,3,4,5,6,8,10,12,16,24,36}; +const Word16 Nregion_index_FB[16] = {0,1,2,3,4,5,6,8,10,12,16,24,36}; +const Word16 Nregion_preoff[12] = {0,0,0,0,0,0,1,1,1,2,3,4}; +const Word16 SNR_SUB_BAND_NUM[4] = {8,10,12,MAX_SUBBAND_NUM}; +const Word16 BAND_MUL[4] = {4096/* 1/8.0 Q15 */,3277/* 1/10.0 Q15 */,2731/* 1/12.0 Q15 */,2731/* 1/12.0 Q15 */}; +const Word16 *REGION_INDEX[4] = {Nregion_index_NB, Nregion_index_WB,Nregion_index_SWB,Nregion_index_FB}; +const Word32 MAX_LF_SNR_TAB[5] = {26843545/* 0.8 Q25 */,26843545/* 0.8 Q25 */,53687090/* 1.6 Q25 */,26843545/* 0.8 Q25 */,26843545/* 0.8 Q25 */}; +const Word32 LS_MIN_SILENCE_SNR[4] = {251658233/* 7.5 Q25 */, 251658233/* 7.5 Q25 */, 228170137/* 6.8 Q25 */,228170137/* 6.8 Q25 */}; +const Word32 LT_MIN_SILENCE_SNR[4] = {150994940/* 4.5 Q25 */, 150994940/* 4.5 Q25 */, 150994940/* 4.5 Q25 */,150994940/* 4.5 Q25 */}; +const Word32 COMVAD_INIT_SNR_DELTA[5] = {33554431/* 1.0 Q25 */, 20132659/* 0.6 Q25 */, 28856811/* 0.86 Q25 */, 38923139/* 1.16 Q25 */, 33554431/* 1.0 Q25 */}; + +/* spec_center.c */ +const Word16 i_t_1[10]= {2048,4096,6144,8192,10240,12288,14336,16384,18432,20480}; +const Word16 i_t_2[23]= {1024,2048,3072,4096,5120,6144,7168,8192,9216,10240,11264,12288,13312,14336,15360,16384,17408,18432,19456,20480,21504,22528,23552}; + +/* subband_fft.c */ +const complex_16 wnk_table_16[16] = +{ + {32767, 0}, {30274, 12540}, {23170, 23170}, {12540, 30274}, + {32767, 0}, {23170, 23170}, {0, 32767}, {-23170, 23170}, + {32767, 0}, {12540, 30274}, {-23170, 23170}, {-30274, -12540}, + {32767, 0}, {32767, 0}, {32767, 0}, {0, -32768}, +}; + +/* x(n)*W_2N^n */ +const complex_16 M_in_fix16[16] = +{ + {32767, 0}, {32138, 6393}, {30274, 12540}, {27246, 18205}, + {23170, 23170}, {18205, 27246}, {12540, 30274}, {6393, 32138}, + {0, 32767}, {-6393, 32138}, {-12540, 30274}, {-18205, 27246}, + {-23170, 23170},{ -27246, 18205}, {-30274, 12540}, {-32138, 6393}, +}; +/*W_2N^(k+1/2)*/ + +const Word16 M_Wr_fix16[16] = +{ + 32609/* 9.9518473e-001f Q15 */,31356/* 9.5694034e-001f Q15 */,28898/* 8.8192126e-001f Q15 */,25329/* 7.7301045e-001f Q15 */,20787/* 6.3439328e-001f Q15 */,15446/* 4.7139674e-001f Q15 */, 9512/* 2.9028468e-001f Q15 */, 3212/* 9.8017140e-002f Q15 */, + -3212/* -9.8017140e-002f Q15 */,-9512/* -2.9028468e-001f Q15 */,-15446/* -4.7139674e-001f Q15 */,-20787/* -6.3439328e-001f Q15 */,-25329/* -7.7301045e-001f Q15 */,-28898/* -8.8192126e-001f Q15 */,-31356/* -9.5694034e-001f Q15 */,-32609/* -9.9518473e-001f Q15 */ +}; + +const Word16 M_Wi_fix16[16] = +{ + 3212/* 9.8017140e-002f Q15 */, 9512/* 2.9028468e-001f Q15 */,15446/* 4.7139674e-001f Q15 */,20787/* 6.3439328e-001f Q15 */,25329/* 7.7301045e-001f Q15 */,28898/* 8.8192126e-001f Q15 */,31356/* 9.5694034e-001f Q15 */,32609/* 9.9518473e-001f Q15 */, + 32609/* 9.9518473e-001f Q15 */,31356/* 9.5694034e-001f Q15 */,28898/* 8.8192126e-001f Q15 */,25329/* 7.7301045e-001f Q15 */,20787/* 6.3439328e-001f Q15 */,15446/* 4.7139674e-001f Q15 */, 9512/* 2.9028468e-001f Q15 */, 3212/* 9.8017140e-002f Q15 */ +}; + +/* vad_proc.c */ +const Word16 BAND_NUM_TAB[5] = {10,10,20,40,60}; /* {OFFSET, NB, WB, SWB, FB} */ +const Word16 BAND_SCALE_AJ[5] = {3,3,5,6,6}; /* {OFFSET, NB, WB, SWB, FB} */ + +/* enc_acelp.c, enc_acelpx.c */ +const UWord8 E_ROM_tipos[40] = +{ + 0, 1, 2, 3, /* starting point &ipos[0], 1st iter */ + 1, 2, 3, 0, /* starting point &ipos[4], 2nd iter */ + 2, 3, 0, 1, /* starting point &ipos[8], 3rd iter */ + 3, 0, 1, 2, /* starting point &ipos[12], 4th iter */ + 0, 1, 2, 3, + 1, 2, 3, 0, + 2, 3, 0, 1, + 3, 0, 1, 2, + 0, 1, 2, 3, /* end point for 24 pulses &ipos[35], 4th iter */ + 1, 2, 3, 0 /* end point for 36 pulses &ipos[39], 2nd iter */ +}; + +/* bw_detect_fx.c */ +const Word16 bwd_start_bin_fx[4] = {1, 3, 6, 11}; +const Word16 bwd_end_bin_fx[4] = {1, 4, 9, 12}; + + + + diff --git a/lib_enc/rom_enc_fx.h b/lib_enc/rom_enc_fx.h new file mode 100644 index 0000000..73c246c --- /dev/null +++ b/lib_enc/rom_enc_fx.h @@ -0,0 +1,120 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#ifndef ROM_ENC_FX_H +#define ROM_ENC_FX_H + +#include +#include "options.h" +#include "cnst_fx.h" +#include "stat_enc_fx.h" + + +/*----------------------------------------------------------------------------------* + * General tables + *----------------------------------------------------------------------------------*/ + +extern const Word16 sqrt_han_window[]; /* LP analysis: half of the square root hanning window */ +extern const Word16 crit_bands[]; /* LP analysis: critical bands */ + +extern const Word16 hangover_hd_tbl_fx[3]; +extern const Word16 hangover_sf_tbl_fx[6]; + +extern const Word16 H_fir[]; +extern const Word16 len_12k8_fx[]; +extern const Word16 len1_12k8_fx[]; +extern const Word16 sublen_12k8_fx[]; +extern const Word16 sublen1_12k8_fx[]; +extern const Word16 pit_max_12k8_fx[]; +extern const Word16 sec_length_12k8_fx[]; +extern const Word16 sec_length1_12k8_fx[]; +extern const Word16 w_spmus_fx[HANG_LEN][HANG_LEN]; +extern const Word16 SF_mult_fx[N_FEATURES]; +extern const Word16 SF_8k_mult_fx[N_FEATURES]; +extern const Word32 SF_add_fx[N_FEATURES]; +extern const Word32 SF_8k_add_fx[N_FEATURES]; + +extern const Word32 lvm_noise_fx[]; +extern const Word32 invV_noise_fx[N_MIXTURES*N_FEATURES*N_FEATURES]; +extern const Word16 m_noise_fx[N_MIXTURES*N_FEATURES]; +extern const Word32 lvm_music_fx[N_MIXTURES]; +extern const Word32 invV_music_fx[N_MIXTURES*N_FEATURES*N_FEATURES]; +extern const Word16 m_music_fx[N_MIXTURES*N_FEATURES]; +extern const Word32 invV_speech_fx[N_MIXTURES*N_FEATURES*N_FEATURES]; +extern const Word32 lvm_speech_fx[N_MIXTURES]; +extern const Word16 m_speech_fx[N_MIXTURES*N_FEATURES]; +extern const Word16 inv_delta_tab[7]; + +extern const Word16 lsf_unified_fit_model_nb[4][16]; +extern const Word16 lsf_unified_fit_model_wb[4][16]; +extern const Word16 lsf_unified_fit_model_wbhb[4][16]; + +extern const Word32 Freq_Weight_Com_fx[160]; +extern const Word32 Freq_Weight_UV_fx[160]; /*Q31*/ +extern const Word16 hann_window_320_fx[]; +extern const Word16 W_HIST_FX[]; +extern const Word16 W_HIST_S_FX[]; + + +/*----------------------------------------------------------------------------------* + * Huffman coding + *----------------------------------------------------------------------------------*/ + +extern const Word16 huffsizn_e_fx[32]; +extern const Word16 huffsizn_n_fx[32]; + +extern const Word16 huffnorm_e_fx[32]; +extern const Word16 huffnorm_n_fx[32]; +extern const Word16 hessize_fx[8]; +extern const Word16 hescode_fx[8]; + +extern const Word16 resize_huffnorm_fx[32]; +extern const Word16 huffnorm_fx[32]; +extern const Word16 pgain_huffnorm_fx[32]; + +extern const Word16 Weight[86]; +extern const Word16 kLowPeriodicityThr[2]; /* ari_hm_enc.c */ + +extern const UWord8 E_ROM_tipos[]; /* ACELP indexing */ + +extern const Word16 lsf_numlevels[TCXLPC_NUMSTAGES]; +extern const Word16 lsf_ind_numlevels[TCXLPC_IND_NUMSTAGES]; + +/*----------------------------------------------------------------------------------* + * Starting line for the noise measurement in TCX. + *----------------------------------------------------------------------------------*/ +extern const Word16 startLineWB[11]; +extern const Word16 startLineSWB[9]; + +/*----------------------------------------------------------------------------------* +* CLDFB-VAD +*----------------------------------------------------------------------------------*/ +extern const Word16 BAND_NUM_TAB[5]; +extern const Word16 BAND_SCALE_AJ[5]; +extern const Word32 LS_MIN_SILENCE_SNR[4] ; +extern const Word32 LT_MIN_SILENCE_SNR[4] ; +extern const Word16 Nregion_index_NB[9]; +extern const Word16 Nregion_index_WB[13]; +extern const Word16 Nregion_index_SWB[16] ; +extern const Word16 Nregion_index_FB[16] ; +extern const Word16 Nregion_preoff[12]; +extern const Word16 SNR_SUB_BAND_NUM[4]; +extern const Word16 BAND_MUL[4] ; +extern const Word16 *REGION_INDEX[4] ; +extern const Word32 MAX_LF_SNR_TAB[5]; +extern const Word16 band_num[4]; +extern const Word32 COMVAD_INIT_SNR_DELTA[5]; +extern const Word16 i_t_1[10]; +extern const Word16 i_t_2[23]; +extern const complex_16 wnk_table_16[16]; +extern const complex_16 M_in_fix16[16]; +extern const Word16 M_Wr_fix16[16]; +extern const Word16 M_Wi_fix16[16]; + +/* bw_detect_fx.c */ +extern const Word16 bwd_start_bin_fx[4]; +extern const Word16 bwd_end_bin_fx[4]; + +#endif /* ROM_ENC_FX_H */ + diff --git a/lib_enc/rst_enc_fx.c b/lib_enc/rst_enc_fx.c new file mode 100644 index 0000000..ed721e3 --- /dev/null +++ b/lib_enc/rst_enc_fx.c @@ -0,0 +1,69 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * CNG_reset_enc() + * + * Reset encoder static variables after a CNG frame + *-------------------------------------------------------------------*/ + +void CNG_reset_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + LPD_state *mem, /* i/o: acelp memories */ + Word16 *pitch_buf, /* o : floating pitch for each subframe */ + Word16 *voice_factors /* o : voicing factors */ + ,Word16 VBR_cng_reset_flag +) +{ + init_gp_clip_fx( st_fx->clip_var_fx ); + Copy( UVWB_Ave_fx, st_fx->mem_AR_fx, M ); + set16_fx( st_fx->mem_MA_fx, 0, M ); + mem->mem_w0 = 0; + move16(); + mem->tilt_code = 0; + move16(); + mem->gc_threshold = 0; + move16(); + IF( EQ_16(VBR_cng_reset_flag,1)) + { + set16_fx( mem->mem_syn, 0, M ); + } + /*set16_fx( st_fx->dispMem_fx , 0, 8 ); */ + set16_fx( st_fx->dm_fx.prev_gain_pit , 0, 6 ); + st_fx->dm_fx.prev_gain_code = L_deposit_l(0); + st_fx->dm_fx.prev_state = 0; + move16(); + + /* last good received frame for FEC in ACELP */ + st_fx->clas_fx = UNVOICED_CLAS; + move16(); + + /* reset the pitch buffer in case of FRAME_NO_DATA or SID frames */ + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + set16_fx( pitch_buf, L_SUBFR, NB_SUBFR ); + } + ELSE /* st->L_frame == L_FRAME16k */ + { + set16_fx( pitch_buf, L_SUBFR16k, NB_SUBFR16k ); + } + + set16_fx( voice_factors, 1, NB_SUBFR16k ); + + /* deactivate bass post-filter */ + st_fx->bpf_off_fx = 1; + move16(); + + /* Reset active frame counter */ + st_fx->act_cnt2_fx = 0; + move16(); + + return; +} diff --git a/lib_enc/scale_enc_fx.c b/lib_enc/scale_enc_fx.c new file mode 100644 index 0000000..b319cb3 --- /dev/null +++ b/lib_enc/scale_enc_fx.c @@ -0,0 +1,273 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * Scale_wsp + * + * Find scaling factor for weighted speech input + *-------------------------------------------------------------------*/ +void Scale_wsp( + Word16 *wsp, /* i : Weigthed speech */ + Word16 *old_wsp_max, /* i : Last weigthed speech maximal valu */ + Word16 *shift, /* i/o: Scaling of current frame */ + Word16 *Q_exp, /* i/o: Differential scaling factor */ + Word16 *old_wsp_shift, /* i/o: Last wsp scaling */ + Word16 *old_wsp, /* i/o: Old weighted speech buffer */ + Word16 *mem_decim2, /* i/o: Decimation buffer */ + Word16 *old_wsp12k8, /* i/o: wsp memory @ 12.8 kHz used in pitol2 */ + const Word16 Len_p_look /* i : L_frame + look ahead */ +) +{ + Word16 max, i, tmp; + + /* find maximum value on wsp[] for 12 bits scaling */ + max = 0; + move16(); + FOR (i = 0; i < Len_p_look; i++) + { + tmp = abs_s(wsp[i]); + max = s_max(max,tmp); + } + tmp = *old_wsp_max; + move16(); + tmp = s_max(max, tmp); + *old_wsp_max = max; + move16(); + + *shift = sub(norm_s(tmp), 3); + move16(); + + *shift = s_min(*shift, 0); + move16(); /* shift = 0..-3 */ + + + Scale_sig(wsp, Len_p_look, *shift); + /* scale old_wsp (warning: exp must be Q_new-Q_old) */ + *Q_exp= add(*Q_exp, sub(*shift, *old_wsp_shift)); + move16(); + *old_wsp_shift = *shift; + move16(); + Scale_sig(old_wsp12k8, L_WSP_MEM, *Q_exp); /* Already scaled with premphasis */ + Scale_sig(old_wsp, (L_WSP_MEM - L_INTERPOL)/OPL_DECIM, *Q_exp ); + Scale_sig(mem_decim2, 3, *Q_exp); + + Copy( old_wsp12k8, wsp - L_WSP_MEM, L_WSP_MEM ); /* Now memory and wsp vector have the same scaling */ +} + +/*-------------------------------------------------------------------* + * Preemph_scaled + * + * Find scaled preemphasis vector and its scaling factor + *-------------------------------------------------------------------*/ +void Preemph_scaled( + Word16 new_speech[], /* i : Speech to scale already on 14 bits*/ + Word16 *Q_new, /* o : Scaling factor */ + Word16 *mem_preemph, /* i/o: Preemph memory */ + Word16 *Q_max, /* i/o: Q_new limitation */ + const Word16 Preemph_factor, /* i : Preemphasis factor Q15 */ + const Word16 bits, /* i : Bit to remove from the output to (15-bits)*/ + const Word16 bit1, /* i : Limit the output scaling to ((15-bits)-bit1) bits */ + const Word16 L_Q_mem, /* i : Number of old scaling to take into account */ + const Word16 Lframe, /* i : Frame length */ + const Word16 last_coder_type, /* i : coder_type */ + const Word16 Search_scaling /* i : enable the search of a proper scaling factor*/ +) +{ + Word16 i, tmp_fixed; + Word16 mu, shift, QVal; + Word32 L_tmp, L_maxloc; + Word16 Q_min; + + /*---------------------------------------------------------------* + * Perform fixed preemphasis through 1 - g z^-1 * + * Scale signal to get maximum of precision in filtering * + *---------------------------------------------------------------*/ + + BASOP_SATURATE_WARNING_OFF + QVal = shl(1, sub(15,bits)); + BASOP_SATURATE_WARNING_ON + mu = shr(Preemph_factor, bits); /* Q15 --> Q(15-bits) */ + + IF(EQ_16(Search_scaling,1)) + { + /* get max of new preemphased samples (L_FRAME+L_FILT) */ + + L_tmp = L_mult(new_speech[0], QVal); + L_tmp = L_msu(L_tmp, *mem_preemph, mu); + L_maxloc = L_abs(L_tmp); + + FOR (i = 1; i < Lframe; i++) + { + /* Equivalent to tmp = max((abs(x[i] - mu*x[i-1]),tmp) + * finds the max of preemphasized signal */ + L_tmp = L_mult(new_speech[i], QVal); + L_tmp = L_msu(L_tmp, new_speech[i - 1], mu); + L_tmp = L_abs(L_tmp); + L_maxloc = L_max(L_tmp, L_maxloc); + } + + /* get scaling factor for new and previous samples */ + /* limit scaling to Q_MAX to keep dynamic for ringing in low signal */ + /* limit scaling to Q_MAX also to avoid a[0]<1 in syn_filt_32 */ + tmp_fixed = s_max(extract_h(L_maxloc),1); + + /* output on 14 bits: needed unless the resampling itself removes 1 bit*/ + shift = sub(norm_s(tmp_fixed), add(bits,bit1)); + shift = s_max(shift, 0); + shift = s_min(shift, Q_MAX); + + minimum_fx(Q_max, L_Q_mem, &Q_min); + *Q_new = s_min(shift, Q_min); + move16(); + + IF (tmp_fixed == 0) + { + IF ( NE_16(last_coder_type, UNVOICED)) + { + *Q_new = s_min(*Q_new, 1); + move16(); + } + } + + FOR(i = L_Q_mem-1; i > 0; i--) + { + Q_max[i] = Q_max[i-1]; + move16(); + } + Q_max[i] = shift; + move16(); + } + + /*---------------------------------------------------------------* + * preemphasis with scaling (L_FRAME+L_FILT) + * now do the actual preemphasis, since we have the + * proper scaling factor. + * Done backwards to save storage space + *---------------------------------------------------------------*/ + + tmp_fixed = new_speech[Lframe - 1]; + move16(); + + FOR (i = sub(Lframe,1); i > 0; i--) + { + L_tmp = L_mult(new_speech[i], QVal); + L_tmp = L_msu(L_tmp, new_speech[i - 1], mu); + L_tmp = L_shl(L_tmp, *Q_new); + new_speech[i] = round_fx(L_tmp); + } + + L_tmp = L_mult(new_speech[0], QVal); + L_tmp = L_msu(L_tmp, *mem_preemph, mu); + L_tmp = L_shl(L_tmp, *Q_new); + new_speech[0] = round_fx(L_tmp); + + *mem_preemph = tmp_fixed; + move16(); +} +/*-------------------------------------------------------------------* + * Scale_mem + * + * Rescale memories + *-------------------------------------------------------------------*/ +Word32 Scale_mem_pre_proc( /* o : Min energy scaled */ + Word16 ini_frame_fx, /* i : Frame number */ + Word16 Q_exp, /* i : Diff scaling factor */ + Word16 *Q_new, /* i/o: Absolute scaling factor */ + Word16 *old_speech, /* i/o: Speech memory */ + Word16 *mem_wsp, /* i/o: wsp vector memory */ + Word32 *enrO, /* i/o: Enr mem */ + Word32 *bckr, /* i/o: Back ground_fx ener mem */ + Word32 *ave_enr, /* i/o: Ave_enr mem */ + Word32 *ave_enr2, /* i/o: Ave_enr2 mem */ + Word32 *st_fr_bands1, /* i/o: spectrum per critical bands of the previous frame */ + Word32 *st_fr_bands2, /* i/o: spectrum per critical bands 2 frames ago */ + Word32 *st_Bin_E_old +) +{ + Word16 i; + Word32 e_min_scaled; + + e_min_scaled = L_shr_r(L_add(L_shr(E_MIN_FXQ15,sub(14,add(*Q_new,QSCALE))),1),1); + + /* scale previous samples and memory (Q_exp - Q_new - Q_old) */ + /* Scale( x, y, z ) : shift left vector x of size y by z bits ) */ + IF (Q_exp != 0) + { + IF(old_speech != NULL) + { + Scale_sig(old_speech, L_INP_MEM, Q_exp); + } + Scale_sig(mem_wsp, 1, Q_exp); + IF( ini_frame_fx ==0 ) + { + /* Scaling noise vectors if frame ==1*/ + Scale_sig32(enrO, NB_BANDS,*Q_new); + Scale_sig32(bckr, NB_BANDS, *Q_new); + Scale_sig32(ave_enr, NB_BANDS, *Q_new); + Scale_sig32(ave_enr2, NB_BANDS, *Q_new); + Scale_sig32(st_fr_bands1, NB_BANDS, *Q_new); + Scale_sig32(st_fr_bands2, NB_BANDS, *Q_new); + Scale_sig32(st_Bin_E_old, L_FFT/2, *Q_new); + } + ELSE + { + /* Do scaling and valide minimum energy value */ + FOR (i = 0; i < NB_BANDS; i++) + { + enrO[i] = L_max(L_shl(enrO[i], Q_exp),e_min_scaled); + move32(); + bckr[i] = L_max(L_shl(bckr[i], Q_exp),e_min_scaled); + move32(); + ave_enr[i] = L_max(L_shl(ave_enr[i], Q_exp),e_min_scaled); + move32(); + ave_enr2[i] = L_max(L_shl(ave_enr2[i], Q_exp),e_min_scaled); + move32(); + st_fr_bands1[i] = L_max(L_shl(st_fr_bands1[i], Q_exp),e_min_scaled); + move32(); + st_fr_bands2[i] = L_max(L_shl(st_fr_bands2[i], Q_exp),e_min_scaled); + move32(); + } + } + } + return e_min_scaled; +} + +void Scale_mem_enc( + Word16 Q_exp, /* i : Diff scaling factor */ + Word16 *old_speech16k, /* i/o: Speech memory */ + Word16 *old_exc, /* i/o: excitation memory */ + Word16 *old_bwe_exc, /* i/o: BWE excitation memory */ + Word16 *mem_w0, /* i/o: target vector memory */ + Word16 *mem_syn, /* i/o: synthesis memory */ + Word16 *mem_syn2, /* i/o: synthesis memory */ + Word16 *mem_deemp_preQ_fx, /*i/o: deemphasis memory for the high rate celp codec */ + Word16 *last_exc_dct_in, + Word16 *old_input_lp +) +{ + /* scale previous samples and memory (Q_exp - Q_new - Q_old) */ + /* Scale( x, y, z ) : shift left vector x of size y by z bits ) */ + IF (Q_exp != 0) + { + Scale_sig(old_speech16k, L_INP_MEM, Q_exp); + Scale_sig(mem_w0, 1, Q_exp); + /* Scaling excitation */ + Scale_sig(old_exc,L_EXC_MEM, Q_exp); + Scale_sig(old_bwe_exc, PIT16k_MAX*2, Q_exp); + Scale_sig(mem_syn, M, Q_exp); + Scale_sig(mem_syn2, M, Q_exp); + Scale_sig(last_exc_dct_in,L_FRAME, Q_exp); + Scale_sig(mem_deemp_preQ_fx, 1, Q_exp); + Scale_sig(old_input_lp, NS2SA(16000, ACELP_LOOK_NS + DELAY_SWB_TBE_16k_NS + DELAY_FIR_RESAMPL_NS), Q_exp); + } + + return; +} + diff --git a/lib_enc/set_impulse_fx.c b/lib_enc/set_impulse_fx.c new file mode 100644 index 0000000..76f0a25 --- /dev/null +++ b/lib_enc/set_impulse_fx.c @@ -0,0 +1,348 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-----------------------------------------------------------------* + * Local constant + *-----------------------------------------------------------------*/ +#define INPOL 4 /* +- range in samples for impulse position searching */ + +/*-----------------------------------------------------------------* + * Local function prototype + *-----------------------------------------------------------------*/ +static void convolve_tc_fx(const Word16 g[],const Word16 h[],Word16 y[],const Word16 L_1,const Word16 L_2); +static void correlate_tc_fx(const Word16 *x, Word16 *y, const Word16 *h, const Word16 start, const Word16 L_1,const Word16 L_2); +static void convolve_tc2_fx(const Word16 g[],const Word16 h[], Word16 y[], const Word16 pos_max); + +/*---------------------------------------------------------------------------------------* + * Function set_impulse() for TC * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * + * Builds glottal codebook contribution based on glotal impulses positions finding. * + * * + * Returns a position of the glotal impulse center and * + * a number of the glotal impulse shape. * + * * + * |----| |----| xn * + * imp_pos-> || | imp_shape-> | g1 | | * + * | | | | g2 | exc |---| y1 ---- | * + * | | |--------------| |---------| h |-------|gain|-------(-)---> xn2 * + * | || | gn | |---| ---- * + * |----| |----| * + * codebook excitation h_orig gain * + * * + * * + * nominator dd * * + * Searching criterion: maximize ------------- = ---- = ----------------- * + * denominator rr * + * * + * Notice: gain = gain_trans * gain_pit (computed in trans_enc() function) * + * * + *---------------------------------------------------------------------------------------*/ +void set_impulse_fx( + const Word16 xn_fx[], /* i : target signal */ + const Word16 h_orig_fx[], /* i : impulse response of weighted synthesis filter */ + Word16 exc_fx[], /* o : adaptive codebook excitation */ + Word16 yy1_fx[], /* o : filtered adaptive codebook excitation */ + Word16 *imp_shape, /* o : adaptive codebook index */ + Word16 *imp_pos, /* o : position of the glotal impulse center index */ + Word32 *gain_trans_fx, /* o : transition gain Q7 */ + Word16 Q_new /* i : Current scaling */ +) +{ + Word16 i, j, m; + Word16 start1, start2, end1; + Word32 rr_fx[L_SUBFR]; /* criterion: nominator coeficients */ + Word16 dd_fx[L_SUBFR],tmp16; /* criterion: denominator coeficients */ + Word16 gh_fx[L_SUBFR], num, den, exp_num, exp_den; /* convolution of 'g' and 'h' filters */ + Word16 krit_fx, krit_max_fx, gain16; + Word32 Lrr, Ldd, Ltmp,Ltmp1; + const Word16 *pt_Glt; + krit_max_fx = -32768; + move16(); + + /* main loop */ + /* impulse */ + FOR (m = 0; m < NUM_IMPULSE; m++) + { + /* set searching ranges */ + IF (LT_16(*imp_pos, L_SUBFR-INPOL)) + { + end1 = add(*imp_pos, INPOL); + } + ELSE + { + end1 = L_SUBFR; + move16(); + } + IF (GT_16(*imp_pos, INPOL)) + { + start1 = sub(*imp_pos, INPOL); + } + ELSE + { + start1 = 0; + move16(); + } + IF (GT_16(start1, L_IMPULSE2)) + { + start2 = start1; + move16(); + } + ELSE + { + start2 = L_IMPULSE2; + move16(); + } + + /*-----------------------------------------------------------* + * nominator & DEnominator, gh=convolve(g,h) + *-----------------------------------------------------------*/ + IF (LT_16(start1, L_IMPULSE2)) + { + Lrr = L_deposit_l(0); + Ldd = L_deposit_l(0); + convolve_tc_fx(&Glottal_cdbk_fx[m*L_IMPULSE+L_IMPULSE2-start1], + &h_orig_fx[0], gh_fx, add(L_IMPULSE-L_IMPULSE2, start1), L_SUBFR); + + /* nominator & DEnominator row <0> */ + FOR (i=0; i < L_SUBFR; i++) + { + Lrr = L_mac(Lrr, gh_fx[i], gh_fx[i]); + Ldd = L_mac(Ldd, gh_fx[i], xn_fx[i]); + } + rr_fx[start1] = Lrr; + move32(); + dd_fx[start1] = round_fx(Ldd); + rr_fx[start1] = L_max(rr_fx[start1], 1); + + FOR (i=add(start1, 1); i */ + FOR (j = L_SUBFR-1; j > 0; j--) + { + /* gh_fx[j] = gh_fx[j-1] + glottal_cdbk[m*L_IMPULSE+L_IMPULSE2-i]*h_orig_fx[j] */ + gh_fx[j] = mac_r(L_deposit_h(gh_fx[j-1]), + Glottal_cdbk_fx[m*L_IMPULSE+L_IMPULSE2-i], h_orig_fx[j]); + move16(); + Lrr = L_mac(Lrr, gh_fx[j], gh_fx[j]); + Ldd = L_mac(Ldd, gh_fx[j], xn_fx[j]); + } + + gh_fx[0] = mult_r(Glottal_cdbk_fx[m*L_IMPULSE+L_IMPULSE2-i],h_orig_fx[0]); + move16(); + Lrr = L_mac(Lrr, gh_fx[0], gh_fx[0]); + Ldd = L_mac(Ldd, gh_fx[0], xn_fx[0]); + dd_fx[i] = round_fx(Ldd); + rr_fx[i] = L_max(Lrr, 1); + move32(); + /* move rr and dd into rr[i] and dd[i] */ + } + + /* complete convolution(excitation,h_orig) */ + FOR (j=L_SUBFR-1; j > 0; j--) + { + gh_fx[j] = mac_r(L_deposit_h(gh_fx[j-1]), + Glottal_cdbk_fx[m*L_IMPULSE], h_orig_fx[j]); + } + } + ELSE + { + convolve_tc_fx(&Glottal_cdbk_fx[m*L_IMPULSE], h_orig_fx, gh_fx, L_IMPULSE, L_SUBFR); + } + + IF (GE_16(end1, start2)) + { + /* DEnominator row */ + Lrr = L_mult(gh_fx[0], gh_fx[0]); + FOR (j=1; j <= L_IMPULSE2; j++) + { + /*rr[L_SUBFR-1] += gh[j]*gh[j];*/ + Lrr = L_mac(Lrr, gh_fx[j], gh_fx[j]); + } + rr_fx[L_SUBFR-1] = Lrr; + move32(); + /* DEnominator rows */ + FOR (i = L_SUBFR-2; i >= start2; i--) + { + /*rr[i] = rr[i+1] + gh[L_SUBFR+L_IMPULSE2-1-i]*gh[L_SUBFR+L_IMPULSE2-1-i];*/ + rr_fx[i] = L_mac(rr_fx[i+1], gh_fx[L_SUBFR+L_IMPULSE2-1-i], + gh_fx[L_SUBFR+L_IMPULSE2-1-i]); + move32(); + } + /* nominator rows */ + correlate_tc_fx(xn_fx, &dd_fx[L_IMPULSE2], gh_fx, sub(start2, L_IMPULSE2), + L_SUBFR, sub(end1, L_IMPULSE2)); + } + /*------------------------------------------------------------* + * maxim. criterion + *------------------------------------------------------------*/ + FOR (i = start1; i < end1; i++) + { + /* krit = (float)(dd[i]*dd[i])/rr[i] */ + exp_num = sub(norm_s(dd_fx[i]), 1); + num = shl(dd_fx[i], exp_num); + num = mult_r(num, num); + + exp_den = norm_l(rr_fx[i]); + den = extract_h(L_shl(rr_fx[i], exp_den)); + + num = div_s(num,den); + krit_fx = shr(num, sub(sub(shl(exp_num, 1), exp_den), 2)); /* Q18 */ + + IF (GT_16(krit_fx, krit_max_fx)) + { + krit_max_fx = krit_fx; + move16(); + *imp_pos = i; + move16(); + *imp_shape = m; + move16(); + } + } + } + + /*---------------------------------------------------------------* + * Build the excitation using found codeword + *---------------------------------------------------------------*/ + + set16_fx(exc_fx, 0, L_SUBFR); + set16_fx(yy1_fx, 0, L_SUBFR); + tmp16 = sub(extract_l(L_mac0(L_IMPULSE2, *imp_shape, L_IMPULSE)), *imp_pos); + pt_Glt = &Glottal_cdbk_fx[tmp16]; + move16(); + j = add(*imp_pos, L_IMPULSE2); + FOR (i = sub(*imp_pos, L_IMPULSE2); i <= j; i++) + { + test(); + if (i >= 0 && LT_16(i, L_SUBFR)) + { + exc_fx[i] = pt_Glt[i]; + move16();/*Q13*/ + } + } + + /*---------------------------------------------------------------* + * Form filtered excitation, find gain_trans + *---------------------------------------------------------------*/ + convolve_tc2_fx(exc_fx, h_orig_fx, yy1_fx, *imp_pos); + + /* Find the ACELP correlations and the pitch gain (for current subframe) */ + /**gain_trans = dot_product( xn, yy1, L_SUBFR )/(dot_product( yy1, yy1, L_SUBFR ) + 0.01f);*/ + /* Compute scalar product */ + Ltmp = Dot_product(yy1_fx, yy1_fx, L_SUBFR); + exp_den = norm_l(Ltmp); + den = extract_h(L_shl(Ltmp, exp_den)); + + /* Compute scalar product */ + Ltmp1 = Dot_product(xn_fx, yy1_fx, L_SUBFR); + exp_num = sub(norm_l(Ltmp1), 1); + num = extract_h(L_shl(Ltmp1, exp_num)); + tmp16 = s_or(shr(num, 16), 1); /* extract sign if num < 0 tmp16 = -1 else tmp16 = 1 */ + num = abs_s(num); + + /* compute gain = xy/yy */ + gain16= div_s(num, den); + + i = add(exp_num, sub(Q_new, 1+1+3)); + i = sub(i, exp_den); /* Gain_trans in Q7 */ + gain16 = i_mult2(gain16, tmp16);/* apply sign */ + *gain_trans_fx = L_shr(L_deposit_l(gain16), i); + move32(); + +} +/*-------------------------------------------------------------------* + * convolve_tc_fx: + * + * convolution for different vectors' lengths + *-------------------------------------------------------------------*/ +static void convolve_tc_fx( + const Word16 g[], /* i : input vector Qx */ + const Word16 h[], /* i : impulse response (or second input vector) Q15 */ + Word16 y[], /* o : output vetor (result of convolution) 12 bits */ + const Word16 L_1, /* i : vector h size */ + const Word16 L_2 /* i : vector g size */ +) +{ + Word16 i, n, len; + Word32 L_sum; + + FOR (n = 0; n < L_2; n++) + { + len = s_min(add(n,1), L_1); + L_sum = L_mult(g[0], h[n]); + FOR (i = 1; i < len; i++) + { + L_sum = L_mac(L_sum, g[i], h[n - i]); + } + + y[n] = round_fx(L_sum); /* Q12*/ + } +} +/*-------------------------------------------------------------------* + * convolve_tc2_fx: + * + * convolution for one vector with only L_IMPULSE nonzero coefficients + *-------------------------------------------------------------------*/ +static void convolve_tc2_fx( + const Word16 g[], /* i : input vector Qx */ + const Word16 h[], /* i : impulse response (or second input vector) Q15 */ + Word16 y[], /* o : output vetor (result of convolution) 12 bits */ + const Word16 pos_max /* o : artificial impulse position */ +) +{ + Word32 temp; + Word16 i, n; + Word16 i_start, i_end, i_end2; + + i_start = sub(pos_max,L_IMPULSE2); + i_start = s_max(i_start, 0); + + i_end = add(pos_max, L_IMPULSE); + i_end = s_min(i_end, L_SUBFR); + + FOR (n = i_start; n < L_SUBFR; n++) + { + temp = L_mult(g[0], h[n]); + i_end2 = s_min(add(n, 1), i_end); + + FOR (i = 1; i < i_end2; i++) + { + temp = L_mac(temp, g[i], h[n-i]); + } + y[n] = round_fx(temp); + } +} +/*-------------------------------------------------------------------* + * correlate_tc: + * + * correlation for different vectors' lengths + *-------------------------------------------------------------------*/ +static void correlate_tc_fx( + const Word16 *x, /* i: target signal */ + Word16 *y, /* o: correlation between x[] and h[] -Q3 */ + const Word16 *h, /* i: impulse response (of weighted synthesis filter) */ + const Word16 start, /* i: index of iterest */ + const Word16 L_1, /* i: vector size */ + const Word16 L_2 /* i: index of interest */ +) +{ + Word16 i, j; + Word32 s; + + FOR (i = start; i < L_2; i++) + { + s = L_deposit_l(0); + FOR (j = i; j < L_1; j++) + { + s = L_mac(s, x[j],h[j-i]); + } + y[i] = round_fx(s); + } +} diff --git a/lib_enc/setmodeindex.c b/lib_enc/setmodeindex.c new file mode 100644 index 0000000..e9c3702 --- /dev/null +++ b/lib_enc/setmodeindex.c @@ -0,0 +1,50 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include + +#include "options.h" +#include "stl.h" +#include "prot_fx.h" +#include "cnst_fx.h" +#include "rom_com_fx.h" +#include "rom_enc_fx.h" + +/*--------------------------------------------------------------------------- + + function name: SetModeIndex + description: function for configuring the codec between frames - currently bit rate and bandwidth only + must not be called while a frame is encoded - hence mutexes must be used in MT environments + + format: BANDWIDTH*16 + BITRATE (mode index) + + ---------------------------------------------------------------------------*/ + +void SetModeIndex( + Encoder_State_fx *st, + Word32 total_brate, + Word16 bwidth, + const Word16 shift) +{ + + /* Reconfigure the core coder */ + test(); + test(); + test(); + IF( + (NE_32(st->last_total_brate_fx,total_brate) ) || + (NE_16(st->last_bwidth_fx,bwidth) ) || + (EQ_16(st->last_codec_mode,MODE1) ) + || (NE_16(st->rf_mode_last,st->rf_mode) ) + ) + { + core_coder_mode_switch( st, st->bwidth_fx, total_brate, shift); + } + + + return; +} diff --git a/lib_enc/sig_clas.c b/lib_enc/sig_clas.c new file mode 100644 index 0000000..548c1f7 --- /dev/null +++ b/lib_enc/sig_clas.c @@ -0,0 +1,378 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define K_COR_FX 23405 /* Q13 2.857 */ +#define C_COR_FX -10535 /* Q13 -1.286 */ + +#define K_EE_FX 1365 /* Q15 0.04167 */ +#define C_EE_FX 0 + +#define K_ZC_FX -1311 /* Q15 -0.04 */ +#define C_ZC_FX 19661 /* Q13 2.4 */ + +#define K_RELE_FX 1638 /* Q15 0.05 */ +#define C_RELE_FX 14746 /* Q15 0.45 */ + +#define K_PC_FX -2341 /* Q15 -0.07143*/ +#define C_PC_FX 30425 /* Q1 1.857 */ + +#define K_SNR_FX 3541 /* Q15 .1111 */ +#define C_SNR_FX -10921 /* Q15 -0.3333f */ + + +#define THRES_EEN 514206 /* 251.077 => (10^(1/(K_EE*10))) Q11*/ + +/*-------------------------------------------------------------------* + * signal_clas_fx() + * + * classification state machine for FEC + * TC frames selection + *-------------------------------------------------------------------*/ + +Word16 signal_clas_fx( /* o : classification for current frames */ + Encoder_State_fx *st, /* i/o: encoder state structure */ + Word16 *coder_type, /* i/o: coder type */ + const Word16 voicing[3], /* i : normalized correlation for 3 half-frames */ + const Word16 *speech, /* i : pointer to speech signal for E computation */ + const Word16 localVAD, /* i : vad without hangover */ + const Word16 pit[3], /* i : open loop pitch values for 3 half-frames */ + const Word32 *ee, /* i : lf/hf E ration for 2 half-frames */ + const Word16 relE, /* i : frame relative E to the long term average */ + const Word16 L_look , /* i : look-ahead */ + Word16 *uc_clas /* o : temporary classification used in music/speech class*/ +) +{ + Word32 Ltmp; + Word16 mean_voi2, een, corn, zcn, relEn, pcn, fmerit1; + Word16 i, clas, pc, zc, lo, lo2, hi, hi2, exp_ee, frac_ee; + Word16 tmp16, tmpS; + const Word16 *pt1; + Word16 unmod_coder_type; + + /*----------------------------------------------------------------* + * Calculate average voicing + * Calculate average spectral tilt + * Calculate zero-crossing rate + * Calculate pitch stability + *----------------------------------------------------------------*/ + + /* average voicing on second half-frame and look-ahead */ + Ltmp = L_mult(voicing[1], 16384); + mean_voi2 = mac_r(Ltmp, voicing[2], 16384); + + /* average spectral tilt in dB */ + lo = L_Extract_lc(ee[0], &hi); + lo2 = L_Extract_lc(ee[1], &hi2); + Ltmp = L_mult(lo, lo2); /* Q5*Q5->Q11 */ + + test(); + test(); + IF (LT_32(Ltmp, 2048)) + { + een = 0; + move16(); + } + ELSE IF (GT_32(Ltmp, THRES_EEN)||hi>0||hi2>0) + { + een = 512; + move16(); + } + ELSE + { + /* mean_ee2 = 0.5f * 20.0f * (float)log10( tmp ); */ + /* een = K_EE_ENC * mean_ee2 + C_EE_ENC; */ + exp_ee = norm_l(Ltmp); + frac_ee = Log2_norm_lc(L_shl(Ltmp, exp_ee)); + exp_ee = sub(30-11, exp_ee); + Ltmp = Mpy_32_16(exp_ee, frac_ee, LG10); /* Ltmp Q14 */ + een = round_fx(L_shl(Ltmp, 16-5)); /* Q14 -> Q9 */ + een = mac_r(C_EE_FX, een, K_EE_FX); + } + + /* compute zero crossing rate */ + pt1 = speech + L_look - 1; + tmpS = shr(*pt1, 15); /* sets 'tmpS to -1 if *pt1 < 0 */ + Ltmp = L_deposit_l(0); + FOR (i = 0; i < L_FRAME; i++) + { + tmp16 = add(1, tmpS); + pt1++; + tmpS = shr(*pt1, 15); /* pt1 >=0 ---> 0 OTHERWISE -1 */ + Ltmp = L_msu0(Ltmp, tmpS, tmp16); + } + zc = extract_l(Ltmp); + + /* compute pitch stability */ + pc = add( abs_s(sub(pit[1], pit[0])), abs_s(sub(pit[2], pit[1]))); + + /*-----------------------------------------------------------------* + * Transform parameters to the range <0:1> + * Compute the merit function + *-----------------------------------------------------------------*/ + + /* corn = K_COR * mean_voi2 + C_COR */ + Ltmp = L_mult(C_COR_FX, 32767); + corn = round_fx(L_shl(L_mac(Ltmp, mean_voi2, K_COR_FX),-4)); /*Q13+Q13*Q15 =>Q13->Q9*/ + /* Limit [0, 1] */ + corn = s_max(corn, 0); + corn = s_min(corn, 512); + + Ltmp = L_mult(C_ZC_FX, 4); /*Q13*Q2 -> Q16*/ + zcn = round_fx(L_shl(L_mac(Ltmp, zc, K_ZC_FX),16-7)); /*Q0*Q15 + Q16*/ + /* Limit [0, 1] */ + zcn = s_max(zcn, 0); + zcn = s_min(zcn, 512); + + Ltmp = L_mult(C_RELE_FX, 256); /*Q15 ->Q24*/ + relEn = round_fx(L_shl(L_mac(Ltmp, relE, K_RELE_FX), 1)); /*relE in Q8 but relEn in Q9*/ + /* Limit [0.5, 1] */ + relEn = s_max(relEn, 256); + relEn = s_min(relEn, 512); + + Ltmp = L_mult(C_PC_FX, 2); /*Q14*Q1 -> Q16*/ + pcn = round_fx(L_shl(L_mac(Ltmp, pc, K_PC_FX),16-7)); /*Q16 + Q0*Q15*/ + /* Limit [0, 1] */ + pcn = s_max(pcn, 0); + pcn = s_min(pcn, 512); + + Ltmp = L_mult(een, 10923); + Ltmp = L_mac(Ltmp, corn, 21845); + Ltmp = L_mac(Ltmp, zcn, 10923); + Ltmp = L_mac(Ltmp, relEn, 10923); + Ltmp = L_mac(Ltmp, pcn, 10923); + + fmerit1 = round_fx(L_shl(Ltmp, 16-10-1)); /* fmerit1 ->Q15 */ + + /*-----------------------------------------------------------------* + * FEC classification + * Onset classification + *-----------------------------------------------------------------*/ + + + /* FEC classification */ + test(); + test(); + IF (localVAD == 0 || EQ_16(*coder_type,UNVOICED)||LT_16(relE,-1536)) + { + clas = UNVOICED_CLAS; + move16(); + } + ELSE + { + SWITCH (st->last_clas_fx) + { + case VOICED_CLAS: + case ONSET: + case VOICED_TRANSITION: + + IF (LT_16(fmerit1, 16056)) /*0.49f*/ + { + clas = UNVOICED_CLAS; + move16(); + } + ELSE IF (LT_16(fmerit1, 21626)) /*0.66*/ + { + clas = VOICED_TRANSITION; + move16(); + } + ELSE + { + clas = VOICED_CLAS; + move16(); + } + BREAK; + + case UNVOICED_CLAS: + case UNVOICED_TRANSITION: + IF (GT_16(fmerit1, 20643)) /*0.63*/ + { + clas = ONSET; + move16(); + } + ELSE IF (GT_16(fmerit1, 19169)) /*0.585*/ + { + clas = UNVOICED_TRANSITION; + move16(); + } + ELSE + { + clas = UNVOICED_CLAS; + move16(); + } + BREAK; + + default: + clas = UNVOICED_CLAS; + move16(); + BREAK; + } + } + + /* set flag for unvoiced class, it will be used in sp/mus classifier */ + *uc_clas = clas; + move16(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + if( ( (EQ_16(*coder_type,UNVOICED))|| + (NE_16(st->input_bwidth_fx,NB) && LT_16(fmerit1,13435) && GT_16(st->mold_corr_fx,21299) ) || /* WB case */ + (EQ_16(st->input_bwidth_fx,NB) && LT_16(mult_r(fmerit1,28836),13435) && GT_16(st->mold_corr_fx,18022) ) ) && /* NB case */ + GT_16(relE,-3840) && LT_16(st->lt_dec_thres_fx,768) ) /* to compute unvoiced on frame that tends to speech */ + { + *uc_clas = UNVOICED_CLAS; + move16(); + } + + /* Onset classification */ + + /* tc_cnt == -1: frame after TC frame in continuous block of GC/VC frames */ + /* tc_cnt == 0: UC frame */ + /* tc_cnt == 1: onset/transition frame, coded by GC mode */ + /* tc_cnt == 2: frame after onset/transition frame, coded by TC mode */ + + if( EQ_16(clas,UNVOICED_CLAS )) + { + st->tc_cnt_fx = 0; + move16(); + } + + test(); + if( GE_16(clas,VOICED_TRANSITION)&&st->tc_cnt_fx>=0) + { + st->tc_cnt_fx = add(st->tc_cnt_fx,1); + move16(); + } + + if( GT_16(st->tc_cnt_fx,2)) + { + st->tc_cnt_fx = -1; + move16(); + } + + IF ( EQ_16(st->codec_mode,MODE1)) + { + /*---------------------------------------------------------------------* + * Coder type modification + * + * Prevent UC mode in certain conditions + * Prevent VC mode in certain conditions + * Select TC mode in appropriate frames + *---------------------------------------------------------------------*/ + + /* At higher rates, use GC coding instead of UC coding to improve quality */ + test(); + if( GT_32(st->total_brate_fx,ACELP_9k60)&&EQ_16(*coder_type,UNVOICED)) + { + *coder_type = GENERIC; + move16(); + } + + /* Prevent UC coding on mixed content at 9.6 kb/s */ + test(); + test(); + if( EQ_32(st->total_brate_fx,ACELP_9k60)&&EQ_16(*coder_type,UNVOICED)&&st->audio_frame_cnt_fx!=0) + { + *coder_type = GENERIC; + move16(); + } + + unmod_coder_type = *coder_type; + move16(); + + /* Enforce GC mode on inactive signal (this can be later overwritten to INACTIVE) */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + if( localVAD == 0 && ( + ( + EQ_16(*coder_type,UNVOICED) + && ( ( st->Opt_SC_VBR_fx == 0) || ( ( st->Opt_SC_VBR_fx == 1 ) && st->vbr_generic_ho_fx == 0 && GT_16(st->last_coder_type_fx,UNVOICED) )) ) + || EQ_16(*coder_type,TRANSITION) || EQ_16(*coder_type,VOICED) ) + + ) + { + *coder_type = GENERIC; + move16(); + } + + test(); + test(); + if( EQ_16(*coder_type,GENERIC)&&EQ_16(unmod_coder_type,UNVOICED)&&(st->Opt_SC_VBR_fx==1)) + { + st->vbr_generic_ho_fx = 1; + move16(); + } + + test(); + if ( GT_16(*coder_type,UNVOICED)&&(st->Opt_SC_VBR_fx==1)) + { + st->vbr_generic_ho_fx = 0; + move16(); + } + + st->last_7k2_coder_type_fx = *coder_type; + move16(); + test(); + if( localVAD == 0 && EQ_16( *coder_type, UNVOICED )) + { + st->last_7k2_coder_type_fx = GENERIC; + move16(); + } + + /* Select TC mode for appropriate frames which is in general VOICED_TRANSITION, VOICED_CLAS or MODE1_ONSET frames following UNVOICED_CLAS frames */ + test(); + IF( localVAD != 0 && GE_16(st->tc_cnt_fx,1)) /* TC mode is allowed only in active signal */ + { + /* frame after onset/transition frame is coded by TC mode */ + *coder_type = TRANSITION; + move16(); + if ( EQ_16(st->tc_cnt_fx,1)) + { + /* onset/transition frame is always coded using GC mode */ + *coder_type = GENERIC; + move16(); + } + } + + /* At higher rates and with 16kHz core, allow only GC and TC mode */ + test(); + test(); + if( (GE_32(st->total_brate_fx,ACELP_24k40))&&NE_16(*coder_type,GENERIC)&&NE_16(*coder_type,TRANSITION)) + { + *coder_type = GENERIC; + move16(); + } + + /* Patch for certain low-level signals for which the gain quantizer sometimes goes out of its dynamic range */ + test(); + test(); + test(); + if( EQ_16(*coder_type,VOICED)&&EQ_16(st->input_bwidth_fx,NB)&<_16(relE,-2560)&&LE_32(st->total_brate_fx,ACELP_8k00)) + { + *coder_type = GENERIC; + move16(); + } + } + + return clas; +} diff --git a/lib_enc/spec_center.c b/lib_enc/spec_center.c new file mode 100644 index 0000000..428a107 --- /dev/null +++ b/lib_enc/spec_center.c @@ -0,0 +1,311 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "basop_util.h" +#include "stl.h" +#include "vad_basop.h" +#include "prot_fx.h" +#include "rom_enc_fx.h" + + + +void spec_center(Word32* sb_power, /*(i) energy of sub-band divided uniformly*/ + Word16* sp_center, /*(o) spectral center*/ + Word32 bandwith, /*(i) band width*/ + Word16 Q_sb_p /*(i) the Scaling of sb_power*/ + ) +{ + Word16 i; + + Word32 t_sp_center, frame_power; + Word32 t_sp_center_num, frame_power_den; + Word32 sb_power_mlt; + Word32 t_sp_center_nb, frame_power_nb; + Word32 zerop1; + Word32 sb_power_shr[24]; + + Word16 d_t_sp_center; + Word16 Q_t_sp_center, Q_frame_power; + Word16 Q_t_sc,Q_f_p; + Word16 d_t_sp_center_Qtmp; + + + zerop1 = 0; move32(); + t_sp_center = 0; move32(); + frame_power = 0; move32(); + + FOR (i=0; i<10; i++) + { + sb_power_shr[i] = L_shr(sb_power[i],5); + move32(); + } + + FOR(i=0; i<10; i++) + { + sb_power_mlt = Mpy_32_16_1(sb_power[i],i_t_1[i]); + t_sp_center = L_add(L_shr(sb_power_mlt,6), t_sp_center); + frame_power = L_add(sb_power_shr[i], frame_power);/*0-9 */ + } + + t_sp_center_nb = t_sp_center; move32(); + frame_power_nb = frame_power; move32(); + + /*+0.1 */ + Q_t_sc = sub(Q_sb_p, 10); + IF (GE_16(Q_t_sc,34)) + { + t_sp_center = L_shr(t_sp_center,sub(Q_t_sc, 33)); + zerop1 = L_shr(CNT0P1,1); + Q_t_sc = 33; + move16(); + } + ELSE + { + Q_t_sc = sub(Q_t_sc, 1); + t_sp_center = L_shr(t_sp_center,1); + zerop1 = L_shr(CNT0P1, sub(34, Q_t_sc)); + } + t_sp_center_num = L_add(t_sp_center, zerop1); + + Q_f_p = sub(Q_sb_p, 5); + IF (GE_16(Q_f_p,34)) + { + frame_power = L_shr(frame_power,sub(Q_f_p, 33)); + zerop1 = L_shr(CNT0P1,1); + Q_f_p = 33; + move16(); + } + ELSE + { + Q_f_p = sub(Q_f_p, 1); + frame_power = L_shr(frame_power,1); + zerop1 = L_shr(CNT0P1, sub(34, Q_f_p)); + } + + frame_power_den = L_add(frame_power, zerop1); + IF (frame_power == 0) + { + frame_power_den = CNT0P1; move32(); + Q_f_p = 34; + move16(); + } + /*div */ + Q_t_sp_center = sub(norm_l(t_sp_center_num), 1); + Q_frame_power = norm_l(frame_power_den); + t_sp_center_num = L_shl(t_sp_center_num,Q_t_sp_center); + frame_power_den = L_shl(frame_power_den,Q_frame_power); + + d_t_sp_center = div_l(t_sp_center_num,extract_h(frame_power_den)); + + d_t_sp_center_Qtmp = add(Q_t_sc,Q_t_sp_center); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,Q_frame_power); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,Q_f_p); + d_t_sp_center_Qtmp = add(d_t_sp_center_Qtmp,15); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,SP_CENTER_Q); + + d_t_sp_center = shr(d_t_sp_center,d_t_sp_center_Qtmp); + sp_center[0] = add(mult(sp_center[0],0x5999),mult(d_t_sp_center,0x2666)); + move16(); + sp_center[2] = d_t_sp_center; + move16(); + + t_sp_center = 0; move32(); + frame_power = 0; move32(); + IF(EQ_32(bandwith,CLDFBVAD_WB_ID)) + { + FOR (i=10; i<20; i++) + { + sb_power_shr[i] = L_shr(sb_power[i],5); + move32(); + } + + FOR(i=1; i<20; i++) + { + sb_power_mlt = Mpy_32_16_1(sb_power[i],i_t_2[i-1]); + t_sp_center = L_add(L_shr(sb_power_mlt,8), t_sp_center); + frame_power = L_add(sb_power_shr[i], frame_power);/*1-19 */ + } + /*+0.1 */ + Q_t_sc = sub(Q_sb_p, 13); + + IF (GE_16(Q_t_sc, 34)) + { + t_sp_center = L_shr(t_sp_center,sub(Q_t_sc, 33)); + zerop1 = L_shr(CNT0P1,1); + Q_t_sc = 33; + move16(); + } + ELSE + { + Q_t_sc = sub(Q_t_sc, 1); + t_sp_center = L_shr(t_sp_center,1); + zerop1 = L_shr(CNT0P1, s_min(31, sub(34, Q_t_sc))); + } + t_sp_center_num = L_add(t_sp_center, zerop1); + + Q_f_p = sub(Q_sb_p, 5); + IF (GE_16(Q_f_p,34)) + { + frame_power = L_shr(frame_power, sub(Q_f_p, 33)); + zerop1 = L_shr(CNT0P1,1); + Q_f_p = 33; + move16(); + } + ELSE + { + Q_f_p = sub(Q_f_p, 1); + frame_power = L_shr(frame_power,1); + zerop1 = L_shr(CNT0P1, sub(34, Q_f_p)); + } + frame_power_den = L_add(frame_power, zerop1); + IF (frame_power == 0) + { + frame_power_den = CNT0P1; move32(); + Q_f_p = 34; + move16(); + } + + /*div */ + Q_t_sp_center = sub(norm_l(t_sp_center_num), 1); + Q_frame_power = norm_l(frame_power_den); + t_sp_center_num = L_shl(t_sp_center_num,Q_t_sp_center); + frame_power_den = L_shl(frame_power_den,Q_frame_power); + + d_t_sp_center = div_l(t_sp_center_num,extract_h(frame_power_den)); + + d_t_sp_center_Qtmp = add(Q_t_sc,Q_t_sp_center); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,Q_frame_power); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,Q_f_p); + d_t_sp_center_Qtmp = add(d_t_sp_center_Qtmp,15); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,SP_CENTER_Q); + + sp_center[3]= shr(d_t_sp_center,d_t_sp_center_Qtmp); + move16(); + } + ELSE IF(EQ_32(bandwith, CLDFBVAD_SWB_ID)) + { + FOR (i=10; i<24; i++) + { + sb_power_shr[i] = L_shr(sb_power[i],5); + move32(); + } + + FOR(i=1; i<24; i++) + { + sb_power_mlt = Mpy_32_16_1(sb_power[i],i_t_2[i-1]); + t_sp_center = L_add(L_shr(sb_power_mlt,9), t_sp_center); + frame_power = L_add(sb_power_shr[i], frame_power);/*1-23 */ + } + + /*+0.1 */ + Q_t_sc = sub(Q_sb_p, 14); + + IF (GE_16(Q_t_sc,34)) + { + t_sp_center = L_shr(t_sp_center, limitScale32(sub(Q_t_sc, 33))); + zerop1 = L_shr(CNT0P1,1); + Q_t_sc = 33; + move16(); + } + ELSE + { + Q_t_sc = sub(Q_t_sc, 1); + t_sp_center = L_shr(t_sp_center,1); + zerop1 = L_shr(CNT0P1, limitScale32(sub(34, Q_t_sc))); + } + t_sp_center_num = L_add(t_sp_center, zerop1); + + Q_f_p = sub(Q_sb_p, 5); + IF (GE_16(Q_f_p,34)) + { + frame_power = L_shr(frame_power,sub(Q_f_p, 33)); + zerop1 = L_shr(CNT0P1,1); + Q_f_p = 33; + move16(); + } + ELSE + { + Q_f_p = sub(Q_f_p, 1); + frame_power = L_shr(frame_power,1); + zerop1 = L_shr(CNT0P1, sub(34, Q_f_p)); + } + frame_power_den = L_add(frame_power, zerop1); + IF (frame_power == 0) + { + frame_power_den = CNT0P1; move32(); + Q_f_p = 34; + move16(); + } + + /*div*/ + Q_t_sp_center=sub(norm_l(t_sp_center_num), 1); + Q_frame_power=norm_l(frame_power_den); + t_sp_center_num = L_shl(t_sp_center_num,Q_t_sp_center); + frame_power_den = L_shl(frame_power_den,Q_frame_power); + + d_t_sp_center = div_l(t_sp_center_num,extract_h(frame_power_den)); + + d_t_sp_center_Qtmp = add(Q_t_sc,Q_t_sp_center); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,Q_frame_power); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,Q_f_p); + d_t_sp_center_Qtmp = add(d_t_sp_center_Qtmp,15); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,SP_CENTER_Q); + sp_center[3]= shr(d_t_sp_center,d_t_sp_center_Qtmp); + move16(); + } + ELSE + { + t_sp_center = t_sp_center_nb; move32(); + frame_power = frame_power_nb; move32(); + + IF (frame_power==0) + { + d_t_sp_center = 0; + move16(); + } + ELSE + { + /*div*/ + Q_t_sp_center = sub(norm_l(t_sp_center), 1); + Q_frame_power = norm_l(frame_power); + t_sp_center_num = L_shl(t_sp_center,Q_t_sp_center); + frame_power_den = L_shl(frame_power,Q_frame_power); + + d_t_sp_center = div_l(t_sp_center_num,extract_h(frame_power_den)); + d_t_sp_center = shr(d_t_sp_center,sub(add(sub(Q_t_sp_center,Q_frame_power),10),SP_CENTER_Q)); + } + + sp_center[0] = add(mult(sp_center[0], 0x5999), mult(d_t_sp_center, 0x2666)); + sp_center[2] = d_t_sp_center; + move16(); + move16(); + + t_sp_center = 0; move32(); + frame_power = 0; move32(); + FOR(i=1; i<10; i++) + { + sb_power_mlt = Mpy_32_16_1(sb_power[i],i_t_1[i-1]); + t_sp_center = L_add(L_shr(sb_power_mlt,6), t_sp_center); + frame_power = L_add(sb_power_shr[i], frame_power); /*1-9 */ + } + IF (frame_power==0) + { + sp_center[3] = 0; + move16(); + } + ELSE + { + /*div */ + Q_t_sp_center = sub(norm_l(t_sp_center), 1); + Q_frame_power = norm_l(frame_power); + t_sp_center_num = L_shl(t_sp_center,Q_t_sp_center); + frame_power_den = L_shl(frame_power,Q_frame_power); + + d_t_sp_center = div_l(t_sp_center_num,extract_h(frame_power_den)); + sp_center[3] = shr(d_t_sp_center,sub(add(sub(Q_t_sp_center, Q_frame_power), 10),SP_CENTER_Q)); + move16(); + } + } + +} diff --git a/lib_enc/spec_flatness.c b/lib_enc/spec_flatness.c new file mode 100644 index 0000000..1a595a0 --- /dev/null +++ b/lib_enc/spec_flatness.c @@ -0,0 +1,314 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include "basop_util.h" +#include "stl.h" +#include "vad_basop.h" +#include "prot_fx.h" + +void spec_flatness(Word32 *spec_amp, /*(i) spectral amplitude*/ + Word32 smooth_spec_amp[], /*(i) smoothed spectral amplitude*/ + Word16 sSFM[5] /*(o) spectral flatness rate*/ + ) +{ + Word32 i; + Word32 *smooth_spec_amp32; + Word32 prods,prods_Exp; + Word32 sums,prods_ExpM; + Word32 zerop1; + + Word16 smooth_spec_amp16; + Word16 Qnorm_prods,Qnorm_sums; + Word16 SFM; + Word16 prods_s,prods_Exps; + Word16 prods_leadingzero,prods_Expleadingzero; + + Word16 leadingzero_prod, leadingzero_spec_amp; + Word16 prods_Q_last,prods_ExpQ; + Word16 SFM_Qtmp; + Word16 prods_Q; + + + smooth_spec_amp32 = smooth_spec_amp; + zerop1 = 0; + move32(); + prods_Q = 0; + move16(); + FOR(i=MIN_AMP_ID; i<=MAX_AMP_ID; i++) + { + smooth_spec_amp32[i-MIN_AMP_ID] = L_add(MUL_F(smooth_spec_amp32[i-MIN_AMP_ID],0x5999),MUL_F(spec_amp[i],0x2666)); + move32(); + } + /*sSFM1*/ + sums = 0; + move32(); + prods = 1; + move32(); + prods_Q = 0; + move16(); + + + FOR(i=(5-MIN_AMP_ID); i<(20-MIN_AMP_ID); i++) + { + sums = L_add(sums, smooth_spec_amp32[i]); + leadingzero_spec_amp = norm_l(smooth_spec_amp32[i]); + smooth_spec_amp16 = extract_h(L_shl(smooth_spec_amp32[i],leadingzero_spec_amp)); + leadingzero_prod = norm_l(prods); + prods = L_shl(prods,leadingzero_prod); + prods_s = extract_h(prods); + prods = L_mult(prods_s, smooth_spec_amp16); + prods_Q = add(add(prods_Q, leadingzero_spec_amp),leadingzero_prod); + } + prods_Q = sub(prods_Q, 255); + + prods_Q_last = prods_Q; + move16(); + prods_ExpM = L_mult(prods_Q_last,-2184); + + prods = VAD_Pow(prods,0x08888888,0,31,&prods_Q); + prods_Exp = VAD_Pow2(prods_ExpM,16, &prods_ExpQ); + + prods_leadingzero = norm_l(prods); + prods_Expleadingzero = norm_l(prods_Exp); + prods_s = extract_h(L_shl(prods,prods_leadingzero)); + prods_Exps = extract_h(L_shl(prods_Exp,prods_Expleadingzero)); + + prods = L_mult(prods_s, prods_Exps); + prods_Q = add(prods_Q, prods_leadingzero); + prods_Q = add(prods_Q, prods_ExpQ); + prods_Q = add(prods_Q, prods_Expleadingzero); + prods_Q = sub(prods_Q, 31); + + prods = L_max(prods, 0); + + if(prods <= 0) + { + prods_Q = 34; + move16(); + } + sums = MUL_F(sums, 0x0888); + + /*+0.1 */ + IF (GE_16(prods_Q, 34)) + { + prods = L_shr(prods, sub(prods_Q, 33)); + zerop1 = L_shr(CNT0P1, 1); + prods_Q = 33; + move16(); + } + ELSE + { + prods_Q = sub(prods_Q, 1); + prods = L_shr(prods, 1); + zerop1 = L_shr(CNT0P1, sub(34, prods_Q)); + } + prods = L_add(prods, zerop1); + + zerop1 = L_shr(CNT0P1, 20); + sums = L_add(sums, zerop1); + + /*div*/ + Qnorm_prods = sub(norm_l(prods), 1); + Qnorm_sums = norm_l(sums); + prods = L_shl(prods,Qnorm_prods); + sums = L_shl(sums,Qnorm_sums); + + SFM = div_l(prods, extract_h(sums)); + + SFM_Qtmp = add(prods_Q, Qnorm_prods); + SFM_Qtmp = sub(SFM_Qtmp, Qnorm_sums); + SFM_Qtmp = add(SFM_Qtmp, 15); + SFM_Qtmp = sub(SFM_Qtmp, SPEC_AMP_Q); + SFM_Qtmp = sub(SFM_Qtmp, SFM_Q); + + sSFM[0] = add(mult(sSFM[0], 0x6ccc), shr(mult(SFM, 0x1333), SFM_Qtmp)); + move16(); + + /*sSFM2*/ + sums = 0; + move32(); + prods = 1; + move32(); + prods_Q = 0; + move16(); + + FOR(i=(20-MIN_AMP_ID); i<(40-MIN_AMP_ID); i++) + { + sums = L_add(sums, smooth_spec_amp32[i]); + leadingzero_spec_amp = norm_l(smooth_spec_amp32[i]); + smooth_spec_amp16 = extract_h(L_shl(smooth_spec_amp32[i],leadingzero_spec_amp)); + leadingzero_prod = norm_l(prods); + prods = L_shl(prods,leadingzero_prod); + prods_s = extract_h(prods); + prods = L_mult(prods_s, smooth_spec_amp16); + prods_Q = add(add(prods_Q, leadingzero_spec_amp),leadingzero_prod); + } + prods_Q = sub(prods_Q, 340); + + prods_Q_last = prods_Q; + move16(); + prods_ExpM = L_mult(prods_Q_last,-1638); + + prods = VAD_Pow(prods,0x06666666,0,31,&prods_Q); + prods_Exp = VAD_Pow2(prods_ExpM,16, &prods_ExpQ); + + prods_leadingzero = norm_l(prods); + prods_Expleadingzero = norm_l(prods_Exp); + prods_s = extract_h(L_shl(prods,prods_leadingzero)); + prods_Exps = extract_h(L_shl(prods_Exp,prods_Expleadingzero)); + + prods = L_mult(prods_s, prods_Exps); + prods_Q = add(prods_Q, prods_leadingzero); + prods_Q = add(prods_Q, prods_ExpQ); + prods_Q = add(prods_Q, prods_Expleadingzero); + prods_Q = sub(prods_Q, 31); + + prods = L_max(prods, 0); + + if(prods<=0) + { + prods_Q = 34; + move16(); + } + sums = MUL_F(sums, 0x0666); + + /*+0.1 */ + IF (GE_16(prods_Q, 34)) + { + prods = L_shr(prods,sub(prods_Q, 33)); + zerop1 = L_shr(CNT0P1,1); + prods_Q = 33; + move16(); + } + ELSE + { + prods_Q = sub(prods_Q,1); + prods = L_shr(prods,1); + zerop1 = L_shr(CNT0P1, sub(34, prods_Q)); + } + prods = L_add(prods, zerop1); + + zerop1 = L_shr(CNT0P1, 20); + sums = L_add(sums, zerop1); + + /*div*/ + Qnorm_prods=sub(norm_l(prods), 1); + Qnorm_sums=norm_l(sums); + prods = L_shl(prods, Qnorm_prods); + sums = L_shl(sums, Qnorm_sums); + + SFM = div_l(prods, extract_h(sums)); + + SFM_Qtmp = add(prods_Q, Qnorm_prods); + SFM_Qtmp = sub(SFM_Qtmp, Qnorm_sums); + SFM_Qtmp = add(SFM_Qtmp, 15); + SFM_Qtmp = sub(SFM_Qtmp, SPEC_AMP_Q); + SFM_Qtmp = sub(SFM_Qtmp, SFM_Q); + + sSFM[1] = add(mult(sSFM[1],0x6ccc),shr(mult(SFM,0x1333),SFM_Qtmp)); + move16(); + /*sSFM3*/ + sums = 0; + move32(); + prods =1; + move32(); + prods_Q = 0; + move16(); + + FOR(i=(40-MIN_AMP_ID); i<=(MAX_AMP_ID-MIN_AMP_ID); i++) + { + sums = L_add(sums, smooth_spec_amp32[i]); + leadingzero_spec_amp = norm_l(smooth_spec_amp32[i]); + smooth_spec_amp16 = extract_h(L_shl(smooth_spec_amp32[i],leadingzero_spec_amp)); + leadingzero_prod = norm_l(prods); + prods = L_shl(prods,leadingzero_prod); + prods_s = extract_h(prods); + prods = L_mult(prods_s, smooth_spec_amp16); + prods_Q = add(add(prods_Q, leadingzero_spec_amp),leadingzero_prod); + } + prods_Q = sub(prods_Q, 425); + + prods_Q_last = prods_Q; + move16(); + prods_ExpM = L_mult(prods_Q_last,-1310); + + prods = VAD_Pow(prods,0x051eb851,0,31,&prods_Q); + prods_Exp = VAD_Pow2(prods_ExpM,16, &prods_ExpQ); + + prods_leadingzero = norm_l(prods); + prods_Expleadingzero = norm_l(prods_Exp); + prods_s = extract_h(L_shl(prods,prods_leadingzero)); + prods_Exps = extract_h(L_shl(prods_Exp,prods_Expleadingzero)); + + prods = L_mult(prods_s, prods_Exps); + prods_Q = add(prods_Q, prods_leadingzero); + prods_Q = add(prods_Q, prods_ExpQ); + prods_Q = add(prods_Q, prods_Expleadingzero); + prods_Q = sub(prods_Q, 31); + + prods = L_max(prods, 0); + if(prods <= 0) + { + prods_Q = 34; + move16(); + } + + sums = MUL_F(sums, 0x051e); + + /*+0.1 */ + IF (GE_16(prods_Q, 34)) + { + prods = L_shr(prods,sub(prods_Q, 33)); + zerop1 = L_shr(CNT0P1,1); + prods_Q = 33; + move16(); + } + ELSE + { + prods_Q = sub(prods_Q, 1); + prods = L_shr(prods,1); + zerop1 = L_shr(CNT0P1, sub(34, prods_Q)); + } + prods = L_add(prods, zerop1); + + zerop1 = L_shr(CNT0P1, 20); + sums = L_add(sums, zerop1); + + /*div*/ + Qnorm_prods = sub(norm_l(prods), 1); + Qnorm_sums = norm_l(sums); + prods = L_shl(prods,Qnorm_prods); + sums = L_shl(sums,Qnorm_sums); + + SFM = div_l(prods,extract_h(sums)); + + SFM_Qtmp = add(prods_Q, Qnorm_prods); + SFM_Qtmp = sub(SFM_Qtmp, Qnorm_sums); + SFM_Qtmp = add(SFM_Qtmp, 15); + SFM_Qtmp = sub(SFM_Qtmp, SPEC_AMP_Q); + SFM_Qtmp = sub(SFM_Qtmp, SFM_Q); + + sSFM[2] = add(mult(sSFM[2],0x6ccc),shr(mult(SFM,0x1333),SFM_Qtmp)); + move16(); +} + + + + + + + + + + + + + + + + + + + diff --git a/lib_enc/speech_music_classif_fx.c b/lib_enc/speech_music_classif_fx.c new file mode 100644 index 0000000..bc1c2f8 --- /dev/null +++ b/lib_enc/speech_music_classif_fx.c @@ -0,0 +1,2889 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include "rom_enc_fx.h" +#include "rom_com_fx.h" +#include "stl.h" + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ +#define ATT_NSEG 32 +#define ATT_SEG_LEN (L_FRAME/ATT_NSEG) +#define ATT_3LSUB_POS (3 * ATT_NSEG / NB_SUBFR) +#define ATT_3LSUB_POS_16k 26 /* (short)((4.0f * ATT_NSEG / (float)NB_SUBFR16k) + 0.5f) */ + +#define LOG_PROB_CONST 11292 /*0.5f * N_FEATURES * LOG_PI2 in Q10 */ + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static Word16 sp_mus_classif_gmm_fx( Encoder_State_fx *st_fx, const Word16 localVAD, const Word16 pitch[3], const Word16 voicing[3], + const Word16 lsp_new[M], const Word16 cor_map_sum, const Word32 epsP[M+1], const Word32 PS[], + Word16 non_sta, Word16 relE, Word16 *voi_fv, Word16 *cor_map_sum_fv, Word16 *LPCErr, Word16 Q_esp + , Word16 *high_lpn_flag_ptr); + + +static void sp_mus_classif_2nd_fx( Encoder_State_fx *st, const Word16 sp_aud_decision1, Word16 *sp_aud_decision2, + const Word16 pitch[3], const Word16 Etot, Word16 *coder_type, Word16 *attack_flag, + const Word16 *inp, const Word16 Qx, const Word16 localVAD, const Word16 vad_flag ); + +static void music_mixed_classif_improv_fx( Encoder_State_fx *st, const Word16 *new_inp, Word16 *sp_aud_decision1, Word16 vad_flag, + const Word16 *voicing, const Word32 *epsP, Word16 Q_epsP, Word16 etot, Word16 old_cor, + Word16 cor_map_sum ); + +static void tonal_context_improv_fx( Encoder_State_fx *st_fx, const Word32 PS[], Word16 *sp_aud_decision1, Word16 *sp_aud_decision2, + const Word16 vad_flag, const Word16 pitch[3], const Word16 voicing[3], const Word16 voi_fv, + const Word16 cor_map_sum_fv, const Word16 LPCErr, const Word16 Qx ); + +static void var_cor_calc_fx( const Word16 old_corr, Word16 *mold_corr, Word16 var_cor_t[], Word16 *high_stable_cor ); + +static Word16 attack_det_fx( const Word16 *inp, const Word16 Qx, const Word16 last_clas, const Word16 localVAD, const Word16 coder_type + ,const Word32 total_brate + + ); + +static void order_spectrum_fx( Word16 *vec, Word16 len ); + +static void detect_sparseness_fx( Encoder_State_fx *st_fx, const Word16 localVAD_HE_SAD, Word16 *sp_aud_decision1, + Word16 *sp_aud_decision2, const Word16 voi_fv ); + + +/*---------------------------------------------------------------------* + * speech_music_classif() + * + * Speech/music classification + * + * The following technologies are used based on the outcome of the sp/mus classifier + * sp_aud_decision1 sp_aud_decision2 + * 0 0 use ACELP (+TD BWE) + * 1 0 use ACELP (+FD BWE) or HQ/LR-MDCT depending on bitrate + * 1 1 use GSC (+FD BWE) or HQ/LR-MDCT depending on bitrate + * + * 0 1 exceptionally use GSC (+FD BWE) instead of LR-MDCT at 13.2 kbps (WB/SWB) for sparse spectra + *---------------------------------------------------------------------*/ + +void speech_music_classif_fx( + Encoder_State_fx *st, /* i/o: state structure */ + Word16 *sp_aud_decision0, + Word16 *sp_aud_decision1, /* o : 1st stage speech/music decision for GSC */ + Word16 *sp_aud_decision2, /* o : 2nd stage speech/music decision for GSC */ + const Word16 *new_inp, /* i : new input signal */ + const Word16 *inp, /* i : input signal to locate attach position */ + const Word16 vad_flag, + const Word16 localVAD, + const Word16 localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ + const Word16 pitch[3], /* i : open-loop pitch estimate in three subframes */ + const Word16 voicing[3], /* i : voicing estimate in three subframes Q15 */ + const Word16 lsp_new[M], /* i : LSPs in current frame Q15 */ + const Word16 cor_map_sum, /* i : correlation map sum (from multi-harmonic anal.)Q8*/ + const Word32 epsP[M+1], /* i : LP prediciton error Q_esp*/ + const Word32 PS[], /* i : energy spectrum Q_new+QSCALE*/ + const Word16 Etot, /* i : total frame energy Q8 */ + const Word16 old_cor, /* i : max correlation from previous frame Q15 */ + Word16 *coder_type, /* i/o: coding type */ + Word16 *attack_flag, /* o : flag to indicate if attack is to be treated by TC or GSC */ + Word16 non_sta, /* i : unbound non-stationarity for sp/mus classifier */ + Word16 relE, /* i : relative frame energy */ + Word16 Q_esp, /* i : scaling of esP */ + Word16 Q_inp, /* i : scaling of input */ + Word16 *high_lpn_flag_ptr, /* o : noise log prob flag for NOISE_EST */ + Word16 flag_spitch /* i : flag to indicate very short stable pitch */ +) +{ + Word16 voi_fv, cor_map_sum_fv, LPCErr; + + + /* 1st stage speech/music classifier based on the GMM model */ + *sp_aud_decision1 = sp_mus_classif_gmm_fx( st, localVAD_HE_SAD, pitch, voicing, lsp_new, cor_map_sum, + epsP, PS, non_sta, relE, &voi_fv, &cor_map_sum_fv, &LPCErr, + + + Q_esp, high_lpn_flag_ptr ); + + test(); + IF ( EQ_16( st->codec_mode, MODE1)||EQ_32(st->sr_core,12800)) + { + + + /* Improvement of the 1st stage decision on mixed/music content */ + test(); + IF ( st->Opt_SC_VBR_fx == 0 && ( NE_32(st->total_brate_fx, ACELP_24k40))) + { + + + music_mixed_classif_improv_fx( st, new_inp, sp_aud_decision1, vad_flag, voicing, epsP, Q_esp, Etot, + old_cor, cor_map_sum ); + + + } + + *sp_aud_decision0 = *sp_aud_decision1; + + + /* 2nd stage speech/music classifier (rewrite music to speech in onsets) */ + *sp_aud_decision2 = *sp_aud_decision1; + move16(); + + IF ( GT_16(st->bwidth_fx,NB)) + { + sp_mus_classif_2nd_fx( st, *sp_aud_decision1, sp_aud_decision2, pitch, Etot, coder_type, + attack_flag, inp, Q_inp-1, localVAD, vad_flag ); + + /* avoid switch to AUDIO/MUSIC class for very short stable high pitch + and/or stable pitch with high correlation at low bitrates*/ + test(); + test(); + IF ( flag_spitch && EQ_16(st->bwidth_fx,WB)&<_32(st->total_brate_fx,ACELP_13k20)) + { + *sp_aud_decision2 = 0; + move16(); + } + } + + + + /* Context-based improvement of 1st and 2nd stage decision on stable tonal signals */ + test(); + IF ( st->Opt_SC_VBR_fx == 0 && ( NE_32(st->total_brate_fx, ACELP_24k40))) + { + tonal_context_improv_fx( st, PS, sp_aud_decision1, sp_aud_decision2, vad_flag, pitch, voicing, + voi_fv, cor_map_sum_fv, LPCErr, Q_inp + QSCALE -2 ); + } + + /* Avoid using LR-MDCT on sparse spectra, use GSC instead at 13.2 kbps (WB/SWB) */ + test(); + test(); + test(); + test(); + IF ( !st->Opt_SC_VBR_fx && EQ_32(st->total_brate_fx, ACELP_13k20)&&EQ_16(vad_flag,1)&& + ( EQ_16(st->bwidth_fx, WB) || EQ_16(st->bwidth_fx, SWB)) ) + { + detect_sparseness_fx( st, localVAD_HE_SAD, sp_aud_decision1, sp_aud_decision2, voi_fv ); + } + + /* override speech/music classification to ACELP when background noise level reaches certain level */ + /* this is a patch against mis-classifications during active noisy speech segments */ + IF ( GT_16(st->lp_noise_fx, 3072)) + { + *sp_aud_decision1 = 0; + move16(); + *sp_aud_decision2 = 0; + move16(); + } + + + /* select GSC on SWB noisy speech (only on active unvoiced SWB noisy speech segments) */ + st->GSC_noisy_speech_fx = 0; + move16(); + test(); + test(); + test(); + test(); + test(); + test(); + IF ( EQ_16(vad_flag,1)&&GE_32(st->total_brate_fx,ACELP_13k20)&<_32(st->total_brate_fx,ACELP_24k40)&& + GT_16(st->lp_noise_fx,3072) && *sp_aud_decision1 == 0 && GE_16(st->bwidth_fx,SWB) && + EQ_16(st->coder_type_raw_fx,UNVOICED)) + { + st->GSC_noisy_speech_fx = 1; + move16(); + } + + /* Select AUDIO frames */ + test(); + test(); + test(); + test(); + IF ( EQ_16(st->codec_mode,MODE1)&&(*sp_aud_decision2||st->GSC_noisy_speech_fx)) + { + *coder_type = AUDIO; + move16(); + st->noise_lev_fx = NOISE_LEVEL_SP0; + move16(); + } + + } + ELSE + { + *sp_aud_decision0 = *sp_aud_decision1; + } + + + return; +} + +/*---------------------------------------------------------------------* + * sp_mus_classif_gmm_fx() + * + * Speech/music classification based on GMM model + *---------------------------------------------------------------------*/ + +static Word16 sp_mus_classif_gmm_fx( /* o : decision flag (1-music, 0-speech or noise) */ + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 localVAD, + const Word16 pitch[3], /* i : open-loop pitch estimate in three subframes Q0 */ + const Word16 voicing[3], /* i : voicing estimate in three subframes Q15 */ + const Word16 lsp_new[M], /* i : LSPs in current frame Q15 */ + const Word16 cor_map_sum, /* i : correlation map sum (from multi-harmonic anal.)Q8 */ + const Word32 epsP[M+1], /* i : LP prediciton error Q_esp */ + const Word32 PS[], /* i : energy spectrum Q_new+Qscale-2 */ + Word16 non_sta, /* i : unbound non-stationarity for sp/mus classifier */ + Word16 relE, /* i : relative frame energy */ + Word16 *voi_fv, /* o : scaled voicing feature */ + Word16 *cor_map_sum_fv, /* o : scaled correlation map feature */ + Word16 *LPCErr, /* o : scaled LP prediction error feature */ + Word16 Q_esp /* i : scaling of epsP */ + ,Word16 *high_lpn_flag_ptr /* o : noise log prob flag for NOISE_EST */ +) +{ + Word16 i, k, p, dec, vad; + + Word16 lsp[M], FV[N_FEATURES], *pFV = FV; + const Word32 *pSF_a; + const Word16 *pSF_m; + Word16 lsf2acos_fact, wrelE, dlp, wdrop, wght; + + Word32 mx; + Word32 sum_PS; + Word16 ftmp, tmp16; + Word16 xm[N_FEATURES]; + Word16 lps, lpm; + Word16 lpn; + Word16 e_tmp, f_tmp; + Word32 L_tmp; + Word16 exp1; + Word32 ps_sta; + Word32 ps_diff; + Word16 ps_diff_16; + Word32 dPS[128], PS_norm[128]; + Word32 lepsP1; + Word32 max_s=0, max_m=0, py_s, py_m; + Word32 max_n, py_n; /* pyn */ + Word16 ishift[12] = {8,0,2,2,2,2,2,1,0,2,2,1}; + Word16 tmp; + Word16 tmp1,tmp2,exp2,scale,exp3; + + /*------------------------------------------------------------------* + * Initialization + *------------------------------------------------------------------*/ + + vad = localVAD; + move16(); + + /*------------------------------------------------------------------* + * Preparation of the feature vector + *------------------------------------------------------------------*/ + + /* [0] OL pitch Q0 */ + /*(float)(pitch[0] + pitch[1] + pitch[2]) / 3.0f;*/ + L_tmp = L_mult(pitch[0], 10923); + L_tmp = L_mac(L_tmp, pitch[1], 10923); + L_tmp = L_mac(L_tmp, pitch[2], 10923); + + test(); + IF ( EQ_16(st_fx->tc_cnt_fx,1)||EQ_16(st_fx->tc_cnt_fx,2)) + { + *pFV++ = pitch[2]; + move16(); + } + ELSE + { + *pFV++ = round_fx(L_tmp); + } + + /* [1] voicing Q15 */ + /*(float)(voicing[0] + voicing[1] + voicing[2]) / 3.0f*/ + test(); + IF ( EQ_16(st_fx->tc_cnt_fx,1)||EQ_16(st_fx->tc_cnt_fx,2)) + { + *pFV++ = voicing[2]; + move16(); + } + ELSE + { + L_tmp = L_mult(voicing[0], 10923); + L_tmp = L_mac(L_tmp, voicing[1], 10923); + L_tmp = L_mac(L_tmp, voicing[2], 10923); + *pFV++ = round_fx(L_tmp); + } + + /* [2,3,4,5,6] LSFs Q15*/ + Copy( lsp_new, lsp, M ); + lsf2acos_fact = 25735; + move16(); /* PI/6400 -> Q27 */ + + /*ftmp = (float)acos(lsp[1...5]);*/ + /**pFV++ = ftmp + st->last_lsp[1...5];*/ + /*st->last_lsp[1...5] = ftmp;*/ + FOR(i= 1; i < M_LSP_SPMUS; i++) + { + L_tmp = sub_lsp2lsf_fx(lsp[i]); + tmp16 = round_fx(L_shl(L_mult0(extract_l(L_tmp),lsf2acos_fact),2)); + *pFV++ = add(tmp16,st_fx->last_lsp_fx[i]); + move16(); /*Q13*/ + st_fx->last_lsp_fx[i] = tmp16; + move16(); + } + + /* [7] cor_map_sum Q8 */ + *pFV++ = round_fx(L_mac(L_mult(cor_map_sum, 16384), st_fx->last_cor_map_sum_fx, 16384)); /* Q8 ->Q7*/ + st_fx->last_cor_map_sum_fx = cor_map_sum; + move16(); + + /* [8] non_sta Q8*/ + *pFV++ = round_fx(L_mac(L_mult(non_sta,16384), st_fx->last_non_sta_fx, 16384)); /* Q8 -> Q7 */ + st_fx->last_non_sta_fx = non_sta; + move16(); + + /* [9] epsP Q10 */ + IF ( EQ_16(st_fx->bwidth_fx,NB)) + { + *pFV++ = -1687; + move16(); /*Q10*/ + } + ELSE + { + /*lepsP1 = (float)log(epsP[1] + 1e-5f);*/ + IF(epsP[1] != 0) + { + e_tmp = norm_l(epsP[1]); + f_tmp = Log2_norm_lc(L_shl(epsP[1],e_tmp)); + e_tmp = sub(30,add(e_tmp,Q_esp)); + lepsP1 = Mpy_32_16(e_tmp, f_tmp, 22713); /* Q16 */ /* 22713 = ln(2) in Q15 */ + } + ELSE + { + lepsP1 = L_deposit_l(0); + } + + /*ftmp = (float)log(epsP[13]);*/ + IF(epsP[13] != 0) + { + e_tmp = norm_l(epsP[13]); + f_tmp = Log2_norm_lc(L_shl(epsP[13],e_tmp)); + e_tmp = sub(30,add(e_tmp,Q_esp)); + L_tmp = Mpy_32_16(e_tmp, f_tmp, 22713); /* Q16 */ /* 22713 = ln(2) in Q15 */ + } + ELSE + { + L_tmp = L_deposit_l(0); + } + + /*ftmp = (float)log(epsP[13]) - lepsP1;*/ + L_tmp = L_sub(L_tmp, lepsP1); /*Q16 */ + ftmp = round_fx(L_shl(L_tmp,10)); /*Q10 */ + + /**pFV++ = ftmp + st->past_epsP2;*/ + *pFV++ = add(ftmp,st_fx->past_epsP2_fx); + move16(); /*Q10 */ + + /*st->past_epsP2 = ftmp;*/ + st_fx->past_epsP2_fx = ftmp; + move16(); /*Q10 */ + } + + /* calculation of differential normalized power spectrum */ + sum_PS = L_deposit_l(0); + FOR ( i = LOWEST_FBIN; i < HIGHEST_FBIN; i++ ) + { + sum_PS = L_add(sum_PS,PS[i]); + } + exp1 = norm_l(sum_PS); + tmp1 = round_fx(L_shl(sum_PS,exp1)); + exp1 = sub(30,exp1); + + FOR ( i = LOWEST_FBIN; i < HIGHEST_FBIN; i++ ) + { + /*PS_norm[i] = PS[i] / sum_PS;*/ + /*dPS[i] = (float)fabs(PS_norm[i] - st->past_PS[i]);*/ + exp2 = norm_l(PS[i]); + tmp2 = round_fx(L_shl(PS[i],exp2)); + exp2 = sub(30,exp2); + + scale = shr(sub(tmp1, tmp2), 15); + tmp2 = shl(tmp2, scale); + exp2 = sub(exp2, scale); + + exp3 = sub(exp1,exp2); + + tmp = div_s(tmp2, tmp1); /*Q(15+exp3) */ + PS_norm[i] = L_shl(tmp,sub(10,exp3)); + move32(); /*Q25 */ + dPS[i] = L_abs(L_sub(PS_norm[i],st_fx->past_PS_fx[i-LOWEST_FBIN])); + move32(); /*Q25 */ + } + + /* [10] ps_diff (spectral difference) Q10*/ + ps_diff = 0; + move16(); + FOR ( i = LOWEST_FBIN; i < HIGHEST_FBIN; i++ ) + { + /*ps_diff += dPS[i];*/ + ps_diff = L_add(ps_diff,dPS[i]); /*Q25*/ + } + + /*ps_diff = (float)log(ps_diff + 1e-5f);*/ + IF( ps_diff != 0 ) + { + e_tmp = norm_l(ps_diff); + f_tmp = Log2_norm_lc(L_shl(ps_diff,e_tmp)); + e_tmp = sub(30-25,e_tmp); + ps_diff = Mpy_32_16(e_tmp, f_tmp, 22713);/* Q16 */ /* 22713 = ln(2) in Q15 */ + ps_diff_16 = round_fx(L_shl(ps_diff,10)); /*Q10 */ + } + ELSE + { + ps_diff_16 = -11789; + move16(); /*Q10 */ + } + + *pFV++ = add(ps_diff_16, st_fx->past_ps_diff_fx); + move16();/*Q10 */ + st_fx->past_ps_diff_fx = ps_diff_16; + move16(); /*Q10 */ + + /* [11] ps_sta (spectral stationarity) Q11 */ + ps_sta = 0; + move16(); + FOR ( i = LOWEST_FBIN; i < HIGHEST_FBIN; i++ ) + { + /*mx = PS_norm[i] > st->past_PS[i] ? PS_norm[i] : st->past_PS[i];*/ + IF (GT_32(PS_norm[i],st_fx->past_PS_fx[i-LOWEST_FBIN])) + { + mx = PS_norm[i]; + move16(); /*Q25 */ + } + ELSE + { + mx = st_fx->past_PS_fx[i-LOWEST_FBIN]; + move16(); /*Q25 */ + } + + /*ps_sta += mx / (dPS[i] + 1e-5f);*/ + IF( !dPS[i] ) + { + ps_sta = L_add(ps_sta,L_shr(mx,9)); /*Q16 */ + } + ELSE + { + exp1 = norm_l(L_add(dPS[i],336)); + tmp1 = round_fx(L_shl(L_add(dPS[i],336),exp1)); + exp1 = sub(30,exp1); + + exp2 = norm_l(mx); + tmp2 = round_fx(L_shl(mx,exp2)); + exp2 = sub(30,exp2); + + scale = shr(sub(tmp1, tmp2), 15); + tmp2 = shl(tmp2, scale); + exp2 = sub(exp2, scale); + + exp3 = sub(exp1,exp2); + move16(); + + tmp = div_s(tmp2, tmp1); /*Q(15+exp3) */ + L_tmp = L_shl(tmp,sub(1,exp3)); /*Q16 */ + ps_sta = L_add(ps_sta,L_tmp); /*Q16 */ + } + } + + /**pFV++ = (float)log(ps_sta + 1e-5f);*/ + ps_sta = L_add(ps_sta, 336); + e_tmp = norm_l(ps_sta); + f_tmp = Log2_norm_lc(L_shl(ps_sta,e_tmp)); + e_tmp = sub(30-16,e_tmp); + L_tmp = Mpy_32_16(e_tmp, f_tmp, 22713); /* Q16 */ /* 22713 = ln(2) in Q15 */ + *pFV++ = round_fx(L_shl(L_tmp,11)); /*Q11 */ + + /* update PS vector */ + Copy32( &PS_norm[LOWEST_FBIN], st_fx->past_PS_fx, HIGHEST_FBIN-LOWEST_FBIN ); + + /*------------------------------------------------------------------* + * Scaling of the feature vector + *------------------------------------------------------------------*/ + + /* FV[0] -> Q0 */ + /* FV[1...6] -> Q13*/ + /* FV[7,8] -> Q7 */ + /* FV[9,10] -> Q10 */ + /* FV[11] -> Q11 */ + + + pFV = FV; + move16(); + IF ( EQ_16(st_fx->bwidth_fx,NB)) + { + pSF_m = SF_8k_mult_fx; + pSF_a = SF_8k_add_fx; + } + ELSE + { + pSF_m = SF_mult_fx; + pSF_a = SF_add_fx; + } + + FOR ( i=0; ilpm_fx = lpm; + move16(); + st_fx->lps_fx = lps; + move16(); + + /* determine HQ GENERIC speech class */ + st_fx->hq_generic_speech_class_fx = 0; + move16(); + if( GT_16(lps,add(lpm,256))) + { + st_fx->hq_generic_speech_class_fx = 1; + move16(); + } + + + /*------------------------------------------------------------------* + * State machine (sp_mus_state < 0 .. inactive, > 0 .. entry, = 0 .. active ) + *------------------------------------------------------------------*/ + + IF ( vad ) + { + test(); + test(); + test(); + IF ( LT_16(relE,-20*256)||(LE_16(lps,-5*512)&&LE_16(lpm,-5*512))) + { + IF ( st_fx->sp_mus_state_fx > 0 ) + { + if ( LT_16(st_fx->sp_mus_state_fx,HANG_LEN)) + { + /* energy is too low but we are in entry period -> reset the inactive counter to allow new entry later */ + st_fx->inact_cnt_fx = 0; + move16(); + } + + /* energy is too low -> we are going to instable state */ + st_fx->sp_mus_state_fx = 0; + move16(); + } + ELSE IF ( GT_16(st_fx->sp_mus_state_fx,-HANG_LEN)) + { + /* energy is still too low -> we are still in instable state */ + st_fx->sp_mus_state_fx = sub(st_fx->sp_mus_state_fx,1); + } + } + ELSE IF ( st_fx->sp_mus_state_fx <= 0 ) + { + IF ( st_fx->inact_cnt_fx == 0 ) + { + + st_fx->sp_mus_state_fx = 1; + move16(); + } + ELSE + { + + st_fx->sp_mus_state_fx = HANG_LEN; + move16(); + } + + st_fx->inact_cnt_fx = 12; + move16(); + } + ELSE IF ( st_fx->sp_mus_state_fx > 0 && LT_16(st_fx->sp_mus_state_fx,HANG_LEN)) + { + /* we are inside an entry period -> increment the counter of entry frames */ + st_fx->sp_mus_state_fx = add(st_fx->sp_mus_state_fx,1); + } + + test(); + if ( st_fx->sp_mus_state_fx < 0 && st_fx->inact_cnt_fx > 0 ) + { + st_fx->inact_cnt_fx = sub(st_fx->inact_cnt_fx,1); + } + } + ELSE + { + test(); + IF ( st_fx->sp_mus_state_fx > 0 && LT_16(st_fx->sp_mus_state_fx,HANG_LEN)) + { + st_fx->inact_cnt_fx = 0; + move16(); + } + ELSE IF ( st_fx->inact_cnt_fx > 0 ) + { + st_fx->inact_cnt_fx = sub(st_fx->inact_cnt_fx,1); + } + + test(); + IF ( st_fx->sp_mus_state_fx > 0 && LT_16(st_fx->sp_mus_state_fx,HANG_LEN)) + { + + st_fx->sp_mus_state_fx = -HANG_LEN; + move16(); + } + ELSE IF ( st_fx->sp_mus_state_fx > 0 ) + { + + st_fx->sp_mus_state_fx = -1; + move16(); + } + ELSE IF ( GT_16(st_fx->sp_mus_state_fx,-HANG_LEN)) + { + /* we are in inactive state */ + st_fx->sp_mus_state_fx = sub(st_fx->sp_mus_state_fx,1); + } + } + + /*------------------------------------------------------------------* + * Decision without hangover + * Weighted decision + *------------------------------------------------------------------*/ + + /* decision without hangover (0 - speech/noise, 1 - music) */ + logic16(); + dec = sub(lpm,lps) > 0; + move16(); + dlp = sub(lpm,lps); /*Q9*/ + + IF ( !vad ) + { + dec = 0; + move16(); + dlp = 0; + move16(); + } + + /* calculate weight based on relE (close to 0.01 in low-E regions, close to 1 in high-E regions) */ + /*wrelE = 1.0f + relE/15;*/ + wrelE = add(2048, mult_r(relE,17476)); /* 1/15 in Q18 -> 17476 result in Q11 */ + + + wrelE = s_min(wrelE, 2048); + wrelE = s_max(wrelE, 20); + + /* calculate weight based on drops of dlp (close to 1 during sudden drops of dlp, close to 0 otherwise) */ + test(); + IF ( dlp < 0 && LT_16(dlp,st_fx->past_dlp_fx[0])) + { + IF ( st_fx->past_dlp_fx[0] > 0 ) + { + st_fx->wdrop_fx = negate(dlp); /*Q9*/ + } + ELSE + { + st_fx->wdrop_fx = add(st_fx->wdrop_fx, sub(st_fx->past_dlp_fx[0], dlp)); /*Q9*/ + } + } + ELSE + { + st_fx->wdrop_fx = 0; + move16(); + } + + /*wdrop = st->wdrop/20;*/ + wdrop = mult_r(st_fx->wdrop_fx, 26214); /*Q9*Q19->Q13*/ + wdrop = s_min(wdrop,8192); /* limitation [0.1,1] Q13 */ + wdrop = s_max(wdrop,819); + + /* combine weights into one */ + /*wght = wrelE * wdrop;*/ + wght = mult_r(wrelE, wdrop); /* Q11*Q13 -> Q9*/ + wght = s_max(wght,5); + + /* calculate weighted decision */ + /*st->wdlp_0_95_sp = wght * dlp + (1 - wght) * st->wdlp_0_95_sp;*/ + /* = Q9 * Q9 + (Q9-Q9)*Q9 */ + L_tmp = L_mac(L_mult(wght, dlp), sub(512, wght), st_fx->wdlp_0_95_sp_fx); + st_fx->wdlp_0_95_sp_fx = round_fx(L_shl(L_tmp, 6)); + + if ( EQ_16(st_fx->sp_mus_state_fx,-HANG_LEN)) + { + st_fx->wdlp_0_95_sp_fx = 0; + move16(); + } + + /*------------------------------------------------------------------* + * Final speech/music decision + *------------------------------------------------------------------*/ + + test(); + test(); + IF ( !vad && EQ_16(st_fx->sp_mus_state_fx,-HANG_LEN)) + { + /* inactive state */ + dec = 0; + move16(); + } + ELSE IF ( st_fx->sp_mus_state_fx <= 0 ) + { + /* transition from active to inactive state or instable state */ + dec = st_fx->past_dec_fx[0]; + move16(); + } + ELSE IF ( st_fx->sp_mus_state_fx > 0 && LT_16(st_fx->sp_mus_state_fx,HANG_LEN)) + { + /* entry state -> final decision is calculated based on weighted average of past non-binary decisions */ + L_tmp = L_mult(w_spmus_fx[st_fx->sp_mus_state_fx-1][0], dlp); /*Q15*Q9 */ + + /*ftmp += dotp( &w[st_fx->sp_mus_state_fx-1][1], st_fx->past_dlp_fx, HANG_LEN-1 );*/ + L_tmp = L_add(L_tmp, Dot_product( &w_spmus_fx[st_fx->sp_mus_state_fx-1][1], st_fx->past_dlp_fx, HANG_LEN-1 )); + logic16(); + move16(); + + /*dec = ftmp > 2.0f;*/ + dec = L_sub(L_tmp, 2*(1<<25))>0; + } + ELSE + { + /* stable active state */ + test(); + test(); + test(); + test(); + IF ( st_fx->wdlp_0_95_sp_fx > 0 && st_fx->past_dec_fx[0] == 0 && st_fx->past_dec_fx[1] == 0 && st_fx->past_dec_fx[2] == 0 ) + { + /* switching from speech to music */ + dec = 1; + move16(); + } + ELSE IF ( st_fx->past_dec_fx[0] == 1 && st_fx->wdlp_0_95_sp_fx < 0 ) + { + /* switching from music to speech */ + dec = 0; + move16(); + } + ELSE + { + dec = st_fx->past_dec_fx[0]; + move16(); + } + } + + + /*------------------------------------------------------------------* + * Updates + *------------------------------------------------------------------*/ + + /* update the buffer of past non-binary decisions */ + Copy( &st_fx->past_dlp_fx[0], &st_fx->past_dlp_fx[1], HANG_LEN-2 ); + st_fx->past_dlp_fx[0] = dlp; + move16(); + + /* update the buffer of past binary decisions */ + Copy( &st_fx->past_dec_fx[0], &st_fx->past_dec_fx[1], HANG_LEN-2 ); + st_fx->past_dec_fx[0] = dec; + move16(); + + return dec; +} + + +/*---------------------------------------------------------------------* + * sp_mus_classif_2nd_fx() + * + * 2nd stage speech/music classifier (convert music to speech for onsets) + *---------------------------------------------------------------------*/ + +static void sp_mus_classif_2nd_fx( + Encoder_State_fx *st, /* i/o: Encoder state structure */ + const Word16 sp_aud_decision1, /* i : 1st stage decision flag */ + Word16 *sp_aud_decision2, /* i/o: 2nd stage decision flag */ + const Word16 pitch[3], /* i : open-loop pitch estimate in three subframes */ + const Word16 Etot, /* i : total frame energy */ + Word16 *coder_type, /* i/o: coder type */ + Word16 *attack_flag, /* i/o: attack flag (GSC or TC) */ + const Word16 *inp, /* i : input signal */ + const Word16 Qx, + const Word16 localVAD, + const Word16 vad_flag +) +{ + Word16 attack; + + /* initialization */ + *attack_flag = 0; + move16(); + + /* signal stability estimation */ + stab_est_fx( Etot, st->gsc_lt_diff_etot_fx, &st->gsc_mem_etot_fx + , &st->gsc_nb_thr_3_fx, &st->gsc_nb_thr_1_fx, st->gsc_thres_fx, &st->gsc_last_music_flag_fx, vad_flag ); + + /* calculate variance of correlation */ + var_cor_calc_fx( st->old_corr_fx, &st->mold_corr_fx, st->var_cor_t_fx, &st->high_stable_cor_fx ); + + /* attack detection */ + attack = attack_det_fx( inp, Qx, st->clas_fx, localVAD, *coder_type + , st->total_brate_fx); + + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_16(sp_aud_decision1,1)) + { + test(); + test(); + test(); + IF( LT_16(st->ener_RAT_fx,5898)&>_16(st->lt_dec_thres_fx,7680)) + { + *sp_aud_decision2 = 0; + move16(); + } + ELSE IF( EQ_16(st->high_stable_cor_fx, 1)&&GE_16(pitch[0],130)) + { + /* prevent GSC in highly correlated signal with low energy variation */ + /* this is basically a patch against bassoon-type of music */ + *sp_aud_decision2 = 0; + move16(); + + test(); + IF( EQ_16(st->codec_mode,MODE1)&&EQ_16(*coder_type,TRANSITION)) + { + *coder_type = GENERIC; + move16(); + } + } + ELSE IF( GT_16(st->gsc_lt_diff_etot_fx[MAX_LT-1],1152)&& + GT_16(sub(st->gsc_lt_diff_etot_fx[MAX_LT-1], st->gsc_lt_diff_etot_fx[MAX_LT-2]),2560)) /* 10.0f in Q8 */ + { + IF ( EQ_16(st->tc_cnt_fx,1)) + { + *sp_aud_decision2 = 0; + move16(); + + IF( EQ_16(st->codec_mode,MODE1)) + { + *coder_type = TRANSITION; + move16(); + } + } + ELSE + { + IF( GE_16(attack, ATT_3LSUB_POS)) + { + /* do TC coding if attack is located in the last subframe */ + *sp_aud_decision2 = 0; + move16(); + *attack_flag = 1; + move16(); + IF( EQ_16(st->codec_mode,MODE1)) + { + *coder_type = TRANSITION; + move16(); + } + } + ELSE IF( GE_16(attack,ATT_SEG_LEN/2)) + { + /* do GSC coding if attack is located after the first quarter of the first subframe */ + /* (pre-echo will be treated at the decoder side) */ + *attack_flag = 1; + move16(); + } + } + } + } + ELSE IF( EQ_16(localVAD,1)&&EQ_16(*coder_type,GENERIC)&& + ( (GE_16(attack,ATT_3LSUB_POS) && LT_32(st->total_brate_fx,ACELP_24k40)) || + (GE_16(attack,ATT_3LSUB_POS_16k) && GE_32(st->total_brate_fx,ACELP_24k40) && LT_32(st->total_brate_fx,ACELP_48k)) ) + ) + { + /* do TC coding if attack is located in the last subframe */ + *attack_flag = 1; + move16(); + IF( EQ_16(st->codec_mode,MODE1)) + { + *coder_type = TRANSITION; + move16(); + } + } + + return; +} + + +/*---------------------------------------------------------------------* + * var_cor_calc_fx() + * + * Calculate variance of correlation + *---------------------------------------------------------------------*/ + +static void var_cor_calc_fx( + const Word16 old_corr, + Word16 *mold_corr, + Word16 var_cor_t[], + Word16 *high_stable_cor +) +{ + Word16 i, var_cor; + + /* update buffer of old correlation values */ + FOR( i = VAR_COR_LEN-1; i > 0; i-- ) + { + var_cor_t[i] = var_cor_t[i-1]; /*Q11*/ move16(); + } + var_cor_t[i] = old_corr; + move16(); + + /* calculate variance of correlation */ + var_cor = var_fx( var_cor_t, 11, VAR_COR_LEN ); + + *high_stable_cor = 0; + move16(); + test(); + IF( GT_16(*mold_corr,26214)&<_16(var_cor,2)) + { + *high_stable_cor = 1; + move16(); + } + + /* update average correlation */ + /*st->mold_corr = 0.1f * st->old_corr + 0.9f * st->mold_corr;*/ + *mold_corr = mac_r(L_mult(3277,old_corr),29491,*mold_corr); /*Q15 */ + + return; +} + +/*---------------------------------------------------------------------* + * attack_det_fx() + * + * Attack detection + *---------------------------------------------------------------------*/ + +static Word16 attack_det_fx( /* o : attack flag */ + const Word16 *inp, /* i : input signal */ + const Word16 Qx, + const Word16 last_clas, /* i : last signal clas */ + const Word16 localVAD, + const Word16 coder_type /* i : coder type */ + ,const Word32 total_brate /* i : total bit-rate */ +) +{ + Word16 i, j, tmp, tmp1, attack, exp1; + Word32 L_tmp, etmp, etmp2, finc[ATT_NSEG]; + Word16 att_3lsub_pos; + + att_3lsub_pos = ATT_3LSUB_POS; + move16(); + if( GE_32(total_brate,ACELP_24k40)) + { + att_3lsub_pos = ATT_3LSUB_POS_16k; + move16(); + } + + /* compute energy per section */ + FOR( i=0; i 0 ) + { + etmp2 = L_add(finc[attack], 0); + etmp = Mult_32_16(etmp2, 16384); /* etmp2 / 2.0 = (etmp2*0.5) */ + FOR( i=2; i 0 ) + { + etmp2 = L_add(finc[attack], 0); + etmp = Mult_32_16(etmp2, 25206); /* etmp2 / 1.3 = (etmp2*0.76923) */ + FOR( i=2; i etmp2 ) -> finc[i] > (etmp2*0.76923) */ + test(); + IF( NE_16(i,attack)&>_32(finc[i],etmp)) + { + attack = 0; + move16(); + BREAK; + } + } + } + + return attack; +} + +/*---------------------------------------------------------------------* + * mode_decision_fx() + * + * + *---------------------------------------------------------------------*/ + +static Word16 mode_decision_fx( + Encoder_State_fx *st, /* i : endoer state structure */ + Word16 len, /* i : buffering status */ + Word16 *dec_mov, /* i/o: moving average of classifier decision Q15*/ + Word16 *buf_flux, /* i : buffer storing spectral energy fluctuation Q7*/ + Word16 *buf_epsP_tilt, /* i : buffer storing LP prediciton error tilt Q15*/ + Word16 *buf_pkh, /* i : buffer storing highband spectral peakiness Q1*/ + Word16 *buf_cor_map_sum, /* i : buffer storing correlation map sum Q8*/ + Word16 *buf_Ntonal, /* i : buffer storing No.of 1st spectral tone Q0*/ + Word16 *buf_Ntonal2, /* i : buffer storing No.of 2nd spectral tone Q0*/ + Word16 *buf_Ntonal_lf, /* i : buffer storing low band spectral tone ratio Q0*/ + Word16 *buf_dlp /* i : buffer storing log probability diff between speech and music Q9*/ +) +{ + Word16 mode; + Word16 i; + Word16 voiced_cnt; + Word16 M_pkh; + Word16 M_cor_map_sum; + Word16 M_Ntonal; + Word16 M_flux; + Word32 V_epsP_tilt; + Word16 lf_Ntonal_ratio; + Word16 tmp, tmp1; + Word32 L_tmp; + Word16 inv_len; + Word16 j; + Word16 M_flux10; + + + mode = *dec_mov > 16384; + logic16(); + move16(); + + IF ( LE_16(len,5)) + { + return (mode); + } + ELSE + { + IF ( LT_16(len,10)) + { + inv_len = div_s(1,len); /*Q15 */ + + L_tmp = L_deposit_l(0); + FOR(i=0; i3; i-- ) + { + if ( buf_dlp[i] > 0 ) + { + voiced_cnt = add(voiced_cnt,1); + } + } + + test(); + test(); + test(); + test(); + IF ( (GT_16(M_pkh,2200)||LT_32(V_epsP_tilt,171799)||GT_16(M_cor_map_sum,25600))&&voiced_cnt<4) + { + mode = 1; + move16(); + } + ELSE IF ( GT_16(M_Ntonal,108)&&voiced_cnt<4) /*27 in Q2 */ + { + mode = 1; + move16(); + } + } + ELSE + { + voiced_cnt = 0; + move16(); + FOR ( i=0; i<10; i++ ) + { + if ( buf_dlp[i] > 0 ) + { + voiced_cnt = add(voiced_cnt,1); + } + } + + inv_len = 3277; /*Q15 */ + + L_tmp = L_deposit_l(0); + FOR(i=0; i<10; i++) + { + L_tmp = L_add(L_tmp,L_shl(buf_flux[BUF_LEN-10+i],2)); /*Q9 */ + } + L_tmp = Mult_32_16(L_tmp,inv_len); /*Q9 */ + M_flux10 = extract_l(L_tmp); /*Q9 */ + + L_tmp = L_deposit_l(0); + FOR(i=0; i<10; i++) + { + L_tmp = L_add(L_tmp,buf_pkh[BUF_LEN-10+i]); /*Q1 */ + } + L_tmp = Mult_32_16(L_tmp,inv_len); /*Q1 */ + M_pkh = extract_l(L_tmp); /*Q1 */ + + L_tmp = L_deposit_l(0); + FOR(i=0; i<10; i++) + { + L_tmp = L_add(L_tmp,buf_cor_map_sum[BUF_LEN-10+i]); /*Q8 */ + } + L_tmp = Mult_32_16(L_tmp,inv_len); /*Q8 */ + M_cor_map_sum = extract_l(L_tmp); /*Q8 */ + + V_epsP_tilt = var_fx_32( buf_epsP_tilt+BUF_LEN-10, 15, 10 ); /*Q31 */ + + L_tmp = L_deposit_l(0); + FOR(i=0; i<5; i++) + { + L_tmp = L_add(L_tmp,L_shl(buf_flux[BUF_LEN-5+i],2)); /*Q9 */ + } + L_tmp = Mult_32_16(L_tmp,6554); /*Q9 */ + tmp = extract_l(L_tmp); /*Q9 */ + + test(); + test(); + test(); + test(); + test(); + test(); + IF ( (LT_16(M_flux10,4352)||(LT_32(V_epsP_tilt,2147484)&<_16(M_flux10,6144))||GT_16(M_pkh,2100)||GT_16(M_cor_map_sum,25600))&& + LT_16(voiced_cnt,3) && LT_16(tmp,7680) ) + { + mode = 1; + move16(); + *dec_mov = 32767; + move16(); + return ( mode ); + } + + test(); + test(); + test(); + test(); + test(); + IF ( GT_16(M_flux10,8192)||(GT_16(M_flux10,7680)&&voiced_cnt>2)||GT_16(tmp,9728)||(GE_16(buf_flux[59],2560)&>_16(st->lps_fx,st->lpm_fx))) + { + mode = 0; + move16(); + *dec_mov = 0; + move16(); + return ( mode ); + } + + FOR ( i=10; i=0; i-- ) + { + IF (LE_16(Bin_E[i+1],Bin_E[i])) + { + BREAK; + } + k = i; + move16(); + } + + FOR ( i=1; ilp_speech_fx,st->lp_noise_fx),6400)) /* 25 in Q8 */ + { + /* st->dec_mov = 0.5f; */ + /* st->dec_mov1 = 0.5f; */ + st->dec_mov_fx = 16384; + move16(); + st->dec_mov1_fx = 16384; + move16(); + + if ( vad_flag == 0 ) + { + st->onset_cnt_fx = 0; + move16(); + } + + return; + } + + st->onset_cnt_fx = add(st->onset_cnt_fx,1); + st->onset_cnt_fx = s_min(st->onset_cnt_fx, 9); + + IF ( EQ_16(st->onset_cnt_fx,1)) + { + set16_fx( st->buf_flux_fx, -12800, BUF_LEN ); /*-100.0 in Q7 */ + } + + /* spectral analysis */ + spec_analysis_fx( st->lgBin_E_fx, p2v_map ); + + /* percussive music detection */ + log_max_spl = 0; + move16(); + IF ( max_spl ) + { + L_tmp = L_deposit_h(max_spl); /*Q16 */ + exp = norm_l(L_tmp); + frac = Log2_norm_lc(L_shl(L_tmp,exp)); + exp = sub(sub(30,exp),16); + L_tmp = Mpy_32_16(exp,frac,28391); /*Q12 */ + log_max_spl = round_fx(L_shl(L_tmp,11)); /*Q7 */ + } + + lt_diff = sub(log_max_spl,st->mov_log_max_spl_fx); /*Q7 */ + + FOR ( i=0; i<3; i++ ) + { + st->buf_etot_fx[i] = st->buf_etot_fx[i+1]; + move16(); /*Q8 */ + } + st->buf_etot_fx[i] = etot; + move16();/*Q8 */ + + percus_flag = 0; + move16(); + test(); + test(); + IF ( GT_16(sub(st->buf_etot_fx[1],st->buf_etot_fx[0]),1536)&& + LT_16(st->buf_etot_fx[2],st->buf_etot_fx[1]) && + GT_16(sub(st->buf_etot_fx[1],st->lp_speech_fx),768) ) /* 3 in Q8 */ + { + /*tmp = add(shr(voicing[0],2),shr(voicing[1],2)); //Q15 */ + /*tmp = add(tmp,shr(old_cor,1)); //Q15 */ + tmp = mac_r(L_mac(L_mult(voicing[0],8192),voicing[1],8192),old_cor, 16384); + test(); + test(); + IF ( GT_16(sub(st->buf_etot_fx[1],st->buf_etot_fx[3]),768)&& + LT_16(st->buf_etot_fx[3],st->buf_etot_fx[2]) && + LT_16(tmp,24576)) /* 0.75 in Q15 */ + { + IF ( GT_16(st->dec_mov_fx,26214)) /* 0.8 in Q15 */ + { + percus_flag = 1; + move16(); + } + ELSE + { + test(); + test(); + test(); + IF ( LT_16(old_cor,24576)&<_16(voicing[0],24576)&<_16(voicing[1],24576)&>_16(st->old_lt_diff_fx[0],1280)) + { + percus_flag = 1; + move16(); + } + } + } + } + + /* sound attack detection */ + test(); + test(); + test(); + IF ( GT_16(sub(st->buf_etot_fx[3],st->buf_etot_fx[2]),1536) + && GT_16(st->dec_mov_fx,29491) + && GT_16(sub(etot,st->lp_speech_fx),1280) + && GT_16(st->old_lt_diff_fx[0],640)) + { + st->attack_hangover_fx = 3; + move16(); + } + + test(); + IF ( GT_16(voicing[0],29491)&>_16(voicing[1],29491)) + { + IF ( GT_16(log_max_spl,st->mov_log_max_spl_fx)) + { + /**mov_log_max_spl = add(mult_r(31130,(*mov_log_max_spl)),mult_r(1638,log_max_spl)); //Q7 */ + st->mov_log_max_spl_fx = round_fx(L_mac(L_mult(31130,st->mov_log_max_spl_fx),1638,log_max_spl)); /*Q7 */ + } + ELSE + { + /**mov_log_max_spl = add(mult_r(32604,(*mov_log_max_spl)),mult_r(164,log_max_spl)); //Q7 */ + st->mov_log_max_spl_fx = round_fx(L_mac(L_mult(32604,st->mov_log_max_spl_fx),164,log_max_spl)); /*Q7 */ + } + } + + st->old_lt_diff_fx[0] = st->old_lt_diff_fx[1]; + move16(); /*Q7 */ + st->old_lt_diff_fx[1] = lt_diff; + move16(); /*Q7 */ + + /* calculate and buffer spectral energy fluctuation */ + flux_fx( st->lgBin_E_fx, p2v_map, st->old_Bin_E_fx, st->buf_flux_fx, st->attack_hangover_fx, st->dec_mov_fx ); + + st->attack_hangover_fx = sub(st->attack_hangover_fx,1); + st->attack_hangover_fx = s_max(st->attack_hangover_fx,0); + + /* identify flux buffer buffering status */ + len = 0; + move16(); + FOR ( i=BUF_LEN-1; i>=0; i-- ) + { + IF (st->buf_flux_fx[i] < 0) + { + BREAK; + } + + len = add(len,1); + } + + /* reset flux buffer if percussive music is detected */ + IF ( EQ_16(percus_flag,1)) + { + set16_fx( &st->buf_flux_fx[BUF_LEN-len], 640, len ); /* 5 in Q7 */ + } + + /* calculate and buffer the tilt of residual LP energies */ + ftmp = 0; + move16(); + ftmp1 = 0; + move16(); + FOR( i=1; i<=16; i++ ) + { + epsP_max = L_max(epsP_max , epsP[i]); + } + + FOR ( i=1; i<16; i++ ) + { + IF(EQ_32(epsP[i], epsP_max)) + { + tmp = -32768; + move16(); + L_tmp = Mult_32_16(epsP[i],tmp); /* Q_epsP */ + ftmp = L_sub(ftmp,L_shr(L_tmp,4)); /* Q(Q_epsP-4) */ + } + ELSE + { + expn = norm_l(epsP[i]); + fracn = extract_h(L_shl(epsP[i],expn)); + expn = sub(sub(30,expn),Q_epsP); + + expd = norm_l(epsP_max); + fracd = extract_h(L_shl(epsP_max,expd)); + expd = sub(sub(30,expd),Q_epsP); + + scale = shr(sub(fracd,fracn),15); + fracn = shl(fracn,scale); + expn = sub(expn,scale); + + tmp = div_s(fracn,fracd); /*Q(15+expd-expn) */ + tmp = shl(tmp,sub(expn,expd)); /*Q15 */ + + L_tmp = Mult_32_16(epsP[i],tmp); /*Q_epsP */ + ftmp = L_add(ftmp,L_shr(L_tmp,4)); /*Q(Q_epsP-4) */ + } + } + + FOR ( i=1; i<16; i++ ) + { + IF(EQ_32(epsP[i], epsP_max)) + { + tmp = -32768; + move16(); + L_tmp = Mult_32_16(epsP[i+1],tmp); /*Q_epsP */ + ftmp1 = L_sub(ftmp1,L_shr(L_tmp,4)); /*Q(Q_epsP-4) */ + } + ELSE IF(EQ_32(epsP[i+1],epsP_max)) + { + tmp = -32768; + move16(); + L_tmp = Mult_32_16(epsP[i],tmp); /*Q_epsP */ + ftmp1 = L_sub(ftmp1,L_shr(L_tmp,4)); /*Q(Q_epsP-4) */ + } + ELSE + { + expn = norm_l(epsP[i]); + fracn = extract_h(L_shl(epsP[i],expn)); + expn = sub(sub(30,expn),Q_epsP); + + expd = norm_l(epsP_max); + fracd = extract_h(L_shl(epsP_max,expd)); + expd = sub(sub(30,expd),Q_epsP); + + scale = shr(sub(fracd,fracn),15); + fracn = shl(fracn,scale); + expn = sub(expn,scale); + + tmp = div_s(fracn,fracd); /*Q(15+expd-expn) */ + tmp = shl(tmp,sub(expn,expd)); /*Q15 */ + + L_tmp = Mult_32_16(epsP[i+1],tmp); /*Q_epsP */ + ftmp1 = L_add(ftmp1,L_shr(L_tmp,4)); /*Q(Q_epsP-4) */ + } + } + + /* epsP_tilt = ftmp1/ftmp; */ + expn = norm_l(ftmp1); + fracn = extract_h(L_shl(ftmp1,expn)); + expn = sub(sub(30,expn),Q_epsP-4); + + expd = norm_l(ftmp); + fracd = round_fx(L_shl(ftmp,expd)); + expd = sub(sub(30,expd),sub(Q_epsP,4)); + + scale = shr(sub(fracd,fracn),15); + fracn = shl(fracn,scale); + expn = sub(expn,scale); + + tmp = div_s(fracn,fracd); /*Q(15+expd-expn) */ + + epsP_tilt = shl(tmp,sub(expn,expd)); /*Q15 */ + + FOR ( i=0; ibuf_epsP_tilt_fx[i] = st->buf_epsP_tilt_fx[i+1]; + move16(); /*Q15 */ + } + st->buf_epsP_tilt_fx[i] = epsP_tilt; + move16(); /*Q15 */ + + /* calculate and buffer highband spectral peakness */ + tonal_dist_fx( p2v_map, st->buf_pkh_fx, st->buf_Ntonal_fx, st->buf_Ntonal2_fx, st->buf_Ntonal_lf_fx ); + + /* buffer sum of correlation map */ + FOR ( i=0; ibuf_cor_map_sum_fx[i] = st->buf_cor_map_sum_fx[i+1]; + move16(); /*Q8 */ + } + st->buf_cor_map_sum_fx[i] = cor_map_sum; + move16(); /*Q8 */ + + /* buffer voicing metric */ + FOR ( i=0; i<9; i++ ) + { + st->buf_dlp_fx[i] = st->buf_dlp_fx[i+1]; + move16(); + } + st->buf_dlp_fx[i] = sub(st->lps_fx, st->lpm_fx); + move16();/*Q9 */ + + /* classification */ + dec = mode_decision_fx( st, len, &st->dec_mov_fx, st->buf_flux_fx, st->buf_epsP_tilt_fx, st->buf_pkh_fx, + st->buf_cor_map_sum_fx, st->buf_Ntonal_fx, st->buf_Ntonal2_fx, st->buf_Ntonal_lf_fx, + st->buf_dlp_fx ); + move16(); + + /* update long term moving average of the classification decisions */ + IF ( GT_16(len,30)) + { + IF( dec == 0 ) + { + st->dec_mov_fx = mult_r(31785,st->dec_mov_fx); /*Q15 */ + st->dec_mov1_fx = mult_r(31785,st->dec_mov1_fx); /*Q15 */ + } + ELSE + { + st->dec_mov_fx = add(mult_r(31785,st->dec_mov_fx),983); /*Q15 */ + st->dec_mov1_fx = add(mult_r(31785,st->dec_mov1_fx),983); /*Q15 */ + } + } + + /* update long term unvoiced counter */ + test(); + test(); + test(); + IF ( (EQ_16(st->coder_type_raw_fx,UNVOICED)||EQ_16(st->coder_type_raw_fx,INACTIVE))&& + GT_16(etot,384) && LT_16(st->buf_Ntonal2_fx[59],2) ) + { + st->UV_cnt1_fx = sub(st->UV_cnt1_fx,8); + } + ELSE + { + st->UV_cnt1_fx = add(st->UV_cnt1_fx,1); + } + + st->UV_cnt1_fx = s_min(st->UV_cnt1_fx,300); + st->UV_cnt1_fx = s_max(st->UV_cnt1_fx,0); + + /**LT_UV_cnt1 = add(mult_r(29491,*LT_UV_cnt1),mult_r(3277,shl(*UV_cnt1,6)));*/ /* Q6 */ + st->LT_UV_cnt1_fx = round_fx(L_mac(L_mult(29491,st->LT_UV_cnt1_fx),3277,shl(st->UV_cnt1_fx,6))); /*Q6 */ + + /* revert classification decision due to long-term unvoiced counter */ + test(); + test(); + IF ( EQ_16(dec,1)&<_16(st->dec_mov1_fx,6554)&<_16(st->LT_UV_cnt1_fx,12800)) + { + dec = 0; + move16(); + } + + /* overwrite 1st stage speech/music decision to music */ + IF (EQ_16(dec,1)) + { + *sp_aud_decision1 = 1; + move16(); + } + + return; +} + + + +/*----------------------------------------------------------------------------------* + * tonal_context_improv_fx() + * + * Context-based improvement of 1st/2nd stage speech/music decision on stable tonal signals + *----------------------------------------------------------------------------------*/ + +static void tonal_context_improv_fx( + Encoder_State_fx *st_fx, /* i/o: Encoder state structure */ + const Word32 PS[], /* i : energy spectrum */ + Word16 *sp_aud_decision1, /* i/o: 1st stage speech/music decision */ + Word16 *sp_aud_decision2, /* i/o: 2nd stage speech/music decision */ + const Word16 vad_flag, + const Word16 pitch[3], /* i : open-loop pitch estimate in three subframes */ + const Word16 voicing[3], /* i : voicing estimate in three subframes */ + const Word16 voi_fv, /* i : scaled voicing feature */ + const Word16 cor_map_sum_fv, /* i : scaled correlation map feature */ + const Word16 LPCErr, /* i : scaled LP prediction error feature */ + const Word16 Qx +) +{ + Word16 t2_fx, t3_fx, tL_fx, err_fx, cor_fx, dft_fx; + Word16 exp, expa, expb, fraca, fracb, scale, exp1, exp2, exp3, tmp; + Word16 voi_mean, lt_pitch_diff; + Word32 L_tmp, tonality, tonality1, tonality2, tonality3, sort_max, sort_avg, sort_val[80]; + + IF ( EQ_16(st_fx->last_codec_mode, MODE2)) + { + set16_fx(st_fx->tonality2_buf_fx,0,HANG_LEN_INIT); + set16_fx(st_fx->tonality3_buf_fx,0,HANG_LEN_INIT); + set16_fx(st_fx->LPCErr_buf_fx,0,HANG_LEN_INIT); + st_fx->lt_music_hangover_fx = 0; + move16(); + st_fx->lt_music_state_fx = 0; + move16(); + st_fx->lt_speech_state_fx = 0; + move16(); + st_fx->lt_speech_hangover_fx= 0; + move16(); + } + + /* estimate maximum tonality in bands [0-1 kHz], [1-2kHz] and [2-4kHz] */ + Copy32( PS, sort_val, 80 ); + + /* tonality in band [0-1 kHz] */ + sort_32_fx(sort_val, 0, 19); + sort_max = L_add(sort_val[19], 0); + sort_avg = sum32_fx(&sort_val[0], 10); + + /* tonality1 = sort_max / sort_avg; */ + IF( sort_avg ) + { + expa = norm_l(sort_max); + fraca = extract_h(L_shl(sort_max,expa)); + expa = sub(30,add(expa, Qx)); + + expb = norm_l(sort_avg); + fracb = extract_h(L_shl(sort_avg,expb)); + expb = sub(30,add(expb, Qx)); + + scale = shr(sub(fracb,fraca),15); + fraca = shl(fraca,scale); + expa = sub(expa,scale); + + tmp = div_s(fraca,fracb); + exp1 = sub(expa,expb); + + tonality1 = L_shl(tmp , exp1); + } + ELSE + { + tonality1 = L_shl(sort_max,sub(15,Qx)); /*Q15 */ + } + + /* tonality in band [1-2 kHz] */ + sort_32_fx(sort_val, 20, 39); + sort_max = sort_val[39]; + sort_avg = sum32_fx(&sort_val[20], 10); + + IF( sort_avg ) + { + /* tonality2 = sort_max / sort_avg; */ + expa = norm_l(sort_max); + fraca = extract_h(L_shl(sort_max,expa)); + expa = sub(30,add(expa, Qx)); + + + expb = norm_l(sort_avg); + fracb = extract_h(L_shl(sort_avg,expb)); + expb = sub(30,add(expb, Qx)); + + scale = shr(sub(fracb,fraca),15); + fraca = shl(fraca,scale); + expa = sub(expa,scale); + + tmp = div_s(fraca,fracb); + exp2 = sub(expa,expb); + + tonality2 = L_shl(tmp , exp2); + } + ELSE + { + tonality2 = L_shl(sort_max,sub(15,Qx)); /*Q15 */ + } + + /* tonality in band [2-4 kHz] */ + sort_32_fx(sort_val, 40, 79); + sort_max = sort_val[79]; + sort_avg = sum32_fx(&sort_val[40], 20); + + IF( sort_avg ) + { + /* tonality3 = sort_max / sort_avg; */ + expa = norm_l(sort_max); + fraca = extract_h(L_shl(sort_max,expa)); + expa = sub(30,add(expa, Qx)); + + expb = norm_l(sort_avg); + fracb = extract_h(L_shl(sort_avg,expb)); + expb = sub(30,add(expb, Qx)); + + scale = shr(sub(fracb,fraca),15); + fraca = shl(fraca,scale); + expa = sub(expa,scale); + + tmp = div_s(fraca,fracb); + exp3 = sub(expa,expb); + + tonality3 = L_shl(tmp , exp3); + } + ELSE + { + tonality3 = L_shl(sort_max,sub(15,Qx)); /*Q15 */ + } + + tonality = L_max(L_max(tonality1, tonality2), tonality3); + + /* voi_mean = 0.33f * (voicing[0] + voicing[1] + voicing[2]); */ + L_tmp = L_mult(voicing[0], 10923); + L_tmp = L_mac(L_tmp, voicing[1], 10923); + voi_mean = mac_r(L_tmp, voicing[2], 10923); /* Q15 */ + + test(); + IF( EQ_16(st_fx->hangover_cnt_fx,10)&&EQ_16(vad_flag,1)) + { + /* long-term voicing parameter */ + st_fx->lt_voicing = round_fx(L_mac(L_mult(3277,st_fx->lt_voicing),29491, voi_mean)); + + /* long-term correlation value */ + st_fx->lt_corr = round_fx(L_mac(L_mult(3277,st_fx->lt_corr),29491, st_fx->old_corr_fx)); + + /* long-term tonality measure */ + st_fx->lt_tonality = L_add(Mult_32_16(st_fx->lt_tonality,3277),Mult_32_16(tonality,29491)); + } + ELSE + { + /* long-term voicing parameter */ + st_fx->lt_voicing = round_fx(L_mac(L_mult(22938,st_fx->lt_voicing),9830, voi_mean)); + + /* long-term correlation value */ + st_fx->lt_corr = round_fx(L_mac(L_mult(22938,st_fx->lt_corr),9830, st_fx->old_corr_fx)); + + /* long-term tonality measure */ + st_fx->lt_tonality = L_add(Mult_32_16(st_fx->lt_tonality,16384),Mult_32_16(tonality,16384)); + } + + /* Pitch difference w.r.t to past 3 frames */ + lt_pitch_diff = abs_s(sub(st_fx->lt_corr_pitch[0], pitch[0])); + lt_pitch_diff = add(lt_pitch_diff , abs_s(sub(st_fx->lt_corr_pitch[1], pitch[0]))); + lt_pitch_diff = add(lt_pitch_diff,abs_s(sub(st_fx->lt_corr_pitch[2], pitch[0]))); + + st_fx->lt_corr_pitch[0] = st_fx->lt_corr_pitch[1]; + move16(); + st_fx->lt_corr_pitch[1] = st_fx->lt_corr_pitch[2]; + move16(); + st_fx->lt_corr_pitch[2] = pitch[0]; + move16(); + + st_fx->lt_old_mode[0] = st_fx->lt_old_mode[1]; + move16(); + st_fx->lt_old_mode[1] = st_fx->lt_old_mode[2]; + move16(); + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF ( *sp_aud_decision1 == 1 && + ( GT_32(L_min(L_min(tonality1, tonality2), tonality3),1638400) ) && + ( GT_32(L_add(tonality1, tonality2),6553600) && GT_32(L_add(tonality2, tonality3),6553600) && GT_32(L_add(tonality1, tonality3),6553600)) && + ( LT_32(st_fx->lt_tonality,655360000) ) && + ( ( GT_32(st_fx->lt_tonality,32768000) && GT_16(s_max(st_fx->lt_voicing, voi_mean),32440) ) || + ( GT_32(st_fx->lt_tonality,49152000) && GT_16(st_fx->lt_corr,32440) ) || + ( GT_32(st_fx->lt_tonality,98304000) && GT_16(st_fx->lowrate_pitchGain,15729) ) || + ( lt_pitch_diff == 0 && GT_16(st_fx->lowrate_pitchGain,14582)))) + { + IF( LT_16(sum16_fx(st_fx->lt_old_mode, 2),2)) + { + /* probably speech - change the decision to speech */ + *sp_aud_decision1 = 0; + move16(); + *sp_aud_decision2 = 0; + move16(); + + if( st_fx->lt_hangover == 0 ) + { + st_fx->lt_hangover = 6; + move16(); + } + } + } + ELSE + { + /* not speech, but still in the hangover period - change the decision to speech */ + IF( st_fx->lt_hangover > 0 ) + { + *sp_aud_decision1 = 0; + move16(); + *sp_aud_decision2 = 0; + move16(); + + st_fx->lt_hangover = sub(st_fx->lt_hangover,1); + } + } + + /* calculate standard deviation of log-tonality */ + Copy( st_fx->tonality2_buf_fx + 1, st_fx->tonality2_buf_fx, HANG_LEN_INIT - 1 ); + /* st->tonality2_buf[HANG_LEN_INIT - 1] = 0.2f*(float)log10(tonality2); */ + exp = norm_l(tonality2); + tmp = Log2_norm_lc(L_shl(tonality2, exp));/*15 */ + exp = sub(30, add(exp, 16)); + L_tmp = Mpy_32_16(exp, tmp, 15783);/*19 //3945, 0.2*log10(2), Q18 */ + st_fx->tonality2_buf_fx[HANG_LEN_INIT - 1] = round_fx(L_shl(L_tmp, 11));/*14 */ + /* t2 = std( st->tonality2_buf, HANG_LEN_INIT ); */ + t2_fx = std_fx( st_fx->tonality2_buf_fx, HANG_LEN_INIT ); /*14 */ + + Copy( st_fx->tonality3_buf_fx + 1, st_fx->tonality3_buf_fx, HANG_LEN_INIT - 1 ); + /* st->tonality3_buf[HANG_LEN_INIT - 1] = 0.2f*(float)log10(tonality3); */ + exp = norm_l(tonality3); + tmp = Log2_norm_lc(L_shl(tonality3, exp));/*15 */ + exp = sub(30, add(exp, 16)); + L_tmp = Mpy_32_16(exp, tmp, 15783);/*19 //3945, 0.2*log10(2), Q18 */ + st_fx->tonality3_buf_fx[HANG_LEN_INIT - 1] = round_fx(L_shl(L_tmp, 11));/*14 */ + t3_fx = std_fx( st_fx->tonality3_buf_fx, HANG_LEN_INIT ); /*14 */ + + /* tL = 0.2f*(float)log10(st->lt_tonality); */ + exp = norm_l(st_fx->lt_tonality); + tmp = Log2_norm_lc(L_shl(st_fx->lt_tonality, exp));/*15 */ + exp = sub(30, add(exp, 16)); + L_tmp = Mpy_32_16(exp, tmp, 15783);/*19 //3945, 0.2*log10(2), Q18 */ + tL_fx = round_fx(L_shl(L_tmp, 11));/*14 */ + + /* calculate standard deviation of residual LP energy */ + Copy( st_fx->LPCErr_buf_fx + 1, st_fx->LPCErr_buf_fx, HANG_LEN_INIT - 1 ); + st_fx->LPCErr_buf_fx[HANG_LEN_INIT - 1] = LPCErr; + /* err = std( st->LPCErr_buf, HANG_LEN_INIT ); */ + err_fx = std_fx( st_fx->LPCErr_buf_fx, HANG_LEN_INIT ); + + cor_fx = s_max(sub(voi_fv, cor_map_sum_fv), 0);/*15 */ + dft_fx = abs_s(sub(st_fx->tonality2_buf_fx[HANG_LEN_INIT - 1], st_fx->tonality3_buf_fx[HANG_LEN_INIT - 1]));/*14 */ + + + /* state machine for strong music */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF ( (EQ_16(*sp_aud_decision1, 1))&&st_fx->lt_music_state_fx==0&&st_fx->lt_music_hangover_fx==0&& + (LT_16(t2_fx, 8847)) && (GT_16(t2_fx, 4260)) && (GT_16(t3_fx, 3604)) && (LT_16(tL_fx, 8847)) && (GT_16(tL_fx, 4260)) && (GT_16(err_fx, 8192)) ) + { + st_fx->lt_music_state_fx = 1; + move16(); + st_fx->lt_music_hangover_fx = 6; + move16(); + } + ELSE IF( EQ_16(st_fx->lt_music_state_fx, 1)&&st_fx->lt_music_hangover_fx==0&& + (LT_16(t2_fx, 5571) ) && (LT_16(t3_fx, 4260) ) && (LT_16(tL_fx, 7373) ) ) + { + st_fx->lt_music_state_fx = 0; + move16(); + st_fx->lt_music_hangover_fx = 6; + move16(); + } + + IF ( st_fx->lt_music_hangover_fx > 0 ) + { + st_fx->lt_music_hangover_fx = sub(st_fx->lt_music_hangover_fx,1); + } + + /* state machine for strong speech */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF ( (EQ_16(*sp_aud_decision1, 1))&&st_fx->lt_speech_state_fx==0&&st_fx->lt_speech_hangover_fx==0&& + (GT_16(cor_fx, 13107)) && (LT_16(dft_fx, 1638)) && GT_16(shr(voi_fv,1), add(cor_map_sum_fv, 1966)) && + (LT_16(t2_fx, shr(cor_fx, 1))) && (LT_16(t3_fx, shr(cor_fx, 1))) && (LT_16(tL_fx, shr(cor_fx, 1))) && + (LT_16(cor_map_sum_fv, cor_fx)) && (GT_16(voi_fv, cor_fx)) && (GT_16(voi_fv, 24903) ) ) + { + st_fx->lt_speech_state_fx = 1; + move16(); + st_fx->lt_speech_hangover_fx = 6; + move16(); + } + ELSE IF ( (EQ_16(st_fx->lt_speech_state_fx, 1))&&st_fx->lt_speech_hangover_fx==0&&(LT_16(cor_fx,13107))) + { + st_fx->lt_speech_state_fx = 0; + move16(); + st_fx->lt_speech_hangover_fx = 6; + move16(); + } + + IF ( st_fx->lt_speech_hangover_fx > 0) + { + st_fx->lt_speech_hangover_fx = sub(st_fx->lt_speech_hangover_fx,1); + } + + /* final decision */ + test(); + test(); + IF ( EQ_16(*sp_aud_decision1,1)&&EQ_16(st_fx->lt_speech_state_fx,1)) + { + /* strong speech - probably error in speech/music classification */ + *sp_aud_decision1 = 0; + move16(); + *sp_aud_decision2 = 0; + move16(); + } + ELSE IF ( *sp_aud_decision1 == 0 && EQ_16(st_fx->lt_speech_state_fx,1)) + { + /* strong music - probably error in speech/music classification */ + *sp_aud_decision1 = 0; + move16(); + *sp_aud_decision2 = 0; + move16(); + } + + /* update the buffer of past decisions */ + st_fx->lt_old_mode[2] = *sp_aud_decision1; + move16(); + + return; +} + + +static void detect_sparseness_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ + Word16 *sp_aud_decision1, /* i/o: 1st stage speech/music decision */ + Word16 *sp_aud_decision2, /* i/o: 2nd stage speech/music decision */ + const Word16 voi_fv /* i : scaled voicing feature */ +) +{ + Word16 sum, sumh; + Word32 L_tmp,L_tmp1; + Word16 tmp, tmp1; + Word16 S1[128]; + Word16 i,j; + Word16 hb_sp_high_flag = 0; + Word16 lb_sp_high_flag = 0; + Word16 sparse; + Word16 tmp_buf[4]; + Word16 Mlpe=0, Mv=0, Msp; + + Copy(st_fx->lgBin_E_fx, S1, 128); + + L_tmp = L_deposit_l(0); + FOR (i = 0; i < 80; i++) + { + if (S1[i] < 0) + { + S1[i] = 0; + move16(); /* Q7 */ + } + L_tmp = L_add(L_tmp, L_deposit_l(S1[i])); + } + + L_tmp1 = L_deposit_l(0); + FOR (i = 80; i < 128; i++) + { + if (S1[i] < 0) + { + S1[i] = 0; + move16(); + } + L_tmp1 = L_add(L_tmp1, L_deposit_l(S1[i])); + } + + sumh = extract_l(L_shr(L_tmp1, 7)); /* Q0 */ + sum = add(extract_l(L_shr(L_tmp, 7)), sumh); /* Q0 */ + + /* order spectral from max to min */ + order_spectrum_fx(S1, 128); + + /* calculate spectral sparseness in the range 0 - 6.4 kHz */ + j = 0; + move16(); + L_tmp = 0; + move16(); + L_tmp1 = L_deposit_l(mult(sum, 24576)); + FOR (i = 0; i < 128; i++) + { + L_tmp = L_add(L_tmp, L_deposit_l(S1[i])); + IF (GT_32(L_shr(L_tmp, 7), L_tmp1)) + { + j = i; + move16(); + BREAK; + } + } + + FOR (i = 0; i < HANG_LEN_INIT-1; i++) + { + st_fx->sparse_buf_fx[i] = st_fx->sparse_buf_fx[i+1]; + move16(); + } + + sparse = j; + move16(); + st_fx->sparse_buf_fx[i] = sparse; + move16(); + + IF (EQ_16(st_fx->bwidth_fx, WB)) + { + Msp = 0; + move16(); + FOR (i = 0; i < 8; i++) + { + Msp = add(Msp, st_fx->sparse_buf_fx[i]); + } + Msp = shl(Msp, 5); /* Q8 */ + + /* find long-term smoothed sparseness */ + IF (st_fx->last_vad_spa_fx == 0 ) + { + set16_fx( &st_fx->sparse_buf_fx[0], sparse, HANG_LEN_INIT-1 ); + st_fx->LT_sparse_fx = sparse; + move16(); + } + ELSE + { + set16_fx(tmp_buf, 0, 4); + + FOR (i = 0; i < HANG_LEN_INIT; i++) + { + FOR (j = 0; j < 4; j++) + { + IF (GT_16(st_fx->sparse_buf_fx[i], tmp_buf[j])) + { + Copy(&tmp_buf[j], &tmp_buf[j+1], sub(3, j)); + tmp_buf[j] = st_fx->sparse_buf_fx[i]; + move16(); + BREAK; + } + } + } + + /* ftmp = 0.25f*(HANG_LEN_INIT*Msp - sum_f(tmp_buf, 4)) - st->LT_sparse; */ + tmp = shl(sum16_fx(tmp_buf, 4), 5); + tmp = shl(sub(Msp, tmp), 1); + tmp = sub(tmp, st_fx->LT_sparse_fx); + + st_fx->LT_sparse_fx = add(st_fx->LT_sparse_fx, shr(tmp, 2)); /* Q8 */ + } + + /* find high-band sparseness */ + Copy(st_fx->lgBin_E_fx+80, S1, 48); + + order_spectrum_fx(S1, 48); + + FOR (i = 0; i < HANG_LEN_INIT-1; i++) + { + st_fx->hf_spar_buf_fx[i] = st_fx->hf_spar_buf_fx[i+1]; + move16(); + } + + /* st_fx->hf_spar_buf_fx[i] = sum_f(S1, 5)/sumh; */ + L_tmp = L_deposit_l(0); + FOR (i = 0; i < 5; i++) + { + if (S1[i] < 0) + { + S1[i] = 0; + move16(); + } + + L_tmp = L_add(L_tmp, S1[i]); + } + + tmp = extract_l(L_shr(L_tmp, 7)); + IF (tmp == 0) + { + st_fx->hf_spar_buf_fx[HANG_LEN_INIT-1] = 0; + move16(); + } + ELSE + { + st_fx->hf_spar_buf_fx[HANG_LEN_INIT-1] = div_s(tmp, sumh); + } + + tmp = 0; + move16(); + FOR (i = 0; i < 8; i++) + { + tmp = add(tmp, shr(st_fx->hf_spar_buf_fx[i], 3)); + } + IF (GT_16(tmp, 6554)) + { + hb_sp_high_flag = 1; + move16(); + } + + /* find low-band sparseness */ + Copy(st_fx->lgBin_E_fx, S1, 60); + + order_spectrum_fx(S1, 60); + L_tmp = L_deposit_l(0); + L_tmp1 = L_deposit_l(0); + FOR (i = 0; i < 5; i++) + { + if (S1[i] < 0) + { + S1[i] = 0; + move16(); + } + + L_tmp = L_add(L_tmp, S1[i]); + } + + FOR (; i < 60; i++) + { + if (S1[i] < 0) + { + S1[i] = 0; + move16(); + } + + L_tmp1 = L_add(L_tmp1, S1[i]); + } + + /* if ( sum_f(S1, 5)/sum_f(S1,60) > 0.18f ) */ + tmp = extract_l(L_shr(L_tmp, 7)); + IF (tmp != 0) + { + tmp = div_s(tmp, add(tmp, extract_l(L_shr(L_tmp1, 7)))); + if (GT_16(tmp, 5898)) + { + lb_sp_high_flag = 1; + move16(); + } + } + + /* find smoothed linear prediction efficiency */ + FOR (i = 0; i < 7; i++) + { + st_fx->lpe_buf_fx[i] = st_fx->lpe_buf_fx[i+1]; + move16(); + } + + st_fx->lpe_buf_fx[i] = st_fx->past_epsP2_fx; + move16(); + Mlpe = 0; + move16(); + FOR (i = 0; i < 8; i++) + { + Mlpe = add(Mlpe, shr(st_fx->lpe_buf_fx[i], 3)); + } + + /* find smoothed voicing */ + FOR (i = 0; i < HANG_LEN_INIT-1; i++) + { + st_fx->voicing_buf_fx[i] = st_fx->voicing_buf_fx[i+1]; + move16(); + } + + st_fx->voicing_buf_fx[i] = voi_fv; + move16(); + Mv = 0; + move16(); + FOR (i = 0; i < 8; i++) + { + Mv = add(Mv, shr(st_fx->voicing_buf_fx[i], 3)); + } + } + + /* avoid using LR-MDCT on sparse spectra */ + IF (EQ_16(*sp_aud_decision1, 1)) + { + tmp = 91; + move16(); + if (EQ_16(st_fx->bwidth_fx, WB)) + { + tmp = 90; + } + + IF (GT_16(sparse, tmp)) + { + *sp_aud_decision1 = 0; + move16(); + *sp_aud_decision2 = 1; + move16(); + st_fx->gsc_hangover_fx = 1; + move16(); + } + ELSE IF (EQ_16(st_fx->gsc_hangover_fx, 1)) + { + IF (GT_16(sparse, 85)) + { + *sp_aud_decision1 = 0; + move16(); + *sp_aud_decision2 = 1; + move16(); + } + ELSE + { + tmp = 0; + move16(); + FOR (i=0; igsc_cnt_fx; i++) + { + tmp = add(tmp, st_fx->sparse_buf_fx[HANG_LEN_INIT-1-st_fx->gsc_cnt_fx+i]); + } + tmp1 = div_s(1, st_fx->gsc_cnt_fx); + tmp = mult(tmp, tmp1); + + IF (LT_16(abs_s(sub(sparse, tmp)), 7)) + { + *sp_aud_decision1 = 0; + move16(); + *sp_aud_decision2 = 1; + move16(); + } + } + } + + IF (EQ_16(st_fx->bwidth_fx, WB)) + { + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF (GT_16(st_fx->LT_sparse_fx, 15360)&>_16(sparse,50)&<_16(Mlpe,-1331)&>_16(Mv,27853)&& + lb_sp_high_flag == 0 && ((hb_sp_high_flag == 0 && GT_16(sumh, mult_r(4915, sum))) || LE_16(sumh, mult_r(4915, sum)))) + { + *sp_aud_decision1 = 0; + move16(); + *sp_aud_decision2 = 1; + move16(); + st_fx->gsc_hangover_fx = 1; + move16(); + } + ELSE IF (EQ_16(st_fx->gsc_hangover_fx, 1)&&!(*sp_aud_decision1==0&&*sp_aud_decision2==1)) + { + IF (LT_16(abs_s(sub(sparse, mean_fx(&st_fx->sparse_buf_fx[HANG_LEN_INIT-1-st_fx->gsc_cnt_fx], st_fx->gsc_cnt_fx))), 7)) + { + *sp_aud_decision1 = 0; + move16(); + *sp_aud_decision2 = 1; + move16(); + } + } + } + } + + /* update the counter of consecutive GSC frames with sparse spectrum */ + test(); + IF (*sp_aud_decision1 == 0 && EQ_16(*sp_aud_decision2, 1)) + { + st_fx->gsc_cnt_fx = add(st_fx->gsc_cnt_fx, 1); + IF (GT_16(st_fx->gsc_cnt_fx, 7)) + { + st_fx->gsc_cnt_fx = 7; + move16(); + } + } + ELSE + { + st_fx->gsc_cnt_fx = 0; + move16(); + st_fx->gsc_hangover_fx = 0; + move16(); + } + + st_fx->last_vad_spa_fx = localVAD_HE_SAD; + move16(); + + return; +} + + +static void order_spectrum_fx( + Word16 *vec, + Word16 len +) +{ + Word16 i, j, end, end_1, len_2, tmp; + Word16 smax, smin; + Word16 imax, imin; + + len_2 = shr(len, 1); + FOR(i = 0; i < len_2; i++) + { + imax = i; + move16(); + imin = i; + move16(); + smax = vec[i]; + move16(); + smin = vec[i]; + move16(); + end = sub(len, i); + FOR(j = i; j < end; j++) + { + IF(GT_16(vec[j], smax)) + { + smax = vec[j]; + move16(); + imax = j; + move16(); + } + ELSE + { + IF(LT_16(vec[j], smin) ) + { + smin = vec[j]; + move16(); + imin = j; + move16(); + } + } + } + + tmp = vec[i]; + move16(); + vec[i] = smax; + move16(); + vec[imax] = tmp; + move16(); + + IF(EQ_16(imin, i)) + { + imin = imax; + move16(); + } + + end_1 = sub(end, 1); + tmp = vec[end_1]; + move16(); + vec[end_1] = smin; + move16(); + vec[imin] = tmp; + move16(); + } +} + diff --git a/lib_enc/stat_enc_fx.h b/lib_enc/stat_enc_fx.h new file mode 100644 index 0000000..aaea555 --- /dev/null +++ b/lib_enc/stat_enc_fx.h @@ -0,0 +1,1325 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#ifndef STAT_ENC_FX_H +#define STAT_ENC_FX_H + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "stat_dec_fx.h" /* Compilation switches */ + + +/*------------------------------------------------------------------------------------------* + * Indice + *------------------------------------------------------------------------------------------*/ + +typedef struct +{ + UWord16 value; /* value of the quantized indice */ + Word16 nb_bits; /* number of bits used for the quantization of the indice */ +} Indice_fx; + +typedef struct +{ + Word32 r; + Word32 i; +} complex_32; +typedef struct +{ + Word16 r; + Word16 i; +} complex_16; +typedef struct +{ + Word16 s16Exp; + Word32 s32Mantissa; +} T_VAD_EXP; + +typedef struct +{ + Word16 bw_index; /* index of band width */ + + /* feature */ + Word16 sp_center[SP_CENTER_NUM]; /* spectral center*/ + Word16 ltd_stable_rate[STABLE_NUM]; /* time-domain stable rate*/ + Word16 sfm[SFM_NUM]; /* spectral flatness*/ + Word16 f_tonality_rate[TONA_NUM]; /* tonality rate*/ + Word16 pre_spec_low_dif[PRE_SPEC_DIF_NUM]; /* low frequency spectral different*/ + Word32 frames_power_32[POWER_NUM]; /* energy of several frames*/ + Word32 frame_sb_energy[BG_ENG_NUM]; /* energy of sub-band divided non-uniformly*/ + Word32 t_bg_energy; /* time background energy of several frames*/ + T_VAD_EXP t_bg_energy_sum; /* number of time background energy*/ + Word16 tbg_energy_count; /* sum of time background energy of several frames*/ + Word16 bg_update_count; /* time of background update*/ + Word32 frame_energy_smooth; /* smoothed energy of several frames*/ + + /************************************************************************/ + /* history parameters */ + /************************************************************************/ + Word32 smooth_spec_amp[SPEC_AMP_NUM]; /* smoothed spectral amplitude*/ + Word32 pre_snr[PRE_SNR_NUM]; /* previous time SNR*/ + Word32 sb_bg_energy[BG_ENG_NUM]; /* sub-band background energy*/ + Word16 continuous_noise_num; /* time of continuous noise frames*/ + Word16 continuous_speech_num; /* time of continuous speech frames*/ + Word16 continuous_speech_num2; /* time 2 of continuous speech frames*/ + Word32 fg_energy_est_start; /* flag by that indicate whether if estimate energy*/ + Word16 speech_flag; /* residual number of hangover 1 */ + Word32 lt_noise_sp_center_diff_counter; /* number of the member lt_noise_sp_center_diff_sum*/ + Word32 fg_energy; /* foreground energy sum */ + Word32 bg_energy; /* background energy sum */ + Word32 lt_bg_highf_eng; /* average of long time high frequency energy*/ + Word32 lt_noise_sp_center_diff_sum; /* different sum of long time noise sp_center*/ + Word32 lt_snr_org; /* original long time SNR*/ + Word32 l_speech_snr; /* sum of snr's of active frames*/ + Word32 l_silence_snr; /* sum of snr's of non active frames*/ + Word32 l_speech_snr_count; /* number of active frames*/ + Word32 l_silence_snr_count; /* number of non active frames*/ + Word32 lf_snr_smooth; /* smoothed lf_snr*/ + Word16 frameloop; /* number of frame*/ + Word16 lt_noise_sp_center0; /* long time noise sp_center0*/ + Word16 lt_noise_sp_center3; /* long time noise sp_center3*/ + Word16 music_background_rate; /* music background rate*/ + Word16 tonality_rate3; /* tonality rate*/ + Word16 bg_energy_count; /* number of the background energy frame */ + Word16 fg_energy_count; /* number of the foreground energy frame */ + Word16 Q_frames_power_32; /* the Scaling of frames_power_fix32*/ + Word16 scale_spec_low_dif; /* the Scaling of spec_low_dif*/ + Word16 sb_bg_energy_scale; /* the Scaling of sb_bg_energy*/ + Word16 frame_sb_energy_scale; /* the Scaling of frame_sb_energy*/ + Word16 scale_t_bg_energy; /* the Scaling of t_bg_energy*/ + Word16 frame_energy_smooth_scale; /* the Scaling of frame_energy_smooth*/ + Word16 bg_energy_scale; /* the Scaling of bg_energy*/ + Word16 fg_energy_scale; /* the Scaling of fg_energy*/ + Word16 updateNumWithSnr; /* the number of the background update with SNR*/ + Word16 update_count; /* the number of the background update*/ + Word16 warm_hang_num; /* the number of hangover for warm up*/ + Word16 vad_flag_for_bk_update; +} T_CldfbVadState; + +/*ari.h*/ +typedef struct +{ + Word32 low,high; + Word16 vobf; +} TastatEnc; + +/*---------------------------------------------------------------* + * IGF * + *---------------------------------------------------------------*/ +/* IGFSCFEncoder.h */ +typedef struct +{ + Word16 ptrBitIndex; + Word16 bitCount; + Word16 prev[64]; /* no more than 64 SCFs for the IGF energy envelope of one block, short or long */ + Word16 prevSave[64]; + Word16 scfCountLongBlock; + Word16 t; + Word16 tSave; + Word16 context_saved; + const Word16 *cf_se00; + const Word16 *cf_se01; + Word16 cf_off_se01; + const Word16 *cf_se02; + const Word16 *cf_off_se02; + const Word16 *cf_se10; + Word16 cf_off_se10; + const Word16 *cf_se11; + const Word16 *cf_off_se11; + TastatEnc acState; +} IGFSCFENC_INSTANCE, *IGFSCFENC_INSTANCE_HANDLE; + +/* IGFEnc.h */ +typedef struct igf_enc_private_data_struct +{ + IGF_INFO igfInfo; + Word16 igfScfQuantized[IGF_MAX_SFB]; + IGFSCFENC_INSTANCE hIGFSCFArithEnc; + + + /*** whitening ***/ + Word16 igfCurrWhiteningLevel[IGF_MAX_TILES]; + Word16 igfPrevWhiteningLevel[IGF_MAX_TILES]; + + Word32 prevSFM_FIR[IGF_MAX_TILES]; /* 15Q16 */ + Word16 prevSFM_IIR[IGF_MAX_TILES]; /* 2Q13 */ + Word16 wasTransient; /* 15Q0 */ + + UWord8 igfBitstream[BITBUFSIZE/8]; + Word16 igfBitstreamBits; + +} IGF_ENC_PRIVATE_DATA, *IGF_ENC_PRIVATE_DATA_HANDLE; + +typedef struct igf_enc_instance_struct +{ + IGF_ENC_PRIVATE_DATA igfData; + Word32 infoSamplingRate; + Word16 infoStartFrequency; + Word16 infoStopFrequency; + Word16 infoStartLine; + Word16 infoStopLine; + Word16 infoTotalBitsWritten; + Word16 infoTotalBitsPerFrameWritten; + Word16 flatteningTrigger; + Word32 spec_be_igf[N_MAX_TCX-IGF_START_MN]; /* copy of MDCT spectrum */ + Word16 spec_be_igf_e; /* exponent of copy of MDCT spectrum */ + Word16 tns_predictionGain; +} IGF_ENC_INSTANCE, *IGF_ENC_INSTANCE_HANDLE; + + + +typedef struct +{ + Word16 nbits; /* number of bits used by ACELP or TCX */ + + /* signal memory */ + Word16 syn[1+M]; /* Synthesis memory (non-pe) */ + /*Word16 wsyn;*/ /* Weighted synthesis memory */ + Word16 mem_syn[M]; /* ACELP synthesis memory (pe) before post-proc */ + Word16 mem_syn2[M]; /* ACELP synthesis memory (pe) after post-proc */ + Word16 mem_w0; /* weighting filter memory */ + Word16 tilt_code; + Word16 mem_syn_r[L_SYN_MEM]; /* ACELP synthesis memory for 1.25ms */ + Word16 mem_syn3[M]; + + /* ACELP memory */ + Word16 old_exc[L_EXC_MEM]; /* ACELP exc memory (Aq) */ + + /* TCX memory */ + Word16 Txnq[L_FRAME32k/2+64]; /* Q target (overlap or ACELP+ZIR, use Aq) */ + Word16 *acelp_zir; + Word16 tcx_target_bits_fac; + + Word32 gc_threshold; /* exponent = 15, 15Q16 */ + +} LPD_state; + + +typedef struct PLC_ENC_EVS +{ + + Word16 nBits; /* number of bits */ + Word16 enableGplc; + + Word16 Q_new; + Word16 Q_exp; + + Word16 T0_4th; + Word16 T0; + Word16 old_exc_Qold[8]; /* ACELP exc memory (Aq) */ + Word8 calcOnlylsf; + Word16 pit_min; + Word16 pit_max; + + Word16 lsfoldbfi0_14Q1[M]; /* Previous frame LSF */ + Word16 lsfoldbfi1_14Q1[M]; /* Past previous frame LSF */ + Word16 lsfold_14Q1[M]; /* old lsf (frequency domain) */ + Word16 lspold_Q15[M]; /* old lsp (immittance spectral pairs) */ + + Word16 mem_MA_14Q1[M]; + Word16 mem_AR[M]; + Word16 lsf_adaptive_mean_14Q1[M]; /* Mean isf for bfi cases */ + Word16 stab_fac_Q15; + + + /* For TCX case */ + + LPD_state *LPDmem; + Word16 lsf_con[M]; + Word16 last_lsf_ref[M]; + Word16 last_lsf_con[M]; +} PLC_ENC_EVS, *HANDLE_PLC_ENC_EVS; + + +/*****************************************/ +/* MODE2 STAT ENC */ +/*****************************************/ + +/*transient_detection.h*/ +/** Delay buffer. + * Used to buffer input samples and to define the subblock size of a transient detector. + */ +typedef struct +{ + /** Subblock size of a transient detector that uses this delay buffer. */ + Word16 nSubblockSize; + /** Delay buffer */ + Word16 buffer[L_FRAME48k/NSUBBLOCKS]; + /** Size of the delay buffer in use. Maximum delay from all users of this buffer. */ + Word16 nDelay; +} DelayBuffer; + +/** Subblock energies. + * Holds subblock energies and recursively accumulated energies. + * Also buffers the energies. + */ +typedef struct +{ + /** Delay buffer. */ + DelayBuffer * pDelayBuffer; + /** Subblock energies with a delay buffering. */ + Word32 subblockNrg[NSUBBLOCKS+MAX_TD_DELAY]; + /** Recursively accumulated subblock energies with a delay buffering. + At index i the value corresponds to the accumulated subblock energy up to i-1, + including block i-1 and without block i. */ + Word32 accSubblockNrg[NSUBBLOCKS+MAX_TD_DELAY+1]; + /** subblockNrgChange[i] = max(subblockNrg[i]/subblockNrg[i-1], subblockNrg[i-1]/subblockNrg[i]) */ + Word16 subblockNrgChange[NSUBBLOCKS+MAX_TD_DELAY]; + /** Size of the delay buffer in use, as number of subblocks. Maximum delay from all users of this buffer. */ + Word16 nDelay; + /* Delay of the input (modulo pDelayBuffer->nSubblockSize), nPartialDelay <= pDelayBuffer->nDelay. */ + Word16 nPartialDelay; + + /** Decay factor for the recursive accumulation */ + Word16 facAccSubblockNrg; + + /** High-pass filter states (delay line) */ + Word16 firState1; + Word16 firState2; + +} SubblockEnergies; + +struct TransientDetector; + +/** Attack detection function. + * Definition of a function used for checking the presence of an attack, given subblock energies, accumulated subblock energies and a threshold. + * @param pSubblockNrg Subblock energies. + * @param pAccSubblockNrg Recursively accumulated subblock energies. + At index i the value corresponds to the accumulated subblock energy up to i-1, + including block i-1 and without block i. + * @param nSubblocks Number of subblocks available (those with an index >= 0). Subblocks from 0 to NSUBBLOCKS-1 correspond to the current frame. + * @param nPastSubblocks Number of past subblocks available (those with a negative index). + * @param attackRatioThreshold Attack ratio threshold. + * @param pbIsAttackPresent Pointer to an output variable that will be set to TRUE if an attack is found, otherwise set to FALSE. + * @param pAttackIndex Pointer to an output variable that will hold an attack position. + */ +typedef void (* TCheckSubblocksForAttack)(Word32 const * pSubblockNrg, Word32 const * pAccSubblockNrg, Word16 nSubblocks, Word16 nPastSubblocks, Word16 attackRatioThreshold, Word16 * pbIsAttackPresent, Word16 * pAttackIndex); + +/** Transient detector. + */ +typedef struct TransientDetector +{ + /** Subblock energies used in this transient detector. */ + SubblockEnergies * pSubblockEnergies; + /* Delay of the transient detector in number of subblocks, nDelay <= pSubblockEnergies->nDelay. */ + Word16 nDelay; + /** Number of subblocks to check for transients. */ + Word16 nSubblocksToCheck; + /** Function for checking a presence of an attack. */ + TCheckSubblocksForAttack CheckSubblocksForAttack; + /** Attack ratio threshold. */ + Word16 attackRatioThreshold; + /** True when an attack was detected. */ + Word16 bIsAttackPresent; + /** The index of an attack. */ + Word16 attackIndex; + +} TransientDetector; + + +/** Transient detection. + * Holds all transient detectors and buffers used by them. + */ +typedef struct TransientDetection +{ + /** Transient detector. */ + TransientDetector transientDetector; + /** Delay buffer used by the transient detectors. */ + DelayBuffer delayBuffer; + /** Subblock energies used by the transient detector. */ + SubblockEnergies subblockEnergies; +} TransientDetection; + +/* Arrays and variables specific to encoder */ +typedef struct +{ + HANDLE_FD_CNG_COM hFdCngCom; + + Word32 msPeriodog[NPART]; /* Periodogram */ + Word16 msPeriodog_exp; /* Common exponent for fft and cldfb energies */ + Word16 msPeriodog_exp_fft; + Word16 msPeriodog_exp_cldfb; + Word32 msBminWin[NPART]; + Word32 msBminSubWin[NPART]; + Word16 msPsd[NPART]; /* Power Spectral Density estimate (i.e., smoothed periodogram) */ + Word32 msAlpha[NPART]; /* Optimal smoothing parameter */ + Word32 msMinBuf[MSNUMSUBFR*NPART]; /* Buffer of minima */ + Word32 msCurrentMinOut[NPART]; + Word32 msCurrentMin[NPART]; + Word32 msCurrentMinSubWindow[NPART]; + Word16 msLocalMinFlag[NPART]; + Word16 msNewMinFlag[NPART]; + Word16 msPsdFirstMoment[NPART]; + Word32 msPsdSecondMoment[NPART]; + Word16 msNoiseFloor[NPART]; /* Estimated noise floor */ + Word32 msNoiseEst[NPART]; /* Estimated noise level */ + Word16 msNoiseEst_exp; + Word32 energy_ho[NPART]; + Word16 energy_ho_exp; + Word32 msNoiseEst_old[NPART]; + Word16 msNoiseEst_old_exp; + + Word16 msPeriodogBuf[MSBUFLEN*NPART]; + Word16 msPeriodogBufPtr; + + Word16 stopFFTbinDec; + Word16 startBandDec; + Word16 stopBandDec; + Word16 npartDec; + Word16 midbandDec[NPART]; + Word16 nFFTpartDec; + Word16 partDec[NPART]; + + Word16 msLogPeriodog[NPART]; + Word16 msLogNoiseEst[NPART]; +} +FD_CNG_ENC; +typedef FD_CNG_ENC *HANDLE_FD_CNG_ENC; + + + +typedef struct Encoder_State_fx +{ + + /*----------------------------------------------------------------------------------* + * Common parameters + *----------------------------------------------------------------------------------*/ + + Word16 codec_mode; /* MODE1 or MODE2 */ + Word16 last_codec_mode; /* Previous Codec Mode*/ + Word16 last_codec_mode_cng; /* Codec Mode of the last inactive frame*/ + Word16 mdct_sw_enable; /* MDCT switching enable flag */ + Word16 mdct_sw; /* MDCT switching indicator */ + Word16 prev_hi_ener; + Word16 prev_hi_sparse; + Word16 clas_sec_old_fx; /* MDCT classifier secondary decision memory */ + Word16 clas_final_old_fx; /* MDCT classifier final decision memory */ + Word32 last_gain1; + Word32 last_gain2; + Word16 last_enerBuffer_exp; + Word16 nb_bits_tot_fx; /* total number of bits already written */ + Word16 next_bit_pos_fx; /* position of the next bit to be written in the bitstream */ + Indice_fx *ind_list_fx; /* list of indices */ + Word16 next_ind_fx; /* pointer to the next empty slot in the list of indices */ + Word16 last_ind_fx; /* last written indice */ + Word16 bitstreamformat; /* Bitstream format flag (G.192/MIME) */ + + Word32 input_Fs_fx; /* input signal sampling frequency in Hz */ + Word32 total_brate_fx; /* total bitrate in kbps of the codec */ + Word32 last_total_brate_fx; /* total bitrate in kbps of the codec */ + Word32 last_total_brate_cng_fx; /* total bitrate in kbps of the last inactive frame */ + Word16 core_fx; /* core (ACELP_CORE, TCX_20_CORE, TCX_10_CORE, HQ_CORE, AMR_WB_CORE) */ + Word32 core_brate_fx; /* core bitrate */ + Word32 last_core_brate_fx; /* previous frame core bitrate */ + Word16 input_frame_fx; /* Frame lenght (function of input_Fs) */ + Word16 extl_fx; /* extension layer */ + Word16 last_extl_fx; /* previous extension layer */ + Word32 extl_brate_fx; /* extension layer bitrate */ + Word16 input_bwidth_fx; /* input signal bandwidth */ + Word16 last_input_bwidth_fx; /* input signal bandwidth in the previous frame */ + Word16 bwidth_fx; /* encoded bandwidth NB, WB, SWB or FB */ + Word16 max_bwidth_fx; /* maximum encoded bandwidth */ + Word16 last_bwidth_fx; /* input signal bandwidth in the previous frame */ + Word16 last_bwidth_cng_fx; /* input signal bandwidth in the previous inactive frame */ + Word16 L_frame_fx; /* ACELP core internal frame length */ + Word16 Opt_AMR_WB_fx; /* flag indicating AMR-WB IO mode */ + Word16 Opt_DTX_ON_fx; /* flag indicating DTX operation */ + Word16 cng_type_fx; /* flag indicating LP or CLDFB based SID/CNG */ + Word16 active_fr_cnt_fx; /* counter of active frames */ + Word16 Opt_SC_VBR_fx; /* flag indicating SC-VBR mode */ + Word16 last_Opt_SC_VBR_fx; /* flag indicating SC-VBR mode in the last frame */ + Word16 lp_cng_mode2; + + /*----------------------------------------------------------------------------------* + * ACELP core parameters + *----------------------------------------------------------------------------------*/ + + Word16 clas_fx; /* current frame clas */ + Word16 last_clas_fx; /* previous frame signal classification */ + Word32 Bin_E_fx[L_FFT]; /* Q_new + Q_SCALE -2 per bin energy of two frames */ + Word32 Bin_E_old_fx[L_FFT/2]; /* per bin energy of old 2nd frames */ + Word16 lsp_old1_fx[M]; /* old unquantized LSP vector at the end of the frame */ + Word16 lsf_old1_fx[M]; /* old LSF vector at the end of the frame */ + Word16 lsp_old_fx[M]; /* old LSP vector at the end of the frame */ + Word16 lsf_old_fx[M]; /* old LSF vector at the end of the frame */ + Word16 lsp_old16k_fx[M]; /* old LSP vector at the end of the frame @16kHz */ + Word16 lspold_enc_fx[M]; /* old LSP vector at the end of the frame @16kHz */ + Word16 pstreaklen_fx; /* LSF quantizer */ + Word16 streaklimit_fx; /* LSF quantizer */ + Word32 offset_scale1_fx[MAX_NO_MODES+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure 1st 8-dim subvector*/ + Word32 offset_scale2_fx[MAX_NO_MODES+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure 2nd 8-dim subvector*/ + Word32 offset_scale1_p_fx[MAX_NO_MODES_p+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure, pred. case, 1st 8-dim subvector*/ + Word32 offset_scale2_p_fx[MAX_NO_MODES_p+1][MAX_NO_SCALES+1]; /* offsets for LSF LVQ structure, pred. case, 2nd 8-dim subvector*/ + Word16 no_scales_fx[MAX_NO_MODES][2]; /* LSF LVQ structure Q0*/ + Word16 no_scales_p_fx[MAX_NO_MODES_p][2]; /* LSF LVQ structure Q0*/ + Word16 stab_fac_fx; /* LSF stability factor */ + Word16 mem_decim_fx[2*L_FILT_MAX]; /* decimation filter memory */ + Word16 mem_deemph_fx; /* deemphasis filter memory */ + Word16 mem_preemph_fx; /* preemphasis filter memory */ + Word32 mem_hp20_in_fx[5]; /* HP filter memory for AMR-WB IO */ + Word16 old_inp_12k8_fx[L_INP_MEM]; /* memory of input signal at 12.8kHz */ + Word16 old_wsp_fx[L_WSP_MEM]; /* old weighted signal vector */ + /*Word16 old_exc_fx[L_EXC_MEM];*/ /* old excitation vector */ + Word16 old_wsp2_fx[(L_WSP_MEM - L_INTERPOL)/OPL_DECIM]; /* old decimated weighted signal vector qwsp */ + Word32 fr_bands1_fx[NB_BANDS]; /* Q_new + Q_SCALE spectrum per critical bands of the previous frame */ + Word32 fr_bands2_fx[NB_BANDS]; /* Q_new + Q_SCALE spectrum per critical bands 2 frames ago */ + Word16 mem_wsp_fx; /* weighted signal vector memory */ + Word16 mem_decim2_fx[3]; /* weighted signal decimation filter memory qwsp */ + Word16 mem_syn1_fx[M]; /* synthesis filter memory (for core switching and FD BWE) */ + + Word16 clip_var_fx[6]; + Word16 past_qua_en_fx[4]; + Word16 mem_AR_fx[M]; /* AR memory of LSF quantizer (past quantized LSFs without mean) */ + Word16 mem_MA_fx[M]; /* MA memory of LSF quantizer (past quantized residual) (used also in AMR-WB IO mode) */ + Word16 mCb1_fx; /* LSF quantizer - counter of stationary frames after a transition frame */ + Word16 coder_type_raw_fx; + Word16 last_coder_type_raw_fx; /* raw last_coder_type (coming from the sigal classification) */ + Word16 last_coder_type_fx; /*Q0 previous coding type */ + Word16 ini_frame_fx; /* initialization frames counter */ + Word16 old_thres_fx; /* normalized correlation weighting in open-loop pitch Q15 */ + Word16 old_corr_fx; /* normalized correlation in previous frame (mean value) Q15 */ + Word16 old_pitch; /* previous pitch for open-loop pitch search Q0 */ + Word16 delta_pit_fx; /* open-loop pitch extrapolation correction Q0 */ + Word32 ee_old_fx; + Word16 min_band_fx; /* Q0 minimum critical band of useful bandwidth */ + Word16 max_band_fx; /* Q0 maximum critical band of useful bandwidth */ + Word16 tc_cnt_fx; /* TC frame counter */ + Word16 audio_frame_cnt_fx; /* Counter of relative presence of audio frames */ + Word32 old_dE1_fx; /* Maximum energy increase in previous frame */ + Word16 old_ind_deltaMax_fx; /* Index of the sub-subframe of maximum energy in previous frame */ + Word32 old_enr_ssf_fx[2*NB_SSF]; /* Maxima of energies per sub-subframes of previous frame */ + Word16 spike_hyst_fx; /* Hysteresis to prevent UC after sharp energy spike */ + Word16 music_hysteresis_fx; /* Counter of frames after AUDIO coding mode to prevent UC */ + Word16 last_harm_flag_acelp_fx; /* harmonicity flag for ACELP @32kbps rate */ + Word16 old_Aq_12_8_fx[M+1]; /* Q12 old Aq[] for core switching */ + Word16 old_Es_pred_fx; /* Q8 old Es_pred for core switching */ + Word16 high_stable_cor_fx; /* flag for stable high correlation */ + + Word16 seed_tcx_fx ; /* AC mode (GSC) - seed for noise fill*/ + Word16 cor_strong_limit_fx; /* AC mode (GSC) - Indicator about high spectral correlation per band */ + Word16 GSC_noisy_speech_fx; /* AC mode (GSC) - flag to indicate GSC on SWB noisy speech */ + Word16 mem_last_pit_band_fx; /* AC mode (GSC) - memory of the last band where pitch contribution was significant */ + Word16 mem_w0_tmp_fx; + Word16 mem_syn_tmp_fx[M]; + Word16 var_cor_t_fx[VAR_COR_LEN]; + Word16 mid_dyn_fx; /* AC mode (GSC) - signal dynamic */ + Word16 noise_lev_fx; /* AC mode (GSC) - Q0 noise level */ + Word16 past_dyn_dec_fx; /* AC mode (GSC) - Past noise level decision */ + Word32 Last_frame_ener_fx; /* AC mode (GSC) - Last frame energy */ + Word16 pit_exc_hangover; /* AC mode (GSC) - Hangover for the time contribution switching*/ + + Word16 last_exc_dct_in_fx[L_FRAME]; /* AC mode (GSC) - previous exciation */ + Word16 last_bitallocation_band_fx[6]; /* AC mode (GSC) - previous bit allocation of each band */ + + Word32 past_PS_fx[HIGHEST_FBIN-LOWEST_FBIN]; + Word16 past_ps_diff_fx; + Word16 past_epsP2_fx; + Word16 inact_cnt_fx; + Word16 wdrop_fx; + Word16 wdlp_0_95_sp_fx; + Word16 sp_mus_state_fx; + Word16 past_dec_fx[HANG_LEN-1]; + Word16 past_dlp_fx[HANG_LEN-1]; /* Speech/music classifier - buffer of past non-binary decisions */ + Word16 last_lsp_fx[M_LSP_SPMUS]; + Word16 last_cor_map_sum_fx; + Word16 last_non_sta_fx; + Word16 past_log_enr_fx[NB_BANDS_SPMUS]; /* Speech/music classifier - last average per-band log energy used for non_staX */ + + Word16 mold_corr_fx; + Word16 lt_gpitch_fx; /*Q15 */ + Word16 mean_avr_dyn_fx; /* Q7 Speech/music classifier - long term average dynamic */ + Word16 last_sw_dyn_fx; /* Q7 Speech/music classifier - last dynamic */ + Word16 lt_dec_thres_fx; /* Speech/music classifier - Long term speech/music thresold values */ + Word16 ener_RAT_fx; /* Q15 Speech/music classifier - LF/to total energy ratio */ + Word16 lgBin_E_fx[L_FFT/2]; /* Q8 per bin energy of two frames */ + + /* speech/music classifier improvement parameters */ + Word16 old_Bin_E_fx[3*N_OLD_BIN_E]; + Word16 buf_flux_fx[BUF_LEN]; + Word16 buf_pkh_fx[BUF_LEN]; + Word16 buf_epsP_tilt_fx[BUF_LEN]; + Word16 buf_cor_map_sum_fx[BUF_LEN]; + Word16 buf_Ntonal_fx[BUF_LEN]; + Word16 buf_Ntonal2_fx[BUF_LEN]; + Word16 buf_Ntonal_lf_fx[BUF_LEN]; + Word16 buf_dlp_fx[10]; + Word16 onset_cnt_fx; + Word16 buf_etot_fx[4]; + Word16 attack_hangover_fx; + Word16 dec_mov_fx; + Word16 dec_mov1_fx; + Word16 mov_log_max_spl_fx; + Word16 old_lt_diff_fx[2]; + Word16 UV_cnt1_fx; + Word16 LT_UV_cnt1_fx; + Word16 lpe_buf_fx[HANG_LEN_INIT]; + Word16 voicing_buf_fx[HANG_LEN_INIT]; + Word16 gsc_hangover_fx; + Word16 sparse_buf_fx[HANG_LEN_INIT]; + Word16 hf_spar_buf_fx[HANG_LEN_INIT]; + Word16 LT_sparse_fx; + Word16 gsc_cnt_fx; + Word16 last_vad_spa_fx; + + Word16 lt_music_hangover_fx; + Word16 tonality2_buf_fx[HANG_LEN_INIT]; + Word16 tonality3_buf_fx[HANG_LEN_INIT]; + Word16 LPCErr_buf_fx[HANG_LEN_INIT]; + Word16 lt_music_state_fx; + Word16 lt_speech_state_fx; + Word16 lt_speech_hangover_fx; + + Word16 Last_pulse_pos_fx; /* FEC - last position of the first glotal pulse in the frame */ + Word16 lsfoldbfi0_fx[M]; /* FEC - LSF vector of the previous frame */ + Word16 lsfoldbfi1_fx[M]; /* FEC - LSF vector of the past previous frame */ + Word16 lsf_adaptive_mean_fx[M]; /* FEC - adaptive mean LSF vector for FEC */ + Word16 next_force_safety_net_fx; /* FEC - flag to force safety net in next frame */ + Word16 gsc_last_music_flag_fx; /* Speech/music classifier - last music flag */ + Word16 gsc_lt_diff_etot_fx[MAX_LT]; /* Speech/music classifier - long-term total energy variation */ + Word16 gsc_thres_fx[4]; /* Speech/music classifier - classification threshold */ + Word16 gsc_nb_thr_1_fx; /* Speech/music classifier - number of consecutives frames of level 1 */ + Word16 gsc_nb_thr_3_fx; /* Speech/music classifier - number of consecutives frames of level 3 */ + Word16 gsc_mem_etot_fx; /* Speech/music classifier - total energy memory */ + + Word16 old_S_fx[L_FFT/2]; /* Q7 Tonal detector - prev. log-energy spectrum with subtracted floor */ + Word16 cor_map_fx[L_FFT/2]; /* Q15 Tonal detector - LT correlation map */ + Word16 noise_char_fx; /* Q11 Tonal detector - LT noise character */ + Word32 ave_enr2_fx[NB_BANDS]; /* Q_new + Q_SCALE Tonal detector - LT average E per crit. band (for non_sta2) */ + Word16 act_pred_fx; /* Q15 Tonal detector - prediction of speech activity from 0 to 1 (0-inactive, 1-active) */ + Word16 multi_harm_limit_fx; /* Q9 Tonal detector - adaptive threshold */ + Word32 enrO_fx[NB_BANDS]; /* Noise estimator - previous energy per critical band */ + Word32 bckr_fx[NB_BANDS]; /* Q_new + Q_SCALE Noise estimator - background noise estimation per critical band */ + Word32 ave_enr_fx[NB_BANDS]; /* Q_new + Q_SCALE Noise estimator - long-term average energy per critical band */ + Word16 pitO_fx; /* Q0 Noise estimator - previous open-loop pitch value */ + Word16 aEn_fx; /* Q0 Noise estimator - noise estimator adaptation flag */ + Word16 totalNoise_fx; /* Q8 Noise estimator - total noise energy */ + Word16 first_noise_updt_fx; /* Q0 Noise estimator - flag used to determine if the first noise update frame */ + Word16 harm_cor_cnt_fx; /* Q0 Noise estimator - 1st memory counter of harm or correlation frame */ + Word16 bg_cnt_fx; /* Q0 Noise estimator - pause length counter */ + Word16 prim_act_quick_fx; /* Noise estimator - primary activity quick */ + Word16 prim_act_slow_fx; /* Noise estimator - primary activity slow */ + Word16 prim_act_fx; /* Noise estimator - primary activity slow rise quick fall */ + Word16 prim_act_quick_he_fx; /* Noise estimator - primary activity quick */ + Word16 prim_act_slow_he_fx; /* Noise estimator - primary activity slow */ + Word16 prim_act_he_fx; /* Q15 Noise estimator - primary activity slow rise quick fall */ + Word16 Etot_l_fx; /* Q8 Noise estimator - Track energy from below */ + Word16 Etot_h_fx; /* Q8 Noise estimator - Track energy from above */ + Word16 Etot_l_lp_fx; /* Q8 Noise estimator - Smoothed low energy */ + Word16 Etot_last_fx; /*Q8*/ + Word16 Etot_lp_fx; /* Q8 Noise estimator - Filtered input energy */ + Word16 lt_tn_track_fx; /* Q15 */ + Word16 lt_tn_dist_fx; /* Q8*/ + Word16 lt_Ellp_dist_fx; /* Etot low lp same domain as *Etot_l_lp, Q8 */ + Word16 lt_haco_ev_fx; /* Q15 */ + Word16 low_tn_track_cnt_fx; /* Q0 */ + Word16 epsP_0_2_lp_fx; /* Q12, all epsP quotas , range ]8.0 ..0]*/ + Word16 epsP_0_2_ad_lp_fx; + Word16 epsP_2_16_lp_fx; + Word16 epsP_2_16_lp2_fx; + Word16 epsP_2_16_dlp_lp2_fx; /* Q12 */ + Word16 lt_aEn_zero_fx; /* Q15 */ + + Word16 Etot_st_est_fx; /* Q8 Noise estimation - short term estimate of E{ Etot } */ + Word16 Etot_sq_st_est_fx; /* Q2 Noise estimation - short term estimate of E{ Etot^2 } */ + + Word16 nb_active_frames_fx; + Word16 hangover_cnt_fx; + Word16 lp_speech_fx; + Word16 Etot_v_h2_fx; + + Word16 sign_dyn_lp_fx; /*Q8*/ + Word16 Opt_HE_SAD_ON_fx; + Word16 nb_active_frames_he_fx; + Word16 hangover_cnt_he_fx; + Word16 nb_active_frames_HE_SAD_fx; + + /* should be L_var */ + Word32 L_vad_flag_reg_H_fx; + Word32 L_vad_flag_reg_L_fx; + Word32 L_vad_prim_reg_fx; + Word16 vad_flag_cnt_50_fx; + Word16 vad_prim_cnt_16_fx; + + Word16 hangover_cnt_dtx_fx; + Word16 hangover_cnt_music_fx; + + + Word16 bcg_flux_fx; + Word16 soft_hangover_fx; + Word16 voiced_burst_fx; + Word16 bcg_flux_init_fx; + Word16 voicing_old_fx; + Word16 nb_active_frames_he1_fx; + Word16 hangover_cnt_he1_fx; + + + Word32 bckr_tilt_lt; + + Word16 var_SID_rate_flag_fx; /* CNG and DTX - flag for variable SID rate */ + Word32 lp_ener_fx; /* CNG and DTX - low-pass filtered energy for CNG */ + Word16 cng_seed_fx; /* CNG and DTX - seed for white noise random generator */ + Word16 lspCNG_fx[M]; /* CNG and DTX - LP filtered lsps */ + Word16 first_CNG_fx; /* CNG and DTX - first CNG frame flag */ + Word16 lp_noise_fx; /* CNG and DTX - LP filterend total noise estimation */ + Word16 cnt_SID_fx; /* CNG and DTX - counter of SID update for the interop. mode or dtx, if enabled*/ + Word16 max_SID_fx; /* CNG and DTX - max allowed number of CNG FRAME_NO_DATA frames */ + Word16 interval_SID_fx; /* CNG and DTX - interval of SID update, default 8 */ + Word16 old_enr_index_fx; /* CNG and DTX - index of last encoded CNG energy */ + Word32 Enew_fx; /* CNG and DTX - CNG target residual energy */ + Word16 VarDTX_cnt_voiced_fx; /* CNG and DTX - counter for variable DTX activation (speech) */ + Word32 lt_ener_voiced_fx; /* CNG and DTX - long-term energy of signal (measured on voiced parts) */ + Word16 VarDTX_cnt_noise_fx; /* CNG and DTX - counter for variable DTX activation (noise) */ + Word32 lt_ener_noise_fx; /* CNG and DTX - long-term energy of background noise */ + Word32 lt_ener_last_SID_fx; /* CNG and DTX - long-term energy of last SID frame */ + Word16 cng_hist_size_fx; /* CNG and DTX - size of CNG history buffer for averaging, <0,DTX_HIST_SIZE> */ + Word16 cng_hist_ptr_fx; /* CNG and DTX - pointer for averaging buffers */ + Word16 cng_lsp_hist_fx[DTX_HIST_SIZE*M]; /* CNG and DTX - old LSP buffer for averaging */ + Word16 cng_ener_hist_fx[DTX_HIST_SIZE]; /* CNG and DTX - log energy buffer for averaging */ + Word16 cng_cnt_fx; /* CNG and DTX - counter of CNG frames for averaging */ + Word16 cng_ener_seed_fx; /* CNG and DTX - seed for random generator for variation of excitation energy */ + Word16 cng_ener_seed1_fx; + Word32 frame_ener_fx; + Word16 lp_sp_enr_fx; /*Q8*/ + Word16 last_allow_cn_step_fx; + Word16 ho_hist_size_fx; /* CNG and DTX - size of DTX hangover history buffer for averaging, <0,HO_HIST_SIZE> */ + Word16 ho_hist_ptr_fx; /* CNG and DTX - pointer for averaging buffers */ + Word32 ho_sid_bw_fx; /* CNG and DTX - SID bandwidth flags */ + Word16 ho_lsp_hist_fx[HO_HIST_SIZE*M]; /* CNG and DTX - old LSP buffer for averaging */ + Word32 ho_ener_hist_fx[HO_HIST_SIZE]; /* CNG and DTX - energy buffer for averaging */ + Word32 ho_env_hist_fx[HO_HIST_SIZE*NUM_ENV_CNG]; + Word16 act_cnt_fx; /* CNG and DTX - counter of active frames */ + Word16 ho_circ_size_fx; /* CNG and DTX - size of DTX hangover history buffer for averaging, <0,HO_HIST_SIZE> */ + Word16 ho_circ_ptr_fx; /* CNG and DTX - pointer for averaging buffers */ + Word16 ho_lsp_circ_fx[HO_HIST_SIZE*M]; /* CNG and DTX - old LSP buffer for averaging */ + Word32 ho_ener_circ_fx[HO_HIST_SIZE]; /* CNG and DTX - energy buffer for averaging */ + Word32 ho_env_circ_fx[HO_HIST_SIZE*NUM_ENV_CNG]; + Word16 burst_ho_cnt_fx; /* CNG and DTX - counter of hangover frames at end of active burst */ + Word16 cng_buf_cnt; /* CNG and DTX - Counter of buffered CNG parameters */ + Word16 cng_exc2_buf[HO_HIST_SIZE*L_FFT]; /* CNG and DTX - exc2 buffer for storing */ + Word16 cng_Qexc_buf[HO_HIST_SIZE]; /* CNG and DTX - Q_exc buffer for storing */ + Word32 cng_brate_buf[HO_HIST_SIZE]; /* CNG and DTX - buffer for storing last_active_brate */ + + + Word16 CNG_mode_fx; /* CNG and DTX - mode for DTX configuration */ + Word32 last_active_brate_fx; /* CNG and DTX - last active frame bitrate used for CNG_mode control */ + Word16 ho_16k_lsp_fx[HO_HIST_SIZE]; /* CNG and DTX - 16k LSPs flags */ + Word16 last_CNG_L_frame_fx; /* CNG and DTX - last CNG frame length */ + Word16 act_cnt2_fx; /* CNG and DTX - counter of active frames for CNG_mode switching */ + Word16 ho_lsp_circ2_fx[HO_HIST_SIZE*M]; /* CNG and DTX - second buffer of LSPs */ + Word16 num_ho_fx; /* CNG and DTX - number of selected hangover frames */ + Word16 hangover_terminate_flag_fx; /* CNG and DTX - flag indicating whether to early terminate DTX hangover */ + Word32 old_env_fx[NUM_ENV_CNG]; + Word32 lp_env_fx[NUM_ENV_CNG]; + Word32 cng_res_env_fx[NUM_ENV_CNG*HO_HIST_SIZE]; + Word16 exc_mem_fx[24]; + Word16 exc_mem1_fx[30]; + Word16 exc_mem2_fx[30]; + + struct dispMem_fx dm_fx; /* Noise enhancer - phase dispersion algorithm memory */ + + Word16 uv_count_fx; /*Q0*/ /* Stationary noise UV modification - unvoiced counter */ + Word16 act_count_fx; /*Q0*/ /* Stationary noise UV modification - activation counter */ + Word32 ge_sm_fx; /* Stationary noise UV modification - smoothed excitation gain */ + Word16 lspold_s_fx[M]; /*Q15*/ /* Stationary noise UV modification - old LSP vector */ + Word16 noimix_seed_fx; /*Q0*/ /* Stationary noise UV modification - mixture seed */ + Word16 min_alpha_fx; /*Q15*/ /* Stationary noise UV modification - minimum alpha */ + Word16 exc_pe_fx; /* Stationary noise UV modification - memory of the preemphasis filter */ + + Word16 last_L_frame_fx; /* ACELP@16kHz - last L_frame value */ + Word16 mem_decim16k_fx[2*L_FILT_MAX]; /* ACELP@16kHz - decimation filter memory @16kHz */ + Word16 mem_preemph16k_fx; /* ACELP@16kHz - preemphasis filter memory @16kHz */ + Word16 old_inp_16k_fx[L_INP_MEM]; /* ACELP@16kHz - memory of input signal @16 kHz */ + Word16 mem_deemp_preQ_fx; /* ACELP@16kHz - prequantizer deemhasis memory */ + Word16 mem_preemp_preQ_fx; /* ACELP@16kHz - prequantizer preemhasis memory */ + Word16 last_nq_preQ_fx; /* ACELP@16kHz - AVQ subquantizer number of the last sub-band of the last subframe */ + Word16 use_acelp_preq; /* ACELP@16kHz - flag of prequantizer usage */ + + Word16 bpf_off_fx; + Word16 old_pitch_buf_fx[2*NB_SUBFR16k]; /*Q6 Bass post-filter - buffer of old subframe pitch values */ + + Word16 lps_fx; + Word16 lpm_fx; + + /* stable short pitch detection */ + Word16 voicing0_sm_fx; + Word16 voicing_sm_fx; + Word16 LF_EnergyRatio_sm_fx; + Word16 predecision_flag_fx; + Word32 diff_sm_fx; + Word32 energy_sm_fx; + + Word16 last_ener_fx; /* AC mode (GSC) - previous energy */ + + /*----------------------------------------------------------------------------------* + * HF WB BWE for AMR-WB IO mode at 23.85 kbps + *----------------------------------------------------------------------------------*/ + + Word16 gain_alpha_fx; + Word16 mem_hf2_enc_fx[L_FIR-1]; + Word16 mem_hp400_enc_fx[6]; + Word16 mem_hf_enc_fx[L_FIR-1]; + Word16 mem_syn_hf_enc_fx[M]; + Word16 seed2_enc_fx; + + /*----------------------------------------------------------------------------------* + * CLDFB analysis + *----------------------------------------------------------------------------------*/ + HANDLE_CLDFB_FILTER_BANK cldfbAna_Fx; + + HANDLE_CLDFB_FILTER_BANK cldfbSyn_Fx; + + /*----------------------------------------------------------------------------------* + * FD CNG handle + *----------------------------------------------------------------------------------*/ + HANDLE_FD_CNG_ENC hFdCngEnc_fx; + Word16 fd_cng_reset_flag; + Word16 last_totalNoise_fx; + Word16 totalNoise_increase_hist_fx[TOTALNOISE_HIST_SIZE]; + Word16 totalNoise_increase_len_fx; + /*----------------------------------------------------------------------------------* + * SC-VBR parameters + *----------------------------------------------------------------------------------*/ + + Word16 vadsnr_fx; /*Q7*/ + Word16 vadnoise_fx; + + /* NELP variables */ + Word16 shape1_filt_mem_fx[10]; + Word16 shape2_filt_mem_fx[10]; + Word16 shape3_filt_mem_fx[10]; + Word16 txlpf1_filt1_mem_fx[10]; + Word16 txlpf1_filt2_mem_fx[10]; + Word16 txhpf1_filt1_mem_fx[10]; + Word16 txhpf1_filt2_mem_fx[10]; + Word16 bp1_filt_mem_wb_fx[8]; + Word32 bp1_filt_mem_nb_fx[14]; + Word16 nelp_lp_fit_mem[NELP_LP_ORDER*2]; + Word16 nelp_enc_seed_fx; + Word16 nelp_gain_mem_fx; + Word16 last_nelp_mode_fx; + Word16 nelp_mode_fx; + Word16 qprevIn_fx; + Word16 qprevGain_fx; + + /* PPP variables */ + Word16 pppcountE_fx; + Word16 bump_up_fx; /*Q0*/ + Word16 last_ppp_mode_fx; /*Q0*/ + Word16 ppp_mode_fx; + Word16 prev_ppp_gain_pit_fx; /*Q14*/ + Word16 prev_tilt_code_fx; + + /* voiced encoder variables */ + Word16 firstTime_voicedenc_fx; /*Q0*/ + + /* DTFS variables */ + Word16 dtfs_enc_a_fx[MAXLAG_WI]; /*Q0*/ + Word16 dtfs_enc_b_fx[MAXLAG_WI]; /*Q0*/ + Word16 dtfs_enc_lag_fx; + Word16 dtfs_enc_nH_fx; + Word16 dtfs_enc_nH_4kHz_fx; + Word16 dtfs_enc_upper_cut_off_freq_of_interest_fx; + Word16 dtfs_enc_upper_cut_off_freq_fx; + Word16 dtfs_enc_Q; + + Word32 prev_cw_en_fx; /*Q_prev_cw_en_fx*/ + Word16 ph_offset_E_fx; /*Q15 normalized y 2*Pi */ + Word16 lastLgainE_fx; /*Q11 Previous gain value for the low band */ + Word16 lastHgainE_fx; /*Q11 Previous gain value for the high band */ + Word16 lasterbE_fx[NUM_ERB_WB]; /*Q13 Previous Amplitude spectrum (ERB) */ + Word16 Q_prev_cw_en_fx; + + Word16 mode_QQF_fx; + Word16 rate_control_fx; + Word16 SNR_THLD_fx; + Word16 Q_to_F_fx; + Word16 pattern_m_fx; + Word16 patterncount_fx; + Word16 Last_Resort_fx; + Word16 numactive_fx; /* keep the count of the frames inside current 600 frame bloack.*/ + Word32 sum_of_rates_fx; /* sum of the rates of past 600 active frames*/ + Word32 global_avr_rate_fx; /* global rate upto current time. recorded a (rate in kbps) *6000*/ + Word16 frame_cnt_ratewin_fx; /* keep count of how many ratewin (600) windows */ + + Word16 set_ppp_generic_fx; + Word16 avoid_HQ_VBR_NB; + + /*----------------------------------------------------------------------------------* + * HQ core parameters + *----------------------------------------------------------------------------------*/ + Word16 input_buff[L_FRAME48k+L_FRAME48k+NS2SA(48000, DELAY_FIR_RESAMPL_NS)]; + Word16 * input; + Word16 * old_input_signal_fx; + Word16 Q_old_wtda; + Word16 old_hpfilt_in_fx; + Word16 old_hpfilt_out_fx; + Word32 EnergyLT_fx; + Word32 Energy_Old_fx; + Word16 TransientHangOver_fx; + Word16 old_out_fx[L_FRAME32k]; /* buffer for OLA; at the encoder, the maximum length is L_FRAME32k (corresponds to maximum internal L_frame length) */ + Word16 Q_old_out; + Word16 last_core_fx; + Word16 hq_generic_speech_class_fx; + Word16 mode_count_fx; /* HQ_HARMONIC mode count */ + Word16 mode_count1_fx; /* HQ_NORMAL mode count */ + Word16 Nb_ACELP_frames_fx; + Word16 prev_Npeaks_fx; /* number of peaks in previous frame */ + Word16 prev_peaks_fx[HVQ_MAX_PEAKS]; /* indices of the peaks in previous frame */ + Word16 hvq_hangover_fx; + Word16 prev_hqswb_clas_fx; + Word16 prev_SWB_peak_pos_fx[SPT_SHORTEN_SBNUM]; + + + Word16 lt_old_mode[3]; + Word16 lt_voicing; + Word16 lt_corr; + Word32 lt_tonality; + Word16 lt_corr_pitch[3]; + Word16 lt_hangover; + Word16 lowrate_pitchGain; + + Word16 prev_frm_index_fx[NB_SWB_SUBBANDS_HAR_SEARCH_SB]; + Word16 prev_frm_hfe2_fx; + Word16 prev_stab_hfe2_fx; + Word16 prev_ni_ratio_fx; /* 15 */ + Word16 prev_En_sb_fx[NB_SWB_SUBBANDS]; /* QsEn(4) */ + + Word16 last_bitalloc_max_band_fx[2]; + Word32 last_ni_gain_fx[BANDS_MAX]; + Word16 last_env_fx[BANDS_MAX]; + Word16 last_max_pos_pulse_fx; + + /* PVQ range coder state */ + UWord32 rc_low_fx; + UWord32 rc_range_fx; + Word16 rc_cache_fx; + Word16 rc_carry_fx; + Word16 rc_carry_count_fx; + Word16 rc_num_bits_fx; + Word16 rc_tot_bits_fx; + Word16 rc_offset_fx; + /*----------------------------------------------------------------------------------* + * TBE parameters + *----------------------------------------------------------------------------------*/ + + Word16 old_speech_shb_fx[L_LOOK_16k + L_SUBFR16k]; /* Buffer memories */ + Word16 old_speech_wb_fx[(L_LOOK_12k8 + L_SUBFR) * 5/16]; /* Buffer memories */ + Word16 old_input_fhb_fx[NS2SA(48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) - L_FRAME48k/2]; + Word16 old_input_fhb_fx_Q; + + Word16 state_ana_filt_shb_fx[ (2*ALLPASSSECTIONS_STEEP+1) ]; + Word16 cldfbHBLT; + /* states for the filters used in generating SHB excitation from WB excitation*/ + Word32 mem_csfilt_fx[2]; + + /* states for the filters used in generating SHB signal from SHB excitation*/ + Word16 state_syn_shbexc_fx[L_SHB_LAHEAD]; + Word16 state_lpc_syn_fx[LPC_SHB_ORDER]; + Word16 old_bwe_exc_fx[PIT16k_MAX * 2]; /*Q_exc*/ + Word16 bwe_seed_fx[2]; + Word32 bwe_non_lin_prev_scale_fx; /*Q30*/ + Word16 old_bwe_exc_extended_fx[NL_BUFF_OFFSET]; + Word16 syn_overlap_fx[L_SHB_LAHEAD]; + Word16 decim_state1_fx[(2*ALLPASSSECTIONS_STEEP+1)]; + Word16 decim_state2_fx[(2*ALLPASSSECTIONS_STEEP+1)]; + Word16 mem_genSHBexc_filt_down_wb2_fx[(2*ALLPASSSECTIONS_STEEP+1)]; + Word16 mem_genSHBexc_filt_down_wb3_fx[(2*ALLPASSSECTIONS_STEEP+1)]; + Word16 mem_genSHBexc_filt_down_shb_fx[(2*ALLPASSSECTIONS_STEEP+1)]; + Word32 elliptic_bpf_2_48k_mem_fx[4][4]; + Word16 elliptic_bpf_2_48k_mem_fx_Q[4]; + Word32 prev_fb_energy_fx; + Word16 prev_fb_energy_fx_Q; + Word32 prev_gainFr_SHB_fx; + Word16 lsp_shb_slow_interpl_fx[LPC_SHB_ORDER]; + Word16 lsp_shb_fast_interpl_fx[LPC_SHB_ORDER]; + Word16 shb_inv_filt_mem_fx[LPC_SHB_ORDER]; + Word16 lsp_shb_spacing_fx[3]; + Word16 prev_swb_GainShape_fx; + Word16 prev_frGainAtten_fx; + + Word16 spectral_tilt_reset_fx; + Word16 consec_inactive_fx; + Word16 ra_deltasum_fx; + Word16 trigger_SID_fx; + Word16 running_avg_fx; /*Q15 */ + Word32 L_snr_sum_vad_fx; /*Q4*/ + Word16 prev_wb_GainShape; + Word16 swb_lsp_prev_interp_fx[LPC_SHB_ORDER]; + Word16 fb_state_lpc_syn_fx[LPC_SHB_ORDER]; + Word16 prev_Q_bwe_exc_fb; + Word16 fb_tbe_demph_fx; + Word16 tilt_mem_fx; + + Word16 prev_coder_type_fx; + Word16 prev_lsf_diff_fx[LPC_SHB_ORDER-2]; + Word16 prev_tilt_para_fx; + Word16 cur_sub_Aq_fx[M+1]; + + /* quantized data */ + Word16 lsf_idx_fx[NUM_Q_LSF]; + Word16 m_idx_fx; + Word16 grid_idx_fx; + Word16 idxSubGains_fx; + Word16 idxFrameGain_fx; + Word16 idx_shb_fr_gain_fx; + Word16 idx_res_gs_fx[NB_SUBFR16k]; + Word16 idx_mixFac_fx; + + Word16 lsf_WB_fx; + Word16 gFrame_WB_fx; + + Word16 idxGain_fx; + Word16 dec_2_over_3_mem_fx[12]; + Word16 dec_2_over_3_mem_lp_fx[6]; + /*----------------------------------------------------------------------------------* + * SWB BWE parameters + *----------------------------------------------------------------------------------*/ + + Word16 new_input_hp_fx[NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS)]; + Word16 old_input_fx[NS2SA(48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS)]; + Word16 old_input_wb_fx[NS2SA(16000, DELAY_FD_BWE_ENC_NS)]; + Word16 old_input_lp_fx[NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS)]; + Word16 old_syn_12k8_16k_fx[NS2SA(16000, DELAY_FD_BWE_ENC_NS)]; + Word16 old_fdbwe_speech_fx[L_FRAME48k]; + Word16 mem_deemph_old_syn_fx; + Word16 prev_mode_fx; + Word16 L_old_wtda_swb_fx[L_FRAME48k]; + Word16 prev_Q_input_lp; + Word16 prev_L_swb_norm1_fx; + Word32 prev_global_gain_fx; + Word16 modeCount_fx; + Word32 EnergyLF_fx; + Word16 tbe_demph_fx; + Word16 tbe_premph_fx; + Word16 mem_stp_swb_fx[LPC_SHB_ORDER]; + Word16 *ptr_mem_stp_swb_fx; + Word16 gain_prec_swb_fx; + Word16 mem_zero_swb_fx[LPC_SHB_ORDER]; + + /*----------------------------------------------------------------------------------* + * WB, SWB and FB bandwidth detector + *----------------------------------------------------------------------------------*/ + + Word16 lt_mean_NB_fx; + Word16 lt_mean_WB_fx; + Word16 lt_mean_SWB_fx; + Word16 count_WB_fx; + Word16 count_SWB_fx; + Word16 count_FB_fx; + + /*----------------------------------------------------------------------------------* + * SWB DTX/CNG parameters + *----------------------------------------------------------------------------------*/ + + Word16 last_vad_fx; + Word16 last_wb_cng_ener_fx; + Word16 last_shb_cng_ener_fx; + Word16 mov_wb_cng_ener_fx; + Word16 mov_shb_cng_ener_fx; + Word16 shb_cng_ini_cnt_fx; + Word16 last_SID_bwidth_fx; + Word16 shb_NO_DATA_cnt_fx; + + /*----------------------------------------------------------------------------------* + * Channel-aware mode + *----------------------------------------------------------------------------------*/ + + + Word16 rf_mode; + Word16 rf_mode_last; + Word16 last_rf_mode_cng; + Word16 Opt_RF_ON; + Word16 rf_frame_type; + + Word16 rf_target_bits_write; + Word16 rf_fec_offset; + Word16 rf_fec_indicator; + + Word16 rf_targetbits_buff[MAX_RF_FEC_OFFSET]; + Word16 rf_indx_frametype[MAX_RF_FEC_OFFSET]; + + Word16 rf_mem_w0; + Word16 rf_clip_var[6]; + Word16 rf_tilt_code; + Word16 rf_mem_syn2[M]; + struct dispMem_fx rf_dm_fx; + Word32 rf_gc_threshold; + + Word16 rf_target_bits; + Word16 rf_tilt_buf[NB_SUBFR16k]; + + Word16 rf_indx_lsf[MAX_RF_FEC_OFFSET][3]; + Word16 rf_indx_pitch[MAX_RF_FEC_OFFSET][NB_SUBFR16k]; + Word16 rf_indx_fcb[MAX_RF_FEC_OFFSET][NB_SUBFR16k]; + Word16 rf_indx_gain[MAX_RF_FEC_OFFSET][NB_SUBFR16k]; + Word16 rf_indx_EsPred[MAX_RF_FEC_OFFSET]; + Word16 rf_indx_ltfMode[MAX_RF_FEC_OFFSET][NB_SUBFR16k]; + + Word16 rf_indx_nelp_fid[MAX_RF_FEC_OFFSET]; + Word16 rf_indx_nelp_iG1[MAX_RF_FEC_OFFSET]; + Word16 rf_indx_nelp_iG2[MAX_RF_FEC_OFFSET][2]; + + Word16 rf_indx_tbeGainFr[MAX_RF_FEC_OFFSET]; + + Word16 rf_tcxltp_pitch_int_past; + Word16 rf_last_tns_active; + Word16 rf_second_last_tns_active; + Word16 rf_second_last_core; + Word16 rf_clas[MAX_RF_FEC_OFFSET]; + Word16 rf_gain_tcx[MAX_RF_FEC_OFFSET]; + Word16 rf_tcxltp_param[MAX_RF_FEC_OFFSET]; + + Word16 rf_bwe_gainFr_ind; + + + + /*----------------------------------------------------------------------------------* + * Fixed point only variables + *----------------------------------------------------------------------------------*/ + + Word16 prev_Q_bwe_exc; + Word16 prev_Q_bwe_syn; + Word16 Q_stat_noise_ge; + Word16 Q_stat_noise; + Word16 Q_syn2; + Word16 Q_syn; + Word16 Q_max[L_Q_MEM]; + Word16 Q_max_16k[L_Q_MEM]; + Word16 Q_old; + Word16 prev_Q_old; + Word16 old_wsp_max; /* Last weigthed speech maximal value */ + Word16 old_wsp_shift; /* Last wsp scaling */ + Word16 prev_Q_new; + Word16 prev_Q_shb; + + /*----------------------------------------------------------------------------------* + * + *----------------------------------------------------------------------------------*/ + + Word16 EnergyLT_fx_exp; + Word16 prev_lsp_shb_fx[LPC_SHB_ORDER]; + Word16 prev_lsp_wb_fx[LPC_SHB_ORDER_WB]; + Word16 prev_lpc_wb_fx[LPC_SHB_ORDER_WB]; + Word16 last_last_ppp_mode_fx; + Word16 prev_lsp_wb_temp_fx[LPC_SHB_ORDER_WB]; + + Word16 frame_size_index; /* 0-FRAME_SIZE_NB-1: index determining the frame size */ + Word16 bits_frame_nominal; /* avg bits per frame on active frame */ + Word16 bits_frame; /* total bits per frame */ + Word16 bits_frame_core; /* bits per frame for the core */ + Word8 narrowBand; + + /*ACELP config*/ + ACELP_config acelp_cfg; /* configuration set for each frame */ + + ACELP_config acelp_cfg_rf; /* configuration for RF frame */ + + Word16 mode_index; /* Mode Index for LPD core */ + + /*TCX config*/ + TCX_config tcx_cfg; + Word16 L_frameTCX; + + /* cod_main.c */ + Word16 mem_preemph_enc; /* speech preemph filter memory (at encoder-sampling-rate) */ + + Word16 *speech_TCX; + Word16 *new_speech_TCX; + + Word16 *speech_enc; + Word16 *speech_enc_pe; + Word16 *new_speech_enc; + Word16 *new_speech_enc_pe; + Word16 buf_speech_enc[L_PAST_MAX_32k+L_FRAME32k+L_NEXT_MAX_32k]; + Word16 buf_speech_enc_pe[L_PAST_MAX_32k+L_FRAME32k+L_NEXT_MAX_32k]; + Word16 *wspeech_enc; + Word16 buf_wspeech_enc[L_FRAME16k+L_SUBFR+L_FRAME16k+L_NEXT_MAX_16k]; /*normally there is a lookahead for 12k8 and 16k but L_FRAME_MAX=L_FRAME_16K+L_NEXT_16k*/ + Word16 *synth; + Word16 buf_synth[OLD_SYNTH_SIZE_ENC+L_FRAME32k]; + + /* Core Signal Analysis Outputs */ + Word16 noiseTiltFactor; /* compensation for LPC tilt in noise filling */ + Word16 noiseLevelMemory; /* counter of consecutive low TCX noise levels */ + STnsData tnsData[2]; + Word8 fUseTns[2]; + + Word8 enableTcxLpc; /* global toggle for the TCX LPC quantizer */ + Word16 envWeighted; /* are is{p,f}_old_q[] weighted or not? */ + + Word8 acelpEnabled; /* Flag indicating if ACELP can be used */ + Word8 tcx10Enabled; /* Flag indicating if TCX 10 can be used */ + Word8 tcx20Enabled; /* Flag indicating if TCX 20 can be used */ + + Word16 tcxMode; /* Chosen TCX mode for this frame */ + + LPD_state LPDmem; + + Word16 mem_wsp_enc; /* wsp vector memory */ + + Word16 nb_bits_header_ace; /* number of bits for the header */ + Word16 nb_bits_header_tcx; /* number of bits for the header */ + + /*Added by fcs : restrict the possible in EVS: 0 base 10 = d.c.b.a base 2*/ + /* a = 0/1 : ACELP on/off*/ + /* b = 0/1 : TCX20 on/off*/ + /* c = 0/1 : TCX40 on/off*/ + /* d = 0/1 : TCX80 on/off*/ + Word8 restrictedMode; + + /* Framing */ + Word16 nb_subfr; + + Word16 preemph_fac; /*Preemphasis factor*/ + + Word16 gamma; + Word16 inv_gamma; + + TransientDetection transientDetection; + Word16 transient_info[3]; + + Word16 acelpFramesCount; /* Acelp frame counter. Counts upto 50 only !!! */ + + Word16 prevTempFlatness_fx; /* exponent is AVG_FLAT_E */ + + Word32 prevEnergyHF_fx; + Word32 currEnergyHF_fx; + Word16 currEnergyHF_e_fx; /* exponent of currEnergyHF and prevEnergyHF */ + Word32 energyCoreLookahead_Fx; + Word16 sf_energyCoreLookahead_Fx; + + /* lsf quantizer*/ + Word16 parcorr[2]; + Word16 parcorr_mid[2]; + + Word16 lpcQuantization; + Word16 numlpc; + Word16 encoderLookahead_enc; + Word16 encoderPastSamples_enc; + Word16 encoderLookahead_FB; + + /* pitch_ol for adaptive lag window */ + Word16 old_pitch_la; /* past open loop pitch lag from look-ahead */ + Word16 old_voicing_la; /* past open loop pitch gain from look-ahead */ + + Word32 band_energies[2*NB_BANDS]; /* energy in critical bands without minimum noise floor MODE2_E_MIN */ + Word16 band_energies_exp; /* exponent for energy in critical bands without minimum noise floor MODE2_E_MIN */ + + Word8 tcxonly; + + Word16 Q_max_enc[2]; + + Word16 finalVAD; + Word8 flag_noisy_speech_snr; /*encoder detector for noisy speech*/ + Word16 Pos_relE_cnt; /* Number of frames between positive relE */ + + Word16 fscale; + Word32 sr_core; + Word32 last_sr_core; + Word8 acelp_autocorr; /* Optimize acelp in 0 covariance or 1 correlation domain */ + + Word16 pit_min; + Word16 pit_fr1; + Word16 pit_fr1b; + Word16 pit_fr2; + Word16 pit_max; + Word16 pit_res_max; /* goes from 1 upto 6 (see core_enc_init.c: init_acelp()) */ + + /* for FAC */ + Word16 L_frame_past; + Word8 memQuantZeros[L_FRAME_PLUS]; + + /*Adaptive BPF*/ + Word16 bpf_gain_param; + Word16 bpf_T[NB_SUBFR16k]; + Word16 bpf_gainT[NB_SUBFR16k]; + + struct MEM_BPF + { + Word16 noise_buf[2*L_FILT16k]; + Word16 error_buf[L_FILT16k]; + Word32 lp_error; + Word32 lp_error_ener; + Word16 noise_shift_old; + } mem_bpf; + + /* TCX-LTP */ + Word8 tcxltp; + Word16 tcxltp_pitch_int; + Word16 tcxltp_pitch_fr; + Word16 tcxltp_gain; + Word16 tcxltp_pitch_int_past; + Word16 tcxltp_pitch_fr_past; + Word16 tcxltp_gain_past; + Word16 tcxltp_norm_corr_past; + Word16 buf_speech_ltp[L_PAST_MAX_32k+L_FRAME32k+L_NEXT_MAX_32k]; + Word16 *speech_ltp; + Word16 *new_speech_ltp; + Word16 tcxltp_bits; + Word16 tcxltp_param[LTPSIZE]; + + Word16 measuredBwRatio; /* measured bw; used for TCX noise-filling. 1Q14 */ + Word16 nmStartLine; /* Starting line for the noise measurement. Q0 */ + + Word8 glr; + Word16 glr_idx[2]; + Word32 gain_code[NB_SUBFR16k]; + Word32 mean_gc[2]; + Word16 prev_lsf4_mean; + Word16 last_stab_fac; + Word8 glr_reset; + + /*for rate switching*/ + Word16 rate_switching_reset; /*Rate switching flag requiring a reset of memories at least partially */ + Word16 rate_switching_reset_16kHz; + + Word16 enablePlcWaveadjust; + Word16 Tonal_SideInfo; + IGF_ENC_INSTANCE hIGFEnc; + Word16 igf; + + Word16 seed_acelp; + + Word16 tcx_lpc_shaped_ari; + + PLC_ENC_EVS plcExt; + + Word16 tec_tfa; + TEMPORAL_ENVELOPE_CODING_ENCODER_FX tecEnc; + Word16 tec_flag; + Word16 tfa_flag; + Word32 tfa_enr[N_TEC_TFA_SUBFR]; + + Word16 nTimeSlots; /* for CLDFB */ + + T_CldfbVadState vad_st; + + Word16 vbr_generic_ho_fx; + Word16 last_7k2_coder_type_fx; + + Word16 sharpFlag; + + Word16 Local_VAD; + +} Encoder_State_fx; + +/* Structure for storing correlations between ACELP codebook components and target */ +typedef struct +{ + Word16 xx; /* energy of target x */ + Word16 y1y1; /* energy of adaptive cbk contribution y1 */ + Word16 y2y2; /* energy of fixed cbk contribution y2 */ + Word16 xy1; /* correlation of x and y1 */ + Word16 xy2; /* correlation of x and y2 */ + Word16 y1y2; /* correlation of y1 and y2 */ + + Word16 xx_e; /* energy of target x */ + Word16 y1y1_e; /* energy of adaptive cbk contribution y1 */ + Word16 y2y2_e; /* energy of fixed cbk contribution y2 */ + Word16 xy1_e; /* correlation of x and y1 */ + Word16 xy2_e; /* correlation of x and y2 */ + Word16 y1y2_e; /* correlation of y1 and y2 */ +} ACELP_CbkCorr; + +#endif diff --git a/lib_enc/stat_noise_uv_enc_fx.c b/lib_enc/stat_noise_uv_enc_fx.c new file mode 100644 index 0000000..b9199fa --- /dev/null +++ b/lib_enc/stat_noise_uv_enc_fx.c @@ -0,0 +1,103 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stl.h" + +/*======================================================================*/ +/* FUNCTION : stat_noise_uv_enc_fx */ +/*----------------------------------------------------------------------*/ +/* PURPOSE : Modifies excitation signal in UC mode */ +/* when the noise is stationary */ +/*----------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Encoder_State_fx) st_fx : Encoder state Structure */ +/* _ (Word16) coder_type : coding type */ +/* _ (Word16*) epsP : LP prediction errors */ +/* _ (Word16*) isp_new : immittance spectral pairs at 4th sfr Q15 */ +/* _ (Word16*) isp_mid : immittance spectral pairs at 2nd sfr Q15 */ +/* _ (Word16*) Aq : A(z) quantized for the 4 subframes Q12 */ +/*-----------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16*) exc2 : excitation buffer Q_exc */ +/*-----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*-----------------------------------------------------------------------*/ + +/* _ None */ +/*-----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*=======================================================================*/ +void stat_noise_uv_enc_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 coder_type, /* i : coding type */ + const Word32 *LepsP, /* i : LP prediction errors */ + Word16 *isp_new, /* i : immittance spectral pairs at 4th sfr */ + Word16 *isp_mid, /* i : immittance spectral pairs at 2nd sfr */ + Word16 *Aq, /* i : A(z) quantized for the 4 subframes */ + Word16 *exc2, /* i/o: excitation buffer */ + Word16 Q_new +) +{ + Word16 noisiness = 0; + Word16 num,den,expn,expd; + + test(); + test(); + IF ( EQ_16(coder_type,UNVOICED)||(EQ_16(coder_type,INACTIVE)&&LE_32(st_fx->core_brate_fx,ACELP_9k60))) + { + + /*-----------------------------------------------------------------* + * Calculate and write the noisiness parameter + *-----------------------------------------------------------------*/ + /* epsP[2] is located in LepsP[0] and epsP[16] in LepsP[1] */ + expn = sub(norm_l(LepsP[0]),1); + num = extract_h(L_shl(LepsP[0],expn));/*expn-16*/ + expd = norm_l(LepsP[1]); + den = extract_h(L_shl(LepsP[1],expd));/*expd-16*/ + + num = div_s(num,den);/*expn-expd+15*/ + num = shr(num,add(sub(expn,expd),5));/*Q10*/ + num = sub(num,1024);/*num - 1*/ + + test(); + IF ( NE_16(st_fx->bwidth_fx,NB)) + { + /* WB case */ + /* noisiness = (Word16)(((epsP[2] / epsP[16]) - 1)*2 * 32);*/ + noisiness = shr(num,4);/*Q10 x64 -> Q0 */ + } + ELSE IF ( EQ_16(coder_type,INACTIVE)&&EQ_16(st_fx->bwidth_fx,NB)) + { + /* NB GSC case */ + /* noisiness = (Word16)(((epsP[2] / epsP[16]) - 1)*.25f * 32);*/ + noisiness = shr(num,4+3);/*Q10 x8 -> Q0 */ + } + ELSE + { + /* NB case */ + noisiness = shr(num,4+2);/*Q16 x16 -> Q0 */ + } + + noisiness = s_max(noisiness, 0); + noisiness = s_min(noisiness, 31); + + push_indice_fx( st_fx, IND_NOISINESS, noisiness, 5 ); + } + + /*-----------------------------------------------------------------* + * Modify the stationary noise excitation signal + *-----------------------------------------------------------------*/ + + stat_noise_uv_mod_fx( coder_type, noisiness, st_fx->lsp_old_fx, isp_new, isp_mid, Aq + ,exc2, Q_new, 0, &st_fx->ge_sm_fx, &st_fx->uv_count_fx, &st_fx->act_count_fx, + st_fx->lspold_s_fx, &st_fx->noimix_seed_fx, &st_fx->min_alpha_fx, &st_fx->exc_pe_fx, + st_fx->core_brate_fx, st_fx->bwidth_fx, &st_fx->Q_stat_noise, &st_fx->Q_stat_noise_ge ); + + + return; +} diff --git a/lib_enc/subband_fft.c b/lib_enc/subband_fft.c new file mode 100644 index 0000000..f4aafca --- /dev/null +++ b/lib_enc/subband_fft.c @@ -0,0 +1,323 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include "basop_util.h" +#include "stl.h" +#include "vad_basop.h" +#include "prot_fx.h" +#include "rom_enc_fx.h" + +#define RE(A) A.r +#define IM(A) A.i + +typedef struct +{ + complex_16 work[32]; + complex_16 const* tab; +} cfft_info_16; + +static void ComplexMult_16(Word16 *y1, Word16 *y2, Word16 x1, Word16 x2, Word16 c1, Word16 c2) +{ + *y1 = add(mult(x1, c1) , mult(x2, c2)); + move16(); + *y2 = sub(mult(x2, c1) , mult(x1, c2)); + move16(); +} + +Word16 ffr_getSfWord32(Word32 *vector, /*!< Pointer to input vector */ + Word16 len) /*!< Length of input vector */ +{ + Word32 maxVal; + Word16 i; + Word16 resu; + + + maxVal = 0; + move32(); + FOR(i=0; i +#include "options.h" + +#include "prot_fx.h" +#include "cnst_fx.h" +#include "rom_com_fx.h" +#include "stl.h" + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static Word16 SWB_BWE_encoding_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *insig_fx, /* i/o: delayed original input signal at 32kHz (might be rescaled)*/ + const Word16 *insig_lp_fx, /* i : delayed original lowband input signal at 32kHz */ + const Word16 *insig_hp_fx, /* i : delayed original highband input signal at 32kHz */ + const Word16 *synth_fx, /* i : delayed ACELP core synthesis at 12.8kHz */ + const Word16 *yos_fx, /* i : MDCT coefficients of the windowed original input signal at 32kHz */ + Word16 *SWB_fenv_fx, /* o : frequency-domain quantized BWE envelope */ + const Word16 tilt_nb_fx, /* i : SWB tilt */ + const Word16 st_offset, /* i : start frequency offset for BWE envelope */ + const Word16 coder_type, /* i : coding type */ + Word16 Q_insig_lp, + Word16 Q_shb, + Word16 Q_synth, + Word16 Q_synth_lf +); + +static void delay_input_signal_fx( + Word16 *old_sig, + Word16 *cur_sig, + Word16 *new_sig, + Word16 m1, + Word16 m2, + Word16 *Q_old, + Word16 *Q_new +) +{ + Word16 i; + Word16 max; + Word16 max1_exp, max2_exp; + + max = abs_s(old_sig[0]); + FOR(i=1; itotal_brate_fx, ACELP_13k20)) + { + /*---------------------------------------------------------------------* + * Delay the original input signal to be synchronized with ACELP core synthesis + *---------------------------------------------------------------------*/ + set16_fx( old_input_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME16k ); + Sample_Delay_WB_BWE = NS2SA( 16000, DELAY_FD_BWE_ENC_12k8_NS); + + new_input_fx = old_input_fx + Sample_Delay_WB_BWE; + Copy( st_fx->old_input_wb_fx, old_input_fx, Sample_Delay_WB_BWE ); + Copy( new_wb_speech_fx, new_input_fx, L_FRAME16k ); + Copy( old_input_fx + L_FRAME16k, st_fx->old_input_wb_fx, Sample_Delay_WB_BWE ); + + /*---------------------------------------------------------------------*/ + /* WB BWE encoding */ + + + /* MDCT of the core synthesis signal */ + /*---------------------------------------------------------------------*/ + new_input_fx_exp = 0; + move16(); + + wtda_fx(old_input_fx, &new_input_fx_exp, L_wtda_synth_fx, st_fx->L_old_wtda_swb_fx, + &st_fx->Q_old_wtda,ALDO_WINDOW,ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */ + L_FRAME16k ); + + /* DCT of the ACELP core synthesis */ + direct_transform_fx(L_wtda_synth_fx, yorig_32, 0, L_FRAME16k, &new_input_fx_exp); + + /* Convert to 16 Bits (Calc Shift Required to Stay within MAX_Q_NEW_INPUT) */ + scl = sub(16+8/*MAX_Q_NEW_INPUT*/, new_input_fx_exp); + /* Possible to Upscale? */ + IF (scl > 0) + { + /* Yes */ + /* Calc Room to Upscale */ + Q_synth = Find_Max_Norm32(yorig_32, L_FRAME16k); + + /* Stay within MAX_Q_NEW_INPUT */ + scl = s_min(Q_synth, scl); + } + Copy_Scale_sig32_16(yorig_32, yorig_fx, L_FRAME16k, scl); + Q_synth = add(sub(new_input_fx_exp, 16), scl) - 1; + + mode = WB_BWE_encoding_fx( coder_type, yorig_fx, WB_fenv_fx, st_fx, Q_synth, Q_synth); + push_indice_fx(st_fx, IND_WB_CLASS, mode - 2, 1 ); + } + + st_fx->prev_mode_fx = mode; + + return; +} + +/*-------------------------------------------------------------------* +* swb_bwe_enc() +* +* SWB BWE encoder (only for 32kHz signals) +*-------------------------------------------------------------------*/ +void swb_bwe_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *old_input_12k8_fx, /* i : input signal @12.8kHz for SWB BWE */ + Word16 *old_input_16k_fx, /* i : input signal @16kHz for SWB BWE */ + const Word16 *old_syn_12k8_16k_fx, /* i : ACELP core synthesis at 12.8kHz or 16kHz */ + const Word16 *new_swb_speech_fx, /* i : original input signal at 32kHz */ + Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz */ + const Word16 coder_type, /* i : coding type */ + Word16 Q_shb_speech, + Word16 Q_slb_speech +) +{ + Word16 i; + Word16 *new_input_fx; + Word16 tmp, exp, exp1; + Word16 frac; + Word32 L_tmp; + Word16 inner_frame; + Word32 inner_Fs; + Word32 L_old_input_fx[2*L_FRAME48k]; + Word32 yorig_32[L_FRAME48k]; + Word16 old_input_fx[NS2SA(48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME48k]; + Word16 old_input_lp_fx[L_FRAME16k]; + Word16 new_input_hp_fx[L_FRAME16k]; + Word16 yorig_fx[L_FRAME48k]; + Word16 scl, new_input_fx_exp; + Word16 max; + Word16 Sample_Delay_SWB_BWE; + Word16 Sample_Delay_HP; + Word16 Sample_Delay_LP; + Word16 idxGain = 0; + + Word16 Q_synth_hf, Q_synth, Q_shb; + Word16 tilt_nb_fx; + Word16 SWB_fenv_fx[SWB_FENV]; + Word32 ener_low_fx; + Word32 energy_fbe_fb_fx = 0; + Word16 fb_ener_adjust_fx; + Word16 ener_adjust_quan_fx = 0; + + + /*---------------------------------------------------------------------* + * Delay the original input signal to be synchronized with ACELP core synthesis + *---------------------------------------------------------------------*/ + IF( EQ_16(st_fx->extl_fx, FB_BWE)) + { + inner_frame = L_FRAME48k; + inner_Fs = 48000; + } + ELSE + { + inner_frame = L_FRAME32k; + inner_Fs = 32000; + } + + set16_fx( old_input_fx, 0, add(NS2SA(inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS), inner_frame) ); + + IF( EQ_16(st_fx->L_frame_fx, L_FRAME)) + { + Sample_Delay_SWB_BWE = NS2SA(inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS); + Sample_Delay_HP = NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS); + Sample_Delay_LP = NS2SA(12800, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS); + + delay_input_signal_fx( st_fx->old_input_lp_fx, old_input_lp_fx, &old_input_12k8_fx[L_INP_MEM], Sample_Delay_LP, L_FRAME, &st_fx->prev_Q_input_lp, &Q_slb_speech ); + } + ELSE + { + Sample_Delay_SWB_BWE = NS2SA(inner_Fs, DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS); + Sample_Delay_HP = NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS); + Sample_Delay_LP = NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS); + + delay_input_signal_fx( st_fx->old_input_lp_fx, old_input_lp_fx, &old_input_16k_fx[L_INP_MEM], Sample_Delay_LP, L_FRAME16k, &st_fx->prev_Q_input_lp, &Q_slb_speech ); + } + + Copy(st_fx->new_input_hp_fx, new_input_hp_fx, Sample_Delay_HP); + Copy( shb_speech_fx, &new_input_hp_fx[Sample_Delay_HP], L_FRAME16k-Sample_Delay_HP ); + Copy( shb_speech_fx + L_FRAME16k-Sample_Delay_HP, st_fx->new_input_hp_fx, Sample_Delay_HP ); + new_input_fx = old_input_fx + Sample_Delay_SWB_BWE; + Copy( st_fx->old_input_fx, old_input_fx, Sample_Delay_SWB_BWE ); + Copy( new_swb_speech_fx, new_input_fx, inner_frame ); + Copy( old_input_fx + inner_frame, st_fx->old_input_fx, Sample_Delay_SWB_BWE ); + /*----------------------------------------------------------------------* + * Calculate tilt of the input signal and the ACELP core synthesis + *----------------------------------------------------------------------*/ + + /* tilt returned in Q24 goto to Q11 */ + tilt_nb_fx = round_fx(L_shl(calc_tilt_bwe_fx(old_input_lp_fx, Q_slb_speech, st_fx->L_frame_fx), 3)); + /*---------------------------------------------------------------------* + * SWB BWE encoding + * FB BWE encoding + *---------------------------------------------------------------------*/ + new_input_fx_exp = 0; + /* MDCT of the core synthesis signal */ + wtda_fx(old_input_fx, &new_input_fx_exp, L_old_input_fx, st_fx->L_old_wtda_swb_fx, + &st_fx->Q_old_wtda, ALDO_WINDOW, ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */ + inner_frame ); + + /* DCT of the ACELP core synthesis */ + direct_transform_fx(L_old_input_fx, yorig_32, 0, inner_frame, &new_input_fx_exp); + + /* Convert to 16 Bits (Calc Shift Required to Stay within MAX_Q_NEW_INPUT) */ + scl = sub(16+8, new_input_fx_exp); + /* Possible to Upscale? */ + IF (scl > 0) + { + /* Yes */ + /* Calc Room to Upscale */ + Q_synth = Find_Max_Norm32(yorig_32, inner_frame); + /* Stay within MAX_Q_NEW_INPUT */ + scl = s_min(Q_synth, scl); + } + Copy_Scale_sig32_16(yorig_32, yorig_fx, inner_frame, scl); + Q_synth = add(sub(new_input_fx_exp, 16), scl); + + max = 0; + move16(); + Q_synth_hf = 0; + move16(); + IF (EQ_16(st_fx->L_frame_fx, L_FRAME16k)) + { + scl = 300; + move16(); + } + ELSE + { + scl = 240; + move16(); + } + FOR(i=scl; ilast_extl_fx, SWB_BWE)||EQ_16(st_fx->last_extl_fx,FB_BWE)) + { + exp = norm_l(st_fx->EnergyLT_fx); + IF(add(st_fx->EnergyLT_fx_exp, exp) > shl(sub(Q_synth_hf, 4), 1)) + { + Q_shb = sub(Q_synth_hf, 4); + st_fx->EnergyLT_fx = L_shr(st_fx->EnergyLT_fx, sub(st_fx->EnergyLT_fx_exp, shl(Q_shb, 1))); + } + ELSE + { + Q_shb = shr(add(st_fx->EnergyLT_fx_exp, exp), 1); + IF(s_and(exp, 0x0001) == 1) + { + exp = sub(exp, 1); + } + st_fx->EnergyLT_fx = L_shl(st_fx->EnergyLT_fx, exp); + } + } + ELSE + { + Q_shb = sub(Q_synth_hf, 4); + } + Copy_Scale_sig(new_input_hp_fx, new_input_hp_fx, L_FRAME16k, sub(Q_shb, Q_shb_speech)); + /* SWB BWE encoding */ + IF (EQ_16(st_fx->L_frame_fx, L_FRAME16k)) + { + SWB_BWE_encoding_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, + SWB_fenv_fx, tilt_nb_fx, 80, coder_type, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); + + } + ELSE + { + SWB_BWE_encoding_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, + SWB_fenv_fx, tilt_nb_fx, 6, coder_type, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); + } + + /* FB BWE encoding */ + IF ( EQ_16(st_fx->extl_fx, FB_BWE)) + { + energy_fbe_fb_fx = L_deposit_l(0); + FOR( i=FB_BAND_BEGIN; i45-(exp+2*(Q_synth_hf-4)) */ + L_tmp = Mult_32_16(ener_low_fx, tmp); /*45-(exp+2*(Q_synth_hf-4)) + 2*(Q_synth_hf-4) - 15 = 30-exp */ + exp1 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, exp1); + exp = 31-exp1-(30-exp); + L_tmp = Isqrt_lc(L_tmp, &exp); /*31-exp */ + fb_ener_adjust_fx = round_fx(L_shl(L_tmp, exp)); /*Q15 */ + + } + ELSE + { + fb_ener_adjust_fx = 0; + move16(); + } + + fb_ener_adjust_fx = s_min(fb_ener_adjust_fx, 16384); /*Q15 */ + idxGain = usquant_fx( fb_ener_adjust_fx, &ener_adjust_quan_fx, 0, 512, shl(1, NUM_BITS_FB_FRAMEGAIN) ); + } + + /* write FB BWE frame gain to the bitstream */ + IF( EQ_16(st_fx->extl_fx, FB_BWE)) + { + push_indice_fx(st_fx, IND_FB_SLOPE, idxGain, NUM_BITS_FB_FRAMEGAIN ); + } + + return; +} +/*==========================================================================*/ +/* FUNCTION : static Word16 WB_BWE_fenv_q_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Scalar quantizer routine */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 *cb i: quantizer codebook Q10 */ +/* Word16 cb_length i: length of codebook */ +/* Word16 cb_dim i: dimension of codebook */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Word16 *x i/o: energy of WB envelop Q10 */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* */ +/*==========================================================================*/ +static Word16 WB_BWE_fenv_q_fx( /* o: quantized gain index */ + Word16 *x, /* i/o: energy of WB envelop Q10*/ + const Word16 *cb, /* i: quantizer codebook Q10 */ + const Word16 cb_length, /* i: length of codebook */ + const Word16 cb_dim /* i: dimension of codebook */ +) +{ + Word16 i, j, indx = 0; + Word32 dist, min_dist; + const Word16 *pit = cb;/*Q10 */ + Word16 tmp; + Word32 L_tmp; + + min_dist = L_add(MAX_32, 0); + FOR (i=0; iQ20 */ + dist = L_add(dist, L_tmp); + + pit++; + } + + IF( LT_32(dist,min_dist)) + { + min_dist = L_add(dist, 0); + indx = i; + move16(); + } + } + + FOR(j=0; jextl_fx, SWB_BWE)||EQ_16(st_fx->extl_fx,FB_BWE)) + { + input_hi = &fSpectrum[256]; + move16(); + numsharp = NUM_SHARP; + move16(); + + test(); + test(); + test(); + IF ( ( EQ_16(st_fx->last_extl_fx, SWB_BWE)&&EQ_16(st_fx->extl_fx,SWB_BWE))||(EQ_16(st_fx->last_extl_fx,FB_BWE)&&EQ_16(st_fx->extl_fx,FB_BWE))) + { + IF(st_fx->prev_global_gain_fx == 0) + { + gain_tmp = round_fx(L_shl(fGain, 30)); /*Q14 */ + } + ELSE + { + expn = norm_l(fGain); + num = extract_h(L_shl(fGain, expn)); + expn = sub(sub(30, expn), shl(Q_shb,1)); + + expd = norm_l(st_fx->prev_global_gain_fx); + den = extract_h(L_shl(st_fx->prev_global_gain_fx, expd)); + expd = sub(sub(30, expd), shl(st_fx->prev_Q_shb,1)); + + scale = shr(sub(den, num), 15); + num = shl(num, scale); + expn = sub(expn, scale); + + tmp = div_s(num, den); + expn = sub(expn, expd); + gain_tmp = shl(tmp, sub(expn,1));/*Q14 */ + } + test(); + IF (EQ_16(st_fx->prev_mode_fx,TRANSIENT)) + { + numharmonic = shl(numharmonic, 1); + } + ELSE IF (EQ_16(st_fx->prev_mode_fx, NORMAL)||EQ_16(st_fx->prev_mode_fx,NOISE)) + { + numharmonic = add(shr(numharmonic, 1), numharmonic); + } + } + ELSE + { + gain_tmp = 16384; + move16(); + IF (EQ_16(st_fx->prev_mode_fx, HARMONIC)) + { + numharmonic = shr(numharmonic, 1); + sharplimit = shr(sharplimit, 1); + } + ELSE + { + numharmonic = shl(numharmonic, 1); + sharplimit = shl(sharplimit, 1); + } + } + } + ELSE IF (EQ_16(st_fx->extl_fx, WB_BWE)) + { + input_hi = &fSpectrum[224]; + move16(); + numsharp = 3; + move16(); + + IF (EQ_16(st_fx->prev_mode_fx, HARMONIC)) + { + numharmonic = shr(numharmonic, 2); + } + ELSE + { + numharmonic = shr(numharmonic, 1); + } + IF (NE_16(st_fx->last_extl_fx, WB_BWE)) + { + IF (EQ_16(st_fx->prev_mode_fx, HARMONIC)) + { + sharplimit = shr(sharplimit, 1); + } + ELSE + { + sharplimit = shl(sharplimit, 1); + } + } + } + + L_meanH = L_deposit_l(0); + FOR(i = 0; i < numsharp; i ++) + { + peak = 0; + move16(); + mean[i] = L_deposit_l(0); + + FOR(j = 0; j < SHARP_WIDTH; j ++) + { + mag = abs_s(*input_hi); + IF (GT_16(mag, peak)) + { + peak = mag; + move16();/*Q_syn */ + } + mean[i] = L_add(mean[i], mag); + move32();/*Q_syn */ + input_hi ++; + } + + L_meanH = L_add(L_meanH, mean[i]);/*Q_syn */ + + IF(NE_32(mean[i], L_deposit_l(peak))) + { + L_tmp = L_sub(mean[i], peak);/*Q_syn */ + L_tmp = Mult_32_16(L_tmp, 16913); /* 1/31->Q19 -> Q_syn+19-15 */ + den = extract_l(L_shr(L_tmp, 4)); /*Q_syn */ + IF(den == 0) + { + den = 1; + move16(); + } + expd = norm_s(den); + tmp = div_s(shl(1,sub(14,expd)), den); /*Q(29-expd-Q_syn) */ + L_tmp = L_mult(tmp, peak); /*Q(30-expd) */ + sharp = round_fx(L_shl(L_tmp, sub(expd, 4)));/*Q10 */ + } + ELSE + { + sharp = 0; + move16(); + } + + test(); + IF (GT_16(sharp, 4608)&>_16(peak,shl(1,add(Q_syn,3)))) + { + k = add(k, 1); + move16(); + } + ELSE IF (LT_16(sharp, 3072)) + { + noise = add(noise, 1); + move16(); + } + + IF (GT_16(sharp, sharpPeak)) + { + sharpPeak = sharp; + move16(); + } + } + test(); + IF ( EQ_16(st_fx->extl_fx, SWB_BWE)||EQ_16(st_fx->extl_fx,FB_BWE)) + { + test(); + test(); + test(); + IF(GE_16(k, numharmonic)&>_16(gain_tmp,8192)&<_16(gain_tmp,29491)&>_16(sharpPeak,shl(sharplimit,10))) + { + sharpMod = 1; + move16(); + } + ELSE + { + sharpMod = 0; + move16(); + } + + L_meanH = Mult_32_16(L_meanH, 29127); /*Q_syn+8 */ + L_mean_d = 0; + move16(); + FOR(i=0; iextl_fx, WB_BWE)) + { + test(); + IF (GE_16(k,numharmonic)&>_16(sharpPeak,shl(sharplimit,10))) + { + sharpMod = 1; + move16(); + } + ELSE + { + sharpMod = 0; + move16(); + } + } + + test(); + test(); + IF (sharpMod && LT_16(st_fx->modeCount_fx, 12)) + { + st_fx->modeCount_fx = add(st_fx->modeCount_fx, 1); + } + ELSE IF (sharpMod == 0 && st_fx->modeCount_fx > 0) + { + st_fx->modeCount_fx = sub(st_fx->modeCount_fx, 1); + } + + IF (GE_16(st_fx->modeCount_fx, 2)) + { + sharpMod = 1; + move16(); + } + + test(); + IF (sharpMod) + { + mode = HARMONIC; + move16(); + } + ELSE IF ( EQ_16(st_fx->extl_fx, SWB_BWE)||EQ_16(st_fx->extl_fx,FB_BWE)) + { + L_tmp = Mult_32_16(L_mean_d, 6827); /*Q_syn+8 ; 1/4.8 in Q15 */ + + test(); + test(); + test(); + IF (GT_16(noise, 4)&&(LT_32(L_tmp,L_meanH)||L_meanH==0)&<_16(tilt_nb,10240)) + { + mode = NOISE; + move16(); + } + } + + return (mode); +} +/*-------------------------------------------------------------------* +* freq_weights_fx() +* +*-------------------------------------------------------------------*/ +static void freq_weights_fx( + const Word16 Band_Ener[], /* i : Band energy Q8 */ + const Word16 f_weighting[], /* i : weigting coefs. Q15 */ + Word16 w_env[], /* o : Freq. weighting Q13 */ + const Word16 Nbands /* i : Number of bands */ +) +{ + Word16 i; + Word16 tmp, tmp1, w1[SWB_FENV], w2[SWB_FENV]; + Word16 min_b, max_b; + Word32 L_tmp; + Word16 exp; + + /* Find Max band energy */ + min_b = Band_Ener[0]; + move16(); + max_b = Band_Ener[0]; + move16(); + FOR( i=1; i k; l-- ) + { + dist_min[l] = dist_min[l - 1]; + move32(); + index[l] = index[l - 1]; + move16(); + } + dist_min[k] = L_dist; + move32(); + index[k] = i; + move16(); + BREAK; + } + } + } + } + ELSE + { + set32_fx( dist_min, MAX_32, surv ); /* FLT_MAX */ + + FOR (i = 0; i < surv; i++) + { + index[i] = i; + move16(); + } + + p_E_ROM_dico = E_ROM_dico; + move16(); + + FOR( i = 0; i < E_ROM_dico_size; i++ ) + { + dist = sub(x[0],*p_E_ROM_dico++);/*Q8 */ + L_dist = L_mult(dist,dist);/*Q17 */ + L_dist = L_shr(L_dist,12);/*Q5 */ + + FOR( j = 1; j < dim; j++ ) + { + temp1 = sub(x[j],*p_E_ROM_dico++);/*Q8 */ + L_tmp = L_mult(temp1,temp1);/*Q17 */ + L_dist = L_add(L_dist,L_shr(L_tmp,12));/*Q5 */ + } + + FOR( k = 0; k < surv; k++ ) + { + IF( LT_32(L_dist,dist_min[k])) + { + FOR( l = surv - 1; l > k; l-- ) + { + dist_min[l] = dist_min[l-1]; + move32(); + index[l] = index[l-1]; + move16(); + } + dist_min[k] = L_dist; + move32(); + index[k] = i; + move16(); + BREAK; + } + } + } + } + + return; +} + +/*-------------------------------------------------------------------* +* vqSimple_w_fx() +* +*-------------------------------------------------------------------*/ + +static Word16 vqSimple_w_fx( + const Word16 *x, /* i : input for quantizer Q8 */ + Word16 *y, /* i : quantized value Q8 */ + const Word16 *cb, /* i : codebooks Q8 */ + const Word16 *w, /* i : weight Q13 */ + const Word16 dim, /* i : dimension */ + const Word16 l, /* i : number of candidates */ + const Word16 flag /* i : flag indicationg weighted distortion metric */ +) +{ + Word16 i, j, index; + const Word16 *cbP; + Word16 dist, temp; + Word32 L_dist,L_tmp,L_dist_min; + + index = 0; + move16(); + L_dist_min = L_add(MAX_32, 0); /* FLT_MAX */ + cbP = cb; + move16(); + IF( flag ) + { + FOR( i = 0; i < l; i++ ) + { + /*dist = x[0] - *cbP++; */ + /*dist *= (dist * w[0]); */ + dist = sub(x[0],*cbP++);/*Q8 */ + L_dist = L_mult(dist,w[0]);/*Q22 */ + L_dist = Mult_32_16(L_dist,dist);/*Q15 */ + L_dist = L_shr(L_dist,10);/*Q5 */ + + FOR( j = 1; j < dim; j++ ) + { + /*temp = x[j] - *cbP++; */ + /*dist += temp * temp * w[j]; */ + temp = sub(x[j],*cbP++); + L_tmp = L_mult(temp,w[j]);/*Q22 */ + L_tmp = Mult_32_16(L_tmp,temp);/*Q15 */ + L_dist = L_add(L_dist,L_shr(L_tmp,10));/*Q5 */ + } + IF (LT_32(L_dist, L_dist_min)) + { + L_dist_min = L_add(L_dist, 0);/*Q5 */ + index = i; + move16(); + } + } + } + ELSE + { + FOR( i = 0; i < l; i++ ) + { + /*dist = x[0] - *cbP++; */ + dist = sub(x[0],*cbP++); + /*dist *= dist; */ + L_dist = L_mult(dist,dist);/*Q17 */ + L_dist = L_shr(L_dist,12); + + FOR( j = 1; j < dim; j++ ) + { + /*temp = x[j] - *cbP++; */ + temp = sub(x[j] , *cbP++); + /*dist += temp * temp; */ + L_tmp = L_mult(temp,temp);/*Q17 */ + L_dist = L_add(L_dist,L_shr(L_tmp,12));/*Q5 */ + } + IF (LT_32(L_dist, L_dist_min)) + { + L_dist_min = L_add(L_dist, 0); + index = i; + move16(); + } + } + } + + + /* Reading the selected vector */ + Copy( &cb[index * dim], y, dim ); + + return(index); +} + + + +/*-------------------------------------------------------------------* +* MSVQ_Interpol_Tran_fx() +* +*-------------------------------------------------------------------*/ +static void MSVQ_Interpol_Tran_fx( + Word16 *SWB_env_energy, /* i/o : (original/quantized) energy Q8 */ + Word16 *indice /* o : quantized index */ +) + +{ + Word16 k, n_band, candInd[N_CAND_TR], ind_tmp[2],tmp; + Word16 env_temp11[SWB_FENV_TRANS/2], env_temp12[SWB_FENV_TRANS/2]; + Word16 tmp_q; + Word16 quant_tmp[SWB_FENV_TRANS], quant_tmp2[SWB_FENV_TRANS]; + Word16 quant_select[SWB_FENV_TRANS]; + Word32 L_tmp, L_dist, L_minDist,distCand[N_CAND_TR]; + + /* Extract target vector */ + FOR( n_band = 0; n_band < DIM_TR1; n_band++ ) + { + env_temp11[n_band] = SWB_env_energy[2*n_band]; + move16();/*Q8 */ + env_temp12[n_band] = SWB_env_energy[2*n_band+1]; + move16();/*Q8 */ + } + + vqWithCand_w_fx( env_temp11, Env_TR_Cdbk1_fx, DIM_TR1, N_CB_TR1, candInd, N_CAND_TR, distCand, NULL, 0 ); + + L_minDist = L_add(MAX_32, 0); /* FLT_MAX */ + + FOR( k=0; ktotal_brate_fx,ACELP_8k85)) + { + core_type = 0; + move16(); + } + ELSE + { + core_type = 1; + move16(); + } + get_normalize_spec_fx(core, st_fx->extl_fx, mode, core_type, org_fx, SWB_signal_fx, &(st_fx->prev_L_swb_norm1_fx), offset, Q_new_lf); + + IF ( EQ_16(st_fx->extl_fx,WB_BWE)) + { + max_band = 4; + move16(); + band_step = 2; + move16(); + } + ELSE + { + max_band = SWB_FENV; + move16(); + band_step = 1; + move16(); + } + } + ELSE /* HQ core */ + { + gamma_fx = 18022; + move16();/*.55 in Q15 */ + get_normalize_spec_fx(core, st_fx->extl_fx, mode, -1, org_fx, SWB_signal_fx, &(st_fx->prev_L_swb_norm1_fx), offset, Q_new_lf); + + band_step = 1; + move16(); + IF ( EQ_16(offset,HQ_GENERIC_FOFFSET_32K)) + { + max_band = 12; + move16(); + } + ELSE + { + max_band = SWB_FENV; + move16(); + } + } + + FOR( n_band=0; n_bandL_frame_fx, L_FRAME )) + { + L = L_SUBFR; + move16(); + } + ELSE + { + L = L_SUBFR16k; + move16(); + } + + /* HF transient detect */ + IsTransient = detect_transient_fx( insig_hp_fx, L_FRAME16k, coder_type, Q_shb, st_fx); + st_fx->EnergyLT_fx_exp = shl(Q_shb, 1); + + /* LF transient detect */ + IsTransient_LF = 0; + move16(); + FOR ( n_band = 0; n_band < 4; n_band++ ) + { + tmp = i_mult2(n_band, L); + energy_fx = L_deposit_l(0); + FOR(i=0; iEnergyLF_fx)) + { + IsTransient_LF = 1; + move16(); + } + + st_fx->EnergyLF_fx = energy_fx; + move32(); + } + + /* tilt returned in Q24 go to Q11 */ + tilt_fx = round_fx(L_shl(calc_tilt_bwe_fx(insig_fx, 0, L_FRAME32k), 3)); + + test(); + test(); + IF( EQ_16(IsTransient,1)&&(GT_16(tilt_fx,16384)||GT_16(st_fx->clas_fx,1))) + { + IsTransient = 0; + move16(); + st_fx->TransientHangOver_fx = 0; + move16(); + } + + IF( EQ_16(IsTransient,1)) + { + mode = IsTransient; + move16(); + push_indice_fx(st_fx, IND_SWB_CLASS, mode, 2 ); + + /* Energy for the different bands and global energies */ + global_gain_fx = L_deposit_l(0); + FOR (n_band = 0; n_band < SWB_FENV_TRANS; n_band++) + { + energy_fx = L_deposit_l(0); + FOR (n_coeff = swb_bwe_trans_subband_fx[n_band]+st_offset; n_coeff < swb_bwe_trans_subband_fx[n_band+1]+st_offset; n_coeff++) + { + L_tmp = L_shr(L_mult0(yos_fx[n_coeff], yos_fx[n_coeff]), 7); /*2*Q_synth-7 */ + energy_fx = L_add(L_tmp, energy_fx); /*2*Q_synth-7 */ + } + global_gain_fx = L_add(global_gain_fx, L_shr(energy_fx, sub(sub(shl(Q_synth,1),7), shl(Q_shb,1)))); /*2*Q_shb */ + L_SWB_fenv_fx[n_band] = energy_fx; + move32(); + } + global_gain_fx = L_shr(global_gain_fx, 1); /*2*Q_shb */ + + FOR (n_band = 0; n_band < SWB_FENV_TRANS; n_band++) + { + expd = norm_s(swb_bwe_trans_subband_width_fx[n_band]); + tmp = div_s(shl(1,sub(14,expd)), swb_bwe_trans_subband_width_fx[n_band]);/*Q(29-expd) */ + L_tmp = Mult_32_16(L_SWB_fenv_fx[n_band], tmp); /*2*Q_synth-7+29-expd - 15 */ + exp = norm_l(L_tmp); + tmp = Log2_norm_lc(L_shl(L_tmp, exp)); + move16(); + exp = sub(sub(30, exp), sub(add(shl(Q_synth,1),7),expd)); + L_tmp = Mpy_32_16(exp, tmp, 24660); /* Q14 */ /*10log10(2) in Q13 */ + tmp = round_fx(L_shl(L_tmp, 10)); /* Q8 */ + + SWB_fenv_fx[n_band] = sub(tmp, Mean_env_tr_fx[n_band]); + move16();/*Q8 */ + } + + WB_tenv_orig_fx = L_deposit_l(0); + WB_tenv_syn_fx = L_deposit_l(1); + FOR(n_band = 0; n_band < SWB_TENV; n_band++) + { + tmp = i_mult2(n_band, L_SUBFR16k); + L_SWB_tenv = L_deposit_l(0); + FOR(i = 0; i < L_SUBFR16k; i++) + { + L_SWB_tenv = L_add(L_SWB_tenv, L_mult0(insig_hp_fx[i + tmp], insig_hp_fx[i + tmp])); /*2*Q_shb */ + } + + tmp = i_mult2(n_band, L); + FOR(i=0; iQ_syn2 - 7 */ + WB_tenv_orig_fx = L_add(WB_tenv_orig_fx, L_shr(L_mult0(insig_lp_fx[i + tmp], insig_lp_fx[i + tmp]), 7)); /*2*Q_insig_lp - 7 */ + } + + L_tmp = Mult_32_16(L_SWB_tenv, INV_L_SUBFR16k_FX);/*2*Q_shb */ + SWB_tenv_fx[n_band] = 0; + move16(); + IF(L_tmp != 0) + { + exp = norm_l(L_tmp); + tmp = extract_h(L_shl(L_tmp, exp)); + exp = sub(exp, sub(30, 2*Q_shb)); + + tmp = div_s(16384, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp); /*Q(31-exp) */ + + SWB_tenv_fx[n_band] = round_fx(L_shl(L_tmp, sub(exp, 12))); /*Q3 */ + } + } + + IF(WB_tenv_orig_fx != 0) + { + expn = norm_l(WB_tenv_orig_fx); + num = extract_h(L_shl(WB_tenv_orig_fx, expn)); + expn = sub(sub(30, expn), sub(shl(Q_insig_lp,1),7)); + + expd = norm_l(WB_tenv_syn_fx); + den = round_fx(L_shl(WB_tenv_syn_fx, expd)); + expd = sub(sub(30, expd), sub(shl(st_fx->Q_syn2, 1), 7)); + + scale = shr(sub(den, num), 15); + num = shl(num, scale); + expn = sub(expn, scale); + + tmp = div_s(num, den); + expn = sub(expn, expd); + + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &expn); /*31-expn */ + + Rat_tenv_fx = round_fx(L_shl(L_tmp, sub(expn, 1)));/*Q14 */ + } + ELSE + { + Rat_tenv_fx = 16384; + move16(); + } + + IF(LT_16(Rat_tenv_fx, 8192)) + { + L_tmp = L_mult(Rat_tenv_fx, 19661);/*Q29 */ + Rat_tenv_fx = round_fx(L_shl(L_tmp, 2));/*Q15 */ + } + ELSE IF (GT_16(Rat_tenv_fx, 16384)) + { + Rat_tenv_fx = 32767; + move16(); + } + + FOR(n_band = 0; n_band < SWB_TENV; n_band++) + { + SWB_tenv_fx[n_band] = mult_r(SWB_tenv_fx[n_band], Rat_tenv_fx); + move16();/*Q3 */ + } + + max_fx = SWB_tenv_fx[0]; + move16(); + pos = 0; + move16(); + FOR(n_band = 1; n_band < SWB_TENV; n_band++) + { + IF(GT_16(SWB_tenv_fx[n_band],max_fx)) + { + max_fx = SWB_tenv_fx[n_band]; + move16(); + pos = n_band; + move16(); + } + } + + max_fx = SWB_tenv_fx[0]; + move16(); + FOR(n_band = 1; n_band < SWB_TENV; n_band++) + { + tmp = sub(mult_r(SWB_tenv_fx[n_band], 6554), SWB_tenv_fx[n_band-1]); + IF(tmp > 0) + { + BREAK; + } + } + + IF(n_band < SWB_TENV) + { + energy_fx = L_deposit_l(0); + FOR(n_band = (pos+1); n_band < SWB_TENV; n_band++) + { + energy_fx = L_add(energy_fx, SWB_tenv_fx[n_band]);/*Q3 */ + } + + IF(pos == sub(SWB_TENV, 1)) + { + energy_fx = L_deposit_l(0); + } + ELSE + { + tmp = sub(SWB_TENV, pos+1); + tmp = div_s(1, tmp); /*Q15 */ + energy_fx = Mult_32_16(energy_fx, tmp);/*Q3 */ + } + + FOR(n_band = 0; n_band < pos; n_band++) + { + SWB_tenv_fx[n_band] = mult_r(SWB_tenv_fx[n_band], 16384); + move16(); + } + + /*SWB_tenv_fx[pos] = add(SWB_tenv_fx[pos], mult_r(SWB_tenv_fx[pos], 164)); move16();//Q3 */ + SWB_tenv_fx[pos] = round_fx(L_mac(L_mult(SWB_tenv_fx[pos],32767), SWB_tenv_fx[pos], 164)); /*Q3 */ + + IF(LT_32(energy_fx, SWB_tenv_fx[pos])) + { + FOR(n_band = pos+1; n_band < SWB_TENV; n_band++) + { + SWB_tenv_fx[n_band] = mult_r(SWB_tenv_fx[n_band], 29491); + move16();/*Q3 */ + } + } + } + ELSE + { + FOR(n_band = 1; n_band < SWB_TENV; n_band++) + { + IF(GT_16(SWB_tenv_fx[n_band-1], SWB_tenv_fx[n_band])) + { + /*SWB_tenv_fx[n_band-1] = add(mult_r(SWB_tenv_fx[n_band-1], 16384), mult_r(SWB_tenv_fx[n_band], 16384)); move16();//Q3 */ + SWB_tenv_fx[n_band-1] = round_fx(L_mac(L_mult(SWB_tenv_fx[n_band-1], 16384), SWB_tenv_fx[n_band], 16384)); /*Q3 */ + } + ELSE + { + /*SWB_tenv_fx[n_band] = add(mult_r(SWB_tenv_fx[n_band-1], 16384), mult_r(SWB_tenv_fx[n_band], 16384)); move16();//Q3 */ + SWB_tenv_fx[n_band] = round_fx(L_mac(L_mult(SWB_tenv_fx[n_band-1], 16384), SWB_tenv_fx[n_band], 16384)); /*Q3 */ + } + } + + FOR(n_band = 0; n_band < SWB_TENV; n_band++) + { + SWB_tenv_fx[n_band] = mult_r(SWB_tenv_fx[n_band], 29491); + move16();/*Q3 */ + } + } + + test(); + test(); + IF(IsTransient_LF == 0 && EQ_16(coder_type,INACTIVE)&&EQ_16(st_fx->TransientHangOver_fx,1)) + { + FOR(n_band = 0; n_band < SWB_TENV; n_band++) + { + SWB_tenv_fx[n_band] = mult_r(SWB_tenv_fx[n_band], 16384); + move16(); + } + FOR(n_band = 0; n_band < SWB_FENV_TRANS; n_band++) + { + SWB_fenv_fx[n_band] = mult_r(SWB_fenv_fx[n_band], 1638); + move16(); + } + } + ELSE + { + SWB_fenv_fx[2] = mult_r(SWB_fenv_fx[2], 3277); + move16(); + SWB_fenv_fx[3] = mult_r(SWB_fenv_fx[3], 1638); + move16(); + } + + FOR(n_band = 0; n_band < SWB_TENV; n_band++) + { + IF(SWB_tenv_fx[n_band] == 0) + { + SWB_tenv_tmp_fx[n_band] = -32768; + move16(); /*-16 in Q11 */ + } + ELSE + { + L_tmp = L_deposit_h(SWB_tenv_fx[n_band]); /*Q19 */ + expn = norm_l(L_tmp); + tmp = Log2_norm_lc(L_shl(L_tmp, expn)); + expn = sub(sub(30, expn), 19); + L_tmp = Mpy_32_16(expn, tmp, 32767); /* Q16 */ /*1 in Q15 */ + SWB_tenv_tmp_fx[n_band] = round_fx(L_shl(L_tmp, 11)); /* Q11 */ + } + + IF (GT_16(SWB_tenv_tmp_fx[n_band], 30720)) + { + index = 15; + move16(); + } + ELSE IF (SWB_tenv_tmp_fx[n_band] < 0) + { + index = 0; + move16(); + } + ELSE + { + index = shr(add(SWB_tenv_tmp_fx[n_band], 1024), 11); + } + + push_indice_fx(st_fx, IND_SWB_TENV, index, 4 ); + } + + MSVQ_Interpol_Tran_fx(SWB_fenv_fx, indice); + + push_indice_fx(st_fx, IND_SWB_FENV, indice[0], 7 ); + push_indice_fx(st_fx, IND_SWB_FENV, indice[1], 6 ); + } + ELSE + { + /* Energy for the different bands and global energies */ + global_gain_fx = L_deposit_l(0); + FOR (n_band = 0; n_band < SWB_FENV; n_band++) + { + energy_fx = L_deposit_l(0); + FOR (n_coeff = swb_bwe_subband_fx[n_band]+st_offset; n_coeff < swb_bwe_subband_fx[n_band+1]+st_offset; n_coeff++) + { + L_tmp = L_shr(L_mult0(yos_fx[n_coeff], yos_fx[n_coeff]), 5); /*2*Q_synth-5 */ + energy_fx = L_add(L_tmp, energy_fx); /*2*Q_synth-5 */ + } + + IF (LT_16(n_band, sub(SWB_FENV,2))) + { + global_gain_fx = L_add(global_gain_fx, L_shr(energy_fx, sub(2*Q_synth-5, 2*Q_shb))); /*2*Q_shb */ + } + L_SWB_fenv_fx[n_band] = energy_fx; + move32(); + } + + global_gain_fx = L_shr(global_gain_fx, 1); /*2*Q_shb */ + mode = FD_BWE_class_fx(yos_fx, global_gain_fx, tilt_nb_fx, Q_synth, Q_shb, st_fx); + push_indice_fx(st_fx, IND_SWB_CLASS, mode, 2 ); + + energy_control_fx( st_fx, ACELP_CORE, mode, -1, yos_fx, st_offset, energy_factor_fx, Q_synth_lf ); + + FOR (n_band = 0; n_band < SWB_FENV; n_band++) + { + L_tmp = Mult_32_16(L_SWB_fenv_fx[n_band],energy_factor_fx[n_band]);/*2*Q_synth-5 */ + L_tmp = Mult_32_16(L_tmp,swb_inv_bwe_subband_width_fx[n_band]);/*2*Q_synth-5 */ + + IF(L_tmp != 0) + { + expn = norm_l(L_tmp); + tmp = Log2_norm_lc(L_shl(L_tmp,expn)); + expn = sub(30,add(expn,sub(shl(Q_synth,1),5))); + L_tmp = Mpy_32_16(expn, tmp, 24660); /* Q14 */ /*10log10(2) in Q13 */ + SWB_fenv_fx[n_band] = round_fx(L_shl(L_tmp, 10)); /* Q8 */ + } + ELSE + { + SWB_fenv_fx[n_band] = -24576; + move16(); + } + } + freq_weights_fx(SWB_fenv_fx, w_NOR_fx, w_env_fx, SWB_FENV); + + FOR (n_band = 0; n_band < SWB_FENV; n_band++) + { + SWB_fenv_fx[n_band] = sub(SWB_fenv_fx[n_band] , Mean_env_fx[n_band]); + move16(); + } + + /* Energy VQ */ + msvq_interpol_fx(SWB_fenv_fx, w_env_fx, indice); + + push_indice_fx(st_fx, IND_SWB_FENV, indice[0], 5 ); + push_indice_fx(st_fx, IND_SWB_FENV, indice[1], 7 ); + push_indice_fx(st_fx, IND_SWB_FENV, indice[2], 6 ); + push_indice_fx(st_fx, IND_SWB_FENV, indice[3], 5 ); + push_indice_fx(st_fx, IND_SWB_FENV, indice[4], 6 ); + + } + st_fx->prev_mode_fx = mode; + move16(); + st_fx->prev_global_gain_fx = global_gain_fx; + move32(); + st_fx->prev_Q_shb = Q_shb; + move16(); + + return mode; +} + +/*-------------------------------------------------------------------* + * get_normalize_spec_fx_32() + * + *-------------------------------------------------------------------*/ + +static void get_normalize_spec_fx_32( + const Word16 core, /* i : core selected : Q0 */ + const Word16 extl, /* i : extension layer selected: Q0 */ + const Word16 mode, /* i : SHB BWE class : Q0 */ + const Word16 core_type, /* i : coding type : Q0 */ + const Word32 *org_fx, /* i : input spectrum : Q12 */ + Word32 *SWB_signal_fx, /* o : output spectrum : Q20 */ + Word16 *prev_L_swb_norm, /* i : previous norm. len : Q0 */ + const Word16 offset /* i : frequency offset : Q0 */ +) +{ + Word16 n_freq, L_swb_norm; + Word16 frq_end; + Word16 exp1, exp2, tmp; + Word32 L_tmp; + Word32 envelope_fx[L_FRAME32k]; + + set32_fx(SWB_signal_fx, 0, HQ_GENERIC_HIGH0+offset); + calc_normal_length_fx_32(core, org_fx, mode, extl, &L_swb_norm, prev_L_swb_norm); + test(); + IF(EQ_16(extl , SWB_BWE)||EQ_16(extl,FB_BWE)) + { + IF ( EQ_16(mode ,HARMONIC)) + { + Copy32(org_fx, &SWB_signal_fx[add(240,offset)], 240); + Copy32(&org_fx[128], &SWB_signal_fx[add(480,offset)], 80); + } + ELSE + { + Copy32( &org_fx[112], &SWB_signal_fx[add(240,offset)], 128 ); + Copy32( &org_fx[112], &SWB_signal_fx[add(368,offset)], 128 ); + Copy32( &org_fx[176], &SWB_signal_fx[add(496,offset)], 64 ); + } + frq_end = 560+offset; + move16(); + } + ELSE IF (EQ_16(extl , WB_BWE)) + { + IF ( core_type == 0 ) + { + Copy32(&org_fx[160], &SWB_signal_fx[240], 80); + } + ELSE + { + Copy32(&org_fx[80], &SWB_signal_fx[240], 80); + } + frq_end = L_FRAME16k; + move16(); + } + ELSE + { + Copy32( org_fx+HQ_GENERIC_OFFSET, SWB_signal_fx+HQ_GENERIC_HIGH0+offset, HQ_GENERIC_LEN0 ); + Copy32( org_fx+HQ_GENERIC_OFFSET, SWB_signal_fx+HQ_GENERIC_HIGH1+offset, HQ_GENERIC_LEN0 ); + IF ( EQ_16(offset , HQ_GENERIC_FOFFSET_24K4)) + { + Copy32( org_fx+HQ_GENERIC_LOW0, SWB_signal_fx+HQ_GENERIC_HIGH2+offset, HQ_GENERIC_END_FREQ-HQ_GENERIC_HIGH2 ); + } + frq_end = L_FRAME32k; + move16(); + } + + /* calculate envelope */ + calc_norm_envelop_fx_32(SWB_signal_fx, envelope_fx, L_swb_norm, frq_end - offset, offset); + + /* Normalize with envelope */ + FOR ( n_freq = add(swb_bwe_subband_fx[0],offset); n_freqtotal_brate_fx,ACELP_8k00)) + { + core_type = 0; + move16(); + } + ELSE + { + core_type = 1; + move16(); + } + + get_normalize_spec_fx_32(core, st_fx->extl_fx, mode, core_type, org_fx, SWB_signal_fx, &(st_fx->prev_L_swb_norm1_fx), offset ); + + IF ( EQ_16(st_fx->extl_fx , WB_BWE)) + { + max_band = 4; + move16(); + band_step = 2; + move16(); + } + } + ELSE /* HQ core */ + { + gamma_fx = 18021; + move16(); + get_normalize_spec_fx_32(core, -1, mode, -1, org_fx, SWB_signal_fx, &(st_fx->prev_L_swb_norm1_fx), offset ); + + IF ( EQ_16(offset , HQ_GENERIC_FOFFSET_32K)) + { + max_band = 12; + move16(); + } + } + + FOR ( n_band=0; n_band 0) + { + a_fx = Mult_32_16(a_fx, swb_inv_bwe_subband_width_fx[k]);/*6 */ + + exp = norm_l(p_fx); + tmp = Log2_norm_lc(L_shl(p_fx, exp));/*15 */ + exp = sub(30, add(exp, 6)); + L_tmp1 = L_add(L_deposit_h(exp), L_shr(L_deposit_h(tmp), 15));/*16 */ + + exp = norm_l(a_fx); + tmp = Log2_norm_lc(L_shl(a_fx, exp)); + exp = sub(30, add(exp, 6)); + L_tmp2 = L_add(L_deposit_h(exp), L_shr(L_deposit_h(tmp), 15));/*16 */ + + p2a_fx = L_sub(L_tmp1, L_tmp2);/*16 */ + avgp2a_fx = L_add(avgp2a_fx, p2a_fx);/*16 */ + } + } + avgp2a_fx = Mult_32_16(avgp2a_fx, inv_band_fx);/*16 + 15 - 15 */ + IF (GT_32(avgp2a_fx , 187227))/*8.6 / 10log10(2), Q16 */ + { + return HQ_GENERIC_EXC1; + } + ELSE + { + return HQ_GENERIC_EXC0; + } +} + +/*-------------------------------------------------------------------* + * hq_generic_encoding_fx() + * + *-------------------------------------------------------------------*/ +void hq_generic_encoding_fx( + const Word32 *coefs_fx, /* i : MDCT coefficients of weighted original : Q12 */ + Word16 *hq_generic_fenv_fx, /* i/o: energy of SWB envelope : Q3 */ + const Word16 hq_generic_offset, /* i : frequency offset for extracting energy : Q0 */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *hq_generic_exc_clas /* o : bwe excitation class : Q0 */ +) +{ + Word16 n_coeff, n_band; + Word16 indice[HQ_GENERIC_NVQIDX]; + Word16 nenv; + + Word16 energy_factor_fx[SWB_FENV] = {0}; + Word16 cs, exp, tmp, tmp2; + Word32 energy_fx; + Word32 L_tmp, max_coefs_fx; + Word16 w_env_fx[SWB_FENV]; + + IF ( LE_16(hq_generic_offset , HQ_GENERIC_FOFFSET_24K4)) + { + nenv = SWB_FENV; + move16(); + } + ELSE + { + nenv = SWB_FENV-2; + move16(); + } + + + energy_control_fx_32(st_fx, HQ_CORE, -1, -1, coefs_fx, hq_generic_offset, energy_factor_fx); + + IF ( EQ_16(st_fx->hq_generic_speech_class_fx , 1)) + { + push_indice_fx( st_fx, IND_HQ_SWB_EXC_SP_CLAS, 1, 1 ); + *hq_generic_exc_clas = HQ_GENERIC_SP_EXC; + move16(); + } + ELSE + { + *hq_generic_exc_clas = decision_hq_generic_class_fx_32(coefs_fx, hq_generic_offset); + push_indice_fx( st_fx, IND_HQ_SWB_EXC_SP_CLAS, 0, 1 ); + push_indice_fx( st_fx, IND_HQ_SWB_EXC_CLAS, *hq_generic_exc_clas, 1 ); + } + + FOR ( n_band = 0; n_band < nenv; n_band++ ) + { + energy_fx = L_deposit_l(0); + max_coefs_fx = L_deposit_l(0); + tmp2 = add(swb_bwe_subband_fx[n_band+1] , hq_generic_offset); + FOR ( n_coeff = add(swb_bwe_subband_fx[n_band],hq_generic_offset); n_coeff < tmp2; n_coeff++ ) + { + IF (LT_32(max_coefs_fx , L_abs(coefs_fx[n_coeff]))) + { + max_coefs_fx = L_abs(coefs_fx[n_coeff]); + } + } + cs = norm_l(max_coefs_fx); + tmp2 = add(swb_bwe_subband_fx[n_band+1] , hq_generic_offset); + FOR ( n_coeff = add(swb_bwe_subband_fx[n_band],hq_generic_offset); n_coeff < tmp2; n_coeff++ ) + { + tmp = extract_h(L_shl(coefs_fx[n_coeff], cs));/*12 + cs - 16 */ + L_tmp = L_mult0(tmp, tmp);/*2*cs - 8 */ + energy_fx = L_add(energy_fx, L_shr(L_tmp, 5)); + } + + IF (energy_fx != 0) + { + L_tmp = Mult_32_16(energy_fx, energy_factor_fx[n_band]);/*2*cs - 13 */ + L_tmp = Mult_32_16(L_tmp, swb_inv_bwe_subband_width_fx[n_band]);/*2*cs - 13 + 15 - 15 */ + + exp = norm_l(L_tmp); + tmp = Log2_norm_lc(L_shl(L_tmp, exp)); + exp = sub(30, add(exp, 2*cs-13)); + + L_tmp = Mpy_32_16(exp, tmp, 24660); /* Q14 */ /*10log10(2) in Q13 */ + hq_generic_fenv_fx[n_band] = round_fx(L_shl(L_tmp, 10));/*Q8 */ + } + ELSE + { + hq_generic_fenv_fx[n_band] = -24576; + move16(); + } + } + + IF ( EQ_16(st_fx->bwidth_fx , FB)) + { + FOR ( n_band = 0; n_band < DIM_FB; n_band++ ) + { + energy_fx = L_deposit_l(0); + max_coefs_fx = L_deposit_l(0); + tmp2 = fb_bwe_subband[add(n_band,1)]; + FOR ( n_coeff = fb_bwe_subband[n_band]; n_coeff < tmp2; n_coeff++ ) + { + IF (LT_32(max_coefs_fx, L_abs(coefs_fx[n_coeff]))) + { + max_coefs_fx = L_abs(coefs_fx[n_coeff]); + } + } + cs = norm_l(max_coefs_fx); + tmp2 = fb_bwe_subband[add(n_band,1)]; + FOR ( n_coeff = fb_bwe_subband[n_band]; n_coeff < tmp2; n_coeff++ ) + { + tmp = extract_h(L_shl(coefs_fx[n_coeff], cs));/*12 + cs - 16 */ + L_tmp = L_mult0(tmp, tmp);/*2*cs - 8 */ + energy_fx = L_add(energy_fx, L_shr(L_tmp, 5)); + } + + IF (energy_fx != 0) + { + L_tmp = Mult_32_16(energy_fx, fb_inv_bwe_subband_width_fx[n_band]);/*2*cs - 13 + 18 - 15 */ + + exp = norm_l(L_tmp); + tmp = Log2_norm_lc(L_shl(L_tmp, exp)); + exp = sub(30, add(exp, 2*cs-13)); + + L_tmp = Mpy_32_16(exp, tmp, 24660); /* Q14 */ /*10log10(2) in Q13 */ + hq_generic_fenv_fx[add(n_band,nenv)] = round_fx(L_shl(L_tmp, 10));/*Q8 */ + } + ELSE + { + hq_generic_fenv_fx[add(n_band,nenv)] = -24576; + move16(); + } + } + } + + freq_weights_fx(hq_generic_fenv_fx, w_NOR_fx, w_env_fx, nenv); + + FOR ( n_band = 0; n_band < nenv; n_band++ ) + { + hq_generic_fenv_fx[n_band] = sub(hq_generic_fenv_fx[n_band], Mean_env_fx[n_band]); + } + + IF ( st_fx->bwidth_fx == FB ) + { + FOR ( n_band = 0; n_band < DIM_FB; n_band++ ) + { + hq_generic_fenv_fx[add(n_band,nenv)] = sub(shr(hq_generic_fenv_fx[add(n_band,nenv)], 1), Mean_env_fb_fx[n_band]); + } + } + + + /* Energy VQ */ + IF ( LE_16(hq_generic_offset , HQ_GENERIC_FOFFSET_24K4)) + { + msvq_interpol_fx( hq_generic_fenv_fx, w_env_fx, indice ); + } + ELSE + { + msvq_interpol_2_fx(hq_generic_fenv_fx, w_env_fx, indice, nenv); + } + + IF ( EQ_16(st_fx->bwidth_fx , FB)) + { + indice[5] = vqSimple_w_fx(hq_generic_fenv_fx+nenv, hq_generic_fenv_fx+nenv, EnvCdbkFB_fx, NULL, DIM_FB, N_CB_FB, 0); + } + + push_indice_fx( st_fx, IND_SWB_FENV_HQ, indice[0], 5 ); + push_indice_fx( st_fx, IND_SWB_FENV_HQ, indice[1], 7 ); + push_indice_fx( st_fx, IND_SWB_FENV_HQ, indice[2], 6 ); + push_indice_fx( st_fx, IND_SWB_FENV_HQ, indice[3], 5 ); + + IF ( LE_16(hq_generic_offset , HQ_GENERIC_FOFFSET_24K4)) + { + push_indice_fx( st_fx, IND_SWB_FENV_HQ, indice[4], 6 ); + } + ELSE + { + push_indice_fx( st_fx, IND_SWB_FENV_HQ, indice[4], 5 ); + } + + IF ( EQ_16(st_fx->bwidth_fx , FB)) + { + push_indice_fx( st_fx, IND_FB_FENV_HQ, indice[5], 5 ); + } + + FOR ( n_band = 0; n_band < nenv; n_band++ ) + { + tmp = add(hq_generic_fenv_fx[n_band], Mean_env_fx[n_band]);/*8 */ + L_tmp = L_mult(tmp, 21771);/*26 */ + L_tmp = L_shr(L_tmp, 10);/*16 */ + L_Extract(L_tmp, &exp, &tmp);/* */ + tmp = extract_l(Pow2(13, tmp)); + exp = sub(exp, 13); + hq_generic_fenv_fx[n_band] = shl(tmp, add(exp, 1));/*1 */ + } + + + IF ( EQ_16(st_fx->bwidth_fx , FB)) + { + FOR ( n_band = 0; n_band < DIM_FB; n_band++ ) + { + tmp = add(hq_generic_fenv_fx[add(n_band,nenv)], Mean_env_fb_fx[n_band]);/*7 */ + L_tmp = L_mult(tmp, 21771);/*25 */ + L_tmp = L_shr(L_tmp, 9);/*16 */ + L_Extract(L_tmp, &exp, &tmp); + tmp = extract_l(Pow2(13, tmp)); + exp = sub(exp, 13); + hq_generic_fenv_fx[add(n_band,nenv)] = shl(tmp, add(exp, 1));/*2 */ + } + } + + return; +} + + diff --git a/lib_enc/swb_bwe_enc_hr_fx.c b/lib_enc/swb_bwe_enc_hr_fx.c new file mode 100644 index 0000000..3caaae1 --- /dev/null +++ b/lib_enc/swb_bwe_enc_hr_fx.c @@ -0,0 +1,787 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_enc_fx.h" /* Encoder static table prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +/* Values that Allow to Use Left/Right Shifting instead of Division & + 'and' (&) instead of 'modulo' (%) which is also a costly division. */ +#define NUM_TIME_SW_BLKS_SHIFT 2 +#define NUM_TIME_SW_BLKS_MASK (NUM_TIME_SWITCHING_BLOCKS-1) +#define WIDTH_BAND_SHIFT 3 + +/* Values for Max Scaling of Different Sub Function */ +#define DETECT_TRANSIENT_MAX_Q (11+2) +#define MAX_Q_NEW_INPUT 8 +#define NON_TRANSIENT_RESCALE_Q_GUARD 4 +#define TRANSIENT_RESCALE_Q_GUARD 0 +#define SPECTRUM_RESCALE_Q_GUARD 1 +#define MAX_Q_UPSCALING 6 +#define MAX_AVQ_COD_Q_IN 14 + +/*-------------------------------------------------------------------* + * en_band_quant_fx() + * + * Quantize the band envelop + *-------------------------------------------------------------------*/ + +static Word16 en_band_quant_fx(/* o : quantization index */ + Word16 *en_band, /* i/o: (un)quantized envelope value */ + const Word16 *env_code, /* i : envelope codebook */ + const Word16 N /* i : codebook dimension */ +) +{ + Word16 i, ind, tmp16; + Word32 L_err, L_maxerr; + + L_maxerr = 2147483647L; + move32(); + ind = 0; + move16(); + + FOR( i = 0; i < N; i++ ) + { + /* This is More Efficient */ + tmp16 = sub(en_band[0], env_code[i*2]); + L_err = L_mult0(tmp16, tmp16); + tmp16 = sub(en_band[1], env_code[i*2+1]); + L_err = L_mac0(L_err, tmp16, tmp16); + /* L_err = 0; move32(); + FOR (j = 0; j < 2; j++) + { + tmp16 = sub(en_band[j], env_code[i*2+j]); + L_err = L_mac0(L_err, tmp16, tmp16); + } */ + if (LT_32(L_err, L_maxerr)) + { + ind = i; + move16(); + } + L_maxerr = L_min(L_maxerr, L_err); + } + + en_band[0] = env_code[2*ind]; + move16(); + en_band[1] = env_code[2*ind+1]; + move16(); + + return( ind ); +} + +/*-------------------------------------------------------------------* + * swb_bwe_enc_hr_fx() + * + * HR SWB BWE encoder + *-------------------------------------------------------------------*/ +void swb_bwe_enc_hr_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *new_input_fx, /* i : input signal */ + Word16 new_input_fx_exp, /* i : Exponent of input signal */ + const Word16 input_frame, /* i : frame length */ + const Word16 coder_type, /* i : coding type */ + const Word16 unbits /* i : number of core unused bits */ +) +{ + Word16 i, j, k, nBits, nBits_total, nBits_block, Nsv, Nsv2, width_noncoded; + Word16 is_transient, pos; + Word16 x_norm_fx[NSV_MAX*(WIDTH_BAND+1)], x_norm1_fx[NSV_MAX*(WIDTH_BAND+1)]; + Word32 t_audio32[L_FRAME48k]; + Word16 *t_audio_fx, t_audio_fx_exp; + Word16 *t_audio_tmp_fx; /* same exponent as 't_audio_fx' */ + Word16 en_band_fx[N_BANDS_BWE_HR]; /* in Q9 */ + Word16 gain1_fx, exp1, gain2_fx, exp2; + Word32 L_gain_fx; + Word16 ind1, ind2; + Word16 nq[NSV_MAX], nq2[NSV_MAX]; + Word32 L_tmp, L_temp; + Word16 temp, temp2; + Word16 *ptr16; + Word16 min_env_fx; + Word32 L_en_noncoded_fx; /* in Q16 */ + Word16 en_noncoded_fx_exp; + Word16 scl; +#if (N_BANDS_BWE_HR*WIDTH_NONTRANS_FREQ_COEF) > L_FRAME48k + Word32 L_t_audio_tmp_fx[N_BANDS_BWE_HR*WIDTH_NONTRANS_FREQ_COEF]; +#else + Word32 L_t_audio_tmp_fx[L_FRAME48k]; +#endif + Word32 *ptr32; + + /*---------------------------------------------------------------------* + * initializations + *---------------------------------------------------------------------*/ + + /* Use 32 Bits Buffer to Store Two 16 Bits Vectors in Order to Save Stack Space */ + t_audio_fx = (Word16 *)&t_audio32[0]; + move16(); + t_audio_tmp_fx = (Word16 *)&t_audio32[L_FRAME48k/2]; + move16(); + + ind2 = 0; + move16();/* only to suppress warnings */ + Nsv2 = 0; + move16();/* only to suppress warnings */ + L_en_noncoded_fx = 0; + move16();/* only to suppress warnings */ + en_noncoded_fx_exp = 0; + move16();/* only to suppress warnings */ + gain2_fx = 0; + move16(); + + /* reset memories in case that last frame was a different technology */ + test(); + IF( EQ_16(st_fx->last_core_fx, HQ_CORE)||NE_16(st_fx->last_extl_fx,st_fx->extl_fx)) + { + set16_fx( st_fx->L_old_wtda_swb_fx, 0, L_FRAME48k ); + st_fx->Q_old_wtda = 0; + move16(); + } + + /* calculate SWB BWE bit-budget (extension layer bit-rate + AVQ unused bits from the core layer) */ + /* nBits = st->extl_brate/50 + unbits */ + nBits = add(320,unbits); /* st->extl_brate_fx is always 16kbps */ + nBits_total = nBits; + move16(); + + /*---------------------------------------------------------------------* + * detect transient frames + *---------------------------------------------------------------------*/ + /* Calc Room for Energy */ + temp = norm_l(st_fx->EnergyLT_fx); + /* Calc Max Exponent for 'new_input_fx' */ + temp = shr(temp, 1); + temp = add(temp, st_fx->EnergyLT_fx_exp); + temp = sub(temp, new_input_fx_exp); + /* Do not Upscale */ + temp = s_min(0, temp); + /* Limit Input to 'Q_DETECT_TRANSIENT_MAX_Q' (to avoid overflow in 'detect_transient_fx' for Energy Loop)*/ + exp1 = Find_Max_Norm16(new_input_fx, input_frame); + exp1 = sub(exp1, 15-DETECT_TRANSIENT_MAX_Q); + /* Downscale at Least by 'exp1' */ + temp = s_min(temp, exp1); + /* Set Exponent of Input */ + exp1 = add(new_input_fx_exp, temp); + + Copy_Scale_sig(new_input_fx, t_audio_fx, input_frame, temp); + /* Bring Energy in 2*Q'exp1' */ + st_fx->EnergyLT_fx = L_shl(st_fx->EnergyLT_fx, shl(sub(exp1, st_fx->EnergyLT_fx_exp), 1)); + + is_transient = detect_transient_fx( t_audio_fx, input_frame, coder_type, exp1, st_fx ); + st_fx->EnergyLT_fx_exp = exp1; + move16(); + + push_indice_fx( st_fx, IND_HR_IS_TRANSIENT, is_transient, 1 ); + + /*---------------------------------------------------------------------* + * OLA and MDCT + *---------------------------------------------------------------------*/ + + /* To Bring Back to Q15 + 'new_input_fx_exp' */ + /* Save Exponent of Memory (relative to Q15) */ + st_fx->Q_old_wtda = new_input_fx_exp; + move16(); + new_input_fx_exp=0; + wtda_fx( new_input_fx, &new_input_fx_exp, L_t_audio_tmp_fx, st_fx->L_old_wtda_swb_fx, + &st_fx->Q_old_wtda, ALDO_WINDOW, ALDO_WINDOW, input_frame ); + + direct_transform_fx(L_t_audio_tmp_fx, t_audio32, is_transient, input_frame, &new_input_fx_exp); + + /* Convert to 16 Bits (Calc Shift Required to Stay within MAX_Q_NEW_INPUT) */ + scl = sub(16+MAX_Q_NEW_INPUT, new_input_fx_exp); + /* Possible to Upscale? */ + IF (scl > 0) + { + /* Yes */ + /* Calc Room to Upscale */ + t_audio_fx_exp = Find_Max_Norm32(t_audio32, input_frame); + /* Stay within MAX_Q_NEW_INPUT */ + scl = s_min(t_audio_fx_exp, scl); + } + Copy_Scale_sig32_16(t_audio32, t_audio_fx, input_frame, scl); + t_audio_fx_exp = add(sub(new_input_fx_exp, 16), scl); + + IF( is_transient ) + { + nBits = -1; + move16(); /* is_transient flag */ + /* 'nBits_block = nBits_total / NUM_TIME_SWITCHING_BLOCKS' */ + nBits_block = shr(nBits_total, NUM_TIME_SW_BLKS_SHIFT); + /* 'nBits += nBits_total % NUM_TIME_SWITCHING_BLOCKS' */ + nBits = add(nBits, s_and(nBits_total, NUM_TIME_SW_BLKS_MASK)); + + /* set width of noncoded (blind estimated) spectrum */ + IF( EQ_16(st_fx->extl_fx, SWB_BWE_HIGHRATE)) + { + width_noncoded = L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF; + move16(); + } + ELSE /* st->extl == FB_BWE_HIGHRATE */ + { + width_noncoded = (2*END_FREQ_BWE_FULL_FB/50)/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF; + move16(); + } + + /* Find Max Scaling on Remaining Frequencies (after frequencies of non interest are zeroed) */ + temp = shr(input_frame, NUM_TIME_SW_BLKS_SHIFT); + scl = 99; + move16(); + ptr16 = &t_audio_fx[NUM_TRANS_START_FREQ_COEF]; + move16(); + FOR( k = 0; k < input_frame; k+=temp ) + { + /* from t_audio_fx[k..NUM_TRANS_START_FREQ_COEF+k-1] will be zeroed out */ + /* AND */ + /* from t_audio_fx[k+L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS..k+switching_block_length-1] will be zeroed out */ + /* Find Max Scaling on Remaining Frequencies */ + scl = s_min(Find_Max_Norm16(ptr16+k, L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS-NUM_TRANS_START_FREQ_COEF), scl); + IF (scl == 0) + { + BREAK; + } + } + /* Need to Keep at Least some Guard Bits */ + scl = s_max(0, sub(scl, TRANSIENT_RESCALE_Q_GUARD)); + /* Reduce if 't_audio_fx_exp' is Q14 or more (AVQ Cod overflow with more than Q14 Input) */ + scl = sub(scl, s_max(0, sub(add(scl, t_audio_fx_exp), MAX_AVQ_COD_Q_IN))); + /* Update Exponent of 't_audio_fx' */ + /* Here tne Signal is not Upscaled yet and some adjustement to 't_audio_fx_exp' will be used + until the signal is indeed upscaled by 'scl'. That Occurs at the 'normalization with global gain'. */ + t_audio_fx_exp = add(t_audio_fx_exp, scl); + + /*---------------------------------------------------------------------* + * transient frames: processing in blocks (subframes) + *---------------------------------------------------------------------*/ + + FOR( k = 0; k < NUM_TIME_SWITCHING_BLOCKS; k++ ) + { + nBits = add(nBits, nBits_block); + + temp = i_mult2(k, shr(input_frame, NUM_TIME_SW_BLKS_SHIFT)); + + /* Calculate Original Exponent (because the part of the signal that is used + to Calculate the Energy is not yet Scaled) */ + j = sub(t_audio_fx_exp, scl); + + /* compute energy of noncoded (14.4-20kHz) spectrum */ + IF( EQ_16(st_fx->extl_fx, FB_BWE_HIGHRATE)) + { + L_tmp = Calc_Energy_Autoscaled(t_audio_fx + add(temp, NUM_TRANS_END_FREQ_COEF), j, width_noncoded, &temp2); + L_en_noncoded_fx = Sqrt_Ratio32(L_tmp, temp2, L_deposit_l(width_noncoded), 0, &en_noncoded_fx_exp); + en_noncoded_fx_exp = sub(31, en_noncoded_fx_exp); + } + + /* keep only frequencies in interest */ + set16_fx( t_audio_fx + temp, 0, NUM_TRANS_START_FREQ_COEF ); + set16_fx( t_audio_fx + add(temp, L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS), 0, shr(sub(input_frame, L_FRAME32k), NUM_TIME_SW_BLKS_SHIFT) ); + + /*---------------------------------------------------------------------* + * global gain coding + *---------------------------------------------------------------------*/ + + /* compute and quantize global energy */ + /* Original float Code: 'gain = (float)sqrt( gain ) / (WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR)' */ + /* Put Divisor to Square to Move it Inside the Sqrt */ + /* So we can do 'sqrt( gain (WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR)^2)' */ + L_temp = L_mult0(WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR, WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR); + L_tmp = Calc_Energy_Autoscaled(t_audio_fx + add(temp, NUM_TRANS_START_FREQ_COEF), j, WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR, &temp2); + L_tmp = Sqrt_Ratio32(L_tmp, temp2, L_temp, /*L_temp is in Q0*/0, &exp2); + /* Put in Q16 */ + L_gain_fx = L_shr(L_tmp, sub(31-16, exp2)); /* 31: 'L_tmp' is already in Q31 */ + + ind1 = gain_quant_fx( &L_gain_fx, &gain1_fx, LG10_MIN_GLOB_GAIN_BWE_HR_Q14, LG10_MAX_GLOB_GAIN_BWE_HR_Q13, NBITS_GLOB_GAIN_BWE_HR, &exp1); + + push_indice_fx( st_fx, IND_HR_GAIN, ind1, NBITS_GLOB_GAIN_BWE_HR ); + nBits = sub(nBits, NBITS_GLOB_GAIN_BWE_HR); + + /* normalization with global gain */ + ptr16 = &t_audio_fx[add(NUM_TRANS_START_FREQ_COEF, temp)]; + move16(); + temp2 = negate(exp1); + gain2_fx = Invert16(gain1_fx, &temp2); + + /* Also Upscale by 'scl' */ + temp2 = sub(temp2, scl); + FOR( i=0; iextl_fx, SWB_BWE_HIGHRATE)) + { + /* st->extl == FB_BWE_HIGHRATE */ + /* 'en_noncoded /= (gain * en_band[N_BANDS_TRANS_BWE_HR-1])' */ + /* Normalize 'L_en_noncoded_fx' */ + j = norm_l(L_en_noncoded_fx); + L_en_noncoded_fx = L_shl(L_en_noncoded_fx, j); + en_noncoded_fx_exp = add(en_noncoded_fx_exp, j); + /* Calc Divisor */ + L_temp = L_mult0(gain1_fx, en_band_fx[N_BANDS_TRANS_BWE_HR-1]); + /* Normalize Divisor */ + temp2 = norm_l(L_temp); + L_temp = L_shl(L_temp, temp2); + temp2 = sub(add(9, temp2), exp1); /* Q9 for 'en_band_fx' */ + j = Invert16(round_fx(L_temp), &temp2); + L_temp = Mult_32_16(L_en_noncoded_fx, j); + temp2 = add(temp2, en_noncoded_fx_exp); + /* Put in Q16 */ + L_temp = L_shr(L_temp, temp2); + + IF( L_msu0(L_temp, BWE_HR_TRANS_EN_LIMIT1_FX_Q16, 1) < 0) + { + ind1 = 1; + move16(); + L_en_noncoded_fx = L_mult0(en_band_fx[N_BANDS_TRANS_BWE_HR-1], BWE_HR_TRANS_EN_LIMIT1_FX_Q16); + } + ELSE IF( L_msu0(L_temp, BWE_HR_TRANS_EN_LIMIT2_FX_Q16, 1) < 0) + { + ind1 = 2; + move16(); + L_en_noncoded_fx = L_mult0(en_band_fx[N_BANDS_TRANS_BWE_HR-1], BWE_HR_TRANS_EN_LIMIT2_FX_Q16); + } + ELSE IF( L_msu0(L_temp, BWE_HR_TRANS_EN_LIMIT3_FX_Q16, 1) < 0) + { + ind1 = 3; + move16(); + L_en_noncoded_fx = L_mult0(en_band_fx[N_BANDS_TRANS_BWE_HR-1], BWE_HR_TRANS_EN_LIMIT3_FX_Q16); + } + ELSE + { + ind1 = 0; + move16(); + L_en_noncoded_fx = L_deposit_h(en_band_fx[N_BANDS_TRANS_BWE_HR-1]); /* to Put in Q16+9 */ + } + + push_indice_fx( st_fx, IND_HR_HF_GAIN, ind1, NBITS_HF_GAIN_BWE_HR ); + nBits = sub(nBits, NBITS_HF_GAIN_BWE_HR); + } + ELSE + { + L_en_noncoded_fx = L_deposit_h(en_band_fx[N_BANDS_TRANS_BWE_HR-1]); + } + en_noncoded_fx_exp = 9+16; + move16(); /* 9 for 'en_band_fx', 16 for 'BWE_HR_TRANS_EN_LIMIT...' */ + + /*---------------------------------------------------------------------* + * AVQ coding (quantize normalized spectrum) + *---------------------------------------------------------------------*/ + + Nsv = (NUM_TRANS_END_FREQ_COEF - NUM_TRANS_START_FREQ_COEF) / WIDTH_BAND; + move16(); + AVQ_cod_fx(t_audio_fx + add(temp, NUM_TRANS_START_FREQ_COEF), x_norm_fx, nBits, Nsv, t_audio_fx_exp); + AVQ_encmux_fx(st_fx, st_fx->extl_fx, x_norm_fx, &nBits, Nsv, nq); + + } + } + ELSE /* !is_transient */ + { + /* subtract one bit for is_transient flag */ + nBits = sub(nBits, 1); + + /*---------------------------------------------------------------------* + * processing of normal (non-transient) frames + *---------------------------------------------------------------------*/ + + /* set width of noncoded (blind estimated) spectrum */ + IF( EQ_16(st_fx->extl_fx, SWB_BWE_HIGHRATE)) + { + width_noncoded = L_FRAME32k - NUM_NONTRANS_END_FREQ_COEF; + move16(); + } + ELSE /* st->extl == FB_BWE_HIGHRATE */ + { + width_noncoded = 2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_END_FREQ_COEF; + move16(); + } + + /* compute energy of noncoded (14.4-20kHz) spectrum */ + IF( EQ_16(st_fx->extl_fx, FB_BWE_HIGHRATE)) + { + L_tmp = Calc_Energy_Autoscaled(t_audio_fx + NUM_NONTRANS_END_FREQ_COEF, t_audio_fx_exp, width_noncoded, &temp2); + L_en_noncoded_fx = Sqrt_Ratio32(L_tmp, temp2, L_deposit_l(width_noncoded), 0, &en_noncoded_fx_exp); + en_noncoded_fx_exp = sub(31, en_noncoded_fx_exp); + } + + /* keep only frequencies in interest */ + set16_fx( t_audio_fx, 0, NUM_NONTRANS_START_FREQ_COEF ); + set16_fx( t_audio_fx + NUM_NONTRANS_END_FREQ_COEF, 0, sub(input_frame, NUM_NONTRANS_END_FREQ_COEF) ); + + /*---------------------------------------------------------------------* + * global gain coding + *---------------------------------------------------------------------*/ + + /* compute and quantize global gain */ + L_tmp = Calc_Energy_Autoscaled(t_audio_fx + NUM_NONTRANS_START_FREQ_COEF, t_audio_fx_exp, WIDTH_NONTRANS_FREQ_COEF*N_BANDS_BWE_HR, &temp2); + /* Original float Code: 'gain = (float)sqrt( gain ) / (WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR)' */ + /* Put Divisor to Square to Move it Inside the Sqrt */ + /* So we can do 'sqrt( gain (WIDTH_NONTRANS_FREQ_COEF*N_BANDS_BWE_HR)^2)' */ + L_temp = L_mult0(WIDTH_NONTRANS_FREQ_COEF*N_BANDS_BWE_HR, WIDTH_NONTRANS_FREQ_COEF*N_BANDS_BWE_HR); + L_tmp = Sqrt_Ratio32(L_tmp, temp2, L_temp, /*L_temp is in Q0*/0, &exp2); + /* Put in Q16 */ + L_gain_fx = L_shr(L_tmp, sub(31-16, exp2)); /* 31: 'L_tmp' is already in Q31 */ + ind1 = gain_quant_fx( &L_gain_fx, &gain1_fx, LG10_MIN_GLOB_GAIN_BWE_HR_Q14, LG10_MAX_GLOB_GAIN_BWE_HR_Q13, NBITS_GLOB_GAIN_BWE_HR, &exp1); + + push_indice_fx( st_fx, IND_HR_GAIN, ind1, NBITS_GLOB_GAIN_BWE_HR ); + nBits = sub(nBits, NBITS_GLOB_GAIN_BWE_HR); + + /* normalization with global gain */ + ptr16 = &t_audio_fx[NUM_NONTRANS_START_FREQ_COEF]; + move16(); + /* Find Max Scaling on Remaining Frequencies */ + temp2 = Find_Max_Norm16(ptr16, NUM_NONTRANS_END_FREQ_COEF-NUM_NONTRANS_START_FREQ_COEF); + temp2 = s_max(0, sub(temp2, NON_TRANSIENT_RESCALE_Q_GUARD)); + temp2 = s_min(temp2, MAX_Q_UPSCALING); + t_audio_fx_exp = add(t_audio_fx_exp, temp2); + temp2 = sub(temp2, exp1); + temp = Invert16(gain1_fx, &temp2); + + FOR( i=0; iextl_fx, SWB_BWE_HIGHRATE)) + { + /* st->extl == FB_BWE_HIGHRATE */ + /* 'en_noncoded /= (gain * min_env)' */ + /* Normalize 'L_en_noncoded_fx' */ + temp = norm_l(L_en_noncoded_fx); + L_en_noncoded_fx = L_shl(L_en_noncoded_fx, temp); + en_noncoded_fx_exp = add(en_noncoded_fx_exp, temp); + /* Calc Divisor */ + L_temp = L_mult0(gain1_fx, min_env_fx); + /* Normalize Divisor */ + temp2 = norm_l(L_temp); + L_temp = L_shl(L_temp, temp2); + temp2 = sub(add(9, temp2), exp1); /* Q9 for 'min_env_fx', 'exp1' for 'gain1' */ + j = Invert16(round_fx(L_temp), &temp2); + L_temp = Mult_32_16(L_en_noncoded_fx, j); + temp2 = add(temp2, en_noncoded_fx_exp); + /* Put in Q16 */ + L_temp = L_shr(L_temp, temp2); + IF( L_msu(L_temp, BWE_HR_NONTRANS_EN_LIMIT1_FX_Q15, 1) < 0) + { + ind1 = 1; + move16(); + /* 'en_noncoded = 0.5f * min_env * BWE_HR_NONTRANS_EN_LIMIT1' */ + L_en_noncoded_fx = L_mult0(min_env_fx, BWE_HR_NONTRANS_EN_LIMIT1_FX_Q15/2); + } + ELSE IF( L_msu(L_temp, BWE_HR_NONTRANS_EN_LIMIT2_FX_Q14, 2) > 0) + { + ind1 = 2; + move16(); + /* 'min_env * BWE_HR_NONTRANS_EN_LIMIT2' */ + L_en_noncoded_fx = L_mult(min_env_fx, BWE_HR_NONTRANS_EN_LIMIT2_FX_Q14); + } + ELSE IF( L_msu(L_temp, BWE_HR_NONTRANS_EN_LIMIT3_FX_Q15, 1) > 0) + { + ind1 = 3; + move16(); + L_en_noncoded_fx = L_mult0(min_env_fx, BWE_HR_NONTRANS_EN_LIMIT3_FX_Q15); + } + ELSE + { + ind1 = 0; + move16(); + L_en_noncoded_fx = L_mult0(min_env_fx, 16384); + } + + push_indice_fx( st_fx, IND_HR_HF_GAIN, ind1, NBITS_HF_GAIN_BWE_HR ); + nBits = sub(nBits, NBITS_HF_GAIN_BWE_HR); + } + ELSE + { + L_en_noncoded_fx = L_mult0(min_env_fx, 16384); + } + en_noncoded_fx_exp = 9+16-1; + move16(); /* 9 for 'en_band_fx', 16 for 'BWE_HR_TRANS_EN_LIMIT...' & -1 becaues of 'L_mult0' */ + + /*---------------------------------------------------------------------* + * AVQ coding (quantize normalized spectrum) + *---------------------------------------------------------------------*/ + + Nsv = shr(i, WIDTH_BAND_SHIFT); + AVQ_cod_fx(t_audio_tmp_fx/*same exponent as t_audio_fx*/, x_norm_fx, nBits, Nsv, t_audio_fx_exp); + AVQ_encmux_fx(st_fx, st_fx->extl_fx, x_norm_fx, &nBits, Nsv, nq); + + /*---------------------------------------------------------------------* + * second stage coding + *---------------------------------------------------------------------*/ + + test(); + IF( GE_16(nBits, 9 + NBITS_GLOB_GAIN_BWE_HR)&&sum16_fx(nq,Nsv)>0) + { + /* select spectrum of the second stage coding */ + ptr16 = &t_audio_fx[0]; + move16(); + FOR( i=0; iextl_fx, x_norm1_fx, &nBits, Nsv2, nq2 ); + } + + } /* 'ELSE' of ' IF( is_transient )' */ + + /* write unused bits */ + WHILE( nBits > 0 ) + { + i = s_min( nBits, 16 ); + push_indice_fx( st_fx, IND_UNUSED, 0, i ); + nBits = sub(nBits, i); + } + return; +} + diff --git a/lib_enc/swb_bwe_enc_lr_fx.c b/lib_enc/swb_bwe_enc_lr_fx.c new file mode 100644 index 0000000..6c7dfb0 --- /dev/null +++ b/lib_enc/swb_bwe_enc_lr_fx.c @@ -0,0 +1,1067 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" + +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "stl.h" +#include "basop_mpy.h" + +/*--------------------------------------------------------------------------* + * GetSubbandCorrIndex2_har() + * + * Finds the index of best correlation between highband (*inBuf) and lowband (*predBuf) for current subband of length (fLen) + *--------------------------------------------------------------------------*/ +static +Word16 GetSubbandCorrIndex2_har_fx( /* o : best correlation index */ + const Word32 *L_inBuf, /* i : target buffer (i.e., highband signal) : spectra */ + const Word16 fLen, /* i : window length */ + const Word16 *predBuf_fx, /* i : prediction buffer (i.e., lowband) : sspectra */ + const Word16 predBufLen, /* i : sspectra buffer size */ + const Word16 maxLag_fx, /* i : search length */ + const GainItem_fx *G_item_fx, /* i : */ + const Word16 nZero_fx, /* i : number of nonzero components used in */ + Word16 *prev_frame_bstindx_fx /* i : previous frame best Indices */ +) +{ + Word16 i, j; + Word16 bestIdx_fx; + Word32 L_lagCorr_sq; + Word32 L_lagEnergy; + + Word32 L_energy; + Word32 L_corr; + Word32 L_corr_sq; + + Word16 corr_sq_hi_fx; + Word32 L_corr_sq_tmp; + Word32 L_lagCorr_sq_tmp; + Word16 corr_sq_fx; + Word16 lagCorr_sq_fx; + Word32 L_energy_tmp; + Word32 L_lagEnergy_tmp; + Word16 energy_fx; + Word16 lagEnergy_fx; + + Word16 N1_fx, N2_fx; + Word16 exp_safe_e; + + Word16 exp_corr; + Word16 exp_energy; + + Word32 L_buf; + + Word16 ibuf_fx[L_FRAME32k]; + Word16 pbuf_fx[L_FRAME32k]; + Word16 *ptr_pbuf; + Word16 exp_shift; + + Word16 exp_norm; + + Word32 L_tmp; + + exp_safe_e = 4; + + L_tmp = L_deposit_l(0); + FOR(i=0; i Overflow */ + L_corr_sq = L_shl(L_corr, exp_norm); + corr_sq_hi_fx = extract_h(L_corr_sq); + L_corr_sq = L_mult(corr_sq_hi_fx, corr_sq_hi_fx); /* (((Qhi:Qsh+exp_norm_hi-16)+Qss+1)+exp_norm-16)*2+1 */ + L_corr_sq = L_shr(L_corr_sq, s_min(shl(exp_norm, 1), 31)); /* (QCorr-16)*2+1 */ + + IF(Overflow != 0) + { + L_corr_sq = 0x0L; + move16(); + Overflow = 0; + move16(); + } + + /* normalize for L_lagCorr_sq and L_corr_sq */ + L_buf = L_or(L_lagCorr_sq, L_corr_sq); + exp_corr = norm_l(L_buf); + L_corr_sq_tmp = L_shl(L_corr_sq, exp_corr); + L_lagCorr_sq_tmp = L_shl(L_lagCorr_sq, exp_corr); + corr_sq_fx = extract_h(L_corr_sq_tmp); + lagCorr_sq_fx = extract_h(L_lagCorr_sq_tmp); + + /* normalize for L_lagEnergy and L_energy */ + L_buf = L_or(L_lagEnergy, L_energy); + exp_energy = norm_l(L_buf); + L_energy_tmp = L_shl(L_energy, exp_energy); + L_lagEnergy_tmp = L_shl(L_lagEnergy, exp_energy); + energy_fx = extract_h(L_energy_tmp); + lagEnergy_fx = extract_h(L_lagEnergy_tmp); + + /*if( (double)lagCorr_sq*(double)energy < (double)corr_sq*(double)lagEnergy ) */ + IF (L_msu(L_mult(lagCorr_sq_fx, energy_fx), corr_sq_fx, lagEnergy_fx) < 0) + { + bestIdx_fx = i; + move16(); + L_lagCorr_sq = L_add(L_corr_sq, 0); + L_lagEnergy = L_add(L_energy, 0); + } + + } + predBuf_fx++; + ptr_pbuf++; + } + + test(); + IF( L_lagCorr_sq == 0x0 && *prev_frame_bstindx_fx < 0 ) + { + bestIdx_fx = 0x0; + move16(); + } + ELSE + { + if( L_lagCorr_sq == 0x0 ) + { + bestIdx_fx = *prev_frame_bstindx_fx; + move16(); + } + } + + *prev_frame_bstindx_fx = bestIdx_fx; + move16(); + + return bestIdx_fx; +} + +/*--------------------------------------------------------------------------* + * getswbindices_har() + * + * Finds the pulse index of best correlation between highband (*yos) and lowband (*y2) for two groups of length sbLen + *--------------------------------------------------------------------------*/ + +static void getswbindices_har_fx( + const Word32 *L_yos, /* i : original input spectrum */ + Word16 exp_refBuf, /* i : */ + Word16 *y2_fx, /* i : decoded spectrum */ + const Word16 nBands_search_fx, /* i : number of bands */ + Word16 *lagIndices_fx, /* o : pulse index */ + Word16 *prev_frame_bstindx_fx, /* i/o: prev frame index */ + const Word16 swb_lowband_fx, /* i : length of the LF spectrum */ + const Word16 *subband_offsets_fx, /* i : */ + const Word16 *sbWidth_fx, /* i : */ + const Word16 *subband_search_offset_fx /* i : */ +) +{ + Word16 i, j, k, sb, tmp; + Word16 *ptr_predBuf; + GainItem_fx Nbiggest_fx[(NB_SWB_SUBBANDS_HAR_SEARCH_SB)*N_NBIGGEST_PULSEARCH]; + Word16 n_nbiggestsearch_fx[NB_SWB_SUBBANDS_HAR]; + + Word16 search_offset_fx[NB_SWB_SUBBANDS_HAR_SEARCH_SB]; + Word16 nlags_fx[NB_SWB_SUBBANDS_HAR_SEARCH_SB]; + + Word16 low_freqsgnl_fx[L_FRAME32k]; /* Qy2 (sspectra) */ + + ptr_predBuf = y2_fx; + + /* Get the number of HF groups for performing Similarity search */ + FOR( sb = 0; sb < nBands_search_fx; sb++ ) + { + /*nlags[sb] = (short)pow(2, bits_lagIndices_mode0_Har[sb]); */ + nlags_fx[sb] = shl(1, bits_lagIndices_mode0_Har_fx[sb]); + } + + j = 0; + move16(); + FOR( sb=0; sb tmp; j-- ) + { + low_freqsgnl_fx[k] = y2_fx[j]; + k = add(k, 1); + } + } + /* correlation b/w HF spectrum Group1 of length sbLen and decoded LF spectrum */ + lagIndices_fx[sb] = (Word16)GetSubbandCorrIndex2_har_fx( L_yos + add(swb_lowband_fx, subband_offsets_fx[sb]), + sbWidth_fx[sb], + low_freqsgnl_fx, + add(sbWidth_fx[sb], nlags_fx[sb]), + nlags_fx[sb], Nbiggest_fx+(sb*N_NBIGGEST_PULSEARCH), + n_nbiggestsearch_fx[sb], &prev_frame_bstindx_fx[sb] + ); + } + + return; +} + +static Word16 GetSubbandCorrIndex2_pulsestep_fx( + const Word32 *L_inBuf, /* i: original input vector (highband) */ + const Word16 *predBuf_fx, /* i: spectrum smoothing vector */ + const Word16 *predBufMa_fx, /* i: moving averaged spectrum smoothing vector Q=Qss */ + const Word16 fLen, /* i: subband length of highband */ + const Word16 maxLag, /* i: number of search pulse number */ + const GainItem_fx *gi_fx, /* i: lag gain structure */ + const Word16 nZero, /* i: */ + const Word16 ssearch_buflim, /* i: length of search buffer */ + const Word16 *predBuf_ni_fx /* i: spectrum including noise smoothing vector */ +) +{ + Word16 i, j; + Word16 absPos_fx; + Word16 bestIdx_fx; + Word32 L_lagCorr_sq; + Word32 L_lagEnergy; + + const Word16 *ptr_predBuf; + const Word16 *ptr_predBuf_ni; + + Word32 L_energy; + Word32 L_corr; + Word16 corr_fx; + + Word32 L_corr_sq; + + + Word16 hiBuf_fx[L_FRAME32k]; + Word16 exp_norm_hi; + + Word16 exp_norm; + Word32 L_corr_sq_tmp; + Word32 L_lagCorr_sq_tmp; + Word16 corr_sq_fx; + Word16 lagCorr_sq_fx; + Word32 L_energy_tmp; + Word32 L_lagEnergy_tmp; + Word16 energy_fx; + Word16 lagEnergy_fx; + + Word16 ib_flag_fx; + + Word32 L_buf; + Word32 L_buf2; + Word32 L_temp; + + Word16 ssBuf_fx[L_FRAME32k]; + Word16 ssBuf_ni_fx[L_FRAME32k]; + Word16 *ptr_ssBuf_ni_fx; + Word16 exp_norm_ss; + + set16_fx(hiBuf_fx, 0x0, L_FRAME32k); + set16_fx(ssBuf_fx, 0x0, L_FRAME32k); + + ib_flag_fx = 0; + move16(); + + absPos_fx = 0; + move16(); + bestIdx_fx = -1; + move16(); + L_lagCorr_sq = L_deposit_l(0); + L_lagEnergy = 0x7FFFFFFFL; + move32(); + + ptr_predBuf = predBuf_fx; + ptr_predBuf_ni = predBuf_ni_fx; + + /* This part must be computed on parent function. */ + exp_norm_ss = 2; + move16(); + + j = add(ssearch_buflim,fLen); + FOR (i=0; i Overflow */ + L_corr_sq = L_shl(L_corr, exp_norm); + corr_fx = extract_h(L_corr_sq); + L_corr_sq = L_mult(corr_fx, corr_fx); /* (((Qhi:Qsh+exp_norm_hi-16)+Qss+1)+exp_norm-16)*2+1 */ + L_corr_sq = L_shr(L_corr_sq, s_min(shl(exp_norm, 1), 31)); /* (QCorr-16)*2+1 */ + + /*if( (lagCorr_sq == 0.0f && corr_sq == 0.0f) || (double)lagCorr_sq*(double)energy < (double)corr_sq*(double)lagEnergy ) */ + /*{ */ + /* bestIdx = i; */ + /* bestAbsPos = absPos; */ + /* lagCorr_sq = corr_sq; */ + /* lagCorr = corr; */ + /* lagEnergy = energy; */ + /*} */ + /* normalize for L_lagCorr_sq and L_corr_sq */ + L_buf = L_or(L_lagCorr_sq, L_corr_sq); + exp_norm = norm_l(L_buf); /* overflow allowed */ + L_corr_sq_tmp = L_shl(L_corr_sq, exp_norm); + L_lagCorr_sq_tmp = L_shl(L_lagCorr_sq, exp_norm); + corr_sq_fx = extract_h(L_corr_sq_tmp); + lagCorr_sq_fx = extract_h(L_lagCorr_sq_tmp); + + /* normalize for L_lagEnergy and L_energy */ + L_buf = L_or(L_lagEnergy, L_energy); + exp_norm = norm_l(L_buf); /* overflow allowed */ + L_energy_tmp = L_shl(L_energy, exp_norm); + L_lagEnergy_tmp = L_shl(L_lagEnergy, exp_norm); + energy_fx = extract_h(L_energy_tmp); + lagEnergy_fx = extract_h(L_lagEnergy_tmp); + + L_buf = L_or(L_lagCorr_sq, L_corr_sq); + L_buf2 = L_msu(L_mult(lagCorr_sq_fx, energy_fx), corr_sq_fx, lagEnergy_fx); + test(); + IF( L_buf == 0 || L_buf2 < 0 ) + { + bestIdx_fx = i; + move16(); + L_lagCorr_sq = L_add(L_corr_sq, 0); + L_lagEnergy = L_add(L_energy, 0); + } + } + ptr_predBuf++; + ptr_ssBuf_ni_fx++; + ptr_predBuf_ni++; + absPos_fx++; + + WHILE( *ptr_predBuf == 0 && LT_16(absPos_fx, ssearch_buflim)) + { + ptr_predBuf++; + ptr_ssBuf_ni_fx++; + ptr_predBuf_ni++; + absPos_fx = add(absPos_fx, 1); + } + + IF( GE_16(absPos_fx, ssearch_buflim)) + { + if( EQ_16(bestIdx_fx, -1)) + { + ib_flag_fx = 1; + move16(); + } + + BREAK; + } + } + + IF( EQ_16(ib_flag_fx, 1)) + { + bestIdx_fx = 0; + move16(); + } + + return bestIdx_fx; +} + +static void GetSWBIndices_fx( + const Word16 *predBuf_fx, /* i : low-frequency band */ + /*const Word16 Qss,*/ /* i : Q value of predBuf_fx */ + const Word32 *L_targetBuf, /* i : SWB MDCT coeff. */ + const Word16 Qsh, /* i : Q value of L_targetBuf */ + const Word16 nBands_search, /* i : number of search subbands */ + const Word16 *sbWidth, /* i : subband lengths */ + Word16 *lagIndices, /* o : selected lags for subband coding */ + const Word16 predBufLen, /* i : low-frequency band length */ + GainItem_fx *gi_fx, /* o : most representative region */ + const Word16 *subband_offsets, /* o : N biggest components */ + Word16 *predBuf_ni_fx /* i : low-frequency band filled noise */ +) +{ + Word16 j; + Word16 sb, tmp; + Word16 sbLen; + Word16 n_nbiggestsearch_fx[NB_SWB_SUBBANDS]; + Word16 ssearch_buflim_fx; + Word16 search_offset_fx[NB_SWB_SUBBANDS]; + Word16 nlags_fx[NB_SWB_SUBBANDS]; + + Word16 exp_refBuf; + Word16 sspectra_ma_fx[L_FRAME32k]; + + + Word32 L_temp; + + + /* Initializations */ + exp_refBuf = Qsh; + + j = 0; + move16(); + FOR (sb = 0; sb < nBands_search; sb++) + { + FindNBiggest2_simple_fx_har( L_targetBuf + subband_offsets[sb], exp_refBuf, gi_fx+j, sbWidth[sb], &n_nbiggestsearch_fx[sb], N_NBIGGEST_PULSEARCH ); + + j = add(j, N_NBIGGEST_PULSEARCH); + move16(); + } + + /* Selection of most representative subband (full search) */ + FOR ( sb = 0; sb < nBands_search; sb++ ) + { + nlags_fx[sb] = shl(1, bits_lagIndices_modeNormal_fx[sb]); + move16(); + } + + FOR ( sb = 0; sb < nBands_search; sb++ ) + { + search_offset_fx[sb] = subband_search_offsets_fx[sb]; + move16(); + } + + sspectra_ma_fx[0] = add(shr(predBuf_ni_fx[0],1), shr(predBuf_ni_fx[1],1)); + tmp = sub(predBufLen, 1); + FOR( sb=1; sb < tmp; sb++ ) + { + /*sspectra_ma[sb] = (predBuf[sb-1] + predBuf[sb] + predBuf[sb+1])/3.0f; */ + L_temp = L_mult(predBuf_ni_fx[sb], 10922); /* 10922 = 0.33333 (Q15) */ + L_temp = L_add(L_temp, L_mult(predBuf_ni_fx[sb-1], 10922)); + L_temp = L_add(L_temp, L_mult(predBuf_ni_fx[sb+1], 10922)); /* Qss+15+1 */ + sspectra_ma_fx[sb] = round_fx(L_temp); + } + sspectra_ma_fx[sb] = add(shr(predBuf_ni_fx[sb-1],1), shr(predBuf_ni_fx[sb],1)); + + /* Partial search for rest of subbands except the last which is fixed */ + FOR ( sb=0; sb 0x0 ) + { + L_temp = L_deposit_l(sqrt_fx); + + exp = norm_l(L_temp); + frac = Log2_norm_lc(L_shl(L_temp, exp)); + exp = sub(30, exp); + exp = sub(exp, Qsqrt); + L_temp = L_Comp(exp, frac); + + L_temp = Mpy_32_16_1(L_temp, 19728); /* log(2)/log(10)=.30102999566398119521 = 19728.3(Q16) Q(0+16+1)=Q17 */ + L_temp = L_shl(L_temp, 13); /* Q17+13=30 30-16=14 */ + g_fx = round_fx(L_temp); + } + + gqlevs_fx = 4; + move16(); + dmin_fx = 32767; + move16(); + imin_fx = 0; + move16(); + + FOR (i = 0; i < gqlevs_fx; i++) + { + d_fx = abs_s(g_fx - gain_table_SWB_BWE_fx[i]); + IF (LT_16(d_fx, dmin_fx)) + { + dmin_fx = d_fx; + move16(); + imin_fx = i; + move16(); + } + } + } + + push_indice_fx( st_fx,IND_NOISEG, imin_fx, 2); + + /*g=(float) pow (10.0f,gain_table[imin]);*/ + L_temp = L_mult(gain_table_SWB_BWE_fx[imin_fx], 27213); /* Q14+Q13+1=Q28 log(10)/log(2)=3.3219 27213.23(Q13) */ + L_temp = L_shr(L_temp, 12); /* Q28-Q12 -> Q16 */ + temp_lo = L_Extract_lc(L_temp, &temp_hi); + Qg = sub(14, temp_hi); + g_fx = extract_l(Pow2(14, temp_lo)); + g_fx = shl(g_fx, sub(11, Qg)); + + ton_ene_est_fx( + L_xSynth_har, QsL, L_be_tonal, QbeL, L_band_energy, Qbe, + band_start, band_end, band_width, fLenLow, fLenHigh, bands, har_bands, g_fx, + pk_sf_fx, Qss, pul_res_fx + ); + + return; +} + +static void EncodeSWBSubbands_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word32 *L_spectra, /* i/o: MDCT domain spectrum */ + Word16 QsL, /* i : Q value for L_spectra */ + const Word16 fLenLow_fx, /* i : lowband length */ + const Word16 fLenHigh_fx, /* i : highband length */ + const Word16 nBands_fx, /* i : number of subbands */ + const Word16 nBands_search_fx, /* i : number of subbands to be searched for BWE */ + const Word16 *sbWidth_fx, /* i : subband lengths */ + const Word16 *subband_offsets_fx, /* i : Subband offset for BWE */ + Word16 *lagIndices_fx, /* o : lowband index for each subband */ + const Word16 BANDS_fx, /* i : noise estimate from WB part */ + const Word16 *band_start_fx, /* i : Number subbands/Frame */ + const Word16 *band_end_fx, /* i : Band Start of each SB */ + Word32 *L_band_energy, /* i : Band end of each SB, :Qbe */ + Word16 Qbe, /* i : Q value of band energy */ + const Word16 *p2a_flags_fx, /* i : BAnd energy of each SB */ + const Word16 hqswb_clas_fx, /* i : lowband synthesis */ + Word16 *prev_frm_index_fx, /* i : clas information */ + const Word16 har_bands_fx, /* i/o: Index of the previous Frame */ + const Word16 *subband_search_offset_fx,/* i : Number of harmonic LF bands */ + Word16 *prev_frm_hfe2_fx, /* i/o: */ + Word16 *prev_stab_hfe2_fx, /* i/o: */ + const Word16 band_width_fx[], /* i : band width */ + const Word32 L_spectra_ni[], /* i : Qs noise injected spectra */ + Word16 *ni_seed_fx /* i/o: random seed */ +) +{ + Word16 i, k; + Word16 sspectra_fx[L_FRAME32k]; + Word16 sspectra_ni_fx[L_FRAME32k]; + Word16 sspectra_diff_fx[L_FRAME32k]; + Word16 Qss; /* Q value of Smoothed Spectrum low-subband */ + Word32 L_be_tonal[SWB_HAR_RAN1]; /* Q */ + Word16 ss_min_fx; /* Qss */ + Word32 L_th_g[NB_SWB_SUBBANDS]; + Word16 QbeL; + GainItem_fx pk_sf_fx[(NB_SWB_SUBBANDS)*8]; + Word16 pul_res_fx[NB_SWB_SUBBANDS]; + + GainItem_fx Nbiggest_fx[NB_SWB_SUBBANDS*N_NBIGGEST_PULSEARCH]; + + Word32 L_xSynth_har[L_FRAME32k]; /* Qs */ + + Word16 lagGains_fx[NB_SWB_SUBBANDS]; + Word16 QlagGains[NB_SWB_SUBBANDS]; + Word16 har_freq_est1,har_freq_est2; + Word16 flag_dis; + Word16 pos_max_hfe2; + + har_freq_est1 = 0; + move16(); + har_freq_est2 = 0; + move16(); + flag_dis = 1; + move16(); + pos_max_hfe2 = 0; + move16(); + + set16_fx(sspectra_fx, 0, fLenLow_fx); + set16_fx(sspectra_ni_fx, 0, fLenLow_fx); + set32_fx(L_xSynth_har, 0, L_FRAME32k); + set16_fx(pul_res_fx,0,NB_SWB_SUBBANDS); + + + IF( EQ_16(hqswb_clas_fx, HQ_HARMONIC)) + { + pos_max_hfe2 = har_est_fx( L_spectra, fLenLow_fx, &har_freq_est1, &har_freq_est2, &flag_dis, prev_frm_hfe2_fx, subband_search_offset_fx, sbWidth_fx, prev_stab_hfe2_fx ); + noise_extr_corcod_fx(L_spectra, L_spectra_ni, sspectra_fx, sspectra_diff_fx, sspectra_ni_fx, fLenLow_fx , st_fx->prev_hqswb_clas_fx ,&st_fx->prev_ni_ratio_fx, &Qss); + /* Find best indices for each group */ + getswbindices_har_fx( + L_spectra, + QsL, sspectra_ni_fx, + nBands_search_fx, lagIndices_fx, prev_frm_index_fx, fLenLow_fx, subband_offsets_fx, sbWidth_fx , subband_search_offset_fx); + + /* Write the indices into the bitstream */ + FOR (k = 0; k < nBands_search_fx; k++) + { + push_indice_fx( st_fx, IND_LAGINDICES, lagIndices_fx[k], bits_lagIndices_mode0_Har_fx[k]); + } + + IF ( flag_dis == 0 ) + { + test(); + if ( NE_16(har_freq_est2, SWB_HAR_RAN1)||NE_16(har_freq_est2,*prev_frm_hfe2_fx)) + { + har_freq_est2 = add(har_freq_est2, lagIndices_fx[0]); + move16(); + } + } + + gethar_noisegn_fx( + st_fx, + L_spectra, QsL, sspectra_diff_fx, Qss, L_xSynth_har, + sbWidth_fx, lagIndices_fx, BANDS_fx, har_bands_fx, fLenLow_fx, fLenHigh_fx, + subband_offsets_fx, subband_search_offset_fx, band_start_fx, band_end_fx, band_width_fx, + L_band_energy, Qbe, L_be_tonal, &QbeL, sspectra_fx, + har_freq_est2, pos_max_hfe2, pul_res_fx, pk_sf_fx); + + + Gettonl_scalfact_fx( + L_xSynth_har, QsL, L_spectra_ni, fLenLow_fx, fLenHigh_fx, har_bands_fx, BANDS_fx, L_band_energy, Qbe, band_start_fx, band_end_fx, + p2a_flags_fx, L_be_tonal, QbeL, pk_sf_fx ,Qss, pul_res_fx); + + IF( flag_dis == 0 ) + { + *prev_frm_hfe2_fx = 0; + move16(); + } + ELSE + { + *prev_frm_hfe2_fx = har_freq_est2; + move16(); + } + + FOR( k = BANDS_fx - NB_SWB_SUBBANDS; k < BANDS_fx; k++ ) + { + FOR( i = band_start_fx[k]; i <= band_end_fx[k]; i++ ) + { + L_spectra[i] = L_xSynth_har[i-fLenLow_fx]; + move32(); /* QsL */ + } + } + } + ELSE + { + ss_min_fx = spectrumsmooth_noiseton_fx( + L_spectra, /*QsL,*/ L_spectra_ni, sspectra_fx, sspectra_diff_fx, sspectra_ni_fx, &Qss, fLenLow_fx, ni_seed_fx); + + /* Get lag indices */ + GetSWBIndices_fx( sspectra_fx, /*Qss,*/ + L_spectra + fLenLow_fx, QsL, + nBands_fx, sbWidth_fx, lagIndices_fx, fLenLow_fx, + Nbiggest_fx, subband_offsets_fx, sspectra_fx + ); + + /* Bitstream operations */ + FOR(k=0; k QsL */ + } + } + + GetSynthesizedSpecThinOut_fx(sspectra_ni_fx, Qss, L_xSynth_har, QsL, nBands_fx, sbWidth_fx, lagIndices_fx, lagGains_fx, QlagGains, fLenLow_fx); + + /*Level adjustment for the missing bands*/ + noiseinj_hf_fx( + L_xSynth_har, QsL, L_th_g, L_band_energy, Qbe, + st_fx->prev_En_sb_fx, + p2a_flags_fx, BANDS_fx, band_start_fx, band_end_fx, fLenLow_fx, fLenHigh_fx); + + + FOR( k = BANDS_fx - NB_SWB_SUBBANDS; k < BANDS_fx; k++ ) + { + IF( p2a_flags_fx[k] == 0 ) + { + FOR( i = band_start_fx[k]; i <= band_end_fx[k]; i++ ) + { + L_spectra[i] = L_xSynth_har[i-fLenLow_fx]; + move32(); /* Qob */ + } + } + ELSE + { + FOR( i = band_start_fx[k]; i <= band_end_fx[k]; i++ ) + { + L_spectra[i] = L_spectra_ni[i]; + move32(); + } + } + } + } + + return; +} + +void swb_bwe_enc_lr_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 L_m_core[], /* i : lowband synthesis */ + Word16 QsL, /* i : Q value */ + const Word32 L_m_orig[], /* i/o: scaled orig signal (MDCT) */ + Word32 L_m[], /* o : highband synthesis with lowband zeroed */ + const Word32 L_total_brate, /* i : total bitrate for selecting subband pattern */ + Word16 BANDS_fx, /* i : Total number of Subbands in a frame */ + Word16 *band_start_fx, /* i : band start of each SB */ + Word16 *band_end_fx, /* i : band end of each SB */ + Word32 *L_band_energy, /* i : band_energy of each SB */ + Word16 Qbe, /* i : Q value of band energy */ + Word16 *p2a_flags_fx, /* i : HF tonal indicator */ + const Word16 hqswb_clas_fx, /* i : HQ_NORMAL2 or HQ_HARMONIC mode */ + Word16 lowlength_fx, /* i : lowband length */ + Word16 highlength_fx, /* i : highband length */ + Word16 *prev_frm_index_fx, /* i/o: previous frame lag index for harmonic mode */ + const Word16 har_bands_fx, /* i : Number of LF harmonic bands */ + Word16 *prev_frm_hfe2, /* i/o: */ + Word16 *prev_stab_hfe2, /* i/o: */ + const Word16 band_width_fx[], /* i : band_width information */ + const Word32 L_y2_ni[], /* i : band_width information */ + Word16 *ni_seed_fx /* i/o: random seed for search buffer NI */ +) +{ + Word16 k; + Word16 nBands_fx; + Word16 nBands_search_fx; + Word16 wBands_fx[NB_SWB_SUBBANDS]; + Word16 lagIndices_fx[NB_SWB_SUBBANDS]; + Word16 swb_lowband_fx, swb_highband_fx, allband_fx; + + const Word16 *subband_offsets_fx; + const Word16 *subband_search_offset_fx; + + Word32 *p_L_m; + + subband_search_offset_fx = subband_search_offsets_13p2kbps_Har_fx; + subband_offsets_fx = subband_offsets_sub5_13p2kbps_Har_fx; + + hf_parinitiz_fx(L_total_brate,hqswb_clas_fx,lowlength_fx,highlength_fx,wBands_fx,&subband_search_offset_fx,&subband_offsets_fx,&nBands_fx,&nBands_search_fx,&swb_lowband_fx,&swb_highband_fx); + allband_fx = add(swb_lowband_fx, swb_highband_fx); + move16(); + + /* Prepare m[], low part from WB core, high part from 32k input */ + Copy32( L_m_core, L_m, swb_lowband_fx ); + Copy32(&L_m_orig[swb_lowband_fx], &L_m[swb_lowband_fx], swb_highband_fx ); + + EncodeSWBSubbands_fx( + st_fx, + L_m, QsL, + swb_lowband_fx, swb_highband_fx, nBands_fx, nBands_search_fx, wBands_fx, subband_offsets_fx, + lagIndices_fx, + BANDS_fx, band_start_fx, band_end_fx, + L_band_energy, Qbe, + p2a_flags_fx, + hqswb_clas_fx, prev_frm_index_fx, har_bands_fx, subband_search_offset_fx, + prev_frm_hfe2, prev_stab_hfe2, + band_width_fx, L_y2_ni, ni_seed_fx + ); + + p_L_m = &L_m[sub(allband_fx, 1)]; + *p_L_m = Mult_32_16(*p_L_m, 2028); + move32(); + p_L_m--; /* 0.0625 = 2028 (Q15) */ + *p_L_m = Mult_32_16(*p_L_m, 4096); + move32(); + p_L_m--; /* 0.125 = 4096 (Q15) */ + *p_L_m = Mult_32_16(*p_L_m, 8192); + move32(); + p_L_m--; /* 0.25 = 8192 (Q15) */ + *p_L_m = Mult_32_16(*p_L_m, 16384); + move32(); + p_L_m--; /* 0.5 = 16384 (Q15) */ + + /* set low frequencies to zero */ + FOR ( k = 0; k < swb_lowband_fx; k++ ) + { + L_m[k] = L_deposit_l(0); + } + + return; +} diff --git a/lib_enc/swb_pre_proc_fx.c b/lib_enc/swb_pre_proc_fx.c new file mode 100644 index 0000000..5065177 --- /dev/null +++ b/lib_enc/swb_pre_proc_fx.c @@ -0,0 +1,435 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "stl.h" +#include "basop_util.h" + +#include + +/*========================================================================*/ +/* FUNCTION : wb_pre_proc_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : Resampling of input signal when input signal sample rate */ +/* is above 16kHz */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Encoder_State_fx *st_fx : Encoder State Structure */ +/* _ (Word16*) input : original input signal */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) new_wb_speech : original input signal at 16kHz Q-1 */ +/*------------------------------------------------------------------------*/ + +/* st_fx->old_wtda_wb_fx */ +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ + +void wb_pre_proc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *new_inp_resamp16k, /* i : original input signal in Q-1 */ + Word16 *hb_speech /* o : HB target signal (6-8kHz) at 16kHz in Q-1 */ +) +{ + Word16 Sample_Delay_WB_BWE; + Word16 ramp_flag; + Word16 old_input[NS2SA(16000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME16k]; + Word16 *highband_new_speech; + Word16 highband_old_speech[(L_LOOK_12k8+L_SUBFR+L_FRAME)*5/16]; + Word16 temp_buf[320]; + Word16 Q_wb_sp, i, max_wb; + Word16 fSwitchFromIO = 0; + Word32 temp1 = 0; + Word32 temp2 = 0; + + test(); + test(); + test(); + test(); + test(); + test(); + IF ( (EQ_32(st_fx->last_total_brate_fx, ACELP_6k60))|| + (EQ_32(st_fx->last_total_brate_fx, ACELP_8k85)) || + (EQ_32(st_fx->last_total_brate_fx, ACELP_12k65)) || + (EQ_32(st_fx->last_total_brate_fx, ACELP_14k25)) || + (EQ_32(st_fx->last_total_brate_fx, ACELP_15k85)) || + (GE_32(st_fx->last_total_brate_fx, ACELP_18k25) && LE_32(st_fx->last_total_brate_fx, ACELP_23k85)) ) + { + fSwitchFromIO = 1; + move16(); + } + + set16_fx( old_input, 0, NS2SA_fx2(16000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME16k ); + + max_wb = 1; + move16(); + FOR (i = 0; i < L_FRAME16k; i++ ) + { + max_wb = s_max(max_wb, abs_s(new_inp_resamp16k[i])); + } + Q_wb_sp = norm_s(max_wb); + + Copy_Scale_sig(new_inp_resamp16k, temp_buf, L_FRAME16k, -3); + temp1 = L_mac0(temp1, temp_buf[0], temp_buf[0]); + FOR (i = 1; i < L_FRAME16k; i++) + { + temp1 = L_mac0(temp1, temp_buf[i], temp_buf[i]); + temp2 = L_mac0(temp2, temp_buf[i-1], temp_buf[i]); + } + + if( temp2 < Mult_32_16(temp1, 31129 /*0.95f*/) ) + { + Q_wb_sp = sub(Q_wb_sp, 3); /* leave 3 bit headroom */ + } + Copy_Scale_sig(new_inp_resamp16k, temp_buf, L_FRAME16k, Q_wb_sp); + Scale_sig(st_fx->decim_state1_fx, (2*ALLPASSSECTIONS_STEEP+1), Q_wb_sp); + Scale_sig(st_fx->decim_state2_fx, (2*ALLPASSSECTIONS_STEEP+1), Q_wb_sp); + /* temp_buf, and the memory states are in Q_wb_sp */ + + test(); + test(); + IF ( EQ_16(st_fx->extl_fx, WB_BWE)||EQ_16(st_fx->extl_fx,WB_TBE)||st_fx->igf!=0) + { + ramp_flag = 0; + + test(); + test(); + test(); + test(); + IF( (NE_16(st_fx->last_extl_fx, WB_TBE)&&NE_16(st_fx->last_extl_fx,WB_BWE)&&st_fx->igf==0)|| + (st_fx->igf != 0 && fSwitchFromIO != 0) ) + { + ramp_flag = 1; + } + + IF ( !st_fx->ppp_mode_fx) + { + /* temp_buf is in Q_wb_sp + hb_speech and the two decimator memories are in Q_wb_sp */ + flip_spectrum_and_decimby4_fx( temp_buf, hb_speech, L_FRAME16k, st_fx->decim_state1_fx, st_fx->decim_state2_fx, ramp_flag ); + + /* rescale the hb_speech and memories back to Q-1 to keep the downstream BWE coding unaffected */ + Scale_sig(hb_speech, L_FRAME16k/4, -Q_wb_sp); + Scale_sig(st_fx->decim_state1_fx, (2*ALLPASSSECTIONS_STEEP+1), -Q_wb_sp); + Scale_sig(st_fx->decim_state2_fx, (2*ALLPASSSECTIONS_STEEP+1), -Q_wb_sp); + + IF( NE_16(st_fx->extl_fx, WB_TBE)) + { + /* Update the previous wideband speech buffer in case of a WB_BWE frame */ + Sample_Delay_WB_BWE = (L_LOOK_12k8 + L_SUBFR) * 5/16; + + highband_new_speech = highband_old_speech + Sample_Delay_WB_BWE; + Copy( hb_speech, highband_new_speech, L_FRAME16k / 4 ); + Copy( highband_old_speech + L_FRAME16k / 4, st_fx->old_speech_wb_fx, Sample_Delay_WB_BWE ); + } + } + } + ELSE + { + set16_fx( st_fx->decim_state1_fx, 0, (2*ALLPASSSECTIONS_STEEP+1) ); + set16_fx( st_fx->decim_state2_fx, 0, (2*ALLPASSSECTIONS_STEEP+1) ); + set16_fx( st_fx->old_speech_wb_fx, 0, (L_LOOK_12k8 + L_SUBFR) * 5/16 ); + } + + /* st->old_input_wb and st->old_wtda_wb must be updated each frame, or there are often some clicks during WB TBE <-> WB BWE switching */ + test(); + test(); + test(); + IF ( (NE_16(st_fx->extl_fx, WB_BWE)||(EQ_16(st_fx->extl_fx,WB_BWE)&&LE_32(st_fx->total_brate_fx,ACELP_8k00)))&&!st_fx->ppp_mode_fx) + { + Sample_Delay_WB_BWE = NS2SA_fx2( 16000, DELAY_FD_BWE_ENC_12k8_NS ); + + Copy( new_inp_resamp16k, &old_input[Sample_Delay_WB_BWE], L_FRAME16k ); + Copy( st_fx->old_input_wb_fx, old_input, Sample_Delay_WB_BWE ); + Copy( new_inp_resamp16k + L_FRAME16k - Sample_Delay_WB_BWE, st_fx->old_input_wb_fx, Sample_Delay_WB_BWE ); + Copy( old_input, st_fx->L_old_wtda_swb_fx, L_FRAME16k ); + } + return; +} + + +/*========================================================================*/ +/* FUNCTION : swb_pre_proc_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : Calculate the 6 to 14 kHz (or 7.5 - 15.5 kHz) */ +/* SHB target signal for SWB TBE or SWB BWE coding */ +/* Common SWB TBE and SWB BWE pre-processing */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Encoder_State_fx *st_fx : Encoder State Structure Q0 */ +/* _ (Word16*) input_fx : original input signal Q0 */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) new_swb_speech_fx : original input signal at 16kHz Q0 */ +/* _ (Word16*) shb_speech_fx : original input signal at 16kHz Q0 */ +/*------------------------------------------------------------------------*/ + +/* st_fx->old_input_fx */ +/* st_fx->old_wtda_shb_fx */ +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ + +void swb_pre_proc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *input_fx, /* i : original input signal */ + Word16 *new_swb_speech_fx, /* o : original input signal at 32kHz */ + Word16 *shb_speech_fx, /* o : SHB target signal (6-14kHz) at 16kHz */ + Word16 *Q_shb_spch, + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : real CLDFB buffer for target synthesis */ + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : imag CLDFB buffer for target synthesis */ + const CLDFB_SCALE_FACTOR *cldfbScale /* i : scale data of real and imag CLDFB buffers */ +) +{ + Word16 Sample_Delay_SWB_BWE, delay; + Word16 inner_frame; + UWord16 inner_Fs; + Word16 old_input_fx[NS2SA(48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME48k]; + Word16 spchTmp_fx[L_FRAME32k]; + Word16 i; + Word16 startB, endB; + Word16 j; + Word32 *realBufferFlipped[CLDFB_NO_COL_MAX]; + Word32 *imagBufferFlipped[CLDFB_NO_COL_MAX]; + Word32 realBufferTmp[CLDFB_NO_COL_MAX][20]; + Word32 imagBufferTmp[CLDFB_NO_COL_MAX][20]; + Word32 cldfbWorkBuffer[256]; + Word16 ts, nB, uB; + /* Highband energy computation using CLDFB */ + Word32 CldfbHB_ener; + Word16 realQ_neg1, imagQ_neg1, exp, Cldfbtemp1; + + FOR( j=0; j < CLDFB_NO_COL_MAX; j++ ) + { + set32_fx(realBufferTmp[j], 0, 20); + set32_fx(imagBufferTmp[j], 0, 20); + realBufferFlipped[j] = realBufferTmp[j]; + imagBufferFlipped[j] = imagBufferTmp[j]; + } + + set16_fx( old_input_fx, 0, NS2SA_fx2(48000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME48k ); + + IF( EQ_32(st_fx->input_Fs_fx, 32000)) + { + Copy(input_fx, new_swb_speech_fx, L_FRAME32k); /*Q0 */ + test(); + test(); + IF( NE_16(st_fx->last_extl_fx, SWB_BWE)&&NE_16(st_fx->last_extl_fx,FB_BWE)&&NE_16(st_fx->extl_fx,SWB_BWE_HIGHRATE)) + { + Sample_Delay_SWB_BWE = NS2SA_fx2( 32000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); + Copy( st_fx->old_fdbwe_speech_fx, &old_input_fx[Sample_Delay_SWB_BWE], L_FRAME32k ); + set16_fx( old_input_fx, 0, Sample_Delay_SWB_BWE ); + Copy( st_fx->old_fdbwe_speech_fx + L_FRAME32k - Sample_Delay_SWB_BWE, st_fx->old_input_fx, Sample_Delay_SWB_BWE ); + + IF( sub(st_fx->extl_fx, WB_BWE) != 0 ) + { + Copy( old_input_fx, st_fx->L_old_wtda_swb_fx, L_FRAME32k ); + } + } + + test(); + IF( NE_16(st_fx->extl_fx, SWB_BWE)&&NE_16(st_fx->extl_fx,FB_BWE)) + { + Copy( input_fx, st_fx->old_fdbwe_speech_fx, L_FRAME32k ); + } + } + ELSE /* 48 kHz */ + { + /* 48kHz sampled processing needs review of FD2 memory handling/Q-factors */ + IF( EQ_16(st_fx->codec_mode,MODE1)) + { + test(); + test(); + IF( NE_16(st_fx->extl_fx,SWB_BWE)&&NE_16(st_fx->extl_fx,FB_BWE)&&EQ_16(st_fx->core_fx,ACELP_CORE)) + { + /* move the resampling out of the TDBWE path as new_swb_speech is not needed for TDBWE. */ + Copy( input_fx, st_fx->old_fdbwe_speech_fx, L_FRAME48k ); + } + ELSE + { + test(); + IF( NE_16(st_fx->last_extl_fx,SWB_BWE)&&NE_16(st_fx->last_extl_fx,FB_BWE)) + { + /* resample 48 kHz to 32kHz */ + IF( EQ_16(st_fx->last_bwidth_fx,FB)) + { + inner_frame = L_FRAME48k; + inner_Fs = 48000; + Copy( st_fx->old_fdbwe_speech_fx, new_swb_speech_fx, L_FRAME48k ); + } + ELSE + { + inner_frame = L_FRAME32k; + inner_Fs = 32000; + decimate_2_over_3_allpass_fx( st_fx->old_fdbwe_speech_fx, L_FRAME48k, new_swb_speech_fx, st_fx->dec_2_over_3_mem_fx, allpass_poles_3_ov_2, + decimate_3_ov_2_lowpass_num, decimate_3_ov_2_lowpass_den, st_fx->dec_2_over_3_mem_lp_fx ); + } + + Sample_Delay_SWB_BWE = NS2SA_fx2( inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); + Copy( new_swb_speech_fx, &old_input_fx[Sample_Delay_SWB_BWE], inner_frame ); + set16_fx( old_input_fx, 0, Sample_Delay_SWB_BWE ); + Copy( new_swb_speech_fx + inner_frame - Sample_Delay_SWB_BWE, st_fx->old_input_fx, Sample_Delay_SWB_BWE ); + Copy( old_input_fx, st_fx->L_old_wtda_swb_fx, inner_frame ); + st_fx->Q_old_wtda = 0; + move16(); + } + /* resample 48 kHz to 32kHz */ + IF( EQ_16(st_fx->bwidth_fx,FB)) + { + Copy( input_fx, new_swb_speech_fx, L_FRAME48k ); + } + ELSE + { + decimate_2_over_3_allpass_fx( input_fx, L_FRAME48k, new_swb_speech_fx, st_fx->dec_2_over_3_mem_fx, allpass_poles_3_ov_2, + decimate_3_ov_2_lowpass_num, decimate_3_ov_2_lowpass_den, st_fx->dec_2_over_3_mem_lp_fx ); + } + } + } + ELSE + { + /* resample 48 kHz to 32kHz */ + IF( EQ_16(st_fx->bwidth_fx,FB)) + { + Copy( input_fx, new_swb_speech_fx, L_FRAME48k ); + } + ELSE + { + decimate_2_over_3_allpass_fx( input_fx, L_FRAME48k, new_swb_speech_fx, st_fx->dec_2_over_3_mem_fx, allpass_poles_3_ov_2, + decimate_3_ov_2_lowpass_num, decimate_3_ov_2_lowpass_den, st_fx->dec_2_over_3_mem_lp_fx ); + } + } + } + + test(); + test(); + test(); + test(); + test(); + IF( ( EQ_16(st_fx->core_fx, ACELP_CORE)&&NE_16(st_fx->extl_fx,SWB_BWE_HIGHRATE)&&NE_16(st_fx->extl_fx,FB_BWE_HIGHRATE)) + || ( ( EQ_32(st_fx->total_brate_fx, 9600) || st_fx->rf_mode != 0 ) && EQ_16(st_fx->bwidth_fx, SWB) ) ) + { + IF( EQ_16(st_fx->L_frame_fx, L_FRAME)) + { + startB= 34; + endB= 14; + FOR( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + { + uB = 0; + FOR( nB = startB; nB > endB; nB-- ) + { + move16(); + realBufferFlipped[ts][uB] = realBuffer[ts][nB]; + if (s_and(ts, 1) != 0) + { + realBufferFlipped[ts][uB] = L_negate(realBufferFlipped[ts][uB]); + } + imagBufferFlipped[ts][uB] = imagBuffer[ts][nB]; + if (s_and(ts, 1) == 0) + { + imagBufferFlipped[ts][uB] = L_negate(imagBufferFlipped[ts][uB]); + } + uB = add(uB, 1); /* uB ++ */ + } + } + } + ELSE + { + startB = 39; + endB = 19; + FOR( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + { + uB = 0; + FOR( nB = startB; nB > endB; nB-- ) + { + realBufferFlipped[ts][uB] = L_negate(realBuffer[ts][nB]); + imagBufferFlipped[ts][uB] = imagBuffer[ts][nB]; + uB = add(uB, 1); /* uB ++ */ + } + } + } + + /* Highband energy computation for gain shape control in case of bandwidth switching fix*/ + { + CldfbHB_ener = 0; + FOR (nB = 0; nB < 10; nB++) + { + FOR (ts = 0; ts < CLDFB_NO_COL_MAX; ts++) + { + realQ_neg1 = extract_l(L_shr(realBufferFlipped[ts][nB], 31-(15+cldfbScale->hb_scale)+1)); + imagQ_neg1 = extract_l(L_shr(imagBufferFlipped[ts][nB], 31-(15+cldfbScale->hb_scale)+1)); /* Q(-1), headroom needed */ + + CldfbHB_ener = L_mac0(CldfbHB_ener, realQ_neg1, realQ_neg1); + CldfbHB_ener = L_mac0(CldfbHB_ener, imagQ_neg1, imagQ_neg1); /* Q(-2) */ + } + } + + exp = norm_l(CldfbHB_ener); + CldfbHB_ener = L_shl(CldfbHB_ener, exp); /* CldfbHB_ener = CldfbHB_fl*2^(exp) */ + Cldfbtemp1 = (Log2_norm_lc(CldfbHB_ener)); + Cldfbtemp1 = add(shr(Cldfbtemp1, 6), shl(sub(30, sub(exp, 2)), 9));/* Log2_norm_lc(CldfbHB_ener) = 2^15*(log2(CldfbHB_ener/2^30)) = 2^15*(log2(CldfbHB_fl*(2^-2)*2^exp/2^30)) = 2^15*(log2(CldfbHB_fl) + exp-2-30) => 2^(-6)*l2nc + 2^9(20-(exp-2)) = 2^9*log2(CldfbHB_fl), Q9 */ + CldfbHB_ener = L_mult(sub(Cldfbtemp1, 1741/*3.401 Q9*/), 3495); /* 3495 = Q19 log10(2)*0.1/log10(32768), Q = 19+9+1 = 29 */ + st_fx->cldfbHBLT = mac_r(CldfbHB_ener, 29491/*0.9 Q15*/, st_fx->cldfbHBLT); /* cldfbHBLT is in Q13 */ + } + cldfbSynthesisFiltering( st_fx->cldfbSyn_Fx, realBufferFlipped, imagBufferFlipped, + cldfbScale, shb_speech_fx, 0, CLDFB_NO_COL_MAX, cldfbWorkBuffer ); + *Q_shb_spch = 0; /*shb_speech_fx : Q0*/ + + test(); + test(); + IF( NE_16(st_fx->extl_fx, WB_TBE)&&NE_16(st_fx->extl_fx,SWB_TBE)&&NE_16(st_fx->extl_fx,FB_TBE)) + { + /* Update the previous superwideband speech buffer in case of a SWB_BWE frame - this code is in swb_tbe_enc */ + delay = L_LOOK_16k + L_SUBFR16k; + Copy( shb_speech_fx + L_FRAME16k - delay, st_fx->old_speech_shb_fx, delay ); + } + } + ELSE + { + IF( EQ_16(st_fx->bwidth_fx, FB)||EQ_16(st_fx->core_fx,ACELP_CORE)) + { + set16_fx( st_fx->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k ); + set16_fx( shb_speech_fx, 0, L_FRAME16k ); /* shb_speech for FB/SWB BWE_HIGHRATE is not used at 64kbps */ + } + ELSE + { + /* flip the spectrm */ + Copy( new_swb_speech_fx, spchTmp_fx, L_FRAME32k ); + + FOR( i = 0; i < L_FRAME32k; i = i+2 ) + { + spchTmp_fx[i] = negate(spchTmp_fx[i]); + } + + Decimate_allpass_steep_fx( spchTmp_fx, st_fx->state_ana_filt_shb_fx, L_FRAME32k, shb_speech_fx ); + Copy( shb_speech_fx + L_FRAME16k - (L_LOOK_16k + L_SUBFR16k), st_fx->old_speech_shb_fx, L_LOOK_16k + L_SUBFR16k ); + } + + /* Reset CLDFB synthesis buffer */ + set16_fx( st_fx->cldfbSyn_Fx->FilterStates, 0, st_fx->cldfbSyn_Fx->p_filter_length + st_fx->cldfbSyn_Fx->no_channels*st_fx->cldfbSyn_Fx->no_col ); + } + IF( st_fx->last_extl_fx == -1 ) + { + delay = NS2SA(st_fx->input_Fs_fx, DELAY_FIR_RESAMPL_NS); + FOR( i = 0; i < delay; i++ ) + { + shb_speech_fx[i] = mult_r( mult_r(i, 983/*0.03f Q15*/), shb_speech_fx[2*delay-1-i] ); + } + } + + return; +} + diff --git a/lib_enc/swb_tbe_enc_fx.c b/lib_enc/swb_tbe_enc_fx.c new file mode 100644 index 0000000..0852934 --- /dev/null +++ b/lib_enc/swb_tbe_enc_fx.c @@ -0,0 +1,3678 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include "options.h" +#include "cnst_fx.h" +#include "prot_fx.h" +#include "rom_com_fx.h" +#include "stl.h" + +/*-----------------------------------------------------------------* +* Local functions +*-----------------------------------------------------------------*/ +static void return_M_Least_fx_GainFrame( const Word32* inp, + const Word32* codebook, const Word16 num_grp, + const Word16 interNum, Word16* least ); + + +static void singlevectortest_gain_fx( const Word32* inp, const Word16 dimen, + const Word16 cb_size, Word16* index, + Word32* recon, const Word32* codebook ); + + +static void determine_gain_weights_fx( const Word32* gain, Word16* weights, + const Word16 dims ); + +static void QuantizeSHBsubgains_fx( Encoder_State_fx* st_fx, Word16* subgains, const Word16 extl ); + + +static void QuantizeSHBframegain_fx( Encoder_State_fx* st_fx, Word32* GainFrame, const Word16 extl, Word32 extl_brate + ,Word16 *rf_gainFrame_ind); + +static Word16 closest_centroid_fx( const Word16* data, const Word16* weights, + const Word16* quantizer, const Word16 centroids, const Word16 length ); + +static Word16 closest_centroid_lc_fx( const Word16* data, const Word16* quantizer, const Word16 centroids ); + +static void EstimateSHBFrameGain_fx( const Word16 length, + const Word16* oriSHB, const Word16 Q_oriSHB, + const Word16* synSHB, const Word16 Q_synSHB, Word16* subgain, + Word32* GainFrame, const Word16* win_shb, const Word16* subwin_shb, const Word16 n_subfr_saturation ); + + +static void EstimateSHBGainShape_fx( const Word16 length, + const Word16* oriSHB, const Word16 Q_oriSHB, + const Word16* synSHB, const Word16 Q_synSHB, + Word16* subgain, const Word16* subwin, Word16* n_subfr_saturation ); + + +static Word32 pow_off_pk_fx( Word16 a[], Word16 len, Word16 step ); + +static void find_max_mem_enc( Encoder_State_fx *st_fx, Word16 *n_mem, Word16 *n_mem2 ); +static void rescale_genSHB_mem_enc( Encoder_State_fx* st_fx, Word16 sf ); +static void find_max_mem_wb_enc( Encoder_State_fx* st_fx, Word16* n_mem ); +static void rescale_genWB_mem_enc( Encoder_State_fx* st_fx, Word16 sf ); + +static void Quant_lower_LSF_fx( const Word16 lsf[], + Word16 lsf_q[], + Word16 lsf_idx[]); + +static Word16 Quant_mirror_point_fx( const Word16 lsf[], const Word16 lsf_q[], + Word16* m ); +static Word16 Find_LSF_grid_fx( const Word16 lsf[], Word16 lsf_q[], + const Word16 m ); +static void Quant_BWE_LSF_fx( Encoder_State_fx* st_fx, const Word16 lsp_shb[], Word16 Q_lsfs[]); +static void Quant_shb_ener_sf_fx(Encoder_State_fx *st_fx, Word32 *shb_ener_sf_fx_32, Word16 Q_shb); +static void Quant_shb_res_gshape_fx(Encoder_State_fx *st_fx, Word16 *shb_res_gshape_fx); + +static void gainFrSmooth_En_fx(Encoder_State_fx *st_fx, + Word16 *shb_frame_fx, + const Word16 *lpc_shb_fx, + const Word16 *lsp_shb_fx, + Word16 *MA_lsp_shb_spacing, + Word16 *frGainAttenuate, + Word16 *frGainSmoothEn + ); + + +/*-------------------------------------------------------------------* + * find_max_mem_enc() + * + * Find norm and max in TBE memories and past buffers + *-------------------------------------------------------------------*/ +void find_max_mem_enc( + Encoder_State_fx *st_fx, + Word16 *n_mem, + Word16 *n_mem2 +) +{ + Word16 i; + Word16 n_mem_32; + Word16 max = 0; + Word32 Lmax = 0; + Word16 tempQ15, max2 = 0; + + /* old BWE exc max */ + FOR( i = 0; i < NL_BUFF_OFFSET; i++ ) + { + tempQ15 = abs_s( st_fx->old_bwe_exc_extended_fx[i] ); + max = s_max( max, tempQ15 ); + } + + /* decimate all-pass steep memory */ + FOR ( i = 0; i < (2*ALLPASSSECTIONS_STEEP+1); i++ ) + { + tempQ15 = abs_s( st_fx->mem_genSHBexc_filt_down_shb_fx[i] ); + max = s_max(max, tempQ15); + } + + /* -- keep norm of state_lpc_syn_fx, state_syn_shbexc_fx, + and mem_stp_swb_fx separately for 24.4 and 32kbps ----*/ + /* findMaxMem2() inside tbe com */ + FOR ( i = 0; i < LPC_SHB_ORDER; i++ ) + { + tempQ15 = abs_s( st_fx->state_lpc_syn_fx[i] ); + max2 = s_max(max2, tempQ15); + } + + /* findMaxMem2() inside tbe com */ + FOR ( i = 0; i < L_SHB_LAHEAD; i++ ) + { + tempQ15 = abs_s( st_fx->state_syn_shbexc_fx[i] ); + max2 = s_max(max2, tempQ15); + } + + /* findMaxMem2() inside tbe com */ + FOR ( i = 0; i < LPC_SHB_ORDER; i++ ) + { + tempQ15 = abs_s( st_fx->mem_stp_swb_fx[i] ); + max2 = s_max(max2, tempQ15); + } + + /* for total_brate > 16.4kbps, use n_mem2; else account for the max2 for n_mem calculation */ + *n_mem2 = norm_s(max2); + if(max2 == 0) *n_mem2 = 15; + if(LT_32(st_fx->total_brate_fx, ACELP_24k40)) + { + max = s_max(max, max2); + } + + /* de-emph and pre-emph memory */ + tempQ15 = abs_s( st_fx->tbe_demph_fx ); + max = s_max(max, tempQ15); + + tempQ15 = abs_s( st_fx->tbe_premph_fx ); + max = s_max(max, tempQ15); + + IF( EQ_16(st_fx->extl_fx, FB_TBE)) + { + FOR ( i = 0; i < LPC_SHB_ORDER; i++ ) + { + tempQ15 = abs_s( st_fx->fb_state_lpc_syn_fx[i] ); + max = s_max(max, tempQ15); + } + /* FB de-emph memory */ + tempQ15 = abs_s( st_fx->fb_tbe_demph_fx); + max = s_max(max, tempQ15); + } + /* estimate the norm for 16-bit memories */ + *n_mem = norm_s( max ); + if( max == 0 ) + { + *n_mem = 15; + } + + /* estimate the norm for 32-bit memories */ + Lmax = L_abs( st_fx->mem_csfilt_fx[0] ); /* only element [0] is used in env. shaping */ + + n_mem_32 = norm_l( Lmax ); + if( Lmax == 0 ) + { + n_mem_32 = 31; + } + + tempQ15 = sub( s_min( *n_mem, n_mem_32 ), 1 ); + *n_mem = s_max( tempQ15, 0 ); +} + + +/*-------------------------------------------------------------------* + * rescale_genSHB_mem_enc() + * + * Rescale genSHB memories + *-------------------------------------------------------------------*/ +void rescale_genSHB_mem_enc( Encoder_State_fx* st_fx, Word16 sf ) +{ + Word16 i; + + FOR( i = 0; i old_bwe_exc_extended_fx[i] = shl( st_fx->old_bwe_exc_extended_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < 7; i++ ) + { + st_fx->mem_genSHBexc_filt_down_shb_fx[i] = shl( st_fx->mem_genSHBexc_filt_down_shb_fx[i], sf ); + move16(); + } + + /* -- Apply memory scaling for 13.2 and 16.4k bps using sf ----*/ + IF(LT_32(st_fx->total_brate_fx, ACELP_24k40)) + { + FOR ( i = 0; i < LPC_SHB_ORDER; i++ ) + { + st_fx->state_lpc_syn_fx[i] = shl( st_fx->state_lpc_syn_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < L_SHB_LAHEAD; i++ ) + { + st_fx->state_syn_shbexc_fx[i] = shl( st_fx->state_syn_shbexc_fx[i], sf ); + move16(); + } + } + + st_fx->mem_csfilt_fx[0] = L_shl( st_fx->mem_csfilt_fx[0], sf ); + move32(); + + st_fx->tbe_demph_fx = shl_r( st_fx->tbe_demph_fx, sf ); + move16(); + st_fx->tbe_premph_fx = shl_r( st_fx->tbe_premph_fx, sf ); + move16(); + +} + +void find_max_mem_wb_enc( Encoder_State_fx* st_fx, Word16* n_mem ) +{ + Word16 i; + Word16 n_mem_32; + Word16 max =0; + Word32 Lmax =0; + + FOR ( i = 0; i < NL_BUFF_OFFSET; i++ ) + max = s_max( max, abs_s( st_fx->old_bwe_exc_extended_fx[i] ) ); + + FOR ( i = 0; i < 7; i++ ) + { + IF ( abs_s( st_fx->mem_genSHBexc_filt_down_shb_fx[i] ) > max ) + max = abs_s( st_fx->mem_genSHBexc_filt_down_shb_fx[i] ); + } + + FOR ( i = 0; i < 7; i++ ) + { + IF ( abs_s( st_fx->mem_genSHBexc_filt_down_wb2_fx[i] ) > max ) + max = abs_s( st_fx->mem_genSHBexc_filt_down_wb2_fx[i] ); + } + + FOR ( i = 0; i < 7; i++ ) + { + IF ( abs_s( st_fx->mem_genSHBexc_filt_down_wb3_fx[i] ) > max ) + max = abs_s( st_fx->mem_genSHBexc_filt_down_wb3_fx[i] ); + } + + FOR ( i = 0; i < 10; i++ ) + { + IF ( abs_s( st_fx->state_lpc_syn_fx[i] ) > max ) + max = abs_s( st_fx->state_lpc_syn_fx[i] ); + } + + FOR ( i = 0; i < 5; i++ ) + { + IF ( abs_s( st_fx->state_syn_shbexc_fx[i] ) > max ) + max = abs_s( st_fx->state_syn_shbexc_fx[i] ); + } + + IF ( max == 0 ) + { + *n_mem = 15; + move16(); + } + ELSE + { + *n_mem = norm_s( max ); + move16(); + } + + FOR ( i = 0; i < 2; i++ ) + { + IF ( L_abs( st_fx->mem_csfilt_fx[i] ) > Lmax ) + Lmax = L_abs( st_fx->mem_csfilt_fx[i] ); + } + + + IF ( Lmax == 0 ) + { + n_mem_32 = 31; + move16(); + } + ELSE + { + n_mem_32 = norm_l( Lmax ); + } + + *n_mem = sub( s_min( *n_mem, n_mem_32 ), 1 ); + move16(); + *n_mem = s_max( *n_mem, 0 ); +} + +void rescale_genWB_mem_enc( Encoder_State_fx* st_fx, Word16 sf ) +{ + Word16 i; + + FOR ( i = 0; i < NL_BUFF_OFFSET; i++ ) + { + st_fx->old_bwe_exc_extended_fx[i] = shl( st_fx->old_bwe_exc_extended_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < 10; i++ ) + { + st_fx->state_lpc_syn_fx[i] = shl( st_fx->state_lpc_syn_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < 5; i++ ) + { + st_fx->state_syn_shbexc_fx[i] = shl( st_fx->state_syn_shbexc_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < 7; i++ ) + { + st_fx->mem_genSHBexc_filt_down_shb_fx[i] = shl( st_fx->mem_genSHBexc_filt_down_shb_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < 7; i++ ) + { + st_fx->mem_genSHBexc_filt_down_wb2_fx[i] = shl( st_fx->mem_genSHBexc_filt_down_wb2_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < 7; i++ ) + { + st_fx->mem_genSHBexc_filt_down_wb3_fx[i] = shl( st_fx->mem_genSHBexc_filt_down_wb3_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < 2; i++ ) + { + st_fx->mem_csfilt_fx[i] = L_shl( st_fx->mem_csfilt_fx[i], sf ); + move32(); + } +} + + +/*-------------------------------------------------------------------* + * InitSWBencBuffer() + * + * Initialize SWB buffers + *-------------------------------------------------------------------*/ +void InitSWBencBuffer_fx( + Encoder_State_fx* st_fx /* i/o: SHB encoder structure */ +) +{ + set16_fx( st_fx->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k ); + set16_fx( st_fx->old_bwe_exc_fx, 0, ( PIT16k_MAX * 2 ) ); + st_fx->bwe_seed_fx[0] = 23; + move16(); + st_fx->bwe_seed_fx[1] = 59; + move16(); + set16_fx( st_fx->old_bwe_exc_extended_fx, 0, NL_BUFF_OFFSET ); + + st_fx->bwe_non_lin_prev_scale_fx = L_deposit_l(0); + + set16_fx(st_fx->state_ana_filt_shb_fx, 0, (2*ALLPASSSECTIONS_STEEP+1)); + set32_fx( st_fx->elliptic_bpf_2_48k_mem_fx[0], 0, 4 ); + set32_fx( st_fx->elliptic_bpf_2_48k_mem_fx[1], 0, 4 ); + set32_fx( st_fx->elliptic_bpf_2_48k_mem_fx[2], 0, 4 ); + set32_fx( st_fx->elliptic_bpf_2_48k_mem_fx[3], 0, 4 ); + st_fx->prev_fb_energy_fx = 0; + move16(); + set16_fx( st_fx->elliptic_bpf_2_48k_mem_fx_Q, 0, 4 ); + st_fx->prev_fb_energy_fx_Q = 0; + move16(); + set16_fx( st_fx->prev_lsp_shb_fx, 0, 10 ); + st_fx->prev_Q_bwe_exc = 31; + move16(); + st_fx->prev_Q_bwe_syn = 31; + move16(); + set16_fx( st_fx->prev_lsp_wb_fx, 0, 6 ); + set16_fx( st_fx->prev_lsp_wb_temp_fx, 0, 6 ); + + set16_fx( st_fx->prev_lpc_wb_fx, 0, LPC_SHB_ORDER_WB); + + return; +} + +/*-------------------------------------------------------------------* + * ResetSHBbuffer_Enc() + * + *-------------------------------------------------------------------*/ +void ResetSHBbuffer_Enc_fx( + Encoder_State_fx* st_fx /* i/o: SHB encoder structure */ +) +{ + /* states for the filters used in generating SHB excitation from WB excitation*/ + set16_fx( st_fx->mem_genSHBexc_filt_down_shb_fx, 0, 2*ALLPASSSECTIONS_STEEP+1); + set32_fx( st_fx->mem_csfilt_fx, 0, 2 ); + + /* states for the filters used in generating SHB signal from SHB excitation*/ + set16_fx( st_fx->state_syn_shbexc_fx, 0, L_SHB_LAHEAD ); + set16_fx( st_fx->state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + + IF( EQ_16(st_fx->extl_fx, FB_TBE)) + { + set16_fx( st_fx->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + st_fx->fb_tbe_demph_fx = 0; + move16(); + } + /* states for the filters used in generating WB signal from WB excitation*/ + set16_fx( st_fx->decim_state1_fx, 0, 2*ALLPASSSECTIONS_STEEP+1 ); + set16_fx( st_fx->decim_state2_fx, 0, 2*ALLPASSSECTIONS_STEEP+1); + set16_fx( st_fx->mem_genSHBexc_filt_down_wb2_fx, 0, 2*ALLPASSSECTIONS_STEEP+1 ); + set16_fx( st_fx->mem_genSHBexc_filt_down_wb3_fx, 0, 2*ALLPASSSECTIONS_STEEP+1 ); + + /* overlap buffer used to Adjust SHB Frame Gain */ + set16_fx(st_fx->mem_stp_swb_fx, 0, LPC_SHB_ORDER); + st_fx->gain_prec_swb_fx = 16384;/*Q14=1 */ + set16_fx( st_fx->syn_overlap_fx, 0, L_SHB_LAHEAD ); + st_fx->tbe_demph_fx = 0; + st_fx->tbe_premph_fx = 0; + + + return; +} + + +/*==========================================================================*/ +/* FUNCTION : void wb_tbe_enc_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : WB TBE encoder, 6 - 8 kHz band encoding module */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 coder_type i : coding type */ +/* Word16 *new_speech i : original input signal Q0 */ +/* Word32 *bwe_exc_extended i : bandwidth extended exciatation 2*Q_new*/ +/* Word16 voice_factors[] i : voicing factors Q15 */ +/* Word16 pitch_buf[] i : pitch for each subframe Q6 */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* Word16 *synth o : WB SHB final synthesis */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Encoder_State_fx *st_fx i/o: encoder state structure */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* */ +/*==========================================================================*/ + +#define WBTBE_LOOK_LSUFBR_5_OVER_16 (L_LOOK_12k8 + L_SUBFR)*5/16 +#define WBTBE_LSUBFR_5_OVER_16 L_SUBFR*5/16 +#define WBTBE_ANA_ALIGNDELAY -(L_SHB_LAHEAD/4 + 5) +#define LFRAME16K_OVER_4 L_FRAME16k/4 +#define WBTBE_LPCWIN_LENGTH (L_LOOK_12k8 + L_SUBFR + L_FRAME) * 5/16 - 1 + +void wb_tbe_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 coder_type, /* i : coding type */ + const Word16 *hb_speech, /* i : HB target signal (6-8kHz) at 16kHz at Q-1 */ + const Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation */ + const Word16 Q_new, /* i : input HB speech Q factor */ + const Word16 voice_factors[], /* i : voicing factors */ + const Word16 pitch_buf[], /* i : pitch for each subframe */ + const Word16 voicing_fx[] /* i : OL maximum normalized correlation */ +) +{ + Word16 i, j, k; + Word16 hb_old_speech [(L_LOOK_12k8 + L_SUBFR + L_FRAME)*5/16]; + Word16 bwe_exc_extended_16[ L_FRAME32k+NL_BUFF_OFFSET ]; + + Word16 shaped_wb_excitation[(L_FRAME16k + L_SHB_LAHEAD)/4]; + Word16 exc4kWhtnd[L_FRAME16k/4]; + /*Word16 ana_align_delay = WBTBE_ANA_ALIGNDELAY; */ /* -L_SHB_LAHEAD/4 - 5 */ + Word32 GainFrame; + Word16 GainShape[NUM_SHB_SUBFR]; + Word16 lpc_wb[LPC_SHB_ORDER_WB+1]; + Word32 lpc_wb_32_fx[LPC_SHB_ORDER_WB + 1]; + Word16 lsp_wb[LPC_SHB_ORDER_WB], weights_lsp[LPC_SHB_ORDER_WB] = {32767, 32767}; + Word16 *hb_new_speech, *hb_frame/*, hb_speech[ L_FRAME16k ]*/; + Word16 R_h[ LPC_SHB_ORDER_WB + 2 ], R_l[ LPC_SHB_ORDER_WB + 2 ]; + Word16 Q_R; + Word32 LepsP[LPC_SHB_ORDER_WB+1]; + + Word32 prev_pow, curr_pow, Lscale; + /* Word16 scale; */ + /*Word16 ramp_flag;*/ + Word32 p2m_in, p2m_out; + /*Word16 cnt, max =0;*/ + Word16 n_mem, Q_bwe_exc, Q_bwe_exc_ext, exp_out; /* Q_hb_frame; */ + Word32 L_tmp, Lmax; + Word16 tmp, exp, Q_out, sc; + Word16 Q_ns = -1; + + Word16 pitBufAvg_fx, voicingBufAvg_fx; + Word16 vf_modified_fx[NB_SUBFR16k]; + Word16 temp_wb_fac_fx, feedback_fx; + Word16 lsp_spacing_fx; + Word16 lsp_wb_temp_fx[ LPC_SHB_ORDER_WB ], lpc_wb_temp_fx[ LPC_SHB_ORDER_WB + 1 ]; + Word32 L_feedback; + Word16 frac, exp1; + Word16 uv_flag; + Word16 dummy=0; + Word16 avg_voice_fac; + /*Word16 att = 32767;*/ + + hb_new_speech = hb_old_speech + WBTBE_LOOK_LSUFBR_5_OVER_16; + hb_frame = hb_old_speech + WBTBE_LSUBFR_5_OVER_16 + WBTBE_ANA_ALIGNDELAY; + + Copy( st_fx->old_speech_wb_fx, hb_old_speech, WBTBE_LOOK_LSUFBR_5_OVER_16 ); + Copy( hb_speech, hb_new_speech, LFRAME16K_OVER_4 ); + Copy( hb_old_speech + LFRAME16K_OVER_4, st_fx->old_speech_wb_fx, WBTBE_LOOK_LSUFBR_5_OVER_16 ); + + test(); + test(); + test(); + test(); + test(); + test(); + IF ( ( NE_16 (st_fx->last_extl_fx, WB_TBE) && NE_16( st_fx->last_extl_fx, WB_BWE)) + && ( EQ_16( st_fx->clas_fx, UNVOICED_CLAS) || ( LT_16( voicing_fx[0], 16384 ) && LT_16( voicing_fx[1], 16384 ) && LT_16( voicing_fx[2], 16384 ) ) ) + && st_fx->igf == 0 ) + { + /* In case of unvoiced signals after switching cores, back-propagate the target signal */ + Copy( hb_speech, hb_old_speech, WBTBE_LOOK_LSUFBR_5_OVER_16 ); + + i = WBTBE_LOOK_LSUFBR_5_OVER_16; + move16(); + k = 0; + move16(); + + FOR ( j = 0; j < L_SUBFR16k; j = j + 4 ) + { + L_tmp = L_mult( hb_old_speech[i], ola_win_shb_switch_fold_fx[j] ); + hb_old_speech[i] = mac_r( L_tmp, hb_speech[j], ola_win_shb_switch_fold_fx[ L_SUBFR16k - 4 - j ] ); + move16(); + i--; + k++; + } + } + + autocorr_fx( hb_old_speech, LPC_SHB_ORDER_WB + 1, R_h, R_l, &Q_R, WBTBE_LPCWIN_LENGTH, win_lpc_hb_wb_fx, 0, 1 ); + + E_LPC_lev_dur(R_h, R_l, lpc_wb_temp_fx, LepsP, LPC_SHB_ORDER_WB, NULL); + + Copy_Scale_sig( lpc_wb_temp_fx, lpc_wb_temp_fx, LPC_SHB_ORDER_WB+1, sub(norm_s(lpc_wb_temp_fx[0]),2) ); + + /* convert into lsps and calculate weights */ + FOR ( i = 0; i <= LPC_SHB_ORDER_WB; i++ ) + { + lpc_wb_32_fx[i] = L_negate( L_shr( L_deposit_h( lpc_wb_temp_fx[i] ), 1 ) ); + move32(); + } + + lpc2lsp_fx( &lpc_wb_32_fx[1], lsp_wb_temp_fx, st_fx->prev_lsp_wb_temp_fx, LPC_SHB_ORDER_WB ); + + FOR ( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lsp_wb_temp_fx[i] = lsp_wb_temp_fx[i]; + move16(); + } + + /* lsp_spacing_fx = 16384; move16(); */ + lsp_spacing_fx = lsp_wb_temp_fx[0]; + move16(); + FOR ( i = 1; i < LPC_SHB_ORDER_WB; i++ ) + { + /*if ( i == 0 ) + { + tmp = lsp_wb_temp_fx[0]; move16(); + } + else + {*/ + tmp = sub( lsp_wb_temp_fx[i], lsp_wb_temp_fx[i - 1] ); + /*} */ + + lsp_spacing_fx = s_min( lsp_spacing_fx, tmp ); + } + + /* Spectral smoothing of autocorrelation coefficients */ + FOR ( i = 1; i <= LPC_SHB_ORDER_WB; i++ ) + { + L_tmp = Mpy_32( R_h[i], R_l[i], wac_h[i - 1], wac_l[i - 1] ); + L_Extract( L_tmp, &R_h[i], &R_l[i] ); + } + R_l[0] = s_max( R_l[0], 1 ); + move16(); + + test(); + IF ( EQ_16(st_fx->rf_mode, 1)||EQ_32(st_fx->extl_brate_fx,WB_TBE_0k35)) + { + E_LPC_lev_dur(R_h, R_l, lpc_wb, LepsP, LPC_SHB_ORDER_LBR_WB, NULL); + Copy_Scale_sig( lpc_wb, lpc_wb, LPC_SHB_ORDER_LBR_WB+1, sub(norm_s(lpc_wb[0]),2) ); + + /* Expand bandwidth of the LP coeffs */ + FOR ( i = 0; i <= LPC_SHB_ORDER_LBR_WB; i++ ) + { + lpc_wb[i] = mult_r( lpc_wb[i], lpc_weights_fx[i] ); + move16(); + } + + /* convert into lsps and calculate weights */ + FOR ( i = 0; i <= LPC_SHB_ORDER_LBR_WB; i++ ) + { + lpc_wb_32_fx[i] = L_negate( L_shr( L_deposit_h( lpc_wb[i] ),1 ) ); + move32();/*Q27 */ + } + lpc2lsp_fx( &lpc_wb_32_fx[1], lsp_wb, st_fx->prev_lsp_wb_fx,LPC_SHB_ORDER_LBR_WB ); + + FOR ( i = 0; i < LPC_SHB_ORDER_LBR_WB; i++ ) + { + st_fx->prev_lsp_wb_fx[i] = lsp_wb[i]; + move16(); + } + + lsp_weights_fx( lsp_wb, weights_lsp, LPC_SHB_ORDER_LBR_WB, &Q_out ); + + /* Quantization of LSFs */ + i = closest_centroid_fx( lsp_wb, weights_lsp, lbr_wb_bwe_lsfvq_cbook_2bit_fx, 4, LPC_SHB_ORDER_LBR_WB ); + IF( EQ_16(st_fx->codec_mode, MODE2)) + { + st_fx->lsf_WB_fx = i; + move16(); + } + ELSE + { + push_indice_fx( st_fx, IND_SHB_LSF, i, NUM_BITS_LBR_WB_LSF ); + } + + Copy( lbr_wb_bwe_lsfvq_cbook_2bit_fx + i * LPC_SHB_ORDER_LBR_WB, lsp_wb, LPC_SHB_ORDER_LBR_WB ); + + lsp2lpc_fx( &lpc_wb[1], lsp_wb, st_fx->prev_lpc_wb_fx, LPC_SHB_ORDER_LBR_WB ); + + set16_fx( lpc_wb + LPC_SHB_ORDER_LBR_WB + 1, 0, ( LPC_SHB_ORDER_WB - LPC_SHB_ORDER_LBR_WB ) ); + FOR ( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lpc_wb_fx[i] = lpc_wb[i + 1]; + move16(); + } + + FOR ( i = 1; i < LPC_SHB_ORDER_LBR_WB + 1; i++ ) + { + lpc_wb[i] = negate( lpc_wb[i] ); + move16(); + } + lpc_wb[0] = 4096; + move16(); + } + ELSE /* 13.2kbps */ + { + E_LPC_lev_dur(R_h, R_l, lpc_wb, LepsP, LPC_SHB_ORDER_WB, NULL); + Copy_Scale_sig( lpc_wb, lpc_wb, LPC_SHB_ORDER_WB+1, sub(norm_s(lpc_wb[0]),2) ); + + /* Expand bandwidth of the LP coeffs */ + FOR ( i = 0; i <= LPC_SHB_ORDER_WB; i++ ) + { + lpc_wb[i] = mult_r( lpc_wb[i], lpc_weights_fx[i] ); + move16(); + } + + /* convert into lsps and calculate weights */ + FOR ( i = 0; i <= LPC_SHB_ORDER_WB; i++ ) + { + lpc_wb_32_fx[i] = L_negate( L_shr( L_deposit_h( lpc_wb[i] ), 1 ) ); + move32();/*Q27 */ + } + + lpc2lsp_fx( &lpc_wb_32_fx[1], lsp_wb, st_fx->prev_lsp_wb_fx, LPC_SHB_ORDER_WB ); + + + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lsp_wb_fx[i] = lsp_wb[i]; + move16(); + } + + lsp_weights_fx( lsp_wb, weights_lsp, LPC_SHB_ORDER_WB, &Q_out ); + + /* Quantization of LSFs */ + i = closest_centroid_fx( lsp_wb, weights_lsp, wb_bwe_lsfvq_cbook_8bit_fx, 256, LPC_SHB_ORDER_WB );/*move16(); */ + + IF( EQ_16(st_fx->codec_mode, MODE2)) + { + st_fx->lsf_WB_fx = i; + move16(); + } + ELSE + { + push_indice_fx( st_fx, IND_SHB_LSF, i, NUM_BITS_WB_LSF ); + } + Copy( wb_bwe_lsfvq_cbook_8bit_fx + i * LPC_SHB_ORDER_WB, lsp_wb, LPC_SHB_ORDER_WB ); + + lsp2lpc_fx( &lpc_wb[1], lsp_wb, st_fx->prev_lpc_wb_fx, LPC_SHB_ORDER_WB ); + + + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lpc_wb_fx[i] = lpc_wb[i + 1]; + move16(); + } + FOR( i = 1; i < LPC_SHB_ORDER_WB + 1; i++ ) + { + lpc_wb[i] = negate( lpc_wb[i] ); + move16(); + } + lpc_wb[0] = 4096; + move16(); + } + + uv_flag = 0; + move16(); + test(); + if( EQ_32(st_fx->extl_brate_fx, WB_TBE_1k05)&&EQ_16(st_fx->coder_type_raw_fx,UNVOICED)) + { + uv_flag = 1; + move16(); + } + + Copy( voice_factors, vf_modified_fx, NB_SUBFR16k ); + IF( EQ_16(coder_type,VOICED)) + { + FOR( i = 1; i < NB_SUBFR; i++ ) + { + /*vf_modified[i] = 0.8f * voice_factors[i] + 0.2f * voice_factors[i-1];*/ + vf_modified_fx[i] = add( mult_r( 26214, voice_factors[i] ), mult_r( 6553, voice_factors[i - 1] ) ); + } + IF( NE_16(st_fx->L_frame_fx, L_FRAME)) + { + vf_modified_fx[4] = add( mult_r( 26214, voice_factors[4] ), mult_r( 6553, voice_factors[3] ) ); + } + } + + /* From low band excitation, generate highband excitation */ + Lmax = L_deposit_l(0); + FOR( i = 0; i < L_FRAME32k; i++ ) + { + Lmax = L_max( Lmax, L_abs( bwe_exc_extended[i] ) ); + } + + Q_bwe_exc = 31; + if( Lmax != 0 ) + { + Q_bwe_exc = norm_l( Lmax ); + } + Q_bwe_exc = sub( Q_bwe_exc, 3 ); + Q_bwe_exc = add( Q_bwe_exc, add( Q_new, Q_new ) ); + + find_max_mem_wb_enc( st_fx, &n_mem ); + + if( GT_16(sub( Q_bwe_exc, st_fx->prev_Q_bwe_exc ),n_mem)) + { + Q_bwe_exc = add( st_fx->prev_Q_bwe_exc, n_mem ); + } + + IF( uv_flag ) + { + if( GT_16( Q_bwe_exc, 20 )) + { + Q_bwe_exc = 20; + move16();/* restrict this to 20 due to the Q factor requireemnt of the random number generator (keep 1 bit headroom) */ + } + } + + prev_pow = 0; + move16(); + FOR( i = 0; i < L_SHB_LAHEAD / 4; i++ ) + { + prev_pow = L_mac0( prev_pow, st_fx->state_syn_shbexc_fx[i], st_fx->state_syn_shbexc_fx[i] ); /* Q(2*st_fx->prev_Q_bwe_exc) */ + } + + rescale_genWB_mem_enc( st_fx, sub( Q_bwe_exc, st_fx->prev_Q_bwe_exc ) ); + + Copy( st_fx->old_bwe_exc_extended_fx, bwe_exc_extended_16, NL_BUFF_OFFSET ); + sc = sub( Q_bwe_exc, add( Q_new, Q_new ) ); + FOR ( i = 0; i < L_FRAME32k; i++ ) + { + bwe_exc_extended_16[i + NL_BUFF_OFFSET] = round_fx( L_shl( bwe_exc_extended[i], sc ) ); + } + Copy( bwe_exc_extended_16 + L_FRAME32k, st_fx->old_bwe_exc_extended_fx, NL_BUFF_OFFSET ); + + + Copy( st_fx->state_syn_shbexc_fx, shaped_wb_excitation, L_SHB_LAHEAD / 4 ); + Q_bwe_exc_ext = sub( Q_bwe_exc, 16 ); + + + GenShapedWBExcitation_fx( shaped_wb_excitation + L_SHB_LAHEAD / 4, lpc_wb, exc4kWhtnd, st_fx->mem_csfilt_fx, + st_fx->mem_genSHBexc_filt_down_shb_fx, st_fx->mem_genSHBexc_filt_down_wb2_fx, st_fx->mem_genSHBexc_filt_down_wb3_fx, + st_fx->state_lpc_syn_fx, coder_type, bwe_exc_extended_16, Q_bwe_exc_ext, st_fx->bwe_seed_fx, + vf_modified_fx, uv_flag + , st_fx->igf + ); + + curr_pow = 0; + move16(); + FOR ( i = 0; i < L_SHB_LAHEAD / 4; i++ ) + { + curr_pow = L_mac0( curr_pow, shaped_wb_excitation[i + L_SHB_LAHEAD/4], shaped_wb_excitation[i + L_SHB_LAHEAD / 4] ); /* Q(2*Q_bwe_exc_ext) */ + } + + IF ( GT_16( voice_factors[0], 24576 )) + { + curr_pow = L_shr( curr_pow, 2 ); /* Q(2*Q_bwe_exc_ext) */ + } + + Lscale = root_a_over_b_fx( curr_pow, shl_r( Q_bwe_exc_ext, 1 ), prev_pow, shl_r( sub( st_fx->prev_Q_bwe_exc, 16 ), 1 ), &exp ); + + + FOR ( i = 0; i < L_SHB_LAHEAD / 4 - 1; i++ ) + { + L_tmp = Mult_32_16( Lscale, shaped_wb_excitation[i] ); /* Q(16-exp+Q_bwe_exc_ext) */ + shaped_wb_excitation[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc_ext */ + } + + Lscale = root_a_fx( Lscale, 31 - exp, &exp ); + L_tmp = Mult_32_16( Lscale, shaped_wb_excitation[L_SHB_LAHEAD / 4 - 1] ); /* Q(16-exp+Q_bwe_exc_ext) */ + shaped_wb_excitation[L_SHB_LAHEAD / 4 - 1] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc_ext */ + + /* Update WB excitation */ + Copy( shaped_wb_excitation + L_FRAME16k / 4, st_fx->state_syn_shbexc_fx, L_SHB_LAHEAD / 4 ); + + EstimateSHBGainShape_fx( SHB_OVERLAP_LEN / 2, hb_frame, Q_ns, + shaped_wb_excitation, Q_bwe_exc_ext, GainShape,subwin_wb_fx, NULL ); + + /* Gain frame adjustment factor */ + test(); + IF( GainShape[0] && st_fx->prev_wb_GainShape ) + { + exp = norm_s( st_fx->prev_wb_GainShape ); + tmp = div_s( shl(1,sub( 14,exp )), st_fx->prev_wb_GainShape ); + L_tmp = L_mult( GainShape[0], tmp ); /* Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) ); + exp1 = sub( exp, exp1 ); + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_wb_fac_fx = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_wb_fac_fx = 0; + move16(); + } + L_feedback = L_mult0( temp_wb_fac_fx, temp_wb_fac_fx ); + FOR( i = 1; i < NUM_SHB_SUBFR / 4; i++ ) + { + /* temp_swb_fac = (float)log( (GainShape[i]+0.00001f) / (GainShape[i-1]+0.0001f) ); */ + test(); + IF( GainShape[i] && GainShape[i - 1] ) + { + exp = norm_s( GainShape[i - 1] ); + tmp = div_s( shl(1,sub( 14,exp )), GainShape[i - 1] ); + L_tmp = L_mult( GainShape[i], tmp );/*Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) ); + move16(); + exp1 = sub( exp, exp1 ); + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_wb_fac_fx = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_wb_fac_fx = 0; + move16(); + } + + L_feedback = L_mac( L_feedback, temp_wb_fac_fx, temp_wb_fac_fx ); + + } + L_tmp = L_add( L_shr( L_feedback, 1 ), 1 << 21 ); /* Q30 */ + + IF( L_tmp != 0 ) + { + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + exp = sub( sub( 30, exp ), 21 ); + tmp = div_s( 16384, tmp ); /* Q(15+exp) */ + L_tmp = L_shr( L_mult( 13107, tmp ), exp ); /* Q31 */ + feedback_fx = round_fx( L_tmp ); /* Q15 */ + } + ELSE + { + feedback_fx = 8738; + move16();/* Q15 */ + } + + + temp_wb_fac_fx = st_fx->prev_wb_GainShape; + move16(); + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + GainShape[i] = add( mult_r( sub( 32767, feedback_fx ), GainShape[i] ), mult_r( feedback_fx, temp_wb_fac_fx ) ); + move16(); + temp_wb_fac_fx = GainShape[i]; + move16(); + } + + st_fx->prev_wb_GainShape = GainShape[sub(shr(NUM_SHB_SUBFR,2),1)]; + move16(); + p2m_in = pow_off_pk_fx( GainShape, shr(NUM_SHB_SUBFR,2), 1 ); + move16(); + + IF( EQ_32(st_fx->extl_brate_fx,WB_TBE_0k35)) + { + FOR( i = 0; i < 8; i++ ) + { + GainShape[i] = RECIP_ROOT_EIGHT_FX; + move16(); + } + + } + ELSE + { + push_indice_fx( st_fx, IND_UV_FLAG, uv_flag, 1 ); + + /* Quantization of the subframe gain parameter */ + QuantizeSHBsubgains_fx( st_fx, GainShape, st_fx->extl_fx ); + } + + /* Compute the power of gains away from the peak gain after quantization */ + p2m_out = pow_off_pk_fx( GainShape, NUM_SHB_SUBFR / 2, 2 ); + + /* Estimate the gain parameter */ + EstimateSHBFrameGain_fx( SHB_OVERLAP_LEN / 2, hb_frame, Q_ns, shaped_wb_excitation, Q_bwe_exc_ext, GainShape, + &GainFrame, window_wb_fx, subwin_wb_fx, 0 ); + + + /* If there's a big difference in the power of gains away from the peak gain */ + /* due to poor quantization then suppress energy of the high band. */ + + IF( GT_32( p2m_out, L_shl( p2m_in, 1 ) )) + { + L_tmp = root_a_over_b_fx( L_shl( p2m_in, 1 ), 29, p2m_out, 29, &exp_out ); + GainFrame = L_shl( Mult_32_32( GainFrame, L_tmp ), exp_out ); /* Q18 */ + } + + pitBufAvg_fx = 0; + move16(); + + FOR( i = 0; i < NB_SUBFR; i++ ) + { + pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[i], 82 ) ); /*Q6 */ + } + voicingBufAvg_fx = 0; + move16(); + FOR( i = 0; i < 3; i++ ) + { + voicingBufAvg_fx = add( voicingBufAvg_fx, mult_r( voicing_fx[i], 10912 ) ); /*Q15 */ + } + /* GainFrame *= max(min((float)(pitBufAvg/voicingBufAvg), 1.0f), 0.7f); */ + tmp = 32767; + move16(); + IF( voicingBufAvg_fx > 0 ) + { + exp = norm_s( voicingBufAvg_fx ); + tmp = div_s( shl(1,sub( 14,exp )), voicingBufAvg_fx );/* (14-exp) */ + L_tmp = L_mult( pitBufAvg_fx, tmp ); /* (21-exp) */ + L_tmp = L_shl( L_tmp, add(exp, 10) ); + tmp = round_fx( L_tmp ); /* Q15 */ + } + + tmp = s_max( s_min( tmp, 32767 ), 22938 ); /* Q15 */ + GainFrame = Mult_32_16( GainFrame, tmp ); /* Q18 */ + + IF( LT_16( lsp_spacing_fx, 328 )&&lsp_spacing_fx) + { + GainFrame = Mult_32_16( GainFrame, 21299 ); /* Q18 */ + } + + IF( EQ_16(st_fx->codec_mode, MODE1)) + { + /*wbbwe_em_factor = add( mult_r( 29491, st_fx->prev_wbbwe_em_factor_fx ), mult_r( 3277, wbbwe_em_factor ) ); */ /* Q15 */ + } + + + /*0.25f*sum_f(voice_factors, NB_SUBFR)*/ + L_tmp = L_mult(voice_factors[0], 8192); + FOR (i=1; iigf != 0 && EQ_16(coder_type, VOICED)) + { + /*GainFrame *= 0.5f;*/ + + GainFrame = Mult_32_16( GainFrame, 16384 ); + } + ELSE IF( st_fx->igf != 0 && GT_16( avg_voice_fac, 11469 )) /*Q15 -> 0.35f*/ + { + /*GainFrame *= 0.75f;*/ + GainFrame = Mult_32_16( GainFrame, 24576 ); + } + + /* Quantization of the frame gain parameter */ + QuantizeSHBframegain_fx( st_fx, &GainFrame, st_fx->extl_fx, st_fx->extl_brate_fx, &st_fx->rf_bwe_gainFr_ind ); + + /* Adjust the subframe and frame gain of the synthesized SHB signal */ + /* Scale the shaped excitation*/ + ScaleShapedSHB_fx( SHB_OVERLAP_LEN / 2, shaped_wb_excitation, st_fx->syn_overlap_fx, GainShape, GainFrame, window_wb_fx, subwin_wb_fx, + &Q_bwe_exc_ext, &dummy, dummy, dummy ); + + st_fx->prev_Q_bwe_exc = Q_bwe_exc; + move16(); + + return; +} + + +void fb_tbe_reset_enc_fx( + Word32 elliptic_bpf_2_48k_mem_fx[][4], + Word32 *prev_fb_energy_fx + ,Word16 elliptic_bpf_2_48k_mem_fx_Q[], + Word16 *prev_fb_energy_fx_Q +) +{ + set32_fx( elliptic_bpf_2_48k_mem_fx[0], 0, 4 ); + set32_fx( elliptic_bpf_2_48k_mem_fx[1], 0, 4 ); + set32_fx( elliptic_bpf_2_48k_mem_fx[2], 0, 4 ); + set32_fx( elliptic_bpf_2_48k_mem_fx[3], 0, 4 ); + *prev_fb_energy_fx = 0; + move16(); + set16_fx(elliptic_bpf_2_48k_mem_fx_Q, 0, 4); + *prev_fb_energy_fx_Q = 0; + move16(); + + return; +} +/*======================================================================================*/ +/* FUNCTION : void swb_tbe_enc_fx () */ +/*--------------------------------------------------------------------------------------*/ +/* PURPOSE : SWB TBE encoder, 6 - 14 kHz (or 7.5 - 15.5 kHz) band encoding module */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16) coder_type_fx : coding type */ +/* _(Word16*) shb_speech_fx : SHB target signal (6-14kHz) at 16kHz Q0 */ +/* _(Word16*) bwe_exc_extended :bandwidth extended exciatation Q0 */ +/* _(Word16[]) voice_factors :voicing factors Q15 */ +/* _(Word16*) Q_white_exc :Q Format of White Exc */ +/*--------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16[])White_exc16k_fx : shaped white excitation for the FB TBE Q_white_exc */ +/* _(Word16*)fb_slope_fx : slope +ve (high freq > low freq), -ve or neutral Q12 */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ Encoder_State_fx *st_fx: : Encoder state structure */ +/*--------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*======================================================================================*/ + +void swb_tbe_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 coder_type_fx, /* i : coding type */ + Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz Q_shb*/ + Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation 2*Q_new*/ + const Word16 voice_factors_fx[], /* i : voicing factors Q15*/ + Word16 *White_exc16k_fx, /* o : shaped white excitation for the FB TBE Q_white_exc*/ + Word16 *Q_white_exc, + Word16 Q_new, + Word16 Q_shb, + Word16 *voicing, /* i : OL maximum normalized correlation */ + const Word16 pitch_buf[] /* i : subframe pitch Q6*/ +) +{ + Word16 i, j; + + Word16 shb_old_speech_fx[ L_LOOK_16k + L_SUBFR16k + L_FRAME16k ]; + Word16 bwe_exc_extended_16[ L_FRAME32k+NL_BUFF_OFFSET ]; + + Word16 shaped_shb_excitation_fx [ L_FRAME16k + L_SHB_LAHEAD ]; + Word32 GainFrame_fx; + Word16 GainShape_fx[ NUM_SHB_SUBFR ]; + Word16 lpc_shb_fx[ LPC_SHB_ORDER + 1 ], lsp_shb_fx[ LPC_SHB_ORDER ], lsf_shb_fx[ LPC_SHB_ORDER ]; + Word16 weights_lsp[LPC_SHB_ORDER]; + Word16 Q_out; + Word16* shb_frame_fx, *shb_new_speech_fx; + Word16 R_h[ LPC_SHB_ORDER+ 2 ]; /* Autocorrelations of windowed speech MSB */ + Word16 R_l[ LPC_SHB_ORDER+ 2 ]; /* Autocorrelations of windowed speech LSB */ + Word16 Q_R; + Word32 LepsP[LPC_SHB_ORDER+1]; + + Word16 ana_align_delay[2] = {-L_SHB_LAHEAD - (NL_BUFF_OFFSET/2), -L_SHB_LAHEAD - (NL_BUFF_OFFSET/2)}; + Word32 prev_pow_fx, curr_pow_fx, Lscale; + Word32 p2m_in_fx, p2m_out_fx; + + Word16 exp_out, exp, exp1, frac; + Word16 cnt, n_mem, n_mem2; + Word32 L_tmp, L_tmp1; + Word16 Q_bwe_exc; + + Word16 frGainAttenuate, frGainSmoothEn; + Word16 MA_lsp_shb_spacing; + Word16 temp_swb_fac, feedback; + Word32 L_feedback; + Word16 tmp, tmp1, tmp2; + Word32 Lmax; + Word16 sc; + Word16 lsf_shb_orig_fx[LPC_SHB_ORDER]; + Word16 sd_uq_q_fx; + Word16 vf_modified_fx[NB_SUBFR16k]; + Word16 pitBufAvg_fx; + Word16 voicingBufAvg_fx; + Word16 sum1, sum2; + Word16 recip,Q_recip; + const Word16 *ptr_lsp_interp_coef_fx; + + Word16 lsp_shb_1_fx[LPC_SHB_ORDER], lsp_shb_2_fx[LPC_SHB_ORDER], lsp_temp_fx[LPC_SHB_ORDER]; + Word16 lpc_shb_sf_fx[4*(LPC_SHB_ORDER+1)]; + + /*Word32 shb_ener_sf_fx_32[4];*/ + Word32 shb_ener_sf_Q31; + Word16 shb_res_fx[L_FRAME16k]; + Word16 shb_res_gshape_fx[NB_SUBFR16k]; + Word32 shb_res_gshape_fx_32[NB_SUBFR16k]; + Word16 vf_ind_fx; + + Word16 formant_fac_fx; + Word16 shaped_shb_excitationTemp_fx[L_FRAME16k]; + + Word16 mean_vf; + Word16 lsf_diff[LPC_SHB_ORDER], w[LPC_SHB_ORDER]; + Word16 refl[M]; + Word16 tilt_para; + Word16 Q_bwe_exc_fb; + Word16 n_subfr_saturation; + + /* init and buffers set up */ + exp1 = 0; /* to avoid compilation warnings */ + set16_fx( shaped_shb_excitationTemp_fx, 0, L_FRAME16k ); + + /* compensate for the delay in target generation and subframe LA */ + shb_frame_fx = shb_old_speech_fx + L_SUBFR16k + ana_align_delay[0]; + move16(); + + /* set up the speech buffers for TBE processing*/ + shb_new_speech_fx = shb_old_speech_fx + (L_LOOK_16k + L_SUBFR16k); + move16(); + Copy( st_fx->old_speech_shb_fx, shb_old_speech_fx, (L_LOOK_16k + L_SUBFR16k) ); + Copy( shb_speech_fx, shb_new_speech_fx, L_FRAME16k ); + Copy( shb_old_speech_fx + L_FRAME16k, st_fx->old_speech_shb_fx, (L_LOOK_16k + L_SUBFR16k) ); + + /* autocorrelation of SHB speech for 10-th order LP analysis */ + autocorr_fx( shb_old_speech_fx, + LPC_SHB_ORDER + 1, + R_h, /* autocorr (msb) Q15 */ + R_l, /* autocorr (lsb) */ + &Q_R, + NS2SA(INT_FS_16k, ACELP_LOOK_NS) + L_SUBFR16k + L_FRAME16k, + win_lpc_shb_fx, + 0, + 1 ); + + + /* Spectral smoothing of autocorrelation coefficients */ + test(); + IF( (st_fx->rf_mode != 0) || EQ_32( st_fx->total_brate_fx, ACELP_9k60 )) + { + FOR( i = 1; i <= LPC_SHB_ORDER; i++ ) + { + L_tmp = Mpy_32( R_h[i], R_l[i], wac_swb_h[i - 1], wac_swb_l[i - 1] ); + L_Extract( L_tmp, &R_h[i], &R_l[i] ); + } + } + + /* Set the autocorr[0] element to a non-negative value */ + R_l[0] = s_max( R_l[0], 1 ); + move16(); + + E_LPC_lev_dur(R_h, R_l, lpc_shb_fx, LepsP, LPC_SHB_ORDER, NULL); /* LPC in Q14 */ + { + Word16 enerG, lpc_shb1[M+1]; + + /* extend the lpc_shb to a 16th order gain calc */ + set16_fx(lpc_shb1, 0, M+1); + Copy(lpc_shb_fx, lpc_shb1, LPC_SHB_ORDER + 1); + + /* estimate the LP gain */ + enerG = Enr_1_Az_fx(lpc_shb1, 2*L_SUBFR); /* Q3 */ + + /* if the LP gain is greater than a threshold, avoid saturation */ + IF(GT_16(enerG, 256/*32 Q3*/)) + { + set16_fx(lpc_shb_fx, 0, LPC_SHB_ORDER+1); + E_LPC_lev_dur(R_h, R_l, lpc_shb_fx, LepsP, 2, NULL); /* LPC in Q14 */ + } + } + + /* this is needed as the E_LPC_lev_dur function outputs lpc in Q14 */ + Copy_Scale_sig( lpc_shb_fx, lpc_shb_fx, LPC_SHB_ORDER+1, sub(norm_s(lpc_shb_fx[0]),2) ); + + /* Expand bandwidth of the LP coeffs */ + test(); + IF( (st_fx->rf_mode != 0) || EQ_32( st_fx->total_brate_fx, ACELP_9k60 )) + { + FOR( i = 1; i <= LPC_SHB_ORDER; i++ ) + { + lpc_shb_fx[i] = mult_r(lpc_shb_fx[i], lpc_weights_fx[i]); + } + } + + /* LPC to LSP conversion */ + /* LPC: Q12, LSP: Q15 */ + E_LPC_a_lsp_conversion(lpc_shb_fx, lsp_shb_fx, st_fx->prev_lsp_shb_fx, LPC_SHB_ORDER ); + + /* LSP to LSF conversion */ + /* LSP: Q15, LSF: Q15 */ + E_LPC_lsp_lsf_conversion( lsp_shb_fx, lsf_shb_fx, LPC_SHB_ORDER ); + + /* Input signal filtering in case of tonal sounds in the high band + gain Frame smoothing and attenuation control */ + gainFrSmooth_En_fx(st_fx, shb_frame_fx, lpc_shb_fx, lsf_shb_fx, &MA_lsp_shb_spacing, &frGainAttenuate, &frGainSmoothEn); + + Copy( lsp_shb_fx, st_fx->prev_lsp_shb_fx, LPC_SHB_ORDER ); + Copy( lsf_shb_fx, lsf_shb_orig_fx, LPC_SHB_ORDER ); + + test(); + IF( (EQ_16(st_fx->rf_mode,1))||EQ_32(st_fx->total_brate_fx,ACELP_9k60)) + { + lsp_weights_fx( lsf_shb_fx, weights_lsp, LPC_SHB_ORDER, &Q_out ); + + /* to compensate for the 1.1* weighting done inside the function lsp_weights */ + /*weights_lsp[3]*=0.909091f; weights_lsp[4]*=0.909091f; */ + weights_lsp[3] = mult_r( weights_lsp[3], 29789/*0.909091f Q15*/ ); + weights_lsp[4] = mult_r( weights_lsp[4], 29789/*0.909091f Q15*/ ); + + /* 8-bit VQ, 10 dimension */ + i = closest_centroid_fx( lsf_shb_fx, weights_lsp, swb_tbe_lsfvq_cbook_8b, 256, LPC_SHB_ORDER ); + Copy(swb_tbe_lsfvq_cbook_8b + i*LPC_SHB_ORDER, lsf_shb_fx, LPC_SHB_ORDER); + + set16_fx(st_fx->lsf_idx_fx, 0, NUM_Q_LSF); + st_fx->lsf_idx_fx[0] = i; + } + ELSE + { + /* LSF quantization (21 bits) */ + Quant_BWE_LSF_fx( st_fx, lsf_shb_fx, lsf_shb_fx ); + } + + /* space the lsfs to assert a minimum distance */ + space_lsfs_fx( lsf_shb_fx, LPC_SHB_ORDER ); + + /* voice factor adjustment and gainframe attenuation factor */ + tmp = sub( lsf_shb_fx[0], lsf_shb_orig_fx[0] ); + L_tmp = L_mult(tmp, tmp); + FOR( i = 1; i < LPC_SHB_ORDER; i++ ) + { + /* Estimate the QD in lsfs between UQ and Q */ + tmp = sub( lsf_shb_fx[i], lsf_shb_orig_fx[i] ); + L_tmp = L_mac( L_tmp, tmp, tmp ); + } + sd_uq_q_fx = round_fx(L_tmp); /* sd_uq_q_fx in Q15 */ + /* voice factor modification to limit any spurious jumps in the middle of voiced subframes*/ + /* mean(voice_factors_fx[i], 4); */ + + L_tmp = L_mult(voice_factors_fx[0], 8192); + L_tmp = L_mac(L_tmp, voice_factors_fx[1], 8192); + L_tmp = L_mac(L_tmp, voice_factors_fx[2], 8192); + mean_vf = mac_r(L_tmp, voice_factors_fx[3], 8192); + + Copy( voice_factors_fx, vf_modified_fx, NB_SUBFR16k ); + + test(); + IF( EQ_16(coder_type_fx, VOICED)||GT_16(mean_vf,13107/*0.4f Q15*/)) + { + FOR( i = 1; i < NB_SUBFR; i++ ) + { + L_tmp = L_mult(voice_factors_fx[i], 26214); + vf_modified_fx[i] = mac_r(L_tmp, voice_factors_fx[i-1], 6554); + move16(); + } + IF( NE_16(st_fx->L_frame_fx, L_FRAME)) + { + L_tmp = L_mult(voice_factors_fx[4], 26214); + vf_modified_fx[4] = mac_r(L_tmp, voice_factors_fx[3], 6554); + move16(); + } + } + + /* convert quantized LSFs to LSPs for interpolation */ + E_LPC_lsf_lsp_conversion(lsf_shb_fx, lsp_shb_2_fx, LPC_SHB_ORDER); + + test(); + IF( EQ_16(st_fx->last_extl_fx, SWB_TBE)||EQ_16(st_fx->last_extl_fx,FB_TBE)) + { + /* SHB LSP values from prev. frame for interpolation */ + Copy(st_fx->swb_lsp_prev_interp_fx, lsp_shb_1_fx, LPC_SHB_ORDER); + } + ELSE + { + /* Use current frame's LSPs; in effect no interpolation */ + Copy(lsp_shb_2_fx, lsp_shb_1_fx, LPC_SHB_ORDER); + } + + lsf_diff[0] = lsf_diff[sub(LPC_SHB_ORDER,1)] = 16384;/*Q15*/ + FOR(i=1; i < LPC_SHB_ORDER-1; i++) + { + lsf_diff[i] = sub(lsf_shb_fx[i],lsf_shb_fx[sub(i,1)]); + } + a2rc_fx (st_fx->cur_sub_Aq_fx+1, refl, M); + + /* LSP interpolation for 13.2 kbps and 16.4 kbps */ + /* tilt_para = 6.6956f * (1.0f + refl[0]) * (1.0f + refl[0]) + - 3.8714f * (1.0f + refl[0]) + + 1.3041f; */ + tmp = add(16384,shr(refl[0],1));/*Q14*/ + tmp1 = mult(27425 /*Q12*/,tmp);/*Q11*/ + tmp1 = mult(tmp1,tmp); + tmp2 = shr(mult(31715,tmp),2); /* Q11 */ + tilt_para = add(sub(tmp1,tmp2),1335);/*Q10*/ + + IF(NE_16(st_fx->last_extl_fx,SWB_TBE)) + { + FOR( i=1; iprev_lsf_diff_fx[i-1] = mult(lsf_diff[i],16384);/*Q15*/ + } + } + + IF( LE_32(st_fx->total_brate_fx,ACELP_16k40)) + { + test(); + test(); + test(); + test(); + test(); + IF(!(GT_16(st_fx->prev_tilt_para_fx,5120)&&(EQ_16(coder_type_fx,TRANSITION)||LT_16(tilt_para,1024)))&& + !(((LT_16(st_fx->prev_tilt_para_fx,3072) && GE_16(st_fx->prev_coder_type_fx,VOICED) )) && GT_16(tilt_para,5120) )) + { + FOR( i = 1; i < LPC_SHB_ORDER-1; i++ ) + { + IF(LT_16(lsf_diff[i],st_fx->prev_lsf_diff_fx[i-1])) + { + tmp = mult(26214,lsf_diff[i]); + tmp = div_s(tmp,st_fx->prev_lsf_diff_fx[i-1]); + tmp = s_max(tmp,16384); + w[i] = s_min(tmp,32767); + } + ELSE + { + tmp = mult(26214,st_fx->prev_lsf_diff_fx[i-1]); + tmp = div_s(tmp,lsf_diff[i]); + tmp = s_max(tmp,16384); + w[i] = s_min(tmp,32767); + } + } + w[0] = w[1]; + w[sub(LPC_SHB_ORDER,1)] = w[sub(LPC_SHB_ORDER,2)]; + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + tmp1 = mult(lsp_shb_1_fx[i],sub(32767,w[i])); + tmp2 = mult(lsp_shb_2_fx[i],w[i]); + lsp_temp_fx[i] =add(tmp1,tmp2); + } + } + ELSE + { + Copy(lsp_shb_2_fx, lsp_temp_fx, LPC_SHB_ORDER); + } + } + + Copy( lsf_diff + 1, st_fx->prev_lsf_diff_fx, LPC_SHB_ORDER-2 ); + st_fx->prev_tilt_para_fx = tilt_para; + + shb_ener_sf_Q31 = 0; + move16(); + test(); + IF ( EQ_32(st_fx->total_brate_fx, ACELP_24k40 )||EQ_32(st_fx->total_brate_fx,ACELP_32k)) + { + /* ---------- SHB LSP interpolation ---------- */ + ptr_lsp_interp_coef_fx = interpol_frac_shb; /* Q15 */ + FOR( j = 0; j < 4; j++ ) + { + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + /*lsp_temp_fx[i] = lsp_shb_1_fx[i]*(*ptr_lsp_interp_coef_fx) */ + /* + lsp_shb_2_fx[i]*(*(ptr_lsp_interp_coef_fx+1)); */ + L_tmp = L_mult(lsp_shb_1_fx[i], (*ptr_lsp_interp_coef_fx)); + lsp_temp_fx[i] = mac_r(L_tmp, lsp_shb_2_fx[i], (*(ptr_lsp_interp_coef_fx+1))); + move16(); + } + ptr_lsp_interp_coef_fx += 2; + + tmp = i_mult2(j, (LPC_SHB_ORDER+1)); + /* convert LSPs to LPC coefficients for SHB synthesis*/ + E_LPC_f_lsp_a_conversion(lsp_temp_fx, lpc_shb_sf_fx+tmp, LPC_SHB_ORDER); + /* Bring the LPCs to Q12 */ + Copy_Scale_sig( lpc_shb_sf_fx+tmp, lpc_shb_sf_fx+tmp, LPC_SHB_ORDER+1, sub(norm_s(lpc_shb_sf_fx[tmp]),2) ); + } + + /* -------- Calculate the SHB Energy -------- */ + /*shb_ener_sf[0] = 0.003125f * sum2_f( shb_frame + L_SHB_LAHEAD, 320 );*/ + FOR( i = L_SHB_LAHEAD; i < L_FRAME16k + L_SHB_LAHEAD; i++) + { + /* shbEner = shbEner + in[i] * in[i] */ + shb_ener_sf_Q31 = L_mac0(shb_ener_sf_Q31, shb_frame_fx[i], shb_frame_fx[i]); + /* o: shb_ener_sf_Q31 in (2*Q_shb) */ + } + shb_ener_sf_Q31= Mult_32_16(shb_ener_sf_Q31, 102/*0.003125f Q15*/); + shb_ener_sf_Q31= L_add(1l/*1 Q0*/, shb_ener_sf_Q31); + Quant_shb_ener_sf_fx(st_fx, &shb_ener_sf_Q31, (2*Q_shb)); + + /* -------- calculate the residuals using the FOUR subframe LPCs -------- */ + set16_fx(shb_res_fx, 0, L_FRAME16k); + Residu3_10_fx(lpc_shb_sf_fx, shb_frame_fx + L_SHB_LAHEAD, shb_res_fx, 80, 0); + Residu3_10_fx(lpc_shb_sf_fx + (LPC_SHB_ORDER+1), shb_frame_fx + L_SHB_LAHEAD + 80, shb_res_fx + 80, 80, 0); + Residu3_10_fx(lpc_shb_sf_fx + 2*(LPC_SHB_ORDER+1), shb_frame_fx + L_SHB_LAHEAD + 160, shb_res_fx + 160, 80, 0); + Residu3_10_fx(lpc_shb_sf_fx + 3*(LPC_SHB_ORDER+1), shb_frame_fx + L_SHB_LAHEAD + 240, shb_res_fx + 240, 80, 0); + /* i: shb_frame_fx in Q_shb */ + /* o: shb_res_fx in Q_shb */ + + set32_fx(shb_res_gshape_fx_32, 0, NB_SUBFR16k); + FOR(i = 0; i < NB_SUBFR16k; i++) + { + shb_res_gshape_fx_32[i] = sum2_fx(shb_res_fx+i*64, 64); + } + /* o: shb_res_gshape_fx_32 in (2*Q_shb+1) */ + + maximum_32_fx(shb_res_gshape_fx_32, NB_SUBFR16k, &L_tmp); + + /* root_a_over_b_fx(shb_res_gshape_fx_32[i], (2*Q_shb+1), L_tmp, (2*Q_shb+1), &exp);*/ + /* First, find 1/L_tmp, L_tmp in QA = (2*Q_shb+1) */ + + /* case when den = 0 */ + recip = 0; /*instead of 32767 to be compatible with previous root_a_over_b_fx() output */ + Q_recip = 0; + + IF(L_tmp) + { + exp = norm_l(L_tmp); + tmp = extract_h(L_shl(L_tmp,exp)); + recip = div_s(16384,tmp); + Q_recip = 31-(exp-14); /* = 31-(exp+2*Q_shb+1-14), but adjusted by (2*Q_shb+1) for use at Mult_32_16 below */ + } + + FOR(i = 0; i < NB_SUBFR16k; i++) + { + L_tmp1 = Mult_32_16(shb_res_gshape_fx_32[i], recip); /*Q = Q_recip+1-16*/ + L_tmp = root_a_fx( L_tmp1, Q_recip+1-16, &exp ); + shb_res_gshape_fx[i] = round_fx(L_shl(L_tmp, exp-1)); /* Q14 */ + } + + Quant_shb_res_gshape_fx(st_fx, shb_res_gshape_fx); + } + + /* for 13.2 and 16.4kbps */ + E_LPC_f_lsp_a_conversion(lsp_temp_fx, lpc_shb_fx, LPC_SHB_ORDER); + Copy_Scale_sig( lpc_shb_fx, lpc_shb_fx, LPC_SHB_ORDER+1, sub(norm_s(lpc_shb_fx[0]),2) ); /* Q12 */ + + /* Save the SWB LSP values from current frame for interpolation */ + Copy(lsp_shb_2_fx, st_fx->swb_lsp_prev_interp_fx, LPC_SHB_ORDER); /* lsp_shb_2_fx in Q15 */ + + /* -------- start of memory rescaling -------- */ + /* ----- calculate optimum Q_bwe_exc and rescale memories accordingly ----- */ + Lmax = L_deposit_l(0); + FOR( cnt = 0; cnt < L_FRAME32k; cnt++ ) + { + Lmax = L_max( Lmax, L_abs( bwe_exc_extended[cnt] ) ); + } + Q_bwe_exc = norm_l( Lmax ); + if(Lmax == 0) + { + Q_bwe_exc = 31; + } + Q_bwe_exc = add( Q_bwe_exc, add( Q_new, Q_new ) ); + + /* Account for any outliers in the memories from previous frame for rescaling to avoid saturation */ + find_max_mem_enc( st_fx, &n_mem, &n_mem2); + + tmp2 = add( st_fx->prev_Q_bwe_exc, n_mem ); + if( GT_16( Q_bwe_exc, tmp2)) + { + Q_bwe_exc = tmp2; + } + + /* rescale the memories if Q_bwe_exc is different from previous frame */ + sc = sub( Q_bwe_exc, st_fx->prev_Q_bwe_exc ); + IF( sc != 0 ) + { + rescale_genSHB_mem_enc( st_fx, sc ); + } + + /* rescale the bwe_exc_extended and bring it to 16-bit single precision with dynamic norm */ + Copy( st_fx->old_bwe_exc_extended_fx, bwe_exc_extended_16, NL_BUFF_OFFSET ); + sc = sub( Q_bwe_exc, add( Q_new, Q_new ) ); + + FOR( cnt = 0; cnt < L_FRAME32k; cnt++ ) + { + bwe_exc_extended_16[cnt + NL_BUFF_OFFSET] = round_fx( L_shl( bwe_exc_extended[cnt], sc ) ); + } + Copy( bwe_exc_extended_16 + L_FRAME32k, st_fx->old_bwe_exc_extended_fx, NL_BUFF_OFFSET ); + + /* state_syn_shbexc_fx is kept at (st_fx->prev_Q_bwe_syn) for 24.4/32kbps or is kept at Q_bwe_exc for 13.2/16.4kbps */ + Copy( st_fx->state_syn_shbexc_fx, shaped_shb_excitation_fx, L_SHB_LAHEAD ); + + /* save the previous Q factor of the buffer */ + st_fx->prev_Q_bwe_exc = Q_bwe_exc; + move16(); + + Q_bwe_exc = sub( Q_bwe_exc, 16 ); /* Q_bwe_exc reflecting the single precision dynamic norm-ed buffers from here */ + + /* -------- end of rescaling memories -------- */ + Q_bwe_exc_fb = st_fx->prev_Q_bwe_exc_fb; + move16(); + /* Determine formant PF strength */ + formant_fac_fx = swb_formant_fac_fx( lpc_shb_fx[1], &st_fx->tilt_mem_fx ); + /* i:lpc_shb_fx Q12, o:formant_fac_fx Q15 */ + + /* Calculate the 6 to 14 kHz (or 7.5 - 15.5 kHz) SHB excitation signal from the ACELP core excitation */ + vf_ind_fx = 20; + move16(); + + GenShapedSHBExcitation_fx( shaped_shb_excitation_fx + L_SHB_LAHEAD, lpc_shb_fx, White_exc16k_fx, + st_fx->mem_csfilt_fx, st_fx->mem_genSHBexc_filt_down_shb_fx, st_fx->state_lpc_syn_fx, + coder_type_fx, bwe_exc_extended_16, st_fx->bwe_seed_fx, vf_modified_fx, st_fx->extl_fx, + &( st_fx->tbe_demph_fx ), &( st_fx->tbe_premph_fx ), lpc_shb_sf_fx, shb_ener_sf_Q31, + shb_res_gshape_fx, shb_res_fx, &vf_ind_fx, formant_fac_fx, st_fx->fb_state_lpc_syn_fx, + &(st_fx->fb_tbe_demph_fx), &Q_bwe_exc,&Q_bwe_exc_fb, Q_shb, n_mem2, st_fx->prev_Q_bwe_syn, st_fx->total_brate_fx, 0 ); + + *Q_white_exc = Q_bwe_exc_fb; + IF( EQ_16(st_fx->extl_fx, FB_TBE)) + { + st_fx->prev_Q_bwe_exc_fb = Q_bwe_exc_fb; + } + ELSE + { + /*Indirectly a memory reset of FB memories for next frame such that rescaling of memories would lead to 0 due to such high prev. Q value. + 51 because of 31 + 20(shift of Q_bwe_exc_fb before de-emphasis)*/ + st_fx->prev_Q_bwe_exc_fb = 51; + move16(); + } + + test(); + IF( EQ_32(st_fx->total_brate_fx, ACELP_24k40)||EQ_32(st_fx->total_brate_fx,ACELP_32k)) + { + IF( EQ_16( st_fx->codec_mode, MODE2 )) + { + st_fx->idx_mixFac_fx = vf_ind_fx; + move16(); + } + ELSE + { + push_indice_fx( st_fx, IND_SHB_VF, vf_ind_fx, NUM_BITS_SHB_VF); + } + } + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + st_fx->mem_stp_swb_fx[i] = shl(st_fx->mem_stp_swb_fx[i], sub(Q_bwe_exc, st_fx->prev_Q_bwe_syn) ); + } + + FOR( i = 0; i < L_FRAME16k; i += L_SUBFR16k ) + { + PostShortTerm_fx( &shaped_shb_excitation_fx[L_SHB_LAHEAD+i], lpc_shb_fx, &shaped_shb_excitationTemp_fx[i], st_fx->mem_stp_swb_fx, + st_fx->ptr_mem_stp_swb_fx, &(st_fx->gain_prec_swb_fx), st_fx->mem_zero_swb_fx, formant_fac_fx ); + /* i: shaped_shb_excitation_fx in Q_bwe_exc */ + /* i: lpc_shb_fx in Q12 */ + } + Copy( shaped_shb_excitationTemp_fx, &shaped_shb_excitation_fx[L_SHB_LAHEAD], L_FRAME16k ); + + + + tmp = sub(shl(Q_bwe_exc, 1), 31); + prev_pow_fx = L_shl(21475l/*0.00001f Q31*/, tmp); /* 2*(Q_bwe_exc) */ + curr_pow_fx = L_shl(21475l/*0.00001f Q31*/, tmp); /* 2*(Q_bwe_exc) */ + FOR( i = 0; i < L_SHB_LAHEAD + 10; i++ ) + { + prev_pow_fx = L_mac0( prev_pow_fx, shaped_shb_excitation_fx[i], shaped_shb_excitation_fx[i] ); /* 2*Q_bwe_exc */ + curr_pow_fx = L_mac0( curr_pow_fx, shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10] ); /* 2*Q_bwe_exc */ + } + + if( GT_16( voice_factors_fx[0], 24576/*0.75f Q15*/ )) + { + /*curr_pow_fx = Mult_32_16( curr_pow_fx, 8192);*/ /* Q(2*Q_bwe_exc) */ + curr_pow_fx = L_shr(curr_pow_fx, 2); /* scale by 0.25 */ + } + + Lscale = root_a_over_b_fx( curr_pow_fx, + shl(Q_bwe_exc, 1), + prev_pow_fx, + shl(Q_bwe_exc, 1), + &exp ); + FOR( i = 0; i < L_SHB_LAHEAD; i++ ) + { + L_tmp = Mult_32_16( Lscale, shaped_shb_excitation_fx[i] ); /* Q(16-exp+Q_bwe_exc) */ + shaped_shb_excitation_fx[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc */ + } + IF( exp < 0 ) + { + Lscale = L_shl(Lscale, exp); + exp = 0; + } + FOR( ; i < L_SHB_LAHEAD + 10; i++ ) + { + tmp = i_mult(sub(i,19), 3277/*0.1f Q15*/); /* Q15 */ + L_tmp1 = Mult_32_16(L_shl(1, sub(31,exp)), tmp); /* Q31-exp */ + tmp = sub(32767/*1.0f Q15*/, tmp); + Lscale = L_add(Mult_32_16(Lscale, tmp), L_tmp1); + L_tmp = Mult_32_16( Lscale, shaped_shb_excitation_fx[i] ); /* Q_bwe_exc + (31-exp) - 15 */ + shaped_shb_excitation_fx[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc */ + } + + /* Update SHB excitation */ + Copy( shaped_shb_excitation_fx + L_FRAME16k, st_fx->state_syn_shbexc_fx, L_SHB_LAHEAD ); /* Q_bwe_exc */ + + /* Estimate the gain-shape parameter */ + n_subfr_saturation = 0; + move16(); + EstimateSHBGainShape_fx( SHB_OVERLAP_LEN, shb_frame_fx, Q_shb, shaped_shb_excitation_fx, + Q_bwe_exc, GainShape_fx, subwin_shb_fx, &n_subfr_saturation ); + + /* Gain shape BWS/high band low energy fix */ + IF( LT_16(st_fx->cldfbHBLT, 8192/*1.0f Q13*/)) /* cldfbHBLT in Q13 */ + { + /* There is not much HB past 10kHz; the temporal resolution is quite coarse, so reduce the dynamic range */ + FOR(i = 0; i < NUM_SHB_SUBGAINS; i++) + { + /* 0.35f +/- delta variation; delta = 0.1*(GS-0.35)*/ + /* GainShape[i] = 0.315f + 0.1f * GainShape[i]; */ + GainShape_fx[i] = mac_r(676457349l/*0.315 Q31*/, 3277/*0.1 Q15*/, GainShape_fx[i]); + } + } + + /* Gain frame adjustment factor */ + /* log( (GainShape[0]) / (st->prev_wb_GainShape) )*/ + test(); + IF( GainShape_fx[0] && st_fx->prev_swb_GainShape_fx ) + { + exp = norm_s( st_fx->prev_swb_GainShape_fx ); + tmp = div_s( shl(1, sub( 14, exp )), st_fx->prev_swb_GainShape_fx ); + L_tmp = L_mult( GainShape_fx[0], tmp );/*Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) );/*move16(); */ + exp1 = sub(exp, exp1 ); /*move16(); */ + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_swb_fac = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_swb_fac = 0; + move16(); + } + L_feedback = L_mult0( temp_swb_fac, temp_swb_fac ); + + + FOR( i = 1; i < NUM_SHB_SUBGAINS; i++ ) + { + test(); + IF( GainShape_fx[i] && GainShape_fx[i - 1] ) + { + exp = norm_s( GainShape_fx[i - 1] ); + tmp = div_s( shl(1, sub( 14, exp )), GainShape_fx[i - 1] ); + L_tmp = L_mult( GainShape_fx[i], tmp );/* Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) ); + exp1 = sub( exp , exp1 ); + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_swb_fac = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_swb_fac = 0; + move16(); + } + + L_feedback = L_mac( L_feedback, temp_swb_fac, temp_swb_fac ); + } + + /* feedback = 0.4f / (1 + 0.5f * feedback) */ + L_tmp = L_add( L_shr( L_feedback, 1 ), L_shl(1,21) ); /* Q21 */ + IF( L_tmp != 0 ) + { + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + exp = sub( sub( 30, exp ), 21 ); + tmp = div_s( 16384, tmp ); /*Q(15+exp) */ + L_tmp = L_shr( L_mult( 13107, tmp ), exp ); /*Q31 */ + feedback = round_fx( L_tmp ); /*Q15 */ + } + ELSE + { + feedback = 8738; + move16(); /*Q15 */ + } + + /* voicing in Q15 */ + L_tmp = L_mult(voicing[0],8192); + L_tmp = L_mac(L_tmp, voicing[1],8192); + L_tmp = L_mac(L_tmp, voicing[2],8192); + tmp = sum1 = round_fx(L_tmp); /* sum1 used again below - Q13 */ + tmp = add(tmp,1); /* To ensure change is BE */ + + /* voice_factors_fx in Q15 */ + L_tmp = L_mult(voice_factors_fx[0],8192); + L_tmp = L_mac(L_tmp, voice_factors_fx[1],8192); + L_tmp = L_mac(L_tmp, voice_factors_fx[2],8192); + L_tmp = L_mac(L_tmp, voice_factors_fx[3],8192); + tmp1 = sum2 = round_fx(L_tmp); /* sum2 used again below - Q13 */ + + + test(); + test(); + IF( EQ_16(frGainAttenuate,1)||(GT_16(tmp,19661)&>_16(tmp1,6554))) + + { + temp_swb_fac = st_fx->prev_swb_GainShape_fx; + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + /*GainShape_fx[i] = (1 - feedback) * GainShape[i] + feedback * temp_swb_fac; */ + GainShape_fx[i] = round_fx(L_mac(L_mult(sub( 32767, feedback ), GainShape_fx[i] ),feedback, temp_swb_fac ) ); + temp_swb_fac = GainShape_fx[i]; + move16(); + } + } + st_fx->prev_swb_GainShape_fx = GainShape_fx[3]; + move16(); + + /* Compute the power of gains away from the peak gain prior to quantization */ + p2m_in_fx = pow_off_pk_fx( GainShape_fx, NUM_SHB_SUBGAINS, 1 ); + + /* Quantization of the gain shape parameter */ + + QuantizeSHBsubgains_fx( st_fx, GainShape_fx, st_fx->extl_fx ); + /* o: GainShape_fx in Q15 */ + /* Compute the power of gains away from the peak gain after quantization */ + p2m_out_fx = pow_off_pk_fx( GainShape_fx, NUM_SHB_SUBFR, 4 ); + + /* Estimate the gain parameter */ + EstimateSHBFrameGain_fx( SHB_OVERLAP_LEN, shb_frame_fx, Q_shb, shaped_shb_excitation_fx, Q_bwe_exc, + GainShape_fx, &GainFrame_fx, window_shb_fx, subwin_shb_fx, n_subfr_saturation ); + + IF( EQ_16(st_fx->tec_tfa, 1)) + { + tfaCalcEnv_fx( shb_frame_fx, st_fx->tfa_enr ); + } + + /* If there's a big difference in the power of gains away from the peak gain */ + /* due to poor quantization then suppress energy of the high band. */ + IF( GT_32( p2m_out_fx, L_shl( p2m_in_fx, 1 ) )) + { + L_tmp = root_a_over_b_fx( p2m_in_fx, 28, p2m_out_fx, 29, &exp_out ); + GainFrame_fx = L_shl( Mult_32_32( GainFrame_fx, L_tmp ), exp_out ); /* Q18 */ + } + test(); + IF( EQ_16(frGainSmoothEn,1)&<_32(st_fx->prev_gainFr_SHB_fx,GainFrame_fx)) + { + GainFrame_fx = L_add( L_shr(st_fx->prev_gainFr_SHB_fx, 1), L_shr(GainFrame_fx, 1) ); /* Q18 */ + } + + test(); + IF( EQ_16(frGainAttenuate, 1)&&LE_16(MA_lsp_shb_spacing,79/*0.0024f Q15*/)) + { + exp1 = norm_l( GainFrame_fx ); + frac = Log2_norm_lc( L_shl( GainFrame_fx, exp1 ) ); + exp = sub(30, add( exp1, 21 ) ); + L_tmp = Mpy_32_16( exp, frac, 26214 ); /* Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + GainFrame_fx = Pow2( 30, frac ); + exp = sub( exp, 30); + GainFrame_fx = L_shl( GainFrame_fx, exp + 18 ); /* Q18 */ + } + ELSE IF( EQ_16(st_fx->prev_frGainAtten_fx, 1)&>_32(Mult_32_16(GainFrame_fx,10923),st_fx->prev_gainFr_SHB_fx)) + { + /*GainFrame *= (0.8f + 0.5f*feedback); */ + tmp = add( 26214, mult_r( feedback, 16384 ) ); + GainFrame_fx = Mult_32_16( GainFrame_fx, tmp ); /* Q18 */ + } + st_fx->prev_frGainAtten_fx = frGainAttenuate; + move16(); + st_fx->prev_gainFr_SHB_fx = GainFrame_fx; + move16(); /* Q18 */ + + + /* Gain attenuation when the SWB LSF quantization error is larger than a threshold */ + tmp = mult_r(25600/*400 Q6*/, sd_uq_q_fx); /* Q6 * Q15 => Q6 */ + IF(EQ_16(st_fx->L_frame_fx, L_FRAME)) + { + tmp1 = mult_r(6554/*0.2f Q15*/, tmp); /* Q15, Q6 => Q6 */ + L_tmp = L_msu(8192l/*1.0f Q13*/, tmp1, tmp); /* Q13 */ + } + ELSE + { + tmp1 = mult_r(3277/*0.1f Q15*/, tmp); /* Q15, Q6 => Q6 */ + L_tmp = L_msu(8192l/*1.0f Q13*/, tmp1, tmp); /* Q13 */ + } + /* sd_uq_q = max(min(sd_uq_q, 1.0f), 0.5f); */ + L_tmp = L_min(L_tmp, 8192l/*1.0f Q13*/); + L_tmp = L_max(L_tmp, 4096l/*0.5f Q13*/); /* Q13 */ + /* keep the L_tmp; dont overwrite */ + + /* pitBufAvg = 0.0025f * sum_f(pitch_buf, 4); */ + /* pitch_buf: Q6 */ + pitBufAvg_fx = mult_r(pitch_buf[0],1311) ; + pitBufAvg_fx = add( pitBufAvg_fx, mult_r(pitch_buf[1],1311) ); + pitBufAvg_fx = add( pitBufAvg_fx, mult_r(pitch_buf[2],1311) ); + pitBufAvg_fx = add( pitBufAvg_fx, mult_r(pitch_buf[3],1311) ); /* Q10 */ + + /* voicingBufAvg = (sum_f(voice_factors, 4)=sum2 > 0.6f) ? 0.333f : 0.1667f; */ + tmp2 = 5462/*0.1667f Q15*/; + if(GT_16(sum2, 4915/*0.6f Q13*/)) + { + tmp2 = 10912/*0.333f Q15*/; /* Q15 */ + } + voicingBufAvg_fx = shl(mult(tmp2, sum1),2); /* Q15 */ + + + + /* max(min((float)(sd_uq_q*pitBufAvg/voicingBufAvg), 1.0f), 0.6f) */ + /* sd_uq_q: Q13, pitBufAvg_fx: Q6, voicingBufAvg_fx: Q15 */ + + /* 1/voicingBufAvg_fx */ + tmp = 32767; + move16(); + IF( voicingBufAvg_fx > 0 ) + { + exp = norm_s( voicingBufAvg_fx ); + tmp = div_s( shl(1, sub( 14, exp )), voicingBufAvg_fx ); /* (14-exp) */ + + /* sd_uq_q*pitBufAvg */ + L_tmp = Mult_32_16(L_tmp, pitBufAvg_fx); /* Q13 * Q10 + 1 -16 => Q8 */ + L_tmp = Mult_32_16(L_tmp, tmp ); /* Q8 + (14 - exp) - 15 => Q7 - exp */ + tmp = round_fx(L_shl(L_tmp, 31-(7-exp))); /* Q15 */ + } + + tmp = s_min(tmp, 32767/*1.0f Q15*/); + tmp = s_max(tmp, 19661/*0.6f Q15*/); + GainFrame_fx = Mult_32_16(GainFrame_fx, tmp); /* Q18 + Q15 + 1 - 16 : Q18 */ + + test(); + IF(EQ_16(st_fx->L_frame_fx, L_FRAME16k)||EQ_16(st_fx->rf_mode,1)) + { + /* Compensate for energy increase mismatch due to memory-less synthesis*/ + GainFrame_fx = Mult_32_16(GainFrame_fx, 27853/*0.85f Q15*/ ); /* Q18 */ + } + + /* Quantization of the frame gain parameter */ + QuantizeSHBframegain_fx( st_fx, &GainFrame_fx, st_fx->extl_fx, 0, &st_fx->rf_bwe_gainFr_ind ); + + /* Adjust the subframe and frame gain of the synthesized SHB signal */ + /* Scale the shaped excitation */ + IF( EQ_32(st_fx->extl_fx,FB_TBE)) + { + tmp = norm_l( GainFrame_fx ); + if(GainFrame_fx == 0) + { + tmp = 31; + } + L_tmp = L_shl(GainFrame_fx,tmp);/* 18 + tmp */ + + tmp1 =0; + FOR( i = 0; i < L_FRAME16k; i++ ) + { + L_tmp1 = Mult_32_16( L_tmp, GainShape_fx[NUM_SHB_SUBFR * i / L_FRAME16k] ); /* Q : 18 + tmp +15 -15*/ + /*White_exc16k_fx[i] = round_fx( L_shl(Mult_32_16( L_tmp1, White_exc16k_fx[i]),(23 - tmp -*Q_white_exc)) );*/ + /*18 + tmp +*Q_white_exc -15 + 23 - tmp -*Q_white_exc -16 = 10*/ + White_exc16k_fx[i] = round_fx( Mult_32_16( L_tmp1, White_exc16k_fx[i] ) );/* 18 + tmp +*Q_white_exc -15 -16 */ + /*Lmax = L_max(Lmax,White_exc16k_fx[i]);*/ + tmp1 = s_max(tmp1,abs_s(White_exc16k_fx[i])); + /*White_exc16k_fx[i] =32767;*/ + /*White_exc16k_fx[i] = shr(White_exc16k_fx[i],5);*/ + } + *Q_white_exc = sub(add(*Q_white_exc, tmp),13); /* *Q_white_exc + 18 + tmp -15 -16 */ + tmp = norm_s( tmp1 ); + if(tmp1 == 0) + { + tmp = 15; + } + + FOR(i=0; iprev_Q_bwe_syn = Q_bwe_exc; + move16(); + + return; +} + + +/*==========================================================================*/ +/* FUNCTION : static void EstimateSHBFrameGain_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Estimate the overall gain factor needed to scale */ +/* synthesized highband to original highband signal level. */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16) length : SHB overlap length Q0 */ +/* _(Word16*) oriSHB : target original SHB frame Q_oriSHB */ +/* _(Word16*) synSHB : shaped SHB excitation Q_synSHB */ +/* _(Word16*) win_shb : SHB window Q15 */ +/* _(Word16*) subwin_shb : SHB subframe window Q15 */ +/* _(Word16) Q_oriSHB : Q format of oriSHB */ +/* _(Word16) Q_synSHB : Q format of synSHB */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word32*)GainFrame :estimat of gain frame Q18 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ + +static void EstimateSHBFrameGain_fx( + const Word16 length, /* i : SHB overlap length */ + const Word16* oriSHB, /* i : target original SHB frame Q_oriSHB */ + const Word16 Q_oriSHB, + const Word16* synSHB, /* i : shaped SHB excitation Q_synSHB */ + const Word16 Q_synSHB, + Word16* subgain, /* i : estimate of gain shape Q15 */ + Word32* GainFrame, /* o : estimat of gain frame Q18 */ + const Word16* win_shb, /* i : SHB window Q15 */ + const Word16* subwin_shb /* i : SHB subframe window Q15 */ + ,const Word16 n_subfr_saturation /* i : Number of subframes which saturated in GainShape oriNrg calculation */ +) +{ + const Word16* skip; + Word16 i, j, k, l_shb_lahead, l_frame; + Word16 join_length, num_join, sig; + Word32 mod_syn[L_FRAME16k+L_SHB_LAHEAD]; + Word32 oriNrg = 0, synNrg = 0; + Word16 sum_gain; + Word32 frame_gain; + Word32 L_tmp; + Word16 exp_out; + Word16 tmp; + Word16 scaling = 0; + + + /* initilaization */ + l_frame = L_FRAME16k; + move16(); + l_shb_lahead = L_SHB_LAHEAD; + move16(); + skip = skip_bands_SWB_TBE; + + + IF( EQ_16(length,SHB_OVERLAP_LEN / 2)) + { + skip = skip_bands_WB_TBE; + l_frame = L_FRAME16k / 4; + move16(); + l_shb_lahead = L_SHB_LAHEAD / 4; + move16(); + } + + /* apply gain for each subframe, and store noise output signal using overlap-add*/ + set32_fx( mod_syn, 0, l_frame + l_shb_lahead ); + + + IF( EQ_16(length,SHB_OVERLAP_LEN / 2 )) + { + sum_gain = 0; + move16(); + j = skip[0]; + move16(); + FOR( k = 0; k < length / 2; k++ ) + { + sum_gain = mult_r( subwin_shb[2 * k + 2], subgain[0] ); /* Q15 */ + mod_syn[j + k] = L_mult( synSHB[j + k], sum_gain ); + move32();/* Q(16+Q_synSHB) */ + mod_syn[j + k + length / 2] = L_mult( synSHB[j + k + length / 2], subgain[0] ); + move32();/* Q(16+Q_synSHB) */ + } + + FOR( i = 1; i < NUM_SHB_SUBFR / 2; i++ ) + { + j = skip[i]; + move16(); + FOR( k = 0; k < length; k++ ) + { + + L_tmp = L_mult0( subwin_shb[k + 1], subgain[i] ); /* Q30 */ + sum_gain = round_fx( L_mac0( L_tmp, subwin_shb[length - k - 1], subgain[i - 1] ) );/* Q14 */ + mod_syn[j + k] = L_shl( L_mult( sum_gain, synSHB[j + k] ), 1 ); + move32();/* Q(16+Q_synSHB) */ + } + } + FOR( k = 0; k < length / 2; k++ ) + { + j = skip[i]; + move16(); + sum_gain = mult_r( subwin_shb_fx[ length - 2 * k - 2 ], subgain[i - 1] ); /* Q15 */ + mod_syn[ j + k ] = L_mult( synSHB[j + k], sum_gain ); + move32();/* Q(16+Q_synSHB) */ + } + } + ELSE + { + num_join = NUM_SHB_SUBFR / NUM_SHB_SUBGAINS; + move16(); + join_length = i_mult2( num_join, length ); + j = 0; + move16(); + FOR( k = 0; k < length; k++ ) + { + sum_gain = mult_r( subwin_shb[k + 1], subgain[0] ); /* Q15 */ + mod_syn[j] = L_mult( synSHB[j], sum_gain ); + move32(); /* Q(16+Q_synSHB) */ + j++; + } + FOR( i = 0; i < NUM_SHB_SUBGAINS - 1; i++ ) + { + FOR( k = 0; k < join_length - length; k++ ) + { + mod_syn[j] = L_mult( synSHB[j], subgain[i * num_join] ); + move32(); /* Q(16+Q_synSHB) */ + j++; + } + + FOR( k = 0; k < length; k++ ) + { + L_tmp = L_mult0( subwin_shb[length - k - 1], subgain[i * num_join] ); + tmp = round_fx( L_mac0( L_tmp, subwin_shb[k + 1], subgain[( i + 1 ) * num_join] ) ); /* Q14 */ + mod_syn[j] = L_shl( L_mult( tmp, synSHB[j] ), 1 ); + move32(); /* Q(16+Q_synSHB) */ + j++; + } + } + FOR( k = 0; k < join_length - length; k++ ) + { + mod_syn[j] = L_mult( synSHB[j], subgain[( NUM_SHB_SUBGAINS - 1 ) * num_join] ); + move32();/* Q(16+Q_synSHB)*/ + j++; + } + FOR( k = 0; k < length; k++ ) + { + tmp = mult_r( subwin_shb[length - k - 1], subgain[( NUM_SHB_SUBGAINS - 1 ) * num_join] ); /* Q15 */ + mod_syn[j] = L_mult( tmp, synSHB[j] ); + move32();/* Q(16+Q_synSHB ) */ + j++; + } + + } + /* adjust frame energy */ + oriNrg = L_deposit_l(0); + synNrg = L_deposit_l(0); + + FOR( i = 0; i < l_shb_lahead; i++ ) + { + sig = mult_r( oriSHB[i], win_shb[i] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_orisHB*/ + sig = round_fx( Mult_32_16( mod_syn[i], win_shb[i] ) ); /*Q_synSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_synSHB */ + } + + FOR( ; i < l_frame; i++) + { + oriNrg = L_mac0( oriNrg, oriSHB[i], oriSHB[i] ); /* 2*Q_oriSHB */ + sig = round_fx( mod_syn[i] ); /* Q_oriSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_oriSHB */ + } + + tmp = add(l_frame, l_shb_lahead); + FOR( ; i < tmp; i++) + { + sig = mult_r( oriSHB[i], win_shb[l_frame + l_shb_lahead - 1 - i] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB */ + + sig = round_fx( Mult_32_16( mod_syn[i], win_shb[l_frame + l_shb_lahead - 1 - i] ) ); /* Q_oriSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_oriSHB */ + } + IF(EQ_32(oriNrg, MAX_32)) + { + scaling = negate(shr(n_subfr_saturation, 1) + 1); + move16(); + oriNrg = 0; + move32(); + FOR( i = 0; i < l_shb_lahead; i++ ) + { + sig = mult_r( shl(oriSHB[i], scaling), win_shb[i] ); + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB + 2*scaling */ + } + FOR( ; i < l_frame; i++) + { + sig = shl(oriSHB[i], scaling); + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB + 2*scaling */ + } + FOR( ; i < tmp; i++) + { + sig = mult_r( shl(oriSHB[i], scaling), win_shb[l_frame + l_shb_lahead - 1 - i] ); + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB + 2*scaling */ + } + } + L_tmp = root_a_over_b_fx( oriNrg, 2 * Q_oriSHB, synNrg, 2 * Q_synSHB, &exp_out ); + exp_out = sub(exp_out, scaling); + frame_gain = L_shl( L_tmp, sub( exp_out, 13 ) ); /* Q18 */ + *GainFrame = frame_gain; + move32(); + + return; +} + + +static Word32 pow_off_pk_fx( Word16 a[], Word16 len, Word16 step ) +{ + Word16 i, j = 0; + Word32 sum, L_tmp; + + sum = L_shr( L_mult0( a[0], a[0] ), 1 ); /* Q29 */ + + j = 0; + move16(); + FOR( i=1; i < len; i += step) + { + L_tmp = L_shr( L_mult0( a[i], a[i] ), 1 ); /* Q29 */ + sum = L_add( sum, L_tmp ); /* Q29 */ + if( GT_16( a[i], a[j] )) + { + j = i; + move16(); + } + } + L_tmp = L_shr( L_mult0( a[j], a[j] ), 1 ); /* Q29 */ + sum = L_sub( sum, L_tmp ); /* Q29 */ + + return ( sum ); +} + + +/*==========================================================================*/ +/* FUNCTION : static void EstimateSHBGainShape_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Estimate temporal gain parameters */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16) length : SHB overlap length Q0 */ +/* _(Word16*) oriSHB : target original SHB frame Q_oriSHB */ +/* _(Word16*) synSHB : shaped SHB excitation Q_synSHB */ +/* _(Word16*) subwin : SHB subframe window Q15 */ +/* _(Word16) Q_oriSHB : Q format of oriSHB */ +/* _(Word16) Q_synSHB : Q format of synSHB */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16*)subgain :estimate of gain shape Q15 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +static void EstimateSHBGainShape_fx( + const Word16 length, /* i : SHB overlap length */ + const Word16* oriSHB, /* i : target original SHB frame Q_oriSHB*/ + const Word16 Q_oriSHB, + const Word16* synSHB, /* i : shaped SHB excitation Q_synSHB*/ + const Word16 Q_synSHB, + Word16* subgain, /* o : estimate of gain shape Q15*/ + const Word16* subwin /* i : SHB subframe window Q15*/ + ,Word16* n_subfr_saturation /* o : Number of subframes which saturated while calculating oriNrg */ +) +{ + const Word16* skip; + Word16 i, j, k; + Word16 sig; + Word32 L_subgain[NUM_SHB_SUBFR]; + Word32 L_sum_gain = 0; + Word32 oriNrg, synNrg; + Word16 num_join, num_gains, join_length; + Word16 norm[NUM_SHB_SUBFR]; + Word16 n_max = -32768; + Word16 n; + Word16 length2 = shl(length, 1); + Word16 length_tmp; + Word32 L_tmp, normFact; + Word16 scaling = 0; + move16(); + num_join = NUM_SHB_SUBFR / NUM_SHB_SUBGAINS; + move16(); + num_gains = NUM_SHB_SUBGAINS; + move16(); + skip = skip_bands_SWB_TBE; + + IF( EQ_16(length,SHB_OVERLAP_LEN / 2)) + { + num_gains = NUM_SHB_SUBFR / 4; + move16(); + skip = skip_bands_WB_TBE; + move16(); + } + /* calculate and normalize the subgain */ + oriNrg = 0; + move16(); + synNrg = 0; + move16(); + + IF( EQ_16(length,SHB_OVERLAP_LEN / 2)) + { + FOR( i = 0; i < NUM_SHB_SUBFR / 2; i++ ) + { + logic16(); + IF( ( i & 0x1 ) == 0 ) + { + oriNrg = 0; + move16(); + synNrg = 0; + move16(); + } + j = skip[i]; + IF( i == 0 ) + { + FOR( k = 0; k < length / 2; k++ ) + { + sig = mult_r( oriSHB[j + k], subwin[2 * k + 2] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ + sig = mult_r( synSHB[j + k], subwin[2 * k + 2] ); /* Q_synSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_synSHB */ + } + FOR( k = length / 2; k < length; k++ ) + { + sig = oriSHB[j + k]; + move16(); + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ + sig = synSHB[j + k]; + move16(); + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_synSHB */ + } + } + ELSE + { + FOR( k = 0; k < length; k++ ) + { + sig = mult_r( oriSHB[j + k], subwin[k + 1] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ + + sig = mult_r( synSHB[j + k], subwin[k + 1] ); /* Q_synSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_synSHB */ + + } + } + IF( i == NUM_SHB_SUBFR / 2 - 1 ) + { + length_tmp = sub(length2, shr(length, 1)); + FOR( ; k < length_tmp; k++ ) + { + sig = mult_r( oriSHB[j + k], subwin[3 * length - 2 * k - 2] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ + + sig = mult_r( synSHB[j + k], subwin[3 * length - 2 * k - 2] ); /* Q_synSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_synSHB */ + } + } + ELSE + { + FOR(; k < length2; k++ ) + { + sig = mult_r( oriSHB[j + k], subwin[2 * length - k - 1] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ + + sig = mult_r( synSHB[j + k], subwin[2 * length - k - 1] ); /* Q_synSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_synSHB */ + } + } + + logic16(); + IF( EQ_16(( i & 0x1 ),1)) + { + L_subgain[i / 2] = root_a_over_b_fx( oriNrg, 2 * Q_oriSHB, synNrg, 2 * Q_synSHB, &n ); + move16(); /* Q(31-n) */ + norm[i / 2] = n; + move16(); + IF( GT_16(norm[i / 2],n_max)) + { + n_max = norm[i / 2]; + move16(); + } + } + } + } + ELSE + { + join_length = i_mult2( num_join, length ); + FOR( i = 0; i < num_gains; i++ ) + { + oriNrg = 0; + move16(); + synNrg = 0; + move16(); + + j = join_length * i; + move16(); + FOR( k = 0; k < length; k++ ) + { + sig = mult_r( oriSHB[j + k], subwin[k + 1] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ + + sig = mult_r( synSHB[j + k], subwin[k + 1] ); /* Q_oriSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_oriSHB */ + } + + FOR( k = 0; k < ( join_length - length ); k++ ) + { + sig = mult_r( oriSHB[length + j + k], 32767 ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ + + sig = mult_r( synSHB[length + j + k], 32767 ); /* Q_oriSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_oriSHB */ + } + + FOR( k = 0; k < length; k++ ) + { + sig = mult_r( oriSHB[j + join_length + k], subwin[length - k - 1] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ + + sig = mult_r( synSHB[j + join_length + k], subwin[length - k - 1] ); /* Q_oriSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_oriSHB */ + } + /* Only implemented in SWB because the length of samples in SWB frame is longer, more likely to saturate */ + scaling = 0; + move16(); + IF(EQ_32(oriNrg, MAX_32)) + { + if(n_subfr_saturation != NULL) + { + *n_subfr_saturation = add(*n_subfr_saturation, 1); + } + scaling = -1; + move16(); + oriNrg = 0; + move32(); + FOR( k = 0; k < length; k++ ) + { + sig = mult_r( oriSHB[j + k], subwin[k + 1] ); + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB - 2*/ + } + FOR( k = 0; k < ( join_length - length ); k++ ) + { + sig = shr(oriSHB[length + j + k], 1); + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB - 2*/ + } + FOR( k = 0; k < length; k++ ) + { + sig = mult_r( shr(oriSHB[j + join_length + k], 1), subwin[length - k - 1] ); /* Q_oriSHB - 1(scaling) */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB - 2 */ + } + } + L_subgain[i] = root_a_over_b_fx( oriNrg, 2 * Q_oriSHB, synNrg, 2 * Q_synSHB, &n ); + move32(); /* Q(31-n) */ + n = sub(n, scaling); + norm[i] = n; + move16(); + IF( GT_16(norm[i],n_max)) + { + n_max = norm[i]; + move16(); + } + } + } + + FOR( i = 0; i < num_gains; i++ ) + { + subgain[i] = round_fx( L_shl( L_subgain[i], sub( norm[i], n_max + 1 ) ) ); /* Q(14-n_max) */ + L_sum_gain = L_mac0( L_sum_gain, subgain[i], subgain[i] ); /* Q(28-2*n_max) */ + } + + /* normalize the subgain */ + n = norm_l( L_sum_gain ); + L_sum_gain = L_shl( L_sum_gain, n ); + n = sub(31, add (n, (sub( 28 , n_max*2 ) ))); + normFact = Isqrt_lc( L_sum_gain, &n ); + + FOR( i = 0; i < num_gains; i++ ) + { + L_tmp = Mult_32_16( normFact, subgain[i] ); /*Q(31-n) * Q(31-norm[i]) */ /* Q(30-n-n_max) */ + subgain[i] = s_max( round_fx( L_shl( L_tmp, add( n, n_max + 1 ) ) ), 3277/*0.1f Q15*/); /* Q15 */ + } + + return; +} + + + +/*==========================================================================*/ +/* FUNCTION :static short closest_centroid_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Determine a set of closest VQ centroids for a given input*/ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16*) data : input data Q15 */ +/* _(Word16*) weights : weights Q0 */ +/* _(Word16*) quantizer : quantizer table Q15 */ +/* _(Word16) centroids : number of centroids Q0 */ +/* _(Word16) length : dimension of quantiser Q0 */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _None */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ Word16 : index Q0 */ +/*--------------------------------------------------------------------------*/ +static Word16 closest_centroid_fx( + const Word16* data, /* i : input data Qx*/ + const Word16* weights, /* i : weights */ + const Word16* quantizer, /* i : quantizer table Qx*/ + const Word16 centroids, /* i : number of centroids */ + const Word16 length ) /* i : dimension of quantiser */ +{ + Word16 i, j, index; + Word16 tmp, tmpL; + Word64 werr_64; + Word32 L_tmp, werr, best_werr; + + index = 0; + move16(); + best_werr = MAX_32; + move32(); + + FOR( i = 0; i < centroids; i++ ) + { + werr_64 = 0; + move64(); + tmpL = i_mult2(i, length); + FOR( j = 0; j < length; j++ ) + { + tmp = sub( data[j], quantizer[tmpL + j] ); + L_tmp = L_mult( tmp, tmp ); + werr_64 = W_mac_32_16( werr_64, L_tmp, weights[j] ); + } + werr = W_sat_m( werr_64); + if( LT_32( werr, best_werr) ) + { + index = i; + move16(); + } + best_werr = L_min( best_werr, werr ); + } + return index; +} + +/*==========================================================================*/ +/* FUNCTION :static short closest_centroid_lc_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Determine a set of closest VQ centroids for a given input */ +/* Gain shape is 4 dimensional */ +/*--------------------------------------------------------------------------*/ +static Word16 closest_centroid_lc_fx( + const Word16 *data, /* i : input data Qx*/ + const Word16 *quantizer, /* i : quantizer table Qx*/ + const Word16 centroids) /* i : number of centroids */ +{ + Word16 i, index, tmp, tmpL; + Word32 werr, best_werr; + + index = 0; + move16(); + best_werr = MAX_32; + move32(); + + FOR( i = 0; i < centroids; i++ ) + { + /* Gain shape dimension 4 */ + tmpL = shl(i, 2); + + /* index 0 */ + tmp = sub( data[0], quantizer[tmpL] ); + werr = L_mult(tmp, tmp); + + /* index 1 */ + tmp = sub( data[1], quantizer[tmpL + 1] ); + werr = L_mac(werr, tmp, tmp); + + /* index 2 */ + tmp = sub( data[2], quantizer[tmpL + 2] ); + werr = L_mac(werr, tmp, tmp); + + /* index 3 */ + tmp = sub( data[3], quantizer[tmpL + 3] ); + werr = L_mac(werr, tmp, tmp); + + if( LT_32( werr, best_werr )) + { + index = i; + move16(); + } + best_werr = L_min(best_werr, werr); + } + + return index; +} + +/*============================================================*/ +/* FUNCTION : static void QuantizeSHBsubgains_fx() */ +/*------------------------------------------------------------*/ +/* PURPOSE : Quantize super highband temporal gains */ +/*------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16) extl : extension layer Q0 */ +/*------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _(Word16[])subgains :super highband temporal gains Q15 */ +/*------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------*/ + +static void QuantizeSHBsubgains_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 subgains[], /* i/o: super highband temporal gains Q15*/ + const Word16 extl /* i : extension layer */ +) +{ + Word16 i, idxSubGain; + Word16 Unit_weights10[NUM_SHB_SUBFR]; + Word16 exp, frac; + Word32 L_tmp; + + IF( EQ_16(extl, WB_TBE)) + { + set16_fx( Unit_weights10, 32767, ( Word16 )NUM_SHB_SUBFR / 4 ); + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + IF( EQ_16(subgains[i] ,0) ) + { + subgains[i + NUM_SHB_SUBFR / 4] = -18432; + move16(); /* (-72) in Q8 */ + } + ELSE + { + L_tmp = L_deposit_h( subgains[i] ); /* Q31 */ + exp = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp ) ); /* move16(); */ + /*exp = -1 - exp; */ + exp = sub(-1, exp); + L_tmp = Mpy_32_16( exp, frac, 24660 );/* Q13 ; 20.0 * log10(2) in Q12*/ + subgains[i + NUM_SHB_SUBFR / 4] = round_fx( L_shl( L_tmp, 11 ) ); /* Q8 */ + } + } + idxSubGain = closest_centroid_lc_fx( subgains + NUM_SHB_SUBFR / 4, HBCB_SubGain5bit_fx, 1 << NUM_BITS_SHB_SUBGAINS ); + Copy( HBCB_SubGain5bit_fx + idxSubGain * NUM_SHB_SUBFR / 4, subgains, NUM_SHB_SUBFR / 4 ); + + push_indice_fx( st_fx, IND_SHB_SUBGAIN, idxSubGain, NUM_BITS_SHB_SUBGAINS ); + + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + L_tmp = L_mult( subgains[i], 21771 ); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr( L_tmp, 10 ); /* From Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + subgains[i] = extract_l( Pow2( 14, frac ) ); + /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + subgains[i] = shl( subgains[i], exp + 1 ); + move16();/*Q15 */ + } + + FOR( i = NUM_SHB_SUBFR / 2 - 1; i >= 0; i-- ) + { + subgains[i] = subgains[i / 2]; + move16(); + } + } + ELSE + { + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + IF( EQ_16(subgains[i] ,0) ) + { + subgains[i] = -12288; + move16(); /* (-3) in Q12 */ + } + ELSE + { + L_tmp = L_deposit_h( subgains[i] ); /* Q31 */ + exp = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp ) ); + /*exp = -1 - exp; */ + exp = sub(-1, exp); + + L_tmp = Mpy_32_16( exp, frac, 9864 ); /*move32(); // Q16 ; log10(2) in Q15 */ + subgains[i] = round_fx( L_shl( L_tmp, 12 ) ); /*Q12 */ + } + } + + idxSubGain = ( Word16 )vquant_fx( subgains, 0, subgains, SHBCB_SubGain5bit_12_fx, NUM_SHB_SUBGAINS, 1 << NUM_BITS_SHB_SUBGAINS ); + + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + L_tmp = L_mult( subgains[i], 27213 ); /* *3.321928 in Q13 -> Q26 */ + L_tmp = L_shr( L_tmp, 10 ); /* From Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + subgains[i] = extract_l( Pow2( 14, frac ) ); + /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + subgains[i] = shl( subgains[i], exp + 1 ); + move16();/*Q15 */ + } + + FOR( i = NUM_SHB_SUBFR - 1; i >= 0; i-- ) + { + subgains[i] = subgains[i * NUM_SHB_SUBGAINS / NUM_SHB_SUBFR]; + move16(); + } + + st_fx->idxSubGains_fx = idxSubGain; + move16(); + IF( NE_16( st_fx->codec_mode, MODE2 )) + { + push_indice_fx( st_fx, IND_SHB_SUBGAIN, idxSubGain, NUM_BITS_SHB_SUBGAINS ); + } + } + + return; +} + + + +/*-------------------------------------------------------------------* + * Quant_shb_ener_sf_fx_fx() + * + * Quantize SHB subframe energies + *-------------------------------------------------------------------*/ + +static void Quant_shb_ener_sf_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word32 *shb_ener_sf_Q31, /* i/o: super highband subframe energies */ + Word16 Q_ener +) +{ + Word16 idxSubEner_fx; + Word16 temp_shb_ener_sf_fx; + Word16 exp/*, exp2*/,frac; + Word32 L_tmp1, L_tmp; + Word32 sum; + Word16 tmp; + + /* shb_ener_sf_fx[0] = log10(0.003125*shb_ener_sf[0:319]); */ + sum = *shb_ener_sf_Q31; /* L_tmp in Q_ener = (2*Q_shb+1) */ + + exp = norm_l(sum); + frac = Log2_norm_lc(L_shl(sum, exp)); + exp = sub(30, add(exp, Q_ener)); /* 30-(exp+Q_ener ) */ + L_tmp1 = Mpy_32_16(exp, frac, 617); /* 2466=LOG10(2) in Q11, so answer Ltmp in Q12 */ + + tmp = round_fx(L_shl(L_tmp1, 30-14)); /* tmp in Q12 */ + + temp_shb_ener_sf_fx = 0; + move16(); + idxSubEner_fx = usquant_fx(tmp, &temp_shb_ener_sf_fx, 0, 86, shl(1,NUM_BITS_SHB_ENER_SF)); /* 86 = 0.042f in Q11 = Qin-1 */ + /* o: temp_shb_ener_sf_fx in Q12 */ + + /* shb_ener_sf_fx[0] = pow(10.0, temp_shb_ener_sf_fx ); */ + /* = pow(2, 3.321928*temp_shb_ener_sf_fx) */ + L_tmp = L_mult(temp_shb_ener_sf_fx, 27213 ); /* 3.321928 in Q13 -> L_tmp in Q12+Q13+1 = Q26 */ + L_tmp = L_shl( L_tmp, -10 ); /* bring L_tmp from Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); /* Extract exponent */ + L_tmp = Pow2(14, frac ); + *shb_ener_sf_Q31 = L_shl(L_tmp, exp-14+Q_ener ); /* In Q_ener */ + + st_fx->idx_shb_fr_gain_fx = idxSubEner_fx; + move16(); + IF( NE_16( st_fx->codec_mode, MODE2 )) + { + push_indice_fx( st_fx, IND_SHB_ENER_SF, idxSubEner_fx, NUM_BITS_SHB_ENER_SF); + } + return; +} + + +/*-------------------------------------------------------------------* +* Quant_shb_res_gshape_fx() +* +* Quantize SHB gain shapes in residual domain +*-------------------------------------------------------------------*/ + +static void Quant_shb_res_gshape_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 shb_res_gshape_fx[] /* i/o: super highband gain shapes Q14 */ +) +{ + Word16 i, idxSubGain_fx[NB_SUBFR16k]; + + FOR(i = 0; i < NB_SUBFR16k; i++) + { + idxSubGain_fx[i] = usquant_fx(shb_res_gshape_fx[i], + &shb_res_gshape_fx[i], + 2048/*0.125f Q14*/, /*2048 = 0.125 in Q14 */ + 1024/*0.125f Q13*/, /*1024 = 0.125 in Q13 */ + shl(1,NUM_BITS_SHB_RES_GS)); + + st_fx->idx_res_gs_fx[i] = idxSubGain_fx[i]; + IF ( NE_16( st_fx->codec_mode, MODE2 )) + { + push_indice_fx( st_fx, IND_SHB_RES_GS1+i, idxSubGain_fx[i], NUM_BITS_SHB_RES_GS); + } + } +} + +/*==========================================================================*/ +/* FUNCTION : static void QuantizeSHBframegain_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : QQuantize super highband frame gain */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 extl i : extension layer */ +/* Word32 extl_brate i : extension layer bitrate */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Word32 *GainFrame i/o: Gain Q18 */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* */ +/*==========================================================================*/ +static void QuantizeSHBframegain_fx( + Encoder_State_fx* st_fx, /* i/o: encoder state structure */ + Word32* GainFrame, /* i/o: Gain Q18 */ + const Word16 extl, /* i : extension layer */ + Word32 extl_brate /* i : extension layer bitrate */ + ,Word16 *rf_gainFrame_ind +) +{ + Word16 idxFrameGain; + Word32 Q_GainFrame; + Word16 Unit_weights1 = 1; + Word16 exp, frac, tmp; + Word32 L_tmp; + Word32 GainFrameLog; + + IF( EQ_16(extl, WB_TBE)) + { + determine_gain_weights_fx( GainFrame, &( Unit_weights1 ), 1 ); + IF( EQ_32(extl_brate,WB_TBE_0k35)) + { + singlevectortest_gain_fx( GainFrame, 1, + 1 << NUM_BITS_SHB_FrameGain_LBR_WB, &idxFrameGain, + &Q_GainFrame, SHBCB_FrameGain16_fx ); + test(); + IF( GT_32( Q_GainFrame, L_shl( Mult_32_16( *GainFrame, 17367 ), 1 ) )&&idxFrameGain>0) /* 1.06 = +0.5 dB */ + { + idxFrameGain--; + Q_GainFrame = L_add(SHBCB_FrameGain16_fx[idxFrameGain], 0); /* Q18 */ + } + st_fx->gFrame_WB_fx = idxFrameGain; + move16(); + *rf_gainFrame_ind = idxFrameGain; + } + ELSE + { + singlevectortest_gain_fx( GainFrame, 1, + 1 << NUM_BITS_SHB_FrameGain, &idxFrameGain, &Q_GainFrame, + SHBCB_FrameGain64_fx ); + + push_indice_fx( st_fx, IND_SHB_FRAMEGAIN, idxFrameGain, NUM_BITS_SHB_FrameGain ); + *rf_gainFrame_ind = idxFrameGain; + move16(); /* Q18 */ + } + } + ELSE + { + IF( *GainFrame == 0 ) + { + GainFrameLog = -196608; + move32(); + } + ELSE + { + exp = norm_l( *GainFrame ); + frac = Log2_norm_lc( L_shl( *GainFrame, exp ) ); + exp = ( 30 - exp - 18 ); + GainFrameLog = Mpy_32_16( exp, frac, 9864 ); + /*GainFrameLog= round_fx(L_shl(L_tmp,12)); //Q12 */ + } + + exp = norm_s( SHB_GAIN_QDELTA_FX_15 ); + tmp = div_s( shl(1, sub(14, exp)), SHB_GAIN_QDELTA_FX_15 ); + L_tmp = Mult_32_16( L_sub( GainFrameLog, SHB_GAIN_QLOW_FX_16 ), tmp ); + idxFrameGain = extract_l( L_shr( L_add( L_tmp, shl(1, sub(14, exp)) ), sub(15, exp) ) ); /*Q0*/ + IF( GT_16( idxFrameGain, ( 1 << NUM_BITS_SHB_FRAMEGAIN ) - 1 )) + { + idxFrameGain = sub( ( 1 << NUM_BITS_SHB_FRAMEGAIN ), 1 ); + } + ELSE + { + if( idxFrameGain < 0 ) + { + idxFrameGain = 0; + move16(); + } + } + + L_tmp = SHB_GAIN_QLOW_FX_16; + Q_GainFrame = L_mac( L_tmp, idxFrameGain, SHB_GAIN_QDELTA_FX_15 ); + + WHILE( GT_32( Q_GainFrame, L_add( GainFrameLog, 4866 ) )&& + idxFrameGain != 0 ) + { + idxFrameGain = sub(idxFrameGain, 1); + Q_GainFrame = L_mac0( SHB_GAIN_QLOW_FX_16, idxFrameGain, SHB_GAIN_QDELTA_FX_16 ); + } + + /* Q_GainFrame = (float) pow(10.0, Q_GainFrame ); */ + /* i: Q_GainFrame in Q16 */ + L_tmp = Mult_32_16( Q_GainFrame, 27213 ); /* *3.321928 in Q13 -> Q25 */ + L_tmp = L_shr( L_tmp, -2 ); /* From Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + Q_GainFrame = Pow2( 30, frac ); + exp = sub ( exp, 30) ; + Q_GainFrame = L_shl( Q_GainFrame, exp + 18 ); /* Q18 */ + + st_fx->idxFrameGain_fx = idxFrameGain; + move16(); + IF ( NE_16( st_fx->codec_mode, MODE2 )) + { + push_indice_fx( st_fx, IND_SHB_FRAMEGAIN, idxFrameGain, NUM_BITS_SHB_FRAMEGAIN ); + } + *rf_gainFrame_ind = idxFrameGain; + } + + IF( EQ_16(st_fx->rf_mode,1)) + { + /*Currently intended for SWB only. Modify for WB is needed later!*/ + IF( EQ_16(st_fx->rf_frame_type,RF_NELP)) + { + *rf_gainFrame_ind = idxFrameGain; /* NELP Frame uses full 5 bits */ + } + ELSE /*RF_ALLPRED, RF_GENPRED, RF_NOPRED modes*/ + { + IF( *GainFrame <= 327680 /*1.25 in Q18*/ ) /* [0 to 1.25] range --> 0.5*/ + *rf_gainFrame_ind = 0; + ELSE IF ( *GainFrame <= 786432 /*3 in Q18*/ ) /* (1.25 to 3] --> 2 */ + *rf_gainFrame_ind = 1; + ELSE IF ( *GainFrame <= 1572864 /*6 in Q18*/ ) /* (3 to 6] --> 4 */ + *rf_gainFrame_ind = 2; + ELSE /* (6 to Inf) --> 8 */ + *rf_gainFrame_ind = 3; + } + } + + *GainFrame = Q_GainFrame; + move32(); /* Q18 */ + + return; +} + + +/*============================================================*/ +/* FUNCTION : static void determine_gain_weights_fx() */ +/*------------------------------------------------------------*/ +/* PURPOSE : Determine weights for gain quantization */ +/*------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word32*)gain :Gain parameter Q18 */ +/* _(Word16) dims : number of gains */ +/*------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16*)weights : gain weights Q12/Q6 */ +/*------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------*/ +static void determine_gain_weights_fx ( + const Word32* gain, /* i : Gain parameter Q18 */ + Word16* weights, /* o : gain weights Q12/Q6*/ + const Word16 dims /* i : number of gains */ ) +{ + Word16 j; + Word16 exp, exp1, frac, tmp, exp2; + Word32 L_tmp; + + FOR( j = 0; j < dims; j++ ) + { + IF( GT_32(gain[j],8))/* 8 = 0.001 in Q13 */ + { + /*weights[j] = (float)(pow (fabs (gain[j]), -0.9f)); = pow(2,(-0.9)*log2(gain[j])) */ + exp1 = norm_l( gain[j] ); + frac = Log2_norm_lc( L_shl( gain[j], exp1 ) ); + move16(); + exp = 30 - exp1 - 18; + move16(); + L_tmp = Mpy_32_16( exp, frac, -29491 ); /* Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + tmp = extract_l( Pow2( 14, frac ) ); /* Q14 */ + + exp2 = sub(exp,8); + if( LE_16(exp1,21)) + { + exp2 = sub(exp,2); + } + weights[j] = shl( tmp, exp2); + move16(); /* Q12 */ + } + ELSE + { + weights[j] = 32076; + move16();/* (501.187233628f) in Q6*/ + } + } + + return; +} + + + + +/*==============================================================================*/ +/* FUNCTION : static singlevectortest_gain_fx () */ +/*------------------------------------------------------------------------------*/ +/* PURPOSE : Single stage VQ for coding */ +/*------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word32*) inp : input gain vector Q18 */ +/* _(Word16) dimen : dimension of the input vector */ +/* _(Word16) cb_size : codebook size */ +/* _(Word16*) weight : Weights for the quanitzation */ +/* _(Word32*) codebook : Codebook 19Q13 */ +/*------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16*)index :quanitzation index */ +/* _(Word32*)recon :Reconstruction 19Q13 */ +/*------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------------------------*/ +static void singlevectortest_gain_fx ( + const Word32* inp, /* i : input gain vector Q18*/ + const Word16 dimen, /* i : dimension of the input vector */ + const Word16 cb_size, /* i : codebook size */ + Word16* index, /* o : quanitzation index */ + Word32* recon, /* o : Reconstruction Q18 */ + const Word32* codebook + /* i : Codebook Q18*/ ) +{ + Word16 k, interNum, flag; + Word32 meanU, meanQ; + Word16 least[4]; + Word32 L_tmp; + + interNum = 4; + move16(); + + return_M_Least_fx_GainFrame( inp, codebook, cb_size, interNum, least ); + + meanU = sum32_fx( inp, dimen ); /* Q18 */ + Copy32( codebook + dimen * least[0], recon, dimen ); + + L_tmp = L_shl( Mult_32_16( meanU, 18022 ), 1 ); /* Q18 */ + index[0] = least[0]; + move16(); + flag = 0; + move16(); + FOR( k = 0; k < interNum; k++ ) + { + IF( flag == 0 ) + { + meanQ = sum32_fx( codebook + dimen * least[k], dimen ); /* Q18 */ + IF( LE_32( meanQ, L_tmp )) + { + flag = 1; + move16(); + Copy32( codebook + dimen * least[k], recon, dimen ); + index[0] = least[k]; + move16(); + } + } + } + + return; +} + + + + +/*==============================================================================*/ +/* FUNCTION : return_M_Least_fx_GainFrame () */ +/*------------------------------------------------------------------------------*/ +/* PURPOSE : */ +/*------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word32*) inp : input Q18 */ +/* _(Word16*) weight : input gain weights */ +/* _(Word16) n_cols : vector size */ +/* _(Word16) num_grp : number of centroids for 1st stage */ +/* _(Word16) interNum : number on short list prior to 2nd stage search */ +/* _(Word32*) codebook : first stage codebook Q18 */ +/*------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16*)least :return value */ +/*------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------------------------*/ +static void return_M_Least_fx_GainFrame( + const Word32* inp, /* i: input Q18*/ + const Word32* codebook, /* i: codebook Q18*/ + const Word16 num_grp, /* i: number of centroids */ + const Word16 interNum, /* i: number on short list prior to 2nd stage search*/ + Word16* least /* o: return value */ ) +{ + Word16 i, k; + Word32 distance[1024], mindist; + + Word16 n; + Word32 diff[1024]; + Word32 max_diff; + mindist = L_add(MAX_32, 0); + + diff[0] = L_sub( *inp, codebook[0] ); + move32(); + max_diff = L_abs( diff[0] ); + FOR( i = 1; i < num_grp; i++ ) + { + diff[i] = L_sub( *inp, codebook[i] ); + move32(); + max_diff = L_max(max_diff , L_abs( diff[i] )); + } + n = 31; + if( max_diff != 0 ) + { + n = norm_l(max_diff); + } + + FOR( i = 0; i < num_grp; i++ ) + { + diff[i] = L_shl( diff[i], n ); + move32(); + } + + FOR( i = 0; i < num_grp; i++ ) + { + distance[i] = L_deposit_l(0); + distance[i] = Mult_32_32( diff[i], diff[i] ); + move32(); + + if( LT_32( distance[i], mindist )) + { + least[0] = i; + move16(); + } + mindist = L_min(mindist,distance[i]); + } + + distance[least[0]] = MAX_32; + move32(); + + FOR( k = 1; k < interNum; k++ ) + { + mindist = L_add(MAX_32, 0); + FOR( i = 0; i < num_grp; i++ ) + { + if( LT_32( distance[i], mindist )) + { + least[k] = i; + move16(); + } + mindist = L_min(mindist,distance[i]); + } + + distance[least[k]] = MAX_32; + move32(); + } + + return; +} + + +/*-------------------------------------------------------------------* +* Quant_lower_LSF_fx() +*-------------------------------------------------------------------*/ +static void Quant_lower_LSF_fx( + const Word16 lsf[], /* i : Input LSFs Q15 */ + Word16 lsf_q[], /* o : Quantized LSFs Q15 */ + Word16 lsf_idx[] /* o : Quantized LSFs indices */ +) +{ + Word16 i; + + lsf_idx[0] = ( Word16 )squant_fx( lsf[0], &lsf_q[0], lsf_q_cb_fx[0], lsf_q_cb_size_fx[0] ); + FOR( i = 1; i < NUM_Q_LSF; i++ ) + { + lsf_idx[i] = ( Word16 )squant_fx( sub( lsf[i], lsf_q[i - 1] ), &lsf_q[i], lsf_q_cb_fx[i], lsf_q_cb_size_fx[i] ); + move16(); + lsf_q[i] = add( lsf_q[i - 1], lsf_q[i] ); + move16(); + } + + return; +} + + +/*-------------------------------------------------------------------* +* Quant_mirror_point_fx() +*-------------------------------------------------------------------*/ +static Word16 Quant_mirror_point_fx( + const Word16 lsf[], /* i : Input LSFs */ + const Word16 lsf_q[], + Word16* m /* o : Mirror point */ +) +{ + Word16 m_diff; + Word16 m_idx; + + m_diff = mult_r( sub( lsf[NUM_Q_LSF], lsf_q[NUM_Q_LSF - 1] ), 16384 ); + + m_idx = ( Word16 )squant_fx( m_diff, m, mirror_point_q_cb_fx, + MIRROR_POINT_Q_CB_SIZE ); /*move16(); */ + + *m = add( lsf_q[NUM_Q_LSF - 1], *m ); + move16(); + + return m_idx; +} + +/*-------------------------------------------------------------------* +* Find_LSF_grid() +* +* Find the best grid for the LSFs +*-------------------------------------------------------------------*/ + +static Word16 Find_LSF_grid_fx( + const Word16 lsf[], /* i : Input LSFs */ + Word16 lsf_q[], /* o : Quantized LSFs */ + const Word16 m /* i : Mirror point */ +) +{ + Word16 lsf_map[NUM_MAP_LSF]; + Word16 grid[NUM_LSF_GRIDS][NUM_MAP_LSF]; + Word16 offset; + Word16 last_q_lsf; + Word16 lsf_t[NUM_MAP_LSF]; + Word16 lsf_smooth[NUM_MAP_LSF]; + Word32 D, D_best; + Word16 I_best = 0; + Word16 i, j; + Word16 scale; + + Word16 tmp, exp, tmp1; + Word32 L_tmp; + + + tmp = shl(m, 1); + lsf_map[0] = sub( tmp, lsf_q[NUM_MAP_LSF-1-0] ); + move16(); + lsf_map[1] = sub( tmp, lsf_q[NUM_MAP_LSF-1-1] ); + move16(); + lsf_map[2] = sub( tmp, lsf_q[NUM_MAP_LSF-1-2] ); + move16(); + lsf_map[3] = sub( tmp, lsf_q[NUM_MAP_LSF-1-3] ); + move16(); + lsf_map[4] = sub( tmp, lsf_q[NUM_MAP_LSF-1-4] ); + move16(); + + + IF( GT_16( m, MAX_LSF_FX_2 )) + { + offset = lsf_map[0]; + move16(); + exp = norm_s( m ); + tmp = div_s( shl(1, sub(14, exp)), m ); + L_tmp = L_mult( sub( MAX_LSF_FX, m ), tmp ); + scale = round_fx( L_shl( L_tmp, exp + 1 ) ); + + FOR( i = 0; i < NUM_MAP_LSF; i++ ) + { + tmp = mult_r( sub( lsf_map[i], offset ), scale ); + lsf_map[i] = add( tmp, offset ); + move16(); + } + } + + last_q_lsf = lsf_q[NUM_Q_LSF - 1]; + move16(); + scale = sub( MAX_LSF_FX, last_q_lsf ); + + FOR( i = 0; i < NUM_LSF_GRIDS; i++ ) + { + FOR( j = 0; j < NUM_MAP_LSF; j++ ) + { + grid[i][j] = add( mult_r( lsf_grid_fx[i][j], scale ), last_q_lsf ); + move16(); + } + } + + D_best = L_add(MAX_32, 0); + FOR( i = 0; i < NUM_LSF_GRIDS; i++ ) + { + D = L_deposit_l(0); + FOR( j = 0; j < NUM_MAP_LSF; j++ ) + { + /*lsf_t[j] = (1 - grid_smoothing[j])*lsf_map[j] + grid_smoothing[j]*grid[i][j]; */ + tmp = sub( 32767, grid_smoothing_fx[j] ); + tmp = mult_r( tmp, lsf_map[j] ); + tmp1 = mult_r( grid_smoothing_fx[j], grid[i][j] ); + lsf_t[j] = add( tmp, tmp1 ); + move16(); + + tmp = sub( lsf_t[j], lsf[NUM_Q_LSF + j] ); + D = L_mac0( D, tmp, tmp ); + + /* D += (lsf_t[j] - lsf[NUM_Q_LSF + j])*(lsf_t[j] - lsf[NUM_Q_LSF + j]); */ + } + IF( LT_32( D, D_best )) + { + Copy( lsf_t, lsf_smooth, NUM_MAP_LSF ); + D_best = L_add(D, 0); + I_best = i; + move16(); + } + } + + FOR( i = 0; i < NUM_MAP_LSF; i++ ) + { + lsf_q[NUM_Q_LSF + i] = lsf_smooth[i]; + move16(); + } + + return I_best; +} + +/*-------------------------------------------------------------------* +* gainFrSmooth_En_fx() +* +* Gain frame smoothing and attenuation control +*-------------------------------------------------------------------*/ +static void gainFrSmooth_En_fx(Encoder_State_fx *st_fx, + Word16 *shb_frame_fx, + const Word16 *lpc_shb_fx, + const Word16 *lsp_shb_fx, + Word16 *MA_lsp_shb_spacing, + Word16 *frGainAttenuate, + Word16 *frGainSmoothEn + ) +{ + Word16 temp_shb_frame[L_FRAME16k+L_SHB_LAHEAD]; + Word32 lsp_slow_evol_rate, lsp_fast_evol_rate; + Word16 lsp_spacing; + + Word32 tempQ31; + Word16 tempQ15_1, tempQ15_2; + Word16 i; + + /* inits */ + *frGainAttenuate = 0; + move16(); + *frGainSmoothEn = 0; + move16(); + *MA_lsp_shb_spacing = 16384; + move16(); + lsp_spacing = lsp_shb_fx[0]; + move16(); + + /* estimate the mean square error in lsps from current frame to past frames */ + tempQ15_1 = sub( lsp_shb_fx[0], st_fx->lsp_shb_slow_interpl_fx[0] ); + tempQ15_2 = sub( lsp_shb_fx[0], st_fx->lsp_shb_fast_interpl_fx[0] ); + lsp_slow_evol_rate = L_mult(tempQ15_1, tempQ15_1 ); + lsp_fast_evol_rate = L_mult(tempQ15_2, tempQ15_2 ); + + /* update the slow and fast lsp interp for next frame */ + tempQ31 = L_mult(st_fx->lsp_shb_slow_interpl_fx[0], 22937 ); + st_fx->lsp_shb_slow_interpl_fx[0] = mac_r(tempQ31, lsp_shb_fx[0], 9830 ); + move16(); + tempQ31 = L_mult(st_fx->lsp_shb_fast_interpl_fx[0], 9830 ); + st_fx->lsp_shb_fast_interpl_fx[0] = mac_r(tempQ31, lsp_shb_fx[0], 22937 ); + move16(); + + FOR( i = 1; i < LPC_SHB_ORDER; i++ ) + { + tempQ15_1 = sub(lsp_shb_fx[i], lsp_shb_fx[i-1]); + lsp_spacing = s_min( lsp_spacing, tempQ15_1); + + /* estimate the mean square error in lsps from current frame to past frames */ + tempQ15_1 = sub( lsp_shb_fx[i], st_fx->lsp_shb_slow_interpl_fx[i] ); + tempQ15_2 = sub( lsp_shb_fx[i], st_fx->lsp_shb_fast_interpl_fx[i] ); + lsp_slow_evol_rate = L_mac(lsp_slow_evol_rate, tempQ15_1, tempQ15_1 ); + lsp_fast_evol_rate = L_mac(lsp_fast_evol_rate , tempQ15_2, tempQ15_2 ); + + /* update the slow and fast interpolation lsps for next frame */ + tempQ31 = L_mult(st_fx->lsp_shb_slow_interpl_fx[i], 22937 ); + st_fx->lsp_shb_slow_interpl_fx[i] = mac_r(tempQ31, lsp_shb_fx[i], 9830 ); + move16(); + tempQ31 = L_mult(st_fx->lsp_shb_fast_interpl_fx[i], 9830 ); + st_fx->lsp_shb_fast_interpl_fx[i] = mac_r(tempQ31, lsp_shb_fx[i], 22937 ); + move16(); + } + + test(); + test(); + IF( NE_16( st_fx->last_extl_fx, SWB_TBE ) + && NE_16(st_fx->last_extl_fx, FB_TBE) + && LT_16( lsp_spacing, 262 ) ) + { + st_fx->lsp_shb_spacing_fx[0] = lsp_spacing; + move16(); + st_fx->lsp_shb_spacing_fx[1] = lsp_spacing; + move16(); + st_fx->lsp_shb_spacing_fx[2] = lsp_spacing; + move16(); + st_fx->prev_frGainAtten_fx = 1; + move16(); + set16_fx(st_fx->shb_inv_filt_mem_fx, 0, LPC_SHB_ORDER); + } + + /* Estimate the moving average LSP spacing */ + tempQ31 = L_mult(st_fx->lsp_shb_spacing_fx[0], 3277); /* 0.1f */ + tempQ31 = L_mac(tempQ31, st_fx->lsp_shb_spacing_fx[1], 6553); /* 0.2f */ + tempQ31 = L_mac(tempQ31, st_fx->lsp_shb_spacing_fx[2], 9830); /* 0.3f */ + *MA_lsp_shb_spacing = mac_r(tempQ31, lsp_spacing, 13107); /* 0.4f */ + + st_fx->lsp_shb_spacing_fx[0] = st_fx->lsp_shb_spacing_fx[1]; + move16(); + st_fx->lsp_shb_spacing_fx[1] = st_fx->lsp_shb_spacing_fx[2]; + move16(); + st_fx->lsp_shb_spacing_fx[2] = lsp_spacing; + move16(); + + test(); + test(); + test(); + IF( ( LT_16( lsp_spacing, 262 )&&(LT_16(*MA_lsp_shb_spacing,164)||EQ_16(st_fx->prev_frGainAtten_fx,1))) + || LE_16( lsp_spacing, 105 ) ) + { + *frGainAttenuate = 1; + move16(); + + IF( NE_32(st_fx->total_brate_fx , ACELP_24k40)) + { + Copy( shb_frame_fx, temp_shb_frame, L_FRAME16k + L_SHB_LAHEAD ); + fir_fx( temp_shb_frame, lpc_shb_fx, shb_frame_fx, st_fx->shb_inv_filt_mem_fx, L_FRAME16k + L_SHB_LAHEAD, LPC_SHB_ORDER, 1,3); + } + ELSE + { + set16_fx(st_fx->shb_inv_filt_mem_fx, 0, LPC_SHB_ORDER); + } + + test(); + IF ( LT_32( lsp_slow_evol_rate, 2147484l/*0.001f Q31*/ )&<_32(lsp_fast_evol_rate,2147484l/*0.001f Q31*/)) + { + *frGainSmoothEn = 1; + move16(); + } + } + +} + +/*-------------------------------------------------------------------* +* Quant_BWE_LSF() +* +* Quantize super highband spectral envolope +*-------------------------------------------------------------------*/ + +static void Quant_BWE_LSF_fx( + + Encoder_State_fx* st_fx, /* i/o: encoder state structure */ + const Word16 lsf_shb[], /* i : unquanitzed LSFs */ + Word16 Q_lsfs[] /* o : quanitzed LSFs */ +) +{ + Word16 lsf[LPC_SHB_ORDER]; + Word16 lsf_q[LPC_SHB_ORDER]; + Word16 lsf_idx[NUM_Q_LSF]; + Word16 i; + Word16 m_idx; + Word16 m; + Word16 grid_idx; + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + lsf[i] = sub( 16384, lsf_shb[LPC_SHB_ORDER - 1 - i] ); + move16(); + } + + Quant_lower_LSF_fx( lsf, lsf_q, lsf_idx); + /* i: lsf in Q15 */ + /* o: lsf_q in Q15 */ + + FOR( i = 0; i < NUM_Q_LSF; i++ ) + { + st_fx->lsf_idx_fx[i] = lsf_idx[i]; + move16(); + IF( NE_16( st_fx->codec_mode, MODE2 )) + { + push_indice_fx( st_fx, IND_SHB_LSF, lsf_idx[i], lsf_q_num_bits[i] ); + } + } + + m_idx = Quant_mirror_point_fx( lsf, lsf_q, &m ); + + st_fx->m_idx_fx = m_idx; + move16(); + IF( NE_16( st_fx->codec_mode, MODE2 )) + { + push_indice_fx( st_fx, IND_SHB_MIRROR, m_idx, MIRROR_POINT_BITS ); + } + + grid_idx = Find_LSF_grid_fx( lsf, lsf_q, m ); + + st_fx->grid_idx_fx = grid_idx; + IF( NE_16( st_fx->codec_mode, MODE2 )) + { + push_indice_fx( st_fx, IND_SHB_GRID, grid_idx, NUM_LSF_GRID_BITS ); + } + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + Q_lsfs[i] = sub( 16384, lsf_q[LPC_SHB_ORDER - 1 - i] ); + move16(); + } + + return; +} + +/*-------------------------------------------------------------------* + * fb_tbe_enc() + * + * FB TBE encoder, 14(resp. 15.5) - 20 kHz band encoding module + *-------------------------------------------------------------------*/ + +void fb_tbe_enc_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 new_input[], /* i : input speech at 48 kHz sample rate */ + const Word16 fb_exc[], /* i : FB excitation from the SWB part */ + Word16 Q_fb_exc +) +{ + Word16 ratio; + Word16 tmp_vec[L_FRAME48k]; + Word16 idxGain; + Word16 input_fhb[L_FRAME48k]; + Word16 Sample_Delay_HP; + Word32 fb_exc_energy, temp2; + Word32 L_tmp; + Word16 tmp,tmp1,tmp2,exp,exp2,exp_norm; + Word16 s_max_value,exp_temp,i; + + s_max_value = 0; + FOR( i = 0; i < L_FRAME48k; i++ ) + { + s_max_value = s_max(s_max_value,abs_s(new_input[i])); + } + exp_temp = norm_s( s_max_value ); + if( s_max_value == 0 ) + { + exp_temp = 15; + } + exp_temp = sub(exp_temp,1); + + Copy_Scale_sig( new_input, input_fhb, L_FRAME48k, exp_temp ); + + elliptic_bpf_48k_generic_fx( input_fhb, &exp_temp , tmp_vec, st->elliptic_bpf_2_48k_mem_fx, st->elliptic_bpf_2_48k_mem_fx_Q,full_band_bpf_2_fx ); + Sample_Delay_HP = NS2SA(48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) - L_FRAME48k/2 ; + + IF( NE_16(st->last_extl_fx,FB_TBE)) + { + set16_fx( st->old_input_fhb_fx, 0, Sample_Delay_HP ); + st->old_input_fhb_fx_Q = 0; + move16(); + set16_fx( tmp_vec, 0, L_FRAME16k ); + } + Copy_Scale_sig( st->old_input_fhb_fx, st->old_input_fhb_fx, Sample_Delay_HP, sub(exp_temp,st->old_input_fhb_fx_Q) ); + st->old_input_fhb_fx_Q = exp_temp; + Copy( st->old_input_fhb_fx, input_fhb, Sample_Delay_HP ); + Copy( tmp_vec, input_fhb + Sample_Delay_HP, L_FRAME48k-Sample_Delay_HP ); + Copy( tmp_vec + L_FRAME48k - Sample_Delay_HP, st->old_input_fhb_fx, Sample_Delay_HP ); + temp2 = sum2_fx_mod( input_fhb, L_FRAME48k/2 );/* Q11 */ + temp2 = L_add(temp2,L_shl(st->prev_fb_energy_fx,sub(sub(add(exp_temp,exp_temp),6),st->prev_fb_energy_fx_Q)));/* Q11 */ + st->prev_fb_energy_fx = sum2_fx_mod( input_fhb + L_FRAME48k/2, L_FRAME48k/2 );/*Q11*/ + st->prev_fb_energy_fx_Q = sub(add(exp_temp,exp_temp),6); + fb_exc_energy = sum2_fx_mod( fb_exc, L_FRAME16k );/* Q(2*Q_fb_exc+1 -7) */ + + /*ratio = (float) sqrt( temp2 / fb_exc_energy );*/ + L_tmp = L_max(1, temp2); /*Q6*/ + exp = norm_l(L_tmp); + tmp = extract_h(L_shl(L_tmp, exp)); + exp = sub(sub(31,sub(add(exp_temp,exp_temp),8)), exp); /* in Q15 (L_tmp in Q6)*/ + + exp2 = norm_l(fb_exc_energy); + tmp2 = extract_h(L_shl(fb_exc_energy, exp2)); + tmp1 = sub(add(Q_fb_exc,Q_fb_exc), 8);/*1 - 9*/ + exp2 = sub(sub(31,tmp1), exp2); /* in Q15 (L_tmp in Q6)*/ + + exp = sub(exp2, exp); /* Denormalize and substract */ + IF (GT_16(tmp2, tmp)) + { + tmp2 = shr(tmp2, 1); + exp = add(exp, 1); + } + IF( 0 != tmp ) + { + tmp = div_s(tmp2, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp); /*Q(31-exp)*/ + L_tmp = L_max(L_shr(L_tmp,sub(31,exp)),0x1);/* Q0 */ + } + ELSE + { + L_tmp =0; + } + + /* idxGain = (short)( log2_f ((float)ratio) + 0.5f ); + idxGain = max( 0, min(15,idxGain) ); */ + ratio = 0; + IF(GE_32(L_tmp,32768)) + { + idxGain = 15; + } + ELSE + { + ratio = extract_l(L_tmp); + exp_norm = norm_s(ratio); + idxGain = sub(14, exp_norm); + idxGain = s_max(0,idxGain); + } + IF(GT_16(idxGain,2)&<_16(idxGain,15)&>_16(ratio,add(shl(2,sub(idxGain,1)),shl(2,sub(idxGain,2))))) + { + idxGain = add(idxGain,1); + } + + /* ratio = (float)(1 << idxGain);*/ + IF( st->codec_mode == MODE2 ) + { + st->idxGain_fx = idxGain; + } + ELSE + { + push_indice_fx( st, IND_FB_SLOPE, idxGain, 4 ); + } + + return; +} +void tbe_write_bitstream_fx( + Encoder_State_fx *st_fx /* i/o: encoder state structure */ +) +{ + Word16 i; + + test(); + test(); + test(); + test(); + test(); + IF ( ( st_fx->rf_mode || EQ_32( st_fx->total_brate_fx, ACELP_9k60 ))&&(EQ_16(st_fx->bwidth_fx,WB))) + { + /* WB LSF */ + push_next_indice_fx( st_fx, st_fx->lsf_WB_fx, NUM_BITS_LBR_WB_LSF ); + + /* WB frame */ + push_next_indice_fx( st_fx, st_fx->gFrame_WB_fx, NUM_BITS_SHB_FrameGain_LBR_WB ); + } + ELSE IF ( ( GE_32( st_fx->total_brate_fx, ACELP_9k60 ))&&(LE_32(st_fx->total_brate_fx,ACELP_32k))&& + ( ( EQ_16( st_fx->bwidth_fx, SWB ) ) || ( EQ_16( st_fx->bwidth_fx, FB ) ) ) ) + { + /* LSF coefficients */ + + test(); + IF( (EQ_16(st_fx->rf_mode,1))||EQ_32(st_fx->total_brate_fx,ACELP_9k60)) + { + push_next_indice_fx( st_fx, st_fx->lsf_idx_fx[0], 8 ); + } + ELSE + { + FOR (i = 0; i < NUM_Q_LSF; i++) + { + push_next_indice_fx( st_fx, st_fx->lsf_idx_fx[i], lsf_q_num_bits[i] ); + } + + /* LSF mirror points */ + push_next_indice_fx( st_fx, st_fx->m_idx_fx, MIRROR_POINT_BITS ); + + /* LSF grid points */ + push_next_indice_fx( st_fx, st_fx->grid_idx_fx, NUM_LSF_GRID_BITS ); + } + + /* Gain shape */ + push_next_indice_fx( st_fx, st_fx->idxSubGains_fx, NUM_BITS_SHB_SUBGAINS ); + + /* frame gain */ + push_next_indice_fx( st_fx, st_fx->idxFrameGain_fx, NUM_BITS_SHB_FRAMEGAIN ); + + IF ( GE_32( st_fx->total_brate_fx, ACELP_24k40 )) + { + /* sub frame energy*/ + push_next_indice_fx( st_fx, st_fx->idx_shb_fr_gain_fx, NUM_BITS_SHB_ENER_SF ); + + /* gain shapes residual */ + FOR (i = 0; i < NB_SUBFR16k; i++) + { + push_next_indice_fx( st_fx, st_fx->idx_res_gs_fx[i], NUM_BITS_SHB_RES_GS ); + } + + /* voicing factor */ + push_next_indice_fx( st_fx, st_fx->idx_mixFac_fx, NUM_BITS_SHB_VF ); + } + + IF( EQ_16(st_fx->tec_tfa, 1)) + { + push_next_indice_fx( st_fx, st_fx->tec_flag, BITS_TEC ); + push_next_indice_fx( st_fx, st_fx->tfa_flag, BITS_TFA ); + } + } + + IF ( EQ_16( st_fx->bwidth_fx, FB )) + { + push_next_indice_fx( st_fx, st_fx->idxGain_fx, 4 ); + } +} + + +void TBEreset_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 bandwidth /* i : bandwidth mode */ +) +{ + IF( NE_16(st_fx->last_core_fx,ACELP_CORE)) + { + set16_fx( st_fx->old_bwe_exc_fx, 0, PIT16k_MAX * 2 ); + st_fx->bwe_non_lin_prev_scale_fx = L_deposit_l(0); + st_fx->prev_Q_bwe_exc = 31; + move16(); + } + + test(); + IF( EQ_16( bandwidth, WB )) + { + wb_tbe_extras_reset_fx( st_fx->mem_genSHBexc_filt_down_wb2_fx, st_fx->mem_genSHBexc_filt_down_wb3_fx ); + set16_fx( st_fx->mem_genSHBexc_filt_down_shb_fx, 0, 7 ); + set16_fx( st_fx->state_lpc_syn_fx, 0, 10 ); + set16_fx( st_fx->state_syn_shbexc_fx, 0, L_SHB_LAHEAD/4 ); + set16_fx( st_fx->syn_overlap_fx, 0, L_SHB_LAHEAD ); + set32_fx( st_fx->mem_csfilt_fx, 0, 2 ); + } + ELSE IF( ( EQ_16( bandwidth, SWB ))||(EQ_16(bandwidth,FB))) + { + set16_fx( st_fx->state_ana_filt_shb_fx, 0, (2*ALLPASSSECTIONS_STEEP+1) ); + + swb_tbe_reset_fx( st_fx->mem_csfilt_fx, st_fx->mem_genSHBexc_filt_down_shb_fx, st_fx->state_lpc_syn_fx, + st_fx->syn_overlap_fx, st_fx->state_syn_shbexc_fx, &(st_fx->tbe_demph_fx), &(st_fx->tbe_premph_fx), + st_fx->mem_stp_swb_fx, &(st_fx->gain_prec_swb_fx) ); + + IF( EQ_16( bandwidth, FB )) + { + set16_fx( st_fx->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + st_fx->fb_tbe_demph_fx = 0; + move16(); + fb_tbe_reset_enc_fx( st_fx->elliptic_bpf_2_48k_mem_fx, &st_fx->prev_fb_energy_fx,st_fx->elliptic_bpf_2_48k_mem_fx_Q,&st_fx->prev_fb_energy_fx_Q); + } + } +} + + diff --git a/lib_enc/tcq_core_enc_fx.c b/lib_enc/tcq_core_enc_fx.c new file mode 100644 index 0000000..82354f0 --- /dev/null +++ b/lib_enc/tcq_core_enc_fx.c @@ -0,0 +1,474 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" +#include "stl.h" + +void tcq_core_LR_enc_fx( + Encoder_State_fx* st_fx, + Word16 inp_vector_fx[], /* x5 */ + const Word32 coefs_norm_fx[], /* Q12 */ + Word32 coefs_quant_fx[], /* Q12 */ + const Word16 bit_budget, /* number of bits */ + const Word16 BANDS, + const Word16 *sfm_start, + const Word16 *sfm_end, + const Word16 *sfmsize, + Word32 *R_fx, /* Q16 */ + Word16 *npulses, + Word16 *k_sort, + const Word16 *p2a_flags, + const Word16 p2a_bands, + const Word16 *last_bitalloc, + const Word16 input_frame, + const Word16 adjustFlag, + const Word16 is_transient +) +{ + Word16 i, j, k, size, nb_bytes; + + Word16 USQ_TCQ[NB_SFM]; /* TCQ is selected by default*/ + Word16 coefs_norm_dec_fx[L_FRAME32k]; /* New output buffer (TCQ+USQ)*/ + Word32 savedstates[TCQ_MAX_BAND_SIZE]; + ARCODEC_FX arenc_fx, *parenc_fx; + BITSTREAM_FX bs_fx, *pbs_fx; + Word16 k_num[2]; + Word32 bit_surplus_fx[2]; + + Word16 flag_wbnb = 0; + Word16 lsbtcq_bits = TCQ_AMP; + Word16 tcq_arbits = 2; + Word16 nzb = 0; + Word16 nzbands = 0; + Word16 bcount = 0; + Word32 bsub_fx = 0; + Word32 abuffer_fx[MAX_PULSES]; + Word16 mbuffer_fx[MAX_PULSES]; + Word32 sbuffer_fx[MAX_PULSES]; + Word16 dpath[280]; + Word32 Rk_sort_fx[NB_SFM]; + Word32 step_scale_fx[NB_SFM]; + Word16 pulses_fx, nzp_fx; + + Word32 gain_fx, crosscorr_fx, selfcorr_fx; + Word16 hi, lo, exp; + Word32 surplus_fx, delta_fx, est_frame_bits_fx; + + Word32 leftbits = 0; + Word32 sepbits = 0; + Word32 divider = 0; + + set16_fx(dpath, 0, 280); + set32_fx(abuffer_fx, 0, MAX_PULSES); + set32_fx(sbuffer_fx, 0, MAX_PULSES); + set16_fx(mbuffer_fx, 0, MAX_PULSES); + /* initialization */ + set32_fx(Rk_sort_fx, 0, NB_SFM); + set16_fx(USQ_TCQ, 0, NB_SFM); + set16_fx(coefs_norm_dec_fx, 0, L_FRAME32k); + + InitLSBTCQ_fx(&bcount); + + test(); + test(); + IF( input_frame <= L_FRAME16k && adjustFlag == 0 && is_transient == 0 ) + { + flag_wbnb = 1; + move16(); + lsbtcq_bits = 0; + move16(); + tcq_arbits = 0; + move16(); + } + + /* TCQ Index initialize */ + parenc_fx = &arenc_fx; + pbs_fx = &bs_fx; + + pbs_fx->curPos = 7; + move16(); + pbs_fx->numbits = L_deposit_l(0); + pbs_fx->numByte = L_deposit_l(0); + FOR (i = 0; i < MAX_SIZEBUF_PBITSTREAM; i++) + { + pbs_fx->buf[i] = 0; + move16(); + } + ar_encoder_start_fx(parenc_fx, pbs_fx, L_deposit_l(bit_budget)); + + /* Bits distribution analysis */ + FOR ( i = 0; i < BANDS; i++ ) + { + IF ( GE_32(ar_div(R_fx[i], sfmsize[i]), 49152)) + { + /* USQ used for high importance bands*/ + USQ_TCQ[i] = 1; + move16(); + } + ELSE + { + /* TCQ used for usual bands */ + USQ_TCQ[i] = 0; + move16(); + } + + IF( R_fx[i] > 0 ) + { + /* nzbands++; */ + nzbands = add(nzbands, 1); + } + } + + FOR ( j = 0; j < BANDS; j++ ) + { + IF ( R_fx[j] > 0 ) + { + nzb++; + } + } + + bsub_fx = L_shl(add(tcq_arbits, lsbtcq_bits), 16); /* Q16 */ + IF( bsub_fx > 0) + { + bsub_fx = L_add( bsub_fx, 2048); + } + FOR ( j = BANDS - 1; j >= 0; j-- ) + { + IF( R_fx[j] > 0 ) + { + R_fx[j] = L_sub(R_fx[j], ar_div(bsub_fx, nzb)); + + IF( R_fx[j] < 0) + { + bsub_fx = L_sub(bsub_fx, L_add(ar_div(bsub_fx, nzb), R_fx[j])); + R_fx[j] = L_deposit_l(0); + } + ELSE + { + bsub_fx = L_sub(bsub_fx, ar_div(bsub_fx, nzb)); + } + /* nzb--; */ + nzb = sub(nzb, 1); + } + } + + /* Sort the bit allocation table (R) in ascending order, figure out number of pulses per band */ + srt_vec_ind_fx(R_fx, Rk_sort_fx, k_sort, BANDS); + + /* Quantize spectral band shapes using TCQ */ + /* Select ISC */ + set32_fx(coefs_quant_fx, 0, sfm_end[BANDS - 1]+1); + Copy32( coefs_norm_fx, coefs_quant_fx,sfm_end[BANDS-1]+1); + + delta_fx = L_deposit_l(0); + est_frame_bits_fx = L_deposit_l(0); + + test(); + test(); + IF ( LE_16(input_frame, L_FRAME16k)&&adjustFlag==0&&is_transient==0) + { + surplus_fx = -131072; + move32(); + bit_allocation_second_fx( R_fx, Rk_sort_fx, BANDS, sfmsize, k_sort, k_num, p2a_flags, p2a_bands, last_bitalloc, input_frame ); + + nzbands = 0; + move16(); + FOR ( j = 0; j < BANDS; j++ ) + { + IF( NE_16(j, k_num[0])&&NE_16(j,k_num[1])) + { + leftbits = L_add( leftbits, R_fx[k_sort[j]]); + if( R_fx[k_sort[j]] > 0 ) + { + nzbands = add(nzbands, 1); + } + } + ELSE + { + sepbits = L_add( sepbits, R_fx[k_sort[j]]); + } + } + /* Separate the position information from the input signal(coefs_norm) */ + /* Gather the NZ coefficients*/ + FOR ( k = 0; k < BANDS; k++) /* Loop through non-zero blocks */ + { + test(); + IF ( NE_16(k, k_num[0])&&NE_16(k,k_num[1])) + { + test(); + test(); + IF ( R_fx[k_sort[k]] > 0 && USQ_TCQ[k_sort[k]] == 0 ) /* Then have non-zero block AND WILL BE ENCODED BY TCQ */ + { + /* Encode Position Info, NZ Info, Signs */ + size = sfmsize[k_sort[k]]; + move16(); + + /* Determine scale step, ISC and TCQ quantizer */ + GetISCScale_fx( &coefs_quant_fx[sfm_start[k_sort[k]]], size, + L_add( R_fx[k_sort[k]], delta_fx), + /* R_fx[k_sort[k]], */ + &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], &step_scale_fx[k_sort[k]], &surplus_fx, &pulses_fx, savedstates, 0, &nzp_fx + , 0, 0, 0, 0 + ); + leftbits = L_sub( leftbits, L_add( R_fx[k_sort[k]], delta_fx) ); + npulses[ k_sort[k]] = pulses_fx; + move16(); + + encode_position_ari_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, &est_frame_bits_fx ); + encode_magnitude_tcq_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, npulses[k_sort[k]], nzp_fx, savedstates, &est_frame_bits_fx ); + encode_signs_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, nzp_fx, &est_frame_bits_fx ); + nzbands--; + } + /* Have USQ coded band */ + ELSE IF( R_fx[k_sort[k]] > 0 && EQ_16(USQ_TCQ[k_sort[k]], 1)) + { + size = sfmsize[k_sort[k]]; + move16(); + + GetISCScale_fx( &coefs_quant_fx[ sfm_start[ k_sort[k]]], size, + L_add( R_fx[k_sort[k]], delta_fx), + /* R_fx[k_sort[k]], */ + &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], &step_scale_fx[k_sort[k]], &surplus_fx, &pulses_fx, savedstates, 1, &nzp_fx + , 0, 0, 0, 0 + ); + leftbits = L_sub( leftbits, L_add( R_fx[k_sort[k]], delta_fx) ); + npulses[ k_sort[k]] = pulses_fx; + move16(); + + encode_position_ari_fx( parenc_fx, &coefs_norm_dec_fx[sfm_start[k_sort[k]]], size, &est_frame_bits_fx ); + encode_magnitude_usq_fx( parenc_fx, &coefs_norm_dec_fx[sfm_start[k_sort[k]]], size, npulses[k_sort[k]], nzp_fx, &est_frame_bits_fx ); + encode_signs_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[ k]]], size, nzp_fx, &est_frame_bits_fx ); + nzbands--; + } + ELSE /* Then have zero block */ + { + npulses[ k_sort[ k]] = 0; + move16(); + size = sfmsize[k_sort[k]]; + move16(); + } + + delta_fx = L_deposit_l(0); + test(); + IF( R_fx[k_sort[k]] > 0 && surplus_fx < 0 ) + { + /* delta_fx = L_deposit_h( div_l( surplus_fx, nzbands ) ); */ + IF( nzbands <= 1 ) + { + divider = 0; + } + ELSE + { + divider = 2; + } + + IF( L_add( L_add( surplus_fx, sepbits), ar_div( leftbits, divider) ) < 0 ) + { + /* Overflow possible => start to distribute negative surplus */ + delta_fx = ar_div( surplus_fx + sepbits, nzbands); + } + else + { + delta_fx = 0; + } + surplus_fx = L_sub(surplus_fx, delta_fx); + } + } + } + + test(); + test(); + test(); + IF (( GT_32(surplus_fx,524288)&&EQ_16(input_frame,L_FRAME8k))||(GT_32(surplus_fx,786432)&&EQ_16(input_frame,L_FRAME16k))) + { + bit_surplus_fx[0] = Mult_32_16(surplus_fx,24576); /* Q16 */ + bit_surplus_fx[1] = Mult_32_16(surplus_fx,8192); /* Q16 */ + } + ELSE + { + bit_surplus_fx[0] = surplus_fx; + move32(); + bit_surplus_fx[1] = L_deposit_l(0); + } + + FOR ( k = 0; k < BANDS; k++ ) + { + FOR ( j = 0; j < 2; j++ ) + { + IF ( EQ_16(k, k_num[j])) + { + R_fx[k_sort[k]] = L_add(R_fx[k_sort[k]],bit_surplus_fx[j]); + + test(); + test(); + IF ( R_fx[k_sort[k]] > 0 && USQ_TCQ[k_sort[k]] == 0 ) /* Then have non-zero block AND WILL BE ENCODED BY TCQ */ + { + /* Encode Position Info, NZ Info, Signs */ + size = sfmsize[k_sort[k]]; + move16(); + + /* Determine scale step, ISC and TCQ quantizer */ + GetISCScale_fx( &coefs_quant_fx[sfm_start[k_sort[k]]], size, R_fx[k_sort[k]], &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], &step_scale_fx[k_sort[k]], &surplus_fx, &pulses_fx, savedstates, 0, &nzp_fx + , 0, 0, 0, 0 + ); + + npulses[ k_sort[k]] = pulses_fx; + move16(); + + encode_position_ari_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, &est_frame_bits_fx ); + encode_magnitude_tcq_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, npulses[k_sort[k]], nzp_fx, savedstates, &est_frame_bits_fx ); + encode_signs_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, nzp_fx, &est_frame_bits_fx ); + } + /* Have USQ coded band */ + ELSE IF( R_fx[k_sort[k]] > 0 && EQ_16(USQ_TCQ[k_sort[k]], 1)) + { + size = sfmsize[k_sort[k]]; + move16(); + + GetISCScale_fx( &coefs_quant_fx[ sfm_start[ k_sort[k]]], size, R_fx[k_sort[k]], &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], &step_scale_fx[k_sort[k]], &surplus_fx, &pulses_fx, savedstates, 1, &nzp_fx + , 0, 0, 0, 0 + ); + + npulses[ k_sort[k]] = pulses_fx; + move16(); + + encode_position_ari_fx( parenc_fx, &coefs_norm_dec_fx[sfm_start[k_sort[k]]], size, &est_frame_bits_fx ); + encode_magnitude_usq_fx( parenc_fx, &coefs_norm_dec_fx[sfm_start[k_sort[k]]], size, npulses[k_sort[k]], nzp_fx, &est_frame_bits_fx ); + encode_signs_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, nzp_fx, &est_frame_bits_fx ); + } + ELSE /* Then have zero block */ + { + npulses[ k_sort[k]] = 0; + move16(); + size = sfmsize[k_sort[k]]; + move16(); + } + } + } + } + } + ELSE + { + surplus_fx = L_deposit_l(0); + + /* Separate the position information from the input signal(coefs_norm) */ + /* Gather the NZ coefficients*/ + FOR( k = 0; k < BANDS; k++) /* Loop through non-zero blocks */ + { + IF( R_fx[k_sort[k]] > 0 ) + { + size = sfmsize[k_sort[k]]; + move16(); + GetISCScale_fx( &coefs_quant_fx[ sfm_start[ k_sort[k]]], size, R_fx[k_sort[k]] + delta_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], &step_scale_fx[k_sort[k]], &surplus_fx, &pulses_fx, savedstates, 1, &nzp_fx, &bcount, abuffer_fx, mbuffer_fx, sbuffer_fx); + + npulses[ k_sort[k]] = pulses_fx; + move16(); + encode_position_ari_fx(parenc_fx, &coefs_norm_dec_fx[sfm_start[k_sort[k]]], size, &est_frame_bits_fx); + encode_magnitude_usq_fx(parenc_fx, &coefs_norm_dec_fx[sfm_start[k_sort[k]]], size, npulses[k_sort[k]], nzp_fx, &est_frame_bits_fx); + encode_signs_fx(parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, nzp_fx, &est_frame_bits_fx); + + /* nzbands--; */ + nzbands = sub(nzbands, 1); + } + ELSE /* Then have zero block */ + { + npulses[ k_sort[k]] = 0; + move16(); + size = sfmsize[k_sort[k]]; + move16(); + } + + /* Surplus distribution */ + /* if( surplus > 0.0f && nzbands > 0 ) */ + test(); + IF( surplus_fx > 0 && nzbands > 0 ) + { + /* delta = surplus / nzbands; + surplus -= delta; */ + + delta_fx = ar_div(surplus_fx, nzbands); + surplus_fx = L_sub(surplus_fx, delta_fx); + } + } + } + + TCQLSB_fx(bcount, /*abuffer, */abuffer_fx, /*mbuffer, */mbuffer_fx, /*sbuffer, */sbuffer_fx, dpath); + + /* Save TCQ path to bitstream */ + SaveTCQdata_fx(parenc_fx, dpath, lsbtcq_bits); + + /* Add tcq sequence to decoding buffer */ + InitLSBTCQ_fx(&bcount); + + ar_encoder_done_fx(parenc_fx); + + /* Loop through non-zero blocks */ + FOR (i = 0; i < L_FRAME32k; i++) + { + coefs_norm_dec_fx[i] = extract_l(L_mult0(coefs_norm_dec_fx[i], 5)); + } + IF( !flag_wbnb ) + { + FOR ( k = 0; k < BANDS; k++) + { + IF( R_fx[k_sort[k]] > 0 ) + { + size = sfmsize[k_sort[k]]; + move16(); + RestoreTCQ_fx( &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, &bcount, mbuffer_fx ); + } + } + } + + nb_bytes = shr(bit_budget, 3); + j = sub(bit_budget, shl(nb_bytes, 3)); + FOR( i = 0; i < nb_bytes; i++ ) + { + push_indice_fx(st_fx, IND_HQ2_SUBBAND_TCQ, pbs_fx->buf[i], 8); + } + IF( j > 0 ) + { + push_indice_fx(st_fx, IND_HQ2_SUBBAND_TCQ, shr(pbs_fx->buf[nb_bytes],(8 - j)), j); + } + /* Clear decoding buffer */ + set32_fx(coefs_quant_fx, 0, sfm_end[BANDS-1]+1); + + /* New analysis of decoded frame */ + FOR ( i = 0; i < BANDS; i++ ) + { + IF ( R_fx[ k_sort[i]] > 0 ) + { + gain_fx = L_deposit_l(0); + + crosscorr_fx = L_deposit_l(0); + selfcorr_fx = L_deposit_l(0); + + FOR ( j = 0; j < sfmsize[k_sort[i]]; j++ ) + { + crosscorr_fx = L_add( crosscorr_fx, Mult_32_16( coefs_norm_fx[sfm_start[k_sort[ i]]+j], shl(coefs_norm_dec_fx[sfm_start[k_sort[ i]]+j], 2) ) );/*1 */ + selfcorr_fx = L_mac0(selfcorr_fx, coefs_norm_dec_fx[sfm_start[k_sort[ i]]+j], coefs_norm_dec_fx[sfm_start[k_sort[ i]]+j]); + } + + exp =sub(norm_l(crosscorr_fx), 1); + gain_fx = ar_div( L_shl(crosscorr_fx, exp), selfcorr_fx); /* 1 + exp */ + gain_fx = L_shl( gain_fx, sub( 16, 1 + exp) + 2);/* 0.2 * Q16 */ + lo = L_Extract_lc(gain_fx, &hi); + /* Use optimal gain */ + FOR ( j = 0; j < sfmsize[k_sort[i]]; j++ ) + { + inp_vector_fx[sfm_start[k_sort[i]]+j] = coefs_norm_dec_fx[sfm_start[k_sort[i]]+j]; + move16(); + coefs_quant_fx[sfm_start[k_sort[ i]]+j] = L_add(L_shl(L_mult0(hi, coefs_norm_dec_fx[sfm_start[k_sort[ i]]+j]), 12), + L_shr(L_mult0(lo, coefs_norm_dec_fx[sfm_start[k_sort[ i]]+j]), 3)); /* Q12 */ + } + } + } + + + + return; + +} diff --git a/lib_enc/tcx_ltp_enc.c b/lib_enc/tcx_ltp_enc.c new file mode 100644 index 0000000..ed7bbd1 --- /dev/null +++ b/lib_enc/tcx_ltp_enc.c @@ -0,0 +1,614 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "prot_fx.h" +#include "stl.h" +#include "cnst_fx.h" +#include "basop_util.h" +#include "rom_com_fx.h" + +static Word32 dot(const Word16 *X, const Word16 *Y, Word16 n) +{ + Word32 acc; + Word16 i; + + Word64 acc_64; + acc_64 = 0; + move64(); + FOR (i = 0; i < n; i++) + { + acc_64 = W_mac0_16_16(acc_64, X[i], Y[i]); + } + acc = W_sat_l( acc_64 ); + + return acc; +} + +static Word32 interpolate_corr( /* o : interpolated value */ + const Word32 *x, /* i : input vector */ + const Word16 frac, /* i : fraction of lag */ + const Word16 frac_max /* i : max fraction */ +) +{ + Word32 s; + const Word16 *c, *win; + + + win = E_ROM_inter4_1; + if (EQ_16(frac_max, 6))win=E_ROM_inter6_1; + + + s = L_deposit_l(0); + + c = &win[frac]; + s = L_add(s, Mpy_32_16_1(x[0], *c)); + c += frac_max; + s = L_add(s, Mpy_32_16_1(x[-1], *c)); + c += frac_max; + s = L_add(s, Mpy_32_16_1(x[-2], *c)); + c += frac_max; + s = L_add(s, Mpy_32_16_1(x[-3], *c)); + + c = &win[frac_max-frac]; + s = L_add(s, Mpy_32_16_1(x[1], *c)); + c += frac_max; + s = L_add(s, Mpy_32_16_1(x[2], *c)); + c += frac_max; + s = L_add(s, Mpy_32_16_1(x[3], *c)); + c += frac_max; + s = L_add(s, Mpy_32_16_1(x[4], *c)); + + + return s; +} + +void tcx_ltp_pitch_search( + Word16 pitch_ol, + Word16 *pitch_int, + Word16 *pitch_fr, + Word16 *index, + Word16 *norm_corr, + const Word16 len, + Word16 *wsp, + Word16 pitmin, + Word16 pitfr1, + Word16 pitfr2, + Word16 pitmax, + Word16 pitres +) +{ + Word16 i, t, t0, t1, step, fraction, t0_min, t0_max, t_min, t_max, delta, temp_m, temp_e, s, s_wsp; + Word32 cor_max, cor[256], *pt_cor, temp; + Word16 wsp2[L_FRAME_PLUS+PIT_MAX_MAX+L_INTERPOL1]; + + + + delta = 16; + move16(); + if ( EQ_16(pitres, 6)) + { + delta = 8; + move16(); + } + + t0_min = sub(pitch_ol, shr(delta, 1)); + t0_max = sub(add(t0_min, delta), 1); + + IF ( LT_16(t0_min, pitmin)) + { + t0_min = pitmin; + move16(); + t0_max = sub(add(t0_min, delta), 1); + } + + IF ( GT_16(t0_max, pitmax)) + { + t0_max = pitmax; + move16(); + t0_min = add(sub(t0_max, delta), 1); + } + + t_min = sub(t0_min, L_INTERPOL1); + t_max = add(t0_max, L_INTERPOL1); + + /* normalize wsp */ + assert(len+t_max <= L_FRAME_PLUS+PIT_MAX_MAX+L_INTERPOL1); + s_wsp = getScaleFactor16(wsp - t_max, add(len, t_max)); + s_wsp = sub(s_wsp, 4); + FOR (t = negate(t_max); t < len; t++) + { + wsp2[t+t_max] = shl(wsp[t], s_wsp); + move16(); + } + wsp = wsp2 + t_max; + + pt_cor = cor; + + FOR ( t=t_min; t<=t_max; t++ ) + { + *pt_cor = dot(wsp, wsp-t, len); + pt_cor++; + } + + pt_cor = cor + L_INTERPOL1; + cor_max = L_add(*pt_cor++, 0); + t1 = t0_min; + move16(); + + FOR ( t = add(t0_min, 1); t <= t0_max; t++ ) + { + IF ( *pt_cor > cor_max ) + { + cor_max = *pt_cor; + t1 = t; + } + pt_cor++; + } + + temp = dot(wsp, wsp, len); + s = norm_l(temp); + temp_m = extract_h(L_shl(temp, s)); + temp_e = negate(s); + + temp = dot(wsp-t1, wsp-t1, len); + s = norm_l(temp); + temp_m = mult(temp_m, extract_h(L_shl(temp, s))); + temp_e = sub(temp_e, s); + + temp_m = Sqrt16(temp_m, &temp_e); + + if (temp_m == 0) + { + temp_m = 1; + move16(); + } + s = sub(norm_l(cor_max), 1); + temp_m = divide1616(extract_h(L_shl(cor_max, s)), temp_m); + temp_e = sub(negate(s), temp_e); + + BASOP_SATURATE_WARNING_OFF + *norm_corr = shl(temp_m, temp_e); + BASOP_SATURATE_WARNING_ON + + IF ( GE_16(t1, pitfr1)) + { + *pitch_int = t1; + move16(); + *pitch_fr = 0; + move16(); + + *index = add(sub(t1, pitfr1), extract_l(L_mac0(L_mult0(sub(pitfr2, pitmin), pitres), + sub(pitfr1, pitfr2), shr(pitres,1)))); + move16(); + + return; + } + + /*------------------------------------------------------------------* + * Search fractional pitch with 1/4 subsample resolution. + * search the fractions around t0 and choose the one which maximizes + * the interpolated normalized correlation. + *-----------------------------------------------------------------*/ + + pt_cor = cor + sub(L_INTERPOL1, t0_min); + t0 = t1; + move16(); + + step = 1; + move16(); + if (GE_16(t0, pitfr2)) + { + step = 2; + move16(); + } + fraction = step; + move16(); + + IF (EQ_16(t0, t0_min)) /* Limit case */ + { + fraction = 0; + move16(); + cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres ); + } + ELSE /* Process negative fractions */ + { + t0 = sub(t0, 1); + cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres ); + + FOR ( i = add(fraction, step); i < pitres; i += step ) + { + temp = interpolate_corr( &pt_cor[t0], i, pitres ); + + IF (GT_32(temp, cor_max)) + { + cor_max = L_add(temp, 0); + fraction = i; + move16(); + } + } + } + + i = 0; + FOR ( i = 0; i < pitres; i += step ) /* Process positive fractions */ + { + temp = interpolate_corr( &pt_cor[t1], i, pitres ); + + IF (GT_32(temp, cor_max)) + { + cor_max = L_add(temp, 0); + fraction = i; + move16(); + t0 = t1; + move16(); + } + } + + *pitch_int = t0; + move16(); + *pitch_fr = fraction; + move16(); + + IF ( GE_16(t0, pitfr2)) + { + *index = add( extract_l(L_mac0(L_mult0(sub(t0, pitfr2), shr(pitres,1)), + sub(pitfr2, pitmin), pitres)), shr(fraction,1) ); + move16(); + } + ELSE + { + *index = add(imult1616(sub(t0, pitmin), pitres), fraction); + move16(); + } + +} + + +static void tcx_ltp_find_gain( Word16 *speech, Word16 *pred_speech, Word16 L_frame, Word16 *gain, Word16 *gain_index ) +{ + Word32 corr, ener; + Word16 i, g, s1, s2, tmp; + + + + s1 = sub(getScaleFactor16(speech, L_frame), 4); + s2 = sub(getScaleFactor16(pred_speech, L_frame), 4); + + /* Find gain */ + corr = L_deposit_l(0); + ener = L_deposit_l(1); + + FOR (i = 0; i < L_frame; i++) + { + tmp = shl(pred_speech[i], s2); + corr = L_mac0(corr, shl(speech[i], s1), tmp); + ener = L_mac0(ener, tmp, tmp); + } + + s1 = sub(1, add(s1, s2)); + s2 = sub(1, shl(s2, 1)); + + tmp = sub(norm_l(corr), 1); + corr = L_shl(corr, tmp); + s1 = sub(s1, tmp); + + tmp = norm_l(ener); + ener = L_shl(ener, tmp); + s2 = sub(s2, tmp); + + g = divide1616(round_fx(corr), round_fx(ener)); + BASOP_SATURATE_WARNING_OFF + g = shl(g, sub(s1, s2)); + BASOP_SATURATE_WARNING_ON + + /* Quantize gain */ + g = shr(sub(g, 0x1000), 13); + g = s_max(g, -1); + + *gain_index = g; + move16(); + + /* Dequantize gain */ + *gain = imult1616(add(g, 1), 0x1400); + move16(); + + +} + +void tcx_ltp_encode( Word8 tcxltp_on, + Word8 tcxOnly, + Word16 tcxMode, + Word16 L_frame, + Word16 L_subfr, + Word16 *speech, + Word16 *speech_ltp, + Word16 *wsp, + Word16 Top, + Word16 *ltp_param, + Word16 *ltp_bits, + Word16 *pitch_int, + Word16 *pitch_fr, + Word16 *gain, + Word16 *pitch_int_past, + Word16 *pitch_fr_past, + Word16 *gain_past, + Word16 *norm_corr_past, + Word16 last_core, + Word16 pitmin, + Word16 pitfr1, + Word16 pitfr2, + Word16 pitmax, + Word16 pitres, + struct TransientDetection const * pTransientDetection, + Word8 SideInfoOnly, + Word16 *A, + Word16 lpcorder + ) +{ + Word16 n; + Word16 norm_corr; + Word16 pred_speech[L_FRAME32k]; + Word16 tempFlatness; + Word16 maxEnergyChange; + Word16 buf_zir[M+L_SUBFR], *zir; + Word16 Aest[M+1]; + Word16 alpha, step; + + + + norm_corr = 0; + move16(); + + /* Reset memory if past frame is acelp */ + IF (last_core == ACELP_CORE) + { + *pitch_int_past = L_frame; + move16(); + *pitch_fr_past = 0; + move16(); + *gain_past = 0; + move16(); + } + + /* By default, LTP is off */ + ltp_param[0] = 0; + move16(); + + test(); + IF (tcxltp_on != 0 || SideInfoOnly != 0) + { + Word16 nPrevSubblocks; + Word8 isTCX10 = 0; + + if (EQ_16(tcxMode, TCX_10)) + { + isTCX10 = 1; + move16(); + } + + /* Find pitch lag */ + tcx_ltp_pitch_search( Top, pitch_int, pitch_fr, <p_param[1], &norm_corr, L_frame, wsp, pitmin, pitfr1, pitfr2, pitmax, pitres ); + + nPrevSubblocks = extract_h(L_mac(0x17fff, NSUBBLOCKS, div_s(*pitch_int, L_frame))); + nPrevSubblocks = add(s_min(nPrevSubblocks, NSUBBLOCKS), 1); + + tempFlatness = GetTCXAvgTemporalFlatnessMeasure(pTransientDetection, NSUBBLOCKS, nPrevSubblocks); + + maxEnergyChange = GetTCXMaxenergyChange(pTransientDetection, + (const Word8) isTCX10, + NSUBBLOCKS, nPrevSubblocks); + + /* Switch LTP on */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + BASOP_SATURATE_WARNING_OFF; + if ( ( + tcxOnly == 0 && + EQ_16(tcxMode, TCX_20) && + GT_16(mult(norm_corr, *norm_corr_past), 0x2000) && + LT_16(tempFlatness, 448/*3.5f Q7*/) + ) || + ( + tcxOnly != 0 && + EQ_16(tcxMode, TCX_10) && + GT_16(s_max(norm_corr, *norm_corr_past), 0x4000) && + LT_16(maxEnergyChange, 448/*3.5f Q7*/) + ) || + ( /* Use LTP for lower correlation when pitch lag is big, L_frame*(1.2f-norm_corr) < pitch_int <=> norm_corr > 1.2f-pitch_int/L_frame */ + tcxOnly != 0 && + GT_16(norm_corr, 14418/*0.44f Q15*/) && + L_msu(L_mult(L_frame, sub(19661/*1.2f Q14*/, shr(norm_corr, 1))), *pitch_int, 1<<14) < 0 /* L_frame*(1.2f-norm_corr) < pitch_int */ + ) || + ( + tcxOnly != 0 && + EQ_16(tcxMode, TCX_20) && + GT_16(norm_corr, 14418/*0.44f Q15*/) && + ( + LT_16(tempFlatness, 768/*6.0f Q7*/) || + ( + LT_16(tempFlatness, 896/*7.0f Q7*/) && + LT_16(maxEnergyChange, 2816/*22.0f Q7*/) + ) + ) + ) + ) + { + ltp_param[0] = 1; + move16(); + } + BASOP_SATURATE_WARNING_ON; + } + + IF (ltp_param[0] != 0) + { + /* Find predicted signal */ + predict_signal( speech, pred_speech, *pitch_int, *pitch_fr, pitres, L_frame ); + + /* Find gain */ + tcx_ltp_find_gain( speech, pred_speech, L_frame, gain, <p_param[2] ); + + /* Total number of bits for LTP */ + IF (NE_16(ltp_param[2], -1) ) /* gain > 0 */ + { + *ltp_bits = 12; + move16(); + } + ELSE /* gain <= 0 -> turn off LTP */ + { + ltp_param[0] = 0; + move16(); + } + } + + IF (ltp_param[0] == 0) + { + /* No LTP -> set everything to zero */ + *pitch_int = L_frame; + move16(); + *pitch_fr = 0; + move16(); + ltp_param[1] = 0; + move16(); + set16_fx( pred_speech, 0, L_frame ); + *gain = 0; + move16(); + ltp_param[2] = 0; + move16(); + + *ltp_bits = 0; + move16(); + test(); + if (tcxltp_on != 0 || SideInfoOnly != 0) + { + *ltp_bits = 1; + move16(); + } + } + + if (SideInfoOnly != 0) + { + *gain = 0; + move16(); + } + + test(); + IF (*gain_past == 0 && *gain == 0) + { + Copy(speech, speech_ltp, L_subfr); + } + ELSE IF (*gain_past == 0) + { + alpha = 0; + move16(); + + /* step = 1.f/(float)(L_subfr); */ + step = shl(2, norm_s(L_subfr)); + if (s_and(L_subfr, sub(L_subfr, 1)) != 0) + { + step = mult_r(step, 26214/*64.f/80.f Q15*/); + } + + FOR (n = 0; n < L_subfr; n++) + { + speech_ltp[n] = sub(speech[n], mult_r(*gain, mult_r(alpha, pred_speech[n]))); + move16(); + BASOP_SATURATE_WARNING_OFF; + alpha = add(alpha, step); + BASOP_SATURATE_WARNING_ON; + } + } + ELSE + { + IF (A == NULL) + { + tcx_ltp_get_lpc(speech-L_frame, L_frame, Aest, lpcorder); + A = Aest; + } + + IF (*gain > 0) + { + predict_signal(speech-lpcorder, buf_zir, *pitch_int, *pitch_fr, pitres, lpcorder); + } + ELSE { + set16_fx(buf_zir, 0, lpcorder); + } + + FOR (n = 0; n < lpcorder; n++) + { + buf_zir[n] = add(sub(speech_ltp[n-lpcorder], speech[n-lpcorder]), mult_r(*gain, buf_zir[n])); + move16(); + } + + zir = buf_zir + lpcorder; + + set16_fx(zir, 0, L_subfr); + + E_UTIL_synthesis(0, A, zir, zir, L_subfr, buf_zir, 0, lpcorder); + + alpha = 0x7FFF; + /* step = 1.f/(float)(L_subfr/2); */ + step = shl(4, norm_s(L_subfr)); + if (s_and(L_subfr, sub(L_subfr, 1)) != 0) + { + step = mult_r(step, 26214/*64.f/80.f Q15*/); + } + + FOR (n = shr(L_subfr, 1); n < L_subfr; n++) + { + zir[n] = mult_r(zir[n], alpha); + move16(); + alpha = sub(alpha, step); + } + + FOR (n = 0; n < L_subfr; n++) + { + speech_ltp[n] = add(sub(speech[n], mult_r(*gain, pred_speech[n])), zir[n]); + move16(); + } + } + + test(); + IF ( SideInfoOnly || *gain == 0) + { + FOR ( n=L_subfr; n +#include +#include +#include "stl.h" +#include "options.h" +#include "prot_fx.h" +#include "rom_basop_util.h" +#include "basop_util.h" +#include "cnst_fx.h" + +#define inv_int InvIntTable +extern const Word16 int_sqr[17]; + +static Word16 quantize(Word32 x, Word16 invGain, Word16 shift, Word32 offset) +{ + Word16 tmp16; + Word32 tmp32; + + tmp32 = Mpy_32_16_1(L_abs(x), invGain); /* multiply */ + tmp32 = L_shl(tmp32, shift); /* convert to 15Q16 */ + tmp32 = L_add(tmp32, offset); /* add offset */ + tmp16 = extract_h(tmp32); /* truncate */ + if (x < 0) tmp16 = negate(tmp16); /* restore sign */ + + return tmp16; +} + +/* compute noise-measure flags for spectrum filling and quantization (0: tonal, 1: noise-like) */ +void ComputeSpectrumNoiseMeasure(const Word32 *powerSpec, + Word16 L_frame, + Word16 startLine, + Word8 resetMemory, + Word8 *noiseFlags, + Word16 lowpassLine) +{ + Word16 i, lastTone; + Word32 s, c; + Word16 tmp16; + Word32 tmp1, tmp2 = 0; /* initialization only to avoid compiler warning, not counted */ + + int j; + + IF (resetMemory != 0) + { + FOR (i = 0; i < lowpassLine; i++) + { + noiseFlags[i] = 0; + move16(); + } + } + + FOR (i = lowpassLine; i < L_frame; i++) + { + noiseFlags[i] = 1; + move16(); + } + + test(); + IF (powerSpec != NULL && LT_16(add(startLine, 6), L_frame)) + { + lastTone = 0; + move16(); + + /* noise-measure flags for spectrum filling and quantization (0: tonal, 1: noise-like) */ + i = sub(startLine, 1); + s = 0; + move32(); + for (j=-7; j<8; j++) + { + s = L_add(s, L_shr(powerSpec[i+j], 4)); + } + tmp16 = sub(lowpassLine, 7); + FOR (i = add(i, 1); i < tmp16; i++) + { + c = L_shr(powerSpec[i-1], 4); + c = L_add(c, L_shr(powerSpec[i], 4)); + c = L_add(c, L_shr(powerSpec[i+1], 4)); + + s = L_sub(s, L_shr(powerSpec[i-8], 4)); + s = L_add(s, L_shr(powerSpec[i+7], 4)); + + tmp1 = L_shr(c, 2); + if (noiseFlags[i] == 0) c = L_shl(c, 1); + if (noiseFlags[i] == 0) tmp2 = L_sub(c, tmp1); /* 1.75 * c */ + if (noiseFlags[i] != 0) tmp2 = L_add(c, tmp1); /* 1.25 * c */ + + tmp2 = L_sub(s, tmp2); + if (tmp2 >= 0) + { + noiseFlags[i] = 1; + move16(); + } + if (tmp2 < 0) + { + noiseFlags[i] = 0; + move16(); + } + if (tmp2 < 0) + { + lastTone = i; + move16(); + } + } + + /* lower L_frame*startRatio lines are tonal (0), upper 7 lines are processed separately */ + tmp16 = sub(lowpassLine, 1); + FOR (; i < tmp16; i++) + { + c = L_shr(powerSpec[i-1], 4); + c = L_add(c, L_shr(powerSpec[i], 4)); + c = L_add(c, L_shr(powerSpec[i+1], 4)); + + tmp1 = L_shr(c, 2); + if (noiseFlags[i] == 0) c = L_shl(c, 1); + if (noiseFlags[i] == 0) tmp2 = L_sub(c, tmp1); /* 1.75 * c */ + if (noiseFlags[i] != 0) tmp2 = L_add(c, tmp1); /* 1.25 * c */ + + /* running sum can't be updated any more, just use the latest one */ + tmp2 = L_sub(s, tmp2); + if (tmp2 >= 0) + { + noiseFlags[i] = 1; + move16(); + } + if (tmp2 < 0) + { + noiseFlags[i] = 0; + move16(); + /* lastTone = i; */ + } + } + noiseFlags[i] = 1; /* uppermost line is defined as noise-like (1) */ move16(); + + if (lastTone > 0) /* spread uppermost tonal line one line upward */ + { + noiseFlags[lastTone+1] = 0; + move16(); + } + } + +} + +void detectLowpassFac(const Word32 *powerSpec, Word16 powerSpec_e, Word16 L_frame, Word8 rectWin, Word16 *pLpFac, Word16 lowpassLine) +{ + Word16 i, tmp; + Word32 threshold; + + + threshold = 256l/*0.1f * 2*NORM_MDCT_FACTOR Q3*/; /* Q3 */ + BASOP_SATURATE_WARNING_OFF /* Allow saturation, because threshold is being compared to powerSpec[i] below. */ + threshold = L_shl(threshold, sub(28, powerSpec_e)); + + if (rectWin != 0) + { + /* compensate for bad side-lobe attenuation with asymmetric windows */ + threshold = L_shl(threshold, 1); + } + BASOP_SATURATE_WARNING_ON + + tmp = shr(lowpassLine, 1); + FOR (i = sub(lowpassLine, 1); i >= tmp; i--) + { + IF (GT_32(powerSpec[i], threshold)) + { + BREAK; + } + } + + tmp = getInvFrameLen(L_frame); + + tmp = mult_r(22938/*0.7f Q15*/, round_fx(L_shl(L_mult0(add(i, 1), tmp), 9))); + *pLpFac = add(tmp, mult_r(9830/*0.3f Q15*/, *pLpFac)); + move16(); + +} + +/*-----------------------------------------------------------* + * Compute noise-measure flags for spectrum filling * + * and quantization (0: tonal, 1: noise-like). * + * Detect low pass if present. * + *-----------------------------------------------------------*/ +void AnalyzePowerSpectrum( + Encoder_State_fx *st, /* i/o: encoder states */ + Word16 L_frame, /* input: frame length */ + Word16 L_frameTCX, /* input: full band frame length */ + Word16 left_overlap, /* input: left overlap length */ + Word16 right_overlap, /* input: right overlap length */ + Word32 const mdctSpectrum[], /* input: MDCT spectrum */ + Word16 mdctSpectrum_e, + Word16 const signal[], /* input: windowed signal corresponding to mdctSpectrum */ + Word32 powerSpec[], /* output: Power spectrum. Can point to signal */ + Word16 *powerSpec_e +) +{ + Word16 i, iStart, iEnd, lowpassLine; + Word16 tmp, s1, s2; + Word32 tmp32; + Word8 tmp8; + + lowpassLine = L_frameTCX; + move16(); + + *powerSpec_e = 16; + move16(); + TCX_MDST(signal, + powerSpec, + powerSpec_e, + left_overlap, + sub(L_frameTCX, shr(add(left_overlap, right_overlap), 1)), + right_overlap); + + iStart = 0; + move16(); + iEnd = L_frameTCX; + move16(); + + IF (st->narrowBand != 0) + { + attenuateNbSpectrum(L_frameTCX, powerSpec); + } + + /* get shift to common exponent */ + s1 = 0; + move16(); + s2 = 0; + move16(); + tmp = sub(mdctSpectrum_e, *powerSpec_e); + if (tmp > 0) + { + s2 = negate(tmp); + } + if (tmp < 0) + { + s1 = tmp; + move16(); + } + + /* get headroom */ + tmp = sub(getScaleFactor32(mdctSpectrum, L_frameTCX), s1); + tmp = s_min(tmp, sub(getScaleFactor32(powerSpec, L_frameTCX), s2)); + s1 = add(s1, tmp); + s2 = add(s2, tmp); + + /* power spectrum: MDCT^2 + MDST^2 */ + FOR (i = iStart; i < iEnd; i++) + { + tmp = round_fx(L_shl(mdctSpectrum[i], s1)); + tmp32 = L_mult0(tmp, tmp); + + tmp = round_fx(L_shl(powerSpec[i], s2)); + tmp32 = L_mac0(tmp32, tmp, tmp); + + powerSpec[i] = tmp32; + move32(); + } + + *powerSpec_e = add(shl(sub(mdctSpectrum_e, s1), 1), 1); + move16(); + + tmp8 = 0; + move16(); + test(); + if ( L_msu0(L_mult0(st->L_frame_fx, extract_l(st->last_sr_core)), st->L_frame_past, extract_l(st->sr_core)) != 0 + || NE_16(st->last_core_fx, TCX_20_CORE ) ) + { + tmp8 = 1; + move16(); + } + + ComputeSpectrumNoiseMeasure(powerSpec, + L_frameTCX, + divide3216(L_mult(st->nmStartLine, L_frame), st->L_frame_fx), + tmp8, + st->memQuantZeros, + lowpassLine); + + IF( LE_32(st->total_brate_fx, ACELP_24k40)) + { + lowpassLine = shl(mult(st->tcx_cfg.bandwidth, L_frame), 1); + + test(); + detectLowpassFac(powerSpec, *powerSpec_e, + L_frame, + sub(st->last_core_fx, ACELP_CORE) == 0, + &st->measuredBwRatio, + lowpassLine); + } + ELSE + { + st->measuredBwRatio = 0x4000; + move16(); + } +} + +void AdaptLowFreqEmph(Word32 x[], + Word16 x_e, + Word16 xq[], + Word16 invGain, + Word16 invGain_e, + Word16 tcx_lpc_shaped_ari, + Word16 lpcGains[], Word16 lpcGains_e[], + const Word16 lg + ) +{ + Word16 i, i_max, i_max_old, lg_4, tmp16, s; + Word32 tmp32; + + + IF (tcx_lpc_shaped_ari == 0) + { + lg_4 = shr(lg, 2); + + /* 1. find first magnitude maximum in lower quarter of spectrum */ + invGain_e = add(invGain_e, 1); + i_max = -1; + move16(); + + FOR (i = 0; i < lg_4; i++) + { + tmp32 = Mpy_32_16_1(L_abs(x[i]), invGain); /* multiply */ + tmp32 = L_shl(tmp32, sub(add(x_e, invGain_e), 15)); /* convert to 15Q16 */ + + test(); + IF ((GE_16(abs_s(xq[i]), 2))&&(tmp32>=0x3A000)) /* 0x3A000 -> 3.625 (15Q16) */ + { + + /* Debug initialization to catch illegal cases of xq[i] */ + tmp16 = 0; + + if (xq[i] > 0) + { + tmp16 = 2; + move16(); + } + if (xq[i] < 0) + { + tmp16 = -2; + move16(); + } + + assert(tmp16 != 0); + + xq[i] = add(xq[i], tmp16); + move16(); + + i_max = i; + move16(); + BREAK; + } + } + + s = sub(add(x_e, invGain_e), 15); + + /* 2. compress value range of all xq up to i_max: add two steps */ + FOR (i = 0; i < i_max; i++) + { + xq[i] = quantize(x[i], invGain, s, 0x6000); + move16(); + } + + /* 3. find first mag. maximum below i_max which is half as high */ + i_max_old = i_max; + move16(); + + IF (i_max_old >= 0) + { + invGain_e = add(invGain_e, 1); + i_max = -1; /* reset first maximum, update inverse gain */ move16(); + + FOR (i = 0; i < lg_4; i++) + { + tmp32 = Mpy_32_16_1(L_abs(x[i]), invGain); /* multiply */ + tmp32 = L_shl(tmp32, sub(add(x_e, invGain_e), 15)); /* convert to 15Q16 */ + + test(); + IF ((GE_16(abs_s(xq[i]), 2))&&(tmp32>=0x3A000)) /* 0x3A000 -> 3.625 (15Q16) */ + { + + /* Debug initialization to catch illegal cases of xq[i] */ + tmp16 = 0; + + if (xq[i] > 0) + { + tmp16 = 2; + move16(); + } + if (xq[i] < 0) + { + tmp16 = -2; + move16(); + } + + assert(tmp16 != 0); + + xq[i] = add(xq[i], tmp16); + move16(); + + i_max = i; + move16(); + BREAK; + } + } + } + + s = sub(add(x_e, invGain_e), 15); + + /* 4. re-compress and quantize all xq up to half-height i_max+1 */ + FOR (i = 0; i < i_max; i++) + { + xq[i] = quantize(x[i], invGain, s, 0x6000); + move16(); + } + + /* 5. always compress 2 lines; lines could be at index 0 and 1! */ + IF (i_max_old >= 0) + { + invGain_e = sub(invGain_e, 1); /* reset inverse gain */ + if (LT_16(i_max, i_max_old)) + { + i_max = i_max_old; + move16(); + } + } + + i = add(i_max, 1); + + tmp32 = Mpy_32_16_1(L_abs(x[i]), invGain); /* multiply */ + tmp32 = L_shl(tmp32, sub(add(x_e, invGain_e), 15)); /* convert to 15Q16 */ + IF (GE_32(tmp32, 0x3A000)) + { + + /* Debug initialization to catch illegal cases of xq[i] */ + tmp16 = 0; + + if (xq[i] > 0) + { + tmp16 = 2; + move16(); + } + if (xq[i] < 0) + { + tmp16 = -2; + move16(); + } + + assert(tmp16 != 0); + + xq[i] = add(xq[i], tmp16); + move16(); + } + ELSE + { + xq[i] = quantize(x[i], invGain, sub(add(x_e, invGain_e), 15), 0x6000); + move16(); + } + + i = add(i, 1); + + tmp32 = Mpy_32_16_1(L_abs(x[i]), invGain); /* multiply */ + tmp32 = L_shl(tmp32, sub(add(x_e, invGain_e), 15)); /* convert to 15Q16 */ + IF (GE_32(tmp32, 0x3A000)) + { + + /* Debug initialization to catch illegal cases of xq[i] */ + tmp16 = 0; + + if (xq[i] > 0) + { + tmp16 = 2; + move16(); + } + if (xq[i] < 0) + { + tmp16 = -2; + move16(); + } + + assert(tmp16 != 0); + + xq[i] = add(xq[i], tmp16); + move16(); + } + ELSE + { + xq[i] = quantize(x[i], invGain, sub(add(x_e, invGain_e), 15), 0x6000); + move16(); + } + + + } + ELSE /*if(!tcx_lpc_shaped_ari)*/ + { + PsychAdaptLowFreqEmph(x, lpcGains, lpcGains_e); + }/*if(!tcx_lpc_shaped_ari)*/ + +} + +void PsychAdaptLowFreqEmph(Word32 x[], + const Word16 lpcGains[], const Word16 lpcGains_e[] + ) +{ + Word16 i; + Word16 max, max_e, fac, min, min_e, tmp, tmp_e; + Word32 L_tmp; + + + + assert(lpcGains[0] >= 0x4000); + + max = lpcGains[0]; + move16(); + max_e = lpcGains_e[0]; + move16(); + min = lpcGains[0]; + move16(); + min_e = lpcGains_e[0]; + move16(); + + /* find minimum (min) and maximum (max) of LPC gains in low frequencies */ + FOR (i = 1; i < 9; i++) + { + IF (compMantExp16Unorm(lpcGains[i], lpcGains_e[i], min, min_e) < 0) + { + min = lpcGains[i]; + move16(); + min_e = lpcGains_e[i]; + move16(); + } + + IF (compMantExp16Unorm(lpcGains[i], lpcGains_e[i], max, max_e) > 0) + { + max = lpcGains[i]; + move16(); + max_e = lpcGains_e[i]; + move16(); + } + } + + min_e = add(min_e, 5); /* min *= 32.0f; */ + + test(); + IF ((compMantExp16Unorm(max, max_e, min, min_e) < 0) && (max > 0)) + { + /* fac = tmp = (float)pow(min / max, 0.0078125f); */ + tmp_e = max_e; + move16(); + tmp = Inv16(max, &tmp_e); + L_tmp = L_shl(L_mult(tmp, min), sub(add(tmp_e, min_e), 6)); /* Q25 */ + L_tmp = L_add(BASOP_Util_Log2(L_tmp), 6<<25); /* Q25 */ + L_tmp = L_shr(L_tmp, 7); /* 0.0078125f = 1.f/(1<<7) */ + L_tmp = BASOP_Util_InvLog2(L_sub(L_tmp, 1<<25)); /* Q30 */ + tmp = round_fx(L_tmp); /* Q14 */ + fac = shr(tmp, 1); /* Q13 */ + + /* gradual boosting of lowest 32 bins; DC is boosted by (min/max)^1/4 */ + FOR (i = 31; i >= 0; i--) + { + x[i] = L_shl(Mpy_32_16_1(x[i], fac), 2); + move32(); + fac = shl(mult_r(fac, tmp), 1); + } + } + +} + +Word16 SQ_gain( /* output: SQ gain */ + Word32 x[], /* input: vector to quantize */ + Word16 x_e, /* input: exponent */ + Word16 nbitsSQ, /* input: number of bits targeted */ + Word16 lg, /* input: vector size (2048 max) */ + Word16 *gain_e) /* output: SQ gain exponent */ +{ + Word16 i, iter, lg_4, s, tmp16; + Word32 ener, tmp32; + Word32 target, fac, offset; + Word32 en[N_MAX/4]; + + + lg_4 = shr(lg, 2); + + /* energy of quadruples with 9dB offset */ + FOR (i=0; i 0.15*log2(10) */ + fac = L_add(0x2A854B, 0); /* -> 12.8f*log2(10); */ + offset = L_add(fac, 0); + + /* find offset (0 to 128 dB with step of 0.125dB) */ + FOR (iter=0; iter<10; iter++) + { + fac = L_shr(fac, 1); + offset = L_sub(offset, fac); + ener = L_deposit_l(0); + + FOR (i=0; i 0.3*log2(10); */ + { + ener = L_add(ener, tmp32); + } + + /* if ener is above target -> break and increase offset */ + IF (GT_32(ener, target)) + { + offset = L_add(offset, fac); + BREAK; + } + } + } + + offset = L_add(L_shr(offset, 1), 0x17EB0); /* 0x17EB0 -> 0.45*log2(10) */ + + *gain_e = add(extract_h(offset), 1); + move16(); + offset = L_sub(L_and(offset, 0xFFFF), 0x10000); + tmp16 = extract_h(BASOP_Util_InvLog2(L_shl(offset, 9))); + + /* return gain */ + + return tmp16; +} + +void tcx_scalar_quantization( + Word32 *x, /* i: input coefficients */ + Word16 x_e, /* i: exponent */ + Word16 *xq, /* o: quantized coefficients */ + Word16 L_frame, /* i: frame length */ + Word16 gain, /* i: quantization gain */ + Word16 gain_e, /* i: quantization gain exponent */ + Word16 offset, /* i: rounding offset (deadzone) */ + Word8 const *memQuantZeros, /* i: coefficients to be set to 0 */ + const Word16 alfe_flag +) +{ + Word16 i, tmp16, s; + Word32 tmp32, offs32; + + + /* common exponent for x and gain for comparison */ + tmp16 = sub(gain_e, x_e); + tmp32 = L_shl(L_deposit_h(gain), s_max(-31, s_min(tmp16, 0))); + tmp16 = negate(s_max(tmp16, 0)); + + i = sub(L_frame, 1); + WHILE ((memQuantZeros[i] != 0) && (LT_32(L_abs(L_shl(x[i], tmp16)), tmp32))) + { + test(); + xq[i] = 0; + move16(); + i = sub(i, 1); + } + + /* invert gain */ + gain = Inv16(gain, &gain_e); + + s = sub(add(x_e, gain_e), 15); + + /*It should almost never happen and if so the quantization will be discarded later on (saturation of gain Quantizer).*/ + IF( GT_16(s,31)) + { + /* Limit the inverse gain to maximal possible value=sqrtL_spec/NORM_MDCT_FACTOR)*/ + gain = 22435; /*sqrt(1200/NORM_MDCT_FACTOR) in 2Q13*/ + gain_e = 2; + + s = sub(add(x_e, gain_e), 15); + } + + /* substract 0x8000 to affect the mac_r in the following loop + so it acts like extract_h. the 0x4000 will be multiplied by 2 + by the mac_r to get to 0x8000 and disable the round. */ + offset = sub(offset, 0x4000); + + FOR (; i >= 0; i--) + { + offs32 = Mpy_32_16_1(L_abs(x[i]), gain); /* multiply */ + offs32 = L_shl(offs32, s); /* convert to 15Q16 */ + tmp16 = mac_r(offs32, offset, 1); /* add offset and truncate */ + if (x[i] < 0) tmp16 = negate(tmp16); /* restore sign */ + + xq[i] = tmp16; + move16(); + } + + IF (alfe_flag == 0) + { + AdaptLowFreqEmph(x, x_e, xq, gain, gain_e, + 0, NULL, NULL, + L_frame + ); + } + +} + +Word16 tcx_scalar_quantization_rateloop( + Word32 *x, /* i : input coefficients */ + Word16 x_e, /* i : exponent */ + Word16 *xq, /* o : quantized coefficients */ + Word16 L_frame, /* i : frame length */ + Word16 *gain, /* i/o: quantization gain */ + Word16 *gain_e, /* i/o: gain exponent */ + Word16 offset, /* i : rounding offset (deadzone) */ + Word8 const*memQuantZeros, /* i : coefficients to be set to 0 */ + Word16 *lastnz_out, /* i/o: last nonzero coeff index */ + Word16 target, /* i : target number of bits */ + Word16 *nEncoded, /* o : number of encoded coeff */ + Word16 *stop, /* i/o: stop param */ + Word16 sqBits_in_noStop, /* i : number of sqBits as determined in prev. quant. stage, w/o using stop mechanism (ie might exceed target bits) */ + Word16 sqBits_in, /* i : number of sqBits as determined in prev. quant. stage, using stop mechanism (ie always <= target bits) */ + Word16 tcxRateLoopOpt, /* i : turns on/off rateloop optimization */ + const Word8 tcxonly, + CONTEXT_HM_CONFIG *hm_cfg /* i : configuration of the context-based harmonic model */ +) +{ + const Word16 iter_max = 4; + Word16 sqBits; + Word16 stopFlag; + Word8 ubfound,lbfound; + Word16 ub, ub_e, lb, lb_e; + Word16 shift, shiftInv; + Word16 iter; + Word16 sqGain, sqGain_e; + Word16 w_lb, w_ub; + const Word16 kDampen = 10; + Word16 old_stopFlag; + Word16 old_nEncoded; + Word16 old_sqBits; + Word16 mod_adjust0, mod_adjust1; + Word16 inv_target, inv_target_e; + const Word16 kMargin = 0x7AE1; /* 0.96 */ + const Word16 kMarginInv = 0x42AB; /* 1/0.96 (1Q14) */ + Word16 tmp, fac1, fac2; + Word32 tmp32; + Word16 lastnz; + + + + /* Init */ + sqGain = *gain; + move16(); + sqGain_e = *gain_e; + move16(); + stopFlag = *stop; + move16(); + ubfound = 0; + move16(); + lbfound = 0; + move16(); + shift = 0x41DE; /* 10^(1/80), 1Q14 */ move16(); + shiftInv = 0x78D7; /* 10^(-1/40) */ move16(); + lb = lb_e = 0; + move16(); + ub = ub_e = 0; + move16(); + w_lb = 0; + move16(); + w_ub = 0; + move16(); + lastnz = *lastnz_out; + move16(); + old_stopFlag = stopFlag; + move16(); + old_nEncoded = *nEncoded; + move16(); + old_sqBits = sqBits_in_noStop; + move16(); + + sqBits = sqBits_in; + move16(); + + mod_adjust0 = extract_l(L_shr(L_max(0x10000, L_sub(0x24CCD, L_mult(0x0052, target))), 3)); /* 2Q13 */ + mod_adjust1 = div_s(0x2000, mod_adjust0); /* 0Q15 */ + + inv_target_e = 15; + move16(); + inv_target = Inv16(target, &inv_target_e); + + fac1 = shl(mult(mult(kMarginInv, mod_adjust0), inv_target), 1); /* 2Q13 */ + fac2 = mult(mult(kMargin, mod_adjust1), inv_target); + + /* Loop */ + FOR ( iter=0 ; iter 0) + { + stopFlag = 0; + move16(); + } + + sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC( xq, L_frame, + &lastnz, + nEncoded, target, &stopFlag, + hm_cfg + ); + + IF ( tcxRateLoopOpt > 0 ) + { + test(); + test(); + test(); + test(); + test(); + test(); + IF ( ((GE_16(*nEncoded, old_nEncoded))&&(GE_16(stopFlag,old_stopFlag)))|| + ((GT_16(*nEncoded, old_nEncoded) ) && ((stopFlag == 0) && (old_stopFlag > 0))) || + ((stopFlag == 0) && (old_stopFlag == 0)) ) + { + *gain = sqGain; + move16(); + *gain_e = sqGain_e; + move16(); + old_nEncoded = *nEncoded; + move16(); + old_stopFlag = stopFlag; + move16(); + old_sqBits = sqBits; + move16(); + *lastnz_out = lastnz; + move16(); + } + } + } /* for ( iter=0 ; iter 0 ) + { + /* Quantize spectrum */ + tcx_scalar_quantization( x, x_e, xq, L_frame, *gain, *gain_e, offset, memQuantZeros, tcxonly ); + + /* Output */ + *nEncoded = old_nEncoded; + move16(); + sqBits = old_sqBits; + move16(); + *stop = old_stopFlag; + move16(); + } + ELSE + { + /* Output */ + *gain = sqGain; + move16(); + *gain_e = sqGain_e; + move16(); + *stop = stopFlag; + move16(); + *lastnz_out = lastnz; + move16(); + } + + + return sqBits; +} + +void QuantizeGain(Word16 n, Word16 *pGain, Word16 *pGain_e, Word16 *pQuantizedGain) +{ + Word16 ener, ener_e, enerInv, enerInv_e, gain, gain_e; + Word16 quantizedGain; + Word32 tmp32; + + + ener = mult_r(shl(n, 5), 26214/*128.f/NORM_MDCT_FACTOR Q15*/); + ener_e = 15-5-7; + move16(); + IF( n >= 1024 ) + { + /*reduce precision for avoiding overflow*/ + ener = mult_r(shl(n, 4), 26214/*128.f/NORM_MDCT_FACTOR Q15*/); + ener_e = 15-4-7; + } + BASOP_Util_Sqrt_InvSqrt_MantExp(ener, ener_e, &ener, &ener_e, &enerInv, &enerInv_e); + + gain = mult(*pGain, ener); + gain_e = *pGain_e + ener_e; + + assert(gain > 0); + + /* quantize gain with step of 0.714 dB */ + quantizedGain = add(round_fx(BASOP_Util_Log2(L_deposit_h(gain))), shl(gain_e, 9)); /* 6Q9 */ + quantizedGain = mult(quantizedGain, 0x436E); /* 10Q5; 0x436E -> 28/log2(10) (4Q11) */ + quantizedGain = shr(add(quantizedGain, 0x10), 5); /* round */ + + if (quantizedGain < 0) + { + quantizedGain = 0; + move16(); + } + + if (quantizedGain > 127) + { + quantizedGain = 127; + move16(); + } + + *pQuantizedGain = quantizedGain; + move16(); + + tmp32 = L_shl(L_mult0(quantizedGain, 0x797D), 7); /* 6Q25; 0x797D -> log2(10)/28 (Q18) */ + gain_e = add(extract_l(L_shr(tmp32, 25)), 1); /* get exponent */ + gain = round_fx(BASOP_Util_InvLog2(L_or(tmp32, 0xFE000000))); + + *pGain = mult(gain, enerInv); + move16(); + *pGain_e = add(gain_e, enerInv_e); + move16(); + +} + +void tcx_noise_factor( + Word32 *x_orig, /* i: unquantized mdct coefficients */ + Word16 x_orig_e, /* i: exponent */ + Word32 *sqQ, /* i: quantized mdct coefficients */ + Word16 iFirstLine, /* i: first coefficient to be considered */ + Word16 lowpassLine, /* i: last nonzero coefficients after low-pass */ + Word16 nTransWidth, /* i: minimum size of hole to be checked */ + Word16 L_frame, /* i: frame length */ + Word16 gain_tcx, /* i: tcx gain */ + Word16 gain_tcx_e, /* i: gain exponent */ + Word16 tiltCompFactor, /* i: LPC tilt compensation factor */ + Word16 *fac_ns, /* o: noise factor */ + Word16 *quantized_fac_ns/* o: quantized noise factor */ +) +{ + Word16 i, k, maxK, segmentOffset; + Word32 sqErrorNrg, n; + Word16 inv_gain2, inv_gain2_e, tilt_factor, nTransWidth_1; + Word32 accu1, accu2, tmp32; + Word16 tmp1, tmp2, s; + Word16 c1, c2; + Word16 att; /* noise level attenuation factor for transient windows */ + Word32 xMax; + + + assert(nTransWidth <= 16); + + c1 = sub(shl(nTransWidth, 1), 4); + c2 = mult(9216/*0.28125f Q15*/, inv_int[nTransWidth]); + nTransWidth_1 = sub(nTransWidth, 1); + + /*Adjust noise filling level*/ + sqErrorNrg = L_deposit_l(0); + n = L_deposit_l(0); + + /* get inverse frame length */ + tmp1 = getInvFrameLen(L_frame); + + /* tilt_factor = 1.0f /(float)pow(max(0.375f, tiltCompFactor), 1.0f/(float)L_frame); */ + tmp32 = BASOP_Util_Log2(L_deposit_h(s_max(0x3000, tiltCompFactor))); /* 6Q25 */ + tmp32 = L_shr(Mpy_32_16_1(tmp32, negate(tmp1)), 6); + tilt_factor = round_fx(BASOP_Util_InvLog2(L_sub(tmp32, 0x2000000))); /* 1Q14 */ + + /* inv_gain2 = 1.0f / ((float)(nTransWidth * nTransWidth) * gain_tcx); */ + tmp32 = L_mult(imult1616(nTransWidth, nTransWidth), gain_tcx); /* 15Q16 */ + tmp1 = norm_l(tmp32); + inv_gain2 = round_fx(L_shl(tmp32, tmp1)); + inv_gain2_e = add(sub(15, tmp1), gain_tcx_e); + inv_gain2 = Inv16(inv_gain2, &inv_gain2_e); + inv_gain2 = shr(inv_gain2, 2); /* 2 bits headroom */ + inv_gain2_e = add(inv_gain2_e, 2); + + /* find last nonzero line below iFirstLine, use it as start offset */ + tmp1 = shr(iFirstLine, 1); + FOR (i = iFirstLine; i > tmp1; i--) + { + IF (sqQ[i] != 0) + { + BREAK; + } + } + /* inv_gain2 *= (float)pow(tilt_factor, (float)i); */ + FOR (k = 0; k < i; k++) + { + inv_gain2 = shl(mult(inv_gain2, tilt_factor), 1); + } + + /* initialize left (k) and right (maxK) non-zero neighbor pointers */ + k = 0; + move16(); + FOR (maxK = 1; maxK < nTransWidth; maxK++) + { + IF (sqQ[i+maxK] != 0) + { + BREAK; + } + } + i = add(i, 1); + segmentOffset = i; + move16(); + + IF (LE_16(nTransWidth, 3)) + { + accu1 = L_deposit_l(0); + accu2 = L_deposit_l(0); + xMax = L_deposit_l(0); + + FOR (k = s_and(i, (Word16)0xFFFE); k < lowpassLine; k++) + { + xMax = L_max(xMax, L_abs(x_orig[k])); + } + s = sub(norm_l(xMax), 4); + + FOR (k = s_and(i, (Word16)0xFFFE); k < lowpassLine; k += 2) + { + /* even-index bins, left sub-win */ + tmp1 = round_fx(L_shl(x_orig[k], s)); + accu1 = L_mac0(accu1, tmp1, tmp1); + + /* odd-index bins, right sub-win */ + tmp1 = round_fx(L_shl(x_orig[k+1], s)); + accu2 = L_mac0(accu2, tmp1, tmp1); + } + k = 0; + move16(); + + if (accu1 == 0) accu1 = L_deposit_l(1); + if (accu2 == 0) accu2 = L_deposit_l(1); + + att = BASOP_Util_Divide3232_Scale( L_shl(L_min(accu1, accu2), 1), L_add(accu1, accu2), &s ); + att = Sqrt16(att, &s); + BASOP_SATURATE_WARNING_OFF; /* att is always <= 1.0 */ + att = shl(att, s); + BASOP_SATURATE_WARNING_ON; + } + ELSE + { + att = 0x7FFF; + move16(); + } + + accu1 = L_deposit_l(0); + + tmp1 = sub(lowpassLine, nTransWidth); + FOR (; i <= tmp1; i++) + { + inv_gain2 = shl(mult(inv_gain2, tilt_factor), 1); + + IF (EQ_16(maxK, 1)) /* current line is not zero, so reset pointers */ + { + k = sub(i, segmentOffset); + + IF (k > 0) /* add segment sum to sum of segment magnitudes */ + { + IF (LE_16(nTransWidth, 3)) + { + tmp2 = sub(k, c1); + if (tmp2 > 0) n = L_msu(n, k, (Word16)0x8000); + if (tmp2 > 0) n = L_mac(n, nTransWidth_1, (Word16)0x8000); + if (tmp2 <= 0) n = L_mac(n, int_sqr[k], c2); + } + ELSE + { + tmp2 = sub(k, 12); + if (tmp2 > 0) n = L_msu(n, k, (Word16)0x8000); + if (tmp2 > 0) n = L_sub(n, 0x70000); + if (tmp2 <= 0) n = L_mac(n, int_sqr[k], 1152/*0.03515625f Q15*/); + } + sqErrorNrg = L_add(sqErrorNrg, accu1); + accu1 = L_deposit_l(0); /* segment ended here, so reset segment sum */ + k = 0; + move16(); + } + + FOR (; maxK < nTransWidth; maxK++) + { + IF (sqQ[i+maxK] != 0) + { + BREAK; + } + } + segmentOffset = add(i, 1); /* new segment might start at next line */ + } + ELSE /* current line is zero, so update pointers & segment sum */ + { + if (LT_16(k, nTransWidth)) + { + k = add(k, 1); + } + + tmp2 = sub(maxK, nTransWidth); + if (tmp2 < 0) + { + maxK = sub(maxK, 1); + } + + test(); + if ((tmp2 >= 0) && (sqQ[i+sub(nTransWidth, 1)] != 0)) + { + maxK = sub(nTransWidth, 1); + } + + /* update segment sum: magnitudes scaled by smoothing function */ + /*accu1 += (float)fabs(x_orig[i]) * inv_gain2 * (float)(k * maxK);*/ + tmp2 = mult(inv_gain2, shl(imult1616(k, maxK), 8)); + accu1 = L_add(accu1, L_abs(Mpy_32_16_1(x_orig[i], tmp2))); + } + } + + FOR (; i < lowpassLine; i++) + { + inv_gain2 = shl(mult(inv_gain2, tilt_factor), 1); + + IF (EQ_16(maxK, 1)) /* current line is not zero, so reset pointers */ + { + k = sub(i, segmentOffset); + + IF (k > 0) /* add segment sum to sum of segment magnitudes */ + { + IF (LE_16(nTransWidth, 3)) + { + tmp2 = sub(k, c1); + if (tmp2 > 0) n = L_msu(n, k, (Word16)0x8000); + if (tmp2 > 0) n = L_mac(n, nTransWidth_1, (Word16)0x8000); + if (tmp2 <= 0) n = L_mac(n, int_sqr[k], c2); + } + ELSE + { + tmp2 = sub(k, 12); + if (tmp2 > 0) n = L_msu(n, k, (Word16)0x8000); + if (tmp2 > 0) n = L_sub(n, 0x70000); + if (tmp2 <= 0) n = L_mac(n, int_sqr[k], 1152/*0.03515625f Q15*/); + } + sqErrorNrg = L_add(sqErrorNrg, accu1); + } + segmentOffset = add(i, 1); /* no new segments since maxK remains 1 */ + } + ELSE /* current line is zero, so update pointers & energy sum */ + { + if (LT_16(k, nTransWidth)) + { + k = add(k, 1); + } + if (LT_16(maxK, nTransWidth)) + { + maxK = sub(maxK, 1); + } + + /* update segment sum: magnitudes scaled by smoothing function */ + /*accu1 += (float)fabs(x_orig[i]) * inv_gain2 * (float)(k * maxK);*/ + tmp2 = mult(inv_gain2, shl(imult1616(k, maxK), 8)); + accu1 = L_add(accu1, L_abs(Mpy_32_16_1(x_orig[i], tmp2))); + } + } + + k = sub(i, segmentOffset); + IF (k > 0) /* add last segment sum to sum of segment magnitudes */ + { + IF (LE_16(nTransWidth, 3)) + { + tmp2 = sub(k, c1); + if (tmp2 > 0) n = L_msu(n, k, (Word16)0x8000); + if (tmp2 > 0) n = L_mac(n, nTransWidth_1, (Word16)0x8000); + if (tmp2 <= 0) n = L_mac(n, int_sqr[k], c2); + } + ELSE + { + tmp2 = sub(k, 12); + if (tmp2 > 0) n = L_msu(n, k, (Word16)0x8000); + if (tmp2 > 0) n = L_sub(n, 0x70000); + if (tmp2 <= 0) n = L_mac(n, int_sqr[k], 1152/*0.03515625f Q15*/); + } + sqErrorNrg = L_add(sqErrorNrg, accu1); + } + + /* noise level factor: average of segment magnitudes of noise bins */ + IF (n > 0) + { + tmp1 = BASOP_Util_Divide3232_Scale(Mpy_32_16_1(sqErrorNrg, att), n, &s); + s = add(add(add(s, x_orig_e), inv_gain2_e), 7 - 15); + BASOP_SATURATE_WARNING_OFF; + tmp1 = shl(tmp1, s); + BASOP_SATURATE_WARNING_ON; + } + ELSE + { + tmp1 = 0; + move16(); + } + + /* quantize, dequantize noise level factor (range 0.09375 - 0.65625) */ + tmp2 = round_fx(L_shr(L_mult(tmp1, 22016/*1.34375f Q14*/), 14-NBITS_NOISE_FILL_LEVEL)); + + if (GT_16(tmp2, (1<syn, buf, M+1); + + Copy(xn_buf, synth, L_frame_glob); + Copy(synth + sub(L_frame_glob, M+1), LPDmem->syn, M+1); + + IF (st->tcxonly == 0) + { + /* Update weighted synthesis */ + Residu3_fx(Ai+(st->nb_subfr-1)*(M+1), synth + sub(L_frame_glob, 1), &tmp, 1, Q_new+shift-1); + LPDmem->mem_w0 =sub(wsig[sub(L_frame_glob, 1)], tmp); + move16(); + LPDmem->mem_w0 =shr(LPDmem->mem_w0, shift); /*Qnew-1*/ + } + + + /* Emphasis of synth -> synth_pe */ + tmp = synth[-(M+1)]; + move16(); + E_UTIL_f_preemph2(Q_new-1, synth - M, preemph, add(M, L_frame_glob), &tmp); + + Copy(synth + sub(L_frame_glob, M), LPDmem->mem_syn, M); + Copy(synth + sub(L_frame_glob, M), LPDmem->mem_syn2, M); + Copy(synth + sub(L_frame_glob, L_SYN_MEM), LPDmem->mem_syn_r, L_SYN_MEM); + + test(); + IF (st->tcxonly == 0 || LE_16(L_frame_glob,L_FRAME16k)) + { + /* Update excitation */ + IF (LT_16(L_frame_glob, L_EXC_MEM)) + { + Copy( LPDmem->old_exc + L_frame_glob, LPDmem->old_exc, sub(L_EXC_MEM, L_frame_glob) ); + Residu3_fx(A, synth, LPDmem->old_exc + sub(L_EXC_MEM, L_frame_glob), L_frame_glob, 1); + } + ELSE + { + Residu3_fx(A, synth + sub(L_frame_glob, L_EXC_MEM), LPDmem->old_exc, L_EXC_MEM, 1); + } + + } + +} + + +/*--------------------------------------------------------------- + * Residual Quantization + *--------------------------------------------------------------*/ + +/* Returns: number of bits used (including "bits") Q0 */ +Word16 tcx_ari_res_Q_spec( + const Word32 x_orig[], /* i: original spectrum Q31-e */ + Word16 x_orig_e, /* i: original spectrum exponent Q0 */ + const Word16 signs[], /* i: signs (x_orig[.]<0) Q0 */ + Word32 x_Q[], /* i/o: quantized spectrum Q31-e */ + Word16 x_Q_e, /* i: quantized spectrum exponent Q0 */ + Word16 L_frame, /* i: number of lines Q0 */ + Word16 gain, /* i: TCX gain Q15-e */ + Word16 gain_e, /* i: TCX gain exponent Q0 */ + Word16 prm[], /* o: bit-stream Q0 */ + Word16 target_bits, /* i: number of bits available Q0 */ + Word16 bits, /* i: number of bits used so far Q0 */ + Word16 deadzone, /* i: quantizer deadzone Q15 */ + const Word16 x_fac[] /* i: spectrum post-quantization factors Q14 */ +) +{ + Word16 i, j, num_zeros; + Word16 zeros[L_FRAME_PLUS]; + Word16 fac_p, sign; + Word32 thres, x_Q_m, x_Q_p; + Word32 L_tmp, L_tmp2; + Word16 s, s2; + + + /* Limit the number of residual bits */ + target_bits = s_min(target_bits, NPRM_RESQ); + + + /* Requantize the spectrum line-by-line */ + /* fac_m = deadzone * 0.5f; + fac_p = 0.5f - fac_m; */ + num_zeros = 0; + move16(); + + s = sub(add(gain_e, x_Q_e), x_orig_e); + FOR (i=0; i < L_frame; i++) + { + IF (GE_16(bits, target_bits)) /* no bits left */ + { + BREAK; + } + + IF (x_Q[i] != 0) + { + sign = x_fac[i]; + move16(); + if (signs[i] != 0) sign = negate(sign); + + /* x_Q_m = x_Q[i] - sign*fac_m; + x_Q_p = x_Q[i] + sign*fac_p; */ + + L_tmp = L_mult(sign, deadzone); /* sign*deadzone/2 in Q31 */ + x_Q_m = L_sub(x_Q[i], L_shr(L_tmp, x_Q_e)); + + L_tmp = L_mac(L_tmp, sign, (Word16)0x8000); /* sign*(deadzone-1)/2 in Q31 */ + x_Q_p = L_sub(x_Q[i], L_shr(L_tmp, x_Q_e)); + + /* if (fabs(x_orig[i] - gain * x_Q_m) < fabs(x_orig[i] - gain * x_Q_p)) */ + L_tmp = L_abs(L_sub(x_orig[i], L_shl(Mpy_32_16_1(x_Q_m, gain), s))); + L_tmp2 = L_abs(L_sub(x_orig[i], L_shl(Mpy_32_16_1(x_Q_p, gain), s))); + + IF (LT_32(L_tmp, L_tmp2)) /* Decrease magnitude */ + { + x_Q[i] = x_Q_m; + move32(); + prm[bits] = 0; + move16(); + } + ELSE /* Increase magnitude */ + { + x_Q[i] = x_Q_p; + move32(); + prm[bits] = 1; + move16(); + } + bits = add(bits, 1); + } + ELSE + { + zeros[num_zeros] = i; + move16(); + num_zeros = add(num_zeros, 1); + } + } + + /* Requantize zeroed-lines of the spectrum */ + fac_p = msu_r(1417339264l/*2*0.33f Q31*/, deadzone, 21627/*2*0.33f Q15*/); /* Q16 */ + target_bits = sub(target_bits, 1); /* reserve 1 bit for the check below */ + + s = sub(gain_e, x_orig_e); + s2 = sub(x_Q_e, 1); + FOR (j = 0; j < num_zeros; j++) + { + IF (GE_16(bits, target_bits)) /* 1 or 0 bits left */ + { + BREAK; + } + + i = zeros[j]; + move16(); + + thres = L_mult(fac_p, x_fac[i]); /* Q31 */ + + IF (GT_32(L_abs(x_orig[i]), L_shl(Mpy_32_16_1(thres, gain), s))) + { + prm[bits] = 1; + move16(); + bits = add(bits, 1); + + prm[bits] = sub(1, signs[i]); + move16(); + bits = add(bits, 1); + + L_tmp = L_shr(thres, s2); + if (signs[i]) L_tmp = L_negate(L_tmp); + x_Q[i] = L_tmp; + move32(); + } + ELSE + { + prm[bits] = 0; + move16(); + bits = add(bits, 1); + } + } + + + return bits; +} + +#define kMaxEstimatorOvershoot 5 +#define kMaxEstimatorUndershoot 0 + +Word16 tcx_res_Q_gain( + Word16 sqGain, + Word16 sqGain_e, + Word16 *gain_tcx, + Word16 *gain_tcx_e, + Word16 *prm, + Word16 sqTargetBits +) +{ + Word16 bits; + Word16 gain_reQ, gain_reQ_e; + + /*Refine the gain quantization : Normal greedy gain coding */ + + gain_reQ = *gain_tcx; + move16(); + gain_reQ_e = *gain_tcx_e; + move16(); + + /* make sure we have a bit of headroom */ + IF (GT_16(gain_reQ, 0x7000)) + { + gain_reQ = shr(gain_reQ, 1); + gain_reQ_e = add(gain_reQ_e, 1); + } + + /* bring sqGain to same exponent */ + sqGain = shr(sqGain, sub(gain_reQ_e, sqGain_e)); + + FOR (bits=0; bits < TCX_RES_Q_BITS_GAIN; bits++) + { + IF (LT_16(sqGain, gain_reQ)) + { + prm[bits] = 0; + move16(); + gain_reQ = mult_r(gain_reQ, gain_corr_inv_fac[bits]); + } + ELSE + { + prm[bits] = 1; + move16(); + gain_reQ = shl(mult_r(gain_reQ, gain_corr_fac[bits]), 1); + } + + IF (LT_16(bits, sqTargetBits)) + { + *gain_tcx = gain_reQ; + move16(); + *gain_tcx_e = gain_reQ_e; + move16(); + } + } + + + return bits; +} + +Word16 tcx_res_Q_spec( + Word32 *x_orig, + Word16 x_orig_e, + Word32 *x_Q, + Word16 x_Q_e, + Word16 L_frame, + Word16 sqGain, + Word16 sqGain_e, + Word16 *prm, + Word16 sqTargetBits, + Word16 bits, + Word16 sq_round, + const Word16 lf_deemph_factors[] /* 1Q14 */ +) +{ + Word16 i; + Word16 fac_m, fac_p; + Word32 tmp1, tmp2; + Word16 s, s2, lf_deemph_factor; + Word16 c; + Word32 thres; + + + /* Limit the number of residual bits */ + sqTargetBits = s_min(sqTargetBits, NPRM_RESQ); + + /* Requantize the spectrum line-by-line */ + fac_m = shr(sq_round, 1); + fac_p = sub(0x4000, fac_m); + + /* exponent difference of x_orig and x_Q * sqGain */ + s = sub(x_orig_e, add(x_Q_e, sqGain_e)); + + lf_deemph_factor = 0x4000; + move16(); + s2 = sub(x_Q_e, 1); + + FOR (i = 0; i < L_frame; i++) + { + IF (GE_16(bits, sub(sqTargetBits, kMaxEstimatorUndershoot))) + { + fac_m = 0; + move16(); + fac_p = 0; + move16(); + + IF (GE_16(bits, s_min(NPRM_RESQ, add(sqTargetBits, kMaxEstimatorOvershoot)))) + { + BREAK; + } + } + + test(); + test(); + IF ((x_Q[i] != 0) && ((lf_deemph_factors == NULL) || (GT_16(lf_deemph_factors[i], 0x2000)))) + { + tmp1 = L_add(x_orig[i], 0); + tmp2 = Mpy_32_16_1(x_Q[i], sqGain); + if (s > 0) tmp2 = L_shr(tmp2, s); + if (s < 0) tmp1 = L_shl(tmp1, s); + + if (lf_deemph_factors != NULL) + { + lf_deemph_factor = lf_deemph_factors[i]; + move16(); + } + + IF (LT_32(tmp1, tmp2)) + { + prm[bits] = 0; + move16(); + bits = add(bits, 1); + + if (x_Q[i] > 0) tmp1 = L_mult(fac_m, lf_deemph_factor); + if (x_Q[i] < 0) tmp1 = L_mult(fac_p, lf_deemph_factor); + x_Q[i] = L_sub(x_Q[i], L_shr(tmp1, s2)); + move32(); + } + ELSE + { + prm[bits] = 1; + move16(); + bits = add(bits, 1); + + if (x_Q[i] > 0) tmp1 = L_mult(fac_p, lf_deemph_factor); + if (x_Q[i] < 0) tmp1 = L_mult(fac_m, lf_deemph_factor); + x_Q[i] = L_add(x_Q[i], L_shr(tmp1, s2)); + move32(); + } + } + } + + /*Quantize zeroed-line of the spectrum*/ + c = sub(21627/*0.66f Q15*/, mult_r(sq_round, 21627/*0.66f Q15*/)); + + FOR (i = 0; i < L_frame; i++) + { + IF (GE_16(bits, sub(sqTargetBits, 2))) + { + BREAK; + } + + test(); + test(); + IF ((x_Q[i] == 0) && ((lf_deemph_factors == NULL) || (GT_16(lf_deemph_factors[i], 0x2000)))) + { + if (lf_deemph_factors != NULL) + { + lf_deemph_factor = lf_deemph_factors[i]; + move16(); + } + + thres = L_mult(c, lf_deemph_factor); + tmp1 = L_shl(Mpy_32_16_1(thres, sqGain), sub(sqGain_e, x_orig_e)); + + IF (GT_32(x_orig[i], tmp1)) + { + prm[bits] = 1; + move16(); + bits = add(bits, 1); + + prm[bits] = 1; + move16(); + bits = add(bits, 1); + + x_Q[i] = L_shl(thres, sub(1, x_Q_e)); + move32(); + } + ELSE IF (L_add(x_orig[i], tmp1) < 0) + { + prm[bits] = 1; + move16(); + bits = add(bits, 1); + + prm[bits] = 0; + move16(); + bits = add(bits, 1); + + x_Q[i] = L_shl(L_negate(thres), sub(1, x_Q_e)); + move32(); + } + ELSE + { + prm[bits] = 0; + move16(); + bits = add(bits, 1); + } + } + } + + /*Be sure that every possible bits are initialized*/ + FOR (i = bits; i < NPRM_RESQ; i++) + { + prm[i] = 0; + move16(); + } + + + return bits; +} +void ProcessIGF( + IGF_ENC_INSTANCE_HANDLE const hInstance, /**< in: instance handle of IGF Encoder */ + Encoder_State_fx *st, /**< in: Encoder state */ + Word32 pMDCTSpectrum[], /**< in: MDCT spectrum */ + Word16 *pMDCTSpectrum_e, + Word32 pPowerSpectrum[], /**< in: MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 *pPowerSpectrum_e, + Word16 isTCX20, /**< in: flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + Word16 isTNSActive, /**< in: flag indicating if the TNS is active */ + Word16 isTransition, /**< in: flag indicating if the input is the transition from from ACELP to TCX20/TCX10 */ + Word16 frameno /**< in: flag indicating index of current subframe */ +) +{ + Word16 igfGridIdx; + Word16 isIndepFlag; + Word16 bsBits; + Word16 bsStart; + + + isIndepFlag = 1; + move16(); + test(); + IF (isTransition && isTCX20) + { + igfGridIdx = IGF_GRID_LB_TRAN; + move16(); + } + ELSE + { + IF (isTCX20) + { + igfGridIdx = IGF_GRID_LB_NORM; + move16(); + } + ELSE + { + /* It is short block */ + igfGridIdx = IGF_GRID_LB_SHORT; + move16(); + if (EQ_16(frameno, 1)) + { + isIndepFlag = 0; + move16(); + } + } + } + + + IGFEncApplyMono(hInstance, /**< in: instance handle of IGF Encoder */ + igfGridIdx, /**< in: IGF grid index */ + st, /**< in: Encoder state */ + pMDCTSpectrum, /**< in: MDCT spectrum */ + *pMDCTSpectrum_e, + pPowerSpectrum, /**< in: MDCT^2 + MDST^2 spectrum, or estimate */ + *pPowerSpectrum_e, + isTCX20, /**< in: flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + isTNSActive, /**< in: flag indicating if the TNS is active */ + (st->last_core_fx == ACELP_CORE) + ); + { + const Word32 tns_predictionGain = (&st->hIGFEnc)->tns_predictionGain; + const Word16 startLine = (&st->hIGFEnc)->infoStartLine; + const Word16 endLine = (&st->hIGFEnc)->infoStopLine; + const Word16 maxOrder = 8; + const Word32 *spec_before = (&st->hIGFEnc)->spec_be_igf; + Word16 curr_order = 0; + Word16 A[ITF_MAX_FILTER_ORDER+1]; + Word16 Q_A; + Word16 predictionGain = 0; + Word16 *flatteningTrigger = &(&st->hIGFEnc)->flatteningTrigger; + ITF_Detect_fx( spec_before, startLine, endLine, maxOrder, A, &Q_A, &predictionGain, &curr_order, shl((&st->hIGFEnc)->spec_be_igf_e, 1) ); + *flatteningTrigger = 0; + test(); + IF (LT_32(tns_predictionGain, 9646899l/*1.15 Q23*/)&& + LT_16(predictionGain, 147/*1.15 Q7*/)) + { + *flatteningTrigger = 1; + } + } + + bsStart = st->next_ind_fx; + move16(); + hInstance->infoTotalBitsPerFrameWritten = 0; + move16(); + IF (isTCX20) + { + IGFEncWriteBitstream(hInstance, + NULL, + &hInstance->infoTotalBitsPerFrameWritten, + igfGridIdx, + isIndepFlag); + } + ELSE + { + IGFEncWriteBitstream(hInstance, + st, + &hInstance->infoTotalBitsPerFrameWritten, + igfGridIdx, + isIndepFlag); + } + + bsBits = sub(st->next_ind_fx, bsStart); + IF (!isTCX20) + { + IGFEncConcatenateBitstream(hInstance, bsBits, &st->next_ind_fx, &st->nb_bits_tot_fx, st->ind_list_fx); + } + +} + +void attenuateNbSpectrum(Word16 L_frame, Word32 *spectrum) +{ + Word16 i, length, att; + + length = idiv1616U(L_frame, 20); + + att = 21627/*0.66f Q15*/; + move16(); + if (EQ_16(length, 8)) + { + att = 19661/*0.6f Q15*/; + move16(); + } + + spectrum += sub(L_frame, length); + FOR (i=0; i < length; i++) + { + spectrum[i] = Mpy_32_16_1(spectrum[i], att); + move32(); + att = mult_r(att, att); + } +} diff --git a/lib_enc/tfa_enc.c b/lib_enc/tfa_enc.c new file mode 100644 index 0000000..2c453af --- /dev/null +++ b/lib_enc/tfa_enc.c @@ -0,0 +1,104 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "stl.h" +#include "basop_util.h" +#include "cnst_fx.h" +#include "prot_fx.h" + + +void tfaCalcEnv_fx(const Word16* shb_speech, Word32* enr) +{ + Word16 i, j, k; + + k = 0; + move16(); + FOR (i=0; i +#include +#include "rom_com_fx.h" + +#define HLM_MIN_NRG (32768.0f * 2*NORM_MDCT_FACTOR / (640*640)) + +/** Get TNS filter parameters from autocorrelation. + * + * @param rxx Autocorrelation function/coefficients. + * @param maxOrder Maximum filter order/number of coefficients. + * @param pTnsFilter Pointer to the output filter. + */ +static void GetFilterParameters(Word32 rxx[], Word16 maxOrder, STnsFilter * pTnsFilter); + +/** Quantization for reflection coefficients. + * + * @param parCoeff input reflection coefficients. + * @param index output quantized values. + * @param order number of coefficients/values. + */ +static void Parcor2Index(Word16 const parCoeff[], Word16 index[], Word16 order); + +/** Linear prediction analysis/synthesis filter definition. + * @param order filter order. + * @param parCoeff filter (PARCOR) coefficients. + * @param state state of the filter. Must be at least of 'order' size. + * @param x the current input value. + * @return the output of the filter. + */ +typedef Word32 (* TLinearPredictionFilter)(Word16 order, Word16 const parCoeff[], Word32 * state, Word32 x); + + +/********************************/ +/* Interface functions */ +/********************************/ + +#define MAX_SUBDIVISIONS 3 + +Word16 DetectTnsFilt(STnsConfig const * pTnsConfig, + Word32 const pSpectrum[], + STnsData * pTnsData, + Word16 *predictionGain) +{ + Word16 facs[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS]; + Word16 facs_e[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS]; /* exponents of facs[][] */ + Word16 shifts[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS]; + Word16 iFilter = 0; + + ResetTnsData(pTnsData); + + IF (pTnsConfig->maxOrder <= 0) + { + return 0; + } + + /* Calculate norms for each spectrum part */ + FOR (iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++) + { + Word16 idx0; + Word16 idx1; + Word16 nSubdivisions; + Word16 iSubdivisions; + + move16(); + move16(); + move16(); + idx0 = pTnsConfig->iFilterBorders[iFilter+1]; + idx1 = pTnsConfig->iFilterBorders[iFilter]; + nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions; + + assert(pTnsConfig->pTnsParameters[iFilter].nSubdivisions <= MAX_SUBDIVISIONS); + + FOR (iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++) + { + Word16 iStartLine; + Word16 iEndLine; + Word16 tmp, headroom, shift; + Word32 L_tmp, tmp32; + + /* iStartLine = idx0 + (idx1-idx0)*iSubdivisions/nSubdivisions; + iEndLine = idx0 + (idx1-idx0)*(iSubdivisions+1)/nSubdivisions; */ + assert((nSubdivisions == 1) || (nSubdivisions == 3)); + + tmp = sub(idx1, idx0); + iStartLine = imult1616(tmp, iSubdivisions); + iEndLine = add(iStartLine, tmp); + + if (EQ_16(nSubdivisions, 3))iStartLine=mult(iStartLine,0x2AAB); + iStartLine = add(iStartLine, idx0); + + if (EQ_16(nSubdivisions, 3))iEndLine=mult(iEndLine,0x2AAB); + iEndLine = add(iEndLine, idx0); + + /*norms[iFilter][iSubdivisions] = norm2FLOAT(pSpectrum+iStartLine, iEndLine-iStartLine);*/ + headroom = getScaleFactor32(&pSpectrum[iStartLine], sub(iEndLine, iStartLine)); + + /* Calculate norm of spectrum band */ + L_tmp = Norm32Norm(pSpectrum+iStartLine, headroom, sub(iEndLine, iStartLine), &shift); + + /* Check threshold HLM_MIN_NRG */ + BASOP_SATURATE_WARNING_OFF; + tmp32 = L_sub(L_shl(L_tmp, s_min(31, sub(shift, 24-31*2))), 3277l/*HLM_MIN_NRG Q7*/); + BASOP_SATURATE_WARNING_ON; + + /* get pre-shift for autocorrelation */ + tmp = sub(shift, norm_l(L_tmp)); /* exponent for normalized L_tmp */ + tmp = shr(sub(1, tmp), 1); /* pre-shift to apply before autocorrelation */ + shifts[iFilter][iSubdivisions] = s_min(tmp, headroom); + move16(); + + /* calc normalization factor */ + facs[iFilter][iSubdivisions] = 0; + move16(); + facs_e[iFilter][iSubdivisions] = 0; + move16(); + + if (tmp32 > 0) + { + facs[iFilter][iSubdivisions] = 0x7FFF; + move16(); /* normalization not needed for one subdivision */ + } + + test(); + IF ((tmp32 > 0) && (GT_16(nSubdivisions, 1))) + { + move16(); + facs_e[iFilter][iSubdivisions] = shl(sub(tmp, shifts[iFilter][iSubdivisions]), 1); + + tmp = sub(1, shl(tmp, 1)); /* exponent of autocorrelation */ + L_tmp = L_shl(L_tmp, sub(shift, tmp)); /* shift L_tmp to that exponent */ + + /* calc factor (with 2 bits headroom for sum of 3 subdivisions) */ + move16(); + facs[iFilter][iSubdivisions] = div_s(0x2000, round_fx(L_tmp)); /* L_tmp is >= 0x2000000 */ + } + + } + + } + /* Calculate normalized autocorrelation for spectrum subdivision and get TNS filter parameters based on it */ + FOR (iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++) + { +#define RXX_E (3) + Word32 rxx[TNS_MAX_FILTER_ORDER+1]; + Word16 idx0; + Word16 idx1; + Word16 spectrumLength; + STnsFilter * pFilter; + Word16 nSubdivisions; + Word16 iSubdivisions; + Word16 tmpbuf[325]; + + set32_fx(rxx, 0, TNS_MAX_FILTER_ORDER+1); + + move16(); + move16(); + move16(); + idx0 = pTnsConfig->iFilterBorders[iFilter+1]; + idx1 = pTnsConfig->iFilterBorders[iFilter]; + spectrumLength = sub(idx1, idx0); + pFilter = pTnsData->filter + iFilter; + nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions; + + FOR (iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++) + { + Word16 iStartLine, n, i; + Word16 iEndLine; + const Word16 * pWindow; + Word16 lag, shift; + Word32 L_tmp; + + IF ( facs[iFilter][iSubdivisions] == 0 ) + { + BREAK; + } + + + /* iStartLine = idx0 + (idx1-idx0)*iSubdivisions/nSubdivisions; + iEndLine = idx0 + (idx1-idx0)*(iSubdivisions+1)/nSubdivisions; */ + assert((nSubdivisions == 1) || (nSubdivisions == 3)); + + iStartLine = imult1616(spectrumLength, iSubdivisions); + iEndLine = add(iStartLine, spectrumLength); + + if (EQ_16(nSubdivisions, 3))iStartLine=mult(iStartLine,0x2AAB); + iStartLine = add(iStartLine, idx0); + + if (EQ_16(nSubdivisions, 3))iEndLine=mult(iEndLine,0x2AAB); + iEndLine = add(iEndLine, idx0); + + + move16(); + shift = shifts[iFilter][iSubdivisions]; + + move16(); + pWindow = tnsAcfWindow; + + n = sub(iEndLine, iStartLine); + assert(n < (Word16)(sizeof(tmpbuf)/sizeof(Word16))); + FOR (i = 0; i < n; i++) + { + tmpbuf[i] = round_fx(L_shl(pSpectrum[iStartLine+i], shift)); + } + + FOR (lag = 0; lag <= pTnsConfig->maxOrder; lag++) + { + n = sub(sub(iEndLine,lag), iStartLine); + + L_tmp = L_deposit_l(0); + FOR (i = 0; i < n; i++) + { + L_tmp = L_mac0(L_tmp, tmpbuf[i], tmpbuf[i+lag]); + } + + if (lag != 0) L_tmp = Mpy_32_16_1(L_tmp, *pWindow++); + + L_tmp = Mpy_32_16_1(L_tmp, facs[iFilter][iSubdivisions]); + L_tmp = L_shl(L_tmp, facs_e[iFilter][iSubdivisions]); + + rxx[lag] = L_add(rxx[lag], L_tmp); + move32(); + } + + } + + IF ( EQ_16(iSubdivisions,nSubdivisions)) /* meaning there is no subdivision with low energy */ + { + pFilter->spectrumLength = spectrumLength; + move16(); + /* Limit the maximum order to spectrum length/4 */ + GetFilterParameters(rxx, s_min (pTnsConfig->maxOrder, shr(pFilter->spectrumLength,2)), pFilter); + } + } + + if (predictionGain) + { + assert(pTnsConfig->nMaxFilters == 1); + move16(); + *predictionGain = pTnsData->filter->predictionGain; + } + + /* We check the filter's decisions in the opposite direction */ + FOR (iFilter = sub(pTnsConfig->nMaxFilters,1); iFilter >= 0; iFilter--) + { + STnsFilter * pFilter; + struct TnsParameters const * pTnsParameters; + + move16(); + move16(); + pFilter = pTnsData->filter + iFilter; + pTnsParameters = pTnsConfig->pTnsParameters + iFilter; + + IF ( s_or((Word16)GT_16(pFilter->predictionGain,pTnsParameters->minPredictionGain), + sub(pFilter->avgSqrCoef,pTnsParameters->minAvgSqrCoef) > 0 ) ) + { + move16(); + pTnsData->nFilters = add(pTnsData->nFilters,1); + } + ELSE IF (pTnsData->nFilters > 0) /* If a previous filter is turned on */ + { + /* Since TNS filter of order 0 is not allowed we haved to signal in the stream filter of order 1 with the 0th coefficient equal to 0 */ + ClearTnsFilterCoefficients(pFilter); + move16(); + move16(); + pFilter->order = 1; + pTnsData->nFilters = add(pTnsData->nFilters,1); + } + ELSE + { + ClearTnsFilterCoefficients(pFilter); + } + } + + + test(); + return (pTnsData->nFilters > 0); +} + +Word16 EncodeTnsData(STnsConfig const * pTnsConfig, STnsData const * pTnsData, Word16 * stream, Word16 * pnSize, Word16 * pnBits) +{ + + move16(); + move16(); + *pnSize = 0; + *pnBits = 0; + + IF ( GT_16(pTnsConfig->nMaxFilters, 1)) + { + + IF ( LT_16(pTnsConfig->iFilterBorders[0],512)) + { + GetParameters(tnsEnabledSWBTCX10BitMap, 1, pTnsData, &stream, pnSize, pnBits); + } + ELSE + { + GetParameters(tnsEnabledSWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits); + } + } + ELSE + { + GetParameters(tnsEnabledWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits); + } + + return TNS_NO_ERROR; +} + +Word16 WriteTnsData(STnsConfig const * pTnsConfig, Word16 const * stream, Word16 * pnSize, Encoder_State_fx *st, Word16 * pnBits) +{ + + IF ( GT_16(pTnsConfig->nMaxFilters,1)) + { + + IF ( LT_16(pTnsConfig->iFilterBorders[0],512)) + { + WriteToBitstream(tnsEnabledSWBTCX10BitMap, 1, &stream, pnSize, st, pnBits); + } + ELSE + { + WriteToBitstream(tnsEnabledSWBTCX20BitMap, 1, &stream, pnSize, st, pnBits); + } + } + ELSE + { + WriteToBitstream(tnsEnabledWBTCX20BitMap, 1, &stream, pnSize, st, pnBits); + } + + + return TNS_NO_ERROR; +} + +/*********************************************************************************************/ +/* Definitions of functions used in the mapping between TNS parameters and a bitstream. */ +/*********************************************************************************************/ + +/* Helper functions for Hufmann table coding */ + +/********************************/ +/* Private functions */ +/********************************/ + +static void GetFilterParameters(Word32 rxx[], Word16 maxOrder, STnsFilter * pTnsFilter) +{ + Word16 i; + Word16 parCoeff[TNS_MAX_FILTER_ORDER]; + Word32 epsP[TNS_MAX_FILTER_ORDER+1], L_tmp; +#if TNS_COEF_RES == 5 + Word16 const * values = tnsCoeff5; +#elif TNS_COEF_RES == 4 + Word16 const * values = tnsCoeff4; +#elif TNS_COEF_RES == 3 + Word16 const * values = tnsCoeff3; +#endif + Word16 * indexes = pTnsFilter->coefIndex; + + + /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */ + L_tmp = E_LPC_schur(rxx, parCoeff, epsP, maxOrder); + BASOP_SATURATE_WARNING_OFF /* Allow saturation, this value is compared against a threshold. */ + pTnsFilter->predictionGain = divide3232(L_shr(epsP[0], PRED_GAIN_E), L_tmp); + BASOP_SATURATE_WARNING_ON + /* non-linear quantization of TNS lattice coefficients with given resolution */ + Parcor2Index(parCoeff, indexes, maxOrder); + + /* reduce filter order by truncating trailing zeros */ + i = sub(maxOrder,1); + + WHILE ((i >= 0) && (indexes[i] == 0)) + { + i = sub(i, 1); + } + + move16(); + pTnsFilter->order = add(i, 1); + + /* compute avg(coef*coef) */ + L_tmp = L_deposit_l(0); + + FOR (i = pTnsFilter->order-1; i >= 0; i--) + { + Word16 value ; + + move16(); + value = shr(values[indexes[i]+INDEX_SHIFT], 1); + + move16(); + L_tmp = L_mac0(L_tmp, value, value); + + } + move16(); + pTnsFilter->avgSqrCoef = round_fx(L_tmp); + + /* assert(maxOrder == 8); + pTnsFilter->avgSqrCoef = shr(pTnsFilter->avgSqrCoef, 3); */ + +} + +static void Parcor2Index(const Word16 parCoeff[] /*Q15*/, Word16 index[], Word16 order) +{ + Word16 nValues; + Word16 const * values; + Word16 i; + Word16 iIndex; + Word16 x; + + + move16(); + move16(); + nValues = 1 << TNS_COEF_RES; +#if TNS_COEF_RES == 5 + values = tnsCoeff5; +#elif TNS_COEF_RES == 4 + values = tnsCoeff4; +#elif TNS_COEF_RES == 3 + values = tnsCoeff3; +#endif + + FOR (i = 0; i < order; i++) + { + move16(); + move16(); + iIndex = 1; + x = parCoeff[i]; + + /* parCoeff is in the range of -1.0 ... 1.0 by definition */ + /* assert((x >= FL2WORD16(-1.0f)) && (x <= FL2WORD16(1.0f))); */ + + WHILE ((iIndex < nValues) && (x > add(shr(values[iIndex-1], 1), shr(values[iIndex], 1))) ) + { + iIndex = add(iIndex,1); + + } + index[i] = sub(iIndex, 1 + INDEX_SHIFT); + } + +} + diff --git a/lib_enc/transient_detection.c b/lib_enc/transient_detection.c new file mode 100644 index 0000000..3c469bb --- /dev/null +++ b/lib_enc/transient_detection.c @@ -0,0 +1,729 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include "options.h" +#include "stl.h" +#include "basop_util.h" +#include "prot_fx.h" +#include +#include +#include +#include + +/* Exponent of attack threshold. Picked according to current threshold values. */ +#define ATTACKTHRESHOLD_E 4 +/* Exponent of subblock energies and accumulated subblock energies. + The current value of 2 does not prevent saturations to happen in all cases. */ +#define SUBBLOCK_NRG_E 4 +/* Exponent of the subblock energy change. + This value is coupled to the transient detector API. */ +#define SUBBLOCK_NRG_CHANGE_E NRG_CHANGE_E + +#define MIN_BLOCK_ENERGY ((Word32)1) + + +/************************************************/ +/* */ +/* Internal functions prototypes */ +/* */ +/************************************************/ + +static void InitDelayBuffer(Word16 nFrameLength, Word16 nDelay, DelayBuffer * pDelayBuffer); +static void InitSubblockEnergies(Word16 nFrameLength, Word16 nDelay, DelayBuffer * pDelayBuffer, SubblockEnergies * pSubblockEnergies); +static void InitTransientDetector(SubblockEnergies * pSubblockEnergies, Word16 nDelay, Word16 nSubblocksToCheck, + TCheckSubblocksForAttack pCheckSubblocksForAttack, + Word16 attackRatioThreshold, TransientDetector * pTransientDetector); +static void UpdateDelayBuffer(Word16 const * input, Word16 nSamplesAvailable, DelayBuffer * pDelayBuffer); +static void HighPassFilter(Word16 const * input, Word16 length, Word16 * pFirState1, Word16 * pFirState2, Word16 * output); +static void UpdateSubblockEnergies(Word16 const * input, Word16 nSamplesAvailable, SubblockEnergies * pSubblockEnergies); +static void CalculateSubblockEnergies(Word16 const * input, Word16 nSamplesAvailable, SubblockEnergies * pSubblockEnergies); +static void RunTransientDetector(TransientDetector * pTransientDetector); + +/************************************************/ +/* */ +/* Functions that define transient detectors */ +/* */ +/************************************************/ + +/** TCX decision. + * Check IF there is an attack in a subblock. Version FOR TCX Long/Short decision. + * See TCheckSubblocksForAttack FOR definition of parameters. + * It is assumed that the delay of MDCT overlap was not taken into account, so that the last subblock corresponds to the newest input subblock. + */ +static void GetAttackForTCXDecision(Word32 const * pSubblockNrg, Word32 const * pAccSubblockNrg, Word16 nSubblocks, Word16 nPastSubblocks, Word16 attackRatioThreshold, Word16 * pbIsAttackPresent, Word16 * pAttackIndex) +{ + Word16 i; + Word16 bIsAttackPresent, attackIndex; + Word16 attackRatioThreshold_1_5; + + (void)nPastSubblocks; + (void)nSubblocks; + assert(nSubblocks >= NSUBBLOCKS); + assert(nPastSubblocks >= 2); + + /* attackRatioThreshold_1_5 = attackRatioThreshold * 1.5, exponent is ATTACKTHRESHOLD_E+1 */ + attackRatioThreshold_1_5 = add(shr(attackRatioThreshold,2),shr(attackRatioThreshold,1)); + + move16(); + move16(); + bIsAttackPresent = FALSE; + attackIndex = 0; + /* Search for the last attack in the subblocks */ + if ( s_or((Word16)GT_32(L_shr(pSubblockNrg[-1],ATTACKTHRESHOLD_E), Mpy_32_16_1(pAccSubblockNrg[-1], attackRatioThreshold)), + L_sub(L_shr(pSubblockNrg[-2],ATTACKTHRESHOLD_E), Mpy_32_16_1(pAccSubblockNrg[-2], attackRatioThreshold)) > 0) ) + { + move16(); + bIsAttackPresent = TRUE; + } + + FOR (i = 0; i < NSUBBLOCKS; i++) + { + IF ( GT_32(L_shr(pSubblockNrg[i],ATTACKTHRESHOLD_E), Mpy_32_16_1(pAccSubblockNrg[i], attackRatioThreshold))) + { + if (i < 6) + { + move16(); + bIsAttackPresent = TRUE; + } + + if ( s_and((Word16)NE_16(attackIndex,2),(Word16)NE_16(attackIndex,6))) + { + move16(); + attackIndex = i; + } + } + ELSE /* no attack, but set index anyway in case of strong energy increase */ + { + IF ( s_and(( (Word16)GT_32(L_shr(pSubblockNrg[i],1+ATTACKTHRESHOLD_E), Mpy_32_16_1(pSubblockNrg[sub(i,1)], attackRatioThreshold_1_5))), + ( L_sub(L_shr(pSubblockNrg[i],1+ATTACKTHRESHOLD_E), Mpy_32_16_1(pSubblockNrg[sub(i,2)], attackRatioThreshold_1_5)) > 0 )) ) + { + + if ( s_and((Word16)NE_16(attackIndex,2),(Word16)NE_16(attackIndex,6))) + { + move16(); + attackIndex = i; + } + } + } + } + /* avoid post-echos on click sounds (very short transients) due to TNS aliasing */ + if ( EQ_16(attackIndex,4)) + { + move16(); + attackIndex = 7; + } + if ( EQ_16(attackIndex,5)) + { + move16(); + attackIndex = 6; + } + + move16(); + move16(); + *pAttackIndex = attackIndex; + *pbIsAttackPresent = bIsAttackPresent; + +} + + +/** Initialize TCX transient detector. + * See InitTransientDetector for definition of parameters. + */ +static void InitTCXTransientDetector(Word16 nDelay, SubblockEnergies * pSubblockEnergies, TransientDetector * pTransientDetector) +{ + InitTransientDetector(pSubblockEnergies, nDelay, NSUBBLOCKS, GetAttackForTCXDecision, 17408/*8.5f/(1<delayBuffer); + /* Init a subblock energies buffer used for the TCX Short/Long decision. */ + InitSubblockEnergies(nFrameLength, nTCXDelay, &pTransientDetection->delayBuffer, &pTransientDetection->subblockEnergies); + /* Init the TCX Short/Long transient detector. */ + InitTCXTransientDetector(nTCXDelay, &pTransientDetection->subblockEnergies, &pTransientDetection->transientDetector); + /* We need two past subblocks for the TCX TD and NSUBBLOCKS+1 for the temporal flatness measure FOR the TCX LTP. */ + pTransientDetection->transientDetector.pSubblockEnergies->nDelay = + add(pTransientDetection->transientDetector.pSubblockEnergies->nDelay, NSUBBLOCKS+1); +} + +/** + * \brief Calculate average of temporal energy change. + * \return average temporal energy change with exponent = 8 + */ +Word16 GetTCXAvgTemporalFlatnessMeasure(struct TransientDetection const * pTransientDetection, Word16 nCurrentSubblocks, Word16 nPrevSubblocks) +{ + Word16 i; + TransientDetector const * pTransientDetector; + SubblockEnergies const * pSubblockEnergies; + Word16 nDelay; + Word16 nRelativeDelay; + Word16 const * pSubblockNrgChange; + Word32 sumTempFlatness; + Word16 nTotBlocks; + + + /* Initialization */ + pTransientDetector = &pTransientDetection->transientDetector; + pSubblockEnergies = pTransientDetector->pSubblockEnergies; + move16(); + nDelay = pTransientDetector->nDelay; + nRelativeDelay = sub(pSubblockEnergies->nDelay, nDelay); + pSubblockNrgChange = NULL; + nTotBlocks = add(nCurrentSubblocks,nPrevSubblocks); + + assert(nTotBlocks > 0); + + sumTempFlatness = L_deposit_l(0); + + assert((nPrevSubblocks <= nRelativeDelay) && (nCurrentSubblocks <= NSUBBLOCKS+nDelay)); + + move16(); + pSubblockNrgChange = &pSubblockEnergies->subblockNrgChange[sub(nRelativeDelay,nPrevSubblocks)]; + + FOR (i = 0; i < nTotBlocks; i++) + { + sumTempFlatness = L_add(sumTempFlatness, L_deposit_l(pSubblockNrgChange[i])); + } + + /* exponent = AVG_FLAT_E */ + i = div_l(L_shl(sumTempFlatness,16-15+SUBBLOCK_NRG_CHANGE_E-AVG_FLAT_E), nTotBlocks); + + return i; +} + +Word16 GetTCXMaxenergyChange(struct TransientDetection const * pTransientDetection, + const Word8 isTCX10, + const Word16 nCurrentSubblocks, const Word16 nPrevSubblocks) +{ + Word16 i; + TransientDetector const * pTransientDetector; + SubblockEnergies const * pSubblockEnergies; + Word16 nDelay; + Word16 nRelativeDelay; + Word16 const * pSubblockNrgChange; + Word16 maxEnergyChange; + Word16 nTotBlocks; + + + pTransientDetector = &pTransientDetection->transientDetector; + pSubblockEnergies = pTransientDetector->pSubblockEnergies; + move16(); + nDelay = pTransientDetector->nDelay; + nRelativeDelay = sub(pSubblockEnergies->nDelay, nDelay); + pSubblockNrgChange = NULL; + nTotBlocks = nCurrentSubblocks+nPrevSubblocks; + + assert(nTotBlocks > 0); + maxEnergyChange = 0/*0.0f Q7*/; + + assert((nPrevSubblocks <= nRelativeDelay) && (nCurrentSubblocks <= NSUBBLOCKS+nDelay)); + pSubblockNrgChange = &pSubblockEnergies->subblockNrgChange[nRelativeDelay-nPrevSubblocks]; + + IF ( s_or(pTransientDetector->bIsAttackPresent, isTCX10) ) /* frame is TCX-10 */ + { + Word32 const * pSubblockNrg = &pSubblockEnergies->subblockNrg[sub(nRelativeDelay,nPrevSubblocks)]; + Word32 nrgMin, nrgMax; + Word16 idxMax = 0; + + move16(); + + nrgMax = L_add(pSubblockNrg[0], 0); + + /* find subblock with maximum energy */ + FOR (i = 1; i < nTotBlocks; i++) + { + if ( LT_32(nrgMax, pSubblockNrg[i])) + { + idxMax = i; + move16(); + } + nrgMax = L_max(nrgMax, pSubblockNrg[i]); + } + + nrgMin = L_add(nrgMax, 0); + + /* find minimum energy after maximum */ + FOR (i = idxMax + 1; i < nTotBlocks; i++) + { + nrgMin = L_min(nrgMin, pSubblockNrg[i]); + } + /* lower maxEnergyChange if energy doesn't decrease much after energy peak */ + /* if (nrgMin > 0.375f * nrgMax) */ + if ( LT_32(Mpy_32_16_1(nrgMax, 12288/*0.375f Q15*/), nrgMin) ) + { + nTotBlocks = sub(idxMax, 3); + } + } + + FOR (i = 0; i < nTotBlocks; i++) + { + maxEnergyChange = s_max(maxEnergyChange, pSubblockNrgChange[i]); + } + + move16(); + i = maxEnergyChange; + + return i; +} + +void RunTransientDetection(Word16 const * input, Word16 nSamplesAvailable, TransientDetection * pTransientDetection) +{ + Word16 filteredInput[L_FRAME48k]; + SubblockEnergies * pSubblockEnergies = &pTransientDetection->subblockEnergies; + TransientDetector * pTransientDetector = &pTransientDetection->transientDetector; + + assert((input != NULL) && (pTransientDetection != NULL) && (pSubblockEnergies != NULL) && (pTransientDetector != NULL)); + + HighPassFilter(input, nSamplesAvailable, &pSubblockEnergies->firState1, &pSubblockEnergies->firState2, filteredInput); + + /* Update subblock energies. */ + UpdateSubblockEnergies(filteredInput, nSamplesAvailable, pSubblockEnergies); + + /* Run transient detectors. */ + RunTransientDetector(pTransientDetector); + + /* Update the delay buffer. */ + UpdateDelayBuffer(filteredInput, nSamplesAvailable, &pTransientDetection->delayBuffer); +} + +void SetTCXModeInfo(Encoder_State_fx *st, + TransientDetection const * pTransientDetection, + Word16 * tcxModeOverlap) +{ + assert(pTransientDetection != NULL); + + IF( EQ_16(st->codec_mode,MODE2)) + { + + /* determine window sequence (1 long or 2 short windows) */ + + test(); + IF ( st->tcx10Enabled != 0 && st->tcx20Enabled != 0 ) + { + /* window switching based on transient detector output */ + test(); + test(); + test(); + IF ( ((pTransientDetection->transientDetector.bIsAttackPresent != 0) + || (GT_32(Mpy_32_16_1(st->currEnergyHF_fx, 840/*1.0f/39.0f Q15*/), st->prevEnergyHF_fx) )) + && ((NE_16(st->last_core_fx, ACELP_CORE) ) && (NE_16(st->last_core_fx, AMR_WB_CORE) )) ) + { + move16(); + st->tcxMode = TCX_10; + } + ELSE + { + move16(); + st->tcxMode = TCX_20; + } + } + ELSE + { + /* window selection (non-adaptive) based on flags only */ + IF (st->tcx10Enabled) + { + move16(); + st->tcxMode = TCX_10; + } + ELSE IF (st->tcx20Enabled) + { + move16(); + st->tcxMode = TCX_20; + } + ELSE { + move16(); + st->tcxMode = NO_TCX; + } + } + test(); + test(); + IF (st->last_core_fx == ACELP_CORE || st->last_core_fx == AMR_WB_CORE) + { + move16(); + st->tcx_cfg.tcx_last_overlap_mode = TRANSITION_OVERLAP; + } + ELSE IF ( (EQ_16(st->tcxMode, TCX_10))&&(EQ_16(st->tcx_cfg.tcx_curr_overlap_mode,ALDO_WINDOW))) + { + move16(); + st->tcx_cfg.tcx_last_overlap_mode = FULL_OVERLAP; + } + ELSE + { + move16(); + st->tcx_cfg.tcx_last_overlap_mode = st->tcx_cfg.tcx_curr_overlap_mode; + } + + /* determine window overlaps (0 full, 2 none, or 3 half) */ + + IF ( EQ_16(st->tcxMode, TCX_10)) + { + IF( pTransientDetection->transientDetector.attackIndex < 0) + { + move16(); + *tcxModeOverlap = HALF_OVERLAP; + } + ELSE + { + move16(); + *tcxModeOverlap = s_and(pTransientDetection->transientDetector.attackIndex, 3); + if ( EQ_16(*tcxModeOverlap,1)) + { + move16(); + *tcxModeOverlap = FULL_OVERLAP; + } + } + } + ELSE IF ( EQ_16(st->tcxMode, TCX_20)) + { + IF (EQ_16(pTransientDetection->transientDetector.attackIndex, 7)) + { + move16(); + *tcxModeOverlap = HALF_OVERLAP; + } + ELSE IF (EQ_16(pTransientDetection->transientDetector.attackIndex, 6)) + { + move16(); + *tcxModeOverlap = MIN_OVERLAP; + } + ELSE + { + move16(); + *tcxModeOverlap = ALDO_WINDOW; + } + } + ELSE /* NO_TCX */ + { + move16(); + *tcxModeOverlap = TRANSITION_OVERLAP; + } + test(); + if ((EQ_16(st->tcx_cfg.tcx_last_overlap_mode, TRANSITION_OVERLAP))&&(EQ_16(*tcxModeOverlap,ALDO_WINDOW))) + { + move16(); + *tcxModeOverlap = FULL_OVERLAP; + } + + /* Sanity check */ + assert(*tcxModeOverlap !=1); + + } + +} + +/************************************************/ +/* */ +/* Internal functions */ +/* */ +/************************************************/ + +static void InitDelayBuffer(Word16 nFrameLength, Word16 nDelay, DelayBuffer * pDelayBuffer) +{ + Word16 const nMaxBuffSize = sizeof(pDelayBuffer->buffer)/sizeof(pDelayBuffer->buffer[0]); + + + move16(); + move16(); + assert((nFrameLength > NSUBBLOCKS) && (nFrameLength % NSUBBLOCKS == 0) && (nDelay >= 0) && (pDelayBuffer != NULL)); + pDelayBuffer->nSubblockSize = nFrameLength/NSUBBLOCKS; + assert(pDelayBuffer->nSubblockSize <= nMaxBuffSize); + set16_fx(pDelayBuffer->buffer, 0, nMaxBuffSize); + pDelayBuffer->nDelay = nDelay % pDelayBuffer->nSubblockSize; + assert(pDelayBuffer->nDelay <= nMaxBuffSize); + +} + +static void InitSubblockEnergies(Word16 nFrameLength, Word16 nDelay, DelayBuffer * pDelayBuffer, SubblockEnergies * pSubblockEnergies) +{ + Word16 const nMaxBuffSize = sizeof(pSubblockEnergies->subblockNrg)/sizeof(pSubblockEnergies->subblockNrg[0]); + (void)nFrameLength; + + + assert((pDelayBuffer != NULL) && (pSubblockEnergies != NULL) && (pDelayBuffer->nSubblockSize * NSUBBLOCKS == nFrameLength) && (pDelayBuffer->nSubblockSize > 0)); + + set32_fx(pSubblockEnergies->subblockNrg, MIN_BLOCK_ENERGY, nMaxBuffSize); + set32_fx(pSubblockEnergies->accSubblockNrg, MIN_BLOCK_ENERGY, nMaxBuffSize+1); + set16_fx(pSubblockEnergies->subblockNrgChange, 0x7fff, nMaxBuffSize); + pSubblockEnergies->nDelay = nDelay / pDelayBuffer->nSubblockSize; + assert(pSubblockEnergies->nDelay < nMaxBuffSize); + pSubblockEnergies->nPartialDelay = nDelay % pDelayBuffer->nSubblockSize; + pSubblockEnergies->facAccSubblockNrg = 26624/*0.8125f Q15*/; /* Energy accumulation factor */ + pSubblockEnergies->firState1 = 0; + pSubblockEnergies->firState2 = 0; + + pSubblockEnergies->pDelayBuffer = pDelayBuffer; + pDelayBuffer->nDelay = s_max(pDelayBuffer->nDelay, pSubblockEnergies->nPartialDelay); + +} + +/** Init transient detector. + * Fills TransientDetector structure with sensible content and enable it. + * @param pSubblockEnergies Subblock energies used in this transient detector. + * @param nDelay Delay FOR this transient detector. + * @param nSubblocksToCheck Number of subblocks to check in this transient detector. + * @param pCheckSubblockForAttack Attack detection function FOR this transient detector. + * @param pSetAttackPosition Function FOR finalizing this transient detector. + * @param attackRatioThreshold Attack ratio threshold with exponent ATTACKTHRESHOLD_E. + * @param pTransientDetector Structure to be initialized. + */ +static void InitTransientDetector(SubblockEnergies * pSubblockEnergies, Word16 nDelay, Word16 nSubblocksToCheck, + TCheckSubblocksForAttack pCheckSubblocksForAttack, + Word16 attackRatioThreshold, TransientDetector * pTransientDetector) +{ + Word16 nMaxBuffSize; + + move16(); + nMaxBuffSize = sizeof(pSubblockEnergies->subblockNrg)/sizeof(pSubblockEnergies->subblockNrg[0]); + + assert((pSubblockEnergies != NULL) && (pSubblockEnergies->pDelayBuffer != NULL) && (pTransientDetector != NULL) && (pSubblockEnergies->pDelayBuffer->nSubblockSize != 0)); + pTransientDetector->pSubblockEnergies = pSubblockEnergies; + pTransientDetector->nDelay = (nDelay - pSubblockEnergies->nPartialDelay) / pSubblockEnergies->pDelayBuffer->nSubblockSize; + assert(nDelay == pTransientDetector->nDelay * pSubblockEnergies->pDelayBuffer->nSubblockSize + pSubblockEnergies->nPartialDelay); + assert(pTransientDetector->nDelay < nMaxBuffSize); + pSubblockEnergies->nDelay = s_max(pSubblockEnergies->nDelay, pTransientDetector->nDelay); + assert(nSubblocksToCheck <= NSUBBLOCKS + pTransientDetector->nDelay); + pTransientDetector->nSubblocksToCheck = nSubblocksToCheck; + pTransientDetector->CheckSubblocksForAttack = pCheckSubblocksForAttack; + pTransientDetector->attackRatioThreshold = attackRatioThreshold; + pTransientDetector->bIsAttackPresent = FALSE; + pTransientDetector->attackIndex = -1; +} + +/* This function should be inlined and WMOPS instrumentation takes that into account, meaning that all references are considered as local variables */ +static Word32 InlineFilter(Word16 inValue, Word16 firState1, Word16 firState2) +{ + /* 0.375f * inValue - 0.5f * firState1 + 0.125f * firState2 */ + + return L_msu(L_mac(L_mult(firState2, 4096/*0.125f Q15*/), inValue, 12288/*0.375f Q15*/), firState1, 16384/*0.5f Q15*/); +} + +static void HighPassFilter(Word16 const * input, Word16 length, Word16 * pFirState1, Word16 * pFirState2, Word16 * output) +{ + Word16 i; + + output[0] = round_fx(InlineFilter(input[0], *pFirState1, *pFirState2)); + output[1] = round_fx(InlineFilter(input[1], input[0], *pFirState1)); + + FOR (i = 2; i < length; i++) + { + output[i] = round_fx(InlineFilter(input[i], input[i-1], input[i-2])); + } + + /* update filter states: shift time samples through delay line */ + move16(); + move16(); + *pFirState2 = input[length-2]; + *pFirState1 = input[length-1]; + +} + +static void RunTransientDetector(TransientDetector * pTransientDetector) +{ + Word16 const attackRatioThreshold = pTransientDetector->attackRatioThreshold; + SubblockEnergies const * pSubblockEnergies = pTransientDetector->pSubblockEnergies; + Word16 const nDelay = pTransientDetector->nDelay; + Word16 const nRelativeDelay = pSubblockEnergies->nDelay - nDelay; + Word32 const * pSubblockNrg = &pSubblockEnergies->subblockNrg[nRelativeDelay]; + Word32 const * pAccSubblockNrg = &pSubblockEnergies->accSubblockNrg[nRelativeDelay]; + + assert((pTransientDetector->CheckSubblocksForAttack != NULL)); + + pTransientDetector->CheckSubblocksForAttack(pSubblockNrg, pAccSubblockNrg, + NSUBBLOCKS+nDelay, nRelativeDelay, + attackRatioThreshold, + &pTransientDetector->bIsAttackPresent, &pTransientDetector->attackIndex); + +} + +static void UpdateDelayBuffer(Word16 const * input, Word16 nSamplesAvailable, DelayBuffer * pDelayBuffer) +{ + Word16 i; + Word16 nDelay; + + + move16(); + nDelay = pDelayBuffer->nDelay; + + assert((nDelay >= 0) && (nDelay <= (int)sizeof(pDelayBuffer->buffer)/(int)sizeof(pDelayBuffer->buffer[0]))); + assert(nSamplesAvailable <= NSUBBLOCKS*pDelayBuffer->nSubblockSize); + /* If this is not the last frame */ + IF (nSamplesAvailable == NSUBBLOCKS*pDelayBuffer->nSubblockSize) + { + /* Store the newest samples into the delay buffer */ + FOR (i = 0; i < nDelay; i++) + { + move16(); + pDelayBuffer->buffer[i] = input[i+nSamplesAvailable-nDelay]; + } + } + +} + +static void UpdateSubblockEnergies(Word16 const * input, Word16 nSamplesAvailable, SubblockEnergies * pSubblockEnergies) +{ + Word16 i; + + + assert((pSubblockEnergies->nDelay >= 0) && (pSubblockEnergies->nDelay+NSUBBLOCKS <= (int)sizeof(pSubblockEnergies->subblockNrg)/(int)sizeof(pSubblockEnergies->subblockNrg[0]))); + assert(pSubblockEnergies->nPartialDelay <= pSubblockEnergies->pDelayBuffer->nDelay); + /* At least one block delay is required when subblock energy change is required */ + assert(pSubblockEnergies->nDelay >= 1); + + /* Shift old subblock energies */ + FOR (i = 0; i < pSubblockEnergies->nDelay; i++) + { + move32(); + move32(); + move16(); + pSubblockEnergies->subblockNrg[i] = pSubblockEnergies->subblockNrg[i+NSUBBLOCKS]; + pSubblockEnergies->accSubblockNrg[i] = pSubblockEnergies->accSubblockNrg[i+NSUBBLOCKS]; + pSubblockEnergies->subblockNrgChange[i] = pSubblockEnergies->subblockNrgChange[i+NSUBBLOCKS]; + } + + /* Compute filtered subblock energies for the new samples */ + CalculateSubblockEnergies(input, nSamplesAvailable, pSubblockEnergies); + +} + +/* This function should be inlined and WMOPS instrumentation takes that into account, meaning that all references are considered as local variables */ +static void UpdatedAndStoreAccWindowNrg(Word32 newWindowNrgF, Word32 * pAccSubblockNrg, Word16 facAccSubblockNrg, Word32 * pOutAccWindowNrgF) +{ + /* Store the accumulated energy */ + move32(); + *pOutAccWindowNrgF = *pAccSubblockNrg; + /* Update the accumulated energy: maximum of the current and the accumulated energy */ + *pAccSubblockNrg = Mpy_32_16_1(*pAccSubblockNrg, facAccSubblockNrg); + + if ( GT_32(newWindowNrgF, *pAccSubblockNrg)) + { + move32(); + *pAccSubblockNrg = newWindowNrgF; + } +} + +static void CalculateSubblockEnergies(Word16 const * input, Word16 nSamplesAvailable, SubblockEnergies * pSubblockEnergies) +{ + DelayBuffer * pDelayBuffer; + Word16 nSubblockSize; + Word16 nDelay; + Word16 nPartialDelay; + Word16 * delayBuffer; + Word16 facAccSubblockNrg; + Word32 * pSubblockNrg; + Word32 * pAccSubblockNrg; + Word16 * pSubblockNrgChange; + Word32 * pAccSubblockTmp; + Word16 nWindows; + Word16 w, k, k2, tmp; + Word16 firState1, firState2; + Word32 w0, w1; + Word32 accu; + + move16(); + pDelayBuffer = pSubblockEnergies->pDelayBuffer; + facAccSubblockNrg = pSubblockEnergies->facAccSubblockNrg; + + move16(); + move16(); + move16(); + nSubblockSize = pDelayBuffer->nSubblockSize; + nDelay = pSubblockEnergies->nDelay; + nPartialDelay = pSubblockEnergies->nPartialDelay; + + delayBuffer = &pDelayBuffer->buffer[sub(pDelayBuffer->nDelay, nPartialDelay)]; + pSubblockNrg = &pSubblockEnergies->subblockNrg[nDelay]; + pAccSubblockNrg = &pSubblockEnergies->accSubblockNrg[nDelay]; + pSubblockNrgChange = &pSubblockEnergies->subblockNrgChange[nDelay]; + + move16(); + move16(); + /* nWindows = (nSamplesAvailable + nPartialDelay) / nSubblockSize */ + nWindows = shr(div_s( add(nSamplesAvailable,nPartialDelay), shl(nSubblockSize, 7)),8); + firState1 = pSubblockEnergies->firState1; + firState2 = pSubblockEnergies->firState2; + pAccSubblockTmp = &pAccSubblockNrg[nWindows]; + + IF (nWindows > 0) + { + /* Process left over samples from the previous frame. */ + accu = L_add(MIN_BLOCK_ENERGY, 0); + assert((SUBBLOCK_NRG_E & 1) == 0); + FOR (k = 0; k < nPartialDelay; k++) + { + tmp = shr(delayBuffer[k], SUBBLOCK_NRG_E/2); + accu = L_mac0(accu, tmp, tmp); + } + + /* Process new samples in the 0. subblock. */ + w = sub(nSubblockSize,nPartialDelay); + assert((SUBBLOCK_NRG_E & 1) == 0); + FOR (k = 0; k < w; k++) + { + tmp = shr(input[k], SUBBLOCK_NRG_E/2); + accu = L_mac0(accu, tmp, tmp); + } + + move32(); + pSubblockNrg[0] = accu; + /* Set accumulated subblock energy at this point. */ + UpdatedAndStoreAccWindowNrg(pSubblockNrg[0], pAccSubblockTmp, facAccSubblockNrg, &pAccSubblockNrg[0]); + + FOR (w = 1; w < nWindows; w++) + { + accu = L_add(MIN_BLOCK_ENERGY, 0); + /* Process new samples in the w. subblock. */ + k2 = add(k, nSubblockSize); + assert((SUBBLOCK_NRG_E & 1) == 0); + FOR (; k < k2; k++) + { + tmp = shr(input[k], SUBBLOCK_NRG_E/2); + accu = L_mac0(accu, tmp, tmp); + } + move32(); + pSubblockNrg[w] = accu; + /* Set accumulated subblock energy at this point. */ + UpdatedAndStoreAccWindowNrg(pSubblockNrg[w], pAccSubblockTmp, facAccSubblockNrg, &pAccSubblockNrg[w]); + } + + /* Calculate energy change for each block. */ + FOR (w = 0; w < nWindows; w++) + { + w0 = L_add(pSubblockNrg[w], 0); + w1 = L_add(pSubblockNrg[sub(w,1)], 0); + + IF ( GT_32(w0, w1)) + { + k2 = BASOP_Util_Divide3232_uu_1616_Scale(w0, w1, &k); + } + ELSE + { + k2 = BASOP_Util_Divide3232_uu_1616_Scale(w1, w0, &k); + } + move16(); + pSubblockNrgChange[w] = MAX_16; + IF ( LT_16(k,SUBBLOCK_NRG_CHANGE_E)) + { + move16(); + pSubblockNrgChange[w] = shr(k2, sub(SUBBLOCK_NRG_CHANGE_E,k)); + } + } + } + + move16(); + move16(); + pSubblockEnergies->firState1 = firState1; + pSubblockEnergies->firState2 = firState2; +} + + diff --git a/lib_enc/transition_enc_fx.c b/lib_enc/transition_enc_fx.c new file mode 100644 index 0000000..85cc79c --- /dev/null +++ b/lib_enc/transition_enc_fx.c @@ -0,0 +1,1200 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + +static void gain_trans_enc_fx(Word32 gain_trans32, Word16 exc[], Word16 *quant_index, Word16 *quant_sign, Word16 Q_new); + +static void tc_enc_fx(Encoder_State_fx *st_fx, const Word32 core_brate, const Word16 L_frame, const Word16 i_subfr, Word16 *tc_subfr, Word16 *position, + const Word16 *h1_fx, const Word16 *xn_fx, Word16 *exc_fx, Word16 *yy1_fx, Word16 *T0_min, Word16 *T0_max, + Word16 *T0, Word16 *T0_frac, Word16 *gain_pit_fx, Word16 g_corr_fx[], Word16 *bwe_exc_fx, Word16 Q_new); + + +/*==========================================================================*/ +/* FUNCTION : void transition_enc_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE :Principal function for adaptive excitation construction in TC*/ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* (Word32) core_brate : core bitrate Q0 */ +/* (Word16) L_frame : length of the frame Q0 */ +/* (Word16) coder_type : coding type Q0 */ +/* (Word16) bwidth : input signal bandwidth Q0 */ +/* (Word16) i_subfr : subrame index Q0 */ +/* (Word16*) Jopt_flag : joint optimization flag Q0 */ +/* (Word16[]) voicing_fx : normalized correlations(from OL pitch)Q15 */ +/* (Word16[]) T_op_fx : open loop pitch estimates in current frameQ0*/ +/* (Word16*) res_fx : pointer to the LP residual signal frameQ_new*/ +/* (Word16*) h1_fx : weighted filter input response Q14 */ +/* (Word16*) xn_fx : target signal Q_new*/ +/* (Word16) Q_new : input scaling */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* (Word16*) y1_fx : zero-memory filtered adaptive excitation Q12*/ +/* (Word16*) xn2_fx : target vector for innovation search Qnew */ +/* (Word16*) gain_pit_fx : pitch gain (0..GAIN_PIT_MAX) Q14*/ +/* (Word16[])g_corr_fx : correlations and -2 */ +/* (Word16**)pt_pitch_fx : floating pitch values Q6 */ +/* (Word16*) bwe_exc_fx : excitation for SWB TBE Q0 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* (Word16*) tc_subfr : TC subframe index Q0 */ +/* (Word16*) position : index of the residual signal maximum Q0 */ +/* (Word16*) T0_min : lower pitch limit Q0 */ +/* (Word16*) T0_max : higher pitch limit Q0 */ +/* (Word16*) T0 : close loop integer pitch Q0 */ +/* (Word16*) T0_frac : close loop fractional part of the pitch Q0*/ +/* (Word16*) exc_fx : pointer to excitation signal frame */ +/* (Word16*) gp_cl_fx : memory of gain of pitch clipping algorithm*/ +/* (Word16*) clip_gain : adaptive gain clipping flag Q0 */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ + +void transition_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + const Word16 i_subfr, /* i : subframe index */ + Word16 *tc_subfr, /* i/o: TC subframe index */ + Word16 *Jopt_flag, /* i : joint optimization flag */ + Word16 *position, /* i/o: maximum of residual signal index */ + const Word16 voicing_fx[], /* i : normalized correlations (from OL pitch) Q15*/ + const Word16 T_op_fx[], /* i : open loop pitch estimates in current frame Q0*/ + Word16 *T0, /* i/o: close loop integer pitch Q0*/ + Word16 *T0_frac, /* i/o: close loop fractional part of the pitch Q0*/ + Word16 *T0_min, /* i/o: lower limit for close-loop search Q0*/ + Word16 *T0_max, /* i/o: higher limit for close-loop search Q0*/ + Word16 *exc_fx, /* i/o: pointer to excitation signal frame Q_new*/ + Word16 *y1_fx, /* o : zero-memory filtered adaptive excitation Q_new-1+shift*/ + const Word16 *res_fx, /* i : pointer to the LP residual signal frame Q_new*/ + const Word16 *h1_fx, /* i : weighted filter input response Q(14+shift)*/ + const Word16 *xn_fx, /* i : target vector Q_new-1+shift*/ + Word16 *xn2_fx, /* o : target vector for innovation search Q_new-1+shift*/ + Word16 *gp_cl_fx, /* i/o: memory of gain of pitch clipping algorithm */ + Word16 *gain_pit_fx, /* o : adaptive excitation gain Q14*/ + Word16 *g_corr_fx, /* o : ACELP correlation values */ + Word16 *clip_gain, /* i/o: adaptive gain clipping flag */ + Word16 **pt_pitch_fx, /* o : floating pitch values */ + Word16 *bwe_exc_fx, /* o : excitation for SWB TBE Q_new*/ + Word16 Q_new, /* i : Current scaling */ + Word16 shift /* i : downscaling needs for 12 bits convolutions */ + +) +{ + Word16 pit_flag, pit_start, pit_limit, index, nBits; + Word16 tmp, tmp1; + Word32 i, offset,temp; + Word16 shift_wsp; + Word16 limit_flag, mult_Top, lp_select, lp_flag; + + /* set limit_flag to 0 for restrained limits, and 1 for extended limits */ + limit_flag = 0; + move16(); + + pit_start = PIT_MIN; + move16(); + shift_wsp = add(Q_new,shift); + + /*-----------------------------------------------------------------* + * TC: subrame determination for glottal shape search + * ------------------------------------------------------- + * tc_subfr == 0 - TC in 1st subframe + * tc_subfr == TC_0_0 - TC in 1st subframe + information about T0 + * tc_subfr == L_SUBFR - TC in 2nd subframe + * tc_subfr == 2*L_SUBFR - TC in 3rd subframe + * tc_subfr == 3*L_SUBFR - TC in 4th subframe + *-----------------------------------------------------------------*/ + + IF( i_subfr == 0 ) + { + IF( EQ_16(*tc_subfr,3*L_SUBFR)) + { + IF( EQ_16(L_frame,L_FRAME)) + { + *position = emaximum_fx( Q_new, res_fx + 3*L_SUBFR,s_min(add(T_op_fx[0],2),L_SUBFR), &temp ) + 3*L_SUBFR; + move16(); + *tc_subfr = 3*L_SUBFR; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + *position = emaximum_fx( Q_new, res_fx + 4*L_SUBFR,s_min(add(T_op_fx[0],2),L_SUBFR), &temp ) + 4*L_SUBFR; + move16(); + *tc_subfr = 4*L_SUBFR; + move16(); + } + } + ELSE + { + *position = emaximum_fx( Q_new, res_fx, add(T_op_fx[0],2), &temp ); + + /* correction in case of possibly wrong T_op (double-pitch values) */ + test(); + test(); + test(); + IF( (EQ_16(L_frame,L_FRAME)&>_16(T_op_fx[0],2*PIT_MIN))|| + (EQ_16(L_frame,L_FRAME16k) && GT_16(T_op_fx[0],2*PIT16k_MIN) ) + ) + { + Word16 position_tmp, len, exp_aver=0, exp=0, exp2=0; + Word32 aver, temp2, L_sum, L_temp1, L_temp2; + + len = add(shr(T_op_fx[0],1), 2); + position_tmp = emaximum_fx( Q_new, res_fx, len, &temp2 ); + + L_sum = L_mac(1L, res_fx[0], res_fx[0]); + FOR (i = 1; i < len; i++) + { + L_sum = L_mac0(L_sum, res_fx[i], res_fx[i]); + } + aver = L_sum; /*Q = 2*Q_new */ + aver = root_a_over_b_fx(aver, 2*Q_new, L_shl(len,15), 15, &exp_aver); /*Q = 31-exp_aver*/ + + temp = root_a_fx(temp, 0, &exp); /* Q=31-exp */ + temp2 = root_a_fx(temp2, 0, &exp2); /* Q=31-exp2 */ + + L_temp2 = Mult_32_16(temp, 26214); /* Q=31-exp */ + L_temp1 = Mult_32_16(temp, 8192); /* Q=31-exp */ + + test(); + IF( GT_32(temp2, L_shl(L_temp2,(31-exp2)-(31-exp)))&& + LT_32(aver, L_shl(L_temp1,(31-exp_aver)-(31-exp))) ) + { + *position = position_tmp; + } + } + *tc_subfr = s_and(*position, 0x7FC0); + } + mult_Top = 1; + IF( limit_flag == 0 ) + { + test(); + IF( EQ_16(L_frame,L_FRAME)&<_16(T_op_fx[1],PIT_MIN)) + { + mult_Top = 2; + move16(); + } + test(); + if( EQ_16(L_frame,L_FRAME16k)&<_16(T_op_fx[1],PIT16k_MIN)) + { + mult_Top = 2; + move16(); + } + } + + limit_T0_fx( L_frame, 8, 0, limit_flag, mult_Top*T_op_fx[1], 0, T0_min, T0_max ); + + } + /*-----------------------------------------------------------------* + * zero adaptive excitation signal construction + *-----------------------------------------------------------------*/ + IF ( GT_16(*tc_subfr,i_subfr)) + { + *gain_pit_fx = 0; + move16(); + *clip_gain = 0; + move16(); + g_corr_fx[0] = 16384; + move16(); + g_corr_fx[1] = add(shl(sub(shift_wsp,1),1),1); + move16(); + g_corr_fx[2] = -16384; + move16(); + g_corr_fx[3] = shl(sub(shift_wsp,1),1); + + set16_fx(&exc_fx[i_subfr], 0, L_SUBFR); /* set excitation for current subrame to 0 */ + + IF( EQ_16(L_frame,L_FRAME)) + { + set16_fx(&bwe_exc_fx[i_subfr*HIBND_ACB_L_FAC], 0, (Word16)(L_SUBFR*HIBND_ACB_L_FAC)); /* set past excitation buffer to 0 */ + } + ELSE + { + set16_fx(&bwe_exc_fx[i_subfr*2], 0, L_SUBFR*2); /* set past excitation buffer to 0 */ + } + + set16_fx(y1_fx, 0, L_SUBFR); /* set filtered adaptive excitation to 0 */ + Copy(xn_fx, xn2_fx, L_SUBFR); /* target vector for codebook search */ + *T0 = L_SUBFR; + move16(); + *T0_frac = 0; + move16(); + + **pt_pitch_fx = shl(add(shl(*T0,2),*T0_frac),4); + move16(); /* save subframe pitch values Q6 */ + + } + + /*-----------------------------------------------------------------* + * glottal codebook contribution construction + *-----------------------------------------------------------------*/ + ELSE IF ( EQ_16(*tc_subfr,i_subfr)) + { + IF( EQ_16(L_frame,L_FRAME)) + { + set16_fx( bwe_exc_fx-PIT_MAX*HIBND_ACB_L_FAC, 0, PIT_MAX*HIBND_ACB_L_FAC); /* set past excitation buffer to 0 */ + } + ELSE + { + set16_fx( bwe_exc_fx-PIT16k_MAX*2, 0, PIT16k_MAX*2); /* set past excitation buffer to 0 */ + } + + tc_enc_fx( st_fx, core_brate, L_frame, i_subfr, tc_subfr, position, h1_fx, xn_fx, exc_fx, + y1_fx, T0_min, T0_max, T0, T0_frac, gain_pit_fx, g_corr_fx, bwe_exc_fx,Q_new); + + *clip_gain = gp_clip_fx( core_brate, voicing_fx, i_subfr, coder_type, xn_fx, gp_cl_fx, sub(shift_wsp,1) ); + updt_tar_fx( xn_fx, xn2_fx, y1_fx, *gain_pit_fx, L_SUBFR ); + + **pt_pitch_fx = shl(add(shl(*T0,2),*T0_frac),4); + move16(); + *Jopt_flag = 1; + move16(); + } + + /*--------------------------------------------------------------* + * other subframes -> GENERIC encoding type, + * standard adaptive excitation contribution + * - exemption only in case when first glottal impulse is + * in the 1st subframe and the second one in 2nd subframe + * and later + *--------------------------------------------------------------*/ + ELSE IF ( LT_16(*tc_subfr,i_subfr)) + { + IF( EQ_16(L_frame,L_FRAME)) + { + *Jopt_flag = 1; + move16(); + /* pit_flag for T0 bits number coding determination */ + test(); + IF( (EQ_16(sub(i_subfr,*tc_subfr),L_SUBFR))||(EQ_16(sub(i_subfr,*tc_subfr),L_SUBFR-TC_0_0))) + { + pit_flag = 0; + move16(); + } + ELSE + { + pit_flag = L_SUBFR; + move16(); + } + + IF( EQ_16(*tc_subfr,TC_0_0)) + { + IF( EQ_16(i_subfr,L_SUBFR)) + { + limit_T0_fx( L_FRAME, 8, pit_flag, limit_flag, *T0, 0, T0_min, T0_max ); + } + pit_flag = 1; + move16(); + } + + /*----------------------------------------------------------* + * if tc_subfr==0, change tc_subfr corresponding to the + * second glot. impulse position + *----------------------------------------------------------*/ + test(); + IF( (*tc_subfr == 0) && (EQ_16(i_subfr,L_SUBFR))) + { + IF( GT_16(PIT_MIN,(*position))) + { + pit_start = sub(L_SUBFR, (*position)); + } + ELSE + { + pit_start = PIT_MIN; + move16(); + } + pit_start = s_max(pit_start, PIT_MIN); + + pit_limit = add(shl(pit_start,1), *position); + + /* Find the closed loop pitch period */ + + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, pit_flag, limit_flag, pit_start, pit_limit, L_FRAME, L_SUBFR ); + + offset = tbe_celp_exc_offset(*T0, *T0_frac, L_frame); + + + FOR (i=0; i= 2*L_SUBFR) && (i_subfr == 3*L_SUBFR) ) + { + tmp = shl(add(shl(*T0,2),*T0_frac),4); + (*pt_pitch_fx) -= 3; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + } + ELSE IF( (*tc_subfr == L_SUBFR) && (i_subfr == 2*L_SUBFR) ) + { + tmp = shl(add(shl(*T0,2),*T0_frac),4); + (*pt_pitch_fx) -= 2; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + } + ELSE IF( (*tc_subfr == TC_0_64) && (i_subfr == L_SUBFR) ) + { + tmp = shl(add(shl(*T0,2),*T0_frac),4); + (*pt_pitch_fx) -= 1; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + } + ELSE IF( (*tc_subfr == TC_0_128) && (i_subfr == 2*L_SUBFR) ) + { + tmp = shl(add(shl(*T0,2),*T0_frac),4); + (*pt_pitch_fx) -= 2; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + } + ELSE IF( (*tc_subfr == TC_0_192) && (i_subfr == 3*L_SUBFR) ) + { + tmp = shl(add(shl(*T0,2),*T0_frac),4); + (*pt_pitch_fx) -= 3; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + } + } + ELSE /* L_frame == L_FRAME16k */ + { + if( GE_16(i_subfr,2*L_SUBFR)) + { + limit_flag = 1; + move16(); + } + IF( LE_16(i_subfr,2*L_SUBFR)) + { + IF( LT_16(i_subfr,2*L_SUBFR)) + { + mult_Top = 1; + move16(); + if( LT_16(T_op_fx[0],PIT16k_MIN)) + { + mult_Top = 2; + move16(); + } + + limit_T0_fx( L_FRAME16k, 8, 0, limit_flag, mult_Top*T_op_fx[0], 0, T0_min, T0_max ); /* TC0 second subfr. */ + + } + ELSE + { + limit_T0_fx( L_FRAME16k, 8, 0, limit_flag, T_op_fx[1], 0, T0_min, T0_max ); /* TC0 third subfr., or TC64 third subfr. */ + } + } + + /*-----------------------------------------------------------------* + * get number of bits for pitch encoding + *-----------------------------------------------------------------*/ + + nBits = ACB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(core_brate, coder_type, i_subfr, TC_SUBFR2IDX_16KHZ_fx(*tc_subfr))]; + move16(); + + /*-----------------------------------------------------------------* + * Find adaptive part of excitation, encode pitch period + *-----------------------------------------------------------------*/ + + IF( EQ_16(nBits,10)) + { + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, 0, limit_flag, PIT16k_FR2_EXTEND_10b, PIT16k_MAX, L_frame, L_SUBFR ); + pit16k_Q_enc_fx( st_fx, nBits, limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + ELSE IF( EQ_16(nBits,8)) /* tc_subfr==0 && i_subfr==L_SUBFR */ + { + /*-----------------------------------------------------------------------------* + * The pitch range is encoded absolutely with 8 bits and is divided as follows: + * PIT16k_MIN to PIT16k_FR2_TC0_2SUBFR-1 resolution 1/4 (frac = 0,1,2 or 3) + * PIT16k_FR2_TC0_2SUBFR to 2*L_SUBFR resolution 1/2 (frac = 0 or 2) + *-----------------------------------------------------------------------------*/ + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, 0, limit_flag, PIT16k_FR2_TC0_2SUBFR, 2*L_SUBFR, L_frame, L_SUBFR ); + + IF( GT_16(*T0_max,2*L_SUBFR)) + { + *T0 = 2*L_SUBFR; + move16(); + *T0_frac = 0; + move16(); + } + + IF( LT_16(*T0,PIT16k_FR2_TC0_2SUBFR )) + { + /*index = (*T0)*4 + (*T0_frac) - (PIT16k_MIN*4);*/ + index = add(shl(*T0,2), sub(*T0_frac, PIT16k_MIN*4)); + } + ELSE + { + /*index = (*T0)*2 + ((*T0_frac)>>1) - (PIT16k_FR2_TC0_2SUBFR*2) + ((PIT16k_FR2_TC0_2SUBFR-PIT16k_MIN)*4);*/ + index = add(sub(add(shl(*T0,1), shr(*T0_frac,1)), (PIT16k_FR2_TC0_2SUBFR*2)), (PIT16k_FR2_TC0_2SUBFR-PIT16k_MIN)*4); + } + push_indice_fx( st_fx, IND_PITCH, index, nBits ); + } + ELSE IF( EQ_16(nBits,6)) + { + /* delta search */ + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, L_SUBFR, limit_flag, PIT16k_FR2_EXTEND_9b, PIT16k_FR1_EXTEND_9b, L_frame, L_SUBFR ); + + index = delta_pit_enc_fx( 4, *T0, *T0_frac, *T0_min ); + push_indice_fx( st_fx, IND_PITCH, index, nBits ); + } + IF( EQ_16(nBits,6)) + { + limit_T0_fx( L_FRAME16k, 8, L_SUBFR, limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + + /*-----------------------------------------------------------------* + * - gain clipping test to avoid unstable synthesis + * - LP filtering of the adaptive excitation + * - codebook target computation + *-----------------------------------------------------------------*/ + test(); + IF( (EQ_16(i_subfr,L_SUBFR))&&(EQ_16(*T0,2*L_SUBFR))) + { + *gain_pit_fx = 0; + move16(); + *clip_gain = 0; + move16(); + g_corr_fx[0] = 0; + move16(); + g_corr_fx[1] = 0; + move16(); + *Jopt_flag = 0; + move16(); + + set16_fx( &exc_fx[i_subfr], 0, L_SUBFR+1 ); /* set excitation for current subrame to 0 */ + push_indice_fx( st_fx, IND_LP_FILT_SELECT, 0, 1 ); /* this bit is actually not needed */ + + Copy( xn_fx, xn2_fx, L_SUBFR ); /* target vector for codebook search */ + set16_fx( y1_fx, 0, L_SUBFR ); /* set filtered adaptive excitation to 0 */ + set16_fx( &bwe_exc_fx[i_subfr * 2], 0, L_SUBFR * 2 ); + } + ELSE + { + /* Find the adaptive codebook vector - ACELP long-term prediction */ + pred_lt4(&exc_fx[i_subfr], &exc_fx[i_subfr], *T0, *T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP); + offset = L_deposit_l(0); + + tmp = extract_l(L_mult(*T0_frac,32));/*Q8, 0.25 in Q7*/ + tmp = add(512,tmp);/*Q8; 2 in Q8*/ + tmp = mult_r(tmp,256);/*Q16->Q0; 2 in Q7*/ + + tmp1 = sub(*T0,2);/*Q0*/ + tmp1 = shl(tmp1,1);/*Q0 */ + + offset = add(tmp,tmp1);/*Q0*/ + FOR (i=0; i|| | imp_shape->| g1 | | + * | | | | g2 | ---- exc |---| y1 ---- | + * | | |-------------| |----|gain|-------| h |------|gain|----(-)---> xn2 + * | || | gn | ---- |---| ---- + * |----| |----| + * codebook excitation gain_trans h_orig gain_pit + * + *-------------------------------------------------------------------------------------------*/ + +static void tc_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 i_subfr, /* i : subrame index */ + Word16 *tc_subfr, /* i/o: TC subframe index */ + Word16 *position, /* i/o: index of the residual signal maximum */ + const Word16 *h1_fx, /* i : weighted filter input response Q(14+shift)*/ + const Word16 *xn_fx, /* i : target signal Q_new-1+shift*/ + Word16 *exc_fx, /* o : glottal codebook contribution Q_new*/ + Word16 *yy1_fx, /* o : filtered glottal codebook contribution */ + Word16 *T0_min, /* o : lower pitch limit Q0*/ + Word16 *T0_max, /* o : higher pitch limit Q0*/ + Word16 *T0, /* o : close loop integer pitch Q0*/ + Word16 *T0_frac, /* o : close loop fractional part of the pitch Q0*/ + Word16 *gain_pit_fx, /* o : pitch gain (0..GAIN_PIT_MAX) Q14*/ + Word16 g_corr_fx[], /* o : correlations and -2 */ + Word16 *bwe_exc_fx, /* i/o: excitation for SWB TBE Q_new*/ + Word16 Q_new /* i : input scaling */ +) +{ + Word16 i,imp_shape, imp_pos, index, nBits, h1_tmp_fx[L_SUBFR]; + Word16 pitch_index,pitch_sign_fx; + Word32 gain_trans32; + + imp_pos = sub(*position, i_subfr); + FOR (i = 0; i < L_SUBFR; i++) + { + h1_tmp_fx[i] = h1_fx[i]; + move16(); + } + /*-----------------------------------------------------------------* + * get number of bits for pitch encoding + *-----------------------------------------------------------------*/ + + IF( EQ_16(L_frame,L_FRAME)) + { + nBits = ACB_bits_tbl[BIT_ALLOC_IDX_fx(core_brate, TRANSITION, i_subfr, TC_SUBFR2IDX_fx(*tc_subfr))]; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + nBits = ACB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(core_brate, TRANSITION, i_subfr, TC_SUBFR2IDX_16KHZ_fx(*tc_subfr))]; + move16(); + } + + /*--------------------------------------------------------------* + * Closed loop pitch search + *--------------------------------------------------------------*/ + + *T0_frac = 0; + move16(); + + IF( EQ_16(L_frame,L_FRAME)) + { + test(); + IF( (LE_16(*T0_min,L_SUBFR))||(EQ_16(*tc_subfr,3*L_SUBFR))) + { + IF( EQ_16(nBits,9)) + { + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, 0, 0, PIT_FR2_9b, PIT_FR1_9b, L_FRAME, L_SUBFR ); + } + ELSE IF( EQ_16(nBits,6)) + { + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, 0, 0, PIT_MIN, L_SUBFR, L_FRAME, L_SUBFR ); + } + ELSE + { + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, 0, 0, PIT_MAX, PIT_MIN, L_FRAME, L_SUBFR ); + } + } + ELSE + { + *T0 = L_SUBFR; + move16(); + } + test(); + if( EQ_16(*tc_subfr,L_SUBFR)&<_16(*T0,L_SUBFR)) + { + *T0 = L_SUBFR; + move16(); + } + } + ELSE /* L_frame == L_FRAME16k */ + { + IF( EQ_16(nBits,10)) + { + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, 0, 1, PIT16k_FR2_EXTEND_10b, PIT16k_MAX, L_FRAME16k, L_SUBFR ); + } + ELSE IF( EQ_16(nBits,6)) + { + /* T0_frac with 1/2 sample resolution */ + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, 0, 0, PIT16k_MIN, L_SUBFR, L_FRAME16k, L_SUBFR ); + IF( *T0 > L_SUBFR ) + { + *T0 = L_SUBFR; + move16(); + *T0_frac = 0; + move16(); + } + } + } + + + /* set tc_subfr to TC_0_0 */ + test(); + test(); + test(); + if( i_subfr == 0 && EQ_16(L_frame,L_FRAME)&&(LT_16(*T0,L_SUBFR)||EQ_16(*tc_subfr,3*L_SUBFR))) + { + *tc_subfr = TC_0_0; + move16(); + } + + /*--------------------------------------------------------------* + * Builds glottal codebook contribution + *--------------------------------------------------------------*/ + + set_impulse_fx(xn_fx, h1_tmp_fx, &exc_fx[i_subfr], yy1_fx, &imp_shape, &imp_pos, &gain_trans32, Q_new);/*chk h1_tmp_fx*/ + + /*--------------------------------------------------------------* + * quantize gain_trans and scale glottal codebook contribution + *--------------------------------------------------------------*/ + + gain_trans_enc_fx( gain_trans32, &exc_fx[i_subfr], &pitch_index, &pitch_sign_fx, Q_new ); + + /* set past excitation buffer to zeros */ + set16_fx( exc_fx-L_EXC_MEM, 0, L_EXC_MEM ); + /*--------------------------------------------------------------* + * adapt. search of the second impulse in the same subframe + * (when appears) + *--------------------------------------------------------------*/ + + pred_lt4_tc_fx( exc_fx, *T0, *T0_frac, inter4_2_fx, imp_pos, i_subfr ); + + IF( EQ_16(L_frame,L_FRAME)) + { + interp_code_5over2_fx(&exc_fx[i_subfr], &bwe_exc_fx[i_subfr * HIBND_ACB_L_FAC], L_SUBFR); + } + ELSE + { + interp_code_4over2_fx(&exc_fx[i_subfr], &bwe_exc_fx[i_subfr * 2], L_SUBFR); + } + + /*--------------------------------------------------------------* + * compute glottal-shape codebook excitation + *--------------------------------------------------------------*/ + + /* create filtered glottal codebook contribution */ + conv_fx( &exc_fx[i_subfr], h1_fx, yy1_fx, L_SUBFR ); + + /* gain_pit computation */ + *gain_pit_fx = corr_xy1_fx( xn_fx, yy1_fx, g_corr_fx, L_SUBFR, 0 ); + + /*--------------------------------------------------------------* + * Encode parameters and write indices + *--------------------------------------------------------------*/ + IF( EQ_16(L_frame,L_FRAME)) + { + test(); + test(); + IF( ( (i_subfr != 0) || (EQ_16(*tc_subfr,TC_0_0))) + && (NE_16(*tc_subfr,L_SUBFR) )) + { + test(); + /* write pitch index */ + IF( (GE_16(*T0,L_SUBFR))&&(NE_16(*tc_subfr,3*L_SUBFR))) + { + push_indice_fx( st_fx, IND_PITCH, 0, nBits ); + } + ELSE IF( EQ_16(*tc_subfr,3*L_SUBFR)) + { + IF( EQ_16(nBits,9)) + { + index = abs_pit_enc_fx( 4, 0, *T0, *T0_frac ); + } + ELSE + { + index = abs_pit_enc_fx( 2, 0, *T0, *T0_frac ); + } + push_indice_fx( st_fx, IND_PITCH, index, nBits ); + + limit_T0_fx( L_FRAME, 8, 0, 0, *T0, 0, T0_min, T0_max ); + } + ELSE + { + IF( EQ_16(nBits,6)) + { + index = delta_pit_enc_fx( 2, *T0, *T0_frac, PIT_MIN-1 ); + push_indice_fx( st_fx, IND_PITCH, index, nBits ); + } + ELSE + { + index = delta_pit_enc_fx( 0, *T0, *T0_frac, PIT_MIN-1 ); + push_indice_fx( st_fx, IND_PITCH, index, nBits ); + } + } + } + } + ELSE /* L_frame == L_FRAME16k */ + { + IF( EQ_16(nBits,10)) + { + pit16k_Q_enc_fx( st_fx, nBits, 1, *T0, *T0_frac, T0_min, T0_max ); + } + ELSE IF( EQ_16(nBits,6)) + { + index = add(shl(sub(*T0,PIT16k_MIN),1) , shr(*T0_frac,1)); + push_indice_fx( st_fx, IND_PITCH, index, nBits ); + } + } + push_indice_fx( st_fx, IND_TC_IMP_SHAPE, imp_shape, 3 ); + push_indice_fx( st_fx, IND_TC_IMP_POS, imp_pos, 6 ); + push_indice_fx( st_fx, IND_TC_IMP_SIGN, pitch_sign_fx, 1 ); + push_indice_fx( st_fx, IND_TC_IMP_GAIN, pitch_index, 3 ); + + *position = add(imp_pos, i_subfr); + move16(); + return; +} + + +/*-----------------------------------------------------------------* + * gain_trans_enc() + * + * Quantize gain_trans of TC (gains of glottal impulses). + * - Uses scalar quantization prototypes tbl_gain_trans_tc[N_GAIN_TC]. + * - Gains the glottal codebook contibution signal. + *-----------------------------------------------------------------*/ +static void gain_trans_enc_fx( + Word32 gain_trans32, /* i : gain for mode Tc Q7 */ + Word16 exc[], /* i/o: glottal codebook contribution i:Q13 o:Q_new*gain_trans */ + Word16 *quant_index, /* o : index of quantized gain_trans */ + Word16 *quant_sign, /* o : sign of quantized gain_trans */ + Word16 Q_new /* i : curent scaling */ +) +{ + Word16 i, imax, istart, tmp16, gain_trans, gscale; + + istart = 0; + move16(); + imax = 4; + move16(); + gscale = 7; + move16(); + gain_trans = extract_h(L_shl(gain_trans32,16)); /* Q7 */ + + IF (GT_32(L_abs(gain_trans32), 29862L)) + { + gain_trans = extract_h(L_shl(gain_trans32,16-3)); /* Q4 */ + istart = 4; + move16(); + imax = N_GAIN_TC-1; + move16(); + gscale = 4; + move16(); + } + + /* qsign = 0 if *gain_trans < 0 else qsign = 1*/ + tmp16 = shr(gain_trans,16); + *quant_sign = add(1, tmp16); + move16();/* quantize sign */ + tmp16 = s_or(tmp16, 1); /* Keep sign */ + gain_trans = abs_s(gain_trans); + + *quant_index = N_GAIN_TC-1; + move16(); + FOR (i = istart; i < imax; i++) + { + IF (LE_16(gain_trans,tbl_gain_trans_tc_fx[i])) + { + *quant_index = i; + move16(); + BREAK; + } + } + + gain_trans = i_mult2(tbl_gain_trans_tc_fx[i], tmp16); /* Retreive quantized gain with sign */ + tmp16 = sub(Q_new,add(gscale,13-16+1)); /*remove 16 from rounding */ + FOR (i = 0; i < L_SUBFR; i++) + { + /*exc[i] *= (*gain_trans);*/ + exc[i] = round_fx(L_shl(L_mult(exc[i], gain_trans),tmp16)); + } +} + diff --git a/lib_enc/update_decision.c b/lib_enc/update_decision.c new file mode 100644 index 0000000..19bd5a6 --- /dev/null +++ b/lib_enc/update_decision.c @@ -0,0 +1,465 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include "basop_util.h" +#include "stl.h" +#include "vad_basop.h" +#include "prot_fx.h" + +void bg_music_decision(T_CldfbVadState *st, + Word16 *music_backgound_f, /*(i) background music flag*/ + Word32 frame_energy, /*(i) current frame energy 1*/ + Word16 frame_energy_Q /*(i) the Scaling of current frame energy*/ + ) +{ + + Word16 *f_tonality_rate = st->f_tonality_rate; + Word16 *ltd_stable_rate = st->ltd_stable_rate; + Word16 *sp_center = st->sp_center; + Word16 *sSFM = st->sfm; + Word16 cmp_result; + Word32 music_background_frame; + Word32 tmp1; + Word16 tmp1_Q; + Word16 tmp_norm; + Word32 frame_energy_Mcount; + Word16 fg_energy_Qtmp; + + + music_background_frame = 0; + move32(); + tmp1 = L_mult(st->fg_energy_count,18842); + tmp1_Q = norm_l(tmp1); + tmp1 = L_shl(tmp1,tmp1_Q); + tmp_norm = extract_h(tmp1); + frame_energy_Mcount = MUL_F(frame_energy,tmp_norm); + + fg_energy_Qtmp = sub(frame_energy_Q, 18); + fg_energy_Qtmp = add(fg_energy_Qtmp, tmp1_Q); + + cmp_result = VAD_L_CMP(frame_energy_Mcount,fg_energy_Qtmp,st->fg_energy,st->fg_energy_scale); + + test(); + IF((GT_16(f_tonality_rate[1],9830/* 0.6 Q14 */)) + ||(GT_16(f_tonality_rate[0],14089/* 0.86 Q14 */))) + { + + test(); + test(); + test(); + test(); + if((LT_16(ltd_stable_rate[0], 2359/* 0.072 Q15 */)) + &&(GT_16(sp_center[0],1228/* 1.2 Q10 */)) + &&((LT_16(sSFM[0],24903/* 0.76 Q15 */)) + ||(LT_16(sSFM[1],28835/* 0.88 Q15 */)) + ||(LT_16(sSFM[2],31456/* 0.96 Q15 */)))) + { + music_background_frame = 1; + move32(); + } + } + + test(); + test(); + IF(music_background_frame + &&(cmp_result > 0) + &&(EQ_32(st->fg_energy_est_start,1))) + { + st->music_background_rate = add(mult(st->music_background_rate,31949), 819); + move16(); + } + ELSE IF(music_background_frame) + { + st->music_background_rate = add(mult(st->music_background_rate,32702), 66); + move16(); + } + ELSE + { + st->music_background_rate = mult(st->music_background_rate,32670); + move16(); + } + + *music_backgound_f = 0; + move16(); + if(GT_16(st->music_background_rate, 16384)) + { + *music_backgound_f = 1; + move16(); + } + +} + +Word16 update_decision(T_CldfbVadState *st, + Word32 frame_energy, /*(i) current frame energy*/ + Word32 HB_Power,/*(i) current frame high frequency energy*/ + Word16 frameloop,/*(i) amount of frames*/ + Word16 bw, /*(i) band width index*/ + Word16 frame_energy_Q, /*(i) the Scaling of current frame energy*/ + Word16 HB_Power_Q, /*(i) the Scaling of current frame high frequency energy*/ + Word32 snr, /*(i) frequency domain SNR */ + Word32 tsnr, /*(i) time domain SNR */ + Word16 vad_flag, + Word16 music_backgound_f/*(i) background music flag*/ + ) +{ + Word16 *sp_center = st->sp_center; + Word16 *ltd_stable_rate = st->ltd_stable_rate; + Word16 *sSFM = st->sfm; + Word16 *f_tonality_rate = st->f_tonality_rate; + + Word16 update_flag; + Word16 tonality_flag; + Word32 tmp1; + Word16 tmp1_Q; + Word16 tmp_norm; + Word32 frame_energy_Mcount; + Word32 lt_bg_highf_eng_trbl; + Word16 flag_high_eng; + Word16 fg_energy_Qtmp; + Word16 cmp_result; + Word16 tmpout; + Word16 sp_center3_diff; + + Word16 Q_counter; + Word16 Q_sum; + Word32 sum_num,counter_den; + Word16 div_r; + + Word16 div_r_Q; + Word32 div_r_32; + + + update_flag = 1; + move16(); + tonality_flag = 0; + move16(); + + lt_bg_highf_eng_trbl = MUL_F(st->lt_bg_highf_eng,24576); + IF (GT_16(14,HB_Power_Q)) + { + lt_bg_highf_eng_trbl = L_shr(lt_bg_highf_eng_trbl,sub(14,HB_Power_Q)); + } + ELSE + { + HB_Power = L_shr(HB_Power, s_min(31, sub(HB_Power_Q, 14))); + } + + flag_high_eng = 0; + move16(); + if (GT_32(HB_Power,lt_bg_highf_eng_trbl)) + { + flag_high_eng = 1; + move16(); + } + + sp_center3_diff = sub(sp_center[3], st->lt_noise_sp_center3); + + IF(sub(frameloop, 50) > 0) + { + if(GT_16(ltd_stable_rate[0],3932/* 0.12 Q15 */)) + + { + update_flag = 0; + move16(); + } + + tmpout= VAD_L_CMP(frame_energy, sub(frame_energy_Q,2), st->frame_energy_smooth,st->frame_energy_smooth_scale); + test(); + IF((NE_16(bw, CLDFBVAD_NB_ID))&&tmpout>0) + { + test(); + if((flag_high_eng) && (GT_16(sp_center3_diff, 409))) + { + update_flag = 0; + move16(); + } + test(); + if((GT_16(sp_center[3],2864/* 2.8 Q10 */))&&(GT_16(ltd_stable_rate[0],655/* 0.02 Q15 */))) + { + update_flag = 0; + move16(); + } + } + } + + test(); + if((GT_16(f_tonality_rate[1], 8192/* 0.5 Q14 */)) + && (GT_16(ltd_stable_rate[0],3277/* 0.1 Q15 */))) + { + update_flag = 0; + move16(); + } + + test(); + test(); + IF((LT_16(sSFM[1], 30146/* 0.92 Q15 */)) + && (LT_16(sSFM[0], 30146/* 0.92 Q15 */)) + && (LT_16(sSFM[2], 30146/* 0.92 Q15 */))) + { + update_flag = 0; + move16(); + } + + test(); + test(); + IF((LT_16(sSFM[0], 26214/* 0.8 Q15 */)) + || (LT_16(sSFM[1],25558/* 0.78 Q15 */) ) + || (LT_16(sSFM[2],26214/* 0.8 Q15 */) )) + { + update_flag = 0; + move16(); + } + + /*if(frame_energy > 32*st->frame_energy_smooth)*/ + tmpout= VAD_L_CMP(frame_energy, frame_energy_Q, st->frame_energy_smooth,sub(st->frame_energy_smooth_scale,5)); + + if(tmpout>0) + { + update_flag = 0; + move16(); + } + tmp1 = L_mult(st->fg_energy_count,18842); + tmp1_Q = norm_l(tmp1); + tmp1 = L_shl(tmp1,tmp1_Q); + tmp_norm = extract_h(tmp1); + frame_energy_Mcount = MUL_F(frame_energy,tmp_norm); + + fg_energy_Qtmp = sub(frame_energy_Q, 18); + fg_energy_Qtmp = add(fg_energy_Qtmp, tmp1_Q); + + cmp_result = VAD_L_CMP(frame_energy_Mcount,fg_energy_Qtmp,st->fg_energy,st->fg_energy_scale); + + tmpout = VAD_L_CMP(frame_energy, frame_energy_Q, 3, 0); + + test(); + test(); + if((cmp_result>0) + &&(EQ_32(st->fg_energy_est_start,1)) + &&(tmpout>0)) + { + update_flag = 0; + move16(); + } + + test(); + IF((GT_16(f_tonality_rate[1],9830/* 0.6 Q14 */)) + ||(GT_16(f_tonality_rate[0],14089/* 0.86 Q14 */))) + { + update_flag = 0; + move16(); + tonality_flag = 1; + move16(); + } + + st->tonality_rate3 = mult(st->tonality_rate3, 32211); + move16(); + if(tonality_flag) + { + st->tonality_rate3 = add(mult(st->tonality_rate3,32211), 557); + move16(); + } + + if(GT_16(st->tonality_rate3, 16384)) + { + update_flag = 0; + move16(); + } + + test(); + if((GT_16(sp_center[0], 4092/* 4.0 Q10 */)) + && (GT_16(ltd_stable_rate[0], 1311/* 0.04 Q15 */))) + { + update_flag = 0; + move16(); + } + + test(); + test(); + IF((GT_16(f_tonality_rate[1], 7536/* 0.46 Q14 */)) + && ((GT_16(sSFM[1],30473/* 0.93 Q15 */) ) + ||(GT_16(ltd_stable_rate[0], 2949/* 0.09 Q15 */)))) + + { + update_flag = 0; + move16(); + } + + test(); + test(); + test(); + IF( (LT_16(sSFM[1],30473/* 0.93 Q15 */) + && LT_16(sSFM[0], 30146/* 0.92 Q15 */) + && LT_16(sSFM[2], 31784/* 0.97 Q15 */)) + && (GT_16(f_tonality_rate[1], 8192/* 0.5 Q14 */))) + { + update_flag = 0; + move16(); + } + + test(); + test(); + IF((f_tonality_rate[1] > 7045/* 0.43 Q14 */) + &&(sSFM[0] < 31129/* 0.95 Q15 */) + &&(sp_center[1] > 1985/* 1.94 Q10 */)) + { + update_flag = 0; + move16(); + } + + IF(EQ_16(update_flag, 1)) + { + if(LT_16(st->update_count, 1000)) + { + st->update_count = add(st->update_count,1); + } + } + + + IF(update_flag) + { + st->lt_noise_sp_center3 = add(mult(st->lt_noise_sp_center3,29491),mult(sp_center[3],3277)); + move16(); + } + + + + tmpout= VAD_L_CMP(frame_energy, frame_energy_Q, st->frame_energy_smooth,sub(st->frame_energy_smooth_scale,2)); + + + test(); + test(); + test(); + test(); + if((tmpout>0) + &&(LT_16(frameloop, 100) ) + &&(LT_16(f_tonality_rate[1],9174/* 0.56 Q14 */)) + &&((LT_16(sp_center[0], 1391/* 1.36 Q10 */))||LT_16(ltd_stable_rate[0],983/* 0.03 Q15 */))) + { + update_flag = 1; + move16(); + } + + test(); + test(); + test(); + test(); + test(); + test(); + if((LT_32(snr,10066329/* 0.3 Q25 */))&&tmpout<0 + &&(LT_32(L_shr(tsnr,1), 20132659/* 1.2/2.0 Q25 */)) + &&(vad_flag==0) + &&(LT_16(st->f_tonality_rate[1],8192/* 0.5 Q14 */)) + &&(music_backgound_f==0) + &&(LT_16(st->ltd_stable_rate[3],3277/* 0.1 Q15 */))) + { + update_flag = 1; + move16(); + } + + test(); + test(); + test(); + IF(vad_flag && GT_32(snr, 33554431/* 1.0 Q25 */)&&EQ_16(bw,CLDFBVAD_SWB_ID)&&tmpout>0) + { + update_flag = 0; + } + + test(); + test(); + test(); + IF(vad_flag && GT_32(snr, 50331647/* 1.5 Q25 */)&&NE_16(bw,CLDFBVAD_SWB_ID)&&tmpout>0) + { + update_flag = 0; + } + + + IF(update_flag == 0) + { + st->updateNumWithSnr = 0; + } + ELSE + { + test(); + test(); + IF(vad_flag && GT_32(snr, 100663293/* 3.0 Q25 */)&<_16(st->updateNumWithSnr,10)) + { + update_flag = 0; move16(); + st->updateNumWithSnr = add(st->updateNumWithSnr, 1); + } + } + + + test(); + IF(vad_flag==0||EQ_16(update_flag,1)) + { + Word16 tmp_fix; + tmp_fix = sub(st->sp_center[2],st->lt_noise_sp_center0); + tmp_fix = abs_s(tmp_fix); + if (GT_16(tmp_fix, 2558/* 2.5 Q10 */)) + { + tmp_fix = 2558/* 2.5 Q10 */; + move16(); + } + st->lt_noise_sp_center_diff_sum = L_add(st->lt_noise_sp_center_diff_sum ,tmp_fix); + move32(); + + st->lt_noise_sp_center_diff_counter = L_add(st->lt_noise_sp_center_diff_counter,1); + move32(); + IF(EQ_32(st->lt_noise_sp_center_diff_counter, 128)) + { + st->lt_noise_sp_center_diff_sum = MUL_F(st->lt_noise_sp_center_diff_sum,24576); + move32(); + st->lt_noise_sp_center_diff_counter = 96; + move32(); + } + + move16(); + move16(); + IF(GT_16((Word16)abs_s(sub(st->sp_center[0],st->lt_noise_sp_center0)), 2455/* 2.4 Q10 */)) + { + st->lt_noise_sp_center0 = add(mult(st->lt_noise_sp_center0,32637),mult(st->sp_center[0],131)); + move16(); + } + ELSE IF(GT_16((Word16)abs_s(sub(st->sp_center[0],st->lt_noise_sp_center0)), 1023/* 1.0 Q10 */)) + { + st->lt_noise_sp_center0 = add(mult(st->lt_noise_sp_center0,32440),mult(st->sp_center[0],328)); + move16(); + } + ELSE + { + st->lt_noise_sp_center0 = add(mult(st->lt_noise_sp_center0,31457),mult(st->sp_center[0],1311)); + move16(); + } + } + + Q_sum = sub(norm_l(st->lt_noise_sp_center_diff_sum), 1); + Q_counter = norm_l(st->lt_noise_sp_center_diff_counter); + sum_num = L_shl(st->lt_noise_sp_center_diff_sum,Q_sum); + counter_den = L_shl(st->lt_noise_sp_center_diff_counter,Q_counter); + + IF(extract_h(counter_den)==0) + { + div_r = EVS_SW_MAX; + move16(); + } + ELSE + { + div_r = div_l(sum_num,extract_h(counter_den)); + } + + div_r = mult(div_r,24576); + div_r_32 = VAD_L_ADD(L_deposit_l(div_r),add(sub(Q_sum,Q_counter),22), 9830, 15,&div_r_Q); + div_r =extract_l(L_shr(div_r_32, sub(div_r_Q, SP_CENTER_Q))); + + test(); + if((GT_16(abs_s(sub(st->sp_center[2],st->lt_noise_sp_center0)), div_r))&&(GT_16(frameloop,200))) + { + update_flag = 0; + move16(); + } + + + return update_flag; +} diff --git a/lib_enc/updt_enc_fx.c b/lib_enc/updt_enc_fx.c new file mode 100644 index 0000000..a87801a --- /dev/null +++ b/lib_enc/updt_enc_fx.c @@ -0,0 +1,271 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * updt_enc() + * + * Common updates (all frame types) + *-------------------------------------------------------------------*/ + +void updt_enc_fx( + Encoder_State_fx *st, /* i/o: state structure */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : speech coder type */ + const Word16 *old_exc, /* i : buffer of excitation */ + const Word16 *pitch_buf, /* i : floating pitch for each subframe */ + const Word16 Es_pred, /* i : predicited scaled innovation energy */ + const Word16 *Aq, /* i : A(z) quantized for all subframes */ + const Word16 *lsf_new, /* i : current frame LSF vector */ + const Word16 *lsp_new, /* i : current frame LSP vector */ + const Word16 *old_bwe_exc /* i : buffer of excitation */ +) +{ + Word16 i, tmp; + + + /* update old excitation buffer */ + Copy( &old_exc[L_frame], st->LPDmem.old_exc, L_EXC_MEM ); + IF( !st->Opt_AMR_WB_fx ) + { + Copy( &old_bwe_exc[L_FRAME32k], st->old_bwe_exc_fx, PIT16k_MAX * 2 ); + } + + /* update old LSP and LSF vector */ + Copy( lsp_new, st->lsp_old_fx, M ); + Copy( lsf_new, st->lsf_old_fx, M ); + + /* update last coder type */ + st->last_coder_type_fx = coder_type; + move16(); + test(); + test(); + test(); + if( EQ_16(coder_type,INACTIVE)||(EQ_16(st->bpf_off_fx,1)&&NE_16(coder_type,AUDIO)&&NE_16(coder_type,TRANSITION))) + { + st->last_coder_type_fx = UNVOICED; + move16(); + } + + /* this ensures that st->last_coder_type_fx is never set to INACTIVE in case of AVQ inactive because the FEC does not distinguish between GSC inactive and AVQ inactive */ + test(); + if ( EQ_16(coder_type,INACTIVE)&>_32(st->total_brate_fx,ACELP_24k40)) + { + st->last_coder_type_fx = GENERIC; + move16(); + } + + test(); + test(); + test(); + IF( st->Opt_AMR_WB_fx && EQ_16(coder_type,INACTIVE)&&st->core_brate_fx!=SID_1k75&&st->core_brate_fx!=FRAME_NO_DATA) + { + /* overwrite previous coding type to help FEC */ + st->last_coder_type_fx = UNVOICED; + move16(); + } + + /* AC mode (GSC) - in speech we can consider that the last pitch band reached the max */ + test(); + IF ( NE_16(coder_type,AUDIO)&&NE_16(coder_type,INACTIVE)) + { + st->mem_last_pit_band_fx = 10 + BAND1k2; + move16(); + st->past_dyn_dec_fx = NOISE_LEVEL_SP0-1; + move16(); /* tends to speech */ + st->noise_lev_fx = NOISE_LEVEL_SP0-1; + move16(); /* tends to speech */ + /*st->mid_dyn_fx = 40.0f * 0.5f + st->mid_dyn * 0.5f;*/ + st->mid_dyn_fx = add(20*128, mult_r(st->mid_dyn_fx, 16384)); /*Q7*/ + } + + /* convert old LSP vector from 12kHz domain to 16kHz domain (needed in case of ACELP@12k8 <-> ACELP@16kHz switching) */ + IF( EQ_16(L_frame,L_FRAME)) + { + Copy( st->lsp_old_fx, st->lsp_old16k_fx, M ); + st->rate_switching_reset_16kHz=lsp_convert_poly_fx( st->lsp_old16k_fx, L_FRAME16k, st->Opt_AMR_WB_fx ); + } + + /* update buffer of old subframe pitch values */ + IF( NE_16(st->last_L_frame_fx,L_frame)) + { + IF( EQ_16(L_frame,L_FRAME)) + { + FOR( i=0; iold_pitch_buf_fx[NB_SUBFR+i] = mult_r(26214, st->old_pitch_buf_fx[NB_SUBFR+i+1]); + move16(); + } + } + ELSE + { + FOR( i=NB_SUBFR; i>0; i-- ) + { + st->old_pitch_buf_fx[NB_SUBFR+i] = add(mult_r(8192, st->old_pitch_buf_fx[NB_SUBFR+i-1]),st->old_pitch_buf_fx[NB_SUBFR+i-1]); + move16(); + } + st->old_pitch_buf_fx[2*NB_SUBFR16k-1] = st->old_pitch_buf_fx[2*NB_SUBFR16k-2]; + move16(); + } + } + tmp = shr(L_frame,6); + Copy( &st->old_pitch_buf_fx[tmp], st->old_pitch_buf_fx, tmp); + Copy( pitch_buf, &st->old_pitch_buf_fx[tmp], tmp); + + /* SC-VBR */ + st->last_Opt_SC_VBR_fx = st->Opt_SC_VBR_fx; + move16(); + st->last_last_ppp_mode_fx = st->last_ppp_mode_fx; + move16(); + st->last_ppp_mode_fx = st->ppp_mode_fx; + move16(); + st->last_nelp_mode_fx = st->nelp_mode_fx; + move16(); + + /* core switching updates */ + Copy( &Aq[(st->L_frame_fx/L_SUBFR-1)*(M+1)], st->old_Aq_12_8_fx, M+1 ); + st->old_Es_pred_fx = Es_pred; + + return; +} + +/*-------------------------------------------------------------------* + * updt_IO_switch() + * + * Common updates for AMR-WB IO mode and EVS primary mode switching + *-------------------------------------------------------------------*/ + +void updt_IO_switch_enc_fx( + Encoder_State_fx *st, /* i/o: state structure */ + const Word16 input_frame /* i : input frame length */ +) +{ + Word16 xsp_tmp[M]; + + IF( EQ_16(st->last_core_fx,AMR_WB_CORE)) /* switching to EVS primary mode */ + { + /* reset onset detection counter */ + st->tc_cnt_fx = -1; + + /* force safety-net LSFQ in the first frames after the switching */ + st->Nb_ACELP_frames_fx = 0; + move16(); + + /* AMR-WB IO mode uses ISF(ISP), but EVS primary mode LSF(LSP) */ + Copy( stable_LSP_fx, xsp_tmp, M ); + isf2lsf_fx( st->lsf_old_fx, st->lsf_old_fx, xsp_tmp); + Copy( stable_LSP_fx, xsp_tmp, M ); + isp2lsp_fx( st->lsp_old_fx, st->lsp_old_fx, xsp_tmp, M); + isp2lsp_fx( st->lsp_old1_fx, st->lsp_old1_fx, xsp_tmp, M); + + Copy( stable_LSP_fx, xsp_tmp, M ); + isp2lsp_fx( st->lspCNG_fx, st->lspCNG_fx, xsp_tmp, M); + /*st->old_enr_index = min( (short)((float)st->old_enr_index / STEP_AMR_WB_SID * STEP_SID), 127 );*/ + IF( st->old_enr_index_fx >=0 ) + { + /* old index is initialized to -1, and may only be updated after it has been calculated properly at least once once */ + st->old_enr_index_fx = s_min(mult(shl(st->old_enr_index_fx,1), 32459), 127 ); /*32459 = 2/(STEP_SID/STEP_AMR_WB_SID)*/ + } + /* Perform preemphasis of the old input signal @16kHz */ + st->mem_preemph16k_fx = 0; + move16(); + preemph_fx( st->old_inp_16k_fx, PREEMPH_FAC_16k, L_INP_MEM, &(st->mem_preemph16k_fx) ); + Scale_sig(st->old_inp_16k_fx, L_INP_MEM, st->prev_Q_new); + /* reset TD BWE buffers */ + set16_fx( st->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k ); + set16_fx( st->old_speech_wb_fx, 0, (L_LOOK_12k8 + L_SUBFR) * 5/16 ); + set16_fx( st->old_bwe_exc_fx, 0, PIT16k_MAX * 2 ); + set16_fx( st->old_bwe_exc_extended_fx, 0, NL_BUFF_OFFSET ); + + st->bwe_non_lin_prev_scale_fx = 0; + move16(); + set16_fx( st->decim_state1_fx, 0, (2*ALLPASSSECTIONS_STEEP+1) ); + set16_fx( st->decim_state2_fx, 0, (2*ALLPASSSECTIONS_STEEP+1) ); + set16_fx( st->L_old_wtda_swb_fx, 0, L_FRAME16k ); + set16_fx( st->old_input_wb_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) ); + + wb_tbe_extras_reset_fx( st->mem_genSHBexc_filt_down_wb2_fx, st->mem_genSHBexc_filt_down_wb3_fx ); + + IF( GE_16(input_frame,L_FRAME32k)) + { + swb_tbe_reset_fx( st->mem_csfilt_fx, st->mem_genSHBexc_filt_down_shb_fx, st->state_lpc_syn_fx, + st->syn_overlap_fx, st->state_syn_shbexc_fx, &(st->tbe_demph_fx),&(st->tbe_premph_fx), st->mem_stp_swb_fx, &(st->gain_prec_swb_fx) ); + + } + + IF( EQ_16(input_frame,L_FRAME48k)) + { + set16_fx(st->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER); + st->fb_tbe_demph_fx = 0; + move16(); + fb_tbe_reset_enc_fx( st->elliptic_bpf_2_48k_mem_fx, &st->prev_fb_energy_fx,st->elliptic_bpf_2_48k_mem_fx_Q,&st->prev_fb_energy_fx_Q); + } + + /* reset FD BWE buffers */ + st->prev_mode_fx = NORMAL; + move16(); + + /* reset the unvoiced/audio signal improvement memories */ + st->seed_tcx_fx = 15687; + move16(); + + st->use_acelp_preq = 0; + move16(); + + } + ELSE /* switching to AMR-WB IO mode */ + { + set16_fx(st->mem_MA_fx, 0, M ); + + /* AMR-WB IO mode uses ISF(ISP), but EVS primary mode LSF(LSP) */ + Copy( stable_ISP_fx, xsp_tmp, M ); + lsf2isf_fx( st->lsf_old_fx, st->lsf_old_fx, xsp_tmp, M); + Copy( stable_ISP_fx, xsp_tmp, M ); + lsp2isp_fx( st->lsp_old_fx, st->lsp_old_fx, xsp_tmp, M); + lsp2isp_fx( st->lsp_old1_fx, st->lsp_old1_fx, xsp_tmp, M); + Copy( stable_ISP_fx, xsp_tmp, M ); + lsp2isp_fx( st->lspCNG_fx, st->lspCNG_fx, xsp_tmp, M); + + IF( st->old_enr_index_fx >= 0 ) + { + /* old_enr__index is initialized to -1, and may only be updated this way after it has been calculated properly at least once once */ + /*st->old_enr_index = min( (short)((float)st->old_enr_index / STEP_SID * STEP_AMR_WB_SID), 63 );*/ + st->old_enr_index_fx = s_max(s_min(mult(st->old_enr_index_fx, 16384), 63 ),0); /*32459 = 2/(STEP_SID/STEP_AMR_WB_SID)*/ + } + /* gain quantization memory */ + set16_fx(st->past_qua_en_fx, (-14*1024), GAIN_PRED_ORDER ); + /* reset VBR signalling */ + st->ppp_mode_fx = 0; + move16(); + st->nelp_mode_fx = 0; + move16(); + } + + /* Force SID in case of AMR-WB IO/EVS primary mode switching */ + st->cnt_SID_fx = 0; + move16(); + + /* CNG - reset */ + st->cng_cnt_fx = 0; + move16(); + st->ho_hist_size_fx = 0; + move16(); + st->burst_ho_cnt_fx = 0; + move16(); + + /* LP memories */ + Copy( UVWB_Ave_fx, st->mem_AR_fx, M ); + + /* FEC - update adaptive LSF mean vector */ + Copy( st->lsf_old_fx, st->lsfoldbfi0_fx, M ); + Copy( st->lsf_old_fx, st->lsfoldbfi1_fx, M ); + Copy( st->lsf_old_fx, st->lsf_adaptive_mean_fx, M ); + + return; +} diff --git a/lib_enc/updt_tar_fx.c b/lib_enc/updt_tar_fx.c new file mode 100644 index 0000000..82d78cb --- /dev/null +++ b/lib_enc/updt_tar_fx.c @@ -0,0 +1,60 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*----------------------------------------------------------------------------------* + * procedure updt_tar: + * + * Update the target vector for codebook search. + *----------------------------------------------------------------------------------*/ +void updt_tar_fx( + const Word16 *x, /* i : old target (for pitch search) */ + Word16 *x2, /* o : new target (for codebook search) */ + const Word16 *y, /* i : filtered adaptive codebook vector */ + const Word16 gain, /* i : adaptive codebook gain */ + const Word16 L /* i : subframe size */ +) +{ + Word16 i; + Word32 L_tmp; + + + FOR (i = 0; i < L; i++) + { + /*x2[i] = x[i] - gain*y[i];*/ + L_tmp = L_mult(x[i], 16384); + L_tmp = L_msu(L_tmp, y[i], gain); + x2[i] = extract_h(L_shl(L_tmp, 1)); + } +} +/*----------------------------------------------------------------------------------* + * procedure updt_tar: + * + * Update the target vector for codebook search. + *----------------------------------------------------------------------------------*/ +void updt_tar_HR_fx( + const Word16 *x, /* i : old target (for pitch search) */ + Word16 *x2, /* o : new target (for codebook search) */ + const Word16 *y, /* i : filtered adaptive codebook vector */ + const Word16 gain, /* i : adaptive codebook gain Q2 */ + const Word16 Qx, /* i : Scaling factor to adapt output to input */ + const Word16 L /* i : subframe size */ +) +{ + Word16 i; + Word32 L_tmp, L_tmp1; + + + FOR (i = 0; i < L; i++) + { + /*x2[i] = x[i] - gain*y[i];*/ + L_tmp = L_mult(x[i], 32767); + L_tmp1 = L_shl(L_mult(y[i], gain), Qx); + L_tmp = L_sub(L_tmp, L_tmp1); + x2[i] = extract_h(L_tmp); + } +} diff --git a/lib_enc/vad_basop.c b/lib_enc/vad_basop.c new file mode 100644 index 0000000..ff97b38 --- /dev/null +++ b/lib_enc/vad_basop.c @@ -0,0 +1,145 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "prot_fx.h" +#include "vad_basop.h" +#include "basop_util.h" +#include "stl.h" +#include "options.h" /* Needed for Stack Counting Mechanism Macros (when Instrumented) */ + +Word32 vad_Sqrt_l( /* o : output value, Q31 */ + Word32 i_s32Val, + Word16 *io_s16Q +) +{ + Word16 exp; + Word32 result; + + exp = sub(31,*io_s16Q); + result = Sqrt32(i_s32Val, &exp); + *io_s16Q = sub(31,exp); + move16(); + + return (result); +} + +Word32 fft_vad_Sqrt_l( /* o : output value, Q31 */ + Word32 i_s32Val, + Word16 i_s16Q, + Word16 *o_s16Q +) +{ + Word16 exp; + Word32 result; + + exp = sub(31, i_s16Q); + result = Sqrt32(i_s32Val, &exp); + *o_s16Q = sub(31, exp); + move16(); + + return (result); +} + +Word32 VAD_L_div(Word32 L_var1, Word32 L_var2,Word16 Q_L_var1,Word16 Q_L_var2,Word16 *Q_OUT ) +{ + Word32 result; + + result = L_deposit_h(BASOP_Util_Divide3232_Scale(L_var1, L_var2, Q_OUT)); + move16(); + *Q_OUT = add(sub(sub(31, *Q_OUT), Q_L_var2), Q_L_var1); + return result; +} + +Word32 VAD_Log2(Word32 i_s32Val, Word16 i_s16Q) +{ + Word32 result; + + /* log10(x) = log2(x) * 1.0/log2(10), exponent LD_DATA_SCALE - 1 */ + result = BASOP_Util_Log2(i_s32Val); + + result = L_add(result, L_shl(L_deposit_l(sub(31, i_s16Q)), 31-LD_DATA_SCALE)); + + return result; +} + +T_VAD_EXP VAD_AddExp(T_VAD_EXP i_tExp1, T_VAD_EXP i_tExp2) +{ + Word16 s16Shift; + T_VAD_EXP tRtnVal; + + if(i_tExp1.s32Mantissa == 0) + { + return i_tExp2; + } + + if(i_tExp2.s32Mantissa == 0) + { + return i_tExp1; + } + s16Shift = sub(s_min(i_tExp1.s16Exp,i_tExp2.s16Exp),1); + tRtnVal.s32Mantissa = L_add(L_shr(i_tExp2.s32Mantissa, sub(i_tExp2.s16Exp,s16Shift)), L_shr(i_tExp1.s32Mantissa, sub(i_tExp1.s16Exp,s16Shift))); + tRtnVal.s16Exp = s16Shift; + move16(); + + s16Shift = norm_l(tRtnVal.s32Mantissa); + tRtnVal.s32Mantissa = L_shl(tRtnVal.s32Mantissa, s16Shift); + tRtnVal.s16Exp = add(tRtnVal.s16Exp,s16Shift); + + return tRtnVal; + +} +Word32 VAD_L_ADD(Word32 s32Mantissa1,Word16 i_tExp1, Word32 s32Mantissa2, Word16 i_tExp2,Word16 *s16Exp) +{ + Word32 result; + + result = BASOP_Util_Add_Mant32Exp(s32Mantissa1, sub(31, i_tExp1), s32Mantissa2, sub(31, i_tExp2), s16Exp); + + move16(); + *s16Exp = sub(31, *s16Exp); + + return result; +} + +Word16 VAD_L_CMP(Word32 s32Mantissa1,Word16 i_tExp1, Word32 s32Mantissa2, Word16 i_tExp2) +{ + Word16 ret; + + ret = BASOP_Util_Cmp_Mant32Exp(s32Mantissa1, sub(31, i_tExp1), s32Mantissa2, sub(31, i_tExp2)); + + return ret; +} + +Word16 FixSqrt(Word32 i_s32Val, Word16 *io_s16Q) +{ + Word16 result, exp; + + exp = sub(31, *io_s16Q); + result = round_fx(Sqrt32(i_s32Val, &exp)); + move16(); + *io_s16Q = sub(15, exp); + + return result; +} + +Word32 VAD_Pow(Word32 i_s32Base, Word32 i_s32Exp, + Word16 i_s16BaseQ, Word16 i_s16ExpQ, Word16 *o_pOuQ) +{ + Word32 result; + result = BASOP_Util_fPow(i_s32Base, sub(31, i_s16BaseQ), i_s32Exp, sub(31, i_s16ExpQ), o_pOuQ); + move16(); + *o_pOuQ = sub(31, *o_pOuQ); + return result; +} + +Word32 VAD_Pow2(Word32 i_s32X, Word16 i_s16Q, Word16 *o_pOuQ) +{ + Word32 result; + result = BASOP_util_Pow2(i_s32X, sub(31, i_s16Q), o_pOuQ); + move16(); + *o_pOuQ = sub(31, *o_pOuQ); + + return result; +} diff --git a/lib_enc/vad_basop.h b/lib_enc/vad_basop.h new file mode 100644 index 0000000..d2acc8f --- /dev/null +++ b/lib_enc/vad_basop.h @@ -0,0 +1,80 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#ifndef __VAD_BASOP_H__ +#define __VAD_BASOP_H__ + +#include "typedef.h" +#include "basop32.h" +#include "stat_enc_fx.h" + +Word16 vadmin( Word16 a, + Word16 b + ); + +Word32 vad_Sqrt_l( Word32 i_s32Val, + Word16 *io_s16Q + ); + +Word32 fft_vad_Sqrt_l( Word32 i_s32Val, + Word16 i_s16Q, + Word16 *o_s16Q + ); + +T_VAD_EXP VAD_AddExp( T_VAD_EXP i_tExp1, + T_VAD_EXP i_tExp2 + ); + +Word16 VAD_L_CMP( Word32 s32Mantissa1, + Word16 i_tExp1, + Word32 s32Mantissa2, + Word16 i_tExp2 + ); + +Word32 VAD_L_ADD( Word32 s32Mantissa1, + Word16 i_tExp1, + Word32 s32Mantissa2, + Word16 i_tExp2, + Word16 *s16Exp + ); + +Word32 VAD_L_div( Word32 L_var1, + Word32 L_var2, + Word16 Q_L_var1, + Word16 Q_L_var2, + Word16 *Q_OUT + ); + +Word32 VAD_Log2( Word32 i_s32Val, + Word16 i_s16Q + ); + +Word16 ffr_getSfWord32( Word32 *vector, + Word16 len + ); + +Word32 VAD_Pow( Word32 i_s32Base, + Word32 i_s32Exp, + Word16 i_s16BaseQ, + Word16 i_s16ExpQ, + Word16 *o_pOuQ + ); + +Word32 VAD_Pow2( Word32 i_s32X, + Word16 i_s16Q, + Word16 *o_pOuQ + ); + +Word16 FixSqrt( Word32 i_s32Val, + Word16 *io_s16Q + ); + +void cfftf( Word16* scale, + complex_32 *c, + complex_32 *ch, + const complex_16 *wa + ); + + +#endif diff --git a/lib_enc/vad_fx.c b/lib_enc/vad_fx.c new file mode 100644 index 0000000..398cab3 --- /dev/null +++ b/lib_enc/vad_fx.c @@ -0,0 +1,1553 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_enc_fx.h" +#include "stl.h" + + + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ +/* old fx constants */ +#define HANGOVER_LONG 10 /* Hangover for CNG */ +#define HANGOVER_LONG_HE 20 /* Hangover of CNG */ +#define HANGOVER_LONG_NB 8 /* Hangover for CNG */ +#define ACTIVE_FRAMES 3 /* Number of consecutive active SPEECH frames necessary to trigger HO */ + +/* SNR threshold curve constants for WB input */ +#define SK16_2_FX 16930 /* Q14 (1.0333f)-> Linear function for clean speech */ +#define SC16_2_FX -4608 /* Q8 (-18)*/ +#define NK16_2_FX 13529 /* Q15 (.41287)-> Linear function for noisy speech */ +#define NC16_2_FX 3394 /* Q8 (13.259625)*/ +/* SNR threshold curve constants for NB input */ +#define NK8_1_FX 3509 /*Q15 (0.1071f) Linear function for noisy speech */ +#define NC8_1_FX 4224 /*Q8 (16.5f) */ +#define SK8_1_FX 12406 /*Q15 (0.3786f) Linear function for clean speech */ +#define SC8_1_FX 2834 /*Q8 (11.07f) */ +#define SIGN_THR_FX 40 /*Q4 (2.5f) Significanse threshold for per band snr calculation */ +#define MIN_SNR_FX 2 /*Q4 Minimum snr used for per band snr calculation */ + + +#define THR_M0_FX 3379 /* Q8 (13.2) Zero ofset for threshod */ +#define THR_K_BG_FX -8192 /* Q15(-0.25) Coefficient for dependence on background level */ +#define THR_K_BG_OFS_FX 5120 /* Q8 (20.0f) Zero offset for background level */ +#define THR_K_SNR_FX 3277 /* Q15 (0.1f) Coefficient for dependence on SNR */ +#define THR_K_EV_FX 18022 /* Q15 (0.55) Coefficient for dependence on noise variations */ + + +#define HO_DTX_CLEAN 1 /* Hangover for dtx in clean conditions */ +#define HO_DTX_NOISY 10 /* Hangover for dtx in noisy conditions */ +#define HO_DTX_NOISY2 4 /* Hangover for dtx in very noisy conditions */ +#define VAD_THR_MIN_FX 2688 + +#define ONE_LG10 2466 /* 1.0*log10(2) in Q13 */ + + +#define HANGOVER_LONG_FX 10 /* Hangover for CNG */ +#define HANGOVER_LONG_MUSIC_FX 20 /* Hangover of CNG */ +#define HANGOVER_LONG_HE_FX 20 /* Hangover of CNG */ +#define HANGOVER_LONG_NB_FX 8 /* Hangover for CNG */ +#define ACTIVE_FRAMES_FX 3 /* Number of consecutive active SPEECH frames necessary to trigger HO */ + +/* SNR threshold curve constants for WB input */ +#define TH16_2_FX 8960 /* Q8 (35) -> lp SNR that separates the curves for clean speech and noisy speech */ +#define TH8_1_FX 5120 /*Q8 (20.0f) long-term SNR that separates the curves for clean speech and noisy speech */ + +#define TH16_2_NFLAG_FX 8960 /* Q8 (35) */ +#define TH8_1_NFLAG_FX 8960 /* Q8 (35) */ + + +#define SNR_OUTLIER_WGHT_1_FX 16384 /* Q14 (1.00)*/ +#define SNR_OUTLIER_WGHT_2_FX 16548 /* Q14 (1.01)*/ +#define SNR_OUTLIER_WGHT_3_FX 16712 /* Q14 (1.02)*/ +#define INV_OUTLIER_THR_1_FX 3277 /* (1/10.0f) in Q15*/ +#define INV_OUTLIER_THR_2_FX 5461 /* (1/6.0f) in Q15 */ + +#define MAX_SNR_OUTLIER_IND_FX 17 /*Q0 */ +#define MAX_SNR_OUTLIER_1_FX 160 /*Q4 (10.0f)*/ +#define MAX_SNR_OUTLIER_2_FX 400 /*Q4 (25.0f)*/ +#define MAX_SNR_OUTLIER_3_FX 800 /*Q4 (50.0f)*/ + + +/* snr_sum = "scale" * (float)log10( L_snr_sum ) ;*/ +static +Word16 vad_snr_log_fx( /* o: Q8 */ + Word32 L_snr /* i: Q4 */ + , Word16 scale)/* i: scale Q13 , 10.0*log10(2) or 1.0*log10(2) */ +{ + Word16 e_snr,f_snr; + Word32 L_tmp; + + e_snr = norm_l(L_snr); + f_snr = Log2_norm_lc(L_shl(L_snr, e_snr)); + e_snr = sub(30-4, e_snr); + L_tmp=Mpy_32_16(e_snr, f_snr, scale); + return round_fx(L_shl(L_tmp, 10)); /* Q8 */ +} + + +void wb_vad_init_fx( + Word16 *nb_active_frames, /* o : nb of consecutive active speech frames */ + Word16 *hangover_cnt, + Word16 *lp_speech, /* o : long-term active speech level */ + Word16 *nb_active_frames_he, /* o : nb of consecutive active speech frames */ + Word16 *hangover_cnt_he, + Word16 *bcg_flux, /* o : background noise fluctuation */ + Word16 *soft_hangover, /* o : soft hangover counter */ + Word16 *voiced_burst, /* o : consecutive voiced speech counter */ + Word16 *bcg_flux_init, /* o : initialization period for noise fluctuation estimation */ + Word16 *nb_active_frames_he1, /* o : nb of consecutive active speech frames 1 */ + Word16 *hangover_cnt_he1, + Word32 *L_vad_flag_reg_H, + Word32 *L_vad_flag_reg_L, + Word32 *L_vad_prim_reg, + Word16 *vad_flag_cnt_50, + Word16 *vad_prim_cnt_16, + Word16 *hangover_cnt_dtx + , Word16 *hangover_cnt_music +) +{ + *hangover_cnt = 0; + move16(); /* Hangover counter initialized to 0 */ + *nb_active_frames = ACTIVE_FRAMES_FX; + move16(); /* The counter of SPEECH frames necessary to trigger HO */ + /* is set to max (-> start with hangover) */ + *lp_speech = 11520; + move16(); /*Q8 (45.0) */ /* Initialize the long-term active speech level in dB */ + + *L_vad_flag_reg_H = L_deposit_l(0); + *L_vad_flag_reg_L = L_deposit_l(0); + *L_vad_prim_reg = L_deposit_l(0); + *vad_flag_cnt_50 = 0; + move16(); + *vad_prim_cnt_16 = 0; + move16(); + + *hangover_cnt_dtx = HANGOVER_LONG_FX; + move16(); /* hangover for DTX */ + *hangover_cnt_music = HANGOVER_LONG_MUSIC_FX; + move16(); /* hangover for MUSIC DTX */ + + *hangover_cnt_he = 0; + move16(); /* Hangover counter initialized to 0 */ + *nb_active_frames_he = ACTIVE_FRAMES_FX; + move16(); /* The counter of SPEECH frames necessary to trigger HO */ + *bcg_flux = 1120; + move16(); /*70 in Q4 */ + *soft_hangover = 0; + move16(); + *voiced_burst = 0; + move16(); + *bcg_flux_init = 50; + move16(); + *nb_active_frames_he1 = ACTIVE_FRAMES_FX; + move16(); + *hangover_cnt_he1 = 0; + move16(); + return; +} + + +/*-----------------------------------------------------------------* + * sign_thr_snr_acc_fx() + * + * accumulate snr_sum with significance thresholds + *-----------------------------------------------------------------*/ +static +void sign_thr_snr_acc_fx( + Word32 *L_snr_sum, /* o: Q4 */ + Word32 L_snr, /* i: Q4 */ + Word16 sign_thr, /* i: Q4 */ + Word16 min_snr ) /* i: Q4 */ +{ + /*if( snr >= sign_thr ) */ + Word32 L_tmp; + + L_tmp = L_deposit_l(min_snr); + if( GE_32(L_snr, L_deposit_l(sign_thr))) + { + L_tmp = L_add(L_snr, 0); + } + BASOP_SATURATE_WARNING_OFF /* may saturate in BASOP */ + *L_snr_sum = L_add(*L_snr_sum, L_tmp); /* Q4 */ + BASOP_SATURATE_WARNING_ON +} + +/*-----------------------------------------------------------------* + * dtx_hangover_addition_fx() + * + *-----------------------------------------------------------------*/ + +Word16 dtx_hangover_addition_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 localVAD, /* i Q0 */ + const Word16 vad_flag, /* i Q0 */ + const Word16 lp_snr, /* i Q8 */ + const Word16 cldfb_subtraction, /* i Q0 number of DTX-HO frames CLDFB wants to reduce */ + Word16 *vad_hover_flag_ptr +) +{ + Word16 hangover_short_dtx ; + Word16 flag_dtx ; + Word16 tmp; + + + flag_dtx = 0; + move16(); + + /* Determine initial hangover length */ + hangover_short_dtx = 2; + move16(); + + test(); + test(); + if ( ( ( LT_16(lp_snr,(16*256))) + && ( NE_16(st_fx->input_bwidth_fx, NB) )) + || ( GT_16(st_fx->prim_act_he_fx, 31130) ) ) /*.95*Q15*/ + { + hangover_short_dtx = 3; + move16(); + } + + /* Adjust hangover according to activity history */ + if (GT_16(st_fx->vad_prim_cnt_16_fx, 12)) /* 12 requires roughly > 80% primary activity */ + { + hangover_short_dtx = add(hangover_short_dtx,2); + } + + if (GT_16(st_fx->vad_flag_cnt_50_fx, 40)) /* 40 requires roughtly > 80% flag activity */ + { + hangover_short_dtx = add(hangover_short_dtx,5); + } + + /* Keep hangover_short lower than maximum hangover count */ + if (GT_16(hangover_short_dtx, HANGOVER_LONG_FX-1)) + { + hangover_short_dtx = (HANGOVER_LONG_FX-1); + move16(); + } + + /* Only allow short HO if not sufficient active frames in clean speech*/ + + tmp = 3; + move16(); /* default for EVS*/ + if (EQ_16(st_fx->core_fx,AMR_WB_CORE)) + { + tmp = 2; + move16(); /* default for AMRWBIO*/ + } + + /* need to be a bit stricter with the DTXHO in very clean WB, SWB cond for EVS12k8VAD section */ + test(); + test(); + if ( ( NE_16(st_fx->input_bwidth_fx, NB)) /* WB or SWB or FB */ + && ( NE_16(st_fx->core_fx, AMR_WB_CORE) ) + && ( GT_16(lp_snr, 25*256) ) + ) + { + tmp = 2; + move16(); + } + + /* limit dtx hangover addition up to "tmp" frames in clean cond */ + IF ( tmp != 0 ) + { + test(); + test(); + test(); + if ( (GT_16(hangover_short_dtx, tmp)) + && ( (LT_16(st_fx->vad_prim_cnt_16_fx, 7) ) + || ( (GT_16(lp_snr, (16*256)) ) + && (LT_16(st_fx->prim_act_he_fx, 27853) ) /*0.85f*2^15 */ + ) + ) + ) + { + hangover_short_dtx = tmp; + move16(); + } + } + + + /* hangover adjustment from combined FFT+CLDFBVAD */ + IF (NE_16(st_fx->core_fx,AMR_WB_CORE)) + { + hangover_short_dtx = sub(hangover_short_dtx, cldfb_subtraction); + hangover_short_dtx = s_max(hangover_short_dtx, 0); + } + + IF ( vad_flag != 0 ) /* Speech present */ + { + flag_dtx = 1; + move16(); + + /* Add hangover after sufficient # of active frames or sufficient activity during last second */ + test(); + if ( ( GE_16(st_fx->nb_active_frames_fx, ACTIVE_FRAMES_FX)) + || (GT_16(st_fx->vad_flag_cnt_50_fx,45)) ) /* 45 requires roughly > 90% flag activity */ + { + st_fx->hangover_cnt_dtx_fx = 0; + move16(); + } + + /* inside HO period */ + test(); + if( ( LT_16(st_fx->hangover_cnt_dtx_fx, HANGOVER_LONG_FX)) + && (st_fx->hangover_cnt_dtx_fx != 0) ) + { + st_fx->hangover_cnt_dtx_fx = add(st_fx->hangover_cnt_dtx_fx, 1); + } + st_fx->hangover_terminate_flag_fx = 0; + move16();/* float fix FIX_HO_TERMINATE */ + + /* Music hangover when music detected */ + test(); + test(); + test(); + if ( (GT_16(st_fx->prim_act_he_fx,31129)) + && (GT_16(st_fx->Etot_lp_fx,40*256) ) + && (GT_16(st_fx->vad_prim_cnt_16_fx,14) ) + && (GT_16(st_fx->vad_flag_cnt_50_fx,48) ) ) /* 45 requires roughly > 95% flag activity */ + { + st_fx->hangover_cnt_music_fx = 0; + move16(); + } + + /* inside Music HO period */ + test(); + if( ( LT_16(st_fx->hangover_cnt_music_fx, HANGOVER_LONG_MUSIC_FX)) + && (st_fx->hangover_cnt_music_fx != 0) ) + { + st_fx->hangover_cnt_music_fx = add(st_fx->hangover_cnt_music_fx, 1); + } + } + ELSE + { + /* Reset the counter of speech frames necessary to start hangover algorithm */ + if(LT_16(st_fx->hangover_cnt_dtx_fx,HANGOVER_LONG_FX)) /* inside HO period */ + { + st_fx->hangover_cnt_dtx_fx = add(st_fx->hangover_cnt_dtx_fx,1); + } + if(LT_16(st_fx->hangover_cnt_music_fx,HANGOVER_LONG_MUSIC_FX)) /* inside HO period */ + { + st_fx->hangover_cnt_music_fx = add(st_fx->hangover_cnt_music_fx,1); + } + + /* fast terminate DTX hangover if st->hangover_terminate_flag is set */ + IF ( st_fx->hangover_terminate_flag_fx != 0 ) + { + st_fx->hangover_cnt_fx = HANGOVER_LONG_FX; + move16(); + st_fx->hangover_cnt_dtx_fx = HANGOVER_LONG_FX; + move16(); + st_fx->hangover_terminate_flag_fx = 0; + move16(); + /* Only shorten music hangover when low energy frames */ + if (LT_16(st_fx->Etot_lp_fx,20*256)) + { + st_fx->hangover_cnt_music_fx = HANGOVER_LONG_MUSIC_FX; + move16(); + } + } + + if( LE_16(st_fx->hangover_cnt_dtx_fx, hangover_short_dtx)) /* "hard" hangover */ + { + flag_dtx = 1; + move16(); + } + + if( LE_16(st_fx->hangover_cnt_music_fx, 15)) /* "hard" hangover music */ + { + flag_dtx = 1; + move16(); + } + } + + + + test(); + if ( flag_dtx != 0 && localVAD == 0 ) + { + *vad_hover_flag_ptr = 1; + move16(); + } + + return flag_dtx ; +} + + +/* new simplified and harmonized code */ +Word16 wb_vad_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 fr_bands[], /* i : per band input energy (contains 2 vectors) Q_new+QSCALE*/ + Word16 *localVAD, + Word16 *noisy_speech_HO, /* o : SC-VBR noisy speech HO flag */ + Word16 *clean_speech_HO, /* o : SC-VBR clean speech HO flag */ + Word16 *NB_speech_HO, /* o : SC-VBR NB speech HO flag */ + Word16 *snr_sum_he, /* o : Output snr_sum as weighted spectral measure*/ + Word16 *localVAD_HE_SAD, + Word8 *flag_noisy_speech_snr , /* o : */ + const Word16 Q_new /* i : scaling factor Q0 */ +) +{ + Word16 i, flag=0, hangover_short; + + Word16 snr_sum, thr1=0, thr1_nb_mod, thr2=0, nk=0, nc=0, th_clean=0; + Word16 lp_snr; /* Q8 */ + const Word32 *pt1; + const Word32 *pt2; + const Word32 *pt3; + + Word16 min_snr, sign_thr; + + Word32 L_snr, L_snr_sum ; + Word32 ftmp, ftmp1, ftmp2; + Word16 m_noise, e_noise, e_num, m_num, snr, snr_tmp, shift_snr; + + Word16 snr_sumt; + Word32 L_vad_thr; + Word16 hangover_hd; + Word16 snr_idx; + Word16 delta1, delta2, delta3,delta4; + + Word16 flag_he1; + Word16 stmp; + Word32 L_msnr, L_mssnr=0, L_mssnr_hov; + Word16 j, tmp, tmp1, tmp2 ; + Word32 L_tmp, L_tmp1, L_tmp2; + + Word32 L_snr18, L_snr19; /* Q4 */ + Word32 L_msnr18, L_msnr19; /* Q13 */ + Word16 nb_sig_snr; /* Q0 */ + + Word16 nv; + Word16 nv_ofs; /* Q8 */ + Word32 L_snr_sum_HE_SAD; /* Q4 */ + Word16 snr_sum_HE_SAD; /*Q8 log */ + Word16 sign_thr_HE_SAD, min_snr_HE_SAD; + + + Word16 thr1_ol; + Word32 L_snr_sum_ol; + Word16 snr_sum_ol; /* Q8 log */ + + Word32 L_snr_outlier; + Word16 snr_outlier_index; + Word32 L_accum_ener_L; + Word32 L_accum_ener_H; + Word16 vad_bwidth_fx; + + vad_bwidth_fx = st_fx->input_bwidth_fx; + move16(); + + L_snr_outlier = L_deposit_l(0); + snr_outlier_index = 0; + move16(); + L_accum_ener_L = L_deposit_l(0); + L_accum_ener_H = L_deposit_l(0); + + L_snr18 = L_deposit_l(0); /* Q4*/ + L_snr19 = L_deposit_l(0); /* Q4 */ + L_msnr18 = L_deposit_l(8192); /* 1.0 Q13*/ + L_msnr19 = L_deposit_l(8192); /* 1.0 Q13 */ + + + IF( EQ_16(vad_bwidth_fx, NB)) + { + st_fx->min_band_fx = 1; + move16(); + st_fx->max_band_fx = 16; + move16(); + } + ELSE + { + st_fx->min_band_fx = 0; + move16(); + st_fx->max_band_fx = 19; + move16(); + } + + /*---------------------------------------------------------------------* + * set SNR thresholds depending on the input bandwitdh + *---------------------------------------------------------------------*/ + IF( EQ_16(st_fx->max_band_fx,19)) /* WB input */ /* or SWB input */ + { + nk = 3277; + move16(); /*0.1 Q15 */ + nc = 4122 ; + move16(); /*16.1 Q8 */ + nv = 525; + move16();/* 2.05 Q8*/ + nv_ofs = 422; + move16();/* 1.65 Q8*/ + th_clean = TH16_2_FX; + move16();/* 35 Q8 */ + sign_thr = 21; + move16(); /*1.3 Q4 */ + tmp = sub(vad_bwidth_fx, WB); + if ( tmp != 0 ) + { + sign_thr = 28; + move16();/*1.75f; Q4 SWB */ + } + min_snr = 13; + move16(); /*0.8 Q4 WB */ + if ( tmp != 0 ) + { + min_snr = 4; + move16(); /*0.25f; Q4 SWB */ + } + + sign_thr_HE_SAD = 40; + move16();/* 2.5f Q4 */; + min_snr_HE_SAD = 3; + move16(); /* 0.2f Q4 */; + } + ELSE /* NB input */ + { + move16(); + nk = 3277; + move16(); /* 0.1 Q15 */ + nc = 4096; + move16(); /* 16.0 Q8 */ + nv = 1024; + move16(); /* 4.0 Q8 */ + nv_ofs = 294 ; + move16(); /*1.15 Q8*/ + th_clean = TH8_1_FX; + move16(); /*20 Q8 */ + sign_thr = 28; + move16(); /* 1.75 * Q4 SIGN_THR */ + min_snr = 4; + move16(); /* .25 *Q4 MIN_SNR */ + sign_thr_HE_SAD = 42; + move16(); /* 2.65f Q4 */; + min_snr_HE_SAD = 1; + move16(); /* 0.05f Q4 */; + } + + hangover_short = 0; + move16(); + + /* IF( st_fx->Opt_SC_VBR_fx != 0 ) */ + *noisy_speech_HO = 0; + move16(); + *clean_speech_HO = 0; + move16(); + *NB_speech_HO = 0; + move16(); + /* } */ + + /*---------------------------------------------------------------------* + * compute SNR for each band & total + *---------------------------------------------------------------------*/ + + lp_snr = sub(st_fx->lp_speech_fx, st_fx->lp_noise_fx); /*Q8 */ + + snr_idx = 2; + move16(); + if( GT_16(lp_snr,4608)) /*18.0 Q8*/ + { + snr_idx = 1; + move16(); + } + if ( GT_16(lp_snr,6144)) /*24.0 Q8*/ + { + snr_idx = 0; + move16(); + } + + + IF ( snr_idx == 0 ) + { + stmp = 6; + move16(); + delta1 = 0; + move16(); /*0.0f in Q13 */ + delta2 = 0; + move16(); /*0.0f in Q13 */ + delta3 = 0; + move16(); /*0.0f in Q13 */ + delta4 = 0; + move16(); + + + /*vad_thr = 2.4f*lp_snr - 42.2f; + vad_thr = min(vad_thr, 80 ); */ + + L_vad_thr = -345702; + move32() ; /* -42.2 Q13*/ + L_vad_thr = L_mac0(L_vad_thr,77,lp_snr) ; /* (2.4)Q5*(lp_snr)Q8 */ + L_vad_thr = L_min(L_vad_thr, 80*(1<<13) ); + } + ELSE IF ( EQ_16(snr_idx,1)) + { + stmp = 6; + move16(); + delta1 = 819; + move16(); /*0.1f in Q13 */ + delta2 = 1638; + move16(); /*0.2f in Q13 */ + delta3 = 1638; + move16(); /*0.2f in Q13 */ + delta4 = 1638; + move16(); /*0.2f in Q13 */ + + /* vad_thr = 2.4f*lp_snr - 40.2f; + vad_thr = min(vad_thr, 80); + */ + L_vad_thr = -329318; + move32() ; /* -40.2 Q13*/ + L_vad_thr = L_mac0(L_vad_thr,77,lp_snr) ; /* (2.4)Q5*(lp_snr)Q8 */ + L_vad_thr = L_min(L_vad_thr, 80*(1<<13) ); + } + ELSE + { + stmp = 9; + move16(); + delta1 = 1638; + move16(); /*0.2f in Q13 */ + delta2 = 3277; + move16(); /*0.4f in Q13 */ + delta3 = 2458; + move16(); /*0.3f in Q13 */ + delta4 = 3277; + move16(); /*0.4f in Q13 */ + /* vad_thr = 2.5f*lp_snr - 10.0f; + vad_thr = max(vad_thr, 1); + */ + L_vad_thr = -81920; + move32() ; /* -10 Q13*/ + L_vad_thr = L_mac0(L_vad_thr,80,lp_snr) ; /* (2.5)Q5*(lp_snr)Q8 */ + L_vad_thr = L_max(L_vad_thr, 1*(1<<13) ); + } + + nb_sig_snr = 20; + move16(); + + pt1 = fr_bands; + pt2 = fr_bands + NB_BANDS; + pt3 = st_fx->bckr_fx; + + L_snr_sum = L_deposit_l(0); + L_snr_sum_HE_SAD = L_deposit_l(0); + snr_sumt = 0; + move16(); + L_mssnr_hov = L_deposit_l(0); + *snr_sum_he = 0; + move16(); + snr_sum_HE_SAD = 0; + move16(); + + + FOR( i=st_fx->min_band_fx; i<=st_fx->max_band_fx; i++ ) + { + ftmp = L_add(*pt1++, 0); + ftmp1 = L_add(*pt2++, 0); + ftmp2 = L_add(*pt3++, 0); + + /*fr_enr = ( 0.2f * st->enrO[i] + 0.4f * ftmp + 0.4f * ftmp1 );*/ + L_tmp = Mult_32_16(st_fx->enrO_fx[i], 13107); /* L_tmp(high word) = Qenr0fx*Q16+1 -16 -> Qener0+1 */ + L_tmp1 = Madd_32_16(L_tmp, ftmp, 26214); /* 26214 = .4 in Q16 */ + L_tmp1 = Madd_32_16(L_tmp1, ftmp1, 26214); /* L_tmp1 re_used a bit later for final snr[i]*/ + + L_tmp2 = Madd_32_16(L_tmp, ftmp, 19661); /* 19661 = 0.3 in Q16 */ + L_tmp2 = Msub_32_16(L_tmp2, ftmp1, -32768); /* -32768= -0.5 in Q16 */ + + IF (GT_32(ftmp,ftmp1)) + { + /*snr[i] = ( 0.2f * st->enrO[i] + 0.4f * ftmp + 0.4f * ftmp1 ) / ftmp2 ;*/ + /*snr[i] = L_tmp1/(ftmp2) */ + IF (ftmp2 != 0) + { + e_num = norm_l(L_tmp1); + m_num = extract_h(L_shl(L_tmp1,e_num)); + + e_noise = norm_l(ftmp2); + m_noise= extract_h(L_shl(ftmp2,e_noise)); + + m_num = shr(m_num,1); + shift_snr = add(sub(e_num, e_noise),15-4); + + snr_tmp = div_s(m_num, m_noise); + L_snr = L_shr(snr_tmp, shift_snr); /* L_snr in Q4 */ + } + ELSE + { + e_num = norm_l(L_tmp1); + m_num = extract_h(L_shl(L_tmp1,e_num)); + + /* if bckr[i] == 0; approx. L_snr */ + e_noise = add(30+1, abs_s(Q_new)); + + m_num = shr(m_num, 1); + shift_snr = add(sub(e_num, e_noise), 15-4); + + snr_tmp = div_s(m_num, 32767); + L_snr = L_shr(snr_tmp, shift_snr); /*L_snr in Q4*/ + } + } + ELSE + { + /*snr[i] = ( 0.2f * st->enrO[i] + 0.3f * ftmp + 0.5f * ftmp1 ) / ftmp2 ;*/ + /*snr[i] =L_tmp2/( ftmp2 ) */ + IF (ftmp2 != 0) + { + e_num = norm_l(L_tmp2); + m_num = extract_h(L_shl(L_tmp2,e_num)); + + e_noise = norm_l(ftmp2); + m_noise= extract_h(L_shl(ftmp2,e_noise)); + + m_num = shr(m_num,1); + shift_snr = add(sub(e_num, e_noise),15-4); + + snr_tmp = div_s(m_num, m_noise); + L_snr = L_shr(snr_tmp, shift_snr); /* L_snr in Q4 */ + } + ELSE + { + e_num = norm_l(L_tmp2); + m_num = extract_h(L_shl(L_tmp2,e_num)); + + /* if bckr[i] == 0; approx. L_snr */ + e_noise = add(30+1, abs_s(Q_new)); + + m_num = shr(m_num, 1); + shift_snr = add(sub(e_num, e_noise), 15-4); + + snr_tmp = div_s(m_num, 32767); + L_snr = L_shr(snr_tmp, shift_snr); /*L_snr in Q4*/ + } + } + + if(LT_32(L_snr,2*(1<<4))) + { + nb_sig_snr=sub(nb_sig_snr,1); /* nb_sig_snr--; */ + } + L_snr = L_max(L_snr, 1*(1<<4)); /* if ( snr[i] < 1 ){snr[i] = 1;}*/ + + + /* snr[i] = (float)log10(snr[i]); */ + snr = vad_snr_log_fx(L_snr, ONE_LG10); + + /* snr_sumt += snr[i];*/ + snr_sumt = add(snr_sumt,shr(snr,4)); /*Q4 */ + + + tmp = shl(snr,5); /* Q8 -> Q13 */ + IF (LT_16(i,2)) + { + tmp = add(tmp,delta1); /*Q13 */ + } + ELSE IF (LT_16(i,7)) + { + tmp = add(tmp,delta2); /*Q13 */ + } + ELSE IF (LT_16(i,18)) + { + tmp = add(tmp,delta3); /*Q13 */ + } + ELSE + { + tmp = add(tmp,delta4); /*Q13 */ + } + + tmp1=tmp; + move16(); /* ftmp1 = ftmp; */ + sub(0,0); + if ( i < 7 ) + { + tmp1=add(tmp,3277); /*.4 in Q13 ftmp1 = ftmp + 0.4f; */ + } + + tmp=s_min(tmp,16384); /* Q13, ftmp = min(ftmp, 2.0f); */ + tmp1=s_min(tmp1,16384); /* Q13, ftmp1 = min(ftmp1, 2.0f); */ + + L_msnr = L_deposit_l(tmp); /*msnr = 1*tmp;*/ + FOR (j=1; jbckr[i] = L_tmp1/st->bckr[i];*/ + IF (st_fx->bckr_fx[i] != 0) + { + e_num = norm_l(L_tmp1); + m_num = extract_h(L_shl(L_tmp1,e_num)); + + e_noise = norm_l(st_fx->bckr_fx[i]); + m_noise= extract_h(L_shl(st_fx->bckr_fx[i],e_noise)); + + m_num = shr(m_num,1); + shift_snr = add(sub(e_num, e_noise),15-4); + + snr_tmp = div_s(m_num, m_noise); + L_snr = L_shr(snr_tmp, shift_snr); /* L_snr in Q4 */ + } + ELSE + { + e_num = norm_l(L_tmp1); + m_num = extract_h(L_shl(L_tmp1,e_num)); + + /* if bckr[i] == 0; approx. L_snr */ + e_noise = add(30+1, abs_s(Q_new)); + + m_num = shr(m_num, 1); + shift_snr = add(sub(e_num, e_noise), 15-4); + + snr_tmp = div_s(m_num, 32767); + L_snr = L_shr(snr_tmp, shift_snr); /*L_snr in Q4*/ + } + + + /* conditional snrsum, snr_sum = snr_sum + snr[i];*/ + sign_thr_snr_acc_fx(&L_snr_sum_HE_SAD,L_snr, sign_thr_HE_SAD, min_snr_HE_SAD); + sign_thr_snr_acc_fx(&L_snr_sum, L_snr, sign_thr, min_snr); + + L_snr = L_max(L_snr, 16); /*Q4, if( snr[i] < 1.0f ) { snr[i] = 1.0f;} */ + + /* float saves all snrs in an snr[] vector , + in fix we only save two bands */ + if ( EQ_16(i,18)) + { + L_snr18 = L_add(L_snr, 0); /*Q4 */ + } + if ( EQ_16(i,19)) + { + L_snr19 = L_add(L_snr, 0); /* Q4 */ + } + + /* accumulate background noise energy in bands [0-2] and in bands [3-19]*/ + IF(LT_16(i,3)) + { + L_accum_ener_L = L_add(L_accum_ener_L , st_fx->bckr_fx[i]);/*Q_new+QSCALE */ + } + ELSE + { + L_accum_ener_H = L_add(L_accum_ener_H , st_fx->bckr_fx[i]);/*Q_new+QSCALE */ + } + + /* Identify the outlier band */ + IF( GT_32(L_snr, L_snr_outlier)) + { + L_snr_outlier = L_add(L_snr, 0); /*Q4*/ + snr_outlier_index = i; + move16(); + } + } /* end of band loop */ + + test(); + test(); + test(); /* one additional test for ELSE IF */ + IF ( (EQ_16(st_fx->max_band_fx, 19)) + && ( GT_32(L_snr18, 5*(1<<4)) ) + && ( GT_32(L_snr19, 5*(1<<4)) ) ) + { + /* mssnr = (mssnr + 3*(msnr18 + msnr19)) * 0.77f; */ + /* mssnr = (mssnr*.77f + 2.31f*(msnr18 + msnr19)); */ + L_tmp1 = Mult_32_16(L_mssnr, 25231 ); /* Q13+Q15+1-16 --> Q13 */ + L_tmp = Mult_32_16(L_shl(L_add(L_msnr18, L_msnr19),2),18924 ); /* Q(13+2)+Q(15-2)+1-16 --> Q13 */ + L_tmp = L_add( L_tmp1, L_tmp); + if ( GT_32(L_tmp, L_mssnr)) + { + L_mssnr = L_tmp; + } + } + ELSE IF ( (snr_idx != 0) + && GT_16(nb_sig_snr, 13) ) + { + L_tmp = -126976; + move32() ; /* -15.5 Q13 */ + L_tmp = L_mac0(L_tmp,80,lp_snr) ; /* 2.5f(Q5)*lp_snr(Q8) - 15.5f */ + if ( L_tmp > 0 ) /* 2.5f*lp_snr - 15.5f > 0 */ + { + L_mssnr = L_add(L_mssnr, L_tmp); /* mssnr += 2.5f*lp_snr - 15.5f; */ + } + } + + + /* Separated SNR_SUM outlier modification */ + L_snr_sum_ol = L_snr_sum; /* snr_sum_ol = snr_sum; */ + + test(); + test(); + test(); + IF( ( EQ_16(st_fx->max_band_fx, 19)) + && LT_32(L_snr_outlier , MAX_SNR_OUTLIER_3_FX) + && GT_16(snr_outlier_index, 3) + && LT_16(snr_outlier_index, MAX_SNR_OUTLIER_IND_FX) ) + { + /* Update the total SNR only for WB signals */ + + + /* corresponding float section + if( (accum_ener_L > OUTLIER_THR_1 * accum_ener_H ) || (snr_outlier < MAX_SNR_OUTLIER_1) ) + { + snr_sum_ol = SNR_OUTLIER_WGHT_1 * (snr_sum_ol - snr_outlier); + } + else if( (accum_ener_L > OUTLIER_THR_2 * accum_ener_H ) || (snr_outlier < MAX_SNR_OUTLIER_2) ) + { + snr_sum_ol = SNR_OUTLIER_WGHT_2 * (snr_sum_ol - snr_outlier); + } + else + { + snr_sum_ol = SNR_OUTLIER_WGHT_3 * (snr_sum_ol - snr_outlier); + } + } */ + + test(); + test(); + IF( LT_32(L_accum_ener_H, Mult_32_16(L_accum_ener_L,INV_OUTLIER_THR_1_FX))/* float:: (accum_ener_L*INV_OUTLIER_THR_1 > accum_ener_H ) !!! */ + || LT_32(L_snr_outlier,MAX_SNR_OUTLIER_1_FX) ) + + { + /* as weight1 is 1.0 we do not need to multiply here , i.e. no need to loose any precisison */ + L_snr_sum_ol = L_sub(L_snr_sum_ol,L_snr_outlier); /*Q4 */ + + } + ELSE IF( LT_32(L_accum_ener_H, Mult_32_16(L_accum_ener_L,INV_OUTLIER_THR_2_FX))/* float:: (accum_ener_L *INV_OUTLIER_THR_2 > accum_ener_H ) !!! */ + || LT_32(L_snr_outlier,MAX_SNR_OUTLIER_2_FX) ) + { + /* L_snr_sum = SNR_OUTLIER_WGHT_2 * (snr_sum - snr_outlier); */ + + /* 1.01*x -> (1*x + 0.01*x) to not drop down to Q3 */ + L_tmp = L_sub(L_snr_sum_ol,L_snr_outlier); + L_tmp2 = Mult_32_16(L_tmp, 20972); /* 0.01(in Q21)= 20972 Q4*Q21+1-16 -> Q10 */ + L_snr_sum_ol = L_add(L_tmp, L_shr(L_tmp2,6)); /* Q4 */ + } + ELSE + { + /* L_snr_sum = SNR_OUTLIER_WGHT_3 * (snr_sum - snr_outlier);*/ + /* 1.02*x -> (1*x + 0.02*x) to not drop down to Q3 */ + L_tmp = L_sub(L_snr_sum_ol,L_snr_outlier); + L_tmp2 = Mult_32_16(L_tmp, 20972); /* 0.02(in Q20)= 20972 Q4*Q20+1-16 -> Q9 */ + L_snr_sum_ol = L_add(L_tmp, L_shr(L_tmp2, 5)); /* Q4 */ + + } + } + /*st_fx->snr_sum_vad_fx = 0.5f * st->snr_sum_vad + 0.5f * snr_sum_ol;*/ + st_fx->L_snr_sum_vad_fx = L_shr(L_add(st_fx->L_snr_sum_vad_fx ,L_snr_sum_ol ),1); /*Q4*/ + + /* snr_sum_ol = 10.0f * (float)log10( snr_sum_ol ); */ + snr_sum_ol = vad_snr_log_fx(L_snr_sum_ol, LG10); + snr_sum = snr_sum_ol; + move16(); /* note for NB no outlier modification */ + + /* snr_sum_HE_SAD = 10.0f * (float)log10( snr_sum_HE_SAD ); */ + snr_sum_HE_SAD = vad_snr_log_fx( L_snr_sum_HE_SAD, LG10); + + *snr_sum_he=snr_sum_HE_SAD; + move16(); /* *snr_sum_he=snr_sum_HE_SAD; */ + + + /*---------------------------------------------------------------------* + * compute thr1 for SAD decision + *---------------------------------------------------------------------*/ + lp_snr = sub(st_fx->lp_speech_fx,st_fx->lp_noise_fx); /*Q8*/ + + sub(0,0); + IF ( LT_16(lp_snr, st_fx->sign_dyn_lp_fx)) + { + lp_snr = add(lp_snr,1<<8); /* lp_snr += 1; */ + + if (GT_16(lp_snr, st_fx->sign_dyn_lp_fx)) + { + lp_snr = st_fx->sign_dyn_lp_fx; + move16(); + } + } + + /*thr1 = nk * lp_snr + nc*1.0 + nv * ( st->Etot_v_h2 - nv_ofs); */ /* Linear function for noisy speech */ + + L_tmp = L_shl(L_mult(sub(st_fx->Etot_v_h2_fx, nv_ofs), nv ),7); /* Q8+Q8+1 +7 --> Q24 */ + L_tmp = L_mac(L_tmp, nc, (Word16)32767); /* Q8+Q15+1 = Q24 */ + thr1 = mac_r(L_tmp, lp_snr, nk ); /* Q8+Q15+1 - 16 --> Q8 */ + + + IF (GT_16(lp_snr, (Word16)20*(1<<8))) /* if (lp_snr > 20.0f )*/ + { + /* thr1 = thr1 + 0.3f * (lp_snr - 20.0f); */ + thr1 = add(thr1, mult(9830, sub(lp_snr,(Word16) 20*(1<<8) ))); /* Q15*Q8+1 -16 --> Q8 */ + + test(); + test(); + test(); + if( EQ_16(st_fx->max_band_fx,16) + && GT_16(lp_snr,40*256) + && GT_16(thr1,6600) + && LT_16(st_fx->lp_speech_fx,11520) ) + { + thr1 = 6600; + } + } + + + + + /*---------------------------------------------------------------------* + * WB input + * SNR threshold computing + * Hangover control & final VAD decision + *---------------------------------------------------------------------*/ + + IF( NE_16(vad_bwidth_fx, NB)) + { + + /* Outlier Detection first calculates thr1_ol and snr_sum_ol instead of + modyfying thr1 and snr_sum */ + + thr1_ol = thr1; + move16(); + hangover_short = 3; + move16(); + + IF( LT_16(lp_snr,th_clean)) + { + hangover_short = 4; + move16(); + + /* In this section the modified nk, and nc are used */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( (LE_16(snr_outlier_index, 4))&&(GT_16(st_fx->last_coder_type_fx,UNVOICED))&&(st_fx->Opt_SC_VBR_fx!=0))|| + ( (LE_16(snr_outlier_index, 4)) && (GT_16(st_fx->last_7k2_coder_type_fx, UNVOICED) ) && ( st_fx->Opt_SC_VBR_fx == 0 ) ) ) + + + { + thr1_ol = sub(thr1_ol,(Word16)(1<<8)); /*thr1_ol = thr1 - 1.0f ; */ + /*snr_sum_ol = 10.0f * (float)log10( st_fx->L_snr_sum_vad_fx );*/ + snr_sum_ol = vad_snr_log_fx(st_fx->L_snr_sum_vad_fx, LG10); /* snr in Q8 */ + + } + ELSE IF ( ((LE_16(st_fx->last_coder_type_fx, UNVOICED))&&(LT_32(L_snr_outlier,MAX_SNR_OUTLIER_2_FX))&&(st_fx->Opt_SC_VBR_fx!=0))|| + ((LE_16(st_fx->last_7k2_coder_type_fx, UNVOICED) ) && (LT_32(L_snr_outlier,MAX_SNR_OUTLIER_2_FX)) && ( st_fx->Opt_SC_VBR_fx == 0 ) ) ) + + { + /* thr1_ol = thr1 + (float)(1.0f - 0.04f * snr_outlier); */ + L_tmp2 = Msub_32_16( (Word32)(1<<(24-16)), L_snr_outlier, 20972 ); /* (1.0)Q24(Q8 in high 32bit word) - Q4*Q19+1 */ + tmp2 = round_fx( L_shl(L_tmp2,16)); /* high word is in Q8 */ + thr1_ol = add(thr1_ol, tmp2 ); /* (Q8 , Q8) */ + } + ELSE + { + /*thr1_ol = thr1 + max(0, (float)(0.6f - 0.01f * L_snr_outlier)); */ + thr1_ol = thr1; + move16(); + L_tmp2 = Msub_32_16( (Word32)614 , L_snr_outlier, 20972); /* .6*1024= */ /* 0.6 Q26(Q10 in high word) - Q4*Q21+1 */ + tmp2 = round_fx(L_shl(L_tmp2,14)); /* Q10(high word)+ 14 -16 --> Q8*/ + if(L_tmp2 > 0) + { + thr1_ol = add(thr1_ol, tmp2 ); /* Q24 >>16 + Q8 */ + } + } + } + + /* apply outlier modification */ + snr_sum = snr_sum_ol; + move16(); /*NB s*/ + thr1 = thr1_ol; + move16(); + + /* DTX HANGOVER is in pre_proc_fx() */ + flag_he1 = 0; + move16(); + + IF ( GT_32(L_mssnr, L_vad_thr)) + { + flag_he1 = 1; + move16(); /* he1 primary decision */ + st_fx->nb_active_frames_he1_fx = add(st_fx->nb_active_frames_he1_fx,1); /* Counter of consecutive active speech frames */ + + IF ( GE_16(st_fx->nb_active_frames_he1_fx,ACTIVE_FRAMES_FX)) + { + st_fx->nb_active_frames_he1_fx = ACTIVE_FRAMES_FX; + move16(); + st_fx->hangover_cnt_he1_fx = 0; + move16(); /* Reset the counter of hangover frames after at least "active_frames" speech frames */ + } + + /* inside HO period */ + test(); + if ( sub(st_fx->hangover_cnt_he1_fx, HANGOVER_LONG_HE_FX) < 0 && st_fx->hangover_cnt_he1_fx != 0 ) + { + st_fx->hangover_cnt_he1_fx = add(st_fx->hangover_cnt_he1_fx ,1); + } + + if ( st_fx->soft_hangover_fx > 0 ) + { + st_fx->soft_hangover_fx = sub(st_fx->soft_hangover_fx ,1); + } + } + ELSE + { + /* Reset the counter of speech frames necessary to start hangover algorithm */ + st_fx->nb_active_frames_he1_fx = 0; + move16(); + } + + + + + IF ( GT_16(st_fx->voiced_burst_fx, 3)) + { + IF ( LT_16(st_fx->bcg_flux_fx, 640)) /* Q4 */ + { + st_fx->soft_hangover_fx = hangover_sf_tbl_fx[add(snr_idx,3)]; + move16(); + } + ELSE + { + st_fx->soft_hangover_fx = hangover_sf_tbl_fx[snr_idx]; + move16(); + } + } + + + hangover_hd = hangover_hd_tbl_fx[snr_idx]; + move16(); + + IF ( LT_16(st_fx->bcg_flux_fx, 640)) + { + hangover_hd = add(shr(hangover_hd,1), 1); + move16(); + } + + /* VAD hangover for he1 */ + test(); + IF ( flag_he1 == 0 && st_fx->soft_hangover_fx > 0 ) + { + IF ( GT_32(L_mssnr_hov, L_vad_thr)) + { + flag_he1 = 1; + move16(); + st_fx->soft_hangover_fx=sub(st_fx->soft_hangover_fx,1); + } + ELSE + { + st_fx->soft_hangover_fx=0; + move16(); + } + + if( st_fx->soft_hangover_fx < 0) + { + st_fx->soft_hangover_fx=0; + move16(); + } + } + + test(); + test(); + IF ( (flag_he1 == 0) + && (LT_16(st_fx->hangover_cnt_he1_fx, hangover_hd) ) + && (st_fx->soft_hangover_fx == 0 ) ) + { + flag_he1 = 1; + move16(); + st_fx->hangover_cnt_he1_fx = add(st_fx->hangover_cnt_he1_fx,1); + } + + + + /* Calculate background stationarity */ + test(); + IF ( flag_he1 == 0 && st_fx->first_noise_updt_fx > 0 ) + { + IF ( GT_16(snr_sumt, st_fx->bcg_flux_fx)) + { + IF ( st_fx->bcg_flux_init_fx-- > 0 ) + { + IF ( GT_16(snr_sumt,add(st_fx->bcg_flux_fx,800))) + { + /*st->bcg_flux = 0.9f * st->bcg_flux + (1-0.9f)*(st->bcg_flux+50);*/ + st_fx->bcg_flux_fx = mac_r(L_mult(st_fx->bcg_flux_fx,29491),add(st_fx->bcg_flux_fx,800),3277); /*Q4 */ + } + ELSE + { + /*st->bcg_flux = 0.9f * st->bcg_flux + (1-0.9f)*snr_sumt*/ + st_fx->bcg_flux_fx = mac_r(L_mult(st_fx->bcg_flux_fx,29491),snr_sumt,3277); /*Q4 */ + } + } + ELSE + { + IF ( GT_16(snr_sumt,add(st_fx->bcg_flux_fx,160))) + { + /*st->bcg_flux = 0.99f * st->bcg_flux + (1-0.99f)*(st->bcg_flux+10);*/ + st_fx->bcg_flux_fx = mac_r(L_mult(st_fx->bcg_flux_fx,32440),add(st_fx->bcg_flux_fx,160),328); /*Q4 */ + } + ELSE + { + /*st->bcg_flux = 0.99f * st->bcg_flux + (1-0.99f)*snr_sumt;*/ + st_fx->bcg_flux_fx = mac_r(L_mult(st_fx->bcg_flux_fx,32440),snr_sumt,328); /*Q4 */ + } + } + } + ELSE + { + IF ( st_fx->bcg_flux_init_fx-- > 0 ) + { + IF ( LT_16(snr_sumt,sub(st_fx->bcg_flux_fx,480))) + { + /*st->bcg_flux = 0.95f * st->bcg_flux + (1-0.95f)*(st->bcg_flux-30);*/ + st_fx->bcg_flux_fx = mac_r(L_mult(st_fx->bcg_flux_fx,31130),sub(st_fx->bcg_flux_fx,480),1638); /*Q4 */ + } + ELSE + { + /*st->bcg_flux = 0.95f * st->bcg_flux + (1-0.95f)*snr_sumt;*/ + st_fx->bcg_flux_fx = mac_r(L_mult(st_fx->bcg_flux_fx,31130),snr_sumt,1638); /*Q4 */ + } + } + ELSE + { + IF ( LT_16(snr_sumt,sub(st_fx->bcg_flux_fx,160))) + { + /*st->bcg_flux = 0.9992f * st->bcg_flux + (1-0.9992f)*(st->bcg_flux-10);*/ + st_fx->bcg_flux_fx = mac_r(L_mult(st_fx->bcg_flux_fx,32742),sub(st_fx->bcg_flux_fx,160),26); /*Q4 */ + } + ELSE + { + /*st->bcg_flux = 0.9992f * st->bcg_flux + (1-0.9992f)*snr_sumt;*/ + st_fx->bcg_flux_fx = mac_r(L_mult(st_fx->bcg_flux_fx,32742),snr_sumt,26); /*Q4 */ + } + } + } + + st_fx->bcg_flux_init_fx = s_max(st_fx->bcg_flux_init_fx,0); + } + + flag = 0; + move16(); + *localVAD = 0; + move16(); + /* if ( snr_sum > thr1 && flag_he1 == 1 ) *//* Speech present */ + test(); + + IF ( (GT_16(snr_sum, thr1))&&(EQ_16(flag_he1,1))) /* Speech present */ + { + flag = 1; + move16(); + *localVAD = 1; + move16(); + + st_fx->nb_active_frames_fx = add(st_fx->nb_active_frames_fx,1); /* Counter of consecutive active speech frames */ + + IF ( GE_16(st_fx->nb_active_frames_fx,ACTIVE_FRAMES_FX)) + { + st_fx->nb_active_frames_fx = ACTIVE_FRAMES_FX; + move16(); + st_fx->hangover_cnt_fx = 0; + move16(); /* Reset the counter of hangover frames after at least "active_frames" speech frames */ + } + + /* inside HO period */ + test(); + if( LT_16(st_fx->hangover_cnt_fx,HANGOVER_LONG_FX) + && st_fx->hangover_cnt_fx != 0 ) + { + st_fx->hangover_cnt_fx = add(st_fx->hangover_cnt_fx,1); + } + } + ELSE + { + /* Reset the counter of speech frames necessary to start hangover algorithm */ + st_fx->nb_active_frames_fx = 0; + move16(); + + if( LT_16(st_fx->hangover_cnt_fx,HANGOVER_LONG_FX)) /* inside HO period */ + { + st_fx->hangover_cnt_fx = add(st_fx->hangover_cnt_fx,1); + } + + + IF( LE_16(st_fx->hangover_cnt_fx, hangover_short)) /* "hard" hangover */ + { + test(); + test(); + if ( (LT_16(lp_snr,th_clean)) + && (st_fx->Opt_SC_VBR_fx != 0 ) + && (GE_16(st_fx->hangover_cnt_fx, 2)) ) + { + *noisy_speech_HO = 1; + move16(); + } + test(); + test(); + if ( (GE_16(lp_snr,th_clean)) + && (st_fx->Opt_SC_VBR_fx != 0 ) + && (GE_16(st_fx->hangover_cnt_fx, 2) ) ) + { + *clean_speech_HO = 1; + move16(); + } + flag = 1; + move16(); /*HO*/ + } + } + + + /* localVAD and vad_flag for HE-SAD - in parallel with normal localVAD and vad_flag */ + + *localVAD_HE_SAD = 0; + move16(); + + test(); + IF ( (GT_16(snr_sum_HE_SAD, thr1)) + && (EQ_16(flag_he1, 1) ) ) /* Speech present */ + { + + *localVAD_HE_SAD = 1; + move16(); + } + } /* end of WB SWB */ + + /*---------------------------------------------------------------------* + * NB input + * SNR threshold computing + * Hangover control & final VAD decision + *---------------------------------------------------------------------*/ + + ELSE /* NB input */ + { + /* Add localVAD_HE_SAD also for NB operation for use with speech music classifier */ + *localVAD_HE_SAD = 0; + move16(); + if (GT_16(snr_sum_HE_SAD, thr1)) + { + *localVAD_HE_SAD = 1; + move16(); + } + + *localVAD = 0; + move16(); /* safety inits for fx */ + IF ( GT_16(snr_sum,thr1)) /* Speech present, possibly in hangover */ + { + st_fx->nb_active_frames_fx = add(st_fx->nb_active_frames_fx,1); /* Counter of consecutive active speech frames */ + IF ( GE_16(st_fx->nb_active_frames_fx,ACTIVE_FRAMES_FX)) + { + st_fx->nb_active_frames_fx = ACTIVE_FRAMES_FX; + move16(); + st_fx->hangover_cnt_fx = 0; + move16();/* Reset the counter of hangover frames after at least "active_frames" speech frames */ + } + + *localVAD = 1; + move16(); + } + ELSE + { + st_fx->nb_active_frames_fx = 0; + move16(); /* Reset the counter of speech frames necessary to start hangover algorithm */ + /* *localVAD = 0; move16(); */ /* set above */ + } + + thr1_nb_mod = thr1; + move16(); /* thr1 may be adjusted after this point */ + IF( LT_16(st_fx->hangover_cnt_fx,HANGOVER_LONG_NB_FX)) + { + st_fx->hangover_cnt_fx = add(st_fx->hangover_cnt_fx,1); + + IF( LT_16(lp_snr, 4864 )) /*19.0f Q8*/ /* very low SNR */ + { + thr1_nb_mod = sub(thr1_nb_mod , 1331); /*thr1 -= 5.2f;*/ + } + ELSE IF( LT_16(lp_snr, 8960)) /*35 in Q8 */ /* low SNR */ + { + thr1_nb_mod = sub(thr1_nb_mod , 512); /*thr1 -= 2.0f;*/ + } + } + + + thr2 = sub(thr1_nb_mod, 384); /*thr2 = thr1 - 1.5f; , clean speech */ + + /* -dtx condition dependency in noisy speech */ + tmp = 333; + move16(); /* 1.3f; */ + if ( st_fx->Opt_DTX_ON_fx == 0 ) + { + tmp = 282; + move16(); /* 1.10f; */ + } + if (LT_16(lp_snr,th_clean)) + { + thr2 = sub(thr1_nb_mod, tmp); /*thr2 = thr1 - [ 1.10 || 1.3 ];*/ + } + + + flag = 0; + move16(); + IF ( GT_16(snr_sum, thr1_nb_mod)) /* Speech assumed present, even though lowered thr1 */ + { + flag = 1; + move16(); + } + + + + test(); + IF ( (LT_16(snr_sum, thr1_nb_mod)) + && (GT_16(snr_sum, thr2)) ) /* Speech present */ + { + flag = 1; + move16(); + *localVAD = 0; + move16(); + *NB_speech_HO = 1; + move16(); + } + thr1 = thr1_nb_mod ; + move16(); /* needed for st_fx->vadnoise_fx update below */ + } /* end of NB */ + + + + /* *flag_noisy_speech_snr is a Word8 parameter */ + *flag_noisy_speech_snr = 0; + move16(); + IF( vad_bwidth_fx != NB ) + { + if(LT_16(lp_snr, TH16_2_NFLAG_FX )) /*now 27, original threshold: 35dB*/ + { + *flag_noisy_speech_snr = 1; + move16(); + } + } + ELSE + { + if(LT_16(lp_snr, TH8_1_NFLAG_FX )) /* now 20.0 */ + { + *flag_noisy_speech_snr = 1; + move16(); + } + } + + /* SC-VBR */ + st_fx->vadsnr_fx = snr_sum; + move16(); /* for ppp, voiced_enc */ + st_fx->vadnoise_fx = thr1; + move16(); /* used in nb for find_uv */ + + /* Updates */ + st_fx->prim_act_quick_fx = mult_r(26214,st_fx->prim_act_quick_fx); /*Q15 */ + + if(*localVAD != 0) + { + st_fx->prim_act_quick_fx = add(6554,st_fx->prim_act_quick_fx ); /*Q15 */ + } + + st_fx->prim_act_slow_fx = mult_r(32440,st_fx->prim_act_slow_fx); /*Q15 */ + + if(*localVAD != 0) + { + st_fx->prim_act_slow_fx = add(328, st_fx->prim_act_slow_fx ); /*Q15 */ + } + + tmp = st_fx->prim_act_slow_fx; + move16(); + if (LE_16(st_fx->prim_act_quick_fx,st_fx->prim_act_slow_fx)) + { + tmp=st_fx->prim_act_quick_fx; + move16(); + } + /*st->prim_act = 0.1f * tmp + (1.0f-0.1f)* st->prim_act;*/ + st_fx->prim_act_fx = mac_r(L_mult(3277,tmp),29491,st_fx->prim_act_fx); + + + + st_fx->prim_act_quick_he_fx = mult_r(26214,st_fx->prim_act_quick_he_fx); /*Q15 */ + if(*localVAD_HE_SAD != 0) + { + st_fx->prim_act_quick_he_fx = add(6554,st_fx->prim_act_quick_he_fx ); /*Q15 */ + } + + st_fx->prim_act_slow_he_fx = mult_r(32440,st_fx->prim_act_slow_he_fx); /*Q15 */ + if(*localVAD_HE_SAD != 0) + { + st_fx->prim_act_slow_he_fx = add(328, st_fx->prim_act_slow_he_fx ); /*Q15 */ + } + + tmp = st_fx->prim_act_slow_he_fx; + move16(); + if (LE_16(st_fx->prim_act_quick_he_fx,st_fx->prim_act_slow_he_fx)) + { + tmp = st_fx->prim_act_quick_he_fx; + move16(); + } + st_fx->prim_act_he_fx = mac_r(L_mult(3277,tmp),29491,st_fx->prim_act_he_fx); + + + if (L_and(st_fx->L_vad_flag_reg_H_fx, (Word32) 0x40000L) != 0) /* 0x4000L = 0x01L << 18 */ + { + st_fx->vad_flag_cnt_50_fx = sub(st_fx->vad_flag_cnt_50_fx,1); + } + + st_fx->L_vad_flag_reg_H_fx = L_shl(L_and(st_fx->L_vad_flag_reg_H_fx, (Word32) 0x3fffffffL ), 1); + + + if (L_and(st_fx->L_vad_flag_reg_L_fx, (Word32) 0x40000000L) != 0) + { + st_fx->L_vad_flag_reg_H_fx = L_or(st_fx->L_vad_flag_reg_H_fx, 0x01L); + } + + st_fx->L_vad_flag_reg_L_fx = L_shl(L_and(st_fx->L_vad_flag_reg_L_fx, (Word32) 0x3fffffffL ), 1); + + + IF ( flag != 0 ) /* should not include the extra DTX hangover */ + { + st_fx->L_vad_flag_reg_L_fx = L_or(st_fx->L_vad_flag_reg_L_fx, 0x01L); + st_fx->vad_flag_cnt_50_fx = add(st_fx->vad_flag_cnt_50_fx, 1); + } + + + if (L_and(st_fx->L_vad_prim_reg_fx, (Word32) 0x8000L) != 0) /* 0x8000L = 1L << 15 */ + { + st_fx->vad_prim_cnt_16_fx = sub(st_fx->vad_prim_cnt_16_fx,1); + } + + st_fx->L_vad_prim_reg_fx = L_shl(L_and(st_fx->L_vad_prim_reg_fx, (Word32) 0x3fffffffL ), 1); + + IF ( *localVAD != 0 ) + { + st_fx->L_vad_prim_reg_fx = L_or(st_fx->L_vad_prim_reg_fx, 0x01L); + st_fx->vad_prim_cnt_16_fx = add(st_fx->vad_prim_cnt_16_fx,1); + } + + return flag; +} + + + + diff --git a/lib_enc/vad_param_updt_fx.c b/lib_enc/vad_param_updt_fx.c new file mode 100644 index 0000000..68caf7e --- /dev/null +++ b/lib_enc/vad_param_updt_fx.c @@ -0,0 +1,177 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * vad_param_updt() + * + * Update parameters used by VAD + *--------------------------------------------------------------------*/ + +void vad_param_updt_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + Word16 pitch[3], /* i : open loop pitch lag for each half-frame Q0*/ + Word16 voicing[3], /* i : maximum normalized correlation for each half-frame Q15*/ + const Word16 old_pitch1,/* i : OL pitch value from last frame */ + Word16 corr_shift, /* i : correlation shift Q15*/ + Word16 vad_flag, /* i : vad flag Q0*/ + const Word16 Az[] /* i: a coeffs Q12 */ +) +{ + Word16 voice_tmp, pitch_tmp; + Word32 L_tmp; + + + Word16 refl[M+1]; + Word16 tmp1,tmp2; + Word16 tmp_active_flag; + + IF( !st_fx->Opt_AMR_WB_fx ) + { + /* fix explanation + , after function dtx_fx, the "vad_flag" parameter can not be used for SID scheduling purposes any longer + as dtx_fx can schedules active frames even if the initial analyzed vad_flag is 0 ) + in the worst case without the fix an active frame could be classified as SID frame, quite/very unlikley though + */ + tmp1 = vad_flag; + move16(); /* kill MSVC warning */ + tmp_active_flag = 0; + move16(); + test(); + if( (NE_32(st_fx->core_brate_fx, (Word32)SID_2k40))&&(st_fx->core_brate_fx!=0)) /* Note, core_brate_fx can be -1 */ + { + tmp_active_flag = 1; + move16(); /* reqires active coding according to dtx_fx logic */ + } + test(); + test(); + IF( (st_fx->Opt_DTX_ON_fx != 0) && (tmp_active_flag == 0) && ( GT_16(st_fx->ini_frame_fx,3))) + + + { + /* update the counter of consecutive inactive frames in DTX */ + st_fx->consec_inactive_fx = add(st_fx->consec_inactive_fx,1); + IF( GT_16(st_fx->consec_inactive_fx,5)) + { + st_fx->consec_inactive_fx = 5; + move16(); + } + + IF( EQ_16(st_fx->consec_inactive_fx,5)) + { + /* compute spectral tilt parameter */ + a2rc_fx( &Az[1], refl, M ); /* cast to kill MSVC warning */ + /* i: Az in Q12 */ + /* o: refl in Q15 */ + + IF( EQ_16(st_fx->spectral_tilt_reset_fx,1)) + { + st_fx->spectral_tilt_reset_fx = 0; + move16(); + st_fx->running_avg_fx = refl[0]; + move16(); /*Q15*/ + st_fx->ra_deltasum_fx = 0; + move16(); /*Q15*/ + } + + /* st_fx->ra_deltasum_fx += (0.80f * st_fx->running_avg_fx + 0.20f * refl[0]) - st_fx->running_avg_fx; + st_fx->running_avg_fx = 0.80f * st_fx->running_avg_fx + 0.20f * refl[0]; */ + tmp1 = mult(6553, st_fx->running_avg_fx); /* = -0.80f * st_fx->running_avg_fx + st_fx->running_avg_fx*/ + tmp2 = mult(6553, refl[0]); + st_fx->ra_deltasum_fx = add(st_fx->ra_deltasum_fx, sub(tmp2,tmp1)); + move16(); + + tmp1 = mult(26214, st_fx->running_avg_fx); + st_fx->running_avg_fx = add(tmp1,tmp2); + move16(); + + IF( GT_16(abs_s(st_fx->ra_deltasum_fx), 6553)) /*0.2 in Q15*/ + { + st_fx->spectral_tilt_reset_fx = 1; + move16(); + st_fx->running_avg_fx = 0; + move16(); + st_fx->ra_deltasum_fx = 0; + move16(); + st_fx->trigger_SID_fx = 1; + move16(); + } + } + } + ELSE + { + st_fx->trigger_SID_fx = 0; + move16(); + st_fx->consec_inactive_fx = 0; + move16(); + } + + IF( st_fx->trigger_SID_fx == 1 ) + { + IF( st_fx->cng_cnt_fx >= 8 ) + { + /* Declare SID frame due to spectral tilt changes */ + st_fx->cnt_SID_fx = 1; + move16(); + st_fx->core_brate_fx = SID_2k40; + move16(); + st_fx->trigger_SID_fx = 0; + move16(); + } + ELSE IF ( st_fx->core_brate_fx == SID_2k40 ) + { + /* SID fame has already been declared before */ + st_fx->trigger_SID_fx = 0; + move16(); + } + } + } + + + + /* (voicing[0] + voicing[1] + voicing[2]) / 3 + corr_shift */ + L_tmp = L_mult(voicing[0], 10923); + L_tmp = L_mac(L_tmp, voicing[1], 10923); + L_tmp = L_mac(L_tmp, voicing[2], 10923); /*Q15 */ + L_tmp = L_mac(L_tmp, corr_shift, 32767); /*Q15 */ + voice_tmp = round_fx(L_tmp); /*Q15 */ + + /* abs(pitch[0] - *pitO) + abs(pitch[1] - pitch[0]) + abs(pitch[2] - pitch[1]) */ + pitch_tmp = abs_s( sub( pitch[0], old_pitch1 ) ); /*Q0 */ + pitch_tmp = add(pitch_tmp,abs_s(sub(pitch[1],pitch[0]))); /*Q0 */ + pitch_tmp = add(pitch_tmp,abs_s(sub(pitch[2],pitch[1]))); /*Q0 */ + + + /* if( (voicing[0] + voicing[1] + voicing[2]) / 3 + corr_shift > 0.65 && + (short)(abs(pitch[0] - st->pitO) + abs(pitch[1] - pitch[0]) + abs(pitch[2] - pitch[1])) / 3 < 14 ) + { + (st->voiced_burst)++; + } else { + st->voiced_burst = 0; + } */ + + st_fx->voiced_burst_fx = add( st_fx->voiced_burst_fx,1); + move16(); + test(); + if ( ( LE_16(voice_tmp,21299)) /* 0.65 in Q15 */ + || ( GE_16(pitch_tmp,42) ) ) /*3*14 = 42 Q0 */ + { + st_fx->voiced_burst_fx = 0; + move16(); + } + + /* Update previous voicing value for next frame use */ + /* st->voicing_old = (voicing[0] + voicing[1] + voicing[2]) / 3 + corr_shift; */ + st_fx->voicing_old_fx = voice_tmp; + move16(); + + + + return; +} diff --git a/lib_enc/vad_proc.c b/lib_enc/vad_proc.c new file mode 100644 index 0000000..b8554d3 --- /dev/null +++ b/lib_enc/vad_proc.c @@ -0,0 +1,455 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include +#include + + +#include "basop_util.h" +#include "stl.h" +#include "vad_basop.h" +#include "prot_fx.h" +#include "stat_enc_fx.h" +#include "rom_enc_fx.h" + +Word16 vad_init(T_CldfbVadState *vad_state) +{ + Word16 i = 0; + + IF(vad_state == NULL) + { + return -1; + } + + vad_state->frameloop=0; + move16(); + vad_state->continuous_noise_num = 0; + move16(); + vad_state->continuous_speech_num = 0; + move16(); + vad_state->continuous_speech_num2 = 0; + move16(); + vad_state->fg_energy_est_start = L_deposit_l(0); + vad_state->speech_flag = 0; + move16(); + vad_state->frame_sb_energy_scale = 0; + move16(); + vad_state->updateNumWithSnr=0; + move16(); + vad_state->update_count = 0; + move16(); + vad_state->warm_hang_num = 0; + move16(); + + FOR(i = 0; i < SPEC_AMP_NUM; i++) + { + vad_state->smooth_spec_amp[i] = L_deposit_l(0); + } + + FOR(i = 0; i < PRE_SNR_NUM; i++) + { + vad_state->pre_snr[i] = L_deposit_l(0); + } + + FOR(i = 0; i < BG_ENG_NUM; i++) + { + vad_state->frame_sb_energy[i] = L_deposit_l(0); + } + + vad_state->sfm[0] = 28835/* 0.88 Q15 */; + move16(); + vad_state->sfm[1] = 30146/* 0.92 Q15 */; + move16(); + vad_state->sfm[2] = 30146/* 0.92 Q15 */; + move16(); + vad_state->l_silence_snr_count = L_deposit_l(1); + vad_state->l_speech_snr_count = L_deposit_l(1); + vad_state->lt_snr_org = 33554432; + move32(); + vad_state->lf_snr_smooth = 167772155/* 5.0 Q25 */; + move32(); + vad_state->fg_energy = 1073741824; + move32(); + vad_state->fg_energy_scale = 41; + move16(); + + vad_state->bg_energy = 1073741824; + move32(); + vad_state->bg_energy_scale = 57; + move16(); + vad_state->lt_noise_sp_center_diff_counter = L_deposit_l(4); + + vad_state->t_bg_energy = 1374389535; + move32(); + vad_state->scale_t_bg_energy = 37; + move16(); + + vad_state->t_bg_energy_sum.s16Exp = 37; + move16(); + vad_state->t_bg_energy_sum.s32Mantissa = 1374389535; + move32(); + vad_state->tbg_energy_count = 1; + move16(); + vad_state->fg_energy_count = 16; + move16(); + vad_state->bg_energy_count = 16; + move16(); + + vad_state->bg_update_count = 0; + move16(); + vad_state->frame_energy_smooth = 1073741824; + move32(); + vad_state->frame_energy_smooth_scale = 30; + move16(); + vad_state->Q_frames_power_32 = 31; + move16(); + vad_state->lt_bg_highf_eng = 131070/* 2.0 Q16 */; + move16(); + vad_state->lt_noise_sp_center0 = 1841/* 0.4 Q10 */; + move16(); + vad_state->lt_noise_sp_center3 = 2046/* 0.4 Q10 */; + move16(); + vad_state->music_background_rate = 15073/* 0.46 Q15 */; + move16(); + vad_state->tonality_rate3 = 15073/* 0.46 Q15 */; + move16(); + vad_state->lt_noise_sp_center_diff_sum = 409/* 0.4 Q10 */; + move32(); + vad_state->l_silence_snr = 32768/* 0.5 Q16 */; + move32(); + vad_state->l_speech_snr = 327675/* 5.0 Q16 */; + move32(); + + FOR(i = 0; i < SP_CENTER_NUM; i++) + { + vad_state->sp_center[i] = 1228/* 1.2 Q10 */; + move16(); + } + + FOR(i = 0; i < STABLE_NUM; i++) + { + vad_state->ltd_stable_rate[i] = 2294/* 0.07 Q15 */; + move16(); + } + + FOR(i = 0; i < BG_ENG_NUM; i++) + { + vad_state->sb_bg_energy[i] =1374389535; + move32(); + } + vad_state->sb_bg_energy_scale = 37; + move16(); + + vad_state->f_tonality_rate[0] = 7864/* 0.48 Q14 */; + move16(); + vad_state->f_tonality_rate[1] = 7864/* 0.48 Q14 */; + move16(); + vad_state->f_tonality_rate[2] = 7864/* 0.48 Q14 */; + move16(); + + + FOR(i = 0; i < PRE_SPEC_DIF_NUM; i++) + { + vad_state->pre_spec_low_dif[i] = 4095; + move16(); + } + vad_state->scale_spec_low_dif = 12; + move16(); + + FOR (i = 0; i < 56; i++) + { + vad_state->frames_power_32[i] = L_deposit_l(0); + } + + + return 0; +} + + +void UpdateState(T_CldfbVadState *vad_state, + Word16 vad_flag, + Word32 frame_energy, /*(i) current frame energy*/ + Word16 sacle_sbpower, /*(i) the Scaling of current frame energy*/ + Word32 update_flag, /*(i) current frame update flag*/ + Word16 music_backgound_f, /*(i) backgound music flag*/ + Word32 HB_Power, /*(i) current frame high frequency energy*/ + Word16 HB_Power_Q /*(i) the Scaling of current frame high frequency energy*/ + ,Word32 snr + ) +{ + Word16 lt_bg_energy_scal; + Word32 tmp,tmp2; + + + tmp = MUL_F(vad_state->frame_energy_smooth, 31129/* 0.95 Q15 */); + tmp2 = MUL_F(frame_energy, 26214); + vad_state->frame_energy_smooth = VAD_L_ADD(tmp, vad_state->frame_energy_smooth_scale, tmp2, add(4, sacle_sbpower), <_bg_energy_scal); + move32(); + vad_state->frame_energy_smooth_scale = lt_bg_energy_scal; + move16(); + + + IF( vad_flag == 0 ) + { + vad_state->lt_bg_highf_eng = L_add(MUL_F(vad_state->lt_bg_highf_eng, 31130), L_shr(MUL_F(HB_Power, 1638), sub(HB_Power_Q, lt_bg_highf_eng_Q))); + } + + if(LT_16(vad_state->frameloop, 1000)) + { + vad_state->frameloop = add(vad_state->frameloop, 1); + move16(); + } + + background_update(vad_state, + sacle_sbpower, + frame_energy, + update_flag, + music_backgound_f + ,snr + ); + IF( vad_flag== 0) + { + vad_state->continuous_speech_num2 = 0; + move16(); + IF(GT_16(vad_state->continuous_noise_num, 10)) + { + vad_state->continuous_speech_num = 0; + move16(); + } + ELSE IF(GT_32(vad_state->continuous_speech_num, 9)) + { + vad_state->continuous_speech_num = 9; + move16(); + } + vad_state->continuous_noise_num = add(vad_state->continuous_noise_num, 1); + move16(); + + if(GT_16(vad_state->continuous_noise_num, 2048)) + { + vad_state->continuous_noise_num = 2048; + move16(); + } + } + ELSE + { + vad_state->continuous_noise_num = 0; + move16(); + + vad_state->continuous_speech_num2 = add(vad_state->continuous_speech_num2, 1); + vad_state->continuous_speech_num = add(vad_state->continuous_speech_num, 1); + if(GT_16(vad_state->continuous_speech_num, 2048)) + { + vad_state->continuous_speech_num = 2048; + move16(); + } + + if(GT_16(vad_state->continuous_speech_num2, 2048)) + { + vad_state->continuous_speech_num2 = 2048; + move16(); + } + } + +} + + +Word16 vad_proc(T_CldfbVadState *vad_st, + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i: real values */ + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i: imag values */ + Word16 riBuffer_exp, /* i: exponent of real & imag Buffer */ + Word16 *cldfb_addition, /*o: adjust the harmonized hangover */ + Word32 enerBuffer[CLDFB_NO_CHANNELS_MAX], /* i: energy vector per band */ + Word16 enerBuffer_exp, /* i: exponent of energy vector */ + Word16 numBands, /* i: band width 1: NB; 2:WB;3:SWB;4:FB*/ + Word16 vada_flag + ) +{ + Word16 i; + Word16 bandwidth; + Word16 music_backgound_f; + Word16 Q_cldfb; + Word16 frame_energy2_Q, HB_Power_Q; + Word16 sb_power_Q,frame_energy_Q; + Word32 frame_energy, frame_energy2, HB_Power; + Word32 spec_amp[120]; + Word32 update_flag,snr_flux,lt_snr_org,lt_snr,lf_snr; + Word32 snr,tsnr; + Word16 vad_flag; + Word32 *cldfbBufferReal[CLDFB_NO_COL_MAX]; /* dynamic scaling; cldfbBufferReal_float[x][y] = cldfbBufferReal[x][y] * 2^(-Q_cldfb) */ + Word32 *cldfbBufferImag[CLDFB_NO_COL_MAX]; /* dynamic scaling; cldfbBufferImag_float[x][y] = cldfbBufferReal[x][y] * 2^(-Q_cldfb) */ + + + music_backgound_f = 0; + move16(); + frame_energy = 0; + move32(); + + + IF(LT_16(numBands, 20)) + { + bandwidth = 1; + move16(); + } + ELSE IF(LT_16(numBands, 40)) + { + bandwidth = 2; + move16(); + } + ELSE + { + bandwidth = 3; + move16(); + } + + vad_st->bw_index = bandwidth; + move16(); + FOR (i=0; iframe_sb_energy, + &frame_energy2, + &HB_Power, + &frame_energy, + &sb_power_Q, + &frame_energy2_Q, + &HB_Power_Q, + &frame_energy_Q, + &vad_st->frame_sb_energy_scale, + bandwidth + ); + + subband_FFT(cldfbBufferReal, + cldfbBufferImag, + spec_amp, + 0, + &Q_cldfb + ); + + frame_spec_dif_cor_rate(vad_st, spec_amp, + add(Q_cldfb, 8), + vad_st->f_tonality_rate + ); + + spec_center(enerBuffer, + vad_st->sp_center, + bandwidth, + sb_power_Q + ); + + ltd_stable(vad_st, + vad_st->ltd_stable_rate, + frame_energy, + vad_st->frameloop, + frame_energy_Q + ); + + spec_flatness(spec_amp, + vad_st->smooth_spec_amp, + vad_st->sfm + ); + + bg_music_decision(vad_st, + &music_backgound_f, + frame_energy, + frame_energy_Q + ); + + snr_calc(vad_st, + frame_energy2_Q, + &snr, + &tsnr, + frame_energy2, + bandwidth + ); + + calc_snr_flux(tsnr, + vad_st->pre_snr, + &snr_flux + ); + + calc_lt_snr(vad_st, + <_snr_org, + <_snr, + vad_st->fg_energy, + vad_st->fg_energy_count, + vad_st->bg_energy, + vad_st->bg_energy_count, + bandwidth, + vad_st->lt_noise_sp_center0 + ); + + calc_lf_snr(&vad_st->lf_snr_smooth, + &lf_snr, + vad_st->l_speech_snr, + vad_st->l_speech_snr_count, + vad_st->l_silence_snr, + vad_st->l_silence_snr_count, + vad_st->fg_energy_count, + vad_st->bg_energy_count, + bandwidth + ); + + + vad_flag = comvad_decision(vad_st, + lf_snr, + lt_snr_org, + lt_snr, + snr_flux, + snr, + tsnr, + frame_energy2, + music_backgound_f, + frame_energy2_Q, + cldfb_addition, + vada_flag + ); + + + update_flag = update_decision(vad_st, + frame_energy, + HB_Power, + vad_st->frameloop, + bandwidth, + frame_energy_Q, + HB_Power_Q, + snr, + tsnr, + vad_st->vad_flag_for_bk_update, + music_backgound_f + ); + + + UpdateState(vad_st, + vad_st->vad_flag_for_bk_update, + frame_energy2, + frame_energy2_Q, + update_flag, + music_backgound_f, + HB_Power, + HB_Power_Q + ,snr + ); + + + return vad_flag; +} + + + diff --git a/lib_enc/vbr_average_rate_fx.c b/lib_enc/vbr_average_rate_fx.c new file mode 100644 index 0000000..927d890 --- /dev/null +++ b/lib_enc/vbr_average_rate_fx.c @@ -0,0 +1,244 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst_fx.h" /* Common constants */ +#include "prot_fx.h" /* Function prototypes */ +#include "rom_com_fx.h" /* Static table prototypes */ +#include "stat_enc_fx.h" /* Static table prototypes */ +#include "stl.h" + + +#define RATEWIN 600 /* length of the rate control window. This is 600 active speech frames. This equals roughly 12s of active speech */ + +/*=================================================================================*/ +/* FUNCTION : update_average_rate_fx */ +/*---------------------------------------------------------------------------------*/ +/* PURPOSE : SC-VBR update average data rate */ +/*---------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) */ +/*---------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* st_fx->global_avr_rate_fx Q13 */ +/* st_fx->sum_of_rates_fx Q13 */ +/* st_fx->SNR_THLD_fx Q8 */ +/* st_fx->Q_to_F_fx Q0 */ +/* st_fx->pattern_m_fx Q0 */ +/* st_fx->rate_control_fx Q0 */ +/*---------------------------------------------------------------------------------*/ +/*/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*---------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*---------------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*=================================================================================*/ +void update_average_rate_fx( + Encoder_State_fx *st_fx /* i/o: encoder state structure */ +) +{ + Word32 avratetarg_fx; /* target rate for next RATEWIN active frames */ + Word32 target_fx; /* target set by VBR_ADR_MAX_TARGET*RATEWIN*10 */ + Word16 tmp; + Word32 L_tmp; + Word32 L_tmp1,L_tmp2; + + Word16 exp, recip, Qrecip; + + IF ( EQ_16(st_fx->numactive_fx,RATEWIN)) /* goes into rate control only the numactive ==RATEWIN. So rate control is triggered after each RATEWIN avtive frames */ + { + /* after 1000 blocks of RATEWIN frames, we change the way we control the average rate by using + st->global_avr_rate=0.99*st->global_avr_rate+0.01*st->sum_of_rates. This will avoid + veriables growing indefinitely while providing a good long term average rate */ + + IF ( LT_32(st_fx->frame_cnt_ratewin_fx,1000)) + { + st_fx->frame_cnt_ratewin_fx = add(st_fx->frame_cnt_ratewin_fx,1); + + /*st->global_avr_rate = (st->global_avr_rate * (st->global_frame_cnt-1) + st->sum_of_rates) / st->global_frame_cnt; */ + exp = norm_s(st_fx->frame_cnt_ratewin_fx); + tmp = shl(st_fx->frame_cnt_ratewin_fx,exp); + recip = div_s(16384,tmp); + Qrecip = 15-(exp-14); + + IF(GT_32(st_fx->frame_cnt_ratewin_fx,1)) + { + tmp = div_s(sub(st_fx->frame_cnt_ratewin_fx,1),st_fx->frame_cnt_ratewin_fx); /*Q15*/ + L_tmp1 = Mult_32_16(st_fx->global_avr_rate_fx, tmp); /* Q13*Q15 = Q13 */ + + L_tmp2 = Mult_32_16(st_fx->sum_of_rates_fx, recip); /*Q13*Qrecip = 13+Qrecip+1-16 = Qrecip-2 */ + + st_fx->global_avr_rate_fx = L_add(L_tmp1, L_shl(L_tmp2,13-(Qrecip-2))); /*Q13 */ + } + ELSE + { + st_fx->global_avr_rate_fx = st_fx->sum_of_rates_fx; /*handle the first frame*/ + } + /* Q13 */ + } + ELSE + { + /* st->global_avr_rate = 0.01f * st->sum_of_rates + 0.99f * st->global_avr_rate; */ + st_fx->global_avr_rate_fx = L_add(Mult_32_16(st_fx->sum_of_rates_fx,328),Mult_32_16(st_fx->global_avr_rate_fx,32441) ); /*Q13 */ + } + + + IF ( st_fx->sum_of_rates_fx == 0 ) + { + /* st->sum_of_rates = (float) (RATEWIN * VBR_ADR_MAX_TARGET * 10); */ + st_fx->sum_of_rates_fx = L_shl(L_mult0(RATEWIN ,VBR_ADR_MAX_TARGET_x10_Q1 ),12); /*Q13 */ + } + + /* target = VBR_ADR_MAX_TARGET * 10 * RATEWIN; */ + target_fx = L_shl(L_mult0(VBR_ADR_MAX_TARGET_x10_Q1,RATEWIN ),12); /*Q13 */ + + IF ( LT_32(target_fx,st_fx->global_avr_rate_fx)) /* Action is taken to reduce the averge rate. Only initiated if the global rate > target rate */ + { + /* Check the vad snr values to table the noisey/not noisey decision */ + + test(); + IF ( LT_16(st_fx->SNR_THLD_fx , 17152)) /*Q8 */ /* Currently in QFF mode. The bumpup thresholds are slightly relaxed for noisy speech. */ + { + /* Increase the threshold so the the bumpup procedure is done using the noisy thresholds. + Use 3.5 steps to quickly ramp up the rate control to reduce the settling time */ + + /* st->SNR_THLD += 3.5f; */ + st_fx->SNR_THLD_fx = add(st_fx->SNR_THLD_fx , 896 ); /*Q8 */ + } + ELSE IF ( st_fx->mode_QQF_fx == 0 && GT_32(st_fx->sum_of_rates_fx, target_fx)) /* Now SNR_THLD is in the max allowed. Sill the global average is higher and + last RATEWIN frames have a higher agerage than the target rate. Now slightly + more aggresive rate control is used by changing the mode to QQF. Still the + same strict bumpups (more bumpups,higher rate) are used. */ + { + /* Kick in QQF mode */ + st_fx->mode_QQF_fx = 1; + move16(); + } + ELSE IF ( GT_32(st_fx->sum_of_rates_fx , target_fx)) /* Actions (1) and (2) are not sufficient to control the rate. Still the last RATEWIN active + frames have a higher average rate than the target rate. More aggresive rate control is + needed. At this point the rate_control flag is set. This will enable the more relaxed + bump up thresholds (less bump ups->reduced rate)*/ + { + /* Relaxed bump ups are used */ + st_fx->rate_control_fx = 1; + move16(); + /* This will be triggered only if the gloabl average rate is considerablly higher than the target rate. + Keep a higher threshold to avoid short term rate increases over the target rate. */ + IF ( GT_32(st_fx->global_avr_rate_fx ,L_add(target_fx,3440640))) /* Last resort rate control. This is a safer rate control mechanism by increasing NELPS */ + { + st_fx->Last_Resort_fx = 1; + move16(); /* compute based on a larger window as the last resort */ + } + ELSE + { + st_fx->Last_Resort_fx = 0; + move16(); + } + } + ELSE IF ( LT_32(st_fx->sum_of_rates_fx, target_fx )) /* If the average rate of last RATEWIN frames is controlled by above actions, disable the most + aggresive rate control mechanisms. Still keep QQF mode as the global rate is not under + the target rate*/ + { + st_fx->Last_Resort_fx = 0; + move16(); + st_fx->mode_QQF_fx = 1; + move16(); + st_fx->rate_control_fx = 0; + move16(); + } + } + ELSE + { + /* floding back to lesser and leser aggresive rate control mechanisms gradually if global rate is under control */ + st_fx->Last_Resort_fx = 0; + move16(); + + IF ( EQ_16(st_fx->rate_control_fx,1)) + { + st_fx->rate_control_fx = 0; + move16(); + } + ELSE IF ( EQ_16(st_fx->mode_QQF_fx,1)) /* now rate control is not active and still the global rate is below the target. so go to QFF mode */ + { + st_fx->mode_QQF_fx = 0; + move16(); + } + ELSE + { + IF ( GE_16(st_fx->SNR_THLD_fx, 15360)) + { + st_fx->SNR_THLD_fx =sub(st_fx->SNR_THLD_fx ,384 ); /*Q8 */ + } + ELSE + { + st_fx->SNR_THLD_fx = 15360; + move16(); + } + } + } + + IF ( LT_32(st_fx->global_avr_rate_fx , L_sub(target_fx,983040))) /* In QFF mode and global rate is less than target rate-0.2kbps. We can send some Q frames + to F frames to improve the quality */ + { + /* kick in bouncing back from Q to F */ + st_fx->Q_to_F_fx = 1; + move16(); + + /* average rate for next 600ms = global_rate * 2 - rate of the past RATEWIN active frames */ + /* avratetarg = (float)((RATEWIN * 10) * 2 * VBR_ADR_MAX_TARGET - st->global_avr_rate); */ + avratetarg_fx = L_sub(L_shl(L_mult0(RATEWIN ,VBR_ADR_MAX_TARGET_x10_Q1 ),13), st_fx->global_avr_rate_fx ); + /* Q13 */ + + + /* compute the percentage of frames that needed to be sent to F. st->pattern_m is computed as % val * 1000. eg. if % is 10%, then + st->pattern_m=100 . Later this value is used in voiced.enc to bump up 10% of PPP frames to F frames. */ + /* st->pattern_m = (short)(1000 * (avratetarg - 6.15f * RATEWIN * 10)/(10 * RATEWIN * 0.1f) ); */ + + L_tmp = L_mult0(RATEWIN ,VBR_ADR_MAX_TARGET_x10_Q1 ); + L_tmp = L_shl(L_tmp , 12); + L_tmp = L_sub(avratetarg_fx , L_tmp); + tmp = extract_h(L_shl(Mult_32_16(L_tmp,27307),4)); + st_fx->pattern_m_fx =tmp; + move16(); + + if ( st_fx->pattern_m_fx < 0 ) + { + st_fx->pattern_m_fx = 0; + move16(); /* no bump up will ever happen */ + } + + if ( GT_16(st_fx->pattern_m_fx,1000)) + { + st_fx->pattern_m_fx = 1000; + move16();/* 10% of bump ups */ + } + + st_fx->patterncount_fx = 0; + move16(); + } + ELSE + { + st_fx->Q_to_F_fx = 0; + move16(); + } + + st_fx->sum_of_rates_fx = 0; + move16(); + st_fx->numactive_fx = 0; + move16(); + + } + + st_fx->numactive_fx = add(st_fx->numactive_fx,1); + + /* sum the total number of bits (in kbytes) * 10 here */ + /*st->sum_of_rates += (st_fx->core_brate_fx / 1000.0f) * 10; */ + L_tmp = L_shl(Mult_32_16(st_fx->core_brate_fx ,20972),7); + st_fx->sum_of_rates_fx = L_add(st_fx->sum_of_rates_fx ,L_tmp); + + return; +} + diff --git a/lib_enc/vlpc_1st_cod.c b/lib_enc/vlpc_1st_cod.c new file mode 100644 index 0000000..079f387 --- /dev/null +++ b/lib_enc/vlpc_1st_cod.c @@ -0,0 +1,137 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "stl.h" +#include "control.h" +#include "cnst_fx.h" +#include "prot_fx.h" + +#define ISF_ONE 3/*1.0f*1.28f Q1*/ /*=1.0f in 14Q1*1.28*/ + +extern const Word16 dico_lsf_abs_8b[]; + +/*outputs only the weightings, doesn't do anything with the lsfq*/ +static void lsf_weight( + const Word16 *lsfq, /* input: quantized lsf coefficients (14Q1*1.28)*/ + Word16 *w /* output: lsf weighting vector (0Q15) */ +) +{ + Word16 i; + Word16 inv_di0, inv_di1; + + + + /* weighting function */ + /*use the second element as the base to avoid the following division by 0*/ + /*this happens when the ac function is nearly flat*/ + i = lsfq[0]; + move16(); + if (lsfq[0] == 0) + { + i = lsfq[1]; + move16(); + } + inv_di0 = 0x7fff; + move16(); + if (GT_16(i, ISF_ONE)) + { + inv_di0 = div_s(ISF_ONE,i); /*0Q15*/ /*inv_di0 = 1.0f / lsfq[0];*/ + } + + /* Allow saturation during weight calculation, because the values that are + weighted later are used for a minimum search and experimental saturation + avoidance also showed no improvement. */ + BASOP_SATURATE_WARNING_OFF + FOR (i=1; i<(M-2); i+=2) /*for (i=1; i<(M-2); i+=2)*/ + { + inv_di1 = div_s(ISF_ONE,s_max(ISF_ONE, sub(lsfq[i],lsfq[i-1]))); /*0Q15*/ /*inv_di1 = 1.0f / (lsfq[i] - lsfq[i-1]);*/ + w[i-1] = add(inv_di0,inv_di1); + move16(); /*0Q15*/ /*w[i-1] = inv_di0 + inv_di1;*/ + inv_di0 = div_s(ISF_ONE,s_max(ISF_ONE, sub(lsfq[i+1],lsfq[i]))); /*0Q15*/ /*inv_di0 = 1.0f / (lsfq[i+1] - lsfq[i]);*/ + w[i] = add(inv_di1,inv_di0); + move16(); /*0Q15*/ /*w[i] = inv_di1 + inv_di0;*/ + } + inv_di1 = div_s(ISF_ONE, s_max(ISF_ONE, sub(lsfq[i],lsfq[i-1]))); /*inv_di1 = 1.0f / (lsfq[i] - lsfq[i-1]);*/ + w[i-1] = add(inv_di0,inv_di1); + move16(); /*w[i-1] = inv_di0 + inv_di1;*/ + inv_di0 = div_s(ISF_ONE, s_max(ISF_ONE, sub(FREQ_MAX,lsfq[i]))); /*inv_di0 = 1.0f / (FREQ_MAX - lsfq[i]);*/ + w[i] = add(inv_di1,inv_di0); + move16(); /*w[i] = inv_di1 + inv_di0;*/ + + BASOP_SATURATE_WARNING_ON + + + return; +} + +Word16 vlpc_1st_cod( /* output: codebook index */ + const Word16 *lsf, /* input: vector to quantize (14Q1*1.28) */ + Word16 *lsfq /* o: quantized lsf (14Q1*1.28) */ + ,Word16 *wout /* o: lsf weights */ + ,Word16 rf_mode +) +{ + Word16 i, j, index, diff, wdiff; + Word16 w[M]; + Word32 dist_min, dist; + const Word16 *p_dico; + + + + /* weighting */ + lsf_weight(lsf, w);/*lsf:14Q1*1.28=>w:0Q15*/ + IF(EQ_16(rf_mode, 1)) + { + Word16 s; + s = Find_Max_Norm16(w, M); + Scale_sig(w, M, s); + } + Copy(w, wout, M); + /* remove lsf prediction/means */ + + /*dist_min = 1.0e30f;*/ + dist_min = L_add(MAX_32, 0); + p_dico = dico_lsf_abs_8b; /*14Q1*1.28*/ + index = 0; + move16(); + + FOR (i = 0; i < 256; i++) + { + dist = 0; + move32(); + FOR (j = 0; j < M; j++) + { + diff = sub(lsf[j], p_dico[j]); + wdiff = shr(mult_r(w[j],diff),4); + dist = L_mac(dist,wdiff,diff); + } + p_dico += M; + + if (LT_32(dist,dist_min)) + { + index = i; /* store index of new minimum */ + move16(); + } + dist_min = L_min(dist,dist_min); + } + + /* quantized vector */ + p_dico = &dico_lsf_abs_8b[index * M]; + + FOR (j = 0; j < M; j++) + { + /*lsfq[j] += *p_dico++;*/ /* += cause it's differential# + -> since isfq[i] is 0, only data move is sufficient*/ + /*lsfq[j] = add(lsfq[j],*p_dico++);*/ + lsfq[j] = *p_dico++; + move16(); + } + + + return index; +} + + + diff --git a/lib_enc/vlpc_2st_cod.c b/lib_enc/vlpc_2st_cod.c new file mode 100644 index 0000000..75f3d2e --- /dev/null +++ b/lib_enc/vlpc_2st_cod.c @@ -0,0 +1,147 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "cnst_fx.h" +#include "prot_fx.h" +#include "stl.h" +#include "control.h" +#include "basop_util.h" + + +Word16 vlpc_2st_cod( /* output: number of allocated bits */ + const Word16 *lsf, /* input: normalized vector to quantize (14Q1*1.28)*/ + Word16 *lsfq, /* i/o: i:1st stage o:1st+2nd stage (14Q1*1.28)*/ + Word16 *indx, /* output: index[] (4 bits per words) */ + Word16 mode, /* input: 0=abs, >0=rel */ + Word32 sr_core +) +{ + Word16 i, nbits; + Word16 w[M], x[M]; + Word16 nq, xq[M]; + Word32 L_tmp; + Word16 gap; + + + + /* 0 bit with true weighting: save 0.5 bit */ + lsf_weight_2st(lsf, w, 1); /*w:0Q15*1.28*/ + + FOR (i=1; i wops) */ + nbits = 6; /* 2*(2+1) */ move16(); + test(); + IF ( (mode == 0) || (EQ_16(mode,3))) + { + nbits = 10; /* 2*(2+3) */ move16(); + } + ELSE IF (EQ_16(mode,1)) + { + nbits = 2; /* 2*1 */ move16(); + } + + return nbits; + } + + /* weighting from the 1st stage */ + lsf_weight_2st(lsfq, w, mode); + + /* find lsf and scale the residual */ + FOR (i=0; i +#include "prot_fx.h" +#include "cnst_fx.h" +#include "rom_com_fx.h" +#include "stl.h" + +/*-------------------------------------------------------------------* + * Local functions + *--------------------------------------------------------------------*/ +void synthesis_filter_fx (Word16 b[], Word16 x[], Word16 y[], Word16 buf[], + Word16 P, Word16 N ); + + +/*=======================================================================================*/ +/* FUNCTION : ppp_voiced_encoder_fx() */ +/*---------------------------------------------------------------------------------------*/ +/* PURPOSE : */ +/*---------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) delay_fx: open loop pitch, Q6 - WRONG, it is Q0 */ +/* _ (Word16) vadsnr_fx: SNR for current frame Q7 */ +/* _ (Word16) prevCW_lag_fx: Previous lag, Q0 */ +/* _ (Word16 *) in_fx : residual signal (Q_res) */ +/* _ (Word16 *) lpc1_fx : prev frame de-emphasized LPC Q12 */ +/* _ (Word16 *) lpc2_fx : current frame de-emphasized LPC Q12 */ +/* _ (Word16 *) exc_fx : prrevious frame quantized excitation (Q_exc) */ +/* _ (Word16) Q_res: Q factor for res */ +/* _ (Word16) Q_exc: Q factor for exc */ +/*---------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) pitch_fx: floating pitch values for each subframe(Q6) */ +/* _ (Word16*) out_fx: Quantized residual signal (Q0) */ +/* _ Encoder_State_fx *st_fx: */ +/* _ lastLgainE_fx - Q11 */ +/* _ lastHgainE_fx - Q11 */ +/* _ lasterbE_fx - Q13 */ +/*---------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ Encoder_State_fx *st_fx: */ +/* _ st_fx->dtfs_enc_xxxx */ +/* _ a nd b in st_fx->dtfs_enc_Q */ +/* rest all in Q0 */ +/* - bump_up_fx - Q0 */ +/*---------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None. */ +/*---------------------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*=======================================================================================*/ + +void ppp_voiced_encoder_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + Word16 *in_fx, /* i : residual signal */ + Word16 *out_fx, /* o : Quantized residual signal */ + Word16 delay_fx, /* i : open loop pitch */ + Word16 *lpc1_fx, /* i : prev frame de-emphasized LPC */ + Word16* lpc2_fx, /* i : current frame de-emphasized LPC */ + Word16 *exc_fx, /* i: previous frame quantized excitation */ + Word16 *pitch_fx, /* o: floating pitch values for each subframe */ + Word16 vadsnr_fx, /* i: current frame SNR Q7, later shl by 1 for compare */ + Word16 Qres +) +{ + Word16 i; + Word16 spike_near_edge = 0; + Word16 flag; + Word16 delta_lag_E = 0, PPP_MODE_E, Q_delta_lag = 0; + Word16 out_of_bound = 0; + Word16 tmp, tmptmp, tmptmp1; + Word16 pl, l; + Word16 interp_delay[3], temp_pl, temp_l; + Word16 upper_cut_off_freq_of_interest_fx = 0; + Word16 upper_cut_off_freq_of_interest_norm_fx = 0, upper_cut_off_freq_norm_fx = 0; + + Word16 S_fx[PIT_MAX*4+1], C_fx[PIT_MAX*4+1]; + Word16 Qtmpres; + Word32 Ltemp, logLag, Ltemp_q; + Word32 Lacc,Lacc1; + Word16 Ql, Qh,n,sft,flag1; + + Word16 pf_temp1[MAXLAG_WI]; /*maynot need more than MAXLAG_WI/2+1 */ + Word16 pf_temp2[MAXLAG_WI]; + Word16 pf_temp[MAXLAG_WI]; + Word16 pf_n2[MAXLAG_WI]; + Word16 exp,expa,expb,fraca,fracb,scale,frac; + Word32 L_tmp; + + Word16 x_fx; + Word16 impzi_fx[160],impzo_fx[160]; + Word16 exp_ee, frac_ee; + Word16 Qtmp; + Word32 res_enratio_fx =0 ; + Word16 mem_fx[10]; + Word32 energy_impz_fx = 0,tmpres_fx; + Word32 pos_nq0_fx,neg_nq0_fx,Ltmp; + Word32 Ltmp_32, Ltmp1_32, Ltemp1, Ltemp2, Ltemp_fx; + Word16 Qadj; + + Word32 tmp_fx = 0,sp_hb_enratio_fx = 0,sp_enratio_fx = 0; + Word32 low_band_en_fx; + Word32 curr_Engy,prev_Engy; + Word16 temp_Fs; + + + DTFS_STRUCTURE_FX *CURRP_NQ_FX = DTFS_new_fx(); + DTFS_STRUCTURE_FX *TMPDTFS_FX = DTFS_new_fx(); + DTFS_STRUCTURE_FX *TMPDTFS2_FX = DTFS_new_fx(); + DTFS_STRUCTURE_FX *TMPDTFS3_FX = DTFS_new_fx(); + DTFS_STRUCTURE_FX *CURRP_Q_E_FX = DTFS_new_fx(); + DTFS_STRUCTURE_FX *dtfs_temp_fx = DTFS_new_fx(); + + + + temp_Fs = 8000; + move16(); + + if ( EQ_16( st_fx->bwidth_fx, WB)) + { + temp_Fs = 16000; + move16(); + } + + test(); + IF (EQ_16(st_fx->bwidth_fx,WB)||EQ_16(st_fx->bwidth_fx,SWB)) + { + upper_cut_off_freq_of_interest_fx = 4000; + move16(); + upper_cut_off_freq_of_interest_norm_fx = 10240; + move16();/*value normalized by 12800 */ + upper_cut_off_freq_norm_fx = 16384; + move16();/*value normalized by 12800 */ + } + ELSE IF (EQ_16(st_fx->bwidth_fx,NB)) + { + upper_cut_off_freq_of_interest_fx = 3300; + move16(); + upper_cut_off_freq_of_interest_norm_fx = 8448; + move16();/*value normalized by 12800 */ + upper_cut_off_freq_norm_fx = 10240; + move16();/*value normalized by 12800 */ + } + + /* Initialization */ + IF (st_fx->firstTime_voicedenc_fx) + { + st_fx->firstTime_voicedenc_fx = 0; + move16(); + st_fx->dtfs_enc_lag_fx = 0; + move16(); + st_fx->dtfs_enc_nH_fx = 0; + move16(); + st_fx->dtfs_enc_nH_4kHz_fx = 0; + move16(); + st_fx->dtfs_enc_upper_cut_off_freq_of_interest_fx = 3300; + move16(); + st_fx->dtfs_enc_upper_cut_off_freq_fx = 4000; + move16(); + set16_fx(st_fx->dtfs_enc_a_fx, 0, MAXLAG_WI); + set16_fx(st_fx->dtfs_enc_b_fx, 0, MAXLAG_WI); + } + test(); + /* Figure out the PPP_MODE */ + IF ( EQ_16(st_fx->last_ppp_mode_fx,1)&&!st_fx->mode_QQF_fx) + { + st_fx->bump_up_fx = 1; + move16(); + free(CURRP_NQ_FX); + free(TMPDTFS_FX); + free(TMPDTFS2_FX); + free(TMPDTFS3_FX); + free(CURRP_Q_E_FX); + free(dtfs_temp_fx); + return; + } + + /* Use the aggresive bumpups if there are two consecutive Q frames */ + /* Aggresive bump upsare only used in the second Q frame */ + if ( st_fx->last_ppp_mode_fx == 1 ) + { + st_fx->rate_control_fx = 0; + } + + PPP_MODE_E = 'Q'; + move16(); + + pl = s_min(MAX_LAG_PIT, rint_new_fx(L_shl(st_fx->old_pitch_buf_fx[(2*NB_SUBFR)-1],10))); + move16(); + l = s_min(MAX_LAG_PIT, rint_new_fx(L_deposit_h(delay_fx))); + move16(); + /* st_fx->old_pitch_buf_fx in Q6*/ + + /* Bump up if the lag is out_fx of range */ + test(); + IF (GT_16(sub(l,pl),13)||LT_16(sub(l,pl),-11)||LT_16(l,19)||LT_16(pl,19)) + { + st_fx->bump_up_fx = 1; + move16(); + free(CURRP_NQ_FX); + free(TMPDTFS_FX); + free(TMPDTFS2_FX); + free(TMPDTFS3_FX); + free(CURRP_Q_E_FX); + free(dtfs_temp_fx); + return; + } + + IF (NE_16(st_fx->last_ppp_mode_fx,1)) + { + /* Obtain DTFS of last pl values of past excitation */ + GetSinCosTab_fx(pl,S_fx,C_fx); + DTFS_to_fs_fx(exc_fx-pl, pl, dtfs_temp_fx, temp_Fs, 0,S_fx,C_fx); + } + + if (EQ_16(st_fx->last_coder_type_raw_fx,UNVOICED)) + { + pl = l; + move16(); /* if prev frame was sil/uv */ + } + + /* Use the out_fx array as a temp storage for currp */ + spike_near_edge = ppp_extract_pitch_period_fx(in_fx, out_fx, l, &out_of_bound,Qres) ; + move16(); + /* out_fx in Qres */ + + IF (out_of_bound == 1) + { + st_fx->bump_up_fx = 1; + move16(); + free(CURRP_NQ_FX); + free(TMPDTFS_FX); + free(TMPDTFS2_FX); + free(TMPDTFS3_FX); + free(CURRP_Q_E_FX); + free(dtfs_temp_fx); + return; + } + + /* Get DTFS of current prototype */ + GetSinCosTab_fx(l,S_fx,C_fx); + + DTFS_to_fs_fx(out_fx, l, CURRP_NQ_FX, temp_Fs, 0,S_fx,C_fx); + /* This requires input out_fx in Q0, but currently in Qres */ + + /* Ensure the extracted prototype is time-synchronous to the + * last l samples of the frame. This proves to eliminate + * some of the PPP-CELP transition problems. + * Convert last samples into DTFS */ + IF (spike_near_edge != 0) + { + /* These two function calls are combined in one call DTFS_alignment_extract_td_fx() */ + /* DTFS_to_fs(in+L_FRAME-l, l, TMPDTFS,(short) st->input_Fs,0); */ + /* tmp = DTFS_alignment_extract(*TMPDTFS, *CURRP_NQ, 0.0, lpc2) ; */ + tmp = DTFS_alignment_extract_td_fx(out_fx, in_fx+L_FRAME-l, l) ; + move16(); /*Q0 */ + tmp = negate(shl(tmp,2));/*Q2 */ + Q2phaseShift_fx(CURRP_NQ_FX, tmp, l, S_fx,C_fx) ; + /* output CURRP_NQ is correct */ + } + temp_pl = pl; + move16(); + temp_l = l; + move16(); + + FOR(i = 0; i < NB_SUBFR; i++) + { + /* do the linear pitch_fx interp to drive the nb_post_filt */ + Interpol_delay_fx(interp_delay, temp_pl, temp_l, i, frac_4sf_fx); /* interp_delay in Q4 */ + pitch_fx[i] = shl(interp_delay[0],2); + move16();/* pitch_fx in Q6 */ + } + curr_Engy=DTFS_getEngy_P2A_fx(CURRP_NQ_FX); /*2Q where Q=CURRP_NQ_FX->Q */ + + /* Restoring PPP memories when the last frame is non-PPP */ + IF (NE_16(st_fx->last_ppp_mode_fx,1)) + { + + st_fx->ph_offset_E_fx = 0 ; + move16(); + + /* st->prev_cw_en = DTFS_getEngy(*dtfs_temp); */ + Lacc=DTFS_getEngy_P2A_fx(dtfs_temp_fx); /*2Q where Q = dtfs_temp_fx->Q */ + + + prev_Engy = L_add(Lacc, 0); + + st_fx->Q_prev_cw_en_fx=norm_l(Lacc); /* = K = headroom */ + + /*st_fx->Q_prev_cw_en_fx = (Lacc==0)?31: st_fx->Q_prev_cw_en_fx; */ + if (Lacc==0) + { + st_fx->Q_prev_cw_en_fx = 31; + move16(); + } + + st_fx->prev_cw_en_fx=(Word32) L_shl(Lacc,st_fx->Q_prev_cw_en_fx); /*2Q+K */ + st_fx->Q_prev_cw_en_fx = add(st_fx->Q_prev_cw_en_fx,shl(dtfs_temp_fx->Q,1)); + /* st_fx->Q_prev_cw_en_fx = 2*(dtfs_temp_fx->Q) + K */ + + DTFS_copy_fx(TMPDTFS_FX,*dtfs_temp_fx); /* output = TMPDTFS_FX */ + + DTFS_car2pol_fx(TMPDTFS_FX); + + logLag=log10_fx(TMPDTFS_FX->lag_fx); /* logLag=10*log10(pl), Q23 */ + Ltemp_q=L_shl(L_mult(shl(TMPDTFS_FX->Q,1),24660),9); /* Ltemp_q=2Q*10log10(2), Q23 */ + + /* Process low band */ + Ltemp=DTFS_setEngyHarm_fx(236,2828,0,2828, 1, 0, &Ql,TMPDTFS_FX);/* Q of Ltemp = 2*(TMPDTFS_FX->Q) = Ql ? */ + /* Compensate for Q factor of energy to get log10(lag*eng) */ + Ltemp=log10_fx(Ltemp); /* Ltemp=10log10(eng), Q23 */ + Ltemp=L_add(L_sub(Ltemp,Ltemp_q),logLag); /* Ltemp=10*log10(lag*eng), Q23 */ + /*st_fx->lastLgainE_fx=round_fx(L_shl((Word32)Mpy_32_16(extract_h(Ltemp),extract_l(Ltemp),0x6666),1)); // Q11, 0x6666 = 0.1 in Q18 */ + st_fx->lastLgainE_fx=round_fx(L_shl(Mult_32_16(Ltemp,0x6666),1)); /* Q11, 0x6666 = 0.1 in Q18 */ + + + /* Process high band */ + Ltemp=DTFS_setEngyHarm_fx(2828,upper_cut_off_freq_of_interest_norm_fx,2828,upper_cut_off_freq_norm_fx, 1, 0, &Qh,TMPDTFS_FX); + Ltemp=log10_fx(Ltemp); + Ltemp=L_add(L_sub(Ltemp,Ltemp_q),logLag); /* Ltemp=10*log10(lag*eng), Q23 */ + st_fx->lastHgainE_fx=round_fx(L_shl(Mult_32_16(Ltemp,0x6666),1)); /* Q11 */ + + /* Need to unify the Q factors of both bands */ + TMPDTFS_FX->Q=s_min(Ql,Qh); + move16();/* set Q factor to be the smaller one of Ql and Qh */ + n=sub(Ql,Qh); /* compare band Q factors */ + + IF (n<0) + { + rshiftHarmBand_fx(TMPDTFS_FX,2828, upper_cut_off_freq_norm_fx,n); + } + ELSE IF (n>0) + { + rshiftHarmBand_fx(TMPDTFS_FX,0, 2828, sub(Qh,Ql)); + } + + DTFS_to_erb_fx(*TMPDTFS_FX,st_fx->lasterbE_fx); /* output lasterbE_fx in Q13 */ + Lacc1 = L_max(prev_Engy, 1); + } + ELSE + { + /* Copy DTFS related parameters from 'st_fx' to 'dtfs_temp' structure */ + dtfs_temp_fx->lag_fx = st_fx->dtfs_enc_lag_fx; + move16(); + dtfs_temp_fx->nH_fx = st_fx->dtfs_enc_nH_fx; + move16(); + dtfs_temp_fx->nH_4kHz_fx = st_fx->dtfs_enc_nH_4kHz_fx; + move16(); + dtfs_temp_fx->upper_cut_off_freq_of_interest_fx = st_fx->dtfs_enc_upper_cut_off_freq_of_interest_fx; + move16(); + dtfs_temp_fx->upper_cut_off_freq_fx = st_fx->dtfs_enc_upper_cut_off_freq_fx; + move16(); + + Copy(st_fx->dtfs_enc_a_fx, dtfs_temp_fx->a_fx, MAXLAG_WI); + Copy(st_fx->dtfs_enc_b_fx, dtfs_temp_fx->b_fx, MAXLAG_WI); + + dtfs_temp_fx->Q = st_fx->dtfs_enc_Q; + move16(); + Lacc1=DTFS_getEngy_P2A_fx(dtfs_temp_fx); + prev_Engy = L_add(Lacc1, 0); + } + + /*-----Open-loop Bump-Up-------- */ + + /* Energy ratio calculation in_fx residual and speech domain */ + /* Also, compute correlation between the previous and the */ + /* current prototype */ + + /* res_enratio = DTFS_getEngy(*CURRP_NQ) / DTFS_getEngy(*dtfs_temp); */ + Lacc = L_add(curr_Engy, 0); + /* Lacc1 has been handled above */ + + sft=add(shl(sub(CURRP_NQ_FX->Q,dtfs_temp_fx->Q),1),4); + IF (sft>0) + { + if (LT_32(Lacc1,L_shr(Lacc,sft))) + { + res_enratio_fx=0x7FFF; + move16(); + } + } + ELSE + { + if (LT_32(L_shr(Lacc1,negate(sft)),Lacc)) + { + res_enratio_fx=0x7FFF; + move16(); + } + } + /* max value res_enratio compared against is 0x7400 (14.5 in Q11) */ + + IF (NE_32(res_enratio_fx,0x7FFF)) + { + + expb = norm_l(Lacc); + fracb = extract_h(L_shl(Lacc,expb)); + expb = sub(30,add(expb, shl(CURRP_NQ_FX->Q, 1))); + + + expa = norm_l(Lacc1); + fraca = extract_h(L_shl(Lacc1,expa)); + expa = sub(30, add(expa, shl(dtfs_temp_fx->Q, 1))); + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); + exp = sub(expb,expa); + res_enratio_fx = shl(tmp,sub(exp,4)); + } + /* res_enratio_fx is Q11 */ + + /* Copy over CURRP_NQ into TMPDTFS */ + DTFS_copy_fx(TMPDTFS_FX, *CURRP_NQ_FX); /* output = TMPDTFS_FX with Q = CURRP_NQ_FX->Q */ + + /* Copy over dtfs_temp into TMPDTFS2 */ + DTFS_copy_fx(TMPDTFS2_FX, *dtfs_temp_fx); /* output = TMPDTFS2_FX with Q = dtfs_temp_fx->Q */ + + tmptmp = DTFS_alignment_full_fx(*TMPDTFS2_FX,*TMPDTFS_FX,st_fx->ph_offset_E_fx,S_fx,C_fx + , 0 + ); + + tmptmp1 = sub(shl(TMPDTFS_FX->lag_fx,1), tmptmp);/* (C_l-tmptmp) , Q1 */ + + Q2phaseShift_fx(TMPDTFS_FX, negate(shl(tmptmp1,1)), TMPDTFS_FX->lag_fx,S_fx,C_fx); /* fixed bug , phase shift by tmp computed in_fx TMP.lag domain (above) */ + + /*tmpres = (float)(DTFS_freq_corr(*TMPDTFS, *TMPDTFS2, 100.0f, 3700.0f));*/ + tmpres_fx = DTFS_freq_corr_fx(*TMPDTFS_FX, *TMPDTFS2_FX, 100, 3700, &Qtmpres); /* tmpres_fx has Q factor tmpres */ + + + + poleFilter_setup_fx(lpc2_fx, M+1, *TMPDTFS_FX, S_fx, C_fx, pf_temp1, pf_temp2, pf_temp, pf_n2); + DTFS_poleFilter_fx_9(TMPDTFS_FX, pf_temp1, pf_temp2, pf_temp, pf_n2); + /* lpc2_fx in Q12 */ + + DTFS_adjustLag_fx(TMPDTFS2_FX, TMPDTFS_FX->lag_fx); /* operate in_fx CL domain */ + + DTFS_poleFilter_fx(TMPDTFS2_FX,lpc1_fx,M+1, S_fx, C_fx); /* lpc1_fx in Q12 */ + + tmp_fx = DTFS_freq_corr_fx(*TMPDTFS_FX, *TMPDTFS2_FX, 100, 3700, &Qtmp); + /* tmp_fx Q = Qtmp */ + + + /******************************************************************************* + if ( DTFS_getEngy(*TMPDTFS2) > 0 ) + { + sp_enratio = DTFS_getEngy(*TMPDTFS)/DTFS_getEngy(*TMPDTFS2); + } + else + { + sp_enratio = 0.0f; + } + *******************************************************************************/ + Ltmp_32 = (DTFS_getEngy_fx(TMPDTFS2_FX)); /* Output Q=2*(TMPDTFS2_FX->Q) */ + IF ( Ltmp_32 > 0 ) + { + /*sp_enratio = DTFS_getEngy(*TMPDTFS)/DTFS_getEngy(*TMPDTFS2); in Q15 */ + Lacc=DTFS_getEngy_P2A_fx(TMPDTFS_FX); + Lacc1=Ltmp_32; + /* IF (L_sub(sp_enratio_fx,0x7FFF)!=0) */ + { + expb = norm_l(Lacc); + fracb = extract_h(L_shl(Lacc,expb)); + + expb = sub(30, add(expb, shl(TMPDTFS_FX->Q, 1))); + + expa = norm_l(Lacc1); + fraca = extract_h(L_shl(Lacc1,expa)); + + expa = sub(30, add(expa, shl(TMPDTFS2_FX->Q, 1))); + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); + exp = sub(expb,expa); + sp_enratio_fx = L_shl(tmp, exp); /* Q15 */ + } + } + ELSE + { + sp_enratio_fx = L_deposit_l(0);/* Q15 */ + } + + /*******************************************************************************/ + IF (EQ_16(PPP_MODE_E,'Q')) + { + /* Bump up if the lag is out_fx of range */ + test(); + IF (GT_16(sub(l,pl),13)||LT_16(sub(l,pl),-11)) + { + PPP_MODE_E = 'B' ; + move16(); + } + ELSE + { + delta_lag_E= sub(l,pl); + } + + /* Bump up if big change between the previous and the current CWs */ + IF ( LT_16(shl(vadsnr_fx,1) ,st_fx->SNR_THLD_fx)) /*Q8 */ + { + /*if ( res_enratio > 5.0 && tmp < 0.65 ) */ + /* 5 in Q11, 0.65 in Q15 // L_shl(tmp_fx,sub(31,Qtmp)) makes tmp_fx FIXED Q31 */ + test(); + IF ((GT_32(res_enratio_fx,10240))&&(LT_16(extract_h(L_shl(tmp_fx,sub(31,Qtmp))),21299))) + { + PPP_MODE_E = 'B'; + move16(); + } + } + ELSE + { + /* if ( res_enratio > 3.0 && tmp < 1.2 ) */ + /*3 in Q11, 1.2 in Q14 // L_shl(tmp_fx,sub(31,Qtmp)) makes tmp_fx FIXED Q14 */ + test(); + IF ( (GT_32(res_enratio_fx,6144))&&(LT_16(extract_h(L_shl(tmp_fx,sub(30,Qtmp))),19661))) + { + PPP_MODE_E = 'B'; + move16(); + } + } + } + + /* Rapid rampdown frame where time resolution is important */ + /* Not a suitable PPP frame -> Bump to CELP */ + + IF ( LT_16(shl(vadsnr_fx,1) ,st_fx->SNR_THLD_fx)) /*Q8 */ + { + /* if (res_enratio < 0.025) */ + IF (LT_32(L_shl(res_enratio_fx,4),819)) /*0x0333 = 0.025 in Q15, res_enratio_fx in Q15 after shl 4 */ + { + st_fx->bump_up_fx = 1; + move16(); + free(CURRP_NQ_FX); + free(TMPDTFS_FX); + free(TMPDTFS2_FX); + free(TMPDTFS3_FX); + free(CURRP_Q_E_FX); + free(dtfs_temp_fx); + return; + } + } + ELSE + { + /* if ( res_enratio < 0.092f) */ + if ( LT_32(L_shl(res_enratio_fx,4), 3015))/*3015 = 0.092 in Q15, res_enratio_fx in Q15 after shl 4 */ + { + st_fx->bump_up_fx = 1; + move16(); + } + } + + /* if (min(res_enratio, sp_enratio) < 0.075 && tmp < -0.5f)) : 2458 = 0.075 in Q15 */ + test(); + if ( LT_32(L_min(L_shl(res_enratio_fx,4), sp_enratio_fx), 2458)&<_32(tmp_fx,shl(-1,sub(Qtmp,1)))) + { + st_fx->bump_up_fx = 1; + move16(); + } + + /* Rapid rampup frame where time resolution is important */ + /* Not a suitable PPP frame -> Bump to CELP */ + IF ( LT_16(shl(vadsnr_fx,1) ,st_fx->SNR_THLD_fx)) /*Q8 */ + { + IF (GT_32(res_enratio_fx,29696)) /*14.5 in Q11 */ + { + st_fx->bump_up_fx = 1; + move16(); + free(CURRP_NQ_FX); + free(TMPDTFS_FX); + free(TMPDTFS2_FX); + free(TMPDTFS3_FX); + free(CURRP_Q_E_FX); + free(dtfs_temp_fx); + return; + } + } + ELSE + { + if (GT_32(res_enratio_fx,14336)) /* 7.0 in Q11 */ + { + st_fx->bump_up_fx = 1; + move16(); + } + } + + IF ( st_fx->bump_up_fx == 1 ) + { + free(CURRP_NQ_FX); + free(TMPDTFS_FX); + free(TMPDTFS2_FX); + free(TMPDTFS3_FX); + free(CURRP_Q_E_FX); + free(dtfs_temp_fx); + return; + } + + /* Bump up when the previous frame is an unvoiced or a silent frame */ + IF (EQ_16(st_fx->last_coder_type_raw_fx,UNVOICED)) + { + st_fx->bump_up_fx = 1; + move16(); + free(CURRP_NQ_FX); + free(TMPDTFS_FX); + free(TMPDTFS2_FX); + free(TMPDTFS3_FX); + free(CURRP_Q_E_FX); + free(dtfs_temp_fx); + return; + } + /* -----End Open-loop Bump-Up */ + + /* PPP-WI Quantization */ + IF (EQ_16(PPP_MODE_E,'Q')) + { + flag = 1; + move16(); + IF (EQ_16(PPP_MODE_E,'Q')) + { + flag = ppp_quarter_encoder_fx(CURRP_Q_E_FX, TMPDTFS_FX, dtfs_temp_fx->lag_fx, *CURRP_NQ_FX, + lpc2_fx, &st_fx->lastLgainE_fx, &st_fx->lastHgainE_fx, st_fx->lasterbE_fx, *dtfs_temp_fx, S_fx, C_fx, st_fx); + move16(); + } + + IF (flag) + { + /* TMPDTFS : Target prototype: Amp Quantized + Phase Unquantized */ + /* TMPDTFS2: Quantized prototype: Amp Quantized + Phase Quantized */ + /* TMPDTFS3: Delta prototype: Diff betw. target and quant. in_fx speech dom */ + + /* ----- Closed-loop Bump-Up ---------- */ + Word32 pos_nq_fx, neg_nq_fx,pos_q_fx,neg_q_fx; + Word16 Qposnq, Qnegnq, Qposq,Qnegq; + + DTFS_peaktoaverage_fx(*TMPDTFS_FX,&pos_nq_fx,&Qposnq,&neg_nq_fx,&Qnegnq); + DTFS_peaktoaverage_fx(*CURRP_Q_E_FX, &pos_q_fx, &Qposq,&neg_q_fx,&Qnegq); + + + /* Before we perform the peak-to-average ratio comparison, we have to */ + /* ensure that the energy is not decaying and also the pitch_fx pulse */ + /* is clearly defined */ + + /* Usually triggers in the slow ramp down frames. Does not fall under the test condition (res_enratio < 0.025) as + both frames have little energy and the ratio is not very small. Not suitable for PPP */ + + IF ( GT_16(CURRP_Q_E_FX->upper_cut_off_freq_fx , 4000)) + { + Ltemp2 = DTFS_getEngy_band_wb_fx(*CURRP_Q_E_FX, 0, 2000); + /* Use this bump-up only for WB signals */ + IF ( Ltemp2 > 0 ) + { + /* sp_hb_enratio = DTFS_getEngy_band_wb(*CURRP_Q_E, 2000.0, 6400.0)/DTFS_getEngy_band_wb(*CURRP_Q_E, 0.0, 2000.0); */ + Ltemp1 = DTFS_getEngy_band_wb_fx(*CURRP_Q_E_FX, 2000, 6400);/*Q13 */ + /*sp_hb_enratio_fx = divide_dp(Ltemp1,Ltemp2,0, 1);//Q29 */ + Qadj = 0; + move16(); + /*----------------------------------------------------------*/ + /* Ltemp_fx = (Word32)divide_dp(Ltemp1, Ltemp2, Qadj,1); Q29*/ + /*----------------------------------------------------------*/ + if(Ltemp1<0) + { + Ltemp1 = L_negate(Ltemp1); + } + expa = norm_l(Ltemp2); + fraca = extract_h(L_shl(Ltemp2,expa)); + expa = sub(30,expa); + + expb = norm_l(Ltemp1); + fracb = round_fx(L_shl(Ltemp1,expb)); + expb = sub(30, add(expb, Qadj)); + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); + exp = sub(expb,expa); + Ltemp_fx = L_shl(tmp, add(exp,14)); + /*-------------------------------------------*/ + sp_hb_enratio_fx = L_add(Ltemp_fx, 0); /* Q29 */ + } + ELSE + { + sp_hb_enratio_fx = L_deposit_l(0); + } + low_band_en_fx = Ltemp2; /*Q13 */ + + /* if ( low_band_en < 25.0f && sp_hb_enratio < 1.6f ) */ + /* 25.0 in Q13 = 204800, 1.6 in Q29 = 858993459 */ + test(); + IF ( LT_32(low_band_en_fx , 204800 )&<_32(sp_hb_enratio_fx,858993459)) + { + PPP_MODE_E = 'B'; + move16(); + } + } + + Ltmp_32=DTFS_getEngy_fx(CURRP_NQ_FX); /*Q = 2*(CURRP_NQ_FX->Q) */ + Qadj = sub(st_fx->Q_prev_cw_en_fx, shl(CURRP_NQ_FX->Q, 1)); + + Ltmp_32 = L_shl(Ltmp_32,Qadj); /* shift left required to adjust Q of CURRP_NQ_FX = Q_prev_cw_en_fx */ + + /* Ltmp1_32 = 0.8f * st->prev_cw_en */ + Ltmp1_32 = Mult_32_16(st_fx->prev_cw_en_fx,26214); /* Q = (Q_prev_cw_en_fx + Q15+1)-Q16 = Q_prev_cw_en_fx */ + + IF ( LT_16(shl(vadsnr_fx,1) ,st_fx->SNR_THLD_fx)) /*Q8 */ + { + /* if ( DTFS_getEngy(*CURRP_NQ) > 0.8f * st->prev_cw_en && max(pos_nq, neg_nq) > 3.0f && st->rate_control ) */ + /* pos_nq_fx and neg_nq_fx in Q28 ???? */ + test(); + test(); + IF ( GT_32( Ltmp_32, Ltmp1_32)&>_32(L_max(pos_nq_fx,neg_nq_fx),805306368)&&st_fx->rate_control_fx) + { + /*if ( pos_nq > neg_nq && pos_nq > 2.0f * pos_q ) */ + test(); + IF ( GT_32(pos_nq_fx , neg_nq_fx)&>_32(Mult_32_16(pos_nq_fx,16384),pos_q_fx)) + { + PPP_MODE_E = 'B'; + move16(); + } + + test(); + /*if ( pos_nq < neg_nq && neg_nq > 2.0f * neg_q ) */ + IF ( LT_32(pos_nq_fx , neg_nq_fx)&>_32(Mult_32_16(neg_nq_fx,16384),neg_q_fx)) + { + PPP_MODE_E = 'B'; + move16(); + } + } + } + + ELSE + { + /* if ((((DTFS_getEngy(*CURRP_NQ) >(st->prev_cw_en))&&(max(pos_nq,neg_nq)>3.5))&&(st->rate_control))|| */ + /* (((DTFS_getEngy(*CURRP_NQ) >0.8*(st->prev_cw_en))&&(max(pos_nq,neg_nq)>3.0))&&(!st->rate_control))) */ + test(); + test(); + test(); + test(); + test(); + IF ((((L_sub(Ltmp_32 ,(st_fx->prev_cw_en_fx)>0))&&(GT_32(L_max(pos_nq_fx,neg_nq_fx),939524096)))&&(st_fx->rate_control_fx))|| + (((GT_32( Ltmp_32, Ltmp1_32) ) && (GT_32(L_max(pos_nq_fx,neg_nq_fx),805306368)))&&(!st_fx->rate_control_fx))) + { + /* if (((pos_nq > neg_nq) && (pos_nq > 2.5*pos_q)&&(st->rate_control))|| + ((pos_nq > neg_nq) && (pos_nq > 2.0*pos_q)&&(!st->rate_control))) */ + test(); + test(); + test(); + test(); + test(); + IF ((GT_32(pos_nq_fx , neg_nq_fx)&>_32(Mult_32_16(pos_nq_fx,13107),pos_q_fx)&&(st_fx->rate_control_fx))|| + (GT_32(pos_nq_fx , neg_nq_fx) && GT_32(Mult_32_16(pos_nq_fx,16384),pos_q_fx) && (!st_fx->rate_control_fx))) + { + PPP_MODE_E='B'; + move16(); + } + + /* if ((((pos_nq < neg_nq) && (neg_nq > 2.5*neg_q))&&(st->rate_control))|| + ((pos_nq < neg_nq) && (neg_nq > 2.0*neg_q)&&(!st->rate_control))) */ + test(); + test(); + test(); + test(); + test(); + IF ((LT_32(pos_nq_fx , neg_nq_fx)&>_32(Mult_32_16(neg_nq_fx,13107),neg_q_fx)&&(st_fx->rate_control_fx))|| + (LT_32(pos_nq_fx , neg_nq_fx) && GT_32(Mult_32_16(neg_nq_fx,16384),neg_q_fx) && (!st_fx->rate_control_fx))) + { + PPP_MODE_E='B'; + move16(); + } + } + + + IF ( st_fx->rate_control_fx ) + { + + DTFS_peaktoaverage_fx(*CURRP_NQ_FX,&pos_nq0_fx,&Qposnq,&neg_nq0_fx,&Qnegnq); + + impzi_fx[0]=1; + move16(); + FOR (x_fx=1; x_fx<160; x_fx++) + { + impzi_fx[x_fx]=0; + move16(); + } + + FOR (x_fx=0; x_fx<160; x_fx++) + { + impzo_fx[x_fx]=0; + move16(); + } + + FOR (x_fx=0; x_fx<10; x_fx++) + { + mem_fx[x_fx]=0; + move16(); + } + + /* lpc2_fx in Q12, so Qadj is set to 3 toi bring it to Q15 */ + Qadj = 15-12; + move16(); + synthesis_filter_fx(lpc2_fx,&impzi_fx[0],&impzo_fx[0],&mem_fx[0],10,160 ); + + /* compute energy of impz */ + FOR (x_fx=0; x_fx<160; x_fx++) + { + energy_impz_fx = L_add(energy_impz_fx , L_mult0(impzo_fx[x_fx],impzo_fx[x_fx])); + } + + /*energy_impz = (float)(10*log10((float)energy_impz)); */ + exp_ee = norm_l(energy_impz_fx); + frac_ee = Log2_norm_lc(L_shl(energy_impz_fx, exp_ee)); + exp_ee = sub(30, exp_ee); /*30-exp-Q0 */ + Ltmp = Mpy_32_16(exp_ee, frac_ee, LG10); /* Ltmp Q14 */ + energy_impz_fx =L_shr(Ltmp, 3); /* 16+11(4bits for 15 no) = 14+x => x= 11 */ + /* energy_impz_fx is Q11 */ + + Ltmp_32 = DTFS_getEngy_fx(CURRP_Q_E_FX); /*Q = 2*(CURRP_Q_E_FX->Q) */ + Qadj = sub(st_fx->Q_prev_cw_en_fx, shl(CURRP_Q_E_FX->Q, 1)); + Ltmp_32 = L_shl(Ltmp_32,Qadj); /* shift left required to adjust Q of CURRP_Q_E_FX = Q_prev_cw_en_fx */ + + /* if ((DTFS_getEngy(*CURRP_Q_E) > st->prev_cw_en)&&(max(pos_q,neg_q)>3.5) && energy_impz>15.0 && tmpres>0.7) */ + test(); + test(); + test(); + IF ((GT_32(Ltmp_32, st_fx->prev_cw_en_fx ))&&(GT_32(L_max(pos_q_fx,neg_q_fx),939524096))&&(GT_32(energy_impz_fx,30720)) + && (GT_32(Mult_32_16(tmpres_fx,23265),shl(1,sub(Qtmpres,1)))) ) + { + /* if ((pos_q > neg_q) && ((pos_q>3.0*pos_nq0) || ((pos_q > 1.5*pos_nq0) && (neg_q < 1.5*neg_nq0)))) */ + test(); + test(); + test(); + IF ( (GT_32(pos_q_fx , neg_q_fx)) + && ((GT_32(Mult_32_16(pos_q_fx,10923), L_shr(pos_nq0_fx,sub(Qposnq,28)) )) + || ((GT_32( Mult_32_16(pos_q_fx,21845),L_shr(pos_nq0_fx,sub(Qposnq,28)) )) + && (LT_32(Mult_32_16(neg_q_fx,21846), L_shr(neg_nq0_fx,sub(Qnegnq,28)) )) )) + ) + /* 10923 = (1/3) oin Q15, pos_q_fx is Q28, so result of Mult_32_16(pos_q_fx,10923) = Q28 */ + /* L_shr(pos_nq0_fx,sub(Qposnq,28)) brings pos_nq0_fx with variable Q to fixed Q28 */ + { + PPP_MODE_E='B'; + move16(); + } + test(); + test(); + test(); + /* if ((pos_q <= neg_q) && ((neg_q>3.0*neg_nq0)|| ((neg_q > 1.5*neg_nq0) && (pos_q < 1.5*pos_nq0)))) */ + IF ( (LE_32(pos_q_fx ,neg_q_fx)) + && ((GT_32(Mult_32_16(neg_q_fx,10923), L_shr(neg_nq0_fx,sub(Qnegnq,28)))) + || ((GT_32(Mult_32_16(neg_q_fx,21846), L_shr(neg_nq0_fx,sub(Qnegnq,28)))) + && (LT_32( Mult_32_16( pos_q_fx,21846),L_shr(pos_nq0_fx,sub(Qposnq,28)))))) + ) + { + PPP_MODE_E='B'; + move16(); + } + } + } + } + + DTFS_copy_fx(TMPDTFS2_FX,*CURRP_Q_E_FX); + DTFS_poleFilter_fx_9(TMPDTFS_FX, pf_temp1, pf_temp2, pf_temp, pf_n2); + DTFS_poleFilter_fx_9(TMPDTFS2_FX, pf_temp1, pf_temp2, pf_temp, pf_n2); + + *TMPDTFS3_FX = DTFS_sub_fx(*TMPDTFS_FX,*TMPDTFS2_FX); + + + /* operate in ADR mode only the rate control is active. This adds some bumpups to improve the speech quality */ + /* if ((DTFS_getEngy_band(*TMPDTFS, 1500.0, upper_cut_off_freq_of_interest)/DTFS_getEngy(*TMPDTFS) > 0.05)&&(!st->rate_control)) */ + Ltemp1 = DTFS_getEngy_band_fx(*TMPDTFS_FX, 1500, upper_cut_off_freq_of_interest_fx); /* Q = 2*TMPDTFS_FX->Q*/ + Ltemp2 = DTFS_getEngy_fx(TMPDTFS_FX); /* Q = 2*TMPDTFS_FX->Q */ + + IF (Ltemp2==0) + { + Ltemp_fx=0; + } + ELSE + { + expb = norm_l(Ltemp1); + fracb = extract_h(L_shl(Ltemp1,expb)); + expb = sub(30, add(expb,shl(TMPDTFS_FX->Q, 1))); + expa = norm_l(Ltemp2); + fraca = extract_h(L_shl(Ltemp2,expa)); + expa = sub(30, add(expa,shl(TMPDTFS_FX->Q, 1))); + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); /* tmp in Q15 */ + exp = sub(expb,expa); /* ans = tmp*2^(exp) */ + Ltemp_fx = L_shl(tmp, add(exp,12)); /* make tmp Q27 */ + + } + test(); + IF (GT_32(Ltemp_fx , 6710886)&&(!st_fx->rate_control_fx)) /* 0.05 in Q27 = 6710886 */ + { + /*if (10.0*log10(DTFS_getEngy_band(*TMPDTFS,1500.0,upper_cut_off_freq_of_interest)/ */ + /*DTFS_getEngy_band(*TMPDTFS3,1500.0,upper_cut_off_freq_of_interest)) < 0.1) */ + + Ltemp1 = DTFS_getEngy_band_fx(*TMPDTFS_FX,1500,upper_cut_off_freq_of_interest_fx); + Ltemp2 = DTFS_getEngy_band_fx(*TMPDTFS3_FX,1500,upper_cut_off_freq_of_interest_fx); + + /*--------------------------------------------------------------*/ + /* Ltemp_fx = (Word32)divide_dp(Ltemp1, Ltemp2, Qadj,1);//Q29+1 */ + /*--------------------------------------------------------------*/ + IF (Ltemp2==0) + { + Ltemp_fx=0; + } + ELSE + { + expa = norm_l(Ltemp2); + fraca = extract_h(L_shl(Ltemp2,expa)); + expa = sub(30, expa); + + expb = norm_l(Ltemp1); + fracb = round_fx(L_shl(Ltemp1,expb)); + expb = sub(30,expb); + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); + exp = sub(expb,expa); + Ltemp_fx = L_shl(tmp,add(exp,14)); /* answer in Q29 */ + + } + /*-------------------------------------------*/ + + /* 10.0*log10(Ltemp_fx) */ + exp_ee = norm_l(Ltemp_fx); + frac_ee = Log2_norm_lc(L_shl(Ltemp_fx, exp_ee)); + exp_ee = sub(30,add(exp_ee,29)); /* 30 fixed here, 29 is the Q of Ltemp_fx */ + Ltmp = Mpy_32_16(exp_ee, frac_ee, LG10); /* LG10 in Q13, so answer Ltmp in Q14 */ + + IF(LT_32(Ltmp,1638)) /* 1638 = 0.1 in Q14 */ + { + /* if (res_enratio > 0.8) */ + if (GT_32(res_enratio_fx , 1638)) /* 1638 = 0.8 in Q11, res_enratio_fx in Q11 */ + { + PPP_MODE_E = 'B'; + move16(); + } + } + } + + /* To increase bump up, raise first threshold, lower second */ + /*tmp = (float)(10.0*log10(DTFS_getEngy(*TMPDTFS)/DTFS_getEngy(*TMPDTFS3)));*/ + Lacc = DTFS_getEngy_P2A_fx(TMPDTFS_FX); /* Q = 2*(TMPDTFS_FX->Q) */ + Lacc1= DTFS_getEngy_P2A_fx(TMPDTFS3_FX); /* Q = 2*(TMPDTFS3_FX->Q) */ + + + sft=shl(sub(TMPDTFS_FX->Q,TMPDTFS3_FX->Q),1);/* to check if Lacc<=2*Lacc1 */ + flag1=0; + move16(); + IF (sft>0) + { + /*if (L_sub40_40(L_shr40(Lacc,sft),Lacc1)<=0) */ + Lacc = L_shr(Lacc,sft); + flag1=1; + move16(); /* do the divide */ + } + ELSE + { + /*if (L_sub40_40(Lacc,L_shr40(Lacc1,negate(sft)))<=0) */ + Lacc1 = L_shr(Lacc1,negate(sft)); + flag1=1; + move16();/* do the divide */ + } + IF (EQ_16(flag1,1)) + { + expb = norm_l(Lacc); + fracb = extract_h(L_shl(Lacc,expb)); + expb = sub(30,add(expb,shl(TMPDTFS_FX->Q, 1))); + + expa = norm_l(Lacc1); + fraca = extract_h(L_shl(Lacc1,expa)); + expa = sub(30,add(expa,shl(TMPDTFS3_FX->Q, 1))); + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); /* tmp is always Q15 */ + exp = sub(expb,expa); /* Answer after division Lacc/Lacc1 = (2^exp)*(tmp/2^15) */ + + L_tmp = L_deposit_h(tmp); /* tmp is always Q15, L_tmp is always Q31 */ + expa = norm_l(L_tmp); + L_tmp = L_shl(L_tmp,expa); + exp = sub(30,add(expa,sub(31,exp))); + frac = Log2_norm_lc(L_tmp); + L_tmp = Mpy_32_16(exp,frac,12330); /* L_tmp is always Q13 */ + Ltemp = L_shl(L_tmp,10); /* Ltemp is always Q23 */ + } + ELSE + { + Ltemp = L_add(MAX_32, 0); + } + + test(); + if ((Ltemp <= 0)&&(!st_fx->rate_control_fx)) + { + PPP_MODE_E = 'B'; + move16(); + } + + IF ( LT_16(shl(vadsnr_fx,1) ,st_fx->SNR_THLD_fx)) /* Q8 */ + { + /* if ((( tmp < 3.05 && max(res_enratio,sp_enratio) > 0.8 ) && (st->rate_control))|| + (( tmp < 2.8 && max(res_enratio,sp_enratio) > 0.65 ) && (!st->rate_control))) */ + /* First comparison in Q23, Second comparison in Q15 */ + test(); + test(); + test(); + test(); + test(); + if ((( LT_32(Ltemp, 25585254 )&>_32(L_max(L_shl(res_enratio_fx,4),sp_enratio_fx),6554))&&(st_fx->rate_control_fx))|| + (( LT_32(Ltemp, 23488102 ) && GT_32(L_max(L_shl(res_enratio_fx,4),sp_enratio_fx) , 5325) )&&(!st_fx->rate_control_fx))) + { + PPP_MODE_E = 'B'; + move16(); + } + } + ELSE + { + /* if ((( tmp < 2.4 && max(res_enratio,sp_enratio) > 0.94) && (st->rate_control))|| + (( tmp < 4.5 && max(res_enratio,sp_enratio) > 0.5 ) && (!st->rate_control))) */ + test(); + test(); + test(); + test(); + test(); + if ((( LT_32(Ltemp ,20132659 )&>_32(L_max(L_shl(res_enratio_fx,4),sp_enratio_fx),7700))&&(st_fx->rate_control_fx))|| + (( LT_32(Ltemp, 37748736 ) && GT_32(L_max(L_shl(res_enratio_fx,4),sp_enratio_fx) , 4096) )&&(!st_fx->rate_control_fx))) + { + PPP_MODE_E = 'B'; + move16(); + } + } + + /* -----End closed-loop Bump-Up */ + } + ELSE + { + PPP_MODE_E = 'B' ; + move16();/*Amplitude quantization is failing*/ + } + } + ELSE + { + } + if (PPP_MODE_E == 'B') + { + st_fx->bump_up_fx = 1; + move16(); + free(CURRP_NQ_FX); + free(TMPDTFS_FX); + free(TMPDTFS2_FX); + free(TMPDTFS3_FX); + free(CURRP_Q_E_FX); + free(dtfs_temp_fx); + return; + } + + IF ( st_fx->Q_to_F_fx ) + { + st_fx->patterncount_fx = add(st_fx->patterncount_fx ,st_fx->pattern_m_fx); + + IF (GE_16(st_fx->patterncount_fx , 1000)) + { + st_fx->patterncount_fx = sub (st_fx->patterncount_fx , 1000); + PPP_MODE_E = 'B'; + move16(); + st_fx->bump_up_fx = 1; + move16(); + free(CURRP_NQ_FX); + free(TMPDTFS_FX); + free(TMPDTFS2_FX); + free(TMPDTFS3_FX); + free(CURRP_Q_E_FX); + free(dtfs_temp_fx); + return; + } + + } + + /* packetization of the delta lag in_fx PPP */ + IF (EQ_16(PPP_MODE_E,'Q')) + { + Q_delta_lag = add(delta_lag_E,11); /* to make it positive always */ + + push_indice_fx( st_fx, IND_DELTALAG, Q_delta_lag, 5 ); + } + + WIsyn_fx(*dtfs_temp_fx, CURRP_Q_E_FX, lpc2_fx, &(st_fx->ph_offset_E_fx), out_fx, L_FRAME,0,S_fx,C_fx, + pf_temp1,pf_temp2,pf_temp,pf_n2); + /* i/o ph_offset_fx in Q15, out_fx in Q0 */ + + DTFS_copy_fx(dtfs_temp_fx, *CURRP_Q_E_FX); + Lacc = DTFS_getEngy_P2A_fx(CURRP_NQ_FX); + st_fx->Q_prev_cw_en_fx=norm_l(Lacc); + + /* st_fx->Q_prev_cw_en_fx = (Lacc==0)?31: st_fx->Q_prev_cw_en_fx;move16(); */ + if (Lacc==0) + { + st_fx->Q_prev_cw_en_fx = 31; + move16(); + } + + st_fx->prev_cw_en_fx=(Word32) L_shl(Lacc,st_fx->Q_prev_cw_en_fx); /*2Q+Q_prev_cw_en_fx */ + st_fx->Q_prev_cw_en_fx=add(st_fx->Q_prev_cw_en_fx,shl(CURRP_NQ_FX->Q,1)); + /* Copy DTFS related parameters from 'dtfs_temp' to 'st_fx' structure */ + st_fx->dtfs_enc_lag_fx = dtfs_temp_fx->lag_fx; + move16(); + st_fx->dtfs_enc_nH_fx = dtfs_temp_fx->nH_fx; + move16(); + st_fx->dtfs_enc_nH_4kHz_fx = dtfs_temp_fx->nH_4kHz_fx; + move16(); + st_fx->dtfs_enc_upper_cut_off_freq_of_interest_fx = dtfs_temp_fx->upper_cut_off_freq_of_interest_fx; + move16(); + st_fx->dtfs_enc_upper_cut_off_freq_fx = dtfs_temp_fx->upper_cut_off_freq_fx; + move16(); + Copy(dtfs_temp_fx->a_fx, st_fx->dtfs_enc_a_fx, MAXLAG_WI); + Copy(dtfs_temp_fx->b_fx, st_fx->dtfs_enc_b_fx, MAXLAG_WI); + + st_fx->dtfs_enc_Q = dtfs_temp_fx->Q; + move16(); + + free(CURRP_NQ_FX); + free(TMPDTFS_FX); + free(TMPDTFS2_FX); + free(TMPDTFS3_FX); + free(CURRP_Q_E_FX); + free(dtfs_temp_fx); + + return; +} + + +/*===================================================================*/ +/* FUNCTION : synthesis_filter_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : IIR-filter residual by the LPC sysnthesis filter */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) b : filter coefficients (Qc). */ +/* _ (Word16 []) x : residual input (Qn). */ +/* _ (Word16) P : filter order. */ +/* _ (Word16) N : number of input samples. */ +/* _ (Word16) Qa : Q factor compensation (Qa=15-Qc) */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) y : output speech (Qn) */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* */ +/* _ (Word32 []) buf : filter memory (Q16+Qn) */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*===================================================================*/ +/* y(n)=sum(i=1 to 10){ */ +/* rxLpcCoeff(i)*rxFormSynthMem(n-i) */ +/* } */ +/* +fres(n) */ +/*===================================================================*/ +void synthesis_filter_fx (Word16 b[], Word16 x[], Word16 y[], Word16 buf[], + Word16 P, Word16 N ) +{ + Word32 acc; + Word16 i, j; + + FOR (i = 0; i < N; i++) + { + acc = L_deposit_h(*x++);/*Q16 */ + acc = L_shr(acc, 3);/*Q13 */ + + FOR (j = P - 1; j > 0; j--) + { + /* acc = L_sub(acc, L_mult(memory[j], coef[j])); */ + acc = L_msu(acc, buf[j], b[j]);/*Q13 */ + buf[j] = buf[j - 1]; + move16(); + } + /* acc = L_sub(acc, L_mult(memory[0], coef[0])); */ + acc = L_msu(acc, buf[0], b[0]); + acc = L_shl(acc, 3); + + *y++ = round_fx(acc); + buf[0] = round_fx(acc); + } +} + + + + + diff --git a/lib_enc/waveadjust_fec_cod.c b/lib_enc/waveadjust_fec_cod.c new file mode 100644 index 0000000..d8868e0 --- /dev/null +++ b/lib_enc/waveadjust_fec_cod.c @@ -0,0 +1,76 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "prot_fx.h" +#include "stat_com.h" +#include "stl.h" /* for wmc_tool */ + + +Word32 SFM_Cal(Word32 magn[], Word16 n) +{ + /* Counted Dymamic RAM: 16 words */ + Word32 logCurFlatness; + Word32 magn_abs, frac, logMagn, sumLogMagn, sumMagn; + Word16 i, norm_value, logSumMagn, logn; + sumLogMagn = L_deposit_l(0); + sumMagn = L_deposit_l(0); + FOR(i = 0; i < n; i++) + { + /* log2(magn(i)) */ + magn_abs = L_abs(magn[i]); + norm_value = norm_l(L_max(magn_abs, 1)); + /* next two codes lost precision. */ + frac = L_and(L_shr(L_shl(magn_abs, norm_value), 22), 0xFF); + logMagn = L_deposit_l(add(shl(sub(30, norm_value), 8), kLog2TableFrac_x[frac]));; /* Q8 */ + /* sum(log2(magn(i))) */ + sumLogMagn =L_add(sumLogMagn, logMagn); /* Q8 */ + + sumMagn =L_add(sumMagn, magn_abs); + } + + IF(EQ_32(sumMagn,MAX_32)) + { + sumMagn = L_deposit_l(0); + FOR(i = 0; i < n; i++) + { + magn_abs = L_shr(L_abs(magn[i]), 8); + sumMagn = L_add(sumMagn, magn_abs); + } + /* log2(sumMagn) */ + norm_value = norm_l(sumMagn); + frac = L_and(L_shr(L_shl(sumMagn, norm_value), 22), 0xFF); + logSumMagn = add(shl(sub(38,norm_value), 8), kLog2TableFrac_x[frac]); /* Q8 */ + } + ELSE + { + /* log2(sumMagn) */ + norm_value = norm_l(sumMagn); + frac = L_and(L_shr(L_shl(sumMagn, norm_value), 22), 0xFF); + logSumMagn = add(shl(sub(30, norm_value), 8), kLog2TableFrac_x[frac]); /* Q8 */ + } + + /* log2(n) */ + norm_value = norm_l(n); + frac = L_and(L_shr(L_shl(n, norm_value), 22), 0xFF); + logn = add(shl(sub(30, norm_value), 8), kLog2TableFrac_x[frac]); /* Q8 */ + + + logMagn=L_sub(L_mult0(n, sub(logSumMagn, logn)), sumLogMagn); + logMagn = (Word32)L_max(0, logMagn); + + logCurFlatness = L_deposit_l(div_l(L_shl(logMagn, 1), n)); + frac = L_and(logCurFlatness, 0xFF); + norm_value = (Word16)L_shr(logCurFlatness, 8); + move16(); + + logCurFlatness = L_sub(kExp2TableFrac_x[frac], 33); + logCurFlatness = L_shl(logCurFlatness, sub(16, norm_value)); /* Q31 */ + + + return logCurFlatness; +} + diff --git a/scripts/switchPaths/sw_13k2_512k.bin b/scripts/switchPaths/sw_13k2_512k.bin new file mode 100644 index 0000000..6a3bf8d --- /dev/null +++ b/scripts/switchPaths/sw_13k2_512k.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c4f1de1f88faaf5eccdceed7afa71dadb9e6d87d61d8a5929e683528aeb129e +size 60000 diff --git a/scripts/switchPaths/sw_13k2_to_128k_10fr.bin b/scripts/switchPaths/sw_13k2_to_128k_10fr.bin new file mode 100644 index 0000000..2727200 --- /dev/null +++ b/scripts/switchPaths/sw_13k2_to_128k_10fr.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b14c666d436f8a004ea055b28eb8f0866c436f32a0b44af56579fc333ce58050 +size 4000 diff --git a/scripts/switchPaths/sw_amrwb.bin b/scripts/switchPaths/sw_amrwb.bin new file mode 100644 index 0000000..984fb33 --- /dev/null +++ b/scripts/switchPaths/sw_amrwb.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c496eaaa8a8aec1fc28c8eaf48f08d895de2c6570dcace363d3fcc47c16e63e +size 12240 diff --git a/scripts/switchPaths/sw_amrwb_evs.bin b/scripts/switchPaths/sw_amrwb_evs.bin new file mode 100644 index 0000000..7933830 --- /dev/null +++ b/scripts/switchPaths/sw_amrwb_evs.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c5e256951f05f6f65880128a9b9a251c29ea65e971a6b2ea07387a5220ee8169 +size 20000 diff --git a/scripts/switchPaths/sw_amrwb_evs2.bin b/scripts/switchPaths/sw_amrwb_evs2.bin new file mode 100644 index 0000000..cf85d98 --- /dev/null +++ b/scripts/switchPaths/sw_amrwb_evs2.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f15558c58ed1ee433d60952c37b4593a3429a46616cd33fb5fa88966e3f5077 +size 60000 diff --git a/scripts/switchPaths/sw_highest.bin b/scripts/switchPaths/sw_highest.bin new file mode 100644 index 0000000..e9957a0 --- /dev/null +++ b/scripts/switchPaths/sw_highest.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:938932630efca29c853e70d097afa74260167a5562a19b01cf8bb984f65a3c21 +size 16000 diff --git a/scripts/switchPaths/sw_nb1.bin b/scripts/switchPaths/sw_nb1.bin new file mode 100644 index 0000000..dafbbf0 --- /dev/null +++ b/scripts/switchPaths/sw_nb1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8cfb313b3c1108c902eea7135572a03d46624ac23bc713533f84b8922814728a +size 800 diff --git a/scripts/switchPaths/sw_nb5.bin b/scripts/switchPaths/sw_nb5.bin new file mode 100644 index 0000000..fce9caf --- /dev/null +++ b/scripts/switchPaths/sw_nb5.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1f5daa955bbba9c7d2751a4af537dc167946700edb9b69dffc62d557a39fad3 +size 1600 diff --git a/scripts/switchPaths/sw_swb1.bin b/scripts/switchPaths/sw_swb1.bin new file mode 100644 index 0000000..1a8027f --- /dev/null +++ b/scripts/switchPaths/sw_swb1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e5b1c8aef8057c25b594513b46b3ba9853a8c9556fda2f4c5dc84a10241c51fe +size 1600 diff --git a/scripts/switchPaths/sw_wb1.bin b/scripts/switchPaths/sw_wb1.bin new file mode 100644 index 0000000..bad1459 --- /dev/null +++ b/scripts/switchPaths/sw_wb1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6793118e380d768c39aaa3eb6505fc54efbf2215032845ce79f0d131e3ef9b3f +size 1800 diff --git a/scripts/switchPaths/sw_wb5.bin b/scripts/switchPaths/sw_wb5.bin new file mode 100644 index 0000000..36e5ce4 --- /dev/null +++ b/scripts/switchPaths/sw_wb5.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:adbea95dc5ddd35a616fc8c27cd8d5310a31f511671b80caac4879a0ec87de00 +size 3600 diff --git a/scripts/switchPaths/swb_high1.bin b/scripts/switchPaths/swb_high1.bin new file mode 100644 index 0000000..fe074e5 --- /dev/null +++ b/scripts/switchPaths/swb_high1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa29cf9e0b348dc3fa330848c4d974f96cda605129e867f522228d14c15c5f18 +size 16000 diff --git a/scripts/switchPaths/swb_low1.bin b/scripts/switchPaths/swb_low1.bin new file mode 100644 index 0000000..aa6c137 --- /dev/null +++ b/scripts/switchPaths/swb_low1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5861a8ad4bd66eab0014d84b1a4073a0e355d930b7a786da7577154c6f0f3da5 +size 16000 diff --git a/scripts/switchPaths/wb_high1.bin b/scripts/switchPaths/wb_high1.bin new file mode 100644 index 0000000..db65048 --- /dev/null +++ b/scripts/switchPaths/wb_high1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:025d6d2d84935f40a21452ec14dfc3b954401447f50843285522c1e484896087 +size 14400 diff --git a/scripts/switchPaths/wb_low1.bin b/scripts/switchPaths/wb_low1.bin new file mode 100644 index 0000000..15f2e0f --- /dev/null +++ b/scripts/switchPaths/wb_low1.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:887eec052b27812b950d7ed0e3a934b4a15d481de07b9ddac97ed6cdecceb47e +size 12000 -- GitLab